All of lore.kernel.org
 help / color / mirror / Atom feed
From: Lars-Peter Clausen <lars-Qo5EllUWu/uELgA04lAiVw@public.gmane.org>
To: Sean Cross <xobs-nXMMniAx+RbQT0dZR+AlfA@public.gmane.org>
Cc: devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	alsa-devel-K7yf7f+aM1XWsZ/bQMPhNw@public.gmane.org,
	Mark Brown <broonie-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>,
	Shawn Guo <shawn.guo-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>,
	Liam Girdwood <lgirdwood-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>,
	Sascha Hauer <kernel-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
Subject: Re: [alsa-devel] [PATCH 1/3] sound: soc: codecs: Add es8328 codec
Date: Sat, 08 Feb 2014 17:06:39 +0100	[thread overview]
Message-ID: <52F6560F.7060606@metafoo.de> (raw)
In-Reply-To: <1391749517-11787-2-git-send-email-xobs-nXMMniAx+RbQT0dZR+AlfA@public.gmane.org>

On 02/07/2014 06:05 AM, Sean Cross wrote:
> Add support for the ES8328 audio codec.

Hi,

a couple of minor coments. Also when submitting a patch it is a good idea to 
run scripts/checkpatch.pl on the patch itself and `make C=2` and `make C=2 
CHECK=scripts/coccicheck` on your driver module (E.g. in your case `make C=2 
sound/soc/codecs/es8328.o`). These tools check your driver for a couple of 
known issues. Fixing those before the submission will make the reviews job 
easier.
> [...]
> +uint8_t sample_ratios[] = {

static const

> +	[ES8328_RATE_8019 ] = 0x9,
> +	[ES8328_RATE_11025] = 0x7,
> +	[ES8328_RATE_22050] = 0x4,
> +	[ES8328_RATE_44100] = 0x2,
> +};
> [...]
> +
> +static int es8328_hw_params(struct snd_pcm_substream *substream,
> +	struct snd_pcm_hw_params *params,
> +	struct snd_soc_dai *dai)
> +{
> +	struct snd_soc_codec *codec = dai->codec;
> +
> +	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
> +		u8 dac = snd_soc_read(codec, ES8328_DACCONTROL2);
> +		dac &= ~ES8328_DACCONTROL2_RATEMASK;
> +
> +		switch (params_rate(params)) {
> +		case 8000:
> +			dac |= sample_ratios[ES8328_RATE_8019];
> +			break;
> +		case 11025:
> +			dac |= sample_ratios[ES8328_RATE_11025];
> +			break;
> +		case 22050:
> +			dac |= sample_ratios[ES8328_RATE_22050];
> +			break;
> +		case 44100:
> +			dac |= sample_ratios[ES8328_RATE_44100];
> +			break;
> +		default:
> +			dev_err(codec->dev, "%s: unknown rate %d\n",
> +				 __func__, params_rate(params));
> +			return -EINVAL;
> +		}
> +		snd_soc_write(codec, ES8328_DACCONTROL2, dac);
> +	}
> +
> +	if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
> +		u8 adc = snd_soc_read(codec, ES8328_ADCCONTROL5);
> +		adc &= ~ES8328_ADCCONTROL5_RATEMASK;
> +
> +		switch (params_rate(params)) {
> +		case 8000:
> +			adc |= sample_ratios[ES8328_RATE_8019];
> +			break;
> +		case 11025:
> +			adc |= sample_ratios[ES8328_RATE_11025];
> +			break;
> +		case 22050:
> +			adc |= sample_ratios[ES8328_RATE_22050];
> +			break;
> +		case 44100:
> +			adc |= sample_ratios[ES8328_RATE_44100];
> +			break;
> +		default:
> +			dev_err(codec->dev, "%s: unknown rate %d\n",
> +				 __func__, params_rate(params));
> +			return -EINVAL;
> +		}
> +		snd_soc_write(codec, ES8328_ADCCONTROL5, adc);
> +	}

The only difference between the capture and the playback path seems to be 
the register that's written two. By adding a variable that holds the 
register number and gets initialized based on the direction you can elimate 
about half of the code in this function.

