summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/drm_format_helper.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/drm_format_helper.c')
-rw-r--r--drivers/gpu/drm/drm_format_helper.c96
1 files changed, 92 insertions, 4 deletions
diff --git a/drivers/gpu/drm/drm_format_helper.c b/drivers/gpu/drm/drm_format_helper.c
index c043ca364c86..0e885cd34107 100644
--- a/drivers/gpu/drm/drm_format_helper.c
+++ b/drivers/gpu/drm/drm_format_helper.c
@@ -52,6 +52,7 @@ EXPORT_SYMBOL(drm_fb_memcpy);
/**
* drm_fb_memcpy_dstclip - Copy clip buffer
* @dst: Destination buffer (iomem)
+ * @dst_pitch: Number of bytes between two consecutive scanlines within dst
* @vaddr: Source buffer
* @fb: DRM framebuffer
* @clip: Clip rectangle area to copy
@@ -59,12 +60,12 @@ EXPORT_SYMBOL(drm_fb_memcpy);
* This function applies clipping on dst, i.e. the destination is a
* full (iomem) framebuffer but only the clip rect content is copied over.
*/
-void drm_fb_memcpy_dstclip(void __iomem *dst, void *vaddr,
- struct drm_framebuffer *fb,
+void drm_fb_memcpy_dstclip(void __iomem *dst, unsigned int dst_pitch,
+ void *vaddr, struct drm_framebuffer *fb,
struct drm_rect *clip)
{
unsigned int cpp = fb->format->cpp[0];
- unsigned int offset = clip_offset(clip, fb->pitches[0], cpp);
+ unsigned int offset = clip_offset(clip, dst_pitch, cpp);
size_t len = (clip->x2 - clip->x1) * cpp;
unsigned int y, lines = clip->y2 - clip->y1;
@@ -73,7 +74,7 @@ void drm_fb_memcpy_dstclip(void __iomem *dst, void *vaddr,
for (y = 0; y < lines; y++) {
memcpy_toio(dst, vaddr, len);
vaddr += fb->pitches[0];
- dst += fb->pitches[0];
+ dst += dst_pitch;
}
}
EXPORT_SYMBOL(drm_fb_memcpy_dstclip);
@@ -343,3 +344,90 @@ void drm_fb_xrgb8888_to_gray8(u8 *dst, void *vaddr, struct drm_framebuffer *fb,
}
EXPORT_SYMBOL(drm_fb_xrgb8888_to_gray8);
+/**
+ * drm_fb_blit_rect_dstclip - Copy parts of a framebuffer to display memory
+ * @dst: The display memory to copy to
+ * @dst_pitch: Number of bytes between two consecutive scanlines within dst
+ * @dst_format: FOURCC code of the display's color format
+ * @vmap: The framebuffer memory to copy from
+ * @fb: The framebuffer to copy from
+ * @clip: Clip rectangle area to copy
+ *
+ * This function copies parts of a framebuffer to display memory. If the
+ * formats of the display and the framebuffer mismatch, the blit function
+ * will attempt to convert between them.
+ *
+ * Use drm_fb_blit_dstclip() to copy the full framebuffer.
+ *
+ * Returns:
+ * 0 on success, or
+ * -EINVAL if the color-format conversion failed, or
+ * a negative error code otherwise.
+ */
+int drm_fb_blit_rect_dstclip(void __iomem *dst, unsigned int dst_pitch,
+ uint32_t dst_format, void *vmap,
+ struct drm_framebuffer *fb,
+ struct drm_rect *clip)
+{
+ uint32_t fb_format = fb->format->format;
+
+ /* treat alpha channel like filler bits */
+ if (fb_format == DRM_FORMAT_ARGB8888)
+ fb_format = DRM_FORMAT_XRGB8888;
+ if (dst_format == DRM_FORMAT_ARGB8888)
+ dst_format = DRM_FORMAT_XRGB8888;
+
+ if (dst_format == fb_format) {
+ drm_fb_memcpy_dstclip(dst, dst_pitch, vmap, fb, clip);
+ return 0;
+
+ } else if (dst_format == DRM_FORMAT_RGB565) {
+ if (fb_format == DRM_FORMAT_XRGB8888) {
+ drm_fb_xrgb8888_to_rgb565_dstclip(dst, dst_pitch,
+ vmap, fb, clip,
+ false);
+ return 0;
+ }
+ } else if (dst_format == DRM_FORMAT_RGB888) {
+ if (fb_format == DRM_FORMAT_XRGB8888) {
+ drm_fb_xrgb8888_to_rgb888_dstclip(dst, dst_pitch,
+ vmap, fb, clip);
+ return 0;
+ }
+ }
+
+ return -EINVAL;
+}
+EXPORT_SYMBOL(drm_fb_blit_rect_dstclip);
+
+/**
+ * drm_fb_blit_dstclip - Copy framebuffer to display memory
+ * @dst: The display memory to copy to
+ * @dst_pitch: Number of bytes between two consecutive scanlines within dst
+ * @dst_format: FOURCC code of the display's color format
+ * @vmap: The framebuffer memory to copy from
+ * @fb: The framebuffer to copy from
+ *
+ * This function copies a full framebuffer to display memory. If the formats
+ * of the display and the framebuffer mismatch, the copy function will
+ * attempt to convert between them.
+ *
+ * See drm_fb_blit_rect_dstclip() for more inforamtion.
+ *
+ * Returns:
+ * 0 on success, or a negative error code otherwise.
+ */
+int drm_fb_blit_dstclip(void __iomem *dst, unsigned int dst_pitch,
+ uint32_t dst_format, void *vmap,
+ struct drm_framebuffer *fb)
+{
+ struct drm_rect fullscreen = {
+ .x1 = 0,
+ .x2 = fb->width,
+ .y1 = 0,
+ .y2 = fb->height,
+ };
+ return drm_fb_blit_rect_dstclip(dst, dst_pitch, dst_format, vmap, fb,
+ &fullscreen);
+}
+EXPORT_SYMBOL(drm_fb_blit_dstclip);