aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sound/soc/codecs/ssm2602.c67
-rw-r--r--sound/soc/codecs/ssm2602.h6
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
371static int ssm2602_set_dai_fmt(struct snd_soc_dai *codec_dai, 402static 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,
430static int ssm2602_set_bias_level(struct snd_soc_codec *codec, 461static 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 119enum ssm2602_clk {
120 SSM2602_SYSCLK,
121 SSM2602_CLK_CLKOUT,
122 SSM2602_CLK_XTO
123};
120 124
121#endif 125#endif