Every drm/tiny MIPI DBI driver pins mode_config.max_width/max_height to
the panel size, so KMS rejects any framebuffer that is not exactly
panel-sized:

    ili9341 spi0.0: bad framebuffer width 480, should be >= 240 && <= 240

Raise the maximums to DRM_SHADOW_PLANE_MAX_WIDTH/HEIGHT (which its
kerneldoc recommends for shadow-plane drivers) on the drivers that flush
through the shared drm_mipi_dbi_plane_helper_atomic_update(), so a client
can allocate a larger framebuffer and pick the displayed region through
the plane source rectangle - a crop / pan with no scaling, now that
drm_mipi_dbi honours the source offset (previous patch):

    ili9341, hx8357d, ili9486, mi0283qt, ili9163, panel-mipi-dbi,
    st7735r

The fixed mode, the minimums and the connector are unchanged. The plane
check (drm_mipi_dbi_plane_helper_atomic_check) still forbids scaling and
repositioning, and the transfer buffer is sized from the display mode,
so the flushed rectangle stays bounded by the panel regardless of the
framebuffer dimensions.

ili9225 is left out: it has its own atomic_update / ili9225_fb_dirty()
that addresses the panel from the damage rectangle without the source
offset, so raising its limits would let a mispositioned buffer through.

st7735r lives under drivers/gpu/drm/sitronix/ rather than
drivers/gpu/drm/tiny/ and was missed in the original pass over this
list; confirmed by grepping the whole tree for
DRM_MIPI_DBI_PLANE_HELPER_FUNCS, which finds exactly these seven
drivers and no others.

Cc: Dave Stevenson <[email protected]>
Signed-off-by: Jonathan Frazin <[email protected]>
---
Changes since v2:
- Add st7735r, missed from the original list because it lives under
  drivers/gpu/drm/sitronix/ rather than drivers/gpu/drm/tiny/. Confirmed
  by grepping the whole tree for DRM_MIPI_DBI_PLANE_HELPER_FUNCS that no
  other driver shares this flush path. Thanks to the automated review
  for catching this.

Changes since v1: unchanged.

 drivers/gpu/drm/sitronix/st7735r.c    | 8 ++++++--
 drivers/gpu/drm/tiny/hx8357d.c        | 8 ++++++--
 drivers/gpu/drm/tiny/ili9163.c        | 8 ++++++--
 drivers/gpu/drm/tiny/ili9341.c        | 8 ++++++--
 drivers/gpu/drm/tiny/ili9486.c        | 8 ++++++--
 drivers/gpu/drm/tiny/mi0283qt.c       | 8 ++++++--
 drivers/gpu/drm/tiny/panel-mipi-dbi.c | 8 ++++++--
 7 files changed, 42 insertions(+), 14 deletions(-)

diff --git a/drivers/gpu/drm/sitronix/st7735r.c 
b/drivers/gpu/drm/sitronix/st7735r.c
index bd763871d..e78bd2da3 100644
--- a/drivers/gpu/drm/sitronix/st7735r.c
+++ b/drivers/gpu/drm/sitronix/st7735r.c
@@ -295,9 +295,13 @@ static int st7735r_probe(struct spi_device *spi)
                return ret;
 
        drm->mode_config.min_width = dbidev->mode.hdisplay;
-       drm->mode_config.max_width = dbidev->mode.hdisplay;
+       /*
+        * Allow a framebuffer larger than the panel so a sub-region can be
+        * displayed via the plane source rectangle (crop / pan, no scaling).
+        */
+       drm->mode_config.max_width = DRM_SHADOW_PLANE_MAX_WIDTH;
        drm->mode_config.min_height = dbidev->mode.vdisplay;
-       drm->mode_config.max_height = dbidev->mode.vdisplay;
+       drm->mode_config.max_height = DRM_SHADOW_PLANE_MAX_HEIGHT;
        drm->mode_config.funcs = &st7735r_mode_config_funcs;
        drm->mode_config.preferred_depth = 16;
        drm->mode_config.helper_private = &st7735r_mode_config_helper_funcs;
