[lkml]   [2017]   [Nov]   [17]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
Messages in this thread
Patch in this message
Subject[RFC] [PATCH] drm: adv7511/33: Fix adv7511_cec_init() failure handling
If the device tree for a board did not specify a cec clock, then
adv7511_cec_init would return an error, which would cause adv7511_probe()
to fail and thus there is no HDMI output.

There is no need to have adv7511_probe() fail if the CEC initialization
fails, so just change adv7511_cec_init() to a void function. In addition,
adv7511_cec_init() should just return silently if the cec clock isn't
found and show a message for any other errors.

An otherwise correct cleanup patch from Dan Carpenter turned this broken
failure handling into a kernel Oops, so bisection points to commit
7af35b0addbc ("drm/kirin: Checking for IS_ERR() instead of NULL") rather
than 3b1b975003e4 ("drm: adv7511/33: add HDMI CEC support").

Based on earlier patches from Arnd and John.

Reported-by: Naresh Kamboju <>
Cc: Xinliang Liu <>
Cc: Dan Carpenter <>
Cc: Sean Paul <>
Cc: Hans Verkuil <>
Cc: Archit Taneja <>
Cc: John Stultz <>
Fixes: 7af35b0addbc ("drm/kirin: Checking for IS_ERR() instead of NULL")
Fixes: 3b1b975003e4 ("drm: adv7511/33: add HDMI CEC support")
Signed-off-by: Hans Verkuil <>
This rework of Arnd and John's patches goes a bit further and makes
cec_init a void function and just silently exits if there is no cec clock
defined in the dts. I'm sure that's the reason why the kirin board failed
on this. BTW: if the kirin board DOES support cec, then it would be nice
if it can be hooked up in the dts!

I'll test this with my two adv7511/33 boards on Monday.


diff --git a/drivers/gpu/drm/bridge/adv7511/adv7511.h b/drivers/gpu/drm/bridge/adv7511/adv7511.h
index 543a5eb91624..bc17aa965e58 100644
--- a/drivers/gpu/drm/bridge/adv7511/adv7511.h
+++ b/drivers/gpu/drm/bridge/adv7511/adv7511.h
@@ -374,8 +374,8 @@ struct adv7511 {

-int adv7511_cec_init(struct device *dev, struct adv7511 *adv7511,
- unsigned int offset);
+void adv7511_cec_init(struct device *dev, struct adv7511 *adv7511,
+ unsigned int offset);
void adv7511_cec_irq_process(struct adv7511 *adv7511, unsigned int irq1);

diff --git a/drivers/gpu/drm/bridge/adv7511/adv7511_cec.c b/drivers/gpu/drm/bridge/adv7511/adv7511_cec.c
index b33d730e4d73..c1cd471d31fa 100644
--- a/drivers/gpu/drm/bridge/adv7511/adv7511_cec.c
+++ b/drivers/gpu/drm/bridge/adv7511/adv7511_cec.c
@@ -300,18 +300,20 @@ static int adv7511_cec_parse_dt(struct device *dev, struct adv7511 *adv7511)
return 0;

-int adv7511_cec_init(struct device *dev, struct adv7511 *adv7511,
- unsigned int offset)
+void adv7511_cec_init(struct device *dev, struct adv7511 *adv7511,
+ unsigned int offset)
int ret = adv7511_cec_parse_dt(dev, adv7511);

if (ret)
- return ret;
+ goto disable_cec;

adv7511->cec_adap = cec_allocate_adapter(&adv7511_cec_adap_ops,
adv7511, dev_name(dev), CEC_CAP_DEFAULTS, ADV7511_MAX_ADDRS);
- if (IS_ERR(adv7511->cec_adap))
- return PTR_ERR(adv7511->cec_adap);
+ if (IS_ERR(adv7511->cec_adap)) {
+ ret = PTR_ERR(adv7511->cec_adap);
+ goto fail;
+ }

regmap_write(adv7511->regmap, ADV7511_REG_CEC_CTRL + offset, 0);
/* cec soft reset */
@@ -329,9 +331,15 @@ int adv7511_cec_init(struct device *dev, struct adv7511 *adv7511,
((adv7511->cec_clk_freq / 750000) - 1) << 2);

ret = cec_register_adapter(adv7511->cec_adap, dev);
- if (ret) {
- cec_delete_adapter(adv7511->cec_adap);
- adv7511->cec_adap = NULL;
- }
- return ret;
+ if (!ret)
+ return;
+ cec_delete_adapter(adv7511->cec_adap);
+ adv7511->cec_adap = NULL;
+ dev_info(dev, "Initializing CEC failed with error %d, disabling CEC\n",
+ ret);
+ regmap_write(adv7511->regmap, ADV7511_REG_CEC_CTRL + offset,
diff --git a/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c b/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c
index 3a33075dbb22..56eeeea6a1fa 100644
--- a/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c
+++ b/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c
@@ -1202,9 +1202,7 @@ static int adv7511_probe(struct i2c_client *i2c, const struct i2c_device_id *id)
offset = adv7511->type == ADV7533 ? ADV7533_REG_CEC_OFFSET : 0;

- ret = adv7511_cec_init(dev, adv7511, offset);
- if (ret)
- goto err_unregister_cec;
+ adv7511_cec_init(dev, adv7511, offset);
regmap_write(adv7511->regmap, ADV7511_REG_CEC_CTRL + offset,
 \ /
  Last update: 2017-11-17 17:19    [W:0.105 / U:2.992 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site