1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3 * Himax HX8279 DriverIC panels driver
4 *
5 * Copyright (c) 2025 Collabora Ltd.
6 * AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
7 */
8
9 #include <linux/bitfield.h>
10 #include <linux/delay.h>
11 #include <linux/gpio/consumer.h>
12 #include <linux/module.h>
13 #include <linux/of.h>
14 #include <linux/of_graph.h>
15 #include <linux/regulator/consumer.h>
16
17 #include <drm/drm_connector.h>
18 #include <drm/drm_crtc.h>
19 #include <drm/drm_mipi_dsi.h>
20 #include <drm/drm_modes.h>
21 #include <drm/drm_panel.h>
22
23 /* Page selection */
24 #define HX8279_REG_PAGE 0xb0
25 #define HX8279_PAGE_SEL GENMASK(3, 0)
26
27 /* Page 0 - Driver/Module Configuration */
28 #define HX8279_P0_VGHS 0xbf
29 #define HX8279_P0_VGLS 0xc0
30 #define HX8279_P0_VGPHS 0xc2
31 #define HX8279_P0_VGNHS 0xc4
32 #define HX8279_P0_VG_SEL GENMASK(4, 0)
33 #define HX8279_VGH_MIN_MV 8700
34 #define HX8279_VGH_STEP_MV 300
35 #define HX8279_VGL_MIN_MV 6700
36 #define HX8279_VGL_STEP_MV 300
37 #define HX8279_VGPNH_MIN_MV 4000
38 #define HX8279_VGPNX_STEP_MV 50
39 #define HX8279_VGH_VOLT_SEL(x) ((x - HX8279_VGH_MIN_MV) / HX8279_VGH_STEP_MV)
40 #define HX8279_VGL_VOLT_SEL(x) ((x - HX8279_VGL_MIN_MV) / HX8279_VGL_STEP_MV)
41 #define HX8279_VGPN_VOLT_SEL(x) ((x - HX8279_VGPNH_MIN_MV) / HX8279_VGPNX_STEP_MV)
42
43 /* Page 1 - Gate driver On Array (GOA) Mux */
44 #define HX8279_P1_REG_GOA_L 0xc0
45 #define HX8279_P1_REG_GOUTL(x) (HX8279_P1_REG_GOA_L + (x))
46 #define HX8279_P1_REG_GOA_R 0xd4
47 #define HX8279_P1_REG_GOUTR(x) (HX8279_P1_REG_GOA_R + (x))
48 #define HX8279_GOUT_STB GENMASK(7, 6)
49 #define HX8279_GOUT_SEL GENMASK(5, 0)
50
51 /* Page 2 - Analog Gamma Configuration */
52 #define HX8279_P2_REG_ANALOG_GAMMA 0xc0
53 #define HX8279_P2_REG_GAMMA_T_PVP(x) (HX8279_P2_REG_ANALOG_GAMMA + (x)) /* 0..16 */
54 #define HX8279_P2_REG_GAMMA_T_PVN(x) (HX8279_P2_REG_GAMMA_T_PVP(17) + (x)) /* 0..16 */
55
56 /* Page 3 - Gate driver On Array (GOA) Configuration */
57 #define HX8279_P3_REG_UNKNOWN_BA 0xba
58 #define HX8279_P3_REG_GOA_CKV_FALL_PREC 0xbc
59 #define HX8279_P3_REG_GOA_TIMING_ODD 0xc2
60 #define HX8279_P3_REG_GOA_TO(x) (HX8279_P3_REG_GOA_TIMING_ODD + x) /* GOA_T0..5 */
61 #define HX8279_P3_REG_GOA_STVL 0xc8
62 #define HX8279_P3_GOA_STV_LEAD GENMASK(4, 0)
63 #define HX8279_P3_REG_GOA_CKVL 0xc9
64 #define HX8279_P3_GOA_CKV_LEAD GENMASK(4, 0)
65 #define HX8279_P3_REG_GOA_CKVD 0xca
66 #define HX8279_P3_GOA_CKV_NONOVERLAP BIT(7)
67 #define HX8279_P3_GOA_CKV_RESERVED BIT(6)
68 #define HX8279_P3_GOA_CKV_DUMMY GENMASK(5, 0)
69 #define HX8279_P3_REG_GOA_CKV_RISE_PREC 0xcb
70 #define HX8279_P3_REG_GOA_CLR1_W_ADJ 0xd2
71 #define HX8279_P3_REG_GOA_CLR234_W_ADJ 0xd3
72 #define HX8279_P3_REG_GOA_CLR1_CFG 0xd4
73 #define HX8279_P3_REG_GOA_CLR_CFG(x) (HX8279_P3_REG_GOA_CLR1_CFG + (x)) /* CLR1..4 */
74 #define HX8279_P3_GOA_CLR_CFG_POLARITY BIT(7)
75 #define HX8279_P3_GOA_CLR_CFG_STARTPOS GENMASK(6, 0)
76 #define HX8279_P3_REG_GOA_TIMING_EVEN 0xdd
77 #define HX8279_P3_REG_GOA_TE(x) (HX8279_P3_REG_GOA_TIMING_EVEN + x)
78 #define HX8279_P3_REG_UNKNOWN_E4 0xe4
79 #define HX8279_P3_REG_UNKNOWN_E5 0xe5
80
81 /* Page 5 - MIPI */
82 #define HX8279_P5_REG_TIMING 0xb3
83 #define HX8279_P5_TIMING_THS_SETTLE GENMASK(7, 5)
84 #define HX8279_P5_TIMING_LHS_SETTLE BIT(4)
85 #define HX8279_P5_TIMING_TLPX GENMASK(3, 0)
86 #define HX8279_P5_REG_UNKNOWN_B8 0xb8
87 #define HX8279_P5_REG_UNKNOWN_BC 0xbc
88 #define HX8279_P5_REG_UNKNOWN_D6 0xd6
89
90 /* Page 6 - Engineer */
91 #define HX8279_P6_REG_ENGINEER_PWD 0xb8
92 #define HX8279_P6_REG_INHOUSE_FUNC 0xc0
93 #define HX8279_P6_ENG_UNLOCK_WORD 0xa5
94 #define HX8279_P6_REG_GAMMA_CHOPPER 0xbc
95 #define HX8279_P6_GAMMA_POCGM_CTL GENMASK(6, 4)
96 #define HX8279_P6_GAMMA_POGCMD_CTL GENMASK(2, 0)
97 #define HX8279_P6_REG_VOLT_ADJ 0xc7
98 /* For VCCIFS and VCCS - 0: 1450, 1: 1500, 2: 1550, 3: 1600 uV */
99 #define HX8279_P6_VOLT_ADJ_VCCIFS GENMASK(3, 2)
100 #define HX8279_P6_VOLT_ADJ_VCCS GENMASK(1, 0)
101 #define HX8279_P6_REG_DLY_TIME_ADJ 0xd5
102
103 /* Page 7...12 - Digital Gamma Adjustment */
104 #define HX8279_PG_DIGITAL_GAMMA 0xb1
105 #define HX8279_DGAMMA_DGMA1_HI GENMASK(7, 6)
106 #define HX8279_DGAMMA_DGMA2_HI GENMASK(5, 4)
107 #define HX8279_DGAMMA_DGMA3_HI GENMASK(3, 2)
108 #define HX8279_DGAMMA_DGMA4_HI GENMASK(1, 0)
109 #define HX8279_PG_DGAMMA_NUM_LO_BYTES 24
110 #define HX8279_PG_DGAMMA_NUM_HI_BYTES 6
111
112 struct hx8279 {
113 struct drm_panel panel;
114 struct mipi_dsi_device *dsi[2];
115 struct regulator_bulk_data vregs[2];
116 struct gpio_desc *enable_gpio;
117 struct gpio_desc *reset_gpio;
118 const struct hx8279_panel_desc *desc;
119 u8 last_page;
120 bool skip_voltage_config;
121 bool skip_goa_config;
122 bool skip_goa_timing;
123 bool skip_goa_even_timing;
124 bool skip_mipi_timing;
125 };
126
127 struct hx8279_panel_mode {
128 const struct drm_display_mode mode;
129 u8 bpc;
130 bool is_video_mode;
131 };
132
133 /**
134 * struct hx8279_goa_mux - Gate driver On Array Muxer
135 * @gout_l: Mux GOA signal to GOUT Left pin
136 * @gout_r: Mux GOA signal to GOUT Right pin
137 */
138 struct hx8279_goa_mux {
139 u8 gout_l[20];
140 u8 gout_r[20];
141 };
142
143 /**
144 * struct hx8279_analog_gamma - Analog Gamma Adjustment
145 * @pos: Positive gamma op's input voltage, adjusted by VGP(H/L)
146 * @neg: Negative gamma op's input voltage, adjusted by VGN(H/L)
147 *
148 * Analog Gamma correction is performed with 17+17 reference voltages,
149 * changed with resistor streams, and defined with 17 register values
150 * for positive and 17 for negative.
151 *
152 * Each register holds resistance values, in 8.5ohms per unit, for the
153 * following gamma levels:
154 * 0, 8, 16, 28, 40, 56, 80, 128, 176, 200, 216, 228, 240, 248, 252, 255.
155 */
156 struct hx8279_analog_gamma {
157 u8 pos[17];
158 u8 neg[17];
159 };
160
161 /**
162 * struct hx8279_digital_gamma - Digital Gamma Adjustment
163 * @r: Adjustment for red component
164 * @g: Adjustment for green component
165 * @b: Adjustment for blue component
166 *
167 * The layout of this structure follows the register layout to simplify
168 * both the handling and the declaration of those values in the driver.
169 * Gamma correction is internally done with a 24 segment piecewise
170 * linear interpolation; those segments are defined with 24 ten bits
171 * values of which:
172 * - The LOW eight bits for the first 24 registers start at the first
173 * register (at 0xb1) of the Digital Gamma Adjustment page;
174 * - The HIGH two bits for each of the 24 registers are contained
175 * in the last six registers;
176 * - The last six registers contain four groups of two-bits HI values
177 * for each of the first 24 registers, but in an inverted fashion,
178 * this means that the first two bits relate to the last register
179 * of a set of four.
180 *
181 * The 24 segments refer to the following gamma levels:
182 * 0, 1, 3, 7, 11, 15, 23, 31, 47, 63, 95, 127, 128, 160,
183 * 192, 208, 224, 232, 240, 244, 248, 252, 254, 255
184 */
185 struct hx8279_digital_gamma {
186 u8 r[HX8279_PG_DGAMMA_NUM_LO_BYTES + HX8279_PG_DGAMMA_NUM_HI_BYTES];
187 u8 g[HX8279_PG_DGAMMA_NUM_LO_BYTES + HX8279_PG_DGAMMA_NUM_HI_BYTES];
188 u8 b[HX8279_PG_DGAMMA_NUM_LO_BYTES + HX8279_PG_DGAMMA_NUM_HI_BYTES];
189 };
190
191 struct hx8279_panel_desc {
192 const struct mipi_dsi_device_info dsi_info;
193 const struct hx8279_panel_mode *mode_data;
194 u8 num_lanes;
195 u8 num_modes;
196
197 /* Page 0 */
198 unsigned int vgh_mv;
199 unsigned int vgl_mv;
200 unsigned int vgph_mv;
201 unsigned int vgnh_mv;
202
203 /* Page 1 */
204 const struct hx8279_goa_mux *gmux;
205
206 /* Page 2 */
207 const struct hx8279_analog_gamma *agamma;
208
209 /* Page 3 */
210 u8 goa_unk_ba;
211 u8 goa_odd_timing[6];
212 u8 goa_even_timing[6];
213 u8 goa_stv_lead_time_ck;
214 u8 goa_ckv_lead_time_ck;
215 u8 goa_ckv_dummy_vblank_num;
216 u8 goa_ckv_rise_precharge;
217 u8 goa_ckv_fall_precharge;
218 bool goa_ckv_non_overlap_ctl;
219 u8 goa_clr1_width_adj;
220 u8 goa_clr234_width_adj;
221 s8 goa_clr_polarity[4];
222 int goa_clr_start_pos[4];
223 u8 goa_unk_e4;
224 u8 goa_unk_e5;
225
226 /* Page 5 */
227 u8 bta_tlpx;
228 bool lhs_settle_time_by_osc25;
229 u8 ths_settle_time;
230 u8 timing_unk_b8;
231 u8 timing_unk_bc;
232 u8 timing_unk_d6;
233
234 /* Page 6 */
235 u8 gamma_ctl;
236 u8 volt_adj;
237 u8 src_delay_time_adj_ck;
238
239 /* Page 7..12 */
240 const struct hx8279_digital_gamma *dgamma;
241 };
242
to_hx8279(struct drm_panel * panel)243 static inline struct hx8279 *to_hx8279(struct drm_panel *panel)
244 {
245 return container_of(panel, struct hx8279, panel);
246 }
247
hx8279_set_page(struct hx8279 * hx,struct mipi_dsi_multi_context * dsi_ctx,u8 page)248 static void hx8279_set_page(struct hx8279 *hx,
249 struct mipi_dsi_multi_context *dsi_ctx, u8 page)
250 {
251 const u8 cmd_set_page[] = { HX8279_REG_PAGE, page };
252
253 if (hx->last_page == page)
254 return;
255
256 mipi_dsi_generic_write_multi(dsi_ctx, cmd_set_page, ARRAY_SIZE(cmd_set_page));
257 if (!dsi_ctx->accum_err)
258 hx->last_page = page;
259 }
260
hx8279_set_module_config(struct hx8279 * hx,struct mipi_dsi_multi_context * dsi_ctx)261 static void hx8279_set_module_config(struct hx8279 *hx,
262 struct mipi_dsi_multi_context *dsi_ctx)
263 {
264 const struct hx8279_panel_desc *desc = hx->desc;
265 u8 cmd_set_voltage[2];
266
267 if (hx->skip_voltage_config)
268 return;
269
270 /* Page 0 - Driver/Module Configuration */
271 hx8279_set_page(hx, dsi_ctx, 0);
272
273 if (desc->vgh_mv) {
274 cmd_set_voltage[0] = HX8279_P0_VGHS;
275 cmd_set_voltage[1] = HX8279_VGH_VOLT_SEL(desc->vgh_mv);
276 mipi_dsi_generic_write_multi(dsi_ctx, cmd_set_voltage,
277 ARRAY_SIZE(cmd_set_voltage));
278 }
279
280 if (desc->vgl_mv) {
281 cmd_set_voltage[0] = HX8279_P0_VGLS;
282 cmd_set_voltage[1] = HX8279_VGL_VOLT_SEL(desc->vgl_mv);
283 mipi_dsi_generic_write_multi(dsi_ctx, cmd_set_voltage,
284 ARRAY_SIZE(cmd_set_voltage));
285 }
286
287 if (desc->vgph_mv) {
288 cmd_set_voltage[0] = HX8279_P0_VGPHS;
289 cmd_set_voltage[1] = HX8279_VGPN_VOLT_SEL(desc->vgph_mv);
290 mipi_dsi_generic_write_multi(dsi_ctx, cmd_set_voltage,
291 ARRAY_SIZE(cmd_set_voltage));
292 }
293
294 if (desc->vgnh_mv) {
295 cmd_set_voltage[0] = HX8279_P0_VGNHS;
296 cmd_set_voltage[1] = HX8279_VGPN_VOLT_SEL(desc->vgnh_mv);
297 mipi_dsi_generic_write_multi(dsi_ctx, cmd_set_voltage,
298 ARRAY_SIZE(cmd_set_voltage));
299 }
300 }
301
hx8279_set_gmux(struct hx8279 * hx,struct mipi_dsi_multi_context * dsi_ctx)302 static void hx8279_set_gmux(struct hx8279 *hx,
303 struct mipi_dsi_multi_context *dsi_ctx)
304 {
305 const struct hx8279_goa_mux *gmux = hx->desc->gmux;
306 u8 cmd_set_gmux[2];
307 int i;
308
309 if (!gmux)
310 return;
311
312 hx8279_set_page(hx, dsi_ctx, 1);
313
314 for (i = 0; i < ARRAY_SIZE(gmux->gout_l); i++) {
315 cmd_set_gmux[0] = HX8279_P1_REG_GOUTL(i);
316 cmd_set_gmux[1] = gmux->gout_l[i];
317 mipi_dsi_generic_write_multi(dsi_ctx, cmd_set_gmux,
318 ARRAY_SIZE(cmd_set_gmux));
319 }
320
321 for (i = 0; i < ARRAY_SIZE(gmux->gout_r); i++) {
322 cmd_set_gmux[0] = HX8279_P1_REG_GOUTR(i);
323 cmd_set_gmux[1] = gmux->gout_r[i];
324 mipi_dsi_generic_write_multi(dsi_ctx, cmd_set_gmux,
325 ARRAY_SIZE(cmd_set_gmux));
326 }
327 }
328
hx8279_set_analog_gamma(struct hx8279 * hx,struct mipi_dsi_multi_context * dsi_ctx)329 static void hx8279_set_analog_gamma(struct hx8279 *hx,
330 struct mipi_dsi_multi_context *dsi_ctx)
331 {
332 const struct hx8279_analog_gamma *agamma = hx->desc->agamma;
333 u8 cmd_set_ana_gamma[2];
334 int i;
335
336 if (!agamma)
337 return;
338
339 hx8279_set_page(hx, dsi_ctx, 2);
340
341 for (i = 0; i < ARRAY_SIZE(agamma->pos); i++) {
342 cmd_set_ana_gamma[0] = HX8279_P2_REG_GAMMA_T_PVP(i);
343 cmd_set_ana_gamma[1] = agamma->pos[i];
344 mipi_dsi_generic_write_multi(dsi_ctx, cmd_set_ana_gamma,
345 ARRAY_SIZE(cmd_set_ana_gamma));
346 }
347
348 for (i = 0; i < ARRAY_SIZE(agamma->neg); i++) {
349 cmd_set_ana_gamma[0] = HX8279_P2_REG_GAMMA_T_PVN(i);
350 cmd_set_ana_gamma[1] = agamma->neg[i];
351 mipi_dsi_generic_write_multi(dsi_ctx, cmd_set_ana_gamma,
352 ARRAY_SIZE(cmd_set_ana_gamma));
353 }
354 }
355
hx8279_set_goa_timing(struct hx8279 * hx,struct mipi_dsi_multi_context * dsi_ctx)356 static void hx8279_set_goa_timing(struct hx8279 *hx,
357 struct mipi_dsi_multi_context *dsi_ctx)
358 {
359 const struct hx8279_panel_desc *desc = hx->desc;
360 u8 cmd_set_goa_t[2];
361 int i;
362
363 if (hx->skip_goa_timing)
364 return;
365
366 hx8279_set_page(hx, dsi_ctx, 3);
367
368 for (i = 0; i < ARRAY_SIZE(desc->goa_odd_timing); i++) {
369 cmd_set_goa_t[0] = HX8279_P3_REG_GOA_TO(i);
370 cmd_set_goa_t[1] = desc->goa_odd_timing[i];
371 mipi_dsi_generic_write_multi(dsi_ctx, cmd_set_goa_t,
372 ARRAY_SIZE(cmd_set_goa_t));
373 }
374
375 for (i = 0; i < ARRAY_SIZE(desc->goa_even_timing); i++) {
376 cmd_set_goa_t[0] = HX8279_P3_REG_GOA_TE(i);
377 cmd_set_goa_t[1] = desc->goa_odd_timing[i];
378 mipi_dsi_generic_write_multi(dsi_ctx, cmd_set_goa_t,
379 ARRAY_SIZE(cmd_set_goa_t));
380 }
381 }
382
hx8279_set_goa_cfg(struct hx8279 * hx,struct mipi_dsi_multi_context * dsi_ctx)383 static void hx8279_set_goa_cfg(struct hx8279 *hx,
384 struct mipi_dsi_multi_context *dsi_ctx)
385 {
386 const struct hx8279_panel_desc *desc = hx->desc;
387 u8 cmd_set_goa[2];
388 int i;
389
390 if (hx->skip_goa_config)
391 return;
392
393 hx8279_set_page(hx, dsi_ctx, 3);
394
395 if (desc->goa_unk_ba) {
396 cmd_set_goa[0] = HX8279_P3_REG_UNKNOWN_BA;
397 cmd_set_goa[1] = desc->goa_unk_ba;
398 mipi_dsi_generic_write_multi(dsi_ctx, cmd_set_goa,
399 ARRAY_SIZE(cmd_set_goa));
400 }
401
402 if (desc->goa_stv_lead_time_ck) {
403 cmd_set_goa[0] = HX8279_P3_REG_GOA_STVL;
404 cmd_set_goa[1] = FIELD_PREP(HX8279_P3_GOA_STV_LEAD,
405 desc->goa_stv_lead_time_ck);
406 mipi_dsi_generic_write_multi(dsi_ctx, cmd_set_goa,
407 ARRAY_SIZE(cmd_set_goa));
408 }
409
410 if (desc->goa_ckv_lead_time_ck) {
411 cmd_set_goa[0] = HX8279_P3_REG_GOA_CKVL;
412 cmd_set_goa[1] = FIELD_PREP(HX8279_P3_GOA_CKV_DUMMY,
413 desc->goa_ckv_lead_time_ck);
414 mipi_dsi_generic_write_multi(dsi_ctx, cmd_set_goa,
415 ARRAY_SIZE(cmd_set_goa));
416 }
417
418 if (desc->goa_ckv_dummy_vblank_num) {
419 cmd_set_goa[0] = HX8279_P3_REG_GOA_CKVD;
420 cmd_set_goa[1] = FIELD_PREP(HX8279_P3_GOA_CKV_LEAD,
421 desc->goa_ckv_dummy_vblank_num);
422 cmd_set_goa[1] |= FIELD_PREP(HX8279_P3_GOA_CKV_NONOVERLAP,
423 desc->goa_ckv_non_overlap_ctl);
424 /* RESERVED must be always set */
425 cmd_set_goa[1] |= HX8279_P3_GOA_CKV_RESERVED;
426 mipi_dsi_generic_write_multi(dsi_ctx, cmd_set_goa,
427 ARRAY_SIZE(cmd_set_goa));
428 }
429
430 /*
431 * One of the two being more than zero means that we want to write
432 * both of them. Anyway, the register default is zero in this case.
433 */
434 if (desc->goa_ckv_rise_precharge || desc->goa_ckv_fall_precharge) {
435 cmd_set_goa[0] = HX8279_P3_REG_GOA_CKV_RISE_PREC;
436 cmd_set_goa[1] = desc->goa_ckv_rise_precharge;
437 mipi_dsi_generic_write_multi(dsi_ctx, cmd_set_goa,
438 ARRAY_SIZE(cmd_set_goa));
439
440 cmd_set_goa[0] = HX8279_P3_REG_GOA_CKV_FALL_PREC;
441 cmd_set_goa[1] = desc->goa_ckv_fall_precharge;
442 mipi_dsi_generic_write_multi(dsi_ctx, cmd_set_goa,
443 ARRAY_SIZE(cmd_set_goa));
444 }
445
446 if (desc->goa_clr1_width_adj) {
447 cmd_set_goa[0] = HX8279_P3_REG_GOA_CLR1_W_ADJ;
448 cmd_set_goa[1] = desc->goa_clr1_width_adj;
449 mipi_dsi_generic_write_multi(dsi_ctx, cmd_set_goa,
450 ARRAY_SIZE(cmd_set_goa));
451 }
452
453 if (desc->goa_clr234_width_adj) {
454 cmd_set_goa[0] = HX8279_P3_REG_GOA_CLR234_W_ADJ;
455 cmd_set_goa[1] = desc->goa_clr234_width_adj;
456 mipi_dsi_generic_write_multi(dsi_ctx, cmd_set_goa,
457 ARRAY_SIZE(cmd_set_goa));
458 }
459
460 /* Polarity and Start Position arrays are of the same size */
461 for (i = 0; i < ARRAY_SIZE(desc->goa_clr_polarity); i++) {
462 if (desc->goa_clr_polarity[i] < 0 || desc->goa_clr_start_pos[i] < 0)
463 continue;
464
465 cmd_set_goa[0] = HX8279_P3_REG_GOA_CLR_CFG(i);
466 cmd_set_goa[1] = FIELD_PREP(HX8279_P3_GOA_CLR_CFG_STARTPOS,
467 desc->goa_clr_start_pos[i]);
468 cmd_set_goa[1] |= FIELD_PREP(HX8279_P3_GOA_CLR_CFG_POLARITY,
469 desc->goa_clr_polarity[i]);
470 mipi_dsi_generic_write_multi(dsi_ctx, cmd_set_goa,
471 ARRAY_SIZE(cmd_set_goa));
472 }
473
474 if (desc->goa_unk_e4) {
475 cmd_set_goa[0] = HX8279_P3_REG_UNKNOWN_E4;
476 cmd_set_goa[1] = desc->goa_unk_e4;
477 mipi_dsi_generic_write_multi(dsi_ctx, cmd_set_goa,
478 ARRAY_SIZE(cmd_set_goa));
479 }
480
481 cmd_set_goa[0] = HX8279_P3_REG_UNKNOWN_E5;
482 cmd_set_goa[1] = desc->goa_unk_e5;
483 mipi_dsi_generic_write_multi(dsi_ctx, cmd_set_goa,
484 ARRAY_SIZE(cmd_set_goa));
485 }
486
hx8279_set_mipi_cfg(struct hx8279 * hx,struct mipi_dsi_multi_context * dsi_ctx)487 static void hx8279_set_mipi_cfg(struct hx8279 *hx,
488 struct mipi_dsi_multi_context *dsi_ctx)
489 {
490 const struct hx8279_panel_desc *desc = hx->desc;
491 u8 cmd_set_mipi[2];
492
493 if (hx->skip_mipi_timing)
494 return;
495
496 hx8279_set_page(hx, dsi_ctx, 5);
497
498 if (desc->bta_tlpx || desc->ths_settle_time || desc->lhs_settle_time_by_osc25) {
499 cmd_set_mipi[0] = HX8279_P5_REG_TIMING;
500 cmd_set_mipi[1] = FIELD_PREP(HX8279_P5_TIMING_TLPX, desc->bta_tlpx);
501 cmd_set_mipi[1] |= FIELD_PREP(HX8279_P5_TIMING_THS_SETTLE,
502 desc->ths_settle_time);
503 cmd_set_mipi[1] |= FIELD_PREP(HX8279_P5_TIMING_LHS_SETTLE,
504 desc->lhs_settle_time_by_osc25);
505 mipi_dsi_generic_write_multi(dsi_ctx, cmd_set_mipi,
506 ARRAY_SIZE(cmd_set_mipi));
507 }
508
509 if (desc->timing_unk_b8) {
510 cmd_set_mipi[0] = HX8279_P5_REG_UNKNOWN_B8;
511 cmd_set_mipi[1] = desc->timing_unk_b8;
512 mipi_dsi_generic_write_multi(dsi_ctx, cmd_set_mipi,
513 ARRAY_SIZE(cmd_set_mipi));
514 }
515
516 if (desc->timing_unk_bc) {
517 cmd_set_mipi[0] = HX8279_P5_REG_UNKNOWN_BC;
518 cmd_set_mipi[1] = desc->timing_unk_bc;
519 mipi_dsi_generic_write_multi(dsi_ctx, cmd_set_mipi,
520 ARRAY_SIZE(cmd_set_mipi));
521 }
522
523 if (desc->timing_unk_d6) {
524 cmd_set_mipi[0] = HX8279_P5_REG_UNKNOWN_D6;
525 cmd_set_mipi[1] = desc->timing_unk_d6;
526 mipi_dsi_generic_write_multi(dsi_ctx, cmd_set_mipi,
527 ARRAY_SIZE(cmd_set_mipi));
528 }
529 }
530
hx8279_set_adv_cfg(struct hx8279 * hx,struct mipi_dsi_multi_context * dsi_ctx)531 static void hx8279_set_adv_cfg(struct hx8279 *hx,
532 struct mipi_dsi_multi_context *dsi_ctx)
533 {
534 const struct hx8279_panel_desc *desc = hx->desc;
535 const u8 cmd_set_dly[] = { HX8279_P6_REG_DLY_TIME_ADJ, desc->src_delay_time_adj_ck };
536 const u8 cmd_set_gamma[] = { HX8279_P6_REG_GAMMA_CHOPPER, desc->gamma_ctl };
537 const u8 cmd_set_volt_adj[] = { HX8279_P6_REG_VOLT_ADJ, desc->volt_adj };
538 u8 cmd_set_eng[] = { HX8279_P6_REG_ENGINEER_PWD, HX8279_P6_ENG_UNLOCK_WORD };
539
540 if (!desc->gamma_ctl && !desc->src_delay_time_adj_ck && !desc->volt_adj)
541 return;
542
543 hx8279_set_page(hx, dsi_ctx, 6);
544
545 /* Unlock ENG settings: write same word to both ENGINEER_PWD and INHOUSE_FUNC */
546 mipi_dsi_generic_write_multi(dsi_ctx, cmd_set_eng, ARRAY_SIZE(cmd_set_eng));
547
548 cmd_set_eng[0] = HX8279_P6_REG_INHOUSE_FUNC;
549 mipi_dsi_generic_write_multi(dsi_ctx, cmd_set_eng, ARRAY_SIZE(cmd_set_eng));
550
551 /* Set Gamma Chopper and Gamma buffer Chopper control */
552 mipi_dsi_generic_write_multi(dsi_ctx, cmd_set_gamma, ARRAY_SIZE(cmd_set_gamma));
553
554 /* Set Source delay time adjustment (CKV falling to Source off) */
555 if (desc->src_delay_time_adj_ck)
556 mipi_dsi_generic_write_multi(dsi_ctx, cmd_set_dly,
557 ARRAY_SIZE(cmd_set_dly));
558
559 /* Set voltage adjustment */
560 if (desc->volt_adj)
561 mipi_dsi_generic_write_multi(dsi_ctx, cmd_set_volt_adj,
562 ARRAY_SIZE(cmd_set_volt_adj));
563
564 /* Lock ENG settings again */
565 cmd_set_eng[0] = HX8279_P6_REG_ENGINEER_PWD;
566 cmd_set_eng[1] = 0;
567 mipi_dsi_generic_write_multi(dsi_ctx, cmd_set_eng, ARRAY_SIZE(cmd_set_eng));
568
569 cmd_set_eng[0] = HX8279_P6_REG_INHOUSE_FUNC;
570 mipi_dsi_generic_write_multi(dsi_ctx, cmd_set_eng, ARRAY_SIZE(cmd_set_eng));
571 }
572
hx8279_set_digital_gamma(struct hx8279 * hx,struct mipi_dsi_multi_context * dsi_ctx)573 static void hx8279_set_digital_gamma(struct hx8279 *hx,
574 struct mipi_dsi_multi_context *dsi_ctx)
575 {
576 const struct hx8279_digital_gamma *dgamma = hx->desc->dgamma;
577 u8 cmd_set_dig_gamma[2];
578 int i;
579
580 if (!dgamma)
581 return;
582
583 /*
584 * Pages 7..9 are for RGB Positive, 10..12 are for RGB Negative:
585 * The first iteration sets all positive component registers,
586 * the second one sets all negatives.
587 */
588 for (i = 0; i < 2; i++) {
589 u8 pg_neg = i * 3;
590
591 hx8279_set_page(hx, dsi_ctx, 7 + pg_neg);
592
593 for (i = 0; i < ARRAY_SIZE(dgamma->r); i++) {
594 cmd_set_dig_gamma[0] = HX8279_PG_DIGITAL_GAMMA + i;
595 cmd_set_dig_gamma[1] = dgamma->r[i];
596 mipi_dsi_generic_write_multi(dsi_ctx, cmd_set_dig_gamma,
597 ARRAY_SIZE(cmd_set_dig_gamma));
598 }
599
600 hx8279_set_page(hx, dsi_ctx, 8 + pg_neg);
601
602 for (i = 0; i < ARRAY_SIZE(dgamma->g); i++) {
603 cmd_set_dig_gamma[0] = HX8279_PG_DIGITAL_GAMMA + i;
604 cmd_set_dig_gamma[1] = dgamma->g[i];
605 mipi_dsi_generic_write_multi(dsi_ctx, cmd_set_dig_gamma,
606 ARRAY_SIZE(cmd_set_dig_gamma));
607 }
608
609 hx8279_set_page(hx, dsi_ctx, 9 + pg_neg);
610
611 for (i = 0; i < ARRAY_SIZE(dgamma->b); i++) {
612 cmd_set_dig_gamma[0] = HX8279_PG_DIGITAL_GAMMA + i;
613 cmd_set_dig_gamma[1] = dgamma->b[i];
614 mipi_dsi_generic_write_multi(dsi_ctx, cmd_set_dig_gamma,
615 ARRAY_SIZE(cmd_set_dig_gamma));
616 }
617 }
618 }
619
hx8279_on(struct hx8279 * hx)620 static int hx8279_on(struct hx8279 *hx)
621 {
622 struct mipi_dsi_device *dsi = hx->dsi[0];
623 struct mipi_dsi_multi_context dsi_ctx = { .dsi = dsi };
624
625 /* Page 5 */
626 hx8279_set_mipi_cfg(hx, &dsi_ctx);
627
628 /* Page 1 */
629 hx8279_set_gmux(hx, &dsi_ctx);
630
631 /* Page 2 */
632 hx8279_set_analog_gamma(hx, &dsi_ctx);
633
634 /* Page 3 */
635 hx8279_set_goa_cfg(hx, &dsi_ctx);
636 hx8279_set_goa_timing(hx, &dsi_ctx);
637
638 /* Page 0 - Driver/Module Configuration */
639 hx8279_set_module_config(hx, &dsi_ctx);
640
641 /* Page 6 */
642 hx8279_set_adv_cfg(hx, &dsi_ctx);
643
644 /* Pages 7..12 */
645 hx8279_set_digital_gamma(hx, &dsi_ctx);
646
647 return dsi_ctx.accum_err;
648 }
649
hx8279_power_off(struct hx8279 * hx)650 static void hx8279_power_off(struct hx8279 *hx)
651 {
652 gpiod_set_value_cansleep(hx->reset_gpio, 0);
653 usleep_range(100, 500);
654 gpiod_set_value_cansleep(hx->enable_gpio, 0);
655 regulator_bulk_disable(ARRAY_SIZE(hx->vregs), hx->vregs);
656 }
657
hx8279_disable(struct drm_panel * panel)658 static int hx8279_disable(struct drm_panel *panel)
659 {
660 struct hx8279 *hx = to_hx8279(panel);
661 struct mipi_dsi_device *dsi = hx->dsi[0];
662 struct mipi_dsi_multi_context dsi_ctx = { .dsi = dsi };
663
664 mipi_dsi_dcs_set_display_off_multi(&dsi_ctx);
665
666 return 0;
667 }
668
hx8279_enable(struct drm_panel * panel)669 static int hx8279_enable(struct drm_panel *panel)
670 {
671 struct hx8279 *hx = to_hx8279(panel);
672 struct mipi_dsi_device *dsi = hx->dsi[0];
673 struct mipi_dsi_multi_context dsi_ctx = { .dsi = dsi };
674
675 mipi_dsi_dcs_set_display_on_multi(&dsi_ctx);
676
677 return 0;
678 }
679
hx8279_prepare(struct drm_panel * panel)680 static int hx8279_prepare(struct drm_panel *panel)
681 {
682 struct hx8279 *hx = to_hx8279(panel);
683 struct mipi_dsi_device *dsi = hx->dsi[0];
684 struct mipi_dsi_multi_context dsi_ctx = { .dsi = dsi };
685 int ret;
686
687 ret = regulator_bulk_enable(ARRAY_SIZE(hx->vregs), hx->vregs);
688 if (ret)
689 return ret;
690
691 gpiod_set_value_cansleep(hx->enable_gpio, 1);
692 usleep_range(5000, 6000);
693 gpiod_set_value_cansleep(hx->reset_gpio, 1);
694 usleep_range(6000, 7000);
695
696 dsi->mode_flags |= MIPI_DSI_MODE_LPM;
697 if (hx->dsi[1])
698 hx->dsi[1]->mode_flags |= MIPI_DSI_MODE_LPM;
699
700 ret = hx8279_on(hx);
701 if (ret) {
702 hx8279_power_off(hx);
703 return ret;
704 }
705
706 mipi_dsi_dcs_exit_sleep_mode_multi(&dsi_ctx);
707 mipi_dsi_msleep(&dsi_ctx, 130);
708
709 return dsi_ctx.accum_err;
710 }
711
hx8279_unprepare(struct drm_panel * panel)712 static int hx8279_unprepare(struct drm_panel *panel)
713 {
714 struct hx8279 *hx = to_hx8279(panel);
715 struct mipi_dsi_device *dsi = hx->dsi[0];
716 struct mipi_dsi_multi_context dsi_ctx = { .dsi = dsi };
717
718 mipi_dsi_dcs_enter_sleep_mode_multi(&dsi_ctx);
719 mipi_dsi_msleep(&dsi_ctx, 130);
720
721 dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
722 if (hx->dsi[1])
723 hx->dsi[1]->mode_flags &= ~MIPI_DSI_MODE_LPM;
724
725 hx8279_power_off(hx);
726
727 return dsi_ctx.accum_err;
728 }
729
hx8279_get_modes(struct drm_panel * panel,struct drm_connector * connector)730 static int hx8279_get_modes(struct drm_panel *panel, struct drm_connector *connector)
731 {
732 struct hx8279 *hx = to_hx8279(panel);
733 int i;
734
735 for (i = 0; i < hx->desc->num_modes; i++) {
736 struct drm_display_mode *mode;
737
738 mode = drm_mode_duplicate(connector->dev, &hx->desc->mode_data[i].mode);
739 if (!mode)
740 return -ENOMEM;
741
742 drm_mode_set_name(mode);
743
744 mode->type |= DRM_MODE_TYPE_DRIVER;
745 if (hx->desc->num_modes == 1)
746 mode->type |= DRM_MODE_TYPE_PREFERRED;
747
748 drm_mode_probed_add(connector, mode);
749 }
750
751 connector->display_info.bpc = hx->desc->mode_data[0].bpc;
752 connector->display_info.height_mm = hx->desc->mode_data[0].mode.height_mm;
753 connector->display_info.width_mm = hx->desc->mode_data[0].mode.width_mm;
754
755 return hx->desc->num_modes;
756 }
757
758 static const struct drm_panel_funcs hx8279_panel_funcs = {
759 .disable = hx8279_disable,
760 .unprepare = hx8279_unprepare,
761 .prepare = hx8279_prepare,
762 .enable = hx8279_enable,
763 .get_modes = hx8279_get_modes,
764 };
765
hx8279_init_vregs(struct hx8279 * hx,struct device * dev)766 static int hx8279_init_vregs(struct hx8279 *hx, struct device *dev)
767 {
768 int ret;
769
770 hx->vregs[0].supply = "vdd";
771 hx->vregs[1].supply = "iovcc";
772 ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(hx->vregs),
773 hx->vregs);
774 if (ret < 0)
775 return ret;
776
777 ret = regulator_is_supported_voltage(hx->vregs[0].consumer,
778 3000000, 5000000);
779 if (!ret)
780 return -EINVAL;
781
782 ret = regulator_is_supported_voltage(hx->vregs[1].consumer,
783 1700000, 1900000);
784 if (!ret)
785 return -EINVAL;
786
787 return 0;
788 }
789
hx8279_check_gmux_config(struct hx8279 * hx,struct device * dev)790 static int hx8279_check_gmux_config(struct hx8279 *hx, struct device *dev)
791 {
792 const struct hx8279_panel_desc *desc = hx->desc;
793 const struct hx8279_goa_mux *gmux = desc->gmux;
794 int i;
795
796 /* No gmux defined means we simply skip the GOA mux configuration */
797 if (!gmux)
798 return 0;
799
800 for (i = 0; i < ARRAY_SIZE(gmux->gout_l); i++) {
801 if (gmux->gout_l[i] > (HX8279_GOUT_STB | HX8279_GOUT_SEL))
802 return dev_err_probe(dev, -EINVAL,
803 "Invalid value found in gout_l[%d]\n", i);
804 }
805
806 for (i = 0; i < ARRAY_SIZE(gmux->gout_r); i++) {
807 if (gmux->gout_r[i] > (HX8279_GOUT_STB | HX8279_GOUT_SEL))
808 return dev_err_probe(dev, -EINVAL,
809 "Invalid value found in gout_r[%d]\n", i);
810 }
811
812 return 0;
813 }
814
hx8279_check_goa_config(struct hx8279 * hx,struct device * dev)815 static int hx8279_check_goa_config(struct hx8279 *hx, struct device *dev)
816 {
817 const struct hx8279_panel_desc *desc = hx->desc;
818 bool goa_odd_valid, goa_even_valid;
819 int i, num_zero, num_clr = 0;
820
821 /* Up to 4 zero values is a valid configuration. Check them all. */
822 num_zero = 1;
823 for (i = 0; i < ARRAY_SIZE(desc->goa_odd_timing); i++) {
824 if (desc->goa_odd_timing[i])
825 num_zero++;
826 }
827
828 goa_odd_valid = (num_zero != ARRAY_SIZE(desc->goa_odd_timing));
829
830 /* Up to 3 zeroes is a valid config. Check them all. */
831 num_zero = 1;
832 for (i = 0; i < ARRAY_SIZE(desc->goa_even_timing); i++) {
833 if (desc->goa_even_timing[i])
834 num_zero++;
835 }
836
837 goa_even_valid = (num_zero != ARRAY_SIZE(desc->goa_even_timing));
838
839 /* Programming one without the other would make no sense! */
840 if (goa_odd_valid != goa_even_valid)
841 return -EINVAL;
842
843 /* We know that both are either true or false now, check just one */
844 if (!goa_odd_valid)
845 hx->skip_goa_timing = true;
846
847 if (!desc->goa_unk_ba && !desc->goa_stv_lead_time_ck &&
848 !desc->goa_ckv_lead_time_ck && !desc->goa_ckv_dummy_vblank_num &&
849 !desc->goa_ckv_rise_precharge && !desc->goa_ckv_fall_precharge &&
850 !desc->goa_clr1_width_adj && !desc->goa_clr234_width_adj &&
851 !desc->goa_unk_e4 && !desc->goa_unk_e5) {
852 hx->skip_goa_config = true;
853 return 0;
854 }
855
856 if ((desc->goa_stv_lead_time_ck > HX8279_P3_GOA_STV_LEAD) ||
857 (desc->goa_ckv_lead_time_ck > HX8279_P3_GOA_CKV_LEAD) ||
858 (desc->goa_ckv_dummy_vblank_num > HX8279_P3_GOA_CKV_DUMMY))
859 return dev_err_probe(dev, -EINVAL,
860 "Invalid lead timings in GOA config\n");
861
862 /*
863 * Don't perform zero check for polarity and start position, as
864 * both pol=0 and start=0 are valid configuration values.
865 */
866 for (i = 0; i < ARRAY_SIZE(desc->goa_clr_start_pos); i++) {
867 if (desc->goa_clr_start_pos[i] < 0)
868 continue;
869 else if (desc->goa_clr_start_pos[i] > HX8279_P3_GOA_CLR_CFG_STARTPOS)
870 return dev_err_probe(dev, -EINVAL,
871 "Invalid start position for CLR%d\n", i + 1);
872 else
873 num_clr++;
874 }
875 if (!num_clr)
876 return -EINVAL;
877
878 for (i = 0; i < ARRAY_SIZE(desc->goa_clr_polarity); i++) {
879 if (num_clr < 0)
880 return -EINVAL;
881
882 if (desc->goa_clr_polarity[i] < 0)
883 continue;
884 else if (desc->goa_clr_polarity[i] > 1)
885 return dev_err_probe(dev, -EINVAL,
886 "Invalid polarity for CLR%d\n", i + 1);
887 else
888 num_clr--;
889 }
890
891 return 0;
892 }
893
hx8279_check_dig_gamma(struct hx8279 * hx,struct device * dev,const u8 * component)894 static int hx8279_check_dig_gamma(struct hx8279 *hx, struct device *dev, const u8 *component)
895 {
896 u8 gamma_high_bits[4];
897 u16 prev_val = 0;
898 int i, j, k, x;
899
900 /*
901 * The gamma values are 10 bits long and shall be incremental
902 * to form a digital gamma correction reference curve.
903 *
904 * As for the registers format: the first 24 bytes contain each the
905 * lowest 8 bits for each of the gamma level references, and the last
906 * 6 bytes contain the high two bits of 4 registers at a time, where
907 * the first two bits are relative to the last register, and the last
908 * two are relative to the first register.
909 *
910 * Another way of saying, those are the first four LOW values:
911 * DGMA1_LO = 0xb1, DGMA2_LO = 0xb2, DGMA3_LO = 0xb3, DGMA4_LO = 0xb4
912 *
913 * The high values for those four are at DGMA1_4_HI = 0xc9;
914 * ...and DGMA1_4_HI's data contains the following bits:
915 * [1:0] = DGMA4_HI, [3:2] = DGMA3_HI, [5:4] = DGMA2_HI, [7:6] = DGMA1_HI
916 */
917 for (i = 0; i < HX8279_PG_DGAMMA_NUM_HI_BYTES; i++) {
918 k = HX8279_PG_DGAMMA_NUM_LO_BYTES + i;
919 j = i * 4;
920 x = 0;
921
922 gamma_high_bits[0] = FIELD_GET(HX8279_DGAMMA_DGMA1_HI, component[k]);
923 gamma_high_bits[1] = FIELD_GET(HX8279_DGAMMA_DGMA2_HI, component[k]);
924 gamma_high_bits[2] = FIELD_GET(HX8279_DGAMMA_DGMA3_HI, component[k]);
925 gamma_high_bits[3] = FIELD_GET(HX8279_DGAMMA_DGMA4_HI, component[k]);
926
927 do {
928 u16 cur_val = component[j] | (gamma_high_bits[x] << 8);
929
930 if (cur_val < prev_val)
931 return dev_err_probe(dev, -EINVAL,
932 "Invalid dgamma values: %u < %u!\n",
933 cur_val, prev_val);
934 prev_val = cur_val;
935 j++;
936 x++;
937 } while (x < 4);
938 };
939
940 return 0;
941 }
942
hx8279_check_params(struct hx8279 * hx,struct device * dev)943 static int hx8279_check_params(struct hx8279 *hx, struct device *dev)
944 {
945 const struct hx8279_panel_desc *desc = hx->desc;
946 int ret;
947
948 /* Voltages config validation */
949 if (!desc->vgh_mv && !desc->vgl_mv && !desc->vgph_mv && !desc->vgnh_mv)
950 hx->skip_voltage_config = true;
951 else if ((desc->vgh_mv && desc->vgh_mv < HX8279_VGH_MIN_MV) ||
952 (desc->vgl_mv && desc->vgl_mv < HX8279_VGL_MIN_MV) ||
953 (desc->vgph_mv && desc->vgph_mv < HX8279_VGPNH_MIN_MV) ||
954 (desc->vgnh_mv && desc->vgnh_mv < HX8279_VGPNH_MIN_MV))
955 return -EINVAL;
956
957 /* GOA Muxing validation */
958 ret = hx8279_check_gmux_config(hx, dev);
959 if (ret)
960 return ret;
961
962 /* GOA Configuration validation */
963 ret = hx8279_check_goa_config(hx, dev);
964 if (ret)
965 return ret;
966
967 /* MIPI Configuration validation */
968 if (!desc->bta_tlpx && !desc->lhs_settle_time_by_osc25 &&
969 !desc->ths_settle_time && !desc->timing_unk_b8 &&
970 !desc->timing_unk_bc && !desc->timing_unk_d6)
971 hx->skip_mipi_timing = true;
972
973 /* ENG/Gamma Configuration validation */
974 if (desc->gamma_ctl > (HX8279_P6_GAMMA_POCGM_CTL | HX8279_P6_GAMMA_POGCMD_CTL))
975 return -EINVAL;
976
977 /* Digital Gamma values validation */
978 if (desc->dgamma) {
979 ret = hx8279_check_dig_gamma(hx, dev, desc->dgamma->r);
980 if (ret)
981 return ret;
982
983 ret = hx8279_check_dig_gamma(hx, dev, desc->dgamma->g);
984 if (ret)
985 return ret;
986
987 ret = hx8279_check_dig_gamma(hx, dev, desc->dgamma->b);
988 if (ret)
989 return ret;
990 }
991
992 return 0;
993 }
994
hx8279_probe(struct mipi_dsi_device * dsi)995 static int hx8279_probe(struct mipi_dsi_device *dsi)
996 {
997 struct device *dev = &dsi->dev;
998 struct device_node *dsi_r;
999 struct hx8279 *hx;
1000 int i, ret;
1001
1002 hx = devm_drm_panel_alloc(dev, struct hx8279, panel,
1003 &hx8279_panel_funcs, DRM_MODE_CONNECTOR_DSI);
1004 if (IS_ERR(hx))
1005 return PTR_ERR(hx);
1006
1007 ret = hx8279_init_vregs(hx, dev);
1008 if (ret)
1009 return ret;
1010
1011 hx->desc = device_get_match_data(dev);
1012 if (!hx->desc)
1013 return -ENODEV;
1014
1015 /*
1016 * In some DriverICs some or all fields may be OTP: perform a
1017 * basic configuration check before writing to help avoiding
1018 * irreparable mistakes.
1019 *
1020 * Please note that this is not perfect and will only check if
1021 * the values may be plausible; values that are wrong for a
1022 * specific display, but still plausible for DrIC config will
1023 * be accepted.
1024 */
1025 ret = hx8279_check_params(hx, dev);
1026 if (ret)
1027 return dev_err_probe(dev, ret, "Invalid DriverIC configuration\n");
1028
1029 /* The enable line may be always tied to VCCIO, so this is optional */
1030 hx->enable_gpio = devm_gpiod_get_optional(dev, "enable", GPIOD_ASIS);
1031 if (IS_ERR(hx->enable_gpio))
1032 return dev_err_probe(dev, PTR_ERR(hx->enable_gpio),
1033 "Failed to get enable GPIO\n");
1034
1035 hx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_ASIS);
1036 if (IS_ERR(hx->reset_gpio))
1037 return dev_err_probe(dev, PTR_ERR(hx->reset_gpio),
1038 "Failed to get reset GPIO\n");
1039
1040 /* If the panel is connected on two DSIs then DSI0 left, DSI1 right */
1041 dsi_r = of_graph_get_remote_node(dsi->dev.of_node, 1, -1);
1042 if (dsi_r) {
1043 const struct mipi_dsi_device_info *info = &hx->desc->dsi_info;
1044 struct mipi_dsi_host *dsi_r_host;
1045
1046 dsi_r_host = of_find_mipi_dsi_host_by_node(dsi_r);
1047 of_node_put(dsi_r);
1048 if (!dsi_r_host)
1049 return dev_err_probe(dev, -EPROBE_DEFER,
1050 "Cannot get secondary DSI host\n");
1051
1052 hx->dsi[1] = devm_mipi_dsi_device_register_full(dev, dsi_r_host, info);
1053 if (IS_ERR(hx->dsi[1]))
1054 return dev_err_probe(dev, PTR_ERR(hx->dsi[1]),
1055 "Cannot get secondary DSI node\n");
1056 mipi_dsi_set_drvdata(hx->dsi[1], hx);
1057 }
1058
1059 hx->dsi[0] = dsi;
1060 mipi_dsi_set_drvdata(dsi, hx);
1061
1062 ret = drm_panel_of_backlight(&hx->panel);
1063 if (ret)
1064 return dev_err_probe(dev, ret, "Failed to get backlight\n");
1065
1066 drm_panel_add(&hx->panel);
1067
1068 for (i = 0; i < 2; i++) {
1069 if (!hx->dsi[i])
1070 continue;
1071
1072 hx->dsi[i]->lanes = hx->desc->num_lanes;
1073 hx->dsi[i]->format = MIPI_DSI_FMT_RGB888;
1074
1075 hx->dsi[i]->mode_flags = MIPI_DSI_CLOCK_NON_CONTINUOUS |
1076 MIPI_DSI_MODE_LPM;
1077
1078 if (hx->desc->mode_data[0].is_video_mode)
1079 hx->dsi[i]->mode_flags |= MIPI_DSI_MODE_VIDEO |
1080 MIPI_DSI_MODE_VIDEO_SYNC_PULSE;
1081
1082 ret = devm_mipi_dsi_attach(dev, hx->dsi[i]);
1083 if (ret < 0) {
1084 drm_panel_remove(&hx->panel);
1085 return dev_err_probe(dev, ret,
1086 "Cannot attach to DSI%d host.\n", i);
1087 }
1088 }
1089
1090 return 0;
1091 }
1092
hx8279_remove(struct mipi_dsi_device * dsi)1093 static void hx8279_remove(struct mipi_dsi_device *dsi)
1094 {
1095 struct hx8279 *hx = mipi_dsi_get_drvdata(dsi);
1096
1097 drm_panel_remove(&hx->panel);
1098 }
1099
1100 static const struct hx8279_panel_mode aoly_sl101pm1794fog_v15_modes[] = {
1101 {
1102 .mode = {
1103 .clock = 159420,
1104 .hdisplay = 1200,
1105 .hsync_start = 1200 + 80,
1106 .hsync_end = 1200 + 80 + 60,
1107 .htotal = 1200 + 80 + 60 + 24,
1108 .vdisplay = 1920,
1109 .vsync_start = 1920 + 10,
1110 .vsync_end = 1920 + 10 + 14,
1111 .vtotal = 1920 + 10 + 14 + 4,
1112 .width_mm = 136,
1113 .height_mm = 217,
1114 .type = DRM_MODE_TYPE_DRIVER
1115 },
1116 .bpc = 8,
1117 .is_video_mode = true,
1118 },
1119 };
1120
1121 static const struct hx8279_panel_mode startek_kd070fhfid078_modes[] = {
1122 {
1123 .mode = {
1124 .clock = 156458,
1125 .hdisplay = 1200,
1126 .hsync_start = 1200 + 50,
1127 .hsync_end = 1200 + 50 + 24,
1128 .htotal = 1200 + 50 + 24 + 66,
1129 .vdisplay = 1920,
1130 .vsync_start = 1920 + 14,
1131 .vsync_end = 1920 + 14 + 2,
1132 .vtotal = 1920 + 14 + 2 + 10,
1133 .width_mm = 95,
1134 .height_mm = 151,
1135 .type = DRM_MODE_TYPE_DRIVER
1136 },
1137 .bpc = 8,
1138 .is_video_mode = true,
1139 },
1140 };
1141
1142 static const struct hx8279_goa_mux aoly_sl101pm1794fog_v15_gmux = {
1143 .gout_l = { 0x5, 0x5, 0xb, 0xb, 0x9, 0x9, 0x16, 0x16, 0xe, 0xe,
1144 0x7, 0x7, 0x26, 0x26, 0x15, 0x15, 0x1, 0x1, 0x3, 0x3 },
1145 .gout_r = { 0x6, 0x6, 0xc, 0xc, 0xa, 0xa, 0x16, 0x16, 0xe, 0xe,
1146 0x8, 0x8, 0x26, 0x26, 0x15, 0x15, 0x2, 0x2, 0x4, 0x4 },
1147 };
1148
1149 static const struct hx8279_analog_gamma aoly_sl101pm1794fog_v15_ana_gamma = {
1150 .pos = { 0x0, 0xd, 0x17, 0x26, 0x31, 0x1c, 0x2c, 0x33, 0x31,
1151 0x37, 0x37, 0x37, 0x39, 0x2e, 0x2f, 0x2f, 0x7 },
1152 .neg = { 0x0, 0xd, 0x17, 0x26, 0x31, 0x3f, 0x3f, 0x3f, 0x3f,
1153 0x37, 0x37, 0x37, 0x39, 0x2e, 0x2f, 0x2f, 0x7 },
1154 };
1155
1156 static const struct hx8279_digital_gamma aoly_sl101pm1794fog_v15_dig_gamma = {
1157 .r = { 0x0, 0x5, 0x10, 0x22, 0x36, 0x4a, 0x6c, 0x9a, 0xd7, 0x17,
1158 0x92, 0x15, 0x18, 0x8c, 0x0, 0x3a, 0x72, 0x8c, 0xa5, 0xb1,
1159 0xbe, 0xca, 0xd1, 0xd4, 0x0, 0x0, 0x16, 0xaf, 0xff, 0xff },
1160 .g = { 0x4, 0x5, 0x11, 0x24, 0x39, 0x4e, 0x72, 0xa3, 0xe1, 0x25,
1161 0xa8, 0x2e, 0x32, 0xad, 0x28, 0x63, 0x9b, 0xb5, 0xcf, 0xdb,
1162 0xe8, 0xf5, 0xfa, 0xfc, 0x0, 0x0, 0x16, 0xaf, 0xff, 0xff },
1163 .b = { 0x4, 0x4, 0xf, 0x22, 0x37, 0x4d, 0x71, 0xa2, 0xe1, 0x26,
1164 0xa9, 0x2f, 0x33, 0xac, 0x24, 0x5d, 0x94, 0xac, 0xc5, 0xd1,
1165 0xdc, 0xe8, 0xed, 0xf0, 0x0, 0x0, 0x16, 0xaf, 0xff, 0xff },
1166 };
1167
1168 static const struct hx8279_panel_desc aoly_sl101pm1794fog_v15 = {
1169 .dsi_info = {
1170 .type = "L101PM1794FOG-V15",
1171 .channel = 0,
1172 .node = NULL,
1173 },
1174 .mode_data = aoly_sl101pm1794fog_v15_modes,
1175 .num_modes = ARRAY_SIZE(aoly_sl101pm1794fog_v15_modes),
1176 .num_lanes = 4,
1177
1178 /* Driver/Module Configuration: LC Matrix voltages */
1179 .vgh_mv = 16500,
1180 .vgl_mv = 11200,
1181 .vgph_mv = 4600,
1182 .vgnh_mv = 4600,
1183
1184 /* Analog Gamma correction */
1185 .agamma = &aoly_sl101pm1794fog_v15_ana_gamma,
1186
1187 /* Gate driver On Array (GOA) Muxing */
1188 .gmux = &aoly_sl101pm1794fog_v15_gmux,
1189
1190 /* Gate driver On Array (GOA) Mux Config */
1191 .goa_unk_ba = 0xf0,
1192 .goa_odd_timing = { 0, 0, 0, 42, 0, 0 },
1193 .goa_even_timing = { 1, 42, 0, 0 },
1194 .goa_stv_lead_time_ck = 11,
1195 .goa_ckv_lead_time_ck = 7,
1196 .goa_ckv_dummy_vblank_num = 3,
1197 .goa_ckv_rise_precharge = 1,
1198 .goa_clr1_width_adj = 0,
1199 .goa_clr234_width_adj = 0,
1200 .goa_clr_polarity = { 1, 0, 0, 0 },
1201 .goa_clr_start_pos = { 8, 9, 3, 4 },
1202 .goa_unk_e4 = 0xc0,
1203 .goa_unk_e5 = 0x0d,
1204
1205 /* MIPI Configuration */
1206 .bta_tlpx = 2,
1207 .lhs_settle_time_by_osc25 = true,
1208 .ths_settle_time = 2,
1209 .timing_unk_b8 = 0xa5,
1210 .timing_unk_bc = 0x20,
1211 .timing_unk_d6 = 0x7f,
1212
1213 /* ENG/Gamma Configuration */
1214 .gamma_ctl = 0,
1215 .volt_adj = FIELD_PREP_CONST(HX8279_P6_VOLT_ADJ_VCCIFS, 3) |
1216 FIELD_PREP_CONST(HX8279_P6_VOLT_ADJ_VCCS, 3),
1217 .src_delay_time_adj_ck = 50,
1218
1219 /* Digital Gamma Adjustment */
1220 .dgamma = &aoly_sl101pm1794fog_v15_dig_gamma,
1221 };
1222
1223 static const struct hx8279_goa_mux startek_kd070fhfid078_gmux = {
1224 .gout_l = { 0xd, 0xd, 0x6, 0x6, 0x8, 0x8, 0xa, 0xa, 0xc, 0xc,
1225 0x0, 0x0, 0xe, 0xe, 0x1, 0x1, 0x4, 0x4, 0x0, 0x0 },
1226 .gout_r = { 0xd, 0xd, 0x5, 0x5, 0x7, 0x7, 0x9, 0x9, 0xb, 0xb,
1227 0x0, 0x0, 0xe, 0xe, 0x1, 0x1, 0x3, 0x3, 0x0, 0x0 },
1228 };
1229
1230 static const struct hx8279_panel_desc startek_kd070fhfid078 = {
1231 .dsi_info = {
1232 .type = "KD070FHFID078",
1233 .channel = 0,
1234 .node = NULL,
1235 },
1236 .mode_data = startek_kd070fhfid078_modes,
1237 .num_modes = ARRAY_SIZE(startek_kd070fhfid078_modes),
1238 .num_lanes = 4,
1239
1240 /* Driver/Module Configuration: LC Matrix voltages */
1241 .vgh_mv = 18000,
1242 .vgl_mv = 12100,
1243 .vgph_mv = 5500,
1244 .vgnh_mv = 5500,
1245
1246 /* Gate driver On Array (GOA) Mux Config */
1247 .gmux = &startek_kd070fhfid078_gmux,
1248
1249 /* Gate driver On Array (GOA) Configuration */
1250 .goa_unk_ba = 0xf0,
1251 .goa_stv_lead_time_ck = 7,
1252 .goa_ckv_lead_time_ck = 3,
1253 .goa_ckv_dummy_vblank_num = 1,
1254 .goa_ckv_rise_precharge = 0,
1255 .goa_ckv_fall_precharge = 0,
1256 .goa_clr1_width_adj = 1,
1257 .goa_clr234_width_adj = 5,
1258 .goa_clr_polarity = { 0, 1, -1, -1 },
1259 .goa_clr_start_pos = { 5, 10, -1, -1 },
1260 .goa_unk_e4 = 0xc0,
1261 .goa_unk_e5 = 0x00,
1262
1263 /* MIPI Configuration */
1264 .bta_tlpx = 2,
1265 .lhs_settle_time_by_osc25 = true,
1266 .ths_settle_time = 2,
1267 .timing_unk_b8 = 0x7f,
1268 .timing_unk_bc = 0x20,
1269 .timing_unk_d6 = 0x7f,
1270
1271 /* ENG/Gamma Configuration */
1272 .gamma_ctl = FIELD_PREP_CONST(HX8279_P6_GAMMA_POCGM_CTL, 1) |
1273 FIELD_PREP_CONST(HX8279_P6_GAMMA_POGCMD_CTL, 1),
1274 .src_delay_time_adj_ck = 72,
1275 };
1276
1277 static const struct of_device_id hx8279_of_match[] = {
1278 { .compatible = "aoly,sl101pm1794fog-v15", .data = &aoly_sl101pm1794fog_v15 },
1279 { .compatible = "startek,kd070fhfid078", .data = &startek_kd070fhfid078 },
1280 { /* sentinel */ }
1281 };
1282 MODULE_DEVICE_TABLE(of, hx8279_of_match);
1283
1284 static struct mipi_dsi_driver hx8279_driver = {
1285 .probe = hx8279_probe,
1286 .remove = hx8279_remove,
1287 .driver = {
1288 .name = "panel-himax-hx8279",
1289 .of_match_table = hx8279_of_match,
1290 },
1291 };
1292 module_mipi_dsi_driver(hx8279_driver);
1293
1294 MODULE_AUTHOR("AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>");
1295 MODULE_DESCRIPTION("Himax HX8279 DriverIC panels driver");
1296 MODULE_LICENSE("GPL");
1297