diff options
author | Nicolin Chen <b42378@freescale.com> | 2013-08-05 04:26:16 -0400 |
---|---|---|
committer | Nitin Garg <nitin.garg@freescale.com> | 2014-04-16 09:01:02 -0400 |
commit | 007d3504914096760124f2ef13d52da206341a66 (patch) | |
tree | 90f6ed82c55fbe33cecfe427001e491501c75a43 | |
parent | 8db9a2f44a5eecd02be2259a3783178a521ef2d2 (diff) |
ENGR00273838-8 ASoC: WM8962: Let codec driver enable/disable its MCLK
WM8962 needs its MCLK when powerup -- wm8962_resume(). Thus it's better
to control the MCLK in codec driver. Thus remove the clock enable in
machine dirver accordingly.
Acked-by: Wang Shengjiu <b02247@freescale.com>
Signed-off-by: Nicolin Chen <b42378@freescale.com>
-rw-r--r-- | include/sound/wm8962.h | 3 | ||||
-rw-r--r-- | sound/soc/codecs/wm8962.c | 28 | ||||
-rw-r--r-- | sound/soc/fsl/imx-wm8962.c | 30 |
3 files changed, 39 insertions, 22 deletions
diff --git a/include/sound/wm8962.h b/include/sound/wm8962.h index 79e6d427b858..fb261851da21 100644 --- a/include/sound/wm8962.h +++ b/include/sound/wm8962.h | |||
@@ -55,6 +55,9 @@ struct wm8962_pdata { | |||
55 | * in a DC measurement configuration. | 55 | * in a DC measurement configuration. |
56 | */ | 56 | */ |
57 | bool in4_dc_measure; | 57 | bool in4_dc_measure; |
58 | |||
59 | /* MCLK for wm8962 */ | ||
60 | struct clk *codec_mclk; | ||
58 | }; | 61 | }; |
59 | 62 | ||
60 | #endif | 63 | #endif |
diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c index d2e4a3ca44f9..6150875e08fd 100644 --- a/sound/soc/codecs/wm8962.c +++ b/sound/soc/codecs/wm8962.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/init.h> | 16 | #include <linux/init.h> |
17 | #include <linux/delay.h> | 17 | #include <linux/delay.h> |
18 | #include <linux/pm.h> | 18 | #include <linux/pm.h> |
19 | #include <linux/clk.h> | ||
19 | #include <linux/gcd.h> | 20 | #include <linux/gcd.h> |
20 | #include <linux/gpio.h> | 21 | #include <linux/gpio.h> |
21 | #include <linux/i2c.h> | 22 | #include <linux/i2c.h> |
@@ -3608,6 +3609,15 @@ static int wm8962_set_pdata_from_of(struct i2c_client *i2c, | |||
3608 | pdata->gpio_init[i] = 0x0; | 3609 | pdata->gpio_init[i] = 0x0; |
3609 | } | 3610 | } |
3610 | 3611 | ||
3612 | pdata->codec_mclk = devm_clk_get(&i2c->dev, NULL); | ||
3613 | |||
3614 | /* | ||
3615 | * If clk_get() failed, we assume that clock's enabled by default. | ||
3616 | * Otherwise, we let driver prepare and control the clock source. | ||
3617 | */ | ||
3618 | if (IS_ERR(pdata->codec_mclk)) | ||
3619 | pdata->codec_mclk = NULL; | ||
3620 | |||
3611 | return 0; | 3621 | return 0; |
3612 | } | 3622 | } |
3613 | 3623 | ||
@@ -3639,6 +3649,9 @@ static int wm8962_i2c_probe(struct i2c_client *i2c, | |||
3639 | return ret; | 3649 | return ret; |
3640 | } | 3650 | } |
3641 | 3651 | ||
3652 | if (wm8962->pdata.codec_mclk) | ||
3653 | clk_prepare(wm8962->pdata.codec_mclk); | ||
3654 | |||
3642 | for (i = 0; i < ARRAY_SIZE(wm8962->supplies); i++) | 3655 | for (i = 0; i < ARRAY_SIZE(wm8962->supplies); i++) |
3643 | wm8962->supplies[i].supply = wm8962_supply_names[i]; | 3656 | wm8962->supplies[i].supply = wm8962_supply_names[i]; |
3644 | 3657 | ||
@@ -3730,11 +3743,19 @@ static int wm8962_i2c_probe(struct i2c_client *i2c, | |||
3730 | err_enable: | 3743 | err_enable: |
3731 | regulator_bulk_disable(ARRAY_SIZE(wm8962->supplies), wm8962->supplies); | 3744 | regulator_bulk_disable(ARRAY_SIZE(wm8962->supplies), wm8962->supplies); |
3732 | err: | 3745 | err: |
3746 | if (wm8962->pdata.codec_mclk) | ||
3747 | clk_unprepare(wm8962->pdata.codec_mclk); | ||
3748 | |||
3733 | return ret; | 3749 | return ret; |
3734 | } | 3750 | } |
3735 | 3751 | ||
3736 | static int wm8962_i2c_remove(struct i2c_client *client) | 3752 | static int wm8962_i2c_remove(struct i2c_client *client) |
3737 | { | 3753 | { |
3754 | struct wm8962_priv *wm8962 = dev_get_drvdata(&client->dev); | ||
3755 | |||
3756 | if (wm8962->pdata.codec_mclk) | ||
3757 | clk_unprepare(wm8962->pdata.codec_mclk); | ||
3758 | |||
3738 | snd_soc_unregister_codec(&client->dev); | 3759 | snd_soc_unregister_codec(&client->dev); |
3739 | return 0; | 3760 | return 0; |
3740 | } | 3761 | } |
@@ -3745,6 +3766,9 @@ static int wm8962_runtime_resume(struct device *dev) | |||
3745 | struct wm8962_priv *wm8962 = dev_get_drvdata(dev); | 3766 | struct wm8962_priv *wm8962 = dev_get_drvdata(dev); |
3746 | int ret; | 3767 | int ret; |
3747 | 3768 | ||
3769 | if (wm8962->pdata.codec_mclk) | ||
3770 | clk_enable(wm8962->pdata.codec_mclk); | ||
3771 | |||
3748 | ret = regulator_bulk_enable(ARRAY_SIZE(wm8962->supplies), | 3772 | ret = regulator_bulk_enable(ARRAY_SIZE(wm8962->supplies), |
3749 | wm8962->supplies); | 3773 | wm8962->supplies); |
3750 | if (ret != 0) { | 3774 | if (ret != 0) { |
@@ -3804,6 +3828,10 @@ static int wm8962_runtime_suspend(struct device *dev) | |||
3804 | regulator_bulk_disable(ARRAY_SIZE(wm8962->supplies), | 3828 | regulator_bulk_disable(ARRAY_SIZE(wm8962->supplies), |
3805 | wm8962->supplies); | 3829 | wm8962->supplies); |
3806 | 3830 | ||
3831 | if (wm8962->pdata.codec_mclk) | ||
3832 | clk_disable(wm8962->pdata.codec_mclk); | ||
3833 | |||
3834 | |||
3807 | return 0; | 3835 | return 0; |
3808 | } | 3836 | } |
3809 | #endif | 3837 | #endif |
diff --git a/sound/soc/fsl/imx-wm8962.c b/sound/soc/fsl/imx-wm8962.c index f2840d39a31a..1644c6c12b81 100644 --- a/sound/soc/fsl/imx-wm8962.c +++ b/sound/soc/fsl/imx-wm8962.c | |||
@@ -33,7 +33,6 @@ struct imx_wm8962_data { | |||
33 | struct snd_soc_card card; | 33 | struct snd_soc_card card; |
34 | char codec_dai_name[DAI_NAME_SIZE]; | 34 | char codec_dai_name[DAI_NAME_SIZE]; |
35 | char platform_name[DAI_NAME_SIZE]; | 35 | char platform_name[DAI_NAME_SIZE]; |
36 | struct clk *codec_clk; | ||
37 | unsigned int clk_frequency; | 36 | unsigned int clk_frequency; |
38 | }; | 37 | }; |
39 | 38 | ||
@@ -185,6 +184,7 @@ static int imx_wm8962_probe(struct platform_device *pdev) | |||
185 | struct imx_priv *priv = &card_priv; | 184 | struct imx_priv *priv = &card_priv; |
186 | struct i2c_client *codec_dev; | 185 | struct i2c_client *codec_dev; |
187 | struct imx_wm8962_data *data; | 186 | struct imx_wm8962_data *data; |
187 | struct clk *codec_clk = NULL; | ||
188 | int int_port, ext_port; | 188 | int int_port, ext_port; |
189 | int ret; | 189 | int ret; |
190 | 190 | ||
@@ -256,19 +256,14 @@ static int imx_wm8962_probe(struct platform_device *pdev) | |||
256 | goto fail; | 256 | goto fail; |
257 | } | 257 | } |
258 | 258 | ||
259 | data->codec_clk = devm_clk_get(&codec_dev->dev, NULL); | 259 | codec_clk = devm_clk_get(&codec_dev->dev, NULL); |
260 | if (IS_ERR(data->codec_clk)) { | 260 | if (IS_ERR(codec_clk)) { |
261 | ret = PTR_ERR(data->codec_clk); | 261 | ret = PTR_ERR(codec_clk); |
262 | dev_err(&codec_dev->dev, "failed to get codec clk: %d\n", ret); | 262 | dev_err(&codec_dev->dev, "failed to get codec clk: %d\n", ret); |
263 | goto fail; | 263 | goto fail; |
264 | } | 264 | } |
265 | 265 | ||
266 | data->clk_frequency = clk_get_rate(data->codec_clk); | 266 | data->clk_frequency = clk_get_rate(codec_clk); |
267 | ret = clk_prepare_enable(data->codec_clk); | ||
268 | if (ret) { | ||
269 | dev_err(&codec_dev->dev, "failed to enable codec clk: %d\n", ret); | ||
270 | goto fail; | ||
271 | } | ||
272 | 267 | ||
273 | data->dai.name = "HiFi"; | 268 | data->dai.name = "HiFi"; |
274 | data->dai.stream_name = "HiFi"; | 269 | data->dai.stream_name = "HiFi"; |
@@ -283,10 +278,10 @@ static int imx_wm8962_probe(struct platform_device *pdev) | |||
283 | data->card.dev = &pdev->dev; | 278 | data->card.dev = &pdev->dev; |
284 | ret = snd_soc_of_parse_card_name(&data->card, "model"); | 279 | ret = snd_soc_of_parse_card_name(&data->card, "model"); |
285 | if (ret) | 280 | if (ret) |
286 | goto clk_fail; | 281 | goto fail; |
287 | ret = snd_soc_of_parse_audio_routing(&data->card, "audio-routing"); | 282 | ret = snd_soc_of_parse_audio_routing(&data->card, "audio-routing"); |
288 | if (ret) | 283 | if (ret) |
289 | goto clk_fail; | 284 | goto fail; |
290 | data->card.num_links = 1; | 285 | data->card.num_links = 1; |
291 | data->card.dai_link = &data->dai; | 286 | data->card.dai_link = &data->dai; |
292 | data->card.dapm_widgets = imx_wm8962_dapm_widgets; | 287 | data->card.dapm_widgets = imx_wm8962_dapm_widgets; |
@@ -297,18 +292,11 @@ static int imx_wm8962_probe(struct platform_device *pdev) | |||
297 | ret = snd_soc_register_card(&data->card); | 292 | ret = snd_soc_register_card(&data->card); |
298 | if (ret) { | 293 | if (ret) { |
299 | dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret); | 294 | dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret); |
300 | goto clk_fail; | 295 | goto fail; |
301 | } | 296 | } |
302 | 297 | ||
303 | platform_set_drvdata(pdev, data); | 298 | platform_set_drvdata(pdev, data); |
304 | of_node_put(ssi_np); | ||
305 | of_node_put(codec_np); | ||
306 | |||
307 | return 0; | ||
308 | 299 | ||
309 | clk_fail: | ||
310 | if (!IS_ERR(data->codec_clk)) | ||
311 | clk_disable_unprepare(data->codec_clk); | ||
312 | fail: | 300 | fail: |
313 | if (ssi_np) | 301 | if (ssi_np) |
314 | of_node_put(ssi_np); | 302 | of_node_put(ssi_np); |
@@ -322,8 +310,6 @@ static int imx_wm8962_remove(struct platform_device *pdev) | |||
322 | { | 310 | { |
323 | struct imx_wm8962_data *data = platform_get_drvdata(pdev); | 311 | struct imx_wm8962_data *data = platform_get_drvdata(pdev); |
324 | 312 | ||
325 | if (!IS_ERR(data->codec_clk)) | ||
326 | clk_disable_unprepare(data->codec_clk); | ||
327 | snd_soc_unregister_card(&data->card); | 313 | snd_soc_unregister_card(&data->card); |
328 | 314 | ||
329 | return 0; | 315 | return 0; |