disp: msm: sde: pre-downscale support for inline rotation v2

Add support for enabling pre-downscale block to increase the
maximum downscale capability for true inline rotation use cases.

Change-Id: Ifa544bb0ae69439abef4bd427134290090fe7230
Signed-off-by: Steve Cohen <cohens@codeaurora.org>
这个提交包含在:
Steve Cohen
2019-08-01 12:18:14 -04:00
父节点 5a55e2d121
当前提交 60133f5ebb
修改 7 个文件,包含 193 行新增40 行删除

查看文件

@@ -1512,6 +1512,10 @@ static void _sde_plane_setup_scaler(struct sde_plane *psde,
pe->btm_ftch[i] = pe->num_ext_pxls_btm[i];
}
}
if (psde->pipe_hw->ops.setup_pre_downscale)
psde->pipe_hw->ops.setup_pre_downscale(psde->pipe_hw,
&pstate->pre_down);
}
/**
@@ -1652,7 +1656,7 @@ static int sde_plane_rot_atomic_check(struct drm_plane *plane,
!psde->pipe_sblk->in_rot_maxdwnscale_nrt ||
!psde->pipe_sblk->in_rot_maxheight ||
!psde->pipe_sblk->in_rot_format_list ||
!(psde->features & BIT(SDE_SSPP_TRUE_INLINE_ROT_V1))) {
!(psde->features & BIT(SDE_SSPP_TRUE_INLINE_ROT))) {
SDE_ERROR_PLANE(psde,
"wrong config rt:%d/%d nrt:%d fmt:%d h:%d 0x%x\n",
!psde->pipe_sblk->in_rot_maxdwnscale_rt_num,
@@ -1787,7 +1791,7 @@ static void sde_plane_rot_install_properties(struct drm_plane *plane,
return;
}
if (psde->features & BIT(SDE_SSPP_TRUE_INLINE_ROT_V1))
if (psde->features & BIT(SDE_SSPP_TRUE_INLINE_ROT))
supported_rotations |= DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_90 |
DRM_MODE_ROTATE_180 | DRM_MODE_ROTATE_270;
@@ -2269,6 +2273,12 @@ int sde_plane_validate_src_addr(struct drm_plane *plane,
return ret;
}
static inline bool _sde_plane_is_pre_downscale_enabled(
struct sde_hw_inline_pre_downscale_cfg *pre_down)
{
return pre_down->pre_downscale_x_0 || pre_down->pre_downscale_y_0;
}
static int _sde_plane_validate_scaler_v2(struct sde_plane *psde,
struct sde_plane_state *pstate,
const struct sde_format *fmt,
@@ -2276,6 +2286,8 @@ static int _sde_plane_validate_scaler_v2(struct sde_plane *psde,
uint32_t src_w, uint32_t src_h,
uint32_t deci_w, uint32_t deci_h)
{
struct sde_hw_inline_pre_downscale_cfg *pd_cfg;
bool pre_down_en;
int i;
if (!psde || !pstate || !fmt) {
@@ -2288,6 +2300,9 @@ static int _sde_plane_validate_scaler_v2(struct sde_plane *psde,
pstate->scaler_check_state != SDE_PLANE_SCLCHECK_SCALER_V2_CHECK))
return 0;
pd_cfg = &pstate->pre_down;
pre_down_en = _sde_plane_is_pre_downscale_enabled(pd_cfg);
pstate->scaler_check_state = SDE_PLANE_SCLCHECK_INVALID;
for (i = 0; i < SDE_MAX_PLANES; i++) {
@@ -2295,12 +2310,26 @@ static int _sde_plane_validate_scaler_v2(struct sde_plane *psde,
uint32_t vert_req_pixels, vert_fetch_pixels;
uint32_t src_w_tmp, src_h_tmp;
uint32_t scaler_w, scaler_h;
uint32_t pre_down_ratio_x = 1, pre_down_ratio_y = 1;
bool rot;
/* re-use color plane 1's config for plane 2 */
if (i == 2)
continue;
if (pre_down_en) {
if (i == 0 && pd_cfg->pre_downscale_x_0)
pre_down_ratio_x = pd_cfg->pre_downscale_x_0;
if (i == 0 && pd_cfg->pre_downscale_y_0)
pre_down_ratio_y = pd_cfg->pre_downscale_y_0;
if ((i == 1 || i == 2) && pd_cfg->pre_downscale_x_1)
pre_down_ratio_x = pd_cfg->pre_downscale_x_1;
if ((i == 1 || i == 2) && pd_cfg->pre_downscale_y_1)
pre_down_ratio_y = pd_cfg->pre_downscale_y_1;
SDE_DEBUG_PLANE(psde, "pre_down[%d]: x:%d, y:%d\n",
i, pre_down_ratio_x, pre_down_ratio_y);
}
src_w_tmp = src_w;
src_h_tmp = src_h;
@@ -2359,13 +2388,14 @@ static int _sde_plane_validate_scaler_v2(struct sde_plane *psde,
* repeat/drop, src_width and src_height are only specified
* for Y and UV plane
*/
if (i != 3 && (hor_req_pixels != scaler_w ||
vert_req_pixels != scaler_h)) {
if (i != 3 && (hor_req_pixels / pre_down_ratio_x != scaler_w ||
vert_req_pixels / pre_down_ratio_y !=
scaler_h)) {
SDE_ERROR_PLANE(psde,
"roi[%d] roi:%dx%d scaler:%dx%d src:%dx%d rot:%d\n",
"roi[%d] roi:%dx%d scaler:%dx%d src:%dx%d rot:%d pd:%d/%d\n",
i, pstate->pixel_ext.roi_w[i],
pstate->pixel_ext.roi_h[i],
scaler_w, scaler_h, src_w, src_h, rot);
pstate->pixel_ext.roi_h[i], scaler_w, scaler_h,
src_w, src_h, rot, pre_down_ratio_x, pre_down_ratio_y);
return -EINVAL;
}
@@ -2393,6 +2423,39 @@ static int _sde_plane_validate_scaler_v2(struct sde_plane *psde,
return 0;
}
static int _sde_atomic_check_pre_downscale(struct sde_plane *psde,
struct sde_plane_state *pstate, struct sde_rect *dst,
u32 scaler_src_w, u32 scaler_src_h)
{
int ret = 0;
u32 min_ratio_numer, min_ratio_denom;
min_ratio_numer = psde->pipe_sblk->in_rot_minpredwnscale_num;
min_ratio_denom = psde->pipe_sblk->in_rot_minpredwnscale_denom;
if (!(psde->features & BIT(SDE_SSPP_PREDOWNSCALE))) {
SDE_ERROR_PLANE(psde,
"hw does not support pre-downscaler: 0x%x\n",
psde->features);
ret = -EINVAL;
} else if (!min_ratio_numer || !min_ratio_denom) {
SDE_ERROR_PLANE(psde,
"min downscale ratio not set! %u / %u\n",
min_ratio_numer, min_ratio_denom);
ret = -EINVAL;
} else if ((scaler_src_w < mult_frac(dst->w, min_ratio_numer,
min_ratio_denom)) || (scaler_src_h < mult_frac(
dst->h, min_ratio_numer, min_ratio_denom))) {
SDE_ERROR_PLANE(psde,
"failed min downscale check %ux%u->%ux%u, %u/%u\n",
scaler_src_w, scaler_src_h, dst->w, dst->h,
min_ratio_numer, min_ratio_denom);
ret = -EINVAL;
}
return ret;
}
static int _sde_atomic_check_decimation_scaler(struct drm_plane_state *state,
struct sde_plane *psde, const struct sde_format *fmt,
struct sde_plane_state *pstate, struct sde_rect *src,
@@ -2403,7 +2466,7 @@ static int _sde_atomic_check_decimation_scaler(struct drm_plane_state *state,
uint32_t scaler_src_w, scaler_src_h;
uint32_t max_downscale_num, max_downscale_denom;
uint32_t max_upscale, max_linewidth;
bool inline_rotation, rt_client;
bool inline_rotation, rt_client, pre_down_en = false;
struct drm_crtc *crtc;
struct drm_crtc_state *new_cstate;
@@ -2430,16 +2493,25 @@ static int _sde_atomic_check_decimation_scaler(struct drm_plane_state *state,
max_upscale = psde->pipe_sblk->maxupscale;
max_linewidth = psde->pipe_sblk->maxlinewidth;
if (psde->features & BIT(SDE_SSPP_PREDOWNSCALE))
pre_down_en = _sde_plane_is_pre_downscale_enabled(
&pstate->pre_down);
crtc = state->crtc;
new_cstate = drm_atomic_get_new_crtc_state(state->state, crtc);
rt_client = sde_crtc_is_rt_client(crtc, new_cstate);
max_downscale_num = psde->pipe_sblk->maxdwnscale;
max_downscale_denom = 1;
/* inline rotation RT clients have a different max downscaling limit */
if (inline_rotation) {
if (rt_client) {
if (rt_client && !pre_down_en) {
max_downscale_num =
psde->pipe_sblk->in_rot_minpredwnscale_num;
max_downscale_denom =
psde->pipe_sblk->in_rot_minpredwnscale_denom;
} else if (rt_client) {
max_downscale_num =
psde->pipe_sblk->in_rot_maxdwnscale_rt_num;
max_downscale_denom =
@@ -2448,8 +2520,6 @@ static int _sde_atomic_check_decimation_scaler(struct drm_plane_state *state,
max_downscale_num =
psde->pipe_sblk->in_rot_maxdwnscale_nrt;
}
} else {
max_downscale_num = psde->pipe_sblk->maxdwnscale;
}
/* decimation validation */
@@ -2477,23 +2547,31 @@ static int _sde_atomic_check_decimation_scaler(struct drm_plane_state *state,
"invalid src w:%u, deci w:%u, line w:%u\n",
src->w, src_deci_w, max_linewidth);
ret = -E2BIG;
}
/* check max scaler capability */
else if (((scaler_src_w * max_upscale) < dst->w) ||
} else if (((scaler_src_w * max_upscale) < dst->w) ||
((scaler_src_h * max_upscale) < dst->h) ||
(((dst->w * max_downscale_num) / max_downscale_denom)
< scaler_src_w) ||
(((dst->h * max_downscale_num) / max_downscale_denom)
< scaler_src_h)) {
SDE_ERROR_PLANE(psde,
"too much scaling requested %ux%u->%ux%u rot:%d\n",
"too much scaling %ux%u->%ux%u rot:%d dwn:%d/%d\n",
scaler_src_w, scaler_src_h, dst->w, dst->h,
inline_rotation);
inline_rotation, max_downscale_num,
max_downscale_denom);
ret = -E2BIG;
/* check inline pre-downscale support */
} else if (inline_rotation && pre_down_en &&
_sde_atomic_check_pre_downscale(psde, pstate, dst,
scaler_src_w, scaler_src_h)) {
ret = -EINVAL;
/* QSEED validation */
} else if (_sde_plane_validate_scaler_v2(psde, pstate, fmt,
width, height,
src->w, src->h, deci_w, deci_h)) {
width, height, src->w, src->h,
deci_w, deci_h)) {
ret = -EINVAL;
}
@@ -3571,10 +3649,11 @@ static void _sde_plane_install_properties(struct drm_plane *plane,
if (psde->features & BIT(SDE_SSPP_BLOCK_SEC_UI))
sde_kms_info_add_keyint(info, "block_sec_ui", 1);
if (psde->features & BIT(SDE_SSPP_TRUE_INLINE_ROT_V1)) {
if (psde->features & BIT(SDE_SSPP_TRUE_INLINE_ROT)) {
const struct sde_format_extended *inline_rot_fmt_list;
sde_kms_info_add_keyint(info, "true_inline_rot_rev", 1);
sde_kms_info_add_keyint(info, "true_inline_rot_rev",
catalog->true_inline_rot_rev);
sde_kms_info_add_keyint(info,
"true_inline_dwnscale_rt",
(int) (psde->pipe_sblk->in_rot_maxdwnscale_rt_num /
@@ -3769,6 +3848,15 @@ static inline void _sde_plane_set_scaler_v1(struct sde_plane *psde,
SDE_DEBUG_PLANE(psde, "user property data copied\n");
}
static void _sde_plane_clear_predownscale_settings(
struct sde_plane_state *pstate)
{
pstate->pre_down.pre_downscale_x_0 = 0;
pstate->pre_down.pre_downscale_x_1 = 0;
pstate->pre_down.pre_downscale_y_0 = 0;
pstate->pre_down.pre_downscale_y_1 = 0;
}
static inline void _sde_plane_set_scaler_v2(struct sde_plane *psde,
struct sde_plane_state *pstate, void __user *usr)
{
@@ -3776,6 +3864,7 @@ static inline void _sde_plane_set_scaler_v2(struct sde_plane *psde,
struct sde_hw_pixel_ext *pe;
int i;
struct sde_hw_scaler3_cfg *cfg;
struct sde_hw_inline_pre_downscale_cfg *pd_cfg;
if (!psde || !pstate) {
SDE_ERROR("invalid argument(s)\n");
@@ -3783,10 +3872,12 @@ static inline void _sde_plane_set_scaler_v2(struct sde_plane *psde,
}
cfg = &pstate->scaler3_cfg;
pd_cfg = &pstate->pre_down;
pstate->scaler_check_state = SDE_PLANE_SCLCHECK_NONE;
if (!usr) {
SDE_DEBUG_PLANE(psde, "scale data removed\n");
cfg->enable = 0;
_sde_plane_clear_predownscale_settings(pstate);
goto end;
}
@@ -3799,12 +3890,20 @@ static inline void _sde_plane_set_scaler_v2(struct sde_plane *psde,
if (!scale_v2.enable) {
SDE_DEBUG_PLANE(psde, "scale data removed\n");
cfg->enable = 0;
_sde_plane_clear_predownscale_settings(pstate);
goto end;
}
/* populate from user space */
sde_set_scaler_v2(cfg, &scale_v2);
if (psde->features & BIT(SDE_SSPP_PREDOWNSCALE)) {
pd_cfg->pre_downscale_x_0 = scale_v2.pre_downscale_x_0;
pd_cfg->pre_downscale_x_1 = scale_v2.pre_downscale_x_1;
pd_cfg->pre_downscale_y_0 = scale_v2.pre_downscale_y_0;
pd_cfg->pre_downscale_y_1 = scale_v2.pre_downscale_y_1;
}
pe = &pstate->pixel_ext;
memset(pe, 0, sizeof(struct sde_hw_pixel_ext));
@@ -4311,7 +4410,7 @@ static int _sde_plane_init_debugfs(struct drm_plane *plane)
psde->debugfs_root,
&psde->debugfs_default_scale);
if (cfg->features & BIT(SDE_SSPP_TRUE_INLINE_ROT_V1)) {
if (cfg->features & BIT(SDE_SSPP_TRUE_INLINE_ROT)) {
debugfs_create_u32("in_rot_max_downscale_rt_num",
0600,
psde->debugfs_root,