Commit 7a30a3db authored by Dimitris Papastamos's avatar Dimitris Papastamos Committed by Mark Brown

ASoC: soc-cache: Add support for flat register caching

This patch introduces the new caching API and migrates the
old caching interface into the new one.  The flat register caching
technique does not use compression at all and it is equivalent to
the old caching technique.  One can still access codec->reg_cache
directly but this is not advised as that will not be portable
across different caching strategies.

None of the existing drivers need to be changed to adapt to this
caching technique.  There should be no noticeable overhead associated
with using the new caching API.
Signed-off-by: default avatarDimitris Papastamos <dp@opensource.wolfsonmicro.com>
Acked-by: default avatarLiam Girdwood <lrg@slimlogic.co.uk>
Signed-off-by: default avatarMark Brown <broonie@opensource.wolfsonmicro.com>
parent 84e90930
...@@ -238,6 +238,7 @@ struct soc_enum; ...@@ -238,6 +238,7 @@ struct soc_enum;
struct snd_soc_ac97_ops; struct snd_soc_ac97_ops;
struct snd_soc_jack; struct snd_soc_jack;
struct snd_soc_jack_pin; struct snd_soc_jack_pin;
struct snd_soc_cache_ops;
#include <sound/soc-dapm.h> #include <sound/soc-dapm.h>
#ifdef CONFIG_GPIOLIB #ifdef CONFIG_GPIOLIB
...@@ -254,6 +255,10 @@ enum snd_soc_control_type { ...@@ -254,6 +255,10 @@ enum snd_soc_control_type {
SND_SOC_SPI, SND_SOC_SPI,
}; };
enum snd_soc_compress_type {
SND_SOC_NO_COMPRESSION
};
int snd_soc_register_platform(struct device *dev, int snd_soc_register_platform(struct device *dev,
struct snd_soc_platform_driver *platform_drv); struct snd_soc_platform_driver *platform_drv);
void snd_soc_unregister_platform(struct device *dev); void snd_soc_unregister_platform(struct device *dev);
...@@ -265,6 +270,13 @@ int snd_soc_codec_volatile_register(struct snd_soc_codec *codec, int reg); ...@@ -265,6 +270,13 @@ int snd_soc_codec_volatile_register(struct snd_soc_codec *codec, int reg);
int snd_soc_codec_set_cache_io(struct snd_soc_codec *codec, int snd_soc_codec_set_cache_io(struct snd_soc_codec *codec,
int addr_bits, int data_bits, int addr_bits, int data_bits,
enum snd_soc_control_type control); enum snd_soc_control_type control);
int snd_soc_cache_sync(struct snd_soc_codec *codec);
int snd_soc_cache_init(struct snd_soc_codec *codec);
int snd_soc_cache_exit(struct snd_soc_codec *codec);
int snd_soc_cache_write(struct snd_soc_codec *codec,
unsigned int reg, unsigned int value);
int snd_soc_cache_read(struct snd_soc_codec *codec,
unsigned int reg, unsigned int *value);
/* Utility functions to get clock rates from various things */ /* Utility functions to get clock rates from various things */
int snd_soc_calc_frame_size(int sample_size, int channels, int tdm_slots); int snd_soc_calc_frame_size(int sample_size, int channels, int tdm_slots);
...@@ -421,6 +433,18 @@ struct snd_soc_ops { ...@@ -421,6 +433,18 @@ struct snd_soc_ops {
int (*trigger)(struct snd_pcm_substream *, int); int (*trigger)(struct snd_pcm_substream *, int);
}; };
/* SoC cache ops */
struct snd_soc_cache_ops {
enum snd_soc_compress_type id;
int (*init)(struct snd_soc_codec *codec);
int (*exit)(struct snd_soc_codec *codec);
int (*read)(struct snd_soc_codec *codec, unsigned int reg,
unsigned int *value);
int (*write)(struct snd_soc_codec *codec, unsigned int reg,
unsigned int value);
int (*sync)(struct snd_soc_codec *codec);
};
/* SoC Audio Codec device */ /* SoC Audio Codec device */
struct snd_soc_codec { struct snd_soc_codec {
const char *name; const char *name;
...@@ -450,6 +474,8 @@ struct snd_soc_codec { ...@@ -450,6 +474,8 @@ struct snd_soc_codec {
hw_write_t hw_write; hw_write_t hw_write;
unsigned int (*hw_read)(struct snd_soc_codec *, unsigned int); unsigned int (*hw_read)(struct snd_soc_codec *, unsigned int);
void *reg_cache; void *reg_cache;
const struct snd_soc_cache_ops *cache_ops;
struct mutex cache_rw_mutex;
/* dapm */ /* dapm */
struct snd_soc_dapm_context dapm; struct snd_soc_dapm_context dapm;
...@@ -482,6 +508,7 @@ struct snd_soc_codec_driver { ...@@ -482,6 +508,7 @@ struct snd_soc_codec_driver {
short reg_cache_step; short reg_cache_step;
short reg_word_size; short reg_word_size;
const void *reg_cache_default; const void *reg_cache_default;
enum snd_soc_compress_type compress_type;
/* codec bias level */ /* codec bias level */
int (*set_bias_level)(struct snd_soc_codec *, int (*set_bias_level)(struct snd_soc_codec *,
......
This diff is collapsed.
...@@ -3279,29 +3279,21 @@ int snd_soc_register_codec(struct device *dev, ...@@ -3279,29 +3279,21 @@ int snd_soc_register_codec(struct device *dev,
codec->dapm.bias_level = SND_SOC_BIAS_OFF; codec->dapm.bias_level = SND_SOC_BIAS_OFF;
codec->dapm.dev = dev; codec->dapm.dev = dev;
codec->dapm.codec = codec; codec->dapm.codec = codec;
codec->dev = dev;
codec->driver = codec_drv;
codec->num_dai = num_dai;
mutex_init(&codec->mutex);
/* allocate CODEC register cache */ /* allocate CODEC register cache */
if (codec_drv->reg_cache_size && codec_drv->reg_word_size) { if (codec_drv->reg_cache_size && codec_drv->reg_word_size) {
ret = snd_soc_cache_init(codec);
if (codec_drv->reg_cache_default) if (ret < 0) {
codec->reg_cache = kmemdup(codec_drv->reg_cache_default, dev_err(codec->dev, "Failed to set cache compression type: %d\n",
codec_drv->reg_cache_size * codec_drv->reg_word_size, GFP_KERNEL); ret);
else goto error_cache;
codec->reg_cache = kzalloc(codec_drv->reg_cache_size *
codec_drv->reg_word_size, GFP_KERNEL);
if (codec->reg_cache == NULL) {
kfree(codec->name);
kfree(codec);
return -ENOMEM;
} }
} }
codec->dev = dev;
codec->driver = codec_drv;
codec->num_dai = num_dai;
mutex_init(&codec->mutex);
for (i = 0; i < num_dai; i++) { for (i = 0; i < num_dai; i++) {
fixup_codec_formats(&dai_drv[i].playback); fixup_codec_formats(&dai_drv[i].playback);
fixup_codec_formats(&dai_drv[i].capture); fixup_codec_formats(&dai_drv[i].capture);
...@@ -3311,7 +3303,7 @@ int snd_soc_register_codec(struct device *dev, ...@@ -3311,7 +3303,7 @@ int snd_soc_register_codec(struct device *dev,
if (num_dai) { if (num_dai) {
ret = snd_soc_register_dais(dev, dai_drv, num_dai); ret = snd_soc_register_dais(dev, dai_drv, num_dai);
if (ret < 0) if (ret < 0)
goto error; goto error_dais;
} }
mutex_lock(&client_mutex); mutex_lock(&client_mutex);
...@@ -3322,9 +3314,9 @@ int snd_soc_register_codec(struct device *dev, ...@@ -3322,9 +3314,9 @@ int snd_soc_register_codec(struct device *dev,
pr_debug("Registered codec '%s'\n", codec->name); pr_debug("Registered codec '%s'\n", codec->name);
return 0; return 0;
error: error_dais:
if (codec->reg_cache) snd_soc_cache_exit(codec);
kfree(codec->reg_cache); error_cache:
kfree(codec->name); kfree(codec->name);
kfree(codec); kfree(codec);
return ret; return ret;
...@@ -3358,8 +3350,7 @@ void snd_soc_unregister_codec(struct device *dev) ...@@ -3358,8 +3350,7 @@ void snd_soc_unregister_codec(struct device *dev)
pr_debug("Unregistered codec '%s'\n", codec->name); pr_debug("Unregistered codec '%s'\n", codec->name);
if (codec->reg_cache) snd_soc_cache_exit(codec);
kfree(codec->reg_cache);
kfree(codec->name); kfree(codec->name);
kfree(codec); kfree(codec);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment