diff options
-rw-r--r-- | include/sound/soc.h | 1 | ||||
-rw-r--r-- | sound/soc/soc-cache.c | 36 | ||||
-rw-r--r-- | sound/soc/soc-core.c | 17 |
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; |
1391 | err: | 1393 | err: |
1392 | snd_soc_cache_exit(codec); | 1394 | snd_soc_cache_exit(codec); |
1393 | err_tofree: | 1395 | err_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, | |||
3500 | error_dais: | 3514 | error_dais: |
3501 | snd_soc_cache_exit(codec); | 3515 | snd_soc_cache_exit(codec); |
3502 | error_cache: | 3516 | error_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 | } |