diff options
author | Axel Castaneda Gonzalez <x0055901@ti.com> | 2011-02-23 21:08:28 -0500 |
---|---|---|
committer | Peter Ujfalusi <peter.ujfalusi@ti.com> | 2011-07-04 12:36:29 -0400 |
commit | 1fbe99529d9490fd29982af07731650f112ffdfa (patch) | |
tree | f65de0c7602c079cc24c34e233c19dd9db1770a8 /sound | |
parent | f7026c99961da48cc4c09cc4f152db5fb30832e7 (diff) |
ASoC: twl6040: Configure ramp step based on platform
Enable ramp down/up step to be configured based on
platform.
Signed-off-by: Axel Castaneda Gonzalez <x0055901@ti.com>
Signed-off-by: Misael Lopez Cruz <misael.lopez@ti.com>
Signed-off-by: Peter Ujfalusi <peter.ujfalusi@ti.com>
Acked-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Diffstat (limited to 'sound')
-rw-r--r-- | sound/soc/codecs/twl6040.c | 91 |
1 files changed, 71 insertions, 20 deletions
diff --git a/sound/soc/codecs/twl6040.c b/sound/soc/codecs/twl6040.c index 39ecf2f4940d..014504180ff8 100644 --- a/sound/soc/codecs/twl6040.c +++ b/sound/soc/codecs/twl6040.c | |||
@@ -83,6 +83,10 @@ struct twl6040_data { | |||
83 | int hs_power_mode_locked; | 83 | int hs_power_mode_locked; |
84 | unsigned int clk_in; | 84 | unsigned int clk_in; |
85 | unsigned int sysclk; | 85 | unsigned int sysclk; |
86 | u16 hs_left_step; | ||
87 | u16 hs_right_step; | ||
88 | u16 hf_left_step; | ||
89 | u16 hf_right_step; | ||
86 | struct snd_pcm_hw_constraint_list *sysclk_constraints; | 90 | struct snd_pcm_hw_constraint_list *sysclk_constraints; |
87 | struct twl6040_jack_data hs_jack; | 91 | struct twl6040_jack_data hs_jack; |
88 | struct snd_soc_codec *codec; | 92 | struct snd_soc_codec *codec; |
@@ -339,7 +343,11 @@ static inline int twl6040_hs_ramp_step(struct snd_soc_codec *codec, | |||
339 | if (headset->ramp == TWL6040_RAMP_UP) { | 343 | if (headset->ramp == TWL6040_RAMP_UP) { |
340 | /* ramp step up */ | 344 | /* ramp step up */ |
341 | if (val < headset->left_vol) { | 345 | if (val < headset->left_vol) { |
342 | val += left_step; | 346 | if (val + left_step > headset->left_vol) |
347 | val = headset->left_vol; | ||
348 | else | ||
349 | val += left_step; | ||
350 | |||
343 | reg &= ~TWL6040_HSL_VOL_MASK; | 351 | reg &= ~TWL6040_HSL_VOL_MASK; |
344 | twl6040_write(codec, TWL6040_REG_HSGAIN, | 352 | twl6040_write(codec, TWL6040_REG_HSGAIN, |
345 | (reg | (~val & TWL6040_HSL_VOL_MASK))); | 353 | (reg | (~val & TWL6040_HSL_VOL_MASK))); |
@@ -349,7 +357,11 @@ static inline int twl6040_hs_ramp_step(struct snd_soc_codec *codec, | |||
349 | } else if (headset->ramp == TWL6040_RAMP_DOWN) { | 357 | } else if (headset->ramp == TWL6040_RAMP_DOWN) { |
350 | /* ramp step down */ | 358 | /* ramp step down */ |
351 | if (val > 0x0) { | 359 | if (val > 0x0) { |
352 | val -= left_step; | 360 | if ((int)val - (int)left_step < 0) |
361 | val = 0; | ||
362 | else | ||
363 | val -= left_step; | ||
364 | |||
353 | reg &= ~TWL6040_HSL_VOL_MASK; | 365 | reg &= ~TWL6040_HSL_VOL_MASK; |
354 | twl6040_write(codec, TWL6040_REG_HSGAIN, reg | | 366 | twl6040_write(codec, TWL6040_REG_HSGAIN, reg | |
355 | (~val & TWL6040_HSL_VOL_MASK)); | 367 | (~val & TWL6040_HSL_VOL_MASK)); |
@@ -366,7 +378,11 @@ static inline int twl6040_hs_ramp_step(struct snd_soc_codec *codec, | |||
366 | if (headset->ramp == TWL6040_RAMP_UP) { | 378 | if (headset->ramp == TWL6040_RAMP_UP) { |
367 | /* ramp step up */ | 379 | /* ramp step up */ |
368 | if (val < headset->right_vol) { | 380 | if (val < headset->right_vol) { |
369 | val += right_step; | 381 | if (val + right_step > headset->right_vol) |
382 | val = headset->right_vol; | ||
383 | else | ||
384 | val += right_step; | ||
385 | |||
370 | reg &= ~TWL6040_HSR_VOL_MASK; | 386 | reg &= ~TWL6040_HSR_VOL_MASK; |
371 | twl6040_write(codec, TWL6040_REG_HSGAIN, | 387 | twl6040_write(codec, TWL6040_REG_HSGAIN, |
372 | (reg | (~val << TWL6040_HSR_VOL_SHIFT))); | 388 | (reg | (~val << TWL6040_HSR_VOL_SHIFT))); |
@@ -376,7 +392,11 @@ static inline int twl6040_hs_ramp_step(struct snd_soc_codec *codec, | |||
376 | } else if (headset->ramp == TWL6040_RAMP_DOWN) { | 392 | } else if (headset->ramp == TWL6040_RAMP_DOWN) { |
377 | /* ramp step down */ | 393 | /* ramp step down */ |
378 | if (val > 0x0) { | 394 | if (val > 0x0) { |
379 | val -= right_step; | 395 | if ((int)val - (int)right_step < 0) |
396 | val = 0; | ||
397 | else | ||
398 | val -= right_step; | ||
399 | |||
380 | reg &= ~TWL6040_HSR_VOL_MASK; | 400 | reg &= ~TWL6040_HSR_VOL_MASK; |
381 | twl6040_write(codec, TWL6040_REG_HSGAIN, | 401 | twl6040_write(codec, TWL6040_REG_HSGAIN, |
382 | reg | (~val << TWL6040_HSR_VOL_SHIFT)); | 402 | reg | (~val << TWL6040_HSR_VOL_SHIFT)); |
@@ -407,7 +427,11 @@ static inline int twl6040_hf_ramp_step(struct snd_soc_codec *codec, | |||
407 | if (handsfree->ramp == TWL6040_RAMP_UP) { | 427 | if (handsfree->ramp == TWL6040_RAMP_UP) { |
408 | /* ramp step up */ | 428 | /* ramp step up */ |
409 | if (val < handsfree->left_vol) { | 429 | if (val < handsfree->left_vol) { |
410 | val += left_step; | 430 | if (val + left_step > handsfree->left_vol) |
431 | val = handsfree->left_vol; | ||
432 | else | ||
433 | val += left_step; | ||
434 | |||
411 | reg &= ~TWL6040_HF_VOL_MASK; | 435 | reg &= ~TWL6040_HF_VOL_MASK; |
412 | twl6040_write(codec, TWL6040_REG_HFLGAIN, | 436 | twl6040_write(codec, TWL6040_REG_HFLGAIN, |
413 | reg | (0x1D - val)); | 437 | reg | (0x1D - val)); |
@@ -417,7 +441,11 @@ static inline int twl6040_hf_ramp_step(struct snd_soc_codec *codec, | |||
417 | } else if (handsfree->ramp == TWL6040_RAMP_DOWN) { | 441 | } else if (handsfree->ramp == TWL6040_RAMP_DOWN) { |
418 | /* ramp step down */ | 442 | /* ramp step down */ |
419 | if (val > 0) { | 443 | if (val > 0) { |
420 | val -= left_step; | 444 | if ((int)val - (int)left_step < 0) |
445 | val = 0; | ||
446 | else | ||
447 | val -= left_step; | ||
448 | |||
421 | reg &= ~TWL6040_HF_VOL_MASK; | 449 | reg &= ~TWL6040_HF_VOL_MASK; |
422 | twl6040_write(codec, TWL6040_REG_HFLGAIN, | 450 | twl6040_write(codec, TWL6040_REG_HFLGAIN, |
423 | reg | (0x1D - val)); | 451 | reg | (0x1D - val)); |
@@ -434,7 +462,11 @@ static inline int twl6040_hf_ramp_step(struct snd_soc_codec *codec, | |||
434 | if (handsfree->ramp == TWL6040_RAMP_UP) { | 462 | if (handsfree->ramp == TWL6040_RAMP_UP) { |
435 | /* ramp step up */ | 463 | /* ramp step up */ |
436 | if (val < handsfree->right_vol) { | 464 | if (val < handsfree->right_vol) { |
437 | val += right_step; | 465 | if (val + right_step > handsfree->right_vol) |
466 | val = handsfree->right_vol; | ||
467 | else | ||
468 | val += right_step; | ||
469 | |||
438 | reg &= ~TWL6040_HF_VOL_MASK; | 470 | reg &= ~TWL6040_HF_VOL_MASK; |
439 | twl6040_write(codec, TWL6040_REG_HFRGAIN, | 471 | twl6040_write(codec, TWL6040_REG_HFRGAIN, |
440 | reg | (0x1D - val)); | 472 | reg | (0x1D - val)); |
@@ -444,7 +476,11 @@ static inline int twl6040_hf_ramp_step(struct snd_soc_codec *codec, | |||
444 | } else if (handsfree->ramp == TWL6040_RAMP_DOWN) { | 476 | } else if (handsfree->ramp == TWL6040_RAMP_DOWN) { |
445 | /* ramp step down */ | 477 | /* ramp step down */ |
446 | if (val > 0) { | 478 | if (val > 0) { |
447 | val -= right_step; | 479 | if ((int)val - (int)right_step < 0) |
480 | val = 0; | ||
481 | else | ||
482 | val -= right_step; | ||
483 | |||
448 | reg &= ~TWL6040_HF_VOL_MASK; | 484 | reg &= ~TWL6040_HF_VOL_MASK; |
449 | twl6040_write(codec, TWL6040_REG_HFRGAIN, | 485 | twl6040_write(codec, TWL6040_REG_HFRGAIN, |
450 | reg | (0x1D - val)); | 486 | reg | (0x1D - val)); |
@@ -473,11 +509,9 @@ static void twl6040_pga_hs_work(struct work_struct *work) | |||
473 | 509 | ||
474 | /* HS PGA volumes have 4 bits of resolution to ramp */ | 510 | /* HS PGA volumes have 4 bits of resolution to ramp */ |
475 | for (i = 0; i <= 16; i++) { | 511 | for (i = 0; i <= 16; i++) { |
476 | headset_complete = 1; | 512 | headset_complete = twl6040_hs_ramp_step(codec, |
477 | if (headset->ramp != TWL6040_RAMP_NONE) | 513 | headset->left_step, |
478 | headset_complete = twl6040_hs_ramp_step(codec, | 514 | headset->right_step); |
479 | headset->left_step, | ||
480 | headset->right_step); | ||
481 | 515 | ||
482 | /* ramp finished ? */ | 516 | /* ramp finished ? */ |
483 | if (headset_complete) | 517 | if (headset_complete) |
@@ -518,11 +552,9 @@ static void twl6040_pga_hf_work(struct work_struct *work) | |||
518 | 552 | ||
519 | /* HF PGA volumes have 5 bits of resolution to ramp */ | 553 | /* HF PGA volumes have 5 bits of resolution to ramp */ |
520 | for (i = 0; i <= 32; i++) { | 554 | for (i = 0; i <= 32; i++) { |
521 | handsfree_complete = 1; | 555 | handsfree_complete = twl6040_hf_ramp_step(codec, |
522 | if (handsfree->ramp != TWL6040_RAMP_NONE) | 556 | handsfree->left_step, |
523 | handsfree_complete = twl6040_hf_ramp_step(codec, | 557 | handsfree->right_step); |
524 | handsfree->left_step, | ||
525 | handsfree->right_step); | ||
526 | 558 | ||
527 | /* ramp finished ? */ | 559 | /* ramp finished ? */ |
528 | if (handsfree_complete) | 560 | if (handsfree_complete) |
@@ -563,12 +595,16 @@ static int pga_event(struct snd_soc_dapm_widget *w, | |||
563 | out = &priv->headset; | 595 | out = &priv->headset; |
564 | work = &priv->hs_delayed_work; | 596 | work = &priv->hs_delayed_work; |
565 | queue = priv->hs_workqueue; | 597 | queue = priv->hs_workqueue; |
598 | out->left_step = priv->hs_left_step; | ||
599 | out->right_step = priv->hs_right_step; | ||
566 | out->step_delay = 5; /* 5 ms between volume ramp steps */ | 600 | out->step_delay = 5; /* 5 ms between volume ramp steps */ |
567 | break; | 601 | break; |
568 | case 4: | 602 | case 4: |
569 | out = &priv->handsfree; | 603 | out = &priv->handsfree; |
570 | work = &priv->hf_delayed_work; | 604 | work = &priv->hf_delayed_work; |
571 | queue = priv->hf_workqueue; | 605 | queue = priv->hf_workqueue; |
606 | out->left_step = priv->hf_left_step; | ||
607 | out->right_step = priv->hf_right_step; | ||
572 | out->step_delay = 5; /* 5 ms between volume ramp steps */ | 608 | out->step_delay = 5; /* 5 ms between volume ramp steps */ |
573 | if (SND_SOC_DAPM_EVENT_ON(event)) | 609 | if (SND_SOC_DAPM_EVENT_ON(event)) |
574 | priv->non_lp++; | 610 | priv->non_lp++; |
@@ -601,8 +637,6 @@ static int pga_event(struct snd_soc_dapm_widget *w, | |||
601 | 637 | ||
602 | if (!delayed_work_pending(work)) { | 638 | if (!delayed_work_pending(work)) { |
603 | /* use volume ramp for power-down */ | 639 | /* use volume ramp for power-down */ |
604 | out->left_step = 1; | ||
605 | out->right_step = 1; | ||
606 | out->ramp = TWL6040_RAMP_DOWN; | 640 | out->ramp = TWL6040_RAMP_DOWN; |
607 | INIT_COMPLETION(out->ramp_done); | 641 | INIT_COMPLETION(out->ramp_done); |
608 | 642 | ||
@@ -1492,6 +1526,7 @@ static int twl6040_resume(struct snd_soc_codec *codec) | |||
1492 | static int twl6040_probe(struct snd_soc_codec *codec) | 1526 | static int twl6040_probe(struct snd_soc_codec *codec) |
1493 | { | 1527 | { |
1494 | struct twl6040_data *priv; | 1528 | struct twl6040_data *priv; |
1529 | struct twl4030_codec_data *pdata = dev_get_platdata(codec->dev); | ||
1495 | int ret = 0; | 1530 | int ret = 0; |
1496 | 1531 | ||
1497 | priv = kzalloc(sizeof(struct twl6040_data), GFP_KERNEL); | 1532 | priv = kzalloc(sizeof(struct twl6040_data), GFP_KERNEL); |
@@ -1502,6 +1537,22 @@ static int twl6040_probe(struct snd_soc_codec *codec) | |||
1502 | priv->codec = codec; | 1537 | priv->codec = codec; |
1503 | codec->control_data = dev_get_drvdata(codec->dev->parent); | 1538 | codec->control_data = dev_get_drvdata(codec->dev->parent); |
1504 | 1539 | ||
1540 | if (pdata && pdata->hs_left_step && pdata->hs_right_step) { | ||
1541 | priv->hs_left_step = pdata->hs_left_step; | ||
1542 | priv->hs_right_step = pdata->hs_right_step; | ||
1543 | } else { | ||
1544 | priv->hs_left_step = 1; | ||
1545 | priv->hs_right_step = 1; | ||
1546 | } | ||
1547 | |||
1548 | if (pdata && pdata->hf_left_step && pdata->hf_right_step) { | ||
1549 | priv->hf_left_step = pdata->hf_left_step; | ||
1550 | priv->hf_right_step = pdata->hf_right_step; | ||
1551 | } else { | ||
1552 | priv->hf_left_step = 1; | ||
1553 | priv->hf_right_step = 1; | ||
1554 | } | ||
1555 | |||
1505 | priv->sysclk_constraints = &hp_constraints; | 1556 | priv->sysclk_constraints = &hp_constraints; |
1506 | priv->workqueue = create_singlethread_workqueue("twl6040-codec"); | 1557 | priv->workqueue = create_singlethread_workqueue("twl6040-codec"); |
1507 | if (!priv->workqueue) { | 1558 | if (!priv->workqueue) { |