This switches to drm_atomic_helper_dirtyfb() as the framebuffer dirty handler. All flushing will now happen in the pipe functions. Also enable the damage plane property for all except repaper which can only do full updates. ili9225: This change made ili9225_init() equal to mipi_dbi_init() so use it. v2: Remove fb check in mipi_dbi_enable_flush() it can't be NULL (kbuild test robot) Cc: David Lechner <david@xxxxxxxxxxxxxx> Cc: Eric Anholt <eric@xxxxxxxxxx> Signed-off-by: Noralf Trønnes <noralf@xxxxxxxxxxx> Acked-by: Sam Ravnborg <sam@xxxxxxxxxxxx> Acked-by: Daniel Vetter <daniel.vetter@xxxxxxxx> --- drivers/gpu/drm/tinydrm/core/tinydrm-core.c | 21 +--- .../gpu/drm/tinydrm/core/tinydrm-helpers.c | 91 +--------------- drivers/gpu/drm/tinydrm/core/tinydrm-pipe.c | 30 ------ drivers/gpu/drm/tinydrm/hx8357d.c | 2 +- drivers/gpu/drm/tinydrm/ili9225.c | 101 ++++++------------ drivers/gpu/drm/tinydrm/ili9341.c | 2 +- drivers/gpu/drm/tinydrm/mi0283qt.c | 2 +- drivers/gpu/drm/tinydrm/mipi-dbi.c | 74 ++++++++----- drivers/gpu/drm/tinydrm/repaper.c | 39 ++++--- drivers/gpu/drm/tinydrm/st7586.c | 50 +++++---- drivers/gpu/drm/tinydrm/st7735r.c | 2 +- include/drm/tinydrm/mipi-dbi.h | 2 + include/drm/tinydrm/tinydrm-helpers.h | 11 +- include/drm/tinydrm/tinydrm.h | 26 ----- 14 files changed, 138 insertions(+), 315 deletions(-) diff --git a/drivers/gpu/drm/tinydrm/core/tinydrm-core.c b/drivers/gpu/drm/tinydrm/core/tinydrm-core.c index aeb93eadb047..614f532ea89f 100644 --- a/drivers/gpu/drm/tinydrm/core/tinydrm-core.c +++ b/drivers/gpu/drm/tinydrm/core/tinydrm-core.c @@ -39,31 +39,17 @@ * and registers the DRM device using devm_tinydrm_register(). */ -static struct drm_framebuffer * -tinydrm_fb_create(struct drm_device *drm, struct drm_file *file_priv, - const struct drm_mode_fb_cmd2 *mode_cmd) -{ - struct tinydrm_device *tdev = drm->dev_private; - - return drm_gem_fb_create_with_funcs(drm, file_priv, mode_cmd, - tdev->fb_funcs); -} - static const struct drm_mode_config_funcs tinydrm_mode_config_funcs = { - .fb_create = tinydrm_fb_create, + .fb_create = drm_gem_fb_create_with_dirty, .atomic_check = drm_atomic_helper_check, .atomic_commit = drm_atomic_helper_commit, }; static int tinydrm_init(struct device *parent, struct tinydrm_device *tdev, - const struct drm_framebuffer_funcs *fb_funcs, struct drm_driver *driver) { struct drm_device *drm; - mutex_init(&tdev->dirty_lock); - tdev->fb_funcs = fb_funcs; - /* * We don't embed drm_device, because that prevent us from using * devm_kzalloc() to allocate tinydrm_device in the driver since @@ -86,7 +72,6 @@ static int tinydrm_init(struct device *parent, struct tinydrm_device *tdev, static void tinydrm_fini(struct tinydrm_device *tdev) { drm_mode_config_cleanup(tdev->drm); - mutex_destroy(&tdev->dirty_lock); tdev->drm->dev_private = NULL; drm_dev_put(tdev->drm); } @@ -100,7 +85,6 @@ static void devm_tinydrm_release(void *data) * devm_tinydrm_init - Initialize tinydrm device * @parent: Parent device object * @tdev: tinydrm device - * @fb_funcs: Framebuffer functions * @driver: DRM driver * * This function initializes @tdev, the underlying DRM device and it's @@ -111,12 +95,11 @@ static void devm_tinydrm_release(void *data) * Zero on success, negative error code on failure. */ int devm_tinydrm_init(struct device *parent, struct tinydrm_device *tdev, - const struct drm_framebuffer_funcs *fb_funcs, struct drm_driver *driver) { int ret; - ret = tinydrm_init(parent, tdev, fb_funcs, driver); + ret = tinydrm_init(parent, tdev, driver); if (ret) return ret; diff --git a/drivers/gpu/drm/tinydrm/core/tinydrm-helpers.c b/drivers/gpu/drm/tinydrm/core/tinydrm-helpers.c index d0ece6ad4a1c..2737b6fdadc8 100644 --- a/drivers/gpu/drm/tinydrm/core/tinydrm-helpers.c +++ b/drivers/gpu/drm/tinydrm/core/tinydrm-helpers.c @@ -17,104 +17,15 @@ #include <drm/drm_device.h> #include <drm/drm_drv.h> #include <drm/drm_fourcc.h> +#include <drm/drm_framebuffer.h> #include <drm/drm_print.h> #include <drm/drm_rect.h> -#include <drm/tinydrm/tinydrm.h> #include <drm/tinydrm/tinydrm-helpers.h> -#include <uapi/drm/drm.h> static unsigned int spi_max; module_param(spi_max, uint, 0400); MODULE_PARM_DESC(spi_max, "Set a lower SPI max transfer size"); -/** - * tinydrm_merge_clips - Merge clip rectangles - * @dst: Destination clip rectangle - * @src: Source clip rectangle(s) - * @num_clips: Number of @src clip rectangles - * @flags: Dirty fb ioctl flags - * @max_width: Maximum width of @dst - * @max_height: Maximum height of @dst - * - * This function merges @src clip rectangle(s) into @dst. If @src is NULL, - * @max_width and @min_width is used to set a full @dst clip rectangle. - * - * Returns: - * true if it's a full clip, false otherwise - */ -bool tinydrm_merge_clips(struct drm_rect *dst, - struct drm_clip_rect *src, unsigned int num_clips, - unsigned int flags, u32 max_width, u32 max_height) -{ - unsigned int i; - - if (!src || !num_clips) { - dst->x1 = 0; - dst->x2 = max_width; - dst->y1 = 0; - dst->y2 = max_height; - return true; - } - - dst->x1 = ~0; - dst->y1 = ~0; - dst->x2 = 0; - dst->y2 = 0; - - for (i = 0; i < num_clips; i++) { - if (flags & DRM_MODE_FB_DIRTY_ANNOTATE_COPY) - i++; - dst->x1 = min_t(int, dst->x1, src[i].x1); - dst->x2 = max_t(int, dst->x2, src[i].x2); - dst->y1 = min_t(int, dst->y1, src[i].y1); - dst->y2 = max_t(int, dst->y2, src[i].y2); - } - - if (dst->x2 > max_width || dst->y2 > max_height || - dst->x1 >= dst->x2 || dst->y1 >= dst->y2) { - DRM_DEBUG_KMS("Illegal clip: x1=%u, x2=%u, y1=%u, y2=%u\n", - dst->x1, dst->x2, dst->y1, dst->y2); - dst->x1 = 0; - dst->y1 = 0; - dst->x2 = max_width; - dst->y2 = max_height; - } - - return (dst->x2 - dst->x1) == max_width && - (dst->y2 - dst->y1) == max_height; -} -EXPORT_SYMBOL(tinydrm_merge_clips); - -int tinydrm_fb_dirty(struct drm_framebuffer *fb, - struct drm_file *file_priv, - unsigned int flags, unsigned int color, - struct drm_clip_rect *clips, - unsigned int num_clips) -{ - struct tinydrm_device *tdev = fb->dev->dev_private; - struct drm_plane *plane = &tdev->pipe.plane; - int ret = 0; - - drm_modeset_lock(&plane->mutex, NULL); - - /* fbdev can flush even when we're not interested */ - if (plane->state->fb == fb) { - mutex_lock(&tdev->dirty_lock); - ret = tdev->fb_dirty(fb, file_priv, flags, - color, clips, num_clips); - mutex_unlock(&tdev->dirty_lock); - } - - drm_modeset_unlock(&plane->mutex); - - if (ret) - dev_err_once(fb->dev->dev, - "Failed to update display %d\n", ret); - - return ret; -} -EXPORT_SYMBOL(tinydrm_fb_dirty); - /** * tinydrm_memcpy - Copy clip buffer * @dst: Destination buffer diff --git a/drivers/gpu/drm/tinydrm/core/tinydrm-pipe.c b/drivers/gpu/drm/tinydrm/core/tinydrm-pipe.c index d4576d6e8ce4..a4796ddb08f0 100644 --- a/drivers/gpu/drm/tinydrm/core/tinydrm-pipe.c +++ b/drivers/gpu/drm/tinydrm/core/tinydrm-pipe.c @@ -111,36 +111,6 @@ tinydrm_connector_create(struct drm_device *drm, return connector; } -/** - * tinydrm_display_pipe_update - Display pipe update helper - * @pipe: Simple display pipe - * @old_state: Old plane state - * - * This function does a full framebuffer flush if the plane framebuffer - * has changed. It also handles vblank events. Drivers can use this as their - * &drm_simple_display_pipe_funcs->update callback. - */ -void tinydrm_display_pipe_update(struct drm_simple_display_pipe *pipe, - struct drm_plane_state *old_state) -{ - struct tinydrm_device *tdev = pipe_to_tinydrm(pipe); - struct drm_framebuffer *fb = pipe->plane.state->fb; - struct drm_crtc *crtc = &tdev->pipe.crtc; - - if (fb && (fb != old_state->fb)) { - if (tdev->fb_dirty) - tdev->fb_dirty(fb, NULL, 0, 0, NULL, 0); - } - - if (crtc->state->event) { - spin_lock_irq(&crtc->dev->event_lock); - drm_crtc_send_vblank_event(crtc, crtc->state->event); - spin_unlock_irq(&crtc->dev->event_lock); - crtc->state->event = NULL; - } -} -EXPORT_SYMBOL(tinydrm_display_pipe_update); - static int tinydrm_rotate_mode(struct drm_display_mode *mode, unsigned int rotation) { diff --git a/drivers/gpu/drm/tinydrm/hx8357d.c b/drivers/gpu/drm/tinydrm/hx8357d.c index 3ae11aa4b73b..8bbd0beafc6a 100644 --- a/drivers/gpu/drm/tinydrm/hx8357d.c +++ b/drivers/gpu/drm/tinydrm/hx8357d.c @@ -176,7 +176,7 @@ static void yx240qv29_enable(struct drm_simple_display_pipe *pipe, static const struct drm_simple_display_pipe_funcs hx8357d_pipe_funcs = { .enable = yx240qv29_enable, .disable = mipi_dbi_pipe_disable, - .update = tinydrm_display_pipe_update, + .update = mipi_dbi_pipe_update, .prepare_fb = drm_gem_fb_simple_display_pipe_prepare_fb, }; diff --git a/drivers/gpu/drm/tinydrm/ili9225.c b/drivers/gpu/drm/tinydrm/ili9225.c index ad644069089f..aa1376a22bda 100644 --- a/drivers/gpu/drm/tinydrm/ili9225.c +++ b/drivers/gpu/drm/tinydrm/ili9225.c @@ -20,6 +20,7 @@ #include <linux/spi/spi.h> #include <video/mipi_display.h> +#include <drm/drm_damage_helper.h> #include <drm/drm_drv.h> #include <drm/drm_fb_cma_helper.h> #include <drm/drm_fourcc.h> @@ -76,17 +77,14 @@ static inline int ili9225_command(struct mipi_dbi *mipi, u8 cmd, u16 data) return mipi_dbi_command_buf(mipi, cmd, par, 2); } -static int ili9225_fb_dirty(struct drm_framebuffer *fb, - struct drm_file *file_priv, unsigned int flags, - unsigned int color, struct drm_clip_rect *clips, - unsigned int num_clips) +static void ili9225_fb_dirty(struct drm_framebuffer *fb, struct drm_rect *rect) { struct drm_gem_cma_object *cma_obj = drm_fb_cma_get_gem_obj(fb, 0); struct tinydrm_device *tdev = fb->dev->dev_private; struct mipi_dbi *mipi = mipi_dbi_from_tinydrm(tdev); + unsigned int height = rect->y2 - rect->y1; + unsigned int width = rect->x2 - rect->x1; bool swap = mipi->swap_bytes; - struct drm_rect clip; - struct drm_rect *rect = &clip; u16 x_start, y_start; u16 x1, x2, y1, y2; int ret = 0; @@ -94,10 +92,9 @@ static int ili9225_fb_dirty(struct drm_framebuffer *fb, void *tr; if (!mipi->enabled) - return 0; + return; - full = tinydrm_merge_clips(&clip, clips, num_clips, flags, - fb->width, fb->height); + full = width == fb->width && height == fb->height; DRM_DEBUG_KMS("Flushing [FB:%d] " DRM_RECT_FMT "\n", fb->base.id, DRM_RECT_ARG(rect)); @@ -106,7 +103,7 @@ static int ili9225_fb_dirty(struct drm_framebuffer *fb, tr = mipi->tx_buf; ret = mipi_dbi_buf_copy(mipi->tx_buf, fb, rect, swap); if (ret) - return ret; + goto err_msg; } else { tr = cma_obj->vaddr; } @@ -155,16 +152,29 @@ static int ili9225_fb_dirty(struct drm_framebuffer *fb, ili9225_command(mipi, ILI9225_RAM_ADDRESS_SET_2, y_start); ret = mipi_dbi_command_buf(mipi, ILI9225_WRITE_DATA_TO_GRAM, tr, - (rect->x2 - rect->x1) * (rect->y2 - rect->y1) * 2); - - return ret; + width * height * 2); +err_msg: + if (ret) + dev_err_once(fb->dev->dev, "Failed to update display %d\n", ret); } -static const struct drm_framebuffer_funcs ili9225_fb_funcs = { - .destroy = drm_gem_fb_destroy, - .create_handle = drm_gem_fb_create_handle, - .dirty = tinydrm_fb_dirty, -}; +static void ili9225_pipe_update(struct drm_simple_display_pipe *pipe, + struct drm_plane_state *old_state) +{ + struct drm_plane_state *state = pipe->plane.state; + struct drm_crtc *crtc = &pipe->crtc; + struct drm_rect rect; + + if (drm_atomic_helper_damage_merged(old_state, state, &rect)) + ili9225_fb_dirty(state->fb, &rect); + + if (crtc->state->event) { + spin_lock_irq(&crtc->dev->event_lock); + drm_crtc_send_vblank_event(crtc, crtc->state->event); + spin_unlock_irq(&crtc->dev->event_lock); + crtc->state->event = NULL; + } +} static void ili9225_pipe_enable(struct drm_simple_display_pipe *pipe, struct drm_crtc_state *crtc_state, @@ -305,59 +315,10 @@ static int ili9225_dbi_command(struct mipi_dbi *mipi, u8 cmd, u8 *par, return tinydrm_spi_transfer(spi, speed_hz, NULL, bpw, par, num); } -static const u32 ili9225_formats[] = { - DRM_FORMAT_RGB565, - DRM_FORMAT_XRGB8888, -}; - -static int ili9225_init(struct device *dev, struct mipi_dbi *mipi, - const struct drm_simple_display_pipe_funcs *pipe_funcs, - struct drm_driver *driver, - const struct drm_display_mode *mode, - unsigned int rotation) -{ - size_t bufsize = mode->vdisplay * mode->hdisplay * sizeof(u16); - struct tinydrm_device *tdev = &mipi->tinydrm; - int ret; - - if (!mipi->command) - return -EINVAL; - - mutex_init(&mipi->cmdlock); - - mipi->tx_buf = devm_kmalloc(dev, bufsize, GFP_KERNEL); - if (!mipi->tx_buf) - return -ENOMEM; - - ret = devm_tinydrm_init(dev, tdev, &ili9225_fb_funcs, driver); - if (ret) - return ret; - - tdev->fb_dirty = ili9225_fb_dirty; - - ret = tinydrm_display_pipe_init(tdev, pipe_funcs, - DRM_MODE_CONNECTOR_VIRTUAL, - ili9225_formats, - ARRAY_SIZE(ili9225_formats), mode, - rotation); - if (ret) - return ret; - - tdev->drm->mode_config.preferred_depth = 16; - mipi->rotation = rotation; - - drm_mode_config_reset(tdev->drm); - - DRM_DEBUG_KMS("preferred_depth=%u, rotation = %u\n", - tdev->drm->mode_config.preferred_depth, rotation); - - return 0; -} - static const struct drm_simple_display_pipe_funcs ili9225_pipe_funcs = { .enable = ili9225_pipe_enable, .disable = ili9225_pipe_disable, - .update = tinydrm_display_pipe_update, + .update = ili9225_pipe_update, .prepare_fb = drm_gem_fb_simple_display_pipe_prepare_fb, }; @@ -424,8 +385,8 @@ static int ili9225_probe(struct spi_device *spi) /* override the command function set in mipi_dbi_spi_init() */ mipi->command = ili9225_dbi_command; - ret = ili9225_init(&spi->dev, mipi, &ili9225_pipe_funcs, - &ili9225_driver, &ili9225_mode, rotation); + ret = mipi_dbi_init(&spi->dev, mipi, &ili9225_pipe_funcs, + &ili9225_driver, &ili9225_mode, rotation); if (ret) return ret; diff --git a/drivers/gpu/drm/tinydrm/ili9341.c b/drivers/gpu/drm/tinydrm/ili9341.c index bcdf10906ade..713bb2dd7e04 100644 --- a/drivers/gpu/drm/tinydrm/ili9341.c +++ b/drivers/gpu/drm/tinydrm/ili9341.c @@ -132,7 +132,7 @@ static void yx240qv29_enable(struct drm_simple_display_pipe *pipe, static const struct drm_simple_display_pipe_funcs ili9341_pipe_funcs = { .enable = yx240qv29_enable, .disable = mipi_dbi_pipe_disable, - .update = tinydrm_display_pipe_update, + .update = mipi_dbi_pipe_update, .prepare_fb = drm_gem_fb_simple_display_pipe_prepare_fb, }; diff --git a/drivers/gpu/drm/tinydrm/mi0283qt.c b/drivers/gpu/drm/tinydrm/mi0283qt.c index 97805ca37a04..82a92ec9ae3c 100644 --- a/drivers/gpu/drm/tinydrm/mi0283qt.c +++ b/drivers/gpu/drm/tinydrm/mi0283qt.c @@ -140,7 +140,7 @@ static void mi0283qt_enable(struct drm_simple_display_pipe *pipe, static const struct drm_simple_display_pipe_funcs mi0283qt_pipe_funcs = { .enable = mi0283qt_enable, .disable = mipi_dbi_pipe_disable, - .update = tinydrm_display_pipe_update, + .update = mipi_dbi_pipe_update, .prepare_fb = drm_gem_fb_simple_display_pipe_prepare_fb, }; diff --git a/drivers/gpu/drm/tinydrm/mipi-dbi.c b/drivers/gpu/drm/tinydrm/mipi-dbi.c index 1e7e8cfc99f0..680692a83f94 100644 --- a/drivers/gpu/drm/tinydrm/mipi-dbi.c +++ b/drivers/gpu/drm/tinydrm/mipi-dbi.c @@ -17,6 +17,7 @@ #include <linux/regulator/consumer.h> #include <linux/spi/spi.h> +#include <drm/drm_damage_helper.h> #include <drm/drm_drv.h> #include <drm/drm_fb_cma_helper.h> #include <drm/drm_gem_cma_helper.h> @@ -25,7 +26,6 @@ #include <drm/drm_rect.h> #include <drm/tinydrm/mipi-dbi.h> #include <drm/tinydrm/tinydrm-helpers.h> -#include <uapi/drm/drm.h> #include <video/mipi_display.h> #define MIPI_DBI_MAX_SPI_READ_SPEED 2000000 /* 2MHz */ @@ -212,27 +212,22 @@ int mipi_dbi_buf_copy(void *dst, struct drm_framebuffer *fb, } EXPORT_SYMBOL(mipi_dbi_buf_copy); -static int mipi_dbi_fb_dirty(struct drm_framebuffer *fb, - struct drm_file *file_priv, - unsigned int flags, unsigned int color, - struct drm_clip_rect *clips, - unsigned int num_clips) +static void mipi_dbi_fb_dirty(struct drm_framebuffer *fb, struct drm_rect *rect) { struct drm_gem_cma_object *cma_obj = drm_fb_cma_get_gem_obj(fb, 0); struct tinydrm_device *tdev = fb->dev->dev_private; struct mipi_dbi *mipi = mipi_dbi_from_tinydrm(tdev); + unsigned int height = rect->y2 - rect->y1; + unsigned int width = rect->x2 - rect->x1; bool swap = mipi->swap_bytes; - struct drm_rect clip; - struct drm_rect *rect = &clip; int ret = 0; bool full; void *tr; if (!mipi->enabled) - return 0; + return; - full = tinydrm_merge_clips(&clip, clips, num_clips, flags, - fb->width, fb->height); + full = width == fb->width && height == fb->height; DRM_DEBUG_KMS("Flushing [FB:%d] " DRM_RECT_FMT "\n", fb->base.id, DRM_RECT_ARG(rect)); @@ -241,7 +236,7 @@ static int mipi_dbi_fb_dirty(struct drm_framebuffer *fb, tr = mipi->tx_buf; ret = mipi_dbi_buf_copy(mipi->tx_buf, fb, rect, swap); if (ret) - return ret; + goto err_msg; } else { tr = cma_obj->vaddr; } @@ -254,16 +249,38 @@ static int mipi_dbi_fb_dirty(struct drm_framebuffer *fb, ((rect->y2 - 1) >> 8) & 0xff, (rect->y2 - 1) & 0xff); ret = mipi_dbi_command_buf(mipi, MIPI_DCS_WRITE_MEMORY_START, tr, - (rect->x2 - rect->x1) * (rect->y2 - rect->y1) * 2); - - return ret; + width * height * 2); +err_msg: + if (ret) + dev_err_once(fb->dev->dev, "Failed to update display %d\n", ret); } -static const struct drm_framebuffer_funcs mipi_dbi_fb_funcs = { - .destroy = drm_gem_fb_destroy, - .create_handle = drm_gem_fb_create_handle, - .dirty = tinydrm_fb_dirty, -}; +/** + * mipi_dbi_pipe_update - Display pipe update helper + * @pipe: Simple display pipe + * @old_state: Old plane state + * + * This function handles framebuffer flushing and vblank events. Drivers can use + * this as their &drm_simple_display_pipe_funcs->update callback. + */ +void mipi_dbi_pipe_update(struct drm_simple_display_pipe *pipe, + struct drm_plane_state *old_state) +{ + struct drm_plane_state *state = pipe->plane.state; + struct drm_crtc *crtc = &pipe->crtc; + struct drm_rect rect; + + if (drm_atomic_helper_damage_merged(old_state, state, &rect)) + mipi_dbi_fb_dirty(state->fb, &rect); + + if (crtc->state->event) { + spin_lock_irq(&crtc->dev->event_lock); + drm_crtc_send_vblank_event(crtc, crtc->state->event); + spin_unlock_irq(&crtc->dev->event_lock); + crtc->state->event = NULL; + } +} +EXPORT_SYMBOL(mipi_dbi_pipe_update); /** * mipi_dbi_enable_flush - MIPI DBI enable helper @@ -279,13 +296,16 @@ void mipi_dbi_enable_flush(struct mipi_dbi *mipi, struct drm_crtc_state *crtc_state, struct drm_plane_state *plane_state) { - struct tinydrm_device *tdev = &mipi->tinydrm; struct drm_framebuffer *fb = plane_state->fb; + struct drm_rect rect = { + .x1 = 0, + .x2 = fb->width, + .y1 = 0, + .y2 = fb->height, + }; mipi->enabled = true; - if (fb) - tdev->fb_dirty(fb, NULL, 0, 0, NULL, 0); - + mipi_dbi_fb_dirty(fb, &rect); backlight_enable(mipi->backlight); } EXPORT_SYMBOL(mipi_dbi_enable_flush); @@ -377,12 +397,10 @@ int mipi_dbi_init(struct device *dev, struct mipi_dbi *mipi, if (!mipi->tx_buf) return -ENOMEM; - ret = devm_tinydrm_init(dev, tdev, &mipi_dbi_fb_funcs, driver); + ret = devm_tinydrm_init(dev, tdev, driver); if (ret) return ret; - tdev->fb_dirty = mipi_dbi_fb_dirty; - /* TODO: Maybe add DRM_MODE_CONNECTOR_SPI */ ret = tinydrm_display_pipe_init(tdev, pipe_funcs, DRM_MODE_CONNECTOR_VIRTUAL, @@ -392,6 +410,8 @@ int mipi_dbi_init(struct device *dev, struct mipi_dbi *mipi, if (ret) return ret; + drm_plane_enable_fb_damage_clips(&tdev->pipe.plane); + tdev->drm->mode_config.preferred_depth = 16; mipi->rotation = rotation; diff --git a/drivers/gpu/drm/tinydrm/repaper.c b/drivers/gpu/drm/tinydrm/repaper.c index 238515de449e..f9cacf49f16b 100644 --- a/drivers/gpu/drm/tinydrm/repaper.c +++ b/drivers/gpu/drm/tinydrm/repaper.c @@ -26,6 +26,7 @@ #include <linux/spi/spi.h> #include <linux/thermal.h> +#include <drm/drm_damage_helper.h> #include <drm/drm_drv.h> #include <drm/drm_fb_cma_helper.h> #include <drm/drm_gem_cma_helper.h> @@ -523,11 +524,7 @@ static void repaper_gray8_to_mono_reversed(u8 *buf, u32 width, u32 height) } } -static int repaper_fb_dirty(struct drm_framebuffer *fb, - struct drm_file *file_priv, - unsigned int flags, unsigned int color, - struct drm_clip_rect *clips, - unsigned int num_clips) +static int repaper_fb_dirty(struct drm_framebuffer *fb) { struct drm_gem_cma_object *cma_obj = drm_fb_cma_get_gem_obj(fb, 0); struct dma_buf_attachment *import_attach = cma_obj->base.import_attach; @@ -626,12 +623,6 @@ static int repaper_fb_dirty(struct drm_framebuffer *fb, return ret; } -static const struct drm_framebuffer_funcs repaper_fb_funcs = { - .destroy = drm_gem_fb_destroy, - .create_handle = drm_gem_fb_create_handle, - .dirty = tinydrm_fb_dirty, -}; - static void power_off(struct repaper_epd *epd) { /* Turn off power and all signals */ @@ -795,9 +786,7 @@ static void repaper_pipe_disable(struct drm_simple_display_pipe *pipe) DRM_DEBUG_DRIVER("\n"); - mutex_lock(&tdev->dirty_lock); epd->enabled = false; - mutex_unlock(&tdev->dirty_lock); /* Nothing frame */ for (line = 0; line < epd->height; line++) @@ -840,10 +829,28 @@ static void repaper_pipe_disable(struct drm_simple_display_pipe *pipe) power_off(epd); } +static void repaper_pipe_update(struct drm_simple_display_pipe *pipe, + struct drm_plane_state *old_state) +{ + struct drm_plane_state *state = pipe->plane.state; + struct drm_crtc *crtc = &pipe->crtc; + struct drm_rect rect; + + if (drm_atomic_helper_damage_merged(old_state, state, &rect)) + repaper_fb_dirty(state->fb); + + if (crtc->state->event) { + spin_lock_irq(&crtc->dev->event_lock); + drm_crtc_send_vblank_event(crtc, crtc->state->event); + spin_unlock_irq(&crtc->dev->event_lock); + crtc->state->event = NULL; + } +} + static const struct drm_simple_display_pipe_funcs repaper_pipe_funcs = { .enable = repaper_pipe_enable, .disable = repaper_pipe_disable, - .update = tinydrm_display_pipe_update, + .update = repaper_pipe_update, .prepare_fb = drm_gem_fb_simple_display_pipe_prepare_fb, }; @@ -1057,12 +1064,10 @@ static int repaper_probe(struct spi_device *spi) tdev = &epd->tinydrm; - ret = devm_tinydrm_init(dev, tdev, &repaper_fb_funcs, &repaper_driver); + ret = devm_tinydrm_init(dev, tdev, &repaper_driver); if (ret) return ret; - tdev->fb_dirty = repaper_fb_dirty; - ret = tinydrm_display_pipe_init(tdev, &repaper_pipe_funcs, DRM_MODE_CONNECTOR_VIRTUAL, repaper_formats, diff --git a/drivers/gpu/drm/tinydrm/st7586.c b/drivers/gpu/drm/tinydrm/st7586.c index a52bc3b02606..50e370ce5a59 100644 --- a/drivers/gpu/drm/tinydrm/st7586.c +++ b/drivers/gpu/drm/tinydrm/st7586.c @@ -17,6 +17,7 @@ #include <linux/spi/spi.h> #include <video/mipi_display.h> +#include <drm/drm_damage_helper.h> #include <drm/drm_drv.h> #include <drm/drm_fb_cma_helper.h> #include <drm/drm_gem_cma_helper.h> @@ -112,23 +113,15 @@ static int st7586_buf_copy(void *dst, struct drm_framebuffer *fb, return ret; } -static int st7586_fb_dirty(struct drm_framebuffer *fb, - struct drm_file *file_priv, unsigned int flags, - unsigned int color, struct drm_clip_rect *clips, - unsigned int num_clips) +static void st7586_fb_dirty(struct drm_framebuffer *fb, struct drm_rect *rect) { struct tinydrm_device *tdev = fb->dev->dev_private; struct mipi_dbi *mipi = mipi_dbi_from_tinydrm(tdev); - struct drm_rect clip; - struct drm_rect *rect = &clip; int start, end; int ret = 0; if (!mipi->enabled) - return 0; - - tinydrm_merge_clips(&clip, clips, num_clips, flags, fb->width, - fb->height); + return; /* 3 pixels per byte, so grow clip to nearest multiple of 3 */ rect->x1 = rounddown(rect->x1, 3); @@ -138,7 +131,7 @@ static int st7586_fb_dirty(struct drm_framebuffer *fb, ret = st7586_buf_copy(mipi->tx_buf, fb, rect); if (ret) - return ret; + goto err_msg; /* Pixels are packed 3 per byte */ start = rect->x1 / 3; @@ -154,15 +147,28 @@ static int st7586_fb_dirty(struct drm_framebuffer *fb, ret = mipi_dbi_command_buf(mipi, MIPI_DCS_WRITE_MEMORY_START, (u8 *)mipi->tx_buf, (end - start) * (rect->y2 - rect->y1)); - - return ret; +err_msg: + if (ret) + dev_err_once(fb->dev->dev, "Failed to update display %d\n", ret); } -static const struct drm_framebuffer_funcs st7586_fb_funcs = { - .destroy = drm_gem_fb_destroy, - .create_handle = drm_gem_fb_create_handle, - .dirty = tinydrm_fb_dirty, -}; +static void st7586_pipe_update(struct drm_simple_display_pipe *pipe, + struct drm_plane_state *old_state) +{ + struct drm_plane_state *state = pipe->plane.state; + struct drm_crtc *crtc = &pipe->crtc; + struct drm_rect rect; + + if (drm_atomic_helper_damage_merged(old_state, state, &rect)) + st7586_fb_dirty(state->fb, &rect); + + if (crtc->state->event) { + spin_lock_irq(&crtc->dev->event_lock); + drm_crtc_send_vblank_event(crtc, crtc->state->event); + spin_unlock_irq(&crtc->dev->event_lock); + crtc->state->event = NULL; + } +} static void st7586_pipe_enable(struct drm_simple_display_pipe *pipe, struct drm_crtc_state *crtc_state, @@ -264,12 +270,10 @@ static int st7586_init(struct device *dev, struct mipi_dbi *mipi, if (!mipi->tx_buf) return -ENOMEM; - ret = devm_tinydrm_init(dev, tdev, &st7586_fb_funcs, driver); + ret = devm_tinydrm_init(dev, tdev, driver); if (ret) return ret; - tdev->fb_dirty = st7586_fb_dirty; - ret = tinydrm_display_pipe_init(tdev, pipe_funcs, DRM_MODE_CONNECTOR_VIRTUAL, st7586_formats, @@ -278,6 +282,8 @@ static int st7586_init(struct device *dev, struct mipi_dbi *mipi, if (ret) return ret; + drm_plane_enable_fb_damage_clips(&tdev->pipe.plane); + tdev->drm->mode_config.preferred_depth = 32; mipi->rotation = rotation; @@ -292,7 +298,7 @@ static int st7586_init(struct device *dev, struct mipi_dbi *mipi, static const struct drm_simple_display_pipe_funcs st7586_pipe_funcs = { .enable = st7586_pipe_enable, .disable = st7586_pipe_disable, - .update = tinydrm_display_pipe_update, + .update = st7586_pipe_update, .prepare_fb = drm_gem_fb_simple_display_pipe_prepare_fb, }; diff --git a/drivers/gpu/drm/tinydrm/st7735r.c b/drivers/gpu/drm/tinydrm/st7735r.c index 9bc93d5a0401..3bab9a9569a6 100644 --- a/drivers/gpu/drm/tinydrm/st7735r.c +++ b/drivers/gpu/drm/tinydrm/st7735r.c @@ -106,7 +106,7 @@ static void jd_t18003_t01_pipe_enable(struct drm_simple_display_pipe *pipe, static const struct drm_simple_display_pipe_funcs jd_t18003_t01_pipe_funcs = { .enable = jd_t18003_t01_pipe_enable, .disable = mipi_dbi_pipe_disable, - .update = tinydrm_display_pipe_update, + .update = mipi_dbi_pipe_update, .prepare_fb = drm_gem_fb_simple_display_pipe_prepare_fb, }; diff --git a/include/drm/tinydrm/mipi-dbi.h b/include/drm/tinydrm/mipi-dbi.h index b52f32897f23..f4ec2834bc22 100644 --- a/include/drm/tinydrm/mipi-dbi.h +++ b/include/drm/tinydrm/mipi-dbi.h @@ -68,6 +68,8 @@ int mipi_dbi_init(struct device *dev, struct mipi_dbi *mipi, const struct drm_simple_display_pipe_funcs *pipe_funcs, struct drm_driver *driver, const struct drm_display_mode *mode, unsigned int rotation); +void mipi_dbi_pipe_update(struct drm_simple_display_pipe *pipe, + struct drm_plane_state *old_state); void mipi_dbi_enable_flush(struct mipi_dbi *mipi, struct drm_crtc_state *crtc_state, struct drm_plane_state *plan_state); diff --git a/include/drm/tinydrm/tinydrm-helpers.h b/include/drm/tinydrm/tinydrm-helpers.h index 8edb75df4e31..f0d598789e4d 100644 --- a/include/drm/tinydrm/tinydrm-helpers.h +++ b/include/drm/tinydrm/tinydrm-helpers.h @@ -11,8 +11,7 @@ #define __LINUX_TINYDRM_HELPERS_H struct backlight_device; -struct tinydrm_device; -struct drm_clip_rect; +struct drm_framebuffer; struct drm_rect; struct spi_transfer; struct spi_message; @@ -34,14 +33,6 @@ static inline bool tinydrm_machine_little_endian(void) #endif } -bool tinydrm_merge_clips(struct drm_rect *dst, - struct drm_clip_rect *src, unsigned int num_clips, - unsigned int flags, u32 max_width, u32 max_height); -int tinydrm_fb_dirty(struct drm_framebuffer *fb, - struct drm_file *file_priv, - unsigned int flags, unsigned int color, - struct drm_clip_rect *clips, - unsigned int num_clips); void tinydrm_memcpy(void *dst, void *vaddr, struct drm_framebuffer *fb, struct drm_rect *clip); void tinydrm_swab16(u16 *dst, void *vaddr, struct drm_framebuffer *fb, diff --git a/include/drm/tinydrm/tinydrm.h b/include/drm/tinydrm/tinydrm.h index 448aa5ea4722..5621688edcc0 100644 --- a/include/drm/tinydrm/tinydrm.h +++ b/include/drm/tinydrm/tinydrm.h @@ -10,14 +10,9 @@ #ifndef __LINUX_TINYDRM_H #define __LINUX_TINYDRM_H -#include <linux/mutex.h> #include <drm/drm_simple_kms_helper.h> -struct drm_clip_rect; struct drm_driver; -struct drm_file; -struct drm_framebuffer; -struct drm_framebuffer_funcs; /** * struct tinydrm_device - tinydrm device @@ -32,24 +27,6 @@ struct tinydrm_device { * @pipe: Display pipe structure */ struct drm_simple_display_pipe pipe; - - /** - * @dirty_lock: Serializes framebuffer flushing - */ - struct mutex dirty_lock; - - /** - * @fb_funcs: Framebuffer functions used when creating framebuffers - */ - const struct drm_framebuffer_funcs *fb_funcs; - - /** - * @fb_dirty: Framebuffer dirty callback - */ - int (*fb_dirty)(struct drm_framebuffer *framebuffer, - struct drm_file *file_priv, unsigned flags, - unsigned color, struct drm_clip_rect *clips, - unsigned num_clips); }; static inline struct tinydrm_device * @@ -82,13 +59,10 @@ pipe_to_tinydrm(struct drm_simple_display_pipe *pipe) .clock = 1 /* pass validation */ int devm_tinydrm_init(struct device *parent, struct tinydrm_device *tdev, - const struct drm_framebuffer_funcs *fb_funcs, struct drm_driver *driver); int devm_tinydrm_register(struct tinydrm_device *tdev); void tinydrm_shutdown(struct tinydrm_device *tdev); -void tinydrm_display_pipe_update(struct drm_simple_display_pipe *pipe, - struct drm_plane_state *old_state); int tinydrm_display_pipe_init(struct tinydrm_device *tdev, const struct drm_simple_display_pipe_funcs *funcs, -- 2.20.1 _______________________________________________ dri-devel mailing list dri-devel@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/dri-devel