@@ -73,6 +73,7 @@ static bool drm_dp_validate_guid(struct drm_dp_mst_topology_mgr *mgr,
static int drm_dp_mst_register_i2c_bus(struct drm_dp_aux *aux);
static void drm_dp_mst_unregister_i2c_bus(struct drm_dp_aux *aux);
static void drm_dp_mst_kick_tx(struct drm_dp_mst_topology_mgr *mgr);
+static void drm_dp_mst_update_dsc_crtcs(struct drm_dp_mst_topology_state *mst_state);
#define DP_STR(x) [DP_ ## x] = #x
@@ -3293,6 +3294,65 @@ int drm_dp_atomic_find_vcpi_slots(struct drm_atomic_state *state,
}
EXPORT_SYMBOL(drm_dp_atomic_find_vcpi_slots);
+/**
+ * drm_dp_helper_update_vcpi_slots_for_dsc() - Update VCPI slots with new on the state
+ *
+ * @state: global atomic state
+ * @port: port to find vcpi slots
+ * @pbn: updated bandwidth required for the mode in PBN
+ *
+ * Function reallocates VCPI slots to the @port by calling
+ * drm_dp_atomic_find_vcpi_slots. The assumption is that VCPI slots
+ * have already been allocated and this is second call overwritting
+ * initial values. After the VCPI is allocated dsc_enable flag is set to
+ * true for atomic check.
+ *
+ * It is driver's responsibility to call this function after it decides
+ * to enable DSC.
+ *
+ * See also:
+ * drm_dp_mst_update_dsc_crtcs()
+ *
+ * Returns:
+ * Total slots in the atomic state assigned for this port, or a negative error
+ * code if the port no longer exists or vcpi slots haven't been assigned.
+ */
+int drm_dp_helper_update_vcpi_slots_for_dsc(struct drm_atomic_state *state,
+ struct drm_dp_mst_port *port,
+ int pbn)
+{
+ struct drm_dp_mst_topology_state *topology_state;
+ struct drm_dp_vcpi_allocation *pos;
+ bool found = false;
+ int vcpi = 0;
+
+ topology_state = drm_atomic_get_mst_topology_state(state, port->mgr);
+
+ if (IS_ERR(topology_state))
+ return PTR_ERR(topology_state);
+
+ list_for_each_entry(pos, &topology_state->vcpis, next) {
+ if (pos->port == port) {
+ found = true;
+ break;
+ }
+ }
+
+ if (!found || !pos->vcpi)
+ return -EINVAL;
+
+ vcpi = drm_dp_atomic_find_vcpi_slots(state, port->mgr,
+ port, pbn);
+
+ if (vcpi < 0)
+ return -EINVAL;
+
+ pos->dsc_enable = true;
+
+ return vcpi;
+}
+
+EXPORT_SYMBOL(drm_dp_helper_update_vcpi_slots_for_dsc);
/**
* drm_dp_atomic_release_vcpi_slots() - Release allocated vcpi slots
* @state: global atomic state
@@ -3871,6 +3931,46 @@ drm_dp_mst_atomic_check_topology_state(struct drm_dp_mst_topology_mgr *mgr,
return 0;
}
+/**
+ * drm_dp_mst_update_dsc_crtcs - Set mode change flag on CRTCs which
+ * just got DSC enabled
+ * @state: Pointer to the new &struct drm_dp_mst_topology_state
+ *
+ * Itearate through all the ports in MST topology to check if DSC
+ * has been enabled on any of them. Set mode_changed to true on
+ * crtc state that just got DSC enabled.
+ *
+ * See also:
+ * drm_dp_helper_update_vcpi_slots_for_dsc()
+ */
+static void
+drm_dp_mst_update_dsc_crtcs(struct drm_dp_mst_topology_state *mst_state)
+{
+ struct drm_dp_vcpi_allocation *pos;
+ struct drm_dp_mst_port *port;
+ struct drm_connector_state *conn_state;
+ struct drm_crtc *crtc;
+ struct drm_crtc_state *crtc_state;
+
+ list_for_each_entry(pos, &mst_state->vcpis, next) {
+
+ port = pos->port;
+ conn_state = drm_atomic_get_connector_state(mst_state->base.state,
+ port->connector);
+ crtc = conn_state->crtc;
+ if (!crtc)
+ continue;
+
+ crtc_state = drm_atomic_get_crtc_state(mst_state->base.state, crtc);
+ if (port->vcpi.vcpi == pos->vcpi)
+ continue;
+
+ if (pos->dsc_enable) {
+ crtc_state->mode_changed = true;
+ pos->dsc_enable = false;
+ }
+ }
+}
/**
* drm_dp_mst_atomic_check - Check that the new state of an MST topology in an
* atomic update is valid
@@ -3887,9 +3987,9 @@ drm_dp_mst_atomic_check_topology_state(struct drm_dp_mst_topology_mgr *mgr,
* See also:
* drm_dp_atomic_find_vcpi_slots()
* drm_dp_atomic_release_vcpi_slots()
- *
* Returns:
*
+ *
* 0 if the new state is valid, negative error code otherwise.
*/
int drm_dp_mst_atomic_check(struct drm_atomic_state *state)
@@ -3902,6 +4002,7 @@ int drm_dp_mst_atomic_check(struct drm_atomic_state *state)
ret = drm_dp_mst_atomic_check_topology_state(mgr, mst_state);
if (ret)
break;
+ drm_dp_mst_update_dsc_crtcs(mst_state);
}
return ret;
@@ -431,6 +431,7 @@ struct drm_dp_payload {
struct drm_dp_vcpi_allocation {
struct drm_dp_mst_port *port;
int vcpi;
+ bool dsc_enable;
struct list_head next;
};
@@ -662,6 +663,9 @@ int __must_check
drm_dp_atomic_find_vcpi_slots(struct drm_atomic_state *state,
struct drm_dp_mst_topology_mgr *mgr,
struct drm_dp_mst_port *port, int pbn);
+int drm_dp_helper_update_vcpi_slots_for_dsc(struct drm_atomic_state *state,
+ struct drm_dp_mst_port *port,
+ int pbn);
int __must_check
drm_dp_atomic_release_vcpi_slots(struct drm_atomic_state *state,
struct drm_dp_mst_topology_mgr *mgr,