diff options
author | Scott Jiang <scott.jiang.linux@gmail.com> | 2011-08-12 18:04:13 -0400 |
---|---|---|
committer | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2011-08-15 22:38:14 +0900 |
commit | 396a2e79cdbd562bf7ea48132f8d3ba8304109b2 (patch) | |
tree | 215fb1c5ff930785281bf33a957edeb73ff6e8df | |
parent | 25ea524bed0202f823a0adcbbda68e86a22e3670 (diff) |
ASoC: Add spi hw read function for 16 addr 8 data mode for ad193x fix
[This will be used by the ad193x driver to fix the fact that the
original author of the driver put a bodge for their particular chip into
a the generic ASoC register I/O abstraction layer which looked like an
obvious bug which ended up getting fixed in 3.0. Sadly there were no
comments documenting what was going on. A minimally invasive correction
to the driver is to remove the register cache support and go direct to
the hardware all the time so we're adding a new feature -- broonie]
Signed-off-by: Scott Jiang <scott.jiang.linux@gmail.com>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
-rw-r--r-- | sound/soc/soc-io.c | 23 |
1 files changed, 23 insertions, 0 deletions
diff --git a/sound/soc/soc-io.c b/sound/soc/soc-io.c index cca490c80589..a62f7dd4ba96 100644 --- a/sound/soc/soc-io.c +++ b/sound/soc/soc-io.c @@ -205,6 +205,25 @@ static unsigned int snd_soc_16_8_read_i2c(struct snd_soc_codec *codec, #define snd_soc_16_8_read_i2c NULL #endif +#if defined(CONFIG_SPI_MASTER) +static unsigned int snd_soc_16_8_read_spi(struct snd_soc_codec *codec, + unsigned int r) +{ + struct spi_device *spi = codec->control_data; + + const u16 reg = cpu_to_be16(r | 0x100); + u8 data; + int ret; + + ret = spi_write_then_read(spi, ®, 2, &data, 1); + if (ret < 0) + return 0; + return data; +} +#else +#define snd_soc_16_8_read_spi NULL +#endif + static int snd_soc_16_8_write(struct snd_soc_codec *codec, unsigned int reg, unsigned int value) { @@ -295,6 +314,7 @@ static struct { int (*write)(struct snd_soc_codec *codec, unsigned int, unsigned int); unsigned int (*read)(struct snd_soc_codec *, unsigned int); unsigned int (*i2c_read)(struct snd_soc_codec *, unsigned int); + unsigned int (*spi_read)(struct snd_soc_codec *, unsigned int); } io_types[] = { { .addr_bits = 4, .data_bits = 12, @@ -318,6 +338,7 @@ static struct { .addr_bits = 16, .data_bits = 8, .write = snd_soc_16_8_write, .i2c_read = snd_soc_16_8_read_i2c, + .spi_read = snd_soc_16_8_read_spi, }, { .addr_bits = 16, .data_bits = 16, @@ -383,6 +404,8 @@ int snd_soc_codec_set_cache_io(struct snd_soc_codec *codec, #ifdef CONFIG_SPI_MASTER codec->hw_write = do_spi_write; #endif + if (io_types[i].spi_read) + codec->hw_read = io_types[i].spi_read; codec->control_data = container_of(codec->dev, struct spi_device, |