Merge "disp: msm: sde: add line insertion support for sspp"

This commit is contained in:
qctecmdr
2022-04-08 04:26:38 -07:00
committed by Gerrit - the friendly Code Review server
16 changed files with 420 additions and 1 deletions

View File

@@ -499,6 +499,8 @@ struct dsi_split_link_config {
* cmd it points to the line after TE. * cmd it points to the line after TE.
* @dma_sched_window: Determines the width of the window during the * @dma_sched_window: Determines the width of the window during the
* DSI command will be sent by the HW. * DSI command will be sent by the HW.
* @vpadding: panel stacking height.
* @line_insertion_enable: line insertion support enable.
*/ */
struct dsi_host_common_cfg { struct dsi_host_common_cfg {
enum dsi_pixel_format dst_format; enum dsi_pixel_format dst_format;
@@ -526,6 +528,8 @@ struct dsi_host_common_cfg {
u32 byte_intf_clk_div; u32 byte_intf_clk_div;
u32 dma_sched_line; u32 dma_sched_line;
u32 dma_sched_window; u32 dma_sched_window;
u32 vpadding;
bool line_insertion_enable;
}; };
/** /**

View File

@@ -641,6 +641,12 @@ int dsi_conn_get_mode_info(struct drm_connector *connector,
mode_info->qsync_min_fps = dsi_mode->timing.qsync_min_fps; mode_info->qsync_min_fps = dsi_mode->timing.qsync_min_fps;
mode_info->wd_jitter = dsi_mode->priv_info->wd_jitter; mode_info->wd_jitter = dsi_mode->priv_info->wd_jitter;
if (dsi_display->panel)
mode_info->vpadding = dsi_display->panel->host_config.vpadding;
if (mode_info->vpadding < drm_mode->vdisplay) {
mode_info->vpadding = 0;
dsi_display->panel->host_config.line_insertion_enable = 0;
}
memcpy(&mode_info->topology, &dsi_mode->priv_info->topology, memcpy(&mode_info->topology, &dsi_mode->priv_info->topology,
sizeof(struct msm_display_topology)); sizeof(struct msm_display_topology));

View File

@@ -1179,7 +1179,8 @@ static int dsi_panel_parse_misc_host_config(struct dsi_host_common_cfg *host,
host->dma_sched_window = 0; host->dma_sched_window = 0;
else else
host->dma_sched_window = window; host->dma_sched_window = window;
rc = utils->read_u32(utils->data, "qcom,vert-padding-value", &host->vpadding);
host->line_insertion_enable = (rc || host->vpadding <= 0) ? false : true;
DSI_DEBUG("[%s] DMA scheduling parameters Line: %d Window: %d\n", name, DSI_DEBUG("[%s] DMA scheduling parameters Line: %d Window: %d\n", name,
host->dma_sched_line, host->dma_sched_window); host->dma_sched_line, host->dma_sched_window);
return 0; return 0;

View File

@@ -800,6 +800,7 @@ struct msm_display_wd_jitter_config {
* @dyn_clk_list: List of dynamic clock rates for RFI. * @dyn_clk_list: List of dynamic clock rates for RFI.
* @qsync_min_fps: qsync min fps rate * @qsync_min_fps: qsync min fps rate
* @wd_jitter: Info for WD jitter. * @wd_jitter: Info for WD jitter.
* @vpadding: panel stacking height
*/ */
struct msm_mode_info { struct msm_mode_info {
uint32_t frame_rate; uint32_t frame_rate;
@@ -822,6 +823,7 @@ struct msm_mode_info {
struct msm_dyn_clk_list dyn_clk_list; struct msm_dyn_clk_list dyn_clk_list;
u32 qsync_min_fps; u32 qsync_min_fps;
struct msm_display_wd_jitter_config wd_jitter; struct msm_display_wd_jitter_config wd_jitter;
u32 vpadding;
}; };
/** /**

View File

@@ -3461,3 +3461,20 @@ int sde_connector_event_notify(struct drm_connector *connector, uint32_t type,
return ret; return ret;
} }
bool sde_connector_is_line_insertion_supported(struct sde_connector *sde_conn)
{
struct dsi_display *display = NULL;
if (!sde_conn)
return false;
if (sde_conn->connector_type != DRM_MODE_CONNECTOR_DSI)
return false;
display = (struct dsi_display *)sde_conn->display;
if (!display || !display->panel)
return false;
return display->panel->host_config.line_insertion_enable;
}

View File

@@ -1275,4 +1275,12 @@ int sde_connector_esd_status(struct drm_connector *connector);
const char *sde_conn_get_topology_name(struct drm_connector *conn, const char *sde_conn_get_topology_name(struct drm_connector *conn,
struct msm_display_topology topology); struct msm_display_topology topology);
/*
* sde_connector_is_line_insertion_supported - get line insertion
* feature bit value from panel
* @sde_conn: Pointer to sde connector structure
* @Return: line insertion support status
*/
bool sde_connector_is_line_insertion_supported(struct sde_connector *sde_conn);
#endif /* _SDE_CONNECTOR_H_ */ #endif /* _SDE_CONNECTOR_H_ */

View File

@@ -795,6 +795,22 @@ static void _sde_crtc_setup_blend_cfg(struct sde_crtc_mixer *mixer,
format->alpha_enable, fg_alpha, bg_alpha, blend_op); format->alpha_enable, fg_alpha, bg_alpha, blend_op);
} }
static void _sde_crtc_calc_split_dim_layer_yh_param(struct drm_crtc *crtc, u16 *y, u16 *h)
{
u32 padding_y = 0, padding_start = 0, padding_height = 0;
struct sde_crtc_state *cstate;
cstate = to_sde_crtc_state(crtc->state);
if (!cstate->line_insertion.panel_line_insertion_enable)
return;
sde_crtc_calc_vpadding_param(crtc->state, *y, *h, &padding_y,
&padding_start, &padding_height);
*y = padding_y;
*h = padding_height;
}
static void _sde_crtc_setup_dim_layer_cfg(struct drm_crtc *crtc, static void _sde_crtc_setup_dim_layer_cfg(struct drm_crtc *crtc,
struct sde_crtc *sde_crtc, struct sde_crtc_mixer *mixer, struct sde_crtc *sde_crtc, struct sde_crtc_mixer *mixer,
struct sde_hw_dim_layer *dim_layer) struct sde_hw_dim_layer *dim_layer)
@@ -853,6 +869,11 @@ static void _sde_crtc_setup_dim_layer_cfg(struct drm_crtc *crtc,
cstate->lm_roi[i].y; cstate->lm_roi[i].y;
} }
/* update dim layer rect for panel stacking crtc */
if (cstate->line_insertion.padding_height)
_sde_crtc_calc_split_dim_layer_yh_param(crtc, &split_dim_layer.rect.y,
&split_dim_layer.rect.h);
SDE_EVT32(DRMID(crtc), dim_layer->stage, SDE_EVT32(DRMID(crtc), dim_layer->stage,
cstate->lm_roi[i].x, cstate->lm_roi[i].x,
cstate->lm_roi[i].y, cstate->lm_roi[i].y,
@@ -1394,6 +1415,100 @@ static int _sde_crtc_check_rois(struct drm_crtc *crtc,
return 0; return 0;
} }
static u32 _sde_crtc_calc_gcd(u32 a, u32 b)
{
if (b == 0)
return a;
return _sde_crtc_calc_gcd(b, a % b);
}
static int _sde_crtc_check_panel_stacking(struct drm_crtc *crtc, struct drm_crtc_state *state)
{
struct sde_kms *kms;
struct sde_crtc *sde_crtc;
struct sde_crtc_state *sde_crtc_state;
struct drm_connector *conn;
struct msm_mode_info mode_info;
struct drm_display_mode *adj_mode = &state->adjusted_mode;
struct msm_sub_mode sub_mode;
u32 gcd = 0, num_of_active_lines = 0, num_of_dummy_lines = 0;
int rc;
struct drm_encoder *encoder;
const u32 max_encoder_cnt = 1;
u32 encoder_cnt = 0;
kms = _sde_crtc_get_kms(crtc);
if (!kms || !kms->catalog) {
SDE_ERROR("invalid kms\n");
return -EINVAL;
}
sde_crtc = to_sde_crtc(crtc);
sde_crtc_state = to_sde_crtc_state(state);
/* panel stacking only support single connector */
drm_for_each_encoder_mask(encoder, crtc->dev, state->encoder_mask)
encoder_cnt++;
if (!kms->catalog->has_line_insertion || !state->mode_changed ||
encoder_cnt > max_encoder_cnt) {
SDE_DEBUG("no line insertion support mode change %d enc cnt %d\n",
state->mode_changed, encoder_cnt);
sde_crtc_state->line_insertion.padding_height = 0;
return 0;
}
conn = sde_crtc_state->connectors[0];
rc = sde_connector_get_mode_info(conn, adj_mode, &sub_mode, &mode_info);
if (rc) {
SDE_ERROR("failed to get mode info %d\n", rc);
return -EINVAL;
}
if (!mode_info.vpadding) {
sde_crtc_state->line_insertion.padding_height = 0;
return 0;
}
if (mode_info.vpadding < state->mode.vdisplay) {
SDE_ERROR("padding height %d is less than vdisplay %d\n",
mode_info.vpadding, state->mode.vdisplay);
return -EINVAL;
} else if (mode_info.vpadding == state->mode.vdisplay) {
SDE_DEBUG("padding height %d is equal to the vdisplay %d\n",
mode_info.vpadding, state->mode.vdisplay);
sde_crtc_state->line_insertion.padding_height = 0;
return 0;
} else if (mode_info.vpadding == sde_crtc_state->line_insertion.padding_height) {
return 0; /* skip calculation if already cached */
}
gcd = _sde_crtc_calc_gcd(mode_info.vpadding, state->mode.vdisplay);
if (!gcd) {
SDE_ERROR("zero gcd found for padding height %d %d\n",
mode_info.vpadding, state->mode.vdisplay);
return -EINVAL;
}
num_of_active_lines = state->mode.vdisplay;
do_div(num_of_active_lines, gcd);
num_of_dummy_lines = mode_info.vpadding;
do_div(num_of_dummy_lines, gcd);
num_of_dummy_lines = num_of_dummy_lines - num_of_active_lines;
if (num_of_active_lines > MAX_VPADDING_RATIO_M ||
num_of_dummy_lines > MAX_VPADDING_RATIO_N) {
SDE_ERROR("unsupported panel stacking pattern %d:%d", num_of_active_lines,
num_of_dummy_lines);
return -EINVAL;
}
sde_crtc_state->line_insertion.padding_active = num_of_active_lines;
sde_crtc_state->line_insertion.padding_dummy = num_of_dummy_lines;
sde_crtc_state->line_insertion.padding_height = mode_info.vpadding;
return 0;
}
static void _sde_crtc_program_lm_output_roi(struct drm_crtc *crtc) static void _sde_crtc_program_lm_output_roi(struct drm_crtc *crtc)
{ {
struct sde_crtc *sde_crtc; struct sde_crtc *sde_crtc;
@@ -3587,6 +3702,26 @@ static void _sde_crtc_setup_mixer_for_encoder(
} }
} }
bool sde_crtc_is_line_insertion_supported(struct drm_crtc *crtc)
{
struct drm_encoder *enc = NULL;
struct sde_kms *kms;
if (!crtc)
return false;
kms = _sde_crtc_get_kms(crtc);
if (!kms->catalog->has_line_insertion)
return false;
list_for_each_entry(enc, &crtc->dev->mode_config.encoder_list, head) {
if (enc->crtc == crtc)
return sde_encoder_is_line_insertion_supported(enc);
}
return false;
}
static void _sde_crtc_setup_mixers(struct drm_crtc *crtc) static void _sde_crtc_setup_mixers(struct drm_crtc *crtc)
{ {
struct sde_crtc *sde_crtc = to_sde_crtc(crtc); struct sde_crtc *sde_crtc = to_sde_crtc(crtc);
@@ -4821,6 +4956,8 @@ static void sde_crtc_enable(struct drm_crtc *crtc,
SDE_DEBUG("crtc%d\n", crtc->base.id); SDE_DEBUG("crtc%d\n", crtc->base.id);
SDE_EVT32_VERBOSE(DRMID(crtc)); SDE_EVT32_VERBOSE(DRMID(crtc));
sde_crtc = to_sde_crtc(crtc); sde_crtc = to_sde_crtc(crtc);
cstate->line_insertion.panel_line_insertion_enable =
sde_crtc_is_line_insertion_supported(crtc);
/* /*
* Avoid drm_crtc_vblank_on during seamless DMS case * Avoid drm_crtc_vblank_on during seamless DMS case
@@ -5639,6 +5776,13 @@ static int _sde_crtc_atomic_check(struct drm_crtc *crtc,
crtc->base.id, rc); crtc->base.id, rc);
goto end; goto end;
} }
rc = _sde_crtc_check_panel_stacking(crtc, state);
if (rc) {
SDE_ERROR("crtc%d failed panel stacking check %d\n",
crtc->base.id, rc);
goto end;
}
end: end:
kfree(pstates); kfree(pstates);
kfree(multirect_plane); kfree(multirect_plane);
@@ -7876,3 +8020,46 @@ void _sde_crtc_vm_release_notify(struct drm_crtc *crtc)
sde_crtc_event_notify(crtc, DRM_EVENT_VM_RELEASE, &val, sizeof(uint32_t)); sde_crtc_event_notify(crtc, DRM_EVENT_VM_RELEASE, &val, sizeof(uint32_t));
} }
void sde_crtc_calc_vpadding_param(struct drm_crtc_state *state, u32 crtc_y, uint32_t crtc_h,
u32 *padding_y, u32 *padding_start, u32 *padding_height)
{
struct sde_kms *kms;
struct sde_crtc_state *cstate = to_sde_crtc_state(state);
u32 y_remain, y_start, y_end;
u32 m, n;
kms = _sde_crtc_get_kms(state->crtc);
if (!kms || !kms->catalog) {
SDE_ERROR("invalid kms or catalog\n");
return;
}
if (!kms->catalog->has_line_insertion)
return;
if (!cstate->line_insertion.padding_active) {
SDE_ERROR("zero padding active value\n");
return;
}
/*
* Computation logic to add number of dummy and active line at
* precise position on display
*/
m = cstate->line_insertion.padding_active;
n = m + cstate->line_insertion.padding_dummy;
if (m == 0)
return;
y_remain = crtc_y % m;
y_start = y_remain + crtc_y / m * n;
y_end = (((crtc_y + crtc_h - 1) / m) * n) + ((crtc_y + crtc_h - 1) % m);
*padding_y = y_start;
*padding_start = m - y_remain;
*padding_height = y_end - y_start + 1;
SDE_EVT32(DRMID(cstate->base.crtc), y_remain, y_start, y_end, *padding_y, *padding_start,
*padding_height);
SDE_DEBUG("crtc:%d padding_y:%d padding_start:%d padding_height:%d\n",
DRMID(cstate->base.crtc), *padding_y, *padding_start, *padding_height);
}

View File

@@ -432,6 +432,20 @@ enum sde_crtc_dirty_flags {
#define to_sde_crtc(x) container_of(x, struct sde_crtc, base) #define to_sde_crtc(x) container_of(x, struct sde_crtc, base)
/**
* struct sde_line_insertion_param - sde line insertion parameters
* @panel_line_insertion_enable: line insertion support status
* @padding_height: panel height after line padding
* @padding_active: active lines in panel stacking pattern
* @padding_dummy: dummy lines in panel stacking pattern
*/
struct sde_line_insertion_param {
bool panel_line_insertion_enable;
u32 padding_height;
u32 padding_active;
u32 padding_dummy;
};
/** /**
* struct sde_crtc_state - sde container for atomic crtc state * struct sde_crtc_state - sde container for atomic crtc state
* @base: Base drm crtc state structure * @base: Base drm crtc state structure
@@ -467,6 +481,7 @@ enum sde_crtc_dirty_flags {
* @cp_dirty_list: array tracking features that are dirty * @cp_dirty_list: array tracking features that are dirty
* @cp_range_payload: array storing state user_data passed via range props * @cp_range_payload: array storing state user_data passed via range props
* @cont_splash_populated: State was populated as part of cont. splash * @cont_splash_populated: State was populated as part of cont. splash
* @param: sde line insertion parameters
*/ */
struct sde_crtc_state { struct sde_crtc_state {
struct drm_crtc_state base; struct drm_crtc_state base;
@@ -506,6 +521,7 @@ struct sde_crtc_state {
struct sde_cp_crtc_range_prop_payload struct sde_cp_crtc_range_prop_payload
cp_range_payload[SDE_CP_CRTC_MAX_FEATURES]; cp_range_payload[SDE_CP_CRTC_MAX_FEATURES];
bool cont_splash_populated; bool cont_splash_populated;
struct sde_line_insertion_param line_insertion;
}; };
enum sde_crtc_irq_state { enum sde_crtc_irq_state {
@@ -1073,4 +1089,24 @@ struct drm_encoder *sde_crtc_get_src_encoder_of_clone(struct drm_crtc *crtc);
*/ */
void _sde_crtc_vm_release_notify(struct drm_crtc *crtc); void _sde_crtc_vm_release_notify(struct drm_crtc *crtc);
/*
* sde_crtc_is_line_insertion_supported - get lineinsertion
* feature bit value from panel
* @drm_crtc: Pointer to drm crtc structure
* @Return: line insertion support status
*/
bool sde_crtc_is_line_insertion_supported(struct drm_crtc *crtc);
/**
* sde_crtc_calc_vpadding_param - calculate vpadding parameters
* @state: Pointer to DRM crtc state object
* @crtc_y: Plane's CRTC_Y offset
* @crtc_h: Plane's CRTC_H size
* @padding_y: Padding Y offset
* @padding_start: Padding start offset
* @padding_height: Padding height in total
*/
void sde_crtc_calc_vpadding_param(struct drm_crtc_state *state, u32 crtc_y, u32 crtc_h,
u32 *padding_y, u32 *padding_start, u32 *padding_height);
#endif /* _SDE_CRTC_H_ */ #endif /* _SDE_CRTC_H_ */

View File

@@ -1069,6 +1069,32 @@ static int _sde_encoder_atomic_check_reserve(struct drm_encoder *drm_enc,
return ret; return ret;
} }
bool sde_encoder_is_line_insertion_supported(struct drm_encoder *drm_enc)
{
struct sde_connector *sde_conn = NULL;
struct sde_kms *sde_kms = NULL;
struct drm_connector *conn = NULL;
if (!drm_enc) {
SDE_ERROR("invalid drm encoder\n");
return false;
}
sde_kms = sde_encoder_get_kms(drm_enc);
if (!sde_kms)
return false;
conn = sde_encoder_get_connector(sde_kms->dev, drm_enc);
if (!conn || !conn->state)
return false;
sde_conn = to_sde_connector(conn);
if (!sde_conn)
return false;
return sde_connector_is_line_insertion_supported(sde_conn);
}
static void _sde_encoder_get_qsync_fps_callback(struct drm_encoder *drm_enc, static void _sde_encoder_get_qsync_fps_callback(struct drm_encoder *drm_enc,
u32 *qsync_fps, struct drm_connector_state *conn_state) u32 *qsync_fps, struct drm_connector_state *conn_state)
{ {

View File

@@ -683,5 +683,13 @@ static inline bool sde_encoder_is_widebus_enabled(struct drm_encoder *drm_enc)
return sde_enc->mode_info.wide_bus_en; return sde_enc->mode_info.wide_bus_en;
} }
/*
* sde_encoder_is_line_insertion_supported - get line insertion
* feature bit value from panel
* @drm_enc: Pointer to drm encoder structure
* @Return: line insertion support status
*/
bool sde_encoder_is_line_insertion_supported(struct drm_encoder *drm_enc);
void sde_encoder_add_data_to_minidump_va(struct drm_encoder *drm_enc); void sde_encoder_add_data_to_minidump_va(struct drm_encoder *drm_enc);
#endif /* __SDE_ENCODER_H__ */ #endif /* __SDE_ENCODER_H__ */

View File

@@ -1820,6 +1820,8 @@ static void sde_sspp_set_features(struct sde_mdss_cfg *sde_cfg,
sblk->maxlinewidth = sde_cfg->max_sspp_linewidth; sblk->maxlinewidth = sde_cfg->max_sspp_linewidth;
if (sde_cfg->has_line_insertion)
set_bit(SDE_SSPP_LINE_INSERTION, &sspp->features);
sblk->smart_dma_priority = sblk->smart_dma_priority =
PROP_VALUE_ACCESS(props->values, SSPP_SMART_DMA, i); PROP_VALUE_ACCESS(props->values, SSPP_SMART_DMA, i);
if (sblk->smart_dma_priority && sde_cfg->smart_dma_rev) if (sblk->smart_dma_priority && sde_cfg->smart_dma_rev)
@@ -5161,6 +5163,7 @@ static int _sde_hardware_pre_caps(struct sde_mdss_cfg *sde_cfg, uint32_t hw_rev)
sde_cfg->demura_supported[SSPP_DMA1][1] = 1; sde_cfg->demura_supported[SSPP_DMA1][1] = 1;
sde_cfg->demura_supported[SSPP_DMA3][0] = 0; sde_cfg->demura_supported[SSPP_DMA3][0] = 0;
sde_cfg->demura_supported[SSPP_DMA3][1] = 1; sde_cfg->demura_supported[SSPP_DMA3][1] = 1;
sde_cfg->has_line_insertion = true;
} else { } else {
SDE_ERROR("unsupported chipset id:%X\n", hw_rev); SDE_ERROR("unsupported chipset id:%X\n", hw_rev);
sde_cfg->perf.min_prefill_lines = 0xffff; sde_cfg->perf.min_prefill_lines = 0xffff;

View File

@@ -199,6 +199,10 @@ enum {
#define SYS_CACHE_OP_TYPE BIT(3) #define SYS_CACHE_OP_TYPE BIT(3)
#define SYS_CACHE_NO_ALLOC BIT(4) #define SYS_CACHE_NO_ALLOC BIT(4)
/* default line padding ratio limitation */
#define MAX_VPADDING_RATIO_M 93
#define MAX_VPADDING_RATIO_N 45
/** /**
* sde_sys_cache_type: Types of system cache supported * sde_sys_cache_type: Types of system cache supported
* SDE_SYS_CACHE_DISP: Static img system cache * SDE_SYS_CACHE_DISP: Static img system cache
@@ -305,6 +309,7 @@ enum {
* @SDE_SSPP_FP16_UNMULT FP16 alpha unmult color processing block support * @SDE_SSPP_FP16_UNMULT FP16 alpha unmult color processing block support
* @SDE_SSPP_UBWC_STATS: Support for ubwc stats * @SDE_SSPP_UBWC_STATS: Support for ubwc stats
* @SDE_SSPP_SCALER_DE_LPF_BLEND: Support for detail enhancer * @SDE_SSPP_SCALER_DE_LPF_BLEND: Support for detail enhancer
* @SDE_SSPP_LINE_INSERTION Line insertion support
* @SDE_SSPP_MAX maximum value * @SDE_SSPP_MAX maximum value
*/ */
enum { enum {
@@ -341,6 +346,7 @@ enum {
SDE_SSPP_FP16_UNMULT, SDE_SSPP_FP16_UNMULT,
SDE_SSPP_UBWC_STATS, SDE_SSPP_UBWC_STATS,
SDE_SSPP_SCALER_DE_LPF_BLEND, SDE_SSPP_SCALER_DE_LPF_BLEND,
SDE_SSPP_LINE_INSERTION,
SDE_SSPP_MAX SDE_SSPP_MAX
}; };
@@ -1826,6 +1832,7 @@ struct sde_perf_cfg {
* @perf performance control settings * @perf performance control settings
* @uidle_cfg settings for uidle feature * @uidle_cfg settings for uidle feature
* @irq_offset_list list of sde_intr_irq_offsets to initialize irq table * @irq_offset_list list of sde_intr_irq_offsets to initialize irq table
* @has_line_insertion line insertion support status
* @features bitmap of supported SDE_FEATUREs * @features bitmap of supported SDE_FEATUREs
* @dma_formats supported formats for dma pipe * @dma_formats supported formats for dma pipe
* @vig_formats supported formats for vig pipe * @vig_formats supported formats for vig pipe
@@ -1940,6 +1947,7 @@ struct sde_mdss_cfg {
struct sde_uidle_cfg uidle_cfg; struct sde_uidle_cfg uidle_cfg;
struct list_head irq_offset_list; struct list_head irq_offset_list;
DECLARE_BITMAP(features, SDE_FEATURE_MAX); DECLARE_BITMAP(features, SDE_FEATURE_MAX);
bool has_line_insertion;
/* Supported Pixel Format Lists */ /* Supported Pixel Format Lists */
struct sde_format_extended *dma_formats; struct sde_format_extended *dma_formats;

View File

@@ -44,6 +44,8 @@
#define SSPP_SRC_CONSTANT_COLOR_REC1 0x180 #define SSPP_SRC_CONSTANT_COLOR_REC1 0x180
#define SSPP_EXCL_REC_SIZE_REC1 0x184 #define SSPP_EXCL_REC_SIZE_REC1 0x184
#define SSPP_EXCL_REC_XY_REC1 0x188 #define SSPP_EXCL_REC_XY_REC1 0x188
#define SSPP_LINE_INSERTION_CTRL_REC1 0x1E4
#define SSPP_LINE_INSERTION_OUT_SIZE_REC1 0x1EC
#define SSPP_UIDLE_CTRL_VALUE 0x1f0 #define SSPP_UIDLE_CTRL_VALUE 0x1f0
#define SSPP_UIDLE_CTRL_VALUE_REC1 0x1f4 #define SSPP_UIDLE_CTRL_VALUE_REC1 0x1f4
@@ -116,6 +118,8 @@
#define SSPP_TRAFFIC_SHAPER_BPC_MAX 0xFF #define SSPP_TRAFFIC_SHAPER_BPC_MAX 0xFF
#define SSPP_CLK_CTRL 0x330 #define SSPP_CLK_CTRL 0x330
#define SSPP_CLK_STATUS 0x334 #define SSPP_CLK_STATUS 0x334
#define SSPP_LINE_INSERTION_CTRL 0x1E0
#define SSPP_LINE_INSERTION_OUT_SIZE 0x1E8
/* SSPP_QOS_CTRL */ /* SSPP_QOS_CTRL */
#define SSPP_QOS_CTRL_VBLANK_EN BIT(16) #define SSPP_QOS_CTRL_VBLANK_EN BIT(16)
@@ -1442,6 +1446,37 @@ static int sde_hw_sspp_get_clk_ctrl_status(struct sde_hw_blk_reg_map *hw,
return 0; return 0;
} }
static void sde_hw_sspp_setup_line_insertion(struct sde_hw_pipe *ctx,
enum sde_sspp_multirect_index rect_index,
struct sde_hw_pipe_line_insertion_cfg *cfg)
{
struct sde_hw_blk_reg_map *c;
u32 ctl_off = 0, size_off = 0, ctl_val = 0;
u32 idx;
if (_sspp_subblk_offset(ctx, SDE_SSPP_SRC, &idx) || !cfg)
return;
c = &ctx->hw;
if (rect_index == SDE_SSPP_RECT_SOLO || rect_index == SDE_SSPP_RECT_0) {
ctl_off = SSPP_LINE_INSERTION_CTRL;
size_off = SSPP_LINE_INSERTION_OUT_SIZE;
} else {
ctl_off = SSPP_LINE_INSERTION_CTRL_REC1;
size_off = SSPP_LINE_INSERTION_OUT_SIZE_REC1;
}
if (cfg->enable)
ctl_val = BIT(31) |
(cfg->dummy_lines << 16) |
(cfg->first_active_lines << 8) |
(cfg->active_lines);
SDE_REG_WRITE(c, ctl_off, ctl_val);
SDE_REG_WRITE(c, size_off, cfg->dst_h << 16);
}
static void _setup_layer_ops(struct sde_hw_pipe *c, static void _setup_layer_ops(struct sde_hw_pipe *c,
unsigned long features, unsigned long perf_features, unsigned long features, unsigned long perf_features,
bool is_virtual_pipe) bool is_virtual_pipe)
@@ -1536,6 +1571,8 @@ static void _setup_layer_ops(struct sde_hw_pipe *c,
c->ops.set_ubwc_stats_roi = sde_hw_sspp_ubwc_stats_set_roi; c->ops.set_ubwc_stats_roi = sde_hw_sspp_ubwc_stats_set_roi;
c->ops.get_ubwc_stats_data = sde_hw_sspp_ubwc_stats_get_data; c->ops.get_ubwc_stats_data = sde_hw_sspp_ubwc_stats_get_data;
} }
if (test_bit(SDE_SSPP_LINE_INSERTION, &features))
c->ops.setup_line_insertion = sde_hw_sspp_setup_line_insertion;
} }
static struct sde_sspp_cfg *_sspp_offset(enum sde_sspp sspp, static struct sde_sspp_cfg *_sspp_offset(enum sde_sspp sspp,

View File

@@ -291,6 +291,22 @@ struct sde_hw_pipe_ts_cfg {
*/ */
#define SDE_PIPE_SBUF_PLANE_NUM 2 #define SDE_PIPE_SBUF_PLANE_NUM 2
/**
* struct sde_hw_pipe_line_insertion_cfg - line insertion config
* @enable: line insertion is enabled
* @dummy_lines: dummy lines before active lines
* @first_active_lines: number of active lines before first dummy lines
* @active_lines: active lines
* @dst_h: total active lines plus dummy lines
*/
struct sde_hw_pipe_line_insertion_cfg {
bool enable;
u32 dummy_lines;
u32 first_active_lines;
u32 active_lines;
u32 dst_h;
};
/** /**
* struct sde_hw_sspp_ops - interface to the SSPP Hw driver functions * struct sde_hw_sspp_ops - interface to the SSPP Hw driver functions
* Caller must call the init function to get the pipe context for each pipe * Caller must call the init function to get the pipe context for each pipe
@@ -688,6 +704,15 @@ struct sde_hw_sspp_ops {
*/ */
void (*setup_fp16_unmult)(struct sde_hw_pipe *ctx, void (*setup_fp16_unmult)(struct sde_hw_pipe *ctx,
enum sde_sspp_multirect_index index, void *data); enum sde_sspp_multirect_index index, void *data);
/**
* setup_line_insertion - setup line insertion
* @ctx: Pointer to pipe context
* @cfg: Pointer to line insertion configuration
*/
void (*setup_line_insertion)(struct sde_hw_pipe *ctx,
enum sde_sspp_multirect_index index,
struct sde_hw_pipe_line_insertion_cfg *cfg);
}; };
/** /**

View File

@@ -188,6 +188,45 @@ static struct sde_hw_ctl *_sde_plane_get_hw_ctl(const struct drm_plane *plane)
return ctl; return ctl;
} }
static void _sde_plane_setup_panel_stacking(struct sde_plane *psde,
struct sde_plane_state *pstate)
{
struct sde_hw_pipe_line_insertion_cfg *cfg;
struct sde_crtc_state *cstate;
u32 h_start = 0, h_total = 0, y_start = 0;
struct drm_plane_state *dpstate = NULL;
struct drm_crtc *drm_crtc = NULL;
if (!psde || !psde->base.state || !psde->base.state->crtc) {
SDE_ERROR("Invalid plane psde %p or drm plane state or drm crtc\n", psde);
return;
}
dpstate = psde->base.state;
drm_crtc = dpstate->crtc;
cstate = to_sde_crtc_state(drm_crtc->state);
pstate->lineinsertion_feature = cstate->line_insertion.panel_line_insertion_enable;
if ((!test_bit(SDE_SSPP_LINE_INSERTION, (unsigned long *)&psde->features)) ||
!cstate->line_insertion.panel_line_insertion_enable)
return;
cfg = &pstate->line_insertion_cfg;
memset(cfg, 0, sizeof(*cfg));
if (!cstate->line_insertion.padding_height)
return;
sde_crtc_calc_vpadding_param(psde->base.state->crtc->state,
pstate->base.crtc_y, pstate->base.crtc_h,
&y_start, &h_start, &h_total);
cfg->enable = true;
cfg->dummy_lines = cstate->line_insertion.padding_dummy;
cfg->active_lines = cstate->line_insertion.padding_active;
cfg->first_active_lines = h_start;
cfg->dst_h = h_total;
psde->pipe_cfg.dst_rect.y += y_start - pstate->base.crtc_y;
}
static bool sde_plane_enabled(const struct drm_plane_state *state) static bool sde_plane_enabled(const struct drm_plane_state *state)
{ {
return state && state->fb && state->crtc; return state && state->fb && state->crtc;
@@ -3094,6 +3133,8 @@ static void _sde_plane_update_roi_config(struct drm_plane *plane,
_sde_plane_setup_scaler(psde, pstate, fmt, false); _sde_plane_setup_scaler(psde, pstate, fmt, false);
_sde_plane_setup_panel_stacking(psde, pstate);
/* check for color fill */ /* check for color fill */
psde->color_fill = (uint32_t)sde_plane_get_property(pstate, psde->color_fill = (uint32_t)sde_plane_get_property(pstate,
PLANE_PROP_COLOR_FILL); PLANE_PROP_COLOR_FILL);
@@ -3137,6 +3178,11 @@ static void _sde_plane_update_roi_config(struct drm_plane *plane,
true, true,
pstate->multirect_index, pstate->multirect_index,
pstate->multirect_mode); pstate->multirect_mode);
/* update line insertion */
if (pstate->lineinsertion_feature && psde->pipe_hw->ops.setup_line_insertion)
psde->pipe_hw->ops.setup_line_insertion(psde->pipe_hw,
pstate->multirect_index,
&pstate->line_insertion_cfg);
} }
static void _sde_plane_update_format_and_rects(struct sde_plane *psde, static void _sde_plane_update_format_and_rects(struct sde_plane *psde,

View File

@@ -1,4 +1,5 @@
/* /*
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
* Copyright (c) 2015-2021, The Linux Foundation. All rights reserved. * Copyright (c) 2015-2021, The Linux Foundation. All rights reserved.
* Copyright (C) 2013 Red Hat * Copyright (C) 2013 Red Hat
* Author: Rob Clark <robdclark@gmail.com> * Author: Rob Clark <robdclark@gmail.com>
@@ -112,6 +113,8 @@ enum sde_plane_sclcheck_state {
* @cdp_cfg: CDP configuration * @cdp_cfg: CDP configuration
* @cont_splash_populated: State was populated as part of cont. splash * @cont_splash_populated: State was populated as part of cont. splash
* @ubwc_stats_roi: cached roi for ubwc stats * @ubwc_stats_roi: cached roi for ubwc stats
* @line_insertion_cfg: line insertion configuration
* @lineinsertion_feature: panel line insertion feature
*/ */
struct sde_plane_state { struct sde_plane_state {
struct drm_plane_state base; struct drm_plane_state base;
@@ -147,6 +150,8 @@ struct sde_plane_state {
bool cont_splash_populated; bool cont_splash_populated;
struct sde_drm_ubwc_stats_roi ubwc_stats_roi; struct sde_drm_ubwc_stats_roi ubwc_stats_roi;
struct sde_hw_pipe_line_insertion_cfg line_insertion_cfg;
bool lineinsertion_feature;
}; };
/** /**