summaryrefslogtreecommitdiff
path: root/sound
diff options
context:
space:
mode:
authorVinod G <vinodg@nvidia.com>2011-12-02 16:32:50 -0800
committerVarun Wadekar <vwadekar@nvidia.com>2011-12-08 17:55:48 +0530
commit444d92c3bc71d2d2dd090ac2c1d4d2c0c8517691 (patch)
treed5085033e329c02f487915eeea1142b0b559087b /sound
parent171d61d7e574f83f7f59affb4d3b8edecd5dd587 (diff)
kernel: sound: soc: Fix TI codec reg access issue.
Using snd_soc_write is causing some issue with TI codec. So register read and write are handled locally inside the codec calls. Added checking to continue card register based on codec availability, this help to use either TI codec or wm8753 codec being present in the board. bug 816608 Change-Id: Ie5edd1c70609991c28216bbc3a0ffcafd0f815ab Reviewed-on: http://git-master/r/68044 Reviewed-by: Vinod Gopalakrishnakurup <vinodg@nvidia.com> Tested-by: Vinod Gopalakrishnakurup <vinodg@nvidia.com> Reviewed-by: Scott Peterson <speterson@nvidia.com>
Diffstat (limited to 'sound')
-rwxr-xr-xsound/soc/codecs/tlv320aic326x.c461
-rwxr-xr-xsound/soc/codecs/tlv320aic326x.h13
-rw-r--r--sound/soc/tegra/tegra_aic326x.c37
-rw-r--r--sound/soc/tegra/tegra_wm8753.c9
4 files changed, 165 insertions, 355 deletions
diff --git a/sound/soc/codecs/tlv320aic326x.c b/sound/soc/codecs/tlv320aic326x.c
index 40b6093737e4..9f1874328b28 100755
--- a/sound/soc/codecs/tlv320aic326x.c
+++ b/sound/soc/codecs/tlv320aic326x.c
@@ -49,7 +49,6 @@
#include <linux/pm.h>
#include <linux/i2c.h>
#include <linux/platform_device.h>
-#include <linux/spi/spi.h>
#include <linux/slab.h>
#include <sound/core.h>
#include <sound/pcm.h>
@@ -120,17 +119,6 @@ static int soc_static_freq_config = 1;
* Function Prototype
*****************************************************************************
*/
-static int aic3262_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params,
- struct snd_soc_dai *dai);
-
-static int aic3262_mute(struct snd_soc_dai *dai, int mute);
-
-static int aic3262_set_dai_sysclk(struct snd_soc_dai *codec_dai,
- int clk_id, unsigned int freq, int dir);
-
-static int aic3262_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt);
-
static int aic3262_set_bias_level(struct snd_soc_codec *codec,
enum snd_soc_bias_level level);
@@ -416,8 +404,8 @@ int snd_soc_get_volsw_2r_n(struct snd_kcontrol *kcontrol,
}
/* Read, update the corresponding Registers */
- val = (snd_soc_read(codec, reg) >> shift) & mask;
- val2 = (snd_soc_read(codec, reg2) >> shift) & mask;
+ val = (aic3262_read(codec, reg) >> shift) & mask;
+ val2 = (aic3262_read(codec, reg2) >> shift) & mask;
if (!strcmp(kcontrol->id.name, "PCM Playback Volume")) {
ucontrol->value.integer.value[0] =
@@ -612,8 +600,12 @@ static int __new_control_put(struct snd_kcontrol *kcontrol,
aic3262->page_no = data[1];
DBG("reg = %d val = %x\n", data[0], data[1]);
-
+#if defined(LOCAL_REG_ACCESS)
+ if (codec->hw_write(codec->control_data, data, 2) != 2)
+ ret = -EIO;
+#else
ret = snd_soc_write(codec, data[0], data[1]);
+#endif
if (ret)
printk(KERN_ERR "Error in i2c write\n");
@@ -894,11 +886,11 @@ static void aic3262_multi_i2s_dump_regs(struct snd_soc_dai *dai)
aic3262_read(codec, counter));
}
- /*DBG(KERN_INFO "#Page1 REGS..\n");
+ DBG(KERN_INFO "#Page1 REGS..\n");
for (counter = 128; counter < 176; counter++) {
DBG(KERN_INFO "#%2d -> 0x%x\n", (counter % 128),
aic3262_read(codec, counter));
- }*/
+ }
DBG(KERN_INFO "#Page4 REGS..\n");
for (counter = 512; counter < 631; counter++) {
@@ -1376,9 +1368,6 @@ static int aic3262_multi_i2s_asi2_set_dai_fmt(struct snd_soc_dai *codec_dai,
*/
iface_reg = aic3262_read(codec, ASI2_BUS_FMT);
clk_reg = aic3262_read(codec, ASI2_BWCLK_CNTL_REG);
- /*
- iface_reg = ifce_reg & ~(3 << 6 | 3 << 2);
- */
/* set master/slave audio interface */
switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
@@ -1592,8 +1581,6 @@ static int aic3262_multi_i2s_set_dai_sysclk(struct snd_soc_dai *codec_dai,
switch (freq) {
case AIC3262_FREQ_12000000:
case AIC3262_FREQ_12288000:
- aic3262->sysclk = freq;
- return 0;
case AIC3262_FREQ_24000000:
aic3262->sysclk = freq;
return 0;
@@ -2172,7 +2159,7 @@ static int aic3262_multi_i2s_hw_free(struct snd_pcm_substream *substream,
*/
if ((substream->stream == SNDRV_PCM_STREAM_PLAYBACK) &&
(dacregoffset != 0)) {
- printk(KERN_INFO "#%s: Disabling Pg %d Reg %d DAC Inputs ..\n",
+ DBG(KERN_INFO "#%s: Disabling Pg %d Reg %d DAC Inputs ..\n",
__func__, (dacregoffset/128), (dacregoffset % 128));
dacpath = aic3262_read(codec, dacregoffset);
@@ -2237,13 +2224,6 @@ err:
* The PCM bit format supported are 16, 20, 24 and 32 bits
*----------------------------------------------------------------------------
*/
-struct snd_soc_dai_ops aic3262_dai_ops = {
- .hw_params = aic3262_hw_params,
- .digital_mute = aic3262_mute,
- .set_sysclk = aic3262_set_dai_sysclk,
- .set_fmt = aic3262_set_dai_fmt,
-};
-
struct snd_soc_dai_ops aic3262_multi_i2s_dai_ops = {
.hw_params = aic3262_multi_i2s_hw_params,
.digital_mute = aic3262_multi_i2s_mute,
@@ -2730,11 +2710,16 @@ int aic3262_change_page(struct snd_soc_codec *codec, u8 new_page)
data[1] = new_page;
aic3262->page_no = new_page;
+#if defined(LOCAL_REG_ACCESS)
+ if (codec->hw_write(codec->control_data, data, 2) != 2)
+ ret = -EIO;
+#else
ret = snd_soc_write(codec, data[0], data[1]);
+#endif
if (ret)
printk(KERN_ERR "Error in changing page to %d\n", new_page);
- DBG("# Changing page to %d\r\n", new_page);
+ /*DBG("# Changing page to %d\r\n", new_page);*/
return ret;
}
@@ -2759,11 +2744,16 @@ int aic3262_change_book(struct snd_soc_codec *codec, u8 new_book)
if (ret)
return ret;
+#if defined(LOCAL_REG_ACCESS)
+ if (codec->hw_write(codec->control_data, data, 2) != 2)
+ ret = -EIO;
+#else
ret = snd_soc_write(codec, data[0], data[1]);
+#endif
if (ret)
printk(KERN_ERR "Error in changing Book\n");
- DBG("# Changing book to %d\r\n", new_book);
+ /*DBG("# Changing book to %d\r\n", new_book);*/
return ret;
}
@@ -2777,6 +2767,7 @@ int aic3262_change_book(struct snd_soc_codec *codec, u8 new_book)
void aic3262_write_reg_cache(struct snd_soc_codec *codec,
u16 reg, u8 value)
{
+#if defined(EN_REG_CACHE)
u8 *cache = codec->reg_cache;
if (reg >= AIC3262_CACHEREGNUM)
@@ -2784,6 +2775,7 @@ void aic3262_write_reg_cache(struct snd_soc_codec *codec,
if (cache)
cache[reg] = value;
+#endif
}
/*
@@ -2804,7 +2796,12 @@ u8 aic3262_read(struct snd_soc_codec *codec, u16 reg)
if (aic3262->page_no != page)
aic3262_change_page(codec, page);
+#if defined(LOCAL_REG_ACCESS)
+ i2c_master_send(codec->control_data, (char *)&reg, 1);
+ i2c_master_recv(codec->control_data, &value, 1);
+#else
value = snd_soc_read(codec, reg);
+#endif
/*DBG("r %2x %02x\r\n", reg, value);*/
return value;
}
@@ -2845,8 +2842,14 @@ int aic3262_write(struct snd_soc_codec *codec, u16 reg, u8 value)
/*DBG("w %2x %02x\r\n",
data[AIC3262_REG_OFFSET_INDEX], data[AIC3262_REG_DATA_INDEX]);*/
+
+#if defined(LOCAL_REG_ACCESS)
+ if (codec->hw_write(codec->control_data, data, 2) != 2)
+ ret = -EIO;
+#else
ret = snd_soc_write(codec, data[AIC3262_REG_OFFSET_INDEX],
data[AIC3262_REG_DATA_INDEX]);
+#endif
if (ret)
printk(KERN_ERR "Error in i2c write\n");
@@ -2873,7 +2876,7 @@ int aic3262_write__(struct i2c_client *client, const char *buf, int count)
ret = i2c_master_send(client, data, 2);
if (ret < 2) {
printk(
- KERN_ERR"I2C write Error : bytes written = %d\n\n", ret);
+ KERN_ERR "I2C write Error : bytes written = %d\n\n", ret);
return -EIO;
}
@@ -2892,6 +2895,13 @@ int aic3262_reset_cache(struct snd_soc_codec *codec)
memcpy(codec->reg_cache, aic3262_reg, sizeof(aic3262_reg));
return 0;
}
+
+ codec->reg_cache = kmemdup(aic3262_reg,
+ sizeof(aic3262_reg), GFP_KERNEL);
+ if (!codec->reg_cache) {
+ printk(KERN_ERR "aic32x4: kmemdup failed\n");
+ return -ENOMEM;
+ }
#endif
return 0;
}
@@ -2939,15 +2949,17 @@ static int aic3262_add_controls(struct snd_soc_codec *codec)
{
int err;
+ DBG("%s++\n", __func__);
+
err = snd_soc_add_controls(codec, aic3262_snd_controls,
- ARRAY_SIZE(aic3262_snd_controls));
+ ARRAY_SIZE(aic3262_snd_controls));
if (err < 0) {
printk(KERN_ERR "Invalid control\n");
return err;
}
err = snd_soc_add_controls(codec, aic3262_snd_controls2,
- ARRAY_SIZE(aic3262_snd_controls2));
+ ARRAY_SIZE(aic3262_snd_controls2));
if (err < 0) {
printk(KERN_ERR "Invalid control\n");
return err;
@@ -3004,9 +3016,15 @@ static int aic3262_add_widgets(struct snd_soc_codec *codec)
int reg_def_conf(struct snd_soc_codec *codec)
{
int i = 0, ret;
+ DBG(KERN_INFO "#%s: Invoked..\n", __func__);
- aic3262_change_page(codec, 0);
- aic3262_change_book(codec, 0);
+ ret = aic3262_change_page(codec, 0);
+ if (ret != 0)
+ return ret;
+
+ ret = aic3262_change_book(codec, 0);
+ if (ret != 0)
+ return ret;
/* Configure the Codec with the default Initialization Values */
for (i = 0; i < reg_init_size; i++) {
@@ -3015,6 +3033,7 @@ int reg_def_conf(struct snd_soc_codec *codec)
if (ret)
break;
}
+ DBG(KERN_INFO "#%s: Done..\n", __func__);
return ret;
}
@@ -3046,295 +3065,17 @@ int i2c_verify_book0(struct snd_soc_codec *codec)
k = 4;
}*/
for (i = 0; i <= 127; i++) {
+#if defined(LOCAL_REG_ACCESS)
+ val1 = i2c_smbus_read_byte_data(codec->control_data, i);
+#else
val1 = snd_soc_read(codec, i);
+#endif
/* printk("[%d][%d]=[0x%2x]\n",k,i,val1); */
}
}
return 0;
}
-
-
-/*
- *----------------------------------------------------------------------------
- * Function : aic3262_hw_params
- * Purpose : This function is to set the hardware parameters for AIC3262.
- * The functions set the sample rate and audio serial data word
- * length.
- *
- *----------------------------------------------------------------------------
- */
-static int aic3262_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params,
- struct snd_soc_dai *dai)
-{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_codec *codec = rtd->codec;
- struct aic3262_priv *aic3262 = snd_soc_codec_get_drvdata(codec);
- int i, j;
- u8 data;
-
- aic3262_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
-
- i = aic3262_get_divs(aic3262->sysclk, params_rate(params));
-
- i2c_verify_book0(codec);
-
- if (i < 0) {
- printk(KERN_ERR "sampling rate not supported\n");
- return i;
- }
-
- if (soc_static_freq_config) {
- /*We will fix R value to 1 and make P & J=K.D as varialble */
-
- /* Setting P & R values are set to 1 and 1 at init*/
-
- /* J value */
- aic3262_write(codec, PLL_J_REG, aic3262_divs[i].pll_j);
-
- /* MSB & LSB for D value */
-
- aic3262_write(codec, PLL_D_MSB, (aic3262_divs[i].pll_d >> 8));
- aic3262_write(codec, PLL_D_LSB,
- (aic3262_divs[i].pll_d & AIC3262_8BITS_MASK));
-
- /* NDAC divider value */
- data = aic3262_read(codec, NDAC_DIV_POW_REG);
- DBG(KERN_INFO "# reading NDAC = %d , NDAC_DIV_POW_REG = %x\n",
- aic3262_divs[i].ndac, data);
- aic3262_write(codec, NDAC_DIV_POW_REG,
- ((data & 0x80)|(aic3262_divs[i].ndac)));
- DBG(KERN_INFO "# writing NDAC = %d , NDAC_DIV_POW_REG = %x\n",
- aic3262_divs[i].ndac,
- ((data & 0x80)|(aic3262_divs[i].ndac)));
-
- /* MDAC divider value */
- data = aic3262_read(codec, MDAC_DIV_POW_REG);
- DBG(KERN_INFO "# reading MDAC = %d , MDAC_DIV_POW_REG = %x\n",
- aic3262_divs[i].mdac, data);
- aic3262_write(codec, MDAC_DIV_POW_REG,
- ((data & 0x80)|(aic3262_divs[i].mdac)));
- DBG(KERN_INFO "# writing MDAC = %d , MDAC_DIV_POW_REG = %x\n",
- aic3262_divs[i].mdac, ((data & 0x80)|(aic3262_divs[i].mdac)));
-
- /* DOSR MSB & LSB values */
- aic3262_write(codec, DOSR_MSB_REG, aic3262_divs[i].dosr >> 8);
- DBG(KERN_INFO "# writing DOSR_MSB_REG = %d\n",
- (aic3262_divs[i].dosr >> 8));
- aic3262_write(codec, DOSR_LSB_REG,
- aic3262_divs[i].dosr & AIC3262_8BITS_MASK);
- DBG(KERN_INFO "# writing DOSR_LSB_REG = %d\n",
- (aic3262_divs[i].dosr & AIC3262_8BITS_MASK));
-
- /* NADC divider value */
- data = aic3262_read(codec, NADC_DIV_POW_REG);
- aic3262_write(codec, NADC_DIV_POW_REG,
- ((data & 0x80)|(aic3262_divs[i].nadc)));
- DBG(KERN_INFO "# writing NADC_DIV_POW_REG = %d\n",
- aic3262_divs[i].nadc);
-
- /* MADC divider value */
- data = aic3262_read(codec, MADC_DIV_POW_REG);
- aic3262_write(codec, MADC_DIV_POW_REG,
- ((data & 0x80)|(aic3262_divs[i].madc)));
- DBG(KERN_INFO "# writing MADC_DIV_POW_REG = %d\n",
- aic3262_divs[i].madc);
-
- /* AOSR value */
- aic3262_write(codec, AOSR_REG, aic3262_divs[i].aosr);
- DBG(KERN_INFO "# writing AOSR = %d\n", aic3262_divs[i].aosr);
- }
-
-
- data = aic3262_read(codec, ASI1_BUS_FMT);
-
- data = data & 0xe7;
-
- switch (params_format(params)) {
- case SNDRV_PCM_FORMAT_S16_LE:
- data = data | 0x00;
- break;
- case SNDRV_PCM_FORMAT_S20_3LE:
- data |= (0x08);
- break;
- case SNDRV_PCM_FORMAT_S24_LE:
- data |= (0x10);
- break;
- case SNDRV_PCM_FORMAT_S32_LE:
- data |= (0x18);
- break;
- }
-
- /* configure the respective Registers for the above configuration */
- aic3262_write(codec, ASI1_BUS_FMT, data);
-
- for (j = 0; j < NO_FEATURE_REGS; j++) {
- aic3262_write(codec,
- aic3262_divs[i].codec_specific_regs[j].reg_offset,
- aic3262_divs[i].codec_specific_regs[j].reg_val);
- }
-
- aic3262_set_bias_level(codec, SND_SOC_BIAS_ON);
- return 0;
-}
-
-/*
- *----------------------------------------------------------------------------
- * Function : aic3262_mute
- * Purpose : This function is to mute or unmute the left and right DAC
- *
- *----------------------------------------------------------------------------
- */
-static int aic3262_mute(struct snd_soc_dai *dai, int mute)
-{
- struct snd_soc_codec *codec = dai->codec;
- struct aic3262_priv *aic3262 = snd_soc_codec_get_drvdata(codec);
-
- DBG(KERN_INFO "#aic3262 codec : mute started\n");
- if (mute) {
- DBG("Mute if part\n");
-
- if (!aic3262->mute_codec) {
- dac_reg = aic3262_read(codec, DAC_MVOL_CONF);
- adc_gain = aic3262_read(codec, ADC_FINE_GAIN);
- hpl = aic3262_read(codec, HPL_VOL);
- hpr = aic3262_read(codec, HPR_VOL);
- rec_amp = aic3262_read(codec, REC_AMP_CNTL_R5);
- rampr = aic3262_read(codec, RAMPR_VOL);
- spk_amp = aic3262_read(codec, SPK_AMP_CNTL_R4);
- }
- DBG("spk_reg = %2x\n\n", spk_amp);
-
- aic3262_write(codec, DAC_MVOL_CONF, ((dac_reg & 0xF3) | 0x0C));
- aic3262_write(codec, ADC_FINE_GAIN, ((adc_gain & 0x77) | 0x88));
- aic3262_write(codec, HPL_VOL, 0xB9);
- aic3262_write(codec, HPR_VOL, 0xB9);
- aic3262_write(codec, REC_AMP_CNTL_R5, 0x39);
- aic3262_write(codec, RAMPR_VOL, 0x39);
- aic3262_write(codec, SPK_AMP_CNTL_R4, 0x00);
- aic3262->mute_codec = 1;
- } else {
- DBG("Mute else part\n");
- aic3262_write(codec, DAC_MVOL_CONF, (dac_reg & 0xF3));
- mdelay(5);
- aic3262_write(codec, ADC_FINE_GAIN, (adc_gain & 0x77));
- mdelay(5);
- aic3262_write(codec, HPL_VOL, hpl);
- mdelay(5);
- aic3262_write(codec, HPR_VOL, hpr);
- mdelay(5);
- aic3262_write(codec, REC_AMP_CNTL_R5, rec_amp);
- mdelay(5);
- aic3262_write(codec, RAMPR_VOL, rampr);
- mdelay(5);
- aic3262_write(codec, SPK_AMP_CNTL_R4, spk_amp);
- mdelay(5);
- aic3262->mute_codec = 0;
- }
- DBG(KERN_INFO "#aic3262 codec : mute ended\n");
- return 0;
-}
-
-/*
- *----------------------------------------------------------------------------
- * Function : aic3262_set_dai_sysclk
- * Purpose : This function is to set the DAI system clock
- *
- *----------------------------------------------------------------------------
- */
-static int aic3262_set_dai_sysclk(struct snd_soc_dai *codec_dai,
- int clk_id, unsigned int freq, int dir)
-{
- struct snd_soc_codec *codec = codec_dai->codec;
- struct aic3262_priv *aic3262 = snd_soc_codec_get_drvdata(codec);
-
- switch (freq) {
- case AIC3262_FREQ_12000000:
- case AIC3262_FREQ_12288000:
- aic3262->sysclk = freq;
- return 0;
- case AIC3262_FREQ_24000000:
- aic3262->sysclk = freq;
- return 0;
- break;
- }
- printk(KERN_ERR "Invalid frequency to set DAI system clock\n");
- return -EINVAL;
-}
-
-/*
- *----------------------------------------------------------------------------
- * Function : aic3262_set_dai_fmt
- * Purpose : This function is to set the DAI format
- *
- *----------------------------------------------------------------------------
- */
-static int aic3262_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
-{
- struct snd_soc_codec *codec = codec_dai->codec;
- struct aic3262_priv *aic3262 = snd_soc_codec_get_drvdata(codec);
- u8 iface_reg, clk_reg;
-
- iface_reg = aic3262_read(codec, ASI1_BUS_FMT);
-
- /* set master/slave audio interface */
- switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
- case SND_SOC_DAIFMT_CBM_CFM:
- DBG("setdai_fmt : SND_SOC_DAIFMT_CBM_CFM : master=1\n");
- aic3262->master = 1;
- /*Test added */
- clk_reg = aic3262_read(codec, ASI1_BWCLK_CNTL_REG);
- clk_reg = (clk_reg & 0x03);
- aic3262_write(codec, ASI1_BWCLK_CNTL_REG,
- (clk_reg | 0x24));
- break;
- case SND_SOC_DAIFMT_CBS_CFS:
- DBG("setdai_fmt : SND_SOC_DAIFMT_CBS_CFS : master=0\n");
- aic3262->master = 0;
- /*Test added */
- clk_reg = aic3262_read(codec, ASI1_BWCLK_CNTL_REG);
- aic3262_write(codec, ASI1_BWCLK_CNTL_REG,
- (clk_reg & 0x03));
- break;
- case SND_SOC_DAIFMT_CBS_CFM: /*new case..just for debugging*/
- DBG("SND_SOC_DAIFMT_CBS_CFM\n");
- aic3262->master = 0;
- break;
- default:
- printk(KERN_ERR "Invalid DAI master/slave interface\n");
- return -EINVAL;
- }
-
- /* interface format */
- switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
- case SND_SOC_DAIFMT_I2S:
- iface_reg = (iface_reg & 0x1f);
- break;
- case SND_SOC_DAIFMT_DSP_A:
- iface_reg = (iface_reg & 0x1f) | 0x20;
- break;
- case SND_SOC_DAIFMT_RIGHT_J:
- iface_reg = (iface_reg & 0x1f) | 0x40;
- break;
- case SND_SOC_DAIFMT_LEFT_J:
- iface_reg = (iface_reg & 0x1f) | 0x60;
- break;
- case SND_SOC_DAIFMT_DSP_B:
- iface_reg = (iface_reg & 0x1f) | 0x80;
- /* voice call need data offset in 1 bitclock */
- aic3262_write(codec, ASI1_LCH_OFFSET, 1);
- break;
- default:
- printk(KERN_ERR "Invalid DAI interface format\n");
- return -EINVAL;
- }
-
- aic3262_write(codec, ASI1_BUS_FMT, iface_reg);
-
- return 0;
-}
-
/*
*----------------------------------------------------------------------------
* Function : aic3262_set_bias_level
@@ -3478,7 +3219,7 @@ static int aic3262_set_bias_level(struct snd_soc_codec *codec,
static int aic3262_suspend(struct snd_soc_codec *codec, pm_message_t state)
{
struct aic3262_priv *aic3262 = snd_soc_codec_get_drvdata(codec);
-
+ DBG(KERN_INFO "#%s: Invoked..\n", __func__);
if (aic3262)
disable_irq(aic3262->irq);
@@ -3501,21 +3242,25 @@ static int aic3262_resume(struct snd_soc_codec *codec)
int ret = 0;
struct aic3262_priv *aic3262 = snd_soc_codec_get_drvdata(codec);
u8 *cache = codec->reg_cache;
+ DBG(KERN_INFO "#%s: Invoked..\n", __func__);
ret = aic3262_change_page(codec, 0);
if (ret)
return ret;
-
+#if defined(EN_REG_CACHE)
/* Sync reg_cache with the hardware */
for (i = 0; i < ARRAY_SIZE(aic3262_reg); i++) {
data[0] = i % 128;
data[1] = cache[i];
-
+#if defined(LOCAL_REG_ACCESS)
+ codec->hw_write(codec->control_data, data, 2);
+#else
ret = snd_soc_write(codec, data[0], data[1]);
if (ret)
break;
+#endif
}
-
+#endif
if (!ret) {
aic3262_change_page(codec, 0);
aic3262_set_bias_level(codec, SND_SOC_BIAS_ON);
@@ -3525,6 +3270,24 @@ static int aic3262_resume(struct snd_soc_codec *codec)
}
return ret;
}
+/*
+ *----------------------------------------------------------------------------
+ * Function : aic3262_hw_read
+ * Purpose : This is a low level harware read function.
+ *
+ *----------------------------------------------------------------------------
+ */
+unsigned int aic3262_hw_read(struct snd_soc_codec *codec, unsigned int count)
+{
+ struct i2c_client *client = codec->control_data;
+ unsigned int buf;
+
+ if (count > (sizeof(unsigned int)))
+ return 0;
+
+ i2c_master_recv(client, (char *)&buf, count);
+ return buf;
+}
/*
* aic3262_jack_handler
@@ -3541,14 +3304,16 @@ static irqreturn_t aic3262_jack_handler(int irq, void *data)
DBG("%s++\n", __func__);
+ aic3262_change_page(codec, 0);
+
/* Read the Jack Status Register*/
- value = snd_soc_read(codec, STICKY_FLAG2);
+ value = aic3262_read(codec, STICKY_FLAG2);
DBG(KERN_INFO "reg44 0x%x\n", value);
- value = snd_soc_read(codec, INT_FLAG2);
+ value = aic3262_read(codec, INT_FLAG2);
DBG("reg46 0x%x\n", value);
- value = snd_soc_read(codec, DAC_FLAG_R1);
+ value = aic3262_read(codec, DAC_FLAG_R1);
DBG("reg37 0x%x\n", value);
micbits = value & DAC_FLAG_MIC_MASKBITS;
@@ -3558,26 +3323,30 @@ static irqreturn_t aic3262_jack_handler(int irq, void *data)
DBG("hsbits 0x%x\n", hsbits);
/* sleep for debounce time */
- msleep(aic3262->pdata->debounce_time_ms);
+ /*msleep(aic3262->pdata->debounce_time_ms);*/
/* No Headphone or Headset*/
if (!micbits && !hsbits) {
+ DBG("no headset/headphone\n");
snd_soc_jack_report(aic3262->headset_jack,
0, SND_JACK_HEADSET);
}
/* Headphone Detected */
if ((micbits == DAC_FLAG_R1_NOMIC) || (hsbits)) {
+ DBG("headphone\n");
snd_soc_jack_report(aic3262->headset_jack,
SND_JACK_HEADPHONE, SND_JACK_HEADSET);
}
/* Headset Detected - only with capless */
if (micbits == DAC_FLAG_R1_MIC) {
+ DBG("headset\n");
snd_soc_jack_report(aic3262->headset_jack,
SND_JACK_HEADSET, SND_JACK_HEADSET);
}
+ DBG("%s--\n", __func__);
return IRQ_HANDLED;
}
@@ -3670,18 +3439,33 @@ static int aic3262_probe(struct snd_soc_codec *codec)
DBG(KERN_INFO "#%s: Invoked..\n", __func__);
+#if defined(EN_REG_CACHE)
+ codec->reg_cache =
+ kmemdup(aic3262_reg, sizeof(aic3262_reg), GFP_KERNEL);
+
+ if (!codec->reg_cache) {
+ printk(KERN_ERR "aic3262: kmemdup failed\n");
+ return -ENOMEM;
+ }
+#else
/* Setting cache bypass - not to overwrite the cache registers,
Codec registers have 4 pages which is not handled in the common
cache code properly - bypass it in write value and save it
using separate call*/
codec->cache_bypass = 1;
+#endif
+#if defined(LOCAL_REG_ACCESS)
+ codec->control_data = aic3262->control_data;
+ codec->hw_write = (hw_write_t) aic3262_write__;
+ codec->hw_read = aic3262_hw_read;
+#else
ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_I2C);
if (ret != 0) {
dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
return ret;
}
-
+#endif
ret = reg_def_conf(codec);
if (ret != 0) {
printk(KERN_ERR "Failed to init TI codec: %d\n", ret);
@@ -3700,11 +3484,11 @@ static int aic3262_probe(struct snd_soc_codec *codec)
dev_err(codec->dev, "Failed to request IRQ: %d\n", ret);
return ret;
} else
- printk(KERN_INFO
+ DBG(KERN_INFO
"#%s: irq Registration for IRQ %d done..\n",
__func__, aic3262->irq);
} else {
- printk(KERN_INFO "#%s: I2C IRQ Configuration is Wrong. \
+ DBG(KERN_INFO "#%s: I2C IRQ Configuration is Wrong. \
Please check it..\n", __func__);
}
@@ -3729,6 +3513,7 @@ static int aic3262_probe(struct snd_soc_codec *codec)
aic3262_add_multiconfig_controls(codec);
#endif
+ DBG(KERN_INFO "#%s: done..\n", __func__);
return ret;
}
@@ -3763,10 +3548,15 @@ static struct snd_soc_codec_driver soc_codec_dev_aic3262 = {
.suspend = aic3262_suspend,
.resume = aic3262_resume,
.set_bias_level = aic3262_set_bias_level,
+#if defined(LOCAL_REG_ACCESS)
+ .read = aic3262_read,
+ .write = aic3262_write,
+#endif
+#if !defined(EN_REG_CACHE)
.reg_cache_size = ARRAY_SIZE(aic3262_reg),
- .reg_word_size = sizeof(u16),
+ .reg_word_size = sizeof(u8),
.reg_cache_default = aic3262_reg,
- .compress_type = SND_SOC_FLAT_COMPRESSION,
+#endif
};
@@ -3802,6 +3592,9 @@ static __devinit int aic3262_codec_probe(struct i2c_client *i2c,
}
i2c_set_clientdata(i2c, aic3262);
+#if defined(LOCAL_REG_ACCESS)
+ aic3262->control_data = i2c;
+#endif
aic3262->control_type = SND_SOC_I2C;
aic3262->irq = i2c->irq;
aic3262->pdata = i2c->dev.platform_data;
@@ -3828,7 +3621,7 @@ static __devinit int aic3262_codec_probe(struct i2c_client *i2c,
if (ret < 0)
kfree(aic3262);
-
+ DBG(KERN_INFO "#%s: Done ret %d\n", __func__, ret);
return ret;
}
@@ -3859,7 +3652,7 @@ MODULE_DEVICE_TABLE(i2c, tlv320aic3262_id);
static struct i2c_driver tlv320aic3262_i2c_driver = {
.driver = {
- .name = "tlv320aic3262",
+ .name = "aic3262-codec",
.owner = THIS_MODULE,
},
.probe = aic3262_codec_probe,
diff --git a/sound/soc/codecs/tlv320aic326x.h b/sound/soc/codecs/tlv320aic326x.h
index e6e67350a5e8..259ecb110787 100755
--- a/sound/soc/codecs/tlv320aic326x.h
+++ b/sound/soc/codecs/tlv320aic326x.h
@@ -28,11 +28,17 @@
/* Enable this macro allow for different ASI formats */
/*#define ASI_MULTI_FMT*/
#undef ASI_MULTI_FMT
+
/* Enable register caching on write */
-#define EN_REG_CACHE
+#define EN_REG_CACHE 1
#define MULTIBYTE_CONFIG_SUPPORT
+/*Setting all codec reg/write locally*/
+/* This definition is added as the snd_ direct call are
+result some issue with cache. Common code doesnot support
+page, so fix that before commenting this line*/
+#define LOCAL_REG_ACCESS 1
/* Macro enables or disables support for miniDSP in the driver */
/* Enable the AIC3262_TiLoad macro first before enabling these macros */
@@ -57,7 +63,7 @@
#define AIC3262_MULTI_I2S 1
/* Driver Debug Messages Enabled */
-#define DEBUG
+/*#define DEBUG*/
#ifdef DEBUG
#define DBG(x...) printk(x)
@@ -519,6 +525,9 @@ struct aic3262_priv {
u8 adc_clkin_option;
int irq;
struct snd_soc_jack *headset_jack;
+#if defined(LOCAL_REG_ACCESS)
+ void *control_data;
+#endif
};
/*
diff --git a/sound/soc/tegra/tegra_aic326x.c b/sound/soc/tegra/tegra_aic326x.c
index 635756379f23..77cc53ad9090 100644
--- a/sound/soc/tegra/tegra_aic326x.c
+++ b/sound/soc/tegra/tegra_aic326x.c
@@ -588,11 +588,11 @@ static int tegra_aic326x_bt_voice_call_hw_params(
static void tegra_aic326x_bt_voice_call_shutdown(
struct snd_pcm_substream *substream)
{
+#ifndef CONFIG_ARCH_TEGRA_2x_SOC
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct tegra_aic326x *machine =
snd_soc_card_get_drvdata(rtd->codec->card);
-#ifndef CONFIG_ARCH_TEGRA_2x_SOC
machine->codec_info[BT_SCO].rate = 0;
machine->codec_info[BT_SCO].channels = 0;
#endif
@@ -915,7 +915,7 @@ static struct snd_soc_dai_link tegra_aic326x_dai[] = {
.codec_dai_name = "dit-hifi",
.ops = &tegra_aic326x_bt_ops,
},
- /*[DAI_LINK_VOICE_CALL] = {
+ [DAI_LINK_VOICE_CALL] = {
.name = "VOICE CALL",
.stream_name = "VOICE CALL PCM",
.codec_name = "aic3262-codec.4-0018",
@@ -923,7 +923,7 @@ static struct snd_soc_dai_link tegra_aic326x_dai[] = {
.cpu_dai_name = "dit-hifi",
.codec_dai_name = "aic3262-asi2",
.ops = &tegra_aic326x_voice_call_ops,
- },*/
+ },
/* TODO - enabling this cause binding issue- figure out */
/*[DAI_LINK_BT_VOICE_CALL] = {
.name = "BT VOICE CALL",
@@ -971,16 +971,6 @@ static __devinit int tegra_aic326x_driver_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, card);
snd_soc_card_set_drvdata(card, machine);
-#ifdef CONFIG_SWITCH
- /* Add h2w switch class support */
- ret = switch_dev_register(&aic326x_wired_switch_dev);
- if (ret < 0) {
- dev_err(&pdev->dev, "not able to register switch device %d\n",
- ret);
- goto err_fini_utils;
- }
-#endif
-
#ifndef CONFIG_ARCH_TEGRA_2x_SOC
for (i = 0; i < NUM_I2S_DEVICES ; i++)
machine->codec_info[i].i2s_id = pdata->audio_port_id[i];
@@ -999,15 +989,28 @@ static __devinit int tegra_aic326x_driver_probe(struct platform_device *pdev)
if (ret) {
dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n",
ret);
- goto err_switch_unregister;
+ goto err_fini_utils;
}
- return 0;
+ if (!card->instantiated) {
+ dev_err(&pdev->dev, "No TI AIC3262 codec\n");
+ goto err_unregister_card;
+ }
-err_switch_unregister:
#ifdef CONFIG_SWITCH
- switch_dev_unregister(&aic326x_wired_switch_dev);
+ /* Add h2w switch class support */
+ ret = switch_dev_register(&aic326x_wired_switch_dev);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "not able to register switch device %d\n",
+ ret);
+ goto err_unregister_card;
+ }
#endif
+
+ return 0;
+
+err_unregister_card:
+ snd_soc_unregister_card(card);
err_fini_utils:
tegra_asoc_utils_fini(&machine->util_data);
err_free_machine:
diff --git a/sound/soc/tegra/tegra_wm8753.c b/sound/soc/tegra/tegra_wm8753.c
index bc9e3104b605..2405a0fe1320 100644
--- a/sound/soc/tegra/tegra_wm8753.c
+++ b/sound/soc/tegra/tegra_wm8753.c
@@ -81,7 +81,6 @@ static int tegra_wm8753_hw_params(struct snd_pcm_substream *substream,
struct tegra_wm8753 *machine = snd_soc_card_get_drvdata(card);
int srate, mclk, i2s_daifmt;
int err;
-
srate = params_rate(params);
switch (srate) {
case 8000:
@@ -571,6 +570,7 @@ static __devinit int tegra_wm8753_driver_probe(struct platform_device *pdev)
struct tegra_wm8753_platform_data *pdata;
int ret;
+
pdata = pdev->dev.platform_data;
if (!pdata) {
dev_err(&pdev->dev, "No platform data supplied\n");
@@ -600,11 +600,16 @@ static __devinit int tegra_wm8753_driver_probe(struct platform_device *pdev)
goto err_fini_utils;
}
+ if (!card->instantiated) {
+ dev_err(&pdev->dev, "No WM8753 codec\n");
+ goto err_unregister_card;
+ }
+
#ifdef CONFIG_SWITCH
/* Add h2w swith class support */
ret = switch_dev_register(&wired_switch_dev);
if (ret < 0) {
- dev_err(&pdev->dev, "not able to register switch device\n",
+ dev_err(&pdev->dev, "not able to register switch device %d\n",
ret);
goto err_unregister_card;
}