Skip to content

Commit b50a1aa

Browse files
Manasi Navareuma-intel
authored andcommitted
drm/i915/dp: Compute port sync crtc states post compute_config()
This patch pushes out the computation of master and slave transcoders in crtc states after encoder's compute_config hook. This ensures that the assigned master slave crtcs have exact same mode and timings which is a requirement for Port sync mode to be enabled. v3: * Make crtc_state const, remove crtc state NULL init (Ville) v2: * Correct indentation * Rename to intel_ddi_port_sync_transcoders (Ville) * remove unwanted debug (Ville) Suggested-by: Ville Syrjälä <[email protected]> Cc: Ville Syrjälä <[email protected]> Signed-off-by: Manasi Navare <[email protected]> Reviewed-by: Ville Syrjälä <[email protected]> Signed-off-by: Uma Shankar <[email protected]> Link: https://patchwork.freedesktop.org/patch/msgid/[email protected]
1 parent f280142 commit b50a1aa

File tree

2 files changed

+108
-158
lines changed

2 files changed

+108
-158
lines changed

drivers/gpu/drm/i915/display/intel_ddi.c

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4456,6 +4456,112 @@ static int intel_ddi_compute_config(struct intel_encoder *encoder,
44564456
return 0;
44574457
}
44584458

4459+
static bool mode_equal(const struct drm_display_mode *mode1,
4460+
const struct drm_display_mode *mode2)
4461+
{
4462+
return drm_mode_match(mode1, mode2,
4463+
DRM_MODE_MATCH_TIMINGS |
4464+
DRM_MODE_MATCH_FLAGS |
4465+
DRM_MODE_MATCH_3D_FLAGS) &&
4466+
mode1->clock == mode2->clock; /* we want an exact match */
4467+
}
4468+
4469+
static bool m_n_equal(const struct intel_link_m_n *m_n_1,
4470+
const struct intel_link_m_n *m_n_2)
4471+
{
4472+
return m_n_1->tu == m_n_2->tu &&
4473+
m_n_1->gmch_m == m_n_2->gmch_m &&
4474+
m_n_1->gmch_n == m_n_2->gmch_n &&
4475+
m_n_1->link_m == m_n_2->link_m &&
4476+
m_n_1->link_n == m_n_2->link_n;
4477+
}
4478+
4479+
static bool crtcs_port_sync_compatible(const struct intel_crtc_state *crtc_state1,
4480+
const struct intel_crtc_state *crtc_state2)
4481+
{
4482+
return crtc_state1->hw.active && crtc_state2->hw.active &&
4483+
crtc_state1->output_types == crtc_state2->output_types &&
4484+
crtc_state1->output_format == crtc_state2->output_format &&
4485+
crtc_state1->lane_count == crtc_state2->lane_count &&
4486+
crtc_state1->port_clock == crtc_state2->port_clock &&
4487+
mode_equal(&crtc_state1->hw.adjusted_mode,
4488+
&crtc_state2->hw.adjusted_mode) &&
4489+
m_n_equal(&crtc_state1->dp_m_n, &crtc_state2->dp_m_n);
4490+
}
4491+
4492+
static u8
4493+
intel_ddi_port_sync_transcoders(const struct intel_crtc_state *ref_crtc_state,
4494+
int tile_group_id)
4495+
{
4496+
struct drm_connector *connector;
4497+
const struct drm_connector_state *conn_state;
4498+
struct drm_i915_private *dev_priv = to_i915(ref_crtc_state->uapi.crtc->dev);
4499+
struct intel_atomic_state *state =
4500+
to_intel_atomic_state(ref_crtc_state->uapi.state);
4501+
u8 transcoders = 0;
4502+
int i;
4503+
4504+
if (INTEL_GEN(dev_priv) < 11)
4505+
return 0;
4506+
4507+
if (!intel_crtc_has_type(ref_crtc_state, INTEL_OUTPUT_DP))
4508+
return 0;
4509+
4510+
for_each_new_connector_in_state(&state->base, connector, conn_state, i) {
4511+
struct intel_crtc *crtc = to_intel_crtc(conn_state->crtc);
4512+
const struct intel_crtc_state *crtc_state;
4513+
4514+
if (!crtc)
4515+
continue;
4516+
4517+
if (!connector->has_tile ||
4518+
connector->tile_group->id !=
4519+
tile_group_id)
4520+
continue;
4521+
crtc_state = intel_atomic_get_new_crtc_state(state,
4522+
crtc);
4523+
if (!crtcs_port_sync_compatible(ref_crtc_state,
4524+
crtc_state))
4525+
continue;
4526+
transcoders |= BIT(crtc_state->cpu_transcoder);
4527+
}
4528+
4529+
return transcoders;
4530+
}
4531+
4532+
static int intel_ddi_compute_config_late(struct intel_encoder *encoder,
4533+
struct intel_crtc_state *crtc_state,
4534+
struct drm_connector_state *conn_state)
4535+
{
4536+
struct drm_connector *connector = conn_state->connector;
4537+
u8 port_sync_transcoders = 0;
4538+
4539+
DRM_DEBUG_KMS("[ENCODER:%d:%s] [CRTC:%d:%s]",
4540+
encoder->base.base.id, encoder->base.name,
4541+
crtc_state->uapi.crtc->base.id, crtc_state->uapi.crtc->name);
4542+
4543+
if (connector->has_tile)
4544+
port_sync_transcoders = intel_ddi_port_sync_transcoders(crtc_state,
4545+
connector->tile_group->id);
4546+
4547+
/*
4548+
* EDP Transcoders cannot be ensalved
4549+
* make them a master always when present
4550+
*/
4551+
if (port_sync_transcoders & BIT(TRANSCODER_EDP))
4552+
crtc_state->master_transcoder = TRANSCODER_EDP;
4553+
else
4554+
crtc_state->master_transcoder = ffs(port_sync_transcoders) - 1;
4555+
4556+
if (crtc_state->master_transcoder == crtc_state->cpu_transcoder) {
4557+
crtc_state->master_transcoder = INVALID_TRANSCODER;
4558+
crtc_state->sync_mode_slaves_mask =
4559+
port_sync_transcoders & ~BIT(crtc_state->cpu_transcoder);
4560+
}
4561+
4562+
return 0;
4563+
}
4564+
44594565
static void intel_ddi_encoder_destroy(struct drm_encoder *encoder)
44604566
{
44614567
struct intel_digital_port *dig_port = enc_to_dig_port(to_intel_encoder(encoder));
@@ -4765,6 +4871,7 @@ void intel_ddi_init(struct drm_i915_private *dev_priv, enum port port)
47654871
encoder->hotplug = intel_ddi_hotplug;
47664872
encoder->compute_output_type = intel_ddi_compute_output_type;
47674873
encoder->compute_config = intel_ddi_compute_config;
4874+
encoder->compute_config_late = intel_ddi_compute_config_late;
47684875
encoder->enable = intel_enable_ddi;
47694876
encoder->pre_pll_enable = intel_ddi_pre_pll_enable;
47704877
encoder->pre_enable = intel_ddi_pre_enable;

drivers/gpu/drm/i915/display/intel_display.c

Lines changed: 1 addition & 158 deletions
Original file line numberDiff line numberDiff line change
@@ -12589,126 +12589,6 @@ static bool c8_planes_changed(const struct intel_crtc_state *new_crtc_state)
1258912589
return !old_crtc_state->c8_planes != !new_crtc_state->c8_planes;
1259012590
}
1259112591

