diff options
Diffstat (limited to 'drivers/gpu/drm/sysfb/drm_sysfb_modeset.c')
-rw-r--r-- | drivers/gpu/drm/sysfb/drm_sysfb_modeset.c | 153 |
1 files changed, 149 insertions, 4 deletions
diff --git a/drivers/gpu/drm/sysfb/drm_sysfb_modeset.c b/drivers/gpu/drm/sysfb/drm_sysfb_modeset.c index ddb4a7523ee6..8517c490e815 100644 --- a/drivers/gpu/drm/sysfb/drm_sysfb_modeset.c +++ b/drivers/gpu/drm/sysfb/drm_sysfb_modeset.c @@ -11,7 +11,6 @@ #include <drm/drm_edid.h> #include <drm/drm_fourcc.h> #include <drm/drm_framebuffer.h> -#include <drm/drm_gem_atomic_helper.h> #include <drm/drm_gem_framebuffer_helper.h> #include <drm/drm_panic.h> #include <drm/drm_print.h> @@ -185,6 +184,104 @@ size_t drm_sysfb_build_fourcc_list(struct drm_device *dev, } EXPORT_SYMBOL(drm_sysfb_build_fourcc_list); +static void drm_sysfb_plane_state_destroy(struct drm_sysfb_plane_state *sysfb_plane_state) +{ + __drm_gem_destroy_shadow_plane_state(&sysfb_plane_state->base); + + kfree(sysfb_plane_state); +} + +static void drm_sysfb_memcpy(struct iosys_map *dst, const unsigned int *dst_pitch, + const struct iosys_map *src, const struct drm_framebuffer *fb, + const struct drm_rect *clip, struct drm_format_conv_state *state) +{ + drm_fb_memcpy(dst, dst_pitch, src, fb, clip); +} + +static drm_sysfb_blit_func drm_sysfb_get_blit_func(u32 dst_format, u32 src_format) +{ + if (src_format == dst_format) { + return drm_sysfb_memcpy; + } else if (src_format == DRM_FORMAT_XRGB8888) { + switch (dst_format) { + case DRM_FORMAT_RGB565: + return drm_fb_xrgb8888_to_rgb565; + case DRM_FORMAT_RGB565 | DRM_FORMAT_BIG_ENDIAN: + return drm_fb_xrgb8888_to_rgb565be; + case DRM_FORMAT_XRGB1555: + return drm_fb_xrgb8888_to_xrgb1555; + case DRM_FORMAT_ARGB1555: + return drm_fb_xrgb8888_to_argb1555; + case DRM_FORMAT_RGBA5551: + return drm_fb_xrgb8888_to_rgba5551; + case DRM_FORMAT_RGB888: + return drm_fb_xrgb8888_to_rgb888; + case DRM_FORMAT_BGR888: + return drm_fb_xrgb8888_to_bgr888; + case DRM_FORMAT_ARGB8888: + return drm_fb_xrgb8888_to_argb8888; + case DRM_FORMAT_XBGR8888: + return drm_fb_xrgb8888_to_xbgr8888; + case DRM_FORMAT_ABGR8888: + return drm_fb_xrgb8888_to_abgr8888; + case DRM_FORMAT_XRGB2101010: + return drm_fb_xrgb8888_to_xrgb2101010; + case DRM_FORMAT_ARGB2101010: + return drm_fb_xrgb8888_to_argb2101010; + case DRM_FORMAT_BGRX8888: + return drm_fb_xrgb8888_to_bgrx8888; + case DRM_FORMAT_RGB332: + return drm_fb_xrgb8888_to_rgb332; + } + } + + return NULL; +} + +int drm_sysfb_plane_helper_begin_fb_access(struct drm_plane *plane, + struct drm_plane_state *plane_state) +{ + struct drm_device *dev = plane->dev; + struct drm_sysfb_plane_state *sysfb_plane_state = to_drm_sysfb_plane_state(plane_state); + struct drm_framebuffer *fb = plane_state->fb; + struct drm_crtc_state *crtc_state; + struct drm_sysfb_crtc_state *sysfb_crtc_state; + drm_sysfb_blit_func blit_to_crtc; + int ret; + + ret = drm_gem_begin_shadow_fb_access(plane, plane_state); + if (ret) + return ret; + + if (!fb) + return 0; + + ret = -EINVAL; + + crtc_state = drm_atomic_get_crtc_state(plane_state->state, plane_state->crtc); + if (drm_WARN_ON_ONCE(dev, !crtc_state)) + goto err_drm_gem_end_shadow_fb_access; + sysfb_crtc_state = to_drm_sysfb_crtc_state(crtc_state); + + if (drm_WARN_ON_ONCE(dev, !sysfb_crtc_state->format)) + goto err_drm_gem_end_shadow_fb_access; + blit_to_crtc = drm_sysfb_get_blit_func(sysfb_crtc_state->format->format, + fb->format->format); + if (!blit_to_crtc) { + drm_warn_once(dev, "No blit helper from %p4cc to %p4cc found.\n", + &fb->format->format, &sysfb_crtc_state->format->format); + goto err_drm_gem_end_shadow_fb_access; + } + sysfb_plane_state->blit_to_crtc = blit_to_crtc; + + return 0; + +err_drm_gem_end_shadow_fb_access: + drm_gem_end_shadow_fb_access(plane, plane_state); + return ret; +} +EXPORT_SYMBOL(drm_sysfb_plane_helper_begin_fb_access); + int drm_sysfb_plane_helper_atomic_check(struct drm_plane *plane, struct drm_atomic_state *new_state) { @@ -235,12 +332,14 @@ void drm_sysfb_plane_helper_atomic_update(struct drm_plane *plane, struct drm_at struct drm_sysfb_device *sysfb = to_drm_sysfb_device(dev); struct drm_plane_state *plane_state = drm_atomic_get_new_plane_state(state, plane); struct drm_plane_state *old_plane_state = drm_atomic_get_old_plane_state(state, plane); - struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state); + struct drm_sysfb_plane_state *sysfb_plane_state = to_drm_sysfb_plane_state(plane_state); + struct drm_shadow_plane_state *shadow_plane_state = &sysfb_plane_state->base; struct drm_framebuffer *fb = plane_state->fb; unsigned int dst_pitch = sysfb->fb_pitch; struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, plane_state->crtc); struct drm_sysfb_crtc_state *sysfb_crtc_state = to_drm_sysfb_crtc_state(crtc_state); const struct drm_format_info *dst_format = sysfb_crtc_state->format; + drm_sysfb_blit_func blit_to_crtc = sysfb_plane_state->blit_to_crtc; struct drm_atomic_helper_damage_iter iter; struct drm_rect damage; int ret, idx; @@ -261,8 +360,8 @@ void drm_sysfb_plane_helper_atomic_update(struct drm_plane *plane, struct drm_at continue; iosys_map_incr(&dst, drm_fb_clip_offset(dst_pitch, dst_format, &dst_clip)); - drm_fb_blit(&dst, &dst_pitch, dst_format->format, shadow_plane_state->data, fb, - &damage, &shadow_plane_state->fmtcnv_state); + blit_to_crtc(&dst, &dst_pitch, shadow_plane_state->data, fb, &damage, + &shadow_plane_state->fmtcnv_state); } drm_dev_exit(idx); @@ -321,6 +420,52 @@ int drm_sysfb_plane_helper_get_scanout_buffer(struct drm_plane *plane, } EXPORT_SYMBOL(drm_sysfb_plane_helper_get_scanout_buffer); +void drm_sysfb_plane_reset(struct drm_plane *plane) +{ + struct drm_sysfb_plane_state *sysfb_plane_state; + + if (plane->state) + drm_sysfb_plane_state_destroy(to_drm_sysfb_plane_state(plane->state)); + + sysfb_plane_state = kzalloc(sizeof(*sysfb_plane_state), GFP_KERNEL); + if (sysfb_plane_state) + __drm_gem_reset_shadow_plane(plane, &sysfb_plane_state->base); + else + __drm_gem_reset_shadow_plane(plane, NULL); +} +EXPORT_SYMBOL(drm_sysfb_plane_reset); + +struct drm_plane_state *drm_sysfb_plane_atomic_duplicate_state(struct drm_plane *plane) +{ + struct drm_device *dev = plane->dev; + struct drm_plane_state *plane_state = plane->state; + struct drm_sysfb_plane_state *sysfb_plane_state; + struct drm_sysfb_plane_state *new_sysfb_plane_state; + struct drm_shadow_plane_state *new_shadow_plane_state; + + if (drm_WARN_ON(dev, !plane_state)) + return NULL; + sysfb_plane_state = to_drm_sysfb_plane_state(plane_state); + + new_sysfb_plane_state = kzalloc(sizeof(*new_sysfb_plane_state), GFP_KERNEL); + if (!new_sysfb_plane_state) + return NULL; + new_shadow_plane_state = &new_sysfb_plane_state->base; + + __drm_gem_duplicate_shadow_plane_state(plane, new_shadow_plane_state); + new_sysfb_plane_state->blit_to_crtc = sysfb_plane_state->blit_to_crtc; + + return &new_shadow_plane_state->base; +} +EXPORT_SYMBOL(drm_sysfb_plane_atomic_duplicate_state); + +void drm_sysfb_plane_atomic_destroy_state(struct drm_plane *plane, + struct drm_plane_state *plane_state) +{ + drm_sysfb_plane_state_destroy(to_drm_sysfb_plane_state(plane_state)); +} +EXPORT_SYMBOL(drm_sysfb_plane_atomic_destroy_state); + /* * CRTC */ |