Commit dc7c0b6a6d28b0de231728de963ed53a9cee85cf

Authored by Paul Mundt

Merge branch 'viafb-next' of git://github.com/schandinat/linux-2.6

Showing 5 changed files Side-by-side Diff

drivers/video/via/via-core.c
... ... @@ -15,6 +15,9 @@
15 15 #include <linux/module.h>
16 16 #include <linux/interrupt.h>
17 17 #include <linux/platform_device.h>
  18 +#include <linux/list.h>
  19 +#include <linux/pm.h>
  20 +#include <asm/olpc.h>
18 21  
19 22 /*
20 23 * The default port config.
... ... @@ -29,6 +32,19 @@
29 32 };
30 33  
31 34 /*
  35 + * The OLPC XO-1.5 puts the camera power and reset lines onto
  36 + * GPIO 2C.
  37 + */
  38 +static const struct via_port_cfg olpc_adap_configs[] = {
  39 + [VIA_PORT_26] = { VIA_PORT_I2C, VIA_MODE_I2C, VIASR, 0x26 },
  40 + [VIA_PORT_31] = { VIA_PORT_I2C, VIA_MODE_I2C, VIASR, 0x31 },
  41 + [VIA_PORT_25] = { VIA_PORT_GPIO, VIA_MODE_GPIO, VIASR, 0x25 },
  42 + [VIA_PORT_2C] = { VIA_PORT_GPIO, VIA_MODE_GPIO, VIASR, 0x2c },
  43 + [VIA_PORT_3D] = { VIA_PORT_GPIO, VIA_MODE_GPIO, VIASR, 0x3d },
  44 + { 0, 0, 0, 0 }
  45 +};
  46 +
  47 +/*
32 48 * We currently only support one viafb device (will there ever be
33 49 * more than one?), so just declare it globally here.
34 50 */
35 51  
... ... @@ -575,7 +591,79 @@
575 591 }
576 592 }
577 593  
  594 +/*
  595 + * Power management functions
  596 + */
  597 +#ifdef CONFIG_PM
  598 +static LIST_HEAD(viafb_pm_hooks);
  599 +static DEFINE_MUTEX(viafb_pm_hooks_lock);
578 600  
  601 +void viafb_pm_register(struct viafb_pm_hooks *hooks)
  602 +{
  603 + INIT_LIST_HEAD(&hooks->list);
  604 +
  605 + mutex_lock(&viafb_pm_hooks_lock);
  606 + list_add_tail(&hooks->list, &viafb_pm_hooks);
  607 + mutex_unlock(&viafb_pm_hooks_lock);
  608 +}
  609 +EXPORT_SYMBOL_GPL(viafb_pm_register);
  610 +
  611 +void viafb_pm_unregister(struct viafb_pm_hooks *hooks)
  612 +{
  613 + mutex_lock(&viafb_pm_hooks_lock);
  614 + list_del(&hooks->list);
  615 + mutex_unlock(&viafb_pm_hooks_lock);
  616 +}
  617 +EXPORT_SYMBOL_GPL(viafb_pm_unregister);
  618 +
  619 +static int via_suspend(struct pci_dev *pdev, pm_message_t state)
  620 +{
  621 + struct viafb_pm_hooks *hooks;
  622 +
  623 + if (state.event != PM_EVENT_SUSPEND)
  624 + return 0;
  625 + /*
  626 + * "I've occasionally hit a few drivers that caused suspend
  627 + * failures, and each and every time it was a driver bug, and
  628 + * the right thing to do was to just ignore the error and suspend
  629 + * anyway - returning an error code and trying to undo the suspend
  630 + * is not what anybody ever really wants, even if our model
  631 + *_allows_ for it."
  632 + * -- Linus Torvalds, Dec. 7, 2009
  633 + */
  634 + mutex_lock(&viafb_pm_hooks_lock);
  635 + list_for_each_entry_reverse(hooks, &viafb_pm_hooks, list)
  636 + hooks->suspend(hooks->private);
  637 + mutex_unlock(&viafb_pm_hooks_lock);
  638 +
  639 + pci_save_state(pdev);
  640 + pci_disable_device(pdev);
  641 + pci_set_power_state(pdev, pci_choose_state(pdev, state));
  642 + return 0;
  643 +}
  644 +
  645 +static int via_resume(struct pci_dev *pdev)
  646 +{
  647 + struct viafb_pm_hooks *hooks;
  648 +
  649 + /* Get the bus side powered up */
  650 + pci_set_power_state(pdev, PCI_D0);
  651 + pci_restore_state(pdev);
  652 + if (pci_enable_device(pdev))
  653 + return 0;
  654 +
  655 + pci_set_master(pdev);
  656 +
  657 + /* Now bring back any subdevs */
  658 + mutex_lock(&viafb_pm_hooks_lock);
  659 + list_for_each_entry(hooks, &viafb_pm_hooks, list)
  660 + hooks->resume(hooks->private);
  661 + mutex_unlock(&viafb_pm_hooks_lock);
  662 +
  663 + return 0;
  664 +}
  665 +#endif /* CONFIG_PM */
  666 +
