diff options
author | Tony Prisk <linux@prisktech.co.nz> | 2012-08-03 04:58:22 -0400 |
---|---|---|
committer | Tony Prisk <linux@prisktech.co.nz> | 2012-09-21 03:23:56 -0400 |
commit | e7b995371fe1e29838321fcdc3cfe35bb0d6bfc4 (patch) | |
tree | def3385d58244aa0c4da4098d0d99b92353a3416 /drivers/video/wm8505fb.c | |
parent | 4001130df1a74948cfa8be02b420953a84ab83e8 (diff) |
video: vt8500: Add devicetree support for vt8500-fb and wm8505-fb
Update vt8500-fb, wm8505-fb and wmt-ge-rops to support device
tree bindings.
Small change in wm8505-fb.c to support WM8650 framebuffer color
format.
Signed-off-by: Tony Prisk <linux@prisktech.co.nz>
Diffstat (limited to 'drivers/video/wm8505fb.c')
-rw-r--r-- | drivers/video/wm8505fb.c | 97 |
1 files changed, 82 insertions, 15 deletions
diff --git a/drivers/video/wm8505fb.c b/drivers/video/wm8505fb.c index c8703bd61b7..ec474244210 100644 --- a/drivers/video/wm8505fb.c +++ b/drivers/video/wm8505fb.c | |||
@@ -28,6 +28,9 @@ | |||
28 | #include <linux/dma-mapping.h> | 28 | #include <linux/dma-mapping.h> |
29 | #include <linux/platform_device.h> | 29 | #include <linux/platform_device.h> |
30 | #include <linux/wait.h> | 30 | #include <linux/wait.h> |
31 | #include <linux/of.h> | ||
32 | #include <linux/of_fdt.h> | ||
33 | #include <linux/memblock.h> | ||
31 | 34 | ||
32 | #include <mach/vt8500fb.h> | 35 | #include <mach/vt8500fb.h> |
33 | 36 | ||
@@ -59,8 +62,12 @@ static int wm8505fb_init_hw(struct fb_info *info) | |||
59 | writel(fbi->fb.fix.smem_start, fbi->regbase + WMT_GOVR_FBADDR); | 62 | writel(fbi->fb.fix.smem_start, fbi->regbase + WMT_GOVR_FBADDR); |
60 | writel(fbi->fb.fix.smem_start, fbi->regbase + WMT_GOVR_FBADDR1); | 63 | writel(fbi->fb.fix.smem_start, fbi->regbase + WMT_GOVR_FBADDR1); |
61 | 64 | ||
62 | /* Set in-memory picture format to RGB 32bpp */ | 65 | /* |
63 | writel(0x1c, fbi->regbase + WMT_GOVR_COLORSPACE); | 66 | * Set in-memory picture format to RGB |
67 | * 0x31C sets the correct color mode (RGB565) for WM8650 | ||
68 | * Bit 8+9 (0x300) are ignored on WM8505 as reserved | ||
69 | */ | ||
70 | writel(0x31c, fbi->regbase + WMT_GOVR_COLORSPACE); | ||
64 | writel(1, fbi->regbase + WMT_GOVR_COLORSPACE1); | 71 | writel(1, fbi->regbase + WMT_GOVR_COLORSPACE1); |
65 | 72 | ||
66 | /* Virtual buffer size */ | 73 | /* Virtual buffer size */ |
@@ -127,6 +134,18 @@ static int wm8505fb_set_par(struct fb_info *info) | |||
127 | info->var.blue.msb_right = 0; | 134 | info->var.blue.msb_right = 0; |
128 | info->fix.visual = FB_VISUAL_TRUECOLOR; | 135 | info->fix.visual = FB_VISUAL_TRUECOLOR; |
129 | info->fix.line_length = info->var.xres_virtual << 2; | 136 | info->fix.line_length = info->var.xres_virtual << 2; |
137 | } else if (info->var.bits_per_pixel == 16) { | ||
138 | info->var.red.offset = 11; | ||
139 | info->var.red.length = 5; | ||
140 | info->var.red.msb_right = 0; | ||
141 | info->var.green.offset = 5; | ||
142 | info->var.green.length = 6; | ||
143 | info->var.green.msb_right = 0; | ||
144 | info->var.blue.offset = 0; | ||
145 | info->var.blue.length = 5; | ||
146 | info->var.blue.msb_right = 0; | ||
147 | info->fix.visual = FB_VISUAL_TRUECOLOR; | ||
148 | info->fix.line_length = info->var.xres_virtual << 1; | ||
130 | } | 149 | } |
131 | 150 | ||
132 | wm8505fb_set_timing(info); | 151 | wm8505fb_set_timing(info); |
@@ -246,16 +265,20 @@ static int __devinit wm8505fb_probe(struct platform_device *pdev) | |||
246 | struct wm8505fb_info *fbi; | 265 | struct wm8505fb_info *fbi; |
247 | struct resource *res; | 266 | struct resource *res; |
248 | void *addr; | 267 | void *addr; |
249 | struct vt8500fb_platform_data *pdata; | ||
250 | int ret; | 268 | int ret; |
251 | 269 | ||
252 | pdata = pdev->dev.platform_data; | 270 | struct fb_videomode of_mode; |
271 | struct device_node *np; | ||
272 | u32 bpp; | ||
273 | dma_addr_t fb_mem_phys; | ||
274 | unsigned long fb_mem_len; | ||
275 | void *fb_mem_virt; | ||
253 | 276 | ||
254 | ret = -ENOMEM; | 277 | ret = -ENOMEM; |
255 | fbi = NULL; | 278 | fbi = NULL; |
256 | 279 | ||
257 | fbi = kzalloc(sizeof(struct wm8505fb_info) + sizeof(u32) * 16, | 280 | fbi = devm_kzalloc(&pdev->dev, sizeof(struct wm8505fb_info) + |
258 | GFP_KERNEL); | 281 | sizeof(u32) * 16, GFP_KERNEL); |
259 | if (!fbi) { | 282 | if (!fbi) { |
260 | dev_err(&pdev->dev, "Failed to initialize framebuffer device\n"); | 283 | dev_err(&pdev->dev, "Failed to initialize framebuffer device\n"); |
261 | ret = -ENOMEM; | 284 | ret = -ENOMEM; |
@@ -305,21 +328,58 @@ static int __devinit wm8505fb_probe(struct platform_device *pdev) | |||
305 | goto failed_free_res; | 328 | goto failed_free_res; |
306 | } | 329 | } |
307 | 330 | ||
308 | fb_videomode_to_var(&fbi->fb.var, &pdata->mode); | 331 | np = of_parse_phandle(pdev->dev.of_node, "default-mode", 0); |
332 | if (!np) { | ||
333 | pr_err("%s: No display description in Device Tree\n", __func__); | ||
334 | ret = -EINVAL; | ||
335 | goto failed_free_res; | ||
336 | } | ||
337 | |||
338 | /* | ||
339 | * This code is copied from Sascha Hauer's of_videomode helper | ||
340 | * and can be replaced with a call to the helper once mainlined | ||
341 | */ | ||
342 | ret = 0; | ||
343 | ret |= of_property_read_u32(np, "hactive", &of_mode.xres); | ||
344 | ret |= of_property_read_u32(np, "vactive", &of_mode.yres); | ||
345 | ret |= of_property_read_u32(np, "hback-porch", &of_mode.left_margin); | ||
346 | ret |= of_property_read_u32(np, "hfront-porch", &of_mode.right_margin); | ||
347 | ret |= of_property_read_u32(np, "hsync-len", &of_mode.hsync_len); | ||
348 | ret |= of_property_read_u32(np, "vback-porch", &of_mode.upper_margin); | ||
349 | ret |= of_property_read_u32(np, "vfront-porch", &of_mode.lower_margin); | ||
350 | ret |= of_property_read_u32(np, "vsync-len", &of_mode.vsync_len); | ||
351 | ret |= of_property_read_u32(np, "bpp", &bpp); | ||
352 | if (ret) { | ||
353 | pr_err("%s: Unable to read display properties\n", __func__); | ||
354 | goto failed_free_res; | ||
355 | } | ||
356 | |||
357 | of_mode.vmode = FB_VMODE_NONINTERLACED; | ||
358 | fb_videomode_to_var(&fbi->fb.var, &of_mode); | ||
309 | 359 | ||
310 | fbi->fb.var.nonstd = 0; | 360 | fbi->fb.var.nonstd = 0; |
311 | fbi->fb.var.activate = FB_ACTIVATE_NOW; | 361 | fbi->fb.var.activate = FB_ACTIVATE_NOW; |
312 | 362 | ||
313 | fbi->fb.var.height = -1; | 363 | fbi->fb.var.height = -1; |
314 | fbi->fb.var.width = -1; | 364 | fbi->fb.var.width = -1; |
315 | fbi->fb.var.xres_virtual = pdata->xres_virtual; | ||
316 | fbi->fb.var.yres_virtual = pdata->yres_virtual; | ||
317 | fbi->fb.var.bits_per_pixel = pdata->bpp; | ||
318 | 365 | ||
319 | fbi->fb.fix.smem_start = pdata->video_mem_phys; | 366 | /* try allocating the framebuffer */ |
320 | fbi->fb.fix.smem_len = pdata->video_mem_len; | 367 | fb_mem_len = of_mode.xres * of_mode.yres * 2 * (bpp / 8); |
321 | fbi->fb.screen_base = pdata->video_mem_virt; | 368 | fb_mem_virt = dma_alloc_coherent(&pdev->dev, fb_mem_len, &fb_mem_phys, |
322 | fbi->fb.screen_size = pdata->video_mem_len; | 369 | GFP_KERNEL); |
370 | if (!fb_mem_virt) { | ||
371 | pr_err("%s: Failed to allocate framebuffer\n", __func__); | ||
372 | return -ENOMEM; | ||
373 | }; | ||
374 | |||
375 | fbi->fb.var.xres_virtual = of_mode.xres; | ||
376 | fbi->fb.var.yres_virtual = of_mode.yres * 2; | ||
377 | fbi->fb.var.bits_per_pixel = bpp; | ||
378 | |||
379 | fbi->fb.fix.smem_start = fb_mem_phys; | ||
380 | fbi->fb.fix.smem_len = fb_mem_len; | ||
381 | fbi->fb.screen_base = fb_mem_virt; | ||
382 | fbi->fb.screen_size = fb_mem_len; | ||
323 | 383 | ||
324 | if (fb_alloc_cmap(&fbi->fb.cmap, 256, 0) < 0) { | 384 | if (fb_alloc_cmap(&fbi->fb.cmap, 256, 0) < 0) { |
325 | dev_err(&pdev->dev, "Failed to allocate color map\n"); | 385 | dev_err(&pdev->dev, "Failed to allocate color map\n"); |
@@ -395,12 +455,18 @@ static int __devexit wm8505fb_remove(struct platform_device *pdev) | |||
395 | return 0; | 455 | return 0; |
396 | } | 456 | } |
397 | 457 | ||
458 | static const struct of_device_id wmt_dt_ids[] = { | ||
459 | { .compatible = "wm,wm8505-fb", }, | ||
460 | {} | ||
461 | }; | ||
462 | |||
398 | static struct platform_driver wm8505fb_driver = { | 463 | static struct platform_driver wm8505fb_driver = { |
399 | .probe = wm8505fb_probe, | 464 | .probe = wm8505fb_probe, |
400 | .remove = __devexit_p(wm8505fb_remove), | 465 | .remove = __devexit_p(wm8505fb_remove), |
401 | .driver = { | 466 | .driver = { |
402 | .owner = THIS_MODULE, | 467 | .owner = THIS_MODULE, |
403 | .name = DRIVER_NAME, | 468 | .name = DRIVER_NAME, |
469 | .of_match_table = of_match_ptr(wmt_dt_ids), | ||
404 | }, | 470 | }, |
405 | }; | 471 | }; |
406 | 472 | ||
@@ -408,4 +474,5 @@ module_platform_driver(wm8505fb_driver); | |||
408 | 474 | ||
409 | MODULE_AUTHOR("Ed Spiridonov <edo.rus@gmail.com>"); | 475 | MODULE_AUTHOR("Ed Spiridonov <edo.rus@gmail.com>"); |
410 | MODULE_DESCRIPTION("Framebuffer driver for WMT WM8505"); | 476 | MODULE_DESCRIPTION("Framebuffer driver for WMT WM8505"); |
411 | MODULE_LICENSE("GPL"); | 477 | MODULE_LICENSE("GPL v2"); |
478 | MODULE_DEVICE_TABLE(of, wmt_dt_ids); | ||