drm/panel/panel-sitronix-st7701: Make gamma correction TFT specific
authorMarek Vasut <marex@denx.de>
Sun, 10 Jul 2022 19:44:32 +0000 (21:44 +0200)
committerLinus Walleij <linus.walleij@linaro.org>
Tue, 19 Jul 2022 08:38:56 +0000 (10:38 +0200)
The gamma correction values are specific to the TFT which is attached to
the ST7701 TFT matrix driver, move the gamma correction values from what
incorrectly looks like common init sequence into TFT matrix specific
settings.

While doing so, add macros which defined fields within the gamma register
file and a macro which mimics FIELD_PREP except works with constant
expressions.

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-4-marex@denx.de
drivers/gpu/drm/panel/panel-sitronix-st7701.c

index 8b050f2..c5783aa 100644 (file)
 #define DSI_CMD2BKX_SEL_NONE           0x00
 
 /* Command2, BK0 bytes */
+#define DSI_CMD2_BK0_GAMCTRL_AJ_MASK   GENMASK(7, 6)
+#define DSI_CMD2_BK0_GAMCTRL_VC0_MASK  GENMASK(3, 0)
+#define DSI_CMD2_BK0_GAMCTRL_VC4_MASK  GENMASK(5, 0)
+#define DSI_CMD2_BK0_GAMCTRL_VC8_MASK  GENMASK(5, 0)
+#define DSI_CMD2_BK0_GAMCTRL_VC16_MASK GENMASK(4, 0)
+#define DSI_CMD2_BK0_GAMCTRL_VC24_MASK GENMASK(4, 0)
+#define DSI_CMD2_BK0_GAMCTRL_VC52_MASK GENMASK(3, 0)
+#define DSI_CMD2_BK0_GAMCTRL_VC80_MASK GENMASK(5, 0)
+#define DSI_CMD2_BK0_GAMCTRL_VC108_MASK        GENMASK(3, 0)
+#define DSI_CMD2_BK0_GAMCTRL_VC147_MASK        GENMASK(3, 0)
+#define DSI_CMD2_BK0_GAMCTRL_VC175_MASK        GENMASK(5, 0)
+#define DSI_CMD2_BK0_GAMCTRL_VC203_MASK        GENMASK(3, 0)
+#define DSI_CMD2_BK0_GAMCTRL_VC231_MASK        GENMASK(4, 0)
+#define DSI_CMD2_BK0_GAMCTRL_VC239_MASK        GENMASK(4, 0)
+#define DSI_CMD2_BK0_GAMCTRL_VC247_MASK        GENMASK(5, 0)
+#define DSI_CMD2_BK0_GAMCTRL_VC251_MASK        GENMASK(5, 0)
+#define DSI_CMD2_BK0_GAMCTRL_VC255_MASK        GENMASK(4, 0)
 #define DSI_LINESET_LINE               0x69
 #define DSI_LINESET_LDE_EN             BIT(7)
 #define DSI_LINESET_LINEDELTA          GENMASK(1, 0)
 #define DSI_MIPISET1_EOT_EN            BIT(3)
 #define DSI_CMD2_BK1_MIPISET1_SET      (BIT(7) | DSI_MIPISET1_EOT_EN)
 
+#define CFIELD_PREP(_mask, _val)                                       \
+       (((typeof(_mask))(_val) << (__builtin_ffsll(_mask) - 1)) & (_mask))
+
 struct st7701_panel_desc {
        const struct drm_display_mode *mode;
        unsigned int lanes;
        enum mipi_dsi_pixel_format format;
        unsigned int panel_sleep_delay;
+
+       /* TFT matrix driver configuration, panel specific. */
+       const u8        pv_gamma[16];   /* Positive voltage gamma control */
+       const u8        nv_gamma[16];   /* Negative voltage gamma control */
 };
 
 struct st7701 {
@@ -122,7 +146,8 @@ static inline int st7701_dsi_write(struct st7701 *st7701, const void *seq,
 
 static void st7701_init_sequence(struct st7701 *st7701)
 {
-       const struct drm_display_mode *mode = st7701->desc->mode;
+       const struct st7701_panel_desc *desc = st7701->desc;
+       const struct drm_display_mode *mode = desc->mode;
 
        ST7701_DSI(st7701, MIPI_DCS_SOFT_RESET, 0x00);
 
@@ -136,12 +161,10 @@ static void st7701_init_sequence(struct st7701 *st7701)
        /* Command2, BK0 */
        ST7701_DSI(st7701, DSI_CMD2BKX_SEL,
                   0x77, 0x01, 0x00, 0x00, DSI_CMD2BK0_SEL);
-       ST7701_DSI(st7701, DSI_CMD2_BK0_PVGAMCTRL, 0x00, 0x0E, 0x15, 0x0F,
-                  0x11, 0x08, 0x08, 0x08, 0x08, 0x23, 0x04, 0x13, 0x12,
-                  0x2B, 0x34, 0x1F);
-       ST7701_DSI(st7701, DSI_CMD2_BK0_NVGAMCTRL, 0x00, 0x0E, 0x95, 0x0F,
-                  0x13, 0x07, 0x09, 0x08, 0x08, 0x22, 0x04, 0x10, 0x0E,
-                  0x2C, 0x34, 0x1F);
+       mipi_dsi_dcs_write(st7701->dsi, DSI_CMD2_BK0_PVGAMCTRL,
+                          desc->pv_gamma, ARRAY_SIZE(desc->pv_gamma));
+       mipi_dsi_dcs_write(st7701->dsi, DSI_CMD2_BK0_NVGAMCTRL,
+                          desc->nv_gamma, ARRAY_SIZE(desc->nv_gamma));
        ST7701_DSI(st7701, DSI_CMD2_BK0_LNESET,
                   DSI_CMD2_BK0_LNESET_B0, DSI_CMD2_BK0_LNESET_B1);
        ST7701_DSI(st7701, DSI_CMD2_BK0_PORCTRL,
@@ -312,6 +335,65 @@ static const struct st7701_panel_desc ts8550b_desc = {
        .lanes = 2,
        .format = MIPI_DSI_FMT_RGB888,
        .panel_sleep_delay = 80, /* panel need extra 80ms for sleep out cmd */
+
+       .pv_gamma = {
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC0_MASK, 0),
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC4_MASK, 0xe),
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC8_MASK, 0x15),
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC16_MASK, 0xf),
+
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC24_MASK, 0x11),
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC52_MASK, 0x8),
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC80_MASK, 0x8),
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC108_MASK, 0x8),
+
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC147_MASK, 0x8),
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC175_MASK, 0x23),
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC203_MASK, 0x4),
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC231_MASK, 0x13),
+
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC239_MASK, 0x12),
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC247_MASK, 0x2b),
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC251_MASK, 0x34),
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC255_MASK, 0x1f)
+       },
+       .nv_gamma = {
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC0_MASK, 0),
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC4_MASK, 0xe),
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0x2) |
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC8_MASK, 0x15),
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC16_MASK, 0xf),
+
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC24_MASK, 0x13),
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC52_MASK, 0x7),
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC80_MASK, 0x9),
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC108_MASK, 0x8),
+
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC147_MASK, 0x8),
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC175_MASK, 0x22),
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC203_MASK, 0x4),
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC231_MASK, 0x10),
+
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC239_MASK, 0xe),
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC247_MASK, 0x2c),
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC251_MASK, 0x34),
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC255_MASK, 0x1f)
+       },
 };
 
 static int st7701_dsi_probe(struct mipi_dsi_device *dsi)