drm/panel/panel-sitronix-st7701: Parametrize voltage and timing
Instead of hard-coding TFT matrix voltage and timing settings, which can even lead to permanent TFT matrix damage, parametrize them in TFT matrix descriptor. Signed-off-by: Marek Vasut <marex@denx.de> Cc: Guido Günther <agx@sigxcpu.org> Cc: Jagan Teki <jagan@amarulasolutions.com> Cc: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Cc: Linus Walleij <linus.walleij@linaro.org> Cc: Sam Ravnborg <sam@ravnborg.org> Cc: Thierry Reding <thierry.reding@gmail.com> Signed-off-by: Linus Walleij <linus.walleij@linaro.org> Link: https://patchwork.freedesktop.org/patch/msgid/20220710194437.289042-8-marex@denx.de
This commit is contained in:
parent
de2b491784
commit
83b7a8e7e8
|
@ -79,30 +79,34 @@
|
|||
#define DSI_CMD2_BK0_INVSEL_RTNI_MASK GENMASK(4, 0)
|
||||
|
||||
/* Command2, BK1 bytes */
|
||||
#define DSI_CMD2_BK1_VRHA_SET 0x45
|
||||
#define DSI_CMD2_BK1_VCOM_SET 0x13
|
||||
#define DSI_CMD2_BK1_VGHSS_SET GENMASK(2, 0)
|
||||
#define DSI_CMD2_BK1_VRHA_MASK GENMASK(7, 0)
|
||||
#define DSI_CMD2_BK1_VCOM_MASK GENMASK(7, 0)
|
||||
#define DSI_CMD2_BK1_VGHSS_MASK GENMASK(3, 0)
|
||||
#define DSI_CMD2_BK1_TESTCMD_VAL BIT(7)
|
||||
#define DSI_VGLS_DEFAULT BIT(6)
|
||||
#define DSI_VGLS_SEL GENMASK(2, 0)
|
||||
#define DSI_CMD2_BK1_VGLS_SET (DSI_VGLS_DEFAULT | DSI_VGLS_SEL)
|
||||
#define DSI_PWCTLR1_AP BIT(7) /* Gamma OP bias, max */
|
||||
#define DSI_PWCTLR1_APIS BIT(2) /* Source OP input bias, min */
|
||||
#define DSI_PWCTLR1_APOS BIT(0) /* Source OP output bias, min */
|
||||
#define DSI_CMD2_BK1_PWCTLR1_SET (DSI_PWCTLR1_AP | DSI_PWCTLR1_APIS | \
|
||||
DSI_PWCTLR1_APOS)
|
||||
#define DSI_PWCTLR2_AVDD BIT(5) /* AVDD 6.6v */
|
||||
#define DSI_PWCTLR2_AVCL 0x0 /* AVCL -4.4v */
|
||||
#define DSI_CMD2_BK1_PWCTLR2_SET (DSI_PWCTLR2_AVDD | DSI_PWCTLR2_AVCL)
|
||||
#define DSI_SPD1_T2D BIT(3)
|
||||
#define DSI_CMD2_BK1_SPD1_SET (GENMASK(6, 4) | DSI_SPD1_T2D)
|
||||
#define DSI_CMD2_BK1_SPD2_SET DSI_CMD2_BK1_SPD1_SET
|
||||
#define DSI_MIPISET1_EOT_EN BIT(3)
|
||||
#define DSI_CMD2_BK1_MIPISET1_SET (BIT(7) | DSI_MIPISET1_EOT_EN)
|
||||
#define DSI_CMD2_BK1_VGLS_ONES BIT(6)
|
||||
#define DSI_CMD2_BK1_VGLS_MASK GENMASK(3, 0)
|
||||
#define DSI_CMD2_BK1_PWRCTRL1_AP_MASK GENMASK(7, 6)
|
||||
#define DSI_CMD2_BK1_PWRCTRL1_APIS_MASK GENMASK(3, 2)
|
||||
#define DSI_CMD2_BK1_PWRCTRL1_APOS_MASK GENMASK(1, 0)
|
||||
#define DSI_CMD2_BK1_PWRCTRL2_AVDD_MASK GENMASK(5, 4)
|
||||
#define DSI_CMD2_BK1_PWRCTRL2_AVCL_MASK GENMASK(1, 0)
|
||||
#define DSI_CMD2_BK1_SPD1_ONES_MASK GENMASK(6, 4)
|
||||
#define DSI_CMD2_BK1_SPD1_T2D_MASK GENMASK(3, 0)
|
||||
#define DSI_CMD2_BK1_SPD2_ONES_MASK GENMASK(6, 4)
|
||||
#define DSI_CMD2_BK1_SPD2_T3D_MASK GENMASK(3, 0)
|
||||
#define DSI_CMD2_BK1_MIPISET1_ONES BIT(7)
|
||||
#define DSI_CMD2_BK1_MIPISET1_EOT_EN BIT(3)
|
||||
|
||||
#define CFIELD_PREP(_mask, _val) \
|
||||
(((typeof(_mask))(_val) << (__builtin_ffsll(_mask) - 1)) & (_mask))
|
||||
|
||||
enum op_bias {
|
||||
OP_BIAS_OFF = 0,
|
||||
OP_BIAS_MIN,
|
||||
OP_BIAS_MIDDLE,
|
||||
OP_BIAS_MAX
|
||||
};
|
||||
|
||||
struct st7701_panel_desc {
|
||||
const struct drm_display_mode *mode;
|
||||
unsigned int lanes;
|
||||
|
@ -113,6 +117,18 @@ struct st7701_panel_desc {
|
|||
const u8 pv_gamma[16]; /* Positive voltage gamma control */
|
||||
const u8 nv_gamma[16]; /* Negative voltage gamma control */
|
||||
const u8 nlinv; /* Inversion selection */
|
||||
const u32 vop_uv; /* Vop in uV */
|
||||
const u32 vcom_uv; /* Vcom in uV */
|
||||
const u16 vgh_mv; /* Vgh in mV */
|
||||
const s16 vgl_mv; /* Vgl in mV */
|
||||
const u16 avdd_mv; /* Avdd in mV */
|
||||
const s16 avcl_mv; /* Avcl in mV */
|
||||
const enum op_bias gamma_op_bias;
|
||||
const enum op_bias input_op_bias;
|
||||
const enum op_bias output_op_bias;
|
||||
const u16 t2d_ns; /* T2D in ns */
|
||||
const u16 t3d_ns; /* T3D in ns */
|
||||
const bool eot_en;
|
||||
};
|
||||
|
||||
struct st7701 {
|
||||
|
@ -142,6 +158,31 @@ static inline int st7701_dsi_write(struct st7701 *st7701, const void *seq,
|
|||
st7701_dsi_write(st7701, d, ARRAY_SIZE(d)); \
|
||||
}
|
||||
|
||||
static u8 st7701_vgls_map(struct st7701 *st7701)
|
||||
{
|
||||
const struct st7701_panel_desc *desc = st7701->desc;
|
||||
struct {
|
||||
s32 vgl;
|
||||
u8 val;
|
||||
} map[16] = {
|
||||
{ -7060, 0x0 }, { -7470, 0x1 },
|
||||
{ -7910, 0x2 }, { -8140, 0x3 },
|
||||
{ -8650, 0x4 }, { -8920, 0x5 },
|
||||
{ -9210, 0x6 }, { -9510, 0x7 },
|
||||
{ -9830, 0x8 }, { -10170, 0x9 },
|
||||
{ -10530, 0xa }, { -10910, 0xb },
|
||||
{ -11310, 0xc }, { -11730, 0xd },
|
||||
{ -12200, 0xe }, { -12690, 0xf }
|
||||
};
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(map); i++)
|
||||
if (desc->vgl_mv == map[i].vgl)
|
||||
return map[i].val;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void st7701_init_sequence(struct st7701 *st7701)
|
||||
{
|
||||
const struct st7701_panel_desc *desc = st7701->desc;
|
||||
|
@ -200,16 +241,62 @@ static void st7701_init_sequence(struct st7701 *st7701)
|
|||
/* Command2, BK1 */
|
||||
ST7701_DSI(st7701, DSI_CMD2BKX_SEL,
|
||||
0x77, 0x01, 0x00, 0x00, DSI_CMD2BK1_SEL);
|
||||
ST7701_DSI(st7701, DSI_CMD2_BK1_VRHS, DSI_CMD2_BK1_VRHA_SET);
|
||||
ST7701_DSI(st7701, DSI_CMD2_BK1_VCOM, DSI_CMD2_BK1_VCOM_SET);
|
||||
ST7701_DSI(st7701, DSI_CMD2_BK1_VGHSS, DSI_CMD2_BK1_VGHSS_SET);
|
||||
|
||||
/* Vop = 3.5375V + (VRHA[7:0] * 0.0125V) */
|
||||
ST7701_DSI(st7701, DSI_CMD2_BK1_VRHS,
|
||||
FIELD_PREP(DSI_CMD2_BK1_VRHA_MASK,
|
||||
DIV_ROUND_CLOSEST(desc->vop_uv - 3537500, 12500)));
|
||||
|
||||
/* Vcom = 0.1V + (VCOM[7:0] * 0.0125V) */
|
||||
ST7701_DSI(st7701, DSI_CMD2_BK1_VCOM,
|
||||
FIELD_PREP(DSI_CMD2_BK1_VCOM_MASK,
|
||||
DIV_ROUND_CLOSEST(desc->vcom_uv - 100000, 12500)));
|
||||
|
||||
/* Vgh = 11.5V + (VGHSS[7:0] * 0.5V) */
|
||||
ST7701_DSI(st7701, DSI_CMD2_BK1_VGHSS,
|
||||
FIELD_PREP(DSI_CMD2_BK1_VGHSS_MASK,
|
||||
DIV_ROUND_CLOSEST(clamp(desc->vgh_mv,
|
||||
(u16)11500,
|
||||
(u16)17000) - 11500,
|
||||
500)));
|
||||
|
||||
ST7701_DSI(st7701, DSI_CMD2_BK1_TESTCMD, DSI_CMD2_BK1_TESTCMD_VAL);
|
||||
ST7701_DSI(st7701, DSI_CMD2_BK1_VGLS, DSI_CMD2_BK1_VGLS_SET);
|
||||
ST7701_DSI(st7701, DSI_CMD2_BK1_PWCTLR1, DSI_CMD2_BK1_PWCTLR1_SET);
|
||||
ST7701_DSI(st7701, DSI_CMD2_BK1_PWCTLR2, DSI_CMD2_BK1_PWCTLR2_SET);
|
||||
ST7701_DSI(st7701, DSI_CMD2_BK1_SPD1, DSI_CMD2_BK1_SPD1_SET);
|
||||
ST7701_DSI(st7701, DSI_CMD2_BK1_SPD2, DSI_CMD2_BK1_SPD2_SET);
|
||||
ST7701_DSI(st7701, DSI_CMD2_BK1_MIPISET1, DSI_CMD2_BK1_MIPISET1_SET);
|
||||
|
||||
/* Vgl is non-linear */
|
||||
ST7701_DSI(st7701, DSI_CMD2_BK1_VGLS,
|
||||
DSI_CMD2_BK1_VGLS_ONES |
|
||||
FIELD_PREP(DSI_CMD2_BK1_VGLS_MASK, st7701_vgls_map(st7701)));
|
||||
|
||||
ST7701_DSI(st7701, DSI_CMD2_BK1_PWCTLR1,
|
||||
FIELD_PREP(DSI_CMD2_BK1_PWRCTRL1_AP_MASK,
|
||||
desc->gamma_op_bias) |
|
||||
FIELD_PREP(DSI_CMD2_BK1_PWRCTRL1_APIS_MASK,
|
||||
desc->input_op_bias) |
|
||||
FIELD_PREP(DSI_CMD2_BK1_PWRCTRL1_APOS_MASK,
|
||||
desc->output_op_bias));
|
||||
|
||||
/* Avdd = 6.2V + (AVDD[1:0] * 0.2V) , Avcl = -4.4V - (AVCL[1:0] * 0.2V) */
|
||||
ST7701_DSI(st7701, DSI_CMD2_BK1_PWCTLR2,
|
||||
FIELD_PREP(DSI_CMD2_BK1_PWRCTRL2_AVDD_MASK,
|
||||
DIV_ROUND_CLOSEST(desc->avdd_mv - 6200, 200)) |
|
||||
FIELD_PREP(DSI_CMD2_BK1_PWRCTRL2_AVCL_MASK,
|
||||
DIV_ROUND_CLOSEST(-4400 + desc->avcl_mv, 200)));
|
||||
|
||||
/* T2D = 0.2us * T2D[3:0] */
|
||||
ST7701_DSI(st7701, DSI_CMD2_BK1_SPD1,
|
||||
DSI_CMD2_BK1_SPD1_ONES_MASK |
|
||||
FIELD_PREP(DSI_CMD2_BK1_SPD1_T2D_MASK,
|
||||
DIV_ROUND_CLOSEST(desc->t2d_ns, 200)));
|
||||
|
||||
/* T3D = 4us + (0.8us * T3D[3:0]) */
|
||||
ST7701_DSI(st7701, DSI_CMD2_BK1_SPD2,
|
||||
DSI_CMD2_BK1_SPD2_ONES_MASK |
|
||||
FIELD_PREP(DSI_CMD2_BK1_SPD2_T3D_MASK,
|
||||
DIV_ROUND_CLOSEST(desc->t3d_ns - 4000, 800)));
|
||||
|
||||
ST7701_DSI(st7701, DSI_CMD2_BK1_MIPISET1,
|
||||
DSI_CMD2_BK1_MIPISET1_ONES |
|
||||
(desc->eot_en ? DSI_CMD2_BK1_MIPISET1_EOT_EN : 0));
|
||||
|
||||
/**
|
||||
* ST7701_SPEC_V1.2 is unable to provide enough information above this
|
||||
|
@ -419,6 +506,18 @@ static const struct st7701_panel_desc ts8550b_desc = {
|
|||
CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC255_MASK, 0x1f)
|
||||
},
|
||||
.nlinv = 7,
|
||||
.vop_uv = 4400000,
|
||||
.vcom_uv = 337500,
|
||||
.vgh_mv = 15000,
|
||||
.vgl_mv = -9510,
|
||||
.avdd_mv = 6600,
|
||||
.avcl_mv = -4400,
|
||||
.gamma_op_bias = OP_BIAS_MAX,
|
||||
.input_op_bias = OP_BIAS_MIN,
|
||||
.output_op_bias = OP_BIAS_MIN,
|
||||
.t2d_ns = 1600,
|
||||
.t3d_ns = 10400,
|
||||
.eot_en = true,
|
||||
};
|
||||
|
||||
static int st7701_dsi_probe(struct mipi_dsi_device *dsi)
|
||||
|
|
Loading…
Reference in New Issue