diff mbox

ASoC: nau8825: support different clock source for FLL function

Message ID 1458014901-28049-1-git-send-email-KCHSU0@nuvoton.com (mailing list archive)
State Accepted
Commit ac61ae979d92cb99c18c938f5854179ed54d111a
Headers show

Commit Message

AS50 KCHSU0 March 15, 2016, 4:08 a.m. UTC
Extend FLL clock source selection. The source can be from MCLK, BCLK or FS.

Signed-off-by: John Hsu <KCHSU0@nuvoton.com>
---
 sound/soc/codecs/nau8825.c | 82 +++++++++++++++++++++++++++++++++-------------
 sound/soc/codecs/nau8825.h |  8 +++++
 2 files changed, 67 insertions(+), 23 deletions(-)

Comments

Anatol Pomozov March 16, 2016, 11:06 p.m. UTC | #1
Hi

On Mon, Mar 14, 2016 at 9:08 PM, John Hsu <KCHSU0@nuvoton.com> wrote:
> Extend FLL clock source selection. The source can be from MCLK, BCLK or FS.
>
> Signed-off-by: John Hsu <KCHSU0@nuvoton.com>
> ---
>  sound/soc/codecs/nau8825.c | 82 +++++++++++++++++++++++++++++++++-------------
>  sound/soc/codecs/nau8825.h |  8 +++++
>  2 files changed, 67 insertions(+), 23 deletions(-)
>
> diff --git a/sound/soc/codecs/nau8825.c b/sound/soc/codecs/nau8825.c
> index 1c87299..ac264ec 100644
> --- a/sound/soc/codecs/nau8825.c
> +++ b/sound/soc/codecs/nau8825.c
> @@ -1053,6 +1053,37 @@ static int nau8825_set_pll(struct snd_soc_codec *codec, int pll_id, int source,
>         return 0;
>  }
>
> +static int nau8825_mclk_prepare(struct nau8825 *nau8825, unsigned int freq)
> +{
> +       int ret = 0;
> +
> +       nau8825->mclk = devm_clk_get(nau8825->dev, "mclk");
> +       if (IS_ERR(nau8825->mclk)) {

Is it possible that clock system is not ready at this point and the
method returns -EPROBE_DEFER? If so it matches IS_ERR() but not a real
error and the nua8825 driver should backoff and wait a little before
clocks are ready.

> +               dev_info(nau8825->dev, "No 'mclk' clock found, assume MCLK is managed externally");
> +               return 0;
> +       }
> +
> +       if (!nau8825->mclk_freq) {
> +               ret = clk_prepare_enable(nau8825->mclk);
> +               if (ret) {
> +                       dev_err(nau8825->dev, "Unable to prepare codec mclk\n");
> +                       return ret;
> +               }
> +       }
> +
AS50 KCHSU0 March 17, 2016, 3:04 a.m. UTC | #2
Hi,

On 3/17/2016 7:06 AM, Anatol Pomozov wrote:
> Hi
>
> On Mon, Mar 14, 2016 at 9:08 PM, John Hsu <KCHSU0@nuvoton.com> wrote:
>   
>> Extend FLL clock source selection. The source can be from MCLK, BCLK or FS.
>>
>> Signed-off-by: John Hsu <KCHSU0@nuvoton.com>
>> ---
>>  sound/soc/codecs/nau8825.c | 82 +++++++++++++++++++++++++++++++++-------------
>>  sound/soc/codecs/nau8825.h |  8 +++++
>>  2 files changed, 67 insertions(+), 23 deletions(-)
>>
>> diff --git a/sound/soc/codecs/nau8825.c b/sound/soc/codecs/nau8825.c
>> index 1c87299..ac264ec 100644
>> --- a/sound/soc/codecs/nau8825.c
>> +++ b/sound/soc/codecs/nau8825.c
>> @@ -1053,6 +1053,37 @@ static int nau8825_set_pll(struct snd_soc_codec *codec, int pll_id, int source,
>>         return 0;
>>  }
>>
>> +static int nau8825_mclk_prepare(struct nau8825 *nau8825, unsigned int freq)
>> +{
>> +       int ret = 0;
>> +
>> +       nau8825->mclk = devm_clk_get(nau8825->dev, "mclk");
>> +       if (IS_ERR(nau8825->mclk)) {
>>     
>
> Is it possible that clock system is not ready at this point and the
> method returns -EPROBE_DEFER? If so it matches IS_ERR() but not a real
> error and the nua8825 driver should backoff and wait a little before
> clocks are ready.
>
>   

The function is used when playback startup not in the driver initiation.
At this moment, we just skip mclk operation and let thing go on.
Should driver return the errorno to machine driver to handle it?

>> +               dev_info(nau8825->dev, "No 'mclk' clock found, assume MCLK is managed externally");
>> +               return 0;
>> +       }
>> +
>> +       if (!nau8825->mclk_freq) {
>> +               ret = clk_prepare_enable(nau8825->mclk);
>> +               if (ret) {
>> +                       dev_err(nau8825->dev, "Unable to prepare codec mclk\n");
>> +                       return ret;
>> +               }
>> +       }
>> +
>>     
> .
>
>
Mark Brown March 17, 2016, 9:18 a.m. UTC | #3
On Thu, Mar 17, 2016 at 11:04:20AM +0800, John Hsu wrote:
> On 3/17/2016 7:06 AM, Anatol Pomozov wrote:

> >>+       nau8825->mclk = devm_clk_get(nau8825->dev, "mclk");
> >>+       if (IS_ERR(nau8825->mclk)) {

> >Is it possible that clock system is not ready at this point and the
> >method returns -EPROBE_DEFER? If so it matches IS_ERR() but not a real
> >error and the nua8825 driver should backoff and wait a little before
> >clocks are ready.

> The function is used when playback startup not in the driver initiation.
> At this moment, we just skip mclk operation and let thing go on.
> Should driver return the errorno to machine driver to handle it?

Well, what should really be happening here is that the clock is
requested at probe time.
diff mbox

Patch

diff --git a/sound/soc/codecs/nau8825.c b/sound/soc/codecs/nau8825.c
index 1c87299..ac264ec 100644
--- a/sound/soc/codecs/nau8825.c
+++ b/sound/soc/codecs/nau8825.c
@@ -1053,6 +1053,37 @@  static int nau8825_set_pll(struct snd_soc_codec *codec, int pll_id, int source,
 	return 0;
 }
 
+static int nau8825_mclk_prepare(struct nau8825 *nau8825, unsigned int freq)
+{
+	int ret = 0;
+
+	nau8825->mclk = devm_clk_get(nau8825->dev, "mclk");
+	if (IS_ERR(nau8825->mclk)) {
+		dev_info(nau8825->dev, "No 'mclk' clock found, assume MCLK is managed externally");
+		return 0;
+	}
+
+	if (!nau8825->mclk_freq) {
+		ret = clk_prepare_enable(nau8825->mclk);
+		if (ret) {
+			dev_err(nau8825->dev, "Unable to prepare codec mclk\n");
+			return ret;
+		}
+	}
+
+	if (nau8825->mclk_freq != freq) {
+		freq = clk_round_rate(nau8825->mclk, freq);
+		ret = clk_set_rate(nau8825->mclk, freq);
+		if (ret) {
+			dev_err(nau8825->dev, "Unable to set mclk rate\n");
+			return ret;
+		}
+		nau8825->mclk_freq = freq;
+	}
+
+	return 0;
+}
+
 static int nau8825_configure_sysclk(struct nau8825 *nau8825, int clk_id,
 	unsigned int freq)
 {
@@ -1064,29 +1095,9 @@  static int nau8825_configure_sysclk(struct nau8825 *nau8825, int clk_id,
 		regmap_update_bits(regmap, NAU8825_REG_CLK_DIVIDER,
 			NAU8825_CLK_SRC_MASK, NAU8825_CLK_SRC_MCLK);
 		regmap_update_bits(regmap, NAU8825_REG_FLL6, NAU8825_DCO_EN, 0);
-
-		/* We selected MCLK source but the clock itself managed externally */
-		if (!nau8825->mclk)
-			break;
-
-		if (!nau8825->mclk_freq) {
-			ret = clk_prepare_enable(nau8825->mclk);
-			if (ret) {
-				dev_err(nau8825->dev, "Unable to prepare codec mclk\n");
-				return ret;
-			}
-		}
-
-		if (nau8825->mclk_freq != freq) {
-			nau8825->mclk_freq = freq;
-
-			freq = clk_round_rate(nau8825->mclk, freq);
-			ret = clk_set_rate(nau8825->mclk, freq);
-			if (ret) {
-				dev_err(nau8825->dev, "Unable to set mclk rate\n");
-				return ret;
-			}
-		}
+		ret = nau8825_mclk_prepare(nau8825, freq);
+		if (ret)
+			return ret;
 
 		break;
 	case NAU8825_CLK_INTERNAL:
@@ -1094,7 +1105,32 @@  static int nau8825_configure_sysclk(struct nau8825 *nau8825, int clk_id,
 			NAU8825_DCO_EN);
 		regmap_update_bits(regmap, NAU8825_REG_CLK_DIVIDER,
 			NAU8825_CLK_SRC_MASK, NAU8825_CLK_SRC_VCO);
+		if (nau8825->mclk_freq) {
+			clk_disable_unprepare(nau8825->mclk);
+			nau8825->mclk_freq = 0;
+		}
 
+		break;
+	case NAU8825_CLK_FLL_MCLK:
+		regmap_update_bits(regmap, NAU8825_REG_FLL3,
+			NAU8825_FLL_CLK_SRC_MASK, NAU8825_FLL_CLK_SRC_MCLK);
+		ret = nau8825_mclk_prepare(nau8825, freq);
+		if (ret)
+			return ret;
+
+		break;
+	case NAU8825_CLK_FLL_BLK:
+		regmap_update_bits(regmap, NAU8825_REG_FLL3,
+			NAU8825_FLL_CLK_SRC_MASK, NAU8825_FLL_CLK_SRC_BLK);
+		if (nau8825->mclk_freq) {
+			clk_disable_unprepare(nau8825->mclk);
+			nau8825->mclk_freq = 0;
+		}
+
+		break;
+	case NAU8825_CLK_FLL_FS:
+		regmap_update_bits(regmap, NAU8825_REG_FLL3,
+			NAU8825_FLL_CLK_SRC_MASK, NAU8825_FLL_CLK_SRC_FS);
 		if (nau8825->mclk_freq) {
 			clk_disable_unprepare(nau8825->mclk);
 			nau8825->mclk_freq = 0;
diff --git a/sound/soc/codecs/nau8825.h b/sound/soc/codecs/nau8825.h
index 8ceb5f3..ed0d8f3 100644
--- a/sound/soc/codecs/nau8825.h
+++ b/sound/soc/codecs/nau8825.h
@@ -113,6 +113,11 @@ 
 
 /* FLL3 (0x06) */
 #define NAU8825_FLL_INTEGER_MASK		(0x3ff << 0)
+#define NAU8825_FLL_CLK_SRC_SFT		10
+#define NAU8825_FLL_CLK_SRC_MASK		(0x3 << NAU8825_FLL_CLK_SRC_SFT)
+#define NAU8825_FLL_CLK_SRC_MCLK		(0 << NAU8825_FLL_CLK_SRC_SFT)
+#define NAU8825_FLL_CLK_SRC_BLK		(0x2 << NAU8825_FLL_CLK_SRC_SFT)
+#define NAU8825_FLL_CLK_SRC_FS			(0x3 << NAU8825_FLL_CLK_SRC_SFT)
 
 /* FLL4 (0x07) */
 #define NAU8825_FLL_REF_DIV_MASK		(0x3 << 10)
@@ -320,6 +325,9 @@ 
 enum {
 	NAU8825_CLK_MCLK = 0,
 	NAU8825_CLK_INTERNAL,
+	NAU8825_CLK_FLL_MCLK,
+	NAU8825_CLK_FLL_BLK,
+	NAU8825_CLK_FLL_FS,
 };
 
 struct nau8825 {