diff options
Diffstat (limited to 'meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0103-gpu-drm-rcar-du-Extend-VSP1-DRM-interface.patch')
-rw-r--r-- | meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0103-gpu-drm-rcar-du-Extend-VSP1-DRM-interface.patch | 546 |
1 files changed, 546 insertions, 0 deletions
diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0103-gpu-drm-rcar-du-Extend-VSP1-DRM-interface.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0103-gpu-drm-rcar-du-Extend-VSP1-DRM-interface.patch new file mode 100644 index 0000000..e3f24a6 --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0103-gpu-drm-rcar-du-Extend-VSP1-DRM-interface.patch @@ -0,0 +1,546 @@ +From b6176e313aea415b83d5762db275b2f364f08820 Mon Sep 17 00:00:00 2001 +From: Konstantin Kozhevnikov <Konstantin.Kozhevnikov@cogentembedded.com> +Date: Tue, 14 Nov 2017 01:38:51 -0800 +Subject: [PATCH] gpu: drm: rcar-du: Extend VSP1-DRM interface + +Extend VSP1-DRM interface + +Signed-off-by: Konstantin Kozhevnikov <Konstantin.Kozhevnikov@cogentembedded.com> +--- + drivers/gpu/drm/drm_framebuffer.c | 1 + + drivers/gpu/drm/rcar-du/rcar_du_drv.h | 5 + + drivers/gpu/drm/rcar-du/rcar_du_kms.c | 42 ++++++- + drivers/gpu/drm/rcar-du/rcar_du_plane.c | 3 +- + drivers/gpu/drm/rcar-du/rcar_du_plane.h | 5 + + drivers/gpu/drm/rcar-du/rcar_du_vsp.c | 209 ++++++++++++++++++++++++++------ + drivers/gpu/drm/rcar-du/rcar_du_vsp.h | 7 +- + 7 files changed, 232 insertions(+), 40 deletions(-) + +diff --git a/drivers/gpu/drm/drm_framebuffer.c b/drivers/gpu/drm/drm_framebuffer.c +index 398efd6..4a43e15 100644 +--- a/drivers/gpu/drm/drm_framebuffer.c ++++ b/drivers/gpu/drm/drm_framebuffer.c +@@ -192,6 +192,7 @@ static int format_check(const struct drm_mode_fb_cmd2 *r) + case DRM_FORMAT_YVU422: + case DRM_FORMAT_YUV444: + case DRM_FORMAT_YVU444: ++ case DRM_FORMAT_R8: + return 0; + default: + format_name = drm_get_format_name(r->pixel_format); +diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.h b/drivers/gpu/drm/rcar-du/rcar_du_drv.h +index 45d6e7e..bdf2612 100644 +--- a/drivers/gpu/drm/rcar-du/rcar_du_drv.h ++++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.h +@@ -104,6 +104,11 @@ struct rcar_du_device { + struct { + struct drm_property *alpha; + struct drm_property *colorkey; ++ struct drm_property *alphaplane; ++ struct drm_property *blend; ++ struct drm_property *ckey; ++ struct drm_property *ckey_set0; ++ struct drm_property *ckey_set1; + } props; + + unsigned int dpad0_source; +diff --git a/drivers/gpu/drm/rcar-du/rcar_du_kms.c b/drivers/gpu/drm/rcar-du/rcar_du_kms.c +index e955e92..31b48bc 100644 +--- a/drivers/gpu/drm/rcar-du/rcar_du_kms.c ++++ b/drivers/gpu/drm/rcar-du/rcar_du_kms.c +@@ -10,7 +10,7 @@ + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ +- ++//#define DEBUG + #include <drm/drmP.h> + #include <drm/drm_atomic.h> + #include <drm/drm_atomic_helper.h> +@@ -101,6 +101,12 @@ static const struct rcar_du_format_info rcar_du_format_infos[] = { + .planes = 2, + .pnmr = PnMR_SPIM_TP_OFF | PnMR_DDDF_YC, + .edf = PnDDCR4_EDF_NONE, ++ }, { ++ .fourcc = DRM_FORMAT_R8, ++ .bpp = 8, ++ .planes = 1, ++ .pnmr = PnMR_SPIM_TP_OFF | PnMR_DDDF_8BPP, ++ .edf = PnDDCR4_EDF_NONE, + }, + }; + +@@ -169,6 +175,10 @@ static const struct rcar_du_format_info rcar_vsp_format_infos[] = { + .fourcc = DRM_FORMAT_YVU444, + .bpp = 24, + .planes = 3, ++ }, { ++ .fourcc = DRM_FORMAT_R8, ++ .bpp = 8, ++ .planes = 1, + }, + }; + +@@ -565,6 +575,36 @@ static int rcar_du_properties_init(struct rcar_du_device *rcdu) + if (rcdu->props.colorkey == NULL) + return -ENOMEM; + ++ rcdu->props.alphaplane = ++ drm_property_create(rcdu->ddev, DRM_MODE_PROP_OBJECT, "alphaplane", 1); ++ if (rcdu->props.alphaplane == NULL) ++ return -ENOMEM; ++ rcdu->props.alphaplane->values[0] = DRM_MODE_OBJECT_FB; ++ ++ rcdu->props.blend = ++ drm_property_create_range(rcdu->ddev, 0, "blend", ++ 0, 0xffffffff); ++ if (rcdu->props.blend == NULL) ++ return -ENOMEM; ++ ++ rcdu->props.ckey = ++ drm_property_create_range(rcdu->ddev, 0, "ckey", ++ 0, 0xffffffff); ++ if (rcdu->props.ckey == NULL) ++ return -ENOMEM; ++ ++ rcdu->props.ckey_set0 = ++ drm_property_create_range(rcdu->ddev, 0, "ckey_set0", ++ 0, 0xffffffff); ++ if (rcdu->props.ckey_set0 == NULL) ++ return -ENOMEM; ++ ++ rcdu->props.ckey_set1 = ++ drm_property_create_range(rcdu->ddev, 0, "ckey_set1", ++ 0, 0xffffffff); ++ if (rcdu->props.ckey_set1 == NULL) ++ return -ENOMEM; ++ + return 0; + } + +diff --git a/drivers/gpu/drm/rcar-du/rcar_du_plane.c b/drivers/gpu/drm/rcar-du/rcar_du_plane.c +index e408aa3..2b57f09 100644 +--- a/drivers/gpu/drm/rcar-du/rcar_du_plane.c ++++ b/drivers/gpu/drm/rcar-du/rcar_du_plane.c +@@ -10,7 +10,7 @@ + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ +- ++//#define DEBUG + #include <drm/drmP.h> + #include <drm/drm_atomic.h> + #include <drm/drm_atomic_helper.h> +@@ -719,6 +719,7 @@ static const uint32_t formats[] = { + DRM_FORMAT_NV12, + DRM_FORMAT_NV21, + DRM_FORMAT_NV16, ++ DRM_FORMAT_R8, + }; + + int rcar_du_planes_init(struct rcar_du_group *rgrp) +diff --git a/drivers/gpu/drm/rcar-du/rcar_du_plane.h b/drivers/gpu/drm/rcar-du/rcar_du_plane.h +index c1de338..a6065ef 100644 +--- a/drivers/gpu/drm/rcar-du/rcar_du_plane.h ++++ b/drivers/gpu/drm/rcar-du/rcar_du_plane.h +@@ -66,6 +66,11 @@ struct rcar_du_plane_state { + + unsigned int alpha; + unsigned int colorkey; ++ struct drm_framebuffer *alphaplane; ++ unsigned int blend; ++ unsigned int ckey; ++ unsigned int ckey_set0; ++ unsigned int ckey_set1; + }; + + static inline struct rcar_du_plane_state * +diff --git a/drivers/gpu/drm/rcar-du/rcar_du_vsp.c b/drivers/gpu/drm/rcar-du/rcar_du_vsp.c +index 770238a..910e0f0 100644 +--- a/drivers/gpu/drm/rcar-du/rcar_du_vsp.c ++++ b/drivers/gpu/drm/rcar-du/rcar_du_vsp.c +@@ -10,7 +10,7 @@ + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ +- ++//#define DEBUG + #include <drm/drmP.h> + #include <drm/drm_atomic.h> + #include <drm/drm_atomic_helper.h> +@@ -91,6 +91,16 @@ void rcar_du_vsp_enable(struct rcar_du_crtc *crtc) + + void rcar_du_vsp_disable(struct rcar_du_crtc *crtc) + { ++ struct rcar_du_vsp *vsp = crtc->vsp; ++ struct rcar_du_vsp_plane *primary = &vsp->planes[0]; ++ struct rcar_du_vsp_plane_state *rstate = to_rcar_vsp_plane_state(primary->plane.state); ++ ++ /* ...drop alpha-plane associated with primary plane (why only primary? - tbd) */ ++ if (rstate->alphaplane) { ++ drm_framebuffer_unreference(rstate->alphaplane); ++ rstate->alphaplane = NULL; ++ } ++ + vsp1_du_setup_lif(crtc->vsp->vsp, NULL, crtc->lif_index, + crtc->suspend); + } +@@ -133,6 +143,7 @@ static const u32 formats_kms[] = { + DRM_FORMAT_YVU422, + DRM_FORMAT_YUV444, + DRM_FORMAT_YVU444, ++ DRM_FORMAT_R8, + }; + + static const u32 formats_v4l2[] = { +@@ -162,6 +173,7 @@ static const u32 formats_v4l2[] = { + V4L2_PIX_FMT_YVU422M, + V4L2_PIX_FMT_YUV444M, + V4L2_PIX_FMT_YVU444M, ++ V4L2_PIX_FMT_GREY, + }; + + static const u32 formats_xlate[][2] = { +@@ -184,6 +196,7 @@ static const u32 formats_xlate[][2] = { + { DRM_FORMAT_NV21, V4L2_PIX_FMT_NV21M }, + { DRM_FORMAT_NV16, V4L2_PIX_FMT_NV16M }, + { DRM_FORMAT_NV61, V4L2_PIX_FMT_NV61M }, ++ { DRM_FORMAT_R8, V4L2_PIX_FMT_GREY }, + }; + + static void rcar_du_vsp_plane_setup(struct rcar_du_vsp_plane *plane) +@@ -226,6 +239,27 @@ static void rcar_du_vsp_plane_setup(struct rcar_du_vsp_plane *plane) + } + } + ++ /* ...add alpha-plane as needed */ ++ if (state->alphaplane) { ++ i = state->format->planes; ++ cfg.alpha_mem = sg_dma_address(state->sg_tables[i].sgl); ++ cfg.alpha_pitch = state->alphaplane->pitches[0]; ++ pr_debug("alpha-%d: set alpha-mem address: %llx, pitch=%d\n", i, (unsigned long long)cfg.alpha_mem, cfg.alpha_pitch); ++ } ++ ++ /* ...add blending formula as needed */ ++ if (state->blend) { ++ cfg.blend = state->blend; ++ pr_debug("set blending formula: %X\n", cfg.blend); ++ } ++ ++ /* ...add color key property as needed */ ++ if (state->ckey) { ++ cfg.ckey = state->ckey; ++ cfg.ckey_set0 = state->ckey_set0; ++ cfg.ckey_set1 = state->ckey_set1; ++ } ++ + vsp1_du_atomic_update(plane->vsp->vsp, plane->index, &cfg); + } + +@@ -259,6 +293,23 @@ static int rcar_du_vsp_plane_prepare_fb(struct drm_plane *plane, + } + } + ++ /* ...check if we have alpha-plane attached */ ++ if (rstate->alphaplane) { ++ struct drm_gem_cma_object *gem = drm_fb_cma_get_gem_obj(rstate->alphaplane, 0); ++ struct sg_table *sgt = &rstate->sg_tables[i++]; ++ ++ ret = dma_get_sgtable(rcdu->dev, sgt, gem->vaddr, gem->paddr, gem->base.size); ++ if (ret) ++ goto fail; ++ ++ ret = vsp1_du_map_sg(vsp->vsp, sgt); ++ if (!ret) { ++ sg_free_table(sgt); ++ ret = -ENOMEM; ++ goto fail; ++ } ++ } ++ + return 0; + + fail: +@@ -288,6 +339,14 @@ static void rcar_du_vsp_plane_cleanup_fb(struct drm_plane *plane, + vsp1_du_unmap_sg(vsp->vsp, sgt); + sg_free_table(sgt); + } ++ ++ if (rstate->alphaplane) { ++ struct sg_table *sgt = &rstate->sg_tables[i]; ++ ++ vsp1_du_unmap_sg(vsp->vsp, sgt); ++ sg_free_table(sgt); ++ pr_debug("unmap alpha-plane\n"); ++ } + } + + static int rcar_du_vsp_plane_atomic_check(struct drm_plane *plane, +@@ -369,6 +428,11 @@ rcar_du_vsp_plane_atomic_duplicate_state(struct drm_plane *plane) + if (copy == NULL) + return NULL; + ++ if (copy->alphaplane) { ++ drm_framebuffer_reference(copy->alphaplane); ++ pr_debug("duplicate alpha-plane '%p' (refcount=%d)\n", copy->alphaplane, drm_framebuffer_read_refcount(copy->alphaplane)); ++ } ++ + __drm_atomic_helper_plane_duplicate_state(plane, ©->state); + + return ©->state; +@@ -377,8 +441,15 @@ rcar_du_vsp_plane_atomic_duplicate_state(struct drm_plane *plane) + static void rcar_du_vsp_plane_atomic_destroy_state(struct drm_plane *plane, + struct drm_plane_state *state) + { ++ struct rcar_du_vsp_plane_state *rstate = to_rcar_vsp_plane_state(state); ++ ++ if (rstate->alphaplane) { ++ pr_debug("unref alpha-plane '%p' (refcount=%d)\n", rstate->alphaplane, drm_framebuffer_read_refcount(rstate->alphaplane)); ++ drm_framebuffer_unreference(rstate->alphaplane); ++ } ++ + __drm_atomic_helper_plane_destroy_state(state); +- kfree(to_rcar_vsp_plane_state(state)); ++ kfree(rstate); + } + + static void rcar_du_vsp_plane_reset(struct drm_plane *plane) +@@ -386,6 +457,7 @@ static void rcar_du_vsp_plane_reset(struct drm_plane *plane) + struct rcar_du_vsp_plane_state *state; + + if (plane->state) { ++ pr_debug("reset plane '%p'\n", to_rcar_vsp_plane_state(plane->state)->alphaplane); + rcar_du_vsp_plane_atomic_destroy_state(plane, plane->state); + plane->state = NULL; + } +@@ -410,7 +482,30 @@ static int rcar_du_vsp_plane_atomic_set_property(struct drm_plane *plane, + + if (property == rcdu->props.alpha) + rstate->alpha = val; +- else ++ else if (property == rcdu->props.blend) ++ rstate->blend = val; ++ else if (property == rcdu->props.ckey) ++ rstate->ckey = val; ++ else if (property == rcdu->props.ckey_set0) ++ rstate->ckey_set0 = val; ++ else if (property == rcdu->props.ckey_set1) ++ rstate->ckey_set1 = val; ++ else if (property == rcdu->props.alphaplane) { ++ if (rstate->alphaplane) { ++ pr_debug("unref alpha-plane '%p' (refcount=%d)\n", rstate->alphaplane, drm_framebuffer_read_refcount(rstate->alphaplane)); ++ drm_framebuffer_unreference(rstate->alphaplane); ++ } ++ rstate->alphaplane = drm_framebuffer_lookup(plane->dev, val); ++ if (rstate->alphaplane) { ++ pr_debug("use alpha-plane '%p' (refcount=%d)\n", rstate->alphaplane, drm_framebuffer_read_refcount(rstate->alphaplane)); ++ /* ...the way how we handle this leads to a "loss" of plane reference (it is acquired ++ * within "drm_property_change_valid_get" but not returned in symmetric "drm_property_change_valid_put") ++ * Whether it is a bug or was done intentionally, I don't know. For a moment just drop that ++ * extra reference right here ++ */ ++ if (0) drm_framebuffer_unreference(rstate->alphaplane); ++ } ++ } else + return -EINVAL; + + return 0; +@@ -426,6 +521,16 @@ static int rcar_du_vsp_plane_atomic_get_property(struct drm_plane *plane, + + if (property == rcdu->props.alpha) + *val = rstate->alpha; ++ else if (property == rcdu->props.alphaplane) ++ *val = (rstate->alphaplane ? rstate->alphaplane->base.id : 0); ++ else if (property == rcdu->props.blend) ++ *val = rstate->blend; ++ else if (property == rcdu->props.ckey) ++ *val = rstate->ckey; ++ else if (property == rcdu->props.ckey_set0) ++ *val = rstate->ckey_set0; ++ else if (property == rcdu->props.ckey_set1) ++ *val = rstate->ckey_set1; + else + return -EINVAL; + +@@ -442,9 +547,10 @@ int rcar_du_vsp_write_back(struct drm_device *dev, void *data, + struct rcar_du_crtc *rcrtc; + struct rcar_du_device *rcdu; + const struct drm_display_mode *mode; +- u32 pixelformat, bpp; +- unsigned int pitch; ++ struct drm_framebuffer *fb; + dma_addr_t mem[3]; ++ struct sg_table sg_tables[3]; ++ int i = 0; + + obj = drm_mode_object_find(dev, sh->crtc_id, DRM_MODE_OBJECT_CRTC); + if (!obj) +@@ -455,62 +561,79 @@ int rcar_du_vsp_write_back(struct drm_device *dev, void *data, + rcdu = rcrtc->group->dev; + mode = &rcrtc->crtc.state->adjusted_mode; + +- switch (sh->fmt) { +- case DRM_FORMAT_RGB565: +- bpp = 16; +- pixelformat = V4L2_PIX_FMT_RGB565; +- break; +- case DRM_FORMAT_ARGB1555: +- bpp = 16; +- pixelformat = V4L2_PIX_FMT_ARGB555; +- break; +- case DRM_FORMAT_ARGB8888: +- bpp = 32; +- pixelformat = V4L2_PIX_FMT_ABGR32; +- break; +- default: +- dev_err(rcdu->dev, "specified format is not supported.\n"); ++ fb = drm_framebuffer_lookup(dev, sh->buff); ++ if (!fb) { ++ dev_err(dev->dev, "failed to lookup destination framebuffer '%lu'\n", sh->buff); + return -EINVAL; + } + +- pitch = mode->hdisplay * bpp / 8; ++ /* ...check framebuffer is okay */ ++ if ((fb->width != (mode->hdisplay)) || ++ (fb->height != (mode->vdisplay))) { ++ dev_err(dev->dev, "wrong fb mode: %d*%d vs %d*%d\n", fb->width, fb->height, mode->hdisplay, mode->vdisplay); ++ ret = -EINVAL; ++ goto done; ++ } + +- mem[0] = sh->buff; +- mem[1] = 0; +- mem[2] = 0; ++ /* ...need to verify compatibility of output format, I guess - tbd */ + +- if ((sh->width != (mode->hdisplay)) || +- (sh->height != (mode->vdisplay))) +- return -EINVAL; ++ /* ...fill memory planes addresses */ ++ for (i = 0; i < 3; i++) { ++ struct drm_gem_cma_object *gem; ++ struct sg_table *sgt = &sg_tables[i]; ++ gem = drm_fb_cma_get_gem_obj(fb, i); ++ if (!gem) ++ break; ++ ret = dma_get_sgtable(rcdu->dev, sgt, gem->vaddr, gem->paddr, ++ gem->base.size); ++ if (ret) ++ goto done; + +- if ((pitch * mode->vdisplay) > sh->buff_len) +- return -EINVAL; ++ ret = vsp1_du_map_sg(rcrtc->vsp->vsp, sgt); ++ if (!ret) { ++ sg_free_table(sgt); ++ ret = -ENOMEM; ++ goto done; ++ } ++ mem[i] = sg_dma_address(sg_tables[i].sgl) + fb->offsets[i]; ++ } ++ ++ dev_info(dev->dev, "setup write-back (pixfmt=%X, %u*%u, planes: %d)\n", fb->pixel_format, fb->width, fb->height, i); ++ ++ vsp1_du_setup_wb(rcrtc->vsp->vsp, fb->pixel_format, fb->pitches[0], mem, rcrtc->lif_index); + +- vsp1_du_setup_wb(rcrtc->vsp->vsp, pixelformat, pitch, mem, +- rcrtc->lif_index); + ret = vsp1_du_wait_wb(rcrtc->vsp->vsp, WB_STAT_CATP_SET, + rcrtc->lif_index); + if (ret != 0) +- return ret; ++ goto done; + + ret = rcar_du_async_commit(dev, crtc); + if (ret != 0) +- return ret; ++ goto done; + + ret = vsp1_du_wait_wb(rcrtc->vsp->vsp, WB_STAT_CATP_START, + rcrtc->lif_index); + if (ret != 0) +- return ret; ++ goto done; + + ret = rcar_du_async_commit(dev, crtc); + if (ret != 0) +- return ret; ++ goto done; + + ret = vsp1_du_wait_wb(rcrtc->vsp->vsp, WB_STAT_CATP_DONE, + rcrtc->lif_index); + if (ret != 0) +- return ret; ++ goto done; ++ ++done: ++ /* ...unmap all tables */ ++ while (i--) { ++ struct sg_table *sgt = &sg_tables[i]; ++ vsp1_du_unmap_sg(rcrtc->vsp->vsp, sgt); ++ sg_free_table(sgt); ++ } + ++ drm_framebuffer_unreference(fb); + return ret; + } + +@@ -574,6 +697,7 @@ static const uint32_t formats[] = { + DRM_FORMAT_NV21, + DRM_FORMAT_NV16, + DRM_FORMAT_NV61, ++ DRM_FORMAT_R8, + }; + + int rcar_du_vsp_init(struct rcar_du_vsp *vsp) +@@ -653,13 +777,24 @@ int rcar_du_vsp_init(struct rcar_du_vsp *vsp) + drm_plane_helper_add(&plane->plane, + &rcar_du_vsp_plane_helper_funcs); + ++#if 0 // ...use same set of properties for all planes + if (type == DRM_PLANE_TYPE_PRIMARY) + continue; +- ++#endif + drm_object_attach_property(&plane->plane.base, + rcdu->props.alpha, 255); + drm_plane_create_zpos_property(&plane->plane, 1, 1, + vsp->num_planes - 1); ++ drm_object_attach_property(&plane->plane.base, ++ rcdu->props.alphaplane, 0); ++ drm_object_attach_property(&plane->plane.base, ++ rcdu->props.blend, 0); ++ drm_object_attach_property(&plane->plane.base, ++ rcdu->props.ckey, 0); ++ drm_object_attach_property(&plane->plane.base, ++ rcdu->props.ckey_set0, 0); ++ drm_object_attach_property(&plane->plane.base, ++ rcdu->props.ckey_set1, 0); + } + + return 0; +diff --git a/drivers/gpu/drm/rcar-du/rcar_du_vsp.h b/drivers/gpu/drm/rcar-du/rcar_du_vsp.h +index 3fd9cef..2f4aa41 100644 +--- a/drivers/gpu/drm/rcar-du/rcar_du_vsp.h ++++ b/drivers/gpu/drm/rcar-du/rcar_du_vsp.h +@@ -52,10 +52,15 @@ struct rcar_du_vsp_plane_state { + struct drm_plane_state state; + + const struct rcar_du_format_info *format; +- struct sg_table sg_tables[3]; ++ struct sg_table sg_tables[4]; + + unsigned int alpha; + unsigned int zpos; ++ struct drm_framebuffer *alphaplane; ++ unsigned int blend; ++ unsigned int ckey; ++ unsigned int ckey_set0; ++ unsigned int ckey_set1; + }; + + static inline struct rcar_du_vsp_plane_state * +-- +2.7.4 + |