ASoC: soc-cache: Use reg_def_copy instead of reg_cache_default

Make sure to use codec->reg_def_copy instead of codec_drv->reg_cache_default
wherever necessary.  This change is necessary because in the next patch we
move the cache initialization code outside snd_soc_register_codec() and by that
time any data marked as __devinitconst such as the original reg_cache_default
array might have already been freed by the kernel.

Signed-off-by: Dimitris Papastamos <dp@opensource.wolfsonmicro.com>
Acked-by: Liam Girdwood <lrg@slimlogic.co.uk>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index 4649db6..a95d111 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -3434,6 +3434,7 @@
 		struct snd_soc_codec_driver *codec_drv,
 		struct snd_soc_dai_driver *dai_drv, int num_dai)
 {
+	size_t reg_size;
 	struct snd_soc_codec *codec;
 	int ret, i;
 
@@ -3469,6 +3470,19 @@
 
 	/* 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;
+		/* 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 __devinitconst the
+		 * kernel might have freed the array by the time we initialize
+		 * the cache.
+		 */
+		codec->reg_def_copy = kmemdup(codec_drv->reg_cache_default,
+					      reg_size, GFP_KERNEL);
+		if (!codec->reg_def_copy) {
+			ret = -ENOMEM;
+			goto error_cache;
+		}
 		ret = snd_soc_cache_init(codec);
 		if (ret < 0) {
 			dev_err(codec->dev, "Failed to set cache compression type: %d\n",
@@ -3500,6 +3514,8 @@
 error_dais:
 	snd_soc_cache_exit(codec);
 error_cache:
+	kfree(codec->reg_def_copy);
+	codec->reg_def_copy = NULL;
 	kfree(codec->name);
 	kfree(codec);
 	return ret;
@@ -3534,6 +3550,7 @@
 	pr_debug("Unregistered codec '%s'\n", codec->name);
 
 	snd_soc_cache_exit(codec);
+	kfree(codec->reg_def_copy);
 	kfree(codec->name);
 	kfree(codec);
 }