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>
This commit is contained in:
Steve Cohen
2019-08-01 12:18:14 -04:00
parent 5a55e2d121
commit 60133f5ebb
7 changed files with 193 additions and 40 deletions

View File

@@ -69,9 +69,12 @@
#define MAX_DOWNSCALE_RATIO 4 #define MAX_DOWNSCALE_RATIO 4
#define SSPP_UNITY_SCALE 1 #define SSPP_UNITY_SCALE 1
#define MAX_DOWNSCALE_RATIO_INLINE_ROT_RT_NUMERATOR 11 #define MAX_DOWNSCALE_RATIO_INROT_NOPD_RT_NUMERATOR 11
#define MAX_DOWNSCALE_RATIO_INLINE_ROT_RT_DENOMINATOR 5 #define MAX_DOWNSCALE_RATIO_INROT_NOPD_RT_DENOMINATOR 5
#define MAX_DOWNSCALE_RATIO_INLINE_ROT_NRT_DEFAULT 4 #define MAX_DOWNSCALE_RATIO_INROT_PD_RT_NUMERATOR 4
#define MAX_DOWNSCALE_RATIO_INROT_PD_RT_DENOMINATOR 1
#define MAX_DOWNSCALE_RATIO_INROT_NRT_DEFAULT 4
#define MAX_PRE_ROT_HEIGHT_INLINE_ROT_DEFAULT 1088 #define MAX_PRE_ROT_HEIGHT_INLINE_ROT_DEFAULT 1088
#define MAX_HORZ_DECIMATION 4 #define MAX_HORZ_DECIMATION 4
@@ -1255,8 +1258,10 @@ static void _sde_sspp_setup_vig(struct sde_mdss_cfg *sde_cfg,
sblk->format_list = sde_cfg->vig_formats; sblk->format_list = sde_cfg->vig_formats;
sblk->virt_format_list = sde_cfg->virt_vig_formats; sblk->virt_format_list = sde_cfg->virt_vig_formats;
if (IS_SDE_INLINE_ROT_REV_100(sde_cfg->true_inline_rot_rev)) { if (IS_SDE_INLINE_ROT_REV_100(sde_cfg->true_inline_rot_rev) ||
set_bit(SDE_SSPP_TRUE_INLINE_ROT_V1, &sspp->features); IS_SDE_INLINE_ROT_REV_200(
sde_cfg->true_inline_rot_rev)) {
set_bit(SDE_SSPP_TRUE_INLINE_ROT, &sspp->features);
sblk->in_rot_format_list = sde_cfg->inline_rot_formats; sblk->in_rot_format_list = sde_cfg->inline_rot_formats;
sblk->in_rot_maxdwnscale_rt_num = sblk->in_rot_maxdwnscale_rt_num =
sde_cfg->true_inline_dwnscale_rt_num; sde_cfg->true_inline_dwnscale_rt_num;
@@ -1274,6 +1279,14 @@ static void _sde_sspp_setup_vig(struct sde_mdss_cfg *sde_cfg,
sde_cfg->true_inline_prefill_lines; sde_cfg->true_inline_prefill_lines;
} }
if (IS_SDE_INLINE_ROT_REV_200(sde_cfg->true_inline_rot_rev)) {
set_bit(SDE_SSPP_PREDOWNSCALE, &sspp->features);
sblk->in_rot_minpredwnscale_num =
MAX_DOWNSCALE_RATIO_INROT_NOPD_RT_NUMERATOR;
sblk->in_rot_minpredwnscale_denom =
MAX_DOWNSCALE_RATIO_INROT_NOPD_RT_DENOMINATOR;
}
if (sde_cfg->sc_cfg.has_sys_cache) { if (sde_cfg->sc_cfg.has_sys_cache) {
set_bit(SDE_PERF_SSPP_SYS_CACHE, &sspp->perf_features); set_bit(SDE_PERF_SSPP_SYS_CACHE, &sspp->perf_features);
sblk->llcc_scid = sde_cfg->sc_cfg.llcc_scid; sblk->llcc_scid = sde_cfg->sc_cfg.llcc_scid;
@@ -2311,8 +2324,7 @@ static int sde_rot_parse_dt(struct device_node *np,
if (rc) { if (rc) {
/* /*
* This is not a fatal error, system cache can be disabled * This is not a fatal error, system cache can be disabled
* in device tree, anyways recommendation is to have it * in device tree
* enabled, so print an error but don't fail
*/ */
SDE_DEBUG("sys cache will be disabled rc:%d\n", rc); SDE_DEBUG("sys cache will be disabled rc:%d\n", rc);
rc = 0; rc = 0;
@@ -4310,11 +4322,11 @@ static int _sde_hardware_pre_caps(struct sde_mdss_cfg *sde_cfg, uint32_t hw_rev)
sde_cfg->has_vig_p010 = true; sde_cfg->has_vig_p010 = true;
sde_cfg->true_inline_rot_rev = SDE_INLINE_ROT_VERSION_1_0_0; sde_cfg->true_inline_rot_rev = SDE_INLINE_ROT_VERSION_1_0_0;
sde_cfg->true_inline_dwnscale_rt_num = sde_cfg->true_inline_dwnscale_rt_num =
MAX_DOWNSCALE_RATIO_INLINE_ROT_RT_NUMERATOR; MAX_DOWNSCALE_RATIO_INROT_NOPD_RT_NUMERATOR;
sde_cfg->true_inline_dwnscale_rt_denom = sde_cfg->true_inline_dwnscale_rt_denom =
MAX_DOWNSCALE_RATIO_INLINE_ROT_RT_DENOMINATOR; MAX_DOWNSCALE_RATIO_INROT_NOPD_RT_DENOMINATOR;
sde_cfg->true_inline_dwnscale_nrt = sde_cfg->true_inline_dwnscale_nrt =
MAX_DOWNSCALE_RATIO_INLINE_ROT_NRT_DEFAULT; MAX_DOWNSCALE_RATIO_INROT_NRT_DEFAULT;
sde_cfg->true_inline_prefill_fudge_lines = 2; sde_cfg->true_inline_prefill_fudge_lines = 2;
sde_cfg->true_inline_prefill_lines_nv12 = 32; sde_cfg->true_inline_prefill_lines_nv12 = 32;
sde_cfg->true_inline_prefill_lines = 48; sde_cfg->true_inline_prefill_lines = 48;
@@ -4341,11 +4353,11 @@ static int _sde_hardware_pre_caps(struct sde_mdss_cfg *sde_cfg, uint32_t hw_rev)
sde_cfg->has_vig_p010 = true; sde_cfg->has_vig_p010 = true;
sde_cfg->true_inline_rot_rev = SDE_INLINE_ROT_VERSION_1_0_0; sde_cfg->true_inline_rot_rev = SDE_INLINE_ROT_VERSION_1_0_0;
sde_cfg->true_inline_dwnscale_rt_num = sde_cfg->true_inline_dwnscale_rt_num =
MAX_DOWNSCALE_RATIO_INLINE_ROT_RT_NUMERATOR; MAX_DOWNSCALE_RATIO_INROT_NOPD_RT_NUMERATOR;
sde_cfg->true_inline_dwnscale_rt_denom = sde_cfg->true_inline_dwnscale_rt_denom =
MAX_DOWNSCALE_RATIO_INLINE_ROT_RT_DENOMINATOR; MAX_DOWNSCALE_RATIO_INROT_NOPD_RT_DENOMINATOR;
sde_cfg->true_inline_dwnscale_nrt = sde_cfg->true_inline_dwnscale_nrt =
MAX_DOWNSCALE_RATIO_INLINE_ROT_NRT_DEFAULT; MAX_DOWNSCALE_RATIO_INROT_NRT_DEFAULT;
sde_cfg->true_inline_prefill_fudge_lines = 2; sde_cfg->true_inline_prefill_fudge_lines = 2;
sde_cfg->true_inline_prefill_lines_nv12 = 32; sde_cfg->true_inline_prefill_lines_nv12 = 32;
sde_cfg->true_inline_prefill_lines = 48; sde_cfg->true_inline_prefill_lines = 48;
@@ -4395,13 +4407,13 @@ static int _sde_hardware_pre_caps(struct sde_mdss_cfg *sde_cfg, uint32_t hw_rev)
sde_cfg->has_hdr_plus = true; sde_cfg->has_hdr_plus = true;
set_bit(SDE_MDP_DHDR_MEMPOOL, &sde_cfg->mdp[0].features); set_bit(SDE_MDP_DHDR_MEMPOOL, &sde_cfg->mdp[0].features);
sde_cfg->has_vig_p010 = true; sde_cfg->has_vig_p010 = true;
sde_cfg->true_inline_rot_rev = SDE_INLINE_ROT_VERSION_1_0_0; sde_cfg->true_inline_rot_rev = SDE_INLINE_ROT_VERSION_2_0_0;
sde_cfg->true_inline_dwnscale_rt_num = sde_cfg->true_inline_dwnscale_rt_num =
MAX_DOWNSCALE_RATIO_INLINE_ROT_RT_NUMERATOR; MAX_DOWNSCALE_RATIO_INROT_PD_RT_NUMERATOR;
sde_cfg->true_inline_dwnscale_rt_denom = sde_cfg->true_inline_dwnscale_rt_denom =
MAX_DOWNSCALE_RATIO_INLINE_ROT_RT_DENOMINATOR; MAX_DOWNSCALE_RATIO_INROT_PD_RT_DENOMINATOR;
sde_cfg->true_inline_dwnscale_nrt = sde_cfg->true_inline_dwnscale_nrt =
MAX_DOWNSCALE_RATIO_INLINE_ROT_NRT_DEFAULT; MAX_DOWNSCALE_RATIO_INROT_NRT_DEFAULT;
sde_cfg->true_inline_prefill_fudge_lines = 2; sde_cfg->true_inline_prefill_fudge_lines = 2;
sde_cfg->true_inline_prefill_lines_nv12 = 32; sde_cfg->true_inline_prefill_lines_nv12 = 32;
sde_cfg->true_inline_prefill_lines = 48; sde_cfg->true_inline_prefill_lines = 48;

View File

@@ -216,7 +216,8 @@ enum {
* @SDE_SSPP_SEC_UI_ALLOWED Allows secure-ui layers * @SDE_SSPP_SEC_UI_ALLOWED Allows secure-ui layers
* @SDE_SSPP_BLOCK_SEC_UI Blocks secure-ui layers * @SDE_SSPP_BLOCK_SEC_UI Blocks secure-ui layers
* @SDE_SSPP_SCALER_QSEED3LITE Qseed3lite algorithm support * @SDE_SSPP_SCALER_QSEED3LITE Qseed3lite algorithm support
* @SDE_SSPP_TRUE_INLINE_ROT_V1, Support of SSPP true inline rotation v1 * @SDE_SSPP_TRUE_INLINE_ROT Support of SSPP true inline rotation v1
* @SDE_SSPP_PREDOWNSCALE Support pre-downscale X-direction by 2 for inline
* @SDE_SSPP_INLINE_CONST_CLR Inline rotation requires const clr disabled * @SDE_SSPP_INLINE_CONST_CLR Inline rotation requires const clr disabled
* @SDE_SSPP_MAX maximum value * @SDE_SSPP_MAX maximum value
*/ */
@@ -245,7 +246,8 @@ enum {
SDE_SSPP_SEC_UI_ALLOWED, SDE_SSPP_SEC_UI_ALLOWED,
SDE_SSPP_BLOCK_SEC_UI, SDE_SSPP_BLOCK_SEC_UI,
SDE_SSPP_SCALER_QSEED3LITE, SDE_SSPP_SCALER_QSEED3LITE,
SDE_SSPP_TRUE_INLINE_ROT_V1, SDE_SSPP_TRUE_INLINE_ROT,
SDE_SSPP_PREDOWNSCALE,
SDE_SSPP_INLINE_CONST_CLR, SDE_SSPP_INLINE_CONST_CLR,
SDE_SSPP_MAX SDE_SSPP_MAX
}; };
@@ -622,6 +624,8 @@ struct sde_qos_lut_tbl {
* @in_rot_maxdwnscale_rt_denom: max downscale ratio for inline rotation * @in_rot_maxdwnscale_rt_denom: max downscale ratio for inline rotation
* rt clients - denominator * rt clients - denominator
* @in_rot_maxdwnscale_nrt: max downscale ratio for inline rotation nrt clients * @in_rot_maxdwnscale_nrt: max downscale ratio for inline rotation nrt clients
* @in_rot_minpredwnscale_num: min downscale ratio to enable pre-downscale
* @in_rot_minpredwnscale_denom: min downscale ratio to enable pre-downscale
* @in_rot_maxheight: max pre rotated height for inline rotation * @in_rot_maxheight: max pre rotated height for inline rotation
* @in_rot_prefill_fudge_lines: prefill fudge lines for inline rotation * @in_rot_prefill_fudge_lines: prefill fudge lines for inline rotation
* @in_rot_prefill_lines_mv12: prefill lines for nv12 format inline rotation * @in_rot_prefill_lines_mv12: prefill lines for nv12 format inline rotation
@@ -661,6 +665,8 @@ struct sde_sspp_sub_blks {
u32 in_rot_maxdwnscale_rt_num; u32 in_rot_maxdwnscale_rt_num;
u32 in_rot_maxdwnscale_rt_denom; u32 in_rot_maxdwnscale_rt_denom;
u32 in_rot_maxdwnscale_nrt; u32 in_rot_maxdwnscale_nrt;
u32 in_rot_minpredwnscale_num;
u32 in_rot_minpredwnscale_denom;
u32 in_rot_maxheight; u32 in_rot_maxheight;
u32 in_rot_prefill_fudge_lines; u32 in_rot_prefill_fudge_lines;
u32 in_rot_prefill_lines_nv12; u32 in_rot_prefill_lines_nv12;

View File

@@ -67,7 +67,8 @@
#define SSPP_SRC_CONSTANT_COLOR 0x3c #define SSPP_SRC_CONSTANT_COLOR 0x3c
#define SSPP_EXCL_REC_CTL 0x40 #define SSPP_EXCL_REC_CTL 0x40
#define SSPP_UBWC_STATIC_CTRL 0x44 #define SSPP_UBWC_STATIC_CTRL 0x44
#define SSPP_FETCH_CONFIG 0x048 #define SSPP_FETCH_CONFIG 0x48
#define SSPP_PRE_DOWN_SCALE 0x50
#define SSPP_DANGER_LUT 0x60 #define SSPP_DANGER_LUT 0x60
#define SSPP_SAFE_LUT 0x64 #define SSPP_SAFE_LUT 0x64
#define SSPP_CREQ_LUT 0x68 #define SSPP_CREQ_LUT 0x68
@@ -596,6 +597,22 @@ static void _sde_hw_sspp_setup_scaler3(struct sde_hw_pipe *ctx,
ctx->cap->sblk->scaler_blk.version, idx, sspp->layout.format); ctx->cap->sblk->scaler_blk.version, idx, sspp->layout.format);
} }
static void sde_hw_sspp_setup_pre_downscale(struct sde_hw_pipe *ctx,
struct sde_hw_inline_pre_downscale_cfg *pre_down)
{
u32 idx, val;
if (!ctx || !pre_down || _sspp_subblk_offset(ctx, SDE_SSPP_SRC, &idx))
return;
val = pre_down->pre_downscale_x_0 |
(pre_down->pre_downscale_x_1 << 4) |
(pre_down->pre_downscale_y_0 << 8) |
(pre_down->pre_downscale_y_1 << 12);
SDE_REG_WRITE(&ctx->hw, SSPP_PRE_DOWN_SCALE + idx, val);
}
static u32 _sde_hw_sspp_get_scaler3_ver(struct sde_hw_pipe *ctx) static u32 _sde_hw_sspp_get_scaler3_ver(struct sde_hw_pipe *ctx)
{ {
u32 idx; u32 idx;
@@ -1242,6 +1259,9 @@ static void _setup_layer_ops(struct sde_hw_pipe *c,
c->ops.setup_scaler = reg_dmav1_setup_vig_qseed3; c->ops.setup_scaler = reg_dmav1_setup_vig_qseed3;
} }
if (test_bit(SDE_SSPP_PREDOWNSCALE, &features))
c->ops.setup_pre_downscale = sde_hw_sspp_setup_pre_downscale;
if (test_bit(SDE_PERF_SSPP_SYS_CACHE, &perf_features)) if (test_bit(SDE_PERF_SSPP_SYS_CACHE, &perf_features))
c->ops.setup_sys_cache = sde_hw_sspp_setup_sys_cache; c->ops.setup_sys_cache = sde_hw_sspp_setup_sys_cache;

View File

@@ -516,6 +516,14 @@ struct sde_hw_sspp_ops {
struct sde_hw_scaler3_cfg *scaler3_cfg, struct sde_hw_scaler3_cfg *scaler3_cfg,
u32 offset); u32 offset);
/**
* setup_pre_downscale - setup pre-downscaler for inline rotation
* @ctx: Pointer to pipe context
* @pre_down: Pointer to pre-downscaler configuration
*/
void (*setup_pre_downscale)(struct sde_hw_pipe *ctx,
struct sde_hw_inline_pre_downscale_cfg *pre_down);
/** /**
* get_scaler_ver - get scaler h/w version * get_scaler_ver - get scaler h/w version
* @ctx: Pointer to pipe context * @ctx: Pointer to pipe context

View File

@@ -160,6 +160,13 @@ struct sde_hw_scaler3_lut_cfg {
size_t sep_len; size_t sep_len;
}; };
struct sde_hw_inline_pre_downscale_cfg {
u32 pre_downscale_x_0;
u32 pre_downscale_x_1;
u32 pre_downscale_y_0;
u32 pre_downscale_y_1;
};
u32 *sde_hw_util_get_log_mask_ptr(void); u32 *sde_hw_util_get_log_mask_ptr(void);
void sde_reg_write(struct sde_hw_blk_reg_map *c, void sde_reg_write(struct sde_hw_blk_reg_map *c,

View File

@@ -1512,6 +1512,10 @@ static void _sde_plane_setup_scaler(struct sde_plane *psde,
pe->btm_ftch[i] = pe->num_ext_pxls_btm[i]; 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_maxdwnscale_nrt ||
!psde->pipe_sblk->in_rot_maxheight || !psde->pipe_sblk->in_rot_maxheight ||
!psde->pipe_sblk->in_rot_format_list || !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, SDE_ERROR_PLANE(psde,
"wrong config rt:%d/%d nrt:%d fmt:%d h:%d 0x%x\n", "wrong config rt:%d/%d nrt:%d fmt:%d h:%d 0x%x\n",
!psde->pipe_sblk->in_rot_maxdwnscale_rt_num, !psde->pipe_sblk->in_rot_maxdwnscale_rt_num,
@@ -1787,7 +1791,7 @@ static void sde_plane_rot_install_properties(struct drm_plane *plane,
return; 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 | supported_rotations |= DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_90 |
DRM_MODE_ROTATE_180 | DRM_MODE_ROTATE_270; DRM_MODE_ROTATE_180 | DRM_MODE_ROTATE_270;
@@ -2269,6 +2273,12 @@ int sde_plane_validate_src_addr(struct drm_plane *plane,
return ret; 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, static int _sde_plane_validate_scaler_v2(struct sde_plane *psde,
struct sde_plane_state *pstate, struct sde_plane_state *pstate,
const struct sde_format *fmt, 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 src_w, uint32_t src_h,
uint32_t deci_w, uint32_t deci_h) uint32_t deci_w, uint32_t deci_h)
{ {
struct sde_hw_inline_pre_downscale_cfg *pd_cfg;
bool pre_down_en;
int i; int i;
if (!psde || !pstate || !fmt) { 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)) pstate->scaler_check_state != SDE_PLANE_SCLCHECK_SCALER_V2_CHECK))
return 0; 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; pstate->scaler_check_state = SDE_PLANE_SCLCHECK_INVALID;
for (i = 0; i < SDE_MAX_PLANES; i++) { 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 vert_req_pixels, vert_fetch_pixels;
uint32_t src_w_tmp, src_h_tmp; uint32_t src_w_tmp, src_h_tmp;
uint32_t scaler_w, scaler_h; uint32_t scaler_w, scaler_h;
uint32_t pre_down_ratio_x = 1, pre_down_ratio_y = 1;
bool rot; bool rot;
/* re-use color plane 1's config for plane 2 */ /* re-use color plane 1's config for plane 2 */
if (i == 2) if (i == 2)
continue; 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_w_tmp = src_w;
src_h_tmp = src_h; 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 * repeat/drop, src_width and src_height are only specified
* for Y and UV plane * for Y and UV plane
*/ */
if (i != 3 && (hor_req_pixels != scaler_w || if (i != 3 && (hor_req_pixels / pre_down_ratio_x != scaler_w ||
vert_req_pixels != scaler_h)) { vert_req_pixels / pre_down_ratio_y !=
scaler_h)) {
SDE_ERROR_PLANE(psde, 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], i, pstate->pixel_ext.roi_w[i],
pstate->pixel_ext.roi_h[i], pstate->pixel_ext.roi_h[i], scaler_w, scaler_h,
scaler_w, scaler_h, src_w, src_h, rot); src_w, src_h, rot, pre_down_ratio_x, pre_down_ratio_y);
return -EINVAL; return -EINVAL;
} }
@@ -2393,6 +2423,39 @@ static int _sde_plane_validate_scaler_v2(struct sde_plane *psde,
return 0; 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, static int _sde_atomic_check_decimation_scaler(struct drm_plane_state *state,
struct sde_plane *psde, const struct sde_format *fmt, struct sde_plane *psde, const struct sde_format *fmt,
struct sde_plane_state *pstate, struct sde_rect *src, 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 scaler_src_w, scaler_src_h;
uint32_t max_downscale_num, max_downscale_denom; uint32_t max_downscale_num, max_downscale_denom;
uint32_t max_upscale, max_linewidth; 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 *crtc;
struct drm_crtc_state *new_cstate; 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_upscale = psde->pipe_sblk->maxupscale;
max_linewidth = psde->pipe_sblk->maxlinewidth; 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; crtc = state->crtc;
new_cstate = drm_atomic_get_new_crtc_state(state->state, crtc); new_cstate = drm_atomic_get_new_crtc_state(state->state, crtc);
rt_client = sde_crtc_is_rt_client(crtc, new_cstate); rt_client = sde_crtc_is_rt_client(crtc, new_cstate);
max_downscale_num = psde->pipe_sblk->maxdwnscale;
max_downscale_denom = 1; max_downscale_denom = 1;
/* inline rotation RT clients have a different max downscaling limit */ /* inline rotation RT clients have a different max downscaling limit */
if (inline_rotation) { 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 = max_downscale_num =
psde->pipe_sblk->in_rot_maxdwnscale_rt_num; psde->pipe_sblk->in_rot_maxdwnscale_rt_num;
max_downscale_denom = max_downscale_denom =
@@ -2448,8 +2520,6 @@ static int _sde_atomic_check_decimation_scaler(struct drm_plane_state *state,
max_downscale_num = max_downscale_num =
psde->pipe_sblk->in_rot_maxdwnscale_nrt; psde->pipe_sblk->in_rot_maxdwnscale_nrt;
} }
} else {
max_downscale_num = psde->pipe_sblk->maxdwnscale;
} }
/* decimation validation */ /* 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", "invalid src w:%u, deci w:%u, line w:%u\n",
src->w, src_deci_w, max_linewidth); src->w, src_deci_w, max_linewidth);
ret = -E2BIG; ret = -E2BIG;
}
/* check max scaler capability */ /* 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) || ((scaler_src_h * max_upscale) < dst->h) ||
(((dst->w * max_downscale_num) / max_downscale_denom) (((dst->w * max_downscale_num) / max_downscale_denom)
< scaler_src_w) || < scaler_src_w) ||
(((dst->h * max_downscale_num) / max_downscale_denom) (((dst->h * max_downscale_num) / max_downscale_denom)
< scaler_src_h)) { < scaler_src_h)) {
SDE_ERROR_PLANE(psde, 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, scaler_src_w, scaler_src_h, dst->w, dst->h,
inline_rotation); inline_rotation, max_downscale_num,
max_downscale_denom);
ret = -E2BIG; 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, } else if (_sde_plane_validate_scaler_v2(psde, pstate, fmt,
width, height, width, height, src->w, src->h,
src->w, src->h, deci_w, deci_h)) { deci_w, deci_h)) {
ret = -EINVAL; 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)) if (psde->features & BIT(SDE_SSPP_BLOCK_SEC_UI))
sde_kms_info_add_keyint(info, "block_sec_ui", 1); 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; 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, sde_kms_info_add_keyint(info,
"true_inline_dwnscale_rt", "true_inline_dwnscale_rt",
(int) (psde->pipe_sblk->in_rot_maxdwnscale_rt_num / (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"); 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, static inline void _sde_plane_set_scaler_v2(struct sde_plane *psde,
struct sde_plane_state *pstate, void __user *usr) 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; struct sde_hw_pixel_ext *pe;
int i; int i;
struct sde_hw_scaler3_cfg *cfg; struct sde_hw_scaler3_cfg *cfg;
struct sde_hw_inline_pre_downscale_cfg *pd_cfg;
if (!psde || !pstate) { if (!psde || !pstate) {
SDE_ERROR("invalid argument(s)\n"); 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; cfg = &pstate->scaler3_cfg;
pd_cfg = &pstate->pre_down;
pstate->scaler_check_state = SDE_PLANE_SCLCHECK_NONE; pstate->scaler_check_state = SDE_PLANE_SCLCHECK_NONE;
if (!usr) { if (!usr) {
SDE_DEBUG_PLANE(psde, "scale data removed\n"); SDE_DEBUG_PLANE(psde, "scale data removed\n");
cfg->enable = 0; cfg->enable = 0;
_sde_plane_clear_predownscale_settings(pstate);
goto end; goto end;
} }
@@ -3799,12 +3890,20 @@ static inline void _sde_plane_set_scaler_v2(struct sde_plane *psde,
if (!scale_v2.enable) { if (!scale_v2.enable) {
SDE_DEBUG_PLANE(psde, "scale data removed\n"); SDE_DEBUG_PLANE(psde, "scale data removed\n");
cfg->enable = 0; cfg->enable = 0;
_sde_plane_clear_predownscale_settings(pstate);
goto end; goto end;
} }
/* populate from user space */ /* populate from user space */
sde_set_scaler_v2(cfg, &scale_v2); 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; pe = &pstate->pixel_ext;
memset(pe, 0, sizeof(struct sde_hw_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_root,
&psde->debugfs_default_scale); &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", debugfs_create_u32("in_rot_max_downscale_rt_num",
0600, 0600,
psde->debugfs_root, psde->debugfs_root,

View File

@@ -102,6 +102,7 @@ struct sde_plane_state {
struct sde_hw_scaler3_cfg scaler3_cfg; struct sde_hw_scaler3_cfg scaler3_cfg;
struct sde_hw_pixel_ext pixel_ext; struct sde_hw_pixel_ext pixel_ext;
enum sde_plane_sclcheck_state scaler_check_state; enum sde_plane_sclcheck_state scaler_check_state;
struct sde_hw_inline_pre_downscale_cfg pre_down;
/* @sc_cfg: system_cache configuration */ /* @sc_cfg: system_cache configuration */
struct sde_hw_pipe_sc_cfg sc_cfg; struct sde_hw_pipe_sc_cfg sc_cfg;