disp: msm: add allowed_mode_switch blob property

The change adds a new mode property allowed_mode_switch. The new
property is a 32bit bitmask that indicates the modes each mode
can switch to. This change is required to pass the driver mode
switching capabilities, so that user mode can reject any mode switch
that is not supported by the driver.

Change-Id: I76d1733a07a6d57487ba9f461055270d7e60e060
Signed-off-by: Satya Rama Aditya Pinapala <psraditya30@codeaurora.org>
此提交包含在:
Satya Rama Aditya Pinapala
2020-08-25 17:21:48 -07:00
父節點 4d3912297a
當前提交 03f9c40e7d
共有 7 個檔案被更改,包括 129 行新增0 行删除

查看文件

@@ -523,6 +523,9 @@ int dsi_conn_get_mode_info(struct drm_connector *connector,
sizeof(dsi_mode.priv_info->roi_caps));
}
mode_info->allowed_mode_switches =
dsi_mode.priv_info->allowed_mode_switch;
return 0;
}
@@ -1084,3 +1087,99 @@ void dsi_drm_bridge_cleanup(struct dsi_bridge *bridge)
kfree(bridge);
}
static bool is_valid_poms_switch(struct dsi_display_mode *mode_a,
struct dsi_display_mode *mode_b)
{
/*
* POMS cannot happen in conjunction with any other type of mode set.
* Check to ensure FPS remains same between the modes and also
* resolution.
*/
return((mode_a->timing.refresh_rate == mode_b->timing.refresh_rate) &&
(mode_a->timing.v_active == mode_b->timing.v_active) &&
(mode_a->timing.h_active == mode_b->timing.h_active));
}
void dsi_conn_set_allowed_mode_switch(struct drm_connector *connector,
void *display)
{
u32 mode_idx = 0, cmp_mode_idx = 0;
struct drm_display_mode *drm_mode, *cmp_drm_mode;
struct dsi_display_mode dsi_mode, *panel_dsi_mode, *cmp_panel_dsi_mode;
struct list_head *mode_list = &connector->modes;
struct dsi_display *disp = display;
struct dsi_panel *panel;
int mode_count, rc = 0;
struct dsi_display_mode_priv_info *dsi_mode_info, *cmp_dsi_mode_info;
bool allow_switch = false;
if (!disp || !disp->panel) {
DSI_ERR("invalid parameters");
return;
}
panel = disp->panel;
mode_count = panel->num_display_modes;
list_for_each_entry(drm_mode, &connector->modes, head) {
convert_to_dsi_mode(drm_mode, &dsi_mode);
rc = dsi_display_find_mode(display, &dsi_mode, &panel_dsi_mode);
if (rc)
return;
dsi_mode_info = panel_dsi_mode->priv_info;
dsi_mode_info->allowed_mode_switch |= BIT(mode_idx);
if (mode_idx == mode_count - 1)
break;
mode_list = mode_list->next;
cmp_mode_idx = 1;
list_for_each_entry(cmp_drm_mode, mode_list, head) {
convert_to_dsi_mode(cmp_drm_mode, &dsi_mode);
rc = dsi_display_find_mode(display, &dsi_mode,
&cmp_panel_dsi_mode);
if (rc)
return;
cmp_dsi_mode_info = cmp_panel_dsi_mode->priv_info;
allow_switch = false;
/*
* FPS switch among video modes, is only supported
* if DFPS or dynamic clocks are specified.
* Reject any mode switches between video mode timing
* nodes if support for those features is not present.
*/
if (panel_dsi_mode->panel_mode ==
cmp_panel_dsi_mode->panel_mode) {
if (panel_dsi_mode->panel_mode ==
DSI_OP_CMD_MODE)
allow_switch = true;
else if (panel->dfps_caps.dfps_support ||
panel->dyn_clk_caps.dyn_clk_support)
allow_switch = true;
} else {
if (is_valid_poms_switch(panel_dsi_mode,
cmp_panel_dsi_mode))
allow_switch = true;
}
if (allow_switch) {
dsi_mode_info->allowed_mode_switch |=
BIT(mode_idx + cmp_mode_idx);
cmp_dsi_mode_info->allowed_mode_switch |=
BIT(mode_idx);
}
if ((mode_idx + cmp_mode_idx) >= mode_count - 1)
break;
cmp_mode_idx++;
}
mode_idx++;
}
}