Merge "disp: msm: sde: adjust DSC encoders to support all 4LM topologies"

This commit is contained in:
qctecmdr
2020-06-09 23:42:42 -07:00
committed by Gerrit - the friendly Code Review server
11 fájl változott, egészen pontosan 189 új sor hozzáadva és 62 régi sor törölve

Fájl megtekintése

@@ -364,6 +364,9 @@ struct msm_roi_caps {
* @det_thresh_flatness: Flatness threshold.
* @extra_width: Extra width required in timing calculations.
* @pps_delay_ms: Post PPS command delay in milliseconds.
* @dsc_4hsmerge_en: Using DSC 4HS merge topology
* @dsc_4hsmerge_padding 4HS merge DSC pair padding value in bytes
* @dsc_4hsmerge_alignment 4HS merge DSC alignment value in bytes
*/
struct msm_display_dsc_info {
struct drm_dsc_config config;
@@ -382,6 +385,9 @@ struct msm_display_dsc_info {
int det_thresh_flatness;
u32 extra_width;
u32 pps_delay_ms;
bool dsc_4hsmerge_en;
u32 dsc_4hsmerge_padding;
u32 dsc_4hsmerge_alignment;
};

Fájl megtekintése

@@ -678,25 +678,6 @@ static int _sde_crtc_set_roi_v1(struct drm_crtc_state *state,
return 0;
}
static bool _sde_crtc_setup_is_3dmux_dsc(struct drm_crtc_state *state)
{
int i;
struct sde_crtc_state *cstate;
bool is_3dmux_dsc = false;
cstate = to_sde_crtc_state(state);
for (i = 0; i < cstate->num_connectors; i++) {
struct drm_connector *conn = cstate->connectors[i];
if (sde_connector_get_topology_name(conn) ==
SDE_RM_TOPOLOGY_DUALPIPE_3DMERGE_DSC)
is_3dmux_dsc = true;
}
return is_3dmux_dsc;
}
static int _sde_crtc_set_crtc_roi(struct drm_crtc *crtc,
struct drm_crtc_state *state)
{
@@ -836,6 +817,7 @@ static int _sde_crtc_check_autorefresh(struct drm_crtc *crtc,
static int _sde_crtc_set_lm_roi(struct drm_crtc *crtc,
struct drm_crtc_state *state, int lm_idx)
{
struct sde_kms *sde_kms;
struct sde_crtc *sde_crtc;
struct sde_crtc_state *crtc_state;
const struct sde_rect *crtc_roi;
@@ -845,6 +827,12 @@ static int _sde_crtc_set_lm_roi(struct drm_crtc *crtc,
if (!crtc || !state || lm_idx >= ARRAY_SIZE(crtc_state->lm_bounds))
return -EINVAL;
sde_kms = _sde_crtc_get_kms(crtc);
if (!sde_kms || !sde_kms->catalog) {
SDE_ERROR("invalid parameters\n");
return -EINVAL;
}
sde_crtc = to_sde_crtc(crtc);
crtc_state = to_sde_crtc_state(state);
crtc_roi = &crtc_state->crtc_roi;
@@ -864,7 +852,7 @@ static int _sde_crtc_set_lm_roi(struct drm_crtc *crtc,
* hence, crtc roi must match the mixer dimensions.
*/
if (crtc_state->num_ds_enabled ||
_sde_crtc_setup_is_3dmux_dsc(state)) {
sde_rm_topology_is_3dmux_dsc(&sde_kms->rm, state)) {
if (memcmp(lm_roi, lm_bounds, sizeof(struct sde_rect))) {
SDE_ERROR("Unsupported: Dest scaler/3d mux DSC + PU\n");
return -EINVAL;

Fájl megtekintése

@@ -71,12 +71,6 @@
/* Maximum number of VSYNC wait attempts for RSC state transition */
#define MAX_RSC_WAIT 5
#define TOPOLOGY_DUALPIPE_MERGE_MODE(x) \
(((x) == SDE_RM_TOPOLOGY_DUALPIPE_DSCMERGE) || \
((x) == SDE_RM_TOPOLOGY_DUALPIPE_3DMERGE) || \
((x) == SDE_RM_TOPOLOGY_DUALPIPE_3DMERGE_VDC) || \
((x) == SDE_RM_TOPOLOGY_DUALPIPE_3DMERGE_DSC))
/**
* enum sde_enc_rc_events - events for resource control state machine
* @SDE_ENC_RC_EVENT_KICKOFF:
@@ -2215,6 +2209,7 @@ static void sde_encoder_virt_mode_set(struct drm_encoder *drm_enc,
struct sde_kms *sde_kms;
struct drm_connector *conn;
int i = 0, ret;
int num_lm, num_intf, num_pp_per_intf;
if (!drm_enc) {
SDE_ERROR("invalid encoder\n");
@@ -2276,17 +2271,25 @@ static void sde_encoder_virt_mode_set(struct drm_encoder *drm_enc,
/* assign the reserved HW blocks to this encoder */
_sde_encoder_virt_populate_hw_res(drm_enc);
/* determine left HW PP block to map to INTF */
num_lm = sde_enc->mode_info.topology.num_lm;
num_intf = sde_enc->mode_info.topology.num_intf;
num_pp_per_intf = num_lm / num_intf;
if (!num_pp_per_intf)
num_pp_per_intf = 1;
/* perform mode_set on phys_encs */
for (i = 0; i < sde_enc->num_phys_encs; i++) {
struct sde_encoder_phys *phys = sde_enc->phys_encs[i];
if (phys) {
if (!sde_enc->hw_pp[i] && sde_enc->topology.num_intf) {
SDE_ERROR_ENC(sde_enc,
"invalid pingpong block for the encoder\n");
if (!sde_enc->hw_pp[i * num_pp_per_intf] &&
sde_enc->topology.num_intf) {
SDE_ERROR_ENC(sde_enc, "invalid hw_pp[%d]\n",
i * num_pp_per_intf);
return;
}
phys->hw_pp = sde_enc->hw_pp[i];
phys->hw_pp = sde_enc->hw_pp[i * num_pp_per_intf];
phys->connector = conn->state->connector;
if (phys->ops.mode_set)
phys->ops.mode_set(phys, mode, adj_mode);
@@ -2493,6 +2496,7 @@ static void _sde_encoder_virt_enable_helper(struct drm_encoder *drm_enc)
static void _sde_encoder_setup_dither(struct sde_encoder_phys *phys)
{
struct sde_kms *sde_kms;
void *dither_cfg = NULL;
int ret = 0, i = 0;
size_t len = 0;
@@ -2502,11 +2506,16 @@ static void _sde_encoder_setup_dither(struct sde_encoder_phys *phys)
struct sde_encoder_virt *sde_enc;
struct sde_hw_pingpong *hw_pp;
u32 bpp, bpc;
int num_lm;
if (!phys || !phys->connector || !phys->hw_pp ||
!phys->hw_pp->ops.setup_dither || !phys->parent)
return;
sde_kms = sde_encoder_get_kms(phys->parent);
if (!sde_kms)
return;
topology = sde_connector_get_topology_name(phys->connector);
if ((topology == SDE_RM_TOPOLOGY_PPSPLIT) &&
(phys->split_role == ENC_ROLE_SLAVE))
@@ -2533,17 +2542,12 @@ static void _sde_encoder_setup_dither(struct sde_encoder_phys *phys)
if (ret && ret == -ENODATA)
return;
if (TOPOLOGY_DUALPIPE_MERGE_MODE(topology)) {
for (i = 0; i < MAX_CHANNELS_PER_ENC; i++) {
num_lm = sde_rm_topology_get_num_lm(&sde_kms->rm, topology);
for (i = 0; i < num_lm; i++) {
hw_pp = sde_enc->hw_pp[i];
phys->hw_pp->ops.setup_dither(hw_pp,
dither_cfg, len);
}
} else {
phys->hw_pp->ops.setup_dither(phys->hw_pp,
dither_cfg, len);
}
}
void sde_encoder_virt_restore(struct drm_encoder *drm_enc)

Fájl megtekintése

@@ -38,7 +38,7 @@
#define MAX_PHYS_ENCODERS_PER_VIRTUAL \
(MAX_H_TILES_PER_DISPLAY * NUM_PHYS_ENCODER_TYPES)
#define MAX_CHANNELS_PER_ENC 2
#define MAX_CHANNELS_PER_ENC 4
#define SDE_ENCODER_FRAME_EVENT_DONE BIT(0)
#define SDE_ENCODER_FRAME_EVENT_ERROR BIT(1)

Fájl megtekintése

@@ -313,7 +313,8 @@ static int _dce_dsc_setup_single(struct sde_encoder_virt *sde_enc,
unsigned long affected_displays, int index,
const struct sde_rect *roi, int dsc_common_mode,
bool merge_3d, bool disable_merge_3d, bool mode_3d,
bool half_panel_partial_update, int ich_res)
bool dsc_4hsmerge, bool half_panel_partial_update,
int ich_res)
{
struct sde_hw_ctl *hw_ctl;
struct sde_hw_dsc *hw_dsc;
@@ -345,8 +346,9 @@ static int _dce_dsc_setup_single(struct sde_encoder_virt *sde_enc,
return -EINVAL;
}
SDE_EVT32(DRMID(&sde_enc->base), roi->w, roi->h, dsc_common_mode,
index, active, merge_3d, disable_merge_3d);
SDE_EVT32(DRMID(&sde_enc->base), roi->w, roi->h,
dsc_common_mode, index, active, merge_3d,
disable_merge_3d, dsc_4hsmerge);
_dce_dsc_pipe_cfg(hw_dsc, hw_pp, dsc, dsc_common_mode, ich_res,
hw_dsc_pp, mode_3d, disable_merge_3d, active,
@@ -401,15 +403,15 @@ static int _dce_dsc_setup_helper(struct sde_encoder_virt *sde_enc,
const struct sde_rm_topology_def *def;
const struct sde_rect *roi;
enum sde_3d_blend_mode mode_3d;
bool half_panel_partial_update, dsc_merge, merge_3d;
bool half_panel_partial_update, dsc_merge, merge_3d, dsc_4hsmerge;
bool disable_merge_3d = false;
int this_frame_slices;
int intf_ip_w, enc_ip_w;
int num_intf, num_dsc, num_lm;
int ich_res;
int dsc_pic_width;
int dsc_common_mode = 0;
int i;
int rc = 0;
int i, rc = 0;
sde_kms = sde_encoder_get_kms(&sde_enc->base);
@@ -420,33 +422,43 @@ static int _dce_dsc_setup_helper(struct sde_encoder_virt *sde_enc,
enc_master = sde_enc->cur_master;
roi = &sde_enc->cur_conn_roi;
dsc = &sde_enc->mode_info.comp_info.dsc_info;
num_lm = def->num_lm;
num_dsc = def->num_comp_enc;
num_intf = def->num_intf;
mode_3d = (topology == SDE_RM_TOPOLOGY_DUALPIPE_3DMERGE_DSC) ?
BLEND_3D_H_ROW_INT : BLEND_3D_NONE;
num_lm = def->num_lm;
mode_3d = (num_lm > num_dsc) ? BLEND_3D_H_ROW_INT : BLEND_3D_NONE;
merge_3d = (mode_3d != BLEND_3D_NONE) ? true : false;
half_panel_partial_update = _dce_check_half_panel_update(num_lm,
affected_displays);
merge_3d = (mode_3d != BLEND_3D_NONE) ? true : false;
dsc_merge = ((num_dsc > num_intf) && !half_panel_partial_update) ?
true : false;
disable_merge_3d = (merge_3d && half_panel_partial_update) ?
false : true;
dsc_4hsmerge = (dsc_merge && num_dsc == 4 && num_intf == 1) ?
true : false;
/*
* If this encoder is driving more than one DSC encoder, they
* operate in tandem, same pic dimension needs to be used by
* each of them.(pp-split is assumed to be not supported)
*
* If encoder is driving more than 2 DSCs, each DSC pair will operate
* on half of the picture in tandem.
*/
_dce_dsc_update_pic_dim(dsc, roi->w, roi->h);
if (num_dsc > 2) {
dsc_pic_width = roi->w / 2;
dsc->dsc_4hsmerge_en = dsc_4hsmerge;
} else
dsc_pic_width = roi->w;
_dce_dsc_update_pic_dim(dsc, dsc_pic_width, roi->h);
this_frame_slices = roi->w / dsc->config.slice_width;
intf_ip_w = this_frame_slices * dsc->config.slice_width;
enc_ip_w = intf_ip_w;
if (!half_panel_partial_update)
intf_ip_w /= def->num_intf;
intf_ip_w /= num_intf;
if (!half_panel_partial_update && (num_dsc > 1))
dsc_common_mode |= DSC_MODE_SPLIT_PANEL;
if (dsc_merge) {
@@ -478,7 +490,7 @@ static int _dce_dsc_setup_helper(struct sde_encoder_virt *sde_enc,
for (i = 0; i < num_dsc; i++) {
rc = _dce_dsc_setup_single(sde_enc, dsc, affected_displays, i,
roi, dsc_common_mode, merge_3d,
disable_merge_3d, mode_3d,
disable_merge_3d, mode_3d, dsc_4hsmerge,
half_panel_partial_update, ich_res);
if (rc)
break;

Fájl megtekintése

@@ -603,16 +603,29 @@ void sde_encoder_helper_hw_reset(struct sde_encoder_phys *phys_enc);
static inline enum sde_3d_blend_mode sde_encoder_helper_get_3d_blend_mode(
struct sde_encoder_phys *phys_enc)
{
enum sde_rm_topology_name topology;
struct msm_display_topology def;
enum sde_enc_split_role split_role;
int ret, num_lm;
bool mode_3d;
if (!phys_enc || phys_enc->enable_state == SDE_ENC_DISABLING)
if (!phys_enc || phys_enc->enable_state == SDE_ENC_DISABLING ||
!phys_enc->connector || !phys_enc->connector->state)
return BLEND_3D_NONE;
topology = sde_connector_get_topology_name(phys_enc->connector);
if (phys_enc->split_role == ENC_ROLE_SOLO &&
(topology == SDE_RM_TOPOLOGY_DUALPIPE_3DMERGE ||
topology == SDE_RM_TOPOLOGY_DUALPIPE_3DMERGE_DSC ||
topology == SDE_RM_TOPOLOGY_DUALPIPE_3DMERGE_VDC))
ret = sde_connector_state_get_topology
(phys_enc->connector->state, &def);
if (ret)
return BLEND_3D_NONE;
num_lm = def.num_lm;
mode_3d = (num_lm > def.num_enc) ? true : false;
split_role = phys_enc->split_role;
if (split_role == ENC_ROLE_SOLO && num_lm == 2 && mode_3d)
return BLEND_3D_H_ROW_INT;
if ((split_role == ENC_ROLE_MASTER || split_role == ENC_ROLE_SLAVE)
&& num_lm == 4 && mode_3d)
return BLEND_3D_H_ROW_INT;
return BLEND_3D_NONE;

Fájl megtekintése

@@ -87,7 +87,7 @@
#define SDE_CTL_CFG_VERSION_1_0_0 0x100
#define MAX_INTF_PER_CTL_V1 2
#define MAX_DSC_PER_CTL_V1 2
#define MAX_DSC_PER_CTL_V1 4
#define MAX_CWB_PER_CTL_V1 2
#define MAX_MERGE_3D_PER_CTL_V1 2
#define MAX_WB_PER_CTL_V1 1

Fájl megtekintése

@@ -141,7 +141,11 @@ static void sde_hw_dsc_config(struct sde_hw_dsc *hw_dsc,
data |= BIT(0);
if (mode & DSC_MODE_MULTIPLEX) {
if (dsc->dsc_4hsmerge_en)
slice_count_per_enc = dsc->config.slice_count >> 2;
else
slice_count_per_enc = dsc->config.slice_count >> 1;
data |= BIT(1);
}
@@ -253,6 +257,11 @@ static void sde_hw_dsc_config(struct sde_hw_dsc *hw_dsc,
data |= BIT(13);
if (!(mode & DSC_MODE_VIDEO))
data |= BIT(17);
if (dsc->dsc_4hsmerge_en) {
data |= dsc->dsc_4hsmerge_padding << 18;
data |= dsc->dsc_4hsmerge_alignment << 22;
data |= BIT(16);
}
SDE_REG_WRITE(dsc_c, DSC_CFG + idx, data);
}

Fájl megtekintése

@@ -2142,6 +2142,63 @@ bool sde_rm_topology_is_quad_pipe(struct sde_rm *rm,
return false;
}
bool sde_rm_topology_is_dual_pipe(struct sde_rm *rm,
struct drm_crtc_state *state)
{
int i;
struct sde_crtc_state *cstate;
uint64_t topology = SDE_RM_TOPOLOGY_NONE;
if ((!rm) || (!state)) {
pr_err("invalid arguments: rm:%d state:%d\n",
rm == NULL, state == NULL);
return false;
}
cstate = to_sde_crtc_state(state);
for (i = 0; i < cstate->num_connectors; i++) {
struct drm_connector *conn = cstate->connectors[i];
topology = sde_connector_get_topology_name(conn);
if (TOPOLOGY_DUALPIPE_MERGE_MODE(topology))
return true;
}
return false;
}
bool sde_rm_topology_is_3dmux_dsc(struct sde_rm *rm,
struct drm_crtc_state *state)
{
int i;
struct sde_crtc_state *cstate;
uint64_t topology = SDE_RM_TOPOLOGY_NONE;
const struct sde_rm_topology_def *def;
int num_lm, num_enc;
if ((!rm) || (!state)) {
pr_err("invalid arguments: rm:%d state:%d\n",
rm == NULL, state == NULL);
return false;
}
cstate = to_sde_crtc_state(state);
for (i = 0; i < cstate->num_connectors; i++) {
struct drm_connector *conn = cstate->connectors[i];
topology = sde_connector_get_topology_name(conn);
def = sde_rm_topology_get_topology_def(rm, topology);
num_lm = def->num_lm;
num_enc = def->num_comp_enc;
if (num_lm > num_enc && num_enc)
return true;
}
return false;
}
/**
* _sde_rm_release_rsvp - release resources and release a reservation
* @rm: KMS handle

Fájl megtekintése

@@ -20,6 +20,12 @@
x == SDE_RM_TOPOLOGY_QUADPIPE_DSCMERGE ||\
x == SDE_RM_TOPOLOGY_QUADPIPE_DSC4HSMERGE)
#define TOPOLOGY_DUALPIPE_MERGE_MODE(x) \
(x == SDE_RM_TOPOLOGY_DUALPIPE_DSCMERGE || \
x == SDE_RM_TOPOLOGY_DUALPIPE_3DMERGE || \
x == SDE_RM_TOPOLOGY_DUALPIPE_3DMERGE_VDC || \
x == SDE_RM_TOPOLOGY_DUALPIPE_3DMERGE_DSC)
/**
* enum sde_rm_topology_name - HW resource use case in use by connector
* @SDE_RM_TOPOLOGY_NONE: No topology in use currently
@@ -343,6 +349,26 @@ static inline int sde_rm_topology_get_num_lm(struct sde_rm *rm,
return rm->topology_tbl[topology].num_lm;
}
/**
* sde_rm_topology_is_dual_pipe - check if the topology used
* is a dual-pipe mode one
* @rm: SDE Resource Manager handle
* @state: drm state of the crtc
* @return: true if attached connector is in dual-pipe mode
*/
bool sde_rm_topology_is_dual_pipe(struct sde_rm *rm,
struct drm_crtc_state *state);
/**
* sde_rm_topology_is_3dmux_dsc - check if the topology used
* is a 3dmerge dsc mode one
* @rm: SDE Resource Manager handle
* @state: drm state of the crtc
* @return: true if attached connector is in 3DMERGE DSC mode
*/
bool sde_rm_topology_is_3dmux_dsc(struct sde_rm *rm,
struct drm_crtc_state *state);
/**
* sde_rm_topology_is_quad_pipe - check if the topology used
* is a quad-pipe mode one

Fájl megtekintése

@@ -309,6 +309,8 @@ int sde_dsc_populate_dsc_private_params(struct msm_display_dsc_info *dsc_info,
int slice_per_pkt, slice_per_intf;
int bytes_in_slice, total_bytes_per_intf;
u16 bpp;
u32 bytes_in_dsc_pair;
u32 total_bytes_in_dsc_pair;
if (!dsc_info || !dsc_info->config.slice_width ||
!dsc_info->config.slice_height ||
@@ -360,6 +362,16 @@ int sde_dsc_populate_dsc_private_params(struct msm_display_dsc_info *dsc_info,
dsc_info->bytes_per_pkt = bytes_in_slice * slice_per_pkt;
dsc_info->pkt_per_line = slice_per_intf / slice_per_pkt;
bytes_in_dsc_pair = DIV_ROUND_UP(bytes_in_slice * 2, 3);
if (bytes_in_dsc_pair % 8) {
dsc_info->dsc_4hsmerge_padding = 8 - (bytes_in_dsc_pair % 8);
total_bytes_in_dsc_pair = bytes_in_dsc_pair +
dsc_info->dsc_4hsmerge_padding;
if (total_bytes_in_dsc_pair % 16)
dsc_info->dsc_4hsmerge_alignment = 16 -
(total_bytes_in_dsc_pair % 16);
}
return 0;
}