1. 注册codec时添加reg cache
static struct snd_soc_codec_driver soc_codec_driver = {
......
.reg_cache_size = MSM8X16_WCD_CACHE_SIZE,
.reg_cache_default = msm8x16_wcd_reset_reg_defaults,
.reg_word_size = 1,
......
};
static int msm8x16_wcd_spmi_probe(struct spmi_device *spmi)
{
......
ret = snd_soc_register_codec(&spmi->dev, &soc_codec_driver,
msm8x16_wcd_i2s_dai,
ARRAY_SIZE(msm8x16_wcd_i2s_dai));
......
}
int snd_soc_register_codec(struct device *dev,
const struct snd_soc_codec_driver *codec_drv,
struct snd_soc_dai_driver *dai_drv,
int num_dai)
{
......
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; //得到codec的cache大小并保存在codec->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) {
//将reg cache保存在codec->reg_def_copy中
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;
}
}
}
......
}
2. 注册声卡时为codec初始化reg cache
static int snd_soc_instantiate_card(struct snd_soc_card *card)
{
......
/* initialize the register cache for each available codec */
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);
if (ret < 0)
goto base_error;
}
......
}
static int snd_soc_init_codec_cache(struct snd_soc_codec *codec,
enum snd_soc_compress_type compress_type)
{
int ret;
/* 如果cache已完成初始化,返回 */
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);
......
/* 标记codec的cache已初始化好 */
codec->cache_init = 1;
return 0;
}
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]; //初始化codec的cache_ops
if (codec->cache_ops->init) {
/* snd_soc_flat_cache_init() */
return codec->cache_ops->init(codec);
}
return -ENOSYS;
}
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); //从codec->reg_def_copy复制一份cache保存在codec->reg_cache中
else
codec->reg_cache = kzalloc(codec->reg_size, GFP_KERNEL);
if (!codec->reg_cache)
return -ENOMEM;
return 0;
}
浙公网安备 33010602011771号