Commit 419e2f50 authored by Sylwester Nawrocki's avatar Sylwester Nawrocki Committed by Mark Brown

ASoC: wm8994: Add support for setting MCLK clock rate

Extend the set_sysclk() handler so we also set frequency of the MCLK1,
MCLK2 clocks through clk API when those clocks are specified in DT.
Reviewed-by: default avatarCharles Keepax <ckeepax@opensource.cirrus.com>
Acked-by: default avatarKrzysztof Kozlowski <krzk@kernel.org>
Signed-off-by: default avatarSylwester Nawrocki <s.nawrocki@samsung.com>
Acked-by: default avatarKrzysztof Kozlowski <krzk@kernel.org>
Link: https://lore.kernel.org/r/20190920130218.32690-4-s.nawrocki@samsung.comSigned-off-by: default avatarMark Brown <broonie@kernel.org>
parent 7cf28047
...@@ -167,12 +167,12 @@ static int configure_aif_clock(struct snd_soc_component *component, int aif) ...@@ -167,12 +167,12 @@ static int configure_aif_clock(struct snd_soc_component *component, int aif)
switch (wm8994->sysclk[aif]) { switch (wm8994->sysclk[aif]) {
case WM8994_SYSCLK_MCLK1: case WM8994_SYSCLK_MCLK1:
rate = wm8994->mclk[0]; rate = wm8994->mclk_rate[0];
break; break;
case WM8994_SYSCLK_MCLK2: case WM8994_SYSCLK_MCLK2:
reg1 |= 0x8; reg1 |= 0x8;
rate = wm8994->mclk[1]; rate = wm8994->mclk_rate[1];
break; break;
case WM8994_SYSCLK_FLL1: case WM8994_SYSCLK_FLL1:
...@@ -2367,12 +2367,29 @@ static int wm8994_set_fll(struct snd_soc_dai *dai, int id, int src, ...@@ -2367,12 +2367,29 @@ static int wm8994_set_fll(struct snd_soc_dai *dai, int id, int src,
return _wm8994_set_fll(dai->component, id, src, freq_in, freq_out); return _wm8994_set_fll(dai->component, id, src, freq_in, freq_out);
} }
static int wm8994_set_mclk_rate(struct wm8994_priv *wm8994, unsigned int id,
unsigned int *freq)
{
int ret;
if (!wm8994->mclk[id].clk || *freq == wm8994->mclk_rate[id])
return 0;
ret = clk_set_rate(wm8994->mclk[id].clk, *freq);
if (ret < 0)
return ret;
*freq = clk_get_rate(wm8994->mclk[id].clk);
return 0;
}
static int wm8994_set_dai_sysclk(struct snd_soc_dai *dai, static int wm8994_set_dai_sysclk(struct snd_soc_dai *dai,
int clk_id, unsigned int freq, int dir) int clk_id, unsigned int freq, int dir)
{ {
struct snd_soc_component *component = dai->component; struct snd_soc_component *component = dai->component;
struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(component); struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(component);
int i; int ret, i;
switch (dai->id) { switch (dai->id) {
case 1: case 1:
...@@ -2387,7 +2404,12 @@ static int wm8994_set_dai_sysclk(struct snd_soc_dai *dai, ...@@ -2387,7 +2404,12 @@ static int wm8994_set_dai_sysclk(struct snd_soc_dai *dai,
switch (clk_id) { switch (clk_id) {
case WM8994_SYSCLK_MCLK1: case WM8994_SYSCLK_MCLK1:
wm8994->sysclk[dai->id - 1] = WM8994_SYSCLK_MCLK1; wm8994->sysclk[dai->id - 1] = WM8994_SYSCLK_MCLK1;
wm8994->mclk[0] = freq;
ret = wm8994_set_mclk_rate(wm8994, dai->id - 1, &freq);
if (ret < 0)
return ret;
wm8994->mclk_rate[0] = freq;
dev_dbg(dai->dev, "AIF%d using MCLK1 at %uHz\n", dev_dbg(dai->dev, "AIF%d using MCLK1 at %uHz\n",
dai->id, freq); dai->id, freq);
break; break;
...@@ -2395,7 +2417,12 @@ static int wm8994_set_dai_sysclk(struct snd_soc_dai *dai, ...@@ -2395,7 +2417,12 @@ static int wm8994_set_dai_sysclk(struct snd_soc_dai *dai,
case WM8994_SYSCLK_MCLK2: case WM8994_SYSCLK_MCLK2:
/* TODO: Set GPIO AF */ /* TODO: Set GPIO AF */
wm8994->sysclk[dai->id - 1] = WM8994_SYSCLK_MCLK2; wm8994->sysclk[dai->id - 1] = WM8994_SYSCLK_MCLK2;
wm8994->mclk[1] = freq;
ret = wm8994_set_mclk_rate(wm8994, dai->id - 1, &freq);
if (ret < 0)
return ret;
wm8994->mclk_rate[1] = freq;
dev_dbg(dai->dev, "AIF%d using MCLK2 at %uHz\n", dev_dbg(dai->dev, "AIF%d using MCLK2 at %uHz\n",
dai->id, freq); dai->id, freq);
break; break;
...@@ -4447,6 +4474,7 @@ static const struct snd_soc_component_driver soc_component_dev_wm8994 = { ...@@ -4447,6 +4474,7 @@ static const struct snd_soc_component_driver soc_component_dev_wm8994 = {
static int wm8994_probe(struct platform_device *pdev) static int wm8994_probe(struct platform_device *pdev)
{ {
struct wm8994_priv *wm8994; struct wm8994_priv *wm8994;
int ret;
wm8994 = devm_kzalloc(&pdev->dev, sizeof(struct wm8994_priv), wm8994 = devm_kzalloc(&pdev->dev, sizeof(struct wm8994_priv),
GFP_KERNEL); GFP_KERNEL);
...@@ -4458,6 +4486,16 @@ static int wm8994_probe(struct platform_device *pdev) ...@@ -4458,6 +4486,16 @@ static int wm8994_probe(struct platform_device *pdev)
wm8994->wm8994 = dev_get_drvdata(pdev->dev.parent); wm8994->wm8994 = dev_get_drvdata(pdev->dev.parent);
wm8994->mclk[WM8994_MCLK1].id = "MCLK1";
wm8994->mclk[WM8994_MCLK2].id = "MCLK2";
ret = devm_clk_bulk_get_optional(pdev->dev.parent, ARRAY_SIZE(wm8994->mclk),
wm8994->mclk);
if (ret < 0) {
dev_err(&pdev->dev, "Failed to get clocks: %d\n", ret);
return ret;
}
pm_runtime_enable(&pdev->dev); pm_runtime_enable(&pdev->dev);
pm_runtime_idle(&pdev->dev); pm_runtime_idle(&pdev->dev);
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#ifndef _WM8994_H #ifndef _WM8994_H
#define _WM8994_H #define _WM8994_H
#include <linux/clk.h>
#include <sound/soc.h> #include <sound/soc.h>
#include <linux/firmware.h> #include <linux/firmware.h>
#include <linux/completion.h> #include <linux/completion.h>
...@@ -14,6 +15,12 @@ ...@@ -14,6 +15,12 @@
#include "wm_hubs.h" #include "wm_hubs.h"
enum {
WM8994_MCLK1,
WM8994_MCLK2,
WM8994_NUM_MCLK
};
/* Sources for AIF1/2 SYSCLK - use with set_dai_sysclk() */ /* Sources for AIF1/2 SYSCLK - use with set_dai_sysclk() */
#define WM8994_SYSCLK_MCLK1 1 #define WM8994_SYSCLK_MCLK1 1
#define WM8994_SYSCLK_MCLK2 2 #define WM8994_SYSCLK_MCLK2 2
...@@ -73,9 +80,10 @@ struct wm8994; ...@@ -73,9 +80,10 @@ struct wm8994;
struct wm8994_priv { struct wm8994_priv {
struct wm_hubs_data hubs; struct wm_hubs_data hubs;
struct wm8994 *wm8994; struct wm8994 *wm8994;
struct clk_bulk_data mclk[WM8994_NUM_MCLK];
int sysclk[2]; int sysclk[2];
int sysclk_rate[2]; int sysclk_rate[2];
int mclk[2]; int mclk_rate[2];
int aifclk[2]; int aifclk[2];
int aifdiv[2]; int aifdiv[2];
int channels[2]; int channels[2];
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment