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: Sven Neumann <s.neumann@raumfeld.com> Cc: Ville Syrjälä <syrjala@sci.fi> Signed-off-by: Daniel Mack <daniel@caiaq.de> Signed-off-by: Eric Miao <eric.y.miao@gmail.com>
This commit is contained in:
parent
7f49a7f701
commit
448ac47976
1 changed files with 17 additions and 5 deletions
|
@ -80,7 +80,8 @@
|
|||
static int pxafb_activate_var(struct fb_var_screeninfo *var,
|
||||
struct pxafb_info *);
|
||||
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,
|
||||
unsigned long offset, size_t size);
|
||||
|
||||
|
@ -531,12 +532,22 @@ static int pxafb_pan_display(struct fb_var_screeninfo *var,
|
|||
struct fb_info *info)
|
||||
{
|
||||
struct pxafb_info *fbi = (struct pxafb_info *)info;
|
||||
struct fb_var_screeninfo newvar;
|
||||
int dma = DMA_MAX + DMA_BASE;
|
||||
|
||||
if (fbi->state != C_ENABLE)
|
||||
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)
|
||||
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,
|
|||
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;
|
||||
int nbytes, dma, pal, bpp = var->bits_per_pixel;
|
||||
unsigned long offset;
|
||||
|
@ -1332,7 +1344,7 @@ static int pxafb_activate_var(struct fb_var_screeninfo *var,
|
|||
#endif
|
||||
setup_parallel_timing(fbi, var);
|
||||
|
||||
setup_base_frame(fbi, 0);
|
||||
setup_base_frame(fbi, var, 0);
|
||||
|
||||
fbi->reg_lccr0 = fbi->lccr0 |
|
||||
(LCCR0_LDM | LCCR0_SFM | LCCR0_IUM | LCCR0_EFM |
|
||||
|
|
Loading…
Reference in a new issue