diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-10-28 17:25:01 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-10-28 17:25:01 -0400 |
commit | 68d99b2c8efcb6ed3807a55569300c53b5f88be5 (patch) | |
tree | f189c8f2132d3668a2f0e503f5c3f8695b26a1c8 /drivers/mfd | |
parent | 0e59e7e7feb5a12938fbf9135147eeda3238c6c4 (diff) | |
parent | 8128c9f21509f9a8b6da94ac432d845dda458406 (diff) |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound: (549 commits)
ALSA: hda - Fix ADC input-amp handling for Cx20549 codec
ALSA: hda - Keep EAPD turned on for old Conexant chips
ALSA: hda/realtek - Fix missing volume controls with ALC260
ASoC: wm8940: Properly set codec->dapm.bias_level
ALSA: hda - Fix pin-config for ASUS W90V
ALSA: hda - Fix surround/CLFE headphone and speaker pins order
ALSA: hda - Fix typo
ALSA: Update the sound git tree URL
ALSA: HDA: Add new revision for ALC662
ASoC: max98095: Convert codec->hw_write to snd_soc_write
ASoC: keep pointer to resource so it can be freed
ASoC: sgtl5000: Fix wrong mask in some snd_soc_update_bits calls
ASoC: wm8996: Fix wrong mask for setting WM8996_AIF_CLOCKING_2
ASoC: da7210: Add support for line out and DAC
ASoC: da7210: Add support for DAPM
ALSA: hda/realtek - Fix DAC assignments of multiple speakers
ASoC: Use SGTL5000_LINREG_VDDD_MASK instead of hardcoded mask value
ASoC: Set sgtl5000->ldo in ldo_regulator_register
ASoC: wm8996: Use SND_SOC_DAPM_AIF_OUT for AIF2 Capture
ASoC: wm8994: Use SND_SOC_DAPM_AIF_OUT for AIF3 Capture
...
Diffstat (limited to 'drivers/mfd')
-rw-r--r-- | drivers/mfd/twl6040-core.c | 67 | ||||
-rw-r--r-- | drivers/mfd/wm8994-core.c | 27 |
2 files changed, 70 insertions, 24 deletions
diff --git a/drivers/mfd/twl6040-core.c b/drivers/mfd/twl6040-core.c index 24d436c2fe4a..268f80fd0439 100644 --- a/drivers/mfd/twl6040-core.c +++ b/drivers/mfd/twl6040-core.c | |||
@@ -34,7 +34,7 @@ | |||
34 | #include <linux/mfd/core.h> | 34 | #include <linux/mfd/core.h> |
35 | #include <linux/mfd/twl6040.h> | 35 | #include <linux/mfd/twl6040.h> |
36 | 36 | ||
37 | static struct platform_device *twl6040_dev; | 37 | #define VIBRACTRL_MEMBER(reg) ((reg == TWL6040_REG_VIBCTLL) ? 0 : 1) |
38 | 38 | ||
39 | int twl6040_reg_read(struct twl6040 *twl6040, unsigned int reg) | 39 | int twl6040_reg_read(struct twl6040 *twl6040, unsigned int reg) |
40 | { | 40 | { |
@@ -42,10 +42,16 @@ int twl6040_reg_read(struct twl6040 *twl6040, unsigned int reg) | |||
42 | u8 val = 0; | 42 | u8 val = 0; |
43 | 43 | ||
44 | mutex_lock(&twl6040->io_mutex); | 44 | mutex_lock(&twl6040->io_mutex); |
45 | ret = twl_i2c_read_u8(TWL_MODULE_AUDIO_VOICE, &val, reg); | 45 | /* Vibra control registers from cache */ |
46 | if (ret < 0) { | 46 | if (unlikely(reg == TWL6040_REG_VIBCTLL || |
47 | mutex_unlock(&twl6040->io_mutex); | 47 | reg == TWL6040_REG_VIBCTLR)) { |
48 | return ret; | 48 | val = twl6040->vibra_ctrl_cache[VIBRACTRL_MEMBER(reg)]; |
49 | } else { | ||
50 | ret = twl_i2c_read_u8(TWL_MODULE_AUDIO_VOICE, &val, reg); | ||
51 | if (ret < 0) { | ||
52 | mutex_unlock(&twl6040->io_mutex); | ||
53 | return ret; | ||
54 | } | ||
49 | } | 55 | } |
50 | mutex_unlock(&twl6040->io_mutex); | 56 | mutex_unlock(&twl6040->io_mutex); |
51 | 57 | ||
@@ -59,6 +65,9 @@ int twl6040_reg_write(struct twl6040 *twl6040, unsigned int reg, u8 val) | |||
59 | 65 | ||
60 | mutex_lock(&twl6040->io_mutex); | 66 | mutex_lock(&twl6040->io_mutex); |
61 | ret = twl_i2c_write_u8(TWL_MODULE_AUDIO_VOICE, val, reg); | 67 | ret = twl_i2c_write_u8(TWL_MODULE_AUDIO_VOICE, val, reg); |
68 | /* Cache the vibra control registers */ | ||
69 | if (reg == TWL6040_REG_VIBCTLL || reg == TWL6040_REG_VIBCTLR) | ||
70 | twl6040->vibra_ctrl_cache[VIBRACTRL_MEMBER(reg)] = val; | ||
62 | mutex_unlock(&twl6040->io_mutex); | 71 | mutex_unlock(&twl6040->io_mutex); |
63 | 72 | ||
64 | return ret; | 73 | return ret; |
@@ -203,11 +212,11 @@ static irqreturn_t twl6040_naudint_handler(int irq, void *data) | |||
203 | if (intid & TWL6040_THINT) { | 212 | if (intid & TWL6040_THINT) { |
204 | status = twl6040_reg_read(twl6040, TWL6040_REG_STATUS); | 213 | status = twl6040_reg_read(twl6040, TWL6040_REG_STATUS); |
205 | if (status & TWL6040_TSHUTDET) { | 214 | if (status & TWL6040_TSHUTDET) { |
206 | dev_warn(&twl6040_dev->dev, | 215 | dev_warn(twl6040->dev, |
207 | "Thermal shutdown, powering-off"); | 216 | "Thermal shutdown, powering-off"); |
208 | twl6040_power(twl6040, 0); | 217 | twl6040_power(twl6040, 0); |
209 | } else { | 218 | } else { |
210 | dev_warn(&twl6040_dev->dev, | 219 | dev_warn(twl6040->dev, |
211 | "Leaving thermal shutdown, powering-on"); | 220 | "Leaving thermal shutdown, powering-on"); |
212 | twl6040_power(twl6040, 1); | 221 | twl6040_power(twl6040, 1); |
213 | } | 222 | } |
@@ -227,7 +236,7 @@ static int twl6040_power_up_completion(struct twl6040 *twl6040, | |||
227 | if (!time_left) { | 236 | if (!time_left) { |
228 | intid = twl6040_reg_read(twl6040, TWL6040_REG_INTID); | 237 | intid = twl6040_reg_read(twl6040, TWL6040_REG_INTID); |
229 | if (!(intid & TWL6040_READYINT)) { | 238 | if (!(intid & TWL6040_READYINT)) { |
230 | dev_err(&twl6040_dev->dev, | 239 | dev_err(twl6040->dev, |
231 | "timeout waiting for READYINT\n"); | 240 | "timeout waiting for READYINT\n"); |
232 | return -ETIMEDOUT; | 241 | return -ETIMEDOUT; |
233 | } | 242 | } |
@@ -255,7 +264,7 @@ int twl6040_power(struct twl6040 *twl6040, int on) | |||
255 | /* wait for power-up completion */ | 264 | /* wait for power-up completion */ |
256 | ret = twl6040_power_up_completion(twl6040, naudint); | 265 | ret = twl6040_power_up_completion(twl6040, naudint); |
257 | if (ret) { | 266 | if (ret) { |
258 | dev_err(&twl6040_dev->dev, | 267 | dev_err(twl6040->dev, |
259 | "automatic power-down failed\n"); | 268 | "automatic power-down failed\n"); |
260 | twl6040->power_count = 0; | 269 | twl6040->power_count = 0; |
261 | goto out; | 270 | goto out; |
@@ -264,7 +273,7 @@ int twl6040_power(struct twl6040 *twl6040, int on) | |||
264 | /* use manual power-up sequence */ | 273 | /* use manual power-up sequence */ |
265 | ret = twl6040_power_up(twl6040); | 274 | ret = twl6040_power_up(twl6040); |
266 | if (ret) { | 275 | if (ret) { |
267 | dev_err(&twl6040_dev->dev, | 276 | dev_err(twl6040->dev, |
268 | "manual power-up failed\n"); | 277 | "manual power-up failed\n"); |
269 | twl6040->power_count = 0; | 278 | twl6040->power_count = 0; |
270 | goto out; | 279 | goto out; |
@@ -276,7 +285,7 @@ int twl6040_power(struct twl6040 *twl6040, int on) | |||
276 | } else { | 285 | } else { |
277 | /* already powered-down */ | 286 | /* already powered-down */ |
278 | if (!twl6040->power_count) { | 287 | if (!twl6040->power_count) { |
279 | dev_err(&twl6040_dev->dev, | 288 | dev_err(twl6040->dev, |
280 | "device is already powered-off\n"); | 289 | "device is already powered-off\n"); |
281 | ret = -EPERM; | 290 | ret = -EPERM; |
282 | goto out; | 291 | goto out; |
@@ -326,7 +335,7 @@ int twl6040_set_pll(struct twl6040 *twl6040, int pll_id, | |||
326 | lppllctl &= ~TWL6040_LPLLFIN; | 335 | lppllctl &= ~TWL6040_LPLLFIN; |
327 | break; | 336 | break; |
328 | default: | 337 | default: |
329 | dev_err(&twl6040_dev->dev, | 338 | dev_err(twl6040->dev, |
330 | "freq_out %d not supported\n", freq_out); | 339 | "freq_out %d not supported\n", freq_out); |
331 | ret = -EINVAL; | 340 | ret = -EINVAL; |
332 | goto pll_out; | 341 | goto pll_out; |
@@ -347,7 +356,7 @@ int twl6040_set_pll(struct twl6040 *twl6040, int pll_id, | |||
347 | hppllctl); | 356 | hppllctl); |
348 | break; | 357 | break; |
349 | default: | 358 | default: |
350 | dev_err(&twl6040_dev->dev, | 359 | dev_err(twl6040->dev, |
351 | "freq_in %d not supported\n", freq_in); | 360 | "freq_in %d not supported\n", freq_in); |
352 | ret = -EINVAL; | 361 | ret = -EINVAL; |
353 | goto pll_out; | 362 | goto pll_out; |
@@ -356,7 +365,7 @@ int twl6040_set_pll(struct twl6040 *twl6040, int pll_id, | |||
356 | case TWL6040_SYSCLK_SEL_HPPLL: | 365 | case TWL6040_SYSCLK_SEL_HPPLL: |
357 | /* high-performance PLL can provide only 19.2 MHz */ | 366 | /* high-performance PLL can provide only 19.2 MHz */ |
358 | if (freq_out != 19200000) { | 367 | if (freq_out != 19200000) { |
359 | dev_err(&twl6040_dev->dev, | 368 | dev_err(twl6040->dev, |
360 | "freq_out %d not supported\n", freq_out); | 369 | "freq_out %d not supported\n", freq_out); |
361 | ret = -EINVAL; | 370 | ret = -EINVAL; |
362 | goto pll_out; | 371 | goto pll_out; |
@@ -389,7 +398,7 @@ int twl6040_set_pll(struct twl6040 *twl6040, int pll_id, | |||
389 | TWL6040_HPLLENA; | 398 | TWL6040_HPLLENA; |
390 | break; | 399 | break; |
391 | default: | 400 | default: |
392 | dev_err(&twl6040_dev->dev, | 401 | dev_err(twl6040->dev, |
393 | "freq_in %d not supported\n", freq_in); | 402 | "freq_in %d not supported\n", freq_in); |
394 | ret = -EINVAL; | 403 | ret = -EINVAL; |
395 | goto pll_out; | 404 | goto pll_out; |
@@ -406,7 +415,7 @@ int twl6040_set_pll(struct twl6040 *twl6040, int pll_id, | |||
406 | twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL, lppllctl); | 415 | twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL, lppllctl); |
407 | break; | 416 | break; |
408 | default: | 417 | default: |
409 | dev_err(&twl6040_dev->dev, "unknown pll id %d\n", pll_id); | 418 | dev_err(twl6040->dev, "unknown pll id %d\n", pll_id); |
410 | ret = -EINVAL; | 419 | ret = -EINVAL; |
411 | goto pll_out; | 420 | goto pll_out; |
412 | } | 421 | } |
@@ -435,6 +444,18 @@ unsigned int twl6040_get_sysclk(struct twl6040 *twl6040) | |||
435 | } | 444 | } |
436 | EXPORT_SYMBOL(twl6040_get_sysclk); | 445 | EXPORT_SYMBOL(twl6040_get_sysclk); |
437 | 446 | ||
447 | /* Get the combined status of the vibra control register */ | ||
448 | int twl6040_get_vibralr_status(struct twl6040 *twl6040) | ||
449 | { | ||
450 | u8 status; | ||
451 | |||
452 | status = twl6040->vibra_ctrl_cache[0] | twl6040->vibra_ctrl_cache[1]; | ||
453 | status &= (TWL6040_VIBENA | TWL6040_VIBSEL); | ||
454 | |||
455 | return status; | ||
456 | } | ||
457 | EXPORT_SYMBOL(twl6040_get_vibralr_status); | ||
458 | |||
438 | static struct resource twl6040_vibra_rsrc[] = { | 459 | static struct resource twl6040_vibra_rsrc[] = { |
439 | { | 460 | { |
440 | .flags = IORESOURCE_IRQ, | 461 | .flags = IORESOURCE_IRQ, |
@@ -471,9 +492,7 @@ static int __devinit twl6040_probe(struct platform_device *pdev) | |||
471 | 492 | ||
472 | platform_set_drvdata(pdev, twl6040); | 493 | platform_set_drvdata(pdev, twl6040); |
473 | 494 | ||
474 | twl6040_dev = pdev; | ||
475 | twl6040->dev = &pdev->dev; | 495 | twl6040->dev = &pdev->dev; |
476 | twl6040->audpwron = pdata->audpwron_gpio; | ||
477 | twl6040->irq = pdata->naudint_irq; | 496 | twl6040->irq = pdata->naudint_irq; |
478 | twl6040->irq_base = pdata->irq_base; | 497 | twl6040->irq_base = pdata->irq_base; |
479 | 498 | ||
@@ -483,6 +502,12 @@ static int __devinit twl6040_probe(struct platform_device *pdev) | |||
483 | 502 | ||
484 | twl6040->rev = twl6040_reg_read(twl6040, TWL6040_REG_ASICREV); | 503 | twl6040->rev = twl6040_reg_read(twl6040, TWL6040_REG_ASICREV); |
485 | 504 | ||
505 | /* ERRATA: Automatic power-up is not possible in ES1.0 */ | ||
506 | if (twl6040_get_revid(twl6040) > TWL6040_REV_ES1_0) | ||
507 | twl6040->audpwron = pdata->audpwron_gpio; | ||
508 | else | ||
509 | twl6040->audpwron = -EINVAL; | ||
510 | |||
486 | if (gpio_is_valid(twl6040->audpwron)) { | 511 | if (gpio_is_valid(twl6040->audpwron)) { |
487 | ret = gpio_request(twl6040->audpwron, "audpwron"); | 512 | ret = gpio_request(twl6040->audpwron, "audpwron"); |
488 | if (ret) | 513 | if (ret) |
@@ -493,10 +518,6 @@ static int __devinit twl6040_probe(struct platform_device *pdev) | |||
493 | goto gpio2_err; | 518 | goto gpio2_err; |
494 | } | 519 | } |
495 | 520 | ||
496 | /* ERRATA: Automatic power-up is not possible in ES1.0 */ | ||
497 | if (twl6040->rev == TWL6040_REV_ES1_0) | ||
498 | twl6040->audpwron = -EINVAL; | ||
499 | |||
500 | /* codec interrupt */ | 521 | /* codec interrupt */ |
501 | ret = twl6040_irq_init(twl6040); | 522 | ret = twl6040_irq_init(twl6040); |
502 | if (ret) | 523 | if (ret) |
@@ -566,7 +587,6 @@ gpio2_err: | |||
566 | gpio1_err: | 587 | gpio1_err: |
567 | platform_set_drvdata(pdev, NULL); | 588 | platform_set_drvdata(pdev, NULL); |
568 | kfree(twl6040); | 589 | kfree(twl6040); |
569 | twl6040_dev = NULL; | ||
570 | return ret; | 590 | return ret; |
571 | } | 591 | } |
572 | 592 | ||
@@ -586,7 +606,6 @@ static int __devexit twl6040_remove(struct platform_device *pdev) | |||
586 | mfd_remove_devices(&pdev->dev); | 606 | mfd_remove_devices(&pdev->dev); |
587 | platform_set_drvdata(pdev, NULL); | 607 | platform_set_drvdata(pdev, NULL); |
588 | kfree(twl6040); | 608 | kfree(twl6040); |
589 | twl6040_dev = NULL; | ||
590 | 609 | ||
591 | return 0; | 610 | return 0; |
592 | } | 611 | } |
diff --git a/drivers/mfd/wm8994-core.c b/drivers/mfd/wm8994-core.c index bfde4e8ec638..b03be1d4e0ca 100644 --- a/drivers/mfd/wm8994-core.c +++ b/drivers/mfd/wm8994-core.c | |||
@@ -167,6 +167,18 @@ static struct mfd_cell wm8994_devs[] = { | |||
167 | * and should be handled via the standard regulator API supply | 167 | * and should be handled via the standard regulator API supply |
168 | * management. | 168 | * management. |
169 | */ | 169 | */ |
170 | static const char *wm1811_main_supplies[] = { | ||
171 | "DBVDD1", | ||
172 | "DBVDD2", | ||
173 | "DBVDD3", | ||
174 | "DCVDD", | ||
175 | "AVDD1", | ||
176 | "AVDD2", | ||
177 | "CPVDD", | ||
178 | "SPKVDD1", | ||
179 | "SPKVDD2", | ||
180 | }; | ||
181 | |||
170 | static const char *wm8994_main_supplies[] = { | 182 | static const char *wm8994_main_supplies[] = { |
171 | "DBVDD", | 183 | "DBVDD", |
172 | "DCVDD", | 184 | "DCVDD", |
@@ -329,6 +341,9 @@ static int wm8994_device_init(struct wm8994 *wm8994, int irq) | |||
329 | } | 341 | } |
330 | 342 | ||
331 | switch (wm8994->type) { | 343 | switch (wm8994->type) { |
344 | case WM1811: | ||
345 | wm8994->num_supplies = ARRAY_SIZE(wm1811_main_supplies); | ||
346 | break; | ||
332 | case WM8994: | 347 | case WM8994: |
333 | wm8994->num_supplies = ARRAY_SIZE(wm8994_main_supplies); | 348 | wm8994->num_supplies = ARRAY_SIZE(wm8994_main_supplies); |
334 | break; | 349 | break; |
@@ -349,6 +364,10 @@ static int wm8994_device_init(struct wm8994 *wm8994, int irq) | |||
349 | } | 364 | } |
350 | 365 | ||
351 | switch (wm8994->type) { | 366 | switch (wm8994->type) { |
367 | case WM1811: | ||
368 | for (i = 0; i < ARRAY_SIZE(wm1811_main_supplies); i++) | ||
369 | wm8994->supplies[i].supply = wm1811_main_supplies[i]; | ||
370 | break; | ||
352 | case WM8994: | 371 | case WM8994: |
353 | for (i = 0; i < ARRAY_SIZE(wm8994_main_supplies); i++) | 372 | for (i = 0; i < ARRAY_SIZE(wm8994_main_supplies); i++) |
354 | wm8994->supplies[i].supply = wm8994_main_supplies[i]; | 373 | wm8994->supplies[i].supply = wm8994_main_supplies[i]; |
@@ -382,6 +401,13 @@ static int wm8994_device_init(struct wm8994 *wm8994, int irq) | |||
382 | goto err_enable; | 401 | goto err_enable; |
383 | } | 402 | } |
384 | switch (ret) { | 403 | switch (ret) { |
404 | case 0x1811: | ||
405 | devname = "WM1811"; | ||
406 | if (wm8994->type != WM1811) | ||
407 | dev_warn(wm8994->dev, "Device registered as type %d\n", | ||
408 | wm8994->type); | ||
409 | wm8994->type = WM1811; | ||
410 | break; | ||
385 | case 0x8994: | 411 | case 0x8994: |
386 | devname = "WM8994"; | 412 | devname = "WM8994"; |
387 | if (wm8994->type != WM8994) | 413 | if (wm8994->type != WM8994) |
@@ -539,6 +565,7 @@ static int wm8994_i2c_remove(struct i2c_client *i2c) | |||
539 | } | 565 | } |
540 | 566 | ||
541 | static const struct i2c_device_id wm8994_i2c_id[] = { | 567 | static const struct i2c_device_id wm8994_i2c_id[] = { |
568 | { "wm1811", WM1811 }, | ||
542 | { "wm8994", WM8994 }, | 569 | { "wm8994", WM8994 }, |
543 | { "wm8958", WM8958 }, | 570 | { "wm8958", WM8958 }, |
544 | { } | 571 | { } |