summary refs log tree commit diff
path: root/sound/soc/codecs/ad1938.c
diff options
context:
space:
mode:
authorBarry Song <21cnbao@gmail.com>2010-01-27 11:46:18 +0800
committerMark Brown <broonie@opensource.wolfsonmicro.com>2010-01-27 10:43:09 +0000
commit994dc4245d3f50329da4ead453a5dfcfbc716a0d (patch)
tree1523d8129ccf168d953c44e500a01e5f13cb8dbf /sound/soc/codecs/ad1938.c
parent63b62ab0d52c736b3274b294df962e0a4b7aae79 (diff)
downloadlinux-994dc4245d3f50329da4ead453a5dfcfbc716a0d.tar.gz
ASoC: ad1938: use soc-cache framework for codec registers access
Signed-off-by: Barry Song <Barry.Song@analog.com>
Acked-by: Liam Girdwood <lrg@slimlogic.co.uk>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Diffstat (limited to 'sound/soc/codecs/ad1938.c')
-rw-r--r--sound/soc/codecs/ad1938.c164
1 files changed, 36 insertions, 128 deletions
diff --git a/sound/soc/codecs/ad1938.c b/sound/soc/codecs/ad1938.c
index 47d9ac0ec9d9..c233810d463d 100644
--- a/sound/soc/codecs/ad1938.c
+++ b/sound/soc/codecs/ad1938.c
@@ -46,6 +46,11 @@ struct ad1938_priv {
 	u8 reg_cache[AD1938_NUM_REGS];
 };
 
+/* ad1938 register cache & default register settings */
+static const u8 ad1938_reg[AD1938_NUM_REGS] = {
+	0, 0, 0, 0, 0, 0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0, 0, 0,
+};
+
 static struct snd_soc_codec *ad1938_codec;
 struct snd_soc_codec_device soc_codec_dev_ad1938;
 static int ad1938_register(struct ad1938_priv *ad1938);
@@ -129,10 +134,10 @@ static int ad1938_mute(struct snd_soc_dai *dai, int mute)
 	struct snd_soc_codec *codec = dai->codec;
 	int reg;
 
-	reg = codec->read(codec, AD1938_DAC_CTRL2);
+	reg = snd_soc_read(codec, AD1938_DAC_CTRL2);
 	reg = (mute > 0) ? reg | AD1938_DAC_MASTER_MUTE : reg &
 		(~AD1938_DAC_MASTER_MUTE);
-	codec->write(codec, AD1938_DAC_CTRL2, reg);
+	snd_soc_write(codec, AD1938_DAC_CTRL2, reg);
 
 	return 0;
 }
@@ -141,8 +146,8 @@ static int ad1938_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask,
 			       unsigned int rx_mask, int slots, int width)
 {
 	struct snd_soc_codec *codec = dai->codec;
-	int dac_reg = codec->read(codec, AD1938_DAC_CTRL1);
-	int adc_reg = codec->read(codec, AD1938_ADC_CTRL2);
+	int dac_reg = snd_soc_read(codec, AD1938_DAC_CTRL1);
+	int adc_reg = snd_soc_read(codec, AD1938_ADC_CTRL2);
 
 	dac_reg &= ~AD1938_DAC_CHAN_MASK;
 	adc_reg &= ~AD1938_ADC_CHAN_MASK;
@@ -168,8 +173,8 @@ static int ad1938_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask,
 		return -EINVAL;
 	}
 
-	codec->write(codec, AD1938_DAC_CTRL1, dac_reg);
-	codec->write(codec, AD1938_ADC_CTRL2, adc_reg);
+	snd_soc_write(codec, AD1938_DAC_CTRL1, dac_reg);
+	snd_soc_write(codec, AD1938_ADC_CTRL2, adc_reg);
 
 	return 0;
 }
