From fb5b2cfea82e02a1d785ba47e6d450d562cd224c Mon Sep 17 00:00:00 2001 From: Andy Yan Date: Wed, 2 Jun 2021 17:04:02 +0800 Subject: [PATCH] drm/rockchip: vop2: Support set cursor win from dts for example: Use CLuster0 as cursor win for vp0. &vp0 { cursor-win-id = ; }; Change-Id: I10f7921928fbf7ff803c55a95cbce62df658fbed Signed-off-by: Andy Yan --- drivers/gpu/drm/rockchip/rockchip_drm_vop2.c | 71 +++++++++++++++----- include/dt-bindings/display/rockchip_vop.h | 21 ++++++ 2 files changed, 76 insertions(+), 16 deletions(-) create mode 100644 include/dt-bindings/display/rockchip_vop.h diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c index 1a9c1cd4ebdc..811aa0ab235b 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c @@ -462,6 +462,8 @@ struct vop2_video_port { */ uint8_t nr_layers; + int cursor_win_id; + /** * @active_tv_state: TV connector related states */ @@ -2992,12 +2994,18 @@ static void vop2_plane_atomic_update(struct drm_plane *plane, struct drm_plane_s DRM_ERROR("vp%d %s dest->x1[%d] + dsp_w[%d] exceed mode hdisplay[%d]\n", vp->id, win->name, dest->x1, dsp_w, adjusted_mode->hdisplay); dsp_w = adjusted_mode->hdisplay - dest->x1; + if (dsp_w < 4) + dsp_w = 4; + actual_w = dsp_w * actual_w / drm_rect_width(dest); } dsp_h = drm_rect_height(dest); if (dest->y1 + dsp_h > adjusted_mode->vdisplay) { DRM_ERROR("vp%d %s dest->y1[%d] + dsp_h[%d] exceed mode vdisplay[%d]\n", vp->id, win->name, dest->y1, dsp_h, adjusted_mode->vdisplay); dsp_h = adjusted_mode->vdisplay - dest->y1; + if (dsp_h < 4) + dsp_h = 4; + actual_h = dsp_h * actual_h / drm_rect_height(dest); } /* @@ -5810,7 +5818,7 @@ static int vop2_plane_init(struct vop2 *vop2, struct vop2_win *win, unsigned lon if (win->feature & WIN_FEATURE_AFBDC) { if (vop2->disable_afbc_win) - return 0; + return -EACCES; } ret = drm_universal_plane_init(vop2->drm_dev, &win->base, possible_crtcs, @@ -5888,6 +5896,24 @@ static int vop2_plane_init(struct vop2 *vop2, struct vop2_win *win, unsigned lon return 0; } +static struct drm_plane *vop2_cursor_plane_init(struct vop2_video_port *vp, + unsigned long possible_crtcs) +{ + struct vop2 *vop2 = vp->vop2; + struct drm_plane *cursor = NULL; + struct vop2_win *win; + + win = vop2_find_win_by_phys_id(vop2, vp->cursor_win_id); + if (win) { + win->type = DRM_PLANE_TYPE_CURSOR; + win->zpos = vop2->registered_num_wins - 1; + if (!vop2_plane_init(vop2, win, possible_crtcs)) + cursor = &win->base; + } + + return cursor; +} + static int vop2_gamma_init(struct vop2 *vop2) { const struct vop2_data *vop2_data = vop2->data; @@ -5995,6 +6021,7 @@ static int vop2_create_crtc(struct vop2 *vop2) struct drm_device *drm_dev = vop2->drm_dev; struct device *dev = vop2->dev; struct drm_plane *plane; + struct drm_plane *cursor = NULL; struct drm_crtc *crtc; struct device_node *port; struct vop2_win *win = NULL; @@ -6022,6 +6049,7 @@ static int vop2_create_crtc(struct vop2 *vop2) vp->vop2 = vop2; vp->id = vp_data->id; vp->regs = vp_data->regs; + vp->cursor_win_id = -1; if (vop2_soc_is_rk3566()) soc_id = vp_data->soc_id[1]; else @@ -6036,6 +6064,14 @@ static int vop2_create_crtc(struct vop2 *vop2) crtc = &vp->crtc; + port = of_graph_get_port_by_id(dev->of_node, i); + if (!port) { + DRM_DEV_ERROR(vop2->dev, "no port node found for video_port%d\n", i); + return -ENOENT; + } + crtc->port = port; + of_property_read_u32(port, "cursor-win-id", &vp->cursor_win_id); + if (vp->primary_plane_phy_id >= 0) { win = vop2_find_win_by_phys_id(vop2, vp->primary_plane_phy_id); if (win) @@ -6076,11 +6112,24 @@ static int vop2_create_crtc(struct vop2 *vop2) } if (vop2_plane_init(vop2, win, possible_crtcs)) { - DRM_DEV_ERROR(vop2->dev, "failed to init plane\n"); + DRM_DEV_ERROR(vop2->dev, "failed to init primary plane\n"); break; } plane = &win->base; - ret = drm_crtc_init_with_planes(drm_dev, crtc, plane, NULL, &vop2_crtc_funcs, + + /* some times we want a cursor window for some vp */ + if (vp->cursor_win_id >= 0) { + cursor = vop2_cursor_plane_init(vp, possible_crtcs); + if (!cursor) + DRM_WARN("failed to init cursor plane for vp%d\n", vp->id); + else + DRM_DEV_INFO(vop2->dev, "%s as cursor plane for vp%d\n", + cursor->name, vp->id); + } else { + cursor = NULL; + } + + ret = drm_crtc_init_with_planes(drm_dev, crtc, plane, cursor, &vop2_crtc_funcs, "video_port%d", vp->id); if (ret) { DRM_DEV_ERROR(vop2->dev, "crtc init for video_port%d failed\n", i); @@ -6089,14 +6138,6 @@ static int vop2_create_crtc(struct vop2 *vop2) drm_crtc_helper_add(crtc, &vop2_crtc_helper_funcs); - port = of_graph_get_port_by_id(dev->of_node, i); - if (!port) { - DRM_DEV_ERROR(vop2->dev, "no port node found for video_port%d\n", i); - ret = -ENOENT; - } - - crtc->port = port; - drm_flip_work_init(&vp->fb_unref_work, "fb_unref", vop2_fb_unref_worker); init_completion(&vp->dsp_hold_completion); @@ -6149,13 +6190,11 @@ static int vop2_create_crtc(struct vop2 *vop2) continue; ret = vop2_plane_init(vop2, win, possible_crtcs); - if (ret) { - DRM_DEV_ERROR(vop2->dev, "failed to init overlay\n"); - break; - } + if (ret) + DRM_WARN("failed to init overlay plane %s\n", win->name); } - return ret; + return 0; } static void vop2_destroy_crtc(struct drm_crtc *crtc) diff --git a/include/dt-bindings/display/rockchip_vop.h b/include/dt-bindings/display/rockchip_vop.h new file mode 100644 index 000000000000..3e14128e7ab1 --- /dev/null +++ b/include/dt-bindings/display/rockchip_vop.h @@ -0,0 +1,21 @@ +/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */ +/* + * Copyright (c) 2021 Rockchip Electronics Co., Ltd. + */ + + +#ifndef _DT_BINDINGS_ROCKCHIP_VOP_H +#define _DT_BINDINGS_ROCKCHIP_VOP_H + +#define ROCKCHIP_VOP2_CLUSTER0 0 +#define ROCKCHIP_VOP2_CLUSTER1 1 +#define ROCKCHIP_VOP2_ESMART0 2 +#define ROCKCHIP_VOP2_ESMART1 3 +#define ROCKCHIP_VOP2_SMART0 4 +#define ROCKCHIP_VOP2_SMART1 5 +#define ROCKCHIP_VOP2_CLUSTER2 6 +#define ROCKCHIP_VOP2_CLUSTER3 7 +#define ROCKCHIP_VOP2_ESMART2 8 +#define ROCKCHIP_VOP2_ESMART3 9 + +#endif