]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/lethal/fbdev...
authorFlorian Tobias Schandinat <FlorianSchandinat@gmx.de>
Mon, 29 Aug 2011 09:14:30 +0000 (09:14 +0000)
committerFlorian Tobias Schandinat <FlorianSchandinat@gmx.de>
Mon, 29 Aug 2011 09:14:30 +0000 (09:14 +0000)
Conflicts:
drivers/video/atmel_lcdfb.c

1  2 
arch/powerpc/platforms/85xx/p1022_ds.c
arch/powerpc/platforms/86xx/mpc8610_hpcd.c
arch/powerpc/sysdev/fsl_soc.h
drivers/video/Kconfig
drivers/video/backlight/adp8860_bl.c
drivers/video/controlfb.c
drivers/video/fb_defio.c
drivers/video/msm/mdp.c
drivers/video/platinumfb.c
drivers/video/udlfb.c
drivers/video/via/viafbdev.c

index 266b3aadfe5e2671d9ab11d1100dfcfcef52829b,a13d3cce413c7014453f05e3de670e3210ce3753..c01c7277888c1e3655fddd6be2dfe2da21705182
@@@ -93,8 -93,8 +93,8 @@@
   * The Area Descriptor is a 32-bit value that determine which bits in each
   * pixel are to be used for each color.
   */