579 667 static int __devinit via_pci_probe(struct pci_dev *pdev,
580 668 const struct pci_device_id *ent)
581 669 {
... ... @@ -584,6 +672,7 @@
584 672 ret = pci_enable_device(pdev);
585 673 if (ret)
586 674 return ret;
  675 +
587 676 /*
588 677 * Global device initialization.
589 678 */
... ... @@ -591,6 +680,9 @@
591 680 global_dev.pdev = pdev;
592 681 global_dev.chip_type = ent->driver_data;
593 682 global_dev.port_cfg = adap_configs;
  683 + if (machine_is_olpc())
  684 + global_dev.port_cfg = olpc_adap_configs;
  685 +
594 686 spin_lock_init(&global_dev.reg_lock);
595 687 ret = via_pci_setup_mmio(&global_dev);
596 688 if (ret)
... ... @@ -663,8 +755,8 @@
663 755 .probe = via_pci_probe,
664 756 .remove = __devexit_p(via_pci_remove),
665 757 #ifdef CONFIG_PM
666   - .suspend = viafb_suspend,
667   - .resume = viafb_resume,
  758 + .suspend = via_suspend,
  759 + .resume = via_resume,
668 760 #endif
669 761 };
670 762  
drivers/video/via/via-gpio.c
... ... @@ -172,6 +172,28 @@
172 172 via_write_reg_mask(VIASR, gpio->vg_port_index, 0, 0x02);
173 173 }
174 174  
  175 +#ifdef CONFIG_PM
  176 +
  177 +static int viafb_gpio_suspend(void *private)
  178 +{
  179 + return 0;
  180 +}
  181 +
  182 +static int viafb_gpio_resume(void *private)
  183 +{
  184 + int i;
  185 +
  186 + for (i = 0; i < gpio_config.gpio_chip.ngpio; i += 2)
  187 + viafb_gpio_enable(gpio_config.active_gpios[i]);
  188 + return 0;
  189 +}
  190 +
  191 +static struct viafb_pm_hooks viafb_gpio_pm_hooks = {
  192 + .suspend = viafb_gpio_suspend,
  193 + .resume = viafb_gpio_resume
  194 +};
  195 +#endif /* CONFIG_PM */
  196 +
175 197 /*
176 198 * Look up a specific gpio and return the number it was assigned.
177 199 */
... ... @@ -236,6 +258,9 @@
236 258 printk(KERN_ERR "viafb: failed to add gpios (%d)\n", ret);
237 259 gpio_config.gpio_chip.ngpio = 0;
238 260 }
  261 +#ifdef CONFIG_PM
  262 + viafb_pm_register(&viafb_gpio_pm_hooks);
  263 +#endif
