drm/rockchip: vop2: add support cubic lut from loader

Change-Id: I11d65477364dc9ff4fb34d038179d5702faeb484
Signed-off-by: Sandy Huang <hjc@rock-chips.com>
This commit is contained in:
Sandy Huang
2021-04-23 14:27:49 +08:00
parent 9dafae176b
commit fb57e7e357
3 changed files with 73 additions and 10 deletions

View File

@@ -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"))

View File

@@ -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

View File

@@ -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;
}