diff options
-rw-r--r-- | Documentation/devicetree/bindings/sound/sgtl5000.txt | 3 | ||||
-rw-r--r-- | sound/soc/codecs/sgtl5000.c | 267 | ||||
-rw-r--r-- | sound/soc/codecs/sgtl5000.h | 2 | ||||
-rw-r--r-- | sound/soc/fsl/imx-sgtl5000.c | 32 |
4 files changed, 220 insertions, 84 deletions
diff --git a/Documentation/devicetree/bindings/sound/sgtl5000.txt b/Documentation/devicetree/bindings/sound/sgtl5000.txt index 9cc44449508d..955df60a118c 100644 --- a/Documentation/devicetree/bindings/sound/sgtl5000.txt +++ b/Documentation/devicetree/bindings/sound/sgtl5000.txt | |||
@@ -5,9 +5,12 @@ Required properties: | |||
5 | 5 | ||
6 | - reg : the I2C address of the device | 6 | - reg : the I2C address of the device |
7 | 7 | ||
8 | - clocks : the clock provider of SYS_MCLK | ||
9 | |||
8 | Example: | 10 | Example: |
9 | 11 | ||
10 | codec: sgtl5000@0a { | 12 | codec: sgtl5000@0a { |
11 | compatible = "fsl,sgtl5000"; | 13 | compatible = "fsl,sgtl5000"; |
12 | reg = <0x0a>; | 14 | reg = <0x0a>; |
15 | clocks = <&clks 150>; | ||
13 | }; | 16 | }; |
diff --git a/sound/soc/codecs/sgtl5000.c b/sound/soc/codecs/sgtl5000.c index 92bbfec9b107..d441559dc92c 100644 --- a/sound/soc/codecs/sgtl5000.c +++ b/sound/soc/codecs/sgtl5000.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/pm.h> | 16 | #include <linux/pm.h> |
17 | #include <linux/i2c.h> | 17 | #include <linux/i2c.h> |
18 | #include <linux/clk.h> | 18 | #include <linux/clk.h> |
19 | #include <linux/regmap.h> | ||
19 | #include <linux/regulator/driver.h> | 20 | #include <linux/regulator/driver.h> |
20 | #include <linux/regulator/machine.h> | 21 | #include <linux/regulator/machine.h> |
21 | #include <linux/regulator/consumer.h> | 22 | #include <linux/regulator/consumer.h> |
@@ -34,30 +35,30 @@ | |||
34 | #define SGTL5000_MAX_REG_OFFSET 0x013A | 35 | #define SGTL5000_MAX_REG_OFFSET 0x013A |
35 | 36 | ||
36 | /* default value of sgtl5000 registers */ | 37 | /* default value of sgtl5000 registers */ |
37 | static const u16 sgtl5000_regs[SGTL5000_MAX_REG_OFFSET] = { | 38 | static const struct reg_default sgtl5000_reg_defaults[] = { |
38 | [SGTL5000_CHIP_CLK_CTRL] = 0x0008, | 39 | { SGTL5000_CHIP_CLK_CTRL, 0x0008 }, |
39 | [SGTL5000_CHIP_I2S_CTRL] = 0x0010, | 40 | { SGTL5000_CHIP_I2S_CTRL, 0x0010 }, |
40 | [SGTL5000_CHIP_SSS_CTRL] = 0x0008, | 41 | { SGTL5000_CHIP_SSS_CTRL, 0x0008 }, |
41 | [SGTL5000_CHIP_DAC_VOL] = 0x3c3c, | 42 | { SGTL5000_CHIP_DAC_VOL, 0x3c3c }, |
42 | [SGTL5000_CHIP_PAD_STRENGTH] = 0x015f, | 43 | { SGTL5000_CHIP_PAD_STRENGTH, 0x015f }, |
43 | [SGTL5000_CHIP_ANA_HP_CTRL] = 0x1818, | 44 | { SGTL5000_CHIP_ANA_HP_CTRL, 0x1818 }, |
44 | [SGTL5000_CHIP_ANA_CTRL] = 0x0111, | 45 | { SGTL5000_CHIP_ANA_CTRL, 0x0111 }, |
45 | [SGTL5000_CHIP_LINE_OUT_VOL] = 0x0404, | 46 | { SGTL5000_CHIP_LINE_OUT_VOL, 0x0404 }, |
46 | [SGTL5000_CHIP_ANA_POWER] = 0x7060, | 47 | { SGTL5000_CHIP_ANA_POWER, 0x7060 }, |
47 | [SGTL5000_CHIP_PLL_CTRL] = 0x5000, | 48 | { SGTL5000_CHIP_PLL_CTRL, 0x5000 }, |
48 | [SGTL5000_DAP_BASS_ENHANCE] = 0x0040, | 49 | { SGTL5000_DAP_BASS_ENHANCE, 0x0040 }, |
49 | [SGTL5000_DAP_BASS_ENHANCE_CTRL] = 0x051f, | 50 | { SGTL5000_DAP_BASS_ENHANCE_CTRL, 0x051f }, |
50 | [SGTL5000_DAP_SURROUND] = 0x0040, | 51 | { SGTL5000_DAP_SURROUND, 0x0040 }, |
51 | [SGTL5000_DAP_EQ_BASS_BAND0] = 0x002f, | 52 | { SGTL5000_DAP_EQ_BASS_BAND0, 0x002f }, |
52 | [SGTL5000_DAP_EQ_BASS_BAND1] = 0x002f, | 53 | { SGTL5000_DAP_EQ_BASS_BAND1, 0x002f }, |
53 | [SGTL5000_DAP_EQ_BASS_BAND2] = 0x002f, | 54 | { SGTL5000_DAP_EQ_BASS_BAND2, 0x002f }, |
54 | [SGTL5000_DAP_EQ_BASS_BAND3] = 0x002f, | 55 | { SGTL5000_DAP_EQ_BASS_BAND3, 0x002f }, |
55 | [SGTL5000_DAP_EQ_BASS_BAND4] = 0x002f, | 56 | { SGTL5000_DAP_EQ_BASS_BAND4, 0x002f }, |
56 | [SGTL5000_DAP_MAIN_CHAN] = 0x8000, | 57 | { SGTL5000_DAP_MAIN_CHAN, 0x8000 }, |
57 | [SGTL5000_DAP_AVC_CTRL] = 0x0510, | 58 | { SGTL5000_DAP_AVC_CTRL, 0x0510 }, |
58 | [SGTL5000_DAP_AVC_THRESHOLD] = 0x1473, | 59 | { SGTL5000_DAP_AVC_THRESHOLD, 0x1473 }, |
59 | [SGTL5000_DAP_AVC_ATTACK] = 0x0028, | 60 | { SGTL5000_DAP_AVC_ATTACK, 0x0028 }, |
60 | [SGTL5000_DAP_AVC_DECAY] = 0x0050, | 61 | { SGTL5000_DAP_AVC_DECAY, 0x0050 }, |
61 | }; | 62 | }; |
62 | 63 | ||
63 | /* regulator supplies for sgtl5000, VDDD is an optional external supply */ | 64 | /* regulator supplies for sgtl5000, VDDD is an optional external supply */ |
@@ -112,6 +113,8 @@ struct sgtl5000_priv { | |||
112 | int fmt; /* i2s data format */ | 113 | int fmt; /* i2s data format */ |
113 | struct regulator_bulk_data supplies[SGTL5000_SUPPLY_NUM]; | 114 | struct regulator_bulk_data supplies[SGTL5000_SUPPLY_NUM]; |
114 | struct ldo_regulator *ldo; | 115 | struct ldo_regulator *ldo; |
116 | struct regmap *regmap; | ||
117 | struct clk *mclk; | ||
115 | }; | 118 | }; |
116 | 119 | ||
117 | /* | 120 | /* |
@@ -151,12 +154,12 @@ static int power_vag_event(struct snd_soc_dapm_widget *w, | |||
151 | struct snd_kcontrol *kcontrol, int event) | 154 | struct snd_kcontrol *kcontrol, int event) |
152 | { | 155 | { |
153 | switch (event) { | 156 | switch (event) { |
154 | case SND_SOC_DAPM_PRE_PMU: | 157 | case SND_SOC_DAPM_POST_PMU: |
155 | snd_soc_update_bits(w->codec, SGTL5000_CHIP_ANA_POWER, | 158 | snd_soc_update_bits(w->codec, SGTL5000_CHIP_ANA_POWER, |
156 | SGTL5000_VAG_POWERUP, SGTL5000_VAG_POWERUP); | 159 | SGTL5000_VAG_POWERUP, SGTL5000_VAG_POWERUP); |
157 | break; | 160 | break; |
158 | 161 | ||
159 | case SND_SOC_DAPM_POST_PMD: | 162 | case SND_SOC_DAPM_PRE_PMD: |
160 | snd_soc_update_bits(w->codec, SGTL5000_CHIP_ANA_POWER, | 163 | snd_soc_update_bits(w->codec, SGTL5000_CHIP_ANA_POWER, |
161 | SGTL5000_VAG_POWERUP, 0); | 164 | SGTL5000_VAG_POWERUP, 0); |
162 | msleep(400); | 165 | msleep(400); |
@@ -217,12 +220,11 @@ static const struct snd_soc_dapm_widget sgtl5000_dapm_widgets[] = { | |||
217 | 0, SGTL5000_CHIP_DIG_POWER, | 220 | 0, SGTL5000_CHIP_DIG_POWER, |
218 | 1, 0), | 221 | 1, 0), |
219 | 222 | ||
220 | SND_SOC_DAPM_SUPPLY("VAG_POWER", SGTL5000_CHIP_ANA_POWER, 7, 0, | ||
221 | power_vag_event, | ||
222 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), | ||
223 | |||
224 | SND_SOC_DAPM_ADC("ADC", "Capture", SGTL5000_CHIP_ANA_POWER, 1, 0), | 223 | SND_SOC_DAPM_ADC("ADC", "Capture", SGTL5000_CHIP_ANA_POWER, 1, 0), |
225 | SND_SOC_DAPM_DAC("DAC", "Playback", SGTL5000_CHIP_ANA_POWER, 3, 0), | 224 | SND_SOC_DAPM_DAC("DAC", "Playback", SGTL5000_CHIP_ANA_POWER, 3, 0), |
225 | |||
226 | SND_SOC_DAPM_PRE("VAG_POWER_PRE", power_vag_event), | ||
227 | SND_SOC_DAPM_POST("VAG_POWER_POST", power_vag_event), | ||
226 | }; | 228 | }; |
227 | 229 | ||
228 | /* routes for sgtl5000 */ | 230 | /* routes for sgtl5000 */ |
@@ -230,16 +232,13 @@ static const struct snd_soc_dapm_route sgtl5000_dapm_routes[] = { | |||
230 | {"Capture Mux", "LINE_IN", "LINE_IN"}, /* line_in --> adc_mux */ | 232 | {"Capture Mux", "LINE_IN", "LINE_IN"}, /* line_in --> adc_mux */ |
231 | {"Capture Mux", "MIC_IN", "MIC_IN"}, /* mic_in --> adc_mux */ | 233 | {"Capture Mux", "MIC_IN", "MIC_IN"}, /* mic_in --> adc_mux */ |
232 | 234 | ||
233 | {"ADC", NULL, "VAG_POWER"}, | ||
234 | {"ADC", NULL, "Capture Mux"}, /* adc_mux --> adc */ | 235 | {"ADC", NULL, "Capture Mux"}, /* adc_mux --> adc */ |
235 | {"AIFOUT", NULL, "ADC"}, /* adc --> i2s_out */ | 236 | {"AIFOUT", NULL, "ADC"}, /* adc --> i2s_out */ |
236 | 237 | ||
237 | {"DAC", NULL, "VAG_POWER"}, | ||
238 | {"DAC", NULL, "AIFIN"}, /* i2s-->dac,skip audio mux */ | 238 | {"DAC", NULL, "AIFIN"}, /* i2s-->dac,skip audio mux */ |
239 | {"Headphone Mux", "DAC", "DAC"}, /* dac --> hp_mux */ | 239 | {"Headphone Mux", "DAC", "DAC"}, /* dac --> hp_mux */ |
240 | {"LO", NULL, "DAC"}, /* dac --> line_out */ | 240 | {"LO", NULL, "DAC"}, /* dac --> line_out */ |
241 | 241 | ||
242 | {"LINE_IN", NULL, "VAG_POWER"}, | ||
243 | {"Headphone Mux", "LINE_IN", "LINE_IN"},/* line_in --> hp_mux */ | 242 | {"Headphone Mux", "LINE_IN", "LINE_IN"},/* line_in --> hp_mux */ |
244 | {"HP", NULL, "Headphone Mux"}, /* hp_mux --> hp */ | 243 | {"HP", NULL, "Headphone Mux"}, /* hp_mux --> hp */ |
245 | 244 | ||
@@ -909,10 +908,25 @@ static int sgtl5000_set_bias_level(struct snd_soc_codec *codec, | |||
909 | if (ret) | 908 | if (ret) |
910 | return ret; | 909 | return ret; |
911 | udelay(10); | 910 | udelay(10); |
911 | |||
912 | regcache_cache_only(sgtl5000->regmap, false); | ||
913 | |||
914 | ret = regcache_sync(sgtl5000->regmap); | ||
915 | if (ret != 0) { | ||
916 | dev_err(codec->dev, | ||
917 | "Failed to restore cache: %d\n", ret); | ||
918 | |||
919 | regcache_cache_only(sgtl5000->regmap, true); | ||
920 | regulator_bulk_disable(ARRAY_SIZE(sgtl5000->supplies), | ||
921 | sgtl5000->supplies); | ||
922 | |||
923 | return ret; | ||
924 | } | ||
912 | } | 925 | } |
913 | 926 | ||
914 | break; | 927 | break; |
915 | case SND_SOC_BIAS_OFF: | 928 | case SND_SOC_BIAS_OFF: |
929 | regcache_cache_only(sgtl5000->regmap, true); | ||
916 | regulator_bulk_disable(ARRAY_SIZE(sgtl5000->supplies), | 930 | regulator_bulk_disable(ARRAY_SIZE(sgtl5000->supplies), |
917 | sgtl5000->supplies); | 931 | sgtl5000->supplies); |
918 | break; | 932 | break; |
@@ -958,17 +972,76 @@ static struct snd_soc_dai_driver sgtl5000_dai = { | |||
958 | .symmetric_rates = 1, | 972 | .symmetric_rates = 1, |
959 | }; | 973 | }; |
960 | 974 | ||
961 | static int sgtl5000_volatile_register(struct snd_soc_codec *codec, | 975 | static bool sgtl5000_volatile(struct device *dev, unsigned int reg) |
962 | unsigned int reg) | ||
963 | { | 976 | { |
964 | switch (reg) { | 977 | switch (reg) { |
965 | case SGTL5000_CHIP_ID: | 978 | case SGTL5000_CHIP_ID: |
966 | case SGTL5000_CHIP_ADCDAC_CTRL: | 979 | case SGTL5000_CHIP_ADCDAC_CTRL: |
967 | case SGTL5000_CHIP_ANA_STATUS: | 980 | case SGTL5000_CHIP_ANA_STATUS: |
968 | return 1; | 981 | return true; |
969 | } | 982 | } |
970 | 983 | ||
971 | return 0; | 984 | return false; |
985 | } | ||
986 | |||
987 | static bool sgtl5000_readable(struct device *dev, unsigned int reg) | ||
988 | { | ||
989 | switch (reg) { | ||
990 | case SGTL5000_CHIP_ID: | ||
991 | case SGTL5000_CHIP_DIG_POWER: | ||
992 | case SGTL5000_CHIP_CLK_CTRL: | ||
993 | case SGTL5000_CHIP_I2S_CTRL: | ||
994 | case SGTL5000_CHIP_SSS_CTRL: | ||
995 | case SGTL5000_CHIP_ADCDAC_CTRL: | ||
996 | case SGTL5000_CHIP_DAC_VOL: | ||
997 | case SGTL5000_CHIP_PAD_STRENGTH: | ||
998 | case SGTL5000_CHIP_ANA_ADC_CTRL: | ||
999 | case SGTL5000_CHIP_ANA_HP_CTRL: | ||
1000 | case SGTL5000_CHIP_ANA_CTRL: | ||
1001 | case SGTL5000_CHIP_LINREG_CTRL: | ||
1002 | case SGTL5000_CHIP_REF_CTRL: | ||
1003 | case SGTL5000_CHIP_MIC_CTRL: | ||
1004 | case SGTL5000_CHIP_LINE_OUT_CTRL: | ||
1005 | case SGTL5000_CHIP_LINE_OUT_VOL: | ||
1006 | case SGTL5000_CHIP_ANA_POWER: | ||
1007 | case SGTL5000_CHIP_PLL_CTRL: | ||
1008 | case SGTL5000_CHIP_CLK_TOP_CTRL: | ||
1009 | case SGTL5000_CHIP_ANA_STATUS: | ||
1010 | case SGTL5000_CHIP_SHORT_CTRL: | ||
1011 | case SGTL5000_CHIP_ANA_TEST2: | ||
1012 | case SGTL5000_DAP_CTRL: | ||
1013 | case SGTL5000_DAP_PEQ: | ||
1014 | case SGTL5000_DAP_BASS_ENHANCE: | ||
1015 | case SGTL5000_DAP_BASS_ENHANCE_CTRL: | ||
1016 | case SGTL5000_DAP_AUDIO_EQ: | ||
1017 | case SGTL5000_DAP_SURROUND: | ||
1018 | case SGTL5000_DAP_FLT_COEF_ACCESS: | ||
1019 | case SGTL5000_DAP_COEF_WR_B0_MSB: | ||
1020 | case SGTL5000_DAP_COEF_WR_B0_LSB: | ||
1021 | case SGTL5000_DAP_EQ_BASS_BAND0: | ||
1022 | case SGTL5000_DAP_EQ_BASS_BAND1: | ||
1023 | case SGTL5000_DAP_EQ_BASS_BAND2: | ||
1024 | case SGTL5000_DAP_EQ_BASS_BAND3: | ||
1025 | case SGTL5000_DAP_EQ_BASS_BAND4: | ||
1026 | case SGTL5000_DAP_MAIN_CHAN: | ||
1027 | case SGTL5000_DAP_MIX_CHAN: | ||
1028 | case SGTL5000_DAP_AVC_CTRL: | ||
1029 | case SGTL5000_DAP_AVC_THRESHOLD: | ||
1030 | case SGTL5000_DAP_AVC_ATTACK: | ||
1031 | case SGTL5000_DAP_AVC_DECAY: | ||
1032 | case SGTL5000_DAP_COEF_WR_B1_MSB: | ||
1033 | case SGTL5000_DAP_COEF_WR_B1_LSB: | ||
1034 | case SGTL5000_DAP_COEF_WR_B2_MSB: | ||
1035 | case SGTL5000_DAP_COEF_WR_B2_LSB: | ||
1036 | case SGTL5000_DAP_COEF_WR_A1_MSB: | ||
1037 | case SGTL5000_DAP_COEF_WR_A1_LSB: | ||
1038 | case SGTL5000_DAP_COEF_WR_A2_MSB: | ||
1039 | case SGTL5000_DAP_COEF_WR_A2_LSB: | ||
1040 | return true; | ||
1041 | |||
1042 | default: | ||
1043 | return false; | ||
1044 | } | ||
972 | } | 1045 | } |
973 | 1046 | ||
974 | #ifdef CONFIG_SUSPEND | 1047 | #ifdef CONFIG_SUSPEND |
@@ -1214,7 +1287,7 @@ static int sgtl5000_replace_vddd_with_ldo(struct snd_soc_codec *codec) | |||
1214 | 1287 | ||
1215 | static int sgtl5000_enable_regulators(struct snd_soc_codec *codec) | 1288 | static int sgtl5000_enable_regulators(struct snd_soc_codec *codec) |
1216 | { | 1289 | { |
1217 | u16 reg; | 1290 | int reg; |
1218 | int ret; | 1291 | int ret; |
1219 | int rev; | 1292 | int rev; |
1220 | int i; | 1293 | int i; |
@@ -1242,23 +1315,17 @@ static int sgtl5000_enable_regulators(struct snd_soc_codec *codec) | |||
1242 | /* wait for all power rails bring up */ | 1315 | /* wait for all power rails bring up */ |
1243 | udelay(10); | 1316 | udelay(10); |
1244 | 1317 | ||
1245 | /* read chip information */ | ||
1246 | reg = snd_soc_read(codec, SGTL5000_CHIP_ID); | ||
1247 | if (((reg & SGTL5000_PARTID_MASK) >> SGTL5000_PARTID_SHIFT) != | ||
1248 | SGTL5000_PARTID_PART_ID) { | ||
1249 | dev_err(codec->dev, | ||
1250 | "Device with ID register %x is not a sgtl5000\n", reg); | ||
1251 | ret = -ENODEV; | ||
1252 | goto err_regulator_disable; | ||
1253 | } | ||
1254 | |||
1255 | rev = (reg & SGTL5000_REVID_MASK) >> SGTL5000_REVID_SHIFT; | ||
1256 | dev_info(codec->dev, "sgtl5000 revision 0x%x\n", rev); | ||
1257 | |||
1258 | /* | 1318 | /* |
1259 | * workaround for revision 0x11 and later, | 1319 | * workaround for revision 0x11 and later, |
1260 | * roll back to use internal LDO | 1320 | * roll back to use internal LDO |
1261 | */ | 1321 | */ |
1322 | |||
1323 | ret = regmap_read(sgtl5000->regmap, SGTL5000_CHIP_ID, ®); | ||
1324 | if (ret) | ||
1325 | goto err_regulator_disable; | ||
1326 | |||
1327 | rev = (reg & SGTL5000_REVID_MASK) >> SGTL5000_REVID_SHIFT; | ||
1328 | |||
1262 | if (external_vddd && rev >= 0x11) { | 1329 | if (external_vddd && rev >= 0x11) { |
1263 | /* disable all regulator first */ | 1330 | /* disable all regulator first */ |
1264 | regulator_bulk_disable(ARRAY_SIZE(sgtl5000->supplies), | 1331 | regulator_bulk_disable(ARRAY_SIZE(sgtl5000->supplies), |
@@ -1300,7 +1367,8 @@ static int sgtl5000_probe(struct snd_soc_codec *codec) | |||
1300 | struct sgtl5000_priv *sgtl5000 = snd_soc_codec_get_drvdata(codec); | 1367 | struct sgtl5000_priv *sgtl5000 = snd_soc_codec_get_drvdata(codec); |
1301 | 1368 | ||
1302 | /* setup i2c data ops */ | 1369 | /* setup i2c data ops */ |
1303 | ret = snd_soc_codec_set_cache_io(codec, 16, 16, SND_SOC_I2C); | 1370 | codec->control_data = sgtl5000->regmap; |
1371 | ret = snd_soc_codec_set_cache_io(codec, 16, 16, SND_SOC_REGMAP); | ||
1304 | if (ret < 0) { | 1372 | if (ret < 0) { |
1305 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | 1373 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); |
1306 | return ret; | 1374 | return ret; |
@@ -1391,11 +1459,6 @@ static struct snd_soc_codec_driver sgtl5000_driver = { | |||
1391 | .suspend = sgtl5000_suspend, | 1459 | .suspend = sgtl5000_suspend, |
1392 | .resume = sgtl5000_resume, | 1460 | .resume = sgtl5000_resume, |
1393 | .set_bias_level = sgtl5000_set_bias_level, | 1461 | .set_bias_level = sgtl5000_set_bias_level, |
1394 | .reg_cache_size = ARRAY_SIZE(sgtl5000_regs), | ||
1395 | .reg_word_size = sizeof(u16), | ||
1396 | .reg_cache_step = 2, | ||
1397 | .reg_cache_default = sgtl5000_regs, | ||
1398 | .volatile_register = sgtl5000_volatile_register, | ||
1399 | .controls = sgtl5000_snd_controls, | 1462 | .controls = sgtl5000_snd_controls, |
1400 | .num_controls = ARRAY_SIZE(sgtl5000_snd_controls), | 1463 | .num_controls = ARRAY_SIZE(sgtl5000_snd_controls), |
1401 | .dapm_widgets = sgtl5000_dapm_widgets, | 1464 | .dapm_widgets = sgtl5000_dapm_widgets, |
@@ -1404,28 +1467,114 @@ static struct snd_soc_codec_driver sgtl5000_driver = { | |||
1404 | .num_dapm_routes = ARRAY_SIZE(sgtl5000_dapm_routes), | 1467 | .num_dapm_routes = ARRAY_SIZE(sgtl5000_dapm_routes), |
1405 | }; | 1468 | }; |
1406 | 1469 | ||
1470 | static const struct regmap_config sgtl5000_regmap = { | ||
1471 | .reg_bits = 16, | ||
1472 | .val_bits = 16, | ||
1473 | |||
1474 | .max_register = SGTL5000_MAX_REG_OFFSET, | ||
1475 | .volatile_reg = sgtl5000_volatile, | ||
1476 | .readable_reg = sgtl5000_readable, | ||
1477 | |||
1478 | .cache_type = REGCACHE_RBTREE, | ||
1479 | .reg_defaults = sgtl5000_reg_defaults, | ||
1480 | .num_reg_defaults = ARRAY_SIZE(sgtl5000_reg_defaults), | ||
1481 | }; | ||
1482 | |||
1483 | /* | ||
1484 | * Write all the default values from sgtl5000_reg_defaults[] array into the | ||
1485 | * sgtl5000 registers, to make sure we always start with the sane registers | ||
1486 | * values as stated in the datasheet. | ||
1487 | * | ||
1488 | * Since sgtl5000 does not have a reset line, nor a reset command in software, | ||
1489 | * we follow this approach to guarantee we always start from the default values | ||
1490 | * and avoid problems like, not being able to probe after an audio playback | ||
1491 | * followed by a system reset or a 'reboot' command in Linux | ||
1492 | */ | ||
1493 | static int sgtl5000_fill_defaults(struct sgtl5000_priv *sgtl5000) | ||
1494 | { | ||
1495 | int i, ret, val, index; | ||
1496 | |||
1497 | for (i = 0; i < ARRAY_SIZE(sgtl5000_reg_defaults); i++) { | ||
1498 | val = sgtl5000_reg_defaults[i].def; | ||
1499 | index = sgtl5000_reg_defaults[i].reg; | ||
1500 | ret = regmap_write(sgtl5000->regmap, index, val); | ||
1501 | if (ret) | ||
1502 | return ret; | ||
1503 | } | ||
1504 | |||
1505 | return 0; | ||
1506 | } | ||
1507 | |||
1407 | static int sgtl5000_i2c_probe(struct i2c_client *client, | 1508 | static int sgtl5000_i2c_probe(struct i2c_client *client, |
1408 | const struct i2c_device_id *id) | 1509 | const struct i2c_device_id *id) |
1409 | { | 1510 | { |
1410 | struct sgtl5000_priv *sgtl5000; | 1511 | struct sgtl5000_priv *sgtl5000; |
1411 | int ret; | 1512 | int ret, reg, rev; |
1412 | 1513 | ||
1413 | sgtl5000 = devm_kzalloc(&client->dev, sizeof(struct sgtl5000_priv), | 1514 | sgtl5000 = devm_kzalloc(&client->dev, sizeof(struct sgtl5000_priv), |
1414 | GFP_KERNEL); | 1515 | GFP_KERNEL); |
1415 | if (!sgtl5000) | 1516 | if (!sgtl5000) |
1416 | return -ENOMEM; | 1517 | return -ENOMEM; |
1417 | 1518 | ||
1519 | sgtl5000->regmap = devm_regmap_init_i2c(client, &sgtl5000_regmap); | ||
1520 | if (IS_ERR(sgtl5000->regmap)) { | ||
1521 | ret = PTR_ERR(sgtl5000->regmap); | ||
1522 | dev_err(&client->dev, "Failed to allocate regmap: %d\n", ret); | ||
1523 | return ret; | ||
1524 | } | ||
1525 | |||
1526 | sgtl5000->mclk = devm_clk_get(&client->dev, NULL); | ||
1527 | if (IS_ERR(sgtl5000->mclk)) { | ||
1528 | ret = PTR_ERR(sgtl5000->mclk); | ||
1529 | dev_err(&client->dev, "Failed to get mclock: %d\n", ret); | ||
1530 | return ret; | ||
1531 | } | ||
1532 | |||
1533 | ret = clk_prepare_enable(sgtl5000->mclk); | ||
1534 | if (ret) | ||
1535 | return ret; | ||
1536 | |||
1537 | /* read chip information */ | ||
1538 | ret = regmap_read(sgtl5000->regmap, SGTL5000_CHIP_ID, ®); | ||
1539 | if (ret) | ||
1540 | goto disable_clk; | ||
1541 | |||
1542 | if (((reg & SGTL5000_PARTID_MASK) >> SGTL5000_PARTID_SHIFT) != | ||
1543 | SGTL5000_PARTID_PART_ID) { | ||
1544 | dev_err(&client->dev, | ||
1545 | "Device with ID register %x is not a sgtl5000\n", reg); | ||
1546 | ret = -ENODEV; | ||
1547 | goto disable_clk; | ||
1548 | } | ||
1549 | |||
1550 | rev = (reg & SGTL5000_REVID_MASK) >> SGTL5000_REVID_SHIFT; | ||
1551 | dev_info(&client->dev, "sgtl5000 revision 0x%x\n", rev); | ||
1552 | |||
1418 | i2c_set_clientdata(client, sgtl5000); | 1553 | i2c_set_clientdata(client, sgtl5000); |
1419 | 1554 | ||
1555 | /* Ensure sgtl5000 will start with sane register values */ | ||
1556 | ret = sgtl5000_fill_defaults(sgtl5000); | ||
1557 | if (ret) | ||
1558 | goto disable_clk; | ||
1559 | |||
1420 | ret = snd_soc_register_codec(&client->dev, | 1560 | ret = snd_soc_register_codec(&client->dev, |
1421 | &sgtl5000_driver, &sgtl5000_dai, 1); | 1561 | &sgtl5000_driver, &sgtl5000_dai, 1); |
1562 | if (ret) | ||
1563 | goto disable_clk; | ||
1564 | |||
1565 | return 0; | ||
1566 | |||
1567 | disable_clk: | ||
1568 | clk_disable_unprepare(sgtl5000->mclk); | ||
1422 | return ret; | 1569 | return ret; |
1423 | } | 1570 | } |
1424 | 1571 | ||
1425 | static int sgtl5000_i2c_remove(struct i2c_client *client) | 1572 | static int sgtl5000_i2c_remove(struct i2c_client *client) |
1426 | { | 1573 | { |
1427 | snd_soc_unregister_codec(&client->dev); | 1574 | struct sgtl5000_priv *sgtl5000 = i2c_get_clientdata(client); |
1428 | 1575 | ||
1576 | snd_soc_unregister_codec(&client->dev); | ||
1577 | clk_disable_unprepare(sgtl5000->mclk); | ||
1429 | return 0; | 1578 | return 0; |
1430 | } | 1579 | } |
1431 | 1580 | ||
diff --git a/sound/soc/codecs/sgtl5000.h b/sound/soc/codecs/sgtl5000.h index 8a9f43534b79..4b69229a9818 100644 --- a/sound/soc/codecs/sgtl5000.h +++ b/sound/soc/codecs/sgtl5000.h | |||
@@ -12,7 +12,7 @@ | |||
12 | #define _SGTL5000_H | 12 | #define _SGTL5000_H |
13 | 13 | ||
14 | /* | 14 | /* |
15 | * Register values. | 15 | * Registers addresses |
16 | */ | 16 | */ |
17 | #define SGTL5000_CHIP_ID 0x0000 | 17 | #define SGTL5000_CHIP_ID 0x0000 |
18 | #define SGTL5000_CHIP_DIG_POWER 0x0002 | 18 | #define SGTL5000_CHIP_DIG_POWER 0x0002 |
diff --git a/sound/soc/fsl/imx-sgtl5000.c b/sound/soc/fsl/imx-sgtl5000.c index a60aaa053d28..7a8bc1220b2e 100644 --- a/sound/soc/fsl/imx-sgtl5000.c +++ b/sound/soc/fsl/imx-sgtl5000.c | |||
@@ -128,21 +128,11 @@ static int imx_sgtl5000_probe(struct platform_device *pdev) | |||
128 | goto fail; | 128 | goto fail; |
129 | } | 129 | } |
130 | 130 | ||
131 | data->codec_clk = clk_get(&codec_dev->dev, NULL); | 131 | data->codec_clk = devm_clk_get(&codec_dev->dev, NULL); |
132 | if (IS_ERR(data->codec_clk)) { | 132 | if (IS_ERR(data->codec_clk)) |
133 | /* assuming clock enabled by default */ | 133 | goto fail; |
134 | data->codec_clk = NULL; | 134 | |
135 | ret = of_property_read_u32(codec_np, "clock-frequency", | 135 | data->clk_frequency = clk_get_rate(data->codec_clk); |
136 | &data->clk_frequency); | ||
137 | if (ret) { | ||
138 | dev_err(&codec_dev->dev, | ||
139 | "clock-frequency missing or invalid\n"); | ||
140 | goto fail; | ||
141 | } | ||
142 | } else { | ||
143 | data->clk_frequency = clk_get_rate(data->codec_clk); | ||
144 | clk_prepare_enable(data->codec_clk); | ||
145 | } | ||
146 | 136 | ||
147 | data->dai.name = "HiFi"; | 137 | data->dai.name = "HiFi"; |
148 | data->dai.stream_name = "HiFi"; | 138 | data->dai.stream_name = "HiFi"; |
@@ -157,10 +147,10 @@ static int imx_sgtl5000_probe(struct platform_device *pdev) | |||
157 | data->card.dev = &pdev->dev; | 147 | data->card.dev = &pdev->dev; |
158 | ret = snd_soc_of_parse_card_name(&data->card, "model"); | 148 | ret = snd_soc_of_parse_card_name(&data->card, "model"); |
159 | if (ret) | 149 | if (ret) |
160 | goto clk_fail; | 150 | goto fail; |
161 | ret = snd_soc_of_parse_audio_routing(&data->card, "audio-routing"); | 151 | ret = snd_soc_of_parse_audio_routing(&data->card, "audio-routing"); |
162 | if (ret) | 152 | if (ret) |
163 | goto clk_fail; | 153 | goto fail; |
164 | data->card.num_links = 1; | 154 | data->card.num_links = 1; |
165 | data->card.owner = THIS_MODULE; | 155 | data->card.owner = THIS_MODULE; |
166 | data->card.dai_link = &data->dai; | 156 | data->card.dai_link = &data->dai; |
@@ -170,7 +160,7 @@ static int imx_sgtl5000_probe(struct platform_device *pdev) | |||
170 | ret = snd_soc_register_card(&data->card); | 160 | ret = snd_soc_register_card(&data->card); |
171 | if (ret) { | 161 | if (ret) { |
172 | dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret); | 162 | dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret); |
173 | goto clk_fail; | 163 | goto fail; |
174 | } | 164 | } |
175 | 165 | ||
176 | platform_set_drvdata(pdev, data); | 166 | platform_set_drvdata(pdev, data); |
@@ -179,8 +169,6 @@ static int imx_sgtl5000_probe(struct platform_device *pdev) | |||
179 | 169 | ||
180 | return 0; | 170 | return 0; |
181 | 171 | ||
182 | clk_fail: | ||
183 | clk_put(data->codec_clk); | ||
184 | fail: | 172 | fail: |
185 | if (ssi_np) | 173 | if (ssi_np) |
186 | of_node_put(ssi_np); | 174 | of_node_put(ssi_np); |
@@ -194,10 +182,6 @@ static int imx_sgtl5000_remove(struct platform_device *pdev) | |||
194 | { | 182 | { |
195 | struct imx_sgtl5000_data *data = platform_get_drvdata(pdev); | 183 | struct imx_sgtl5000_data *data = platform_get_drvdata(pdev); |
196 | 184 | ||
197 | if (data->codec_clk) { | ||
198 | clk_disable_unprepare(data->codec_clk); | ||
199 | clk_put(data->codec_clk); | ||
200 | } | ||
201 | snd_soc_unregister_card(&data->card); | 185 | snd_soc_unregister_card(&data->card); |
202 | 186 | ||
203 | return 0; | 187 | return 0; |