[alsa-devel] [PATCH 7/8] ASoC: codecs: Add AB8500 codec-driver
Mark Brown
broonie at opensource.wolfsonmicro.com
Mon Apr 23 20:59:37 CEST 2012
On Fri, Apr 20, 2012 at 11:33:22AM +0200, Ola Lilja wrote:
This is massively better than previous versions! There's still some
issues but hopefully not hard to correct.
> @@ -12,6 +12,7 @@ config SND_SOC_ALL_CODECS
> tristate "Build all ASoC CODEC drivers"
> select SND_SOC_88PM860X if MFD_88PM860X
> select SND_SOC_L3
> + select SND_SOC_AB8500_CODEC if SND_SOC_UX500
Shouldn't this depend on the MFD core for the device instead?
> +static int regulators_init(struct device *dev)
> +{
> + struct ab8500_codec_drvdata *drvdata = dev_get_drvdata(dev);
> +
> + dev_dbg(dev, "%s: Enter\n", __func__);
> +
> + regulators_get_regulator(dev, &drvdata->reg_vaud, "V-AUD");
> + regulators_get_regulator(dev, &drvdata->reg_vamic1, "V-AMIC1");
> + regulators_get_regulator(dev, &drvdata->reg_vamic2, "V-AMIC2");
> + regulators_get_regulator(dev, &drvdata->reg_vdmic, "V-DMIC");
> +
> + if (IS_ERR(drvdata->reg_vaud.consumer) ||
> + IS_ERR(drvdata->reg_vamic1.consumer) ||
> + IS_ERR(drvdata->reg_vamic2.consumer) ||
> + IS_ERR(drvdata->reg_vdmic.consumer)) {
> + regulators_cleanup(drvdata);
> + return -ENXIO;
> + }
This won't work with probe deferral - if we need to defer then the
driver will squash down the -EPROBE_DEFER and fail totally. Not a big
deal, though.
> +static int dapm_audioclk_event(struct snd_soc_dapm_widget *w,
> + struct snd_kcontrol *k, int event)
> +{
We should add a variant of REGULATOR_SUPPLY for clocks too, have a
framework thing that will own the clock - this is all generic code which
gets repeated for each clock, we could easily factor it out into the
core.
> +static int dapm_audioreg_event(struct snd_soc_dapm_widget *w,
> + struct snd_kcontrol *k, int event)
> +{
> + struct device *dev = w->codec->dev;
> + struct ab8500_codec_drvdata *drvdata = dev_get_drvdata(dev);
> + int status = 0;
> +
> + if (SND_SOC_DAPM_EVENT_ON(event))
> + status = regulator_enable(drvdata->reg_vaud.consumer);
> + else
> + regulator_disable(drvdata->reg_vaud.consumer);
Similarly this is just a REGULATOR_SUPPLY.
> +/* Mic 1b - Regulator select */
> +static const struct soc_enum enum_mic1breg_sel = SOC_ENUM_SINGLE(0, 0, 2,
> + enum_micreg);
> +static const struct snd_kcontrol_new dapm_mic1breg_mux[] = {
> + SOC_DAPM_ENUM_VIRT("Mic 1b Regulator Select",
> + enum_mic1breg_sel),
> +};
Can you explain how this hardware works in more detail? It seems very
odd to be changing the regulator used to supply something at runtime.
> +static int mclk_input_control_put(struct snd_kcontrol *kcontrol,
> + struct snd_ctl_elem_value *ucontrol)
> +{
> + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
> + struct ab8500_codec_drvdata *drvdata = dev_get_drvdata(codec->dev);
> + unsigned int val;
> +
> + val = (ucontrol->value.enumerated.item[0] != 0);
> + if (drvdata->mclk_sel == val)
> + return 0;
> +
> + drvdata->mclk_sel = val;
> +
> + return 1;
> +}
This is really weird
> +static const char * const enum_earselcm[] = {"0.95V", "1.10V", "1.27V",
> + "1.58V"};
> +static SOC_ENUM_SINGLE_DECL(soc_enum_earselcm,
> + AB8500_ANACONF1, AB8500_ANACONF1_EARSELCM, enum_earselcm);
Some of this stuff looks awfully like it ought to be platform data...
> +static const char * const enum_ensemicx[] = {"Differential", "Single Ended"};
> +static SOC_ENUM_SINGLE_DECL(soc_enum_ensemic1,
> + AB8500_ANAGAIN1, AB8500_ANAGAINX_ENSEMICX, enum_ensemicx);
> +static SOC_ENUM_SINGLE_DECL(soc_enum_lowpowmic1,
> + AB8500_ANAGAIN1, AB8500_ANAGAINX_LOWPOWMICX, enum_dis_ena);
This for example is normally fixed by the physical design and can't
sensibly be varied at runtime.
> + /* Digital interface - AD to slot mapping */
> + SOC_ENUM("Digital Interface AD To Slot 0 Map", soc_enum_adslot0map),
> + SOC_ENUM("Digital Interface AD To Slot 1 Map", soc_enum_adslot1map),
Can you usefully leave these fixed with a default configuration?
There's been some chat about adding a framework feature for this but
it's not there yet - lots of devices have similar features. If not then
this code is fine.
> +static int ab8500_codec_configure_audio_macrocell(struct snd_soc_codec *codec)
> +{
> + u8 value8;
> + unsigned int value;
> + int status;
> +
> + status = ab8500_sysctrl_write(AB8500_STW4500CTRL3,
> + AB8500_STW4500CTRL3_CLK32KOUT2DIS |
> + AB8500_STW4500CTRL3_RESETAUDN,
> + AB8500_STW4500CTRL3_RESETAUDN);
> + if (status < 0)
> + return status;
> +
> + status = abx500_get_register_interruptible(codec->dev, (u8)AB8500_MISC,
> + (u8)AB8500_GPIO_DIR4_REG,
> + &value8);
> + if (status < 0)
> + return status;
> + value = value8 | GPIO27_DIR_OUTPUT | GPIO29_DIR_OUTPUT |
> + GPIO31_DIR_OUTPUT;
> + status |= abx500_set_register_interruptible(codec->dev,
> + (u8)AB8500_MISC,
> + (u8)AB8500_GPIO_DIR4_REG,
> + value);
Still not sure why this isn't platform data.
> + /* Add controls */
> + status = snd_soc_add_codec_controls(codec, ab8500_ctrls,
> + ARRAY_SIZE(ab8500_ctrls));
> + if (status < 0) {
> + dev_err(dev, "%s: failed to add codec-controls (%d).\n",
> + __func__, status);
> + return status;
> + }
At least this one could be done from the driver struct.
> + /* Add DAPM-widgets */
> + status = snd_soc_dapm_new_controls(&codec->dapm, ab8500_dapm_widgets,
> + ARRAY_SIZE(ab8500_dapm_widgets));
> + if (status < 0) {
> + dev_err(codec->dev,
> + "%s: Failed to create DAPM controls (%d).\n",
> + __func__, status);
> + return status;
> + }
This could also be done from the driver struct.
> + status = snd_soc_dapm_add_routes(&codec->dapm, ab8500_dapm_routes,
> + ARRAY_SIZE(ab8500_dapm_routes));
> + if (status < 0) {
> + dev_err(codec->dev, "%s: Failed to add DAPM routes (%d).\n",
> + __func__, status);
> + return status;
> + }
This too.
> + if (IS_ERR(drvdata->clk_ptr_sysclk)) {
> + dev_err(dev,
> + "%s: ERROR: Clocks needed for streaming not available!",
> + __func__);
> + return -ENXIO;
return PTR_ERR().
> + dev_info(&pdev->dev, "%s: Register codec.\n", __func__);
Remove this or downgrade to debug, it's noisy and not adding much
information.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
Url : http://mailman.alsa-project.org/pipermail/alsa-devel/attachments/20120423/84298fb0/attachment.sig
More information about the Alsa-devel
mailing list