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