summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/bridge
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/bridge')
-rw-r--r--drivers/gpu/drm/bridge/Kconfig3
-rw-r--r--drivers/gpu/drm/bridge/analogix/analogix_dp_core.c97
-rw-r--r--drivers/gpu/drm/bridge/sii902x.c20
-rw-r--r--drivers/gpu/drm/bridge/synopsys/dw-hdmi.c3
-rw-r--r--drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c10
5 files changed, 65 insertions, 68 deletions
diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig
index 3b99d5a06c16..3aa65bdecb0e 100644
--- a/drivers/gpu/drm/bridge/Kconfig
+++ b/drivers/gpu/drm/bridge/Kconfig
@@ -30,7 +30,8 @@ config DRM_DUMB_VGA_DAC
depends on OF
select DRM_KMS_HELPER
help
- Support for RGB to VGA DAC based bridges
+ Support for non-programmable RGB to VGA DAC bridges, such as ADI
+ ADV7123, TI THS8134 and THS8135 or passive resistor ladder DACs.
config DRM_LVDS_ENCODER
tristate "Transparent parallel to LVDS encoder support"
diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
index b2756bc4225a..a693ab3078f0 100644
--- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
+++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
@@ -98,17 +98,15 @@ static int analogix_dp_detect_hpd(struct analogix_dp_device *dp)
return 0;
}
-int analogix_dp_psr_supported(struct device *dev)
+int analogix_dp_psr_supported(struct analogix_dp_device *dp)
{
- struct analogix_dp_device *dp = dev_get_drvdata(dev);
return dp->psr_support;
}
EXPORT_SYMBOL_GPL(analogix_dp_psr_supported);
-int analogix_dp_enable_psr(struct device *dev)
+int analogix_dp_enable_psr(struct analogix_dp_device *dp)
{
- struct analogix_dp_device *dp = dev_get_drvdata(dev);
struct edp_vsc_psr psr_vsc;
if (!dp->psr_support)
@@ -129,9 +127,8 @@ int analogix_dp_enable_psr(struct device *dev)
}
EXPORT_SYMBOL_GPL(analogix_dp_enable_psr);
-int analogix_dp_disable_psr(struct device *dev)
+int analogix_dp_disable_psr(struct analogix_dp_device *dp)
{
- struct analogix_dp_device *dp = dev_get_drvdata(dev);
struct edp_vsc_psr psr_vsc;
int ret;
@@ -1015,27 +1012,30 @@ static int analogix_dp_bridge_attach(struct drm_bridge *bridge)
{
struct analogix_dp_device *dp = bridge->driver_private;
struct drm_encoder *encoder = dp->encoder;
- struct drm_connector *connector = &dp->connector;
- int ret;
+ struct drm_connector *connector = NULL;
+ int ret = 0;
if (!bridge->encoder) {
DRM_ERROR("Parent encoder object not found");
return -ENODEV;
}
- connector->polled = DRM_CONNECTOR_POLL_HPD;
+ if (!dp->plat_data->skip_connector) {
+ connector = &dp->connector;
+ connector->polled = DRM_CONNECTOR_POLL_HPD;
- ret = drm_connector_init(dp->drm_dev, connector,
- &analogix_dp_connector_funcs,
- DRM_MODE_CONNECTOR_eDP);
- if (ret) {
- DRM_ERROR("Failed to initialize connector with drm\n");
- return ret;
- }
+ ret = drm_connector_init(dp->drm_dev, connector,
+ &analogix_dp_connector_funcs,
+ DRM_MODE_CONNECTOR_eDP);
+ if (ret) {
+ DRM_ERROR("Failed to initialize connector with drm\n");
+ return ret;
+ }
- drm_connector_helper_add(connector,
- &analogix_dp_connector_helper_funcs);
- drm_mode_connector_attach_encoder(connector, encoder);
+ drm_connector_helper_add(connector,
+ &analogix_dp_connector_helper_funcs);
+ drm_mode_connector_attach_encoder(connector, encoder);
+ }
/*
* NOTE: the connector registration is implemented in analogix
@@ -1279,8 +1279,9 @@ static ssize_t analogix_dpaux_transfer(struct drm_dp_aux *aux,
return analogix_dp_transfer(dp, msg);
}
-int analogix_dp_bind(struct device *dev, struct drm_device *drm_dev,
- struct analogix_dp_plat_data *plat_data)
+struct analogix_dp_device *
+analogix_dp_bind(struct device *dev, struct drm_device *drm_dev,
+ struct analogix_dp_plat_data *plat_data)
{
struct platform_device *pdev = to_platform_device(dev);
struct analogix_dp_device *dp;
@@ -1290,14 +1291,12 @@ int analogix_dp_bind(struct device *dev, struct drm_device *drm_dev,
if (!plat_data) {
dev_err(dev, "Invalided input plat_data\n");
- return -EINVAL;
+ return ERR_PTR(-EINVAL);
}
dp = devm_kzalloc(dev, sizeof(struct analogix_dp_device), GFP_KERNEL);
if (!dp)
- return -ENOMEM;
-
- dev_set_drvdata(dev, dp);
+ return ERR_PTR(-ENOMEM);
dp->dev = &pdev->dev;
dp->dpms_mode = DRM_MODE_DPMS_OFF;
@@ -1314,7 +1313,7 @@ int analogix_dp_bind(struct device *dev, struct drm_device *drm_dev,
ret = analogix_dp_dt_parse_pdata(dp);
if (ret)
- return ret;
+ return ERR_PTR(ret);
dp->phy = devm_phy_get(dp->dev, "dp");
if (IS_ERR(dp->phy)) {
@@ -1328,14 +1327,14 @@ int analogix_dp_bind(struct device *dev, struct drm_device *drm_dev,
if (ret == -ENOSYS || ret == -ENODEV)
dp->phy = NULL;
else
- return ret;
+ return ERR_PTR(ret);
}
}
dp->clock = devm_clk_get(&pdev->dev, "dp");
if (IS_ERR(dp->clock)) {
dev_err(&pdev->dev, "failed to get clock\n");
- return PTR_ERR(dp->clock);
+ return ERR_CAST(dp->clock);
}
clk_prepare_enable(dp->clock);
@@ -1344,7 +1343,7 @@ int analogix_dp_bind(struct device *dev, struct drm_device *drm_dev,
dp->reg_base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(dp->reg_base))
- return PTR_ERR(dp->reg_base);
+ return ERR_CAST(dp->reg_base);
dp->force_hpd = of_property_read_bool(dev->of_node, "force-hpd");
@@ -1365,7 +1364,7 @@ int analogix_dp_bind(struct device *dev, struct drm_device *drm_dev,
"hpd_gpio");
if (ret) {
dev_err(&pdev->dev, "failed to get hpd gpio\n");
- return ret;
+ return ERR_PTR(ret);
}
dp->irq = gpio_to_irq(dp->hpd_gpio);
irq_flags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING;
@@ -1377,16 +1376,9 @@ int analogix_dp_bind(struct device *dev, struct drm_device *drm_dev,
if (dp->irq == -ENXIO) {
dev_err(&pdev->dev, "failed to get irq\n");
- return -ENODEV;
+ return ERR_PTR(-ENODEV);
}
- pm_runtime_enable(dev);
-
- pm_runtime_get_sync(dev);
- phy_power_on(dp->phy);
-
- analogix_dp_init_dp(dp);
-
ret = devm_request_threaded_irq(&pdev->dev, dp->irq,
analogix_dp_hardirq,
analogix_dp_irq_thread,
@@ -1406,38 +1398,30 @@ int analogix_dp_bind(struct device *dev, struct drm_device *drm_dev,
ret = drm_dp_aux_register(&dp->aux);
if (ret)
- goto err_disable_pm_runtime;
+ return ERR_PTR(ret);
+
+ pm_runtime_enable(dev);
ret = analogix_dp_create_bridge(drm_dev, dp);
if (ret) {
DRM_ERROR("failed to create bridge (%d)\n", ret);
- drm_encoder_cleanup(dp->encoder);
goto err_disable_pm_runtime;
}
- phy_power_off(dp->phy);
- pm_runtime_put(dev);
-
- return 0;
+ return dp;
err_disable_pm_runtime:
- phy_power_off(dp->phy);
- pm_runtime_put(dev);
pm_runtime_disable(dev);
- return ret;
+ return ERR_PTR(ret);
}
EXPORT_SYMBOL_GPL(analogix_dp_bind);
-void analogix_dp_unbind(struct device *dev, struct device *master,
- void *data)
+void analogix_dp_unbind(struct analogix_dp_device *dp)
{
- struct analogix_dp_device *dp = dev_get_drvdata(dev);
-
analogix_dp_bridge_disable(dp->bridge);
dp->connector.funcs->destroy(&dp->connector);
- dp->encoder->funcs->destroy(dp->encoder);
if (dp->plat_data->panel) {
if (drm_panel_unprepare(dp->plat_data->panel))
@@ -1447,16 +1431,14 @@ void analogix_dp_unbind(struct device *dev, struct device *master,
}
drm_dp_aux_unregister(&dp->aux);
- pm_runtime_disable(dev);
+ pm_runtime_disable(dp->dev);
clk_disable_unprepare(dp->clock);
}
EXPORT_SYMBOL_GPL(analogix_dp_unbind);
#ifdef CONFIG_PM
-int analogix_dp_suspend(struct device *dev)
+int analogix_dp_suspend(struct analogix_dp_device *dp)
{
- struct analogix_dp_device *dp = dev_get_drvdata(dev);
-
clk_disable_unprepare(dp->clock);
if (dp->plat_data->panel) {
@@ -1468,9 +1450,8 @@ int analogix_dp_suspend(struct device *dev)
}
EXPORT_SYMBOL_GPL(analogix_dp_suspend);
-int analogix_dp_resume(struct device *dev)
+int analogix_dp_resume(struct analogix_dp_device *dp)
{
- struct analogix_dp_device *dp = dev_get_drvdata(dev);
int ret;
ret = clk_prepare_enable(dp->clock);
diff --git a/drivers/gpu/drm/bridge/sii902x.c b/drivers/gpu/drm/bridge/sii902x.c
index b1ab4ab09532..60373d7eb220 100644
--- a/drivers/gpu/drm/bridge/sii902x.c
+++ b/drivers/gpu/drm/bridge/sii902x.c
@@ -137,7 +137,9 @@ static int sii902x_get_modes(struct drm_connector *connector)
struct sii902x *sii902x = connector_to_sii902x(connector);
struct regmap *regmap = sii902x->regmap;
u32 bus_format = MEDIA_BUS_FMT_RGB888_1X24;
+ struct device *dev = &sii902x->i2c->dev;
unsigned long timeout;
+ unsigned int retries;
unsigned int status;
struct edid *edid;
int num = 0;
@@ -159,7 +161,7 @@ static int sii902x_get_modes(struct drm_connector *connector)
time_before(jiffies, timeout));
if (!(status & SII902X_SYS_CTRL_DDC_BUS_GRTD)) {
- dev_err(&sii902x->i2c->dev, "failed to acquire the i2c bus\n");
+ dev_err(dev, "failed to acquire the i2c bus\n");
return -ETIMEDOUT;
}
@@ -179,9 +181,19 @@ static int sii902x_get_modes(struct drm_connector *connector)
if (ret)
return ret;
- ret = regmap_read(regmap, SII902X_SYS_CTRL_DATA, &status);
+ /*
+ * Sometimes the I2C bus can stall after failure to use the
+ * EDID channel. Retry a few times to see if things clear
+ * up, else continue anyway.
+ */
+ retries = 5;
+ do {
+ ret = regmap_read(regmap, SII902X_SYS_CTRL_DATA,
+ &status);
+ retries--;
+ } while (ret && retries);
if (ret)
- return ret;
+ dev_err(dev, "failed to read status (%d)\n", ret);
ret = regmap_update_bits(regmap, SII902X_SYS_CTRL_DATA,
SII902X_SYS_CTRL_DDC_BUS_REQ |
@@ -201,7 +213,7 @@ static int sii902x_get_modes(struct drm_connector *connector)
if (status & (SII902X_SYS_CTRL_DDC_BUS_REQ |
SII902X_SYS_CTRL_DDC_BUS_GRTD)) {
- dev_err(&sii902x->i2c->dev, "failed to release the i2c bus\n");
+ dev_err(dev, "failed to release the i2c bus\n");
return -ETIMEDOUT;
}
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
index f9802399cc0d..53ebbe2904b6 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
@@ -1654,6 +1654,8 @@ static void dw_hdmi_clear_overflow(struct dw_hdmi *hdmi)
* (v1.31a) and multiple Allwinner SoCs (v1.32a) have been identified
* as needing the workaround, with 4 iterations for v1.30a and 1
* iteration for others.
+ * The Amlogic Meson GX SoCs (v2.01a) have been identified as needing
+ * the workaround with a single iteration.
*/
switch (hdmi->version) {
@@ -1662,6 +1664,7 @@ static void dw_hdmi_clear_overflow(struct dw_hdmi *hdmi)
break;
case 0x131a:
case 0x132a:
+ case 0x201a:
count = 1;
break;
default:
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c
index 7bac101c285c..226171a3ece1 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c
@@ -342,7 +342,7 @@ static int dw_mipi_dsi_gen_pkt_hdr_write(struct dw_mipi_dsi *dsi, u32 hdr_val)
ret = readl_poll_timeout(dsi->base + DSI_CMD_PKT_STATUS,
val, !(val & GEN_CMD_FULL), 1000,
CMD_PKT_STATUS_TIMEOUT_US);
- if (ret < 0) {
+ if (ret) {
dev_err(dsi->dev, "failed to get available command FIFO\n");
return ret;
}
@@ -353,7 +353,7 @@ static int dw_mipi_dsi_gen_pkt_hdr_write(struct dw_mipi_dsi *dsi, u32 hdr_val)
ret = readl_poll_timeout(dsi->base + DSI_CMD_PKT_STATUS,
val, (val & mask) == mask,
1000, CMD_PKT_STATUS_TIMEOUT_US);
- if (ret < 0) {
+ if (ret) {
dev_err(dsi->dev, "failed to write command FIFO\n");
return ret;
}
@@ -385,7 +385,7 @@ static int dw_mipi_dsi_write(struct dw_mipi_dsi *dsi,
ret = readl_poll_timeout(dsi->base + DSI_CMD_PKT_STATUS,
val, !(val & GEN_PLD_W_FULL), 1000,
CMD_PKT_STATUS_TIMEOUT_US);
- if (ret < 0) {
+ if (ret) {
dev_err(dsi->dev,
"failed to get available write payload FIFO\n");
return ret;
@@ -721,13 +721,13 @@ static void dw_mipi_dsi_dphy_enable(struct dw_mipi_dsi *dsi)
ret = readl_poll_timeout(dsi->base + DSI_PHY_STATUS, val,
val & PHY_LOCK, 1000, PHY_STATUS_TIMEOUT_US);
- if (ret < 0)
+ if (ret)
DRM_DEBUG_DRIVER("failed to wait phy lock state\n");
ret = readl_poll_timeout(dsi->base + DSI_PHY_STATUS,
val, val & PHY_STOP_STATE_CLK_LANE, 1000,
PHY_STATUS_TIMEOUT_US);
- if (ret < 0)
+ if (ret)
DRM_DEBUG_DRIVER("failed to wait phy clk lane stop state\n");
}
OpenPOWER on IntegriCloud