diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index f75c176dde098d..a2bcc9564e3b37 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -484,9 +484,8 @@ vc4_hdmi_connector_detect(struct drm_connector *connector, bool force) WARN_ON(clk_prepare_enable(vc4_hdmi->hsm_clock)); if (vc4_hdmi->hpd_gpio) { - if (gpio_get_value_cansleep(vc4_hdmi->hpd_gpio) ^ - vc4_hdmi->hpd_active_low) - connected = true; + if (gpiod_get_value_cansleep(vc4_hdmi->hpd_gpio)) + connected = true; } else if (drm_probe_ddc(vc4_hdmi->ddc)) { connected = true; } else if (HDMI_READ(HDMI_HOTPLUG) & VC4_HDMI_HOTPLUG_CONNECTED) { @@ -2198,6 +2197,21 @@ static int vc4_hdmi_hotplug_init(struct vc4_hdmi *vc4_hdmi) if (ret) return ret; + connector->polled = DRM_CONNECTOR_POLL_HPD; + } else if (vc4_hdmi->hpd_gpio) { + int irq = gpiod_to_irq(vc4_hdmi->hpd_gpio); + if (irq < 0) + return 0; + + ret = devm_request_threaded_irq(dev, irq, + NULL, vc4_hdmi_hpd_irq_thread, + IRQF_ONESHOT | + IRQF_TRIGGER_RISING | + IRQF_TRIGGER_FALLING, + "vc4 hdmi hpd", vc4_hdmi); + if (ret) + return ret; + connector->polled = DRM_CONNECTOR_POLL_HPD; } @@ -2720,7 +2734,6 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data) struct vc4_hdmi *vc4_hdmi; struct drm_encoder *encoder; struct device_node *ddc_node; - u32 value; int ret; vc4_hdmi = devm_kzalloc(dev, sizeof(*vc4_hdmi), GFP_KERNEL); @@ -2759,18 +2772,10 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data) /* Only use the GPIO HPD pin if present in the DT, otherwise * we'll use the HDMI core's register. */ - if (of_find_property(dev->of_node, "hpd-gpios", &value)) { - enum of_gpio_flags hpd_gpio_flags; - - vc4_hdmi->hpd_gpio = of_get_named_gpio_flags(dev->of_node, - "hpd-gpios", 0, - &hpd_gpio_flags); - if (vc4_hdmi->hpd_gpio < 0) { - ret = vc4_hdmi->hpd_gpio; - goto err_unprepare_hsm; - } - - vc4_hdmi->hpd_active_low = hpd_gpio_flags & OF_GPIO_ACTIVE_LOW; + vc4_hdmi->hpd_gpio = devm_gpiod_get_optional(dev, "hpd", GPIOD_IN); + if (IS_ERR(vc4_hdmi->hpd_gpio)) { + ret = PTR_ERR(vc4_hdmi->hpd_gpio); + goto err_put_ddc; } vc4_hdmi->disable_wifi_frequencies = @@ -2828,8 +2833,8 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data) vc4_hdmi_connector_destroy(&vc4_hdmi->connector); err_destroy_encoder: drm_encoder_cleanup(encoder); -err_unprepare_hsm: pm_runtime_disable(dev); +err_put_ddc: put_device(&vc4_hdmi->ddc->dev); return ret; diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h index 67c372d743cb68..78651ab61fa84c 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.h +++ b/drivers/gpu/drm/vc4/vc4_hdmi.h @@ -153,8 +153,7 @@ struct vc4_hdmi { /* VC5 Only */ void __iomem *rm_regs; - int hpd_gpio; - bool hpd_active_low; + struct gpio_desc *hpd_gpio; /* * On some systems (like the RPi4), some modes are in the same diff --git a/drivers/pinctrl/bcm/pinctrl-bcm2835.c b/drivers/pinctrl/bcm/pinctrl-bcm2835.c index c5d88157f4b289..b0dd126661ec48 100644 --- a/drivers/pinctrl/bcm/pinctrl-bcm2835.c +++ b/drivers/pinctrl/bcm/pinctrl-bcm2835.c @@ -351,6 +351,28 @@ static int bcm2835_gpio_direction_output(struct gpio_chip *chip, return pinctrl_gpio_direction_output(chip->base + offset); } +static int bcm2835_gpio_irq_map(struct irq_domain *d, + unsigned int irq, + irq_hw_number_t hwirq) +{ + unsigned bank = GPIO_REG_OFFSET(hwirq); + + /* + * FIXME: It appears that the interrupts in any bank but the + * first are not working. + */ + if (bank) + return -EINVAL; + + return gpiochip_irq_map(d, irq, hwirq); +} + +static const struct irq_domain_ops bcm2835_irq_domain_ops = { + .map = bcm2835_gpio_irq_map, + .unmap = gpiochip_irq_unmap, + .xlate = irq_domain_xlate_twocell, +}; + static const struct gpio_chip bcm2835_gpio_chip = { .label = MODULE_NAME, .owner = THIS_MODULE, @@ -1258,6 +1280,7 @@ static int bcm2835_pinctrl_probe(struct platform_device *pdev) girq = &pc->gpio_chip.irq; girq->chip = &bcm2835_gpio_irq_chip; + girq->domain_ops = &bcm2835_irq_domain_ops; girq->parent_handler = bcm2835_gpio_irq_handler; girq->num_parents = BCM2835_NUM_IRQS; girq->parents = devm_kcalloc(dev, BCM2835_NUM_IRQS,