> +
> +	return 0;
[...]
> +static int es8328_set_dai_sysclk(struct snd_soc_dai *codec_dai,
> +			         int clk_id, unsigned int freq, int dir)
> +{
> +	struct snd_soc_codec *codec = codec_dai->codec;
> +	struct es8328_priv *es8328 = snd_soc_codec_get_drvdata(codec);
> +
> +	switch (clk_id) {
> +	case 0:
> +		es8328->sysclk = freq;

es8328->sysclk seems to be unused. I guess it might be used if you add 
support for different base clock rates. For now you should probably return 
an error if freq != 22579200.

> +		break;
> +	default:
> +		return -EINVAL;
> +	}
> +
> +	return 0;
> +}
[...]
> +static int es8328_dac_enable(struct snd_soc_codec *codec)
> +{
> +	u16 old_volumes[4];
> +	u16 reg;
> +	int i;
> +
> +	for (i = 0; i < 4; i++) {
> +		old_volumes[i] = snd_soc_read(codec, i + ES8328_DACCONTROL24);
> +		snd_soc_write(codec, i + ES8328_DACCONTROL24, 0);
> +	}

This looks like a job for AUTOMUTE controls. They'll set the volume to zero 
before the DAC is powered down and restore the original value after the DAC 
was powered up.

> +
> +	/* Power up LOUT2 ROUT2, and power down xOUT1 */
> +	snd_soc_write(codec, ES8328_DACPOWER,
> +			ES8328_DACPOWER_ROUT2_ON |
> +			ES8328_DACPOWER_LOUT2_ON);
> +
> +	/* Enable click-free power up */
> +	snd_soc_write(codec, ES8328_DACCONTROL6, ES8328_DACCONTROL6_CLICKFREE);
> +	snd_soc_write(codec, ES8328_DACCONTROL3, 0x36);
> +
> +	/* Set I2S to 16-bit mode */
> +	snd_soc_write(codec, ES8328_DACCONTROL1, ES8328_DACCONTROL1_DACWL_16);
> +
> +	/* No attenuation */
> +	snd_soc_write(codec, ES8328_DACCONTROL4, 0x00);
> +	snd_soc_write(codec, ES8328_DACCONTROL5, 0x00);
> +
> +	/* Set LIN2 for the output mixer */
> +	snd_soc_write(codec, ES8328_DACCONTROL16,
> +			ES8328_DACCONTROL16_RMIXSEL_RIN2 |
> +			ES8328_DACCONTROL16_LMIXSEL_LIN2);
> +
> +	/* Point the left DAC at the left mixer */
> +	snd_soc_write(codec, ES8328_DACCONTROL17, ES8328_DACCONTROL17_LD2LO);
> +	/* Point the right DAC at the right mixer */
> +	snd_soc_write(codec, ES8328_DACCONTROL20, ES8328_DACCONTROL20_RD2RO);
> +
> +	/* Disable all other outputs */
> +	snd_soc_write(codec, ES8328_DACCONTROL18, 0x00);
> +	snd_soc_write(codec, ES8328_DACCONTROL19, 0x00);
> +
> +
> +	/* Disable mono mode for DACL, and mute DACR */
> +	snd_soc_write(codec, ES8328_DACCONTROL7, 0x00);
> +
> +	for (i = 0; i < 4; i++)
> +		snd_soc_write(codec, i + ES8328_DACCONTROL24, old_volumes[i]);
> +
> +	reg = snd_soc_read(codec, ES8328_CHIPPOWER);
> +	reg &= ~(ES8328_CHIPPOWER_DACVREF_OFF |
> +		 ES8328_CHIPPOWER_DACPLL_OFF |
> +		 ES8328_CHIPPOWER_DACSTM_RESET |
> +		 ES8328_CHIPPOWER_DACDIG_OFF);
> +	snd_soc_write(codec, ES8328_CHIPPOWER, reg);
> +	snd_soc_write(codec, ES8328_DACCONTROL3, 0x32);
> +
> +	return 0;
> +}
[...]
> +static int es8328_suspend(struct snd_soc_codec *codec)
> +{
> +	return 0;
> +}
> +

If you don't do anything in suspend there is no need to provide a callback 
function.

