Commit b4d6a726 authored by Grant Likely's avatar Grant Likely Committed by Paul Mackerras

[POWERPC] XilinxFB: Add support for custom screen resolution

Some custom implementations of the xilinx fb can use resolutions other
than 640x480.  This patch allows the resolution to be specified in the
device tree or the xilinx_platform_data structure.
Signed-off-by: default avatarGrant Likely <grant.likely@secretlab.ca>
Signed-off-by: default avatarPaul Mackerras <paulus@samba.org>
parent 01ba1e9d
...@@ -70,12 +70,6 @@ ...@@ -70,12 +70,6 @@
*/ */
#define BYTES_PER_PIXEL 4 #define BYTES_PER_PIXEL 4
#define BITS_PER_PIXEL (BYTES_PER_PIXEL * 8) #define BITS_PER_PIXEL (BYTES_PER_PIXEL * 8)
#define XRES 640
#define YRES 480
#define XRES_VIRTUAL 1024
#define YRES_VIRTUAL YRES
#define LINE_LENGTH (XRES_VIRTUAL * BYTES_PER_PIXEL)
#define FB_SIZE (YRES_VIRTUAL * LINE_LENGTH)
#define RED_SHIFT 16 #define RED_SHIFT 16
#define GREEN_SHIFT 8 #define GREEN_SHIFT 8
...@@ -87,6 +81,10 @@ ...@@ -87,6 +81,10 @@
* Default xilinxfb configuration * Default xilinxfb configuration
*/ */
static struct xilinxfb_platform_data xilinx_fb_default_pdata = { static struct xilinxfb_platform_data xilinx_fb_default_pdata = {
.xres = 640,
.yres = 480,
.xvirt = 1024,
.yvirt = 480;
}; };
/* /*
...@@ -96,17 +94,10 @@ static struct fb_fix_screeninfo xilinx_fb_fix = { ...@@ -96,17 +94,10 @@ static struct fb_fix_screeninfo xilinx_fb_fix = {
.id = "Xilinx", .id = "Xilinx",
.type = FB_TYPE_PACKED_PIXELS, .type = FB_TYPE_PACKED_PIXELS,
.visual = FB_VISUAL_TRUECOLOR, .visual = FB_VISUAL_TRUECOLOR,
.smem_len = FB_SIZE,
.line_length = LINE_LENGTH,
.accel = FB_ACCEL_NONE .accel = FB_ACCEL_NONE
}; };
static struct fb_var_screeninfo xilinx_fb_var = { static struct fb_var_screeninfo xilinx_fb_var = {
.xres = XRES,
.yres = YRES,
.xres_virtual = XRES_VIRTUAL,
.yres_virtual = YRES_VIRTUAL,
.bits_per_pixel = BITS_PER_PIXEL, .bits_per_pixel = BITS_PER_PIXEL,
.red = { RED_SHIFT, 8, 0 }, .red = { RED_SHIFT, 8, 0 },
...@@ -217,6 +208,7 @@ static int xilinxfb_assign(struct device *dev, unsigned long physaddr, ...@@ -217,6 +208,7 @@ static int xilinxfb_assign(struct device *dev, unsigned long physaddr,
{ {
struct xilinxfb_drvdata *drvdata; struct xilinxfb_drvdata *drvdata;
int rc; int rc;
int fbsize = pdata->xvirt * pdata->yvirt * BYTES_PER_PIXEL;
/* Allocate the driver data region */ /* Allocate the driver data region */
drvdata = kzalloc(sizeof(*drvdata), GFP_KERNEL); drvdata = kzalloc(sizeof(*drvdata), GFP_KERNEL);
...@@ -243,7 +235,7 @@ static int xilinxfb_assign(struct device *dev, unsigned long physaddr, ...@@ -243,7 +235,7 @@ static int xilinxfb_assign(struct device *dev, unsigned long physaddr,
} }
/* Allocate the framebuffer memory */ /* Allocate the framebuffer memory */
drvdata->fb_virt = dma_alloc_coherent(dev, PAGE_ALIGN(FB_SIZE), drvdata->fb_virt = dma_alloc_coherent(dev, PAGE_ALIGN(fbsize),
&drvdata->fb_phys, GFP_KERNEL); &drvdata->fb_phys, GFP_KERNEL);
if (!drvdata->fb_virt) { if (!drvdata->fb_virt) {
dev_err(dev, "Could not allocate frame buffer memory\n"); dev_err(dev, "Could not allocate frame buffer memory\n");
...@@ -252,7 +244,7 @@ static int xilinxfb_assign(struct device *dev, unsigned long physaddr, ...@@ -252,7 +244,7 @@ static int xilinxfb_assign(struct device *dev, unsigned long physaddr,
} }
/* Clear (turn to black) the framebuffer */ /* Clear (turn to black) the framebuffer */
memset_io((void __iomem *)drvdata->fb_virt, 0, FB_SIZE); memset_io((void __iomem *)drvdata->fb_virt, 0, fbsize);
/* Tell the hardware where the frame buffer is */ /* Tell the hardware where the frame buffer is */
xilinx_fb_out_be32(drvdata, REG_FB_ADDR, drvdata->fb_phys); xilinx_fb_out_be32(drvdata, REG_FB_ADDR, drvdata->fb_phys);
...@@ -269,12 +261,18 @@ static int xilinxfb_assign(struct device *dev, unsigned long physaddr, ...@@ -269,12 +261,18 @@ static int xilinxfb_assign(struct device *dev, unsigned long physaddr,
drvdata->info.fbops = &xilinxfb_ops; drvdata->info.fbops = &xilinxfb_ops;
drvdata->info.fix = xilinx_fb_fix; drvdata->info.fix = xilinx_fb_fix;
drvdata->info.fix.smem_start = drvdata->fb_phys; drvdata->info.fix.smem_start = drvdata->fb_phys;
drvdata->info.fix.smem_len = fbsize;
drvdata->info.fix.line_length = pdata->xvirt * BYTES_PER_PIXEL;
drvdata->info.pseudo_palette = drvdata->pseudo_palette; drvdata->info.pseudo_palette = drvdata->pseudo_palette;
drvdata->info.flags = FBINFO_DEFAULT; drvdata->info.flags = FBINFO_DEFAULT;
drvdata->info.var = xilinx_fb_var; drvdata->info.var = xilinx_fb_var;
drvdata->info.var.height = pdata->screen_height_mm;
xilinx_fb_var.height = pdata->screen_height_mm; drvdata->info.var.width = pdata->screen_width_mm;
xilinx_fb_var.width = pdata->screen_width_mm; drvdata->info.var.xres = pdata->xres;
drvdata->info.var.yres = pdata->yres;
drvdata->info.var.xres_virtual = pdata->xvirt;
drvdata->info.var.yres_virtual = pdata->yvirt;
/* Allocate a colour map */ /* Allocate a colour map */
rc = fb_alloc_cmap(&drvdata->info.cmap, PALETTE_ENTRIES_NO, 0); rc = fb_alloc_cmap(&drvdata->info.cmap, PALETTE_ENTRIES_NO, 0);
...@@ -294,14 +292,15 @@ static int xilinxfb_assign(struct device *dev, unsigned long physaddr, ...@@ -294,14 +292,15 @@ static int xilinxfb_assign(struct device *dev, unsigned long physaddr,
/* Put a banner in the log (for DEBUG) */ /* Put a banner in the log (for DEBUG) */
dev_dbg(dev, "regs: phys=%lx, virt=%p\n", physaddr, drvdata->regs); dev_dbg(dev, "regs: phys=%lx, virt=%p\n", physaddr, drvdata->regs);
dev_dbg(dev, "fb: phys=%p, virt=%p, size=%x\n", dev_dbg(dev, "fb: phys=%p, virt=%p, size=%x\n",
(void*)drvdata->fb_phys, drvdata->fb_virt, FB_SIZE); (void*)drvdata->fb_phys, drvdata->fb_virt, fbsize);
return 0; /* success */ return 0; /* success */
err_regfb: err_regfb:
fb_dealloc_cmap(&drvdata->info.cmap); fb_dealloc_cmap(&drvdata->info.cmap);
err_cmap: err_cmap:
dma_free_coherent(dev, PAGE_ALIGN(FB_SIZE), drvdata->fb_virt, dma_free_coherent(dev, PAGE_ALIGN(fbsize), drvdata->fb_virt,
drvdata->fb_phys); drvdata->fb_phys);
/* Turn off the display */ /* Turn off the display */
xilinx_fb_out_be32(drvdata, REG_CTRL, 0); xilinx_fb_out_be32(drvdata, REG_CTRL, 0);
...@@ -331,8 +330,8 @@ static int xilinxfb_release(struct device *dev) ...@@ -331,8 +330,8 @@ static int xilinxfb_release(struct device *dev)
fb_dealloc_cmap(&drvdata->info.cmap); fb_dealloc_cmap(&drvdata->info.cmap);
dma_free_coherent(dev, PAGE_ALIGN(FB_SIZE), drvdata->fb_virt, dma_free_coherent(dev, PAGE_ALIGN(drvdata->info.fix.smem_len),
drvdata->fb_phys); drvdata->fb_virt, drvdata->fb_phys);
/* Turn off the display */ /* Turn off the display */
xilinx_fb_out_be32(drvdata, REG_CTRL, 0); xilinx_fb_out_be32(drvdata, REG_CTRL, 0);
...@@ -364,10 +363,18 @@ xilinxfb_platform_probe(struct platform_device *pdev) ...@@ -364,10 +363,18 @@ xilinxfb_platform_probe(struct platform_device *pdev)
} }
/* If a pdata structure is provided, then extract the parameters */ /* If a pdata structure is provided, then extract the parameters */
if (pdev->dev.platform_data)
pdata = pdev->dev.platform_data;
else
pdata = &xilinx_fb_default_pdata; pdata = &xilinx_fb_default_pdata;
if (pdev->dev.platform_data) {
pdata = pdev->dev.platform_data;
if (!pdata->xres)
pdata->xres = xilinx_fb_default_pdata.xres;
if (!pdata->yres)
pdata->yres = xilinx_fb_default_pdata.yres;
if (!pdata->xvirt)
pdata->xvirt = xilinx_fb_default_pdata.xvirt;
if (!pdata->yvirt)
pdata->yvirt = xilinx_fb_default_pdata.yvirt;
}
return xilinxfb_assign(&pdev->dev, res->start, pdata); return xilinxfb_assign(&pdev->dev, res->start, pdata);
} }
...@@ -412,12 +419,24 @@ xilinxfb_of_probe(struct of_device *op, const struct of_device_id *match) ...@@ -412,12 +419,24 @@ xilinxfb_of_probe(struct of_device *op, const struct of_device_id *match)
return rc; return rc;
} }
prop = of_get_property(op->node, "display-number", &size); prop = of_get_property(op->node, "phys-size", &size);
if ((prop) && (size >= sizeof(u32)*2)) { if ((prop) && (size >= sizeof(u32)*2)) {
pdata.screen_width_mm = prop[0]; pdata.screen_width_mm = prop[0];
pdata.screen_height_mm = prop[1]; pdata.screen_height_mm = prop[1];
} }
prop = of_get_property(op->node, "resolution", &size);
if ((prop) && (size >= sizeof(u32)*2)) {
pdata.xres = prop[0];
pdata.yres = prop[1];
}
prop = of_get_property(op->node, "virtual-resolution", &size);
if ((prop) && (size >= sizeof(u32)*2)) {
pdata.xvirt = prop[0];
pdata.yvirt = prop[1];
}
if (of_find_property(op->node, "rotate-display", NULL)) if (of_find_property(op->node, "rotate-display", NULL))
pdata.rotate_screen = 1; pdata.rotate_screen = 1;
......
...@@ -15,9 +15,11 @@ ...@@ -15,9 +15,11 @@
/* ML300/403 reference design framebuffer driver platform data struct */ /* ML300/403 reference design framebuffer driver platform data struct */
struct xilinxfb_platform_data { struct xilinxfb_platform_data {
u32 rotate_screen; u32 rotate_screen; /* Flag to rotate display 180 degrees */
u32 screen_height_mm; u32 screen_height_mm; /* Physical dimentions of screen in mm */
u32 screen_width_mm; u32 screen_width_mm;
u32 xres, yres; /* resolution of screen in pixels */
u32 xvirt, yvirt; /* resolution of memory buffer */
}; };
#endif /* __XILINXFB_H__ */ #endif /* __XILINXFB_H__ */
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