Commit 02890535269338a6d2034ad3ce8b22beb24b449a

Authored by Lars-Peter Clausen
Committed by Mark Brown
1 parent a9d1974ea1

ASoC: ssm2602: Support setting the oscillator and the clock output state

Currently the oscillator is always enabled and the clock output is always
disabled. This patch adds support for controlling the oscillator and clock
output state through snd_soc_dai_set_sysclk. Which makes it possible to
disable or enable them dynamically according to the requirements of the board
on which the CODEC is used.

This patch also slightly modifies the behavior as to when the oscillator is
going to be disabled in low-power states. Previously it would only be disabled
in BIAS_OFF, now it is also going to be disabled in BIAS_STANDBY, since no
components which depend on it should be active in this state.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>

Showing 2 changed files with 56 additions and 17 deletions Side-by-side Diff

sound/soc/codecs/ssm2602.c
... ... @@ -59,6 +59,7 @@
59 59 struct snd_pcm_substream *slave_substream;
60 60  
61 61 enum ssm2602_type type;
  62 + unsigned int clk_out_pwr;
62 63 };
63 64  
64 65 /*
65 66  
... ... @@ -356,16 +357,46 @@
356 357 {
357 358 struct snd_soc_codec *codec = codec_dai->codec;
358 359 struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec);
359   - switch (freq) {
360   - case 11289600:
361   - case 12000000:
362   - case 12288000:
363   - case 16934400:
364   - case 18432000:
365   - ssm2602->sysclk = freq;
366   - return 0;
  360 +
  361 + if (dir == SND_SOC_CLOCK_IN) {
  362 + if (clk_id != SSM2602_SYSCLK)
  363 + return -EINVAL;
  364 +
  365 + switch (freq) {
  366 + case 11289600:
  367 + case 12000000:
  368 + case 12288000:
  369 + case 16934400:
  370 + case 18432000:
  371 + ssm2602->sysclk = freq;
  372 + break;
  373 + default:
  374 + return -EINVAL;
  375 + }
  376 + } else {
  377 + unsigned int mask;
  378 +
  379 + switch (clk_id) {
  380 + case SSM2602_CLK_CLKOUT:
  381 + mask = PWR_CLK_OUT_PDN;
  382 + break;
  383 + case SSM2602_CLK_XTO:
  384 + mask = PWR_OSC_PDN;
  385 + break;
  386 + default:
  387 + return -EINVAL;
  388 + }
  389 +
  390 + if (freq == 0)
  391 + ssm2602->clk_out_pwr |= mask;
  392 + else
  393 + ssm2602->clk_out_pwr &= ~mask;
  394 +
  395 + snd_soc_update_bits(codec, SSM2602_PWR,
  396 + PWR_CLK_OUT_PDN | PWR_OSC_PDN, ssm2602->clk_out_pwr);
367 397 }
368   - return -EINVAL;
  398 +
  399 + return 0;
369 400 }
370 401  
371 402 static int ssm2602_set_dai_fmt(struct snd_soc_dai *codec_dai,
372 403  
373 404  
374 405  
... ... @@ -430,23 +461,27 @@
430 461 static int ssm2602_set_bias_level(struct snd_soc_codec *codec,
431 462 enum snd_soc_bias_level level)
432 463 {
433   - u16 reg = snd_soc_read(codec, SSM2602_PWR);
434   - reg &= ~(PWR_POWER_OFF | PWR_OSC_PDN);
  464 + struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec);
435 465  
436 466 switch (level) {
437 467 case SND_SOC_BIAS_ON:
438   - /* vref/mid, osc on, dac unmute */
439   - snd_soc_write(codec, SSM2602_PWR, reg);
  468 + /* vref/mid on, osc and clkout on if enabled */
  469 + snd_soc_update_bits(codec, SSM2602_PWR,
  470 + PWR_POWER_OFF | PWR_CLK_OUT_PDN | PWR_OSC_PDN,
  471 + ssm2602->clk_out_pwr);
440 472 break;
441 473 case SND_SOC_BIAS_PREPARE:
442 474 break;
443 475 case SND_SOC_BIAS_STANDBY:
444 476 /* everything off except vref/vmid, */
445   - snd_soc_write(codec, SSM2602_PWR, reg | PWR_CLK_OUT_PDN);
  477 + snd_soc_update_bits(codec, SSM2602_PWR,
  478 + PWR_POWER_OFF | PWR_CLK_OUT_PDN | PWR_OSC_PDN,
  479 + PWR_CLK_OUT_PDN | PWR_OSC_PDN);
446 480 break;
447 481 case SND_SOC_BIAS_OFF:
448   - /* everything off, dac mute, inactive */
449   - snd_soc_write(codec, SSM2602_PWR, 0xffff);
  482 + /* everything off */
  483 + snd_soc_update_bits(codec, SSM2602_PWR,
  484 + PWR_POWER_OFF, PWR_POWER_OFF);
450 485 break;
451 486  
452 487 }
sound/soc/codecs/ssm2602.h
... ... @@ -116,7 +116,11 @@
116 116  
117 117 #define SSM2602_CACHEREGNUM 10
118 118  
119   -#define SSM2602_SYSCLK 0
  119 +enum ssm2602_clk {
  120 + SSM2602_SYSCLK,
  121 + SSM2602_CLK_CLKOUT,
  122 + SSM2602_CLK_XTO
  123 +};
120 124  
121 125 #endif