Commit 448ac479 authored by Sven Neumann's avatar Sven Neumann Committed by Eric Miao

pxafb: use passed fb_var_screeninfo struct in pxafb_pan_display()

pxafb_pan_display() used to ignore the fb_var_screeninfo parameter. Now
pass it to setup_base_frame() instead of pulling default values out of
fb_info.

And the original patch has an issue of pxafb_pan_display() paying only
attention to the 'var' parameter passed in, and Ville Syrjälä pointed
out, this is potentially dangerous as user could pass in any other
screeninfo parameters as well, and not only such that are relevant for
display panning. This is fixed by limiting the arguments actually used
to .xoffset, .yoffset and .vmode & FB_VMODE_YWRAP.
Signed-off-by: default avatarSven Neumann <s.neumann@raumfeld.com>
Cc: Ville Syrjälä <syrjala@sci.fi>
Signed-off-by: default avatarDaniel Mack <daniel@caiaq.de>
Signed-off-by: default avatarEric Miao <eric.y.miao@gmail.com>
parent 7f49a7f7
...@@ -80,7 +80,8 @@ ...@@ -80,7 +80,8 @@
static int pxafb_activate_var(struct fb_var_screeninfo *var, static int pxafb_activate_var(struct fb_var_screeninfo *var,
struct pxafb_info *); struct pxafb_info *);
static void set_ctrlr_state(struct pxafb_info *fbi, u_int state); static void set_ctrlr_state(struct pxafb_info *fbi, u_int state);
static void setup_base_frame(struct pxafb_info *fbi, int branch); static void setup_base_frame(struct pxafb_info *fbi,
struct fb_var_screeninfo *var, int branch);
static int setup_frame_dma(struct pxafb_info *fbi, int dma, int pal, static int setup_frame_dma(struct pxafb_info *fbi, int dma, int pal,
unsigned long offset, size_t size); unsigned long offset, size_t size);
...@@ -531,12 +532,22 @@ static int pxafb_pan_display(struct fb_var_screeninfo *var, ...@@ -531,12 +532,22 @@ static int pxafb_pan_display(struct fb_var_screeninfo *var,
struct fb_info *info) struct fb_info *info)
{ {
struct pxafb_info *fbi = (struct pxafb_info *)info; struct pxafb_info *fbi = (struct pxafb_info *)info;
struct fb_var_screeninfo newvar;
int dma = DMA_MAX + DMA_BASE; int dma = DMA_MAX + DMA_BASE;
if (fbi->state != C_ENABLE) if (fbi->state != C_ENABLE)
return 0; return 0;
setup_base_frame(fbi, 1); /* Only take .xoffset, .yoffset and .vmode & FB_VMODE_YWRAP from what
* was passed in and copy the rest from the old screeninfo.
*/
memcpy(&newvar, &fbi->fb.var, sizeof(newvar));
newvar.xoffset = var->xoffset;
newvar.yoffset = var->yoffset;
newvar.vmode &= ~FB_VMODE_YWRAP;
newvar.vmode |= var->vmode & FB_VMODE_YWRAP;
setup_base_frame(fbi, &newvar, 1);
if (fbi->lccr0 & LCCR0_SDS) if (fbi->lccr0 & LCCR0_SDS)
lcd_writel(fbi, FBR1, fbi->fdadr[dma + 1] | 0x1); lcd_writel(fbi, FBR1, fbi->fdadr[dma + 1] | 0x1);
...@@ -1052,9 +1063,10 @@ static int setup_frame_dma(struct pxafb_info *fbi, int dma, int pal, ...@@ -1052,9 +1063,10 @@ static int setup_frame_dma(struct pxafb_info *fbi, int dma, int pal,
return 0; return 0;
} }
static void setup_base_frame(struct pxafb_info *fbi, int branch) static void setup_base_frame(struct pxafb_info *fbi,
struct fb_var_screeninfo *var,
int branch)
{ {
struct fb_var_screeninfo *var = &fbi->fb.var;
struct fb_fix_screeninfo *fix = &fbi->fb.fix; struct fb_fix_screeninfo *fix = &fbi->fb.fix;
int nbytes, dma, pal, bpp = var->bits_per_pixel; int nbytes, dma, pal, bpp = var->bits_per_pixel;
unsigned long offset; unsigned long offset;
...@@ -1332,7 +1344,7 @@ static int pxafb_activate_var(struct fb_var_screeninfo *var, ...@@ -1332,7 +1344,7 @@ static int pxafb_activate_var(struct fb_var_screeninfo *var,
#endif #endif
setup_parallel_timing(fbi, var); setup_parallel_timing(fbi, var);
setup_base_frame(fbi, 0); setup_base_frame(fbi, var, 0);
fbi->reg_lccr0 = fbi->lccr0 | fbi->reg_lccr0 = fbi->lccr0 |
(LCCR0_LDM | LCCR0_SFM | LCCR0_IUM | LCCR0_EFM | (LCCR0_LDM | LCCR0_SFM | LCCR0_IUM | LCCR0_EFM |
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment