summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-08-07 13:18:06 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-08-07 13:18:06 +0000
commit638a9e433ecd61e64761352dbec1fa4f5874c941 (patch)
treefdbff74a238d7a5a7d1cef071b7230bc064b9f25 /drivers/gpu/drm/bridge/adv7511/adv7511_drv.c
parentReleasing progress-linux version 6.9.12-1~progress7.99u1. (diff)
downloadlinux-638a9e433ecd61e64761352dbec1fa4f5874c941.tar.xz
linux-638a9e433ecd61e64761352dbec1fa4f5874c941.zip
Merging upstream version 6.10.3.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'drivers/gpu/drm/bridge/adv7511/adv7511_drv.c')
-rw-r--r--drivers/gpu/drm/bridge/adv7511/adv7511_drv.c33
1 files changed, 28 insertions, 5 deletions
diff --git a/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c b/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c
index b5518ff971..c8d2c4a157 100644
--- a/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c
+++ b/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c
@@ -17,6 +17,7 @@
#include <drm/drm_atomic.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_edid.h>
+#include <drm/drm_of.h>
#include <drm/drm_print.h>
#include <drm/drm_probe_helper.h>
@@ -468,6 +469,8 @@ static int adv7511_irq_process(struct adv7511 *adv7511, bool process_hpd)
{
unsigned int irq0, irq1;
int ret;
+ int cec_status = IRQ_NONE;
+ int irq_status = IRQ_NONE;
ret = regmap_read(adv7511->regmap, ADV7511_REG_INT(0), &irq0);
if (ret < 0)
@@ -480,21 +483,28 @@ static int adv7511_irq_process(struct adv7511 *adv7511, bool process_hpd)
regmap_write(adv7511->regmap, ADV7511_REG_INT(0), irq0);
regmap_write(adv7511->regmap, ADV7511_REG_INT(1), irq1);
- if (process_hpd && irq0 & ADV7511_INT0_HPD && adv7511->bridge.encoder)
+ if (process_hpd && irq0 & ADV7511_INT0_HPD && adv7511->bridge.encoder) {
schedule_work(&adv7511->hpd_work);
+ irq_status = IRQ_HANDLED;
+ }
if (irq0 & ADV7511_INT0_EDID_READY || irq1 & ADV7511_INT1_DDC_ERROR) {
adv7511->edid_read = true;
if (adv7511->i2c_main->irq)
wake_up_all(&adv7511->wq);
+ irq_status = IRQ_HANDLED;
}
#ifdef CONFIG_DRM_I2C_ADV7511_CEC
- adv7511_cec_irq_process(adv7511, irq1);
+ cec_status = adv7511_cec_irq_process(adv7511, irq1);
#endif
- return 0;
+ /* If there is no IRQ to handle, exit indicating no IRQ data */
+ if (irq_status == IRQ_HANDLED || cec_status == IRQ_HANDLED)
+ return IRQ_HANDLED;
+
+ return IRQ_NONE;
}
static irqreturn_t adv7511_irq_handler(int irq, void *devid)
@@ -503,7 +513,7 @@ static irqreturn_t adv7511_irq_handler(int irq, void *devid)
int ret;
ret = adv7511_irq_process(adv7511, true);
- return ret < 0 ? IRQ_NONE : IRQ_HANDLED;
+ return ret < 0 ? IRQ_NONE : ret;
}
/* -----------------------------------------------------------------------------
@@ -946,6 +956,13 @@ static int adv7511_bridge_attach(struct drm_bridge *bridge,
struct adv7511 *adv = bridge_to_adv7511(bridge);
int ret = 0;
+ if (adv->next_bridge) {
+ ret = drm_bridge_attach(bridge->encoder, adv->next_bridge, bridge,
+ flags | DRM_BRIDGE_ATTACH_NO_CONNECTOR);
+ if (ret)
+ return ret;
+ }
+
if (!(flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)) {
ret = adv7511_connector_init(adv);
if (ret < 0)
@@ -1216,6 +1233,11 @@ static int adv7511_probe(struct i2c_client *i2c)
memset(&link_config, 0, sizeof(link_config));
+ ret = drm_of_find_panel_or_bridge(dev->of_node, 1, -1, NULL,
+ &adv7511->next_bridge);
+ if (ret && ret != -ENODEV)
+ return ret;
+
if (adv7511->info->link_config)
ret = adv7511_parse_dt(dev->of_node, &link_config);
else
@@ -1318,7 +1340,8 @@ static int adv7511_probe(struct i2c_client *i2c)
ret = devm_request_threaded_irq(dev, i2c->irq, NULL,
adv7511_irq_handler,
- IRQF_ONESHOT, dev_name(dev),
+ IRQF_ONESHOT | IRQF_SHARED,
+ dev_name(dev),
adv7511);
if (ret)
goto err_unregister_audio;