Loading drivers/video/via/via-core.c +94 −2 Original line number Diff line number Diff line Loading @@ -15,6 +15,9 @@ #include <linux/module.h> #include <linux/interrupt.h> #include <linux/platform_device.h> #include <linux/list.h> #include <linux/pm.h> #include <asm/olpc.h> /* * The default port config. Loading @@ -28,6 +31,19 @@ static struct via_port_cfg adap_configs[] = { { 0, 0, 0, 0 } }; /* * The OLPC XO-1.5 puts the camera power and reset lines onto * GPIO 2C. */ static const struct via_port_cfg olpc_adap_configs[] = { [VIA_PORT_26] = { VIA_PORT_I2C, VIA_MODE_I2C, VIASR, 0x26 }, [VIA_PORT_31] = { VIA_PORT_I2C, VIA_MODE_I2C, VIASR, 0x31 }, [VIA_PORT_25] = { VIA_PORT_GPIO, VIA_MODE_GPIO, VIASR, 0x25 }, [VIA_PORT_2C] = { VIA_PORT_GPIO, VIA_MODE_GPIO, VIASR, 0x2c }, [VIA_PORT_3D] = { VIA_PORT_GPIO, VIA_MODE_GPIO, VIASR, 0x3d }, { 0, 0, 0, 0 } }; /* * We currently only support one viafb device (will there ever be * more than one?), so just declare it globally here. Loading Loading @@ -575,6 +591,78 @@ static void via_teardown_subdevs(void) } } /* * Power management functions */ #ifdef CONFIG_PM static LIST_HEAD(viafb_pm_hooks); static DEFINE_MUTEX(viafb_pm_hooks_lock); void viafb_pm_register(struct viafb_pm_hooks *hooks) { INIT_LIST_HEAD(&hooks->list); mutex_lock(&viafb_pm_hooks_lock); list_add_tail(&hooks->list, &viafb_pm_hooks); mutex_unlock(&viafb_pm_hooks_lock); } EXPORT_SYMBOL_GPL(viafb_pm_register); void viafb_pm_unregister(struct viafb_pm_hooks *hooks) { mutex_lock(&viafb_pm_hooks_lock); list_del(&hooks->list); mutex_unlock(&viafb_pm_hooks_lock); } EXPORT_SYMBOL_GPL(viafb_pm_unregister); static int via_suspend(struct pci_dev *pdev, pm_message_t state) { struct viafb_pm_hooks *hooks; if (state.event != PM_EVENT_SUSPEND) return 0; /* * "I've occasionally hit a few drivers that caused suspend * failures, and each and every time it was a driver bug, and * the right thing to do was to just ignore the error and suspend * anyway - returning an error code and trying to undo the suspend * is not what anybody ever really wants, even if our model *_allows_ for it." * -- Linus Torvalds, Dec. 7, 2009 */ mutex_lock(&viafb_pm_hooks_lock); list_for_each_entry_reverse(hooks, &viafb_pm_hooks, list) hooks->suspend(hooks->private); mutex_unlock(&viafb_pm_hooks_lock); pci_save_state(pdev); pci_disable_device(pdev); pci_set_power_state(pdev, pci_choose_state(pdev, state)); return 0; } static int via_resume(struct pci_dev *pdev) { struct viafb_pm_hooks *hooks; /* Get the bus side powered up */ pci_set_power_state(pdev, PCI_D0); pci_restore_state(pdev); if (pci_enable_device(pdev)) return 0; pci_set_master(pdev); /* Now bring back any subdevs */ mutex_lock(&viafb_pm_hooks_lock); list_for_each_entry(hooks, &viafb_pm_hooks, list) hooks->resume(hooks->private); mutex_unlock(&viafb_pm_hooks_lock); return 0; } #endif /* CONFIG_PM */ static int __devinit via_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) Loading @@ -584,6 +672,7 @@ static int __devinit via_pci_probe(struct pci_dev *pdev, ret = pci_enable_device(pdev); if (ret) return ret; /* * Global device initialization. */ Loading @@ -591,6 +680,9 @@ static int __devinit via_pci_probe(struct pci_dev *pdev, global_dev.pdev = pdev; global_dev.chip_type = ent->driver_data; global_dev.port_cfg = adap_configs; if (machine_is_olpc()) global_dev.port_cfg = olpc_adap_configs; spin_lock_init(&global_dev.reg_lock); ret = via_pci_setup_mmio(&global_dev); if (ret) Loading Loading @@ -663,8 +755,8 @@ static struct pci_driver via_driver = { .probe = via_pci_probe, .remove = __devexit_p(via_pci_remove), #ifdef CONFIG_PM .suspend = viafb_suspend, .resume = viafb_resume, .suspend = via_suspend, .resume = via_resume, #endif }; Loading drivers/video/via/via-gpio.c +29 −0 Original line number Diff line number Diff line Loading @@ -172,6 +172,28 @@ static void viafb_gpio_disable(struct viafb_gpio *gpio) via_write_reg_mask(VIASR, gpio->vg_port_index, 0, 0x02); } #ifdef CONFIG_PM static int viafb_gpio_suspend(void *private) { return 0; } static int viafb_gpio_resume(void *private) { int i; for (i = 0; i < gpio_config.gpio_chip.ngpio; i += 2) viafb_gpio_enable(gpio_config.active_gpios[i]); return 0; } static struct viafb_pm_hooks viafb_gpio_pm_hooks = { .suspend = viafb_gpio_suspend, .resume = viafb_gpio_resume }; #endif /* CONFIG_PM */ /* * Look up a specific gpio and return the number it was assigned. */ Loading Loading @@ -236,6 +258,9 @@ static __devinit int viafb_gpio_probe(struct platform_device *platdev) printk(KERN_ERR "viafb: failed to add gpios (%d)\n", ret); gpio_config.gpio_chip.ngpio = 0; } #ifdef CONFIG_PM viafb_pm_register(&viafb_gpio_pm_hooks); #endif return ret; } Loading @@ -245,6 +270,10 @@ static int viafb_gpio_remove(struct platform_device *platdev) unsigned long flags; int ret = 0, i; #ifdef CONFIG_PM viafb_pm_unregister(&viafb_gpio_pm_hooks); #endif /* * Get unregistered. */ Loading drivers/video/via/viafbdev.c +15 −19 Original line number Diff line number Diff line Loading @@ -1672,31 +1672,19 @@ static int parse_mode(const char *str, u32 *xres, u32 *yres) #ifdef CONFIG_PM int viafb_suspend(struct pci_dev *pdev, pm_message_t state) static int viafb_suspend(void *unused) { if (state.event == PM_EVENT_SUSPEND) { acquire_console_sem(); fb_set_suspend(viafbinfo, 1); viafb_sync(viafbinfo); pci_save_state(pdev); pci_disable_device(pdev); pci_set_power_state(pdev, pci_choose_state(pdev, state)); release_console_sem(); } return 0; } int viafb_resume(struct pci_dev *pdev) static int viafb_resume(void *unused) { acquire_console_sem(); pci_set_power_state(pdev, PCI_D0); pci_restore_state(pdev); if (pci_enable_device(pdev)) goto fail; pci_set_master(pdev); if (viaparinfo->shared->vdev->engine_mmio) viafb_reset_engine(viaparinfo); viafb_set_par(viafbinfo); Loading @@ -1704,11 +1692,15 @@ int viafb_resume(struct pci_dev *pdev) viafb_set_par(viafbinfo1); fb_set_suspend(viafbinfo, 0); fail: release_console_sem(); return 0; } static struct viafb_pm_hooks viafb_fb_pm_hooks = { .suspend = viafb_suspend, .resume = viafb_resume }; #endif Loading Loading @@ -1899,6 +1891,10 @@ int __devinit via_fb_pci_probe(struct viafb_dev *vdev) viafb_init_proc(viaparinfo->shared); viafb_init_dac(IGA2); #ifdef CONFIG_PM viafb_pm_register(&viafb_fb_pm_hooks); #endif return 0; out_fb_unreg: Loading drivers/video/via/viafbdev.h +0 −2 Original line number Diff line number Diff line Loading @@ -108,6 +108,4 @@ void via_fb_pci_remove(struct pci_dev *pdev); /* Temporary */ int viafb_init(void); void viafb_exit(void); int viafb_suspend(struct pci_dev *pdev, pm_message_t state); int viafb_resume(struct pci_dev *pdev); #endif /* __VIAFBDEV_H__ */ include/linux/via-core.h +15 −0 Original line number Diff line number Diff line Loading @@ -59,6 +59,21 @@ struct via_port_cfg { u8 ioport_index; }; /* * Allow subdevs to register suspend/resume hooks. */ #ifdef CONFIG_PM struct viafb_pm_hooks { struct list_head list; int (*suspend)(void *private); int (*resume)(void *private); void *private; }; void viafb_pm_register(struct viafb_pm_hooks *hooks); void viafb_pm_unregister(struct viafb_pm_hooks *hooks); #endif /* CONFIG_PM */ /* * This is the global viafb "device" containing stuff needed by * all subdevs. Loading Loading
drivers/video/via/via-core.c +94 −2 Original line number Diff line number Diff line Loading @@ -15,6 +15,9 @@ #include <linux/module.h> #include <linux/interrupt.h> #include <linux/platform_device.h> #include <linux/list.h> #include <linux/pm.h> #include <asm/olpc.h> /* * The default port config. Loading @@ -28,6 +31,19 @@ static struct via_port_cfg adap_configs[] = { { 0, 0, 0, 0 } }; /* * The OLPC XO-1.5 puts the camera power and reset lines onto * GPIO 2C. */ static const struct via_port_cfg olpc_adap_configs[] = { [VIA_PORT_26] = { VIA_PORT_I2C, VIA_MODE_I2C, VIASR, 0x26 }, [VIA_PORT_31] = { VIA_PORT_I2C, VIA_MODE_I2C, VIASR, 0x31 }, [VIA_PORT_25] = { VIA_PORT_GPIO, VIA_MODE_GPIO, VIASR, 0x25 }, [VIA_PORT_2C] = { VIA_PORT_GPIO, VIA_MODE_GPIO, VIASR, 0x2c }, [VIA_PORT_3D] = { VIA_PORT_GPIO, VIA_MODE_GPIO, VIASR, 0x3d }, { 0, 0, 0, 0 } }; /* * We currently only support one viafb device (will there ever be * more than one?), so just declare it globally here. Loading Loading @@ -575,6 +591,78 @@ static void via_teardown_subdevs(void) } } /* * Power management functions */ #ifdef CONFIG_PM static LIST_HEAD(viafb_pm_hooks); static DEFINE_MUTEX(viafb_pm_hooks_lock); void viafb_pm_register(struct viafb_pm_hooks *hooks) { INIT_LIST_HEAD(&hooks->list); mutex_lock(&viafb_pm_hooks_lock); list_add_tail(&hooks->list, &viafb_pm_hooks); mutex_unlock(&viafb_pm_hooks_lock); } EXPORT_SYMBOL_GPL(viafb_pm_register); void viafb_pm_unregister(struct viafb_pm_hooks *hooks) { mutex_lock(&viafb_pm_hooks_lock); list_del(&hooks->list); mutex_unlock(&viafb_pm_hooks_lock); } EXPORT_SYMBOL_GPL(viafb_pm_unregister); static int via_suspend(struct pci_dev *pdev, pm_message_t state) { struct viafb_pm_hooks *hooks; if (state.event != PM_EVENT_SUSPEND) return 0; /* * "I've occasionally hit a few drivers that caused suspend * failures, and each and every time it was a driver bug, and * the right thing to do was to just ignore the error and suspend * anyway - returning an error code and trying to undo the suspend * is not what anybody ever really wants, even if our model *_allows_ for it." * -- Linus Torvalds, Dec. 7, 2009 */ mutex_lock(&viafb_pm_hooks_lock); list_for_each_entry_reverse(hooks, &viafb_pm_hooks, list) hooks->suspend(hooks->private); mutex_unlock(&viafb_pm_hooks_lock); pci_save_state(pdev); pci_disable_device(pdev); pci_set_power_state(pdev, pci_choose_state(pdev, state)); return 0; } static int via_resume(struct pci_dev *pdev) { struct viafb_pm_hooks *hooks; /* Get the bus side powered up */ pci_set_power_state(pdev, PCI_D0); pci_restore_state(pdev); if (pci_enable_device(pdev)) return 0; pci_set_master(pdev); /* Now bring back any subdevs */ mutex_lock(&viafb_pm_hooks_lock); list_for_each_entry(hooks, &viafb_pm_hooks, list) hooks->resume(hooks->private); mutex_unlock(&viafb_pm_hooks_lock); return 0; } #endif /* CONFIG_PM */ static int __devinit via_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) Loading @@ -584,6 +672,7 @@ static int __devinit via_pci_probe(struct pci_dev *pdev, ret = pci_enable_device(pdev); if (ret) return ret; /* * Global device initialization. */ Loading @@ -591,6 +680,9 @@ static int __devinit via_pci_probe(struct pci_dev *pdev, global_dev.pdev = pdev; global_dev.chip_type = ent->driver_data; global_dev.port_cfg = adap_configs; if (machine_is_olpc()) global_dev.port_cfg = olpc_adap_configs; spin_lock_init(&global_dev.reg_lock); ret = via_pci_setup_mmio(&global_dev); if (ret) Loading Loading @@ -663,8 +755,8 @@ static struct pci_driver via_driver = { .probe = via_pci_probe, .remove = __devexit_p(via_pci_remove), #ifdef CONFIG_PM .suspend = viafb_suspend, .resume = viafb_resume, .suspend = via_suspend, .resume = via_resume, #endif }; Loading
drivers/video/via/via-gpio.c +29 −0 Original line number Diff line number Diff line Loading @@ -172,6 +172,28 @@ static void viafb_gpio_disable(struct viafb_gpio *gpio) via_write_reg_mask(VIASR, gpio->vg_port_index, 0, 0x02); } #ifdef CONFIG_PM static int viafb_gpio_suspend(void *private) { return 0; } static int viafb_gpio_resume(void *private) { int i; for (i = 0; i < gpio_config.gpio_chip.ngpio; i += 2) viafb_gpio_enable(gpio_config.active_gpios[i]); return 0; } static struct viafb_pm_hooks viafb_gpio_pm_hooks = { .suspend = viafb_gpio_suspend, .resume = viafb_gpio_resume }; #endif /* CONFIG_PM */ /* * Look up a specific gpio and return the number it was assigned. */ Loading Loading @@ -236,6 +258,9 @@ static __devinit int viafb_gpio_probe(struct platform_device *platdev) printk(KERN_ERR "viafb: failed to add gpios (%d)\n", ret); gpio_config.gpio_chip.ngpio = 0; } #ifdef CONFIG_PM viafb_pm_register(&viafb_gpio_pm_hooks); #endif return ret; } Loading @@ -245,6 +270,10 @@ static int viafb_gpio_remove(struct platform_device *platdev) unsigned long flags; int ret = 0, i; #ifdef CONFIG_PM viafb_pm_unregister(&viafb_gpio_pm_hooks); #endif /* * Get unregistered. */ Loading
drivers/video/via/viafbdev.c +15 −19 Original line number Diff line number Diff line Loading @@ -1672,31 +1672,19 @@ static int parse_mode(const char *str, u32 *xres, u32 *yres) #ifdef CONFIG_PM int viafb_suspend(struct pci_dev *pdev, pm_message_t state) static int viafb_suspend(void *unused) { if (state.event == PM_EVENT_SUSPEND) { acquire_console_sem(); fb_set_suspend(viafbinfo, 1); viafb_sync(viafbinfo); pci_save_state(pdev); pci_disable_device(pdev); pci_set_power_state(pdev, pci_choose_state(pdev, state)); release_console_sem(); } return 0; } int viafb_resume(struct pci_dev *pdev) static int viafb_resume(void *unused) { acquire_console_sem(); pci_set_power_state(pdev, PCI_D0); pci_restore_state(pdev); if (pci_enable_device(pdev)) goto fail; pci_set_master(pdev); if (viaparinfo->shared->vdev->engine_mmio) viafb_reset_engine(viaparinfo); viafb_set_par(viafbinfo); Loading @@ -1704,11 +1692,15 @@ int viafb_resume(struct pci_dev *pdev) viafb_set_par(viafbinfo1); fb_set_suspend(viafbinfo, 0); fail: release_console_sem(); return 0; } static struct viafb_pm_hooks viafb_fb_pm_hooks = { .suspend = viafb_suspend, .resume = viafb_resume }; #endif Loading Loading @@ -1899,6 +1891,10 @@ int __devinit via_fb_pci_probe(struct viafb_dev *vdev) viafb_init_proc(viaparinfo->shared); viafb_init_dac(IGA2); #ifdef CONFIG_PM viafb_pm_register(&viafb_fb_pm_hooks); #endif return 0; out_fb_unreg: Loading
drivers/video/via/viafbdev.h +0 −2 Original line number Diff line number Diff line Loading @@ -108,6 +108,4 @@ void via_fb_pci_remove(struct pci_dev *pdev); /* Temporary */ int viafb_init(void); void viafb_exit(void); int viafb_suspend(struct pci_dev *pdev, pm_message_t state); int viafb_resume(struct pci_dev *pdev); #endif /* __VIAFBDEV_H__ */
include/linux/via-core.h +15 −0 Original line number Diff line number Diff line Loading @@ -59,6 +59,21 @@ struct via_port_cfg { u8 ioport_index; }; /* * Allow subdevs to register suspend/resume hooks. */ #ifdef CONFIG_PM struct viafb_pm_hooks { struct list_head list; int (*suspend)(void *private); int (*resume)(void *private); void *private; }; void viafb_pm_register(struct viafb_pm_hooks *hooks); void viafb_pm_unregister(struct viafb_pm_hooks *hooks); #endif /* CONFIG_PM */ /* * This is the global viafb "device" containing stuff needed by * all subdevs. Loading