Root/
Source at commit a0570c5a4352b42e3e62ddce75e24db15650bfa7 created 12 years 9 months ago. By Maarten ter Huurne, MIPS: JZ4740: SLCD framebufer driver | |
---|---|
1 | /* |
2 | * linux/drivers/video/jz4740_slcd_panels.c |
3 | * -- LCD panel definitions for Ingenic On-Chip SLCD frame buffer device |
4 | * |
5 | * Copyright (C) 2005-2007, Ingenic Semiconductor Inc. |
6 | * Copyright (C) 2009, Ignacio Garcia Perez <iggarpe@gmail.com> |
7 | * Copyright (C) 2010, Maarten ter Huurne <maarten@treewalker.org> |
8 | * Copyright (C) 2011, ChinaChip |
9 | * |
10 | * This program is free software; you can redistribute it and/or modify |
11 | * it under the terms of the GNU General Public License version 2 as |
12 | * published by the Free Software Foundation. |
13 | * |
14 | */ |
15 | |
16 | #include <asm/io.h> |
17 | #include <asm/mach-jz4740/gpio.h> |
18 | #include <asm/mach-jz4740/jz4740_fb.h> |
19 | #include <linux/delay.h> |
20 | #include <linux/gpio.h> |
21 | #include <linux/kernel.h> |
22 | #include <linux/moduleparam.h> |
23 | #include <linux/platform_device.h> |
24 | |
25 | #include "jz4740_slcd.h" |
26 | |
27 | static char *default_slcd_panel; |
28 | #ifdef CONFIG_JZ_SLCD_ILI9338 |
29 | static unsigned int default_slcd_rgb[3] = { 100, 100, 100, }; |
30 | #endif |
31 | |
32 | /* Send a command without data. */ |
33 | static void send_panel_command(struct jzfb *jzfb, u32 cmd) { |
34 | u16 slcd_cfg = readw(jzfb->base + JZ_REG_SLCD_CFG); |
35 | switch (slcd_cfg & SLCD_CFG_CWIDTH_MASK) { |
36 | case SLCD_CFG_CWIDTH_8BIT: |
37 | while (readb(jzfb->base + JZ_REG_SLCD_STATE) & SLCD_STATE_BUSY); |
38 | writel(SLCD_DATA_RS_COMMAND | ((cmd&0xff00) >> 8), jzfb->base + JZ_REG_SLCD_DATA); |
39 | while (readb(jzfb->base + JZ_REG_SLCD_STATE) & SLCD_STATE_BUSY); |
40 | writel(SLCD_DATA_RS_COMMAND | ((cmd&0xff) >> 0), jzfb->base + JZ_REG_SLCD_DATA); |
41 | break; |
42 | case SLCD_CFG_CWIDTH_16BIT: |
43 | while (readb(jzfb->base + JZ_REG_SLCD_STATE) & SLCD_STATE_BUSY); |
44 | writel(SLCD_DATA_RS_COMMAND | (cmd&0xffff), jzfb->base + JZ_REG_SLCD_DATA); |
45 | break; |
46 | case SLCD_CFG_CWIDTH_18BIT: |
47 | while (readb(jzfb->base + JZ_REG_SLCD_STATE) & SLCD_STATE_BUSY); |
48 | writel(SLCD_DATA_RS_COMMAND | ((cmd&0xff00) << 2) | ((cmd&0xff) << 1), jzfb->base + JZ_REG_SLCD_DATA); |
49 | break; |
50 | default: |
51 | break; |
52 | } |
53 | } |
54 | |
55 | /* Send data without command. */ |
56 | static void send_panel_data(struct jzfb *jzfb, u32 data) |
57 | { |
58 | u16 slcd_cfg = readw(jzfb->base + JZ_REG_SLCD_CFG); |
59 | switch (slcd_cfg & SLCD_CFG_DWIDTH_MASK) { |
60 | case SLCD_CFG_DWIDTH_18: |
61 | while (readb(jzfb->base + JZ_REG_SLCD_STATE) & SLCD_STATE_BUSY); |
62 | data = ((data & 0xff) << 1) | ((data & 0xff00) << 2); |
63 | writel(SLCD_DATA_RS_DATA | ((data<<6)&0xfc0000)|((data<<4)&0xfc00) | ((data<<2)&0xfc), jzfb->base + JZ_REG_SLCD_DATA); |
64 | break; |
65 | case SLCD_CFG_DWIDTH_16: |
66 | while (readb(jzfb->base + JZ_REG_SLCD_STATE) & SLCD_STATE_BUSY); |
67 | writel(SLCD_DATA_RS_DATA | (data&0xffff), jzfb->base + JZ_REG_SLCD_DATA); |
68 | break; |
69 | case SLCD_CFG_DWIDTH_9_x2: |
70 | data = ((data & 0xff) << 1) | ((data & 0xff00) << 2); |
71 | data = ((data << 6) & 0xfc0000) | ((data << 4) & 0xfc00) | ((data << 2) & 0xfc); |
72 | while (readb(jzfb->base + JZ_REG_SLCD_STATE) & SLCD_STATE_BUSY); |
73 | writel(SLCD_DATA_RS_DATA | data, jzfb->base + JZ_REG_SLCD_DATA); |
74 | break; |
75 | default: |
76 | while (readb(jzfb->base + JZ_REG_SLCD_STATE) & SLCD_STATE_BUSY); |
77 | writel(SLCD_DATA_RS_DATA | (data&0xffff), jzfb->base + JZ_REG_SLCD_DATA); |
78 | break; |
79 | } |
80 | } |
81 | |
82 | /* Send command and data. */ |
83 | static void set_panel_reg(struct jzfb *jzfb, u32 cmd, u32 data) |
84 | { |
85 | send_panel_command(jzfb, cmd); |
86 | send_panel_data(jzfb, data); |
87 | } |
88 | |
89 | #ifdef CONFIG_JZ_SLCD_ILI9325 |
90 | |
91 | // TODO(MtH): GPIO assignments belong in the board definition, since two |
92 | // boards using the same panel controller could still use different |
93 | // GPIO assignments. |
94 | // TODO(MtH): CS mismatch: B17 (A320) vs C20 (standard). |
95 | #define ILI9325_GPIO_CS_N JZ_GPIO_PORTB(17) /* Chip select */ |
96 | #define ILI9325_GPIO_RESET_N JZ_GPIO_PORTB(18) /* LCD reset */ |
97 | |
98 | static void ili9325_enable(struct jzfb *jzfb) |
99 | { |
100 | /* RESET pulse */ |
101 | gpio_set_value(ILI9325_GPIO_RESET_N, 0); |
102 | msleep(10); |
103 | gpio_set_value(ILI9325_GPIO_RESET_N, 1); |
104 | msleep(50); |
105 | |
106 | /* Enable chip select */ |
107 | gpio_set_value(ILI9325_GPIO_CS_N, 0); |
108 | |
109 | /* Black magic */ |
110 | set_panel_reg(jzfb, 0xE3, 0x3008); |
111 | set_panel_reg(jzfb, 0xE7, 0x0012); |
112 | set_panel_reg(jzfb, 0xEF, 0x1231); |
113 | set_panel_reg(jzfb, 0x01, 0x0100); |
114 | set_panel_reg(jzfb, 0x02, 0x0700); |
115 | set_panel_reg(jzfb, 0x03, 0x1098); |
116 | set_panel_reg(jzfb, 0x04, 0x0000); |
117 | set_panel_reg(jzfb, 0x08, 0x0207); |
118 | set_panel_reg(jzfb, 0x09, 0x0000); |
119 | set_panel_reg(jzfb, 0x0A, 0x0000); |
120 | set_panel_reg(jzfb, 0x0C, 0x0000); |
121 | set_panel_reg(jzfb, 0x0D, 0x0000); |
122 | set_panel_reg(jzfb, 0x0F, 0x0000); |
123 | set_panel_reg(jzfb, 0x10, 0x0000); |
124 | set_panel_reg(jzfb, 0x11, 0x0007); |
125 | set_panel_reg(jzfb, 0x12, 0x0000); |
126 | set_panel_reg(jzfb, 0x13, 0x0000); |
127 | msleep(200); |
128 | set_panel_reg(jzfb, 0x10, 0x1290); |
129 | set_panel_reg(jzfb, 0x11, 0x0227); |
130 | msleep(50); |
131 | set_panel_reg(jzfb, 0x12, 0x001B); |
132 | msleep(50); |
133 | set_panel_reg(jzfb, 0x13, 0x0500); |
134 | set_panel_reg(jzfb, 0x29, 0x000C); |
135 | set_panel_reg(jzfb, 0x2B, 0x000D); |
136 | msleep(50); |
137 | set_panel_reg(jzfb, 0x20, 0x0000); |
138 | set_panel_reg(jzfb, 0x21, 0x0000); |
139 | set_panel_reg(jzfb, 0x30, 0x0000); |
140 | set_panel_reg(jzfb, 0x31, 0x0204); |
141 | set_panel_reg(jzfb, 0x32, 0x0200); |
142 | set_panel_reg(jzfb, 0x35, 0x0007); |
143 | set_panel_reg(jzfb, 0x36, 0x1404); |
144 | set_panel_reg(jzfb, 0x37, 0x0705); |
145 | set_panel_reg(jzfb, 0x38, 0x0305); |
146 | set_panel_reg(jzfb, 0x39, 0x0707); |
147 | set_panel_reg(jzfb, 0x3C, 0x0701); |
148 | set_panel_reg(jzfb, 0x3D, 0x000E); |
149 | set_panel_reg(jzfb, 0x50, 0x0000); |
150 | set_panel_reg(jzfb, 0x51, 0x00EF); |
151 | set_panel_reg(jzfb, 0x52, 0x0000); |
152 | set_panel_reg(jzfb, 0x53, 0x013F); |
153 | set_panel_reg(jzfb, 0x60, 0xA700); |
154 | set_panel_reg(jzfb, 0x61, 0x0001); |
155 | set_panel_reg(jzfb, 0x6A, 0x0000); |
156 | set_panel_reg(jzfb, 0x80, 0x0000); |
157 | set_panel_reg(jzfb, 0x81, 0x0000); |
158 | set_panel_reg(jzfb, 0x82, 0x0000); |
159 | set_panel_reg(jzfb, 0x83, 0x0000); |
160 | set_panel_reg(jzfb, 0x84, 0x0000); |
161 | set_panel_reg(jzfb, 0x85, 0x0000); |
162 | set_panel_reg(jzfb, 0x90, 0x0010); |
163 | set_panel_reg(jzfb, 0x92, 0x0600); |
164 | msleep(50); |
165 | set_panel_reg(jzfb, 0x07, 0x0133); |
166 | msleep(50); |
167 | send_panel_command(jzfb, 0x22); |
168 | } |
169 | |
170 | /* TODO(IGP): make sure LCD power consumption is low in these conditions */ |
171 | static void ili9325_disable(struct jzfb *jzfb) |
172 | { |
173 | /* Keep chip select disabled */ |
174 | gpio_set_value(ILI9325_GPIO_CS_N, 1); |
175 | /* Keep RESET active */ |
176 | gpio_set_value(ILI9325_GPIO_RESET_N, 0); |
177 | } |
178 | |
179 | static int ili9325_init(struct jzfb *jzfb) |
180 | { |
181 | struct device *dev = &jzfb->pdev->dev; |
182 | int ret; |
183 | |
184 | ret = gpio_request(ILI9325_GPIO_CS_N, dev_name(dev)); |
185 | if (ret) |
186 | goto err_cs; |
187 | gpio_direction_output(ILI9325_GPIO_CS_N, 1); |
188 | |
189 | ret = gpio_request(ILI9325_GPIO_RESET_N, dev_name(dev)); |
190 | if (ret) |
191 | goto err_reset; |
192 | gpio_direction_output(ILI9325_GPIO_RESET_N, 0); |
193 | |
194 | msleep(100); |
195 | return 0; |
196 | |
197 | err_reset: |
198 | gpio_free(ILI9325_GPIO_CS_N); |
199 | err_cs: |
200 | dev_err(dev, "Could not reserve GPIO pins for ILI9325 panel driver\n"); |
201 | return ret; |
202 | } |
203 | |
204 | static void ili9325_exit(struct jzfb *jzfb) |
205 | { |
206 | gpio_free(ILI9325_GPIO_CS_N); |
207 | gpio_free(ILI9325_GPIO_RESET_N); |
208 | } |
209 | |
210 | #endif |
211 | |
212 | #ifdef CONFIG_JZ_SLCD_ILI9331 |
213 | |
214 | #define ILI9331_GPIO_CS_N JZ_GPIO_PORTB(17) /* Chip select */ |
215 | #define ILI9331_GPIO_RESET_N JZ_GPIO_PORTB(18) /* LCD reset */ |
216 | |
217 | static void ili9331_enable(struct jzfb *jzfb) |
218 | { |
219 | /* RESET pulse */ |
220 | gpio_set_value(ILI9331_GPIO_RESET_N, 0); |
221 | msleep(10); |
222 | gpio_set_value(ILI9331_GPIO_RESET_N, 1); |
223 | msleep(50); |
224 | |
225 | /* Enable chip select */ |
226 | gpio_set_value(ILI9331_GPIO_CS_N, 0); |
227 | |
228 | /* Black magic */ |
229 | set_panel_reg(jzfb, 0xE7, 0x1014); |
230 | set_panel_reg(jzfb, 0x01, 0x0000); |
231 | set_panel_reg(jzfb, 0x02, 0x0200); |
232 | set_panel_reg(jzfb, 0x03, 0x1048); |
233 | set_panel_reg(jzfb, 0x08, 0x0202); |
234 | set_panel_reg(jzfb, 0x09, 0x0000); |
235 | set_panel_reg(jzfb, 0x0A, 0x0000); |
236 | set_panel_reg(jzfb, 0x0C, 0x0000); |
237 | set_panel_reg(jzfb, 0x0D, 0x0000); |
238 | set_panel_reg(jzfb, 0x0F, 0x0000); |
239 | set_panel_reg(jzfb, 0x10, 0x0000); |
240 | set_panel_reg(jzfb, 0x11, 0x0007); |
241 | set_panel_reg(jzfb, 0x12, 0x0000); |
242 | set_panel_reg(jzfb, 0x13, 0x0000); |
243 | msleep(100); |
244 | set_panel_reg(jzfb, 0x10, 0x1690); |
245 | set_panel_reg(jzfb, 0x11, 0x0224); |
246 | msleep(50); |
247 | set_panel_reg(jzfb, 0x12, 0x001F); |
248 | msleep(50); |
249 | set_panel_reg(jzfb, 0x13, 0x0500); |
250 | set_panel_reg(jzfb, 0x29, 0x000C); |
251 | set_panel_reg(jzfb, 0x2B, 0x000D); |
252 | msleep(50); |
253 | set_panel_reg(jzfb, 0x30, 0x0000); |
254 | set_panel_reg(jzfb, 0x31, 0x0106); |
255 | set_panel_reg(jzfb, 0x32, 0x0000); |
256 | set_panel_reg(jzfb, 0x35, 0x0204); |
257 | set_panel_reg(jzfb, 0x36, 0x160A); |
258 | set_panel_reg(jzfb, 0x37, 0x0707); |
259 | set_panel_reg(jzfb, 0x38, 0x0106); |
260 | set_panel_reg(jzfb, 0x39, 0x0706); |
261 | set_panel_reg(jzfb, 0x3C, 0x0402); |
262 | set_panel_reg(jzfb, 0x3D, 0x0C0F); |
263 | set_panel_reg(jzfb, 0x50, 0x0000); |
264 | set_panel_reg(jzfb, 0x51, 0x00EF); |
265 | set_panel_reg(jzfb, 0x52, 0x0000); |
266 | set_panel_reg(jzfb, 0x53, 0x013F); |
267 | set_panel_reg(jzfb, 0x20, 0x0000); |
268 | set_panel_reg(jzfb, 0x21, 0x0000); |
269 | set_panel_reg(jzfb, 0x60, 0x2700); |
270 | set_panel_reg(jzfb, 0x61, 0x0001); |
271 | set_panel_reg(jzfb, 0x6A, 0x0000); |
272 | set_panel_reg(jzfb, 0x80, 0x0000); |
273 | set_panel_reg(jzfb, 0x81, 0x0000); |
274 | set_panel_reg(jzfb, 0x82, 0x0000); |
275 | set_panel_reg(jzfb, 0x83, 0x0000); |
276 | set_panel_reg(jzfb, 0x84, 0x0000); |
277 | set_panel_reg(jzfb, 0x85, 0x0000); |
278 | set_panel_reg(jzfb, 0x20, 0x00EF); |
279 | set_panel_reg(jzfb, 0x21, 0x0190); |
280 | set_panel_reg(jzfb, 0x90, 0x0010); |
281 | set_panel_reg(jzfb, 0x92, 0x0600); |
282 | set_panel_reg(jzfb, 0x07, 0x0133); |
283 | send_panel_command(jzfb, 0x22); |
284 | } |
285 | |
286 | /* TODO(IGP): make sure LCD power consumption is low in these conditions */ |
287 | static void ili9331_disable(struct jzfb *jzfb) |
288 | { |
289 | /* Keep chip select disabled */ |
290 | gpio_set_value(ILI9331_GPIO_CS_N, 1); |
291 | /* Keep RESET active */ |
292 | gpio_set_value(ILI9331_GPIO_RESET_N, 0); |
293 | } |
294 | |
295 | static int ili9331_init(struct jzfb *jzfb) |
296 | { |
297 | struct device *dev = &jzfb->pdev->dev; |
298 | int ret; |
299 | |
300 | ret = gpio_request(ILI9331_GPIO_CS_N, dev_name(dev)); |
301 | if (ret) |
302 | goto err_cs; |
303 | gpio_direction_output(ILI9331_GPIO_CS_N, 1); |
304 | |
305 | ret = gpio_request(ILI9331_GPIO_RESET_N, dev_name(dev)); |
306 | if (ret) |
307 | goto err_reset; |
308 | gpio_direction_output(ILI9331_GPIO_RESET_N, 0); |
309 | |
310 | msleep(100); |
311 | return 0; |
312 | |
313 | err_reset: |
314 | gpio_free(ILI9331_GPIO_CS_N); |
315 | err_cs: |
316 | dev_err(dev, "Could not reserve GPIO pins for ILI9331 panel driver\n"); |
317 | return ret; |
318 | } |
319 | |
320 | static void ili9331_exit(struct jzfb *jzfb) |
321 | { |
322 | gpio_free(ILI9331_GPIO_CS_N); |
323 | gpio_free(ILI9331_GPIO_RESET_N); |
324 | } |
325 | |
326 | #endif |
327 | |
328 | #ifdef CONFIG_JZ_SLCD_ILI9338 |
329 | |
330 | static void ili9338_set_color_table(struct jzfb *jzfb) |
331 | { |
332 | unsigned int c; |
333 | struct device *dev = &jzfb->pdev->dev; |
334 | |
335 | /* Set up a custom color lookup table. |
336 | * This helps to fix the 'blueish' display on some devices. */ |
337 | send_panel_command(jzfb, 0x2d); |
338 | |
339 | for (c = 0; c < 3; c++) { |
340 | unsigned int i, n, v, s; |
341 | n = c == 1 ? 64 /* 6 bits G */ : 32 /* 5 bits R/B */; |
342 | s = jzfb->rgb[c] * (((63 << 24) - 1) / (100 * (n - 1))); |
343 | v = 0; |
344 | for (i = 0; i < n; i++, v += s) |
345 | send_panel_data(jzfb, (v >> 24) + ((v >> 23) & 1)); |
346 | } |
347 | |
348 | dev_info(dev, "ILI9338 color table initialized with R=%u G=%u B=%u\n", |
349 | jzfb->rgb[0], jzfb->rgb[1], jzfb->rgb[2]); |
350 | } |
351 | |
352 | module_param_array_named(rgb, default_slcd_rgb, uint, NULL, 0); |
353 | MODULE_PARM_DESC(rgb, "comma-separated list of three values representing the percentage of red, green and blue"); |
354 | |
355 | static ssize_t rgb_show(struct device *dev, struct device_attribute *attr, |
356 | char *buf) |
357 | { |
358 | struct jzfb *jzfb = dev_get_drvdata(dev); |
359 | return sprintf(buf, "%u,%u,%u\n", jzfb->rgb[0], |
360 | jzfb->rgb[1], jzfb->rgb[2]); |
361 | } |
362 | |
363 | static ssize_t rgb_store(struct device *dev, struct device_attribute *attr, |
364 | const char *buf, size_t n) |
365 | { |
366 | struct jzfb *jzfb = dev_get_drvdata(dev); |
367 | unsigned int rgb[3]; |
368 | |
369 | if (sscanf(buf, "%u,%u,%u", &rgb[0], &rgb[1], &rgb[2]) < 3) |
370 | return -EINVAL; |
371 | |
372 | if (rgb[0] > 100 || rgb[1] > 100 || rgb[2] > 100) |
373 | return -EINVAL; |
374 | |
375 | memcpy(jzfb->rgb, rgb, sizeof(rgb)); |
376 | ili9338_set_color_table(jzfb); |
377 | return n; |
378 | } |
379 | |
380 | static DEVICE_ATTR(rgb, 0644, rgb_show, rgb_store); |
381 | |
382 | #define ILI9338_GPIO_CS_N JZ_GPIO_PORTB(17) /* Chip select */ |
383 | #define ILI9338_GPIO_RESET_N JZ_GPIO_PORTB(18) /* LCD reset */ |
384 | |
385 | static void ili9338_enable(struct jzfb *jzfb) |
386 | { |
387 | /* RESET pulse */ |
388 | gpio_set_value(ILI9338_GPIO_RESET_N, 0); |
389 | msleep(10); |
390 | gpio_set_value(ILI9338_GPIO_RESET_N, 1); |
391 | msleep(50); |
392 | |
393 | /* Enable chip select */ |
394 | gpio_set_value(ILI9338_GPIO_CS_N, 0); |
395 | |
396 | /* Black magic */ |
397 | send_panel_command(jzfb, 0x11); |
398 | msleep(100); |
399 | |
400 | send_panel_command(jzfb, 0xCB); |
401 | send_panel_data(jzfb, 0x01); |
402 | |
403 | send_panel_command(jzfb, 0xC0); |
404 | send_panel_data(jzfb, 0x26); |
405 | send_panel_data(jzfb, 0x01); |
406 | send_panel_command(jzfb, 0xC1); |
407 | send_panel_data(jzfb, 0x10); |
408 | send_panel_command(jzfb, 0xC5); |
409 | send_panel_data(jzfb, 0x10); |
410 | send_panel_data(jzfb, 0x52); |
411 | |
412 | send_panel_command(jzfb, 0x26); |
413 | send_panel_data(jzfb, 0x01); |
414 | send_panel_command(jzfb, 0xE0); |
415 | send_panel_data(jzfb, 0x10); |
416 | send_panel_data(jzfb, 0x10); |
417 | send_panel_data(jzfb, 0x10); |
418 | send_panel_data(jzfb, 0x08); |
419 | send_panel_data(jzfb, 0x0E); |
420 | send_panel_data(jzfb, 0x06); |
421 | send_panel_data(jzfb, 0x42); |
422 | send_panel_data(jzfb, 0x28); |
423 | send_panel_data(jzfb, 0x36); |
424 | send_panel_data(jzfb, 0x03); |
425 | send_panel_data(jzfb, 0x0E); |
426 | send_panel_data(jzfb, 0x04); |
427 | send_panel_data(jzfb, 0x13); |
428 | send_panel_data(jzfb, 0x0E); |
429 | send_panel_data(jzfb, 0x0C); |
430 | send_panel_command(jzfb, 0XE1); |
431 | send_panel_data(jzfb, 0x0C); |
432 | send_panel_data(jzfb, 0x23); |
433 | send_panel_data(jzfb, 0x26); |
434 | send_panel_data(jzfb, 0x04); |
435 | send_panel_data(jzfb, 0x0C); |
436 | send_panel_data(jzfb, 0x04); |
437 | send_panel_data(jzfb, 0x39); |
438 | send_panel_data(jzfb, 0x24); |
439 | send_panel_data(jzfb, 0x4B); |
440 | send_panel_data(jzfb, 0x03); |
441 | send_panel_data(jzfb, 0x0B); |
442 | send_panel_data(jzfb, 0x0B); |
443 | send_panel_data(jzfb, 0x33); |
444 | send_panel_data(jzfb, 0x37); |
445 | send_panel_data(jzfb, 0x0F); |
446 | |
447 | send_panel_command(jzfb, 0x2a); |
448 | send_panel_data(jzfb, 0x00); |
449 | send_panel_data(jzfb, 0x00); |
450 | send_panel_data(jzfb, 0x01); |
451 | send_panel_data(jzfb, 0x3f); |
452 | |
453 | send_panel_command(jzfb, 0x2b); |
454 | send_panel_data(jzfb, 0x00); |
455 | send_panel_data(jzfb, 0x00); |
456 | send_panel_data(jzfb, 0x00); |
457 | send_panel_data(jzfb, 0xef); |
458 | |
459 | send_panel_command(jzfb, 0x36); |
460 | send_panel_data(jzfb, 0xe8); |
461 | |
462 | send_panel_command(jzfb, 0x3A); |
463 | send_panel_data(jzfb, 0x05); |
464 | |
465 | ili9338_set_color_table(jzfb); |
466 | |
467 | send_panel_command(jzfb, 0x29); |
468 | |
469 | send_panel_command(jzfb, 0x2c); |
470 | } |
471 | |
472 | /* TODO(IGP): make sure LCD power consumption is low in these conditions */ |
473 | static void ili9338_disable(struct jzfb *jzfb) |
474 | { |
475 | /* Keep chip select disabled */ |
476 | gpio_set_value(ILI9338_GPIO_CS_N, 1); |
477 | /* Keep RESET active */ |
478 | gpio_set_value(ILI9338_GPIO_RESET_N, 0); |
479 | } |
480 | |
481 | static int ili9338_init(struct jzfb *jzfb) |
482 | { |
483 | struct device *dev = &jzfb->pdev->dev; |
484 | int ret; |
485 | |
486 | ret = gpio_request(ILI9338_GPIO_CS_N, dev_name(dev)); |
487 | if (ret) |
488 | goto err_cs; |
489 | gpio_direction_output(ILI9338_GPIO_CS_N, 1); |
490 | |
491 | ret = gpio_request(ILI9338_GPIO_RESET_N, dev_name(dev)); |
492 | if (ret) |
493 | goto err_reset; |
494 | gpio_direction_output(ILI9338_GPIO_RESET_N, 0); |
495 | |
496 | memcpy(jzfb->rgb, default_slcd_rgb, sizeof(default_slcd_rgb)); |
497 | msleep(100); |
498 | |
499 | ret = device_create_file(dev, &dev_attr_rgb); |
500 | if (!ret) |
501 | return 0; |
502 | |
503 | err_reset: |
504 | gpio_free(ILI9338_GPIO_CS_N); |
505 | err_cs: |
506 | dev_err(dev, "Could not reserve GPIO pins for ILI9338 panel driver\n"); |
507 | return ret; |
508 | } |
509 | |
510 | static void ili9338_exit(struct jzfb *jzfb) |
511 | { |
512 | struct device *dev = &jzfb->pdev->dev; |
513 | device_remove_file(dev, &dev_attr_rgb); |
514 | |
515 | gpio_free(ILI9338_GPIO_CS_N); |
516 | gpio_free(ILI9338_GPIO_RESET_N); |
517 | } |
518 | |
519 | #endif |
520 | |
521 | static const struct jz_slcd_panel jz_slcd_panels[] = { |
522 | #ifdef CONFIG_JZ_SLCD_ILI9325 |
523 | { |
524 | ili9325_init, ili9325_exit, |
525 | ili9325_enable, ili9325_disable, |
526 | "ili9325", |
527 | }, |
528 | #endif |
529 | #ifdef CONFIG_JZ_SLCD_ILI9331 |
530 | { |
531 | ili9331_init, ili9331_exit, |
532 | ili9331_enable, ili9331_disable, |
533 | "ili9331", |
534 | }, |
535 | #endif |
536 | #ifdef CONFIG_JZ_SLCD_ILI9338 |
537 | { |
538 | ili9338_init, ili9338_exit, |
539 | ili9338_enable, ili9338_disable, |
540 | "ili9338", |
541 | }, |
542 | #endif |
543 | }; |
544 | |
545 | module_param_named(panel, default_slcd_panel, charp, 0); |
546 | MODULE_PARM_DESC(panel, "SLCD panel used on the device"); |
547 | |
548 | const struct jz_slcd_panel *jz_slcd_panel_from_name(const char *name) |
549 | { |
550 | unsigned int i; |
551 | for (i = 0; i < ARRAY_SIZE(jz_slcd_panels); i++) { |
552 | if (sysfs_streq(name, jz_slcd_panels[i].name)) |
553 | return &jz_slcd_panels[i]; |
554 | } |
555 | return NULL; |
556 | } |
557 | |
558 | const struct jz_slcd_panel *jz_slcd_panels_probe(struct jzfb *jzfb) |
559 | { |
560 | const struct jz_slcd_panel *panel; |
561 | if (ARRAY_SIZE(jz_slcd_panels) == 0) |
562 | return NULL; |
563 | |
564 | panel = &jz_slcd_panels[0]; |
565 | |
566 | if (default_slcd_panel) { |
567 | panel = jz_slcd_panel_from_name(default_slcd_panel); |
568 | if (!panel) { |
569 | struct device *dev = &jzfb->pdev->dev; |
570 | dev_err(dev, "Unknown SLCD panel: %s\n", |
571 | default_slcd_panel); |
572 | } |
573 | } |
574 | return panel; |
575 | } |
576 |
Branches:
ben-wpan
ben-wpan-stefan
javiroman/ks7010
jz-2.6.34
jz-2.6.34-rc5
jz-2.6.34-rc6
jz-2.6.34-rc7
jz-2.6.35
jz-2.6.36
jz-2.6.37
jz-2.6.38
jz-2.6.39
jz-3.0
jz-3.1
jz-3.11
jz-3.12
jz-3.13
jz-3.15
jz-3.16
jz-3.18-dt
jz-3.2
jz-3.3
jz-3.4
jz-3.5
jz-3.6
jz-3.6-rc2-pwm
jz-3.9
jz-3.9-clk
jz-3.9-rc8
jz47xx
jz47xx-2.6.38
master
Tags:
od-2011-09-04
od-2011-09-18
v2.6.34-rc5
v2.6.34-rc6
v2.6.34-rc7
v3.9