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:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user