diff options
-rw-r--r-- | firmware/drivers/audio/aic3x.c | 8 | ||||
-rw-r--r-- | firmware/target/arm/tms320dm320/sansa-connect/avr-sansaconnect.c | 108 |
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; | |||
74 | static int btn = 0; | 75 | static int btn = 0; |
75 | static bool hold_switch; | 76 | static bool hold_switch; |
76 | #ifndef BOOTLOADER | 77 | #ifndef BOOTLOADER |
77 | static long btn_stack[DEFAULT_STACK_SIZE/sizeof(long)]; | 78 | static long avr_stack[DEFAULT_STACK_SIZE/sizeof(long)]; |
78 | static const char btn_thread_name[] = "buttons"; | 79 | static const char avr_thread_name[] = "avr"; |
79 | static struct event_queue btn_queue; | 80 | static struct semaphore avr_thread_trigger; |
80 | #endif | 81 | #endif |
81 | 82 | ||
82 | static int current_battery_level = 100; | 83 | static 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 | ||
369 | void 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 | |||
368 | void avr_hid_power_off(void) | 376 | void 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 |
376 | void btn_thread(void) | 384 | static 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) | 389 | static 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) | 394 | static 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 */ | 410 | void 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 | |||
422 | static 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 | ||
438 | void GIO2(void) __attribute__ ((section(".icode"))); | 445 | void GIO2(void) __attribute__ ((section(".icode"))); |
439 | void GIO2(void) | 446 | void 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 */ |