@@ -289,6 +289,7 @@ struct zynqmp_dp_config {
289289 * @phy: PHY handles for DP lanes
290290 * @num_lanes: number of enabled phy lanes
291291 * @hpd_work: hot plug detection worker
292+ * @hpd_irq_work: hot plug detection IRQ worker
292293 * @status: connection status
293294 * @enabled: flag to indicate if the device is enabled
294295 * @dpcd: DP configuration data from currently connected sink device
@@ -304,6 +305,7 @@ struct zynqmp_dp {
304305 struct drm_dp_aux aux ;
305306 struct drm_bridge bridge ;
306307 struct work_struct hpd_work ;
308+ struct work_struct hpd_irq_work ;
307309 struct mutex lock ;
308310
309311 struct drm_bridge * next_bridge ;
@@ -1671,6 +1673,29 @@ static void zynqmp_dp_hpd_work_func(struct work_struct *work)
16711673 drm_bridge_hpd_notify (& dp -> bridge , status );
16721674}
16731675
1676+ static void zynqmp_dp_hpd_irq_work_func (struct work_struct * work )
1677+ {
1678+ struct zynqmp_dp * dp = container_of (work , struct zynqmp_dp ,
1679+ hpd_irq_work );
1680+ u8 status [DP_LINK_STATUS_SIZE + 2 ];
1681+ int err ;
1682+
1683+ mutex_lock (& dp -> lock );
1684+ err = drm_dp_dpcd_read (& dp -> aux , DP_SINK_COUNT , status ,
1685+ DP_LINK_STATUS_SIZE + 2 );
1686+ if (err < 0 ) {
1687+ dev_dbg_ratelimited (dp -> dev ,
1688+ "could not read sink status: %d\n" , err );
1689+ } else {
1690+ if (status [4 ] & DP_LINK_STATUS_UPDATED ||
1691+ !drm_dp_clock_recovery_ok (& status [2 ], dp -> mode .lane_cnt ) ||
1692+ !drm_dp_channel_eq_ok (& status [2 ], dp -> mode .lane_cnt )) {
1693+ zynqmp_dp_train_loop (dp );
1694+ }
1695+ }
1696+ mutex_unlock (& dp -> lock );
1697+ }
1698+
16741699static irqreturn_t zynqmp_dp_irq_handler (int irq , void * data )
16751700{
16761701 struct zynqmp_dp * dp = (struct zynqmp_dp * )data ;
@@ -1702,23 +1727,9 @@ static irqreturn_t zynqmp_dp_irq_handler(int irq, void *data)
17021727 if (status & ZYNQMP_DP_INT_HPD_EVENT )
17031728 schedule_work (& dp -> hpd_work );
17041729
1705- if (status & ZYNQMP_DP_INT_HPD_IRQ ) {
1706- int ret ;
1707- u8 status [DP_LINK_STATUS_SIZE + 2 ];
1708-
1709- ret = drm_dp_dpcd_read (& dp -> aux , DP_SINK_COUNT , status ,
1710- DP_LINK_STATUS_SIZE + 2 );
1711- if (ret < 0 )
1712- goto handled ;
1713-
1714- if (status [4 ] & DP_LINK_STATUS_UPDATED ||
1715- !drm_dp_clock_recovery_ok (& status [2 ], dp -> mode .lane_cnt ) ||
1716- !drm_dp_channel_eq_ok (& status [2 ], dp -> mode .lane_cnt )) {
1717- zynqmp_dp_train_loop (dp );
1718- }
1719- }
1730+ if (status & ZYNQMP_DP_INT_HPD_IRQ )
1731+ schedule_work (& dp -> hpd_irq_work );
17201732
1721- handled :
17221733 return IRQ_HANDLED ;
17231734}
17241735
@@ -1744,6 +1755,7 @@ int zynqmp_dp_probe(struct zynqmp_dpsub *dpsub)
17441755 mutex_init (& dp -> lock );
17451756
17461757 INIT_WORK (& dp -> hpd_work , zynqmp_dp_hpd_work_func );
1758+ INIT_WORK (& dp -> hpd_irq_work , zynqmp_dp_hpd_irq_work_func );
17471759
17481760 /* Acquire all resources (IOMEM, IRQ and PHYs). */
17491761 res = platform_get_resource_byname (pdev , IORESOURCE_MEM , "dp" );
@@ -1848,6 +1860,7 @@ void zynqmp_dp_remove(struct zynqmp_dpsub *dpsub)
18481860 zynqmp_dp_write (dp , ZYNQMP_DP_INT_DS , ZYNQMP_DP_INT_ALL );
18491861 disable_irq (dp -> irq );
18501862
1863+ cancel_work_sync (& dp -> hpd_irq_work );
18511864 cancel_work_sync (& dp -> hpd_work );
18521865
18531866 zynqmp_dp_write (dp , ZYNQMP_DP_TRANSMITTER_ENABLE , 0 );
0 commit comments