Merge branch 'drm-intel-next' of git://git.kernel.org/pub/scm/linux/kernel/git/anholt...
[sfrench/cifs-2.6.git] / arch / sh / boards / mach-kfr2r09 / lcd_wqvga.c
1 /*
2  * KFR2R09 LCD panel support
3  *
4  * Copyright (C) 2009 Magnus Damm
5  *
6  * Register settings based on the out-of-tree t33fb.c driver
7  * Copyright (C) 2008 Lineo Solutions, Inc.
8  *
9  * This file is subject to the terms and conditions of the GNU General Public
10  * License. See the file COPYING in the main directory of this archive for
11  * more details.
12  */
13
14 #include <linux/delay.h>
15 #include <linux/err.h>
16 #include <linux/fb.h>
17 #include <linux/init.h>
18 #include <linux/kernel.h>
19 #include <linux/module.h>
20 #include <linux/gpio.h>
21 #include <video/sh_mobile_lcdc.h>
22 #include <mach/kfr2r09.h>
23 #include <cpu/sh7724.h>
24
25 /* The on-board LCD module is a Hitachi TX07D34VM0AAA. This module is made
26  * up of a 240x400 LCD hooked up to a R61517 driver IC. The driver IC is
27  * communicating with the main port of the LCDC using an 18-bit SYS interface.
28  *
29  * The device code for this LCD module is 0x01221517.
30  */
31
32 static const unsigned char data_frame_if[] = {
33         0x02, /* WEMODE: 1=cont, 0=one-shot */
34         0x00, 0x00,
35         0x00, /* EPF, DFM */
36         0x02, /* RIM[1] : 1 (18bpp) */
37 };
38
39 static const unsigned char data_panel[] = {
40         0x0b,
41         0x63, /* 400 lines */
42         0x04, 0x00, 0x00, 0x04, 0x11, 0x00, 0x00,
43 };
44
45 static const unsigned char data_timing[] = {
46         0x00, 0x00, 0x13, 0x08, 0x08,
47 };
48
49 static const unsigned char data_timing_src[] = {
50         0x11, 0x01, 0x00, 0x01,
51 };
52
53 static const unsigned char data_gamma[] = {
54         0x01, 0x02, 0x08, 0x23, 0x03, 0x0c, 0x00, 0x06, 0x00, 0x00,
55         0x01, 0x00, 0x0c, 0x23, 0x03, 0x08, 0x02, 0x06, 0x00, 0x00,
56 };
57
58 static const unsigned char data_power[] = {
59         0x07, 0xc5, 0xdc, 0x02, 0x33, 0x0a,
60 };
61
62 static unsigned long read_reg(void *sohandle,
63                               struct sh_mobile_lcdc_sys_bus_ops *so)
64 {
65         return so->read_data(sohandle);
66 }
67
68 static void write_reg(void *sohandle,
69                       struct sh_mobile_lcdc_sys_bus_ops *so,
70                       int i, unsigned long v)
71 {
72         if (i)
73                 so->write_data(sohandle, v); /* PTH4/LCDRS High [param, 17:0] */
74         else
75                 so->write_index(sohandle, v); /* PTH4/LCDRS Low [cmd, 7:0] */
76 }
77
78 static void write_data(void *sohandle,
79                        struct sh_mobile_lcdc_sys_bus_ops *so,
80                        unsigned char const *data, int no_data)
81 {
82         int i;
83
84         for (i = 0; i < no_data; i++)
85                 write_reg(sohandle, so, 1, data[i]);
86 }
87
88 static unsigned long read_device_code(void *sohandle,
89                                       struct sh_mobile_lcdc_sys_bus_ops *so)
90 {
91         unsigned long device_code;
92
93         /* access protect OFF */
94         write_reg(sohandle, so, 0, 0xb0);
95         write_reg(sohandle, so, 1, 0x00);
96
97         /* deep standby OFF */
98         write_reg(sohandle, so, 0, 0xb1);
99         write_reg(sohandle, so, 1, 0x00);
100
101         /* device code command */
102         write_reg(sohandle, so, 0, 0xbf);
103         mdelay(50);
104
105         /* dummy read */
106         read_reg(sohandle, so);
107
108         /* read device code */
109         device_code = ((read_reg(sohandle, so) & 0xff) << 24);
110         device_code |= ((read_reg(sohandle, so) & 0xff) << 16);
111         device_code |= ((read_reg(sohandle, so) & 0xff) << 8);
112         device_code |= (read_reg(sohandle, so) & 0xff);
113
114         return device_code;
115 }
116
117 static void write_memory_start(void *sohandle,
118                                struct sh_mobile_lcdc_sys_bus_ops *so)
119 {
120         write_reg(sohandle, so, 0, 0x2c);
121 }
122
123 static void clear_memory(void *sohandle,
124                          struct sh_mobile_lcdc_sys_bus_ops *so)
125 {
126         int i;
127
128         /* write start */
129         write_memory_start(sohandle, so);
130
131         /* paint it black */
132         for (i = 0; i < (240 * 400); i++)
133                 write_reg(sohandle, so, 1, 0x00);
134 }
135
136 static void display_on(void *sohandle,
137                        struct sh_mobile_lcdc_sys_bus_ops *so)
138 {
139         /* access protect off */
140         write_reg(sohandle, so, 0, 0xb0);
141         write_reg(sohandle, so, 1, 0x00);
142
143         /* exit deep standby mode */
144         write_reg(sohandle, so, 0, 0xb1);
145         write_reg(sohandle, so, 1, 0x00);
146
147         /* frame memory I/F */
148         write_reg(sohandle, so, 0, 0xb3);
149         write_data(sohandle, so, data_frame_if, ARRAY_SIZE(data_frame_if));
150
151         /* display mode and frame memory write mode */
152         write_reg(sohandle, so, 0, 0xb4);
153         write_reg(sohandle, so, 1, 0x00); /* DBI, internal clock */
154
155         /* panel */
156         write_reg(sohandle, so, 0, 0xc0);
157         write_data(sohandle, so, data_panel, ARRAY_SIZE(data_panel));
158
159         /* timing (normal) */
160         write_reg(sohandle, so, 0, 0xc1);
161         write_data(sohandle, so, data_timing, ARRAY_SIZE(data_timing));
162
163         /* timing (partial) */
164         write_reg(sohandle, so, 0, 0xc2);
165         write_data(sohandle, so, data_timing, ARRAY_SIZE(data_timing));
166
167         /* timing (idle) */
168         write_reg(sohandle, so, 0, 0xc3);
169         write_data(sohandle, so, data_timing, ARRAY_SIZE(data_timing));
170
171         /* timing (source/VCOM/gate driving) */
172         write_reg(sohandle, so, 0, 0xc4);
173         write_data(sohandle, so, data_timing_src, ARRAY_SIZE(data_timing_src));
174
175         /* gamma (red) */
176         write_reg(sohandle, so, 0, 0xc8);
177         write_data(sohandle, so, data_gamma, ARRAY_SIZE(data_gamma));
178
179         /* gamma (green) */
180         write_reg(sohandle, so, 0, 0xc9);
181         write_data(sohandle, so, data_gamma, ARRAY_SIZE(data_gamma));
182
183         /* gamma (blue) */
184         write_reg(sohandle, so, 0, 0xca);
185         write_data(sohandle, so, data_gamma, ARRAY_SIZE(data_gamma));
186
187         /* power (common) */
188         write_reg(sohandle, so, 0, 0xd0);
189         write_data(sohandle, so, data_power, ARRAY_SIZE(data_power));
190
191         /* VCOM */
192         write_reg(sohandle, so, 0, 0xd1);
193         write_reg(sohandle, so, 1, 0x00);
194         write_reg(sohandle, so, 1, 0x0f);
195         write_reg(sohandle, so, 1, 0x02);
196
197         /* power (normal) */
198         write_reg(sohandle, so, 0, 0xd2);
199         write_reg(sohandle, so, 1, 0x63);
200         write_reg(sohandle, so, 1, 0x24);
201
202         /* power (partial) */
203         write_reg(sohandle, so, 0, 0xd3);
204         write_reg(sohandle, so, 1, 0x63);
205         write_reg(sohandle, so, 1, 0x24);
206
207         /* power (idle) */
208         write_reg(sohandle, so, 0, 0xd4);
209         write_reg(sohandle, so, 1, 0x63);
210         write_reg(sohandle, so, 1, 0x24);
211
212         write_reg(sohandle, so, 0, 0xd8);
213         write_reg(sohandle, so, 1, 0x77);
214         write_reg(sohandle, so, 1, 0x77);
215
216         /* TE signal */
217         write_reg(sohandle, so, 0, 0x35);
218         write_reg(sohandle, so, 1, 0x00);
219
220         /* TE signal line */
221         write_reg(sohandle, so, 0, 0x44);
222         write_reg(sohandle, so, 1, 0x00);
223         write_reg(sohandle, so, 1, 0x00);
224
225         /* column address */
226         write_reg(sohandle, so, 0, 0x2a);
227         write_reg(sohandle, so, 1, 0x00);
228         write_reg(sohandle, so, 1, 0x00);
229         write_reg(sohandle, so, 1, 0x00);
230         write_reg(sohandle, so, 1, 0xef);
231
232         /* page address */
233         write_reg(sohandle, so, 0, 0x2b);
234         write_reg(sohandle, so, 1, 0x00);
235         write_reg(sohandle, so, 1, 0x00);
236         write_reg(sohandle, so, 1, 0x01);
237         write_reg(sohandle, so, 1, 0x8f);
238
239         /* exit sleep mode */
240         write_reg(sohandle, so, 0, 0x11);
241
242         mdelay(120);
243
244         /* clear vram */
245         clear_memory(sohandle, so);
246
247         /* display ON */
248         write_reg(sohandle, so, 0, 0x29);
249         mdelay(1);
250
251         write_memory_start(sohandle, so);
252 }
253
254 int kfr2r09_lcd_setup(void *board_data, void *sohandle,
255                       struct sh_mobile_lcdc_sys_bus_ops *so)
256 {
257         /* power on */
258         gpio_set_value(GPIO_PTF4, 0);  /* PROTECT/ -> L */
259         gpio_set_value(GPIO_PTE4, 0);  /* LCD_RST/ -> L */
260         gpio_set_value(GPIO_PTF4, 1);  /* PROTECT/ -> H */
261         udelay(1100);
262         gpio_set_value(GPIO_PTE4, 1);  /* LCD_RST/ -> H */
263         udelay(10);
264         gpio_set_value(GPIO_PTF4, 0);  /* PROTECT/ -> L */
265         mdelay(20);
266
267         if (read_device_code(sohandle, so) != 0x01221517)
268                 return -ENODEV;
269
270         pr_info("KFR2R09 WQVGA LCD Module detected.\n");
271
272         display_on(sohandle, so);
273         return 0;
274 }
275
276 void kfr2r09_lcd_start(void *board_data, void *sohandle,
277                        struct sh_mobile_lcdc_sys_bus_ops *so)
278 {
279         write_memory_start(sohandle, so);
280 }
281
282 #define CTRL_CKSW       0x10
283 #define CTRL_C10        0x20
284 #define CTRL_CPSW       0x80
285 #define MAIN_MLED4      0x40
286 #define MAIN_MSW        0x80
287
288 static int kfr2r09_lcd_backlight(int on)
289 {
290         struct i2c_adapter *a;
291         struct i2c_msg msg;
292         unsigned char buf[2];
293         int ret;
294
295         a = i2c_get_adapter(0);
296         if (!a)
297                 return -ENODEV;
298
299         buf[0] = 0x00;
300         if (on)
301                 buf[1] = CTRL_CPSW | CTRL_C10 | CTRL_CKSW;
302         else
303                 buf[1] = 0;
304
305         msg.addr = 0x75;
306         msg.buf = buf;
307         msg.len = 2;
308         msg.flags = 0;
309         ret = i2c_transfer(a, &msg, 1);
310         if (ret != 1)
311                 return -ENODEV;
312
313         buf[0] = 0x01;
314         if (on)
315                 buf[1] = MAIN_MSW | MAIN_MLED4 | 0x0c;
316         else
317                 buf[1] = 0;
318
319         msg.addr = 0x75;
320         msg.buf = buf;
321         msg.len = 2;
322         msg.flags = 0;
323         ret = i2c_transfer(a, &msg, 1);
324         if (ret != 1)
325                 return -ENODEV;
326
327         return 0;
328 }
329
330 void kfr2r09_lcd_on(void *board_data)
331 {
332         kfr2r09_lcd_backlight(1);
333 }
334
335 void kfr2r09_lcd_off(void *board_data)
336 {
337         kfr2r09_lcd_backlight(0);
338 }