• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *	linux/arch/arm/mach-nspire/clcd.c
3  *
4  *	Copyright (C) 2013 Daniel Tang <tangrs@tangrs.id.au>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2, as
8  * published by the Free Software Foundation.
9  *
10  */
11 
12 #include <linux/init.h>
13 #include <linux/of.h>
14 #include <linux/amba/bus.h>
15 #include <linux/amba/clcd.h>
16 #include <linux/dma-mapping.h>
17 
18 static struct clcd_panel nspire_cx_lcd_panel = {
19 	.mode		= {
20 		.name		= "Color LCD",
21 		.refresh	= 60,
22 		.xres		= 320,
23 		.yres		= 240,
24 		.sync		= 0,
25 		.vmode		= FB_VMODE_NONINTERLACED,
26 		.pixclock	= 1,
27 		.hsync_len	= 6,
28 		.vsync_len	= 1,
29 		.right_margin	= 50,
30 		.left_margin	= 38,
31 		.lower_margin	= 3,
32 		.upper_margin	= 17,
33 	},
34 	.width		= 65, /* ~6.50 cm */
35 	.height		= 49, /* ~4.87 cm */
36 	.tim2		= TIM2_IPC,
37 	.cntl		= CNTL_LCDTFT | CNTL_LCDVCOMP(1),
38 	.bpp		= 16,
39 	.caps		= CLCD_CAP_565,
40 };
41 
42 static struct clcd_panel nspire_classic_lcd_panel = {
43 	.mode		= {
44 		.name		= "Grayscale LCD",
45 		.refresh	= 60,
46 		.xres		= 320,
47 		.yres		= 240,
48 		.sync		= FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
49 		.vmode		= FB_VMODE_NONINTERLACED,
50 		.pixclock	= 1,
51 		.hsync_len	= 6,
52 		.vsync_len	= 1,
53 		.right_margin	= 6,
54 		.left_margin	= 6,
55 	},
56 	.width		= 71, /* 7.11cm */
57 	.height		= 53, /* 5.33cm */
58 	.tim2		= 0x80007d0,
59 	.cntl		= CNTL_LCDMONO8,
60 	.bpp		= 8,
61 	.grayscale	= 1,
62 	.caps		= CLCD_CAP_5551,
63 };
64 
nspire_clcd_setup(struct clcd_fb * fb)65 int nspire_clcd_setup(struct clcd_fb *fb)
66 {
67 	struct clcd_panel *panel;
68 	size_t panel_size;
69 	const char *type;
70 	dma_addr_t dma;
71 	int err;
72 
73 	BUG_ON(!fb->dev->dev.of_node);
74 
75 	err = of_property_read_string(fb->dev->dev.of_node, "lcd-type", &type);
76 	if (err) {
77 		pr_err("CLCD: Could not find lcd-type property\n");
78 		return err;
79 	}
80 
81 	if (!strcmp(type, "cx")) {
82 		panel = &nspire_cx_lcd_panel;
83 	} else if (!strcmp(type, "classic")) {
84 		panel = &nspire_classic_lcd_panel;
85 	} else {
86 		pr_err("CLCD: Unknown lcd-type %s\n", type);
87 		return -EINVAL;
88 	}
89 
90 	panel_size = ((panel->mode.xres * panel->mode.yres) * panel->bpp) / 8;
91 	panel_size = ALIGN(panel_size, PAGE_SIZE);
92 
93 	fb->fb.screen_base = dma_alloc_wc(&fb->dev->dev, panel_size, &dma,
94 					  GFP_KERNEL);
95 
96 	if (!fb->fb.screen_base) {
97 		pr_err("CLCD: unable to map framebuffer\n");
98 		return -ENOMEM;
99 	}
100 
101 	fb->fb.fix.smem_start = dma;
102 	fb->fb.fix.smem_len = panel_size;
103 	fb->panel = panel;
104 
105 	return 0;
106 }
107 
nspire_clcd_mmap(struct clcd_fb * fb,struct vm_area_struct * vma)108 int nspire_clcd_mmap(struct clcd_fb *fb, struct vm_area_struct *vma)
109 {
110 	return dma_mmap_wc(&fb->dev->dev, vma, fb->fb.screen_base,
111 			   fb->fb.fix.smem_start, fb->fb.fix.smem_len);
112 }
113 
nspire_clcd_remove(struct clcd_fb * fb)114 void nspire_clcd_remove(struct clcd_fb *fb)
115 {
116 	dma_free_wc(&fb->dev->dev, fb->fb.fix.smem_len, fb->fb.screen_base,
117 		    fb->fb.fix.smem_start);
118 }
119