mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-07 19:30:30 +09:00
drm/bridge: analogix_dp: Fix hpd handling for GPIO
Change-Id: I0d62201095ab82f5ed0ddcfd53abaef6089a2e9d Signed-off-by: Wyon Bi <bivvy.bi@rock-chips.com>
This commit is contained in:
@@ -800,25 +800,44 @@ static int analogix_dp_enable_scramble(struct analogix_dp_device *dp,
|
||||
return ret < 0 ? ret : 0;
|
||||
}
|
||||
|
||||
static irqreturn_t analogix_dp_hpd_irq_handler(int irq, void *arg)
|
||||
{
|
||||
struct analogix_dp_device *dp = arg;
|
||||
|
||||
if (dp->drm_dev)
|
||||
drm_helper_hpd_irq_event(dp->drm_dev);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static irqreturn_t analogix_dp_hardirq(int irq, void *arg)
|
||||
{
|
||||
struct analogix_dp_device *dp = arg;
|
||||
irqreturn_t ret = IRQ_NONE;
|
||||
enum dp_irq_type irq_type;
|
||||
int ret;
|
||||
|
||||
ret = pm_runtime_get_sync(dp->dev);
|
||||
if (ret < 0)
|
||||
return IRQ_NONE;
|
||||
|
||||
irq_type = analogix_dp_get_irq_type(dp);
|
||||
if (irq_type != DP_IRQ_TYPE_UNKNOWN) {
|
||||
if (irq_type != DP_IRQ_TYPE_UNKNOWN)
|
||||
analogix_dp_mute_hpd_interrupt(dp);
|
||||
ret = IRQ_WAKE_THREAD;
|
||||
}
|
||||
|
||||
return ret;
|
||||
pm_runtime_put_sync(dp->dev);
|
||||
|
||||
return IRQ_WAKE_THREAD;
|
||||
}
|
||||
|
||||
static irqreturn_t analogix_dp_irq_thread(int irq, void *arg)
|
||||
{
|
||||
struct analogix_dp_device *dp = arg;
|
||||
enum dp_irq_type irq_type;
|
||||
int ret;
|
||||
|
||||
ret = pm_runtime_get_sync(dp->dev);
|
||||
if (ret < 0)
|
||||
return IRQ_NONE;
|
||||
|
||||
irq_type = analogix_dp_get_irq_type(dp);
|
||||
if (irq_type & DP_IRQ_TYPE_HP_CABLE_IN ||
|
||||
@@ -833,6 +852,8 @@ static irqreturn_t analogix_dp_irq_thread(int irq, void *arg)
|
||||
analogix_dp_unmute_hpd_interrupt(dp);
|
||||
}
|
||||
|
||||
pm_runtime_put_sync(dp->dev);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
@@ -1567,7 +1588,6 @@ analogix_dp_probe(struct device *dev, struct analogix_dp_plat_data *plat_data)
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
struct analogix_dp_device *dp;
|
||||
struct resource *res;
|
||||
unsigned int irq_flags;
|
||||
int ret;
|
||||
|
||||
if (!plat_data) {
|
||||
@@ -1640,20 +1660,21 @@ analogix_dp_probe(struct device *dev, struct analogix_dp_plat_data *plat_data)
|
||||
}
|
||||
|
||||
if (dp->hpd_gpiod) {
|
||||
/*
|
||||
* Set up the hotplug GPIO from the device tree as an interrupt.
|
||||
* Simply specifying a different interrupt in the device tree
|
||||
* doesn't work since we handle hotplug rather differently when
|
||||
* using a GPIO. We also need the actual GPIO specifier so
|
||||
* that we can get the current state of the GPIO.
|
||||
*/
|
||||
dp->irq = gpiod_to_irq(dp->hpd_gpiod);
|
||||
irq_flags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING;
|
||||
} else {
|
||||
dp->irq = platform_get_irq(pdev, 0);
|
||||
irq_flags = 0;
|
||||
ret = devm_request_threaded_irq(dev,
|
||||
gpiod_to_irq(dp->hpd_gpiod),
|
||||
NULL,
|
||||
analogix_dp_hpd_irq_handler,
|
||||
IRQF_TRIGGER_RISING |
|
||||
IRQF_TRIGGER_FALLING |
|
||||
IRQF_ONESHOT,
|
||||
"analogix-hpd", dp);
|
||||
if (ret) {
|
||||
dev_err(dev, "failed to request hpd IRQ: %d\n", ret);
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
}
|
||||
|
||||
dp->irq = platform_get_irq(pdev, 0);
|
||||
if (dp->irq == -ENXIO) {
|
||||
dev_err(&pdev->dev, "failed to get irq\n");
|
||||
return ERR_PTR(-ENODEV);
|
||||
@@ -1663,7 +1684,7 @@ analogix_dp_probe(struct device *dev, struct analogix_dp_plat_data *plat_data)
|
||||
ret = devm_request_threaded_irq(&pdev->dev, dp->irq,
|
||||
analogix_dp_hardirq,
|
||||
analogix_dp_irq_thread,
|
||||
irq_flags, "analogix-dp", dp);
|
||||
0, "analogix-dp", dp);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "failed to request irq\n");
|
||||
return ERR_PTR(ret);
|
||||
|
||||
@@ -22,7 +22,6 @@
|
||||
#define COMMON_INT_MASK_2 0
|
||||
#define COMMON_INT_MASK_3 0
|
||||
#define COMMON_INT_MASK_4 (HOTPLUG_CHG | HPD_LOST | PLUG)
|
||||
#define INT_STA_MASK INT_HPD
|
||||
|
||||
static void analogix_dp_write(struct analogix_dp_device *dp, u32 reg, u32 val)
|
||||
{
|
||||
@@ -203,11 +202,10 @@ void analogix_dp_config_interrupt(struct analogix_dp_device *dp)
|
||||
reg = COMMON_INT_MASK_3;
|
||||
analogix_dp_write(dp, ANALOGIX_DP_COMMON_INT_MASK_3, reg);
|
||||
|
||||
reg = COMMON_INT_MASK_4;
|
||||
analogix_dp_write(dp, ANALOGIX_DP_COMMON_INT_MASK_4, reg);
|
||||
|
||||
reg = INT_STA_MASK;
|
||||
analogix_dp_write(dp, ANALOGIX_DP_INT_STA_MASK, reg);
|
||||
if (dp->force_hpd || dp->hpd_gpiod)
|
||||
analogix_dp_mute_hpd_interrupt(dp);
|
||||
else
|
||||
analogix_dp_unmute_hpd_interrupt(dp);
|
||||
}
|
||||
|
||||
void analogix_dp_mute_hpd_interrupt(struct analogix_dp_device *dp)
|
||||
@@ -220,7 +218,7 @@ void analogix_dp_mute_hpd_interrupt(struct analogix_dp_device *dp)
|
||||
analogix_dp_write(dp, ANALOGIX_DP_COMMON_INT_MASK_4, reg);
|
||||
|
||||
reg = analogix_dp_read(dp, ANALOGIX_DP_INT_STA_MASK);
|
||||
reg &= ~INT_STA_MASK;
|
||||
reg &= ~INT_HPD;
|
||||
analogix_dp_write(dp, ANALOGIX_DP_INT_STA_MASK, reg);
|
||||
}
|
||||
|
||||
@@ -232,7 +230,8 @@ void analogix_dp_unmute_hpd_interrupt(struct analogix_dp_device *dp)
|
||||
reg = COMMON_INT_MASK_4;
|
||||
analogix_dp_write(dp, ANALOGIX_DP_COMMON_INT_MASK_4, reg);
|
||||
|
||||
reg = INT_STA_MASK;
|
||||
reg = analogix_dp_read(dp, ANALOGIX_DP_INT_STA_MASK);
|
||||
reg |= INT_HPD;
|
||||
analogix_dp_write(dp, ANALOGIX_DP_INT_STA_MASK, reg);
|
||||
}
|
||||
|
||||
@@ -437,27 +436,19 @@ enum dp_irq_type analogix_dp_get_irq_type(struct analogix_dp_device *dp)
|
||||
{
|
||||
u32 reg;
|
||||
|
||||
if (dp->hpd_gpiod) {
|
||||
reg = gpiod_get_value(dp->hpd_gpiod);
|
||||
if (reg)
|
||||
return DP_IRQ_TYPE_HP_CABLE_IN;
|
||||
else
|
||||
return DP_IRQ_TYPE_HP_CABLE_OUT;
|
||||
} else {
|
||||
/* Parse hotplug interrupt status register */
|
||||
reg = analogix_dp_read(dp, ANALOGIX_DP_COMMON_INT_STA_4);
|
||||
/* Parse hotplug interrupt status register */
|
||||
reg = analogix_dp_read(dp, ANALOGIX_DP_COMMON_INT_STA_4);
|
||||
|
||||
if (reg & PLUG)
|
||||
return DP_IRQ_TYPE_HP_CABLE_IN;
|
||||
if (reg & PLUG)
|
||||
return DP_IRQ_TYPE_HP_CABLE_IN;
|
||||
|
||||
if (reg & HPD_LOST)
|
||||
return DP_IRQ_TYPE_HP_CABLE_OUT;
|
||||
if (reg & HPD_LOST)
|
||||
return DP_IRQ_TYPE_HP_CABLE_OUT;
|
||||
|
||||
if (reg & HOTPLUG_CHG)
|
||||
return DP_IRQ_TYPE_HP_CHANGE;
|
||||
if (reg & HOTPLUG_CHG)
|
||||
return DP_IRQ_TYPE_HP_CHANGE;
|
||||
|
||||
return DP_IRQ_TYPE_UNKNOWN;
|
||||
}
|
||||
return DP_IRQ_TYPE_UNKNOWN;
|
||||
}
|
||||
|
||||
void analogix_dp_reset_aux(struct analogix_dp_device *dp)
|
||||
|
||||
Reference in New Issue
Block a user