mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-02-26 12:16:05 -05:00
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 <sean.anderson@linux.dev> Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com> Link: https://patchwork.freedesktop.org/patch/msgid/20240809193600.3360015-6-sean.anderson@linux.dev
This commit is contained in:
committed by
Tomi Valkeinen
parent
948a944ea7
commit
2425dee876
@@ -286,6 +286,7 @@ struct zynqmp_dp_config {
|
||||
* @next_bridge: The downstream bridge
|
||||
* @config: IP core configuration from DTS
|
||||
* @aux: aux channel
|
||||
* @aux_done: Completed when we get an AUX reply or timeout
|
||||
* @phy: PHY handles for DP lanes
|
||||
* @num_lanes: number of enabled phy lanes
|
||||
* @hpd_work: hot plug detection worker
|
||||
@@ -306,6 +307,7 @@ struct zynqmp_dp {
|
||||
struct drm_bridge bridge;
|
||||
struct work_struct hpd_work;
|
||||
struct work_struct hpd_irq_work;
|
||||
struct completion aux_done;
|
||||
struct mutex lock;
|
||||
|
||||
struct drm_bridge *next_bridge;
|
||||
@@ -942,12 +944,15 @@ static int zynqmp_dp_aux_cmd_submit(struct zynqmp_dp *dp, u32 cmd, u16 addr,
|
||||
u8 *buf, u8 bytes, u8 *reply)
|
||||
{
|
||||
bool is_read = (cmd & AUX_READ_BIT) ? true : false;
|
||||
unsigned long time_left;
|
||||
u32 reg, i;
|
||||
|
||||
reg = zynqmp_dp_read(dp, ZYNQMP_DP_INTERRUPT_SIGNAL_STATE);
|
||||
if (reg & ZYNQMP_DP_INTERRUPT_SIGNAL_STATE_REQUEST)
|
||||
return -EBUSY;
|
||||
|
||||
reinit_completion(&dp->aux_done);
|
||||
|
||||
zynqmp_dp_write(dp, ZYNQMP_DP_AUX_ADDRESS, addr);
|
||||
if (!is_read)
|
||||
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,
|
||||
zynqmp_dp_write(dp, ZYNQMP_DP_AUX_COMMAND, reg);
|
||||
|
||||
/* Wait for reply to be delivered upto 2ms */
|
||||
for (i = 0; ; i++) {
|
||||
reg = zynqmp_dp_read(dp, ZYNQMP_DP_INTERRUPT_SIGNAL_STATE);
|
||||
if (reg & ZYNQMP_DP_INTERRUPT_SIGNAL_STATE_REPLY)
|
||||
break;
|
||||
time_left = wait_for_completion_timeout(&dp->aux_done,
|
||||
msecs_to_jiffies(2));
|
||||
if (!time_left)
|
||||
return -ETIMEDOUT;
|
||||
|
||||
if (reg & ZYNQMP_DP_INTERRUPT_SIGNAL_STATE_REPLY_TIMEOUT ||
|
||||
i == 2)
|
||||
return -ETIMEDOUT;
|
||||
|
||||
usleep_range(1000, 1100);
|
||||
}
|
||||
reg = zynqmp_dp_read(dp, ZYNQMP_DP_INTERRUPT_SIGNAL_STATE);
|
||||
if (reg & ZYNQMP_DP_INTERRUPT_SIGNAL_STATE_REPLY_TIMEOUT)
|
||||
return -ETIMEDOUT;
|
||||
|
||||
reg = zynqmp_dp_read(dp, ZYNQMP_DP_AUX_REPLY_CODE);
|
||||
if (reply)
|
||||
@@ -1056,6 +1058,9 @@ static int zynqmp_dp_aux_init(struct zynqmp_dp *dp)
|
||||
(w << ZYNQMP_DP_AUX_CLK_DIVIDER_AUX_FILTER_SHIFT) |
|
||||
(rate / (1000 * 1000)));
|
||||
|
||||
zynqmp_dp_write(dp, ZYNQMP_DP_INT_EN, ZYNQMP_DP_INT_REPLY_RECEIVED |
|
||||
ZYNQMP_DP_INT_REPLY_TIMEOUT);
|
||||
|
||||
dp->aux.name = "ZynqMP DP AUX";
|
||||
dp->aux.dev = dp->dev;
|
||||
dp->aux.drm_dev = dp->bridge.dev;
|
||||
@@ -1073,6 +1078,9 @@ static int zynqmp_dp_aux_init(struct zynqmp_dp *dp)
|
||||
static void zynqmp_dp_aux_cleanup(struct zynqmp_dp *dp)
|
||||
{
|
||||
drm_dp_aux_unregister(&dp->aux);
|
||||
|
||||
zynqmp_dp_write(dp, ZYNQMP_DP_INT_DS, ZYNQMP_DP_INT_REPLY_RECEIVED |
|
||||
ZYNQMP_DP_INT_REPLY_TIMEOUT);
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
@@ -1730,6 +1738,12 @@ static irqreturn_t zynqmp_dp_irq_handler(int irq, void *data)
|
||||
if (status & ZYNQMP_DP_INT_HPD_IRQ)
|
||||
schedule_work(&dp->hpd_irq_work);
|
||||
|
||||
if (status & ZYNQMP_DP_INTERRUPT_SIGNAL_STATE_REPLY)
|
||||
complete(&dp->aux_done);
|
||||
|
||||
if (status & ZYNQMP_DP_INTERRUPT_SIGNAL_STATE_REPLY_TIMEOUT)
|
||||
complete(&dp->aux_done);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
@@ -1753,6 +1767,7 @@ int zynqmp_dp_probe(struct zynqmp_dpsub *dpsub)
|
||||
dp->dpsub = dpsub;
|
||||
dp->status = connector_status_disconnected;
|
||||
mutex_init(&dp->lock);
|
||||
init_completion(&dp->aux_done);
|
||||
|
||||
INIT_WORK(&dp->hpd_work, zynqmp_dp_hpd_work_func);
|
||||
INIT_WORK(&dp->hpd_irq_work, zynqmp_dp_hpd_irq_work_func);
|
||||
|
||||
Reference in New Issue
Block a user