diff options
Diffstat (limited to 'drivers/video/fbdev/exynos/s6e8ax0.c')
-rw-r--r-- | drivers/video/fbdev/exynos/s6e8ax0.c | 898 |
1 files changed, 898 insertions, 0 deletions
diff --git a/drivers/video/fbdev/exynos/s6e8ax0.c b/drivers/video/fbdev/exynos/s6e8ax0.c new file mode 100644 index 000000000000..29e70ed3f154 --- /dev/null +++ b/drivers/video/fbdev/exynos/s6e8ax0.c | |||
@@ -0,0 +1,898 @@ | |||
1 | /* linux/drivers/video/exynos/s6e8ax0.c | ||
2 | * | ||
3 | * MIPI-DSI based s6e8ax0 AMOLED lcd 4.65 inch panel driver. | ||
4 | * | ||
5 | * Inki Dae, <inki.dae@samsung.com> | ||
6 | * Donghwa Lee, <dh09.lee@samsung.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | |||
13 | #include <linux/module.h> | ||
14 | #include <linux/kernel.h> | ||
15 | #include <linux/errno.h> | ||
16 | #include <linux/mutex.h> | ||
17 | #include <linux/wait.h> | ||
18 | #include <linux/ctype.h> | ||
19 | #include <linux/io.h> | ||
20 | #include <linux/delay.h> | ||
21 | #include <linux/irq.h> | ||
22 | #include <linux/interrupt.h> | ||
23 | #include <linux/lcd.h> | ||
24 | #include <linux/fb.h> | ||
25 | #include <linux/backlight.h> | ||
26 | #include <linux/regulator/consumer.h> | ||
27 | |||
28 | #include <video/mipi_display.h> | ||
29 | #include <video/exynos_mipi_dsim.h> | ||
30 | |||
31 | #define LDI_MTP_LENGTH 24 | ||
32 | #define DSIM_PM_STABLE_TIME 10 | ||
33 | #define MIN_BRIGHTNESS 0 | ||
34 | #define MAX_BRIGHTNESS 24 | ||
35 | #define GAMMA_TABLE_COUNT 26 | ||
36 | |||
37 | #define POWER_IS_ON(pwr) ((pwr) == FB_BLANK_UNBLANK) | ||
38 | #define POWER_IS_OFF(pwr) ((pwr) == FB_BLANK_POWERDOWN) | ||
39 | #define POWER_IS_NRM(pwr) ((pwr) == FB_BLANK_NORMAL) | ||
40 | |||
41 | #define lcd_to_master(a) (a->dsim_dev->master) | ||
42 | #define lcd_to_master_ops(a) ((lcd_to_master(a))->master_ops) | ||
43 | |||
44 | enum { | ||
45 | DSIM_NONE_STATE = 0, | ||
46 | DSIM_RESUME_COMPLETE = 1, | ||
47 | DSIM_FRAME_DONE = 2, | ||
48 | }; | ||
49 | |||
50 | struct s6e8ax0 { | ||
51 | struct device *dev; | ||
52 | unsigned int power; | ||
53 | unsigned int id; | ||
54 | unsigned int gamma; | ||
55 | unsigned int acl_enable; | ||
56 | unsigned int cur_acl; | ||
57 | |||
58 | struct lcd_device *ld; | ||
59 | struct backlight_device *bd; | ||
60 | |||
61 | struct mipi_dsim_lcd_device *dsim_dev; | ||
62 | struct lcd_platform_data *ddi_pd; | ||
63 | struct mutex lock; | ||
64 | bool enabled; | ||
65 | }; | ||
66 | |||
67 | |||
68 | static struct regulator_bulk_data supplies[] = { | ||
69 | { .supply = "vdd3", }, | ||
70 | { .supply = "vci", }, | ||
71 | }; | ||
72 | |||
73 | static void s6e8ax0_regulator_enable(struct s6e8ax0 *lcd) | ||
74 | { | ||
75 | int ret = 0; | ||
76 | struct lcd_platform_data *pd = NULL; | ||
77 | |||
78 | pd = lcd->ddi_pd; | ||
79 | mutex_lock(&lcd->lock); | ||
80 | if (!lcd->enabled) { | ||
81 | ret = regulator_bulk_enable(ARRAY_SIZE(supplies), supplies); | ||
82 | if (ret) | ||
83 | goto out; | ||
84 | |||
85 | lcd->enabled = true; | ||
86 | } | ||
87 | msleep(pd->power_on_delay); | ||
88 | out: | ||
89 | mutex_unlock(&lcd->lock); | ||
90 | } | ||
91 | |||
92 | static void s6e8ax0_regulator_disable(struct s6e8ax0 *lcd) | ||
93 | { | ||
94 | int ret = 0; | ||
95 | |||
96 | mutex_lock(&lcd->lock); | ||
97 | if (lcd->enabled) { | ||
98 | ret = regulator_bulk_disable(ARRAY_SIZE(supplies), supplies); | ||
99 | if (ret) | ||
100 | goto out; | ||
101 | |||
102 | lcd->enabled = false; | ||
103 | } | ||
104 | out: | ||
105 | mutex_unlock(&lcd->lock); | ||
106 | } | ||
107 | |||
108 | static const unsigned char s6e8ax0_22_gamma_30[] = { | ||
109 | 0xfa, 0x01, 0x60, 0x10, 0x60, 0xf5, 0x00, 0xff, 0xad, 0xaf, | ||
110 | 0xbA, 0xc3, 0xd8, 0xc5, 0x9f, 0xc6, 0x9e, 0xc1, 0xdc, 0xc0, | ||
111 | 0x00, 0x61, 0x00, 0x5a, 0x00, 0x74, | ||
112 | }; | ||
113 | |||
114 | static const unsigned char s6e8ax0_22_gamma_50[] = { | ||
115 | 0xfa, 0x01, 0x60, 0x10, 0x60, 0xe8, 0x1f, 0xf7, 0xad, 0xc0, | ||
116 | 0xb5, 0xc4, 0xdc, 0xc4, 0x9e, 0xc6, 0x9c, 0xbb, 0xd8, 0xbb, | ||
117 | 0x00, 0x70, 0x00, 0x68, 0x00, 0x86, | ||
118 | }; | ||
119 | |||
120 | static const unsigned char s6e8ax0_22_gamma_60[] = { | ||
121 | 0xfa, 0x01, 0x60, 0x10, 0x60, 0xde, 0x1f, 0xef, 0xad, 0xc4, | ||
122 | 0xb3, 0xc3, 0xdd, 0xc4, 0x9e, 0xc6, 0x9c, 0xbc, 0xd6, 0xba, | ||
123 | 0x00, 0x75, 0x00, 0x6e, 0x00, 0x8d, | ||
124 | }; | ||
125 | |||
126 | static const unsigned char s6e8ax0_22_gamma_70[] = { | ||
127 | 0xfa, 0x01, 0x60, 0x10, 0x60, 0xd8, 0x1f, 0xe7, 0xaf, 0xc8, | ||
128 | 0xb4, 0xc4, 0xdd, 0xc3, 0x9d, 0xc6, 0x9c, 0xbb, 0xd6, 0xb9, | ||
129 | 0x00, 0x7a, 0x00, 0x72, 0x00, 0x93, | ||
130 | }; | ||
131 | |||
132 | static const unsigned char s6e8ax0_22_gamma_80[] = { | ||
133 | 0xfa, 0x01, 0x60, 0x10, 0x60, 0xc9, 0x1f, 0xde, 0xae, 0xc9, | ||
134 | 0xb1, 0xc3, 0xdd, 0xc2, 0x9d, 0xc5, 0x9b, 0xbc, 0xd6, 0xbb, | ||
135 | 0x00, 0x7f, 0x00, 0x77, 0x00, 0x99, | ||
136 | }; | ||
137 | |||
138 | static const unsigned char s6e8ax0_22_gamma_90[] = { | ||
139 | 0xfa, 0x01, 0x60, 0x10, 0x60, 0xc7, 0x1f, 0xd9, 0xb0, 0xcc, | ||
140 | 0xb2, 0xc3, 0xdc, 0xc1, 0x9c, 0xc6, 0x9c, 0xbc, 0xd4, 0xb9, | ||
141 | 0x00, 0x83, 0x00, 0x7b, 0x00, 0x9e, | ||
142 | }; | ||
143 | |||
144 | static const unsigned char s6e8ax0_22_gamma_100[] = { | ||
145 | 0xfa, 0x01, 0x60, 0x10, 0x60, 0xbd, 0x80, 0xcd, 0xba, 0xce, | ||
146 | 0xb3, 0xc4, 0xde, 0xc3, 0x9c, 0xc4, 0x9, 0xb8, 0xd3, 0xb6, | ||
147 | 0x00, 0x88, 0x00, 0x80, 0x00, 0xa5, | ||
148 | }; | ||
149 | |||
150 | static const unsigned char s6e8ax0_22_gamma_120[] = { | ||
151 | 0xfa, 0x01, 0x60, 0x10, 0x60, 0xb9, 0x95, 0xc8, 0xb1, 0xcf, | ||
152 | 0xb2, 0xc6, 0xdf, 0xc5, 0x9b, 0xc3, 0x99, 0xb6, 0xd2, 0xb6, | ||
153 | 0x00, 0x8f, 0x00, 0x86, 0x00, 0xac, | ||
154 | }; | ||
155 | |||
156 | static const unsigned char s6e8ax0_22_gamma_130[] = { | ||
157 | 0xfa, 0x01, 0x60, 0x10, 0x60, 0xb7, 0xa0, 0xc7, 0xb1, 0xd0, | ||
158 | 0xb2, 0xc4, 0xdd, 0xc3, 0x9a, 0xc3, 0x98, 0xb6, 0xd0, 0xb4, | ||
159 | 0x00, 0x92, 0x00, 0x8a, 0x00, 0xb1, | ||
160 | }; | ||
161 | |||
162 | static const unsigned char s6e8ax0_22_gamma_140[] = { | ||
163 | 0xfa, 0x01, 0x60, 0x10, 0x60, 0xb7, 0xa0, 0xc5, 0xb2, 0xd0, | ||
164 | 0xb3, 0xc3, 0xde, 0xc3, 0x9b, 0xc2, 0x98, 0xb6, 0xd0, 0xb4, | ||
165 | 0x00, 0x95, 0x00, 0x8d, 0x00, 0xb5, | ||
166 | }; | ||
167 | |||
168 | static const unsigned char s6e8ax0_22_gamma_150[] = { | ||
169 | 0xfa, 0x01, 0x60, 0x10, 0x60, 0xb3, 0xa0, 0xc2, 0xb2, 0xd0, | ||
170 | 0xb2, 0xc1, 0xdd, 0xc2, 0x9b, 0xc2, 0x98, 0xb4, 0xcf, 0xb1, | ||
171 | 0x00, 0x99, 0x00, 0x90, 0x00, 0xba, | ||
172 | }; | ||
173 | |||
174 | static const unsigned char s6e8ax0_22_gamma_160[] = { | ||
175 | 0xfa, 0x01, 0x60, 0x10, 0x60, 0xaf, 0xa5, 0xbf, 0xb0, 0xd0, | ||
176 | 0xb1, 0xc3, 0xde, 0xc2, 0x99, 0xc1, 0x97, 0xb4, 0xce, 0xb1, | ||
177 | 0x00, 0x9c, 0x00, 0x93, 0x00, 0xbe, | ||
178 | }; | ||
179 | |||
180 | static const unsigned char s6e8ax0_22_gamma_170[] = { | ||
181 | 0xfa, 0x01, 0x60, 0x10, 0x60, 0xaf, 0xb5, 0xbf, 0xb1, 0xd1, | ||
182 | 0xb1, 0xc3, 0xde, 0xc3, 0x99, 0xc0, 0x96, 0xb4, 0xce, 0xb1, | ||
183 | 0x00, 0x9f, 0x00, 0x96, 0x00, 0xc2, | ||
184 | }; | ||
185 | |||
186 | static const unsigned char s6e8ax0_22_gamma_180[] = { | ||
187 | 0xfa, 0x01, 0x60, 0x10, 0x60, 0xaf, 0xb7, 0xbe, 0xb3, 0xd2, | ||
188 | 0xb3, 0xc3, 0xde, 0xc2, 0x97, 0xbf, 0x95, 0xb4, 0xcd, 0xb1, | ||
189 | 0x00, 0xa2, 0x00, 0x99, 0x00, 0xc5, | ||
190 | }; | ||
191 | |||
192 | static const unsigned char s6e8ax0_22_gamma_190[] = { | ||
193 | 0xfa, 0x01, 0x60, 0x10, 0x60, 0xaf, 0xb9, 0xbe, 0xb2, 0xd2, | ||
194 | 0xb2, 0xc3, 0xdd, 0xc3, 0x98, 0xbf, 0x95, 0xb2, 0xcc, 0xaf, | ||
195 | 0x00, 0xa5, 0x00, 0x9c, 0x00, 0xc9, | ||
196 | }; | ||
197 | |||
198 | static const unsigned char s6e8ax0_22_gamma_200[] = { | ||
199 | 0xfa, 0x01, 0x60, 0x10, 0x60, 0xaf, 0xb9, 0xbc, 0xb2, 0xd2, | ||
200 | 0xb1, 0xc4, 0xdd, 0xc3, 0x97, 0xbe, 0x95, 0xb1, 0xcb, 0xae, | ||
201 | 0x00, 0xa8, 0x00, 0x9f, 0x00, 0xcd, | ||
202 | }; | ||
203 | |||
204 | static const unsigned char s6e8ax0_22_gamma_210[] = { | ||
205 | 0xfa, 0x01, 0x60, 0x10, 0x60, 0xb1, 0xc1, 0xbd, 0xb1, 0xd1, | ||
206 | 0xb1, 0xc2, 0xde, 0xc2, 0x97, 0xbe, 0x94, 0xB0, 0xc9, 0xad, | ||
207 | 0x00, 0xae, 0x00, 0xa4, 0x00, 0xd4, | ||
208 | }; | ||
209 | |||
210 | static const unsigned char s6e8ax0_22_gamma_220[] = { | ||
211 | 0xfa, 0x01, 0x60, 0x10, 0x60, 0xb1, 0xc7, 0xbd, 0xb1, 0xd1, | ||
212 | 0xb1, 0xc2, 0xdd, 0xc2, 0x97, 0xbd, 0x94, 0xb0, 0xc9, 0xad, | ||
213 | 0x00, 0xad, 0x00, 0xa2, 0x00, 0xd3, | ||
214 | }; | ||
215 | |||
216 | static const unsigned char s6e8ax0_22_gamma_230[] = { | ||
217 | 0xfa, 0x01, 0x60, 0x10, 0x60, 0xb1, 0xc3, 0xbd, 0xb2, 0xd1, | ||
218 | 0xb1, 0xc3, 0xdd, 0xc1, 0x96, 0xbd, 0x94, 0xb0, 0xc9, 0xad, | ||
219 | 0x00, 0xb0, 0x00, 0xa7, 0x00, 0xd7, | ||
220 | }; | ||
221 | |||
222 | static const unsigned char s6e8ax0_22_gamma_240[] = { | ||
223 | 0xfa, 0x01, 0x60, 0x10, 0x60, 0xb1, 0xcb, 0xbd, 0xb1, 0xd2, | ||
224 | 0xb1, 0xc3, 0xdD, 0xc2, 0x95, 0xbd, 0x93, 0xaf, 0xc8, 0xab, | ||
225 | 0x00, 0xb3, 0x00, 0xa9, 0x00, 0xdb, | ||
226 | }; | ||
227 | |||
228 | static const unsigned char s6e8ax0_22_gamma_250[] = { | ||
229 | 0xfa, 0x01, 0x60, 0x10, 0x60, 0xb3, 0xcc, 0xbe, 0xb0, 0xd2, | ||
230 | 0xb0, 0xc3, 0xdD, 0xc2, 0x94, 0xbc, 0x92, 0xae, 0xc8, 0xab, | ||
231 | 0x00, 0xb6, 0x00, 0xab, 0x00, 0xde, | ||
232 | }; | ||
233 | |||
234 | static const unsigned char s6e8ax0_22_gamma_260[] = { | ||
235 | 0xfa, 0x01, 0x60, 0x10, 0x60, 0xb3, 0xd0, 0xbe, 0xaf, 0xd1, | ||
236 | 0xaf, 0xc2, 0xdd, 0xc1, 0x96, 0xbc, 0x93, 0xaf, 0xc8, 0xac, | ||
237 | 0x00, 0xb7, 0x00, 0xad, 0x00, 0xe0, | ||
238 | }; | ||
239 | |||
240 | static const unsigned char s6e8ax0_22_gamma_270[] = { | ||
241 | 0xfa, 0x01, 0x60, 0x10, 0x60, 0xb2, 0xcF, 0xbd, 0xb0, 0xd2, | ||
242 | 0xaf, 0xc2, 0xdc, 0xc1, 0x95, 0xbd, 0x93, 0xae, 0xc6, 0xaa, | ||
243 | 0x00, 0xba, 0x00, 0xb0, 0x00, 0xe4, | ||
244 | }; | ||
245 | |||
246 | static const unsigned char s6e8ax0_22_gamma_280[] = { | ||
247 | 0xfa, 0x01, 0x60, 0x10, 0x60, 0xb2, 0xd0, 0xbd, 0xaf, 0xd0, | ||
248 | 0xad, 0xc4, 0xdd, 0xc3, 0x95, 0xbd, 0x93, 0xac, 0xc5, 0xa9, | ||
249 | 0x00, 0xbd, 0x00, 0xb2, 0x00, 0xe7, | ||
250 | }; | ||
251 | |||
252 | static const unsigned char s6e8ax0_22_gamma_300[] = { | ||
253 | 0xfa, 0x01, 0x60, 0x10, 0x60, 0xb5, 0xd3, 0xbd, 0xb1, 0xd2, | ||
254 | 0xb0, 0xc0, 0xdc, 0xc0, 0x94, 0xba, 0x91, 0xac, 0xc5, 0xa9, | ||
255 | 0x00, 0xc2, 0x00, 0xb7, 0x00, 0xed, | ||
256 | }; | ||
257 | |||
258 | static const unsigned char *s6e8ax0_22_gamma_table[] = { | ||
259 | s6e8ax0_22_gamma_30, | ||
260 | s6e8ax0_22_gamma_50, | ||
261 | s6e8ax0_22_gamma_60, | ||
262 | s6e8ax0_22_gamma_70, | ||
263 | s6e8ax0_22_gamma_80, | ||
264 | s6e8ax0_22_gamma_90, | ||
265 | s6e8ax0_22_gamma_100, | ||
266 | s6e8ax0_22_gamma_120, | ||
267 | s6e8ax0_22_gamma_130, | ||
268 | s6e8ax0_22_gamma_140, | ||
269 | s6e8ax0_22_gamma_150, | ||
270 | s6e8ax0_22_gamma_160, | ||
271 | s6e8ax0_22_gamma_170, | ||
272 | s6e8ax0_22_gamma_180, | ||
273 | s6e8ax0_22_gamma_190, | ||
274 | s6e8ax0_22_gamma_200, | ||
275 | s6e8ax0_22_gamma_210, | ||
276 | s6e8ax0_22_gamma_220, | ||
277 | s6e8ax0_22_gamma_230, | ||
278 | s6e8ax0_22_gamma_240, | ||
279 | s6e8ax0_22_gamma_250, | ||
280 | s6e8ax0_22_gamma_260, | ||
281 | s6e8ax0_22_gamma_270, | ||
282 | s6e8ax0_22_gamma_280, | ||
283 | s6e8ax0_22_gamma_300, | ||
284 | }; | ||
285 | |||
286 | static void s6e8ax0_panel_cond(struct s6e8ax0 *lcd) | ||
287 | { | ||
288 | struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd); | ||
289 | |||
290 | static const unsigned char data_to_send[] = { | ||
291 | 0xf8, 0x3d, 0x35, 0x00, 0x00, 0x00, 0x93, 0x00, 0x3c, 0x7d, | ||
292 | 0x08, 0x27, 0x7d, 0x3f, 0x00, 0x00, 0x00, 0x20, 0x04, 0x08, | ||
293 | 0x6e, 0x00, 0x00, 0x00, 0x02, 0x08, 0x08, 0x23, 0x23, 0xc0, | ||
294 | 0xc8, 0x08, 0x48, 0xc1, 0x00, 0xc1, 0xff, 0xff, 0xc8 | ||
295 | }; | ||
296 | static const unsigned char data_to_send_panel_reverse[] = { | ||
297 | 0xf8, 0x19, 0x35, 0x00, 0x00, 0x00, 0x93, 0x00, 0x3c, 0x7d, | ||
298 | 0x08, 0x27, 0x7d, 0x3f, 0x00, 0x00, 0x00, 0x20, 0x04, 0x08, | ||
299 | 0x6e, 0x00, 0x00, 0x00, 0x02, 0x08, 0x08, 0x23, 0x23, 0xc0, | ||
300 | 0xc1, 0x01, 0x41, 0xc1, 0x00, 0xc1, 0xf6, 0xf6, 0xc1 | ||
301 | }; | ||
302 | |||
303 | if (lcd->dsim_dev->panel_reverse) | ||
304 | ops->cmd_write(lcd_to_master(lcd), MIPI_DSI_DCS_LONG_WRITE, | ||
305 | data_to_send_panel_reverse, | ||
306 | ARRAY_SIZE(data_to_send_panel_reverse)); | ||
307 | else | ||
308 | ops->cmd_write(lcd_to_master(lcd), MIPI_DSI_DCS_LONG_WRITE, | ||
309 | data_to_send, ARRAY_SIZE(data_to_send)); | ||
310 | } | ||
311 | |||
312 | static void s6e8ax0_display_cond(struct s6e8ax0 *lcd) | ||
313 | { | ||
314 | struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd); | ||
315 | static const unsigned char data_to_send[] = { | ||
316 | 0xf2, 0x80, 0x03, 0x0d | ||
317 | }; | ||
318 | |||
319 | ops->cmd_write(lcd_to_master(lcd), MIPI_DSI_DCS_LONG_WRITE, | ||
320 | data_to_send, ARRAY_SIZE(data_to_send)); | ||
321 | } | ||
322 | |||
323 | /* Gamma 2.2 Setting (200cd, 7500K, 10MPCD) */ | ||
324 | static void s6e8ax0_gamma_cond(struct s6e8ax0 *lcd) | ||
325 | { | ||
326 | struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd); | ||
327 | unsigned int gamma = lcd->bd->props.brightness; | ||
328 | |||
329 | ops->cmd_write(lcd_to_master(lcd), MIPI_DSI_DCS_LONG_WRITE, | ||
330 | s6e8ax0_22_gamma_table[gamma], | ||
331 | GAMMA_TABLE_COUNT); | ||
332 | } | ||
333 | |||
334 | static void s6e8ax0_gamma_update(struct s6e8ax0 *lcd) | ||
335 | { | ||
336 | struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd); | ||
337 | static const unsigned char data_to_send[] = { | ||
338 | 0xf7, 0x03 | ||
339 | }; | ||
340 | |||
341 | ops->cmd_write(lcd_to_master(lcd), | ||
342 | MIPI_DSI_DCS_SHORT_WRITE_PARAM, data_to_send, | ||
343 | ARRAY_SIZE(data_to_send)); | ||
344 | } | ||
345 | |||
346 | static void s6e8ax0_etc_cond1(struct s6e8ax0 *lcd) | ||
347 | { | ||
348 | struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd); | ||
349 | static const unsigned char data_to_send[] = { | ||
350 | 0xd1, 0xfe, 0x80, 0x00, 0x01, 0x0b, 0x00, 0x00, 0x40, | ||
351 | 0x0d, 0x00, 0x00 | ||
352 | }; | ||
353 | |||
354 | ops->cmd_write(lcd_to_master(lcd), MIPI_DSI_DCS_LONG_WRITE, | ||
355 | data_to_send, ARRAY_SIZE(data_to_send)); | ||
356 | } | ||
357 | |||
358 | static void s6e8ax0_etc_cond2(struct s6e8ax0 *lcd) | ||
359 | { | ||
360 | struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd); | ||
361 | static const unsigned char data_to_send[] = { | ||
362 | 0xb6, 0x0c, 0x02, 0x03, 0x32, 0xff, 0x44, 0x44, 0xc0, | ||
363 | 0x00 | ||
364 | }; | ||
365 | |||
366 | ops->cmd_write(lcd_to_master(lcd), MIPI_DSI_DCS_LONG_WRITE, | ||
367 | data_to_send, ARRAY_SIZE(data_to_send)); | ||
368 | } | ||
369 | |||
370 | static void s6e8ax0_etc_cond3(struct s6e8ax0 *lcd) | ||
371 | { | ||
372 | struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd); | ||
373 | static const unsigned char data_to_send[] = { | ||
374 | 0xe1, 0x10, 0x1c, 0x17, 0x08, 0x1d | ||
375 | }; | ||
376 | |||
377 | ops->cmd_write(lcd_to_master(lcd), MIPI_DSI_DCS_LONG_WRITE, | ||
378 | data_to_send, ARRAY_SIZE(data_to_send)); | ||
379 | } | ||
380 | |||
381 | static void s6e8ax0_etc_cond4(struct s6e8ax0 *lcd) | ||
382 | { | ||
383 | struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd); | ||
384 | static const unsigned char data_to_send[] = { | ||
385 | 0xe2, 0xed, 0x07, 0xc3, 0x13, 0x0d, 0x03 | ||
386 | }; | ||
387 | |||
388 | ops->cmd_write(lcd_to_master(lcd), MIPI_DSI_DCS_LONG_WRITE, | ||
389 | data_to_send, ARRAY_SIZE(data_to_send)); | ||
390 | } | ||
391 | |||
392 | static void s6e8ax0_etc_cond5(struct s6e8ax0 *lcd) | ||
393 | { | ||
394 | struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd); | ||
395 | static const unsigned char data_to_send[] = { | ||
396 | 0xf4, 0xcf, 0x0a, 0x12, 0x10, 0x19, 0x33, 0x02 | ||
397 | }; | ||
398 | |||
399 | ops->cmd_write(lcd_to_master(lcd), MIPI_DSI_DCS_LONG_WRITE, | ||
400 | data_to_send, ARRAY_SIZE(data_to_send)); | ||
401 | } | ||
402 | static void s6e8ax0_etc_cond6(struct s6e8ax0 *lcd) | ||
403 | { | ||
404 | struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd); | ||
405 | static const unsigned char data_to_send[] = { | ||
406 | 0xe3, 0x40 | ||
407 | }; | ||
408 | |||
409 | ops->cmd_write(lcd_to_master(lcd), | ||
410 | MIPI_DSI_DCS_SHORT_WRITE_PARAM, | ||
411 | data_to_send, ARRAY_SIZE(data_to_send)); | ||
412 | } | ||
413 | |||
414 | static void s6e8ax0_etc_cond7(struct s6e8ax0 *lcd) | ||
415 | { | ||
416 | struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd); | ||
417 | static const unsigned char data_to_send[] = { | ||
418 | 0xe4, 0x00, 0x00, 0x14, 0x80, 0x00, 0x00, 0x00 | ||
419 | }; | ||
420 | |||
421 | ops->cmd_write(lcd_to_master(lcd), MIPI_DSI_DCS_LONG_WRITE, | ||
422 | data_to_send, ARRAY_SIZE(data_to_send)); | ||
423 | } | ||
424 | |||
425 | static void s6e8ax0_elvss_set(struct s6e8ax0 *lcd) | ||
426 | { | ||
427 | struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd); | ||
428 | static const unsigned char data_to_send[] = { | ||
429 | 0xb1, 0x04, 0x00 | ||
430 | }; | ||
431 | |||
432 | ops->cmd_write(lcd_to_master(lcd), MIPI_DSI_DCS_LONG_WRITE, | ||
433 | data_to_send, ARRAY_SIZE(data_to_send)); | ||
434 | } | ||
435 | |||
436 | static void s6e8ax0_elvss_nvm_set(struct s6e8ax0 *lcd) | ||
437 | { | ||
438 | struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd); | ||
439 | static const unsigned char data_to_send[] = { | ||
440 | 0xd9, 0x5c, 0x20, 0x0c, 0x0f, 0x41, 0x00, 0x10, 0x11, | ||
441 | 0x12, 0xd1, 0x00, 0x00, 0x00, 0x00, 0x80, 0xcb, 0xed, | ||
442 | 0x64, 0xaf | ||
443 | }; | ||
444 | |||
445 | ops->cmd_write(lcd_to_master(lcd), MIPI_DSI_DCS_LONG_WRITE, | ||
446 | data_to_send, ARRAY_SIZE(data_to_send)); | ||
447 | } | ||
448 | |||
449 | static void s6e8ax0_sleep_in(struct s6e8ax0 *lcd) | ||
450 | { | ||
451 | struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd); | ||
452 | static const unsigned char data_to_send[] = { | ||
453 | 0x10, 0x00 | ||
454 | }; | ||
455 | |||
456 | ops->cmd_write(lcd_to_master(lcd), | ||
457 | MIPI_DSI_DCS_SHORT_WRITE, | ||
458 | data_to_send, ARRAY_SIZE(data_to_send)); | ||
459 | } | ||
460 | |||
461 | static void s6e8ax0_sleep_out(struct s6e8ax0 *lcd) | ||
462 | { | ||
463 | struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd); | ||
464 | static const unsigned char data_to_send[] = { | ||
465 | 0x11, 0x00 | ||
466 | }; | ||
467 | |||
468 | ops->cmd_write(lcd_to_master(lcd), | ||
469 | MIPI_DSI_DCS_SHORT_WRITE, | ||
470 | data_to_send, ARRAY_SIZE(data_to_send)); | ||
471 | } | ||
472 | |||
473 | static void s6e8ax0_display_on(struct s6e8ax0 *lcd) | ||
474 | { | ||
475 | struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd); | ||
476 | static const unsigned char data_to_send[] = { | ||
477 | 0x29, 0x00 | ||
478 | }; | ||
479 | |||
480 | ops->cmd_write(lcd_to_master(lcd), | ||
481 | MIPI_DSI_DCS_SHORT_WRITE, | ||
482 | data_to_send, ARRAY_SIZE(data_to_send)); | ||
483 | } | ||
484 | |||
485 | static void s6e8ax0_display_off(struct s6e8ax0 *lcd) | ||
486 | { | ||
487 | struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd); | ||
488 | static const unsigned char data_to_send[] = { | ||
489 | 0x28, 0x00 | ||
490 | }; | ||
491 | |||
492 | ops->cmd_write(lcd_to_master(lcd), | ||
493 | MIPI_DSI_DCS_SHORT_WRITE, | ||
494 | data_to_send, ARRAY_SIZE(data_to_send)); | ||
495 | } | ||
496 | |||
497 | static void s6e8ax0_apply_level2_key(struct s6e8ax0 *lcd) | ||
498 | { | ||
499 | struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd); | ||
500 | static const unsigned char data_to_send[] = { | ||
501 | 0xf0, 0x5a, 0x5a | ||
502 | }; | ||
503 | |||
504 | ops->cmd_write(lcd_to_master(lcd), MIPI_DSI_DCS_LONG_WRITE, | ||
505 | data_to_send, ARRAY_SIZE(data_to_send)); | ||
506 | } | ||
507 | |||
508 | static void s6e8ax0_acl_on(struct s6e8ax0 *lcd) | ||
509 | { | ||
510 | struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd); | ||
511 | static const unsigned char data_to_send[] = { | ||
512 | 0xc0, 0x01 | ||
513 | }; | ||
514 | |||
515 | ops->cmd_write(lcd_to_master(lcd), | ||
516 | MIPI_DSI_DCS_SHORT_WRITE, | ||
517 | data_to_send, ARRAY_SIZE(data_to_send)); | ||
518 | } | ||
519 | |||
520 | static void s6e8ax0_acl_off(struct s6e8ax0 *lcd) | ||
521 | { | ||
522 | struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd); | ||
523 | static const unsigned char data_to_send[] = { | ||
524 | 0xc0, 0x00 | ||
525 | }; | ||
526 | |||
527 | ops->cmd_write(lcd_to_master(lcd), | ||
528 | MIPI_DSI_DCS_SHORT_WRITE, | ||
529 | data_to_send, ARRAY_SIZE(data_to_send)); | ||
530 | } | ||
531 | |||
532 | /* Full white 50% reducing setting */ | ||
533 | static void s6e8ax0_acl_ctrl_set(struct s6e8ax0 *lcd) | ||
534 | { | ||
535 | struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd); | ||
536 | /* Full white 50% reducing setting */ | ||
537 | static const unsigned char cutoff_50[] = { | ||
538 | 0xc1, 0x47, 0x53, 0x13, 0x53, 0x00, 0x00, 0x02, 0xcf, | ||
539 | 0x00, 0x00, 0x04, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
540 | 0x01, 0x08, 0x0f, 0x16, 0x1d, 0x24, 0x2a, 0x31, 0x38, | ||
541 | 0x3f, 0x46 | ||
542 | }; | ||
543 | /* Full white 45% reducing setting */ | ||
544 | static const unsigned char cutoff_45[] = { | ||
545 | 0xc1, 0x47, 0x53, 0x13, 0x53, 0x00, 0x00, 0x02, 0xcf, | ||
546 | 0x00, 0x00, 0x04, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
547 | 0x01, 0x07, 0x0d, 0x13, 0x19, 0x1f, 0x25, 0x2b, 0x31, | ||
548 | 0x37, 0x3d | ||
549 | }; | ||
550 | /* Full white 40% reducing setting */ | ||
551 | static const unsigned char cutoff_40[] = { | ||
552 | 0xc1, 0x47, 0x53, 0x13, 0x53, 0x00, 0x00, 0x02, 0xcf, | ||
553 | 0x00, 0x00, 0x04, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
554 | 0x01, 0x06, 0x0c, 0x11, 0x16, 0x1c, 0x21, 0x26, 0x2b, | ||
555 | 0x31, 0x36 | ||
556 | }; | ||
557 | |||
558 | if (lcd->acl_enable) { | ||
559 | if (lcd->cur_acl == 0) { | ||
560 | if (lcd->gamma == 0 || lcd->gamma == 1) { | ||
561 | s6e8ax0_acl_off(lcd); | ||
562 | dev_dbg(&lcd->ld->dev, | ||
563 | "cur_acl=%d\n", lcd->cur_acl); | ||
564 | } else | ||
565 | s6e8ax0_acl_on(lcd); | ||
566 | } | ||
567 | switch (lcd->gamma) { | ||
568 | case 0: /* 30cd */ | ||
569 | s6e8ax0_acl_off(lcd); | ||
570 | lcd->cur_acl = 0; | ||
571 | break; | ||
572 | case 1 ... 3: /* 50cd ~ 90cd */ | ||
573 | ops->cmd_write(lcd_to_master(lcd), | ||
574 | MIPI_DSI_DCS_LONG_WRITE, | ||
575 | cutoff_40, | ||
576 | ARRAY_SIZE(cutoff_40)); | ||
577 | lcd->cur_acl = 40; | ||
578 | break; | ||
579 | case 4 ... 7: /* 120cd ~ 210cd */ | ||
580 | ops->cmd_write(lcd_to_master(lcd), | ||
581 | MIPI_DSI_DCS_LONG_WRITE, | ||
582 | cutoff_45, | ||
583 | ARRAY_SIZE(cutoff_45)); | ||
584 | lcd->cur_acl = 45; | ||
585 | break; | ||
586 | case 8 ... 10: /* 220cd ~ 300cd */ | ||
587 | ops->cmd_write(lcd_to_master(lcd), | ||
588 | MIPI_DSI_DCS_LONG_WRITE, | ||
589 | cutoff_50, | ||
590 | ARRAY_SIZE(cutoff_50)); | ||
591 | lcd->cur_acl = 50; | ||
592 | break; | ||
593 | default: | ||
594 | break; | ||
595 | } | ||
596 | } else { | ||
597 | s6e8ax0_acl_off(lcd); | ||
598 | lcd->cur_acl = 0; | ||
599 | dev_dbg(&lcd->ld->dev, "cur_acl = %d\n", lcd->cur_acl); | ||
600 | } | ||
601 | } | ||
602 | |||
603 | static void s6e8ax0_read_id(struct s6e8ax0 *lcd, u8 *mtp_id) | ||
604 | { | ||
605 | unsigned int ret; | ||
606 | unsigned int addr = 0xd1; /* MTP ID */ | ||
607 | struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd); | ||
608 | |||
609 | ret = ops->cmd_read(lcd_to_master(lcd), | ||
610 | MIPI_DSI_GENERIC_READ_REQUEST_1_PARAM, | ||
611 | addr, 3, mtp_id); | ||
612 | } | ||
613 | |||
614 | static int s6e8ax0_panel_init(struct s6e8ax0 *lcd) | ||
615 | { | ||
616 | s6e8ax0_apply_level2_key(lcd); | ||
617 | s6e8ax0_sleep_out(lcd); | ||
618 | msleep(1); | ||
619 | s6e8ax0_panel_cond(lcd); | ||
620 | s6e8ax0_display_cond(lcd); | ||
621 | s6e8ax0_gamma_cond(lcd); | ||
622 | s6e8ax0_gamma_update(lcd); | ||
623 | |||
624 | s6e8ax0_etc_cond1(lcd); | ||
625 | s6e8ax0_etc_cond2(lcd); | ||
626 | s6e8ax0_etc_cond3(lcd); | ||
627 | s6e8ax0_etc_cond4(lcd); | ||
628 | s6e8ax0_etc_cond5(lcd); | ||
629 | s6e8ax0_etc_cond6(lcd); | ||
630 | s6e8ax0_etc_cond7(lcd); | ||
631 | |||
632 | s6e8ax0_elvss_nvm_set(lcd); | ||
633 | s6e8ax0_elvss_set(lcd); | ||
634 | |||
635 | s6e8ax0_acl_ctrl_set(lcd); | ||
636 | s6e8ax0_acl_on(lcd); | ||
637 | |||
638 | /* if ID3 value is not 33h, branch private elvss mode */ | ||
639 | msleep(lcd->ddi_pd->power_on_delay); | ||
640 | |||
641 | return 0; | ||
642 | } | ||
643 | |||
644 | static int s6e8ax0_update_gamma_ctrl(struct s6e8ax0 *lcd, int brightness) | ||
645 | { | ||
646 | struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd); | ||
647 | |||
648 | ops->cmd_write(lcd_to_master(lcd), MIPI_DSI_DCS_LONG_WRITE, | ||
649 | s6e8ax0_22_gamma_table[brightness], | ||
650 | ARRAY_SIZE(s6e8ax0_22_gamma_table)); | ||
651 | |||
652 | /* update gamma table. */ | ||
653 | s6e8ax0_gamma_update(lcd); | ||
654 | lcd->gamma = brightness; | ||
655 | |||
656 | return 0; | ||
657 | } | ||
658 | |||
659 | static int s6e8ax0_gamma_ctrl(struct s6e8ax0 *lcd, int gamma) | ||
660 | { | ||
661 | s6e8ax0_update_gamma_ctrl(lcd, gamma); | ||
662 | |||
663 | return 0; | ||
664 | } | ||
665 | |||
666 | static int s6e8ax0_set_power(struct lcd_device *ld, int power) | ||
667 | { | ||
668 | struct s6e8ax0 *lcd = lcd_get_data(ld); | ||
669 | struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd); | ||
670 | int ret = 0; | ||
671 | |||
672 | if (power != FB_BLANK_UNBLANK && power != FB_BLANK_POWERDOWN && | ||
673 | power != FB_BLANK_NORMAL) { | ||
674 | dev_err(lcd->dev, "power value should be 0, 1 or 4.\n"); | ||
675 | return -EINVAL; | ||
676 | } | ||
677 | |||
678 | if ((power == FB_BLANK_UNBLANK) && ops->set_blank_mode) { | ||
679 | /* LCD power on */ | ||
680 | if ((POWER_IS_ON(power) && POWER_IS_OFF(lcd->power)) | ||
681 | || (POWER_IS_ON(power) && POWER_IS_NRM(lcd->power))) { | ||
682 | ret = ops->set_blank_mode(lcd_to_master(lcd), power); | ||
683 | if (!ret && lcd->power != power) | ||
684 | lcd->power = power; | ||
685 | } | ||
686 | } else if ((power == FB_BLANK_POWERDOWN) && ops->set_early_blank_mode) { | ||
687 | /* LCD power off */ | ||
688 | if ((POWER_IS_OFF(power) && POWER_IS_ON(lcd->power)) || | ||
689 | (POWER_IS_ON(lcd->power) && POWER_IS_NRM(power))) { | ||
690 | ret = ops->set_early_blank_mode(lcd_to_master(lcd), | ||
691 | power); | ||
692 | if (!ret && lcd->power != power) | ||
693 | lcd->power = power; | ||
694 | } | ||
695 | } | ||
696 | |||
697 | return ret; | ||
698 | } | ||
699 | |||
700 | static int s6e8ax0_get_power(struct lcd_device *ld) | ||
701 | { | ||
702 | struct s6e8ax0 *lcd = lcd_get_data(ld); | ||
703 | |||
704 | return lcd->power; | ||
705 | } | ||
706 | |||
707 | static int s6e8ax0_get_brightness(struct backlight_device *bd) | ||
708 | { | ||
709 | return bd->props.brightness; | ||
710 | } | ||
711 | |||
712 | static int s6e8ax0_set_brightness(struct backlight_device *bd) | ||
713 | { | ||
714 | int ret = 0, brightness = bd->props.brightness; | ||
715 | struct s6e8ax0 *lcd = bl_get_data(bd); | ||
716 | |||
717 | if (brightness < MIN_BRIGHTNESS || | ||
718 | brightness > bd->props.max_brightness) { | ||
719 | dev_err(lcd->dev, "lcd brightness should be %d to %d.\n", | ||
720 | MIN_BRIGHTNESS, MAX_BRIGHTNESS); | ||
721 | return -EINVAL; | ||
722 | } | ||
723 | |||
724 | ret = s6e8ax0_gamma_ctrl(lcd, brightness); | ||
725 | if (ret) { | ||
726 | dev_err(&bd->dev, "lcd brightness setting failed.\n"); | ||
727 | return -EIO; | ||
728 | } | ||
729 | |||
730 | return ret; | ||
731 | } | ||
732 | |||
733 | static struct lcd_ops s6e8ax0_lcd_ops = { | ||
734 | .set_power = s6e8ax0_set_power, | ||
735 | .get_power = s6e8ax0_get_power, | ||
736 | }; | ||
737 | |||
738 | static const struct backlight_ops s6e8ax0_backlight_ops = { | ||
739 | .get_brightness = s6e8ax0_get_brightness, | ||
740 | .update_status = s6e8ax0_set_brightness, | ||
741 | }; | ||
742 | |||
743 | static void s6e8ax0_power_on(struct mipi_dsim_lcd_device *dsim_dev, int power) | ||
744 | { | ||
745 | struct s6e8ax0 *lcd = dev_get_drvdata(&dsim_dev->dev); | ||
746 | |||
747 | msleep(lcd->ddi_pd->power_on_delay); | ||
748 | |||
749 | /* lcd power on */ | ||
750 | if (power) | ||
751 | s6e8ax0_regulator_enable(lcd); | ||
752 | else | ||
753 | s6e8ax0_regulator_disable(lcd); | ||
754 | |||
755 | msleep(lcd->ddi_pd->reset_delay); | ||
756 | |||
757 | /* lcd reset */ | ||
758 | if (lcd->ddi_pd->reset) | ||
759 | lcd->ddi_pd->reset(lcd->ld); | ||
760 | msleep(5); | ||
761 | } | ||
762 | |||
763 | static void s6e8ax0_set_sequence(struct mipi_dsim_lcd_device *dsim_dev) | ||
764 | { | ||
765 | struct s6e8ax0 *lcd = dev_get_drvdata(&dsim_dev->dev); | ||
766 | |||
767 | s6e8ax0_panel_init(lcd); | ||
768 | s6e8ax0_display_on(lcd); | ||
769 | |||
770 | lcd->power = FB_BLANK_UNBLANK; | ||
771 | } | ||
772 | |||
773 | static int s6e8ax0_probe(struct mipi_dsim_lcd_device *dsim_dev) | ||
774 | { | ||
775 | struct s6e8ax0 *lcd; | ||
776 | int ret; | ||
777 | u8 mtp_id[3] = {0, }; | ||
778 | |||
779 | lcd = devm_kzalloc(&dsim_dev->dev, sizeof(struct s6e8ax0), GFP_KERNEL); | ||
780 | if (!lcd) { | ||
781 | dev_err(&dsim_dev->dev, "failed to allocate s6e8ax0 structure.\n"); | ||
782 | return -ENOMEM; | ||
783 | } | ||
784 | |||
785 | lcd->dsim_dev = dsim_dev; | ||
786 | lcd->ddi_pd = (struct lcd_platform_data *)dsim_dev->platform_data; | ||
787 | lcd->dev = &dsim_dev->dev; | ||
788 | |||
789 | mutex_init(&lcd->lock); | ||
790 | |||
791 | ret = devm_regulator_bulk_get(lcd->dev, ARRAY_SIZE(supplies), supplies); | ||
792 | if (ret) { | ||
793 | dev_err(lcd->dev, "Failed to get regulators: %d\n", ret); | ||
794 | return ret; | ||
795 | } | ||
796 | |||
797 | lcd->ld = devm_lcd_device_register(lcd->dev, "s6e8ax0", lcd->dev, lcd, | ||
798 | &s6e8ax0_lcd_ops); | ||
799 | if (IS_ERR(lcd->ld)) { | ||
800 | dev_err(lcd->dev, "failed to register lcd ops.\n"); | ||
801 | return PTR_ERR(lcd->ld); | ||
802 | } | ||
803 | |||
804 | lcd->bd = devm_backlight_device_register(lcd->dev, "s6e8ax0-bl", | ||
805 | lcd->dev, lcd, &s6e8ax0_backlight_ops, NULL); | ||
806 | if (IS_ERR(lcd->bd)) { | ||
807 | dev_err(lcd->dev, "failed to register backlight ops.\n"); | ||
808 | return PTR_ERR(lcd->bd); | ||
809 | } | ||
810 | |||
811 | lcd->bd->props.max_brightness = MAX_BRIGHTNESS; | ||
812 | lcd->bd->props.brightness = MAX_BRIGHTNESS; | ||
813 | |||
814 | s6e8ax0_read_id(lcd, mtp_id); | ||
815 | if (mtp_id[0] == 0x00) | ||
816 | dev_err(lcd->dev, "read id failed\n"); | ||
817 | |||
818 | dev_info(lcd->dev, "Read ID : %x, %x, %x\n", | ||
819 | mtp_id[0], mtp_id[1], mtp_id[2]); | ||
820 | |||
821 | if (mtp_id[2] == 0x33) | ||
822 | dev_info(lcd->dev, | ||
823 | "ID-3 is 0xff does not support dynamic elvss\n"); | ||
824 | else | ||
825 | dev_info(lcd->dev, | ||
826 | "ID-3 is 0x%x support dynamic elvss\n", mtp_id[2]); | ||
827 | |||
828 | lcd->acl_enable = 1; | ||
829 | lcd->cur_acl = 0; | ||
830 | |||
831 | dev_set_drvdata(&dsim_dev->dev, lcd); | ||
832 | |||
833 | dev_dbg(lcd->dev, "probed s6e8ax0 panel driver.\n"); | ||
834 | |||
835 | return 0; | ||
836 | } | ||
837 | |||
838 | #ifdef CONFIG_PM | ||
839 | static int s6e8ax0_suspend(struct mipi_dsim_lcd_device *dsim_dev) | ||
840 | { | ||
841 | struct s6e8ax0 *lcd = dev_get_drvdata(&dsim_dev->dev); | ||
842 | |||
843 | s6e8ax0_sleep_in(lcd); | ||
844 | msleep(lcd->ddi_pd->power_off_delay); | ||
845 | s6e8ax0_display_off(lcd); | ||
846 | |||
847 | s6e8ax0_regulator_disable(lcd); | ||
848 | |||
849 | return 0; | ||
850 | } | ||
851 | |||
852 | static int s6e8ax0_resume(struct mipi_dsim_lcd_device *dsim_dev) | ||
853 | { | ||
854 | struct s6e8ax0 *lcd = dev_get_drvdata(&dsim_dev->dev); | ||
855 | |||
856 | s6e8ax0_sleep_out(lcd); | ||
857 | msleep(lcd->ddi_pd->power_on_delay); | ||
858 | |||
859 | s6e8ax0_regulator_enable(lcd); | ||
860 | s6e8ax0_set_sequence(dsim_dev); | ||
861 | |||
862 | return 0; | ||
863 | } | ||
864 | #else | ||
865 | #define s6e8ax0_suspend NULL | ||
866 | #define s6e8ax0_resume NULL | ||
867 | #endif | ||
868 | |||
869 | static struct mipi_dsim_lcd_driver s6e8ax0_dsim_ddi_driver = { | ||
870 | .name = "s6e8ax0", | ||
871 | .id = -1, | ||
872 | |||
873 | .power_on = s6e8ax0_power_on, | ||
874 | .set_sequence = s6e8ax0_set_sequence, | ||
875 | .probe = s6e8ax0_probe, | ||
876 | .suspend = s6e8ax0_suspend, | ||
877 | .resume = s6e8ax0_resume, | ||
878 | }; | ||
879 | |||
880 | static int s6e8ax0_init(void) | ||
881 | { | ||
882 | exynos_mipi_dsi_register_lcd_driver(&s6e8ax0_dsim_ddi_driver); | ||
883 | |||
884 | return 0; | ||
885 | } | ||
886 | |||
887 | static void s6e8ax0_exit(void) | ||
888 | { | ||
889 | return; | ||
890 | } | ||
891 | |||
892 | module_init(s6e8ax0_init); | ||
893 | module_exit(s6e8ax0_exit); | ||
894 | |||
895 | MODULE_AUTHOR("Donghwa Lee <dh09.lee@samsung.com>"); | ||
896 | MODULE_AUTHOR("Inki Dae <inki.dae@samsung.com>"); | ||
897 | MODULE_DESCRIPTION("MIPI-DSI based s6e8ax0 AMOLED LCD Panel Driver"); | ||
898 | MODULE_LICENSE("GPL"); | ||