> +static int es8328_resume(struct snd_soc_codec *codec)
> +{
> +	es8328_init(codec);
> +	return 0;
> +}
> +
> +static int es8328_probe(struct snd_soc_codec *codec)
> +{
> +	int ret;
> +	struct device *dev = codec->dev;
> +
> +	ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP);
> +	if (ret < 0) {
> +		dev_err(dev, "failed to configure cache I/O: %d\n", ret);
> +		return ret;
> +	}
> +
> +	/* power on device */
> +	es8328_init(codec);
> +
> +	return 0;
> +}
> +
> +static int es8328_remove(struct snd_soc_codec *codec)
> +{
> +	/* Power everything down and reset the cip */
> +	snd_soc_write(codec, ES8328_CHIPPOWER,
> +			ES8328_CHIPPOWER_DACSTM_RESET |
> +			ES8328_CHIPPOWER_ADCSTM_RESET |
> +			ES8328_CHIPPOWER_DACDIG_OFF |
> +			ES8328_CHIPPOWER_ADCDIG_OFF |
> +			ES8328_CHIPPOWER_DACVREF_OFF |
> +			ES8328_CHIPPOWER_ADCVREF_OFF);
> +
> +	return 0;
> +}
> +
> +static struct snd_soc_codec_driver soc_codec_dev_es8328 = {

es8328_codec_driver is a better name.

THe soc_codec_dev_... naming scheme you see in some drivers comes from a pre 
multi-component era where it was more firt

> +	.probe =		es8328_probe,
> +	.remove =		es8328_remove,
> +	.suspend =		es8328_suspend,
> +	.resume =		es8328_resume,
> +	.controls =		es8328_snd_controls,
> +	.num_controls =		ARRAY_SIZE(es8328_snd_controls),
> +	.dapm_widgets =		es8328_dapm_widgets,
> +	.num_dapm_widgets =	ARRAY_SIZE(es8328_dapm_widgets),
> +	.dapm_routes =		es8328_intercon,
> +	.num_dapm_routes =	ARRAY_SIZE(es8328_intercon),
> +};
[...]
> +#if defined(CONFIG_SPI_MASTER)
> +static int es8328_spi_probe(struct spi_device *spi)
> +{
> +	struct es8328_priv *es8328;
> +	int ret;
> +
> +	es8328 = devm_kzalloc(&spi->dev, sizeof(struct es8328_priv),
> +			      GFP_KERNEL);

sizeof(*es8328) is the preferred style for kernel code.

> +	if (es8328 == NULL)
> +		return -ENOMEM;
> +
> +	es8328->regmap = devm_regmap_init_spi(spi, &es8328_regmap);
> +	if (IS_ERR(es8328->regmap))
> +		return PTR_ERR(es8328->regmap);
> +
> +	spi_set_drvdata(spi, es8328);
> +
> +	ret = snd_soc_register_codec(&spi->dev,
> +			&soc_codec_dev_es8328, &es8328_dai, 1);
> +	if (ret < 0)
> +		dev_err(&spi->dev, "unable to register codec: %d\n", ret);
> +
> +	return ret;
> +}
[...]
> +#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
> +static int es8328_i2c_probe(struct i2c_client *i2c,
> +			    const struct i2c_device_id *id)
> +{
> +	struct es8328_priv *es8328;
> +	int ret;
> +
> +	es8328 = devm_kzalloc(&i2c->dev, sizeof(struct es8328_priv),
> +			      GFP_KERNEL);

same here.

> +	if (es8328 == NULL)
> +		return -ENOMEM;
> +
> +	es8328->regmap = devm_regmap_init_i2c(i2c, &es8328_regmap);
> +	if (IS_ERR(es8328->regmap))
> +		return PTR_ERR(es8328->regmap);
> +
> +	i2c_set_clientdata(i2c, es8328);
> +
> +	ret =  snd_soc_register_codec(&i2c->dev,
> +			&soc_codec_dev_es8328, &es8328_dai, 1);
> +
> +	return ret;
> +}
> +
[...]
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

  parent reply	other threads:[~2014-02-08 16:06 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-02-07  5:05 [PATCH 0/3] Add i.MX6q Kosagi Novena support Sean Cross
     [not found] ` <1391749517-11787-1-git-send-email-xobs-nXMMniAx+RbQT0dZR+AlfA@public.gmane.org>
2014-02-07  5:05   ` [PATCH 1/3] sound: soc: codecs: Add es8328 codec Sean Cross
2014-02-07 18:12     ` Mark Brown
2014-02-08  8:10       ` Sean Cross
     [not found]         ` <52F5E661.5010807-nXMMniAx+RbQT0dZR+AlfA@public.gmane.org>
2014-02-10 14:23           ` Mark Brown
     [not found]       ` <20140207181238.GL1757-GFdadSzt00ze9xe1eoZjHA@public.gmane.org>
2014-02-08  8:17         ` Sean Cross
2014-02-10  9:24         ` Sean Cross
     [not found]           ` <52F89ADF.8020305-nXMMniAx+RbQT0dZR+AlfA@public.gmane.org>
2014-02-10 14:27             ` Mark Brown
     [not found]     ` <1391749517-11787-2-git-send-email-xobs-nXMMniAx+RbQT0dZR+AlfA@public.gmane.org>
2014-02-08 16:06       ` Lars-Peter Clausen [this message]
2014-02-07  5:05   ` [PATCH 2/3] sound: soc: fsl: Add support for Novena onboard audio Sean Cross
     [not found]     ` <1391749517-11787-3-git-send-email-xobs-nXMMniAx+RbQT0dZR+AlfA@public.gmane.org>
2014-02-07 18:14       ` Mark Brown
     [not found]         ` <20140207181433.GM1757-GFdadSzt00ze9xe1eoZjHA@public.gmane.org>
2014-02-08  8:27           ` Sean Cross
     [not found]             ` <52F5EA67.1080008-nXMMniAx+RbQT0dZR+AlfA@public.gmane.org>
2014-02-10 14:45               ` Mark Brown
2014-02-07  5:05   ` [PATCH 3/3] dts: imx: add kosagi novena imx6q dts file Sean Cross

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=52F6560F.7060606@metafoo.de \
    --to=lars-qo5elluwu/uelga04laivw@public.gmane.org \
    --cc=alsa-devel-K7yf7f+aM1XWsZ/bQMPhNw@public.gmane.org \
    --cc=broonie-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org \
    --cc=devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
    --cc=kernel-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org \
    --cc=lgirdwood-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org \
    --cc=shawn.guo-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org \
    --cc=xobs-nXMMniAx+RbQT0dZR+AlfA@public.gmane.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.