diff options
Diffstat (limited to 'sound/soc/codecs/cs42l52.c')
-rw-r--r-- | sound/soc/codecs/cs42l52.c | 105 |
1 files changed, 75 insertions, 30 deletions
diff --git a/sound/soc/codecs/cs42l52.c b/sound/soc/codecs/cs42l52.c index 8b427c977083..0bac6d5a4ac8 100644 --- a/sound/soc/codecs/cs42l52.c +++ b/sound/soc/codecs/cs42l52.c | |||
@@ -17,7 +17,7 @@ | |||
17 | #include <linux/kernel.h> | 17 | #include <linux/kernel.h> |
18 | #include <linux/init.h> | 18 | #include <linux/init.h> |
19 | #include <linux/delay.h> | 19 | #include <linux/delay.h> |
20 | #include <linux/gpio.h> | 20 | #include <linux/of_gpio.h> |
21 | #include <linux/pm.h> | 21 | #include <linux/pm.h> |
22 | #include <linux/i2c.h> | 22 | #include <linux/i2c.h> |
23 | #include <linux/input.h> | 23 | #include <linux/input.h> |
@@ -50,7 +50,7 @@ struct cs42l52_private { | |||
50 | u8 mclksel; | 50 | u8 mclksel; |
51 | u32 mclk; | 51 | u32 mclk; |
52 | u8 flags; | 52 | u8 flags; |
53 | #if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE) | 53 | #if IS_ENABLED(CONFIG_INPUT) |
54 | struct input_dev *beep; | 54 | struct input_dev *beep; |
55 | struct work_struct beep_work; | 55 | struct work_struct beep_work; |
56 | int beep_rate; | 56 | int beep_rate; |
@@ -233,7 +233,7 @@ static const struct soc_enum mic_bias_level_enum = | |||
233 | SOC_ENUM_SINGLE(CS42L52_IFACE_CTL2, 0, | 233 | SOC_ENUM_SINGLE(CS42L52_IFACE_CTL2, 0, |
234 | ARRAY_SIZE(mic_bias_level_text), mic_bias_level_text); | 234 | ARRAY_SIZE(mic_bias_level_text), mic_bias_level_text); |
235 | 235 | ||
236 | static const char * const cs42l52_mic_text[] = { "Single", "Differential" }; | 236 | static const char * const cs42l52_mic_text[] = { "MIC1", "MIC2" }; |
237 | 237 | ||
238 | static const struct soc_enum mica_enum = | 238 | static const struct soc_enum mica_enum = |
239 | SOC_ENUM_SINGLE(CS42L52_MICA_CTL, 5, | 239 | SOC_ENUM_SINGLE(CS42L52_MICA_CTL, 5, |
@@ -243,12 +243,6 @@ static const struct soc_enum micb_enum = | |||
243 | SOC_ENUM_SINGLE(CS42L52_MICB_CTL, 5, | 243 | SOC_ENUM_SINGLE(CS42L52_MICB_CTL, 5, |
244 | ARRAY_SIZE(cs42l52_mic_text), cs42l52_mic_text); | 244 | ARRAY_SIZE(cs42l52_mic_text), cs42l52_mic_text); |
245 | 245 | ||
246 | static const struct snd_kcontrol_new mica_mux = | ||
247 | SOC_DAPM_ENUM("Left Mic Input Capture Mux", mica_enum); | ||
248 | |||
249 | static const struct snd_kcontrol_new micb_mux = | ||
250 | SOC_DAPM_ENUM("Right Mic Input Capture Mux", micb_enum); | ||
251 | |||
252 | static const char * const digital_output_mux_text[] = {"ADC", "DSP"}; | 246 | static const char * const digital_output_mux_text[] = {"ADC", "DSP"}; |
253 | 247 | ||
254 | static const struct soc_enum digital_output_mux_enum = | 248 | static const struct soc_enum digital_output_mux_enum = |
@@ -531,6 +525,30 @@ static const struct snd_kcontrol_new cs42l52_snd_controls[] = { | |||
531 | 525 | ||
532 | }; | 526 | }; |
533 | 527 | ||
528 | static const struct snd_kcontrol_new cs42l52_mica_controls[] = { | ||
529 | SOC_ENUM("MICA Select", mica_enum), | ||
530 | }; | ||
531 | |||
532 | static const struct snd_kcontrol_new cs42l52_micb_controls[] = { | ||
533 | SOC_ENUM("MICB Select", micb_enum), | ||
534 | }; | ||
535 | |||
536 | static int cs42l52_add_mic_controls(struct snd_soc_codec *codec) | ||
537 | { | ||
538 | struct cs42l52_private *cs42l52 = snd_soc_codec_get_drvdata(codec); | ||
539 | struct cs42l52_platform_data *pdata = &cs42l52->pdata; | ||
540 | |||
541 | if (!pdata->mica_diff_cfg) | ||
542 | snd_soc_add_codec_controls(codec, cs42l52_mica_controls, | ||
543 | ARRAY_SIZE(cs42l52_mica_controls)); | ||
544 | |||
545 | if (!pdata->micb_diff_cfg) | ||
546 | snd_soc_add_codec_controls(codec, cs42l52_micb_controls, | ||
547 | ARRAY_SIZE(cs42l52_micb_controls)); | ||
548 | |||
549 | return 0; | ||
550 | } | ||
551 | |||
534 | static const struct snd_soc_dapm_widget cs42l52_dapm_widgets[] = { | 552 | static const struct snd_soc_dapm_widget cs42l52_dapm_widgets[] = { |
535 | 553 | ||
536 | SND_SOC_DAPM_INPUT("AIN1L"), | 554 | SND_SOC_DAPM_INPUT("AIN1L"), |
@@ -550,9 +568,6 @@ static const struct snd_soc_dapm_widget cs42l52_dapm_widgets[] = { | |||
550 | SND_SOC_DAPM_AIF_OUT("AIFOUTR", NULL, 0, | 568 | SND_SOC_DAPM_AIF_OUT("AIFOUTR", NULL, 0, |
551 | SND_SOC_NOPM, 0, 0), | 569 | SND_SOC_NOPM, 0, 0), |
552 | 570 | ||
553 | SND_SOC_DAPM_MUX("MICA Mux", SND_SOC_NOPM, 0, 0, &mica_mux), | ||
554 | SND_SOC_DAPM_MUX("MICB Mux", SND_SOC_NOPM, 0, 0, &micb_mux), | ||
555 | |||
556 | SND_SOC_DAPM_ADC("ADC Left", NULL, CS42L52_PWRCTL1, 1, 1), | 571 | SND_SOC_DAPM_ADC("ADC Left", NULL, CS42L52_PWRCTL1, 1, 1), |
557 | SND_SOC_DAPM_ADC("ADC Right", NULL, CS42L52_PWRCTL1, 2, 1), | 572 | SND_SOC_DAPM_ADC("ADC Right", NULL, CS42L52_PWRCTL1, 2, 1), |
558 | SND_SOC_DAPM_PGA("PGA Left", CS42L52_PWRCTL1, 3, 1, NULL, 0), | 573 | SND_SOC_DAPM_PGA("PGA Left", CS42L52_PWRCTL1, 3, 1, NULL, 0), |
@@ -953,7 +968,7 @@ static int cs42l52_resume(struct snd_soc_codec *codec) | |||
953 | return 0; | 968 | return 0; |
954 | } | 969 | } |
955 | 970 | ||
956 | #if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE) | 971 | #if IS_ENABLED(CONFIG_INPUT) |
957 | static int beep_rates[] = { | 972 | static int beep_rates[] = { |
958 | 261, 522, 585, 667, 706, 774, 889, 1000, | 973 | 261, 522, 585, 667, 706, 774, 889, 1000, |
959 | 1043, 1200, 1333, 1412, 1600, 1714, 2000, 2182 | 974 | 1043, 1200, 1333, 1412, 1600, 1714, 2000, 2182 |
@@ -1110,6 +1125,8 @@ static int cs42l52_probe(struct snd_soc_codec *codec) | |||
1110 | } | 1125 | } |
1111 | regcache_cache_only(cs42l52->regmap, true); | 1126 | regcache_cache_only(cs42l52->regmap, true); |
1112 | 1127 | ||
1128 | cs42l52_add_mic_controls(codec); | ||
1129 | |||
1113 | cs42l52_init_beep(codec); | 1130 | cs42l52_init_beep(codec); |
1114 | 1131 | ||
1115 | cs42l52_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 1132 | cs42l52_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
@@ -1176,6 +1193,7 @@ static int cs42l52_i2c_probe(struct i2c_client *i2c_client, | |||
1176 | int ret; | 1193 | int ret; |
1177 | unsigned int devid = 0; | 1194 | unsigned int devid = 0; |
1178 | unsigned int reg; | 1195 | unsigned int reg; |
1196 | u32 val32; | ||
1179 | 1197 | ||
1180 | cs42l52 = devm_kzalloc(&i2c_client->dev, sizeof(struct cs42l52_private), | 1198 | cs42l52 = devm_kzalloc(&i2c_client->dev, sizeof(struct cs42l52_private), |
1181 | GFP_KERNEL); | 1199 | GFP_KERNEL); |
@@ -1189,9 +1207,39 @@ static int cs42l52_i2c_probe(struct i2c_client *i2c_client, | |||
1189 | dev_err(&i2c_client->dev, "regmap_init() failed: %d\n", ret); | 1207 | dev_err(&i2c_client->dev, "regmap_init() failed: %d\n", ret); |
1190 | return ret; | 1208 | return ret; |
1191 | } | 1209 | } |
1192 | 1210 | if (pdata) { | |
1193 | if (pdata) | 1211 | cs42l52->pdata = *pdata; |
1212 | } else { | ||
1213 | pdata = devm_kzalloc(&i2c_client->dev, | ||
1214 | sizeof(struct cs42l52_platform_data), | ||
1215 | GFP_KERNEL); | ||
1216 | if (!pdata) { | ||
1217 | dev_err(&i2c_client->dev, "could not allocate pdata\n"); | ||
1218 | return -ENOMEM; | ||
1219 | } | ||
1220 | if (i2c_client->dev.of_node) { | ||
1221 | if (of_property_read_bool(i2c_client->dev.of_node, | ||
1222 | "cirrus,mica-differential-cfg")) | ||
1223 | pdata->mica_diff_cfg = true; | ||
1224 | |||
1225 | if (of_property_read_bool(i2c_client->dev.of_node, | ||
1226 | "cirrus,micb-differential-cfg")) | ||
1227 | pdata->micb_diff_cfg = true; | ||
1228 | |||
1229 | if (of_property_read_u32(i2c_client->dev.of_node, | ||
1230 | "cirrus,micbias-lvl", &val32) >= 0) | ||
1231 | pdata->micbias_lvl = val32; | ||
1232 | |||
1233 | if (of_property_read_u32(i2c_client->dev.of_node, | ||
1234 | "cirrus,chgfreq-divisor", &val32) >= 0) | ||
1235 | pdata->chgfreq = val32; | ||
1236 | |||
1237 | pdata->reset_gpio = | ||
1238 | of_get_named_gpio(i2c_client->dev.of_node, | ||
1239 | "cirrus,reset-gpio", 0); | ||
1240 | } | ||
1194 | cs42l52->pdata = *pdata; | 1241 | cs42l52->pdata = *pdata; |
1242 | } | ||
1195 | 1243 | ||
1196 | if (cs42l52->pdata.reset_gpio) { | 1244 | if (cs42l52->pdata.reset_gpio) { |
1197 | ret = gpio_request_one(cs42l52->pdata.reset_gpio, | 1245 | ret = gpio_request_one(cs42l52->pdata.reset_gpio, |
@@ -1227,29 +1275,18 @@ static int cs42l52_i2c_probe(struct i2c_client *i2c_client, | |||
1227 | reg & 0xFF); | 1275 | reg & 0xFF); |
1228 | 1276 | ||
1229 | /* Set Platform Data */ | 1277 | /* Set Platform Data */ |
1230 | if (cs42l52->pdata.mica_cfg) | 1278 | if (cs42l52->pdata.mica_diff_cfg) |
1231 | regmap_update_bits(cs42l52->regmap, CS42L52_MICA_CTL, | 1279 | regmap_update_bits(cs42l52->regmap, CS42L52_MICA_CTL, |
1232 | CS42L52_MIC_CTL_TYPE_MASK, | 1280 | CS42L52_MIC_CTL_TYPE_MASK, |
1233 | cs42l52->pdata.mica_cfg << | 1281 | cs42l52->pdata.mica_diff_cfg << |
1234 | CS42L52_MIC_CTL_TYPE_SHIFT); | 1282 | CS42L52_MIC_CTL_TYPE_SHIFT); |
1235 | 1283 | ||
1236 | if (cs42l52->pdata.micb_cfg) | 1284 | if (cs42l52->pdata.micb_diff_cfg) |
1237 | regmap_update_bits(cs42l52->regmap, CS42L52_MICB_CTL, | 1285 | regmap_update_bits(cs42l52->regmap, CS42L52_MICB_CTL, |
1238 | CS42L52_MIC_CTL_TYPE_MASK, | 1286 | CS42L52_MIC_CTL_TYPE_MASK, |
1239 | cs42l52->pdata.micb_cfg << | 1287 | cs42l52->pdata.micb_diff_cfg << |
1240 | CS42L52_MIC_CTL_TYPE_SHIFT); | 1288 | CS42L52_MIC_CTL_TYPE_SHIFT); |
1241 | 1289 | ||
1242 | if (cs42l52->pdata.mica_sel) | ||
1243 | regmap_update_bits(cs42l52->regmap, CS42L52_MICA_CTL, | ||
1244 | CS42L52_MIC_CTL_MIC_SEL_MASK, | ||
1245 | cs42l52->pdata.mica_sel << | ||
1246 | CS42L52_MIC_CTL_MIC_SEL_SHIFT); | ||
1247 | if (cs42l52->pdata.micb_sel) | ||
1248 | regmap_update_bits(cs42l52->regmap, CS42L52_MICB_CTL, | ||
1249 | CS42L52_MIC_CTL_MIC_SEL_MASK, | ||
1250 | cs42l52->pdata.micb_sel << | ||
1251 | CS42L52_MIC_CTL_MIC_SEL_SHIFT); | ||
1252 | |||
1253 | if (cs42l52->pdata.chgfreq) | 1290 | if (cs42l52->pdata.chgfreq) |
1254 | regmap_update_bits(cs42l52->regmap, CS42L52_CHARGE_PUMP, | 1291 | regmap_update_bits(cs42l52->regmap, CS42L52_CHARGE_PUMP, |
1255 | CS42L52_CHARGE_PUMP_MASK, | 1292 | CS42L52_CHARGE_PUMP_MASK, |
@@ -1274,6 +1311,13 @@ static int cs42l52_i2c_remove(struct i2c_client *client) | |||
1274 | return 0; | 1311 | return 0; |
1275 | } | 1312 | } |
1276 | 1313 | ||
1314 | static const struct of_device_id cs42l52_of_match[] = { | ||
1315 | { .compatible = "cirrus,cs42l52", }, | ||
1316 | {}, | ||
1317 | }; | ||
1318 | MODULE_DEVICE_TABLE(of, cs42l52_of_match); | ||
1319 | |||
1320 | |||
1277 | static const struct i2c_device_id cs42l52_id[] = { | 1321 | static const struct i2c_device_id cs42l52_id[] = { |
1278 | { "cs42l52", 0 }, | 1322 | { "cs42l52", 0 }, |
1279 | { } | 1323 | { } |
@@ -1284,6 +1328,7 @@ static struct i2c_driver cs42l52_i2c_driver = { | |||
1284 | .driver = { | 1328 | .driver = { |
1285 | .name = "cs42l52", | 1329 | .name = "cs42l52", |
1286 | .owner = THIS_MODULE, | 1330 | .owner = THIS_MODULE, |
1331 | .of_match_table = cs42l52_of_match, | ||
1287 | }, | 1332 | }, |
1288 | .id_table = cs42l52_id, | 1333 | .id_table = cs42l52_id, |
1289 | .probe = cs42l52_i2c_probe, | 1334 | .probe = cs42l52_i2c_probe, |