From d933990c57b498c092ceef591c7c5d69dbfe9f30 Mon Sep 17 00:00:00 2001 From: Florian Tobias Schandinat Date: Mon, 23 May 2011 21:39:58 +0000 Subject: viafb: use display information in info not in var for panning As Laurent pointed out we must not use any information in the passed var besides xoffset, yoffset and vmode as otherwise applications might abuse it. Also use the aligned fix.line_length and not the (possible) unaligned xres_virtual. Signed-off-by: Florian Tobias Schandinat Reported-by: Laurent Pinchart Acked-by: Laurent Pinchart Cc: stable@kernel.org --- drivers/video/via/viafbdev.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/video/via/viafbdev.c b/drivers/video/via/viafbdev.c index 3114a8755c13..aa87529d7d6a 100644 --- a/drivers/video/via/viafbdev.c +++ b/drivers/video/via/viafbdev.c @@ -348,8 +348,9 @@ static int viafb_pan_display(struct fb_var_screeninfo *var, 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) { -- cgit v1.2.3 From 0cf9cd026adeacc3fe5e88e4d3e7f8f3aeff6790 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 14 Jun 2011 09:25:03 +0000 Subject: vfb: use display information in info not in var for panning We must not use any information in the passed var besides xoffset, yoffset and vmode as otherwise applications might abuse it. Signed-off-by: Laurent Pinchart Signed-off-by: Paul Mundt --- drivers/video/vfb.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/video/vfb.c b/drivers/video/vfb.c index bc67251f1a2f..bf2f78065cf9 100644 --- a/drivers/video/vfb.c +++ b/drivers/video/vfb.c @@ -395,8 +395,8 @@ static int vfb_pan_display(struct fb_var_screeninfo *var, || var->xoffset) return -EINVAL; } else { - if (var->xoffset + var->xres > info->var.xres_virtual || - var->yoffset + var->yres > info->var.yres_virtual) + if (var->xoffset + info->var.xres > info->var.xres_virtual || + var->yoffset + info->var.yres > info->var.yres_virtual) return -EINVAL; } info->var.xoffset = var->xoffset; -- cgit v1.2.3 From c42a3d543d2bbd2cb72c7179234358a4a33a583d Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 14 Jun 2011 09:25:07 +0000 Subject: staging: xgifb: use display information in info not in var for panning We must not use any information in the passed var besides xoffset, yoffset and vmode as otherwise applications might abuse it. Signed-off-by: Laurent Pinchart Cc: Aaro Koskinen Cc: Arnaud Patard Signed-off-by: Paul Mundt --- drivers/staging/xgifb/XGI_main_26.c | 22 ++++++---------------- 1 file changed, 6 insertions(+), 16 deletions(-) diff --git a/drivers/staging/xgifb/XGI_main_26.c b/drivers/staging/xgifb/XGI_main_26.c index cadec2ad0d32..e92f6fa67dcb 100644 --- a/drivers/staging/xgifb/XGI_main_26.c +++ b/drivers/staging/xgifb/XGI_main_26.c @@ -1365,26 +1365,16 @@ static int XGIfb_do_set_var(struct fb_var_screeninfo *var, int isactive, } #ifdef XGIFB_PAN -static int XGIfb_pan_var(struct fb_var_screeninfo *var) +static int XGIfb_pan_var(struct fb_var_screeninfo *var, struct fb_info *info) { unsigned int base; /* printk("Inside pan_var"); */ - if (var->xoffset > (var->xres_virtual - var->xres)) { - /* printk("Pan: xo: %d xv %d xr %d\n", - var->xoffset, var->xres_virtual, var->xres); */ - return -EINVAL; - } - if (var->yoffset > (var->yres_virtual - var->yres)) { - /* printk("Pan: yo: %d yv %d yr %d\n", - var->yoffset, var->yres_virtual, var->yres); */ - return -EINVAL; - } - base = var->yoffset * var->xres_virtual + var->xoffset; + base = var->yoffset * info->var.xres_virtual + var->xoffset; /* calculate base bpp dep. */ - switch (var->bits_per_pixel) { + switch (info->var.bits_per_pixel) { case 16: base >>= 1; break; @@ -1682,9 +1672,9 @@ static int XGIfb_pan_display(struct fb_var_screeninfo *var, /* printk("\nInside pan_display:\n"); */ - if (var->xoffset > (var->xres_virtual - var->xres)) + if (var->xoffset > (info->var.xres_virtual - info->var.xres)) return -EINVAL; - if (var->yoffset > (var->yres_virtual - var->yres)) + if (var->yoffset > (info->var.yres_virtual - info->var.yres)) return -EINVAL; if (var->vmode & FB_VMODE_YWRAP) { @@ -1697,7 +1687,7 @@ static int XGIfb_pan_display(struct fb_var_screeninfo *var, > info->var.yres_virtual) return -EINVAL; } - err = XGIfb_pan_var(var); + err = XGIfb_pan_var(var, info); if (err < 0) return err; -- cgit v1.2.3 From a1bb7010d494d3fcde3814d7a8ac609f1dff96ee Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 14 Jun 2011 09:24:40 +0000 Subject: acornfb: Dont BUG() on invalid pan parameters The driver currently BUG()s if the pan parameters passed directly from userspace are invalid. Return -EINVAL instead. Signed-off-by: Laurent Pinchart Signed-off-by: Paul Mundt --- drivers/video/acornfb.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/video/acornfb.c b/drivers/video/acornfb.c index 6183a57eb69d..3bacc1290548 100644 --- a/drivers/video/acornfb.c +++ b/drivers/video/acornfb.c @@ -852,7 +852,8 @@ acornfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info) if (!(var->vmode & FB_VMODE_YWRAP)) y_bottom += var->yres; - BUG_ON(y_bottom > var->yres_virtual); + if (y_bottom > var->yres_virtual) + return -EINVAL; acornfb_update_dma(info, var); -- cgit v1.2.3 From a4aadc9311ed8459471a1d4580d3199230a88437 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 14 Jun 2011 09:24:58 +0000 Subject: s3fb: use display information in info not in var for panning We must not use any information in the passed var besides xoffset, yoffset and vmode as otherwise applications might abuse it. Signed-off-by: Laurent Pinchart Cc: Ondrej Zary Signed-off-by: Paul Mundt --- drivers/video/s3fb.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/video/s3fb.c b/drivers/video/s3fb.c index 4ca5d0c8fe84..0f9af1aa5077 100644 --- a/drivers/video/s3fb.c +++ b/drivers/video/s3fb.c @@ -1019,12 +1019,13 @@ static int s3fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info) unsigned int offset; /* Calculate the offset */ - if (var->bits_per_pixel == 0) { - offset = (var->yoffset / 16) * (var->xres_virtual / 2) + (var->xoffset / 2); + if (info->var.bits_per_pixel == 0) { + offset = (var->yoffset / 16) * (info->var.xres_virtual / 2) + + (var->xoffset / 2); offset = offset >> 2; } else { offset = (var->yoffset * info->fix.line_length) + - (var->xoffset * var->bits_per_pixel / 8); + (var->xoffset * info->var.bits_per_pixel / 8); offset = offset >> 2; } -- cgit v1.2.3 From 4ee99f7e2edbd32501cb1fc0b701966d7cbe57e4 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 14 Jun 2011 09:24:53 +0000 Subject: mx3fb: use display information in info not in var for panning We must not use any information in the passed var besides xoffset, yoffset and vmode as otherwise applications might abuse it. Also use the aligned fix.line_length and not the (possible) unaligned xres_virtual. Signed-off-by: Laurent Pinchart Tested-by: Guennadi Liakhovetski Signed-off-by: Paul Mundt --- drivers/video/mx3fb.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/video/mx3fb.c b/drivers/video/mx3fb.c index 7e3a490e8d76..bd768588cf10 100644 --- a/drivers/video/mx3fb.c +++ b/drivers/video/mx3fb.c @@ -1062,15 +1062,15 @@ static int mx3fb_pan_display(struct fb_var_screeninfo *var, y_bottom = var->yoffset; if (!(var->vmode & FB_VMODE_YWRAP)) - y_bottom += var->yres; + y_bottom += fbi->var.yres; if (y_bottom > fbi->var.yres_virtual) return -EINVAL; mutex_lock(&mx3_fbi->mutex); - offset = (var->yoffset * var->xres_virtual + var->xoffset) * - (var->bits_per_pixel / 8); + offset = var->yoffset * fbi->fix.line_length + + var->xoffset * (fbi->var.bits_per_pixel / 8); base = fbi->fix.smem_start + offset; dev_dbg(fbi->device, "Updating SDC BG buf %d address=0x%08lX\n", -- cgit v1.2.3 From 2bdb0278eec7bb466d2b1b31ecf6e48f10b34fbf Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 14 Jun 2011 09:24:54 +0000 Subject: neofb: use display information in info not in var for panning We must not use any information in the passed var besides xoffset, yoffset and vmode as otherwise applications might abuse it. Signed-off-by: Laurent Pinchart Cc: Krzysztof Helt Signed-off-by: Paul Mundt --- drivers/video/neofb.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/video/neofb.c b/drivers/video/neofb.c index 588527a254c2..feea7b1dc386 100644 --- a/drivers/video/neofb.c +++ b/drivers/video/neofb.c @@ -1185,8 +1185,8 @@ static int neofb_pan_display(struct fb_var_screeninfo *var, DBG("neofb_update_start"); - Base = (var->yoffset * var->xres_virtual + var->xoffset) >> 2; - Base *= (var->bits_per_pixel + 7) / 8; + Base = (var->yoffset * info->var.xres_virtual + var->xoffset) >> 2; + Base *= (info->var.bits_per_pixel + 7) / 8; neoUnlock(); -- cgit v1.2.3 From 1388f6a77296b4fa926c6830f884b08c5ef4beab Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 14 Jun 2011 09:24:59 +0000 Subject: savagefb: use display information in info not in var for panning We must not use any information in the passed var besides xoffset, yoffset and vmode as otherwise applications might abuse it. Also use the aligned fix.line_length and not the (possible) unaligned xres_virtual. Signed-off-by: Laurent Pinchart Reviewed-by: Tormod Volden Cc: Antonino Daplas Signed-off-by: Paul Mundt --- drivers/video/savage/savagefb_driver.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/drivers/video/savage/savagefb_driver.c b/drivers/video/savage/savagefb_driver.c index 4de541ca9c52..beb495044b24 100644 --- a/drivers/video/savage/savagefb_driver.c +++ b/drivers/video/savage/savagefb_driver.c @@ -1477,15 +1477,9 @@ static void savagefb_set_par_int(struct savagefb_par *par, struct savage_reg *r vgaHWProtect(par, 0); } -static void savagefb_update_start(struct savagefb_par *par, - struct fb_var_screeninfo *var) +static void savagefb_update_start(struct savagefb_par *par, int base) { - int base; - - base = ((var->yoffset * var->xres_virtual + (var->xoffset & ~1)) - * ((var->bits_per_pixel+7) / 8)) >> 2; - - /* now program the start address registers */ + /* program the start address registers */ vga_out16(0x3d4, (base & 0x00ff00) | 0x0c, par); vga_out16(0x3d4, ((base & 0x00ff) << 8) | 0x0d, par); vga_out8(0x3d4, 0x69, par); @@ -1550,8 +1544,12 @@ static int savagefb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info) { struct savagefb_par *par = info->par; + int base; + + base = (var->yoffset * info->fix.line_length + + (var->xoffset & ~1) * ((info->var.bits_per_pixel+7) / 8)) >> 2; - savagefb_update_start(par, var); + savagefb_update_start(par, base); return 0; } -- cgit v1.2.3 From eca7370bd2f29296126011caed64af93c2c73803 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 14 Jun 2011 09:25:01 +0000 Subject: sm501fb: use display information in info not in var for panning We must not use any information in the passed var besides xoffset, yoffset and vmode as otherwise applications might abuse it. Signed-off-by: Laurent Pinchart Cc: Ben Dooks Signed-off-by: Paul Mundt --- drivers/video/sm501fb.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/video/sm501fb.c b/drivers/video/sm501fb.c index 87f0be1e78b5..2c9e9d3eb4ba 100644 --- a/drivers/video/sm501fb.c +++ b/drivers/video/sm501fb.c @@ -582,7 +582,7 @@ static int sm501fb_pan_crt(struct fb_var_screeninfo *var, { struct sm501fb_par *par = info->par; struct sm501fb_info *fbi = par->info; - unsigned int bytes_pixel = var->bits_per_pixel / 8; + unsigned int bytes_pixel = info->var.bits_per_pixel / 8; unsigned long reg; unsigned long xoffs; @@ -614,10 +614,10 @@ static int sm501fb_pan_pnl(struct fb_var_screeninfo *var, struct sm501fb_info *fbi = par->info; unsigned long reg; - reg = var->xoffset | (var->xres_virtual << 16); + reg = var->xoffset | (info->var.xres_virtual << 16); smc501_writel(reg, fbi->regs + SM501_DC_PANEL_FB_WIDTH); - reg = var->yoffset | (var->yres_virtual << 16); + reg = var->yoffset | (info->var.yres_virtual << 16); smc501_writel(reg, fbi->regs + SM501_DC_PANEL_FB_HEIGHT); sm501fb_sync_regs(fbi); -- cgit v1.2.3 From c12665ffcf4e5e67b84771d30fb76dd9ff16600e Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 14 Jun 2011 09:24:50 +0000 Subject: imsttfb: use display information in info not in var for panning We must not use any information in the passed var besides xoffset, yoffset and vmode as otherwise applications might abuse it. Signed-off-by: Laurent Pinchart Signed-off-by: Paul Mundt --- drivers/video/imsttfb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/video/imsttfb.c b/drivers/video/imsttfb.c index efb2c10656b0..8149356471e4 100644 --- a/drivers/video/imsttfb.c +++ b/drivers/video/imsttfb.c @@ -749,7 +749,7 @@ set_offset (struct fb_var_screeninfo *var, struct fb_info *info) { struct imstt_par *par = info->par; __u32 off = var->yoffset * (info->fix.line_length >> 3) - + ((var->xoffset * (var->bits_per_pixel >> 3)) >> 3); + + ((var->xoffset * (info->var.bits_per_pixel >> 3)) >> 3); write_reg_le32(par->dc_regs, SSR, off); } -- cgit v1.2.3 From c2d340a403f08e57fb76e738e691fe466a38a8c8 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 14 Jun 2011 09:24:48 +0000 Subject: gxt4500: use display information in info not in var for panning We must not use any information in the passed var besides xoffset, yoffset and vmode as otherwise applications might abuse it. Signed-off-by: Laurent Pinchart Cc: Paul Mackerras Signed-off-by: Paul Mundt --- drivers/video/gxt4500.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/video/gxt4500.c b/drivers/video/gxt4500.c index 896e53dea906..0fad23f810a3 100644 --- a/drivers/video/gxt4500.c +++ b/drivers/video/gxt4500.c @@ -543,8 +543,8 @@ static int gxt4500_pan_display(struct fb_var_screeninfo *var, if (var->xoffset & 7) return -EINVAL; - if (var->xoffset + var->xres > var->xres_virtual || - var->yoffset + var->yres > var->yres_virtual) + if (var->xoffset + info->var.xres > info->var.xres_virtual || + var->yoffset + info->var.yres > info->var.yres_virtual) return -EINVAL; writereg(par, REFRESH_START, (var->xoffset << 16) | var->yoffset); -- cgit v1.2.3 From df9306de45529f02d18a1a16b8685ef5c90f98f7 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 14 Jun 2011 09:24:55 +0000 Subject: pm2fb: use display information in info not in var for panning We must not use any information in the passed var besides xoffset, yoffset and vmode as otherwise applications might abuse it. Signed-off-by: Laurent Pinchart Cc: Krzysztof Helt Signed-off-by: Paul Mundt --- drivers/video/pm2fb.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/video/pm2fb.c b/drivers/video/pm2fb.c index 27f93aab6ddc..f4f8ce802d02 100644 --- a/drivers/video/pm2fb.c +++ b/drivers/video/pm2fb.c @@ -973,8 +973,8 @@ static int pm2fb_pan_display(struct fb_var_screeninfo *var, { struct pm2fb_par *p = info->par; u32 base; - u32 depth = (var->bits_per_pixel + 7) & ~7; - u32 xres = (var->xres + 31) & ~31; + u32 depth = (info->var.bits_per_pixel + 7) & ~7; + u32 xres = (info->var.xres + 31) & ~31; depth = (depth > 32) ? 32 : depth; base = to3264(var->yoffset * xres + var->xoffset, depth, 1); -- cgit v1.2.3 From 5dac1518373824dc36fef9efc4d80491eb0ed50f Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 14 Jun 2011 09:25:00 +0000 Subject: sisfb: use display information in info not in var for panning We must not use any information in the passed var besides xoffset, yoffset and vmode as otherwise applications might abuse it. Fix checkpatch.pl warnings in the surrounding code. Signed-off-by: Laurent Pinchart Cc: Aaro Koskinen Cc: Thomas Winischhofer Signed-off-by: Paul Mundt --- drivers/video/sis/sis_main.c | 30 ++++++++++-------------------- 1 file changed, 10 insertions(+), 20 deletions(-) diff --git a/drivers/video/sis/sis_main.c b/drivers/video/sis/sis_main.c index 75259845933d..078ca2167d6f 100644 --- a/drivers/video/sis/sis_main.c +++ b/drivers/video/sis/sis_main.c @@ -1333,19 +1333,14 @@ sisfb_set_base_CRT2(struct sis_video_info *ivideo, unsigned int base) } static int -sisfb_pan_var(struct sis_video_info *ivideo, struct fb_var_screeninfo *var) +sisfb_pan_var(struct sis_video_info *ivideo, struct fb_info *info, + struct fb_var_screeninfo *var) { - if(var->xoffset > (var->xres_virtual - var->xres)) { - return -EINVAL; - } - if(var->yoffset > (var->yres_virtual - var->yres)) { - return -EINVAL; - } - - ivideo->current_base = (var->yoffset * var->xres_virtual) + var->xoffset; + ivideo->current_base = var->yoffset * info->var.xres_virtual + + var->xoffset; /* calculate base bpp dep. */ - switch(var->bits_per_pixel) { + switch (info->var.bits_per_pixel) { case 32: break; case 16: @@ -1635,20 +1630,15 @@ sisfb_pan_display(struct fb_var_screeninfo *var, struct fb_info* info) struct sis_video_info *ivideo = (struct sis_video_info *)info->par; int err; - if(var->xoffset > (var->xres_virtual - var->xres)) - return -EINVAL; - - if(var->yoffset > (var->yres_virtual - var->yres)) - return -EINVAL; - - if(var->vmode & FB_VMODE_YWRAP) + if (var->vmode & FB_VMODE_YWRAP) return -EINVAL; - if(var->xoffset + info->var.xres > info->var.xres_virtual || - var->yoffset + info->var.yres > info->var.yres_virtual) + if (var->xoffset + info->var.xres > info->var.xres_virtual || + var->yoffset + info->var.yres > info->var.yres_virtual) return -EINVAL; - if((err = sisfb_pan_var(ivideo, var)) < 0) + err = sisfb_pan_var(ivideo, info, var); + if (err < 0) return err; info->var.xoffset = var->xoffset; -- cgit v1.2.3 From 895607ec5c7d7b0d840416db6499f83a0ee187af Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 14 Jun 2011 09:24:43 +0000 Subject: atmel_lcdfb: use display information in info not in var for panning We must not use any information in the passed var besides xoffset, yoffset and vmode as otherwise applications might abuse it. Signed-off-by: Laurent Pinchart Cc: Nicolas Ferre Signed-off-by: Paul Mundt --- drivers/video/atmel_lcdfb.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/drivers/video/atmel_lcdfb.c b/drivers/video/atmel_lcdfb.c index 4484c721f0f9..8b5d7552bb65 100644 --- a/drivers/video/atmel_lcdfb.c +++ b/drivers/video/atmel_lcdfb.c @@ -39,7 +39,8 @@ | FBINFO_HWACCEL_YPAN) static inline void atmel_lcdfb_update_dma2d(struct atmel_lcdfb_info *sinfo, - struct fb_var_screeninfo *var) + struct fb_var_screeninfo *var, + struct fb_info *info) { } @@ -50,14 +51,16 @@ static inline void atmel_lcdfb_update_dma2d(struct atmel_lcdfb_info *sinfo, | FBINFO_HWACCEL_YPAN) static void atmel_lcdfb_update_dma2d(struct atmel_lcdfb_info *sinfo, - struct fb_var_screeninfo *var) + struct fb_var_screeninfo *var, + struct fb_info *info) { u32 dma2dcfg; u32 pixeloff; - pixeloff = (var->xoffset * var->bits_per_pixel) & 0x1f; + pixeloff = (var->xoffset * info->var.bits_per_pixel) & 0x1f; - dma2dcfg = ((var->xres_virtual - var->xres) * var->bits_per_pixel) / 8; + dma2dcfg = (info-var.xres_virtual - info->var.xres) + * info->var.bits_per_pixel / 8; dma2dcfg |= pixeloff << ATMEL_LCDC_PIXELOFF_OFFSET; lcdc_writel(sinfo, ATMEL_LCDC_DMA2DCFG, dma2dcfg); @@ -249,14 +252,14 @@ static void atmel_lcdfb_update_dma(struct fb_info *info, unsigned long dma_addr; dma_addr = (fix->smem_start + var->yoffset * fix->line_length - + var->xoffset * var->bits_per_pixel / 8); + + var->xoffset * info->var.bits_per_pixel / 8); dma_addr &= ~3UL; /* Set framebuffer DMA base address and pixel offset */ lcdc_writel(sinfo, ATMEL_LCDC_DMABADDR1, dma_addr); - atmel_lcdfb_update_dma2d(sinfo, var); + atmel_lcdfb_update_dma2d(sinfo, var, info); } static inline void atmel_lcdfb_free_video_memory(struct atmel_lcdfb_info *sinfo) -- cgit v1.2.3 From 635e9620e8361005b9a80c9fb0445b6b87d36f8c Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 14 Jun 2011 09:24:51 +0000 Subject: intelfb: use display information in info not in var for panning We must not use any information in the passed var besides xoffset, yoffset and vmode as otherwise applications might abuse it. Signed-off-by: Laurent Pinchart Cc: Maik Broemme Signed-off-by: Paul Mundt --- drivers/video/intelfb/intelfbhw.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/video/intelfb/intelfbhw.c b/drivers/video/intelfb/intelfbhw.c index 38065cf94ac4..fbad61da359f 100644 --- a/drivers/video/intelfb/intelfbhw.c +++ b/drivers/video/intelfb/intelfbhw.c @@ -390,12 +390,12 @@ int intelfbhw_pan_display(struct fb_var_screeninfo *var, struct fb_info *info) xoffset = ROUND_DOWN_TO(var->xoffset, 8); yoffset = var->yoffset; - if ((xoffset + var->xres > var->xres_virtual) || - (yoffset + var->yres > var->yres_virtual)) + if ((xoffset + info->var.xres > info->var.xres_virtual) || + (yoffset + info->var.yres > info->var.yres_virtual)) return -EINVAL; offset = (yoffset * dinfo->pitch) + - (xoffset * var->bits_per_pixel) / 8; + (xoffset * info->var.bits_per_pixel) / 8; offset += dinfo->fb.offset << 12; -- cgit v1.2.3 From e4c735af0076923643af48577fc9ad6e123a55fa Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 14 Jun 2011 09:25:02 +0000 Subject: tridentfb: use display information in info not in var for panning We must not use any information in the passed var besides xoffset, yoffset and vmode as otherwise applications might abuse it. Signed-off-by: Laurent Pinchart Cc: Krzysztof Helt Signed-off-by: Paul Mundt --- drivers/video/tridentfb.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/video/tridentfb.c b/drivers/video/tridentfb.c index c6c77562839d..34cf019bba44 100644 --- a/drivers/video/tridentfb.c +++ b/drivers/video/tridentfb.c @@ -987,8 +987,8 @@ static int tridentfb_pan_display(struct fb_var_screeninfo *var, unsigned int offset; debug("enter\n"); - offset = (var->xoffset + (var->yoffset * var->xres_virtual)) - * var->bits_per_pixel / 32; + offset = (var->xoffset + (var->yoffset * info->var.xres_virtual)) + * info->var.bits_per_pixel / 32; set_screen_start(par, offset); debug("exit\n"); return 0; -- cgit v1.2.3 From 4d3c68a1b468741fcebfbfb0b92ff9e75a063484 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 14 Jun 2011 09:25:04 +0000 Subject: vga16fb: use display information in info not in var for panning We must not use any information in the passed var besides xoffset, yoffset and vmode as otherwise applications might abuse it. Signed-off-by: Laurent Pinchart Cc: Antonino A. Daplas Signed-off-by: Paul Mundt --- drivers/video/vga16fb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/video/vga16fb.c b/drivers/video/vga16fb.c index 305c975b1787..0267acd8dc83 100644 --- a/drivers/video/vga16fb.c +++ b/drivers/video/vga16fb.c @@ -207,7 +207,7 @@ static void vga16fb_pan_var(struct fb_info *info, * granularity if someone supports xoffset in bit resolution */ vga_io_r(VGA_IS1_RC); /* reset flip-flop */ vga_io_w(VGA_ATT_IW, VGA_ATC_PEL); - if (var->bits_per_pixel == 8) + if (info->var.bits_per_pixel == 8) vga_io_w(VGA_ATT_IW, (xoffset & 3) << 1); else vga_io_w(VGA_ATT_IW, xoffset & 7); -- cgit v1.2.3 From ff55fe9ac19d800bfab02bc877c06e74f3e2537d Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 14 Jun 2011 09:24:44 +0000 Subject: radeonfb: use display information in info not in var for panning We must not use any information in the passed var besides xoffset, yoffset and vmode as otherwise applications might abuse it. Also use the aligned fix.line_length and not the (possible) unaligned xres_virtual. Signed-off-by: Laurent Pinchart Cc: Benjamin Herrenschmidt Signed-off-by: Paul Mundt --- drivers/video/aty/radeon_base.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/video/aty/radeon_base.c b/drivers/video/aty/radeon_base.c index 32f8cf6200a7..150684882ef7 100644 --- a/drivers/video/aty/radeon_base.c +++ b/drivers/video/aty/radeon_base.c @@ -845,16 +845,16 @@ static int radeonfb_pan_display (struct fb_var_screeninfo *var, { struct radeonfb_info *rinfo = info->par; - if ((var->xoffset + var->xres > var->xres_virtual) - || (var->yoffset + var->yres > var->yres_virtual)) - return -EINVAL; + if ((var->xoffset + info->var.xres > info->var.xres_virtual) + || (var->yoffset + info->var.yres > info->var.yres_virtual)) + return -EINVAL; if (rinfo->asleep) return 0; radeon_fifo_wait(2); - OUTREG(CRTC_OFFSET, ((var->yoffset * var->xres_virtual + var->xoffset) - * var->bits_per_pixel / 8) & ~7); + OUTREG(CRTC_OFFSET, (var->yoffset * info->fix.line_length + + var->xoffset * info->var.bits_per_pixel / 8) & ~7); return 0; } -- cgit v1.2.3 From df2d79810930ead3112b4ebab86ea0f9229ccf70 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 14 Jun 2011 09:24:49 +0000 Subject: hgafb: use display information in info not in var for panning We must not use any information in the passed var besides xoffset, yoffset and vmode as otherwise applications might abuse it. Signed-off-by: Laurent Pinchart Cc: Ferenc Bakonyi Cc: Brent Cook Signed-off-by: Paul Mundt --- drivers/video/hgafb.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/video/hgafb.c b/drivers/video/hgafb.c index 4052718eefaa..4394389caf68 100644 --- a/drivers/video/hgafb.c +++ b/drivers/video/hgafb.c @@ -422,8 +422,8 @@ static int hgafb_pan_display(struct fb_var_screeninfo *var, var->xoffset) return -EINVAL; } else { - if (var->xoffset + var->xres > info->var.xres_virtual - || var->yoffset + var->yres > info->var.yres_virtual + if (var->xoffset + info->var.xres > info->var.xres_virtual + || var->yoffset + info->var.yres > info->var.yres_virtual || var->yoffset % 8) return -EINVAL; } -- cgit v1.2.3 From 1fdb518f9f9c804d78e84a54ce1814fe9003bca4 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 14 Jun 2011 09:24:56 +0000 Subject: pm3fb: use display information in info not in var for panning We must not use any information in the passed var besides xoffset, yoffset and vmode as otherwise applications might abuse it. Signed-off-by: Laurent Pinchart Cc: Krzysztof Helt Signed-off-by: Paul Mundt --- drivers/video/pm3fb.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/video/pm3fb.c b/drivers/video/pm3fb.c index 6666f45a2f8c..8221b5b42da9 100644 --- a/drivers/video/pm3fb.c +++ b/drivers/video/pm3fb.c @@ -1147,9 +1147,9 @@ static int pm3fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info) { struct pm3_par *par = info->par; - const u32 xres = (var->xres + 31) & ~31; + const u32 xres = (info->var.xres + 31) & ~31; - par->base = pm3fb_shift_bpp(var->bits_per_pixel, + par->base = pm3fb_shift_bpp(info->var.bits_per_pixel, (var->yoffset * xres) + var->xoffset); PM3_WAIT(par, 1); -- cgit v1.2.3 From 1dbe8514fdb9ec6c82aa295c57886dfcf17574f1 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 14 Jun 2011 09:24:41 +0000 Subject: acornfb: use display information in info not in var for panning We must not use any information in the passed var besides xoffset, yoffset and vmode as otherwise applications might abuse it. Signed-off-by: Laurent Pinchart Signed-off-by: Paul Mundt --- drivers/video/acornfb.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/video/acornfb.c b/drivers/video/acornfb.c index 3bacc1290548..b303f1715065 100644 --- a/drivers/video/acornfb.c +++ b/drivers/video/acornfb.c @@ -850,9 +850,9 @@ acornfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info) u_int y_bottom = var->yoffset; if (!(var->vmode & FB_VMODE_YWRAP)) - y_bottom += var->yres; + y_bottom += info->var.yres; - if (y_bottom > var->yres_virtual) + if (y_bottom > info->var.yres_virtual) return -EINVAL; acornfb_update_dma(info, var); -- cgit v1.2.3 From aa7984cf51875bbb867485a72817bca5162fe80d Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 14 Jun 2011 09:24:46 +0000 Subject: fbdev: unicore32: use display information in info not in var for panning We must not use any information in the passed var besides xoffset, yoffset and vmode as otherwise applications might abuse it. Signed-off-by: Laurent Pinchart Cc: Guan Xuetao Signed-off-by: Paul Mundt --- drivers/video/fb-puv3.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/video/fb-puv3.c b/drivers/video/fb-puv3.c index 27f2c57e06e9..60a787fa32cf 100644 --- a/drivers/video/fb-puv3.c +++ b/drivers/video/fb-puv3.c @@ -624,8 +624,8 @@ static int unifb_pan_display(struct fb_var_screeninfo *var, || var->xoffset) return -EINVAL; } else { - if (var->xoffset + var->xres > info->var.xres_virtual || - var->yoffset + var->yres > info->var.yres_virtual) + if (var->xoffset + info->var.xres > info->var.xres_virtual || + var->yoffset + info->var.yres > info->var.yres_virtual) return -EINVAL; } info->var.xoffset = var->xoffset; -- cgit v1.2.3 From 3362903cad196d2a8ba340c0c3c5889db3b65c68 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 14 Jun 2011 09:24:57 +0000 Subject: s3c-fb: use display information in info not in var for panning We must not use any information in the passed var besides xoffset, yoffset and vmode as otherwise applications might abuse it. Signed-off-by: Laurent Pinchart Acked-by: Jingoo Han Signed-off-by: Paul Mundt --- drivers/video/s3c-fb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/video/s3c-fb.c b/drivers/video/s3c-fb.c index 0352afa49a39..42b557c44e84 100644 --- a/drivers/video/s3c-fb.c +++ b/drivers/video/s3c-fb.c @@ -884,7 +884,7 @@ static int s3c_fb_pan_display(struct fb_var_screeninfo *var, } } /* Offset in bytes to the end of the displayed area */ - end_boff = start_boff + var->yres * info->fix.line_length; + end_boff = start_boff + info->var.yres * info->fix.line_length; /* Temporarily turn off per-vsync update from shadow registers until * both start and end addresses are updated to prevent corruption */ -- cgit v1.2.3 From f316fe726a0edd3941111b61681bb8bbd4fda2e6 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 14 Jun 2011 09:24:52 +0000 Subject: mb862xxfb: use display information in info not in var for panning We must not use any information in the passed var besides xoffset, yoffset and vmode as otherwise applications might abuse it. Signed-off-by: Laurent Pinchart Cc: Anatolij Gustschin Signed-off-by: Paul Mundt --- drivers/video/mb862xx/mb862xxfbdrv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/video/mb862xx/mb862xxfbdrv.c b/drivers/video/mb862xx/mb862xxfbdrv.c index f70bd63b0187..2191de0bb309 100644 --- a/drivers/video/mb862xx/mb862xxfbdrv.c +++ b/drivers/video/mb862xx/mb862xxfbdrv.c @@ -278,7 +278,7 @@ static int mb862xxfb_pan(struct fb_var_screeninfo *var, reg = pack(var->yoffset, var->xoffset); outreg(disp, GC_L0WY_L0WX, reg); - reg = pack(var->yres_virtual, var->xres_virtual); + reg = pack(info->var.yres_virtual, info->var.xres_virtual); outreg(disp, GC_L0WH_L0WW, reg); return 0; } -- cgit v1.2.3 From 3b30f9f437eed6a1fd7f306fa0d2ab1e18e44a1f Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 14 Jun 2011 09:24:47 +0000 Subject: g364fb: use display information in info not in var for panning We must not use any information in the passed var besides xoffset, yoffset and vmode as otherwise applications might abuse it. Signed-off-by: Laurent Pinchart Signed-off-by: Paul Mundt --- drivers/video/g364fb.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/video/g364fb.c b/drivers/video/g364fb.c index d662317d85e3..223896cc5f7d 100644 --- a/drivers/video/g364fb.c +++ b/drivers/video/g364fb.c @@ -149,10 +149,11 @@ int g364fb_cursor(struct fb_info *info, struct fb_cursor *cursor) static int g364fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info) { - if (var->xoffset || var->yoffset + var->yres > var->yres_virtual) + if (var->xoffset || + var->yoffset + info->var.yres > info->var.yres_virtual) return -EINVAL; - *(unsigned int *) TOP_REG = var->yoffset * var->xres; + *(unsigned int *) TOP_REG = var->yoffset * info->var.xres; return 0; } -- cgit v1.2.3 From 7b8067f202b9dc0b6baea1dee918d95e3112f2a5 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 14 Jun 2011 09:24:42 +0000 Subject: arkfb: use display information in info not in var for panning We must not use any information in the passed var besides xoffset, yoffset and vmode as otherwise applications might abuse it. Signed-off-by: Laurent Pinchart Cc: Ondrej Zajicek Signed-off-by: Paul Mundt --- drivers/video/arkfb.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/video/arkfb.c b/drivers/video/arkfb.c index 8686429cbdf0..555dd4c64f5b 100644 --- a/drivers/video/arkfb.c +++ b/drivers/video/arkfb.c @@ -908,13 +908,14 @@ static int arkfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info unsigned int offset; /* Calculate the offset */ - if (var->bits_per_pixel == 0) { - offset = (var->yoffset / 16) * (var->xres_virtual / 2) + (var->xoffset / 2); + if (info->var.bits_per_pixel == 0) { + offset = (var->yoffset / 16) * (info->var.xres_virtual / 2) + + (var->xoffset / 2); offset = offset >> 2; } else { offset = (var->yoffset * info->fix.line_length) + - (var->xoffset * var->bits_per_pixel / 8); - offset = offset >> ((var->bits_per_pixel == 4) ? 2 : 3); + (var->xoffset * info->var.bits_per_pixel / 8); + offset = offset >> ((info->var.bits_per_pixel == 4) ? 2 : 3); } /* Set the offset */ -- cgit v1.2.3 From c6990b775d543c432f968808119d7fe33d506a71 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 14 Jun 2011 09:24:39 +0000 Subject: 68328fb: use display information in info not in var for panning We must not use any information in the passed var besides xoffset, yoffset and vmode as otherwise applications might abuse it. Signed-off-by: Laurent Pinchart Signed-off-by: Paul Mundt --- drivers/video/68328fb.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/video/68328fb.c b/drivers/video/68328fb.c index 75a39eab70c3..a425d65d5ba2 100644 --- a/drivers/video/68328fb.c +++ b/drivers/video/68328fb.c @@ -378,8 +378,8 @@ static int mc68x328fb_pan_display(struct fb_var_screeninfo *var, || var->xoffset) return -EINVAL; } else { - if (var->xoffset + var->xres > info->var.xres_virtual || - var->yoffset + var->yres > info->var.yres_virtual) + if (var->xoffset + info->var.xres > info->var.xres_virtual || + var->yoffset + info->var.yres > info->var.yres_virtual) return -EINVAL; } info->var.xoffset = var->xoffset; -- cgit v1.2.3 From 83f0e27c253554b7be329e2786d0814a276fd240 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 14 Jun 2011 09:25:06 +0000 Subject: vt8623fb: use display information in info not in var for panning We must not use any information in the passed var besides xoffset, yoffset and vmode as otherwise applications might abuse it. Signed-off-by: Laurent Pinchart Cc: Ondrej Zajicek Cc: David S. Miller Signed-off-by: Paul Mundt --- drivers/video/vt8623fb.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/video/vt8623fb.c b/drivers/video/vt8623fb.c index f9b3e3dc2421..4e74d262cf3e 100644 --- a/drivers/video/vt8623fb.c +++ b/drivers/video/vt8623fb.c @@ -620,13 +620,14 @@ static int vt8623fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *i unsigned int offset; /* Calculate the offset */ - if (var->bits_per_pixel == 0) { - offset = (var->yoffset / 16) * var->xres_virtual + var->xoffset; + if (info->var.bits_per_pixel == 0) { + offset = (var->yoffset / 16) * info->var.xres_virtual + + var->xoffset; offset = offset >> 3; } else { offset = (var->yoffset * info->fix.line_length) + - (var->xoffset * var->bits_per_pixel / 8); - offset = offset >> ((var->bits_per_pixel == 4) ? 2 : 1); + (var->xoffset * info->var.bits_per_pixel / 8); + offset = offset >> ((info->var.bits_per_pixel == 4) ? 2 : 1); } /* Set the offset */ -- cgit v1.2.3 From 3478b1cd43284ef798974384ba894eadc37fc1d9 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 14 Jun 2011 09:25:05 +0000 Subject: vt8500lcdfb: use display information in info not in var for panning We must not use any information in the passed var besides xoffset, yoffset and vmode as otherwise applications might abuse it. Signed-off-by: Laurent Pinchart Acked-by: Alexey Charkov Signed-off-by: Paul Mundt --- drivers/video/vt8500lcdfb.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/video/vt8500lcdfb.c b/drivers/video/vt8500lcdfb.c index 0e120d67eb65..c13c246be9a5 100644 --- a/drivers/video/vt8500lcdfb.c +++ b/drivers/video/vt8500lcdfb.c @@ -210,8 +210,8 @@ static int vt8500lcd_pan_display(struct fb_var_screeninfo *var, struct vt8500lcd_info *fbi = to_vt8500lcd_info(info); writel((1 << 31) - | (((var->xres_virtual - var->xres) * pixlen / 4) << 20) - | (off >> 2), fbi->regbase + 0x20); + | (((info->var.xres_virtual - info->var.xres) * pixlen / 4) << 20) + | (off >> 2), fbi->regbase + 0x20); return 0; } -- cgit v1.2.3 From e6c4d3d43d4d00a0ed945c77e6b89c74b38120d7 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 14 Jun 2011 09:24:45 +0000 Subject: fbdev: da8xx: use display information in info not in var for panning We must not use any information in the passed var besides xoffset, yoffset and vmode as otherwise applications might abuse it. Signed-off-by: Laurent Pinchart Cc: Sudhakar Rajashekhara Cc: Martin Ambrose Signed-off-by: Paul Mundt --- drivers/video/da8xx-fb.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c index fcdac872522d..8d4e4ebd9977 100644 --- a/drivers/video/da8xx-fb.c +++ b/drivers/video/da8xx-fb.c @@ -877,8 +877,8 @@ static int da8xx_pan_display(struct fb_var_screeninfo *var, start = fix->smem_start + new_var.yoffset * fix->line_length + - new_var.xoffset * var->bits_per_pixel / 8; - end = start + var->yres * fix->line_length - 1; + new_var.xoffset * fbi->var.bits_per_pixel / 8; + end = start + fbi->var.yres * fix->line_length - 1; par->dma_start = start; par->dma_end = end; } -- cgit v1.2.3 From c329f606a23e13fe952768cb9c32ea929ed91480 Mon Sep 17 00:00:00 2001 From: Manuel Lauss Date: Fri, 10 Jun 2011 15:23:01 +0000 Subject: au1200fb: use framebuffer_alloc() Convert to use framebuffer_alloc() instead of using fb_info embedded into device context (which broke the driver in the past due to un- initialized elements). Signed-off-by: Manuel Lauss Signed-off-by: Paul Mundt --- drivers/video/au1200fb.c | 80 ++++++++++++++++++++++++++++-------------------- 1 file changed, 46 insertions(+), 34 deletions(-) diff --git a/drivers/video/au1200fb.c b/drivers/video/au1200fb.c index 5dff32ac8044..442d005e452d 100644 --- a/drivers/video/au1200fb.c +++ b/drivers/video/au1200fb.c @@ -150,7 +150,7 @@ struct au1200_lcd_iodata_t { /* Private, per-framebuffer management information (independent of the panel itself) */ struct au1200fb_device { - struct fb_info fb_info; /* FB driver info record */ + struct fb_info *fb_info; /* FB driver info record */ int plane; unsigned char* fb_mem; /* FrameBuffer memory map */ @@ -158,7 +158,7 @@ struct au1200fb_device { dma_addr_t fb_phys; }; -static struct au1200fb_device _au1200fb_devices[CONFIG_FB_AU1200_DEVS]; +static struct fb_info *_au1200fb_infos[CONFIG_FB_AU1200_DEVS]; /********************************************************************/ /* LCD controller restrictions */ @@ -713,7 +713,7 @@ static int fbinfo2index (struct fb_info *fb_info) int i; for (i = 0; i < CONFIG_FB_AU1200_DEVS; ++i) { - if (fb_info == (struct fb_info *)(&_au1200fb_devices[i].fb_info)) + if (fb_info == _au1200fb_infos[i]) return i; } printk("au1200fb: ERROR: fbinfo2index failed!\n"); @@ -962,7 +962,7 @@ static void au1200_setmode(struct au1200fb_device *fbdev) lcd->window[plane].winctrl2 = ( 0 | LCD_WINCTRL2_CKMODE_00 | LCD_WINCTRL2_DBM - | LCD_WINCTRL2_BX_N( fbdev->fb_info.fix.line_length) + | LCD_WINCTRL2_BX_N(fbdev->fb_info->fix.line_length) | LCD_WINCTRL2_SCX_1 | LCD_WINCTRL2_SCY_1 ) ; @@ -1050,7 +1050,7 @@ static void au1200fb_update_fbinfo(struct fb_info *fbi) static int au1200fb_fb_check_var(struct fb_var_screeninfo *var, struct fb_info *fbi) { - struct au1200fb_device *fbdev = (struct au1200fb_device *)fbi; + struct au1200fb_device *fbdev = fbi->par; u32 pixclock; int screen_size, plane; @@ -1142,7 +1142,7 @@ static int au1200fb_fb_check_var(struct fb_var_screeninfo *var, */ static int au1200fb_fb_set_par(struct fb_info *fbi) { - struct au1200fb_device *fbdev = (struct au1200fb_device *)fbi; + struct au1200fb_device *fbdev = fbi->par; au1200fb_update_fbinfo(fbi); au1200_setmode(fbdev); @@ -1246,7 +1246,7 @@ static int au1200fb_fb_mmap(struct fb_info *info, struct vm_area_struct *vma) { unsigned int len; unsigned long start=0, off; - struct au1200fb_device *fbdev = (struct au1200fb_device *) info; + struct au1200fb_device *fbdev = info->par; #ifdef CONFIG_PM au1xxx_pm_access(LCD_pm_dev); @@ -1561,10 +1561,9 @@ static irqreturn_t au1200fb_handle_irq(int irq, void* dev_id) static int au1200fb_init_fbinfo(struct au1200fb_device *fbdev) { - struct fb_info *fbi = &fbdev->fb_info; + struct fb_info *fbi = fbdev->fb_info; int bpp; - memset(fbi, 0, sizeof(struct fb_info)); fbi->fbops = &au1200fb_fb_ops; bpp = winbpp(win->w[fbdev->plane].mode_winctrl1); @@ -1626,11 +1625,13 @@ static int au1200fb_init_fbinfo(struct au1200fb_device *fbdev) static int au1200fb_drv_probe(struct platform_device *dev) { struct au1200fb_device *fbdev; + struct fb_info *fbi = NULL; unsigned long page; int bpp, plane, ret; - if (!dev) - return -EINVAL; + /* shut gcc up */ + ret = 0; + fbdev = NULL; for (plane = 0; plane < CONFIG_FB_AU1200_DEVS; ++plane) { bpp = winbpp(win->w[plane].mode_winctrl1); @@ -1639,8 +1640,15 @@ static int au1200fb_drv_probe(struct platform_device *dev) if (win->w[plane].yres == 0) win->w[plane].yres = panel->Yres; - fbdev = &_au1200fb_devices[plane]; - memset(fbdev, 0, sizeof(struct au1200fb_device)); + fbi = framebuffer_alloc(sizeof(struct au1200fb_device), + &dev->dev); + if (!fbi) + goto failed; + + _au1200fb_infos[plane] = fbi; + fbdev = fbi->par; + fbdev->fb_info = fbi; + fbdev->plane = plane; /* Allocate the framebuffer to the maximum screen size */ @@ -1673,21 +1681,20 @@ static int au1200fb_drv_probe(struct platform_device *dev) goto failed; /* Register new framebuffer */ - if ((ret = register_framebuffer(&fbdev->fb_info)) < 0) { + ret = register_framebuffer(fbi); + if (ret < 0) { print_err("cannot register new framebuffer"); goto failed; } - au1200fb_fb_set_par(&fbdev->fb_info); + au1200fb_fb_set_par(fbi); #if !defined(CONFIG_FRAMEBUFFER_CONSOLE) && defined(CONFIG_LOGO) if (plane == 0) - if (fb_prepare_logo(&fbdev->fb_info, FB_ROTATE_UR)) { + if (fb_prepare_logo(fbi, FB_ROTATE_UR)) { /* Start display and show logo on boot */ - fb_set_cmap(&fbdev->fb_info.cmap, - &fbdev->fb_info); - - fb_show_logo(&fbdev->fb_info, FB_ROTATE_UR); + fb_set_cmap(&fbi->cmap, fbi); + fb_show_logo(fbi, FB_ROTATE_UR); } #endif } @@ -1705,12 +1712,13 @@ static int au1200fb_drv_probe(struct platform_device *dev) failed: /* NOTE: This only does the current plane/window that failed; others are still active */ if (fbdev->fb_mem) - dma_free_noncoherent(dev, PAGE_ALIGN(fbdev->fb_len), + dma_free_noncoherent(&dev->dev, PAGE_ALIGN(fbdev->fb_len), fbdev->fb_mem, fbdev->fb_phys); - if (fbdev->fb_info.cmap.len != 0) - fb_dealloc_cmap(&fbdev->fb_info.cmap); - if (fbdev->fb_info.pseudo_palette) - kfree(fbdev->fb_info.pseudo_palette); + if (fbi) { + if (fbi->cmap.len != 0) + fb_dealloc_cmap(&fbi->cmap); + kfree(fbi->pseudo_palette); + } if (plane == 0) free_irq(AU1200_LCD_INT, (void*)dev); return ret; @@ -1719,6 +1727,7 @@ failed: static int au1200fb_drv_remove(struct platform_device *dev) { struct au1200fb_device *fbdev; + struct fb_info *fbi; int plane; if (!dev) @@ -1727,20 +1736,22 @@ static int au1200fb_drv_remove(struct platform_device *dev) /* Turn off the panel */ au1200_setpanel(NULL); - for (plane = 0; plane < CONFIG_FB_AU1200_DEVS; ++plane) - { - fbdev = &_au1200fb_devices[plane]; + for (plane = 0; plane < CONFIG_FB_AU1200_DEVS; ++plane) { + fbi = _au1200fb_infos[plane]; + fbdev = fbi->par; /* Clean up all probe data */ - unregister_framebuffer(&fbdev->fb_info); + unregister_framebuffer(fbi); if (fbdev->fb_mem) dma_free_noncoherent(&dev->dev, PAGE_ALIGN(fbdev->fb_len), fbdev->fb_mem, fbdev->fb_phys); - if (fbdev->fb_info.cmap.len != 0) - fb_dealloc_cmap(&fbdev->fb_info.cmap); - if (fbdev->fb_info.pseudo_palette) - kfree(fbdev->fb_info.pseudo_palette); + if (fbi->cmap.len != 0) + fb_dealloc_cmap(&fbi->cmap); + kfree(fbi->pseudo_palette); + + framebuffer_release(fbi); + _au1200fb_infos[plane] = NULL; } free_irq(AU1200_LCD_INT, (void *)dev); @@ -1749,7 +1760,8 @@ static int au1200fb_drv_remove(struct platform_device *dev) } #ifdef CONFIG_PM -static int au1200fb_drv_suspend(struct platform_device *dev, u32 state) +static int au1200fb_drv_suspend(struct platform_device *dev, + pm_message_t state) { /* TODO */ return 0; -- cgit v1.2.3 From 98707fcc044c2e6120448041bf738d1b134cfaa4 Mon Sep 17 00:00:00 2001 From: Manuel Lauss Date: Fri, 10 Jun 2011 15:23:02 +0000 Subject: au1200fb: fixup PM Remove last traces of the unused custom Alchemy PM code, implement suspend/resume callbacks. Signed-off-by: Manuel Lauss Signed-off-by: Paul Mundt --- drivers/video/au1200fb.c | 154 ++++++++++++----------------------------------- 1 file changed, 39 insertions(+), 115 deletions(-) diff --git a/drivers/video/au1200fb.c b/drivers/video/au1200fb.c index 442d005e452d..480ecb1b9d0b 100644 --- a/drivers/video/au1200fb.c +++ b/drivers/video/au1200fb.c @@ -46,10 +46,6 @@ #include #include "au1200fb.h" -#ifdef CONFIG_PM -#include -#endif - #ifndef CONFIG_FB_AU1200_DEVS #define CONFIG_FB_AU1200_DEVS 4 #endif @@ -205,12 +201,6 @@ struct window_settings { extern int board_au1200fb_panel_init (void); extern int board_au1200fb_panel_shutdown (void); -#ifdef CONFIG_PM -int au1200fb_pm_callback(au1xxx_power_dev_t *dev, - au1xxx_request_t request, void *data); -au1xxx_power_dev_t *LCD_pm_dev; -#endif - /* * Default window configurations */ @@ -652,25 +642,6 @@ static struct panel_settings known_lcd_panels[] = /********************************************************************/ -#ifdef CONFIG_PM -static int set_brightness(unsigned int brightness) -{ - unsigned int hi1, divider; - - /* limit brightness pwm duty to >= 30/1600 */ - if (brightness < 30) { - brightness = 30; - } - divider = (lcd->pwmdiv & 0x3FFFF) + 1; - hi1 = (lcd->pwmhi >> 16) + 1; - hi1 = (((brightness & 0xFF) + 1) * divider >> 8); - lcd->pwmhi &= 0xFFFF; - lcd->pwmhi |= (hi1 << 16); - - return brightness; -} -#endif /* CONFIG_PM */ - static int winbpp (unsigned int winctrl1) { int bits = 0; @@ -1248,10 +1219,6 @@ static int au1200fb_fb_mmap(struct fb_info *info, struct vm_area_struct *vma) unsigned long start=0, off; struct au1200fb_device *fbdev = info->par; -#ifdef CONFIG_PM - au1xxx_pm_access(LCD_pm_dev); -#endif - if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT)) { return -EINVAL; } @@ -1461,10 +1428,6 @@ static int au1200fb_ioctl(struct fb_info *info, unsigned int cmd, int plane; int val; -#ifdef CONFIG_PM - au1xxx_pm_access(LCD_pm_dev); -#endif - plane = fbinfo2index(info); print_dbg("au1200fb: ioctl %d on plane %d\n", cmd, plane); @@ -1622,7 +1585,7 @@ static int au1200fb_init_fbinfo(struct au1200fb_device *fbdev) /* AU1200 LCD controller device driver */ -static int au1200fb_drv_probe(struct platform_device *dev) +static int __devinit au1200fb_drv_probe(struct platform_device *dev) { struct au1200fb_device *fbdev; struct fb_info *fbi = NULL; @@ -1633,6 +1596,9 @@ static int au1200fb_drv_probe(struct platform_device *dev) ret = 0; fbdev = NULL; + /* Kickstart the panel */ + au1200_setpanel(panel); + for (plane = 0; plane < CONFIG_FB_AU1200_DEVS; ++plane) { bpp = winbpp(win->w[plane].mode_winctrl1); if (win->w[plane].xres == 0) @@ -1724,15 +1690,12 @@ failed: return ret; } -static int au1200fb_drv_remove(struct platform_device *dev) +static int __devexit au1200fb_drv_remove(struct platform_device *dev) { struct au1200fb_device *fbdev; struct fb_info *fbi; int plane; - if (!dev) - return -ENODEV; - /* Turn off the panel */ au1200_setpanel(NULL); @@ -1760,31 +1723,53 @@ static int au1200fb_drv_remove(struct platform_device *dev) } #ifdef CONFIG_PM -static int au1200fb_drv_suspend(struct platform_device *dev, - pm_message_t state) +static int au1200fb_drv_suspend(struct device *dev) { - /* TODO */ + au1200_setpanel(NULL); + + lcd->outmask = 0; + au_sync(); + return 0; } -static int au1200fb_drv_resume(struct platform_device *dev) +static int au1200fb_drv_resume(struct device *dev) { - /* TODO */ + struct fb_info *fbi; + int i; + + /* Kickstart the panel */ + au1200_setpanel(panel); + + for (i = 0; i < CONFIG_FB_AU1200_DEVS; i++) { + fbi = _au1200fb_infos[i]; + au1200fb_fb_set_par(fbi); + } + return 0; } + +static const struct dev_pm_ops au1200fb_pmops = { + .suspend = au1200fb_drv_suspend, + .resume = au1200fb_drv_resume, + .freeze = au1200fb_drv_suspend, + .thaw = au1200fb_drv_resume, +}; + +#define AU1200FB_PMOPS (&au1200fb_pmops) + +#else +#define AU1200FB_PMOPS NULL #endif /* CONFIG_PM */ static struct platform_driver au1200fb_driver = { .driver = { - .name = "au1200-lcd", - .owner = THIS_MODULE, + .name = "au1200-lcd", + .owner = THIS_MODULE, + .pm = AU1200FB_PMOPS, }, .probe = au1200fb_drv_probe, - .remove = au1200fb_drv_remove, -#ifdef CONFIG_PM - .suspend = au1200fb_drv_suspend, - .resume = au1200fb_drv_resume, -#endif + .remove = __devexit_p(au1200fb_drv_remove), }; /*-------------------------------------------------------------------------*/ @@ -1847,56 +1832,6 @@ static void au1200fb_setup(void) } } -#ifdef CONFIG_PM -static int au1200fb_pm_callback(au1xxx_power_dev_t *dev, - au1xxx_request_t request, void *data) { - int retval = -1; - unsigned int d = 0; - unsigned int brightness = 0; - - if (request == AU1XXX_PM_SLEEP) { - board_au1200fb_panel_shutdown(); - } - else if (request == AU1XXX_PM_WAKEUP) { - if(dev->prev_state == SLEEP_STATE) - { - int plane; - au1200_setpanel(panel); - for (plane = 0; plane < CONFIG_FB_AU1200_DEVS; ++plane) { - struct au1200fb_device *fbdev; - fbdev = &_au1200fb_devices[plane]; - au1200fb_fb_set_par(&fbdev->fb_info); - } - } - - d = *((unsigned int*)data); - if(d <=10) brightness = 26; - else if(d<=20) brightness = 51; - else if(d<=30) brightness = 77; - else if(d<=40) brightness = 102; - else if(d<=50) brightness = 128; - else if(d<=60) brightness = 153; - else if(d<=70) brightness = 179; - else if(d<=80) brightness = 204; - else if(d<=90) brightness = 230; - else brightness = 255; - set_brightness(brightness); - } else if (request == AU1XXX_PM_GETSTATUS) { - return dev->cur_state; - } else if (request == AU1XXX_PM_ACCESS) { - if (dev->cur_state != SLEEP_STATE) - return retval; - else { - au1200_setpanel(panel); - } - } else if (request == AU1XXX_PM_IDLE) { - } else if (request == AU1XXX_PM_CLEANUP) { - } - - return retval; -} -#endif - static int __init au1200fb_init(void) { print_info("" DRIVER_DESC ""); @@ -1911,17 +1846,6 @@ static int __init au1200fb_init(void) printk(DRIVER_NAME ": Panel %d %s\n", panel_index, panel->name); printk(DRIVER_NAME ": Win %d %s\n", window_index, win->name); - /* Kickstart the panel, the framebuffers/windows come soon enough */ - au1200_setpanel(panel); - - #ifdef CONFIG_PM - LCD_pm_dev = new_au1xxx_power_device("LCD", &au1200fb_pm_callback, NULL); - if ( LCD_pm_dev == NULL) - printk(KERN_INFO "Unable to create a power management device entry for the au1200fb.\n"); - else - printk(KERN_INFO "Power management device entry for the au1200fb loaded.\n"); - #endif - return platform_driver_register(&au1200fb_driver); } -- cgit v1.2.3 From 8be90b07ac2a07b4f1eb685caa97e88b9f85ef27 Mon Sep 17 00:00:00 2001 From: Manuel Lauss Date: Fri, 10 Jun 2011 15:23:03 +0000 Subject: au1200fb: make number of windows configurable at load time. Make the number of framebuffer windows and the window configuration selectable at the kernel commandline instead of hardcoding it in the kernel config. Signed-off-by: Manuel Lauss Signed-off-by: Paul Mundt --- drivers/video/au1200fb.c | 53 +++++++++++++++++++++++++++++++++++------------- 1 file changed, 39 insertions(+), 14 deletions(-) diff --git a/drivers/video/au1200fb.c b/drivers/video/au1200fb.c index 480ecb1b9d0b..4b58f7ba5728 100644 --- a/drivers/video/au1200fb.c +++ b/drivers/video/au1200fb.c @@ -46,10 +46,6 @@ #include #include "au1200fb.h" -#ifndef CONFIG_FB_AU1200_DEVS -#define CONFIG_FB_AU1200_DEVS 4 -#endif - #define DRIVER_NAME "au1200fb" #define DRIVER_DESC "LCD controller driver for AU1200 processors" @@ -154,7 +150,6 @@ struct au1200fb_device { dma_addr_t fb_phys; }; -static struct fb_info *_au1200fb_infos[CONFIG_FB_AU1200_DEVS]; /********************************************************************/ /* LCD controller restrictions */ @@ -167,10 +162,18 @@ static struct fb_info *_au1200fb_infos[CONFIG_FB_AU1200_DEVS]; /* Default number of visible screen buffer to allocate */ #define AU1200FB_NBR_VIDEO_BUFFERS 1 +/* Default maximum number of fb devices to create */ +#define MAX_DEVICE_COUNT 4 + +/* Default window configuration entry to use (see windows[]) */ +#define DEFAULT_WINDOW_INDEX 2 + /********************************************************************/ +static struct fb_info *_au1200fb_infos[MAX_DEVICE_COUNT]; static struct au1200_lcd *lcd = (struct au1200_lcd *) AU1200_LCD_ADDR; -static int window_index = 2; /* default is zero */ +static int device_count = MAX_DEVICE_COUNT; +static int window_index = DEFAULT_WINDOW_INDEX; /* default is zero */ static int panel_index = 2; /* default is zero */ static struct window_settings *win; static struct panel_settings *panel; @@ -683,7 +686,7 @@ static int fbinfo2index (struct fb_info *fb_info) { int i; - for (i = 0; i < CONFIG_FB_AU1200_DEVS; ++i) { + for (i = 0; i < device_count; ++i) { if (fb_info == _au1200fb_infos[i]) return i; } @@ -1599,7 +1602,7 @@ static int __devinit au1200fb_drv_probe(struct platform_device *dev) /* Kickstart the panel */ au1200_setpanel(panel); - for (plane = 0; plane < CONFIG_FB_AU1200_DEVS; ++plane) { + for (plane = 0; plane < device_count; ++plane) { bpp = winbpp(win->w[plane].mode_winctrl1); if (win->w[plane].xres == 0) win->w[plane].xres = panel->Xres; @@ -1699,7 +1702,7 @@ static int __devexit au1200fb_drv_remove(struct platform_device *dev) /* Turn off the panel */ au1200_setpanel(NULL); - for (plane = 0; plane < CONFIG_FB_AU1200_DEVS; ++plane) { + for (plane = 0; plane < device_count; ++plane) { fbi = _au1200fb_infos[plane]; fbdev = fbi->par; @@ -1741,7 +1744,7 @@ static int au1200fb_drv_resume(struct device *dev) /* Kickstart the panel */ au1200_setpanel(panel); - for (i = 0; i < CONFIG_FB_AU1200_DEVS; i++) { + for (i = 0; i < device_count; i++) { fbi = _au1200fb_infos[i]; au1200fb_fb_set_par(fbi); } @@ -1776,10 +1779,10 @@ static struct platform_driver au1200fb_driver = { /* Kernel driver */ -static void au1200fb_setup(void) +static int au1200fb_setup(void) { - char* options = NULL; - char* this_opt; + char *options = NULL; + char *this_opt, *endptr; int num_panels = ARRAY_SIZE(known_lcd_panels); int panel_idx = -1; @@ -1824,12 +1827,33 @@ static void au1200fb_setup(void) nohwcursor = 1; } + else if (strncmp(this_opt, "devices:", 8) == 0) { + this_opt += 8; + device_count = simple_strtol(this_opt, + &endptr, 0); + if ((device_count < 0) || + (device_count > MAX_DEVICE_COUNT)) + device_count = MAX_DEVICE_COUNT; + } + + else if (strncmp(this_opt, "wincfg:", 7) == 0) { + this_opt += 7; + window_index = simple_strtol(this_opt, + &endptr, 0); + if ((window_index < 0) || + (window_index >= ARRAY_SIZE(windows))) + window_index = DEFAULT_WINDOW_INDEX; + } + + else if (strncmp(this_opt, "off", 3) == 0) + return 1; /* Unsupported option */ else { print_warn("Unsupported option \"%s\"", this_opt); } } } + return 0; } static int __init au1200fb_init(void) @@ -1837,7 +1861,8 @@ static int __init au1200fb_init(void) print_info("" DRIVER_DESC ""); /* Setup driver with options */ - au1200fb_setup(); + if (au1200fb_setup()) + return -ENODEV; /* Point to the panel selected */ panel = &known_lcd_panels[panel_index]; -- cgit v1.2.3 From 4ee58461510221a53080afd02752838f93cc57fc Mon Sep 17 00:00:00 2001 From: Manuel Lauss Date: Fri, 10 Jun 2011 15:23:04 +0000 Subject: au1200fb: switch to FB_SYS helpers Since all video memory is in system ram, use FB_SYS helpers. Signed-off-by: Manuel Lauss Signed-off-by: Paul Mundt --- drivers/video/Kconfig | 7 ++++--- drivers/video/au1200fb.c | 8 +++++--- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 549b960667c8..5e19de97242a 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -1756,9 +1756,10 @@ config FB_AU1100 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 diff --git a/drivers/video/au1200fb.c b/drivers/video/au1200fb.c index 4b58f7ba5728..b1b16d98c919 100644 --- a/drivers/video/au1200fb.c +++ b/drivers/video/au1200fb.c @@ -1502,9 +1502,11 @@ static struct fb_ops au1200fb_fb_ops = { .fb_set_par = au1200fb_fb_set_par, .fb_setcolreg = au1200fb_fb_setcolreg, .fb_blank = au1200fb_fb_blank, - .fb_fillrect = cfb_fillrect, - .fb_copyarea = cfb_copyarea, - .fb_imageblit = cfb_imageblit, + .fb_fillrect = sys_fillrect, + .fb_copyarea = sys_copyarea, + .fb_imageblit = sys_imageblit, + .fb_read = fb_sys_read, + .fb_write = fb_sys_write, .fb_sync = NULL, .fb_ioctl = au1200fb_ioctl, .fb_mmap = au1200fb_fb_mmap, -- cgit v1.2.3 From 1630d85a831273868651d46d74f069e0cdf9b698 Mon Sep 17 00:00:00 2001 From: Manuel Lauss Date: Sun, 12 Jun 2011 17:15:29 +0000 Subject: au1200fb: fix hardcoded IRQ Use the IRQ provided by platform resource information. Required for Au1300 support. Signed-off-by: Manuel Lauss Signed-off-by: Paul Mundt --- drivers/video/au1200fb.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/drivers/video/au1200fb.c b/drivers/video/au1200fb.c index b1b16d98c919..ed5dcdb29cf7 100644 --- a/drivers/video/au1200fb.c +++ b/drivers/video/au1200fb.c @@ -1595,7 +1595,7 @@ static int __devinit au1200fb_drv_probe(struct platform_device *dev) struct au1200fb_device *fbdev; struct fb_info *fbi = NULL; unsigned long page; - int bpp, plane, ret; + int bpp, plane, ret, irq; /* shut gcc up */ ret = 0; @@ -1671,10 +1671,12 @@ static int __devinit au1200fb_drv_probe(struct platform_device *dev) } /* Now hook interrupt too */ - if ((ret = request_irq(AU1200_LCD_INT, au1200fb_handle_irq, - IRQF_DISABLED | IRQF_SHARED, "lcd", (void *)dev)) < 0) { + irq = platform_get_irq(dev, 0); + ret = request_irq(irq, au1200fb_handle_irq, + IRQF_DISABLED | IRQF_SHARED, "lcd", (void *)dev); + if (ret) { print_err("fail to request interrupt line %d (err: %d)", - AU1200_LCD_INT, ret); + irq, ret); goto failed; } @@ -1722,7 +1724,7 @@ static int __devexit au1200fb_drv_remove(struct platform_device *dev) _au1200fb_infos[plane] = NULL; } - free_irq(AU1200_LCD_INT, (void *)dev); + free_irq(platform_get_irq(dev, 0), (void *)dev); return 0; } -- cgit v1.2.3 From 181b74ef794e198df36fbc8c962126a11a01d395 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 15 Jun 2011 16:57:21 +0200 Subject: video: don't use flush_scheduled_work() in fb_defio flush_scheduled_work() in on the way out. fb_deferred_io_cleanup() can simply sync-cancel info->deferred_work instead of cancel + flush_scheduled_work(). Drop flush_scheduled_work() usage. Signed-off-by: Tejun Heo Cc: Jaya Kumar Signed-off-by: Paul Mundt --- drivers/video/fb_defio.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/video/fb_defio.c b/drivers/video/fb_defio.c index 804000183c5e..a79c0dedfbd4 100644 --- a/drivers/video/fb_defio.c +++ b/drivers/video/fb_defio.c @@ -216,8 +216,7 @@ void fb_deferred_io_cleanup(struct fb_info *info) 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) { -- cgit v1.2.3 From 75e1b6a84f7e2186e843da94751b6d175caf9209 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Thu, 23 Jun 2011 22:35:19 +0000 Subject: video: Fix speficied typo Signed-off-by: Joe Perches Signed-off-by: Paul Mundt --- drivers/video/controlfb.c | 2 +- drivers/video/platinumfb.c | 2 +- drivers/video/pm2fb.c | 2 +- drivers/video/pm3fb.c | 2 +- drivers/video/s3fb.c | 2 +- drivers/video/skeletonfb.c | 2 +- drivers/video/valkyriefb.c | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/video/controlfb.c b/drivers/video/controlfb.c index c225dcce89e7..f6944019cb66 100644 --- a/drivers/video/controlfb.c +++ b/drivers/video/controlfb.c @@ -550,7 +550,7 @@ static void control_set_hardware(struct fb_info_control *p, struct fb_par_contro /* - * Parse user speficied options (`video=controlfb:') + * Parse user specified options (`video=controlfb:') */ static void __init control_setup(char *options) { diff --git a/drivers/video/platinumfb.c b/drivers/video/platinumfb.c index ef532d9d3c99..a0d0c3d625b9 100644 --- a/drivers/video/platinumfb.c +++ b/drivers/video/platinumfb.c @@ -490,7 +490,7 @@ static int platinum_var_to_par(struct fb_var_screeninfo *var, /* - * Parse user speficied options (`video=platinumfb:') + * Parse user specified options (`video=platinumfb:') */ static int __init platinumfb_setup(char *options) { diff --git a/drivers/video/pm2fb.c b/drivers/video/pm2fb.c index f4f8ce802d02..dc7bfa91e57a 100644 --- a/drivers/video/pm2fb.c +++ b/drivers/video/pm2fb.c @@ -1773,7 +1773,7 @@ MODULE_DEVICE_TABLE(pci, pm2fb_id_table); #ifndef MODULE /** - * Parse user speficied options. + * Parse user specified options. * * This is, comma-separated options following `video=pm2fb:'. */ diff --git a/drivers/video/pm3fb.c b/drivers/video/pm3fb.c index 8221b5b42da9..6632ee5ecb7e 100644 --- a/drivers/video/pm3fb.c +++ b/drivers/video/pm3fb.c @@ -1525,7 +1525,7 @@ static int __init pm3fb_setup(char *options) { char *this_opt; - /* Parse user speficied options (`video=pm3fb:') */ + /* Parse user specified options (`video=pm3fb:') */ if (!options || !*options) return 0; diff --git a/drivers/video/s3fb.c b/drivers/video/s3fb.c index 0f9af1aa5077..946a949f4c7d 100644 --- a/drivers/video/s3fb.c +++ b/drivers/video/s3fb.c @@ -1505,7 +1505,7 @@ static struct pci_driver s3fb_pci_driver = { .resume = s3_pci_resume, }; -/* Parse user speficied options */ +/* Parse user specified options */ #ifndef MODULE static int __init s3fb_setup(char *options) diff --git a/drivers/video/skeletonfb.c b/drivers/video/skeletonfb.c index 89158bc71da2..30f7a815a62b 100644 --- a/drivers/video/skeletonfb.c +++ b/drivers/video/skeletonfb.c @@ -989,7 +989,7 @@ static struct platform_device *xxxfb_device; */ int __init xxxfb_setup(char *options) { - /* Parse user speficied options (`video=xxxfb:') */ + /* Parse user specified options (`video=xxxfb:') */ } #endif /* MODULE */ diff --git a/drivers/video/valkyriefb.c b/drivers/video/valkyriefb.c index 6b52bf65f0b5..3f5a041601da 100644 --- a/drivers/video/valkyriefb.c +++ b/drivers/video/valkyriefb.c @@ -555,7 +555,7 @@ static int __init valkyrie_init_info(struct fb_info *info, /* - * Parse user speficied options (`video=valkyriefb:') + * Parse user specified options (`video=valkyriefb:') */ int __init valkyriefb_setup(char *options) { -- cgit v1.2.3 From dd37739f47ea278a57d66b2afe20243f0a6294a0 Mon Sep 17 00:00:00 2001 From: Jesper Juhl Date: Thu, 23 Jun 2011 22:35:17 +0000 Subject: Remove unneeded version.h includes from drivers/video/ It was pointed out by 'make versioncheck' that some includes of linux/version.h are not needed in drivers/video/. This patch removes them. Signed-off-by: Jesper Juhl Acked-by: Mike Frysinger Signed-off-by: Paul Mundt --- drivers/video/backlight/adp8860_bl.c | 1 - drivers/video/backlight/adp8870_bl.c | 1 - drivers/video/pxa3xx-gcu.c | 2 -- drivers/video/xilinxfb.c | 1 - 4 files changed, 5 deletions(-) diff --git a/drivers/video/backlight/adp8860_bl.c b/drivers/video/backlight/adp8860_bl.c index d2a96a421ffd..24a6dfd21b35 100644 --- a/drivers/video/backlight/adp8860_bl.c +++ b/drivers/video/backlight/adp8860_bl.c @@ -7,7 +7,6 @@ */ #include -#include #include #include #include diff --git a/drivers/video/backlight/adp8870_bl.c b/drivers/video/backlight/adp8870_bl.c index 05a8832bb3eb..383c4c364b5f 100644 --- a/drivers/video/backlight/adp8870_bl.c +++ b/drivers/video/backlight/adp8870_bl.c @@ -7,7 +7,6 @@ */ #include -#include #include #include #include diff --git a/drivers/video/pxa3xx-gcu.c b/drivers/video/pxa3xx-gcu.c index 0283c7021090..d8de5577d3cf 100644 --- a/drivers/video/pxa3xx-gcu.c +++ b/drivers/video/pxa3xx-gcu.c @@ -31,8 +31,6 @@ */ #include -#include - #include #include #include diff --git a/drivers/video/xilinxfb.c b/drivers/video/xilinxfb.c index 77dea015ff69..fcb6cd90f64d 100644 --- a/drivers/video/xilinxfb.c +++ b/drivers/video/xilinxfb.c @@ -23,7 +23,6 @@ #include #include #include -#include #include #include #include -- cgit v1.2.3 From 945903c7a477784e796168ef87b5022241cb52b5 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Mon, 4 Jul 2011 16:11:45 +0200 Subject: drivers/video/msm/mdp.c: adjust error handling code Use the error handling code at the end of the function, rather than returning directly. The semantic match that finds this problem is as follows: (http://coccinelle.lip6.fr/) // @r@ identifier x; @@ kfree(x) @@ identifier r.x; expression E1!=0,E2,E3,E4; statement S; @@ ( if (<+...x...+>) S | if (...) { ... when != kfree(x) when != if (...) { ... kfree(x); ... } when != x = E3 * return E1; } ... when != x = E2 if (...) { ... when != x = E4 kfree(x); ... return ...; } ) // Signed-off-by: Julia Lawall Signed-off-by: Paul Mundt --- drivers/video/msm/mdp.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/video/msm/mdp.c b/drivers/video/msm/mdp.c index c3636d55a3c5..7e94ee3d2521 100644 --- a/drivers/video/msm/mdp.c +++ b/drivers/video/msm/mdp.c @@ -422,7 +422,8 @@ int mdp_probe(struct platform_device *pdev) 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); @@ -496,6 +497,7 @@ int mdp_probe(struct platform_device *pdev) error_device_register: free_irq(mdp->irq, mdp); error_request_irq: +error_get_clk: iounmap(mdp->base); error_get_irq: error_ioremap: -- cgit v1.2.3 From c91a793f66d5b06292aa431ae3a36c8aca991fa3 Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Tue, 5 Jul 2011 17:04:11 -0700 Subject: drivers/video/udlfb bind framebuffer to interface. Udlfb has been binding the framebuffer device to its parent, which isn't correct and causes confusion with operations like udev remove. Coming plug and play multiseat support is dependent on this fix. Signed-off-by: Kay Sievers Signed-off-by: Bernie Thompson Signed-off-by: Paul Mundt --- drivers/video/udlfb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/video/udlfb.c b/drivers/video/udlfb.c index 816a4fda04f5..c6584c9f235a 100644 --- a/drivers/video/udlfb.c +++ b/drivers/video/udlfb.c @@ -1549,7 +1549,7 @@ static int dlfb_usb_probe(struct usb_interface *interface, /* 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"); -- cgit v1.2.3 From af48d1c6c85752053ddfed5cfb3933d6336d645c Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Thu, 7 Jul 2011 12:20:37 +0200 Subject: video: s3c2410: remove unused variable Fixes: drivers/video/s3c2410fb.c: In function 's3c2410fb_cpufreq_transition': drivers/video/s3c2410fb.c:770:24: warning: unused variable 'freqs' Signed-off-by: Wolfram Sang Cc: Paul Mundt Signed-off-by: Paul Mundt --- drivers/video/s3c2410fb.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/video/s3c2410fb.c b/drivers/video/s3c2410fb.c index 0aa13761de6e..798144a4eedd 100644 --- a/drivers/video/s3c2410fb.c +++ b/drivers/video/s3c2410fb.c @@ -767,7 +767,6 @@ static irqreturn_t s3c2410fb_irq(int irq, void *dev_id) static int s3c2410fb_cpufreq_transition(struct notifier_block *nb, unsigned long val, void *data) { - struct cpufreq_freqs *freqs = data; struct s3c2410fb_info *info; struct fb_info *fbinfo; long delta_f; -- cgit v1.2.3 From c84c14224bbca6ec60d5851fcc87be0e34df2f44 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Fri, 8 Jul 2011 11:04:38 +0200 Subject: carminefb: Fix module parameters permissions The third parameter of module_param is supposed to be an octal value. The missing leading "0" causes the following: $ ls -l /sys/module/carminefb/parameters/ total 0 -rw-rwxr-- 1 root root 4096 Jul 8 08:55 fb_displays -rw-rwxr-- 1 root root 4096 Jul 8 08:55 fb_mode -rw-rwxr-- 1 root root 4096 Jul 8 08:55 fb_mode_str After fixing the perm parameter, we get the expected: $ ls -l /sys/module/carminefb/parameters/ total 0 -r--r--r-- 1 root root 4096 Jul 8 08:56 fb_displays -r--r--r-- 1 root root 4096 Jul 8 08:56 fb_mode -r--r--r-- 1 root root 4096 Jul 8 08:56 fb_mode_str Signed-off-by: Jean Delvare Cc: Paul Mundt Cc: Sebastian Siewior Cc: stable@kernel.org Signed-off-by: Paul Mundt --- drivers/video/carminefb.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/video/carminefb.c b/drivers/video/carminefb.c index caaa27d4a46a..cb09aa1fa138 100644 --- a/drivers/video/carminefb.c +++ b/drivers/video/carminefb.c @@ -32,11 +32,11 @@ #define CARMINEFB_DEFAULT_VIDEO_MODE 1 static unsigned int fb_mode = CARMINEFB_DEFAULT_VIDEO_MODE; -module_param(fb_mode, uint, 444); +module_param(fb_mode, uint, 0444); MODULE_PARM_DESC(fb_mode, "Initial video mode as integer."); static char *fb_mode_str; -module_param(fb_mode_str, charp, 444); +module_param(fb_mode_str, charp, 0444); MODULE_PARM_DESC(fb_mode_str, "Initial video mode in characters."); /* @@ -46,7 +46,7 @@ MODULE_PARM_DESC(fb_mode_str, "Initial video mode in characters."); * 0b010 Display 1 */ static int fb_displays = CARMINE_USE_DISPLAY0 | CARMINE_USE_DISPLAY1; -module_param(fb_displays, int, 444); +module_param(fb_displays, int, 0444); MODULE_PARM_DESC(fb_displays, "Bit mode, which displays are used"); struct carmine_hw { -- cgit v1.2.3 From b63d10130e68aa6480cc1b2483d7c5ce57a05481 Mon Sep 17 00:00:00 2001 From: Bernie Thompson Date: Sun, 10 Jul 2011 00:30:00 -0700 Subject: drivers/video/udlfb match class, subclass, and protocol Match udlfb only against vendor-specific class (e.g. only DisplayLink graphics, not composite standard audio class interfaces). This enables compatibility with composite graphics+audio devices (e.g. HDMI). Match udlfb only against compatible subclass 0 and protocol 0 chips. DisplayLink's USB 3.0 generation chips increment these values to signal that they have a incompatible protocol, preventing udlfb from erroneously matching to hardware it does not support. Tested to confirm proper behavior on both USB 2.0 and USB 3.0 generation devices. Reported-by: Andrew Kephart Signed-off-by: Bernie Thompson Signed-off-by: Paul Mundt --- drivers/video/udlfb.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/drivers/video/udlfb.c b/drivers/video/udlfb.c index c6584c9f235a..4e133754ba2b 100644 --- a/drivers/video/udlfb.c +++ b/drivers/video/udlfb.c @@ -49,13 +49,22 @@ static const u32 udlfb_info_flags = FBINFO_DEFAULT | FBINFO_READS_FAST | 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); -- cgit v1.2.3 From a4b8f97a8fdeb94492738c36fddbd2cf822ed138 Mon Sep 17 00:00:00 2001 From: Kristoffer Glembo Date: Tue, 5 Jul 2011 09:29:19 +0200 Subject: video: Add Aeroflex Gaisler GRVGA framebuffer device driver This patch adds support for the GRVGA framebuffer IP core from Aeroflex Gaisler. The device is used in LEON SPARCV8 based System on Chips. Documentation can be found here: www.gaisler.com/products/grlib/grip.pdf. Signed-off-by: Kristoffer Glembo Signed-off-by: Paul Mundt --- drivers/video/Kconfig | 9 + drivers/video/Makefile | 1 + drivers/video/grvga.c | 579 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 589 insertions(+) create mode 100644 drivers/video/grvga.c diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 5e19de97242a..e087fc2207e7 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -259,6 +259,15 @@ config FB_TILEBLITTING 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) diff --git a/drivers/video/Makefile b/drivers/video/Makefile index 8b83129e209c..43079108bb16 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile @@ -33,6 +33,7 @@ obj-$(CONFIG_FB_AMIGA) += amifb.o c2p_planar.o obj-$(CONFIG_FB_ARC) += arcfb.o obj-$(CONFIG_FB_CLPS711X) += clps711xfb.o obj-$(CONFIG_FB_CYBER2000) += cyber2000fb.o +obj-$(CONFIG_FB_GRVGA) += grvga.o obj-$(CONFIG_FB_PM2) += pm2fb.o obj-$(CONFIG_FB_PM3) += pm3fb.o diff --git a/drivers/video/grvga.c b/drivers/video/grvga.c new file mode 100644 index 000000000000..f37e02538203 --- /dev/null +++ b/drivers/video/grvga.c @@ -0,0 +1,579 @@ +/* + * Driver for Aeroflex Gaisler SVGACTRL framebuffer device. + * + * 2011 (c) Aeroflex Gaisler AB + * + * Full documentation of the core can be found here: + * http://www.gaisler.com/products/grlib/grip.pdf + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * Contributors: Kristoffer Glembo + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct grvga_regs { + u32 status; /* 0x00 */ + u32 video_length; /* 0x04 */ + u32 front_porch; /* 0x08 */ + u32 sync_length; /* 0x0C */ + u32 line_length; /* 0x10 */ + u32 fb_pos; /* 0x14 */ + u32 clk_vector[4]; /* 0x18 */ + u32 clut; /* 0x20 */ +}; + +struct grvga_par { + struct grvga_regs *regs; + u32 color_palette[16]; /* 16 entry pseudo palette used by fbcon in true color mode */ + int clk_sel; + int fb_alloced; /* = 1 if framebuffer is allocated in main memory */ +}; + + +static const struct fb_videomode grvga_modedb[] = { + { + /* 640x480 @ 60 Hz */ + NULL, 60, 640, 480, 40000, 48, 16, 39, 11, 96, 2, + 0, FB_VMODE_NONINTERLACED + }, { + /* 800x600 @ 60 Hz */ + NULL, 60, 800, 600, 25000, 88, 40, 23, 1, 128, 4, + 0, FB_VMODE_NONINTERLACED + }, { + /* 800x600 @ 72 Hz */ + NULL, 72, 800, 600, 20000, 64, 56, 23, 37, 120, 6, + 0, FB_VMODE_NONINTERLACED + }, { + /* 1024x768 @ 60 Hz */ + NULL, 60, 1024, 768, 15385, 160, 24, 29, 3, 136, 6, + 0, FB_VMODE_NONINTERLACED + } + }; + +static struct fb_fix_screeninfo grvga_fix __initdata = { + .id = "AG SVGACTRL", + .type = FB_TYPE_PACKED_PIXELS, + .visual = FB_VISUAL_PSEUDOCOLOR, + .xpanstep = 0, + .ypanstep = 1, + .ywrapstep = 0, + .accel = FB_ACCEL_NONE, +}; + +static int grvga_check_var(struct fb_var_screeninfo *var, + struct fb_info *info) +{ + struct grvga_par *par = info->par; + int i; + + if (!var->xres) + var->xres = 1; + if (!var->yres) + var->yres = 1; + if (var->bits_per_pixel <= 8) + var->bits_per_pixel = 8; + else if (var->bits_per_pixel <= 16) + var->bits_per_pixel = 16; + else if (var->bits_per_pixel <= 24) + var->bits_per_pixel = 24; + else if (var->bits_per_pixel <= 32) + var->bits_per_pixel = 32; + else + return -EINVAL; + + var->xres_virtual = var->xres; + var->yres_virtual = 2*var->yres; + + if (info->fix.smem_len) { + if ((var->yres_virtual*var->xres_virtual*var->bits_per_pixel/8) > info->fix.smem_len) + return -ENOMEM; + } + + /* Which clocks that are available can be read out in these registers */ + for (i = 0; i <= 3 ; i++) { + if (var->pixclock == par->regs->clk_vector[i]) + break; + } + if (i <= 3) + par->clk_sel = i; + else + return -EINVAL; + + switch (info->var.bits_per_pixel) { + case 8: + var->red = (struct fb_bitfield) {0, 8, 0}; /* offset, length, msb-right */ + var->green = (struct fb_bitfield) {0, 8, 0}; + var->blue = (struct fb_bitfield) {0, 8, 0}; + var->transp = (struct fb_bitfield) {0, 0, 0}; + break; + case 16: + var->red = (struct fb_bitfield) {11, 5, 0}; + var->green = (struct fb_bitfield) {5, 6, 0}; + var->blue = (struct fb_bitfield) {0, 5, 0}; + var->transp = (struct fb_bitfield) {0, 0, 0}; + break; + case 24: + case 32: + var->red = (struct fb_bitfield) {16, 8, 0}; + var->green = (struct fb_bitfield) {8, 8, 0}; + var->blue = (struct fb_bitfield) {0, 8, 0}; + var->transp = (struct fb_bitfield) {24, 8, 0}; + break; + default: + return -EINVAL; + } + + return 0; +} + +static int grvga_set_par(struct fb_info *info) +{ + + u32 func = 0; + struct grvga_par *par = info->par; + + __raw_writel(((info->var.yres - 1) << 16) | (info->var.xres - 1), + &par->regs->video_length); + + __raw_writel((info->var.lower_margin << 16) | (info->var.right_margin), + &par->regs->front_porch); + + __raw_writel((info->var.vsync_len << 16) | (info->var.hsync_len), + &par->regs->sync_length); + + __raw_writel(((info->var.yres + info->var.lower_margin + info->var.upper_margin + info->var.vsync_len - 1) << 16) | + (info->var.xres + info->var.right_margin + info->var.left_margin + info->var.hsync_len - 1), + &par->regs->line_length); + + switch (info->var.bits_per_pixel) { + case 8: + info->fix.visual = FB_VISUAL_PSEUDOCOLOR; + func = 1; + break; + case 16: + info->fix.visual = FB_VISUAL_TRUECOLOR; + func = 2; + break; + case 24: + case 32: + info->fix.visual = FB_VISUAL_TRUECOLOR; + func = 3; + break; + default: + return -EINVAL; + } + + __raw_writel((par->clk_sel << 6) | (func << 4) | 1, + &par->regs->status); + + info->fix.line_length = (info->var.xres_virtual*info->var.bits_per_pixel)/8; + return 0; +} + +static int grvga_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue, unsigned transp, struct fb_info *info) +{ + struct grvga_par *par; + par = info->par; + + if (regno >= 256) /* Size of CLUT */ + return -EINVAL; + + if (info->var.grayscale) { + /* grayscale = 0.30*R + 0.59*G + 0.11*B */ + red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8; + } + + + +#define CNVT_TOHW(val, width) ((((val)<<(width))+0x7FFF-(val))>>16) + + red = CNVT_TOHW(red, info->var.red.length); + green = CNVT_TOHW(green, info->var.green.length); + blue = CNVT_TOHW(blue, info->var.blue.length); + transp = CNVT_TOHW(transp, info->var.transp.length); + +#undef CNVT_TOHW + + /* In PSEUDOCOLOR we use the hardware CLUT */ + if (info->fix.visual == FB_VISUAL_PSEUDOCOLOR) + __raw_writel((regno << 24) | (red << 16) | (green << 8) | blue, + &par->regs->clut); + + /* Truecolor uses the pseudo palette */ + else if (info->fix.visual == FB_VISUAL_TRUECOLOR) { + u32 v; + if (regno >= 16) + return -EINVAL; + + + v = (red << info->var.red.offset) | + (green << info->var.green.offset) | + (blue << info->var.blue.offset) | + (transp << info->var.transp.offset); + + ((u32 *) (info->pseudo_palette))[regno] = v; + } + return 0; +} + +static int grvga_pan_display(struct fb_var_screeninfo *var, + struct fb_info *info) +{ + struct grvga_par *par = info->par; + struct fb_fix_screeninfo *fix = &info->fix; + u32 base_addr; + + if (var->xoffset != 0) + return -EINVAL; + + base_addr = fix->smem_start + (var->yoffset * fix->line_length); + base_addr &= ~3UL; + + /* Set framebuffer base address */ + __raw_writel(base_addr, + &par->regs->fb_pos); + + return 0; +} + +static struct fb_ops grvga_ops = { + .owner = THIS_MODULE, + .fb_check_var = grvga_check_var, + .fb_set_par = grvga_set_par, + .fb_setcolreg = grvga_setcolreg, + .fb_pan_display = grvga_pan_display, + .fb_fillrect = cfb_fillrect, + .fb_copyarea = cfb_copyarea, + .fb_imageblit = cfb_imageblit +}; + +static int __init grvga_parse_custom(char *options, + struct fb_var_screeninfo *screendata) +{ + char *this_opt; + int count = 0; + if (!options || !*options) + return -1; + + while ((this_opt = strsep(&options, " ")) != NULL) { + if (!*this_opt) + continue; + + switch (count) { + case 0: + screendata->pixclock = simple_strtoul(this_opt, NULL, 0); + count++; + break; + case 1: + screendata->xres = screendata->xres_virtual = simple_strtoul(this_opt, NULL, 0); + count++; + break; + case 2: + screendata->right_margin = simple_strtoul(this_opt, NULL, 0); + count++; + break; + case 3: + screendata->hsync_len = simple_strtoul(this_opt, NULL, 0); + count++; + break; + case 4: + screendata->left_margin = simple_strtoul(this_opt, NULL, 0); + count++; + break; + case 5: + screendata->yres = screendata->yres_virtual = simple_strtoul(this_opt, NULL, 0); + count++; + break; + case 6: + screendata->lower_margin = simple_strtoul(this_opt, NULL, 0); + count++; + break; + case 7: + screendata->vsync_len = simple_strtoul(this_opt, NULL, 0); + count++; + break; + case 8: + screendata->upper_margin = simple_strtoul(this_opt, NULL, 0); + count++; + break; + case 9: + screendata->bits_per_pixel = simple_strtoul(this_opt, NULL, 0); + count++; + break; + default: + return -1; + } + } + screendata->activate = FB_ACTIVATE_NOW; + screendata->vmode = FB_VMODE_NONINTERLACED; + return 0; +} + +static int __devinit grvga_probe(struct platform_device *dev) +{ + struct fb_info *info; + int retval = -ENOMEM; + unsigned long virtual_start; + unsigned long grvga_fix_addr = 0; + unsigned long physical_start = 0; + unsigned long grvga_mem_size = 0; + struct grvga_par *par = NULL; + char *options = NULL, *mode_opt = NULL; + + info = framebuffer_alloc(sizeof(struct grvga_par), &dev->dev); + if (!info) { + dev_err(&dev->dev, "framebuffer_alloc failed\n"); + return -ENOMEM; + } + + /* Expecting: "grvga: modestring, [addr:], [size:] + * + * If modestring is custom: we parse the string which then contains all videoparameters + * If address is left out, we allocate memory, + * if size is left out we only allocate enough to support the given mode. + */ + if (fb_get_options("grvga", &options)) { + retval = -ENODEV; + goto err; + } + + if (!options || !*options) + options = "640x480-8@60"; + + while (1) { + char *this_opt = strsep(&options, ","); + + if (!this_opt) + break; + + if (!strncmp(this_opt, "custom", 6)) { + if (grvga_parse_custom(this_opt, &info->var) < 0) { + dev_err(&dev->dev, "Failed to parse custom mode (%s).\n", this_opt); + retval = -EINVAL; + goto err1; + } + } else if (!strncmp(this_opt, "addr", 4)) + grvga_fix_addr = simple_strtoul(this_opt + 5, NULL, 16); + else if (!strncmp(this_opt, "size", 4)) + grvga_mem_size = simple_strtoul(this_opt + 5, NULL, 0); + else + mode_opt = this_opt; + } + + par = info->par; + info->fbops = &grvga_ops; + info->fix = grvga_fix; + info->pseudo_palette = par->color_palette; + info->flags = FBINFO_DEFAULT | FBINFO_PARTIAL_PAN_OK | FBINFO_HWACCEL_YPAN; + info->fix.smem_len = grvga_mem_size; + + if (!request_mem_region(dev->resource[0].start, resource_size(&dev->resource[0]), "grlib-svgactrl regs")) { + dev_err(&dev->dev, "registers already mapped\n"); + retval = -EBUSY; + goto err; + } + + par->regs = of_ioremap(&dev->resource[0], 0, + resource_size(&dev->resource[0]), + "grlib-svgactrl regs"); + + if (!par->regs) { + dev_err(&dev->dev, "failed to map registers\n"); + retval = -ENOMEM; + goto err1; + } + + retval = fb_alloc_cmap(&info->cmap, 256, 0); + if (retval < 0) { + dev_err(&dev->dev, "failed to allocate mem with fb_alloc_cmap\n"); + retval = -ENOMEM; + goto err2; + } + + if (mode_opt) { + retval = fb_find_mode(&info->var, info, mode_opt, + grvga_modedb, sizeof(grvga_modedb), &grvga_modedb[0], 8); + if (!retval || retval == 4) { + retval = -EINVAL; + goto err3; + } + } + + if (!grvga_mem_size) + grvga_mem_size = info->var.xres_virtual * info->var.yres_virtual * info->var.bits_per_pixel/8; + + if (grvga_fix_addr) { + /* Got framebuffer base address from argument list */ + + physical_start = grvga_fix_addr; + + if (!request_mem_region(physical_start, grvga_mem_size, dev->name)) { + dev_err(&dev->dev, "failed to request memory region\n"); + retval = -ENOMEM; + goto err3; + } + + virtual_start = (unsigned long) ioremap(physical_start, grvga_mem_size); + + if (!virtual_start) { + dev_err(&dev->dev, "error mapping framebuffer memory\n"); + retval = -ENOMEM; + goto err4; + } + } else { /* Allocate frambuffer memory */ + + unsigned long page; + + virtual_start = (unsigned long) __get_free_pages(GFP_DMA, + get_order(grvga_mem_size)); + if (!virtual_start) { + dev_err(&dev->dev, + "unable to allocate framebuffer memory (%lu bytes)\n", + grvga_mem_size); + retval = -ENOMEM; + goto err3; + } + + physical_start = dma_map_single(&dev->dev, (void *)virtual_start, grvga_mem_size, DMA_TO_DEVICE); + + /* Set page reserved so that mmap will work. This is necessary + * since we'll be remapping normal memory. + */ + for (page = virtual_start; + page < PAGE_ALIGN(virtual_start + grvga_mem_size); + page += PAGE_SIZE) { + SetPageReserved(virt_to_page(page)); + } + + par->fb_alloced = 1; + } + + memset((unsigned long *) virtual_start, 0, grvga_mem_size); + + info->screen_base = (char __iomem *) virtual_start; + info->fix.smem_start = physical_start; + info->fix.smem_len = grvga_mem_size; + + dev_set_drvdata(&dev->dev, info); + + dev_info(&dev->dev, + "Aeroflex Gaisler framebuffer device (fb%d), %dx%d-%d, using %luK of video memory @ %p\n", + info->node, info->var.xres, info->var.yres, info->var.bits_per_pixel, + grvga_mem_size >> 10, info->screen_base); + + retval = register_framebuffer(info); + if (retval < 0) { + dev_err(&dev->dev, "failed to register framebuffer\n"); + goto err4; + } + + __raw_writel(physical_start, &par->regs->fb_pos); + __raw_writel(__raw_readl(&par->regs->status) | 1, /* Enable framebuffer */ + &par->regs->status); + + return 0; + +err4: + dev_set_drvdata(&dev->dev, NULL); + if (grvga_fix_addr) { + release_mem_region(physical_start, grvga_mem_size); + iounmap((void *)virtual_start); + } else + kfree((void *)virtual_start); +err3: + fb_dealloc_cmap(&info->cmap); +err2: + of_iounmap(&dev->resource[0], par->regs, + resource_size(&dev->resource[0])); +err1: + release_mem_region(dev->resource[0].start, resource_size(&dev->resource[0])); +err: + framebuffer_release(info); + + return retval; +} + +static int __devexit grvga_remove(struct platform_device *device) +{ + struct fb_info *info = dev_get_drvdata(&device->dev); + struct grvga_par *par = info->par; + + if (info) { + unregister_framebuffer(info); + fb_dealloc_cmap(&info->cmap); + + of_iounmap(&device->resource[0], par->regs, + resource_size(&device->resource[0])); + release_mem_region(device->resource[0].start, resource_size(&device->resource[0])); + + if (!par->fb_alloced) { + release_mem_region(info->fix.smem_start, info->fix.smem_len); + iounmap(info->screen_base); + } else + kfree((void *)info->screen_base); + + framebuffer_release(info); + dev_set_drvdata(&device->dev, NULL); + } + + return 0; +} + +static struct of_device_id svgactrl_of_match[] = { + { + .name = "GAISLER_SVGACTRL", + }, + { + .name = "01_063", + }, + {}, +}; +MODULE_DEVICE_TABLE(of, svgactrl_of_match); + +static struct platform_driver grvga_driver = { + .driver = { + .name = "grlib-svgactrl", + .owner = THIS_MODULE, + .of_match_table = svgactrl_of_match, + }, + .probe = grvga_probe, + .remove = __devexit_p(grvga_remove), +}; + + +static int __init grvga_init(void) +{ + return platform_driver_register(&grvga_driver); +} + +static void __exit grvga_exit(void) +{ + platform_driver_unregister(&grvga_driver); +} + +module_init(grvga_init); +module_exit(grvga_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Aeroflex Gaisler"); +MODULE_DESCRIPTION("Aeroflex Gaisler framebuffer device driver"); -- cgit v1.2.3 From c6daf05b6d7afca4c9e04a7361e284ef9e1d8dad Mon Sep 17 00:00:00 2001 From: "Manjunathappa, Prakash" Date: Tue, 5 Jul 2011 15:51:20 +0530 Subject: video: da8xx-fb: Interrupt configuration of revised LCDC IP An upcoming SoC of TI comes with an LCD controller which is an updated version of that found on TI's DA850 SoC. The da8xx-fb driver can support this LCD with some enhancements. This patch adds support for updated interrupt configuration on the new SoC. 1) Registers for setting and clearing interrupts are different. 2) Raw and masked status registers are different. The updates have been tested on an emulation platform for new features and the patch has been tested on DA850 platform to make sure nothing existing breaks. Signed-off-by: Manjunathappa, Prakash Signed-off-by: Paul Mundt --- drivers/video/da8xx-fb.c | 151 ++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 142 insertions(+), 9 deletions(-) diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c index 8d4e4ebd9977..217c05f74541 100644 --- a/drivers/video/da8xx-fb.c +++ b/drivers/video/da8xx-fb.c @@ -35,6 +35,9 @@ #define DRIVER_NAME "da8xx_lcdc" +#define LCD_VERSION_1 1 +#define LCD_VERSION_2 2 + /* LCD Status Register */ #define LCD_END_OF_FRAME1 BIT(9) #define LCD_END_OF_FRAME0 BIT(8) @@ -49,7 +52,9 @@ #define LCD_DMA_BURST_4 0x2 #define LCD_DMA_BURST_8 0x3 #define LCD_DMA_BURST_16 0x4 -#define LCD_END_OF_FRAME_INT_ENA BIT(2) +#define LCD_V1_END_OF_FRAME_INT_ENA BIT(2) +#define LCD_V2_END_OF_FRAME0_INT_ENA BIT(8) +#define LCD_V2_END_OF_FRAME1_INT_ENA BIT(9) #define LCD_DUAL_FRAME_BUFFER_ENABLE BIT(0) /* LCD Control Register */ @@ -65,12 +70,18 @@ #define LCD_MONO_8BIT_MODE BIT(9) #define LCD_RASTER_ORDER BIT(8) #define LCD_TFT_MODE BIT(7) -#define LCD_UNDERFLOW_INT_ENA BIT(6) -#define LCD_PL_ENABLE BIT(4) +#define LCD_V1_UNDERFLOW_INT_ENA BIT(6) +#define LCD_V2_UNDERFLOW_INT_ENA BIT(5) +#define LCD_V1_PL_INT_ENA BIT(4) +#define LCD_V2_PL_INT_ENA BIT(6) #define LCD_MONOCHROME_MODE BIT(1) #define LCD_RASTER_ENABLE BIT(0) #define LCD_TFT_ALT_ENABLE BIT(23) #define LCD_STN_565_ENABLE BIT(24) +#define LCD_V2_DMA_CLK_EN BIT(2) +#define LCD_V2_LIDD_CLK_EN BIT(1) +#define LCD_V2_CORE_CLK_EN BIT(0) +#define LCD_V2_LPP_B10 26 /* LCD Raster Timing 2 Register */ #define LCD_AC_BIAS_TRANSITIONS_PER_INT(x) ((x) << 16) @@ -82,6 +93,7 @@ #define LCD_INVERT_FRAME_CLOCK BIT(20) /* LCD Block */ +#define LCD_PID_REG 0x0 #define LCD_CTRL_REG 0x4 #define LCD_STAT_REG 0x8 #define LCD_RASTER_CTRL_REG 0x28 @@ -94,6 +106,17 @@ #define LCD_DMA_FRM_BUF_BASE_ADDR_1_REG 0x4C #define LCD_DMA_FRM_BUF_CEILING_ADDR_1_REG 0x50 +/* Interrupt Registers available only in Version 2 */ +#define LCD_RAW_STAT_REG 0x58 +#define LCD_MASKED_STAT_REG 0x5c +#define LCD_INT_ENABLE_SET_REG 0x60 +#define LCD_INT_ENABLE_CLR_REG 0x64 +#define LCD_END_OF_INT_IND_REG 0x68 + +/* Clock registers available only on Version 2 */ +#define LCD_CLK_ENABLE_REG 0x6c +#define LCD_CLK_RESET_REG 0x70 + #define LCD_NUM_BUFFERS 2 #define WSI_TIMEOUT 50 @@ -105,6 +128,8 @@ static resource_size_t da8xx_fb_reg_base; static struct resource *lcdc_regs; +static unsigned int lcd_revision; +static irq_handler_t lcdc_irq_handler; static inline unsigned int lcdc_read(unsigned int addr) { @@ -240,6 +265,7 @@ static void lcd_blit(int load_mode, struct da8xx_fb_par *par) u32 end; u32 reg_ras; u32 reg_dma; + u32 reg_int; /* init reg to clear PLM (loading mode) fields */ reg_ras = lcdc_read(LCD_RASTER_CTRL_REG); @@ -252,7 +278,14 @@ static void lcd_blit(int load_mode, struct da8xx_fb_par *par) end = par->dma_end; reg_ras |= LCD_PALETTE_LOAD_MODE(DATA_ONLY); - reg_dma |= LCD_END_OF_FRAME_INT_ENA; + if (lcd_revision == LCD_VERSION_1) { + reg_dma |= LCD_V1_END_OF_FRAME_INT_ENA; + } else { + reg_int = lcdc_read(LCD_INT_ENABLE_SET_REG) | + LCD_V2_END_OF_FRAME0_INT_ENA | + LCD_V2_END_OF_FRAME1_INT_ENA; + lcdc_write(reg_int, LCD_INT_ENABLE_SET_REG); + } reg_dma |= LCD_DUAL_FRAME_BUFFER_ENABLE; lcdc_write(start, LCD_DMA_FRM_BUF_BASE_ADDR_0_REG); @@ -264,7 +297,14 @@ static void lcd_blit(int load_mode, struct da8xx_fb_par *par) end = start + par->palette_sz - 1; reg_ras |= LCD_PALETTE_LOAD_MODE(PALETTE_ONLY); - reg_ras |= LCD_PL_ENABLE; + + if (lcd_revision == LCD_VERSION_1) { + reg_ras |= LCD_V1_PL_INT_ENA; + } else { + reg_int = lcdc_read(LCD_INT_ENABLE_SET_REG) | + LCD_V2_PL_INT_ENA; + lcdc_write(reg_int, LCD_INT_ENABLE_SET_REG); + } lcdc_write(start, LCD_DMA_FRM_BUF_BASE_ADDR_0_REG); lcdc_write(end, LCD_DMA_FRM_BUF_CEILING_ADDR_0_REG); @@ -348,6 +388,7 @@ static void lcd_cfg_vertical_sync(int back_porch, int pulse_width, static int lcd_cfg_display(const struct lcd_ctrl_config *cfg) { u32 reg; + u32 reg_int; reg = lcdc_read(LCD_RASTER_CTRL_REG) & ~(LCD_TFT_MODE | LCD_MONO_8BIT_MODE | @@ -375,7 +416,13 @@ static int lcd_cfg_display(const struct lcd_ctrl_config *cfg) } /* enable additional interrupts here */ - reg |= LCD_UNDERFLOW_INT_ENA; + if (lcd_revision == LCD_VERSION_1) { + reg |= LCD_V1_UNDERFLOW_INT_ENA; + } else { + reg_int = lcdc_read(LCD_INT_ENABLE_SET_REG) | + LCD_V2_UNDERFLOW_INT_ENA; + lcdc_write(reg_int, LCD_INT_ENABLE_SET_REG); + } lcdc_write(reg, LCD_RASTER_CTRL_REG); @@ -511,6 +558,9 @@ static void lcd_reset(struct da8xx_fb_par *par) /* DMA has to be disabled */ lcdc_write(0, LCD_DMA_CTRL_REG); lcdc_write(0, LCD_RASTER_CTRL_REG); + + if (lcd_revision == LCD_VERSION_2) + lcdc_write(0, LCD_INT_ENABLE_SET_REG); } static void lcd_calc_clk_divider(struct da8xx_fb_par *par) @@ -523,6 +573,11 @@ static void lcd_calc_clk_divider(struct da8xx_fb_par *par) /* Configure the LCD clock divisor. */ lcdc_write(LCD_CLK_DIVISOR(div) | (LCD_RASTER_MODE & 0x1), LCD_CTRL_REG); + + if (lcd_revision == LCD_VERSION_2) + lcdc_write(LCD_V2_DMA_CLK_EN | LCD_V2_LIDD_CLK_EN | + LCD_V2_CORE_CLK_EN, LCD_CLK_ENABLE_REG); + } static int lcd_init(struct da8xx_fb_par *par, const struct lcd_ctrl_config *cfg, @@ -583,7 +638,63 @@ static int lcd_init(struct da8xx_fb_par *par, const struct lcd_ctrl_config *cfg, return 0; } -static irqreturn_t lcdc_irq_handler(int irq, void *arg) +/* IRQ handler for version 2 of LCDC */ +static irqreturn_t lcdc_irq_handler_rev02(int irq, void *arg) +{ + struct da8xx_fb_par *par = arg; + u32 stat = lcdc_read(LCD_MASKED_STAT_REG); + u32 reg_int; + + if ((stat & LCD_SYNC_LOST) && (stat & LCD_FIFO_UNDERFLOW)) { + lcd_disable_raster(); + lcdc_write(stat, LCD_MASKED_STAT_REG); + lcd_enable_raster(); + } else if (stat & LCD_PL_LOAD_DONE) { + /* + * Must disable raster before changing state of any control bit. + * And also must be disabled before clearing the PL loading + * interrupt via the following write to the status register. If + * this is done after then one gets multiple PL done interrupts. + */ + lcd_disable_raster(); + + lcdc_write(stat, LCD_MASKED_STAT_REG); + + /* Disable PL completion inerrupt */ + reg_int = lcdc_read(LCD_INT_ENABLE_CLR_REG) | + (LCD_V2_PL_INT_ENA); + lcdc_write(reg_int, LCD_INT_ENABLE_CLR_REG); + + /* Setup and start data loading mode */ + lcd_blit(LOAD_DATA, par); + } else { + lcdc_write(stat, LCD_MASKED_STAT_REG); + + if (stat & LCD_END_OF_FRAME0) { + lcdc_write(par->dma_start, + LCD_DMA_FRM_BUF_BASE_ADDR_0_REG); + lcdc_write(par->dma_end, + LCD_DMA_FRM_BUF_CEILING_ADDR_0_REG); + par->vsync_flag = 1; + wake_up_interruptible(&par->vsync_wait); + } + + if (stat & LCD_END_OF_FRAME1) { + lcdc_write(par->dma_start, + LCD_DMA_FRM_BUF_BASE_ADDR_1_REG); + lcdc_write(par->dma_end, + LCD_DMA_FRM_BUF_CEILING_ADDR_1_REG); + par->vsync_flag = 1; + wake_up_interruptible(&par->vsync_wait); + } + } + + lcdc_write(0, LCD_END_OF_INT_IND_REG); + return IRQ_HANDLED; +} + +/* IRQ handler for version 1 LCDC */ +static irqreturn_t lcdc_irq_handler_rev01(int irq, void *arg) { struct da8xx_fb_par *par = arg; u32 stat = lcdc_read(LCD_STAT_REG); @@ -606,7 +717,7 @@ static irqreturn_t lcdc_irq_handler(int irq, void *arg) /* Disable PL completion inerrupt */ reg_ras = lcdc_read(LCD_RASTER_CTRL_REG); - reg_ras &= ~LCD_PL_ENABLE; + reg_ras &= ~LCD_V1_PL_INT_ENA; lcdc_write(reg_ras, LCD_RASTER_CTRL_REG); /* Setup and start data loading mode */ @@ -945,6 +1056,22 @@ static int __devinit fb_probe(struct platform_device *device) if (ret) goto err_clk_put; + /* Determine LCD IP Version */ + switch (lcdc_read(LCD_PID_REG)) { + case 0x4C100102: + lcd_revision = LCD_VERSION_1; + break; + case 0x4F200800: + lcd_revision = LCD_VERSION_2; + break; + default: + dev_warn(&device->dev, "Unknown PID Reg value 0x%x, " + "defaulting to LCD revision 1\n", + lcdc_read(LCD_PID_REG)); + lcd_revision = LCD_VERSION_1; + break; + } + for (i = 0, lcdc_info = known_lcd_panels; i < ARRAY_SIZE(known_lcd_panels); i++, lcdc_info++) { @@ -1085,7 +1212,13 @@ static int __devinit fb_probe(struct platform_device *device) } #endif - ret = request_irq(par->irq, lcdc_irq_handler, 0, DRIVER_NAME, par); + if (lcd_revision == LCD_VERSION_1) + lcdc_irq_handler = lcdc_irq_handler_rev01; + else + lcdc_irq_handler = lcdc_irq_handler_rev02; + + ret = request_irq(par->irq, lcdc_irq_handler, 0, + DRIVER_NAME, par); if (ret) goto irq_freq; return 0; -- cgit v1.2.3 From 7653aaab775d4c205a7dce52850c8e3d4f31d4ea Mon Sep 17 00:00:00 2001 From: Timur Tabi Date: Sat, 9 Jul 2011 15:38:14 -0500 Subject: drivers/video: use strings to specify the Freescale DIU monitor port Instead of using ill-defined numbers (0, 1, and 2) for the monitor port, allow the user to specify the port by name ("dvi", "lvds", or "dlvds"). This works on the kernel command line, the module command-line, and the sysfs "monitor" device. Note that changing the monitor port does not currently work on the P1022DS, because the code that talks to the PIXIS FPGA is broken. Signed-off-by: Timur Tabi Acked-by: Anatolij Gustschin Signed-off-by: Paul Mundt --- arch/powerpc/platforms/512x/mpc512x_shared.c | 22 ++++----- arch/powerpc/platforms/85xx/p1022_ds.c | 47 +++++++++--------- arch/powerpc/platforms/86xx/mpc8610_hpcd.c | 55 ++++++++++----------- arch/powerpc/sysdev/fsl_soc.h | 25 +++++++--- drivers/video/fsl-diu-fb.c | 74 +++++++++++++++++++++------- 5 files changed, 128 insertions(+), 95 deletions(-) diff --git a/arch/powerpc/platforms/512x/mpc512x_shared.c b/arch/powerpc/platforms/512x/mpc512x_shared.c index e41ebbdb3e12..3dc62f907a1e 100644 --- a/arch/powerpc/platforms/512x/mpc512x_shared.c +++ b/arch/powerpc/platforms/512x/mpc512x_shared.c @@ -66,8 +66,8 @@ struct fsl_diu_shared_fb { bool in_use; }; -unsigned int mpc512x_get_pixel_format(unsigned int bits_per_pixel, - int monitor_port) +u32 mpc512x_get_pixel_format(enum fsl_diu_monitor_port port, + unsigned int bits_per_pixel) { switch (bits_per_pixel) { case 32: @@ -80,11 +80,12 @@ unsigned int mpc512x_get_pixel_format(unsigned int bits_per_pixel, return 0x00000400; } -void mpc512x_set_gamma_table(int monitor_port, char *gamma_table_base) +void mpc512x_set_gamma_table(enum fsl_diu_monitor_port port, + char *gamma_table_base) { } -void mpc512x_set_monitor_port(int monitor_port) +void mpc512x_set_monitor_port(enum fsl_diu_monitor_port port) { } @@ -182,14 +183,10 @@ void mpc512x_set_pixel_clock(unsigned int pixclock) iounmap(ccm); } -ssize_t mpc512x_show_monitor_port(int monitor_port, char *buf) +enum fsl_diu_monitor_port +mpc512x_valid_monitor_port(enum fsl_diu_monitor_port port) { - return sprintf(buf, "0 - 5121 LCD\n"); -} - -int mpc512x_set_sysfs_monitor_port(int val) -{ - return 0; + return FSL_DIU_PORT_DVI; } static struct fsl_diu_shared_fb __attribute__ ((__aligned__(8))) diu_shared_fb; @@ -332,8 +329,7 @@ void __init mpc512x_setup_diu(void) diu_ops.set_gamma_table = mpc512x_set_gamma_table; diu_ops.set_monitor_port = mpc512x_set_monitor_port; diu_ops.set_pixel_clock = mpc512x_set_pixel_clock; - diu_ops.show_monitor_port = mpc512x_show_monitor_port; - diu_ops.set_sysfs_monitor_port = mpc512x_set_sysfs_monitor_port; + diu_ops.valid_monitor_port = mpc512x_valid_monitor_port; diu_ops.release_bootmem = mpc512x_release_bootmem; #endif } diff --git a/arch/powerpc/platforms/85xx/p1022_ds.c b/arch/powerpc/platforms/85xx/p1022_ds.c index 7eb5c40c069f..a13d3cce413c 100644 --- a/arch/powerpc/platforms/85xx/p1022_ds.c +++ b/arch/powerpc/platforms/85xx/p1022_ds.c @@ -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: @@ -118,7 +118,8 @@ static unsigned int p1022ds_get_pixel_format(unsigned int bits_per_pixel, * 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) { } @@ -126,7 +127,7 @@ static void p1022ds_set_gamma_table(int monitor_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; u8 __iomem *brdcfg1; @@ -144,19 +145,21 @@ static void p1022ds_set_monitor_port(int monitor_port) } brdcfg1 += 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); } } @@ -204,23 +207,18 @@ void p1022ds_set_pixel_clock(unsigned int pixclock) } /** - * 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 @@ -295,8 +293,7 @@ static void __init p1022_ds_setup_arch(void) 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 diff --git a/arch/powerpc/platforms/86xx/mpc8610_hpcd.c b/arch/powerpc/platforms/86xx/mpc8610_hpcd.c index a896511690c2..0d80e9614f31 100644 --- a/arch/powerpc/platforms/86xx/mpc8610_hpcd.c +++ b/arch/powerpc/platforms/86xx/mpc8610_hpcd.c @@ -145,10 +145,10 @@ machine_device_initcall(mpc86xx_hpcd, mpc8610_declare_of_platform_devices); (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), @@ -163,7 +163,8 @@ unsigned int mpc8610hpcd_get_pixel_format(unsigned int bits_per_pixel, 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: @@ -178,10 +179,11 @@ unsigned int mpc8610hpcd_get_pixel_format(unsigned int bits_per_pixel, } } -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); @@ -192,17 +194,21 @@ void mpc8610hpcd_set_gamma_table(int monitor_port, char *gamma_table_base) #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; + } } void mpc8610hpcd_set_pixel_clock(unsigned int pixclock) @@ -273,20 +279,10 @@ void mpc8610hpcd_set_pixel_clock(unsigned int pixclock) iounmap(clkdvdr); } -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 @@ -318,8 +314,7 @@ static void __init mpc86xx_hpcd_setup_arch(void) 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"); diff --git a/arch/powerpc/sysdev/fsl_soc.h b/arch/powerpc/sysdev/fsl_soc.h index 53609489a62b..064bc7089134 100644 --- a/arch/powerpc/sysdev/fsl_soc.h +++ b/arch/powerpc/sysdev/fsl_soc.h @@ -22,15 +22,24 @@ 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; diff --git a/drivers/video/fsl-diu-fb.c b/drivers/video/fsl-diu-fb.c index 0acc7d65aeaa..0f1933b54596 100644 --- a/drivers/video/fsl-diu-fb.c +++ b/drivers/video/fsl-diu-fb.c @@ -31,8 +31,6 @@ #include #include -#include - #include #include #include "edid.h" @@ -183,7 +181,8 @@ static struct fb_videomode __devinitdata fsl_diu_mode_db[] = { static char *fb_mode = "1024x768-32@60"; static unsigned long default_bpp = 32; -static int monitor_port; +static enum fsl_diu_monitor_port monitor_port; +static char *monitor_string; #if defined(CONFIG_NOT_COHERENT_CACHE) static u8 *coherence_data; @@ -201,7 +200,7 @@ struct fsl_diu_data { void *dummy_aoi_virt; unsigned int irq; int fb_enabled; - int monitor_port; + enum fsl_diu_monitor_port monitor_port; }; struct mfb_info { @@ -281,6 +280,37 @@ static struct diu_hw dr = { static struct diu_pool pool; +/** + * fsl_diu_name_to_port - convert a port name to a monitor port enum + * + * Takes the name of a monitor port ("dvi", "lvds", or "dlvds") and returns + * the enum fsl_diu_monitor_port that corresponds to that string. + * + * For compatibility with older versions, a number ("0", "1", or "2") is also + * supported. + * + * If the string is unknown, DVI is assumed. + * + * If the particular port is not supported by the platform, another port + * (platform-specific) is chosen instead. + */ +static enum fsl_diu_monitor_port fsl_diu_name_to_port(const char *s) +{ + enum fsl_diu_monitor_port port = FSL_DIU_PORT_DVI; + unsigned long val; + + if (s) { + if (!strict_strtoul(s, 10, &val) && (val <= 2)) + port = (enum fsl_diu_monitor_port) val; + else if (strncmp(s, "lvds", 4) == 0) + port = FSL_DIU_PORT_LVDS; + else if (strncmp(s, "dlvds", 5) == 0) + port = FSL_DIU_PORT_DLVDS; + } + + return diu_ops.valid_monitor_port(port); +} + /** * fsl_diu_alloc - allocate memory for the DIU * @size: number of bytes to allocate @@ -831,9 +861,8 @@ static int fsl_diu_set_par(struct fb_info *info) } } - ad->pix_fmt = - diu_ops.get_pixel_format(var->bits_per_pixel, - machine_data->monitor_port); + ad->pix_fmt = diu_ops.get_pixel_format(machine_data->monitor_port, + var->bits_per_pixel); ad->addr = cpu_to_le32(info->fix.smem_start); ad->src_size_g_alpha = cpu_to_le32((var->yres_virtual << 12) | var->xres_virtual) | mfbi->g_alpha; @@ -1439,16 +1468,12 @@ static void free_buf(struct device *dev, struct diu_addr *buf, u32 size, static ssize_t store_monitor(struct device *device, struct device_attribute *attr, const char *buf, size_t count) { - int old_monitor_port; - unsigned long val; + enum fsl_diu_monitor_port old_monitor_port; struct fsl_diu_data *machine_data = container_of(attr, struct fsl_diu_data, dev_attr); - if (strict_strtoul(buf, 10, &val)) - return 0; - old_monitor_port = machine_data->monitor_port; - machine_data->monitor_port = diu_ops.set_sysfs_monitor_port(val); + machine_data->monitor_port = fsl_diu_name_to_port(buf); if (old_monitor_port != machine_data->monitor_port) { /* All AOIs need adjust pixel format @@ -1468,7 +1493,17 @@ static ssize_t show_monitor(struct device *device, { struct fsl_diu_data *machine_data = container_of(attr, struct fsl_diu_data, dev_attr); - return diu_ops.show_monitor_port(machine_data->monitor_port, buf); + + switch (machine_data->monitor_port) { + case FSL_DIU_PORT_DVI: + return sprintf(buf, "DVI\n"); + case FSL_DIU_PORT_LVDS: + return sprintf(buf, "Single-link LVDS\n"); + case FSL_DIU_PORT_DLVDS: + return sprintf(buf, "Dual-link LVDS\n"); + } + + return 0; } static int __devinit fsl_diu_probe(struct platform_device *ofdev) @@ -1692,8 +1727,7 @@ static int __init fsl_diu_setup(char *options) if (!*opt) continue; if (!strncmp(opt, "monitor=", 8)) { - if (!strict_strtoul(opt + 8, 10, &val) && (val <= 2)) - monitor_port = val; + monitor_port = fsl_diu_name_to_port(opt + 8); } else if (!strncmp(opt, "bpp=", 4)) { if (!strict_strtoul(opt + 4, 10, &val)) default_bpp = val; @@ -1746,6 +1780,8 @@ static int __init fsl_diu_init(void) if (fb_get_options("fslfb", &option)) return -ENODEV; fsl_diu_setup(option); +#else + monitor_port = fsl_diu_name_to_port(monitor_string); #endif printk(KERN_INFO "Freescale DIU driver\n"); @@ -1812,7 +1848,7 @@ MODULE_PARM_DESC(mode, "Specify resolution as \"x[-][@]\" "); module_param_named(bpp, default_bpp, ulong, 0); MODULE_PARM_DESC(bpp, "Specify bit-per-pixel if not specified mode"); -module_param_named(monitor, monitor_port, int, 0); -MODULE_PARM_DESC(monitor, - "Specify the monitor port (0, 1 or 2) if supported by the platform"); +module_param_named(monitor, monitor_string, charp, 0); +MODULE_PARM_DESC(monitor, "Specify the monitor port " + "(\"dvi\", \"lvds\", or \"dlvds\") if supported by the platform"); -- cgit v1.2.3 From 936a3f770b8de7042d793272f008ef1bb08522e9 Mon Sep 17 00:00:00 2001 From: Florian Tobias Schandinat Date: Mon, 6 Jun 2011 01:27:34 +0000 Subject: viafb: improve pitch handling This patch adds checks for minimum and maximum pitch size to prevent invalid settings which could otherwise crash the machine. Also the alignment is done in a slightly more readable way. Signed-off-by: Florian Tobias Schandinat Cc: stable@kernel.org --- drivers/video/via/via_modesetting.h | 5 +++++ drivers/video/via/viafbdev.c | 11 ++++++++--- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/drivers/video/via/via_modesetting.h b/drivers/video/via/via_modesetting.h index ae35cfdeb37c..013884543e91 100644 --- a/drivers/video/via/via_modesetting.h +++ b/drivers/video/via/via_modesetting.h @@ -28,6 +28,11 @@ #include + +#define VIA_PITCH_SIZE (1<<3) +#define VIA_PITCH_MAX 0x3FF8 + + void via_set_primary_address(u32 addr); void via_set_secondary_address(u32 addr); void via_set_primary_pitch(u32 pitch); diff --git a/drivers/video/via/viafbdev.c b/drivers/video/via/viafbdev.c index aa87529d7d6a..bddae58ecd8a 100644 --- a/drivers/video/via/viafbdev.c +++ b/drivers/video/via/viafbdev.c @@ -151,7 +151,8 @@ static void viafb_update_fix(struct fb_info *info) 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 @@ static int viafb_check_var(struct fb_var_screeninfo *var, 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, -- cgit v1.2.3