aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/wm8505fb.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/video/wm8505fb.c')
-rw-r--r--drivers/video/wm8505fb.c145
1 files changed, 45 insertions, 100 deletions
diff --git a/drivers/video/wm8505fb.c b/drivers/video/wm8505fb.c
index 4dd0580f96fd..01f9ace068e2 100644
--- a/drivers/video/wm8505fb.c
+++ b/drivers/video/wm8505fb.c
@@ -14,25 +14,25 @@
14 * GNU General Public License for more details. 14 * GNU General Public License for more details.
15 */ 15 */
16 16
17#include <linux/module.h>
18#include <linux/kernel.h>
19#include <linux/errno.h>
20#include <linux/string.h>
21#include <linux/mm.h>
22#include <linux/slab.h>
23#include <linux/delay.h> 17#include <linux/delay.h>
18#include <linux/dma-mapping.h>
24#include <linux/fb.h> 19#include <linux/fb.h>
20#include <linux/errno.h>
21#include <linux/err.h>
25#include <linux/init.h> 22#include <linux/init.h>
26#include <linux/interrupt.h> 23#include <linux/interrupt.h>
27#include <linux/io.h> 24#include <linux/io.h>
28#include <linux/dma-mapping.h> 25#include <linux/kernel.h>
29#include <linux/platform_device.h> 26#include <linux/memblock.h>
30#include <linux/wait.h> 27#include <linux/mm.h>
28#include <linux/module.h>
31#include <linux/of.h> 29#include <linux/of.h>
32#include <linux/of_fdt.h> 30#include <linux/of_fdt.h>
33#include <linux/memblock.h> 31#include <linux/platform_device.h>
34 32#include <linux/slab.h>
35#include <linux/platform_data/video-vt8500lcdfb.h> 33#include <linux/string.h>
34#include <linux/wait.h>
35#include <video/of_display_timing.h>
36 36
37#include "wm8505fb_regs.h" 37#include "wm8505fb_regs.h"
38#include "wmt_ge_rops.h" 38#include "wmt_ge_rops.h"
@@ -263,26 +263,22 @@ static struct fb_ops wm8505fb_ops = {
263static int wm8505fb_probe(struct platform_device *pdev) 263static int wm8505fb_probe(struct platform_device *pdev)
264{ 264{
265 struct wm8505fb_info *fbi; 265 struct wm8505fb_info *fbi;
266 struct resource *res; 266 struct resource *res;
267 struct display_timings *disp_timing;
267 void *addr; 268 void *addr;
268 int ret; 269 int ret;
269 270
270 struct fb_videomode of_mode; 271 struct fb_videomode mode;
271 struct device_node *np;
272 u32 bpp; 272 u32 bpp;
273 dma_addr_t fb_mem_phys; 273 dma_addr_t fb_mem_phys;
274 unsigned long fb_mem_len; 274 unsigned long fb_mem_len;
275 void *fb_mem_virt; 275 void *fb_mem_virt;
276 276
277 ret = -ENOMEM;
278 fbi = NULL;
279
280 fbi = devm_kzalloc(&pdev->dev, sizeof(struct wm8505fb_info) + 277 fbi = devm_kzalloc(&pdev->dev, sizeof(struct wm8505fb_info) +
281 sizeof(u32) * 16, GFP_KERNEL); 278 sizeof(u32) * 16, GFP_KERNEL);
282 if (!fbi) { 279 if (!fbi) {
283 dev_err(&pdev->dev, "Failed to initialize framebuffer device\n"); 280 dev_err(&pdev->dev, "Failed to initialize framebuffer device\n");
284 ret = -ENOMEM; 281 return -ENOMEM;
285 goto failed;
286 } 282 }
287 283
288 strcpy(fbi->fb.fix.id, DRIVER_NAME); 284 strcpy(fbi->fb.fix.id, DRIVER_NAME);
@@ -308,54 +304,23 @@ static int wm8505fb_probe(struct platform_device *pdev)
308 fbi->fb.pseudo_palette = addr; 304 fbi->fb.pseudo_palette = addr;
309 305
310 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 306 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
311 if (res == NULL) { 307 fbi->regbase = devm_ioremap_resource(&pdev->dev, res);
312 dev_err(&pdev->dev, "no I/O memory resource defined\n"); 308 if (IS_ERR(fbi->regbase))
313 ret = -ENODEV; 309 return PTR_ERR(fbi->regbase);
314 goto failed_fbi;
315 }
316 310
317 res = request_mem_region(res->start, resource_size(res), DRIVER_NAME); 311 disp_timing = of_get_display_timings(pdev->dev.of_node);
318 if (res == NULL) { 312 if (!disp_timing)
319 dev_err(&pdev->dev, "failed to request I/O memory\n"); 313 return -EINVAL;
320 ret = -EBUSY;
321 goto failed_fbi;
322 }
323
324 fbi->regbase = ioremap(res->start, resource_size(res));
325 if (fbi->regbase == NULL) {
326 dev_err(&pdev->dev, "failed to map I/O memory\n");
327 ret = -EBUSY;
328 goto failed_free_res;
329 }
330 314
331 np = of_parse_phandle(pdev->dev.of_node, "default-mode", 0); 315 ret = of_get_fb_videomode(pdev->dev.of_node, &mode, OF_USE_NATIVE_MODE);
332 if (!np) { 316 if (ret)
333 pr_err("%s: No display description in Device Tree\n", __func__); 317 return ret;
334 ret = -EINVAL;
335 goto failed_free_res;
336 }
337 318
338 /* 319 ret = of_property_read_u32(pdev->dev.of_node, "bits-per-pixel", &bpp);
339 * This code is copied from Sascha Hauer's of_videomode helper 320 if (ret)
340 * and can be replaced with a call to the helper once mainlined 321 return ret;
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 322
357 of_mode.vmode = FB_VMODE_NONINTERLACED; 323 fb_videomode_to_var(&fbi->fb.var, &mode);
358 fb_videomode_to_var(&fbi->fb.var, &of_mode);
359 324
360 fbi->fb.var.nonstd = 0; 325 fbi->fb.var.nonstd = 0;
361 fbi->fb.var.activate = FB_ACTIVATE_NOW; 326 fbi->fb.var.activate = FB_ACTIVATE_NOW;
@@ -364,16 +329,16 @@ static int wm8505fb_probe(struct platform_device *pdev)
364 fbi->fb.var.width = -1; 329 fbi->fb.var.width = -1;
365 330
366 /* try allocating the framebuffer */ 331 /* try allocating the framebuffer */
367 fb_mem_len = of_mode.xres * of_mode.yres * 2 * (bpp / 8); 332 fb_mem_len = mode.xres * mode.yres * 2 * (bpp / 8);
368 fb_mem_virt = dma_alloc_coherent(&pdev->dev, fb_mem_len, &fb_mem_phys, 333 fb_mem_virt = dmam_alloc_coherent(&pdev->dev, fb_mem_len, &fb_mem_phys,
369 GFP_KERNEL); 334 GFP_KERNEL);
370 if (!fb_mem_virt) { 335 if (!fb_mem_virt) {
371 pr_err("%s: Failed to allocate framebuffer\n", __func__); 336 pr_err("%s: Failed to allocate framebuffer\n", __func__);
372 return -ENOMEM; 337 return -ENOMEM;
373 }; 338 }
374 339
375 fbi->fb.var.xres_virtual = of_mode.xres; 340 fbi->fb.var.xres_virtual = mode.xres;
376 fbi->fb.var.yres_virtual = of_mode.yres * 2; 341 fbi->fb.var.yres_virtual = mode.yres * 2;
377 fbi->fb.var.bits_per_pixel = bpp; 342 fbi->fb.var.bits_per_pixel = bpp;
378 343
379 fbi->fb.fix.smem_start = fb_mem_phys; 344 fbi->fb.fix.smem_start = fb_mem_phys;
@@ -381,28 +346,29 @@ static int wm8505fb_probe(struct platform_device *pdev)
381 fbi->fb.screen_base = fb_mem_virt; 346 fbi->fb.screen_base = fb_mem_virt;
382 fbi->fb.screen_size = fb_mem_len; 347 fbi->fb.screen_size = fb_mem_len;
383 348
349 fbi->contrast = 0x10;
350 ret = wm8505fb_set_par(&fbi->fb);
351 if (ret) {
352 dev_err(&pdev->dev, "Failed to set parameters\n");
353 return ret;
354 }
355
384 if (fb_alloc_cmap(&fbi->fb.cmap, 256, 0) < 0) { 356 if (fb_alloc_cmap(&fbi->fb.cmap, 256, 0) < 0) {
385 dev_err(&pdev->dev, "Failed to allocate color map\n"); 357 dev_err(&pdev->dev, "Failed to allocate color map\n");
386 ret = -ENOMEM; 358 return -ENOMEM;
387 goto failed_free_io;
388 } 359 }
389 360
390 wm8505fb_init_hw(&fbi->fb); 361 wm8505fb_init_hw(&fbi->fb);
391 362
392 fbi->contrast = 0x80;
393 ret = wm8505fb_set_par(&fbi->fb);
394 if (ret) {
395 dev_err(&pdev->dev, "Failed to set parameters\n");
396 goto failed_free_cmap;
397 }
398
399 platform_set_drvdata(pdev, fbi); 363 platform_set_drvdata(pdev, fbi);
400 364
401 ret = register_framebuffer(&fbi->fb); 365 ret = register_framebuffer(&fbi->fb);
402 if (ret < 0) { 366 if (ret < 0) {
403 dev_err(&pdev->dev, 367 dev_err(&pdev->dev,
404 "Failed to register framebuffer device: %d\n", ret); 368 "Failed to register framebuffer device: %d\n", ret);
405 goto failed_free_cmap; 369 if (fbi->fb.cmap.len)
370 fb_dealloc_cmap(&fbi->fb.cmap);
371 return ret;
406 } 372 }
407 373
408 ret = device_create_file(&pdev->dev, &dev_attr_contrast); 374 ret = device_create_file(&pdev->dev, &dev_attr_contrast);
@@ -416,25 +382,11 @@ static int wm8505fb_probe(struct platform_device *pdev)
416 fbi->fb.fix.smem_start + fbi->fb.fix.smem_len - 1); 382 fbi->fb.fix.smem_start + fbi->fb.fix.smem_len - 1);
417 383
418 return 0; 384 return 0;
419
420failed_free_cmap:
421 if (fbi->fb.cmap.len)
422 fb_dealloc_cmap(&fbi->fb.cmap);
423failed_free_io:
424 iounmap(fbi->regbase);
425failed_free_res:
426 release_mem_region(res->start, resource_size(res));
427failed_fbi:
428 platform_set_drvdata(pdev, NULL);
429 kfree(fbi);
430failed:
431 return ret;
432} 385}
433 386
434static int wm8505fb_remove(struct platform_device *pdev) 387static int wm8505fb_remove(struct platform_device *pdev)
435{ 388{
436 struct wm8505fb_info *fbi = platform_get_drvdata(pdev); 389 struct wm8505fb_info *fbi = platform_get_drvdata(pdev);
437 struct resource *res;
438 390
439 device_remove_file(&pdev->dev, &dev_attr_contrast); 391 device_remove_file(&pdev->dev, &dev_attr_contrast);
440 392
@@ -445,13 +397,6 @@ static int wm8505fb_remove(struct platform_device *pdev)
445 if (fbi->fb.cmap.len) 397 if (fbi->fb.cmap.len)
446 fb_dealloc_cmap(&fbi->fb.cmap); 398 fb_dealloc_cmap(&fbi->fb.cmap);
447 399
448 iounmap(fbi->regbase);
449
450 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
451 release_mem_region(res->start, resource_size(res));
452
453 kfree(fbi);
454
455 return 0; 400 return 0;
456} 401}
457 402