diff options
Diffstat (limited to 'sound/soc/codecs/cs42l73.c')
-rw-r--r-- | sound/soc/codecs/cs42l73.c | 51 |
1 files changed, 33 insertions, 18 deletions
diff --git a/sound/soc/codecs/cs42l73.c b/sound/soc/codecs/cs42l73.c index 3b20c86cdb01..db9d39604d68 100644 --- a/sound/soc/codecs/cs42l73.c +++ b/sound/soc/codecs/cs42l73.c | |||
@@ -17,6 +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/pm.h> | 21 | #include <linux/pm.h> |
21 | #include <linux/i2c.h> | 22 | #include <linux/i2c.h> |
22 | #include <linux/regmap.h> | 23 | #include <linux/regmap.h> |
@@ -28,6 +29,7 @@ | |||
28 | #include <sound/soc-dapm.h> | 29 | #include <sound/soc-dapm.h> |
29 | #include <sound/initval.h> | 30 | #include <sound/initval.h> |
30 | #include <sound/tlv.h> | 31 | #include <sound/tlv.h> |
32 | #include <sound/cs42l73.h> | ||
31 | #include "cs42l73.h" | 33 | #include "cs42l73.h" |
32 | 34 | ||
33 | struct sp_config { | 35 | struct sp_config { |
@@ -35,6 +37,7 @@ struct sp_config { | |||
35 | u32 srate; | 37 | u32 srate; |
36 | }; | 38 | }; |
37 | struct cs42l73_private { | 39 | struct cs42l73_private { |
40 | struct cs42l73_platform_data pdata; | ||
38 | struct sp_config config[3]; | 41 | struct sp_config config[3]; |
39 | struct regmap *regmap; | 42 | struct regmap *regmap; |
40 | u32 sysclk; | 43 | u32 sysclk; |
@@ -310,15 +313,6 @@ static const struct soc_enum ng_delay_enum = | |||
310 | SOC_ENUM_SINGLE(CS42L73_NGCAB, 0, | 313 | SOC_ENUM_SINGLE(CS42L73_NGCAB, 0, |
311 | ARRAY_SIZE(cs42l73_ng_delay_text), cs42l73_ng_delay_text); | 314 | ARRAY_SIZE(cs42l73_ng_delay_text), cs42l73_ng_delay_text); |
312 | 315 | ||
313 | static const char * const charge_pump_freq_text[] = { | ||
314 | "0", "1", "2", "3", "4", | ||
315 | "5", "6", "7", "8", "9", | ||
316 | "10", "11", "12", "13", "14", "15" }; | ||
317 | |||
318 | static const struct soc_enum charge_pump_enum = | ||
319 | SOC_ENUM_SINGLE(CS42L73_CPFCHC, 4, | ||
320 | ARRAY_SIZE(charge_pump_freq_text), charge_pump_freq_text); | ||
321 | |||
322 | static const char * const cs42l73_mono_mix_texts[] = { | 316 | static const char * const cs42l73_mono_mix_texts[] = { |
323 | "Left", "Right", "Mono Mix"}; | 317 | "Left", "Right", "Mono Mix"}; |
324 | 318 | ||
@@ -511,8 +505,6 @@ static const struct snd_kcontrol_new cs42l73_snd_controls[] = { | |||
511 | SOC_SINGLE("NG Threshold", CS42L73_NGCAB, 2, 7, 0), | 505 | SOC_SINGLE("NG Threshold", CS42L73_NGCAB, 2, 7, 0), |
512 | SOC_ENUM("NG Delay", ng_delay_enum), | 506 | SOC_ENUM("NG Delay", ng_delay_enum), |
513 | 507 | ||
514 | SOC_ENUM("Charge Pump Frequency", charge_pump_enum), | ||
515 | |||
516 | SOC_DOUBLE_R_TLV("XSP-IP Volume", | 508 | SOC_DOUBLE_R_TLV("XSP-IP Volume", |
517 | CS42L73_XSPAIPAA, CS42L73_XSPBIPBA, 0, 0x3F, 1, | 509 | CS42L73_XSPAIPAA, CS42L73_XSPBIPBA, 0, 0x3F, 1, |
518 | attn_tlv), | 510 | attn_tlv), |
@@ -1367,11 +1359,16 @@ static int cs42l73_probe(struct snd_soc_codec *codec) | |||
1367 | return ret; | 1359 | return ret; |
1368 | } | 1360 | } |
1369 | 1361 | ||
1370 | regcache_cache_only(cs42l73->regmap, true); | ||
1371 | |||
1372 | cs42l73_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 1362 | cs42l73_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
1373 | 1363 | ||
1374 | cs42l73->mclksel = CS42L73_CLKID_MCLK1; /* MCLK1 as master clk */ | 1364 | /* Set Charge Pump Frequency */ |
1365 | if (cs42l73->pdata.chgfreq) | ||
1366 | snd_soc_update_bits(codec, CS42L73_CPFCHC, | ||
1367 | CS42L73_CHARGEPUMP_MASK, | ||
1368 | cs42l73->pdata.chgfreq << 4); | ||
1369 | |||
1370 | /* MCLK1 as master clk */ | ||
1371 | cs42l73->mclksel = CS42L73_CLKID_MCLK1; | ||
1375 | cs42l73->mclk = 0; | 1372 | cs42l73->mclk = 0; |
1376 | 1373 | ||
1377 | return ret; | 1374 | return ret; |
@@ -1415,6 +1412,7 @@ static int cs42l73_i2c_probe(struct i2c_client *i2c_client, | |||
1415 | const struct i2c_device_id *id) | 1412 | const struct i2c_device_id *id) |
1416 | { | 1413 | { |
1417 | struct cs42l73_private *cs42l73; | 1414 | struct cs42l73_private *cs42l73; |
1415 | struct cs42l73_platform_data *pdata = dev_get_platdata(&i2c_client->dev); | ||
1418 | int ret; | 1416 | int ret; |
1419 | unsigned int devid = 0; | 1417 | unsigned int devid = 0; |
1420 | unsigned int reg; | 1418 | unsigned int reg; |
@@ -1426,14 +1424,32 @@ static int cs42l73_i2c_probe(struct i2c_client *i2c_client, | |||
1426 | return -ENOMEM; | 1424 | return -ENOMEM; |
1427 | } | 1425 | } |
1428 | 1426 | ||
1429 | i2c_set_clientdata(i2c_client, cs42l73); | ||
1430 | |||
1431 | cs42l73->regmap = devm_regmap_init_i2c(i2c_client, &cs42l73_regmap); | 1427 | cs42l73->regmap = devm_regmap_init_i2c(i2c_client, &cs42l73_regmap); |
1432 | if (IS_ERR(cs42l73->regmap)) { | 1428 | if (IS_ERR(cs42l73->regmap)) { |
1433 | ret = PTR_ERR(cs42l73->regmap); | 1429 | ret = PTR_ERR(cs42l73->regmap); |
1434 | dev_err(&i2c_client->dev, "regmap_init() failed: %d\n", ret); | 1430 | dev_err(&i2c_client->dev, "regmap_init() failed: %d\n", ret); |
1435 | return ret; | 1431 | return ret; |
1436 | } | 1432 | } |
1433 | |||
1434 | if (pdata) | ||
1435 | cs42l73->pdata = *pdata; | ||
1436 | |||
1437 | i2c_set_clientdata(i2c_client, cs42l73); | ||
1438 | |||
1439 | if (cs42l73->pdata.reset_gpio) { | ||
1440 | ret = gpio_request_one(cs42l73->pdata.reset_gpio, | ||
1441 | GPIOF_OUT_INIT_HIGH, "CS42L73 /RST"); | ||
1442 | if (ret < 0) { | ||
1443 | dev_err(&i2c_client->dev, "Failed to request /RST %d: %d\n", | ||
1444 | cs42l73->pdata.reset_gpio, ret); | ||
1445 | return ret; | ||
1446 | } | ||
1447 | gpio_set_value_cansleep(cs42l73->pdata.reset_gpio, 0); | ||
1448 | gpio_set_value_cansleep(cs42l73->pdata.reset_gpio, 1); | ||
1449 | } | ||
1450 | |||
1451 | regcache_cache_bypass(cs42l73->regmap, true); | ||
1452 | |||
1437 | /* initialize codec */ | 1453 | /* initialize codec */ |
1438 | ret = regmap_read(cs42l73->regmap, CS42L73_DEVID_AB, ®); | 1454 | ret = regmap_read(cs42l73->regmap, CS42L73_DEVID_AB, ®); |
1439 | devid = (reg & 0xFF) << 12; | 1455 | devid = (reg & 0xFF) << 12; |
@@ -1444,7 +1460,6 @@ static int cs42l73_i2c_probe(struct i2c_client *i2c_client, | |||
1444 | ret = regmap_read(cs42l73->regmap, CS42L73_DEVID_E, ®); | 1460 | ret = regmap_read(cs42l73->regmap, CS42L73_DEVID_E, ®); |
1445 | devid |= (reg & 0xF0) >> 4; | 1461 | devid |= (reg & 0xF0) >> 4; |
1446 | 1462 | ||
1447 | |||
1448 | if (devid != CS42L73_DEVID) { | 1463 | if (devid != CS42L73_DEVID) { |
1449 | ret = -ENODEV; | 1464 | ret = -ENODEV; |
1450 | dev_err(&i2c_client->dev, | 1465 | dev_err(&i2c_client->dev, |
@@ -1462,7 +1477,7 @@ static int cs42l73_i2c_probe(struct i2c_client *i2c_client, | |||
1462 | dev_info(&i2c_client->dev, | 1477 | dev_info(&i2c_client->dev, |
1463 | "Cirrus Logic CS42L73, Revision: %02X\n", reg & 0xFF); | 1478 | "Cirrus Logic CS42L73, Revision: %02X\n", reg & 0xFF); |
1464 | 1479 | ||
1465 | regcache_cache_only(cs42l73->regmap, true); | 1480 | regcache_cache_bypass(cs42l73->regmap, false); |
1466 | 1481 | ||
1467 | ret = snd_soc_register_codec(&i2c_client->dev, | 1482 | ret = snd_soc_register_codec(&i2c_client->dev, |
1468 | &soc_codec_dev_cs42l73, cs42l73_dai, | 1483 | &soc_codec_dev_cs42l73, cs42l73_dai, |