aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/sound/soc.h1
-rw-r--r--sound/soc/soc-cache.c36
-rw-r--r--sound/soc/soc-core.c17
3 files changed, 42 insertions, 12 deletions
diff --git a/include/sound/soc.h b/include/sound/soc.h
index cf76021f04a7..017986159d5e 100644
--- a/include/sound/soc.h
+++ b/include/sound/soc.h
@@ -480,6 +480,7 @@ struct snd_soc_codec {
480 unsigned int (*read)(struct snd_soc_codec *, unsigned int); 480 unsigned int (*read)(struct snd_soc_codec *, unsigned int);
481 int (*write)(struct snd_soc_codec *, unsigned int, unsigned int); 481 int (*write)(struct snd_soc_codec *, unsigned int, unsigned int);
482 void *reg_cache; 482 void *reg_cache;
483 const void *reg_def_copy;
483 const struct snd_soc_cache_ops *cache_ops; 484 const struct snd_soc_cache_ops *cache_ops;
484 struct mutex cache_rw_mutex; 485 struct mutex cache_rw_mutex;
485 486
diff --git a/sound/soc/soc-cache.c b/sound/soc/soc-cache.c
index cb58b11d4f47..6c6ced7a3819 100644
--- a/sound/soc/soc-cache.c
+++ b/sound/soc/soc-cache.c
@@ -933,7 +933,7 @@ static int snd_soc_rbtree_cache_init(struct snd_soc_codec *codec)
933 rbtree_ctx = codec->reg_cache; 933 rbtree_ctx = codec->reg_cache;
934 rbtree_ctx->root = RB_ROOT; 934 rbtree_ctx->root = RB_ROOT;
935 935
936 if (!codec->driver->reg_cache_default) 936 if (!codec->reg_def_copy)
937 return 0; 937 return 0;
938 938
939/* 939/*
@@ -951,7 +951,7 @@ static int snd_soc_rbtree_cache_init(struct snd_soc_codec *codec)
951 struct snd_soc_rbtree_node *rbtree_node; \ 951 struct snd_soc_rbtree_node *rbtree_node; \
952 \ 952 \
953 ret = 0; \ 953 ret = 0; \
954 cache = codec->driver->reg_cache_default; \ 954 cache = codec->reg_def_copy; \
955 for (i = 0; i < codec->driver->reg_cache_size; ++i) { \ 955 for (i = 0; i < codec->driver->reg_cache_size; ++i) { \
956 if (!cache[i]) \ 956 if (!cache[i]) \
957 continue; \ 957 continue; \
@@ -1316,13 +1316,13 @@ static int snd_soc_lzo_cache_init(struct snd_soc_codec *codec)
1316 * and remember to free it afterwards. 1316 * and remember to free it afterwards.
1317 */ 1317 */
1318 tofree = 0; 1318 tofree = 0;
1319 if (!codec_drv->reg_cache_default) 1319 if (!codec->reg_def_copy)
1320 tofree = 1; 1320 tofree = 1;
1321 1321
1322 if (!codec_drv->reg_cache_default) { 1322 if (!codec->reg_def_copy) {
1323 codec_drv->reg_cache_default = kzalloc(reg_size, 1323 codec->reg_def_copy = kzalloc(reg_size,
1324 GFP_KERNEL); 1324 GFP_KERNEL);
1325 if (!codec_drv->reg_cache_default) 1325 if (!codec->reg_def_copy)
1326 return -ENOMEM; 1326 return -ENOMEM;
1327 } 1327 }
1328 1328
@@ -1368,8 +1368,8 @@ static int snd_soc_lzo_cache_init(struct snd_soc_codec *codec)
1368 } 1368 }
1369 1369
1370 blksize = snd_soc_lzo_get_blksize(codec); 1370 blksize = snd_soc_lzo_get_blksize(codec);
1371 p = codec_drv->reg_cache_default; 1371 p = codec->reg_def_copy;
1372 end = codec_drv->reg_cache_default + reg_size; 1372 end = codec->reg_def_copy + reg_size;
1373 /* compress the register map and fill the lzo blocks */ 1373 /* compress the register map and fill the lzo blocks */
1374 for (i = 0; i < blkcount; ++i, p += blksize) { 1374 for (i = 0; i < blkcount; ++i, p += blksize) {
1375 lzo_blocks[i]->src = p; 1375 lzo_blocks[i]->src = p;
@@ -1385,14 +1385,18 @@ static int snd_soc_lzo_cache_init(struct snd_soc_codec *codec)
1385 lzo_blocks[i]->src_len; 1385 lzo_blocks[i]->src_len;
1386 } 1386 }
1387 1387
1388 if (tofree) 1388 if (tofree) {
1389 kfree(codec_drv->reg_cache_default); 1389 kfree(codec->reg_def_copy);
1390 codec->reg_def_copy = NULL;
1391 }
1390 return 0; 1392 return 0;
1391err: 1393err:
1392 snd_soc_cache_exit(codec); 1394 snd_soc_cache_exit(codec);
1393err_tofree: 1395err_tofree:
1394 if (tofree) 1396 if (tofree) {
1395 kfree(codec_drv->reg_cache_default); 1397 kfree(codec->reg_def_copy);
1398 codec->reg_def_copy = NULL;
1399 }
1396 return ret; 1400 return ret;
1397} 1401}
1398 1402
@@ -1506,6 +1510,14 @@ static int snd_soc_flat_cache_init(struct snd_soc_codec *codec)
1506 codec_drv = codec->driver; 1510 codec_drv = codec->driver;
1507 reg_size = codec_drv->reg_cache_size * codec_drv->reg_word_size; 1511 reg_size = codec_drv->reg_cache_size * codec_drv->reg_word_size;
1508 1512
1513 /*
1514 * for flat compression, we don't need to keep a copy of the
1515 * original defaults register cache as it will definitely not
1516 * be marked as __devinitconst
1517 */
1518 kfree(codec->reg_def_copy);
1519 codec->reg_def_copy = NULL;
1520
1509 if (codec_drv->reg_cache_default) 1521 if (codec_drv->reg_cache_default)
1510 codec->reg_cache = kmemdup(codec_drv->reg_cache_default, 1522 codec->reg_cache = kmemdup(codec_drv->reg_cache_default,
1511 reg_size, GFP_KERNEL); 1523 reg_size, GFP_KERNEL);
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index 4649db6163b8..a95d111a6531 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -3434,6 +3434,7 @@ int snd_soc_register_codec(struct device *dev,
3434 struct snd_soc_codec_driver *codec_drv, 3434 struct snd_soc_codec_driver *codec_drv,
3435 struct snd_soc_dai_driver *dai_drv, int num_dai) 3435 struct snd_soc_dai_driver *dai_drv, int num_dai)
3436{ 3436{
3437 size_t reg_size;
3437 struct snd_soc_codec *codec; 3438 struct snd_soc_codec *codec;
3438 int ret, i; 3439 int ret, i;
3439 3440
@@ -3469,6 +3470,19 @@ int snd_soc_register_codec(struct device *dev,
3469 3470
3470 /* allocate CODEC register cache */ 3471 /* allocate CODEC register cache */
3471 if (codec_drv->reg_cache_size && codec_drv->reg_word_size) { 3472 if (codec_drv->reg_cache_size && codec_drv->reg_word_size) {
3473 reg_size = codec_drv->reg_cache_size * codec_drv->reg_word_size;
3474 /* it is necessary to make a copy of the default register cache
3475 * because in the case of using a compression type that requires
3476 * the default register cache to be marked as __devinitconst the
3477 * kernel might have freed the array by the time we initialize
3478 * the cache.
3479 */
3480 codec->reg_def_copy = kmemdup(codec_drv->reg_cache_default,
3481 reg_size, GFP_KERNEL);
3482 if (!codec->reg_def_copy) {
3483 ret = -ENOMEM;
3484 goto error_cache;
3485 }
3472 ret = snd_soc_cache_init(codec); 3486 ret = snd_soc_cache_init(codec);
3473 if (ret < 0) { 3487 if (ret < 0) {
3474 dev_err(codec->dev, "Failed to set cache compression type: %d\n", 3488 dev_err(codec->dev, "Failed to set cache compression type: %d\n",
@@ -3500,6 +3514,8 @@ int snd_soc_register_codec(struct device *dev,
3500error_dais: 3514error_dais:
3501 snd_soc_cache_exit(codec); 3515 snd_soc_cache_exit(codec);
3502error_cache: 3516error_cache:
3517 kfree(codec->reg_def_copy);
3518 codec->reg_def_copy = NULL;
3503 kfree(codec->name); 3519 kfree(codec->name);
3504 kfree(codec); 3520 kfree(codec);
3505 return ret; 3521 return ret;
@@ -3534,6 +3550,7 @@ found:
3534 pr_debug("Unregistered codec '%s'\n", codec->name); 3550 pr_debug("Unregistered codec '%s'\n", codec->name);
3535 3551
3536 snd_soc_cache_exit(codec); 3552 snd_soc_cache_exit(codec);
3553 kfree(codec->reg_def_copy);
3537 kfree(codec->name); 3554 kfree(codec->name);
3538 kfree(codec); 3555 kfree(codec);
3539} 3556}