From 336b8423e285174ebecf02a743d69913b83bbc48 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 10 Nov 2014 22:41:46 +0100 Subject: ASoC: Move AC'97 support to its own file Currently the AC'97 support is splattered all throughout soc-core.c. Some parts are #ifdef'd some parts are not. This patch moves the AC'97 support to its own file, this should make the code a bit more clearer and also makes it possible to easily not compile it into the kernel when not needed. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/soc-ac97.c | 382 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 382 insertions(+) create mode 100644 sound/soc/soc-ac97.c (limited to 'sound/soc/soc-ac97.c') diff --git a/sound/soc/soc-ac97.c b/sound/soc/soc-ac97.c new file mode 100644 index 000000000000..da7b031a6eea --- /dev/null +++ b/sound/soc/soc-ac97.c @@ -0,0 +1,382 @@ +/* + * soc-ac97.c -- ALSA SoC Audio Layer AC97 support + * + * Copyright 2005 Wolfson Microelectronics PLC. + * Copyright 2005 Openedhand Ltd. + * Copyright (C) 2010 Slimlogic Ltd. + * Copyright (C) 2010 Texas Instruments Inc. + * + * Author: Liam Girdwood + * with code, comments and ideas from :- + * Richard Purdie + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct snd_ac97_reset_cfg { + struct pinctrl *pctl; + struct pinctrl_state *pstate_reset; + struct pinctrl_state *pstate_warm_reset; + struct pinctrl_state *pstate_run; + int gpio_sdata; + int gpio_sync; + int gpio_reset; +}; + +/* unregister ac97 codec */ +static int soc_ac97_dev_unregister(struct snd_soc_codec *codec) +{ + if (codec->ac97->dev.bus) + device_del(&codec->ac97->dev); + return 0; +} + +/* register ac97 codec to bus */ +static int soc_ac97_dev_register(struct snd_soc_codec *codec) +{ + int err; + + codec->ac97->dev.bus = &ac97_bus_type; + codec->ac97->dev.parent = codec->component.card->dev; + + dev_set_name(&codec->ac97->dev, "%d-%d:%s", + codec->component.card->snd_card->number, 0, + codec->component.name); + err = device_add(&codec->ac97->dev); + if (err < 0) { + dev_err(codec->dev, "ASoC: Can't register ac97 bus\n"); + codec->ac97->dev.bus = NULL; + return err; + } + return 0; +} + +static int soc_register_ac97_codec(struct snd_soc_codec *codec, + struct snd_soc_dai *codec_dai) +{ + int ret; + + /* Only instantiate AC97 if not already done by the adaptor + * for the generic AC97 subsystem. + */ + if (codec_dai->driver->ac97_control && !codec->ac97_registered) { + /* + * It is possible that the AC97 device is already registered to + * the device subsystem. This happens when the device is created + * via snd_ac97_mixer(). Currently only SoC codec that does so + * is the generic AC97 glue but others migh emerge. + * + * In those cases we don't try to register the device again. + */ + if (!codec->ac97_created) + return 0; + + ret = soc_ac97_dev_register(codec); + if (ret < 0) { + dev_err(codec->dev, + "ASoC: AC97 device register failed: %d\n", ret); + return ret; + } + + codec->ac97_registered = 1; + } + return 0; +} + +static void soc_unregister_ac97_codec(struct snd_soc_codec *codec) +{ + if (codec->ac97_registered) { + soc_ac97_dev_unregister(codec); + codec->ac97_registered = 0; + } +} + +static int soc_register_ac97_dai_link(struct snd_soc_pcm_runtime *rtd) +{ + int i, ret; + + for (i = 0; i < rtd->num_codecs; i++) { + struct snd_soc_dai *codec_dai = rtd->codec_dais[i]; + + ret = soc_register_ac97_codec(codec_dai->codec, codec_dai); + if (ret) { + while (--i >= 0) + soc_unregister_ac97_codec(codec_dai->codec); + return ret; + } + } + + return 0; +} + +static void soc_unregister_ac97_dai_link(struct snd_soc_pcm_runtime *rtd) +{ + int i; + + for (i = 0; i < rtd->num_codecs; i++) + soc_unregister_ac97_codec(rtd->codec_dais[i]->codec); +} + +static void soc_ac97_device_release(struct device *dev) +{ + kfree(to_ac97_t(dev)); +} + +/** + * snd_soc_new_ac97_codec - initailise AC97 device + * @codec: audio codec + * @ops: AC97 bus operations + * @num: AC97 codec number + * + * Initialises AC97 codec resources for use by ad-hoc devices only. + */ +int snd_soc_new_ac97_codec(struct snd_soc_codec *codec, + struct snd_ac97_bus_ops *ops, int num) +{ + codec->ac97 = kzalloc(sizeof(struct snd_ac97), GFP_KERNEL); + if (codec->ac97 == NULL) + return -ENOMEM; + + codec->ac97->bus = kzalloc(sizeof(struct snd_ac97_bus), GFP_KERNEL); + if (codec->ac97->bus == NULL) { + kfree(codec->ac97); + codec->ac97 = NULL; + return -ENOMEM; + } + + codec->ac97->bus->ops = ops; + codec->ac97->num = num; + codec->ac97->dev.release = soc_ac97_device_release; + + /* + * Mark the AC97 device to be created by us. This way we ensure that the + * device will be registered with the device subsystem later on. + */ + codec->ac97_created = 1; + device_initialize(&codec->ac97->dev); + + return 0; +} +EXPORT_SYMBOL_GPL(snd_soc_new_ac97_codec); + +/** + * snd_soc_free_ac97_codec - free AC97 codec device + * @codec: audio codec + * + * Frees AC97 codec device resources. + */ +void snd_soc_free_ac97_codec(struct snd_soc_codec *codec) +{ + soc_unregister_ac97_codec(codec); + kfree(codec->ac97->bus); + codec->ac97->bus = NULL; + put_device(&codec->ac97->dev); + codec->ac97 = NULL; + codec->ac97_created = 0; +} +EXPORT_SYMBOL_GPL(snd_soc_free_ac97_codec); + +static struct snd_ac97_reset_cfg snd_ac97_rst_cfg; + +static void snd_soc_ac97_warm_reset(struct snd_ac97 *ac97) +{ + struct pinctrl *pctl = snd_ac97_rst_cfg.pctl; + + pinctrl_select_state(pctl, snd_ac97_rst_cfg.pstate_warm_reset); + + gpio_direction_output(snd_ac97_rst_cfg.gpio_sync, 1); + + udelay(10); + + gpio_direction_output(snd_ac97_rst_cfg.gpio_sync, 0); + + pinctrl_select_state(pctl, snd_ac97_rst_cfg.pstate_run); + msleep(2); +} + +static void snd_soc_ac97_reset(struct snd_ac97 *ac97) +{ + struct pinctrl *pctl = snd_ac97_rst_cfg.pctl; + + pinctrl_select_state(pctl, snd_ac97_rst_cfg.pstate_reset); + + gpio_direction_output(snd_ac97_rst_cfg.gpio_sync, 0); + gpio_direction_output(snd_ac97_rst_cfg.gpio_sdata, 0); + gpio_direction_output(snd_ac97_rst_cfg.gpio_reset, 0); + + udelay(10); + + gpio_direction_output(snd_ac97_rst_cfg.gpio_reset, 1); + + pinctrl_select_state(pctl, snd_ac97_rst_cfg.pstate_run); + msleep(2); +} + +static int snd_soc_ac97_parse_pinctl(struct device *dev, + struct snd_ac97_reset_cfg *cfg) +{ + struct pinctrl *p; + struct pinctrl_state *state; + int gpio; + int ret; + + p = devm_pinctrl_get(dev); + if (IS_ERR(p)) { + dev_err(dev, "Failed to get pinctrl\n"); + return PTR_ERR(p); + } + cfg->pctl = p; + + state = pinctrl_lookup_state(p, "ac97-reset"); + if (IS_ERR(state)) { + dev_err(dev, "Can't find pinctrl state ac97-reset\n"); + return PTR_ERR(state); + } + cfg->pstate_reset = state; + + state = pinctrl_lookup_state(p, "ac97-warm-reset"); + if (IS_ERR(state)) { + dev_err(dev, "Can't find pinctrl state ac97-warm-reset\n"); + return PTR_ERR(state); + } + cfg->pstate_warm_reset = state; + + state = pinctrl_lookup_state(p, "ac97-running"); + if (IS_ERR(state)) { + dev_err(dev, "Can't find pinctrl state ac97-running\n"); + return PTR_ERR(state); + } + cfg->pstate_run = state; + + gpio = of_get_named_gpio(dev->of_node, "ac97-gpios", 0); + if (gpio < 0) { + dev_err(dev, "Can't find ac97-sync gpio\n"); + return gpio; + } + ret = devm_gpio_request(dev, gpio, "AC97 link sync"); + if (ret) { + dev_err(dev, "Failed requesting ac97-sync gpio\n"); + return ret; + } + cfg->gpio_sync = gpio; + + gpio = of_get_named_gpio(dev->of_node, "ac97-gpios", 1); + if (gpio < 0) { + dev_err(dev, "Can't find ac97-sdata gpio %d\n", gpio); + return gpio; + } + ret = devm_gpio_request(dev, gpio, "AC97 link sdata"); + if (ret) { + dev_err(dev, "Failed requesting ac97-sdata gpio\n"); + return ret; + } + cfg->gpio_sdata = gpio; + + gpio = of_get_named_gpio(dev->of_node, "ac97-gpios", 2); + if (gpio < 0) { + dev_err(dev, "Can't find ac97-reset gpio\n"); + return gpio; + } + ret = devm_gpio_request(dev, gpio, "AC97 link reset"); + if (ret) { + dev_err(dev, "Failed requesting ac97-reset gpio\n"); + return ret; + } + cfg->gpio_reset = gpio; + + return 0; +} + +struct snd_ac97_bus_ops *soc_ac97_ops; +EXPORT_SYMBOL_GPL(soc_ac97_ops); + +int snd_soc_set_ac97_ops(struct snd_ac97_bus_ops *ops) +{ + if (ops == soc_ac97_ops) + return 0; + + if (soc_ac97_ops && ops) + return -EBUSY; + + soc_ac97_ops = ops; + + return 0; +} +EXPORT_SYMBOL_GPL(snd_soc_set_ac97_ops); + +/** + * snd_soc_set_ac97_ops_of_reset - Set ac97 ops with generic ac97 reset functions + * + * This function sets the reset and warm_reset properties of ops and parses + * the device node of pdev to get pinctrl states and gpio numbers to use. + */ +int snd_soc_set_ac97_ops_of_reset(struct snd_ac97_bus_ops *ops, + struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct snd_ac97_reset_cfg cfg; + int ret; + + ret = snd_soc_ac97_parse_pinctl(dev, &cfg); + if (ret) + return ret; + + ret = snd_soc_set_ac97_ops(ops); + if (ret) + return ret; + + ops->warm_reset = snd_soc_ac97_warm_reset; + ops->reset = snd_soc_ac97_reset; + + snd_ac97_rst_cfg = cfg; + return 0; +} +EXPORT_SYMBOL_GPL(snd_soc_set_ac97_ops_of_reset); + +int snd_soc_ac97_register_dai_links(struct snd_soc_card *card) +{ + int i; + int ret; + + /* register any AC97 codecs */ + for (i = 0; i < card->num_rtd; i++) { + ret = soc_register_ac97_dai_link(&card->rtd[i]); + if (ret < 0) + goto err; + } + + return 0; +err: + dev_err(card->dev, + "ASoC: failed to register AC97: %d\n", ret); + while (--i >= 0) + soc_unregister_ac97_dai_link(&card->rtd[i]); + return ret; +} + +void snd_soc_ac97_add_pdata(struct snd_soc_pcm_runtime *rtd) +{ + unsigned int i; + + /* add platform data for AC97 devices */ + for (i = 0; i < rtd->num_codecs; i++) { + if (rtd->codec_dais[i]->driver->ac97_control) + snd_ac97_dev_add_pdata(rtd->codec_dais[i]->codec->ac97, + rtd->cpu_dai->ac97_pdata); + } +} -- cgit v1.2.3 From eda1a701fd9589b6ed15b109558bd4f6202e3829 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 10 Nov 2014 22:41:47 +0100 Subject: ASoC: ac97: Use static ac97_bus We always pass soc_ac97_ops to snd_soc_new_ac97_codec(). So instead of allocating a snd_ac97_bus in snd_soc_new_ac97_codec() just use a static one that gets initialized when snd_soc_set_ac97_ops() is called. Also drop the device number parameter from snd_soc_new_ac97_codec(). We currently only support one device per bus and all drivers pass 0 for the device number. And if we should ever support multiple devices per bus it wouldn't be up to individual AC'97 device drivers to pick their number, but rather either the AC'97 adapter driver or the core code will assign them. Signed-off-by: Lars-Peter Clausen Acked-by: Charles Keepax Signed-off-by: Mark Brown --- include/sound/soc.h | 3 +-- sound/soc/codecs/ad1980.c | 2 +- sound/soc/codecs/stac9766.c | 2 +- sound/soc/codecs/wm9705.c | 2 +- sound/soc/codecs/wm9712.c | 2 +- sound/soc/codecs/wm9713.c | 2 +- sound/soc/soc-ac97.c | 22 ++++++++-------------- 7 files changed, 14 insertions(+), 21 deletions(-) (limited to 'sound/soc/soc-ac97.c') diff --git a/include/sound/soc.h b/include/sound/soc.h index adef34fa5209..44b3ce531fd6 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -499,8 +499,7 @@ int snd_soc_test_bits(struct snd_soc_codec *codec, unsigned int reg, unsigned int mask, unsigned int value); #ifdef CONFIG_SND_SOC_AC97_BUS -int snd_soc_new_ac97_codec(struct snd_soc_codec *codec, - struct snd_ac97_bus_ops *ops, int num); +int snd_soc_new_ac97_codec(struct snd_soc_codec *codec); void snd_soc_free_ac97_codec(struct snd_soc_codec *codec); int snd_soc_set_ac97_ops(struct snd_ac97_bus_ops *ops); diff --git a/sound/soc/codecs/ad1980.c b/sound/soc/codecs/ad1980.c index 9ed4e12c26d1..f71cc21e67d4 100644 --- a/sound/soc/codecs/ad1980.c +++ b/sound/soc/codecs/ad1980.c @@ -220,7 +220,7 @@ static int ad1980_soc_probe(struct snd_soc_codec *codec) u16 vendor_id2; u16 ext_status; - ret = snd_soc_new_ac97_codec(codec, soc_ac97_ops, 0); + ret = snd_soc_new_ac97_codec(codec); if (ret < 0) { dev_err(codec->dev, "Failed to register AC97 codec\n"); return ret; diff --git a/sound/soc/codecs/stac9766.c b/sound/soc/codecs/stac9766.c index 53b810d23fea..45ac4a71ecff 100644 --- a/sound/soc/codecs/stac9766.c +++ b/sound/soc/codecs/stac9766.c @@ -336,7 +336,7 @@ static int stac9766_codec_probe(struct snd_soc_codec *codec) { int ret = 0; - ret = snd_soc_new_ac97_codec(codec, soc_ac97_ops, 0); + ret = snd_soc_new_ac97_codec(codec); if (ret < 0) goto codec_err; diff --git a/sound/soc/codecs/wm9705.c b/sound/soc/codecs/wm9705.c index 1650195f6c84..2cb8a31819fa 100644 --- a/sound/soc/codecs/wm9705.c +++ b/sound/soc/codecs/wm9705.c @@ -337,7 +337,7 @@ static int wm9705_soc_probe(struct snd_soc_codec *codec) { int ret = 0; - ret = snd_soc_new_ac97_codec(codec, soc_ac97_ops, 0); + ret = snd_soc_new_ac97_codec(codec); if (ret < 0) { dev_err(codec->dev, "Failed to register AC97 codec\n"); return ret; diff --git a/sound/soc/codecs/wm9712.c b/sound/soc/codecs/wm9712.c index 3fad37e0d33d..6b36223fd247 100644 --- a/sound/soc/codecs/wm9712.c +++ b/sound/soc/codecs/wm9712.c @@ -666,7 +666,7 @@ static int wm9712_soc_probe(struct snd_soc_codec *codec) { int ret = 0; - ret = snd_soc_new_ac97_codec(codec, soc_ac97_ops, 0); + ret = snd_soc_new_ac97_codec(codec); if (ret < 0) { dev_err(codec->dev, "Failed to register AC97 codec\n"); return ret; diff --git a/sound/soc/codecs/wm9713.c b/sound/soc/codecs/wm9713.c index 998e4c7b6b12..2071df707e88 100644 --- a/sound/soc/codecs/wm9713.c +++ b/sound/soc/codecs/wm9713.c @@ -1219,7 +1219,7 @@ static int wm9713_soc_probe(struct snd_soc_codec *codec) { int ret = 0, reg; - ret = snd_soc_new_ac97_codec(codec, soc_ac97_ops, 0); + ret = snd_soc_new_ac97_codec(codec); if (ret < 0) return ret; diff --git a/sound/soc/soc-ac97.c b/sound/soc/soc-ac97.c index da7b031a6eea..dbfca7e7dddb 100644 --- a/sound/soc/soc-ac97.c +++ b/sound/soc/soc-ac97.c @@ -38,6 +38,10 @@ struct snd_ac97_reset_cfg { int gpio_reset; }; +static struct snd_ac97_bus soc_ac97_bus = { + .ops = NULL, /* Gets initialized in snd_soc_set_ac97_ops() */ +}; + /* unregister ac97 codec */ static int soc_ac97_dev_unregister(struct snd_soc_codec *codec) { @@ -140,27 +144,17 @@ static void soc_ac97_device_release(struct device *dev) /** * snd_soc_new_ac97_codec - initailise AC97 device * @codec: audio codec - * @ops: AC97 bus operations - * @num: AC97 codec number * * Initialises AC97 codec resources for use by ad-hoc devices only. */ -int snd_soc_new_ac97_codec(struct snd_soc_codec *codec, - struct snd_ac97_bus_ops *ops, int num) +int snd_soc_new_ac97_codec(struct snd_soc_codec *codec) { codec->ac97 = kzalloc(sizeof(struct snd_ac97), GFP_KERNEL); if (codec->ac97 == NULL) return -ENOMEM; - codec->ac97->bus = kzalloc(sizeof(struct snd_ac97_bus), GFP_KERNEL); - if (codec->ac97->bus == NULL) { - kfree(codec->ac97); - codec->ac97 = NULL; - return -ENOMEM; - } - - codec->ac97->bus->ops = ops; - codec->ac97->num = num; + codec->ac97->bus = &soc_ac97_bus; + codec->ac97->num = 0; codec->ac97->dev.release = soc_ac97_device_release; /* @@ -183,7 +177,6 @@ EXPORT_SYMBOL_GPL(snd_soc_new_ac97_codec); void snd_soc_free_ac97_codec(struct snd_soc_codec *codec) { soc_unregister_ac97_codec(codec); - kfree(codec->ac97->bus); codec->ac97->bus = NULL; put_device(&codec->ac97->dev); codec->ac97 = NULL; @@ -314,6 +307,7 @@ int snd_soc_set_ac97_ops(struct snd_ac97_bus_ops *ops) return -EBUSY; soc_ac97_ops = ops; + soc_ac97_bus.ops = ops; return 0; } -- cgit v1.2.3 From bdfd60e3c0affb914549f1d22e8aeef71e7828e6 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 10 Nov 2014 22:41:48 +0100 Subject: ASoC: ac97: Merge soc_ac97_dev_{un,}register()/soc_{un,}register_ac97_codec() soc_{un,}register_ac97_codec() is just a simple wrapper around soc_ac97_dev_{un,}register(). There is no need to split these up into two different sets of functions. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/soc-ac97.c | 80 ++++++++++++++++++++-------------------------------- 1 file changed, 30 insertions(+), 50 deletions(-) (limited to 'sound/soc/soc-ac97.c') diff --git a/sound/soc/soc-ac97.c b/sound/soc/soc-ac97.c index dbfca7e7dddb..b5d23c976662 100644 --- a/sound/soc/soc-ac97.c +++ b/sound/soc/soc-ac97.c @@ -42,18 +42,28 @@ static struct snd_ac97_bus soc_ac97_bus = { .ops = NULL, /* Gets initialized in snd_soc_set_ac97_ops() */ }; -/* unregister ac97 codec */ -static int soc_ac97_dev_unregister(struct snd_soc_codec *codec) -{ - if (codec->ac97->dev.bus) - device_del(&codec->ac97->dev); - return 0; -} - /* register ac97 codec to bus */ -static int soc_ac97_dev_register(struct snd_soc_codec *codec) +static int soc_register_ac97_codec(struct snd_soc_codec *codec, + struct snd_soc_dai *codec_dai) { - int err; + int ret; + + /* Only instantiate AC97 if not already done by the adaptor + * for the generic AC97 subsystem. + */ + if (!codec_dai->driver->ac97_control || codec->ac97_registered) + return 0; + + /* + * It is possible that the AC97 device is already registered to + * the device subsystem. This happens when the device is created + * via snd_ac97_mixer(). Currently only SoC codec that does so + * is the generic AC97 glue but others migh emerge. + * + * In those cases we don't try to register the device again. + */ + if (!codec->ac97_created) + return 0; codec->ac97->dev.bus = &ac97_bus_type; codec->ac97->dev.parent = codec->component.card->dev; @@ -61,53 +71,23 @@ static int soc_ac97_dev_register(struct snd_soc_codec *codec) dev_set_name(&codec->ac97->dev, "%d-%d:%s", codec->component.card->snd_card->number, 0, codec->component.name); - err = device_add(&codec->ac97->dev); - if (err < 0) { - dev_err(codec->dev, "ASoC: Can't register ac97 bus\n"); - codec->ac97->dev.bus = NULL; - return err; + ret = device_add(&codec->ac97->dev); + if (ret < 0) { + dev_err(codec->dev, "ASoC: AC97 device register failed: %d\n", + ret); + return ret; } - return 0; -} - -static int soc_register_ac97_codec(struct snd_soc_codec *codec, - struct snd_soc_dai *codec_dai) -{ - int ret; + codec->ac97_registered = 1; - /* Only instantiate AC97 if not already done by the adaptor - * for the generic AC97 subsystem. - */ - if (codec_dai->driver->ac97_control && !codec->ac97_registered) { - /* - * It is possible that the AC97 device is already registered to - * the device subsystem. This happens when the device is created - * via snd_ac97_mixer(). Currently only SoC codec that does so - * is the generic AC97 glue but others migh emerge. - * - * In those cases we don't try to register the device again. - */ - if (!codec->ac97_created) - return 0; - - ret = soc_ac97_dev_register(codec); - if (ret < 0) { - dev_err(codec->dev, - "ASoC: AC97 device register failed: %d\n", ret); - return ret; - } - - codec->ac97_registered = 1; - } return 0; } static void soc_unregister_ac97_codec(struct snd_soc_codec *codec) { - if (codec->ac97_registered) { - soc_ac97_dev_unregister(codec); - codec->ac97_registered = 0; - } + if (!codec->ac97_registered) + return; + device_del(&codec->ac97->dev); + codec->ac97_registered = 0; } static int soc_register_ac97_dai_link(struct snd_soc_pcm_runtime *rtd) -- cgit v1.2.3 From ca005f324ee38308b319c693f40523d959027acf Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 10 Nov 2014 22:41:49 +0100 Subject: ASoC: ac97: Drop support for setting platform data via the CPU DAI This has no users since commit f0fba2ad1b6b ("ASoC: multi-component - ASoC Multi-Component Support") which was almost 5 years ago. Given that this runs after CODEC probe functions have been run it also doesn't seem to be that useful. So drop it altogether to make the code simpler. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- include/sound/soc-dai.h | 1 - include/sound/soc.h | 3 --- sound/soc/soc-ac97.c | 12 ------------ sound/soc/soc-core.c | 2 -- 4 files changed, 18 deletions(-) (limited to 'sound/soc/soc-ac97.c') diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h index e8b3080d196a..c0e04688c6ed 100644 --- a/include/sound/soc-dai.h +++ b/include/sound/soc-dai.h @@ -241,7 +241,6 @@ struct snd_soc_dai { const char *name; int id; struct device *dev; - void *ac97_pdata; /* platform_data for the ac97 codec */ /* driver ops */ struct snd_soc_dai_driver *driver; diff --git a/include/sound/soc.h b/include/sound/soc.h index 44b3ce531fd6..5b4dec693ca5 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -509,7 +509,6 @@ int snd_soc_set_ac97_ops_of_reset(struct snd_ac97_bus_ops *ops, extern struct snd_ac97_bus_ops *soc_ac97_ops; int snd_soc_ac97_register_dai_links(struct snd_soc_card *card); -void snd_soc_ac97_add_pdata(struct snd_soc_pcm_runtime *rtd); #else static inline int snd_soc_ac97_register_dai_links(struct snd_soc_card *card) @@ -517,8 +516,6 @@ static inline int snd_soc_ac97_register_dai_links(struct snd_soc_card *card) return 0; } -static inline void snd_soc_ac97_add_pdata(struct snd_soc_pcm_runtime *rtd) {} - static inline int snd_soc_set_ac97_ops_of_reset(struct snd_ac97_bus_ops *ops, struct platform_device *pdev) { diff --git a/sound/soc/soc-ac97.c b/sound/soc/soc-ac97.c index b5d23c976662..f2ed77b5169a 100644 --- a/sound/soc/soc-ac97.c +++ b/sound/soc/soc-ac97.c @@ -342,15 +342,3 @@ err: soc_unregister_ac97_dai_link(&card->rtd[i]); return ret; } - -void snd_soc_ac97_add_pdata(struct snd_soc_pcm_runtime *rtd) -{ - unsigned int i; - - /* add platform data for AC97 devices */ - for (i = 0; i < rtd->num_codecs; i++) { - if (rtd->codec_dais[i]->driver->ac97_control) - snd_ac97_dev_add_pdata(rtd->codec_dais[i]->codec->ac97, - rtd->cpu_dai->ac97_pdata); - } -} diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 026722f5ebf4..d883b4ad03ac 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -1375,8 +1375,6 @@ static int soc_probe_link_dais(struct snd_soc_card *card, int num, int order) } } - snd_soc_ac97_add_pdata(rtd); - return 0; } -- cgit v1.2.3 From 6794f709b7124ff1e574c4f4c9494418ab56c4b4 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 10 Nov 2014 22:41:50 +0100 Subject: ASoC: ac97: Drop delayed device registration We have all the information and dependencies we need to initialize and register the device available in snd_soc_new_ac97_codec(). So there is no need to delay the device registration until after the card itself as been registered. This makes the code significantly simpler and also makes it possible to use the AC'97 device in the CODECs probe function. The later will be required to be able to convert the AC'97 CODEC drivers to regmap. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- include/sound/soc.h | 10 ----- sound/soc/soc-ac97.c | 118 ++++++--------------------------------------------- sound/soc/soc-core.c | 4 -- 3 files changed, 14 insertions(+), 118 deletions(-) (limited to 'sound/soc/soc-ac97.c') diff --git a/include/sound/soc.h b/include/sound/soc.h index 5b4dec693ca5..206cc8d6eefa 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -507,15 +507,7 @@ int snd_soc_set_ac97_ops_of_reset(struct snd_ac97_bus_ops *ops, struct platform_device *pdev); extern struct snd_ac97_bus_ops *soc_ac97_ops; - -int snd_soc_ac97_register_dai_links(struct snd_soc_card *card); #else - -static inline int snd_soc_ac97_register_dai_links(struct snd_soc_card *card) -{ - return 0; -} - static inline int snd_soc_set_ac97_ops_of_reset(struct snd_ac97_bus_ops *ops, struct platform_device *pdev) { @@ -808,8 +800,6 @@ struct snd_soc_codec { struct snd_ac97 *ac97; /* for ad-hoc ac97 devices */ unsigned int cache_bypass:1; /* Suppress access to the cache */ unsigned int suspended:1; /* Codec is in suspend PM state */ - unsigned int ac97_registered:1; /* Codec has been AC97 registered */ - unsigned int ac97_created:1; /* Codec has been created by SoC */ unsigned int cache_init:1; /* codec cache has been initialized */ u32 cache_sync; /* Cache needs to be synced to hardware */ diff --git a/sound/soc/soc-ac97.c b/sound/soc/soc-ac97.c index f2ed77b5169a..920d76c43827 100644 --- a/sound/soc/soc-ac97.c +++ b/sound/soc/soc-ac97.c @@ -42,80 +42,6 @@ static struct snd_ac97_bus soc_ac97_bus = { .ops = NULL, /* Gets initialized in snd_soc_set_ac97_ops() */ }; -/* register ac97 codec to bus */ -static int soc_register_ac97_codec(struct snd_soc_codec *codec, - struct snd_soc_dai *codec_dai) -{ - int ret; - - /* Only instantiate AC97 if not already done by the adaptor - * for the generic AC97 subsystem. - */ - if (!codec_dai->driver->ac97_control || codec->ac97_registered) - return 0; - - /* - * It is possible that the AC97 device is already registered to - * the device subsystem. This happens when the device is created - * via snd_ac97_mixer(). Currently only SoC codec that does so - * is the generic AC97 glue but others migh emerge. - * - * In those cases we don't try to register the device again. - */ - if (!codec->ac97_created) - return 0; - - codec->ac97->dev.bus = &ac97_bus_type; - codec->ac97->dev.parent = codec->component.card->dev; - - dev_set_name(&codec->ac97->dev, "%d-%d:%s", - codec->component.card->snd_card->number, 0, - codec->component.name); - ret = device_add(&codec->ac97->dev); - if (ret < 0) { - dev_err(codec->dev, "ASoC: AC97 device register failed: %d\n", - ret); - return ret; - } - codec->ac97_registered = 1; - - return 0; -} - -static void soc_unregister_ac97_codec(struct snd_soc_codec *codec) -{ - if (!codec->ac97_registered) - return; - device_del(&codec->ac97->dev); - codec->ac97_registered = 0; -} - -static int soc_register_ac97_dai_link(struct snd_soc_pcm_runtime *rtd) -{ - int i, ret; - - for (i = 0; i < rtd->num_codecs; i++) { - struct snd_soc_dai *codec_dai = rtd->codec_dais[i]; - - ret = soc_register_ac97_codec(codec_dai->codec, codec_dai); - if (ret) { - while (--i >= 0) - soc_unregister_ac97_codec(codec_dai->codec); - return ret; - } - } - - return 0; -} - -static void soc_unregister_ac97_dai_link(struct snd_soc_pcm_runtime *rtd) -{ - int i; - - for (i = 0; i < rtd->num_codecs; i++) - soc_unregister_ac97_codec(rtd->codec_dais[i]->codec); -} - static void soc_ac97_device_release(struct device *dev) { kfree(to_ac97_t(dev)); @@ -129,22 +55,28 @@ static void soc_ac97_device_release(struct device *dev) */ int snd_soc_new_ac97_codec(struct snd_soc_codec *codec) { + int ret; + codec->ac97 = kzalloc(sizeof(struct snd_ac97), GFP_KERNEL); if (codec->ac97 == NULL) return -ENOMEM; codec->ac97->bus = &soc_ac97_bus; codec->ac97->num = 0; + + codec->ac97->dev.bus = &ac97_bus_type; + codec->ac97->dev.parent = codec->component.card->dev; codec->ac97->dev.release = soc_ac97_device_release; - /* - * Mark the AC97 device to be created by us. This way we ensure that the - * device will be registered with the device subsystem later on. - */ - codec->ac97_created = 1; - device_initialize(&codec->ac97->dev); + dev_set_name(&codec->ac97->dev, "%d-%d:%s", + codec->component.card->snd_card->number, 0, + codec->component.name); + + ret = device_register(&codec->ac97->dev); + if (ret) + put_device(&codec->ac97->dev); - return 0; + return ret; } EXPORT_SYMBOL_GPL(snd_soc_new_ac97_codec); @@ -156,11 +88,10 @@ EXPORT_SYMBOL_GPL(snd_soc_new_ac97_codec); */ void snd_soc_free_ac97_codec(struct snd_soc_codec *codec) { - soc_unregister_ac97_codec(codec); + device_del(&codec->ac97->dev); codec->ac97->bus = NULL; put_device(&codec->ac97->dev); codec->ac97 = NULL; - codec->ac97_created = 0; } EXPORT_SYMBOL_GPL(snd_soc_free_ac97_codec); @@ -321,24 +252,3 @@ int snd_soc_set_ac97_ops_of_reset(struct snd_ac97_bus_ops *ops, return 0; } EXPORT_SYMBOL_GPL(snd_soc_set_ac97_ops_of_reset); - -int snd_soc_ac97_register_dai_links(struct snd_soc_card *card) -{ - int i; - int ret; - - /* register any AC97 codecs */ - for (i = 0; i < card->num_rtd; i++) { - ret = soc_register_ac97_dai_link(&card->rtd[i]); - if (ret < 0) - goto err; - } - - return 0; -err: - dev_err(card->dev, - "ASoC: failed to register AC97: %d\n", ret); - while (--i >= 0) - soc_unregister_ac97_dai_link(&card->rtd[i]); - return ret; -} diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index d883b4ad03ac..fba6e28e18d3 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -1671,10 +1671,6 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card) goto probe_aux_dev_err; } - ret = snd_soc_ac97_register_dai_links(card); - if (ret < 0) - goto probe_aux_dev_err; - card->instantiated = 1; snd_soc_dapm_sync(&card->dapm); mutex_unlock(&card->mutex); -- cgit v1.2.3 From 358a8bb5628420529e4f0b77068155ca8fa8973b Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 10 Nov 2014 22:41:53 +0100 Subject: ASoC: ac97: Push snd_ac97 pointer to the driver level Now that the ASoC core no longer needs a handle to the AC'97 device that is associated with a CODEC we can remove it from the snd_soc_codec struct and push it into the individual driver state structs like we do for other communication buses. Doing so creates a clean separation between the AC'97 bus support and the ASoC core. Signed-off-by: Lars-Peter Clausen Acked-by: Charles Keepax Signed-off-by: Mark Brown --- include/sound/soc.h | 5 ++--- sound/soc/codecs/ac97.c | 17 +++++++++++++---- sound/soc/codecs/ad1980.c | 27 ++++++++++++++++++--------- sound/soc/codecs/stac9766.c | 38 ++++++++++++++++++++++++-------------- sound/soc/codecs/wm9705.c | 31 ++++++++++++++++++++++--------- sound/soc/codecs/wm9712.c | 32 +++++++++++++++++++++----------- sound/soc/codecs/wm9713.c | 31 ++++++++++++++++++++----------- sound/soc/soc-ac97.c | 40 +++++++++++++++++++++------------------- 8 files changed, 141 insertions(+), 80 deletions(-) (limited to 'sound/soc/soc-ac97.c') diff --git a/include/sound/soc.h b/include/sound/soc.h index 206cc8d6eefa..9e513ae11749 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -499,8 +499,8 @@ int snd_soc_test_bits(struct snd_soc_codec *codec, unsigned int reg, unsigned int mask, unsigned int value); #ifdef CONFIG_SND_SOC_AC97_BUS -int snd_soc_new_ac97_codec(struct snd_soc_codec *codec); -void snd_soc_free_ac97_codec(struct snd_soc_codec *codec); +struct snd_ac97 *snd_soc_new_ac97_codec(struct snd_soc_codec *codec); +void snd_soc_free_ac97_codec(struct snd_ac97 *ac97); int snd_soc_set_ac97_ops(struct snd_ac97_bus_ops *ops); int snd_soc_set_ac97_ops_of_reset(struct snd_ac97_bus_ops *ops, @@ -797,7 +797,6 @@ struct snd_soc_codec { struct list_head card_list; /* runtime */ - struct snd_ac97 *ac97; /* for ad-hoc ac97 devices */ unsigned int cache_bypass:1; /* Suppress access to the cache */ unsigned int suspended:1; /* Codec is in suspend PM state */ unsigned int cache_init:1; /* codec cache has been initialized */ diff --git a/sound/soc/codecs/ac97.c b/sound/soc/codecs/ac97.c index 5d90924e8b96..c6e5a313ebf4 100644 --- a/sound/soc/codecs/ac97.c +++ b/sound/soc/codecs/ac97.c @@ -37,10 +37,11 @@ static int ac97_prepare(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct snd_soc_codec *codec = dai->codec; + struct snd_ac97 *ac97 = snd_soc_codec_get_drvdata(codec); int reg = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ? AC97_PCM_FRONT_DAC_RATE : AC97_PCM_LR_ADC_RATE; - return snd_ac97_set_rate(codec->ac97, reg, substream->runtime->rate); + return snd_ac97_set_rate(ac97, reg, substream->runtime->rate); } #define STD_AC97_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\ @@ -70,6 +71,7 @@ static struct snd_soc_dai_driver ac97_dai = { static int ac97_soc_probe(struct snd_soc_codec *codec) { + struct snd_ac97 *ac97; struct snd_ac97_bus *ac97_bus; struct snd_ac97_template ac97_template; int ret; @@ -81,24 +83,31 @@ static int ac97_soc_probe(struct snd_soc_codec *codec) return ret; memset(&ac97_template, 0, sizeof(struct snd_ac97_template)); - ret = snd_ac97_mixer(ac97_bus, &ac97_template, &codec->ac97); + ret = snd_ac97_mixer(ac97_bus, &ac97_template, &ac97); if (ret < 0) return ret; + snd_soc_codec_set_drvdata(codec, ac97); + return 0; } #ifdef CONFIG_PM static int ac97_soc_suspend(struct snd_soc_codec *codec) { - snd_ac97_suspend(codec->ac97); + struct snd_ac97 *ac97 = snd_soc_codec_get_drvdata(codec); + + snd_ac97_suspend(ac97); return 0; } static int ac97_soc_resume(struct snd_soc_codec *codec) { - snd_ac97_resume(codec->ac97); + + struct snd_ac97 *ac97 = snd_soc_codec_get_drvdata(codec); + + snd_ac97_resume(ac97); return 0; } diff --git a/sound/soc/codecs/ad1980.c b/sound/soc/codecs/ad1980.c index c6cb101a5b8f..93bd47db6d0c 100644 --- a/sound/soc/codecs/ad1980.c +++ b/sound/soc/codecs/ad1980.c @@ -135,6 +135,7 @@ static const struct snd_soc_dapm_route ad1980_dapm_routes[] = { static unsigned int ac97_read(struct snd_soc_codec *codec, unsigned int reg) { + struct snd_ac97 *ac97 = snd_soc_codec_get_drvdata(codec); u16 *cache = codec->reg_cache; switch (reg) { @@ -144,7 +145,7 @@ static unsigned int ac97_read(struct snd_soc_codec *codec, case AC97_EXTENDED_STATUS: case AC97_VENDOR_ID1: case AC97_VENDOR_ID2: - return soc_ac97_ops->read(codec->ac97, reg); + return soc_ac97_ops->read(ac97, reg); default: reg = reg >> 1; @@ -158,9 +159,10 @@ static unsigned int ac97_read(struct snd_soc_codec *codec, static int ac97_write(struct snd_soc_codec *codec, unsigned int reg, unsigned int val) { + struct snd_ac97 *ac97 = snd_soc_codec_get_drvdata(codec); u16 *cache = codec->reg_cache; - soc_ac97_ops->write(codec->ac97, reg, val); + soc_ac97_ops->write(ac97, reg, val); reg = reg >> 1; if (reg < ARRAY_SIZE(ad1980_reg)) cache[reg] = val; @@ -186,16 +188,17 @@ static struct snd_soc_dai_driver ad1980_dai = { static int ad1980_reset(struct snd_soc_codec *codec, int try_warm) { + struct snd_ac97 *ac97 = snd_soc_codec_get_drvdata(codec); unsigned int retry_cnt = 0; do { if (try_warm && soc_ac97_ops->warm_reset) { - soc_ac97_ops->warm_reset(codec->ac97); + soc_ac97_ops->warm_reset(ac97); if (ac97_read(codec, AC97_RESET) == 0x0090) return 1; } - soc_ac97_ops->reset(codec->ac97); + soc_ac97_ops->reset(ac97); /* * Set bit 16slot in register 74h, then every slot will has only * 16 bits. This command is sent out in 20bit mode, in which @@ -215,16 +218,20 @@ static int ad1980_reset(struct snd_soc_codec *codec, int try_warm) static int ad1980_soc_probe(struct snd_soc_codec *codec) { + struct snd_ac97 *ac97; int ret; u16 vendor_id2; u16 ext_status; - ret = snd_soc_new_ac97_codec(codec); - if (ret < 0) { - dev_err(codec->dev, "Failed to register AC97 codec\n"); + ac97 = snd_soc_new_ac97_codec(codec); + if (IS_ERR(ac97)) { + ret = PTR_ERR(ac97); + dev_err(codec->dev, "Failed to register AC97 codec: %d\n", ret); return ret; } + snd_soc_codec_set_drvdata(codec, ac97); + ret = ad1980_reset(codec, 0); if (ret < 0) goto reset_err; @@ -261,13 +268,15 @@ static int ad1980_soc_probe(struct snd_soc_codec *codec) return 0; reset_err: - snd_soc_free_ac97_codec(codec); + snd_soc_free_ac97_codec(ac97); return ret; } static int ad1980_soc_remove(struct snd_soc_codec *codec) { - snd_soc_free_ac97_codec(codec); + struct snd_ac97 *ac97 = snd_soc_codec_get_drvdata(codec); + + snd_soc_free_ac97_codec(ac97); return 0; } diff --git a/sound/soc/codecs/stac9766.c b/sound/soc/codecs/stac9766.c index c0808061b08a..f37a79ec45e6 100644 --- a/sound/soc/codecs/stac9766.c +++ b/sound/soc/codecs/stac9766.c @@ -139,18 +139,19 @@ static const struct snd_kcontrol_new stac9766_snd_ac97_controls[] = { static int stac9766_ac97_write(struct snd_soc_codec *codec, unsigned int reg, unsigned int val) { + struct snd_ac97 *ac97 = snd_soc_codec_get_drvdata(codec); u16 *cache = codec->reg_cache; if (reg > AC97_STAC_PAGE0) { stac9766_ac97_write(codec, AC97_INT_PAGING, 0); - soc_ac97_ops->write(codec->ac97, reg, val); + soc_ac97_ops->write(ac97, reg, val); stac9766_ac97_write(codec, AC97_INT_PAGING, 1); return 0; } if (reg / 2 >= ARRAY_SIZE(stac9766_reg)) return -EIO; - soc_ac97_ops->write(codec->ac97, reg, val); + soc_ac97_ops->write(ac97, reg, val); cache[reg / 2] = val; return 0; } @@ -158,11 +159,12 @@ static int stac9766_ac97_write(struct snd_soc_codec *codec, unsigned int reg, static unsigned int stac9766_ac97_read(struct snd_soc_codec *codec, unsigned int reg) { + struct snd_ac97 *ac97 = snd_soc_codec_get_drvdata(codec); u16 val = 0, *cache = codec->reg_cache; if (reg > AC97_STAC_PAGE0) { stac9766_ac97_write(codec, AC97_INT_PAGING, 0); - val = soc_ac97_ops->read(codec->ac97, reg - AC97_STAC_PAGE0); + val = soc_ac97_ops->read(ac97, reg - AC97_STAC_PAGE0); stac9766_ac97_write(codec, AC97_INT_PAGING, 1); return val; } @@ -173,7 +175,7 @@ static unsigned int stac9766_ac97_read(struct snd_soc_codec *codec, reg == AC97_INT_PAGING || reg == AC97_VENDOR_ID1 || reg == AC97_VENDOR_ID2) { - val = soc_ac97_ops->read(codec->ac97, reg); + val = soc_ac97_ops->read(ac97, reg); return val; } return cache[reg / 2]; @@ -240,15 +242,17 @@ static int stac9766_set_bias_level(struct snd_soc_codec *codec, static int stac9766_reset(struct snd_soc_codec *codec, int try_warm) { + struct snd_ac97 *ac97 = snd_soc_codec_get_drvdata(codec); + if (try_warm && soc_ac97_ops->warm_reset) { - soc_ac97_ops->warm_reset(codec->ac97); + soc_ac97_ops->warm_reset(ac97); if (stac9766_ac97_read(codec, 0) == stac9766_reg[0]) return 1; } - soc_ac97_ops->reset(codec->ac97); + soc_ac97_ops->reset(ac97); if (soc_ac97_ops->warm_reset) - soc_ac97_ops->warm_reset(codec->ac97); + soc_ac97_ops->warm_reset(ac97); if (stac9766_ac97_read(codec, 0) != stac9766_reg[0]) return -EIO; return 0; @@ -262,6 +266,7 @@ static int stac9766_codec_suspend(struct snd_soc_codec *codec) static int stac9766_codec_resume(struct snd_soc_codec *codec) { + struct snd_ac97 *ac97 = snd_soc_codec_get_drvdata(codec); u16 id, reset; reset = 0; @@ -271,8 +276,8 @@ reset: printk(KERN_ERR "stac9766 failed to resume"); return -EIO; } - codec->ac97->bus->ops->warm_reset(codec->ac97); - id = soc_ac97_ops->read(codec->ac97, AC97_VENDOR_ID2); + ac97->bus->ops->warm_reset(ac97); + id = soc_ac97_ops->read(ac97, AC97_VENDOR_ID2); if (id != 0x4c13) { stac9766_reset(codec, 0); reset++; @@ -332,11 +337,14 @@ static struct snd_soc_dai_driver stac9766_dai[] = { static int stac9766_codec_probe(struct snd_soc_codec *codec) { + struct snd_ac97 *ac97; int ret = 0; - ret = snd_soc_new_ac97_codec(codec); - if (ret < 0) - goto codec_err; + ac97 = snd_soc_new_ac97_codec(codec); + if (IS_ERR(ac97)) + return PTR_ERR(ac97); + + snd_soc_codec_set_drvdata(codec, ac97); /* do a cold reset for the controller and then try * a warm reset followed by an optional cold reset for codec */ @@ -355,13 +363,15 @@ static int stac9766_codec_probe(struct snd_soc_codec *codec) return 0; codec_err: - snd_soc_free_ac97_codec(codec); + snd_soc_free_ac97_codec(ac97); return ret; } static int stac9766_codec_remove(struct snd_soc_codec *codec) { - snd_soc_free_ac97_codec(codec); + struct snd_ac97 *ac97 = snd_soc_codec_get_drvdata(codec); + + snd_soc_free_ac97_codec(ac97); return 0; } diff --git a/sound/soc/codecs/wm9705.c b/sound/soc/codecs/wm9705.c index 5b5118ba1526..d3a800fa6f06 100644 --- a/sound/soc/codecs/wm9705.c +++ b/sound/soc/codecs/wm9705.c @@ -203,13 +203,14 @@ static const struct snd_soc_dapm_route wm9705_audio_map[] = { /* We use a register cache to enhance read performance. */ static unsigned int ac97_read(struct snd_soc_codec *codec, unsigned int reg) { + struct snd_ac97 *ac97 = snd_soc_codec_get_drvdata(codec); u16 *cache = codec->reg_cache; switch (reg) { case AC97_RESET: case AC97_VENDOR_ID1: case AC97_VENDOR_ID2: - return soc_ac97_ops->read(codec->ac97, reg); + return soc_ac97_ops->read(ac97, reg); default: reg = reg >> 1; @@ -223,9 +224,10 @@ static unsigned int ac97_read(struct snd_soc_codec *codec, unsigned int reg) static int ac97_write(struct snd_soc_codec *codec, unsigned int reg, unsigned int val) { + struct snd_ac97 *ac97 = snd_soc_codec_get_drvdata(codec); u16 *cache = codec->reg_cache; - soc_ac97_ops->write(codec->ac97, reg, val); + soc_ac97_ops->write(ac97, reg, val); reg = reg >> 1; if (reg < (ARRAY_SIZE(wm9705_reg))) cache[reg] = val; @@ -293,8 +295,10 @@ static struct snd_soc_dai_driver wm9705_dai[] = { static int wm9705_reset(struct snd_soc_codec *codec) { + struct snd_ac97 *ac97 = snd_soc_codec_get_drvdata(codec); + if (soc_ac97_ops->reset) { - soc_ac97_ops->reset(codec->ac97); + soc_ac97_ops->reset(ac97); if (ac97_read(codec, 0) == wm9705_reg[0]) return 0; /* Success */ } @@ -307,13 +311,16 @@ static int wm9705_reset(struct snd_soc_codec *codec) #ifdef CONFIG_PM static int wm9705_soc_suspend(struct snd_soc_codec *codec) { - soc_ac97_ops->write(codec->ac97, AC97_POWERDOWN, 0xffff); + struct snd_ac97 *ac97 = snd_soc_codec_get_drvdata(codec); + + soc_ac97_ops->write(ac97, AC97_POWERDOWN, 0xffff); return 0; } static int wm9705_soc_resume(struct snd_soc_codec *codec) { + struct snd_ac97 *ac97 = snd_soc_codec_get_drvdata(codec); int i, ret; u16 *cache = codec->reg_cache; @@ -322,7 +329,7 @@ static int wm9705_soc_resume(struct snd_soc_codec *codec) return ret; for (i = 2; i < ARRAY_SIZE(wm9705_reg) << 1; i += 2) { - soc_ac97_ops->write(codec->ac97, i, cache[i>>1]); + soc_ac97_ops->write(ac97, i, cache[i>>1]); } return 0; @@ -334,14 +341,18 @@ static int wm9705_soc_resume(struct snd_soc_codec *codec) static int wm9705_soc_probe(struct snd_soc_codec *codec) { + struct snd_ac97 *ac97; int ret = 0; - ret = snd_soc_new_ac97_codec(codec); - if (ret < 0) { + ac97 = snd_soc_new_ac97_codec(codec); + if (IS_ERR(ac97)) { + ret = PTR_ERR(ac97); dev_err(codec->dev, "Failed to register AC97 codec\n"); return ret; } + snd_soc_codec_set_drvdata(codec, ac97); + ret = wm9705_reset(codec); if (ret) goto reset_err; @@ -349,13 +360,15 @@ static int wm9705_soc_probe(struct snd_soc_codec *codec) return 0; reset_err: - snd_soc_free_ac97_codec(codec); + snd_soc_free_ac97_codec(ac97); return ret; } static int wm9705_soc_remove(struct snd_soc_codec *codec) { - snd_soc_free_ac97_codec(codec); + struct snd_ac97 *ac97 = snd_soc_codec_get_drvdata(codec); + + snd_soc_free_ac97_codec(ac97); return 0; } diff --git a/sound/soc/codecs/wm9712.c b/sound/soc/codecs/wm9712.c index 9fa794baa5f8..52a211be5b47 100644 --- a/sound/soc/codecs/wm9712.c +++ b/sound/soc/codecs/wm9712.c @@ -24,6 +24,7 @@ #include "wm9712.h" struct wm9712_priv { + struct snd_ac97 *ac97; unsigned int hp_mixer[2]; struct mutex lock; }; @@ -484,12 +485,13 @@ static const struct snd_soc_dapm_route wm9712_audio_map[] = { static unsigned int ac97_read(struct snd_soc_codec *codec, unsigned int reg) { + struct wm9712_priv *wm9712 = snd_soc_codec_get_drvdata(codec); u16 *cache = codec->reg_cache; if (reg == AC97_RESET || reg == AC97_GPIO_STATUS || reg == AC97_VENDOR_ID1 || reg == AC97_VENDOR_ID2 || reg == AC97_REC_GAIN) - return soc_ac97_ops->read(codec->ac97, reg); + return soc_ac97_ops->read(wm9712->ac97, reg); else { reg = reg >> 1; @@ -503,9 +505,10 @@ static unsigned int ac97_read(struct snd_soc_codec *codec, static int ac97_write(struct snd_soc_codec *codec, unsigned int reg, unsigned int val) { + struct wm9712_priv *wm9712 = snd_soc_codec_get_drvdata(codec); u16 *cache = codec->reg_cache; - soc_ac97_ops->write(codec->ac97, reg, val); + soc_ac97_ops->write(wm9712->ac97, reg, val); reg = reg >> 1; if (reg < (ARRAY_SIZE(wm9712_reg))) cache[reg] = val; @@ -613,15 +616,17 @@ static int wm9712_set_bias_level(struct snd_soc_codec *codec, static int wm9712_reset(struct snd_soc_codec *codec, int try_warm) { + struct wm9712_priv *wm9712 = snd_soc_codec_get_drvdata(codec); + if (try_warm && soc_ac97_ops->warm_reset) { - soc_ac97_ops->warm_reset(codec->ac97); + soc_ac97_ops->warm_reset(wm9712->ac97); if (ac97_read(codec, 0) == wm9712_reg[0]) return 1; } - soc_ac97_ops->reset(codec->ac97); + soc_ac97_ops->reset(wm9712->ac97); if (soc_ac97_ops->warm_reset) - soc_ac97_ops->warm_reset(codec->ac97); + soc_ac97_ops->warm_reset(wm9712->ac97); if (ac97_read(codec, 0) != wm9712_reg[0]) goto err; return 0; @@ -639,6 +644,7 @@ static int wm9712_soc_suspend(struct snd_soc_codec *codec) static int wm9712_soc_resume(struct snd_soc_codec *codec) { + struct wm9712_priv *wm9712 = snd_soc_codec_get_drvdata(codec); int i, ret; u16 *cache = codec->reg_cache; @@ -654,7 +660,7 @@ static int wm9712_soc_resume(struct snd_soc_codec *codec) if (i == AC97_INT_PAGING || i == AC97_POWERDOWN || (i > 0x58 && i != 0x5c)) continue; - soc_ac97_ops->write(codec->ac97, i, cache[i>>1]); + soc_ac97_ops->write(wm9712->ac97, i, cache[i>>1]); } } @@ -663,11 +669,13 @@ static int wm9712_soc_resume(struct snd_soc_codec *codec) static int wm9712_soc_probe(struct snd_soc_codec *codec) { + struct wm9712_priv *wm9712 = snd_soc_codec_get_drvdata(codec); int ret = 0; - ret = snd_soc_new_ac97_codec(codec); - if (ret < 0) { - dev_err(codec->dev, "Failed to register AC97 codec\n"); + wm9712->ac97 = snd_soc_new_ac97_codec(codec); + if (IS_ERR(wm9712->ac97)) { + ret = PTR_ERR(wm9712->ac97); + dev_err(codec->dev, "Failed to register AC97 codec: %d\n", ret); return ret; } @@ -683,13 +691,15 @@ static int wm9712_soc_probe(struct snd_soc_codec *codec) return 0; reset_err: - snd_soc_free_ac97_codec(codec); + snd_soc_free_ac97_codec(wm9712->ac97); return ret; } static int wm9712_soc_remove(struct snd_soc_codec *codec) { - snd_soc_free_ac97_codec(codec); + struct wm9712_priv *wm9712 = snd_soc_codec_get_drvdata(codec); + + snd_soc_free_ac97_codec(wm9712->ac97); return 0; } diff --git a/sound/soc/codecs/wm9713.c b/sound/soc/codecs/wm9713.c index cd1b266d3af3..6c95d98b0eb1 100644 --- a/sound/soc/codecs/wm9713.c +++ b/sound/soc/codecs/wm9713.c @@ -30,6 +30,7 @@ #include "wm9713.h" struct wm9713_priv { + struct snd_ac97 *ac97; u32 pll_in; /* PLL input frequency */ unsigned int hp_mixer[2]; struct mutex lock; @@ -674,12 +675,13 @@ static const struct snd_soc_dapm_route wm9713_audio_map[] = { static unsigned int ac97_read(struct snd_soc_codec *codec, unsigned int reg) { + struct wm9713_priv *wm9713 = snd_soc_codec_get_drvdata(codec); u16 *cache = codec->reg_cache; if (reg == AC97_RESET || reg == AC97_GPIO_STATUS || reg == AC97_VENDOR_ID1 || reg == AC97_VENDOR_ID2 || reg == AC97_CD) - return soc_ac97_ops->read(codec->ac97, reg); + return soc_ac97_ops->read(wm9713->ac97, reg); else { reg = reg >> 1; @@ -693,8 +695,10 @@ static unsigned int ac97_read(struct snd_soc_codec *codec, static int ac97_write(struct snd_soc_codec *codec, unsigned int reg, unsigned int val) { + struct wm9713_priv *wm9713 = snd_soc_codec_get_drvdata(codec); + u16 *cache = codec->reg_cache; - soc_ac97_ops->write(codec->ac97, reg, val); + soc_ac97_ops->write(wm9713->ac97, reg, val); reg = reg >> 1; if (reg < (ARRAY_SIZE(wm9713_reg))) cache[reg] = val; @@ -1121,15 +1125,17 @@ static struct snd_soc_dai_driver wm9713_dai[] = { int wm9713_reset(struct snd_soc_codec *codec, int try_warm) { + struct wm9713_priv *wm9713 = snd_soc_codec_get_drvdata(codec); + if (try_warm && soc_ac97_ops->warm_reset) { - soc_ac97_ops->warm_reset(codec->ac97); + soc_ac97_ops->warm_reset(wm9713->ac97); if (ac97_read(codec, 0) == wm9713_reg[0]) return 1; } - soc_ac97_ops->reset(codec->ac97); + soc_ac97_ops->reset(wm9713->ac97); if (soc_ac97_ops->warm_reset) - soc_ac97_ops->warm_reset(codec->ac97); + soc_ac97_ops->warm_reset(wm9713->ac97); if (ac97_read(codec, 0) != wm9713_reg[0]) { dev_err(codec->dev, "Failed to reset: AC97 link error\n"); return -EIO; @@ -1207,7 +1213,7 @@ static int wm9713_soc_resume(struct snd_soc_codec *codec) if (i == AC97_POWERDOWN || i == AC97_EXTENDED_MID || i == AC97_EXTENDED_MSTATUS || i > 0x66) continue; - soc_ac97_ops->write(codec->ac97, i, cache[i>>1]); + soc_ac97_ops->write(wm9713->ac97, i, cache[i>>1]); } } @@ -1216,11 +1222,12 @@ static int wm9713_soc_resume(struct snd_soc_codec *codec) static int wm9713_soc_probe(struct snd_soc_codec *codec) { + struct wm9713_priv *wm9713 = snd_soc_codec_get_drvdata(codec); int ret = 0, reg; - ret = snd_soc_new_ac97_codec(codec); - if (ret < 0) - return ret; + wm9713->ac97 = snd_soc_new_ac97_codec(codec); + if (IS_ERR(wm9713->ac97)) + return PTR_ERR(wm9713->ac97); /* do a cold reset for the controller and then try * a warm reset followed by an optional cold reset for codec */ @@ -1238,13 +1245,15 @@ static int wm9713_soc_probe(struct snd_soc_codec *codec) return 0; reset_err: - snd_soc_free_ac97_codec(codec); + snd_soc_free_ac97_codec(wm9713->ac97); return ret; } static int wm9713_soc_remove(struct snd_soc_codec *codec) { - snd_soc_free_ac97_codec(codec); + struct wm9713_priv *wm9713 = snd_soc_codec_get_drvdata(codec); + + snd_soc_free_ac97_codec(wm9713->ac97); return 0; } diff --git a/sound/soc/soc-ac97.c b/sound/soc/soc-ac97.c index 920d76c43827..2e10e9a38376 100644 --- a/sound/soc/soc-ac97.c +++ b/sound/soc/soc-ac97.c @@ -53,30 +53,33 @@ static void soc_ac97_device_release(struct device *dev) * * Initialises AC97 codec resources for use by ad-hoc devices only. */ -int snd_soc_new_ac97_codec(struct snd_soc_codec *codec) +struct snd_ac97 *snd_soc_new_ac97_codec(struct snd_soc_codec *codec) { + struct snd_ac97 *ac97; int ret; - codec->ac97 = kzalloc(sizeof(struct snd_ac97), GFP_KERNEL); - if (codec->ac97 == NULL) - return -ENOMEM; + ac97 = kzalloc(sizeof(struct snd_ac97), GFP_KERNEL); + if (ac97 == NULL) + return ERR_PTR(-ENOMEM); - codec->ac97->bus = &soc_ac97_bus; - codec->ac97->num = 0; + ac97->bus = &soc_ac97_bus; + ac97->num = 0; - codec->ac97->dev.bus = &ac97_bus_type; - codec->ac97->dev.parent = codec->component.card->dev; - codec->ac97->dev.release = soc_ac97_device_release; + ac97->dev.bus = &ac97_bus_type; + ac97->dev.parent = codec->component.card->dev; + ac97->dev.release = soc_ac97_device_release; - dev_set_name(&codec->ac97->dev, "%d-%d:%s", + dev_set_name(&ac97->dev, "%d-%d:%s", codec->component.card->snd_card->number, 0, codec->component.name); - ret = device_register(&codec->ac97->dev); - if (ret) - put_device(&codec->ac97->dev); + ret = device_register(&ac97->dev); + if (ret) { + put_device(&ac97->dev); + return ERR_PTR(ret); + } - return ret; + return ac97; } EXPORT_SYMBOL_GPL(snd_soc_new_ac97_codec); @@ -86,12 +89,11 @@ EXPORT_SYMBOL_GPL(snd_soc_new_ac97_codec); * * Frees AC97 codec device resources. */ -void snd_soc_free_ac97_codec(struct snd_soc_codec *codec) +void snd_soc_free_ac97_codec(struct snd_ac97 *ac97) { - device_del(&codec->ac97->dev); - codec->ac97->bus = NULL; - put_device(&codec->ac97->dev); - codec->ac97 = NULL; + device_del(&ac97->dev); + ac97->bus = NULL; + put_device(&ac97->dev); } EXPORT_SYMBOL_GPL(snd_soc_free_ac97_codec); -- cgit v1.2.3