drm/rockchip: Add support for afbc
This patch adds support for afbc handling. afbc is a compressed format which reduces the necessary memory bandwidth. Co-developed-by: Mark Yao <mark.yao@rock-chips.com> Signed-off-by: Mark Yao <mark.yao@rock-chips.com> Signed-off-by: Andrzej Pietrasiewicz <andrzej.p@collabora.com> Reviewed-by: Sandy Huang <hjc@rock-chips.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200311145541.29186-7-andrzej.p@collabora.com
This commit is contained in:
		
							parent
							
								
									7f60c4b9d9
								
							
						
					
					
						commit
						7707f7227f
					
				| @ -30,6 +30,7 @@ struct rockchip_crtc_state { | ||||
| 	int output_mode; | ||||
| 	int output_bpc; | ||||
| 	int output_flags; | ||||
| 	bool enable_afbc; | ||||
| }; | ||||
| #define to_rockchip_crtc_state(s) \ | ||||
| 		container_of(s, struct rockchip_crtc_state, base) | ||||
|  | ||||
| @ -57,8 +57,49 @@ static const struct drm_mode_config_helper_funcs rockchip_mode_config_helpers = | ||||
| 	.atomic_commit_tail = drm_atomic_helper_commit_tail_rpm, | ||||
| }; | ||||
| 
 | ||||
