summaryrefslogtreecommitdiff
path: root/firmware
diff options
context:
space:
mode:
Diffstat (limited to 'firmware')
-rw-r--r--firmware/drivers/audio/aic3x.c8
-rw-r--r--firmware/target/arm/tms320dm320/sansa-connect/avr-sansaconnect.c108
2 files changed, 60 insertions, 56 deletions
diff --git a/firmware/drivers/audio/aic3x.c b/firmware/drivers/audio/aic3x.c
index 9b705db7f5..39576e9f47 100644
--- a/firmware/drivers/audio/aic3x.c
+++ b/firmware/drivers/audio/aic3x.c
@@ -305,8 +305,8 @@ void aic3x_switch_output(bool stereo)
305{ 305{
306 if (stereo) 306 if (stereo)
307 { 307 {
308 /* mute MONO_LOP/M */ 308 /* MONO_LOP/M not fully powered up */
309 aic3x_change_reg(AIC3X_MONO_LOP_M_LVL, 0x00, 0xF6); 309 aic3x_change_reg(AIC3X_MONO_LOP_M_LVL, 0x00, 0xFE);
310 /* HPLOUT fully powered up */ 310 /* HPLOUT fully powered up */
311 aic3x_change_reg(AIC3X_HPLOUT_LVL, 0x01, 0xFF); 311 aic3x_change_reg(AIC3X_HPLOUT_LVL, 0x01, 0xFF);
312 /* HPROUT fully powered up */ 312 /* HPROUT fully powered up */
@@ -316,8 +316,8 @@ void aic3x_switch_output(bool stereo)
316 } 316 }
317 else 317 else
318 { 318 {
319 /* MONO_LOP/M not muted */ 319 /* MONO_LOP/M fully powered up */
320 aic3x_change_reg(AIC3X_MONO_LOP_M_LVL, 0x09, 0xFF); 320 aic3x_change_reg(AIC3X_MONO_LOP_M_LVL, 0x01, 0xFF);
321 /* HPLOUT not fully powered up */ 321 /* HPLOUT not fully powered up */
322 aic3x_change_reg(AIC3X_HPLOUT_LVL, 0x00, 0xFE); 322 aic3x_change_reg(AIC3X_HPLOUT_LVL, 0x00, 0xFE);
323 /* HPROUT not fully powered up */ 323 /* HPROUT not fully powered up */
diff --git a/firmware/target/arm/tms320dm320/sansa-connect/avr-sansaconnect.c b/firmware/target/arm/tms320dm320/sansa-connect/avr-sansaconnect.c
index ec35af9f62..47c5489657 100644
--- a/firmware/target/arm/tms320dm320/sansa-connect/avr-sansaconnect.c
+++ b/firmware/target/arm/tms320dm320/sansa-connect/avr-sansaconnect.c
@@ -7,7 +7,7 @@
7* \/ \/ \/ \/ \/ 7* \/ \/ \/ \/ \/
8* $Id: $ 8* $Id: $
9* 9*
10* Copyright (C) 2011 by Tomasz Moń 10* Copyright (C) 2011-2021 by Tomasz Moń
11* 11*
12* This program is free software; you can redistribute it and/or 12* This program is free software; you can redistribute it and/or
13* modify it under the terms of the GNU General Public License 13* modify it under the terms of the GNU General Public License
@@ -61,6 +61,7 @@
61#define CMD_WHEEL_EN 0xD0 61#define CMD_WHEEL_EN 0xD0
62#define CMD_SET_INTCHRG 0xD1 62#define CMD_SET_INTCHRG 0xD1
63#define CMD_CODEC_RESET 0xD7 63#define CMD_CODEC_RESET 0xD7
64#define CMD_AMP_ENABLE 0xCA
64#define CMD_FILL 0xFF 65#define CMD_FILL 0xFF
65 66
66#define CMD_SYS_CTRL 0xDA 67#define CMD_SYS_CTRL 0xDA
@@ -74,9 +75,9 @@ static struct mutex avr_mtx;
74static int btn = 0; 75static int btn = 0;
75static bool hold_switch; 76static bool hold_switch;
76#ifndef BOOTLOADER 77#ifndef BOOTLOADER
77static long btn_stack[DEFAULT_STACK_SIZE/sizeof(long)]; 78static long avr_stack[DEFAULT_STACK_SIZE/sizeof(long)];
78static const char btn_thread_name[] = "buttons"; 79static const char avr_thread_name[] = "avr";
79static struct event_queue btn_queue; 80static struct semaphore avr_thread_trigger;
80#endif 81#endif
81 82
82static int current_battery_level = 100; 83static int current_battery_level = 100;
@@ -365,6 +366,13 @@ void avr_hid_reset_codec(void)
365 spi_txrx(codec_reset, NULL, sizeof(codec_reset)); 366 spi_txrx(codec_reset, NULL, sizeof(codec_reset));
366} 367}
367 368
369void avr_hid_set_amp_enable(unsigned char enable)
370{
371 unsigned char amp_enable[4] = {CMD_SYNC, CMD_AMP_ENABLE, enable, CMD_CLOSE};
372
373 spi_txrx(amp_enable, NULL, sizeof(amp_enable));
374}
375
368void avr_hid_power_off(void) 376void avr_hid_power_off(void)
369{ 377{
370 unsigned char prg[4] = {CMD_SYNC, CMD_SYS_CTRL, SYS_CTRL_POWEROFF, CMD_CLOSE}; 378 unsigned char prg[4] = {CMD_SYNC, CMD_SYS_CTRL, SYS_CTRL_POWEROFF, CMD_CLOSE};
@@ -373,36 +381,54 @@ void avr_hid_power_off(void)
373} 381}
374 382
375#ifndef BOOTLOADER 383#ifndef BOOTLOADER
376void btn_thread(void) 384static bool avr_state_changed(void)
377{ 385{
378 struct queue_event ev; 386 return (IO_GIO_BITSET0 & 0x1) ? false : true;
387}
379 388
380 while (1) 389static bool headphones_inserted(void)
381 { 390{
382 queue_wait(&btn_queue, &ev); 391 return (IO_GIO_BITSET0 & 0x04) ? false : true;
392}
383 393
384 if (ev.id == SYS_USB_CONNECTED) 394static void set_audio_output(bool headphones)
385 { 395{
386 /* Allow USB to gain exclusive storage access */ 396 if (headphones)
387 usb_acknowledge(SYS_USB_CONNECTED_ACK); 397 {
388 } 398 /* Stereo output on headphones */
399 avr_hid_set_amp_enable(0);
400 aic3x_switch_output(true);
401 }
402 else
403 {
404 /* Mono output on built-in speaker */
405 aic3x_switch_output(false);
406 avr_hid_set_amp_enable(1);
407 }
408}
389 409
390 /* Ignore all messages except BTN_INTERRUPT */ 410void avr_thread(void)
391 if (ev.id != BTN_INTERRUPT) 411{
392 continue; 412 bool headphones_active_state = headphones_inserted();
413 bool headphones_state;
393 414
394 /* Enable back button interrupt */ 415 set_audio_output(headphones_active_state);
395 IO_INTC_EINT1 |= INTR_EINT1_EXT0;
396 416
397 /* Read buttons state */ 417 while (1)
398 avr_hid_get_state(); 418 {
419 semaphore_wait(&avr_thread_trigger, TIMEOUT_BLOCK);
399 420
400 yield(); 421 if (avr_state_changed())
422 {
423 /* Read buttons state */
424 avr_hid_get_state();
425 }
401 426
402 if (queue_empty(&btn_queue) && ((IO_GIO_BITSET0 & 0x1) == 0)) 427 headphones_state = headphones_inserted();
428 if (headphones_state != headphones_active_state)
403 { 429 {
404 /* for some reason we have lost next interrupt */ 430 set_audio_output(headphones_state);
405 queue_post(&btn_queue, BTN_INTERRUPT, 0); 431 headphones_active_state = headphones_state;
406 } 432 }
407 } 433 }
408} 434}
@@ -412,39 +438,17 @@ void GIO0(void)
412{ 438{
413 /* Clear interrupt */ 439 /* Clear interrupt */
414 IO_INTC_IRQ1 = (1 << 5); 440 IO_INTC_IRQ1 = (1 << 5);
415 /* Disable interrupt */
416 IO_INTC_EINT1 &= ~INTR_EINT1_EXT0;
417 441
418 /* interrupt will be enabled back after button read */ 442 semaphore_release(&avr_thread_trigger);
419 queue_post(&btn_queue, BTN_INTERRUPT, 0);
420}
421
422static int headphones_inserted_callback(struct timeout *tmo)
423{
424 (void)tmo;
425
426 if (IO_GIO_BITSET0 & 0x04)
427 {
428 aic3x_switch_output(false);
429 }
430 else
431 {
432 aic3x_switch_output(true);
433 }
434
435 return 0;
436} 443}
437 444
438void GIO2(void) __attribute__ ((section(".icode"))); 445void GIO2(void) __attribute__ ((section(".icode")));
439void GIO2(void) 446void GIO2(void)
440{ 447{
441 static struct timeout headphones_oneshot;
442
443 /* Clear interrupt */ 448 /* Clear interrupt */
444 IO_INTC_IRQ1 = (1 << 7); 449 IO_INTC_IRQ1 = (1 << 7);
445 450
446 timeout_register(&headphones_oneshot, headphones_inserted_callback, 451 semaphore_release(&avr_thread_trigger);
447 HZ/2, 0);
448} 452}
449#endif 453#endif
450 454
@@ -453,9 +457,9 @@ void button_init_device(void)
453 btn = 0; 457 btn = 0;
454 hold_switch = false; 458 hold_switch = false;
455#ifndef BOOTLOADER 459#ifndef BOOTLOADER
456 queue_init(&btn_queue, true); 460 semaphore_init(&avr_thread_trigger, 1, 1);
457 create_thread(btn_thread, btn_stack, sizeof(btn_stack), 0, 461 create_thread(avr_thread, avr_stack, sizeof(avr_stack), 0,
458 btn_thread_name IF_PRIO(, PRIORITY_USER_INTERFACE) 462 avr_thread_name IF_PRIO(, PRIORITY_USER_INTERFACE)
459 IF_COP(, CPU)); 463 IF_COP(, CPU));
460#endif 464#endif
461 IO_GIO_DIR0 |= 0x01; /* Set GIO0 as input */ 465 IO_GIO_DIR0 |= 0x01; /* Set GIO0 as input */