1 #include <linux/device.h>
2 #include <linux/dma-mapping.h>
3 #include <linux/amba/bus.h>
4 #include <linux/amba/clcd.h>
5 #include <plat/clcd.h>
6 
7 static struct clcd_panel vga = {
8 	.mode		= {
9 		.name		= "VGA",
10 		.refresh	= 60,
11 		.xres		= 640,
12 		.yres		= 480,
13 		.pixclock	= 39721,
14 		.left_margin	= 40,
15 		.right_margin	= 24,
16 		.upper_margin	= 32,
17 		.lower_margin	= 11,
18 		.hsync_len	= 96,
19 		.vsync_len	= 2,
20 		.sync		= 0,
21 		.vmode		= FB_VMODE_NONINTERLACED,
22 	},
23 	.width		= -1,
24 	.height		= -1,
25 	.tim2		= TIM2_BCD | TIM2_IPC,
26 	.cntl		= CNTL_LCDTFT | CNTL_BGR | CNTL_LCDVCOMP(1),
27 	.caps		= CLCD_CAP_5551 | CLCD_CAP_565 | CLCD_CAP_888,
28 	.bpp		= 16,
29 };
30 
31 static struct clcd_panel xvga = {
32 	.mode		= {
33 		.name		= "XVGA",
34 		.refresh	= 60,
35 		.xres		= 1024,
36 		.yres		= 768,
37 		.pixclock	= 15748,
38 		.left_margin	= 152,
39 		.right_margin	= 48,
40 		.upper_margin	= 23,
41 		.lower_margin	= 3,
42 		.hsync_len	= 104,
43 		.vsync_len	= 4,
44 		.sync		= 0,
45 		.vmode		= FB_VMODE_NONINTERLACED,
46 	},
47 	.width		= -1,
48 	.height		= -1,
49 	.tim2		= TIM2_BCD | TIM2_IPC,
50 	.cntl		= CNTL_LCDTFT | CNTL_BGR | CNTL_LCDVCOMP(1),
51 	.caps		= CLCD_CAP_5551 | CLCD_CAP_565 | CLCD_CAP_888,
52 	.bpp		= 16,
53 };
54 
55 /* Sanyo TM38QV67A02A - 3.8 inch QVGA (320x240) Color TFT */
56 static struct clcd_panel sanyo_tm38qv67a02a = {
57 	.mode		= {
58 		.name		= "Sanyo TM38QV67A02A",
59 		.refresh	= 116,
60 		.xres		= 320,
61 		.yres		= 240,
62 		.pixclock	= 100000,
63 		.left_margin	= 6,
64 		.right_margin	= 6,
65 		.upper_margin	= 5,
66 		.lower_margin	= 5,
67 		.hsync_len	= 6,
68 		.vsync_len	= 6,
69 		.sync		= 0,
70 		.vmode		= FB_VMODE_NONINTERLACED,
71 	},
72 	.width		= -1,
73 	.height		= -1,
74 	.tim2		= TIM2_BCD,
75 	.cntl		= CNTL_LCDTFT | CNTL_BGR | CNTL_LCDVCOMP(1),
76 	.caps		= CLCD_CAP_5551,
77 	.bpp		= 16,
78 };
79 
80 static struct clcd_panel sanyo_2_5_in = {
81 	.mode		= {
82 		.name		= "Sanyo QVGA Portrait",
83 		.refresh	= 116,
84 		.xres		= 240,
85 		.yres		= 320,
86 		.pixclock	= 100000,
87 		.left_margin	= 20,
88 		.right_margin	= 10,
89 		.upper_margin	= 2,
90 		.lower_margin	= 2,
91 		.hsync_len	= 10,
92 		.vsync_len	= 2,
93 		.sync		= FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
94 		.vmode		= FB_VMODE_NONINTERLACED,
95 	},
96 	.width		= -1,
97 	.height		= -1,
98 	.tim2		= TIM2_IVS | TIM2_IHS | TIM2_IPC,
99 	.cntl		= CNTL_LCDTFT | CNTL_BGR | CNTL_LCDVCOMP(1),
100 	.caps		= CLCD_CAP_5551,
101 	.bpp		= 16,
102 };
103 
104 /* Epson L2F50113T00 - 2.2 inch 176x220 Color TFT */
105 static struct clcd_panel epson_l2f50113t00 = {
106 	.mode		= {
107 		.name		= "Epson L2F50113T00",
108 		.refresh	= 390,
109 		.xres		= 176,
110 		.yres		= 220,
111 		.pixclock	= 62500,
112 		.left_margin	= 3,
113 		.right_margin	= 2,
114 		.upper_margin	= 1,
115 		.lower_margin	= 0,
116 		.hsync_len	= 3,
117 		.vsync_len	= 2,
118 		.sync		= 0,
119 		.vmode		= FB_VMODE_NONINTERLACED,
120 	},
121 	.width		= -1,
122 	.height		= -1,
123 	.tim2		= TIM2_BCD | TIM2_IPC,
124 	.cntl		= CNTL_LCDTFT | CNTL_BGR | CNTL_LCDVCOMP(1),
125 	.caps		= CLCD_CAP_5551,
126 	.bpp		= 16,
127 };
128 
129 static struct clcd_panel *panels[] = {
130 	&vga,
131 	&xvga,
132 	&sanyo_tm38qv67a02a,
133 	&sanyo_2_5_in,
134 	&epson_l2f50113t00,
135 };
136 
versatile_clcd_get_panel(const char * name)137 struct clcd_panel *versatile_clcd_get_panel(const char *name)
138 {
139 	int i;
140 
141 	for (i = 0; i < ARRAY_SIZE(panels); i++)
142 		if (strcmp(panels[i]->mode.name, name) == 0)
143 			break;
144 
145 	if (i < ARRAY_SIZE(panels))
146 		return panels[i];
147 
148 	pr_err("CLCD: couldn't get parameters for panel %s\n", name);
149 
150 	return NULL;
151 }
152 
versatile_clcd_setup_dma(struct clcd_fb * fb,unsigned long framesize)153 int versatile_clcd_setup_dma(struct clcd_fb *fb, unsigned long framesize)
154 {
155 	dma_addr_t dma;
156 
157 	fb->fb.screen_base = dma_alloc_writecombine(&fb->dev->dev, framesize,
158 						    &dma, GFP_KERNEL);
159 	if (!fb->fb.screen_base) {
160 		pr_err("CLCD: unable to map framebuffer\n");
161 		return -ENOMEM;
162 	}
163 
164 	fb->fb.fix.smem_start	= dma;
165 	fb->fb.fix.smem_len	= framesize;
166 
167 	return 0;
168 }
169 
versatile_clcd_mmap_dma(struct clcd_fb * fb,struct vm_area_struct * vma)170 int versatile_clcd_mmap_dma(struct clcd_fb *fb, struct vm_area_struct *vma)
171 {
172 	return dma_mmap_writecombine(&fb->dev->dev, vma,
173 				     fb->fb.screen_base,
174 				     fb->fb.fix.smem_start,
175 				     fb->fb.fix.smem_len);
176 }
177 
versatile_clcd_remove_dma(struct clcd_fb * fb)178 void versatile_clcd_remove_dma(struct clcd_fb *fb)
179 {
180 	dma_free_writecombine(&fb->dev->dev, fb->fb.fix.smem_len,
181 			      fb->fb.screen_base, fb->fb.fix.smem_start);
182 }
183