Commit | Line | Data |
---|---|---|
9d200153 SM |
1 | /* Copyright (c) 2009, Code Aurora Forum. All rights reserved. |
2 | * | |
3 | * This program is free software; you can redistribute it and/or modify | |
4 | * it under the terms of the GNU General Public License version 2 and | |
5 | * only version 2 as published by the Free Software Foundation. | |
6 | * | |
7 | * This program is distributed in the hope that it will be useful, | |
8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
10 | * GNU General Public License for more details. | |
11 | * | |
12 | * You should have received a copy of the GNU General Public License | |
13 | * along with this program; if not, write to the Free Software | |
14 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | |
15 | * 02110-1301, USA. | |
16 | */ | |
17 | ||
18 | #include <linux/delay.h> | |
19 | #include <linux/module.h> | |
20 | #include <mach/gpio.h> | |
21 | #include <mach/pmic.h> | |
22 | #include "msm_fb.h" | |
23 | ||
24 | #ifdef CONFIG_FB_MSM_TRY_MDDI_CATCH_LCDC_PRISM | |
25 | #include "mddihosti.h" | |
26 | #endif | |
27 | ||
28 | static int spi_cs; | |
29 | static int spi_sclk; | |
30 | static int spi_mosi; | |
31 | static int spi_miso; | |
32 | ||
33 | struct toshiba_state_type{ | |
34 | boolean disp_initialized; | |
35 | boolean display_on; | |
36 | boolean disp_powered_up; | |
37 | }; | |
38 | ||
39 | static struct toshiba_state_type toshiba_state = { 0 }; | |
40 | static struct msm_panel_common_pdata *lcdc_toshiba_pdata; | |
41 | ||
42 | static void toshiba_spi_write_byte(char dc, uint8 data) | |
43 | { | |
44 | uint32 bit; | |
45 | int bnum; | |
46 | ||
47 | gpio_set_value(spi_sclk, 0); /* clk low */ | |
48 | /* dc: 0 for command, 1 for parameter */ | |
49 | gpio_set_value(spi_mosi, dc); | |
50 | udelay(1); /* at least 20 ns */ | |
51 | gpio_set_value(spi_sclk, 1); /* clk high */ | |
52 | udelay(1); /* at least 20 ns */ | |
53 | bnum = 8; /* 8 data bits */ | |
54 | bit = 0x80; | |
55 | while (bnum) { | |
56 | gpio_set_value(spi_sclk, 0); /* clk low */ | |
57 | if (data & bit) | |
58 | gpio_set_value(spi_mosi, 1); | |
59 | else | |
60 | gpio_set_value(spi_mosi, 0); | |
61 | udelay(1); | |
62 | gpio_set_value(spi_sclk, 1); /* clk high */ | |
63 | udelay(1); | |
64 | bit >>= 1; | |
65 | bnum--; | |
66 | } | |
67 | } | |
68 | ||
69 | static void toshiba_spi_write(char cmd, uint32 data, int num) | |
70 | { | |
71 | char *bp; | |
72 | ||
73 | gpio_set_value(spi_cs, 1); /* cs high */ | |
74 | ||
75 | /* command byte first */ | |
76 | toshiba_spi_write_byte(0, cmd); | |
77 | ||
78 | /* followed by parameter bytes */ | |
79 | if (num) { | |
80 | bp = (char *)&data;; | |
81 | bp += (num - 1); | |
82 | while (num) { | |
83 | toshiba_spi_write_byte(1, *bp); | |
84 | num--; | |
85 | bp--; | |
86 | } | |
87 | } | |
88 | ||
89 | gpio_set_value(spi_cs, 0); /* cs low */ | |
90 | udelay(1); | |
91 | } | |
92 | ||
93 | void toshiba_spi_read_bytes(char cmd, uint32 *data, int num) | |
94 | { | |
95 | uint32 dbit, bits; | |
96 | int bnum; | |
97 | ||
98 | gpio_set_value(spi_cs, 1); /* cs high */ | |
99 | ||
100 | /* command byte first */ | |
101 | toshiba_spi_write_byte(0, cmd); | |
102 | ||
103 | if (num > 1) { | |
104 | /* extra dc bit */ | |
105 | gpio_set_value(spi_sclk, 0); /* clk low */ | |
106 | udelay(1); | |
107 | dbit = gpio_get_value(spi_miso);/* dc bit */ | |
108 | udelay(1); | |
109 | gpio_set_value(spi_sclk, 1); /* clk high */ | |
110 | } | |
111 | ||
112 | /* followed by data bytes */ | |
113 | bnum = num * 8; /* number of bits */ | |
114 | bits = 0; | |
115 | while (bnum) { | |
116 | bits <<= 1; | |
117 | gpio_set_value(spi_sclk, 0); /* clk low */ | |
118 | udelay(1); | |
119 | dbit = gpio_get_value(spi_miso); | |
120 | udelay(1); | |
121 | gpio_set_value(spi_sclk, 1); /* clk high */ | |
122 | bits |= dbit; | |
123 | bnum--; | |
124 | } | |
125 | ||
126 | *data = bits; | |
127 | ||
128 | udelay(1); | |
129 | gpio_set_value(spi_cs, 0); /* cs low */ | |
130 | udelay(1); | |
131 | } | |
132 | ||
133 | static void spi_pin_assign(void) | |
134 | { | |
135 | /* Setting the Default GPIO's */ | |
136 | spi_sclk = *(lcdc_toshiba_pdata->gpio_num); | |
137 | spi_cs = *(lcdc_toshiba_pdata->gpio_num + 1); | |
138 | spi_mosi = *(lcdc_toshiba_pdata->gpio_num + 2); | |
139 | spi_miso = *(lcdc_toshiba_pdata->gpio_num + 3); | |
140 | } | |
141 | ||
142 | static void toshiba_disp_powerup(void) | |
143 | { | |
144 | if (!toshiba_state.disp_powered_up && !toshiba_state.display_on) { | |
145 | /* Reset the hardware first */ | |
146 | /* Include DAC power up implementation here */ | |
147 | toshiba_state.disp_powered_up = TRUE; | |
148 | } | |
149 | } | |
150 | ||
151 | static void toshiba_disp_on(void) | |
152 | { | |
153 | uint32 data; | |
154 | ||
155 | gpio_set_value(spi_cs, 0); /* low */ | |
156 | gpio_set_value(spi_sclk, 1); /* high */ | |
157 | gpio_set_value(spi_mosi, 0); | |
158 | gpio_set_value(spi_miso, 0); | |
159 | ||
160 | if (toshiba_state.disp_powered_up && !toshiba_state.display_on) { | |
161 | toshiba_spi_write(0, 0, 0); | |
162 | mdelay(7); | |
163 | toshiba_spi_write(0, 0, 0); | |
164 | mdelay(7); | |
165 | toshiba_spi_write(0, 0, 0); | |
166 | mdelay(7); | |
167 | toshiba_spi_write(0xba, 0x11, 1); | |
168 | toshiba_spi_write(0x36, 0x00, 1); | |
169 | mdelay(1); | |
170 | toshiba_spi_write(0x3a, 0x60, 1); | |
171 | toshiba_spi_write(0xb1, 0x5d, 1); | |
172 | mdelay(1); | |
173 | toshiba_spi_write(0xb2, 0x33, 1); | |
174 | toshiba_spi_write(0xb3, 0x22, 1); | |
175 | mdelay(1); | |
176 | toshiba_spi_write(0xb4, 0x02, 1); | |
177 | toshiba_spi_write(0xb5, 0x1e, 1); /* vcs -- adjust brightness */ | |
178 | mdelay(1); | |
179 | toshiba_spi_write(0xb6, 0x27, 1); | |
180 | toshiba_spi_write(0xb7, 0x03, 1); | |
181 | mdelay(1); | |
182 | toshiba_spi_write(0xb9, 0x24, 1); | |
183 | toshiba_spi_write(0xbd, 0xa1, 1); | |
184 | mdelay(1); | |
185 | toshiba_spi_write(0xbb, 0x00, 1); | |
186 | toshiba_spi_write(0xbf, 0x01, 1); | |
187 | mdelay(1); | |
188 | toshiba_spi_write(0xbe, 0x00, 1); | |
189 | toshiba_spi_write(0xc0, 0x11, 1); | |
190 | mdelay(1); | |
191 | toshiba_spi_write(0xc1, 0x11, 1); | |
192 | toshiba_spi_write(0xc2, 0x11, 1); | |
193 | mdelay(1); | |
194 | toshiba_spi_write(0xc3, 0x3232, 2); | |
195 | mdelay(1); | |
196 | toshiba_spi_write(0xc4, 0x3232, 2); | |
197 | mdelay(1); | |
198 | toshiba_spi_write(0xc5, 0x3232, 2); | |
199 | mdelay(1); | |
200 | toshiba_spi_write(0xc6, 0x3232, 2); | |
201 | mdelay(1); | |
202 | toshiba_spi_write(0xc7, 0x6445, 2); | |
203 | mdelay(1); | |
204 | toshiba_spi_write(0xc8, 0x44, 1); | |
205 | toshiba_spi_write(0xc9, 0x52, 1); | |
206 | mdelay(1); | |
207 | toshiba_spi_write(0xca, 0x00, 1); | |
208 | mdelay(1); | |
209 | toshiba_spi_write(0xec, 0x02a4, 2); /* 0x02a4 */ | |
210 | mdelay(1); | |
211 | toshiba_spi_write(0xcf, 0x01, 1); | |
212 | mdelay(1); | |
213 | toshiba_spi_write(0xd0, 0xc003, 2); /* c003 */ | |
214 | mdelay(1); | |
215 | toshiba_spi_write(0xd1, 0x01, 1); | |
216 | mdelay(1); | |
217 | toshiba_spi_write(0xd2, 0x0028, 2); | |
218 | mdelay(1); | |
219 | toshiba_spi_write(0xd3, 0x0028, 2); | |
220 | mdelay(1); | |
221 | toshiba_spi_write(0xd4, 0x26a4, 2); | |
222 | mdelay(1); | |
223 | toshiba_spi_write(0xd5, 0x20, 1); | |
224 | mdelay(1); | |
225 | toshiba_spi_write(0xef, 0x3200, 2); | |
226 | mdelay(32); | |
227 | toshiba_spi_write(0xbc, 0x80, 1); /* wvga pass through */ | |
228 | toshiba_spi_write(0x3b, 0x00, 1); | |
229 | mdelay(1); | |
230 | toshiba_spi_write(0xb0, 0x16, 1); | |
231 | mdelay(1); | |
232 | toshiba_spi_write(0xb8, 0xfff5, 2); | |
233 | mdelay(1); | |
234 | toshiba_spi_write(0x11, 0, 0); | |
235 | mdelay(5); | |
236 | toshiba_spi_write(0x29, 0, 0); | |
237 | mdelay(5); | |
238 | toshiba_state.display_on = TRUE; | |
239 | } | |
240 | ||
241 | data = 0; | |
242 | toshiba_spi_read_bytes(0x04, &data, 3); | |
243 | printk(KERN_INFO "toshiba_disp_on: id=%x\n", data); | |
244 | ||
245 | } | |
246 | ||
247 | static int lcdc_toshiba_panel_on(struct platform_device *pdev) | |
248 | { | |
249 | if (!toshiba_state.disp_initialized) { | |
250 | /* Configure reset GPIO that drives DAC */ | |
251 | if (lcdc_toshiba_pdata->panel_config_gpio) | |
252 | lcdc_toshiba_pdata->panel_config_gpio(1); | |
253 | toshiba_disp_powerup(); | |
254 | toshiba_disp_on(); | |
255 | toshiba_state.disp_initialized = TRUE; | |
256 | } | |
257 | return 0; | |
258 | } | |
259 | ||
260 | static int lcdc_toshiba_panel_off(struct platform_device *pdev) | |
261 | { | |
262 | if (toshiba_state.disp_powered_up && toshiba_state.display_on) { | |
263 | /* Main panel power off (Deep standby in) */ | |
264 | ||
265 | toshiba_spi_write(0x28, 0, 0); /* display off */ | |
266 | mdelay(1); | |
267 | toshiba_spi_write(0xb8, 0x8002, 2); /* output control */ | |
268 | mdelay(1); | |
269 | toshiba_spi_write(0x10, 0x00, 1); /* sleep mode in */ | |
270 | mdelay(85); /* wait 85 msec */ | |
271 | toshiba_spi_write(0xb0, 0x00, 1); /* deep standby in */ | |
272 | mdelay(1); | |
273 | if (lcdc_toshiba_pdata->panel_config_gpio) | |
274 | lcdc_toshiba_pdata->panel_config_gpio(0); | |
275 | toshiba_state.display_on = FALSE; | |
276 | toshiba_state.disp_initialized = FALSE; | |
277 | } | |
278 | return 0; | |
279 | } | |
280 | ||
281 | static void lcdc_toshiba_set_backlight(struct msm_fb_data_type *mfd) | |
282 | { | |
283 | int bl_level; | |
284 | int ret = -EPERM; | |
285 | ||
286 | bl_level = mfd->bl_level; | |
287 | ret = pmic_set_led_intensity(LED_LCD, bl_level); | |
288 | ||
289 | if (ret) | |
290 | printk(KERN_WARNING "%s: can't set lcd backlight!\n", | |
291 | __func__); | |
292 | } | |
293 | ||
294 | static int __init toshiba_probe(struct platform_device *pdev) | |
295 | { | |
296 | if (pdev->id == 0) { | |
297 | lcdc_toshiba_pdata = pdev->dev.platform_data; | |
298 | spi_pin_assign(); | |
299 | return 0; | |
300 | } | |
301 | msm_fb_add_device(pdev); | |
302 | return 0; | |
303 | } | |
304 | ||
305 | static struct platform_driver this_driver = { | |
306 | .probe = toshiba_probe, | |
307 | .driver = { | |
308 | .name = "lcdc_toshiba_wvga", | |
309 | }, | |
310 | }; | |
311 | ||
312 | static struct msm_fb_panel_data toshiba_panel_data = { | |
313 | .on = lcdc_toshiba_panel_on, | |
314 | .off = lcdc_toshiba_panel_off, | |
315 | .set_backlight = lcdc_toshiba_set_backlight, | |
316 | }; | |
317 | ||
318 | static struct platform_device this_device = { | |
319 | .name = "lcdc_toshiba_wvga", | |
320 | .id = 1, | |
321 | .dev = { | |
322 | .platform_data = &toshiba_panel_data, | |
323 | } | |
324 | }; | |
325 | ||
326 | static int __init lcdc_toshiba_panel_init(void) | |
327 | { | |
328 | int ret; | |
329 | struct msm_panel_info *pinfo; | |
330 | #ifdef CONFIG_FB_MSM_TRY_MDDI_CATCH_LCDC_PRISM | |
331 | if (mddi_get_client_id() != 0) | |
332 | return 0; | |
333 | ||
334 | ret = msm_fb_detect_client("lcdc_toshiba_wvga_pt"); | |
335 | if (ret) | |
336 | return 0; | |
337 | ||
338 | #endif | |
339 | ||
340 | ret = platform_driver_register(&this_driver); | |
341 | if (ret) | |
342 | return ret; | |
343 | ||
344 | pinfo = &toshiba_panel_data.panel_info; | |
345 | pinfo->xres = 480; | |
346 | pinfo->yres = 800; | |
347 | pinfo->type = LCDC_PANEL; | |
348 | pinfo->pdest = DISPLAY_1; | |
349 | pinfo->wait_cycle = 0; | |
350 | pinfo->bpp = 18; | |
351 | pinfo->fb_num = 2; | |
352 | /* 30Mhz mdp_lcdc_pclk and mdp_lcdc_pad_pcl */ | |
353 | pinfo->clk_rate = 27648000; | |
354 | pinfo->bl_max = 15; | |
355 | pinfo->bl_min = 1; | |
356 | ||
357 | pinfo->lcdc.h_back_porch = 184; /* hsw = 8 + hbp=184 */ | |
358 | pinfo->lcdc.h_front_porch = 4; | |
359 | pinfo->lcdc.h_pulse_width = 8; | |
360 | pinfo->lcdc.v_back_porch = 2; /* vsw=1 + vbp = 2 */ | |
361 | pinfo->lcdc.v_front_porch = 3; | |
362 | pinfo->lcdc.v_pulse_width = 1; | |
363 | pinfo->lcdc.border_clr = 0; /* blk */ | |
364 | pinfo->lcdc.underflow_clr = 0xff; /* blue */ | |
365 | pinfo->lcdc.hsync_skew = 0; | |
366 | ||
367 | ret = platform_device_register(&this_device); | |
368 | if (ret) | |
369 | platform_driver_unregister(&this_driver); | |
370 | ||
371 | return ret; | |
372 | } | |
373 | ||
374 | device_initcall(lcdc_toshiba_panel_init); |