summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/bridge/cadence/cdns-hdmi-core.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/bridge/cadence/cdns-hdmi-core.c')
-rw-r--r--drivers/gpu/drm/bridge/cadence/cdns-hdmi-core.c47
1 files changed, 38 insertions, 9 deletions
diff --git a/drivers/gpu/drm/bridge/cadence/cdns-hdmi-core.c b/drivers/gpu/drm/bridge/cadence/cdns-hdmi-core.c
index 73a7d0a04f21..067290b3b3ad 100644
--- a/drivers/gpu/drm/bridge/cadence/cdns-hdmi-core.c
+++ b/drivers/gpu/drm/bridge/cadence/cdns-hdmi-core.c
@@ -226,6 +226,7 @@ void cdns_hdmi_mode_set(struct cdns_mhdp_device *mhdp)
static enum drm_connector_status
cdns_hdmi_connector_detect(struct drm_connector *connector, bool force)
{
+ struct edid *edid;
struct cdns_mhdp_device *mhdp =
container_of(connector, struct cdns_mhdp_device, connector.base);
@@ -233,15 +234,21 @@ cdns_hdmi_connector_detect(struct drm_connector *connector, bool force)
hpd = cdns_mhdp_read_hpd(mhdp);
- if (hpd == 1)
+ if (hpd == 1) {
/* Cable Connected */
return connector_status_connected;
- else if (hpd == 0)
+ } else if (hpd == 0) {
/* Cable Disconnedted */
return connector_status_disconnected;
- else {
+ } else if (mhdp->ddc) {
+ edid = drm_get_edid(connector, mhdp->ddc);
+ if (drm_edid_is_valid(edid))
+ return connector_status_connected;
+ else
+ return connector_status_disconnected;
+ } else {
/* Cable status unknown */
- DRM_INFO("Unknow cable status, hdp=%u\n", hpd);
+ DRM_INFO("Unknow cable status, hpd=%u\n", hpd);
return connector_status_unknown;
}
}
@@ -253,8 +260,15 @@ static int cdns_hdmi_connector_get_modes(struct drm_connector *connector)
int num_modes = 0;
struct edid *edid;
- edid = drm_do_get_edid(&mhdp->connector.base,
- cdns_hdmi_get_edid_block, mhdp);
+ /*
+ * Check if optional regular DDC I2C bus should be used.
+ * Fall-back to using IP/firmware integrated one.
+ */
+ if (mhdp->ddc)
+ edid = drm_get_edid(&mhdp->connector.base, mhdp->ddc);
+ else
+ edid = drm_do_get_edid(&mhdp->connector.base,
+ cdns_hdmi_get_edid_block, mhdp);
if (edid) {
dev_info(mhdp->dev, "%x,%x,%x,%x,%x,%x,%x,%x\n",
edid->header[0], edid->header[1],
@@ -374,9 +388,12 @@ cdns_hdmi_bridge_mode_valid(struct drm_bridge *bridge,
if (mode->hdisplay > 3840 || mode->vdisplay > 2160)
return MODE_BAD_HVALUE;
- vic = drm_match_cea_mode(mode);
- if (vic == 0)
- return MODE_BAD;
+ /* imx8mq-hdmi does not support non CEA modes */
+ if (!strncmp("imx8mq-hdmi", mhdp->plat_data->plat_name, 11)) {
+ vic = drm_match_cea_mode(mode);
+ if (vic == 0)
+ return MODE_BAD;
+ }
mhdp->valid_mode = mode;
ret = cdns_mhdp_plat_call(mhdp, phy_video_valid);
@@ -503,6 +520,7 @@ static irqreturn_t cdns_hdmi_irq_thread(int irq, void *data)
static void cdns_hdmi_parse_dt(struct cdns_mhdp_device *mhdp)
{
struct device_node *of_node = mhdp->dev->of_node;
+ struct device_node *ddc_phandle;
int ret;
ret = of_property_read_u32(of_node, "lane-mapping", &mhdp->lane_mapping);
@@ -511,6 +529,17 @@ static void cdns_hdmi_parse_dt(struct cdns_mhdp_device *mhdp)
dev_warn(mhdp->dev, "Failed to get lane_mapping - using default 0xc6\n");
}
dev_info(mhdp->dev, "lane-mapping 0x%02x\n", mhdp->lane_mapping);
+
+ /* get optional regular DDC I2C bus */
+ ddc_phandle = of_parse_phandle(of_node, "ddc-i2c-bus", 0);
+ if (ddc_phandle) {
+ mhdp->ddc = of_get_i2c_adapter_by_node(ddc_phandle);
+ if (mhdp->ddc)
+ dev_info(mhdp->dev, "Connector's ddc i2c bus found\n");
+ else
+ ret = -EPROBE_DEFER;
+ of_node_put(ddc_phandle);
+ }
}
static int __cdns_hdmi_probe(struct platform_device *pdev,