162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0+
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Copyright (C) 2019, Amarula Solutions.
462306a36Sopenharmony_ci * Author: Jagan Teki <jagan@amarulasolutions.com>
562306a36Sopenharmony_ci */
662306a36Sopenharmony_ci
762306a36Sopenharmony_ci#include <drm/drm_mipi_dsi.h>
862306a36Sopenharmony_ci#include <drm/drm_modes.h>
962306a36Sopenharmony_ci#include <drm/drm_panel.h>
1062306a36Sopenharmony_ci
1162306a36Sopenharmony_ci#include <linux/bitfield.h>
1262306a36Sopenharmony_ci#include <linux/gpio/consumer.h>
1362306a36Sopenharmony_ci#include <linux/delay.h>
1462306a36Sopenharmony_ci#include <linux/module.h>
1562306a36Sopenharmony_ci#include <linux/of.h>
1662306a36Sopenharmony_ci#include <linux/regulator/consumer.h>
1762306a36Sopenharmony_ci
1862306a36Sopenharmony_ci#include <video/mipi_display.h>
1962306a36Sopenharmony_ci
2062306a36Sopenharmony_ci/* Command2 BKx selection command */
2162306a36Sopenharmony_ci#define DSI_CMD2BKX_SEL			0xFF
2262306a36Sopenharmony_ci#define DSI_CMD1			0
2362306a36Sopenharmony_ci#define DSI_CMD2			BIT(4)
2462306a36Sopenharmony_ci#define DSI_CMD2BK_MASK			GENMASK(3, 0)
2562306a36Sopenharmony_ci
2662306a36Sopenharmony_ci/* Command2, BK0 commands */
2762306a36Sopenharmony_ci#define DSI_CMD2_BK0_PVGAMCTRL		0xB0 /* Positive Voltage Gamma Control */
2862306a36Sopenharmony_ci#define DSI_CMD2_BK0_NVGAMCTRL		0xB1 /* Negative Voltage Gamma Control */
2962306a36Sopenharmony_ci#define DSI_CMD2_BK0_LNESET		0xC0 /* Display Line setting */
3062306a36Sopenharmony_ci#define DSI_CMD2_BK0_PORCTRL		0xC1 /* Porch control */
3162306a36Sopenharmony_ci#define DSI_CMD2_BK0_INVSEL		0xC2 /* Inversion selection, Frame Rate Control */
3262306a36Sopenharmony_ci
3362306a36Sopenharmony_ci/* Command2, BK1 commands */
3462306a36Sopenharmony_ci#define DSI_CMD2_BK1_VRHS		0xB0 /* Vop amplitude setting */
3562306a36Sopenharmony_ci#define DSI_CMD2_BK1_VCOM		0xB1 /* VCOM amplitude setting */
3662306a36Sopenharmony_ci#define DSI_CMD2_BK1_VGHSS		0xB2 /* VGH Voltage setting */
3762306a36Sopenharmony_ci#define DSI_CMD2_BK1_TESTCMD		0xB3 /* TEST Command Setting */
3862306a36Sopenharmony_ci#define DSI_CMD2_BK1_VGLS		0xB5 /* VGL Voltage setting */
3962306a36Sopenharmony_ci#define DSI_CMD2_BK1_PWCTLR1		0xB7 /* Power Control 1 */
4062306a36Sopenharmony_ci#define DSI_CMD2_BK1_PWCTLR2		0xB8 /* Power Control 2 */
4162306a36Sopenharmony_ci#define DSI_CMD2_BK1_SPD1		0xC1 /* Source pre_drive timing set1 */
4262306a36Sopenharmony_ci#define DSI_CMD2_BK1_SPD2		0xC2 /* Source EQ2 Setting */
4362306a36Sopenharmony_ci#define DSI_CMD2_BK1_MIPISET1		0xD0 /* MIPI Setting 1 */
4462306a36Sopenharmony_ci
4562306a36Sopenharmony_ci/* Command2, BK0 bytes */
4662306a36Sopenharmony_ci#define DSI_CMD2_BK0_GAMCTRL_AJ_MASK	GENMASK(7, 6)
4762306a36Sopenharmony_ci#define DSI_CMD2_BK0_GAMCTRL_VC0_MASK	GENMASK(3, 0)
4862306a36Sopenharmony_ci#define DSI_CMD2_BK0_GAMCTRL_VC4_MASK	GENMASK(5, 0)
4962306a36Sopenharmony_ci#define DSI_CMD2_BK0_GAMCTRL_VC8_MASK	GENMASK(5, 0)
5062306a36Sopenharmony_ci#define DSI_CMD2_BK0_GAMCTRL_VC16_MASK	GENMASK(4, 0)
5162306a36Sopenharmony_ci#define DSI_CMD2_BK0_GAMCTRL_VC24_MASK	GENMASK(4, 0)
5262306a36Sopenharmony_ci#define DSI_CMD2_BK0_GAMCTRL_VC52_MASK	GENMASK(3, 0)
5362306a36Sopenharmony_ci#define DSI_CMD2_BK0_GAMCTRL_VC80_MASK	GENMASK(5, 0)
5462306a36Sopenharmony_ci#define DSI_CMD2_BK0_GAMCTRL_VC108_MASK	GENMASK(3, 0)
5562306a36Sopenharmony_ci#define DSI_CMD2_BK0_GAMCTRL_VC147_MASK	GENMASK(3, 0)
5662306a36Sopenharmony_ci#define DSI_CMD2_BK0_GAMCTRL_VC175_MASK	GENMASK(5, 0)
5762306a36Sopenharmony_ci#define DSI_CMD2_BK0_GAMCTRL_VC203_MASK	GENMASK(3, 0)
5862306a36Sopenharmony_ci#define DSI_CMD2_BK0_GAMCTRL_VC231_MASK	GENMASK(4, 0)
5962306a36Sopenharmony_ci#define DSI_CMD2_BK0_GAMCTRL_VC239_MASK	GENMASK(4, 0)
6062306a36Sopenharmony_ci#define DSI_CMD2_BK0_GAMCTRL_VC247_MASK	GENMASK(5, 0)
6162306a36Sopenharmony_ci#define DSI_CMD2_BK0_GAMCTRL_VC251_MASK	GENMASK(5, 0)
6262306a36Sopenharmony_ci#define DSI_CMD2_BK0_GAMCTRL_VC255_MASK	GENMASK(4, 0)
6362306a36Sopenharmony_ci#define DSI_CMD2_BK0_LNESET_LINE_MASK	GENMASK(6, 0)
6462306a36Sopenharmony_ci#define DSI_CMD2_BK0_LNESET_LDE_EN	BIT(7)
6562306a36Sopenharmony_ci#define DSI_CMD2_BK0_LNESET_LINEDELTA	GENMASK(1, 0)
6662306a36Sopenharmony_ci#define DSI_CMD2_BK0_PORCTRL_VBP_MASK	GENMASK(7, 0)
6762306a36Sopenharmony_ci#define DSI_CMD2_BK0_PORCTRL_VFP_MASK	GENMASK(7, 0)
6862306a36Sopenharmony_ci#define DSI_CMD2_BK0_INVSEL_ONES_MASK	GENMASK(5, 4)
6962306a36Sopenharmony_ci#define DSI_CMD2_BK0_INVSEL_NLINV_MASK	GENMASK(2, 0)
7062306a36Sopenharmony_ci#define DSI_CMD2_BK0_INVSEL_RTNI_MASK	GENMASK(4, 0)
7162306a36Sopenharmony_ci
7262306a36Sopenharmony_ci/* Command2, BK1 bytes */
7362306a36Sopenharmony_ci#define DSI_CMD2_BK1_VRHA_MASK		GENMASK(7, 0)
7462306a36Sopenharmony_ci#define DSI_CMD2_BK1_VCOM_MASK		GENMASK(7, 0)
7562306a36Sopenharmony_ci#define DSI_CMD2_BK1_VGHSS_MASK		GENMASK(3, 0)
7662306a36Sopenharmony_ci#define DSI_CMD2_BK1_TESTCMD_VAL	BIT(7)
7762306a36Sopenharmony_ci#define DSI_CMD2_BK1_VGLS_ONES		BIT(6)
7862306a36Sopenharmony_ci#define DSI_CMD2_BK1_VGLS_MASK		GENMASK(3, 0)
7962306a36Sopenharmony_ci#define DSI_CMD2_BK1_PWRCTRL1_AP_MASK	GENMASK(7, 6)
8062306a36Sopenharmony_ci#define DSI_CMD2_BK1_PWRCTRL1_APIS_MASK	GENMASK(3, 2)
8162306a36Sopenharmony_ci#define DSI_CMD2_BK1_PWRCTRL1_APOS_MASK	GENMASK(1, 0)
8262306a36Sopenharmony_ci#define DSI_CMD2_BK1_PWRCTRL2_AVDD_MASK	GENMASK(5, 4)
8362306a36Sopenharmony_ci#define DSI_CMD2_BK1_PWRCTRL2_AVCL_MASK	GENMASK(1, 0)
8462306a36Sopenharmony_ci#define DSI_CMD2_BK1_SPD1_ONES_MASK	GENMASK(6, 4)
8562306a36Sopenharmony_ci#define DSI_CMD2_BK1_SPD1_T2D_MASK	GENMASK(3, 0)
8662306a36Sopenharmony_ci#define DSI_CMD2_BK1_SPD2_ONES_MASK	GENMASK(6, 4)
8762306a36Sopenharmony_ci#define DSI_CMD2_BK1_SPD2_T3D_MASK	GENMASK(3, 0)
8862306a36Sopenharmony_ci#define DSI_CMD2_BK1_MIPISET1_ONES	BIT(7)
8962306a36Sopenharmony_ci#define DSI_CMD2_BK1_MIPISET1_EOT_EN	BIT(3)
9062306a36Sopenharmony_ci
9162306a36Sopenharmony_ci#define CFIELD_PREP(_mask, _val)					\
9262306a36Sopenharmony_ci	(((typeof(_mask))(_val) << (__builtin_ffsll(_mask) - 1)) & (_mask))
9362306a36Sopenharmony_ci
9462306a36Sopenharmony_cienum op_bias {
9562306a36Sopenharmony_ci	OP_BIAS_OFF = 0,
9662306a36Sopenharmony_ci	OP_BIAS_MIN,
9762306a36Sopenharmony_ci	OP_BIAS_MIDDLE,
9862306a36Sopenharmony_ci	OP_BIAS_MAX
9962306a36Sopenharmony_ci};
10062306a36Sopenharmony_ci
10162306a36Sopenharmony_cistruct st7701;
10262306a36Sopenharmony_ci
10362306a36Sopenharmony_cistruct st7701_panel_desc {
10462306a36Sopenharmony_ci	const struct drm_display_mode *mode;
10562306a36Sopenharmony_ci	unsigned int lanes;
10662306a36Sopenharmony_ci	enum mipi_dsi_pixel_format format;
10762306a36Sopenharmony_ci	unsigned int panel_sleep_delay;
10862306a36Sopenharmony_ci
10962306a36Sopenharmony_ci	/* TFT matrix driver configuration, panel specific. */
11062306a36Sopenharmony_ci	const u8	pv_gamma[16];	/* Positive voltage gamma control */
11162306a36Sopenharmony_ci	const u8	nv_gamma[16];	/* Negative voltage gamma control */
11262306a36Sopenharmony_ci	const u8	nlinv;		/* Inversion selection */
11362306a36Sopenharmony_ci	const u32	vop_uv;		/* Vop in uV */
11462306a36Sopenharmony_ci	const u32	vcom_uv;	/* Vcom in uV */
11562306a36Sopenharmony_ci	const u16	vgh_mv;		/* Vgh in mV */
11662306a36Sopenharmony_ci	const s16	vgl_mv;		/* Vgl in mV */
11762306a36Sopenharmony_ci	const u16	avdd_mv;	/* Avdd in mV */
11862306a36Sopenharmony_ci	const s16	avcl_mv;	/* Avcl in mV */
11962306a36Sopenharmony_ci	const enum op_bias	gamma_op_bias;
12062306a36Sopenharmony_ci	const enum op_bias	input_op_bias;
12162306a36Sopenharmony_ci	const enum op_bias	output_op_bias;
12262306a36Sopenharmony_ci	const u16	t2d_ns;		/* T2D in ns */
12362306a36Sopenharmony_ci	const u16	t3d_ns;		/* T3D in ns */
12462306a36Sopenharmony_ci	const bool	eot_en;
12562306a36Sopenharmony_ci
12662306a36Sopenharmony_ci	/* GIP sequence, fully custom and undocumented. */
12762306a36Sopenharmony_ci	void		(*gip_sequence)(struct st7701 *st7701);
12862306a36Sopenharmony_ci};
12962306a36Sopenharmony_ci
13062306a36Sopenharmony_cistruct st7701 {
13162306a36Sopenharmony_ci	struct drm_panel panel;
13262306a36Sopenharmony_ci	struct mipi_dsi_device *dsi;
13362306a36Sopenharmony_ci	const struct st7701_panel_desc *desc;
13462306a36Sopenharmony_ci
13562306a36Sopenharmony_ci	struct regulator_bulk_data supplies[2];
13662306a36Sopenharmony_ci	struct gpio_desc *reset;
13762306a36Sopenharmony_ci	unsigned int sleep_delay;
13862306a36Sopenharmony_ci	enum drm_panel_orientation orientation;
13962306a36Sopenharmony_ci};
14062306a36Sopenharmony_ci
14162306a36Sopenharmony_cistatic inline struct st7701 *panel_to_st7701(struct drm_panel *panel)
14262306a36Sopenharmony_ci{
14362306a36Sopenharmony_ci	return container_of(panel, struct st7701, panel);
14462306a36Sopenharmony_ci}
14562306a36Sopenharmony_ci
14662306a36Sopenharmony_cistatic inline int st7701_dsi_write(struct st7701 *st7701, const void *seq,
14762306a36Sopenharmony_ci				   size_t len)
14862306a36Sopenharmony_ci{
14962306a36Sopenharmony_ci	return mipi_dsi_dcs_write_buffer(st7701->dsi, seq, len);
15062306a36Sopenharmony_ci}
15162306a36Sopenharmony_ci
15262306a36Sopenharmony_ci#define ST7701_DSI(st7701, seq...)				\
15362306a36Sopenharmony_ci	{							\
15462306a36Sopenharmony_ci		const u8 d[] = { seq };				\
15562306a36Sopenharmony_ci		st7701_dsi_write(st7701, d, ARRAY_SIZE(d));	\
15662306a36Sopenharmony_ci	}
15762306a36Sopenharmony_ci
15862306a36Sopenharmony_cistatic u8 st7701_vgls_map(struct st7701 *st7701)
15962306a36Sopenharmony_ci{
16062306a36Sopenharmony_ci	const struct st7701_panel_desc *desc = st7701->desc;
16162306a36Sopenharmony_ci	struct {
16262306a36Sopenharmony_ci		s32	vgl;
16362306a36Sopenharmony_ci		u8	val;
16462306a36Sopenharmony_ci	} map[16] = {
16562306a36Sopenharmony_ci		{ -7060, 0x0 }, { -7470, 0x1 },
16662306a36Sopenharmony_ci		{ -7910, 0x2 }, { -8140, 0x3 },
16762306a36Sopenharmony_ci		{ -8650, 0x4 }, { -8920, 0x5 },
16862306a36Sopenharmony_ci		{ -9210, 0x6 }, { -9510, 0x7 },
16962306a36Sopenharmony_ci		{ -9830, 0x8 }, { -10170, 0x9 },
17062306a36Sopenharmony_ci		{ -10530, 0xa }, { -10910, 0xb },
17162306a36Sopenharmony_ci		{ -11310, 0xc }, { -11730, 0xd },
17262306a36Sopenharmony_ci		{ -12200, 0xe }, { -12690, 0xf }
17362306a36Sopenharmony_ci	};
17462306a36Sopenharmony_ci	int i;
17562306a36Sopenharmony_ci
17662306a36Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(map); i++)
17762306a36Sopenharmony_ci		if (desc->vgl_mv == map[i].vgl)
17862306a36Sopenharmony_ci			return map[i].val;
17962306a36Sopenharmony_ci
18062306a36Sopenharmony_ci	return 0;
18162306a36Sopenharmony_ci}
18262306a36Sopenharmony_ci
18362306a36Sopenharmony_cistatic void st7701_switch_cmd_bkx(struct st7701 *st7701, bool cmd2, u8 bkx)
18462306a36Sopenharmony_ci{
18562306a36Sopenharmony_ci	u8 val;
18662306a36Sopenharmony_ci
18762306a36Sopenharmony_ci	if (cmd2)
18862306a36Sopenharmony_ci		val = DSI_CMD2 | FIELD_PREP(DSI_CMD2BK_MASK, bkx);
18962306a36Sopenharmony_ci	else
19062306a36Sopenharmony_ci		val = DSI_CMD1;
19162306a36Sopenharmony_ci
19262306a36Sopenharmony_ci	ST7701_DSI(st7701, DSI_CMD2BKX_SEL, 0x77, 0x01, 0x00, 0x00, val);
19362306a36Sopenharmony_ci}
19462306a36Sopenharmony_ci
19562306a36Sopenharmony_cistatic void st7701_init_sequence(struct st7701 *st7701)
19662306a36Sopenharmony_ci{
19762306a36Sopenharmony_ci	const struct st7701_panel_desc *desc = st7701->desc;
19862306a36Sopenharmony_ci	const struct drm_display_mode *mode = desc->mode;
19962306a36Sopenharmony_ci	const u8 linecount8 = mode->vdisplay / 8;
20062306a36Sopenharmony_ci	const u8 linecountrem2 = (mode->vdisplay % 8) / 2;
20162306a36Sopenharmony_ci
20262306a36Sopenharmony_ci	ST7701_DSI(st7701, MIPI_DCS_SOFT_RESET, 0x00);
20362306a36Sopenharmony_ci
20462306a36Sopenharmony_ci	/* We need to wait 5ms before sending new commands */
20562306a36Sopenharmony_ci	msleep(5);
20662306a36Sopenharmony_ci
20762306a36Sopenharmony_ci	ST7701_DSI(st7701, MIPI_DCS_EXIT_SLEEP_MODE, 0x00);
20862306a36Sopenharmony_ci
20962306a36Sopenharmony_ci	msleep(st7701->sleep_delay);
21062306a36Sopenharmony_ci
21162306a36Sopenharmony_ci	/* Command2, BK0 */
21262306a36Sopenharmony_ci	st7701_switch_cmd_bkx(st7701, true, 0);
21362306a36Sopenharmony_ci
21462306a36Sopenharmony_ci	mipi_dsi_dcs_write(st7701->dsi, DSI_CMD2_BK0_PVGAMCTRL,
21562306a36Sopenharmony_ci			   desc->pv_gamma, ARRAY_SIZE(desc->pv_gamma));
21662306a36Sopenharmony_ci	mipi_dsi_dcs_write(st7701->dsi, DSI_CMD2_BK0_NVGAMCTRL,
21762306a36Sopenharmony_ci			   desc->nv_gamma, ARRAY_SIZE(desc->nv_gamma));
21862306a36Sopenharmony_ci	/*
21962306a36Sopenharmony_ci	 * Vertical line count configuration:
22062306a36Sopenharmony_ci	 * Line[6:0]: select number of vertical lines of the TFT matrix in
22162306a36Sopenharmony_ci	 *            multiples of 8 lines
22262306a36Sopenharmony_ci	 * LDE_EN: enable sub-8-line granularity line count
22362306a36Sopenharmony_ci	 * Line_delta[1:0]: add 0/2/4/6 extra lines to line count selected
22462306a36Sopenharmony_ci	 *                  using Line[6:0]
22562306a36Sopenharmony_ci	 *
22662306a36Sopenharmony_ci	 * Total number of vertical lines:
22762306a36Sopenharmony_ci	 * LN = ((Line[6:0] + 1) * 8) + (LDE_EN ? Line_delta[1:0] * 2 : 0)
22862306a36Sopenharmony_ci	 */
22962306a36Sopenharmony_ci	ST7701_DSI(st7701, DSI_CMD2_BK0_LNESET,
23062306a36Sopenharmony_ci		   FIELD_PREP(DSI_CMD2_BK0_LNESET_LINE_MASK, linecount8 - 1) |
23162306a36Sopenharmony_ci		   (linecountrem2 ? DSI_CMD2_BK0_LNESET_LDE_EN : 0),
23262306a36Sopenharmony_ci		   FIELD_PREP(DSI_CMD2_BK0_LNESET_LINEDELTA, linecountrem2));
23362306a36Sopenharmony_ci	ST7701_DSI(st7701, DSI_CMD2_BK0_PORCTRL,
23462306a36Sopenharmony_ci		   FIELD_PREP(DSI_CMD2_BK0_PORCTRL_VBP_MASK,
23562306a36Sopenharmony_ci			      mode->vtotal - mode->vsync_end),
23662306a36Sopenharmony_ci		   FIELD_PREP(DSI_CMD2_BK0_PORCTRL_VFP_MASK,
23762306a36Sopenharmony_ci			      mode->vsync_start - mode->vdisplay));
23862306a36Sopenharmony_ci	/*
23962306a36Sopenharmony_ci	 * Horizontal pixel count configuration:
24062306a36Sopenharmony_ci	 * PCLK = 512 + (RTNI[4:0] * 16)
24162306a36Sopenharmony_ci	 * The PCLK is number of pixel clock per line, which matches
24262306a36Sopenharmony_ci	 * mode htotal. The minimum is 512 PCLK.
24362306a36Sopenharmony_ci	 */
24462306a36Sopenharmony_ci	ST7701_DSI(st7701, DSI_CMD2_BK0_INVSEL,
24562306a36Sopenharmony_ci		   DSI_CMD2_BK0_INVSEL_ONES_MASK |
24662306a36Sopenharmony_ci		   FIELD_PREP(DSI_CMD2_BK0_INVSEL_NLINV_MASK, desc->nlinv),
24762306a36Sopenharmony_ci		   FIELD_PREP(DSI_CMD2_BK0_INVSEL_RTNI_MASK,
24862306a36Sopenharmony_ci			      (clamp((u32)mode->htotal, 512U, 1008U) - 512) / 16));
24962306a36Sopenharmony_ci
25062306a36Sopenharmony_ci	/* Command2, BK1 */
25162306a36Sopenharmony_ci	st7701_switch_cmd_bkx(st7701, true, 1);
25262306a36Sopenharmony_ci
25362306a36Sopenharmony_ci	/* Vop = 3.5375V + (VRHA[7:0] * 0.0125V) */
25462306a36Sopenharmony_ci	ST7701_DSI(st7701, DSI_CMD2_BK1_VRHS,
25562306a36Sopenharmony_ci		   FIELD_PREP(DSI_CMD2_BK1_VRHA_MASK,
25662306a36Sopenharmony_ci			      DIV_ROUND_CLOSEST(desc->vop_uv - 3537500, 12500)));
25762306a36Sopenharmony_ci
25862306a36Sopenharmony_ci	/* Vcom = 0.1V + (VCOM[7:0] * 0.0125V) */
25962306a36Sopenharmony_ci	ST7701_DSI(st7701, DSI_CMD2_BK1_VCOM,
26062306a36Sopenharmony_ci		   FIELD_PREP(DSI_CMD2_BK1_VCOM_MASK,
26162306a36Sopenharmony_ci			      DIV_ROUND_CLOSEST(desc->vcom_uv - 100000, 12500)));
26262306a36Sopenharmony_ci
26362306a36Sopenharmony_ci	/* Vgh = 11.5V + (VGHSS[7:0] * 0.5V) */
26462306a36Sopenharmony_ci	ST7701_DSI(st7701, DSI_CMD2_BK1_VGHSS,
26562306a36Sopenharmony_ci		   FIELD_PREP(DSI_CMD2_BK1_VGHSS_MASK,
26662306a36Sopenharmony_ci			      DIV_ROUND_CLOSEST(clamp(desc->vgh_mv,
26762306a36Sopenharmony_ci						      (u16)11500,
26862306a36Sopenharmony_ci						      (u16)17000) - 11500,
26962306a36Sopenharmony_ci						500)));
27062306a36Sopenharmony_ci
27162306a36Sopenharmony_ci	ST7701_DSI(st7701, DSI_CMD2_BK1_TESTCMD, DSI_CMD2_BK1_TESTCMD_VAL);
27262306a36Sopenharmony_ci
27362306a36Sopenharmony_ci	/* Vgl is non-linear */
27462306a36Sopenharmony_ci	ST7701_DSI(st7701, DSI_CMD2_BK1_VGLS,
27562306a36Sopenharmony_ci		   DSI_CMD2_BK1_VGLS_ONES |
27662306a36Sopenharmony_ci		   FIELD_PREP(DSI_CMD2_BK1_VGLS_MASK, st7701_vgls_map(st7701)));
27762306a36Sopenharmony_ci
27862306a36Sopenharmony_ci	ST7701_DSI(st7701, DSI_CMD2_BK1_PWCTLR1,
27962306a36Sopenharmony_ci		   FIELD_PREP(DSI_CMD2_BK1_PWRCTRL1_AP_MASK,
28062306a36Sopenharmony_ci			      desc->gamma_op_bias) |
28162306a36Sopenharmony_ci		   FIELD_PREP(DSI_CMD2_BK1_PWRCTRL1_APIS_MASK,
28262306a36Sopenharmony_ci			      desc->input_op_bias) |
28362306a36Sopenharmony_ci		   FIELD_PREP(DSI_CMD2_BK1_PWRCTRL1_APOS_MASK,
28462306a36Sopenharmony_ci			      desc->output_op_bias));
28562306a36Sopenharmony_ci
28662306a36Sopenharmony_ci	/* Avdd = 6.2V + (AVDD[1:0] * 0.2V) , Avcl = -4.4V - (AVCL[1:0] * 0.2V) */
28762306a36Sopenharmony_ci	ST7701_DSI(st7701, DSI_CMD2_BK1_PWCTLR2,
28862306a36Sopenharmony_ci		   FIELD_PREP(DSI_CMD2_BK1_PWRCTRL2_AVDD_MASK,
28962306a36Sopenharmony_ci			      DIV_ROUND_CLOSEST(desc->avdd_mv - 6200, 200)) |
29062306a36Sopenharmony_ci		   FIELD_PREP(DSI_CMD2_BK1_PWRCTRL2_AVCL_MASK,
29162306a36Sopenharmony_ci			      DIV_ROUND_CLOSEST(-4400 - desc->avcl_mv, 200)));
29262306a36Sopenharmony_ci
29362306a36Sopenharmony_ci	/* T2D = 0.2us * T2D[3:0] */
29462306a36Sopenharmony_ci	ST7701_DSI(st7701, DSI_CMD2_BK1_SPD1,
29562306a36Sopenharmony_ci		   DSI_CMD2_BK1_SPD1_ONES_MASK |
29662306a36Sopenharmony_ci		   FIELD_PREP(DSI_CMD2_BK1_SPD1_T2D_MASK,
29762306a36Sopenharmony_ci			      DIV_ROUND_CLOSEST(desc->t2d_ns, 200)));
29862306a36Sopenharmony_ci
29962306a36Sopenharmony_ci	/* T3D = 4us + (0.8us * T3D[3:0]) */
30062306a36Sopenharmony_ci	ST7701_DSI(st7701, DSI_CMD2_BK1_SPD2,
30162306a36Sopenharmony_ci		   DSI_CMD2_BK1_SPD2_ONES_MASK |
30262306a36Sopenharmony_ci		   FIELD_PREP(DSI_CMD2_BK1_SPD2_T3D_MASK,
30362306a36Sopenharmony_ci			      DIV_ROUND_CLOSEST(desc->t3d_ns - 4000, 800)));
30462306a36Sopenharmony_ci
30562306a36Sopenharmony_ci	ST7701_DSI(st7701, DSI_CMD2_BK1_MIPISET1,
30662306a36Sopenharmony_ci		   DSI_CMD2_BK1_MIPISET1_ONES |
30762306a36Sopenharmony_ci		   (desc->eot_en ? DSI_CMD2_BK1_MIPISET1_EOT_EN : 0));
30862306a36Sopenharmony_ci}
30962306a36Sopenharmony_ci
31062306a36Sopenharmony_cistatic void ts8550b_gip_sequence(struct st7701 *st7701)
31162306a36Sopenharmony_ci{
31262306a36Sopenharmony_ci	/**
31362306a36Sopenharmony_ci	 * ST7701_SPEC_V1.2 is unable to provide enough information above this
31462306a36Sopenharmony_ci	 * specific command sequence, so grab the same from vendor BSP driver.
31562306a36Sopenharmony_ci	 */
31662306a36Sopenharmony_ci	ST7701_DSI(st7701, 0xE0, 0x00, 0x00, 0x02);
31762306a36Sopenharmony_ci	ST7701_DSI(st7701, 0xE1, 0x0B, 0x00, 0x0D, 0x00, 0x0C, 0x00, 0x0E,
31862306a36Sopenharmony_ci		   0x00, 0x00, 0x44, 0x44);
31962306a36Sopenharmony_ci	ST7701_DSI(st7701, 0xE2, 0x33, 0x33, 0x44, 0x44, 0x64, 0x00, 0x66,
32062306a36Sopenharmony_ci		   0x00, 0x65, 0x00, 0x67, 0x00, 0x00);
32162306a36Sopenharmony_ci	ST7701_DSI(st7701, 0xE3, 0x00, 0x00, 0x33, 0x33);
32262306a36Sopenharmony_ci	ST7701_DSI(st7701, 0xE4, 0x44, 0x44);
32362306a36Sopenharmony_ci	ST7701_DSI(st7701, 0xE5, 0x0C, 0x78, 0x3C, 0xA0, 0x0E, 0x78, 0x3C,
32462306a36Sopenharmony_ci		   0xA0, 0x10, 0x78, 0x3C, 0xA0, 0x12, 0x78, 0x3C, 0xA0);
32562306a36Sopenharmony_ci	ST7701_DSI(st7701, 0xE6, 0x00, 0x00, 0x33, 0x33);
32662306a36Sopenharmony_ci	ST7701_DSI(st7701, 0xE7, 0x44, 0x44);
32762306a36Sopenharmony_ci	ST7701_DSI(st7701, 0xE8, 0x0D, 0x78, 0x3C, 0xA0, 0x0F, 0x78, 0x3C,
32862306a36Sopenharmony_ci		   0xA0, 0x11, 0x78, 0x3C, 0xA0, 0x13, 0x78, 0x3C, 0xA0);
32962306a36Sopenharmony_ci	ST7701_DSI(st7701, 0xEB, 0x02, 0x02, 0x39, 0x39, 0xEE, 0x44, 0x00);
33062306a36Sopenharmony_ci	ST7701_DSI(st7701, 0xEC, 0x00, 0x00);
33162306a36Sopenharmony_ci	ST7701_DSI(st7701, 0xED, 0xFF, 0xF1, 0x04, 0x56, 0x72, 0x3F, 0xFF,
33262306a36Sopenharmony_ci		   0xFF, 0xFF, 0xFF, 0xF3, 0x27, 0x65, 0x40, 0x1F, 0xFF);
33362306a36Sopenharmony_ci}
33462306a36Sopenharmony_ci
33562306a36Sopenharmony_cistatic void dmt028vghmcmi_1a_gip_sequence(struct st7701 *st7701)
33662306a36Sopenharmony_ci{
33762306a36Sopenharmony_ci	ST7701_DSI(st7701, 0xEE, 0x42);
33862306a36Sopenharmony_ci	ST7701_DSI(st7701, 0xE0, 0x00, 0x00, 0x02);
33962306a36Sopenharmony_ci
34062306a36Sopenharmony_ci	ST7701_DSI(st7701, 0xE1,
34162306a36Sopenharmony_ci		   0x04, 0xA0, 0x06, 0xA0,
34262306a36Sopenharmony_ci			   0x05, 0xA0, 0x07, 0xA0,
34362306a36Sopenharmony_ci			   0x00, 0x44, 0x44);
34462306a36Sopenharmony_ci	ST7701_DSI(st7701, 0xE2,
34562306a36Sopenharmony_ci		   0x00, 0x00, 0x00, 0x00,
34662306a36Sopenharmony_ci			   0x00, 0x00, 0x00, 0x00,
34762306a36Sopenharmony_ci			   0x00, 0x00, 0x00, 0x00);
34862306a36Sopenharmony_ci	ST7701_DSI(st7701, 0xE3,
34962306a36Sopenharmony_ci		   0x00, 0x00, 0x22, 0x22);
35062306a36Sopenharmony_ci	ST7701_DSI(st7701, 0xE4, 0x44, 0x44);
35162306a36Sopenharmony_ci	ST7701_DSI(st7701, 0xE5,
35262306a36Sopenharmony_ci		   0x0C, 0x90, 0xA0, 0xA0,
35362306a36Sopenharmony_ci			   0x0E, 0x92, 0xA0, 0xA0,
35462306a36Sopenharmony_ci			   0x08, 0x8C, 0xA0, 0xA0,
35562306a36Sopenharmony_ci			   0x0A, 0x8E, 0xA0, 0xA0);
35662306a36Sopenharmony_ci	ST7701_DSI(st7701, 0xE6,
35762306a36Sopenharmony_ci		   0x00, 0x00, 0x22, 0x22);
35862306a36Sopenharmony_ci	ST7701_DSI(st7701, 0xE7, 0x44, 0x44);
35962306a36Sopenharmony_ci	ST7701_DSI(st7701, 0xE8,
36062306a36Sopenharmony_ci		   0x0D, 0x91, 0xA0, 0xA0,
36162306a36Sopenharmony_ci			   0x0F, 0x93, 0xA0, 0xA0,
36262306a36Sopenharmony_ci			   0x09, 0x8D, 0xA0, 0xA0,
36362306a36Sopenharmony_ci			   0x0B, 0x8F, 0xA0, 0xA0);
36462306a36Sopenharmony_ci	ST7701_DSI(st7701, 0xEB,
36562306a36Sopenharmony_ci		   0x00, 0x00, 0xE4, 0xE4,
36662306a36Sopenharmony_ci			   0x44, 0x00, 0x00);
36762306a36Sopenharmony_ci	ST7701_DSI(st7701, 0xED,
36862306a36Sopenharmony_ci		   0xFF, 0xF5, 0x47, 0x6F,
36962306a36Sopenharmony_ci			   0x0B, 0xA1, 0xAB, 0xFF,
37062306a36Sopenharmony_ci			   0xFF, 0xBA, 0x1A, 0xB0,
37162306a36Sopenharmony_ci			   0xF6, 0x74, 0x5F, 0xFF);
37262306a36Sopenharmony_ci	ST7701_DSI(st7701, 0xEF,
37362306a36Sopenharmony_ci		   0x08, 0x08, 0x08, 0x40,
37462306a36Sopenharmony_ci			   0x3F, 0x64);
37562306a36Sopenharmony_ci
37662306a36Sopenharmony_ci	st7701_switch_cmd_bkx(st7701, false, 0);
37762306a36Sopenharmony_ci
37862306a36Sopenharmony_ci	st7701_switch_cmd_bkx(st7701, true, 3);
37962306a36Sopenharmony_ci	ST7701_DSI(st7701, 0xE6, 0x7C);
38062306a36Sopenharmony_ci	ST7701_DSI(st7701, 0xE8, 0x00, 0x0E);
38162306a36Sopenharmony_ci
38262306a36Sopenharmony_ci	st7701_switch_cmd_bkx(st7701, false, 0);
38362306a36Sopenharmony_ci	ST7701_DSI(st7701, 0x11);
38462306a36Sopenharmony_ci	msleep(120);
38562306a36Sopenharmony_ci
38662306a36Sopenharmony_ci	st7701_switch_cmd_bkx(st7701, true, 3);
38762306a36Sopenharmony_ci	ST7701_DSI(st7701, 0xE8, 0x00, 0x0C);
38862306a36Sopenharmony_ci	msleep(10);
38962306a36Sopenharmony_ci	ST7701_DSI(st7701, 0xE8, 0x00, 0x00);
39062306a36Sopenharmony_ci
39162306a36Sopenharmony_ci	st7701_switch_cmd_bkx(st7701, false, 0);
39262306a36Sopenharmony_ci	ST7701_DSI(st7701, 0x11);
39362306a36Sopenharmony_ci	msleep(120);
39462306a36Sopenharmony_ci	ST7701_DSI(st7701, 0xE8, 0x00, 0x00);
39562306a36Sopenharmony_ci
39662306a36Sopenharmony_ci	st7701_switch_cmd_bkx(st7701, false, 0);
39762306a36Sopenharmony_ci
39862306a36Sopenharmony_ci	ST7701_DSI(st7701, 0x3A, 0x70);
39962306a36Sopenharmony_ci}
40062306a36Sopenharmony_ci
40162306a36Sopenharmony_cistatic void kd50t048a_gip_sequence(struct st7701 *st7701)
40262306a36Sopenharmony_ci{
40362306a36Sopenharmony_ci	/**
40462306a36Sopenharmony_ci	 * ST7701_SPEC_V1.2 is unable to provide enough information above this
40562306a36Sopenharmony_ci	 * specific command sequence, so grab the same from vendor BSP driver.
40662306a36Sopenharmony_ci	 */
40762306a36Sopenharmony_ci	ST7701_DSI(st7701, 0xE0, 0x00, 0x00, 0x02);
40862306a36Sopenharmony_ci	ST7701_DSI(st7701, 0xE1, 0x08, 0x00, 0x0A, 0x00, 0x07, 0x00, 0x09,
40962306a36Sopenharmony_ci		   0x00, 0x00, 0x33, 0x33);
41062306a36Sopenharmony_ci	ST7701_DSI(st7701, 0xE2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
41162306a36Sopenharmony_ci		   0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
41262306a36Sopenharmony_ci	ST7701_DSI(st7701, 0xE3, 0x00, 0x00, 0x33, 0x33);
41362306a36Sopenharmony_ci	ST7701_DSI(st7701, 0xE4, 0x44, 0x44);
41462306a36Sopenharmony_ci	ST7701_DSI(st7701, 0xE5, 0x0E, 0x60, 0xA0, 0xA0, 0x10, 0x60, 0xA0,
41562306a36Sopenharmony_ci		   0xA0, 0x0A, 0x60, 0xA0, 0xA0, 0x0C, 0x60, 0xA0, 0xA0);
41662306a36Sopenharmony_ci	ST7701_DSI(st7701, 0xE6, 0x00, 0x00, 0x33, 0x33);
41762306a36Sopenharmony_ci	ST7701_DSI(st7701, 0xE7, 0x44, 0x44);
41862306a36Sopenharmony_ci	ST7701_DSI(st7701, 0xE8, 0x0D, 0x60, 0xA0, 0xA0, 0x0F, 0x60, 0xA0,
41962306a36Sopenharmony_ci		   0xA0, 0x09, 0x60, 0xA0, 0xA0, 0x0B, 0x60, 0xA0, 0xA0);
42062306a36Sopenharmony_ci	ST7701_DSI(st7701, 0xEB, 0x02, 0x01, 0xE4, 0xE4, 0x44, 0x00, 0x40);
42162306a36Sopenharmony_ci	ST7701_DSI(st7701, 0xEC, 0x02, 0x01);
42262306a36Sopenharmony_ci	ST7701_DSI(st7701, 0xED, 0xAB, 0x89, 0x76, 0x54, 0x01, 0xFF, 0xFF,
42362306a36Sopenharmony_ci		   0xFF, 0xFF, 0xFF, 0xFF, 0x10, 0x45, 0x67, 0x98, 0xBA);
42462306a36Sopenharmony_ci}
42562306a36Sopenharmony_ci
42662306a36Sopenharmony_cistatic int st7701_prepare(struct drm_panel *panel)
42762306a36Sopenharmony_ci{
42862306a36Sopenharmony_ci	struct st7701 *st7701 = panel_to_st7701(panel);
42962306a36Sopenharmony_ci	int ret;
43062306a36Sopenharmony_ci
43162306a36Sopenharmony_ci	gpiod_set_value(st7701->reset, 0);
43262306a36Sopenharmony_ci
43362306a36Sopenharmony_ci	ret = regulator_bulk_enable(ARRAY_SIZE(st7701->supplies),
43462306a36Sopenharmony_ci				    st7701->supplies);
43562306a36Sopenharmony_ci	if (ret < 0)
43662306a36Sopenharmony_ci		return ret;
43762306a36Sopenharmony_ci	msleep(20);
43862306a36Sopenharmony_ci
43962306a36Sopenharmony_ci	gpiod_set_value(st7701->reset, 1);
44062306a36Sopenharmony_ci	msleep(150);
44162306a36Sopenharmony_ci
44262306a36Sopenharmony_ci	st7701_init_sequence(st7701);
44362306a36Sopenharmony_ci
44462306a36Sopenharmony_ci	if (st7701->desc->gip_sequence)
44562306a36Sopenharmony_ci		st7701->desc->gip_sequence(st7701);
44662306a36Sopenharmony_ci
44762306a36Sopenharmony_ci	/* Disable Command2 */
44862306a36Sopenharmony_ci	st7701_switch_cmd_bkx(st7701, false, 0);
44962306a36Sopenharmony_ci
45062306a36Sopenharmony_ci	return 0;
45162306a36Sopenharmony_ci}
45262306a36Sopenharmony_ci
45362306a36Sopenharmony_cistatic int st7701_enable(struct drm_panel *panel)
45462306a36Sopenharmony_ci{
45562306a36Sopenharmony_ci	struct st7701 *st7701 = panel_to_st7701(panel);
45662306a36Sopenharmony_ci
45762306a36Sopenharmony_ci	ST7701_DSI(st7701, MIPI_DCS_SET_DISPLAY_ON, 0x00);
45862306a36Sopenharmony_ci
45962306a36Sopenharmony_ci	return 0;
46062306a36Sopenharmony_ci}
46162306a36Sopenharmony_ci
46262306a36Sopenharmony_cistatic int st7701_disable(struct drm_panel *panel)
46362306a36Sopenharmony_ci{
46462306a36Sopenharmony_ci	struct st7701 *st7701 = panel_to_st7701(panel);
46562306a36Sopenharmony_ci
46662306a36Sopenharmony_ci	ST7701_DSI(st7701, MIPI_DCS_SET_DISPLAY_OFF, 0x00);
46762306a36Sopenharmony_ci
46862306a36Sopenharmony_ci	return 0;
46962306a36Sopenharmony_ci}
47062306a36Sopenharmony_ci
47162306a36Sopenharmony_cistatic int st7701_unprepare(struct drm_panel *panel)
47262306a36Sopenharmony_ci{
47362306a36Sopenharmony_ci	struct st7701 *st7701 = panel_to_st7701(panel);
47462306a36Sopenharmony_ci
47562306a36Sopenharmony_ci	ST7701_DSI(st7701, MIPI_DCS_ENTER_SLEEP_MODE, 0x00);
47662306a36Sopenharmony_ci
47762306a36Sopenharmony_ci	msleep(st7701->sleep_delay);
47862306a36Sopenharmony_ci
47962306a36Sopenharmony_ci	gpiod_set_value(st7701->reset, 0);
48062306a36Sopenharmony_ci
48162306a36Sopenharmony_ci	/**
48262306a36Sopenharmony_ci	 * During the Resetting period, the display will be blanked
48362306a36Sopenharmony_ci	 * (The display is entering blanking sequence, which maximum
48462306a36Sopenharmony_ci	 * time is 120 ms, when Reset Starts in Sleep Out –mode. The
48562306a36Sopenharmony_ci	 * display remains the blank state in Sleep In –mode.) and
48662306a36Sopenharmony_ci	 * then return to Default condition for Hardware Reset.
48762306a36Sopenharmony_ci	 *
48862306a36Sopenharmony_ci	 * So we need wait sleep_delay time to make sure reset completed.
48962306a36Sopenharmony_ci	 */
49062306a36Sopenharmony_ci	msleep(st7701->sleep_delay);
49162306a36Sopenharmony_ci
49262306a36Sopenharmony_ci	regulator_bulk_disable(ARRAY_SIZE(st7701->supplies), st7701->supplies);
49362306a36Sopenharmony_ci
49462306a36Sopenharmony_ci	return 0;
49562306a36Sopenharmony_ci}
49662306a36Sopenharmony_ci
49762306a36Sopenharmony_cistatic int st7701_get_modes(struct drm_panel *panel,
49862306a36Sopenharmony_ci			    struct drm_connector *connector)
49962306a36Sopenharmony_ci{
50062306a36Sopenharmony_ci	struct st7701 *st7701 = panel_to_st7701(panel);
50162306a36Sopenharmony_ci	const struct drm_display_mode *desc_mode = st7701->desc->mode;
50262306a36Sopenharmony_ci	struct drm_display_mode *mode;
50362306a36Sopenharmony_ci
50462306a36Sopenharmony_ci	mode = drm_mode_duplicate(connector->dev, desc_mode);
50562306a36Sopenharmony_ci	if (!mode) {
50662306a36Sopenharmony_ci		dev_err(&st7701->dsi->dev, "failed to add mode %ux%u@%u\n",
50762306a36Sopenharmony_ci			desc_mode->hdisplay, desc_mode->vdisplay,
50862306a36Sopenharmony_ci			drm_mode_vrefresh(desc_mode));
50962306a36Sopenharmony_ci		return -ENOMEM;
51062306a36Sopenharmony_ci	}
51162306a36Sopenharmony_ci
51262306a36Sopenharmony_ci	drm_mode_set_name(mode);
51362306a36Sopenharmony_ci	drm_mode_probed_add(connector, mode);
51462306a36Sopenharmony_ci
51562306a36Sopenharmony_ci	connector->display_info.width_mm = desc_mode->width_mm;
51662306a36Sopenharmony_ci	connector->display_info.height_mm = desc_mode->height_mm;
51762306a36Sopenharmony_ci
51862306a36Sopenharmony_ci	/*
51962306a36Sopenharmony_ci	 * TODO: Remove once all drm drivers call
52062306a36Sopenharmony_ci	 * drm_connector_set_orientation_from_panel()
52162306a36Sopenharmony_ci	 */
52262306a36Sopenharmony_ci	drm_connector_set_panel_orientation(connector, st7701->orientation);
52362306a36Sopenharmony_ci
52462306a36Sopenharmony_ci	return 1;
52562306a36Sopenharmony_ci}
52662306a36Sopenharmony_ci
52762306a36Sopenharmony_cistatic enum drm_panel_orientation st7701_get_orientation(struct drm_panel *panel)
52862306a36Sopenharmony_ci{
52962306a36Sopenharmony_ci	struct st7701 *st7701 = panel_to_st7701(panel);
53062306a36Sopenharmony_ci
53162306a36Sopenharmony_ci	return st7701->orientation;
53262306a36Sopenharmony_ci}
53362306a36Sopenharmony_ci
53462306a36Sopenharmony_cistatic const struct drm_panel_funcs st7701_funcs = {
53562306a36Sopenharmony_ci	.disable	= st7701_disable,
53662306a36Sopenharmony_ci	.unprepare	= st7701_unprepare,
53762306a36Sopenharmony_ci	.prepare	= st7701_prepare,
53862306a36Sopenharmony_ci	.enable		= st7701_enable,
53962306a36Sopenharmony_ci	.get_modes	= st7701_get_modes,
54062306a36Sopenharmony_ci	.get_orientation = st7701_get_orientation,
54162306a36Sopenharmony_ci};
54262306a36Sopenharmony_ci
54362306a36Sopenharmony_cistatic const struct drm_display_mode ts8550b_mode = {
54462306a36Sopenharmony_ci	.clock		= 27500,
54562306a36Sopenharmony_ci
54662306a36Sopenharmony_ci	.hdisplay	= 480,
54762306a36Sopenharmony_ci	.hsync_start	= 480 + 38,
54862306a36Sopenharmony_ci	.hsync_end	= 480 + 38 + 12,
54962306a36Sopenharmony_ci	.htotal		= 480 + 38 + 12 + 12,
55062306a36Sopenharmony_ci
55162306a36Sopenharmony_ci	.vdisplay	= 854,
55262306a36Sopenharmony_ci	.vsync_start	= 854 + 18,
55362306a36Sopenharmony_ci	.vsync_end	= 854 + 18 + 8,
55462306a36Sopenharmony_ci	.vtotal		= 854 + 18 + 8 + 4,
55562306a36Sopenharmony_ci
55662306a36Sopenharmony_ci	.width_mm	= 69,
55762306a36Sopenharmony_ci	.height_mm	= 139,
55862306a36Sopenharmony_ci
55962306a36Sopenharmony_ci	.type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
56062306a36Sopenharmony_ci};
56162306a36Sopenharmony_ci
56262306a36Sopenharmony_cistatic const struct st7701_panel_desc ts8550b_desc = {
56362306a36Sopenharmony_ci	.mode = &ts8550b_mode,
56462306a36Sopenharmony_ci	.lanes = 2,
56562306a36Sopenharmony_ci	.format = MIPI_DSI_FMT_RGB888,
56662306a36Sopenharmony_ci	.panel_sleep_delay = 80, /* panel need extra 80ms for sleep out cmd */
56762306a36Sopenharmony_ci
56862306a36Sopenharmony_ci	.pv_gamma = {
56962306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
57062306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC0_MASK, 0),
57162306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
57262306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC4_MASK, 0xe),
57362306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
57462306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC8_MASK, 0x15),
57562306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC16_MASK, 0xf),
57662306a36Sopenharmony_ci
57762306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
57862306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC24_MASK, 0x11),
57962306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC52_MASK, 0x8),
58062306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC80_MASK, 0x8),
58162306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC108_MASK, 0x8),
58262306a36Sopenharmony_ci
58362306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC147_MASK, 0x8),
58462306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC175_MASK, 0x23),
58562306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC203_MASK, 0x4),
58662306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
58762306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC231_MASK, 0x13),
58862306a36Sopenharmony_ci
58962306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC239_MASK, 0x12),
59062306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
59162306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC247_MASK, 0x2b),
59262306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
59362306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC251_MASK, 0x34),
59462306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
59562306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC255_MASK, 0x1f)
59662306a36Sopenharmony_ci	},
59762306a36Sopenharmony_ci	.nv_gamma = {
59862306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
59962306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC0_MASK, 0),
60062306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
60162306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC4_MASK, 0xe),
60262306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0x2) |
60362306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC8_MASK, 0x15),
60462306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC16_MASK, 0xf),
60562306a36Sopenharmony_ci
60662306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
60762306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC24_MASK, 0x13),
60862306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC52_MASK, 0x7),
60962306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC80_MASK, 0x9),
61062306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC108_MASK, 0x8),
61162306a36Sopenharmony_ci
61262306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC147_MASK, 0x8),
61362306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC175_MASK, 0x22),
61462306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC203_MASK, 0x4),
61562306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
61662306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC231_MASK, 0x10),
61762306a36Sopenharmony_ci
61862306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC239_MASK, 0xe),
61962306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
62062306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC247_MASK, 0x2c),
62162306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
62262306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC251_MASK, 0x34),
62362306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
62462306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC255_MASK, 0x1f)
62562306a36Sopenharmony_ci	},
62662306a36Sopenharmony_ci	.nlinv = 7,
62762306a36Sopenharmony_ci	.vop_uv = 4400000,
62862306a36Sopenharmony_ci	.vcom_uv = 337500,
62962306a36Sopenharmony_ci	.vgh_mv = 15000,
63062306a36Sopenharmony_ci	.vgl_mv = -9510,
63162306a36Sopenharmony_ci	.avdd_mv = 6600,
63262306a36Sopenharmony_ci	.avcl_mv = -4400,
63362306a36Sopenharmony_ci	.gamma_op_bias = OP_BIAS_MAX,
63462306a36Sopenharmony_ci	.input_op_bias = OP_BIAS_MIN,
63562306a36Sopenharmony_ci	.output_op_bias = OP_BIAS_MIN,
63662306a36Sopenharmony_ci	.t2d_ns = 1600,
63762306a36Sopenharmony_ci	.t3d_ns = 10400,
63862306a36Sopenharmony_ci	.eot_en = true,
63962306a36Sopenharmony_ci	.gip_sequence = ts8550b_gip_sequence,
64062306a36Sopenharmony_ci};
64162306a36Sopenharmony_ci
64262306a36Sopenharmony_cistatic const struct drm_display_mode dmt028vghmcmi_1a_mode = {
64362306a36Sopenharmony_ci	.clock		= 22325,
64462306a36Sopenharmony_ci
64562306a36Sopenharmony_ci	.hdisplay	= 480,
64662306a36Sopenharmony_ci	.hsync_start	= 480 + 40,
64762306a36Sopenharmony_ci	.hsync_end	= 480 + 40 + 4,
64862306a36Sopenharmony_ci	.htotal		= 480 + 40 + 4 + 20,
64962306a36Sopenharmony_ci
65062306a36Sopenharmony_ci	.vdisplay	= 640,
65162306a36Sopenharmony_ci	.vsync_start	= 640 + 2,
65262306a36Sopenharmony_ci	.vsync_end	= 640 + 2 + 40,
65362306a36Sopenharmony_ci	.vtotal		= 640 + 2 + 40 + 16,
65462306a36Sopenharmony_ci
65562306a36Sopenharmony_ci	.width_mm	= 56,
65662306a36Sopenharmony_ci	.height_mm	= 78,
65762306a36Sopenharmony_ci
65862306a36Sopenharmony_ci	.flags		= DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC,
65962306a36Sopenharmony_ci
66062306a36Sopenharmony_ci	.type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
66162306a36Sopenharmony_ci};
66262306a36Sopenharmony_ci
66362306a36Sopenharmony_cistatic const struct st7701_panel_desc dmt028vghmcmi_1a_desc = {
66462306a36Sopenharmony_ci	.mode = &dmt028vghmcmi_1a_mode,
66562306a36Sopenharmony_ci	.lanes = 2,
66662306a36Sopenharmony_ci	.format = MIPI_DSI_FMT_RGB888,
66762306a36Sopenharmony_ci	.panel_sleep_delay = 5, /* panel need extra 5ms for sleep out cmd */
66862306a36Sopenharmony_ci
66962306a36Sopenharmony_ci	.pv_gamma = {
67062306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
67162306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC0_MASK, 0),
67262306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
67362306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC4_MASK, 0x10),
67462306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
67562306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC8_MASK, 0x17),
67662306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC16_MASK, 0xd),
67762306a36Sopenharmony_ci
67862306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
67962306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC24_MASK, 0x11),
68062306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC52_MASK, 0x6),
68162306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC80_MASK, 0x5),
68262306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC108_MASK, 0x8),
68362306a36Sopenharmony_ci
68462306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC147_MASK, 0x7),
68562306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC175_MASK, 0x1f),
68662306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC203_MASK, 0x4),
68762306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
68862306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC231_MASK, 0x11),
68962306a36Sopenharmony_ci
69062306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC239_MASK, 0xe),
69162306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
69262306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC247_MASK, 0x29),
69362306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
69462306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC251_MASK, 0x30),
69562306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
69662306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC255_MASK, 0x1f)
69762306a36Sopenharmony_ci	},
69862306a36Sopenharmony_ci	.nv_gamma = {
69962306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
70062306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC0_MASK, 0),
70162306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
70262306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC4_MASK, 0xd),
70362306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
70462306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC8_MASK, 0x14),
70562306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC16_MASK, 0xe),
70662306a36Sopenharmony_ci
70762306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
70862306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC24_MASK, 0x11),
70962306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC52_MASK, 0x6),
71062306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC80_MASK, 0x4),
71162306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC108_MASK, 0x8),
71262306a36Sopenharmony_ci
71362306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC147_MASK, 0x8),
71462306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC175_MASK, 0x20),
71562306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC203_MASK, 0x5),
71662306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
71762306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC231_MASK, 0x13),
71862306a36Sopenharmony_ci
71962306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC239_MASK, 0x13),
72062306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
72162306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC247_MASK, 0x26),
72262306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
72362306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC251_MASK, 0x30),
72462306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
72562306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC255_MASK, 0x1f)
72662306a36Sopenharmony_ci	},
72762306a36Sopenharmony_ci	.nlinv = 1,
72862306a36Sopenharmony_ci	.vop_uv = 4800000,
72962306a36Sopenharmony_ci	.vcom_uv = 1650000,
73062306a36Sopenharmony_ci	.vgh_mv = 15000,
73162306a36Sopenharmony_ci	.vgl_mv = -10170,
73262306a36Sopenharmony_ci	.avdd_mv = 6600,
73362306a36Sopenharmony_ci	.avcl_mv = -4400,
73462306a36Sopenharmony_ci	.gamma_op_bias = OP_BIAS_MIDDLE,
73562306a36Sopenharmony_ci	.input_op_bias = OP_BIAS_MIN,
73662306a36Sopenharmony_ci	.output_op_bias = OP_BIAS_MIN,
73762306a36Sopenharmony_ci	.t2d_ns = 1600,
73862306a36Sopenharmony_ci	.t3d_ns = 10400,
73962306a36Sopenharmony_ci	.eot_en = true,
74062306a36Sopenharmony_ci	.gip_sequence = dmt028vghmcmi_1a_gip_sequence,
74162306a36Sopenharmony_ci};
74262306a36Sopenharmony_ci
74362306a36Sopenharmony_cistatic const struct drm_display_mode kd50t048a_mode = {
74462306a36Sopenharmony_ci	.clock          = 27500,
74562306a36Sopenharmony_ci
74662306a36Sopenharmony_ci	.hdisplay       = 480,
74762306a36Sopenharmony_ci	.hsync_start    = 480 + 2,
74862306a36Sopenharmony_ci	.hsync_end      = 480 + 2 + 10,
74962306a36Sopenharmony_ci	.htotal         = 480 + 2 + 10 + 2,
75062306a36Sopenharmony_ci
75162306a36Sopenharmony_ci	.vdisplay       = 854,
75262306a36Sopenharmony_ci	.vsync_start    = 854 + 2,
75362306a36Sopenharmony_ci	.vsync_end      = 854 + 2 + 2,
75462306a36Sopenharmony_ci	.vtotal         = 854 + 2 + 2 + 17,
75562306a36Sopenharmony_ci
75662306a36Sopenharmony_ci	.width_mm       = 69,
75762306a36Sopenharmony_ci	.height_mm      = 139,
75862306a36Sopenharmony_ci
75962306a36Sopenharmony_ci	.type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
76062306a36Sopenharmony_ci};
76162306a36Sopenharmony_ci
76262306a36Sopenharmony_cistatic const struct st7701_panel_desc kd50t048a_desc = {
76362306a36Sopenharmony_ci	.mode = &kd50t048a_mode,
76462306a36Sopenharmony_ci	.lanes = 2,
76562306a36Sopenharmony_ci	.format = MIPI_DSI_FMT_RGB888,
76662306a36Sopenharmony_ci	.panel_sleep_delay = 0,
76762306a36Sopenharmony_ci
76862306a36Sopenharmony_ci	.pv_gamma = {
76962306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
77062306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC0_MASK, 0),
77162306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
77262306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC4_MASK, 0xd),
77362306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
77462306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC8_MASK, 0x14),
77562306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC16_MASK, 0xd),
77662306a36Sopenharmony_ci
77762306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
77862306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC24_MASK, 0x10),
77962306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC52_MASK, 0x5),
78062306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC80_MASK, 0x2),
78162306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC108_MASK, 0x8),
78262306a36Sopenharmony_ci
78362306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC147_MASK, 0x8),
78462306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC175_MASK, 0x1e),
78562306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC203_MASK, 0x5),
78662306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
78762306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC231_MASK, 0x13),
78862306a36Sopenharmony_ci
78962306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC239_MASK, 0x11),
79062306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 2) |
79162306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC247_MASK, 0x23),
79262306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
79362306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC251_MASK, 0x29),
79462306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
79562306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC255_MASK, 0x18)
79662306a36Sopenharmony_ci	},
79762306a36Sopenharmony_ci	.nv_gamma = {
79862306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
79962306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC0_MASK, 0),
80062306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
80162306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC4_MASK, 0xc),
80262306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
80362306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC8_MASK, 0x14),
80462306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC16_MASK, 0xc),
80562306a36Sopenharmony_ci
80662306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
80762306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC24_MASK, 0x10),
80862306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC52_MASK, 0x5),
80962306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC80_MASK, 0x3),
81062306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC108_MASK, 0x8),
81162306a36Sopenharmony_ci
81262306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC147_MASK, 0x7),
81362306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC175_MASK, 0x20),
81462306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC203_MASK, 0x5),
81562306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
81662306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC231_MASK, 0x13),
81762306a36Sopenharmony_ci
81862306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC239_MASK, 0x11),
81962306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 2) |
82062306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC247_MASK, 0x24),
82162306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
82262306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC251_MASK, 0x29),
82362306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
82462306a36Sopenharmony_ci		CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC255_MASK, 0x18)
82562306a36Sopenharmony_ci	},
82662306a36Sopenharmony_ci	.nlinv = 1,
82762306a36Sopenharmony_ci	.vop_uv = 4887500,
82862306a36Sopenharmony_ci	.vcom_uv = 937500,
82962306a36Sopenharmony_ci	.vgh_mv = 15000,
83062306a36Sopenharmony_ci	.vgl_mv = -9510,
83162306a36Sopenharmony_ci	.avdd_mv = 6600,
83262306a36Sopenharmony_ci	.avcl_mv = -4400,
83362306a36Sopenharmony_ci	.gamma_op_bias = OP_BIAS_MIDDLE,
83462306a36Sopenharmony_ci	.input_op_bias = OP_BIAS_MIN,
83562306a36Sopenharmony_ci	.output_op_bias = OP_BIAS_MIN,
83662306a36Sopenharmony_ci	.t2d_ns = 1600,
83762306a36Sopenharmony_ci	.t3d_ns = 10400,
83862306a36Sopenharmony_ci	.eot_en = true,
83962306a36Sopenharmony_ci	.gip_sequence = kd50t048a_gip_sequence,
84062306a36Sopenharmony_ci};
84162306a36Sopenharmony_ci
84262306a36Sopenharmony_cistatic int st7701_dsi_probe(struct mipi_dsi_device *dsi)
84362306a36Sopenharmony_ci{
84462306a36Sopenharmony_ci	const struct st7701_panel_desc *desc;
84562306a36Sopenharmony_ci	struct st7701 *st7701;
84662306a36Sopenharmony_ci	int ret;
84762306a36Sopenharmony_ci
84862306a36Sopenharmony_ci	st7701 = devm_kzalloc(&dsi->dev, sizeof(*st7701), GFP_KERNEL);
84962306a36Sopenharmony_ci	if (!st7701)
85062306a36Sopenharmony_ci		return -ENOMEM;
85162306a36Sopenharmony_ci
85262306a36Sopenharmony_ci	desc = of_device_get_match_data(&dsi->dev);
85362306a36Sopenharmony_ci	dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST |
85462306a36Sopenharmony_ci			  MIPI_DSI_MODE_LPM | MIPI_DSI_CLOCK_NON_CONTINUOUS;
85562306a36Sopenharmony_ci	dsi->format = desc->format;
85662306a36Sopenharmony_ci	dsi->lanes = desc->lanes;
85762306a36Sopenharmony_ci
85862306a36Sopenharmony_ci	st7701->supplies[0].supply = "VCC";
85962306a36Sopenharmony_ci	st7701->supplies[1].supply = "IOVCC";
86062306a36Sopenharmony_ci
86162306a36Sopenharmony_ci	ret = devm_regulator_bulk_get(&dsi->dev, ARRAY_SIZE(st7701->supplies),
86262306a36Sopenharmony_ci				      st7701->supplies);
86362306a36Sopenharmony_ci	if (ret < 0)
86462306a36Sopenharmony_ci		return ret;
86562306a36Sopenharmony_ci
86662306a36Sopenharmony_ci	st7701->reset = devm_gpiod_get(&dsi->dev, "reset", GPIOD_OUT_LOW);
86762306a36Sopenharmony_ci	if (IS_ERR(st7701->reset)) {
86862306a36Sopenharmony_ci		dev_err(&dsi->dev, "Couldn't get our reset GPIO\n");
86962306a36Sopenharmony_ci		return PTR_ERR(st7701->reset);
87062306a36Sopenharmony_ci	}
87162306a36Sopenharmony_ci
87262306a36Sopenharmony_ci	ret = of_drm_get_panel_orientation(dsi->dev.of_node, &st7701->orientation);
87362306a36Sopenharmony_ci	if (ret < 0)
87462306a36Sopenharmony_ci		return dev_err_probe(&dsi->dev, ret, "Failed to get orientation\n");
87562306a36Sopenharmony_ci
87662306a36Sopenharmony_ci	drm_panel_init(&st7701->panel, &dsi->dev, &st7701_funcs,
87762306a36Sopenharmony_ci		       DRM_MODE_CONNECTOR_DSI);
87862306a36Sopenharmony_ci
87962306a36Sopenharmony_ci	/**
88062306a36Sopenharmony_ci	 * Once sleep out has been issued, ST7701 IC required to wait 120ms
88162306a36Sopenharmony_ci	 * before initiating new commands.
88262306a36Sopenharmony_ci	 *
88362306a36Sopenharmony_ci	 * On top of that some panels might need an extra delay to wait, so
88462306a36Sopenharmony_ci	 * add panel specific delay for those cases. As now this panel specific
88562306a36Sopenharmony_ci	 * delay information is referenced from those panel BSP driver, example
88662306a36Sopenharmony_ci	 * ts8550b and there is no valid documentation for that.
88762306a36Sopenharmony_ci	 */
88862306a36Sopenharmony_ci	st7701->sleep_delay = 120 + desc->panel_sleep_delay;
88962306a36Sopenharmony_ci
89062306a36Sopenharmony_ci	ret = drm_panel_of_backlight(&st7701->panel);
89162306a36Sopenharmony_ci	if (ret)
89262306a36Sopenharmony_ci		return ret;
89362306a36Sopenharmony_ci
89462306a36Sopenharmony_ci	drm_panel_add(&st7701->panel);
89562306a36Sopenharmony_ci
89662306a36Sopenharmony_ci	mipi_dsi_set_drvdata(dsi, st7701);
89762306a36Sopenharmony_ci	st7701->dsi = dsi;
89862306a36Sopenharmony_ci	st7701->desc = desc;
89962306a36Sopenharmony_ci
90062306a36Sopenharmony_ci	ret = mipi_dsi_attach(dsi);
90162306a36Sopenharmony_ci	if (ret)
90262306a36Sopenharmony_ci		goto err_attach;
90362306a36Sopenharmony_ci
90462306a36Sopenharmony_ci	return 0;
90562306a36Sopenharmony_ci
90662306a36Sopenharmony_cierr_attach:
90762306a36Sopenharmony_ci	drm_panel_remove(&st7701->panel);
90862306a36Sopenharmony_ci	return ret;
90962306a36Sopenharmony_ci}
91062306a36Sopenharmony_ci
91162306a36Sopenharmony_cistatic void st7701_dsi_remove(struct mipi_dsi_device *dsi)
91262306a36Sopenharmony_ci{
91362306a36Sopenharmony_ci	struct st7701 *st7701 = mipi_dsi_get_drvdata(dsi);
91462306a36Sopenharmony_ci
91562306a36Sopenharmony_ci	mipi_dsi_detach(dsi);
91662306a36Sopenharmony_ci	drm_panel_remove(&st7701->panel);
91762306a36Sopenharmony_ci}
91862306a36Sopenharmony_ci
91962306a36Sopenharmony_cistatic const struct of_device_id st7701_of_match[] = {
92062306a36Sopenharmony_ci	{ .compatible = "densitron,dmt028vghmcmi-1a", .data = &dmt028vghmcmi_1a_desc },
92162306a36Sopenharmony_ci	{ .compatible = "elida,kd50t048a", .data = &kd50t048a_desc },
92262306a36Sopenharmony_ci	{ .compatible = "techstar,ts8550b", .data = &ts8550b_desc },
92362306a36Sopenharmony_ci	{ }
92462306a36Sopenharmony_ci};
92562306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, st7701_of_match);
92662306a36Sopenharmony_ci
92762306a36Sopenharmony_cistatic struct mipi_dsi_driver st7701_dsi_driver = {
92862306a36Sopenharmony_ci	.probe		= st7701_dsi_probe,
92962306a36Sopenharmony_ci	.remove		= st7701_dsi_remove,
93062306a36Sopenharmony_ci	.driver = {
93162306a36Sopenharmony_ci		.name		= "st7701",
93262306a36Sopenharmony_ci		.of_match_table	= st7701_of_match,
93362306a36Sopenharmony_ci	},
93462306a36Sopenharmony_ci};
93562306a36Sopenharmony_cimodule_mipi_dsi_driver(st7701_dsi_driver);
93662306a36Sopenharmony_ci
93762306a36Sopenharmony_ciMODULE_AUTHOR("Jagan Teki <jagan@amarulasolutions.com>");
93862306a36Sopenharmony_ciMODULE_DESCRIPTION("Sitronix ST7701 LCD Panel Driver");
93962306a36Sopenharmony_ciMODULE_LICENSE("GPL");
940