Commit af741381 authored by Noralf Trønnes's avatar Noralf Trønnes

drm/tinydrm: Use damage helper for dirtyfb

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.

v3: Include vblank header (Sam)
    ili9225 and st7586 can't use mipi_dbi_enable_flush() (David)

v2: Remove fb check in mipi_dbi_enable_flush() it can't be NULL
    (kbuild test robot)

Cc: David Lechner <david@lechnology.com>
Cc: Eric Anholt <eric@anholt.net>
Signed-off-by: default avatarNoralf Trønnes <noralf@tronnes.org>
Acked-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
Reviewed-by: default avatarSam Ravnborg <sam@ravnborg.org>
Tested-by: default avatarDavid Lechner <david@lechnology.com>
Reviewed-by: default avatarDavid Lechner <david@lechnology.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20190115043643.2364-5-noralf@tronnes.org
parent b051b345
...@@ -39,31 +39,17 @@ ...@@ -39,31 +39,17 @@
* and registers the DRM device using devm_tinydrm_register(). * 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 = { 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_check = drm_atomic_helper_check,
.atomic_commit = drm_atomic_helper_commit, .atomic_commit = drm_atomic_helper_commit,
}; };
static int tinydrm_init(struct device *parent, struct tinydrm_device *tdev, static int tinydrm_init(struct device *parent, struct tinydrm_device *tdev,
const struct drm_framebuffer_funcs *fb_funcs,
struct drm_driver *driver) struct drm_driver *driver)
{ {
struct drm_device *drm; 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 * We don't embed drm_device, because that prevent us from using
* devm_kzalloc() to allocate tinydrm_device in the driver since * 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, ...@@ -86,7 +72,6 @@ static int tinydrm_init(struct device *parent, struct tinydrm_device *tdev,
static void tinydrm_fini(struct tinydrm_device *tdev) static void tinydrm_fini(struct tinydrm_device *tdev)
{ {
drm_mode_config_cleanup(tdev->drm); drm_mode_config_cleanup(tdev->drm);
mutex_destroy(&tdev->dirty_lock);
tdev->drm->dev_private = NULL; tdev->drm->dev_private = NULL;
drm_dev_put(tdev->drm); drm_dev_put(tdev->drm);
} }
...@@ -100,7 +85,6 @@ static void devm_tinydrm_release(void *data) ...@@ -100,7 +85,6 @@ static void devm_tinydrm_release(void *data)
* devm_tinydrm_init - Initialize tinydrm device * devm_tinydrm_init - Initialize tinydrm device
* @parent: Parent device object * @parent: Parent device object
* @tdev: tinydrm device * @tdev: tinydrm device
* @fb_funcs: Framebuffer functions
* @driver: DRM driver * @driver: DRM driver
* *
* This function initializes @tdev, the underlying DRM device and it's * This function initializes @tdev, the underlying DRM device and it's
...@@ -111,12 +95,11 @@ static void devm_tinydrm_release(void *data) ...@@ -111,12 +95,11 @@ static void devm_tinydrm_release(void *data)
* Zero on success, negative error code on failure. * Zero on success, negative error code on failure.
*/ */
int devm_tinydrm_init(struct device *parent, struct tinydrm_device *tdev, int devm_tinydrm_init(struct device *parent, struct tinydrm_device *tdev,
const struct drm_framebuffer_funcs *fb_funcs,
struct drm_driver *driver) struct drm_driver *driver)
{ {
int ret; int ret;
ret = tinydrm_init(parent, tdev, fb_funcs, driver); ret = tinydrm_init(parent, tdev, driver);
if (ret) if (ret)
return ret; return ret;
......
...@@ -17,104 +17,15 @@ ...@@ -17,104 +17,15 @@
#include <drm/drm_device.h> #include <drm/drm_device.h>
#include <drm/drm_drv.h> #include <drm/drm_drv.h>
#include <drm/drm_fourcc.h> #include <drm/drm_fourcc.h>
#include <drm/drm_framebuffer.h>
#include <drm/drm_print.h> #include <drm/drm_print.h>
#include <drm/drm_rect.h> #include <drm/drm_rect.h>
#include <drm/tinydrm/tinydrm.h>
#include <drm/tinydrm/tinydrm-helpers.h> #include <drm/tinydrm/tinydrm-helpers.h>
#include <uapi/drm/drm.h>
static unsigned int spi_max; static unsigned int spi_max;
module_param(spi_max, uint, 0400); module_param(spi_max, uint, 0400);
MODULE_PARM_DESC(spi_max, "Set a lower SPI max transfer size"); 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 * tinydrm_memcpy - Copy clip buffer
* @dst: Destination buffer * @dst: Destination buffer
......
...@@ -13,7 +13,6 @@ ...@@ -13,7 +13,6 @@
#include <drm/drm_gem_framebuffer_helper.h> #include <drm/drm_gem_framebuffer_helper.h>
#include <drm/drm_modes.h> #include <drm/drm_modes.h>
#include <drm/drm_print.h> #include <drm/drm_print.h>
#include <drm/drm_vblank.h>
#include <drm/tinydrm/tinydrm.h> #include <drm/tinydrm/tinydrm.h>
struct tinydrm_connector { struct tinydrm_connector {
...@@ -111,36 +110,6 @@ tinydrm_connector_create(struct drm_device *drm, ...@@ -111,36 +110,6 @@ tinydrm_connector_create(struct drm_device *drm,
return connector; 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, static int tinydrm_rotate_mode(struct drm_display_mode *mode,
unsigned int rotation) unsigned int rotation)
{ {
......
...@@ -176,7 +176,7 @@ static void yx240qv29_enable(struct drm_simple_display_pipe *pipe, ...@@ -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 = { static const struct drm_simple_display_pipe_funcs hx8357d_pipe_funcs = {
.enable = yx240qv29_enable, .enable = yx240qv29_enable,
.disable = mipi_dbi_pipe_disable, .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, .prepare_fb = drm_gem_fb_simple_display_pipe_prepare_fb,
}; };
......
...@@ -20,12 +20,14 @@ ...@@ -20,12 +20,14 @@
#include <linux/spi/spi.h> #include <linux/spi/spi.h>
#include <video/mipi_display.h> #include <video/mipi_display.h>
#include <drm/drm_damage_helper.h>
#include <drm/drm_drv.h> #include <drm/drm_drv.h>
#include <drm/drm_fb_cma_helper.h> #include <drm/drm_fb_cma_helper.h>
#include <drm/drm_fourcc.h> #include <drm/drm_fourcc.h>
#include <drm/drm_gem_cma_helper.h> #include <drm/drm_gem_cma_helper.h>
#include <drm/drm_gem_framebuffer_helper.h> #include <drm/drm_gem_framebuffer_helper.h>
#include <drm/drm_rect.h> #include <drm/drm_rect.h>
#include <drm/drm_vblank.h>
#include <drm/tinydrm/mipi-dbi.h> #include <drm/tinydrm/mipi-dbi.h>
#include <drm/tinydrm/tinydrm-helpers.h> #include <drm/tinydrm/tinydrm-helpers.h>
...@@ -76,17 +78,14 @@ static inline int ili9225_command(struct mipi_dbi *mipi, u8 cmd, u16 data) ...@@ -76,17 +78,14 @@ static inline int ili9225_command(struct mipi_dbi *mipi, u8 cmd, u16 data)
return mipi_dbi_command_buf(mipi, cmd, par, 2); return mipi_dbi_command_buf(mipi, cmd, par, 2);
} }
static int ili9225_fb_dirty(struct drm_framebuffer *fb, static void ili9225_fb_dirty(struct drm_framebuffer *fb, struct drm_rect *rect)
struct drm_file *file_priv, unsigned int flags,
unsigned int color, struct drm_clip_rect *clips,
unsigned int num_clips)
{ {
struct drm_gem_cma_object *cma_obj = drm_fb_cma_get_gem_obj(fb, 0); struct drm_gem_cma_object *cma_obj = drm_fb_cma_get_gem_obj(fb, 0);
struct tinydrm_device *tdev = fb->dev->dev_private; struct tinydrm_device *tdev = fb->dev->dev_private;
struct mipi_dbi *mipi = mipi_dbi_from_tinydrm(tdev); 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; bool swap = mipi->swap_bytes;
struct drm_rect clip;
struct drm_rect *rect = &clip;
u16 x_start, y_start; u16 x_start, y_start;
u16 x1, x2, y1, y2; u16 x1, x2, y1, y2;
int ret = 0; int ret = 0;
...@@ -94,10 +93,9 @@ static int ili9225_fb_dirty(struct drm_framebuffer *fb, ...@@ -94,10 +93,9 @@ static int ili9225_fb_dirty(struct drm_framebuffer *fb,
void *tr; void *tr;
if (!mipi->enabled) if (!mipi->enabled)
return 0; return;
full = tinydrm_merge_clips(&clip, clips, num_clips, flags, full = width == fb->width && height == fb->height;
fb->width, fb->height);
DRM_DEBUG_KMS("Flushing [FB:%d] " DRM_RECT_FMT "\n", fb->base.id, DRM_RECT_ARG(rect)); DRM_DEBUG_KMS("Flushing [FB:%d] " DRM_RECT_FMT "\n", fb->base.id, DRM_RECT_ARG(rect));
...@@ -106,7 +104,7 @@ static int ili9225_fb_dirty(struct drm_framebuffer *fb, ...@@ -106,7 +104,7 @@ static int ili9225_fb_dirty(struct drm_framebuffer *fb,
tr = mipi->tx_buf; tr = mipi->tx_buf;
ret = mipi_dbi_buf_copy(mipi->tx_buf, fb, rect, swap); ret = mipi_dbi_buf_copy(mipi->tx_buf, fb, rect, swap);
if (ret) if (ret)
return ret; goto err_msg;
} else { } else {
tr = cma_obj->vaddr; tr = cma_obj->vaddr;
} }
...@@ -155,16 +153,29 @@ static int ili9225_fb_dirty(struct drm_framebuffer *fb, ...@@ -155,16 +153,29 @@ static int ili9225_fb_dirty(struct drm_framebuffer *fb,
ili9225_command(mipi, ILI9225_RAM_ADDRESS_SET_2, y_start); ili9225_command(mipi, ILI9225_RAM_ADDRESS_SET_2, y_start);
ret = mipi_dbi_command_buf(mipi, ILI9225_WRITE_DATA_TO_GRAM, tr, ret = mipi_dbi_command_buf(mipi, ILI9225_WRITE_DATA_TO_GRAM, tr,
(rect->x2 - rect->x1) * (rect->y2 - rect->y1) * 2); width * height * 2);
err_msg:
return ret; if (ret)
dev_err_once(fb->dev->dev, "Failed to update display %d\n", ret);
} }
static const struct drm_framebuffer_funcs ili9225_fb_funcs = { static void ili9225_pipe_update(struct drm_simple_display_pipe *pipe,
.destroy = drm_gem_fb_destroy, struct drm_plane_state *old_state)
.create_handle = drm_gem_fb_create_handle, {
.dirty = tinydrm_fb_dirty, 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, static void ili9225_pipe_enable(struct drm_simple_display_pipe *pipe,
struct drm_crtc_state *crtc_state, struct drm_crtc_state *crtc_state,
...@@ -172,7 +183,14 @@ static void ili9225_pipe_enable(struct drm_simple_display_pipe *pipe, ...@@ -172,7 +183,14 @@ static void ili9225_pipe_enable(struct drm_simple_display_pipe *pipe,
{ {
struct tinydrm_device *tdev = pipe_to_tinydrm(pipe); struct tinydrm_device *tdev = pipe_to_tinydrm(pipe);
struct mipi_dbi *mipi = mipi_dbi_from_tinydrm(tdev); struct mipi_dbi *mipi = mipi_dbi_from_tinydrm(tdev);
struct drm_framebuffer *fb = plane_state->fb;
struct device *dev = tdev->drm->dev; struct device *dev = tdev->drm->dev;
struct drm_rect rect = {
.x1 = 0,
.x2 = fb->width,
.y1 = 0,
.y2 = fb->height,
};
int ret; int ret;
u8 am_id; u8 am_id;
...@@ -260,7 +278,8 @@ static void ili9225_pipe_enable(struct drm_simple_display_pipe *pipe, ...@@ -260,7 +278,8 @@ static void ili9225_pipe_enable(struct drm_simple_display_pipe *pipe,
ili9225_command(mipi, ILI9225_DISPLAY_CONTROL_1, 0x1017); ili9225_command(mipi, ILI9225_DISPLAY_CONTROL_1, 0x1017);
mipi_dbi_enable_flush(mipi, crtc_state, plane_state); mipi->enabled = true;
ili9225_fb_dirty(fb, &rect);
} }
static void ili9225_pipe_disable(struct drm_simple_display_pipe *pipe) static void ili9225_pipe_disable(struct drm_simple_display_pipe *pipe)
...@@ -305,59 +324,10 @@ static int ili9225_dbi_command(struct mipi_dbi *mipi, u8 cmd, u8 *par, ...@@ -305,59 +324,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); 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 = { static const struct drm_simple_display_pipe_funcs ili9225_pipe_funcs = {
.enable = ili9225_pipe_enable, .enable = ili9225_pipe_enable,
.disable = ili9225_pipe_disable, .disable = ili9225_pipe_disable,
.update = tinydrm_display_pipe_update, .update = ili9225_pipe_update,
.prepare_fb = drm_gem_fb_simple_display_pipe_prepare_fb, .prepare_fb = drm_gem_fb_simple_display_pipe_prepare_fb,
}; };
...@@ -424,8 +394,8 @@ static int ili9225_probe(struct spi_device *spi) ...@@ -424,8 +394,8 @@ static int ili9225_probe(struct spi_device *spi)
/* override the command function set in mipi_dbi_spi_init() */ /* override the command function set in mipi_dbi_spi_init() */
mipi->command = ili9225_dbi_command; mipi->command = ili9225_dbi_command;
ret = ili9225_init(&spi->dev, mipi, &ili9225_pipe_funcs, ret = mipi_dbi_init(&spi->dev, mipi, &ili9225_pipe_funcs,
&ili9225_driver, &ili9225_mode, rotation); &ili9225_driver, &ili9225_mode, rotation);
if (ret) if (ret)
return ret; return ret;
......
...@@ -132,7 +132,7 @@ static void yx240qv29_enable(struct drm_simple_display_pipe *pipe, ...@@ -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 = { static const struct drm_simple_display_pipe_funcs ili9341_pipe_funcs = {
.enable = yx240qv29_enable, .enable = yx240qv29_enable,
.disable = mipi_dbi_pipe_disable, .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, .prepare_fb = drm_gem_fb_simple_display_pipe_prepare_fb,
}; };
......
...@@ -140,7 +140,7 @@ static void mi0283qt_enable(struct drm_simple_display_pipe *pipe, ...@@ -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 = { static const struct drm_simple_display_pipe_funcs mi0283qt_pipe_funcs = {
.enable = mi0283qt_enable, .enable = mi0283qt_enable,
.disable = mipi_dbi_pipe_disable, .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, .prepare_fb = drm_gem_fb_simple_display_pipe_prepare_fb,
}; };
......
...@@ -17,15 +17,16 @@ ...@@ -17,15 +17,16 @@
#include <linux/regulator/consumer.h> #include <linux/regulator/consumer.h>
#include <linux/spi/spi.h> #include <linux/spi/spi.h>
#include <drm/drm_damage_helper.h>
#include <drm/drm_drv.h> #include <drm/drm_drv.h>
#include <drm/drm_fb_cma_helper.h> #include <drm/drm_fb_cma_helper.h>
#include <drm/drm_gem_cma_helper.h> #include <drm/drm_gem_cma_helper.h>
#include <drm/drm_fourcc.h> #include <drm/drm_fourcc.h>
#include <drm/drm_gem_framebuffer_helper.h> #include <drm/drm_gem_framebuffer_helper.h>
#include <drm/drm_vblank.h>
#include <drm/drm_rect.h> #include <drm/drm_rect.h>
#include <drm/tinydrm/mipi-dbi.h> #include <drm/tinydrm/mipi-dbi.h>
#include <drm/tinydrm/tinydrm-helpers.h> #include <drm/tinydrm/tinydrm-helpers.h>
#include <uapi/drm/drm.h>
#include <video/mipi_display.h> #include <video/mipi_display.h>
#define MIPI_DBI_MAX_SPI_READ_SPEED 2000000 /* 2MHz */ #define MIPI_DBI_MAX_SPI_READ_SPEED 2000000 /* 2MHz */
...@@ -212,27 +213,22 @@ int mipi_dbi_buf_copy(void *dst, struct drm_framebuffer *fb, ...@@ -212,27 +213,22 @@ int mipi_dbi_buf_copy(void *dst, struct drm_framebuffer *fb,
} }
EXPORT_SYMBOL(mipi_dbi_buf_copy); EXPORT_SYMBOL(mipi_dbi_buf_copy);
static int mipi_dbi_fb_dirty(struct drm_framebuffer *fb, static void mipi_dbi_fb_dirty(struct drm_framebuffer *fb, struct drm_rect *rect)
struct drm_file *file_priv,
unsigned int flags, unsigned int color,
struct drm_clip_rect *clips,
unsigned int num_clips)
{ {
struct drm_gem_cma_object *cma_obj = drm_fb_cma_get_gem_obj(fb, 0); struct drm_gem_cma_object *cma_obj = drm_fb_cma_get_gem_obj(fb, 0);
struct tinydrm_device *tdev = fb->dev->dev_private; struct tinydrm_device *tdev = fb->dev->dev_private;
struct mipi_dbi *mipi = mipi_dbi_from_tinydrm(tdev); 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; bool swap = mipi->swap_bytes;
struct drm_rect clip;
struct drm_rect *rect = &clip;
int ret = 0; int ret = 0;
bool full; bool full;
void *tr; void *tr;
if (!mipi->enabled) if (!mipi->enabled)
return 0; return;
full = tinydrm_merge_clips(&clip, clips, num_clips, flags, full = width == fb->width && height == fb->height;
fb->width, fb->height);
DRM_DEBUG_KMS("Flushing [FB:%d] " DRM_RECT_FMT "\n", fb->base.id, DRM_RECT_ARG(rect)); DRM_DEBUG_KMS("Flushing [FB:%d] " DRM_RECT_FMT "\n", fb->base.id, DRM_RECT_ARG(rect));
...@@ -241,7 +237,7 @@ static int mipi_dbi_fb_dirty(struct drm_framebuffer *fb, ...@@ -241,7 +237,7 @@ static int mipi_dbi_fb_dirty(struct drm_framebuffer *fb,
tr = mipi->tx_buf; tr = mipi->tx_buf;
ret = mipi_dbi_buf_copy(mipi->tx_buf, fb, rect, swap); ret = mipi_dbi_buf_copy(mipi->tx_buf, fb, rect, swap);
if (ret) if (ret)
return ret; goto err_msg;
} else { } else {
tr = cma_obj->vaddr; tr = cma_obj->vaddr;
} }
...@@ -254,16 +250,38 @@ static int mipi_dbi_fb_dirty(struct drm_framebuffer *fb, ...@@ -254,16 +250,38 @@ static int mipi_dbi_fb_dirty(struct drm_framebuffer *fb,
((rect->y2 - 1) >> 8) & 0xff, (rect->y2 - 1) & 0xff); ((rect->y2 - 1) >> 8) & 0xff, (rect->y2 - 1) & 0xff);
ret = mipi_dbi_command_buf(mipi, MIPI_DCS_WRITE_MEMORY_START, tr, ret = mipi_dbi_command_buf(mipi, MIPI_DCS_WRITE_MEMORY_START, tr,
(rect->x2 - rect->x1) * (rect->y2 - rect->y1) * 2); width * height * 2);
err_msg:
return ret; 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, * mipi_dbi_pipe_update - Display pipe update helper
.create_handle = drm_gem_fb_create_handle, * @pipe: Simple display pipe
.dirty = tinydrm_fb_dirty, * @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 * mipi_dbi_enable_flush - MIPI DBI enable helper
...@@ -274,18 +292,25 @@ static const struct drm_framebuffer_funcs mipi_dbi_fb_funcs = { ...@@ -274,18 +292,25 @@ static const struct drm_framebuffer_funcs mipi_dbi_fb_funcs = {
* This function sets &mipi_dbi->enabled, flushes the whole framebuffer and * This function sets &mipi_dbi->enabled, flushes the whole framebuffer and
* enables the backlight. Drivers can use this in their * enables the backlight. Drivers can use this in their
* &drm_simple_display_pipe_funcs->enable callback. * &drm_simple_display_pipe_funcs->enable callback.
*
* Note: Drivers which don't use mipi_dbi_pipe_update() because they have custom
* framebuffer flushing, can't use this function since they both use the same
* flushing code.
*/ */
void mipi_dbi_enable_flush(struct mipi_dbi *mipi, void mipi_dbi_enable_flush(struct mipi_dbi *mipi,
struct drm_crtc_state *crtc_state, struct drm_crtc_state *crtc_state,
struct drm_plane_state *plane_state) struct drm_plane_state *plane_state)
{ {
struct tinydrm_device *tdev = &mipi->tinydrm;
struct drm_framebuffer *fb = plane_state->fb; struct drm_framebuffer *fb = plane_state->fb;
struct drm_rect rect = {
.x1 = 0,
.x2 = fb->width,
.y1 = 0,
.y2 = fb->height,
};
mipi->enabled = true; mipi->enabled = true;
if (fb) mipi_dbi_fb_dirty(fb, &rect);
tdev->fb_dirty(fb, NULL, 0, 0, NULL, 0);
backlight_enable(mipi->backlight); backlight_enable(mipi->backlight);
} }
EXPORT_SYMBOL(mipi_dbi_enable_flush); EXPORT_SYMBOL(mipi_dbi_enable_flush);
...@@ -377,12 +402,10 @@ int mipi_dbi_init(struct device *dev, struct mipi_dbi *mipi, ...@@ -377,12 +402,10 @@ int mipi_dbi_init(struct device *dev, struct mipi_dbi *mipi,
if (!mipi->tx_buf) if (!mipi->tx_buf)
return -ENOMEM; return -ENOMEM;
ret = devm_tinydrm_init(dev, tdev, &mipi_dbi_fb_funcs, driver); ret = devm_tinydrm_init(dev, tdev, driver);
if (ret) if (ret)
return ret; return ret;
tdev->fb_dirty = mipi_dbi_fb_dirty;
/* TODO: Maybe add DRM_MODE_CONNECTOR_SPI */ /* TODO: Maybe add DRM_MODE_CONNECTOR_SPI */
ret = tinydrm_display_pipe_init(tdev, pipe_funcs, ret = tinydrm_display_pipe_init(tdev, pipe_funcs,
DRM_MODE_CONNECTOR_VIRTUAL, DRM_MODE_CONNECTOR_VIRTUAL,
...@@ -392,6 +415,8 @@ int mipi_dbi_init(struct device *dev, struct mipi_dbi *mipi, ...@@ -392,6 +415,8 @@ int mipi_dbi_init(struct device *dev, struct mipi_dbi *mipi,
if (ret) if (ret)
return ret; return ret;
drm_plane_enable_fb_damage_clips(&tdev->pipe.plane);
tdev->drm->mode_config.preferred_depth = 16; tdev->drm->mode_config.preferred_depth = 16;
mipi->rotation = rotation; mipi->rotation = rotation;
......
...@@ -26,11 +26,13 @@ ...@@ -26,11 +26,13 @@
#include <linux/spi/spi.h> #include <linux/spi/spi.h>
#include <linux/thermal.h> #include <linux/thermal.h>
#include <drm/drm_damage_helper.h>
#include <drm/drm_drv.h> #include <drm/drm_drv.h>
#include <drm/drm_fb_cma_helper.h> #include <drm/drm_fb_cma_helper.h>
#include <drm/drm_gem_cma_helper.h> #include <drm/drm_gem_cma_helper.h>
#include <drm/drm_gem_framebuffer_helper.h> #include <drm/drm_gem_framebuffer_helper.h>
#include <drm/drm_rect.h> #include <drm/drm_rect.h>
#include <drm/drm_vblank.h>
#include <drm/tinydrm/tinydrm.h> #include <drm/tinydrm/tinydrm.h>
#include <drm/tinydrm/tinydrm-helpers.h> #include <drm/tinydrm/tinydrm-helpers.h>
...@@ -523,11 +525,7 @@ static void repaper_gray8_to_mono_reversed(u8 *buf, u32 width, u32 height) ...@@ -523,11 +525,7 @@ static void repaper_gray8_to_mono_reversed(u8 *buf, u32 width, u32 height)
} }
} }
static int repaper_fb_dirty(struct drm_framebuffer *fb, 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)
{ {
struct drm_gem_cma_object *cma_obj = drm_fb_cma_get_gem_obj(fb, 0); 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; struct dma_buf_attachment *import_attach = cma_obj->base.import_attach;
...@@ -626,12 +624,6 @@ static int repaper_fb_dirty(struct drm_framebuffer *fb, ...@@ -626,12 +624,6 @@ static int repaper_fb_dirty(struct drm_framebuffer *fb,
return ret; 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) static void power_off(struct repaper_epd *epd)
{ {
/* Turn off power and all signals */ /* Turn off power and all signals */
...@@ -795,9 +787,7 @@ static void repaper_pipe_disable(struct drm_simple_display_pipe *pipe) ...@@ -795,9 +787,7 @@ static void repaper_pipe_disable(struct drm_simple_display_pipe *pipe)
DRM_DEBUG_DRIVER("\n"); DRM_DEBUG_DRIVER("\n");
mutex_lock(&tdev->dirty_lock);
epd->enabled = false; epd->enabled = false;
mutex_unlock(&tdev->dirty_lock);
/* Nothing frame */ /* Nothing frame */
for (line = 0; line < epd->height; line++) for (line = 0; line < epd->height; line++)
...@@ -840,10 +830,28 @@ static void repaper_pipe_disable(struct drm_simple_display_pipe *pipe) ...@@ -840,10 +830,28 @@ static void repaper_pipe_disable(struct drm_simple_display_pipe *pipe)
power_off(epd); 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 = { static const struct drm_simple_display_pipe_funcs repaper_pipe_funcs = {
.enable = repaper_pipe_enable, .enable = repaper_pipe_enable,
.disable = repaper_pipe_disable, .disable = repaper_pipe_disable,
.update = tinydrm_display_pipe_update, .update = repaper_pipe_update,
.prepare_fb = drm_gem_fb_simple_display_pipe_prepare_fb, .prepare_fb = drm_gem_fb_simple_display_pipe_prepare_fb,
}; };
...@@ -1057,12 +1065,10 @@ static int repaper_probe(struct spi_device *spi) ...@@ -1057,12 +1065,10 @@ static int repaper_probe(struct spi_device *spi)
tdev = &epd->tinydrm; tdev = &epd->tinydrm;
ret = devm_tinydrm_init(dev, tdev, &repaper_fb_funcs, &repaper_driver); ret = devm_tinydrm_init(dev, tdev, &repaper_driver);
if (ret) if (ret)
return ret; return ret;
tdev->fb_dirty = repaper_fb_dirty;
ret = tinydrm_display_pipe_init(tdev, &repaper_pipe_funcs, ret = tinydrm_display_pipe_init(tdev, &repaper_pipe_funcs,
DRM_MODE_CONNECTOR_VIRTUAL, DRM_MODE_CONNECTOR_VIRTUAL,
repaper_formats, repaper_formats,
......
...@@ -17,11 +17,13 @@ ...@@ -17,11 +17,13 @@
#include <linux/spi/spi.h> #include <linux/spi/spi.h>
#include <video/mipi_display.h> #include <video/mipi_display.h>
#include <drm/drm_damage_helper.h>
#include <drm/drm_drv.h> #include <drm/drm_drv.h>
#include <drm/drm_fb_cma_helper.h> #include <drm/drm_fb_cma_helper.h>
#include <drm/drm_gem_cma_helper.h> #include <drm/drm_gem_cma_helper.h>
#include <drm/drm_gem_framebuffer_helper.h> #include <drm/drm_gem_framebuffer_helper.h>
#include <drm/drm_rect.h> #include <drm/drm_rect.h>
#include <drm/drm_vblank.h>
#include <drm/tinydrm/mipi-dbi.h> #include <drm/tinydrm/mipi-dbi.h>
#include <drm/tinydrm/tinydrm-helpers.h> #include <drm/tinydrm/tinydrm-helpers.h>
...@@ -112,23 +114,15 @@ static int st7586_buf_copy(void *dst, struct drm_framebuffer *fb, ...@@ -112,23 +114,15 @@ static int st7586_buf_copy(void *dst, struct drm_framebuffer *fb,
return ret; return ret;
} }
static int st7586_fb_dirty(struct drm_framebuffer *fb, static void st7586_fb_dirty(struct drm_framebuffer *fb, struct drm_rect *rect)
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 tinydrm_device *tdev = fb->dev->dev_private;
struct mipi_dbi *mipi = mipi_dbi_from_tinydrm(tdev); struct mipi_dbi *mipi = mipi_dbi_from_tinydrm(tdev);
struct drm_rect clip;
struct drm_rect *rect = &clip;
int start, end; int start, end;
int ret = 0; int ret = 0;
if (!mipi->enabled) if (!mipi->enabled)
return 0; return;
tinydrm_merge_clips(&clip, clips, num_clips, flags, fb->width,
fb->height);
/* 3 pixels per byte, so grow clip to nearest multiple of 3 */ /* 3 pixels per byte, so grow clip to nearest multiple of 3 */
rect->x1 = rounddown(rect->x1, 3); rect->x1 = rounddown(rect->x1, 3);
...@@ -138,7 +132,7 @@ static int st7586_fb_dirty(struct drm_framebuffer *fb, ...@@ -138,7 +132,7 @@ static int st7586_fb_dirty(struct drm_framebuffer *fb,
ret = st7586_buf_copy(mipi->tx_buf, fb, rect); ret = st7586_buf_copy(mipi->tx_buf, fb, rect);
if (ret) if (ret)
return ret; goto err_msg;
/* Pixels are packed 3 per byte */ /* Pixels are packed 3 per byte */
start = rect->x1 / 3; start = rect->x1 / 3;
...@@ -154,15 +148,28 @@ static int st7586_fb_dirty(struct drm_framebuffer *fb, ...@@ -154,15 +148,28 @@ static int st7586_fb_dirty(struct drm_framebuffer *fb,
ret = mipi_dbi_command_buf(mipi, MIPI_DCS_WRITE_MEMORY_START, ret = mipi_dbi_command_buf(mipi, MIPI_DCS_WRITE_MEMORY_START,
(u8 *)mipi->tx_buf, (u8 *)mipi->tx_buf,
(end - start) * (rect->y2 - rect->y1)); (end - start) * (rect->y2 - rect->y1));
err_msg:
return ret; if (ret)
dev_err_once(fb->dev->dev, "Failed to update display %d\n", ret);
} }
static const struct drm_framebuffer_funcs st7586_fb_funcs = { static void st7586_pipe_update(struct drm_simple_display_pipe *pipe,
.destroy = drm_gem_fb_destroy, struct drm_plane_state *old_state)
.create_handle = drm_gem_fb_create_handle, {
.dirty = tinydrm_fb_dirty, 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, static void st7586_pipe_enable(struct drm_simple_display_pipe *pipe,
struct drm_crtc_state *crtc_state, struct drm_crtc_state *crtc_state,
...@@ -170,6 +177,13 @@ static void st7586_pipe_enable(struct drm_simple_display_pipe *pipe, ...@@ -170,6 +177,13 @@ static void st7586_pipe_enable(struct drm_simple_display_pipe *pipe,
{ {
struct tinydrm_device *tdev = pipe_to_tinydrm(pipe); struct tinydrm_device *tdev = pipe_to_tinydrm(pipe);
struct mipi_dbi *mipi = mipi_dbi_from_tinydrm(tdev); struct mipi_dbi *mipi = mipi_dbi_from_tinydrm(tdev);
struct drm_framebuffer *fb = plane_state->fb;
struct drm_rect rect = {
.x1 = 0,
.x2 = fb->width,
.y1 = 0,
.y2 = fb->height,
};
int ret; int ret;
u8 addr_mode; u8 addr_mode;
...@@ -226,9 +240,10 @@ static void st7586_pipe_enable(struct drm_simple_display_pipe *pipe, ...@@ -226,9 +240,10 @@ static void st7586_pipe_enable(struct drm_simple_display_pipe *pipe,
msleep(100); msleep(100);
mipi_dbi_command(mipi, MIPI_DCS_SET_DISPLAY_ON); mipi->enabled = true;
st7586_fb_dirty(fb, &rect);
mipi_dbi_enable_flush(mipi, crtc_state, plane_state); mipi_dbi_command(mipi, MIPI_DCS_SET_DISPLAY_ON);
} }
static void st7586_pipe_disable(struct drm_simple_display_pipe *pipe) static void st7586_pipe_disable(struct drm_simple_display_pipe *pipe)
...@@ -264,12 +279,10 @@ static int st7586_init(struct device *dev, struct mipi_dbi *mipi, ...@@ -264,12 +279,10 @@ static int st7586_init(struct device *dev, struct mipi_dbi *mipi,
if (!mipi->tx_buf) if (!mipi->tx_buf)
return -ENOMEM; return -ENOMEM;
ret = devm_tinydrm_init(dev, tdev, &st7586_fb_funcs, driver); ret = devm_tinydrm_init(dev, tdev, driver);
if (ret) if (ret)
return ret; return ret;
tdev->fb_dirty = st7586_fb_dirty;
ret = tinydrm_display_pipe_init(tdev, pipe_funcs, ret = tinydrm_display_pipe_init(tdev, pipe_funcs,
DRM_MODE_CONNECTOR_VIRTUAL, DRM_MODE_CONNECTOR_VIRTUAL,
st7586_formats, st7586_formats,
...@@ -278,6 +291,8 @@ static int st7586_init(struct device *dev, struct mipi_dbi *mipi, ...@@ -278,6 +291,8 @@ static int st7586_init(struct device *dev, struct mipi_dbi *mipi,
if (ret) if (ret)
return ret; return ret;
drm_plane_enable_fb_damage_clips(&tdev->pipe.plane);
tdev->drm->mode_config.preferred_depth = 32; tdev->drm->mode_config.preferred_depth = 32;
mipi->rotation = rotation; mipi->rotation = rotation;
...@@ -292,7 +307,7 @@ static int st7586_init(struct device *dev, struct mipi_dbi *mipi, ...@@ -292,7 +307,7 @@ static int st7586_init(struct device *dev, struct mipi_dbi *mipi,
static const struct drm_simple_display_pipe_funcs st7586_pipe_funcs = { static const struct drm_simple_display_pipe_funcs st7586_pipe_funcs = {
.enable = st7586_pipe_enable, .enable = st7586_pipe_enable,
.disable = st7586_pipe_disable, .disable = st7586_pipe_disable,
.update = tinydrm_display_pipe_update, .update = st7586_pipe_update,
.prepare_fb = drm_gem_fb_simple_display_pipe_prepare_fb, .prepare_fb = drm_gem_fb_simple_display_pipe_prepare_fb,
}; };
......
...@@ -106,7 +106,7 @@ static void jd_t18003_t01_pipe_enable(struct drm_simple_display_pipe *pipe, ...@@ -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 = { static const struct drm_simple_display_pipe_funcs jd_t18003_t01_pipe_funcs = {
.enable = jd_t18003_t01_pipe_enable, .enable = jd_t18003_t01_pipe_enable,
.disable = mipi_dbi_pipe_disable, .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, .prepare_fb = drm_gem_fb_simple_display_pipe_prepare_fb,
}; };
......
...@@ -68,6 +68,8 @@ int mipi_dbi_init(struct device *dev, struct mipi_dbi *mipi, ...@@ -68,6 +68,8 @@ int mipi_dbi_init(struct device *dev, struct mipi_dbi *mipi,
const struct drm_simple_display_pipe_funcs *pipe_funcs, const struct drm_simple_display_pipe_funcs *pipe_funcs,
struct drm_driver *driver, struct drm_driver *driver,
const struct drm_display_mode *mode, unsigned int rotation); 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, void mipi_dbi_enable_flush(struct mipi_dbi *mipi,
struct drm_crtc_state *crtc_state, struct drm_crtc_state *crtc_state,
struct drm_plane_state *plan_state); struct drm_plane_state *plan_state);
......
...@@ -11,8 +11,7 @@ ...@@ -11,8 +11,7 @@
#define __LINUX_TINYDRM_HELPERS_H #define __LINUX_TINYDRM_HELPERS_H
struct backlight_device; struct backlight_device;
struct tinydrm_device; struct drm_framebuffer;
struct drm_clip_rect;
struct drm_rect; struct drm_rect;
struct spi_transfer; struct spi_transfer;
struct spi_message; struct spi_message;
...@@ -34,14 +33,6 @@ static inline bool tinydrm_machine_little_endian(void) ...@@ -34,14 +33,6 @@ static inline bool tinydrm_machine_little_endian(void)
#endif #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, void tinydrm_memcpy(void *dst, void *vaddr, struct drm_framebuffer *fb,
struct drm_rect *clip); struct drm_rect *clip);
void tinydrm_swab16(u16 *dst, void *vaddr, struct drm_framebuffer *fb, void tinydrm_swab16(u16 *dst, void *vaddr, struct drm_framebuffer *fb,
......
...@@ -10,14 +10,9 @@ ...@@ -10,14 +10,9 @@
#ifndef __LINUX_TINYDRM_H #ifndef __LINUX_TINYDRM_H
#define __LINUX_TINYDRM_H #define __LINUX_TINYDRM_H
#include <linux/mutex.h>
#include <drm/drm_simple_kms_helper.h> #include <drm/drm_simple_kms_helper.h>
struct drm_clip_rect;
struct drm_driver; struct drm_driver;
struct drm_file;
struct drm_framebuffer;
struct drm_framebuffer_funcs;
/** /**
* struct tinydrm_device - tinydrm device * struct tinydrm_device - tinydrm device
...@@ -32,24 +27,6 @@ struct tinydrm_device { ...@@ -32,24 +27,6 @@ struct tinydrm_device {
* @pipe: Display pipe structure * @pipe: Display pipe structure
*/ */
struct drm_simple_display_pipe pipe; 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 * static inline struct tinydrm_device *
...@@ -82,13 +59,10 @@ pipe_to_tinydrm(struct drm_simple_display_pipe *pipe) ...@@ -82,13 +59,10 @@ pipe_to_tinydrm(struct drm_simple_display_pipe *pipe)
.clock = 1 /* pass validation */ .clock = 1 /* pass validation */
int devm_tinydrm_init(struct device *parent, struct tinydrm_device *tdev, int devm_tinydrm_init(struct device *parent, struct tinydrm_device *tdev,
const struct drm_framebuffer_funcs *fb_funcs,
struct drm_driver *driver); struct drm_driver *driver);
int devm_tinydrm_register(struct tinydrm_device *tdev); int devm_tinydrm_register(struct tinydrm_device *tdev);
void tinydrm_shutdown(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 int
tinydrm_display_pipe_init(struct tinydrm_device *tdev, tinydrm_display_pipe_init(struct tinydrm_device *tdev,
const struct drm_simple_display_pipe_funcs *funcs, const struct drm_simple_display_pipe_funcs *funcs,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment