[alsa-devel] [PATCH 1/6] soc - wm8753 - Clean up checkpatch warnings
Signed-off-by: Mark Brown broonie@opensource.wolfsonmicro.com --- sound/soc/codecs/wm8753.c | 34 ++++++++++++++++++---------------- 1 files changed, 18 insertions(+), 16 deletions(-)
diff --git a/sound/soc/codecs/wm8753.c b/sound/soc/codecs/wm8753.c index 76a5c7b..fb41826 100644 --- a/sound/soc/codecs/wm8753.c +++ b/sound/soc/codecs/wm8753.c @@ -150,7 +150,7 @@ static int wm8753_write(struct snd_soc_codec *codec, unsigned int reg, data[0] = (reg << 1) | ((value >> 8) & 0x0001); data[1] = value & 0x00ff;
- wm8753_write_reg_cache (codec, reg, value); + wm8753_write_reg_cache(codec, reg, value); if (codec->hw_write(codec->control_data, data, 2) == 2) return 0; else @@ -249,7 +249,7 @@ static int wm8753_set_dai(struct snd_kcontrol *kcontrol, struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); int mode = wm8753_read_reg_cache(codec, WM8753_IOCTL);
- if (((mode &0xc) >> 2) == ucontrol->value.integer.value[0]) + if (((mode & 0xc) >> 2) == ucontrol->value.integer.value[0]) return 0;
mode &= 0xfff3; @@ -342,7 +342,8 @@ static int wm8753_add_controls(struct snd_soc_codec *codec)
for (i = 0; i < ARRAY_SIZE(wm8753_snd_controls); i++) { err = snd_ctl_add(codec->card, - snd_soc_cnew(&wm8753_snd_controls[i],codec, NULL)); + snd_soc_cnew(&wm8753_snd_controls[i], + codec, NULL)); if (err < 0) return err; } @@ -722,7 +723,7 @@ static void pll_factors(struct _pll_div *pll_div, unsigned int target,
if ((Ndiv < 6) || (Ndiv > 12)) printk(KERN_WARNING - "WM8753 N value outwith recommended range! N = %d\n",Ndiv); + "wm8753: unsupported N = %d\n", Ndiv);
pll_div->n = Ndiv; Nmod = target % source; @@ -1300,8 +1301,9 @@ static int wm8753_dapm_event(struct snd_soc_codec *codec, int event) }
#define WM8753_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\ - SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_44100 | \ - SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000) + SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 |\ + SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |\ + SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000)
#define WM8753_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ SNDRV_PCM_FMTBIT_S24_LE) @@ -1507,9 +1509,9 @@ static int wm8753_suspend(struct platform_device *pdev, pm_message_t state) struct snd_soc_codec *codec = socdev->codec;
/* we only need to suspend if we are a valid card */ - if(!codec->card) + if (!codec->card) return 0; - + wm8753_dapm_event(codec, SNDRV_CTL_POWER_D3cold); return 0; } @@ -1523,7 +1525,7 @@ static int wm8753_resume(struct platform_device *pdev) u16 *cache = codec->reg_cache;
/* we only need to resume if we are a valid card */ - if(!codec->card) + if (!codec->card) return 0;
/* Sync reg_cache with the hardware */ @@ -1613,9 +1615,10 @@ static int wm8753_init(struct snd_soc_device *socdev) wm8753_add_widgets(codec); ret = snd_soc_register_card(socdev); if (ret < 0) { - printk(KERN_ERR "wm8753: failed to register card\n"); + printk(KERN_ERR "wm8753: failed to register card\n"); goto card_err; - } + } + return ret;
card_err: @@ -1630,7 +1633,7 @@ pcm_err: around */ static struct snd_soc_device *wm8753_socdev;
-#if defined (CONFIG_I2C) || defined (CONFIG_I2C_MODULE) +#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
/* * WM8753 2 wire address is determined by GPIO5 @@ -1661,7 +1664,7 @@ static int wm8753_codec_probe(struct i2c_adapter *adap, int addr, int kind) client_template.addr = addr;
i2c = kmemdup(&client_template, sizeof(client_template), GFP_KERNEL); - if (i2c == NULL){ + if (!i2c) { kfree(codec); return -ENOMEM; } @@ -1749,7 +1752,7 @@ static int wm8753_probe(struct platform_device *pdev) wm8753_socdev = socdev; INIT_DELAYED_WORK(&codec->delayed_work, wm8753_work);
-#if defined (CONFIG_I2C) || defined (CONFIG_I2C_MODULE) +#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) if (setup->i2c_address) { normal_i2c[0] = setup->i2c_address; codec->hw_write = (hw_write_t)i2c_master_send; @@ -1793,7 +1796,7 @@ static int wm8753_remove(struct platform_device *pdev) run_delayed_work(&codec->delayed_work); snd_soc_free_pcms(socdev); snd_soc_dapm_free(socdev); -#if defined (CONFIG_I2C) || defined (CONFIG_I2C_MODULE) +#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) i2c_del_driver(&wm8753_i2c_driver); #endif kfree(codec->private_data); @@ -1808,7 +1811,6 @@ struct snd_soc_codec_device soc_codec_dev_wm8753 = { .suspend = wm8753_suspend, .resume = wm8753_resume, }; - EXPORT_SYMBOL_GPL(soc_codec_dev_wm8753);
MODULE_DESCRIPTION("ASoC WM8753 driver");
Signed-off-by: Mark Brown broonie@opensource.wolfsonmicro.com --- sound/soc/s3c24xx/s3c2443-ac97.c | 9 ++++----- 1 files changed, 4 insertions(+), 5 deletions(-)
diff --git a/sound/soc/s3c24xx/s3c2443-ac97.c b/sound/soc/s3c24xx/s3c2443-ac97.c index 1c1ddbf..e81d9a6 100644 --- a/sound/soc/s3c24xx/s3c2443-ac97.c +++ b/sound/soc/s3c24xx/s3c2443-ac97.c @@ -19,6 +19,7 @@ #include <linux/module.h> #include <linux/platform_device.h> #include <linux/interrupt.h> +#include <linux/io.h> #include <linux/wait.h> #include <linux/delay.h> #include <linux/clk.h> @@ -30,7 +31,6 @@ #include <sound/soc.h>
#include <asm/hardware.h> -#include <asm/io.h> #include <asm/plat-s3c/regs-ac97.h> #include <asm/arch/regs-gpio.h> #include <asm/arch/regs-clock.h> @@ -47,7 +47,7 @@ struct s3c24xx_ac97_info { }; static struct s3c24xx_ac97_info s3c24xx_ac97;
-DECLARE_COMPLETION(ac97_completion); +static DECLARE_COMPLETION(ac97_completion); static u32 codec_ready; static DECLARE_MUTEX(ac97_mutex);
@@ -290,7 +290,7 @@ static int s3c2443_ac97_trigger(struct snd_pcm_substream *substream, int cmd) u32 ac_glbctrl;
ac_glbctrl = readl(s3c24xx_ac97.regs + S3C_AC97_GLBCTRL); - switch(cmd) { + switch (cmd) { case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_RESUME: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: @@ -333,7 +333,7 @@ static int s3c2443_ac97_mic_trigger(struct snd_pcm_substream *substream, u32 ac_glbctrl;
ac_glbctrl = readl(s3c24xx_ac97.regs + S3C_AC97_GLBCTRL); - switch(cmd) { + switch (cmd) { case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_RESUME: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: @@ -391,7 +391,6 @@ struct snd_soc_cpu_dai s3c2443_ac97_dai[] = { .trigger = s3c2443_ac97_mic_trigger,}, }, }; - EXPORT_SYMBOL_GPL(s3c2443_ac97_dai); EXPORT_SYMBOL_GPL(soc_ac97_ops);
Signed-off-by: Mark Brown broonie@opensource.wolfsonmicro.com --- sound/soc/s3c24xx/s3c24xx-pcm.c | 33 ++++++++++++++++----------------- 1 files changed, 16 insertions(+), 17 deletions(-)
diff --git a/sound/soc/s3c24xx/s3c24xx-pcm.c b/sound/soc/s3c24xx/s3c24xx-pcm.c index 49580fb..6c70a81 100644 --- a/sound/soc/s3c24xx/s3c24xx-pcm.c +++ b/sound/soc/s3c24xx/s3c24xx-pcm.c @@ -20,6 +20,7 @@
#include <linux/module.h> #include <linux/init.h> +#include <linux/io.h> #include <linux/platform_device.h> #include <linux/slab.h> #include <linux/dma-mapping.h> @@ -30,7 +31,6 @@ #include <sound/soc.h>
#include <asm/dma.h> -#include <asm/io.h> #include <asm/hardware.h> #include <asm/arch/dma.h> #include <asm/arch/audio.h> @@ -93,7 +93,7 @@ static void s3c24xx_pcm_enqueue(struct snd_pcm_substream *substream) while (prtd->dma_loaded < prtd->dma_limit) { unsigned long len = prtd->dma_period;
- DBG("dma_loaded: %d\n",prtd->dma_loaded); + DBG("dma_loaded: %d\n", prtd->dma_loaded);
if ((pos + len) > prtd->dma_end) { len = prtd->dma_end - pos; @@ -101,7 +101,7 @@ static void s3c24xx_pcm_enqueue(struct snd_pcm_substream *substream) __func__, len); }
- ret = s3c2410_dma_enqueue(prtd->params->channel, + ret = s3c2410_dma_enqueue(prtd->params->channel, substream, pos, len);
if (ret == 0) { @@ -129,7 +129,7 @@ static void s3c24xx_audio_buffdone(struct s3c2410_dma_chan *channel, return;
prtd = substream->runtime->private_data; - + if (substream) snd_pcm_period_elapsed(substream);
@@ -150,7 +150,7 @@ static int s3c24xx_pcm_hw_params(struct snd_pcm_substream *substream, struct snd_soc_pcm_runtime *rtd = substream->private_data; struct s3c24xx_pcm_dma_params *dma = rtd->dai->cpu_dai->dma_data; unsigned long totbytes = params_buffer_bytes(params); - int ret=0; + int ret = 0;
DBG("Entered %s\n", __func__);
@@ -223,7 +223,7 @@ static int s3c24xx_pcm_prepare(struct snd_pcm_substream *substream) /* return if this is a bufferless transfer e.g. * codec <--> BT codec or GSM modem -- lg FIXME */ if (!prtd->params) - return 0; + return 0;
/* channel needs configuring for mem=>device, increment memory addr, * sync to pclk, half-word transfers to the IIS-FIFO. */ @@ -293,8 +293,8 @@ static int s3c24xx_pcm_trigger(struct snd_pcm_substream *substream, int cmd) return ret; }
-static snd_pcm_uframes_t - s3c24xx_pcm_pointer(struct snd_pcm_substream *substream) +static snd_pcm_uframes_t +s3c24xx_pcm_pointer(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; struct s3c24xx_runtime_data *prtd = runtime->private_data; @@ -313,7 +313,7 @@ static snd_pcm_uframes_t
spin_unlock(&prtd->lock);
- DBG("Pointer %x %x\n",src,dst); + DBG("Pointer %x %x\n", src, dst);
/* we seem to be getting the odd error from the pcm library due * to out-of-bounds pointers. this is maybe due to the dma engine @@ -355,11 +355,11 @@ static int s3c24xx_pcm_close(struct snd_pcm_substream *substream)
DBG("Entered %s\n", __func__);
- if (prtd) - kfree(prtd); - else + if (!prtd) DBG("s3c24xx_pcm_close called with prtd == NULL\n");
+ kfree(prtd); + return 0; }
@@ -371,9 +371,9 @@ static int s3c24xx_pcm_mmap(struct snd_pcm_substream *substream, DBG("Entered %s\n", __func__);
return dma_mmap_writecombine(substream->pcm->card->dev, vma, - runtime->dma_area, - runtime->dma_addr, - runtime->dma_bytes); + runtime->dma_area, + runtime->dma_addr, + runtime->dma_bytes); }
static struct snd_pcm_ops s3c24xx_pcm_ops = { @@ -432,7 +432,7 @@ static void s3c24xx_pcm_free_dma_buffers(struct snd_pcm *pcm)
static u64 s3c24xx_pcm_dmamask = DMA_32BIT_MASK;
-static int s3c24xx_pcm_new(struct snd_card *card, +static int s3c24xx_pcm_new(struct snd_card *card, struct snd_soc_codec_dai *dai, struct snd_pcm *pcm) { int ret = 0; @@ -467,7 +467,6 @@ struct snd_soc_platform s3c24xx_soc_platform = { .pcm_new = s3c24xx_pcm_new, .pcm_free = s3c24xx_pcm_free_dma_buffers, }; - EXPORT_SYMBOL_GPL(s3c24xx_soc_platform);
MODULE_AUTHOR("Ben Dooks, ben@simtec.co.uk");
Signed-off-by: Mark Brown broonie@opensource.wolfsonmicro.com --- sound/soc/s3c24xx/ln2440sbc_alc650.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/sound/soc/s3c24xx/ln2440sbc_alc650.c b/sound/soc/s3c24xx/ln2440sbc_alc650.c index 9ed8f2e..4eab2c1 100644 --- a/sound/soc/s3c24xx/ln2440sbc_alc650.c +++ b/sound/soc/s3c24xx/ln2440sbc_alc650.c @@ -1,10 +1,10 @@ /* * SoC audio for ln2440sbc - * + * * Copyright 2007 KonekTel, a.s. * Author: Ivan Kuten * ivan.kuten@promwad.com - * + * * Heavily based on smdk2443_wm9710.c * Copyright 2007 Wolfson Microelectronics PLC. * Author: Graeme Gregory
From: Daniel Mack daniel@caiaq.org
This patch cleans up the clocking setup for aic3x codecs. It drops the dividers table and determines the PLL control values programatically. Under certain conditions, the PLL is disabled entirely which could save some power.
Signed-off-by: Daniel Mack daniel@caiaq.de Acked-by: Jarkko Nikula jarkko.nikula@nokia.com Signed-off-by: Mark Brown broonie@opensource.wolfsonmicro.com --- sound/soc/codecs/tlv320aic3x.c | 225 ++++++++++++++++------------------------ sound/soc/codecs/tlv320aic3x.h | 4 + 2 files changed, 95 insertions(+), 134 deletions(-)
diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c index 630684f..d76fa35 100644 --- a/sound/soc/codecs/tlv320aic3x.c +++ b/sound/soc/codecs/tlv320aic3x.c @@ -49,7 +49,7 @@ #include "tlv320aic3x.h"
#define AUDIO_NAME "aic3x" -#define AIC3X_VERSION "0.1" +#define AIC3X_VERSION "0.2"
/* codec private data */ struct aic3x_priv { @@ -648,81 +648,6 @@ static int aic3x_add_widgets(struct snd_soc_codec *codec) return 0; }
-struct aic3x_rate_divs { - u32 mclk; - u32 rate; - u32 fsref_reg; - u8 sr_reg:4; - u8 pllj_reg; - u16 plld_reg; -}; - -/* AIC3X codec mclk clock divider coefficients */ -static const struct aic3x_rate_divs aic3x_divs[] = { - /* 8k */ - {12000000, 8000, 48000, 0xa, 16, 3840}, - {19200000, 8000, 48000, 0xa, 10, 2400}, - {22579200, 8000, 48000, 0xa, 8, 7075}, - {33868800, 8000, 48000, 0xa, 5, 8049}, - /* 11.025k */ - {12000000, 11025, 44100, 0x6, 15, 528}, - {19200000, 11025, 44100, 0x6, 9, 4080}, - {22579200, 11025, 44100, 0x6, 8, 0}, - {33868800, 11025, 44100, 0x6, 5, 3333}, - /* 16k */ - {12000000, 16000, 48000, 0x4, 16, 3840}, - {19200000, 16000, 48000, 0x4, 10, 2400}, - {22579200, 16000, 48000, 0x4, 8, 7075}, - {33868800, 16000, 48000, 0x4, 5, 8049}, - /* 22.05k */ - {12000000, 22050, 44100, 0x2, 15, 528}, - {19200000, 22050, 44100, 0x2, 9, 4080}, - {22579200, 22050, 44100, 0x2, 8, 0}, - {33868800, 22050, 44100, 0x2, 5, 3333}, - /* 32k */ - {12000000, 32000, 48000, 0x1, 16, 3840}, - {19200000, 32000, 48000, 0x1, 10, 2400}, - {22579200, 32000, 48000, 0x1, 8, 7075}, - {33868800, 32000, 48000, 0x1, 5, 8049}, - /* 44.1k */ - {12000000, 44100, 44100, 0x0, 15, 528}, - {19200000, 44100, 44100, 0x0, 9, 4080}, - {22579200, 44100, 44100, 0x0, 8, 0}, - {33868800, 44100, 44100, 0x0, 5, 3333}, - /* 48k */ - {12000000, 48000, 48000, 0x0, 16, 3840}, - {19200000, 48000, 48000, 0x0, 10, 2400}, - {22579200, 48000, 48000, 0x0, 8, 7075}, - {33868800, 48000, 48000, 0x0, 5, 8049}, - /* 64k */ - {12000000, 64000, 96000, 0x1, 16, 3840}, - {19200000, 64000, 96000, 0x1, 10, 2400}, - {22579200, 64000, 96000, 0x1, 8, 7075}, - {33868800, 64000, 96000, 0x1, 5, 8049}, - /* 88.2k */ - {12000000, 88200, 88200, 0x0, 15, 528}, - {19200000, 88200, 88200, 0x0, 9, 4080}, - {22579200, 88200, 88200, 0x0, 8, 0}, - {33868800, 88200, 88200, 0x0, 5, 3333}, - /* 96k */ - {12000000, 96000, 96000, 0x0, 16, 3840}, - {19200000, 96000, 96000, 0x0, 10, 2400}, - {22579200, 96000, 96000, 0x0, 8, 7075}, - {33868800, 96000, 96000, 0x0, 5, 8049}, -}; - -static inline int aic3x_get_divs(int mclk, int rate) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(aic3x_divs); i++) { - if (aic3x_divs[i].rate == rate && aic3x_divs[i].mclk == mclk) - return i; - } - - return 0; -} - static int aic3x_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { @@ -730,49 +655,107 @@ static int aic3x_hw_params(struct snd_pcm_substream *substream, struct snd_soc_device *socdev = rtd->socdev; struct snd_soc_codec *codec = socdev->codec; struct aic3x_priv *aic3x = codec->private_data; - int i; - u8 data, pll_p, pll_r, pll_j; - u16 pll_d; - - i = aic3x_get_divs(aic3x->sysclk, params_rate(params)); + int codec_clk = 0, bypass_pll = 0, fsref, last_clk = 0; + u8 data, r, p, pll_q, pll_p = 1, pll_r = 1, pll_j = 1; + u16 pll_d = 1;
- /* Route Left DAC to left channel input and - * right DAC to right channel input */ - data = (LDAC2LCH | RDAC2RCH); - switch (aic3x_divs[i].fsref_reg) { - case 44100: - data |= FSREF_44100; + /* select data word length */ + data = + aic3x_read_reg_cache(codec, AIC3X_ASD_INTF_CTRLB) & (~(0x3 << 4)); + switch (params_format(params)) { + case SNDRV_PCM_FORMAT_S16_LE: break; - case 48000: - data |= FSREF_48000; + case SNDRV_PCM_FORMAT_S20_3LE: + data |= (0x01 << 4); break; - case 88200: - data |= FSREF_44100 | DUAL_RATE_MODE; + case SNDRV_PCM_FORMAT_S24_LE: + data |= (0x02 << 4); break; - case 96000: - data |= FSREF_48000 | DUAL_RATE_MODE; + case SNDRV_PCM_FORMAT_S32_LE: + data |= (0x03 << 4); break; } + aic3x_write(codec, AIC3X_ASD_INTF_CTRLB, data); + + /* Fsref can be 44100 or 48000 */ + fsref = (params_rate(params) % 11025 == 0) ? 44100 : 48000; + + /* Try to find a value for Q which allows us to bypass the PLL and + * generate CODEC_CLK directly. */ + for (pll_q = 2; pll_q < 18; pll_q++) + if (aic3x->sysclk / (128 * pll_q) == fsref) { + bypass_pll = 1; + break; + } + + if (bypass_pll) { + pll_q &= 0xf; + aic3x_write(codec, AIC3X_PLL_PROGA_REG, pll_q << PLLQ_SHIFT); + aic3x_write(codec, AIC3X_GPIOB_REG, CODEC_CLKIN_CLKDIV); + } else + aic3x_write(codec, AIC3X_GPIOB_REG, CODEC_CLKIN_PLLDIV); + + /* Route Left DAC to left channel input and + * right DAC to right channel input */ + data = (LDAC2LCH | RDAC2RCH); + data |= (fsref == 44100) ? FSREF_44100 : FSREF_48000; + if (params_rate(params) >= 64000) + data |= DUAL_RATE_MODE; aic3x_write(codec, AIC3X_CODEC_DATAPATH_REG, data);
/* codec sample rate select */ - data = aic3x_divs[i].sr_reg; + data = (fsref * 20) / params_rate(params); + if (params_rate(params) < 64000) + data /= 2; + data /= 5; + data -= 2; data |= (data << 4); aic3x_write(codec, AIC3X_SAMPLE_RATE_SEL_REG, data);
- /* Use PLL for generation Fsref by equation: - * Fsref = (MCLK * K * R)/(2048 * P); - * Fix P = 2 and R = 1 and calculate K, if - * K = J.D, i.e. J - an interger portion of K and D is the fractional - * one with 4 digits of precision; - * Example: - * For MCLK = 22.5792 MHz and Fsref = 48kHz: - * Select P = 2, R= 1, K = 8.7074, which results in J = 8, D = 7074 + if (bypass_pll) + return 0; + + /* Use PLL + * find an apropriate setup for j, d, r and p by iterating over + * p and r - j and d are calculated for each fraction. + * Up to 128 values are probed, the closest one wins the game. + * The sysclk is divided by 1000 to prevent integer overflows. */ - pll_p = 2; - pll_r = 1; - pll_j = aic3x_divs[i].pllj_reg; - pll_d = aic3x_divs[i].plld_reg; + codec_clk = (2048 * fsref) / (aic3x->sysclk / 1000); + + for (r = 1; r <= 16; r++) + for (p = 1; p <= 8; p++) { + int clk, tmp = (codec_clk * pll_r * 10) / pll_p; + u8 j = tmp / 10000; + u16 d = tmp % 10000; + + if (j > 63) + continue; + + if (d != 0 && aic3x->sysclk < 10000000) + continue; + + /* This is actually 1000 * ((j + (d/10000)) * r) / p + * The term had to be converted to get rid of the + * division by 10000 */ + clk = ((10000 * j * r) + (d * r)) / (10 * p); + + /* check whether this values get closer than the best + * ones we had before */ + if (abs(codec_clk - clk) < abs(codec_clk - last_clk)) { + pll_j = j; pll_d = d; pll_r = r; pll_p = p; + last_clk = clk; + } + + /* Early exit for exact matches */ + if (clk == codec_clk) + break; + } + + if (last_clk == 0) { + printk(KERN_ERR "%s(): unable to setup PLL\n", __func__); + return -EINVAL; + }
data = aic3x_read_reg_cache(codec, AIC3X_PLL_PROGA_REG); aic3x_write(codec, AIC3X_PLL_PROGA_REG, data | (pll_p << PLLP_SHIFT)); @@ -782,24 +765,6 @@ static int aic3x_hw_params(struct snd_pcm_substream *substream, aic3x_write(codec, AIC3X_PLL_PROGD_REG, (pll_d & 0x3F) << PLLD_LSB_SHIFT);
- /* select data word length */ - data = - aic3x_read_reg_cache(codec, AIC3X_ASD_INTF_CTRLB) & (~(0x3 << 4)); - switch (params_format(params)) { - case SNDRV_PCM_FORMAT_S16_LE: - break; - case SNDRV_PCM_FORMAT_S20_3LE: - data |= (0x01 << 4); - break; - case SNDRV_PCM_FORMAT_S24_LE: - data |= (0x02 << 4); - break; - case SNDRV_PCM_FORMAT_S32_LE: - data |= (0x03 << 4); - break; - } - aic3x_write(codec, AIC3X_ASD_INTF_CTRLB, data); - return 0; }
@@ -826,16 +791,8 @@ static int aic3x_set_dai_sysclk(struct snd_soc_codec_dai *codec_dai, struct snd_soc_codec *codec = codec_dai->codec; struct aic3x_priv *aic3x = codec->private_data;
- switch (freq) { - case 12000000: - case 19200000: - case 22579200: - case 33868800: - aic3x->sysclk = freq; - return 0; - } - - return -EINVAL; + aic3x->sysclk = freq; + return 0; }
static int aic3x_set_dai_fmt(struct snd_soc_codec_dai *codec_dai, diff --git a/sound/soc/codecs/tlv320aic3x.h b/sound/soc/codecs/tlv320aic3x.h index d0cdeeb..d49d001 100644 --- a/sound/soc/codecs/tlv320aic3x.h +++ b/sound/soc/codecs/tlv320aic3x.h @@ -109,6 +109,7 @@ #define LLOPM_CTRL 86 #define RLOPM_CTRL 93 /* Clock generation control register */ +#define AIC3X_GPIOB_REG 101 #define AIC3X_CLKGEN_CTRL_REG 102
/* Page select register bits */ @@ -128,12 +129,15 @@
/* PLL registers bitfields */ #define PLLP_SHIFT 0 +#define PLLQ_SHIFT 3 #define PLLR_SHIFT 0 #define PLLJ_SHIFT 2 #define PLLD_MSB_SHIFT 0 #define PLLD_LSB_SHIFT 2
/* Clock generation register bits */ +#define CODEC_CLKIN_PLLDIV 0 +#define CODEC_CLKIN_CLKDIV 1 #define PLL_CLKIN_SHIFT 4 #define MCLK_SOURCE 0x0 #define PLL_CLKDIV_SHIFT 0
From: Daniel Mack daniel@caiaq.org
This patch adds support for AIC3x GPIO lines. They can be configured for many possible functions as well as be driven manually. I also introduced i2c read functionality since the GPIO state register has to be read from hardware every time and can not be served from cache.
Signed-off-by: Daniel Mack daniel@caiaq.de Signed-off-by: Mark Brown broonie@opensource.wolfsonmicro.com --- sound/soc/codecs/tlv320aic3x.c | 53 ++++++++++++++++++++++++++++++++++++++++ sound/soc/codecs/tlv320aic3x.h | 49 ++++++++++++++++++++++++++++++++++++- 2 files changed, 101 insertions(+), 1 deletions(-)
diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c index d76fa35..6e4bc69 100644 --- a/sound/soc/codecs/tlv320aic3x.c +++ b/sound/soc/codecs/tlv320aic3x.c @@ -138,6 +138,20 @@ static int aic3x_write(struct snd_soc_codec *codec, unsigned int reg, return -EIO; }
+/* + * read from the aic3x register space + */ +static int aic3x_read(struct snd_soc_codec *codec, unsigned int reg, + u8 *value) +{ + *value = reg & 0xff; + if (codec->hw_read(codec->control_data, value, 1) != 1) + return -EIO; + + aic3x_write_reg_cache(codec, reg, *value); + return 0; +} + #define SOC_DAPM_SINGLE_AIC3X(xname, reg, shift, mask, invert) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ .info = snd_soc_info_volsw, \ @@ -911,6 +925,33 @@ static int aic3x_dapm_event(struct snd_soc_codec *codec, int event) return 0; }
+void aic3x_set_gpio(struct snd_soc_codec *codec, int gpio, int state) +{ + u8 reg = gpio ? AIC3X_GPIO2_REG : AIC3X_GPIO1_REG; + u8 bit = gpio ? 3: 0; + u8 val = aic3x_read_reg_cache(codec, reg) & ~(1 << bit); + aic3x_write(codec, reg, val | (!!state << bit)); +} +EXPORT_SYMBOL_GPL(aic3x_set_gpio); + +int aic3x_get_gpio(struct snd_soc_codec *codec, int gpio) +{ + u8 reg = gpio ? AIC3X_GPIO2_REG : AIC3X_GPIO1_REG; + u8 val, bit = gpio ? 2: 1; + + aic3x_read(codec, reg, &val); + return (val >> bit) & 1; +} +EXPORT_SYMBOL_GPL(aic3x_get_gpio); + +int aic3x_headset_detected(struct snd_soc_codec *codec) +{ + u8 val; + aic3x_read(codec, AIC3X_RT_IRQ_FLAGS_REG, &val); + return (val >> 2) & 1; +} +EXPORT_SYMBOL_GPL(aic3x_headset_detected); + #define AIC3X_RATES SNDRV_PCM_RATE_8000_96000 #define AIC3X_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE) @@ -977,6 +1018,7 @@ static int aic3x_resume(struct platform_device *pdev) static int aic3x_init(struct snd_soc_device *socdev) { struct snd_soc_codec *codec = socdev->codec; + struct aic3x_setup_data *setup = socdev->codec_data; int reg, ret = 0;
codec->name = "aic3x"; @@ -1067,6 +1109,10 @@ static int aic3x_init(struct snd_soc_device *socdev) /* off, with power on */ aic3x_dapm_event(codec, SNDRV_CTL_POWER_D3hot);
+ /* setup GPIO functions */ + aic3x_write(codec, AIC3X_GPIO1_REG, (setup->gpio_func[0] & 0xf) << 4); + aic3x_write(codec, AIC3X_GPIO2_REG, (setup->gpio_func[1] & 0xf) << 4); + aic3x_add_controls(codec); aic3x_add_widgets(codec); ret = snd_soc_register_card(socdev); @@ -1174,6 +1220,12 @@ static struct i2c_client client_template = { .name = "AIC3X", .driver = &aic3x_i2c_driver, }; + +static int aic3x_i2c_read(struct i2c_client *client, u8 *value, int len) +{ + value[0] = i2c_smbus_read_byte_data(client, value[0]); + return (len == 1); +} #endif
static int aic3x_probe(struct platform_device *pdev) @@ -1208,6 +1260,7 @@ static int aic3x_probe(struct platform_device *pdev) if (setup->i2c_address) { normal_i2c[0] = setup->i2c_address; codec->hw_write = (hw_write_t) i2c_master_send; + codec->hw_read = (hw_read_t) aic3x_i2c_read; ret = i2c_add_driver(&aic3x_i2c_driver); if (ret != 0) printk(KERN_ERR "can't add i2c driver"); diff --git a/sound/soc/codecs/tlv320aic3x.h b/sound/soc/codecs/tlv320aic3x.h index d49d001..c1dd1ac 100644 --- a/sound/soc/codecs/tlv320aic3x.h +++ b/sound/soc/codecs/tlv320aic3x.h @@ -108,8 +108,14 @@ #define DACR1_2_RLOPM_VOL 92 #define LLOPM_CTRL 86 #define RLOPM_CTRL 93 -/* Clock generation control register */ +/* GPIO/IRQ registers */ +#define AIC3X_STICKY_IRQ_FLAGS_REG 96 +#define AIC3X_RT_IRQ_FLAGS_REG 97 +#define AIC3X_GPIO1_REG 98 +#define AIC3X_GPIO2_REG 99 +#define AIC3X_GPIOA_REG 100 #define AIC3X_GPIOB_REG 101 +/* Clock generation control register */ #define AIC3X_CLKGEN_CTRL_REG 102
/* Page select register bits */ @@ -175,8 +181,49 @@ /* Default input volume */ #define DEFAULT_GAIN 0x20
+/* GPIO API */ +enum { + AIC3X_GPIO1_FUNC_DISABLED = 0, + AIC3X_GPIO1_FUNC_AUDIO_WORDCLK_ADC = 1, + AIC3X_GPIO1_FUNC_CLOCK_MUX = 2, + AIC3X_GPIO1_FUNC_CLOCK_MUX_DIV2 = 3, + AIC3X_GPIO1_FUNC_CLOCK_MUX_DIV4 = 4, + AIC3X_GPIO1_FUNC_CLOCK_MUX_DIV8 = 5, + AIC3X_GPIO1_FUNC_SHORT_CIRCUIT_IRQ = 6, + AIC3X_GPIO1_FUNC_AGC_NOISE_IRQ = 7, + AIC3X_GPIO1_FUNC_INPUT = 8, + AIC3X_GPIO1_FUNC_OUTPUT = 9, + AIC3X_GPIO1_FUNC_DIGITAL_MIC_MODCLK = 10, + AIC3X_GPIO1_FUNC_AUDIO_WORDCLK = 11, + AIC3X_GPIO1_FUNC_BUTTON_IRQ = 12, + AIC3X_GPIO1_FUNC_HEADSET_DETECT_IRQ = 13, + AIC3X_GPIO1_FUNC_HEADSET_DETECT_OR_BUTTON_IRQ = 14, + AIC3X_GPIO1_FUNC_ALL_IRQ = 16 +}; + +enum { + AIC3X_GPIO2_FUNC_DISABLED = 0, + AIC3X_GPIO2_FUNC_HEADSET_DETECT_IRQ = 2, + AIC3X_GPIO2_FUNC_INPUT = 3, + AIC3X_GPIO2_FUNC_OUTPUT = 4, + AIC3X_GPIO2_FUNC_DIGITAL_MIC_INPUT = 5, + AIC3X_GPIO2_FUNC_AUDIO_BITCLK = 8, + AIC3X_GPIO2_FUNC_HEADSET_DETECT_OR_BUTTON_IRQ = 9, + AIC3X_GPIO2_FUNC_ALL_IRQ = 10, + AIC3X_GPIO2_FUNC_SHORT_CIRCUIT_OR_AGC_IRQ = 11, + AIC3X_GPIO2_FUNC_HEADSET_OR_BUTTON_PRESS_OR_SHORT_CIRCUIT_IRQ = 12, + AIC3X_GPIO2_FUNC_SHORT_CIRCUIT_IRQ = 13, + AIC3X_GPIO2_FUNC_AGC_NOISE_IRQ = 14, + AIC3X_GPIO2_FUNC_BUTTON_PRESS_IRQ = 15 +}; + +void aic3x_set_gpio(struct snd_soc_codec *codec, int gpio, int state); +int aic3x_get_gpio(struct snd_soc_codec *codec, int gpio); +int aic3x_headset_detected(struct snd_soc_codec *codec); + struct aic3x_setup_data { unsigned short i2c_address; + unsigned int gpio_func[2]; };
extern struct snd_soc_codec_dai aic3x_dai;
At Wed, 30 Apr 2008 10:10:14 +0100, Mark Brown wrote:
Signed-off-by: Mark Brown broonie@opensource.wolfsonmicro.com
Thanks, all applied now.
Takashi
sound/soc/codecs/wm8753.c | 34 ++++++++++++++++++---------------- 1 files changed, 18 insertions(+), 16 deletions(-)
diff --git a/sound/soc/codecs/wm8753.c b/sound/soc/codecs/wm8753.c index 76a5c7b..fb41826 100644 --- a/sound/soc/codecs/wm8753.c +++ b/sound/soc/codecs/wm8753.c @@ -150,7 +150,7 @@ static int wm8753_write(struct snd_soc_codec *codec, unsigned int reg, data[0] = (reg << 1) | ((value >> 8) & 0x0001); data[1] = value & 0x00ff;
- wm8753_write_reg_cache (codec, reg, value);
- wm8753_write_reg_cache(codec, reg, value); if (codec->hw_write(codec->control_data, data, 2) == 2) return 0; else
@@ -249,7 +249,7 @@ static int wm8753_set_dai(struct snd_kcontrol *kcontrol, struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); int mode = wm8753_read_reg_cache(codec, WM8753_IOCTL);
- if (((mode &0xc) >> 2) == ucontrol->value.integer.value[0])
if (((mode & 0xc) >> 2) == ucontrol->value.integer.value[0]) return 0;
mode &= 0xfff3;
@@ -342,7 +342,8 @@ static int wm8753_add_controls(struct snd_soc_codec *codec)
for (i = 0; i < ARRAY_SIZE(wm8753_snd_controls); i++) { err = snd_ctl_add(codec->card,
snd_soc_cnew(&wm8753_snd_controls[i],codec, NULL));
snd_soc_cnew(&wm8753_snd_controls[i],
if (err < 0) return err; }codec, NULL));
@@ -722,7 +723,7 @@ static void pll_factors(struct _pll_div *pll_div, unsigned int target,
if ((Ndiv < 6) || (Ndiv > 12)) printk(KERN_WARNING
"WM8753 N value outwith recommended range! N = %d\n",Ndiv);
"wm8753: unsupported N = %d\n", Ndiv);
pll_div->n = Ndiv; Nmod = target % source;
@@ -1300,8 +1301,9 @@ static int wm8753_dapm_event(struct snd_soc_codec *codec, int event) }
#define WM8753_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\
SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_44100 | \
SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000)
SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 |\
SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |\
SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000)
#define WM8753_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ SNDRV_PCM_FMTBIT_S24_LE) @@ -1507,9 +1509,9 @@ static int wm8753_suspend(struct platform_device *pdev, pm_message_t state) struct snd_soc_codec *codec = socdev->codec;
/* we only need to suspend if we are a valid card */
- if(!codec->card)
- if (!codec->card) return 0;
- wm8753_dapm_event(codec, SNDRV_CTL_POWER_D3cold); return 0;
} @@ -1523,7 +1525,7 @@ static int wm8753_resume(struct platform_device *pdev) u16 *cache = codec->reg_cache;
/* we only need to resume if we are a valid card */
- if(!codec->card)
if (!codec->card) return 0;
/* Sync reg_cache with the hardware */
@@ -1613,9 +1615,10 @@ static int wm8753_init(struct snd_soc_device *socdev) wm8753_add_widgets(codec); ret = snd_soc_register_card(socdev); if (ret < 0) {
printk(KERN_ERR "wm8753: failed to register card\n");
goto card_err;printk(KERN_ERR "wm8753: failed to register card\n");
- }
- }
- return ret;
card_err: @@ -1630,7 +1633,7 @@ pcm_err: around */ static struct snd_soc_device *wm8753_socdev;
-#if defined (CONFIG_I2C) || defined (CONFIG_I2C_MODULE) +#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
/*
- WM8753 2 wire address is determined by GPIO5
@@ -1661,7 +1664,7 @@ static int wm8753_codec_probe(struct i2c_adapter *adap, int addr, int kind) client_template.addr = addr;
i2c = kmemdup(&client_template, sizeof(client_template), GFP_KERNEL);
- if (i2c == NULL){
- if (!i2c) { kfree(codec); return -ENOMEM; }
@@ -1749,7 +1752,7 @@ static int wm8753_probe(struct platform_device *pdev) wm8753_socdev = socdev; INIT_DELAYED_WORK(&codec->delayed_work, wm8753_work);
-#if defined (CONFIG_I2C) || defined (CONFIG_I2C_MODULE) +#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) if (setup->i2c_address) { normal_i2c[0] = setup->i2c_address; codec->hw_write = (hw_write_t)i2c_master_send; @@ -1793,7 +1796,7 @@ static int wm8753_remove(struct platform_device *pdev) run_delayed_work(&codec->delayed_work); snd_soc_free_pcms(socdev); snd_soc_dapm_free(socdev); -#if defined (CONFIG_I2C) || defined (CONFIG_I2C_MODULE) +#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) i2c_del_driver(&wm8753_i2c_driver); #endif kfree(codec->private_data); @@ -1808,7 +1811,6 @@ struct snd_soc_codec_device soc_codec_dev_wm8753 = { .suspend = wm8753_suspend, .resume = wm8753_resume, };
EXPORT_SYMBOL_GPL(soc_codec_dev_wm8753);
MODULE_DESCRIPTION("ASoC WM8753 driver");
1.5.5.1
participants (2)
-
Mark Brown
-
Takashi Iwai