diff --git a/firmware/drivers/audio/as3514.c b/firmware/drivers/audio/as3514.c index ac3350eb47..3b0a7cf087 100644 --- a/firmware/drivers/audio/as3514.c +++ b/firmware/drivers/audio/as3514.c @@ -88,19 +88,10 @@ static uint8_t as3514_regs[AS3514_NUM_AUDIO_REGS]; /* 8-bit registers */ */ static void as3514_write(unsigned int reg, unsigned int value) { - if (ascodec_write(reg, value) != 2) - { - DEBUGF("as3514 error reg=0x%02x", reg); - } + ascodec_write(reg, value); - if (reg < ARRAYLEN(as3514_regs)) - { + if (reg < AS3514_NUM_AUDIO_REGS) as3514_regs[reg] = value; - } - else - { - DEBUGF("as3514 error reg=0x%02x", reg); - } } /* Helpers to set/clear bits */ @@ -135,24 +126,18 @@ int tenthdb2master(int db) int sound_val2phys(int setting, int value) { - int result; - switch(setting) { #if defined(HAVE_RECORDING) case SOUND_LEFT_GAIN: case SOUND_RIGHT_GAIN: case SOUND_MIC_GAIN: - result = (value - 23) * 15; - break; + return (value - 23) * 15; #endif default: - result = value; - break; + return value; } - - return result; } /* @@ -160,28 +145,49 @@ int sound_val2phys(int setting, int value) */ void audiohw_preinit(void) { - unsigned int i; - /* read all reg values */ - for (i = 0; i < ARRAYLEN(as3514_regs); i++) - { - as3514_regs[i] = ascodec_read(i); - } + ascodec_readbytes(0x0, AS3514_NUM_AUDIO_REGS, as3514_regs); + +#ifdef HAVE_AS3543 + + as3514_write(AS3514_AUDIOSET1, AUDIOSET1_DAC_on | AUDIOSET1_DAC_GAIN_on); + as3514_write(AS3514_AUDIOSET2, AUDIOSET2_HPH_QUALITY_LOW_POWER); + /* common ground on, delay playback unmuting when inserting headphones */ + as3514_write(AS3514_AUDIOSET3, AUDIOSET3_HPCM_on | AUDIOSET3_HP_LONGSTART); + + as3514_write(AS3543_DAC_IF, AS3543_DAC_INT_PLL); + /* Select Line 2 for FM radio */ + as3514_set(AS3514_LINE_IN1_R, LINE_IN_R_LINE_SELECT); + /* Output SUM of microphone/line/DAC */ + as3514_write(AS3514_HPH_OUT_R, HPH_OUT_R_HEADPHONES | HPH_OUT_R_HP_OUT_SUM); + +#else + /* as3514/as3515 */ /* Set ADC off, mixer on, DAC on, line out off, line in off, mic off */ - /* Turn on SUM, DAC */ as3514_write(AS3514_AUDIOSET1, AUDIOSET1_DAC_on | AUDIOSET1_SUM_on); -#ifdef HAVE_AS3543 - as3514_write(AS3514_AUDIOSET2, AUDIOSET2_HPH_QUALITY_LOW_POWER); -#else /* Set BIAS on, DITH off, AGC off, IBR_DAC max reduction, LSP_LP on, IBR_LSP max reduction (50%), taken from c200v2 OF */ as3514_write(AS3514_AUDIOSET2, AUDIOSET2_IBR_LSP_50 | AUDIOSET2_LSP_LP | AUDIOSET2_IBR_DAC_50 | AUDIOSET2_AGC_off | AUDIOSET2_DITH_off ); -#endif + + /* Mute and disable speaker */ + as3514_write(AS3514_LSP_OUT_R, LSP_OUT_R_SP_OVC_TO_256MS | 0x00); + as3514_write(AS3514_LSP_OUT_L, LSP_OUT_L_SP_MUTE | 0x00); + +#ifdef PHILIPS_SA9200 + /* LRCK 8-23kHz (there are audible clicks while reading the ADC otherwise) */ + as3514_write(AS3514_PLLMODE, PLLMODE_LRCK_8_23); +#else + /* LRCK 24-48kHz */ + as3514_write(AS3514_PLLMODE, PLLMODE_LRCK_24_48); +#endif /* PHILIPS_SA9200 */ + + /* Set headphone over-current to 0, Min volume */ + as3514_write(AS3514_HPH_OUT_R, HPH_OUT_R_HP_OVC_TO_0MS | 0x00); /* AMS Sansas based on the AS3525 need HPCM enabled, otherwise they output the L-R signal on both L and R headphone outputs instead of normal stereo. @@ -194,46 +200,23 @@ void audiohw_preinit(void) /* TODO: check if AS3525 settings save power on e200v1 or as3525v2 */ /* Set HPCM off, ZCU on */ as3514_write(AS3514_AUDIOSET3, AUDIOSET3_HPCM_off); -#endif +#endif /* CONFIG_CPU == AS3525 */ -#ifdef HAVE_AS3543 - as3514_write(AS3543_DAC_IF, AS3543_DAC_INT_PLL); - as3514_set(AS3514_LINE_IN1_R, LINE_IN_R_LINE_SELECT); /* Line 2 */ -#else - /* Mute and disable speaker */ - as3514_write(AS3514_LSP_OUT_R, LSP_OUT_R_SP_OVC_TO_256MS | 0x00); - as3514_write(AS3514_LSP_OUT_L, LSP_OUT_L_SP_MUTE | 0x00); -#endif + /* M2_Sup_off */ + as3514_set(AS3514_MIC2_L, MIC2_L_M2_SUP_off); -#ifdef HAVE_AS3543 - as3514_write(AS3514_HPH_OUT_R, (0<<7) /* out */ | HPH_OUT_R_HP_OUT_SUM | - 0x00); -#else - /* Set headphone over-current to 0, Min volume */ - as3514_write(AS3514_HPH_OUT_R, - HPH_OUT_R_HP_OVC_TO_0MS | 0x00); -#endif - /* Headphone ON, MUTE, Min volume */ - as3514_write(AS3514_HPH_OUT_L, - HPH_OUT_L_HP_ON | HPH_OUT_L_HP_MUTE | 0x00); +#endif /* HAVE_AS3543 */ -#ifdef PHILIPS_SA9200 - /* LRCK 8-23kHz (there are audible clicks while reading the ADC otherwise) */ - as3514_write(AS3514_PLLMODE, PLLMODE_LRCK_8_23); -#else - /* LRCK 24-48kHz */ - as3514_write(AS3514_PLLMODE, PLLMODE_LRCK_24_48); -#endif - - /* DAC_Mute_off */ - as3514_set(AS3514_DAC_L, DAC_L_DAC_MUTE_off); + /* registers identical on as3514/as3515 and as3543 */ /* M1_Sup_off */ as3514_set(AS3514_MIC1_L, MIC1_L_M1_SUP_off); -#ifndef HAVE_AS3543 - /* M2_Sup_off */ - as3514_set(AS3514_MIC2_L, MIC2_L_M2_SUP_off); -#endif + + /* Headphone ON, MUTE, Min volume */ + as3514_write(AS3514_HPH_OUT_L, HPH_OUT_L_HP_ON | HPH_OUT_L_HP_MUTE | 0x00); + + /* DAC_Mute_off */ + as3514_set(AS3514_DAC_L, DAC_L_DAC_MUTE_off); } static void audiohw_mute(bool mute) @@ -262,8 +245,7 @@ void audiohw_set_master_vol(int vol_l, int vol_r) unsigned int hph_r, hph_l; unsigned int mix_l, mix_r; - if(vol_l == 0 && vol_r == 0) - { + if (vol_l == 0 && vol_r == 0) { audiohw_mute(true); return; } @@ -298,11 +280,18 @@ void audiohw_set_master_vol(int vol_l, int vol_r) audiohw_mute(false); } +#if 0 /* unused */ void audiohw_set_lineout_vol(int vol_l, int vol_r) { +#ifdef HAVE_AS3543 + /* line out volume is set in the same registers */ + audiohw_set_master_vol(vol_l, vol_r); +#else as3514_write_masked(AS3514_LINE_OUT_R, vol_r, AS3514_VOL_MASK); as3514_write_masked(AS3514_LINE_OUT_L, vol_l, AS3514_VOL_MASK); +#endif } +#endif /* Nice shutdown of AS3514 audio codec */ void audiohw_close(void) @@ -343,6 +332,7 @@ void audiohw_enable_recording(bool source_mic) AUDIOSET1_INPUT_MASK); #if CONFIG_CPU == AS3525v2 + /* XXX: why is the microphone supply not needed on other models ?? */ /* Enable supply */ as3514_clear(AS3514_MIC1_L, MIC1_L_M1_SUP_off); #endif @@ -455,5 +445,3 @@ void audiohw_set_monitor(bool enable) } } #endif /* HAVE_RECORDING || HAVE_FMRADIO_IN */ - - diff --git a/firmware/export/as3514.h b/firmware/export/as3514.h index 6916e2fb4a..e9eda62ee3 100644 --- a/firmware/export/as3514.h +++ b/firmware/export/as3514.h @@ -30,31 +30,45 @@ extern void audiohw_set_master_vol(int vol_l, int vol_r); extern void audiohw_set_lineout_vol(int vol_l, int vol_r); /* Register Descriptions */ + +#ifndef HAVE_AS3543 #define AS3514_LINE_OUT_R 0x00 #define AS3514_LINE_OUT_L 0x01 +#endif + #define AS3514_HPH_OUT_R 0x02 #define AS3514_HPH_OUT_L 0x03 + +#ifndef HAVE_AS3543 #define AS3514_LSP_OUT_R 0x04 #define AS3514_LSP_OUT_L 0x05 +#endif + #define AS3514_MIC1_R 0x06 #define AS3514_MIC1_L 0x07 + #ifndef HAVE_AS3543 #define AS3514_MIC2_R 0x08 #define AS3514_MIC2_L 0x09 #endif + #define AS3514_LINE_IN1_R 0x0a #define AS3514_LINE_IN1_L 0x0b + #ifndef HAVE_AS3543 #define AS3514_LINE_IN2_R 0x0c #define AS3514_LINE_IN2_L 0x0d #endif + #define AS3514_DAC_R 0x0e #define AS3514_DAC_L 0x0f #define AS3514_ADC_R 0x10 #define AS3514_ADC_L 0x11 + #ifdef HAVE_AS3543 #define AS3543_DAC_IF 0x12 #endif + #define AS3514_AUDIOSET1 0x14 #define AS3514_AUDIOSET2 0x15 #define AS3514_AUDIOSET3 0x16 @@ -65,18 +79,27 @@ extern void audiohw_set_lineout_vol(int vol_l, int vol_r); #define AS3543_PMU_ENABLE 0x1c #endif +#ifndef HAVE_AS3543 #define AS3514_PLLMODE 0x1d +#endif #ifdef HAVE_AS3543 -#define AS3543_CHARGER 0x19 /* PMU: sub register 1 (CHGVBUS1) */ +#define AS3543_CHARGER 0x19 /* PMU: 2 sub registers */ #endif #define AS3514_SYSTEM 0x20 #define AS3514_CVDD_DCDC3 0x21 + +#ifndef HAVE_AS3543 #define AS3514_CHARGER 0x22 #define AS3514_DCDC15 0x23 #define AS3514_SUPERVISOR 0x24 +#endif +/* AS3543 has 2 IRQ_ENRD registers at 0x23 and 0x24, but we don't use them + * We call the real IRQ_ENRD2 register, IRQ_ENRD0, to stay compatible with + * as3514, because the bits we use are the same + */ #define AS3514_IRQ_ENRD0 0x25 #define AS3514_IRQ_ENRD1 0x26 #define AS3514_IRQ_ENRD2 0x27 @@ -98,8 +121,8 @@ extern void audiohw_set_lineout_vol(int vol_l, int vol_r); /*** Audio Registers ***/ -/* 00h (LINE_OUT_R) to 1Dh (PLLMODE) */ -#define AS3514_NUM_AUDIO_REGS (0x1e) +/* 00h (LINE_OUT_R) to 16h (AUDIOSET3) */ +#define AS3514_NUM_AUDIO_REGS (0x17) /* Common registers masks */ #define AS3514_VOL_MASK (0x1f << 0) @@ -122,6 +145,8 @@ extern void audiohw_set_lineout_vol(int vol_l, int vol_r); #define HPH_OUT_R_HP_OVC_TO_256MS (0x0 << 6) #define HPH_OUT_R_HP_OVC_TO_512MS (0x2 << 6) /* AS3543 */ + #define HPH_OUT_R_LINEOUT (0x1 << 7) + #define HPH_OUT_R_HEADPHONES (0x0 << 7) #define HPH_OUT_R_HP_OUT_SUM (0x0 << 5) #define HPH_OUT_R_HP_OUT_DAC (0x1 << 5) #define HPH_OUT_R_HP_OUT_LINE (0x2 << 5) @@ -237,17 +262,25 @@ extern void audiohw_set_lineout_vol(int vol_l, int vol_r); #endif /* AUDIOSET1 (14h)*/ -#define AUDIOSET1_ADC_on (0x1 << 7) +#ifdef HAVE_AS3543 +#define AUDIOSET1_DAC_on (0x1 << 6) +#define AUDIOSET1_DAC_GAIN_on (0x1 << 5) +#else #define AUDIOSET1_SUM_on (0x1 << 6) #define AUDIOSET1_DAC_on (0x1 << 5) #define AUDIOSET1_LOUT_on (0x1 << 4) +#endif /* HAVE_AS3543 */ +/* common bits */ +#define AUDIOSET1_ADC_on (0x1 << 7) #define AUDIOSET1_LIN2_on (0x1 << 3) #define AUDIOSET1_LIN1_on (0x1 << 2) #define AUDIOSET1_MIC2_on (0x1 << 1) #define AUDIOSET1_MIC1_on (0x1 << 0) + #define AUDIOSET1_INPUT_MASK AUDIOSET1_MIC1_on | AUDIOSET1_MIC2_on | \ AUDIOSET1_LIN1_on | AUDIOSET1_LIN2_on + /* AUDIOSET2 (15h) */ #ifdef HAVE_AS3543 #define AUDIOSET2_HPH_QUALITY_LOW_POWER (0x0 << 4) @@ -270,9 +303,17 @@ extern void audiohw_set_lineout_vol(int vol_l, int vol_r); #endif /* AUDIOSET3 (16h) */ +#ifdef HAVE_AS3543 +#define AUDIOSET3_HP_FASTSTART (0x1 << 2) +#define AUDIOSET3_HP_LONGSTART (0x0 << 2) +#define AUDIOSET3_HP_BIAS_150 (0x1 << 1) +#define AUDIOSET3_HPCM_on (0x1 << 0) +#define AUDIOSET3_HPCM_off (0x0 << 0) +#else #define AUDIOSET3_ZCU_off (0x1 << 2) #define AUDIOSET3_IBR_HPH (0x1 << 1) #define AUDIOSET3_HPCM_off (0x1 << 0) +#endif /* PLLMODE (1Dh) */ #define PLLMODE_LRCK (0x3 << 1)