diff options
author | Takashi Iwai <tiwai@suse.de> | 2010-05-20 06:00:43 -0400 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2010-05-20 06:00:43 -0400 |
commit | d71f4cece4bd97d05592836202fc04ff2e7817e3 (patch) | |
tree | 6c877c7a938758b1323d9c97d46b9c536e618c69 /sound/soc/codecs/tpa6130a2.c | |
parent | 19008bdacb9f7841166ebafe0aef361ee582ffbf (diff) | |
parent | ad8332c1302bcb4f80d593fd3eb477be9d7f5604 (diff) |
Merge branch 'topic/asoc' into for-linus
Conflicts:
sound/soc/codecs/ad1938.c
Diffstat (limited to 'sound/soc/codecs/tpa6130a2.c')
-rw-r--r-- | sound/soc/codecs/tpa6130a2.c | 103 |
1 files changed, 57 insertions, 46 deletions
diff --git a/sound/soc/codecs/tpa6130a2.c b/sound/soc/codecs/tpa6130a2.c index 569ad8758a84..99b70e5978a2 100644 --- a/sound/soc/codecs/tpa6130a2.c +++ b/sound/soc/codecs/tpa6130a2.c | |||
@@ -36,24 +36,14 @@ | |||
36 | 36 | ||
37 | static struct i2c_client *tpa6130a2_client; | 37 | static struct i2c_client *tpa6130a2_client; |
38 | 38 | ||
39 | #define TPA6130A2_NUM_SUPPLIES 2 | ||
40 | static const char *tpa6130a2_supply_names[TPA6130A2_NUM_SUPPLIES] = { | ||
41 | "CPVSS", | ||
42 | "Vdd", | ||
43 | }; | ||
44 | |||
45 | static const char *tpa6140a2_supply_names[TPA6130A2_NUM_SUPPLIES] = { | ||
46 | "HPVdd", | ||
47 | "AVdd", | ||
48 | }; | ||
49 | |||
50 | /* This struct is used to save the context */ | 39 | /* This struct is used to save the context */ |
51 | struct tpa6130a2_data { | 40 | struct tpa6130a2_data { |
52 | struct mutex mutex; | 41 | struct mutex mutex; |
53 | unsigned char regs[TPA6130A2_CACHEREGNUM]; | 42 | unsigned char regs[TPA6130A2_CACHEREGNUM]; |
54 | struct regulator_bulk_data supplies[TPA6130A2_NUM_SUPPLIES]; | 43 | struct regulator *supply; |
55 | int power_gpio; | 44 | int power_gpio; |
56 | unsigned char power_state; | 45 | unsigned char power_state; |
46 | enum tpa_model id; | ||
57 | }; | 47 | }; |
58 | 48 | ||
59 | static int tpa6130a2_i2c_read(int reg) | 49 | static int tpa6130a2_i2c_read(int reg) |
@@ -135,11 +125,10 @@ static int tpa6130a2_power(int power) | |||
135 | if (data->power_gpio >= 0) | 125 | if (data->power_gpio >= 0) |
136 | gpio_set_value(data->power_gpio, 1); | 126 | gpio_set_value(data->power_gpio, 1); |
137 | 127 | ||
138 | ret = regulator_bulk_enable(ARRAY_SIZE(data->supplies), | 128 | ret = regulator_enable(data->supply); |
139 | data->supplies); | ||
140 | if (ret != 0) { | 129 | if (ret != 0) { |
141 | dev_err(&tpa6130a2_client->dev, | 130 | dev_err(&tpa6130a2_client->dev, |
142 | "Failed to enable supplies: %d\n", ret); | 131 | "Failed to enable supply: %d\n", ret); |
143 | goto exit; | 132 | goto exit; |
144 | } | 133 | } |
145 | 134 | ||
@@ -160,11 +149,10 @@ static int tpa6130a2_power(int power) | |||
160 | if (data->power_gpio >= 0) | 149 | if (data->power_gpio >= 0) |
161 | gpio_set_value(data->power_gpio, 0); | 150 | gpio_set_value(data->power_gpio, 0); |
162 | 151 | ||
163 | ret = regulator_bulk_disable(ARRAY_SIZE(data->supplies), | 152 | ret = regulator_disable(data->supply); |
164 | data->supplies); | ||
165 | if (ret != 0) { | 153 | if (ret != 0) { |
166 | dev_err(&tpa6130a2_client->dev, | 154 | dev_err(&tpa6130a2_client->dev, |
167 | "Failed to disable supplies: %d\n", ret); | 155 | "Failed to disable supply: %d\n", ret); |
168 | goto exit; | 156 | goto exit; |
169 | } | 157 | } |
170 | 158 | ||
@@ -176,7 +164,7 @@ exit: | |||
176 | return ret; | 164 | return ret; |
177 | } | 165 | } |
178 | 166 | ||
179 | static int tpa6130a2_get_reg(struct snd_kcontrol *kcontrol, | 167 | static int tpa6130a2_get_volsw(struct snd_kcontrol *kcontrol, |
180 | struct snd_ctl_elem_value *ucontrol) | 168 | struct snd_ctl_elem_value *ucontrol) |
181 | { | 169 | { |
182 | struct soc_mixer_control *mc = | 170 | struct soc_mixer_control *mc = |
@@ -184,7 +172,8 @@ static int tpa6130a2_get_reg(struct snd_kcontrol *kcontrol, | |||
184 | struct tpa6130a2_data *data; | 172 | struct tpa6130a2_data *data; |
185 | unsigned int reg = mc->reg; | 173 | unsigned int reg = mc->reg; |
186 | unsigned int shift = mc->shift; | 174 | unsigned int shift = mc->shift; |
187 | unsigned int mask = mc->max; | 175 | int max = mc->max; |
176 | unsigned int mask = (1 << fls(max)) - 1; | ||
188 | unsigned int invert = mc->invert; | 177 | unsigned int invert = mc->invert; |
189 | 178 | ||
190 | BUG_ON(tpa6130a2_client == NULL); | 179 | BUG_ON(tpa6130a2_client == NULL); |
@@ -197,13 +186,13 @@ static int tpa6130a2_get_reg(struct snd_kcontrol *kcontrol, | |||
197 | 186 | ||
198 | if (invert) | 187 | if (invert) |
199 | ucontrol->value.integer.value[0] = | 188 | ucontrol->value.integer.value[0] = |
200 | mask - ucontrol->value.integer.value[0]; | 189 | max - ucontrol->value.integer.value[0]; |
201 | 190 | ||
202 | mutex_unlock(&data->mutex); | 191 | mutex_unlock(&data->mutex); |
203 | return 0; | 192 | return 0; |
204 | } | 193 | } |
205 | 194 | ||
206 | static int tpa6130a2_set_reg(struct snd_kcontrol *kcontrol, | 195 | static int tpa6130a2_put_volsw(struct snd_kcontrol *kcontrol, |
207 | struct snd_ctl_elem_value *ucontrol) | 196 | struct snd_ctl_elem_value *ucontrol) |
208 | { | 197 | { |
209 | struct soc_mixer_control *mc = | 198 | struct soc_mixer_control *mc = |
@@ -211,7 +200,8 @@ static int tpa6130a2_set_reg(struct snd_kcontrol *kcontrol, | |||
211 | struct tpa6130a2_data *data; | 200 | struct tpa6130a2_data *data; |
212 | unsigned int reg = mc->reg; | 201 | unsigned int reg = mc->reg; |
213 | unsigned int shift = mc->shift; | 202 | unsigned int shift = mc->shift; |
214 | unsigned int mask = mc->max; | 203 | int max = mc->max; |
204 | unsigned int mask = (1 << fls(max)) - 1; | ||
215 | unsigned int invert = mc->invert; | 205 | unsigned int invert = mc->invert; |
216 | unsigned int val = (ucontrol->value.integer.value[0] & mask); | 206 | unsigned int val = (ucontrol->value.integer.value[0] & mask); |
217 | unsigned int val_reg; | 207 | unsigned int val_reg; |
@@ -220,7 +210,7 @@ static int tpa6130a2_set_reg(struct snd_kcontrol *kcontrol, | |||
220 | data = i2c_get_clientdata(tpa6130a2_client); | 210 | data = i2c_get_clientdata(tpa6130a2_client); |
221 | 211 | ||
222 | if (invert) | 212 | if (invert) |
223 | val = mask - val; | 213 | val = max - val; |
224 | 214 | ||
225 | mutex_lock(&data->mutex); | 215 | mutex_lock(&data->mutex); |
226 | 216 | ||
@@ -260,10 +250,24 @@ static const unsigned int tpa6130_tlv[] = { | |||
260 | static const struct snd_kcontrol_new tpa6130a2_controls[] = { | 250 | static const struct snd_kcontrol_new tpa6130a2_controls[] = { |
261 | SOC_SINGLE_EXT_TLV("TPA6130A2 Headphone Playback Volume", | 251 | SOC_SINGLE_EXT_TLV("TPA6130A2 Headphone Playback Volume", |
262 | TPA6130A2_REG_VOL_MUTE, 0, 0x3f, 0, | 252 | TPA6130A2_REG_VOL_MUTE, 0, 0x3f, 0, |
263 | tpa6130a2_get_reg, tpa6130a2_set_reg, | 253 | tpa6130a2_get_volsw, tpa6130a2_put_volsw, |
264 | tpa6130_tlv), | 254 | tpa6130_tlv), |
265 | }; | 255 | }; |
266 | 256 | ||
257 | static const unsigned int tpa6140_tlv[] = { | ||
258 | TLV_DB_RANGE_HEAD(3), | ||
259 | 0, 8, TLV_DB_SCALE_ITEM(-5900, 400, 0), | ||
260 | 9, 16, TLV_DB_SCALE_ITEM(-2500, 200, 0), | ||
261 | 17, 31, TLV_DB_SCALE_ITEM(-1000, 100, 0), | ||
262 | }; | ||
263 | |||
264 | static const struct snd_kcontrol_new tpa6140a2_controls[] = { | ||
265 | SOC_SINGLE_EXT_TLV("TPA6140A2 Headphone Playback Volume", | ||
266 | TPA6130A2_REG_VOL_MUTE, 1, 0x1f, 0, | ||
267 | tpa6130a2_get_volsw, tpa6130a2_put_volsw, | ||
268 | tpa6140_tlv), | ||
269 | }; | ||
270 | |||
267 | /* | 271 | /* |
268 | * Enable or disable channel (left or right) | 272 | * Enable or disable channel (left or right) |
269 | * The bit number for mute and amplifier are the same per channel: | 273 | * The bit number for mute and amplifier are the same per channel: |
@@ -355,8 +359,8 @@ static const struct snd_soc_dapm_widget tpa6130a2_dapm_widgets[] = { | |||
355 | 0, 0, tpa6130a2_supply_event, | 359 | 0, 0, tpa6130a2_supply_event, |
356 | SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD), | 360 | SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD), |
357 | /* Outputs */ | 361 | /* Outputs */ |
358 | SND_SOC_DAPM_HP("TPA6130A2 Headphone Left", NULL), | 362 | SND_SOC_DAPM_OUTPUT("TPA6130A2 Headphone Left"), |
359 | SND_SOC_DAPM_HP("TPA6130A2 Headphone Right", NULL), | 363 | SND_SOC_DAPM_OUTPUT("TPA6130A2 Headphone Right"), |
360 | }; | 364 | }; |
361 | 365 | ||
362 | static const struct snd_soc_dapm_route audio_map[] = { | 366 | static const struct snd_soc_dapm_route audio_map[] = { |
@@ -369,13 +373,22 @@ static const struct snd_soc_dapm_route audio_map[] = { | |||
369 | 373 | ||
370 | int tpa6130a2_add_controls(struct snd_soc_codec *codec) | 374 | int tpa6130a2_add_controls(struct snd_soc_codec *codec) |
371 | { | 375 | { |
376 | struct tpa6130a2_data *data; | ||
377 | |||
378 | BUG_ON(tpa6130a2_client == NULL); | ||
379 | data = i2c_get_clientdata(tpa6130a2_client); | ||
380 | |||
372 | snd_soc_dapm_new_controls(codec, tpa6130a2_dapm_widgets, | 381 | snd_soc_dapm_new_controls(codec, tpa6130a2_dapm_widgets, |
373 | ARRAY_SIZE(tpa6130a2_dapm_widgets)); | 382 | ARRAY_SIZE(tpa6130a2_dapm_widgets)); |
374 | 383 | ||
375 | snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); | 384 | snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); |
376 | 385 | ||
377 | return snd_soc_add_controls(codec, tpa6130a2_controls, | 386 | if (data->id == TPA6140A2) |
378 | ARRAY_SIZE(tpa6130a2_controls)); | 387 | return snd_soc_add_controls(codec, tpa6140a2_controls, |
388 | ARRAY_SIZE(tpa6140a2_controls)); | ||
389 | else | ||
390 | return snd_soc_add_controls(codec, tpa6130a2_controls, | ||
391 | ARRAY_SIZE(tpa6130a2_controls)); | ||
379 | 392 | ||
380 | } | 393 | } |
381 | EXPORT_SYMBOL_GPL(tpa6130a2_add_controls); | 394 | EXPORT_SYMBOL_GPL(tpa6130a2_add_controls); |
@@ -386,7 +399,8 @@ static int __devinit tpa6130a2_probe(struct i2c_client *client, | |||
386 | struct device *dev; | 399 | struct device *dev; |
387 | struct tpa6130a2_data *data; | 400 | struct tpa6130a2_data *data; |
388 | struct tpa6130a2_platform_data *pdata; | 401 | struct tpa6130a2_platform_data *pdata; |
389 | int i, ret; | 402 | const char *regulator; |
403 | int ret; | ||
390 | 404 | ||
391 | dev = &client->dev; | 405 | dev = &client->dev; |
392 | 406 | ||
@@ -408,6 +422,7 @@ static int __devinit tpa6130a2_probe(struct i2c_client *client, | |||
408 | 422 | ||
409 | pdata = client->dev.platform_data; | 423 | pdata = client->dev.platform_data; |
410 | data->power_gpio = pdata->power_gpio; | 424 | data->power_gpio = pdata->power_gpio; |
425 | data->id = pdata->id; | ||
411 | 426 | ||
412 | mutex_init(&data->mutex); | 427 | mutex_init(&data->mutex); |
413 | 428 | ||
@@ -426,26 +441,22 @@ static int __devinit tpa6130a2_probe(struct i2c_client *client, | |||
426 | gpio_direction_output(data->power_gpio, 0); | 441 | gpio_direction_output(data->power_gpio, 0); |
427 | } | 442 | } |
428 | 443 | ||
429 | switch (pdata->id) { | 444 | switch (data->id) { |
445 | default: | ||
446 | dev_warn(dev, "Unknown TPA model (%d). Assuming 6130A2\n", | ||
447 | pdata->id); | ||
430 | case TPA6130A2: | 448 | case TPA6130A2: |
431 | for (i = 0; i < ARRAY_SIZE(data->supplies); i++) | 449 | regulator = "Vdd"; |
432 | data->supplies[i].supply = tpa6130a2_supply_names[i]; | ||
433 | break; | 450 | break; |
434 | case TPA6140A2: | 451 | case TPA6140A2: |
435 | for (i = 0; i < ARRAY_SIZE(data->supplies); i++) | 452 | regulator = "AVdd"; |
436 | data->supplies[i].supply = tpa6140a2_supply_names[i];; | ||
437 | break; | 453 | break; |
438 | default: | ||
439 | dev_warn(dev, "Unknown TPA model (%d). Assuming 6130A2\n", | ||
440 | pdata->id); | ||
441 | for (i = 0; i < ARRAY_SIZE(data->supplies); i++) | ||
442 | data->supplies[i].supply = tpa6130a2_supply_names[i]; | ||
443 | } | 454 | } |
444 | 455 | ||
445 | ret = regulator_bulk_get(dev, ARRAY_SIZE(data->supplies), | 456 | data->supply = regulator_get(dev, regulator); |
446 | data->supplies); | 457 | if (IS_ERR(data->supply)) { |
447 | if (ret != 0) { | 458 | ret = PTR_ERR(data->supply); |
448 | dev_err(dev, "Failed to request supplies: %d\n", ret); | 459 | dev_err(dev, "Failed to request supply: %d\n", ret); |
449 | goto err_regulator; | 460 | goto err_regulator; |
450 | } | 461 | } |
451 | 462 | ||
@@ -468,7 +479,7 @@ static int __devinit tpa6130a2_probe(struct i2c_client *client, | |||
468 | return 0; | 479 | return 0; |
469 | 480 | ||
470 | err_power: | 481 | err_power: |
471 | regulator_bulk_free(ARRAY_SIZE(data->supplies), data->supplies); | 482 | regulator_put(data->supply); |
472 | err_regulator: | 483 | err_regulator: |
473 | if (data->power_gpio >= 0) | 484 | if (data->power_gpio >= 0) |
474 | gpio_free(data->power_gpio); | 485 | gpio_free(data->power_gpio); |
@@ -489,7 +500,7 @@ static int __devexit tpa6130a2_remove(struct i2c_client *client) | |||
489 | if (data->power_gpio >= 0) | 500 | if (data->power_gpio >= 0) |
490 | gpio_free(data->power_gpio); | 501 | gpio_free(data->power_gpio); |
491 | 502 | ||
492 | regulator_bulk_free(ARRAY_SIZE(data->supplies), data->supplies); | 503 | regulator_put(data->supply); |
493 | 504 | ||
494 | kfree(data); | 505 | kfree(data); |
495 | tpa6130a2_client = NULL; | 506 | tpa6130a2_client = NULL; |