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