From e3a93adcc4f6c3b538f3d617fc48a87979d4548b Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Tue, 13 Dec 2016 12:15:57 -0200 Subject: [media] cec: integrate CEC notifier support Support the CEC notifier framework, simplifying drivers that depend on this. Signed-off-by: Hans Verkuil Tested-by: Marek Szyprowski Tested-by: Benjamin Gaignard Acked-by: Daniel Vetter Signed-off-by: Mauro Carvalho Chehab --- drivers/media/cec/cec-core.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) (limited to 'drivers/media/cec/cec-core.c') diff --git a/drivers/media/cec/cec-core.c b/drivers/media/cec/cec-core.c index 37217e205040..e5070b374276 100644 --- a/drivers/media/cec/cec-core.c +++ b/drivers/media/cec/cec-core.c @@ -195,6 +195,24 @@ static void cec_devnode_unregister(struct cec_devnode *devnode) put_device(&devnode->dev); } +#ifdef CONFIG_MEDIA_CEC_NOTIFIER +static void cec_cec_notify(struct cec_adapter *adap, u16 pa) +{ + cec_s_phys_addr(adap, pa, false); +} + +void cec_register_cec_notifier(struct cec_adapter *adap, + struct cec_notifier *notifier) +{ + if (WARN_ON(!adap->devnode.registered)) + return; + + adap->notifier = notifier; + cec_notifier_register(adap->notifier, adap, cec_cec_notify); +} +EXPORT_SYMBOL_GPL(cec_register_cec_notifier); +#endif + struct cec_adapter *cec_allocate_adapter(const struct cec_adap_ops *ops, void *priv, const char *name, u32 caps, u8 available_las) @@ -343,6 +361,10 @@ void cec_unregister_adapter(struct cec_adapter *adap) adap->rc = NULL; #endif debugfs_remove_recursive(adap->cec_dir); +#ifdef CONFIG_MEDIA_CEC_NOTIFIER + if (adap->notifier) + cec_notifier_unregister(adap->notifier); +#endif cec_devnode_unregister(&adap->devnode); } EXPORT_SYMBOL_GPL(cec_unregister_adapter); -- cgit v1.2.3 From 43c0c03961d0b19bd225a336897606b46e0021a6 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Tue, 4 Apr 2017 09:32:19 -0300 Subject: [media] cec: Fix runtime BUG when (CONFIG_RC_CORE && !CEC_CAP_RC) Currently when the RC Core is enabled (reachable) core code located in cec_register_adapter() attempts to populate the RC structure with a pointer to the 'parent' passed in by the caller. Unfortunately if the caller did not specify RC capability when calling cec_allocate_adapter(), then there will be no RC structure to populate. This causes a "NULL pointer dereference" error. Fixes: f51e80804f0 ("[media] cec: pass parent device in register(), not allocate()") Signed-off-by: Lee Jones Cc: # for v4.10 and up Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/cec/cec-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/media/cec/cec-core.c') diff --git a/drivers/media/cec/cec-core.c b/drivers/media/cec/cec-core.c index e5070b374276..6b32a288714f 100644 --- a/drivers/media/cec/cec-core.c +++ b/drivers/media/cec/cec-core.c @@ -304,8 +304,8 @@ int cec_register_adapter(struct cec_adapter *adap, adap->devnode.dev.parent = parent; #if IS_REACHABLE(CONFIG_RC_CORE) - adap->rc->dev.parent = parent; if (adap->capabilities & CEC_CAP_RC) { + adap->rc->dev.parent = parent; res = rc_register_device(adap->rc); if (res) { -- cgit v1.2.3 From ee044f5be17fdba92b41ac68f136039bfce1d32b Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Tue, 4 Apr 2017 13:43:33 -0300 Subject: [media] cec: fix confusing CEC_CAP_RC and IS_REACHABLE(CONFIG_RC_CORE) code It is a bit confusing how CEC_CAP_RC and IS_REACHABLE(CONFIG_RC_CORE) interact. By stripping CEC_CAP_RC at the beginning rather than after #else it should be a bit clearer what is going on. Signed-off-by: Hans Verkuil Reported-by: Lee Jones Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/cec/cec-core.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers/media/cec/cec-core.c') diff --git a/drivers/media/cec/cec-core.c b/drivers/media/cec/cec-core.c index 6b32a288714f..430f5e052ab3 100644 --- a/drivers/media/cec/cec-core.c +++ b/drivers/media/cec/cec-core.c @@ -220,6 +220,10 @@ struct cec_adapter *cec_allocate_adapter(const struct cec_adap_ops *ops, struct cec_adapter *adap; int res; +#if !IS_REACHABLE(CONFIG_RC_CORE) + caps &= ~CEC_CAP_RC; +#endif + if (WARN_ON(!caps)) return ERR_PTR(-EINVAL); if (WARN_ON(!ops)) @@ -252,10 +256,10 @@ struct cec_adapter *cec_allocate_adapter(const struct cec_adap_ops *ops, return ERR_PTR(res); } +#if IS_REACHABLE(CONFIG_RC_CORE) if (!(caps & CEC_CAP_RC)) return adap; -#if IS_REACHABLE(CONFIG_RC_CORE) /* Prepare the RC input device */ adap->rc = rc_allocate_device(RC_DRIVER_SCANCODE); if (!adap->rc) { @@ -282,8 +286,6 @@ struct cec_adapter *cec_allocate_adapter(const struct cec_adap_ops *ops, adap->rc->priv = adap; adap->rc->map_name = RC_MAP_CEC; adap->rc->timeout = MS_TO_NS(100); -#else - adap->capabilities &= ~CEC_CAP_RC; #endif return adap; } -- cgit v1.2.3 From 5f2c467c54f5437e35b79fa10c73295d1e0ff586 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 17 Apr 2017 08:05:10 -0300 Subject: [media] cec: add MEDIA_CEC_RC config option Add an explicit config option to select whether the CEC remote control messages are to be passed on to the RC subsystem or not. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/cec/cec-core.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/media/cec/cec-core.c') diff --git a/drivers/media/cec/cec-core.c b/drivers/media/cec/cec-core.c index 430f5e052ab3..a21fca7f7883 100644 --- a/drivers/media/cec/cec-core.c +++ b/drivers/media/cec/cec-core.c @@ -220,7 +220,7 @@ struct cec_adapter *cec_allocate_adapter(const struct cec_adap_ops *ops, struct cec_adapter *adap; int res; -#if !IS_REACHABLE(CONFIG_RC_CORE) +#ifndef CONFIG_MEDIA_CEC_RC caps &= ~CEC_CAP_RC; #endif @@ -256,7 +256,7 @@ struct cec_adapter *cec_allocate_adapter(const struct cec_adap_ops *ops, return ERR_PTR(res); } -#if IS_REACHABLE(CONFIG_RC_CORE) +#ifdef CONFIG_MEDIA_CEC_RC if (!(caps & CEC_CAP_RC)) return adap; @@ -305,7 +305,7 @@ int cec_register_adapter(struct cec_adapter *adap, adap->owner = parent->driver->owner; adap->devnode.dev.parent = parent; -#if IS_REACHABLE(CONFIG_RC_CORE) +#ifdef CONFIG_MEDIA_CEC_RC if (adap->capabilities & CEC_CAP_RC) { adap->rc->dev.parent = parent; res = rc_register_device(adap->rc); @@ -322,7 +322,7 @@ int cec_register_adapter(struct cec_adapter *adap, res = cec_devnode_register(&adap->devnode, adap->owner); if (res) { -#if IS_REACHABLE(CONFIG_RC_CORE) +#ifdef CONFIG_MEDIA_CEC_RC /* Note: rc_unregister also calls rc_free */ rc_unregister_device(adap->rc); adap->rc = NULL; @@ -357,7 +357,7 @@ void cec_unregister_adapter(struct cec_adapter *adap) if (IS_ERR_OR_NULL(adap)) return; -#if IS_REACHABLE(CONFIG_RC_CORE) +#ifdef CONFIG_MEDIA_CEC_RC /* Note: rc_unregister also calls rc_free */ rc_unregister_device(adap->rc); adap->rc = NULL; @@ -381,7 +381,7 @@ void cec_delete_adapter(struct cec_adapter *adap) kthread_stop(adap->kthread); if (adap->kthread_config) kthread_stop(adap->kthread_config); -#if IS_REACHABLE(CONFIG_RC_CORE) +#ifdef CONFIG_MEDIA_CEC_RC rc_free_device(adap->rc); #endif kfree(adap); -- cgit v1.2.3