diff options
Diffstat (limited to 'drivers/mfd/wm8994-core.c')
-rw-r--r-- | drivers/mfd/wm8994-core.c | 93 |
1 files changed, 74 insertions, 19 deletions
diff --git a/drivers/mfd/wm8994-core.c b/drivers/mfd/wm8994-core.c index b3b2aaf89dbe..8d221ba5e38d 100644 --- a/drivers/mfd/wm8994-core.c +++ b/drivers/mfd/wm8994-core.c | |||
@@ -218,6 +218,18 @@ static const char *wm8994_main_supplies[] = { | |||
218 | "SPKVDD2", | 218 | "SPKVDD2", |
219 | }; | 219 | }; |
220 | 220 | ||
221 | static const char *wm8958_main_supplies[] = { | ||
222 | "DBVDD1", | ||
223 | "DBVDD2", | ||
224 | "DBVDD3", | ||
225 | "DCVDD", | ||
226 | "AVDD1", | ||
227 | "AVDD2", | ||
228 | "CPVDD", | ||
229 | "SPKVDD1", | ||
230 | "SPKVDD2", | ||
231 | }; | ||
232 | |||
221 | #ifdef CONFIG_PM | 233 | #ifdef CONFIG_PM |
222 | static int wm8994_device_suspend(struct device *dev) | 234 | static int wm8994_device_suspend(struct device *dev) |
223 | { | 235 | { |
@@ -239,7 +251,7 @@ static int wm8994_device_suspend(struct device *dev) | |||
239 | if (ret < 0) | 251 | if (ret < 0) |
240 | dev_err(dev, "Failed to save LDO registers: %d\n", ret); | 252 | dev_err(dev, "Failed to save LDO registers: %d\n", ret); |
241 | 253 | ||
242 | ret = regulator_bulk_disable(ARRAY_SIZE(wm8994_main_supplies), | 254 | ret = regulator_bulk_disable(wm8994->num_supplies, |
243 | wm8994->supplies); | 255 | wm8994->supplies); |
244 | if (ret != 0) { | 256 | if (ret != 0) { |
245 | dev_err(dev, "Failed to disable supplies: %d\n", ret); | 257 | dev_err(dev, "Failed to disable supplies: %d\n", ret); |
@@ -254,7 +266,7 @@ static int wm8994_device_resume(struct device *dev) | |||
254 | struct wm8994 *wm8994 = dev_get_drvdata(dev); | 266 | struct wm8994 *wm8994 = dev_get_drvdata(dev); |
255 | int ret; | 267 | int ret; |
256 | 268 | ||
257 | ret = regulator_bulk_enable(ARRAY_SIZE(wm8994_main_supplies), | 269 | ret = regulator_bulk_enable(wm8994->num_supplies, |
258 | wm8994->supplies); | 270 | wm8994->supplies); |
259 | if (ret != 0) { | 271 | if (ret != 0) { |
260 | dev_err(dev, "Failed to enable supplies: %d\n", ret); | 272 | dev_err(dev, "Failed to enable supplies: %d\n", ret); |
@@ -305,9 +317,10 @@ static int wm8994_ldo_in_use(struct wm8994_pdata *pdata, int ldo) | |||
305 | /* | 317 | /* |
306 | * Instantiate the generic non-control parts of the device. | 318 | * Instantiate the generic non-control parts of the device. |
307 | */ | 319 | */ |
308 | static int wm8994_device_init(struct wm8994 *wm8994, unsigned long id, int irq) | 320 | static int wm8994_device_init(struct wm8994 *wm8994, int irq) |
309 | { | 321 | { |
310 | struct wm8994_pdata *pdata = wm8994->dev->platform_data; | 322 | struct wm8994_pdata *pdata = wm8994->dev->platform_data; |
323 | const char *devname; | ||
311 | int ret, i; | 324 | int ret, i; |
312 | 325 | ||
313 | mutex_init(&wm8994->io_lock); | 326 | mutex_init(&wm8994->io_lock); |
@@ -323,25 +336,48 @@ static int wm8994_device_init(struct wm8994 *wm8994, unsigned long id, int irq) | |||
323 | goto err; | 336 | goto err; |
324 | } | 337 | } |
325 | 338 | ||
339 | switch (wm8994->type) { | ||
340 | case WM8994: | ||
341 | wm8994->num_supplies = ARRAY_SIZE(wm8994_main_supplies); | ||
342 | break; | ||
343 | case WM8958: | ||
344 | wm8994->num_supplies = ARRAY_SIZE(wm8958_main_supplies); | ||
345 | break; | ||
346 | default: | ||
347 | BUG(); | ||
348 | return -EINVAL; | ||
349 | } | ||
350 | |||
326 | wm8994->supplies = kzalloc(sizeof(struct regulator_bulk_data) * | 351 | wm8994->supplies = kzalloc(sizeof(struct regulator_bulk_data) * |
327 | ARRAY_SIZE(wm8994_main_supplies), | 352 | wm8994->num_supplies, |
328 | GFP_KERNEL); | 353 | GFP_KERNEL); |
329 | if (!wm8994->supplies) { | 354 | if (!wm8994->supplies) { |
330 | ret = -ENOMEM; | 355 | ret = -ENOMEM; |
331 | goto err; | 356 | goto err; |
332 | } | 357 | } |
333 | 358 | ||
334 | for (i = 0; i < ARRAY_SIZE(wm8994_main_supplies); i++) | 359 | switch (wm8994->type) { |
335 | wm8994->supplies[i].supply = wm8994_main_supplies[i]; | 360 | case WM8994: |
336 | 361 | for (i = 0; i < ARRAY_SIZE(wm8994_main_supplies); i++) | |
337 | ret = regulator_bulk_get(wm8994->dev, ARRAY_SIZE(wm8994_main_supplies), | 362 | wm8994->supplies[i].supply = wm8994_main_supplies[i]; |
363 | break; | ||
364 | case WM8958: | ||
365 | for (i = 0; i < ARRAY_SIZE(wm8958_main_supplies); i++) | ||
366 | wm8994->supplies[i].supply = wm8958_main_supplies[i]; | ||
367 | break; | ||
368 | default: | ||
369 | BUG(); | ||
370 | return -EINVAL; | ||
371 | } | ||
372 | |||
373 | ret = regulator_bulk_get(wm8994->dev, wm8994->num_supplies, | ||
338 | wm8994->supplies); | 374 | wm8994->supplies); |
339 | if (ret != 0) { | 375 | if (ret != 0) { |
340 | dev_err(wm8994->dev, "Failed to get supplies: %d\n", ret); | 376 | dev_err(wm8994->dev, "Failed to get supplies: %d\n", ret); |
341 | goto err_supplies; | 377 | goto err_supplies; |
342 | } | 378 | } |
343 | 379 | ||
344 | ret = regulator_bulk_enable(ARRAY_SIZE(wm8994_main_supplies), | 380 | ret = regulator_bulk_enable(wm8994->num_supplies, |
345 | wm8994->supplies); | 381 | wm8994->supplies); |
346 | if (ret != 0) { | 382 | if (ret != 0) { |
347 | dev_err(wm8994->dev, "Failed to enable supplies: %d\n", ret); | 383 | dev_err(wm8994->dev, "Failed to enable supplies: %d\n", ret); |
@@ -353,7 +389,22 @@ static int wm8994_device_init(struct wm8994 *wm8994, unsigned long id, int irq) | |||
353 | dev_err(wm8994->dev, "Failed to read ID register\n"); | 389 | dev_err(wm8994->dev, "Failed to read ID register\n"); |
354 | goto err_enable; | 390 | goto err_enable; |
355 | } | 391 | } |
356 | if (ret != 0x8994) { | 392 | switch (ret) { |
393 | case 0x8994: | ||
394 | devname = "WM8994"; | ||
395 | if (wm8994->type != WM8994) | ||
396 | dev_warn(wm8994->dev, "Device registered as type %d\n", | ||
397 | wm8994->type); | ||
398 | wm8994->type = WM8994; | ||
399 | break; | ||
400 | case 0x8958: | ||
401 | devname = "WM8958"; | ||
402 | if (wm8994->type != WM8958) | ||
403 | dev_warn(wm8994->dev, "Device registered as type %d\n", | ||
404 | wm8994->type); | ||
405 | wm8994->type = WM8958; | ||
406 | break; | ||
407 | default: | ||
357 | dev_err(wm8994->dev, "Device is not a WM8994, ID is %x\n", | 408 | dev_err(wm8994->dev, "Device is not a WM8994, ID is %x\n", |
358 | ret); | 409 | ret); |
359 | ret = -EINVAL; | 410 | ret = -EINVAL; |
@@ -370,14 +421,16 @@ static int wm8994_device_init(struct wm8994 *wm8994, unsigned long id, int irq) | |||
370 | switch (ret) { | 421 | switch (ret) { |
371 | case 0: | 422 | case 0: |
372 | case 1: | 423 | case 1: |
373 | dev_warn(wm8994->dev, "revision %c not fully supported\n", | 424 | if (wm8994->type == WM8994) |
374 | 'A' + ret); | 425 | dev_warn(wm8994->dev, |
426 | "revision %c not fully supported\n", | ||
427 | 'A' + ret); | ||
375 | break; | 428 | break; |
376 | default: | 429 | default: |
377 | dev_info(wm8994->dev, "revision %c\n", 'A' + ret); | ||
378 | break; | 430 | break; |
379 | } | 431 | } |
380 | 432 | ||
433 | dev_info(wm8994->dev, "%s revision %c\n", devname, 'A' + ret); | ||
381 | 434 | ||
382 | if (pdata) { | 435 | if (pdata) { |
383 | wm8994->irq_base = pdata->irq_base; | 436 | wm8994->irq_base = pdata->irq_base; |
@@ -423,10 +476,10 @@ static int wm8994_device_init(struct wm8994 *wm8994, unsigned long id, int irq) | |||
423 | err_irq: | 476 | err_irq: |
424 | wm8994_irq_exit(wm8994); | 477 | wm8994_irq_exit(wm8994); |
425 | err_enable: | 478 | err_enable: |
426 | regulator_bulk_disable(ARRAY_SIZE(wm8994_main_supplies), | 479 | regulator_bulk_disable(wm8994->num_supplies, |
427 | wm8994->supplies); | 480 | wm8994->supplies); |
428 | err_get: | 481 | err_get: |
429 | regulator_bulk_free(ARRAY_SIZE(wm8994_main_supplies), wm8994->supplies); | 482 | regulator_bulk_free(wm8994->num_supplies, wm8994->supplies); |
430 | err_supplies: | 483 | err_supplies: |
431 | kfree(wm8994->supplies); | 484 | kfree(wm8994->supplies); |
432 | err: | 485 | err: |
@@ -439,9 +492,9 @@ static void wm8994_device_exit(struct wm8994 *wm8994) | |||
439 | { | 492 | { |
440 | mfd_remove_devices(wm8994->dev); | 493 | mfd_remove_devices(wm8994->dev); |
441 | wm8994_irq_exit(wm8994); | 494 | wm8994_irq_exit(wm8994); |
442 | regulator_bulk_disable(ARRAY_SIZE(wm8994_main_supplies), | 495 | regulator_bulk_disable(wm8994->num_supplies, |
443 | wm8994->supplies); | 496 | wm8994->supplies); |
444 | regulator_bulk_free(ARRAY_SIZE(wm8994_main_supplies), wm8994->supplies); | 497 | regulator_bulk_free(wm8994->num_supplies, wm8994->supplies); |
445 | kfree(wm8994->supplies); | 498 | kfree(wm8994->supplies); |
446 | kfree(wm8994); | 499 | kfree(wm8994); |
447 | } | 500 | } |
@@ -506,8 +559,9 @@ static int wm8994_i2c_probe(struct i2c_client *i2c, | |||
506 | wm8994->read_dev = wm8994_i2c_read_device; | 559 | wm8994->read_dev = wm8994_i2c_read_device; |
507 | wm8994->write_dev = wm8994_i2c_write_device; | 560 | wm8994->write_dev = wm8994_i2c_write_device; |
508 | wm8994->irq = i2c->irq; | 561 | wm8994->irq = i2c->irq; |
562 | wm8994->type = id->driver_data; | ||
509 | 563 | ||
510 | return wm8994_device_init(wm8994, id->driver_data, i2c->irq); | 564 | return wm8994_device_init(wm8994, i2c->irq); |
511 | } | 565 | } |
512 | 566 | ||
513 | static int wm8994_i2c_remove(struct i2c_client *i2c) | 567 | static int wm8994_i2c_remove(struct i2c_client *i2c) |
@@ -535,7 +589,8 @@ static int wm8994_i2c_resume(struct i2c_client *i2c) | |||
535 | #endif | 589 | #endif |
536 | 590 | ||
537 | static const struct i2c_device_id wm8994_i2c_id[] = { | 591 | static const struct i2c_device_id wm8994_i2c_id[] = { |
538 | { "wm8994", 0 }, | 592 | { "wm8994", WM8994 }, |
593 | { "wm8958", WM8958 }, | ||
539 | { } | 594 | { } |
540 | }; | 595 | }; |
541 | MODULE_DEVICE_TABLE(i2c, wm8994_i2c_id); | 596 | MODULE_DEVICE_TABLE(i2c, wm8994_i2c_id); |