drm/rockchip: dw_hdmi: check display mode with crtc mode valid

Change-Id: I23470e46b97169da0b59153dfc0835833f1aa549
Signed-off-by: Mark Yao <mark.yao@rock-chips.com>
Signed-off-by: Algea Cao <algea.cao@rock-chips.com>
This commit is contained in:
Algea Cao
2021-07-27 10:10:00 +08:00
committed by Tao Huang
parent 157918bc84
commit 0a52ff8181
3 changed files with 56 additions and 15 deletions
+13 -2
View File
@@ -2509,6 +2509,15 @@ static int dw_hdmi_connector_get_modes(struct drm_connector *connector)
return ret;
}
static struct drm_encoder *
dw_hdmi_connector_best_encoder(struct drm_connector *connector)
{
struct dw_hdmi *hdmi = container_of(connector, struct dw_hdmi,
connector);
return hdmi->bridge.encoder;
}
static bool hdr_metadata_equal(const struct drm_connector_state *old_state,
const struct drm_connector_state *new_state)
{
@@ -2572,6 +2581,7 @@ static const struct drm_connector_funcs dw_hdmi_connector_funcs = {
static const struct drm_connector_helper_funcs dw_hdmi_connector_helper_funcs = {
.get_modes = dw_hdmi_connector_get_modes,
.best_encoder = dw_hdmi_connector_best_encoder,
.atomic_check = dw_hdmi_connector_atomic_check,
};
@@ -2926,6 +2936,7 @@ dw_hdmi_bridge_mode_valid(struct drm_bridge *bridge,
const struct drm_display_mode *mode)
{
struct dw_hdmi *hdmi = bridge->driver_private;
struct drm_connector *connector = &hdmi->connector;
const struct dw_hdmi_plat_data *pdata = hdmi->plat_data;
enum drm_mode_status mode_status = MODE_OK;
@@ -2934,8 +2945,8 @@ dw_hdmi_bridge_mode_valid(struct drm_bridge *bridge,
return MODE_BAD;
if (pdata->mode_valid)
mode_status = pdata->mode_valid(hdmi, pdata->priv_data, info,
mode);
mode_status = pdata->mode_valid(connector, pdata->priv_data,
info, mode);
return mode_status;
}
+41 -12
View File
@@ -273,21 +273,16 @@ static int rockchip_hdmi_parse_dt(struct rockchip_hdmi *hdmi)
}
static enum drm_mode_status
dw_hdmi_rockchip_mode_valid(struct dw_hdmi *hdmi, void *data,
dw_hdmi_rockchip_mode_valid(struct drm_connector *connector, void *data,
const struct drm_display_info *info,
const struct drm_display_mode *mode)
{
const struct dw_hdmi_mpll_config *mpll_cfg = rockchip_mpll_cfg;
int pclk = mode->clock * 1000;
bool valid = false;
int i;
struct drm_encoder *encoder = connector->encoder;
enum drm_mode_status status = MODE_OK;
struct drm_device *dev = connector->dev;
struct rockchip_drm_private *priv = dev->dev_private;
struct drm_crtc *crtc;
for (i = 0; mpll_cfg[i].mpixelclock != (~0UL); i++) {
if (pclk == mpll_cfg[i].mpixelclock) {
valid = true;
break;
}
}
/*
* Pixel clocks we support are always < 2GHz and so fit in an
* int. We should make sure source rate does too so we don't get
@@ -296,7 +291,41 @@ dw_hdmi_rockchip_mode_valid(struct dw_hdmi *hdmi, void *data,
if (mode->clock > INT_MAX / 1000)
return MODE_BAD;
return (valid) ? MODE_OK : MODE_BAD;
if (!encoder) {
const struct drm_connector_helper_funcs *funcs;
funcs = connector->helper_private;
if (funcs->atomic_best_encoder)
encoder = funcs->atomic_best_encoder(connector,
connector->state);
else
encoder = funcs->best_encoder(connector);
}
if (!encoder || !encoder->possible_crtcs)
return MODE_BAD;
/*
* ensure all drm display mode can work, if someone want support more
* resolutions, please limit the possible_crtc, only connect to
* needed crtc.
*/
drm_for_each_crtc(crtc, connector->dev) {
int pipe = drm_crtc_index(crtc);
const struct rockchip_crtc_funcs *funcs =
priv->crtc_funcs[pipe];
if (!(encoder->possible_crtcs & drm_crtc_mask(crtc)))
continue;
if (!funcs || !funcs->mode_valid)
continue;
status = funcs->mode_valid(crtc, mode,
DRM_MODE_CONNECTOR_HDMIA);
if (status != MODE_OK)
return status;
}
return status;
}
static void dw_hdmi_rockchip_encoder_disable(struct drm_encoder *encoder)
+2 -1
View File
@@ -144,7 +144,8 @@ struct dw_hdmi_plat_data {
void *priv_data;
/* Platform-specific mode validation (optional). */
enum drm_mode_status (*mode_valid)(struct dw_hdmi *hdmi, void *data,
enum drm_mode_status (*mode_valid)(struct drm_connector *connector,
void *data,
const struct drm_display_info *info,
const struct drm_display_mode *mode);