Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/arch/sh/boards/mach-kfr2r09/lcd_wqvga.c
15131 views
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, struct fb_info *info)
331
{
332
kfr2r09_lcd_backlight(1);
333
}
334
335
void kfr2r09_lcd_off(void *board_data)
336
{
337
kfr2r09_lcd_backlight(0);
338
}
339
340