From: Mark Brown Date: Tue, 22 Apr 2014 12:22:52 +0000 (+0100) Subject: Merge branches 'topic/sta350', 'topic/core', 'topic/dapm' and 'topic/cache' of git... X-Git-Tag: v3.16-rc1~12^2~52^2~14^2~7 X-Git-Url: https://asedeno.scripts.mit.edu/gitweb/?a=commitdiff_plain;h=2b17ef4071d37ef5e357a4ec75686315cfa9d3e6;p=linux.git Merge branches 'topic/sta350', 'topic/core', 'topic/dapm' and 'topic/cache' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound into asoc-component --- 2b17ef4071d37ef5e357a4ec75686315cfa9d3e6 diff --cc include/sound/soc.h index 81454b0dd624,0b83168d8ff4,192ddc40ae0a,0b83168d8ff4,2f62436026d2..8148c98b5f8f --- a/include/sound/soc.h +++ b/include/sound/soc.h @@@@@@ -746,8 -754,13 -746,8 -754,13 -754,14 +746,9 @@@@@@ struct snd_soc_codec_driver unsigned int freq_in, unsigned int freq_out); /* codec IO */ ++++ struct regmap *(*get_regmap)(struct device *); unsigned int (*read)(struct snd_soc_codec *, unsigned int); int (*write)(struct snd_soc_codec *, unsigned int, unsigned int); - -- int (*display_register)(struct snd_soc_codec *, char *, - -- size_t, unsigned int); - -- int (*volatile_register)(struct snd_soc_codec *, unsigned int); - -- int (*readable_register)(struct snd_soc_codec *, unsigned int); - -- int (*writable_register)(struct snd_soc_codec *, unsigned int); unsigned int reg_cache_size; short reg_cache_step; short reg_word_size; @@@@@@ -1110,23 -1120,10 -1110,23 -1120,10 -1121,10 +1111,23 @@@@@@ static inline struct snd_soc_codec *snd return container_of(component, struct snd_soc_codec, component); } + ++/** + ++ * snd_soc_component_to_platform() - Casts a component to the platform it is embedded in + ++ * @component: The component to cast to a platform + ++ * + ++ * This function must only be used on components that are known to be platforms. + ++ * Otherwise the behavior is undefined. + ++ */ + ++static inline struct snd_soc_platform *snd_soc_component_to_platform( + ++ struct snd_soc_component *component) + ++{ + ++ return container_of(component, struct snd_soc_platform, component); + ++} + ++ /* codec IO */ unsigned int snd_soc_read(struct snd_soc_codec *codec, unsigned int reg); -- --unsigned int snd_soc_write(struct snd_soc_codec *codec, -- -- unsigned int reg, unsigned int val); ++ ++int snd_soc_write(struct snd_soc_codec *codec, unsigned int reg, ++ ++ unsigned int val); /* device driver data */ @@@@@@ -1231,34 -1228,6 -1231,34 -1228,6 -1229,6 +1232,34 @@@@@@ static inline bool snd_soc_codec_is_act return snd_soc_component_is_active(&codec->component); } + ++/** + ++ * snd_soc_kcontrol_codec() - Returns the CODEC that registered the control + ++ * @kcontrol: The control for which to get the CODEC + ++ * + ++ * Note: This function will only work correctly if the control has been + ++ * registered with snd_soc_add_codec_controls() or via table based setup of + ++ * snd_soc_codec_driver. Otherwise the behavior is undefined. + ++ */ + ++static inline struct snd_soc_codec *snd_soc_kcontrol_codec( + ++ struct snd_kcontrol *kcontrol) + ++{ + ++ return snd_kcontrol_chip(kcontrol); + ++} + ++ + ++/** + ++ * snd_soc_kcontrol_platform() - Returns the platform that registerd the control + ++ * @kcontrol: The control for which to get the platform + ++ * + ++ * Note: This function will only work correctly if the control has been + ++ * registered with snd_soc_add_platform_controls() or via table based setup of + ++ * a snd_soc_platform_driver. Otherwise the behavior is undefined. + ++ */ - static inline struct snd_soc_codec *snd_soc_kcontrol_platform( ++++static inline struct snd_soc_platform *snd_soc_kcontrol_platform( + ++ struct snd_kcontrol *kcontrol) + ++{ + ++ return snd_kcontrol_chip(kcontrol); + ++} + ++ int snd_soc_util_init(void); void snd_soc_util_exit(void); diff --cc sound/soc/soc-core.c index a95c7e524dfc,051c006281f5,7f8efea5c5b1,051c006281f5,5071a3a0ac83..db577e4cdf49 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@@@@@ -1120,26 -1127,26 -1120,41 -1127,26 -1127,16 +1120,31 @@@@@@ static int soc_probe_codec(struct snd_s soc_init_codec_debugfs(codec); -- -- if (driver->dapm_widgets) -- -- snd_soc_dapm_new_controls(&codec->dapm, driver->dapm_widgets, -- -- driver->num_dapm_widgets); ++ ++ if (driver->dapm_widgets) { ++ ++ ret = snd_soc_dapm_new_controls(&codec->dapm, ++ ++ driver->dapm_widgets, ++ ++ driver->num_dapm_widgets); + -- - /* Create DAPM widgets for each DAI stream */ -- - list_for_each_entry(dai, &codec->component.dai_list, list) -- - snd_soc_dapm_new_dai_widgets(&codec->dapm, dai); ++ ++ if (ret != 0) { ++ ++ dev_err(codec->dev, ++ ++ "Failed to create new controls %d\n", ret); ++ ++ goto err_probe; ++ ++ } ++ ++ } -- - codec->dapm.idle_bias_off = driver->idle_bias_off; ++ + /* Create DAPM widgets for each DAI stream */ - list_for_each_entry(dai, &codec->component.dai_list, list) - snd_soc_dapm_new_dai_widgets(&codec->dapm, dai); ++ ++ list_for_each_entry(dai, &codec->component.dai_list, list) { ++ ++ ret = snd_soc_dapm_new_dai_widgets(&codec->dapm, dai); + -- - if (!codec->write && dev_get_regmap(codec->dev, NULL)) { -- - /* Set the default I/O up try regmap */ -- - ret = snd_soc_codec_set_cache_io(codec, NULL); -- - if (ret < 0) { ++ ++ if (ret != 0) { + dev_err(codec->dev, -- - "Failed to set cache I/O: %d\n", ret); ++ ++ "Failed to create DAI widgets %d\n", ret); + goto err_probe; + } + } ++ + codec->dapm.idle_bias_off = driver->idle_bias_off; ++ + - if (!codec->write && dev_get_regmap(codec->dev, NULL)) { - /* Set the default I/O up try regmap */ - ret = snd_soc_codec_set_cache_io(codec, NULL); - if (ret < 0) { - dev_err(codec->dev, - "Failed to set cache I/O: %d\n", ret); - goto err_probe; - } - } - if (driver->probe) { ret = driver->probe(codec); if (ret < 0) { @@@@@@ -4099,9 -4292,8 -4114,9 -4292,8 -4283,25 +4105,26 @@@@@@ int snd_soc_register_codec(struct devic codec->dev = dev; codec->driver = codec_drv; codec->num_dai = num_dai; + ++ codec->val_bytes = codec_drv->reg_word_size; mutex_init(&codec->mutex); ++++ if (!codec->write) { ++++ if (codec_drv->get_regmap) ++++ regmap = codec_drv->get_regmap(dev); ++++ else ++++ regmap = dev_get_regmap(dev, NULL); ++++ ++++ if (regmap) { ++++ ret = snd_soc_codec_set_cache_io(codec, regmap); ++++ if (ret && ret != -ENOTSUPP) { ++++ dev_err(codec->dev, ++++ "Failed to set cache I/O:%d\n", ++++ ret); ++++ return ret; ++++ } ++++ } ++++ } ++++ for (i = 0; i < num_dai; i++) { fixup_codec_formats(&dai_drv[i].playback); fixup_codec_formats(&dai_drv[i].capture); diff --cc sound/soc/soc-io.c index bfd7206c178f,260efc8466fc,5fb85783b044,260efc8466fc,6480e8f29310..dc0c09d2682a --- a/sound/soc/soc-io.c +++ b/sound/soc/soc-io.c @@@@@@ -19,150 -19,6 -19,150 -19,6 -19,6 +19,150 @@@@@@ #include + ++unsigned int snd_soc_read(struct snd_soc_codec *codec, unsigned int reg) + ++{ + ++ unsigned int ret; + ++ + ++ ret = codec->read(codec, reg); + ++ dev_dbg(codec->dev, "read %x => %x\n", reg, ret); + ++ trace_snd_soc_reg_read(codec, reg, ret); + ++ + ++ return ret; + ++} + ++EXPORT_SYMBOL_GPL(snd_soc_read); + ++ - unsigned int snd_soc_write(struct snd_soc_codec *codec, - unsigned int reg, unsigned int val) ++ ++int snd_soc_write(struct snd_soc_codec *codec, unsigned int reg, ++ ++ unsigned int val) + ++{ + ++ dev_dbg(codec->dev, "write %x = %x\n", reg, val); + ++ trace_snd_soc_reg_write(codec, reg, val); + ++ return codec->write(codec, reg, val); + ++} + ++EXPORT_SYMBOL_GPL(snd_soc_write); + ++ + ++/** + ++ * snd_soc_update_bits - update codec register bits + ++ * @codec: audio codec + ++ * @reg: codec register + ++ * @mask: register mask + ++ * @value: new value + ++ * + ++ * Writes new register value. + ++ * + ++ * Returns 1 for change, 0 for no change, or negative error code. + ++ */ - int snd_soc_update_bits(struct snd_soc_codec *codec, unsigned short reg, ++ ++int snd_soc_update_bits(struct snd_soc_codec *codec, unsigned int reg, + ++ unsigned int mask, unsigned int value) + ++{ + ++ bool change; + ++ unsigned int old, new; + ++ int ret; + ++ + ++ if (codec->using_regmap) { + ++ ret = regmap_update_bits_check(codec->control_data, reg, + ++ mask, value, &change); + ++ } else { + ++ ret = snd_soc_read(codec, reg); + ++ if (ret < 0) + ++ return ret; + ++ + ++ old = ret; + ++ new = (old & ~mask) | (value & mask); + ++ change = old != new; + ++ if (change) + ++ ret = snd_soc_write(codec, reg, new); + ++ } + ++ + ++ if (ret < 0) + ++ return ret; + ++ + ++ return change; + ++} + ++EXPORT_SYMBOL_GPL(snd_soc_update_bits); + ++ + ++/** + ++ * snd_soc_update_bits_locked - update codec register bits + ++ * @codec: audio codec + ++ * @reg: codec register + ++ * @mask: register mask + ++ * @value: new value + ++ * + ++ * Writes new register value, and takes the codec mutex. + ++ * + ++ * Returns 1 for change else 0. + ++ */ + ++int snd_soc_update_bits_locked(struct snd_soc_codec *codec, - unsigned short reg, unsigned int mask, ++ ++ unsigned int reg, unsigned int mask, + ++ unsigned int value) + ++{ + ++ int change; + ++ + ++ mutex_lock(&codec->mutex); + ++ change = snd_soc_update_bits(codec, reg, mask, value); + ++ mutex_unlock(&codec->mutex); + ++ + ++ return change; + ++} + ++EXPORT_SYMBOL_GPL(snd_soc_update_bits_locked); + ++ + ++/** + ++ * snd_soc_test_bits - test register for change + ++ * @codec: audio codec + ++ * @reg: codec register + ++ * @mask: register mask + ++ * @value: new value + ++ * + ++ * Tests a register with a new value and checks if the new value is + ++ * different from the old value. + ++ * + ++ * Returns 1 for change else 0. + ++ */ - int snd_soc_test_bits(struct snd_soc_codec *codec, unsigned short reg, ++ ++int snd_soc_test_bits(struct snd_soc_codec *codec, unsigned int reg, + ++ unsigned int mask, unsigned int value) + ++{ + ++ int change; + ++ unsigned int old, new; + ++ + ++ old = snd_soc_read(codec, reg); + ++ new = (old & ~mask) | value; + ++ change = old != new; + ++ + ++ return change; + ++} + ++EXPORT_SYMBOL_GPL(snd_soc_test_bits); + ++ + ++int snd_soc_platform_read(struct snd_soc_platform *platform, + ++ unsigned int reg) + ++{ + ++ unsigned int ret; + ++ + ++ if (!platform->driver->read) { + ++ dev_err(platform->dev, "ASoC: platform has no read back\n"); + ++ return -1; + ++ } + ++ + ++ ret = platform->driver->read(platform, reg); + ++ dev_dbg(platform->dev, "read %x => %x\n", reg, ret); + ++ trace_snd_soc_preg_read(platform, reg, ret); + ++ + ++ return ret; + ++} + ++EXPORT_SYMBOL_GPL(snd_soc_platform_read); + ++ + ++int snd_soc_platform_write(struct snd_soc_platform *platform, + ++ unsigned int reg, unsigned int val) + ++{ + ++ if (!platform->driver->write) { + ++ dev_err(platform->dev, "ASoC: platform has no write back\n"); + ++ return -1; + ++ } + ++ + ++ dev_dbg(platform->dev, "write %x = %x\n", reg, val); + ++ trace_snd_soc_preg_write(platform, reg, val); + ++ return platform->driver->write(platform, reg, val); + ++} + ++EXPORT_SYMBOL_GPL(snd_soc_platform_write); + ++ #ifdef CONFIG_REGMAP static int hw_write(struct snd_soc_codec *codec, unsigned int reg, unsigned int value)