aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLars-Peter Clausen <lars@metafoo.de>2014-04-22 07:23:13 -0400
committerMark Brown <broonie@linaro.org>2014-04-22 08:23:35 -0400
commite2c330b9b5665006c99327c05bc22f7a8e471043 (patch)
tree2cee0640f32ee9ceeaeb3939ecad1fe127db9ba7
parent2b17ef4071d37ef5e357a4ec75686315cfa9d3e6 (diff)
ASoC: Move IO abstraction to the component level
We currently have two very similar IO abstractions in ASoC, one for CODECs, the other for platforms. Moving this to the component level will allow us to unify those two. It will also enable us to move the standard kcontrol helpers as well as DAPM support to the component level. The new component level abstraction layer is primarily build around regmap. There is a per component pointer for the regmap instance for the underlying device. There are four new function snd_soc_component_read(), snd_soc_component_write(), snd_soc_component_update_bits() and snd_soc_component_update_bits_async(). They have the same signature as their regmap counter-part and will internally forward the call one-to-one to regmap. If the component it not using regmap it will fallback to using the custom IO callbacks. This is done to be able to support drivers that haven't been converted to regmap yet, but it is expected that this will eventually be removed in the future once all component drivers have been converted to regmap. Signed-off-by: Lars-Peter Clausen <lars@metafoo.de> Signed-off-by: Mark Brown <broonie@linaro.org>
-rw-r--r--include/sound/soc-dapm.h1
-rw-r--r--include/sound/soc.h31
-rw-r--r--sound/soc/soc-core.c96
-rw-r--r--sound/soc/soc-dapm.c84
-rw-r--r--sound/soc/soc-io.c322
5 files changed, 317 insertions, 217 deletions
diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h
index ef78f562f4a8..75020f52acdd 100644
--- a/include/sound/soc-dapm.h
+++ b/include/sound/soc-dapm.h
@@ -606,6 +606,7 @@ struct snd_soc_dapm_context {
606 enum snd_soc_dapm_type, int); 606 enum snd_soc_dapm_type, int);
607 607
608 struct device *dev; /* from parent - for debug */ 608 struct device *dev; /* from parent - for debug */
609 struct snd_soc_component *component; /* parent component */
609 struct snd_soc_codec *codec; /* parent codec */ 610 struct snd_soc_codec *codec; /* parent codec */
610 struct snd_soc_platform *platform; /* parent platform */ 611 struct snd_soc_platform *platform; /* parent platform */
611 struct snd_soc_card *card; /* parent card */ 612 struct snd_soc_card *card; /* parent card */
diff --git a/include/sound/soc.h b/include/sound/soc.h
index 8148c98b5f8f..a4179e73369a 100644
--- a/include/sound/soc.h
+++ b/include/sound/soc.h
@@ -393,8 +393,6 @@ int devm_snd_soc_register_component(struct device *dev,
393 const struct snd_soc_component_driver *cmpnt_drv, 393 const struct snd_soc_component_driver *cmpnt_drv,
394 struct snd_soc_dai_driver *dai_drv, int num_dai); 394 struct snd_soc_dai_driver *dai_drv, int num_dai);
395void snd_soc_unregister_component(struct device *dev); 395void snd_soc_unregister_component(struct device *dev);
396int snd_soc_codec_set_cache_io(struct snd_soc_codec *codec,
397 struct regmap *regmap);
398int snd_soc_cache_sync(struct snd_soc_codec *codec); 396int snd_soc_cache_sync(struct snd_soc_codec *codec);
399int snd_soc_cache_init(struct snd_soc_codec *codec); 397int snd_soc_cache_init(struct snd_soc_codec *codec);
400int snd_soc_cache_exit(struct snd_soc_codec *codec); 398int snd_soc_cache_exit(struct snd_soc_codec *codec);
@@ -672,6 +670,14 @@ struct snd_soc_component {
672 const struct snd_soc_component_driver *driver; 670 const struct snd_soc_component_driver *driver;
673 671
674 struct list_head dai_list; 672 struct list_head dai_list;
673
674 int (*read)(struct snd_soc_component *, unsigned int, unsigned int *);
675 int (*write)(struct snd_soc_component *, unsigned int, unsigned int);
676
677 struct regmap *regmap;
678 int val_bytes;
679
680 struct mutex io_mutex;
675}; 681};
676 682
677/* SoC Audio Codec device */ 683/* SoC Audio Codec device */
@@ -696,18 +702,14 @@ struct snd_soc_codec {
696 unsigned int ac97_registered:1; /* Codec has been AC97 registered */ 702 unsigned int ac97_registered:1; /* Codec has been AC97 registered */
697 unsigned int ac97_created:1; /* Codec has been created by SoC */ 703 unsigned int ac97_created:1; /* Codec has been created by SoC */
698 unsigned int cache_init:1; /* codec cache has been initialized */ 704 unsigned int cache_init:1; /* codec cache has been initialized */
699 unsigned int using_regmap:1; /* using regmap access */
700 u32 cache_only; /* Suppress writes to hardware */ 705 u32 cache_only; /* Suppress writes to hardware */
701 u32 cache_sync; /* Cache needs to be synced to hardware */ 706 u32 cache_sync; /* Cache needs to be synced to hardware */
702 707
703 /* codec IO */ 708 /* codec IO */
704 void *control_data; /* codec control (i2c/3wire) data */ 709 void *control_data; /* codec control (i2c/3wire) data */
705 hw_write_t hw_write; 710 hw_write_t hw_write;
706 unsigned int (*read)(struct snd_soc_codec *, unsigned int);
707 int (*write)(struct snd_soc_codec *, unsigned int, unsigned int);
708 void *reg_cache; 711 void *reg_cache;
709 struct mutex cache_rw_mutex; 712 struct mutex cache_rw_mutex;
710 int val_bytes;
711 713
712 /* component */ 714 /* component */
713 struct snd_soc_component component; 715 struct snd_soc_component component;
@@ -824,7 +826,6 @@ struct snd_soc_platform {
824 int id; 826 int id;
825 struct device *dev; 827 struct device *dev;
826 const struct snd_soc_platform_driver *driver; 828 const struct snd_soc_platform_driver *driver;
827 struct mutex mutex;
828 829
829 unsigned int suspended:1; /* platform is suspended */ 830 unsigned int suspended:1; /* platform is suspended */
830 unsigned int probed:1; 831 unsigned int probed:1;
@@ -1129,6 +1130,22 @@ unsigned int snd_soc_read(struct snd_soc_codec *codec, unsigned int reg);
1129int snd_soc_write(struct snd_soc_codec *codec, unsigned int reg, 1130int snd_soc_write(struct snd_soc_codec *codec, unsigned int reg,
1130 unsigned int val); 1131 unsigned int val);
1131 1132
1133/* component IO */
1134int snd_soc_component_read(struct snd_soc_component *component,
1135 unsigned int reg, unsigned int *val);
1136int snd_soc_component_write(struct snd_soc_component *component,
1137 unsigned int reg, unsigned int val);
1138int snd_soc_component_update_bits(struct snd_soc_component *component,
1139 unsigned int reg, unsigned int mask, unsigned int val);
1140int snd_soc_component_update_bits_async(struct snd_soc_component *component,
1141 unsigned int reg, unsigned int mask, unsigned int val);
1142void snd_soc_component_async_complete(struct snd_soc_component *component);
1143int snd_soc_component_test_bits(struct snd_soc_component *component,
1144 unsigned int reg, unsigned int mask, unsigned int value);
1145
1146int snd_soc_component_init_io(struct snd_soc_component *component,
1147 struct regmap *regmap);
1148
1132/* device driver data */ 1149/* device driver data */
1133 1150
1134static inline void snd_soc_card_set_drvdata(struct snd_soc_card *card, 1151static inline void snd_soc_card_set_drvdata(struct snd_soc_card *card,
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index db577e4cdf49..f7eb21e70611 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -656,8 +656,8 @@ int snd_soc_suspend(struct device *dev)
656 codec->driver->suspend(codec); 656 codec->driver->suspend(codec);
657 codec->suspended = 1; 657 codec->suspended = 1;
658 codec->cache_sync = 1; 658 codec->cache_sync = 1;
659 if (codec->using_regmap) 659 if (codec->component.regmap)
660 regcache_mark_dirty(codec->control_data); 660 regcache_mark_dirty(codec->component.regmap);
661 /* deactivate pins to sleep state */ 661 /* deactivate pins to sleep state */
662 pinctrl_pm_select_sleep_state(codec->dev); 662 pinctrl_pm_select_sleep_state(codec->dev);
663 break; 663 break;
@@ -2971,7 +2971,7 @@ int snd_soc_bytes_info(struct snd_kcontrol *kcontrol,
2971 struct soc_bytes *params = (void *)kcontrol->private_value; 2971 struct soc_bytes *params = (void *)kcontrol->private_value;
2972 2972
2973 uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES; 2973 uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
2974 uinfo->count = params->num_regs * codec->val_bytes; 2974 uinfo->count = params->num_regs * codec->component.val_bytes;
2975 2975
2976 return 0; 2976 return 0;
2977} 2977}
@@ -2984,16 +2984,16 @@ int snd_soc_bytes_get(struct snd_kcontrol *kcontrol,
2984 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); 2984 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
2985 int ret; 2985 int ret;
2986 2986
2987 if (codec->using_regmap) 2987 if (codec->component.regmap)
2988 ret = regmap_raw_read(codec->control_data, params->base, 2988 ret = regmap_raw_read(codec->component.regmap, params->base,
2989 ucontrol->value.bytes.data, 2989 ucontrol->value.bytes.data,
2990 params->num_regs * codec->val_bytes); 2990 params->num_regs * codec->component.val_bytes);
2991 else 2991 else
2992 ret = -EINVAL; 2992 ret = -EINVAL;
2993 2993
2994 /* Hide any masked bytes to ensure consistent data reporting */ 2994 /* Hide any masked bytes to ensure consistent data reporting */
2995 if (ret == 0 && params->mask) { 2995 if (ret == 0 && params->mask) {
2996 switch (codec->val_bytes) { 2996 switch (codec->component.val_bytes) {
2997 case 1: 2997 case 1:
2998 ucontrol->value.bytes.data[0] &= ~params->mask; 2998 ucontrol->value.bytes.data[0] &= ~params->mask;
2999 break; 2999 break;
@@ -3023,10 +3023,10 @@ int snd_soc_bytes_put(struct snd_kcontrol *kcontrol,
3023 unsigned int val, mask; 3023 unsigned int val, mask;
3024 void *data; 3024 void *data;
3025 3025
3026 if (!codec->using_regmap) 3026 if (!codec->component.regmap)
3027 return -EINVAL; 3027 return -EINVAL;
3028 3028
3029 len = params->num_regs * codec->val_bytes; 3029 len = params->num_regs * codec->component.val_bytes;
3030 3030
3031 data = kmemdup(ucontrol->value.bytes.data, len, GFP_KERNEL | GFP_DMA); 3031 data = kmemdup(ucontrol->value.bytes.data, len, GFP_KERNEL | GFP_DMA);
3032 if (!data) 3032 if (!data)
@@ -3038,27 +3038,27 @@ int snd_soc_bytes_put(struct snd_kcontrol *kcontrol,
3038 * copy. 3038 * copy.
3039 */ 3039 */
3040 if (params->mask) { 3040 if (params->mask) {
3041 ret = regmap_read(codec->control_data, params->base, &val); 3041 ret = regmap_read(codec->component.regmap, params->base, &val);
3042 if (ret != 0) 3042 if (ret != 0)
3043 goto out; 3043 goto out;
3044 3044
3045 val &= params->mask; 3045 val &= params->mask;
3046 3046
3047 switch (codec->val_bytes) { 3047 switch (codec->component.val_bytes) {
3048 case 1: 3048 case 1:
3049 ((u8 *)data)[0] &= ~params->mask; 3049 ((u8 *)data)[0] &= ~params->mask;
3050 ((u8 *)data)[0] |= val; 3050 ((u8 *)data)[0] |= val;
3051 break; 3051 break;
3052 case 2: 3052 case 2:
3053 mask = ~params->mask; 3053 mask = ~params->mask;
3054 ret = regmap_parse_val(codec->control_data, 3054 ret = regmap_parse_val(codec->component.regmap,
3055 &mask, &mask); 3055 &mask, &mask);
3056 if (ret != 0) 3056 if (ret != 0)
3057 goto out; 3057 goto out;
3058 3058
3059 ((u16 *)data)[0] &= mask; 3059 ((u16 *)data)[0] &= mask;
3060 3060
3061 ret = regmap_parse_val(codec->control_data, 3061 ret = regmap_parse_val(codec->component.regmap,
3062 &val, &val); 3062 &val, &val);
3063 if (ret != 0) 3063 if (ret != 0)
3064 goto out; 3064 goto out;
@@ -3067,14 +3067,14 @@ int snd_soc_bytes_put(struct snd_kcontrol *kcontrol,
3067 break; 3067 break;
3068 case 4: 3068 case 4:
3069 mask = ~params->mask; 3069 mask = ~params->mask;
3070 ret = regmap_parse_val(codec->control_data, 3070 ret = regmap_parse_val(codec->component.regmap,
3071 &mask, &mask); 3071 &mask, &mask);
3072 if (ret != 0) 3072 if (ret != 0)
3073 goto out; 3073 goto out;
3074 3074
3075 ((u32 *)data)[0] &= mask; 3075 ((u32 *)data)[0] &= mask;
3076 3076
3077 ret = regmap_parse_val(codec->control_data, 3077 ret = regmap_parse_val(codec->component.regmap,
3078 &val, &val); 3078 &val, &val);
3079 if (ret != 0) 3079 if (ret != 0)
3080 goto out; 3080 goto out;
@@ -3087,7 +3087,7 @@ int snd_soc_bytes_put(struct snd_kcontrol *kcontrol,
3087 } 3087 }
3088 } 3088 }
3089 3089
3090 ret = regmap_raw_write(codec->control_data, params->base, 3090 ret = regmap_raw_write(codec->component.regmap, params->base,
3091 data, len); 3091 data, len);
3092 3092
3093out: 3093out:
@@ -3143,7 +3143,7 @@ int snd_soc_get_xr_sx(struct snd_kcontrol *kcontrol,
3143 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); 3143 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
3144 unsigned int regbase = mc->regbase; 3144 unsigned int regbase = mc->regbase;
3145 unsigned int regcount = mc->regcount; 3145 unsigned int regcount = mc->regcount;
3146 unsigned int regwshift = codec->val_bytes * BITS_PER_BYTE; 3146 unsigned int regwshift = codec->component.val_bytes * BITS_PER_BYTE;
3147 unsigned int regwmask = (1<<regwshift)-1; 3147 unsigned int regwmask = (1<<regwshift)-1;
3148 unsigned int invert = mc->invert; 3148 unsigned int invert = mc->invert;
3149 unsigned long mask = (1UL<<mc->nbits)-1; 3149 unsigned long mask = (1UL<<mc->nbits)-1;
@@ -3189,7 +3189,7 @@ int snd_soc_put_xr_sx(struct snd_kcontrol *kcontrol,
3189 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); 3189 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
3190 unsigned int regbase = mc->regbase; 3190 unsigned int regbase = mc->regbase;
3191 unsigned int regcount = mc->regcount; 3191 unsigned int regcount = mc->regcount;
3192 unsigned int regwshift = codec->val_bytes * BITS_PER_BYTE; 3192 unsigned int regwshift = codec->component.val_bytes * BITS_PER_BYTE;
3193 unsigned int regwmask = (1<<regwshift)-1; 3193 unsigned int regwmask = (1<<regwshift)-1;
3194 unsigned int invert = mc->invert; 3194 unsigned int invert = mc->invert;
3195 unsigned long mask = (1UL<<mc->nbits)-1; 3195 unsigned long mask = (1UL<<mc->nbits)-1;
@@ -3837,6 +3837,8 @@ __snd_soc_register_component(struct device *dev,
3837 return -ENOMEM; 3837 return -ENOMEM;
3838 } 3838 }
3839 3839
3840 mutex_init(&cmpnt->io_mutex);
3841
3840 cmpnt->name = fmt_single_name(dev, &cmpnt->id); 3842 cmpnt->name = fmt_single_name(dev, &cmpnt->id);
3841 if (!cmpnt->name) { 3843 if (!cmpnt->name) {
3842 dev_err(dev, "ASoC: Failed to simplifying name\n"); 3844 dev_err(dev, "ASoC: Failed to simplifying name\n");
@@ -3917,6 +3919,24 @@ found:
3917} 3919}
3918EXPORT_SYMBOL_GPL(snd_soc_unregister_component); 3920EXPORT_SYMBOL_GPL(snd_soc_unregister_component);
3919 3921
3922static int snd_soc_platform_drv_write(struct snd_soc_component *component,
3923 unsigned int reg, unsigned int val)
3924{
3925 struct snd_soc_platform *platform = snd_soc_component_to_platform(component);
3926
3927 return platform->driver->write(platform, reg, val);
3928}
3929
3930static int snd_soc_platform_drv_read(struct snd_soc_component *component,
3931 unsigned int reg, unsigned int *val)
3932{
3933 struct snd_soc_platform *platform = snd_soc_component_to_platform(component);
3934
3935 *val = platform->driver->read(platform, reg);
3936
3937 return 0;
3938}
3939
3920/** 3940/**
3921 * snd_soc_add_platform - Add a platform to the ASoC core 3941 * snd_soc_add_platform - Add a platform to the ASoC core
3922 * @dev: The parent device for the platform 3942 * @dev: The parent device for the platform
@@ -3937,8 +3957,12 @@ int snd_soc_add_platform(struct device *dev, struct snd_soc_platform *platform,
3937 platform->driver = platform_drv; 3957 platform->driver = platform_drv;
3938 platform->dapm.dev = dev; 3958 platform->dapm.dev = dev;
3939 platform->dapm.platform = platform; 3959 platform->dapm.platform = platform;
3960 platform->dapm.component = &platform->component;
3940 platform->dapm.stream_event = platform_drv->stream_event; 3961 platform->dapm.stream_event = platform_drv->stream_event;
3941 mutex_init(&platform->mutex); 3962 if (platform_drv->write)
3963 platform->component.write = snd_soc_platform_drv_write;
3964 if (platform_drv->read)
3965 platform->component.read = snd_soc_platform_drv_read;
3942 3966
3943 /* register component */ 3967 /* register component */
3944 ret = __snd_soc_register_component(dev, &platform->component, 3968 ret = __snd_soc_register_component(dev, &platform->component,
@@ -4067,6 +4091,24 @@ static void fixup_codec_formats(struct snd_soc_pcm_stream *stream)
4067 stream->formats |= codec_format_map[i]; 4091 stream->formats |= codec_format_map[i];
4068} 4092}
4069 4093
4094static int snd_soc_codec_drv_write(struct snd_soc_component *component,
4095 unsigned int reg, unsigned int val)
4096{
4097 struct snd_soc_codec *codec = snd_soc_component_to_codec(component);
4098
4099 return codec->driver->write(codec, reg, val);
4100}
4101
4102static int snd_soc_codec_drv_read(struct snd_soc_component *component,
4103 unsigned int reg, unsigned int *val)
4104{
4105 struct snd_soc_codec *codec = snd_soc_component_to_codec(component);
4106
4107 *val = codec->driver->read(codec, reg);
4108
4109 return 0;
4110}
4111
4070/** 4112/**
4071 * snd_soc_register_codec - Register a codec with the ASoC core 4113 * snd_soc_register_codec - Register a codec with the ASoC core
4072 * 4114 *
@@ -4094,29 +4136,33 @@ int snd_soc_register_codec(struct device *dev,
4094 goto fail_codec; 4136 goto fail_codec;
4095 } 4137 }
4096 4138
4097 codec->write = codec_drv->write; 4139 if (codec_drv->write)
4098 codec->read = codec_drv->read; 4140 codec->component.write = snd_soc_codec_drv_write;
4141 if (codec_drv->read)
4142 codec->component.read = snd_soc_codec_drv_read;
4099 codec->component.ignore_pmdown_time = codec_drv->ignore_pmdown_time; 4143 codec->component.ignore_pmdown_time = codec_drv->ignore_pmdown_time;
4100 codec->dapm.bias_level = SND_SOC_BIAS_OFF; 4144 codec->dapm.bias_level = SND_SOC_BIAS_OFF;
4101 codec->dapm.dev = dev; 4145 codec->dapm.dev = dev;
4102 codec->dapm.codec = codec; 4146 codec->dapm.codec = codec;
4147 codec->dapm.component = &codec->component;
4103 codec->dapm.seq_notifier = codec_drv->seq_notifier; 4148 codec->dapm.seq_notifier = codec_drv->seq_notifier;
4104 codec->dapm.stream_event = codec_drv->stream_event; 4149 codec->dapm.stream_event = codec_drv->stream_event;
4105 codec->dev = dev; 4150 codec->dev = dev;
4106 codec->driver = codec_drv; 4151 codec->driver = codec_drv;
4107 codec->num_dai = num_dai; 4152 codec->num_dai = num_dai;
4108 codec->val_bytes = codec_drv->reg_word_size; 4153 codec->component.val_bytes = codec_drv->reg_word_size;
4109 mutex_init(&codec->mutex); 4154 mutex_init(&codec->mutex);
4110 4155
4111 if (!codec->write) { 4156 if (!codec->component.write) {
4112 if (codec_drv->get_regmap) 4157 if (codec_drv->get_regmap)
4113 regmap = codec_drv->get_regmap(dev); 4158 regmap = codec_drv->get_regmap(dev);
4114 else 4159 else
4115 regmap = dev_get_regmap(dev, NULL); 4160 regmap = dev_get_regmap(dev, NULL);
4116 4161
4117 if (regmap) { 4162 if (regmap) {
4118 ret = snd_soc_codec_set_cache_io(codec, regmap); 4163 ret = snd_soc_component_init_io(&codec->component,
4119 if (ret && ret != -ENOTSUPP) { 4164 regmap);
4165 if (ret) {
4120 dev_err(codec->dev, 4166 dev_err(codec->dev,
4121 "Failed to set cache I/O:%d\n", 4167 "Failed to set cache I/O:%d\n",
4122 ret); 4168 ret);
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index f4ba7b40a6ab..da266e1e61b0 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -379,86 +379,24 @@ static void dapm_reset(struct snd_soc_card *card)
379static int soc_widget_read(struct snd_soc_dapm_widget *w, int reg, 379static int soc_widget_read(struct snd_soc_dapm_widget *w, int reg,
380 unsigned int *value) 380 unsigned int *value)
381{ 381{
382 if (w->codec) { 382 if (!w->dapm->component)
383 *value = snd_soc_read(w->codec, reg); 383 return -EIO;
384 return 0; 384 return snd_soc_component_read(w->dapm->component, reg, value);
385 } else if (w->platform) {
386 *value = snd_soc_platform_read(w->platform, reg);
387 return 0;
388 }
389
390 dev_err(w->dapm->dev, "ASoC: no valid widget read method\n");
391 return -1;
392}
393
394static int soc_widget_write(struct snd_soc_dapm_widget *w, int reg,
395 unsigned int val)
396{
397 if (w->codec)
398 return snd_soc_write(w->codec, reg, val);
399 else if (w->platform)
400 return snd_soc_platform_write(w->platform, reg, val);
401
402 dev_err(w->dapm->dev, "ASoC: no valid widget write method\n");
403 return -1;
404}
405
406static inline void soc_widget_lock(struct snd_soc_dapm_widget *w)
407{
408 if (w->codec && !w->codec->using_regmap)
409 mutex_lock(&w->codec->mutex);
410 else if (w->platform)
411 mutex_lock(&w->platform->mutex);
412} 385}
413 386
414static inline void soc_widget_unlock(struct snd_soc_dapm_widget *w) 387static int soc_widget_update_bits_locked(struct snd_soc_dapm_widget *w,
388 int reg, unsigned int mask, unsigned int value)
415{ 389{
416 if (w->codec && !w->codec->using_regmap) 390 if (!w->dapm->component)
417 mutex_unlock(&w->codec->mutex); 391 return -EIO;
418 else if (w->platform) 392 return snd_soc_component_update_bits_async(w->dapm->component, reg,
419 mutex_unlock(&w->platform->mutex); 393 mask, value);
420} 394}
421 395
422static void soc_dapm_async_complete(struct snd_soc_dapm_context *dapm) 396static void soc_dapm_async_complete(struct snd_soc_dapm_context *dapm)
423{ 397{
424 if (dapm->codec && dapm->codec->using_regmap) 398 if (dapm->component)
425 regmap_async_complete(dapm->codec->control_data); 399 snd_soc_component_async_complete(dapm->component);
426}
427
428static int soc_widget_update_bits_locked(struct snd_soc_dapm_widget *w,
429 int reg, unsigned int mask, unsigned int value)
430{
431 bool change;
432 unsigned int old, new;
433 int ret;
434
435 if (w->codec && w->codec->using_regmap) {
436 ret = regmap_update_bits_check_async(w->codec->control_data,
437 reg, mask, value,
438 &change);
439 if (ret != 0)
440 return ret;
441 } else {
442 soc_widget_lock(w);
443 ret = soc_widget_read(w, reg, &old);
444 if (ret < 0) {
445 soc_widget_unlock(w);
446 return ret;
447 }
448
449 new = (old & ~mask) | (value & mask);
450 change = old != new;
451 if (change) {
452 ret = soc_widget_write(w, reg, new);
453 if (ret < 0) {
454 soc_widget_unlock(w);
455 return ret;
456 }
457 }
458 soc_widget_unlock(w);
459 }
460
461 return change;
462} 400}
463 401
464/** 402/**
diff --git a/sound/soc/soc-io.c b/sound/soc/soc-io.c
index dc0c09d2682a..ac64fd7252b2 100644
--- a/sound/soc/soc-io.c
+++ b/sound/soc/soc-io.c
@@ -19,24 +19,205 @@
19 19
20#include <trace/events/asoc.h> 20#include <trace/events/asoc.h>
21 21
22unsigned int snd_soc_read(struct snd_soc_codec *codec, unsigned int reg) 22/**
23 * snd_soc_component_read() - Read register value
24 * @component: Component to read from
25 * @reg: Register to read
26 * @val: Pointer to where the read value is stored
27 *
28 * Return: 0 on success, a negative error code otherwise.
29 */
30int snd_soc_component_read(struct snd_soc_component *component,
31 unsigned int reg, unsigned int *val)
32{
33 int ret;
34
35 if (component->regmap)
36 ret = regmap_read(component->regmap, reg, val);
37 else if (component->read)
38 ret = component->read(component, reg, val);
39 else
40 ret = -EIO;
41
42 dev_dbg(component->dev, "read %x => %x\n", reg, *val);
43
44 return ret;
45}
46EXPORT_SYMBOL_GPL(snd_soc_component_read);
47
48/**
49 * snd_soc_component_write() - Write register value
50 * @component: Component to write to
51 * @reg: Register to write
52 * @val: Value to write to the register
53 *
54 * Return: 0 on success, a negative error code otherwise.
55 */
56int snd_soc_component_write(struct snd_soc_component *component,
57 unsigned int reg, unsigned int val)
23{ 58{
24 unsigned int ret; 59 dev_dbg(component->dev, "write %x = %x\n", reg, val);
25 60
26 ret = codec->read(codec, reg); 61 if (component->regmap)
27 dev_dbg(codec->dev, "read %x => %x\n", reg, ret); 62 return regmap_write(component->regmap, reg, val);
28 trace_snd_soc_reg_read(codec, reg, ret); 63 else if (component->write)
64 return component->write(component, reg, val);
65 else
66 return -EIO;
67}
68EXPORT_SYMBOL_GPL(snd_soc_component_write);
69
70static int snd_soc_component_update_bits_legacy(
71 struct snd_soc_component *component, unsigned int reg,
72 unsigned int mask, unsigned int val, bool *change)
73{
74 unsigned int old, new;
75 int ret;
76
77 if (!component->read || !component->write)
78 return -EIO;
79
80 mutex_lock(&component->io_mutex);
81
82 ret = component->read(component, reg, &old);
83 if (ret < 0)
84 goto out_unlock;
85
86 new = (old & ~mask) | (val & mask);
87 *change = old != new;
88 if (*change)
89 ret = component->write(component, reg, new);
90out_unlock:
91 mutex_unlock(&component->io_mutex);
29 92
30 return ret; 93 return ret;
31} 94}
95
96/**
97 * snd_soc_component_update_bits() - Perform read/modify/write cycle
98 * @component: Component to update
99 * @reg: Register to update
100 * @mask: Mask that specifies which bits to update
101 * @val: New value for the bits specified by mask
102 *
103 * Return: 1 if the operation was successful and the value of the register
104 * changed, 0 if the operation was successful, but the value did not change.
105 * Returns a negative error code otherwise.
106 */
107int snd_soc_component_update_bits(struct snd_soc_component *component,
108 unsigned int reg, unsigned int mask, unsigned int val)
109{
110 bool change;
111 int ret;
112
113 if (component->regmap)
114 ret = regmap_update_bits_check(component->regmap, reg, mask,
115 val, &change);
116 else
117 ret = snd_soc_component_update_bits_legacy(component, reg,
118 mask, val, &change);
119
120 if (ret < 0)
121 return ret;
122 return change;
123}
124EXPORT_SYMBOL_GPL(snd_soc_component_update_bits);
125
126/**
127 * snd_soc_component_update_bits_async() - Perform asynchronous
128 * read/modify/write cycle
129 * @component: Component to update
130 * @reg: Register to update
131 * @mask: Mask that specifies which bits to update
132 * @val: New value for the bits specified by mask
133 *
134 * This function is similar to snd_soc_component_update_bits(), but the update
135 * operation is scheduled asynchronously. This means it may not be completed
136 * when the function returns. To make sure that all scheduled updates have been
137 * completed snd_soc_component_async_complete() must be called.
138 *
139 * Return: 1 if the operation was successful and the value of the register
140 * changed, 0 if the operation was successful, but the value did not change.
141 * Returns a negative error code otherwise.
142 */
143int snd_soc_component_update_bits_async(struct snd_soc_component *component,
144 unsigned int reg, unsigned int mask, unsigned int val)
145{
146 bool change;
147 int ret;
148
149 if (component->regmap)
150 ret = regmap_update_bits_check_async(component->regmap, reg,
151 mask, val, &change);
152 else
153 ret = snd_soc_component_update_bits_legacy(component, reg,
154 mask, val, &change);
155
156 if (ret < 0)
157 return ret;
158 return change;
159}
160EXPORT_SYMBOL_GPL(snd_soc_component_update_bits_async);
161
162/**
163 * snd_soc_component_async_complete() - Ensure asynchronous I/O has completed
164 * @component: Component for which to wait
165 *
166 * This function blocks until all asynchronous I/O which has previously been
167 * scheduled using snd_soc_component_update_bits_async() has completed.
168 */
169void snd_soc_component_async_complete(struct snd_soc_component *component)
170{
171 if (component->regmap)
172 regmap_async_complete(component->regmap);
173}
174EXPORT_SYMBOL_GPL(snd_soc_component_async_complete);
175
176/**
177 * snd_soc_component_test_bits - Test register for change
178 * @component: component
179 * @reg: Register to test
180 * @mask: Mask that specifies which bits to test
181 * @value: Value to test against
182 *
183 * Tests a register with a new value and checks if the new value is
184 * different from the old value.
185 *
186 * Return: 1 for change, otherwise 0.
187 */
188int snd_soc_component_test_bits(struct snd_soc_component *component,
189 unsigned int reg, unsigned int mask, unsigned int value)
190{
191 unsigned int old, new;
192 int ret;
193
194 ret = snd_soc_component_read(component, reg, &old);
195 if (ret < 0)
196 return ret;
197 new = (old & ~mask) | value;
198 return old != new;
199}
200EXPORT_SYMBOL_GPL(snd_soc_component_test_bits);
201
202unsigned int snd_soc_read(struct snd_soc_codec *codec, unsigned int reg)
203{
204 unsigned int val;
205 int ret;
206
207 ret = snd_soc_component_read(&codec->component, reg, &val);
208 if (ret < 0)
209 return -1;
210 trace_snd_soc_reg_read(codec, reg, val);
211
212 return val;
213}
32EXPORT_SYMBOL_GPL(snd_soc_read); 214EXPORT_SYMBOL_GPL(snd_soc_read);
33 215
34int snd_soc_write(struct snd_soc_codec *codec, unsigned int reg, 216int snd_soc_write(struct snd_soc_codec *codec, unsigned int reg,
35 unsigned int val) 217 unsigned int val)
36{ 218{
37 dev_dbg(codec->dev, "write %x = %x\n", reg, val);
38 trace_snd_soc_reg_write(codec, reg, val); 219 trace_snd_soc_reg_write(codec, reg, val);
39 return codec->write(codec, reg, val); 220 return snd_soc_component_write(&codec->component, reg, val);
40} 221}
41EXPORT_SYMBOL_GPL(snd_soc_write); 222EXPORT_SYMBOL_GPL(snd_soc_write);
42 223
@@ -54,29 +235,8 @@ EXPORT_SYMBOL_GPL(snd_soc_write);
54int snd_soc_update_bits(struct snd_soc_codec *codec, unsigned int reg, 235int snd_soc_update_bits(struct snd_soc_codec *codec, unsigned int reg,
55 unsigned int mask, unsigned int value) 236 unsigned int mask, unsigned int value)
56{ 237{
57 bool change; 238 return snd_soc_component_update_bits(&codec->component, reg, mask,
58 unsigned int old, new; 239 value);
59 int ret;
60
61 if (codec->using_regmap) {
62 ret = regmap_update_bits_check(codec->control_data, reg,
63 mask, value, &change);
64 } else {
65 ret = snd_soc_read(codec, reg);
66 if (ret < 0)
67 return ret;
68
69 old = ret;
70 new = (old & ~mask) | (value & mask);
71 change = old != new;
72 if (change)
73 ret = snd_soc_write(codec, reg, new);
74 }
75
76 if (ret < 0)
77 return ret;
78
79 return change;
80} 240}
81EXPORT_SYMBOL_GPL(snd_soc_update_bits); 241EXPORT_SYMBOL_GPL(snd_soc_update_bits);
82 242
@@ -95,13 +255,8 @@ int snd_soc_update_bits_locked(struct snd_soc_codec *codec,
95 unsigned int reg, unsigned int mask, 255 unsigned int reg, unsigned int mask,
96 unsigned int value) 256 unsigned int value)
97{ 257{
98 int change; 258 return snd_soc_component_update_bits(&codec->component, reg, mask,
99 259 value);
100 mutex_lock(&codec->mutex);
101 change = snd_soc_update_bits(codec, reg, mask, value);
102 mutex_unlock(&codec->mutex);
103
104 return change;
105} 260}
106EXPORT_SYMBOL_GPL(snd_soc_update_bits_locked); 261EXPORT_SYMBOL_GPL(snd_soc_update_bits_locked);
107 262
@@ -120,115 +275,58 @@ EXPORT_SYMBOL_GPL(snd_soc_update_bits_locked);
120int snd_soc_test_bits(struct snd_soc_codec *codec, unsigned int reg, 275int snd_soc_test_bits(struct snd_soc_codec *codec, unsigned int reg,
121 unsigned int mask, unsigned int value) 276 unsigned int mask, unsigned int value)
122{ 277{
123 int change; 278 return snd_soc_component_test_bits(&codec->component, reg, mask, value);
124 unsigned int old, new;
125
126 old = snd_soc_read(codec, reg);
127 new = (old & ~mask) | value;
128 change = old != new;
129
130 return change;
131} 279}
132EXPORT_SYMBOL_GPL(snd_soc_test_bits); 280EXPORT_SYMBOL_GPL(snd_soc_test_bits);
133 281
134int snd_soc_platform_read(struct snd_soc_platform *platform, 282int snd_soc_platform_read(struct snd_soc_platform *platform,
135 unsigned int reg) 283 unsigned int reg)
136{ 284{
137 unsigned int ret; 285 unsigned int val;
286 int ret;
138 287
139 if (!platform->driver->read) { 288 ret = snd_soc_component_read(&platform->component, reg, &val);
140 dev_err(platform->dev, "ASoC: platform has no read back\n"); 289 if (ret < 0)
141 return -1; 290 return -1;
142 }
143 291
144 ret = platform->driver->read(platform, reg); 292 trace_snd_soc_preg_read(platform, reg, val);
145 dev_dbg(platform->dev, "read %x => %x\n", reg, ret);
146 trace_snd_soc_preg_read(platform, reg, ret);
147 293
148 return ret; 294 return val;
149} 295}
150EXPORT_SYMBOL_GPL(snd_soc_platform_read); 296EXPORT_SYMBOL_GPL(snd_soc_platform_read);
151 297
152int snd_soc_platform_write(struct snd_soc_platform *platform, 298int snd_soc_platform_write(struct snd_soc_platform *platform,
153 unsigned int reg, unsigned int val) 299 unsigned int reg, unsigned int val)
154{ 300{
155 if (!platform->driver->write) {
156 dev_err(platform->dev, "ASoC: platform has no write back\n");
157 return -1;
158 }
159
160 dev_dbg(platform->dev, "write %x = %x\n", reg, val);
161 trace_snd_soc_preg_write(platform, reg, val); 301 trace_snd_soc_preg_write(platform, reg, val);
162 return platform->driver->write(platform, reg, val); 302 return snd_soc_component_write(&platform->component, reg, val);
163} 303}
164EXPORT_SYMBOL_GPL(snd_soc_platform_write); 304EXPORT_SYMBOL_GPL(snd_soc_platform_write);
165 305
166#ifdef CONFIG_REGMAP
167static int hw_write(struct snd_soc_codec *codec, unsigned int reg,
168 unsigned int value)
169{
170 return regmap_write(codec->control_data, reg, value);
171}
172
173static unsigned int hw_read(struct snd_soc_codec *codec, unsigned int reg)
174{
175 int ret;
176 unsigned int val;
177
178 ret = regmap_read(codec->control_data, reg, &val);
179 if (ret == 0)
180 return val;
181 else
182 return -1;
183}
184
185/** 306/**
186 * snd_soc_codec_set_cache_io: Set up standard I/O functions. 307 * snd_soc_component_init_io() - Initialize regmap IO
187 *
188 * @codec: CODEC to configure.
189 * @map: Register map to write to
190 * 308 *
191 * Register formats are frequently shared between many I2C and SPI 309 * @component: component to initialize
192 * devices. In order to promote code reuse the ASoC core provides 310 * @regmap: regmap instance to use for IO operations
193 * some standard implementations of CODEC read and write operations
194 * which can be set up using this function.
195 * 311 *
196 * The caller is responsible for allocating and initialising the 312 * Return: 0 on success, a negative error code otherwise
197 * actual cache.
198 *
199 * Note that at present this code cannot be used by CODECs with
200 * volatile registers.
201 */ 313 */
202int snd_soc_codec_set_cache_io(struct snd_soc_codec *codec, 314int snd_soc_component_init_io(struct snd_soc_component *component,
203 struct regmap *regmap) 315 struct regmap *regmap)
204{ 316{
205 int ret; 317 int ret;
206 318
207 if (!regmap) 319 if (!regmap)
208 return -EINVAL; 320 return -EINVAL;
209 321
210 /* Device has made its own regmap arrangements */ 322 ret = regmap_get_val_bytes(regmap);
211 codec->control_data = regmap;
212
213 codec->write = hw_write;
214 codec->read = hw_read;
215
216 ret = regmap_get_val_bytes(codec->control_data);
217 /* Errors are legitimate for non-integer byte 323 /* Errors are legitimate for non-integer byte
218 * multiples */ 324 * multiples */
219 if (ret > 0) 325 if (ret > 0)
220 codec->val_bytes = ret; 326 component->val_bytes = ret;
221 327
222 codec->using_regmap = true; 328 component->regmap = regmap;
223 329
224 return 0; 330 return 0;
225} 331}
226EXPORT_SYMBOL_GPL(snd_soc_codec_set_cache_io); 332EXPORT_SYMBOL_GPL(snd_soc_component_init_io);
227#else
228int snd_soc_codec_set_cache_io(struct snd_soc_codec *codec,
229 struct regmap *regmap)
230{
231 return -ENOTSUPP;
232}
233EXPORT_SYMBOL_GPL(snd_soc_codec_set_cache_io);
234#endif