staging: fbtft: Add minipitft13 variant
authorPhil Elwell <phil@raspberrypi.com>
Fri, 19 Feb 2021 10:25:01 +0000 (10:25 +0000)
committerDom Cobley <popcornmix@gmail.com>
Mon, 19 Feb 2024 11:33:10 +0000 (11:33 +0000)
The Adafruit Mini-PiTFT13 display needs offsets applying when rotated,
so use the "variant" mechanism to select a custom set_addr_win method
using a dedicated compatible string of "fbtft,minipitft13".

See: https://github.com/raspberrypi/firmware/issues/1524

Signed-off-by: Phil Elwell <phil@raspberrypi.com>
drivers/staging/fbtft/fb_st7789v.c

index 861a154..3bcd9ee 100644 (file)
@@ -75,6 +75,11 @@ enum st7789v_command {
 
 static struct completion panel_te; /* completion for panel TE line */
 static int irq_te; /* Linux IRQ for LCD TE line */
+static u32 col_offset = 0;
+static u32 row_offset = 0;
+static u8 col_hack_fix_offset = 0;
+static short x_offset = 0;
+static short y_offset = 0;
 
 static irqreturn_t panel_te_handler(int irq, void *data)
 {
@@ -261,6 +266,22 @@ static int write_vmem(struct fbtft_par *par, size_t offset, size_t len)
        return ret;
 }
 
+static void minipitft13_set_addr_win(struct fbtft_par *par, int xs, int ys,
+                                    int xe, int ye)
+{
+       xs += x_offset;
+       xe += x_offset;
+       ys += y_offset;
+       ye += y_offset;
+       write_reg(par, MIPI_DCS_SET_COLUMN_ADDRESS,
+                 xs >> 8, xs & 0xFF, xe >> 8, xe & 0xFF);
+
+       write_reg(par, MIPI_DCS_SET_PAGE_ADDRESS,
+                 ys >> 8, ys & 0xFF, ye >> 8, ye & 0xFF);
+
+       write_reg(par, MIPI_DCS_WRITE_MEMORY_START);
+}
+
 /**
  * set_var() - apply LCD properties like rotation and BGR mode
  *
@@ -271,20 +292,32 @@ static int write_vmem(struct fbtft_par *par, size_t offset, size_t len)
 static int set_var(struct fbtft_par *par)
 {
        u8 madctl_par = 0;
+       struct fbtft_display *display = &par->pdata->display;
+       u32 width = display->width;
+       u32 height = display->height;
 
        if (par->bgr)
                madctl_par |= MADCTL_BGR;
        switch (par->info->var.rotate) {
        case 0:
+               x_offset = 0;
+               y_offset = 0;
                break;
        case 90:
                madctl_par |= (MADCTL_MV | MADCTL_MY);
+               x_offset = (320 - height) - row_offset;
+               y_offset = (240 - width) - col_offset;
                break;
        case 180:
                madctl_par |= (MADCTL_MX | MADCTL_MY);
+               x_offset = (240 - width) - col_offset + col_hack_fix_offset;
+               // hack tweak to account for extra pixel width to make even
+               y_offset = (320 - height) - row_offset;
                break;
        case 270:
                madctl_par |= (MADCTL_MV | MADCTL_MX);
+               x_offset = row_offset;
+               y_offset = col_offset;
                break;
        default:
                return -EINVAL;
@@ -382,7 +415,16 @@ static struct fbtft_display display = {
        },
 };
 
-FBTFT_REGISTER_DRIVER(DRVNAME, "sitronix,st7789v", &display);
+int variant_minipitft13(struct fbtft_display *display)
+{
+       display->fbtftops.set_addr_win = minipitft13_set_addr_win;
+       return 0;
+}
+
+FBTFT_REGISTER_DRIVER_START(&display)
+FBTFT_COMPATIBLE("sitronix,st7789v")
+FBTFT_VARIANT_COMPATIBLE("fbtft,minipitft13", variant_minipitft13)
+FBTFT_REGISTER_DRIVER_END(DRVNAME, &display);
 
 MODULE_ALIAS("spi:" DRVNAME);
 MODULE_ALIAS("platform:" DRVNAME);