diff --git a/drivers/gpu/drm/tiny/hx8357d.c b/drivers/gpu/drm/tiny/hx8357d.c
index f942a8d09..0599b8ccf 100644
--- a/drivers/gpu/drm/tiny/hx8357d.c
+++ b/drivers/gpu/drm/tiny/hx8357d.c
@@ -320,9 +320,13 @@ static int hx8357d_probe(struct spi_device *spi)
                return ret;
 
        drm->mode_config.min_width = dbidev->mode.hdisplay;
-       drm->mode_config.max_width = dbidev->mode.hdisplay;
+       /*
+        * Allow a framebuffer larger than the panel so a sub-region can be
+        * displayed via the plane source rectangle (crop / pan, no scaling).
+        */
+       drm->mode_config.max_width = DRM_SHADOW_PLANE_MAX_WIDTH;
        drm->mode_config.min_height = dbidev->mode.vdisplay;
-       drm->mode_config.max_height = dbidev->mode.vdisplay;
+       drm->mode_config.max_height = DRM_SHADOW_PLANE_MAX_HEIGHT;
        drm->mode_config.funcs = &hx8357d_mode_config_funcs;
        drm->mode_config.preferred_depth = 16;
        drm->mode_config.helper_private = &hx8357d_mode_config_helper_funcs;
diff --git a/drivers/gpu/drm/tiny/ili9163.c b/drivers/gpu/drm/tiny/ili9163.c
index 884242450..fe6c13056 100644
--- a/drivers/gpu/drm/tiny/ili9163.c
+++ b/drivers/gpu/drm/tiny/ili9163.c
@@ -251,9 +251,13 @@ static int ili9163_probe(struct spi_device *spi)
                return ret;
 
        drm->mode_config.min_width = dbidev->mode.hdisplay;
-       drm->mode_config.max_width = dbidev->mode.hdisplay;
+       /*
+        * Allow a framebuffer larger than the panel so a sub-region can be
+        * displayed via the plane source rectangle (crop / pan, no scaling).
+        */
+       drm->mode_config.max_width = DRM_SHADOW_PLANE_MAX_WIDTH;
        drm->mode_config.min_height = dbidev->mode.vdisplay;
-       drm->mode_config.max_height = dbidev->mode.vdisplay;
+       drm->mode_config.max_height = DRM_SHADOW_PLANE_MAX_HEIGHT;
        drm->mode_config.funcs = &ili9163_mode_config_funcs;
        drm->mode_config.preferred_depth = 16;
        drm->mode_config.helper_private = &ili9163_mode_config_helper_funcs;
diff --git a/drivers/gpu/drm/tiny/ili9341.c b/drivers/gpu/drm/tiny/ili9341.c
index 003381aa2..1e4bb56e3 100644
--- a/drivers/gpu/drm/tiny/ili9341.c
+++ b/drivers/gpu/drm/tiny/ili9341.c
@@ -282,9 +282,13 @@ static int ili9341_probe(struct spi_device *spi)
                return ret;
 
        drm->mode_config.min_width = dbidev->mode.hdisplay;
-       drm->mode_config.max_width = dbidev->mode.hdisplay;
+       /*
+        * Allow a framebuffer larger than the panel so a sub-region can be
+        * displayed via the plane source rectangle (crop / pan, no scaling).
+        */
+       drm->mode_config.max_width = DRM_SHADOW_PLANE_MAX_WIDTH;
        drm->mode_config.min_height = dbidev->mode.vdisplay;
-       drm->mode_config.max_height = dbidev->mode.vdisplay;
+       drm->mode_config.max_height = DRM_SHADOW_PLANE_MAX_HEIGHT;
        drm->mode_config.funcs = &ili9341_mode_config_funcs;
        drm->mode_config.preferred_depth = 16;
        drm->mode_config.helper_private = &ili9341_mode_config_helper_funcs;