- static unsigned int p1022ds_get_pixel_format(unsigned int bits_per_pixel,
-       int monitor_port)
+ static u32 p1022ds_get_pixel_format(enum fsl_diu_monitor_port port,
+                                   unsigned int bits_per_pixel)
  {
        switch (bits_per_pixel) {
        case 32:
   * On some boards, the gamma table for some ports may need to be modified.
   * This is not the case on the P1022DS, so we do nothing.
  */
- static void p1022ds_set_gamma_table(int monitor_port, char *gamma_table_base)
+ static void p1022ds_set_gamma_table(enum fsl_diu_monitor_port port,
+                                   char *gamma_table_base)
  {
  }
  
   * p1022ds_set_monitor_port: switch the output to a different monitor port
   *
   */
- static void p1022ds_set_monitor_port(int monitor_port)
+ static void p1022ds_set_monitor_port(enum fsl_diu_monitor_port port)
  {
        struct device_node *pixis_node;
 +      void __iomem *pixis;
        u8 __iomem *brdcfg1;
  
        pixis_node = of_find_compatible_node(NULL, NULL, "fsl,p1022ds-pixis");
                return;
        }
  
 -      brdcfg1 = of_iomap(pixis_node, 0);
 -      if (!brdcfg1) {
 +      pixis = of_iomap(pixis_node, 0);
 +      if (!pixis) {
                pr_err("p1022ds: could not map ngPIXIS registers\n");
                return;
        }
 -      brdcfg1 += 9;   /* BRDCFG1 is at offset 9 in the ngPIXIS */
 +      brdcfg1 = pixis + 9;    /* BRDCFG1 is at offset 9 in the ngPIXIS */
  
-       switch (monitor_port) {
-       case 0: /* DVI */
+       switch (port) {
+       case FSL_DIU_PORT_DVI:
+               printk(KERN_INFO "%s:%u\n", __func__, __LINE__);
                /* Enable the DVI port, disable the DFP and the backlight */
                clrsetbits_8(brdcfg1, PX_BRDCFG1_DFPEN | PX_BRDCFG1_BACKLIGHT,
                             PX_BRDCFG1_DVIEN);
                break;
-       case 1: /* Single link LVDS */
+       case FSL_DIU_PORT_LVDS:
+               printk(KERN_INFO "%s:%u\n", __func__, __LINE__);
                /* Enable the DFP port, disable the DVI and the backlight */
                clrsetbits_8(brdcfg1, PX_BRDCFG1_DVIEN | PX_BRDCFG1_BACKLIGHT,
                             PX_BRDCFG1_DFPEN);
                break;
        default:
-               pr_err("p1022ds: unsupported monitor port %i\n", monitor_port);
+               pr_err("p1022ds: unsupported monitor port %i\n", port);
        }
 +
 +      iounmap(pixis);
  }
  
  /**
@@@ -195,13 -195,8 +198,13 @@@ void p1022ds_set_pixel_clock(unsigned i
        do_div(temp, pixclock);
        freq = temp;
  
 -      /* pixclk is the ratio of the platform clock to the pixel clock */
 +      /*
 +       * 'pxclk' is the ratio of the platform clock to the pixel clock.
 +       * This number is programmed into the CLKDVDR register, and the valid
 +       * range of values is 2-255.
 +       */
        pxclk = DIV_ROUND_CLOSEST(fsl_get_sys_freq(), freq);
 +      pxclk = clamp_t(u32, pxclk, 2, 255);
  
        /* Disable the pixel clock, and set it to non-inverted and no delay */
        clrbits32(&guts->clkdvdr,
  
        /* Enable the clock and set the pxclk */
        setbits32(&guts->clkdvdr, CLKDVDR_PXCKEN | (pxclk << 16));
 +
 +      iounmap(guts);
  }
  
  /**
-  * p1022ds_show_monitor_port: show the current monitor
-  *
-  * This function returns a string indicating whether the current monitor is
-  * set to DVI or LVDS.
-  */
- ssize_t p1022ds_show_monitor_port(int monitor_port, char *buf)
- {
-       return sprintf(buf, "%c0 - DVI\n%c1 - Single link LVDS\n",
-               monitor_port == 0 ? '*' : ' ', monitor_port == 1 ? '*' : ' ');
- }
- /**
-  * p1022ds_set_sysfs_monitor_port: set the monitor port for sysfs
+  * p1022ds_valid_monitor_port: set the monitor port for sysfs
   */
- int p1022ds_set_sysfs_monitor_port(int val)
+ enum fsl_diu_monitor_port
+ p1022ds_valid_monitor_port(enum fsl_diu_monitor_port port)
  {
-       return val < 2 ? val : 0;
+       switch (port) {
+       case FSL_DIU_PORT_DVI:
+       case FSL_DIU_PORT_LVDS:
+               return port;
+       default:
+               return FSL_DIU_PORT_DVI; /* Dual-link LVDS is not supported */
+       }
  }
  
  #endif
@@@ -305,8 -293,7 +303,7 @@@ static void __init p1022_ds_setup_arch(
        diu_ops.set_gamma_table         = p1022ds_set_gamma_table;
        diu_ops.set_monitor_port        = p1022ds_set_monitor_port;
        diu_ops.set_pixel_clock         = p1022ds_set_pixel_clock;
-       diu_ops.show_monitor_port       = p1022ds_show_monitor_port;
-       diu_ops.set_sysfs_monitor_port  = p1022ds_set_sysfs_monitor_port;
+       diu_ops.valid_monitor_port      = p1022ds_valid_monitor_port;
  #endif
  
  #ifdef CONFIG_SMP
index 74e018ef724b0acc0aed5574e0bc483f2be37b83,0d80e9614f31aff45a75853028e7170a2b6d8e08..13fa9a6403e6fc8820554126b113038209e7fb91
  #include <sysdev/fsl_pci.h>
  #include <sysdev/fsl_soc.h>
  #include <sysdev/simple_gpio.h>
 +#include <asm/fsl_guts.h>
  
  #include "mpc86xx.h"
  
  static struct device_node *pixis_node;
  static unsigned char *pixis_bdcfg0, *pixis_arch;
  
 +/* DIU Pixel Clock bits of the CLKDVDR Global Utilities register */
 +#define CLKDVDR_PXCKEN                0x80000000
 +#define CLKDVDR_PXCKINV               0x10000000
 +#define CLKDVDR_PXCKDLY               0x06000000
 +#define CLKDVDR_PXCLK_MASK    0x001F0000
 +
  #ifdef CONFIG_SUSPEND
  static irqreturn_t mpc8610_sw9_irq(int irq, void *data)
  {
@@@ -152,10 -145,10 +152,10 @@@ machine_device_initcall(mpc86xx_hpcd, m
        (c2 << AD_COMP_2_SHIFT) | (c1 << AD_COMP_1_SHIFT) | \
        (c0 << AD_COMP_0_SHIFT) | (size << AD_PIXEL_S_SHIFT))
  
- unsigned int mpc8610hpcd_get_pixel_format(unsigned int bits_per_pixel,
-                                               int monitor_port)
+ u32 mpc8610hpcd_get_pixel_format(enum fsl_diu_monitor_port port,
+                                unsigned int bits_per_pixel)
  {
-       static const unsigned long pixelformat[][3] = {
+       static const u32 pixelformat[][3] = {
                {
                        MAKE_AD(3, 0, 2, 1, 3, 8, 8, 8, 8),
                        MAKE_AD(4, 2, 0, 1, 2, 8, 8, 8, 0),
        unsigned int arch_monitor;
  
        /* The DVI port is mis-wired on revision 1 of this board. */
-       arch_monitor = ((*pixis_arch == 0x01) && (monitor_port == 0))? 0 : 1;
+       arch_monitor =
+               ((*pixis_arch == 0x01) && (port == FSL_DIU_PORT_DVI)) ? 0 : 1;
  
        switch (bits_per_pixel) {
        case 32:
        }
  }
  
- void mpc8610hpcd_set_gamma_table(int monitor_port, char *gamma_table_base)
+ void mpc8610hpcd_set_gamma_table(enum fsl_diu_monitor_port port,
+                                char *gamma_table_base)
  {
        int i;
-       if (monitor_port == 2) {                /* dual link LVDS */
+       if (port == FSL_DIU_PORT_DLVDS) {
                for (i = 0; i < 256*3; i++)
                        gamma_table_base[i] = (gamma_table_base[i] << 2) |
                                         ((gamma_table_base[i] >> 6) & 0x03);
  #define PX_BRDCFG0_DLINK      (1 << 4)
  #define PX_BRDCFG0_DIU_MASK   (PX_BRDCFG0_DVISEL | PX_BRDCFG0_DLINK)
  
- void mpc8610hpcd_set_monitor_port(int monitor_port)
+ void mpc8610hpcd_set_monitor_port(enum fsl_diu_monitor_port port)
  {
-       static const u8 bdcfg[] = {
-               PX_BRDCFG0_DVISEL | PX_BRDCFG0_DLINK,
-               PX_BRDCFG0_DLINK,
-               0,
-       };
-       if (monitor_port < 3)
+       switch (port) {
+       case FSL_DIU_PORT_DVI:
                clrsetbits_8(pixis_bdcfg0, PX_BRDCFG0_DIU_MASK,
-                            bdcfg[monitor_port]);
+                            PX_BRDCFG0_DVISEL | PX_BRDCFG0_DLINK);
+               break;
+       case FSL_DIU_PORT_LVDS:
+               clrsetbits_8(pixis_bdcfg0, PX_BRDCFG0_DIU_MASK,
+                            PX_BRDCFG0_DLINK);
+               break;
+       case FSL_DIU_PORT_DLVDS:
+               clrbits8(pixis_bdcfg0, PX_BRDCFG0_DIU_MASK);
+               break;
+       }
  }
  
 +/**
 + * mpc8610hpcd_set_pixel_clock: program the DIU's clock
 + *
 + * @pixclock: the wavelength, in picoseconds, of the clock
 + */
  void mpc8610hpcd_set_pixel_clock(unsigned int pixclock)
  {
 -      u32 __iomem *clkdvdr;
 -      u32 temp;
 -      /* variables for pixel clock calcs */
 -      ulong  bestval, bestfreq, speed_ccb, minpixclock, maxpixclock;
 -      ulong pixval;
 -      long err;
 -      int i;
 -
 -      clkdvdr = ioremap(get_immrbase() + 0xe0800, sizeof(u32));
 -      if (!clkdvdr) {
 -              printk(KERN_ERR "Err: can't map clock divider register!\n");
 +      struct device_node *guts_np = NULL;
 +      struct ccsr_guts_86xx __iomem *guts;
 +      unsigned long freq;
 +      u64 temp;
 +      u32 pxclk;
 +
 +      /* Map the global utilities registers. */
 +      guts_np = of_find_compatible_node(NULL, NULL, "fsl,mpc8610-guts");
 +      if (!guts_np) {
 +              pr_err("mpc8610hpcd: missing global utilties device node\n");
                return;
        }
  
 -      /* Pixel Clock configuration */
 -      speed_ccb = fsl_get_sys_freq();
 -
 -      /* Calculate the pixel clock with the smallest error */
 -      /* calculate the following in steps to avoid overflow */
 -      pr_debug("DIU pixclock in ps - %d\n", pixclock);
 -      temp = 1000000000/pixclock;
 -      temp *= 1000;
 -      pixclock = temp;
 -      pr_debug("DIU pixclock freq - %u\n", pixclock);
 -
 -      temp = pixclock * 5 / 100;
 -      pr_debug("deviation = %d\n", temp);
 -      minpixclock = pixclock - temp;
 -      maxpixclock = pixclock + temp;
 -      pr_debug("DIU minpixclock - %lu\n", minpixclock);
 -      pr_debug("DIU maxpixclock - %lu\n", maxpixclock);
 -      pixval = speed_ccb/pixclock;
 -      pr_debug("DIU pixval = %lu\n", pixval);
 -
 -      err = 100000000;
 -      bestval = pixval;
 -      pr_debug("DIU bestval = %lu\n", bestval);
 -
 -      bestfreq = 0;
 -      for (i = -1; i <= 1; i++) {
 -              temp = speed_ccb / ((pixval+i) + 1);
 -              pr_debug("DIU test pixval i= %d, pixval=%lu, temp freq. = %u\n",
 -                                                      i, pixval, temp);
 -              if ((temp < minpixclock) || (temp > maxpixclock))
 -                      pr_debug("DIU exceeds monitor range (%lu to %lu)\n",
 -                              minpixclock, maxpixclock);
 -              else if (abs(temp - pixclock) < err) {
 -                pr_debug("Entered the else if block %d\n", i);
 -                      err = abs(temp - pixclock);
 -                      bestval = pixval+i;
 -                      bestfreq = temp;
 -              }
 +      guts = of_iomap(guts_np, 0);
 +      of_node_put(guts_np);
 +      if (!guts) {
 +              pr_err("mpc8610hpcd: could not map global utilties device\n");
 +              return;
        }
  
 -      pr_debug("DIU chose = %lx\n", bestval);
 -      pr_debug("DIU error = %ld\n NomPixClk ", err);
 -      pr_debug("DIU: Best Freq = %lx\n", bestfreq);
 -      /* Modify PXCLK in GUTS CLKDVDR */
 -      pr_debug("DIU: Current value of CLKDVDR = 0x%08x\n", (*clkdvdr));
 -      temp = (*clkdvdr) & 0x2000FFFF;
 -      *clkdvdr = temp;                /* turn off clock */
 -      *clkdvdr = temp | 0x80000000 | (((bestval) & 0x1F) << 16);
 -      pr_debug("DIU: Modified value of CLKDVDR = 0x%08x\n", (*clkdvdr));
 -      iounmap(clkdvdr);
 +      /* Convert pixclock from a wavelength to a frequency */
 +      temp = 1000000000000ULL;
 +      do_div(temp, pixclock);
 +      freq = temp;
 +
 +      /*
 +       * 'pxclk' is the ratio of the platform clock to the pixel clock.
 +       * On the MPC8610, the value programmed into CLKDVDR is the ratio
 +       * minus one.  The valid range of values is 2-31.
 +       */
 +      pxclk = DIV_ROUND_CLOSEST(fsl_get_sys_freq(), freq) - 1;
 +      pxclk = clamp_t(u32, pxclk, 2, 31);
 +
 +      /* Disable the pixel clock, and set it to non-inverted and no delay */
 +      clrbits32(&guts->clkdvdr,
 +                CLKDVDR_PXCKEN | CLKDVDR_PXCKDLY | CLKDVDR_PXCLK_MASK);
 +
 +      /* Enable the clock and set the pxclk */
 +      setbits32(&guts->clkdvdr, CLKDVDR_PXCKEN | (pxclk << 16));
 +
 +      iounmap(guts);
  }
  
- ssize_t mpc8610hpcd_show_monitor_port(int monitor_port, char *buf)
- {
-       return snprintf(buf, PAGE_SIZE,
-                       "%c0 - DVI\n"
-                       "%c1 - Single link LVDS\n"
-                       "%c2 - Dual link LVDS\n",
-                       monitor_port == 0 ? '*' : ' ',
-                       monitor_port == 1 ? '*' : ' ',
-                       monitor_port == 2 ? '*' : ' ');
- }
- int mpc8610hpcd_set_sysfs_monitor_port(int val)
+ enum fsl_diu_monitor_port
+ mpc8610hpcd_valid_monitor_port(enum fsl_diu_monitor_port port)
  {
-       return val < 3 ? val : 0;
+       return port;
  }
  
  #endif
@@@ -307,8 -314,7 +303,7 @@@ static void __init mpc86xx_hpcd_setup_a
        diu_ops.set_gamma_table         = mpc8610hpcd_set_gamma_table;
        diu_ops.set_monitor_port        = mpc8610hpcd_set_monitor_port;
        diu_ops.set_pixel_clock         = mpc8610hpcd_set_pixel_clock;
-       diu_ops.show_monitor_port       = mpc8610hpcd_show_monitor_port;
-       diu_ops.set_sysfs_monitor_port  = mpc8610hpcd_set_sysfs_monitor_port;
+       diu_ops.valid_monitor_port      = mpc8610hpcd_valid_monitor_port;
  #endif
  
        pixis_node = of_find_compatible_node(NULL, NULL, "fsl,fpga-pixis");
index 2ece02beb8ffed1a0828877d02adf251d779ed96,064bc70891349e5c3afa07cf6443f45663f2e727..c6d00736f07f559f677e25344c15c09943a3b25e
@@@ -22,22 -22,28 +22,31 @@@ struct device_node
  extern void fsl_rstcr_restart(char *cmd);
  
  #if defined(CONFIG_FB_FSL_DIU) || defined(CONFIG_FB_FSL_DIU_MODULE)
+ /* The different ports that the DIU can be connected to */
+ enum fsl_diu_monitor_port {
+       FSL_DIU_PORT_DVI,       /* DVI */
+       FSL_DIU_PORT_LVDS,      /* Single-link LVDS */
+       FSL_DIU_PORT_DLVDS      /* Dual-link LVDS */
+ };
  struct platform_diu_data_ops {
-       unsigned int (*get_pixel_format) (unsigned int bits_per_pixel,
-               int monitor_port);
-       void (*set_gamma_table) (int monitor_port, char *gamma_table_base);
-       void (*set_monitor_port) (int monitor_port);
-       void (*set_pixel_clock) (unsigned int pixclock);
-       ssize_t (*show_monitor_port) (int monitor_port, char *buf);
-       int (*set_sysfs_monitor_port) (int val);
-       void (*release_bootmem) (void);
+       u32 (*get_pixel_format)(enum fsl_diu_monitor_port port,
+               unsigned int bpp);
+       void (*set_gamma_table)(enum fsl_diu_monitor_port port,
+               char *gamma_table_base);
+       void (*set_monitor_port)(enum fsl_diu_monitor_port port);
+       void (*set_pixel_clock)(unsigned int pixclock);
+       enum fsl_diu_monitor_port (*valid_monitor_port)
+               (enum fsl_diu_monitor_port port);
+       void (*release_bootmem)(void);
  };
  
  extern struct platform_diu_data_ops diu_ops;
  #endif
  
 +void fsl_hv_restart(char *cmd);
 +void fsl_hv_halt(void);
 +
  #endif
  #endif
diff --combined drivers/video/Kconfig
index 963b8b767b832b8465c1aafafbf295713d4e5eda,e087fc2207e7b9f6cbe9a868a8fee620bec366d8..903ace58fec544bc601d5898aef4f31817bbc0f5
@@@ -259,6 -259,15 +259,15 @@@ config FB_TILEBLITTIN
  comment "Frame buffer hardware drivers"
        depends on FB
  
+ config FB_GRVGA
+       tristate "Aeroflex Gaisler framebuffer support"
+       depends on FB && SPARC
+       select FB_CFB_FILLRECT
+       select FB_CFB_COPYAREA
+       select FB_CFB_IMAGEBLIT
+       ---help---
+       This enables support for the SVGACTRL framebuffer in the GRLIB IP library from Aeroflex Gaisler.
  config FB_CIRRUS
        tristate "Cirrus Logic support"
        depends on FB && (ZORRO || PCI)
@@@ -1756,9 -1765,10 +1765,10 @@@ config FB_AU110
  config FB_AU1200
        bool "Au1200 LCD Driver"
        depends on (FB = y) && MIPS && SOC_AU1200
-       select FB_CFB_FILLRECT
-       select FB_CFB_COPYAREA
-       select FB_CFB_IMAGEBLIT
+       select FB_SYS_FILLRECT
+       select FB_SYS_COPYAREA
+       select FB_SYS_IMAGEBLIT
+       select FB_SYS_FOPS
        help
          This is the framebuffer driver for the AMD Au1200 SOC.  It can drive
          various panels and CRTs by passing in kernel cmd line option
@@@ -2027,7 -2037,7 +2037,7 @@@ config FB_TMIO_ACCEL
  
  config FB_S3C
        tristate "Samsung S3C framebuffer support"
 -      depends on FB && S3C_DEV_FB
 +      depends on FB && (S3C_DEV_FB || S5P_DEV_FIMD0)
        select FB_CFB_FILLRECT
        select FB_CFB_COPYAREA
        select FB_CFB_IMAGEBLIT
index 183b6f6398523d86fbb14a45f5fa08025ac71c3e,24a6dfd21b35f377d16e50426d3bef6cd95f6306..66bc74d9ce2af30889d026835d00442923cbc822
@@@ -7,7 -7,6 +7,6 @@@
   */
  
  #include <linux/module.h>
- #include <linux/version.h>
  #include <linux/init.h>
  #include <linux/errno.h>
  #include <linux/pm.h>
@@@ -722,7 -721,8 +721,7 @@@ static int __devinit adp8860_probe(stru
                goto out2;
        }
  
 -      bl->props.max_brightness =
 -              bl->props.brightness = ADP8860_MAX_BRIGHTNESS;
 +      bl->props.brightness = ADP8860_MAX_BRIGHTNESS;
  
        data->bl = bl;
  
index 9075bea55879fc9c3eb507dc9e7e2a4c707111e1,f6944019cb66e6745d266c54fb49f79123d50af0..7b2c40abae15b21e5ba26f460d809c216fb8e30a
@@@ -550,7 -550,7 +550,7 @@@ static void control_set_hardware(struc
  
  
  /*
-  * Parse user speficied options (`video=controlfb:')
+  * Parse user specified options (`video=controlfb:')
   */
  static void __init control_setup(char *options)
  {
@@@ -709,11 -709,11 +709,11 @@@ static int __init control_of_init(struc
  
        /* Map in frame buffer and registers */
        p->fb_orig_base = fb_res.start;
 -      p->fb_orig_size = fb_res.end - fb_res.start + 1;
 +      p->fb_orig_size = resource_size(&fb_res);
        /* use the big-endian aperture (??) */
        p->frame_buffer_phys = fb_res.start + 0x800000;
        p->control_regs_phys = reg_res.start;
 -      p->control_regs_size = reg_res.end - reg_res.start + 1;
 +      p->control_regs_size = resource_size(&reg_res);
  
        if (!p->fb_orig_base ||
            !request_mem_region(p->fb_orig_base,p->fb_orig_size,"controlfb")) {
diff --combined drivers/video/fb_defio.c
index 32814e8800e034ccb073024a0959f5764ced7d86,a79c0dedfbd466147bad92735c297205a2895108..c27e153d8882053e2d28ab72cfc784875752f337
@@@ -66,26 -66,19 +66,26 @@@ static int fb_deferred_io_fault(struct 
        return 0;
  }
  
 -int fb_deferred_io_fsync(struct file *file, int datasync)
 +int fb_deferred_io_fsync(struct file *file, loff_t start, loff_t end, int datasync)
  {
        struct fb_info *info = file->private_data;
 +      struct inode *inode = file->f_path.dentry->d_inode;
 +      int err = filemap_write_and_wait_range(inode->i_mapping, start, end);
 +      if (err)
 +              return err;
  
        /* Skip if deferred io is compiled-in but disabled on this fbdev */
        if (!info->fbdefio)
                return 0;
  
 +      mutex_lock(&inode->i_mutex);
        /* Kill off the delayed work */
        cancel_delayed_work_sync(&info->deferred_work);
  
        /* Run it immediately */
 -      return schedule_delayed_work(&info->deferred_work, 0);
 +      err = schedule_delayed_work(&info->deferred_work, 0);
 +      mutex_unlock(&inode->i_mutex);
 +      return err;
  }
  EXPORT_SYMBOL_GPL(fb_deferred_io_fsync);
  
@@@ -223,8 -216,7 +223,7 @@@ void fb_deferred_io_cleanup(struct fb_i
        int i;
  
        BUG_ON(!fbdefio);
-       cancel_delayed_work(&info->deferred_work);
-       flush_scheduled_work();
+       cancel_delayed_work_sync(&info->deferred_work);
  
        /* clear out the mapping that we setup */
        for (i = 0 ; i < info->fix.smem_len; i += PAGE_SIZE) {
diff --combined drivers/video/msm/mdp.c
index 243d16f09b8a2cbbfc6f5604f1775ec97cf91d72,7e94ee3d2521e78c169d14598f5a63757f405765..01fa660764b4caea65c69b24e9c51be0a9636318
@@@ -406,7 -406,8 +406,7 @@@ int mdp_probe(struct platform_device *p
                goto error_get_irq;
        }
  
 -      mdp->base = ioremap(resource->start,
 -                          resource->end - resource->start);
 +      mdp->base = ioremap(resource->start, resource_size(resource));
        if (mdp->base == 0) {
                printk(KERN_ERR "msmfb: cannot allocate mdp regs!\n");
                ret = -ENOMEM;
        clk = clk_get(&pdev->dev, "mdp_clk");
        if (IS_ERR(clk)) {
                printk(KERN_INFO "mdp: failed to get mdp clk");
-               return PTR_ERR(clk);
+               ret = PTR_ERR(clk);
+               goto error_get_clk;
        }
  
        ret = request_irq(mdp->irq, mdp_isr, IRQF_DISABLED, "msm_mdp", mdp);
  error_device_register:
        free_irq(mdp->irq, mdp);
  error_request_irq:
+ error_get_clk:
        iounmap(mdp->base);
  error_get_irq:
  error_ioremap:
index f27ae16ead2ea1671e782821a1f6836140120ee7,a0d0c3d625b95bf3fa3e22218bf04dbd8d3c2336..66949232f85ce354325858a188a015f6d0864407
@@@ -490,7 -490,7 +490,7 @@@ static int platinum_var_to_par(struct f
  
  
  /* 
-  * Parse user speficied options (`video=platinumfb:')
+  * Parse user specified options (`video=platinumfb:')
   */
  static int __init platinumfb_setup(char *options)
  {
@@@ -567,7 -567,7 +567,7 @@@ static int __devinit platinumfb_probe(s
         * northbridge and that can fail. Only request framebuffer
         */
        if (!request_mem_region(pinfo->rsrc_fb.start,
 -                              pinfo->rsrc_fb.end - pinfo->rsrc_fb.start + 1,
 +                              resource_size(&pinfo->rsrc_fb),
                                "platinumfb framebuffer")) {
                printk(KERN_ERR "platinumfb: Can't request framebuffer !\n");
                framebuffer_release(info);
@@@ -658,7 -658,8 +658,7 @@@ static int __devexit platinumfb_remove(
        iounmap(pinfo->cmap_regs);
  
        release_mem_region(pinfo->rsrc_fb.start,
 -                         pinfo->rsrc_fb.end -
 -                         pinfo->rsrc_fb.start + 1);
 +                         resource_size(&pinfo->rsrc_fb));
  
        release_mem_region(pinfo->cmap_regs_phys, 0x1000);
  
diff --combined drivers/video/udlfb.c
index 101846c2084aa36299b19a1b5a1028639bd145b4,4e133754ba2ba04c16b22e5fe17293f93d1eea95..3473e75ce78511106905f68d66d638b63a886972
@@@ -29,6 -29,7 +29,6 @@@
  #include <linux/slab.h>
  #include <linux/prefetch.h>
  #include <linux/delay.h>
 -#include <linux/prefetch.h>
  #include <video/udlfb.h>
  #include "edid.h"
  
@@@ -48,21 -49,29 +48,30 @@@ static const u32 udlfb_info_flags = FBI
                FBINFO_HWACCEL_COPYAREA | FBINFO_MISC_ALWAYS_SETPAR;
  
  /*
-  * There are many DisplayLink-based products, all with unique PIDs. We are able
-  * to support all volume ones (circa 2009) with a single driver, so we match
-  * globally on VID. TODO: Probe() needs to detect when we might be running
-  * "future" chips, and bail on those, so a compatible driver can match.
+  * There are many DisplayLink-based graphics products, all with unique PIDs.
+  * So we match on DisplayLink's VID + Vendor-Defined Interface Class (0xff)
+  * We also require a match on SubClass (0x00) and Protocol (0x00),
+  * which is compatible with all known USB 2.0 era graphics chips and firmware,
+  * but allows DisplayLink to increment those for any future incompatible chips
   */
  static struct usb_device_id id_table[] = {
-       {.idVendor = 0x17e9, .match_flags = USB_DEVICE_ID_MATCH_VENDOR,},
+       {.idVendor = 0x17e9,
+        .bInterfaceClass = 0xff,
+        .bInterfaceSubClass = 0x00,
+        .bInterfaceProtocol = 0x00,
+        .match_flags = USB_DEVICE_ID_MATCH_VENDOR |
+               USB_DEVICE_ID_MATCH_INT_CLASS |
+               USB_DEVICE_ID_MATCH_INT_SUBCLASS |
+               USB_DEVICE_ID_MATCH_INT_PROTOCOL,
+       },
        {},
  };
  MODULE_DEVICE_TABLE(usb, id_table);
  
  /* module options */
 -static int console;   /* Optionally allow fbcon to consume first framebuffer */
 -static int fb_defio;  /* Optionally enable experimental fb_defio mmap support */
 +static int console = 1; /* Allow fbcon to open framebuffer */
 +static int fb_defio = 1;  /* Detect mmap writes using page faults */
 +static int shadow = 1; /* Optionally disable shadow framebuffer */
  
  /* dlfb keeps a list of urbs for efficient bulk transfers */
  static void dlfb_urb_completion(struct urb *urb);
@@@ -95,39 -104,17 +104,39 @@@ static char *dlfb_vidreg_unlock(char *b
  }
  
  /*
 - * On/Off for driving the DisplayLink framebuffer to the display
 - *  0x00 H and V sync on
 - *  0x01 H and V sync off (screen blank but powered)
 - *  0x07 DPMS powerdown (requires modeset to come back)
 + * Map FB_BLANK_* to DisplayLink register
 + * DLReg FB_BLANK_*
 + * ----- -----------------------------
 + *  0x00 FB_BLANK_UNBLANK (0)
 + *  0x01 FB_BLANK (1)
 + *  0x03 FB_BLANK_VSYNC_SUSPEND (2)
 + *  0x05 FB_BLANK_HSYNC_SUSPEND (3)
 + *  0x07 FB_BLANK_POWERDOWN (4) Note: requires modeset to come back
   */
 -static char *dlfb_enable_hvsync(char *buf, bool enable)
 +static char *dlfb_blanking(char *buf, int fb_blank)
  {
 -      if (enable)
 -              return dlfb_set_register(buf, 0x1F, 0x00);
 -      else
 -              return dlfb_set_register(buf, 0x1F, 0x07);
 +      u8 reg;
 +
 +      switch (fb_blank) {
 +      case FB_BLANK_POWERDOWN:
 +              reg = 0x07;
 +              break;
 +      case FB_BLANK_HSYNC_SUSPEND:
 +              reg = 0x05;
 +              break;
 +      case FB_BLANK_VSYNC_SUSPEND:
 +              reg = 0x03;
 +              break;
 +      case FB_BLANK_NORMAL:
 +              reg = 0x01;
 +              break;
 +      default:
 +              reg = 0x00;
 +      }
 +
 +      buf = dlfb_set_register(buf, 0x1F, reg);
 +
 +      return buf;
  }
  
  static char *dlfb_set_color_depth(char *buf, u8 selection)
@@@ -295,15 -282,13 +304,15 @@@ static int dlfb_set_video_mode(struct d
        wrptr = dlfb_set_base8bpp(wrptr, dev->info->fix.smem_len);
  
        wrptr = dlfb_set_vid_cmds(wrptr, var);
 -      wrptr = dlfb_enable_hvsync(wrptr, true);
 +      wrptr = dlfb_blanking(wrptr, FB_BLANK_UNBLANK);
        wrptr = dlfb_vidreg_unlock(wrptr);
  
        writesize = wrptr - buf;
  
        retval = dlfb_submit_urb(dev, urb, writesize);
  
 +      dev->blank_mode = FB_BLANK_UNBLANK;
 +
        return retval;
  }
  
@@@ -777,13 -762,14 +786,13 @@@ static int dlfb_ops_ioctl(struct fb_inf
  {
  
        struct dlfb_data *dev = info->par;
 -      struct dloarea *area = NULL;
  
        if (!atomic_read(&dev->usb_active))
                return 0;
  
        /* TODO: Update X server to get this from sysfs instead */
        if (cmd == DLFB_IOCTL_RETURN_EDID) {
 -              char *edid = (char *)arg;
 +              void __user *edid = (void __user *)arg;
                if (copy_to_user(edid, dev->edid, dev->edid_size))
                        return -EFAULT;
                return 0;
  
        /* TODO: Help propose a standard fb.h ioctl to report mmap damage */
        if (cmd == DLFB_IOCTL_REPORT_DAMAGE) {
 +              struct dloarea area;
 +
 +              if (copy_from_user(&area, (void __user *)arg,
 +                                sizeof(struct dloarea)))
 +                      return -EFAULT;
  
                /*
                 * If we have a damage-aware client, turn fb_defio "off"
                if (info->fbdefio)
                        info->fbdefio->delay = DL_DEFIO_WRITE_DISABLE;
  
 -              area = (struct dloarea *)arg;
 -
 -              if (area->x < 0)
 -                      area->x = 0;
 +              if (area.x < 0)
 +                      area.x = 0;
  
 -              if (area->x > info->var.xres)
 -                      area->x = info->var.xres;
 +              if (area.x > info->var.xres)
 +                      area.x = info->var.xres;
  
 -              if (area->y < 0)
 -                      area->y = 0;
 +              if (area.y < 0)
 +                      area.y = 0;
  
 -              if (area->y > info->var.yres)
 -                      area->y = info->var.yres;
 +              if (area.y > info->var.yres)
 +                      area.y = info->var.yres;
  
 -              dlfb_handle_damage(dev, area->x, area->y, area->w, area->h,
 +              dlfb_handle_damage(dev, area.x, area.y, area.w, area.h,
                           info->screen_base);
        }
  
@@@ -867,7 -850,7 +876,7 @@@ static int dlfb_ops_open(struct fb_inf
         * preventing other clients (X) from working properly. Usually
         * not what the user wants. Fail by default with option to enable.
         */
 -      if ((user == 0) & (!console))
 +      if ((user == 0) && (!console))
                return -EBUSY;
  
        /* If the USB device is gone, we don't accept new opens */
@@@ -1066,57 -1049,32 +1075,57 @@@ static int dlfb_ops_set_par(struct fb_i
        return result;
  }
  
 +/* To fonzi the jukebox (e.g. make blanking changes take effect) */
 +static char *dlfb_dummy_render(char *buf)
 +{
 +      *buf++ = 0xAF;
 +      *buf++ = 0x6A; /* copy */
 +      *buf++ = 0x00; /* from address*/
 +      *buf++ = 0x00;
 +      *buf++ = 0x00;
 +      *buf++ = 0x01; /* one pixel */
 +      *buf++ = 0x00; /* to address */
 +      *buf++ = 0x00;
 +      *buf++ = 0x00;
 +      return buf;
 +}
 +
  /*
   * In order to come back from full DPMS off, we need to set the mode again
   */
  static int dlfb_ops_blank(int blank_mode, struct fb_info *info)
  {
        struct dlfb_data *dev = info->par;
 +      char *bufptr;
 +      struct urb *urb;
  
 -      if (blank_mode != FB_BLANK_UNBLANK) {
 -              char *bufptr;
 -              struct urb *urb;
 -
 -              urb = dlfb_get_urb(dev);
 -              if (!urb)
 -                      return 0;
 +      pr_info("/dev/fb%d FB_BLANK mode %d --> %d\n",
 +              info->node, dev->blank_mode, blank_mode);
  
 -              bufptr = (char *) urb->transfer_buffer;
 -              bufptr = dlfb_vidreg_lock(bufptr);
 -              bufptr = dlfb_enable_hvsync(bufptr, false);
 -              bufptr = dlfb_vidreg_unlock(bufptr);
 +      if ((dev->blank_mode == FB_BLANK_POWERDOWN) &&
 +          (blank_mode != FB_BLANK_POWERDOWN)) {
  
 -              dlfb_submit_urb(dev, urb, bufptr -
 -                              (char *) urb->transfer_buffer);
 -      } else {
 +              /* returning from powerdown requires a fresh modeset */
                dlfb_set_video_mode(dev, &info->var);
        }
  
 +      urb = dlfb_get_urb(dev);
 +      if (!urb)
 +              return 0;
 +
 +      bufptr = (char *) urb->transfer_buffer;
 +      bufptr = dlfb_vidreg_lock(bufptr);
 +      bufptr = dlfb_blanking(bufptr, blank_mode);
 +      bufptr = dlfb_vidreg_unlock(bufptr);
 +
 +      /* seems like a render op is needed to have blank change take effect */
 +      bufptr = dlfb_dummy_render(bufptr);
 +
 +      dlfb_submit_urb(dev, urb, bufptr -
 +                      (char *) urb->transfer_buffer);
 +
 +      dev->blank_mode = blank_mode;
 +
        return 0;
  }
  
@@@ -1149,7 -1107,7 +1158,7 @@@ static int dlfb_realloc_framebuffer(str
        int new_len;
        unsigned char *old_fb = info->screen_base;
        unsigned char *new_fb;
 -      unsigned char *new_back;
 +      unsigned char *new_back = 0;
  
        pr_warn("Reallocating framebuffer. Addresses will change!\n");
  
                 * But with imperfect damage info we may send pixels over USB
                 * that were, in fact, unchanged - wasting limited USB bandwidth
                 */
 -              new_back = vzalloc(new_len);
 +              if (shadow)
 +                      new_back = vzalloc(new_len);
                if (!new_back)
                        pr_info("No shadow/backing buffer allocated\n");
                else {
@@@ -1483,30 -1440,21 +1492,30 @@@ static int dlfb_select_std_channel(stru
  }
  
  static int dlfb_parse_vendor_descriptor(struct dlfb_data *dev,
 -                                      struct usb_device *usbdev)
 +                                      struct usb_interface *interface)
  {
        char *desc;
        char *buf;
        char *desc_end;
  
 -      u8 total_len = 0;
 +      int total_len = 0;
  
        buf = kzalloc(MAX_VENDOR_DESCRIPTOR_SIZE, GFP_KERNEL);
        if (!buf)
                return false;
        desc = buf;
  
 -      total_len = usb_get_descriptor(usbdev, 0x5f, /* vendor specific */
 -                                  0, desc, MAX_VENDOR_DESCRIPTOR_SIZE);
 +      total_len = usb_get_descriptor(interface_to_usbdev(interface),
 +                                      0x5f, /* vendor specific */
 +                                      0, desc, MAX_VENDOR_DESCRIPTOR_SIZE);
 +
 +      /* if not found, look in configuration descriptor */
 +      if (total_len < 0) {
 +              if (0 == usb_get_extra_descriptor(interface->cur_altsetting,
 +                      0x5f, &desc))
 +                      total_len = (int) desc[0];
 +      }
 +
        if (total_len > 5) {
                pr_info("vendor descriptor length:%x data:%02x %02x %02x %02x" \
                        "%02x %02x %02x %02x %02x %02x %02x\n",
                        }
                        desc += length;
                }
 +      } else {
 +              pr_info("vendor descriptor not available (%d)\n", total_len);
        }
  
        goto success;
@@@ -1595,11 -1541,10 +1604,11 @@@ static int dlfb_usb_probe(struct usb_in
                usbdev->descriptor.bcdDevice, dev);
        pr_info("console enable=%d\n", console);
        pr_info("fb_defio enable=%d\n", fb_defio);
 +      pr_info("shadow enable=%d\n", shadow);
  
        dev->sku_pixel_limit = 2048 * 1152; /* default to maximum */
  
 -      if (!dlfb_parse_vendor_descriptor(dev, usbdev)) {
 +      if (!dlfb_parse_vendor_descriptor(dev, interface)) {
                pr_err("firmware not recognized. Assume incompatible device\n");
                goto error;
        }
        /* We don't register a new USB class. Our client interface is fbdev */
  
        /* allocates framebuffer driver structure, not framebuffer memory */
-       info = framebuffer_alloc(0, &usbdev->dev);
+       info = framebuffer_alloc(0, &interface->dev);
        if (!info) {
                retval = -ENOMEM;
                pr_err("framebuffer_alloc failed\n");
@@@ -1948,13 -1893,10 +1957,13 @@@ static int dlfb_submit_urb(struct dlfb_
  }
  
  module_param(console, bool, S_IWUSR | S_IRUSR | S_IWGRP | S_IRGRP);
 -MODULE_PARM_DESC(console, "Allow fbcon to consume first framebuffer found");
 +MODULE_PARM_DESC(console, "Allow fbcon to open framebuffer");
  
  module_param(fb_defio, bool, S_IWUSR | S_IRUSR | S_IWGRP | S_IRGRP);
 -MODULE_PARM_DESC(fb_defio, "Enable fb_defio mmap support. *Experimental*");
 +MODULE_PARM_DESC(fb_defio, "Page fault detection of mmap writes");
 +
 +module_param(shadow, bool, S_IWUSR | S_IRUSR | S_IWGRP | S_IRGRP);
 +MODULE_PARM_DESC(shadow, "Shadow vid mem. Disable to save mem but lose perf");
  
  MODULE_AUTHOR("Roberto De Ioris <roberto@unbit.it>, "
              "Jaya Kumar <jayakumar.lkml@gmail.com>, "
index 53aa4430d86ea74cb525a1adc37484ee60c07b07,dd1276e886f3ceb942b40fe545c1d8092f955d4f..09fa57cea8446e06dc1c99cf4cd250818c64a692
@@@ -151,7 -151,8 +151,8 @@@ static void viafb_update_fix(struct fb_
  
        info->fix.visual =
                bpp == 8 ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
-       info->fix.line_length = (info->var.xres_virtual * bpp / 8 + 7) & ~7;
+       info->fix.line_length = ALIGN(info->var.xres_virtual * bpp / 8,
+               VIA_PITCH_SIZE);
  }
  
  static void viafb_setup_fixinfo(struct fb_fix_screeninfo *fix,
@@@ -238,8 -239,12 +239,12 @@@ static int viafb_check_var(struct fb_va
                depth = 24;
  
        viafb_fill_var_color_info(var, depth);
-       line = (var->xres_virtual * var->bits_per_pixel / 8 + 7) & ~7;
-       if (line * var->yres_virtual > ppar->memsize)
+       if (var->xres_virtual < var->xres)
+               var->xres_virtual = var->xres;
+       line = ALIGN(var->xres_virtual * var->bits_per_pixel / 8,
+               VIA_PITCH_SIZE);
+       if (line > VIA_PITCH_MAX || line * var->yres_virtual > ppar->memsize)
                return -EINVAL;
  
        /* Based on var passed in to calculate the refresh,
@@@ -348,8 -353,9 +353,9 @@@ static int viafb_pan_display(struct fb_
        struct fb_info *info)
  {
        struct viafb_par *viapar = info->par;
-       u32 vram_addr = (var->yoffset * var->xres_virtual + var->xoffset)
-               * (var->bits_per_pixel / 8) + viapar->vram_addr;
+       u32 vram_addr = viapar->vram_addr
+               + var->yoffset * info->fix.line_length
+               + var->xoffset * info->var.bits_per_pixel / 8;
  
        DEBUG_MSG(KERN_DEBUG "viafb_pan_display, address = %d\n", vram_addr);
        if (!viafb_dual_fb) {
@@@ -2016,7 -2022,7 +2022,7 @@@ static int __init viafb_setup(void
  int __init viafb_init(void)
  {
        u32 dummy_x, dummy_y;
 -      int r;
 +      int r = 0;
  
        if (machine_is_olpc())
                /* Apply XO-1.5-specific configuration. */
        printk(KERN_INFO
         "VIA Graphics Integration Chipset framebuffer %d.%d initializing\n",
               VERSION_MAJOR, VERSION_MINOR);
 -      return 0;
 +      return r;
  }
  
  void __exit viafb_exit(void)