aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGrant Likely <grant.likely@secretlab.ca>2007-10-10 14:31:51 -0400
committerPaul Mackerras <paulus@samba.org>2007-10-12 00:05:17 -0400
commitb4d6a7268fc754eefb196cabc0ccfa2e97022af2 (patch)
tree406af23412b9a984b91804c9ca956c8f3dda0a22
parent01ba1e9d26fcd29f3ad4f3a5bcf40c0fbc40ee81 (diff)
[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: Grant Likely <grant.likely@secretlab.ca> Signed-off-by: Paul Mackerras <paulus@samba.org>
-rw-r--r--drivers/video/xilinxfb.c71
-rw-r--r--include/linux/xilinxfb.h6
2 files changed, 49 insertions, 28 deletions
diff --git a/drivers/video/xilinxfb.c b/drivers/video/xilinxfb.c
index b3b57f4a35a2..c6174125f52b 100644
--- a/drivers/video/xilinxfb.c
+++ b/drivers/video/xilinxfb.c
@@ -70,12 +70,6 @@
70 */ 70 */
71#define BYTES_PER_PIXEL 4 71#define BYTES_PER_PIXEL 4
72#define BITS_PER_PIXEL (BYTES_PER_PIXEL * 8) 72#define BITS_PER_PIXEL (BYTES_PER_PIXEL * 8)
73#define XRES 640
74#define YRES 480
75#define XRES_VIRTUAL 1024
76#define YRES_VIRTUAL YRES
77#define LINE_LENGTH (XRES_VIRTUAL * BYTES_PER_PIXEL)
78#define FB_SIZE (YRES_VIRTUAL * LINE_LENGTH)
79 73
80#define RED_SHIFT 16 74#define RED_SHIFT 16
81#define GREEN_SHIFT 8 75#define GREEN_SHIFT 8
@@ -87,6 +81,10 @@
87 * Default xilinxfb configuration 81 * Default xilinxfb configuration
88 */ 82 */
89static struct xilinxfb_platform_data xilinx_fb_default_pdata = { 83static struct xilinxfb_platform_data xilinx_fb_default_pdata = {
84 .xres = 640,
85 .yres = 480,
86 .xvirt = 1024,
87 .yvirt = 480;
90}; 88};
91 89
92/* 90/*
@@ -96,17 +94,10 @@ static struct fb_fix_screeninfo xilinx_fb_fix = {
96 .id = "Xilinx", 94 .id = "Xilinx",
97 .type = FB_TYPE_PACKED_PIXELS, 95 .type = FB_TYPE_PACKED_PIXELS,
98 .visual = FB_VISUAL_TRUECOLOR, 96 .visual = FB_VISUAL_TRUECOLOR,
99 .smem_len = FB_SIZE,
100 .line_length = LINE_LENGTH,
101 .accel = FB_ACCEL_NONE 97 .accel = FB_ACCEL_NONE
102}; 98};
103 99
104static struct fb_var_screeninfo xilinx_fb_var = { 100static struct fb_var_screeninfo xilinx_fb_var = {
105 .xres = XRES,
106 .yres = YRES,
107 .xres_virtual = XRES_VIRTUAL,
108 .yres_virtual = YRES_VIRTUAL,
109
110 .bits_per_pixel = BITS_PER_PIXEL, 101 .bits_per_pixel = BITS_PER_PIXEL,
111 102
112 .red = { RED_SHIFT, 8, 0 }, 103 .red = { RED_SHIFT, 8, 0 },
@@ -217,6 +208,7 @@ static int xilinxfb_assign(struct device *dev, unsigned long physaddr,
217{ 208{
218 struct xilinxfb_drvdata *drvdata; 209 struct xilinxfb_drvdata *drvdata;
219 int rc; 210 int rc;
211 int fbsize = pdata->xvirt * pdata->yvirt * BYTES_PER_PIXEL;
220 212
221 /* Allocate the driver data region */ 213 /* Allocate the driver data region */
222 drvdata = kzalloc(sizeof(*drvdata), GFP_KERNEL); 214 drvdata = kzalloc(sizeof(*drvdata), GFP_KERNEL);
@@ -243,7 +235,7 @@ static int xilinxfb_assign(struct device *dev, unsigned long physaddr,
243 } 235 }
244 236
245 /* Allocate the framebuffer memory */ 237 /* Allocate the framebuffer memory */
246 drvdata->fb_virt = dma_alloc_coherent(dev, PAGE_ALIGN(FB_SIZE), 238 drvdata->fb_virt = dma_alloc_coherent(dev, PAGE_ALIGN(fbsize),
247 &drvdata->fb_phys, GFP_KERNEL); 239 &drvdata->fb_phys, GFP_KERNEL);
248 if (!drvdata->fb_virt) { 240 if (!drvdata->fb_virt) {
249 dev_err(dev, "Could not allocate frame buffer memory\n"); 241 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 } 244 }
253 245
254 /* Clear (turn to black) the framebuffer */ 246 /* Clear (turn to black) the framebuffer */
255 memset_io((void __iomem *)drvdata->fb_virt, 0, FB_SIZE); 247 memset_io((void __iomem *)drvdata->fb_virt, 0, fbsize);
256 248
257 /* Tell the hardware where the frame buffer is */ 249 /* Tell the hardware where the frame buffer is */
258 xilinx_fb_out_be32(drvdata, REG_FB_ADDR, drvdata->fb_phys); 250 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 drvdata->info.fbops = &xilinxfb_ops; 261 drvdata->info.fbops = &xilinxfb_ops;
270 drvdata->info.fix = xilinx_fb_fix; 262 drvdata->info.fix = xilinx_fb_fix;
271 drvdata->info.fix.smem_start = drvdata->fb_phys; 263 drvdata->info.fix.smem_start = drvdata->fb_phys;
264 drvdata->info.fix.smem_len = fbsize;
265 drvdata->info.fix.line_length = pdata->xvirt * BYTES_PER_PIXEL;
266
272 drvdata->info.pseudo_palette = drvdata->pseudo_palette; 267 drvdata->info.pseudo_palette = drvdata->pseudo_palette;
273 drvdata->info.flags = FBINFO_DEFAULT; 268 drvdata->info.flags = FBINFO_DEFAULT;
274 drvdata->info.var = xilinx_fb_var; 269 drvdata->info.var = xilinx_fb_var;
275 270 drvdata->info.var.height = pdata->screen_height_mm;
276 xilinx_fb_var.height = pdata->screen_height_mm; 271 drvdata->info.var.width = pdata->screen_width_mm;
277 xilinx_fb_var.width = pdata->screen_width_mm; 272 drvdata->info.var.xres = pdata->xres;
273 drvdata->info.var.yres = pdata->yres;
274 drvdata->info.var.xres_virtual = pdata->xvirt;
275 drvdata->info.var.yres_virtual = pdata->yvirt;
278 276
279 /* Allocate a colour map */ 277 /* Allocate a colour map */
280 rc = fb_alloc_cmap(&drvdata->info.cmap, PALETTE_ENTRIES_NO, 0); 278 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 /* Put a banner in the log (for DEBUG) */ 292 /* Put a banner in the log (for DEBUG) */
295 dev_dbg(dev, "regs: phys=%lx, virt=%p\n", physaddr, drvdata->regs); 293 dev_dbg(dev, "regs: phys=%lx, virt=%p\n", physaddr, drvdata->regs);
296 dev_dbg(dev, "fb: phys=%p, virt=%p, size=%x\n", 294 dev_dbg(dev, "fb: phys=%p, virt=%p, size=%x\n",
297 (void*)drvdata->fb_phys, drvdata->fb_virt, FB_SIZE); 295 (void*)drvdata->fb_phys, drvdata->fb_virt, fbsize);
296
298 return 0; /* success */ 297 return 0; /* success */
299 298
300err_regfb: 299err_regfb:
301 fb_dealloc_cmap(&drvdata->info.cmap); 300 fb_dealloc_cmap(&drvdata->info.cmap);
302 301
303err_cmap: 302err_cmap:
304 dma_free_coherent(dev, PAGE_ALIGN(FB_SIZE), drvdata->fb_virt, 303 dma_free_coherent(dev, PAGE_ALIGN(fbsize), drvdata->fb_virt,
305 drvdata->fb_phys); 304 drvdata->fb_phys);
306 /* Turn off the display */ 305 /* Turn off the display */
307 xilinx_fb_out_be32(drvdata, REG_CTRL, 0); 306 xilinx_fb_out_be32(drvdata, REG_CTRL, 0);
@@ -331,8 +330,8 @@ static int xilinxfb_release(struct device *dev)
331 330
332 fb_dealloc_cmap(&drvdata->info.cmap); 331 fb_dealloc_cmap(&drvdata->info.cmap);
333 332
334 dma_free_coherent(dev, PAGE_ALIGN(FB_SIZE), drvdata->fb_virt, 333 dma_free_coherent(dev, PAGE_ALIGN(drvdata->info.fix.smem_len),
335 drvdata->fb_phys); 334 drvdata->fb_virt, drvdata->fb_phys);
336 335
337 /* Turn off the display */ 336 /* Turn off the display */
338 xilinx_fb_out_be32(drvdata, REG_CTRL, 0); 337 xilinx_fb_out_be32(drvdata, REG_CTRL, 0);
@@ -364,10 +363,18 @@ xilinxfb_platform_probe(struct platform_device *pdev)
364 } 363 }
365 364
366 /* If a pdata structure is provided, then extract the parameters */ 365 /* If a pdata structure is provided, then extract the parameters */
367 if (pdev->dev.platform_data) 366 pdata = &xilinx_fb_default_pdata;
367 if (pdev->dev.platform_data) {
368 pdata = pdev->dev.platform_data; 368 pdata = pdev->dev.platform_data;
369 else 369 if (!pdata->xres)
370 pdata = &xilinx_fb_default_pdata; 370 pdata->xres = xilinx_fb_default_pdata.xres;
371 if (!pdata->yres)
372 pdata->yres = xilinx_fb_default_pdata.yres;
373 if (!pdata->xvirt)
374 pdata->xvirt = xilinx_fb_default_pdata.xvirt;
375 if (!pdata->yvirt)
376 pdata->yvirt = xilinx_fb_default_pdata.yvirt;
377 }
371 378
372 return xilinxfb_assign(&pdev->dev, res->start, pdata); 379 return xilinxfb_assign(&pdev->dev, res->start, pdata);
373} 380}
@@ -412,12 +419,24 @@ xilinxfb_of_probe(struct of_device *op, const struct of_device_id *match)
412 return rc; 419 return rc;
413 } 420 }
414 421
415 prop = of_get_property(op->node, "display-number", &size); 422 prop = of_get_property(op->node, "phys-size", &size);
416 if ((prop) && (size >= sizeof(u32)*2)) { 423 if ((prop) && (size >= sizeof(u32)*2)) {
417 pdata.screen_width_mm = prop[0]; 424 pdata.screen_width_mm = prop[0];
418 pdata.screen_height_mm = prop[1]; 425 pdata.screen_height_mm = prop[1];
419 } 426 }
420 427
428 prop = of_get_property(op->node, "resolution", &size);
429 if ((prop) && (size >= sizeof(u32)*2)) {
430 pdata.xres = prop[0];
431 pdata.yres = prop[1];
432 }
433
434 prop = of_get_property(op->node, "virtual-resolution", &size);
435 if ((prop) && (size >= sizeof(u32)*2)) {
436 pdata.xvirt = prop[0];
437 pdata.yvirt = prop[1];
438 }
439
421 if (of_find_property(op->node, "rotate-display", NULL)) 440 if (of_find_property(op->node, "rotate-display", NULL))
422 pdata.rotate_screen = 1; 441 pdata.rotate_screen = 1;
423 442
diff --git a/include/linux/xilinxfb.h b/include/linux/xilinxfb.h
index 9ad984d22c38..199a1eedf223 100644
--- a/include/linux/xilinxfb.h
+++ b/include/linux/xilinxfb.h
@@ -15,9 +15,11 @@
15 15
16/* ML300/403 reference design framebuffer driver platform data struct */ 16/* ML300/403 reference design framebuffer driver platform data struct */
17struct xilinxfb_platform_data { 17struct xilinxfb_platform_data {
18 u32 rotate_screen; 18 u32 rotate_screen; /* Flag to rotate display 180 degrees */
19 u32 screen_height_mm; 19 u32 screen_height_mm; /* Physical dimentions of screen in mm */
20 u32 screen_width_mm; 20 u32 screen_width_mm;
21 u32 xres, yres; /* resolution of screen in pixels */
22 u32 xvirt, yvirt; /* resolution of memory buffer */
21}; 23};
22 24
23#endif /* __XILINXFB_H__ */ 25#endif /* __XILINXFB_H__ */