[alsa-devel] [PATCH 1/2] ASoC: cs35l36: Add support for Cirrus CS35L36 Amplifier

Charles Keepax ckeepax at opensource.cirrus.com
Wed Nov 14 12:29:14 CET 2018


On Tue, Nov 13, 2018 at 12:49:16PM -0600, James Schulman wrote:
> Add driver support for Cirrus Logic CS35L36 boosted
> speaker amplifier
> 
> Signed-off-by: James Schulman <james.schulman at cirrus.com>
> ---

Mostly just some small nitpicky comments from me:

> +#include "cs35l36.h"
> +
> +struct reg_default cs35l36_reg[CS35L36_MAX_CACHE_REG] = {

Your allocating an array that is much larger than you need here.
This array will have an entry for all possible register addresses
on the device, whereas only a very small subset of those
addresses have defaults infact most of them arn't even registers.

> +	{CS35L36_TESTKEY_CTRL,			0x00000000},
...
> +struct  cs35l36_private {
> +	struct device *dev;
> +	struct cs35l36_platform_data pdata;
> +	struct regmap *regmap;
> +	struct regulator_bulk_data supplies[2];
> +	int num_supplies;
> +	int clksrc;
> +	int prev_clksrc;
> +	int extclk_freq;
> +	int extclk_cfg;
> +	int fll_igain;
> +	int sclk;
> +	int chip_version;
> +	int rev_id;
> +	struct gpio_desc *reset_gpio;
> +	struct completion global_pup_done;
> +	struct completion global_pdn_done;

These two completions are unused.

> +static int cs35l36_dai_set_sysclk(struct snd_soc_dai *dai,
> +				int clk_id, unsigned int freq, int dir)
> +{
> +	struct snd_soc_component *component = dai->component;
> +	struct cs35l36_private *cs35l36 =
> +			snd_soc_component_get_drvdata(component);
> +	int fs1_val = 0;
> +	int fs2_val = 0;
> +
> +	/* Need the SCLK Frequency regardless of sysclk source */
> +	cs35l36->sclk = freq;

Yet it is only used locally in this function.

> +	if (cs35l36->sclk > 6000000) {
> +		fs1_val = 3 * 4 + 4;
> +		fs2_val = 8 * 4 + 4;
> +	}
> +
> +	if (cs35l36->sclk <= 6000000) {
> +		fs1_val = 3 * ((24000000 + cs35l36->sclk - 1) / cs35l36->sclk)
> +				+ 4;
> +		fs2_val = 5 * ((24000000 + cs35l36->sclk - 1) / cs35l36->sclk)
> +				+ 4;
> +	}

Nitpicking: Since both paths add 4 you could initialise fs1_val and
fs2_val to 4, then use += would avoid the line wraps for the + 4's
here.

> +static int cs35l36_pcm_startup(struct snd_pcm_substream *substream,
> +			       struct snd_soc_dai *dai)
> +{
> +	if (!substream->runtime)
> +		return 0;

This null check shouldn't be needed now since:

8053f21675b0 ("ASoC: dapm: Add a dummy snd_pcm_runtime to avoid NULL pointer access")

> +
> +	snd_pcm_hw_constraint_list(substream->runtime, 0,
> +				SNDRV_PCM_HW_PARAM_RATE, &cs35l36_constraints);
> +	return 0;
> +}
...
> +static int cs35l36_component_set_sysclk(struct snd_soc_component *component,
> +				int clk_id, int source, unsigned int freq,
> +				int dir)
> +{
> +	struct cs35l36_private *cs35l36 =
> +			snd_soc_component_get_drvdata(component);
> +	int ret;
> +
> +	cs35l36->extclk_freq = freq;

extclk_freq doesn't appear to be used at all, is there an
expectation it will be in the future?

> +	cs35l36->prev_clksrc = cs35l36->clksrc;

Should this be stored in cs35l36_private, given it is only used
locally in this function?

> +
> +	switch (clk_id) {
> +	case 0:
> +		cs35l36->clksrc = CS35L36_PLLSRC_SCLK;
> +		break;
> +	case 1:
> +		cs35l36->clksrc = CS35L36_PLLSRC_LRCLK;
> +		break;
> +	case 2:
> +		cs35l36->clksrc = CS35L36_PLLSRC_PDMCLK;
> +		break;
> +	case 3:
> +		cs35l36->clksrc = CS35L36_PLLSRC_SELF;
> +		break;
> +	case 4:
> +		cs35l36->clksrc = CS35L36_PLLSRC_MCLK;

Seems clksrc is also only used locally, is there some future work
expected on the clocking?

> +		break;
> +	default:
> +		return -EINVAL;
> +	}
> +
> +	ret = cs35l36_get_clk_config(cs35l36, freq);
> +

Would it be simpler just to return a pointer to the
cs35l36_pll_sysclk_config structure?

> +	if (cs35l36->rev_id == CS35L36_REV_A0) {
> +		if (cs35l36->pdata.dcm_mode) {

Nitpick:
Could probably use an && here.

> +static int cs35l36_pac(struct cs35l36_private *cs35l36)
> +{
> +	int ret, count;
> +	unsigned int val;
> +
> +	if (cs35l36->rev_id == CS35L36_REV_B0) {

Nitpick:
This is already checked before you call the function, so I would
be inclined to drop it but if doing it here it would probably be
better to invert the logic and do:

if (cs35l36->rev_id != CS35L36_REV_B0)
	return 0;

> +	switch (cs35l36->rev_id) {
> +	case CS35L36_REV_A0:
> +		ret = regmap_register_patch(cs35l36->regmap,
> +				cs35l36_reva0_errata_patch,
> +				ARRAY_SIZE(cs35l36_reva0_errata_patch));
> +		if (ret < 0) {
> +			dev_err(dev, "Failed to apply A0 errata patch %d\n",
> +					ret);
> +			goto err;
> +		}
> +		ret = regmap_register_patch(cs35l36->regmap,
> +					cs35l36_pac_int_patch,
> +					ARRAY_SIZE(cs35l36_pac_int_patch));
> +		if (ret < 0) {
> +			dev_err(dev, "Failed to apply A0PAC errata patch %d\n",
> +					ret);
> +			goto err;
> +		}

Is this really what you want, having two calls to
remap_register_patch will apply the settings from both here, but
only the second of those calls would be reapplied on cache_sync
later. Now I guess you don't have any cache_syncs so it won't
cause a problem now but feels like it has the potential to cause
confusion down the road.

> +	ret = devm_request_threaded_irq(dev, i2c_client->irq, NULL, cs35l36_irq,
> +					IRQF_ONESHOT |
> +					irq_pol,

Nitpick probably fire this up on the same line as the ONESHOT.

> +					"cs35l36", cs35l36);

Thanks,
Charles


More information about the Alsa-devel mailing list