From d77ae3329292baebfc6eced97d2e12b66349f83c Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Mon, 23 Jul 2012 12:39:51 +0300 Subject: ASoC: omap-mcpdm: Convert to use devm_* Switch to use devm_* te make the probe/remove code more cleaner. Signed-off-by: Peter Ujfalusi Signed-off-by: Mark Brown --- sound/soc/omap/omap-mcpdm.c | 52 ++++++++++++--------------------------------- 1 file changed, 13 insertions(+), 39 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/omap/omap-mcpdm.c b/sound/soc/omap/omap-mcpdm.c index 2c66e2498a45..f7babb374a37 100644 --- a/sound/soc/omap/omap-mcpdm.c +++ b/sound/soc/omap/omap-mcpdm.c @@ -445,9 +445,8 @@ static __devinit int asoc_mcpdm_probe(struct platform_device *pdev) { struct omap_mcpdm *mcpdm; struct resource *res; - int ret = 0; - mcpdm = kzalloc(sizeof(struct omap_mcpdm), GFP_KERNEL); + mcpdm = devm_kzalloc(&pdev->dev, sizeof(struct omap_mcpdm), GFP_KERNEL); if (!mcpdm) return -ENOMEM; @@ -456,55 +455,30 @@ static __devinit int asoc_mcpdm_probe(struct platform_device *pdev) mutex_init(&mcpdm->mutex); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (res == NULL) { - dev_err(&pdev->dev, "no resource\n"); - goto err_res; - } + if (res == NULL) + return -ENOMEM; - if (!request_mem_region(res->start, resource_size(res), "McPDM")) { - ret = -EBUSY; - goto err_res; - } + if (!devm_request_mem_region(&pdev->dev, res->start, + resource_size(res), "McPDM")) + return -EBUSY; - mcpdm->io_base = ioremap(res->start, resource_size(res)); - if (!mcpdm->io_base) { - ret = -ENOMEM; - goto err_iomap; - } + mcpdm->io_base = devm_ioremap(&pdev->dev, res->start, + resource_size(res)); + if (!mcpdm->io_base) + return -ENOMEM; mcpdm->irq = platform_get_irq(pdev, 0); - if (mcpdm->irq < 0) { - ret = mcpdm->irq; - goto err_irq; - } + if (mcpdm->irq < 0) + return mcpdm->irq; mcpdm->dev = &pdev->dev; - ret = snd_soc_register_dai(&pdev->dev, &omap_mcpdm_dai); - if (!ret) - return 0; - -err_irq: - iounmap(mcpdm->io_base); -err_iomap: - release_mem_region(res->start, resource_size(res)); -err_res: - kfree(mcpdm); - return ret; + return snd_soc_register_dai(&pdev->dev, &omap_mcpdm_dai); } static int __devexit asoc_mcpdm_remove(struct platform_device *pdev) { - struct omap_mcpdm *mcpdm = platform_get_drvdata(pdev); - struct resource *res; - snd_soc_unregister_dai(&pdev->dev); - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - iounmap(mcpdm->io_base); - release_mem_region(res->start, resource_size(res)); - - kfree(mcpdm); return 0; } -- cgit v1.2.3 From 0651322bfcf3ca51802c6d8d161d6d1c9f3013eb Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Mon, 23 Jul 2012 17:25:15 +0530 Subject: ASoC: isabelle: Remove version.h header file inclusion version.h header file inclusion is no longer needed for this file. Signed-off-by: Sachin Kamat Signed-off-by: Mark Brown --- sound/soc/codecs/isabelle.c | 1 - 1 file changed, 1 deletion(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/isabelle.c b/sound/soc/codecs/isabelle.c index 5d8f39e32978..1bf55602c9eb 100644 --- a/sound/soc/codecs/isabelle.c +++ b/sound/soc/codecs/isabelle.c @@ -13,7 +13,6 @@ */ #include #include -#include #include #include #include -- cgit v1.2.3 From fbfe69836c088bcc0c5a0f32e788d3aef5f66aca Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 23 Jul 2012 20:14:43 +0100 Subject: ASoC: wm8994: Implement support for self-oscillation mode in the FLL The FLLs in the WM8994 series devices can be started without any reference being supplied, mainly for use in analogue bypass cases. Implement support for this mode. Signed-off-by: Mark Brown --- sound/soc/codecs/wm8994.c | 21 +++++++++++++++------ sound/soc/codecs/wm8994.h | 9 +++++---- 2 files changed, 20 insertions(+), 10 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index 04ef03175c51..2c9b8b7fdf3d 100644 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c @@ -2102,6 +2102,10 @@ static int _wm8994_set_fll(struct snd_soc_codec *codec, int id, int src, case WM8994_FLL_SRC_LRCLK: case WM8994_FLL_SRC_BCLK: break; + case WM8994_FLL_SRC_INTERNAL: + freq_in = 12000000; + freq_out = 12000000; + break; default: return -EINVAL; } @@ -2164,9 +2168,11 @@ static int _wm8994_set_fll(struct snd_soc_codec *codec, int id, int src, fll.n << WM8994_FLL1_N_SHIFT); snd_soc_update_bits(codec, WM8994_FLL1_CONTROL_5 + reg_offset, - WM8958_FLL1_BYP | + WM8994_FLL1_FRC_NCO | WM8958_FLL1_BYP | WM8994_FLL1_REFCLK_DIV_MASK | WM8994_FLL1_REFCLK_SRC_MASK, + ((src == WM8994_FLL_SRC_INTERNAL) + << WM8994_FLL1_FRC_NCO_SHIFT) | (fll.clk_ref_div << WM8994_FLL1_REFCLK_DIV_SHIFT) | (src - 1)); @@ -2192,13 +2198,16 @@ static int _wm8994_set_fll(struct snd_soc_codec *codec, int id, int src, } } + reg = WM8994_FLL1_ENA; + if (fll.k) - reg = WM8994_FLL1_ENA | WM8994_FLL1_FRAC; - else - reg = WM8994_FLL1_ENA; + reg |= WM8994_FLL1_FRAC; + if (src == WM8994_FLL_SRC_INTERNAL) + reg |= WM8994_FLL1_OSC_ENA; + snd_soc_update_bits(codec, WM8994_FLL1_CONTROL_1 + reg_offset, - WM8994_FLL1_ENA | WM8994_FLL1_FRAC, - reg); + WM8994_FLL1_ENA | WM8994_FLL1_OSC_ENA | + WM8994_FLL1_FRAC, reg); if (wm8994->fll_locked_irq) { timeout = wait_for_completion_timeout(&wm8994->fll_locked[id], diff --git a/sound/soc/codecs/wm8994.h b/sound/soc/codecs/wm8994.h index d77e06f0a675..19068d8fa301 100644 --- a/sound/soc/codecs/wm8994.h +++ b/sound/soc/codecs/wm8994.h @@ -28,10 +28,11 @@ #define WM8994_FLL1 1 #define WM8994_FLL2 2 -#define WM8994_FLL_SRC_MCLK1 1 -#define WM8994_FLL_SRC_MCLK2 2 -#define WM8994_FLL_SRC_LRCLK 3 -#define WM8994_FLL_SRC_BCLK 4 +#define WM8994_FLL_SRC_MCLK1 1 +#define WM8994_FLL_SRC_MCLK2 2 +#define WM8994_FLL_SRC_LRCLK 3 +#define WM8994_FLL_SRC_BCLK 4 +#define WM8994_FLL_SRC_INTERNAL 5 enum wm8994_vmid_mode { WM8994_VMID_NORMAL, -- cgit v1.2.3 From 0dcd47426abde223b2386165470ec45d9777478e Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Thu, 26 Jul 2012 11:28:37 +0100 Subject: ASoC: ux500: Strengthen error checking after memory allocation Currently there is no out-of-memory error checking after attempting to allocate memory for the ux500_msp or ux500_msp_i2s_drvdata data structures. Instead we go about populating them regardless. This patch applies the necessary error checking to prevent a panic. Signed-off-by: Lee Jones Signed-off-by: Mark Brown --- sound/soc/ux500/ux500_msp_dai.c | 3 +++ sound/soc/ux500/ux500_msp_i2s.c | 2 ++ 2 files changed, 5 insertions(+) (limited to 'sound/soc') diff --git a/sound/soc/ux500/ux500_msp_dai.c b/sound/soc/ux500/ux500_msp_dai.c index 057e28ef770e..772cb19d2fb3 100644 --- a/sound/soc/ux500/ux500_msp_dai.c +++ b/sound/soc/ux500/ux500_msp_dai.c @@ -760,6 +760,9 @@ static int __devinit ux500_msp_drv_probe(struct platform_device *pdev) drvdata = devm_kzalloc(&pdev->dev, sizeof(struct ux500_msp_i2s_drvdata), GFP_KERNEL); + if (!drvdata) + return -ENOMEM; + drvdata->fmt = 0; drvdata->slots = 1; drvdata->tx_mask = 0x01; diff --git a/sound/soc/ux500/ux500_msp_i2s.c b/sound/soc/ux500/ux500_msp_i2s.c index 5c472f335a64..36be11e47ad6 100644 --- a/sound/soc/ux500/ux500_msp_i2s.c +++ b/sound/soc/ux500/ux500_msp_i2s.c @@ -673,6 +673,8 @@ int ux500_msp_i2s_init_msp(struct platform_device *pdev, *msp_p = devm_kzalloc(&pdev->dev, sizeof(struct ux500_msp), GFP_KERNEL); msp = *msp_p; + if (!msp) + return -ENOMEM; msp->id = platform_data->id; msp->dev = &pdev->dev; -- cgit v1.2.3 From 5ef75e710b4950439f953c4897e4a871c2f9dc8f Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Wed, 25 Jul 2012 16:09:11 +0300 Subject: ASoC: omap-abe-twl6040: Add device tree support When the board boots with device tree the driver will receive the name of the card, DAPM routing map, phandle for the audio components described in the dts file, mclk speed, and the possibility of detecting the jack detection. The card will be set up based on this information. Since the routing is provided via DT we can mark the card fully routed so core can take care of disconnecting the unused pins. Signed-off-by: Peter Ujfalusi Reviwed-by: Mark Brown Signed-off-by: Mark Brown --- .../devicetree/bindings/sound/omap-abe-twl6040.txt | 91 +++++++++++++ sound/soc/omap/omap-abe-twl6040.c | 145 ++++++++++++++++----- 2 files changed, 206 insertions(+), 30 deletions(-) create mode 100644 Documentation/devicetree/bindings/sound/omap-abe-twl6040.txt (limited to 'sound/soc') diff --git a/Documentation/devicetree/bindings/sound/omap-abe-twl6040.txt b/Documentation/devicetree/bindings/sound/omap-abe-twl6040.txt new file mode 100644 index 000000000000..65dec876cb2d --- /dev/null +++ b/Documentation/devicetree/bindings/sound/omap-abe-twl6040.txt @@ -0,0 +1,91 @@ +* Texas Instruments OMAP4+ and twl6040 based audio setups + +Required properties: +- compatible: "ti,abe-twl6040" +- ti,model: Name of the sound card ( for example "SDP4430") +- ti,mclk-freq: MCLK frequency for HPPLL operation +- ti,mcpdm: phandle for the McPDM node +- ti,twl6040: phandle for the twl6040 core node +- ti,audio-routing: List of connections between audio components. + Each entry is a pair of strings, the first being the connection's sink, + the second being the connection's source. + +Optional properties: +- ti,dmic: phandle for the OMAP dmic node if the machine have it connected +- ti,jack_detection: Need to be set to <1> if the board capable to detect jack + insertion, removal. + +Available audio endpoints for the audio-routing table: + +Board connectors: + * Headset Stereophone + * Earphone Spk + * Ext Spk + * Line Out + * Vibrator + * Headset Mic + * Main Handset Mic + * Sub Handset Mic + * Line In + * Digital Mic + +twl6040 pins: + * HSOL + * HSOR + * EP + * HFL + * HFR + * AUXL + * AUXR + * VIBRAL + * VIBRAR + * HSMIC + * MAINMIC + * SUBMIC + * AFML + * AFMR + + * Headset Mic Bias + * Main Mic Bias + * Digital Mic1 Bias + * Digital Mic2 Bias + +Digital mic pins: + * DMic + +Example: + +sound { + compatible = "ti,abe-twl6040"; + ti,model = "SDP4430"; + + ti,jack-detection = <1>; + ti,mclk-freq = <38400000>; + + ti,mcpdm = <&mcpdm>; + ti,dmic = <&dmic>; + + ti,twl6040 = <&twl6040>; + + /* Audio routing */ + ti,audio-routing = + "Headset Stereophone", "HSOL", + "Headset Stereophone", "HSOR", + "Earphone Spk", "EP", + "Ext Spk", "HFL", + "Ext Spk", "HFR", + "Line Out", "AUXL", + "Line Out", "AUXR", + "Vibrator", "VIBRAL", + "Vibrator", "VIBRAR", + "HSMIC", "Headset Mic", + "Headset Mic", "Headset Mic Bias", + "MAINMIC", "Main Handset Mic", + "Main Handset Mic", "Main Mic Bias", + "SUBMIC", "Sub Handset Mic", + "Sub Handset Mic", "Main Mic Bias", + "AFML", "Line In", + "AFMR", "Line In", + "DMic", "Digital Mic", + "Digital Mic", "Digital Mic1 Bias"; +}; diff --git a/sound/soc/omap/omap-abe-twl6040.c b/sound/soc/omap/omap-abe-twl6040.c index 9d93793d3077..be525dfe9faa 100644 --- a/sound/soc/omap/omap-abe-twl6040.c +++ b/sound/soc/omap/omap-abe-twl6040.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -43,6 +44,8 @@ struct abe_twl6040 { int jack_detection; /* board can detect jack events */ int mclk_freq; /* MCLK frequency speed for twl6040 */ + + struct platform_device *dmic_codec_dev; }; static int omap_abe_hw_params(struct snd_pcm_substream *substream, @@ -185,17 +188,6 @@ static int omap_abe_twl6040_init(struct snd_soc_pcm_runtime *rtd) int hs_trim; int ret = 0; - /* Disable not connected paths if not used */ - twl6040_disconnect_pin(dapm, pdata->has_hs, "Headset Stereophone"); - twl6040_disconnect_pin(dapm, pdata->has_hf, "Ext Spk"); - twl6040_disconnect_pin(dapm, pdata->has_ep, "Earphone Spk"); - twl6040_disconnect_pin(dapm, pdata->has_aux, "Line Out"); - twl6040_disconnect_pin(dapm, pdata->has_vibra, "Vinrator"); - twl6040_disconnect_pin(dapm, pdata->has_hsmic, "Headset Mic"); - twl6040_disconnect_pin(dapm, pdata->has_mainmic, "Main Handset Mic"); - twl6040_disconnect_pin(dapm, pdata->has_submic, "Sub Handset Mic"); - twl6040_disconnect_pin(dapm, pdata->has_afm, "Line In"); - /* * Configure McPDM offset cancellation based on the HSOTRIM value from * twl6040. @@ -216,6 +208,24 @@ static int omap_abe_twl6040_init(struct snd_soc_pcm_runtime *rtd) twl6040_hs_jack_detect(codec, &hs_jack, SND_JACK_HEADSET); } + /* + * NULL pdata means we booted with DT. In this case the routing is + * provided and the card is fully routed, no need to mark pins. + */ + if (!pdata) + return ret; + + /* Disable not connected paths if not used */ + twl6040_disconnect_pin(dapm, pdata->has_hs, "Headset Stereophone"); + twl6040_disconnect_pin(dapm, pdata->has_hf, "Ext Spk"); + twl6040_disconnect_pin(dapm, pdata->has_ep, "Earphone Spk"); + twl6040_disconnect_pin(dapm, pdata->has_aux, "Line Out"); + twl6040_disconnect_pin(dapm, pdata->has_vibra, "Vinrator"); + twl6040_disconnect_pin(dapm, pdata->has_hsmic, "Headset Mic"); + twl6040_disconnect_pin(dapm, pdata->has_mainmic, "Main Handset Mic"); + twl6040_disconnect_pin(dapm, pdata->has_submic, "Sub Handset Mic"); + twl6040_disconnect_pin(dapm, pdata->has_afm, "Line In"); + return ret; } @@ -270,52 +280,116 @@ static struct snd_soc_card omap_abe_card = { static __devinit int omap_abe_probe(struct platform_device *pdev) { struct omap_abe_twl6040_data *pdata = dev_get_platdata(&pdev->dev); + struct device_node *node = pdev->dev.of_node; struct snd_soc_card *card = &omap_abe_card; struct abe_twl6040 *priv; int num_links = 0; - int ret; + int ret = 0; card->dev = &pdev->dev; - if (!pdata) { - dev_err(&pdev->dev, "Missing pdata\n"); - return -ENODEV; - } - priv = devm_kzalloc(&pdev->dev, sizeof(struct abe_twl6040), GFP_KERNEL); if (priv == NULL) return -ENOMEM; - if (pdata->card_name) { - card->name = pdata->card_name; + priv->dmic_codec_dev = ERR_PTR(-EINVAL); + + if (node) { + struct device_node *dai_node; + + if (snd_soc_of_parse_card_name(card, "ti,model")) { + dev_err(&pdev->dev, "Card name is not provided\n"); + return -ENODEV; + } + + ret = snd_soc_of_parse_audio_routing(card, + "ti,audio-routing"); + if (ret) { + dev_err(&pdev->dev, + "Error while parsing DAPM routing\n"); + return ret; + } + + dai_node = of_parse_phandle(node, "ti,mcpdm", 0); + if (!dai_node) { + dev_err(&pdev->dev, "McPDM node is not provided\n"); + return -EINVAL; + } + abe_twl6040_dai_links[0].cpu_dai_name = NULL; + abe_twl6040_dai_links[0].cpu_of_node = dai_node; + + dai_node = of_parse_phandle(node, "ti,dmic", 0); + if (dai_node) { + num_links = 2; + abe_twl6040_dai_links[1].cpu_dai_name = NULL; + abe_twl6040_dai_links[1].cpu_of_node = dai_node; + + priv->dmic_codec_dev = platform_device_register_simple( + "dmic-codec", -1, NULL, 0); + if (IS_ERR(priv->dmic_codec_dev)) { + dev_err(&pdev->dev, + "Can't instantiate dmic-codec\n"); + return PTR_ERR(priv->dmic_codec_dev); + } + } else { + num_links = 1; + } + + of_property_read_u32(node, "ti,jack-detection", + &priv->jack_detection); + of_property_read_u32(node, "ti,mclk-freq", + &priv->mclk_freq); + if (!priv->mclk_freq) { + dev_err(&pdev->dev, "MCLK frequency not provided\n"); + ret = -EINVAL; + goto err_unregister; + } + + omap_abe_card.fully_routed = 1; + } else if (pdata) { + if (pdata->card_name) { + card->name = pdata->card_name; + } else { + dev_err(&pdev->dev, "Card name is not provided\n"); + return -ENODEV; + } + + if (pdata->has_dmic) + num_links = 2; + else + num_links = 1; + + priv->jack_detection = pdata->jack_detection; + priv->mclk_freq = pdata->mclk_freq; } else { - dev_err(&pdev->dev, "Card name is not provided\n"); + dev_err(&pdev->dev, "Missing pdata\n"); return -ENODEV; } - priv->jack_detection = pdata->jack_detection; - priv->mclk_freq = pdata->mclk_freq; - if (!priv->mclk_freq) { dev_err(&pdev->dev, "MCLK frequency missing\n"); - return -ENODEV; + ret = -ENODEV; + goto err_unregister; } - if (pdata->has_dmic) - num_links = 2; - else - num_links = 1; - card->dai_link = abe_twl6040_dai_links; card->num_links = num_links; snd_soc_card_set_drvdata(card, priv); ret = snd_soc_register_card(card); - if (ret) + if (ret) { dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", ret); + goto err_unregister; + } + + return 0; + +err_unregister: + if (!IS_ERR(priv->dmic_codec_dev)) + platform_device_unregister(priv->dmic_codec_dev); return ret; } @@ -323,17 +397,28 @@ static __devinit int omap_abe_probe(struct platform_device *pdev) static int __devexit omap_abe_remove(struct platform_device *pdev) { struct snd_soc_card *card = platform_get_drvdata(pdev); + struct abe_twl6040 *priv = snd_soc_card_get_drvdata(card); snd_soc_unregister_card(card); + if (!IS_ERR(priv->dmic_codec_dev)) + platform_device_unregister(priv->dmic_codec_dev); + return 0; } +static const struct of_device_id omap_abe_of_match[] = { + {.compatible = "ti,abe-twl6040", }, + { }, +}; +MODULE_DEVICE_TABLE(of, omap_abe_of_match); + static struct platform_driver omap_abe_driver = { .driver = { .name = "omap-abe-twl6040", .owner = THIS_MODULE, .pm = &snd_soc_pm_ops, + .of_match_table = omap_abe_of_match, }, .probe = omap_abe_probe, .remove = __devexit_p(omap_abe_remove), -- cgit v1.2.3 From acaf24f015b2bdd34032188d26c3092d6ca749b3 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 25 Jul 2012 22:57:35 +0100 Subject: ASoC: jack: Always update jack state even for noop changes Now that DAPM is very cheap for most updates we've no need to avoid trying to run it so always notify even if we don't think there are any changes. This avoids potential issues with bootstrapping state like the pin state or other notifiers when there's nothing in the jack. Signed-off-by: Mark Brown Acked-by: Liam Girdwood --- sound/soc/soc-jack.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/soc-jack.c b/sound/soc/soc-jack.c index 7f8b3b7428bb..2ca3c734a288 100644 --- a/sound/soc/soc-jack.c +++ b/sound/soc/soc-jack.c @@ -83,11 +83,6 @@ void snd_soc_jack_report(struct snd_soc_jack *jack, int status, int mask) jack->status &= ~mask; jack->status |= status & mask; - /* The DAPM sync is expensive enough to be worth skipping. - * However, empty mask means pin synchronization is desired. */ - if (mask && (jack->status == oldstatus)) - goto out; - trace_snd_soc_jack_notify(jack, status); list_for_each_entry(pin, &jack->pins, list) { @@ -109,7 +104,6 @@ void snd_soc_jack_report(struct snd_soc_jack *jack, int status, int mask) snd_jack_report(jack->jack, jack->status); -out: mutex_unlock(&jack->mutex); } EXPORT_SYMBOL_GPL(snd_soc_jack_report); -- cgit v1.2.3 From 8cb8e83bfa7cb63ad4b3c3b79410766da397124b Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 25 Jul 2012 18:10:03 +0100 Subject: ASoC: wm_hubs: Move CODEC stored in private data into wm_hubs Further wm_hubs code will use this. Signed-off-by: Mark Brown --- sound/soc/codecs/wm8958-dsp2.c | 28 ++++++++++++++++------------ sound/soc/codecs/wm8994.c | 28 +++++++++++++--------------- sound/soc/codecs/wm8994.h | 1 - sound/soc/codecs/wm_hubs.c | 2 ++ sound/soc/codecs/wm_hubs.h | 2 ++ 5 files changed, 33 insertions(+), 28 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/wm8958-dsp2.c b/sound/soc/codecs/wm8958-dsp2.c index 1332692ef81b..00121ba36597 100644 --- a/sound/soc/codecs/wm8958-dsp2.c +++ b/sound/soc/codecs/wm8958-dsp2.c @@ -946,7 +946,7 @@ void wm8958_dsp2_init(struct snd_soc_codec *codec) wm8994->mbc_texts = kmalloc(sizeof(char *) * pdata->num_mbc_cfgs, GFP_KERNEL); if (!wm8994->mbc_texts) { - dev_err(wm8994->codec->dev, + dev_err(wm8994->hubs.codec->dev, "Failed to allocate %d MBC config texts\n", pdata->num_mbc_cfgs); return; @@ -958,9 +958,10 @@ void wm8958_dsp2_init(struct snd_soc_codec *codec) wm8994->mbc_enum.max = pdata->num_mbc_cfgs; wm8994->mbc_enum.texts = wm8994->mbc_texts; - ret = snd_soc_add_codec_controls(wm8994->codec, control, 1); + ret = snd_soc_add_codec_controls(wm8994->hubs.codec, + control, 1); if (ret != 0) - dev_err(wm8994->codec->dev, + dev_err(wm8994->hubs.codec->dev, "Failed to add MBC mode controls: %d\n", ret); } @@ -974,7 +975,7 @@ void wm8958_dsp2_init(struct snd_soc_codec *codec) wm8994->vss_texts = kmalloc(sizeof(char *) * pdata->num_vss_cfgs, GFP_KERNEL); if (!wm8994->vss_texts) { - dev_err(wm8994->codec->dev, + dev_err(wm8994->hubs.codec->dev, "Failed to allocate %d VSS config texts\n", pdata->num_vss_cfgs); return; @@ -986,9 +987,10 @@ void wm8958_dsp2_init(struct snd_soc_codec *codec) wm8994->vss_enum.max = pdata->num_vss_cfgs; wm8994->vss_enum.texts = wm8994->vss_texts; - ret = snd_soc_add_codec_controls(wm8994->codec, control, 1); + ret = snd_soc_add_codec_controls(wm8994->hubs.codec, + control, 1); if (ret != 0) - dev_err(wm8994->codec->dev, + dev_err(wm8994->hubs.codec->dev, "Failed to add VSS mode controls: %d\n", ret); } @@ -1003,7 +1005,7 @@ void wm8958_dsp2_init(struct snd_soc_codec *codec) wm8994->vss_hpf_texts = kmalloc(sizeof(char *) * pdata->num_vss_hpf_cfgs, GFP_KERNEL); if (!wm8994->vss_hpf_texts) { - dev_err(wm8994->codec->dev, + dev_err(wm8994->hubs.codec->dev, "Failed to allocate %d VSS HPF config texts\n", pdata->num_vss_hpf_cfgs); return; @@ -1015,9 +1017,10 @@ void wm8958_dsp2_init(struct snd_soc_codec *codec) wm8994->vss_hpf_enum.max = pdata->num_vss_hpf_cfgs; wm8994->vss_hpf_enum.texts = wm8994->vss_hpf_texts; - ret = snd_soc_add_codec_controls(wm8994->codec, control, 1); + ret = snd_soc_add_codec_controls(wm8994->hubs.codec, + control, 1); if (ret != 0) - dev_err(wm8994->codec->dev, + dev_err(wm8994->hubs.codec->dev, "Failed to add VSS HPFmode controls: %d\n", ret); } @@ -1033,7 +1036,7 @@ void wm8958_dsp2_init(struct snd_soc_codec *codec) wm8994->enh_eq_texts = kmalloc(sizeof(char *) * pdata->num_enh_eq_cfgs, GFP_KERNEL); if (!wm8994->enh_eq_texts) { - dev_err(wm8994->codec->dev, + dev_err(wm8994->hubs.codec->dev, "Failed to allocate %d enhanced EQ config texts\n", pdata->num_enh_eq_cfgs); return; @@ -1045,9 +1048,10 @@ void wm8958_dsp2_init(struct snd_soc_codec *codec) wm8994->enh_eq_enum.max = pdata->num_enh_eq_cfgs; wm8994->enh_eq_enum.texts = wm8994->enh_eq_texts; - ret = snd_soc_add_codec_controls(wm8994->codec, control, 1); + ret = snd_soc_add_codec_controls(wm8994->hubs.codec, + control, 1); if (ret != 0) - dev_err(wm8994->codec->dev, + dev_err(wm8994->hubs.codec->dev, "Failed to add enhanced EQ controls: %d\n", ret); } diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index 2c9b8b7fdf3d..1237c11c8c35 100644 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c @@ -3036,7 +3036,7 @@ static int wm8994_codec_resume(struct snd_soc_codec *codec) static void wm8994_handle_retune_mobile_pdata(struct wm8994_priv *wm8994) { - struct snd_soc_codec *codec = wm8994->codec; + struct snd_soc_codec *codec = wm8994->hubs.codec; struct wm8994_pdata *pdata = wm8994->pdata; struct snd_kcontrol_new controls[] = { SOC_ENUM_EXT("AIF1.1 EQ Mode", @@ -3094,16 +3094,16 @@ static void wm8994_handle_retune_mobile_pdata(struct wm8994_priv *wm8994) wm8994->retune_mobile_enum.max = wm8994->num_retune_mobile_texts; wm8994->retune_mobile_enum.texts = wm8994->retune_mobile_texts; - ret = snd_soc_add_codec_controls(wm8994->codec, controls, + ret = snd_soc_add_codec_controls(wm8994->hubs.codec, controls, ARRAY_SIZE(controls)); if (ret != 0) - dev_err(wm8994->codec->dev, + dev_err(wm8994->hubs.codec->dev, "Failed to add ReTune Mobile controls: %d\n", ret); } static void wm8994_handle_pdata(struct wm8994_priv *wm8994) { - struct snd_soc_codec *codec = wm8994->codec; + struct snd_soc_codec *codec = wm8994->hubs.codec; struct wm8994_pdata *pdata = wm8994->pdata; int ret, i; @@ -3132,10 +3132,10 @@ static void wm8994_handle_pdata(struct wm8994_priv *wm8994) }; /* We need an array of texts for the enum API */ - wm8994->drc_texts = devm_kzalloc(wm8994->codec->dev, + wm8994->drc_texts = devm_kzalloc(wm8994->hubs.codec->dev, sizeof(char *) * pdata->num_drc_cfgs, GFP_KERNEL); if (!wm8994->drc_texts) { - dev_err(wm8994->codec->dev, + dev_err(wm8994->hubs.codec->dev, "Failed to allocate %d DRC config texts\n", pdata->num_drc_cfgs); return; @@ -3147,10 +3147,10 @@ static void wm8994_handle_pdata(struct wm8994_priv *wm8994) wm8994->drc_enum.max = pdata->num_drc_cfgs; wm8994->drc_enum.texts = wm8994->drc_texts; - ret = snd_soc_add_codec_controls(wm8994->codec, controls, + ret = snd_soc_add_codec_controls(wm8994->hubs.codec, controls, ARRAY_SIZE(controls)); if (ret != 0) - dev_err(wm8994->codec->dev, + dev_err(wm8994->hubs.codec->dev, "Failed to add DRC mode controls: %d\n", ret); for (i = 0; i < WM8994_NUM_DRC; i++) @@ -3163,7 +3163,7 @@ static void wm8994_handle_pdata(struct wm8994_priv *wm8994) if (pdata->num_retune_mobile_cfgs) wm8994_handle_retune_mobile_pdata(wm8994); else - snd_soc_add_codec_controls(wm8994->codec, wm8994_eq_controls, + snd_soc_add_codec_controls(wm8994->hubs.codec, wm8994_eq_controls, ARRAY_SIZE(wm8994_eq_controls)); for (i = 0; i < ARRAY_SIZE(pdata->micbias); i++) { @@ -3318,7 +3318,7 @@ static void wm8994_mic_work(struct work_struct *work) static irqreturn_t wm8994_mic_irq(int irq, void *data) { struct wm8994_priv *priv = data; - struct snd_soc_codec *codec = priv->codec; + struct snd_soc_codec *codec = priv->hubs.codec; #ifndef CONFIG_SND_SOC_WM8994_MODULE trace_snd_soc_jack_irq(dev_name(codec->dev)); @@ -3431,7 +3431,7 @@ static void wm8958_default_micdet(u16 status, void *data) static irqreturn_t wm1811_jackdet_irq(int irq, void *data) { struct wm8994_priv *wm8994 = data; - struct snd_soc_codec *codec = wm8994->codec; + struct snd_soc_codec *codec = wm8994->hubs.codec; int reg; bool present; @@ -3609,7 +3609,7 @@ EXPORT_SYMBOL_GPL(wm8958_mic_detect); static irqreturn_t wm8958_mic_irq(int irq, void *data) { struct wm8994_priv *wm8994 = data; - struct snd_soc_codec *codec = wm8994->codec; + struct snd_soc_codec *codec = wm8994->hubs.codec; int reg, count; /* @@ -3699,13 +3699,11 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec) unsigned int reg; int ret, i; - wm8994->codec = codec; + wm8994->hubs.codec = codec; codec->control_data = control->regmap; snd_soc_codec_set_cache_io(codec, 16, 16, SND_SOC_REGMAP); - wm8994->codec = codec; - mutex_init(&wm8994->accdet_lock); INIT_DELAYED_WORK(&wm8994->mic_work, wm8994_mic_work); diff --git a/sound/soc/codecs/wm8994.h b/sound/soc/codecs/wm8994.h index 19068d8fa301..e6d8209b8f29 100644 --- a/sound/soc/codecs/wm8994.h +++ b/sound/soc/codecs/wm8994.h @@ -73,7 +73,6 @@ struct wm8994; struct wm8994_priv { struct wm_hubs_data hubs; struct wm8994 *wm8994; - struct snd_soc_codec *codec; int sysclk[2]; int sysclk_rate[2]; int mclk[2]; diff --git a/sound/soc/codecs/wm_hubs.c b/sound/soc/codecs/wm_hubs.c index 61baa48823cb..728a18010a49 100644 --- a/sound/soc/codecs/wm_hubs.c +++ b/sound/soc/codecs/wm_hubs.c @@ -1112,6 +1112,8 @@ int wm_hubs_add_analogue_routes(struct snd_soc_codec *codec, struct wm_hubs_data *hubs = snd_soc_codec_get_drvdata(codec); struct snd_soc_dapm_context *dapm = &codec->dapm; + hubs->codec = codec; + INIT_LIST_HEAD(&hubs->dcs_cache); init_completion(&hubs->dcs_done); diff --git a/sound/soc/codecs/wm_hubs.h b/sound/soc/codecs/wm_hubs.h index da2dc899ce6d..a5a09e6f87d5 100644 --- a/sound/soc/codecs/wm_hubs.h +++ b/sound/soc/codecs/wm_hubs.h @@ -46,6 +46,8 @@ struct wm_hubs_data { bool dcs_done_irq; struct completion dcs_done; + + struct snd_soc_codec *codec; }; extern int wm_hubs_add_analogue_controls(struct snd_soc_codec *); -- cgit v1.2.3 From 99af79dff5a609fe886d271bbc91e1a95eca3066 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 25 Jul 2012 23:03:36 +0100 Subject: ASoC: wm8994: Ensure we get a notification on startup for jackdet Since jackdet only reports deltas it won't generate an interrupt on startup when a jack is not present. This doesn't make a difference to userspace but does mean we don't generate a notification via the internal notifier chains. Fix that by scheduling a work to poll the chip after the clock is enabled. Use an extremely large timeout since there's no urgency and we don't want to report a false negative. Signed-off-by: Mark Brown --- sound/soc/codecs/wm8994.c | 37 ++++++++++++++++++++++++++++++++++++- sound/soc/codecs/wm8994.h | 2 ++ 2 files changed, 38 insertions(+), 1 deletion(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index 1237c11c8c35..7bb0c2c824cc 100644 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c @@ -789,11 +789,27 @@ static int clk_sys_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) { struct snd_soc_codec *codec = w->codec; + struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); switch (event) { case SND_SOC_DAPM_PRE_PMU: return configure_clock(codec); + case SND_SOC_DAPM_POST_PMU: + /* + * JACKDET won't run until we start the clock and it + * only reports deltas, make sure we notify the state + * up the stack on startup. Use a *very* generous + * timeout for paranoia, there's no urgency and we + * don't want false reports. + */ + if (wm8994->jackdet && !wm8994->clk_has_run) { + schedule_delayed_work(&wm8994->jackdet_bootstrap, + msecs_to_jiffies(1000)); + wm8994->clk_has_run = true; + } + break; + case SND_SOC_DAPM_POST_PMD: configure_clock(codec); break; @@ -1632,7 +1648,8 @@ SND_SOC_DAPM_SUPPLY("VMID", SND_SOC_NOPM, 0, 0, vmid_event, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), SND_SOC_DAPM_SUPPLY("CLK_SYS", SND_SOC_NOPM, 0, 0, clk_sys_event, - SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_PRE_PMD), SND_SOC_DAPM_SUPPLY("DSP1CLK", SND_SOC_NOPM, 3, 0, NULL, 0), SND_SOC_DAPM_SUPPLY("DSP2CLK", SND_SOC_NOPM, 2, 0, NULL, 0), @@ -3508,10 +3525,22 @@ static irqreturn_t wm1811_jackdet_irq(int irq, void *data) SND_JACK_MECHANICAL | SND_JACK_HEADSET | wm8994->btn_mask); + /* Since we only report deltas force an update, ensures we + * avoid bootstrapping issues with the core. */ + snd_soc_jack_report(wm8994->micdet[0].jack, 0, 0); + pm_runtime_put(codec->dev); return IRQ_HANDLED; } +static void wm1811_jackdet_bootstrap(struct work_struct *work) +{ + struct wm8994_priv *wm8994 = container_of(work, + struct wm8994_priv, + jackdet_bootstrap.work); + wm1811_jackdet_irq(0, wm8994); +} + /** * wm8958_mic_detect - Enable microphone detection via the WM8958 IRQ * @@ -3582,6 +3611,10 @@ int wm8958_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack, * otherwise jump straight to microphone detection. */ if (wm8994->jackdet) { + /* Disable debounce for the initial detect */ + snd_soc_update_bits(codec, WM1811_JACKDET_CTRL, + WM1811_JACKDET_DB, 0); + snd_soc_update_bits(codec, WM8958_MICBIAS2, WM8958_MICB2_DISCH, WM8958_MICB2_DISCH); @@ -3706,6 +3739,8 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec) mutex_init(&wm8994->accdet_lock); INIT_DELAYED_WORK(&wm8994->mic_work, wm8994_mic_work); + INIT_DELAYED_WORK(&wm8994->jackdet_bootstrap, + wm1811_jackdet_bootstrap); for (i = 0; i < ARRAY_SIZE(wm8994->fll_locked); i++) init_completion(&wm8994->fll_locked[i]); diff --git a/sound/soc/codecs/wm8994.h b/sound/soc/codecs/wm8994.h index e6d8209b8f29..f142ec198db3 100644 --- a/sound/soc/codecs/wm8994.h +++ b/sound/soc/codecs/wm8994.h @@ -81,6 +81,7 @@ struct wm8994_priv { struct completion fll_locked[2]; bool fll_locked_irq; bool fll_byp; + bool clk_has_run; int vmid_refcount; int active_refcount; @@ -134,6 +135,7 @@ struct wm8994_priv { int btn_mask; bool jackdet; int jackdet_mode; + struct delayed_work jackdet_bootstrap; wm8958_micdet_cb jack_cb; void *jack_cb_data; -- cgit v1.2.3 From fae4efa23ac012a57d45682bc22d540271c54532 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 23 Jul 2012 19:49:06 +0100 Subject: ASoC: wm_hubs: Factor out DC servo readback code It's currently only used in one place but another user will be added shortly and there's an argument it's clearer anyway. Also add support for readback in mode 1, though it's not currently used. Signed-off-by: Mark Brown --- sound/soc/codecs/wm_hubs.c | 65 ++++++++++++++++++++++++++++++---------------- 1 file changed, 43 insertions(+), 22 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/wm_hubs.c b/sound/soc/codecs/wm_hubs.c index 728a18010a49..6ab69f32f249 100644 --- a/sound/soc/codecs/wm_hubs.c +++ b/sound/soc/codecs/wm_hubs.c @@ -199,6 +199,47 @@ static void wm_hubs_dcs_cache_set(struct snd_soc_codec *codec, u16 dcs_cfg) list_add_tail(&cache->list, &hubs->dcs_cache); } +static void wm_hubs_read_dc_servo(struct snd_soc_codec *codec, + u16 *reg_l, u16 *reg_r) +{ + struct wm_hubs_data *hubs = snd_soc_codec_get_drvdata(codec); + u16 dcs_reg, reg; + + switch (hubs->dcs_readback_mode) { + case 2: + dcs_reg = WM8994_DC_SERVO_4E; + break; + case 1: + dcs_reg = WM8994_DC_SERVO_READBACK; + break; + default: + dcs_reg = WM8993_DC_SERVO_3; + break; + } + + /* Different chips in the family support different readback + * methods. + */ + switch (hubs->dcs_readback_mode) { + case 0: + *reg_l = snd_soc_read(codec, WM8993_DC_SERVO_READBACK_1) + & WM8993_DCS_INTEG_CHAN_0_MASK; + *reg_r = snd_soc_read(codec, WM8993_DC_SERVO_READBACK_2) + & WM8993_DCS_INTEG_CHAN_1_MASK; + break; + case 2: + case 1: + reg = snd_soc_read(codec, dcs_reg); + *reg_r = (reg & WM8993_DCS_DAC_WR_VAL_1_MASK) + >> WM8993_DCS_DAC_WR_VAL_1_SHIFT; + *reg_l = reg & WM8993_DCS_DAC_WR_VAL_0_MASK; + break; + default: + WARN(1, "Unknown DCS readback method\n"); + return; + } +} + /* * Startup calibration of the DC servo */ @@ -207,7 +248,7 @@ static void calibrate_dc_servo(struct snd_soc_codec *codec) struct wm_hubs_data *hubs = snd_soc_codec_get_drvdata(codec); struct wm_hubs_dcs_cache *cache; s8 offset; - u16 reg, reg_l, reg_r, dcs_cfg, dcs_reg; + u16 reg_l, reg_r, dcs_cfg, dcs_reg; switch (hubs->dcs_readback_mode) { case 2: @@ -245,27 +286,7 @@ static void calibrate_dc_servo(struct snd_soc_codec *codec) WM8993_DCS_TRIG_STARTUP_1); } - /* Different chips in the family support different readback - * methods. - */ - switch (hubs->dcs_readback_mode) { - case 0: - reg_l = snd_soc_read(codec, WM8993_DC_SERVO_READBACK_1) - & WM8993_DCS_INTEG_CHAN_0_MASK; - reg_r = snd_soc_read(codec, WM8993_DC_SERVO_READBACK_2) - & WM8993_DCS_INTEG_CHAN_1_MASK; - break; - case 2: - case 1: - reg = snd_soc_read(codec, dcs_reg); - reg_r = (reg & WM8993_DCS_DAC_WR_VAL_1_MASK) - >> WM8993_DCS_DAC_WR_VAL_1_SHIFT; - reg_l = reg & WM8993_DCS_DAC_WR_VAL_0_MASK; - break; - default: - WARN(1, "Unknown DCS readback method\n"); - return; - } + wm_hubs_read_dc_servo(codec, ®_l, ®_r); dev_dbg(codec->dev, "DCS input: %x %x\n", reg_l, reg_r); -- cgit v1.2.3 From a7892c35cfad4d6c6ccf1242b55c1004b0d5d1d1 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 23 Jul 2012 19:50:45 +0100 Subject: ASoC: wm_hubs: Rename calibrate_dc_servo() Really we're enabling it here and the name will become very confusing shortly. Signed-off-by: Mark Brown --- sound/soc/codecs/wm_hubs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/wm_hubs.c b/sound/soc/codecs/wm_hubs.c index 6ab69f32f249..05a02e1b7e92 100644 --- a/sound/soc/codecs/wm_hubs.c +++ b/sound/soc/codecs/wm_hubs.c @@ -243,7 +243,7 @@ static void wm_hubs_read_dc_servo(struct snd_soc_codec *codec, /* * Startup calibration of the DC servo */ -static void calibrate_dc_servo(struct snd_soc_codec *codec) +static void enable_dc_servo(struct snd_soc_codec *codec) { struct wm_hubs_data *hubs = snd_soc_codec_get_drvdata(codec); struct wm_hubs_dcs_cache *cache; @@ -556,7 +556,7 @@ static int hp_event(struct snd_soc_dapm_widget *w, snd_soc_update_bits(codec, WM8993_DC_SERVO_1, WM8993_DCS_TIMER_PERIOD_01_MASK, 0); - calibrate_dc_servo(codec); + enable_dc_servo(codec); reg |= WM8993_HPOUT1R_OUTP | WM8993_HPOUT1R_RMV_SHORT | WM8993_HPOUT1L_OUTP | WM8993_HPOUT1L_RMV_SHORT; -- cgit v1.2.3 From 7435d4eec76ee9debffb070f3e0d67615a828673 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 26 Jul 2012 14:49:11 +0100 Subject: ASoC: wm8994: Fix some indentation issues Signed-off-by: Mark Brown --- sound/soc/codecs/wm8994.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index 7bb0c2c824cc..5fc31797994a 100644 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c @@ -2182,7 +2182,7 @@ static int _wm8994_set_fll(struct snd_soc_codec *codec, int id, int src, snd_soc_update_bits(codec, WM8994_FLL1_CONTROL_4 + reg_offset, WM8994_FLL1_N_MASK, - fll.n << WM8994_FLL1_N_SHIFT); + fll.n << WM8994_FLL1_N_SHIFT); snd_soc_update_bits(codec, WM8994_FLL1_CONTROL_5 + reg_offset, WM8994_FLL1_FRC_NCO | WM8958_FLL1_BYP | @@ -3371,7 +3371,7 @@ static void wm8958_default_micdet(u16 status, void *data) snd_soc_jack_report(wm8994->micdet[0].jack, 0, wm8994->btn_mask | - SND_JACK_HEADSET); + SND_JACK_HEADSET); } return; } -- cgit v1.2.3 From d95e933730b3eb7b06bd778dc1d8f0ab3702b607 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 26 Jul 2012 15:25:48 +0100 Subject: ASoC: ab8500: Remove pointless cast There's never any need to cast away from void. Signed-off-by: Mark Brown Acked-by: Lee Jones --- sound/soc/codecs/ab8500-codec.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/ab8500-codec.c b/sound/soc/codecs/ab8500-codec.c index 23b40186f9b8..b7836503dc69 100644 --- a/sound/soc/codecs/ab8500-codec.c +++ b/sound/soc/codecs/ab8500-codec.c @@ -2404,12 +2404,12 @@ static int ab8500_codec_probe(struct snd_soc_codec *codec) dev_dbg(dev, "%s: Enter.\n", __func__); - /* Setup AB8500 according to board-settings */ - pdata = (struct ab8500_platform_data *)dev_get_platdata(dev->parent); - /* Inform SoC Core that we have our own I/O arrangements. */ codec->control_data = (void *)true; + /* Setup AB8500 according to board-settings */ + pdata = dev_get_platdata(dev->parent); + status = ab8500_audio_setup_mics(codec, &pdata->codec->amics); if (status < 0) { pr_err("%s: Failed to setup mics (%d)!\n", __func__, status); -- cgit v1.2.3 From d9f34df782b2aa7d233cb08850c8b12fdb37d18a Mon Sep 17 00:00:00 2001 From: Chris Rattray Date: Tue, 31 Jul 2012 14:51:34 +0100 Subject: ASoC: wm8994: enable mic and short detect debounce. Signed-off-by: Chris Rattray Signed-off-by: Mark Brown --- sound/soc/codecs/wm8994.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'sound/soc') diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index 5fc31797994a..02080da8b451 100644 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c @@ -3262,6 +3262,12 @@ int wm8994_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack, snd_soc_update_bits(codec, WM8994_MICBIAS, WM8994_MICD_ENA, reg); + /* enable MICDET and MICSHRT deboune */ + snd_soc_update_bits(codec, WM8994_IRQ_DEBOUNCE, + WM8994_MIC1_DET_DB_MASK | WM8994_MIC1_SHRT_DB_MASK | + WM8994_MIC2_DET_DB_MASK | WM8994_MIC2_SHRT_DB_MASK, + WM8994_MIC1_DET_DB | WM8994_MIC1_SHRT_DB); + snd_soc_dapm_sync(&codec->dapm); return 0; -- cgit v1.2.3 From 85d07e4d625d6511934799f7df93e9111ac2c88b Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Wed, 25 Jul 2012 15:28:34 +0200 Subject: ASoC: add DT bindings for cs4270 Signed-off-by: Daniel Mack Acked-by: Timur Tabi Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/sound/cs4270.txt | 16 ++++++++++++++++ sound/soc/codecs/cs4270.c | 11 +++++++++++ 2 files changed, 27 insertions(+) create mode 100644 Documentation/devicetree/bindings/sound/cs4270.txt (limited to 'sound/soc') diff --git a/Documentation/devicetree/bindings/sound/cs4270.txt b/Documentation/devicetree/bindings/sound/cs4270.txt new file mode 100644 index 000000000000..7f0bfd84d3fc --- /dev/null +++ b/Documentation/devicetree/bindings/sound/cs4270.txt @@ -0,0 +1,16 @@ +CS4270 audio CODEC + +The driver for this device currently only supports I2C. + +Required properties: + + - compatible : "cirrus,cs4270" + + - reg : the I2C address of the device for I2C + +Example: + +codec: cs4270@48 { + compatible = "cirrus,cs4270"; + reg = <0x48>; +}; diff --git a/sound/soc/codecs/cs4270.c b/sound/soc/codecs/cs4270.c index 047917f0b8ae..4b71b01ecbcd 100644 --- a/sound/soc/codecs/cs4270.c +++ b/sound/soc/codecs/cs4270.c @@ -29,6 +29,7 @@ #include #include #include +#include /* * The codec isn't really big-endian or little-endian, since the I2S @@ -639,6 +640,15 @@ static const struct snd_soc_codec_driver soc_codec_device_cs4270 = { .reg_cache_default = cs4270_default_reg_cache, }; +/* + * cs4270_of_match - the device tree bindings + */ +static const struct of_device_id cs4270_of_match[] = { + { .compatible = "cirrus,cs4270", }, + { } +}; +MODULE_DEVICE_TABLE(of, cs4270_of_match); + /** * cs4270_i2c_probe - initialize the I2C interface of the CS4270 * @i2c_client: the I2C client object @@ -718,6 +728,7 @@ static struct i2c_driver cs4270_i2c_driver = { .driver = { .name = "cs4270", .owner = THIS_MODULE, + .of_match_table = cs4270_of_match, }, .id_table = cs4270_id, .probe = cs4270_i2c_probe, -- cgit v1.2.3 From 02286190f3ec86f03025a60c4d3f747ff1047248 Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Wed, 25 Jul 2012 15:28:35 +0200 Subject: ASoC: Add reset-gpio DT property to cs4270 driver In the process of moving over from static board files to the device tree, reset pins of peripheral reset pins should be handled by their corresponding drivers. Add a reset-gpio DT property to the cs4270 driver, and de-assert it before probing the chip. The logic could be augmented some day to re-assert it when codec is put to suspend. Signed-off-by: Daniel Mack Acked-by: Timur Tabi Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/sound/cs4270.txt | 5 +++++ sound/soc/codecs/cs4270.c | 17 +++++++++++++++++ 2 files changed, 22 insertions(+) (limited to 'sound/soc') diff --git a/Documentation/devicetree/bindings/sound/cs4270.txt b/Documentation/devicetree/bindings/sound/cs4270.txt index 7f0bfd84d3fc..6b222f9b8ef5 100644 --- a/Documentation/devicetree/bindings/sound/cs4270.txt +++ b/Documentation/devicetree/bindings/sound/cs4270.txt @@ -8,6 +8,11 @@ Required properties: - reg : the I2C address of the device for I2C +Optional properties: + + - reset-gpio : a GPIO spec for the reset pin. If specified, it will be + deasserted before communication to the codec starts. + Example: codec: cs4270@48 { diff --git a/sound/soc/codecs/cs4270.c b/sound/soc/codecs/cs4270.c index 4b71b01ecbcd..fd11bb646d40 100644 --- a/sound/soc/codecs/cs4270.c +++ b/sound/soc/codecs/cs4270.c @@ -30,6 +30,7 @@ #include #include #include +#include /* * The codec isn't really big-endian or little-endian, since the I2S @@ -660,9 +661,25 @@ MODULE_DEVICE_TABLE(of, cs4270_of_match); static int cs4270_i2c_probe(struct i2c_client *i2c_client, const struct i2c_device_id *id) { + struct device_node *np = i2c_client->dev.of_node; struct cs4270_private *cs4270; int ret; + /* See if we have a way to bring the codec out of reset */ + if (np) { + enum of_gpio_flags flags; + int gpio = of_get_named_gpio_flags(np, "reset-gpio", 0, &flags); + + if (gpio_is_valid(gpio)) { + ret = devm_gpio_request_one(&i2c_client->dev, gpio, + flags & OF_GPIO_ACTIVE_LOW ? + GPIOF_OUT_INIT_LOW : GPIOF_OUT_INIT_HIGH, + "cs4270 reset"); + if (ret < 0) + return ret; + } + } + /* Verify that we have a CS4270 */ ret = i2c_smbus_read_byte_data(i2c_client, CS4270_CHIPID); -- cgit v1.2.3 From ad3ab1bba9bf3fcd13a4e3f868a438013174dcc1 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Fri, 27 Jul 2012 14:32:10 -0300 Subject: ASoC: imx-ssi: Use devm functions Using devm_ functions can make the code simpler and smaller. Signed-off-by: Fabio Estevam Signed-off-by: Mark Brown --- sound/soc/fsl/imx-ssi.c | 24 +++++------------------- 1 file changed, 5 insertions(+), 19 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/fsl/imx-ssi.c b/sound/soc/fsl/imx-ssi.c index 28dd76c7cb1c..e174c1767c2d 100644 --- a/sound/soc/fsl/imx-ssi.c +++ b/sound/soc/fsl/imx-ssi.c @@ -523,7 +523,7 @@ static int imx_ssi_probe(struct platform_device *pdev) int ret = 0; struct snd_soc_dai_driver *dai; - ssi = kzalloc(sizeof(*ssi), GFP_KERNEL); + ssi = devm_kzalloc(&pdev->dev, sizeof(*ssi), GFP_KERNEL); if (!ssi) return -ENOMEM; dev_set_drvdata(&pdev->dev, ssi); @@ -536,7 +536,7 @@ static int imx_ssi_probe(struct platform_device *pdev) ssi->irq = platform_get_irq(pdev, 0); - ssi->clk = clk_get(&pdev->dev, NULL); + ssi->clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(ssi->clk)) { ret = PTR_ERR(ssi->clk); dev_err(&pdev->dev, "Cannot get the clock: %d\n", @@ -551,23 +551,17 @@ static int imx_ssi_probe(struct platform_device *pdev) goto failed_get_resource; } - if (!request_mem_region(res->start, resource_size(res), DRV_NAME)) { - dev_err(&pdev->dev, "request_mem_region failed\n"); - ret = -EBUSY; - goto failed_get_resource; - } - - ssi->base = ioremap(res->start, resource_size(res)); + ssi->base = devm_request_and_ioremap(&pdev->dev, res); if (!ssi->base) { dev_err(&pdev->dev, "ioremap failed\n"); ret = -ENODEV; - goto failed_ioremap; + goto failed_register; } if (ssi->flags & IMX_SSI_USE_AC97) { if (ac97_ssi) { ret = -EBUSY; - goto failed_ac97; + goto failed_register; } ac97_ssi = ssi; setup_channel_to_ac97(ssi); @@ -636,15 +630,10 @@ failed_pdev_fiq_add: failed_pdev_fiq_alloc: snd_soc_unregister_dai(&pdev->dev); failed_register: -failed_ac97: - iounmap(ssi->base); -failed_ioremap: release_mem_region(res->start, resource_size(res)); failed_get_resource: clk_disable_unprepare(ssi->clk); - clk_put(ssi->clk); failed_clk: - kfree(ssi); return ret; } @@ -662,11 +651,8 @@ static int __devexit imx_ssi_remove(struct platform_device *pdev) if (ssi->flags & IMX_SSI_USE_AC97) ac97_ssi = NULL; - iounmap(ssi->base); release_mem_region(res->start, resource_size(res)); clk_disable_unprepare(ssi->clk); - clk_put(ssi->clk); - kfree(ssi); return 0; } -- cgit v1.2.3 From 9a37eae230e7350ba803801404a022e098016e56 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 31 Jul 2012 18:37:30 +0100 Subject: ASoC: wm9712: Fix funky indentation Signed-off-by: Mark Brown --- sound/soc/codecs/wm9712.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/wm9712.c b/sound/soc/codecs/wm9712.c index f16fb361a4eb..3fefa6e8e451 100644 --- a/sound/soc/codecs/wm9712.c +++ b/sound/soc/codecs/wm9712.c @@ -684,8 +684,8 @@ static int __devexit wm9712_remove(struct platform_device *pdev) static struct platform_driver wm9712_codec_driver = { .driver = { - .name = "wm9712-codec", - .owner = THIS_MODULE, + .name = "wm9712-codec", + .owner = THIS_MODULE, }, .probe = wm9712_probe, -- cgit v1.2.3 From 689185b78ba6fbe0042f662a468b5565909dff7a Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 31 Jul 2012 18:37:29 +0100 Subject: ASoC: wm9712: Fix name of Capture Switch Help UIs associate it with the matching gain control. Signed-off-by: Mark Brown --- sound/soc/codecs/wm9712.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/wm9712.c b/sound/soc/codecs/wm9712.c index 3fefa6e8e451..c9c696ca76f7 100644 --- a/sound/soc/codecs/wm9712.c +++ b/sound/soc/codecs/wm9712.c @@ -146,7 +146,7 @@ SOC_SINGLE("Playback Attenuate (-6dB) Switch", AC97_MASTER_TONE, 6, 1, 0), SOC_SINGLE("Bass Volume", AC97_MASTER_TONE, 8, 15, 1), SOC_SINGLE("Treble Volume", AC97_MASTER_TONE, 0, 15, 1), -SOC_SINGLE("Capture ADC Switch", AC97_REC_GAIN, 15, 1, 1), +SOC_SINGLE("Capture Switch", AC97_REC_GAIN, 15, 1, 1), SOC_ENUM("Capture Volume Steps", wm9712_enum[6]), SOC_DOUBLE("Capture Volume", AC97_REC_GAIN, 8, 0, 63, 1), SOC_SINGLE("Capture ZC Switch", AC97_REC_GAIN, 7, 1, 0), -- cgit v1.2.3 From 1427cc37b6c073e83309565bfebad25fb6cd9182 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 1 Aug 2012 19:25:50 +0100 Subject: ASoC: sta529: Staticise non-exported codec driver struct Signed-off-by: Mark Brown --- sound/soc/codecs/sta529.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/sta529.c b/sound/soc/codecs/sta529.c index 0c225cd569d2..9e3144862386 100644 --- a/sound/soc/codecs/sta529.c +++ b/sound/soc/codecs/sta529.c @@ -358,7 +358,7 @@ static int sta529_resume(struct snd_soc_codec *codec) return 0; } -struct snd_soc_codec_driver sta529_codec_driver = { +static const struct snd_soc_codec_driver sta529_codec_driver = { .probe = sta529_probe, .remove = sta529_remove, .set_bias_level = sta529_set_bias_level, -- cgit v1.2.3 From a0f1e98b34f22bb4055aebfc528bc9080b259f8f Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 31 Jul 2012 18:34:07 +0100 Subject: ASoC: imx-ssi: Say if we fail to register a second AC'97 bus Saves anyone wondering what happened if they run into this error. Signed-off-by: Mark Brown --- sound/soc/fsl/imx-ssi.c | 1 + 1 file changed, 1 insertion(+) (limited to 'sound/soc') diff --git a/sound/soc/fsl/imx-ssi.c b/sound/soc/fsl/imx-ssi.c index e174c1767c2d..3c520c46fa4a 100644 --- a/sound/soc/fsl/imx-ssi.c +++ b/sound/soc/fsl/imx-ssi.c @@ -560,6 +560,7 @@ static int imx_ssi_probe(struct platform_device *pdev) if (ssi->flags & IMX_SSI_USE_AC97) { if (ac97_ssi) { + dev_err(&pdev->dev, "AC'97 SSI already registered\n"); ret = -EBUSY; goto failed_register; } -- cgit v1.2.3 From 3b09efd1decb2b36ba2c7eb88ae4893f0581e470 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Mon, 6 Aug 2012 17:25:34 +0530 Subject: ASoC: tlv320aic32x4: Use module_i2c_driver module_i2c_driver makes the code simpler by eliminating module_init and module_exit calls. Signed-off-by: Sachin Kamat Signed-off-by: Mark Brown --- sound/soc/codecs/tlv320aic32x4.c | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/tlv320aic32x4.c b/sound/soc/codecs/tlv320aic32x4.c index b0a73d37ed52..f230292ba96b 100644 --- a/sound/soc/codecs/tlv320aic32x4.c +++ b/sound/soc/codecs/tlv320aic32x4.c @@ -746,24 +746,7 @@ static struct i2c_driver aic32x4_i2c_driver = { .id_table = aic32x4_i2c_id, }; -static int __init aic32x4_modinit(void) -{ - int ret = 0; - - ret = i2c_add_driver(&aic32x4_i2c_driver); - if (ret != 0) { - printk(KERN_ERR "Failed to register aic32x4 I2C driver: %d\n", - ret); - } - return ret; -} -module_init(aic32x4_modinit); - -static void __exit aic32x4_exit(void) -{ - i2c_del_driver(&aic32x4_i2c_driver); -} -module_exit(aic32x4_exit); +module_i2c_driver(aic32x4_i2c_driver); MODULE_DESCRIPTION("ASoC tlv320aic32x4 codec driver"); MODULE_AUTHOR("Javier Martin "); -- cgit v1.2.3 From a3627e9c0a22283cb1f73fa1170f70fe604315d9 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Mon, 6 Aug 2012 17:25:35 +0530 Subject: ASoC: max9877: Use module_i2c_driver module_i2c_driver makes the code simpler by eliminating module_init and module_exit calls. Signed-off-by: Sachin Kamat Signed-off-by: Mark Brown --- sound/soc/codecs/max9877.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/max9877.c b/sound/soc/codecs/max9877.c index 3a2ba3d8fd6d..d15e5943c85e 100644 --- a/sound/soc/codecs/max9877.c +++ b/sound/soc/codecs/max9877.c @@ -291,17 +291,7 @@ static struct i2c_driver max9877_i2c_driver = { .id_table = max9877_i2c_id, }; -static int __init max9877_init(void) -{ - return i2c_add_driver(&max9877_i2c_driver); -} -module_init(max9877_init); - -static void __exit max9877_exit(void) -{ - i2c_del_driver(&max9877_i2c_driver); -} -module_exit(max9877_exit); +module_i2c_driver(max9877_i2c_driver); MODULE_DESCRIPTION("ASoC MAX9877 amp driver"); MODULE_AUTHOR("Joonyoung Shim "); -- cgit v1.2.3 From 96124c2910a5317b5ea9fbfd9e07b135fdc1dd28 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Mon, 6 Aug 2012 17:25:39 +0530 Subject: ASoC: wm9090: Use module_i2c_driver module_i2c_driver makes the code simpler by eliminating module_init and module_exit calls. Signed-off-by: Sachin Kamat Signed-off-by: Mark Brown --- sound/soc/codecs/wm9090.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/wm9090.c b/sound/soc/codecs/wm9090.c index 2c2346fdd637..c7ddc56175d1 100644 --- a/sound/soc/codecs/wm9090.c +++ b/sound/soc/codecs/wm9090.c @@ -695,17 +695,7 @@ static struct i2c_driver wm9090_i2c_driver = { .id_table = wm9090_id, }; -static int __init wm9090_init(void) -{ - return i2c_add_driver(&wm9090_i2c_driver); -} -module_init(wm9090_init); - -static void __exit wm9090_exit(void) -{ - i2c_del_driver(&wm9090_i2c_driver); -} -module_exit(wm9090_exit); +module_i2c_driver(wm9090_i2c_driver); MODULE_AUTHOR("Mark Brown "); MODULE_DESCRIPTION("WM9090 ASoC driver"); -- cgit v1.2.3 From 38ece8db99e1c7954608a6452bbe8b331d269ad6 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Mon, 6 Aug 2012 17:25:40 +0530 Subject: ASoC: wm8991: Use module_i2c_driver module_i2c_driver makes the code simpler by eliminating module_init and module_exit calls. Signed-off-by: Sachin Kamat Signed-off-by: Mark Brown --- sound/soc/codecs/wm8991.c | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/wm8991.c b/sound/soc/codecs/wm8991.c index 9ac31ba9b82e..b9dbfebbda13 100644 --- a/sound/soc/codecs/wm8991.c +++ b/sound/soc/codecs/wm8991.c @@ -1400,23 +1400,7 @@ static struct i2c_driver wm8991_i2c_driver = { .id_table = wm8991_i2c_id, }; -static int __init wm8991_modinit(void) -{ - int ret; - ret = i2c_add_driver(&wm8991_i2c_driver); - if (ret != 0) { - printk(KERN_ERR "Failed to register WM8991 I2C driver: %d\n", - ret); - } - return 0; -} -module_init(wm8991_modinit); - -static void __exit wm8991_exit(void) -{ - i2c_del_driver(&wm8991_i2c_driver); -} -module_exit(wm8991_exit); +module_i2c_driver(wm8991_i2c_driver); MODULE_DESCRIPTION("ASoC WM8991 driver"); MODULE_AUTHOR("Graeme Gregory"); -- cgit v1.2.3 From 5e383f53e80f4c644bc49a17b5590b110bad5832 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Mon, 6 Aug 2012 17:25:41 +0530 Subject: ASoC: cs4270: Use module_i2c_driver module_i2c_driver makes the code simpler by eliminating module_init and module_exit calls. Signed-off-by: Sachin Kamat Signed-off-by: Mark Brown --- sound/soc/codecs/cs4270.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/cs4270.c b/sound/soc/codecs/cs4270.c index fd11bb646d40..44a176f74170 100644 --- a/sound/soc/codecs/cs4270.c +++ b/sound/soc/codecs/cs4270.c @@ -752,17 +752,7 @@ static struct i2c_driver cs4270_i2c_driver = { .remove = cs4270_i2c_remove, }; -static int __init cs4270_init(void) -{ - return i2c_add_driver(&cs4270_i2c_driver); -} -module_init(cs4270_init); - -static void __exit cs4270_exit(void) -{ - i2c_del_driver(&cs4270_i2c_driver); -} -module_exit(cs4270_exit); +module_i2c_driver(cs4270_i2c_driver); MODULE_AUTHOR("Timur Tabi "); MODULE_DESCRIPTION("Cirrus Logic CS4270 ALSA SoC Codec Driver"); -- cgit v1.2.3 From fd39d14b9676cfd3dbd5b7bfdefe3ec6149b9e1a Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Mon, 6 Aug 2012 17:25:42 +0530 Subject: ASoC: tlv320aic3x: Use module_i2c_driver module_i2c_driver makes the code simpler by eliminating module_init and module_exit calls. Signed-off-by: Sachin Kamat Signed-off-by: Mark Brown --- sound/soc/codecs/tlv320aic3x.c | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c index dc78f5a4bcbf..01485bd51404 100644 --- a/sound/soc/codecs/tlv320aic3x.c +++ b/sound/soc/codecs/tlv320aic3x.c @@ -1499,23 +1499,7 @@ static struct i2c_driver aic3x_i2c_driver = { .id_table = aic3x_i2c_id, }; -static int __init aic3x_modinit(void) -{ - int ret = 0; - ret = i2c_add_driver(&aic3x_i2c_driver); - if (ret != 0) { - printk(KERN_ERR "Failed to register TLV320AIC3x I2C driver: %d\n", - ret); - } - return ret; -} -module_init(aic3x_modinit); - -static void __exit aic3x_exit(void) -{ - i2c_del_driver(&aic3x_i2c_driver); -} -module_exit(aic3x_exit); +module_i2c_driver(aic3x_i2c_driver); MODULE_DESCRIPTION("ASoC TLV320AIC3X codec driver"); MODULE_AUTHOR("Vladimir Barinov"); -- cgit v1.2.3 From 0ead1136bda75d04cc134960bd265eebe210f74b Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Mon, 6 Aug 2012 17:25:43 +0530 Subject: ASoC: sta32x: Use module_i2c_driver module_i2c_driver makes the code simpler by eliminating module_init and module_exit calls. Signed-off-by: Sachin Kamat Signed-off-by: Mark Brown --- sound/soc/codecs/sta32x.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/sta32x.c b/sound/soc/codecs/sta32x.c index 8d717f4b5a87..51b7313a4c14 100644 --- a/sound/soc/codecs/sta32x.c +++ b/sound/soc/codecs/sta32x.c @@ -1006,17 +1006,7 @@ static struct i2c_driver sta32x_i2c_driver = { .id_table = sta32x_i2c_id, }; -static int __init sta32x_init(void) -{ - return i2c_add_driver(&sta32x_i2c_driver); -} -module_init(sta32x_init); - -static void __exit sta32x_exit(void) -{ - i2c_del_driver(&sta32x_i2c_driver); -} -module_exit(sta32x_exit); +module_i2c_driver(sta32x_i2c_driver); MODULE_DESCRIPTION("ASoC STA32X driver"); MODULE_AUTHOR("Johannes Stezenbach "); -- cgit v1.2.3 From 63a47a7544c65f0d4ca28f3ffa54468bc5f6cc6c Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Mon, 6 Aug 2012 17:25:44 +0530 Subject: ASoC: tlv320dac33: Use module_i2c_driver module_i2c_driver makes the code simpler by eliminating module_init and module_exit calls. Signed-off-by: Sachin Kamat Signed-off-by: Mark Brown --- sound/soc/codecs/tlv320dac33.c | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/tlv320dac33.c b/sound/soc/codecs/tlv320dac33.c index 0dd41077ab79..d2e16c5d7d1f 100644 --- a/sound/soc/codecs/tlv320dac33.c +++ b/sound/soc/codecs/tlv320dac33.c @@ -1621,24 +1621,7 @@ static struct i2c_driver tlv320dac33_i2c_driver = { .id_table = tlv320dac33_i2c_id, }; -static int __init dac33_module_init(void) -{ - int r; - r = i2c_add_driver(&tlv320dac33_i2c_driver); - if (r < 0) { - printk(KERN_ERR "DAC33: driver registration failed\n"); - return r; - } - return 0; -} -module_init(dac33_module_init); - -static void __exit dac33_module_exit(void) -{ - i2c_del_driver(&tlv320dac33_i2c_driver); -} -module_exit(dac33_module_exit); - +module_i2c_driver(tlv320dac33_i2c_driver); MODULE_DESCRIPTION("ASoC TLV320DAC33 codec driver"); MODULE_AUTHOR("Peter Ujfalusi "); -- cgit v1.2.3 From beb22de07e87a2f6802cc0e916b2f5c6aeb3f59f Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Mon, 6 Aug 2012 17:25:45 +0530 Subject: ASoC: adau1701: Use module_i2c_driver module_i2c_driver makes the code simpler by eliminating module_init and module_exit calls. Signed-off-by: Sachin Kamat Signed-off-by: Mark Brown --- sound/soc/codecs/adau1701.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/adau1701.c b/sound/soc/codecs/adau1701.c index 3d50fc8646b6..51f2f3cd8136 100644 --- a/sound/soc/codecs/adau1701.c +++ b/sound/soc/codecs/adau1701.c @@ -527,17 +527,7 @@ static struct i2c_driver adau1701_i2c_driver = { .id_table = adau1701_i2c_id, }; -static int __init adau1701_init(void) -{ - return i2c_add_driver(&adau1701_i2c_driver); -} -module_init(adau1701_init); - -static void __exit adau1701_exit(void) -{ - i2c_del_driver(&adau1701_i2c_driver); -} -module_exit(adau1701_exit); +module_i2c_driver(adau1701_i2c_driver); MODULE_DESCRIPTION("ASoC ADAU1701 SigmaDSP driver"); MODULE_AUTHOR("Cliff Cai "); -- cgit v1.2.3 From 4abdc8c8fd25fa2f85d86babcbdb4fbbf759c86a Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Mon, 6 Aug 2012 17:25:46 +0530 Subject: ASoC: max9850: Use module_i2c_driver module_i2c_driver makes the code simpler by eliminating module_init and module_exit calls. Signed-off-by: Sachin Kamat Signed-off-by: Mark Brown --- sound/soc/codecs/max9850.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/max9850.c b/sound/soc/codecs/max9850.c index a1913091f56c..efe535c37b39 100644 --- a/sound/soc/codecs/max9850.c +++ b/sound/soc/codecs/max9850.c @@ -369,17 +369,7 @@ static struct i2c_driver max9850_i2c_driver = { .id_table = max9850_i2c_id, }; -static int __init max9850_init(void) -{ - return i2c_add_driver(&max9850_i2c_driver); -} -module_init(max9850_init); - -static void __exit max9850_exit(void) -{ - i2c_del_driver(&max9850_i2c_driver); -} -module_exit(max9850_exit); +module_i2c_driver(max9850_i2c_driver); MODULE_AUTHOR("Christian Glindkamp "); MODULE_DESCRIPTION("ASoC MAX9850 codec driver"); -- cgit v1.2.3 From 28285b96c9e75a79b7698bc4286aa1cb94e5c9cb Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Mon, 6 Aug 2012 17:25:47 +0530 Subject: ASoC: wm8971: Use module_i2c_driver module_i2c_driver makes the code simpler by eliminating module_init and module_exit calls. Signed-off-by: Sachin Kamat Signed-off-by: Mark Brown --- sound/soc/codecs/wm8971.c | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/wm8971.c b/sound/soc/codecs/wm8971.c index eef783f6b6d6..5ce647758443 100644 --- a/sound/soc/codecs/wm8971.c +++ b/sound/soc/codecs/wm8971.c @@ -721,23 +721,7 @@ static struct i2c_driver wm8971_i2c_driver = { .id_table = wm8971_i2c_id, }; -static int __init wm8971_modinit(void) -{ - int ret = 0; - ret = i2c_add_driver(&wm8971_i2c_driver); - if (ret != 0) { - printk(KERN_ERR "Failed to register WM8971 I2C driver: %d\n", - ret); - } - return ret; -} -module_init(wm8971_modinit); - -static void __exit wm8971_exit(void) -{ - i2c_del_driver(&wm8971_i2c_driver); -} -module_exit(wm8971_exit); +module_i2c_driver(wm8971_i2c_driver); MODULE_DESCRIPTION("ASoC WM8971 driver"); MODULE_AUTHOR("Lab126"); -- cgit v1.2.3 From 0ecbbb4fe5f0aae4cd70ec02383fd6b96aedb052 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Mon, 6 Aug 2012 17:25:48 +0530 Subject: ASoC: ak4671: Use module_i2c_driver module_i2c_driver makes the code simpler by eliminating module_init and module_exit calls. Signed-off-by: Sachin Kamat Signed-off-by: Mark Brown --- sound/soc/codecs/ak4671.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/ak4671.c b/sound/soc/codecs/ak4671.c index 5fb7c2a80e6d..2b457976a7bf 100644 --- a/sound/soc/codecs/ak4671.c +++ b/sound/soc/codecs/ak4671.c @@ -696,17 +696,7 @@ static struct i2c_driver ak4671_i2c_driver = { .id_table = ak4671_i2c_id, }; -static int __init ak4671_modinit(void) -{ - return i2c_add_driver(&ak4671_i2c_driver); -} -module_init(ak4671_modinit); - -static void __exit ak4671_exit(void) -{ - i2c_del_driver(&ak4671_i2c_driver); -} -module_exit(ak4671_exit); +module_i2c_driver(ak4671_i2c_driver); MODULE_DESCRIPTION("ASoC AK4671 codec driver"); MODULE_AUTHOR("Joonyoung Shim "); -- cgit v1.2.3 From f6ec139f2dc5380c542fa3100dbe1c73324be432 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Mon, 6 Aug 2012 17:25:49 +0530 Subject: ASoC: lm4857: Use module_i2c_driver module_i2c_driver makes the code simpler by eliminating module_init and module_exit calls. Signed-off-by: Sachin Kamat Signed-off-by: Mark Brown --- sound/soc/codecs/lm4857.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/lm4857.c b/sound/soc/codecs/lm4857.c index ba4fafb93e56..81a328c78838 100644 --- a/sound/soc/codecs/lm4857.c +++ b/sound/soc/codecs/lm4857.c @@ -250,17 +250,7 @@ static struct i2c_driver lm4857_i2c_driver = { .id_table = lm4857_i2c_id, }; -static int __init lm4857_init(void) -{ - return i2c_add_driver(&lm4857_i2c_driver); -} -module_init(lm4857_init); - -static void __exit lm4857_exit(void) -{ - i2c_del_driver(&lm4857_i2c_driver); -} -module_exit(lm4857_exit); +module_i2c_driver(lm4857_i2c_driver); MODULE_AUTHOR("Lars-Peter Clausen "); MODULE_DESCRIPTION("LM4857 amplifier driver"); -- cgit v1.2.3 From 0b34ac810ac079735f9e7e2c58d467f849a67ede Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Mon, 6 Aug 2012 17:25:50 +0530 Subject: ASoC: wm8978: Use module_i2c_driver module_i2c_driver makes the code simpler by eliminating module_init and module_exit calls. Signed-off-by: Sachin Kamat Signed-off-by: Mark Brown --- sound/soc/codecs/wm8978.c | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/wm8978.c b/sound/soc/codecs/wm8978.c index a5be3adecf75..5421fd9fbcb5 100644 --- a/sound/soc/codecs/wm8978.c +++ b/sound/soc/codecs/wm8978.c @@ -1105,23 +1105,7 @@ static struct i2c_driver wm8978_i2c_driver = { .id_table = wm8978_i2c_id, }; -static int __init wm8978_modinit(void) -{ - int ret = 0; - ret = i2c_add_driver(&wm8978_i2c_driver); - if (ret != 0) { - printk(KERN_ERR "Failed to register WM8978 I2C driver: %d\n", - ret); - } - return ret; -} -module_init(wm8978_modinit); - -static void __exit wm8978_exit(void) -{ - i2c_del_driver(&wm8978_i2c_driver); -} -module_exit(wm8978_exit); +module_i2c_driver(wm8978_i2c_driver); MODULE_DESCRIPTION("ASoC WM8978 codec driver"); MODULE_AUTHOR("Guennadi Liakhovetski "); -- cgit v1.2.3 From 2342a07f2ca81c8e076ed6d5c6d19ac36794c848 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Mon, 6 Aug 2012 17:25:51 +0530 Subject: ASoC: max98088: Use module_i2c_driver module_i2c_driver makes the code simpler by eliminating module_init and module_exit calls. Signed-off-by: Sachin Kamat Signed-off-by: Mark Brown --- sound/soc/codecs/max98088.c | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/max98088.c b/sound/soc/codecs/max98088.c index af7324b79dd0..3264a5169306 100644 --- a/sound/soc/codecs/max98088.c +++ b/sound/soc/codecs/max98088.c @@ -2107,23 +2107,7 @@ static struct i2c_driver max98088_i2c_driver = { .id_table = max98088_i2c_id, }; -static int __init max98088_init(void) -{ - int ret; - - ret = i2c_add_driver(&max98088_i2c_driver); - if (ret) - pr_err("Failed to register max98088 I2C driver: %d\n", ret); - - return ret; -} -module_init(max98088_init); - -static void __exit max98088_exit(void) -{ - i2c_del_driver(&max98088_i2c_driver); -} -module_exit(max98088_exit); +module_i2c_driver(max98088_i2c_driver); MODULE_DESCRIPTION("ALSA SoC MAX98088 driver"); MODULE_AUTHOR("Peter Hsiang, Jesse Marroquin"); -- cgit v1.2.3 From 07c9c32be01db1705db2655922ee66173594b230 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Mon, 6 Aug 2012 17:25:52 +0530 Subject: ASoC: wm8955: Use module_i2c_driver module_i2c_driver makes the code simpler by eliminating module_init and module_exit calls. Signed-off-by: Sachin Kamat Signed-off-by: Mark Brown --- sound/soc/codecs/wm8955.c | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/wm8955.c b/sound/soc/codecs/wm8955.c index 61fe97433e73..2f1c075755b1 100644 --- a/sound/soc/codecs/wm8955.c +++ b/sound/soc/codecs/wm8955.c @@ -1071,23 +1071,7 @@ static struct i2c_driver wm8955_i2c_driver = { .id_table = wm8955_i2c_id, }; -static int __init wm8955_modinit(void) -{ - int ret = 0; - ret = i2c_add_driver(&wm8955_i2c_driver); - if (ret != 0) { - printk(KERN_ERR "Failed to register WM8955 I2C driver: %d\n", - ret); - } - return ret; -} -module_init(wm8955_modinit); - -static void __exit wm8955_exit(void) -{ - i2c_del_driver(&wm8955_i2c_driver); -} -module_exit(wm8955_exit); +module_i2c_driver(wm8955_i2c_driver); MODULE_DESCRIPTION("ASoC WM8955 driver"); MODULE_AUTHOR("Mark Brown "); -- cgit v1.2.3 From a9418ddca69db1c4b5d2d7b5f091e50893387be3 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Mon, 6 Aug 2012 17:25:53 +0530 Subject: ASoC: wm2200: Use module_i2c_driver module_i2c_driver makes the code simpler by eliminating module_init and module_exit calls. Signed-off-by: Sachin Kamat Signed-off-by: Mark Brown --- sound/soc/codecs/wm2200.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/wm2200.c b/sound/soc/codecs/wm2200.c index 32682c1b7cde..71debd0a3822 100644 --- a/sound/soc/codecs/wm2200.c +++ b/sound/soc/codecs/wm2200.c @@ -2270,17 +2270,7 @@ static struct i2c_driver wm2200_i2c_driver = { .id_table = wm2200_i2c_id, }; -static int __init wm2200_modinit(void) -{ - return i2c_add_driver(&wm2200_i2c_driver); -} -module_init(wm2200_modinit); - -static void __exit wm2200_exit(void) -{ - i2c_del_driver(&wm2200_i2c_driver); -} -module_exit(wm2200_exit); +module_i2c_driver(wm2200_i2c_driver); MODULE_DESCRIPTION("ASoC WM2200 driver"); MODULE_AUTHOR("Mark Brown "); -- cgit v1.2.3 From 3a4bfd88af87b065e8a650211a7730b3f1e58e3e Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Mon, 6 Aug 2012 17:25:54 +0530 Subject: ASoC: wm2000: Use module_i2c_driver module_i2c_driver makes the code simpler by eliminating module_init and module_exit calls. Signed-off-by: Sachin Kamat Signed-off-by: Mark Brown --- sound/soc/codecs/wm2000.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/wm2000.c b/sound/soc/codecs/wm2000.c index 3fd5b29dc933..89cd6fcad015 100644 --- a/sound/soc/codecs/wm2000.c +++ b/sound/soc/codecs/wm2000.c @@ -858,17 +858,7 @@ static struct i2c_driver wm2000_i2c_driver = { .id_table = wm2000_i2c_id, }; -static int __init wm2000_init(void) -{ - return i2c_add_driver(&wm2000_i2c_driver); -} -module_init(wm2000_init); - -static void __exit wm2000_exit(void) -{ - i2c_del_driver(&wm2000_i2c_driver); -} -module_exit(wm2000_exit); +module_i2c_driver(wm2000_i2c_driver); MODULE_DESCRIPTION("ASoC WM2000 driver"); MODULE_AUTHOR("Mark Brown "); -- cgit v1.2.3 From 794836b959e95b4e4705e11e7bdf2a688c72e2f7 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Mon, 6 Aug 2012 17:25:55 +0530 Subject: ASoC: wm8940: Use module_i2c_driver module_i2c_driver makes the code simpler by eliminating module_init and module_exit calls. Signed-off-by: Sachin Kamat Signed-off-by: Mark Brown --- sound/soc/codecs/wm8940.c | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/wm8940.c b/sound/soc/codecs/wm8940.c index 481a3d9cfe48..b20aa4e7c3f9 100644 --- a/sound/soc/codecs/wm8940.c +++ b/sound/soc/codecs/wm8940.c @@ -785,23 +785,7 @@ static struct i2c_driver wm8940_i2c_driver = { .id_table = wm8940_i2c_id, }; -static int __init wm8940_modinit(void) -{ - int ret = 0; - ret = i2c_add_driver(&wm8940_i2c_driver); - if (ret != 0) { - printk(KERN_ERR "Failed to register wm8940 I2C driver: %d\n", - ret); - } - return ret; -} -module_init(wm8940_modinit); - -static void __exit wm8940_exit(void) -{ - i2c_del_driver(&wm8940_i2c_driver); -} -module_exit(wm8940_exit); +module_i2c_driver(wm8940_i2c_driver); MODULE_DESCRIPTION("ASoC WM8940 driver"); MODULE_AUTHOR("Jonathan Cameron"); -- cgit v1.2.3 From 8b08eb28c761aea8434e0228a0f080e31e16d791 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Mon, 6 Aug 2012 17:25:56 +0530 Subject: ASoC: wm8961: Use module_i2c_driver module_i2c_driver makes the code simpler by eliminating module_init and module_exit calls. Signed-off-by: Sachin Kamat Signed-off-by: Mark Brown --- sound/soc/codecs/wm8961.c | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/wm8961.c b/sound/soc/codecs/wm8961.c index 01edbcc754d2..719fb69a17c8 100644 --- a/sound/soc/codecs/wm8961.c +++ b/sound/soc/codecs/wm8961.c @@ -1114,23 +1114,7 @@ static struct i2c_driver wm8961_i2c_driver = { .id_table = wm8961_i2c_id, }; -static int __init wm8961_modinit(void) -{ - int ret = 0; - ret = i2c_add_driver(&wm8961_i2c_driver); - if (ret != 0) { - printk(KERN_ERR "Failed to register wm8961 I2C driver: %d\n", - ret); - } - return ret; -} -module_init(wm8961_modinit); - -static void __exit wm8961_exit(void) -{ - i2c_del_driver(&wm8961_i2c_driver); -} -module_exit(wm8961_exit); +module_i2c_driver(wm8961_i2c_driver); MODULE_DESCRIPTION("ASoC WM8961 driver"); MODULE_AUTHOR("Mark Brown "); -- cgit v1.2.3 From 5c86ea44bba82641b6173419c88c0de7cf09b60a Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Mon, 6 Aug 2012 17:25:57 +0530 Subject: ASoC: wm8903: Use module_i2c_driver module_i2c_driver makes the code simpler by eliminating module_init and module_exit calls. Signed-off-by: Sachin Kamat Signed-off-by: Mark Brown --- sound/soc/codecs/wm8903.c | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/wm8903.c b/sound/soc/codecs/wm8903.c index 73f1c8d7bafb..839414f9e2ed 100644 --- a/sound/soc/codecs/wm8903.c +++ b/sound/soc/codecs/wm8903.c @@ -2241,23 +2241,7 @@ static struct i2c_driver wm8903_i2c_driver = { .id_table = wm8903_i2c_id, }; -static int __init wm8903_modinit(void) -{ - int ret = 0; - ret = i2c_add_driver(&wm8903_i2c_driver); - if (ret != 0) { - printk(KERN_ERR "Failed to register wm8903 I2C driver: %d\n", - ret); - } - return ret; -} -module_init(wm8903_modinit); - -static void __exit wm8903_exit(void) -{ - i2c_del_driver(&wm8903_i2c_driver); -} -module_exit(wm8903_exit); +module_i2c_driver(wm8903_i2c_driver); MODULE_DESCRIPTION("ASoC WM8903 driver"); MODULE_AUTHOR("Mark Brown "); -- cgit v1.2.3 From d0b2d4fabb262dd7200382ee834d4292f6d76b1e Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Mon, 6 Aug 2012 17:25:58 +0530 Subject: ASoC: adau1373: Use module_i2c_driver module_i2c_driver makes the code simpler by eliminating module_init and module_exit calls. Signed-off-by: Sachin Kamat Signed-off-by: Mark Brown --- sound/soc/codecs/adau1373.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/adau1373.c b/sound/soc/codecs/adau1373.c index 44f59064d8de..704544bfc90d 100644 --- a/sound/soc/codecs/adau1373.c +++ b/sound/soc/codecs/adau1373.c @@ -1392,17 +1392,7 @@ static struct i2c_driver adau1373_i2c_driver = { .id_table = adau1373_i2c_id, }; -static int __init adau1373_init(void) -{ - return i2c_add_driver(&adau1373_i2c_driver); -} -module_init(adau1373_init); - -static void __exit adau1373_exit(void) -{ - i2c_del_driver(&adau1373_i2c_driver); -} -module_exit(adau1373_exit); +module_i2c_driver(adau1373_i2c_driver); MODULE_DESCRIPTION("ASoC ADAU1373 driver"); MODULE_AUTHOR("Lars-Peter Clausen "); -- cgit v1.2.3 From 3c010e60ee54ee19dc2f39b4efa43dea03d65aaa Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Mon, 6 Aug 2012 17:25:36 +0530 Subject: ASoC: wm8960: Use module_i2c_driver module_i2c_driver makes the code simpler by eliminating module_init and module_exit calls. Signed-off-by: Sachin Kamat Signed-off-by: Mark Brown --- sound/soc/codecs/wm8960.c | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/wm8960.c b/sound/soc/codecs/wm8960.c index 96518ac8e24c..804f4116912f 100644 --- a/sound/soc/codecs/wm8960.c +++ b/sound/soc/codecs/wm8960.c @@ -1010,23 +1010,7 @@ static struct i2c_driver wm8960_i2c_driver = { .id_table = wm8960_i2c_id, }; -static int __init wm8960_modinit(void) -{ - int ret = 0; - ret = i2c_add_driver(&wm8960_i2c_driver); - if (ret != 0) { - printk(KERN_ERR "Failed to register WM8960 I2C driver: %d\n", - ret); - } - return ret; -} -module_init(wm8960_modinit); - -static void __exit wm8960_exit(void) -{ - i2c_del_driver(&wm8960_i2c_driver); -} -module_exit(wm8960_exit); +module_i2c_driver(wm8960_i2c_driver); MODULE_DESCRIPTION("ASoC WM8960 driver"); MODULE_AUTHOR("Liam Girdwood"); -- cgit v1.2.3 From 2be59418f76dac590b98027586ac1714be17fcae Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Mon, 6 Aug 2012 17:25:59 +0530 Subject: ASoC: wm8974: Use module_i2c_driver module_i2c_driver makes the code simpler by eliminating module_init and module_exit calls. Signed-off-by: Sachin Kamat Signed-off-by: Mark Brown --- sound/soc/codecs/wm8974.c | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/wm8974.c b/sound/soc/codecs/wm8974.c index d93c03f820c9..9a39511af52a 100644 --- a/sound/soc/codecs/wm8974.c +++ b/sound/soc/codecs/wm8974.c @@ -659,23 +659,7 @@ static struct i2c_driver wm8974_i2c_driver = { .id_table = wm8974_i2c_id, }; -static int __init wm8974_modinit(void) -{ - int ret = 0; - ret = i2c_add_driver(&wm8974_i2c_driver); - if (ret != 0) { - printk(KERN_ERR "Failed to register wm8974 I2C driver: %d\n", - ret); - } - return ret; -} -module_init(wm8974_modinit); - -static void __exit wm8974_exit(void) -{ - i2c_del_driver(&wm8974_i2c_driver); -} -module_exit(wm8974_exit); +module_i2c_driver(wm8974_i2c_driver); MODULE_DESCRIPTION("ASoC WM8974 driver"); MODULE_AUTHOR("Liam Girdwood"); -- cgit v1.2.3 From a8af02cf62e32644c02566adc462bba9ae148154 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Mon, 6 Aug 2012 17:26:00 +0530 Subject: ASoC: max98095: Use module_i2c_driver module_i2c_driver makes the code simpler by eliminating module_init and module_exit calls. Signed-off-by: Sachin Kamat Signed-off-by: Mark Brown --- sound/soc/codecs/max98095.c | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/max98095.c b/sound/soc/codecs/max98095.c index 7cd508e16a5c..38d43c59d3f4 100644 --- a/sound/soc/codecs/max98095.c +++ b/sound/soc/codecs/max98095.c @@ -2533,23 +2533,7 @@ static struct i2c_driver max98095_i2c_driver = { .id_table = max98095_i2c_id, }; -static int __init max98095_init(void) -{ - int ret; - - ret = i2c_add_driver(&max98095_i2c_driver); - if (ret) - pr_err("Failed to register max98095 I2C driver: %d\n", ret); - - return ret; -} -module_init(max98095_init); - -static void __exit max98095_exit(void) -{ - i2c_del_driver(&max98095_i2c_driver); -} -module_exit(max98095_exit); +module_i2c_driver(max98095_i2c_driver); MODULE_DESCRIPTION("ALSA SoC MAX98095 driver"); MODULE_AUTHOR("Peter Hsiang"); -- cgit v1.2.3 From cee4fcfa9dba7f13b0b45810832208df48ff4ca4 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Mon, 6 Aug 2012 17:25:37 +0530 Subject: ASoC: cs42l51: Use module_i2c_driver module_i2c_driver makes the code simpler by eliminating module_init and module_exit calls. Signed-off-by: Sachin Kamat Signed-off-by: Mark Brown --- sound/soc/codecs/cs42l51.c | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/cs42l51.c b/sound/soc/codecs/cs42l51.c index 091d0193f507..1e0fa3b5f79a 100644 --- a/sound/soc/codecs/cs42l51.c +++ b/sound/soc/codecs/cs42l51.c @@ -614,24 +614,7 @@ static struct i2c_driver cs42l51_i2c_driver = { .remove = cs42l51_i2c_remove, }; -static int __init cs42l51_init(void) -{ - int ret; - - ret = i2c_add_driver(&cs42l51_i2c_driver); - if (ret != 0) { - printk(KERN_ERR "%s: can't add i2c driver\n", __func__); - return ret; - } - return 0; -} -module_init(cs42l51_init); - -static void __exit cs42l51_exit(void) -{ - i2c_del_driver(&cs42l51_i2c_driver); -} -module_exit(cs42l51_exit); +module_i2c_driver(cs42l51_i2c_driver); MODULE_AUTHOR("Arnaud Patard "); MODULE_DESCRIPTION("Cirrus Logic CS42L51 ALSA SoC Codec Driver"); -- cgit v1.2.3 From f062e2b64153e9769adf5370103f787971c9cd95 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Mon, 6 Aug 2012 17:25:38 +0530 Subject: ASoC: tpa6130a2: Use module_i2c_driver module_i2c_driver makes the code simpler by eliminating module_init and module_exit calls. Signed-off-by: Sachin Kamat Signed-off-by: Mark Brown --- sound/soc/codecs/tpa6130a2.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/tpa6130a2.c b/sound/soc/codecs/tpa6130a2.c index 6fe4aa3ac544..565ff39ad3a3 100644 --- a/sound/soc/codecs/tpa6130a2.c +++ b/sound/soc/codecs/tpa6130a2.c @@ -487,19 +487,8 @@ static struct i2c_driver tpa6130a2_i2c_driver = { .id_table = tpa6130a2_id, }; -static int __init tpa6130a2_init(void) -{ - return i2c_add_driver(&tpa6130a2_i2c_driver); -} - -static void __exit tpa6130a2_exit(void) -{ - i2c_del_driver(&tpa6130a2_i2c_driver); -} +module_i2c_driver(tpa6130a2_i2c_driver); MODULE_AUTHOR("Peter Ujfalusi "); MODULE_DESCRIPTION("TPA6130A2 Headphone amplifier driver"); MODULE_LICENSE("GPL"); - -module_init(tpa6130a2_init); -module_exit(tpa6130a2_exit); -- cgit v1.2.3 From 209ffe19ff98f5c0133bd98a689fc4fb42202de3 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Tue, 7 Aug 2012 12:07:27 +0530 Subject: ASoC: cs42l52: Remove duplicate inclusion of slab.h header file slab.h header file was included twice. Signed-off-by: Sachin Kamat Signed-off-by: Mark Brown --- sound/soc/codecs/cs42l52.c | 1 - 1 file changed, 1 deletion(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/cs42l52.c b/sound/soc/codecs/cs42l52.c index 628daf6a1d97..61599298fb26 100644 --- a/sound/soc/codecs/cs42l52.c +++ b/sound/soc/codecs/cs42l52.c @@ -24,7 +24,6 @@ #include #include #include -#include #include #include #include -- cgit v1.2.3 From 5f800080ca6840326b3048202fb63fc4a71a4c49 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Tue, 7 Aug 2012 10:24:13 +0300 Subject: ASoC: core: Set dapm->idle_bias_off for DAIs not mapped with a codec The idle_bias_off flag is not configured for DAIs not mapped with a codec. This causes the pm counter to be increased at probe time for the CPU dai which unbalances the pm counter handling. Signed-off-by: Peter Ujfalusi Signed-off-by: Mark Brown --- sound/soc/soc-core.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'sound/soc') diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index f81c5976b961..f10f00b5d29f 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -3715,6 +3715,9 @@ int snd_soc_register_dai(struct device *dev, } } + if (!dai->codec) + dai->dapm.idle_bias_off = 1; + list_add(&dai->list, &dai_list); mutex_unlock(&client_mutex); @@ -3803,6 +3806,9 @@ int snd_soc_register_dais(struct device *dev, } } + if (!dai->codec) + dai->dapm.idle_bias_off = 1; + list_add(&dai->list, &dai_list); mutex_unlock(&client_mutex); -- cgit v1.2.3 From 730963f8190b7650b0445a76e701fdef20c31cfb Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Tue, 7 Aug 2012 01:29:43 -0300 Subject: ASoC: mxs-saif: Use devm_clk_get() Using devm_clk_get can make the code simpler and smaller. Signed-off-by: Fabio Estevam Signed-off-by: Mark Brown --- sound/soc/mxs/mxs-saif.c | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/mxs/mxs-saif.c b/sound/soc/mxs/mxs-saif.c index b3030718c228..aa037b292f3d 100644 --- a/sound/soc/mxs/mxs-saif.c +++ b/sound/soc/mxs/mxs-saif.c @@ -704,7 +704,7 @@ static int __devinit mxs_saif_probe(struct platform_device *pdev) return ret; } - saif->clk = clk_get(&pdev->dev, NULL); + saif->clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(saif->clk)) { ret = PTR_ERR(saif->clk); dev_err(&pdev->dev, "Cannot get the clock: %d\n", @@ -717,8 +717,7 @@ static int __devinit mxs_saif_probe(struct platform_device *pdev) saif->base = devm_request_and_ioremap(&pdev->dev, iores); if (!saif->base) { dev_err(&pdev->dev, "ioremap failed\n"); - ret = -ENODEV; - goto failed_get_resource; + return -ENODEV; } dmares = platform_get_resource(pdev, IORESOURCE_DMA, 0); @@ -731,7 +730,7 @@ static int __devinit mxs_saif_probe(struct platform_device *pdev) &saif->dma_param.chan_num); if (ret) { dev_err(&pdev->dev, "failed to get dma channel\n"); - goto failed_get_resource; + return ret; } } else { saif->dma_param.chan_num = dmares->start; @@ -742,7 +741,7 @@ static int __devinit mxs_saif_probe(struct platform_device *pdev) ret = saif->irq; dev_err(&pdev->dev, "failed to get irq resource: %d\n", ret); - goto failed_get_resource; + return ret; } saif->dev = &pdev->dev; @@ -750,7 +749,7 @@ static int __devinit mxs_saif_probe(struct platform_device *pdev) "mxs-saif", saif); if (ret) { dev_err(&pdev->dev, "failed to request irq\n"); - goto failed_get_resource; + return ret; } saif->dma_param.chan_irq = platform_get_irq(pdev, 1); @@ -758,7 +757,7 @@ static int __devinit mxs_saif_probe(struct platform_device *pdev) ret = saif->dma_param.chan_irq; dev_err(&pdev->dev, "failed to get dma irq resource: %d\n", ret); - goto failed_get_resource; + return ret; } platform_set_drvdata(pdev, saif); @@ -766,7 +765,7 @@ static int __devinit mxs_saif_probe(struct platform_device *pdev) ret = snd_soc_register_dai(&pdev->dev, &mxs_saif_dai); if (ret) { dev_err(&pdev->dev, "register DAI failed\n"); - goto failed_get_resource; + return ret; } ret = mxs_pcm_platform_register(&pdev->dev); @@ -779,19 +778,14 @@ static int __devinit mxs_saif_probe(struct platform_device *pdev) failed_pdev_alloc: snd_soc_unregister_dai(&pdev->dev); -failed_get_resource: - clk_put(saif->clk); return ret; } static int __devexit mxs_saif_remove(struct platform_device *pdev) { - struct mxs_saif *saif = platform_get_drvdata(pdev); - mxs_pcm_platform_unregister(&pdev->dev); snd_soc_unregister_dai(&pdev->dev); - clk_put(saif->clk); return 0; } -- cgit v1.2.3 From 8f245499791a4701bfe1ce9b0df90cea9d2f13e5 Mon Sep 17 00:00:00 2001 From: "Hebbar, Gururaja" Date: Wed, 8 Aug 2012 20:40:30 +0530 Subject: ASoC: Davinci: McASP: remove unused header include Defines or parameters from isn't used anywhere. Hence remove the header include. Signed-off-by: Hebbar, Gururaja Signed-off-by: Mark Brown --- sound/soc/davinci/davinci-evm.c | 1 - 1 file changed, 1 deletion(-) (limited to 'sound/soc') diff --git a/sound/soc/davinci/davinci-evm.c b/sound/soc/davinci/davinci-evm.c index 10a2d8c788b7..c80c20a89b11 100644 --- a/sound/soc/davinci/davinci-evm.c +++ b/sound/soc/davinci/davinci-evm.c @@ -24,7 +24,6 @@ #include #include -#include #include "davinci-pcm.h" #include "davinci-i2s.h" -- cgit v1.2.3 From 10884347f18842aa9b8ae18ebb16272d9b7fafa2 Mon Sep 17 00:00:00 2001 From: "Hebbar, Gururaja" Date: Wed, 8 Aug 2012 20:40:32 +0530 Subject: ASoC: McASP: Convert driver to use Runtime PM API * Add Runtime PM support to McASP host controller. * Use Runtime PM API to enable/disable McASP clock. This was tested on AM18x Board using suspend/resume Signed-off-by: Hebbar, Gururaja Signed-off-by: Mark Brown --- sound/soc/davinci/davinci-mcasp.c | 40 +++++++++++++++++++-------------------- sound/soc/davinci/davinci-mcasp.h | 3 +-- 2 files changed, 20 insertions(+), 23 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c index 95441bfc8190..d919fb8de7a3 100644 --- a/sound/soc/davinci/davinci-mcasp.c +++ b/sound/soc/davinci/davinci-mcasp.c @@ -21,7 +21,7 @@ #include #include #include -#include +#include #include #include @@ -776,20 +776,17 @@ static int davinci_mcasp_trigger(struct snd_pcm_substream *substream, case SNDRV_PCM_TRIGGER_RESUME: case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - if (!dev->clk_active) { - clk_enable(dev->clk); - dev->clk_active = 1; - } + ret = pm_runtime_get_sync(dev->dev); + if (IS_ERR_VALUE(ret)) + dev_err(dev->dev, "pm_runtime_get_sync() failed\n"); davinci_mcasp_start(dev, substream->stream); break; case SNDRV_PCM_TRIGGER_SUSPEND: davinci_mcasp_stop(dev, substream->stream); - if (dev->clk_active) { - clk_disable(dev->clk); - dev->clk_active = 0; - } - + ret = pm_runtime_put_sync(dev->dev); + if (IS_ERR_VALUE(ret)) + dev_err(dev->dev, "pm_runtime_put_sync() failed\n"); break; case SNDRV_PCM_TRIGGER_STOP: @@ -886,12 +883,13 @@ static int davinci_mcasp_probe(struct platform_device *pdev) } pdata = pdev->dev.platform_data; - dev->clk = clk_get(&pdev->dev, NULL); - if (IS_ERR(dev->clk)) - return -ENODEV; + pm_runtime_enable(&pdev->dev); - clk_enable(dev->clk); - dev->clk_active = 1; + ret = pm_runtime_get_sync(&pdev->dev); + if (IS_ERR_VALUE(ret)) { + dev_err(&pdev->dev, "pm_runtime_get_sync() failed\n"); + return ret; + } dev->base = devm_ioremap(&pdev->dev, mem->start, resource_size(mem)); if (!dev->base) { @@ -908,6 +906,7 @@ static int davinci_mcasp_probe(struct platform_device *pdev) dev->version = pdata->version; dev->txnumevt = pdata->txnumevt; dev->rxnumevt = pdata->rxnumevt; + dev->dev = &pdev->dev; dma_data = &dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK]; dma_data->asp_chan_q = pdata->asp_chan_q; @@ -949,19 +948,18 @@ static int davinci_mcasp_probe(struct platform_device *pdev) return 0; err_release_clk: - clk_disable(dev->clk); - clk_put(dev->clk); + pm_runtime_put_sync(&pdev->dev); + pm_runtime_disable(&pdev->dev); return ret; } static int davinci_mcasp_remove(struct platform_device *pdev) { - struct davinci_audio_dev *dev = dev_get_drvdata(&pdev->dev); snd_soc_unregister_dai(&pdev->dev); - clk_disable(dev->clk); - clk_put(dev->clk); - dev->clk = NULL; + + pm_runtime_put_sync(&pdev->dev); + pm_runtime_disable(&pdev->dev); return 0; } diff --git a/sound/soc/davinci/davinci-mcasp.h b/sound/soc/davinci/davinci-mcasp.h index 4681acc63606..51479f9ee909 100644 --- a/sound/soc/davinci/davinci-mcasp.h +++ b/sound/soc/davinci/davinci-mcasp.h @@ -40,9 +40,8 @@ struct davinci_audio_dev { struct davinci_pcm_dma_params dma_params[2]; void __iomem *base; int sample_rate; - struct clk *clk; + struct device *dev; unsigned int codec_fmt; - u8 clk_active; /* McASP specific data */ int tdm_slots; -- cgit v1.2.3 From 28d528c8dbab5c6b3cf2fc4f0e91470a9a63dbc0 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 9 Aug 2012 18:45:23 +0100 Subject: ASoC: core: Remove pointless error on card registration failure If we fail to register the card we should say why somewhere else so there's no point in repeating the same thing with less information. Signed-off-by: Mark Brown --- sound/soc/soc-core.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index f10f00b5d29f..3a43fa6ba2ee 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -1830,13 +1830,7 @@ static int soc_probe(struct platform_device *pdev) /* Bodge while we unpick instantiation */ card->dev = &pdev->dev; - ret = snd_soc_register_card(card); - if (ret != 0) { - dev_err(&pdev->dev, "Failed to register card\n"); - return ret; - } - - return 0; + return snd_soc_register_card(card); } static int soc_cleanup_card_resources(struct snd_soc_card *card) -- cgit v1.2.3 From cbd840dadeb03826b6cc074e38f380bbd4faaea5 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 8 Aug 2012 17:52:44 +0100 Subject: ASoC: arizona: Implement OPCLK support Arizona devices support two output system clocks. Provide support for configuring these via set_sysclk(). Once the clock API is more useful we should migrate over to that. Signed-off-by: Mark Brown --- sound/soc/codecs/arizona.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++ sound/soc/codecs/arizona.h | 6 +++-- 2 files changed, 70 insertions(+), 2 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/arizona.c b/sound/soc/codecs/arizona.c index 5c9cacaf2d52..5e96a0a1669c 100644 --- a/sound/soc/codecs/arizona.c +++ b/sound/soc/codecs/arizona.c @@ -229,6 +229,69 @@ int arizona_out_ev(struct snd_soc_dapm_widget *w, } EXPORT_SYMBOL_GPL(arizona_out_ev); +static unsigned int arizona_sysclk_48k_rates[] = { + 6144000, + 12288000, + 22579200, + 49152000, +}; + +static unsigned int arizona_sysclk_44k1_rates[] = { + 5644800, + 11289600, + 24576000, + 45158400, +}; + +static int arizona_set_opclk(struct snd_soc_codec *codec, unsigned int clk, + unsigned int freq) +{ + struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec); + unsigned int reg; + unsigned int *rates; + int ref, div, refclk; + + switch (clk) { + case ARIZONA_CLK_OPCLK: + reg = ARIZONA_OUTPUT_SYSTEM_CLOCK; + refclk = priv->sysclk; + break; + case ARIZONA_CLK_ASYNC_OPCLK: + reg = ARIZONA_OUTPUT_ASYNC_CLOCK; + refclk = priv->asyncclk; + break; + default: + return -EINVAL; + } + + if (refclk % 8000) + rates = arizona_sysclk_44k1_rates; + else + rates = arizona_sysclk_48k_rates; + + for (ref = 0; ref < ARRAY_SIZE(arizona_sysclk_48k_rates) && + rates[ref] <= refclk; ref++) { + div = 1; + while (rates[ref] / div >= freq && div < 32) { + if (rates[ref] / div == freq) { + dev_dbg(codec->dev, "Configured %dHz OPCLK\n", + freq); + snd_soc_update_bits(codec, reg, + ARIZONA_OPCLK_DIV_MASK | + ARIZONA_OPCLK_SEL_MASK, + (div << + ARIZONA_OPCLK_DIV_SHIFT) | + ref); + return 0; + } + div++; + } + } + + dev_err(codec->dev, "Unable to generate %dHz OPCLK\n", freq); + return -EINVAL; +} + int arizona_set_sysclk(struct snd_soc_codec *codec, int clk_id, int source, unsigned int freq, int dir) { @@ -252,6 +315,9 @@ int arizona_set_sysclk(struct snd_soc_codec *codec, int clk_id, reg = ARIZONA_ASYNC_CLOCK_1; clk = &priv->asyncclk; break; + case ARIZONA_CLK_OPCLK: + case ARIZONA_CLK_ASYNC_OPCLK: + return arizona_set_opclk(codec, clk_id, freq); default: return -EINVAL; } diff --git a/sound/soc/codecs/arizona.h b/sound/soc/codecs/arizona.h index 59caca8865e8..eb66b52777c9 100644 --- a/sound/soc/codecs/arizona.h +++ b/sound/soc/codecs/arizona.h @@ -17,8 +17,10 @@ #include -#define ARIZONA_CLK_SYSCLK 1 -#define ARIZONA_CLK_ASYNCCLK 2 +#define ARIZONA_CLK_SYSCLK 1 +#define ARIZONA_CLK_ASYNCCLK 2 +#define ARIZONA_CLK_OPCLK 3 +#define ARIZONA_CLK_ASYNC_OPCLK 4 #define ARIZONA_CLK_SRC_MCLK1 0x0 #define ARIZONA_CLK_SRC_MCLK2 0x1 -- cgit v1.2.3 From c665d1a8c4c391a7918f53c8a02d909626266773 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 8 Aug 2012 17:53:01 +0100 Subject: ASoC: wm5102: Enable output clocks Signed-off-by: Mark Brown --- sound/soc/codecs/wm5102.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'sound/soc') diff --git a/sound/soc/codecs/wm5102.c b/sound/soc/codecs/wm5102.c index 6537f16d383e..4c2fc361051c 100644 --- a/sound/soc/codecs/wm5102.c +++ b/sound/soc/codecs/wm5102.c @@ -285,6 +285,10 @@ SND_SOC_DAPM_SUPPLY("SYSCLK", ARIZONA_SYSTEM_CLOCK_1, ARIZONA_SYSCLK_ENA_SHIFT, 0, NULL, 0), SND_SOC_DAPM_SUPPLY("ASYNCCLK", ARIZONA_ASYNC_CLOCK_1, ARIZONA_ASYNC_CLK_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_SUPPLY("OPCLK", ARIZONA_OUTPUT_SYSTEM_CLOCK, + ARIZONA_OPCLK_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_SUPPLY("ASYNCOPCLK", ARIZONA_OUTPUT_ASYNC_CLOCK, + ARIZONA_OPCLK_ASYNC_ENA_SHIFT, 0, NULL, 0), SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD2", 0), SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD3", 0), -- cgit v1.2.3 From 94237f8e8ed5c2bfc5d8a28cdda241170eda6994 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 9 Aug 2012 19:14:43 +0100 Subject: ASoC: wm5110: Enable output clocks Signed-off-by: Mark Brown --- sound/soc/codecs/wm5110.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'sound/soc') diff --git a/sound/soc/codecs/wm5110.c b/sound/soc/codecs/wm5110.c index 8033f7065189..3db6e6e7a591 100644 --- a/sound/soc/codecs/wm5110.c +++ b/sound/soc/codecs/wm5110.c @@ -305,6 +305,10 @@ SND_SOC_DAPM_SUPPLY("SYSCLK", ARIZONA_SYSTEM_CLOCK_1, ARIZONA_SYSCLK_ENA_SHIFT, 0, NULL, 0), SND_SOC_DAPM_SUPPLY("ASYNCCLK", ARIZONA_ASYNC_CLOCK_1, ARIZONA_ASYNC_CLK_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_SUPPLY("OPCLK", ARIZONA_OUTPUT_SYSTEM_CLOCK, + ARIZONA_OPCLK_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_SUPPLY("ASYNCOPCLK", ARIZONA_OUTPUT_ASYNC_CLOCK, + ARIZONA_OPCLK_ASYNC_ENA_SHIFT, 0, NULL, 0), SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD2", 0), SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD3", 0), -- cgit v1.2.3 From b545dd924b4ffaf1e4fdd73fe7e9b6eb01e45aea Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 7 Aug 2012 20:03:02 +0100 Subject: ASoC: bells: Add machine driver for Wolfson Bells boards The Wolfson Bells board takes submodules for various audio functions but since the system integrations are virtually identical for most of them we can support the overwhemling majority from the same machine driver. Signed-off-by: Mark Brown --- sound/soc/samsung/Kconfig | 8 ++ sound/soc/samsung/Makefile | 2 + sound/soc/samsung/bells.c | 346 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 356 insertions(+) create mode 100644 sound/soc/samsung/bells.c (limited to 'sound/soc') diff --git a/sound/soc/samsung/Kconfig b/sound/soc/samsung/Kconfig index fe3995ce9b38..fb5600083612 100644 --- a/sound/soc/samsung/Kconfig +++ b/sound/soc/samsung/Kconfig @@ -199,6 +199,14 @@ config SND_SOC_TOBERMORY select SND_SAMSUNG_I2S select SND_SOC_WM8962 +config SND_SOC_BELLS + tristate "Audio support for Wolfson Bells" + depends on SND_SOC_SAMSUNG && MACH_WLF_CRAGG_6410 + select SND_SAMSUNG_I2S + select SND_SOC_WM5102 + select SND_SOC_WM5110 + select SND_SOC_WM9081 + config SND_SOC_LOWLAND tristate "Audio support for Wolfson Lowland" depends on SND_SOC_SAMSUNG && MACH_WLF_CRAGG_6410 diff --git a/sound/soc/samsung/Makefile b/sound/soc/samsung/Makefile index 9d03beb40c86..709f6059ad67 100644 --- a/sound/soc/samsung/Makefile +++ b/sound/soc/samsung/Makefile @@ -42,6 +42,7 @@ snd-soc-speyside-objs := speyside.o snd-soc-tobermory-objs := tobermory.o snd-soc-lowland-objs := lowland.o snd-soc-littlemill-objs := littlemill.o +snd-soc-bells-objs := bells.o obj-$(CONFIG_SND_SOC_SAMSUNG_JIVE_WM8750) += snd-soc-jive-wm8750.o obj-$(CONFIG_SND_SOC_SAMSUNG_NEO1973_WM8753) += snd-soc-neo1973-wm8753.o @@ -65,3 +66,4 @@ obj-$(CONFIG_SND_SOC_SPEYSIDE) += snd-soc-speyside.o obj-$(CONFIG_SND_SOC_TOBERMORY) += snd-soc-tobermory.o obj-$(CONFIG_SND_SOC_LOWLAND) += snd-soc-lowland.o obj-$(CONFIG_SND_SOC_LITTLEMILL) += snd-soc-littlemill.o +obj-$(CONFIG_SND_SOC_BELLS) += snd-soc-bells.o diff --git a/sound/soc/samsung/bells.c b/sound/soc/samsung/bells.c new file mode 100644 index 000000000000..5dc10dfc0d42 --- /dev/null +++ b/sound/soc/samsung/bells.c @@ -0,0 +1,346 @@ +/* + * Bells audio support + * + * Copyright 2012 Wolfson Microelectronics + * + * 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 "../codecs/wm5102.h" +#include "../codecs/wm9081.h" + +/* + * 44.1kHz based clocks for the SYSCLK domain, use a very high clock + * to allow all the DSP functionality to be enabled if desired. + */ +#define SYSCLK_RATE (44100 * 1024) + +/* 48kHz based clocks for the ASYNC domain */ +#define ASYNCCLK_RATE (48000 * 512) + +/* BCLK2 is fixed at this currently */ +#define BCLK2_RATE (64 * 8000) + +/* + * Expect a 24.576MHz crystal if one is fitted (the driver will function + * if this is not fitted). + */ +#define MCLK_RATE 24576000 + +#define WM9081_AUDIO_RATE 44100 +#define WM9081_MCLK_RATE (WM9081_AUDIO_RATE * 256) + +static int bells_set_bias_level(struct snd_soc_card *card, + struct snd_soc_dapm_context *dapm, + enum snd_soc_bias_level level) +{ + struct snd_soc_dai *codec_dai = card->rtd[0].codec_dai; + struct snd_soc_codec *codec = codec_dai->codec; + int ret; + + if (dapm->dev != codec_dai->dev) + return 0; + + switch (level) { + case SND_SOC_BIAS_PREPARE: + if (dapm->bias_level == SND_SOC_BIAS_STANDBY) { + ret = snd_soc_codec_set_pll(codec, WM5102_FLL1, + ARIZONA_FLL_SRC_MCLK1, + MCLK_RATE, + SYSCLK_RATE); + if (ret < 0) + pr_err("Failed to start FLL: %d\n", ret); + + ret = snd_soc_codec_set_pll(codec, WM5102_FLL2, + ARIZONA_FLL_SRC_AIF2BCLK, + BCLK2_RATE, + ASYNCCLK_RATE); + if (ret < 0) + pr_err("Failed to start FLL: %d\n", ret); + } + break; + + default: + break; + } + + return 0; +} + +static int bells_set_bias_level_post(struct snd_soc_card *card, + struct snd_soc_dapm_context *dapm, + enum snd_soc_bias_level level) +{ + struct snd_soc_dai *codec_dai = card->rtd[0].codec_dai; + struct snd_soc_codec *codec = codec_dai->codec; + int ret; + + if (dapm->dev != codec_dai->dev) + return 0; + + switch (level) { + case SND_SOC_BIAS_STANDBY: + ret = snd_soc_codec_set_pll(codec, WM5102_FLL1, 0, 0, 0); + if (ret < 0) { + pr_err("Failed to stop FLL: %d\n", ret); + return ret; + } + + ret = snd_soc_codec_set_pll(codec, WM5102_FLL2, 0, 0, 0); + if (ret < 0) { + pr_err("Failed to stop FLL: %d\n", ret); + return ret; + } + break; + + default: + break; + } + + dapm->bias_level = level; + + return 0; +} + +static int bells_late_probe(struct snd_soc_card *card) +{ + struct snd_soc_codec *codec = card->rtd[0].codec; + struct snd_soc_dai *aif1_dai = card->rtd[0].codec_dai; + struct snd_soc_dai *aif2_dai = card->rtd[1].cpu_dai; + struct snd_soc_dai *aif3_dai = card->rtd[2].cpu_dai; + struct snd_soc_dai *wm9081_dai = card->rtd[2].codec_dai; + int ret; + + ret = snd_soc_dai_set_sysclk(aif1_dai, ARIZONA_CLK_SYSCLK, 0, 0); + if (ret != 0) { + dev_err(aif1_dai->dev, "Failed to set AIF1 clock: %d\n", ret); + return ret; + } + + ret = snd_soc_dai_set_sysclk(aif2_dai, ARIZONA_CLK_ASYNCCLK, 0, 0); + if (ret != 0) { + dev_err(aif2_dai->dev, "Failed to set AIF2 clock: %d\n", ret); + return ret; + } + + ret = snd_soc_dai_set_sysclk(aif3_dai, ARIZONA_CLK_SYSCLK, 0, 0); + if (ret != 0) { + dev_err(aif1_dai->dev, "Failed to set AIF1 clock: %d\n", ret); + return ret; + } + + ret = snd_soc_codec_set_sysclk(codec, ARIZONA_CLK_SYSCLK, + ARIZONA_CLK_SRC_FLL1, SYSCLK_RATE, + SND_SOC_CLOCK_IN); + if (ret != 0) { + dev_err(codec->dev, "Failed to set SYSCLK: %d\n", ret); + return ret; + } + + ret = snd_soc_codec_set_sysclk(codec, ARIZONA_CLK_OPCLK, 0, + WM9081_MCLK_RATE, SND_SOC_CLOCK_OUT); + if (ret != 0) { + dev_err(codec->dev, "Failed to set OPCLK: %d\n", ret); + return ret; + } + + ret = snd_soc_codec_set_sysclk(codec, ARIZONA_CLK_ASYNCCLK, + ARIZONA_CLK_SRC_FLL2, ASYNCCLK_RATE, + SND_SOC_CLOCK_IN); + if (ret != 0) { + dev_err(codec->dev, "Failed to set SYSCLK: %d\n", ret); + return ret; + } + + ret = snd_soc_codec_set_sysclk(wm9081_dai->codec, WM9081_SYSCLK_MCLK, + 0, WM9081_MCLK_RATE, 0); + if (ret != 0) { + dev_err(wm9081_dai->dev, "Failed to set MCLK: %d\n", ret); + return ret; + } + + return 0; +} + +static const struct snd_soc_pcm_stream baseband_params = { + .formats = SNDRV_PCM_FMTBIT_S32_LE, + .rate_min = 8000, + .rate_max = 8000, + .channels_min = 2, + .channels_max = 2, +}; + +static const struct snd_soc_pcm_stream sub_params = { + .formats = SNDRV_PCM_FMTBIT_S32_LE, + .rate_min = WM9081_AUDIO_RATE, + .rate_max = WM9081_AUDIO_RATE, + .channels_min = 2, + .channels_max = 2, +}; + +static struct snd_soc_dai_link bells_dai_wm5102[] = { + { + .name = "CPU", + .stream_name = "CPU", + .cpu_dai_name = "samsung-i2s.0", + .codec_dai_name = "wm5102-aif1", + .platform_name = "samsung-audio", + .codec_name = "wm5102-codec", + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF + | SND_SOC_DAIFMT_CBM_CFM, + }, + { + .name = "Baseband", + .stream_name = "Baseband", + .cpu_dai_name = "wm5102-aif2", + .codec_dai_name = "wm1250-ev1", + .codec_name = "wm1250-ev1.1-0027", + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF + | SND_SOC_DAIFMT_CBM_CFM, + .ignore_suspend = 1, + .params = &baseband_params, + }, + { + .name = "Sub", + .stream_name = "Sub", + .cpu_dai_name = "wm5102-aif3", + .codec_dai_name = "wm9081-hifi", + .codec_name = "wm9081.1-006c", + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF + | SND_SOC_DAIFMT_CBS_CFS, + .ignore_suspend = 1, + .params = &sub_params, + }, +}; + +static struct snd_soc_dai_link bells_dai_wm5110[] = { + { + .name = "CPU", + .stream_name = "CPU", + .cpu_dai_name = "samsung-i2s.0", + .codec_dai_name = "wm5110-aif1", + .platform_name = "samsung-audio", + .codec_name = "wm5110-codec", + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF + | SND_SOC_DAIFMT_CBM_CFM, + }, + { + .name = "Baseband", + .stream_name = "Baseband", + .cpu_dai_name = "wm5110-aif2", + .codec_dai_name = "wm1250-ev1", + .codec_name = "wm1250-ev1.1-0027", + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF + | SND_SOC_DAIFMT_CBM_CFM, + .ignore_suspend = 1, + .params = &baseband_params, + }, + { + .name = "Sub", + .stream_name = "Sub", + .cpu_dai_name = "wm5102-aif3", + .codec_dai_name = "wm9081-hifi", + .codec_name = "wm9081.1-006c", + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF + | SND_SOC_DAIFMT_CBS_CFS, + .ignore_suspend = 1, + .params = &sub_params, + }, +}; + +static struct snd_soc_codec_conf bells_codec_conf[] = { + { + .dev_name = "wm9081.1-006c", + .name_prefix = "Sub", + }, +}; + +static struct snd_soc_dapm_route bells_routes[] = { + { "Sub CLK_SYS", NULL, "OPCLK" }, +}; + +static struct snd_soc_card bells_cards[] = { + { + .name = "Bells WM5102", + .owner = THIS_MODULE, + .dai_link = bells_dai_wm5102, + .num_links = ARRAY_SIZE(bells_dai_wm5102), + .codec_conf = bells_codec_conf, + .num_configs = ARRAY_SIZE(bells_codec_conf), + + .late_probe = bells_late_probe, + + .dapm_routes = bells_routes, + .num_dapm_routes = ARRAY_SIZE(bells_routes), + + .set_bias_level = bells_set_bias_level, + .set_bias_level_post = bells_set_bias_level_post, + }, + { + .name = "Bells WM5110", + .owner = THIS_MODULE, + .dai_link = bells_dai_wm5110, + .num_links = ARRAY_SIZE(bells_dai_wm5110), + .codec_conf = bells_codec_conf, + .num_configs = ARRAY_SIZE(bells_codec_conf), + + .late_probe = bells_late_probe, + + .dapm_routes = bells_routes, + .num_dapm_routes = ARRAY_SIZE(bells_routes), + + .set_bias_level = bells_set_bias_level, + .set_bias_level_post = bells_set_bias_level_post, + }, +}; + + +static __devinit int bells_probe(struct platform_device *pdev) +{ + int ret; + + bells_cards[pdev->id].dev = &pdev->dev; + + ret = snd_soc_register_card(&bells_cards[pdev->id]); + if (ret) { + dev_err(&pdev->dev, + "snd_soc_register_card(%s) failed: %d\n", + bells_cards[pdev->id].name, ret); + return ret; + } + + return 0; +} + +static int __devexit bells_remove(struct platform_device *pdev) +{ + snd_soc_unregister_card(&bells_cards[pdev->id]); + + return 0; +} + +static struct platform_driver bells_driver = { + .driver = { + .name = "bells", + .owner = THIS_MODULE, + .pm = &snd_soc_pm_ops, + }, + .probe = bells_probe, + .remove = __devexit_p(bells_remove), +}; + +module_platform_driver(bells_driver); + +MODULE_DESCRIPTION("Bells audio support"); +MODULE_AUTHOR("Mark Brown "); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:bells"); -- cgit v1.2.3 From 3876566a368b30908ec4195d58f04a411f22f736 Mon Sep 17 00:00:00 2001 From: Jerry Snitselaar Date: Thu, 9 Aug 2012 23:16:26 -0700 Subject: ASoC: core: remove unused variable in soc_probe() in linux-next With commit 28d528c8 "ASoC: core: Remove pointless error on card registration failure", the variable ret is no longer used in soc_probe() and generates an unused variable warning during a build. Signed-off-by: Jerry Snitselaar Signed-off-by: Mark Brown --- sound/soc/soc-core.c | 1 - 1 file changed, 1 deletion(-) (limited to 'sound/soc') diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 3a43fa6ba2ee..f585d0239551 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -1814,7 +1814,6 @@ base_error: static int soc_probe(struct platform_device *pdev) { struct snd_soc_card *card = platform_get_drvdata(pdev); - int ret = 0; /* * no card, so machine driver should be registering card -- cgit v1.2.3 From fff8491c8b8cce5fc9190e025d1a665f2ee71a4f Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Tue, 14 Aug 2012 12:07:56 +0300 Subject: ASoC: omap-twl4030: Simple machine driver for TI SoC with twl4030 codec Machine driver to handle simple devices using twl4030 as audio codec. The driver supports the following boards: - Beagleboard or Devkit8000 - Gumstix Overo or CompuLab CM-T35/CM-T3730 - IGEP v2 - OMAP3EVM All of these boards can be switched to use this driver since their setup is identical. Devicetree support for the omap-twl4030 machine driver also implemented. Signed-off-by: Peter Ujfalusi Signed-off-by: Mark Brown --- .../devicetree/bindings/sound/omap-twl4030.txt | 17 ++ include/linux/platform_data/omap-twl4030.h | 32 ++++ sound/soc/omap/Kconfig | 13 ++ sound/soc/omap/Makefile | 2 + sound/soc/omap/omap-twl4030.c | 188 +++++++++++++++++++++ 5 files changed, 252 insertions(+) create mode 100644 Documentation/devicetree/bindings/sound/omap-twl4030.txt create mode 100644 include/linux/platform_data/omap-twl4030.h create mode 100644 sound/soc/omap/omap-twl4030.c (limited to 'sound/soc') diff --git a/Documentation/devicetree/bindings/sound/omap-twl4030.txt b/Documentation/devicetree/bindings/sound/omap-twl4030.txt new file mode 100644 index 000000000000..6fae51c7f766 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/omap-twl4030.txt @@ -0,0 +1,17 @@ +* Texas Instruments SoC with twl4030 based audio setups + +Required properties: +- compatible: "ti,omap-twl4030" +- ti,model: Name of the sound card (for example "omap3beagle") +- ti,mcbsp: phandle for the McBSP node +- ti,codec: phandle for the twl4030 audio node + +Example: + +sound { + compatible = "ti,omap-twl4030"; + ti,model = "omap3beagle"; + + ti,mcbsp = <&mcbsp2>; + ti,codec = <&twl_audio>; +}; diff --git a/include/linux/platform_data/omap-twl4030.h b/include/linux/platform_data/omap-twl4030.h new file mode 100644 index 000000000000..c7bef788daab --- /dev/null +++ b/include/linux/platform_data/omap-twl4030.h @@ -0,0 +1,32 @@ +/** + * omap-twl4030.h - ASoC machine driver for TI SoC based boards with twl4030 + * codec, header. + * + * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com + * All rights reserved. + * + * Author: Peter Ujfalusi + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + */ + +#ifndef _OMAP_TWL4030_H_ +#define _OMAP_TWL4030_H_ + +struct omap_tw4030_pdata { + const char *card_name; +}; + +#endif /* _OMAP_TWL4030_H_ */ diff --git a/sound/soc/omap/Kconfig b/sound/soc/omap/Kconfig index 57a2fa751085..fc83d748625f 100644 --- a/sound/soc/omap/Kconfig +++ b/sound/soc/omap/Kconfig @@ -95,6 +95,19 @@ config SND_OMAP_SOC_SDP3430 Say Y if you want to add support for SoC audio on Texas Instruments SDP3430. +config SND_OMAP_SOC_OMAP_TWL4030 + tristate "SoC Audio support for TI SoC based boards with twl4030 codec" + depends on TWL4030_CORE && SND_OMAP_SOC + select SND_OMAP_SOC_MCBSP + select SND_SOC_TWL4030 + help + Say Y if you want to add support for SoC audio on TI SoC based boards + using twl4030 as c codec. This driver currently supports: + - Beagleboard or Devkit8000 + - Gumstix Overo or CompuLab CM-T35/CM-T3730 + - IGEP v2 + - OMAP3EVM + config SND_OMAP_SOC_OMAP_ABE_TWL6040 tristate "SoC Audio support for OMAP boards using ABE and twl6040 codec" depends on TWL6040_CORE && SND_OMAP_SOC && ARCH_OMAP4 diff --git a/sound/soc/omap/Makefile b/sound/soc/omap/Makefile index 0e14dd322565..861e640e2be9 100644 --- a/sound/soc/omap/Makefile +++ b/sound/soc/omap/Makefile @@ -21,6 +21,7 @@ snd-soc-omap3evm-objs := omap3evm.o snd-soc-am3517evm-objs := am3517evm.o snd-soc-sdp3430-objs := sdp3430.o snd-soc-omap-abe-twl6040-objs := omap-abe-twl6040.o +snd-soc-omap-twl4030-objs := omap-twl4030.o snd-soc-omap3pandora-objs := omap3pandora.o snd-soc-omap3beagle-objs := omap3beagle.o snd-soc-zoom2-objs := zoom2.o @@ -37,6 +38,7 @@ obj-$(CONFIG_SND_OMAP_SOC_OMAP3EVM) += snd-soc-omap3evm.o obj-$(CONFIG_SND_OMAP_SOC_AM3517EVM) += snd-soc-am3517evm.o obj-$(CONFIG_SND_OMAP_SOC_SDP3430) += snd-soc-sdp3430.o obj-$(CONFIG_SND_OMAP_SOC_OMAP_ABE_TWL6040) += snd-soc-omap-abe-twl6040.o +obj-$(CONFIG_SND_OMAP_SOC_OMAP_TWL4030) += snd-soc-omap-twl4030.o obj-$(CONFIG_SND_OMAP_SOC_OMAP3_PANDORA) += snd-soc-omap3pandora.o obj-$(CONFIG_SND_OMAP_SOC_OMAP3_BEAGLE) += snd-soc-omap3beagle.o obj-$(CONFIG_SND_OMAP_SOC_ZOOM2) += snd-soc-zoom2.o diff --git a/sound/soc/omap/omap-twl4030.c b/sound/soc/omap/omap-twl4030.c new file mode 100644 index 000000000000..3b97b87971f5 --- /dev/null +++ b/sound/soc/omap/omap-twl4030.c @@ -0,0 +1,188 @@ +/* + * omap-twl4030.c -- SoC audio for TI SoC based boards with twl4030 codec + * + * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com + * All rights reserved. + * + * Author: Peter Ujfalusi + * + * This driver replaces the following machine drivers: + * omap3beagle (Author: Steve Sakoman ) + * omap3evm (Author: Anuj Aggarwal ) + * overo (Author: Steve Sakoman ) + * igep0020 (Author: Enric Balletbo i Serra ) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#include +#include +#include +#include + +#include +#include +#include + +#include "omap-mcbsp.h" +#include "omap-pcm.h" + +static int omap_twl4030_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_dai *codec_dai = rtd->codec_dai; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + struct snd_soc_codec *codec = rtd->codec; + struct snd_soc_card *card = codec->card; + unsigned int fmt; + int ret; + + switch (params_channels(params)) { + case 2: /* Stereo I2S mode */ + fmt = SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_NB_NF | + SND_SOC_DAIFMT_CBM_CFM; + break; + case 4: /* Four channel TDM mode */ + fmt = SND_SOC_DAIFMT_DSP_A | + SND_SOC_DAIFMT_IB_NF | + SND_SOC_DAIFMT_CBM_CFM; + break; + default: + return -EINVAL; + } + + /* Set codec DAI configuration */ + ret = snd_soc_dai_set_fmt(codec_dai, fmt); + if (ret < 0) { + dev_err(card->dev, "can't set codec DAI configuration\n"); + return ret; + } + + /* Set cpu DAI configuration */ + ret = snd_soc_dai_set_fmt(cpu_dai, fmt); + if (ret < 0) { + dev_err(card->dev, "can't set cpu DAI configuration\n"); + return ret; + } + + return 0; +} + +static struct snd_soc_ops omap_twl4030_ops = { + .hw_params = omap_twl4030_hw_params, +}; + +/* Digital audio interface glue - connects codec <--> CPU */ +static struct snd_soc_dai_link omap_twl4030_dai_links[] = { + { + .name = "TWL4030", + .stream_name = "TWL4030", + .cpu_dai_name = "omap-mcbsp.2", + .codec_dai_name = "twl4030-hifi", + .platform_name = "omap-pcm-audio", + .codec_name = "twl4030-codec", + .ops = &omap_twl4030_ops, + }, +}; + +/* Audio machine driver */ +static struct snd_soc_card omap_twl4030_card = { + .owner = THIS_MODULE, + .dai_link = omap_twl4030_dai_links, + .num_links = ARRAY_SIZE(omap_twl4030_dai_links), +}; + +static __devinit int omap_twl4030_probe(struct platform_device *pdev) +{ + struct omap_tw4030_pdata *pdata = dev_get_platdata(&pdev->dev); + struct device_node *node = pdev->dev.of_node; + struct snd_soc_card *card = &omap_twl4030_card; + int ret = 0; + + card->dev = &pdev->dev; + + if (node) { + struct device_node *dai_node; + + if (snd_soc_of_parse_card_name(card, "ti,model")) { + dev_err(&pdev->dev, "Card name is not provided\n"); + return -ENODEV; + } + + dai_node = of_parse_phandle(node, "ti,mcbsp", 0); + if (!dai_node) { + dev_err(&pdev->dev, "McBSP node is not provided\n"); + return -EINVAL; + } + omap_twl4030_dai_links[0].cpu_dai_name = NULL; + omap_twl4030_dai_links[0].cpu_of_node = dai_node; + + } else if (pdata) { + if (pdata->card_name) { + card->name = pdata->card_name; + } else { + dev_err(&pdev->dev, "Card name is not provided\n"); + return -ENODEV; + } + } else { + dev_err(&pdev->dev, "Missing pdata\n"); + return -ENODEV; + } + + ret = snd_soc_register_card(card); + if (ret) { + dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", + ret); + return ret; + } + + return 0; +} + +static int __devexit omap_twl4030_remove(struct platform_device *pdev) +{ + struct snd_soc_card *card = platform_get_drvdata(pdev); + + snd_soc_unregister_card(card); + + return 0; +} + +static const struct of_device_id omap_twl4030_of_match[] = { + {.compatible = "ti,omap-twl4030", }, + { }, +}; +MODULE_DEVICE_TABLE(of, omap_twl4030_of_match); + +static struct platform_driver omap_twl4030_driver = { + .driver = { + .name = "omap-twl4030", + .owner = THIS_MODULE, + .pm = &snd_soc_pm_ops, + .of_match_table = omap_twl4030_of_match, + }, + .probe = omap_twl4030_probe, + .remove = __devexit_p(omap_twl4030_remove), +}; + +module_platform_driver(omap_twl4030_driver); + +MODULE_AUTHOR("Peter Ujfalusi "); +MODULE_DESCRIPTION("ALSA SoC for TI SoC based boards with twl4030 codec"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:omap-twl4030"); -- cgit v1.2.3 From 152c6e56f6a8577bd291f6f4ca897e5758332a1b Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Tue, 14 Aug 2012 12:07:59 +0300 Subject: ASoC: Remove obsolete OMAP3 machine drivers The new omap-twl4030 handles the boards used the following drivers: igep0020, omap3beagle, omap3evm and overo. Remove these drivers since they are mostly identical and we already have drop in replacement for all of them. Note: Earlier patch added the needed code for the board files to retain the audio support for boards I can identify that used one of the removed drivers. If I missed something please take a look at for example: arch/arm/mach-omap2/board-omap3beagle.c on how add support for omap-twl4030 audio. Signed-off-by: Peter Ujfalusi Signed-off-by: Mark Brown --- sound/soc/omap/Kconfig | 35 ---------- sound/soc/omap/Makefile | 8 --- sound/soc/omap/igep0020.c | 120 ---------------------------------- sound/soc/omap/omap3beagle.c | 150 ------------------------------------------- sound/soc/omap/omap3evm.c | 118 ---------------------------------- sound/soc/omap/overo.c | 122 ----------------------------------- 6 files changed, 553 deletions(-) delete mode 100644 sound/soc/omap/igep0020.c delete mode 100644 sound/soc/omap/omap3beagle.c delete mode 100644 sound/soc/omap/omap3evm.c delete mode 100644 sound/soc/omap/overo.c (limited to 'sound/soc') diff --git a/sound/soc/omap/Kconfig b/sound/soc/omap/Kconfig index fc83d748625f..2c484a52ef92 100644 --- a/sound/soc/omap/Kconfig +++ b/sound/soc/omap/Kconfig @@ -60,23 +60,6 @@ config SND_OMAP_SOC_OSK5912 help Say Y if you want to add support for SoC audio on osk5912. -config SND_OMAP_SOC_OVERO - tristate "SoC Audio support for Gumstix Overo and CompuLab CM-T35" - depends on TWL4030_CORE && SND_OMAP_SOC && (MACH_OVERO || MACH_CM_T35) - select SND_OMAP_SOC_MCBSP - select SND_SOC_TWL4030 - help - Say Y if you want to add support for SoC audio on the - Gumstix Overo or CompuLab CM-T35 - -config SND_OMAP_SOC_OMAP3EVM - tristate "SoC Audio support for OMAP3EVM board" - depends on TWL4030_CORE && SND_OMAP_SOC && MACH_OMAP3EVM - select SND_OMAP_SOC_MCBSP - select SND_SOC_TWL4030 - help - Say Y if you want to add support for SoC audio on the omap3evm board. - config SND_OMAP_SOC_AM3517EVM tristate "SoC Audio support for OMAP3517 / AM3517 EVM" depends on SND_OMAP_SOC && MACH_OMAP3517EVM && I2C @@ -140,16 +123,6 @@ config SND_OMAP_SOC_OMAP3_PANDORA help Say Y if you want to add support for SoC audio on the OMAP3 Pandora. -config SND_OMAP_SOC_OMAP3_BEAGLE - tristate "SoC Audio support for OMAP3 Beagle and Devkit8000" - depends on TWL4030_CORE && SND_OMAP_SOC - depends on (MACH_OMAP3_BEAGLE || MACH_DEVKIT8000) - select SND_OMAP_SOC_MCBSP - select SND_SOC_TWL4030 - help - Say Y if you want to add support for SoC audio on the Beagleboard or - the clone Devkit8000. - config SND_OMAP_SOC_ZOOM2 tristate "SoC Audio support for Zoom2" depends on TWL4030_CORE && SND_OMAP_SOC && MACH_OMAP_ZOOM2 @@ -157,11 +130,3 @@ config SND_OMAP_SOC_ZOOM2 select SND_SOC_TWL4030 help Say Y if you want to add support for Soc audio on Zoom2 board. - -config SND_OMAP_SOC_IGEP0020 - tristate "SoC Audio support for IGEP v2" - depends on TWL4030_CORE && SND_OMAP_SOC && MACH_IGEP0020 - select SND_OMAP_SOC_MCBSP - select SND_SOC_TWL4030 - help - Say Y if you want to add support for Soc audio on IGEP v2 board. diff --git a/sound/soc/omap/Makefile b/sound/soc/omap/Makefile index 861e640e2be9..19637e55ea48 100644 --- a/sound/soc/omap/Makefile +++ b/sound/soc/omap/Makefile @@ -16,31 +16,23 @@ snd-soc-n810-objs := n810.o snd-soc-rx51-objs := rx51.o snd-soc-ams-delta-objs := ams-delta.o snd-soc-osk5912-objs := osk5912.o -snd-soc-overo-objs := overo.o -snd-soc-omap3evm-objs := omap3evm.o snd-soc-am3517evm-objs := am3517evm.o snd-soc-sdp3430-objs := sdp3430.o snd-soc-omap-abe-twl6040-objs := omap-abe-twl6040.o snd-soc-omap-twl4030-objs := omap-twl4030.o snd-soc-omap3pandora-objs := omap3pandora.o -snd-soc-omap3beagle-objs := omap3beagle.o snd-soc-zoom2-objs := zoom2.o -snd-soc-igep0020-objs := igep0020.o snd-soc-omap-hdmi-card-objs := omap-hdmi-card.o obj-$(CONFIG_SND_OMAP_SOC_N810) += snd-soc-n810.o obj-$(CONFIG_SND_OMAP_SOC_RX51) += snd-soc-rx51.o obj-$(CONFIG_SND_OMAP_SOC_AMS_DELTA) += snd-soc-ams-delta.o obj-$(CONFIG_SND_OMAP_SOC_OSK5912) += snd-soc-osk5912.o -obj-$(CONFIG_SND_OMAP_SOC_OVERO) += snd-soc-overo.o obj-$(CONFIG_SND_OMAP_SOC_OMAP2EVM) += snd-soc-omap2evm.o -obj-$(CONFIG_SND_OMAP_SOC_OMAP3EVM) += snd-soc-omap3evm.o obj-$(CONFIG_SND_OMAP_SOC_AM3517EVM) += snd-soc-am3517evm.o obj-$(CONFIG_SND_OMAP_SOC_SDP3430) += snd-soc-sdp3430.o obj-$(CONFIG_SND_OMAP_SOC_OMAP_ABE_TWL6040) += snd-soc-omap-abe-twl6040.o obj-$(CONFIG_SND_OMAP_SOC_OMAP_TWL4030) += snd-soc-omap-twl4030.o obj-$(CONFIG_SND_OMAP_SOC_OMAP3_PANDORA) += snd-soc-omap3pandora.o -obj-$(CONFIG_SND_OMAP_SOC_OMAP3_BEAGLE) += snd-soc-omap3beagle.o obj-$(CONFIG_SND_OMAP_SOC_ZOOM2) += snd-soc-zoom2.o -obj-$(CONFIG_SND_OMAP_SOC_IGEP0020) += snd-soc-igep0020.o obj-$(CONFIG_SND_OMAP_SOC_OMAP_HDMI) += snd-soc-omap-hdmi-card.o diff --git a/sound/soc/omap/igep0020.c b/sound/soc/omap/igep0020.c deleted file mode 100644 index e8357819175b..000000000000 --- a/sound/soc/omap/igep0020.c +++ /dev/null @@ -1,120 +0,0 @@ -/* - * igep0020.c -- SoC audio for IGEP v2 - * - * Based on sound/soc/omap/overo.c by Steve Sakoman - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "omap-mcbsp.h" -#include "omap-pcm.h" - -static int igep2_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *codec_dai = rtd->codec_dai; - int ret; - - /* Set the codec system clock for DAC and ADC */ - ret = snd_soc_dai_set_sysclk(codec_dai, 0, 26000000, - SND_SOC_CLOCK_IN); - if (ret < 0) { - printk(KERN_ERR "can't set codec system clock\n"); - return ret; - } - - return 0; -} - -static struct snd_soc_ops igep2_ops = { - .hw_params = igep2_hw_params, -}; - -/* Digital audio interface glue - connects codec <--> CPU */ -static struct snd_soc_dai_link igep2_dai = { - .name = "TWL4030", - .stream_name = "TWL4030", - .cpu_dai_name = "omap-mcbsp.2", - .codec_dai_name = "twl4030-hifi", - .platform_name = "omap-pcm-audio", - .codec_name = "twl4030-codec", - .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBM_CFM, - .ops = &igep2_ops, -}; - -/* Audio machine driver */ -static struct snd_soc_card snd_soc_card_igep2 = { - .name = "igep2", - .owner = THIS_MODULE, - .dai_link = &igep2_dai, - .num_links = 1, -}; - -static struct platform_device *igep2_snd_device; - -static int __init igep2_soc_init(void) -{ - int ret; - - if (!machine_is_igep0020()) - return -ENODEV; - printk(KERN_INFO "IGEP v2 SoC init\n"); - - igep2_snd_device = platform_device_alloc("soc-audio", -1); - if (!igep2_snd_device) { - printk(KERN_ERR "Platform device allocation failed\n"); - return -ENOMEM; - } - - platform_set_drvdata(igep2_snd_device, &snd_soc_card_igep2); - - ret = platform_device_add(igep2_snd_device); - if (ret) - goto err1; - - return 0; - -err1: - printk(KERN_ERR "Unable to add platform device\n"); - platform_device_put(igep2_snd_device); - - return ret; -} -module_init(igep2_soc_init); - -static void __exit igep2_soc_exit(void) -{ - platform_device_unregister(igep2_snd_device); -} -module_exit(igep2_soc_exit); - -MODULE_AUTHOR("Enric Balletbo i Serra "); -MODULE_DESCRIPTION("ALSA SoC IGEP v2"); -MODULE_LICENSE("GPL"); diff --git a/sound/soc/omap/omap3beagle.c b/sound/soc/omap/omap3beagle.c deleted file mode 100644 index 2830dfd05661..000000000000 --- a/sound/soc/omap/omap3beagle.c +++ /dev/null @@ -1,150 +0,0 @@ -/* - * omap3beagle.c -- SoC audio for OMAP3 Beagle - * - * Author: Steve Sakoman - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "omap-mcbsp.h" -#include "omap-pcm.h" - -static int omap3beagle_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *codec_dai = rtd->codec_dai; - struct snd_soc_dai *cpu_dai = rtd->cpu_dai; - unsigned int fmt; - int ret; - - switch (params_channels(params)) { - case 2: /* Stereo I2S mode */ - fmt = SND_SOC_DAIFMT_I2S | - SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBM_CFM; - break; - case 4: /* Four channel TDM mode */ - fmt = SND_SOC_DAIFMT_DSP_A | - SND_SOC_DAIFMT_IB_NF | - SND_SOC_DAIFMT_CBM_CFM; - break; - default: - return -EINVAL; - } - - /* Set codec DAI configuration */ - ret = snd_soc_dai_set_fmt(codec_dai, fmt); - if (ret < 0) { - printk(KERN_ERR "can't set codec DAI configuration\n"); - return ret; - } - - /* Set cpu DAI configuration */ - ret = snd_soc_dai_set_fmt(cpu_dai, fmt); - if (ret < 0) { - printk(KERN_ERR "can't set cpu DAI configuration\n"); - return ret; - } - - /* Set the codec system clock for DAC and ADC */ - ret = snd_soc_dai_set_sysclk(codec_dai, 0, 26000000, - SND_SOC_CLOCK_IN); - if (ret < 0) { - printk(KERN_ERR "can't set codec system clock\n"); - return ret; - } - - return 0; -} - -static struct snd_soc_ops omap3beagle_ops = { - .hw_params = omap3beagle_hw_params, -}; - -/* Digital audio interface glue - connects codec <--> CPU */ -static struct snd_soc_dai_link omap3beagle_dai = { - .name = "TWL4030", - .stream_name = "TWL4030", - .cpu_dai_name = "omap-mcbsp.2", - .platform_name = "omap-pcm-audio", - .codec_dai_name = "twl4030-hifi", - .codec_name = "twl4030-codec", - .ops = &omap3beagle_ops, -}; - -/* Audio machine driver */ -static struct snd_soc_card snd_soc_omap3beagle = { - .name = "omap3beagle", - .owner = THIS_MODULE, - .dai_link = &omap3beagle_dai, - .num_links = 1, -}; - -static struct platform_device *omap3beagle_snd_device; - -static int __init omap3beagle_soc_init(void) -{ - int ret; - - if (!(machine_is_omap3_beagle() || machine_is_devkit8000())) - return -ENODEV; - pr_info("OMAP3 Beagle/Devkit8000 SoC init\n"); - - omap3beagle_snd_device = platform_device_alloc("soc-audio", -1); - if (!omap3beagle_snd_device) { - printk(KERN_ERR "Platform device allocation failed\n"); - return -ENOMEM; - } - - platform_set_drvdata(omap3beagle_snd_device, &snd_soc_omap3beagle); - - ret = platform_device_add(omap3beagle_snd_device); - if (ret) - goto err1; - - return 0; - -err1: - printk(KERN_ERR "Unable to add platform device\n"); - platform_device_put(omap3beagle_snd_device); - - return ret; -} - -static void __exit omap3beagle_soc_exit(void) -{ - platform_device_unregister(omap3beagle_snd_device); -} - -module_init(omap3beagle_soc_init); -module_exit(omap3beagle_soc_exit); - -MODULE_AUTHOR("Steve Sakoman "); -MODULE_DESCRIPTION("ALSA SoC OMAP3 Beagle"); -MODULE_LICENSE("GPL"); diff --git a/sound/soc/omap/omap3evm.c b/sound/soc/omap/omap3evm.c deleted file mode 100644 index 3d468c9179d7..000000000000 --- a/sound/soc/omap/omap3evm.c +++ /dev/null @@ -1,118 +0,0 @@ -/* - * omap3evm.c -- ALSA SoC support for OMAP3 EVM - * - * Author: Anuj Aggarwal - * - * Based on sound/soc/omap/beagle.c by Steve Sakoman - * - * Copyright (C) 2008 Texas Instruments, Incorporated - * - * 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 version 2. - * - * This program is distributed "as is" WITHOUT ANY WARRANTY of any kind, - * whether express or implied; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - */ - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "omap-mcbsp.h" -#include "omap-pcm.h" - -static int omap3evm_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *codec_dai = rtd->codec_dai; - int ret; - - /* Set the codec system clock for DAC and ADC */ - ret = snd_soc_dai_set_sysclk(codec_dai, 0, 26000000, - SND_SOC_CLOCK_IN); - if (ret < 0) { - printk(KERN_ERR "Can't set codec system clock\n"); - return ret; - } - - return 0; -} - -static struct snd_soc_ops omap3evm_ops = { - .hw_params = omap3evm_hw_params, -}; - -/* Digital audio interface glue - connects codec <--> CPU */ -static struct snd_soc_dai_link omap3evm_dai = { - .name = "TWL4030", - .stream_name = "TWL4030", - .cpu_dai_name = "omap-mcbsp.2", - .codec_dai_name = "twl4030-hifi", - .platform_name = "omap-pcm-audio", - .codec_name = "twl4030-codec", - .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBM_CFM, - .ops = &omap3evm_ops, -}; - -/* Audio machine driver */ -static struct snd_soc_card snd_soc_omap3evm = { - .name = "omap3evm", - .owner = THIS_MODULE, - .dai_link = &omap3evm_dai, - .num_links = 1, -}; - -static struct platform_device *omap3evm_snd_device; - -static int __init omap3evm_soc_init(void) -{ - int ret; - - if (!machine_is_omap3evm()) - return -ENODEV; - pr_info("OMAP3 EVM SoC init\n"); - - omap3evm_snd_device = platform_device_alloc("soc-audio", -1); - if (!omap3evm_snd_device) { - printk(KERN_ERR "Platform device allocation failed\n"); - return -ENOMEM; - } - - platform_set_drvdata(omap3evm_snd_device, &snd_soc_omap3evm); - ret = platform_device_add(omap3evm_snd_device); - if (ret) - goto err1; - - return 0; - -err1: - printk(KERN_ERR "Unable to add platform device\n"); - platform_device_put(omap3evm_snd_device); - - return ret; -} - -static void __exit omap3evm_soc_exit(void) -{ - platform_device_unregister(omap3evm_snd_device); -} - -module_init(omap3evm_soc_init); -module_exit(omap3evm_soc_exit); - -MODULE_AUTHOR("Anuj Aggarwal "); -MODULE_DESCRIPTION("ALSA SoC OMAP3 EVM"); -MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/omap/overo.c b/sound/soc/omap/overo.c deleted file mode 100644 index 6ac3e0c3c282..000000000000 --- a/sound/soc/omap/overo.c +++ /dev/null @@ -1,122 +0,0 @@ -/* - * overo.c -- SoC audio for Gumstix Overo - * - * Author: Steve Sakoman - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "omap-mcbsp.h" -#include "omap-pcm.h" - -static int overo_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *codec_dai = rtd->codec_dai; - int ret; - - /* Set the codec system clock for DAC and ADC */ - ret = snd_soc_dai_set_sysclk(codec_dai, 0, 26000000, - SND_SOC_CLOCK_IN); - if (ret < 0) { - printk(KERN_ERR "can't set codec system clock\n"); - return ret; - } - - return 0; -} - -static struct snd_soc_ops overo_ops = { - .hw_params = overo_hw_params, -}; - -/* Digital audio interface glue - connects codec <--> CPU */ -static struct snd_soc_dai_link overo_dai = { - .name = "TWL4030", - .stream_name = "TWL4030", - .cpu_dai_name = "omap-mcbsp.2", - .codec_dai_name = "twl4030-hifi", - .platform_name = "omap-pcm-audio", - .codec_name = "twl4030-codec", - .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBM_CFM, - .ops = &overo_ops, -}; - -/* Audio machine driver */ -static struct snd_soc_card snd_soc_card_overo = { - .name = "overo", - .owner = THIS_MODULE, - .dai_link = &overo_dai, - .num_links = 1, -}; - -static struct platform_device *overo_snd_device; - -static int __init overo_soc_init(void) -{ - int ret; - - if (!(machine_is_overo() || machine_is_cm_t35())) { - pr_debug("Incomatible machine!\n"); - return -ENODEV; - } - printk(KERN_INFO "overo SoC init\n"); - - overo_snd_device = platform_device_alloc("soc-audio", -1); - if (!overo_snd_device) { - printk(KERN_ERR "Platform device allocation failed\n"); - return -ENOMEM; - } - - platform_set_drvdata(overo_snd_device, &snd_soc_card_overo); - - ret = platform_device_add(overo_snd_device); - if (ret) - goto err1; - - return 0; - -err1: - printk(KERN_ERR "Unable to add platform device\n"); - platform_device_put(overo_snd_device); - - return ret; -} -module_init(overo_soc_init); - -static void __exit overo_soc_exit(void) -{ - platform_device_unregister(overo_snd_device); -} -module_exit(overo_soc_exit); - -MODULE_AUTHOR("Steve Sakoman "); -MODULE_DESCRIPTION("ALSA SoC overo"); -MODULE_LICENSE("GPL"); -- cgit v1.2.3 From a3150f09174ace7878bf4bbbf23d3ba25cc01261 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 16 Aug 2012 20:28:18 +0100 Subject: ASoC: wm5102: Add AEC routing control Signed-off-by: Mark Brown --- sound/soc/codecs/wm5102.c | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) (limited to 'sound/soc') diff --git a/sound/soc/codecs/wm5102.c b/sound/soc/codecs/wm5102.c index 4c2fc361051c..2e6f1ffc9fd4 100644 --- a/sound/soc/codecs/wm5102.c +++ b/sound/soc/codecs/wm5102.c @@ -280,6 +280,27 @@ ARIZONA_MIXER_ENUMS(ASRC1R, ARIZONA_ASRC1RMIX_INPUT_1_SOURCE); ARIZONA_MIXER_ENUMS(ASRC2L, ARIZONA_ASRC2LMIX_INPUT_1_SOURCE); ARIZONA_MIXER_ENUMS(ASRC2R, ARIZONA_ASRC2RMIX_INPUT_1_SOURCE); + +static const char *wm5102_aec_loopback_texts[] = { + "HPOUT1L", "HPOUT1R", "HPOUT2L", "HPOUT2R", "EPOUT", + "SPKOUTL", "SPKOUTR", "SPKDAT1L", "SPKDAT1R", +}; + +static const unsigned int wm5102_aec_loopback_values[] = { + 0, 1, 2, 3, 4, 6, 7, 8, 9, +}; + +static const struct soc_enum wm5102_aec_loopback = + SOC_VALUE_ENUM_SINGLE(ARIZONA_DAC_AEC_CONTROL_1, + ARIZONA_AEC_LOOPBACK_SRC_SHIFT, + ARIZONA_AEC_LOOPBACK_SRC_MASK, + ARRAY_SIZE(wm5102_aec_loopback_texts), + wm5102_aec_loopback_texts, + wm5102_aec_loopback_values); + +static const struct snd_kcontrol_new wm5102_aec_loopback_mux = + SOC_DAPM_VALUE_ENUM("AEC Loopback", wm5102_aec_loopback); + static const struct snd_soc_dapm_widget wm5102_dapm_widgets[] = { SND_SOC_DAPM_SUPPLY("SYSCLK", ARIZONA_SYSTEM_CLOCK_1, ARIZONA_SYSCLK_ENA_SHIFT, 0, NULL, 0), @@ -435,6 +456,9 @@ SND_SOC_DAPM_AIF_IN("AIF3RX1", NULL, 0, SND_SOC_DAPM_AIF_IN("AIF3RX2", NULL, 0, ARIZONA_AIF3_RX_ENABLES, ARIZONA_AIF3RX2_ENA_SHIFT, 0), +SND_SOC_DAPM_VALUE_MUX("AEC Loopback", ARIZONA_DAC_AEC_CONTROL_1, + ARIZONA_AEC_LOOPBACK_ENA, 0, &wm5102_aec_loopback_mux), + SND_SOC_DAPM_PGA_E("OUT1L", ARIZONA_OUTPUT_ENABLES_1, ARIZONA_OUT1L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev, SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), @@ -532,6 +556,7 @@ SND_SOC_DAPM_OUTPUT("SPKDAT1R"), { name, "Noise Generator", "Noise Generator" }, \ { name, "Tone Generator 1", "Tone Generator 1" }, \ { name, "Tone Generator 2", "Tone Generator 2" }, \ + { name, "AEC", "AEC Loopback" }, \ { name, "IN1L", "IN1L PGA" }, \ { name, "IN1R", "IN1R PGA" }, \ { name, "IN2L", "IN2L PGA" }, \ @@ -692,21 +717,30 @@ static const struct snd_soc_dapm_route wm5102_dapm_routes[] = { ARIZONA_MIXER_ROUTES("ASRC2L", "ASRC2L"), ARIZONA_MIXER_ROUTES("ASRC2R", "ASRC2R"), + { "AEC Loopback", "HPOUT1L", "OUT1L" }, + { "AEC Loopback", "HPOUT1R", "OUT1R" }, { "HPOUT1L", NULL, "OUT1L" }, { "HPOUT1R", NULL, "OUT1R" }, + { "AEC Loopback", "HPOUT2L", "OUT2L" }, + { "AEC Loopback", "HPOUT2R", "OUT2R" }, { "HPOUT2L", NULL, "OUT2L" }, { "HPOUT2R", NULL, "OUT2R" }, + { "AEC Loopback", "EPOUT", "OUT3L" }, { "EPOUTN", NULL, "OUT3L" }, { "EPOUTP", NULL, "OUT3L" }, + { "AEC Loopback", "SPKOUTL", "OUT4L" }, { "SPKOUTLN", NULL, "OUT4L" }, { "SPKOUTLP", NULL, "OUT4L" }, + { "AEC Loopback", "SPKOUTR", "OUT4R" }, { "SPKOUTRN", NULL, "OUT4R" }, { "SPKOUTRP", NULL, "OUT4R" }, + { "AEC Loopback", "SPKDAT1L", "OUT5L" }, + { "AEC Loopback", "SPKDAT1R", "OUT5R" }, { "SPKDAT1L", NULL, "OUT5L" }, { "SPKDAT1R", NULL, "OUT5R" }, }; -- cgit v1.2.3 From 45a690f6bcd5506d9988d0d069811ac9380750ad Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 15 Aug 2012 19:20:54 +0100 Subject: ASoC: wm8994: Add bytes controls for DRC If DRC coefficients are not configured via platform data then add bytes controls for them instead so they can be configured by applications. This is the normal means of controlling things like this for newer systems, we maintain compatibility with platform data to avoid disruption to existing systems. Signed-off-by: Mark Brown --- sound/soc/codecs/wm8994.c | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index 02080da8b451..353612eec8bf 100644 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c @@ -671,6 +671,18 @@ SOC_SINGLE_TLV("AIF2 EQ5 Volume", WM8994_AIF2_EQ_GAINS_2, 6, 31, 0, eq_tlv), }; +static const struct snd_kcontrol_new wm8994_drc_controls[] = { +SND_SOC_BYTES_MASK("AIF1.1 DRC", WM8994_AIF1_DRC1_1, 5, + WM8994_AIF1DAC1_DRC_ENA | WM8994_AIF1ADC1L_DRC_ENA | + WM8994_AIF1ADC1R_DRC_ENA), +SND_SOC_BYTES_MASK("AIF1.2 DRC", WM8994_AIF1_DRC2_1, 5, + WM8994_AIF1DAC2_DRC_ENA | WM8994_AIF1ADC2L_DRC_ENA | + WM8994_AIF1ADC2R_DRC_ENA), +SND_SOC_BYTES_MASK("AIF2 DRC", WM8994_AIF2_DRC_1, 5, + WM8994_AIF2DAC_DRC_ENA | WM8994_AIF2ADCL_DRC_ENA | + WM8994_AIF2ADCR_DRC_ENA), +}; + static const char *wm8958_ng_text[] = { "30ms", "125ms", "250ms", "500ms", }; @@ -3166,14 +3178,19 @@ static void wm8994_handle_pdata(struct wm8994_priv *wm8994) ret = snd_soc_add_codec_controls(wm8994->hubs.codec, controls, ARRAY_SIZE(controls)); - if (ret != 0) - dev_err(wm8994->hubs.codec->dev, - "Failed to add DRC mode controls: %d\n", ret); - for (i = 0; i < WM8994_NUM_DRC; i++) wm8994_set_drc(codec, i); + } else { + ret = snd_soc_add_codec_controls(wm8994->hubs.codec, + wm8994_drc_controls, + ARRAY_SIZE(wm8994_drc_controls)); } + if (ret != 0) + dev_err(wm8994->hubs.codec->dev, + "Failed to add DRC mode controls: %d\n", ret); + + dev_dbg(codec->dev, "%d ReTune Mobile configurations\n", pdata->num_retune_mobile_cfgs); -- cgit v1.2.3 From d14a13d3d94bae80c3f44ff35a3c76192fb3408c Mon Sep 17 00:00:00 2001 From: Scott Jiang Date: Fri, 10 Aug 2012 18:06:08 -0400 Subject: ASoC: bf5xx-ad1836: convert to use snd_soc_register_card Cpu dai and codec name are passed in through platform data. Signed-off-by: Scott Jiang Signed-off-by: Mark Brown --- sound/soc/blackfin/bf5xx-ad1836.c | 73 ++++++++++++++++++++------------------- 1 file changed, 37 insertions(+), 36 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/blackfin/bf5xx-ad1836.c b/sound/soc/blackfin/bf5xx-ad1836.c index d542d4063771..16b9c9efd19a 100644 --- a/sound/soc/blackfin/bf5xx-ad1836.c +++ b/sound/soc/blackfin/bf5xx-ad1836.c @@ -59,62 +59,63 @@ static struct snd_soc_ops bf5xx_ad1836_ops = { #define BF5XX_AD1836_DAIFMT (SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_IB_IF | \ SND_SOC_DAIFMT_CBM_CFM) -static struct snd_soc_dai_link bf5xx_ad1836_dai[] = { - { - .name = "ad1836", - .stream_name = "AD1836", - .cpu_dai_name = "bfin-tdm.0", - .codec_dai_name = "ad1836-hifi", - .platform_name = "bfin-tdm-pcm-audio", - .codec_name = "spi0.4", - .ops = &bf5xx_ad1836_ops, - .dai_fmt = BF5XX_AD1836_DAIFMT, - }, - { - .name = "ad1836", - .stream_name = "AD1836", - .cpu_dai_name = "bfin-tdm.1", - .codec_dai_name = "ad1836-hifi", - .platform_name = "bfin-tdm-pcm-audio", - .codec_name = "spi0.4", - .ops = &bf5xx_ad1836_ops, - .dai_fmt = BF5XX_AD1836_DAIFMT, - }, +static struct snd_soc_dai_link bf5xx_ad1836_dai = { + .name = "ad1836", + .stream_name = "AD1836", + .codec_dai_name = "ad1836-hifi", + .platform_name = "bfin-tdm-pcm-audio", + .ops = &bf5xx_ad1836_ops, + .dai_fmt = BF5XX_AD1836_DAIFMT, }; static struct snd_soc_card bf5xx_ad1836 = { .name = "bfin-ad1836", .owner = THIS_MODULE, - .dai_link = &bf5xx_ad1836_dai[CONFIG_SND_BF5XX_SPORT_NUM], + .dai_link = &bf5xx_ad1836_dai, .num_links = 1, }; -static struct platform_device *bfxx_ad1836_snd_device; - -static int __init bf5xx_ad1836_init(void) +static __devinit int bf5xx_ad1836_driver_probe(struct platform_device *pdev) { + struct snd_soc_card *card = &bf5xx_ad1836; + const char **link_name; int ret; - bfxx_ad1836_snd_device = platform_device_alloc("soc-audio", -1); - if (!bfxx_ad1836_snd_device) - return -ENOMEM; + link_name = pdev->dev.platform_data; + if (!link_name) { + dev_err(&pdev->dev, "No platform data supplied\n"); + return -EINVAL; + } + bf5xx_ad1836_dai.cpu_dai_name = link_name[0]; + bf5xx_ad1836_dai.codec_name = link_name[1]; - platform_set_drvdata(bfxx_ad1836_snd_device, &bf5xx_ad1836); - ret = platform_device_add(bfxx_ad1836_snd_device); + card->dev = &pdev->dev; + platform_set_drvdata(pdev, card); + ret = snd_soc_register_card(card); if (ret) - platform_device_put(bfxx_ad1836_snd_device); - + dev_err(&pdev->dev, "Failed to register card\n"); return ret; } -static void __exit bf5xx_ad1836_exit(void) +static int __devexit bf5xx_ad1836_driver_remove(struct platform_device *pdev) { - platform_device_unregister(bfxx_ad1836_snd_device); + struct snd_soc_card *card = platform_get_drvdata(pdev); + + snd_soc_unregister_card(card); + return 0; } -module_init(bf5xx_ad1836_init); -module_exit(bf5xx_ad1836_exit); +static struct platform_driver bf5xx_ad1836_driver = { + .driver = { + .name = "bfin-snd-ad1836", + .owner = THIS_MODULE, + .pm = &snd_soc_pm_ops, + }, + .probe = bf5xx_ad1836_driver_probe, + .remove = __devexit_p(bf5xx_ad1836_driver_remove), +}; +module_platform_driver(bf5xx_ad1836_driver); /* Module information */ MODULE_AUTHOR("Barry Song"); -- cgit v1.2.3 From 1245b7005de02d5bfa0c321df925f5b6c83c99e1 Mon Sep 17 00:00:00 2001 From: Namarta Kohli Date: Thu, 16 Aug 2012 17:10:41 +0530 Subject: ASoC: add compress stream support This patch adds the support to parse the compress dai's and then also adds the soc-compress.c file while handles the compress stream operations, mostly analogus to what is done in the soc-pcm.c and aditional handling of the compress opertaions Signed-off-by: Namarta Kohli Signed-off-by: Ramesh Babu K V Signed-off-by: Vinod Koul Signed-off-by: Mark Brown --- sound/soc/Kconfig | 1 + sound/soc/Makefile | 2 +- sound/soc/soc-compress.c | 295 +++++++++++++++++++++++++++++++++++++++++++++++ sound/soc/soc-core.c | 57 +++++---- 4 files changed, 331 insertions(+), 24 deletions(-) create mode 100644 sound/soc/soc-compress.c (limited to 'sound/soc') diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig index c5de0a84566f..c24de902f5f5 100644 --- a/sound/soc/Kconfig +++ b/sound/soc/Kconfig @@ -9,6 +9,7 @@ menuconfig SND_SOC select SND_JACK if INPUT=y || INPUT=SND select REGMAP_I2C if I2C select REGMAP_SPI if SPI_MASTER + select SND_COMPRESS_OFFLOAD ---help--- If you want ASoC support, you should say Y here and also to the diff --git a/sound/soc/Makefile b/sound/soc/Makefile index 00a555a743b6..c1264007b4ee 100644 --- a/sound/soc/Makefile +++ b/sound/soc/Makefile @@ -1,5 +1,5 @@ snd-soc-core-objs := soc-core.o soc-dapm.o soc-jack.o soc-cache.o soc-utils.o -snd-soc-core-objs += soc-pcm.o soc-io.o +snd-soc-core-objs += soc-pcm.o soc-compress.o soc-io.o snd-soc-dmaengine-pcm-objs := soc-dmaengine-pcm.o obj-$(CONFIG_SND_SOC_DMAENGINE_PCM) += snd-soc-dmaengine-pcm.o diff --git a/sound/soc/soc-compress.c b/sound/soc/soc-compress.c new file mode 100644 index 000000000000..88d85badd932 --- /dev/null +++ b/sound/soc/soc-compress.c @@ -0,0 +1,295 @@ +/* + * soc-compress.c -- ALSA SoC Compress + * + * Copyright (C) 2012 Intel Corp. + * + * Authors: Namarta Kohli + * Ramesh Babu K V + * Vinod Koul + * + * 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 + +static int soc_compr_open(struct snd_compr_stream *cstream) +{ + struct snd_soc_pcm_runtime *rtd = cstream->private_data; + struct snd_soc_platform *platform = rtd->platform; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + struct snd_soc_dai *codec_dai = rtd->codec_dai; + int ret = 0; + + if (platform->driver->compr_ops && platform->driver->compr_ops->open) { + ret = platform->driver->compr_ops->open(cstream); + if (ret < 0) { + pr_err("compress asoc: can't open platform %s\n", platform->name); + goto out; + } + } + + if (rtd->dai_link->compr_ops && rtd->dai_link->compr_ops->startup) { + ret = rtd->dai_link->compr_ops->startup(cstream); + if (ret < 0) { + pr_err("compress asoc: %s startup failed\n", rtd->dai_link->name); + goto machine_err; + } + } + + if (cstream->direction == SND_COMPRESS_PLAYBACK) { + cpu_dai->playback_active++; + codec_dai->playback_active++; + } else { + cpu_dai->capture_active++; + codec_dai->capture_active++; + } + + cpu_dai->active++; + codec_dai->active++; + rtd->codec->active++; + + return 0; + +machine_err: + if (platform->driver->compr_ops && platform->driver->compr_ops->free) + platform->driver->compr_ops->free(cstream); +out: + return ret; +} + +static int soc_compr_free(struct snd_compr_stream *cstream) +{ + struct snd_soc_pcm_runtime *rtd = cstream->private_data; + struct snd_soc_platform *platform = rtd->platform; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + struct snd_soc_dai *codec_dai = rtd->codec_dai; + struct snd_soc_codec *codec = rtd->codec; + + if (cstream->direction == SND_COMPRESS_PLAYBACK) { + cpu_dai->playback_active--; + codec_dai->playback_active--; + } else { + cpu_dai->capture_active--; + codec_dai->capture_active--; + } + + snd_soc_dai_digital_mute(codec_dai, 1); + + cpu_dai->active--; + codec_dai->active--; + codec->active--; + + if (!cpu_dai->active) + cpu_dai->rate = 0; + + if (!codec_dai->active) + codec_dai->rate = 0; + + + if (rtd->dai_link->compr_ops && rtd->dai_link->compr_ops->shutdown) + rtd->dai_link->compr_ops->shutdown(cstream); + + if (platform->driver->compr_ops && platform->driver->compr_ops->free) + platform->driver->compr_ops->free(cstream); + cpu_dai->runtime = NULL; + + if (cstream->direction == SND_COMPRESS_PLAYBACK) { + if (!rtd->pmdown_time || codec->ignore_pmdown_time || + rtd->dai_link->ignore_pmdown_time) { + snd_soc_dapm_stream_event(rtd, + SNDRV_PCM_STREAM_PLAYBACK, + SND_SOC_DAPM_STREAM_STOP); + } else + codec_dai->pop_wait = 1; + schedule_delayed_work(&rtd->delayed_work, + msecs_to_jiffies(rtd->pmdown_time)); + } else { + /* capture streams can be powered down now */ + snd_soc_dapm_stream_event(rtd, + SNDRV_PCM_STREAM_CAPTURE, + SND_SOC_DAPM_STREAM_STOP); + } + + return 0; +} + +static int soc_compr_trigger(struct snd_compr_stream *cstream, int cmd) +{ + + struct snd_soc_pcm_runtime *rtd = cstream->private_data; + struct snd_soc_platform *platform = rtd->platform; + struct snd_soc_dai *codec_dai = rtd->codec_dai; + int ret = 0; + + if (platform->driver->compr_ops && platform->driver->compr_ops->trigger) { + ret = platform->driver->compr_ops->trigger(cstream, cmd); + if (ret < 0) + return ret; + } + + if (cmd == SNDRV_PCM_TRIGGER_START) + snd_soc_dai_digital_mute(codec_dai, 0); + else if (cmd == SNDRV_PCM_TRIGGER_STOP) + snd_soc_dai_digital_mute(codec_dai, 1); + + return ret; +} + +static int soc_compr_set_params(struct snd_compr_stream *cstream, + struct snd_compr_params *params) +{ + struct snd_soc_pcm_runtime *rtd = cstream->private_data; + struct snd_soc_platform *platform = rtd->platform; + struct snd_soc_dai *codec_dai = rtd->codec_dai; + int ret = 0; + + /* first we call set_params for the platform driver + * this should configure the soc side + * if the machine has compressed ops then we call that as well + * expectation is that platform and machine will configure everything + * for this compress path, like configuring pcm port for codec + */ + if (platform->driver->compr_ops && platform->driver->compr_ops->set_params) { + ret = platform->driver->compr_ops->set_params(cstream, params); + if (ret < 0) + return ret; + } + + if (rtd->dai_link->compr_ops && rtd->dai_link->compr_ops->set_params) { + ret = rtd->dai_link->compr_ops->set_params(cstream); + if (ret < 0) + return ret; + } + + snd_soc_dapm_stream_event(rtd, SNDRV_PCM_STREAM_PLAYBACK, + SND_SOC_DAPM_STREAM_START); + + return ret; +} + +static int soc_compr_get_params(struct snd_compr_stream *cstream, + struct snd_codec *params) +{ + struct snd_soc_pcm_runtime *rtd = cstream->private_data; + struct snd_soc_platform *platform = rtd->platform; + int ret = 0; + + if (platform->driver->compr_ops && platform->driver->compr_ops->get_params) + ret = platform->driver->compr_ops->get_params(cstream, params); + + return ret; +} + +static int soc_compr_get_caps(struct snd_compr_stream *cstream, + struct snd_compr_caps *caps) +{ + struct snd_soc_pcm_runtime *rtd = cstream->private_data; + struct snd_soc_platform *platform = rtd->platform; + int ret = 0; + + if (platform->driver->compr_ops && platform->driver->compr_ops->get_caps) + ret = platform->driver->compr_ops->get_caps(cstream, caps); + + return ret; +} + +static int soc_compr_get_codec_caps(struct snd_compr_stream *cstream, + struct snd_compr_codec_caps *codec) +{ + struct snd_soc_pcm_runtime *rtd = cstream->private_data; + struct snd_soc_platform *platform = rtd->platform; + int ret = 0; + + if (platform->driver->compr_ops && platform->driver->compr_ops->get_codec_caps) + ret = platform->driver->compr_ops->get_codec_caps(cstream, codec); + + return ret; +} + +static int soc_compr_ack(struct snd_compr_stream *cstream, size_t bytes) +{ + struct snd_soc_pcm_runtime *rtd = cstream->private_data; + struct snd_soc_platform *platform = rtd->platform; + int ret = 0; + + if (platform->driver->compr_ops && platform->driver->compr_ops->ack) + ret = platform->driver->compr_ops->ack(cstream, bytes); + + return ret; +} + +static int soc_compr_pointer(struct snd_compr_stream *cstream, + struct snd_compr_tstamp *tstamp) +{ + struct snd_soc_pcm_runtime *rtd = cstream->private_data; + struct snd_soc_platform *platform = rtd->platform; + + if (platform->driver->compr_ops && platform->driver->compr_ops->pointer) + platform->driver->compr_ops->pointer(cstream, tstamp); + + return 0; +} + +/* ASoC Compress operations */ +static struct snd_compr_ops soc_compr_ops = { + .open = soc_compr_open, + .free = soc_compr_free, + .set_params = soc_compr_set_params, + .get_params = soc_compr_get_params, + .trigger = soc_compr_trigger, + .pointer = soc_compr_pointer, + .ack = soc_compr_ack, + .get_caps = soc_compr_get_caps, + .get_codec_caps = soc_compr_get_codec_caps +}; + +/* create a new compress */ +int soc_new_compress(struct snd_soc_pcm_runtime *rtd, int num) +{ + struct snd_soc_codec *codec = rtd->codec; + struct snd_soc_dai *codec_dai = rtd->codec_dai; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + struct snd_compr *compr; + char new_name[64]; + int ret = 0, direction = 0; + + /* check client and interface hw capabilities */ + snprintf(new_name, sizeof(new_name), "%s %s-%d", + rtd->dai_link->stream_name, codec_dai->name, num); + direction = SND_COMPRESS_PLAYBACK; + compr = kzalloc(sizeof(*compr), GFP_KERNEL); + if (compr == NULL) { + snd_printk(KERN_ERR "Cannot allocate compr\n"); + return -ENOMEM; + } + + compr->ops = &soc_compr_ops; + mutex_init(&compr->lock); + ret = snd_compress_new(rtd->card->snd_card, num, direction, compr); + if (ret < 0) { + pr_err("compress asoc: can't create compress for codec %s\n", + codec->name); + kfree(compr); + return ret; + } + + rtd->compr = compr; + compr->private_data = rtd; + + printk(KERN_INFO "compress asoc: %s <-> %s mapping ok\n", codec_dai->name, + cpu_dai->name); + return ret; +} diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index f585d0239551..c7a00fd8cc66 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -1388,37 +1388,48 @@ static int soc_probe_link_dais(struct snd_soc_card *card, int num, int order) if (ret < 0) pr_warn("asoc: failed to add pmdown_time sysfs:%d\n", ret); - if (!dai_link->params) { - /* create the pcm */ - ret = soc_new_pcm(rtd, num); + if (cpu_dai->driver->compress_dai) { + /*create compress_device"*/ + ret = soc_new_compress(rtd, num); if (ret < 0) { - pr_err("asoc: can't create pcm %s :%d\n", - dai_link->stream_name, ret); + pr_err("asoc: can't create compress %s\n", + dai_link->stream_name); return ret; } } else { - /* link the DAI widgets */ - play_w = codec_dai->playback_widget; - capture_w = cpu_dai->capture_widget; - if (play_w && capture_w) { - ret = snd_soc_dapm_new_pcm(card, dai_link->params, - capture_w, play_w); - if (ret != 0) { - dev_err(card->dev, "Can't link %s to %s: %d\n", - play_w->name, capture_w->name, ret); + + if (!dai_link->params) { + /* create the pcm */ + ret = soc_new_pcm(rtd, num); + if (ret < 0) { + pr_err("asoc: can't create pcm %s :%d\n", + dai_link->stream_name, ret); return ret; } - } + } else { + /* link the DAI widgets */ + play_w = codec_dai->playback_widget; + capture_w = cpu_dai->capture_widget; + if (play_w && capture_w) { + ret = snd_soc_dapm_new_pcm(card, dai_link->params, + capture_w, play_w); + if (ret != 0) { + dev_err(card->dev, "Can't link %s to %s: %d\n", + play_w->name, capture_w->name, ret); + return ret; + } + } - play_w = cpu_dai->playback_widget; - capture_w = codec_dai->capture_widget; - if (play_w && capture_w) { - ret = snd_soc_dapm_new_pcm(card, dai_link->params, + play_w = cpu_dai->playback_widget; + capture_w = codec_dai->capture_widget; + if (play_w && capture_w) { + ret = snd_soc_dapm_new_pcm(card, dai_link->params, capture_w, play_w); - if (ret != 0) { - dev_err(card->dev, "Can't link %s to %s: %d\n", - play_w->name, capture_w->name, ret); - return ret; + if (ret != 0) { + dev_err(card->dev, "Can't link %s to %s: %d\n", + play_w->name, capture_w->name, ret); + return ret; + } } } } -- cgit v1.2.3 From c514a9119a982a6c7a9fd29ee62c0ba8a8e4c7d1 Mon Sep 17 00:00:00 2001 From: Vinod Koul Date: Thu, 16 Aug 2012 17:10:42 +0530 Subject: ASoC: mid-x86 - add support for compressed streams Signed-off-by: Namarta Kohli Signed-off-by: Ramesh Babu K V Signed-off-by: Vinod Koul Signed-off-by: Mark Brown --- sound/soc/mid-x86/mfld_machine.c | 9 ++ sound/soc/mid-x86/sst_dsp.h | 134 +++++++++++++++++++++++++ sound/soc/mid-x86/sst_platform.c | 204 ++++++++++++++++++++++++++++++++++++++- sound/soc/mid-x86/sst_platform.h | 26 ++++- 4 files changed, 371 insertions(+), 2 deletions(-) create mode 100644 sound/soc/mid-x86/sst_dsp.h (limited to 'sound/soc') diff --git a/sound/soc/mid-x86/mfld_machine.c b/sound/soc/mid-x86/mfld_machine.c index 2937e54da49e..2cc7782714b5 100644 --- a/sound/soc/mid-x86/mfld_machine.c +++ b/sound/soc/mid-x86/mfld_machine.c @@ -318,6 +318,15 @@ static struct snd_soc_dai_link mfld_msic_dailink[] = { .platform_name = "sst-platform", .init = NULL, }, + { + .name = "Medfield Compress", + .stream_name = "Speaker", + .cpu_dai_name = "Compress-cpu-dai", + .codec_dai_name = "SN95031 Speaker", + .codec_name = "sn95031", + .platform_name = "sst-platform", + .init = NULL, + }, }; /* SoC card */ diff --git a/sound/soc/mid-x86/sst_dsp.h b/sound/soc/mid-x86/sst_dsp.h new file mode 100644 index 000000000000..0fce1de284ff --- /dev/null +++ b/sound/soc/mid-x86/sst_dsp.h @@ -0,0 +1,134 @@ +#ifndef __SST_DSP_H__ +#define __SST_DSP_H__ +/* + * sst_dsp.h - Intel SST Driver for audio engine + * + * Copyright (C) 2008-12 Intel Corporation + * Authors: Vinod Koul + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + * 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; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + */ + +enum sst_codec_types { + /* AUDIO/MUSIC CODEC Type Definitions */ + SST_CODEC_TYPE_UNKNOWN = 0, + SST_CODEC_TYPE_PCM, /* Pass through Audio codec */ + SST_CODEC_TYPE_MP3, + SST_CODEC_TYPE_MP24, + SST_CODEC_TYPE_AAC, + SST_CODEC_TYPE_AACP, + SST_CODEC_TYPE_eAACP, +}; + +enum stream_type { + SST_STREAM_TYPE_NONE = 0, + SST_STREAM_TYPE_MUSIC = 1, +}; + +struct snd_pcm_params { + u16 codec; /* codec type */ + u8 num_chan; /* 1=Mono, 2=Stereo */ + u8 pcm_wd_sz; /* 16/24 - bit*/ + u32 reserved; /* Bitrate in bits per second */ + u32 sfreq; /* Sampling rate in Hz */ + u8 use_offload_path; + u8 reserved2; + u16 reserved3; + u8 channel_map[8]; +} __packed; + +/* MP3 Music Parameters Message */ +struct snd_mp3_params { + u16 codec; + u8 num_chan; /* 1=Mono, 2=Stereo */ + u8 pcm_wd_sz; /* 16/24 - bit*/ + u8 crc_check; /* crc_check - disable (0) or enable (1) */ + u8 reserved1; /* unused*/ + u16 reserved2; /* Unused */ +} __packed; + +#define AAC_BIT_STREAM_ADTS 0 +#define AAC_BIT_STREAM_ADIF 1 +#define AAC_BIT_STREAM_RAW 2 + +/* AAC Music Parameters Message */ +struct snd_aac_params { + u16 codec; + u8 num_chan; /* 1=Mono, 2=Stereo*/ + u8 pcm_wd_sz; /* 16/24 - bit*/ + u8 bdownsample; /*SBR downsampling 0 - disable 1 -enabled AAC+ only */ + u8 bs_format; /* input bit stream format adts=0, adif=1, raw=2 */ + u16 reser2; + u32 externalsr; /*sampling rate of basic AAC raw bit stream*/ + u8 sbr_signalling;/*disable/enable/set automode the SBR tool.AAC+*/ + u8 reser1; + u16 reser3; +} __packed; + +/* WMA Music Parameters Message */ +struct snd_wma_params { + u16 codec; + u8 num_chan; /* 1=Mono, 2=Stereo */ + u8 pcm_wd_sz; /* 16/24 - bit*/ + u32 brate; /* Use the hard coded value. */ + u32 sfreq; /* Sampling freq eg. 8000, 441000, 48000 */ + u32 channel_mask; /* Channel Mask */ + u16 format_tag; /* Format Tag */ + u16 block_align; /* packet size */ + u16 wma_encode_opt;/* Encoder option */ + u8 op_align; /* op align 0- 16 bit, 1- MSB, 2 LSB */ + u8 reserved; /* reserved */ +} __packed; + +/* Codec params struture */ +union snd_sst_codec_params { + struct snd_pcm_params pcm_params; + struct snd_mp3_params mp3_params; + struct snd_aac_params aac_params; + struct snd_wma_params wma_params; +} __packed; + +/* Address and size info of a frame buffer */ +struct sst_address_info { + u32 addr; /* Address at IA */ + u32 size; /* Size of the buffer */ +}; + +struct snd_sst_alloc_params_ext { + struct sst_address_info ring_buf_info[8]; + u8 sg_count; + u8 reserved; + u16 reserved2; + u32 frag_size; /*Number of samples after which period elapsed + message is sent valid only if path = 0*/ +} __packed; + +struct snd_sst_stream_params { + union snd_sst_codec_params uc; +} __packed; + +struct snd_sst_params { + u32 stream_id; + u8 codec; + u8 ops; + u8 stream_type; + u8 device_type; + struct snd_sst_stream_params sparams; + struct snd_sst_alloc_params_ext aparams; +}; + +#endif /* __SST_DSP_H__ */ diff --git a/sound/soc/mid-x86/sst_platform.c b/sound/soc/mid-x86/sst_platform.c index d34563b12c3b..a263cbed8624 100644 --- a/sound/soc/mid-x86/sst_platform.c +++ b/sound/soc/mid-x86/sst_platform.c @@ -1,7 +1,7 @@ /* * sst_platform.c - Intel MID Platform driver * - * Copyright (C) 2010 Intel Corp + * Copyright (C) 2010-2012 Intel Corp * Author: Vinod Koul * Author: Harsha Priya * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -32,6 +32,7 @@ #include #include #include +#include #include "sst_platform.h" static struct sst_device *sst; @@ -152,6 +153,16 @@ static struct snd_soc_dai_driver sst_platform_dai[] = { .formats = SNDRV_PCM_FMTBIT_S24_LE, }, }, +{ + .name = "Compress-cpu-dai", + .compress_dai = 1, + .playback = { + .channels_min = SST_STEREO, + .channels_max = SST_STEREO, + .rates = SNDRV_PCM_RATE_44100|SNDRV_PCM_RATE_48000, + .formats = SNDRV_PCM_FMTBIT_S16_LE, + }, +}, }; /* helper functions */ @@ -463,8 +474,199 @@ static int sst_pcm_new(struct snd_soc_pcm_runtime *rtd) } return retval; } + +/* compress stream operations */ +static void sst_compr_fragment_elapsed(void *arg) +{ + struct snd_compr_stream *cstream = (struct snd_compr_stream *)arg; + + pr_debug("fragment elapsed by driver\n"); + if (cstream) + snd_compr_fragment_elapsed(cstream); +} + +static int sst_platform_compr_open(struct snd_compr_stream *cstream) +{ + + int ret_val = 0; + struct snd_compr_runtime *runtime = cstream->runtime; + struct sst_runtime_stream *stream; + + stream = kzalloc(sizeof(*stream), GFP_KERNEL); + if (!stream) + return -ENOMEM; + + spin_lock_init(&stream->status_lock); + + /* get the sst ops */ + if (!sst || !try_module_get(sst->dev->driver->owner)) { + pr_err("no device available to run\n"); + ret_val = -ENODEV; + goto out_ops; + } + stream->compr_ops = sst->compr_ops; + + stream->id = 0; + sst_set_stream_status(stream, SST_PLATFORM_INIT); + runtime->private_data = stream; + return 0; +out_ops: + kfree(stream); + return ret_val; +} + +static int sst_platform_compr_free(struct snd_compr_stream *cstream) +{ + struct sst_runtime_stream *stream; + int ret_val = 0, str_id; + + stream = cstream->runtime->private_data; + /*need to check*/ + str_id = stream->id; + if (str_id) + ret_val = stream->compr_ops->close(str_id); + module_put(sst->dev->driver->owner); + kfree(stream); + pr_debug("%s: %d\n", __func__, ret_val); + return 0; +} + +static int sst_platform_compr_set_params(struct snd_compr_stream *cstream, + struct snd_compr_params *params) +{ + struct sst_runtime_stream *stream; + int retval; + struct snd_sst_params str_params; + struct sst_compress_cb cb; + + stream = cstream->runtime->private_data; + /* construct fw structure for this*/ + memset(&str_params, 0, sizeof(str_params)); + + str_params.ops = STREAM_OPS_PLAYBACK; + str_params.stream_type = SST_STREAM_TYPE_MUSIC; + str_params.device_type = SND_SST_DEVICE_COMPRESS; + + switch (params->codec.id) { + case SND_AUDIOCODEC_MP3: { + str_params.codec = SST_CODEC_TYPE_MP3; + str_params.sparams.uc.mp3_params.codec = SST_CODEC_TYPE_MP3; + str_params.sparams.uc.mp3_params.num_chan = params->codec.ch_in; + str_params.sparams.uc.mp3_params.pcm_wd_sz = 16; + break; + } + + case SND_AUDIOCODEC_AAC: { + str_params.codec = SST_CODEC_TYPE_AAC; + str_params.sparams.uc.aac_params.codec = SST_CODEC_TYPE_AAC; + str_params.sparams.uc.aac_params.num_chan = params->codec.ch_in; + str_params.sparams.uc.aac_params.pcm_wd_sz = 16; + if (params->codec.format == SND_AUDIOSTREAMFORMAT_MP4ADTS) + str_params.sparams.uc.aac_params.bs_format = + AAC_BIT_STREAM_ADTS; + else if (params->codec.format == SND_AUDIOSTREAMFORMAT_RAW) + str_params.sparams.uc.aac_params.bs_format = + AAC_BIT_STREAM_RAW; + else { + pr_err("Undefined format%d\n", params->codec.format); + return -EINVAL; + } + str_params.sparams.uc.aac_params.externalsr = + params->codec.sample_rate; + break; + } + + default: + pr_err("codec not supported, id =%d\n", params->codec.id); + return -EINVAL; + } + + str_params.aparams.ring_buf_info[0].addr = + virt_to_phys(cstream->runtime->buffer); + str_params.aparams.ring_buf_info[0].size = + cstream->runtime->buffer_size; + str_params.aparams.sg_count = 1; + str_params.aparams.frag_size = cstream->runtime->fragment_size; + + cb.param = cstream; + cb.compr_cb = sst_compr_fragment_elapsed; + + retval = stream->compr_ops->open(&str_params, &cb); + if (retval < 0) { + pr_err("stream allocation failed %d\n", retval); + return retval; + } + + stream->id = retval; + return 0; +} + +static int sst_platform_compr_trigger(struct snd_compr_stream *cstream, int cmd) +{ + struct sst_runtime_stream *stream = + cstream->runtime->private_data; + + return stream->compr_ops->control(cmd, stream->id); +} + +static int sst_platform_compr_pointer(struct snd_compr_stream *cstream, + struct snd_compr_tstamp *tstamp) +{ + struct sst_runtime_stream *stream; + + stream = cstream->runtime->private_data; + stream->compr_ops->tstamp(stream->id, tstamp); + tstamp->byte_offset = tstamp->copied_total % + (u32)cstream->runtime->buffer_size; + pr_debug("calc bytes offset/copied bytes as %d\n", tstamp->byte_offset); + return 0; +} + +static int sst_platform_compr_ack(struct snd_compr_stream *cstream, + size_t bytes) +{ + struct sst_runtime_stream *stream; + + stream = cstream->runtime->private_data; + stream->compr_ops->ack(stream->id, (unsigned long)bytes); + stream->bytes_written += bytes; + + return 0; +} + +static int sst_platform_compr_get_caps(struct snd_compr_stream *cstream, + struct snd_compr_caps *caps) +{ + struct sst_runtime_stream *stream = + cstream->runtime->private_data; + + return stream->compr_ops->get_caps(caps); +} + +static int sst_platform_compr_get_codec_caps(struct snd_compr_stream *cstream, + struct snd_compr_codec_caps *codec) +{ + struct sst_runtime_stream *stream = + cstream->runtime->private_data; + + return stream->compr_ops->get_codec_caps(codec); +} + +static struct snd_compr_ops sst_platform_compr_ops = { + + .open = sst_platform_compr_open, + .free = sst_platform_compr_free, + .set_params = sst_platform_compr_set_params, + .trigger = sst_platform_compr_trigger, + .pointer = sst_platform_compr_pointer, + .ack = sst_platform_compr_ack, + .get_caps = sst_platform_compr_get_caps, + .get_codec_caps = sst_platform_compr_get_codec_caps, +}; + static struct snd_soc_platform_driver sst_soc_platform_drv = { .ops = &sst_platform_ops, + .compr_ops = &sst_platform_compr_ops, .pcm_new = sst_pcm_new, .pcm_free = sst_pcm_free, }; diff --git a/sound/soc/mid-x86/sst_platform.h b/sound/soc/mid-x86/sst_platform.h index f04f4f72daa0..d61c5d514ffa 100644 --- a/sound/soc/mid-x86/sst_platform.h +++ b/sound/soc/mid-x86/sst_platform.h @@ -27,6 +27,8 @@ #ifndef __SST_PLATFORMDRV_H__ #define __SST_PLATFORMDRV_H__ +#include "sst_dsp.h" + #define SST_MONO 1 #define SST_STEREO 2 #define SST_MAX_CAP 5 @@ -42,7 +44,6 @@ #define SST_MIN_PERIODS 2 #define SST_MAX_PERIODS (1024*2) #define SST_FIFO_SIZE 0 -#define SST_CODEC_TYPE_PCM 1 struct pcm_stream_info { int str_id; @@ -83,6 +84,7 @@ enum sst_audio_device_type { SND_SST_DEVICE_VIBRA, SND_SST_DEVICE_HAPTIC, SND_SST_DEVICE_CAPTURE, + SND_SST_DEVICE_COMPRESS, }; /* PCM Parameters */ @@ -107,6 +109,24 @@ struct sst_stream_params { struct sst_pcm_params sparams; }; +struct sst_compress_cb { + void *param; + void (*compr_cb)(void *param); +}; + +struct compress_sst_ops { + const char *name; + int (*open) (struct snd_sst_params *str_params, + struct sst_compress_cb *cb); + int (*control) (unsigned int cmd, unsigned int str_id); + int (*tstamp) (unsigned int str_id, struct snd_compr_tstamp *tstamp); + int (*ack) (unsigned int str_id, unsigned long bytes); + int (*close) (unsigned int str_id); + int (*get_caps) (struct snd_compr_caps *caps); + int (*get_codec_caps) (struct snd_compr_codec_caps *codec); + +}; + struct sst_ops { int (*open) (struct sst_stream_params *str_param); int (*device_control) (int cmd, void *arg); @@ -115,8 +135,11 @@ struct sst_ops { struct sst_runtime_stream { int stream_status; + unsigned int id; + size_t bytes_written; struct pcm_stream_info stream_info; struct sst_ops *ops; + struct compress_sst_ops *compr_ops; spinlock_t status_lock; }; @@ -124,6 +147,7 @@ struct sst_device { char *name; struct device *dev; struct sst_ops *ops; + struct compress_sst_ops *compr_ops; }; int sst_register_dsp(struct sst_device *sst); -- cgit v1.2.3 From 9d2667a910b8d889a8307bd2534032eb6ed0ea36 Mon Sep 17 00:00:00 2001 From: Vinod Koul Date: Tue, 21 Aug 2012 12:15:02 +0530 Subject: ASoC: compress - fix code alignment Reported-by: Fengguang Wu Signed-off-by: Namarta Kohli Signed-off-by: Vinod Koul Signed-off-by: Mark Brown --- sound/soc/soc-compress.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound/soc') diff --git a/sound/soc/soc-compress.c b/sound/soc/soc-compress.c index 88d85badd932..cc0562d28df2 100644 --- a/sound/soc/soc-compress.c +++ b/sound/soc/soc-compress.c @@ -104,7 +104,7 @@ static int soc_compr_free(struct snd_compr_stream *cstream) if (platform->driver->compr_ops && platform->driver->compr_ops->free) platform->driver->compr_ops->free(cstream); - cpu_dai->runtime = NULL; + cpu_dai->runtime = NULL; if (cstream->direction == SND_COMPRESS_PLAYBACK) { if (!rtd->pmdown_time || codec->ignore_pmdown_time || -- cgit v1.2.3 From 1be437fa53609da9a796a4d213d3fc0a17fc03e0 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Tue, 21 Aug 2012 12:20:22 +0530 Subject: ASoC: soc-compress: Remove unused variable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit codec_dai is not used in the function. sound/soc/soc-compress.c: In function ‘soc_compr_set_params’: sound/soc/soc-compress.c:156:22: warning: unused variable ‘codec_dai’ [-Wunused-variable] Signed-off-by: Sachin Kamat Signed-off-by: Mark Brown --- sound/soc/soc-compress.c | 1 - 1 file changed, 1 deletion(-) (limited to 'sound/soc') diff --git a/sound/soc/soc-compress.c b/sound/soc/soc-compress.c index cc0562d28df2..967d0e173e1b 100644 --- a/sound/soc/soc-compress.c +++ b/sound/soc/soc-compress.c @@ -153,7 +153,6 @@ static int soc_compr_set_params(struct snd_compr_stream *cstream, { struct snd_soc_pcm_runtime *rtd = cstream->private_data; struct snd_soc_platform *platform = rtd->platform; - struct snd_soc_dai *codec_dai = rtd->codec_dai; int ret = 0; /* first we call set_params for the platform driver -- cgit v1.2.3 From 3eadd88a37c330a83bfdee35b3e5837b7c2f7214 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 22 Aug 2012 17:30:13 +0100 Subject: ASoC: wm9712: Provide TLV information for capture boost controls Signed-off-by: Mark Brown --- sound/soc/codecs/wm9712.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/wm9712.c b/sound/soc/codecs/wm9712.c index c9c696ca76f7..6aa1bf8c6897 100644 --- a/sound/soc/codecs/wm9712.c +++ b/sound/soc/codecs/wm9712.c @@ -132,8 +132,9 @@ SOC_SINGLE("Aux Playback Phone Volume", AC97_CD, 4, 7, 1), SOC_SINGLE("Phone Volume", AC97_PHONE, 0, 15, 1), SOC_DOUBLE("Line Capture Volume", AC97_LINE, 8, 0, 31, 1), -SOC_SINGLE("Capture 20dB Boost Switch", AC97_REC_SEL, 14, 1, 0), -SOC_SINGLE("Capture to Phone 20dB Boost Switch", AC97_REC_SEL, 11, 1, 1), +SOC_SINGLE_TLV("Capture Boost Switch", AC97_REC_SEL, 14, 1, 0, boost_tlv), +SOC_SINGLE_TLV("Capture to Phone Boost Switch", AC97_REC_SEL, 11, 1, 1, + boost_tlv), SOC_SINGLE("3D Upper Cut-off Switch", AC97_3D_CONTROL, 5, 1, 1), SOC_SINGLE("3D Lower Cut-off Switch", AC97_3D_CONTROL, 4, 1, 1), -- cgit v1.2.3 From 363947d7d999f74dfd710fb7b7ccad965590f098 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 20 Aug 2012 19:54:24 +0100 Subject: ASoC: wm_hubs: Use explicit casts for converting to signed Should be no behaviour change. Signed-off-by: Mark Brown --- sound/soc/codecs/wm_hubs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/wm_hubs.c b/sound/soc/codecs/wm_hubs.c index 05a02e1b7e92..b340552efe4e 100644 --- a/sound/soc/codecs/wm_hubs.c +++ b/sound/soc/codecs/wm_hubs.c @@ -297,12 +297,12 @@ static void enable_dc_servo(struct snd_soc_codec *codec) hubs->dcs_codes_l, hubs->dcs_codes_r); /* HPOUT1R */ - offset = reg_r; + offset = (s8)reg_r; offset += hubs->dcs_codes_r; dcs_cfg = (u8)offset << WM8993_DCS_DAC_WR_VAL_1_SHIFT; /* HPOUT1L */ - offset = reg_l; + offset = (s8)reg_l; offset += hubs->dcs_codes_l; dcs_cfg |= (u8)offset; -- cgit v1.2.3 From 20bac1f3f470e2d5c87af7b41b10e088e47989bb Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 20 Aug 2012 20:01:51 +0100 Subject: ASoC: wm_hubs: Add trace showing semantics of the DCS update Aids diagnostics. Signed-off-by: Mark Brown --- sound/soc/codecs/wm_hubs.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'sound/soc') diff --git a/sound/soc/codecs/wm_hubs.c b/sound/soc/codecs/wm_hubs.c index b340552efe4e..b2e939a8970e 100644 --- a/sound/soc/codecs/wm_hubs.c +++ b/sound/soc/codecs/wm_hubs.c @@ -298,11 +298,15 @@ static void enable_dc_servo(struct snd_soc_codec *codec) /* HPOUT1R */ offset = (s8)reg_r; + dev_dbg(codec->dev, "DCS right %d->%d\n", offset, + offset + hubs->dcs_codes_r); offset += hubs->dcs_codes_r; dcs_cfg = (u8)offset << WM8993_DCS_DAC_WR_VAL_1_SHIFT; /* HPOUT1L */ offset = (s8)reg_l; + dev_dbg(codec->dev, "DCS left %d->%d\n", offset, + offset + hubs->dcs_codes_l); offset += hubs->dcs_codes_l; dcs_cfg |= (u8)offset; -- cgit v1.2.3 From 02e79476998ba7e62842d20dca898c403ad55c7e Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 21 Aug 2012 17:54:52 +0100 Subject: ASoC: wm_hubs: Allow configuration of MICBIAS power up delay via pdata Sometimes the analogue circuitry connected to the microphone needs some time to settle after power up. Allow systems to configure this delay in the platform data, the driver will then insert the required delay during power up of paths that involve the microphone. Signed-off-by: Mark Brown --- include/linux/mfd/wm8994/pdata.h | 4 ++++ include/sound/wm8993.h | 4 ++++ sound/soc/codecs/wm8993.c | 2 ++ sound/soc/codecs/wm8994.c | 2 ++ sound/soc/codecs/wm_hubs.c | 35 +++++++++++++++++++++++++++++++---- sound/soc/codecs/wm_hubs.h | 4 ++++ 6 files changed, 47 insertions(+), 4 deletions(-) (limited to 'sound/soc') diff --git a/include/linux/mfd/wm8994/pdata.h b/include/linux/mfd/wm8994/pdata.h index f0361c031927..fc87be4fdc25 100644 --- a/include/linux/mfd/wm8994/pdata.h +++ b/include/linux/mfd/wm8994/pdata.h @@ -164,6 +164,10 @@ struct wm8994_pdata { int num_micd_rates; struct wm8958_micd_rate *micd_rates; + /* Power up delays to add after microphone bias power up (ms) */ + int micb1_delay; + int micb2_delay; + /* LINEOUT can be differential or single ended */ unsigned int lineout1_diff:1; unsigned int lineout2_diff:1; diff --git a/include/sound/wm8993.h b/include/sound/wm8993.h index eee19f63c0d8..8016fd826f5a 100644 --- a/include/sound/wm8993.h +++ b/include/sound/wm8993.h @@ -32,6 +32,10 @@ struct wm8993_platform_data { unsigned int lineout1fb:1; unsigned int lineout2fb:1; + /* Delay to add for microphones to stabalise after power up */ + int micbias1_delay; + int micbias2_delay; + /* Microphone biases: 0=0.9*AVDD1 1=0.65*AVVD1 */ unsigned int micbias1_lvl:1; unsigned int micbias2_lvl:1; diff --git a/sound/soc/codecs/wm8993.c b/sound/soc/codecs/wm8993.c index 9fd80d688979..94737a30716b 100644 --- a/sound/soc/codecs/wm8993.c +++ b/sound/soc/codecs/wm8993.c @@ -1520,6 +1520,8 @@ static int wm8993_probe(struct snd_soc_codec *codec) wm8993->pdata.lineout2fb, wm8993->pdata.jd_scthr, wm8993->pdata.jd_thr, + wm8993->pdata.micbias1_delay, + wm8993->pdata.micbias2_delay, wm8993->pdata.micbias1_lvl, wm8993->pdata.micbias2_lvl); diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index 353612eec8bf..b74df52d2820 100644 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c @@ -3145,6 +3145,8 @@ static void wm8994_handle_pdata(struct wm8994_priv *wm8994) pdata->lineout2fb, pdata->jd_scthr, pdata->jd_thr, + pdata->micb1_delay, + pdata->micb2_delay, pdata->micbias1_lvl, pdata->micbias2_lvl); diff --git a/sound/soc/codecs/wm_hubs.c b/sound/soc/codecs/wm_hubs.c index b2e939a8970e..7a773a835b8e 100644 --- a/sound/soc/codecs/wm_hubs.c +++ b/sound/soc/codecs/wm_hubs.c @@ -644,6 +644,28 @@ static int lineout_event(struct snd_soc_dapm_widget *w, return 0; } +static int micbias_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_codec *codec = w->codec; + struct wm_hubs_data *hubs = snd_soc_codec_get_drvdata(codec); + + switch (w->shift) { + case WM8993_MICB1_ENA_SHIFT: + if (hubs->micb1_delay) + msleep(hubs->micb1_delay); + break; + case WM8993_MICB2_ENA_SHIFT: + if (hubs->micb2_delay) + msleep(hubs->micb2_delay); + break; + default: + return -EINVAL; + } + + return 0; +} + void wm_hubs_update_class_w(struct snd_soc_codec *codec) { struct wm_hubs_data *hubs = snd_soc_codec_get_drvdata(codec); @@ -834,8 +856,10 @@ SND_SOC_DAPM_INPUT("IN1RP"), SND_SOC_DAPM_INPUT("IN2RN"), SND_SOC_DAPM_INPUT("IN2RP:VXRP"), -SND_SOC_DAPM_SUPPLY("MICBIAS2", WM8993_POWER_MANAGEMENT_1, 5, 0, NULL, 0), -SND_SOC_DAPM_SUPPLY("MICBIAS1", WM8993_POWER_MANAGEMENT_1, 4, 0, NULL, 0), +SND_SOC_DAPM_SUPPLY("MICBIAS2", WM8993_POWER_MANAGEMENT_1, 5, 0, + micbias_event, SND_SOC_DAPM_POST_PMU), +SND_SOC_DAPM_SUPPLY("MICBIAS1", WM8993_POWER_MANAGEMENT_1, 4, 0, + micbias_event, SND_SOC_DAPM_POST_PMU), SND_SOC_DAPM_MIXER("IN1L PGA", WM8993_POWER_MANAGEMENT_2, 6, 0, in1l_pga, ARRAY_SIZE(in1l_pga)), @@ -1170,13 +1194,16 @@ EXPORT_SYMBOL_GPL(wm_hubs_add_analogue_routes); int wm_hubs_handle_analogue_pdata(struct snd_soc_codec *codec, int lineout1_diff, int lineout2_diff, int lineout1fb, int lineout2fb, - int jd_scthr, int jd_thr, int micbias1_lvl, - int micbias2_lvl) + int jd_scthr, int jd_thr, + int micbias1_delay, int micbias2_delay, + int micbias1_lvl, int micbias2_lvl) { struct wm_hubs_data *hubs = snd_soc_codec_get_drvdata(codec); hubs->lineout1_se = !lineout1_diff; hubs->lineout2_se = !lineout2_diff; + hubs->micb1_delay = micbias1_delay; + hubs->micb2_delay = micbias2_delay; if (!lineout1_diff) snd_soc_update_bits(codec, WM8993_LINE_MIXER1, diff --git a/sound/soc/codecs/wm_hubs.h b/sound/soc/codecs/wm_hubs.h index a5a09e6f87d5..24c763df21f9 100644 --- a/sound/soc/codecs/wm_hubs.h +++ b/sound/soc/codecs/wm_hubs.h @@ -36,6 +36,9 @@ struct wm_hubs_data { struct list_head dcs_cache; bool (*check_class_w_digital)(struct snd_soc_codec *); + int micb1_delay; + int micb2_delay; + bool lineout1_se; bool lineout1n_ena; bool lineout1p_ena; @@ -56,6 +59,7 @@ extern int wm_hubs_handle_analogue_pdata(struct snd_soc_codec *, int lineout1_diff, int lineout2_diff, int lineout1fb, int lineout2fb, int jd_scthr, int jd_thr, + int micbias1_dly, int micbias2_dly, int micbias1_lvl, int micbias2_lvl); extern irqreturn_t wm_hubs_dcs_done(int irq, void *data); -- cgit v1.2.3 From f199131a8f1dde3309c8520b663aa7a3daf5995e Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Thu, 16 Aug 2012 16:41:00 +0300 Subject: ARM/ASoC: omap-mcbsp: Move OMAP2+ clock parenting code to ASoC driver Move the McBSP CLKS re-parenting code to ASoC driver from arch/arm/mach-omap2. The call fort the re-parenting has been already limited to OMAP2+ SoC in the ASoC driver. There is no longer need to have callback function for it. Signed-off-by: Peter Ujfalusi Acked-by: Jarkko Nikula Acked-by: Tony Lindgren Signed-off-by: Mark Brown --- arch/arm/mach-omap2/mcbsp.c | 40 --------------------------------- arch/arm/plat-omap/include/plat/mcbsp.h | 1 - sound/soc/omap/mcbsp.c | 31 ++++++++++++++++++++----- 3 files changed, 26 insertions(+), 46 deletions(-) (limited to 'sound/soc') diff --git a/arch/arm/mach-omap2/mcbsp.c b/arch/arm/mach-omap2/mcbsp.c index 577cb77db26c..ebc801ea5be9 100644 --- a/arch/arm/mach-omap2/mcbsp.c +++ b/arch/arm/mach-omap2/mcbsp.c @@ -101,45 +101,6 @@ static int omap4_mcbsp4_mux_rx_clk(struct device *dev, const char *signal, return 0; } -/* McBSP CLKS source switching function */ -static int omap2_mcbsp_set_clk_src(struct device *dev, struct clk *clk, - const char *src) -{ - struct clk *fck_src; - char *fck_src_name; - int r; - - if (!strcmp(src, "clks_ext")) - fck_src_name = "pad_fck"; - else if (!strcmp(src, "clks_fclk")) - fck_src_name = "prcm_fck"; - else - return -EINVAL; - - fck_src = clk_get(dev, fck_src_name); - if (IS_ERR_OR_NULL(fck_src)) { - pr_err("omap-mcbsp: %s: could not clk_get() %s\n", "clks", - fck_src_name); - return -EINVAL; - } - - pm_runtime_put_sync(dev); - - r = clk_set_parent(clk, fck_src); - if (IS_ERR_VALUE(r)) { - pr_err("omap-mcbsp: %s: could not clk_set_parent() to %s\n", - "clks", fck_src_name); - clk_put(fck_src); - return -EINVAL; - } - - pm_runtime_get_sync(dev); - - clk_put(fck_src); - - return 0; -} - static int omap3_enable_st_clock(unsigned int id, bool enable) { unsigned int w; @@ -181,7 +142,6 @@ static int __init omap_init_mcbsp(struct omap_hwmod *oh, void *unused) pdata->reg_size = 4; pdata->has_ccr = true; } - pdata->set_clk_src = omap2_mcbsp_set_clk_src; /* On OMAP2/3 the McBSP1 port has 6 pin configuration */ if (id == 1 && oh->class->rev < MCBSP_CONFIG_TYPE4) diff --git a/arch/arm/plat-omap/include/plat/mcbsp.h b/arch/arm/plat-omap/include/plat/mcbsp.h index 18814127809a..0a7d5ca471e0 100644 --- a/arch/arm/plat-omap/include/plat/mcbsp.h +++ b/arch/arm/plat-omap/include/plat/mcbsp.h @@ -47,7 +47,6 @@ struct omap_mcbsp_platform_data { bool has_wakeup; /* Wakeup capability */ bool has_ccr; /* Transceiver has configuration control registers */ int (*enable_st_clock)(unsigned int, bool); - int (*set_clk_src)(struct device *dev, struct clk *clk, const char *src); int (*mux_signal)(struct device *dev, const char *signal, const char *src); }; diff --git a/sound/soc/omap/mcbsp.c b/sound/soc/omap/mcbsp.c index 34835e8a9160..6afbc26cef70 100644 --- a/sound/soc/omap/mcbsp.c +++ b/sound/soc/omap/mcbsp.c @@ -24,6 +24,7 @@ #include #include #include +#include #include @@ -726,19 +727,39 @@ void omap_mcbsp_stop(struct omap_mcbsp *mcbsp, int tx, int rx) int omap2_mcbsp_set_clks_src(struct omap_mcbsp *mcbsp, u8 fck_src_id) { + struct clk *fck_src; const char *src; + int r; if (fck_src_id == MCBSP_CLKS_PAD_SRC) - src = "clks_ext"; + src = "pad_fck"; else if (fck_src_id == MCBSP_CLKS_PRCM_SRC) - src = "clks_fclk"; + src = "prcm_fck"; else return -EINVAL; - if (mcbsp->pdata->set_clk_src) - return mcbsp->pdata->set_clk_src(mcbsp->dev, mcbsp->fclk, src); - else + fck_src = clk_get(mcbsp->dev, src); + if (IS_ERR(fck_src)) { + dev_err(mcbsp->dev, "CLKS: could not clk_get() %s\n", src); return -EINVAL; + } + + pm_runtime_put_sync(mcbsp->dev); + + r = clk_set_parent(mcbsp->fclk, fck_src); + if (r) { + dev_err(mcbsp->dev, "CLKS: could not clk_set_parent() to %s\n", + src); + clk_put(fck_src); + return r; + } + + pm_runtime_get_sync(mcbsp->dev); + + clk_put(fck_src); + + return 0; + } int omap_mcbsp_6pin_src_mux(struct omap_mcbsp *mcbsp, u8 mux) -- cgit v1.2.3 From fca04aea36a82bc451ddc33dee6f9a48bb0f8a2a Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Thu, 16 Aug 2012 16:41:03 +0300 Subject: ASoC: am3517evm: Do not configure McBSP1 CLKR/FSR signal muxing The muxing is done at board level, no need to do it in the ASoC machine driver. Signed-off-by: Peter Ujfalusi Acked-by: Jarkko Nikula Signed-off-by: Mark Brown --- sound/soc/omap/am3517evm.c | 20 ++------------------ 1 file changed, 2 insertions(+), 18 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/omap/am3517evm.c b/sound/soc/omap/am3517evm.c index 009533ab8d18..a997988af147 100644 --- a/sound/soc/omap/am3517evm.c +++ b/sound/soc/omap/am3517evm.c @@ -47,26 +47,10 @@ static int am3517evm_hw_params(struct snd_pcm_substream *substream, /* Set the codec system clock for DAC and ADC */ ret = snd_soc_dai_set_sysclk(codec_dai, 0, CODEC_CLOCK, SND_SOC_CLOCK_IN); - if (ret < 0) { + if (ret < 0) printk(KERN_ERR "can't set codec system clock\n"); - return ret; - } - - ret = snd_soc_dai_set_sysclk(cpu_dai, OMAP_MCBSP_CLKR_SRC_CLKX, 0, - SND_SOC_CLOCK_IN); - if (ret < 0) { - printk(KERN_ERR "can't set CPU system clock OMAP_MCBSP_CLKR_SRC_CLKX\n"); - return ret; - } - snd_soc_dai_set_sysclk(cpu_dai, OMAP_MCBSP_FSR_SRC_FSX, 0, - SND_SOC_CLOCK_IN); - if (ret < 0) { - printk(KERN_ERR "can't set CPU system clock OMAP_MCBSP_FSR_SRC_FSX\n"); - return ret; - } - - return 0; + return ret; } static struct snd_soc_ops am3517evm_ops = { -- cgit v1.2.3 From 8fef6263ea68f6160637f370a5864d0a455c620d Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Thu, 16 Aug 2012 16:41:04 +0300 Subject: ARM/ASoC: omap-mcbsp: Remove CLKR/FSR mux configuration code Remove the feature to configure the CLKR/FSR mux on McBSP port with 6pin configuration. When moving to devicetree these callback can no longer be used in a clean way anymore. If a board require to change the 6pin port to work in 4pin setup it needs to set up the mux in the board file. For OMAP2/3: u32 devconf0; /* McBSP1 CLKR/FSR signal to be connected to CLKX/FSX pin */ devconf0 = omap_ctrl_readl(OMAP2_CONTROL_DEVCONF0); devconf0 |= OMAP2_MCBSP1_CLKR_MASK | OMAP2_MCBSP1_FSR_MASK; omap_ctrl_writel(devconf0, OMAP2_CONTROL_DEVCONF0); For OMAP4: u32 mcbsp_pad; /* McBSP4 CLKR/FSR signal to be connected to CLKX/FSX pin */ mcbsp_pad = omap4_ctrl_pad_readl(OMAP2_CONTROL_DEVCONF0); mcbsp_pad |= ((1 << 31) | (1 << 30)); omap4_ctrl_pad_writel(mcbsp_pad, OMAP2_CONTROL_DEVCONF0); In case when the kernel is booted with DT blob the pinctrl-single will be provided as soon as it is enabled on the platform. Signed-off-by: Peter Ujfalusi Acked-by: Jarkko Nikula Acked-by: Tony Lindgren Signed-off-by: Mark Brown --- arch/arm/mach-omap2/mcbsp.c | 77 --------------------------------- arch/arm/plat-omap/include/plat/mcbsp.h | 1 - sound/soc/omap/mcbsp.h | 3 -- sound/soc/omap/omap-mcbsp.c | 32 ++------------ sound/soc/omap/omap-mcbsp.h | 4 -- 5 files changed, 3 insertions(+), 114 deletions(-) (limited to 'sound/soc') diff --git a/arch/arm/mach-omap2/mcbsp.c b/arch/arm/mach-omap2/mcbsp.c index 6e046e1111b1..660e00b3ef82 100644 --- a/arch/arm/mach-omap2/mcbsp.c +++ b/arch/arm/mach-omap2/mcbsp.c @@ -25,8 +25,6 @@ #include #include -#include "control.h" - /* * FIXME: Find a mechanism to enable/disable runtime the McBSP ICLK autoidle. * Sidetone needs non-gated ICLK and sidetone autoidle is broken. @@ -34,73 +32,6 @@ #include "cm2xxx_3xxx.h" #include "cm-regbits-34xx.h" -/* McBSP1 internal signal muxing function for OMAP2/3 */ -static int omap2_mcbsp1_mux_rx_clk(struct device *dev, const char *signal, - const char *src) -{ - u32 v; - - v = omap_ctrl_readl(OMAP2_CONTROL_DEVCONF0); - - if (!strcmp(signal, "clkr")) { - if (!strcmp(src, "clkr")) - v &= ~OMAP2_MCBSP1_CLKR_MASK; - else if (!strcmp(src, "clkx")) - v |= OMAP2_MCBSP1_CLKR_MASK; - else - return -EINVAL; - } else if (!strcmp(signal, "fsr")) { - if (!strcmp(src, "fsr")) - v &= ~OMAP2_MCBSP1_FSR_MASK; - else if (!strcmp(src, "fsx")) - v |= OMAP2_MCBSP1_FSR_MASK; - else - return -EINVAL; - } else { - return -EINVAL; - } - - omap_ctrl_writel(v, OMAP2_CONTROL_DEVCONF0); - - return 0; -} - -/* McBSP4 internal signal muxing function for OMAP4 */ -#define OMAP4_CONTROL_MCBSPLP_ALBCTRLRX_FSX (1 << 31) -#define OMAP4_CONTROL_MCBSPLP_ALBCTRLRX_CLKX (1 << 30) -static int omap4_mcbsp4_mux_rx_clk(struct device *dev, const char *signal, - const char *src) -{ - u32 v; - - /* - * In CONTROL_MCBSPLP register only bit 30 (CLKR mux), and bit 31 (FSR - * mux) is used */ - v = omap4_ctrl_pad_readl(OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_MCBSPLP); - - if (!strcmp(signal, "clkr")) { - if (!strcmp(src, "clkr")) - v &= ~OMAP4_CONTROL_MCBSPLP_ALBCTRLRX_CLKX; - else if (!strcmp(src, "clkx")) - v |= OMAP4_CONTROL_MCBSPLP_ALBCTRLRX_CLKX; - else - return -EINVAL; - } else if (!strcmp(signal, "fsr")) { - if (!strcmp(src, "fsr")) - v &= ~OMAP4_CONTROL_MCBSPLP_ALBCTRLRX_FSX; - else if (!strcmp(src, "fsx")) - v |= OMAP4_CONTROL_MCBSPLP_ALBCTRLRX_FSX; - else - return -EINVAL; - } else { - return -EINVAL; - } - - omap4_ctrl_pad_writel(v, OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_MCBSPLP); - - return 0; -} - static int omap3_enable_st_clock(unsigned int id, bool enable) { unsigned int w; @@ -143,14 +74,6 @@ static int __init omap_init_mcbsp(struct omap_hwmod *oh, void *unused) pdata->has_ccr = true; } - /* On OMAP2/3 the McBSP1 port has 6 pin configuration */ - if (id == 1 && oh->class->rev < MCBSP_CONFIG_TYPE4) - pdata->mux_signal = omap2_mcbsp1_mux_rx_clk; - - /* On OMAP4 the McBSP4 port has 6 pin configuration */ - if (id == 4 && oh->class->rev == MCBSP_CONFIG_TYPE4) - pdata->mux_signal = omap4_mcbsp4_mux_rx_clk; - if (oh->class->rev == MCBSP_CONFIG_TYPE2) { /* The FIFO has 128 locations */ pdata->buffer_size = 0x80; diff --git a/arch/arm/plat-omap/include/plat/mcbsp.h b/arch/arm/plat-omap/include/plat/mcbsp.h index 0a7d5ca471e0..c78d90b28b19 100644 --- a/arch/arm/plat-omap/include/plat/mcbsp.h +++ b/arch/arm/plat-omap/include/plat/mcbsp.h @@ -47,7 +47,6 @@ struct omap_mcbsp_platform_data { bool has_wakeup; /* Wakeup capability */ bool has_ccr; /* Transceiver has configuration control registers */ int (*enable_st_clock)(unsigned int, bool); - int (*mux_signal)(struct device *dev, const char *signal, const char *src); }; /** diff --git a/sound/soc/omap/mcbsp.h b/sound/soc/omap/mcbsp.h index 262a6152111f..49a67259ce5a 100644 --- a/sound/soc/omap/mcbsp.h +++ b/sound/soc/omap/mcbsp.h @@ -334,9 +334,6 @@ void omap_mcbsp_stop(struct omap_mcbsp *mcbsp, int tx, int rx); /* McBSP functional clock source changing function */ int omap2_mcbsp_set_clks_src(struct omap_mcbsp *mcbsp, u8 fck_src_id); -/* McBSP signal muxing API */ -int omap_mcbsp_6pin_src_mux(struct omap_mcbsp *mcbsp, u8 mux); - /* Sidetone specific API */ int omap_st_set_chgain(struct omap_mcbsp *mcbsp, int channel, s16 chgain); int omap_st_get_chgain(struct omap_mcbsp *mcbsp, int channel, s16 *chgain); diff --git a/sound/soc/omap/omap-mcbsp.c b/sound/soc/omap/omap-mcbsp.c index 1046083e90a0..506159493a9d 100644 --- a/sound/soc/omap/omap-mcbsp.c +++ b/sound/soc/omap/omap-mcbsp.c @@ -516,21 +516,9 @@ static int omap_mcbsp_dai_set_dai_sysclk(struct snd_soc_dai *cpu_dai, return -EBUSY; } - if (clk_id == OMAP_MCBSP_SYSCLK_CLK || - clk_id == OMAP_MCBSP_SYSCLK_CLKS_FCLK || - clk_id == OMAP_MCBSP_SYSCLK_CLKS_EXT || - clk_id == OMAP_MCBSP_SYSCLK_CLKX_EXT || - clk_id == OMAP_MCBSP_SYSCLK_CLKR_EXT) { - mcbsp->in_freq = freq; - regs->srgr2 &= ~CLKSM; - regs->pcr0 &= ~SCLKME; - } else if (cpu_class_is_omap1()) { - /* - * McBSP CLKR/FSR signal muxing functions are only available on - * OMAP2 or newer versions - */ - return -EINVAL; - } + mcbsp->in_freq = freq; + regs->srgr2 &= ~CLKSM; + regs->pcr0 &= ~SCLKME; switch (clk_id) { case OMAP_MCBSP_SYSCLK_CLK: @@ -558,20 +546,6 @@ static int omap_mcbsp_dai_set_dai_sysclk(struct snd_soc_dai *cpu_dai, case OMAP_MCBSP_SYSCLK_CLKR_EXT: regs->pcr0 |= SCLKME; break; - - - case OMAP_MCBSP_CLKR_SRC_CLKR: - err = omap_mcbsp_6pin_src_mux(mcbsp, CLKR_SRC_CLKR); - break; - case OMAP_MCBSP_CLKR_SRC_CLKX: - err = omap_mcbsp_6pin_src_mux(mcbsp, CLKR_SRC_CLKX); - break; - case OMAP_MCBSP_FSR_SRC_FSR: - err = omap_mcbsp_6pin_src_mux(mcbsp, FSR_SRC_FSR); - break; - case OMAP_MCBSP_FSR_SRC_FSX: - err = omap_mcbsp_6pin_src_mux(mcbsp, FSR_SRC_FSX); - break; default: err = -ENODEV; } diff --git a/sound/soc/omap/omap-mcbsp.h b/sound/soc/omap/omap-mcbsp.h index f877b16f19c9..baebcee30e30 100644 --- a/sound/soc/omap/omap-mcbsp.h +++ b/sound/soc/omap/omap-mcbsp.h @@ -32,10 +32,6 @@ enum omap_mcbsp_clksrg_clk { OMAP_MCBSP_SYSCLK_CLK, /* Internal ICLK */ OMAP_MCBSP_SYSCLK_CLKX_EXT, /* External CLKX pin */ OMAP_MCBSP_SYSCLK_CLKR_EXT, /* External CLKR pin */ - OMAP_MCBSP_CLKR_SRC_CLKR, /* CLKR from CLKR pin */ - OMAP_MCBSP_CLKR_SRC_CLKX, /* CLKR from CLKX pin */ - OMAP_MCBSP_FSR_SRC_FSR, /* FSR from FSR pin */ - OMAP_MCBSP_FSR_SRC_FSX, /* FSR from FSX pin */ }; /* McBSP dividers */ -- cgit v1.2.3 From 8d3c09096500aa20702395b87c81a62ac9cbe3be Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Thu, 16 Aug 2012 16:41:05 +0300 Subject: ASoC: omap-mcbsp: Remove unused defines NUM_LINKS is no longer in use by the code. Signed-off-by: Peter Ujfalusi Acked-by: Jarkko Nikula Signed-off-by: Mark Brown --- sound/soc/omap/omap-mcbsp.h | 16 ---------------- 1 file changed, 16 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/omap/omap-mcbsp.h b/sound/soc/omap/omap-mcbsp.h index baebcee30e30..ba8386a0d8dc 100644 --- a/sound/soc/omap/omap-mcbsp.h +++ b/sound/soc/omap/omap-mcbsp.h @@ -39,22 +39,6 @@ enum omap_mcbsp_div { OMAP_MCBSP_CLKGDV, /* Sample rate generator divider */ }; -#if defined(CONFIG_SOC_OMAP2420) -#define NUM_LINKS 2 -#endif -#if defined(CONFIG_ARCH_OMAP15XX) || defined(CONFIG_ARCH_OMAP16XX) -#undef NUM_LINKS -#define NUM_LINKS 3 -#endif -#if defined(CONFIG_ARCH_OMAP4) -#undef NUM_LINKS -#define NUM_LINKS 4 -#endif -#if defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_SOC_OMAP2430) -#undef NUM_LINKS -#define NUM_LINKS 5 -#endif - int omap_mcbsp_st_add_controls(struct snd_soc_pcm_runtime *rtd); #endif -- cgit v1.2.3 From dc26df52455348e06e4c34a2af2910d291369fe8 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Thu, 16 Aug 2012 16:41:06 +0300 Subject: ASoC: omap-mcbsp: Remove cpu_is_omap* checks from the code We can use the has_ccr flag to replace the cpu_is_omap* checks. This provides future proof implementation and we do not need to update the code if new OMAP revision starts to use the McBSP driver. Signed-off-by: Peter Ujfalusi Acked-by: Jarkko Nikula Signed-off-by: Mark Brown --- sound/soc/omap/omap-mcbsp.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/omap/omap-mcbsp.c b/sound/soc/omap/omap-mcbsp.c index 506159493a9d..b9770eea28a0 100644 --- a/sound/soc/omap/omap-mcbsp.c +++ b/sound/soc/omap/omap-mcbsp.c @@ -398,12 +398,14 @@ static int omap_mcbsp_dai_set_dai_fmt(struct snd_soc_dai *cpu_dai, /* Generic McBSP register settings */ regs->spcr2 |= XINTM(3) | FREE; regs->spcr1 |= RINTM(3); - /* RFIG and XFIG are not defined in 34xx */ - if (!cpu_is_omap34xx() && !cpu_is_omap44xx()) { + /* RFIG and XFIG are not defined in 2430 and on OMAP3+ */ + if (!mcbsp->pdata->has_ccr) { regs->rcr2 |= RFIG; regs->xcr2 |= XFIG; } - if (cpu_is_omap2430() || cpu_is_omap34xx() || cpu_is_omap44xx()) { + + /* Configure XCCR/RCCR only for revisions which have ccr registers */ + if (mcbsp->pdata->has_ccr) { regs->xccr = DXENDLY(1) | XDMAEN | XDISABLE; regs->rccr = RFULL_CYCLE | RDMAEN | RDISABLE; } -- cgit v1.2.3 From 11dd586421b3091007e6f084a9211f3baa66f9fc Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Thu, 16 Aug 2012 16:41:08 +0300 Subject: ASoC: omap-mcbsp: Add device tree bindings Device tree support for McBSP modules on OMAP2+ SoC. Signed-off-by: Peter Ujfalusi Signed-off-by: Mark Brown --- .../devicetree/bindings/sound/omap-mcbsp.txt | 45 +++++++++++++++ sound/soc/omap/omap-mcbsp.c | 66 +++++++++++++++++++++- 2 files changed, 110 insertions(+), 1 deletion(-) create mode 100644 Documentation/devicetree/bindings/sound/omap-mcbsp.txt (limited to 'sound/soc') diff --git a/Documentation/devicetree/bindings/sound/omap-mcbsp.txt b/Documentation/devicetree/bindings/sound/omap-mcbsp.txt new file mode 100644 index 000000000000..447cb131e909 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/omap-mcbsp.txt @@ -0,0 +1,45 @@ +* Texas Instruments OMAP2+ McBSP module + +Required properties: +- compatible: "ti,omap2420-mcbsp" for McBSP on OMAP2420 + "ti,omap2430-mcbsp" for McBSP on OMAP2430 + "ti,omap3-mcbsp" for McBSP on OMAP3 + "ti,omap4-mcbsp" for McBSP on OMAP4 and newer SoC +- reg: Register location and size, for OMAP4+ as an array: + , + ; +- interrupts: Interrupt numbers for the McBSP port, as an array in case the + McBSP IP have more interrupt lines: + , + , + ; +- interrupt-parent: The parent interrupt controller +- ti,buffer-size: Size of the FIFO on the port (OMAP2430 and newer SoC) +- ti,hwmods: Name of the hwmod associated to the McBSP port + +Sidetone support for OMAP3 McBSP2 and 3 ports: +- sidetone { }: Within this section the following parameters are required: +- reg: Register location and size for the ST block +- interrupts: The interrupt number for the ST block +- interrupt-parent: The parent interrupt controller for the ST block + +Example: + +mcbsp2: mcbsp@49022000 { + compatible = "ti,omap3-mcbsp"; + #address-cells = <1>; + #size-cells = <1>; + reg = <0x49022000 0xff>; + interrupts = <0 17 0x4>, /* OCP compliant interrup */ + <0 62 0x4>, /* TX interrup */ + <0 63 0x4>; /* RX interrup */ + interrupt-parent = <&intc>; + ti,buffer-size = <1280>; + ti,hwmods = "mcbsp2"; + + sidetone { + reg = <0x49028000 0xff>; + interrupts = <0 4 0x4>; + interrupt-parent = <&intc>; + }; +}; diff --git a/sound/soc/omap/omap-mcbsp.c b/sound/soc/omap/omap-mcbsp.c index b9770eea28a0..2e1750e2ab31 100644 --- a/sound/soc/omap/omap-mcbsp.c +++ b/sound/soc/omap/omap-mcbsp.c @@ -26,6 +26,8 @@ #include #include #include +#include +#include #include #include #include @@ -737,13 +739,74 @@ int omap_mcbsp_st_add_controls(struct snd_soc_pcm_runtime *rtd) } EXPORT_SYMBOL_GPL(omap_mcbsp_st_add_controls); +static struct omap_mcbsp_platform_data omap2420_pdata = { + .reg_step = 4, + .reg_size = 2, +}; + +static struct omap_mcbsp_platform_data omap2430_pdata = { + .reg_step = 4, + .reg_size = 4, + .has_ccr = true, +}; + +static struct omap_mcbsp_platform_data omap3_pdata = { + .reg_step = 4, + .reg_size = 4, + .has_ccr = true, + .has_wakeup = true, +}; + +static struct omap_mcbsp_platform_data omap4_pdata = { + .reg_step = 4, + .reg_size = 4, + .has_ccr = true, + .has_wakeup = true, +}; + +static const struct of_device_id omap_mcbsp_of_match[] = { + { + .compatible = "ti,omap2420-mcbsp", + .data = &omap2420_pdata, + }, + { + .compatible = "ti,omap2430-mcbsp", + .data = &omap2430_pdata, + }, + { + .compatible = "ti,omap3-mcbsp", + .data = &omap3_pdata, + }, + { + .compatible = "ti,omap4-mcbsp", + .data = &omap4_pdata, + }, + { }, +}; +MODULE_DEVICE_TABLE(of, omap_mcbsp_of_match); + static __devinit int asoc_mcbsp_probe(struct platform_device *pdev) { struct omap_mcbsp_platform_data *pdata = dev_get_platdata(&pdev->dev); struct omap_mcbsp *mcbsp; + const struct of_device_id *match; int ret; - if (!pdata) { + match = of_match_device(omap_mcbsp_of_match, &pdev->dev); + if (match) { + struct device_node *node = pdev->dev.of_node; + int buffer_size; + + pdata = devm_kzalloc(&pdev->dev, + sizeof(struct omap_mcbsp_platform_data), + GFP_KERNEL); + if (!pdata) + return -ENOMEM; + + memcpy(pdata, match->data, sizeof(*pdata)); + if (!of_property_read_u32(node, "ti,buffer-size", &buffer_size)) + pdata->buffer_size = buffer_size; + } else if (!pdata) { dev_err(&pdev->dev, "missing platform data.\n"); return -EINVAL; } @@ -785,6 +848,7 @@ static struct platform_driver asoc_mcbsp_driver = { .driver = { .name = "omap-mcbsp", .owner = THIS_MODULE, + .of_match_table = omap_mcbsp_of_match, }, .probe = asoc_mcbsp_probe, -- cgit v1.2.3 From 52ca1138fa55bf6f46a5e02a2c1088756a5c8f2e Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 23 Aug 2012 15:50:45 +0100 Subject: ASoC: wm8994: Update for new WM1811 variants There are some new WM1811 variants distinguished by both revision and cust_id which need slightly different handling. Signed-off-by: Mark Brown --- sound/soc/codecs/wm8994.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index b74df52d2820..890b582b40f3 100644 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c @@ -3823,14 +3823,17 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec) wm8994->hubs.no_cache_dac_hp_direct = true; wm8994->fll_byp = true; - switch (wm8994->revision) { + switch (control->cust_id) { case 0: - case 1: case 2: - case 3: wm8994->hubs.dcs_codes_l = -9; wm8994->hubs.dcs_codes_r = -7; break; + case 1: + case 3: + wm8994->hubs.dcs_codes_l = -8; + wm8994->hubs.dcs_codes_r = -7; + break; default: break; } @@ -3919,7 +3922,7 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec) switch (control->type) { case WM1811: - if (wm8994->revision > 1) { + if (control->cust_id > 1 || wm8994->revision > 1) { ret = wm8994_request_irq(wm8994->wm8994, WM8994_IRQ_GPIO(6), wm1811_jackdet_irq, "JACKDET", -- cgit v1.2.3 From e3523e01869da20fdd12ffd19ae1df7bf492650e Mon Sep 17 00:00:00 2001 From: Dimitris Papastamos Date: Thu, 23 Aug 2012 15:59:56 +0100 Subject: ASoC: wm0010: Add initial wm0010 DSP driver The WM0010 is a compact digital signal processor that has been highly optimised for low-power audio applications. Extensive memory resources and core optimisation allow the device to manage all audio processing algorithms efficiently and autonomously, while the host processor sleeps or performs other tasks. Signed-off-by: Dimitris Papastamos Signed-off-by: Mark Brown --- include/sound/wm0010.h | 27 ++ sound/soc/codecs/Kconfig | 4 + sound/soc/codecs/Makefile | 2 + sound/soc/codecs/wm0010.c | 930 ++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 963 insertions(+) create mode 100644 include/sound/wm0010.h create mode 100644 sound/soc/codecs/wm0010.c (limited to 'sound/soc') diff --git a/include/sound/wm0010.h b/include/sound/wm0010.h new file mode 100644 index 000000000000..3261e90815af --- /dev/null +++ b/include/sound/wm0010.h @@ -0,0 +1,27 @@ +/* + * wm0010.h -- Platform data for WM0010 DSP Driver + * + * Copyright 2012 Wolfson Microelectronics PLC. + * + * Author: Dimitris Papastamos + * + * 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. + */ + +#ifndef WM0010_PDATA_H +#define WM0010_PDATA_H + +struct wm0010_pdata { + int gpio_reset; + + /* Set if there is an inverter between the GPIO controlling + * the reset signal and the device. + */ + int reset_active_high; + int irq_flags; +}; + +#endif diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 9f8e8594aeb9..3684255e5fba 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -70,6 +70,7 @@ config SND_SOC_ALL_CODECS select SND_SOC_UDA134X select SND_SOC_UDA1380 if I2C select SND_SOC_WL1273 if MFD_WL1273_CORE + select SND_SOC_WM0010 if SPI_MASTER select SND_SOC_WM1250_EV1 if I2C select SND_SOC_WM2000 if I2C select SND_SOC_WM2200 if I2C @@ -326,6 +327,9 @@ config SND_SOC_UDA1380 config SND_SOC_WL1273 tristate +config SND_SOC_WM0010 + tristate + config SND_SOC_WM1250_EV1 tristate diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index 34148bb59c68..ca508b251df7 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -61,6 +61,7 @@ snd-soc-twl6040-objs := twl6040.o snd-soc-uda134x-objs := uda134x.o snd-soc-uda1380-objs := uda1380.o snd-soc-wl1273-objs := wl1273.o +snd-soc-wm0010-objs := wm0010.o snd-soc-wm1250-ev1-objs := wm1250-ev1.o snd-soc-wm2000-objs := wm2000.o snd-soc-wm2200-objs := wm2200.o @@ -177,6 +178,7 @@ obj-$(CONFIG_SND_SOC_TWL6040) += snd-soc-twl6040.o obj-$(CONFIG_SND_SOC_UDA134X) += snd-soc-uda134x.o obj-$(CONFIG_SND_SOC_UDA1380) += snd-soc-uda1380.o obj-$(CONFIG_SND_SOC_WL1273) += snd-soc-wl1273.o +obj-$(CONFIG_SND_SOC_WM0010) += snd-soc-wm0010.o obj-$(CONFIG_SND_SOC_WM1250_EV1) += snd-soc-wm1250-ev1.o obj-$(CONFIG_SND_SOC_WM2000) += snd-soc-wm2000.o obj-$(CONFIG_SND_SOC_WM2200) += snd-soc-wm2200.o diff --git a/sound/soc/codecs/wm0010.c b/sound/soc/codecs/wm0010.c new file mode 100644 index 000000000000..8e0b6d6bffaf --- /dev/null +++ b/sound/soc/codecs/wm0010.c @@ -0,0 +1,930 @@ +/* + * wm0010.c -- WM0010 DSP Driver + * + * Copyright 2012 Wolfson Microelectronics PLC. + * + * Authors: Mark Brown + * Dimitris Papastamos + * Scott Ling + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#define DEVICE_ID_WM0010 10 + +enum dfw_cmd { + DFW_CMD_FUSE = 0x01, + DFW_CMD_CODE_HDR, + DFW_CMD_CODE_DATA, + DFW_CMD_PLL, + DFW_CMD_INFO = 0xff +}; + +struct dfw_binrec { + u8 command; + u32 length:24; + u32 address; + uint8_t data[0]; +} __packed; + +struct dfw_pllrec { + u8 command; + u32 length:24; + u32 address; + u32 clkctrl1; + u32 clkctrl2; + u32 clkctrl3; + u32 ldetctrl; + u32 uart_div; + u32 spi_div; +} __packed; + +static struct pll_clock_map { + int max_sysclk; + int max_pll_spi_speed; + u32 pll_clkctrl1; +} pll_clock_map[] = { /* Dividers */ + { 22000000, 26000000, 0x00201f11 }, /* 2,32,2 */ + { 18000000, 26000000, 0x00203f21 }, /* 2,64,4 */ + { 14000000, 26000000, 0x00202620 }, /* 1,39,4 */ + { 10000000, 22000000, 0x00203120 }, /* 1,50,4 */ + { 6500000, 22000000, 0x00204520 }, /* 1,70,4 */ + { 5500000, 22000000, 0x00103f10 }, /* 1,64,2 */ +}; + +enum wm0010_state { + WM0010_POWER_OFF, + WM0010_OUT_OF_RESET, + WM0010_BOOTROM, + WM0010_STAGE2, + WM0010_FIRMWARE, +}; + +struct wm0010_priv { + struct snd_soc_codec *codec; + + struct mutex lock; + struct device *dev; + + struct wm0010_pdata pdata; + + int gpio_reset; + int gpio_reset_value; + + struct regulator_bulk_data core_supplies[2]; + struct regulator *dbvdd; + + int sysclk; + + enum wm0010_state state; + bool boot_failed; + int boot_done; + bool ready; + bool pll_running; + int max_spi_freq; + int board_max_spi_speed; + u32 pll_clkctrl1; + + spinlock_t irq_lock; + int irq; + + struct completion boot_completion; +}; + +struct wm0010_spi_msg { + struct spi_message m; + struct spi_transfer t; + u8 *tx_buf; + u8 *rx_buf; + size_t len; +}; + +static const struct snd_soc_dapm_route wm0010_dapm_routes[] = { + { "SDI2 Playback", NULL, "SDI1 Playback" }, +}; + +static const char *wm0010_state_to_str(enum wm0010_state state) +{ + const char *state_to_str[] = { + "Power off", + "Out of reset", + "Bootrom", + "Stage2", + "Firmware" + }; + + if (state < 0 || state >= ARRAY_SIZE(state_to_str)) + return "null"; + return state_to_str[state]; +} + +/* Called with wm0010->lock held */ +static void wm0010_halt(struct snd_soc_codec *codec) +{ + struct wm0010_priv *wm0010 = snd_soc_codec_get_drvdata(codec); + unsigned long flags; + enum wm0010_state state; + + /* Fetch the wm0010 state */ + spin_lock_irqsave(&wm0010->irq_lock, flags); + state = wm0010->state; + spin_unlock_irqrestore(&wm0010->irq_lock, flags); + + switch (state) { + case WM0010_POWER_OFF: + /* If there's nothing to do, bail out */ + return; + case WM0010_OUT_OF_RESET: + case WM0010_BOOTROM: + case WM0010_STAGE2: + case WM0010_FIRMWARE: + /* Remember to put chip back into reset */ + gpio_set_value(wm0010->gpio_reset, wm0010->gpio_reset_value); + /* Disable the regulators */ + regulator_disable(wm0010->dbvdd); + regulator_bulk_disable(ARRAY_SIZE(wm0010->core_supplies), + wm0010->core_supplies); + break; + } + + spin_lock_irqsave(&wm0010->irq_lock, flags); + wm0010->state = WM0010_POWER_OFF; + spin_unlock_irqrestore(&wm0010->irq_lock, flags); +} + +struct wm0010_boot_xfer { + struct list_head list; + struct snd_soc_codec *codec; + struct completion *done; + struct spi_message m; + struct spi_transfer t; +}; + +/* Called with wm0010->lock held */ +static void wm0010_mark_boot_failure(struct wm0010_priv *wm0010) +{ + enum wm0010_state state; + unsigned long flags; + + spin_lock_irqsave(&wm0010->irq_lock, flags); + state = wm0010->state; + spin_unlock_irqrestore(&wm0010->irq_lock, flags); + + dev_err(wm0010->dev, "Failed to transition from `%s' state to `%s' state\n", + wm0010_state_to_str(state), wm0010_state_to_str(state + 1)); + + wm0010->boot_failed = true; +} + +static void wm0010_boot_xfer_complete(void *data) +{ + struct wm0010_boot_xfer *xfer = data; + struct snd_soc_codec *codec = xfer->codec; + struct wm0010_priv *wm0010 = snd_soc_codec_get_drvdata(codec); + u32 *out32 = xfer->t.rx_buf; + int i; + + if (xfer->m.status != 0) { + dev_err(codec->dev, "SPI transfer failed: %d\n", + xfer->m.status); + wm0010_mark_boot_failure(wm0010); + if (xfer->done) + complete(xfer->done); + return; + } + + for (i = 0; i < xfer->t.len / 4; i++) { + dev_dbg(codec->dev, "%d: %04x\n", i, out32[i]); + + switch (be32_to_cpu(out32[i])) { + case 0xe0e0e0e0: + dev_err(codec->dev, + "%d: ROM error reported in stage 2\n", i); + wm0010_mark_boot_failure(wm0010); + break; + + case 0x55555555: + if (wm0010->boot_done == 0) + break; + dev_err(codec->dev, + "%d: ROM bootloader running in stage 2\n", i); + wm0010_mark_boot_failure(wm0010); + break; + + case 0x0fed0000: + dev_dbg(codec->dev, "Stage2 loader running\n"); + break; + + case 0x0fed0007: + dev_dbg(codec->dev, "CODE_HDR packet received\n"); + break; + + case 0x0fed0008: + dev_dbg(codec->dev, "CODE_DATA packet received\n"); + break; + + case 0x0fed0009: + dev_dbg(codec->dev, "Download complete\n"); + break; + + case 0x0fed000c: + dev_dbg(codec->dev, "Application start\n"); + break; + + case 0x0fed000e: + dev_dbg(codec->dev, "PLL packet received\n"); + wm0010->pll_running = true; + break; + + case 0x0fed0025: + dev_err(codec->dev, "Device reports image too long\n"); + wm0010_mark_boot_failure(wm0010); + break; + + case 0x0fed002c: + dev_err(codec->dev, "Device reports bad SPI packet\n"); + wm0010_mark_boot_failure(wm0010); + break; + + case 0x0fed0031: + dev_err(codec->dev, "Device reports SPI read overflow\n"); + wm0010_mark_boot_failure(wm0010); + break; + + case 0x0fed0032: + dev_err(codec->dev, "Device reports SPI underclock\n"); + wm0010_mark_boot_failure(wm0010); + break; + + case 0x0fed0033: + dev_err(codec->dev, "Device reports bad header packet\n"); + wm0010_mark_boot_failure(wm0010); + break; + + case 0x0fed0034: + dev_err(codec->dev, "Device reports invalid packet type\n"); + wm0010_mark_boot_failure(wm0010); + break; + + case 0x0fed0035: + dev_err(codec->dev, "Device reports data before header error\n"); + wm0010_mark_boot_failure(wm0010); + break; + + case 0x0fed0038: + dev_err(codec->dev, "Device reports invalid PLL packet\n"); + break; + + case 0x0fed003a: + dev_err(codec->dev, "Device reports packet alignment error\n"); + wm0010_mark_boot_failure(wm0010); + break; + + default: + dev_err(codec->dev, "Unrecognised return 0x%x\n", + be32_to_cpu(out32[i])); + wm0010_mark_boot_failure(wm0010); + break; + } + + if (wm0010->boot_failed) + break; + } + + wm0010->boot_done++; + if (xfer->done) + complete(xfer->done); +} + +static void byte_swap_64(u64 *data_in, u64 *data_out, u32 len) +{ + int i; + + for (i = 0; i < len / 8; i++) + data_out[i] = cpu_to_be64(le64_to_cpu(data_in[i])); +} + +static int wm0010_boot(struct snd_soc_codec *codec) +{ + struct spi_device *spi = to_spi_device(codec->dev); + struct wm0010_priv *wm0010 = snd_soc_codec_get_drvdata(codec); + unsigned long flags; + struct list_head xfer_list; + struct wm0010_boot_xfer *xfer; + int ret; + struct completion done; + const struct firmware *fw; + const struct dfw_binrec *rec; + struct spi_message m; + struct spi_transfer t; + struct dfw_pllrec pll_rec; + u32 *img, *p; + u64 *img_swap; + u8 *out; + u32 len, offset; + int i; + + spin_lock_irqsave(&wm0010->irq_lock, flags); + if (wm0010->state != WM0010_POWER_OFF) + dev_warn(wm0010->dev, "DSP already powered up!\n"); + spin_unlock_irqrestore(&wm0010->irq_lock, flags); + + if (wm0010->sysclk > 26000000) { + dev_err(codec->dev, "Max DSP clock frequency is 26MHz\n"); + ret = -ECANCELED; + goto err; + } + + INIT_LIST_HEAD(&xfer_list); + + mutex_lock(&wm0010->lock); + wm0010->pll_running = false; + + dev_dbg(codec->dev, "max_spi_freq: %d\n", wm0010->max_spi_freq); + + ret = regulator_bulk_enable(ARRAY_SIZE(wm0010->core_supplies), + wm0010->core_supplies); + if (ret != 0) { + dev_err(&spi->dev, "Failed to enable core supplies: %d\n", + ret); + mutex_unlock(&wm0010->lock); + goto err; + } + + ret = regulator_enable(wm0010->dbvdd); + if (ret != 0) { + dev_err(&spi->dev, "Failed to enable DBVDD: %d\n", ret); + goto err_core; + } + + /* Release reset */ + gpio_set_value(wm0010->gpio_reset, !wm0010->gpio_reset_value); + spin_lock_irqsave(&wm0010->irq_lock, flags); + wm0010->state = WM0010_OUT_OF_RESET; + spin_unlock_irqrestore(&wm0010->irq_lock, flags); + + /* First the bootloader */ + ret = request_firmware(&fw, "wm0010_stage2.bin", codec->dev); + if (ret != 0) { + dev_err(codec->dev, "Failed to request stage2 loader: %d\n", + ret); + goto abort; + } + + if (!wait_for_completion_timeout(&wm0010->boot_completion, + msecs_to_jiffies(10))) + dev_err(codec->dev, "Failed to get interrupt from DSP\n"); + + spin_lock_irqsave(&wm0010->irq_lock, flags); + wm0010->state = WM0010_BOOTROM; + spin_unlock_irqrestore(&wm0010->irq_lock, flags); + + dev_dbg(codec->dev, "Downloading %d byte stage 2 loader\n", fw->size); + + /* Copy to local buffer first as vmalloc causes problems for dma */ + img = kzalloc(fw->size, GFP_KERNEL); + if (!img) { + dev_err(codec->dev, "Failed to allocate image buffer\n"); + goto abort; + } + + out = kzalloc(fw->size, GFP_KERNEL); + if (!out) { + dev_err(codec->dev, "Failed to allocate output buffer\n"); + goto abort; + } + + memcpy(img, &fw->data[0], fw->size); + + spi_message_init(&m); + memset(&t, 0, sizeof(t)); + t.rx_buf = out; + t.tx_buf = img; + t.len = fw->size; + t.bits_per_word = 8; + t.speed_hz = wm0010->sysclk / 10; + spi_message_add_tail(&t, &m); + + dev_dbg(codec->dev, "Starting initial download at %dHz\n", + t.speed_hz); + + ret = spi_sync(spi, &m); + if (ret != 0) { + dev_err(codec->dev, "Initial download failed: %d\n", ret); + goto abort; + } + + /* Look for errors from the boot ROM */ + for (i = 0; i < fw->size; i++) { + if (out[i] != 0x55) { + ret = -EBUSY; + dev_err(codec->dev, "Boot ROM error: %x in %d\n", + out[i], i); + wm0010_mark_boot_failure(wm0010); + goto abort; + } + } + + release_firmware(fw); + kfree(img); + kfree(out); + + if (!wait_for_completion_timeout(&wm0010->boot_completion, + msecs_to_jiffies(10))) + dev_err(codec->dev, "Failed to get interrupt from DSP loader.\n"); + + spin_lock_irqsave(&wm0010->irq_lock, flags); + wm0010->state = WM0010_STAGE2; + spin_unlock_irqrestore(&wm0010->irq_lock, flags); + + /* Only initialise PLL if max_spi_freq initialised */ + if (wm0010->max_spi_freq) { + + /* Initialise a PLL record */ + memset(&pll_rec, 0, sizeof(pll_rec)); + pll_rec.command = DFW_CMD_PLL; + pll_rec.length = (sizeof(pll_rec) - 8); + + /* On wm0010 only the CLKCTRL1 value is used */ + pll_rec.clkctrl1 = wm0010->pll_clkctrl1; + + len = pll_rec.length + 8; + out = kzalloc(len, GFP_KERNEL); + if (!out) { + dev_err(codec->dev, + "Failed to allocate RX buffer\n"); + goto abort; + } + + img_swap = kzalloc(len, GFP_KERNEL); + if (!img_swap) { + dev_err(codec->dev, + "Failed to allocate image buffer\n"); + goto abort; + } + + /* We need to re-order for 0010 */ + byte_swap_64((u64 *)&pll_rec, img_swap, len); + + spi_message_init(&m); + memset(&t, 0, sizeof(t)); + t.rx_buf = out; + t.tx_buf = img_swap; + t.len = len; + t.bits_per_word = 8; + t.speed_hz = wm0010->sysclk / 6; + spi_message_add_tail(&t, &m); + + ret = spi_sync(spi, &m); + if (ret != 0) { + dev_err(codec->dev, "First PLL write failed: %d\n", ret); + goto abort; + } + + /* Use a second send of the message to get the return status */ + ret = spi_sync(spi, &m); + if (ret != 0) { + dev_err(codec->dev, "Second PLL write failed: %d\n", ret); + goto abort; + } + + p = (u32 *)out; + + /* Look for PLL active code from the DSP */ + for (i = 0; i < len / 4; i++) { + if (*p == 0x0e00ed0f) { + dev_dbg(codec->dev, "PLL packet received\n"); + wm0010->pll_running = true; + break; + } + p++; + } + + kfree(img_swap); + kfree(out); + } else + dev_dbg(codec->dev, "Not enabling DSP PLL."); + + ret = request_firmware(&fw, "wm0010.dfw", codec->dev); + if (ret != 0) { + dev_err(codec->dev, "Failed to request application: %d\n", + ret); + goto abort; + } + + rec = (const struct dfw_binrec *)fw->data; + offset = 0; + wm0010->boot_done = 0; + wm0010->boot_failed = false; + BUG_ON(!list_empty(&xfer_list)); + init_completion(&done); + + /* First record should be INFO */ + if (rec->command != DFW_CMD_INFO) { + dev_err(codec->dev, "First record not INFO\r\n"); + goto abort; + } + + /* Check it's a 0010 file */ + if (rec->data[0] != DEVICE_ID_WM0010) { + dev_err(codec->dev, "Not a WM0010 firmware file.\r\n"); + goto abort; + } + + /* Skip the info record as we don't need to send it */ + offset += ((rec->length) + 8); + rec = (void *)&rec->data[rec->length]; + + while (offset < fw->size) { + dev_dbg(codec->dev, + "Packet: command %d, data length = 0x%x\r\n", + rec->command, rec->length); + len = rec->length + 8; + + out = kzalloc(len, GFP_KERNEL); + if (!out) { + dev_err(codec->dev, + "Failed to allocate RX buffer\n"); + goto abort; + } + + img_swap = kzalloc(len, GFP_KERNEL); + if (!img_swap) { + dev_err(codec->dev, + "Failed to allocate image buffer\n"); + goto abort; + } + + /* We need to re-order for 0010 */ + byte_swap_64((u64 *)&rec->command, img_swap, len); + + xfer = kzalloc(sizeof(*xfer), GFP_KERNEL); + if (!xfer) { + dev_err(codec->dev, "Failed to allocate xfer\n"); + goto abort; + } + + xfer->codec = codec; + list_add_tail(&xfer->list, &xfer_list); + + spi_message_init(&xfer->m); + xfer->m.complete = wm0010_boot_xfer_complete; + xfer->m.context = xfer; + xfer->t.tx_buf = img_swap; + xfer->t.rx_buf = out; + xfer->t.len = len; + xfer->t.bits_per_word = 8; + + if (!wm0010->pll_running) { + xfer->t.speed_hz = wm0010->sysclk / 6; + } else { + xfer->t.speed_hz = wm0010->max_spi_freq; + + if (wm0010->board_max_spi_speed && + (wm0010->board_max_spi_speed < wm0010->max_spi_freq)) + xfer->t.speed_hz = wm0010->board_max_spi_speed; + } + + /* Store max usable spi frequency for later use */ + wm0010->max_spi_freq = xfer->t.speed_hz; + + spi_message_add_tail(&xfer->t, &xfer->m); + + offset += ((rec->length) + 8); + rec = (void *)&rec->data[rec->length]; + + if (offset >= fw->size) { + dev_dbg(codec->dev, "All transfers scheduled\n"); + xfer->done = &done; + } + + ret = spi_async(spi, &xfer->m); + if (ret != 0) { + dev_err(codec->dev, "Write failed: %d\n", ret); + goto abort; + } + + if (wm0010->boot_failed) + goto abort; + } + + wait_for_completion(&done); + + spin_lock_irqsave(&wm0010->irq_lock, flags); + wm0010->state = WM0010_FIRMWARE; + spin_unlock_irqrestore(&wm0010->irq_lock, flags); + + mutex_unlock(&wm0010->lock); + + release_firmware(fw); + + while (!list_empty(&xfer_list)) { + xfer = list_first_entry(&xfer_list, struct wm0010_boot_xfer, + list); + kfree(xfer->t.rx_buf); + kfree(xfer->t.tx_buf); + list_del(&xfer->list); + kfree(xfer); + } + + return 0; + +abort: + /* Put the chip back into reset */ + wm0010_halt(codec); + mutex_unlock(&wm0010->lock); + return ret; +err_core: + regulator_bulk_disable(ARRAY_SIZE(wm0010->core_supplies), + wm0010->core_supplies); +err: + return ret; +} + +static int wm0010_set_bias_level(struct snd_soc_codec *codec, + enum snd_soc_bias_level level) +{ + struct wm0010_priv *wm0010 = snd_soc_codec_get_drvdata(codec); + + switch (level) { + case SND_SOC_BIAS_ON: + if (codec->dapm.bias_level == SND_SOC_BIAS_PREPARE) + wm0010_boot(codec); + break; + case SND_SOC_BIAS_PREPARE: + break; + case SND_SOC_BIAS_STANDBY: + if (codec->dapm.bias_level == SND_SOC_BIAS_PREPARE) { + mutex_lock(&wm0010->lock); + wm0010_halt(codec); + mutex_unlock(&wm0010->lock); + } + break; + case SND_SOC_BIAS_OFF: + break; + } + + codec->dapm.bias_level = level; + + return 0; +} + +static int wm0010_set_sysclk(struct snd_soc_codec *codec, int source, + int clk_id, unsigned int freq, int dir) +{ + struct wm0010_priv *wm0010 = snd_soc_codec_get_drvdata(codec); + unsigned int i; + + wm0010->sysclk = freq; + + if (freq < pll_clock_map[ARRAY_SIZE(pll_clock_map)-1].max_sysclk) { + wm0010->max_spi_freq = 0; + } else { + for (i = 0; i < ARRAY_SIZE(pll_clock_map); i++) + if (freq >= pll_clock_map[i].max_sysclk) + break; + + wm0010->max_spi_freq = pll_clock_map[i].max_pll_spi_speed; + wm0010->pll_clkctrl1 = pll_clock_map[i].pll_clkctrl1; + } + + return 0; +} + +static int wm0010_probe(struct snd_soc_codec *codec); + +static struct snd_soc_codec_driver soc_codec_dev_wm0010 = { + .probe = wm0010_probe, + .set_bias_level = wm0010_set_bias_level, + .set_sysclk = wm0010_set_sysclk, + + .dapm_routes = wm0010_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(wm0010_dapm_routes), +}; + +#define WM0010_RATES (SNDRV_PCM_RATE_48000) +#define WM0010_FORMATS (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE |\ + SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE |\ + SNDRV_PCM_FMTBIT_S32_LE) + +static struct snd_soc_dai_driver wm0010_dai[] = { + { + .name = "wm0010-sdi1", + .playback = { + .stream_name = "SDI1 Playback", + .channels_min = 1, + .channels_max = 2, + .rates = WM0010_RATES, + .formats = WM0010_FORMATS, + }, + .capture = { + .stream_name = "SDI1 Capture", + .channels_min = 1, + .channels_max = 2, + .rates = WM0010_RATES, + .formats = WM0010_FORMATS, + }, + }, + { + .name = "wm0010-sdi2", + .playback = { + .stream_name = "SDI2 Playback", + .channels_min = 1, + .channels_max = 2, + .rates = WM0010_RATES, + .formats = WM0010_FORMATS, + }, + .capture = { + .stream_name = "SDI2 Capture", + .channels_min = 1, + .channels_max = 2, + .rates = WM0010_RATES, + .formats = WM0010_FORMATS, + }, + }, +}; + +static irqreturn_t wm0010_irq(int irq, void *data) +{ + struct wm0010_priv *wm0010 = data; + + switch (wm0010->state) { + case WM0010_POWER_OFF: + case WM0010_OUT_OF_RESET: + case WM0010_BOOTROM: + case WM0010_STAGE2: + spin_lock(&wm0010->irq_lock); + complete(&wm0010->boot_completion); + spin_unlock(&wm0010->irq_lock); + return IRQ_HANDLED; + default: + return IRQ_NONE; + } + + return IRQ_NONE; +} + +static int wm0010_probe(struct snd_soc_codec *codec) +{ + struct wm0010_priv *wm0010 = snd_soc_codec_get_drvdata(codec); + struct spi_device *spi = to_spi_device(wm0010->dev); + unsigned long flags; + unsigned long gpio_flags; + int ret; + int trigger; + int irq; + + wm0010->codec = codec; + + init_completion(&wm0010->boot_completion); + + wm0010->core_supplies[0].supply = "AVDD"; + wm0010->core_supplies[1].supply = "DCVDD"; + ret = devm_regulator_bulk_get(wm0010->dev, ARRAY_SIZE(wm0010->core_supplies), + wm0010->core_supplies); + if (ret != 0) { + dev_err(wm0010->dev, "Failed to obtain core supplies: %d\n", + ret); + return ret; + } + + wm0010->dbvdd = devm_regulator_get(wm0010->dev, "DBVDD"); + if (IS_ERR(wm0010->dbvdd)) { + ret = PTR_ERR(wm0010->dbvdd); + dev_err(wm0010->dev, "Failed to obtain DBVDD: %d\n", ret); + return ret; + } + + if (wm0010->pdata.gpio_reset) { + wm0010->gpio_reset = wm0010->pdata.gpio_reset; + + if (wm0010->pdata.reset_active_high) + wm0010->gpio_reset_value = 1; + else + wm0010->gpio_reset_value = 0; + + if (wm0010->gpio_reset_value) + gpio_flags = GPIOF_OUT_INIT_HIGH; + else + gpio_flags = GPIOF_OUT_INIT_LOW; + + ret = devm_gpio_request_one(wm0010->dev, wm0010->gpio_reset, + gpio_flags, "wm0010 reset"); + if (ret < 0) { + dev_err(wm0010->dev, + "Failed to request GPIO for DSP reset: %d\n", + ret); + return ret; + } + } else { + dev_err(wm0010->dev, "No reset GPIO configured\n"); + return ret; + } + + irq = spi->irq; + if (wm0010->pdata.irq_flags) + trigger = wm0010->pdata.irq_flags; + else + trigger = IRQF_TRIGGER_FALLING; + trigger |= IRQF_ONESHOT; + + ret = request_threaded_irq(irq, NULL, wm0010_irq, trigger, + "wm0010", wm0010); + if (ret) + dev_err(wm0010->dev, "Failed to request IRQ %d: %d\n", + irq, ret); + wm0010->irq = irq; + + if (spi->max_speed_hz) + wm0010->board_max_spi_speed = spi->max_speed_hz; + else + wm0010->board_max_spi_speed = 0; + + spin_lock_irqsave(&wm0010->irq_lock, flags); + wm0010->state = WM0010_POWER_OFF; + spin_unlock_irqrestore(&wm0010->irq_lock, flags); + + return 0; +} + +static int __devinit wm0010_spi_probe(struct spi_device *spi) +{ + struct wm0010_priv *wm0010; + int ret; + + wm0010 = devm_kzalloc(&spi->dev, sizeof(*wm0010), + GFP_KERNEL); + if (!wm0010) + return -ENOMEM; + + mutex_init(&wm0010->lock); + spin_lock_init(&wm0010->irq_lock); + + spi_set_drvdata(spi, wm0010); + wm0010->dev = &spi->dev; + + if (dev_get_platdata(&spi->dev)) + memcpy(&wm0010->pdata, dev_get_platdata(&spi->dev), + sizeof(wm0010->pdata)); + + ret = snd_soc_register_codec(&spi->dev, + &soc_codec_dev_wm0010, wm0010_dai, + ARRAY_SIZE(wm0010_dai)); + if (ret < 0) + return ret; + + return 0; +} + +static int __devexit wm0010_spi_remove(struct spi_device *spi) +{ + struct wm0010_priv *wm0010 = spi_get_drvdata(spi); + + snd_soc_unregister_codec(&spi->dev); + + if (wm0010->gpio_reset) { + /* Remember to put chip back into reset */ + gpio_set_value(wm0010->gpio_reset, wm0010->gpio_reset_value); + gpio_free(wm0010->gpio_reset); + } + + if (wm0010->irq) + free_irq(wm0010->irq, wm0010); + + return 0; +} + +static struct spi_driver wm0010_spi_driver = { + .driver = { + .name = "wm0010", + .bus = &spi_bus_type, + .owner = THIS_MODULE, + }, + .probe = wm0010_spi_probe, + .remove = __devexit_p(wm0010_spi_remove), +}; + +module_spi_driver(wm0010_spi_driver); + +MODULE_DESCRIPTION("ASoC WM0010 driver"); +MODULE_AUTHOR("Mark Brown "); +MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 1549c34bfdf3dc29b769c803f6cfdc53dfc67f93 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 23 Aug 2012 17:50:52 +0100 Subject: ASoC: wm0010: Fix passthrough routing Signed-off-by: Mark Brown --- sound/soc/codecs/wm0010.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/wm0010.c b/sound/soc/codecs/wm0010.c index 8e0b6d6bffaf..e1315e0e7856 100644 --- a/sound/soc/codecs/wm0010.c +++ b/sound/soc/codecs/wm0010.c @@ -119,7 +119,8 @@ struct wm0010_spi_msg { }; static const struct snd_soc_dapm_route wm0010_dapm_routes[] = { - { "SDI2 Playback", NULL, "SDI1 Playback" }, + { "SDI2 Capture", NULL, "SDI1 Playback" }, + { "SDI1 Capture", NULL, "SDI2 Playback" }, }; static const char *wm0010_state_to_str(enum wm0010_state state) -- cgit v1.2.3 From f9372c9c06166dc24a17cf25d325d83a9a06a02d Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 23 Aug 2012 17:05:48 +0100 Subject: ASoC: samsung: Add hookup of WM0010 on Speyside The Speyside platform by default has a WM0010 fitted. Now that we have a public driver hook it up in the machine integration. Signed-off-by: Mark Brown --- sound/soc/samsung/Kconfig | 1 + sound/soc/samsung/speyside.c | 42 +++++++++++++++++++++++++++++++++++++----- 2 files changed, 38 insertions(+), 5 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/samsung/Kconfig b/sound/soc/samsung/Kconfig index fb5600083612..f17dd25e0f4a 100644 --- a/sound/soc/samsung/Kconfig +++ b/sound/soc/samsung/Kconfig @@ -191,6 +191,7 @@ config SND_SOC_SPEYSIDE select SND_SAMSUNG_I2S select SND_SOC_WM8996 select SND_SOC_WM9081 + select SND_SOC_WM0010 select SND_SOC_WM1250_EV1 config SND_SOC_TOBERMORY diff --git a/sound/soc/samsung/speyside.c b/sound/soc/samsung/speyside.c index a4a9fc7e8c76..c7e1c28528a4 100644 --- a/sound/soc/samsung/speyside.c +++ b/sound/soc/samsung/speyside.c @@ -25,7 +25,7 @@ static int speyside_set_bias_level(struct snd_soc_card *card, struct snd_soc_dapm_context *dapm, enum snd_soc_bias_level level) { - struct snd_soc_dai *codec_dai = card->rtd[0].codec_dai; + struct snd_soc_dai *codec_dai = card->rtd[1].codec_dai; int ret; if (dapm->dev != codec_dai->dev) @@ -57,7 +57,7 @@ static int speyside_set_bias_level_post(struct snd_soc_card *card, struct snd_soc_dapm_context *dapm, enum snd_soc_bias_level level) { - struct snd_soc_dai *codec_dai = card->rtd[0].codec_dai; + struct snd_soc_dai *codec_dai = card->rtd[1].codec_dai; int ret; if (dapm->dev != codec_dai->dev) @@ -126,6 +126,18 @@ static void speyside_set_polarity(struct snd_soc_codec *codec, snd_soc_dapm_sync(&codec->dapm); } +static int speyside_wm0010_init(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_soc_dai *dai = rtd->codec_dai; + int ret; + + ret = snd_soc_dai_set_sysclk(dai, 0, MCLK_AUDIO_RATE, 0); + if (ret < 0) + return ret; + + return 0; +} + static int speyside_wm8996_init(struct snd_soc_pcm_runtime *rtd) { struct snd_soc_dai *dai = rtd->codec_dai; @@ -172,17 +184,37 @@ static int speyside_late_probe(struct snd_soc_card *card) return 0; } +static const struct snd_soc_pcm_stream dsp_codec_params = { + .formats = SNDRV_PCM_FMTBIT_S32_LE, + .rate_min = 48000, + .rate_max = 48000, + .channels_min = 2, + .channels_max = 2, +}; + static struct snd_soc_dai_link speyside_dai[] = { { - .name = "CPU", - .stream_name = "CPU", + .name = "CPU-DSP", + .stream_name = "CPU-DSP", .cpu_dai_name = "samsung-i2s.0", - .codec_dai_name = "wm8996-aif1", + .codec_dai_name = "wm0010-sdi1", .platform_name = "samsung-audio", + .codec_name = "spi0.0", + .init = speyside_wm0010_init, + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF + | SND_SOC_DAIFMT_CBM_CFM, + }, + { + .name = "DSP-CODEC", + .stream_name = "DSP-CODEC", + .cpu_dai_name = "wm0010-sdi2", + .codec_dai_name = "wm8996-aif1", .codec_name = "wm8996.1-001a", .init = speyside_wm8996_init, .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM, + .params = &dsp_codec_params, + .ignore_suspend = 1, }, { .name = "Baseband", -- cgit v1.2.3 From 6df3198635e2ad961952566a05994bc592abe774 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Sat, 25 Aug 2012 14:05:35 +0100 Subject: ASoC: wm0010: Enable 44.1kHz support With appropriate clocking configuration the WM0010 driver supports 44.1kHz audio; enable that. Signed-off-by: Mark Brown --- sound/soc/codecs/wm0010.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/wm0010.c b/sound/soc/codecs/wm0010.c index e1315e0e7856..f820b5725163 100644 --- a/sound/soc/codecs/wm0010.c +++ b/sound/soc/codecs/wm0010.c @@ -722,7 +722,7 @@ static struct snd_soc_codec_driver soc_codec_dev_wm0010 = { .num_dapm_routes = ARRAY_SIZE(wm0010_dapm_routes), }; -#define WM0010_RATES (SNDRV_PCM_RATE_48000) +#define WM0010_RATES (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000) #define WM0010_FORMATS (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE |\ SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE |\ SNDRV_PCM_FMTBIT_S32_LE) -- cgit v1.2.3 From 1470bfacb675ab0e25c30c97772a764ca16e0e52 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Sat, 25 Aug 2012 09:17:42 -0700 Subject: ASoC: wm0010: Add dummy widget for CLKIN Make it easier to integrate the management of the clock supplying the WM0010 with DAPM by providing a dummy supply widget which supplies the interface widgets, this can be connected to clock outputs by the machines. Signed-off-by: Mark Brown --- sound/soc/codecs/wm0010.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'sound/soc') diff --git a/sound/soc/codecs/wm0010.c b/sound/soc/codecs/wm0010.c index f820b5725163..b6f7097d7953 100644 --- a/sound/soc/codecs/wm0010.c +++ b/sound/soc/codecs/wm0010.c @@ -118,9 +118,18 @@ struct wm0010_spi_msg { size_t len; }; +static const struct snd_soc_dapm_widget wm0010_dapm_widgets[] = { +SND_SOC_DAPM_SUPPLY("CLKIN", SND_SOC_NOPM, 0, 0, NULL, 0), +}; + static const struct snd_soc_dapm_route wm0010_dapm_routes[] = { { "SDI2 Capture", NULL, "SDI1 Playback" }, { "SDI1 Capture", NULL, "SDI2 Playback" }, + + { "SDI1 Capture", NULL, "CLKIN" }, + { "SDI2 Capture", NULL, "CLKIN" }, + { "SDI1 Playback", NULL, "CLKIN" }, + { "SDI2 Playback", NULL, "CLKIN" }, }; static const char *wm0010_state_to_str(enum wm0010_state state) @@ -718,6 +727,8 @@ static struct snd_soc_codec_driver soc_codec_dev_wm0010 = { .set_bias_level = wm0010_set_bias_level, .set_sysclk = wm0010_set_sysclk, + .dapm_widgets = wm0010_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(wm0010_dapm_widgets), .dapm_routes = wm0010_dapm_routes, .num_dapm_routes = ARRAY_SIZE(wm0010_dapm_routes), }; -- cgit v1.2.3 From d3fd716e82ed643d804c49ca9ca554079c429a5c Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Sat, 25 Aug 2012 09:23:40 -0700 Subject: ASoC: wm0010: Set idle_bias_off Doesn't make any practical difference given that _SUSPEND and _OFF are equivalent for the driver but it's what we're really doing. Signed-off-by: Mark Brown --- sound/soc/codecs/wm0010.c | 1 + 1 file changed, 1 insertion(+) (limited to 'sound/soc') diff --git a/sound/soc/codecs/wm0010.c b/sound/soc/codecs/wm0010.c index b6f7097d7953..61ec7633fe5a 100644 --- a/sound/soc/codecs/wm0010.c +++ b/sound/soc/codecs/wm0010.c @@ -726,6 +726,7 @@ static struct snd_soc_codec_driver soc_codec_dev_wm0010 = { .probe = wm0010_probe, .set_bias_level = wm0010_set_bias_level, .set_sysclk = wm0010_set_sysclk, + .idle_bias_off = true, .dapm_widgets = wm0010_dapm_widgets, .num_dapm_widgets = ARRAY_SIZE(wm0010_dapm_widgets), -- cgit v1.2.3 From 4f3c3c1b32bb8fddcd7f626c2fb09d55f469f976 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Sat, 25 Aug 2012 09:24:16 -0700 Subject: ASoC: wm0010: Don't double free reset GPIO We are using devm_ to allocate the GPIO so it will be freed automatically. Signed-off-by: Mark Brown --- sound/soc/codecs/wm0010.c | 1 - 1 file changed, 1 deletion(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/wm0010.c b/sound/soc/codecs/wm0010.c index 61ec7633fe5a..6c4a2fa90fbe 100644 --- a/sound/soc/codecs/wm0010.c +++ b/sound/soc/codecs/wm0010.c @@ -917,7 +917,6 @@ static int __devexit wm0010_spi_remove(struct spi_device *spi) if (wm0010->gpio_reset) { /* Remember to put chip back into reset */ gpio_set_value(wm0010->gpio_reset, wm0010->gpio_reset_value); - gpio_free(wm0010->gpio_reset); } if (wm0010->irq) -- cgit v1.2.3 From bf9d323722845c8643287dca436e04e34cb21bb8 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Sat, 25 Aug 2012 13:01:15 -0700 Subject: ASoC: wm0010: Tweak diagnostic output Make it scan better by writing ROM with capitals. Signed-off-by: Mark Brown --- sound/soc/codecs/wm0010.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/wm0010.c b/sound/soc/codecs/wm0010.c index 6c4a2fa90fbe..30ec0bd85307 100644 --- a/sound/soc/codecs/wm0010.c +++ b/sound/soc/codecs/wm0010.c @@ -137,7 +137,7 @@ static const char *wm0010_state_to_str(enum wm0010_state state) const char *state_to_str[] = { "Power off", "Out of reset", - "Bootrom", + "Boot ROM", "Stage2", "Firmware" }; -- cgit v1.2.3 From 32c50a31aad77e8faf2718d149da13f2136c1b46 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Sat, 25 Aug 2012 13:04:04 -0700 Subject: ASoC: wm0010: Move resource acquisition to device probe This is more idimatic for modern drivers. Also fix a couple of return codes while we're at it. Signed-off-by: Mark Brown --- sound/soc/codecs/wm0010.c | 54 +++++++++++++++++++++++------------------------ 1 file changed, 27 insertions(+), 27 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/wm0010.c b/sound/soc/codecs/wm0010.c index 30ec0bd85307..5f99148447e1 100644 --- a/sound/soc/codecs/wm0010.c +++ b/sound/soc/codecs/wm0010.c @@ -799,14 +799,35 @@ static irqreturn_t wm0010_irq(int irq, void *data) static int wm0010_probe(struct snd_soc_codec *codec) { struct wm0010_priv *wm0010 = snd_soc_codec_get_drvdata(codec); - struct spi_device *spi = to_spi_device(wm0010->dev); + + wm0010->codec = codec; + + return 0; +} + +static int __devinit wm0010_spi_probe(struct spi_device *spi) +{ unsigned long flags; unsigned long gpio_flags; int ret; int trigger; int irq; + struct wm0010_priv *wm0010; - wm0010->codec = codec; + wm0010 = devm_kzalloc(&spi->dev, sizeof(*wm0010), + GFP_KERNEL); + if (!wm0010) + return -ENOMEM; + + mutex_init(&wm0010->lock); + spin_lock_init(&wm0010->irq_lock); + + spi_set_drvdata(spi, wm0010); + wm0010->dev = &spi->dev; + + if (dev_get_platdata(&spi->dev)) + memcpy(&wm0010->pdata, dev_get_platdata(&spi->dev), + sizeof(wm0010->pdata)); init_completion(&wm0010->boot_completion); @@ -850,7 +871,7 @@ static int wm0010_probe(struct snd_soc_codec *codec) } } else { dev_err(wm0010->dev, "No reset GPIO configured\n"); - return ret; + return -EINVAL; } irq = spi->irq; @@ -862,9 +883,11 @@ static int wm0010_probe(struct snd_soc_codec *codec) ret = request_threaded_irq(irq, NULL, wm0010_irq, trigger, "wm0010", wm0010); - if (ret) + if (ret) { dev_err(wm0010->dev, "Failed to request IRQ %d: %d\n", irq, ret); + return ret; + } wm0010->irq = irq; if (spi->max_speed_hz) @@ -876,29 +899,6 @@ static int wm0010_probe(struct snd_soc_codec *codec) wm0010->state = WM0010_POWER_OFF; spin_unlock_irqrestore(&wm0010->irq_lock, flags); - return 0; -} - -static int __devinit wm0010_spi_probe(struct spi_device *spi) -{ - struct wm0010_priv *wm0010; - int ret; - - wm0010 = devm_kzalloc(&spi->dev, sizeof(*wm0010), - GFP_KERNEL); - if (!wm0010) - return -ENOMEM; - - mutex_init(&wm0010->lock); - spin_lock_init(&wm0010->irq_lock); - - spi_set_drvdata(spi, wm0010); - wm0010->dev = &spi->dev; - - if (dev_get_platdata(&spi->dev)) - memcpy(&wm0010->pdata, dev_get_platdata(&spi->dev), - sizeof(wm0010->pdata)); - ret = snd_soc_register_codec(&spi->dev, &soc_codec_dev_wm0010, wm0010_dai, ARRAY_SIZE(wm0010_dai)); -- cgit v1.2.3 From 28739dfcffaad629b28cbab947193b259f745ea9 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Wed, 22 Aug 2012 13:11:40 +0300 Subject: ASoC: omap-mcbsp: Check mcbsp->id instead of cpu_dai->id when adding ST controls In ddevice tree booted kernel all device have unique name and their device id is set to 0. Use the mcbsp->id for checking to decide which control set we should add for McBSP sidetone handling. Signed-off-by: Peter Ujfalusi Acked-by: Jarkko Nikula Signed-off-by: Mark Brown --- sound/soc/omap/omap-mcbsp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound/soc') diff --git a/sound/soc/omap/omap-mcbsp.c b/sound/soc/omap/omap-mcbsp.c index 2e1750e2ab31..20d30c9ae573 100644 --- a/sound/soc/omap/omap-mcbsp.c +++ b/sound/soc/omap/omap-mcbsp.c @@ -722,7 +722,7 @@ int omap_mcbsp_st_add_controls(struct snd_soc_pcm_runtime *rtd) if (!mcbsp->st_data) return -ENODEV; - switch (cpu_dai->id) { + switch (mcbsp->id) { case 2: /* McBSP 2 */ return snd_soc_add_dai_controls(cpu_dai, omap_mcbsp2_st_controls, -- cgit v1.2.3 From 8a88df4cda5eaed97e027f9c9e76012a7113bf9a Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Wed, 22 Aug 2012 13:11:41 +0300 Subject: ASoC: omap-mcbsp: Only print warning if the st_data is missing for the port When asked to add the ST controls warn only if the st_data is missing. In this way we do not block the otherwise functional card to probe. Signed-off-by: Peter Ujfalusi Acked-by: Jarkko Nikula Signed-off-by: Mark Brown --- sound/soc/omap/omap-mcbsp.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/omap/omap-mcbsp.c b/sound/soc/omap/omap-mcbsp.c index 20d30c9ae573..c1f466e1b8b6 100644 --- a/sound/soc/omap/omap-mcbsp.c +++ b/sound/soc/omap/omap-mcbsp.c @@ -719,8 +719,10 @@ int omap_mcbsp_st_add_controls(struct snd_soc_pcm_runtime *rtd) struct snd_soc_dai *cpu_dai = rtd->cpu_dai; struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai); - if (!mcbsp->st_data) - return -ENODEV; + if (!mcbsp->st_data) { + dev_warn(mcbsp->dev, "No sidetone data for port\n"); + return 0; + } switch (mcbsp->id) { case 2: /* McBSP 2 */ -- cgit v1.2.3 From 8996a31c58374742dfb555675a8569617572d82c Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Wed, 22 Aug 2012 13:11:42 +0300 Subject: ASoC: omap-mcbsp: Use macro to create the McBSP2/3 ST controls To remove duplicated code from the driver. Signed-off-by: Peter Ujfalusi Acked-by: Jarkko Nikula Signed-off-by: Mark Brown --- sound/soc/omap/omap-mcbsp.c | 39 +++++++++++++++------------------------ 1 file changed, 15 insertions(+), 24 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/omap/omap-mcbsp.c b/sound/soc/omap/omap-mcbsp.c index c1f466e1b8b6..1b9f5ebba44f 100644 --- a/sound/soc/omap/omap-mcbsp.c +++ b/sound/soc/omap/omap-mcbsp.c @@ -688,31 +688,22 @@ static int omap_mcbsp_st_get_mode(struct snd_kcontrol *kcontrol, return 0; } -static const struct snd_kcontrol_new omap_mcbsp2_st_controls[] = { - SOC_SINGLE_EXT("McBSP2 Sidetone Switch", 1, 0, 1, 0, - omap_mcbsp_st_get_mode, omap_mcbsp_st_put_mode), - OMAP_MCBSP_SOC_SINGLE_S16_EXT("McBSP2 Sidetone Channel 0 Volume", - -32768, 32767, - omap_mcbsp_get_st_ch0_volume, - omap_mcbsp_set_st_ch0_volume), - OMAP_MCBSP_SOC_SINGLE_S16_EXT("McBSP2 Sidetone Channel 1 Volume", - -32768, 32767, - omap_mcbsp_get_st_ch1_volume, - omap_mcbsp_set_st_ch1_volume), -}; +#define OMAP_MCBSP_ST_CONTROLS(port) \ +static const struct snd_kcontrol_new omap_mcbsp##port##_st_controls[] = { \ +SOC_SINGLE_EXT("McBSP" #port " Sidetone Switch", 1, 0, 1, 0, \ + omap_mcbsp_st_get_mode, omap_mcbsp_st_put_mode), \ +OMAP_MCBSP_SOC_SINGLE_S16_EXT("McBSP" #port " Sidetone Channel 0 Volume", \ + -32768, 32767, \ + omap_mcbsp_get_st_ch0_volume, \ + omap_mcbsp_set_st_ch0_volume), \ +OMAP_MCBSP_SOC_SINGLE_S16_EXT("McBSP" #port " Sidetone Channel 1 Volume", \ + -32768, 32767, \ + omap_mcbsp_get_st_ch1_volume, \ + omap_mcbsp_set_st_ch1_volume), \ +} -static const struct snd_kcontrol_new omap_mcbsp3_st_controls[] = { - SOC_SINGLE_EXT("McBSP3 Sidetone Switch", 2, 0, 1, 0, - omap_mcbsp_st_get_mode, omap_mcbsp_st_put_mode), - OMAP_MCBSP_SOC_SINGLE_S16_EXT("McBSP3 Sidetone Channel 0 Volume", - -32768, 32767, - omap_mcbsp_get_st_ch0_volume, - omap_mcbsp_set_st_ch0_volume), - OMAP_MCBSP_SOC_SINGLE_S16_EXT("McBSP3 Sidetone Channel 1 Volume", - -32768, 32767, - omap_mcbsp_get_st_ch1_volume, - omap_mcbsp_set_st_ch1_volume), -}; +OMAP_MCBSP_ST_CONTROLS(2); +OMAP_MCBSP_ST_CONTROLS(3); int omap_mcbsp_st_add_controls(struct snd_soc_pcm_runtime *rtd) { -- cgit v1.2.3 From db61550931957ee6c7dba751662919424b4344f3 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Wed, 22 Aug 2012 13:11:43 +0300 Subject: ASoC: omap-mcbsp: Single macro for st channel volume set/get Since we always need to have set and get callbacks for McBSP sidetone it makes sense to combine the two macro to create the two callbacks. Signed-off-by: Peter Ujfalusi Signed-off-by: Mark Brown --- sound/soc/omap/omap-mcbsp.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/omap/omap-mcbsp.c b/sound/soc/omap/omap-mcbsp.c index 1b9f5ebba44f..9dff177cd4e2 100644 --- a/sound/soc/omap/omap-mcbsp.c +++ b/sound/soc/omap/omap-mcbsp.c @@ -619,9 +619,9 @@ static int omap_mcbsp_st_info_volsw(struct snd_kcontrol *kcontrol, return 0; } -#define OMAP_MCBSP_ST_SET_CHANNEL_VOLUME(channel) \ +#define OMAP_MCBSP_ST_CHANNEL_VOLUME(channel) \ static int \ -omap_mcbsp_set_st_ch##channel##_volume(struct snd_kcontrol *kc, \ +omap_mcbsp_set_st_ch##channel##_volume(struct snd_kcontrol *kc, \ struct snd_ctl_elem_value *uc) \ { \ struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kc); \ @@ -637,11 +637,10 @@ omap_mcbsp_set_st_ch##channel##_volume(struct snd_kcontrol *kc, \ \ /* OMAP McBSP implementation uses index values 0..4 */ \ return omap_st_set_chgain(mcbsp, channel, val); \ -} - -#define OMAP_MCBSP_ST_GET_CHANNEL_VOLUME(channel) \ +} \ + \ static int \ -omap_mcbsp_get_st_ch##channel##_volume(struct snd_kcontrol *kc, \ +omap_mcbsp_get_st_ch##channel##_volume(struct snd_kcontrol *kc, \ struct snd_ctl_elem_value *uc) \ { \ struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kc); \ @@ -655,10 +654,8 @@ omap_mcbsp_get_st_ch##channel##_volume(struct snd_kcontrol *kc, \ return 0; \ } -OMAP_MCBSP_ST_SET_CHANNEL_VOLUME(0) -OMAP_MCBSP_ST_SET_CHANNEL_VOLUME(1) -OMAP_MCBSP_ST_GET_CHANNEL_VOLUME(0) -OMAP_MCBSP_ST_GET_CHANNEL_VOLUME(1) +OMAP_MCBSP_ST_CHANNEL_VOLUME(0) +OMAP_MCBSP_ST_CHANNEL_VOLUME(1) static int omap_mcbsp_st_put_mode(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -- cgit v1.2.3 From 9bb280a2eb9f4bc951549dceb1d4e0b0a316eb95 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Mon, 27 Aug 2012 17:00:26 +0530 Subject: ASoC: tlv320aic26: Use module_spi_driver module_spi_driver makes the code simpler by eliminating module_init and module_exit calls. Signed-off-by: Sachin Kamat Signed-off-by: Mark Brown --- sound/soc/codecs/tlv320aic26.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/tlv320aic26.c b/sound/soc/codecs/tlv320aic26.c index 85944e953578..b1f6982c7c9c 100644 --- a/sound/soc/codecs/tlv320aic26.c +++ b/sound/soc/codecs/tlv320aic26.c @@ -444,14 +444,4 @@ static struct spi_driver aic26_spi = { .remove = aic26_spi_remove, }; -static int __init aic26_init(void) -{ - return spi_register_driver(&aic26_spi); -} -module_init(aic26_init); - -static void __exit aic26_exit(void) -{ - spi_unregister_driver(&aic26_spi); -} -module_exit(aic26_exit); +module_spi_driver(aic26_spi); -- cgit v1.2.3 From a5c8878017dd3b51f6f97a36d90c405f8061fe83 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Mon, 27 Aug 2012 17:00:27 +0530 Subject: ASoC: wm8770: Use module_spi_driver module_spi_driver makes the code simpler by eliminating module_init and module_exit calls. Signed-off-by: Sachin Kamat Signed-off-by: Mark Brown --- sound/soc/codecs/wm8770.c | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/wm8770.c b/sound/soc/codecs/wm8770.c index a5127b4ff9e1..c7c0034d3966 100644 --- a/sound/soc/codecs/wm8770.c +++ b/sound/soc/codecs/wm8770.c @@ -724,24 +724,7 @@ static struct spi_driver wm8770_spi_driver = { .remove = __devexit_p(wm8770_spi_remove) }; -static int __init wm8770_modinit(void) -{ - int ret = 0; - - ret = spi_register_driver(&wm8770_spi_driver); - if (ret) { - printk(KERN_ERR "Failed to register wm8770 SPI driver: %d\n", - ret); - } - return ret; -} -module_init(wm8770_modinit); - -static void __exit wm8770_exit(void) -{ - spi_unregister_driver(&wm8770_spi_driver); -} -module_exit(wm8770_exit); +module_spi_driver(wm8770_spi_driver); MODULE_DESCRIPTION("ASoC WM8770 driver"); MODULE_AUTHOR("Dimitris Papastamos "); -- cgit v1.2.3 From 2a9a9c876fd6486978a24cd8bc72bd1aeb228b7b Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Mon, 27 Aug 2012 17:00:28 +0530 Subject: ASoC: ad1836: Use module_spi_driver module_spi_driver makes the code simpler by eliminating module_init and module_exit calls. Signed-off-by: Sachin Kamat Signed-off-by: Mark Brown --- sound/soc/codecs/ad1836.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/ad1836.c b/sound/soc/codecs/ad1836.c index c67b50d8b317..ae1eb51bc9da 100644 --- a/sound/soc/codecs/ad1836.c +++ b/sound/soc/codecs/ad1836.c @@ -379,17 +379,7 @@ static struct spi_driver ad1836_spi_driver = { .id_table = ad1836_ids, }; -static int __init ad1836_init(void) -{ - return spi_register_driver(&ad1836_spi_driver); -} -module_init(ad1836_init); - -static void __exit ad1836_exit(void) -{ - spi_unregister_driver(&ad1836_spi_driver); -} -module_exit(ad1836_exit); +module_spi_driver(ad1836_spi_driver); MODULE_DESCRIPTION("ASoC ad1836 driver"); MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>"); -- cgit v1.2.3 From c24fdc886fde9ce7bda8115b9c2b338818796c65 Mon Sep 17 00:00:00 2001 From: "Hebbar, Gururaja" Date: Mon, 27 Aug 2012 18:56:44 +0530 Subject: ASoC: tlv320aic3x: Add device tree bindings Device tree support for tlv320aic3x CODEC driver. Signed-off-by: Hebbar, Gururaja Signed-off-by: Mark Brown --- .../devicetree/bindings/sound/tlv320aic3x.txt | 20 ++++++++++++++ sound/soc/codecs/tlv320aic3x.c | 31 ++++++++++++++++++++++ 2 files changed, 51 insertions(+) create mode 100644 Documentation/devicetree/bindings/sound/tlv320aic3x.txt (limited to 'sound/soc') diff --git a/Documentation/devicetree/bindings/sound/tlv320aic3x.txt b/Documentation/devicetree/bindings/sound/tlv320aic3x.txt new file mode 100644 index 000000000000..e7b98f41fa5f --- /dev/null +++ b/Documentation/devicetree/bindings/sound/tlv320aic3x.txt @@ -0,0 +1,20 @@ +Texas Instruments - tlv320aic3x Codec module + +The tlv320aic3x serial control bus communicates through I2C protocols + +Required properties: +- compatible - "string" - "ti,tlv320aic3x" +- reg - - I2C slave address + + +Optional properties: + +- gpio-reset - gpio pin number used for codec reset +- ai3x-gpio-func - - AIC3X_GPIO1 & AIC3X_GPIO2 Functionality + +Example: + +tlv320aic3x: tlv320aic3x@1b { + compatible = "ti,tlv320aic3x"; + reg = <0x1b>; +}; diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c index 01485bd51404..5708a973a776 100644 --- a/sound/soc/codecs/tlv320aic3x.c +++ b/sound/soc/codecs/tlv320aic3x.c @@ -40,6 +40,7 @@ #include #include #include +#include #include #include #include @@ -1457,6 +1458,8 @@ static int aic3x_i2c_probe(struct i2c_client *i2c, { struct aic3x_pdata *pdata = i2c->dev.platform_data; struct aic3x_priv *aic3x; + struct aic3x_setup_data *ai3x_setup; + struct device_node *np = i2c->dev.of_node; int ret; aic3x = devm_kzalloc(&i2c->dev, sizeof(struct aic3x_priv), GFP_KERNEL); @@ -1471,6 +1474,25 @@ static int aic3x_i2c_probe(struct i2c_client *i2c, if (pdata) { aic3x->gpio_reset = pdata->gpio_reset; aic3x->setup = pdata->setup; + } else if (np) { + ai3x_setup = devm_kzalloc(&i2c->dev, sizeof(*ai3x_setup), + GFP_KERNEL); + if (ai3x_setup == NULL) { + dev_err(&i2c->dev, "failed to create private data\n"); + return -ENOMEM; + } + + ret = of_get_named_gpio(np, "gpio-reset", 0); + if (ret >= 0) + aic3x->gpio_reset = ret; + else + aic3x->gpio_reset = -1; + + if (of_property_read_u32_array(np, "ai3x-gpio-func", + ai3x_setup->gpio_func, 2) >= 0) { + aic3x->setup = ai3x_setup; + } + } else { aic3x->gpio_reset = -1; } @@ -1488,11 +1510,20 @@ static int aic3x_i2c_remove(struct i2c_client *client) return 0; } +#if defined(CONFIG_OF) +static const struct of_device_id tlv320aic3x_of_match[] = { + { .compatible = "ti,tlv320aic3x", }, + {}, +}; +MODULE_DEVICE_TABLE(of, tlv320aic3x_of_match); +#endif + /* machine i2c codec control layer */ static struct i2c_driver aic3x_i2c_driver = { .driver = { .name = "tlv320aic3x-codec", .owner = THIS_MODULE, + .of_match_table = of_match_ptr(tlv320aic3x_of_match), }, .probe = aic3x_i2c_probe, .remove = aic3x_i2c_remove, -- cgit v1.2.3 From f08095a408bf6489b4a710d794ae6d5475a007ef Mon Sep 17 00:00:00 2001 From: "Hebbar, Gururaja" Date: Mon, 27 Aug 2012 18:56:39 +0530 Subject: ASoC: davinci: davinci-pcm does not need to be a plaform_driver Same as the commit 518de86 (ASoC: tegra: register 'platform' from DAIs, get rid of pdev). It makes davinci-pcm not a platform_driver but helper to register "platform", so that the platform_device for davinci-pcm can be saved completely. Signed-off-by: Hebbar, Gururaja Signed-off-by: Mark Brown --- sound/soc/davinci/davinci-evm.c | 15 ++++++++------- sound/soc/davinci/davinci-i2s.c | 10 ++++++++++ sound/soc/davinci/davinci-mcasp.c | 10 ++++++++++ sound/soc/davinci/davinci-pcm.c | 23 ++++++----------------- sound/soc/davinci/davinci-pcm.h | 3 +++ sound/soc/davinci/davinci-sffsdr.c | 2 +- sound/soc/davinci/davinci-vcif.c | 8 ++++++++ 7 files changed, 46 insertions(+), 25 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/davinci/davinci-evm.c b/sound/soc/davinci/davinci-evm.c index c80c20a89b11..4b37e2ac4685 100644 --- a/sound/soc/davinci/davinci-evm.c +++ b/sound/soc/davinci/davinci-evm.c @@ -159,7 +159,7 @@ static struct snd_soc_dai_link dm6446_evm_dai = { .cpu_dai_name = "davinci-mcbsp", .codec_dai_name = "tlv320aic3x-hifi", .codec_name = "tlv320aic3x-codec.1-001b", - .platform_name = "davinci-pcm-audio", + .platform_name = "davinci-mcbsp", .init = evm_aic3x_init, .ops = &evm_ops, }; @@ -170,7 +170,7 @@ static struct snd_soc_dai_link dm355_evm_dai = { .cpu_dai_name = "davinci-mcbsp.1", .codec_dai_name = "tlv320aic3x-hifi", .codec_name = "tlv320aic3x-codec.1-001b", - .platform_name = "davinci-pcm-audio", + .platform_name = "davinci-mcbsp.1", .init = evm_aic3x_init, .ops = &evm_ops, }; @@ -184,14 +184,15 @@ static struct snd_soc_dai_link dm365_evm_dai = { .init = evm_aic3x_init, .codec_name = "tlv320aic3x-codec.1-0018", .ops = &evm_ops, + .platform_name = "davinci-mcbsp", #elif defined(CONFIG_SND_DM365_VOICE_CODEC) .name = "Voice Codec - CQ93VC", .stream_name = "CQ93", .cpu_dai_name = "davinci-vcif", .codec_dai_name = "cq93vc-hifi", .codec_name = "cq93vc-codec", + .platform_name = "avinci-vcif", #endif - .platform_name = "davinci-pcm-audio", }; static struct snd_soc_dai_link dm6467_evm_dai[] = { @@ -200,7 +201,7 @@ static struct snd_soc_dai_link dm6467_evm_dai[] = { .stream_name = "AIC3X", .cpu_dai_name= "davinci-mcasp.0", .codec_dai_name = "tlv320aic3x-hifi", - .platform_name ="davinci-pcm-audio", + .platform_name = "davinci-mcasp.0", .codec_name = "tlv320aic3x-codec.0-001a", .init = evm_aic3x_init, .ops = &evm_ops, @@ -211,7 +212,7 @@ static struct snd_soc_dai_link dm6467_evm_dai[] = { .cpu_dai_name= "davinci-mcasp.1", .codec_dai_name = "dit-hifi", .codec_name = "spdif_dit", - .platform_name = "davinci-pcm-audio", + .platform_name = "davinci-mcasp.1", .ops = &evm_spdif_ops, }, }; @@ -222,7 +223,7 @@ static struct snd_soc_dai_link da830_evm_dai = { .cpu_dai_name = "davinci-mcasp.1", .codec_dai_name = "tlv320aic3x-hifi", .codec_name = "tlv320aic3x-codec.1-0018", - .platform_name = "davinci-pcm-audio", + .platform_name = "davinci-mcasp.1", .init = evm_aic3x_init, .ops = &evm_ops, }; @@ -233,7 +234,7 @@ static struct snd_soc_dai_link da850_evm_dai = { .cpu_dai_name= "davinci-mcasp.0", .codec_dai_name = "tlv320aic3x-hifi", .codec_name = "tlv320aic3x-codec.1-0018", - .platform_name = "davinci-pcm-audio", + .platform_name = "davinci-mcasp.0", .init = evm_aic3x_init, .ops = &evm_ops, }; diff --git a/sound/soc/davinci/davinci-i2s.c b/sound/soc/davinci/davinci-i2s.c index 0a74b9587a2c..407df7233d6d 100644 --- a/sound/soc/davinci/davinci-i2s.c +++ b/sound/soc/davinci/davinci-i2s.c @@ -732,8 +732,16 @@ static int davinci_i2s_probe(struct platform_device *pdev) if (ret != 0) goto err_release_clk; + ret = davinci_soc_platform_register(&pdev->dev); + if (ret) { + dev_err(&pdev->dev, "register PCM failed: %d\n", ret); + goto err_unregister_dai; + } + return 0; +err_unregister_dai: + snd_soc_unregister_dai(&pdev->dev); err_release_clk: clk_disable(dev->clk); clk_put(dev->clk); @@ -745,6 +753,8 @@ static int davinci_i2s_remove(struct platform_device *pdev) struct davinci_mcbsp_dev *dev = dev_get_drvdata(&pdev->dev); snd_soc_unregister_dai(&pdev->dev); + davinci_soc_platform_unregister(&pdev->dev); + clk_disable(dev->clk); clk_put(dev->clk); dev->clk = NULL; diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c index d919fb8de7a3..8f3c5a4cf537 100644 --- a/sound/soc/davinci/davinci-mcasp.c +++ b/sound/soc/davinci/davinci-mcasp.c @@ -945,8 +945,17 @@ static int davinci_mcasp_probe(struct platform_device *pdev) if (ret != 0) goto err_release_clk; + + ret = davinci_soc_platform_register(&pdev->dev); + if (ret) { + dev_err(&pdev->dev, "register PCM failed: %d\n", ret); + goto err_unregister_dai; + } + return 0; +err_unregister_dai: + snd_soc_unregister_dai(&pdev->dev); err_release_clk: pm_runtime_put_sync(&pdev->dev); pm_runtime_disable(&pdev->dev); @@ -957,6 +966,7 @@ static int davinci_mcasp_remove(struct platform_device *pdev) { snd_soc_unregister_dai(&pdev->dev); + davinci_soc_platform_unregister(&pdev->dev); pm_runtime_put_sync(&pdev->dev); pm_runtime_disable(&pdev->dev); diff --git a/sound/soc/davinci/davinci-pcm.c b/sound/soc/davinci/davinci-pcm.c index 97d77b298968..4b70828beedb 100644 --- a/sound/soc/davinci/davinci-pcm.c +++ b/sound/soc/davinci/davinci-pcm.c @@ -864,28 +864,17 @@ static struct snd_soc_platform_driver davinci_soc_platform = { .pcm_free = davinci_pcm_free, }; -static int __devinit davinci_soc_platform_probe(struct platform_device *pdev) +int davinci_soc_platform_register(struct device *dev) { - return snd_soc_register_platform(&pdev->dev, &davinci_soc_platform); + return snd_soc_register_platform(dev, &davinci_soc_platform); } +EXPORT_SYMBOL_GPL(davinci_soc_platform_register); -static int __devexit davinci_soc_platform_remove(struct platform_device *pdev) +void davinci_soc_platform_unregister(struct device *dev) { - snd_soc_unregister_platform(&pdev->dev); - return 0; + snd_soc_unregister_platform(dev); } - -static struct platform_driver davinci_pcm_driver = { - .driver = { - .name = "davinci-pcm-audio", - .owner = THIS_MODULE, - }, - - .probe = davinci_soc_platform_probe, - .remove = __devexit_p(davinci_soc_platform_remove), -}; - -module_platform_driver(davinci_pcm_driver); +EXPORT_SYMBOL_GPL(davinci_soc_platform_unregister); MODULE_AUTHOR("Vladimir Barinov"); MODULE_DESCRIPTION("TI DAVINCI PCM DMA module"); diff --git a/sound/soc/davinci/davinci-pcm.h b/sound/soc/davinci/davinci-pcm.h index c0d6c9be4b4d..5e5516460461 100644 --- a/sound/soc/davinci/davinci-pcm.h +++ b/sound/soc/davinci/davinci-pcm.h @@ -28,4 +28,7 @@ struct davinci_pcm_dma_params { unsigned int fifo_level; }; +int davinci_soc_platform_register(struct device *dev); +void davinci_soc_platform_unregister(struct device *dev); + #endif diff --git a/sound/soc/davinci/davinci-sffsdr.c b/sound/soc/davinci/davinci-sffsdr.c index f71175b29e38..5be65aae7e0e 100644 --- a/sound/soc/davinci/davinci-sffsdr.c +++ b/sound/soc/davinci/davinci-sffsdr.c @@ -86,7 +86,7 @@ static struct snd_soc_dai_link sffsdr_dai = { .cpu_dai_name = "davinci-mcbsp", .codec_dai_name = "pcm3008-hifi", .codec_name = "pcm3008-codec", - .platform_name = "davinci-pcm-audio", + .platform_name = "davinci-mcbsp", .ops = &sffsdr_ops, }; diff --git a/sound/soc/davinci/davinci-vcif.c b/sound/soc/davinci/davinci-vcif.c index da030ff883d5..07bde2e6f84e 100644 --- a/sound/soc/davinci/davinci-vcif.c +++ b/sound/soc/davinci/davinci-vcif.c @@ -240,12 +240,20 @@ static int davinci_vcif_probe(struct platform_device *pdev) return ret; } + ret = davinci_soc_platform_register(&pdev->dev); + if (ret) { + dev_err(&pdev->dev, "register PCM failed: %d\n", ret); + snd_soc_unregister_dai(&pdev->dev); + return ret; + } + return 0; } static int davinci_vcif_remove(struct platform_device *pdev) { snd_soc_unregister_dai(&pdev->dev); + davinci_soc_platform_unregister(&pdev->dev); return 0; } -- cgit v1.2.3 From 896f66b7de293644e65cf62600e4933af954dcf2 Mon Sep 17 00:00:00 2001 From: "Hebbar, Gururaja" Date: Mon, 27 Aug 2012 18:56:41 +0530 Subject: ASoC/ARM: Davinci: McASP: split asp header into platform and audio specific Davinci McASP header & driver are shared by few OMAP platforms (like TI81xx, AM335x). Splitting asp header into Davinci platform specific header and Audio specific header helps to share them across platforms. Audio specific defines is moved to to common so that the header can be accessed by all related platforms. While here, correct the header usage (remove multiple header re-definitions and unused headers) and remove platform names from structures comments and enum. Also some some coding style errors. Signed-off-by: Hebbar, Gururaja Acked-by: Vaibhav Bedia Signed-off-by: Mark Brown --- arch/arm/mach-davinci/asp.h | 49 +++++++++++ arch/arm/mach-davinci/davinci.h | 3 +- arch/arm/mach-davinci/devices-da8xx.c | 1 + arch/arm/mach-davinci/dm355.c | 2 +- arch/arm/mach-davinci/dm365.c | 2 +- arch/arm/mach-davinci/dm644x.c | 2 +- arch/arm/mach-davinci/dm646x.c | 2 +- arch/arm/mach-davinci/include/mach/asp.h | 137 ----------------------------- arch/arm/mach-davinci/include/mach/da8xx.h | 2 +- include/linux/platform_data/davinci_asp.h | 104 ++++++++++++++++++++++ sound/soc/davinci/davinci-evm.c | 3 - sound/soc/davinci/davinci-i2s.c | 3 +- sound/soc/davinci/davinci-mcasp.h | 3 +- sound/soc/davinci/davinci-pcm.c | 1 - sound/soc/davinci/davinci-pcm.h | 3 +- 15 files changed, 165 insertions(+), 152 deletions(-) create mode 100644 arch/arm/mach-davinci/asp.h delete mode 100644 arch/arm/mach-davinci/include/mach/asp.h create mode 100644 include/linux/platform_data/davinci_asp.h (limited to 'sound/soc') diff --git a/arch/arm/mach-davinci/asp.h b/arch/arm/mach-davinci/asp.h new file mode 100644 index 000000000000..d9b2acd12393 --- /dev/null +++ b/arch/arm/mach-davinci/asp.h @@ -0,0 +1,49 @@ +/* + * TI DaVinci Audio definitions + */ +#ifndef __ASM_ARCH_DAVINCI_ASP_H +#define __ASM_ARCH_DAVINCI_ASP_H + +/* Bases of dm644x and dm355 register banks */ +#define DAVINCI_ASP0_BASE 0x01E02000 +#define DAVINCI_ASP1_BASE 0x01E04000 + +/* Bases of dm365 register banks */ +#define DAVINCI_DM365_ASP0_BASE 0x01D02000 + +/* Bases of dm646x register banks */ +#define DAVINCI_DM646X_MCASP0_REG_BASE 0x01D01000 +#define DAVINCI_DM646X_MCASP1_REG_BASE 0x01D01800 + +/* Bases of da850/da830 McASP0 register banks */ +#define DAVINCI_DA8XX_MCASP0_REG_BASE 0x01D00000 + +/* Bases of da830 McASP1 register banks */ +#define DAVINCI_DA830_MCASP1_REG_BASE 0x01D04000 + +/* EDMA channels of dm644x and dm355 */ +#define DAVINCI_DMA_ASP0_TX 2 +#define DAVINCI_DMA_ASP0_RX 3 +#define DAVINCI_DMA_ASP1_TX 8 +#define DAVINCI_DMA_ASP1_RX 9 + +/* EDMA channels of dm646x */ +#define DAVINCI_DM646X_DMA_MCASP0_AXEVT0 6 +#define DAVINCI_DM646X_DMA_MCASP0_AREVT0 9 +#define DAVINCI_DM646X_DMA_MCASP1_AXEVT1 12 + +/* EDMA channels of da850/da830 McASP0 */ +#define DAVINCI_DA8XX_DMA_MCASP0_AREVT 0 +#define DAVINCI_DA8XX_DMA_MCASP0_AXEVT 1 + +/* EDMA channels of da830 McASP1 */ +#define DAVINCI_DA830_DMA_MCASP1_AREVT 2 +#define DAVINCI_DA830_DMA_MCASP1_AXEVT 3 + +/* Interrupts */ +#define DAVINCI_ASP0_RX_INT IRQ_MBRINT +#define DAVINCI_ASP0_TX_INT IRQ_MBXINT +#define DAVINCI_ASP1_RX_INT IRQ_MBRINT +#define DAVINCI_ASP1_TX_INT IRQ_MBXINT + +#endif /* __ASM_ARCH_DAVINCI_ASP_H */ diff --git a/arch/arm/mach-davinci/davinci.h b/arch/arm/mach-davinci/davinci.h index 8db0fc6809dd..8661b2013527 100644 --- a/arch/arm/mach-davinci/davinci.h +++ b/arch/arm/mach-davinci/davinci.h @@ -22,10 +22,11 @@ #include #include #include +#include -#include #include #include +#include #include #include diff --git a/arch/arm/mach-davinci/devices-da8xx.c b/arch/arm/mach-davinci/devices-da8xx.c index 4735d64fd6f2..bd2f72b414bc 100644 --- a/arch/arm/mach-davinci/devices-da8xx.c +++ b/arch/arm/mach-davinci/devices-da8xx.c @@ -24,6 +24,7 @@ #include #include "clock.h" +#include "asp.h" #define DA8XX_TPCC_BASE 0x01c00000 #define DA8XX_TPTC0_BASE 0x01c08000 diff --git a/arch/arm/mach-davinci/dm355.c b/arch/arm/mach-davinci/dm355.c index 678cd99b7336..e47a3f0e8ac4 100644 --- a/arch/arm/mach-davinci/dm355.c +++ b/arch/arm/mach-davinci/dm355.c @@ -26,13 +26,13 @@ #include #include #include -#include #include #include #include "davinci.h" #include "clock.h" #include "mux.h" +#include "asp.h" #define DM355_UART2_BASE (IO_PHYS + 0x206000) diff --git a/arch/arm/mach-davinci/dm365.c b/arch/arm/mach-davinci/dm365.c index a50d49de1883..f473745d6e3c 100644 --- a/arch/arm/mach-davinci/dm365.c +++ b/arch/arm/mach-davinci/dm365.c @@ -29,7 +29,6 @@ #include #include #include -#include #include #include #include @@ -37,6 +36,7 @@ #include "davinci.h" #include "clock.h" #include "mux.h" +#include "asp.h" #define DM365_REF_FREQ 24000000 /* 24 MHz on the DM365 EVM */ diff --git a/arch/arm/mach-davinci/dm644x.c b/arch/arm/mach-davinci/dm644x.c index c8b866657fcb..0755d466221a 100644 --- a/arch/arm/mach-davinci/dm644x.c +++ b/arch/arm/mach-davinci/dm644x.c @@ -23,12 +23,12 @@ #include #include #include -#include #include #include "davinci.h" #include "clock.h" #include "mux.h" +#include "asp.h" /* * Device specific clocks diff --git a/arch/arm/mach-davinci/dm646x.c b/arch/arm/mach-davinci/dm646x.c index 9eb87c1d1edd..97c0f8e555bd 100644 --- a/arch/arm/mach-davinci/dm646x.c +++ b/arch/arm/mach-davinci/dm646x.c @@ -24,12 +24,12 @@ #include #include #include -#include #include #include "davinci.h" #include "clock.h" #include "mux.h" +#include "asp.h" #define DAVINCI_VPIF_BASE (0x01C12000) diff --git a/arch/arm/mach-davinci/include/mach/asp.h b/arch/arm/mach-davinci/include/mach/asp.h deleted file mode 100644 index 9aa240909a2c..000000000000 --- a/arch/arm/mach-davinci/include/mach/asp.h +++ /dev/null @@ -1,137 +0,0 @@ -/* - * - DaVinci Audio Serial Port support - */ -#ifndef __ASM_ARCH_DAVINCI_ASP_H -#define __ASM_ARCH_DAVINCI_ASP_H - -#include -#include - -/* Bases of dm644x and dm355 register banks */ -#define DAVINCI_ASP0_BASE 0x01E02000 -#define DAVINCI_ASP1_BASE 0x01E04000 - -/* Bases of dm365 register banks */ -#define DAVINCI_DM365_ASP0_BASE 0x01D02000 - -/* Bases of dm646x register banks */ -#define DAVINCI_DM646X_MCASP0_REG_BASE 0x01D01000 -#define DAVINCI_DM646X_MCASP1_REG_BASE 0x01D01800 - -/* Bases of da850/da830 McASP0 register banks */ -#define DAVINCI_DA8XX_MCASP0_REG_BASE 0x01D00000 - -/* Bases of da830 McASP1 register banks */ -#define DAVINCI_DA830_MCASP1_REG_BASE 0x01D04000 - -/* EDMA channels of dm644x and dm355 */ -#define DAVINCI_DMA_ASP0_TX 2 -#define DAVINCI_DMA_ASP0_RX 3 -#define DAVINCI_DMA_ASP1_TX 8 -#define DAVINCI_DMA_ASP1_RX 9 - -/* EDMA channels of dm646x */ -#define DAVINCI_DM646X_DMA_MCASP0_AXEVT0 6 -#define DAVINCI_DM646X_DMA_MCASP0_AREVT0 9 -#define DAVINCI_DM646X_DMA_MCASP1_AXEVT1 12 - -/* EDMA channels of da850/da830 McASP0 */ -#define DAVINCI_DA8XX_DMA_MCASP0_AREVT 0 -#define DAVINCI_DA8XX_DMA_MCASP0_AXEVT 1 - -/* EDMA channels of da830 McASP1 */ -#define DAVINCI_DA830_DMA_MCASP1_AREVT 2 -#define DAVINCI_DA830_DMA_MCASP1_AXEVT 3 - -/* Interrupts */ -#define DAVINCI_ASP0_RX_INT IRQ_MBRINT -#define DAVINCI_ASP0_TX_INT IRQ_MBXINT -#define DAVINCI_ASP1_RX_INT IRQ_MBRINT -#define DAVINCI_ASP1_TX_INT IRQ_MBXINT - -struct snd_platform_data { - u32 tx_dma_offset; - u32 rx_dma_offset; - enum dma_event_q asp_chan_q; /* event queue number for ASP channel */ - enum dma_event_q ram_chan_q; /* event queue number for RAM channel */ - unsigned int codec_fmt; - /* - * Allowing this is more efficient and eliminates left and right swaps - * caused by underruns, but will swap the left and right channels - * when compared to previous behavior. - */ - unsigned enable_channel_combine:1; - unsigned sram_size_playback; - unsigned sram_size_capture; - - /* - * If McBSP peripheral gets the clock from an external pin, - * there are three chooses, that are MCBSP_CLKX, MCBSP_CLKR - * and MCBSP_CLKS. - * Depending on different hardware connections it is possible - * to use this setting to change the behaviour of McBSP - * driver. The dm365_clk_input_pin enum is available for dm365 - */ - int clk_input_pin; - - /* - * This flag works when both clock and FS are outputs for the cpu - * and makes clock more accurate (FS is not symmetrical and the - * clock is very fast. - * The clock becoming faster is named - * i2s continuous serial clock (I2S_SCK) and it is an externally - * visible bit clock. - * - * first line : WordSelect - * second line : ContinuousSerialClock - * third line: SerialData - * - * SYMMETRICAL APPROACH: - * _______________________ LEFT - * _| RIGHT |______________________| - * _ _ _ _ _ _ _ _ - * _| |_| |_ x16 _| |_| |_| |_| |_ x16 _| |_| |_ - * _ _ _ _ _ _ _ _ - * _/ \_/ \_ ... _/ \_/ \_/ \_/ \_ ... _/ \_/ \_ - * \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ - * - * ACCURATE CLOCK APPROACH: - * ______________ LEFT - * _| RIGHT |_______________________________| - * _ _ _ _ _ _ _ _ _ - * _| |_ x16 _| |_| |_ x16 _| |_| |_| |_| |_| |_| | - * _ _ _ _ dummy cycles - * _/ \_ ... _/ \_/ \_ ... _/ \__________________ - * \_/ \_/ \_/ \_/ - * - */ - bool i2s_accurate_sck; - - /* McASP specific fields */ - int tdm_slots; - u8 op_mode; - u8 num_serializer; - u8 *serial_dir; - u8 version; - u8 txnumevt; - u8 rxnumevt; -}; - -enum { - MCASP_VERSION_1 = 0, /* DM646x */ - MCASP_VERSION_2, /* DA8xx/OMAPL1x */ -}; - -enum dm365_clk_input_pin { - MCBSP_CLKR = 0, /* DM365 */ - MCBSP_CLKS, -}; - -#define INACTIVE_MODE 0 -#define TX_MODE 1 -#define RX_MODE 2 - -#define DAVINCI_MCASP_IIS_MODE 0 -#define DAVINCI_MCASP_DIT_MODE 1 - -#endif /* __ASM_ARCH_DAVINCI_ASP_H */ diff --git a/arch/arm/mach-davinci/include/mach/da8xx.h b/arch/arm/mach-davinci/include/mach/da8xx.h index a2f1f274f189..c74a6abef187 100644 --- a/arch/arm/mach-davinci/include/mach/da8xx.h +++ b/arch/arm/mach-davinci/include/mach/da8xx.h @@ -16,11 +16,11 @@ #include #include #include +#include #include #include #include -#include #include #include #include diff --git a/include/linux/platform_data/davinci_asp.h b/include/linux/platform_data/davinci_asp.h new file mode 100644 index 000000000000..79c26aa11db6 --- /dev/null +++ b/include/linux/platform_data/davinci_asp.h @@ -0,0 +1,104 @@ +/* + * TI DaVinci Audio Serial Port support + * + * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/ + * + * 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 version 2. + * + * This program is distributed "as is" WITHOUT ANY WARRANTY of any + * kind, whether express or implied; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef __DAVINCI_ASP_H +#define __DAVINCI_ASP_H + +struct snd_platform_data { + u32 tx_dma_offset; + u32 rx_dma_offset; + int asp_chan_q; /* event queue number for ASP channel */ + int ram_chan_q; /* event queue number for RAM channel */ + unsigned int codec_fmt; + /* + * Allowing this is more efficient and eliminates left and right swaps + * caused by underruns, but will swap the left and right channels + * when compared to previous behavior. + */ + unsigned enable_channel_combine:1; + unsigned sram_size_playback; + unsigned sram_size_capture; + + /* + * If McBSP peripheral gets the clock from an external pin, + * there are three chooses, that are MCBSP_CLKX, MCBSP_CLKR + * and MCBSP_CLKS. + * Depending on different hardware connections it is possible + * to use this setting to change the behaviour of McBSP + * driver. + */ + int clk_input_pin; + + /* + * This flag works when both clock and FS are outputs for the cpu + * and makes clock more accurate (FS is not symmetrical and the + * clock is very fast. + * The clock becoming faster is named + * i2s continuous serial clock (I2S_SCK) and it is an externally + * visible bit clock. + * + * first line : WordSelect + * second line : ContinuousSerialClock + * third line: SerialData + * + * SYMMETRICAL APPROACH: + * _______________________ LEFT + * _| RIGHT |______________________| + * _ _ _ _ _ _ _ _ + * _| |_| |_ x16 _| |_| |_| |_| |_ x16 _| |_| |_ + * _ _ _ _ _ _ _ _ + * _/ \_/ \_ ... _/ \_/ \_/ \_/ \_ ... _/ \_/ \_ + * \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ + * + * ACCURATE CLOCK APPROACH: + * ______________ LEFT + * _| RIGHT |_______________________________| + * _ _ _ _ _ _ _ _ _ + * _| |_ x16 _| |_| |_ x16 _| |_| |_| |_| |_| |_| | + * _ _ _ _ dummy cycles + * _/ \_ ... _/ \_/ \_ ... _/ \__________________ + * \_/ \_/ \_/ \_/ + * + */ + bool i2s_accurate_sck; + + /* McASP specific fields */ + int tdm_slots; + u8 op_mode; + u8 num_serializer; + u8 *serial_dir; + u8 version; + u8 txnumevt; + u8 rxnumevt; +}; + +enum { + MCASP_VERSION_1 = 0, /* DM646x */ + MCASP_VERSION_2, /* DA8xx/OMAPL1x */ +}; + +enum mcbsp_clk_input_pin { + MCBSP_CLKR = 0, /* as in DM365 */ + MCBSP_CLKS, +}; + +#define INACTIVE_MODE 0 +#define TX_MODE 1 +#define RX_MODE 2 + +#define DAVINCI_MCASP_IIS_MODE 0 +#define DAVINCI_MCASP_DIT_MODE 1 + +#endif diff --git a/sound/soc/davinci/davinci-evm.c b/sound/soc/davinci/davinci-evm.c index 4b37e2ac4685..ab0ad4591b08 100644 --- a/sound/soc/davinci/davinci-evm.c +++ b/sound/soc/davinci/davinci-evm.c @@ -22,9 +22,6 @@ #include #include -#include -#include - #include "davinci-pcm.h" #include "davinci-i2s.h" #include "davinci-mcasp.h" diff --git a/sound/soc/davinci/davinci-i2s.c b/sound/soc/davinci/davinci-i2s.c index 407df7233d6d..821831207180 100644 --- a/sound/soc/davinci/davinci-i2s.c +++ b/sound/soc/davinci/davinci-i2s.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include @@ -23,8 +24,6 @@ #include #include -#include - #include "davinci-pcm.h" #include "davinci-i2s.h" diff --git a/sound/soc/davinci/davinci-mcasp.h b/sound/soc/davinci/davinci-mcasp.h index 51479f9ee909..0de9ed6ce038 100644 --- a/sound/soc/davinci/davinci-mcasp.h +++ b/sound/soc/davinci/davinci-mcasp.h @@ -19,7 +19,8 @@ #define DAVINCI_MCASP_H #include -#include +#include + #include "davinci-pcm.h" #define DAVINCI_MCASP_RATES SNDRV_PCM_RATE_8000_96000 diff --git a/sound/soc/davinci/davinci-pcm.c b/sound/soc/davinci/davinci-pcm.c index 4b70828beedb..93ea3bf567e1 100644 --- a/sound/soc/davinci/davinci-pcm.c +++ b/sound/soc/davinci/davinci-pcm.c @@ -23,7 +23,6 @@ #include #include -#include #include #include "davinci-pcm.h" diff --git a/sound/soc/davinci/davinci-pcm.h b/sound/soc/davinci/davinci-pcm.h index 5e5516460461..fc4d01cdd8c9 100644 --- a/sound/soc/davinci/davinci-pcm.h +++ b/sound/soc/davinci/davinci-pcm.h @@ -12,9 +12,8 @@ #ifndef _DAVINCI_PCM_H #define _DAVINCI_PCM_H +#include #include -#include - struct davinci_pcm_dma_params { int channel; /* sync dma channel ID */ -- cgit v1.2.3 From 3e3b8c3415b15adb5a7ffcbfbeb360e7c9f5f4f7 Mon Sep 17 00:00:00 2001 From: "Hebbar, Gururaja" Date: Mon, 27 Aug 2012 18:56:42 +0530 Subject: ASoC: Davinci: McASP: add device tree support for McASP Add device tree probe for McASP driver. Note: DMA parameters are not populated from DT and will be done later. Signed-off-by: Hebbar, Gururaja Signed-off-by: Mark Brown --- .../bindings/sound/davinci-mcasp-audio.txt | 44 ++++++++ sound/soc/davinci/davinci-mcasp.c | 124 ++++++++++++++++++++- 2 files changed, 167 insertions(+), 1 deletion(-) create mode 100644 Documentation/devicetree/bindings/sound/davinci-mcasp-audio.txt (limited to 'sound/soc') diff --git a/Documentation/devicetree/bindings/sound/davinci-mcasp-audio.txt b/Documentation/devicetree/bindings/sound/davinci-mcasp-audio.txt new file mode 100644 index 000000000000..e6148eca2942 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/davinci-mcasp-audio.txt @@ -0,0 +1,44 @@ +Texas Instruments McASP controller + +Required properties: +- compatible : + "ti,dm646x-mcasp-audio" : for DM646x platforms + "ti,da830-mcasp-audio" : for both DA830 & DA850 platforms + +- reg : Should contain McASP registers offset and length +- interrupts : Interrupt number for McASP +- op-mode : I2S/DIT ops mode. +- tdm-slots : Slots for TDM operation. +- num-serializer : Serializers used by McASP. +- serial-dir : A list of serializer pin mode. The list number should be equal + to "num-serializer" parameter. Each entry is a number indication + serializer pin direction. (0 - INACTIVE, 1 - TX, 2 - RX) + + +Optional properties: + +- ti,hwmods : Must be "mcasp", n is controller instance starting 0 +- tx-num-evt : FIFO levels. +- rx-num-evt : FIFO levels. +- sram-size-playback : size of sram to be allocated during playback +- sram-size-capture : size of sram to be allocated during capture + +Example: + +mcasp0: mcasp0@1d00000 { + compatible = "ti,da830-mcasp-audio"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x100000 0x3000>; + interrupts = <82 83>; + op-mode = <0>; /* MCASP_IIS_MODE */ + tdm-slots = <2>; + num-serializer = <16>; + serial-dir = < + 0 0 0 0 /* 0: INACTIVE, 1: TX, 2: RX */ + 0 0 0 0 + 0 0 0 1 + 2 0 0 0 >; + tx-num-evt = <1>; + rx-num-evt = <1>; +}; diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c index 8f3c5a4cf537..7ecf19dfb07c 100644 --- a/sound/soc/davinci/davinci-mcasp.c +++ b/sound/soc/davinci/davinci-mcasp.c @@ -22,6 +22,9 @@ #include #include #include +#include +#include +#include #include #include @@ -856,6 +859,114 @@ static struct snd_soc_dai_driver davinci_mcasp_dai[] = { }; +static const struct of_device_id mcasp_dt_ids[] = { + { + .compatible = "ti,dm646x-mcasp-audio", + .data = (void *)MCASP_VERSION_1, + }, + { + .compatible = "ti,da830-mcasp-audio", + .data = (void *)MCASP_VERSION_2, + }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, mcasp_dt_ids); + +static struct snd_platform_data *davinci_mcasp_set_pdata_from_of( + struct platform_device *pdev) +{ + struct device_node *np = pdev->dev.of_node; + struct snd_platform_data *pdata = NULL; + const struct of_device_id *match = + of_match_device(of_match_ptr(mcasp_dt_ids), &pdev->dev); + + const u32 *of_serial_dir32; + u8 *of_serial_dir; + u32 val; + int i, ret = 0; + + if (pdev->dev.platform_data) { + pdata = pdev->dev.platform_data; + return pdata; + } else if (match) { + pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); + if (!pdata) { + ret = -ENOMEM; + goto nodata; + } + } else { + /* control shouldn't reach here. something is wrong */ + ret = -EINVAL; + goto nodata; + } + + if (match->data) + pdata->version = (u8)((int)match->data); + + ret = of_property_read_u32(np, "op-mode", &val); + if (ret >= 0) + pdata->op_mode = val; + + ret = of_property_read_u32(np, "tdm-slots", &val); + if (ret >= 0) + pdata->tdm_slots = val; + + ret = of_property_read_u32(np, "num-serializer", &val); + if (ret >= 0) + pdata->num_serializer = val; + + of_serial_dir32 = of_get_property(np, "serial-dir", &val); + val /= sizeof(u32); + if (val != pdata->num_serializer) { + dev_err(&pdev->dev, + "num-serializer(%d) != serial-dir size(%d)\n", + pdata->num_serializer, val); + ret = -EINVAL; + goto nodata; + } + + if (of_serial_dir32) { + of_serial_dir = devm_kzalloc(&pdev->dev, + (sizeof(*of_serial_dir) * val), + GFP_KERNEL); + if (!of_serial_dir) { + ret = -ENOMEM; + goto nodata; + } + + for (i = 0; i < pdata->num_serializer; i++) + of_serial_dir[i] = be32_to_cpup(&of_serial_dir32[i]); + + pdata->serial_dir = of_serial_dir; + } + + ret = of_property_read_u32(np, "tx-num-evt", &val); + if (ret >= 0) + pdata->txnumevt = val; + + ret = of_property_read_u32(np, "rx-num-evt", &val); + if (ret >= 0) + pdata->rxnumevt = val; + + ret = of_property_read_u32(np, "sram-size-playback", &val); + if (ret >= 0) + pdata->sram_size_playback = val; + + ret = of_property_read_u32(np, "sram-size-capture", &val); + if (ret >= 0) + pdata->sram_size_capture = val; + + return pdata; + +nodata: + if (ret < 0) { + dev_err(&pdev->dev, "Error populating platform data, err %d\n", + ret); + pdata = NULL; + } + return pdata; +} + static int davinci_mcasp_probe(struct platform_device *pdev) { struct davinci_pcm_dma_params *dma_data; @@ -864,11 +975,22 @@ static int davinci_mcasp_probe(struct platform_device *pdev) struct davinci_audio_dev *dev; int ret; + if (!pdev->dev.platform_data && !pdev->dev.of_node) { + dev_err(&pdev->dev, "No platform data supplied\n"); + return -EINVAL; + } + dev = devm_kzalloc(&pdev->dev, sizeof(struct davinci_audio_dev), GFP_KERNEL); if (!dev) return -ENOMEM; + pdata = davinci_mcasp_set_pdata_from_of(pdev); + if (!pdata) { + dev_err(&pdev->dev, "no platform data\n"); + return -EINVAL; + } + mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!mem) { dev_err(&pdev->dev, "no mem resource?\n"); @@ -882,7 +1004,6 @@ static int davinci_mcasp_probe(struct platform_device *pdev) return -EBUSY; } - pdata = pdev->dev.platform_data; pm_runtime_enable(&pdev->dev); ret = pm_runtime_get_sync(&pdev->dev); @@ -980,6 +1101,7 @@ static struct platform_driver davinci_mcasp_driver = { .driver = { .name = "davinci-mcasp", .owner = THIS_MODULE, + .of_match_table = of_match_ptr(mcasp_dt_ids), }, }; -- cgit v1.2.3 From 3d721a34e66e8133404bda6852897b818df69b4c Mon Sep 17 00:00:00 2001 From: Sangsu Park Date: Tue, 28 Aug 2012 17:55:49 +0900 Subject: ASoC: SAMSUNG: Change Kconfig to support all SAMSUNG ASoC All SAMSUNG ASoC needs SND_SOC_SAMSUNG configuration. This patch change Kconfig to support all SAMSUNG ASoC. Signed-off-by: Sangsu Park Acked-by: Sangbeom Kim Signed-off-by: Mark Brown --- sound/soc/samsung/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound/soc') diff --git a/sound/soc/samsung/Kconfig b/sound/soc/samsung/Kconfig index f17dd25e0f4a..e7b83179aca2 100644 --- a/sound/soc/samsung/Kconfig +++ b/sound/soc/samsung/Kconfig @@ -1,6 +1,6 @@ config SND_SOC_SAMSUNG tristate "ASoC support for Samsung" - depends on ARCH_S3C24XX || ARCH_S3C64XX || ARCH_S5PC100 || ARCH_S5PV210 || ARCH_S5P64X0 || ARCH_EXYNOS4 + depends on PLAT_SAMSUNG select S3C64XX_DMA if ARCH_S3C64XX select S3C2410_DMA if ARCH_S3C24XX help -- cgit v1.2.3 From 0ed275eff31029c39355828cb48c46c0a006e2f8 Mon Sep 17 00:00:00 2001 From: Alexander Shiyan Date: Tue, 21 Aug 2012 19:21:51 +0400 Subject: ASoC: Rename ep93xx soc directory to cirrus This patch is to rename the directory "ep93xx" in "cirrus". Name more accurately reflects the manufacturer and allows to add drivers not only for architecture ep93xx in this directory. Patch not contain any functional changes. Signed-off-by: Alexander Shiyan Signed-off-by: Mark Brown --- sound/soc/Kconfig | 2 +- sound/soc/Makefile | 2 +- sound/soc/cirrus/Kconfig | 42 ++++ sound/soc/cirrus/Makefile | 17 ++ sound/soc/cirrus/edb93xx.c | 128 ++++++++++++ sound/soc/cirrus/ep93xx-ac97.c | 435 +++++++++++++++++++++++++++++++++++++++ sound/soc/cirrus/ep93xx-i2s.c | 451 +++++++++++++++++++++++++++++++++++++++++ sound/soc/cirrus/ep93xx-pcm.c | 242 ++++++++++++++++++++++ sound/soc/cirrus/ep93xx-pcm.h | 20 ++ sound/soc/cirrus/simone.c | 90 ++++++++ sound/soc/cirrus/snappercl15.c | 146 +++++++++++++ sound/soc/ep93xx/Kconfig | 42 ---- sound/soc/ep93xx/Makefile | 17 -- sound/soc/ep93xx/edb93xx.c | 128 ------------ sound/soc/ep93xx/ep93xx-ac97.c | 435 --------------------------------------- sound/soc/ep93xx/ep93xx-i2s.c | 451 ----------------------------------------- sound/soc/ep93xx/ep93xx-pcm.c | 242 ---------------------- sound/soc/ep93xx/ep93xx-pcm.h | 20 -- sound/soc/ep93xx/simone.c | 90 -------- sound/soc/ep93xx/snappercl15.c | 146 ------------- 20 files changed, 1573 insertions(+), 1573 deletions(-) create mode 100644 sound/soc/cirrus/Kconfig create mode 100644 sound/soc/cirrus/Makefile create mode 100644 sound/soc/cirrus/edb93xx.c create mode 100644 sound/soc/cirrus/ep93xx-ac97.c create mode 100644 sound/soc/cirrus/ep93xx-i2s.c create mode 100644 sound/soc/cirrus/ep93xx-pcm.c create mode 100644 sound/soc/cirrus/ep93xx-pcm.h create mode 100644 sound/soc/cirrus/simone.c create mode 100644 sound/soc/cirrus/snappercl15.c delete mode 100644 sound/soc/ep93xx/Kconfig delete mode 100644 sound/soc/ep93xx/Makefile delete mode 100644 sound/soc/ep93xx/edb93xx.c delete mode 100644 sound/soc/ep93xx/ep93xx-ac97.c delete mode 100644 sound/soc/ep93xx/ep93xx-i2s.c delete mode 100644 sound/soc/ep93xx/ep93xx-pcm.c delete mode 100644 sound/soc/ep93xx/ep93xx-pcm.h delete mode 100644 sound/soc/ep93xx/simone.c delete mode 100644 sound/soc/ep93xx/snappercl15.c (limited to 'sound/soc') diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig index c24de902f5f5..5da8ca7aee05 100644 --- a/sound/soc/Kconfig +++ b/sound/soc/Kconfig @@ -33,9 +33,9 @@ config SND_SOC_DMAENGINE_PCM source "sound/soc/atmel/Kconfig" source "sound/soc/au1x/Kconfig" source "sound/soc/blackfin/Kconfig" +source "sound/soc/cirrus/Kconfig" source "sound/soc/davinci/Kconfig" source "sound/soc/dwc/Kconfig" -source "sound/soc/ep93xx/Kconfig" source "sound/soc/fsl/Kconfig" source "sound/soc/jz4740/Kconfig" source "sound/soc/nuc900/Kconfig" diff --git a/sound/soc/Makefile b/sound/soc/Makefile index c1264007b4ee..bcbf1d00aa85 100644 --- a/sound/soc/Makefile +++ b/sound/soc/Makefile @@ -10,9 +10,9 @@ obj-$(CONFIG_SND_SOC) += generic/ obj-$(CONFIG_SND_SOC) += atmel/ obj-$(CONFIG_SND_SOC) += au1x/ obj-$(CONFIG_SND_SOC) += blackfin/ +obj-$(CONFIG_SND_SOC) += cirrus/ obj-$(CONFIG_SND_SOC) += davinci/ obj-$(CONFIG_SND_SOC) += dwc/ -obj-$(CONFIG_SND_SOC) += ep93xx/ obj-$(CONFIG_SND_SOC) += fsl/ obj-$(CONFIG_SND_SOC) += jz4740/ obj-$(CONFIG_SND_SOC) += mid-x86/ diff --git a/sound/soc/cirrus/Kconfig b/sound/soc/cirrus/Kconfig new file mode 100644 index 000000000000..88143db7e753 --- /dev/null +++ b/sound/soc/cirrus/Kconfig @@ -0,0 +1,42 @@ +config SND_EP93XX_SOC + tristate "SoC Audio support for the Cirrus Logic EP93xx series" + depends on ARCH_EP93XX && SND_SOC + select SND_SOC_DMAENGINE_PCM + help + Say Y or M if you want to add support for codecs attached to + the EP93xx I2S or AC97 interfaces. + +config SND_EP93XX_SOC_I2S + tristate + +config SND_EP93XX_SOC_AC97 + tristate + select AC97_BUS + select SND_SOC_AC97_BUS + +config SND_EP93XX_SOC_SNAPPERCL15 + tristate "SoC Audio support for Bluewater Systems Snapper CL15 module" + depends on SND_EP93XX_SOC && MACH_SNAPPER_CL15 + select SND_EP93XX_SOC_I2S + select SND_SOC_TLV320AIC23 + help + Say Y or M here if you want to add support for I2S audio on the + Bluewater Systems Snapper CL15 module. + +config SND_EP93XX_SOC_SIMONE + tristate "SoC Audio support for Simplemachines Sim.One board" + depends on SND_EP93XX_SOC && MACH_SIM_ONE + select SND_EP93XX_SOC_AC97 + select SND_SOC_AC97_CODEC + help + Say Y or M here if you want to add support for AC97 audio on the + Simplemachines Sim.One board. + +config SND_EP93XX_SOC_EDB93XX + tristate "SoC Audio support for Cirrus Logic EDB93xx boards" + depends on SND_EP93XX_SOC && (MACH_EDB9301 || MACH_EDB9302 || MACH_EDB9302A || MACH_EDB9307A || MACH_EDB9315A) + select SND_EP93XX_SOC_I2S + select SND_SOC_CS4271 + help + Say Y or M here if you want to add support for I2S audio on the + Cirrus Logic EDB93xx boards. diff --git a/sound/soc/cirrus/Makefile b/sound/soc/cirrus/Makefile new file mode 100644 index 000000000000..5514146cbdf0 --- /dev/null +++ b/sound/soc/cirrus/Makefile @@ -0,0 +1,17 @@ +# EP93xx Platform Support +snd-soc-ep93xx-objs := ep93xx-pcm.o +snd-soc-ep93xx-i2s-objs := ep93xx-i2s.o +snd-soc-ep93xx-ac97-objs := ep93xx-ac97.o + +obj-$(CONFIG_SND_EP93XX_SOC) += snd-soc-ep93xx.o +obj-$(CONFIG_SND_EP93XX_SOC_I2S) += snd-soc-ep93xx-i2s.o +obj-$(CONFIG_SND_EP93XX_SOC_AC97) += snd-soc-ep93xx-ac97.o + +# EP93XX Machine Support +snd-soc-snappercl15-objs := snappercl15.o +snd-soc-simone-objs := simone.o +snd-soc-edb93xx-objs := edb93xx.o + +obj-$(CONFIG_SND_EP93XX_SOC_SNAPPERCL15) += snd-soc-snappercl15.o +obj-$(CONFIG_SND_EP93XX_SOC_SIMONE) += snd-soc-simone.o +obj-$(CONFIG_SND_EP93XX_SOC_EDB93XX) += snd-soc-edb93xx.o diff --git a/sound/soc/cirrus/edb93xx.c b/sound/soc/cirrus/edb93xx.c new file mode 100644 index 000000000000..e01cb02abd3a --- /dev/null +++ b/sound/soc/cirrus/edb93xx.c @@ -0,0 +1,128 @@ +/* + * SoC audio for EDB93xx + * + * Copyright (c) 2010 Alexander Sverdlin + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * This driver support CS4271 codec being master or slave, working + * in control port mode, connected either via SPI or I2C. + * The data format accepted is I2S or left-justified. + * DAPM support not implemented. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "ep93xx-pcm.h" + +static int edb93xx_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_dai *codec_dai = rtd->codec_dai; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + int err; + unsigned int mclk_rate; + unsigned int rate = params_rate(params); + + /* + * According to CS4271 datasheet we use MCLK/LRCK=256 for + * rates below 50kHz and 128 for higher sample rates + */ + if (rate < 50000) + mclk_rate = rate * 64 * 4; + else + mclk_rate = rate * 64 * 2; + + err = snd_soc_dai_set_sysclk(codec_dai, 0, mclk_rate, + SND_SOC_CLOCK_IN); + if (err) + return err; + + return snd_soc_dai_set_sysclk(cpu_dai, 0, mclk_rate, + SND_SOC_CLOCK_OUT); +} + +static struct snd_soc_ops edb93xx_ops = { + .hw_params = edb93xx_hw_params, +}; + +static struct snd_soc_dai_link edb93xx_dai = { + .name = "CS4271", + .stream_name = "CS4271 HiFi", + .platform_name = "ep93xx-pcm-audio", + .cpu_dai_name = "ep93xx-i2s", + .codec_name = "spi0.0", + .codec_dai_name = "cs4271-hifi", + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_IF | + SND_SOC_DAIFMT_CBS_CFS, + .ops = &edb93xx_ops, +}; + +static struct snd_soc_card snd_soc_edb93xx = { + .name = "EDB93XX", + .owner = THIS_MODULE, + .dai_link = &edb93xx_dai, + .num_links = 1, +}; + +static int __devinit edb93xx_probe(struct platform_device *pdev) +{ + struct snd_soc_card *card = &snd_soc_edb93xx; + int ret; + + ret = ep93xx_i2s_acquire(); + if (ret) + return ret; + + card->dev = &pdev->dev; + + ret = snd_soc_register_card(card); + if (ret) { + dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", + ret); + ep93xx_i2s_release(); + } + + return ret; +} + +static int __devexit edb93xx_remove(struct platform_device *pdev) +{ + struct snd_soc_card *card = platform_get_drvdata(pdev); + + snd_soc_unregister_card(card); + ep93xx_i2s_release(); + + return 0; +} + +static struct platform_driver edb93xx_driver = { + .driver = { + .name = "edb93xx-audio", + .owner = THIS_MODULE, + }, + .probe = edb93xx_probe, + .remove = __devexit_p(edb93xx_remove), +}; + +module_platform_driver(edb93xx_driver); + +MODULE_AUTHOR("Alexander Sverdlin "); +MODULE_DESCRIPTION("ALSA SoC EDB93xx"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:edb93xx-audio"); diff --git a/sound/soc/cirrus/ep93xx-ac97.c b/sound/soc/cirrus/ep93xx-ac97.c new file mode 100644 index 000000000000..bdffab33e160 --- /dev/null +++ b/sound/soc/cirrus/ep93xx-ac97.c @@ -0,0 +1,435 @@ +/* + * ASoC driver for Cirrus Logic EP93xx AC97 controller. + * + * Copyright (c) 2010 Mika Westerberg + * + * Based on s3c-ac97 ASoC driver by Jaswinder Singh. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include "ep93xx-pcm.h" + +/* + * Per channel (1-4) registers. + */ +#define AC97CH(n) (((n) - 1) * 0x20) + +#define AC97DR(n) (AC97CH(n) + 0x0000) + +#define AC97RXCR(n) (AC97CH(n) + 0x0004) +#define AC97RXCR_REN BIT(0) +#define AC97RXCR_RX3 BIT(3) +#define AC97RXCR_RX4 BIT(4) +#define AC97RXCR_CM BIT(15) + +#define AC97TXCR(n) (AC97CH(n) + 0x0008) +#define AC97TXCR_TEN BIT(0) +#define AC97TXCR_TX3 BIT(3) +#define AC97TXCR_TX4 BIT(4) +#define AC97TXCR_CM BIT(15) + +#define AC97SR(n) (AC97CH(n) + 0x000c) +#define AC97SR_TXFE BIT(1) +#define AC97SR_TXUE BIT(6) + +#define AC97RISR(n) (AC97CH(n) + 0x0010) +#define AC97ISR(n) (AC97CH(n) + 0x0014) +#define AC97IE(n) (AC97CH(n) + 0x0018) + +/* + * Global AC97 controller registers. + */ +#define AC97S1DATA 0x0080 +#define AC97S2DATA 0x0084 +#define AC97S12DATA 0x0088 + +#define AC97RGIS 0x008c +#define AC97GIS 0x0090 +#define AC97IM 0x0094 +/* + * Common bits for RGIS, GIS and IM registers. + */ +#define AC97_SLOT2RXVALID BIT(1) +#define AC97_CODECREADY BIT(5) +#define AC97_SLOT2TXCOMPLETE BIT(6) + +#define AC97EOI 0x0098 +#define AC97EOI_WINT BIT(0) +#define AC97EOI_CODECREADY BIT(1) + +#define AC97GCR 0x009c +#define AC97GCR_AC97IFE BIT(0) + +#define AC97RESET 0x00a0 +#define AC97RESET_TIMEDRESET BIT(0) + +#define AC97SYNC 0x00a4 +#define AC97SYNC_TIMEDSYNC BIT(0) + +#define AC97_TIMEOUT msecs_to_jiffies(5) + +/** + * struct ep93xx_ac97_info - EP93xx AC97 controller info structure + * @lock: mutex serializing access to the bus (slot 1 & 2 ops) + * @dev: pointer to the platform device dev structure + * @regs: mapped AC97 controller registers + * @done: bus ops wait here for an interrupt + */ +struct ep93xx_ac97_info { + struct mutex lock; + struct device *dev; + void __iomem *regs; + struct completion done; +}; + +/* currently ALSA only supports a single AC97 device */ +static struct ep93xx_ac97_info *ep93xx_ac97_info; + +static struct ep93xx_pcm_dma_params ep93xx_ac97_pcm_out = { + .name = "ac97-pcm-out", + .dma_port = EP93XX_DMA_AAC1, +}; + +static struct ep93xx_pcm_dma_params ep93xx_ac97_pcm_in = { + .name = "ac97-pcm-in", + .dma_port = EP93XX_DMA_AAC1, +}; + +static inline unsigned ep93xx_ac97_read_reg(struct ep93xx_ac97_info *info, + unsigned reg) +{ + return __raw_readl(info->regs + reg); +} + +static inline void ep93xx_ac97_write_reg(struct ep93xx_ac97_info *info, + unsigned reg, unsigned val) +{ + __raw_writel(val, info->regs + reg); +} + +static unsigned short ep93xx_ac97_read(struct snd_ac97 *ac97, + unsigned short reg) +{ + struct ep93xx_ac97_info *info = ep93xx_ac97_info; + unsigned short val; + + mutex_lock(&info->lock); + + ep93xx_ac97_write_reg(info, AC97S1DATA, reg); + ep93xx_ac97_write_reg(info, AC97IM, AC97_SLOT2RXVALID); + if (!wait_for_completion_timeout(&info->done, AC97_TIMEOUT)) { + dev_warn(info->dev, "timeout reading register %x\n", reg); + mutex_unlock(&info->lock); + return -ETIMEDOUT; + } + val = (unsigned short)ep93xx_ac97_read_reg(info, AC97S2DATA); + + mutex_unlock(&info->lock); + return val; +} + +static void ep93xx_ac97_write(struct snd_ac97 *ac97, + unsigned short reg, + unsigned short val) +{ + struct ep93xx_ac97_info *info = ep93xx_ac97_info; + + mutex_lock(&info->lock); + + /* + * Writes to the codec need to be done so that slot 2 is filled in + * before slot 1. + */ + ep93xx_ac97_write_reg(info, AC97S2DATA, val); + ep93xx_ac97_write_reg(info, AC97S1DATA, reg); + + ep93xx_ac97_write_reg(info, AC97IM, AC97_SLOT2TXCOMPLETE); + if (!wait_for_completion_timeout(&info->done, AC97_TIMEOUT)) + dev_warn(info->dev, "timeout writing register %x\n", reg); + + mutex_unlock(&info->lock); +} + +static void ep93xx_ac97_warm_reset(struct snd_ac97 *ac97) +{ + struct ep93xx_ac97_info *info = ep93xx_ac97_info; + + mutex_lock(&info->lock); + + /* + * We are assuming that before this functions gets called, the codec + * BIT_CLK is stopped by forcing the codec into powerdown mode. We can + * control the SYNC signal directly via AC97SYNC register. Using + * TIMEDSYNC the controller will keep the SYNC high > 1us. + */ + ep93xx_ac97_write_reg(info, AC97SYNC, AC97SYNC_TIMEDSYNC); + ep93xx_ac97_write_reg(info, AC97IM, AC97_CODECREADY); + if (!wait_for_completion_timeout(&info->done, AC97_TIMEOUT)) + dev_warn(info->dev, "codec warm reset timeout\n"); + + mutex_unlock(&info->lock); +} + +static void ep93xx_ac97_cold_reset(struct snd_ac97 *ac97) +{ + struct ep93xx_ac97_info *info = ep93xx_ac97_info; + + mutex_lock(&info->lock); + + /* + * For doing cold reset, we disable the AC97 controller interface, clear + * WINT and CODECREADY bits, and finally enable the interface again. + */ + ep93xx_ac97_write_reg(info, AC97GCR, 0); + ep93xx_ac97_write_reg(info, AC97EOI, AC97EOI_CODECREADY | AC97EOI_WINT); + ep93xx_ac97_write_reg(info, AC97GCR, AC97GCR_AC97IFE); + + /* + * Now, assert the reset and wait for the codec to become ready. + */ + ep93xx_ac97_write_reg(info, AC97RESET, AC97RESET_TIMEDRESET); + ep93xx_ac97_write_reg(info, AC97IM, AC97_CODECREADY); + if (!wait_for_completion_timeout(&info->done, AC97_TIMEOUT)) + dev_warn(info->dev, "codec cold reset timeout\n"); + + /* + * Give the codec some time to come fully out from the reset. This way + * we ensure that the subsequent reads/writes will work. + */ + usleep_range(15000, 20000); + + mutex_unlock(&info->lock); +} + +static irqreturn_t ep93xx_ac97_interrupt(int irq, void *dev_id) +{ + struct ep93xx_ac97_info *info = dev_id; + unsigned status, mask; + + /* + * Just mask out the interrupt and wake up the waiting thread. + * Interrupts are cleared via reading/writing to slot 1 & 2 registers by + * the waiting thread. + */ + status = ep93xx_ac97_read_reg(info, AC97GIS); + mask = ep93xx_ac97_read_reg(info, AC97IM); + mask &= ~status; + ep93xx_ac97_write_reg(info, AC97IM, mask); + + complete(&info->done); + return IRQ_HANDLED; +} + +struct snd_ac97_bus_ops soc_ac97_ops = { + .read = ep93xx_ac97_read, + .write = ep93xx_ac97_write, + .reset = ep93xx_ac97_cold_reset, + .warm_reset = ep93xx_ac97_warm_reset, +}; +EXPORT_SYMBOL_GPL(soc_ac97_ops); + +static int ep93xx_ac97_trigger(struct snd_pcm_substream *substream, + int cmd, struct snd_soc_dai *dai) +{ + struct ep93xx_ac97_info *info = snd_soc_dai_get_drvdata(dai); + unsigned v = 0; + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_RESUME: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + /* + * Enable compact mode, TX slots 3 & 4, and the TX FIFO + * itself. + */ + v |= AC97TXCR_CM; + v |= AC97TXCR_TX3 | AC97TXCR_TX4; + v |= AC97TXCR_TEN; + ep93xx_ac97_write_reg(info, AC97TXCR(1), v); + } else { + /* + * Enable compact mode, RX slots 3 & 4, and the RX FIFO + * itself. + */ + v |= AC97RXCR_CM; + v |= AC97RXCR_RX3 | AC97RXCR_RX4; + v |= AC97RXCR_REN; + ep93xx_ac97_write_reg(info, AC97RXCR(1), v); + } + break; + + case SNDRV_PCM_TRIGGER_STOP: + case SNDRV_PCM_TRIGGER_SUSPEND: + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + /* + * As per Cirrus EP93xx errata described below: + * + * http://www.cirrus.com/en/pubs/errata/ER667E2B.pdf + * + * we will wait for the TX FIFO to be empty before + * clearing the TEN bit. + */ + unsigned long timeout = jiffies + AC97_TIMEOUT; + + do { + v = ep93xx_ac97_read_reg(info, AC97SR(1)); + if (time_after(jiffies, timeout)) { + dev_warn(info->dev, "TX timeout\n"); + break; + } + } while (!(v & (AC97SR_TXFE | AC97SR_TXUE))); + + /* disable the TX FIFO */ + ep93xx_ac97_write_reg(info, AC97TXCR(1), 0); + } else { + /* disable the RX FIFO */ + ep93xx_ac97_write_reg(info, AC97RXCR(1), 0); + } + break; + + default: + dev_warn(info->dev, "unknown command %d\n", cmd); + return -EINVAL; + } + + return 0; +} + +static int ep93xx_ac97_startup(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct ep93xx_pcm_dma_params *dma_data; + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + dma_data = &ep93xx_ac97_pcm_out; + else + dma_data = &ep93xx_ac97_pcm_in; + + snd_soc_dai_set_dma_data(dai, substream, dma_data); + return 0; +} + +static const struct snd_soc_dai_ops ep93xx_ac97_dai_ops = { + .startup = ep93xx_ac97_startup, + .trigger = ep93xx_ac97_trigger, +}; + +static struct snd_soc_dai_driver ep93xx_ac97_dai = { + .name = "ep93xx-ac97", + .id = 0, + .ac97_control = 1, + .playback = { + .stream_name = "AC97 Playback", + .channels_min = 2, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_8000_48000, + .formats = SNDRV_PCM_FMTBIT_S16_LE, + }, + .capture = { + .stream_name = "AC97 Capture", + .channels_min = 2, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_8000_48000, + .formats = SNDRV_PCM_FMTBIT_S16_LE, + }, + .ops = &ep93xx_ac97_dai_ops, +}; + +static int __devinit ep93xx_ac97_probe(struct platform_device *pdev) +{ + struct ep93xx_ac97_info *info; + struct resource *res; + unsigned int irq; + int ret; + + info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL); + if (!info) + return -ENOMEM; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) + return -ENODEV; + + info->regs = devm_request_and_ioremap(&pdev->dev, res); + if (!info->regs) + return -ENXIO; + + irq = platform_get_irq(pdev, 0); + if (!irq) + return -ENODEV; + + ret = devm_request_irq(&pdev->dev, irq, ep93xx_ac97_interrupt, + IRQF_TRIGGER_HIGH, pdev->name, info); + if (ret) + goto fail; + + dev_set_drvdata(&pdev->dev, info); + + mutex_init(&info->lock); + init_completion(&info->done); + info->dev = &pdev->dev; + + ep93xx_ac97_info = info; + platform_set_drvdata(pdev, info); + + ret = snd_soc_register_dai(&pdev->dev, &ep93xx_ac97_dai); + if (ret) + goto fail; + + return 0; + +fail: + platform_set_drvdata(pdev, NULL); + ep93xx_ac97_info = NULL; + dev_set_drvdata(&pdev->dev, NULL); + return ret; +} + +static int __devexit ep93xx_ac97_remove(struct platform_device *pdev) +{ + struct ep93xx_ac97_info *info = platform_get_drvdata(pdev); + + snd_soc_unregister_dai(&pdev->dev); + + /* disable the AC97 controller */ + ep93xx_ac97_write_reg(info, AC97GCR, 0); + + platform_set_drvdata(pdev, NULL); + ep93xx_ac97_info = NULL; + dev_set_drvdata(&pdev->dev, NULL); + + return 0; +} + +static struct platform_driver ep93xx_ac97_driver = { + .probe = ep93xx_ac97_probe, + .remove = __devexit_p(ep93xx_ac97_remove), + .driver = { + .name = "ep93xx-ac97", + .owner = THIS_MODULE, + }, +}; + +module_platform_driver(ep93xx_ac97_driver); + +MODULE_DESCRIPTION("EP93xx AC97 ASoC Driver"); +MODULE_AUTHOR("Mika Westerberg "); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:ep93xx-ac97"); diff --git a/sound/soc/cirrus/ep93xx-i2s.c b/sound/soc/cirrus/ep93xx-i2s.c new file mode 100644 index 000000000000..8df8f6dc474f --- /dev/null +++ b/sound/soc/cirrus/ep93xx-i2s.c @@ -0,0 +1,451 @@ +/* + * linux/sound/soc/ep93xx-i2s.c + * EP93xx I2S driver + * + * Copyright (C) 2010 Ryan Mallon + * + * Based on the original driver by: + * Copyright (C) 2007 Chase Douglas + * Copyright (C) 2006 Lennert Buytenhek + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "ep93xx-pcm.h" + +#define EP93XX_I2S_TXCLKCFG 0x00 +#define EP93XX_I2S_RXCLKCFG 0x04 +#define EP93XX_I2S_GLCTRL 0x0C + +#define EP93XX_I2S_TXLINCTRLDATA 0x28 +#define EP93XX_I2S_TXCTRL 0x2C +#define EP93XX_I2S_TXWRDLEN 0x30 +#define EP93XX_I2S_TX0EN 0x34 + +#define EP93XX_I2S_RXLINCTRLDATA 0x58 +#define EP93XX_I2S_RXCTRL 0x5C +#define EP93XX_I2S_RXWRDLEN 0x60 +#define EP93XX_I2S_RX0EN 0x64 + +#define EP93XX_I2S_WRDLEN_16 (0 << 0) +#define EP93XX_I2S_WRDLEN_24 (1 << 0) +#define EP93XX_I2S_WRDLEN_32 (2 << 0) + +#define EP93XX_I2S_LINCTRLDATA_R_JUST (1 << 2) /* Right justify */ + +#define EP93XX_I2S_CLKCFG_LRS (1 << 0) /* lrclk polarity */ +#define EP93XX_I2S_CLKCFG_CKP (1 << 1) /* Bit clock polarity */ +#define EP93XX_I2S_CLKCFG_REL (1 << 2) /* First bit transition */ +#define EP93XX_I2S_CLKCFG_MASTER (1 << 3) /* Master mode */ +#define EP93XX_I2S_CLKCFG_NBCG (1 << 4) /* Not bit clock gating */ + +struct ep93xx_i2s_info { + struct clk *mclk; + struct clk *sclk; + struct clk *lrclk; + struct ep93xx_pcm_dma_params *dma_params; + void __iomem *regs; +}; + +struct ep93xx_pcm_dma_params ep93xx_i2s_dma_params[] = { + [SNDRV_PCM_STREAM_PLAYBACK] = { + .name = "i2s-pcm-out", + .dma_port = EP93XX_DMA_I2S1, + }, + [SNDRV_PCM_STREAM_CAPTURE] = { + .name = "i2s-pcm-in", + .dma_port = EP93XX_DMA_I2S1, + }, +}; + +static inline void ep93xx_i2s_write_reg(struct ep93xx_i2s_info *info, + unsigned reg, unsigned val) +{ + __raw_writel(val, info->regs + reg); +} + +static inline unsigned ep93xx_i2s_read_reg(struct ep93xx_i2s_info *info, + unsigned reg) +{ + return __raw_readl(info->regs + reg); +} + +static void ep93xx_i2s_enable(struct ep93xx_i2s_info *info, int stream) +{ + unsigned base_reg; + int i; + + if ((ep93xx_i2s_read_reg(info, EP93XX_I2S_TX0EN) & 0x1) == 0 && + (ep93xx_i2s_read_reg(info, EP93XX_I2S_RX0EN) & 0x1) == 0) { + /* Enable clocks */ + clk_enable(info->mclk); + clk_enable(info->sclk); + clk_enable(info->lrclk); + + /* Enable i2s */ + ep93xx_i2s_write_reg(info, EP93XX_I2S_GLCTRL, 1); + } + + /* Enable fifos */ + if (stream == SNDRV_PCM_STREAM_PLAYBACK) + base_reg = EP93XX_I2S_TX0EN; + else + base_reg = EP93XX_I2S_RX0EN; + for (i = 0; i < 3; i++) + ep93xx_i2s_write_reg(info, base_reg + (i * 4), 1); +} + +static void ep93xx_i2s_disable(struct ep93xx_i2s_info *info, int stream) +{ + unsigned base_reg; + int i; + + /* Disable fifos */ + if (stream == SNDRV_PCM_STREAM_PLAYBACK) + base_reg = EP93XX_I2S_TX0EN; + else + base_reg = EP93XX_I2S_RX0EN; + for (i = 0; i < 3; i++) + ep93xx_i2s_write_reg(info, base_reg + (i * 4), 0); + + if ((ep93xx_i2s_read_reg(info, EP93XX_I2S_TX0EN) & 0x1) == 0 && + (ep93xx_i2s_read_reg(info, EP93XX_I2S_RX0EN) & 0x1) == 0) { + /* Disable i2s */ + ep93xx_i2s_write_reg(info, EP93XX_I2S_GLCTRL, 0); + + /* Disable clocks */ + clk_disable(info->lrclk); + clk_disable(info->sclk); + clk_disable(info->mclk); + } +} + +static int ep93xx_i2s_startup(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct ep93xx_i2s_info *info = snd_soc_dai_get_drvdata(dai); + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + + snd_soc_dai_set_dma_data(cpu_dai, substream, + &info->dma_params[substream->stream]); + return 0; +} + +static void ep93xx_i2s_shutdown(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct ep93xx_i2s_info *info = snd_soc_dai_get_drvdata(dai); + + ep93xx_i2s_disable(info, substream->stream); +} + +static int ep93xx_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai, + unsigned int fmt) +{ + struct ep93xx_i2s_info *info = snd_soc_dai_get_drvdata(cpu_dai); + unsigned int clk_cfg, lin_ctrl; + + clk_cfg = ep93xx_i2s_read_reg(info, EP93XX_I2S_RXCLKCFG); + lin_ctrl = ep93xx_i2s_read_reg(info, EP93XX_I2S_RXLINCTRLDATA); + + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { + case SND_SOC_DAIFMT_I2S: + clk_cfg |= EP93XX_I2S_CLKCFG_REL; + lin_ctrl &= ~EP93XX_I2S_LINCTRLDATA_R_JUST; + break; + + case SND_SOC_DAIFMT_LEFT_J: + clk_cfg &= ~EP93XX_I2S_CLKCFG_REL; + lin_ctrl &= ~EP93XX_I2S_LINCTRLDATA_R_JUST; + break; + + case SND_SOC_DAIFMT_RIGHT_J: + clk_cfg &= ~EP93XX_I2S_CLKCFG_REL; + lin_ctrl |= EP93XX_I2S_LINCTRLDATA_R_JUST; + break; + + default: + return -EINVAL; + } + + switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { + case SND_SOC_DAIFMT_CBS_CFS: + /* CPU is master */ + clk_cfg |= EP93XX_I2S_CLKCFG_MASTER; + break; + + case SND_SOC_DAIFMT_CBM_CFM: + /* Codec is master */ + clk_cfg &= ~EP93XX_I2S_CLKCFG_MASTER; + break; + + default: + return -EINVAL; + } + + switch (fmt & SND_SOC_DAIFMT_INV_MASK) { + case SND_SOC_DAIFMT_NB_NF: + /* Negative bit clock, lrclk low on left word */ + clk_cfg &= ~(EP93XX_I2S_CLKCFG_CKP | EP93XX_I2S_CLKCFG_REL); + break; + + case SND_SOC_DAIFMT_NB_IF: + /* Negative bit clock, lrclk low on right word */ + clk_cfg &= ~EP93XX_I2S_CLKCFG_CKP; + clk_cfg |= EP93XX_I2S_CLKCFG_REL; + break; + + case SND_SOC_DAIFMT_IB_NF: + /* Positive bit clock, lrclk low on left word */ + clk_cfg |= EP93XX_I2S_CLKCFG_CKP; + clk_cfg &= ~EP93XX_I2S_CLKCFG_REL; + break; + + case SND_SOC_DAIFMT_IB_IF: + /* Positive bit clock, lrclk low on right word */ + clk_cfg |= EP93XX_I2S_CLKCFG_CKP | EP93XX_I2S_CLKCFG_REL; + break; + } + + /* Write new register values */ + ep93xx_i2s_write_reg(info, EP93XX_I2S_RXCLKCFG, clk_cfg); + ep93xx_i2s_write_reg(info, EP93XX_I2S_TXCLKCFG, clk_cfg); + ep93xx_i2s_write_reg(info, EP93XX_I2S_RXLINCTRLDATA, lin_ctrl); + ep93xx_i2s_write_reg(info, EP93XX_I2S_TXLINCTRLDATA, lin_ctrl); + return 0; +} + +static int ep93xx_i2s_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct ep93xx_i2s_info *info = snd_soc_dai_get_drvdata(dai); + unsigned word_len, div, sdiv, lrdiv; + int err; + + switch (params_format(params)) { + case SNDRV_PCM_FORMAT_S16_LE: + word_len = EP93XX_I2S_WRDLEN_16; + break; + + case SNDRV_PCM_FORMAT_S24_LE: + word_len = EP93XX_I2S_WRDLEN_24; + break; + + case SNDRV_PCM_FORMAT_S32_LE: + word_len = EP93XX_I2S_WRDLEN_32; + break; + + default: + return -EINVAL; + } + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + ep93xx_i2s_write_reg(info, EP93XX_I2S_TXWRDLEN, word_len); + else + ep93xx_i2s_write_reg(info, EP93XX_I2S_RXWRDLEN, word_len); + + /* + * EP93xx I2S module can be setup so SCLK / LRCLK value can be + * 32, 64, 128. MCLK / SCLK value can be 2 and 4. + * We set LRCLK equal to `rate' and minimum SCLK / LRCLK + * value is 64, because our sample size is 32 bit * 2 channels. + * I2S standard permits us to transmit more bits than + * the codec uses. + */ + div = clk_get_rate(info->mclk) / params_rate(params); + sdiv = 4; + if (div > (256 + 512) / 2) { + lrdiv = 128; + } else { + lrdiv = 64; + if (div < (128 + 256) / 2) + sdiv = 2; + } + + err = clk_set_rate(info->sclk, clk_get_rate(info->mclk) / sdiv); + if (err) + return err; + + err = clk_set_rate(info->lrclk, clk_get_rate(info->sclk) / lrdiv); + if (err) + return err; + + ep93xx_i2s_enable(info, substream->stream); + return 0; +} + +static int ep93xx_i2s_set_sysclk(struct snd_soc_dai *cpu_dai, int clk_id, + unsigned int freq, int dir) +{ + struct ep93xx_i2s_info *info = snd_soc_dai_get_drvdata(cpu_dai); + + if (dir == SND_SOC_CLOCK_IN || clk_id != 0) + return -EINVAL; + + return clk_set_rate(info->mclk, freq); +} + +#ifdef CONFIG_PM +static int ep93xx_i2s_suspend(struct snd_soc_dai *dai) +{ + struct ep93xx_i2s_info *info = snd_soc_dai_get_drvdata(dai); + + if (!dai->active) + return 0; + + ep93xx_i2s_disable(info, SNDRV_PCM_STREAM_PLAYBACK); + ep93xx_i2s_disable(info, SNDRV_PCM_STREAM_CAPTURE); + + return 0; +} + +static int ep93xx_i2s_resume(struct snd_soc_dai *dai) +{ + struct ep93xx_i2s_info *info = snd_soc_dai_get_drvdata(dai); + + if (!dai->active) + return 0; + + ep93xx_i2s_enable(info, SNDRV_PCM_STREAM_PLAYBACK); + ep93xx_i2s_enable(info, SNDRV_PCM_STREAM_CAPTURE); + + return 0; +} +#else +#define ep93xx_i2s_suspend NULL +#define ep93xx_i2s_resume NULL +#endif + +static const struct snd_soc_dai_ops ep93xx_i2s_dai_ops = { + .startup = ep93xx_i2s_startup, + .shutdown = ep93xx_i2s_shutdown, + .hw_params = ep93xx_i2s_hw_params, + .set_sysclk = ep93xx_i2s_set_sysclk, + .set_fmt = ep93xx_i2s_set_dai_fmt, +}; + +#define EP93XX_I2S_FORMATS (SNDRV_PCM_FMTBIT_S32_LE) + +static struct snd_soc_dai_driver ep93xx_i2s_dai = { + .symmetric_rates= 1, + .suspend = ep93xx_i2s_suspend, + .resume = ep93xx_i2s_resume, + .playback = { + .channels_min = 2, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_8000_192000, + .formats = EP93XX_I2S_FORMATS, + }, + .capture = { + .channels_min = 2, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_8000_192000, + .formats = EP93XX_I2S_FORMATS, + }, + .ops = &ep93xx_i2s_dai_ops, +}; + +static int ep93xx_i2s_probe(struct platform_device *pdev) +{ + struct ep93xx_i2s_info *info; + struct resource *res; + int err; + + info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL); + if (!info) + return -ENOMEM; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) + return -ENODEV; + + info->regs = devm_request_and_ioremap(&pdev->dev, res); + if (!info->regs) + return -ENXIO; + + info->mclk = clk_get(&pdev->dev, "mclk"); + if (IS_ERR(info->mclk)) { + err = PTR_ERR(info->mclk); + goto fail; + } + + info->sclk = clk_get(&pdev->dev, "sclk"); + if (IS_ERR(info->sclk)) { + err = PTR_ERR(info->sclk); + goto fail_put_mclk; + } + + info->lrclk = clk_get(&pdev->dev, "lrclk"); + if (IS_ERR(info->lrclk)) { + err = PTR_ERR(info->lrclk); + goto fail_put_sclk; + } + + dev_set_drvdata(&pdev->dev, info); + info->dma_params = ep93xx_i2s_dma_params; + + err = snd_soc_register_dai(&pdev->dev, &ep93xx_i2s_dai); + if (err) + goto fail_put_lrclk; + + return 0; + +fail_put_lrclk: + dev_set_drvdata(&pdev->dev, NULL); + clk_put(info->lrclk); +fail_put_sclk: + clk_put(info->sclk); +fail_put_mclk: + clk_put(info->mclk); +fail: + return err; +} + +static int __devexit ep93xx_i2s_remove(struct platform_device *pdev) +{ + struct ep93xx_i2s_info *info = dev_get_drvdata(&pdev->dev); + + snd_soc_unregister_dai(&pdev->dev); + dev_set_drvdata(&pdev->dev, NULL); + clk_put(info->lrclk); + clk_put(info->sclk); + clk_put(info->mclk); + return 0; +} + +static struct platform_driver ep93xx_i2s_driver = { + .probe = ep93xx_i2s_probe, + .remove = __devexit_p(ep93xx_i2s_remove), + .driver = { + .name = "ep93xx-i2s", + .owner = THIS_MODULE, + }, +}; + +module_platform_driver(ep93xx_i2s_driver); + +MODULE_ALIAS("platform:ep93xx-i2s"); +MODULE_AUTHOR("Ryan Mallon"); +MODULE_DESCRIPTION("EP93XX I2S driver"); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/cirrus/ep93xx-pcm.c b/sound/soc/cirrus/ep93xx-pcm.c new file mode 100644 index 000000000000..4eea98b42bc8 --- /dev/null +++ b/sound/soc/cirrus/ep93xx-pcm.c @@ -0,0 +1,242 @@ +/* + * linux/sound/arm/ep93xx-pcm.c - EP93xx ALSA PCM interface + * + * Copyright (C) 2006 Lennert Buytenhek + * Copyright (C) 2006 Applied Data Systems + * + * Rewritten for the SoC audio subsystem (Based on PXA2xx code): + * Copyright (c) 2008 Ryan Mallon + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "ep93xx-pcm.h" + +static const struct snd_pcm_hardware ep93xx_pcm_hardware = { + .info = (SNDRV_PCM_INFO_MMAP | + SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_BLOCK_TRANSFER), + + .rates = SNDRV_PCM_RATE_8000_192000, + .rate_min = SNDRV_PCM_RATE_8000, + .rate_max = SNDRV_PCM_RATE_192000, + + .formats = (SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S32_LE), + + .buffer_bytes_max = 131072, + .period_bytes_min = 32, + .period_bytes_max = 32768, + .periods_min = 1, + .periods_max = 32, + .fifo_size = 32, +}; + +static bool ep93xx_pcm_dma_filter(struct dma_chan *chan, void *filter_param) +{ + struct ep93xx_dma_data *data = filter_param; + + if (data->direction == ep93xx_dma_chan_direction(chan)) { + chan->private = data; + return true; + } + + return false; +} + +static int ep93xx_pcm_open(struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + struct ep93xx_pcm_dma_params *dma_params; + struct ep93xx_dma_data *dma_data; + int ret; + + snd_soc_set_runtime_hwparams(substream, &ep93xx_pcm_hardware); + + dma_data = kmalloc(sizeof(*dma_data), GFP_KERNEL); + if (!dma_data) + return -ENOMEM; + + dma_params = snd_soc_dai_get_dma_data(cpu_dai, substream); + dma_data->port = dma_params->dma_port; + dma_data->name = dma_params->name; + dma_data->direction = snd_pcm_substream_to_dma_direction(substream); + + ret = snd_dmaengine_pcm_open(substream, ep93xx_pcm_dma_filter, dma_data); + if (ret) { + kfree(dma_data); + return ret; + } + + snd_dmaengine_pcm_set_data(substream, dma_data); + + return 0; +} + +static int ep93xx_pcm_close(struct snd_pcm_substream *substream) +{ + struct dma_data *dma_data = snd_dmaengine_pcm_get_data(substream); + + snd_dmaengine_pcm_close(substream); + kfree(dma_data); + return 0; +} + +static int ep93xx_pcm_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); + + return 0; +} + +static int ep93xx_pcm_hw_free(struct snd_pcm_substream *substream) +{ + snd_pcm_set_runtime_buffer(substream, NULL); + return 0; +} + +static int ep93xx_pcm_mmap(struct snd_pcm_substream *substream, + struct vm_area_struct *vma) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + + return dma_mmap_writecombine(substream->pcm->card->dev, vma, + runtime->dma_area, + runtime->dma_addr, + runtime->dma_bytes); +} + +static struct snd_pcm_ops ep93xx_pcm_ops = { + .open = ep93xx_pcm_open, + .close = ep93xx_pcm_close, + .ioctl = snd_pcm_lib_ioctl, + .hw_params = ep93xx_pcm_hw_params, + .hw_free = ep93xx_pcm_hw_free, + .trigger = snd_dmaengine_pcm_trigger, + .pointer = snd_dmaengine_pcm_pointer_no_residue, + .mmap = ep93xx_pcm_mmap, +}; + +static int ep93xx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream) +{ + struct snd_pcm_substream *substream = pcm->streams[stream].substream; + struct snd_dma_buffer *buf = &substream->dma_buffer; + size_t size = ep93xx_pcm_hardware.buffer_bytes_max; + + buf->dev.type = SNDRV_DMA_TYPE_DEV; + buf->dev.dev = pcm->card->dev; + buf->private_data = NULL; + buf->area = dma_alloc_writecombine(pcm->card->dev, size, + &buf->addr, GFP_KERNEL); + buf->bytes = size; + + return (buf->area == NULL) ? -ENOMEM : 0; +} + +static void ep93xx_pcm_free_dma_buffers(struct snd_pcm *pcm) +{ + struct snd_pcm_substream *substream; + struct snd_dma_buffer *buf; + int stream; + + for (stream = 0; stream < 2; stream++) { + substream = pcm->streams[stream].substream; + if (!substream) + continue; + + buf = &substream->dma_buffer; + if (!buf->area) + continue; + + dma_free_writecombine(pcm->card->dev, buf->bytes, buf->area, + buf->addr); + buf->area = NULL; + } +} + +static u64 ep93xx_pcm_dmamask = DMA_BIT_MASK(32); + +static int ep93xx_pcm_new(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_card *card = rtd->card->snd_card; + struct snd_pcm *pcm = rtd->pcm; + int ret = 0; + + if (!card->dev->dma_mask) + card->dev->dma_mask = &ep93xx_pcm_dmamask; + if (!card->dev->coherent_dma_mask) + card->dev->coherent_dma_mask = DMA_BIT_MASK(32); + + if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) { + ret = ep93xx_pcm_preallocate_dma_buffer(pcm, + SNDRV_PCM_STREAM_PLAYBACK); + if (ret) + return ret; + } + + if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) { + ret = ep93xx_pcm_preallocate_dma_buffer(pcm, + SNDRV_PCM_STREAM_CAPTURE); + if (ret) + return ret; + } + + return 0; +} + +static struct snd_soc_platform_driver ep93xx_soc_platform = { + .ops = &ep93xx_pcm_ops, + .pcm_new = &ep93xx_pcm_new, + .pcm_free = &ep93xx_pcm_free_dma_buffers, +}; + +static int __devinit ep93xx_soc_platform_probe(struct platform_device *pdev) +{ + return snd_soc_register_platform(&pdev->dev, &ep93xx_soc_platform); +} + +static int __devexit ep93xx_soc_platform_remove(struct platform_device *pdev) +{ + snd_soc_unregister_platform(&pdev->dev); + return 0; +} + +static struct platform_driver ep93xx_pcm_driver = { + .driver = { + .name = "ep93xx-pcm-audio", + .owner = THIS_MODULE, + }, + + .probe = ep93xx_soc_platform_probe, + .remove = __devexit_p(ep93xx_soc_platform_remove), +}; + +module_platform_driver(ep93xx_pcm_driver); + +MODULE_AUTHOR("Ryan Mallon"); +MODULE_DESCRIPTION("EP93xx ALSA PCM interface"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:ep93xx-pcm-audio"); diff --git a/sound/soc/cirrus/ep93xx-pcm.h b/sound/soc/cirrus/ep93xx-pcm.h new file mode 100644 index 000000000000..111e1121ecb8 --- /dev/null +++ b/sound/soc/cirrus/ep93xx-pcm.h @@ -0,0 +1,20 @@ +/* + * sound/soc/ep93xx/ep93xx-pcm.h - EP93xx ALSA PCM interface + * + * Copyright (C) 2006 Lennert Buytenhek + * Copyright (C) 2006 Applied Data Systems + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef _EP93XX_SND_SOC_PCM_H +#define _EP93XX_SND_SOC_PCM_H + +struct ep93xx_pcm_dma_params { + char *name; + int dma_port; +}; + +#endif /* _EP93XX_SND_SOC_PCM_H */ diff --git a/sound/soc/cirrus/simone.c b/sound/soc/cirrus/simone.c new file mode 100644 index 000000000000..dd997094eb30 --- /dev/null +++ b/sound/soc/cirrus/simone.c @@ -0,0 +1,90 @@ +/* + * simone.c -- ASoC audio for Simplemachines Sim.One board + * + * Copyright (c) 2010 Mika Westerberg + * + * Based on snappercl15 machine driver by Ryan Mallon. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include "ep93xx-pcm.h" + +static struct snd_soc_dai_link simone_dai = { + .name = "AC97", + .stream_name = "AC97 HiFi", + .cpu_dai_name = "ep93xx-ac97", + .codec_dai_name = "ac97-hifi", + .codec_name = "ac97-codec", + .platform_name = "ep93xx-pcm-audio", +}; + +static struct snd_soc_card snd_soc_simone = { + .name = "Sim.One", + .owner = THIS_MODULE, + .dai_link = &simone_dai, + .num_links = 1, +}; + +static struct platform_device *simone_snd_ac97_device; + +static int __devinit simone_probe(struct platform_device *pdev) +{ + struct snd_soc_card *card = &snd_soc_simone; + int ret; + + simone_snd_ac97_device = platform_device_register_simple("ac97-codec", + -1, NULL, 0); + if (IS_ERR(simone_snd_ac97_device)) + return PTR_ERR(simone_snd_ac97_device); + + card->dev = &pdev->dev; + + ret = snd_soc_register_card(card); + if (ret) { + dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", + ret); + platform_device_unregister(simone_snd_ac97_device); + } + + return ret; +} + +static int __devexit simone_remove(struct platform_device *pdev) +{ + struct snd_soc_card *card = platform_get_drvdata(pdev); + + snd_soc_unregister_card(card); + platform_device_unregister(simone_snd_ac97_device); + + return 0; +} + +static struct platform_driver simone_driver = { + .driver = { + .name = "simone-audio", + .owner = THIS_MODULE, + }, + .probe = simone_probe, + .remove = __devexit_p(simone_remove), +}; + +module_platform_driver(simone_driver); + +MODULE_DESCRIPTION("ALSA SoC Simplemachines Sim.One"); +MODULE_AUTHOR("Mika Westerberg "); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:simone-audio"); diff --git a/sound/soc/cirrus/snappercl15.c b/sound/soc/cirrus/snappercl15.c new file mode 100644 index 000000000000..a193cea3cf3c --- /dev/null +++ b/sound/soc/cirrus/snappercl15.c @@ -0,0 +1,146 @@ +/* + * snappercl15.c -- SoC audio for Bluewater Systems Snapper CL15 module + * + * Copyright (C) 2008 Bluewater Systems Ltd + * Author: Ryan Mallon + * + * 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 "../codecs/tlv320aic23.h" +#include "ep93xx-pcm.h" + +#define CODEC_CLOCK 5644800 + +static int snappercl15_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_dai *codec_dai = rtd->codec_dai; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + int err; + + err = snd_soc_dai_set_sysclk(codec_dai, 0, CODEC_CLOCK, + SND_SOC_CLOCK_IN); + if (err) + return err; + + err = snd_soc_dai_set_sysclk(cpu_dai, 0, CODEC_CLOCK, + SND_SOC_CLOCK_OUT); + if (err) + return err; + + return 0; +} + +static struct snd_soc_ops snappercl15_ops = { + .hw_params = snappercl15_hw_params, +}; + +static const struct snd_soc_dapm_widget tlv320aic23_dapm_widgets[] = { + SND_SOC_DAPM_HP("Headphone Jack", NULL), + SND_SOC_DAPM_LINE("Line In", NULL), + SND_SOC_DAPM_MIC("Mic Jack", NULL), +}; + +static const struct snd_soc_dapm_route audio_map[] = { + {"Headphone Jack", NULL, "LHPOUT"}, + {"Headphone Jack", NULL, "RHPOUT"}, + + {"LLINEIN", NULL, "Line In"}, + {"RLINEIN", NULL, "Line In"}, + + {"MICIN", NULL, "Mic Jack"}, +}; + +static int snappercl15_tlv320aic23_init(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_soc_codec *codec = rtd->codec; + struct snd_soc_dapm_context *dapm = &codec->dapm; + + snd_soc_dapm_new_controls(dapm, tlv320aic23_dapm_widgets, + ARRAY_SIZE(tlv320aic23_dapm_widgets)); + + snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map)); + return 0; +} + +static struct snd_soc_dai_link snappercl15_dai = { + .name = "tlv320aic23", + .stream_name = "AIC23", + .cpu_dai_name = "ep93xx-i2s", + .codec_dai_name = "tlv320aic23-hifi", + .codec_name = "tlv320aic23-codec.0-001a", + .platform_name = "ep93xx-pcm-audio", + .init = snappercl15_tlv320aic23_init, + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_IF | + SND_SOC_DAIFMT_CBS_CFS, + .ops = &snappercl15_ops, +}; + +static struct snd_soc_card snd_soc_snappercl15 = { + .name = "Snapper CL15", + .owner = THIS_MODULE, + .dai_link = &snappercl15_dai, + .num_links = 1, +}; + +static int __devinit snappercl15_probe(struct platform_device *pdev) +{ + struct snd_soc_card *card = &snd_soc_snappercl15; + int ret; + + ret = ep93xx_i2s_acquire(); + if (ret) + return ret; + + card->dev = &pdev->dev; + + ret = snd_soc_register_card(card); + if (ret) { + dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", + ret); + ep93xx_i2s_release(); + } + + return ret; +} + +static int __devexit snappercl15_remove(struct platform_device *pdev) +{ + struct snd_soc_card *card = platform_get_drvdata(pdev); + + snd_soc_unregister_card(card); + ep93xx_i2s_release(); + + return 0; +} + +static struct platform_driver snappercl15_driver = { + .driver = { + .name = "snappercl15-audio", + .owner = THIS_MODULE, + }, + .probe = snappercl15_probe, + .remove = __devexit_p(snappercl15_remove), +}; + +module_platform_driver(snappercl15_driver); + +MODULE_AUTHOR("Ryan Mallon"); +MODULE_DESCRIPTION("ALSA SoC Snapper CL15"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:snappercl15-audio"); diff --git a/sound/soc/ep93xx/Kconfig b/sound/soc/ep93xx/Kconfig deleted file mode 100644 index 88143db7e753..000000000000 --- a/sound/soc/ep93xx/Kconfig +++ /dev/null @@ -1,42 +0,0 @@ -config SND_EP93XX_SOC - tristate "SoC Audio support for the Cirrus Logic EP93xx series" - depends on ARCH_EP93XX && SND_SOC - select SND_SOC_DMAENGINE_PCM - help - Say Y or M if you want to add support for codecs attached to - the EP93xx I2S or AC97 interfaces. - -config SND_EP93XX_SOC_I2S - tristate - -config SND_EP93XX_SOC_AC97 - tristate - select AC97_BUS - select SND_SOC_AC97_BUS - -config SND_EP93XX_SOC_SNAPPERCL15 - tristate "SoC Audio support for Bluewater Systems Snapper CL15 module" - depends on SND_EP93XX_SOC && MACH_SNAPPER_CL15 - select SND_EP93XX_SOC_I2S - select SND_SOC_TLV320AIC23 - help - Say Y or M here if you want to add support for I2S audio on the - Bluewater Systems Snapper CL15 module. - -config SND_EP93XX_SOC_SIMONE - tristate "SoC Audio support for Simplemachines Sim.One board" - depends on SND_EP93XX_SOC && MACH_SIM_ONE - select SND_EP93XX_SOC_AC97 - select SND_SOC_AC97_CODEC - help - Say Y or M here if you want to add support for AC97 audio on the - Simplemachines Sim.One board. - -config SND_EP93XX_SOC_EDB93XX - tristate "SoC Audio support for Cirrus Logic EDB93xx boards" - depends on SND_EP93XX_SOC && (MACH_EDB9301 || MACH_EDB9302 || MACH_EDB9302A || MACH_EDB9307A || MACH_EDB9315A) - select SND_EP93XX_SOC_I2S - select SND_SOC_CS4271 - help - Say Y or M here if you want to add support for I2S audio on the - Cirrus Logic EDB93xx boards. diff --git a/sound/soc/ep93xx/Makefile b/sound/soc/ep93xx/Makefile deleted file mode 100644 index 5514146cbdf0..000000000000 --- a/sound/soc/ep93xx/Makefile +++ /dev/null @@ -1,17 +0,0 @@ -# EP93xx Platform Support -snd-soc-ep93xx-objs := ep93xx-pcm.o -snd-soc-ep93xx-i2s-objs := ep93xx-i2s.o -snd-soc-ep93xx-ac97-objs := ep93xx-ac97.o - -obj-$(CONFIG_SND_EP93XX_SOC) += snd-soc-ep93xx.o -obj-$(CONFIG_SND_EP93XX_SOC_I2S) += snd-soc-ep93xx-i2s.o -obj-$(CONFIG_SND_EP93XX_SOC_AC97) += snd-soc-ep93xx-ac97.o - -# EP93XX Machine Support -snd-soc-snappercl15-objs := snappercl15.o -snd-soc-simone-objs := simone.o -snd-soc-edb93xx-objs := edb93xx.o - -obj-$(CONFIG_SND_EP93XX_SOC_SNAPPERCL15) += snd-soc-snappercl15.o -obj-$(CONFIG_SND_EP93XX_SOC_SIMONE) += snd-soc-simone.o -obj-$(CONFIG_SND_EP93XX_SOC_EDB93XX) += snd-soc-edb93xx.o diff --git a/sound/soc/ep93xx/edb93xx.c b/sound/soc/ep93xx/edb93xx.c deleted file mode 100644 index e01cb02abd3a..000000000000 --- a/sound/soc/ep93xx/edb93xx.c +++ /dev/null @@ -1,128 +0,0 @@ -/* - * SoC audio for EDB93xx - * - * Copyright (c) 2010 Alexander Sverdlin - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * This driver support CS4271 codec being master or slave, working - * in control port mode, connected either via SPI or I2C. - * The data format accepted is I2S or left-justified. - * DAPM support not implemented. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include "ep93xx-pcm.h" - -static int edb93xx_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *codec_dai = rtd->codec_dai; - struct snd_soc_dai *cpu_dai = rtd->cpu_dai; - int err; - unsigned int mclk_rate; - unsigned int rate = params_rate(params); - - /* - * According to CS4271 datasheet we use MCLK/LRCK=256 for - * rates below 50kHz and 128 for higher sample rates - */ - if (rate < 50000) - mclk_rate = rate * 64 * 4; - else - mclk_rate = rate * 64 * 2; - - err = snd_soc_dai_set_sysclk(codec_dai, 0, mclk_rate, - SND_SOC_CLOCK_IN); - if (err) - return err; - - return snd_soc_dai_set_sysclk(cpu_dai, 0, mclk_rate, - SND_SOC_CLOCK_OUT); -} - -static struct snd_soc_ops edb93xx_ops = { - .hw_params = edb93xx_hw_params, -}; - -static struct snd_soc_dai_link edb93xx_dai = { - .name = "CS4271", - .stream_name = "CS4271 HiFi", - .platform_name = "ep93xx-pcm-audio", - .cpu_dai_name = "ep93xx-i2s", - .codec_name = "spi0.0", - .codec_dai_name = "cs4271-hifi", - .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_IF | - SND_SOC_DAIFMT_CBS_CFS, - .ops = &edb93xx_ops, -}; - -static struct snd_soc_card snd_soc_edb93xx = { - .name = "EDB93XX", - .owner = THIS_MODULE, - .dai_link = &edb93xx_dai, - .num_links = 1, -}; - -static int __devinit edb93xx_probe(struct platform_device *pdev) -{ - struct snd_soc_card *card = &snd_soc_edb93xx; - int ret; - - ret = ep93xx_i2s_acquire(); - if (ret) - return ret; - - card->dev = &pdev->dev; - - ret = snd_soc_register_card(card); - if (ret) { - dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", - ret); - ep93xx_i2s_release(); - } - - return ret; -} - -static int __devexit edb93xx_remove(struct platform_device *pdev) -{ - struct snd_soc_card *card = platform_get_drvdata(pdev); - - snd_soc_unregister_card(card); - ep93xx_i2s_release(); - - return 0; -} - -static struct platform_driver edb93xx_driver = { - .driver = { - .name = "edb93xx-audio", - .owner = THIS_MODULE, - }, - .probe = edb93xx_probe, - .remove = __devexit_p(edb93xx_remove), -}; - -module_platform_driver(edb93xx_driver); - -MODULE_AUTHOR("Alexander Sverdlin "); -MODULE_DESCRIPTION("ALSA SoC EDB93xx"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:edb93xx-audio"); diff --git a/sound/soc/ep93xx/ep93xx-ac97.c b/sound/soc/ep93xx/ep93xx-ac97.c deleted file mode 100644 index bdffab33e160..000000000000 --- a/sound/soc/ep93xx/ep93xx-ac97.c +++ /dev/null @@ -1,435 +0,0 @@ -/* - * ASoC driver for Cirrus Logic EP93xx AC97 controller. - * - * Copyright (c) 2010 Mika Westerberg - * - * Based on s3c-ac97 ASoC driver by Jaswinder Singh. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include "ep93xx-pcm.h" - -/* - * Per channel (1-4) registers. - */ -#define AC97CH(n) (((n) - 1) * 0x20) - -#define AC97DR(n) (AC97CH(n) + 0x0000) - -#define AC97RXCR(n) (AC97CH(n) + 0x0004) -#define AC97RXCR_REN BIT(0) -#define AC97RXCR_RX3 BIT(3) -#define AC97RXCR_RX4 BIT(4) -#define AC97RXCR_CM BIT(15) - -#define AC97TXCR(n) (AC97CH(n) + 0x0008) -#define AC97TXCR_TEN BIT(0) -#define AC97TXCR_TX3 BIT(3) -#define AC97TXCR_TX4 BIT(4) -#define AC97TXCR_CM BIT(15) - -#define AC97SR(n) (AC97CH(n) + 0x000c) -#define AC97SR_TXFE BIT(1) -#define AC97SR_TXUE BIT(6) - -#define AC97RISR(n) (AC97CH(n) + 0x0010) -#define AC97ISR(n) (AC97CH(n) + 0x0014) -#define AC97IE(n) (AC97CH(n) + 0x0018) - -/* - * Global AC97 controller registers. - */ -#define AC97S1DATA 0x0080 -#define AC97S2DATA 0x0084 -#define AC97S12DATA 0x0088 - -#define AC97RGIS 0x008c -#define AC97GIS 0x0090 -#define AC97IM 0x0094 -/* - * Common bits for RGIS, GIS and IM registers. - */ -#define AC97_SLOT2RXVALID BIT(1) -#define AC97_CODECREADY BIT(5) -#define AC97_SLOT2TXCOMPLETE BIT(6) - -#define AC97EOI 0x0098 -#define AC97EOI_WINT BIT(0) -#define AC97EOI_CODECREADY BIT(1) - -#define AC97GCR 0x009c -#define AC97GCR_AC97IFE BIT(0) - -#define AC97RESET 0x00a0 -#define AC97RESET_TIMEDRESET BIT(0) - -#define AC97SYNC 0x00a4 -#define AC97SYNC_TIMEDSYNC BIT(0) - -#define AC97_TIMEOUT msecs_to_jiffies(5) - -/** - * struct ep93xx_ac97_info - EP93xx AC97 controller info structure - * @lock: mutex serializing access to the bus (slot 1 & 2 ops) - * @dev: pointer to the platform device dev structure - * @regs: mapped AC97 controller registers - * @done: bus ops wait here for an interrupt - */ -struct ep93xx_ac97_info { - struct mutex lock; - struct device *dev; - void __iomem *regs; - struct completion done; -}; - -/* currently ALSA only supports a single AC97 device */ -static struct ep93xx_ac97_info *ep93xx_ac97_info; - -static struct ep93xx_pcm_dma_params ep93xx_ac97_pcm_out = { - .name = "ac97-pcm-out", - .dma_port = EP93XX_DMA_AAC1, -}; - -static struct ep93xx_pcm_dma_params ep93xx_ac97_pcm_in = { - .name = "ac97-pcm-in", - .dma_port = EP93XX_DMA_AAC1, -}; - -static inline unsigned ep93xx_ac97_read_reg(struct ep93xx_ac97_info *info, - unsigned reg) -{ - return __raw_readl(info->regs + reg); -} - -static inline void ep93xx_ac97_write_reg(struct ep93xx_ac97_info *info, - unsigned reg, unsigned val) -{ - __raw_writel(val, info->regs + reg); -} - -static unsigned short ep93xx_ac97_read(struct snd_ac97 *ac97, - unsigned short reg) -{ - struct ep93xx_ac97_info *info = ep93xx_ac97_info; - unsigned short val; - - mutex_lock(&info->lock); - - ep93xx_ac97_write_reg(info, AC97S1DATA, reg); - ep93xx_ac97_write_reg(info, AC97IM, AC97_SLOT2RXVALID); - if (!wait_for_completion_timeout(&info->done, AC97_TIMEOUT)) { - dev_warn(info->dev, "timeout reading register %x\n", reg); - mutex_unlock(&info->lock); - return -ETIMEDOUT; - } - val = (unsigned short)ep93xx_ac97_read_reg(info, AC97S2DATA); - - mutex_unlock(&info->lock); - return val; -} - -static void ep93xx_ac97_write(struct snd_ac97 *ac97, - unsigned short reg, - unsigned short val) -{ - struct ep93xx_ac97_info *info = ep93xx_ac97_info; - - mutex_lock(&info->lock); - - /* - * Writes to the codec need to be done so that slot 2 is filled in - * before slot 1. - */ - ep93xx_ac97_write_reg(info, AC97S2DATA, val); - ep93xx_ac97_write_reg(info, AC97S1DATA, reg); - - ep93xx_ac97_write_reg(info, AC97IM, AC97_SLOT2TXCOMPLETE); - if (!wait_for_completion_timeout(&info->done, AC97_TIMEOUT)) - dev_warn(info->dev, "timeout writing register %x\n", reg); - - mutex_unlock(&info->lock); -} - -static void ep93xx_ac97_warm_reset(struct snd_ac97 *ac97) -{ - struct ep93xx_ac97_info *info = ep93xx_ac97_info; - - mutex_lock(&info->lock); - - /* - * We are assuming that before this functions gets called, the codec - * BIT_CLK is stopped by forcing the codec into powerdown mode. We can - * control the SYNC signal directly via AC97SYNC register. Using - * TIMEDSYNC the controller will keep the SYNC high > 1us. - */ - ep93xx_ac97_write_reg(info, AC97SYNC, AC97SYNC_TIMEDSYNC); - ep93xx_ac97_write_reg(info, AC97IM, AC97_CODECREADY); - if (!wait_for_completion_timeout(&info->done, AC97_TIMEOUT)) - dev_warn(info->dev, "codec warm reset timeout\n"); - - mutex_unlock(&info->lock); -} - -static void ep93xx_ac97_cold_reset(struct snd_ac97 *ac97) -{ - struct ep93xx_ac97_info *info = ep93xx_ac97_info; - - mutex_lock(&info->lock); - - /* - * For doing cold reset, we disable the AC97 controller interface, clear - * WINT and CODECREADY bits, and finally enable the interface again. - */ - ep93xx_ac97_write_reg(info, AC97GCR, 0); - ep93xx_ac97_write_reg(info, AC97EOI, AC97EOI_CODECREADY | AC97EOI_WINT); - ep93xx_ac97_write_reg(info, AC97GCR, AC97GCR_AC97IFE); - - /* - * Now, assert the reset and wait for the codec to become ready. - */ - ep93xx_ac97_write_reg(info, AC97RESET, AC97RESET_TIMEDRESET); - ep93xx_ac97_write_reg(info, AC97IM, AC97_CODECREADY); - if (!wait_for_completion_timeout(&info->done, AC97_TIMEOUT)) - dev_warn(info->dev, "codec cold reset timeout\n"); - - /* - * Give the codec some time to come fully out from the reset. This way - * we ensure that the subsequent reads/writes will work. - */ - usleep_range(15000, 20000); - - mutex_unlock(&info->lock); -} - -static irqreturn_t ep93xx_ac97_interrupt(int irq, void *dev_id) -{ - struct ep93xx_ac97_info *info = dev_id; - unsigned status, mask; - - /* - * Just mask out the interrupt and wake up the waiting thread. - * Interrupts are cleared via reading/writing to slot 1 & 2 registers by - * the waiting thread. - */ - status = ep93xx_ac97_read_reg(info, AC97GIS); - mask = ep93xx_ac97_read_reg(info, AC97IM); - mask &= ~status; - ep93xx_ac97_write_reg(info, AC97IM, mask); - - complete(&info->done); - return IRQ_HANDLED; -} - -struct snd_ac97_bus_ops soc_ac97_ops = { - .read = ep93xx_ac97_read, - .write = ep93xx_ac97_write, - .reset = ep93xx_ac97_cold_reset, - .warm_reset = ep93xx_ac97_warm_reset, -}; -EXPORT_SYMBOL_GPL(soc_ac97_ops); - -static int ep93xx_ac97_trigger(struct snd_pcm_substream *substream, - int cmd, struct snd_soc_dai *dai) -{ - struct ep93xx_ac97_info *info = snd_soc_dai_get_drvdata(dai); - unsigned v = 0; - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - case SNDRV_PCM_TRIGGER_RESUME: - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - /* - * Enable compact mode, TX slots 3 & 4, and the TX FIFO - * itself. - */ - v |= AC97TXCR_CM; - v |= AC97TXCR_TX3 | AC97TXCR_TX4; - v |= AC97TXCR_TEN; - ep93xx_ac97_write_reg(info, AC97TXCR(1), v); - } else { - /* - * Enable compact mode, RX slots 3 & 4, and the RX FIFO - * itself. - */ - v |= AC97RXCR_CM; - v |= AC97RXCR_RX3 | AC97RXCR_RX4; - v |= AC97RXCR_REN; - ep93xx_ac97_write_reg(info, AC97RXCR(1), v); - } - break; - - case SNDRV_PCM_TRIGGER_STOP: - case SNDRV_PCM_TRIGGER_SUSPEND: - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - /* - * As per Cirrus EP93xx errata described below: - * - * http://www.cirrus.com/en/pubs/errata/ER667E2B.pdf - * - * we will wait for the TX FIFO to be empty before - * clearing the TEN bit. - */ - unsigned long timeout = jiffies + AC97_TIMEOUT; - - do { - v = ep93xx_ac97_read_reg(info, AC97SR(1)); - if (time_after(jiffies, timeout)) { - dev_warn(info->dev, "TX timeout\n"); - break; - } - } while (!(v & (AC97SR_TXFE | AC97SR_TXUE))); - - /* disable the TX FIFO */ - ep93xx_ac97_write_reg(info, AC97TXCR(1), 0); - } else { - /* disable the RX FIFO */ - ep93xx_ac97_write_reg(info, AC97RXCR(1), 0); - } - break; - - default: - dev_warn(info->dev, "unknown command %d\n", cmd); - return -EINVAL; - } - - return 0; -} - -static int ep93xx_ac97_startup(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - struct ep93xx_pcm_dma_params *dma_data; - - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - dma_data = &ep93xx_ac97_pcm_out; - else - dma_data = &ep93xx_ac97_pcm_in; - - snd_soc_dai_set_dma_data(dai, substream, dma_data); - return 0; -} - -static const struct snd_soc_dai_ops ep93xx_ac97_dai_ops = { - .startup = ep93xx_ac97_startup, - .trigger = ep93xx_ac97_trigger, -}; - -static struct snd_soc_dai_driver ep93xx_ac97_dai = { - .name = "ep93xx-ac97", - .id = 0, - .ac97_control = 1, - .playback = { - .stream_name = "AC97 Playback", - .channels_min = 2, - .channels_max = 2, - .rates = SNDRV_PCM_RATE_8000_48000, - .formats = SNDRV_PCM_FMTBIT_S16_LE, - }, - .capture = { - .stream_name = "AC97 Capture", - .channels_min = 2, - .channels_max = 2, - .rates = SNDRV_PCM_RATE_8000_48000, - .formats = SNDRV_PCM_FMTBIT_S16_LE, - }, - .ops = &ep93xx_ac97_dai_ops, -}; - -static int __devinit ep93xx_ac97_probe(struct platform_device *pdev) -{ - struct ep93xx_ac97_info *info; - struct resource *res; - unsigned int irq; - int ret; - - info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL); - if (!info) - return -ENOMEM; - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) - return -ENODEV; - - info->regs = devm_request_and_ioremap(&pdev->dev, res); - if (!info->regs) - return -ENXIO; - - irq = platform_get_irq(pdev, 0); - if (!irq) - return -ENODEV; - - ret = devm_request_irq(&pdev->dev, irq, ep93xx_ac97_interrupt, - IRQF_TRIGGER_HIGH, pdev->name, info); - if (ret) - goto fail; - - dev_set_drvdata(&pdev->dev, info); - - mutex_init(&info->lock); - init_completion(&info->done); - info->dev = &pdev->dev; - - ep93xx_ac97_info = info; - platform_set_drvdata(pdev, info); - - ret = snd_soc_register_dai(&pdev->dev, &ep93xx_ac97_dai); - if (ret) - goto fail; - - return 0; - -fail: - platform_set_drvdata(pdev, NULL); - ep93xx_ac97_info = NULL; - dev_set_drvdata(&pdev->dev, NULL); - return ret; -} - -static int __devexit ep93xx_ac97_remove(struct platform_device *pdev) -{ - struct ep93xx_ac97_info *info = platform_get_drvdata(pdev); - - snd_soc_unregister_dai(&pdev->dev); - - /* disable the AC97 controller */ - ep93xx_ac97_write_reg(info, AC97GCR, 0); - - platform_set_drvdata(pdev, NULL); - ep93xx_ac97_info = NULL; - dev_set_drvdata(&pdev->dev, NULL); - - return 0; -} - -static struct platform_driver ep93xx_ac97_driver = { - .probe = ep93xx_ac97_probe, - .remove = __devexit_p(ep93xx_ac97_remove), - .driver = { - .name = "ep93xx-ac97", - .owner = THIS_MODULE, - }, -}; - -module_platform_driver(ep93xx_ac97_driver); - -MODULE_DESCRIPTION("EP93xx AC97 ASoC Driver"); -MODULE_AUTHOR("Mika Westerberg "); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:ep93xx-ac97"); diff --git a/sound/soc/ep93xx/ep93xx-i2s.c b/sound/soc/ep93xx/ep93xx-i2s.c deleted file mode 100644 index 8df8f6dc474f..000000000000 --- a/sound/soc/ep93xx/ep93xx-i2s.c +++ /dev/null @@ -1,451 +0,0 @@ -/* - * linux/sound/soc/ep93xx-i2s.c - * EP93xx I2S driver - * - * Copyright (C) 2010 Ryan Mallon - * - * Based on the original driver by: - * Copyright (C) 2007 Chase Douglas - * Copyright (C) 2006 Lennert Buytenhek - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - */ - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "ep93xx-pcm.h" - -#define EP93XX_I2S_TXCLKCFG 0x00 -#define EP93XX_I2S_RXCLKCFG 0x04 -#define EP93XX_I2S_GLCTRL 0x0C - -#define EP93XX_I2S_TXLINCTRLDATA 0x28 -#define EP93XX_I2S_TXCTRL 0x2C -#define EP93XX_I2S_TXWRDLEN 0x30 -#define EP93XX_I2S_TX0EN 0x34 - -#define EP93XX_I2S_RXLINCTRLDATA 0x58 -#define EP93XX_I2S_RXCTRL 0x5C -#define EP93XX_I2S_RXWRDLEN 0x60 -#define EP93XX_I2S_RX0EN 0x64 - -#define EP93XX_I2S_WRDLEN_16 (0 << 0) -#define EP93XX_I2S_WRDLEN_24 (1 << 0) -#define EP93XX_I2S_WRDLEN_32 (2 << 0) - -#define EP93XX_I2S_LINCTRLDATA_R_JUST (1 << 2) /* Right justify */ - -#define EP93XX_I2S_CLKCFG_LRS (1 << 0) /* lrclk polarity */ -#define EP93XX_I2S_CLKCFG_CKP (1 << 1) /* Bit clock polarity */ -#define EP93XX_I2S_CLKCFG_REL (1 << 2) /* First bit transition */ -#define EP93XX_I2S_CLKCFG_MASTER (1 << 3) /* Master mode */ -#define EP93XX_I2S_CLKCFG_NBCG (1 << 4) /* Not bit clock gating */ - -struct ep93xx_i2s_info { - struct clk *mclk; - struct clk *sclk; - struct clk *lrclk; - struct ep93xx_pcm_dma_params *dma_params; - void __iomem *regs; -}; - -struct ep93xx_pcm_dma_params ep93xx_i2s_dma_params[] = { - [SNDRV_PCM_STREAM_PLAYBACK] = { - .name = "i2s-pcm-out", - .dma_port = EP93XX_DMA_I2S1, - }, - [SNDRV_PCM_STREAM_CAPTURE] = { - .name = "i2s-pcm-in", - .dma_port = EP93XX_DMA_I2S1, - }, -}; - -static inline void ep93xx_i2s_write_reg(struct ep93xx_i2s_info *info, - unsigned reg, unsigned val) -{ - __raw_writel(val, info->regs + reg); -} - -static inline unsigned ep93xx_i2s_read_reg(struct ep93xx_i2s_info *info, - unsigned reg) -{ - return __raw_readl(info->regs + reg); -} - -static void ep93xx_i2s_enable(struct ep93xx_i2s_info *info, int stream) -{ - unsigned base_reg; - int i; - - if ((ep93xx_i2s_read_reg(info, EP93XX_I2S_TX0EN) & 0x1) == 0 && - (ep93xx_i2s_read_reg(info, EP93XX_I2S_RX0EN) & 0x1) == 0) { - /* Enable clocks */ - clk_enable(info->mclk); - clk_enable(info->sclk); - clk_enable(info->lrclk); - - /* Enable i2s */ - ep93xx_i2s_write_reg(info, EP93XX_I2S_GLCTRL, 1); - } - - /* Enable fifos */ - if (stream == SNDRV_PCM_STREAM_PLAYBACK) - base_reg = EP93XX_I2S_TX0EN; - else - base_reg = EP93XX_I2S_RX0EN; - for (i = 0; i < 3; i++) - ep93xx_i2s_write_reg(info, base_reg + (i * 4), 1); -} - -static void ep93xx_i2s_disable(struct ep93xx_i2s_info *info, int stream) -{ - unsigned base_reg; - int i; - - /* Disable fifos */ - if (stream == SNDRV_PCM_STREAM_PLAYBACK) - base_reg = EP93XX_I2S_TX0EN; - else - base_reg = EP93XX_I2S_RX0EN; - for (i = 0; i < 3; i++) - ep93xx_i2s_write_reg(info, base_reg + (i * 4), 0); - - if ((ep93xx_i2s_read_reg(info, EP93XX_I2S_TX0EN) & 0x1) == 0 && - (ep93xx_i2s_read_reg(info, EP93XX_I2S_RX0EN) & 0x1) == 0) { - /* Disable i2s */ - ep93xx_i2s_write_reg(info, EP93XX_I2S_GLCTRL, 0); - - /* Disable clocks */ - clk_disable(info->lrclk); - clk_disable(info->sclk); - clk_disable(info->mclk); - } -} - -static int ep93xx_i2s_startup(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct ep93xx_i2s_info *info = snd_soc_dai_get_drvdata(dai); - struct snd_soc_dai *cpu_dai = rtd->cpu_dai; - - snd_soc_dai_set_dma_data(cpu_dai, substream, - &info->dma_params[substream->stream]); - return 0; -} - -static void ep93xx_i2s_shutdown(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - struct ep93xx_i2s_info *info = snd_soc_dai_get_drvdata(dai); - - ep93xx_i2s_disable(info, substream->stream); -} - -static int ep93xx_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai, - unsigned int fmt) -{ - struct ep93xx_i2s_info *info = snd_soc_dai_get_drvdata(cpu_dai); - unsigned int clk_cfg, lin_ctrl; - - clk_cfg = ep93xx_i2s_read_reg(info, EP93XX_I2S_RXCLKCFG); - lin_ctrl = ep93xx_i2s_read_reg(info, EP93XX_I2S_RXLINCTRLDATA); - - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_I2S: - clk_cfg |= EP93XX_I2S_CLKCFG_REL; - lin_ctrl &= ~EP93XX_I2S_LINCTRLDATA_R_JUST; - break; - - case SND_SOC_DAIFMT_LEFT_J: - clk_cfg &= ~EP93XX_I2S_CLKCFG_REL; - lin_ctrl &= ~EP93XX_I2S_LINCTRLDATA_R_JUST; - break; - - case SND_SOC_DAIFMT_RIGHT_J: - clk_cfg &= ~EP93XX_I2S_CLKCFG_REL; - lin_ctrl |= EP93XX_I2S_LINCTRLDATA_R_JUST; - break; - - default: - return -EINVAL; - } - - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBS_CFS: - /* CPU is master */ - clk_cfg |= EP93XX_I2S_CLKCFG_MASTER; - break; - - case SND_SOC_DAIFMT_CBM_CFM: - /* Codec is master */ - clk_cfg &= ~EP93XX_I2S_CLKCFG_MASTER; - break; - - default: - return -EINVAL; - } - - switch (fmt & SND_SOC_DAIFMT_INV_MASK) { - case SND_SOC_DAIFMT_NB_NF: - /* Negative bit clock, lrclk low on left word */ - clk_cfg &= ~(EP93XX_I2S_CLKCFG_CKP | EP93XX_I2S_CLKCFG_REL); - break; - - case SND_SOC_DAIFMT_NB_IF: - /* Negative bit clock, lrclk low on right word */ - clk_cfg &= ~EP93XX_I2S_CLKCFG_CKP; - clk_cfg |= EP93XX_I2S_CLKCFG_REL; - break; - - case SND_SOC_DAIFMT_IB_NF: - /* Positive bit clock, lrclk low on left word */ - clk_cfg |= EP93XX_I2S_CLKCFG_CKP; - clk_cfg &= ~EP93XX_I2S_CLKCFG_REL; - break; - - case SND_SOC_DAIFMT_IB_IF: - /* Positive bit clock, lrclk low on right word */ - clk_cfg |= EP93XX_I2S_CLKCFG_CKP | EP93XX_I2S_CLKCFG_REL; - break; - } - - /* Write new register values */ - ep93xx_i2s_write_reg(info, EP93XX_I2S_RXCLKCFG, clk_cfg); - ep93xx_i2s_write_reg(info, EP93XX_I2S_TXCLKCFG, clk_cfg); - ep93xx_i2s_write_reg(info, EP93XX_I2S_RXLINCTRLDATA, lin_ctrl); - ep93xx_i2s_write_reg(info, EP93XX_I2S_TXLINCTRLDATA, lin_ctrl); - return 0; -} - -static int ep93xx_i2s_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) -{ - struct ep93xx_i2s_info *info = snd_soc_dai_get_drvdata(dai); - unsigned word_len, div, sdiv, lrdiv; - int err; - - switch (params_format(params)) { - case SNDRV_PCM_FORMAT_S16_LE: - word_len = EP93XX_I2S_WRDLEN_16; - break; - - case SNDRV_PCM_FORMAT_S24_LE: - word_len = EP93XX_I2S_WRDLEN_24; - break; - - case SNDRV_PCM_FORMAT_S32_LE: - word_len = EP93XX_I2S_WRDLEN_32; - break; - - default: - return -EINVAL; - } - - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - ep93xx_i2s_write_reg(info, EP93XX_I2S_TXWRDLEN, word_len); - else - ep93xx_i2s_write_reg(info, EP93XX_I2S_RXWRDLEN, word_len); - - /* - * EP93xx I2S module can be setup so SCLK / LRCLK value can be - * 32, 64, 128. MCLK / SCLK value can be 2 and 4. - * We set LRCLK equal to `rate' and minimum SCLK / LRCLK - * value is 64, because our sample size is 32 bit * 2 channels. - * I2S standard permits us to transmit more bits than - * the codec uses. - */ - div = clk_get_rate(info->mclk) / params_rate(params); - sdiv = 4; - if (div > (256 + 512) / 2) { - lrdiv = 128; - } else { - lrdiv = 64; - if (div < (128 + 256) / 2) - sdiv = 2; - } - - err = clk_set_rate(info->sclk, clk_get_rate(info->mclk) / sdiv); - if (err) - return err; - - err = clk_set_rate(info->lrclk, clk_get_rate(info->sclk) / lrdiv); - if (err) - return err; - - ep93xx_i2s_enable(info, substream->stream); - return 0; -} - -static int ep93xx_i2s_set_sysclk(struct snd_soc_dai *cpu_dai, int clk_id, - unsigned int freq, int dir) -{ - struct ep93xx_i2s_info *info = snd_soc_dai_get_drvdata(cpu_dai); - - if (dir == SND_SOC_CLOCK_IN || clk_id != 0) - return -EINVAL; - - return clk_set_rate(info->mclk, freq); -} - -#ifdef CONFIG_PM -static int ep93xx_i2s_suspend(struct snd_soc_dai *dai) -{ - struct ep93xx_i2s_info *info = snd_soc_dai_get_drvdata(dai); - - if (!dai->active) - return 0; - - ep93xx_i2s_disable(info, SNDRV_PCM_STREAM_PLAYBACK); - ep93xx_i2s_disable(info, SNDRV_PCM_STREAM_CAPTURE); - - return 0; -} - -static int ep93xx_i2s_resume(struct snd_soc_dai *dai) -{ - struct ep93xx_i2s_info *info = snd_soc_dai_get_drvdata(dai); - - if (!dai->active) - return 0; - - ep93xx_i2s_enable(info, SNDRV_PCM_STREAM_PLAYBACK); - ep93xx_i2s_enable(info, SNDRV_PCM_STREAM_CAPTURE); - - return 0; -} -#else -#define ep93xx_i2s_suspend NULL -#define ep93xx_i2s_resume NULL -#endif - -static const struct snd_soc_dai_ops ep93xx_i2s_dai_ops = { - .startup = ep93xx_i2s_startup, - .shutdown = ep93xx_i2s_shutdown, - .hw_params = ep93xx_i2s_hw_params, - .set_sysclk = ep93xx_i2s_set_sysclk, - .set_fmt = ep93xx_i2s_set_dai_fmt, -}; - -#define EP93XX_I2S_FORMATS (SNDRV_PCM_FMTBIT_S32_LE) - -static struct snd_soc_dai_driver ep93xx_i2s_dai = { - .symmetric_rates= 1, - .suspend = ep93xx_i2s_suspend, - .resume = ep93xx_i2s_resume, - .playback = { - .channels_min = 2, - .channels_max = 2, - .rates = SNDRV_PCM_RATE_8000_192000, - .formats = EP93XX_I2S_FORMATS, - }, - .capture = { - .channels_min = 2, - .channels_max = 2, - .rates = SNDRV_PCM_RATE_8000_192000, - .formats = EP93XX_I2S_FORMATS, - }, - .ops = &ep93xx_i2s_dai_ops, -}; - -static int ep93xx_i2s_probe(struct platform_device *pdev) -{ - struct ep93xx_i2s_info *info; - struct resource *res; - int err; - - info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL); - if (!info) - return -ENOMEM; - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) - return -ENODEV; - - info->regs = devm_request_and_ioremap(&pdev->dev, res); - if (!info->regs) - return -ENXIO; - - info->mclk = clk_get(&pdev->dev, "mclk"); - if (IS_ERR(info->mclk)) { - err = PTR_ERR(info->mclk); - goto fail; - } - - info->sclk = clk_get(&pdev->dev, "sclk"); - if (IS_ERR(info->sclk)) { - err = PTR_ERR(info->sclk); - goto fail_put_mclk; - } - - info->lrclk = clk_get(&pdev->dev, "lrclk"); - if (IS_ERR(info->lrclk)) { - err = PTR_ERR(info->lrclk); - goto fail_put_sclk; - } - - dev_set_drvdata(&pdev->dev, info); - info->dma_params = ep93xx_i2s_dma_params; - - err = snd_soc_register_dai(&pdev->dev, &ep93xx_i2s_dai); - if (err) - goto fail_put_lrclk; - - return 0; - -fail_put_lrclk: - dev_set_drvdata(&pdev->dev, NULL); - clk_put(info->lrclk); -fail_put_sclk: - clk_put(info->sclk); -fail_put_mclk: - clk_put(info->mclk); -fail: - return err; -} - -static int __devexit ep93xx_i2s_remove(struct platform_device *pdev) -{ - struct ep93xx_i2s_info *info = dev_get_drvdata(&pdev->dev); - - snd_soc_unregister_dai(&pdev->dev); - dev_set_drvdata(&pdev->dev, NULL); - clk_put(info->lrclk); - clk_put(info->sclk); - clk_put(info->mclk); - return 0; -} - -static struct platform_driver ep93xx_i2s_driver = { - .probe = ep93xx_i2s_probe, - .remove = __devexit_p(ep93xx_i2s_remove), - .driver = { - .name = "ep93xx-i2s", - .owner = THIS_MODULE, - }, -}; - -module_platform_driver(ep93xx_i2s_driver); - -MODULE_ALIAS("platform:ep93xx-i2s"); -MODULE_AUTHOR("Ryan Mallon"); -MODULE_DESCRIPTION("EP93XX I2S driver"); -MODULE_LICENSE("GPL"); diff --git a/sound/soc/ep93xx/ep93xx-pcm.c b/sound/soc/ep93xx/ep93xx-pcm.c deleted file mode 100644 index 4eea98b42bc8..000000000000 --- a/sound/soc/ep93xx/ep93xx-pcm.c +++ /dev/null @@ -1,242 +0,0 @@ -/* - * linux/sound/arm/ep93xx-pcm.c - EP93xx ALSA PCM interface - * - * Copyright (C) 2006 Lennert Buytenhek - * Copyright (C) 2006 Applied Data Systems - * - * Rewritten for the SoC audio subsystem (Based on PXA2xx code): - * Copyright (c) 2008 Ryan Mallon - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "ep93xx-pcm.h" - -static const struct snd_pcm_hardware ep93xx_pcm_hardware = { - .info = (SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER), - - .rates = SNDRV_PCM_RATE_8000_192000, - .rate_min = SNDRV_PCM_RATE_8000, - .rate_max = SNDRV_PCM_RATE_192000, - - .formats = (SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S24_LE | - SNDRV_PCM_FMTBIT_S32_LE), - - .buffer_bytes_max = 131072, - .period_bytes_min = 32, - .period_bytes_max = 32768, - .periods_min = 1, - .periods_max = 32, - .fifo_size = 32, -}; - -static bool ep93xx_pcm_dma_filter(struct dma_chan *chan, void *filter_param) -{ - struct ep93xx_dma_data *data = filter_param; - - if (data->direction == ep93xx_dma_chan_direction(chan)) { - chan->private = data; - return true; - } - - return false; -} - -static int ep93xx_pcm_open(struct snd_pcm_substream *substream) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *cpu_dai = rtd->cpu_dai; - struct ep93xx_pcm_dma_params *dma_params; - struct ep93xx_dma_data *dma_data; - int ret; - - snd_soc_set_runtime_hwparams(substream, &ep93xx_pcm_hardware); - - dma_data = kmalloc(sizeof(*dma_data), GFP_KERNEL); - if (!dma_data) - return -ENOMEM; - - dma_params = snd_soc_dai_get_dma_data(cpu_dai, substream); - dma_data->port = dma_params->dma_port; - dma_data->name = dma_params->name; - dma_data->direction = snd_pcm_substream_to_dma_direction(substream); - - ret = snd_dmaengine_pcm_open(substream, ep93xx_pcm_dma_filter, dma_data); - if (ret) { - kfree(dma_data); - return ret; - } - - snd_dmaengine_pcm_set_data(substream, dma_data); - - return 0; -} - -static int ep93xx_pcm_close(struct snd_pcm_substream *substream) -{ - struct dma_data *dma_data = snd_dmaengine_pcm_get_data(substream); - - snd_dmaengine_pcm_close(substream); - kfree(dma_data); - return 0; -} - -static int ep93xx_pcm_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); - - return 0; -} - -static int ep93xx_pcm_hw_free(struct snd_pcm_substream *substream) -{ - snd_pcm_set_runtime_buffer(substream, NULL); - return 0; -} - -static int ep93xx_pcm_mmap(struct snd_pcm_substream *substream, - struct vm_area_struct *vma) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - - return dma_mmap_writecombine(substream->pcm->card->dev, vma, - runtime->dma_area, - runtime->dma_addr, - runtime->dma_bytes); -} - -static struct snd_pcm_ops ep93xx_pcm_ops = { - .open = ep93xx_pcm_open, - .close = ep93xx_pcm_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = ep93xx_pcm_hw_params, - .hw_free = ep93xx_pcm_hw_free, - .trigger = snd_dmaengine_pcm_trigger, - .pointer = snd_dmaengine_pcm_pointer_no_residue, - .mmap = ep93xx_pcm_mmap, -}; - -static int ep93xx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream) -{ - struct snd_pcm_substream *substream = pcm->streams[stream].substream; - struct snd_dma_buffer *buf = &substream->dma_buffer; - size_t size = ep93xx_pcm_hardware.buffer_bytes_max; - - buf->dev.type = SNDRV_DMA_TYPE_DEV; - buf->dev.dev = pcm->card->dev; - buf->private_data = NULL; - buf->area = dma_alloc_writecombine(pcm->card->dev, size, - &buf->addr, GFP_KERNEL); - buf->bytes = size; - - return (buf->area == NULL) ? -ENOMEM : 0; -} - -static void ep93xx_pcm_free_dma_buffers(struct snd_pcm *pcm) -{ - struct snd_pcm_substream *substream; - struct snd_dma_buffer *buf; - int stream; - - for (stream = 0; stream < 2; stream++) { - substream = pcm->streams[stream].substream; - if (!substream) - continue; - - buf = &substream->dma_buffer; - if (!buf->area) - continue; - - dma_free_writecombine(pcm->card->dev, buf->bytes, buf->area, - buf->addr); - buf->area = NULL; - } -} - -static u64 ep93xx_pcm_dmamask = DMA_BIT_MASK(32); - -static int ep93xx_pcm_new(struct snd_soc_pcm_runtime *rtd) -{ - struct snd_card *card = rtd->card->snd_card; - struct snd_pcm *pcm = rtd->pcm; - int ret = 0; - - if (!card->dev->dma_mask) - card->dev->dma_mask = &ep93xx_pcm_dmamask; - if (!card->dev->coherent_dma_mask) - card->dev->coherent_dma_mask = DMA_BIT_MASK(32); - - if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) { - ret = ep93xx_pcm_preallocate_dma_buffer(pcm, - SNDRV_PCM_STREAM_PLAYBACK); - if (ret) - return ret; - } - - if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) { - ret = ep93xx_pcm_preallocate_dma_buffer(pcm, - SNDRV_PCM_STREAM_CAPTURE); - if (ret) - return ret; - } - - return 0; -} - -static struct snd_soc_platform_driver ep93xx_soc_platform = { - .ops = &ep93xx_pcm_ops, - .pcm_new = &ep93xx_pcm_new, - .pcm_free = &ep93xx_pcm_free_dma_buffers, -}; - -static int __devinit ep93xx_soc_platform_probe(struct platform_device *pdev) -{ - return snd_soc_register_platform(&pdev->dev, &ep93xx_soc_platform); -} - -static int __devexit ep93xx_soc_platform_remove(struct platform_device *pdev) -{ - snd_soc_unregister_platform(&pdev->dev); - return 0; -} - -static struct platform_driver ep93xx_pcm_driver = { - .driver = { - .name = "ep93xx-pcm-audio", - .owner = THIS_MODULE, - }, - - .probe = ep93xx_soc_platform_probe, - .remove = __devexit_p(ep93xx_soc_platform_remove), -}; - -module_platform_driver(ep93xx_pcm_driver); - -MODULE_AUTHOR("Ryan Mallon"); -MODULE_DESCRIPTION("EP93xx ALSA PCM interface"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:ep93xx-pcm-audio"); diff --git a/sound/soc/ep93xx/ep93xx-pcm.h b/sound/soc/ep93xx/ep93xx-pcm.h deleted file mode 100644 index 111e1121ecb8..000000000000 --- a/sound/soc/ep93xx/ep93xx-pcm.h +++ /dev/null @@ -1,20 +0,0 @@ -/* - * sound/soc/ep93xx/ep93xx-pcm.h - EP93xx ALSA PCM interface - * - * Copyright (C) 2006 Lennert Buytenhek - * Copyright (C) 2006 Applied Data Systems - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef _EP93XX_SND_SOC_PCM_H -#define _EP93XX_SND_SOC_PCM_H - -struct ep93xx_pcm_dma_params { - char *name; - int dma_port; -}; - -#endif /* _EP93XX_SND_SOC_PCM_H */ diff --git a/sound/soc/ep93xx/simone.c b/sound/soc/ep93xx/simone.c deleted file mode 100644 index dd997094eb30..000000000000 --- a/sound/soc/ep93xx/simone.c +++ /dev/null @@ -1,90 +0,0 @@ -/* - * simone.c -- ASoC audio for Simplemachines Sim.One board - * - * Copyright (c) 2010 Mika Westerberg - * - * Based on snappercl15 machine driver by Ryan Mallon. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include -#include - -#include -#include -#include - -#include -#include - -#include "ep93xx-pcm.h" - -static struct snd_soc_dai_link simone_dai = { - .name = "AC97", - .stream_name = "AC97 HiFi", - .cpu_dai_name = "ep93xx-ac97", - .codec_dai_name = "ac97-hifi", - .codec_name = "ac97-codec", - .platform_name = "ep93xx-pcm-audio", -}; - -static struct snd_soc_card snd_soc_simone = { - .name = "Sim.One", - .owner = THIS_MODULE, - .dai_link = &simone_dai, - .num_links = 1, -}; - -static struct platform_device *simone_snd_ac97_device; - -static int __devinit simone_probe(struct platform_device *pdev) -{ - struct snd_soc_card *card = &snd_soc_simone; - int ret; - - simone_snd_ac97_device = platform_device_register_simple("ac97-codec", - -1, NULL, 0); - if (IS_ERR(simone_snd_ac97_device)) - return PTR_ERR(simone_snd_ac97_device); - - card->dev = &pdev->dev; - - ret = snd_soc_register_card(card); - if (ret) { - dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", - ret); - platform_device_unregister(simone_snd_ac97_device); - } - - return ret; -} - -static int __devexit simone_remove(struct platform_device *pdev) -{ - struct snd_soc_card *card = platform_get_drvdata(pdev); - - snd_soc_unregister_card(card); - platform_device_unregister(simone_snd_ac97_device); - - return 0; -} - -static struct platform_driver simone_driver = { - .driver = { - .name = "simone-audio", - .owner = THIS_MODULE, - }, - .probe = simone_probe, - .remove = __devexit_p(simone_remove), -}; - -module_platform_driver(simone_driver); - -MODULE_DESCRIPTION("ALSA SoC Simplemachines Sim.One"); -MODULE_AUTHOR("Mika Westerberg "); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:simone-audio"); diff --git a/sound/soc/ep93xx/snappercl15.c b/sound/soc/ep93xx/snappercl15.c deleted file mode 100644 index a193cea3cf3c..000000000000 --- a/sound/soc/ep93xx/snappercl15.c +++ /dev/null @@ -1,146 +0,0 @@ -/* - * snappercl15.c -- SoC audio for Bluewater Systems Snapper CL15 module - * - * Copyright (C) 2008 Bluewater Systems Ltd - * Author: Ryan Mallon - * - * 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 "../codecs/tlv320aic23.h" -#include "ep93xx-pcm.h" - -#define CODEC_CLOCK 5644800 - -static int snappercl15_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *codec_dai = rtd->codec_dai; - struct snd_soc_dai *cpu_dai = rtd->cpu_dai; - int err; - - err = snd_soc_dai_set_sysclk(codec_dai, 0, CODEC_CLOCK, - SND_SOC_CLOCK_IN); - if (err) - return err; - - err = snd_soc_dai_set_sysclk(cpu_dai, 0, CODEC_CLOCK, - SND_SOC_CLOCK_OUT); - if (err) - return err; - - return 0; -} - -static struct snd_soc_ops snappercl15_ops = { - .hw_params = snappercl15_hw_params, -}; - -static const struct snd_soc_dapm_widget tlv320aic23_dapm_widgets[] = { - SND_SOC_DAPM_HP("Headphone Jack", NULL), - SND_SOC_DAPM_LINE("Line In", NULL), - SND_SOC_DAPM_MIC("Mic Jack", NULL), -}; - -static const struct snd_soc_dapm_route audio_map[] = { - {"Headphone Jack", NULL, "LHPOUT"}, - {"Headphone Jack", NULL, "RHPOUT"}, - - {"LLINEIN", NULL, "Line In"}, - {"RLINEIN", NULL, "Line In"}, - - {"MICIN", NULL, "Mic Jack"}, -}; - -static int snappercl15_tlv320aic23_init(struct snd_soc_pcm_runtime *rtd) -{ - struct snd_soc_codec *codec = rtd->codec; - struct snd_soc_dapm_context *dapm = &codec->dapm; - - snd_soc_dapm_new_controls(dapm, tlv320aic23_dapm_widgets, - ARRAY_SIZE(tlv320aic23_dapm_widgets)); - - snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map)); - return 0; -} - -static struct snd_soc_dai_link snappercl15_dai = { - .name = "tlv320aic23", - .stream_name = "AIC23", - .cpu_dai_name = "ep93xx-i2s", - .codec_dai_name = "tlv320aic23-hifi", - .codec_name = "tlv320aic23-codec.0-001a", - .platform_name = "ep93xx-pcm-audio", - .init = snappercl15_tlv320aic23_init, - .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_IF | - SND_SOC_DAIFMT_CBS_CFS, - .ops = &snappercl15_ops, -}; - -static struct snd_soc_card snd_soc_snappercl15 = { - .name = "Snapper CL15", - .owner = THIS_MODULE, - .dai_link = &snappercl15_dai, - .num_links = 1, -}; - -static int __devinit snappercl15_probe(struct platform_device *pdev) -{ - struct snd_soc_card *card = &snd_soc_snappercl15; - int ret; - - ret = ep93xx_i2s_acquire(); - if (ret) - return ret; - - card->dev = &pdev->dev; - - ret = snd_soc_register_card(card); - if (ret) { - dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", - ret); - ep93xx_i2s_release(); - } - - return ret; -} - -static int __devexit snappercl15_remove(struct platform_device *pdev) -{ - struct snd_soc_card *card = platform_get_drvdata(pdev); - - snd_soc_unregister_card(card); - ep93xx_i2s_release(); - - return 0; -} - -static struct platform_driver snappercl15_driver = { - .driver = { - .name = "snappercl15-audio", - .owner = THIS_MODULE, - }, - .probe = snappercl15_probe, - .remove = __devexit_p(snappercl15_remove), -}; - -module_platform_driver(snappercl15_driver); - -MODULE_AUTHOR("Ryan Mallon"); -MODULE_DESCRIPTION("ALSA SoC Snapper CL15"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:snappercl15-audio"); -- cgit v1.2.3 From ffb690d5aa36d38d7bed7579e3f07b84ff6b3a08 Mon Sep 17 00:00:00 2001 From: "Hebbar, Gururaja" Date: Fri, 31 Aug 2012 18:20:59 +0530 Subject: ASoC: Davinci: evm: Fix typo in cpu dai name Fix typo caused by recent commit (cf53756 - ASoC: davinci: davinci-pcm does not need to be a plaform_driver) Signed-off-by: Hebbar, Gururaja Signed-off-by: Mark Brown --- sound/soc/davinci/davinci-evm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound/soc') diff --git a/sound/soc/davinci/davinci-evm.c b/sound/soc/davinci/davinci-evm.c index ab0ad4591b08..6fac5af13298 100644 --- a/sound/soc/davinci/davinci-evm.c +++ b/sound/soc/davinci/davinci-evm.c @@ -188,7 +188,7 @@ static struct snd_soc_dai_link dm365_evm_dai = { .cpu_dai_name = "davinci-vcif", .codec_dai_name = "cq93vc-hifi", .codec_name = "cq93vc-codec", - .platform_name = "avinci-vcif", + .platform_name = "davinci-vcif", #endif }; -- cgit v1.2.3 From e93c7d1bc350189511d32cec2f0af79c30e7fa47 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Thu, 30 Aug 2012 17:06:15 +0300 Subject: ASoC: omap-mcbsp: Fix compilation error due to leftover code Part of commit (which patches sound/soc/omap/mcbsp.c file): 8fef626 ARM/ASoC: omap-mcbsp: Remove CLKR/FSR mux configuration code since the tree where it has been applied did not had the earlier patch: d0db84e ASoC: omap-mcbsp: Fix 6pin mux configuration which changed code around omap_mcbsp_6pin_src_mux(). Because of the missing part from 8fef626 the sound/soc/omap/mcbsp.c does not compile in linux-next. Signed-off-by: Peter Ujfalusi Signed-off-by: Mark Brown --- sound/soc/omap/mcbsp.c | 31 ------------------------------- 1 file changed, 31 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/omap/mcbsp.c b/sound/soc/omap/mcbsp.c index 935ccf633976..bc06175e6367 100644 --- a/sound/soc/omap/mcbsp.c +++ b/sound/soc/omap/mcbsp.c @@ -762,37 +762,6 @@ int omap2_mcbsp_set_clks_src(struct omap_mcbsp *mcbsp, u8 fck_src_id) } -int omap_mcbsp_6pin_src_mux(struct omap_mcbsp *mcbsp, u8 mux) -{ - const char *signal, *src; - - if (!mcbsp->pdata->mux_signal) - return -EINVAL; - - switch (mux) { - case CLKR_SRC_CLKR: - signal = "clkr"; - src = "clkr"; - break; - case CLKR_SRC_CLKX: - signal = "clkr"; - src = "clkx"; - break; - case FSR_SRC_FSR: - signal = "fsr"; - src = "fsr"; - break; - case FSR_SRC_FSX: - signal = "fsr"; - src = "fsx"; - break; - default: - return -EINVAL; - } - - return mcbsp->pdata->mux_signal(mcbsp->dev, signal, src); -} - #define max_thres(m) (mcbsp->pdata->buffer_size) #define valid_threshold(m, val) ((val) <= max_thres(m)) #define THRESHOLD_PROP_BUILDER(prop) \ -- cgit v1.2.3 From 58d468328646effa72ada4deaa33e80d678980d6 Mon Sep 17 00:00:00 2001 From: Fengguang Wu Date: Thu, 30 Aug 2012 08:16:52 -0700 Subject: ASoC: wm0010: Add missing IRQF_ONESHOT FYI, there are new coccinelle warnings show up in tree: git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git for-3.7 head: e3523e01869da20fdd12ffd19ae1df7bf492650e commit: e3523e01869da20fdd12ffd19ae1df7bf492650e [95/95] ASoC: wm0010: Add initial wm0010 DSP driver All coccinelle warnings: + sound/soc/codecs/wm0010.c:850:7-27: ERROR: Threaded IRQ with no primary handler requested without IRQF_ONESHOT -- + sound/soc/codecs/wm0010.c:660:1-7: preceding lock on line 359 vim +850 sound/soc/codecs/wm0010.c 847 trigger = IRQF_TRIGGER_FALLING; 848 trigger |= IRQF_ONESHOT; 849 > 850 ret = request_threaded_irq(irq, NULL, wm0010_irq, trigger, 851 "wm0010", wm0010); 852 if (ret) 853 dev_err(wm0010->dev, "Failed to request IRQ %d: %d\n", Please consider folding the attached diff :-) Signed-off-by: Fengguang Wu Signed-off-by: Mark Brown --- sound/soc/codecs/wm0010.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/wm0010.c b/sound/soc/codecs/wm0010.c index 5f99148447e1..a4c35119792e 100644 --- a/sound/soc/codecs/wm0010.c +++ b/sound/soc/codecs/wm0010.c @@ -881,7 +881,7 @@ static int __devinit wm0010_spi_probe(struct spi_device *spi) trigger = IRQF_TRIGGER_FALLING; trigger |= IRQF_ONESHOT; - ret = request_threaded_irq(irq, NULL, wm0010_irq, trigger, + ret = request_threaded_irq(irq, NULL, wm0010_irq, trigger | IRQF_ONESHOT, "wm0010", wm0010); if (ret) { dev_err(wm0010->dev, "Failed to request IRQ %d: %d\n", -- cgit v1.2.3 From 4f3ad7956d91a5371a572f0420cc07f8c4f32c22 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Wed, 5 Sep 2012 15:29:46 +0300 Subject: ASoC: wm0010: unlock on error path We're holding the wm0010->lock mutex when we goto err_core. Signed-off-by: Dan Carpenter Signed-off-by: Mark Brown --- sound/soc/codecs/wm0010.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'sound/soc') diff --git a/sound/soc/codecs/wm0010.c b/sound/soc/codecs/wm0010.c index a4c35119792e..0274f04a940a 100644 --- a/sound/soc/codecs/wm0010.c +++ b/sound/soc/codecs/wm0010.c @@ -663,7 +663,9 @@ abort: wm0010_halt(codec); mutex_unlock(&wm0010->lock); return ret; + err_core: + mutex_unlock(&wm0010->lock); regulator_bulk_disable(ARRAY_SIZE(wm0010->core_supplies), wm0010->core_supplies); err: -- cgit v1.2.3 From 5d86e25c70407cd97a5aa8f39cc3be390bcab116 Mon Sep 17 00:00:00 2001 From: Emil Goode Date: Wed, 5 Sep 2012 22:22:24 +0200 Subject: ASoC: wm0010: Fix warning, use format %zu for type size_t MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix warning by using format specifier %zu for type size_t Sparse warning: sound/soc/codecs/wm0010.c:411:2: warning: format ‘%d’ expects argument of type ‘int’, but argument 4 has type ‘size_t’ [-Wformat] Signed-off-by: Emil Goode Signed-off-by: Mark Brown --- sound/soc/codecs/wm0010.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/wm0010.c b/sound/soc/codecs/wm0010.c index 0274f04a940a..f8d6c31db870 100644 --- a/sound/soc/codecs/wm0010.c +++ b/sound/soc/codecs/wm0010.c @@ -408,7 +408,7 @@ static int wm0010_boot(struct snd_soc_codec *codec) wm0010->state = WM0010_BOOTROM; spin_unlock_irqrestore(&wm0010->irq_lock, flags); - dev_dbg(codec->dev, "Downloading %d byte stage 2 loader\n", fw->size); + dev_dbg(codec->dev, "Downloading %zu byte stage 2 loader\n", fw->size); /* Copy to local buffer first as vmalloc causes problems for dma */ img = kzalloc(fw->size, GFP_KERNEL); -- cgit v1.2.3 From 03f67433758a3eeb37b9c1559886c377da874ad2 Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Wed, 5 Sep 2012 10:27:14 -0600 Subject: ASoC: tegra: move platform data header Move the Tegra+WM8903 ASoC platform data header out of arch/arm/mach-tegra, as a pre-requisite of single zImage. Signed-off-by: Stephen Warren Signed-off-by: Mark Brown --- .../mach-tegra/include/mach/tegra_wm8903_pdata.h | 23 ------------------- include/sound/tegra_wm8903.h | 26 ++++++++++++++++++++++ sound/soc/tegra/tegra_wm8903.c | 3 +-- 3 files changed, 27 insertions(+), 25 deletions(-) delete mode 100644 arch/arm/mach-tegra/include/mach/tegra_wm8903_pdata.h create mode 100644 include/sound/tegra_wm8903.h (limited to 'sound/soc') diff --git a/arch/arm/mach-tegra/include/mach/tegra_wm8903_pdata.h b/arch/arm/mach-tegra/include/mach/tegra_wm8903_pdata.h deleted file mode 100644 index 9d293344a7ff..000000000000 --- a/arch/arm/mach-tegra/include/mach/tegra_wm8903_pdata.h +++ /dev/null @@ -1,23 +0,0 @@ -/* - * arch/arm/mach-tegra/include/mach/tegra_wm8903_pdata.h - * - * Copyright 2011 NVIDIA, Inc. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - */ - -struct tegra_wm8903_platform_data { - int gpio_spkr_en; - int gpio_hp_det; - int gpio_hp_mute; - int gpio_int_mic_en; - int gpio_ext_mic_en; -}; diff --git a/include/sound/tegra_wm8903.h b/include/sound/tegra_wm8903.h new file mode 100644 index 000000000000..57b202ee97c3 --- /dev/null +++ b/include/sound/tegra_wm8903.h @@ -0,0 +1,26 @@ +/* + * Copyright 2011 NVIDIA, Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#ifndef __SOUND_TEGRA_WM38903_H +#define __SOUND_TEGRA_WM38903_H + +struct tegra_wm8903_platform_data { + int gpio_spkr_en; + int gpio_hp_det; + int gpio_hp_mute; + int gpio_int_mic_en; + int gpio_ext_mic_en; +}; + +#endif diff --git a/sound/soc/tegra/tegra_wm8903.c b/sound/soc/tegra/tegra_wm8903.c index d4f14e492341..cee13b7bfb94 100644 --- a/sound/soc/tegra/tegra_wm8903.c +++ b/sound/soc/tegra/tegra_wm8903.c @@ -34,13 +34,12 @@ #include #include -#include - #include #include #include #include #include +#include #include "../codecs/wm8903.h" -- cgit v1.2.3 From e5ec69da24803c68f5c035662a68d367359a4132 Mon Sep 17 00:00:00 2001 From: "Hebbar, Gururaja" Date: Mon, 3 Sep 2012 13:40:40 +0530 Subject: ASoC: Davinci: McASP: add support new McASP IP Variant The OMAP2+ variant of McASP is different from Davinci variant w.r.to some register offset. Changes - Add new MCASP_VERSION_3 to identify new variant. New DT compatible "ti,omap2-mcasp-audio" to identify version 3 controller. - The register offsets are handled depending on the version. Note: DMA parameters (dma fifo offset) are not updated and will be done later. Signed-off-by: Hebbar, Gururaja Signed-off-by: Mark Brown --- .../bindings/sound/davinci-mcasp-audio.txt | 1 + include/linux/platform_data/davinci_asp.h | 1 + sound/soc/davinci/davinci-mcasp.c | 86 ++++++++++++++++++---- 3 files changed, 75 insertions(+), 13 deletions(-) (limited to 'sound/soc') diff --git a/Documentation/devicetree/bindings/sound/davinci-mcasp-audio.txt b/Documentation/devicetree/bindings/sound/davinci-mcasp-audio.txt index e6148eca2942..374e145c2ef1 100644 --- a/Documentation/devicetree/bindings/sound/davinci-mcasp-audio.txt +++ b/Documentation/devicetree/bindings/sound/davinci-mcasp-audio.txt @@ -4,6 +4,7 @@ Required properties: - compatible : "ti,dm646x-mcasp-audio" : for DM646x platforms "ti,da830-mcasp-audio" : for both DA830 & DA850 platforms + "ti,omap2-mcasp-audio" : for OMAP2 platforms (TI81xx, AM33xx) - reg : Should contain McASP registers offset and length - interrupts : Interrupt number for McASP diff --git a/include/linux/platform_data/davinci_asp.h b/include/linux/platform_data/davinci_asp.h index 79c26aa11db6..d0c5825876f8 100644 --- a/include/linux/platform_data/davinci_asp.h +++ b/include/linux/platform_data/davinci_asp.h @@ -87,6 +87,7 @@ struct snd_platform_data { enum { MCASP_VERSION_1 = 0, /* DM646x */ MCASP_VERSION_2, /* DA8xx/OMAPL1x */ + MCASP_VERSION_3, /* TI81xx/AM33xx */ }; enum mcbsp_clk_input_pin { diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c index c3eae1d8e077..714e51e5be5b 100644 --- a/sound/soc/davinci/davinci-mcasp.c +++ b/sound/soc/davinci/davinci-mcasp.c @@ -111,6 +111,10 @@ #define DAVINCI_MCASP_WFIFOSTS (0x1014) #define DAVINCI_MCASP_RFIFOCTL (0x1018) #define DAVINCI_MCASP_RFIFOSTS (0x101C) +#define MCASP_VER3_WFIFOCTL (0x1000) +#define MCASP_VER3_WFIFOSTS (0x1004) +#define MCASP_VER3_RFIFOCTL (0x1008) +#define MCASP_VER3_RFIFOSTS (0x100C) /* * DAVINCI_MCASP_PWREMUMGT_REG - Power Down and Emulation Management @@ -384,18 +388,36 @@ static void davinci_mcasp_start(struct davinci_audio_dev *dev, int stream) { if (stream == SNDRV_PCM_STREAM_PLAYBACK) { if (dev->txnumevt) { /* enable FIFO */ - mcasp_clr_bits(dev->base + DAVINCI_MCASP_WFIFOCTL, + switch (dev->version) { + case MCASP_VERSION_3: + mcasp_clr_bits(dev->base + MCASP_VER3_WFIFOCTL, FIFO_ENABLE); - mcasp_set_bits(dev->base + DAVINCI_MCASP_WFIFOCTL, + mcasp_set_bits(dev->base + MCASP_VER3_WFIFOCTL, FIFO_ENABLE); + break; + default: + mcasp_clr_bits(dev->base + + DAVINCI_MCASP_WFIFOCTL, FIFO_ENABLE); + mcasp_set_bits(dev->base + + DAVINCI_MCASP_WFIFOCTL, FIFO_ENABLE); + } } mcasp_start_tx(dev); } else { if (dev->rxnumevt) { /* enable FIFO */ - mcasp_clr_bits(dev->base + DAVINCI_MCASP_RFIFOCTL, + switch (dev->version) { + case MCASP_VERSION_3: + mcasp_clr_bits(dev->base + MCASP_VER3_RFIFOCTL, FIFO_ENABLE); - mcasp_set_bits(dev->base + DAVINCI_MCASP_RFIFOCTL, + mcasp_set_bits(dev->base + MCASP_VER3_RFIFOCTL, FIFO_ENABLE); + break; + default: + mcasp_clr_bits(dev->base + + DAVINCI_MCASP_RFIFOCTL, FIFO_ENABLE); + mcasp_set_bits(dev->base + + DAVINCI_MCASP_RFIFOCTL, FIFO_ENABLE); + } } mcasp_start_rx(dev); } @@ -416,14 +438,31 @@ static void mcasp_stop_tx(struct davinci_audio_dev *dev) static void davinci_mcasp_stop(struct davinci_audio_dev *dev, int stream) { if (stream == SNDRV_PCM_STREAM_PLAYBACK) { - if (dev->txnumevt) /* disable FIFO */ - mcasp_clr_bits(dev->base + DAVINCI_MCASP_WFIFOCTL, + if (dev->txnumevt) { /* disable FIFO */ + switch (dev->version) { + case MCASP_VERSION_3: + mcasp_clr_bits(dev->base + MCASP_VER3_WFIFOCTL, FIFO_ENABLE); + break; + default: + mcasp_clr_bits(dev->base + + DAVINCI_MCASP_WFIFOCTL, FIFO_ENABLE); + } + } mcasp_stop_tx(dev); } else { - if (dev->rxnumevt) /* disable FIFO */ - mcasp_clr_bits(dev->base + DAVINCI_MCASP_RFIFOCTL, + if (dev->rxnumevt) { /* disable FIFO */ + switch (dev->version) { + case MCASP_VERSION_3: + mcasp_clr_bits(dev->base + MCASP_VER3_RFIFOCTL, FIFO_ENABLE); + break; + + default: + mcasp_clr_bits(dev->base + + DAVINCI_MCASP_RFIFOCTL, FIFO_ENABLE); + } + } mcasp_stop_rx(dev); } } @@ -622,20 +661,37 @@ static void davinci_hw_common_param(struct davinci_audio_dev *dev, int stream) if (dev->txnumevt * tx_ser > 64) dev->txnumevt = 1; - mcasp_mod_bits(dev->base + DAVINCI_MCASP_WFIFOCTL, tx_ser, + switch (dev->version) { + case MCASP_VERSION_3: + mcasp_mod_bits(dev->base + MCASP_VER3_WFIFOCTL, tx_ser, NUMDMA_MASK); - mcasp_mod_bits(dev->base + DAVINCI_MCASP_WFIFOCTL, + mcasp_mod_bits(dev->base + MCASP_VER3_WFIFOCTL, ((dev->txnumevt * tx_ser) << 8), NUMEVT_MASK); + break; + default: + mcasp_mod_bits(dev->base + DAVINCI_MCASP_WFIFOCTL, + tx_ser, NUMDMA_MASK); + mcasp_mod_bits(dev->base + DAVINCI_MCASP_WFIFOCTL, + ((dev->txnumevt * tx_ser) << 8), NUMEVT_MASK); + } } if (dev->rxnumevt && stream == SNDRV_PCM_STREAM_CAPTURE) { if (dev->rxnumevt * rx_ser > 64) dev->rxnumevt = 1; - - mcasp_mod_bits(dev->base + DAVINCI_MCASP_RFIFOCTL, rx_ser, + switch (dev->version) { + case MCASP_VERSION_3: + mcasp_mod_bits(dev->base + MCASP_VER3_RFIFOCTL, rx_ser, NUMDMA_MASK); - mcasp_mod_bits(dev->base + DAVINCI_MCASP_RFIFOCTL, + mcasp_mod_bits(dev->base + MCASP_VER3_RFIFOCTL, + ((dev->rxnumevt * rx_ser) << 8), NUMEVT_MASK); + break; + default: + mcasp_mod_bits(dev->base + DAVINCI_MCASP_RFIFOCTL, + rx_ser, NUMDMA_MASK); + mcasp_mod_bits(dev->base + DAVINCI_MCASP_RFIFOCTL, ((dev->rxnumevt * rx_ser) << 8), NUMEVT_MASK); + } } } @@ -874,6 +930,10 @@ static const struct of_device_id mcasp_dt_ids[] = { .compatible = "ti,da830-mcasp-audio", .data = (void *)MCASP_VERSION_2, }, + { + .compatible = "ti,omap2-mcasp-audio", + .data = (void *)MCASP_VERSION_3, + }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, mcasp_dt_ids); -- cgit v1.2.3 From e2d32ff6ce4ee9958f3973a086f3fa5d009e6306 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 31 Aug 2012 17:38:32 -0700 Subject: ASoC: dapm: Ensure bypass paths are suspended and resumed Since bypass paths aren't part of DAPM streams and we may not have any DAPM streams there may not be anything that triggers a DAPM sync for them. Mark all input and output widgets as dirty and then sync to do so at the end of suspend and resume. Signed-off-by: Mark Brown Acked-by: Liam Girdwood --- include/sound/soc-dapm.h | 1 + sound/soc/soc-core.c | 8 ++++++++ sound/soc/soc-dapm.c | 22 ++++++++++++++++++++++ 3 files changed, 31 insertions(+) (limited to 'sound/soc') diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h index 0a1553748d65..07e2510619a1 100644 --- a/include/sound/soc-dapm.h +++ b/include/sound/soc-dapm.h @@ -412,6 +412,7 @@ void snd_soc_dapm_auto_nc_codec_pins(struct snd_soc_codec *codec); /* Mostly internal - should not normally be used */ void dapm_mark_dirty(struct snd_soc_dapm_widget *w, const char *reason); +void dapm_mark_io_dirty(struct snd_soc_dapm_context *dapm); /* dapm path query */ int snd_soc_dapm_dai_get_connected_widgets(struct snd_soc_dai *dai, int stream, diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index b95d1fb388a1..ad65459da28e 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -609,6 +609,10 @@ int snd_soc_suspend(struct device *dev) SND_SOC_DAPM_STREAM_SUSPEND); } + /* Recheck all analogue paths too */ + dapm_mark_io_dirty(&card->dapm); + snd_soc_dapm_sync(&card->dapm); + /* suspend all CODECs */ list_for_each_entry(codec, &card->codec_dev_list, card_list) { /* If there are paths active then the CODEC will be held with @@ -756,6 +760,10 @@ static void soc_resume_deferred(struct work_struct *work) /* userspace can access us now we are back as we were before */ snd_power_change_state(card->snd_card, SNDRV_CTL_POWER_D0); + + /* Recheck all analogue paths too */ + dapm_mark_io_dirty(&card->dapm); + snd_soc_dapm_sync(&card->dapm); } /* powers up audio subsystem after a suspend */ diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index dd7c49fafd75..f7999e949acb 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -141,6 +141,28 @@ void dapm_mark_dirty(struct snd_soc_dapm_widget *w, const char *reason) } EXPORT_SYMBOL_GPL(dapm_mark_dirty); +void dapm_mark_io_dirty(struct snd_soc_dapm_context *dapm) +{ + struct snd_soc_card *card = dapm->card; + struct snd_soc_dapm_widget *w; + + mutex_lock(&card->dapm_mutex); + + list_for_each_entry(w, &card->widgets, list) { + switch (w->id) { + case snd_soc_dapm_input: + case snd_soc_dapm_output: + dapm_mark_dirty(w, "Rechecking inputs and outputs"); + break; + default: + break; + } + } + + mutex_unlock(&card->dapm_mutex); +} +EXPORT_SYMBOL_GPL(dapm_mark_io_dirty); + /* create a new dapm widget */ static inline struct snd_soc_dapm_widget *dapm_cnew_widget( const struct snd_soc_dapm_widget *_widget) -- cgit v1.2.3 From 104c229932f18605acef2351373f8fd8f6c6f8c6 Mon Sep 17 00:00:00 2001 From: Javier Martin Date: Wed, 5 Sep 2012 21:30:10 -0300 Subject: ASoC: Revert 'ASoC: imx-ssi: Remove mono support' Revert 0865a75(ASoC: imx-ssi: Remove mono support). The bug this patch is meant to solve doesn't occur in Visstrim_M10 boards. Furthermore, after applying this patch sound in Visstrim_M10 is played at slower rates. Signed-off-by: Javier Martin Signed-off-by: Mark Brown --- sound/soc/fsl/imx-ssi.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/fsl/imx-ssi.c b/sound/soc/fsl/imx-ssi.c index 7074ae689984..3c520c46fa4a 100644 --- a/sound/soc/fsl/imx-ssi.c +++ b/sound/soc/fsl/imx-ssi.c @@ -380,14 +380,13 @@ static int imx_ssi_dai_probe(struct snd_soc_dai *dai) static struct snd_soc_dai_driver imx_ssi_dai = { .probe = imx_ssi_dai_probe, .playback = { - /* The SSI does not support monaural audio. */ - .channels_min = 2, + .channels_min = 1, .channels_max = 2, .rates = SNDRV_PCM_RATE_8000_96000, .formats = SNDRV_PCM_FMTBIT_S16_LE, }, .capture = { - .channels_min = 2, + .channels_min = 1, .channels_max = 2, .rates = SNDRV_PCM_RATE_8000_96000, .formats = SNDRV_PCM_FMTBIT_S16_LE, -- cgit v1.2.3 From 6d97c09c64974ab41708e2d38394928ec0eeb2f0 Mon Sep 17 00:00:00 2001 From: Gaëtan Carlier Date: Thu, 6 Sep 2012 09:40:12 +0200 Subject: ASoC: imx-mc13783: use defines instead of numerical address of register MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This uses already defined name of registers and makes code more readable. Signed-off-by: Gaëtan Carlier Signed-off-by: Mark Brown --- sound/soc/codecs/mc13783.c | 58 +++++++++++++++++++++++++--------------------- 1 file changed, 31 insertions(+), 27 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/mc13783.c b/sound/soc/codecs/mc13783.c index 8f726c063f42..bbfa5535cdd3 100644 --- a/sound/soc/codecs/mc13783.c +++ b/sound/soc/codecs/mc13783.c @@ -426,16 +426,16 @@ static int mc13783_set_tdm_slot_sync(struct snd_soc_dai *dai, } static const struct snd_kcontrol_new mc1l_amp_ctl = - SOC_DAPM_SINGLE("Switch", 38, 7, 1, 0); + SOC_DAPM_SINGLE("Switch", MC13783_AUDIO_TX, 7, 1, 0); static const struct snd_kcontrol_new mc1r_amp_ctl = - SOC_DAPM_SINGLE("Switch", 38, 5, 1, 0); + SOC_DAPM_SINGLE("Switch", MC13783_AUDIO_TX, 5, 1, 0); static const struct snd_kcontrol_new mc2_amp_ctl = - SOC_DAPM_SINGLE("Switch", 38, 9, 1, 0); + SOC_DAPM_SINGLE("Switch", MC13783_AUDIO_TX, 9, 1, 0); static const struct snd_kcontrol_new atx_amp_ctl = - SOC_DAPM_SINGLE("Switch", 38, 11, 1, 0); + SOC_DAPM_SINGLE("Switch", MC13783_AUDIO_TX, 11, 1, 0); /* Virtual mux. The chip does the input selection automatically @@ -461,22 +461,22 @@ static const struct snd_kcontrol_new right_input_mux = SOC_DAPM_ENUM_VIRT("Route", adcr_enum); static const struct snd_kcontrol_new samp_ctl = - SOC_DAPM_SINGLE("Switch", 36, 3, 1, 0); + SOC_DAPM_SINGLE("Switch", MC13783_AUDIO_RX0, 3, 1, 0); static const struct snd_kcontrol_new lamp_ctl = - SOC_DAPM_SINGLE("Switch", 36, 5, 1, 0); + SOC_DAPM_SINGLE("Switch", MC13783_AUDIO_RX0, 5, 1, 0); static const struct snd_kcontrol_new hlamp_ctl = - SOC_DAPM_SINGLE("Switch", 36, 10, 1, 0); + SOC_DAPM_SINGLE("Switch", MC13783_AUDIO_RX0, 10, 1, 0); static const struct snd_kcontrol_new hramp_ctl = - SOC_DAPM_SINGLE("Switch", 36, 9, 1, 0); + SOC_DAPM_SINGLE("Switch", MC13783_AUDIO_RX0, 9, 1, 0); static const struct snd_kcontrol_new llamp_ctl = - SOC_DAPM_SINGLE("Switch", 36, 16, 1, 0); + SOC_DAPM_SINGLE("Switch", MC13783_AUDIO_RX0, 16, 1, 0); static const struct snd_kcontrol_new lramp_ctl = - SOC_DAPM_SINGLE("Switch", 36, 15, 1, 0); + SOC_DAPM_SINGLE("Switch", MC13783_AUDIO_RX0, 15, 1, 0); static const struct snd_soc_dapm_widget mc13783_dapm_widgets[] = { /* Input */ @@ -487,13 +487,13 @@ static const struct snd_soc_dapm_widget mc13783_dapm_widgets[] = { SND_SOC_DAPM_INPUT("RXINL"), SND_SOC_DAPM_INPUT("TXIN"), - SND_SOC_DAPM_SUPPLY("MC1 Bias", 38, 0, 0, NULL, 0), - SND_SOC_DAPM_SUPPLY("MC2 Bias", 38, 1, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("MC1 Bias", MC13783_AUDIO_TX, 0, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("MC2 Bias", MC13783_AUDIO_TX, 1, 0, NULL, 0), - SND_SOC_DAPM_SWITCH("MC1L Amp", 38, 7, 0, &mc1l_amp_ctl), - SND_SOC_DAPM_SWITCH("MC1R Amp", 38, 5, 0, &mc1r_amp_ctl), - SND_SOC_DAPM_SWITCH("MC2 Amp", 38, 9, 0, &mc2_amp_ctl), - SND_SOC_DAPM_SWITCH("TXIN Amp", 38, 11, 0, &atx_amp_ctl), + SND_SOC_DAPM_SWITCH("MC1L Amp", MC13783_AUDIO_TX, 7, 0, &mc1l_amp_ctl), + SND_SOC_DAPM_SWITCH("MC1R Amp", MC13783_AUDIO_TX, 5, 0, &mc1r_amp_ctl), + SND_SOC_DAPM_SWITCH("MC2 Amp", MC13783_AUDIO_TX, 9, 0, &mc2_amp_ctl), + SND_SOC_DAPM_SWITCH("TXIN Amp", MC13783_AUDIO_TX, 11, 0, &atx_amp_ctl), SND_SOC_DAPM_VIRT_MUX("PGA Left Input Mux", SND_SOC_NOPM, 0, 0, &left_input_mux), @@ -503,12 +503,12 @@ static const struct snd_soc_dapm_widget mc13783_dapm_widgets[] = { SND_SOC_DAPM_PGA("PGA Left Input", SND_SOC_NOPM, 0, 0, NULL, 0), SND_SOC_DAPM_PGA("PGA Right Input", SND_SOC_NOPM, 0, 0, NULL, 0), - SND_SOC_DAPM_ADC("ADC", "Capture", 40, 11, 0), - SND_SOC_DAPM_SUPPLY("ADC_Reset", 40, 15, 0, NULL, 0), + SND_SOC_DAPM_ADC("ADC", "Capture", MC13783_AUDIO_CODEC, 11, 0), + SND_SOC_DAPM_SUPPLY("ADC_Reset", MC13783_AUDIO_CODEC, 15, 0, NULL, 0), /* Output */ - SND_SOC_DAPM_SUPPLY("DAC_E", 41, 11, 0, NULL, 0), - SND_SOC_DAPM_SUPPLY("DAC_Reset", 41, 15, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("DAC_E", MC13783_AUDIO_DAC, 11, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("DAC_Reset", MC13783_AUDIO_DAC, 15, 0, NULL, 0), SND_SOC_DAPM_OUTPUT("RXOUTL"), SND_SOC_DAPM_OUTPUT("RXOUTR"), SND_SOC_DAPM_OUTPUT("HSL"), @@ -516,14 +516,18 @@ static const struct snd_soc_dapm_widget mc13783_dapm_widgets[] = { SND_SOC_DAPM_OUTPUT("LSP"), SND_SOC_DAPM_OUTPUT("SP"), - SND_SOC_DAPM_SWITCH("Speaker Amp", 36, 3, 0, &samp_ctl), + SND_SOC_DAPM_SWITCH("Speaker Amp", MC13783_AUDIO_RX0, 3, 0, &samp_ctl), SND_SOC_DAPM_SWITCH("Loudspeaker Amp", SND_SOC_NOPM, 0, 0, &lamp_ctl), - SND_SOC_DAPM_SWITCH("Headset Amp Left", 36, 10, 0, &hlamp_ctl), - SND_SOC_DAPM_SWITCH("Headset Amp Right", 36, 9, 0, &hramp_ctl), - SND_SOC_DAPM_SWITCH("Line out Amp Left", 36, 16, 0, &llamp_ctl), - SND_SOC_DAPM_SWITCH("Line out Amp Right", 36, 15, 0, &lramp_ctl), - SND_SOC_DAPM_DAC("DAC", "Playback", 36, 22, 0), - SND_SOC_DAPM_PGA("DAC PGA", 37, 5, 0, NULL, 0), + SND_SOC_DAPM_SWITCH("Headset Amp Left", MC13783_AUDIO_RX0, 10, 0, + &hlamp_ctl), + SND_SOC_DAPM_SWITCH("Headset Amp Right", MC13783_AUDIO_RX0, 9, 0, + &hramp_ctl), + SND_SOC_DAPM_SWITCH("Line out Amp Left", MC13783_AUDIO_RX0, 16, 0, + &llamp_ctl), + SND_SOC_DAPM_SWITCH("Line out Amp Right", MC13783_AUDIO_RX0, 15, 0, + &lramp_ctl), + SND_SOC_DAPM_DAC("DAC", "Playback", MC13783_AUDIO_RX0, 22, 0), + SND_SOC_DAPM_PGA("DAC PGA", MC13783_AUDIO_RX1, 5, 0, NULL, 0), }; static struct snd_soc_dapm_route mc13783_routes[] = { -- cgit v1.2.3 From 822b4b8d63e09076a4487eb881d3b7a13b28121c Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 7 Sep 2012 10:54:32 +0800 Subject: ASoC: dapm: Add flags to regulator supplies This will be used to enable additional control of the regulators. Signed-off-by: Mark Brown Acked-by: Liam Girdwood --- include/sound/soc-dapm.h | 5 +++-- sound/soc/codecs/ab8500-codec.c | 8 ++++---- sound/soc/codecs/wm2200.c | 4 ++-- sound/soc/codecs/wm5100.c | 6 +++--- sound/soc/codecs/wm5102.c | 12 ++++++------ sound/soc/codecs/wm5110.c | 12 ++++++------ sound/soc/codecs/wm8996.c | 2 +- 7 files changed, 25 insertions(+), 24 deletions(-) (limited to 'sound/soc') diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h index 07e2510619a1..c96bf5ae80a6 100644 --- a/include/sound/soc-dapm.h +++ b/include/sound/soc-dapm.h @@ -244,10 +244,11 @@ struct device; { .id = snd_soc_dapm_supply, .name = wname, .reg = wreg, \ .shift = wshift, .invert = winvert, .event = wevent, \ .event_flags = wflags} -#define SND_SOC_DAPM_REGULATOR_SUPPLY(wname, wdelay) \ +#define SND_SOC_DAPM_REGULATOR_SUPPLY(wname, wdelay, wflags) \ { .id = snd_soc_dapm_regulator_supply, .name = wname, \ .reg = SND_SOC_NOPM, .shift = wdelay, .event = dapm_regulator_event, \ - .event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD } + .event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD, \ + .invert = wflags} /* dapm kcontrol types */ diff --git a/sound/soc/codecs/ab8500-codec.c b/sound/soc/codecs/ab8500-codec.c index b7836503dc69..3f46bffeb0c3 100644 --- a/sound/soc/codecs/ab8500-codec.c +++ b/sound/soc/codecs/ab8500-codec.c @@ -390,10 +390,10 @@ static const struct snd_soc_dapm_widget ab8500_dapm_widgets[] = { SND_SOC_DAPM_CLOCK_SUPPLY("audioclk"), /* Regulators */ - SND_SOC_DAPM_REGULATOR_SUPPLY("V-AUD", 0), - SND_SOC_DAPM_REGULATOR_SUPPLY("V-AMIC1", 0), - SND_SOC_DAPM_REGULATOR_SUPPLY("V-AMIC2", 0), - SND_SOC_DAPM_REGULATOR_SUPPLY("V-DMIC", 0), + SND_SOC_DAPM_REGULATOR_SUPPLY("V-AUD", 0, 0), + SND_SOC_DAPM_REGULATOR_SUPPLY("V-AMIC1", 0, 0), + SND_SOC_DAPM_REGULATOR_SUPPLY("V-AMIC2", 0, 0), + SND_SOC_DAPM_REGULATOR_SUPPLY("V-DMIC", 0, 0), /* Power */ SND_SOC_DAPM_SUPPLY("Audio Power", diff --git a/sound/soc/codecs/wm2200.c b/sound/soc/codecs/wm2200.c index 71debd0a3822..efa93dbb0191 100644 --- a/sound/soc/codecs/wm2200.c +++ b/sound/soc/codecs/wm2200.c @@ -1117,8 +1117,8 @@ SND_SOC_DAPM_SUPPLY("MICBIAS1", WM2200_MIC_BIAS_CTRL_1, WM2200_MICB1_ENA_SHIFT, 0, NULL, 0), SND_SOC_DAPM_SUPPLY("MICBIAS2", WM2200_MIC_BIAS_CTRL_2, WM2200_MICB2_ENA_SHIFT, 0, NULL, 0), -SND_SOC_DAPM_REGULATOR_SUPPLY("CPVDD", 20), -SND_SOC_DAPM_REGULATOR_SUPPLY("AVDD", 20), +SND_SOC_DAPM_REGULATOR_SUPPLY("CPVDD", 20, 0), +SND_SOC_DAPM_REGULATOR_SUPPLY("AVDD", 20, 0), SND_SOC_DAPM_INPUT("IN1L"), SND_SOC_DAPM_INPUT("IN1R"), diff --git a/sound/soc/codecs/wm5100.c b/sound/soc/codecs/wm5100.c index f4817292ef45..4da1b92b22c2 100644 --- a/sound/soc/codecs/wm5100.c +++ b/sound/soc/codecs/wm5100.c @@ -848,9 +848,9 @@ SND_SOC_DAPM_SUPPLY("SYSCLK", WM5100_CLOCKING_3, WM5100_SYSCLK_ENA_SHIFT, 0, SND_SOC_DAPM_SUPPLY("ASYNCCLK", WM5100_CLOCKING_6, WM5100_ASYNC_CLK_ENA_SHIFT, 0, NULL, 0), -SND_SOC_DAPM_REGULATOR_SUPPLY("CPVDD", 20), -SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD2", 0), -SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD3", 0), +SND_SOC_DAPM_REGULATOR_SUPPLY("CPVDD", 20, 0), +SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD2", 0, 0), +SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD3", 0, 0), SND_SOC_DAPM_SUPPLY("CP1", WM5100_HP_CHARGE_PUMP_1, WM5100_CP1_ENA_SHIFT, 0, NULL, 0), diff --git a/sound/soc/codecs/wm5102.c b/sound/soc/codecs/wm5102.c index e2fb07ee68a7..4a2db4e10885 100644 --- a/sound/soc/codecs/wm5102.c +++ b/sound/soc/codecs/wm5102.c @@ -305,12 +305,12 @@ SND_SOC_DAPM_SUPPLY("OPCLK", ARIZONA_OUTPUT_SYSTEM_CLOCK, SND_SOC_DAPM_SUPPLY("ASYNCOPCLK", ARIZONA_OUTPUT_ASYNC_CLOCK, ARIZONA_OPCLK_ASYNC_ENA_SHIFT, 0, NULL, 0), -SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD2", 0), -SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD3", 0), -SND_SOC_DAPM_REGULATOR_SUPPLY("CPVDD", 20), -SND_SOC_DAPM_REGULATOR_SUPPLY("MICVDD", 0), -SND_SOC_DAPM_REGULATOR_SUPPLY("SPKVDDL", 0), -SND_SOC_DAPM_REGULATOR_SUPPLY("SPKVDDR", 0), +SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD2", 0, 0), +SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD3", 0, 0), +SND_SOC_DAPM_REGULATOR_SUPPLY("CPVDD", 20, 0), +SND_SOC_DAPM_REGULATOR_SUPPLY("MICVDD", 0, 0), +SND_SOC_DAPM_REGULATOR_SUPPLY("SPKVDDL", 0, 0), +SND_SOC_DAPM_REGULATOR_SUPPLY("SPKVDDR", 0, 0), SND_SOC_DAPM_SIGGEN("TONE"), SND_SOC_DAPM_SIGGEN("NOISE"), diff --git a/sound/soc/codecs/wm5110.c b/sound/soc/codecs/wm5110.c index 57c7d9c0aadb..bf47914234b3 100644 --- a/sound/soc/codecs/wm5110.c +++ b/sound/soc/codecs/wm5110.c @@ -310,12 +310,12 @@ SND_SOC_DAPM_SUPPLY("OPCLK", ARIZONA_OUTPUT_SYSTEM_CLOCK, SND_SOC_DAPM_SUPPLY("ASYNCOPCLK", ARIZONA_OUTPUT_ASYNC_CLOCK, ARIZONA_OPCLK_ASYNC_ENA_SHIFT, 0, NULL, 0), -SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD2", 0), -SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD3", 0), -SND_SOC_DAPM_REGULATOR_SUPPLY("CPVDD", 20), -SND_SOC_DAPM_REGULATOR_SUPPLY("MICVDD", 0), -SND_SOC_DAPM_REGULATOR_SUPPLY("SPKVDDL", 0), -SND_SOC_DAPM_REGULATOR_SUPPLY("SPKVDDR", 0), +SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD2", 0, 0), +SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD3", 0, 0), +SND_SOC_DAPM_REGULATOR_SUPPLY("CPVDD", 20, 0), +SND_SOC_DAPM_REGULATOR_SUPPLY("MICVDD", 0, 0), +SND_SOC_DAPM_REGULATOR_SUPPLY("SPKVDDL", 0, 0), +SND_SOC_DAPM_REGULATOR_SUPPLY("SPKVDDR", 0, 0), SND_SOC_DAPM_SIGGEN("TONE"), SND_SOC_DAPM_SIGGEN("NOISE"), diff --git a/sound/soc/codecs/wm8996.c b/sound/soc/codecs/wm8996.c index 00f183dfa454..6dcb02c3666f 100644 --- a/sound/soc/codecs/wm8996.c +++ b/sound/soc/codecs/wm8996.c @@ -931,7 +931,7 @@ SND_SOC_DAPM_INPUT("IN2RP"), SND_SOC_DAPM_INPUT("DMIC1DAT"), SND_SOC_DAPM_INPUT("DMIC2DAT"), -SND_SOC_DAPM_REGULATOR_SUPPLY("CPVDD", 20), +SND_SOC_DAPM_REGULATOR_SUPPLY("CPVDD", 20, 0), SND_SOC_DAPM_SUPPLY_S("SYSCLK", 1, WM8996_AIF_CLOCKING_1, 0, 0, NULL, 0), SND_SOC_DAPM_SUPPLY_S("SYSDSPCLK", 2, WM8996_CLOCKING_1, 1, 0, NULL, 0), SND_SOC_DAPM_SUPPLY_S("AIFCLK", 2, WM8996_CLOCKING_1, 2, 0, NULL, 0), -- cgit v1.2.3 From d6e2dc150ba748c4de518532b0d71275e3c3d959 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 10 Sep 2012 15:14:16 +0800 Subject: ASoC: wm8983: Convert to devm_kzalloc() Signed-off-by: Mark Brown --- sound/soc/codecs/wm8983.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/wm8983.c b/sound/soc/codecs/wm8983.c index 367388fdc486..57c33fc19681 100644 --- a/sound/soc/codecs/wm8983.c +++ b/sound/soc/codecs/wm8983.c @@ -1085,7 +1085,7 @@ static int __devinit wm8983_spi_probe(struct spi_device *spi) struct wm8983_priv *wm8983; int ret; - wm8983 = kzalloc(sizeof *wm8983, GFP_KERNEL); + wm8983 = devm_kzalloc(&spi->dev, sizeof *wm8983, GFP_KERNEL); if (!wm8983) return -ENOMEM; @@ -1094,15 +1094,12 @@ static int __devinit wm8983_spi_probe(struct spi_device *spi) ret = snd_soc_register_codec(&spi->dev, &soc_codec_dev_wm8983, &wm8983_dai, 1); - if (ret < 0) - kfree(wm8983); return ret; } static int __devexit wm8983_spi_remove(struct spi_device *spi) { snd_soc_unregister_codec(&spi->dev); - kfree(spi_get_drvdata(spi)); return 0; } @@ -1123,7 +1120,7 @@ static __devinit int wm8983_i2c_probe(struct i2c_client *i2c, struct wm8983_priv *wm8983; int ret; - wm8983 = kzalloc(sizeof *wm8983, GFP_KERNEL); + wm8983 = devm_kzalloc(&i2c->dev, sizeof *wm8983, GFP_KERNEL); if (!wm8983) return -ENOMEM; @@ -1132,15 +1129,13 @@ static __devinit int wm8983_i2c_probe(struct i2c_client *i2c, ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_wm8983, &wm8983_dai, 1); - if (ret < 0) - kfree(wm8983); + return ret; } static __devexit int wm8983_i2c_remove(struct i2c_client *client) { snd_soc_unregister_codec(&client->dev); - kfree(i2c_get_clientdata(client)); return 0; } -- cgit v1.2.3 From 2ee01ac63b72a3101d6293b50d70d830959bbe8f Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 10 Sep 2012 15:28:19 +0800 Subject: ASoC: wm8983: Convert to direct regmap API usage Signed-off-by: Mark Brown --- sound/soc/codecs/wm8983.c | 151 ++++++++++++++++++++++++++-------------------- 1 file changed, 85 insertions(+), 66 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/wm8983.c b/sound/soc/codecs/wm8983.c index 57c33fc19681..d8879f262d27 100644 --- a/sound/soc/codecs/wm8983.c +++ b/sound/soc/codecs/wm8983.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -27,61 +28,60 @@ #include "wm8983.h" -static const u16 wm8983_reg_defs[WM8983_MAX_REGISTER + 1] = { - [0x00] = 0x0000, /* R0 - Software Reset */ - [0x01] = 0x0000, /* R1 - Power management 1 */ - [0x02] = 0x0000, /* R2 - Power management 2 */ - [0x03] = 0x0000, /* R3 - Power management 3 */ - [0x04] = 0x0050, /* R4 - Audio Interface */ - [0x05] = 0x0000, /* R5 - Companding control */ - [0x06] = 0x0140, /* R6 - Clock Gen control */ - [0x07] = 0x0000, /* R7 - Additional control */ - [0x08] = 0x0000, /* R8 - GPIO Control */ - [0x09] = 0x0000, /* R9 - Jack Detect Control 1 */ - [0x0A] = 0x0000, /* R10 - DAC Control */ - [0x0B] = 0x00FF, /* R11 - Left DAC digital Vol */ - [0x0C] = 0x00FF, /* R12 - Right DAC digital vol */ - [0x0D] = 0x0000, /* R13 - Jack Detect Control 2 */ - [0x0E] = 0x0100, /* R14 - ADC Control */ - [0x0F] = 0x00FF, /* R15 - Left ADC Digital Vol */ - [0x10] = 0x00FF, /* R16 - Right ADC Digital Vol */ - [0x12] = 0x012C, /* R18 - EQ1 - low shelf */ - [0x13] = 0x002C, /* R19 - EQ2 - peak 1 */ - [0x14] = 0x002C, /* R20 - EQ3 - peak 2 */ - [0x15] = 0x002C, /* R21 - EQ4 - peak 3 */ - [0x16] = 0x002C, /* R22 - EQ5 - high shelf */ - [0x18] = 0x0032, /* R24 - DAC Limiter 1 */ - [0x19] = 0x0000, /* R25 - DAC Limiter 2 */ - [0x1B] = 0x0000, /* R27 - Notch Filter 1 */ - [0x1C] = 0x0000, /* R28 - Notch Filter 2 */ - [0x1D] = 0x0000, /* R29 - Notch Filter 3 */ - [0x1E] = 0x0000, /* R30 - Notch Filter 4 */ - [0x20] = 0x0038, /* R32 - ALC control 1 */ - [0x21] = 0x000B, /* R33 - ALC control 2 */ - [0x22] = 0x0032, /* R34 - ALC control 3 */ - [0x23] = 0x0000, /* R35 - Noise Gate */ - [0x24] = 0x0008, /* R36 - PLL N */ - [0x25] = 0x000C, /* R37 - PLL K 1 */ - [0x26] = 0x0093, /* R38 - PLL K 2 */ - [0x27] = 0x00E9, /* R39 - PLL K 3 */ - [0x29] = 0x0000, /* R41 - 3D control */ - [0x2A] = 0x0000, /* R42 - OUT4 to ADC */ - [0x2B] = 0x0000, /* R43 - Beep control */ - [0x2C] = 0x0033, /* R44 - Input ctrl */ - [0x2D] = 0x0010, /* R45 - Left INP PGA gain ctrl */ - [0x2E] = 0x0010, /* R46 - Right INP PGA gain ctrl */ - [0x2F] = 0x0100, /* R47 - Left ADC BOOST ctrl */ - [0x30] = 0x0100, /* R48 - Right ADC BOOST ctrl */ - [0x31] = 0x0002, /* R49 - Output ctrl */ - [0x32] = 0x0001, /* R50 - Left mixer ctrl */ - [0x33] = 0x0001, /* R51 - Right mixer ctrl */ - [0x34] = 0x0039, /* R52 - LOUT1 (HP) volume ctrl */ - [0x35] = 0x0039, /* R53 - ROUT1 (HP) volume ctrl */ - [0x36] = 0x0039, /* R54 - LOUT2 (SPK) volume ctrl */ - [0x37] = 0x0039, /* R55 - ROUT2 (SPK) volume ctrl */ - [0x38] = 0x0001, /* R56 - OUT3 mixer ctrl */ - [0x39] = 0x0001, /* R57 - OUT4 (MONO) mix ctrl */ - [0x3D] = 0x0000 /* R61 - BIAS CTRL */ +static const struct reg_default wm8983_defaults[] = { + { 0x01, 0x0000 }, /* R1 - Power management 1 */ + { 0x02, 0x0000 }, /* R2 - Power management 2 */ + { 0x03, 0x0000 }, /* R3 - Power management 3 */ + { 0x04, 0x0050 }, /* R4 - Audio Interface */ + { 0x05, 0x0000 }, /* R5 - Companding control */ + { 0x06, 0x0140 }, /* R6 - Clock Gen control */ + { 0x07, 0x0000 }, /* R7 - Additional control */ + { 0x08, 0x0000 }, /* R8 - GPIO Control */ + { 0x09, 0x0000 }, /* R9 - Jack Detect Control 1 */ + { 0x0A, 0x0000 }, /* R10 - DAC Control */ + { 0x0B, 0x00FF }, /* R11 - Left DAC digital Vol */ + { 0x0C, 0x00FF }, /* R12 - Right DAC digital vol */ + { 0x0D, 0x0000 }, /* R13 - Jack Detect Control 2 */ + { 0x0E, 0x0100 }, /* R14 - ADC Control */ + { 0x0F, 0x00FF }, /* R15 - Left ADC Digital Vol */ + { 0x10, 0x00FF }, /* R16 - Right ADC Digital Vol */ + { 0x12, 0x012C }, /* R18 - EQ1 - low shelf */ + { 0x13, 0x002C }, /* R19 - EQ2 - peak 1 */ + { 0x14, 0x002C }, /* R20 - EQ3 - peak 2 */ + { 0x15, 0x002C }, /* R21 - EQ4 - peak 3 */ + { 0x16, 0x002C }, /* R22 - EQ5 - high shelf */ + { 0x18, 0x0032 }, /* R24 - DAC Limiter 1 */ + { 0x19, 0x0000 }, /* R25 - DAC Limiter 2 */ + { 0x1B, 0x0000 }, /* R27 - Notch Filter 1 */ + { 0x1C, 0x0000 }, /* R28 - Notch Filter 2 */ + { 0x1D, 0x0000 }, /* R29 - Notch Filter 3 */ + { 0x1E, 0x0000 }, /* R30 - Notch Filter 4 */ + { 0x20, 0x0038 }, /* R32 - ALC control 1 */ + { 0x21, 0x000B }, /* R33 - ALC control 2 */ + { 0x22, 0x0032 }, /* R34 - ALC control 3 */ + { 0x23, 0x0000 }, /* R35 - Noise Gate */ + { 0x24, 0x0008 }, /* R36 - PLL N */ + { 0x25, 0x000C }, /* R37 - PLL K 1 */ + { 0x26, 0x0093 }, /* R38 - PLL K 2 */ + { 0x27, 0x00E9 }, /* R39 - PLL K 3 */ + { 0x29, 0x0000 }, /* R41 - 3D control */ + { 0x2A, 0x0000 }, /* R42 - OUT4 to ADC */ + { 0x2B, 0x0000 }, /* R43 - Beep control */ + { 0x2C, 0x0033 }, /* R44 - Input ctrl */ + { 0x2D, 0x0010 }, /* R45 - Left INP PGA gain ctrl */ + { 0x2E, 0x0010 }, /* R46 - Right INP PGA gain ctrl */ + { 0x2F, 0x0100 }, /* R47 - Left ADC BOOST ctrl */ + { 0x30, 0x0100 }, /* R48 - Right ADC BOOST ctrl */ + { 0x31, 0x0002 }, /* R49 - Output ctrl */ + { 0x32, 0x0001 }, /* R50 - Left mixer ctrl */ + { 0x33, 0x0001 }, /* R51 - Right mixer ctrl */ + { 0x34, 0x0039 }, /* R52 - LOUT1 (HP) volume ctrl */ + { 0x35, 0x0039 }, /* R53 - ROUT1 (HP) volume ctrl */ + { 0x36, 0x0039 }, /* R54 - LOUT2 (SPK) volume ctrl */ + { 0x37, 0x0039 }, /* R55 - ROUT2 (SPK) volume ctrl */ + { 0x38, 0x0001 }, /* R56 - OUT3 mixer ctrl */ + { 0x39, 0x0001 }, /* R57 - OUT4 (MONO) mix ctrl */ + { 0x3D, 0x0000 }, /* R61 - BIAS CTRL */ }; static const struct wm8983_reg_access { @@ -159,7 +159,7 @@ static const int vol_update_regs[] = { }; struct wm8983_priv { - enum snd_soc_control_type control_type; + struct regmap *regmap; u32 sysclk; u32 bclk; }; @@ -610,7 +610,7 @@ static int eqmode_put(struct snd_kcontrol *kcontrol, return 0; } -static int wm8983_readable(struct snd_soc_codec *codec, unsigned int reg) +static bool wm8983_readable(struct device *dev, unsigned int reg) { if (reg > WM8983_MAX_REGISTER) return 0; @@ -905,6 +905,7 @@ static int wm8983_set_sysclk(struct snd_soc_dai *dai, static int wm8983_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level) { + struct wm8983_priv *wm8983 = snd_soc_codec_get_drvdata(codec); int ret; switch (level) { @@ -917,7 +918,7 @@ static int wm8983_set_bias_level(struct snd_soc_codec *codec, break; case SND_SOC_BIAS_STANDBY: if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { - ret = snd_soc_cache_sync(codec); + ret = regcache_sync(wm8983->regmap); if (ret < 0) { dev_err(codec->dev, "Failed to sync cache: %d\n", ret); return ret; @@ -994,10 +995,9 @@ static int wm8983_remove(struct snd_soc_codec *codec) static int wm8983_probe(struct snd_soc_codec *codec) { int ret; - struct wm8983_priv *wm8983 = snd_soc_codec_get_drvdata(codec); int i; - ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8983->control_type); + ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); if (ret < 0) { dev_err(codec->dev, "Failed to set cache i/o: %d\n", ret); return ret; @@ -1067,16 +1067,23 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8983 = { .suspend = wm8983_suspend, .resume = wm8983_resume, .set_bias_level = wm8983_set_bias_level, - .reg_cache_size = ARRAY_SIZE(wm8983_reg_defs), - .reg_word_size = sizeof(u16), - .reg_cache_default = wm8983_reg_defs, .controls = wm8983_snd_controls, .num_controls = ARRAY_SIZE(wm8983_snd_controls), .dapm_widgets = wm8983_dapm_widgets, .num_dapm_widgets = ARRAY_SIZE(wm8983_dapm_widgets), .dapm_routes = wm8983_audio_map, .num_dapm_routes = ARRAY_SIZE(wm8983_audio_map), - .readable_register = wm8983_readable +}; + +static const struct regmap_config wm8983_regmap = { + .reg_bits = 7, + .val_bits = 9, + + .reg_defaults = wm8983_defaults, + .num_reg_defaults = ARRAY_SIZE(wm8983_defaults), + .cache_type = REGCACHE_RBTREE, + + .readable_reg = wm8983_readable, }; #if defined(CONFIG_SPI_MASTER) @@ -1089,7 +1096,13 @@ static int __devinit wm8983_spi_probe(struct spi_device *spi) if (!wm8983) return -ENOMEM; - wm8983->control_type = SND_SOC_SPI; + wm8983->regmap = devm_regmap_init_spi(spi, &wm8983_regmap); + if (IS_ERR(wm8983->regmap)) { + ret = PTR_ERR(wm8983->regmap); + dev_err(&spi->dev, "Failed to init regmap: %d\n", ret); + return ret; + } + spi_set_drvdata(spi, wm8983); ret = snd_soc_register_codec(&spi->dev, @@ -1124,7 +1137,13 @@ static __devinit int wm8983_i2c_probe(struct i2c_client *i2c, if (!wm8983) return -ENOMEM; - wm8983->control_type = SND_SOC_I2C; + wm8983->regmap = devm_regmap_init_i2c(i2c, &wm8983_regmap); + if (IS_ERR(wm8983->regmap)) { + ret = PTR_ERR(wm8983->regmap); + dev_err(&i2c->dev, "Failed to init regmap: %d\n", ret); + return ret; + } + i2c_set_clientdata(i2c, wm8983); ret = snd_soc_register_codec(&i2c->dev, -- cgit v1.2.3 From 7d014db8baf70bcc7e9cf1457350b11bc2affbbd Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 10 Sep 2012 16:18:56 +0800 Subject: ASoC: wm8523: Convert to devm_kzalloc() Signed-off-by: Mark Brown --- sound/soc/codecs/wm8523.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/wm8523.c b/sound/soc/codecs/wm8523.c index 1c3ffb290cdc..af2289ee6cd6 100644 --- a/sound/soc/codecs/wm8523.c +++ b/sound/soc/codecs/wm8523.c @@ -516,7 +516,8 @@ static __devinit int wm8523_i2c_probe(struct i2c_client *i2c, struct wm8523_priv *wm8523; int ret; - wm8523 = kzalloc(sizeof(struct wm8523_priv), GFP_KERNEL); + wm8523 = devm_kzalloc(&i2c->dev, sizeof(struct wm8523_priv), + GFP_KERNEL); if (wm8523 == NULL) return -ENOMEM; @@ -525,8 +526,7 @@ static __devinit int wm8523_i2c_probe(struct i2c_client *i2c, ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_wm8523, &wm8523_dai, 1); - if (ret < 0) - kfree(wm8523); + return ret; } @@ -534,7 +534,6 @@ static __devinit int wm8523_i2c_probe(struct i2c_client *i2c, static __devexit int wm8523_i2c_remove(struct i2c_client *client) { snd_soc_unregister_codec(&client->dev); - kfree(i2c_get_clientdata(client)); return 0; } -- cgit v1.2.3 From 719b0c593cbb2a199e977b4dcca1d096a4a0d6a7 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 10 Sep 2012 16:23:34 +0800 Subject: ASoC: wm8523: Move regulator acquisition to I2C probe() This is better style since we acquire all needed resources before we try to do the ASoC card probe. Signed-off-by: Mark Brown --- sound/soc/codecs/wm8523.c | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/wm8523.c b/sound/soc/codecs/wm8523.c index af2289ee6cd6..c4c64e225c42 100644 --- a/sound/soc/codecs/wm8523.c +++ b/sound/soc/codecs/wm8523.c @@ -402,7 +402,7 @@ static int wm8523_resume(struct snd_soc_codec *codec) static int wm8523_probe(struct snd_soc_codec *codec) { struct wm8523_priv *wm8523 = snd_soc_codec_get_drvdata(codec); - int ret, i; + int ret; wm8523->rate_constraint.list = &wm8523->rate_constraint_list[0]; wm8523->rate_constraint.count = @@ -414,16 +414,6 @@ static int wm8523_probe(struct snd_soc_codec *codec) return ret; } - for (i = 0; i < ARRAY_SIZE(wm8523->supplies); i++) - wm8523->supplies[i].supply = wm8523_supply_names[i]; - - ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8523->supplies), - wm8523->supplies); - if (ret != 0) { - dev_err(codec->dev, "Failed to request supplies: %d\n", ret); - return ret; - } - ret = regulator_bulk_enable(ARRAY_SIZE(wm8523->supplies), wm8523->supplies); if (ret != 0) { @@ -471,7 +461,6 @@ static int wm8523_probe(struct snd_soc_codec *codec) err_enable: regulator_bulk_disable(ARRAY_SIZE(wm8523->supplies), wm8523->supplies); err_get: - regulator_bulk_free(ARRAY_SIZE(wm8523->supplies), wm8523->supplies); return ret; } @@ -481,7 +470,6 @@ static int wm8523_remove(struct snd_soc_codec *codec) struct wm8523_priv *wm8523 = snd_soc_codec_get_drvdata(codec); wm8523_set_bias_level(codec, SND_SOC_BIAS_OFF); - regulator_bulk_free(ARRAY_SIZE(wm8523->supplies), wm8523->supplies); return 0; } @@ -514,13 +502,23 @@ static __devinit int wm8523_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { struct wm8523_priv *wm8523; - int ret; + int ret, i; wm8523 = devm_kzalloc(&i2c->dev, sizeof(struct wm8523_priv), GFP_KERNEL); if (wm8523 == NULL) return -ENOMEM; + for (i = 0; i < ARRAY_SIZE(wm8523->supplies); i++) + wm8523->supplies[i].supply = wm8523_supply_names[i]; + + ret = devm_regulator_bulk_get(&i2c->dev, ARRAY_SIZE(wm8523->supplies), + wm8523->supplies); + if (ret != 0) { + dev_err(&i2c->dev, "Failed to request supplies: %d\n", ret); + return ret; + } + i2c_set_clientdata(i2c, wm8523); wm8523->control_type = SND_SOC_I2C; -- cgit v1.2.3 From b9288f49dc5ac8342cc34163093c9f7d096b6378 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 10 Sep 2012 16:27:45 +0800 Subject: ASoC: wm8523: Convert to direct regmap API usage Signed-off-by: Mark Brown --- sound/soc/codecs/wm8523.c | 69 ++++++++++++++++++++++++++--------------------- 1 file changed, 38 insertions(+), 31 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/wm8523.c b/sound/soc/codecs/wm8523.c index c4c64e225c42..d7d5fe6866a6 100644 --- a/sound/soc/codecs/wm8523.c +++ b/sound/soc/codecs/wm8523.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -39,33 +40,31 @@ static const char *wm8523_supply_names[WM8523_NUM_SUPPLIES] = { /* codec private data */ struct wm8523_priv { - enum snd_soc_control_type control_type; + struct regmap *regmap; struct regulator_bulk_data supplies[WM8523_NUM_SUPPLIES]; unsigned int sysclk; unsigned int rate_constraint_list[WM8523_NUM_RATES]; struct snd_pcm_hw_constraint_list rate_constraint; }; -static const u16 wm8523_reg[WM8523_REGISTER_COUNT] = { - 0x8523, /* R0 - DEVICE_ID */ - 0x0001, /* R1 - REVISION */ - 0x0000, /* R2 - PSCTRL1 */ - 0x1812, /* R3 - AIF_CTRL1 */ - 0x0000, /* R4 - AIF_CTRL2 */ - 0x0001, /* R5 - DAC_CTRL3 */ - 0x0190, /* R6 - DAC_GAINL */ - 0x0190, /* R7 - DAC_GAINR */ - 0x0000, /* R8 - ZERO_DETECT */ +static const struct reg_default wm8523_reg_defaults[] = { + { 2, 0x0000 }, /* R2 - PSCTRL1 */ + { 3, 0x1812 }, /* R3 - AIF_CTRL1 */ + { 4, 0x0000 }, /* R4 - AIF_CTRL2 */ + { 5, 0x0001 }, /* R5 - DAC_CTRL3 */ + { 6, 0x0190 }, /* R6 - DAC_GAINL */ + { 7, 0x0190 }, /* R7 - DAC_GAINR */ + { 8, 0x0000 }, /* R8 - ZERO_DETECT */ }; -static int wm8523_volatile_register(struct snd_soc_codec *codec, unsigned int reg) +static bool wm8523_volatile_register(struct device *dev, unsigned int reg) { switch (reg) { case WM8523_DEVICE_ID: case WM8523_REVISION: - return 1; + return true; default: - return 0; + return false; } } @@ -301,8 +300,7 @@ static int wm8523_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level) { struct wm8523_priv *wm8523 = snd_soc_codec_get_drvdata(codec); - u16 *reg_cache = codec->reg_cache; - int ret, i; + int ret; switch (level) { case SND_SOC_BIAS_ON: @@ -325,16 +323,13 @@ static int wm8523_set_bias_level(struct snd_soc_codec *codec, return ret; } + /* Sync back default/cached values */ + regcache_sync(wm8523->regmap); + /* Initial power up */ snd_soc_update_bits(codec, WM8523_PSCTRL1, WM8523_SYS_ENA_MASK, 1); - /* Sync back default/cached values */ - for (i = WM8523_AIF_CTRL1; - i < WM8523_MAX_REGISTER; i++) - snd_soc_write(codec, i, reg_cache[i]); - - msleep(100); } @@ -408,7 +403,7 @@ static int wm8523_probe(struct snd_soc_codec *codec) wm8523->rate_constraint.count = ARRAY_SIZE(wm8523->rate_constraint_list); - ret = snd_soc_codec_set_cache_io(codec, 8, 16, wm8523->control_type); + ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP); if (ret != 0) { dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); return ret; @@ -426,7 +421,7 @@ static int wm8523_probe(struct snd_soc_codec *codec) dev_err(codec->dev, "Failed to read ID register\n"); goto err_enable; } - if (ret != wm8523_reg[WM8523_DEVICE_ID]) { + if (ret != 0x8523) { dev_err(codec->dev, "Device is not a WM8523, ID is %x\n", ret); ret = -EINVAL; goto err_enable; @@ -467,8 +462,6 @@ err_get: static int wm8523_remove(struct snd_soc_codec *codec) { - struct wm8523_priv *wm8523 = snd_soc_codec_get_drvdata(codec); - wm8523_set_bias_level(codec, SND_SOC_BIAS_OFF); return 0; } @@ -479,10 +472,6 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8523 = { .suspend = wm8523_suspend, .resume = wm8523_resume, .set_bias_level = wm8523_set_bias_level, - .reg_cache_size = WM8523_REGISTER_COUNT, - .reg_word_size = sizeof(u16), - .reg_cache_default = wm8523_reg, - .volatile_register = wm8523_volatile_register, .controls = wm8523_controls, .num_controls = ARRAY_SIZE(wm8523_controls), @@ -497,6 +486,18 @@ static const struct of_device_id wm8523_of_match[] = { { }, }; +static const struct regmap_config wm8523_regmap = { + .reg_bits = 8, + .val_bits = 16, + .max_register = WM8523_ZERO_DETECT, + + .reg_defaults = wm8523_reg_defaults, + .num_reg_defaults = ARRAY_SIZE(wm8523_reg_defaults), + .cache_type = REGCACHE_RBTREE, + + .volatile_reg = wm8523_volatile_register, +}; + #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) static __devinit int wm8523_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) @@ -509,6 +510,13 @@ static __devinit int wm8523_i2c_probe(struct i2c_client *i2c, if (wm8523 == NULL) return -ENOMEM; + wm8523->regmap = devm_regmap_init_i2c(i2c, &wm8523_regmap); + if (IS_ERR(wm8523->regmap)) { + ret = PTR_ERR(wm8523->regmap); + dev_err(&i2c->dev, "Failed to create regmap: %d\n", ret); + return ret; + } + for (i = 0; i < ARRAY_SIZE(wm8523->supplies); i++) wm8523->supplies[i].supply = wm8523_supply_names[i]; @@ -520,7 +528,6 @@ static __devinit int wm8523_i2c_probe(struct i2c_client *i2c, } i2c_set_clientdata(i2c, wm8523); - wm8523->control_type = SND_SOC_I2C; ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_wm8523, &wm8523_dai, 1); -- cgit v1.2.3 From 59ac2149aee9b69732dad602ea250ecb60b9e617 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 10 Sep 2012 17:07:24 +0800 Subject: ASoC: wm8523: Move device ID verification and reset to I2C probe Ensure that we have confirmed that we've got the device in place before we register with ASoC. Signed-off-by: Mark Brown --- sound/soc/codecs/wm8523.c | 84 +++++++++++++++++++++-------------------------- 1 file changed, 38 insertions(+), 46 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/wm8523.c b/sound/soc/codecs/wm8523.c index d7d5fe6866a6..8d5c27673501 100644 --- a/sound/soc/codecs/wm8523.c +++ b/sound/soc/codecs/wm8523.c @@ -68,11 +68,6 @@ static bool wm8523_volatile_register(struct device *dev, unsigned int reg) } } -static int wm8523_reset(struct snd_soc_codec *codec) -{ - return snd_soc_write(codec, WM8523_DEVICE_ID, 0); -} - static const DECLARE_TLV_DB_SCALE(dac_tlv, -10000, 25, 0); static const char *wm8523_zd_count_text[] = { @@ -409,38 +404,6 @@ static int wm8523_probe(struct snd_soc_codec *codec) return ret; } - ret = regulator_bulk_enable(ARRAY_SIZE(wm8523->supplies), - wm8523->supplies); - if (ret != 0) { - dev_err(codec->dev, "Failed to enable supplies: %d\n", ret); - goto err_get; - } - - ret = snd_soc_read(codec, WM8523_DEVICE_ID); - if (ret < 0) { - dev_err(codec->dev, "Failed to read ID register\n"); - goto err_enable; - } - if (ret != 0x8523) { - dev_err(codec->dev, "Device is not a WM8523, ID is %x\n", ret); - ret = -EINVAL; - goto err_enable; - } - - ret = snd_soc_read(codec, WM8523_REVISION); - if (ret < 0) { - dev_err(codec->dev, "Failed to read revision register\n"); - goto err_enable; - } - dev_info(codec->dev, "revision %c\n", - (ret & WM8523_CHIP_REV_MASK) + 'A'); - - ret = wm8523_reset(codec); - if (ret < 0) { - dev_err(codec->dev, "Failed to issue reset\n"); - goto err_enable; - } - /* Change some default settings - latch VU and enable ZC */ snd_soc_update_bits(codec, WM8523_DAC_GAINR, WM8523_DACR_VU, WM8523_DACR_VU); @@ -448,16 +411,7 @@ static int wm8523_probe(struct snd_soc_codec *codec) wm8523_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - /* Bias level configuration will have done an extra enable */ - regulator_bulk_disable(ARRAY_SIZE(wm8523->supplies), wm8523->supplies); - return 0; - -err_enable: - regulator_bulk_disable(ARRAY_SIZE(wm8523->supplies), wm8523->supplies); -err_get: - - return ret; } static int wm8523_remove(struct snd_soc_codec *codec) @@ -503,6 +457,7 @@ static __devinit int wm8523_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { struct wm8523_priv *wm8523; + unsigned int val; int ret, i; wm8523 = devm_kzalloc(&i2c->dev, sizeof(struct wm8523_priv), @@ -527,6 +482,40 @@ static __devinit int wm8523_i2c_probe(struct i2c_client *i2c, return ret; } + ret = regulator_bulk_enable(ARRAY_SIZE(wm8523->supplies), + wm8523->supplies); + if (ret != 0) { + dev_err(&i2c->dev, "Failed to enable supplies: %d\n", ret); + return ret; + } + + ret = regmap_read(wm8523->regmap, WM8523_DEVICE_ID, &val); + if (ret < 0) { + dev_err(&i2c->dev, "Failed to read ID register\n"); + goto err_enable; + } + if (val != 0x8523) { + dev_err(&i2c->dev, "Device is not a WM8523, ID is %x\n", ret); + ret = -EINVAL; + goto err_enable; + } + + ret = regmap_read(wm8523->regmap, WM8523_REVISION, &val); + if (ret < 0) { + dev_err(&i2c->dev, "Failed to read revision register\n"); + goto err_enable; + } + dev_info(&i2c->dev, "revision %c\n", + (val & WM8523_CHIP_REV_MASK) + 'A'); + + ret = regmap_write(wm8523->regmap, WM8523_DEVICE_ID, 0x8523); + if (ret != 0) { + dev_err(&i2c->dev, "Failed to reset device: %d\n", ret); + goto err_enable; + } + + regulator_bulk_disable(ARRAY_SIZE(wm8523->supplies), wm8523->supplies); + i2c_set_clientdata(i2c, wm8523); ret = snd_soc_register_codec(&i2c->dev, @@ -534,6 +523,9 @@ static __devinit int wm8523_i2c_probe(struct i2c_client *i2c, return ret; +err_enable: + regulator_bulk_disable(ARRAY_SIZE(wm8523->supplies), wm8523->supplies); + return ret; } static __devexit int wm8523_i2c_remove(struct i2c_client *client) -- cgit v1.2.3 From aff041af948f5cdf51e2115f267957a89f28ac0f Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 10 Sep 2012 10:59:51 +0800 Subject: ASoC: sta32x: Move regulator acquisition to I2C probe This is better style as it ensures we don't try to do the ASoC probe without required resources. Also convert to devm_ while we're at it, saving a bit of code, and fix a leak of enable on error. Signed-off-by: Mark Brown Acked-by: Johannes Stezenbach --- sound/soc/codecs/sta32x.c | 32 +++++++++++++++----------------- 1 file changed, 15 insertions(+), 17 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/sta32x.c b/sound/soc/codecs/sta32x.c index 51b7313a4c14..039597e66987 100644 --- a/sound/soc/codecs/sta32x.c +++ b/sound/soc/codecs/sta32x.c @@ -825,22 +825,11 @@ static int sta32x_probe(struct snd_soc_codec *codec) sta32x->codec = codec; sta32x->pdata = dev_get_platdata(codec->dev); - /* regulators */ - for (i = 0; i < ARRAY_SIZE(sta32x->supplies); i++) - sta32x->supplies[i].supply = sta32x_supply_names[i]; - - ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(sta32x->supplies), - sta32x->supplies); - if (ret != 0) { - dev_err(codec->dev, "Failed to request supplies: %d\n", ret); - goto err; - } - ret = regulator_bulk_enable(ARRAY_SIZE(sta32x->supplies), sta32x->supplies); if (ret != 0) { dev_err(codec->dev, "Failed to enable supplies: %d\n", ret); - goto err_get; + return ret; } /* Tell ASoC what kind of I/O to use to read the registers. ASoC will @@ -849,7 +838,7 @@ static int sta32x_probe(struct snd_soc_codec *codec) ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_I2C); if (ret < 0) { dev_err(codec->dev, "failed to set cache I/O (ret=%i)\n", ret); - return ret; + goto err; } /* Chip documentation explicitly requires that the reset values @@ -915,9 +904,8 @@ static int sta32x_probe(struct snd_soc_codec *codec) return 0; -err_get: - regulator_bulk_free(ARRAY_SIZE(sta32x->supplies), sta32x->supplies); err: + regulator_bulk_disable(ARRAY_SIZE(sta32x->supplies), sta32x->supplies); return ret; } @@ -928,7 +916,6 @@ static int sta32x_remove(struct snd_soc_codec *codec) sta32x_watchdog_stop(sta32x); sta32x_set_bias_level(codec, SND_SOC_BIAS_OFF); regulator_bulk_disable(ARRAY_SIZE(sta32x->supplies), sta32x->supplies); - regulator_bulk_free(ARRAY_SIZE(sta32x->supplies), sta32x->supplies); return 0; } @@ -966,13 +953,24 @@ static __devinit int sta32x_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { struct sta32x_priv *sta32x; - int ret; + int ret, i; sta32x = devm_kzalloc(&i2c->dev, sizeof(struct sta32x_priv), GFP_KERNEL); if (!sta32x) return -ENOMEM; + /* regulators */ + for (i = 0; i < ARRAY_SIZE(sta32x->supplies); i++) + sta32x->supplies[i].supply = sta32x_supply_names[i]; + + ret = devm_regulator_bulk_get(&i2c->dev, ARRAY_SIZE(sta32x->supplies), + sta32x->supplies); + if (ret != 0) { + dev_err(&i2c->dev, "Failed to request supplies: %d\n", ret); + return ret; + } + i2c_set_clientdata(i2c, sta32x); ret = snd_soc_register_codec(&i2c->dev, &sta32x_codec, &sta32x_dai, 1); -- cgit v1.2.3 From 29fdf4fbbe0891349d8444bde4c09f9cfaf744b6 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 10 Sep 2012 10:59:56 +0800 Subject: ASoC: sta32x: Convert to regmap Long term all drivers should be using regmap directly. This is more idiomatic and moves us towards the removal of the ASoC level cache code. The initialiasation of reserved register bits in probe() is slightly odd as the defaults being written don't appear to match the silicon defaults but the new code should have the same effect as the old code. The watchdog code will now unconditionally do a mute and unmute when resyncing but since we only sync when we are very sure there is something to sync this should have no impact. Signed-off-by: Mark Brown Acked-by: Johannes Stezenbach --- sound/soc/codecs/sta32x.c | 107 ++++++++++++++++++++++++++++++++++------------ 1 file changed, 80 insertions(+), 27 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/sta32x.c b/sound/soc/codecs/sta32x.c index 039597e66987..0935bfe62471 100644 --- a/sound/soc/codecs/sta32x.c +++ b/sound/soc/codecs/sta32x.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -55,12 +56,50 @@ SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S32_BE) /* Power-up register defaults */ -static const u8 sta32x_regs[STA32X_REGISTER_COUNT] = { - 0x63, 0x80, 0xc2, 0x40, 0xc2, 0x5c, 0x10, 0xff, 0x60, 0x60, - 0x60, 0x80, 0x00, 0x00, 0x00, 0x40, 0x80, 0x77, 0x6a, 0x69, - 0x6a, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, - 0xc0, 0xf3, 0x33, 0x00, 0x0c, +static const struct reg_default sta32x_regs[] = { + { 0x0, 0x63 }, + { 0x1, 0x80 }, + { 0x2, 0xc2 }, + { 0x3, 0x40 }, + { 0x4, 0xc2 }, + { 0x5, 0x5c }, + { 0x6, 0x10 }, + { 0x7, 0xff }, + { 0x8, 0x60 }, + { 0x9, 0x60 }, + { 0xa, 0x60 }, + { 0xb, 0x80 }, + { 0xc, 0x00 }, + { 0xd, 0x00 }, + { 0xe, 0x00 }, + { 0xf, 0x40 }, + { 0x10, 0x80 }, + { 0x11, 0x77 }, + { 0x12, 0x6a }, + { 0x13, 0x69 }, + { 0x14, 0x6a }, + { 0x15, 0x69 }, + { 0x16, 0x00 }, + { 0x17, 0x00 }, + { 0x18, 0x00 }, + { 0x19, 0x00 }, + { 0x1a, 0x00 }, + { 0x1b, 0x00 }, + { 0x1c, 0x00 }, + { 0x1d, 0x00 }, + { 0x1e, 0x00 }, + { 0x1f, 0x00 }, + { 0x20, 0x00 }, + { 0x21, 0x00 }, + { 0x22, 0x00 }, + { 0x23, 0x00 }, + { 0x24, 0x00 }, + { 0x25, 0x00 }, + { 0x26, 0x00 }, + { 0x27, 0x2d }, + { 0x28, 0xc0 }, + { 0x2b, 0x00 }, + { 0x2c, 0x0c }, }; /* regulator power supply names */ @@ -72,6 +111,7 @@ static const char *sta32x_supply_names[] = { /* codec private data */ struct sta32x_priv { + struct regmap *regmap; struct regulator_bulk_data supplies[ARRAY_SIZE(sta32x_supply_names)]; struct snd_soc_codec *codec; struct sta32x_platform_data *pdata; @@ -291,17 +331,15 @@ static int sta32x_sync_coef_shadow(struct snd_soc_codec *codec) static int sta32x_cache_sync(struct snd_soc_codec *codec) { + struct sta32x_priv *sta32x = codec->control_data; unsigned int mute; int rc; - if (!codec->cache_sync) - return 0; - /* mute during register sync */ mute = snd_soc_read(codec, STA32X_MMUTE); snd_soc_write(codec, STA32X_MMUTE, mute | STA32X_MMUTE_MMUTE); sta32x_sync_coef_shadow(codec); - rc = snd_soc_cache_sync(codec); + rc = regcache_sync(sta32x->regmap); snd_soc_write(codec, STA32X_MMUTE, mute); return rc; } @@ -316,11 +354,11 @@ static void sta32x_watchdog(struct work_struct *work) /* check if sta32x has reset itself */ confa_cached = snd_soc_read(codec, STA32X_CONFA); - codec->cache_bypass = 1; + regcache_cache_bypass(sta32x->regmap, true); confa = snd_soc_read(codec, STA32X_CONFA); - codec->cache_bypass = 0; + regcache_cache_bypass(sta32x->regmap, false); if (confa != confa_cached) { - codec->cache_sync = 1; + regcache_mark_dirty(sta32x->regmap); sta32x_cache_sync(codec); } @@ -835,7 +873,8 @@ static int sta32x_probe(struct snd_soc_codec *codec) /* Tell ASoC what kind of I/O to use to read the registers. ASoC will * then do the I2C transactions itself. */ - ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_I2C); + codec->control_data = sta32x->regmap; + ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP); if (ret < 0) { dev_err(codec->dev, "failed to set cache I/O (ret=%i)\n", ret); goto err; @@ -847,13 +886,15 @@ static int sta32x_probe(struct snd_soc_codec *codec) * so the write to the these registers are suppressed by the cache * restore code when it skips writes of default registers. */ - snd_soc_cache_write(codec, STA32X_CONFC, 0xc2); - snd_soc_cache_write(codec, STA32X_CONFE, 0xc2); - snd_soc_cache_write(codec, STA32X_CONFF, 0x5c); - snd_soc_cache_write(codec, STA32X_MMUTE, 0x10); - snd_soc_cache_write(codec, STA32X_AUTO1, 0x60); - snd_soc_cache_write(codec, STA32X_AUTO3, 0x00); - snd_soc_cache_write(codec, STA32X_C3CFG, 0x40); + regcache_cache_only(sta32x->regmap, true); + snd_soc_write(codec, STA32X_CONFC, 0xc2); + snd_soc_write(codec, STA32X_CONFE, 0xc2); + snd_soc_write(codec, STA32X_CONFF, 0x5c); + snd_soc_write(codec, STA32X_MMUTE, 0x10); + snd_soc_write(codec, STA32X_AUTO1, 0x60); + snd_soc_write(codec, STA32X_AUTO3, 0x00); + snd_soc_write(codec, STA32X_C3CFG, 0x40); + regcache_cache_only(sta32x->regmap, false); /* set thermal warning adjustment and recovery */ if (!(sta32x->pdata->thermal_conf & STA32X_THERMAL_ADJUSTMENT_ENABLE)) @@ -920,8 +961,7 @@ static int sta32x_remove(struct snd_soc_codec *codec) return 0; } -static int sta32x_reg_is_volatile(struct snd_soc_codec *codec, - unsigned int reg) +static bool sta32x_reg_is_volatile(struct device *dev, unsigned int reg) { switch (reg) { case STA32X_CONFA ... STA32X_L2ATRT: @@ -936,10 +976,6 @@ static const struct snd_soc_codec_driver sta32x_codec = { .remove = sta32x_remove, .suspend = sta32x_suspend, .resume = sta32x_resume, - .reg_cache_size = STA32X_REGISTER_COUNT, - .reg_word_size = sizeof(u8), - .reg_cache_default = sta32x_regs, - .volatile_register = sta32x_reg_is_volatile, .set_bias_level = sta32x_set_bias_level, .controls = sta32x_snd_controls, .num_controls = ARRAY_SIZE(sta32x_snd_controls), @@ -949,6 +985,16 @@ static const struct snd_soc_codec_driver sta32x_codec = { .num_dapm_routes = ARRAY_SIZE(sta32x_dapm_routes), }; +static const struct regmap_config sta32x_regmap = { + .reg_bits = 8, + .val_bits = 8, + .max_register = STA32X_FDRC2, + .reg_defaults = sta32x_regs, + .num_reg_defaults = ARRAY_SIZE(sta32x_regs), + .cache_type = REGCACHE_RBTREE, + .volatile_reg = sta32x_reg_is_volatile, +}; + static __devinit int sta32x_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { @@ -971,6 +1017,13 @@ static __devinit int sta32x_i2c_probe(struct i2c_client *i2c, return ret; } + sta32x->regmap = devm_regmap_init_i2c(i2c, &sta32x_regmap); + if (IS_ERR(sta32x->regmap)) { + ret = PTR_ERR(sta32x->regmap); + dev_err(&i2c->dev, "Failed to init regmap: %d\n", ret); + return ret; + } + i2c_set_clientdata(i2c, sta32x); ret = snd_soc_register_codec(&i2c->dev, &sta32x_codec, &sta32x_dai, 1); -- cgit v1.2.3 From c35e005f3115cd27d85625805645b90ba961f16f Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 10 Sep 2012 02:13:52 -0700 Subject: ASoC: fsi: fixup pm_runtime_disable() timing on fsi_probe() pm_runtime_disable() error handling timing on fsi_probe() was wrong. This patch fixes it up. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/fsi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound/soc') diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c index 0540408a9fa9..8534989836aa 100644 --- a/sound/soc/sh/fsi.c +++ b/sound/soc/sh/fsi.c @@ -1730,12 +1730,12 @@ exit_snd_soc: exit_free_irq: free_irq(irq, master); exit_fsib: + pm_runtime_disable(&pdev->dev); fsi_stream_remove(&master->fsib); exit_fsia: fsi_stream_remove(&master->fsia); exit_iounmap: iounmap(master->base); - pm_runtime_disable(&pdev->dev); exit_kfree: kfree(master); master = NULL; -- cgit v1.2.3 From dbd4e51cd164e7d94b00c0c0dd3ac5517364a8fb Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 10 Sep 2012 02:14:10 -0700 Subject: ASoC: fsi: tidyup: remove un-necessary operation from fsi_probe() struct fsi_master *master became member of struct fsi_priv from 71f6e0645be42f93c0f90dfcc93b9d2d277c2ee6 (ASoC: sh_fsi: avoid using global variable) So, master = NULL is not necessary on fsi_probe() now. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/fsi.c | 1 - 1 file changed, 1 deletion(-) (limited to 'sound/soc') diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c index 8534989836aa..a5ee2faa1073 100644 --- a/sound/soc/sh/fsi.c +++ b/sound/soc/sh/fsi.c @@ -1738,7 +1738,6 @@ exit_iounmap: iounmap(master->base); exit_kfree: kfree(master); - master = NULL; exit: return ret; } -- cgit v1.2.3 From 6ac4262f367fd0d9b0219dfd014ffcca4a6cfa6a Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 10 Sep 2012 02:14:31 -0700 Subject: ASoC: fsi: convert to devm_xxx() Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/fsi.c | 25 ++++++++----------------- 1 file changed, 8 insertions(+), 17 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c index a5ee2faa1073..5328ae5539f1 100644 --- a/sound/soc/sh/fsi.c +++ b/sound/soc/sh/fsi.c @@ -1655,22 +1655,20 @@ static int fsi_probe(struct platform_device *pdev) irq = platform_get_irq(pdev, 0); if (!res || (int)irq <= 0) { dev_err(&pdev->dev, "Not enough FSI platform resources.\n"); - ret = -ENODEV; - goto exit; + return -ENODEV; } - master = kzalloc(sizeof(*master), GFP_KERNEL); + master = devm_kzalloc(&pdev->dev, sizeof(*master), GFP_KERNEL); if (!master) { dev_err(&pdev->dev, "Could not allocate master\n"); - ret = -ENOMEM; - goto exit; + return -ENOMEM; } - master->base = ioremap_nocache(res->start, resource_size(res)); + master->base = devm_ioremap_nocache(&pdev->dev, + res->start, resource_size(res)); if (!master->base) { - ret = -ENXIO; dev_err(&pdev->dev, "Unable to ioremap FSI registers.\n"); - goto exit_kfree; + return -ENXIO; } /* master setting */ @@ -1686,7 +1684,7 @@ static int fsi_probe(struct platform_device *pdev) ret = fsi_stream_probe(&master->fsia, &pdev->dev); if (ret < 0) { dev_err(&pdev->dev, "FSIA stream probe failed\n"); - goto exit_iounmap; + return ret; } /* FSI B setting */ @@ -1734,11 +1732,7 @@ exit_fsib: fsi_stream_remove(&master->fsib); exit_fsia: fsi_stream_remove(&master->fsia); -exit_iounmap: - iounmap(master->base); -exit_kfree: - kfree(master); -exit: + return ret; } @@ -1757,9 +1751,6 @@ static int fsi_remove(struct platform_device *pdev) fsi_stream_remove(&master->fsia); fsi_stream_remove(&master->fsib); - iounmap(master->base); - kfree(master); - return 0; } -- cgit v1.2.3 From d9780550a354058bc47db6ac48d3b77f186882c6 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 10 Sep 2012 17:52:59 +0800 Subject: ASoC: wm8741: Move regulator acquisition to I2C/SPI probe() Better style as we acquire resources before trying the ASoC card probe. Signed-off-by: Mark Brown --- sound/soc/codecs/wm8741.c | 37 ++++++++++++++++++++++--------------- 1 file changed, 22 insertions(+), 15 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/wm8741.c b/sound/soc/codecs/wm8741.c index 35f3d23200e0..742744b4bba7 100644 --- a/sound/soc/codecs/wm8741.c +++ b/sound/soc/codecs/wm8741.c @@ -403,17 +403,6 @@ static int wm8741_probe(struct snd_soc_codec *codec) { struct wm8741_priv *wm8741 = snd_soc_codec_get_drvdata(codec); int ret = 0; - int i; - - for (i = 0; i < ARRAY_SIZE(wm8741->supplies); i++) - wm8741->supplies[i].supply = wm8741_supply_names[i]; - - ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8741->supplies), - wm8741->supplies); - if (ret != 0) { - dev_err(codec->dev, "Failed to request supplies: %d\n", ret); - goto err; - } ret = regulator_bulk_enable(ARRAY_SIZE(wm8741->supplies), wm8741->supplies); @@ -450,7 +439,6 @@ static int wm8741_probe(struct snd_soc_codec *codec) err_enable: regulator_bulk_disable(ARRAY_SIZE(wm8741->supplies), wm8741->supplies); err_get: - regulator_bulk_free(ARRAY_SIZE(wm8741->supplies), wm8741->supplies); err: return ret; } @@ -460,7 +448,6 @@ static int wm8741_remove(struct snd_soc_codec *codec) struct wm8741_priv *wm8741 = snd_soc_codec_get_drvdata(codec); regulator_bulk_disable(ARRAY_SIZE(wm8741->supplies), wm8741->supplies); - regulator_bulk_free(ARRAY_SIZE(wm8741->supplies), wm8741->supplies); return 0; } @@ -492,13 +479,23 @@ static int wm8741_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { struct wm8741_priv *wm8741; - int ret; + int ret, i; wm8741 = devm_kzalloc(&i2c->dev, sizeof(struct wm8741_priv), GFP_KERNEL); if (wm8741 == NULL) return -ENOMEM; + for (i = 0; i < ARRAY_SIZE(wm8741->supplies); i++) + wm8741->supplies[i].supply = wm8741_supply_names[i]; + + ret = devm_regulator_bulk_get(&i2c->dev, ARRAY_SIZE(wm8741->supplies), + wm8741->supplies); + if (ret != 0) { + dev_err(codec->dev, "Failed to request supplies: %d\n", ret); + goto err; + } + i2c_set_clientdata(i2c, wm8741); wm8741->control_type = SND_SOC_I2C; @@ -536,13 +533,23 @@ static struct i2c_driver wm8741_i2c_driver = { static int __devinit wm8741_spi_probe(struct spi_device *spi) { struct wm8741_priv *wm8741; - int ret; + int ret, i; wm8741 = devm_kzalloc(&spi->dev, sizeof(struct wm8741_priv), GFP_KERNEL); if (wm8741 == NULL) return -ENOMEM; + for (i = 0; i < ARRAY_SIZE(wm8741->supplies); i++) + wm8741->supplies[i].supply = wm8741_supply_names[i]; + + ret = devm_regulator_bulk_get(&i2c->dev, ARRAY_SIZE(wm8741->supplies), + wm8741->supplies); + if (ret != 0) { + dev_err(&spi->dev, "Failed to request supplies: %d\n", ret); + goto err; + } + wm8741->control_type = SND_SOC_SPI; spi_set_drvdata(spi, wm8741); -- cgit v1.2.3 From fe98c0cf40883e7d12456e0abc269e4fa31bed69 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 10 Sep 2012 18:00:21 +0800 Subject: ASoC: wm8741: Convert to direct regmap API usage Signed-off-by: Mark Brown --- sound/soc/codecs/wm8741.c | 86 ++++++++++++++++++++++++++++++++++------------- 1 file changed, 62 insertions(+), 24 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/wm8741.c b/sound/soc/codecs/wm8741.c index 742744b4bba7..4281a0802138 100644 --- a/sound/soc/codecs/wm8741.c +++ b/sound/soc/codecs/wm8741.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -40,26 +41,43 @@ static const char *wm8741_supply_names[WM8741_NUM_SUPPLIES] = { /* codec private data */ struct wm8741_priv { - enum snd_soc_control_type control_type; + struct regmap *regmap; struct regulator_bulk_data supplies[WM8741_NUM_SUPPLIES]; unsigned int sysclk; struct snd_pcm_hw_constraint_list *sysclk_constraints; }; -static const u16 wm8741_reg_defaults[WM8741_REGISTER_COUNT] = { - 0x0000, /* R0 - DACLLSB Attenuation */ - 0x0000, /* R1 - DACLMSB Attenuation */ - 0x0000, /* R2 - DACRLSB Attenuation */ - 0x0000, /* R3 - DACRMSB Attenuation */ - 0x0000, /* R4 - Volume Control */ - 0x000A, /* R5 - Format Control */ - 0x0000, /* R6 - Filter Control */ - 0x0000, /* R7 - Mode Control 1 */ - 0x0002, /* R8 - Mode Control 2 */ - 0x0000, /* R9 - Reset */ - 0x0002, /* R32 - ADDITONAL_CONTROL_1 */ +static const struct reg_default wm8741_reg_defaults[] = { + { 0, 0x0000 }, /* R0 - DACLLSB Attenuation */ + { 1, 0x0000 }, /* R1 - DACLMSB Attenuation */ + { 2, 0x0000 }, /* R2 - DACRLSB Attenuation */ + { 3, 0x0000 }, /* R3 - DACRMSB Attenuation */ + { 4, 0x0000 }, /* R4 - Volume Control */ + { 5, 0x000A }, /* R5 - Format Control */ + { 6, 0x0000 }, /* R6 - Filter Control */ + { 7, 0x0000 }, /* R7 - Mode Control 1 */ + { 8, 0x0002 }, /* R8 - Mode Control 2 */ + { 32, 0x0002 }, /* R32 - ADDITONAL_CONTROL_1 */ }; +static bool wm8741_readable(struct device *dev, unsigned int reg) +{ + switch (reg) { + case WM8741_DACLLSB_ATTENUATION: + case WM8741_DACLMSB_ATTENUATION: + case WM8741_DACRLSB_ATTENUATION: + case WM8741_DACRMSB_ATTENUATION: + case WM8741_VOLUME_CONTROL: + case WM8741_FORMAT_CONTROL: + case WM8741_FILTER_CONTROL: + case WM8741_MODE_CONTROL_1: + case WM8741_MODE_CONTROL_2: + case WM8741_ADDITIONAL_CONTROL_1: + return true; + default: + return false; + } +} static int wm8741_reset(struct snd_soc_codec *codec) { @@ -411,7 +429,7 @@ static int wm8741_probe(struct snd_soc_codec *codec) goto err_get; } - ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8741->control_type); + ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); if (ret != 0) { dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); goto err_enable; @@ -439,7 +457,6 @@ static int wm8741_probe(struct snd_soc_codec *codec) err_enable: regulator_bulk_disable(ARRAY_SIZE(wm8741->supplies), wm8741->supplies); err_get: -err: return ret; } @@ -456,9 +473,6 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8741 = { .probe = wm8741_probe, .remove = wm8741_remove, .resume = wm8741_resume, - .reg_cache_size = ARRAY_SIZE(wm8741_reg_defaults), - .reg_word_size = sizeof(u16), - .reg_cache_default = wm8741_reg_defaults, .controls = wm8741_snd_controls, .num_controls = ARRAY_SIZE(wm8741_snd_controls), @@ -474,6 +488,18 @@ static const struct of_device_id wm8741_of_match[] = { }; MODULE_DEVICE_TABLE(of, wm8741_of_match); +static const struct regmap_config wm8741_regmap = { + .reg_bits = 7, + .val_bits = 9, + .max_register = WM8741_MAX_REGISTER, + + .reg_defaults = wm8741_reg_defaults, + .num_reg_defaults = ARRAY_SIZE(wm8741_reg_defaults), + .cache_type = REGCACHE_RBTREE, + + .readable_reg = wm8741_readable, +}; + #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) static int wm8741_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) @@ -492,12 +518,18 @@ static int wm8741_i2c_probe(struct i2c_client *i2c, ret = devm_regulator_bulk_get(&i2c->dev, ARRAY_SIZE(wm8741->supplies), wm8741->supplies); if (ret != 0) { - dev_err(codec->dev, "Failed to request supplies: %d\n", ret); - goto err; + dev_err(&i2c->dev, "Failed to request supplies: %d\n", ret); + return ret; + } + + wm8741->regmap = regmap_init_i2c(i2c, &wm8741_regmap); + if (IS_ERR(wm8741->regmap)) { + ret = PTR_ERR(wm8741->regmap); + dev_err(&i2c->dev, "Failed to init regmap: %d\n", ret); + return ret; } i2c_set_clientdata(i2c, wm8741); - wm8741->control_type = SND_SOC_I2C; ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_wm8741, &wm8741_dai, 1); @@ -543,14 +575,20 @@ static int __devinit wm8741_spi_probe(struct spi_device *spi) for (i = 0; i < ARRAY_SIZE(wm8741->supplies); i++) wm8741->supplies[i].supply = wm8741_supply_names[i]; - ret = devm_regulator_bulk_get(&i2c->dev, ARRAY_SIZE(wm8741->supplies), + ret = devm_regulator_bulk_get(&spi->dev, ARRAY_SIZE(wm8741->supplies), wm8741->supplies); if (ret != 0) { dev_err(&spi->dev, "Failed to request supplies: %d\n", ret); - goto err; + return ret; + } + + wm8741->regmap = regmap_init_spi(spi, &wm8741_regmap); + if (IS_ERR(wm8741->regmap)) { + ret = PTR_ERR(wm8741->regmap); + dev_err(&spi->dev, "Failed to init regmap: %d\n", ret); + return ret; } - wm8741->control_type = SND_SOC_SPI; spi_set_drvdata(spi, wm8741); ret = snd_soc_register_codec(&spi->dev, -- cgit v1.2.3 From a044b75779201b1eb293ffcb887404357b21421e Mon Sep 17 00:00:00 2001 From: Bo Shen Date: Mon, 10 Sep 2012 17:50:33 +0800 Subject: ASoC: wm8904: remove redundant code The core_intercon is added two times, remove the redundant one Signed-off-by: Bo Shen Signed-off-by: Mark Brown --- sound/soc/codecs/wm8904.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/wm8904.c b/sound/soc/codecs/wm8904.c index 0013afe48e66..2b9766d55384 100644 --- a/sound/soc/codecs/wm8904.c +++ b/sound/soc/codecs/wm8904.c @@ -1185,8 +1185,6 @@ static int wm8904_add_widgets(struct snd_soc_codec *codec) snd_soc_dapm_new_controls(dapm, wm8904_dapm_widgets, ARRAY_SIZE(wm8904_dapm_widgets)); - snd_soc_dapm_add_routes(dapm, core_intercon, - ARRAY_SIZE(core_intercon)); snd_soc_dapm_add_routes(dapm, adc_intercon, ARRAY_SIZE(adc_intercon)); snd_soc_dapm_add_routes(dapm, dac_intercon, -- cgit v1.2.3 From 0ebe36c6c4fe8fcfeee3192f37f2ff8318a029bd Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 10 Sep 2012 19:23:57 +0800 Subject: ASoC: wm8960: Convert to direct regmap API usage Signed-off-by: Mark Brown --- sound/soc/codecs/wm8960.c | 107 ++++++++++++++++++++++++++++++++++++---------- 1 file changed, 84 insertions(+), 23 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/wm8960.c b/sound/soc/codecs/wm8960.c index 804f4116912f..7cb0d07ca8a6 100644 --- a/sound/soc/codecs/wm8960.c +++ b/sound/soc/codecs/wm8960.c @@ -52,25 +52,72 @@ * We can't read the WM8960 register space when we are * using 2 wire for device control, so we cache them instead. */ -static const u16 wm8960_reg[WM8960_CACHEREGNUM] = { - 0x0097, 0x0097, 0x0000, 0x0000, - 0x0000, 0x0008, 0x0000, 0x000a, - 0x01c0, 0x0000, 0x00ff, 0x00ff, - 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x007b, 0x0100, 0x0032, - 0x0000, 0x00c3, 0x00c3, 0x01c0, - 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, - 0x0100, 0x0100, 0x0050, 0x0050, - 0x0050, 0x0050, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0040, 0x0000, - 0x0000, 0x0050, 0x0050, 0x0000, - 0x0002, 0x0037, 0x004d, 0x0080, - 0x0008, 0x0031, 0x0026, 0x00e9, +static const struct reg_default wm8960_reg_defaults[] = { + { 0x0, 0x0097 }, + { 0x1, 0x0097 }, + { 0x2, 0x0000 }, + { 0x3, 0x0000 }, + { 0x4, 0x0000 }, + { 0x5, 0x0008 }, + { 0x6, 0x0000 }, + { 0x7, 0x000a }, + { 0x8, 0x01c0 }, + { 0x9, 0x0000 }, + { 0xa, 0x00ff }, + { 0xb, 0x00ff }, + + { 0x10, 0x0000 }, + { 0x11, 0x007b }, + { 0x12, 0x0100 }, + { 0x13, 0x0032 }, + { 0x14, 0x0000 }, + { 0x15, 0x00c3 }, + { 0x16, 0x00c3 }, + { 0x17, 0x01c0 }, + { 0x18, 0x0000 }, + { 0x19, 0x0000 }, + { 0x1a, 0x0000 }, + { 0x1b, 0x0000 }, + { 0x1c, 0x0000 }, + { 0x1d, 0x0000 }, + + { 0x20, 0x0100 }, + { 0x21, 0x0100 }, + { 0x22, 0x0050 }, + + { 0x25, 0x0050 }, + { 0x26, 0x0000 }, + { 0x27, 0x0000 }, + { 0x28, 0x0000 }, + { 0x29, 0x0000 }, + { 0x2a, 0x0040 }, + { 0x2b, 0x0000 }, + { 0x2c, 0x0000 }, + { 0x2d, 0x0050 }, + { 0x2e, 0x0050 }, + { 0x2f, 0x0000 }, + { 0x30, 0x0002 }, + { 0x31, 0x0037 }, + + { 0x33, 0x0080 }, + { 0x34, 0x0008 }, + { 0x35, 0x0031 }, + { 0x36, 0x0026 }, + { 0x37, 0x00e9 }, }; +static bool wm8960_volatile(struct device *dev, unsigned int reg) +{ + switch (reg) { + case WM8960_RESET: + return true; + default: + return false; + } +} + struct wm8960_priv { - enum snd_soc_control_type control_type; + struct regmap *regmap; int (*set_bias_level)(struct snd_soc_codec *, enum snd_soc_bias_level level); struct snd_soc_dapm_widget *lout1; @@ -555,6 +602,8 @@ static int wm8960_mute(struct snd_soc_dai *dai, int mute) static int wm8960_set_bias_level_out3(struct snd_soc_codec *codec, enum snd_soc_bias_level level) { + struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec); + switch (level) { case SND_SOC_BIAS_ON: break; @@ -566,7 +615,7 @@ static int wm8960_set_bias_level_out3(struct snd_soc_codec *codec, case SND_SOC_BIAS_STANDBY: if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { - snd_soc_cache_sync(codec); + regcache_sync(wm8960->regmap); /* Enable anti-pop features */ snd_soc_write(codec, WM8960_APOP1, @@ -667,7 +716,7 @@ static int wm8960_set_bias_level_capless(struct snd_soc_codec *codec, break; case SND_SOC_BIAS_OFF: - snd_soc_cache_sync(codec); + regcache_sync(wm8960->regmap); break; default: break; @@ -915,7 +964,7 @@ static int wm8960_probe(struct snd_soc_codec *codec) wm8960->set_bias_level = wm8960_set_bias_level_capless; } - ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8960->control_type); + ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); if (ret < 0) { dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); return ret; @@ -963,9 +1012,18 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8960 = { .suspend = wm8960_suspend, .resume = wm8960_resume, .set_bias_level = wm8960_set_bias_level, - .reg_cache_size = ARRAY_SIZE(wm8960_reg), - .reg_word_size = sizeof(u16), - .reg_cache_default = wm8960_reg, +}; + +static const struct regmap_config wm8960_regmap = { + .reg_bits = 7, + .val_bits = 9, + .max_register = WM8960_PLL4, + + .reg_defaults = wm8960_reg_defaults, + .num_reg_defaults = ARRAY_SIZE(wm8960_reg_defaults), + .cache_type = REGCACHE_RBTREE, + + .volatile_reg = wm8960_volatile, }; static __devinit int wm8960_i2c_probe(struct i2c_client *i2c, @@ -979,8 +1037,11 @@ static __devinit int wm8960_i2c_probe(struct i2c_client *i2c, if (wm8960 == NULL) return -ENOMEM; + wm8960->regmap = regmap_init_i2c(i2c, &wm8960_regmap); + if (IS_ERR(wm8960->regmap)) + return PTR_ERR(wm8960->regmap); + i2c_set_clientdata(i2c, wm8960); - wm8960->control_type = SND_SOC_I2C; ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_wm8960, &wm8960_dai, 1); -- cgit v1.2.3 From 19ace0e97a605042c481c2ea3f7aeb59c0eb54ed Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 10 Sep 2012 12:48:11 +0800 Subject: ASoC: cs4270: Conver to data based control init Signed-off-by: Mark Brown Acked-by: Timur Tabi --- sound/soc/codecs/cs4270.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/cs4270.c b/sound/soc/codecs/cs4270.c index 44a176f74170..c6e5a73a9f17 100644 --- a/sound/soc/codecs/cs4270.c +++ b/sound/soc/codecs/cs4270.c @@ -521,14 +521,6 @@ static int cs4270_probe(struct snd_soc_codec *codec) return ret; } - /* Add the non-DAPM controls */ - ret = snd_soc_add_codec_controls(codec, cs4270_snd_controls, - ARRAY_SIZE(cs4270_snd_controls)); - if (ret < 0) { - dev_err(codec->dev, "failed to add controls\n"); - return ret; - } - /* get the power supply regulators */ for (i = 0; i < ARRAY_SIZE(supply_names); i++) cs4270->supplies[i].supply = supply_names[i]; @@ -634,6 +626,9 @@ static const struct snd_soc_codec_driver soc_codec_device_cs4270 = { .remove = cs4270_remove, .suspend = cs4270_soc_suspend, .resume = cs4270_soc_resume, + + .controls = cs4270_snd_controls, + .num_controls = ARRAY_SIZE(cs4270_snd_controls), .volatile_register = cs4270_reg_is_volatile, .readable_register = cs4270_reg_is_readable, .reg_cache_size = CS4270_LASTREG + 1, -- cgit v1.2.3 From b61d6d40323997d9da3b95ecce2570f0b782a07f Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 10 Sep 2012 12:53:12 +0800 Subject: ASoC: cs4270: Move regulator acquisition to I2C probe() This is better style since it has us obtaining all resources before we try the ASoC probe. This change also fixes a potential issue where we don't enable the regulators before trying to confirm the device ID which could cause a failure during probe in some system configurations. Signed-off-by: Mark Brown Acked-by: Timur Tabi --- sound/soc/codecs/cs4270.c | 46 +++++++++++++++++++--------------------------- 1 file changed, 19 insertions(+), 27 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/cs4270.c b/sound/soc/codecs/cs4270.c index c6e5a73a9f17..64c29b8a379f 100644 --- a/sound/soc/codecs/cs4270.c +++ b/sound/soc/codecs/cs4270.c @@ -487,7 +487,7 @@ static struct snd_soc_dai_driver cs4270_dai = { static int cs4270_probe(struct snd_soc_codec *codec) { struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec); - int i, ret; + int ret; /* Tell ASoC what kind of I/O to use to read the registers. ASoC will * then do the I2C transactions itself. @@ -521,25 +521,8 @@ static int cs4270_probe(struct snd_soc_codec *codec) return ret; } - /* get the power supply regulators */ - for (i = 0; i < ARRAY_SIZE(supply_names); i++) - cs4270->supplies[i].supply = supply_names[i]; - - ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(cs4270->supplies), - cs4270->supplies); - if (ret < 0) - return ret; - ret = regulator_bulk_enable(ARRAY_SIZE(cs4270->supplies), cs4270->supplies); - if (ret < 0) - goto error_free_regulators; - - return 0; - -error_free_regulators: - regulator_bulk_free(ARRAY_SIZE(cs4270->supplies), - cs4270->supplies); return ret; } @@ -555,7 +538,6 @@ static int cs4270_remove(struct snd_soc_codec *codec) struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec); regulator_bulk_disable(ARRAY_SIZE(cs4270->supplies), cs4270->supplies); - regulator_bulk_free(ARRAY_SIZE(cs4270->supplies), cs4270->supplies); return 0; }; @@ -658,7 +640,24 @@ static int cs4270_i2c_probe(struct i2c_client *i2c_client, { struct device_node *np = i2c_client->dev.of_node; struct cs4270_private *cs4270; - int ret; + int ret, i; + + cs4270 = devm_kzalloc(&i2c_client->dev, sizeof(struct cs4270_private), + GFP_KERNEL); + if (!cs4270) { + dev_err(&i2c_client->dev, "could not allocate codec\n"); + return -ENOMEM; + } + + /* get the power supply regulators */ + for (i = 0; i < ARRAY_SIZE(supply_names); i++) + cs4270->supplies[i].supply = supply_names[i]; + + ret = devm_regulator_bulk_get(&i2c_client->dev, + ARRAY_SIZE(cs4270->supplies), + cs4270->supplies); + if (ret < 0) + return ret; /* See if we have a way to bring the codec out of reset */ if (np) { @@ -694,13 +693,6 @@ static int cs4270_i2c_probe(struct i2c_client *i2c_client, i2c_client->addr); dev_info(&i2c_client->dev, "hardware revision %X\n", ret & 0xF); - cs4270 = devm_kzalloc(&i2c_client->dev, sizeof(struct cs4270_private), - GFP_KERNEL); - if (!cs4270) { - dev_err(&i2c_client->dev, "could not allocate codec\n"); - return -ENOMEM; - } - i2c_set_clientdata(i2c_client, cs4270); cs4270->control_type = SND_SOC_I2C; -- cgit v1.2.3 From 1ca6517566b52662f1dea65e3c3d02997282cb01 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 10 Sep 2012 12:57:03 +0800 Subject: ASoC: cs4270: Convert to direct regmap API usage Signed-off-by: Mark Brown Acked-by: Timur Tabi --- sound/soc/codecs/cs4270.c | 55 ++++++++++++++++++++++++++++------------------- 1 file changed, 33 insertions(+), 22 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/cs4270.c b/sound/soc/codecs/cs4270.c index 64c29b8a379f..815b53bc2d27 100644 --- a/sound/soc/codecs/cs4270.c +++ b/sound/soc/codecs/cs4270.c @@ -112,14 +112,15 @@ * This array contains the power-on default values of the registers, with the * exception of the "CHIPID" register (01h). The lower four bits of that * register contain the hardware revision, so it is treated as volatile. - * - * Also note that on the CS4270, the first readable register is 1, but ASoC - * assumes the first register is 0. Therfore, the array must have an entry for - * register 0, but we use cs4270_reg_is_readable() to tell ASoC that it can't - * be read. */ -static const u8 cs4270_default_reg_cache[CS4270_LASTREG + 1] = { - 0x00, 0x00, 0x00, 0x30, 0x00, 0x60, 0x20, 0x00, 0x00 +static const struct reg_default cs4270_reg_defaults[] = { + { 2, 0x00 }, + { 3, 0x30 }, + { 4, 0x00 }, + { 5, 0x60 }, + { 6, 0x20 }, + { 7, 0x00 }, + { 8, 0x00 }, }; static const char *supply_names[] = { @@ -128,7 +129,7 @@ static const char *supply_names[] = { /* Private data for the CS4270 */ struct cs4270_private { - enum snd_soc_control_type control_type; + struct regmap *regmap; unsigned int mclk; /* Input frequency of the MCLK pin */ unsigned int mode; /* The mode (I2S or left-justified) */ unsigned int slave_mode; @@ -193,12 +194,12 @@ static struct cs4270_mode_ratios cs4270_mode_ratios[] = { /* The number of MCLK/LRCK ratios supported by the CS4270 */ #define NUM_MCLK_RATIOS ARRAY_SIZE(cs4270_mode_ratios) -static int cs4270_reg_is_readable(struct snd_soc_codec *codec, unsigned int reg) +static bool cs4270_reg_is_readable(struct device *dev, unsigned int reg) { return (reg >= CS4270_FIRSTREG) && (reg <= CS4270_LASTREG); } -static int cs4270_reg_is_volatile(struct snd_soc_codec *codec, unsigned int reg) +static bool cs4270_reg_is_volatile(struct device *dev, unsigned int reg) { /* Unreadable registers are considered volatile */ if ((reg < CS4270_FIRSTREG) || (reg > CS4270_LASTREG)) @@ -492,7 +493,7 @@ static int cs4270_probe(struct snd_soc_codec *codec) /* Tell ASoC what kind of I/O to use to read the registers. ASoC will * then do the I2C transactions itself. */ - ret = snd_soc_codec_set_cache_io(codec, 8, 8, cs4270->control_type); + ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP); if (ret < 0) { dev_err(codec->dev, "failed to set cache I/O (ret=%i)\n", ret); return ret; @@ -587,7 +588,7 @@ static int cs4270_soc_resume(struct snd_soc_codec *codec) ndelay(500); /* first restore the entire register cache ... */ - snd_soc_cache_sync(codec); + regcache_sync(cs4270->regmap); /* ... then disable the power-down bits */ reg = snd_soc_read(codec, CS4270_PWRCTL); @@ -611,11 +612,6 @@ static const struct snd_soc_codec_driver soc_codec_device_cs4270 = { .controls = cs4270_snd_controls, .num_controls = ARRAY_SIZE(cs4270_snd_controls), - .volatile_register = cs4270_reg_is_volatile, - .readable_register = cs4270_reg_is_readable, - .reg_cache_size = CS4270_LASTREG + 1, - .reg_word_size = sizeof(u8), - .reg_cache_default = cs4270_default_reg_cache, }; /* @@ -627,6 +623,18 @@ static const struct of_device_id cs4270_of_match[] = { }; MODULE_DEVICE_TABLE(of, cs4270_of_match); +static const struct regmap_config cs4270_regmap = { + .reg_bits = 8, + .val_bits = 8, + .max_register = CS4270_LASTREG, + .reg_defaults = cs4270_reg_defaults, + .num_reg_defaults = ARRAY_SIZE(cs4270_reg_defaults), + .cache_type = REGCACHE_RBTREE, + + .readable_reg = cs4270_reg_is_readable, + .volatile_reg = cs4270_reg_is_volatile, +}; + /** * cs4270_i2c_probe - initialize the I2C interface of the CS4270 * @i2c_client: the I2C client object @@ -640,6 +648,7 @@ static int cs4270_i2c_probe(struct i2c_client *i2c_client, { struct device_node *np = i2c_client->dev.of_node; struct cs4270_private *cs4270; + unsigned int val; int ret, i; cs4270 = devm_kzalloc(&i2c_client->dev, sizeof(struct cs4270_private), @@ -674,16 +683,19 @@ static int cs4270_i2c_probe(struct i2c_client *i2c_client, } } - /* Verify that we have a CS4270 */ + cs4270->regmap = devm_regmap_init_i2c(i2c_client, &cs4270_regmap); + if (IS_ERR(cs4270->regmap)) + return PTR_ERR(cs4270->regmap); - ret = i2c_smbus_read_byte_data(i2c_client, CS4270_CHIPID); + /* Verify that we have a CS4270 */ + ret = regmap_read(cs4270->regmap, CS4270_CHIPID, &val); if (ret < 0) { dev_err(&i2c_client->dev, "failed to read i2c at addr %X\n", i2c_client->addr); return ret; } /* The top four bits of the chip ID should be 1100. */ - if ((ret & 0xF0) != 0xC0) { + if ((val & 0xF0) != 0xC0) { dev_err(&i2c_client->dev, "device at addr %X is not a CS4270\n", i2c_client->addr); return -ENODEV; @@ -691,10 +703,9 @@ static int cs4270_i2c_probe(struct i2c_client *i2c_client, dev_info(&i2c_client->dev, "found device at i2c address %X\n", i2c_client->addr); - dev_info(&i2c_client->dev, "hardware revision %X\n", ret & 0xF); + dev_info(&i2c_client->dev, "hardware revision %X\n", val & 0xF); i2c_set_clientdata(i2c_client, cs4270); - cs4270->control_type = SND_SOC_I2C; ret = snd_soc_register_codec(&i2c_client->dev, &soc_codec_device_cs4270, &cs4270_dai, 1); -- cgit v1.2.3 From 1867b2cdd8b3ce377f7c415ee10ce0cf1e581316 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Mon, 10 Sep 2012 15:55:17 +0300 Subject: ASoC: am3517evm: Remove unused cpu_dai from hw_params cpu_dai is not in use in this function and just generates warning at compile time. Signed-off-by: Peter Ujfalusi Signed-off-by: Mark Brown --- sound/soc/omap/am3517evm.c | 1 - 1 file changed, 1 deletion(-) (limited to 'sound/soc') diff --git a/sound/soc/omap/am3517evm.c b/sound/soc/omap/am3517evm.c index a997988af147..77a87012977c 100644 --- a/sound/soc/omap/am3517evm.c +++ b/sound/soc/omap/am3517evm.c @@ -41,7 +41,6 @@ static int am3517evm_hw_params(struct snd_pcm_substream *substream, { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_dai *codec_dai = rtd->codec_dai; - struct snd_soc_dai *cpu_dai = rtd->cpu_dai; int ret; /* Set the codec system clock for DAC and ADC */ -- cgit v1.2.3 From 57d9a477f908cd20c1b4da06fdfe864722487d8b Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Mon, 10 Sep 2012 13:10:08 -0300 Subject: ASoC: Revert "ASoC: mc13783: Provide codec->control_data" Since commit 98d3088e5 (SoC: core: Fix check before defaulting to regmap) , it is not necessary to provide codec->control_data anymore. Signed-off-by: Fabio Estevam Signed-off-by: Mark Brown --- sound/soc/codecs/mc13783.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/mc13783.c b/sound/soc/codecs/mc13783.c index bbfa5535cdd3..d89e343ff108 100644 --- a/sound/soc/codecs/mc13783.c +++ b/sound/soc/codecs/mc13783.c @@ -585,8 +585,6 @@ static int mc13783_probe(struct snd_soc_codec *codec) { struct mc13783_priv *priv = snd_soc_codec_get_drvdata(codec); - codec->control_data = priv->mc13xxx; - mc13xxx_lock(priv->mc13xxx); /* these are the reset values */ -- cgit v1.2.3 From 4ac7903f1d2cc3dce289d15ce6a6929e935983f5 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Mon, 10 Sep 2012 13:10:09 -0300 Subject: ASoC: Revert "ASoC: ab8500: Inform SoC Core that we have our own I/O arrangements" Since commit 98d3088e5 (SoC: core: Fix check before defaulting to regmap) , it is not necessary to provide codec->control_data anymore. Signed-off-by: Fabio Estevam Signed-off-by: Mark Brown --- sound/soc/codecs/ab8500-codec.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/ab8500-codec.c b/sound/soc/codecs/ab8500-codec.c index 3f46bffeb0c3..2c1c2524ef8c 100644 --- a/sound/soc/codecs/ab8500-codec.c +++ b/sound/soc/codecs/ab8500-codec.c @@ -2404,9 +2404,6 @@ static int ab8500_codec_probe(struct snd_soc_codec *codec) dev_dbg(dev, "%s: Enter.\n", __func__); - /* Inform SoC Core that we have our own I/O arrangements. */ - codec->control_data = (void *)true; - /* Setup AB8500 according to board-settings */ pdata = dev_get_platdata(dev->parent); -- cgit v1.2.3 From dbad34eac26f3d31d168486ffb906b9f46657f63 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Mon, 10 Sep 2012 13:10:10 -0300 Subject: Revert "ASoC: AC97 doesn't use regmap by default" Since commit 98d3088e5 (SoC: core: Fix check before defaulting to regmap) , it is not necessary to provide codec->control_data anymore. Signed-off-by: Fabio Estevam Signed-off-by: Mark Brown --- sound/soc/codecs/ad1980.c | 1 - sound/soc/codecs/stac9766.c | 1 - sound/soc/codecs/wm9712.c | 1 - sound/soc/codecs/wm9713.c | 1 - 4 files changed, 4 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/ad1980.c b/sound/soc/codecs/ad1980.c index 11b1b714b8b5..8c39dddd7d00 100644 --- a/sound/soc/codecs/ad1980.c +++ b/sound/soc/codecs/ad1980.c @@ -186,7 +186,6 @@ static int ad1980_soc_probe(struct snd_soc_codec *codec) printk(KERN_INFO "AD1980 SoC Audio Codec\n"); - codec->control_data = codec; /* we don't use regmap! */ ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0); if (ret < 0) { printk(KERN_ERR "ad1980: failed to register AC97 codec\n"); diff --git a/sound/soc/codecs/stac9766.c b/sound/soc/codecs/stac9766.c index 33c0f3d39c87..982e437799a8 100644 --- a/sound/soc/codecs/stac9766.c +++ b/sound/soc/codecs/stac9766.c @@ -340,7 +340,6 @@ static int stac9766_codec_probe(struct snd_soc_codec *codec) printk(KERN_INFO "STAC9766 SoC Audio Codec %s\n", STAC9766_VERSION); - codec->control_data = codec; /* we don't use regmap! */ ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0); if (ret < 0) goto codec_err; diff --git a/sound/soc/codecs/wm9712.c b/sound/soc/codecs/wm9712.c index 1992a6295a16..4dd73ea08d0b 100644 --- a/sound/soc/codecs/wm9712.c +++ b/sound/soc/codecs/wm9712.c @@ -635,7 +635,6 @@ static int wm9712_soc_probe(struct snd_soc_codec *codec) { int ret = 0; - codec->control_data = codec; /* we don't use regmap! */ ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0); if (ret < 0) { printk(KERN_ERR "wm9712: failed to register AC97 codec\n"); diff --git a/sound/soc/codecs/wm9713.c b/sound/soc/codecs/wm9713.c index d0b8a3287a85..3eb19fb71d17 100644 --- a/sound/soc/codecs/wm9713.c +++ b/sound/soc/codecs/wm9713.c @@ -1196,7 +1196,6 @@ static int wm9713_soc_probe(struct snd_soc_codec *codec) if (wm9713 == NULL) return -ENOMEM; snd_soc_codec_set_drvdata(codec, wm9713); - codec->control_data = wm9713; /* we don't use regmap! */ ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0); if (ret < 0) -- cgit v1.2.3 From 6a58870df89b1941dc9a47e5ccb3c91bffad5b03 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 11 Sep 2012 09:19:19 +0800 Subject: ASoC: wm8900: Convert to devm_kzalloc() Signed-off-by: Mark Brown --- sound/soc/codecs/wm8900.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/wm8900.c b/sound/soc/codecs/wm8900.c index 077c9628c70d..5f7a78ea518c 100644 --- a/sound/soc/codecs/wm8900.c +++ b/sound/soc/codecs/wm8900.c @@ -1226,7 +1226,8 @@ static int __devinit wm8900_spi_probe(struct spi_device *spi) struct wm8900_priv *wm8900; int ret; - wm8900 = kzalloc(sizeof(struct wm8900_priv), GFP_KERNEL); + wm8900 = devm_kzalloc(&spi->dev, sizeof(struct wm8900_priv), + GFP_KERNEL); if (wm8900 == NULL) return -ENOMEM; @@ -1235,15 +1236,13 @@ static int __devinit wm8900_spi_probe(struct spi_device *spi) ret = snd_soc_register_codec(&spi->dev, &soc_codec_dev_wm8900, &wm8900_dai, 1); - if (ret < 0) - kfree(wm8900); + return ret; } static int __devexit wm8900_spi_remove(struct spi_device *spi) { snd_soc_unregister_codec(&spi->dev); - kfree(spi_get_drvdata(spi)); return 0; } @@ -1264,7 +1263,8 @@ static __devinit int wm8900_i2c_probe(struct i2c_client *i2c, struct wm8900_priv *wm8900; int ret; - wm8900 = kzalloc(sizeof(struct wm8900_priv), GFP_KERNEL); + wm8900 = devm_kzalloc(&i2c->dev, sizeof(struct wm8900_priv), + GFP_KERNEL); if (wm8900 == NULL) return -ENOMEM; @@ -1273,15 +1273,13 @@ static __devinit int wm8900_i2c_probe(struct i2c_client *i2c, ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_wm8900, &wm8900_dai, 1); - if (ret < 0) - kfree(wm8900); + return ret; } static __devexit int wm8900_i2c_remove(struct i2c_client *client) { snd_soc_unregister_codec(&client->dev); - kfree(i2c_get_clientdata(client)); return 0; } -- cgit v1.2.3 From 499926246ec77d64b028a953f7a79e941e36b802 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 11 Sep 2012 09:25:41 +0800 Subject: ASoC: wm8900: Convert to direct regmap API usage Signed-off-by: Mark Brown --- sound/soc/codecs/wm8900.c | 148 ++++++++++++++++++++++++++++------------------ 1 file changed, 90 insertions(+), 58 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/wm8900.c b/sound/soc/codecs/wm8900.c index 5f7a78ea518c..5bc877b916eb 100644 --- a/sound/soc/codecs/wm8900.c +++ b/sound/soc/codecs/wm8900.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -137,7 +138,7 @@ #define WM8900_LRC_MASK 0x03ff struct wm8900_priv { - enum snd_soc_control_type control_type; + struct regmap *regmap; u32 fll_in; /* FLL input frequency */ u32 fll_out; /* FLL output frequency */ @@ -147,54 +148,77 @@ struct wm8900_priv { * wm8900 register cache. We can't read the entire register space and we * have slow control buses so we cache the registers. */ -static const u16 wm8900_reg_defaults[WM8900_MAXREG] = { - 0x8900, 0x0000, - 0xc000, 0x0000, - 0x4050, 0x4000, - 0x0008, 0x0000, - 0x0040, 0x0040, - 0x1004, 0x00c0, - 0x00c0, 0x0000, - 0x0100, 0x00c0, - 0x00c0, 0x0000, - 0xb001, 0x0000, - 0x0000, 0x0044, - 0x004c, 0x004c, - 0x0044, 0x0044, - 0x0000, 0x0044, - 0x0000, 0x0000, - 0x0002, 0x0000, - 0x0000, 0x0000, - 0x0000, 0x0000, - 0x0008, 0x0000, - 0x0000, 0x0008, - 0x0097, 0x0100, - 0x0000, 0x0000, - 0x0050, 0x0050, - 0x0055, 0x0055, - 0x0055, 0x0000, - 0x0000, 0x0079, - 0x0079, 0x0079, - 0x0079, 0x0000, - /* Remaining registers all zero */ +static const struct reg_default wm8900_reg_defaults[] = { + { 1, 0x0000 }, + { 2, 0xc000 }, + { 3, 0x0000 }, + { 4, 0x4050 }, + { 5, 0x4000 }, + { 6, 0x0008 }, + { 7, 0x0000 }, + { 8, 0x0040 }, + { 9, 0x0040 }, + { 10, 0x1004 }, + { 11, 0x00c0 }, + { 12, 0x00c0 }, + { 13, 0x0000 }, + { 14, 0x0100 }, + { 15, 0x00c0 }, + { 16, 0x00c0 }, + { 17, 0x0000 }, + { 18, 0xb001 }, + { 19, 0x0000 }, + { 20, 0x0000 }, + { 21, 0x0044 }, + { 22, 0x004c }, + { 23, 0x004c }, + { 24, 0x0044 }, + { 25, 0x0044 }, + { 26, 0x0000 }, + { 27, 0x0044 }, + { 28, 0x0000 }, + { 29, 0x0000 }, + { 30, 0x0002 }, + { 31, 0x0000 }, + { 32, 0x0000 }, + { 33, 0x0000 }, + { 34, 0x0000 }, + { 35, 0x0000 }, + { 36, 0x0008 }, + { 37, 0x0000 }, + { 38, 0x0000 }, + { 39, 0x0008 }, + { 40, 0x0097 }, + { 41, 0x0100 }, + { 42, 0x0000 }, + { 43, 0x0000 }, + { 44, 0x0050 }, + { 45, 0x0050 }, + { 46, 0x0055 }, + { 47, 0x0055 }, + { 48, 0x0055 }, + { 49, 0x0000 }, + { 50, 0x0000 }, + { 51, 0x0079 }, + { 52, 0x0079 }, + { 53, 0x0079 }, + { 54, 0x0079 }, + { 55, 0x0000 }, }; -static int wm8900_volatile_register(struct snd_soc_codec *codec, unsigned int reg) +static bool wm8900_volatile_register(struct device *dev, unsigned int reg) { switch (reg) { case WM8900_REG_ID: - return 1; + return true; default: - return 0; + return false; } } static void wm8900_reset(struct snd_soc_codec *codec) { snd_soc_write(codec, WM8900_REG_RESET, 0); - - memcpy(codec->reg_cache, wm8900_reg_defaults, - sizeof(wm8900_reg_defaults)); } static int wm8900_hp_event(struct snd_soc_dapm_widget *w, @@ -1119,13 +1143,16 @@ static int wm8900_suspend(struct snd_soc_codec *codec) static int wm8900_resume(struct snd_soc_codec *codec) { struct wm8900_priv *wm8900 = snd_soc_codec_get_drvdata(codec); - u16 *cache; - int i, ret; - - cache = kmemdup(codec->reg_cache, sizeof(wm8900_reg_defaults), - GFP_KERNEL); + int ret; wm8900_reset(codec); + + ret = regcache_sync(wm8900->regmap); + if (ret != 0) { + dev_err(codec->dev, "Failed to restore cache: %d\n", ret); + return ret; + } + wm8900_set_bias_level(codec, SND_SOC_BIAS_STANDBY); /* Restart the FLL? */ @@ -1139,27 +1166,18 @@ static int wm8900_resume(struct snd_soc_codec *codec) ret = wm8900_set_fll(codec, 0, fll_in, fll_out); if (ret != 0) { dev_err(codec->dev, "Failed to restart FLL\n"); - kfree(cache); return ret; } } - if (cache) { - for (i = 0; i < WM8900_MAXREG; i++) - snd_soc_write(codec, i, cache[i]); - kfree(cache); - } else - dev_err(codec->dev, "Unable to allocate register cache\n"); - return 0; } static int wm8900_probe(struct snd_soc_codec *codec) { - struct wm8900_priv *wm8900 = snd_soc_codec_get_drvdata(codec); int ret = 0, reg; - ret = snd_soc_codec_set_cache_io(codec, 8, 16, wm8900->control_type); + ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP); if (ret != 0) { dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); return ret; @@ -1207,10 +1225,6 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8900 = { .suspend = wm8900_suspend, .resume = wm8900_resume, .set_bias_level = wm8900_set_bias_level, - .volatile_register = wm8900_volatile_register, - .reg_cache_size = ARRAY_SIZE(wm8900_reg_defaults), - .reg_word_size = sizeof(u16), - .reg_cache_default = wm8900_reg_defaults, .controls = wm8900_snd_controls, .num_controls = ARRAY_SIZE(wm8900_snd_controls), @@ -1220,6 +1234,18 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8900 = { .num_dapm_routes = ARRAY_SIZE(wm8900_dapm_routes), }; +static const struct regmap_config wm8900_regmap = { + .reg_bits = 8, + .val_bits = 16, + .max_register = WM8900_MAXREG, + + .reg_defaults = wm8900_reg_defaults, + .num_reg_defaults = ARRAY_SIZE(wm8900_reg_defaults), + .cache_type = REGCACHE_RBTREE, + + .volatile_reg = wm8900_volatile_register, +}; + #if defined(CONFIG_SPI_MASTER) static int __devinit wm8900_spi_probe(struct spi_device *spi) { @@ -1231,7 +1257,10 @@ static int __devinit wm8900_spi_probe(struct spi_device *spi) if (wm8900 == NULL) return -ENOMEM; - wm8900->control_type = SND_SOC_SPI; + wm8900->regmap = devm_regmap_init_spi(spi, &wm8900_regmap); + if (IS_ERR(wm8900->regmap)) + return PTR_ERR(wm8900->regmap); + spi_set_drvdata(spi, wm8900); ret = snd_soc_register_codec(&spi->dev, @@ -1268,8 +1297,11 @@ static __devinit int wm8900_i2c_probe(struct i2c_client *i2c, if (wm8900 == NULL) return -ENOMEM; + wm8900->regmap = devm_regmap_init_i2c(i2c, &wm8900_regmap); + if (IS_ERR(wm8900->regmap)) + return PTR_ERR(wm8900->regmap); + i2c_set_clientdata(i2c, wm8900); - wm8900->control_type = SND_SOC_I2C; ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_wm8900, &wm8900_dai, 1); -- cgit v1.2.3 From 7e94ca4752991c3830515f6e17ee5a7334a7f590 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 11 Sep 2012 09:26:09 +0800 Subject: ASoC: wm8900: Fix typo of name to wm9700 Signed-off-by: Mark Brown --- sound/soc/codecs/wm8900.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/wm8900.c b/sound/soc/codecs/wm8900.c index 5bc877b916eb..e781f865e5d7 100644 --- a/sound/soc/codecs/wm8900.c +++ b/sound/soc/codecs/wm8900.c @@ -493,10 +493,10 @@ SOC_DAPM_SINGLE("RINPUT2 Switch", WM8900_REG_INCTL, 1, 1, 0), SOC_DAPM_SINGLE("RINPUT3 Switch", WM8900_REG_INCTL, 0, 1, 0), }; -static const char *wm9700_lp_mux[] = { "Disabled", "Enabled" }; +static const char *wm8900_lp_mux[] = { "Disabled", "Enabled" }; static const struct soc_enum wm8900_lineout2_lp_mux = -SOC_ENUM_SINGLE(WM8900_REG_LOUTMIXCTL1, 1, 2, wm9700_lp_mux); +SOC_ENUM_SINGLE(WM8900_REG_LOUTMIXCTL1, 1, 2, wm8900_lp_mux); static const struct snd_kcontrol_new wm8900_lineout2_lp = SOC_DAPM_ENUM("Route", wm8900_lineout2_lp_mux); -- cgit v1.2.3 From 3217b0f5b6fd91440fd72cf24a8986b3f99d0d84 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 12 Sep 2012 09:24:12 +0800 Subject: ASoC: wm8510: Convert to devm_kzalloc() Signed-off-by: Mark Brown --- sound/soc/codecs/wm8510.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/wm8510.c b/sound/soc/codecs/wm8510.c index 56a049555e2c..98f28a006faf 100644 --- a/sound/soc/codecs/wm8510.c +++ b/sound/soc/codecs/wm8510.c @@ -592,7 +592,8 @@ static int __devinit wm8510_spi_probe(struct spi_device *spi) struct wm8510_priv *wm8510; int ret; - wm8510 = kzalloc(sizeof(struct wm8510_priv), GFP_KERNEL); + wm8510 = devm_kzalloc(&spi->dev, sizeof(struct wm8510_priv), + GFP_KERNEL); if (wm8510 == NULL) return -ENOMEM; @@ -601,8 +602,7 @@ static int __devinit wm8510_spi_probe(struct spi_device *spi) ret = snd_soc_register_codec(&spi->dev, &soc_codec_dev_wm8510, &wm8510_dai, 1); - if (ret < 0) - kfree(wm8510); + return ret; } @@ -630,7 +630,8 @@ static __devinit int wm8510_i2c_probe(struct i2c_client *i2c, struct wm8510_priv *wm8510; int ret; - wm8510 = kzalloc(sizeof(struct wm8510_priv), GFP_KERNEL); + wm8510 = devm_kzalloc(&i2c->dev, sizeof(struct wm8510_priv), + GFP_KERNEL); if (wm8510 == NULL) return -ENOMEM; @@ -639,8 +640,7 @@ static __devinit int wm8510_i2c_probe(struct i2c_client *i2c, ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_wm8510, &wm8510_dai, 1); - if (ret < 0) - kfree(wm8510); + return ret; } -- cgit v1.2.3 From 398c02f6c213c5d0a791ebf9517b6e7029dc5cf0 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 12 Sep 2012 09:25:59 +0800 Subject: ASoC: wm8580: Convert to devm_kzalloc() Signed-off-by: Mark Brown --- sound/soc/codecs/wm8580.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/wm8580.c b/sound/soc/codecs/wm8580.c index 7c68226376e4..cc198df15e6e 100644 --- a/sound/soc/codecs/wm8580.c +++ b/sound/soc/codecs/wm8580.c @@ -899,7 +899,8 @@ static int wm8580_i2c_probe(struct i2c_client *i2c, struct wm8580_priv *wm8580; int ret; - wm8580 = kzalloc(sizeof(struct wm8580_priv), GFP_KERNEL); + wm8580 = devm_kzalloc(&i2c->dev, sizeof(struct wm8580_priv), + GFP_KERNEL); if (wm8580 == NULL) return -ENOMEM; @@ -908,15 +909,13 @@ static int wm8580_i2c_probe(struct i2c_client *i2c, ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_wm8580, wm8580_dai, ARRAY_SIZE(wm8580_dai)); - if (ret < 0) - kfree(wm8580); + return ret; } static int wm8580_i2c_remove(struct i2c_client *client) { snd_soc_unregister_codec(&client->dev); - kfree(i2c_get_clientdata(client)); return 0; } -- cgit v1.2.3 From e908ef40e4824a000889b0ab3f9eb9660bbe3f18 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 12 Sep 2012 09:26:12 +0800 Subject: ASoC: wm8711: Convert to devm_kzalloc() Signed-off-by: Mark Brown --- sound/soc/codecs/wm8711.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/wm8711.c b/sound/soc/codecs/wm8711.c index 0b76d1dca5ea..1b1209a4c791 100644 --- a/sound/soc/codecs/wm8711.c +++ b/sound/soc/codecs/wm8711.c @@ -414,7 +414,8 @@ static int __devinit wm8711_spi_probe(struct spi_device *spi) struct wm8711_priv *wm8711; int ret; - wm8711 = kzalloc(sizeof(struct wm8711_priv), GFP_KERNEL); + wm8711 = devm_kzalloc(&spi->dev, sizeof(struct wm8711_priv), + GFP_KERNEL); if (wm8711 == NULL) return -ENOMEM; @@ -423,15 +424,14 @@ static int __devinit wm8711_spi_probe(struct spi_device *spi) ret = snd_soc_register_codec(&spi->dev, &soc_codec_dev_wm8711, &wm8711_dai, 1); - if (ret < 0) - kfree(wm8711); + return ret; } static int __devexit wm8711_spi_remove(struct spi_device *spi) { snd_soc_unregister_codec(&spi->dev); - kfree(spi_get_drvdata(spi)); + return 0; } @@ -453,7 +453,8 @@ static __devinit int wm8711_i2c_probe(struct i2c_client *client, struct wm8711_priv *wm8711; int ret; - wm8711 = kzalloc(sizeof(struct wm8711_priv), GFP_KERNEL); + wm8711 = devm_kzalloc(&client->dev, sizeof(struct wm8711_priv), + GFP_KERNEL); if (wm8711 == NULL) return -ENOMEM; @@ -462,15 +463,13 @@ static __devinit int wm8711_i2c_probe(struct i2c_client *client, ret = snd_soc_register_codec(&client->dev, &soc_codec_dev_wm8711, &wm8711_dai, 1); - if (ret < 0) - kfree(wm8711); + return ret; } static __devexit int wm8711_i2c_remove(struct i2c_client *client) { snd_soc_unregister_codec(&client->dev); - kfree(i2c_get_clientdata(client)); return 0; } -- cgit v1.2.3 From 1a9585b0f7b3e21858f9a893d66a845f23d28ef1 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 12 Sep 2012 09:26:25 +0800 Subject: ASoC: wm8728: Convert to devm_kzalloc() Signed-off-by: Mark Brown --- sound/soc/codecs/wm8728.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/wm8728.c b/sound/soc/codecs/wm8728.c index 1467f97dce21..f274c250d492 100644 --- a/sound/soc/codecs/wm8728.c +++ b/sound/soc/codecs/wm8728.c @@ -280,7 +280,8 @@ static int __devinit wm8728_spi_probe(struct spi_device *spi) struct wm8728_priv *wm8728; int ret; - wm8728 = kzalloc(sizeof(struct wm8728_priv), GFP_KERNEL); + wm8728 = devm_kzalloc(&spi->dev, sizeof(struct wm8728_priv), + GFP_KERNEL); if (wm8728 == NULL) return -ENOMEM; @@ -289,15 +290,14 @@ static int __devinit wm8728_spi_probe(struct spi_device *spi) ret = snd_soc_register_codec(&spi->dev, &soc_codec_dev_wm8728, &wm8728_dai, 1); - if (ret < 0) - kfree(wm8728); + return ret; } static int __devexit wm8728_spi_remove(struct spi_device *spi) { snd_soc_unregister_codec(&spi->dev); - kfree(spi_get_drvdata(spi)); + return 0; } @@ -319,7 +319,8 @@ static __devinit int wm8728_i2c_probe(struct i2c_client *i2c, struct wm8728_priv *wm8728; int ret; - wm8728 = kzalloc(sizeof(struct wm8728_priv), GFP_KERNEL); + wm8728 = devm_kzalloc(&i2c->dev, sizeof(struct wm8728_priv), + GFP_KERNEL); if (wm8728 == NULL) return -ENOMEM; @@ -328,15 +329,13 @@ static __devinit int wm8728_i2c_probe(struct i2c_client *i2c, ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_wm8728, &wm8728_dai, 1); - if (ret < 0) - kfree(wm8728); + return ret; } static __devexit int wm8728_i2c_remove(struct i2c_client *client) { snd_soc_unregister_codec(&client->dev); - kfree(i2c_get_clientdata(client)); return 0; } -- cgit v1.2.3 From 65fdd9bffa1367b75de0c331a105ce36de618794 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 12 Sep 2012 09:26:38 +0800 Subject: ASoC: wm8737: Convert to devm_kzalloc() Signed-off-by: Mark Brown --- sound/soc/codecs/wm8737.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/wm8737.c b/sound/soc/codecs/wm8737.c index d0520124616d..8c25442f9b47 100644 --- a/sound/soc/codecs/wm8737.c +++ b/sound/soc/codecs/wm8737.c @@ -647,7 +647,8 @@ static __devinit int wm8737_i2c_probe(struct i2c_client *i2c, struct wm8737_priv *wm8737; int ret; - wm8737 = kzalloc(sizeof(struct wm8737_priv), GFP_KERNEL); + wm8737 = devm_kzalloc(&i2c->dev, sizeof(struct wm8737_priv), + GFP_KERNEL); if (wm8737 == NULL) return -ENOMEM; @@ -656,8 +657,7 @@ static __devinit int wm8737_i2c_probe(struct i2c_client *i2c, ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_wm8737, &wm8737_dai, 1); - if (ret < 0) - kfree(wm8737); + return ret; } @@ -665,7 +665,7 @@ static __devinit int wm8737_i2c_probe(struct i2c_client *i2c, static __devexit int wm8737_i2c_remove(struct i2c_client *client) { snd_soc_unregister_codec(&client->dev); - kfree(i2c_get_clientdata(client)); + return 0; } @@ -693,7 +693,8 @@ static int __devinit wm8737_spi_probe(struct spi_device *spi) struct wm8737_priv *wm8737; int ret; - wm8737 = kzalloc(sizeof(struct wm8737_priv), GFP_KERNEL); + wm8737 = devm_kzalloc(&spi->dev, sizeof(struct wm8737_priv), + GFP_KERNEL); if (wm8737 == NULL) return -ENOMEM; @@ -702,15 +703,14 @@ static int __devinit wm8737_spi_probe(struct spi_device *spi) ret = snd_soc_register_codec(&spi->dev, &soc_codec_dev_wm8737, &wm8737_dai, 1); - if (ret < 0) - kfree(wm8737); + return ret; } static int __devexit wm8737_spi_remove(struct spi_device *spi) { snd_soc_unregister_codec(&spi->dev); - kfree(spi_get_drvdata(spi)); + return 0; } -- cgit v1.2.3 From 587cbbb36ef2657cd888b7705e02cfe96ab088b7 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 12 Sep 2012 09:26:53 +0800 Subject: ASoC: wm8990: Convert to devm_kzalloc() Signed-off-by: Mark Brown --- sound/soc/codecs/wm8990.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/wm8990.c b/sound/soc/codecs/wm8990.c index db63c97ddf51..c28c83e5395d 100644 --- a/sound/soc/codecs/wm8990.c +++ b/sound/soc/codecs/wm8990.c @@ -1388,7 +1388,8 @@ static __devinit int wm8990_i2c_probe(struct i2c_client *i2c, struct wm8990_priv *wm8990; int ret; - wm8990 = kzalloc(sizeof(struct wm8990_priv), GFP_KERNEL); + wm8990 = devm_kzalloc(&i2c->dev, sizeof(struct wm8990_priv), + GFP_KERNEL); if (wm8990 == NULL) return -ENOMEM; @@ -1396,15 +1397,14 @@ static __devinit int wm8990_i2c_probe(struct i2c_client *i2c, ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_wm8990, &wm8990_dai, 1); - if (ret < 0) - kfree(wm8990); + return ret; } static __devexit int wm8990_i2c_remove(struct i2c_client *client) { snd_soc_unregister_codec(&client->dev); - kfree(i2c_get_clientdata(client)); + return 0; } -- cgit v1.2.3 From 046d4f02e8835ff78f8ba5a09e358b2bc4832903 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 12 Sep 2012 09:28:08 +0800 Subject: ASoC: wm8991: Convert to devm_kzalloc() Signed-off-by: Mark Brown --- sound/soc/codecs/wm8991.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/wm8991.c b/sound/soc/codecs/wm8991.c index b9dbfebbda13..fe439f027e10 100644 --- a/sound/soc/codecs/wm8991.c +++ b/sound/soc/codecs/wm8991.c @@ -1363,7 +1363,7 @@ static __devinit int wm8991_i2c_probe(struct i2c_client *i2c, struct wm8991_priv *wm8991; int ret; - wm8991 = kzalloc(sizeof *wm8991, GFP_KERNEL); + wm8991 = devm_kzalloc(&i2c->dev, sizeof(*wm8991), GFP_KERNEL); if (!wm8991) return -ENOMEM; @@ -1372,15 +1372,14 @@ static __devinit int wm8991_i2c_probe(struct i2c_client *i2c, ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_wm8991, &wm8991_dai, 1); - if (ret < 0) - kfree(wm8991); + return ret; } static __devexit int wm8991_i2c_remove(struct i2c_client *client) { snd_soc_unregister_codec(&client->dev); - kfree(i2c_get_clientdata(client)); + return 0; } -- cgit v1.2.3 From e643049d301142cda473bc4d7f4eba4992fe657c Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 12 Sep 2012 11:43:44 +0800 Subject: ASoC: wm8510: Convert to direct regmap API usage Signed-off-by: Mark Brown --- sound/soc/codecs/wm8510.c | 117 ++++++++++++++++++++++++++++++++++++---------- 1 file changed, 92 insertions(+), 25 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/wm8510.c b/sound/soc/codecs/wm8510.c index 98f28a006faf..c12a54e72e89 100644 --- a/sound/soc/codecs/wm8510.c +++ b/sound/soc/codecs/wm8510.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -33,24 +34,75 @@ * We can't read the WM8510 register space when we are * using 2 wire for device control, so we cache them instead. */ -static const u16 wm8510_reg[WM8510_CACHEREGNUM] = { - 0x0000, 0x0000, 0x0000, 0x0000, - 0x0050, 0x0000, 0x0140, 0x0000, - 0x0000, 0x0000, 0x0000, 0x00ff, - 0x0000, 0x0000, 0x0100, 0x00ff, - 0x0000, 0x0000, 0x012c, 0x002c, - 0x002c, 0x002c, 0x002c, 0x0000, - 0x0032, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, - 0x0038, 0x000b, 0x0032, 0x0000, - 0x0008, 0x000c, 0x0093, 0x00e9, - 0x0000, 0x0000, 0x0000, 0x0000, - 0x0003, 0x0010, 0x0000, 0x0000, - 0x0000, 0x0002, 0x0001, 0x0000, - 0x0000, 0x0000, 0x0039, 0x0000, - 0x0001, +static const struct reg_default wm8510_reg_defaults[] = { + { 1, 0x0000 }, + { 2, 0x0000 }, + { 3, 0x0000 }, + { 4, 0x0050 }, + { 5, 0x0000 }, + { 6, 0x0140 }, + { 7, 0x0000 }, + { 8, 0x0000 }, + { 9, 0x0000 }, + { 10, 0x0000 }, + { 11, 0x00ff }, + { 12, 0x0000 }, + { 13, 0x0000 }, + { 14, 0x0100 }, + { 15, 0x00ff }, + { 16, 0x0000 }, + { 17, 0x0000 }, + { 18, 0x012c }, + { 19, 0x002c }, + { 20, 0x002c }, + { 21, 0x002c }, + { 22, 0x002c }, + { 23, 0x0000 }, + { 24, 0x0032 }, + { 25, 0x0000 }, + { 26, 0x0000 }, + { 27, 0x0000 }, + { 28, 0x0000 }, + { 29, 0x0000 }, + { 30, 0x0000 }, + { 31, 0x0000 }, + { 32, 0x0038 }, + { 33, 0x000b }, + { 34, 0x0032 }, + { 35, 0x0000 }, + { 36, 0x0008 }, + { 37, 0x000c }, + { 38, 0x0093 }, + { 39, 0x00e9 }, + { 40, 0x0000 }, + { 41, 0x0000 }, + { 42, 0x0000 }, + { 43, 0x0000 }, + { 44, 0x0003 }, + { 45, 0x0010 }, + { 46, 0x0000 }, + { 47, 0x0000 }, + { 48, 0x0000 }, + { 49, 0x0002 }, + { 50, 0x0001 }, + { 51, 0x0000 }, + { 52, 0x0000 }, + { 53, 0x0000 }, + { 54, 0x0039 }, + { 55, 0x0000 }, + { 56, 0x0001 }, }; +static bool wm8510_volatile(struct device *dev, unsigned int reg) +{ + switch (reg) { + case WM8510_RESET: + return true; + default: + return false; + } +} + #define WM8510_POWER1_BIASEN 0x08 #define WM8510_POWER1_BUFIOEN 0x10 @@ -58,7 +110,7 @@ static const u16 wm8510_reg[WM8510_CACHEREGNUM] = { /* codec private data */ struct wm8510_priv { - enum snd_soc_control_type control_type; + struct regmap *regmap; }; static const char *wm8510_companding[] = { "Off", "NC", "u-law", "A-law" }; @@ -454,6 +506,7 @@ static int wm8510_mute(struct snd_soc_dai *dai, int mute) static int wm8510_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level) { + struct wm8510_priv *wm8510 = snd_soc_codec_get_drvdata(codec); u16 power1 = snd_soc_read(codec, WM8510_POWER1) & ~0x3; switch (level) { @@ -467,7 +520,7 @@ static int wm8510_set_bias_level(struct snd_soc_codec *codec, power1 |= WM8510_POWER1_BIASEN | WM8510_POWER1_BUFIOEN; if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { - snd_soc_cache_sync(codec); + regcache_sync(wm8510->regmap); /* Initial cap charge at VMID 5k */ snd_soc_write(codec, WM8510_POWER1, power1 | 0x3); @@ -536,10 +589,9 @@ static int wm8510_resume(struct snd_soc_codec *codec) static int wm8510_probe(struct snd_soc_codec *codec) { - struct wm8510_priv *wm8510 = snd_soc_codec_get_drvdata(codec); int ret; - ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8510->control_type); + ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); if (ret < 0) { printk(KERN_ERR "wm8510: failed to set cache I/O: %d\n", ret); return ret; @@ -569,9 +621,6 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8510 = { .suspend = wm8510_suspend, .resume = wm8510_resume, .set_bias_level = wm8510_set_bias_level, - .reg_cache_size = ARRAY_SIZE(wm8510_reg), - .reg_word_size = sizeof(u16), - .reg_cache_default =wm8510_reg, .controls = wm8510_snd_controls, .num_controls = ARRAY_SIZE(wm8510_snd_controls), @@ -586,6 +635,18 @@ static const struct of_device_id wm8510_of_match[] = { { }, }; +static const struct regmap_config wm8510_regmap = { + .reg_bits = 7, + .val_bits = 9, + .max_register = WM8510_MONOMIX, + + .reg_defaults = wm8510_reg_defaults, + .num_reg_defaults = ARRAY_SIZE(wm8510_reg_defaults), + .cache_type = REGCACHE_RBTREE, + + .volatile_reg = wm8510_volatile, +}; + #if defined(CONFIG_SPI_MASTER) static int __devinit wm8510_spi_probe(struct spi_device *spi) { @@ -597,7 +658,10 @@ static int __devinit wm8510_spi_probe(struct spi_device *spi) if (wm8510 == NULL) return -ENOMEM; - wm8510->control_type = SND_SOC_SPI; + wm8510->regmap = devm_regmap_init_spi(spi, &wm8510_regmap); + if (IS_ERR(wm8510->regmap)) + return PTR_ERR(wm8510->regmap); + spi_set_drvdata(spi, wm8510); ret = snd_soc_register_codec(&spi->dev, @@ -635,8 +699,11 @@ static __devinit int wm8510_i2c_probe(struct i2c_client *i2c, if (wm8510 == NULL) return -ENOMEM; + wm8510->regmap = devm_regmap_init_i2c(i2c, &wm8510_regmap); + if (IS_ERR(wm8510->regmap)) + return PTR_ERR(wm8510->regmap); + i2c_set_clientdata(i2c, wm8510); - wm8510->control_type = SND_SOC_I2C; ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_wm8510, &wm8510_dai, 1); -- cgit v1.2.3 From b689d9f9961befd9b322783f512195785fe82daa Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 12 Sep 2012 11:59:51 +0800 Subject: ASoC: wm8580: Convert to direct regmap API usage Signed-off-by: Mark Brown --- sound/soc/codecs/wm8580.c | 116 +++++++++++++++++++++++++++++++++++----------- 1 file changed, 90 insertions(+), 26 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/wm8580.c b/sound/soc/codecs/wm8580.c index cc198df15e6e..02c75bec7d71 100644 --- a/sound/soc/codecs/wm8580.c +++ b/sound/soc/codecs/wm8580.c @@ -1,7 +1,7 @@ /* * wm8580.c -- WM8580 ALSA Soc Audio driver * - * Copyright 2008-11 Wolfson Microelectronics PLC. + * Copyright 2008-12 Wolfson Microelectronics PLC. * * 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 @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -157,23 +158,72 @@ * We can't read the WM8580 register space when we * are using 2 wire for device control, so we cache them instead. */ -static const u16 wm8580_reg[] = { - 0x0121, 0x017e, 0x007d, 0x0014, /*R3*/ - 0x0121, 0x017e, 0x007d, 0x0194, /*R7*/ - 0x0010, 0x0002, 0x0002, 0x00c2, /*R11*/ - 0x0182, 0x0082, 0x000a, 0x0024, /*R15*/ - 0x0009, 0x0000, 0x00ff, 0x0000, /*R19*/ - 0x00ff, 0x00ff, 0x00ff, 0x00ff, /*R23*/ - 0x00ff, 0x00ff, 0x00ff, 0x00ff, /*R27*/ - 0x01f0, 0x0040, 0x0000, 0x0000, /*R31(0x1F)*/ - 0x0000, 0x0000, 0x0031, 0x000b, /*R35*/ - 0x0039, 0x0000, 0x0010, 0x0032, /*R39*/ - 0x0054, 0x0076, 0x0098, 0x0000, /*R43(0x2B)*/ - 0x0000, 0x0000, 0x0000, 0x0000, /*R47*/ - 0x0000, 0x0000, 0x005e, 0x003e, /*R51(0x33)*/ - 0x0000, 0x0000 /*R53*/ +static const struct reg_default wm8580_reg_defaults[] = { + { 0, 0x0121 }, + { 1, 0x017e }, + { 2, 0x007d }, + { 3, 0x0014 }, + { 4, 0x0121 }, + { 5, 0x017e }, + { 6, 0x007d }, + { 7, 0x0194 }, + { 8, 0x0010 }, + { 9, 0x0002 }, + { 10, 0x0002 }, + { 11, 0x00c2 }, + { 12, 0x0182 }, + { 13, 0x0082 }, + { 14, 0x000a }, + { 15, 0x0024 }, + { 16, 0x0009 }, + { 17, 0x0000 }, + { 18, 0x00ff }, + { 19, 0x0000 }, + { 20, 0x00ff }, + { 21, 0x00ff }, + { 22, 0x00ff }, + { 23, 0x00ff }, + { 24, 0x00ff }, + { 25, 0x00ff }, + { 26, 0x00ff }, + { 27, 0x00ff }, + { 28, 0x01f0 }, + { 29, 0x0040 }, + { 30, 0x0000 }, + { 31, 0x0000 }, + { 32, 0x0000 }, + { 33, 0x0000 }, + { 34, 0x0031 }, + { 35, 0x000b }, + { 36, 0x0039 }, + { 37, 0x0000 }, + { 38, 0x0010 }, + { 39, 0x0032 }, + { 40, 0x0054 }, + { 41, 0x0076 }, + { 42, 0x0098 }, + { 43, 0x0000 }, + { 44, 0x0000 }, + { 45, 0x0000 }, + { 46, 0x0000 }, + { 47, 0x0000 }, + { 48, 0x0000 }, + { 49, 0x0000 }, + { 50, 0x005e }, + { 51, 0x003e }, + { 52, 0x0000 }, }; +static bool wm8580_volatile(struct device *dev, unsigned int reg) +{ + switch (reg) { + case WM8580_RESET: + return true; + default: + return false; + } +} + struct pll_state { unsigned int in; unsigned int out; @@ -188,7 +238,7 @@ static const char *wm8580_supply_names[WM8580_NUM_SUPPLIES] = { /* codec private data */ struct wm8580_priv { - enum snd_soc_control_type control_type; + struct regmap *regmap; struct regulator_bulk_data supplies[WM8580_NUM_SUPPLIES]; struct pll_state a; struct pll_state b; @@ -203,14 +253,16 @@ static int wm8580_out_vu(struct snd_kcontrol *kcontrol, struct soc_mixer_control *mc = (struct soc_mixer_control *)kcontrol->private_value; struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - u16 *reg_cache = codec->reg_cache; + struct wm8580_priv *wm8580 = snd_soc_codec_get_drvdata(codec); unsigned int reg = mc->reg; unsigned int reg2 = mc->rreg; int ret; - /* Clear the register cache so we write without VU set */ - reg_cache[reg] = 0; - reg_cache[reg2] = 0; + /* Clear the register cache VU so we write without VU set */ + regcache_cache_only(wm8580->regmap, true); + regmap_update_bits(wm8580->regmap, reg, 0x100, 0x000); + regmap_update_bits(wm8580->regmap, reg2, 0x100, 0x000); + regcache_cache_only(wm8580->regmap, false); ret = snd_soc_put_volsw(kcontrol, ucontrol); if (ret < 0) @@ -817,7 +869,7 @@ static int wm8580_probe(struct snd_soc_codec *codec) struct wm8580_priv *wm8580 = snd_soc_codec_get_drvdata(codec); int ret = 0,i; - ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8580->control_type); + ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); if (ret < 0) { dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); return ret; @@ -875,9 +927,6 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8580 = { .probe = wm8580_probe, .remove = wm8580_remove, .set_bias_level = wm8580_set_bias_level, - .reg_cache_size = ARRAY_SIZE(wm8580_reg), - .reg_word_size = sizeof(u16), - .reg_cache_default = wm8580_reg, .controls = wm8580_snd_controls, .num_controls = ARRAY_SIZE(wm8580_snd_controls), @@ -892,6 +941,18 @@ static const struct of_device_id wm8580_of_match[] = { { }, }; +static const struct regmap_config wm8580_regmap = { + .reg_bits = 7, + .val_bits = 9, + .max_register = WM8580_MAX_REGISTER, + + .reg_defaults = wm8580_reg_defaults, + .num_reg_defaults = ARRAY_SIZE(wm8580_reg_defaults), + .cache_type = REGCACHE_RBTREE, + + .volatile_reg = wm8580_volatile, +}; + #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) static int wm8580_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) @@ -904,8 +965,11 @@ static int wm8580_i2c_probe(struct i2c_client *i2c, if (wm8580 == NULL) return -ENOMEM; + wm8580->regmap = devm_regmap_init_i2c(i2c, &wm8580_regmap); + if (IS_ERR(wm8580->regmap)) + return PTR_ERR(wm8580->regmap); + i2c_set_clientdata(i2c, wm8580); - wm8580->control_type = SND_SOC_I2C; ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_wm8580, wm8580_dai, ARRAY_SIZE(wm8580_dai)); -- cgit v1.2.3 From 18273b05def692d1883745d22e72fa275bc92c17 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 12 Sep 2012 12:03:51 +0800 Subject: ASoC: wm8580: Move regulator acquisition to I2C probe Better style as we get all the resources we need prior to starting the ASoC level probe. Signed-off-by: Mark Brown --- sound/soc/codecs/wm8580.c | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/wm8580.c b/sound/soc/codecs/wm8580.c index 02c75bec7d71..5e9c40fa7eb2 100644 --- a/sound/soc/codecs/wm8580.c +++ b/sound/soc/codecs/wm8580.c @@ -867,7 +867,7 @@ static struct snd_soc_dai_driver wm8580_dai[] = { static int wm8580_probe(struct snd_soc_codec *codec) { struct wm8580_priv *wm8580 = snd_soc_codec_get_drvdata(codec); - int ret = 0,i; + int ret = 0; ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); if (ret < 0) { @@ -875,16 +875,6 @@ static int wm8580_probe(struct snd_soc_codec *codec) return ret; } - for (i = 0; i < ARRAY_SIZE(wm8580->supplies); i++) - wm8580->supplies[i].supply = wm8580_supply_names[i]; - - ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8580->supplies), - wm8580->supplies); - if (ret != 0) { - dev_err(codec->dev, "Failed to request supplies: %d\n", ret); - return ret; - } - ret = regulator_bulk_enable(ARRAY_SIZE(wm8580->supplies), wm8580->supplies); if (ret != 0) { @@ -906,7 +896,6 @@ static int wm8580_probe(struct snd_soc_codec *codec) err_regulator_enable: regulator_bulk_disable(ARRAY_SIZE(wm8580->supplies), wm8580->supplies); err_regulator_get: - regulator_bulk_free(ARRAY_SIZE(wm8580->supplies), wm8580->supplies); return ret; } @@ -918,7 +907,6 @@ static int wm8580_remove(struct snd_soc_codec *codec) wm8580_set_bias_level(codec, SND_SOC_BIAS_OFF); regulator_bulk_disable(ARRAY_SIZE(wm8580->supplies), wm8580->supplies); - regulator_bulk_free(ARRAY_SIZE(wm8580->supplies), wm8580->supplies); return 0; } @@ -958,7 +946,7 @@ static int wm8580_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { struct wm8580_priv *wm8580; - int ret; + int ret, i; wm8580 = devm_kzalloc(&i2c->dev, sizeof(struct wm8580_priv), GFP_KERNEL); @@ -969,6 +957,16 @@ static int wm8580_i2c_probe(struct i2c_client *i2c, if (IS_ERR(wm8580->regmap)) return PTR_ERR(wm8580->regmap); + for (i = 0; i < ARRAY_SIZE(wm8580->supplies); i++) + wm8580->supplies[i].supply = wm8580_supply_names[i]; + + ret = devm_regulator_bulk_get(&i2c->dev, ARRAY_SIZE(wm8580->supplies), + wm8580->supplies); + if (ret != 0) { + dev_err(&i2c->dev, "Failed to request supplies: %d\n", ret); + return ret; + } + i2c_set_clientdata(i2c, wm8580); ret = snd_soc_register_codec(&i2c->dev, -- cgit v1.2.3 From 5aa5fa9fdbda20eee3351dd2492cd5c0d6fa7d1d Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 12 Sep 2012 12:15:20 +0800 Subject: ASoC: wm8711: Convert to direct regmap API usage Signed-off-by: Mark Brown --- sound/soc/codecs/wm8711.c | 50 +++++++++++++++++++++++++++++++++++------------ 1 file changed, 38 insertions(+), 12 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/wm8711.c b/sound/soc/codecs/wm8711.c index 1b1209a4c791..8b8bb70f1eb9 100644 --- a/sound/soc/codecs/wm8711.c +++ b/sound/soc/codecs/wm8711.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -32,7 +33,7 @@ /* codec private data */ struct wm8711_priv { - enum snd_soc_control_type bus_type; + struct regmap *regmap; unsigned int sysclk; }; @@ -42,11 +43,21 @@ struct wm8711_priv { * using 2 wire for device control, so we cache them instead. * There is no point in caching the reset register */ -static const u16 wm8711_reg[WM8711_CACHEREGNUM] = { - 0x0079, 0x0079, 0x000a, 0x0008, - 0x009f, 0x000a, 0x0000, 0x0000 +static const struct reg_default wm8711_reg_defaults[] = { + { 0, 0x0079 }, { 1, 0x0079 }, { 2, 0x000a }, { 3, 0x0008 }, + { 4, 0x009f }, { 5, 0x000a }, { 6, 0x0000 }, { 7, 0x0000 }, }; +static bool wm8711_volatile(struct device *dev, unsigned int reg) +{ + switch (reg) { + case WM8711_RESET: + return true; + default: + return false; + } +} + #define wm8711_reset(c) snd_soc_write(c, WM8711_RESET, 0) static const DECLARE_TLV_DB_SCALE(out_tlv, -12100, 100, 1); @@ -289,6 +300,7 @@ static int wm8711_set_dai_fmt(struct snd_soc_dai *codec_dai, static int wm8711_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level) { + struct wm8711_priv *wm8711 = snd_soc_codec_get_drvdata(codec); u16 reg = snd_soc_read(codec, WM8711_PWR) & 0xff7f; switch (level) { @@ -299,7 +311,7 @@ static int wm8711_set_bias_level(struct snd_soc_codec *codec, break; case SND_SOC_BIAS_STANDBY: if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) - snd_soc_cache_sync(codec); + regcache_sync(wm8711->regmap); snd_soc_write(codec, WM8711_PWR, reg | 0x0040); break; @@ -353,10 +365,9 @@ static int wm8711_resume(struct snd_soc_codec *codec) static int wm8711_probe(struct snd_soc_codec *codec) { - struct wm8711_priv *wm8711 = snd_soc_codec_get_drvdata(codec); int ret; - ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8711->bus_type); + ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); if (ret < 0) { dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); return ret; @@ -391,9 +402,6 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8711 = { .suspend = wm8711_suspend, .resume = wm8711_resume, .set_bias_level = wm8711_set_bias_level, - .reg_cache_size = ARRAY_SIZE(wm8711_reg), - .reg_word_size = sizeof(u16), - .reg_cache_default = wm8711_reg, .controls = wm8711_snd_controls, .num_controls = ARRAY_SIZE(wm8711_snd_controls), .dapm_widgets = wm8711_dapm_widgets, @@ -408,6 +416,18 @@ static const struct of_device_id wm8711_of_match[] = { }; MODULE_DEVICE_TABLE(of, wm8711_of_match); +static const struct regmap_config wm8711_regmap = { + .reg_bits = 7, + .val_bits = 9, + .max_register = WM8711_RESET, + + .reg_defaults = wm8711_reg_defaults, + .num_reg_defaults = ARRAY_SIZE(wm8711_reg_defaults), + .cache_type = REGCACHE_RBTREE, + + .volatile_reg = wm8711_volatile, +}; + #if defined(CONFIG_SPI_MASTER) static int __devinit wm8711_spi_probe(struct spi_device *spi) { @@ -419,8 +439,11 @@ static int __devinit wm8711_spi_probe(struct spi_device *spi) if (wm8711 == NULL) return -ENOMEM; + wm8711->regmap = devm_regmap_init_spi(spi, &wm8711_regmap); + if (IS_ERR(wm8711->regmap)) + return PTR_ERR(wm8711->regmap); + spi_set_drvdata(spi, wm8711); - wm8711->bus_type = SND_SOC_SPI; ret = snd_soc_register_codec(&spi->dev, &soc_codec_dev_wm8711, &wm8711_dai, 1); @@ -458,8 +481,11 @@ static __devinit int wm8711_i2c_probe(struct i2c_client *client, if (wm8711 == NULL) return -ENOMEM; + wm8711->regmap = devm_regmap_init_i2c(client, &wm8711_regmap); + if (IS_ERR(wm8711->regmap)) + return PTR_ERR(wm8711->regmap); + i2c_set_clientdata(client, wm8711); - wm8711->bus_type = SND_SOC_I2C; ret = snd_soc_register_codec(&client->dev, &soc_codec_dev_wm8711, &wm8711_dai, 1); -- cgit v1.2.3 From d16383ef2a62fe53a929eac56b662d6def6bb8c7 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 12 Sep 2012 12:30:01 +0800 Subject: ASoC: wm8728: Convert to direct regmap API usage Signed-off-by: Mark Brown --- sound/soc/codecs/wm8728.c | 45 ++++++++++++++++++++++++++++----------------- 1 file changed, 28 insertions(+), 17 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/wm8728.c b/sound/soc/codecs/wm8728.c index f274c250d492..00a12a0c3919 100644 --- a/sound/soc/codecs/wm8728.c +++ b/sound/soc/codecs/wm8728.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -35,16 +36,16 @@ * the volume update bits, mute the output and enable infinite zero * detect. */ -static const u16 wm8728_reg_defaults[] = { - 0x1ff, - 0x1ff, - 0x001, - 0x100, +static const struct reg_default wm8728_reg_defaults[] = { + { 0, 0x1ff }, + { 1, 0x1ff }, + { 2, 0x001 }, + { 3, 0x100 }, }; /* codec private data */ struct wm8728_priv { - enum snd_soc_control_type control_type; + struct regmap *regmap; }; static const DECLARE_TLV_DB_SCALE(wm8728_tlv, -12750, 50, 1); @@ -162,8 +163,8 @@ static int wm8728_set_dai_fmt(struct snd_soc_dai *codec_dai, static int wm8728_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level) { + struct wm8728_priv *wm8728 = snd_soc_codec_get_drvdata(codec); u16 reg; - int i; switch (level) { case SND_SOC_BIAS_ON: @@ -175,9 +176,7 @@ static int wm8728_set_bias_level(struct snd_soc_codec *codec, snd_soc_write(codec, WM8728_DACCTL, reg & ~0x4); /* ..then sync in the register cache. */ - for (i = 0; i < ARRAY_SIZE(wm8728_reg_defaults); i++) - snd_soc_write(codec, i, - snd_soc_read(codec, i)); + regcache_sync(wm8728->regmap); } break; @@ -229,10 +228,9 @@ static int wm8728_resume(struct snd_soc_codec *codec) static int wm8728_probe(struct snd_soc_codec *codec) { - struct wm8728_priv *wm8728 = snd_soc_codec_get_drvdata(codec); int ret; - ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8728->control_type); + ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); if (ret < 0) { printk(KERN_ERR "wm8728: failed to configure cache I/O: %d\n", ret); @@ -257,9 +255,6 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8728 = { .suspend = wm8728_suspend, .resume = wm8728_resume, .set_bias_level = wm8728_set_bias_level, - .reg_cache_size = ARRAY_SIZE(wm8728_reg_defaults), - .reg_word_size = sizeof(u16), - .reg_cache_default = wm8728_reg_defaults, .controls = wm8728_snd_controls, .num_controls = ARRAY_SIZE(wm8728_snd_controls), .dapm_widgets = wm8728_dapm_widgets, @@ -274,6 +269,16 @@ static const struct of_device_id wm8728_of_match[] = { }; MODULE_DEVICE_TABLE(of, wm8728_of_match); +static const struct regmap_config wm8728_regmap = { + .reg_bits = 7, + .val_bits = 9, + .max_register = WM8728_IFCTL, + + .reg_defaults = wm8728_reg_defaults, + .num_reg_defaults = ARRAY_SIZE(wm8728_reg_defaults), + .cache_type = REGCACHE_RBTREE, +}; + #if defined(CONFIG_SPI_MASTER) static int __devinit wm8728_spi_probe(struct spi_device *spi) { @@ -285,7 +290,10 @@ static int __devinit wm8728_spi_probe(struct spi_device *spi) if (wm8728 == NULL) return -ENOMEM; - wm8728->control_type = SND_SOC_SPI; + wm8728->regmap = devm_regmap_init_spi(spi, &wm8728_regmap); + if (IS_ERR(wm8728->regmap)) + return PTR_ERR(wm8728->regmap); + spi_set_drvdata(spi, wm8728); ret = snd_soc_register_codec(&spi->dev, @@ -324,8 +332,11 @@ static __devinit int wm8728_i2c_probe(struct i2c_client *i2c, if (wm8728 == NULL) return -ENOMEM; + wm8728->regmap = devm_regmap_init_i2c(i2c, &wm8728_regmap); + if (IS_ERR(wm8728->regmap)) + return PTR_ERR(wm8728->regmap); + i2c_set_clientdata(i2c, wm8728); - wm8728->control_type = SND_SOC_I2C; ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_wm8728, &wm8728_dai, 1); -- cgit v1.2.3 From 4f69bb31b8840713f82c6c476bae3f2356819ce2 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 12 Sep 2012 12:36:28 +0800 Subject: ASoC: wm8737: Move regulator acquisition to device registration This is better style as we acquire resources we will need before we go into the ASoC card probe. Signed-off-by: Mark Brown --- sound/soc/codecs/wm8737.c | 41 +++++++++++++++++++++++------------------ 1 file changed, 23 insertions(+), 18 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/wm8737.c b/sound/soc/codecs/wm8737.c index 8c25442f9b47..3bf5bc73e2de 100644 --- a/sound/soc/codecs/wm8737.c +++ b/sound/soc/codecs/wm8737.c @@ -557,7 +557,7 @@ static int wm8737_resume(struct snd_soc_codec *codec) static int wm8737_probe(struct snd_soc_codec *codec) { struct wm8737_priv *wm8737 = snd_soc_codec_get_drvdata(codec); - int ret, i; + int ret; ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8737->control_type); if (ret != 0) { @@ -565,16 +565,6 @@ static int wm8737_probe(struct snd_soc_codec *codec) return ret; } - for (i = 0; i < ARRAY_SIZE(wm8737->supplies); i++) - wm8737->supplies[i].supply = wm8737_supply_names[i]; - - ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8737->supplies), - wm8737->supplies); - if (ret != 0) { - dev_err(codec->dev, "Failed to request supplies: %d\n", ret); - return ret; - } - ret = regulator_bulk_enable(ARRAY_SIZE(wm8737->supplies), wm8737->supplies); if (ret != 0) { @@ -607,17 +597,12 @@ static int wm8737_probe(struct snd_soc_codec *codec) err_enable: regulator_bulk_disable(ARRAY_SIZE(wm8737->supplies), wm8737->supplies); err_get: - regulator_bulk_free(ARRAY_SIZE(wm8737->supplies), wm8737->supplies); - return ret; } static int wm8737_remove(struct snd_soc_codec *codec) { - struct wm8737_priv *wm8737 = snd_soc_codec_get_drvdata(codec); - wm8737_set_bias_level(codec, SND_SOC_BIAS_OFF); - regulator_bulk_free(ARRAY_SIZE(wm8737->supplies), wm8737->supplies); return 0; } @@ -645,13 +630,23 @@ static __devinit int wm8737_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { struct wm8737_priv *wm8737; - int ret; + int ret, i; wm8737 = devm_kzalloc(&i2c->dev, sizeof(struct wm8737_priv), GFP_KERNEL); if (wm8737 == NULL) return -ENOMEM; + for (i = 0; i < ARRAY_SIZE(wm8737->supplies); i++) + wm8737->supplies[i].supply = wm8737_supply_names[i]; + + ret = devm_regulator_bulk_get(&i2c->dev, ARRAY_SIZE(wm8737->supplies), + wm8737->supplies); + if (ret != 0) { + dev_err(&i2c->dev, "Failed to request supplies: %d\n", ret); + return ret; + } + i2c_set_clientdata(i2c, wm8737); wm8737->control_type = SND_SOC_I2C; @@ -691,13 +686,23 @@ static struct i2c_driver wm8737_i2c_driver = { static int __devinit wm8737_spi_probe(struct spi_device *spi) { struct wm8737_priv *wm8737; - int ret; + int ret, i; wm8737 = devm_kzalloc(&spi->dev, sizeof(struct wm8737_priv), GFP_KERNEL); if (wm8737 == NULL) return -ENOMEM; + for (i = 0; i < ARRAY_SIZE(wm8737->supplies); i++) + wm8737->supplies[i].supply = wm8737_supply_names[i]; + + ret = devm_regulator_bulk_get(&spi->dev, ARRAY_SIZE(wm8737->supplies), + wm8737->supplies); + if (ret != 0) { + dev_err(&spi->dev, "Failed to request supplies: %d\n", ret); + return ret; + } + wm8737->control_type = SND_SOC_SPI; spi_set_drvdata(spi, wm8737); -- cgit v1.2.3 From 3ef8ac0d7bd0532fbfb319f3fbf615538394119f Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 12 Sep 2012 12:48:48 +0800 Subject: ASoC: wm8737: Convert to direct regmap API usage Signed-off-by: Mark Brown --- sound/soc/codecs/wm8737.c | 75 +++++++++++++++++++++++++++++++---------------- 1 file changed, 50 insertions(+), 25 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/wm8737.c b/sound/soc/codecs/wm8737.c index 3bf5bc73e2de..5c9634f4c1f0 100644 --- a/sound/soc/codecs/wm8737.c +++ b/sound/soc/codecs/wm8737.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -40,29 +41,39 @@ static const char *wm8737_supply_names[WM8737_NUM_SUPPLIES] = { /* codec private data */ struct wm8737_priv { - enum snd_soc_control_type control_type; + struct regmap *regmap; struct regulator_bulk_data supplies[WM8737_NUM_SUPPLIES]; unsigned int mclk; }; -static const u16 wm8737_reg[WM8737_REGISTER_COUNT] = { - 0x00C3, /* R0 - Left PGA volume */ - 0x00C3, /* R1 - Right PGA volume */ - 0x0007, /* R2 - AUDIO path L */ - 0x0007, /* R3 - AUDIO path R */ - 0x0000, /* R4 - 3D Enhance */ - 0x0000, /* R5 - ADC Control */ - 0x0000, /* R6 - Power Management */ - 0x000A, /* R7 - Audio Format */ - 0x0000, /* R8 - Clocking */ - 0x000F, /* R9 - MIC Preamp Control */ - 0x0003, /* R10 - Misc Bias Control */ - 0x0000, /* R11 - Noise Gate */ - 0x007C, /* R12 - ALC1 */ - 0x0000, /* R13 - ALC2 */ - 0x0032, /* R14 - ALC3 */ +static const struct reg_default wm8737_reg_defaults[] = { + { 0, 0x00C3 }, /* R0 - Left PGA volume */ + { 1, 0x00C3 }, /* R1 - Right PGA volume */ + { 2, 0x0007 }, /* R2 - AUDIO path L */ + { 3, 0x0007 }, /* R3 - AUDIO path R */ + { 4, 0x0000 }, /* R4 - 3D Enhance */ + { 5, 0x0000 }, /* R5 - ADC Control */ + { 6, 0x0000 }, /* R6 - Power Management */ + { 7, 0x000A }, /* R7 - Audio Format */ + { 8, 0x0000 }, /* R8 - Clocking */ + { 9, 0x000F }, /* R9 - MIC Preamp Control */ + { 10, 0x0003 }, /* R10 - Misc Bias Control */ + { 11, 0x0000 }, /* R11 - Noise Gate */ + { 12, 0x007C }, /* R12 - ALC1 */ + { 13, 0x0000 }, /* R13 - ALC2 */ + { 14, 0x0032 }, /* R14 - ALC3 */ }; +static bool wm8737_volatile(struct device *dev, unsigned int reg) +{ + switch (reg) { + case WM8737_RESET: + return true; + default: + return false; + } +} + static int wm8737_reset(struct snd_soc_codec *codec) { return snd_soc_write(codec, WM8737_RESET, 0); @@ -479,7 +490,7 @@ static int wm8737_set_bias_level(struct snd_soc_codec *codec, return ret; } - snd_soc_cache_sync(codec); + regcache_sync(wm8737->regmap); /* Fast VMID ramp at 2*2.5k */ snd_soc_update_bits(codec, WM8737_MISC_BIAS_CONTROL, @@ -559,7 +570,7 @@ static int wm8737_probe(struct snd_soc_codec *codec) struct wm8737_priv *wm8737 = snd_soc_codec_get_drvdata(codec); int ret; - ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8737->control_type); + ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); if (ret != 0) { dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); return ret; @@ -612,10 +623,6 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8737 = { .suspend = wm8737_suspend, .resume = wm8737_resume, .set_bias_level = wm8737_set_bias_level, - - .reg_cache_size = WM8737_REGISTER_COUNT - 1, /* Skip reset */ - .reg_word_size = sizeof(u16), - .reg_cache_default = wm8737_reg, }; static const struct of_device_id wm8737_of_match[] = { @@ -625,6 +632,18 @@ static const struct of_device_id wm8737_of_match[] = { MODULE_DEVICE_TABLE(of, wm8737_of_match); +static const struct regmap_config wm8737_regmap = { + .reg_bits = 7, + .val_bits = 9, + .max_register = WM8737_MAX_REGISTER, + + .reg_defaults = wm8737_reg_defaults, + .num_reg_defaults = ARRAY_SIZE(wm8737_reg_defaults), + .cache_type = REGCACHE_RBTREE, + + .volatile_reg = wm8737_volatile, +}; + #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) static __devinit int wm8737_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) @@ -647,8 +666,11 @@ static __devinit int wm8737_i2c_probe(struct i2c_client *i2c, return ret; } + wm8737->regmap = devm_regmap_init_i2c(i2c, &wm8737_regmap); + if (IS_ERR(wm8737->regmap)) + return PTR_ERR(wm8737->regmap); + i2c_set_clientdata(i2c, wm8737); - wm8737->control_type = SND_SOC_I2C; ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_wm8737, &wm8737_dai, 1); @@ -703,7 +725,10 @@ static int __devinit wm8737_spi_probe(struct spi_device *spi) return ret; } - wm8737->control_type = SND_SOC_SPI; + wm8737->regmap = devm_regmap_init_spi(spi, &wm8737_regmap); + if (IS_ERR(wm8737->regmap)) + return PTR_ERR(wm8737->regmap); + spi_set_drvdata(spi, wm8737); ret = snd_soc_register_codec(&spi->dev, -- cgit v1.2.3 From 6b315958d330d3ebf46b7d45e0978a97be2c4ac0 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 12 Sep 2012 18:44:40 +0800 Subject: ASoC: arizona: Clarify logging for FLL lock status interrupt Signed-off-by: Mark Brown --- sound/soc/codecs/arizona.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/arizona.c b/sound/soc/codecs/arizona.c index 5e96a0a1669c..b79578e7e10c 100644 --- a/sound/soc/codecs/arizona.c +++ b/sound/soc/codecs/arizona.c @@ -732,7 +732,7 @@ static irqreturn_t arizona_fll_lock(int irq, void *data) { struct arizona_fll *fll = data; - arizona_fll_dbg(fll, "Locked\n"); + arizona_fll_dbg(fll, "Lock status changed\n"); complete(&fll->lock); -- cgit v1.2.3 From da8b8e0f15b375b44ed8ef4b0c5f5f60f19ccb37 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 12 Sep 2012 12:21:52 +0800 Subject: ASoC: core: Mark regmap CODEC register maps as dirty when suspending The core has for a long time had support for marking the register maps of devices dirty when suspending so that they are resynced on resume. Also implement this feature for CODECs using regmap. Signed-off-by: Mark Brown Acked-by: Liam Girdwood --- sound/soc/soc-core.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'sound/soc') diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index ad65459da28e..2b418398ec18 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -635,6 +635,8 @@ int snd_soc_suspend(struct device *dev) codec->driver->suspend(codec); codec->suspended = 1; codec->cache_sync = 1; + if (codec->using_regmap) + regcache_mark_dirty(codec->control_data); break; default: dev_dbg(codec->dev, "CODEC is on over suspend\n"); -- cgit v1.2.3 From ab7af5c8d456103ea57c7e9e6f5b03162965e665 Mon Sep 17 00:00:00 2001 From: Peter Senna Tschudin Date: Wed, 12 Sep 2012 17:06:46 +0200 Subject: ASoC: core: Remove useless kfree Remove useless kfree() and clean up code related to the removal. The semantic patch that finds this problem is as follows: (http://coccinelle.lip6.fr/) // @r exists@ position p1,p2; expression x; @@ if (x@p1 == NULL) { ... kfree@p2(x); ... return ...; } @unchanged exists@ position r.p1,r.p2; expression e <= r.x,x,e1; iterator I; statement S; @@ if (x@p1 == NULL) { ... when != I(x,...) S when != e = e1 when != e += e1 when != e -= e1 when != ++e when != --e when != e++ when != e-- when != &e kfree@p2(x); ... return ...; } @ok depends on unchanged exists@ position any r.p1; position r.p2; expression x; @@ ... when != true x@p1 == NULL kfree@p2(x); @depends on !ok && unchanged@ position r.p2; expression x; @@ *kfree@p2(x); // Signed-off-by: Peter Senna Tschudin Signed-off-by: Mark Brown --- sound/soc/soc-core.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 2b418398ec18..e5b0713e6f3c 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -4054,8 +4054,6 @@ int snd_soc_register_codec(struct device *dev, return 0; fail: - kfree(codec->reg_def_copy); - codec->reg_def_copy = NULL; kfree(codec->name); kfree(codec); return ret; -- cgit v1.2.3 From 040242ccfcd4ae878267b521d16539e7b3000527 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Thu, 13 Sep 2012 12:03:23 +0200 Subject: ASoC: ad193x: Use managed regmap init Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/codecs/ad193x.c | 50 ++++++++++------------------------------------- 1 file changed, 10 insertions(+), 40 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/ad193x.c b/sound/soc/codecs/ad193x.c index 13e62be4f990..2f752660f678 100644 --- a/sound/soc/codecs/ad193x.c +++ b/sound/soc/codecs/ad193x.c @@ -381,40 +381,25 @@ static const struct regmap_config ad193x_spi_regmap_config = { static int __devinit ad193x_spi_probe(struct spi_device *spi) { struct ad193x_priv *ad193x; - int ret; ad193x = devm_kzalloc(&spi->dev, sizeof(struct ad193x_priv), GFP_KERNEL); if (ad193x == NULL) return -ENOMEM; - ad193x->regmap = regmap_init_spi(spi, &ad193x_spi_regmap_config); - if (IS_ERR(ad193x->regmap)) { - ret = PTR_ERR(ad193x->regmap); - goto err_out; - } + ad193x->regmap = devm_regmap_init_spi(spi, &ad193x_spi_regmap_config); + if (IS_ERR(ad193x->regmap)) + return PTR_ERR(ad193x->regmap); spi_set_drvdata(spi, ad193x); - ret = snd_soc_register_codec(&spi->dev, - &soc_codec_dev_ad193x, &ad193x_dai, 1); - if (ret < 0) - goto err_regmap_exit; - - return 0; - -err_regmap_exit: - regmap_exit(ad193x->regmap); -err_out: - return ret; + return snd_soc_register_codec(&spi->dev, &soc_codec_dev_ad193x, + &ad193x_dai, 1); } static int __devexit ad193x_spi_remove(struct spi_device *spi) { - struct ad193x_priv *ad193x = spi_get_drvdata(spi); - snd_soc_unregister_codec(&spi->dev); - regmap_exit(ad193x->regmap); return 0; } @@ -449,40 +434,25 @@ static int __devinit ad193x_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct ad193x_priv *ad193x; - int ret; ad193x = devm_kzalloc(&client->dev, sizeof(struct ad193x_priv), GFP_KERNEL); if (ad193x == NULL) return -ENOMEM; - ad193x->regmap = regmap_init_i2c(client, &ad193x_i2c_regmap_config); - if (IS_ERR(ad193x->regmap)) { - ret = PTR_ERR(ad193x->regmap); - goto err_out; - } + ad193x->regmap = devm_regmap_init_i2c(client, &ad193x_i2c_regmap_config); + if (IS_ERR(ad193x->regmap)) + return PTR_ERR(ad193x->regmap); i2c_set_clientdata(client, ad193x); - ret = snd_soc_register_codec(&client->dev, - &soc_codec_dev_ad193x, &ad193x_dai, 1); - if (ret < 0) - goto err_regmap_exit; - - return 0; - -err_regmap_exit: - regmap_exit(ad193x->regmap); -err_out: - return ret; + return snd_soc_register_codec(&client->dev, &soc_codec_dev_ad193x, + &ad193x_dai, 1); } static int __devexit ad193x_i2c_remove(struct i2c_client *client) { - struct ad193x_priv *ad193x = i2c_get_clientdata(client); - snd_soc_unregister_codec(&client->dev); - regmap_exit(ad193x->regmap); return 0; } -- cgit v1.2.3 From 7f22fd9c03c0b67ee6aa138bd10ae91bb0d22151 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Thu, 13 Sep 2012 12:04:51 +0200 Subject: ASoC: ad1836: Convert to direct regmap usage. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/codecs/ad1836.c | 76 +++++++++++++++++++++++++++++++++-------------- 1 file changed, 53 insertions(+), 23 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/ad1836.c b/sound/soc/codecs/ad1836.c index ae1eb51bc9da..dce6ebeef452 100644 --- a/sound/soc/codecs/ad1836.c +++ b/sound/soc/codecs/ad1836.c @@ -19,6 +19,8 @@ #include #include #include +#include + #include "ad1836.h" enum ad1836_type { @@ -30,6 +32,7 @@ enum ad1836_type { /* codec private data */ struct ad1836_priv { enum ad1836_type type; + struct regmap *regmap; }; /* @@ -161,8 +164,8 @@ static int ad1836_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { + struct ad1836_priv *ad1836 = snd_soc_codec_get_drvdata(dai->codec); int word_len = 0; - struct snd_soc_codec *codec = dai->codec; /* bit size */ switch (params_format(params)) { @@ -178,10 +181,12 @@ static int ad1836_hw_params(struct snd_pcm_substream *substream, break; } - snd_soc_update_bits(codec, AD1836_DAC_CTRL1, AD1836_DAC_WORD_LEN_MASK, + regmap_update_bits(ad1836->regmap, AD1836_DAC_CTRL1, + AD1836_DAC_WORD_LEN_MASK, word_len << AD1836_DAC_WORD_LEN_OFFSET); - snd_soc_update_bits(codec, AD1836_ADC_CTRL2, AD1836_ADC_WORD_LEN_MASK, + regmap_update_bits(ad1836->regmap, AD1836_ADC_CTRL2, + AD1836_ADC_WORD_LEN_MASK, word_len << AD1836_ADC_WORD_OFFSET); return 0; @@ -223,15 +228,17 @@ static struct snd_soc_dai_driver ad183x_dais[] = { #ifdef CONFIG_PM static int ad1836_suspend(struct snd_soc_codec *codec) { + struct ad1836_priv *ad1836 = snd_soc_codec_get_drvdata(codec); /* reset clock control mode */ - return snd_soc_update_bits(codec, AD1836_ADC_CTRL2, + return regmap_update_bits(ad1836->regmap, AD1836_ADC_CTRL2, AD1836_ADC_SERFMT_MASK, 0); } static int ad1836_resume(struct snd_soc_codec *codec) { + struct ad1836_priv *ad1836 = snd_soc_codec_get_drvdata(codec); /* restore clock control mode */ - return snd_soc_update_bits(codec, AD1836_ADC_CTRL2, + return regmap_update_bits(ad1836->regmap, AD1836_ADC_CTRL2, AD1836_ADC_SERFMT_MASK, AD1836_ADC_AUX); } #else @@ -250,37 +257,30 @@ static int ad1836_probe(struct snd_soc_codec *codec) num_dacs = ad183x_dais[ad1836->type].playback.channels_max / 2; num_adcs = ad183x_dais[ad1836->type].capture.channels_max / 2; - ret = snd_soc_codec_set_cache_io(codec, 4, 12, SND_SOC_SPI); - if (ret < 0) { - dev_err(codec->dev, "failed to set cache I/O: %d\n", - ret); - return ret; - } - /* default setting for ad1836 */ /* de-emphasis: 48kHz, power-on dac */ - snd_soc_write(codec, AD1836_DAC_CTRL1, 0x300); + regmap_write(ad1836->regmap, AD1836_DAC_CTRL1, 0x300); /* unmute dac channels */ - snd_soc_write(codec, AD1836_DAC_CTRL2, 0x0); + regmap_write(ad1836->regmap, AD1836_DAC_CTRL2, 0x0); /* high-pass filter enable, power-on adc */ - snd_soc_write(codec, AD1836_ADC_CTRL1, 0x100); + regmap_write(ad1836->regmap, AD1836_ADC_CTRL1, 0x100); /* unmute adc channles, adc aux mode */ - snd_soc_write(codec, AD1836_ADC_CTRL2, 0x180); + regmap_write(ad1836->regmap, AD1836_ADC_CTRL2, 0x180); /* volume */ for (i = 1; i <= num_dacs; ++i) { - snd_soc_write(codec, AD1836_DAC_L_VOL(i), 0x3FF); - snd_soc_write(codec, AD1836_DAC_R_VOL(i), 0x3FF); + regmap_write(ad1836->regmap, AD1836_DAC_L_VOL(i), 0x3FF); + regmap_write(ad1836->regmap, AD1836_DAC_R_VOL(i), 0x3FF); } if (ad1836->type == AD1836) { /* left/right diff:PGA/MUX */ - snd_soc_write(codec, AD1836_ADC_CTRL3, 0x3A); + regmap_write(ad1836->regmap, AD1836_ADC_CTRL3, 0x3A); ret = snd_soc_add_codec_controls(codec, ad1836_controls, ARRAY_SIZE(ad1836_controls)); if (ret) return ret; } else { - snd_soc_write(codec, AD1836_ADC_CTRL3, 0x00); + regmap_write(ad1836->regmap, AD1836_ADC_CTRL3, 0x00); } ret = snd_soc_add_codec_controls(codec, ad183x_dac_controls, num_dacs * 2); @@ -313,8 +313,9 @@ static int ad1836_probe(struct snd_soc_codec *codec) /* power down chip */ static int ad1836_remove(struct snd_soc_codec *codec) { + struct ad1836_priv *ad1836 = snd_soc_codec_get_drvdata(codec); /* reset clock control mode */ - return snd_soc_update_bits(codec, AD1836_ADC_CTRL2, + return regmap_update_bits(ad1836->regmap, AD1836_ADC_CTRL2, AD1836_ADC_SERFMT_MASK, 0); } @@ -323,8 +324,6 @@ static struct snd_soc_codec_driver soc_codec_dev_ad1836 = { .remove = ad1836_remove, .suspend = ad1836_suspend, .resume = ad1836_resume, - .reg_cache_size = AD1836_NUM_REGS, - .reg_word_size = sizeof(u16), .controls = ad183x_controls, .num_controls = ARRAY_SIZE(ad183x_controls), @@ -334,6 +333,33 @@ static struct snd_soc_codec_driver soc_codec_dev_ad1836 = { .num_dapm_routes = ARRAY_SIZE(ad183x_dapm_routes), }; +static const struct reg_default ad1836_reg_defaults[] = { + { AD1836_DAC_CTRL1, 0x0000 }, + { AD1836_DAC_CTRL2, 0x0000 }, + { AD1836_DAC_L_VOL(0), 0x0000 }, + { AD1836_DAC_R_VOL(0), 0x0000 }, + { AD1836_DAC_L_VOL(1), 0x0000 }, + { AD1836_DAC_R_VOL(1), 0x0000 }, + { AD1836_DAC_L_VOL(2), 0x0000 }, + { AD1836_DAC_R_VOL(2), 0x0000 }, + { AD1836_DAC_L_VOL(3), 0x0000 }, + { AD1836_DAC_R_VOL(3), 0x0000 }, + { AD1836_ADC_CTRL1, 0x0000 }, + { AD1836_ADC_CTRL2, 0x0000 }, + { AD1836_ADC_CTRL3, 0x0000 }, +}; + +static const struct regmap_config ad1836_regmap_config = { + .val_bits = 12, + .reg_bits = 4, + .read_flag_mask = 0x08, + + .max_register = AD1836_ADC_CTRL3, + .reg_defaults = ad1836_reg_defaults, + .num_reg_defaults = ARRAY_SIZE(ad1836_reg_defaults), + .cache_type = REGCACHE_RBTREE, +}; + static int __devinit ad1836_spi_probe(struct spi_device *spi) { struct ad1836_priv *ad1836; @@ -344,6 +370,10 @@ static int __devinit ad1836_spi_probe(struct spi_device *spi) if (ad1836 == NULL) return -ENOMEM; + ad1836->regmap = devm_regmap_init_spi(spi, &ad1836_regmap_config); + if (IS_ERR(ad1836->regmap)) + return PTR_ERR(ad1836->regmap); + ad1836->type = spi_get_device_id(spi)->driver_data; spi_set_drvdata(spi, ad1836); -- cgit v1.2.3 From d41789b2660e5b18b8401bf83ebcd502916c2cb5 Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Mon, 17 Sep 2012 13:34:31 +0800 Subject: ASoC: mx27vis: retrieve gpio numbers from platform_data Rather than including mach/iomux-mx27.h to define gpio numbers and set up the pins, the patch moves all these into machine code and has the gpio numbers passed to driver via platform_data. As the result, we can remove the mach/iomux-mx27.h inclusion from driver. Signed-off-by: Shawn Guo Acked-by: Javier Martin Signed-off-by: Mark Brown --- arch/arm/mach-imx/mach-imx27_visstrim_m10.c | 42 ++++++++++++++++++++++++++++- include/linux/platform_data/asoc-mx27vis.h | 11 ++++++++ sound/soc/fsl/mx27vis-aic32x4.c | 42 ++++++++++++++--------------- 3 files changed, 72 insertions(+), 23 deletions(-) create mode 100644 include/linux/platform_data/asoc-mx27vis.h (limited to 'sound/soc') diff --git a/arch/arm/mach-imx/mach-imx27_visstrim_m10.c b/arch/arm/mach-imx/mach-imx27_visstrim_m10.c index f264ddddd47c..562722959666 100644 --- a/arch/arm/mach-imx/mach-imx27_visstrim_m10.c +++ b/arch/arm/mach-imx/mach-imx27_visstrim_m10.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -58,6 +59,11 @@ #define EXPBOARD_BIT1 (GPIO_PORTD + 27) #define EXPBOARD_BIT0 (GPIO_PORTD + 28) +#define AMP_GAIN_0 (GPIO_PORTF + 9) +#define AMP_GAIN_1 (GPIO_PORTF + 8) +#define AMP_MUTE_SDL (GPIO_PORTE + 5) +#define AMP_MUTE_SDR (GPIO_PORTF + 7) + static const int visstrim_m10_pins[] __initconst = { /* UART1 (console) */ PE12_PF_UART1_TXD, @@ -139,6 +145,11 @@ static const int visstrim_m10_pins[] __initconst = { EXPBOARD_BIT2 | GPIO_GPIO | GPIO_IN | GPIO_PUEN, EXPBOARD_BIT1 | GPIO_GPIO | GPIO_IN | GPIO_PUEN, EXPBOARD_BIT0 | GPIO_GPIO | GPIO_IN | GPIO_PUEN, + /* Audio AMP control */ + AMP_GAIN_0 | GPIO_GPIO | GPIO_OUT, + AMP_GAIN_1 | GPIO_GPIO | GPIO_OUT, + AMP_MUTE_SDL | GPIO_GPIO | GPIO_OUT, + AMP_MUTE_SDR | GPIO_GPIO | GPIO_OUT, }; static struct gpio visstrim_m10_version_gpios[] = { @@ -166,6 +177,26 @@ static const struct gpio visstrim_m10_gpios[] __initconst = { .flags = GPIOF_DIR_OUT | GPIOF_INIT_LOW, .label = "usbotg_cs", }, + { + .gpio = AMP_GAIN_0, + .flags = GPIOF_DIR_OUT, + .label = "amp-gain-0", + }, + { + .gpio = AMP_GAIN_1, + .flags = GPIOF_DIR_OUT, + .label = "amp-gain-1", + }, + { + .gpio = AMP_MUTE_SDL, + .flags = GPIOF_DIR_OUT, + .label = "amp-mute-sdl", + }, + { + .gpio = AMP_MUTE_SDR, + .flags = GPIOF_DIR_OUT, + .label = "amp-mute-sdr", + }, }; /* Camera */ @@ -405,6 +436,14 @@ static const struct imx_ssi_platform_data visstrim_m10_ssi_pdata __initconst = { .flags = IMX_SSI_DMA | IMX_SSI_SYN, }; +/* Audio */ +static const struct snd_mx27vis_platform_data snd_mx27vis_pdata __initconst = { + .amp_gain0_gpio = AMP_GAIN_0, + .amp_gain1_gpio = AMP_GAIN_1, + .amp_mutel_gpio = AMP_MUTE_SDL, + .amp_muter_gpio = AMP_MUTE_SDR, +}; + static void __init visstrim_m10_revision(void) { int exp_version = 0; @@ -463,7 +502,8 @@ static void __init visstrim_m10_board_init(void) imx27_add_fec(NULL); imx_add_gpio_keys(&visstrim_gpio_keys_platform_data); platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices)); - imx_add_platform_device("mx27vis", 0, NULL, 0, NULL, 0); + imx_add_platform_device("mx27vis", 0, NULL, 0, &snd_mx27vis_pdata, + sizeof(snd_mx27vis_pdata)); platform_device_register_resndata(NULL, "soc-camera-pdrv", 0, NULL, 0, &iclink_tvp5150, sizeof(iclink_tvp5150)); gpio_led_register_device(0, &visstrim_m10_led_data); diff --git a/include/linux/platform_data/asoc-mx27vis.h b/include/linux/platform_data/asoc-mx27vis.h new file mode 100644 index 000000000000..409adcd04d04 --- /dev/null +++ b/include/linux/platform_data/asoc-mx27vis.h @@ -0,0 +1,11 @@ +#ifndef __PLATFORM_DATA_ASOC_MX27VIS_H +#define __PLATFORM_DATA_ASOC_MX27VIS_H + +struct snd_mx27vis_platform_data { + int amp_gain0_gpio; + int amp_gain1_gpio; + int amp_mutel_gpio; + int amp_muter_gpio; +}; + +#endif /* __PLATFORM_DATA_ASOC_MX27VIS_H */ diff --git a/sound/soc/fsl/mx27vis-aic32x4.c b/sound/soc/fsl/mx27vis-aic32x4.c index f6d04ad4bb39..2b76877b1789 100644 --- a/sound/soc/fsl/mx27vis-aic32x4.c +++ b/sound/soc/fsl/mx27vis-aic32x4.c @@ -26,13 +26,13 @@ #include #include #include +#include #include #include #include #include #include #include -#include #include "../codecs/tlv320aic32x4.h" #include "imx-ssi.h" @@ -41,20 +41,12 @@ #define MX27VIS_AMP_GAIN 0 #define MX27VIS_AMP_MUTE 1 -#define MX27VIS_PIN_G0 (GPIO_PORTF + 9) -#define MX27VIS_PIN_G1 (GPIO_PORTF + 8) -#define MX27VIS_PIN_SDL (GPIO_PORTE + 5) -#define MX27VIS_PIN_SDR (GPIO_PORTF + 7) - static int mx27vis_amp_gain; static int mx27vis_amp_mute; - -static const int mx27vis_amp_pins[] = { - MX27VIS_PIN_G0 | GPIO_GPIO | GPIO_OUT, - MX27VIS_PIN_G1 | GPIO_GPIO | GPIO_OUT, - MX27VIS_PIN_SDL | GPIO_GPIO | GPIO_OUT, - MX27VIS_PIN_SDR | GPIO_GPIO | GPIO_OUT, -}; +static int mx27vis_amp_gain0_gpio; +static int mx27vis_amp_gain1_gpio; +static int mx27vis_amp_mutel_gpio; +static int mx27vis_amp_muter_gpio; static int mx27vis_aic32x4_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) @@ -109,13 +101,13 @@ static int mx27vis_amp_set(struct snd_kcontrol *kcontrol, switch (reg) { case MX27VIS_AMP_GAIN: - gpio_set_value(MX27VIS_PIN_G0, value & 1); - gpio_set_value(MX27VIS_PIN_G1, value >> 1); + gpio_set_value(mx27vis_amp_gain0_gpio, value & 1); + gpio_set_value(mx27vis_amp_gain1_gpio, value >> 1); mx27vis_amp_gain = value; break; case MX27VIS_AMP_MUTE: - gpio_set_value(MX27VIS_PIN_SDL, value & 1); - gpio_set_value(MX27VIS_PIN_SDR, value >> 1); + gpio_set_value(mx27vis_amp_mutel_gpio, value & 1); + gpio_set_value(mx27vis_amp_muter_gpio, value >> 1); mx27vis_amp_mute = value; break; } @@ -190,8 +182,19 @@ static struct snd_soc_card mx27vis_aic32x4 = { static int __devinit mx27vis_aic32x4_probe(struct platform_device *pdev) { + struct snd_mx27vis_platform_data *pdata = pdev->dev.platform_data; int ret; + if (!pdata) { + dev_err(&pdev->dev, "No platform data supplied\n"); + return -EINVAL; + } + + mx27vis_amp_gain0_gpio = pdata->amp_gain0_gpio; + mx27vis_amp_gain1_gpio = pdata->amp_gain1_gpio; + mx27vis_amp_mutel_gpio = pdata->amp_mutel_gpio; + mx27vis_amp_muter_gpio = pdata->amp_muter_gpio; + mx27vis_aic32x4.dev = &pdev->dev; ret = snd_soc_register_card(&mx27vis_aic32x4); if (ret) { @@ -213,11 +216,6 @@ static int __devinit mx27vis_aic32x4_probe(struct platform_device *pdev) IMX_AUDMUX_V1_PCR_RXDSEL(MX27_AUDMUX_HPCR1_SSI0) ); - ret = mxc_gpio_setup_multiple_pins(mx27vis_amp_pins, - ARRAY_SIZE(mx27vis_amp_pins), "MX27VIS_AMP"); - if (ret) - printk(KERN_ERR "ASoC: unable to setup gpios\n"); - return ret; } -- cgit v1.2.3 From 13c57e5b868b4f023f6436d8c6a079eaffd7f3a8 Mon Sep 17 00:00:00 2001 From: Timur Tabi Date: Fri, 14 Sep 2012 16:14:34 -0500 Subject: ASoC: fsl: use snd_soc_register_card to register the card Use snd_soc_register_card() instead of platform_device_alloc("soc-audio") to register the sound card from the machine drivers. The use of platform_device_alloc is deprecated. Although several other drivers still use platform_device_alloc(), the Freescale drivers were not using it to pass driver data. Instead of fixing the driver data usage, it's better to replace the deprecated code. Signed-off-by: Timur Tabi Signed-off-by: Mark Brown --- sound/soc/fsl/mpc8610_hpcd.c | 32 +++++++------------------------- sound/soc/fsl/p1022_ds.c | 31 ++++++------------------------- 2 files changed, 13 insertions(+), 50 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/fsl/mpc8610_hpcd.c b/sound/soc/fsl/mpc8610_hpcd.c index 60bcba1bc30e..9ff9318c52b9 100644 --- a/sound/soc/fsl/mpc8610_hpcd.c +++ b/sound/soc/fsl/mpc8610_hpcd.c @@ -192,7 +192,6 @@ static int mpc8610_hpcd_probe(struct platform_device *pdev) container_of(dev, struct platform_device, dev); struct device_node *np = ssi_pdev->dev.of_node; struct device_node *codec_np = NULL; - struct platform_device *sound_device = NULL; struct mpc8610_hpcd_data *machine_data; int ret = -ENODEV; const char *sprop; @@ -341,34 +340,22 @@ static int mpc8610_hpcd_probe(struct platform_device *pdev) machine_data->card.probe = mpc8610_hpcd_machine_probe; machine_data->card.remove = mpc8610_hpcd_machine_remove; machine_data->card.name = pdev->name; /* The platform driver name */ + machine_data->card.owner = THIS_MODULE; + machine_data->card.dev = &pdev->dev; machine_data->card.num_links = 2; machine_data->card.dai_link = machine_data->dai; - /* Allocate a new audio platform device structure */ - sound_device = platform_device_alloc("soc-audio", -1); - if (!sound_device) { - dev_err(&pdev->dev, "platform device alloc failed\n"); - ret = -ENOMEM; - goto error; - } - - /* Associate the card data with the sound device */ - platform_set_drvdata(sound_device, &machine_data->card); - /* Register with ASoC */ - ret = platform_device_add(sound_device); + ret = snd_soc_register_card(&machine_data->card); if (ret) { - dev_err(&pdev->dev, "platform device add failed\n"); - goto error_sound; + dev_err(&pdev->dev, "could not register card\n"); + goto error; } - dev_set_drvdata(&pdev->dev, sound_device); of_node_put(codec_np); return 0; -error_sound: - platform_device_put(sound_device); error: kfree(machine_data); error_alloc: @@ -383,17 +370,12 @@ error_alloc: */ static int __devexit mpc8610_hpcd_remove(struct platform_device *pdev) { - struct platform_device *sound_device = dev_get_drvdata(&pdev->dev); - struct snd_soc_card *card = platform_get_drvdata(sound_device); + struct snd_soc_card *card = platform_get_drvdata(pdev); struct mpc8610_hpcd_data *machine_data = container_of(card, struct mpc8610_hpcd_data, card); - platform_device_unregister(sound_device); - + snd_soc_unregister_card(card); kfree(machine_data); - sound_device->dev.platform_data = NULL; - - dev_set_drvdata(&pdev->dev, NULL); return 0; } diff --git a/sound/soc/fsl/p1022_ds.c b/sound/soc/fsl/p1022_ds.c index 50adf4032bcc..144d49603637 100644 --- a/sound/soc/fsl/p1022_ds.c +++ b/sound/soc/fsl/p1022_ds.c @@ -202,7 +202,6 @@ static int p1022_ds_probe(struct platform_device *pdev) container_of(dev, struct platform_device, dev); struct device_node *np = ssi_pdev->dev.of_node; struct device_node *codec_np = NULL; - struct platform_device *sound_device = NULL; struct machine_data *mdata; int ret = -ENODEV; const char *sprop; @@ -349,36 +348,23 @@ static int p1022_ds_probe(struct platform_device *pdev) mdata->card.probe = p1022_ds_machine_probe; mdata->card.remove = p1022_ds_machine_remove; mdata->card.name = pdev->name; /* The platform driver name */ + mdata->card.owner = THIS_MODULE; + mdata->card.dev = &pdev->dev; mdata->card.num_links = 2; mdata->card.dai_link = mdata->dai; - /* Allocate a new audio platform device structure */ - sound_device = platform_device_alloc("soc-audio", -1); - if (!sound_device) { - dev_err(&pdev->dev, "platform device alloc failed\n"); - ret = -ENOMEM; - goto error; - } - - /* Associate the card data with the sound device */ - platform_set_drvdata(sound_device, &mdata->card); - /* Register with ASoC */ - ret = platform_device_add(sound_device); + ret = snd_soc_register_card(&mdata->card); if (ret) { - dev_err(&pdev->dev, "platform device add failed\n"); + dev_err(&pdev->dev, "could not register card\n"); goto error; } - dev_set_drvdata(&pdev->dev, sound_device); of_node_put(codec_np); return 0; error: - if (sound_device) - platform_device_put(sound_device); - kfree(mdata); error_put: of_node_put(codec_np); @@ -392,17 +378,12 @@ error_put: */ static int __devexit p1022_ds_remove(struct platform_device *pdev) { - struct platform_device *sound_device = dev_get_drvdata(&pdev->dev); - struct snd_soc_card *card = platform_get_drvdata(sound_device); + struct snd_soc_card *card = platform_get_drvdata(pdev); struct machine_data *mdata = container_of(card, struct machine_data, card); - platform_device_unregister(sound_device); - + snd_soc_unregister_card(card); kfree(mdata); - sound_device->dev.platform_data = NULL; - - dev_set_drvdata(&pdev->dev, NULL); return 0; } -- cgit v1.2.3 From d55438beb2329493cb54df5175d83be65a8d5100 Mon Sep 17 00:00:00 2001 From: Timur Tabi Date: Fri, 14 Sep 2012 16:14:36 -0500 Subject: ASoC: fsl: remove unnecessary call to dma_unmap_single Remove a call to dma_unmap_single() from the PowerPC ASoC DMA driver. The buffer is allocated and not actually mapped, so the unmap call doesn't make sense. It was probably left over from some early version of the driver. This bug was unnoticed for so long because the DMA mapping functions normally don't do anything on PowerPC. Signed-off-by: Timur Tabi Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_dma.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/fsl/fsl_dma.c b/sound/soc/fsl/fsl_dma.c index 96bb92dd174c..6feb26500580 100644 --- a/sound/soc/fsl/fsl_dma.c +++ b/sound/soc/fsl/fsl_dma.c @@ -823,12 +823,6 @@ static int fsl_dma_close(struct snd_pcm_substream *substream) if (dma_private->irq) free_irq(dma_private->irq, dma_private); - if (dma_private->ld_buf_phys) { - dma_unmap_single(dev, dma_private->ld_buf_phys, - sizeof(dma_private->link), - DMA_TO_DEVICE); - } - /* Deallocate the fsl_dma_private structure */ dma_free_coherent(dev, sizeof(struct fsl_dma_private), dma_private, dma_private->ld_buf_phys); -- cgit v1.2.3 From 4c2474c007867c102c96482f3bacb1fdf209958c Mon Sep 17 00:00:00 2001 From: Timur Tabi Date: Fri, 14 Sep 2012 16:14:37 -0500 Subject: ASoC: wm8960: add support for big-endian audio samples PowerPC ASoC drivers frequently use the _BE variants of the SNDRV_PCM_FORMAT macros, so we need to look for those as well. Signed-off-by: Timur Tabi Signed-off-by: Mark Brown --- sound/soc/codecs/wm8960.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/wm8960.c b/sound/soc/codecs/wm8960.c index 7cb0d07ca8a6..066250e3f7f4 100644 --- a/sound/soc/codecs/wm8960.c +++ b/sound/soc/codecs/wm8960.c @@ -557,18 +557,25 @@ static int wm8960_hw_params(struct snd_pcm_substream *substream, struct snd_soc_codec *codec = dai->codec; struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec); u16 iface = snd_soc_read(codec, WM8960_IFACE1) & 0xfff3; + snd_pcm_format_t format = params_format(params); int i; /* bit size */ - switch (params_format(params)) { + switch (format) { case SNDRV_PCM_FORMAT_S16_LE: + case SNDRV_PCM_FORMAT_S16_BE: break; case SNDRV_PCM_FORMAT_S20_3LE: + case SNDRV_PCM_FORMAT_S20_3BE: iface |= 0x0004; break; case SNDRV_PCM_FORMAT_S24_LE: + case SNDRV_PCM_FORMAT_S24_BE: iface |= 0x0008; break; + default: + dev_err(codec->dev, "unsupported format %i\n", format); + return -EINVAL; } /* Update filters for the new rate */ -- cgit v1.2.3 From 86767b7d5b3cdbd105e7d7066d671b52aa208188 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Fri, 14 Sep 2012 13:57:27 +0200 Subject: ASoC: Avoid recalculating the bitmask for SOC_ENUM controls For ENUM controls the bitmask is calculated based on the number of items. Currently this is done each time the control is accessed. And while the performance impact of this should be negligible we can easily do better. The roundup_pow_of_two macro performs the same calculation which is currently done manually, but it is also possible to use this macro with compile time constants and so it can be used to initialize static data. So we can use it to initialize the mask field of a ENUM control during its declaration. Signed-off-by: Lars-Peter Clausen Acked-by: Peter Ujfalusi Signed-off-by: Mark Brown --- include/sound/soc.h | 4 +++- sound/soc/codecs/twl4030.c | 8 +++----- sound/soc/soc-core.c | 16 ++++++---------- sound/soc/soc-dapm.c | 22 ++++++++-------------- 4 files changed, 20 insertions(+), 30 deletions(-) (limited to 'sound/soc') diff --git a/include/sound/soc.h b/include/sound/soc.h index 313b7660562c..91244a096c19 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -160,7 +161,8 @@ .platform_max = xmax} } #define SOC_ENUM_DOUBLE(xreg, xshift_l, xshift_r, xmax, xtexts) \ { .reg = xreg, .shift_l = xshift_l, .shift_r = xshift_r, \ - .max = xmax, .texts = xtexts } + .max = xmax, .texts = xtexts, \ + .mask = xmax ? roundup_pow_of_two(xmax) - 1 : 0} #define SOC_ENUM_SINGLE(xreg, xshift, xmax, xtexts) \ SOC_ENUM_DOUBLE(xreg, xshift, xshift, xmax, xtexts) #define SOC_ENUM_SINGLE_EXT(xmax, xtexts) \ diff --git a/sound/soc/codecs/twl4030.c b/sound/soc/codecs/twl4030.c index 391fcfc7b63b..2548f5c56885 100644 --- a/sound/soc/codecs/twl4030.c +++ b/sound/soc/codecs/twl4030.c @@ -999,7 +999,7 @@ static int snd_soc_put_twl4030_opmode_enum_double(struct snd_kcontrol *kcontrol, struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec); struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; unsigned short val; - unsigned short mask, bitmask; + unsigned short mask; if (twl4030->configured) { dev_err(codec->dev, @@ -1007,18 +1007,16 @@ static int snd_soc_put_twl4030_opmode_enum_double(struct snd_kcontrol *kcontrol, return -EBUSY; } - for (bitmask = 1; bitmask < e->max; bitmask <<= 1) - ; if (ucontrol->value.enumerated.item[0] > e->max - 1) return -EINVAL; val = ucontrol->value.enumerated.item[0] << e->shift_l; - mask = (bitmask - 1) << e->shift_l; + mask = e->mask << e->shift_l; if (e->shift_l != e->shift_r) { if (ucontrol->value.enumerated.item[1] > e->max - 1) return -EINVAL; val |= ucontrol->value.enumerated.item[1] << e->shift_r; - mask |= (bitmask - 1) << e->shift_r; + mask |= e->mask << e->shift_r; } return snd_soc_update_bits(codec, e->reg, mask, val); diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index e5b0713e6f3c..9a6daf997319 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -2413,16 +2413,14 @@ int snd_soc_get_enum_double(struct snd_kcontrol *kcontrol, { struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; - unsigned int val, bitmask; + unsigned int val; - for (bitmask = 1; bitmask < e->max; bitmask <<= 1) - ; val = snd_soc_read(codec, e->reg); ucontrol->value.enumerated.item[0] - = (val >> e->shift_l) & (bitmask - 1); + = (val >> e->shift_l) & e->mask; if (e->shift_l != e->shift_r) ucontrol->value.enumerated.item[1] = - (val >> e->shift_r) & (bitmask - 1); + (val >> e->shift_r) & e->mask; return 0; } @@ -2443,19 +2441,17 @@ int snd_soc_put_enum_double(struct snd_kcontrol *kcontrol, struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; unsigned int val; - unsigned int mask, bitmask; + unsigned int mask; - for (bitmask = 1; bitmask < e->max; bitmask <<= 1) - ; if (ucontrol->value.enumerated.item[0] > e->max - 1) return -EINVAL; val = ucontrol->value.enumerated.item[0] << e->shift_l; - mask = (bitmask - 1) << e->shift_l; + mask = e->mask << e->shift_l; if (e->shift_l != e->shift_r) { if (ucontrol->value.enumerated.item[1] > e->max - 1) return -EINVAL; val |= ucontrol->value.enumerated.item[1] << e->shift_r; - mask |= (bitmask - 1) << e->shift_r; + mask |= e->mask << e->shift_r; } return snd_soc_update_bits_locked(codec, e->reg, mask, val); diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index f7999e949acb..a18d115bc507 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -355,12 +355,10 @@ static void dapm_set_path_status(struct snd_soc_dapm_widget *w, case snd_soc_dapm_mux: { struct soc_enum *e = (struct soc_enum *) w->kcontrol_news[i].private_value; - int val, item, bitmask; + int val, item; - for (bitmask = 1; bitmask < e->max; bitmask <<= 1) - ; val = soc_widget_read(w, e->reg); - item = (val >> e->shift_l) & (bitmask - 1); + item = (val >> e->shift_l) & e->mask; p->connect = 0; for (i = 0; i < e->max; i++) { @@ -2677,15 +2675,13 @@ int snd_soc_dapm_get_enum_double(struct snd_kcontrol *kcontrol, struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol); struct snd_soc_dapm_widget *widget = wlist->widgets[0]; struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; - unsigned int val, bitmask; + unsigned int val; - for (bitmask = 1; bitmask < e->max; bitmask <<= 1) - ; val = snd_soc_read(widget->codec, e->reg); - ucontrol->value.enumerated.item[0] = (val >> e->shift_l) & (bitmask - 1); + ucontrol->value.enumerated.item[0] = (val >> e->shift_l) & e->mask; if (e->shift_l != e->shift_r) ucontrol->value.enumerated.item[1] = - (val >> e->shift_r) & (bitmask - 1); + (val >> e->shift_r) & e->mask; return 0; } @@ -2709,22 +2705,20 @@ int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol, struct snd_soc_card *card = codec->card; struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; unsigned int val, mux, change; - unsigned int mask, bitmask; + unsigned int mask; struct snd_soc_dapm_update update; int wi; - for (bitmask = 1; bitmask < e->max; bitmask <<= 1) - ; if (ucontrol->value.enumerated.item[0] > e->max - 1) return -EINVAL; mux = ucontrol->value.enumerated.item[0]; val = mux << e->shift_l; - mask = (bitmask - 1) << e->shift_l; + mask = e->mask << e->shift_l; if (e->shift_l != e->shift_r) { if (ucontrol->value.enumerated.item[1] > e->max - 1) return -EINVAL; val |= ucontrol->value.enumerated.item[1] << e->shift_r; - mask |= (bitmask - 1) << e->shift_r; + mask |= e->mask << e->shift_r; } mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); -- cgit v1.2.3 From d37777a13b4c4b32e274013846d739e5bbbf6f8d Mon Sep 17 00:00:00 2001 From: Richard Zhao Date: Tue, 18 Sep 2012 17:20:05 +0800 Subject: ASoC: imx-pcm-dma: check kzalloc return value in function snd_imx_open It fixed smatch warning: sound/soc/fsl/imx-pcm-dma.c:112 snd_imx_open() error: potential null dereference 'dma_data'. (kzalloc returns null) Signed-off-by: Richard Zhao Signed-off-by: Mark Brown --- sound/soc/fsl/imx-pcm-dma.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'sound/soc') diff --git a/sound/soc/fsl/imx-pcm-dma.c b/sound/soc/fsl/imx-pcm-dma.c index 48f9d886f020..a23505a9ae64 100644 --- a/sound/soc/fsl/imx-pcm-dma.c +++ b/sound/soc/fsl/imx-pcm-dma.c @@ -109,6 +109,9 @@ static int snd_imx_open(struct snd_pcm_substream *substream) dma_params = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); dma_data = kzalloc(sizeof(*dma_data), GFP_KERNEL); + if (!dma_data) + return -ENOMEM; + dma_data->peripheral_type = dma_params->shared_peripheral ? IMX_DMATYPE_SSI_SP : IMX_DMATYPE_SSI; dma_data->priority = DMA_PRIO_HIGH; -- cgit v1.2.3 From f31e08e160d646952a5142e3f92f3fcdc645a09b Mon Sep 17 00:00:00 2001 From: Richard Zhao Date: Tue, 18 Sep 2012 17:20:06 +0800 Subject: ASoC: imx-pcm-dma: open function failed when snd_dmaengine_pcm_open fail snd_imx_open should return error code returned by snd_dmaengine_pcm_open. Signed-off-by: Richard Zhao Signed-off-by: Mark Brown --- sound/soc/fsl/imx-pcm-dma.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound/soc') diff --git a/sound/soc/fsl/imx-pcm-dma.c b/sound/soc/fsl/imx-pcm-dma.c index a23505a9ae64..9a15bc4bd570 100644 --- a/sound/soc/fsl/imx-pcm-dma.c +++ b/sound/soc/fsl/imx-pcm-dma.c @@ -120,7 +120,7 @@ static int snd_imx_open(struct snd_pcm_substream *substream) ret = snd_dmaengine_pcm_open(substream, filter, dma_data); if (ret) { kfree(dma_data); - return 0; + return ret; } snd_dmaengine_pcm_set_data(substream, dma_data); -- cgit v1.2.3 From f3a50c95e275c2e553e2a6dcc646eef3daf98a3e Mon Sep 17 00:00:00 2001 From: Richard Zhao Date: Tue, 18 Sep 2012 16:38:30 +0800 Subject: ASoC: imx-audmux: remove null check of audmux_base in audmux_read_file When audmux_read_file is called, it means the driver is already initialised successfully, so we don't need to check audmux_base. It also fix smatch warning: sound/soc/fsl/imx-audmux.c:78 audmux_read_file() warn: possible memory leak of 'buf' Signed-off-by: Richard Zhao Signed-off-by: Mark Brown --- sound/soc/fsl/imx-audmux.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/fsl/imx-audmux.c b/sound/soc/fsl/imx-audmux.c index e7c800ebbd75..524ce6210cee 100644 --- a/sound/soc/fsl/imx-audmux.c +++ b/sound/soc/fsl/imx-audmux.c @@ -74,9 +74,6 @@ static ssize_t audmux_read_file(struct file *file, char __user *user_buf, if (!buf) return -ENOMEM; - if (!audmux_base) - return -ENOSYS; - if (audmux_clk) clk_prepare_enable(audmux_clk); -- cgit v1.2.3 From f515b67381de0a4a28d639e0f1bb587a3a49f0d2 Mon Sep 17 00:00:00 2001 From: Eric Millbrandt Date: Thu, 13 Sep 2012 17:43:11 -0400 Subject: ASoC: fsl: mpc5200 combine psc_dma platform data The mpc5200_psc_ac97 and mpc5200_psc_i2s modules rely on shared platform data with mpc5200_dma. Signed-off-by: Eric Millbrandt Signed-off-by: Mark Brown --- sound/soc/fsl/mpc5200_dma.c | 24 ++++-------------------- sound/soc/fsl/mpc5200_dma.h | 3 +++ sound/soc/fsl/mpc5200_psc_ac97.c | 5 +++++ sound/soc/fsl/mpc5200_psc_i2s.c | 5 +++++ 4 files changed, 17 insertions(+), 20 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/fsl/mpc5200_dma.c b/sound/soc/fsl/mpc5200_dma.c index 9a3f7c5ab687..9997c039bb24 100644 --- a/sound/soc/fsl/mpc5200_dma.c +++ b/sound/soc/fsl/mpc5200_dma.c @@ -370,7 +370,7 @@ static struct snd_soc_platform_driver mpc5200_audio_dma_platform = { .pcm_free = &psc_dma_free, }; -static int mpc5200_hpcd_probe(struct platform_device *op) +int mpc5200_audio_dma_create(struct platform_device *op) { phys_addr_t fifo; struct psc_dma *psc_dma; @@ -487,8 +487,9 @@ out_unmap: iounmap(regs); return ret; } +EXPORT_SYMBOL_GPL(mpc5200_audio_dma_create); -static int mpc5200_hpcd_remove(struct platform_device *op) +int mpc5200_audio_dma_destroy(struct platform_device *op) { struct psc_dma *psc_dma = dev_get_drvdata(&op->dev); @@ -510,24 +511,7 @@ static int mpc5200_hpcd_remove(struct platform_device *op) return 0; } - -static struct of_device_id mpc5200_hpcd_match[] = { - { .compatible = "fsl,mpc5200-pcm", }, - {} -}; -MODULE_DEVICE_TABLE(of, mpc5200_hpcd_match); - -static struct platform_driver mpc5200_hpcd_of_driver = { - .probe = mpc5200_hpcd_probe, - .remove = mpc5200_hpcd_remove, - .driver = { - .owner = THIS_MODULE, - .name = "mpc5200-pcm-audio", - .of_match_table = mpc5200_hpcd_match, - } -}; - -module_platform_driver(mpc5200_hpcd_of_driver); +EXPORT_SYMBOL_GPL(mpc5200_audio_dma_destroy); MODULE_AUTHOR("Grant Likely "); MODULE_DESCRIPTION("Freescale MPC5200 PSC in DMA mode ASoC Driver"); diff --git a/sound/soc/fsl/mpc5200_dma.h b/sound/soc/fsl/mpc5200_dma.h index a3c0cd5382fb..dff253fde29a 100644 --- a/sound/soc/fsl/mpc5200_dma.h +++ b/sound/soc/fsl/mpc5200_dma.h @@ -81,4 +81,7 @@ to_psc_dma_stream(struct snd_pcm_substream *substream, struct psc_dma *psc_dma) return &psc_dma->playback; } +int mpc5200_audio_dma_create(struct platform_device *op); +int mpc5200_audio_dma_destroy(struct platform_device *op); + #endif /* __SOUND_SOC_FSL_MPC5200_DMA_H__ */ diff --git a/sound/soc/fsl/mpc5200_psc_ac97.c b/sound/soc/fsl/mpc5200_psc_ac97.c index ffa00a2eb770..9a094535fb26 100644 --- a/sound/soc/fsl/mpc5200_psc_ac97.c +++ b/sound/soc/fsl/mpc5200_psc_ac97.c @@ -278,6 +278,10 @@ static int __devinit psc_ac97_of_probe(struct platform_device *op) struct snd_ac97 ac97; struct mpc52xx_psc __iomem *regs; + rc = mpc5200_audio_dma_create(op); + if (rc != 0) + return rc; + rc = snd_soc_register_dais(&op->dev, psc_ac97_dai, ARRAY_SIZE(psc_ac97_dai)); if (rc != 0) { dev_err(&op->dev, "Failed to register DAI\n"); @@ -303,6 +307,7 @@ static int __devinit psc_ac97_of_probe(struct platform_device *op) static int __devexit psc_ac97_of_remove(struct platform_device *op) { + mpc5200_audio_dma_destroy(op); snd_soc_unregister_dais(&op->dev, ARRAY_SIZE(psc_ac97_dai)); return 0; } diff --git a/sound/soc/fsl/mpc5200_psc_i2s.c b/sound/soc/fsl/mpc5200_psc_i2s.c index 7b530327553a..c0b7a23ebbfd 100644 --- a/sound/soc/fsl/mpc5200_psc_i2s.c +++ b/sound/soc/fsl/mpc5200_psc_i2s.c @@ -156,6 +156,10 @@ static int __devinit psc_i2s_of_probe(struct platform_device *op) struct psc_dma *psc_dma; struct mpc52xx_psc __iomem *regs; + rc = mpc5200_audio_dma_create(op); + if (rc != 0) + return rc; + rc = snd_soc_register_dais(&op->dev, psc_i2s_dai, ARRAY_SIZE(psc_i2s_dai)); if (rc != 0) { pr_err("Failed to register DAI\n"); @@ -200,6 +204,7 @@ static int __devinit psc_i2s_of_probe(struct platform_device *op) static int __devexit psc_i2s_of_remove(struct platform_device *op) { + mpc5200_audio_dma_destroy(op); snd_soc_unregister_dais(&op->dev, ARRAY_SIZE(psc_i2s_dai)); return 0; } -- cgit v1.2.3 From a4f7b70dc73d611680a485150f2b11bcf23a2d01 Mon Sep 17 00:00:00 2001 From: Eric Millbrandt Date: Thu, 13 Sep 2012 17:43:12 -0400 Subject: ASoC: fsl: mpc5200 add missing information to snd_soc_dai_driver Add missing dai_driver information to avoid these runtime errors [ 16.433788] asoc: error - multiple DAI f0002c00.i2s registered with no name [ 16.453551] Failed to register DAI [ 16.461222] mpc5200-psc-i2s: probe of f0002c00.i2s failed with error -22 [ 16.475242] asoc: error - multiple DAI f0002000.ac97 registered with no name [ 16.488087] mpc5200-psc-ac97 f0002000.ac97: Failed to register DAI [ 16.502222] mpc5200-psc-ac97: probe of f0002000.ac97 failed with error -22 Signed-off-by: Eric Millbrandt Signed-off-by: Mark Brown --- sound/soc/fsl/mpc5200_psc_ac97.c | 5 +++++ sound/soc/fsl/mpc5200_psc_i2s.c | 3 +++ 2 files changed, 8 insertions(+) (limited to 'sound/soc') diff --git a/sound/soc/fsl/mpc5200_psc_ac97.c b/sound/soc/fsl/mpc5200_psc_ac97.c index 9a094535fb26..a313c0ae36db 100644 --- a/sound/soc/fsl/mpc5200_psc_ac97.c +++ b/sound/soc/fsl/mpc5200_psc_ac97.c @@ -237,15 +237,18 @@ static const struct snd_soc_dai_ops psc_ac97_digital_ops = { static struct snd_soc_dai_driver psc_ac97_dai[] = { { + .name = "mpc5200-psc-ac97.0", .ac97_control = 1, .probe = psc_ac97_probe, .playback = { + .stream_name = "AC97 Playback", .channels_min = 1, .channels_max = 6, .rates = SNDRV_PCM_RATE_8000_48000, .formats = SNDRV_PCM_FMTBIT_S32_BE, }, .capture = { + .stream_name = "AC97 Capture", .channels_min = 1, .channels_max = 2, .rates = SNDRV_PCM_RATE_8000_48000, @@ -254,8 +257,10 @@ static struct snd_soc_dai_driver psc_ac97_dai[] = { .ops = &psc_ac97_analog_ops, }, { + .name = "mpc5200-psc-ac97.1", .ac97_control = 1, .playback = { + .stream_name = "AC97 SPDIF", .channels_min = 1, .channels_max = 2, .rates = SNDRV_PCM_RATE_32000 | \ diff --git a/sound/soc/fsl/mpc5200_psc_i2s.c b/sound/soc/fsl/mpc5200_psc_i2s.c index c0b7a23ebbfd..ba1f0a66358f 100644 --- a/sound/soc/fsl/mpc5200_psc_i2s.c +++ b/sound/soc/fsl/mpc5200_psc_i2s.c @@ -130,13 +130,16 @@ static const struct snd_soc_dai_ops psc_i2s_dai_ops = { }; static struct snd_soc_dai_driver psc_i2s_dai[] = {{ + .name = "mpc5200-psc-i2s.0", .playback = { + .stream_name = "I2S Playback", .channels_min = 2, .channels_max = 2, .rates = PSC_I2S_RATES, .formats = PSC_I2S_FORMATS, }, .capture = { + .stream_name = "I2S Capture", .channels_min = 2, .channels_max = 2, .rates = PSC_I2S_RATES, -- cgit v1.2.3 From 22bab8ceda6ea2885c6315d07c37b4ef69aefb0c Mon Sep 17 00:00:00 2001 From: Eric Millbrandt Date: Thu, 13 Sep 2012 17:43:13 -0400 Subject: ASoC: fsl: cleanup headers in pcm030-audio-fabric Remove unreferenced header files. Signed-off-by: Eric Millbrandt Signed-off-by: Mark Brown --- sound/soc/fsl/pcm030-audio-fabric.c | 9 --------- 1 file changed, 9 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/fsl/pcm030-audio-fabric.c b/sound/soc/fsl/pcm030-audio-fabric.c index b3af55dcde9d..1353e8fecd7b 100644 --- a/sound/soc/fsl/pcm030-audio-fabric.c +++ b/sound/soc/fsl/pcm030-audio-fabric.c @@ -12,22 +12,13 @@ #include #include -#include #include -#include #include #include -#include -#include -#include -#include -#include #include #include "mpc5200_dma.h" -#include "mpc5200_psc_ac97.h" -#include "../codecs/wm9712.h" #define DRV_NAME "pcm030-audio-fabric" -- cgit v1.2.3 From 2cbde7abfdd8c3e2c1293b7096477e8bcf10b755 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 12 Sep 2012 20:15:22 +0800 Subject: ASoC: wm8776: Convert to direct regmap API usage Signed-off-by: Mark Brown --- sound/soc/codecs/wm8776.c | 75 +++++++++++++++++++++++++++++++++++++---------- 1 file changed, 60 insertions(+), 15 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/wm8776.c b/sound/soc/codecs/wm8776.c index 879c356a9045..c32249ddb2e0 100644 --- a/sound/soc/codecs/wm8776.c +++ b/sound/soc/codecs/wm8776.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -37,18 +38,46 @@ enum wm8776_chip_type { /* codec private data */ struct wm8776_priv { - enum snd_soc_control_type control_type; + struct regmap *regmap; int sysclk[2]; }; -static const u16 wm8776_reg[WM8776_CACHEREGNUM] = { - 0x79, 0x79, 0x79, 0xff, 0xff, /* 4 */ - 0xff, 0x00, 0x90, 0x00, 0x00, /* 9 */ - 0x22, 0x22, 0x22, 0x08, 0xcf, /* 14 */ - 0xcf, 0x7b, 0x00, 0x32, 0x00, /* 19 */ - 0xa6, 0x01, 0x01 +static const struct reg_default wm8776_reg_defaults[] = { + { 0, 0x79 }, + { 1, 0x79 }, + { 2, 0x79 }, + { 3, 0xff }, + { 4, 0xff }, + { 5, 0xff }, + { 6, 0x00 }, + { 7, 0x90 }, + { 8, 0x00 }, + { 9, 0x00 }, + { 10, 0x22 }, + { 11, 0x22 }, + { 12, 0x22 }, + { 13, 0x08 }, + { 14, 0xcf }, + { 15, 0xcf }, + { 16, 0x7b }, + { 17, 0x00 }, + { 18, 0x32 }, + { 19, 0x00 }, + { 20, 0xa6 }, + { 21, 0x01 }, + { 22, 0x01 }, }; +static bool wm8776_volatile(struct device *dev, unsigned int reg) +{ + switch (reg) { + case WM8776_RESET: + return true; + default: + return false; + } +} + static int wm8776_reset(struct snd_soc_codec *codec) { return snd_soc_write(codec, WM8776_RESET, 0); @@ -306,6 +335,8 @@ static int wm8776_set_sysclk(struct snd_soc_dai *dai, static int wm8776_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level) { + struct wm8776_priv *wm8776 = snd_soc_codec_get_drvdata(codec); + switch (level) { case SND_SOC_BIAS_ON: break; @@ -313,7 +344,7 @@ static int wm8776_set_bias_level(struct snd_soc_codec *codec, break; case SND_SOC_BIAS_STANDBY: if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { - snd_soc_cache_sync(codec); + regcache_sync(wm8776->regmap); /* Disable the global powerdown; DAPM does the rest */ snd_soc_update_bits(codec, WM8776_PWRDOWN, 1, 0); @@ -396,10 +427,9 @@ static int wm8776_resume(struct snd_soc_codec *codec) static int wm8776_probe(struct snd_soc_codec *codec) { - struct wm8776_priv *wm8776 = snd_soc_codec_get_drvdata(codec); int ret = 0; - ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8776->control_type); + ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); if (ret < 0) { dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); return ret; @@ -434,9 +464,6 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8776 = { .suspend = wm8776_suspend, .resume = wm8776_resume, .set_bias_level = wm8776_set_bias_level, - .reg_cache_size = ARRAY_SIZE(wm8776_reg), - .reg_word_size = sizeof(u16), - .reg_cache_default = wm8776_reg, .controls = wm8776_snd_controls, .num_controls = ARRAY_SIZE(wm8776_snd_controls), @@ -452,6 +479,18 @@ static const struct of_device_id wm8776_of_match[] = { }; MODULE_DEVICE_TABLE(of, wm8776_of_match); +static const struct regmap_config wm8776_regmap = { + .reg_bits = 7, + .val_bits = 9, + .max_register = WM8776_RESET, + + .reg_defaults = wm8776_reg_defaults, + .num_reg_defaults = ARRAY_SIZE(wm8776_reg_defaults), + .cache_type = REGCACHE_RBTREE, + + .volatile_reg = wm8776_volatile, +}; + #if defined(CONFIG_SPI_MASTER) static int __devinit wm8776_spi_probe(struct spi_device *spi) { @@ -463,7 +502,10 @@ static int __devinit wm8776_spi_probe(struct spi_device *spi) if (wm8776 == NULL) return -ENOMEM; - wm8776->control_type = SND_SOC_SPI; + wm8776->regmap = devm_regmap_init_spi(spi, &wm8776_regmap); + if (IS_ERR(wm8776->regmap)) + return PTR_ERR(wm8776->regmap); + spi_set_drvdata(spi, wm8776); ret = snd_soc_register_codec(&spi->dev, @@ -501,8 +543,11 @@ static __devinit int wm8776_i2c_probe(struct i2c_client *i2c, if (wm8776 == NULL) return -ENOMEM; + wm8776->regmap = devm_regmap_init_i2c(i2c, &wm8776_regmap); + if (IS_ERR(wm8776->regmap)) + return PTR_ERR(wm8776->regmap); + i2c_set_clientdata(i2c, wm8776); - wm8776->control_type = SND_SOC_I2C; ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_wm8776, wm8776_dai, ARRAY_SIZE(wm8776_dai)); -- cgit v1.2.3 From 3706163140939bccd58fba739a9820f1d5eebeaf Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 13 Sep 2012 11:46:58 +0800 Subject: ASoC: wm8960: Support shared LRCLK If the LRCLK is shared and the WM8960 is clock master then we should enable the LRCM bit to tell the device that it should drive LRCLK when either ADC or DAC is enabled rather than separately driving the two LRCLKs. Signed-off-by: Mark Brown --- include/sound/wm8960.h | 2 ++ sound/soc/codecs/wm8960.c | 11 +++++++++++ 2 files changed, 13 insertions(+) (limited to 'sound/soc') diff --git a/include/sound/wm8960.h b/include/sound/wm8960.h index 74e9a95529c5..b5a1ab9ebb4a 100644 --- a/include/sound/wm8960.h +++ b/include/sound/wm8960.h @@ -19,6 +19,8 @@ struct wm8960_data { bool capless; /* Headphone outputs configured in capless mode */ int dres; /* Discharge resistance for headphone outputs */ + + bool shared_lrclk; /* DAC and ADC LRCLKs are wired together */ }; #endif diff --git a/sound/soc/codecs/wm8960.c b/sound/soc/codecs/wm8960.c index 066250e3f7f4..782faa0a3b49 100644 --- a/sound/soc/codecs/wm8960.c +++ b/sound/soc/codecs/wm8960.c @@ -1036,6 +1036,7 @@ static const struct regmap_config wm8960_regmap = { static __devinit int wm8960_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { + struct wm8960_data *pdata = dev_get_platdata(&i2c->dev); struct wm8960_priv *wm8960; int ret; @@ -1048,6 +1049,16 @@ static __devinit int wm8960_i2c_probe(struct i2c_client *i2c, if (IS_ERR(wm8960->regmap)) return PTR_ERR(wm8960->regmap); + if (pdata && pdata->shared_lrclk) { + ret = regmap_update_bits(wm8960->regmap, WM8960_ADDCTL2, + 0x4, 0x4); + if (ret != 0) { + dev_err(&i2c->dev, "Failed to enable LRCM: %d\n", + ret); + return ret; + } + } + i2c_set_clientdata(i2c, wm8960); ret = snd_soc_register_codec(&i2c->dev, -- cgit v1.2.3 From 35ecf7cd96a79d92c1b8433c950a827a2a723db9 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 13 Sep 2012 12:53:59 +0800 Subject: ASoC: wm8961: Convert to direct regmap API usage Signed-off-by: Mark Brown --- sound/soc/codecs/wm8961.c | 426 ++++++++++++++++++---------------------------- 1 file changed, 161 insertions(+), 265 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/wm8961.c b/sound/soc/codecs/wm8961.c index 719fb69a17c8..4ea64d6e68e2 100644 --- a/sound/soc/codecs/wm8961.c +++ b/sound/soc/codecs/wm8961.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -31,277 +32,158 @@ #define WM8961_MAX_REGISTER 0xFC -static u16 wm8961_reg_defaults[] = { - 0x009F, /* R0 - Left Input volume */ - 0x009F, /* R1 - Right Input volume */ - 0x0000, /* R2 - LOUT1 volume */ - 0x0000, /* R3 - ROUT1 volume */ - 0x0020, /* R4 - Clocking1 */ - 0x0008, /* R5 - ADC & DAC Control 1 */ - 0x0000, /* R6 - ADC & DAC Control 2 */ - 0x000A, /* R7 - Audio Interface 0 */ - 0x01F4, /* R8 - Clocking2 */ - 0x0000, /* R9 - Audio Interface 1 */ - 0x00FF, /* R10 - Left DAC volume */ - 0x00FF, /* R11 - Right DAC volume */ - 0x0000, /* R12 */ - 0x0000, /* R13 */ - 0x0040, /* R14 - Audio Interface 2 */ - 0x0000, /* R15 - Software Reset */ - 0x0000, /* R16 */ - 0x007B, /* R17 - ALC1 */ - 0x0000, /* R18 - ALC2 */ - 0x0032, /* R19 - ALC3 */ - 0x0000, /* R20 - Noise Gate */ - 0x00C0, /* R21 - Left ADC volume */ - 0x00C0, /* R22 - Right ADC volume */ - 0x0120, /* R23 - Additional control(1) */ - 0x0000, /* R24 - Additional control(2) */ - 0x0000, /* R25 - Pwr Mgmt (1) */ - 0x0000, /* R26 - Pwr Mgmt (2) */ - 0x0000, /* R27 - Additional Control (3) */ - 0x0000, /* R28 - Anti-pop */ - 0x0000, /* R29 */ - 0x005F, /* R30 - Clocking 3 */ - 0x0000, /* R31 */ - 0x0000, /* R32 - ADCL signal path */ - 0x0000, /* R33 - ADCR signal path */ - 0x0000, /* R34 */ - 0x0000, /* R35 */ - 0x0000, /* R36 */ - 0x0000, /* R37 */ - 0x0000, /* R38 */ - 0x0000, /* R39 */ - 0x0000, /* R40 - LOUT2 volume */ - 0x0000, /* R41 - ROUT2 volume */ - 0x0000, /* R42 */ - 0x0000, /* R43 */ - 0x0000, /* R44 */ - 0x0000, /* R45 */ - 0x0000, /* R46 */ - 0x0000, /* R47 - Pwr Mgmt (3) */ - 0x0023, /* R48 - Additional Control (4) */ - 0x0000, /* R49 - Class D Control 1 */ - 0x0000, /* R50 */ - 0x0003, /* R51 - Class D Control 2 */ - 0x0000, /* R52 */ - 0x0000, /* R53 */ - 0x0000, /* R54 */ - 0x0000, /* R55 */ - 0x0106, /* R56 - Clocking 4 */ - 0x0000, /* R57 - DSP Sidetone 0 */ - 0x0000, /* R58 - DSP Sidetone 1 */ - 0x0000, /* R59 */ - 0x0000, /* R60 - DC Servo 0 */ - 0x0000, /* R61 - DC Servo 1 */ - 0x0000, /* R62 */ - 0x015E, /* R63 - DC Servo 3 */ - 0x0010, /* R64 */ - 0x0010, /* R65 - DC Servo 5 */ - 0x0000, /* R66 */ - 0x0001, /* R67 */ - 0x0003, /* R68 - Analogue PGA Bias */ - 0x0000, /* R69 - Analogue HP 0 */ - 0x0060, /* R70 */ - 0x01FB, /* R71 - Analogue HP 2 */ - 0x0000, /* R72 - Charge Pump 1 */ - 0x0065, /* R73 */ - 0x005F, /* R74 */ - 0x0059, /* R75 */ - 0x006B, /* R76 */ - 0x0038, /* R77 */ - 0x000C, /* R78 */ - 0x000A, /* R79 */ - 0x006B, /* R80 */ - 0x0000, /* R81 */ - 0x0000, /* R82 - Charge Pump B */ - 0x0087, /* R83 */ - 0x0000, /* R84 */ - 0x005C, /* R85 */ - 0x0000, /* R86 */ - 0x0000, /* R87 - Write Sequencer 1 */ - 0x0000, /* R88 - Write Sequencer 2 */ - 0x0000, /* R89 - Write Sequencer 3 */ - 0x0000, /* R90 - Write Sequencer 4 */ - 0x0000, /* R91 - Write Sequencer 5 */ - 0x0000, /* R92 - Write Sequencer 6 */ - 0x0000, /* R93 - Write Sequencer 7 */ - 0x0000, /* R94 */ - 0x0000, /* R95 */ - 0x0000, /* R96 */ - 0x0000, /* R97 */ - 0x0000, /* R98 */ - 0x0000, /* R99 */ - 0x0000, /* R100 */ - 0x0000, /* R101 */ - 0x0000, /* R102 */ - 0x0000, /* R103 */ - 0x0000, /* R104 */ - 0x0000, /* R105 */ - 0x0000, /* R106 */ - 0x0000, /* R107 */ - 0x0000, /* R108 */ - 0x0000, /* R109 */ - 0x0000, /* R110 */ - 0x0000, /* R111 */ - 0x0000, /* R112 */ - 0x0000, /* R113 */ - 0x0000, /* R114 */ - 0x0000, /* R115 */ - 0x0000, /* R116 */ - 0x0000, /* R117 */ - 0x0000, /* R118 */ - 0x0000, /* R119 */ - 0x0000, /* R120 */ - 0x0000, /* R121 */ - 0x0000, /* R122 */ - 0x0000, /* R123 */ - 0x0000, /* R124 */ - 0x0000, /* R125 */ - 0x0000, /* R126 */ - 0x0000, /* R127 */ - 0x0000, /* R128 */ - 0x0000, /* R129 */ - 0x0000, /* R130 */ - 0x0000, /* R131 */ - 0x0000, /* R132 */ - 0x0000, /* R133 */ - 0x0000, /* R134 */ - 0x0000, /* R135 */ - 0x0000, /* R136 */ - 0x0000, /* R137 */ - 0x0000, /* R138 */ - 0x0000, /* R139 */ - 0x0000, /* R140 */ - 0x0000, /* R141 */ - 0x0000, /* R142 */ - 0x0000, /* R143 */ - 0x0000, /* R144 */ - 0x0000, /* R145 */ - 0x0000, /* R146 */ - 0x0000, /* R147 */ - 0x0000, /* R148 */ - 0x0000, /* R149 */ - 0x0000, /* R150 */ - 0x0000, /* R151 */ - 0x0000, /* R152 */ - 0x0000, /* R153 */ - 0x0000, /* R154 */ - 0x0000, /* R155 */ - 0x0000, /* R156 */ - 0x0000, /* R157 */ - 0x0000, /* R158 */ - 0x0000, /* R159 */ - 0x0000, /* R160 */ - 0x0000, /* R161 */ - 0x0000, /* R162 */ - 0x0000, /* R163 */ - 0x0000, /* R164 */ - 0x0000, /* R165 */ - 0x0000, /* R166 */ - 0x0000, /* R167 */ - 0x0000, /* R168 */ - 0x0000, /* R169 */ - 0x0000, /* R170 */ - 0x0000, /* R171 */ - 0x0000, /* R172 */ - 0x0000, /* R173 */ - 0x0000, /* R174 */ - 0x0000, /* R175 */ - 0x0000, /* R176 */ - 0x0000, /* R177 */ - 0x0000, /* R178 */ - 0x0000, /* R179 */ - 0x0000, /* R180 */ - 0x0000, /* R181 */ - 0x0000, /* R182 */ - 0x0000, /* R183 */ - 0x0000, /* R184 */ - 0x0000, /* R185 */ - 0x0000, /* R186 */ - 0x0000, /* R187 */ - 0x0000, /* R188 */ - 0x0000, /* R189 */ - 0x0000, /* R190 */ - 0x0000, /* R191 */ - 0x0000, /* R192 */ - 0x0000, /* R193 */ - 0x0000, /* R194 */ - 0x0000, /* R195 */ - 0x0030, /* R196 */ - 0x0006, /* R197 */ - 0x0000, /* R198 */ - 0x0060, /* R199 */ - 0x0000, /* R200 */ - 0x003F, /* R201 */ - 0x0000, /* R202 */ - 0x0000, /* R203 */ - 0x0000, /* R204 */ - 0x0001, /* R205 */ - 0x0000, /* R206 */ - 0x0181, /* R207 */ - 0x0005, /* R208 */ - 0x0008, /* R209 */ - 0x0008, /* R210 */ - 0x0000, /* R211 */ - 0x013B, /* R212 */ - 0x0000, /* R213 */ - 0x0000, /* R214 */ - 0x0000, /* R215 */ - 0x0000, /* R216 */ - 0x0070, /* R217 */ - 0x0000, /* R218 */ - 0x0000, /* R219 */ - 0x0000, /* R220 */ - 0x0000, /* R221 */ - 0x0000, /* R222 */ - 0x0003, /* R223 */ - 0x0000, /* R224 */ - 0x0000, /* R225 */ - 0x0001, /* R226 */ - 0x0008, /* R227 */ - 0x0000, /* R228 */ - 0x0000, /* R229 */ - 0x0000, /* R230 */ - 0x0000, /* R231 */ - 0x0004, /* R232 */ - 0x0000, /* R233 */ - 0x0000, /* R234 */ - 0x0000, /* R235 */ - 0x0000, /* R236 */ - 0x0000, /* R237 */ - 0x0080, /* R238 */ - 0x0000, /* R239 */ - 0x0000, /* R240 */ - 0x0000, /* R241 */ - 0x0000, /* R242 */ - 0x0000, /* R243 */ - 0x0000, /* R244 */ - 0x0052, /* R245 */ - 0x0110, /* R246 */ - 0x0040, /* R247 */ - 0x0000, /* R248 */ - 0x0030, /* R249 */ - 0x0000, /* R250 */ - 0x0000, /* R251 */ - 0x0001, /* R252 - General test 1 */ +static const struct reg_default wm8961_reg_defaults[] = { + { 0, 0x009F }, /* R0 - Left Input volume */ + { 1, 0x009F }, /* R1 - Right Input volume */ + { 2, 0x0000 }, /* R2 - LOUT1 volume */ + { 3, 0x0000 }, /* R3 - ROUT1 volume */ + { 4, 0x0020 }, /* R4 - Clocking1 */ + { 5, 0x0008 }, /* R5 - ADC & DAC Control 1 */ + { 6, 0x0000 }, /* R6 - ADC & DAC Control 2 */ + { 7, 0x000A }, /* R7 - Audio Interface 0 */ + { 8, 0x01F4 }, /* R8 - Clocking2 */ + { 9, 0x0000 }, /* R9 - Audio Interface 1 */ + { 10, 0x00FF }, /* R10 - Left DAC volume */ + { 11, 0x00FF }, /* R11 - Right DAC volume */ + + { 14, 0x0040 }, /* R14 - Audio Interface 2 */ + + { 17, 0x007B }, /* R17 - ALC1 */ + { 18, 0x0000 }, /* R18 - ALC2 */ + { 19, 0x0032 }, /* R19 - ALC3 */ + { 20, 0x0000 }, /* R20 - Noise Gate */ + { 21, 0x00C0 }, /* R21 - Left ADC volume */ + { 22, 0x00C0 }, /* R22 - Right ADC volume */ + { 23, 0x0120 }, /* R23 - Additional control(1) */ + { 24, 0x0000 }, /* R24 - Additional control(2) */ + { 25, 0x0000 }, /* R25 - Pwr Mgmt (1) */ + { 26, 0x0000 }, /* R26 - Pwr Mgmt (2) */ + { 27, 0x0000 }, /* R27 - Additional Control (3) */ + { 28, 0x0000 }, /* R28 - Anti-pop */ + + { 30, 0x005F }, /* R30 - Clocking 3 */ + + { 32, 0x0000 }, /* R32 - ADCL signal path */ + { 33, 0x0000 }, /* R33 - ADCR signal path */ + + { 40, 0x0000 }, /* R40 - LOUT2 volume */ + { 41, 0x0000 }, /* R41 - ROUT2 volume */ + + { 47, 0x0000 }, /* R47 - Pwr Mgmt (3) */ + { 48, 0x0023 }, /* R48 - Additional Control (4) */ + { 49, 0x0000 }, /* R49 - Class D Control 1 */ + + { 51, 0x0003 }, /* R51 - Class D Control 2 */ + + { 56, 0x0106 }, /* R56 - Clocking 4 */ + { 57, 0x0000 }, /* R57 - DSP Sidetone 0 */ + { 58, 0x0000 }, /* R58 - DSP Sidetone 1 */ + + { 60, 0x0000 }, /* R60 - DC Servo 0 */ + { 61, 0x0000 }, /* R61 - DC Servo 1 */ + + { 63, 0x015E }, /* R63 - DC Servo 3 */ + + { 65, 0x0010 }, /* R65 - DC Servo 5 */ + + { 68, 0x0003 }, /* R68 - Analogue PGA Bias */ + { 69, 0x0000 }, /* R69 - Analogue HP 0 */ + + { 71, 0x01FB }, /* R71 - Analogue HP 2 */ + { 72, 0x0000 }, /* R72 - Charge Pump 1 */ + + { 82, 0x0000 }, /* R82 - Charge Pump B */ + + { 87, 0x0000 }, /* R87 - Write Sequencer 1 */ + { 88, 0x0000 }, /* R88 - Write Sequencer 2 */ + { 89, 0x0000 }, /* R89 - Write Sequencer 3 */ + { 90, 0x0000 }, /* R90 - Write Sequencer 4 */ + { 91, 0x0000 }, /* R91 - Write Sequencer 5 */ + { 92, 0x0000 }, /* R92 - Write Sequencer 6 */ + { 93, 0x0000 }, /* R93 - Write Sequencer 7 */ + + { 252, 0x0001 }, /* R252 - General test 1 */ }; struct wm8961_priv { - enum snd_soc_control_type control_type; + struct regmap *regmap; int sysclk; }; -static int wm8961_volatile_register(struct snd_soc_codec *codec, unsigned int reg) +static bool wm8961_volatile(struct device *dev, unsigned int reg) { switch (reg) { case WM8961_SOFTWARE_RESET: case WM8961_WRITE_SEQUENCER_7: case WM8961_DC_SERVO_1: - return 1; + return true; default: - return 0; + return false; + } +} + +static bool wm8961_readable(struct device *dev, unsigned int reg) +{ + switch (reg) { + case WM8961_LEFT_INPUT_VOLUME: + case WM8961_RIGHT_INPUT_VOLUME: + case WM8961_LOUT1_VOLUME: + case WM8961_ROUT1_VOLUME: + case WM8961_CLOCKING1: + case WM8961_ADC_DAC_CONTROL_1: + case WM8961_ADC_DAC_CONTROL_2: + case WM8961_AUDIO_INTERFACE_0: + case WM8961_CLOCKING2: + case WM8961_AUDIO_INTERFACE_1: + case WM8961_LEFT_DAC_VOLUME: + case WM8961_RIGHT_DAC_VOLUME: + case WM8961_AUDIO_INTERFACE_2: + case WM8961_SOFTWARE_RESET: + case WM8961_ALC1: + case WM8961_ALC2: + case WM8961_ALC3: + case WM8961_NOISE_GATE: + case WM8961_LEFT_ADC_VOLUME: + case WM8961_RIGHT_ADC_VOLUME: + case WM8961_ADDITIONAL_CONTROL_1: + case WM8961_ADDITIONAL_CONTROL_2: + case WM8961_PWR_MGMT_1: + case WM8961_PWR_MGMT_2: + case WM8961_ADDITIONAL_CONTROL_3: + case WM8961_ANTI_POP: + case WM8961_CLOCKING_3: + case WM8961_ADCL_SIGNAL_PATH: + case WM8961_ADCR_SIGNAL_PATH: + case WM8961_LOUT2_VOLUME: + case WM8961_ROUT2_VOLUME: + case WM8961_PWR_MGMT_3: + case WM8961_ADDITIONAL_CONTROL_4: + case WM8961_CLASS_D_CONTROL_1: + case WM8961_CLASS_D_CONTROL_2: + case WM8961_CLOCKING_4: + case WM8961_DSP_SIDETONE_0: + case WM8961_DSP_SIDETONE_1: + case WM8961_DC_SERVO_0: + case WM8961_DC_SERVO_1: + case WM8961_DC_SERVO_3: + case WM8961_DC_SERVO_5: + case WM8961_ANALOGUE_PGA_BIAS: + case WM8961_ANALOGUE_HP_0: + case WM8961_ANALOGUE_HP_2: + case WM8961_CHARGE_PUMP_1: + case WM8961_CHARGE_PUMP_B: + case WM8961_WRITE_SEQUENCER_1: + case WM8961_WRITE_SEQUENCER_2: + case WM8961_WRITE_SEQUENCER_3: + case WM8961_WRITE_SEQUENCER_4: + case WM8961_WRITE_SEQUENCER_5: + case WM8961_WRITE_SEQUENCER_6: + case WM8961_WRITE_SEQUENCER_7: + case WM8961_GENERAL_TEST_1: + return true; + default: + return false; } } @@ -958,11 +840,12 @@ static struct snd_soc_dai_driver wm8961_dai = { static int wm8961_probe(struct snd_soc_codec *codec) { + struct wm8961_priv *wm8961 = snd_soc_codec_get_drvdata(codec); struct snd_soc_dapm_context *dapm = &codec->dapm; int ret = 0; u16 reg; - ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C); + ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP); if (ret != 0) { dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); return ret; @@ -975,9 +858,9 @@ static int wm8961_probe(struct snd_soc_codec *codec) } /* This isn't volatile - readback doesn't correspond to write */ - codec->cache_bypass = 1; + regcache_cache_bypass(wm8961->regmap, true); reg = snd_soc_read(codec, WM8961_RIGHT_INPUT_VOLUME); - codec->cache_bypass = 0; + regcache_cache_bypass(wm8961->regmap, false); dev_info(codec->dev, "WM8961 family %d revision %c\n", (reg & WM8961_DEVICE_ID_MASK) >> WM8961_DEVICE_ID_SHIFT, ((reg & WM8961_CHIP_REV_MASK) >> WM8961_CHIP_REV_SHIFT) @@ -1066,10 +949,19 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8961 = { .suspend = wm8961_suspend, .resume = wm8961_resume, .set_bias_level = wm8961_set_bias_level, - .reg_cache_size = ARRAY_SIZE(wm8961_reg_defaults), - .reg_word_size = sizeof(u16), - .reg_cache_default = wm8961_reg_defaults, - .volatile_register = wm8961_volatile_register, +}; + +static const struct regmap_config wm8961_regmap = { + .reg_bits = 8, + .val_bits = 16, + .max_register = WM8961_MAX_REGISTER, + + .reg_defaults = wm8961_reg_defaults, + .num_reg_defaults = ARRAY_SIZE(wm8961_reg_defaults), + .cache_type = REGCACHE_RBTREE, + + .volatile_reg = wm8961_volatile, + .readable_reg = wm8961_readable, }; static __devinit int wm8961_i2c_probe(struct i2c_client *i2c, @@ -1083,6 +975,10 @@ static __devinit int wm8961_i2c_probe(struct i2c_client *i2c, if (wm8961 == NULL) return -ENOMEM; + wm8961->regmap = devm_regmap_init_i2c(i2c, &wm8961_regmap); + if (IS_ERR(wm8961->regmap)) + return PTR_ERR(wm8961->regmap); + i2c_set_clientdata(i2c, wm8961); ret = snd_soc_register_codec(&i2c->dev, -- cgit v1.2.3 From b306e84f9a15e465812d9b66f8d6ecadae806f4c Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 13 Sep 2012 13:31:38 +0800 Subject: ASoC: wm8961: Move device identification and reset to I2C probe This is more idiomatic as it means we verify that the device is there prior to trying to do the card probe. Signed-off-by: Mark Brown --- sound/soc/codecs/wm8961.c | 60 ++++++++++++++++++++++++++--------------------- 1 file changed, 33 insertions(+), 27 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/wm8961.c b/sound/soc/codecs/wm8961.c index 4ea64d6e68e2..f387670d0d75 100644 --- a/sound/soc/codecs/wm8961.c +++ b/sound/soc/codecs/wm8961.c @@ -187,11 +187,6 @@ static bool wm8961_readable(struct device *dev, unsigned int reg) } } -static int wm8961_reset(struct snd_soc_codec *codec) -{ - return snd_soc_write(codec, WM8961_SOFTWARE_RESET, 0); -} - /* * The headphone output supports special anti-pop sequences giving * silent power up and power down. @@ -840,7 +835,6 @@ static struct snd_soc_dai_driver wm8961_dai = { static int wm8961_probe(struct snd_soc_codec *codec) { - struct wm8961_priv *wm8961 = snd_soc_codec_get_drvdata(codec); struct snd_soc_dapm_context *dapm = &codec->dapm; int ret = 0; u16 reg; @@ -851,27 +845,6 @@ static int wm8961_probe(struct snd_soc_codec *codec) return ret; } - reg = snd_soc_read(codec, WM8961_SOFTWARE_RESET); - if (reg != 0x1801) { - dev_err(codec->dev, "Device is not a WM8961: ID=0x%x\n", reg); - return -EINVAL; - } - - /* This isn't volatile - readback doesn't correspond to write */ - regcache_cache_bypass(wm8961->regmap, true); - reg = snd_soc_read(codec, WM8961_RIGHT_INPUT_VOLUME); - regcache_cache_bypass(wm8961->regmap, false); - dev_info(codec->dev, "WM8961 family %d revision %c\n", - (reg & WM8961_DEVICE_ID_MASK) >> WM8961_DEVICE_ID_SHIFT, - ((reg & WM8961_CHIP_REV_MASK) >> WM8961_CHIP_REV_SHIFT) - + 'A'); - - ret = wm8961_reset(codec); - if (ret < 0) { - dev_err(codec->dev, "Failed to issue reset\n"); - return ret; - } - /* Enable class W */ reg = snd_soc_read(codec, WM8961_CHARGE_PUMP_B); reg |= WM8961_CP_DYN_PWR_MASK; @@ -968,6 +941,7 @@ static __devinit int wm8961_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { struct wm8961_priv *wm8961; + unsigned int val; int ret; wm8961 = devm_kzalloc(&i2c->dev, sizeof(struct wm8961_priv), @@ -979,6 +953,38 @@ static __devinit int wm8961_i2c_probe(struct i2c_client *i2c, if (IS_ERR(wm8961->regmap)) return PTR_ERR(wm8961->regmap); + ret = regmap_read(wm8961->regmap, WM8961_SOFTWARE_RESET, &val); + if (ret != 0) { + dev_err(&i2c->dev, "Failed to read chip ID: %d\n", ret); + return ret; + } + + if (val != 0x1801) { + dev_err(&i2c->dev, "Device is not a WM8961: ID=0x%x\n", val); + return -EINVAL; + } + + /* This isn't volatile - readback doesn't correspond to write */ + regcache_cache_bypass(wm8961->regmap, true); + ret = regmap_read(wm8961->regmap, WM8961_RIGHT_INPUT_VOLUME, &val); + regcache_cache_bypass(wm8961->regmap, false); + + if (ret != 0) { + dev_err(&i2c->dev, "Failed to read chip revision: %d\n", ret); + return ret; + } + + dev_info(&i2c->dev, "WM8961 family %d revision %c\n", + (val & WM8961_DEVICE_ID_MASK) >> WM8961_DEVICE_ID_SHIFT, + ((val & WM8961_CHIP_REV_MASK) >> WM8961_CHIP_REV_SHIFT) + + 'A'); + + ret = regmap_write(wm8961->regmap, WM8961_SOFTWARE_RESET, 0x1801); + if (ret != 0) { + dev_err(&i2c->dev, "Failed to issue reset: %d\n", ret); + return ret; + } + i2c_set_clientdata(i2c, wm8961); ret = snd_soc_register_codec(&i2c->dev, -- cgit v1.2.3 From 0534951ba493a97eee646f62101cf88fac2308c6 Mon Sep 17 00:00:00 2001 From: Timur Tabi Date: Thu, 20 Sep 2012 13:57:27 -0500 Subject: ASoC: wm8960: remove 'dres' field from platform data structure The 'dres' field (discharge resistance for headphone outputs) is no longer used in the driver, so remove it. It was used in the original version of the driver when entering standby from off, but we stopped using it when we switched from having a single startup sequence to having separate cap and capless sequences. Signed-off-by: Timur Tabi Signed-off-by: Mark Brown --- include/sound/wm8960.h | 2 -- sound/soc/codecs/wm8960.c | 5 ----- 2 files changed, 7 deletions(-) (limited to 'sound/soc') diff --git a/include/sound/wm8960.h b/include/sound/wm8960.h index b5a1ab9ebb4a..e8ce8ee7d62d 100644 --- a/include/sound/wm8960.h +++ b/include/sound/wm8960.h @@ -18,8 +18,6 @@ struct wm8960_data { bool capless; /* Headphone outputs configured in capless mode */ - int dres; /* Discharge resistance for headphone outputs */ - bool shared_lrclk; /* DAC and ADC LRCLKs are wired together */ }; diff --git a/sound/soc/codecs/wm8960.c b/sound/soc/codecs/wm8960.c index 782faa0a3b49..f0f6f6601785 100644 --- a/sound/soc/codecs/wm8960.c +++ b/sound/soc/codecs/wm8960.c @@ -962,11 +962,6 @@ static int wm8960_probe(struct snd_soc_codec *codec) if (!pdata) { dev_warn(codec->dev, "No platform data supplied\n"); } else { - if (pdata->dres > WM8960_DRES_MAX) { - dev_err(codec->dev, "Invalid DRES: %d\n", pdata->dres); - pdata->dres = 0; - } - if (pdata->capless) wm8960->set_bias_level = wm8960_set_bias_level_capless; } -- cgit v1.2.3 From 7f51e7d30e36ac987d7a0e480d890477c5f8b04f Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Thu, 20 Sep 2012 16:32:02 +0300 Subject: ASoC: twl4030: Convert to use DAI DAPM widgets Use DAPM mapping for stream events and give unique names for the streams. This change also fixes the following warning: twl4030-codec twl4030-codec: Failed to create Capture debugfs file Signed-off-by: Peter Ujfalusi Signed-off-by: Mark Brown --- sound/soc/codecs/twl4030.c | 48 +++++++++++++++++++++++++++------------------- 1 file changed, 28 insertions(+), 20 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/twl4030.c b/sound/soc/codecs/twl4030.c index 2548f5c56885..962341df7ddc 100644 --- a/sound/soc/codecs/twl4030.c +++ b/sound/soc/codecs/twl4030.c @@ -1237,16 +1237,11 @@ static const struct snd_soc_dapm_widget twl4030_dapm_widgets[] = { SND_SOC_DAPM_OUTPUT("Virtual Voice OUT"), /* DACs */ - SND_SOC_DAPM_DAC("DAC Right1", "Right Front HiFi Playback", - SND_SOC_NOPM, 0, 0), - SND_SOC_DAPM_DAC("DAC Left1", "Left Front HiFi Playback", - SND_SOC_NOPM, 0, 0), - SND_SOC_DAPM_DAC("DAC Right2", "Right Rear HiFi Playback", - SND_SOC_NOPM, 0, 0), - SND_SOC_DAPM_DAC("DAC Left2", "Left Rear HiFi Playback", - SND_SOC_NOPM, 0, 0), - SND_SOC_DAPM_DAC("DAC Voice", "Voice Playback", - SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_DAC("DAC Right1", NULL, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_DAC("DAC Left1", NULL, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_DAC("DAC Right2", NULL, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_DAC("DAC Left2", NULL, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_DAC("DAC Voice", NULL, SND_SOC_NOPM, 0, 0), /* Analog bypasses */ SND_SOC_DAPM_SWITCH("Right1 Analog Loopback", SND_SOC_NOPM, 0, 0, @@ -1375,14 +1370,10 @@ static const struct snd_soc_dapm_widget twl4030_dapm_widgets[] = { /* Introducing four virtual ADC, since TWL4030 have four channel for capture */ - SND_SOC_DAPM_ADC("ADC Virtual Left1", "Left Front Capture", - SND_SOC_NOPM, 0, 0), - SND_SOC_DAPM_ADC("ADC Virtual Right1", "Right Front Capture", - SND_SOC_NOPM, 0, 0), - SND_SOC_DAPM_ADC("ADC Virtual Left2", "Left Rear Capture", - SND_SOC_NOPM, 0, 0), - SND_SOC_DAPM_ADC("ADC Virtual Right2", "Right Rear Capture", - SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_ADC("ADC Virtual Left1", NULL, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_ADC("ADC Virtual Right1", NULL, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_ADC("ADC Virtual Left2", NULL, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_ADC("ADC Virtual Right2", NULL, SND_SOC_NOPM, 0, 0), /* Analog/Digital mic path selection. TX1 Left/Right: either analog Left/Right or Digimic0 @@ -1426,6 +1417,23 @@ static const struct snd_soc_dapm_widget twl4030_dapm_widgets[] = { }; static const struct snd_soc_dapm_route intercon[] = { + /* Stream -> DAC mapping */ + {"DAC Right1", NULL, "HiFi Playback"}, + {"DAC Left1", NULL, "HiFi Playback"}, + {"DAC Right2", NULL, "HiFi Playback"}, + {"DAC Left2", NULL, "HiFi Playback"}, + {"DAC Voice", NULL, "Voice Playback"}, + + /* ADC -> Stream mapping */ + {"HiFi Capture", NULL, "ADC Virtual Left1"}, + {"HiFi Capture", NULL, "ADC Virtual Right1"}, + {"HiFi Capture", NULL, "ADC Virtual Left2"}, + {"HiFi Capture", NULL, "ADC Virtual Right2"}, + {"Voice Capture", NULL, "ADC Virtual Left1"}, + {"Voice Capture", NULL, "ADC Virtual Right1"}, + {"Voice Capture", NULL, "ADC Virtual Left2"}, + {"Voice Capture", NULL, "ADC Virtual Right2"}, + {"Digital L1 Playback Mixer", NULL, "DAC Left1"}, {"Digital R1 Playback Mixer", NULL, "DAC Right1"}, {"Digital L2 Playback Mixer", NULL, "DAC Left2"}, @@ -2170,7 +2178,7 @@ static struct snd_soc_dai_driver twl4030_dai[] = { .formats = TWL4030_FORMATS, .sig_bits = 24,}, .capture = { - .stream_name = "Capture", + .stream_name = "HiFi Capture", .channels_min = 2, .channels_max = 4, .rates = TWL4030_RATES, @@ -2187,7 +2195,7 @@ static struct snd_soc_dai_driver twl4030_dai[] = { .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000, .formats = SNDRV_PCM_FMTBIT_S16_LE,}, .capture = { - .stream_name = "Capture", + .stream_name = "Voice Capture", .channels_min = 1, .channels_max = 2, .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000, -- cgit v1.2.3 From 805238b1b76c8f4f17a92f50c12664a8e6f3564f Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Thu, 20 Sep 2012 16:32:15 +0300 Subject: ASoC: twl6040: Convert to use DAI DAPM widgets Use DAPM mapping for stream events and give unique names for the streams. This change also fixes the following warning: twl6040-codec twl6040-codec: Failed to create Capture debugfs file Signed-off-by: Peter Ujfalusi Signed-off-by: Mark Brown --- sound/soc/codecs/twl6040.c | 43 +++++++++++++++++++++++++++++-------------- 1 file changed, 29 insertions(+), 14 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/twl6040.c b/sound/soc/codecs/twl6040.c index c084c549942e..e8f97af75928 100644 --- a/sound/soc/codecs/twl6040.c +++ b/sound/soc/codecs/twl6040.c @@ -727,10 +727,8 @@ static const struct snd_soc_dapm_widget twl6040_dapm_widgets[] = { TWL6040_REG_MICRCTL, 1, 0, NULL, 0), /* ADCs */ - SND_SOC_DAPM_ADC("ADC Left", "Left Front Capture", - TWL6040_REG_MICLCTL, 2, 0), - SND_SOC_DAPM_ADC("ADC Right", "Right Front Capture", - TWL6040_REG_MICRCTL, 2, 0), + SND_SOC_DAPM_ADC("ADC Left", NULL, TWL6040_REG_MICLCTL, 2, 0), + SND_SOC_DAPM_ADC("ADC Right", NULL, TWL6040_REG_MICRCTL, 2, 0), /* Microphone bias */ SND_SOC_DAPM_SUPPLY("Headset Mic Bias", @@ -743,15 +741,12 @@ static const struct snd_soc_dapm_widget twl6040_dapm_widgets[] = { TWL6040_REG_DMICBCTL, 4, 0, NULL, 0), /* DACs */ - SND_SOC_DAPM_DAC("HSDAC Left", "Headset Playback", SND_SOC_NOPM, 0, 0), - SND_SOC_DAPM_DAC("HSDAC Right", "Headset Playback", SND_SOC_NOPM, 0, 0), - SND_SOC_DAPM_DAC("HFDAC Left", "Handsfree Playback", - TWL6040_REG_HFLCTL, 0, 0), - SND_SOC_DAPM_DAC("HFDAC Right", "Handsfree Playback", - TWL6040_REG_HFRCTL, 0, 0), + SND_SOC_DAPM_DAC("HSDAC Left", NULL, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_DAC("HSDAC Right", NULL, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_DAC("HFDAC Left", NULL, TWL6040_REG_HFLCTL, 0, 0), + SND_SOC_DAPM_DAC("HFDAC Right", NULL, TWL6040_REG_HFRCTL, 0, 0), /* Virtual DAC for vibra path (DL4 channel) */ - SND_SOC_DAPM_DAC("VIBRA DAC", "Vibra Playback", - SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_DAC("VIBRA DAC", NULL, SND_SOC_NOPM, 0, 0), SND_SOC_DAPM_MUX("Handsfree Left Playback", SND_SOC_NOPM, 0, 0, &hfl_mux_controls), @@ -810,6 +805,26 @@ static const struct snd_soc_dapm_widget twl6040_dapm_widgets[] = { }; static const struct snd_soc_dapm_route intercon[] = { + /* Stream -> DAC mapping */ + {"HSDAC Left", NULL, "Legacy Playback"}, + {"HSDAC Left", NULL, "Headset Playback"}, + {"HSDAC Right", NULL, "Legacy Playback"}, + {"HSDAC Right", NULL, "Headset Playback"}, + + {"HFDAC Left", NULL, "Legacy Playback"}, + {"HFDAC Left", NULL, "Handsfree Playback"}, + {"HFDAC Right", NULL, "Legacy Playback"}, + {"HFDAC Right", NULL, "Handsfree Playback"}, + + {"VIBRA DAC", NULL, "Legacy Playback"}, + {"VIBRA DAC", NULL, "Vibra Playback"}, + + /* ADC -> Stream mapping */ + {"ADC Left", NULL, "Legacy Capture"}, + {"ADC Left", NULL, "Capture"}, + {"ADC Right", NULL, "Legacy Capture"}, + {"ADC Right", NULL, "Capture"}, + /* Capture path */ {"Analog Left Capture Route", "Headset Mic", "HSMIC"}, {"Analog Left Capture Route", "Main Mic", "MAINMIC"}, @@ -1028,14 +1043,14 @@ static struct snd_soc_dai_driver twl6040_dai[] = { { .name = "twl6040-legacy", .playback = { - .stream_name = "Playback", + .stream_name = "Legacy Playback", .channels_min = 1, .channels_max = 5, .rates = TWL6040_RATES, .formats = TWL6040_FORMATS, }, .capture = { - .stream_name = "Capture", + .stream_name = "Legacy Capture", .channels_min = 1, .channels_max = 2, .rates = TWL6040_RATES, -- cgit v1.2.3 From f99ddef0d8e02884b302701fb7acb6fe51a36749 Mon Sep 17 00:00:00 2001 From: Eric Millbrandt Date: Thu, 20 Sep 2012 10:36:43 -0400 Subject: ASoC: fsl: add PPC_MPC52xx dependency to SND_POWERPC_SOC mpc52xx socs do not define FSL_SOC but need SND_POWERPC_SOC defined to build ASoC drivers. Signed-off-by: Eric Millbrandt Signed-off-by: Mark Brown --- sound/soc/fsl/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound/soc') diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig index d70133086ac3..4563b28bd625 100644 --- a/sound/soc/fsl/Kconfig +++ b/sound/soc/fsl/Kconfig @@ -6,7 +6,7 @@ config SND_SOC_FSL_UTILS menuconfig SND_POWERPC_SOC tristate "SoC Audio for Freescale PowerPC CPUs" - depends on FSL_SOC + depends on FSL_SOC || PPC_MPC52xx help Say Y or M if you want to add support for codecs attached to the PowerPC CPUs. -- cgit v1.2.3 From 084011615c1c885232e8d1fb5cc3f85c9d880d14 Mon Sep 17 00:00:00 2001 From: Eric Millbrandt Date: Thu, 20 Sep 2012 10:36:44 -0400 Subject: ASoC: fsl: pcm030-audio-fabric use snd_soc_register_card Convert pcm030-audio-fabric to use the new snd_soc_register_card api instead of the older method of registering a separate platform device. Create the dai_link to the mpc5200_psc_ac97 platform using the device tree. Convert the pcm030-audio-fabric driver to a platform-driver and add a remove function. Signed-off-by: Eric Millbrandt Signed-off-by: Mark Brown --- sound/soc/fsl/pcm030-audio-fabric.c | 65 +++++++++++++++++++++++++++---------- 1 file changed, 47 insertions(+), 18 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/fsl/pcm030-audio-fabric.c b/sound/soc/fsl/pcm030-audio-fabric.c index 1353e8fecd7b..893e24034816 100644 --- a/sound/soc/fsl/pcm030-audio-fabric.c +++ b/sound/soc/fsl/pcm030-audio-fabric.c @@ -28,7 +28,6 @@ static struct snd_soc_dai_link pcm030_fabric_dai[] = { .stream_name = "AC97 Analog", .codec_dai_name = "wm9712-hifi", .cpu_dai_name = "mpc5200-psc-ac97.0", - .platform_name = "mpc5200-pcm-audio", .codec_name = "wm9712-codec", }, { @@ -36,44 +35,74 @@ static struct snd_soc_dai_link pcm030_fabric_dai[] = { .stream_name = "AC97 IEC958", .codec_dai_name = "wm9712-aux", .cpu_dai_name = "mpc5200-psc-ac97.1", - .platform_name = "mpc5200-pcm-audio", .codec_name = "wm9712-codec", }, }; -static struct snd_soc_card card = { +static struct snd_soc_card pcm030_card = { .name = "pcm030", .owner = THIS_MODULE, .dai_link = pcm030_fabric_dai, .num_links = ARRAY_SIZE(pcm030_fabric_dai), }; -static __init int pcm030_fabric_init(void) +static int __init pcm030_fabric_probe(struct platform_device *op) { - struct platform_device *pdev; - int rc; + struct device_node *np = op->dev.of_node; + struct device_node *platform_np; + struct snd_soc_card *card = &pcm030_card; + int ret; + int i; if (!of_machine_is_compatible("phytec,pcm030")) return -ENODEV; - pdev = platform_device_alloc("soc-audio", 1); - if (!pdev) { - pr_err("pcm030_fabric_init: platform_device_alloc() failed\n"); + card->dev = &op->dev; + platform_set_drvdata(op, card); + + platform_np = of_parse_phandle(np, "asoc-platform", 0); + if (!platform_np) { + dev_err(&op->dev, "ac97 not registered\n"); return -ENODEV; } - platform_set_drvdata(pdev, &card); + for (i = 0; i < card->num_links; i++) + card->dai_link[i].platform_of_node = platform_np; - rc = platform_device_add(pdev); - if (rc) { - pr_err("pcm030_fabric_init: platform_device_add() failed\n"); - platform_device_put(pdev); - return -ENODEV; - } - return 0; + ret = snd_soc_register_card(card); + if (ret) + dev_err(&op->dev, "snd_soc_register_card() failed: %d\n", ret); + + return ret; } -module_init(pcm030_fabric_init); +static int __devexit pcm030_fabric_remove(struct platform_device *op) +{ + struct snd_soc_card *card = platform_get_drvdata(op); + int ret; + + ret = snd_soc_unregister_card(card); + + return ret; +} + +static struct of_device_id pcm030_audio_match[] = { + { .compatible = "phytec,pcm030-audio-fabric", }, + {} +}; +MODULE_DEVICE_TABLE(of, pcm030_audio_match); + +static struct platform_driver pcm030_fabric_driver = { + .probe = pcm030_fabric_probe, + .remove = __devexit_p(pcm030_fabric_remove), + .driver = { + .name = DRV_NAME, + .owner = THIS_MODULE, + .of_match_table = pcm030_audio_match, + }, +}; + +module_platform_driver(pcm030_fabric_driver); MODULE_AUTHOR("Jon Smirl "); -- cgit v1.2.3 From c912fa913446b07147f6cbc1a8fa2fb20d2f7c36 Mon Sep 17 00:00:00 2001 From: Eric Millbrandt Date: Thu, 20 Sep 2012 10:36:45 -0400 Subject: ASoC: fsl: register the wm9712-codec The mpc5200-psc-ac97 driver does not enumerate attached ac97 devices, so register the device here. Signed-off-by: Eric Millbrandt Signed-off-by: Mark Brown --- sound/soc/fsl/pcm030-audio-fabric.c | 32 +++++++++++++++++++++++++++++--- 1 file changed, 29 insertions(+), 3 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/fsl/pcm030-audio-fabric.c b/sound/soc/fsl/pcm030-audio-fabric.c index 893e24034816..4b63ec8eb372 100644 --- a/sound/soc/fsl/pcm030-audio-fabric.c +++ b/sound/soc/fsl/pcm030-audio-fabric.c @@ -22,6 +22,11 @@ #define DRV_NAME "pcm030-audio-fabric" +struct pcm030_audio_data { + struct snd_soc_card *card; + struct platform_device *codec_device; +}; + static struct snd_soc_dai_link pcm030_fabric_dai[] = { { .name = "AC97", @@ -51,14 +56,22 @@ static int __init pcm030_fabric_probe(struct platform_device *op) struct device_node *np = op->dev.of_node; struct device_node *platform_np; struct snd_soc_card *card = &pcm030_card; + struct pcm030_audio_data *pdata; int ret; int i; if (!of_machine_is_compatible("phytec,pcm030")) return -ENODEV; + pdata = devm_kzalloc(&op->dev, sizeof(struct pcm030_audio_data), + GFP_KERNEL); + if (!pdata) + return -ENOMEM; + card->dev = &op->dev; - platform_set_drvdata(op, card); + platform_set_drvdata(op, pdata); + + pdata->card = card; platform_np = of_parse_phandle(np, "asoc-platform", 0); if (!platform_np) { @@ -69,6 +82,18 @@ static int __init pcm030_fabric_probe(struct platform_device *op) for (i = 0; i < card->num_links; i++) card->dai_link[i].platform_of_node = platform_np; + ret = request_module("snd-soc-wm9712"); + if (ret) + dev_err(&op->dev, "request_module returned: %d\n", ret); + + pdata->codec_device = platform_device_alloc("wm9712-codec", -1); + if (!pdata->codec_device) + dev_err(&op->dev, "platform_device_alloc() failed\n"); + + ret = platform_device_add(pdata->codec_device); + if (ret) + dev_err(&op->dev, "platform_device_add() failed: %d\n", ret); + ret = snd_soc_register_card(card); if (ret) dev_err(&op->dev, "snd_soc_register_card() failed: %d\n", ret); @@ -78,10 +103,11 @@ static int __init pcm030_fabric_probe(struct platform_device *op) static int __devexit pcm030_fabric_remove(struct platform_device *op) { - struct snd_soc_card *card = platform_get_drvdata(op); + struct pcm030_audio_data *pdata = platform_get_drvdata(op); int ret; - ret = snd_soc_unregister_card(card); + ret = snd_soc_unregister_card(pdata->card); + platform_device_unregister(pdata->codec_device); return ret; } -- cgit v1.2.3 From dffb360e64968b95a0a0221ca52234a28cc049c9 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Fri, 14 Sep 2012 15:05:49 +0300 Subject: ASoC: omap-mcbsp: Use sDMA packet mode instead of frame mode When McBSP is configured in threshold mode we can use sDMA packet mode in all cases. Signed-off-by: Peter Ujfalusi Tested-by: Janusz Krzysztofik Signed-off-by: Mark Brown --- sound/soc/omap/omap-mcbsp.c | 47 ++++++++++++++++----------------------------- 1 file changed, 17 insertions(+), 30 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/omap/omap-mcbsp.c b/sound/soc/omap/omap-mcbsp.c index 2e91a86b6114..fe3debcc2d0b 100644 --- a/sound/soc/omap/omap-mcbsp.c +++ b/sound/soc/omap/omap-mcbsp.c @@ -81,9 +81,6 @@ static void omap_mcbsp_set_threshold(struct snd_pcm_substream *substream) */ if (dma_data->packet_size) words = dma_data->packet_size; - else if (mcbsp->dma_op_mode == MCBSP_DMA_MODE_THRESHOLD) - words = snd_pcm_lib_period_bytes(substream) / - (mcbsp->wlen / 8); else words = 1; @@ -251,6 +248,7 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream, dma_data->set_threshold = omap_mcbsp_set_threshold; if (mcbsp->dma_op_mode == MCBSP_DMA_MODE_THRESHOLD) { int period_words, max_thrsh; + int divider = 0; period_words = params_period_bytes(params) / (wlen / 8); if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) @@ -258,34 +256,23 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream, else max_thrsh = mcbsp->max_rx_thres; /* - * If the period contains less or equal number of words, - * we are using the original threshold mode setup: - * McBSP threshold = sDMA frame size = period_size - * Otherwise we switch to sDMA packet mode: - * McBSP threshold = sDMA packet size - * sDMA frame size = period size + * Use sDMA packet mode if McBSP is in threshold mode: + * If period words less than the FIFO size the packet + * size is set to the number of period words, otherwise + * Look for the biggest threshold value which divides + * the period size evenly. */ - if (period_words > max_thrsh) { - int divider = 0; - - /* - * Look for the biggest threshold value, which - * divides the period size evenly. - */ - divider = period_words / max_thrsh; - if (period_words % max_thrsh) - divider++; - while (period_words % divider && - divider < period_words) - divider++; - if (divider == period_words) - return -EINVAL; - - pkt_size = period_words / divider; - sync_mode = OMAP_DMA_SYNC_PACKET; - } else { - sync_mode = OMAP_DMA_SYNC_FRAME; - } + divider = period_words / max_thrsh; + if (period_words % max_thrsh) + divider++; + while (period_words % divider && + divider < period_words) + divider++; + if (divider == period_words) + return -EINVAL; + + pkt_size = period_words / divider; + sync_mode = OMAP_DMA_SYNC_PACKET; } else if (channels > 1) { /* Use packet mode for non mono streams */ pkt_size = channels; -- cgit v1.2.3 From e512589c17572e7498693a3e05eefa44e622f62b Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Fri, 14 Sep 2012 15:05:50 +0300 Subject: ASoC: omap-pcm: Select sDMA synchronization based on packet_size Since we only have element or packet synchronization we can use the dma_data->packet_size to select the desired mode: if packet_size is 0 we use ELEMENT mode if packet_size is not 0 we use PACKET mode for sDMA synchronization. Signed-off-by: Peter Ujfalusi Tested-by: Janusz Krzysztofik Signed-off-by: Mark Brown --- sound/soc/omap/omap-pcm.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'sound/soc') diff --git a/sound/soc/omap/omap-pcm.c b/sound/soc/omap/omap-pcm.c index f0feb06615f8..02eeb2e7ceda 100644 --- a/sound/soc/omap/omap-pcm.c +++ b/sound/soc/omap/omap-pcm.c @@ -165,7 +165,12 @@ static int omap_pcm_prepare(struct snd_pcm_substream *substream) memset(&dma_params, 0, sizeof(dma_params)); dma_params.data_type = dma_data->data_type; dma_params.trigger = dma_data->dma_req; - dma_params.sync_mode = dma_data->sync_mode; + + if (dma_data->packet_size) + dma_params.sync_mode = OMAP_DMA_SYNC_PACKET; + else + dma_params.sync_mode = OMAP_DMA_SYNC_ELEMENT; + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { dma_params.src_amode = OMAP_DMA_AMODE_POST_INC; dma_params.dst_amode = OMAP_DMA_AMODE_CONSTANT; -- cgit v1.2.3 From 061fb36db7c0187aa90b95f1ba56f6192f42b984 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Fri, 14 Sep 2012 15:05:51 +0300 Subject: ASoC: OMAP: Remove sync_mode from omap_pcm_dma_data struct The omap-pcm platform driver no longer needs this parameter to select between ELEMENT and PACKET mode. The selection is based on the configured packet_size. Signed-off-by: Peter Ujfalusi Tested-by: Janusz Krzysztofik Signed-off-by: Mark Brown --- sound/soc/omap/omap-dmic.c | 1 - sound/soc/omap/omap-hdmi.c | 1 - sound/soc/omap/omap-mcbsp.c | 5 +---- sound/soc/omap/omap-mcpdm.c | 2 -- sound/soc/omap/omap-pcm.h | 1 - 5 files changed, 1 insertion(+), 9 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/omap/omap-dmic.c b/sound/soc/omap/omap-dmic.c index 75f5dca0e8d2..60b7b8cd1c7d 100644 --- a/sound/soc/omap/omap-dmic.c +++ b/sound/soc/omap/omap-dmic.c @@ -64,7 +64,6 @@ struct omap_dmic { static struct omap_pcm_dma_data omap_dmic_dai_dma_params = { .name = "DMIC capture", .data_type = OMAP_DMA_DATA_TYPE_S32, - .sync_mode = OMAP_DMA_SYNC_PACKET, }; static inline void omap_dmic_write(struct omap_dmic *dmic, u16 reg, u32 val) diff --git a/sound/soc/omap/omap-hdmi.c b/sound/soc/omap/omap-hdmi.c index a08245d9203c..b19464697ac8 100644 --- a/sound/soc/omap/omap-hdmi.c +++ b/sound/soc/omap/omap-hdmi.c @@ -290,7 +290,6 @@ static __devinit int omap_hdmi_probe(struct platform_device *pdev) hdmi_data->dma_params.dma_req = hdmi_rsrc->start; hdmi_data->dma_params.name = "HDMI playback"; - hdmi_data->dma_params.sync_mode = OMAP_DMA_SYNC_PACKET; /* * TODO: We assume that there is only one DSS HDMI device. Future diff --git a/sound/soc/omap/omap-mcbsp.c b/sound/soc/omap/omap-mcbsp.c index fe3debcc2d0b..5b3baccd74c3 100644 --- a/sound/soc/omap/omap-mcbsp.c +++ b/sound/soc/omap/omap-mcbsp.c @@ -225,7 +225,7 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream, struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai); struct omap_mcbsp_reg_cfg *regs = &mcbsp->cfg_regs; struct omap_pcm_dma_data *dma_data; - int wlen, channels, wpf, sync_mode = OMAP_DMA_SYNC_ELEMENT; + int wlen, channels, wpf; int pkt_size = 0; unsigned int format, div, framesize, master; @@ -272,15 +272,12 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream, return -EINVAL; pkt_size = period_words / divider; - sync_mode = OMAP_DMA_SYNC_PACKET; } else if (channels > 1) { /* Use packet mode for non mono streams */ pkt_size = channels; - sync_mode = OMAP_DMA_SYNC_PACKET; } } - dma_data->sync_mode = sync_mode; dma_data->packet_size = pkt_size; snd_soc_dai_set_dma_data(cpu_dai, substream, dma_data); diff --git a/sound/soc/omap/omap-mcpdm.c b/sound/soc/omap/omap-mcpdm.c index f7babb374a37..baf92da42aec 100644 --- a/sound/soc/omap/omap-mcpdm.c +++ b/sound/soc/omap/omap-mcpdm.c @@ -73,14 +73,12 @@ static struct omap_pcm_dma_data omap_mcpdm_dai_dma_params[] = { .name = "Audio playback", .dma_req = OMAP44XX_DMA_MCPDM_DL, .data_type = OMAP_DMA_DATA_TYPE_S32, - .sync_mode = OMAP_DMA_SYNC_PACKET, .port_addr = OMAP44XX_MCPDM_L3_BASE + MCPDM_REG_DN_DATA, }, { .name = "Audio capture", .dma_req = OMAP44XX_DMA_MCPDM_UP, .data_type = OMAP_DMA_DATA_TYPE_S32, - .sync_mode = OMAP_DMA_SYNC_PACKET, .port_addr = OMAP44XX_MCPDM_L3_BASE + MCPDM_REG_UP_DATA, }, }; diff --git a/sound/soc/omap/omap-pcm.h b/sound/soc/omap/omap-pcm.h index b92248cbd47a..1bf47e4b60c2 100644 --- a/sound/soc/omap/omap-pcm.h +++ b/sound/soc/omap/omap-pcm.h @@ -33,7 +33,6 @@ struct omap_pcm_dma_data { unsigned long port_addr; /* transmit/receive register */ void (*set_threshold)(struct snd_pcm_substream *substream); int data_type; /* data type 8,16,32 */ - int sync_mode; /* DMA sync mode */ int packet_size; /* packet size only in PACKET mode */ }; -- cgit v1.2.3 From 03945e99a8ac4f596dad9a679816e5b4bb77e5d2 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Fri, 14 Sep 2012 15:05:52 +0300 Subject: ASoC: omap-pcm: Prepare to configure the DMA data_type based on stream properties Based on the format of the stream the omap-pcm can decide alone what data type should be used with by the sDMA. Keep the possibility for OMAP dai drivers to tell omap-pcm if they want to use different data type. This is needed for the omap-hdmi for example which needs 32bit data type even if the stream format is S16_LE. The check if (dma_data->data_type) is safe at the moment since omap-pcm does not support 8bit samples (OMAP_DMA_DATA_TYPE_S8 == 0x00). The next step is to redefine the meaning of dma_data->data_type to unblock this limitation. Signed-off-by: Peter Ujfalusi Tested-by: Janusz Krzysztofik Signed-off-by: Mark Brown --- sound/soc/omap/omap-pcm.c | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/omap/omap-pcm.c b/sound/soc/omap/omap-pcm.c index 02eeb2e7ceda..4c13a5f4eebb 100644 --- a/sound/soc/omap/omap-pcm.c +++ b/sound/soc/omap/omap-pcm.c @@ -149,6 +149,24 @@ static int omap_pcm_hw_free(struct snd_pcm_substream *substream) return 0; } +static int omap_pcm_get_dma_type(int num_bits) +{ + int data_type; + + switch (num_bits) { + case 16: + data_type = OMAP_DMA_DATA_TYPE_S16; + break; + case 32: + data_type = OMAP_DMA_DATA_TYPE_S32; + break; + default: + data_type = -EINVAL; + break; + } + return data_type; +} + static int omap_pcm_prepare(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; @@ -163,7 +181,16 @@ static int omap_pcm_prepare(struct snd_pcm_substream *substream) return 0; memset(&dma_params, 0, sizeof(dma_params)); - dma_params.data_type = dma_data->data_type; + + if (dma_data->data_type) + dma_params.data_type = dma_data->data_type; + else + dma_params.data_type = omap_pcm_get_dma_type( + snd_pcm_format_physical_width(runtime->format)); + + if (dma_params.data_type < 0) + return dma_params.data_type; + dma_params.trigger = dma_data->dma_req; if (dma_data->packet_size) @@ -195,7 +222,7 @@ static int omap_pcm_prepare(struct snd_pcm_substream *substream) * still can get an interrupt at each period bounary */ bytes = snd_pcm_lib_period_bytes(substream); - dma_params.elem_count = bytes >> dma_data->data_type; + dma_params.elem_count = bytes >> dma_params.data_type; dma_params.frame_count = runtime->periods; omap_set_dma_params(prtd->dma_ch, &dma_params); -- cgit v1.2.3 From 5a40c57af55b17dabe25854c9245171515bb5d23 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Fri, 14 Sep 2012 15:05:54 +0300 Subject: ASoC: omap-mcpdm: Use platform_get_resource_* to get resources Get the needed resources in a correct way and avoid using defines for them. Signed-off-by: Peter Ujfalusi Tested-by: Janusz Krzysztofik Signed-off-by: Mark Brown --- sound/soc/omap/omap-mcpdm.c | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/omap/omap-mcpdm.c b/sound/soc/omap/omap-mcpdm.c index baf92da42aec..f90d5de605c3 100644 --- a/sound/soc/omap/omap-mcpdm.c +++ b/sound/soc/omap/omap-mcpdm.c @@ -71,15 +71,11 @@ struct omap_mcpdm { static struct omap_pcm_dma_data omap_mcpdm_dai_dma_params[] = { { .name = "Audio playback", - .dma_req = OMAP44XX_DMA_MCPDM_DL, .data_type = OMAP_DMA_DATA_TYPE_S32, - .port_addr = OMAP44XX_MCPDM_L3_BASE + MCPDM_REG_DN_DATA, }, { .name = "Audio capture", - .dma_req = OMAP44XX_DMA_MCPDM_UP, .data_type = OMAP_DMA_DATA_TYPE_S32, - .port_addr = OMAP44XX_MCPDM_L3_BASE + MCPDM_REG_UP_DATA, }, }; @@ -452,10 +448,33 @@ static __devinit int asoc_mcpdm_probe(struct platform_device *pdev) mutex_init(&mcpdm->mutex); + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dma"); + if (res == NULL) + return -ENOMEM; + + omap_mcpdm_dai_dma_params[0].port_addr = res->start + MCPDM_REG_DN_DATA; + omap_mcpdm_dai_dma_params[1].port_addr = res->start + MCPDM_REG_UP_DATA; + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (res == NULL) return -ENOMEM; + res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "dn_link"); + if (!res) + return -ENODEV; + + omap_mcpdm_dai_dma_params[0].dma_req = res->start; + + res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "up_link"); + if (!res) + return -ENODEV; + + omap_mcpdm_dai_dma_params[1].dma_req = res->start; + + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mpu"); + if (res == NULL) + return -ENOMEM; + if (!devm_request_mem_region(&pdev->dev, res->start, resource_size(res), "McPDM")) return -EBUSY; -- cgit v1.2.3 From 04564e3258304df607d4536de42603b4c8e21e1a Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Fri, 14 Sep 2012 15:05:55 +0300 Subject: ASoC: OMAP: mcbsp, mcpdm, dmic: Let omap-pcm to pick the dma_type omap-pcm can figure out the correct dma_type based on the stream's format. In this way we can get rid of the plat/dma.h include from these drivers. Signed-off-by: Peter Ujfalusi Tested-by: Janusz Krzysztofik Signed-off-by: Mark Brown --- sound/soc/omap/omap-dmic.c | 2 -- sound/soc/omap/omap-mcbsp.c | 3 --- sound/soc/omap/omap-mcpdm.c | 3 --- 3 files changed, 8 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/omap/omap-dmic.c b/sound/soc/omap/omap-dmic.c index 60b7b8cd1c7d..df0ff247f496 100644 --- a/sound/soc/omap/omap-dmic.c +++ b/sound/soc/omap/omap-dmic.c @@ -33,7 +33,6 @@ #include #include #include -#include #include #include @@ -63,7 +62,6 @@ struct omap_dmic { */ static struct omap_pcm_dma_data omap_dmic_dai_dma_params = { .name = "DMIC capture", - .data_type = OMAP_DMA_DATA_TYPE_S32, }; static inline void omap_dmic_write(struct omap_dmic *dmic, u16 reg, u32 val) diff --git a/sound/soc/omap/omap-mcbsp.c b/sound/soc/omap/omap-mcbsp.c index 5b3baccd74c3..a23064644e58 100644 --- a/sound/soc/omap/omap-mcbsp.c +++ b/sound/soc/omap/omap-mcbsp.c @@ -34,7 +34,6 @@ #include #include -#include #include #include "mcbsp.h" #include "omap-mcbsp.h" @@ -234,11 +233,9 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream, switch (params_format(params)) { case SNDRV_PCM_FORMAT_S16_LE: - dma_data->data_type = OMAP_DMA_DATA_TYPE_S16; wlen = 16; break; case SNDRV_PCM_FORMAT_S32_LE: - dma_data->data_type = OMAP_DMA_DATA_TYPE_S32; wlen = 32; break; default: diff --git a/sound/soc/omap/omap-mcpdm.c b/sound/soc/omap/omap-mcpdm.c index f90d5de605c3..84743d47e687 100644 --- a/sound/soc/omap/omap-mcpdm.c +++ b/sound/soc/omap/omap-mcpdm.c @@ -40,7 +40,6 @@ #include #include -#include #include #include "omap-mcpdm.h" #include "omap-pcm.h" @@ -71,11 +70,9 @@ struct omap_mcpdm { static struct omap_pcm_dma_data omap_mcpdm_dai_dma_params[] = { { .name = "Audio playback", - .data_type = OMAP_DMA_DATA_TYPE_S32, }, { .name = "Audio capture", - .data_type = OMAP_DMA_DATA_TYPE_S32, }, }; -- cgit v1.2.3 From f05cc9dac99ac6403d057d2cccb3c754714d2f32 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Fri, 14 Sep 2012 15:05:56 +0300 Subject: ASoC: omap-pcm, omap-dmic: Change the use of omap_pcm_dma_data->data_type Instead of the OMAP DMA data type definition the data_type will be used to specify the number of bits the DMA word should be configured or 0 in case when based on the stream's format the omap-pcm can decide the needed DMA word size. This feature is needed for the omap-hdmi where the sDMA need to be configured for 32bit word type regardless of the audio format used. Signed-off-by: Peter Ujfalusi Tested-by: Janusz Krzysztofik Signed-off-by: Mark Brown --- sound/soc/omap/omap-hdmi.c | 3 +-- sound/soc/omap/omap-pcm.c | 3 ++- sound/soc/omap/omap-pcm.h | 3 ++- 3 files changed, 5 insertions(+), 4 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/omap/omap-hdmi.c b/sound/soc/omap/omap-hdmi.c index b19464697ac8..095176738fd6 100644 --- a/sound/soc/omap/omap-hdmi.c +++ b/sound/soc/omap/omap-hdmi.c @@ -34,7 +34,6 @@ #include #include