Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 70543c30 authored by John Hsu's avatar John Hsu Committed by Mark Brown
Browse files

ASoC: nau8825: support different clock source for FLL function



Extend FLL clock source selection. The source can be from MCLK, BCLK or FS.

Signed-off-by: default avatarJohn Hsu <KCHSU0@nuvoton.com>
Signed-off-by: default avatarMark Brown <broonie@kernel.org>
parent 1a695a90
Loading
Loading
Loading
Loading
+59 −23
Original line number Diff line number Diff line
@@ -1069,21 +1069,15 @@ static int nau8825_set_pll(struct snd_soc_codec *codec, int pll_id, int source,
	return 0;
}

static int nau8825_configure_sysclk(struct nau8825 *nau8825, int clk_id,
	unsigned int freq)
static int nau8825_mclk_prepare(struct nau8825 *nau8825, unsigned int freq)
{
	struct regmap *regmap = nau8825->regmap;
	int ret;

	switch (clk_id) {
	case NAU8825_CLK_MCLK:
		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);
	int ret = 0;

		/* We selected MCLK source but the clock itself managed externally */
		if (!nau8825->mclk)
			break;
	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);
@@ -1094,23 +1088,65 @@ static int nau8825_configure_sysclk(struct nau8825 *nau8825, int clk_id,
	}

	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;
		}
		nau8825->mclk_freq = freq;
	}

	return 0;
}

static int nau8825_configure_sysclk(struct nau8825 *nau8825, int clk_id,
	unsigned int freq)
{
	struct regmap *regmap = nau8825->regmap;
	int ret;

	switch (clk_id) {
	case NAU8825_CLK_MCLK:
		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);
		ret = nau8825_mclk_prepare(nau8825, freq);
		if (ret)
			return ret;

		break;
	case NAU8825_CLK_INTERNAL:
		regmap_update_bits(regmap, NAU8825_REG_FLL6, NAU8825_DCO_EN,
			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;
+8 −0
Original line number Diff line number Diff line
@@ -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 {