1ed29f942SHoegeun Kwon /*
2ed29f942SHoegeun Kwon  * MIPI-DSI based s6e3ha2 AMOLED 5.7 inch panel driver.
3ed29f942SHoegeun Kwon  *
4ed29f942SHoegeun Kwon  * Copyright (c) 2016 Samsung Electronics Co., Ltd.
5ed29f942SHoegeun Kwon  * Donghwa Lee <dh09.lee@samsung.com>
6ed29f942SHoegeun Kwon  * Hyungwon Hwang <human.hwang@samsung.com>
7ed29f942SHoegeun Kwon  * Hoegeun Kwon <hoegeun.kwon@samsung.com>
8ed29f942SHoegeun Kwon  *
9ed29f942SHoegeun Kwon  * This program is free software; you can redistribute it and/or modify
10ed29f942SHoegeun Kwon  * it under the terms of the GNU General Public License version 2 as
11ed29f942SHoegeun Kwon  * published by the Free Software Foundation.
12ed29f942SHoegeun Kwon  */
13ed29f942SHoegeun Kwon 
14ed29f942SHoegeun Kwon #include <linux/backlight.h>
15cb23eae3SSam Ravnborg #include <linux/delay.h>
16ed29f942SHoegeun Kwon #include <linux/gpio/consumer.h>
17cb23eae3SSam Ravnborg #include <linux/module.h>
18e2af12bfSHoegeun Kwon #include <linux/of_device.h>
19ed29f942SHoegeun Kwon #include <linux/regulator/consumer.h>
20ed29f942SHoegeun Kwon 
21cb23eae3SSam Ravnborg #include <drm/drm_mipi_dsi.h>
22cb23eae3SSam Ravnborg #include <drm/drm_modes.h>
23cb23eae3SSam Ravnborg #include <drm/drm_panel.h>
24cb23eae3SSam Ravnborg #include <drm/drm_print.h>
25cb23eae3SSam Ravnborg 
26ed29f942SHoegeun Kwon #define S6E3HA2_MIN_BRIGHTNESS		0
27ed29f942SHoegeun Kwon #define S6E3HA2_MAX_BRIGHTNESS		100
28ed29f942SHoegeun Kwon #define S6E3HA2_DEFAULT_BRIGHTNESS	80
29ed29f942SHoegeun Kwon 
30ed29f942SHoegeun Kwon #define S6E3HA2_NUM_GAMMA_STEPS		46
31ed29f942SHoegeun Kwon #define S6E3HA2_GAMMA_CMD_CNT		35
32ed29f942SHoegeun Kwon #define S6E3HA2_VINT_STATUS_MAX		10
33ed29f942SHoegeun Kwon 
34ed29f942SHoegeun Kwon static const u8 gamma_tbl[S6E3HA2_NUM_GAMMA_STEPS][S6E3HA2_GAMMA_CMD_CNT] = {
35ed29f942SHoegeun Kwon 	{ 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x89, 0x87, 0x87, 0x82, 0x83,
36ed29f942SHoegeun Kwon 	  0x85, 0x88, 0x8b, 0x8b, 0x84, 0x88, 0x82, 0x82, 0x89, 0x86, 0x8c,
37ed29f942SHoegeun Kwon 	  0x94, 0x84, 0xb1, 0xaf, 0x8e, 0xcf, 0xad, 0xc9, 0x00, 0x00, 0x00,
38ed29f942SHoegeun Kwon 	  0x00, 0x00 },
39ed29f942SHoegeun Kwon 	{ 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x89, 0x87, 0x87, 0x84, 0x84,
40ed29f942SHoegeun Kwon 	  0x85, 0x87, 0x8b, 0x8a, 0x84, 0x88, 0x82, 0x82, 0x89, 0x86, 0x8a,
41ed29f942SHoegeun Kwon 	  0x93, 0x84, 0xb0, 0xae, 0x8e, 0xc9, 0xa8, 0xc5, 0x00, 0x00, 0x00,
42ed29f942SHoegeun Kwon 	  0x00, 0x00 },
43ed29f942SHoegeun Kwon 	{ 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x89, 0x87, 0x87, 0x83, 0x83,
44ed29f942SHoegeun Kwon 	  0x85, 0x86, 0x8a, 0x8a, 0x84, 0x88, 0x81, 0x84, 0x8a, 0x88, 0x8a,
45ed29f942SHoegeun Kwon 	  0x91, 0x84, 0xb1, 0xae, 0x8b, 0xd5, 0xb2, 0xcc, 0x00, 0x00, 0x00,
46ed29f942SHoegeun Kwon 	  0x00, 0x00 },
47ed29f942SHoegeun Kwon 	{ 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x89, 0x87, 0x87, 0x83, 0x83,
48ed29f942SHoegeun Kwon 	  0x85, 0x86, 0x8a, 0x8a, 0x84, 0x87, 0x81, 0x84, 0x8a, 0x87, 0x8a,
49ed29f942SHoegeun Kwon 	  0x91, 0x85, 0xae, 0xac, 0x8a, 0xc3, 0xa3, 0xc0, 0x00, 0x00, 0x00,
50ed29f942SHoegeun Kwon 	  0x00, 0x00 },
51ed29f942SHoegeun Kwon 	{ 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x88, 0x86, 0x87, 0x85, 0x85,
52ed29f942SHoegeun Kwon 	  0x86, 0x85, 0x88, 0x89, 0x84, 0x89, 0x82, 0x84, 0x87, 0x85, 0x8b,
53ed29f942SHoegeun Kwon 	  0x91, 0x88, 0xad, 0xab, 0x8a, 0xb7, 0x9b, 0xb6, 0x00, 0x00, 0x00,
54ed29f942SHoegeun Kwon 	  0x00, 0x00 },
55ed29f942SHoegeun Kwon 	{ 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x89, 0x87, 0x87, 0x83, 0x83,
56ed29f942SHoegeun Kwon 	  0x85, 0x86, 0x89, 0x8a, 0x84, 0x89, 0x83, 0x83, 0x86, 0x84, 0x8b,
57ed29f942SHoegeun Kwon 	  0x90, 0x84, 0xb0, 0xae, 0x8b, 0xce, 0xad, 0xc8, 0x00, 0x00, 0x00,
58ed29f942SHoegeun Kwon 	  0x00, 0x00 },
59ed29f942SHoegeun Kwon 	{ 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x89, 0x87, 0x87, 0x83, 0x83,
60ed29f942SHoegeun Kwon 	  0x85, 0x87, 0x89, 0x8a, 0x83, 0x87, 0x82, 0x85, 0x88, 0x87, 0x89,
61ed29f942SHoegeun Kwon 	  0x8f, 0x84, 0xac, 0xaa, 0x89, 0xb1, 0x98, 0xaf, 0x00, 0x00, 0x00,
62ed29f942SHoegeun Kwon 	  0x00, 0x00 },
63ed29f942SHoegeun Kwon 	{ 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x89, 0x87, 0x87, 0x83, 0x83,
64ed29f942SHoegeun Kwon 	  0x85, 0x86, 0x88, 0x89, 0x84, 0x88, 0x83, 0x82, 0x85, 0x84, 0x8c,
65ed29f942SHoegeun Kwon 	  0x91, 0x86, 0xac, 0xaa, 0x89, 0xc2, 0xa5, 0xbd, 0x00, 0x00, 0x00,
66ed29f942SHoegeun Kwon 	  0x00, 0x00 },
67ed29f942SHoegeun Kwon 	{ 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x88, 0x86, 0x87, 0x84, 0x84,
68ed29f942SHoegeun Kwon 	  0x85, 0x87, 0x89, 0x8a, 0x83, 0x87, 0x82, 0x85, 0x88, 0x87, 0x88,
69ed29f942SHoegeun Kwon 	  0x8b, 0x82, 0xad, 0xaa, 0x8a, 0xc2, 0xa5, 0xbd, 0x00, 0x00, 0x00,
70ed29f942SHoegeun Kwon 	  0x00, 0x00 },
71ed29f942SHoegeun Kwon 	{ 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x89, 0x87, 0x87, 0x83, 0x83,
72ed29f942SHoegeun Kwon 	  0x85, 0x86, 0x87, 0x89, 0x84, 0x88, 0x83, 0x82, 0x85, 0x84, 0x8a,
73ed29f942SHoegeun Kwon 	  0x8e, 0x84, 0xae, 0xac, 0x89, 0xda, 0xb7, 0xd0, 0x00, 0x00, 0x00,
74ed29f942SHoegeun Kwon 	  0x00, 0x00 },
75ed29f942SHoegeun Kwon 	{ 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x88, 0x86, 0x87, 0x84, 0x84,
76ed29f942SHoegeun Kwon 	  0x85, 0x86, 0x87, 0x89, 0x84, 0x88, 0x83, 0x80, 0x83, 0x82, 0x8b,
77ed29f942SHoegeun Kwon 	  0x8e, 0x85, 0xac, 0xaa, 0x89, 0xc8, 0xaa, 0xc1, 0x00, 0x00, 0x00,
78ed29f942SHoegeun Kwon 	  0x00, 0x00 },
79ed29f942SHoegeun Kwon 	{ 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x88, 0x86, 0x87, 0x84, 0x84,
80ed29f942SHoegeun Kwon 	  0x85, 0x86, 0x87, 0x89, 0x81, 0x85, 0x81, 0x84, 0x86, 0x84, 0x8c,
81ed29f942SHoegeun Kwon 	  0x8c, 0x84, 0xa9, 0xa8, 0x87, 0xa3, 0x92, 0xa1, 0x00, 0x00, 0x00,
82ed29f942SHoegeun Kwon 	  0x00, 0x00 },
83ed29f942SHoegeun Kwon 	{ 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x88, 0x86, 0x87, 0x84, 0x84,
84ed29f942SHoegeun Kwon 	  0x85, 0x86, 0x87, 0x89, 0x84, 0x86, 0x83, 0x80, 0x83, 0x81, 0x8c,
85ed29f942SHoegeun Kwon 	  0x8d, 0x84, 0xaa, 0xaa, 0x89, 0xce, 0xaf, 0xc5, 0x00, 0x00, 0x00,
86ed29f942SHoegeun Kwon 	  0x00, 0x00 },
87ed29f942SHoegeun Kwon 	{ 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x88, 0x86, 0x87, 0x84, 0x84,
88ed29f942SHoegeun Kwon 	  0x85, 0x86, 0x87, 0x89, 0x81, 0x83, 0x80, 0x83, 0x85, 0x85, 0x8c,
89ed29f942SHoegeun Kwon 	  0x8c, 0x84, 0xa8, 0xa8, 0x88, 0xb5, 0x9f, 0xb0, 0x00, 0x00, 0x00,
90ed29f942SHoegeun Kwon 	  0x00, 0x00 },
91ed29f942SHoegeun Kwon 	{ 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x88, 0x86, 0x87, 0x84, 0x84,
92ed29f942SHoegeun Kwon 	  0x86, 0x86, 0x87, 0x88, 0x81, 0x83, 0x80, 0x83, 0x85, 0x85, 0x8c,
93ed29f942SHoegeun Kwon 	  0x8b, 0x84, 0xab, 0xa8, 0x86, 0xd4, 0xb4, 0xc9, 0x00, 0x00, 0x00,
94ed29f942SHoegeun Kwon 	  0x00, 0x00 },
95ed29f942SHoegeun Kwon 	{ 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x88, 0x86, 0x87, 0x84, 0x84,
96ed29f942SHoegeun Kwon 	  0x86, 0x86, 0x87, 0x88, 0x81, 0x83, 0x80, 0x84, 0x84, 0x85, 0x8b,
97ed29f942SHoegeun Kwon 	  0x8a, 0x83, 0xa6, 0xa5, 0x84, 0xbb, 0xa4, 0xb3, 0x00, 0x00, 0x00,
98ed29f942SHoegeun Kwon 	  0x00, 0x00 },
99ed29f942SHoegeun Kwon 	{ 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x88, 0x86, 0x87, 0x84, 0x84,
100ed29f942SHoegeun Kwon 	  0x86, 0x85, 0x86, 0x86, 0x82, 0x85, 0x81, 0x82, 0x83, 0x84, 0x8e,
101ed29f942SHoegeun Kwon 	  0x8b, 0x83, 0xa4, 0xa3, 0x8a, 0xa1, 0x93, 0x9d, 0x00, 0x00, 0x00,
102ed29f942SHoegeun Kwon 	  0x00, 0x00 },
103ed29f942SHoegeun Kwon 	{ 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x88, 0x86, 0x87, 0x83, 0x83,
104ed29f942SHoegeun Kwon 	  0x85, 0x86, 0x87, 0x87, 0x82, 0x85, 0x81, 0x82, 0x82, 0x84, 0x8e,
105ed29f942SHoegeun Kwon 	  0x8b, 0x83, 0xa4, 0xa2, 0x86, 0xc1, 0xa9, 0xb7, 0x00, 0x00, 0x00,
106ed29f942SHoegeun Kwon 	  0x00, 0x00 },
107ed29f942SHoegeun Kwon 	{ 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x88, 0x86, 0x87, 0x83, 0x83,
108ed29f942SHoegeun Kwon 	  0x85, 0x86, 0x87, 0x87, 0x82, 0x85, 0x81, 0x82, 0x82, 0x84, 0x8d,
109ed29f942SHoegeun Kwon 	  0x89, 0x82, 0xa2, 0xa1, 0x84, 0xa7, 0x98, 0xa1, 0x00, 0x00, 0x00,
110ed29f942SHoegeun Kwon 	  0x00, 0x00 },
111ed29f942SHoegeun Kwon 	{ 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x88, 0x86, 0x87, 0x83, 0x83,
112ed29f942SHoegeun Kwon 	  0x85, 0x86, 0x87, 0x87, 0x82, 0x85, 0x81, 0x83, 0x83, 0x85, 0x8c,
113ed29f942SHoegeun Kwon 	  0x87, 0x7f, 0xa2, 0x9d, 0x88, 0x8d, 0x88, 0x8b, 0x00, 0x00, 0x00,
114ed29f942SHoegeun Kwon 	  0x00, 0x00 },
115ed29f942SHoegeun Kwon 	{ 0x00, 0xbb, 0x00, 0xc5, 0x00, 0xb4, 0x87, 0x86, 0x86, 0x84, 0x83,
116ed29f942SHoegeun Kwon 	  0x86, 0x87, 0x87, 0x87, 0x80, 0x82, 0x7f, 0x86, 0x86, 0x88, 0x8a,
117ed29f942SHoegeun Kwon 	  0x84, 0x7e, 0x9d, 0x9c, 0x82, 0x8d, 0x88, 0x8b, 0x00, 0x00, 0x00,
118ed29f942SHoegeun Kwon 	  0x00, 0x00 },
119ed29f942SHoegeun Kwon 	{ 0x00, 0xbd, 0x00, 0xc7, 0x00, 0xb7, 0x87, 0x85, 0x85, 0x84, 0x83,
120ed29f942SHoegeun Kwon 	  0x86, 0x86, 0x86, 0x88, 0x81, 0x83, 0x80, 0x83, 0x84, 0x85, 0x8a,
121ed29f942SHoegeun Kwon 	  0x85, 0x7e, 0x9c, 0x9b, 0x85, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00,
122ed29f942SHoegeun Kwon 	  0x00, 0x00 },
123ed29f942SHoegeun Kwon 	{ 0x00, 0xc0, 0x00, 0xca, 0x00, 0xbb, 0x87, 0x86, 0x85, 0x83, 0x83,
124ed29f942SHoegeun Kwon 	  0x85, 0x86, 0x86, 0x88, 0x81, 0x83, 0x80, 0x84, 0x85, 0x86, 0x89,
125ed29f942SHoegeun Kwon 	  0x83, 0x7d, 0x9c, 0x99, 0x87, 0x7b, 0x7b, 0x7c, 0x00, 0x00, 0x00,
126ed29f942SHoegeun Kwon 	  0x00, 0x00 },
127ed29f942SHoegeun Kwon 	{ 0x00, 0xc4, 0x00, 0xcd, 0x00, 0xbe, 0x87, 0x86, 0x85, 0x83, 0x83,
128ed29f942SHoegeun Kwon 	  0x86, 0x85, 0x85, 0x87, 0x81, 0x82, 0x80, 0x82, 0x82, 0x83, 0x8a,
129ed29f942SHoegeun Kwon 	  0x85, 0x7f, 0x9f, 0x9b, 0x86, 0xb4, 0xa1, 0xac, 0x00, 0x00, 0x00,
130ed29f942SHoegeun Kwon 	  0x00, 0x00 },
131ed29f942SHoegeun Kwon 	{ 0x00, 0xc7, 0x00, 0xd0, 0x00, 0xc2, 0x87, 0x85, 0x85, 0x83, 0x82,
132ed29f942SHoegeun Kwon 	  0x85, 0x85, 0x85, 0x86, 0x82, 0x83, 0x80, 0x82, 0x82, 0x84, 0x87,
133ed29f942SHoegeun Kwon 	  0x86, 0x80, 0x9e, 0x9a, 0x87, 0xa7, 0x98, 0xa1, 0x00, 0x00, 0x00,
134ed29f942SHoegeun Kwon 	  0x00, 0x00 },
135ed29f942SHoegeun Kwon 	{ 0x00, 0xca, 0x00, 0xd2, 0x00, 0xc5, 0x87, 0x85, 0x84, 0x82, 0x82,
136ed29f942SHoegeun Kwon 	  0x84, 0x85, 0x85, 0x86, 0x81, 0x82, 0x7f, 0x82, 0x82, 0x84, 0x88,
137ed29f942SHoegeun Kwon 	  0x86, 0x81, 0x9d, 0x98, 0x86, 0x8d, 0x88, 0x8b, 0x00, 0x00, 0x00,
138ed29f942SHoegeun Kwon 	  0x00, 0x00 },
139ed29f942SHoegeun Kwon 	{ 0x00, 0xce, 0x00, 0xd6, 0x00, 0xca, 0x86, 0x85, 0x84, 0x83, 0x83,
140ed29f942SHoegeun Kwon 	  0x85, 0x84, 0x84, 0x85, 0x81, 0x82, 0x80, 0x81, 0x81, 0x82, 0x89,
141ed29f942SHoegeun Kwon 	  0x86, 0x81, 0x9c, 0x97, 0x86, 0xa7, 0x98, 0xa1, 0x00, 0x00, 0x00,
142ed29f942SHoegeun Kwon 	  0x00, 0x00 },
143ed29f942SHoegeun Kwon 	{ 0x00, 0xd1, 0x00, 0xd9, 0x00, 0xce, 0x86, 0x84, 0x83, 0x83, 0x82,
144ed29f942SHoegeun Kwon 	  0x85, 0x85, 0x85, 0x86, 0x81, 0x83, 0x81, 0x82, 0x82, 0x83, 0x86,
145ed29f942SHoegeun Kwon 	  0x83, 0x7f, 0x99, 0x95, 0x86, 0xbb, 0xa4, 0xb3, 0x00, 0x00, 0x00,
146ed29f942SHoegeun Kwon 	  0x00, 0x00 },
147ed29f942SHoegeun Kwon 	{ 0x00, 0xd4, 0x00, 0xdb, 0x00, 0xd1, 0x86, 0x85, 0x83, 0x83, 0x82,
148ed29f942SHoegeun Kwon 	  0x85, 0x84, 0x84, 0x85, 0x80, 0x83, 0x82, 0x80, 0x80, 0x81, 0x87,
149ed29f942SHoegeun Kwon 	  0x84, 0x81, 0x98, 0x93, 0x85, 0xae, 0x9c, 0xa8, 0x00, 0x00, 0x00,
150ed29f942SHoegeun Kwon 	  0x00, 0x00 },
151ed29f942SHoegeun Kwon 	{ 0x00, 0xd8, 0x00, 0xde, 0x00, 0xd6, 0x86, 0x84, 0x83, 0x81, 0x81,
152ed29f942SHoegeun Kwon 	  0x83, 0x85, 0x85, 0x85, 0x82, 0x83, 0x81, 0x81, 0x81, 0x83, 0x86,
153ed29f942SHoegeun Kwon 	  0x84, 0x80, 0x98, 0x91, 0x85, 0x7b, 0x7b, 0x7c, 0x00, 0x00, 0x00,
154ed29f942SHoegeun Kwon 	  0x00, 0x00 },
155ed29f942SHoegeun Kwon 	{ 0x00, 0xdc, 0x00, 0xe2, 0x00, 0xda, 0x85, 0x84, 0x83, 0x82, 0x82,
156ed29f942SHoegeun Kwon 	  0x84, 0x84, 0x84, 0x85, 0x81, 0x82, 0x82, 0x80, 0x80, 0x81, 0x83,
157ed29f942SHoegeun Kwon 	  0x82, 0x7f, 0x99, 0x93, 0x86, 0x94, 0x8b, 0x92, 0x00, 0x00, 0x00,
158ed29f942SHoegeun Kwon 	  0x00, 0x00 },
159ed29f942SHoegeun Kwon 	{ 0x00, 0xdf, 0x00, 0xe5, 0x00, 0xde, 0x85, 0x84, 0x82, 0x82, 0x82,
160ed29f942SHoegeun Kwon 	  0x84, 0x83, 0x83, 0x84, 0x81, 0x81, 0x80, 0x83, 0x82, 0x84, 0x82,
161ed29f942SHoegeun Kwon 	  0x81, 0x7f, 0x99, 0x92, 0x86, 0x7b, 0x7b, 0x7c, 0x00, 0x00, 0x00,
162ed29f942SHoegeun Kwon 	  0x00, 0x00 },
163ed29f942SHoegeun Kwon 	{ 0x00, 0xe4, 0x00, 0xe9, 0x00, 0xe3, 0x84, 0x83, 0x82, 0x81, 0x81,
164ed29f942SHoegeun Kwon 	  0x82, 0x83, 0x83, 0x84, 0x80, 0x81, 0x80, 0x83, 0x83, 0x84, 0x80,
165ed29f942SHoegeun Kwon 	  0x81, 0x7c, 0x99, 0x92, 0x87, 0xa1, 0x93, 0x9d, 0x00, 0x00, 0x00,
166ed29f942SHoegeun Kwon 	  0x00, 0x00 },
167ed29f942SHoegeun Kwon 	{ 0x00, 0xe4, 0x00, 0xe9, 0x00, 0xe3, 0x85, 0x84, 0x83, 0x81, 0x81,
168ed29f942SHoegeun Kwon 	  0x82, 0x82, 0x82, 0x83, 0x80, 0x81, 0x80, 0x81, 0x80, 0x82, 0x83,
169ed29f942SHoegeun Kwon 	  0x82, 0x80, 0x91, 0x8d, 0x83, 0x9a, 0x90, 0x96, 0x00, 0x00, 0x00,
170ed29f942SHoegeun Kwon 	  0x00, 0x00 },
171ed29f942SHoegeun Kwon 	{ 0x00, 0xe4, 0x00, 0xe9, 0x00, 0xe3, 0x84, 0x83, 0x82, 0x81, 0x81,
172ed29f942SHoegeun Kwon 	  0x82, 0x83, 0x83, 0x84, 0x80, 0x81, 0x80, 0x81, 0x80, 0x82, 0x83,
173ed29f942SHoegeun Kwon 	  0x81, 0x7f, 0x91, 0x8c, 0x82, 0x8d, 0x88, 0x8b, 0x00, 0x00, 0x00,
174ed29f942SHoegeun Kwon 	  0x00, 0x00 },
175ed29f942SHoegeun Kwon 	{ 0x00, 0xe4, 0x00, 0xe9, 0x00, 0xe3, 0x84, 0x83, 0x82, 0x81, 0x81,
176ed29f942SHoegeun Kwon 	  0x82, 0x83, 0x83, 0x83, 0x82, 0x82, 0x81, 0x81, 0x80, 0x82, 0x82,
177ed29f942SHoegeun Kwon 	  0x82, 0x7f, 0x94, 0x89, 0x84, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00,
178ed29f942SHoegeun Kwon 	  0x00, 0x00 },
179ed29f942SHoegeun Kwon 	{ 0x00, 0xe4, 0x00, 0xe9, 0x00, 0xe3, 0x84, 0x83, 0x82, 0x81, 0x81,
180ed29f942SHoegeun Kwon 	  0x82, 0x83, 0x83, 0x83, 0x82, 0x82, 0x81, 0x81, 0x80, 0x82, 0x83,
181ed29f942SHoegeun Kwon 	  0x82, 0x7f, 0x91, 0x85, 0x81, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00,
182ed29f942SHoegeun Kwon 	  0x00, 0x00 },
183ed29f942SHoegeun Kwon 	{ 0x00, 0xe4, 0x00, 0xe9, 0x00, 0xe3, 0x84, 0x83, 0x82, 0x81, 0x81,
184ed29f942SHoegeun Kwon 	  0x82, 0x83, 0x83, 0x83, 0x80, 0x80, 0x7f, 0x83, 0x82, 0x84, 0x83,
185ed29f942SHoegeun Kwon 	  0x82, 0x7f, 0x90, 0x84, 0x81, 0x9a, 0x90, 0x96, 0x00, 0x00, 0x00,
186ed29f942SHoegeun Kwon 	  0x00, 0x00 },
187ed29f942SHoegeun Kwon 	{ 0x00, 0xe4, 0x00, 0xe9, 0x00, 0xe3, 0x84, 0x83, 0x82, 0x80, 0x80,
188ed29f942SHoegeun Kwon 	  0x82, 0x83, 0x83, 0x83, 0x80, 0x80, 0x7f, 0x80, 0x80, 0x81, 0x81,
189ed29f942SHoegeun Kwon 	  0x82, 0x83, 0x7e, 0x80, 0x7c, 0xa4, 0x97, 0x9f, 0x00, 0x00, 0x00,
190ed29f942SHoegeun Kwon 	  0x00, 0x00 },
191ed29f942SHoegeun Kwon 	{ 0x00, 0xe9, 0x00, 0xec, 0x00, 0xe8, 0x84, 0x83, 0x82, 0x81, 0x81,
192ed29f942SHoegeun Kwon 	  0x82, 0x82, 0x82, 0x83, 0x7f, 0x7f, 0x7f, 0x81, 0x80, 0x82, 0x83,
193ed29f942SHoegeun Kwon 	  0x83, 0x84, 0x79, 0x7c, 0x79, 0xb1, 0xa0, 0xaa, 0x00, 0x00, 0x00,
194ed29f942SHoegeun Kwon 	  0x00, 0x00 },
195ed29f942SHoegeun Kwon 	{ 0x00, 0xed, 0x00, 0xf0, 0x00, 0xec, 0x83, 0x83, 0x82, 0x80, 0x80,
196ed29f942SHoegeun Kwon 	  0x81, 0x82, 0x82, 0x82, 0x7f, 0x7f, 0x7e, 0x81, 0x81, 0x82, 0x80,
197ed29f942SHoegeun Kwon 	  0x81, 0x81, 0x84, 0x84, 0x83, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00,
198ed29f942SHoegeun Kwon 	  0x00, 0x00 },
199ed29f942SHoegeun Kwon 	{ 0x00, 0xf1, 0x00, 0xf4, 0x00, 0xf1, 0x83, 0x82, 0x82, 0x80, 0x80,
200ed29f942SHoegeun Kwon 	  0x81, 0x82, 0x82, 0x82, 0x80, 0x80, 0x80, 0x80, 0x80, 0x81, 0x7d,
201ed29f942SHoegeun Kwon 	  0x7e, 0x7f, 0x84, 0x84, 0x83, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00,
202ed29f942SHoegeun Kwon 	  0x00, 0x00 },
203ed29f942SHoegeun Kwon 	{ 0x00, 0xf6, 0x00, 0xf7, 0x00, 0xf5, 0x82, 0x82, 0x81, 0x80, 0x80,
204ed29f942SHoegeun Kwon 	  0x80, 0x82, 0x82, 0x82, 0x80, 0x80, 0x80, 0x7f, 0x7f, 0x7f, 0x82,
205ed29f942SHoegeun Kwon 	  0x82, 0x82, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00,
206ed29f942SHoegeun Kwon 	  0x00, 0x00 },
207ed29f942SHoegeun Kwon 	{ 0x00, 0xfa, 0x00, 0xfb, 0x00, 0xfa, 0x81, 0x81, 0x81, 0x80, 0x80,
208ed29f942SHoegeun Kwon 	  0x80, 0x82, 0x82, 0x82, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
209ed29f942SHoegeun Kwon 	  0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00,
210ed29f942SHoegeun Kwon 	  0x00, 0x00 },
211ed29f942SHoegeun Kwon 	{ 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80,
212ed29f942SHoegeun Kwon 	  0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
213ed29f942SHoegeun Kwon 	  0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00,
214ed29f942SHoegeun Kwon 	  0x00, 0x00 },
215ed29f942SHoegeun Kwon 	{ 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80,
216ed29f942SHoegeun Kwon 	  0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
217ed29f942SHoegeun Kwon 	  0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00,
218ed29f942SHoegeun Kwon 	  0x00, 0x00 }
219ed29f942SHoegeun Kwon };
220ed29f942SHoegeun Kwon 
221ed29f942SHoegeun Kwon unsigned char vint_table[S6E3HA2_VINT_STATUS_MAX] = {
222ed29f942SHoegeun Kwon 	0x18, 0x19, 0x1a, 0x1b, 0x1c,
223ed29f942SHoegeun Kwon 	0x1d, 0x1e, 0x1f, 0x20, 0x21
224ed29f942SHoegeun Kwon };
225ed29f942SHoegeun Kwon 
226e2af12bfSHoegeun Kwon enum s6e3ha2_type {
227e2af12bfSHoegeun Kwon 	HA2_TYPE,
228e2af12bfSHoegeun Kwon 	HF2_TYPE,
229e2af12bfSHoegeun Kwon };
230e2af12bfSHoegeun Kwon 
231e2af12bfSHoegeun Kwon struct s6e3ha2_panel_desc {
232e2af12bfSHoegeun Kwon 	const struct drm_display_mode *mode;
233e2af12bfSHoegeun Kwon 	enum s6e3ha2_type type;
234e2af12bfSHoegeun Kwon };
235e2af12bfSHoegeun Kwon 
236ed29f942SHoegeun Kwon struct s6e3ha2 {
237ed29f942SHoegeun Kwon 	struct device *dev;
238ed29f942SHoegeun Kwon 	struct drm_panel panel;
239ed29f942SHoegeun Kwon 	struct backlight_device *bl_dev;
240ed29f942SHoegeun Kwon 
241ed29f942SHoegeun Kwon 	struct regulator_bulk_data supplies[2];
242ed29f942SHoegeun Kwon 	struct gpio_desc *reset_gpio;
243ed29f942SHoegeun Kwon 	struct gpio_desc *enable_gpio;
244e2af12bfSHoegeun Kwon 
245e2af12bfSHoegeun Kwon 	const struct s6e3ha2_panel_desc *desc;
246ed29f942SHoegeun Kwon };
247ed29f942SHoegeun Kwon 
248ed29f942SHoegeun Kwon static int s6e3ha2_dcs_write(struct s6e3ha2 *ctx, const void *data, size_t len)
249ed29f942SHoegeun Kwon {
250ed29f942SHoegeun Kwon 	struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
251ed29f942SHoegeun Kwon 
252ed29f942SHoegeun Kwon 	return mipi_dsi_dcs_write_buffer(dsi, data, len);
253ed29f942SHoegeun Kwon }
254ed29f942SHoegeun Kwon 
255ed29f942SHoegeun Kwon #define s6e3ha2_dcs_write_seq_static(ctx, seq...) do {	\
256ed29f942SHoegeun Kwon 	static const u8 d[] = { seq };			\
257ed29f942SHoegeun Kwon 	int ret;					\
258ed29f942SHoegeun Kwon 	ret = s6e3ha2_dcs_write(ctx, d, ARRAY_SIZE(d));	\
259ed29f942SHoegeun Kwon 	if (ret < 0)					\
260ed29f942SHoegeun Kwon 		return ret;				\
261ed29f942SHoegeun Kwon } while (0)
262ed29f942SHoegeun Kwon 
263ed29f942SHoegeun Kwon #define s6e3ha2_call_write_func(ret, func) do {	\
264ed29f942SHoegeun Kwon 	ret = (func);				\
265ed29f942SHoegeun Kwon 	if (ret < 0)				\
266ed29f942SHoegeun Kwon 		return ret;			\
267ed29f942SHoegeun Kwon } while (0)
268ed29f942SHoegeun Kwon 
269ed29f942SHoegeun Kwon static int s6e3ha2_test_key_on_f0(struct s6e3ha2 *ctx)
270ed29f942SHoegeun Kwon {
271ed29f942SHoegeun Kwon 	s6e3ha2_dcs_write_seq_static(ctx, 0xf0, 0x5a, 0x5a);
272ed29f942SHoegeun Kwon 	return 0;
273ed29f942SHoegeun Kwon }
274ed29f942SHoegeun Kwon 
275ed29f942SHoegeun Kwon static int s6e3ha2_test_key_off_f0(struct s6e3ha2 *ctx)
276ed29f942SHoegeun Kwon {
277ed29f942SHoegeun Kwon 	s6e3ha2_dcs_write_seq_static(ctx, 0xf0, 0xa5, 0xa5);
278ed29f942SHoegeun Kwon 	return 0;
279ed29f942SHoegeun Kwon }
280ed29f942SHoegeun Kwon 
281ed29f942SHoegeun Kwon static int s6e3ha2_test_key_on_fc(struct s6e3ha2 *ctx)
282ed29f942SHoegeun Kwon {
283ed29f942SHoegeun Kwon 	s6e3ha2_dcs_write_seq_static(ctx, 0xfc, 0x5a, 0x5a);
284ed29f942SHoegeun Kwon 	return 0;
285ed29f942SHoegeun Kwon }
286ed29f942SHoegeun Kwon 
287ed29f942SHoegeun Kwon static int s6e3ha2_test_key_off_fc(struct s6e3ha2 *ctx)
288ed29f942SHoegeun Kwon {
289ed29f942SHoegeun Kwon 	s6e3ha2_dcs_write_seq_static(ctx, 0xfc, 0xa5, 0xa5);
290ed29f942SHoegeun Kwon 	return 0;
291ed29f942SHoegeun Kwon }
292ed29f942SHoegeun Kwon 
293ed29f942SHoegeun Kwon static int s6e3ha2_single_dsi_set(struct s6e3ha2 *ctx)
294ed29f942SHoegeun Kwon {
295ed29f942SHoegeun Kwon 	s6e3ha2_dcs_write_seq_static(ctx, 0xf2, 0x67);
296ed29f942SHoegeun Kwon 	s6e3ha2_dcs_write_seq_static(ctx, 0xf9, 0x09);
297ed29f942SHoegeun Kwon 	return 0;
298ed29f942SHoegeun Kwon }
299ed29f942SHoegeun Kwon 
300ed29f942SHoegeun Kwon static int s6e3ha2_freq_calibration(struct s6e3ha2 *ctx)
301ed29f942SHoegeun Kwon {
302ed29f942SHoegeun Kwon 	s6e3ha2_dcs_write_seq_static(ctx, 0xfd, 0x1c);
303e2af12bfSHoegeun Kwon 	if (ctx->desc->type == HF2_TYPE)
304e2af12bfSHoegeun Kwon 		s6e3ha2_dcs_write_seq_static(ctx, 0xf2, 0x67, 0x40, 0xc5);
305ed29f942SHoegeun Kwon 	s6e3ha2_dcs_write_seq_static(ctx, 0xfe, 0x20, 0x39);
306ed29f942SHoegeun Kwon 	s6e3ha2_dcs_write_seq_static(ctx, 0xfe, 0xa0);
307ed29f942SHoegeun Kwon 	s6e3ha2_dcs_write_seq_static(ctx, 0xfe, 0x20);
308e2af12bfSHoegeun Kwon 
309e2af12bfSHoegeun Kwon 	if (ctx->desc->type == HA2_TYPE)
310e2af12bfSHoegeun Kwon 		s6e3ha2_dcs_write_seq_static(ctx, 0xce, 0x03, 0x3b, 0x12, 0x62,
311e2af12bfSHoegeun Kwon 						  0x40, 0x80, 0xc0, 0x28, 0x28,
312e2af12bfSHoegeun Kwon 						  0x28, 0x28, 0x39, 0xc5);
313e2af12bfSHoegeun Kwon 	else
314e2af12bfSHoegeun Kwon 		s6e3ha2_dcs_write_seq_static(ctx, 0xce, 0x03, 0x3b, 0x14, 0x6d,
315e2af12bfSHoegeun Kwon 						  0x40, 0x80, 0xc0, 0x28, 0x28,
316e2af12bfSHoegeun Kwon 						  0x28, 0x28, 0x39, 0xc5);
317e2af12bfSHoegeun Kwon 
318ed29f942SHoegeun Kwon 	return 0;
319ed29f942SHoegeun Kwon }
320ed29f942SHoegeun Kwon 
321ed29f942SHoegeun Kwon static int s6e3ha2_aor_control(struct s6e3ha2 *ctx)
322ed29f942SHoegeun Kwon {
323ed29f942SHoegeun Kwon 	s6e3ha2_dcs_write_seq_static(ctx, 0xb2, 0x03, 0x10);
324ed29f942SHoegeun Kwon 	return 0;
325ed29f942SHoegeun Kwon }
326ed29f942SHoegeun Kwon 
327ed29f942SHoegeun Kwon static int s6e3ha2_caps_elvss_set(struct s6e3ha2 *ctx)
328ed29f942SHoegeun Kwon {
329ed29f942SHoegeun Kwon 	s6e3ha2_dcs_write_seq_static(ctx, 0xb6, 0x9c, 0x0a);
330ed29f942SHoegeun Kwon 	return 0;
331ed29f942SHoegeun Kwon }
332ed29f942SHoegeun Kwon 
333ed29f942SHoegeun Kwon static int s6e3ha2_acl_off(struct s6e3ha2 *ctx)
334ed29f942SHoegeun Kwon {
335ed29f942SHoegeun Kwon 	s6e3ha2_dcs_write_seq_static(ctx, 0x55, 0x00);
336ed29f942SHoegeun Kwon 	return 0;
337ed29f942SHoegeun Kwon }
338ed29f942SHoegeun Kwon 
339ed29f942SHoegeun Kwon static int s6e3ha2_acl_off_opr(struct s6e3ha2 *ctx)
340ed29f942SHoegeun Kwon {
341ed29f942SHoegeun Kwon 	s6e3ha2_dcs_write_seq_static(ctx, 0xb5, 0x40);
342ed29f942SHoegeun Kwon 	return 0;
343ed29f942SHoegeun Kwon }
344ed29f942SHoegeun Kwon 
345ed29f942SHoegeun Kwon static int s6e3ha2_test_global(struct s6e3ha2 *ctx)
346ed29f942SHoegeun Kwon {
347ed29f942SHoegeun Kwon 	s6e3ha2_dcs_write_seq_static(ctx, 0xb0, 0x07);
348ed29f942SHoegeun Kwon 	return 0;
349ed29f942SHoegeun Kwon }
350ed29f942SHoegeun Kwon 
351ed29f942SHoegeun Kwon static int s6e3ha2_test(struct s6e3ha2 *ctx)
352ed29f942SHoegeun Kwon {
353ed29f942SHoegeun Kwon 	s6e3ha2_dcs_write_seq_static(ctx, 0xb8, 0x19);
354ed29f942SHoegeun Kwon 	return 0;
355ed29f942SHoegeun Kwon }
356ed29f942SHoegeun Kwon 
357ed29f942SHoegeun Kwon static int s6e3ha2_touch_hsync_on1(struct s6e3ha2 *ctx)
358ed29f942SHoegeun Kwon {
359ed29f942SHoegeun Kwon 	s6e3ha2_dcs_write_seq_static(ctx, 0xbd, 0x33, 0x11, 0x02,
360ed29f942SHoegeun Kwon 					0x16, 0x02, 0x16);
361ed29f942SHoegeun Kwon 	return 0;
362ed29f942SHoegeun Kwon }
363ed29f942SHoegeun Kwon 
364ed29f942SHoegeun Kwon static int s6e3ha2_pentile_control(struct s6e3ha2 *ctx)
365ed29f942SHoegeun Kwon {
366ed29f942SHoegeun Kwon 	s6e3ha2_dcs_write_seq_static(ctx, 0xc0, 0x00, 0x00, 0xd8, 0xd8);
367ed29f942SHoegeun Kwon 	return 0;
368ed29f942SHoegeun Kwon }
369ed29f942SHoegeun Kwon 
370ed29f942SHoegeun Kwon static int s6e3ha2_poc_global(struct s6e3ha2 *ctx)
371ed29f942SHoegeun Kwon {
372ed29f942SHoegeun Kwon 	s6e3ha2_dcs_write_seq_static(ctx, 0xb0, 0x20);
373ed29f942SHoegeun Kwon 	return 0;
374ed29f942SHoegeun Kwon }
375ed29f942SHoegeun Kwon 
376ed29f942SHoegeun Kwon static int s6e3ha2_poc_setting(struct s6e3ha2 *ctx)
377ed29f942SHoegeun Kwon {
378ed29f942SHoegeun Kwon 	s6e3ha2_dcs_write_seq_static(ctx, 0xfe, 0x08);
379ed29f942SHoegeun Kwon 	return 0;
380ed29f942SHoegeun Kwon }
381ed29f942SHoegeun Kwon 
382ed29f942SHoegeun Kwon static int s6e3ha2_pcd_set_off(struct s6e3ha2 *ctx)
383ed29f942SHoegeun Kwon {
384ed29f942SHoegeun Kwon 	s6e3ha2_dcs_write_seq_static(ctx, 0xcc, 0x40, 0x51);
385ed29f942SHoegeun Kwon 	return 0;
386ed29f942SHoegeun Kwon }
387ed29f942SHoegeun Kwon 
388ed29f942SHoegeun Kwon static int s6e3ha2_err_fg_set(struct s6e3ha2 *ctx)
389ed29f942SHoegeun Kwon {
390ed29f942SHoegeun Kwon 	s6e3ha2_dcs_write_seq_static(ctx, 0xed, 0x44);
391ed29f942SHoegeun Kwon 	return 0;
392ed29f942SHoegeun Kwon }
393ed29f942SHoegeun Kwon 
394ed29f942SHoegeun Kwon static int s6e3ha2_hbm_off(struct s6e3ha2 *ctx)
395ed29f942SHoegeun Kwon {
396ed29f942SHoegeun Kwon 	s6e3ha2_dcs_write_seq_static(ctx, 0x53, 0x00);
397ed29f942SHoegeun Kwon 	return 0;
398ed29f942SHoegeun Kwon }
399ed29f942SHoegeun Kwon 
400ed29f942SHoegeun Kwon static int s6e3ha2_te_start_setting(struct s6e3ha2 *ctx)
401ed29f942SHoegeun Kwon {
402ed29f942SHoegeun Kwon 	s6e3ha2_dcs_write_seq_static(ctx, 0xb9, 0x10, 0x09, 0xff, 0x00, 0x09);
403ed29f942SHoegeun Kwon 	return 0;
404ed29f942SHoegeun Kwon }
405ed29f942SHoegeun Kwon 
406ed29f942SHoegeun Kwon static int s6e3ha2_gamma_update(struct s6e3ha2 *ctx)
407ed29f942SHoegeun Kwon {
408ed29f942SHoegeun Kwon 	s6e3ha2_dcs_write_seq_static(ctx, 0xf7, 0x03);
409ed29f942SHoegeun Kwon 	ndelay(100); /* need for 100ns delay */
410ed29f942SHoegeun Kwon 	s6e3ha2_dcs_write_seq_static(ctx, 0xf7, 0x00);
411ed29f942SHoegeun Kwon 	return 0;
412ed29f942SHoegeun Kwon }
413ed29f942SHoegeun Kwon 
414ed29f942SHoegeun Kwon static int s6e3ha2_get_brightness(struct backlight_device *bl_dev)
415ed29f942SHoegeun Kwon {
416ed29f942SHoegeun Kwon 	return bl_dev->props.brightness;
417ed29f942SHoegeun Kwon }
418ed29f942SHoegeun Kwon 
419ed29f942SHoegeun Kwon static int s6e3ha2_set_vint(struct s6e3ha2 *ctx)
420ed29f942SHoegeun Kwon {
421ed29f942SHoegeun Kwon 	struct backlight_device *bl_dev = ctx->bl_dev;
422ed29f942SHoegeun Kwon 	unsigned int brightness = bl_dev->props.brightness;
423ed29f942SHoegeun Kwon 	unsigned char data[] = { 0xf4, 0x8b,
424ed29f942SHoegeun Kwon 			vint_table[brightness * (S6E3HA2_VINT_STATUS_MAX - 1) /
425ed29f942SHoegeun Kwon 			S6E3HA2_MAX_BRIGHTNESS] };
426ed29f942SHoegeun Kwon 
427ed29f942SHoegeun Kwon 	return s6e3ha2_dcs_write(ctx, data, ARRAY_SIZE(data));
428ed29f942SHoegeun Kwon }
429ed29f942SHoegeun Kwon 
430ed29f942SHoegeun Kwon static unsigned int s6e3ha2_get_brightness_index(unsigned int brightness)
431ed29f942SHoegeun Kwon {
432ed29f942SHoegeun Kwon 	return (brightness * (S6E3HA2_NUM_GAMMA_STEPS - 1)) /
433ed29f942SHoegeun Kwon 		S6E3HA2_MAX_BRIGHTNESS;
434ed29f942SHoegeun Kwon }
435ed29f942SHoegeun Kwon 
436ed29f942SHoegeun Kwon static int s6e3ha2_update_gamma(struct s6e3ha2 *ctx, unsigned int brightness)
437ed29f942SHoegeun Kwon {
438ed29f942SHoegeun Kwon 	struct backlight_device *bl_dev = ctx->bl_dev;
439ed29f942SHoegeun Kwon 	unsigned int index = s6e3ha2_get_brightness_index(brightness);
440ed29f942SHoegeun Kwon 	u8 data[S6E3HA2_GAMMA_CMD_CNT + 1] = { 0xca, };
441ed29f942SHoegeun Kwon 	int ret;
442ed29f942SHoegeun Kwon 
443ed29f942SHoegeun Kwon 	memcpy(data + 1, gamma_tbl + index, S6E3HA2_GAMMA_CMD_CNT);
444ed29f942SHoegeun Kwon 	s6e3ha2_call_write_func(ret,
445ed29f942SHoegeun Kwon 				s6e3ha2_dcs_write(ctx, data, ARRAY_SIZE(data)));
446ed29f942SHoegeun Kwon 
447ed29f942SHoegeun Kwon 	s6e3ha2_call_write_func(ret, s6e3ha2_gamma_update(ctx));
448ed29f942SHoegeun Kwon 	bl_dev->props.brightness = brightness;
449ed29f942SHoegeun Kwon 
450ed29f942SHoegeun Kwon 	return 0;
451ed29f942SHoegeun Kwon }
452ed29f942SHoegeun Kwon 
453ed29f942SHoegeun Kwon static int s6e3ha2_set_brightness(struct backlight_device *bl_dev)
454ed29f942SHoegeun Kwon {
455ed29f942SHoegeun Kwon 	struct s6e3ha2 *ctx = bl_get_data(bl_dev);
456ed29f942SHoegeun Kwon 	unsigned int brightness = bl_dev->props.brightness;
457ed29f942SHoegeun Kwon 	int ret;
458ed29f942SHoegeun Kwon 
459ed29f942SHoegeun Kwon 	if (brightness < S6E3HA2_MIN_BRIGHTNESS ||
460ed29f942SHoegeun Kwon 		brightness > bl_dev->props.max_brightness) {
461ed29f942SHoegeun Kwon 		dev_err(ctx->dev, "Invalid brightness: %u\n", brightness);
462ed29f942SHoegeun Kwon 		return -EINVAL;
463ed29f942SHoegeun Kwon 	}
464ed29f942SHoegeun Kwon 
465ed29f942SHoegeun Kwon 	if (bl_dev->props.power > FB_BLANK_NORMAL)
466ed29f942SHoegeun Kwon 		return -EPERM;
467ed29f942SHoegeun Kwon 
468ed29f942SHoegeun Kwon 	s6e3ha2_call_write_func(ret, s6e3ha2_test_key_on_f0(ctx));
469ed29f942SHoegeun Kwon 	s6e3ha2_call_write_func(ret, s6e3ha2_update_gamma(ctx, brightness));
470ed29f942SHoegeun Kwon 	s6e3ha2_call_write_func(ret, s6e3ha2_aor_control(ctx));
471ed29f942SHoegeun Kwon 	s6e3ha2_call_write_func(ret, s6e3ha2_set_vint(ctx));
472ed29f942SHoegeun Kwon 	s6e3ha2_call_write_func(ret, s6e3ha2_test_key_off_f0(ctx));
473ed29f942SHoegeun Kwon 
474ed29f942SHoegeun Kwon 	return 0;
475ed29f942SHoegeun Kwon }
476ed29f942SHoegeun Kwon 
477ed29f942SHoegeun Kwon static const struct backlight_ops s6e3ha2_bl_ops = {
478ed29f942SHoegeun Kwon 	.get_brightness = s6e3ha2_get_brightness,
479ed29f942SHoegeun Kwon 	.update_status = s6e3ha2_set_brightness,
480ed29f942SHoegeun Kwon };
481ed29f942SHoegeun Kwon 
482ed29f942SHoegeun Kwon static int s6e3ha2_panel_init(struct s6e3ha2 *ctx)
483ed29f942SHoegeun Kwon {
484ed29f942SHoegeun Kwon 	struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
485ed29f942SHoegeun Kwon 	int ret;
486ed29f942SHoegeun Kwon 
487ed29f942SHoegeun Kwon 	s6e3ha2_call_write_func(ret, mipi_dsi_dcs_exit_sleep_mode(dsi));
488ed29f942SHoegeun Kwon 	usleep_range(5000, 6000);
489ed29f942SHoegeun Kwon 
490ed29f942SHoegeun Kwon 	s6e3ha2_call_write_func(ret, s6e3ha2_test_key_on_f0(ctx));
491ed29f942SHoegeun Kwon 	s6e3ha2_call_write_func(ret, s6e3ha2_single_dsi_set(ctx));
492ed29f942SHoegeun Kwon 	s6e3ha2_call_write_func(ret, s6e3ha2_test_key_on_fc(ctx));
493ed29f942SHoegeun Kwon 	s6e3ha2_call_write_func(ret, s6e3ha2_freq_calibration(ctx));
494ed29f942SHoegeun Kwon 	s6e3ha2_call_write_func(ret, s6e3ha2_test_key_off_fc(ctx));
495ed29f942SHoegeun Kwon 	s6e3ha2_call_write_func(ret, s6e3ha2_test_key_off_f0(ctx));
496ed29f942SHoegeun Kwon 
497ed29f942SHoegeun Kwon 	return 0;
498ed29f942SHoegeun Kwon }
499ed29f942SHoegeun Kwon 
500ed29f942SHoegeun Kwon static int s6e3ha2_power_off(struct s6e3ha2 *ctx)
501ed29f942SHoegeun Kwon {
502ed29f942SHoegeun Kwon 	return regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
503ed29f942SHoegeun Kwon }
504ed29f942SHoegeun Kwon 
505ed29f942SHoegeun Kwon static int s6e3ha2_disable(struct drm_panel *panel)
506ed29f942SHoegeun Kwon {
507ed29f942SHoegeun Kwon 	struct s6e3ha2 *ctx = container_of(panel, struct s6e3ha2, panel);
508ed29f942SHoegeun Kwon 	struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
509ed29f942SHoegeun Kwon 	int ret;
510ed29f942SHoegeun Kwon 
511ed29f942SHoegeun Kwon 	s6e3ha2_call_write_func(ret, mipi_dsi_dcs_enter_sleep_mode(dsi));
512ed29f942SHoegeun Kwon 	s6e3ha2_call_write_func(ret, mipi_dsi_dcs_set_display_off(dsi));
513ed29f942SHoegeun Kwon 
514ed29f942SHoegeun Kwon 	msleep(40);
515ed29f942SHoegeun Kwon 	ctx->bl_dev->props.power = FB_BLANK_NORMAL;
516ed29f942SHoegeun Kwon 
517ed29f942SHoegeun Kwon 	return 0;
518ed29f942SHoegeun Kwon }
519ed29f942SHoegeun Kwon 
520ed29f942SHoegeun Kwon static int s6e3ha2_unprepare(struct drm_panel *panel)
521ed29f942SHoegeun Kwon {
522ed29f942SHoegeun Kwon 	struct s6e3ha2 *ctx = container_of(panel, struct s6e3ha2, panel);
523ed29f942SHoegeun Kwon 
524ed29f942SHoegeun Kwon 	return s6e3ha2_power_off(ctx);
525ed29f942SHoegeun Kwon }
526ed29f942SHoegeun Kwon 
527ed29f942SHoegeun Kwon static int s6e3ha2_power_on(struct s6e3ha2 *ctx)
528ed29f942SHoegeun Kwon {
529ed29f942SHoegeun Kwon 	int ret;
530ed29f942SHoegeun Kwon 
531ed29f942SHoegeun Kwon 	ret = regulator_bulk_enable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
532ed29f942SHoegeun Kwon 	if (ret < 0)
533ed29f942SHoegeun Kwon 		return ret;
534ed29f942SHoegeun Kwon 
535ed29f942SHoegeun Kwon 	msleep(120);
536ed29f942SHoegeun Kwon 
537ed29f942SHoegeun Kwon 	gpiod_set_value(ctx->enable_gpio, 0);
538ed29f942SHoegeun Kwon 	usleep_range(5000, 6000);
539ed29f942SHoegeun Kwon 	gpiod_set_value(ctx->enable_gpio, 1);
540ed29f942SHoegeun Kwon 
541ed29f942SHoegeun Kwon 	gpiod_set_value(ctx->reset_gpio, 1);
542ed29f942SHoegeun Kwon 	usleep_range(5000, 6000);
543ed29f942SHoegeun Kwon 	gpiod_set_value(ctx->reset_gpio, 0);
544ed29f942SHoegeun Kwon 	usleep_range(5000, 6000);
545ed29f942SHoegeun Kwon 
546ed29f942SHoegeun Kwon 	return 0;
547ed29f942SHoegeun Kwon }
548ed29f942SHoegeun Kwon static int s6e3ha2_prepare(struct drm_panel *panel)
549ed29f942SHoegeun Kwon {
550ed29f942SHoegeun Kwon 	struct s6e3ha2 *ctx = container_of(panel, struct s6e3ha2, panel);
551ed29f942SHoegeun Kwon 	int ret;
552ed29f942SHoegeun Kwon 
553ed29f942SHoegeun Kwon 	ret = s6e3ha2_power_on(ctx);
554ed29f942SHoegeun Kwon 	if (ret < 0)
555ed29f942SHoegeun Kwon 		return ret;
556ed29f942SHoegeun Kwon 
557ed29f942SHoegeun Kwon 	ret = s6e3ha2_panel_init(ctx);
558ed29f942SHoegeun Kwon 	if (ret < 0)
559ed29f942SHoegeun Kwon 		goto err;
560ed29f942SHoegeun Kwon 
561ed29f942SHoegeun Kwon 	ctx->bl_dev->props.power = FB_BLANK_NORMAL;
562ed29f942SHoegeun Kwon 
563ed29f942SHoegeun Kwon 	return 0;
564ed29f942SHoegeun Kwon 
565ed29f942SHoegeun Kwon err:
566ed29f942SHoegeun Kwon 	s6e3ha2_power_off(ctx);
567ed29f942SHoegeun Kwon 	return ret;
568ed29f942SHoegeun Kwon }
569ed29f942SHoegeun Kwon 
570ed29f942SHoegeun Kwon static int s6e3ha2_enable(struct drm_panel *panel)
571ed29f942SHoegeun Kwon {
572ed29f942SHoegeun Kwon 	struct s6e3ha2 *ctx = container_of(panel, struct s6e3ha2, panel);
573ed29f942SHoegeun Kwon 	struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
574ed29f942SHoegeun Kwon 	int ret;
575ed29f942SHoegeun Kwon 
576ed29f942SHoegeun Kwon 	/* common setting */
577ed29f942SHoegeun Kwon 	s6e3ha2_call_write_func(ret,
578ed29f942SHoegeun Kwon 		mipi_dsi_dcs_set_tear_on(dsi, MIPI_DSI_DCS_TEAR_MODE_VBLANK));
579ed29f942SHoegeun Kwon 
580ed29f942SHoegeun Kwon 	s6e3ha2_call_write_func(ret, s6e3ha2_test_key_on_f0(ctx));
581ed29f942SHoegeun Kwon 	s6e3ha2_call_write_func(ret, s6e3ha2_test_key_on_fc(ctx));
582ed29f942SHoegeun Kwon 	s6e3ha2_call_write_func(ret, s6e3ha2_touch_hsync_on1(ctx));
583ed29f942SHoegeun Kwon 	s6e3ha2_call_write_func(ret, s6e3ha2_pentile_control(ctx));
584ed29f942SHoegeun Kwon 	s6e3ha2_call_write_func(ret, s6e3ha2_poc_global(ctx));
585ed29f942SHoegeun Kwon 	s6e3ha2_call_write_func(ret, s6e3ha2_poc_setting(ctx));
586ed29f942SHoegeun Kwon 	s6e3ha2_call_write_func(ret, s6e3ha2_test_key_off_fc(ctx));
587ed29f942SHoegeun Kwon 
588ed29f942SHoegeun Kwon 	/* pcd setting off for TB */
589ed29f942SHoegeun Kwon 	s6e3ha2_call_write_func(ret, s6e3ha2_pcd_set_off(ctx));
590ed29f942SHoegeun Kwon 	s6e3ha2_call_write_func(ret, s6e3ha2_err_fg_set(ctx));
591ed29f942SHoegeun Kwon 	s6e3ha2_call_write_func(ret, s6e3ha2_te_start_setting(ctx));
592ed29f942SHoegeun Kwon 
593ed29f942SHoegeun Kwon 	/* brightness setting */
594ed29f942SHoegeun Kwon 	s6e3ha2_call_write_func(ret, s6e3ha2_set_brightness(ctx->bl_dev));
595ed29f942SHoegeun Kwon 	s6e3ha2_call_write_func(ret, s6e3ha2_aor_control(ctx));
596ed29f942SHoegeun Kwon 	s6e3ha2_call_write_func(ret, s6e3ha2_caps_elvss_set(ctx));
597ed29f942SHoegeun Kwon 	s6e3ha2_call_write_func(ret, s6e3ha2_gamma_update(ctx));
598ed29f942SHoegeun Kwon 	s6e3ha2_call_write_func(ret, s6e3ha2_acl_off(ctx));
599ed29f942SHoegeun Kwon 	s6e3ha2_call_write_func(ret, s6e3ha2_acl_off_opr(ctx));
600ed29f942SHoegeun Kwon 	s6e3ha2_call_write_func(ret, s6e3ha2_hbm_off(ctx));
601ed29f942SHoegeun Kwon 
602ed29f942SHoegeun Kwon 	/* elvss temp compensation */
603ed29f942SHoegeun Kwon 	s6e3ha2_call_write_func(ret, s6e3ha2_test_global(ctx));
604ed29f942SHoegeun Kwon 	s6e3ha2_call_write_func(ret, s6e3ha2_test(ctx));
605ed29f942SHoegeun Kwon 	s6e3ha2_call_write_func(ret, s6e3ha2_test_key_off_f0(ctx));
606ed29f942SHoegeun Kwon 
607ed29f942SHoegeun Kwon 	s6e3ha2_call_write_func(ret, mipi_dsi_dcs_set_display_on(dsi));
608ed29f942SHoegeun Kwon 	ctx->bl_dev->props.power = FB_BLANK_UNBLANK;
609ed29f942SHoegeun Kwon 
610ed29f942SHoegeun Kwon 	return 0;
611ed29f942SHoegeun Kwon }
612ed29f942SHoegeun Kwon 
613e2af12bfSHoegeun Kwon static const struct drm_display_mode s6e3ha2_mode = {
614ed29f942SHoegeun Kwon 	.clock = 222372,
615ed29f942SHoegeun Kwon 	.hdisplay = 1440,
616ed29f942SHoegeun Kwon 	.hsync_start = 1440 + 1,
617ed29f942SHoegeun Kwon 	.hsync_end = 1440 + 1 + 1,
618ed29f942SHoegeun Kwon 	.htotal = 1440 + 1 + 1 + 1,
619ed29f942SHoegeun Kwon 	.vdisplay = 2560,
620ed29f942SHoegeun Kwon 	.vsync_start = 2560 + 1,
621ed29f942SHoegeun Kwon 	.vsync_end = 2560 + 1 + 1,
622ed29f942SHoegeun Kwon 	.vtotal = 2560 + 1 + 1 + 15,
623ed29f942SHoegeun Kwon 	.vrefresh = 60,
624ed29f942SHoegeun Kwon 	.flags = 0,
625ed29f942SHoegeun Kwon };
626ed29f942SHoegeun Kwon 
627e2af12bfSHoegeun Kwon static const struct s6e3ha2_panel_desc samsung_s6e3ha2 = {
628e2af12bfSHoegeun Kwon 	.mode = &s6e3ha2_mode,
629e2af12bfSHoegeun Kwon 	.type = HA2_TYPE,
630e2af12bfSHoegeun Kwon };
631e2af12bfSHoegeun Kwon 
632e2af12bfSHoegeun Kwon static const struct drm_display_mode s6e3hf2_mode = {
633e2af12bfSHoegeun Kwon 	.clock = 247856,
634e2af12bfSHoegeun Kwon 	.hdisplay = 1600,
635e2af12bfSHoegeun Kwon 	.hsync_start = 1600 + 1,
636e2af12bfSHoegeun Kwon 	.hsync_end = 1600 + 1 + 1,
637e2af12bfSHoegeun Kwon 	.htotal = 1600 + 1 + 1 + 1,
638e2af12bfSHoegeun Kwon 	.vdisplay = 2560,
639e2af12bfSHoegeun Kwon 	.vsync_start = 2560 + 1,
640e2af12bfSHoegeun Kwon 	.vsync_end = 2560 + 1 + 1,
641e2af12bfSHoegeun Kwon 	.vtotal = 2560 + 1 + 1 + 15,
642e2af12bfSHoegeun Kwon 	.vrefresh = 60,
643e2af12bfSHoegeun Kwon 	.flags = 0,
644e2af12bfSHoegeun Kwon };
645e2af12bfSHoegeun Kwon 
646e2af12bfSHoegeun Kwon static const struct s6e3ha2_panel_desc samsung_s6e3hf2 = {
647e2af12bfSHoegeun Kwon 	.mode = &s6e3hf2_mode,
648e2af12bfSHoegeun Kwon 	.type = HF2_TYPE,
649e2af12bfSHoegeun Kwon };
650e2af12bfSHoegeun Kwon 
651ed29f942SHoegeun Kwon static int s6e3ha2_get_modes(struct drm_panel *panel)
652ed29f942SHoegeun Kwon {
653ed29f942SHoegeun Kwon 	struct drm_connector *connector = panel->connector;
654e2af12bfSHoegeun Kwon 	struct s6e3ha2 *ctx = container_of(panel, struct s6e3ha2, panel);
655ed29f942SHoegeun Kwon 	struct drm_display_mode *mode;
656ed29f942SHoegeun Kwon 
657e2af12bfSHoegeun Kwon 	mode = drm_mode_duplicate(panel->drm, ctx->desc->mode);
658ed29f942SHoegeun Kwon 	if (!mode) {
659ed29f942SHoegeun Kwon 		DRM_ERROR("failed to add mode %ux%ux@%u\n",
660e2af12bfSHoegeun Kwon 			ctx->desc->mode->hdisplay, ctx->desc->mode->vdisplay,
661e2af12bfSHoegeun Kwon 			ctx->desc->mode->vrefresh);
662ed29f942SHoegeun Kwon 		return -ENOMEM;
663ed29f942SHoegeun Kwon 	}
664ed29f942SHoegeun Kwon 
665ed29f942SHoegeun Kwon 	drm_mode_set_name(mode);
666ed29f942SHoegeun Kwon 
667ed29f942SHoegeun Kwon 	mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
668ed29f942SHoegeun Kwon 	drm_mode_probed_add(connector, mode);
669ed29f942SHoegeun Kwon 
670ed29f942SHoegeun Kwon 	connector->display_info.width_mm = 71;
671ed29f942SHoegeun Kwon 	connector->display_info.height_mm = 125;
672ed29f942SHoegeun Kwon 
673ed29f942SHoegeun Kwon 	return 1;
674ed29f942SHoegeun Kwon }
675ed29f942SHoegeun Kwon 
676ed29f942SHoegeun Kwon static const struct drm_panel_funcs s6e3ha2_drm_funcs = {
677ed29f942SHoegeun Kwon 	.disable = s6e3ha2_disable,
678ed29f942SHoegeun Kwon 	.unprepare = s6e3ha2_unprepare,
679ed29f942SHoegeun Kwon 	.prepare = s6e3ha2_prepare,
680ed29f942SHoegeun Kwon 	.enable = s6e3ha2_enable,
681ed29f942SHoegeun Kwon 	.get_modes = s6e3ha2_get_modes,
682ed29f942SHoegeun Kwon };
683ed29f942SHoegeun Kwon 
684ed29f942SHoegeun Kwon static int s6e3ha2_probe(struct mipi_dsi_device *dsi)
685ed29f942SHoegeun Kwon {
686ed29f942SHoegeun Kwon 	struct device *dev = &dsi->dev;
687ed29f942SHoegeun Kwon 	struct s6e3ha2 *ctx;
688ed29f942SHoegeun Kwon 	int ret;
689ed29f942SHoegeun Kwon 
690ed29f942SHoegeun Kwon 	ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
691ed29f942SHoegeun Kwon 	if (!ctx)
692ed29f942SHoegeun Kwon 		return -ENOMEM;
693ed29f942SHoegeun Kwon 
694ed29f942SHoegeun Kwon 	mipi_dsi_set_drvdata(dsi, ctx);
695ed29f942SHoegeun Kwon 
696ed29f942SHoegeun Kwon 	ctx->dev = dev;
697e2af12bfSHoegeun Kwon 	ctx->desc = of_device_get_match_data(dev);
698ed29f942SHoegeun Kwon 
699ed29f942SHoegeun Kwon 	dsi->lanes = 4;
700ed29f942SHoegeun Kwon 	dsi->format = MIPI_DSI_FMT_RGB888;
701ed29f942SHoegeun Kwon 	dsi->mode_flags = MIPI_DSI_CLOCK_NON_CONTINUOUS;
702ed29f942SHoegeun Kwon 
703ed29f942SHoegeun Kwon 	ctx->supplies[0].supply = "vdd3";
704ed29f942SHoegeun Kwon 	ctx->supplies[1].supply = "vci";
705ed29f942SHoegeun Kwon 
706ed29f942SHoegeun Kwon 	ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(ctx->supplies),
707ed29f942SHoegeun Kwon 				      ctx->supplies);
708ed29f942SHoegeun Kwon 	if (ret < 0) {
709ed29f942SHoegeun Kwon 		dev_err(dev, "failed to get regulators: %d\n", ret);
710ed29f942SHoegeun Kwon 		return ret;
711ed29f942SHoegeun Kwon 	}
712ed29f942SHoegeun Kwon 
713ed29f942SHoegeun Kwon 	ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW);
714ed29f942SHoegeun Kwon 	if (IS_ERR(ctx->reset_gpio)) {
715ed29f942SHoegeun Kwon 		dev_err(dev, "cannot get reset-gpios %ld\n",
716ed29f942SHoegeun Kwon 			PTR_ERR(ctx->reset_gpio));
717ed29f942SHoegeun Kwon 		return PTR_ERR(ctx->reset_gpio);
718ed29f942SHoegeun Kwon 	}
719ed29f942SHoegeun Kwon 
720ed29f942SHoegeun Kwon 	ctx->enable_gpio = devm_gpiod_get(dev, "enable", GPIOD_OUT_HIGH);
721ed29f942SHoegeun Kwon 	if (IS_ERR(ctx->enable_gpio)) {
722ed29f942SHoegeun Kwon 		dev_err(dev, "cannot get enable-gpios %ld\n",
723ed29f942SHoegeun Kwon 			PTR_ERR(ctx->enable_gpio));
724ed29f942SHoegeun Kwon 		return PTR_ERR(ctx->enable_gpio);
725ed29f942SHoegeun Kwon 	}
726ed29f942SHoegeun Kwon 
727ed29f942SHoegeun Kwon 	ctx->bl_dev = backlight_device_register("s6e3ha2", dev, ctx,
728ed29f942SHoegeun Kwon 						&s6e3ha2_bl_ops, NULL);
729ed29f942SHoegeun Kwon 	if (IS_ERR(ctx->bl_dev)) {
730ed29f942SHoegeun Kwon 		dev_err(dev, "failed to register backlight device\n");
731ed29f942SHoegeun Kwon 		return PTR_ERR(ctx->bl_dev);
732ed29f942SHoegeun Kwon 	}
733ed29f942SHoegeun Kwon 
734ed29f942SHoegeun Kwon 	ctx->bl_dev->props.max_brightness = S6E3HA2_MAX_BRIGHTNESS;
735ed29f942SHoegeun Kwon 	ctx->bl_dev->props.brightness = S6E3HA2_DEFAULT_BRIGHTNESS;
736ed29f942SHoegeun Kwon 	ctx->bl_dev->props.power = FB_BLANK_POWERDOWN;
737ed29f942SHoegeun Kwon 
738ed29f942SHoegeun Kwon 	drm_panel_init(&ctx->panel);
739ed29f942SHoegeun Kwon 	ctx->panel.dev = dev;
740ed29f942SHoegeun Kwon 	ctx->panel.funcs = &s6e3ha2_drm_funcs;
741ed29f942SHoegeun Kwon 
742ed29f942SHoegeun Kwon 	ret = drm_panel_add(&ctx->panel);
743ed29f942SHoegeun Kwon 	if (ret < 0)
744ed29f942SHoegeun Kwon 		goto unregister_backlight;
745ed29f942SHoegeun Kwon 
746ed29f942SHoegeun Kwon 	ret = mipi_dsi_attach(dsi);
747ed29f942SHoegeun Kwon 	if (ret < 0)
748ed29f942SHoegeun Kwon 		goto remove_panel;
749ed29f942SHoegeun Kwon 
750ed29f942SHoegeun Kwon 	return ret;
751ed29f942SHoegeun Kwon 
752ed29f942SHoegeun Kwon remove_panel:
753ed29f942SHoegeun Kwon 	drm_panel_remove(&ctx->panel);
754ed29f942SHoegeun Kwon 
755ed29f942SHoegeun Kwon unregister_backlight:
756ed29f942SHoegeun Kwon 	backlight_device_unregister(ctx->bl_dev);
757ed29f942SHoegeun Kwon 
758ed29f942SHoegeun Kwon 	return ret;
759ed29f942SHoegeun Kwon }
760ed29f942SHoegeun Kwon 
761ed29f942SHoegeun Kwon static int s6e3ha2_remove(struct mipi_dsi_device *dsi)
762ed29f942SHoegeun Kwon {
763ed29f942SHoegeun Kwon 	struct s6e3ha2 *ctx = mipi_dsi_get_drvdata(dsi);
764ed29f942SHoegeun Kwon 
765ed29f942SHoegeun Kwon 	mipi_dsi_detach(dsi);
766ed29f942SHoegeun Kwon 	drm_panel_remove(&ctx->panel);
767ed29f942SHoegeun Kwon 	backlight_device_unregister(ctx->bl_dev);
768ed29f942SHoegeun Kwon 
769ed29f942SHoegeun Kwon 	return 0;
770ed29f942SHoegeun Kwon }
771ed29f942SHoegeun Kwon 
772ed29f942SHoegeun Kwon static const struct of_device_id s6e3ha2_of_match[] = {
773e2af12bfSHoegeun Kwon 	{ .compatible = "samsung,s6e3ha2", .data = &samsung_s6e3ha2 },
774e2af12bfSHoegeun Kwon 	{ .compatible = "samsung,s6e3hf2", .data = &samsung_s6e3hf2 },
775ed29f942SHoegeun Kwon 	{ }
776ed29f942SHoegeun Kwon };
777ed29f942SHoegeun Kwon MODULE_DEVICE_TABLE(of, s6e3ha2_of_match);
778ed29f942SHoegeun Kwon 
779ed29f942SHoegeun Kwon static struct mipi_dsi_driver s6e3ha2_driver = {
780ed29f942SHoegeun Kwon 	.probe = s6e3ha2_probe,
781ed29f942SHoegeun Kwon 	.remove = s6e3ha2_remove,
782ed29f942SHoegeun Kwon 	.driver = {
783ed29f942SHoegeun Kwon 		.name = "panel-samsung-s6e3ha2",
784ed29f942SHoegeun Kwon 		.of_match_table = s6e3ha2_of_match,
785ed29f942SHoegeun Kwon 	},
786ed29f942SHoegeun Kwon };
787ed29f942SHoegeun Kwon module_mipi_dsi_driver(s6e3ha2_driver);
788ed29f942SHoegeun Kwon 
789ed29f942SHoegeun Kwon MODULE_AUTHOR("Donghwa Lee <dh09.lee@samsung.com>");
790ed29f942SHoegeun Kwon MODULE_AUTHOR("Hyungwon Hwang <human.hwang@samsung.com>");
791ed29f942SHoegeun Kwon MODULE_AUTHOR("Hoegeun Kwon <hoegeun.kwon@samsung.com>");
792ed29f942SHoegeun Kwon MODULE_DESCRIPTION("MIPI-DSI based s6e3ha2 AMOLED Panel Driver");
793ed29f942SHoegeun Kwon MODULE_LICENSE("GPL v2");
794