239 264 return ret;
240 265 }
241 266  
... ... @@ -244,6 +269,10 @@
244 269 {
245 270 unsigned long flags;
246 271 int ret = 0, i;
  272 +
  273 +#ifdef CONFIG_PM
  274 + viafb_pm_unregister(&viafb_gpio_pm_hooks);
  275 +#endif
247 276  
248 277 /*
249 278 * Get unregistered.
drivers/video/via/viafbdev.c
... ... @@ -1672,31 +1672,19 @@
1672 1672  
1673 1673  
1674 1674 #ifdef CONFIG_PM
1675   -int viafb_suspend(struct pci_dev *pdev, pm_message_t state)
  1675 +static int viafb_suspend(void *unused)
1676 1676 {
1677   - if (state.event == PM_EVENT_SUSPEND) {
1678   - acquire_console_sem();
1679   - fb_set_suspend(viafbinfo, 1);
  1677 + acquire_console_sem();
  1678 + fb_set_suspend(viafbinfo, 1);
  1679 + viafb_sync(viafbinfo);
  1680 + release_console_sem();
1680 1681  
1681   - viafb_sync(viafbinfo);
1682   -
1683   - pci_save_state(pdev);
1684   - pci_disable_device(pdev);
1685   - pci_set_power_state(pdev, pci_choose_state(pdev, state));
1686   - release_console_sem();
1687   - }
1688   -
1689 1682 return 0;
1690 1683 }
1691 1684  
1692   -int viafb_resume(struct pci_dev *pdev)
  1685 +static int viafb_resume(void *unused)
1693 1686 {
1694 1687 acquire_console_sem();
1695   - pci_set_power_state(pdev, PCI_D0);
1696   - pci_restore_state(pdev);
1697   - if (pci_enable_device(pdev))
1698   - goto fail;
1699   - pci_set_master(pdev);
1700 1688 if (viaparinfo->shared->vdev->engine_mmio)
1701 1689 viafb_reset_engine(viaparinfo);
1702 1690 viafb_set_par(viafbinfo);
1703 1691  
... ... @@ -1704,11 +1692,15 @@
1704 1692 viafb_set_par(viafbinfo1);
1705 1693 fb_set_suspend(viafbinfo, 0);
1706 1694  
1707   -fail:
1708 1695 release_console_sem();
1709 1696 return 0;
1710 1697 }
1711 1698  
  1699 +static struct viafb_pm_hooks viafb_fb_pm_hooks = {
  1700 + .suspend = viafb_suspend,
  1701 + .resume = viafb_resume
  1702 +};
  1703 +
1712 1704 #endif
1713 1705  
1714 1706  
... ... @@ -1899,6 +1891,10 @@
1899 1891  
1900 1892 viafb_init_proc(viaparinfo->shared);
1901 1893 viafb_init_dac(IGA2);
  1894 +
  1895 +#ifdef CONFIG_PM
  1896 + viafb_pm_register(&viafb_fb_pm_hooks);
  1897 +#endif
1902 1898 return 0;
1903 1899  
1904 1900 out_fb_unreg:
drivers/video/via/viafbdev.h
... ... @@ -108,7 +108,5 @@
108 108 /* Temporary */
109 109 int viafb_init(void);
110 110 void viafb_exit(void);
111   -int viafb_suspend(struct pci_dev *pdev, pm_message_t state);
112   -int viafb_resume(struct pci_dev *pdev);
113 111 #endif /* __VIAFBDEV_H__ */
include/linux/via-core.h
... ... @@ -60,6 +60,21 @@
60 60 };
61 61  
62 62 /*
  63 + * Allow subdevs to register suspend/resume hooks.
  64 + */
  65 +#ifdef CONFIG_PM
  66 +struct viafb_pm_hooks {
  67 + struct list_head list;
  68 + int (*suspend)(void *private);
  69 + int (*resume)(void *private);
  70 + void *private;
  71 +};
  72 +
  73 +void viafb_pm_register(struct viafb_pm_hooks *hooks);
  74 +void viafb_pm_unregister(struct viafb_pm_hooks *hooks);
  75 +#endif /* CONFIG_PM */
  76 +
  77 +/*
63 78 * This is the global viafb "device" containing stuff needed by
64 79 * all subdevs.
65 80 */