Skip to content

Commit

Permalink
ASoC: soc-cache: Introduce raw bulk write support
Browse files Browse the repository at this point in the history
As it has become more common to have to write firmware or similar
large chunks of data to the hardware, add a function to perform
raw bulk writes that bypass the cache.  This only handles volatile
registers as we should avoid getting out of sync with the actual
cache.

Signed-off-by: Dimitris Papastamos <dp@opensource.wolfsonmicro.com>
Acked-by: Liam Girdwood <lrg@ti.com>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
  • Loading branch information
Dimitris Papastamos authored and Mark Brown committed Mar 26, 2011
1 parent f3594f5 commit 5fb609d
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 0 deletions.
3 changes: 3 additions & 0 deletions include/sound/soc.h
Original file line number Diff line number Diff line change
Expand Up @@ -543,6 +543,7 @@ struct snd_soc_codec {
unsigned int (*hw_read)(struct snd_soc_codec *, unsigned int);
unsigned int (*read)(struct snd_soc_codec *, unsigned int);
int (*write)(struct snd_soc_codec *, unsigned int, unsigned int);
int (*bulk_write_raw)(struct snd_soc_codec *, unsigned int, const void *, size_t);
void *reg_cache;
const void *reg_def_copy;
const struct snd_soc_cache_ops *cache_ops;
Expand Down Expand Up @@ -814,6 +815,8 @@ struct soc_enum {
unsigned int snd_soc_read(struct snd_soc_codec *codec, unsigned int reg);
unsigned int snd_soc_write(struct snd_soc_codec *codec,
unsigned int reg, unsigned int val);
unsigned int snd_soc_bulk_write_raw(struct snd_soc_codec *codec,
unsigned int reg, const void *data, size_t len);

/* device driver data */

Expand Down
39 changes: 39 additions & 0 deletions sound/soc/soc-cache.c
Original file line number Diff line number Diff line change
Expand Up @@ -625,6 +625,44 @@ static int snd_soc_16_16_spi_write(void *control_data, const char *data,
#define snd_soc_16_16_spi_write NULL
#endif

/* Primitive bulk write support for soc-cache. The data pointed to by `data' needs
* to already be in the form the hardware expects including any leading register specific
* data. Any data written through this function will not go through the cache as it
* only handles writing to volatile or out of bounds registers.
*/
static int snd_soc_hw_bulk_write_raw(struct snd_soc_codec *codec, unsigned int reg,
const void *data, size_t len)
{
int ret;

/* Ensure that the base register is volatile. Subsequently
* any other register that is touched by this routine should be
* volatile as well to ensure that we don't get out of sync with
* the cache.
*/
if (!snd_soc_codec_volatile_register(codec, reg)
&& reg < codec->driver->reg_cache_size)
return -EINVAL;

switch (codec->control_type) {
case SND_SOC_I2C:
ret = i2c_master_send(codec->control_data, data, len);
break;
case SND_SOC_SPI:
ret = do_spi_write(codec->control_data, data, len);
break;
default:
BUG();
}

if (ret == len)
return 0;
if (ret < 0)
return ret;
else
return -EIO;
}

static struct {
int addr_bits;
int data_bits;
Expand Down Expand Up @@ -708,6 +746,7 @@ int snd_soc_codec_set_cache_io(struct snd_soc_codec *codec,

codec->write = io_types[i].write;
codec->read = io_types[i].read;
codec->bulk_write_raw = snd_soc_hw_bulk_write_raw;

switch (control) {
case SND_SOC_CUSTOM:
Expand Down
7 changes: 7 additions & 0 deletions sound/soc/soc-core.c
Original file line number Diff line number Diff line change
Expand Up @@ -2228,6 +2228,13 @@ unsigned int snd_soc_write(struct snd_soc_codec *codec,
}
EXPORT_SYMBOL_GPL(snd_soc_write);

unsigned int snd_soc_bulk_write_raw(struct snd_soc_codec *codec,
unsigned int reg, const void *data, size_t len)
{
return codec->bulk_write_raw(codec, reg, data, len);
}
EXPORT_SYMBOL_GPL(snd_soc_bulk_write_raw);

/**
* snd_soc_update_bits - update codec register bits
* @codec: audio codec
Expand Down

0 comments on commit 5fb609d

Please sign in to comment.