aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorJosh Boyer <jwboyer@linux.vnet.ibm.com>2007-10-11 08:45:20 -0400
committerJosh Boyer <jwboyer@linux.vnet.ibm.com>2007-10-11 08:45:20 -0400
commit0a2cdd88f0b8ea98bcaf9712446cc46a240313f5 (patch)
tree05f2ac8731a0b24bba1552458839b1c7d032ff63 /drivers
parentcdec12aebe1b10aa58bebaa05bb697843154f7f9 (diff)
parent17c5c2093624e81acda16fb737e4679750addd7a (diff)
Merge branch 'virtex-for-2.6.24' of git://git.secretlab.ca/git/linux-2.6-virtex into for-2.6.24-4xx
Diffstat (limited to 'drivers')
-rw-r--r--drivers/video/xilinxfb.c279
1 files changed, 199 insertions, 80 deletions
diff --git a/drivers/video/xilinxfb.c b/drivers/video/xilinxfb.c
index 4bc67ab56afa..dec602c23075 100644
--- a/drivers/video/xilinxfb.c
+++ b/drivers/video/xilinxfb.c
@@ -6,9 +6,12 @@
6 * Author: MontaVista Software, Inc. 6 * Author: MontaVista Software, Inc.
7 * source@mvista.com 7 * source@mvista.com
8 * 8 *
9 * 2002-2007 (c) MontaVista Software, Inc. This file is licensed under the 9 * 2002-2007 (c) MontaVista Software, Inc.
10 * terms of the GNU General Public License version 2. This program is licensed 10 * 2007 (c) Secret Lab Technologies, Ltd.
11 * "as is" without any warranty of any kind, whether express or implied. 11 *
12 * This file is licensed under the terms of the GNU General Public License
13 * version 2. This program is licensed "as is" without any warranty of any
14 * kind, whether express or implied.
12 */ 15 */
13 16
14/* 17/*
@@ -18,6 +21,7 @@
18 * Geert Uytterhoeven. 21 * Geert Uytterhoeven.
19 */ 22 */
20 23
24#include <linux/device.h>
21#include <linux/module.h> 25#include <linux/module.h>
22#include <linux/kernel.h> 26#include <linux/kernel.h>
23#include <linux/version.h> 27#include <linux/version.h>
@@ -28,7 +32,10 @@
28#include <linux/init.h> 32#include <linux/init.h>
29#include <linux/dma-mapping.h> 33#include <linux/dma-mapping.h>
30#include <linux/platform_device.h> 34#include <linux/platform_device.h>
31 35#if defined(CONFIG_OF)
36#include <linux/of_device.h>
37#include <linux/of_platform.h>
38#endif
32#include <asm/io.h> 39#include <asm/io.h>
33#include <linux/xilinxfb.h> 40#include <linux/xilinxfb.h>
34 41
@@ -111,7 +118,7 @@ struct xilinxfb_drvdata {
111 u32 regs_phys; /* phys. address of the control registers */ 118 u32 regs_phys; /* phys. address of the control registers */
112 u32 __iomem *regs; /* virt. address of the control registers */ 119 u32 __iomem *regs; /* virt. address of the control registers */
113 120
114 unsigned char __iomem *fb_virt; /* virt. address of the frame buffer */ 121 void *fb_virt; /* virt. address of the frame buffer */
115 dma_addr_t fb_phys; /* phys. address of the frame buffer */ 122 dma_addr_t fb_phys; /* phys. address of the frame buffer */
116 123
117 u32 reg_ctrl_default; 124 u32 reg_ctrl_default;
@@ -195,130 +202,120 @@ static struct fb_ops xilinxfb_ops =
195 .fb_imageblit = cfb_imageblit, 202 .fb_imageblit = cfb_imageblit,
196}; 203};
197 204
198/* === The device driver === */ 205/* ---------------------------------------------------------------------
206 * Bus independent setup/teardown
207 */
199 208
200static int 209static int xilinxfb_assign(struct device *dev, unsigned long physaddr,
201xilinxfb_drv_probe(struct device *dev) 210 int width_mm, int height_mm, int rotate)
202{ 211{
203 struct platform_device *pdev;
204 struct xilinxfb_platform_data *pdata;
205 struct xilinxfb_drvdata *drvdata; 212 struct xilinxfb_drvdata *drvdata;
206 struct resource *regs_res; 213 int rc;
207 int retval;
208
209 if (!dev)
210 return -EINVAL;
211
212 pdev = to_platform_device(dev);
213 pdata = pdev->dev.platform_data;
214 214
215 /* Allocate the driver data region */
215 drvdata = kzalloc(sizeof(*drvdata), GFP_KERNEL); 216 drvdata = kzalloc(sizeof(*drvdata), GFP_KERNEL);
216 if (!drvdata) { 217 if (!drvdata) {
217 printk(KERN_ERR "Couldn't allocate device private record\n"); 218 dev_err(dev, "Couldn't allocate device private record\n");
218 return -ENOMEM; 219 return -ENOMEM;
219 } 220 }
220 dev_set_drvdata(dev, drvdata); 221 dev_set_drvdata(dev, drvdata);
221 222
222 /* Map the control registers in */ 223 /* Map the control registers in */
223 regs_res = platform_get_resource(pdev, IORESOURCE_IO, 0); 224 if (!request_mem_region(physaddr, 8, DRIVER_NAME)) {
224 if (!regs_res || (regs_res->end - regs_res->start + 1 < 8)) { 225 dev_err(dev, "Couldn't lock memory region at 0x%08lX\n",
225 printk(KERN_ERR "Couldn't get registers resource\n"); 226 physaddr);
226 retval = -EFAULT; 227 rc = -ENODEV;
227 goto failed1; 228 goto err_region;
228 } 229 }
229 230 drvdata->regs_phys = physaddr;
230 if (!request_mem_region(regs_res->start, 8, DRIVER_NAME)) { 231 drvdata->regs = ioremap(physaddr, 8);
231 printk(KERN_ERR 232 if (!drvdata->regs) {
232 "Couldn't lock memory region at 0x%08X\n", 233 dev_err(dev, "Couldn't lock memory region at 0x%08lX\n",
233 regs_res->start); 234 physaddr);
234 retval = -EBUSY; 235 rc = -ENODEV;
235 goto failed1; 236 goto err_map;
236 } 237 }
237 drvdata->regs = (u32 __iomem*) ioremap(regs_res->start, 8);
238 drvdata->regs_phys = regs_res->start;
239 238
240 /* Allocate the framebuffer memory */ 239 /* Allocate the framebuffer memory */
241 drvdata->fb_virt = dma_alloc_coherent(dev, PAGE_ALIGN(FB_SIZE), 240 drvdata->fb_virt = dma_alloc_coherent(dev, PAGE_ALIGN(FB_SIZE),
242 &drvdata->fb_phys, GFP_KERNEL); 241 &drvdata->fb_phys, GFP_KERNEL);
243 if (!drvdata->fb_virt) { 242 if (!drvdata->fb_virt) {
244 printk(KERN_ERR "Could not allocate frame buffer memory\n"); 243 dev_err(dev, "Could not allocate frame buffer memory\n");
245 retval = -ENOMEM; 244 rc = -ENOMEM;
246 goto failed2; 245 goto err_fbmem;
247 } 246 }
248 247
249 /* Clear (turn to black) the framebuffer */ 248 /* Clear (turn to black) the framebuffer */
250 memset_io((void *) drvdata->fb_virt, 0, FB_SIZE); 249 memset_io((void __iomem *)drvdata->fb_virt, 0, FB_SIZE);
251 250
252 /* Tell the hardware where the frame buffer is */ 251 /* Tell the hardware where the frame buffer is */
253 xilinx_fb_out_be32(drvdata, REG_FB_ADDR, drvdata->fb_phys); 252 xilinx_fb_out_be32(drvdata, REG_FB_ADDR, drvdata->fb_phys);
254 253
255 /* Turn on the display */ 254 /* Turn on the display */
256 drvdata->reg_ctrl_default = REG_CTRL_ENABLE; 255 drvdata->reg_ctrl_default = REG_CTRL_ENABLE;
257 if (pdata && pdata->rotate_screen) 256 if (rotate)
258 drvdata->reg_ctrl_default |= REG_CTRL_ROTATE; 257 drvdata->reg_ctrl_default |= REG_CTRL_ROTATE;
259 xilinx_fb_out_be32(drvdata, REG_CTRL, drvdata->reg_ctrl_default); 258 xilinx_fb_out_be32(drvdata, REG_CTRL, drvdata->reg_ctrl_default);
260 259
261 /* Fill struct fb_info */ 260 /* Fill struct fb_info */
262 drvdata->info.device = dev; 261 drvdata->info.device = dev;
263 drvdata->info.screen_base = drvdata->fb_virt; 262 drvdata->info.screen_base = (void __iomem *)drvdata->fb_virt;
264 drvdata->info.fbops = &xilinxfb_ops; 263 drvdata->info.fbops = &xilinxfb_ops;
265 drvdata->info.fix = xilinx_fb_fix; 264 drvdata->info.fix = xilinx_fb_fix;
266 drvdata->info.fix.smem_start = drvdata->fb_phys; 265 drvdata->info.fix.smem_start = drvdata->fb_phys;
267 drvdata->info.pseudo_palette = drvdata->pseudo_palette; 266 drvdata->info.pseudo_palette = drvdata->pseudo_palette;
267 drvdata->info.flags = FBINFO_DEFAULT;
268 drvdata->info.var = xilinx_fb_var;
269
270 xilinx_fb_var.height = height_mm;
271 xilinx_fb_var.width = width_mm;
268 272
269 if (fb_alloc_cmap(&drvdata->info.cmap, PALETTE_ENTRIES_NO, 0) < 0) { 273 /* Allocate a colour map */
270 printk(KERN_ERR "Fail to allocate colormap (%d entries)\n", 274 rc = fb_alloc_cmap(&drvdata->info.cmap, PALETTE_ENTRIES_NO, 0);
275 if (rc) {
276 dev_err(dev, "Fail to allocate colormap (%d entries)\n",
271 PALETTE_ENTRIES_NO); 277 PALETTE_ENTRIES_NO);
272 retval = -EFAULT; 278 goto err_cmap;
273 goto failed3;
274 } 279 }
275 280
276 drvdata->info.flags = FBINFO_DEFAULT;
277 if (pdata) {
278 xilinx_fb_var.height = pdata->screen_height_mm;
279 xilinx_fb_var.width = pdata->screen_width_mm;
280 }
281 drvdata->info.var = xilinx_fb_var;
282
283 /* Register new frame buffer */ 281 /* Register new frame buffer */
284 if (register_framebuffer(&drvdata->info) < 0) { 282 rc = register_framebuffer(&drvdata->info);
285 printk(KERN_ERR "Could not register frame buffer\n"); 283 if (rc) {
286 retval = -EINVAL; 284 dev_err(dev, "Could not register frame buffer\n");
287 goto failed4; 285 goto err_regfb;
288 } 286 }
289 287
288 /* Put a banner in the log (for DEBUG) */
289 dev_dbg(dev, "regs: phys=%lx, virt=%p\n", physaddr, drvdata->regs);
290 dev_dbg(dev, "fb: phys=%p, virt=%p, size=%x\n",
291 (void*)drvdata->fb_phys, drvdata->fb_virt, FB_SIZE);
290 return 0; /* success */ 292 return 0; /* success */
291 293
292failed4: 294err_regfb:
293 fb_dealloc_cmap(&drvdata->info.cmap); 295 fb_dealloc_cmap(&drvdata->info.cmap);
294 296
295failed3: 297err_cmap:
296 dma_free_coherent(dev, PAGE_ALIGN(FB_SIZE), drvdata->fb_virt, 298 dma_free_coherent(dev, PAGE_ALIGN(FB_SIZE), drvdata->fb_virt,
297 drvdata->fb_phys); 299 drvdata->fb_phys);
298
299 /* Turn off the display */ 300 /* Turn off the display */
300 xilinx_fb_out_be32(drvdata, REG_CTRL, 0); 301 xilinx_fb_out_be32(drvdata, REG_CTRL, 0);
302
303err_fbmem:
301 iounmap(drvdata->regs); 304 iounmap(drvdata->regs);
302 305
303failed2: 306err_map:
304 release_mem_region(regs_res->start, 8); 307 release_mem_region(physaddr, 8);
305 308
306failed1: 309err_region:
307 kfree(drvdata); 310 kfree(drvdata);
308 dev_set_drvdata(dev, NULL); 311 dev_set_drvdata(dev, NULL);
309 312
310 return retval; 313 return rc;
311} 314}
312 315
313static int 316static int xilinxfb_release(struct device *dev)
314xilinxfb_drv_remove(struct device *dev)
315{ 317{
316 struct xilinxfb_drvdata *drvdata; 318 struct xilinxfb_drvdata *drvdata = dev_get_drvdata(dev);
317
318 if (!dev)
319 return -ENODEV;
320
321 drvdata = (struct xilinxfb_drvdata *) dev_get_drvdata(dev);
322 319
323#if !defined(CONFIG_FRAMEBUFFER_CONSOLE) && defined(CONFIG_LOGO) 320#if !defined(CONFIG_FRAMEBUFFER_CONSOLE) && defined(CONFIG_LOGO)
324 xilinx_fb_blank(VESA_POWERDOWN, &drvdata->info); 321 xilinx_fb_blank(VESA_POWERDOWN, &drvdata->info);
@@ -343,29 +340,151 @@ xilinxfb_drv_remove(struct device *dev)
343 return 0; 340 return 0;
344} 341}
345 342
343/* ---------------------------------------------------------------------
344 * Platform bus binding
345 */
346
347static int
348xilinxfb_platform_probe(struct platform_device *pdev)
349{
350 struct xilinxfb_platform_data *pdata;
351 struct resource *res;
352 int width_mm = 0;
353 int height_mm = 0;
354 int rotate = 0;
355
356 /* Find the registers address */
357 res = platform_get_resource(pdev, IORESOURCE_IO, 0);
358 if (!res) {
359 dev_err(&pdev->dev, "Couldn't get registers resource\n");
360 return -ENODEV;
361 }
362
363 /* If a pdata structure is provided, then extract the parameters */
364 pdata = pdev->dev.platform_data;
365 if (pdata) {
366 height_mm = pdata->screen_height_mm;
367 width_mm = pdata->screen_width_mm;
368 rotate = pdata->rotate_screen ? 1 : 0;
369 }
370
371 return xilinxfb_assign(&pdev->dev, res->start, width_mm, height_mm,
372 rotate);
373}
374
375static int
376xilinxfb_platform_remove(struct platform_device *pdev)
377{
378 return xilinxfb_release(&pdev->dev);
379}
346 380
347static struct device_driver xilinxfb_driver = {
348 .name = DRIVER_NAME,
349 .bus = &platform_bus_type,
350 381
351 .probe = xilinxfb_drv_probe, 382static struct platform_driver xilinxfb_platform_driver = {
352 .remove = xilinxfb_drv_remove 383 .probe = xilinxfb_platform_probe,
384 .remove = xilinxfb_platform_remove,
385 .driver = {
386 .owner = THIS_MODULE,
387 .name = DRIVER_NAME,
388 },
353}; 389};
354 390
391/* ---------------------------------------------------------------------
392 * OF bus binding
393 */
394
395#if defined(CONFIG_OF)
396static int __devinit
397xilinxfb_of_probe(struct of_device *op, const struct of_device_id *match)
398{
399 struct resource res;
400 const u32 *prop;
401 int width = 0, height = 0, rotate = 0;
402 int size, rc;
403
404 dev_dbg(&op->dev, "xilinxfb_of_probe(%p, %p)\n", op, match);
405
406 rc = of_address_to_resource(op->node, 0, &res);
407 if (rc) {
408 dev_err(&op->dev, "invalid address\n");
409 return rc;
410 }
411
412 prop = of_get_property(op->node, "display-number", &size);
413 if ((prop) && (size >= sizeof(u32)*2)) {
414 width = prop[0];
415 height = prop[1];
416 }
417
418 if (of_find_property(op->node, "rotate-display", NULL))
419 rotate = 1;
420
421 return xilinxfb_assign(&op->dev, res.start, width, height, rotate);
422}
423
424static int __devexit xilinxfb_of_remove(struct of_device *op)
425{
426 return xilinxfb_release(&op->dev);
427}
428
429/* Match table for of_platform binding */
430static struct of_device_id __devinit xilinxfb_of_match[] = {
431 { .compatible = "xilinx,ml300-fb", },
432 {},
433};
434MODULE_DEVICE_TABLE(of, xilinxfb_of_match);
435
436static struct of_platform_driver xilinxfb_of_driver = {
437 .owner = THIS_MODULE,
438 .name = DRIVER_NAME,
439 .match_table = xilinxfb_of_match,
440 .probe = xilinxfb_of_probe,
441 .remove = __devexit_p(xilinxfb_of_remove),
442 .driver = {
443 .name = DRIVER_NAME,
444 },
445};
446
447/* Registration helpers to keep the number of #ifdefs to a minimum */
448static inline int __init xilinxfb_of_register(void)
449{
450 pr_debug("xilinxfb: calling of_register_platform_driver()\n");
451 return of_register_platform_driver(&xilinxfb_of_driver);
452}
453
454static inline void __exit xilinxfb_of_unregister(void)
455{
456 of_unregister_platform_driver(&xilinxfb_of_driver);
457}
458#else /* CONFIG_OF */
459/* CONFIG_OF not enabled; do nothing helpers */
460static inline int __init xilinxfb_of_register(void) { return 0; }
461static inline void __exit xilinxfb_of_unregister(void) { }
462#endif /* CONFIG_OF */
463
464/* ---------------------------------------------------------------------
465 * Module setup and teardown
466 */
467
355static int __init 468static int __init
356xilinxfb_init(void) 469xilinxfb_init(void)
357{ 470{
358 /* 471 int rc;
359 * No kernel boot options used, 472 rc = xilinxfb_of_register();
360 * so we just need to register the driver 473 if (rc)
361 */ 474 return rc;
362 return driver_register(&xilinxfb_driver); 475
476 rc = platform_driver_register(&xilinxfb_platform_driver);
477 if (rc)
478 xilinxfb_of_unregister();
479
480 return rc;
363} 481}
364 482
365static void __exit 483static void __exit
366xilinxfb_cleanup(void) 484xilinxfb_cleanup(void)
367{ 485{
368 driver_unregister(&xilinxfb_driver); 486 platform_driver_unregister(&xilinxfb_platform_driver);
487 xilinxfb_of_unregister();
369} 488}
370 489
371module_init(xilinxfb_init); 490module_init(xilinxfb_init);