blob: a2060f09dc4cd4ed10fbb677d861addbed71d293 [file] [log] [blame]
Taniya Dasd8930342011-08-23 18:47:05 +05301/* Copyright (c) 2011, 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 */
13
14#include "msm_fb.h"
15#include "mipi_dsi.h"
16#include "mipi_truly.h"
17
18static struct msm_panel_common_pdata *mipi_truly_pdata;
19static struct dsi_buf truly_tx_buf;
20static struct dsi_buf truly_rx_buf;
21
22#define TRULY_CMD_DELAY 0
23#define TRULY_SLEEP_OFF_DELAY 150
24#define TRULY_DISPLAY_ON_DELAY 150
25#define GPIO_TRULY_LCD_RESET 129
26
27static int prev_bl = 17;
28
29static char extend_cmd_enable[4] = {0xB9, 0xFF, 0x83, 0x69};
30static char display_setting[16] = {
31 0xB2, 0x00, 0x23, 0x62,
32 0x62, 0x70, 0x00, 0xFF,
33 0x00, 0x00, 0x00, 0x00,
34 0x03, 0x03, 0x00, 0x01,
35};
36static char wave_cycle_setting[6] = {0xB4, 0x00, 0x1D, 0x5F, 0x0E, 0x06};
37static char gip_setting[27] = {
38 0xD5, 0x00, 0x04, 0x03,
39 0x00, 0x01, 0x05, 0x1C,
40 0x70, 0x01, 0x03, 0x00,
41 0x00, 0x40, 0x06, 0x51,
42 0x07, 0x00, 0x00, 0x41,
43 0x06, 0x50, 0x07, 0x07,
44 0x0F, 0x04, 0x00,
45};
46static char power_setting[20] = {
47 0xB1, 0x01, 0x00, 0x34,
48 0x06, 0x00, 0x0F, 0x0F,
49 0x2A, 0x32, 0x3F, 0x3F,
50 0x07, 0x3A, 0x01, 0xE6,
51 0xE6, 0xE6, 0xE6, 0xE6,
52};
53static char vcom_setting[3] = {0xB6, 0x56, 0x56};
54static char pannel_setting[2] = {0xCC, 0x02};
55static char gamma_setting[35] = {
56 0xE0, 0x00, 0x1D, 0x22,
57 0x38, 0x3D, 0x3F, 0x2E,
58 0x4A, 0x06, 0x0D, 0x0F,
59 0x13, 0x15, 0x13, 0x16,
60 0x10, 0x19, 0x00, 0x1D,
61 0x22, 0x38, 0x3D, 0x3F,
62 0x2E, 0x4A, 0x06, 0x0D,
63 0x0F, 0x13, 0x15, 0x13,
64 0x16, 0x10, 0x19,
65};
66static char mipi_setting[14] = {
67 0xBA, 0x00, 0xA0, 0xC6,
68 0x00, 0x0A, 0x00, 0x10,
69 0x30, 0x6F, 0x02, 0x11,
70 0x18, 0x40,
71};
72static char exit_sleep[2] = {0x11, 0x00};
73static char display_on[2] = {0x29, 0x00};
74static char display_off[2] = {0x28, 0x00};
75static char enter_sleep[2] = {0x10, 0x00};
76
77static struct dsi_cmd_desc truly_display_off_cmds[] = {
78 {DTYPE_DCS_WRITE, 1, 0, 0, 10, sizeof(display_off), display_off},
79 {DTYPE_DCS_WRITE, 1, 0, 0, 120, sizeof(enter_sleep), enter_sleep}
80};
81
82static struct dsi_cmd_desc truly_display_on_cmds[] = {
83 {DTYPE_GEN_LWRITE, 1, 0, 0, TRULY_CMD_DELAY,
84 sizeof(extend_cmd_enable), extend_cmd_enable},
85 {DTYPE_GEN_LWRITE, 1, 0, 0, TRULY_CMD_DELAY,
86 sizeof(display_setting), display_setting},
87 {DTYPE_GEN_LWRITE, 1, 0, 0, TRULY_CMD_DELAY,
88 sizeof(wave_cycle_setting), wave_cycle_setting},
89 {DTYPE_GEN_LWRITE, 1, 0, 0, TRULY_CMD_DELAY,
90 sizeof(gip_setting), gip_setting},
91 {DTYPE_GEN_LWRITE, 1, 0, 0, TRULY_CMD_DELAY,
92 sizeof(power_setting), power_setting},
93 {DTYPE_GEN_LWRITE, 1, 0, 0, TRULY_CMD_DELAY,
94 sizeof(vcom_setting), vcom_setting},
95 {DTYPE_GEN_LWRITE, 1, 0, 0, TRULY_CMD_DELAY,
96 sizeof(pannel_setting), pannel_setting},
97 {DTYPE_GEN_LWRITE, 1, 0, 0, TRULY_CMD_DELAY,
98 sizeof(gamma_setting), gamma_setting},
99 {DTYPE_GEN_LWRITE, 1, 0, 0, TRULY_CMD_DELAY,
100 sizeof(mipi_setting), mipi_setting},
101 {DTYPE_DCS_WRITE, 1, 0, 0, TRULY_SLEEP_OFF_DELAY,
102 sizeof(exit_sleep), exit_sleep},
103 {DTYPE_DCS_WRITE, 1, 0, 0, TRULY_DISPLAY_ON_DELAY,
104 sizeof(display_on), display_on},
105};
106
107static int mipi_truly_lcd_on(struct platform_device *pdev)
108{
109 struct msm_fb_data_type *mfd;
110
111 mfd = platform_get_drvdata(pdev);
112
113 if (!mfd)
114 return -ENODEV;
115 if (mfd->key != MFD_KEY)
116 return -EINVAL;
117
118 msleep(20);
119 mipi_dsi_cmds_tx(mfd, &truly_tx_buf, truly_display_on_cmds,
120 ARRAY_SIZE(truly_display_on_cmds));
121
122 return 0;
123}
124
125static int mipi_truly_lcd_off(struct platform_device *pdev)
126{
127 struct msm_fb_data_type *mfd;
128
129 mfd = platform_get_drvdata(pdev);
130
131 if (!mfd)
132 return -ENODEV;
133 if (mfd->key != MFD_KEY)
134 return -EINVAL;
135
136 mipi_dsi_cmds_tx(mfd, &truly_tx_buf, truly_display_off_cmds,
137 ARRAY_SIZE(truly_display_off_cmds));
138
139 return 0;
140}
141
142#define BL_LEVEL 17
143static void mipi_truly_set_backlight(struct msm_fb_data_type *mfd)
144{
145 int step = 0, i = 0;
146 int bl_level = mfd->bl_level;
147
148 /* real backlight level, 1 - max, 16 - min, 17 - off */
149 bl_level = BL_LEVEL - bl_level;
150
151 if (bl_level > prev_bl) {
152 step = bl_level - prev_bl;
153 if (bl_level == BL_LEVEL)
154 step--;
155 } else if (bl_level < prev_bl) {
156 step = bl_level + 16 - prev_bl;
157 } else {
158 pr_debug("%s: no change\n", __func__);
159 return;
160 }
161
162 if (bl_level == BL_LEVEL) {
163 /* turn off backlight */
164 mipi_truly_pdata->pmic_backlight(0);
165 } else {
166 if (prev_bl == BL_LEVEL) {
167 /* turn on backlight */
168 mipi_truly_pdata->pmic_backlight(1);
169 udelay(30);
170 }
171 /* adjust backlight level */
172 for (i = 0; i < step; i++) {
173 mipi_truly_pdata->pmic_backlight(0);
174 udelay(1);
175 mipi_truly_pdata->pmic_backlight(1);
176 udelay(1);
177 }
178 }
179 msleep(20);
180 prev_bl = bl_level;
181
182 return;
183}
184
185static int __devinit mipi_truly_lcd_probe(struct platform_device *pdev)
186{
187 if (pdev->id == 0) {
188 mipi_truly_pdata = pdev->dev.platform_data;
189 return 0;
190 }
191
192 msm_fb_add_device(pdev);
193
194 return 0;
195}
196
197static struct platform_driver this_driver = {
198 .probe = mipi_truly_lcd_probe,
199 .driver = {
200 .name = "mipi_truly",
201 },
202};
203
204static struct msm_fb_panel_data truly_panel_data = {
205 .on = mipi_truly_lcd_on,
206 .off = mipi_truly_lcd_off,
207 .set_backlight = mipi_truly_set_backlight,
208};
209
210static int ch_used[3];
211
212int mipi_truly_device_register(struct msm_panel_info *pinfo,
213 u32 channel, u32 panel)
214{
215 struct platform_device *pdev = NULL;
216 int ret;
217
218 if ((channel >= 3) || ch_used[channel])
219 return -ENODEV;
220
221 ch_used[channel] = TRUE;
222
223 pdev = platform_device_alloc("mipi_truly", (panel << 8)|channel);
224
225 if (!pdev)
226 return -ENOMEM;
227
228 truly_panel_data.panel_info = *pinfo;
229
230 ret = platform_device_add_data(pdev, &truly_panel_data,
231 sizeof(truly_panel_data));
232 if (ret) {
233 pr_err("%s: platform_device_add_data failed!\n", __func__);
234 goto err_device_put;
235 }
236
237 ret = platform_device_add(pdev);
238
239 if (ret) {
240 pr_err("%s: platform_device_register failed!\n", __func__);
241 goto err_device_put;
242 }
243
244 return 0;
245
246err_device_put:
247 platform_device_put(pdev);
248 return ret;
249}
250
251static int __init mipi_truly_lcd_init(void)
252{
253 mipi_dsi_buf_alloc(&truly_tx_buf, DSI_BUF_SIZE);
254 mipi_dsi_buf_alloc(&truly_rx_buf, DSI_BUF_SIZE);
255
256 return platform_driver_register(&this_driver);
257}
258
259module_init(mipi_truly_lcd_init);