diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/video/xilinxfb.c | 290 |
1 files changed, 151 insertions, 139 deletions
diff --git a/drivers/video/xilinxfb.c b/drivers/video/xilinxfb.c index 40a3a2afbfe7..7a868bd16e0e 100644 --- a/drivers/video/xilinxfb.c +++ b/drivers/video/xilinxfb.c | |||
@@ -1,13 +1,12 @@ | |||
1 | /* | 1 | /* |
2 | * xilinxfb.c | 2 | * Xilinx TFT frame buffer driver |
3 | * | ||
4 | * Xilinx TFT LCD frame buffer driver | ||
5 | * | 3 | * |
6 | * Author: MontaVista Software, Inc. | 4 | * Author: MontaVista Software, Inc. |
7 | * source@mvista.com | 5 | * source@mvista.com |
8 | * | 6 | * |
9 | * 2002-2007 (c) MontaVista Software, Inc. | 7 | * 2002-2007 (c) MontaVista Software, Inc. |
10 | * 2007 (c) Secret Lab Technologies, Ltd. | 8 | * 2007 (c) Secret Lab Technologies, Ltd. |
9 | * 2009 (c) Xilinx Inc. | ||
11 | * | 10 | * |
12 | * This file is licensed under the terms of the GNU General Public License | 11 | * 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 | 12 | * version 2. This program is licensed "as is" without any warranty of any |
@@ -24,33 +23,38 @@ | |||
24 | #include <linux/device.h> | 23 | #include <linux/device.h> |
25 | #include <linux/module.h> | 24 | #include <linux/module.h> |
26 | #include <linux/kernel.h> | 25 | #include <linux/kernel.h> |
26 | #include <linux/version.h> | ||
27 | #include <linux/errno.h> | 27 | #include <linux/errno.h> |
28 | #include <linux/string.h> | 28 | #include <linux/string.h> |
29 | #include <linux/mm.h> | 29 | #include <linux/mm.h> |
30 | #include <linux/fb.h> | 30 | #include <linux/fb.h> |
31 | #include <linux/init.h> | 31 | #include <linux/init.h> |
32 | #include <linux/dma-mapping.h> | 32 | #include <linux/dma-mapping.h> |
33 | #include <linux/platform_device.h> | ||
34 | #if defined(CONFIG_OF) | ||
35 | #include <linux/of_device.h> | 33 | #include <linux/of_device.h> |
36 | #include <linux/of_platform.h> | 34 | #include <linux/of_platform.h> |
37 | #endif | 35 | #include <linux/io.h> |
38 | #include <asm/io.h> | ||
39 | #include <linux/xilinxfb.h> | 36 | #include <linux/xilinxfb.h> |
37 | #include <asm/dcr.h> | ||
40 | 38 | ||
41 | #define DRIVER_NAME "xilinxfb" | 39 | #define DRIVER_NAME "xilinxfb" |
42 | #define DRIVER_DESCRIPTION "Xilinx TFT LCD frame buffer driver" | 40 | |
43 | 41 | ||
44 | /* | 42 | /* |
45 | * Xilinx calls it "PLB TFT LCD Controller" though it can also be used for | 43 | * Xilinx calls it "PLB TFT LCD Controller" though it can also be used for |
46 | * the VGA port on the Xilinx ML40x board. This is a hardware display controller | 44 | * the VGA port on the Xilinx ML40x board. This is a hardware display |
47 | * for a 640x480 resolution TFT or VGA screen. | 45 | * controller for a 640x480 resolution TFT or VGA screen. |
48 | * | 46 | * |
49 | * The interface to the framebuffer is nice and simple. There are two | 47 | * The interface to the framebuffer is nice and simple. There are two |
50 | * control registers. The first tells the LCD interface where in memory | 48 | * control registers. The first tells the LCD interface where in memory |
51 | * the frame buffer is (only the 11 most significant bits are used, so | 49 | * the frame buffer is (only the 11 most significant bits are used, so |
52 | * don't start thinking about scrolling). The second allows the LCD to | 50 | * don't start thinking about scrolling). The second allows the LCD to |
53 | * be turned on or off as well as rotated 180 degrees. | 51 | * be turned on or off as well as rotated 180 degrees. |
52 | * | ||
53 | * In case of direct PLB access the second control register will be at | ||
54 | * an offset of 4 as compared to the DCR access where the offset is 1 | ||
55 | * i.e. REG_CTRL. So this is taken care in the function | ||
56 | * xilinx_fb_out_be32 where it left shifts the offset 2 times in case of | ||
57 | * direct PLB access. | ||
54 | */ | 58 | */ |
55 | #define NUM_REGS 2 | 59 | #define NUM_REGS 2 |
56 | #define REG_FB_ADDR 0 | 60 | #define REG_FB_ADDR 0 |
@@ -107,17 +111,28 @@ static struct fb_var_screeninfo xilinx_fb_var = { | |||
107 | .activate = FB_ACTIVATE_NOW | 111 | .activate = FB_ACTIVATE_NOW |
108 | }; | 112 | }; |
109 | 113 | ||
114 | |||
115 | #define PLB_ACCESS_FLAG 0x1 /* 1 = PLB, 0 = DCR */ | ||
116 | |||
110 | struct xilinxfb_drvdata { | 117 | struct xilinxfb_drvdata { |
111 | 118 | ||
112 | struct fb_info info; /* FB driver info record */ | 119 | struct fb_info info; /* FB driver info record */ |
113 | 120 | ||
114 | u32 regs_phys; /* phys. address of the control registers */ | 121 | phys_addr_t regs_phys; /* phys. address of the control |
115 | u32 __iomem *regs; /* virt. address of the control registers */ | 122 | registers */ |
123 | void __iomem *regs; /* virt. address of the control | ||
124 | registers */ | ||
125 | |||
126 | dcr_host_t dcr_host; | ||
127 | unsigned int dcr_start; | ||
128 | unsigned int dcr_len; | ||
116 | 129 | ||
117 | void *fb_virt; /* virt. address of the frame buffer */ | 130 | void *fb_virt; /* virt. address of the frame buffer */ |
118 | dma_addr_t fb_phys; /* phys. address of the frame buffer */ | 131 | dma_addr_t fb_phys; /* phys. address of the frame buffer */ |
119 | int fb_alloced; /* Flag, was the fb memory alloced? */ | 132 | int fb_alloced; /* Flag, was the fb memory alloced? */ |
120 | 133 | ||
134 | u8 flags; /* features of the driver */ | ||
135 | |||
121 | u32 reg_ctrl_default; | 136 | u32 reg_ctrl_default; |
122 | 137 | ||
123 | u32 pseudo_palette[PALETTE_ENTRIES_NO]; | 138 | u32 pseudo_palette[PALETTE_ENTRIES_NO]; |
@@ -128,14 +143,19 @@ struct xilinxfb_drvdata { | |||
128 | container_of(_info, struct xilinxfb_drvdata, info) | 143 | container_of(_info, struct xilinxfb_drvdata, info) |
129 | 144 | ||
130 | /* | 145 | /* |
131 | * The LCD controller has DCR interface to its registers, but all | 146 | * The XPS TFT Controller can be accessed through PLB or DCR interface. |
132 | * the boards and configurations the driver has been tested with | 147 | * To perform the read/write on the registers we need to check on |
133 | * use opb2dcr bridge. So the registers are seen as memory mapped. | 148 | * which bus its connected and call the appropriate write API. |
134 | * This macro is to make it simple to add the direct DCR access | ||
135 | * when it's needed. | ||
136 | */ | 149 | */ |
137 | #define xilinx_fb_out_be32(driverdata, offset, val) \ | 150 | static void xilinx_fb_out_be32(struct xilinxfb_drvdata *drvdata, u32 offset, |
138 | out_be32(driverdata->regs + offset, val) | 151 | u32 val) |
152 | { | ||
153 | if (drvdata->flags & PLB_ACCESS_FLAG) | ||
154 | out_be32(drvdata->regs + (offset << 2), val); | ||
155 | else | ||
156 | dcr_write(drvdata->dcr_host, offset, val); | ||
157 | |||
158 | } | ||
139 | 159 | ||
140 | static int | 160 | static int |
141 | xilinx_fb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue, | 161 | xilinx_fb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue, |
@@ -203,35 +223,34 @@ static struct fb_ops xilinxfb_ops = | |||
203 | * Bus independent setup/teardown | 223 | * Bus independent setup/teardown |
204 | */ | 224 | */ |
205 | 225 | ||
206 | static int xilinxfb_assign(struct device *dev, unsigned long physaddr, | 226 | static int xilinxfb_assign(struct device *dev, |
227 | struct xilinxfb_drvdata *drvdata, | ||
228 | unsigned long physaddr, | ||
207 | struct xilinxfb_platform_data *pdata) | 229 | struct xilinxfb_platform_data *pdata) |
208 | { | 230 | { |
209 | struct xilinxfb_drvdata *drvdata; | ||
210 | int rc; | 231 | int rc; |
211 | int fbsize = pdata->xvirt * pdata->yvirt * BYTES_PER_PIXEL; | 232 | int fbsize = pdata->xvirt * pdata->yvirt * BYTES_PER_PIXEL; |
212 | 233 | ||
213 | /* Allocate the driver data region */ | 234 | if (drvdata->flags & PLB_ACCESS_FLAG) { |
214 | drvdata = kzalloc(sizeof(*drvdata), GFP_KERNEL); | 235 | /* |
215 | if (!drvdata) { | 236 | * Map the control registers in if the controller |
216 | dev_err(dev, "Couldn't allocate device private record\n"); | 237 | * is on direct PLB interface. |
217 | return -ENOMEM; | 238 | */ |
218 | } | 239 | if (!request_mem_region(physaddr, 8, DRIVER_NAME)) { |
219 | dev_set_drvdata(dev, drvdata); | 240 | dev_err(dev, "Couldn't lock memory region at 0x%08lX\n", |
220 | 241 | physaddr); | |
221 | /* Map the control registers in */ | 242 | rc = -ENODEV; |
222 | if (!request_mem_region(physaddr, 8, DRIVER_NAME)) { | 243 | goto err_region; |
223 | dev_err(dev, "Couldn't lock memory region at 0x%08lX\n", | 244 | } |
224 | physaddr); | 245 | |
225 | rc = -ENODEV; | 246 | drvdata->regs_phys = physaddr; |
226 | goto err_region; | 247 | drvdata->regs = ioremap(physaddr, 8); |
227 | } | 248 | if (!drvdata->regs) { |
228 | drvdata->regs_phys = physaddr; | 249 | dev_err(dev, "Couldn't lock memory region at 0x%08lX\n", |
229 | drvdata->regs = ioremap(physaddr, 8); | 250 | physaddr); |
230 | if (!drvdata->regs) { | 251 | rc = -ENODEV; |
231 | dev_err(dev, "Couldn't lock memory region at 0x%08lX\n", | 252 | goto err_map; |
232 | physaddr); | 253 | } |
233 | rc = -ENODEV; | ||
234 | goto err_map; | ||
235 | } | 254 | } |
236 | 255 | ||
237 | /* Allocate the framebuffer memory */ | 256 | /* Allocate the framebuffer memory */ |
@@ -247,7 +266,10 @@ static int xilinxfb_assign(struct device *dev, unsigned long physaddr, | |||
247 | if (!drvdata->fb_virt) { | 266 | if (!drvdata->fb_virt) { |
248 | dev_err(dev, "Could not allocate frame buffer memory\n"); | 267 | dev_err(dev, "Could not allocate frame buffer memory\n"); |
249 | rc = -ENOMEM; | 268 | rc = -ENOMEM; |
250 | goto err_fbmem; | 269 | if (drvdata->flags & PLB_ACCESS_FLAG) |
270 | goto err_fbmem; | ||
271 | else | ||
272 | goto err_region; | ||
251 | } | 273 | } |
252 | 274 | ||
253 | /* Clear (turn to black) the framebuffer */ | 275 | /* Clear (turn to black) the framebuffer */ |
@@ -260,7 +282,8 @@ static int xilinxfb_assign(struct device *dev, unsigned long physaddr, | |||
260 | drvdata->reg_ctrl_default = REG_CTRL_ENABLE; | 282 | drvdata->reg_ctrl_default = REG_CTRL_ENABLE; |
261 | if (pdata->rotate_screen) | 283 | if (pdata->rotate_screen) |
262 | drvdata->reg_ctrl_default |= REG_CTRL_ROTATE; | 284 | drvdata->reg_ctrl_default |= REG_CTRL_ROTATE; |
263 | xilinx_fb_out_be32(drvdata, REG_CTRL, drvdata->reg_ctrl_default); | 285 | xilinx_fb_out_be32(drvdata, REG_CTRL, |
286 | drvdata->reg_ctrl_default); | ||
264 | 287 | ||
265 | /* Fill struct fb_info */ | 288 | /* Fill struct fb_info */ |
266 | drvdata->info.device = dev; | 289 | drvdata->info.device = dev; |
@@ -296,11 +319,14 @@ static int xilinxfb_assign(struct device *dev, unsigned long physaddr, | |||
296 | goto err_regfb; | 319 | goto err_regfb; |
297 | } | 320 | } |
298 | 321 | ||
322 | if (drvdata->flags & PLB_ACCESS_FLAG) { | ||
323 | /* Put a banner in the log (for DEBUG) */ | ||
324 | dev_dbg(dev, "regs: phys=%lx, virt=%p\n", physaddr, | ||
325 | drvdata->regs); | ||
326 | } | ||
299 | /* Put a banner in the log (for DEBUG) */ | 327 | /* Put a banner in the log (for DEBUG) */ |
300 | dev_dbg(dev, "regs: phys=%lx, virt=%p\n", physaddr, drvdata->regs); | 328 | dev_dbg(dev, "fb: phys=%p, virt=%p, size=%x\n", |
301 | dev_dbg(dev, "fb: phys=%llx, virt=%p, size=%x\n", | 329 | (void *)drvdata->fb_phys, drvdata->fb_virt, fbsize); |
302 | (unsigned long long) drvdata->fb_phys, drvdata->fb_virt, | ||
303 | fbsize); | ||
304 | 330 | ||
305 | return 0; /* success */ | 331 | return 0; /* success */ |
306 | 332 | ||
@@ -311,14 +337,19 @@ err_cmap: | |||
311 | if (drvdata->fb_alloced) | 337 | if (drvdata->fb_alloced) |
312 | dma_free_coherent(dev, PAGE_ALIGN(fbsize), drvdata->fb_virt, | 338 | dma_free_coherent(dev, PAGE_ALIGN(fbsize), drvdata->fb_virt, |
313 | drvdata->fb_phys); | 339 | drvdata->fb_phys); |
340 | else | ||
341 | iounmap(drvdata->fb_virt); | ||
342 | |||
314 | /* Turn off the display */ | 343 | /* Turn off the display */ |
315 | xilinx_fb_out_be32(drvdata, REG_CTRL, 0); | 344 | xilinx_fb_out_be32(drvdata, REG_CTRL, 0); |
316 | 345 | ||
317 | err_fbmem: | 346 | err_fbmem: |
318 | iounmap(drvdata->regs); | 347 | if (drvdata->flags & PLB_ACCESS_FLAG) |
348 | iounmap(drvdata->regs); | ||
319 | 349 | ||
320 | err_map: | 350 | err_map: |
321 | release_mem_region(physaddr, 8); | 351 | if (drvdata->flags & PLB_ACCESS_FLAG) |
352 | release_mem_region(physaddr, 8); | ||
322 | 353 | ||
323 | err_region: | 354 | err_region: |
324 | kfree(drvdata); | 355 | kfree(drvdata); |
@@ -342,12 +373,18 @@ static int xilinxfb_release(struct device *dev) | |||
342 | if (drvdata->fb_alloced) | 373 | if (drvdata->fb_alloced) |
343 | dma_free_coherent(dev, PAGE_ALIGN(drvdata->info.fix.smem_len), | 374 | dma_free_coherent(dev, PAGE_ALIGN(drvdata->info.fix.smem_len), |
344 | drvdata->fb_virt, drvdata->fb_phys); | 375 | drvdata->fb_virt, drvdata->fb_phys); |
376 | else | ||
377 | iounmap(drvdata->fb_virt); | ||
345 | 378 | ||
346 | /* Turn off the display */ | 379 | /* Turn off the display */ |
347 | xilinx_fb_out_be32(drvdata, REG_CTRL, 0); | 380 | xilinx_fb_out_be32(drvdata, REG_CTRL, 0); |
348 | iounmap(drvdata->regs); | ||
349 | 381 | ||
350 | release_mem_region(drvdata->regs_phys, 8); | 382 | /* Release the resources, as allocated based on interface */ |
383 | if (drvdata->flags & PLB_ACCESS_FLAG) { | ||
384 | iounmap(drvdata->regs); | ||
385 | release_mem_region(drvdata->regs_phys, 8); | ||
386 | } else | ||
387 | dcr_unmap(drvdata->dcr_host, drvdata->dcr_len); | ||
351 | 388 | ||
352 | kfree(drvdata); | 389 | kfree(drvdata); |
353 | dev_set_drvdata(dev, NULL); | 390 | dev_set_drvdata(dev, NULL); |
@@ -356,77 +393,57 @@ static int xilinxfb_release(struct device *dev) | |||
356 | } | 393 | } |
357 | 394 | ||
358 | /* --------------------------------------------------------------------- | 395 | /* --------------------------------------------------------------------- |
359 | * Platform bus binding | ||
360 | */ | ||
361 | |||
362 | static int | ||
363 | xilinxfb_platform_probe(struct platform_device *pdev) | ||
364 | { | ||
365 | struct xilinxfb_platform_data *pdata; | ||
366 | struct resource *res; | ||
367 | |||
368 | /* Find the registers address */ | ||
369 | res = platform_get_resource(pdev, IORESOURCE_IO, 0); | ||
370 | if (!res) { | ||
371 | dev_err(&pdev->dev, "Couldn't get registers resource\n"); | ||
372 | return -ENODEV; | ||
373 | } | ||
374 | |||
375 | /* If a pdata structure is provided, then extract the parameters */ | ||
376 | pdata = &xilinx_fb_default_pdata; | ||
377 | if (pdev->dev.platform_data) { | ||
378 | pdata = pdev->dev.platform_data; | ||
379 | if (!pdata->xres) | ||
380 | pdata->xres = xilinx_fb_default_pdata.xres; | ||
381 | if (!pdata->yres) | ||
382 | pdata->yres = xilinx_fb_default_pdata.yres; | ||
383 | if (!pdata->xvirt) | ||
384 | pdata->xvirt = xilinx_fb_default_pdata.xvirt; | ||
385 | if (!pdata->yvirt) | ||
386 | pdata->yvirt = xilinx_fb_default_pdata.yvirt; | ||
387 | } | ||
388 | |||
389 | return xilinxfb_assign(&pdev->dev, res->start, pdata); | ||
390 | } | ||
391 | |||
392 | static int | ||
393 | xilinxfb_platform_remove(struct platform_device *pdev) | ||
394 | { | ||
395 | return xilinxfb_release(&pdev->dev); | ||
396 | } | ||
397 | |||
398 | |||
399 | static struct platform_driver xilinxfb_platform_driver = { | ||
400 | .probe = xilinxfb_platform_probe, | ||
401 | .remove = xilinxfb_platform_remove, | ||
402 | .driver = { | ||
403 | .owner = THIS_MODULE, | ||
404 | .name = DRIVER_NAME, | ||
405 | }, | ||
406 | }; | ||
407 | |||
408 | /* --------------------------------------------------------------------- | ||
409 | * OF bus binding | 396 | * OF bus binding |
410 | */ | 397 | */ |
411 | 398 | ||
412 | #if defined(CONFIG_OF) | ||
413 | static int __devinit | 399 | static int __devinit |
414 | xilinxfb_of_probe(struct of_device *op, const struct of_device_id *match) | 400 | xilinxfb_of_probe(struct of_device *op, const struct of_device_id *match) |
415 | { | 401 | { |
416 | struct resource res; | ||
417 | const u32 *prop; | 402 | const u32 *prop; |
403 | u32 *p; | ||
404 | u32 tft_access; | ||
418 | struct xilinxfb_platform_data pdata; | 405 | struct xilinxfb_platform_data pdata; |
406 | struct resource res; | ||
419 | int size, rc; | 407 | int size, rc; |
408 | int start = 0, len = 0; | ||
409 | dcr_host_t dcr_host; | ||
410 | struct xilinxfb_drvdata *drvdata; | ||
420 | 411 | ||
421 | /* Copy with the default pdata (not a ptr reference!) */ | 412 | /* Copy with the default pdata (not a ptr reference!) */ |
422 | pdata = xilinx_fb_default_pdata; | 413 | pdata = xilinx_fb_default_pdata; |
423 | 414 | ||
424 | dev_dbg(&op->dev, "xilinxfb_of_probe(%p, %p)\n", op, match); | 415 | dev_dbg(&op->dev, "xilinxfb_of_probe(%p, %p)\n", op, match); |
425 | 416 | ||
426 | rc = of_address_to_resource(op->node, 0, &res); | 417 | /* |
427 | if (rc) { | 418 | * To check whether the core is connected directly to DCR or PLB |
428 | dev_err(&op->dev, "invalid address\n"); | 419 | * interface and initialize the tft_access accordingly. |
429 | return rc; | 420 | */ |
421 | p = (u32 *)of_get_property(op->node, "xlnx,dcr-splb-slave-if", NULL); | ||
422 | |||
423 | if (p) | ||
424 | tft_access = *p; | ||
425 | else | ||
426 | tft_access = 0; /* For backward compatibility */ | ||
427 | |||
428 | /* | ||
429 | * Fill the resource structure if its direct PLB interface | ||
430 | * otherwise fill the dcr_host structure. | ||
431 | */ | ||
432 | if (tft_access) { | ||
433 | rc = of_address_to_resource(op->node, 0, &res); | ||
434 | if (rc) { | ||
435 | dev_err(&op->dev, "invalid address\n"); | ||
436 | return -ENODEV; | ||
437 | } | ||
438 | |||
439 | } else { | ||
440 | start = dcr_resource_start(op->node, 0); | ||
441 | len = dcr_resource_len(op->node, 0); | ||
442 | dcr_host = dcr_map(op->node, start, len); | ||
443 | if (!DCR_MAP_OK(dcr_host)) { | ||
444 | dev_err(&op->dev, "invalid address\n"); | ||
445 | return -ENODEV; | ||
446 | } | ||
430 | } | 447 | } |
431 | 448 | ||
432 | prop = of_get_property(op->node, "phys-size", &size); | 449 | prop = of_get_property(op->node, "phys-size", &size); |
@@ -450,7 +467,26 @@ xilinxfb_of_probe(struct of_device *op, const struct of_device_id *match) | |||
450 | if (of_find_property(op->node, "rotate-display", NULL)) | 467 | if (of_find_property(op->node, "rotate-display", NULL)) |
451 | pdata.rotate_screen = 1; | 468 | pdata.rotate_screen = 1; |
452 | 469 | ||
453 | return xilinxfb_assign(&op->dev, res.start, &pdata); | 470 | /* Allocate the driver data region */ |
471 | drvdata = kzalloc(sizeof(*drvdata), GFP_KERNEL); | ||
472 | if (!drvdata) { | ||
473 | dev_err(&op->dev, "Couldn't allocate device private record\n"); | ||
474 | return -ENOMEM; | ||
475 | } | ||
476 | dev_set_drvdata(&op->dev, drvdata); | ||
477 | |||
478 | if (tft_access) | ||
479 | drvdata->flags |= PLB_ACCESS_FLAG; | ||
480 | |||
481 | /* Arguments are passed based on the interface */ | ||
482 | if (drvdata->flags & PLB_ACCESS_FLAG) { | ||
483 | return xilinxfb_assign(&op->dev, drvdata, res.start, &pdata); | ||
484 | } else { | ||
485 | drvdata->dcr_start = start; | ||
486 | drvdata->dcr_len = len; | ||
487 | drvdata->dcr_host = dcr_host; | ||
488 | return xilinxfb_assign(&op->dev, drvdata, 0, &pdata); | ||
489 | } | ||
454 | } | 490 | } |
455 | 491 | ||
456 | static int __devexit xilinxfb_of_remove(struct of_device *op) | 492 | static int __devexit xilinxfb_of_remove(struct of_device *op) |
@@ -460,7 +496,9 @@ static int __devexit xilinxfb_of_remove(struct of_device *op) | |||
460 | 496 | ||
461 | /* Match table for of_platform binding */ | 497 | /* Match table for of_platform binding */ |
462 | static struct of_device_id xilinxfb_of_match[] __devinitdata = { | 498 | static struct of_device_id xilinxfb_of_match[] __devinitdata = { |
499 | { .compatible = "xlnx,xps-tft-1.00.a", }, | ||
463 | { .compatible = "xlnx,plb-tft-cntlr-ref-1.00.a", }, | 500 | { .compatible = "xlnx,plb-tft-cntlr-ref-1.00.a", }, |
501 | { .compatible = "xlnx,plb-dvi-cntlr-ref-1.00.c", }, | ||
464 | {}, | 502 | {}, |
465 | }; | 503 | }; |
466 | MODULE_DEVICE_TABLE(of, xilinxfb_of_match); | 504 | MODULE_DEVICE_TABLE(of, xilinxfb_of_match); |
@@ -476,22 +514,6 @@ static struct of_platform_driver xilinxfb_of_driver = { | |||
476 | }, | 514 | }, |
477 | }; | 515 | }; |
478 | 516 | ||
479 | /* Registration helpers to keep the number of #ifdefs to a minimum */ | ||
480 | static inline int __init xilinxfb_of_register(void) | ||
481 | { | ||
482 | pr_debug("xilinxfb: calling of_register_platform_driver()\n"); | ||
483 | return of_register_platform_driver(&xilinxfb_of_driver); | ||
484 | } | ||
485 | |||
486 | static inline void __exit xilinxfb_of_unregister(void) | ||
487 | { | ||
488 | of_unregister_platform_driver(&xilinxfb_of_driver); | ||
489 | } | ||
490 | #else /* CONFIG_OF */ | ||
491 | /* CONFIG_OF not enabled; do nothing helpers */ | ||
492 | static inline int __init xilinxfb_of_register(void) { return 0; } | ||
493 | static inline void __exit xilinxfb_of_unregister(void) { } | ||
494 | #endif /* CONFIG_OF */ | ||
495 | 517 | ||
496 | /* --------------------------------------------------------------------- | 518 | /* --------------------------------------------------------------------- |
497 | * Module setup and teardown | 519 | * Module setup and teardown |
@@ -500,28 +522,18 @@ static inline void __exit xilinxfb_of_unregister(void) { } | |||
500 | static int __init | 522 | static int __init |
501 | xilinxfb_init(void) | 523 | xilinxfb_init(void) |
502 | { | 524 | { |
503 | int rc; | 525 | return of_register_platform_driver(&xilinxfb_of_driver); |
504 | rc = xilinxfb_of_register(); | ||
505 | if (rc) | ||
506 | return rc; | ||
507 | |||
508 | rc = platform_driver_register(&xilinxfb_platform_driver); | ||
509 | if (rc) | ||
510 | xilinxfb_of_unregister(); | ||
511 | |||
512 | return rc; | ||
513 | } | 526 | } |
514 | 527 | ||
515 | static void __exit | 528 | static void __exit |
516 | xilinxfb_cleanup(void) | 529 | xilinxfb_cleanup(void) |
517 | { | 530 | { |
518 | platform_driver_unregister(&xilinxfb_platform_driver); | 531 | of_unregister_platform_driver(&xilinxfb_of_driver); |
519 | xilinxfb_of_unregister(); | ||
520 | } | 532 | } |
521 | 533 | ||
522 | module_init(xilinxfb_init); | 534 | module_init(xilinxfb_init); |
523 | module_exit(xilinxfb_cleanup); | 535 | module_exit(xilinxfb_cleanup); |
524 | 536 | ||
525 | MODULE_AUTHOR("MontaVista Software, Inc. <source@mvista.com>"); | 537 | MODULE_AUTHOR("MontaVista Software, Inc. <source@mvista.com>"); |
526 | MODULE_DESCRIPTION(DRIVER_DESCRIPTION); | 538 | MODULE_DESCRIPTION("Xilinx TFT frame buffer driver"); |
527 | MODULE_LICENSE("GPL"); | 539 | MODULE_LICENSE("GPL"); |