diff options
-rw-r--r-- | drivers/mfd/wm831x-core.c | 9 | ||||
-rw-r--r-- | drivers/mfd/wm831x-irq.c | 209 | ||||
-rw-r--r-- | include/linux/mfd/wm831x/core.h | 40 | ||||
-rw-r--r-- | include/linux/mfd/wm831x/pdata.h | 1 |
4 files changed, 122 insertions, 137 deletions
diff --git a/drivers/mfd/wm831x-core.c b/drivers/mfd/wm831x-core.c index 163029f06185..223a90c7492f 100644 --- a/drivers/mfd/wm831x-core.c +++ b/drivers/mfd/wm831x-core.c | |||
@@ -1504,19 +1504,19 @@ static int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq) | |||
1504 | case WM8310: | 1504 | case WM8310: |
1505 | ret = mfd_add_devices(wm831x->dev, -1, | 1505 | ret = mfd_add_devices(wm831x->dev, -1, |
1506 | wm8310_devs, ARRAY_SIZE(wm8310_devs), | 1506 | wm8310_devs, ARRAY_SIZE(wm8310_devs), |
1507 | NULL, 0); | 1507 | NULL, wm831x->irq_base); |
1508 | break; | 1508 | break; |
1509 | 1509 | ||
1510 | case WM8311: | 1510 | case WM8311: |
1511 | ret = mfd_add_devices(wm831x->dev, -1, | 1511 | ret = mfd_add_devices(wm831x->dev, -1, |
1512 | wm8311_devs, ARRAY_SIZE(wm8311_devs), | 1512 | wm8311_devs, ARRAY_SIZE(wm8311_devs), |
1513 | NULL, 0); | 1513 | NULL, wm831x->irq_base); |
1514 | break; | 1514 | break; |
1515 | 1515 | ||
1516 | case WM8312: | 1516 | case WM8312: |
1517 | ret = mfd_add_devices(wm831x->dev, -1, | 1517 | ret = mfd_add_devices(wm831x->dev, -1, |
1518 | wm8312_devs, ARRAY_SIZE(wm8312_devs), | 1518 | wm8312_devs, ARRAY_SIZE(wm8312_devs), |
1519 | NULL, 0); | 1519 | NULL, wm831x->irq_base); |
1520 | break; | 1520 | break; |
1521 | 1521 | ||
1522 | case WM8320: | 1522 | case WM8320: |
@@ -1538,7 +1538,8 @@ static int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq) | |||
1538 | if (pdata && pdata->backlight) { | 1538 | if (pdata && pdata->backlight) { |
1539 | /* Treat errors as non-critical */ | 1539 | /* Treat errors as non-critical */ |
1540 | ret = mfd_add_devices(wm831x->dev, -1, backlight_devs, | 1540 | ret = mfd_add_devices(wm831x->dev, -1, backlight_devs, |
1541 | ARRAY_SIZE(backlight_devs), NULL, 0); | 1541 | ARRAY_SIZE(backlight_devs), NULL, |
1542 | wm831x->irq_base); | ||
1542 | if (ret < 0) | 1543 | if (ret < 0) |
1543 | dev_err(wm831x->dev, "Failed to add backlight: %d\n", | 1544 | dev_err(wm831x->dev, "Failed to add backlight: %d\n", |
1544 | ret); | 1545 | ret); |
diff --git a/drivers/mfd/wm831x-irq.c b/drivers/mfd/wm831x-irq.c index ac056ea6b66e..301327697117 100644 --- a/drivers/mfd/wm831x-irq.c +++ b/drivers/mfd/wm831x-irq.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <linux/kernel.h> | 15 | #include <linux/kernel.h> |
16 | #include <linux/module.h> | 16 | #include <linux/module.h> |
17 | #include <linux/i2c.h> | 17 | #include <linux/i2c.h> |
18 | #include <linux/irq.h> | ||
18 | #include <linux/mfd/core.h> | 19 | #include <linux/mfd/core.h> |
19 | #include <linux/interrupt.h> | 20 | #include <linux/interrupt.h> |
20 | 21 | ||
@@ -339,110 +340,71 @@ static inline int irq_data_to_mask_reg(struct wm831x_irq_data *irq_data) | |||
339 | return WM831X_INTERRUPT_STATUS_1_MASK - 1 + irq_data->reg; | 340 | return WM831X_INTERRUPT_STATUS_1_MASK - 1 + irq_data->reg; |
340 | } | 341 | } |
341 | 342 | ||
342 | static void __wm831x_enable_irq(struct wm831x *wm831x, int irq) | 343 | static inline struct wm831x_irq_data *irq_to_wm831x_irq(struct wm831x *wm831x, |
344 | int irq) | ||
343 | { | 345 | { |
344 | struct wm831x_irq_data *irq_data = &wm831x_irqs[irq]; | 346 | return &wm831x_irqs[irq - wm831x->irq_base]; |
345 | |||
346 | wm831x->irq_masks[irq_data->reg - 1] &= ~irq_data->mask; | ||
347 | wm831x_reg_write(wm831x, irq_data_to_mask_reg(irq_data), | ||
348 | wm831x->irq_masks[irq_data->reg - 1]); | ||
349 | } | 347 | } |
350 | 348 | ||
351 | void wm831x_enable_irq(struct wm831x *wm831x, int irq) | 349 | static void wm831x_irq_lock(unsigned int irq) |
352 | { | 350 | { |
353 | mutex_lock(&wm831x->irq_lock); | 351 | struct wm831x *wm831x = get_irq_chip_data(irq); |
354 | __wm831x_enable_irq(wm831x, irq); | ||
355 | mutex_unlock(&wm831x->irq_lock); | ||
356 | } | ||
357 | EXPORT_SYMBOL_GPL(wm831x_enable_irq); | ||
358 | 352 | ||
359 | static void __wm831x_disable_irq(struct wm831x *wm831x, int irq) | ||
360 | { | ||
361 | struct wm831x_irq_data *irq_data = &wm831x_irqs[irq]; | ||
362 | |||
363 | wm831x->irq_masks[irq_data->reg - 1] |= irq_data->mask; | ||
364 | wm831x_reg_write(wm831x, irq_data_to_mask_reg(irq_data), | ||
365 | wm831x->irq_masks[irq_data->reg - 1]); | ||
366 | } | ||
367 | |||
368 | void wm831x_disable_irq(struct wm831x *wm831x, int irq) | ||
369 | { | ||
370 | mutex_lock(&wm831x->irq_lock); | 353 | mutex_lock(&wm831x->irq_lock); |
371 | __wm831x_disable_irq(wm831x, irq); | ||
372 | mutex_unlock(&wm831x->irq_lock); | ||
373 | } | 354 | } |
374 | EXPORT_SYMBOL_GPL(wm831x_disable_irq); | ||
375 | 355 | ||
376 | int wm831x_request_irq(struct wm831x *wm831x, | 356 | static void wm831x_irq_sync_unlock(unsigned int irq) |
377 | unsigned int irq, irq_handler_t handler, | ||
378 | unsigned long flags, const char *name, | ||
379 | void *dev) | ||
380 | { | 357 | { |
381 | int ret = 0; | 358 | struct wm831x *wm831x = get_irq_chip_data(irq); |
382 | 359 | int i; | |
383 | if (irq < 0 || irq >= WM831X_NUM_IRQS) | 360 | |
384 | return -EINVAL; | 361 | for (i = 0; i < ARRAY_SIZE(wm831x->irq_masks_cur); i++) { |
385 | 362 | /* If there's been a change in the mask write it back | |
386 | mutex_lock(&wm831x->irq_lock); | 363 | * to the hardware. */ |
387 | 364 | if (wm831x->irq_masks_cur[i] != wm831x->irq_masks_cache[i]) { | |
388 | if (wm831x_irqs[irq].handler) { | 365 | wm831x->irq_masks_cache[i] = wm831x->irq_masks_cur[i]; |
389 | dev_err(wm831x->dev, "Already have handler for IRQ %d\n", irq); | 366 | wm831x_reg_write(wm831x, |
390 | ret = -EINVAL; | 367 | WM831X_INTERRUPT_STATUS_1_MASK + i, |
391 | goto out; | 368 | wm831x->irq_masks_cur[i]); |
369 | } | ||
392 | } | 370 | } |
393 | 371 | ||
394 | wm831x_irqs[irq].handler = handler; | ||
395 | wm831x_irqs[irq].handler_data = dev; | ||
396 | |||
397 | __wm831x_enable_irq(wm831x, irq); | ||
398 | |||
399 | out: | ||
400 | mutex_unlock(&wm831x->irq_lock); | 372 | mutex_unlock(&wm831x->irq_lock); |
401 | |||
402 | return ret; | ||
403 | } | 373 | } |
404 | EXPORT_SYMBOL_GPL(wm831x_request_irq); | ||
405 | 374 | ||
406 | void wm831x_free_irq(struct wm831x *wm831x, unsigned int irq, void *data) | 375 | static void wm831x_irq_unmask(unsigned int irq) |
407 | { | 376 | { |
408 | if (irq < 0 || irq >= WM831X_NUM_IRQS) | 377 | struct wm831x *wm831x = get_irq_chip_data(irq); |
409 | return; | 378 | struct wm831x_irq_data *irq_data = irq_to_wm831x_irq(wm831x, irq); |
410 | |||
411 | mutex_lock(&wm831x->irq_lock); | ||
412 | 379 | ||
413 | wm831x_irqs[irq].handler = NULL; | 380 | wm831x->irq_masks_cur[irq_data->reg - 1] &= ~irq_data->mask; |
414 | wm831x_irqs[irq].handler_data = NULL; | ||
415 | |||
416 | __wm831x_disable_irq(wm831x, irq); | ||
417 | |||
418 | mutex_unlock(&wm831x->irq_lock); | ||
419 | } | 381 | } |
420 | EXPORT_SYMBOL_GPL(wm831x_free_irq); | ||
421 | 382 | ||
422 | 383 | static void wm831x_irq_mask(unsigned int irq) | |
423 | static void wm831x_handle_irq(struct wm831x *wm831x, int irq, int status) | ||
424 | { | 384 | { |
425 | struct wm831x_irq_data *irq_data = &wm831x_irqs[irq]; | 385 | struct wm831x *wm831x = get_irq_chip_data(irq); |
426 | 386 | struct wm831x_irq_data *irq_data = irq_to_wm831x_irq(wm831x, irq); | |
427 | if (irq_data->handler) { | 387 | |
428 | irq_data->handler(irq, irq_data->handler_data); | 388 | wm831x->irq_masks_cur[irq_data->reg - 1] |= irq_data->mask; |
429 | wm831x_reg_write(wm831x, irq_data_to_status_reg(irq_data), | ||
430 | irq_data->mask); | ||
431 | } else { | ||
432 | dev_err(wm831x->dev, "Unhandled IRQ %d, masking\n", irq); | ||
433 | __wm831x_disable_irq(wm831x, irq); | ||
434 | } | ||
435 | } | 389 | } |
436 | 390 | ||
437 | /* Main interrupt handling occurs in a workqueue since we need | 391 | static struct irq_chip wm831x_irq_chip = { |
438 | * interrupts enabled to interact with the chip. */ | 392 | .name = "wm831x", |
439 | static void wm831x_irq_worker(struct work_struct *work) | 393 | .bus_lock = wm831x_irq_lock, |
394 | .bus_sync_unlock = wm831x_irq_sync_unlock, | ||
395 | .mask = wm831x_irq_mask, | ||
396 | .unmask = wm831x_irq_unmask, | ||
397 | }; | ||
398 | |||
399 | /* The processing of the primary interrupt occurs in a thread so that | ||
400 | * we can interact with the device over I2C or SPI. */ | ||
401 | static irqreturn_t wm831x_irq_thread(int irq, void *data) | ||
440 | { | 402 | { |
441 | struct wm831x *wm831x = container_of(work, struct wm831x, irq_work); | 403 | struct wm831x *wm831x = data; |
442 | unsigned int i; | 404 | unsigned int i; |
443 | int primary; | 405 | int primary; |
444 | int status_regs[5]; | 406 | int status_regs[WM831X_NUM_IRQ_REGS] = { 0 }; |
445 | int read[5] = { 0 }; | 407 | int read[WM831X_NUM_IRQ_REGS] = { 0 }; |
446 | int *status; | 408 | int *status; |
447 | 409 | ||
448 | primary = wm831x_reg_read(wm831x, WM831X_SYSTEM_INTERRUPTS); | 410 | primary = wm831x_reg_read(wm831x, WM831X_SYSTEM_INTERRUPTS); |
@@ -452,8 +414,6 @@ static void wm831x_irq_worker(struct work_struct *work) | |||
452 | goto out; | 414 | goto out; |
453 | } | 415 | } |
454 | 416 | ||
455 | mutex_lock(&wm831x->irq_lock); | ||
456 | |||
457 | for (i = 0; i < ARRAY_SIZE(wm831x_irqs); i++) { | 417 | for (i = 0; i < ARRAY_SIZE(wm831x_irqs); i++) { |
458 | int offset = wm831x_irqs[i].reg - 1; | 418 | int offset = wm831x_irqs[i].reg - 1; |
459 | 419 | ||
@@ -471,41 +431,34 @@ static void wm831x_irq_worker(struct work_struct *work) | |||
471 | dev_err(wm831x->dev, | 431 | dev_err(wm831x->dev, |
472 | "Failed to read IRQ status: %d\n", | 432 | "Failed to read IRQ status: %d\n", |
473 | *status); | 433 | *status); |
474 | goto out_lock; | 434 | goto out; |
475 | } | 435 | } |
476 | 436 | ||
477 | /* Mask out the disabled IRQs */ | ||
478 | *status &= ~wm831x->irq_masks[offset]; | ||
479 | read[offset] = 1; | 437 | read[offset] = 1; |
480 | } | 438 | } |
481 | 439 | ||
482 | if (*status & wm831x_irqs[i].mask) | 440 | /* Report it if it isn't masked, or forget the status. */ |
483 | wm831x_handle_irq(wm831x, i, *status); | 441 | if ((*status & ~wm831x->irq_masks_cur[offset]) |
442 | & wm831x_irqs[i].mask) | ||
443 | handle_nested_irq(wm831x->irq_base + i); | ||
444 | else | ||
445 | *status &= ~wm831x_irqs[i].mask; | ||
484 | } | 446 | } |
485 | 447 | ||
486 | out_lock: | ||
487 | mutex_unlock(&wm831x->irq_lock); | ||
488 | out: | 448 | out: |
489 | enable_irq(wm831x->irq); | 449 | for (i = 0; i < ARRAY_SIZE(status_regs); i++) { |
490 | } | 450 | if (status_regs[i]) |
491 | 451 | wm831x_reg_write(wm831x, WM831X_INTERRUPT_STATUS_1 + i, | |
492 | 452 | status_regs[i]); | |
493 | static irqreturn_t wm831x_cpu_irq(int irq, void *data) | 453 | } |
494 | { | ||
495 | struct wm831x *wm831x = data; | ||
496 | |||
497 | /* Shut the interrupt to the CPU up and schedule the actual | ||
498 | * handler; we can't check that the IRQ is asserted. */ | ||
499 | disable_irq_nosync(irq); | ||
500 | |||
501 | queue_work(wm831x->irq_wq, &wm831x->irq_work); | ||
502 | 454 | ||
503 | return IRQ_HANDLED; | 455 | return IRQ_HANDLED; |
504 | } | 456 | } |
505 | 457 | ||
506 | int wm831x_irq_init(struct wm831x *wm831x, int irq) | 458 | int wm831x_irq_init(struct wm831x *wm831x, int irq) |
507 | { | 459 | { |
508 | int i, ret; | 460 | struct wm831x_pdata *pdata = wm831x->dev->platform_data; |
461 | int i, cur_irq, ret; | ||
509 | 462 | ||
510 | mutex_init(&wm831x->irq_lock); | 463 | mutex_init(&wm831x->irq_lock); |
511 | 464 | ||
@@ -515,41 +468,53 @@ int wm831x_irq_init(struct wm831x *wm831x, int irq) | |||
515 | return 0; | 468 | return 0; |
516 | } | 469 | } |
517 | 470 | ||
518 | 471 | if (!pdata || !pdata->irq_base) { | |
519 | wm831x->irq_wq = create_singlethread_workqueue("wm831x-irq"); | 472 | dev_err(wm831x->dev, |
520 | if (!wm831x->irq_wq) { | 473 | "No interrupt base specified, no interrupts\n"); |
521 | dev_err(wm831x->dev, "Failed to allocate IRQ worker\n"); | 474 | return 0; |
522 | return -ESRCH; | ||
523 | } | 475 | } |
524 | 476 | ||
525 | wm831x->irq = irq; | 477 | wm831x->irq = irq; |
526 | INIT_WORK(&wm831x->irq_work, wm831x_irq_worker); | 478 | wm831x->irq_base = pdata->irq_base; |
527 | 479 | ||
528 | /* Mask the individual interrupt sources */ | 480 | /* Mask the individual interrupt sources */ |
529 | for (i = 0; i < ARRAY_SIZE(wm831x->irq_masks); i++) { | 481 | for (i = 0; i < ARRAY_SIZE(wm831x->irq_masks_cur); i++) { |
530 | wm831x->irq_masks[i] = 0xffff; | 482 | wm831x->irq_masks_cur[i] = 0xffff; |
483 | wm831x->irq_masks_cache[i] = 0xffff; | ||
531 | wm831x_reg_write(wm831x, WM831X_INTERRUPT_STATUS_1_MASK + i, | 484 | wm831x_reg_write(wm831x, WM831X_INTERRUPT_STATUS_1_MASK + i, |
532 | 0xffff); | 485 | 0xffff); |
533 | } | 486 | } |
534 | 487 | ||
535 | /* Enable top level interrupts, we mask at secondary level */ | 488 | /* Register them with genirq */ |
536 | wm831x_reg_write(wm831x, WM831X_SYSTEM_INTERRUPTS_MASK, 0); | 489 | for (cur_irq = wm831x->irq_base; |
490 | cur_irq < ARRAY_SIZE(wm831x_irqs) + wm831x->irq_base; | ||
491 | cur_irq++) { | ||
492 | set_irq_chip_data(cur_irq, wm831x); | ||
493 | set_irq_chip_and_handler(cur_irq, &wm831x_irq_chip, | ||
494 | handle_edge_irq); | ||
495 | set_irq_nested_thread(cur_irq, 1); | ||
496 | |||
497 | /* ARM needs us to explicitly flag the IRQ as valid | ||
498 | * and will set them noprobe when we do so. */ | ||
499 | #ifdef CONFIG_ARM | ||
500 | set_irq_flags(cur_irq, IRQF_VALID); | ||
501 | #else | ||
502 | set_irq_noprobe(cur_irq); | ||
503 | #endif | ||
504 | } | ||
537 | 505 | ||
538 | /* We're good to go. We set IRQF_SHARED since there's a | 506 | ret = request_threaded_irq(irq, NULL, wm831x_irq_thread, |
539 | * chance the driver will interoperate with another driver but | 507 | IRQF_TRIGGER_LOW | IRQF_ONESHOT, |
540 | * the need to disable the IRQ while handing via I2C/SPI means | 508 | "wm831x", wm831x); |
541 | * that this may break and performance will be impacted. If | ||
542 | * this does happen it's a hardware design issue and the only | ||
543 | * other alternative would be polling. | ||
544 | */ | ||
545 | ret = request_irq(irq, wm831x_cpu_irq, IRQF_TRIGGER_LOW | IRQF_SHARED, | ||
546 | "wm831x", wm831x); | ||
547 | if (ret != 0) { | 509 | if (ret != 0) { |
548 | dev_err(wm831x->dev, "Failed to request IRQ %d: %d\n", | 510 | dev_err(wm831x->dev, "Failed to request IRQ %d: %d\n", |
549 | irq, ret); | 511 | irq, ret); |
550 | return ret; | 512 | return ret; |
551 | } | 513 | } |
552 | 514 | ||
515 | /* Enable top level interrupts, we mask at secondary level */ | ||
516 | wm831x_reg_write(wm831x, WM831X_SYSTEM_INTERRUPTS_MASK, 0); | ||
517 | |||
553 | return 0; | 518 | return 0; |
554 | } | 519 | } |
555 | 520 | ||
diff --git a/include/linux/mfd/wm831x/core.h b/include/linux/mfd/wm831x/core.h index d01d293a6b25..5184b79c700b 100644 --- a/include/linux/mfd/wm831x/core.h +++ b/include/linux/mfd/wm831x/core.h | |||
@@ -16,7 +16,6 @@ | |||
16 | #define __MFD_WM831X_CORE_H__ | 16 | #define __MFD_WM831X_CORE_H__ |
17 | 17 | ||
18 | #include <linux/interrupt.h> | 18 | #include <linux/interrupt.h> |
19 | #include <linux/workqueue.h> | ||
20 | 19 | ||
21 | /* | 20 | /* |
22 | * Register values. | 21 | * Register values. |
@@ -236,6 +235,8 @@ | |||
236 | 235 | ||
237 | struct regulator_dev; | 236 | struct regulator_dev; |
238 | 237 | ||
238 | #define WM831X_NUM_IRQ_REGS 5 | ||
239 | |||
239 | struct wm831x { | 240 | struct wm831x { |
240 | struct mutex io_lock; | 241 | struct mutex io_lock; |
241 | 242 | ||
@@ -249,10 +250,9 @@ struct wm831x { | |||
249 | 250 | ||
250 | int irq; /* Our chip IRQ */ | 251 | int irq; /* Our chip IRQ */ |
251 | struct mutex irq_lock; | 252 | struct mutex irq_lock; |
252 | struct workqueue_struct *irq_wq; | ||
253 | struct work_struct irq_work; | ||
254 | unsigned int irq_base; | 253 | unsigned int irq_base; |
255 | int irq_masks[5]; | 254 | int irq_masks_cur[WM831X_NUM_IRQ_REGS]; /* Currently active value */ |
255 | int irq_masks_cache[WM831X_NUM_IRQ_REGS]; /* Cached hardware value */ | ||
256 | 256 | ||
257 | int num_gpio; | 257 | int num_gpio; |
258 | 258 | ||
@@ -281,12 +281,30 @@ int wm831x_bulk_read(struct wm831x *wm831x, unsigned short reg, | |||
281 | int wm831x_irq_init(struct wm831x *wm831x, int irq); | 281 | int wm831x_irq_init(struct wm831x *wm831x, int irq); |
282 | void wm831x_irq_exit(struct wm831x *wm831x); | 282 | void wm831x_irq_exit(struct wm831x *wm831x); |
283 | 283 | ||
284 | int __must_check wm831x_request_irq(struct wm831x *wm831x, | 284 | static inline int __must_check wm831x_request_irq(struct wm831x *wm831x, |
285 | unsigned int irq, irq_handler_t handler, | 285 | unsigned int irq, |
286 | unsigned long flags, const char *name, | 286 | irq_handler_t handler, |
287 | void *dev); | 287 | unsigned long flags, |
288 | void wm831x_free_irq(struct wm831x *wm831x, unsigned int, void *); | 288 | const char *name, |
289 | void wm831x_disable_irq(struct wm831x *wm831x, int irq); | 289 | void *dev) |
290 | void wm831x_enable_irq(struct wm831x *wm831x, int irq); | 290 | { |
291 | return request_threaded_irq(irq, NULL, handler, flags, name, dev); | ||
292 | } | ||
293 | |||
294 | static inline void wm831x_free_irq(struct wm831x *wm831x, | ||
295 | unsigned int irq, void *dev) | ||
296 | { | ||
297 | free_irq(irq, dev); | ||
298 | } | ||
299 | |||
300 | static inline void wm831x_disable_irq(struct wm831x *wm831x, int irq) | ||
301 | { | ||
302 | disable_irq(irq); | ||
303 | } | ||
304 | |||
305 | static inline void wm831x_enable_irq(struct wm831x *wm831x, int irq) | ||
306 | { | ||
307 | enable_irq(irq); | ||
308 | } | ||
291 | 309 | ||
292 | #endif | 310 | #endif |
diff --git a/include/linux/mfd/wm831x/pdata.h b/include/linux/mfd/wm831x/pdata.h index 90d820260aad..415c228743d5 100644 --- a/include/linux/mfd/wm831x/pdata.h +++ b/include/linux/mfd/wm831x/pdata.h | |||
@@ -91,6 +91,7 @@ struct wm831x_pdata { | |||
91 | /** Called after subdevices are set up */ | 91 | /** Called after subdevices are set up */ |
92 | int (*post_init)(struct wm831x *wm831x); | 92 | int (*post_init)(struct wm831x *wm831x); |
93 | 93 | ||
94 | int irq_base; | ||
94 | int gpio_base; | 95 | int gpio_base; |
95 | struct wm831x_backlight_pdata *backlight; | 96 | struct wm831x_backlight_pdata *backlight; |
96 | struct wm831x_backup_pdata *backup; | 97 | struct wm831x_backup_pdata *backup; |