diff options
Diffstat (limited to 'sound/soc/codecs/ad193x.c')
-rw-r--r-- | sound/soc/codecs/ad193x.c | 41 |
1 files changed, 40 insertions, 1 deletions
diff --git a/sound/soc/codecs/ad193x.c b/sound/soc/codecs/ad193x.c index c8ca1142b2f4..1def75e4862f 100644 --- a/sound/soc/codecs/ad193x.c +++ b/sound/soc/codecs/ad193x.c | |||
@@ -24,6 +24,7 @@ | |||
24 | 24 | ||
25 | /* codec private data */ | 25 | /* codec private data */ |
26 | struct ad193x_priv { | 26 | struct ad193x_priv { |
27 | unsigned int sysclk; | ||
27 | struct snd_soc_codec codec; | 28 | struct snd_soc_codec codec; |
28 | u8 reg_cache[AD193X_NUM_REGS]; | 29 | u8 reg_cache[AD193X_NUM_REGS]; |
29 | }; | 30 | }; |
@@ -251,15 +252,32 @@ static int ad193x_set_dai_fmt(struct snd_soc_dai *codec_dai, | |||
251 | return 0; | 252 | return 0; |
252 | } | 253 | } |
253 | 254 | ||
255 | static int ad193x_set_dai_sysclk(struct snd_soc_dai *codec_dai, | ||
256 | int clk_id, unsigned int freq, int dir) | ||
257 | { | ||
258 | struct snd_soc_codec *codec = codec_dai->codec; | ||
259 | struct ad193x_priv *ad193x = snd_soc_codec_get_drvdata(codec); | ||
260 | switch (freq) { | ||
261 | case 12288000: | ||
262 | case 18432000: | ||
263 | case 24576000: | ||
264 | case 36864000: | ||
265 | ad193x->sysclk = freq; | ||
266 | return 0; | ||
267 | } | ||
268 | return -EINVAL; | ||
269 | } | ||
270 | |||
254 | static int ad193x_hw_params(struct snd_pcm_substream *substream, | 271 | static int ad193x_hw_params(struct snd_pcm_substream *substream, |
255 | struct snd_pcm_hw_params *params, | 272 | struct snd_pcm_hw_params *params, |
256 | struct snd_soc_dai *dai) | 273 | struct snd_soc_dai *dai) |
257 | { | 274 | { |
258 | int word_len = 0, reg = 0; | 275 | int word_len = 0, reg = 0, master_rate = 0; |
259 | 276 | ||
260 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 277 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
261 | struct snd_soc_device *socdev = rtd->socdev; | 278 | struct snd_soc_device *socdev = rtd->socdev; |
262 | struct snd_soc_codec *codec = socdev->card->codec; | 279 | struct snd_soc_codec *codec = socdev->card->codec; |
280 | struct ad193x_priv *ad193x = snd_soc_codec_get_drvdata(codec); | ||
263 | 281 | ||
264 | /* bit size */ | 282 | /* bit size */ |
265 | switch (params_format(params)) { | 283 | switch (params_format(params)) { |
@@ -275,6 +293,25 @@ static int ad193x_hw_params(struct snd_pcm_substream *substream, | |||
275 | break; | 293 | break; |
276 | } | 294 | } |
277 | 295 | ||
296 | switch (ad193x->sysclk) { | ||
297 | case 12288000: | ||
298 | master_rate = AD193X_PLL_INPUT_256; | ||
299 | break; | ||
300 | case 18432000: | ||
301 | master_rate = AD193X_PLL_INPUT_384; | ||
302 | break; | ||
303 | case 24576000: | ||
304 | master_rate = AD193X_PLL_INPUT_512; | ||
305 | break; | ||
306 | case 36864000: | ||
307 | master_rate = AD193X_PLL_INPUT_768; | ||
308 | break; | ||
309 | } | ||
310 | |||
311 | reg = snd_soc_read(codec, AD193X_PLL_CLK_CTRL0); | ||
312 | reg = (reg & AD193X_PLL_INPUT_MASK) | master_rate; | ||
313 | snd_soc_write(codec, AD193X_PLL_CLK_CTRL0, reg); | ||
314 | |||
278 | reg = snd_soc_read(codec, AD193X_DAC_CTRL2); | 315 | reg = snd_soc_read(codec, AD193X_DAC_CTRL2); |
279 | reg = (reg & (~AD193X_DAC_WORD_LEN_MASK)) | word_len; | 316 | reg = (reg & (~AD193X_DAC_WORD_LEN_MASK)) | word_len; |
280 | snd_soc_write(codec, AD193X_DAC_CTRL2, reg); | 317 | snd_soc_write(codec, AD193X_DAC_CTRL2, reg); |
@@ -348,6 +385,7 @@ static int ad193x_bus_probe(struct device *dev, void *ctrl_data, int bus_type) | |||
348 | /* pll input: mclki/xi */ | 385 | /* pll input: mclki/xi */ |
349 | snd_soc_write(codec, AD193X_PLL_CLK_CTRL0, 0x99); /* mclk=24.576Mhz: 0x9D; mclk=12.288Mhz: 0x99 */ | 386 | snd_soc_write(codec, AD193X_PLL_CLK_CTRL0, 0x99); /* mclk=24.576Mhz: 0x9D; mclk=12.288Mhz: 0x99 */ |
350 | snd_soc_write(codec, AD193X_PLL_CLK_CTRL1, 0x04); | 387 | snd_soc_write(codec, AD193X_PLL_CLK_CTRL1, 0x04); |
388 | ad193x->sysclk = 12288000; | ||
351 | 389 | ||
352 | ret = snd_soc_register_codec(codec); | 390 | ret = snd_soc_register_codec(codec); |
353 | if (ret != 0) { | 391 | if (ret != 0) { |
@@ -383,6 +421,7 @@ static struct snd_soc_dai_ops ad193x_dai_ops = { | |||
383 | .hw_params = ad193x_hw_params, | 421 | .hw_params = ad193x_hw_params, |
384 | .digital_mute = ad193x_mute, | 422 | .digital_mute = ad193x_mute, |
385 | .set_tdm_slot = ad193x_set_tdm_slot, | 423 | .set_tdm_slot = ad193x_set_tdm_slot, |
424 | .set_sysclk = ad193x_set_dai_sysclk, | ||
386 | .set_fmt = ad193x_set_dai_fmt, | 425 | .set_fmt = ad193x_set_dai_fmt, |
387 | }; | 426 | }; |
388 | 427 | ||