xref: /linux/drivers/gpu/drm/panel/panel-himax-hx8279.c (revision e78f70bad29c5ae1e1076698b690b15794e9b81e)
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 
243 static inline struct hx8279 *to_hx8279(struct drm_panel *panel)
244 {
245 	return container_of(panel, struct hx8279, panel);
246 }
247 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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