Commit 7e86efa2 authored by Hans Verkuil's avatar Hans Verkuil Committed by Mauro Carvalho Chehab

media: cec-gpio: add notifier support

Add support for cec-notifier to the cec-gpio driver.

This makes it possible to associate the CEC gpio pin with an HDMI
connector. This feature was always documented in the cec-gpio bindings:

Documentation/devicetree/bindings/media/cec-gpio.txt

But support for the hdmi-phandle property was never actually implemented in
this driver.

This patch adds support for this property.

It also fixes a few incorrect error returns in the probe() function, which
skipped the call to cec_delete_adapter().

Tested on a Raspberry Pi 3B with a modified vc4 driver.
Signed-off-by: default avatarHans Verkuil <hverkuil-cisco@xs4all.nl>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab+samsung@kernel.org>
parent 98f29073
...@@ -588,6 +588,7 @@ config CEC_GPIO ...@@ -588,6 +588,7 @@ config CEC_GPIO
depends on PREEMPT || COMPILE_TEST depends on PREEMPT || COMPILE_TEST
select CEC_CORE select CEC_CORE
select CEC_PIN select CEC_PIN
select CEC_NOTIFIER
select GPIOLIB select GPIOLIB
help help
This is a generic GPIO-based CEC driver. This is a generic GPIO-based CEC driver.
......
...@@ -8,10 +8,12 @@ ...@@ -8,10 +8,12 @@
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/gpio/consumer.h> #include <linux/gpio/consumer.h>
#include <media/cec-notifier.h>
#include <media/cec-pin.h> #include <media/cec-pin.h>
struct cec_gpio { struct cec_gpio {
struct cec_adapter *adap; struct cec_adapter *adap;
struct cec_notifier *notifier;
struct device *dev; struct device *dev;
struct gpio_desc *cec_gpio; struct gpio_desc *cec_gpio;
...@@ -173,9 +175,17 @@ static const struct cec_pin_ops cec_gpio_pin_ops = { ...@@ -173,9 +175,17 @@ static const struct cec_pin_ops cec_gpio_pin_ops = {
static int cec_gpio_probe(struct platform_device *pdev) static int cec_gpio_probe(struct platform_device *pdev)
{ {
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
struct device *hdmi_dev;
struct cec_gpio *cec; struct cec_gpio *cec;
u32 caps = CEC_CAP_DEFAULTS | CEC_CAP_MONITOR_ALL | CEC_CAP_MONITOR_PIN;
int ret; int ret;
hdmi_dev = cec_notifier_parse_hdmi_phandle(dev);
if (PTR_ERR(hdmi_dev) == -EPROBE_DEFER)
return PTR_ERR(hdmi_dev);
if (IS_ERR(hdmi_dev))
caps |= CEC_CAP_PHYS_ADDR;
cec = devm_kzalloc(dev, sizeof(*cec), GFP_KERNEL); cec = devm_kzalloc(dev, sizeof(*cec), GFP_KERNEL);
if (!cec) if (!cec)
return -ENOMEM; return -ENOMEM;
...@@ -196,8 +206,7 @@ static int cec_gpio_probe(struct platform_device *pdev) ...@@ -196,8 +206,7 @@ static int cec_gpio_probe(struct platform_device *pdev)
return PTR_ERR(cec->v5_gpio); return PTR_ERR(cec->v5_gpio);
cec->adap = cec_pin_allocate_adapter(&cec_gpio_pin_ops, cec->adap = cec_pin_allocate_adapter(&cec_gpio_pin_ops,
cec, pdev->name, CEC_CAP_DEFAULTS | CEC_CAP_PHYS_ADDR | cec, pdev->name, caps);
CEC_CAP_MONITOR_ALL | CEC_CAP_MONITOR_PIN);
if (IS_ERR(cec->adap)) if (IS_ERR(cec->adap))
return PTR_ERR(cec->adap); return PTR_ERR(cec->adap);
...@@ -205,7 +214,7 @@ static int cec_gpio_probe(struct platform_device *pdev) ...@@ -205,7 +214,7 @@ static int cec_gpio_probe(struct platform_device *pdev)
IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
cec->adap->name, cec); cec->adap->name, cec);
if (ret) if (ret)
return ret; goto del_adap;
cec_gpio_disable_irq(cec->adap); cec_gpio_disable_irq(cec->adap);
...@@ -218,7 +227,7 @@ static int cec_gpio_probe(struct platform_device *pdev) ...@@ -218,7 +227,7 @@ static int cec_gpio_probe(struct platform_device *pdev)
IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
"hpd-gpio", cec); "hpd-gpio", cec);
if (ret) if (ret)
return ret; goto del_adap;
} }
if (cec->v5_gpio) { if (cec->v5_gpio) {
...@@ -230,23 +239,37 @@ static int cec_gpio_probe(struct platform_device *pdev) ...@@ -230,23 +239,37 @@ static int cec_gpio_probe(struct platform_device *pdev)
IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
"v5-gpio", cec); "v5-gpio", cec);
if (ret) if (ret)
return ret; goto del_adap;
} }
ret = cec_register_adapter(cec->adap, &pdev->dev); if (!IS_ERR(hdmi_dev)) {
if (ret) { cec->notifier = cec_notifier_cec_adap_register(hdmi_dev, NULL,
cec_delete_adapter(cec->adap); cec->adap);
return ret; if (!cec->notifier) {
ret = -ENOMEM;
goto del_adap;
}
} }
ret = cec_register_adapter(cec->adap, &pdev->dev);
if (ret)
goto unreg_notifier;
platform_set_drvdata(pdev, cec); platform_set_drvdata(pdev, cec);
return 0; return 0;
unreg_notifier:
cec_notifier_cec_adap_unregister(cec->notifier);
del_adap:
cec_delete_adapter(cec->adap);
return ret;
} }
static int cec_gpio_remove(struct platform_device *pdev) static int cec_gpio_remove(struct platform_device *pdev)
{ {
struct cec_gpio *cec = platform_get_drvdata(pdev); struct cec_gpio *cec = platform_get_drvdata(pdev);
cec_notifier_cec_adap_unregister(cec->notifier);
cec_unregister_adapter(cec->adap); cec_unregister_adapter(cec->adap);
return 0; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment