aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/codecs/ssm2602.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2011-10-28 17:25:01 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2011-10-28 17:25:01 -0400
commit68d99b2c8efcb6ed3807a55569300c53b5f88be5 (patch)
treef189c8f2132d3668a2f0e503f5c3f8695b26a1c8 /sound/soc/codecs/ssm2602.c
parent0e59e7e7feb5a12938fbf9135147eeda3238c6c4 (diff)
parent8128c9f21509f9a8b6da94ac432d845dda458406 (diff)
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound: (549 commits) ALSA: hda - Fix ADC input-amp handling for Cx20549 codec ALSA: hda - Keep EAPD turned on for old Conexant chips ALSA: hda/realtek - Fix missing volume controls with ALC260 ASoC: wm8940: Properly set codec->dapm.bias_level ALSA: hda - Fix pin-config for ASUS W90V ALSA: hda - Fix surround/CLFE headphone and speaker pins order ALSA: hda - Fix typo ALSA: Update the sound git tree URL ALSA: HDA: Add new revision for ALC662 ASoC: max98095: Convert codec->hw_write to snd_soc_write ASoC: keep pointer to resource so it can be freed ASoC: sgtl5000: Fix wrong mask in some snd_soc_update_bits calls ASoC: wm8996: Fix wrong mask for setting WM8996_AIF_CLOCKING_2 ASoC: da7210: Add support for line out and DAC ASoC: da7210: Add support for DAPM ALSA: hda/realtek - Fix DAC assignments of multiple speakers ASoC: Use SGTL5000_LINREG_VDDD_MASK instead of hardcoded mask value ASoC: Set sgtl5000->ldo in ldo_regulator_register ASoC: wm8996: Use SND_SOC_DAPM_AIF_OUT for AIF2 Capture ASoC: wm8994: Use SND_SOC_DAPM_AIF_OUT for AIF3 Capture ...
Diffstat (limited to 'sound/soc/codecs/ssm2602.c')
-rw-r--r--sound/soc/codecs/ssm2602.c107
1 files changed, 74 insertions, 33 deletions
diff --git a/sound/soc/codecs/ssm2602.c b/sound/soc/codecs/ssm2602.c
index 9801cd7cfcb5..3cb3271c5fe2 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/*
@@ -294,7 +295,6 @@ static int ssm2602_startup(struct snd_pcm_substream *substream,
294 struct snd_soc_pcm_runtime *rtd = substream->private_data; 295 struct snd_soc_pcm_runtime *rtd = substream->private_data;
295 struct snd_soc_codec *codec = rtd->codec; 296 struct snd_soc_codec *codec = rtd->codec;
296 struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec); 297 struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec);
297 struct i2c_client *i2c = codec->control_data;
298 struct snd_pcm_runtime *master_runtime; 298 struct snd_pcm_runtime *master_runtime;
299 299
300 /* The DAI has shared clocks so if we already have a playback or 300 /* The DAI has shared clocks so if we already have a playback or
@@ -303,7 +303,7 @@ static int ssm2602_startup(struct snd_pcm_substream *substream,
303 */ 303 */
304 if (ssm2602->master_substream) { 304 if (ssm2602->master_substream) {
305 master_runtime = ssm2602->master_substream->runtime; 305 master_runtime = ssm2602->master_substream->runtime;
306 dev_dbg(&i2c->dev, "Constraining to %d bits at %dHz\n", 306 dev_dbg(codec->dev, "Constraining to %d bits at %dHz\n",
307 master_runtime->sample_bits, 307 master_runtime->sample_bits,
308 master_runtime->rate); 308 master_runtime->rate);
309 309
@@ -343,12 +343,14 @@ static void ssm2602_shutdown(struct snd_pcm_substream *substream,
343static int ssm2602_mute(struct snd_soc_dai *dai, int mute) 343static int ssm2602_mute(struct snd_soc_dai *dai, int mute)
344{ 344{
345 struct snd_soc_codec *codec = dai->codec; 345 struct snd_soc_codec *codec = dai->codec;
346 u16 mute_reg = snd_soc_read(codec, SSM2602_APDIGI) & ~APDIGI_ENABLE_DAC_MUTE; 346
347 if (mute) 347 if (mute)
348 snd_soc_write(codec, SSM2602_APDIGI, 348 snd_soc_update_bits(codec, SSM2602_APDIGI,
349 mute_reg | APDIGI_ENABLE_DAC_MUTE); 349 APDIGI_ENABLE_DAC_MUTE,
350 APDIGI_ENABLE_DAC_MUTE);
350 else 351 else
351 snd_soc_write(codec, SSM2602_APDIGI, mute_reg); 352 snd_soc_update_bits(codec, SSM2602_APDIGI,
353 APDIGI_ENABLE_DAC_MUTE, 0);
352 return 0; 354 return 0;
353} 355}
354 356
@@ -357,16 +359,46 @@ static int ssm2602_set_dai_sysclk(struct snd_soc_dai *codec_dai,
357{ 359{
358 struct snd_soc_codec *codec = codec_dai->codec; 360 struct snd_soc_codec *codec = codec_dai->codec;
359 struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec); 361 struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec);
360 switch (freq) { 362
361 case 11289600: 363 if (dir == SND_SOC_CLOCK_IN) {
362 case 12000000: 364 if (clk_id != SSM2602_SYSCLK)
363 case 12288000: 365 return -EINVAL;
364 case 16934400: 366
365 case 18432000: 367 switch (freq) {
366 ssm2602->sysclk = freq; 368 case 11289600:
367 return 0; 369 case 12000000:
370 case 12288000:
371 case 16934400:
372 case 18432000:
373 ssm2602->sysclk = freq;
374 break;
375 default:
376 return -EINVAL;
377 }
378 } else {
379 unsigned int mask;
380
381 switch (clk_id) {
382 case SSM2602_CLK_CLKOUT:
383 mask = PWR_CLK_OUT_PDN;
384 break;
385 case SSM2602_CLK_XTO:
386 mask = PWR_OSC_PDN;
387 break;
388 default:
389 return -EINVAL;
390 }
391
392 if (freq == 0)
393 ssm2602->clk_out_pwr |= mask;
394 else
395 ssm2602->clk_out_pwr &= ~mask;
396
397 snd_soc_update_bits(codec, SSM2602_PWR,
398 PWR_CLK_OUT_PDN | PWR_OSC_PDN, ssm2602->clk_out_pwr);
368 } 399 }
369 return -EINVAL; 400
401 return 0;
370} 402}
371 403
372static int ssm2602_set_dai_fmt(struct snd_soc_dai *codec_dai, 404static int ssm2602_set_dai_fmt(struct snd_soc_dai *codec_dai,
@@ -431,23 +463,27 @@ static int ssm2602_set_dai_fmt(struct snd_soc_dai *codec_dai,
431static int ssm2602_set_bias_level(struct snd_soc_codec *codec, 463static int ssm2602_set_bias_level(struct snd_soc_codec *codec,
432 enum snd_soc_bias_level level) 464 enum snd_soc_bias_level level)
433{ 465{
434 u16 reg = snd_soc_read(codec, SSM2602_PWR); 466 struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec);
435 reg &= ~(PWR_POWER_OFF | PWR_OSC_PDN);
436 467
437 switch (level) { 468 switch (level) {
438 case SND_SOC_BIAS_ON: 469 case SND_SOC_BIAS_ON:
439 /* vref/mid, osc on, dac unmute */ 470 /* vref/mid on, osc and clkout on if enabled */
440 snd_soc_write(codec, SSM2602_PWR, reg); 471 snd_soc_update_bits(codec, SSM2602_PWR,
472 PWR_POWER_OFF | PWR_CLK_OUT_PDN | PWR_OSC_PDN,
473 ssm2602->clk_out_pwr);
441 break; 474 break;
442 case SND_SOC_BIAS_PREPARE: 475 case SND_SOC_BIAS_PREPARE:
443 break; 476 break;
444 case SND_SOC_BIAS_STANDBY: 477 case SND_SOC_BIAS_STANDBY:
445 /* everything off except vref/vmid, */ 478 /* everything off except vref/vmid, */
446 snd_soc_write(codec, SSM2602_PWR, reg | PWR_CLK_OUT_PDN); 479 snd_soc_update_bits(codec, SSM2602_PWR,
480 PWR_POWER_OFF | PWR_CLK_OUT_PDN | PWR_OSC_PDN,
481 PWR_CLK_OUT_PDN | PWR_OSC_PDN);
447 break; 482 break;
448 case SND_SOC_BIAS_OFF: 483 case SND_SOC_BIAS_OFF:
449 /* everything off, dac mute, inactive */ 484 /* everything off */
450 snd_soc_write(codec, SSM2602_PWR, 0xffff); 485 snd_soc_update_bits(codec, SSM2602_PWR,
486 PWR_POWER_OFF, PWR_POWER_OFF);
451 break; 487 break;
452 488
453 } 489 }
@@ -506,12 +542,12 @@ static int ssm2602_resume(struct snd_soc_codec *codec)
506static int ssm2602_probe(struct snd_soc_codec *codec) 542static int ssm2602_probe(struct snd_soc_codec *codec)
507{ 543{
508 struct snd_soc_dapm_context *dapm = &codec->dapm; 544 struct snd_soc_dapm_context *dapm = &codec->dapm;
509 int ret, reg; 545 int ret;
510 546
511 reg = snd_soc_read(codec, SSM2602_LOUT1V); 547 snd_soc_update_bits(codec, SSM2602_LOUT1V,
512 snd_soc_write(codec, SSM2602_LOUT1V, reg | LOUT1V_LRHP_BOTH); 548 LOUT1V_LRHP_BOTH, LOUT1V_LRHP_BOTH);
513 reg = snd_soc_read(codec, SSM2602_ROUT1V); 549 snd_soc_update_bits(codec, SSM2602_ROUT1V,
514 snd_soc_write(codec, SSM2602_ROUT1V, reg | ROUT1V_RLHP_BOTH); 550 ROUT1V_RLHP_BOTH, ROUT1V_RLHP_BOTH);
515 551
516 ret = snd_soc_add_controls(codec, ssm2602_snd_controls, 552 ret = snd_soc_add_controls(codec, ssm2602_snd_controls,
517 ARRAY_SIZE(ssm2602_snd_controls)); 553 ARRAY_SIZE(ssm2602_snd_controls));
@@ -544,7 +580,7 @@ static int ssm2604_probe(struct snd_soc_codec *codec)
544static int ssm260x_probe(struct snd_soc_codec *codec) 580static int ssm260x_probe(struct snd_soc_codec *codec)
545{ 581{
546 struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec); 582 struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec);
547 int ret, reg; 583 int ret;
548 584
549 pr_info("ssm2602 Audio Codec %s", SSM2602_VERSION); 585 pr_info("ssm2602 Audio Codec %s", SSM2602_VERSION);
550 586
@@ -561,10 +597,10 @@ static int ssm260x_probe(struct snd_soc_codec *codec)
561 } 597 }
562 598
563 /* set the update bits */ 599 /* set the update bits */
564 reg = snd_soc_read(codec, SSM2602_LINVOL); 600 snd_soc_update_bits(codec, SSM2602_LINVOL,
565 snd_soc_write(codec, SSM2602_LINVOL, reg | LINVOL_LRIN_BOTH); 601 LINVOL_LRIN_BOTH, LINVOL_LRIN_BOTH);
566 reg = snd_soc_read(codec, SSM2602_RINVOL); 602 snd_soc_update_bits(codec, SSM2602_RINVOL,
567 snd_soc_write(codec, SSM2602_RINVOL, reg | RINVOL_RLIN_BOTH); 603 RINVOL_RLIN_BOTH, RINVOL_RLIN_BOTH);
568 /*select Line in as default input*/ 604 /*select Line in as default input*/
569 snd_soc_write(codec, SSM2602_APANA, APANA_SELECT_DAC | 605 snd_soc_write(codec, SSM2602_APANA, APANA_SELECT_DAC |
570 APANA_ENABLE_MIC_BOOST); 606 APANA_ENABLE_MIC_BOOST);
@@ -578,7 +614,12 @@ static int ssm260x_probe(struct snd_soc_codec *codec)
578 break; 614 break;
579 } 615 }
580 616
581 return ret; 617 if (ret)
618 return ret;
619
620 ssm2602_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
621
622 return 0;
582} 623}
583 624
584/* remove everything here */ 625/* remove everything here */