Skip to content

Commit 2425dee

Browse files
Sean Andersontomba
authored andcommitted
drm: zynqmp_dp: Use AUX IRQs instead of polling
Instead of polling the status register for the AUX status, just enable the IRQs and signal a completion. Signed-off-by: Sean Anderson <[email protected]> Signed-off-by: Tomi Valkeinen <[email protected]> Link: https://patchwork.freedesktop.org/patch/msgid/[email protected]
1 parent 948a944 commit 2425dee

File tree

1 file changed

+25
-10
lines changed

1 file changed

+25
-10
lines changed

drivers/gpu/drm/xlnx/zynqmp_dp.c

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,7 @@ struct zynqmp_dp_config {
286286
* @next_bridge: The downstream bridge
287287
* @config: IP core configuration from DTS
288288
* @aux: aux channel
289+
* @aux_done: Completed when we get an AUX reply or timeout
289290
* @phy: PHY handles for DP lanes
290291
* @num_lanes: number of enabled phy lanes
291292
* @hpd_work: hot plug detection worker
@@ -306,6 +307,7 @@ struct zynqmp_dp {
306307
struct drm_bridge bridge;
307308
struct work_struct hpd_work;
308309
struct work_struct hpd_irq_work;
310+
struct completion aux_done;
309311
struct mutex lock;
310312

311313
struct drm_bridge *next_bridge;
@@ -942,12 +944,15 @@ static int zynqmp_dp_aux_cmd_submit(struct zynqmp_dp *dp, u32 cmd, u16 addr,
942944
u8 *buf, u8 bytes, u8 *reply)
943945
{
944946
bool is_read = (cmd & AUX_READ_BIT) ? true : false;
947+
unsigned long time_left;
945948
u32 reg, i;
946949

947950
reg = zynqmp_dp_read(dp, ZYNQMP_DP_INTERRUPT_SIGNAL_STATE);
948951
if (reg & ZYNQMP_DP_INTERRUPT_SIGNAL_STATE_REQUEST)
949952
return -EBUSY;
950953

954+
reinit_completion(&dp->aux_done);
955+
951956
zynqmp_dp_write(dp, ZYNQMP_DP_AUX_ADDRESS, addr);
952957
if (!is_read)
953958
for (i = 0; i < bytes; i++)
@@ -962,17 +967,14 @@ static int zynqmp_dp_aux_cmd_submit(struct zynqmp_dp *dp, u32 cmd, u16 addr,
962967
zynqmp_dp_write(dp, ZYNQMP_DP_AUX_COMMAND, reg);
963968

964969
/* Wait for reply to be delivered upto 2ms */
965-
for (i = 0; ; i++) {
966-
reg = zynqmp_dp_read(dp, ZYNQMP_DP_INTERRUPT_SIGNAL_STATE);
967-
if (reg & ZYNQMP_DP_INTERRUPT_SIGNAL_STATE_REPLY)
968-
break;
970+
time_left = wait_for_completion_timeout(&dp->aux_done,
971+
msecs_to_jiffies(2));
972+
if (!time_left)
973+
return -ETIMEDOUT;
969974

970-
if (reg & ZYNQMP_DP_INTERRUPT_SIGNAL_STATE_REPLY_TIMEOUT ||
971-
i == 2)
972-
return -ETIMEDOUT;
973-
974-
usleep_range(1000, 1100);
975-
}
975+
reg = zynqmp_dp_read(dp, ZYNQMP_DP_INTERRUPT_SIGNAL_STATE);
976+
if (reg & ZYNQMP_DP_INTERRUPT_SIGNAL_STATE_REPLY_TIMEOUT)
977+
return -ETIMEDOUT;
976978

977979
reg = zynqmp_dp_read(dp, ZYNQMP_DP_AUX_REPLY_CODE);
978980
if (reply)
@@ -1056,6 +1058,9 @@ static int zynqmp_dp_aux_init(struct zynqmp_dp *dp)
10561058
(w << ZYNQMP_DP_AUX_CLK_DIVIDER_AUX_FILTER_SHIFT) |
10571059
(rate / (1000 * 1000)));
10581060

1061+
zynqmp_dp_write(dp, ZYNQMP_DP_INT_EN, ZYNQMP_DP_INT_REPLY_RECEIVED |
1062+
ZYNQMP_DP_INT_REPLY_TIMEOUT);
1063+
10591064
dp->aux.name = "ZynqMP DP AUX";
10601065
dp->aux.dev = dp->dev;
10611066
dp->aux.drm_dev = dp->bridge.dev;
@@ -1073,6 +1078,9 @@ static int zynqmp_dp_aux_init(struct zynqmp_dp *dp)
10731078
static void zynqmp_dp_aux_cleanup(struct zynqmp_dp *dp)
10741079
{
10751080
drm_dp_aux_unregister(&dp->aux);
1081+
1082+
zynqmp_dp_write(dp, ZYNQMP_DP_INT_DS, ZYNQMP_DP_INT_REPLY_RECEIVED |
1083+
ZYNQMP_DP_INT_REPLY_TIMEOUT);
10761084
}
10771085

10781086
/* -----------------------------------------------------------------------------
@@ -1730,6 +1738,12 @@ static irqreturn_t zynqmp_dp_irq_handler(int irq, void *data)
17301738
if (status & ZYNQMP_DP_INT_HPD_IRQ)
17311739
schedule_work(&dp->hpd_irq_work);
17321740

1741+
if (status & ZYNQMP_DP_INTERRUPT_SIGNAL_STATE_REPLY)
1742+
complete(&dp->aux_done);
1743+
1744+
if (status & ZYNQMP_DP_INTERRUPT_SIGNAL_STATE_REPLY_TIMEOUT)
1745+
complete(&dp->aux_done);
1746+
17331747
return IRQ_HANDLED;
17341748
}
17351749

@@ -1753,6 +1767,7 @@ int zynqmp_dp_probe(struct zynqmp_dpsub *dpsub)
17531767
dp->dpsub = dpsub;
17541768
dp->status = connector_status_disconnected;
17551769
mutex_init(&dp->lock);
1770+
init_completion(&dp->aux_done);
17561771

17571772
INIT_WORK(&dp->hpd_work, zynqmp_dp_hpd_work_func);
17581773
INIT_WORK(&dp->hpd_irq_work, zynqmp_dp_hpd_irq_work_func);

0 commit comments

Comments
 (0)