[alsa-devel] [PATCH 2/3] ASoC: CS4271 codec support

Mark Brown broonie at opensource.wolfsonmicro.com
Wed Dec 8 14:05:58 CET 2010


On Wed, Dec 08, 2010 at 03:02:52PM +0300, Alexander wrote:

> From: Alexander Sverdlin <subaparts at yandex.ru>
> 
> Added support for CS4271 codec to ASoC.
> 
> Signed-off-by: Alexander Sverdlin <subaparts at yandex.ru>

Overall this looks very good but a few issues below, mostly coding
style/clarity.

> +static int cs4271_set_dai_fmt(struct snd_soc_dai *codec_dai,
> +			      unsigned int format)
> +{
> +	struct snd_soc_codec *codec = codec_dai->codec;
> +	struct cs4271_private *cs4271 = snd_soc_codec_get_drvdata(codec);
> +
> +	cs4271->mode = format & SND_SOC_DAIFMT_FORMAT_MASK;
> +
> +	switch (format & SND_SOC_DAIFMT_MASTER_MASK) {
> +	default:
> +		dev_err(codec->dev, "Invalid DAI format\n");
> +		return -EINVAL;
> +	case SND_SOC_DAIFMT_CBS_CFS:
> +		cs4271->master = 0;
> +		break;
> +	case SND_SOC_DAIFMT_CBM_CFM:
> +		cs4271->master = 1;
> +	}

Missing break;  It's also much more usual to have the default: case be
the last one.  Similarly for your other switch statements.

> +	/* Configure ADC */
> +	snd_soc_update_bits(codec, CS4271_ADCCTL, CS4271_ADCCTL_ADC_DIF_MASK,
> +		(cs4271->mode == SND_SOC_DAIFMT_I2S) ?
> +		CS4271_ADCCTL_ADC_DIF_I2S : CS4271_ADCCTL_ADC_DIF_LJ);

Please don't use the ternery operator like this, it's not terribly
legible.

> +static const char *cs4271_de_texts[] = {"None", "44.1KHz", "48KHz", "32KHz"};
> +static const struct soc_enum cs4271_de_enum =
> +	SOC_ENUM_SINGLE(CS4271_DACCTL, 4, 4, cs4271_de_texts);

Ideally the deemphasis would be managed based on the sample rate.

> +struct snd_soc_dai_driver cs4271_dai = {
> +	.name = "cs4271-hifi",
> +	.playback = {
> +		.stream_name = "Playback",
> +		.channels_min = 2,
> +		.channels_max = 2,
> +		.rates = SNDRV_PCM_RATE_8000_96000,
> +		.rate_min = 8000,
> +		.rate_max = 96000,

No need to set rate_min and rate_max if rates is set.

Looking at the code above I suspect you need to set symmetric_rates on
the DAI too - it looks like the playback and capture must be at the same
rate.

> +/*
> + * This function writes all writeble registers from cache to codec.
> + * It's used to setup initial config and restore after suspend.
> + */
> +static int cs4271_write_cache(struct snd_soc_codec *codec)
> +{
> +	int i, ret;
> +
> +	for (i = CS4271_LASTREG; i >= CS4271_FIRSTREG; i--) {
> +		ret = snd_soc_write(codec, i, snd_soc_read(codec, i));
> +		if (ret) {
> +			dev_err(codec->dev, "Cache write failed\n");
> +			return ret;
> +		}
> +	}

If you use the standard cache code in soc-cache.c there's a standard
cache sync implementation you could use - snd_soc_cache_sync().

> +#ifdef CONFIG_PM
> +static int cs4271_soc_suspend(struct snd_soc_codec *codec, pm_message_t mesg)
> +{
> +	/* Set power-down bit */
> +	snd_soc_update_bits(codec, CS4271_MODE2, CS4271_MODE2_PDN,
> +		CS4271_MODE2_PDN);
> +
> +	return 0;
> +}
> +#else
> +#define cs4271_soc_suspend	NULL
> +#endif /* CONFIG_PM */
> +
> +static int cs4271_soc_resume(struct snd_soc_codec *codec)
> +{

A comment explaining why this isn't in the ifdef above would be useful.
I guessed why it was being done before I searched but it'd be good to be
clear.

> +	if ((gpio_disable >= 0) &&
> +		gpio_request(gpio_disable, "CS4271 Disable"))
> +		gpio_disable = -EINVAL;
> +	if (gpio_disable >= 0)
> +		gpio_direction_output(gpio_disable, 0);

This is quite hard to read.  One issue is that the indentation of the
second argument to the && is very confusing as it's lined up with the
contents of the if statement, the other is that non-explicit check on
the return value of gpio_request() means the expected value is not so
clear as it could be.

> +static struct i2c_driver cs4271_i2c_driver = {
> +	.driver = {
> +		.name	= "cs4271-codec",

No need for the -codec.


More information about the Alsa-devel mailing list