12592-
static bool
12593-
intel_atomic_is_master_connector(struct intel_crtc_state *crtc_state)
12594-
{
12595-
struct drm_crtc *crtc = crtc_state->uapi.crtc;
12596-
struct drm_atomic_state *state = crtc_state->uapi.state;
12597-
struct drm_connector *connector;
12598-
struct drm_connector_state *connector_state;
12599-
int i;
12600-
12601-
for_each_new_connector_in_state(state, connector, connector_state, i) {
12602-
if (connector_state->crtc != crtc)
12603-
continue;
12604-
if (connector->has_tile &&
12605-
connector->tile_h_loc == connector->num_h_tile - 1 &&
12606-
connector->tile_v_loc == connector->num_v_tile - 1)
12607-
return true;
12608-
}
12609-
12610-
return false;
12611-
}
12612-
12613-
static void reset_port_sync_mode_state(struct intel_crtc_state *crtc_state)
12614-
{
12615-
crtc_state->master_transcoder = INVALID_TRANSCODER;
12616-
crtc_state->sync_mode_slaves_mask = 0;
12617-
}
12618-
12619-
static int icl_compute_port_sync_crtc_state(struct drm_connector *connector,
12620-
struct intel_crtc_state *crtc_state,
12621-
int num_tiled_conns)
12622-
{
12623-
struct drm_crtc *crtc = crtc_state->uapi.crtc;
12624-
struct intel_atomic_state *state = to_intel_atomic_state(crtc_state->uapi.state);
12625-
struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev);
12626-
struct drm_connector *master_connector;
12627-
struct drm_connector_list_iter conn_iter;
12628-
struct drm_crtc *master_crtc = NULL;
12629-
struct drm_crtc_state *master_crtc_state;
12630-
struct intel_crtc_state *master_pipe_config;
12631-
12632-
if (INTEL_GEN(dev_priv) < 11)
12633-
return 0;
12634-
12635-
if (!intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DP))
12636-
return 0;
12637-
12638-
/*
12639-
* In case of tiled displays there could be one or more slaves but there is
12640-
* only one master. Lets make the CRTC used by the connector corresponding
12641-
* to the last horizonal and last vertical tile a master/genlock CRTC.
12642-
* All the other CRTCs corresponding to other tiles of the same Tile group
12643-
* are the slave CRTCs and hold a pointer to their genlock CRTC.
12644-
* If all tiles not present do not make master slave assignments.
12645-
*/
12646-
if (!connector->has_tile ||
12647-
crtc_state->hw.mode.hdisplay != connector->tile_h_size ||
12648-
crtc_state->hw.mode.vdisplay != connector->tile_v_size ||
12649-
num_tiled_conns < connector->num_h_tile * connector->num_v_tile) {
12650-
reset_port_sync_mode_state(crtc_state);
12651-
return 0;
12652-
}
12653-
/* Last Horizontal and last vertical tile connector is a master
12654-
* Master's crtc state is already populated in slave for port sync
12655-
*/
12656-
if (connector->tile_h_loc == connector->num_h_tile - 1 &&
12657-
connector->tile_v_loc == connector->num_v_tile - 1)
12658-
return 0;
12659-
12660-
/* Loop through all connectors and configure the Slave crtc_state
12661-
* to point to the correct master.
12662-
*/
12663-
drm_connector_list_iter_begin(&dev_priv->drm, &conn_iter);
12664-
drm_for_each_connector_iter(master_connector, &conn_iter) {
12665-
struct drm_connector_state *master_conn_state = NULL;
12666-
12667-
if (!(master_connector->has_tile &&
12668-
master_connector->tile_group->id == connector->tile_group->id))
12669-
continue;
12670-
if (master_connector->tile_h_loc != master_connector->num_h_tile - 1 ||
12671-
master_connector->tile_v_loc != master_connector->num_v_tile - 1)
12672-
continue;
12673-
12674-
master_conn_state = drm_atomic_get_connector_state(&state->base,
12675-
master_connector);
12676-
if (IS_ERR(master_conn_state)) {
12677-
drm_connector_list_iter_end(&conn_iter);
12678-
return PTR_ERR(master_conn_state);
12679-
}
12680-
if (master_conn_state->crtc) {
12681-
master_crtc = master_conn_state->crtc;
12682-
break;
12683-
}
12684-
}
12685-
drm_connector_list_iter_end(&conn_iter);
12686-
12687-
if (!master_crtc) {
12688-
drm_dbg_kms(&dev_priv->drm,
12689-
"Could not find Master CRTC for Slave CRTC %d\n",
12690-
crtc->base.id);
12691-
return -EINVAL;
12692-
}
12693-
12694-
master_crtc_state = drm_atomic_get_crtc_state(&state->base,
12695-
master_crtc);
12696-
if (IS_ERR(master_crtc_state))
12697-
return PTR_ERR(master_crtc_state);
12698-
12699-
master_pipe_config = to_intel_crtc_state(master_crtc_state);
12700-
crtc_state->master_transcoder = master_pipe_config->cpu_transcoder;
12701-
master_pipe_config->sync_mode_slaves_mask |=
12702-
BIT(crtc_state->cpu_transcoder);
12703-
drm_dbg_kms(&dev_priv->drm,
12704-
"Master Transcoder = %s added for Slave CRTC = %d, slave transcoder bitmask = %d\n",
12705-
transcoder_name(crtc_state->master_transcoder),
12706-
crtc->base.id,
12707-
master_pipe_config->sync_mode_slaves_mask);
12708-
12709-
return 0;
12710-
}
12711-
1271212592
static u16 hsw_linetime_wm(const struct intel_crtc_state *crtc_state)
1271312593
{
1271412594
const struct drm_display_mode *adjusted_mode =
@@ -13359,15 +13239,6 @@ intel_crtc_prepare_cleared_state(struct intel_crtc_state *crtc_state)
1335913239
if (IS_G4X(dev_priv) ||
1336013240
IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
1336113241
saved_state->wm = crtc_state->wm;
13362-
/*
13363-
* Save the slave bitmask which gets filled for master crtc state during
13364-
* slave atomic check call. For all other CRTCs reset the port sync variables
13365-
* crtc_state->master_transcoder needs to be set to INVALID
13366-
*/
13367-
reset_port_sync_mode_state(saved_state);
13368-
if (intel_atomic_is_master_connector(crtc_state))
13369-
saved_state->sync_mode_slaves_mask =
13370-
crtc_state->sync_mode_slaves_mask;
1337113242

1337213243
memcpy(crtc_state, saved_state, sizeof(*crtc_state));
1337313244
kfree(saved_state);
@@ -13385,8 +13256,7 @@ intel_modeset_pipe_config(struct intel_crtc_state *pipe_config)
1338513256
struct drm_i915_private *i915 = to_i915(pipe_config->uapi.crtc->dev);
1338613257
struct drm_connector *connector;
1338713258
struct drm_connector_state *connector_state;
13388-
int base_bpp, ret;
13389-
int i, tile_group_id = -1, num_tiled_conns = 0;
13259+
int base_bpp, ret, i;
1339013260
bool retry = true;
1339113261

1339213262
pipe_config->cpu_transcoder =
@@ -13458,24 +13328,6 @@ intel_modeset_pipe_config(struct intel_crtc_state *pipe_config)
1345813328
drm_mode_set_crtcinfo(&pipe_config->hw.adjusted_mode,
1345913329
CRTC_STEREO_DOUBLE);
1346013330

13461-
/* Get tile_group_id of tiled connector */
13462-
for_each_new_connector_in_state(state, connector, connector_state, i) {
13463-
if (connector_state->crtc == crtc &&
13464-
connector->has_tile) {
13465-
tile_group_id = connector->tile_group->id;
13466-
break;
13467-
}
13468-
}
13469-
13470-
/* Get total number of tiled connectors in state that belong to
13471-
* this tile group.
13472-
*/
13473-
for_each_new_connector_in_state(state, connector, connector_state, i) {
13474-
if (connector->has_tile &&
13475-
connector->tile_group->id == tile_group_id)
13476-
num_tiled_conns++;
13477-
}
13478-
1347913331
/* Pass our mode to the connectors and the CRTC to give them a chance to
1348013332
* adjust it according to limitations or connector properties, and also
1348113333
* a chance to reject the mode entirely.
@@ -13487,15 +13339,6 @@ intel_modeset_pipe_config(struct intel_crtc_state *pipe_config)
1348713339
if (connector_state->crtc != crtc)
1348813340
continue;
1348913341

13490-
ret = icl_compute_port_sync_crtc_state(connector, pipe_config,
13491-
num_tiled_conns);
13492-
if (ret) {
13493-
drm_dbg_kms(&i915->drm,
13494-
"Cannot assign Sync Mode CRTCs: %d\n",
13495-
ret);
13496-
return ret;
13497-
}
13498-
1349913342
ret = encoder->compute_config(encoder, pipe_config,
1350013343
connector_state);
1350113344
if (ret < 0) {

0 commit comments

Comments
 (0)