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: Noralf Trønnes <noralf@tronnes.org> Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch> Reviewed-by: Sam Ravnborg <sam@ravnborg.org> Tested-by: David Lechner <david@lechnology.com> Reviewed-by: David Lechner <david@lechnology.com> Link: https://patchwork.freedesktop.org/patch/msgid/20190115043643.2364-5-noralf@tronnes.org
This commit is contained in:
@@ -20,12 +20,14 @@
|
||||
#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>
|
||||
#include <drm/drm_gem_cma_helper.h>
|
||||
#include <drm/drm_gem_framebuffer_helper.h>
|
||||
#include <drm/drm_rect.h>
|
||||
#include <drm/drm_vblank.h>
|
||||
#include <drm/tinydrm/mipi-dbi.h>
|
||||
#include <drm/tinydrm/tinydrm-helpers.h>
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
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 +93,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 +104,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 +153,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,
|
||||
@@ -172,7 +183,14 @@ static void ili9225_pipe_enable(struct drm_simple_display_pipe *pipe,
|
||||
{
|
||||
struct tinydrm_device *tdev = pipe_to_tinydrm(pipe);
|
||||
struct mipi_dbi *mipi = mipi_dbi_from_tinydrm(tdev);
|
||||
struct drm_framebuffer *fb = plane_state->fb;
|
||||
struct device *dev = tdev->drm->dev;
|
||||
struct drm_rect rect = {
|
||||
.x1 = 0,
|
||||
.x2 = fb->width,
|
||||
.y1 = 0,
|
||||
.y2 = fb->height,
|
||||
};
|
||||
int ret;
|
||||
u8 am_id;
|
||||
|
||||
@@ -260,7 +278,8 @@ static void ili9225_pipe_enable(struct drm_simple_display_pipe *pipe,
|
||||
|
||||
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)
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
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 +394,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;
|
||||
|
||||
|
Reference in New Issue
Block a user