drm/rockchip: vop2: add more plane check

1. NV12/NV16/YUYV xoffset must aligned as 2 pixel;
2. NV12/NV15 yoffset must aligned as 2 pixel;
3. NV30 xoffset must aligned as 4 pixel;
4. NV15/NV20 xoffset must aligend as 8 pixel at rk3568/rk3588/rk3528/rk3562,
   others must aligned as 4 pixel;

Signed-off-by: Sandy Huang <hjc@rock-chips.com>
Change-Id: I28d69d1f8189963170ef798c12bfd60fb092ef20
This commit is contained in:
Sandy Huang
2023-04-19 16:16:02 +08:00
committed by Tao Huang
parent f0023c2918
commit 06906b5a73

View File

@@ -1880,6 +1880,18 @@ static inline uint32_t vop2_read_lut(struct vop2 *vop2, uint32_t offset)
return readl(vop2->lut_regs + offset);
}
static bool is_linear_10bit_yuv(uint32_t format)
{
switch (format) {
case DRM_FORMAT_NV15:
case DRM_FORMAT_NV20:
case DRM_FORMAT_NV30:
return true;
default:
return false;
}
}
static enum vop2_data_format vop2_convert_format(uint32_t format)
{
switch (format) {
@@ -4592,6 +4604,107 @@ static int vop2_plane_splice_check(struct drm_plane *plane, struct drm_plane_sta
return ret;
}
/*
* 1. NV12/NV16/YUYV xoffset must aligned as 2 pixel;
* 2. NV12/NV15 yoffset must aligned as 2 pixel;
* 3. NV30 xoffset must aligned as 4 pixel;
* 4. NV15/NV20 xoffset must aligend as 8 pixel at rk3568/rk3588/rk3528/rk3562,
* others must aligned as 4 pixel;
*/
static int vop2_linear_yuv_format_check(struct drm_plane *plane, struct drm_plane_state *state)
{
struct vop2_plane_state *vpstate = to_vop2_plane_state(state);
struct drm_crtc *crtc = state->crtc;
struct vop2_video_port *vp = to_vop2_video_port(crtc);
struct vop2_win *win = to_vop2_win(plane);
struct drm_framebuffer *fb = state->fb;
struct drm_rect *src = &vpstate->src;
u32 val = 0;
if (vpstate->afbc_en || vpstate->tiled_en || !fb->format->is_yuv)
return 0;
switch (fb->format->format) {
case DRM_FORMAT_NV12:
case DRM_FORMAT_NV21:
val = src->x1 >> 16;
if (val % 2) {
src->x1 = ALIGN(val, 2) << 16;
DRM_WARN("VP%d %s src x offset[%d] must aligned as 2 pixel at NV12 fmt, and adjust to: %d\n", vp->id, win->name, val, src->x1 >> 16);
}
val = src->y1 >> 16;
if (val % 2) {
src->y1 = ALIGN(val, 2) << 16;
DRM_WARN("VP%d %s src y offset[%d] must aligned as 2 pixel at NV12 fmt, and adjust to: %d\n", vp->id, win->name, val, src->y1 >> 16);
}
break;
case DRM_FORMAT_NV15:
val = src->y1 >> 16;
if (val % 2) {
src->y1 = ALIGN(val, 2) << 16;
DRM_WARN("VP%d %s src y offset[%d] must aligned as 2 pixel at NV15 fmt, and adjust to: %d\n", vp->id, win->name, val, src->y1 >> 16);
}
if (vp->vop2->version == VOP_VERSION_RK3568 ||
vp->vop2->version == VOP_VERSION_RK3588 ||
vp->vop2->version == VOP_VERSION_RK3528 ||
vp->vop2->version == VOP_VERSION_RK3562) {
val = src->x1 >> 16;
if (val % 8) {
src->x1 = ALIGN(val, 8) << 16;
DRM_WARN("VP%d %s src x offset[%d] must aligned as 8 pixel at NV15 fmt, and adjust to: %d\n", vp->id, win->name, val, src->x1 >> 16);
}
} else {
val = src->x1 >> 16;
if (val % 4) {
src->x1 = ALIGN(val, 4) << 16;
DRM_WARN("VP%d %s src x offset[%d] must aligned as 4 pixel at NV15 fmt, and adjust to: %d\n", vp->id, win->name, val, src->x1 >> 16);
}
}
break;
case DRM_FORMAT_NV16:
case DRM_FORMAT_NV61:
case DRM_FORMAT_YUYV:
case DRM_FORMAT_YVYU:
case DRM_FORMAT_VYUY:
case DRM_FORMAT_UYVY:
val = src->x1 >> 16;
if (val % 2) {
src->x1 = ALIGN(val, 2) << 16;
DRM_WARN("VP%d %s src x offset[%d] must aligned as 2 pixel at YUYV fmt, and adjust to: %d\n", vp->id, win->name, val, src->x1 >> 16);
}
break;
case DRM_FORMAT_NV20:
if (vp->vop2->version == VOP_VERSION_RK3568 ||
vp->vop2->version == VOP_VERSION_RK3588 ||
vp->vop2->version == VOP_VERSION_RK3528 ||
vp->vop2->version == VOP_VERSION_RK3562) {
val = src->x1 >> 16;
if (val % 8) {
src->x1 = ALIGN(val, 8) << 16;
DRM_WARN("VP%d %s src x offset[%d] must aligned as 8 pixel at NV20 fmt, and adjust to: %d\n", vp->id, win->name, val, src->x1 >> 16);
}
} else {
val = src->x1 >> 16;
if (val % 4) {
src->x1 = ALIGN(val, 4) << 16;
DRM_WARN("VP%d %s src x offset[%d] must aligned as 4 pixel at NV20 fmt, and adjust to: %d\n", vp->id, win->name, val, src->x1 >> 16);
}
}
break;
case DRM_FORMAT_NV30:
val = src->x1 >> 16;
if (val % 4) {
src->x1 = ALIGN(val, 4) << 16;
DRM_WARN("VP%d %s src x offset[%d] must aligned as 4 pixel at NV30 fmt, and adjust to: %d\n", vp->id, win->name, val, src->x1 >> 16);
}
break;
default:
return 0;
}
return 0;
}
static int vop2_plane_atomic_check(struct drm_plane *plane, struct drm_plane_state *state)
{
struct vop2_plane_state *vpstate = to_vop2_plane_state(state);
@@ -4756,14 +4869,8 @@ static int vop2_plane_atomic_check(struct drm_plane *plane, struct drm_plane_sta
return ret;
}
/*
* Src.x1 can be odd when do clip, but yuv plane start point
* need align with 2 pixel.
*/
if (fb->format->is_yuv && ((state->src.x1 >> 16) % 2)) {
DRM_ERROR("Invalid Source: Yuv format not support odd xpos\n");
if (vop2_linear_yuv_format_check(plane, state))
return -EINVAL;
}
if (fb->format->char_per_block[0] == 0)
offset = ALIGN_DOWN(src->x1 >> 16, tile_size) * fb->format->cpp[0] * tile_size;
@@ -5079,22 +5186,35 @@ static void vop2_win_atomic_update(struct vop2_win *win, struct drm_rect *src, s
if (vop2->version == VOP_VERSION_RK3568) {
/*
* This is workaround solution for IC design:
* esmart can't support scale down when actual_w % 16 == 1.
* esmart can't support scale down when actual_w % 16 == 1;
* esmart can't support scale down when dsp_w % 2 == 1;
* esmart actual_w should align as 4 pixel when is linear 10 bit yuv format;
*
* cluster actual_w should align as 4 pixel when enable afbc;
*/
if (!(win->feature & WIN_FEATURE_AFBDC)) {
if (!vop2_cluster_window(win)) {
if (actual_w > dsp_w && (actual_w & 0xf) == 1) {
DRM_WARN("vp%d %s act_w[%d] MODE 16 == 1\n", vp->id, win->name, actual_w);
DRM_WARN("vp%d %s act_w[%d] MODE 16 == 1 at scale down mode\n", vp->id, win->name, actual_w);
actual_w -= 1;
}
if (actual_w > dsp_w && (dsp_w & 0x1) == 1) {
DRM_WARN("vp%d %s dsp_w[%d] MODE 2 == 1 at scale down mode\n", vp->id, win->name, dsp_w);
dsp_w -= 1;
}
}
if (vpstate->afbc_en && actual_w % 4) {
DRM_ERROR("vp%d %s actual_w[%d] should align as 4 pixel when enable afbc\n",
vp->id, win->name, actual_w);
if (vop2_cluster_window(win) && actual_w % 4) {
DRM_WARN("vp%d %s actual_w[%d] should align as 4 pixel when enable afbc\n",
vp->id, win->name, actual_w);
actual_w = ALIGN_DOWN(actual_w, 4);
}
}
if (is_linear_10bit_yuv(fb->format->format) && actual_w & 0x3) {
DRM_WARN("vp%d %s actual_w[%d] should align as 4 pixel when is linear 10 bit yuv format\n", vp->id, win->name, actual_w);
actual_w = ALIGN_DOWN(actual_w, 4);
}
act_info = (actual_h - 1) << 16 | ((actual_w - 1) & 0xffff);
dsp_info = (dsp_h - 1) << 16 | ((dsp_w - 1) & 0xffff);
stride = DIV_ROUND_UP(fb->pitches[0], 4);