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