From: james qian wang (Arm Technology China) Date: Fri, 17 May 2019 10:05:13 +0000 (+0100) Subject: drm/komeda: Add format support for Y0L2, P010, YUV420_8/10BIT X-Git-Url: http://git.lede-project.org./?a=commitdiff_plain;h=04e84545b9805f6a141fce0b1f05fb74551094fc;p=openwrt%2Fstaging%2Fblogic.git drm/komeda: Add format support for Y0L2, P010, YUV420_8/10BIT - Y0L2 and P010 are block (tiled) format, Update the kemeda logic to compatible with such block format. - Since DRM introduced a general block information to drm_format_info, the format_caps->tiled_size no long needed, delete it. - Build some fb utils functions for code sharing. Signed-off-by: James Qian Wang (Arm Technology China) Signed-off-by: Liviu Dudau --- diff --git a/drivers/gpu/drm/arm/display/include/malidp_io.h b/drivers/gpu/drm/arm/display/include/malidp_io.h index 4fb3caf864ce..9440dff94212 100644 --- a/drivers/gpu/drm/arm/display/include/malidp_io.h +++ b/drivers/gpu/drm/arm/display/include/malidp_io.h @@ -21,6 +21,13 @@ malidp_write32(u32 __iomem *base, u32 offset, u32 v) writel(v, (base + (offset >> 2))); } +static inline void +malidp_write64(u32 __iomem *base, u32 offset, u64 v) +{ + writel(lower_32_bits(v), (base + (offset >> 2))); + writel(upper_32_bits(v), (base + (offset >> 2) + 1)); +} + static inline void malidp_write32_mask(u32 __iomem *base, u32 offset, u32 m, u32 v) { diff --git a/drivers/gpu/drm/arm/display/komeda/d71/d71_component.c b/drivers/gpu/drm/arm/display/komeda/d71/d71_component.c index 2a800112be9a..07b4e80378fa 100644 --- a/drivers/gpu/drm/arm/display/komeda/d71/d71_component.c +++ b/drivers/gpu/drm/arm/display/komeda/d71/d71_component.c @@ -163,6 +163,30 @@ static inline u32 to_d71_input_id(struct komeda_component_output *output) return comp ? (comp->hw_id + output->output_port) : 0; } +static void d71_layer_update_fb(struct komeda_component *c, + struct komeda_fb *kfb, + dma_addr_t *addr) +{ + struct drm_framebuffer *fb = &kfb->base; + const struct drm_format_info *info = fb->format; + u32 __iomem *reg = c->reg; + int block_h; + + if (info->num_planes > 2) + malidp_write64(reg, BLK_P2_PTR_LOW, addr[2]); + + if (info->num_planes > 1) { + block_h = drm_format_info_block_height(info, 1); + malidp_write32(reg, BLK_P1_STRIDE, fb->pitches[1] * block_h); + malidp_write64(reg, BLK_P1_PTR_LOW, addr[1]); + } + + block_h = drm_format_info_block_height(info, 0); + malidp_write32(reg, BLK_P0_STRIDE, fb->pitches[0] * block_h); + malidp_write64(reg, BLK_P0_PTR_LOW, addr[0]); + malidp_write32(reg, LAYER_FMT, kfb->format_caps->hw_id); +} + static void d71_layer_disable(struct komeda_component *c) { malidp_write32_mask(c->reg, BLK_CONTROL, L_EN, 0); @@ -178,22 +202,8 @@ static void d71_layer_update(struct komeda_component *c, u32 __iomem *reg = c->reg; u32 ctrl_mask = L_EN | L_ROT(L_ROT_R270) | L_HFLIP | L_VFLIP | L_TBU_EN; u32 ctrl = L_EN | to_rot_ctrl(st->rot); - int i; - for (i = 0; i < fb->format->num_planes; i++) { - malidp_write32(reg, - BLK_P0_PTR_LOW + i * LAYER_PER_PLANE_REGS * 4, - lower_32_bits(st->addr[i])); - malidp_write32(reg, - BLK_P0_PTR_HIGH + i * LAYER_PER_PLANE_REGS * 4, - upper_32_bits(st->addr[i])); - if (i >= 2) - break; - - malidp_write32(reg, - BLK_P0_STRIDE + i * LAYER_PER_PLANE_REGS * 4, - fb->pitches[i] & 0xFFFF); - } + d71_layer_update_fb(c, kfb, st->addr); malidp_write32(reg, AD_CONTROL, to_ad_ctrl(fb->modifier)); if (fb->modifier) { @@ -247,7 +257,6 @@ static void d71_layer_update(struct komeda_component *c, plane_st->color_range)); } - malidp_write32(reg, LAYER_FMT, kfb->format_caps->hw_id); malidp_write32(reg, BLK_IN_SIZE, HV_SIZE(st->hsize, st->vsize)); if (kfb->is_va) @@ -369,26 +378,15 @@ static void d71_wb_layer_update(struct komeda_component *c, { struct komeda_layer_state *st = to_layer_st(state); struct drm_connector_state *conn_st = state->wb_conn->state; - struct drm_framebuffer *fb = conn_st->writeback_job->fb; - struct komeda_fb *kfb = to_kfb(fb); - u32 __iomem *reg = c->reg; + struct komeda_fb *kfb = to_kfb(conn_st->writeback_job->fb); u32 ctrl = L_EN | LW_OFM, mask = L_EN | LW_OFM | LW_TBU_EN; - int i; + u32 __iomem *reg = c->reg; - for (i = 0; i < fb->format->num_planes; i++) { - malidp_write32(reg + i * LAYER_PER_PLANE_REGS, BLK_P0_PTR_LOW, - lower_32_bits(st->addr[i])); - malidp_write32(reg + i * LAYER_PER_PLANE_REGS, BLK_P0_PTR_HIGH, - upper_32_bits(st->addr[i])); - - malidp_write32(reg + i * LAYER_PER_PLANE_REGS, BLK_P0_STRIDE, - fb->pitches[i] & 0xFFFF); - } + d71_layer_update_fb(c, kfb, st->addr); if (kfb->is_va) ctrl |= LW_TBU_EN; - malidp_write32(reg, LAYER_FMT, kfb->format_caps->hw_id); malidp_write32(reg, BLK_IN_SIZE, HV_SIZE(st->hsize, st->vsize)); malidp_write32(reg, BLK_INPUT_ID0, to_d71_input_id(&state->inputs[0])); malidp_write32_mask(reg, BLK_CONTROL, mask, ctrl); diff --git a/drivers/gpu/drm/arm/display/komeda/d71/d71_dev.c b/drivers/gpu/drm/arm/display/komeda/d71/d71_dev.c index 2f06207b58a3..d567ab7ed314 100644 --- a/drivers/gpu/drm/arm/display/komeda/d71/d71_dev.c +++ b/drivers/gpu/drm/arm/display/komeda/d71/d71_dev.c @@ -447,51 +447,47 @@ err_cleanup: #define AFB_TH_SC_YTR_BS AFBC(_TILED | _SC | _SPARSE | _YTR | _SPLIT) static struct komeda_format_caps d71_format_caps_table[] = { - /* HW_ID | fourcc | tile_sz | layer_types | rots | afbc_layouts | afbc_features */ + /* HW_ID | fourcc | layer_types | rots | afbc_layouts | afbc_features */ /* ABGR_2101010*/ - {__HW_ID(0, 0), DRM_FORMAT_ARGB2101010, 1, RICH_SIMPLE_WB, Flip_H_V, 0, 0}, - {__HW_ID(0, 1), DRM_FORMAT_ABGR2101010, 1, RICH_SIMPLE_WB, Flip_H_V, 0, 0}, - {__HW_ID(0, 1), DRM_FORMAT_ABGR2101010, 1, RICH_SIMPLE, Rot_ALL_H_V, LYT_NM_WB, AFB_TH_SC_YTR_BS}, /* afbc */ - {__HW_ID(0, 2), DRM_FORMAT_RGBA1010102, 1, RICH_SIMPLE_WB, Flip_H_V, 0, 0}, - {__HW_ID(0, 3), DRM_FORMAT_BGRA1010102, 1, RICH_SIMPLE_WB, Flip_H_V, 0, 0}, + {__HW_ID(0, 0), DRM_FORMAT_ARGB2101010, RICH_SIMPLE_WB, Flip_H_V, 0, 0}, + {__HW_ID(0, 1), DRM_FORMAT_ABGR2101010, RICH_SIMPLE_WB, Flip_H_V, 0, 0}, + {__HW_ID(0, 1), DRM_FORMAT_ABGR2101010, RICH_SIMPLE, Rot_ALL_H_V, LYT_NM_WB, AFB_TH_SC_YTR_BS}, /* afbc */ + {__HW_ID(0, 2), DRM_FORMAT_RGBA1010102, RICH_SIMPLE_WB, Flip_H_V, 0, 0}, + {__HW_ID(0, 3), DRM_FORMAT_BGRA1010102, RICH_SIMPLE_WB, Flip_H_V, 0, 0}, /* ABGR_8888*/ - {__HW_ID(1, 0), DRM_FORMAT_ARGB8888, 1, RICH_SIMPLE_WB, Flip_H_V, 0, 0}, - {__HW_ID(1, 1), DRM_FORMAT_ABGR8888, 1, RICH_SIMPLE_WB, Flip_H_V, 0, 0}, - {__HW_ID(1, 1), DRM_FORMAT_ABGR8888, 1, RICH_SIMPLE, Rot_ALL_H_V, LYT_NM_WB, AFB_TH_SC_YTR_BS}, /* afbc */ - {__HW_ID(1, 2), DRM_FORMAT_RGBA8888, 1, RICH_SIMPLE_WB, Flip_H_V, 0, 0}, - {__HW_ID(1, 3), DRM_FORMAT_BGRA8888, 1, RICH_SIMPLE_WB, Flip_H_V, 0, 0}, + {__HW_ID(1, 0), DRM_FORMAT_ARGB8888, RICH_SIMPLE_WB, Flip_H_V, 0, 0}, + {__HW_ID(1, 1), DRM_FORMAT_ABGR8888, RICH_SIMPLE_WB, Flip_H_V, 0, 0}, + {__HW_ID(1, 1), DRM_FORMAT_ABGR8888, RICH_SIMPLE, Rot_ALL_H_V, LYT_NM_WB, AFB_TH_SC_YTR_BS}, /* afbc */ + {__HW_ID(1, 2), DRM_FORMAT_RGBA8888, RICH_SIMPLE_WB, Flip_H_V, 0, 0}, + {__HW_ID(1, 3), DRM_FORMAT_BGRA8888, RICH_SIMPLE_WB, Flip_H_V, 0, 0}, /* XBGB_8888 */ - {__HW_ID(2, 0), DRM_FORMAT_XRGB8888, 1, RICH_SIMPLE_WB, Flip_H_V, 0, 0}, - {__HW_ID(2, 1), DRM_FORMAT_XBGR8888, 1, RICH_SIMPLE_WB, Flip_H_V, 0, 0}, - {__HW_ID(2, 2), DRM_FORMAT_RGBX8888, 1, RICH_SIMPLE_WB, Flip_H_V, 0, 0}, - {__HW_ID(2, 3), DRM_FORMAT_BGRX8888, 1, RICH_SIMPLE_WB, Flip_H_V, 0, 0}, + {__HW_ID(2, 0), DRM_FORMAT_XRGB8888, RICH_SIMPLE_WB, Flip_H_V, 0, 0}, + {__HW_ID(2, 1), DRM_FORMAT_XBGR8888, RICH_SIMPLE_WB, Flip_H_V, 0, 0}, + {__HW_ID(2, 2), DRM_FORMAT_RGBX8888, RICH_SIMPLE_WB, Flip_H_V, 0, 0}, + {__HW_ID(2, 3), DRM_FORMAT_BGRX8888, RICH_SIMPLE_WB, Flip_H_V, 0, 0}, /* BGR_888 */ /* none-afbc RGB888 doesn't support rotation and flip */ - {__HW_ID(3, 0), DRM_FORMAT_RGB888, 1, RICH_SIMPLE_WB, Rot_0, 0, 0}, - {__HW_ID(3, 1), DRM_FORMAT_BGR888, 1, RICH_SIMPLE_WB, Rot_0, 0, 0}, - {__HW_ID(3, 1), DRM_FORMAT_BGR888, 1, RICH_SIMPLE, Rot_ALL_H_V, LYT_NM_WB, AFB_TH_SC_YTR_BS}, /* afbc */ + {__HW_ID(3, 0), DRM_FORMAT_RGB888, RICH_SIMPLE_WB, Rot_0, 0, 0}, + {__HW_ID(3, 1), DRM_FORMAT_BGR888, RICH_SIMPLE_WB, Rot_0, 0, 0}, + {__HW_ID(3, 1), DRM_FORMAT_BGR888, RICH_SIMPLE, Rot_ALL_H_V, LYT_NM_WB, AFB_TH_SC_YTR_BS}, /* afbc */ /* BGR 16bpp */ - {__HW_ID(4, 0), DRM_FORMAT_RGBA5551, 1, RICH_SIMPLE, Flip_H_V, 0, 0}, - {__HW_ID(4, 1), DRM_FORMAT_ABGR1555, 1, RICH_SIMPLE, Flip_H_V, 0, 0}, - {__HW_ID(4, 1), DRM_FORMAT_ABGR1555, 1, RICH_SIMPLE, Rot_ALL_H_V, LYT_NM_WB, AFB_TH_SC_YTR}, /* afbc */ - {__HW_ID(4, 2), DRM_FORMAT_RGB565, 1, RICH_SIMPLE, Flip_H_V, 0, 0}, - {__HW_ID(4, 3), DRM_FORMAT_BGR565, 1, RICH_SIMPLE, Flip_H_V, 0, 0}, - {__HW_ID(4, 3), DRM_FORMAT_BGR565, 1, RICH_SIMPLE, Rot_ALL_H_V, LYT_NM_WB, AFB_TH_SC_YTR}, /* afbc */ - {__HW_ID(4, 4), DRM_FORMAT_R8, 1, SIMPLE, Rot_0, 0, 0}, + {__HW_ID(4, 0), DRM_FORMAT_RGBA5551, RICH_SIMPLE, Flip_H_V, 0, 0}, + {__HW_ID(4, 1), DRM_FORMAT_ABGR1555, RICH_SIMPLE, Flip_H_V, 0, 0}, + {__HW_ID(4, 1), DRM_FORMAT_ABGR1555, RICH_SIMPLE, Rot_ALL_H_V, LYT_NM_WB, AFB_TH_SC_YTR}, /* afbc */ + {__HW_ID(4, 2), DRM_FORMAT_RGB565, RICH_SIMPLE, Flip_H_V, 0, 0}, + {__HW_ID(4, 3), DRM_FORMAT_BGR565, RICH_SIMPLE, Flip_H_V, 0, 0}, + {__HW_ID(4, 3), DRM_FORMAT_BGR565, RICH_SIMPLE, Rot_ALL_H_V, LYT_NM_WB, AFB_TH_SC_YTR}, /* afbc */ + {__HW_ID(4, 4), DRM_FORMAT_R8, SIMPLE, Rot_0, 0, 0}, /* YUV 444/422/420 8bit */ - {__HW_ID(5, 0), 0 /*XYUV8888*/, 1, 0, 0, 0, 0}, - /* XYUV unsupported*/ - {__HW_ID(5, 1), DRM_FORMAT_YUYV, 1, RICH, Rot_ALL_H_V, LYT_NM, AFB_TH}, /* afbc */ - {__HW_ID(5, 2), DRM_FORMAT_YUYV, 1, RICH, Flip_H_V, 0, 0}, - {__HW_ID(5, 3), DRM_FORMAT_UYVY, 1, RICH, Flip_H_V, 0, 0}, - {__HW_ID(5, 4), 0, /*X0L0 */ 2, 0, 0, 0}, /* Y0L0 unsupported */ - {__HW_ID(5, 6), DRM_FORMAT_NV12, 1, RICH, Flip_H_V, 0, 0}, - {__HW_ID(5, 6), 0/*DRM_FORMAT_YUV420_8BIT*/, 1, RICH, Rot_ALL_H_V, LYT_NM, AFB_TH}, /* afbc */ - {__HW_ID(5, 7), DRM_FORMAT_YUV420, 1, RICH, Flip_H_V, 0, 0}, + {__HW_ID(5, 1), DRM_FORMAT_YUYV, RICH, Rot_ALL_H_V, LYT_NM, AFB_TH}, /* afbc */ + {__HW_ID(5, 2), DRM_FORMAT_YUYV, RICH, Flip_H_V, 0, 0}, + {__HW_ID(5, 3), DRM_FORMAT_UYVY, RICH, Flip_H_V, 0, 0}, + {__HW_ID(5, 6), DRM_FORMAT_NV12, RICH, Flip_H_V, 0, 0}, + {__HW_ID(5, 6), DRM_FORMAT_YUV420_8BIT, RICH, Rot_ALL_H_V, LYT_NM, AFB_TH}, /* afbc */ + {__HW_ID(5, 7), DRM_FORMAT_YUV420, RICH, Flip_H_V, 0, 0}, /* YUV 10bit*/ - {__HW_ID(6, 0), 0,/*XVYU2101010*/ 1, 0, 0, 0, 0},/* VYV30 unsupported */ - {__HW_ID(6, 6), 0/*DRM_FORMAT_X0L2*/, 2, RICH, Flip_H_V, 0, 0}, - {__HW_ID(6, 7), 0/*DRM_FORMAT_P010*/, 1, RICH, Flip_H_V, 0, 0}, - {__HW_ID(6, 7), 0/*DRM_FORMAT_YUV420_10BIT*/, 1, RICH, Rot_ALL_H_V, LYT_NM, AFB_TH}, + {__HW_ID(6, 6), DRM_FORMAT_X0L2, RICH, Flip_H_V, 0, 0}, + {__HW_ID(6, 7), DRM_FORMAT_P010, RICH, Flip_H_V, 0, 0}, + {__HW_ID(6, 7), DRM_FORMAT_YUV420_10BIT, RICH, Rot_ALL_H_V, LYT_NM, AFB_TH}, }; static bool d71_format_mod_supported(const struct komeda_format_caps *caps, diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_format_caps.h b/drivers/gpu/drm/arm/display/komeda/komeda_format_caps.h index 381e87345e9c..3631910d33b5 100644 --- a/drivers/gpu/drm/arm/display/komeda/komeda_format_caps.h +++ b/drivers/gpu/drm/arm/display/komeda/komeda_format_caps.h @@ -50,7 +50,6 @@ * * @hw_id: hw format id, hw specific value. * @fourcc: drm fourcc format. - * @tile_size: format tiled size, used by ARM format X0L0/X0L2 * @supported_layer_types: indicate which layer supports this format * @supported_rots: allowed rotations for this format * @supported_afbc_layouts: supported afbc layerout @@ -59,7 +58,6 @@ struct komeda_format_caps { u32 hw_id; u32 fourcc; - u32 tile_size; u32 supported_layer_types; u32 supported_rots; u32 supported_afbc_layouts; diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_framebuffer.c b/drivers/gpu/drm/arm/display/komeda/komeda_framebuffer.c index 50858401da05..abc8c0ccc053 100644 --- a/drivers/gpu/drm/arm/display/komeda/komeda_framebuffer.c +++ b/drivers/gpu/drm/arm/display/komeda/komeda_framebuffer.c @@ -112,46 +112,35 @@ komeda_fb_none_afbc_size_check(struct komeda_dev *mdev, struct komeda_fb *kfb, const struct drm_mode_fb_cmd2 *mode_cmd) { struct drm_framebuffer *fb = &kfb->base; + const struct drm_format_info *info = fb->format; struct drm_gem_object *obj; - u32 min_size = 0; - u32 i; + u32 i, min_size, block_h; - for (i = 0; i < fb->format->num_planes; i++) { + if (komeda_fb_check_src_coords(kfb, 0, 0, fb->width, fb->height)) + return -EINVAL; + + for (i = 0; i < info->num_planes; i++) { obj = drm_gem_object_lookup(file, mode_cmd->handles[i]); if (!obj) { DRM_DEBUG_KMS("Failed to lookup GEM object\n"); - fb->obj[i] = NULL; - return -ENOENT; } + fb->obj[i] = obj; - kfb->aligned_w = fb->width / (i ? fb->format->hsub : 1); - kfb->aligned_h = fb->height / (i ? fb->format->vsub : 1); - - if (fb->pitches[i] % mdev->chip.bus_width) { + block_h = drm_format_info_block_height(info, i); + if ((fb->pitches[i] * block_h) % mdev->chip.bus_width) { DRM_DEBUG_KMS("Pitch[%d]: 0x%x doesn't align to 0x%x\n", i, fb->pitches[i], mdev->chip.bus_width); - drm_gem_object_put_unlocked(obj); - fb->obj[i] = NULL; - return -EINVAL; } - min_size = ((kfb->aligned_h / kfb->format_caps->tile_size - 1) - * fb->pitches[i]) - + (kfb->aligned_w * fb->format->cpp[i] - * kfb->format_caps->tile_size) - + fb->offsets[i]; - + min_size = komeda_fb_get_pixel_addr(kfb, 0, fb->height, i) + - to_drm_gem_cma_obj(obj)->paddr; if (obj->size < min_size) { - DRM_DEBUG_KMS("Fail to check none afbc fb size.\n"); - drm_gem_object_put_unlocked(obj); - fb->obj[i] = NULL; - + DRM_DEBUG_KMS("The fb->obj[%d] size: %ld lower than the minimum requirement: %d.\n", + i, obj->size, min_size); return -EINVAL; } - - fb->obj[i] = obj; } if (fb->format->num_planes == 3) { @@ -219,6 +208,8 @@ int komeda_fb_check_src_coords(const struct komeda_fb *kfb, { const struct drm_framebuffer *fb = &kfb->base; const struct drm_format_info *info = fb->format; + u32 block_w = drm_format_info_block_width(fb->format, 0); + u32 block_h = drm_format_info_block_height(fb->format, 0); if ((src_x + src_w > fb->width) || (src_y + src_h > fb->height)) { DRM_DEBUG_ATOMIC("Invalid source coordinate.\n"); @@ -232,6 +223,13 @@ int komeda_fb_check_src_coords(const struct komeda_fb *kfb, return -EINVAL; } + if ((src_x % block_w) || (src_w % block_w) || + (src_y % block_h) || (src_h % block_h)) { + DRM_DEBUG_ATOMIC("x:%d, y:%d, w:%d, h:%d should be multiple of block_w/h for format: %x.\n", + src_x, src_y, src_w, src_h, info->format); + return -EINVAL; + } + return 0; } @@ -240,7 +238,7 @@ komeda_fb_get_pixel_addr(struct komeda_fb *kfb, int x, int y, int plane) { struct drm_framebuffer *fb = &kfb->base; const struct drm_gem_cma_object *obj; - u32 plane_x, plane_y, cpp, pitch, offset; + u32 offset, plane_x, plane_y, block_w, block_sz; if (plane >= fb->format->num_planes) { DRM_DEBUG_KMS("Out of max plane num.\n"); @@ -251,12 +249,13 @@ komeda_fb_get_pixel_addr(struct komeda_fb *kfb, int x, int y, int plane) offset = fb->offsets[plane]; if (!fb->modifier) { + block_w = drm_format_info_block_width(fb->format, plane); + block_sz = fb->format->char_per_block[plane]; plane_x = x / (plane ? fb->format->hsub : 1); plane_y = y / (plane ? fb->format->vsub : 1); - cpp = fb->format->cpp[plane]; - pitch = fb->pitches[plane]; - offset += plane_x * cpp * kfb->format_caps->tile_size + - (plane_y * pitch) / kfb->format_caps->tile_size; + + offset += (plane_x / block_w) * block_sz + + plane_y * fb->pitches[plane]; } return obj->paddr + offset;