From f0fba2ad1b6b53d5360125c41953b7afcd6deff0 Mon Sep 17 00:00:00 2001 From: Liam Girdwood Date: Wed, 17 Mar 2010 20:15:21 +0000 Subject: ASoC: multi-component - ASoC Multi-Component Support This patch extends the ASoC API to allow sound cards to have more than one CODEC and more than one platform DMA controller. This is achieved by dividing some current ASoC structures that contain both driver data and device data into structures that only either contain device data or driver data. i.e. struct snd_soc_codec ---> struct snd_soc_codec (device data) +-> struct snd_soc_codec_driver (driver data) struct snd_soc_platform ---> struct snd_soc_platform (device data) +-> struct snd_soc_platform_driver (driver data) struct snd_soc_dai ---> struct snd_soc_dai (device data) +-> struct snd_soc_dai_driver (driver data) struct snd_soc_device ---> deleted This now allows ASoC to be more tightly aligned with the Linux driver model and also means that every ASoC codec, platform and (platform) DAI is a kernel device. ASoC component private data is now stored as device private data. The ASoC sound card struct snd_soc_card has also been updated to store lists of it's components rather than a pointer to a codec and platform. The PCM runtime struct soc_pcm_runtime now has pointers to all its components. This patch adds DAPM support for ASoC multi-component and removes struct snd_soc_socdev from DAPM core. All DAPM calls are now made on a card, codec or runtime PCM level basis rather than using snd_soc_socdev. Other notable multi-component changes:- * Stream operations now de-reference less structures. * close_delayed work() now runs on a DAI basis rather than looping all DAIs in a card. * PM suspend()/resume() operations can now handle N CODECs and Platforms per sound card. * Added soc_bind_dai_link() to bind the component devices to the sound card. * Added soc_dai_link_probe() and soc_dai_link_remove() to probe and remove DAI link components. * sysfs entries can now be registered per component per card. * snd_soc_new_pcms() functionailty rolled into dai_link_probe(). * snd_soc_register_codec() now does all the codec list and mutex init. This patch changes the probe() and remove() of the CODEC drivers as follows:- o Make CODEC driver a platform driver o Moved all struct snd_soc_codec list, mutex, etc initialiasation to core. o Removed all static codec pointers (drivers now support > 1 codec dev) o snd_soc_register_pcms() now done by core. o snd_soc_register_dai() folded into snd_soc_register_codec(). CS4270 portions: Acked-by: Timur Tabi Some TLV320aic23 and Cirrus platform fixes. Signed-off-by: Ryan Mallon TI CODEC and OMAP fixes Signed-off-by: Peter Ujfalusi Signed-off-by: Janusz Krzysztofik Signed-off-by: Jarkko Nikula Samsung platform and misc fixes :- Signed-off-by: Chanwoo Choi Signed-off-by: Joonyoung Shim Signed-off-by: Kyungmin Park Reviewed-by: Jassi Brar Signed-off-by: Seungwhan Youn MPC8610 and PPC fixes. Signed-off-by: Timur Tabi i.MX fixes and some core fixes. Signed-off-by: Sascha Hauer J4740 platform fixes:- Signed-off-by: Lars-Peter Clausen CC: Tony Lindgren CC: Nicolas Ferre CC: Kevin Hilman CC: Sascha Hauer CC: Atsushi Nemoto CC: Kuninori Morimoto CC: Daniel Gloeckner CC: Manuel Lauss CC: Mike Frysinger CC: Arnaud Patard CC: Wan ZongShun Acked-by: Mark Brown Signed-off-by: Liam Girdwood --- sound/soc/soc-cache.c | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) (limited to 'sound/soc/soc-cache.c') diff --git a/sound/soc/soc-cache.c b/sound/soc/soc-cache.c index 472af38188c1..83cd8ed944bf 100644 --- a/sound/soc/soc-cache.c +++ b/sound/soc/soc-cache.c @@ -19,7 +19,7 @@ static unsigned int snd_soc_4_12_read(struct snd_soc_codec *codec, unsigned int reg) { u16 *cache = codec->reg_cache; - if (reg >= codec->reg_cache_size) + if (reg >= codec->driver->reg_cache_size) return -1; return cache[reg]; } @@ -31,12 +31,12 @@ static int snd_soc_4_12_write(struct snd_soc_codec *codec, unsigned int reg, u8 data[2]; int ret; - BUG_ON(codec->volatile_register); + BUG_ON(codec->driver->volatile_register); data[0] = (reg << 4) | ((value >> 8) & 0x000f); data[1] = value & 0x00ff; - if (reg < codec->reg_cache_size) + if (reg < codec->driver->reg_cache_size) cache[reg] = value; if (codec->cache_only) { @@ -89,7 +89,7 @@ static unsigned int snd_soc_7_9_read(struct snd_soc_codec *codec, unsigned int reg) { u16 *cache = codec->reg_cache; - if (reg >= codec->reg_cache_size) + if (reg >= codec->driver->reg_cache_size) return -1; return cache[reg]; } @@ -101,12 +101,12 @@ static int snd_soc_7_9_write(struct snd_soc_codec *codec, unsigned int reg, u8 data[2]; int ret; - BUG_ON(codec->volatile_register); + BUG_ON(codec->driver->volatile_register); data[0] = (reg << 1) | ((value >> 8) & 0x0001); data[1] = value & 0x00ff; - if (reg < codec->reg_cache_size) + if (reg < codec->driver->reg_cache_size) cache[reg] = value; if (codec->cache_only) { @@ -161,13 +161,13 @@ static int snd_soc_8_8_write(struct snd_soc_codec *codec, unsigned int reg, u8 *cache = codec->reg_cache; u8 data[2]; - BUG_ON(codec->volatile_register); + BUG_ON(codec->driver->volatile_register); reg &= 0xff; data[0] = reg; data[1] = value & 0xff; - if (reg < codec->reg_cache_size) + if (reg < codec->driver->reg_cache_size) cache[reg] = value; if (codec->cache_only) { @@ -188,7 +188,7 @@ static unsigned int snd_soc_8_8_read(struct snd_soc_codec *codec, { u8 *cache = codec->reg_cache; reg &= 0xff; - if (reg >= codec->reg_cache_size) + if (reg >= codec->driver->reg_cache_size) return -1; return cache[reg]; } @@ -224,7 +224,7 @@ static unsigned int snd_soc_8_16_read(struct snd_soc_codec *codec, { u16 *cache = codec->reg_cache; - if (reg >= codec->reg_cache_size || + if (reg >= codec->driver->reg_cache_size || snd_soc_codec_volatile_register(codec, reg)) { if (codec->cache_only) return -EINVAL; @@ -343,7 +343,7 @@ static unsigned int snd_soc_16_8_read(struct snd_soc_codec *codec, u16 *cache = codec->reg_cache; reg &= 0xff; - if (reg >= codec->reg_cache_size) + if (reg >= codec->driver->reg_cache_size) return -1; return cache[reg]; } @@ -355,14 +355,14 @@ static int snd_soc_16_8_write(struct snd_soc_codec *codec, unsigned int reg, u8 data[3]; int ret; - BUG_ON(codec->volatile_register); + BUG_ON(codec->driver->volatile_register); data[0] = (reg >> 8) & 0xff; data[1] = reg & 0xff; data[2] = value; reg &= 0xff; - if (reg < codec->reg_cache_size) + if (reg < codec->driver->reg_cache_size) cache[reg] = value; if (codec->cache_only) { @@ -451,7 +451,7 @@ static unsigned int snd_soc_16_16_read(struct snd_soc_codec *codec, { u16 *cache = codec->reg_cache; - if (reg >= codec->reg_cache_size || + if (reg >= codec->driver->reg_cache_size || snd_soc_codec_volatile_register(codec, reg)) { if (codec->cache_only) return -EINVAL; @@ -474,7 +474,7 @@ static int snd_soc_16_16_write(struct snd_soc_codec *codec, unsigned int reg, data[2] = (value >> 8) & 0xff; data[3] = value & 0xff; - if (reg < codec->reg_cache_size) + if (reg < codec->driver->reg_cache_size) cache[reg] = value; if (codec->cache_only) { @@ -571,8 +571,8 @@ int snd_soc_codec_set_cache_io(struct snd_soc_codec *codec, return -EINVAL; } - codec->write = io_types[i].write; - codec->read = io_types[i].read; + codec->driver->write = io_types[i].write; + codec->driver->read = io_types[i].read; switch (control) { case SND_SOC_CUSTOM: -- cgit v1.2.3 From a6d14342dc46f0ef94cccf323fd9481de84b458f Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 12 Aug 2010 10:59:15 +0100 Subject: ASoC: Automatically determine control_data for soc-cache users Since the provision of a struct device for the CODEC is now mandatory we can use container_of() to locate the struct i2c_client and struct spi_device for relevant devices, removing the need to manually set it in each driver. A further patch will automate selection of the control type based on the bus_type of the struct device, further reducing the amount of driver code required. Signed-off-by: Mark Brown Signed-off-by: Liam Girdwood --- sound/soc/soc-cache.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'sound/soc/soc-cache.c') diff --git a/sound/soc/soc-cache.c b/sound/soc/soc-cache.c index 83cd8ed944bf..b856177ea281 100644 --- a/sound/soc/soc-cache.c +++ b/sound/soc/soc-cache.c @@ -584,11 +584,19 @@ int snd_soc_codec_set_cache_io(struct snd_soc_codec *codec, #endif if (io_types[i].i2c_read) codec->hw_read = io_types[i].i2c_read; + + codec->control_data = container_of(codec->dev, + struct i2c_client, + dev); break; case SND_SOC_SPI: if (io_types[i].spi_write) codec->hw_write = io_types[i].spi_write; + + codec->control_data = container_of(codec->dev, + struct spi_device, + dev); break; } -- cgit v1.2.3 From fa6d52938906305356555e37e38939c7bad8fd7a Mon Sep 17 00:00:00 2001 From: Dimitris Papastamos Date: Tue, 21 Sep 2010 14:12:35 +0100 Subject: ASoC: Fix soc-cache buffer overflow bug Make sure we stay within the cache boundaries when updating the register cache. Signed-off-by: Dimitris Papastamos Acked-by: Liam Girdwood Signed-off-by: Mark Brown --- sound/soc/soc-cache.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'sound/soc/soc-cache.c') diff --git a/sound/soc/soc-cache.c b/sound/soc/soc-cache.c index 12281111f100..28bf1ff980ce 100644 --- a/sound/soc/soc-cache.c +++ b/sound/soc/soc-cache.c @@ -203,8 +203,9 @@ static int snd_soc_8_16_write(struct snd_soc_codec *codec, unsigned int reg, data[1] = (value >> 8) & 0xff; data[2] = value & 0xff; - if (!snd_soc_codec_volatile_register(codec, reg)) - reg_cache[reg] = value; + if (!snd_soc_codec_volatile_register(codec, reg) + && reg < codec->driver->reg_cache_size) + reg_cache[reg] = value; if (codec->cache_only) { codec->cache_sync = 1; -- cgit v1.2.3 From 391d8a04fc0f0d603642daa07f379e17c88001c9 Mon Sep 17 00:00:00 2001 From: Dimitris Papastamos Date: Tue, 21 Sep 2010 17:04:07 +0100 Subject: ASoC: Return -1 instead of -EINVAL to ensure consistency The code can't really cope with I/O errors, so it would be better to be consistent throughout all cache functions and return -1 instead of -EINVAL. The return value of snd_soc_read(...) is mostly checked in the probe function and nowhere else. Signed-off-by: Dimitris Papastamos Acked-by: Liam Girdwood Signed-off-by: Mark Brown --- sound/soc/soc-cache.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'sound/soc/soc-cache.c') diff --git a/sound/soc/soc-cache.c b/sound/soc/soc-cache.c index 28bf1ff980ce..6702a3dcd3fe 100644 --- a/sound/soc/soc-cache.c +++ b/sound/soc/soc-cache.c @@ -228,7 +228,7 @@ static unsigned int snd_soc_8_16_read(struct snd_soc_codec *codec, if (reg >= codec->driver->reg_cache_size || snd_soc_codec_volatile_register(codec, reg)) { if (codec->cache_only) - return -EINVAL; + return -1; return codec->hw_read(codec, reg); } else { @@ -455,7 +455,7 @@ static unsigned int snd_soc_16_16_read(struct snd_soc_codec *codec, if (reg >= codec->driver->reg_cache_size || snd_soc_codec_volatile_register(codec, reg)) { if (codec->cache_only) - return -EINVAL; + return -1; return codec->hw_read(codec, reg); } -- cgit v1.2.3 From 3e13f65e3aa51fc7009afc554683a0b182c057f5 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 23 Sep 2010 07:40:16 +0200 Subject: ASoC: adapt multi-componentism again Go back to the new world order. (Also fixed indentation.) Signed-off-by: Takashi Iwai --- sound/soc/soc-cache.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'sound/soc/soc-cache.c') diff --git a/sound/soc/soc-cache.c b/sound/soc/soc-cache.c index d4f11fbaf0f2..8a3f11cbcb2a 100644 --- a/sound/soc/soc-cache.c +++ b/sound/soc/soc-cache.c @@ -203,9 +203,9 @@ static int snd_soc_8_16_write(struct snd_soc_codec *codec, unsigned int reg, data[1] = (value >> 8) & 0xff; data[2] = value & 0xff; - if (!snd_soc_codec_volatile_register(codec, reg) - && reg < codec->reg_cache_size) - reg_cache[reg] = value; + if (!snd_soc_codec_volatile_register(codec, reg) && + reg < codec->driver->reg_cache_size) + reg_cache[reg] = value; if (codec->cache_only) { codec->cache_sync = 1; -- cgit v1.2.3 From db49c146a8c0e8d49c0ff029c2496d47660dfb28 Mon Sep 17 00:00:00 2001 From: Dimitris Papastamos Date: Wed, 22 Sep 2010 13:25:47 +0100 Subject: ASoC: Delegate to hw specific read for volatile registers Ensure that reads on volatile registers will correctly delegate to the bus specific read function. Signed-off-by: Dimitris Papastamos Acked-by: Liam Girdwood Signed-off-by: Mark Brown --- sound/soc/soc-cache.c | 76 +++++++++++++++++++++++++++++++++------------------ 1 file changed, 50 insertions(+), 26 deletions(-) (limited to 'sound/soc/soc-cache.c') diff --git a/sound/soc/soc-cache.c b/sound/soc/soc-cache.c index 8a3f11cbcb2a..143d2be9eda9 100644 --- a/sound/soc/soc-cache.c +++ b/sound/soc/soc-cache.c @@ -19,8 +19,15 @@ static unsigned int snd_soc_4_12_read(struct snd_soc_codec *codec, unsigned int reg) { u16 *cache = codec->reg_cache; - if (reg >= codec->driver->reg_cache_size) - return -1; + + if (reg >= codec->driver->reg_cache_size || + snd_soc_codec_volatile_register(codec, reg)) { + if (codec->cache_only) + return -1; + + return codec->hw_read(codec, reg); + } + return cache[reg]; } @@ -31,13 +38,12 @@ static int snd_soc_4_12_write(struct snd_soc_codec *codec, unsigned int reg, u8 data[2]; int ret; - BUG_ON(codec->driver->volatile_register); - data[0] = (reg << 4) | ((value >> 8) & 0x000f); data[1] = value & 0x00ff; - if (reg < codec->driver->reg_cache_size) - cache[reg] = value; + if (!snd_soc_codec_volatile_register(codec, reg) && + reg < codec->driver->reg_cache_size) + cache[reg] = value; if (codec->cache_only) { codec->cache_sync = 1; @@ -89,8 +95,15 @@ static unsigned int snd_soc_7_9_read(struct snd_soc_codec *codec, unsigned int reg) { u16 *cache = codec->reg_cache; - if (reg >= codec->driver->reg_cache_size) - return -1; + + if (reg >= codec->driver->reg_cache_size || + snd_soc_codec_volatile_register(codec, reg)) { + if (codec->cache_only) + return -1; + + return codec->hw_read(codec, reg); + } + return cache[reg]; } @@ -101,13 +114,12 @@ static int snd_soc_7_9_write(struct snd_soc_codec *codec, unsigned int reg, u8 data[2]; int ret; - BUG_ON(codec->driver->volatile_register); - data[0] = (reg << 1) | ((value >> 8) & 0x0001); data[1] = value & 0x00ff; - if (reg < codec->driver->reg_cache_size) - cache[reg] = value; + if (!snd_soc_codec_volatile_register(codec, reg) && + reg < codec->driver->reg_cache_size) + cache[reg] = value; if (codec->cache_only) { codec->cache_sync = 1; @@ -161,14 +173,13 @@ static int snd_soc_8_8_write(struct snd_soc_codec *codec, unsigned int reg, u8 *cache = codec->reg_cache; u8 data[2]; - BUG_ON(codec->driver->volatile_register); - reg &= 0xff; data[0] = reg; data[1] = value & 0xff; - if (reg < codec->driver->reg_cache_size) - cache[reg] = value; + if (!snd_soc_codec_volatile_register(codec, value) && + reg < codec->driver->reg_cache_size) + cache[reg] = value; if (codec->cache_only) { codec->cache_sync = 1; @@ -187,9 +198,16 @@ static unsigned int snd_soc_8_8_read(struct snd_soc_codec *codec, unsigned int reg) { u8 *cache = codec->reg_cache; + reg &= 0xff; - if (reg >= codec->driver->reg_cache_size) - return -1; + if (reg >= codec->driver->reg_cache_size || + snd_soc_codec_volatile_register(codec, reg)) { + if (codec->cache_only) + return -1; + + return codec->hw_read(codec, reg); + } + return cache[reg]; } @@ -344,8 +362,14 @@ static unsigned int snd_soc_16_8_read(struct snd_soc_codec *codec, u8 *cache = codec->reg_cache; reg &= 0xff; - if (reg >= codec->driver->reg_cache_size) - return -1; + if (reg >= codec->driver->reg_cache_size || + snd_soc_codec_volatile_register(codec, reg)) { + if (codec->cache_only) + return -1; + + return codec->hw_read(codec, reg); + } + return cache[reg]; } @@ -356,15 +380,14 @@ static int snd_soc_16_8_write(struct snd_soc_codec *codec, unsigned int reg, u8 data[3]; int ret; - BUG_ON(codec->driver->volatile_register); - data[0] = (reg >> 8) & 0xff; data[1] = reg & 0xff; data[2] = value; reg &= 0xff; - if (reg < codec->driver->reg_cache_size) - cache[reg] = value; + if (!snd_soc_codec_volatile_register(codec, reg) && + reg < codec->driver->reg_cache_size) + cache[reg] = value; if (codec->cache_only) { codec->cache_sync = 1; @@ -475,8 +498,9 @@ static int snd_soc_16_16_write(struct snd_soc_codec *codec, unsigned int reg, data[2] = (value >> 8) & 0xff; data[3] = value & 0xff; - if (reg < codec->driver->reg_cache_size) - cache[reg] = value; + if (!snd_soc_codec_volatile_register(codec, reg) && + reg < codec->driver->reg_cache_size) + cache[reg] = value; if (codec->cache_only) { codec->cache_sync = 1; -- cgit v1.2.3 From 005d65fbac28e6cf32c76e95163012eb326f37e4 Mon Sep 17 00:00:00 2001 From: Dimitris Papastamos Date: Wed, 22 Sep 2010 16:16:06 +0100 Subject: ASoC: Fix incorrect parameter to snd_soc_codec_volatile_register We need to pass the register index and not the register value. This patch depends on my previous patch "ASoC: Delegate to hw specific read for volatile registers". Signed-off-by: Dimitris Papastamos Acked-by: Liam Girdwood Signed-off-by: Mark Brown --- sound/soc/soc-cache.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound/soc/soc-cache.c') diff --git a/sound/soc/soc-cache.c b/sound/soc/soc-cache.c index 143d2be9eda9..62f1e2b776c4 100644 --- a/sound/soc/soc-cache.c +++ b/sound/soc/soc-cache.c @@ -177,7 +177,7 @@ static int snd_soc_8_8_write(struct snd_soc_codec *codec, unsigned int reg, data[0] = reg; data[1] = value & 0xff; - if (!snd_soc_codec_volatile_register(codec, value) && + if (!snd_soc_codec_volatile_register(codec, reg) && reg < codec->driver->reg_cache_size) cache[reg] = value; -- cgit v1.2.3 From f479fd93d4028afccf155dec736c6d49cde92571 Mon Sep 17 00:00:00 2001 From: Dimitris Papastamos Date: Mon, 4 Oct 2010 11:25:13 +0100 Subject: ASoC: soc-cache: Add spi_write support for all I/O types Ensure that all drivers that use SPI and I2C will work properly by providing SPI write functions for all different I/O types. Signed-off-by: Dimitris Papastamos Acked-by: Liam Girdwood Signed-off-by: Mark Brown --- sound/soc/soc-cache.c | 96 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) (limited to 'sound/soc/soc-cache.c') diff --git a/sound/soc/soc-cache.c b/sound/soc/soc-cache.c index 62f1e2b776c4..d214f02cbb65 100644 --- a/sound/soc/soc-cache.c +++ b/sound/soc/soc-cache.c @@ -211,6 +211,36 @@ static unsigned int snd_soc_8_8_read(struct snd_soc_codec *codec, return cache[reg]; } +#if defined(CONFIG_SPI_MASTER) +static int snd_soc_8_8_spi_write(void *control_data, const char *data, + int len) +{ + struct spi_device *spi = control_data; + struct spi_transfer t; + struct spi_message m; + u8 msg[2]; + + if (len <= 0) + return 0; + + msg[0] = data[0]; + msg[1] = data[1]; + + spi_message_init(&m); + memset(&t, 0, (sizeof t)); + + t.tx_buf = &msg[0]; + t.len = len; + + spi_message_add_tail(&t, &m); + spi_sync(spi, &m); + + return len; +} +#else +#define snd_soc_8_8_spi_write NULL +#endif + static int snd_soc_8_16_write(struct snd_soc_codec *codec, unsigned int reg, unsigned int value) { @@ -254,6 +284,37 @@ static unsigned int snd_soc_8_16_read(struct snd_soc_codec *codec, } } +#if defined(CONFIG_SPI_MASTER) +static int snd_soc_8_16_spi_write(void *control_data, const char *data, + int len) +{ + struct spi_device *spi = control_data; + struct spi_transfer t; + struct spi_message m; + u8 msg[3]; + + if (len <= 0) + return 0; + + msg[0] = data[0]; + msg[1] = data[1]; + msg[2] = data[2]; + + spi_message_init(&m); + memset(&t, 0, (sizeof t)); + + t.tx_buf = &msg[0]; + t.len = len; + + spi_message_add_tail(&t, &m); + spi_sync(spi, &m); + + return len; +} +#else +#define snd_soc_8_16_spi_write NULL +#endif + #if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE)) static unsigned int snd_soc_8_8_read_i2c(struct snd_soc_codec *codec, unsigned int r) @@ -518,6 +579,38 @@ static int snd_soc_16_16_write(struct snd_soc_codec *codec, unsigned int reg, return -EIO; } +#if defined(CONFIG_SPI_MASTER) +static int snd_soc_16_16_spi_write(void *control_data, const char *data, + int len) +{ + struct spi_device *spi = control_data; + struct spi_transfer t; + struct spi_message m; + u8 msg[4]; + + if (len <= 0) + return 0; + + msg[0] = data[0]; + msg[1] = data[1]; + msg[2] = data[2]; + msg[3] = data[3]; + + spi_message_init(&m); + memset(&t, 0, (sizeof t)); + + t.tx_buf = &msg[0]; + t.len = len; + + spi_message_add_tail(&t, &m); + spi_sync(spi, &m); + + return len; +} +#else +#define snd_soc_16_16_spi_write NULL +#endif + static struct { int addr_bits; int data_bits; @@ -540,11 +633,13 @@ static struct { .addr_bits = 8, .data_bits = 8, .write = snd_soc_8_8_write, .read = snd_soc_8_8_read, .i2c_read = snd_soc_8_8_read_i2c, + .spi_write = snd_soc_8_8_spi_write, }, { .addr_bits = 8, .data_bits = 16, .write = snd_soc_8_16_write, .read = snd_soc_8_16_read, .i2c_read = snd_soc_8_16_read_i2c, + .spi_write = snd_soc_8_16_spi_write, }, { .addr_bits = 16, .data_bits = 8, @@ -556,6 +651,7 @@ static struct { .addr_bits = 16, .data_bits = 16, .write = snd_soc_16_16_write, .read = snd_soc_16_16_read, .i2c_read = snd_soc_16_16_read_i2c, + .spi_write = snd_soc_16_16_spi_write, }, }; -- cgit v1.2.3