| static struct drm_framebuffer * | ||||
| rockchip_fb_create(struct drm_device *dev, struct drm_file *file, | ||||
| 		   const struct drm_mode_fb_cmd2 *mode_cmd) | ||||
| { | ||||
| 	struct drm_afbc_framebuffer *afbc_fb; | ||||
| 	const struct drm_format_info *info; | ||||
| 	int ret; | ||||
| 
 | ||||
| 	info = drm_get_format_info(dev, mode_cmd); | ||||
| 	if (!info) | ||||
| 		return ERR_PTR(-ENOMEM); | ||||
| 
 | ||||
| 	afbc_fb = kzalloc(sizeof(*afbc_fb), GFP_KERNEL); | ||||
| 	if (!afbc_fb) | ||||
| 		return ERR_PTR(-ENOMEM); | ||||
| 
 | ||||
| 	ret = drm_gem_fb_init_with_funcs(dev, &afbc_fb->base, file, mode_cmd, | ||||
| 					 &rockchip_drm_fb_funcs); | ||||
| 	if (ret) { | ||||
| 		kfree(afbc_fb); | ||||
| 		return ERR_PTR(ret); | ||||
| 	} | ||||
| 
 | ||||
| 	if (drm_is_afbc(mode_cmd->modifier[0])) { | ||||
| 		int ret, i; | ||||
| 
 | ||||
| 		ret = drm_gem_fb_afbc_init(dev, mode_cmd, afbc_fb); | ||||
| 		if (ret) { | ||||
| 			struct drm_gem_object **obj = afbc_fb->base.obj; | ||||
| 
 | ||||
| 			for (i = 0; i < info->num_planes; ++i) | ||||
| 				drm_gem_object_put_unlocked(obj[i]); | ||||
| 
 | ||||
| 			kfree(afbc_fb); | ||||
| 			return ERR_PTR(ret); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	return &afbc_fb->base; | ||||
| } | ||||
| 
 | ||||
| static const struct drm_mode_config_funcs rockchip_drm_mode_config_funcs = { | ||||
| 	.fb_create = drm_gem_fb_create_with_dirty, | ||||
| 	.fb_create = rockchip_fb_create, | ||||
| 	.output_poll_changed = drm_fb_helper_output_poll_changed, | ||||
| 	.atomic_check = drm_atomic_helper_check, | ||||
| 	.atomic_commit = drm_atomic_helper_commit, | ||||
|  | ||||
| @ -91,9 +91,22 @@ | ||||
| #define VOP_WIN_TO_INDEX(vop_win) \ | ||||
| 	((vop_win) - (vop_win)->vop->win) | ||||
| 
 | ||||
| #define VOP_AFBC_SET(vop, name, v) \ | ||||
| 	do { \ | ||||
| 		if ((vop)->data->afbc) \ | ||||
| 			vop_reg_set((vop), &(vop)->data->afbc->name, \ | ||||
| 				    0, ~0, v, #name); \ | ||||
| 	} while (0) | ||||
| 
 | ||||
| #define to_vop(x) container_of(x, struct vop, crtc) | ||||
| #define to_vop_win(x) container_of(x, struct vop_win, base) | ||||
| 
 | ||||
| #define AFBC_FMT_RGB565		0x0 | ||||
| #define AFBC_FMT_U8U8U8U8	0x5 | ||||
| #define AFBC_FMT_U8U8U8		0x4 | ||||
| 
 | ||||
| #define AFBC_TILE_16x16		BIT(4) | ||||
| 
 | ||||
| /*
 | ||||
|  * The coefficients of the following matrix are all fixed points. | ||||
|  * The format is S2.10 for the 3x3 part of the matrix, and S9.12 for the offsets. | ||||
| @ -274,6 +287,29 @@ static enum vop_data_format vop_convert_format(uint32_t format) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| static int vop_convert_afbc_format(uint32_t format) | ||||
| { | ||||
| 	switch (format) { | ||||
| 	case DRM_FORMAT_XRGB8888: | ||||
| 	case DRM_FORMAT_ARGB8888: | ||||
| 	case DRM_FORMAT_XBGR8888: | ||||
| 	case DRM_FORMAT_ABGR8888: | ||||
| 		return AFBC_FMT_U8U8U8U8; | ||||
| 	case DRM_FORMAT_RGB888: | ||||
| 	case DRM_FORMAT_BGR888: | ||||
| 		return AFBC_FMT_U8U8U8; | ||||
| 	case DRM_FORMAT_RGB565: | ||||
| 	case DRM_FORMAT_BGR565: | ||||
| 		return AFBC_FMT_RGB565; | ||||
| 	/* either of the below should not be reachable */ | ||||
| 	default: | ||||
| 		DRM_WARN_ONCE("unsupported AFBC format[%08x]\n", format); | ||||
| 		return -EINVAL; | ||||
| 	} | ||||
| 
 | ||||
| 	return -EINVAL; | ||||
| } | ||||
| 
 | ||||
| static uint16_t scl_vop_cal_scale(enum scale_mode mode, uint32_t src, | ||||
| 				  uint32_t dst, bool is_horizontal, | ||||
| 				  int vsu_mode, int *vskiplines) | ||||
| @ -598,6 +634,17 @@ static int vop_enable(struct drm_crtc *crtc, struct drm_crtc_state *old_state) | ||||
| 			vop_win_disable(vop, vop_win); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	if (vop->data->afbc) { | ||||
| 		struct rockchip_crtc_state *s; | ||||
| 		/*
 | ||||
| 		 * Disable AFBC and forget there was a vop window with AFBC | ||||
| 		 */ | ||||
| 		VOP_AFBC_SET(vop, enable, 0); | ||||
| 		s = to_rockchip_crtc_state(crtc->state); | ||||
| 		s->enable_afbc = false; | ||||
| 	} | ||||
| 
 | ||||
| 	spin_unlock(&vop->reg_lock); | ||||
| 
 | ||||
| 	vop_cfg_done(vop); | ||||
| @ -710,6 +757,26 @@ static void vop_plane_destroy(struct drm_plane *plane) | ||||
| 	drm_plane_cleanup(plane); | ||||
| } | ||||
| 
 | ||||
| static inline bool rockchip_afbc(u64 modifier) | ||||
| { | ||||
| 	return modifier == ROCKCHIP_AFBC_MOD; | ||||
| } | ||||
| 
 | ||||
| static bool rockchip_mod_supported(struct drm_plane *plane, | ||||
| 				   u32 format, u64 modifier) | ||||
| { | ||||
| 	if (modifier == DRM_FORMAT_MOD_LINEAR) | ||||
| 		return true; | ||||
| 
 | ||||
| 	if (!rockchip_afbc(modifier)) { | ||||
| 		DRM_DEBUG_KMS("Unsupported format modifer 0x%llx\n", modifier); | ||||
| 
 | ||||
| 		return false; | ||||
| 	} | ||||
| 
 | ||||
| 	return vop_convert_afbc_format(format) >= 0; | ||||
| } | ||||
| 
 | ||||
| static int vop_plane_atomic_check(struct drm_plane *plane, | ||||
| 			   struct drm_plane_state *state) | ||||
| { | ||||
| @ -758,6 +825,30 @@ static int vop_plane_atomic_check(struct drm_plane *plane, | ||||
| 		return -EINVAL; | ||||
| 	} | ||||
| 
 | ||||
| 	if (rockchip_afbc(fb->modifier)) { | ||||
| 		struct vop *vop = to_vop(crtc); | ||||
| 
 | ||||
| 		if (!vop->data->afbc) { | ||||
| 			DRM_ERROR("vop does not support AFBC\n"); | ||||
| 			return -EINVAL; | ||||
| 		} | ||||
| 
 | ||||
| 		ret = vop_convert_afbc_format(fb->format->format); | ||||
| 		if (ret < 0) | ||||
| 			return ret; | ||||
| 
 | ||||
| 		if (state->src.x1 || state->src.y1) { | ||||
| 			DRM_ERROR("AFBC does not support offset display, xpos=%d, ypos=%d, offset=%d\n", state->src.x1, state->src.y1, fb->offsets[0]); | ||||
| 			return -EINVAL; | ||||
| 		} | ||||
| 
 | ||||
| 		if (state->rotation && state->rotation != DRM_MODE_ROTATE_0) { | ||||
| 			DRM_ERROR("No rotation support in AFBC, rotation=%d\n", | ||||
| 				  state->rotation); | ||||
| 			return -EINVAL; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| @ -846,6 +937,16 @@ static void vop_plane_atomic_update(struct drm_plane *plane, | ||||
| 
 | ||||
| 	spin_lock(&vop->reg_lock); | ||||
| 
 | ||||
| 	if (rockchip_afbc(fb->modifier)) { | ||||
| 		int afbc_format = vop_convert_afbc_format(fb->format->format); | ||||
| 
 | ||||
| 		VOP_AFBC_SET(vop, format, afbc_format | AFBC_TILE_16x16); | ||||
| 		VOP_AFBC_SET(vop, hreg_block_split, 0); | ||||
| 		VOP_AFBC_SET(vop, win_sel, VOP_WIN_TO_INDEX(vop_win)); | ||||
| 		VOP_AFBC_SET(vop, hdr_ptr, dma_addr); | ||||
| 		VOP_AFBC_SET(vop, pic_size, act_info); | ||||
| 	} | ||||
| 
 | ||||
| 	VOP_WIN_SET(vop, win, format, format); | ||||
| 	VOP_WIN_SET(vop, win, yrgb_vir, DIV_ROUND_UP(fb->pitches[0], 4)); | ||||
| 	VOP_WIN_SET(vop, win, yrgb_mst, dma_addr); | ||||
| @ -1001,6 +1102,7 @@ static const struct drm_plane_funcs vop_plane_funcs = { | ||||
| 	.reset = drm_atomic_helper_plane_reset, | ||||
| 	.atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state, | ||||
| 	.atomic_destroy_state = drm_atomic_helper_plane_destroy_state, | ||||
| 	.format_mod_supported = rockchip_mod_supported, | ||||
| }; | ||||
| 
 | ||||
| static int vop_crtc_enable_vblank(struct drm_crtc *crtc) | ||||
| @ -1310,6 +1412,10 @@ static int vop_crtc_atomic_check(struct drm_crtc *crtc, | ||||
| 				 struct drm_crtc_state *crtc_state) | ||||
| { | ||||
| 	struct vop *vop = to_vop(crtc); | ||||
| 	struct drm_plane *plane; | ||||
| 	struct drm_plane_state *plane_state; | ||||
| 	struct rockchip_crtc_state *s; | ||||
| 	int afbc_planes = 0; | ||||
| 
 | ||||
| 	if (vop->lut_regs && crtc_state->color_mgmt_changed && | ||||
| 	    crtc_state->gamma_lut) { | ||||
| @ -1323,6 +1429,27 @@ static int vop_crtc_atomic_check(struct drm_crtc *crtc, | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	drm_atomic_crtc_state_for_each_plane(plane, crtc_state) { | ||||
| 		plane_state = | ||||
| 			drm_atomic_get_plane_state(crtc_state->state, plane); | ||||
| 		if (IS_ERR(plane_state)) { | ||||
| 			DRM_DEBUG_KMS("Cannot get plane state for plane %s\n", | ||||
| 				      plane->name); | ||||
| 			return PTR_ERR(plane_state); | ||||
| 		} | ||||
| 
 | ||||
| 		if (drm_is_afbc(plane_state->fb->modifier)) | ||||
| 			++afbc_planes; | ||||
| 	} | ||||
| 
 | ||||
| 	if (afbc_planes > 1) { | ||||
| 		DRM_DEBUG_KMS("Invalid number of AFBC planes; got %d, expected at most 1\n", afbc_planes); | ||||
| 		return -EINVAL; | ||||
| 	} | ||||
| 
 | ||||
| 	s = to_rockchip_crtc_state(crtc_state); | ||||
| 	s->enable_afbc = afbc_planes > 0; | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| @ -1333,6 +1460,7 @@ static void vop_crtc_atomic_flush(struct drm_crtc *crtc, | ||||
| 	struct drm_plane_state *old_plane_state, *new_plane_state; | ||||
| 	struct vop *vop = to_vop(crtc); | ||||
| 	struct drm_plane *plane; | ||||
| 	struct rockchip_crtc_state *s; | ||||
| 	int i; | ||||
| 
 | ||||
| 	if (WARN_ON(!vop->is_enabled)) | ||||
| @ -1340,6 +1468,9 @@ static void vop_crtc_atomic_flush(struct drm_crtc *crtc, | ||||
| 
 | ||||
| 	spin_lock(&vop->reg_lock); | ||||
| 
 | ||||
| 	/* Enable AFBC if there is some AFBC window, disable otherwise. */ | ||||
| 	s = to_rockchip_crtc_state(crtc->state); | ||||
| 	VOP_AFBC_SET(vop, enable, s->enable_afbc); | ||||
| 	vop_cfg_done(vop); | ||||
| 
 | ||||
| 	spin_unlock(&vop->reg_lock); | ||||
| @ -1634,7 +1765,8 @@ static int vop_create_crtc(struct vop *vop) | ||||
| 					       0, &vop_plane_funcs, | ||||
| 					       win_data->phy->data_formats, | ||||
| 					       win_data->phy->nformats, | ||||
| 					       NULL, win_data->type, NULL); | ||||
| 					       win_data->phy->format_modifiers, | ||||
| 					       win_data->type, NULL); | ||||
| 		if (ret) { | ||||
| 			DRM_DEV_ERROR(vop->dev, "failed to init plane %d\n", | ||||
| 				      ret); | ||||
| @ -1678,7 +1810,8 @@ static int vop_create_crtc(struct vop *vop) | ||||
| 					       &vop_plane_funcs, | ||||
| 					       win_data->phy->data_formats, | ||||
| 					       win_data->phy->nformats, | ||||
| 					       NULL, win_data->type, NULL); | ||||
| 					       win_data->phy->format_modifiers, | ||||
| 					       win_data->type, NULL); | ||||
| 		if (ret) { | ||||
| 			DRM_DEV_ERROR(vop->dev, "failed to init overlay %d\n", | ||||
| 				      ret); | ||||
|  | ||||
| @ -17,6 +17,11 @@ | ||||
| 
 | ||||
| #define NUM_YUV2YUV_COEFFICIENTS 12 | ||||
| 
 | ||||
| #define ROCKCHIP_AFBC_MOD \ | ||||
| 	DRM_FORMAT_MOD_ARM_AFBC( \ | ||||
| 		AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 | AFBC_FORMAT_MOD_SPARSE \ | ||||
| 	) | ||||
| 
 | ||||
| enum vop_data_format { | ||||
| 	VOP_FMT_ARGB8888 = 0, | ||||
| 	VOP_FMT_RGB888, | ||||
| @ -34,6 +39,16 @@ struct vop_reg { | ||||
| 	bool relaxed; | ||||
| }; | ||||
| 
 | ||||
| struct vop_afbc { | ||||
| 	struct vop_reg enable; | ||||
| 	struct vop_reg win_sel; | ||||
| 	struct vop_reg format; | ||||
| 	struct vop_reg hreg_block_split; | ||||
| 	struct vop_reg pic_size; | ||||
| 	struct vop_reg hdr_ptr; | ||||
| 	struct vop_reg rstn; | ||||
| }; | ||||
| 
 | ||||
| struct vop_modeset { | ||||
| 	struct vop_reg htotal_pw; | ||||
| 	struct vop_reg hact_st_end; | ||||
| @ -134,6 +149,7 @@ struct vop_win_phy { | ||||
| 	const struct vop_scl_regs *scl; | ||||
| 	const uint32_t *data_formats; | ||||
| 	uint32_t nformats; | ||||
| 	const uint64_t *format_modifiers; | ||||
| 
 | ||||
| 	struct vop_reg enable; | ||||
| 	struct vop_reg gate; | ||||
| @ -173,6 +189,7 @@ struct vop_data { | ||||
| 	const struct vop_misc *misc; | ||||
| 	const struct vop_modeset *modeset; | ||||
| 	const struct vop_output *output; | ||||
| 	const struct vop_afbc *afbc; | ||||
| 	const struct vop_win_yuv2yuv_data *win_yuv2yuv; | ||||
| 	const struct vop_win_data *win; | ||||
| 	unsigned int win_size; | ||||
|  | ||||
| @ -50,6 +50,17 @@ static const uint32_t formats_win_full[] = { | ||||
| 	DRM_FORMAT_NV24, | ||||
| }; | ||||
| 
 | ||||
| static const uint64_t format_modifiers_win_full[] = { | ||||
| 	DRM_FORMAT_MOD_LINEAR, | ||||
| 	DRM_FORMAT_MOD_INVALID, | ||||
| }; | ||||
| 
 | ||||
| static const uint64_t format_modifiers_win_full_afbc[] = { | ||||
| 	ROCKCHIP_AFBC_MOD, | ||||
| 	DRM_FORMAT_MOD_LINEAR, | ||||
| 	DRM_FORMAT_MOD_INVALID, | ||||
| }; | ||||
| 
 | ||||
| static const uint32_t formats_win_lite[] = { | ||||
| 	DRM_FORMAT_XRGB8888, | ||||
| 	DRM_FORMAT_ARGB8888, | ||||
| @ -61,6 +72,11 @@ static const uint32_t formats_win_lite[] = { | ||||
| 	DRM_FORMAT_BGR565, | ||||
| }; | ||||
| 
 | ||||
| static const uint64_t format_modifiers_win_lite[] = { | ||||
| 	DRM_FORMAT_MOD_LINEAR, | ||||
| 	DRM_FORMAT_MOD_INVALID, | ||||
| }; | ||||
| 
 | ||||
| static const struct vop_scl_regs rk3036_win_scl = { | ||||
| 	.scale_yrgb_x = VOP_REG(RK3036_WIN0_SCL_FACTOR_YRGB, 0xffff, 0x0), | ||||
| 	.scale_yrgb_y = VOP_REG(RK3036_WIN0_SCL_FACTOR_YRGB, 0xffff, 16), | ||||
| @ -72,6 +88,7 @@ static const struct vop_win_phy rk3036_win0_data = { | ||||
| 	.scl = &rk3036_win_scl, | ||||
| 	.data_formats = formats_win_full, | ||||
| 	.nformats = ARRAY_SIZE(formats_win_full), | ||||
| 	.format_modifiers = format_modifiers_win_full, | ||||
| 	.enable = VOP_REG(RK3036_SYS_CTRL, 0x1, 0), | ||||
| 	.format = VOP_REG(RK3036_SYS_CTRL, 0x7, 3), | ||||
| 	.rb_swap = VOP_REG(RK3036_SYS_CTRL, 0x1, 15), | ||||
| @ -87,6 +104,7 @@ static const struct vop_win_phy rk3036_win0_data = { | ||||
| static const struct vop_win_phy rk3036_win1_data = { | ||||
| 	.data_formats = formats_win_lite, | ||||
| 	.nformats = ARRAY_SIZE(formats_win_lite), | ||||
| 	.format_modifiers = format_modifiers_win_lite, | ||||
| 	.enable = VOP_REG(RK3036_SYS_CTRL, 0x1, 1), | ||||
| 	.format = VOP_REG(RK3036_SYS_CTRL, 0x7, 6), | ||||
| 	.rb_swap = VOP_REG(RK3036_SYS_CTRL, 0x1, 19), | ||||
| @ -153,6 +171,7 @@ static const struct vop_data rk3036_vop = { | ||||
| static const struct vop_win_phy rk3126_win1_data = { | ||||
| 	.data_formats = formats_win_lite, | ||||
| 	.nformats = ARRAY_SIZE(formats_win_lite), | ||||
| 	.format_modifiers = format_modifiers_win_lite, | ||||
| 	.enable = VOP_REG(RK3036_SYS_CTRL, 0x1, 1), | ||||
| 	.format = VOP_REG(RK3036_SYS_CTRL, 0x7, 6), | ||||
| 	.rb_swap = VOP_REG(RK3036_SYS_CTRL, 0x1, 19), | ||||
| @ -234,6 +253,7 @@ static const struct vop_win_phy px30_win0_data = { | ||||
| 	.scl = &px30_win_scl, | ||||
| 	.data_formats = formats_win_full, | ||||
| 	.nformats = ARRAY_SIZE(formats_win_full), | ||||
| 	.format_modifiers = format_modifiers_win_full, | ||||
| 	.enable = VOP_REG(PX30_WIN0_CTRL0, 0x1, 0), | ||||
| 	.format = VOP_REG(PX30_WIN0_CTRL0, 0x7, 1), | ||||
| 	.rb_swap = VOP_REG(PX30_WIN0_CTRL0, 0x1, 12), | ||||
| @ -249,6 +269,7 @@ static const struct vop_win_phy px30_win0_data = { | ||||
| static const struct vop_win_phy px30_win1_data = { | ||||
| 	.data_formats = formats_win_lite, | ||||
| 	.nformats = ARRAY_SIZE(formats_win_lite), | ||||
| 	.format_modifiers = format_modifiers_win_lite, | ||||
| 	.enable = VOP_REG(PX30_WIN1_CTRL0, 0x1, 0), | ||||
| 	.format = VOP_REG(PX30_WIN1_CTRL0, 0x7, 4), | ||||
| 	.rb_swap = VOP_REG(PX30_WIN1_CTRL0, 0x1, 12), | ||||
| @ -261,6 +282,7 @@ static const struct vop_win_phy px30_win1_data = { | ||||
| static const struct vop_win_phy px30_win2_data = { | ||||
| 	.data_formats = formats_win_lite, | ||||
| 	.nformats = ARRAY_SIZE(formats_win_lite), | ||||
| 	.format_modifiers = format_modifiers_win_lite, | ||||
| 	.gate = VOP_REG(PX30_WIN2_CTRL0, 0x1, 4), | ||||
| 	.enable = VOP_REG(PX30_WIN2_CTRL0, 0x1, 0), | ||||
| 	.format = VOP_REG(PX30_WIN2_CTRL0, 0x3, 5), | ||||
| @ -316,6 +338,7 @@ static const struct vop_win_phy rk3066_win0_data = { | ||||
| 	.scl = &rk3066_win_scl, | ||||
| 	.data_formats = formats_win_full, | ||||
| 	.nformats = ARRAY_SIZE(formats_win_full), | ||||
| 	.format_modifiers = format_modifiers_win_full, | ||||
| 	.enable = VOP_REG(RK3066_SYS_CTRL1, 0x1, 0), | ||||
| 	.format = VOP_REG(RK3066_SYS_CTRL0, 0x7, 4), | ||||
| 	.rb_swap = VOP_REG(RK3066_SYS_CTRL0, 0x1, 19), | ||||
| @ -332,6 +355,7 @@ static const struct vop_win_phy rk3066_win1_data = { | ||||
| 	.scl = &rk3066_win_scl, | ||||
| 	.data_formats = formats_win_full, | ||||
| 	.nformats = ARRAY_SIZE(formats_win_full), | ||||
| 	.format_modifiers = format_modifiers_win_full, | ||||
| 	.enable = VOP_REG(RK3066_SYS_CTRL1, 0x1, 1), | ||||
| 	.format = VOP_REG(RK3066_SYS_CTRL0, 0x7, 7), | ||||
| 	.rb_swap = VOP_REG(RK3066_SYS_CTRL0, 0x1, 23), | ||||
| @ -347,6 +371,7 @@ static const struct vop_win_phy rk3066_win1_data = { | ||||
| static const struct vop_win_phy rk3066_win2_data = { | ||||
| 	.data_formats = formats_win_lite, | ||||
| 	.nformats = ARRAY_SIZE(formats_win_lite), | ||||
| 	.format_modifiers = format_modifiers_win_lite, | ||||
| 	.enable = VOP_REG(RK3066_SYS_CTRL1, 0x1, 2), | ||||
| 	.format = VOP_REG(RK3066_SYS_CTRL0, 0x7, 10), | ||||
| 	.rb_swap = VOP_REG(RK3066_SYS_CTRL0, 0x1, 27), | ||||
| @ -426,6 +451,7 @@ static const struct vop_win_phy rk3188_win0_data = { | ||||
| 	.scl = &rk3188_win_scl, | ||||
| 	.data_formats = formats_win_full, | ||||
| 	.nformats = ARRAY_SIZE(formats_win_full), | ||||
| 	.format_modifiers = format_modifiers_win_full, | ||||
| 	.enable = VOP_REG(RK3188_SYS_CTRL, 0x1, 0), | ||||
| 	.format = VOP_REG(RK3188_SYS_CTRL, 0x7, 3), | ||||
| 	.rb_swap = VOP_REG(RK3188_SYS_CTRL, 0x1, 15), | ||||
| @ -440,6 +466,7 @@ static const struct vop_win_phy rk3188_win0_data = { | ||||
| static const struct vop_win_phy rk3188_win1_data = { | ||||
| 	.data_formats = formats_win_lite, | ||||
| 	.nformats = ARRAY_SIZE(formats_win_lite), | ||||
| 	.format_modifiers = format_modifiers_win_lite, | ||||
| 	.enable = VOP_REG(RK3188_SYS_CTRL, 0x1, 1), | ||||
| 	.format = VOP_REG(RK3188_SYS_CTRL, 0x7, 6), | ||||
| 	.rb_swap = VOP_REG(RK3188_SYS_CTRL, 0x1, 19), | ||||
| @ -545,6 +572,7 @@ static const struct vop_win_phy rk3288_win01_data = { | ||||
| 	.scl = &rk3288_win_full_scl, | ||||
| 	.data_formats = formats_win_full, | ||||
| 	.nformats = ARRAY_SIZE(formats_win_full), | ||||
| 	.format_modifiers = format_modifiers_win_full, | ||||
| 	.enable = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 0), | ||||
| 	.format = VOP_REG(RK3288_WIN0_CTRL0, 0x7, 1), | ||||
| 	.rb_swap = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 12), | ||||
| @ -563,6 +591,7 @@ static const struct vop_win_phy rk3288_win01_data = { | ||||
| static const struct vop_win_phy rk3288_win23_data = { | ||||
| 	.data_formats = formats_win_lite, | ||||
| 	.nformats = ARRAY_SIZE(formats_win_lite), | ||||
| 	.format_modifiers = format_modifiers_win_lite, | ||||
| 	.enable = VOP_REG(RK3288_WIN2_CTRL0, 0x1, 4), | ||||
| 	.gate = VOP_REG(RK3288_WIN2_CTRL0, 0x1, 0), | ||||
| 	.format = VOP_REG(RK3288_WIN2_CTRL0, 0x7, 1), | ||||
| @ -677,6 +706,7 @@ static const struct vop_win_phy rk3368_win01_data = { | ||||
| 	.scl = &rk3288_win_full_scl, | ||||
| 	.data_formats = formats_win_full, | ||||
| 	.nformats = ARRAY_SIZE(formats_win_full), | ||||
| 	.format_modifiers = format_modifiers_win_full, | ||||
| 	.enable = VOP_REG(RK3368_WIN0_CTRL0, 0x1, 0), | ||||
| 	.format = VOP_REG(RK3368_WIN0_CTRL0, 0x7, 1), | ||||
| 	.rb_swap = VOP_REG(RK3368_WIN0_CTRL0, 0x1, 12), | ||||
| @ -697,6 +727,7 @@ static const struct vop_win_phy rk3368_win01_data = { | ||||
| static const struct vop_win_phy rk3368_win23_data = { | ||||
| 	.data_formats = formats_win_lite, | ||||
| 	.nformats = ARRAY_SIZE(formats_win_lite), | ||||
| 	.format_modifiers = format_modifiers_win_lite, | ||||
| 	.gate = VOP_REG(RK3368_WIN2_CTRL0, 0x1, 0), | ||||
| 	.enable = VOP_REG(RK3368_WIN2_CTRL0, 0x1, 4), | ||||
| 	.format = VOP_REG(RK3368_WIN2_CTRL0, 0x3, 5), | ||||
| @ -817,6 +848,53 @@ static const struct vop_win_yuv2yuv_data rk3399_vop_big_win_yuv2yuv_data[] = { | ||||
| 	  .y2r_en = VOP_REG(RK3399_YUV2YUV_WIN, 0x1, 9) }, | ||||
| 	{ .base = 0xC0, .phy = &rk3399_yuv2yuv_win23_data }, | ||||
| 	{ .base = 0x120, .phy = &rk3399_yuv2yuv_win23_data }, | ||||
| 
 | ||||
| }; | ||||
| 
 | ||||
| static const struct vop_win_phy rk3399_win01_data = { | ||||
| 	.scl = &rk3288_win_full_scl, | ||||
| 	.data_formats = formats_win_full, | ||||
| 	.nformats = ARRAY_SIZE(formats_win_full), | ||||
| 	.format_modifiers = format_modifiers_win_full_afbc, | ||||
| 	.enable = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 0), | ||||
| 	.format = VOP_REG(RK3288_WIN0_CTRL0, 0x7, 1), | ||||
| 	.rb_swap = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 12), | ||||
| 	.y_mir_en = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 22), | ||||
| 	.act_info = VOP_REG(RK3288_WIN0_ACT_INFO, 0x1fff1fff, 0), | ||||
| 	.dsp_info = VOP_REG(RK3288_WIN0_DSP_INFO, 0x0fff0fff, 0), | ||||
| 	.dsp_st = VOP_REG(RK3288_WIN0_DSP_ST, 0x1fff1fff, 0), | ||||
| 	.yrgb_mst = VOP_REG(RK3288_WIN0_YRGB_MST, 0xffffffff, 0), | ||||
| 	.uv_mst = VOP_REG(RK3288_WIN0_CBR_MST, 0xffffffff, 0), | ||||
| 	.yrgb_vir = VOP_REG(RK3288_WIN0_VIR, 0x3fff, 0), | ||||
| 	.uv_vir = VOP_REG(RK3288_WIN0_VIR, 0x3fff, 16), | ||||
| 	.src_alpha_ctl = VOP_REG(RK3288_WIN0_SRC_ALPHA_CTRL, 0xff, 0), | ||||
| 	.dst_alpha_ctl = VOP_REG(RK3288_WIN0_DST_ALPHA_CTRL, 0xff, 0), | ||||
| }; | ||||
| 
 | ||||
| /*
 | ||||
|  * rk3399 vop big windows register layout is same as rk3288, but we | ||||
|  * have a separate rk3399 win data array here so that we can advertise | ||||
|  * AFBC on the primary plane. | ||||
|  */ | ||||
| static const struct vop_win_data rk3399_vop_win_data[] = { | ||||
| 	{ .base = 0x00, .phy = &rk3399_win01_data, | ||||
| 	  .type = DRM_PLANE_TYPE_PRIMARY }, | ||||
| 	{ .base = 0x40, .phy = &rk3288_win01_data, | ||||
| 	  .type = DRM_PLANE_TYPE_OVERLAY }, | ||||
| 	{ .base = 0x00, .phy = &rk3288_win23_data, | ||||
| 	  .type = DRM_PLANE_TYPE_OVERLAY }, | ||||
| 	{ .base = 0x50, .phy = &rk3288_win23_data, | ||||
| 	  .type = DRM_PLANE_TYPE_CURSOR }, | ||||
| }; | ||||
| 
 | ||||
| static const struct vop_afbc rk3399_vop_afbc = { | ||||
| 	.rstn = VOP_REG(RK3399_AFBCD0_CTRL, 0x1, 3), | ||||
| 	.enable = VOP_REG(RK3399_AFBCD0_CTRL, 0x1, 0), | ||||
| 	.win_sel = VOP_REG(RK3399_AFBCD0_CTRL, 0x3, 1), | ||||
| 	.format = VOP_REG(RK3399_AFBCD0_CTRL, 0x1f, 16), | ||||
| 	.hreg_block_split = VOP_REG(RK3399_AFBCD0_CTRL, 0x1, 21), | ||||
| 	.hdr_ptr = VOP_REG(RK3399_AFBCD0_HDR_PTR, 0xffffffff, 0), | ||||
| 	.pic_size = VOP_REG(RK3399_AFBCD0_PIC_SIZE, 0xffffffff, 0), | ||||
| }; | ||||
| 
 | ||||
| static const struct vop_data rk3399_vop_big = { | ||||
| @ -826,9 +904,10 @@ static const struct vop_data rk3399_vop_big = { | ||||
| 	.common = &rk3288_common, | ||||
| 	.modeset = &rk3288_modeset, | ||||
| 	.output = &rk3399_output, | ||||
| 	.afbc = &rk3399_vop_afbc, | ||||
| 	.misc = &rk3368_misc, | ||||
| 	.win = rk3368_vop_win_data, | ||||
| 	.win_size = ARRAY_SIZE(rk3368_vop_win_data), | ||||
| 	.win = rk3399_vop_win_data, | ||||
| 	.win_size = ARRAY_SIZE(rk3399_vop_win_data), | ||||
| 	.win_yuv2yuv = rk3399_vop_big_win_yuv2yuv_data, | ||||
| }; | ||||
| 
 | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user