diff options
| -rw-r--r-- | include/sound/cs42l73.h | 22 | ||||
| -rw-r--r-- | sound/soc/codecs/cs42l73.c | 51 | ||||
| -rw-r--r-- | sound/soc/codecs/cs42l73.h | 1 |
3 files changed, 56 insertions, 18 deletions
diff --git a/include/sound/cs42l73.h b/include/sound/cs42l73.h new file mode 100644 index 000000000000..f354be4cdc9e --- /dev/null +++ b/include/sound/cs42l73.h | |||
| @@ -0,0 +1,22 @@ | |||
| 1 | /* | ||
| 2 | * linux/sound/cs42l73.h -- Platform data for CS42L73 | ||
| 3 | * | ||
| 4 | * Copyright (c) 2012 Cirrus Logic Inc. | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify | ||
| 7 | * it under the terms of the GNU General Public License version 2 as | ||
| 8 | * published by the Free Software Foundation. | ||
| 9 | */ | ||
| 10 | |||
| 11 | #ifndef __CS42L73_H | ||
| 12 | #define __CS42L73_H | ||
| 13 | |||
| 14 | struct cs42l73_platform_data { | ||
| 15 | /* RST GPIO */ | ||
| 16 | unsigned int reset_gpio; | ||
| 17 | unsigned int chgfreq; | ||
| 18 | int jack_detection; | ||
| 19 | unsigned int mclk_freq; | ||
| 20 | }; | ||
| 21 | |||
| 22 | #endif /* __CS42L73_H */ | ||
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, |
diff --git a/sound/soc/codecs/cs42l73.h b/sound/soc/codecs/cs42l73.h index f30a4c4d62e6..4f83d39496a8 100644 --- a/sound/soc/codecs/cs42l73.h +++ b/sound/soc/codecs/cs42l73.h | |||
| @@ -159,6 +159,7 @@ | |||
| 159 | #define THMOVLD_115C 2 | 159 | #define THMOVLD_115C 2 |
| 160 | #define THMOVLD_098C 3 | 160 | #define THMOVLD_098C 3 |
| 161 | 161 | ||
| 162 | #define CS42L73_CHARGEPUMP_MASK (0xF0) | ||
| 162 | 163 | ||
| 163 | /* CS42L73_ASPC, CS42L73_XSPC, CS42L73_VSPC */ | 164 | /* CS42L73_ASPC, CS42L73_XSPC, CS42L73_VSPC */ |
| 164 | #define SP_3ST (1 << 7) | 165 | #define SP_3ST (1 << 7) |