@@ -180,8 +185,8 @@ static int ad1938_set_dai_fmt(struct snd_soc_dai *codec_dai,
 	struct snd_soc_codec *codec = codec_dai->codec;
 	int adc_reg, dac_reg;
 
-	adc_reg = codec->read(codec, AD1938_ADC_CTRL2);
-	dac_reg = codec->read(codec, AD1938_DAC_CTRL1);
+	adc_reg = snd_soc_read(codec, AD1938_ADC_CTRL2);
+	dac_reg = snd_soc_read(codec, AD1938_DAC_CTRL1);
 
 	/* At present, the driver only support AUX ADC mode(SND_SOC_DAIFMT_I2S
 	 * with TDM) and ADC&DAC TDM mode(SND_SOC_DAIFMT_DSP_A)
@@ -258,8 +263,8 @@ static int ad1938_set_dai_fmt(struct snd_soc_dai *codec_dai,
 		return -EINVAL;
 	}
 
-	codec->write(codec, AD1938_ADC_CTRL2, adc_reg);
-	codec->write(codec, AD1938_DAC_CTRL1, dac_reg);
+	snd_soc_write(codec, AD1938_ADC_CTRL2, adc_reg);
+	snd_soc_write(codec, AD1938_DAC_CTRL1, dac_reg);
 
 	return 0;
 }
@@ -288,116 +293,13 @@ static int ad1938_hw_params(struct snd_pcm_substream *substream,
 		break;
 	}
 
-	reg = codec->read(codec, AD1938_DAC_CTRL2);
+	reg = snd_soc_read(codec, AD1938_DAC_CTRL2);
 	reg = (reg & (~AD1938_DAC_WORD_LEN_MASK)) | word_len;
-	codec->write(codec, AD1938_DAC_CTRL2, reg);
+	snd_soc_write(codec, AD1938_DAC_CTRL2, reg);
 
-	reg = codec->read(codec, AD1938_ADC_CTRL1);
+	reg = snd_soc_read(codec, AD1938_ADC_CTRL1);
 	reg = (reg & (~AD1938_ADC_WORD_LEN_MASK)) | word_len;
-	codec->write(codec, AD1938_ADC_CTRL1, reg);
-
-	return 0;
-}
-
-/*
- * interface to read/write ad1938 register
- */
-
-#define AD1938_SPI_ADDR    0x4
-#define AD1938_SPI_READ    0x1
-#define AD1938_SPI_BUFLEN  3
-
-/*
- * write to the ad1938 register space
- */
-
-static int ad1938_write_reg(struct snd_soc_codec *codec, unsigned int reg,
-		unsigned int value)
-{
-	u8 *reg_cache = codec->reg_cache;
-	int ret = 0;
-
-	if (value != reg_cache[reg]) {
-		uint8_t buf[AD1938_SPI_BUFLEN];
-		struct spi_transfer t = {
-			.tx_buf = buf,
-			.len = AD1938_SPI_BUFLEN,
-		};
-		struct spi_message m;
-
-		buf[0] = AD1938_SPI_ADDR << 1;
-		buf[1] = reg;
-		buf[2] = value;
-		spi_message_init(&m);
-		spi_message_add_tail(&t, &m);
-		ret = spi_sync(codec->control_data, &m);
-		if (ret == 0)
-			reg_cache[reg] = value;
-	}
-
-	return ret;
-}
-
-/*
- * read from the ad1938 register space cache
- */
-
-static unsigned int ad1938_read_reg_cache(struct snd_soc_codec *codec,
-					  unsigned int reg)
-{
-	u8 *reg_cache = codec->reg_cache;
-
-	if (reg >= codec->reg_cache_size)
-		return -EINVAL;
-
-	return reg_cache[reg];
-}
-
-/*
- * read from the ad1938 register space
- */
-
-static unsigned int ad1938_read_reg(struct snd_soc_codec *codec,
-						unsigned int reg)
-{
-	char w_buf[AD1938_SPI_BUFLEN];
-	char r_buf[AD1938_SPI_BUFLEN];
-	int ret;
-
-	struct spi_transfer t = {
-		.tx_buf = w_buf,
-		.rx_buf = r_buf,
-		.len = AD1938_SPI_BUFLEN,
-	};
-	struct spi_message m;
-
-	w_buf[0] = (AD1938_SPI_ADDR << 1) | AD1938_SPI_READ;
-	w_buf[1] = reg;
-	w_buf[2] = 0;
-
-	spi_message_init(&m);
-	spi_message_add_tail(&t, &m);
-	ret = spi_sync(codec->control_data, &m);
-	if (ret == 0)
-		return	r_buf[2];
-	else
-		return -EIO;
-}
-
-static int ad1938_fill_cache(struct snd_soc_codec *codec)
-{
-	int i;
-	u8 *reg_cache = codec->reg_cache;
-	struct spi_device *spi = codec->control_data;
-
-	for (i = 0; i < codec->reg_cache_size; i++) {
-		int ret = ad1938_read_reg(codec, i);
-		if (ret == -EIO) {
-			dev_err(&spi->dev, "AD1938 SPI read failure\n");
-			return ret;
-		}
-		reg_cache[i] = ret;
-	}
+	snd_soc_write(codec, AD1938_ADC_CTRL1, reg);
 
 	return 0;
 }
@@ -487,31 +389,37 @@ static int ad1938_register(struct ad1938_priv *ad1938)
 	codec->owner = THIS_MODULE;
 	codec->dai = &ad1938_dai;
 	codec->num_dai = 1;
-	codec->write = ad1938_write_reg;
-	codec->read = ad1938_read_reg_cache;
 	INIT_LIST_HEAD(&codec->dapm_widgets);
 	INIT_LIST_HEAD(&codec->dapm_paths);
 
 	ad1938_dai.dev = codec->dev;
 	ad1938_codec = codec;
 
+	memcpy(codec->reg_cache, ad1938_reg, AD1938_NUM_REGS);
+
+	ret = snd_soc_codec_set_cache_io(codec, 16, 8, SND_SOC_SPI);
+	if (ret < 0) {
+		dev_err(codec->dev, "failed to set cache I/O: %d\n",
+				ret);
+		kfree(ad1938);
+		return ret;
+	}
+
 	/* default setting for ad1938 */
 
 	/* unmute dac channels */
-	codec->write(codec, AD1938_DAC_CHNL_MUTE, 0x0);
+	snd_soc_write(codec, AD1938_DAC_CHNL_MUTE, 0x0);
 	/* de-emphasis: 48kHz, powedown dac */
-	codec->write(codec, AD1938_DAC_CTRL2, 0x1A);
+	snd_soc_write(codec, AD1938_DAC_CTRL2, 0x1A);
 	/* powerdown dac, dac in tdm mode */
-	codec->write(codec, AD1938_DAC_CTRL0, 0x41);
+	snd_soc_write(codec, AD1938_DAC_CTRL0, 0x41);
 	/* high-pass filter enable */
-	codec->write(codec, AD1938_ADC_CTRL0, 0x3);
+	snd_soc_write(codec, AD1938_ADC_CTRL0, 0x3);
 	/* sata delay=1, adc aux mode */
-	codec->write(codec, AD1938_ADC_CTRL1, 0x43);
+	snd_soc_write(codec, AD1938_ADC_CTRL1, 0x43);
 	/* pll input: mclki/xi */
-	codec->write(codec, AD1938_PLL_CLK_CTRL0, 0x9D);
-	codec->write(codec, AD1938_PLL_CLK_CTRL1, 0x04);
-
-	ad1938_fill_cache(codec);
+	snd_soc_write(codec, AD1938_PLL_CLK_CTRL0, 0x9D);
+	snd_soc_write(codec, AD1938_PLL_CLK_CTRL1, 0x04);
 
 	ret = snd_soc_register_codec(codec);
 	if (ret != 0) {