forked from len0rd/rockbox
Sansa Connect: Properly setup internal speaker
Switch to internal speaker when headphones are disconnected. Change-Id: I7c04ac139ad540d85f960e9dadc2faaf4f856055
This commit is contained in:
parent
756c0d2ac8
commit
02c4ec294c
2 changed files with 60 additions and 56 deletions
|
|
@ -305,8 +305,8 @@ void aic3x_switch_output(bool stereo)
|
||||||
{
|
{
|
||||||
if (stereo)
|
if (stereo)
|
||||||
{
|
{
|
||||||
/* mute MONO_LOP/M */
|
/* MONO_LOP/M not fully powered up */
|
||||||
aic3x_change_reg(AIC3X_MONO_LOP_M_LVL, 0x00, 0xF6);
|
aic3x_change_reg(AIC3X_MONO_LOP_M_LVL, 0x00, 0xFE);
|
||||||
/* HPLOUT fully powered up */
|
/* HPLOUT fully powered up */
|
||||||
aic3x_change_reg(AIC3X_HPLOUT_LVL, 0x01, 0xFF);
|
aic3x_change_reg(AIC3X_HPLOUT_LVL, 0x01, 0xFF);
|
||||||
/* HPROUT fully powered up */
|
/* HPROUT fully powered up */
|
||||||
|
|
@ -316,8 +316,8 @@ void aic3x_switch_output(bool stereo)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* MONO_LOP/M not muted */
|
/* MONO_LOP/M fully powered up */
|
||||||
aic3x_change_reg(AIC3X_MONO_LOP_M_LVL, 0x09, 0xFF);
|
aic3x_change_reg(AIC3X_MONO_LOP_M_LVL, 0x01, 0xFF);
|
||||||
/* HPLOUT not fully powered up */
|
/* HPLOUT not fully powered up */
|
||||||
aic3x_change_reg(AIC3X_HPLOUT_LVL, 0x00, 0xFE);
|
aic3x_change_reg(AIC3X_HPLOUT_LVL, 0x00, 0xFE);
|
||||||
/* HPROUT not fully powered up */
|
/* HPROUT not fully powered up */
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@
|
||||||
* \/ \/ \/ \/ \/
|
* \/ \/ \/ \/ \/
|
||||||
* $Id: $
|
* $Id: $
|
||||||
*
|
*
|
||||||
* Copyright (C) 2011 by Tomasz Moń
|
* Copyright (C) 2011-2021 by Tomasz Moń
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or
|
* This program is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU General Public License
|
* modify it under the terms of the GNU General Public License
|
||||||
|
|
@ -61,6 +61,7 @@
|
||||||
#define CMD_WHEEL_EN 0xD0
|
#define CMD_WHEEL_EN 0xD0
|
||||||
#define CMD_SET_INTCHRG 0xD1
|
#define CMD_SET_INTCHRG 0xD1
|
||||||
#define CMD_CODEC_RESET 0xD7
|
#define CMD_CODEC_RESET 0xD7
|
||||||
|
#define CMD_AMP_ENABLE 0xCA
|
||||||
#define CMD_FILL 0xFF
|
#define CMD_FILL 0xFF
|
||||||
|
|
||||||
#define CMD_SYS_CTRL 0xDA
|
#define CMD_SYS_CTRL 0xDA
|
||||||
|
|
@ -74,9 +75,9 @@ static struct mutex avr_mtx;
|
||||||
static int btn = 0;
|
static int btn = 0;
|
||||||
static bool hold_switch;
|
static bool hold_switch;
|
||||||
#ifndef BOOTLOADER
|
#ifndef BOOTLOADER
|
||||||
static long btn_stack[DEFAULT_STACK_SIZE/sizeof(long)];
|
static long avr_stack[DEFAULT_STACK_SIZE/sizeof(long)];
|
||||||
static const char btn_thread_name[] = "buttons";
|
static const char avr_thread_name[] = "avr";
|
||||||
static struct event_queue btn_queue;
|
static struct semaphore avr_thread_trigger;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static int current_battery_level = 100;
|
static int current_battery_level = 100;
|
||||||
|
|
@ -365,6 +366,13 @@ void avr_hid_reset_codec(void)
|
||||||
spi_txrx(codec_reset, NULL, sizeof(codec_reset));
|
spi_txrx(codec_reset, NULL, sizeof(codec_reset));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void avr_hid_set_amp_enable(unsigned char enable)
|
||||||
|
{
|
||||||
|
unsigned char amp_enable[4] = {CMD_SYNC, CMD_AMP_ENABLE, enable, CMD_CLOSE};
|
||||||
|
|
||||||
|
spi_txrx(amp_enable, NULL, sizeof(amp_enable));
|
||||||
|
}
|
||||||
|
|
||||||
void avr_hid_power_off(void)
|
void avr_hid_power_off(void)
|
||||||
{
|
{
|
||||||
unsigned char prg[4] = {CMD_SYNC, CMD_SYS_CTRL, SYS_CTRL_POWEROFF, CMD_CLOSE};
|
unsigned char prg[4] = {CMD_SYNC, CMD_SYS_CTRL, SYS_CTRL_POWEROFF, CMD_CLOSE};
|
||||||
|
|
@ -373,36 +381,54 @@ void avr_hid_power_off(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef BOOTLOADER
|
#ifndef BOOTLOADER
|
||||||
void btn_thread(void)
|
static bool avr_state_changed(void)
|
||||||
{
|
{
|
||||||
struct queue_event ev;
|
return (IO_GIO_BITSET0 & 0x1) ? false : true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool headphones_inserted(void)
|
||||||
|
{
|
||||||
|
return (IO_GIO_BITSET0 & 0x04) ? false : true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void set_audio_output(bool headphones)
|
||||||
|
{
|
||||||
|
if (headphones)
|
||||||
|
{
|
||||||
|
/* Stereo output on headphones */
|
||||||
|
avr_hid_set_amp_enable(0);
|
||||||
|
aic3x_switch_output(true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Mono output on built-in speaker */
|
||||||
|
aic3x_switch_output(false);
|
||||||
|
avr_hid_set_amp_enable(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void avr_thread(void)
|
||||||
|
{
|
||||||
|
bool headphones_active_state = headphones_inserted();
|
||||||
|
bool headphones_state;
|
||||||
|
|
||||||
|
set_audio_output(headphones_active_state);
|
||||||
|
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
queue_wait(&btn_queue, &ev);
|
semaphore_wait(&avr_thread_trigger, TIMEOUT_BLOCK);
|
||||||
|
|
||||||
if (ev.id == SYS_USB_CONNECTED)
|
if (avr_state_changed())
|
||||||
{
|
{
|
||||||
/* Allow USB to gain exclusive storage access */
|
|
||||||
usb_acknowledge(SYS_USB_CONNECTED_ACK);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Ignore all messages except BTN_INTERRUPT */
|
|
||||||
if (ev.id != BTN_INTERRUPT)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
/* Enable back button interrupt */
|
|
||||||
IO_INTC_EINT1 |= INTR_EINT1_EXT0;
|
|
||||||
|
|
||||||
/* Read buttons state */
|
/* Read buttons state */
|
||||||
avr_hid_get_state();
|
avr_hid_get_state();
|
||||||
|
}
|
||||||
|
|
||||||
yield();
|
headphones_state = headphones_inserted();
|
||||||
|
if (headphones_state != headphones_active_state)
|
||||||
if (queue_empty(&btn_queue) && ((IO_GIO_BITSET0 & 0x1) == 0))
|
|
||||||
{
|
{
|
||||||
/* for some reason we have lost next interrupt */
|
set_audio_output(headphones_state);
|
||||||
queue_post(&btn_queue, BTN_INTERRUPT, 0);
|
headphones_active_state = headphones_state;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -412,39 +438,17 @@ void GIO0(void)
|
||||||
{
|
{
|
||||||
/* Clear interrupt */
|
/* Clear interrupt */
|
||||||
IO_INTC_IRQ1 = (1 << 5);
|
IO_INTC_IRQ1 = (1 << 5);
|
||||||
/* Disable interrupt */
|
|
||||||
IO_INTC_EINT1 &= ~INTR_EINT1_EXT0;
|
|
||||||
|
|
||||||
/* interrupt will be enabled back after button read */
|
semaphore_release(&avr_thread_trigger);
|
||||||
queue_post(&btn_queue, BTN_INTERRUPT, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int headphones_inserted_callback(struct timeout *tmo)
|
|
||||||
{
|
|
||||||
(void)tmo;
|
|
||||||
|
|
||||||
if (IO_GIO_BITSET0 & 0x04)
|
|
||||||
{
|
|
||||||
aic3x_switch_output(false);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
aic3x_switch_output(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GIO2(void) __attribute__ ((section(".icode")));
|
void GIO2(void) __attribute__ ((section(".icode")));
|
||||||
void GIO2(void)
|
void GIO2(void)
|
||||||
{
|
{
|
||||||
static struct timeout headphones_oneshot;
|
|
||||||
|
|
||||||
/* Clear interrupt */
|
/* Clear interrupt */
|
||||||
IO_INTC_IRQ1 = (1 << 7);
|
IO_INTC_IRQ1 = (1 << 7);
|
||||||
|
|
||||||
timeout_register(&headphones_oneshot, headphones_inserted_callback,
|
semaphore_release(&avr_thread_trigger);
|
||||||
HZ/2, 0);
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
@ -453,9 +457,9 @@ void button_init_device(void)
|
||||||
btn = 0;
|
btn = 0;
|
||||||
hold_switch = false;
|
hold_switch = false;
|
||||||
#ifndef BOOTLOADER
|
#ifndef BOOTLOADER
|
||||||
queue_init(&btn_queue, true);
|
semaphore_init(&avr_thread_trigger, 1, 1);
|
||||||
create_thread(btn_thread, btn_stack, sizeof(btn_stack), 0,
|
create_thread(avr_thread, avr_stack, sizeof(avr_stack), 0,
|
||||||
btn_thread_name IF_PRIO(, PRIORITY_USER_INTERFACE)
|
avr_thread_name IF_PRIO(, PRIORITY_USER_INTERFACE)
|
||||||
IF_COP(, CPU));
|
IF_COP(, CPU));
|
||||||
#endif
|
#endif
|
||||||
IO_GIO_DIR0 |= 0x01; /* Set GIO0 as input */
|
IO_GIO_DIR0 |= 0x01; /* Set GIO0 as input */
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue