[alsa-devel] [PATCH v3] ASoC: Add Freescale SGTL5000 codec support

Zeng Zhaoming zhaoming.zeng at freescale.com
Wed Feb 16 19:53:52 CET 2011


On Wed 2011-02-16 19:53:14, Mark Brown wrote:
> On Wed, Feb 16, 2011 at 06:56:16AM +0800, zhaoming.zeng at freescale.com wrote:
> 
> > +static int mic_bias_event(struct snd_soc_dapm_widget *w,
> > +	struct snd_kcontrol *kcontrol, int event)
> > +{
> > +	/* change mic bias resistor to 4Kohm */
> > +	snd_soc_update_bits(w->codec, SGTL5000_CHIP_MIC_CTRL,
> > +			SGTL5000_BIAS_R_4k, SGTL5000_BIAS_R_4k);
> > +
> > +	return 0;
> > +}
> 
> I'd expect something to power off the mic bias when there's a power off
> event.
>
I will add it in the next version.

> > +	reg = snd_soc_read(codec, SGTL5000_CHIP_DAC_VOL);
> > +	l = (reg & SGTL5000_DAC_VOL_LEFT_MASK) >> SGTL5000_DAC_VOL_LEFT_SHIFT;
> > +	r = (reg & SGTL5000_DAC_VOL_RIGHT_MASK) >> SGTL5000_DAC_VOL_RIGHT_SHIFT;
> > +	l = l < 0x3c ? 0x3c : l;
> > +	l = l > 0xfc ? 0xfc : l;
> > +	r = r < 0x3c ? 0x3c : r;
> > +	r = r > 0xfc ? 0xfc : r;
> 
> My previous comments about the lebility of this still stand.
>
Sorry, I don't catch you means quite well, you means more comments to make it clearer?

> > +/* need SOC_DOUBLE_S8_TLV with invert */
> > +#define SGTL5000_PCM_PLAYBACK_CONTROL	\
> > +	 {			\
> > +		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,	\
> > +		.name = "PCM Playback Volume",		\
> > +		.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |	\
> > +			SNDRV_CTL_ELEM_ACCESS_READWRITE,	\
> > +		.info = dac_info_volsw,				\
> > +		.get = dac_get_volsw,				\
> > +		.put = dac_put_volsw,				\
> > +	}
> 
> Since there's no macro arguments this could just be defined directly in
> line.
>
you means add it to kcontrol array directly instead of define a macro for it?

> > +	SOC_SINGLE("Capture Attenuate Switch (-6db)",
> > +		SGTL5000_CHIP_ANA_ADC_CTRL,
> > +		8, 1, 0),
> 
> This should be a TLV control (-6 to 0 in steps of 6 dB) with Volume
> rather than Switch.
> 
> > +	/* set devided factor of frame clock */
> > +	switch (sys_fs / frame_rate) {
> > +	case 4:
> > +		clk_ctl |= SGTL5000_RATE_MODE_DIV_4 << SGTL5000_RATE_MODE_SHIFT;
> > +		break;
> > +	case 2:
> > +		clk_ctl |= SGTL5000_RATE_MODE_DIV_2 << SGTL5000_RATE_MODE_SHIFT;
> > +		break;
> > +	/*
> > +	 * this implict case 1:
> > +	 * because default: sys_fs = lrclk;
> > +	 */
> > +	default:
> > +		clk_ctl |= SGTL5000_RATE_MODE_DIV_1 << SGTL5000_RATE_MODE_SHIFT;
> > +		break;
> > +	}
> 
> This would be much better off as case 1: with a default returning an
> error in case the user has misclocked the device.  For example, if the
> ratio were to wind up as 8 then we'd accept that.
> 
> > +	/*
> > +	 * calculate the divider of mclk/sample_freq,
> > +	 * factor of freq =96k can only be 256, since mclk in range (12m,27m)
> > +	 */
> > +	if (sys_fs * 256 == sgtl5000->sysclk)
> > +		clk_ctl |= SGTL5000_MCLK_FREQ_256FS <<
> > +			SGTL5000_MCLK_FREQ_SHIFT;
> > +	else if (sys_fs * 384 == sgtl5000->sysclk)
> > +		clk_ctl |= SGTL5000_MCLK_FREQ_384FS <<
> > +			SGTL5000_MCLK_FREQ_SHIFT;
> > +	else if (sys_fs * 512 == sgtl5000->sysclk)
> > +		clk_ctl |= SGTL5000_MCLK_FREQ_512FS <<
> > +			SGTL5000_MCLK_FREQ_SHIFT;
> 
> This'd be clearer as a switch on sysfs / sysclk with this:
> 
> > +	else {
> > +		/* if mclk not satisify the divider, using pll */
> > +		if (sgtl5000->master)
> > +			clk_ctl |= SGTL5000_MCLK_FREQ_PLL <<
> > +				SGTL5000_MCLK_FREQ_SHIFT;
> > +		else {
> > +			pr_err("%s: PLL not supported in slave mode\n",
> > +				__func__);
> > +			return -EINVAL;
> > +		}
> 
> as the default.
>
Yes, it is clearer. thanks for the suggestion.

> > +	} else
> > +		/* power down pll */
> > +		snd_soc_update_bits(codec, SGTL5000_CHIP_ANA_POWER,
> > +			SGTL5000_PLL_POWERUP | SGTL5000_VCOAMP_POWERUP,
> > +			0);
> 
> Use { } for the else case if the main case uses them.
> 
> > +	case SND_SOC_BIAS_STANDBY:
> > +		if (codec->bias_level == SND_SOC_BIAS_OFF) {
> > +			for (i = 0; i < SGTL5000_SUPPLY_NUM; i++) {
> > +				if (!sgtl5000->supplies[i])
> > +					continue;
> > +				regulator_enable(sgtl5000->supplies[i]);
> 
> Why are the supplies optional?
> 
> > +	vdda  = regulator_get_voltage(sgtl5000->supplies[VDDA]) / 1000;
> > +	vddio = regulator_get_voltage(sgtl5000->supplies[VDDIO]) / 1000;
> 
> You're not checking these for errors.
> 
> > +	if (sgtl5000->supplies[VDDD])
> > +		vddd = regulator_get_voltage(sgtl5000->supplies[VDDD]) / 1000;
> > +	else
> > +		vddd = 0;
> 
> If VDD is optional it'd seem easier to substitute in a fixed voltage
> regulator when it's not detected.  It'd make the code much more
> idiomatic and save having to special case missing regulators everywhere.
>
Ok, I will try to add a fixed regulator if VDDD not provided externally.

> > +	if (!vddd) {
> > +		/* set VDDD to 1.2v */
> > +		lreg_ctrl |= 0x8 << SGTL5000_LINREG_VDDD_SHIFT;
> > +		/* power up internal linear regulator */
> > +		ana_pwr |= SGTL5000_LINEREG_D_POWERUP |
> > +				SGTL5000_LINREG_SIMPLE_POWERUP |
> > +				SGTL5000_STARTUP_POWERUP;
> > +	}
> 
> Or even implement an actual regulator driver for it.
> 
> > +	/* set default volume of adc */
> > +	reg = snd_soc_read(codec, SGTL5000_CHIP_ANA_ADC_CTRL);
> > +	reg &= ~SGTL5000_ADC_VOL_M6DB;
> > +	reg &= ~(SGTL5000_ADC_VOL_LEFT_MASK | SGTL5000_ADC_VOL_RIGHT_MASK);
> > +	reg |= (0xf << SGTL5000_ADC_VOL_LEFT_SHIFT)
> > +	    | (0xf << SGTL5000_ADC_VOL_RIGHT_SHIFT);
> > +	snd_soc_write(codec, SGTL5000_CHIP_ANA_ADC_CTRL, reg);
> 
> Leave this up to userspace.

Thanks.



More information about the Alsa-devel mailing list