aboutsummaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
authorMark Brown <broonie@linaro.org>2013-11-08 05:43:37 -0500
committerMark Brown <broonie@linaro.org>2013-11-08 05:43:37 -0500
commitbe529a5b7f3490c9c57295cc8c9891a3ab94b250 (patch)
treee63e7fe82322fc2a0d822ede210f1672b57976e9 /sound
parent6c61bbf0e844a035736272bd863d724d5f112ac5 (diff)
parent285d00c11b0a8d0ef63c176f88caab5071c9e80d (diff)
Merge remote-tracking branch 'asoc/topic/tas5086' into asoc-next
Diffstat (limited to 'sound')
-rw-r--r--sound/soc/codecs/tas5086.c171
1 files changed, 109 insertions, 62 deletions
diff --git a/sound/soc/codecs/tas5086.c b/sound/soc/codecs/tas5086.c
index 6d31d88f7204..fe4d29d88564 100644
--- a/sound/soc/codecs/tas5086.c
+++ b/sound/soc/codecs/tas5086.c
@@ -37,6 +37,7 @@
37#include <linux/i2c.h> 37#include <linux/i2c.h>
38#include <linux/regmap.h> 38#include <linux/regmap.h>
39#include <linux/spi/spi.h> 39#include <linux/spi/spi.h>
40#include <linux/of.h>
40#include <linux/of_device.h> 41#include <linux/of_device.h>
41#include <linux/of_gpio.h> 42#include <linux/of_gpio.h>
42#include <sound/pcm.h> 43#include <sound/pcm.h>
@@ -244,6 +245,8 @@ struct tas5086_private {
244 unsigned int mclk, sclk; 245 unsigned int mclk, sclk;
245 unsigned int format; 246 unsigned int format;
246 bool deemph; 247 bool deemph;
248 unsigned int charge_period;
249 unsigned int pwm_start_mid_z;
247 /* Current sample rate for de-emphasis control */ 250 /* Current sample rate for de-emphasis control */
248 int rate; 251 int rate;
249 /* GPIO driving Reset pin, if any */ 252 /* GPIO driving Reset pin, if any */
@@ -456,6 +459,75 @@ static int tas5086_mute_stream(struct snd_soc_dai *dai, int mute, int stream)
456 return regmap_write(priv->regmap, TAS5086_SOFT_MUTE, val); 459 return regmap_write(priv->regmap, TAS5086_SOFT_MUTE, val);
457} 460}
458 461
462static void tas5086_reset(struct tas5086_private *priv)
463{
464 if (gpio_is_valid(priv->gpio_nreset)) {
465 /* Reset codec - minimum assertion time is 400ns */
466 gpio_direction_output(priv->gpio_nreset, 0);
467 udelay(1);
468 gpio_set_value(priv->gpio_nreset, 1);
469
470 /* Codec needs ~15ms to wake up */
471 msleep(15);
472 }
473}
474
475/* charge period values in microseconds */
476static const int tas5086_charge_period[] = {
477 13000, 16900, 23400, 31200, 41600, 54600, 72800, 96200,
478 130000, 156000, 234000, 312000, 416000, 546000, 728000, 962000,
479 1300000, 169000, 2340000, 3120000, 4160000, 5460000, 7280000, 9620000,
480};
481
482static int tas5086_init(struct device *dev, struct tas5086_private *priv)
483{
484 int ret, i;
485
486 /*
487 * If any of the channels is configured to start in Mid-Z mode,
488 * configure 'part 1' of the PWM starts to use Mid-Z, and tell
489 * all configured mid-z channels to start start under 'part 1'.
490 */
491 if (priv->pwm_start_mid_z)
492 regmap_write(priv->regmap, TAS5086_PWM_START,
493 TAS5086_PWM_START_MIDZ_FOR_START_1 |
494 priv->pwm_start_mid_z);
495
496 /* lookup and set split-capacitor charge period */
497 if (priv->charge_period == 0) {
498 regmap_write(priv->regmap, TAS5086_SPLIT_CAP_CHARGE, 0);
499 } else {
500 i = index_in_array(tas5086_charge_period,
501 ARRAY_SIZE(tas5086_charge_period),
502 priv->charge_period);
503 if (i >= 0)
504 regmap_write(priv->regmap, TAS5086_SPLIT_CAP_CHARGE,
505 i + 0x08);
506 else
507 dev_warn(dev,
508 "Invalid split-cap charge period of %d ns.\n",
509 priv->charge_period);
510 }
511
512 /* enable factory trim */
513 ret = regmap_write(priv->regmap, TAS5086_OSC_TRIM, 0x00);
514 if (ret < 0)
515 return ret;
516
517 /* start all channels */
518 ret = regmap_write(priv->regmap, TAS5086_SYS_CONTROL_2, 0x20);
519 if (ret < 0)
520 return ret;
521
522 /* mute all channels for now */
523 ret = regmap_write(priv->regmap, TAS5086_SOFT_MUTE,
524 TAS5086_SOFT_MUTE_ALL);
525 if (ret < 0)
526 return ret;
527
528 return 0;
529}
530
459/* TAS5086 controls */ 531/* TAS5086 controls */
460static const DECLARE_TLV_DB_SCALE(tas5086_dac_tlv, -10350, 50, 1); 532static const DECLARE_TLV_DB_SCALE(tas5086_dac_tlv, -10350, 50, 1);
461 533
@@ -691,14 +763,39 @@ static struct snd_soc_dai_driver tas5086_dai = {
691}; 763};
692 764
693#ifdef CONFIG_PM 765#ifdef CONFIG_PM
766static int tas5086_soc_suspend(struct snd_soc_codec *codec)
767{
768 struct tas5086_private *priv = snd_soc_codec_get_drvdata(codec);
769 int ret;
770
771 /* Shut down all channels */
772 ret = regmap_write(priv->regmap, TAS5086_SYS_CONTROL_2, 0x60);
773 if (ret < 0)
774 return ret;
775
776 return 0;
777}
778
694static int tas5086_soc_resume(struct snd_soc_codec *codec) 779static int tas5086_soc_resume(struct snd_soc_codec *codec)
695{ 780{
696 struct tas5086_private *priv = snd_soc_codec_get_drvdata(codec); 781 struct tas5086_private *priv = snd_soc_codec_get_drvdata(codec);
782 int ret;
783
784 tas5086_reset(priv);
785 regcache_mark_dirty(priv->regmap);
786
787 ret = tas5086_init(codec->dev, priv);
788 if (ret < 0)
789 return ret;
790
791 ret = regcache_sync(priv->regmap);
792 if (ret < 0)
793 return ret;
697 794
698 /* Restore codec state */ 795 return 0;
699 return regcache_sync(priv->regmap);
700} 796}
701#else 797#else
798#define tas5086_soc_suspend NULL
702#define tas5086_soc_resume NULL 799#define tas5086_soc_resume NULL
703#endif /* CONFIG_PM */ 800#endif /* CONFIG_PM */
704 801
@@ -710,23 +807,19 @@ static const struct of_device_id tas5086_dt_ids[] = {
710MODULE_DEVICE_TABLE(of, tas5086_dt_ids); 807MODULE_DEVICE_TABLE(of, tas5086_dt_ids);
711#endif 808#endif
712 809
713/* charge period values in microseconds */
714static const int tas5086_charge_period[] = {
715 13000, 16900, 23400, 31200, 41600, 54600, 72800, 96200,
716 130000, 156000, 234000, 312000, 416000, 546000, 728000, 962000,
717 1300000, 169000, 2340000, 3120000, 4160000, 5460000, 7280000, 9620000,
718};
719
720static int tas5086_probe(struct snd_soc_codec *codec) 810static int tas5086_probe(struct snd_soc_codec *codec)
721{ 811{
722 struct tas5086_private *priv = snd_soc_codec_get_drvdata(codec); 812 struct tas5086_private *priv = snd_soc_codec_get_drvdata(codec);
723 int charge_period = 1300000; /* hardware default is 1300 ms */
724 u8 pwm_start_mid_z = 0;
725 int i, ret; 813 int i, ret;
726 814
815 priv->pwm_start_mid_z = 0;
816 priv->charge_period = 1300000; /* hardware default is 1300 ms */
817
727 if (of_match_device(of_match_ptr(tas5086_dt_ids), codec->dev)) { 818 if (of_match_device(of_match_ptr(tas5086_dt_ids), codec->dev)) {
728 struct device_node *of_node = codec->dev->of_node; 819 struct device_node *of_node = codec->dev->of_node;
729 of_property_read_u32(of_node, "ti,charge-period", &charge_period); 820
821 of_property_read_u32(of_node, "ti,charge-period",
822 &priv->charge_period);
730 823
731 for (i = 0; i < 6; i++) { 824 for (i = 0; i < 6; i++) {
732 char name[25]; 825 char name[25];
@@ -735,43 +828,11 @@ static int tas5086_probe(struct snd_soc_codec *codec)
735 "ti,mid-z-channel-%d", i + 1); 828 "ti,mid-z-channel-%d", i + 1);
736 829
737 if (of_get_property(of_node, name, NULL) != NULL) 830 if (of_get_property(of_node, name, NULL) != NULL)
738 pwm_start_mid_z |= 1 << i; 831 priv->pwm_start_mid_z |= 1 << i;
739 } 832 }
740 } 833 }
741 834
742 /* 835 ret = tas5086_init(codec->dev, priv);
743 * If any of the channels is configured to start in Mid-Z mode,
744 * configure 'part 1' of the PWM starts to use Mid-Z, and tell
745 * all configured mid-z channels to start start under 'part 1'.
746 */
747 if (pwm_start_mid_z)
748 regmap_write(priv->regmap, TAS5086_PWM_START,
749 TAS5086_PWM_START_MIDZ_FOR_START_1 |
750 pwm_start_mid_z);
751
752 /* lookup and set split-capacitor charge period */
753 if (charge_period == 0) {
754 regmap_write(priv->regmap, TAS5086_SPLIT_CAP_CHARGE, 0);
755 } else {
756 i = index_in_array(tas5086_charge_period,
757 ARRAY_SIZE(tas5086_charge_period),
758 charge_period);
759 if (i >= 0)
760 regmap_write(priv->regmap, TAS5086_SPLIT_CAP_CHARGE,
761 i + 0x08);
762 else
763 dev_warn(codec->dev,
764 "Invalid split-cap charge period of %d ns.\n",
765 charge_period);
766 }
767
768 /* enable factory trim */
769 ret = regmap_write(priv->regmap, TAS5086_OSC_TRIM, 0x00);
770 if (ret < 0)
771 return ret;
772
773 /* start all channels */
774 ret = regmap_write(priv->regmap, TAS5086_SYS_CONTROL_2, 0x20);
775 if (ret < 0) 836 if (ret < 0)
776 return ret; 837 return ret;
777 838
@@ -780,12 +841,6 @@ static int tas5086_probe(struct snd_soc_codec *codec)
780 if (ret < 0) 841 if (ret < 0)
781 return ret; 842 return ret;
782 843
783 /* mute all channels for now */
784 ret = regmap_write(priv->regmap, TAS5086_SOFT_MUTE,
785 TAS5086_SOFT_MUTE_ALL);
786 if (ret < 0)
787 return ret;
788
789 return 0; 844 return 0;
790} 845}
791 846
@@ -803,6 +858,7 @@ static int tas5086_remove(struct snd_soc_codec *codec)
803static struct snd_soc_codec_driver soc_codec_dev_tas5086 = { 858static struct snd_soc_codec_driver soc_codec_dev_tas5086 = {
804 .probe = tas5086_probe, 859 .probe = tas5086_probe,
805 .remove = tas5086_remove, 860 .remove = tas5086_remove,
861 .suspend = tas5086_soc_suspend,
806 .resume = tas5086_soc_resume, 862 .resume = tas5086_soc_resume,
807 .controls = tas5086_controls, 863 .controls = tas5086_controls,
808 .num_controls = ARRAY_SIZE(tas5086_controls), 864 .num_controls = ARRAY_SIZE(tas5086_controls),
@@ -862,17 +918,8 @@ static int tas5086_i2c_probe(struct i2c_client *i2c,
862 if (devm_gpio_request(dev, gpio_nreset, "TAS5086 Reset")) 918 if (devm_gpio_request(dev, gpio_nreset, "TAS5086 Reset"))
863 gpio_nreset = -EINVAL; 919 gpio_nreset = -EINVAL;
864 920
865 if (gpio_is_valid(gpio_nreset)) {
866 /* Reset codec - minimum assertion time is 400ns */
867 gpio_direction_output(gpio_nreset, 0);
868 udelay(1);
869 gpio_set_value(gpio_nreset, 1);
870
871 /* Codec needs ~15ms to wake up */
872 msleep(15);
873 }
874
875 priv->gpio_nreset = gpio_nreset; 921 priv->gpio_nreset = gpio_nreset;
922 tas5086_reset(priv);
876 923
877 /* The TAS5086 always returns 0x03 in its TAS5086_DEV_ID register */ 924 /* The TAS5086 always returns 0x03 in its TAS5086_DEV_ID register */
878 ret = regmap_read(priv->regmap, TAS5086_DEV_ID, &i); 925 ret = regmap_read(priv->regmap, TAS5086_DEV_ID, &i);