diff options
Diffstat (limited to 'sound/soc/codecs/cs35l35.c')
-rw-r--r-- | sound/soc/codecs/cs35l35.c | 94 |
1 files changed, 92 insertions, 2 deletions
diff --git a/sound/soc/codecs/cs35l35.c b/sound/soc/codecs/cs35l35.c index f8aef5869b03..f1ee184ecab2 100644 --- a/sound/soc/codecs/cs35l35.c +++ b/sound/soc/codecs/cs35l35.c | |||
@@ -162,6 +162,14 @@ static bool cs35l35_precious_register(struct device *dev, unsigned int reg) | |||
162 | } | 162 | } |
163 | } | 163 | } |
164 | 164 | ||
165 | static void cs35l35_reset(struct cs35l35_private *cs35l35) | ||
166 | { | ||
167 | gpiod_set_value_cansleep(cs35l35->reset_gpio, 0); | ||
168 | usleep_range(2000, 2100); | ||
169 | gpiod_set_value_cansleep(cs35l35->reset_gpio, 1); | ||
170 | usleep_range(1000, 1100); | ||
171 | } | ||
172 | |||
165 | static int cs35l35_wait_for_pdn(struct cs35l35_private *cs35l35) | 173 | static int cs35l35_wait_for_pdn(struct cs35l35_private *cs35l35) |
166 | { | 174 | { |
167 | int ret; | 175 | int ret; |
@@ -756,6 +764,76 @@ static int cs35l35_codec_set_sysclk(struct snd_soc_codec *codec, | |||
756 | return ret; | 764 | return ret; |
757 | } | 765 | } |
758 | 766 | ||
767 | static int cs35l35_boost_inductor(struct cs35l35_private *cs35l35, | ||
768 | int inductor) | ||
769 | { | ||
770 | struct regmap *regmap = cs35l35->regmap; | ||
771 | unsigned int bst_ipk = 0; | ||
772 | |||
773 | /* | ||
774 | * Digital Boost Converter Configuration for feedback, | ||
775 | * ramping, switching frequency, and estimation block seeding. | ||
776 | */ | ||
777 | |||
778 | regmap_update_bits(regmap, CS35L35_BST_CONV_SW_FREQ, | ||
779 | CS35L35_BST_CONV_SWFREQ_MASK, 0x00); | ||
780 | |||
781 | regmap_read(regmap, CS35L35_BST_PEAK_I, &bst_ipk); | ||
782 | bst_ipk &= CS35L35_BST_IPK_MASK; | ||
783 | |||
784 | switch (inductor) { | ||
785 | case 1000: /* 1 uH */ | ||
786 | regmap_write(regmap, CS35L35_BST_CONV_COEF_1, 0x24); | ||
787 | regmap_write(regmap, CS35L35_BST_CONV_COEF_2, 0x24); | ||
788 | regmap_update_bits(regmap, CS35L35_BST_CONV_SW_FREQ, | ||
789 | CS35L35_BST_CONV_LBST_MASK, 0x00); | ||
790 | |||
791 | if (bst_ipk < 0x04) | ||
792 | regmap_write(regmap, CS35L35_BST_CONV_SLOPE_COMP, 0x1B); | ||
793 | else | ||
794 | regmap_write(regmap, CS35L35_BST_CONV_SLOPE_COMP, 0x4E); | ||
795 | break; | ||
796 | case 1200: /* 1.2 uH */ | ||
797 | regmap_write(regmap, CS35L35_BST_CONV_COEF_1, 0x20); | ||
798 | regmap_write(regmap, CS35L35_BST_CONV_COEF_2, 0x20); | ||
799 | regmap_update_bits(regmap, CS35L35_BST_CONV_SW_FREQ, | ||
800 | CS35L35_BST_CONV_LBST_MASK, 0x01); | ||
801 | |||
802 | if (bst_ipk < 0x04) | ||
803 | regmap_write(regmap, CS35L35_BST_CONV_SLOPE_COMP, 0x1B); | ||
804 | else | ||
805 | regmap_write(regmap, CS35L35_BST_CONV_SLOPE_COMP, 0x47); | ||
806 | break; | ||
807 | case 1500: /* 1.5uH */ | ||
808 | regmap_write(regmap, CS35L35_BST_CONV_COEF_1, 0x20); | ||
809 | regmap_write(regmap, CS35L35_BST_CONV_COEF_2, 0x20); | ||
810 | regmap_update_bits(regmap, CS35L35_BST_CONV_SW_FREQ, | ||
811 | CS35L35_BST_CONV_LBST_MASK, 0x02); | ||
812 | |||
813 | if (bst_ipk < 0x04) | ||
814 | regmap_write(regmap, CS35L35_BST_CONV_SLOPE_COMP, 0x1B); | ||
815 | else | ||
816 | regmap_write(regmap, CS35L35_BST_CONV_SLOPE_COMP, 0x3C); | ||
817 | break; | ||
818 | case 2200: /* 2.2uH */ | ||
819 | regmap_write(regmap, CS35L35_BST_CONV_COEF_1, 0x19); | ||
820 | regmap_write(regmap, CS35L35_BST_CONV_COEF_2, 0x25); | ||
821 | regmap_update_bits(regmap, CS35L35_BST_CONV_SW_FREQ, | ||
822 | CS35L35_BST_CONV_LBST_MASK, 0x03); | ||
823 | |||
824 | if (bst_ipk < 0x04) | ||
825 | regmap_write(regmap, CS35L35_BST_CONV_SLOPE_COMP, 0x1B); | ||
826 | else | ||
827 | regmap_write(regmap, CS35L35_BST_CONV_SLOPE_COMP, 0x23); | ||
828 | break; | ||
829 | default: | ||
830 | dev_err(cs35l35->dev, "Invalid Inductor Value %d uH\n", | ||
831 | inductor); | ||
832 | return -EINVAL; | ||
833 | } | ||
834 | return 0; | ||
835 | } | ||
836 | |||
759 | static int cs35l35_codec_probe(struct snd_soc_codec *codec) | 837 | static int cs35l35_codec_probe(struct snd_soc_codec *codec) |
760 | { | 838 | { |
761 | struct cs35l35_private *cs35l35 = snd_soc_codec_get_drvdata(codec); | 839 | struct cs35l35_private *cs35l35 = snd_soc_codec_get_drvdata(codec); |
@@ -775,6 +853,10 @@ static int cs35l35_codec_probe(struct snd_soc_codec *codec) | |||
775 | cs35l35->pdata.bst_ipk << | 853 | cs35l35->pdata.bst_ipk << |
776 | CS35L35_BST_IPK_SHIFT); | 854 | CS35L35_BST_IPK_SHIFT); |
777 | 855 | ||
856 | ret = cs35l35_boost_inductor(cs35l35, cs35l35->pdata.boost_ind); | ||
857 | if (ret) | ||
858 | return ret; | ||
859 | |||
778 | if (cs35l35->pdata.gain_zc) | 860 | if (cs35l35->pdata.gain_zc) |
779 | regmap_update_bits(cs35l35->regmap, CS35L35_PROTECT_CTL, | 861 | regmap_update_bits(cs35l35->regmap, CS35L35_PROTECT_CTL, |
780 | CS35L35_AMP_GAIN_ZC_MASK, | 862 | CS35L35_AMP_GAIN_ZC_MASK, |
@@ -1195,7 +1277,15 @@ static int cs35l35_handle_of_data(struct i2c_client *i2c_client, | |||
1195 | return -EINVAL; | 1277 | return -EINVAL; |
1196 | } | 1278 | } |
1197 | 1279 | ||
1198 | pdata->bst_ipk = (val32 - 1680) / 110; | 1280 | pdata->bst_ipk = ((val32 - 1680) / 110) | CS35L35_VALID_PDATA; |
1281 | } | ||
1282 | |||
1283 | ret = of_property_read_u32(np, "cirrus,boost-ind-nanohenry", &val32); | ||
1284 | if (ret >= 0) { | ||
1285 | pdata->boost_ind = val32; | ||
1286 | } else { | ||
1287 | dev_err(&i2c_client->dev, "Inductor not specified.\n"); | ||
1288 | return -EINVAL; | ||
1199 | } | 1289 | } |
1200 | 1290 | ||
1201 | if (of_property_read_u32(np, "cirrus,sp-drv-strength", &val32) >= 0) | 1291 | if (of_property_read_u32(np, "cirrus,sp-drv-strength", &val32) >= 0) |
@@ -1454,7 +1544,7 @@ static int cs35l35_i2c_probe(struct i2c_client *i2c_client, | |||
1454 | } | 1544 | } |
1455 | } | 1545 | } |
1456 | 1546 | ||
1457 | gpiod_set_value_cansleep(cs35l35->reset_gpio, 1); | 1547 | cs35l35_reset(cs35l35); |
1458 | 1548 | ||
1459 | init_completion(&cs35l35->pdn_done); | 1549 | init_completion(&cs35l35->pdn_done); |
1460 | 1550 | ||