Index: apps/debug_menu.c =================================================================== --- apps/debug_menu.c (revision 19563) +++ apps/debug_menu.c (working copy) @@ -72,6 +72,7 @@ #if CONFIG_TUNER #include "tuner.h" #include "radio.h" +#include "fmradio_i2c.h" #endif #endif @@ -2306,6 +2307,34 @@ (unsigned)nfo.write_regs[2], (unsigned)nfo.write_regs[3], (unsigned)nfo.write_regs[4]); #endif +#if (CONFIG_TUNER & SI4700) + unsigned char buf[32]; + fmradio_i2c_read(0x20, buf, sizeof(buf)); + simplelist_addline(SIMPLELIST_ADD_LINE, + "%02X%02X %02X%02X %02X%02X %02X%02X", + (unsigned)buf[12], (unsigned)buf[13], + (unsigned)buf[14], (unsigned)buf[15], + (unsigned)buf[16], (unsigned)buf[17], + (unsigned)buf[18], (unsigned)buf[19]); + simplelist_addline(SIMPLELIST_ADD_LINE, + "%02X%02X %02X%02X %02X%02X %02X%02X", + (unsigned)buf[20], (unsigned)buf[21], + (unsigned)buf[22], (unsigned)buf[23], + (unsigned)buf[24], (unsigned)buf[25], + (unsigned)buf[26], (unsigned)buf[27]); + simplelist_addline(SIMPLELIST_ADD_LINE, + "%02X%02X %02X%02X %02X%02X %02X%02X", + (unsigned)buf[28], (unsigned)buf[29], + (unsigned)buf[30], (unsigned)buf[31], + (unsigned)buf[0], (unsigned)buf[1], + (unsigned)buf[2], (unsigned)buf[3]); + simplelist_addline(SIMPLELIST_ADD_LINE, + "%02X%02X %02X%02X %02X%02X %02X%02X", + (unsigned)buf[4], (unsigned)buf[5], + (unsigned)buf[6], (unsigned)buf[7], + (unsigned)buf[8], (unsigned)buf[9], + (unsigned)buf[10], (unsigned)buf[11]); +#endif return ACTION_REDRAW; } static bool dbg_fm_radio(void) Index: apps/keymaps/keymap-clip.c =================================================================== --- apps/keymaps/keymap-clip.c (revision 19563) +++ apps/keymaps/keymap-clip.c (working copy) @@ -220,12 +220,19 @@ /** FM Radio Screen **/ static const struct button_mapping button_context_radio[] = { - { ACTION_FM_MENU, BUTTON_SELECT|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_FM_PRESET, BUTTON_SELECT|BUTTON_REL, BUTTON_NONE }, - { ACTION_FM_STOP, BUTTON_POWER|BUTTON_REL, BUTTON_NONE }, - { ACTION_FM_MODE, BUTTON_UP|BUTTON_REPEAT, BUTTON_UP }, - { ACTION_FM_EXIT, BUTTON_DOWN|BUTTON_REL, BUTTON_NONE }, + /* Copied from keymap-c200.c 20081207. Feel free to suggest a better one.*/ + { ACTION_NONE, BUTTON_UP, BUTTON_NONE }, + { ACTION_FM_MENU, BUTTON_DOWN, BUTTON_NONE }, + { ACTION_FM_PRESET, BUTTON_SELECT, BUTTON_NONE }, + { ACTION_FM_STOP, BUTTON_UP|BUTTON_REPEAT, BUTTON_UP }, +/* { ACTION_FM_MODE, BUTTON_REC, BUTTON_NONE }, */ + { ACTION_FM_EXIT, BUTTON_POWER|BUTTON_REL, BUTTON_POWER }, { ACTION_FM_PLAY, BUTTON_UP|BUTTON_REL, BUTTON_UP }, + { ACTION_SETTINGS_INC, BUTTON_VOL_UP, BUTTON_NONE }, + { ACTION_SETTINGS_INCREPEAT,BUTTON_VOL_UP|BUTTON_REPEAT, BUTTON_NONE }, + { ACTION_SETTINGS_DEC, BUTTON_VOL_DOWN, BUTTON_NONE }, + { ACTION_SETTINGS_DECREPEAT,BUTTON_VOL_DOWN|BUTTON_REPEAT, BUTTON_NONE }, + LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_SETTINGS) }; /* button_context_radio */ Index: firmware/export/config-clip.h =================================================================== --- firmware/export/config-clip.h (revision 19563) +++ firmware/export/config-clip.h (working copy) @@ -20,13 +20,12 @@ #define REC_FREQ_DEFAULT REC_FREQ_22 /* Default is not 44.1kHz */ #define REC_SAMPR_DEFAULT SAMPR_22 +#endif /* Define bitmask of input sources - recordable bitmask can be defined explicitly if different */ #define INPUT_SRC_CAPS (SRC_CAP_MIC | SRC_CAP_FMRADIO) -#endif - /* define this if you have a bitmap LCD display */ #define HAVE_LCD_BITMAP @@ -103,10 +102,8 @@ #define AB_REPEAT_ENABLE 1 /* FM Tuner */ -#if 0 /* disabled since there is no driver (yet) */ #define CONFIG_TUNER SI4700 /* in fact SI4702 but let's hope it's compatible */ //#define HAVE_TUNER_PWR_CTRL -#endif /* Define this for LCD backlight available */ #define HAVE_BACKLIGHT Index: firmware/export/config-fuze.h =================================================================== --- firmware/export/config-fuze.h (revision 19563) +++ firmware/export/config-fuze.h (working copy) @@ -19,8 +19,8 @@ /* Define bitmask of input sources - recordable bitmask can be defined explicitly if different */ +#endif #define INPUT_SRC_CAPS (SRC_CAP_MIC | SRC_CAP_FMRADIO) -#endif /* define this if you have a bitmap LCD display */ #define HAVE_LCD_BITMAP @@ -99,7 +99,7 @@ #define AB_REPEAT_ENABLE 1 /* FM Tuner - suspected to be the SI4702 */ -//#define CONFIG_TUNER SI4700 +#define CONFIG_TUNER SI4700 /* #define HAVE_TUNER_PWR_CTRL */ /* Define this for LCD backlight available */ Index: firmware/export/config-e200v2.h =================================================================== --- firmware/export/config-e200v2.h (revision 19563) +++ firmware/export/config-e200v2.h (working copy) @@ -17,10 +17,10 @@ #define REC_FREQ_DEFAULT REC_FREQ_22 /* Default is not 44.1kHz */ #define REC_SAMPR_DEFAULT SAMPR_22 +#endif /* Define bitmask of input sources - recordable bitmask can be defined explicitly if different */ #define INPUT_SRC_CAPS (SRC_CAP_MIC | SRC_CAP_FMRADIO) -#endif /* define this if you have a bitmap LCD display */ #define HAVE_LCD_BITMAP @@ -99,7 +99,7 @@ #define AB_REPEAT_ENABLE 1 /* FM Tuner - suspected to be the SI4702 */ -//#define CONFIG_TUNER SI4700 +#define CONFIG_TUNER SI4700 /* #define HAVE_TUNER_PWR_CTRL */ /* Define this for LCD backlight available */ Index: firmware/export/audiohw.h =================================================================== --- firmware/export/audiohw.h (revision 19563) +++ firmware/export/audiohw.h (working copy) @@ -269,15 +269,14 @@ */ void audiohw_set_recvol(int left, int right, int type); +#endif /*HAVE_RECORDING*/ + /** - * Enable or disable recording monitor. - * @param enable ture or false. + * Enable or disable (recording) monitor. + * @param enable true or false. */ void audiohw_set_monitor(bool enable); -#endif /*HAVE_RECORDING*/ - - #if CONFIG_CODEC != SWCODEC /* functions which are only used by mas35xx codecs, but are also Index: firmware/export/as3514.h =================================================================== --- firmware/export/as3514.h (revision 19563) +++ firmware/export/as3514.h (working copy) @@ -203,6 +203,8 @@ #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) */ #define AUDIOSET2_BIAS_off (0x1 << 7) Index: firmware/target/arm/as3525/system-as3525.c =================================================================== --- firmware/target/arm/as3525/system-as3525.c (revision 19563) +++ firmware/target/arm/as3525/system-as3525.c (working copy) @@ -26,6 +26,7 @@ #include "ascodec-target.h" #include "dma-target.h" #include "clock-target.h" +#include "fmradio_i2c.h" #define default_interrupt(name) \ extern __attribute__((weak,alias("UIRQ"))) void name (void) @@ -263,6 +264,10 @@ * We don't need the power button in the bootloader. */ ascodec_init(); ascodec_write(AS3514_CVDD_DCDC3, ascodec_read(AS3514_CVDD_DCDC3) & (1<<2)); + +#ifdef CONFIG_TUNER + fmradio_i2c_init(); +#endif #endif /* !BOOTLOADER */ #ifdef HAVE_ADJUSTABLE_CPU_FREQ Index: firmware/target/arm/as3525/audio-as3525.c =================================================================== --- firmware/target/arm/as3525/audio-as3525.c (revision 19563) +++ firmware/target/arm/as3525/audio-as3525.c (working copy) @@ -7,7 +7,7 @@ * \/ \/ \/ \/ \/ * $Id$ * - * Copyright © 2008 Rafaël Carré + * Copyright (C) 2007 by Michael Sevakis * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -18,20 +18,83 @@ * KIND, either express or implied. * ****************************************************************************/ +#include "config.h" #include "system.h" #include "cpu.h" #include "audio.h" +#include "audiohw.h" #include "sound.h" -/* TODO */ +/* TODO + Once all AMS Sansas have recording, we could remove #ifdef HAVE_RECORDING + */ +int audio_channels = 2; +int audio_output_source = AUDIO_SRC_PLAYBACK; + void audio_set_output_source(int source) { - (void)source; -} + if ((unsigned)source >= AUDIO_NUM_SOURCES) + source = AUDIO_SRC_PLAYBACK; + audio_output_source = source; +} /* audio_set_output_source */ + void audio_input_mux(int source, unsigned flags) { - (void)source; - (void)flags; -} + static int last_source = AUDIO_SRC_PLAYBACK; + static bool last_recording = false; + bool recording = flags & SRCF_RECORDING; + + switch (source) + { + default: /* playback - no recording */ + source = AUDIO_SRC_PLAYBACK; + case AUDIO_SRC_PLAYBACK: + audio_channels = 2; + if (source != last_source) + { + audiohw_set_monitor(false); +#ifdef HAVE_RECORDING + audiohw_disable_recording(); +#endif /* HAVE_RECORDING */ + } + break; + +#ifdef HAVE_RECORDING + case AUDIO_SRC_MIC: /* recording only */ + audio_channels = 1; + if (source != last_source) + { + audiohw_set_monitor(false); + audiohw_enable_recording(true); /* source mic */ + } + break; +#endif /* HAVE_RECORDING */ + + case AUDIO_SRC_FMRADIO: /* recording and playback */ + audio_channels = 2; + if (source == last_source && recording == last_recording) + break; + + last_recording = recording; +#ifdef HAVE_RECORDING + if (recording) + { + audiohw_set_monitor(false); + audiohw_enable_recording(false); + } + else + { + audiohw_disable_recording(); + audiohw_set_monitor(true); /* line in analog audio path */ + } +#else + audiohw_set_monitor(true); +#endif /* HAVE_RECORDING */ + break; + } /* end switch */ + + last_source = source; +} /* audio_input_mux */ + Index: firmware/drivers/audio/as3514.c =================================================================== --- firmware/drivers/audio/as3514.c (revision 19563) +++ firmware/drivers/audio/as3514.c (working copy) @@ -31,6 +31,14 @@ #include "i2s.h" #include "ascodec.h" +/* AMS Sansas based on the AS3525 use the LINE2 input for the analog radio + signal instead of LINE1 */ +#if CONFIG_CPU == AS3525 +#define USE_LINEIN_1 0 +#else +#define USE_LINEIN_1 1 +#endif + const struct sound_settings_info audiohw_settings[] = { [SOUND_VOLUME] = {"dB", 0, 1, -74, 6, -25}, /* HAVE_SW_TONE_CONTROLS */ @@ -60,7 +68,9 @@ SOURCE_DAC = 0, SOURCE_MIC1, SOURCE_LINE_IN1, - SOURCE_LINE_IN1_ANALOG + SOURCE_LINE_IN2, + SOURCE_LINE_IN1_ANALOG, + SOURCE_LINE_IN2_ANALOG }; static unsigned int source = SOURCE_DAC; @@ -222,11 +232,14 @@ if (source == SOURCE_LINE_IN1_ANALOG) { mix_reg_r = AS3514_LINE_IN1_R; mix_reg_l = AS3514_LINE_IN1_L; + } else if (source == SOURCE_LINE_IN2_ANALOG) { + mix_reg_r = AS3514_LINE_IN2_R; + mix_reg_l = AS3514_LINE_IN2_L; } else { mix_reg_r = AS3514_DAC_R; mix_reg_l = AS3514_DAC_L; } - + /* We combine the mixer channel volume range with the headphone volume range - keep first stage as loud as possible */ if (vol_r <= 0x16) { @@ -253,10 +266,8 @@ void audiohw_set_lineout_vol(int vol_l, int vol_r) { - as3514_write_masked(AS3514_LINE_OUT_R, vol_r, - AS3514_VOL_MASK); - as3514_write_masked(AS3514_LINE_OUT_L, vol_l, - AS3514_VOL_MASK); + as3514_write_masked(AS3514_LINE_OUT_R, vol_r, AS3514_VOL_MASK); + as3514_write_masked(AS3514_LINE_OUT_L, vol_l, AS3514_VOL_MASK); } void audiohw_mute(bool mute) @@ -307,23 +318,29 @@ as3514_write_masked(AS3514_ADC_R, ADC_R_ADCMUX_ST_MIC, ADC_R_ADCMUX); - /* MIC1_on, LIN1_off */ - as3514_write_masked(AS3514_AUDIOSET1, AUDIOSET1_MIC1_on, - AUDIOSET1_MIC1_on | AUDIOSET1_LIN1_on); + /* MIC1_on, others off */ + as3514_write_masked(AS3514_AUDIOSET1, AUDIOSET1_MIC1_on, + AUDIOSET1_INPUT_MASK); + /* M1_AGC_off */ as3514_clear(AS3514_MIC1_R, MIC1_R_M1_AGC_off); } else { - source = SOURCE_LINE_IN1; - + source = USE_LINEIN_1 ? SOURCE_LINE_IN1 : SOURCE_LINE_IN2; + + /* Sync mixer volumes before switching inputs */ audiohw_set_master_vol(as3514.vol_l, as3514.vol_r); - /* ADCmux = Line_IN1 */ - as3514_write_masked(AS3514_ADC_R, ADC_R_ADCMUX_LINE_IN1, + /* ADCmux = Line_IN1 or Line_IN2 */ + as3514_write_masked(AS3514_ADC_R, + USE_LINEIN_1 ? ADC_R_ADCMUX_LINE_IN1 : + ADC_R_ADCMUX_LINE_IN2, ADC_R_ADCMUX); - /* MIC1_off, LIN1_on */ - as3514_write_masked(AS3514_AUDIOSET1, AUDIOSET1_LIN1_on, - AUDIOSET1_MIC1_on | AUDIOSET1_LIN1_on); + /* LIN1_or LIN2 on, rest off */ + as3514_write_masked(AS3514_AUDIOSET1, + USE_LINEIN_1 ? AUDIOSET1_LIN1_on : + AUDIOSET1_LIN2_on, + AUDIOSET1_INPUT_MASK); } /* ADC_Mute_off */ @@ -339,10 +356,8 @@ /* ADC_Mute_on */ as3514_clear(AS3514_ADC_L, ADC_L_ADC_MUTE_off); - /* ADC_off, LIN1_off, MIC_off */ - as3514_clear(AS3514_AUDIOSET1, - AUDIOSET1_ADC_on | AUDIOSET1_LIN1_on | - AUDIOSET1_MIC1_on); + /* ADC_off, all input sources off */ + as3514_clear(AS3514_AUDIOSET1, AUDIOSET1_ADC_on | AUDIOSET1_INPUT_MASK); audiohw_set_master_vol(as3514.vol_l, as3514.vol_r); } @@ -395,27 +410,37 @@ as3514_write_masked(AS3514_ADC_R, right, AS3514_VOL_MASK); as3514_write_masked(AS3514_ADC_L, left, AS3514_VOL_MASK); } +#endif /* HAVE_RECORDING */ /** - * Enable line in 1 analog monitoring + * Enable line in analog monitoring * */ void audiohw_set_monitor(bool enable) { if (enable) { - source = SOURCE_LINE_IN1_ANALOG; + source = USE_LINEIN_1 ? SOURCE_LINE_IN1_ANALOG : SOURCE_LINE_IN2_ANALOG; - as3514_set(AS3514_AUDIOSET1, AUDIOSET1_LIN1_on); - as3514_set(AS3514_LINE_IN1_R, LINE_IN1_R_LI1R_MUTE_off); - as3514_set(AS3514_LINE_IN1_L, LINE_IN1_L_LI1L_MUTE_off); + /* select either LIN1 or LIN2 */ + as3514_write_masked(AS3514_AUDIOSET1, + USE_LINEIN_1 ? + AUDIOSET1_LIN1_on : AUDIOSET1_LIN2_on, + AUDIOSET1_LIN1_on | AUDIOSET1_LIN2_on); + as3514_set(USE_LINEIN_1 ? AS3514_LINE_IN1_R : AS3514_LINE_IN2_R, + LINE_IN1_R_LI1R_MUTE_off); + as3514_set(USE_LINEIN_1 ? AS3514_LINE_IN1_L : AS3514_LINE_IN2_L, + LINE_IN1_L_LI1L_MUTE_off); } else { - as3514_clear(AS3514_AUDIOSET1, AUDIOSET1_LIN1_on); + /* turn off both LIN1 and LIN2 */ as3514_clear(AS3514_LINE_IN1_R, LINE_IN1_R_LI1R_MUTE_off); as3514_clear(AS3514_LINE_IN1_L, LINE_IN1_L_LI1L_MUTE_off); + as3514_clear(AS3514_LINE_IN2_R, LINE_IN2_R_LI2R_MUTE_off); + as3514_clear(AS3514_LINE_IN2_L, LINE_IN2_L_LI2L_MUTE_off); + as3514_clear(AS3514_AUDIOSET1, AUDIOSET1_LIN1_on | AUDIOSET1_LIN2_on); } /* Sync mixer volume */ audiohw_set_master_vol(as3514.vol_l, as3514.vol_r); } -#endif /* HAVE_RECORDING */ +