aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/drm/bridge/dw_hdmi.c29
1 files changed, 22 insertions, 7 deletions
diff --git a/drivers/gpu/drm/bridge/dw_hdmi.c b/drivers/gpu/drm/bridge/dw_hdmi.c
index cef31d5cacb3..c5c4553258b6 100644
--- a/drivers/gpu/drm/bridge/dw_hdmi.c
+++ b/drivers/gpu/drm/bridge/dw_hdmi.c
@@ -125,6 +125,9 @@ struct dw_hdmi {
125 bool sink_is_hdmi; 125 bool sink_is_hdmi;
126 bool sink_has_audio; 126 bool sink_has_audio;
127 127
128 struct mutex mutex; /* for state below and previous_mode */
129 bool disabled; /* DRM has disabled our bridge */
130
128 spinlock_t audio_lock; 131 spinlock_t audio_lock;
129 struct mutex audio_mutex; 132 struct mutex audio_mutex;
130 unsigned int sample_rate; 133 unsigned int sample_rate;
@@ -1375,8 +1378,12 @@ static void dw_hdmi_bridge_mode_set(struct drm_bridge *bridge,
1375{ 1378{
1376 struct dw_hdmi *hdmi = bridge->driver_private; 1379 struct dw_hdmi *hdmi = bridge->driver_private;
1377 1380
1381 mutex_lock(&hdmi->mutex);
1382
1378 /* Store the display mode for plugin/DKMS poweron events */ 1383 /* Store the display mode for plugin/DKMS poweron events */
1379 memcpy(&hdmi->previous_mode, mode, sizeof(hdmi->previous_mode)); 1384 memcpy(&hdmi->previous_mode, mode, sizeof(hdmi->previous_mode));
1385
1386 mutex_unlock(&hdmi->mutex);
1380} 1387}
1381 1388
1382static bool dw_hdmi_bridge_mode_fixup(struct drm_bridge *bridge, 1389static bool dw_hdmi_bridge_mode_fixup(struct drm_bridge *bridge,
@@ -1390,14 +1397,20 @@ static void dw_hdmi_bridge_disable(struct drm_bridge *bridge)
1390{ 1397{
1391 struct dw_hdmi *hdmi = bridge->driver_private; 1398 struct dw_hdmi *hdmi = bridge->driver_private;
1392 1399
1400 mutex_lock(&hdmi->mutex);
1401 hdmi->disabled = true;
1393 dw_hdmi_poweroff(hdmi); 1402 dw_hdmi_poweroff(hdmi);
1403 mutex_unlock(&hdmi->mutex);
1394} 1404}
1395 1405
1396static void dw_hdmi_bridge_enable(struct drm_bridge *bridge) 1406static void dw_hdmi_bridge_enable(struct drm_bridge *bridge)
1397{ 1407{
1398 struct dw_hdmi *hdmi = bridge->driver_private; 1408 struct dw_hdmi *hdmi = bridge->driver_private;
1399 1409
1410 mutex_lock(&hdmi->mutex);
1400 dw_hdmi_poweron(hdmi); 1411 dw_hdmi_poweron(hdmi);
1412 hdmi->disabled = false;
1413 mutex_unlock(&hdmi->mutex);
1401} 1414}
1402 1415
1403static void dw_hdmi_bridge_nop(struct drm_bridge *bridge) 1416static void dw_hdmi_bridge_nop(struct drm_bridge *bridge)
@@ -1520,20 +1533,20 @@ static irqreturn_t dw_hdmi_irq(int irq, void *dev_id)
1520 phy_int_pol = hdmi_readb(hdmi, HDMI_PHY_POL0); 1533 phy_int_pol = hdmi_readb(hdmi, HDMI_PHY_POL0);
1521 1534
1522 if (intr_stat & HDMI_IH_PHY_STAT0_HPD) { 1535 if (intr_stat & HDMI_IH_PHY_STAT0_HPD) {
1536 hdmi_modb(hdmi, ~phy_int_pol, HDMI_PHY_HPD, HDMI_PHY_POL0);
1537 mutex_lock(&hdmi->mutex);
1523 if (phy_int_pol & HDMI_PHY_HPD) { 1538 if (phy_int_pol & HDMI_PHY_HPD) {
1524 dev_dbg(hdmi->dev, "EVENT=plugin\n"); 1539 dev_dbg(hdmi->dev, "EVENT=plugin\n");
1525 1540
1526 hdmi_modb(hdmi, 0, HDMI_PHY_HPD, HDMI_PHY_POL0); 1541 if (!hdmi->disabled)
1527 1542 dw_hdmi_poweron(hdmi);
1528 dw_hdmi_poweron(hdmi);
1529 } else { 1543 } else {
1530 dev_dbg(hdmi->dev, "EVENT=plugout\n"); 1544 dev_dbg(hdmi->dev, "EVENT=plugout\n");
1531 1545
1532 hdmi_modb(hdmi, HDMI_PHY_HPD, HDMI_PHY_HPD, 1546 if (!hdmi->disabled)
1533 HDMI_PHY_POL0); 1547 dw_hdmi_poweroff(hdmi);
1534
1535 dw_hdmi_poweroff(hdmi);
1536 } 1548 }
1549 mutex_unlock(&hdmi->mutex);
1537 drm_helper_hpd_irq_event(hdmi->bridge->dev); 1550 drm_helper_hpd_irq_event(hdmi->bridge->dev);
1538 } 1551 }
1539 1552
@@ -1601,7 +1614,9 @@ int dw_hdmi_bind(struct device *dev, struct device *master,
1601 hdmi->sample_rate = 48000; 1614 hdmi->sample_rate = 48000;
1602 hdmi->ratio = 100; 1615 hdmi->ratio = 100;
1603 hdmi->encoder = encoder; 1616 hdmi->encoder = encoder;
1617 hdmi->disabled = true;
1604 1618
1619 mutex_init(&hdmi->mutex);
1605 mutex_init(&hdmi->audio_mutex); 1620 mutex_init(&hdmi->audio_mutex);
1606 spin_lock_init(&hdmi->audio_lock); 1621 spin_lock_init(&hdmi->audio_lock);
1607 1622