13 #include <linux/module.h>
14 #include <linux/kernel.h>
15 #include <linux/errno.h>
17 #include <linux/wait.h>
18 #include <linux/ctype.h>
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
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)
41 #define lcd_to_master(a) (a->dsim_dev->master)
42 #define lcd_to_master_ops(a) ((lcd_to_master(a))->master_ops)
69 { .supply =
"vdd3", },
73 static void s6e8ax0_regulator_enable(
struct s6e8ax0 *
lcd)
92 static void s6e8ax0_regulator_disable(
struct s6e8ax0 *lcd)
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
258 static const unsigned char *s6e8ax0_22_gamma_table[] = {
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,
286 static void s6e8ax0_panel_cond(
struct s6e8ax0 *lcd)
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
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
305 data_to_send_panel_reverse,
312 static void s6e8ax0_display_cond(
struct s6e8ax0 *lcd)
315 static const unsigned char data_to_send[] = {
316 0xf2, 0x80, 0x03, 0x0d
324 static void s6e8ax0_gamma_cond(
struct s6e8ax0 *lcd)
327 unsigned int gamma = lcd->
bd->props.brightness;
330 s6e8ax0_22_gamma_table[gamma],
334 static void s6e8ax0_gamma_update(
struct s6e8ax0 *lcd)
337 static const unsigned char data_to_send[] = {
346 static void s6e8ax0_etc_cond1(
struct s6e8ax0 *lcd)
349 static const unsigned char data_to_send[] = {
350 0xd1, 0xfe, 0x80, 0x00, 0x01, 0x0b, 0x00, 0x00, 0x40,
358 static void s6e8ax0_etc_cond2(
struct s6e8ax0 *lcd)
361 static const unsigned char data_to_send[] = {
362 0xb6, 0x0c, 0x02, 0x03, 0x32, 0xff, 0x44, 0x44, 0xc0,
370 static void s6e8ax0_etc_cond3(
struct s6e8ax0 *lcd)
373 static const unsigned char data_to_send[] = {
374 0xe1, 0x10, 0x1c, 0x17, 0x08, 0x1d
381 static void s6e8ax0_etc_cond4(
struct s6e8ax0 *lcd)
384 static const unsigned char data_to_send[] = {
385 0xe2, 0xed, 0x07, 0xc3, 0x13, 0x0d, 0x03
392 static void s6e8ax0_etc_cond5(
struct s6e8ax0 *lcd)
395 static const unsigned char data_to_send[] = {
396 0xf4, 0xcf, 0x0a, 0x12, 0x10, 0x19, 0x33, 0x02
402 static void s6e8ax0_etc_cond6(
struct s6e8ax0 *lcd)
405 static const unsigned char data_to_send[] = {
414 static void s6e8ax0_etc_cond7(
struct s6e8ax0 *lcd)
417 static const unsigned char data_to_send[] = {
418 0xe4, 0x00, 0x00, 0x14, 0x80, 0x00, 0x00, 0x00
425 static void s6e8ax0_elvss_set(
struct s6e8ax0 *lcd)
428 static const unsigned char data_to_send[] = {
436 static void s6e8ax0_elvss_nvm_set(
struct s6e8ax0 *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,
449 static void s6e8ax0_sleep_in(
struct s6e8ax0 *lcd)
452 static const unsigned char data_to_send[] = {
461 static void s6e8ax0_sleep_out(
struct s6e8ax0 *lcd)
464 static const unsigned char data_to_send[] = {
473 static void s6e8ax0_display_on(
struct s6e8ax0 *lcd)
476 static const unsigned char data_to_send[] = {
485 static void s6e8ax0_display_off(
struct s6e8ax0 *lcd)
488 static const unsigned char data_to_send[] = {
497 static void s6e8ax0_apply_level2_key(
struct s6e8ax0 *lcd)
500 static const unsigned char data_to_send[] = {
508 static void s6e8ax0_acl_on(
struct s6e8ax0 *lcd)
511 static const unsigned char data_to_send[] = {
520 static void s6e8ax0_acl_off(
struct s6e8ax0 *lcd)
523 static const unsigned char data_to_send[] = {
533 static void s6e8ax0_acl_ctrl_set(
struct s6e8ax0 *lcd)
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,
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,
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,
561 s6e8ax0_acl_off(lcd);
567 switch (lcd->
gamma) {
569 s6e8ax0_acl_off(lcd);
597 s6e8ax0_acl_off(lcd);
603 static void s6e8ax0_read_id(
struct s6e8ax0 *lcd,
u8 *mtp_id)
606 unsigned int addr = 0xd1;
614 static int s6e8ax0_panel_init(
struct s6e8ax0 *lcd)
616 s6e8ax0_apply_level2_key(lcd);
617 s6e8ax0_sleep_out(lcd);
619 s6e8ax0_panel_cond(lcd);
620 s6e8ax0_display_cond(lcd);
621 s6e8ax0_gamma_cond(lcd);
622 s6e8ax0_gamma_update(lcd);
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);
632 s6e8ax0_elvss_nvm_set(lcd);
633 s6e8ax0_elvss_set(lcd);
635 s6e8ax0_acl_ctrl_set(lcd);
649 s6e8ax0_22_gamma_table[brightness],
653 s6e8ax0_gamma_update(lcd);
659 static int s6e8ax0_gamma_ctrl(
struct s6e8ax0 *lcd,
int gamma)
661 s6e8ax0_update_gamma_ctrl(lcd, gamma);
666 static int s6e8ax0_set_power(
struct lcd_device *
ld,
int power)
668 struct s6e8ax0 *lcd = lcd_get_data(ld);
674 dev_err(lcd->
dev,
"power value should be 0, 1 or 4.\n");
683 if (!ret && lcd->
power != power)
692 if (!ret && lcd->
power != power)
700 static int s6e8ax0_get_power(
struct lcd_device *ld)
702 struct s6e8ax0 *lcd = lcd_get_data(ld);
709 return bd->
props.brightness;
714 int ret = 0, brightness = bd->
props.brightness;
715 struct s6e8ax0 *lcd = bl_get_data(bd);
718 brightness > bd->
props.max_brightness) {
719 dev_err(lcd->
dev,
"lcd brightness should be %d to %d.\n",
724 ret = s6e8ax0_gamma_ctrl(lcd, brightness);
726 dev_err(&bd->
dev,
"lcd brightness setting failed.\n");
733 static struct lcd_ops s6e8ax0_lcd_ops = {
734 .set_power = s6e8ax0_set_power,
735 .get_power = s6e8ax0_get_power,
739 .get_brightness = s6e8ax0_get_brightness,
740 .update_status = s6e8ax0_set_brightness,
751 s6e8ax0_regulator_enable(lcd);
753 s6e8ax0_regulator_disable(lcd);
767 s6e8ax0_panel_init(lcd);
768 s6e8ax0_display_on(lcd);
777 u8 mtp_id[3] = {0, };
781 dev_err(&dsim_dev->
dev,
"failed to allocate s6e8ax0 structure.\n");
787 lcd->
dev = &dsim_dev->
dev;
793 dev_err(lcd->
dev,
"Failed to get regulators: %d\n", ret);
794 goto err_lcd_register;
799 if (IS_ERR(lcd->
ld)) {
800 dev_err(lcd->
dev,
"failed to register lcd ops.\n");
801 ret = PTR_ERR(lcd->
ld);
802 goto err_lcd_register;
806 &s6e8ax0_backlight_ops,
NULL);
807 if (IS_ERR(lcd->
bd)) {
808 dev_err(lcd->
dev,
"failed to register backlight ops.\n");
809 ret = PTR_ERR(lcd->
bd);
810 goto err_backlight_register;
816 s6e8ax0_read_id(lcd, mtp_id);
817 if (mtp_id[0] == 0x00)
821 mtp_id[0], mtp_id[1], mtp_id[2]);
823 if (mtp_id[2] == 0x33)
825 "ID-3 is 0xff does not support dynamic elvss\n");
828 "ID-3 is 0x%x support dynamic elvss\n", mtp_id[2]);
835 dev_dbg(lcd->
dev,
"probed s6e8ax0 panel driver.\n");
839 err_backlight_register:
854 s6e8ax0_sleep_in(lcd);
856 s6e8ax0_display_off(lcd);
858 s6e8ax0_regulator_disable(lcd);
867 s6e8ax0_sleep_out(lcd);
870 s6e8ax0_regulator_enable(lcd);
871 s6e8ax0_set_sequence(dsim_dev);
876 #define s6e8ax0_suspend NULL
877 #define s6e8ax0_resume NULL
884 .power_on = s6e8ax0_power_on,
885 .set_sequence = s6e8ax0_set_sequence,
886 .probe = s6e8ax0_probe,
891 static int s6e8ax0_init(
void)
898 static void s6e8ax0_exit(
void)