[alsa-devel] [PATCH] ASoC: rt5668: add rt5668 codec driver
Mark Brown
broonie at kernel.org
Fri May 13 14:36:41 CEST 2016
On Mon, May 09, 2016 at 06:57:43PM +0800, John Lin wrote:
> +static bool rt5668_volatile_register(struct device *dev, unsigned int reg)
> +{
> + switch (reg) {
> + case 0x0000:
> + case 0x0011:
> + case 0x0082:
I'm not a big fan of all the magic numbers for the registers here, it's
OK if not ideal for the defaults tables since I can understand that
they're probably generated but here it's making things harder to read
and maintain.
> +static void rt5668_enable_push_button_irq(struct snd_soc_codec *codec,
> + bool enable)
> +{
> + struct rt5668_priv *rt5668 = snd_soc_codec_get_drvdata(codec);
This is two separate functions, there's nothing shared between the
enable and disable paths except the private data structure here.
> + if (rt5668->codec_type == CODEC_TYPE_RT5668)
> + snd_soc_update_bits(codec, RT5668_IRQ_3,
> + RT5668_EN_IRQ_INLINE_MASK,
> + RT5668_EN_IRQ_INLINE_NOR);
> + else
> + snd_soc_update_bits(codec, RT5668_IRQ_2,
> + RT5663_EN_IRQ_INLINE_MASK,
> + RT5663_EN_IRQ_INLINE_NOR);
Write this as a switch statement so future variants can be more easily
handled. This is a common pattern in this driver.
> + */
> +
> +static int rt5663_jack_detect(struct snd_soc_codec *codec, int jack_insert)
Extra blank line.
> +{
> + struct rt5668_priv *rt5668 = snd_soc_codec_get_drvdata(codec);
> + int val, i = 0, sleep_time[5] = {300, 150, 100, 50, 30};
> +
> + dev_dbg(codec->dev, "%s jack_insert:%d\n", __func__, jack_insert);
> +
> + if (jack_insert) {
> + while (i < 5) {
> + msleep(sleep_time[i]);
> + val = snd_soc_read(codec, RT5663_EM_JACK_TYPE_2) &
> + 0x0003;
> + i++;
> + if (val == 0x1 || val == 0x2 || val == 0x3)
> + break;
> + dev_dbg(codec->dev, "%s: MX-00e7 val=%x sleep %d\n",
> + __func__, val, sleep_time[i]);
> + }
> + dev_dbg(codec->dev, "%s val = %d\n", __func__, val);
> + switch (val) {
> + case 1:
> + case 2:
This looks like the same code as was in the detection handler, shouldn't
it be shared?
> +int rt5668_button_detect(struct snd_soc_codec *codec)
> +{
> + int btn_type, val;
> +
> + val = snd_soc_read(codec, RT5668_4BTN_IL_CMD_1);
> + dev_dbg(codec->dev, "%s: val=0x%x\n", __func__, val);
> + btn_type = val & 0xfff0;
> + snd_soc_write(codec, RT5668_4BTN_IL_CMD_1, val);
> +
> + return btn_type;
> +}
> +EXPORT_SYMBOL(rt5668_button_detect);
What is this and why is it exported? Note also that all ASoC and regmap
exports are EXPORT_SYMBOL_GPL()...
> +static irqreturn_t rt5668_irq(int irq, void *data)
> +{
> + struct rt5668_priv *rt5668 = data;
> +
> + dev_dbg(rt5668->codec->dev, "%s IRQ queue work\n", __func__);
> +
> + queue_delayed_work(system_wq, &rt5668->jack_detect_work,
> + msecs_to_jiffies(250));
> +
> + return IRQ_HANDLED;
> +}
Given that the interrupt handler just schedules a work item there's no
need for it to be a threaded interrupt, it can just be a normal
interrupt and save the bother of masking the hardware interrupt and
running a thread.
> +int rt5668_set_jack_detect(struct snd_soc_codec *codec,
> + struct snd_soc_jack *hs_jack)
> +{
> + struct rt5668_priv *rt5668 = snd_soc_codec_get_drvdata(codec);
> +
> + rt5668->hs_jack = hs_jack;
> +
> + rt5668_irq(0, rt5668);
> +
> + return 0;
> +}
> +EXPORT_SYMBOL_GPL(rt5668_set_jack_detect);
We don't need to do anything in the hardware to enable jack detection?
> +static int rt5668_set_bclk_ratio(struct snd_soc_dai *dai, unsigned int ratio)
> +{
> + struct snd_soc_codec *codec = dai->codec;
> + struct rt5668_priv *rt5668 = snd_soc_codec_get_drvdata(codec);
> +
> + dev_dbg(codec->dev, "%s ratio = %d\n", __func__, ratio);
> +
> + if (rt5668->codec_type == CODEC_TYPE_RT5663) {
> + switch (ratio) {
No handling for the other CODEC? Should it return an error?
> +static int rt5668_resume(struct snd_soc_codec *codec)
> +{
> + struct rt5668_priv *rt5668 = snd_soc_codec_get_drvdata(codec);
> +
> + regcache_cache_only(rt5668->regmap, false);
> + regcache_sync(rt5668->regmap);
Should check the return code.
> + /* reset and calibrate */
> + regmap_write(rt5668->regmap, RT5668_RESET, 0);
> + regcache_cache_bypass(rt5668->regmap, true);
> + if (rt5668->codec_type == CODEC_TYPE_RT5668)
> + rt5668_calibrate(rt5668);
> + else
> + rt5663_calibrate(rt5668);
> + regcache_cache_bypass(rt5668->regmap, false);
> + regmap_write(rt5668->regmap, RT5668_RESET, 0);
> + dev_dbg(&i2c->dev, "calibrate done\n");
Do we not need to do this on resume?
> + /* BST1 power on for JD */
> + regmap_update_bits(rt5668->regmap, RT5668_PWR_ANLG_2,
> + RT5668_PWR_BST1_MASK, RT5668_PWR_BST1_ON);
> + regmap_update_bits(rt5668->regmap, RT5663_EM_JACK_TYPE_1,
> + RT5663_CBJ_DET_MASK | RT5663_EXT_JD_MASK |
> + RT5663_POL_EXT_JD_MASK, RT5663_CBJ_DET_EN |
> + RT5663_EXT_JD_EN | RT5663_POL_EXT_JD_EN);
I'd expect any enables for jack detection to be done only if the system
is actually using jack detection.
> + /* RECMIX */
> + regmap_update_bits(rt5668->regmap, RT5663_RECMIX,
> + RT5663_RECMIX1_BST1_MASK, RT5663_RECMIX1_BST1_UNMUTE);
> + /* ADCDAT L/L */
> + regmap_update_bits(rt5668->regmap, RT5668_TDM_1,
> + RT5663_DATA_SWAP_ADCDAT1_MASK,
> + RT5663_DATA_SWAP_ADCDAT1_LL);
This looks like routing control?
> + setup_timer(&rt5668->btn_check_timer, rt5668_btn_check_callback,
> + (unsigned long)rt5668);
Does this really need to be running *all* the time?
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 473 bytes
Desc: not available
URL: <http://mailman.alsa-project.org/pipermail/alsa-devel/attachments/20160513/aaa62cde/attachment-0001.sig>
More information about the Alsa-devel
mailing list