@@ -526,7 +526,8 @@ int snd_soc_test_bits(struct snd_soc_codec *codec, unsigned int reg,
#ifdef CONFIG_SND_SOC_AC97_BUS
struct snd_ac97 *snd_soc_alloc_ac97_codec(struct snd_soc_codec *codec);
-struct snd_ac97 *snd_soc_new_ac97_codec(struct snd_soc_codec *codec);
+struct snd_ac97 *snd_soc_new_ac97_codec(struct snd_soc_codec *codec,
+ unsigned int id, unsigned int id_mask);
void snd_soc_free_ac97_codec(struct snd_ac97 *ac97);
int snd_soc_set_ac97_ops(struct snd_ac97_bus_ops *ops);
@@ -240,7 +240,7 @@ static int ad1980_soc_probe(struct snd_soc_codec *codec)
u16 vendor_id2;
u16 ext_status;
- ac97 = snd_soc_new_ac97_codec(codec);
+ ac97 = snd_soc_new_ac97_codec(codec, 0, 0);
if (IS_ERR(ac97)) {
ret = PTR_ERR(ac97);
dev_err(codec->dev, "Failed to register AC97 codec: %d\n", ret);
@@ -332,7 +332,7 @@ static int stac9766_codec_probe(struct snd_soc_codec *codec)
struct snd_ac97 *ac97;
int ret = 0;
- ac97 = snd_soc_new_ac97_codec(codec);
+ ac97 = snd_soc_new_ac97_codec(codec, 0, 0);
if (IS_ERR(ac97))
return PTR_ERR(ac97);
@@ -85,10 +85,19 @@ EXPORT_SYMBOL(snd_soc_alloc_ac97_codec);
/**
* snd_soc_new_ac97_codec - initailise AC97 device
* @codec: audio codec
+ * @id: The expected device ID
+ * @id_mask: Mask that is applied to the device ID before comparing with @id
*
* Initialises AC97 codec resources for use by ad-hoc devices only.
+ *
+ * If @id is not 0 this function will reset the device, then read the ID from
+ * the device and check if it matches the expected ID. If it doesn't match an
+ * error will be returned and device will not be registered.
+ *
+ * Returns: A PTR_ERR() on failure or a valid snd_ac97 struct on success.
*/
-struct snd_ac97 *snd_soc_new_ac97_codec(struct snd_soc_codec *codec)
+struct snd_ac97 *snd_soc_new_ac97_codec(struct snd_soc_codec *codec,
+ unsigned int id, unsigned int id_mask)
{
struct snd_ac97 *ac97;
int ret;
@@ -97,13 +106,24 @@ struct snd_ac97 *snd_soc_new_ac97_codec(struct snd_soc_codec *codec)
if (IS_ERR(ac97))
return ac97;
- ret = device_add(&ac97->dev);
- if (ret) {
- put_device(&ac97->dev);
- return ERR_PTR(ret);
+ if (id) {
+ ret = snd_ac97_reset(ac97, false, id, id_mask);
+ if (ret < 0) {
+ dev_err(codec->dev, "Failed to reset AC97 device: %d\n",
+ ret);
+ goto err_put_device;
+ }
}
+ ret = device_add(&ac97->dev);
+ if (ret)
+ goto err_put_device;
+
return ac97;
+
+err_put_device:
+ put_device(&ac97->dev);
+ return ERR_PTR(ret);
}
EXPORT_SYMBOL_GPL(snd_soc_new_ac97_codec);
AC97 devices need to be initially reset before they can be used. Currently each driver does this on its own. Add support for resetting the device to core in snd_soc_new_ac97_codec(). If the caller supplies a device ID and device ID mask the function will reset the device and verify that it has the correct ID, if it does not a error is returned. This will allow to remove custom code with similar functionality from individual drivers. Signed-off-by: Lars-Peter Clausen <lars@metafoo.de> --- include/sound/soc.h | 3 ++- sound/soc/codecs/ad1980.c | 2 +- sound/soc/codecs/stac9766.c | 2 +- sound/soc/soc-ac97.c | 30 +++++++++++++++++++++++++----- 4 files changed, 29 insertions(+), 8 deletions(-)