[alsa-devel] [PATCH v2] ASoC: Add support for cs42l73 codec

Lars-Peter Clausen lars at metafoo.de
Fri Sep 30 20:50:38 CEST 2011


On 09/30/2011 06:41 PM, Brian Austin wrote:
> This patch adds support for the Cirrus Logic CS42L73
> low power stereo codec.
> 
> This patch has cleared checkpatch.pl with no warnings or errors.
> Code changes requested were implemented.
> ASoC API changes requested were implemented.
> 
> Signed-off-by: Brian Austin <brian.austin at cirrus.com>
> ---
> [...]
> +struct  cs42l73_private {

extra space

> [...]
> +
> +static const struct snd_soc_dapm_route cs42l73_audio_map[] = {
> +	{"HPOUTA", NULL, "HP Amp Left"},
> +	{"HPOUTB", NULL, "HP Amp Right"},
> +	{"LINEOUTA", NULL, "LO Amp Left"},
> +	{"LINEOUTB", NULL, "LO Amp Right"},
> +	{"SPKOUT", NULL, "SPK Amp"},
> +	{"EAROUT", NULL, "EAR Amp"},
> +	{"SPKLINEOUT", NULL, "SPKLO Amp"},
> +
> +	{"HP Amp Left", "DAC", "DAC Left"},
> +	{"HP Amp Right", "DAC", "DAC Right"},
> +	{"LO Amp Left", "DAC", "DAC Left"},
> +	{"LO Amp Right", "DAC", "DAC Right"},
> +	{"SPK Amp", "DAC", "DAC Left"},
> +	{"SPKLO Amp", "DAC", "DAC Right"},
> +	{"EAR Amp", "DAC", "DAC Right"},

I suppose this won't work as expected. The control element of the path will
only have an effect if the sink is a mixer or a mux.

> +
> +	{"PGA Mux Left", NULL, "LINEINA"},
> +	{"PGA Mux Right", NULL, "LINEINB"},
> +	{"PGA Mux Left", NULL, "MIC1"},
> +	{"PGA Mux Right", NULL, "MIC2"},

You probably want connect the inputs of the mux depending on its setting.

e.g. {"PGA Mux Left", "Line A", "LINEINA"},

[...]
> +
> +struct cs42l73_mclk_div cs42l73_mclk_coeffs[] = {

static

> [...]
> +
> +struct cs42l73_mclkx_div cs42l73_mclkx_coeffs[] = {

static

> [...]
> +int cs42l73_get_mclkx_coeff(int mclkx)

static

> [...]
> +int cs42l73_get_mclk_coeff(int mclk, int srate)

static


> +
> +static int cs42l73_set_mclk(struct snd_soc_dai *dai)
> +{
> +	struct snd_soc_codec *codec = dai->codec;
> +	struct cs42l73_private *priv = snd_soc_codec_get_drvdata(codec);
> +
> +	int mclkx_coeff;
> +	u32 mclk = 0;
> +	u8 dmmcc = 0;
> +
> +	/* MCLKX -> MCLK */
> +	mclkx_coeff = cs42l73_get_mclkx_coeff(priv->sysclk);
> +

here you use priv->sysclk ...

> +
> +static int cs42l73_set_sysclk(struct snd_soc_dai *dai,
> +			      int clk_id, unsigned int freq, int dir)
> +{
> +	struct snd_soc_codec *codec = dai->codec;
> +	struct cs42l73_private *priv = snd_soc_codec_get_drvdata(codec);
> +
> +	if (clk_id != CS42L73_CLKID_MCLK1 && clk_id != CS42L73_CLKID_MCLK2) {
> +		dev_err(codec->dev, "Invalid clk_id %u\n", clk_id);
> +		return -EINVAL;
> +	}
> +
> +	if ((cs42l73_get_mclkx_coeff(freq) < 0)) {
> +		dev_err(codec->dev, "Invalid sysclk %u\n", freq);
> +		return -EINVAL;
> +	}
> +
> +	if ((cs42l73_set_mclk(dai)) < 0) {
> +		dev_err(codec->dev, "Unable to set MCLK for dai %s\n",
> +			dai->name);
> +		return -EINVAL;
> +	}
> +
> +	priv->sysclk = freq;
> +	priv->mclksel = clk_id;
> +

... but here you only set it after having called cs42l73_set_mclk. Is this
correct? Maybe pass it in as a parameter to cs42l73_set_mclk

> +	return 0;
> +}
> +
> +static int cs42l73_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
> +{
> +	struct snd_soc_codec *codec = codec_dai->codec;
> +	struct cs42l73_private *priv = snd_soc_codec_get_drvdata(codec);
> +	int id = codec_dai->id;
> +	int inv, format;

unsigned int

> +	u8 spc, mmcc;
> +
>[...]
> +

> +static int cs42l73_set_bias_level(struct snd_soc_codec *codec,
> +				  enum snd_soc_bias_level level)
> +{
> +	int ret;
> +
> +	switch (level) {
> +	case SND_SOC_BIAS_ON:
> +		snd_soc_update_bits(codec, CS42L73_DMMCC, MCLKDIS, 0);
> +		snd_soc_update_bits(codec, CS42L73_PWRCTL1, PDN, 0);
> +		break;
> +
> +	case SND_SOC_BIAS_PREPARE:
> +		break;
> +
> +	case SND_SOC_BIAS_STANDBY:
> +		if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
> +				ret = snd_soc_cache_sync(codec);

indention

> [...]
> +
> +static struct snd_soc_dai_ops cs42l73_ops = {

const

> +	.startup = cs42l73_pcm_startup,
> +	.hw_params = cs42l73_pcm_hw_params,
> +	.set_fmt = cs42l73_set_dai_fmt,
> +	.set_sysclk = cs42l73_set_sysclk,
> +	.set_tristate = cs42l73_set_tristate,
> +};
> +
> +struct snd_soc_dai_driver cs42l73_dai[] = {

static

> +	{
> +	 .name = "cs42l73-xsp",
> +	 .id = CS42L73_XSP,
> +	 .playback = {
> +		      .stream_name = "XSP Playback",
> +		      .channels_min = 1,
> +		      .channels_max = 2,
> +		      .rates = CS42L73_RATES,
> +		      .formats = CS42L73_FORMATS,},
> +
> +	 .capture = {
> +		     .stream_name = "XSP Capture",
> +		     .channels_min = 1,
> +		     .channels_max = 2,
> +		     .rates = CS42L73_RATES,
> +		     .formats = CS42L73_FORMATS,},
> +
> +	 .ops = &cs42l73_ops,
> +	 .symmetric_rates = 1,
> +	 },

Indention looks a bit odd here

> [...]
> +static int cs42l73_probe(struct snd_soc_codec *codec)
> +{
> +	int ret;
> +	unsigned int devid = 0;
> +	struct cs42l73_private *cs42l73 = snd_soc_codec_get_drvdata(codec);
> +
> +	codec->control_data = cs42l73->control_data;
> +	codec->hw_write = (hw_write_t)i2c_master_send;

You don't need to initialize control_data and hw_write.
snd_soc_codec_set_cache_io will do this for you. This also means that you can
remove the control_data field from your driver private data struct.

> +
> +	ret = snd_soc_codec_set_cache_io(codec, 8, 8, cs42l73->control_type);

If you CODEC only has a I2C interface you can use SND_SOC_I2C here directly
instead of cs42l73->control_type

> [...]
> +
> +	snd_soc_add_controls(codec, cs42l73_snd_controls,
> +			     ARRAY_SIZE(cs42l73_snd_controls));

Just put the controls in your codec driver struct instead of manually adding them.

> +
> +	return ret;
> +}
> +
> +static int cs42l73_remove(struct snd_soc_codec *codec)
> +{
> +	cs42l73_set_bias_level(codec, SND_SOC_BIAS_OFF);
> +	return 0;
> +}
> +
> +struct snd_soc_codec_driver soc_codec_dev_cs42l73 = {

static

> +	.probe = cs42l73_probe,
> +	.remove = cs42l73_remove,
> +	.suspend = cs42l73_suspend,
> +	.resume = cs42l73_resume,
> +	.set_bias_level = cs42l73_set_bias_level,
> +	.reg_cache_size = ARRAY_SIZE(cs42l73_reg),
> +	.reg_cache_default = cs42l73_reg,
> +	.reg_word_size = sizeof(u8),
> +	.dapm_widgets = cs42l73_dapm_widgets,
> +	.num_dapm_widgets = ARRAY_SIZE(cs42l73_dapm_widgets),
> +	.dapm_routes = cs42l73_audio_map,
> +	.num_dapm_routes = ARRAY_SIZE(cs42l73_audio_map),
> +};
> +


More information about the Alsa-devel mailing list