* Felipe Balbi <felipebalbi@xxxxxxxxxxxxxxxxxxxxx> [081120 02:55]: > This list has been moved to linux-omap@xxxxxxxxxxxxxxx > > Please, keep that in Cc, also for ASoC development, send it also to the > proper alsa mailing list alsa-devel@xxxxxxxxxxxxxxxx > > Tony, I think you should apply this patch in mainline tree: > > diff --git a/MAINTAINERS b/MAINTAINERS > index 8dae455..54c8e90 100644 > --- a/MAINTAINERS > +++ b/MAINTAINERS > @@ -4010,6 +4010,13 @@ P: Alex Dubov > M: oakad@xxxxxxxxx > S: Maintained > > +TI OMAP > +P: Tony Lindgren > +M: tony@xxxxxxxxxxx > +L: linux-omap@xxxxxxxxxxxxxxx > +T: git kernel.org:/pub/scm/linux/tmlind/linux-omap-2.6.git > +S: Maintained > + > TI OMAP MMC INTERFACE DRIVER > P: Carlos Aguiar, Anderson Briglia and Syed Khasim > M: linux-omap@xxxxxxxxxxxxxxx Yeah sure. Let's also add maintainers for omap subsystems that have maintainers while we're at it. Tony > > > On Thu, Nov 20, 2008 at 12:02 PM, naveen krishna ch > <naveenkrishna.ch@xxxxxxxxx> wrote: > > Hi All > > > > I have been working on TWL4030 codec driver for ALSA SOC. > > I have taken sound/soc/codec/twl4030.c as reference from main line > > > > This Patch adds some kcontrols, widgets and interconnection map for some of > > the TWL4030 ASOC codec > > I was building it for a custom board as it was for OVERO > > > > > > Suggestions on the DAPM part of the driver would be helpful > > > > Thanks in advance. > > > > The patch is as follows. > > > > > > --- twl4030.c 2008-11-19 12:04:32.000000000 +0530 > > +++ /home/chnaveen/Desktop/twl4030.c 2008-11-21 15:08:06.000000000 +0530 > > @@ -16,7 +16,9 @@ > > * along with this program; if not, write to the Free Software > > * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA > > * 02110-1301 USA > > - * > > + * Modified by : Naveen Krishna Ch > > + * Added Kcontrols for OMAP3 WaterlooBoard > > + * Dated : 28th october 2008 > > */ > > > > #include <linux/module.h> > > @@ -29,24 +31,27 @@ > > #include <linux/i2c/twl4030.h> > > #include <sound/core.h> > > #include <sound/pcm.h> > > +#include <sound/jack.h> > > #include <sound/pcm_params.h> > > #include <sound/soc.h> > > #include <sound/soc-dapm.h> > > #include <sound/initval.h> > > - > > +#include <asm/arch/twl4030.h> > > #include "twl4030.h" > > > > +static int twl4030_jack_func; > > + > > /* > > * twl4030 register cache & default register settings > > */ > > static const u8 twl4030_reg[TWL4030_CACHEREGNUM] = { > > 0x00, /* this register not used */ > > - 0x93, /* REG_CODEC_MODE (0x1) */ > > + 0x03, /* REG_CODEC_MODE (0x1) */ > > 0xc3, /* REG_OPTION (0x2) */ > > 0x00, /* REG_UNKNOWN (0x3) */ > > 0x00, /* REG_MICBIAS_CTL (0x4) */ > > - 0x24, /* REG_ANAMICL (0x5) */ > > - 0x04, /* REG_ANAMICR (0x6) */ > > + 0xb0, /* REG_ANAMICL (0x5) */ > > + 0x10, /* REG_ANAMICR (0x6) */ > > 0x0a, /* REG_AVADC_CTL (0x7) */ > > 0x00, /* REG_ADCMICSEL (0x8) */ > > 0x00, /* REG_DIGMIXING (0x9) */ > > @@ -67,22 +72,22 @@ > > 0x00, /* REG_ARX2VTXPGA (0x18) */ > > 0x00, /* REG_ARXL1_APGA_CTL (0x19) */ > > 0x00, /* REG_ARXR1_APGA_CTL (0x1A) */ > > - 0x4b, /* REG_ARXL2_APGA_CTL (0x1B) */ > > - 0x4b, /* REG_ARXR2_APGA_CTL (0x1C) */ > > + 0x2b, /* REG_ARXL2_APGA_CTL (0x1B) */ > > + 0x2b, /* REG_ARXR2_APGA_CTL (0x1C) */ > > 0x00, /* REG_ATX2ARXPGA (0x1D) */ > > 0x00, /* REG_BT_IF (0x1E) */ > > 0x00, /* REG_BTPGA (0x1F) */ > > 0x00, /* REG_BTSTPGA (0x20) */ > > - 0x00, /* REG_EAR_CTL (0x21) */ > > - 0x24, /* REG_HS_SEL (0x22) */ > > - 0x0a, /* REG_HS_GAIN_SET (0x23) */ > > - 0x00, /* REG_HS_POPN_SET (0x24) */ > > - 0x00, /* REG_PREDL_CTL (0x25) */ > > - 0x00, /* REG_PREDR_CTL (0x26) */ > > - 0x00, /* REG_PRECKL_CTL (0x27) */ > > - 0x00, /* REG_PRECKR_CTL (0x28) */ > > - 0x00, /* REG_HFL_CTL (0x29) */ > > - 0x00, /* REG_HFR_CTL (0x2A) */ > > + 0x20, /* REG_EAR_CTL (0x21) */ > > + 0x00, /* REG_HS_SEL (0x22) */ > > + 0x05, /* REG_HS_GAIN_SET (0x23) */ > > + 0x42, /* REG_HS_POPN_SET (0x24) */ > > + 0x20, /* REG_PREDL_CTL (0x25) */ > > + 0x20, /* REG_PREDR_CTL (0x26) */ > > + 0x20, /* REG_PRECKL_CTL (0x27) */ > > + 0x20, /* REG_PRECKR_CTL (0x28) */ > > + 0x1f, /* REG_HFL_CTL (0x29) */ > > + 0x1f, /* REG_HFR_CTL (0x2A) */ > > 0x00, /* REG_ALC_CTL (0x2B) */ > > 0x00, /* REG_ALC_SET1 (0x2C) */ > > 0x00, /* REG_ALC_SET2 (0x2D) */ > > @@ -112,9 +117,40 @@ > > 0x00, /* REG_VIBRA_CTL (0x45) */ > > 0x00, /* REG_VIBRA_SET (0x46) */ > > 0x00, /* REG_VIBRA_PWM_SET (0x47) */ > > - 0x00, /* REG_ANAMIC_GAIN (0x48) */ > > + 0x24, /* REG_ANAMIC_GAIN (0x48) */ > > 0x00, /* REG_MISC_SET_2 (0x49) */ > > }; > > +static void twl4030_ext_control(struct snd_soc_codec *codec) > > +{ > > + if (twl4030_jack_func) > > + snd_soc_dapm_enable_pin(codec, "Headphone Jack"); > > + else > > + snd_soc_dapm_disable_pin(codec, "Headphone Jack"); > > + > > + snd_soc_dapm_sync(codec); > > +} > > + > > +static int twl4030_get_jack(struct snd_kcontrol *kcontrol, > > + struct snd_ctl_elem_value *ucontrol) > > +{ > > + ucontrol->value.integer.value[0] = twl4030_jack_func; > > + > > + return 0; > > +} > > + > > +static int twl4030_set_jack(struct snd_kcontrol *kcontrol, > > + struct snd_ctl_elem_value *ucontrol) > > +{ > > + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); > > + > > + if (twl4030_jack_func == ucontrol->value.integer.value[0]) > > + return 0; > > + > > + twl4030_jack_func = ucontrol->value.integer.value[0]; > > + twl4030_ext_control(codec); > > + > > + return 1; > > +} > > > > /* > > * read twl4030 register cache > > @@ -188,14 +224,83 @@ > > twl4030_write(codec, i, twl4030_reg[i]); > > > > } > > +static const char *jack_function[] = {"Off", "Headphone"}; > > + > > +static const struct soc_enum twl4030_enum[] = { > > + SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(jack_function), jack_function), > > +}; > > + > > > > static const struct snd_kcontrol_new twl4030_snd_controls[] = { > > - SOC_DOUBLE_R("Master Playback Volume", > > - TWL4030_REG_ARXL2PGA, TWL4030_REG_ARXR2PGA, > > - 0, 127, 0), > > - SOC_DOUBLE_R("Capture Volume", > > - TWL4030_REG_ATXL1PGA, TWL4030_REG_ATXR1PGA, > > - 0, 127, 0), > > + > > + /* Master Playback Volume Controls */ > > + SOC_DOUBLE_R("Master PLayback Course Gain ctrl", > > + TWL4030_REG_ARXL2PGA, TWL4030_REG_ARXR2PGA, > > + 6, 3, 0), > > + SOC_DOUBLE_R("Master Playback Fine Gain ctrl", > > + TWL4030_REG_ARXL2PGA, TWL4030_REG_ARXR2PGA, > > + 0, 63, 0), > > + > > + /* Playback Speaker volume controls */ > > + SOC_DOUBLE_R("Speaker R2+L2 Volume ctrls", > > + TWL4030_REG_ARXL2_APGA_CTL, TWL4030_REG_ARXR2_APGA_CTL, > > + 3, 17, 0), > > + > > + /* Capture Gain controls */ > > + SOC_DOUBLE_R("Master Capture Gain ctrl", > > + TWL4030_REG_ATXL1PGA, TWL4030_REG_ATXR1PGA, > > + 0, 31, 0), > > + /* Loop gain controls*/ > > + SOC_DOUBLE("Loop Gain ctrl", TWL4030_REG_ATX2ARXPGA, > > + 3 , 0, 7, 0), > > + > > + SOC_DOUBLE("Main +Sub mic capture gain ctrl", > > + TWL4030_REG_ANAMIC_GAIN, 3 , 0, 5, 0), > > + > > + SOC_DOUBLE_R("External Speaker Volume control", > > + TWL4030_REG_PREDL_CTL, TWL4030_REG_PREDR_CTL, > > + 4, 3, 0), > > + > > + SOC_DOUBLE_R("Pre Car kit Volume control", > > + TWL4030_REG_PRECKL_CTL, TWL4030_REG_PRECKR_CTL, > > + 4, 3, 0), > > + > > + SOC_SINGLE("DACL2", TWL4030_REG_AVDAC_CTL, 3, 1, 0), > > + SOC_SINGLE("DACR2", TWL4030_REG_AVDAC_CTL, 2, 1, 0), > > + > > + SOC_ENUM_EXT("Jack Function", twl4030_enum[0], > > + twl4030_get_jack, twl4030_set_jack), > > +}; > > + > > +/* Right PGA Mixer control switches */ > > +static const struct snd_kcontrol_new twl4030_right_pga_mixer_controls[] = { > > + SOC_DAPM_SINGLE("HS Mic switch", TWL4030_REG_ANAMICL, 1, 1, 0), > > + SOC_DAPM_SINGLE("Aux/FM right switch", TWL4030_REG_ANAMICR, 2, 1, > > 0), > > + SOC_DAPM_SINGLE("Sub Mic switch", TWL4030_REG_ANAMICR, 0, 1, 0), > > +}; > > + > > +/* Left PGA Mixer control switches */ > > +static const struct snd_kcontrol_new twl4030_left_pga_mixer_controls[] = { > > + SOC_DAPM_SINGLE("HS Mic switch", TWL4030_REG_ANAMICL, 1, 1, 0), > > + SOC_DAPM_SINGLE("Aux/FM left switch", TWL4030_REG_ANAMICL, 2, 1, > > 0), > > + SOC_DAPM_SINGLE("Main Mic switch", TWL4030_REG_ANAMICL, 0, 1, 0), > > +}; > > + > > +/* Right DACR2 Mixer */ > > +static const struct snd_kcontrol_new twl4030_dacr2_mixer_controls[] = { > > + SOC_DAPM_SINGLE("Headset-R switch", TWL4030_REG_HS_SEL, 5, 1, 0), > > + SOC_DAPM_SINGLE("Handsfree-R switch", TWL4030_REG_HFR_CTL, 5, 1, > > 0), > > + SOC_DAPM_SINGLE("PRECK-R switch", TWL4030_REG_PRECKR_CTL, 2, 1, > > 0), > > + SOC_DAPM_DOUBLE("E class-D amp-R switch", TWL4030_REG_PREDR_CTL, 3, 2, > > 1, 0, 0), > > +}; > > + > > +/* Left DACL2 Mixer */ > > +static const struct snd_kcontrol_new twl4030_dacl2_mixer_controls[] = { > > + SOC_DAPM_SINGLE("Headset-L switch", TWL4030_REG_HS_SEL, 2, 1, 0), > > + SOC_DAPM_SINGLE("Handsfree-L switch", TWL4030_REG_HFL_CTL, 5, 1, > > 0), > > + SOC_DAPM_SINGLE("Ear peice switch", TWL4030_REG_EAR_CTL, 2, 1, > > 0), > > + SOC_DAPM_SINGLE("PRECK-L switch", TWL4030_REG_PRECKL_CTL, 2, 1, 0), > > + SOC_DAPM_DOUBLE("E class-D amp-L switch", TWL4031_REG_PREDL_CTL, 3, > > 2, 1, 0, 0), > > }; > > > > /* add non dapm controls */ > > @@ -215,27 +320,96 @@ > > } > > > > static const struct snd_soc_dapm_widget twl4030_dapm_widgets[] = { > > - SND_SOC_DAPM_INPUT("INL"), > > - SND_SOC_DAPM_INPUT("INR"), > > - > > - SND_SOC_DAPM_OUTPUT("OUTL"), > > - SND_SOC_DAPM_OUTPUT("OUTR"), > > - > > - SND_SOC_DAPM_DAC("DACL", "Left Playback", SND_SOC_NOPM, 0, 0), > > - SND_SOC_DAPM_DAC("DACR", "Right Playback", SND_SOC_NOPM, 0, 0), > > - > > - SND_SOC_DAPM_ADC("ADCL", "Left Capture", SND_SOC_NOPM, 0, 0), > > - SND_SOC_DAPM_ADC("ADCR", "Right Capture", SND_SOC_NOPM, 0, 0), > > + > > + SND_SOC_DAPM_HP("Headphone Jack", NULL), > > + > > + /* Left ADC for capture */ > > + SND_SOC_DAPM_ADC("ADCL", "Left Capture ADC", TWL4030_REG_AVADC_CTL, > > 3, 0), > > + > > + /* dapm widget (path domain) for left PGA mixer */ > > + SND_SOC_DAPM_MIXER("LINEIN-L", SND_SOC_NOPM, 0, 0, > > + &twl4030_left_pga_mixer_controls[0], > > + ARRAY_SIZE(twl4030_left_pga_mixer_controls)), > > + > > + /* Right ADC for capture*/ > > + SND_SOC_DAPM_ADC("ADCR", "Right Capture ADC", > > TWL4030_REG_AVADC_CTL, 1, 0), > > + > > + /* dapm widget (path domain) for right PGA mixer */ > > + SND_SOC_DAPM_MIXER("LINEIN-R", SND_SOC_NOPM, 0, 0, > > + &twl4030_right_pga_mixer_controls[0], > > + ARRAY_SIZE(twl4030_right_pga_mixer_controls)), > > + > > + /* dapm widget (path domain) for left DACL2 Mixer */ > > + > > + SND_SOC_DAPM_MIXER("DACL2 Mixer", SND_SOC_NOPM, 0, 0, > > + &twl4030_dacl2_mixer_controls[0], > > + ARRAY_SIZE(twl4030_dacl2_mixer_controls)), > > + > > + /* dapm widget (path domain) for DACR2 Mixer */ > > + SND_SOC_DAPM_MIXER("DACR2 Mixer", SND_SOC_NOPM, 0, 0, > > + &twl4030_dacr2_mixer_controls[0], > > + ARRAY_SIZE(twl4030_dacr2_mixer_controls)), > > + > > + /* Inputs Left*/ > > + SND_SOC_DAPM_INPUT("HSMIC"), > > + SND_SOC_DAPM_INPUT("Aux/fm left"), > > + SND_SOC_DAPM_INPUT("Main mic"), > > + > > + /* Inputs Right*/ > > + SND_SOC_DAPM_INPUT("HSMIC"), > > + SND_SOC_DAPM_INPUT("Aux/fm right"), > > + SND_SOC_DAPM_INPUT("Sub mic"), > > + > > + /* Outputs Left*/ > > + SND_SOC_DAPM_OUTPUT("HSOL"), > > + SND_SOC_DAPM_OUTPUT("IHF_LEFT"), > > + SND_SOC_DAPM_OUTPUT("EAR"), > > + SND_SOC_DAPM_OUTPUT("E class-D L"), > > + SND_SOC_DAPM_OUTPUT("PRECK-L"); > > + > > + /* Outputs Right */ > > + SND_SOC_DAPM_OUTPUT("HSOR"), > > + SND_SOC_DAPM_OUTPUT("IHF_RIGHT"), > > + SND_SOC_DAPM_OUTPUT("E class-D R"), > > + SND_SOC_DAPM_OUTPUT("PRECK-R"); > > }; > > > > static const struct snd_soc_dapm_route intercon[] = { > > - /* outputs */ > > - {"OUTL", NULL, "DACL"}, > > - {"OUTR", NULL, "DACR"}, > > - > > - /* inputs */ > > - {"ADCL", NULL, "INL"}, > > - {"ADCR", NULL, "INR"}, > > + > > + /* ******** Left input ******** */ > > + {"LINEIN-L", "HS Mic switch", "HSMIC"}, > > + {"LINEIN-L", "Aux/FM left switch", "Aux/fm left"}, > > + {"LINEIN-L", "Main Mic switch", "Main mic"}, > > + > > + {"ADCL", NULL, "LINEIN-L"}, > > + > > + > > + /* ******** Right Input ******** */ > > + {"LINEIN-R", "HS Mic switch", "HSMIC"}, > > + {"LINEIN-R", "Aux/FM right switch", "Aux/fm right"}, > > + {"LINEIN-R", "Sub Mic switch", "Sub mic"}, > > + > > + {"ADCR", NULL, "LINEIN-R"}, > > + > > + /* ******** Left Output ******** */ > > + //{"DACL2", NULL, "DACL2 Mixer"}, > > + > > + {"DACL2 Mixer", "Headset-L switch", "HSOL"}, > > + {"DACL2 Mixer", "Handsfree-L switch", "IHF_LEFT"}, > > + {"DACL2 Mixer", "Ear peice switch", "EAR"}, > > + {"DACL2 Mixer", "PRECK-L switch", "PRECK-L"}, > > + {"DACL2 Mixer","E class-D amp-L switch","E class-D L"}, > > + > > + {"Headphone Jack",NULL, "HSOL"}, > > + /* ******** Right Output ******** */ > > + //{"DACR2", NULL, "DACR2 Mixer"}, > > + > > + {"DACR2 Mixer", "Headset-R switch","HSOR"}, > > + {"DACR2 Mixer", "Handsfree-R switch","IHF_RIGHT"}, > > + {"DACR2 Mixer", "PRECK-R switch", "PRECK-R"}, > > + {"DACR2 Mixer","E class-D amp-R switch","E class-D R"}, > > + > > + {"Headphone Jack",NULL, "HSOR"}, > > }; > > > > static int twl4030_add_widgets(struct snd_soc_codec *codec) > > @@ -280,7 +454,7 @@ > > /* toggle CODECPDZ as per TRM */ > > twl4030_clear_codecpdz(codec); > > twl4030_set_codecpdz(codec); > > - > > + > > /* program anti-pop with bias ramp delay */ > > popn = twl4030_read_reg_cache(codec, TWL4030_REG_HS_POPN_SET); > > popn &= TWL4030_RAMP_DELAY; > > @@ -384,6 +558,9 @@ > > case 48000: > > mode |= TWL4030_APLL_RATE_48000; > > break; > > + case 96000: > > + mode |= TWL4030_APLL_RATE_96000; > > + break; > > default: > > printk(KERN_ERR "TWL4030 hw params: unknown rate %d\n", > > params_rate(params)); > > @@ -434,6 +611,7 @@ > > u8 infreq; > > > > switch (freq) { > > + > > case 19200000: > > infreq = TWL4030_APLL_INFREQ_19200KHZ; > > break; > > @@ -504,20 +682,24 @@ > > return 0; > > } > > > > -#define TWL4030_RATES (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000) > > +#define TWL4030_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 | \ > > + SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | \ > > + SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \ > > + SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000) > > + > > #define TWL4030_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | > > SNDRV_PCM_FORMAT_S24_LE) > > > > struct snd_soc_dai twl4030_dai = { > > .name = "twl4030", > > .playback = { > > .stream_name = "Playback", > > - .channels_min = 2, > > + .channels_min = 1, > > .channels_max = 2, > > .rates = TWL4030_RATES, > > .formats = TWL4030_FORMATS,}, > > .capture = { > > .stream_name = "Capture", > > - .channels_min = 2, > > + .channels_min = 1, > > .channels_max = 2, > > .rates = TWL4030_RATES, > > .formats = TWL4030_FORMATS,}, > > @@ -616,13 +798,14 @@ > > > > codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); > > if (codec == NULL) > > - return -ENOMEM; > > - > > + return -ENOMEM; > > + > > socdev->codec = codec; > > mutex_init(&codec->mutex); > > INIT_LIST_HEAD(&codec->dapm_widgets); > > INIT_LIST_HEAD(&codec->dapm_paths); > > - > > + > > + > > twl4030_socdev = socdev; > > twl4030_init(socdev); > > > > Patch ends.. > > > > Thanks and Regards, > > > > (: Naveen Krishna Ch :) > > _______________________________________________ > > Linux-omap-open-source mailing list > > Linux-omap-open-source@xxxxxxxxxxxxxx > > http://linux.omap.com/mailman/listinfo/linux-omap-open-source > > > > > > -- > Best Regards, > > Felipe Balbi > felipebalbi@xxxxxxxxxxxxxxxxxxxxx -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html