ASoC: msm8226: Add support to enable codec external MCLK
Add support to enable the clock and the PMIC GPIO needed for
clock used by WCD9306 codec.
Change-Id: Icd50d7b929821f79ad3eca9a02175dd72c27c1ac
Signed-off-by: Bhalchandra Gajare <gajare@codeaurora.org>
diff --git a/arch/arm/mach-msm/clock-8226.c b/arch/arm/mach-msm/clock-8226.c
index 813b210..1a28189 100644
--- a/arch/arm/mach-msm/clock-8226.c
+++ b/arch/arm/mach-msm/clock-8226.c
@@ -3350,6 +3350,15 @@
CLK_LOOKUP("", mmss_mmssnoc_bto_ahb_clk.c, ""),
CLK_LOOKUP("", mmss_mmssnoc_axi_clk.c, ""),
CLK_LOOKUP("", mmss_s0_axi_clk.c, ""),
+
+ /* Audio clocks */
+ CLK_LOOKUP("osr_clk", div_clk1.c, "msm-dai-q6-dev.224"),
+ CLK_LOOKUP("osr_clk", div_clk1.c, "msm-dai-q6-dev.4106"),
+ CLK_LOOKUP("osr_clk", div_clk1.c, "msm-dai-q6-dev.16384"),
+ CLK_LOOKUP("osr_clk", div_clk1.c, "msm-dai-q6-dev.16386"),
+ CLK_LOOKUP("osr_clk", div_clk1.c, "msm-dai-q6-dev.16390"),
+ CLK_LOOKUP("osr_clk", div_clk1.c, "msm-dai-q6-dev.16391"),
+
};
static struct clk_lookup msm_clocks_8226_rumi[] = {
diff --git a/sound/soc/msm/msm8226.c b/sound/soc/msm/msm8226.c
index 7766b60..4c92aab 100644
--- a/sound/soc/msm/msm8226.c
+++ b/sound/soc/msm/msm8226.c
@@ -84,6 +84,7 @@
static int msm_btsco_ch = 1;
static struct mutex cdc_mclk_mutex;
+static struct clk *codec_clk;
static int clk_users;
static int msm_snd_enable_codec_ext_clk(struct snd_soc_codec *codec, int enable,
@@ -95,21 +96,35 @@
mutex_lock(&cdc_mclk_mutex);
if (enable) {
+ if (!codec_clk) {
+ dev_err(codec->dev, "%s: did not get Taiko MCLK\n",
+ __func__);
+ ret = -EINVAL;
+ goto exit;
+ }
clk_users++;
if (clk_users != 1)
goto exit;
- /* TODO: clk_disable */
- tapan_mclk_enable(codec, 1, dapm);
+ if (codec_clk) {
+ clk_set_rate(codec_clk, TAPAN_EXT_CLK_RATE);
+ clk_prepare_enable(codec_clk);
+ tapan_mclk_enable(codec, 1, dapm);
+ } else {
+ pr_err("%s: Error setting Tapan MCLK\n", __func__);
+ clk_users--;
+ ret = -EINVAL;
+ goto exit;
+ }
} else {
if (clk_users > 0) {
clk_users--;
if (clk_users == 0) {
tapan_mclk_enable(codec, 0, dapm);
- /* TODO: clk_enable */
+ clk_disable_unprepare(codec_clk);
}
} else {
- pr_err("%s: Error releasing Tabla MCLK\n", __func__);
+ pr_err("%s: Error releasing Tapan MCLK\n", __func__);
ret = -EINVAL;
goto exit;
}
@@ -349,6 +364,11 @@
snd_soc_dapm_sync(dapm);
+ codec_clk = clk_get(cpu_dai->dev, "osr_clk");
+ if (codec_clk < 0)
+ pr_err("%s() Failed to get clock for %s\n",
+ __func__, dev_name(cpu_dai->dev));
+
snd_soc_dai_set_channel_map(codec_dai, ARRAY_SIZE(tx_ch),
tx_ch, ARRAY_SIZE(rx_ch), rx_ch);
@@ -957,6 +977,17 @@
static int msm8226_prepare_codec_mclk(struct snd_soc_card *card)
{
+ struct msm8226_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card);
+ int ret;
+ if (pdata->mclk_gpio) {
+ ret = gpio_request(pdata->mclk_gpio, "TAPAN_CODEC_PMIC_MCLK");
+ if (ret) {
+ dev_err(card->dev,
+ "%s: Failed to request taiko mclk gpio %d\n",
+ __func__, pdata->mclk_gpio);
+ return ret;
+ }
+ }
return 0;
}
@@ -1008,7 +1039,16 @@
goto err;
}
- /* TODO: MCLK GPIO */
+ pdata->mclk_gpio = of_get_named_gpio(pdev->dev.of_node,
+ "qcom,cdc-mclk-gpios", 0);
+ if (pdata->mclk_gpio < 0) {
+ dev_err(&pdev->dev,
+ "Looking up %s property in node %s failed %d\n",
+ "qcom, cdc-mclk-gpios", pdev->dev.of_node->full_name,
+ pdata->mclk_gpio);
+ ret = -ENODEV;
+ goto err;
+ }
ret = msm8226_prepare_codec_mclk(card);
if (ret)
@@ -1024,6 +1064,12 @@
return 0;
err:
+ if (pdata->mclk_gpio > 0) {
+ dev_dbg(&pdev->dev, "%s free gpio %d\n",
+ __func__, pdata->mclk_gpio);
+ gpio_free(pdata->mclk_gpio);
+ pdata->mclk_gpio = 0;
+ }
devm_kfree(&pdev->dev, pdata);
return ret;
}
@@ -1031,8 +1077,9 @@
static int __devexit msm8226_asoc_machine_remove(struct platform_device *pdev)
{
struct snd_soc_card *card = platform_get_drvdata(pdev);
+ struct msm8226_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card);
- /* TODO: GPIO MCLK */
+ gpio_free(pdata->mclk_gpio);
snd_soc_unregister_card(card);
return 0;