Merge branch 'viafb-next' of git://github.com/schandinat/linux-2.6
authorPaul Mundt <lethal@linux-sh.org>
Wed, 10 Nov 2010 03:04:41 +0000 (12:04 +0900)
committerPaul Mundt <lethal@linux-sh.org>
Wed, 10 Nov 2010 03:04:41 +0000 (12:04 +0900)
1  2 
drivers/video/via/via-core.c
include/linux/via-core.h

@@@ -15,6 -15,9 +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.
@@@ -28,6 -31,19 +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.
@@@ -94,13 -110,6 +110,13 @@@ void viafb_irq_disable(u32 mask
  EXPORT_SYMBOL_GPL(viafb_irq_disable);
  
  /* ---------------------------------------------------------------------- */
 +/*
 + * Currently, the camera driver is the only user of the DMA code, so we
 + * only compile it in if the camera driver is being built.  Chances are,
 + * most viafb systems will not need to have this extra code for a while.
 + * As soon as another user comes long, the ifdef can be removed.
 + */
 +#if defined(CONFIG_VIDEO_VIA_CAMERA) || defined(CONFIG_VIDEO_VIA_CAMERA_MODULE)
  /*
   * Access to the DMA engine.  This currently provides what the camera
   * driver needs (i.e. outgoing only) but is easily expandable if need
@@@ -329,7 -338,7 +345,7 @@@ int viafb_dma_copy_out_sg(unsigned int 
        return 0;
  }
  EXPORT_SYMBOL_GPL(viafb_dma_copy_out_sg);
 -
 +#endif /* CONFIG_VIDEO_VIA_CAMERA */
  
  /* ---------------------------------------------------------------------- */
  /*
@@@ -518,12 -527,7 +534,12 @@@ static struct viafb_subdev_info 
        },
        {
                .name = "viafb-i2c",
 -      }
 +      },
 +#if defined(CONFIG_VIDEO_VIA_CAMERA) || defined(CONFIG_VIDEO_VIA_CAMERA_MODULE)
 +      {
 +              .name = "viafb-camera",
 +      },
 +#endif
  };
  #define N_SUBDEVS ARRAY_SIZE(viafb_subdevs)
  
@@@ -575,6 -579,78 +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)
        ret = pci_enable_device(pdev);
        if (ret)
                return ret;
        /*
         * Global device initialization.
         */
        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)
@@@ -663,8 -743,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
  };
  
diff --combined include/linux/via-core.h
@@@ -59,6 -59,21 +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.
@@@ -81,7 -96,7 +96,7 @@@ struct viafb_dev 
        unsigned long fbmem_start;
        long fbmem_len;
        void __iomem *fbmem;
 -#if defined(CONFIG_FB_VIA_CAMERA) || defined(CONFIG_FB_VIA_CAMERA_MODULE)
 +#if defined(CONFIG_VIDEO_VIA_CAMERA) || defined(CONFIG_VIDEO_VIA_CAMERA_MODULE)
        long camera_fbmem_offset;
        long camera_fbmem_size;
  #endif
@@@ -138,7 -153,6 +153,7 @@@ void viafb_irq_disable(u32 mask)
  #define   VDE_I_LVDSSIEN  0x40000000  /* LVDS Sense enable */
  #define   VDE_I_ENABLE          0x80000000  /* Global interrupt enable */
  
 +#if defined(CONFIG_VIDEO_VIA_CAMERA) || defined(CONFIG_VIDEO_VIA_CAMERA_MODULE)
  /*
   * DMA management.
   */
@@@ -173,7 -187,6 +188,7 @@@ int viafb_dma_copy_out_sg(unsigned int 
   */
  #define VGA_WIDTH     640
  #define VGA_HEIGHT    480
 +#endif /* CONFIG_VIDEO_VIA_CAMERA */
  
  /*
   * Indexed port operations.  Note that these are all multi-op