|
@@ -342,7 +342,9 @@ static void dsi_bridge_mode_set(struct drm_bridge *bridge,
|
|
|
const struct drm_display_mode *mode,
|
|
|
const struct drm_display_mode *adjusted_mode)
|
|
|
{
|
|
|
- struct dsi_bridge *c_bridge = to_dsi_bridge(bridge);
|
|
|
+ int rc = 0;
|
|
|
+ struct dsi_bridge *c_bridge = NULL;
|
|
|
+ struct dsi_display *display;
|
|
|
struct drm_connector *conn;
|
|
|
struct sde_connector_state *conn_state;
|
|
|
|
|
@@ -351,6 +353,18 @@ static void dsi_bridge_mode_set(struct drm_bridge *bridge,
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
+ c_bridge = to_dsi_bridge(bridge);
|
|
|
+ if (!c_bridge) {
|
|
|
+ DSI_ERR("invalid dsi bridge\n");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ display = c_bridge->display;
|
|
|
+ if (!display || !display->drm_conn || !display->drm_conn->state) {
|
|
|
+ DSI_ERR("invalid display\n");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
memset(&(c_bridge->dsi_mode), 0x0, sizeof(struct dsi_display_mode));
|
|
|
convert_to_dsi_mode(adjusted_mode, &(c_bridge->dsi_mode));
|
|
|
conn = sde_encoder_get_connector(bridge->dev, bridge->encoder);
|
|
@@ -366,9 +380,11 @@ static void dsi_bridge_mode_set(struct drm_bridge *bridge,
|
|
|
msm_parse_mode_priv_info(&conn_state->msm_mode,
|
|
|
&(c_bridge->dsi_mode));
|
|
|
|
|
|
- /* restore bit_clk_rate also for dynamic clk use cases */
|
|
|
- c_bridge->dsi_mode.timing.clk_rate_hz =
|
|
|
- dsi_drm_find_bit_clk_rate(c_bridge->display, adjusted_mode);
|
|
|
+ rc = dsi_display_restore_bit_clk(display, &c_bridge->dsi_mode);
|
|
|
+ if (rc) {
|
|
|
+ DSI_ERR("[%s] bit clk rate cannot be restored\n", display->name);
|
|
|
+ return;
|
|
|
+ }
|
|
|
|
|
|
DSI_DEBUG("clk_rate: %llu\n", c_bridge->dsi_mode.timing.clk_rate_hz);
|
|
|
}
|
|
@@ -436,6 +452,18 @@ static bool dsi_bridge_mode_fixup(struct drm_bridge *bridge,
|
|
|
dsi_mode.timing.dsc_enabled = dsi_mode.priv_info->dsc_enabled;
|
|
|
dsi_mode.timing.dsc = &dsi_mode.priv_info->dsc;
|
|
|
|
|
|
+ rc = dsi_display_restore_bit_clk(display, &dsi_mode);
|
|
|
+ if (rc) {
|
|
|
+ DSI_ERR("[%s] bit clk rate cannot be restored\n", display->name);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ rc = dsi_display_update_dyn_bit_clk(display, &dsi_mode);
|
|
|
+ if (rc) {
|
|
|
+ DSI_ERR("[%s] failed to update bit clock\n", display->name);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
rc = dsi_display_validate_mode(c_bridge->display, &dsi_mode,
|
|
|
DSI_VALIDATE_FLAG_ALLOW_ADJUST);
|
|
|
if (rc) {
|
|
@@ -517,33 +545,6 @@ u32 dsi_drm_get_dfps_maxfps(void *display)
|
|
|
return dfps_maxfps;
|
|
|
}
|
|
|
|
|
|
-u64 dsi_drm_find_bit_clk_rate(void *display,
|
|
|
- const struct drm_display_mode *drm_mode)
|
|
|
-{
|
|
|
- int i = 0, count = 0;
|
|
|
- struct dsi_display *dsi_display = display;
|
|
|
- struct dsi_display_mode *dsi_mode;
|
|
|
- u64 bit_clk_rate = 0;
|
|
|
-
|
|
|
- if (!dsi_display || !drm_mode)
|
|
|
- return 0;
|
|
|
-
|
|
|
- dsi_display_get_mode_count(dsi_display, &count);
|
|
|
-
|
|
|
- for (i = 0; i < count; i++) {
|
|
|
- dsi_mode = &dsi_display->modes[i];
|
|
|
- if ((dsi_mode->timing.v_active == drm_mode->vdisplay) &&
|
|
|
- (dsi_mode->timing.h_active == drm_mode->hdisplay) &&
|
|
|
- (dsi_mode->pixel_clk_khz == drm_mode->clock) &&
|
|
|
- (dsi_mode->timing.refresh_rate == drm_mode_vrefresh(drm_mode))) {
|
|
|
- bit_clk_rate = dsi_mode->timing.clk_rate_hz;
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- return bit_clk_rate;
|
|
|
-}
|
|
|
-
|
|
|
int dsi_conn_get_mode_info(struct drm_connector *connector,
|
|
|
const struct drm_display_mode *drm_mode,
|
|
|
struct msm_mode_info *mode_info,
|
|
@@ -696,6 +697,11 @@ int dsi_conn_set_info_blob(struct drm_connector *connector,
|
|
|
sde_kms_info_add_keystr(info, "dyn bitclk support",
|
|
|
panel->dyn_clk_caps.dyn_clk_support ? "true" : "false");
|
|
|
|
|
|
+ if (panel->dyn_clk_caps.dyn_clk_support)
|
|
|
+ sde_kms_info_add_list(info, "dyn_bitclk_list",
|
|
|
+ panel->dyn_clk_caps.bit_clk_list,
|
|
|
+ panel->dyn_clk_caps.bit_clk_list_len);
|
|
|
+
|
|
|
switch (panel->phy_props.rotation) {
|
|
|
case DSI_PANEL_ROTATE_NONE:
|
|
|
sde_kms_info_add_keystr(info, "panel orientation", "none");
|
|
@@ -1288,3 +1294,42 @@ void dsi_conn_set_allowed_mode_switch(struct drm_connector *connector,
|
|
|
mode_idx++;
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+int dsi_conn_set_dyn_bit_clk(struct drm_connector *connector, uint64_t value)
|
|
|
+{
|
|
|
+ int i;
|
|
|
+ bool is_valid = false;
|
|
|
+ struct sde_connector *c_conn = NULL;
|
|
|
+ struct sde_connector_state *c_state;
|
|
|
+ struct dsi_display *display;
|
|
|
+ struct dsi_dyn_clk_caps *dyn_clk_caps;
|
|
|
+
|
|
|
+ if (!connector) {
|
|
|
+ DSI_ERR("invalid connector\n");
|
|
|
+ return -EINVAL;
|
|
|
+ }
|
|
|
+
|
|
|
+ c_conn = to_sde_connector(connector);
|
|
|
+ c_state = to_sde_connector_state(connector->state);
|
|
|
+
|
|
|
+ display = (struct dsi_display *) c_conn->display;
|
|
|
+ dyn_clk_caps = &display->panel->dyn_clk_caps;
|
|
|
+
|
|
|
+ for (i = 0; i < dyn_clk_caps->bit_clk_list_len; i++) {
|
|
|
+ if (dyn_clk_caps->bit_clk_list[i] == value) {
|
|
|
+ is_valid = true;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!is_valid) {
|
|
|
+ DSI_ERR("invalid dynamic bit clock rate selection %llu\n", value);
|
|
|
+ return -EINVAL;
|
|
|
+ }
|
|
|
+
|
|
|
+ display->dyn_bit_clk = value;
|
|
|
+ display->dyn_bit_clk_pending = true;
|
|
|
+ DSI_DEBUG("update dynamic bit clock rate to %llu\n", display->dyn_bit_clk);
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|