diff options
-rw-r--r-- | sound/soc/codecs/ssm2602.c | 67 | ||||
-rw-r--r-- | sound/soc/codecs/ssm2602.h | 6 |
2 files changed, 56 insertions, 17 deletions
diff --git a/sound/soc/codecs/ssm2602.c b/sound/soc/codecs/ssm2602.c index c9e0fdbf0565..e149ec61e6be 100644 --- a/sound/soc/codecs/ssm2602.c +++ b/sound/soc/codecs/ssm2602.c | |||
@@ -59,6 +59,7 @@ struct ssm2602_priv { | |||
59 | struct snd_pcm_substream *slave_substream; | 59 | struct snd_pcm_substream *slave_substream; |
60 | 60 | ||
61 | enum ssm2602_type type; | 61 | enum ssm2602_type type; |
62 | unsigned int clk_out_pwr; | ||
62 | }; | 63 | }; |
63 | 64 | ||
64 | /* | 65 | /* |
@@ -356,16 +357,46 @@ static int ssm2602_set_dai_sysclk(struct snd_soc_dai *codec_dai, | |||
356 | { | 357 | { |
357 | struct snd_soc_codec *codec = codec_dai->codec; | 358 | struct snd_soc_codec *codec = codec_dai->codec; |
358 | struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec); | 359 | struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec); |
359 | switch (freq) { | 360 | |
360 | case 11289600: | 361 | if (dir == SND_SOC_CLOCK_IN) { |
361 | case 12000000: | 362 | if (clk_id != SSM2602_SYSCLK) |
362 | case 12288000: | 363 | return -EINVAL; |
363 | case 16934400: | 364 | |
364 | case 18432000: | 365 | switch (freq) { |
365 | ssm2602->sysclk = freq; | 366 | case 11289600: |
366 | return 0; | 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 | static int ssm2602_set_dai_fmt(struct snd_soc_dai *codec_dai, | 402 | static int ssm2602_set_dai_fmt(struct snd_soc_dai *codec_dai, |
@@ -430,23 +461,27 @@ static int ssm2602_set_dai_fmt(struct snd_soc_dai *codec_dai, | |||
430 | static int ssm2602_set_bias_level(struct snd_soc_codec *codec, | 461 | static int ssm2602_set_bias_level(struct snd_soc_codec *codec, |
431 | enum snd_soc_bias_level level) | 462 | enum snd_soc_bias_level level) |
432 | { | 463 | { |
433 | u16 reg = snd_soc_read(codec, SSM2602_PWR); | 464 | struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec); |
434 | reg &= ~(PWR_POWER_OFF | PWR_OSC_PDN); | ||
435 | 465 | ||
436 | switch (level) { | 466 | switch (level) { |
437 | case SND_SOC_BIAS_ON: | 467 | case SND_SOC_BIAS_ON: |
438 | /* vref/mid, osc on, dac unmute */ | 468 | /* vref/mid on, osc and clkout on if enabled */ |
439 | snd_soc_write(codec, SSM2602_PWR, reg); | 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 | break; | 472 | break; |
441 | case SND_SOC_BIAS_PREPARE: | 473 | case SND_SOC_BIAS_PREPARE: |
442 | break; | 474 | break; |
443 | case SND_SOC_BIAS_STANDBY: | 475 | case SND_SOC_BIAS_STANDBY: |
444 | /* everything off except vref/vmid, */ | 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 | break; | 480 | break; |
447 | case SND_SOC_BIAS_OFF: | 481 | case SND_SOC_BIAS_OFF: |
448 | /* everything off, dac mute, inactive */ | 482 | /* everything off */ |
449 | snd_soc_write(codec, SSM2602_PWR, 0xffff); | 483 | snd_soc_update_bits(codec, SSM2602_PWR, |
484 | PWR_POWER_OFF, PWR_POWER_OFF); | ||
450 | break; | 485 | break; |
451 | 486 | ||
452 | } | 487 | } |
diff --git a/sound/soc/codecs/ssm2602.h b/sound/soc/codecs/ssm2602.h index b98c69168036..fbd07d7b73ca 100644 --- a/sound/soc/codecs/ssm2602.h +++ b/sound/soc/codecs/ssm2602.h | |||
@@ -116,6 +116,10 @@ | |||
116 | 116 | ||
117 | #define SSM2602_CACHEREGNUM 10 | 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 | #endif | 125 | #endif |