ASoC: arizona: Implement OPCLK support

Arizona devices support two output system clocks. Provide support for
configuring these via set_sysclk(). Once the clock API is more useful
we should migrate over to that.

Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
This commit is contained in:
Mark Brown 2012-08-08 17:52:44 +01:00
parent 28d528c8db
commit cbd840dade
2 changed files with 70 additions and 2 deletions

View file

@ -229,6 +229,69 @@ int arizona_out_ev(struct snd_soc_dapm_widget *w,
}
EXPORT_SYMBOL_GPL(arizona_out_ev);
static unsigned int arizona_sysclk_48k_rates[] = {
6144000,
12288000,
22579200,
49152000,
};
static unsigned int arizona_sysclk_44k1_rates[] = {
5644800,
11289600,
24576000,
45158400,
};
static int arizona_set_opclk(struct snd_soc_codec *codec, unsigned int clk,
unsigned int freq)
{
struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
unsigned int reg;
unsigned int *rates;
int ref, div, refclk;
switch (clk) {
case ARIZONA_CLK_OPCLK:
reg = ARIZONA_OUTPUT_SYSTEM_CLOCK;
refclk = priv->sysclk;
break;
case ARIZONA_CLK_ASYNC_OPCLK:
reg = ARIZONA_OUTPUT_ASYNC_CLOCK;
refclk = priv->asyncclk;
break;
default:
return -EINVAL;
}
if (refclk % 8000)
rates = arizona_sysclk_44k1_rates;
else
rates = arizona_sysclk_48k_rates;
for (ref = 0; ref < ARRAY_SIZE(arizona_sysclk_48k_rates) &&
rates[ref] <= refclk; ref++) {
div = 1;
while (rates[ref] / div >= freq && div < 32) {
if (rates[ref] / div == freq) {
dev_dbg(codec->dev, "Configured %dHz OPCLK\n",
freq);
snd_soc_update_bits(codec, reg,
ARIZONA_OPCLK_DIV_MASK |
ARIZONA_OPCLK_SEL_MASK,
(div <<
ARIZONA_OPCLK_DIV_SHIFT) |
ref);
return 0;
}
div++;
}
}
dev_err(codec->dev, "Unable to generate %dHz OPCLK\n", freq);
return -EINVAL;
}
int arizona_set_sysclk(struct snd_soc_codec *codec, int clk_id,
int source, unsigned int freq, int dir)
{
@ -252,6 +315,9 @@ int arizona_set_sysclk(struct snd_soc_codec *codec, int clk_id,
reg = ARIZONA_ASYNC_CLOCK_1;
clk = &priv->asyncclk;
break;
case ARIZONA_CLK_OPCLK:
case ARIZONA_CLK_ASYNC_OPCLK:
return arizona_set_opclk(codec, clk_id, freq);
default:
return -EINVAL;
}

View file

@ -17,8 +17,10 @@
#include <sound/soc.h>
#define ARIZONA_CLK_SYSCLK 1
#define ARIZONA_CLK_ASYNCCLK 2
#define ARIZONA_CLK_SYSCLK 1
#define ARIZONA_CLK_ASYNCCLK 2
#define ARIZONA_CLK_OPCLK 3
#define ARIZONA_CLK_ASYNC_OPCLK 4
#define ARIZONA_CLK_SRC_MCLK1 0x0
#define ARIZONA_CLK_SRC_MCLK2 0x1