From fb57e7e3579e01f2bc6e003a9ed9e5045df3cc9f Mon Sep 17 00:00:00 2001 From: Sandy Huang Date: Fri, 23 Apr 2021 14:27:49 +0800 Subject: [PATCH] drm/rockchip: vop2: add support cubic lut from loader Change-Id: I11d65477364dc9ff4fb34d038179d5702faeb484 Signed-off-by: Sandy Huang --- drivers/gpu/drm/rockchip/rockchip_drm_drv.c | 41 +++++++++++++++++++- drivers/gpu/drm/rockchip/rockchip_drm_drv.h | 9 +++++ drivers/gpu/drm/rockchip/rockchip_drm_vop2.c | 33 ++++++++++++---- 3 files changed, 73 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c index d4051208b04f..b040b3f94933 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c @@ -329,9 +329,13 @@ static int init_loader_memory(struct drm_device *drm_dev) phys_addr_t start, size; u32 pg_size = PAGE_SIZE; struct resource res; - int ret; + int ret, idx; - node = of_parse_phandle(np, "logo-memory-region", 0); + idx = of_property_match_string(np, "memory-region-names", "drm-logo"); + if (idx >= 0) + node = of_parse_phandle(np, "memory-region", idx); + else + node = of_parse_phandle(np, "logo-memory-region", 0); if (!node) return -ENOMEM; @@ -365,6 +369,33 @@ static int init_loader_memory(struct drm_device *drm_dev) logo->count = 1; private->logo = logo; + idx = of_property_match_string(np, "memory-region-names", "drm-cubic-lut"); + if (idx < 0) + return 0; + + node = of_parse_phandle(np, "memory-region", idx); + if (!node) + return -ENOMEM; + + ret = of_address_to_resource(node, 0, &res); + if (ret) + return ret; + start = ALIGN_DOWN(res.start, pg_size); + size = resource_size(&res); + if (!size) + return 0; + + private->cubic_lut_kvaddr = phys_to_virt(start); + if (private->domain) { + ret = iommu_map(private->domain, start, start, ALIGN(size, pg_size), + IOMMU_WRITE | IOMMU_READ); + if (ret) { + dev_err(drm_dev->dev, "failed to create 1v1 mapping for cubic lut\n"); + goto err_free_logo; + } + } + private->cubic_lut_dma_addr = start; + return 0; err_free_logo: @@ -431,6 +462,7 @@ get_framebuffer_by_node(struct drm_device *drm_dev, struct device_node *node) static struct rockchip_drm_mode_set * of_parse_display_resource(struct drm_device *drm_dev, struct device_node *route) { + struct rockchip_drm_private *private = drm_dev->dev_private; struct rockchip_drm_mode_set *set; struct device_node *connect; struct drm_framebuffer *fb; @@ -498,6 +530,11 @@ of_parse_display_resource(struct drm_device *drm_dev, struct device_node *route) if (!of_property_read_u32(route, "overscan,bottom_margin", &val)) set->bottom_margin = val; + if (!of_property_read_u32(route, "cubic_lut,offset", &val)) { + private->cubic_lut[crtc->index].enable = true; + private->cubic_lut[crtc->index].offset = val; + } + set->ratio = 1; if (!of_property_read_string(route, "logo,mode", &string) && !strcmp(string, "fullscreen")) diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h index 7995f6c61945..cfe406457e1b 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h @@ -159,6 +159,11 @@ struct rockchip_logo { int count; }; +struct loader_cubic_lut { + bool enable; + u32 offset; +}; + /* * Rockchip drm private structure. * @@ -202,6 +207,10 @@ struct rockchip_drm_private { * ignore restore_fbdev_mode_atomic when in logo on state */ bool loader_protect; + + dma_addr_t cubic_lut_dma_addr; + void *cubic_lut_kvaddr; + struct loader_cubic_lut cubic_lut[ROCKCHIP_MAX_CRTC]; }; #ifndef MODULE diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c index 9787fcc84735..099d78f90816 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c @@ -2284,6 +2284,7 @@ static int vop2_crtc_atomic_cubic_lut_set(struct drm_crtc *crtc, struct drm_crtc_state *old_state) { struct vop2_video_port *vp = to_vop2_video_port(crtc); + struct rockchip_drm_private *private = crtc->dev->dev_private; struct drm_color_lut *lut = vp->cubic_lut; struct vop2 *vop2 = vp->vop2; u32 *cubic_lut_kvaddr; @@ -2295,16 +2296,22 @@ static int vop2_crtc_atomic_cubic_lut_set(struct drm_crtc *crtc, return -ENODEV; } - if (!vp->cubic_lut_gem_obj) { - size_t size = (vp->cubic_lut_len + 1) / 2 * 16; + if (!private->cubic_lut[vp->id].enable) { + if (!vp->cubic_lut_gem_obj) { + size_t size = (vp->cubic_lut_len + 1) / 2 * 16; - vp->cubic_lut_gem_obj = rockchip_gem_create_object(crtc->dev, size, true, 0); - if (IS_ERR(vp->cubic_lut_gem_obj)) - return -ENOMEM; + vp->cubic_lut_gem_obj = rockchip_gem_create_object(crtc->dev, size, true, 0); + if (IS_ERR(vp->cubic_lut_gem_obj)) + return -ENOMEM; + } + + cubic_lut_kvaddr = (u32 *)vp->cubic_lut_gem_obj->kvaddr; + cubic_lut_mst = vp->cubic_lut_gem_obj->dma_addr; + } else { + cubic_lut_kvaddr = private->cubic_lut[vp->id].offset + private->cubic_lut_kvaddr; + cubic_lut_mst = private->cubic_lut[vp->id].offset + private->cubic_lut_dma_addr; } - cubic_lut_kvaddr = (u32 *)vp->cubic_lut_gem_obj->kvaddr; - cubic_lut_mst = vp->cubic_lut_gem_obj->dma_addr; for (i = 0; i < vp->cubic_lut_len / 2; i++) { *cubic_lut_kvaddr++ = (lut[2 * i].red & 0xfff) + ((lut[2 * i].green & 0xfff) << 12) + @@ -3438,6 +3445,7 @@ static int vop2_crtc_loader_protect(struct drm_crtc *crtc, bool on) { struct vop2_video_port *vp = to_vop2_video_port(crtc); struct vop2 *vop2 = vp->vop2; + struct rockchip_drm_private *private = crtc->dev->dev_private; if (on == vp->loader_protect) return 0; @@ -3447,6 +3455,13 @@ static int vop2_crtc_loader_protect(struct drm_crtc *crtc, bool on) vop2_set_system_status(vop2); vop2_initial(crtc); drm_crtc_vblank_on(crtc); + if (private->cubic_lut[vp->id].enable) { + dma_addr_t cubic_lut_mst; + struct loader_cubic_lut *cubic_lut = &private->cubic_lut[vp->id]; + + cubic_lut_mst = cubic_lut->offset + private->cubic_lut_dma_addr; + VOP_MODULE_SET(vop2, vp, cubic_lut_mst, cubic_lut_mst); + } vp->loader_protect = true; } else { vop2_crtc_atomic_disable(crtc, NULL); @@ -3636,12 +3651,14 @@ static int vop2_cubic_lut_show(struct seq_file *s, void *data) { struct drm_info_node *node = s->private; struct vop2 *vop2 = node->info_ent->data; + struct rockchip_drm_private *private = vop2->drm_dev->dev_private; int i, j; for (i = 0; i < vop2->data->nr_vps; i++) { struct vop2_video_port *vp = &vop2->vps[i]; - if (!vp->cubic_lut_gem_obj || !vp->cubic_lut || !vp->crtc.state->enable) { + if ((!vp->cubic_lut_gem_obj && !private->cubic_lut[vp->id].enable) || + !vp->cubic_lut || !vp->crtc.state->enable) { DEBUG_PRINT("Video port%d cubic lut disabled\n", vp->id); continue; }