summaryrefslogtreecommitdiff
path: root/sound
diff options
context:
space:
mode:
Diffstat (limited to 'sound')
-rw-r--r--sound/soc/soc-cache.c263
-rw-r--r--sound/soc/soc-core.c93
-rw-r--r--sound/soc/soc-io.c26
-rw-r--r--sound/soc/soc-pcm.c8
-rw-r--r--sound/soc/soc-utils.c6
5 files changed, 96 insertions, 300 deletions
diff --git a/sound/soc/soc-cache.c b/sound/soc/soc-cache.c
index e72f55428f0b..1b6663f45b34 100644
--- a/sound/soc/soc-cache.c
+++ b/sound/soc/soc-cache.c
@@ -11,12 +11,9 @@
* option) any later version.
*/
-#include <linux/i2c.h>
-#include <linux/spi/spi.h>
#include <sound/soc.h>
-#include <linux/bitmap.h>
-#include <linux/rbtree.h>
#include <linux/export.h>
+#include <linux/slab.h>
#include <trace/events/asoc.h>
@@ -66,126 +63,42 @@ static unsigned int snd_soc_get_cache_val(const void *base, unsigned int idx,
return -1;
}
-static int snd_soc_flat_cache_sync(struct snd_soc_codec *codec)
+int snd_soc_cache_init(struct snd_soc_codec *codec)
{
- int i;
- int ret;
- const struct snd_soc_codec_driver *codec_drv;
- unsigned int val;
+ const struct snd_soc_codec_driver *codec_drv = codec->driver;
+ size_t reg_size;
- codec_drv = codec->driver;
- for (i = 0; i < codec_drv->reg_cache_size; ++i) {
- ret = snd_soc_cache_read(codec, i, &val);
- if (ret)
- return ret;
- if (codec->reg_def_copy)
- if (snd_soc_get_cache_val(codec->reg_def_copy,
- i, codec_drv->reg_word_size) == val)
- continue;
+ reg_size = codec_drv->reg_cache_size * codec_drv->reg_word_size;
- WARN_ON(!snd_soc_codec_writable_register(codec, i));
-
- ret = snd_soc_write(codec, i, val);
- if (ret)
- return ret;
- dev_dbg(codec->dev, "ASoC: Synced register %#x, value = %#x\n",
- i, val);
- }
- return 0;
-}
-
-static int snd_soc_flat_cache_write(struct snd_soc_codec *codec,
- unsigned int reg, unsigned int value)
-{
- snd_soc_set_cache_val(codec->reg_cache, reg, value,
- codec->driver->reg_word_size);
- return 0;
-}
-
-static int snd_soc_flat_cache_read(struct snd_soc_codec *codec,
- unsigned int reg, unsigned int *value)
-{
- *value = snd_soc_get_cache_val(codec->reg_cache, reg,
- codec->driver->reg_word_size);
- return 0;
-}
+ mutex_init(&codec->cache_rw_mutex);
-static int snd_soc_flat_cache_exit(struct snd_soc_codec *codec)
-{
- if (!codec->reg_cache)
- return 0;
- kfree(codec->reg_cache);
- codec->reg_cache = NULL;
- return 0;
-}
+ dev_dbg(codec->dev, "ASoC: Initializing cache for %s codec\n",
+ codec->name);
-static int snd_soc_flat_cache_init(struct snd_soc_codec *codec)
-{
- if (codec->reg_def_copy)
- codec->reg_cache = kmemdup(codec->reg_def_copy,
- codec->reg_size, GFP_KERNEL);
+ if (codec_drv->reg_cache_default)
+ codec->reg_cache = kmemdup(codec_drv->reg_cache_default,
+ reg_size, GFP_KERNEL);
else
- codec->reg_cache = kzalloc(codec->reg_size, GFP_KERNEL);
+ codec->reg_cache = kzalloc(reg_size, GFP_KERNEL);
if (!codec->reg_cache)
return -ENOMEM;
return 0;
}
-/* an array of all supported compression types */
-static const struct snd_soc_cache_ops cache_types[] = {
- /* Flat *must* be the first entry for fallback */
- {
- .id = SND_SOC_FLAT_COMPRESSION,
- .name = "flat",
- .init = snd_soc_flat_cache_init,
- .exit = snd_soc_flat_cache_exit,
- .read = snd_soc_flat_cache_read,
- .write = snd_soc_flat_cache_write,
- .sync = snd_soc_flat_cache_sync
- },
-};
-
-int snd_soc_cache_init(struct snd_soc_codec *codec)
-{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(cache_types); ++i)
- if (cache_types[i].id == codec->compress_type)
- break;
-
- /* Fall back to flat compression */
- if (i == ARRAY_SIZE(cache_types)) {
- dev_warn(codec->dev, "ASoC: Could not match compress type: %d\n",
- codec->compress_type);
- i = 0;
- }
-
- mutex_init(&codec->cache_rw_mutex);
- codec->cache_ops = &cache_types[i];
-
- if (codec->cache_ops->init) {
- if (codec->cache_ops->name)
- dev_dbg(codec->dev, "ASoC: Initializing %s cache for %s codec\n",
- codec->cache_ops->name, codec->name);
- return codec->cache_ops->init(codec);
- }
- return -ENOSYS;
-}
-
/*
* NOTE: keep in mind that this function might be called
* multiple times.
*/
int snd_soc_cache_exit(struct snd_soc_codec *codec)
{
- if (codec->cache_ops && codec->cache_ops->exit) {
- if (codec->cache_ops->name)
- dev_dbg(codec->dev, "ASoC: Destroying %s cache for %s codec\n",
- codec->cache_ops->name, codec->name);
- return codec->cache_ops->exit(codec);
- }
- return -ENOSYS;
+ dev_dbg(codec->dev, "ASoC: Destroying cache for %s codec\n",
+ codec->name);
+ if (!codec->reg_cache)
+ return 0;
+ kfree(codec->reg_cache);
+ codec->reg_cache = NULL;
+ return 0;
}
/**
@@ -198,18 +111,15 @@ int snd_soc_cache_exit(struct snd_soc_codec *codec)
int snd_soc_cache_read(struct snd_soc_codec *codec,
unsigned int reg, unsigned int *value)
{
- int ret;
+ if (!value)
+ return -EINVAL;
mutex_lock(&codec->cache_rw_mutex);
-
- if (value && codec->cache_ops && codec->cache_ops->read) {
- ret = codec->cache_ops->read(codec, reg, value);
- mutex_unlock(&codec->cache_rw_mutex);
- return ret;
- }
-
+ *value = snd_soc_get_cache_val(codec->reg_cache, reg,
+ codec->driver->reg_word_size);
mutex_unlock(&codec->cache_rw_mutex);
- return -ENOSYS;
+
+ return 0;
}
EXPORT_SYMBOL_GPL(snd_soc_cache_read);
@@ -223,20 +133,42 @@ EXPORT_SYMBOL_GPL(snd_soc_cache_read);
int snd_soc_cache_write(struct snd_soc_codec *codec,
unsigned int reg, unsigned int value)
{
+ mutex_lock(&codec->cache_rw_mutex);
+ snd_soc_set_cache_val(codec->reg_cache, reg, value,
+ codec->driver->reg_word_size);
+ mutex_unlock(&codec->cache_rw_mutex);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(snd_soc_cache_write);
+
+static int snd_soc_flat_cache_sync(struct snd_soc_codec *codec)
+{
+ int i;
int ret;
+ const struct snd_soc_codec_driver *codec_drv;
+ unsigned int val;
- mutex_lock(&codec->cache_rw_mutex);
+ codec_drv = codec->driver;
+ for (i = 0; i < codec_drv->reg_cache_size; ++i) {
+ ret = snd_soc_cache_read(codec, i, &val);
+ if (ret)
+ return ret;
+ if (codec_drv->reg_cache_default)
+ if (snd_soc_get_cache_val(codec_drv->reg_cache_default,
+ i, codec_drv->reg_word_size) == val)
+ continue;
- if (codec->cache_ops && codec->cache_ops->write) {
- ret = codec->cache_ops->write(codec, reg, value);
- mutex_unlock(&codec->cache_rw_mutex);
- return ret;
- }
+ WARN_ON(!snd_soc_codec_writable_register(codec, i));
- mutex_unlock(&codec->cache_rw_mutex);
- return -ENOSYS;
+ ret = snd_soc_write(codec, i, val);
+ if (ret)
+ return ret;
+ dev_dbg(codec->dev, "ASoC: Synced register %#x, value = %#x\n",
+ i, val);
+ }
+ return 0;
}
-EXPORT_SYMBOL_GPL(snd_soc_cache_write);
/**
* snd_soc_cache_sync: Sync the register cache with the hardware.
@@ -249,92 +181,19 @@ EXPORT_SYMBOL_GPL(snd_soc_cache_write);
*/
int snd_soc_cache_sync(struct snd_soc_codec *codec)
{
+ const char *name = "flat";
int ret;
- const char *name;
- if (!codec->cache_sync) {
+ if (!codec->cache_sync)
return 0;
- }
-
- if (!codec->cache_ops || !codec->cache_ops->sync)
- return -ENOSYS;
- if (codec->cache_ops->name)
- name = codec->cache_ops->name;
- else
- name = "unknown";
-
- if (codec->cache_ops->name)
- dev_dbg(codec->dev, "ASoC: Syncing %s cache for %s codec\n",
- codec->cache_ops->name, codec->name);
+ dev_dbg(codec->dev, "ASoC: Syncing cache for %s codec\n",
+ codec->name);
trace_snd_soc_cache_sync(codec, name, "start");
- ret = codec->cache_ops->sync(codec);
+ ret = snd_soc_flat_cache_sync(codec);
if (!ret)
codec->cache_sync = 0;
trace_snd_soc_cache_sync(codec, name, "end");
return ret;
}
EXPORT_SYMBOL_GPL(snd_soc_cache_sync);
-
-static int snd_soc_get_reg_access_index(struct snd_soc_codec *codec,
- unsigned int reg)
-{
- const struct snd_soc_codec_driver *codec_drv;
- unsigned int min, max, index;
-
- codec_drv = codec->driver;
- min = 0;
- max = codec_drv->reg_access_size - 1;
- do {
- index = (min + max) / 2;
- if (codec_drv->reg_access_default[index].reg == reg)
- return index;
- if (codec_drv->reg_access_default[index].reg < reg)
- min = index + 1;
- else
- max = index;
- } while (min <= max);
- return -1;
-}
-
-int snd_soc_default_volatile_register(struct snd_soc_codec *codec,
- unsigned int reg)
-{
- int index;
-
- if (reg >= codec->driver->reg_cache_size)
- return 1;
- index = snd_soc_get_reg_access_index(codec, reg);
- if (index < 0)
- return 0;
- return codec->driver->reg_access_default[index].vol;
-}
-EXPORT_SYMBOL_GPL(snd_soc_default_volatile_register);
-
-int snd_soc_default_readable_register(struct snd_soc_codec *codec,
- unsigned int reg)
-{
- int index;
-
- if (reg >= codec->driver->reg_cache_size)
- return 1;
- index = snd_soc_get_reg_access_index(codec, reg);
- if (index < 0)
- return 0;
- return codec->driver->reg_access_default[index].read;
-}
-EXPORT_SYMBOL_GPL(snd_soc_default_readable_register);
-
-int snd_soc_default_writable_register(struct snd_soc_codec *codec,
- unsigned int reg)
-{
- int index;
-
- if (reg >= codec->driver->reg_cache_size)
- return 1;
- index = snd_soc_get_reg_access_index(codec, reg);
- if (index < 0)
- return 0;
- return codec->driver->reg_access_default[index].write;
-}
-EXPORT_SYMBOL_GPL(snd_soc_default_writable_register);
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index b1c472fde84b..afc3fa8b7470 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -1589,17 +1589,13 @@ static void soc_remove_aux_dev(struct snd_soc_card *card, int num)
soc_remove_codec(codec);
}
-static int snd_soc_init_codec_cache(struct snd_soc_codec *codec,
- enum snd_soc_compress_type compress_type)
+static int snd_soc_init_codec_cache(struct snd_soc_codec *codec)
{
int ret;
if (codec->cache_init)
return 0;
- /* override the compress_type if necessary */
- if (compress_type && codec->compress_type != compress_type)
- codec->compress_type = compress_type;
ret = snd_soc_cache_init(codec);
if (ret < 0) {
dev_err(codec->dev,
@@ -1614,8 +1610,6 @@ static int snd_soc_init_codec_cache(struct snd_soc_codec *codec,
static int snd_soc_instantiate_card(struct snd_soc_card *card)
{
struct snd_soc_codec *codec;
- struct snd_soc_codec_conf *codec_conf;
- enum snd_soc_compress_type compress_type;
struct snd_soc_dai_link *dai_link;
int ret, i, order, dai_fmt;
@@ -1639,19 +1633,7 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card)
list_for_each_entry(codec, &codec_list, list) {
if (codec->cache_init)
continue;
- /* by default we don't override the compress_type */
- compress_type = 0;
- /* check to see if we need to override the compress_type */
- for (i = 0; i < card->num_configs; ++i) {
- codec_conf = &card->codec_conf[i];
- if (!strcmp(codec->name, codec_conf->dev_name)) {
- compress_type = codec_conf->compress_type;
- if (compress_type && compress_type
- != codec->compress_type)
- break;
- }
- }
- ret = snd_soc_init_codec_cache(codec, compress_type);
+ ret = snd_soc_init_codec_cache(codec);
if (ret < 0)
goto base_error;
}
@@ -2297,13 +2279,6 @@ 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
@@ -4063,6 +4038,7 @@ __snd_soc_register_component(struct device *dev,
cmpnt->dev = dev;
cmpnt->driver = cmpnt_drv;
+ cmpnt->dai_drv = dai_drv;
cmpnt->num_dai = num_dai;
/*
@@ -4287,7 +4263,6 @@ int snd_soc_register_codec(struct device *dev,
struct snd_soc_dai_driver *dai_drv,
int num_dai)
{
- size_t reg_size;
struct snd_soc_codec *codec;
int ret, i;
@@ -4304,11 +4279,6 @@ int snd_soc_register_codec(struct device *dev,
goto fail_codec;
}
- if (codec_drv->compress_type)
- codec->compress_type = codec_drv->compress_type;
- else
- codec->compress_type = SND_SOC_FLAT_COMPRESSION;
-
codec->write = codec_drv->write;
codec->read = codec_drv->read;
codec->volatile_register = codec_drv->volatile_register;
@@ -4325,35 +4295,6 @@ int snd_soc_register_codec(struct device *dev,
codec->num_dai = num_dai;
mutex_init(&codec->mutex);
- /* allocate CODEC register cache */
- if (codec_drv->reg_cache_size && codec_drv->reg_word_size) {
- reg_size = codec_drv->reg_cache_size * codec_drv->reg_word_size;
- codec->reg_size = reg_size;
- /* it is necessary to make a copy of the default register cache
- * because in the case of using a compression type that requires
- * the default register cache to be marked as the
- * kernel might have freed the array by the time we initialize
- * the cache.
- */
- if (codec_drv->reg_cache_default) {
- codec->reg_def_copy = kmemdup(codec_drv->reg_cache_default,
- reg_size, GFP_KERNEL);
- if (!codec->reg_def_copy) {
- ret = -ENOMEM;
- goto fail_codec_name;
- }
- }
- }
-
- if (codec_drv->reg_access_size && codec_drv->reg_access_default) {
- if (!codec->volatile_register)
- codec->volatile_register = snd_soc_default_volatile_register;
- if (!codec->readable_register)
- codec->readable_register = snd_soc_default_readable_register;
- if (!codec->writable_register)
- codec->writable_register = snd_soc_default_writable_register;
- }
-
for (i = 0; i < num_dai; i++) {
fixup_codec_formats(&dai_drv[i].playback);
fixup_codec_formats(&dai_drv[i].capture);
@@ -4412,7 +4353,6 @@ found:
dev_dbg(codec->dev, "ASoC: Unregistered codec '%s'\n", codec->name);
snd_soc_cache_exit(codec);
- kfree(codec->reg_def_copy);
kfree(codec->name);
kfree(codec);
}
@@ -4624,12 +4564,31 @@ int snd_soc_of_get_dai_name(struct device_node *of_node,
if (pos->dev->of_node != args.np)
continue;
- if (!pos->driver->of_xlate_dai_name) {
- ret = -ENOSYS;
- break;
+ if (pos->driver->of_xlate_dai_name) {
+ ret = pos->driver->of_xlate_dai_name(pos, &args, dai_name);
+ } else {
+ int id = -1;
+
+ switch (args.args_count) {
+ case 0:
+ id = 0; /* same as dai_drv[0] */
+ break;
+ case 1:
+ id = args.args[0];
+ break;
+ default:
+ /* not supported */
+ break;
+ }
+
+ if (id < 0 || id >= pos->num_dai) {
+ ret = -EINVAL;
+ } else {
+ *dai_name = pos->dai_drv[id].name;
+ ret = 0;
+ }
}
- ret = pos->driver->of_xlate_dai_name(pos, &args, dai_name);
break;
}
mutex_unlock(&client_mutex);
diff --git a/sound/soc/soc-io.c b/sound/soc/soc-io.c
index 122c0c18b9dd..4f11d23f2062 100644
--- a/sound/soc/soc-io.c
+++ b/sound/soc/soc-io.c
@@ -65,31 +65,6 @@ static unsigned int hw_read(struct snd_soc_codec *codec, unsigned int reg)
return val;
}
-/* Primitive bulk write support for soc-cache. The data pointed to by
- * `data' needs to already be in the form the hardware expects. Any
- * data written through this function will not go through the cache as
- * it only handles writing to volatile or out of bounds registers.
- *
- * This is currently only supported for devices using the regmap API
- * wrappers.
- */
-static int snd_soc_hw_bulk_write_raw(struct snd_soc_codec *codec,
- unsigned int reg,
- const void *data, size_t len)
-{
- /* To ensure that we don't get out of sync with the cache, check
- * whether the base register is volatile or if we've directly asked
- * to bypass the cache. Out of bounds registers are considered
- * volatile.
- */
- if (!codec->cache_bypass
- && !snd_soc_codec_volatile_register(codec, reg)
- && reg < codec->driver->reg_cache_size)
- return -EINVAL;
-
- return regmap_raw_write(codec->control_data, reg, data, len);
-}
-
/**
* snd_soc_codec_set_cache_io: Set up standard I/O functions.
*
@@ -119,7 +94,6 @@ int snd_soc_codec_set_cache_io(struct snd_soc_codec *codec,
memset(&config, 0, sizeof(config));
codec->write = hw_write;
codec->read = hw_read;
- codec->bulk_write_raw = snd_soc_hw_bulk_write_raw;
config.reg_bits = addr_bits;
config.val_bits = data_bits;
diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c
index 330c9a6b5cb5..d4498723b375 100644
--- a/sound/soc/soc-pcm.c
+++ b/sound/soc/soc-pcm.c
@@ -721,7 +721,7 @@ static int dpcm_be_connect(struct snd_soc_pcm_runtime *fe,
list_add(&dpcm->list_be, &fe->dpcm[stream].be_clients);
list_add(&dpcm->list_fe, &be->dpcm[stream].fe_clients);
- dev_dbg(fe->dev, " connected new DPCM %s path %s %s %s\n",
+ dev_dbg(fe->dev, "connected new DPCM %s path %s %s %s\n",
stream ? "capture" : "playback", fe->dai_link->name,
stream ? "<-" : "->", be->dai_link->name);
@@ -749,7 +749,7 @@ static void dpcm_be_reparent(struct snd_soc_pcm_runtime *fe,
if (dpcm->fe == fe)
continue;
- dev_dbg(fe->dev, " reparent %s path %s %s %s\n",
+ dev_dbg(fe->dev, "reparent %s path %s %s %s\n",
stream ? "capture" : "playback",
dpcm->fe->dai_link->name,
stream ? "<-" : "->", dpcm->be->dai_link->name);
@@ -773,7 +773,7 @@ static void dpcm_be_disconnect(struct snd_soc_pcm_runtime *fe, int stream)
if (dpcm->state != SND_SOC_DPCM_LINK_STATE_FREE)
continue;
- dev_dbg(fe->dev, " freed DSP %s path %s %s %s\n",
+ dev_dbg(fe->dev, "freed DSP %s path %s %s %s\n",
stream ? "capture" : "playback", fe->dai_link->name,
stream ? "<-" : "->", dpcm->be->dai_link->name);
@@ -2116,7 +2116,7 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num)
pcm->private_free = platform->driver->pcm_free;
out:
- dev_info(rtd->card->dev, " %s <-> %s mapping ok\n", codec_dai->name,
+ dev_info(rtd->card->dev, "%s <-> %s mapping ok\n", codec_dai->name,
cpu_dai->name);
return ret;
}
diff --git a/sound/soc/soc-utils.c b/sound/soc/soc-utils.c
index 29b211e9c060..5e633659c1b3 100644
--- a/sound/soc/soc-utils.c
+++ b/sound/soc/soc-utils.c
@@ -75,7 +75,11 @@ static const struct snd_pcm_hardware dummy_dma_hardware = {
static int dummy_dma_open(struct snd_pcm_substream *substream)
{
- snd_soc_set_runtime_hwparams(substream, &dummy_dma_hardware);
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+
+ /* BE's dont need dummy params */
+ if (!rtd->dai_link->no_pcm)
+ snd_soc_set_runtime_hwparams(substream, &dummy_dma_hardware);
return 0;
}