diff --git a/drivers/gpu/drm/tiny/ili9486.c b/drivers/gpu/drm/tiny/ili9486.c
index fab8bd7ce..de33d702a 100644
--- a/drivers/gpu/drm/tiny/ili9486.c
+++ b/drivers/gpu/drm/tiny/ili9486.c
@@ -309,9 +309,13 @@ static int ili9486_probe(struct spi_device *spi)
                return ret;
 
        drm->mode_config.min_width = dbidev->mode.hdisplay;
-       drm->mode_config.max_width = dbidev->mode.hdisplay;
+       /*
+        * Allow a framebuffer larger than the panel so a sub-region can be
+        * displayed via the plane source rectangle (crop / pan, no scaling).
+        */
+       drm->mode_config.max_width = DRM_SHADOW_PLANE_MAX_WIDTH;
        drm->mode_config.min_height = dbidev->mode.vdisplay;
-       drm->mode_config.max_height = dbidev->mode.vdisplay;
+       drm->mode_config.max_height = DRM_SHADOW_PLANE_MAX_HEIGHT;
        drm->mode_config.funcs = &ili9486_mode_config_funcs;
        drm->mode_config.preferred_depth = 16;
        drm->mode_config.helper_private = &ili9486_mode_config_helper_funcs;
diff --git a/drivers/gpu/drm/tiny/mi0283qt.c b/drivers/gpu/drm/tiny/mi0283qt.c
index b0121e89e..df3801914 100644
--- a/drivers/gpu/drm/tiny/mi0283qt.c
+++ b/drivers/gpu/drm/tiny/mi0283qt.c
@@ -290,9 +290,13 @@ static int mi0283qt_probe(struct spi_device *spi)
                return ret;
 
        drm->mode_config.min_width = dbidev->mode.hdisplay;
-       drm->mode_config.max_width = dbidev->mode.hdisplay;
+       /*
+        * Allow a framebuffer larger than the panel so a sub-region can be
+        * displayed via the plane source rectangle (crop / pan, no scaling).
+        */
+       drm->mode_config.max_width = DRM_SHADOW_PLANE_MAX_WIDTH;
        drm->mode_config.min_height = dbidev->mode.vdisplay;
-       drm->mode_config.max_height = dbidev->mode.vdisplay;
+       drm->mode_config.max_height = DRM_SHADOW_PLANE_MAX_HEIGHT;
        drm->mode_config.funcs = &mi0283qt_mode_config_funcs;
        drm->mode_config.preferred_depth = 16;
        drm->mode_config.helper_private = &mi0283qt_mode_config_helper_funcs;
diff --git a/drivers/gpu/drm/tiny/panel-mipi-dbi.c 
b/drivers/gpu/drm/tiny/panel-mipi-dbi.c
index 60cd65cae..a0a098b0d 100644
--- a/drivers/gpu/drm/tiny/panel-mipi-dbi.c
+++ b/drivers/gpu/drm/tiny/panel-mipi-dbi.c
@@ -448,9 +448,13 @@ static int panel_mipi_dbi_spi_probe(struct spi_device *spi)
                return ret;
 
        drm->mode_config.min_width = dbidev->mode.hdisplay;
-       drm->mode_config.max_width = dbidev->mode.hdisplay;
+       /*
+        * Allow a framebuffer larger than the panel so a sub-region can be
+        * displayed via the plane source rectangle (crop / pan, no scaling).
+        */
+       drm->mode_config.max_width = DRM_SHADOW_PLANE_MAX_WIDTH;
        drm->mode_config.min_height = dbidev->mode.vdisplay;
-       drm->mode_config.max_height = dbidev->mode.vdisplay;
+       drm->mode_config.max_height = DRM_SHADOW_PLANE_MAX_HEIGHT;
        drm->mode_config.funcs = &panel_mipi_dbi_mode_config_funcs;
        drm->mode_config.preferred_depth = bpp;
        drm->mode_config.helper_private = 
&panel_mipi_dbi_mode_config_helper_funcs;
-- 
2.53.0

Reply via email to