Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5fb609d4 authored by Dimitris Papastamos's avatar Dimitris Papastamos Committed by Mark Brown
Browse files

ASoC: soc-cache: Introduce raw bulk write support



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: default avatarDimitris Papastamos <dp@opensource.wolfsonmicro.com>
Acked-by: default avatarLiam Girdwood <lrg@ti.com>
Signed-off-by: default avatarMark Brown <broonie@opensource.wolfsonmicro.com>
parent f3594f5c
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -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;
@@ -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 */

+39 −0
Original line number Diff line number Diff line
@@ -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;
@@ -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:
+7 −0
Original line number Diff line number Diff line
@@ -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