Message ID | 20190814104520.6001-9-darekm@google.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | drm: cec: convert DRM drivers to the new notifier API | expand |
On 8/14/19 12:45 PM, Dariusz Marcinkiewicz wrote: > Use the new cec_notifier_conn_(un)register() functions to > (un)register the notifier for the HDMI connector, and fill in > the cec_connector_info. > > Changes since v6: > - move cec_notifier_conn_unregister to a bridge detach > function, > - add a mutex protecting a CEC notifier. > Changes since v4: > - typo fix > Changes since v2: > - removed unnecessary NULL check before a call to > cec_notifier_conn_unregister, > - use cec_notifier_phys_addr_invalidate to invalidate physical > address. > Changes since v1: > Add memory barrier to make sure that the notifier > becomes visible to the irq thread once it is fully > constructed. > > Signed-off-by: Dariusz Marcinkiewicz <darekm@google.com> Acked-by: Hans Verkuil <hverkuil-cisco@xs4all.nl> Regards, Hans > --- > drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 45 +++++++++++++++-------- > 1 file changed, 30 insertions(+), 15 deletions(-) > > diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c > index 83b94b66e464e..55162c9092f71 100644 > --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c > +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c > @@ -190,6 +190,7 @@ struct dw_hdmi { > void (*enable_audio)(struct dw_hdmi *hdmi); > void (*disable_audio)(struct dw_hdmi *hdmi); > > + struct mutex cec_notifier_mutex; > struct cec_notifier *cec_notifier; > }; > > @@ -2194,6 +2195,8 @@ static int dw_hdmi_bridge_attach(struct drm_bridge *bridge) > struct dw_hdmi *hdmi = bridge->driver_private; > struct drm_encoder *encoder = bridge->encoder; > struct drm_connector *connector = &hdmi->connector; > + struct cec_connector_info conn_info; > + struct cec_notifier *notifier; > > connector->interlace_allowed = 1; > connector->polled = DRM_CONNECTOR_POLL_HPD; > @@ -2207,9 +2210,29 @@ static int dw_hdmi_bridge_attach(struct drm_bridge *bridge) > > drm_connector_attach_encoder(connector, encoder); > > + cec_fill_conn_info_from_drm(&conn_info, connector); > + > + notifier = cec_notifier_conn_register(hdmi->dev, NULL, &conn_info); > + if (!notifier) > + return -ENOMEM; > + > + mutex_lock(&hdmi->cec_notifier_mutex); > + hdmi->cec_notifier = notifier; > + mutex_unlock(&hdmi->cec_notifier_mutex); > + > return 0; > } > > +static void dw_hdmi_bridge_detach(struct drm_bridge *bridge) > +{ > + struct dw_hdmi *hdmi = bridge->driver_private; > + > + mutex_lock(&hdmi->cec_notifier_mutex); > + cec_notifier_conn_unregister(hdmi->cec_notifier); > + hdmi->cec_notifier = NULL; > + mutex_unlock(&hdmi->cec_notifier_mutex); > +} > + > static enum drm_mode_status > dw_hdmi_bridge_mode_valid(struct drm_bridge *bridge, > const struct drm_display_mode *mode) > @@ -2266,6 +2289,7 @@ static void dw_hdmi_bridge_enable(struct drm_bridge *bridge) > > static const struct drm_bridge_funcs dw_hdmi_bridge_funcs = { > .attach = dw_hdmi_bridge_attach, > + .detach = dw_hdmi_bridge_detach, > .enable = dw_hdmi_bridge_enable, > .disable = dw_hdmi_bridge_disable, > .mode_set = dw_hdmi_bridge_mode_set, > @@ -2373,9 +2397,11 @@ static irqreturn_t dw_hdmi_irq(int irq, void *dev_id) > phy_stat & HDMI_PHY_HPD, > phy_stat & HDMI_PHY_RX_SENSE); > > - if ((phy_stat & (HDMI_PHY_RX_SENSE | HDMI_PHY_HPD)) == 0) > - cec_notifier_set_phys_addr(hdmi->cec_notifier, > - CEC_PHYS_ADDR_INVALID); > + if ((phy_stat & (HDMI_PHY_RX_SENSE | HDMI_PHY_HPD)) == 0) { > + mutex_lock(&hdmi->cec_notifier_mutex); > + cec_notifier_phys_addr_invalidate(hdmi->cec_notifier); > + mutex_unlock(&hdmi->cec_notifier_mutex); > + } > } > > if (intr_stat & HDMI_IH_PHY_STAT0_HPD) { > @@ -2561,6 +2587,7 @@ __dw_hdmi_probe(struct platform_device *pdev, > > mutex_init(&hdmi->mutex); > mutex_init(&hdmi->audio_mutex); > + mutex_init(&hdmi->cec_notifier_mutex); > spin_lock_init(&hdmi->audio_lock); > > ddc_node = of_parse_phandle(np, "ddc-i2c-bus", 0); > @@ -2693,12 +2720,6 @@ __dw_hdmi_probe(struct platform_device *pdev, > if (ret) > goto err_iahb; > > - hdmi->cec_notifier = cec_notifier_get(dev); > - if (!hdmi->cec_notifier) { > - ret = -ENOMEM; > - goto err_iahb; > - } > - > /* > * To prevent overflows in HDMI_IH_FC_STAT2, set the clk regenerator > * N and cts values before enabling phy > @@ -2796,9 +2817,6 @@ __dw_hdmi_probe(struct platform_device *pdev, > hdmi->ddc = NULL; > } > > - if (hdmi->cec_notifier) > - cec_notifier_put(hdmi->cec_notifier); > - > clk_disable_unprepare(hdmi->iahb_clk); > if (hdmi->cec_clk) > clk_disable_unprepare(hdmi->cec_clk); > @@ -2820,9 +2838,6 @@ static void __dw_hdmi_remove(struct dw_hdmi *hdmi) > /* Disable all interrupts */ > hdmi_writeb(hdmi, ~0, HDMI_IH_MUTE_PHY_STAT0); > > - if (hdmi->cec_notifier) > - cec_notifier_put(hdmi->cec_notifier); > - > clk_disable_unprepare(hdmi->iahb_clk); > clk_disable_unprepare(hdmi->isfr_clk); > if (hdmi->cec_clk) >
On 8/19/19 11:32 AM, Hans Verkuil wrote: > On 8/14/19 12:45 PM, Dariusz Marcinkiewicz wrote: >> Use the new cec_notifier_conn_(un)register() functions to >> (un)register the notifier for the HDMI connector, and fill in >> the cec_connector_info. >> >> Changes since v6: >> - move cec_notifier_conn_unregister to a bridge detach >> function, >> - add a mutex protecting a CEC notifier. >> Changes since v4: >> - typo fix >> Changes since v2: >> - removed unnecessary NULL check before a call to >> cec_notifier_conn_unregister, >> - use cec_notifier_phys_addr_invalidate to invalidate physical >> address. >> Changes since v1: >> Add memory barrier to make sure that the notifier >> becomes visible to the irq thread once it is fully >> constructed. >> >> Signed-off-by: Dariusz Marcinkiewicz <darekm@google.com> > > Acked-by: Hans Verkuil <hverkuil-cisco@xs4all.nl> Tested-by: Hans Verkuil <hverkuil-cisco@xs4all.nl> Regards, Hans > > Regards, > > Hans > >> --- >> drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 45 +++++++++++++++-------- >> 1 file changed, 30 insertions(+), 15 deletions(-) >> >> diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c >> index 83b94b66e464e..55162c9092f71 100644 >> --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c >> +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c >> @@ -190,6 +190,7 @@ struct dw_hdmi { >> void (*enable_audio)(struct dw_hdmi *hdmi); >> void (*disable_audio)(struct dw_hdmi *hdmi); >> >> + struct mutex cec_notifier_mutex; >> struct cec_notifier *cec_notifier; >> }; >> >> @@ -2194,6 +2195,8 @@ static int dw_hdmi_bridge_attach(struct drm_bridge *bridge) >> struct dw_hdmi *hdmi = bridge->driver_private; >> struct drm_encoder *encoder = bridge->encoder; >> struct drm_connector *connector = &hdmi->connector; >> + struct cec_connector_info conn_info; >> + struct cec_notifier *notifier; >> >> connector->interlace_allowed = 1; >> connector->polled = DRM_CONNECTOR_POLL_HPD; >> @@ -2207,9 +2210,29 @@ static int dw_hdmi_bridge_attach(struct drm_bridge *bridge) >> >> drm_connector_attach_encoder(connector, encoder); >> >> + cec_fill_conn_info_from_drm(&conn_info, connector); >> + >> + notifier = cec_notifier_conn_register(hdmi->dev, NULL, &conn_info); >> + if (!notifier) >> + return -ENOMEM; >> + >> + mutex_lock(&hdmi->cec_notifier_mutex); >> + hdmi->cec_notifier = notifier; >> + mutex_unlock(&hdmi->cec_notifier_mutex); >> + >> return 0; >> } >> >> +static void dw_hdmi_bridge_detach(struct drm_bridge *bridge) >> +{ >> + struct dw_hdmi *hdmi = bridge->driver_private; >> + >> + mutex_lock(&hdmi->cec_notifier_mutex); >> + cec_notifier_conn_unregister(hdmi->cec_notifier); >> + hdmi->cec_notifier = NULL; >> + mutex_unlock(&hdmi->cec_notifier_mutex); >> +} >> + >> static enum drm_mode_status >> dw_hdmi_bridge_mode_valid(struct drm_bridge *bridge, >> const struct drm_display_mode *mode) >> @@ -2266,6 +2289,7 @@ static void dw_hdmi_bridge_enable(struct drm_bridge *bridge) >> >> static const struct drm_bridge_funcs dw_hdmi_bridge_funcs = { >> .attach = dw_hdmi_bridge_attach, >> + .detach = dw_hdmi_bridge_detach, >> .enable = dw_hdmi_bridge_enable, >> .disable = dw_hdmi_bridge_disable, >> .mode_set = dw_hdmi_bridge_mode_set, >> @@ -2373,9 +2397,11 @@ static irqreturn_t dw_hdmi_irq(int irq, void *dev_id) >> phy_stat & HDMI_PHY_HPD, >> phy_stat & HDMI_PHY_RX_SENSE); >> >> - if ((phy_stat & (HDMI_PHY_RX_SENSE | HDMI_PHY_HPD)) == 0) >> - cec_notifier_set_phys_addr(hdmi->cec_notifier, >> - CEC_PHYS_ADDR_INVALID); >> + if ((phy_stat & (HDMI_PHY_RX_SENSE | HDMI_PHY_HPD)) == 0) { >> + mutex_lock(&hdmi->cec_notifier_mutex); >> + cec_notifier_phys_addr_invalidate(hdmi->cec_notifier); >> + mutex_unlock(&hdmi->cec_notifier_mutex); >> + } >> } >> >> if (intr_stat & HDMI_IH_PHY_STAT0_HPD) { >> @@ -2561,6 +2587,7 @@ __dw_hdmi_probe(struct platform_device *pdev, >> >> mutex_init(&hdmi->mutex); >> mutex_init(&hdmi->audio_mutex); >> + mutex_init(&hdmi->cec_notifier_mutex); >> spin_lock_init(&hdmi->audio_lock); >> >> ddc_node = of_parse_phandle(np, "ddc-i2c-bus", 0); >> @@ -2693,12 +2720,6 @@ __dw_hdmi_probe(struct platform_device *pdev, >> if (ret) >> goto err_iahb; >> >> - hdmi->cec_notifier = cec_notifier_get(dev); >> - if (!hdmi->cec_notifier) { >> - ret = -ENOMEM; >> - goto err_iahb; >> - } >> - >> /* >> * To prevent overflows in HDMI_IH_FC_STAT2, set the clk regenerator >> * N and cts values before enabling phy >> @@ -2796,9 +2817,6 @@ __dw_hdmi_probe(struct platform_device *pdev, >> hdmi->ddc = NULL; >> } >> >> - if (hdmi->cec_notifier) >> - cec_notifier_put(hdmi->cec_notifier); >> - >> clk_disable_unprepare(hdmi->iahb_clk); >> if (hdmi->cec_clk) >> clk_disable_unprepare(hdmi->cec_clk); >> @@ -2820,9 +2838,6 @@ static void __dw_hdmi_remove(struct dw_hdmi *hdmi) >> /* Disable all interrupts */ >> hdmi_writeb(hdmi, ~0, HDMI_IH_MUTE_PHY_STAT0); >> >> - if (hdmi->cec_notifier) >> - cec_notifier_put(hdmi->cec_notifier); >> - >> clk_disable_unprepare(hdmi->iahb_clk); >> clk_disable_unprepare(hdmi->isfr_clk); >> if (hdmi->cec_clk) >> >
Hi Hans, On 19/08/2019 16:05, Hans Verkuil wrote: > On 8/19/19 11:32 AM, Hans Verkuil wrote: >> On 8/14/19 12:45 PM, Dariusz Marcinkiewicz wrote: >>> Use the new cec_notifier_conn_(un)register() functions to >>> (un)register the notifier for the HDMI connector, and fill in >>> the cec_connector_info. >>> >>> Changes since v6: >>> - move cec_notifier_conn_unregister to a bridge detach >>> function, >>> - add a mutex protecting a CEC notifier. >>> Changes since v4: >>> - typo fix >>> Changes since v2: >>> - removed unnecessary NULL check before a call to >>> cec_notifier_conn_unregister, >>> - use cec_notifier_phys_addr_invalidate to invalidate physical >>> address. >>> Changes since v1: >>> Add memory barrier to make sure that the notifier >>> becomes visible to the irq thread once it is fully >>> constructed. >>> >>> Signed-off-by: Dariusz Marcinkiewicz <darekm@google.com> >> >> Acked-by: Hans Verkuil <hverkuil-cisco@xs4all.nl> > > Tested-by: Hans Verkuil <hverkuil-cisco@xs4all.nl> Did you test it on an Amlogic platform ? If yes, I don't have to ! Neil > > Regards, > > Hans > >> >> Regards, >> >> Hans >> >>> --- >>> drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 45 +++++++++++++++-------- >>> 1 file changed, 30 insertions(+), 15 deletions(-) >>> >>> diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c >>> index 83b94b66e464e..55162c9092f71 100644 >>> --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c >>> +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c >>> @@ -190,6 +190,7 @@ struct dw_hdmi { >>> void (*enable_audio)(struct dw_hdmi *hdmi); >>> void (*disable_audio)(struct dw_hdmi *hdmi); >>> >>> + struct mutex cec_notifier_mutex; >>> struct cec_notifier *cec_notifier; >>> }; >>> >>> @@ -2194,6 +2195,8 @@ static int dw_hdmi_bridge_attach(struct drm_bridge *bridge) >>> struct dw_hdmi *hdmi = bridge->driver_private; >>> struct drm_encoder *encoder = bridge->encoder; >>> struct drm_connector *connector = &hdmi->connector; >>> + struct cec_connector_info conn_info; >>> + struct cec_notifier *notifier; >>> >>> connector->interlace_allowed = 1; >>> connector->polled = DRM_CONNECTOR_POLL_HPD; >>> @@ -2207,9 +2210,29 @@ static int dw_hdmi_bridge_attach(struct drm_bridge *bridge) >>> >>> drm_connector_attach_encoder(connector, encoder); >>> >>> + cec_fill_conn_info_from_drm(&conn_info, connector); >>> + >>> + notifier = cec_notifier_conn_register(hdmi->dev, NULL, &conn_info); >>> + if (!notifier) >>> + return -ENOMEM; >>> + >>> + mutex_lock(&hdmi->cec_notifier_mutex); >>> + hdmi->cec_notifier = notifier; >>> + mutex_unlock(&hdmi->cec_notifier_mutex); >>> + >>> return 0; >>> } >>> >>> +static void dw_hdmi_bridge_detach(struct drm_bridge *bridge) >>> +{ >>> + struct dw_hdmi *hdmi = bridge->driver_private; >>> + >>> + mutex_lock(&hdmi->cec_notifier_mutex); >>> + cec_notifier_conn_unregister(hdmi->cec_notifier); >>> + hdmi->cec_notifier = NULL; >>> + mutex_unlock(&hdmi->cec_notifier_mutex); >>> +} >>> + >>> static enum drm_mode_status >>> dw_hdmi_bridge_mode_valid(struct drm_bridge *bridge, >>> const struct drm_display_mode *mode) >>> @@ -2266,6 +2289,7 @@ static void dw_hdmi_bridge_enable(struct drm_bridge *bridge) >>> >>> static const struct drm_bridge_funcs dw_hdmi_bridge_funcs = { >>> .attach = dw_hdmi_bridge_attach, >>> + .detach = dw_hdmi_bridge_detach, >>> .enable = dw_hdmi_bridge_enable, >>> .disable = dw_hdmi_bridge_disable, >>> .mode_set = dw_hdmi_bridge_mode_set, >>> @@ -2373,9 +2397,11 @@ static irqreturn_t dw_hdmi_irq(int irq, void *dev_id) >>> phy_stat & HDMI_PHY_HPD, >>> phy_stat & HDMI_PHY_RX_SENSE); >>> >>> - if ((phy_stat & (HDMI_PHY_RX_SENSE | HDMI_PHY_HPD)) == 0) >>> - cec_notifier_set_phys_addr(hdmi->cec_notifier, >>> - CEC_PHYS_ADDR_INVALID); >>> + if ((phy_stat & (HDMI_PHY_RX_SENSE | HDMI_PHY_HPD)) == 0) { >>> + mutex_lock(&hdmi->cec_notifier_mutex); >>> + cec_notifier_phys_addr_invalidate(hdmi->cec_notifier); >>> + mutex_unlock(&hdmi->cec_notifier_mutex); >>> + } >>> } >>> >>> if (intr_stat & HDMI_IH_PHY_STAT0_HPD) { >>> @@ -2561,6 +2587,7 @@ __dw_hdmi_probe(struct platform_device *pdev, >>> >>> mutex_init(&hdmi->mutex); >>> mutex_init(&hdmi->audio_mutex); >>> + mutex_init(&hdmi->cec_notifier_mutex); >>> spin_lock_init(&hdmi->audio_lock); >>> >>> ddc_node = of_parse_phandle(np, "ddc-i2c-bus", 0); >>> @@ -2693,12 +2720,6 @@ __dw_hdmi_probe(struct platform_device *pdev, >>> if (ret) >>> goto err_iahb; >>> >>> - hdmi->cec_notifier = cec_notifier_get(dev); >>> - if (!hdmi->cec_notifier) { >>> - ret = -ENOMEM; >>> - goto err_iahb; >>> - } >>> - >>> /* >>> * To prevent overflows in HDMI_IH_FC_STAT2, set the clk regenerator >>> * N and cts values before enabling phy >>> @@ -2796,9 +2817,6 @@ __dw_hdmi_probe(struct platform_device *pdev, >>> hdmi->ddc = NULL; >>> } >>> >>> - if (hdmi->cec_notifier) >>> - cec_notifier_put(hdmi->cec_notifier); >>> - >>> clk_disable_unprepare(hdmi->iahb_clk); >>> if (hdmi->cec_clk) >>> clk_disable_unprepare(hdmi->cec_clk); >>> @@ -2820,9 +2838,6 @@ static void __dw_hdmi_remove(struct dw_hdmi *hdmi) >>> /* Disable all interrupts */ >>> hdmi_writeb(hdmi, ~0, HDMI_IH_MUTE_PHY_STAT0); >>> >>> - if (hdmi->cec_notifier) >>> - cec_notifier_put(hdmi->cec_notifier); >>> - >>> clk_disable_unprepare(hdmi->iahb_clk); >>> clk_disable_unprepare(hdmi->isfr_clk); >>> if (hdmi->cec_clk) >>> >> >
On 8/19/19 4:38 PM, Neil Armstrong wrote: > Hi Hans, > > On 19/08/2019 16:05, Hans Verkuil wrote: >> On 8/19/19 11:32 AM, Hans Verkuil wrote: >>> On 8/14/19 12:45 PM, Dariusz Marcinkiewicz wrote: >>>> Use the new cec_notifier_conn_(un)register() functions to >>>> (un)register the notifier for the HDMI connector, and fill in >>>> the cec_connector_info. >>>> >>>> Changes since v6: >>>> - move cec_notifier_conn_unregister to a bridge detach >>>> function, >>>> - add a mutex protecting a CEC notifier. >>>> Changes since v4: >>>> - typo fix >>>> Changes since v2: >>>> - removed unnecessary NULL check before a call to >>>> cec_notifier_conn_unregister, >>>> - use cec_notifier_phys_addr_invalidate to invalidate physical >>>> address. >>>> Changes since v1: >>>> Add memory barrier to make sure that the notifier >>>> becomes visible to the irq thread once it is fully >>>> constructed. >>>> >>>> Signed-off-by: Dariusz Marcinkiewicz <darekm@google.com> >>> >>> Acked-by: Hans Verkuil <hverkuil-cisco@xs4all.nl> >> >> Tested-by: Hans Verkuil <hverkuil-cisco@xs4all.nl> > > Did you test it on an Amlogic platform ? If yes, I don't have to ! Yes, tested on my khadas VIM2 (modified a bit to fix the issue where the CEC physical address wasn't invalidated correctly as discussed here earlier). Regards, Hans > > Neil > >> >> Regards, >> >> Hans >> >>> >>> Regards, >>> >>> Hans >>> >>>> --- >>>> drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 45 +++++++++++++++-------- >>>> 1 file changed, 30 insertions(+), 15 deletions(-) >>>> >>>> diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c >>>> index 83b94b66e464e..55162c9092f71 100644 >>>> --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c >>>> +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c >>>> @@ -190,6 +190,7 @@ struct dw_hdmi { >>>> void (*enable_audio)(struct dw_hdmi *hdmi); >>>> void (*disable_audio)(struct dw_hdmi *hdmi); >>>> >>>> + struct mutex cec_notifier_mutex; >>>> struct cec_notifier *cec_notifier; >>>> }; >>>> >>>> @@ -2194,6 +2195,8 @@ static int dw_hdmi_bridge_attach(struct drm_bridge *bridge) >>>> struct dw_hdmi *hdmi = bridge->driver_private; >>>> struct drm_encoder *encoder = bridge->encoder; >>>> struct drm_connector *connector = &hdmi->connector; >>>> + struct cec_connector_info conn_info; >>>> + struct cec_notifier *notifier; >>>> >>>> connector->interlace_allowed = 1; >>>> connector->polled = DRM_CONNECTOR_POLL_HPD; >>>> @@ -2207,9 +2210,29 @@ static int dw_hdmi_bridge_attach(struct drm_bridge *bridge) >>>> >>>> drm_connector_attach_encoder(connector, encoder); >>>> >>>> + cec_fill_conn_info_from_drm(&conn_info, connector); >>>> + >>>> + notifier = cec_notifier_conn_register(hdmi->dev, NULL, &conn_info); >>>> + if (!notifier) >>>> + return -ENOMEM; >>>> + >>>> + mutex_lock(&hdmi->cec_notifier_mutex); >>>> + hdmi->cec_notifier = notifier; >>>> + mutex_unlock(&hdmi->cec_notifier_mutex); >>>> + >>>> return 0; >>>> } >>>> >>>> +static void dw_hdmi_bridge_detach(struct drm_bridge *bridge) >>>> +{ >>>> + struct dw_hdmi *hdmi = bridge->driver_private; >>>> + >>>> + mutex_lock(&hdmi->cec_notifier_mutex); >>>> + cec_notifier_conn_unregister(hdmi->cec_notifier); >>>> + hdmi->cec_notifier = NULL; >>>> + mutex_unlock(&hdmi->cec_notifier_mutex); >>>> +} >>>> + >>>> static enum drm_mode_status >>>> dw_hdmi_bridge_mode_valid(struct drm_bridge *bridge, >>>> const struct drm_display_mode *mode) >>>> @@ -2266,6 +2289,7 @@ static void dw_hdmi_bridge_enable(struct drm_bridge *bridge) >>>> >>>> static const struct drm_bridge_funcs dw_hdmi_bridge_funcs = { >>>> .attach = dw_hdmi_bridge_attach, >>>> + .detach = dw_hdmi_bridge_detach, >>>> .enable = dw_hdmi_bridge_enable, >>>> .disable = dw_hdmi_bridge_disable, >>>> .mode_set = dw_hdmi_bridge_mode_set, >>>> @@ -2373,9 +2397,11 @@ static irqreturn_t dw_hdmi_irq(int irq, void *dev_id) >>>> phy_stat & HDMI_PHY_HPD, >>>> phy_stat & HDMI_PHY_RX_SENSE); >>>> >>>> - if ((phy_stat & (HDMI_PHY_RX_SENSE | HDMI_PHY_HPD)) == 0) >>>> - cec_notifier_set_phys_addr(hdmi->cec_notifier, >>>> - CEC_PHYS_ADDR_INVALID); >>>> + if ((phy_stat & (HDMI_PHY_RX_SENSE | HDMI_PHY_HPD)) == 0) { >>>> + mutex_lock(&hdmi->cec_notifier_mutex); >>>> + cec_notifier_phys_addr_invalidate(hdmi->cec_notifier); >>>> + mutex_unlock(&hdmi->cec_notifier_mutex); >>>> + } >>>> } >>>> >>>> if (intr_stat & HDMI_IH_PHY_STAT0_HPD) { >>>> @@ -2561,6 +2587,7 @@ __dw_hdmi_probe(struct platform_device *pdev, >>>> >>>> mutex_init(&hdmi->mutex); >>>> mutex_init(&hdmi->audio_mutex); >>>> + mutex_init(&hdmi->cec_notifier_mutex); >>>> spin_lock_init(&hdmi->audio_lock); >>>> >>>> ddc_node = of_parse_phandle(np, "ddc-i2c-bus", 0); >>>> @@ -2693,12 +2720,6 @@ __dw_hdmi_probe(struct platform_device *pdev, >>>> if (ret) >>>> goto err_iahb; >>>> >>>> - hdmi->cec_notifier = cec_notifier_get(dev); >>>> - if (!hdmi->cec_notifier) { >>>> - ret = -ENOMEM; >>>> - goto err_iahb; >>>> - } >>>> - >>>> /* >>>> * To prevent overflows in HDMI_IH_FC_STAT2, set the clk regenerator >>>> * N and cts values before enabling phy >>>> @@ -2796,9 +2817,6 @@ __dw_hdmi_probe(struct platform_device *pdev, >>>> hdmi->ddc = NULL; >>>> } >>>> >>>> - if (hdmi->cec_notifier) >>>> - cec_notifier_put(hdmi->cec_notifier); >>>> - >>>> clk_disable_unprepare(hdmi->iahb_clk); >>>> if (hdmi->cec_clk) >>>> clk_disable_unprepare(hdmi->cec_clk); >>>> @@ -2820,9 +2838,6 @@ static void __dw_hdmi_remove(struct dw_hdmi *hdmi) >>>> /* Disable all interrupts */ >>>> hdmi_writeb(hdmi, ~0, HDMI_IH_MUTE_PHY_STAT0); >>>> >>>> - if (hdmi->cec_notifier) >>>> - cec_notifier_put(hdmi->cec_notifier); >>>> - >>>> clk_disable_unprepare(hdmi->iahb_clk); >>>> clk_disable_unprepare(hdmi->isfr_clk); >>>> if (hdmi->cec_clk) >>>> >>> >> >
On 19/08/2019 16:41, Hans Verkuil wrote: > On 8/19/19 4:38 PM, Neil Armstrong wrote: >> Hi Hans, >> >> On 19/08/2019 16:05, Hans Verkuil wrote: >>> On 8/19/19 11:32 AM, Hans Verkuil wrote: >>>> On 8/14/19 12:45 PM, Dariusz Marcinkiewicz wrote: >>>>> Use the new cec_notifier_conn_(un)register() functions to >>>>> (un)register the notifier for the HDMI connector, and fill in >>>>> the cec_connector_info. >>>>> >>>>> Changes since v6: >>>>> - move cec_notifier_conn_unregister to a bridge detach >>>>> function, >>>>> - add a mutex protecting a CEC notifier. >>>>> Changes since v4: >>>>> - typo fix >>>>> Changes since v2: >>>>> - removed unnecessary NULL check before a call to >>>>> cec_notifier_conn_unregister, >>>>> - use cec_notifier_phys_addr_invalidate to invalidate physical >>>>> address. >>>>> Changes since v1: >>>>> Add memory barrier to make sure that the notifier >>>>> becomes visible to the irq thread once it is fully >>>>> constructed. >>>>> >>>>> Signed-off-by: Dariusz Marcinkiewicz <darekm@google.com> >>>> >>>> Acked-by: Hans Verkuil <hverkuil-cisco@xs4all.nl> >>> >>> Tested-by: Hans Verkuil <hverkuil-cisco@xs4all.nl> >> >> Did you test it on an Amlogic platform ? If yes, I don't have to ! > > Yes, tested on my khadas VIM2 (modified a bit to fix the issue where > the CEC physical address wasn't invalidated correctly as discussed here > earlier). Good, thanks. Reviewed-by: Neil Armstrong <narmstrong@baylibre.com> > > Regards, > > Hans > >> >> Neil >> >>> >>> Regards, >>> >>> Hans >>> >>>> >>>> Regards, >>>> >>>> Hans >>>> >>>>> --- >>>>> drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 45 +++++++++++++++-------- >>>>> 1 file changed, 30 insertions(+), 15 deletions(-) >>>>> >>>>> diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c >>>>> index 83b94b66e464e..55162c9092f71 100644 >>>>> --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c >>>>> +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c >>>>> @@ -190,6 +190,7 @@ struct dw_hdmi { >>>>> void (*enable_audio)(struct dw_hdmi *hdmi); >>>>> void (*disable_audio)(struct dw_hdmi *hdmi); >>>>> >>>>> + struct mutex cec_notifier_mutex; >>>>> struct cec_notifier *cec_notifier; >>>>> }; >>>>> >>>>> @@ -2194,6 +2195,8 @@ static int dw_hdmi_bridge_attach(struct drm_bridge *bridge) >>>>> struct dw_hdmi *hdmi = bridge->driver_private; >>>>> struct drm_encoder *encoder = bridge->encoder; >>>>> struct drm_connector *connector = &hdmi->connector; >>>>> + struct cec_connector_info conn_info; >>>>> + struct cec_notifier *notifier; >>>>> >>>>> connector->interlace_allowed = 1; >>>>> connector->polled = DRM_CONNECTOR_POLL_HPD; >>>>> @@ -2207,9 +2210,29 @@ static int dw_hdmi_bridge_attach(struct drm_bridge *bridge) >>>>> >>>>> drm_connector_attach_encoder(connector, encoder); >>>>> >>>>> + cec_fill_conn_info_from_drm(&conn_info, connector); >>>>> + >>>>> + notifier = cec_notifier_conn_register(hdmi->dev, NULL, &conn_info); >>>>> + if (!notifier) >>>>> + return -ENOMEM; >>>>> + >>>>> + mutex_lock(&hdmi->cec_notifier_mutex); >>>>> + hdmi->cec_notifier = notifier; >>>>> + mutex_unlock(&hdmi->cec_notifier_mutex); >>>>> + >>>>> return 0; >>>>> } >>>>> >>>>> +static void dw_hdmi_bridge_detach(struct drm_bridge *bridge) >>>>> +{ >>>>> + struct dw_hdmi *hdmi = bridge->driver_private; >>>>> + >>>>> + mutex_lock(&hdmi->cec_notifier_mutex); >>>>> + cec_notifier_conn_unregister(hdmi->cec_notifier); >>>>> + hdmi->cec_notifier = NULL; >>>>> + mutex_unlock(&hdmi->cec_notifier_mutex); >>>>> +} >>>>> + >>>>> static enum drm_mode_status >>>>> dw_hdmi_bridge_mode_valid(struct drm_bridge *bridge, >>>>> const struct drm_display_mode *mode) >>>>> @@ -2266,6 +2289,7 @@ static void dw_hdmi_bridge_enable(struct drm_bridge *bridge) >>>>> >>>>> static const struct drm_bridge_funcs dw_hdmi_bridge_funcs = { >>>>> .attach = dw_hdmi_bridge_attach, >>>>> + .detach = dw_hdmi_bridge_detach, >>>>> .enable = dw_hdmi_bridge_enable, >>>>> .disable = dw_hdmi_bridge_disable, >>>>> .mode_set = dw_hdmi_bridge_mode_set, >>>>> @@ -2373,9 +2397,11 @@ static irqreturn_t dw_hdmi_irq(int irq, void *dev_id) >>>>> phy_stat & HDMI_PHY_HPD, >>>>> phy_stat & HDMI_PHY_RX_SENSE); >>>>> >>>>> - if ((phy_stat & (HDMI_PHY_RX_SENSE | HDMI_PHY_HPD)) == 0) >>>>> - cec_notifier_set_phys_addr(hdmi->cec_notifier, >>>>> - CEC_PHYS_ADDR_INVALID); >>>>> + if ((phy_stat & (HDMI_PHY_RX_SENSE | HDMI_PHY_HPD)) == 0) { >>>>> + mutex_lock(&hdmi->cec_notifier_mutex); >>>>> + cec_notifier_phys_addr_invalidate(hdmi->cec_notifier); >>>>> + mutex_unlock(&hdmi->cec_notifier_mutex); >>>>> + } >>>>> } >>>>> >>>>> if (intr_stat & HDMI_IH_PHY_STAT0_HPD) { >>>>> @@ -2561,6 +2587,7 @@ __dw_hdmi_probe(struct platform_device *pdev, >>>>> >>>>> mutex_init(&hdmi->mutex); >>>>> mutex_init(&hdmi->audio_mutex); >>>>> + mutex_init(&hdmi->cec_notifier_mutex); >>>>> spin_lock_init(&hdmi->audio_lock); >>>>> >>>>> ddc_node = of_parse_phandle(np, "ddc-i2c-bus", 0); >>>>> @@ -2693,12 +2720,6 @@ __dw_hdmi_probe(struct platform_device *pdev, >>>>> if (ret) >>>>> goto err_iahb; >>>>> >>>>> - hdmi->cec_notifier = cec_notifier_get(dev); >>>>> - if (!hdmi->cec_notifier) { >>>>> - ret = -ENOMEM; >>>>> - goto err_iahb; >>>>> - } >>>>> - >>>>> /* >>>>> * To prevent overflows in HDMI_IH_FC_STAT2, set the clk regenerator >>>>> * N and cts values before enabling phy >>>>> @@ -2796,9 +2817,6 @@ __dw_hdmi_probe(struct platform_device *pdev, >>>>> hdmi->ddc = NULL; >>>>> } >>>>> >>>>> - if (hdmi->cec_notifier) >>>>> - cec_notifier_put(hdmi->cec_notifier); >>>>> - >>>>> clk_disable_unprepare(hdmi->iahb_clk); >>>>> if (hdmi->cec_clk) >>>>> clk_disable_unprepare(hdmi->cec_clk); >>>>> @@ -2820,9 +2838,6 @@ static void __dw_hdmi_remove(struct dw_hdmi *hdmi) >>>>> /* Disable all interrupts */ >>>>> hdmi_writeb(hdmi, ~0, HDMI_IH_MUTE_PHY_STAT0); >>>>> >>>>> - if (hdmi->cec_notifier) >>>>> - cec_notifier_put(hdmi->cec_notifier); >>>>> - >>>>> clk_disable_unprepare(hdmi->iahb_clk); >>>>> clk_disable_unprepare(hdmi->isfr_clk); >>>>> if (hdmi->cec_clk) >>>>> >>>> >>> >> >
On 19/08/2019 16:47, Neil Armstrong wrote: > On 19/08/2019 16:41, Hans Verkuil wrote: >> On 8/19/19 4:38 PM, Neil Armstrong wrote: >>> Hi Hans, >>> >>> On 19/08/2019 16:05, Hans Verkuil wrote: >>>> On 8/19/19 11:32 AM, Hans Verkuil wrote: >>>>> On 8/14/19 12:45 PM, Dariusz Marcinkiewicz wrote: >>>>>> Use the new cec_notifier_conn_(un)register() functions to >>>>>> (un)register the notifier for the HDMI connector, and fill in >>>>>> the cec_connector_info. >>>>>> >>>>>> Changes since v6: >>>>>> - move cec_notifier_conn_unregister to a bridge detach >>>>>> function, >>>>>> - add a mutex protecting a CEC notifier. >>>>>> Changes since v4: >>>>>> - typo fix >>>>>> Changes since v2: >>>>>> - removed unnecessary NULL check before a call to >>>>>> cec_notifier_conn_unregister, >>>>>> - use cec_notifier_phys_addr_invalidate to invalidate physical >>>>>> address. >>>>>> Changes since v1: >>>>>> Add memory barrier to make sure that the notifier >>>>>> becomes visible to the irq thread once it is fully >>>>>> constructed. >>>>>> >>>>>> Signed-off-by: Dariusz Marcinkiewicz <darekm@google.com> >>>>> >>>>> Acked-by: Hans Verkuil <hverkuil-cisco@xs4all.nl> >>>> >>>> Tested-by: Hans Verkuil <hverkuil-cisco@xs4all.nl> >>> >>> Did you test it on an Amlogic platform ? If yes, I don't have to ! >> >> Yes, tested on my khadas VIM2 (modified a bit to fix the issue where >> the CEC physical address wasn't invalidated correctly as discussed here >> earlier). > > Good, thanks. > > Reviewed-by: Neil Armstrong <narmstrong@baylibre.com> > >> >> Regards, >> >> Hans >> >>> >>> Neil >>> >>>> >>>> Regards, >>>> >>>> Hans >>>> >>>>> >>>>> Regards, >>>>> >>>>> Hans >>>>> >>>>>> --- >>>>>> drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 45 +++++++++++++++-------- >>>>>> 1 file changed, 30 insertions(+), 15 deletions(-) >>>>>> >>>>>> diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c >>>>>> index 83b94b66e464e..55162c9092f71 100644 >>>>>> --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c >>>>>> +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c >>>>>> @@ -190,6 +190,7 @@ struct dw_hdmi { >>>>>> void (*enable_audio)(struct dw_hdmi *hdmi); >>>>>> void (*disable_audio)(struct dw_hdmi *hdmi); >>>>>> >>>>>> + struct mutex cec_notifier_mutex; >>>>>> struct cec_notifier *cec_notifier; >>>>>> }; >>>>>> >>>>>> @@ -2194,6 +2195,8 @@ static int dw_hdmi_bridge_attach(struct drm_bridge *bridge) >>>>>> struct dw_hdmi *hdmi = bridge->driver_private; >>>>>> struct drm_encoder *encoder = bridge->encoder; >>>>>> struct drm_connector *connector = &hdmi->connector; >>>>>> + struct cec_connector_info conn_info; >>>>>> + struct cec_notifier *notifier; >>>>>> >>>>>> connector->interlace_allowed = 1; >>>>>> connector->polled = DRM_CONNECTOR_POLL_HPD; >>>>>> @@ -2207,9 +2210,29 @@ static int dw_hdmi_bridge_attach(struct drm_bridge *bridge) >>>>>> >>>>>> drm_connector_attach_encoder(connector, encoder); >>>>>> >>>>>> + cec_fill_conn_info_from_drm(&conn_info, connector); >>>>>> + >>>>>> + notifier = cec_notifier_conn_register(hdmi->dev, NULL, &conn_info); >>>>>> + if (!notifier) >>>>>> + return -ENOMEM; >>>>>> + >>>>>> + mutex_lock(&hdmi->cec_notifier_mutex); >>>>>> + hdmi->cec_notifier = notifier; >>>>>> + mutex_unlock(&hdmi->cec_notifier_mutex); >>>>>> + >>>>>> return 0; >>>>>> } >>>>>> >>>>>> +static void dw_hdmi_bridge_detach(struct drm_bridge *bridge) >>>>>> +{ >>>>>> + struct dw_hdmi *hdmi = bridge->driver_private; >>>>>> + >>>>>> + mutex_lock(&hdmi->cec_notifier_mutex); >>>>>> + cec_notifier_conn_unregister(hdmi->cec_notifier); >>>>>> + hdmi->cec_notifier = NULL; >>>>>> + mutex_unlock(&hdmi->cec_notifier_mutex); >>>>>> +} >>>>>> + >>>>>> static enum drm_mode_status >>>>>> dw_hdmi_bridge_mode_valid(struct drm_bridge *bridge, >>>>>> const struct drm_display_mode *mode) >>>>>> @@ -2266,6 +2289,7 @@ static void dw_hdmi_bridge_enable(struct drm_bridge *bridge) >>>>>> >>>>>> static const struct drm_bridge_funcs dw_hdmi_bridge_funcs = { >>>>>> .attach = dw_hdmi_bridge_attach, >>>>>> + .detach = dw_hdmi_bridge_detach, >>>>>> .enable = dw_hdmi_bridge_enable, >>>>>> .disable = dw_hdmi_bridge_disable, >>>>>> .mode_set = dw_hdmi_bridge_mode_set, >>>>>> @@ -2373,9 +2397,11 @@ static irqreturn_t dw_hdmi_irq(int irq, void *dev_id) >>>>>> phy_stat & HDMI_PHY_HPD, >>>>>> phy_stat & HDMI_PHY_RX_SENSE); >>>>>> >>>>>> - if ((phy_stat & (HDMI_PHY_RX_SENSE | HDMI_PHY_HPD)) == 0) >>>>>> - cec_notifier_set_phys_addr(hdmi->cec_notifier, >>>>>> - CEC_PHYS_ADDR_INVALID); >>>>>> + if ((phy_stat & (HDMI_PHY_RX_SENSE | HDMI_PHY_HPD)) == 0) { >>>>>> + mutex_lock(&hdmi->cec_notifier_mutex); >>>>>> + cec_notifier_phys_addr_invalidate(hdmi->cec_notifier); >>>>>> + mutex_unlock(&hdmi->cec_notifier_mutex); >>>>>> + } >>>>>> } >>>>>> >>>>>> if (intr_stat & HDMI_IH_PHY_STAT0_HPD) { >>>>>> @@ -2561,6 +2587,7 @@ __dw_hdmi_probe(struct platform_device *pdev, >>>>>> >>>>>> mutex_init(&hdmi->mutex); >>>>>> mutex_init(&hdmi->audio_mutex); >>>>>> + mutex_init(&hdmi->cec_notifier_mutex); >>>>>> spin_lock_init(&hdmi->audio_lock); >>>>>> >>>>>> ddc_node = of_parse_phandle(np, "ddc-i2c-bus", 0); >>>>>> @@ -2693,12 +2720,6 @@ __dw_hdmi_probe(struct platform_device *pdev, >>>>>> if (ret) >>>>>> goto err_iahb; >>>>>> >>>>>> - hdmi->cec_notifier = cec_notifier_get(dev); >>>>>> - if (!hdmi->cec_notifier) { >>>>>> - ret = -ENOMEM; >>>>>> - goto err_iahb; >>>>>> - } >>>>>> - >>>>>> /* >>>>>> * To prevent overflows in HDMI_IH_FC_STAT2, set the clk regenerator >>>>>> * N and cts values before enabling phy >>>>>> @@ -2796,9 +2817,6 @@ __dw_hdmi_probe(struct platform_device *pdev, >>>>>> hdmi->ddc = NULL; >>>>>> } >>>>>> >>>>>> - if (hdmi->cec_notifier) >>>>>> - cec_notifier_put(hdmi->cec_notifier); >>>>>> - >>>>>> clk_disable_unprepare(hdmi->iahb_clk); >>>>>> if (hdmi->cec_clk) >>>>>> clk_disable_unprepare(hdmi->cec_clk); >>>>>> @@ -2820,9 +2838,6 @@ static void __dw_hdmi_remove(struct dw_hdmi *hdmi) >>>>>> /* Disable all interrupts */ >>>>>> hdmi_writeb(hdmi, ~0, HDMI_IH_MUTE_PHY_STAT0); >>>>>> >>>>>> - if (hdmi->cec_notifier) >>>>>> - cec_notifier_put(hdmi->cec_notifier); >>>>>> - >>>>>> clk_disable_unprepare(hdmi->iahb_clk); >>>>>> clk_disable_unprepare(hdmi->isfr_clk); >>>>>> if (hdmi->cec_clk) >>>>>> >>>>> >>>> >>> >> > Applying to drm-misc-next
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c index 83b94b66e464e..55162c9092f71 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c @@ -190,6 +190,7 @@ struct dw_hdmi { void (*enable_audio)(struct dw_hdmi *hdmi); void (*disable_audio)(struct dw_hdmi *hdmi); + struct mutex cec_notifier_mutex; struct cec_notifier *cec_notifier; }; @@ -2194,6 +2195,8 @@ static int dw_hdmi_bridge_attach(struct drm_bridge *bridge) struct dw_hdmi *hdmi = bridge->driver_private; struct drm_encoder *encoder = bridge->encoder; struct drm_connector *connector = &hdmi->connector; + struct cec_connector_info conn_info; + struct cec_notifier *notifier; connector->interlace_allowed = 1; connector->polled = DRM_CONNECTOR_POLL_HPD; @@ -2207,9 +2210,29 @@ static int dw_hdmi_bridge_attach(struct drm_bridge *bridge) drm_connector_attach_encoder(connector, encoder); + cec_fill_conn_info_from_drm(&conn_info, connector); + + notifier = cec_notifier_conn_register(hdmi->dev, NULL, &conn_info); + if (!notifier) + return -ENOMEM; + + mutex_lock(&hdmi->cec_notifier_mutex); + hdmi->cec_notifier = notifier; + mutex_unlock(&hdmi->cec_notifier_mutex); + return 0; } +static void dw_hdmi_bridge_detach(struct drm_bridge *bridge) +{ + struct dw_hdmi *hdmi = bridge->driver_private; + + mutex_lock(&hdmi->cec_notifier_mutex); + cec_notifier_conn_unregister(hdmi->cec_notifier); + hdmi->cec_notifier = NULL; + mutex_unlock(&hdmi->cec_notifier_mutex); +} + static enum drm_mode_status dw_hdmi_bridge_mode_valid(struct drm_bridge *bridge, const struct drm_display_mode *mode) @@ -2266,6 +2289,7 @@ static void dw_hdmi_bridge_enable(struct drm_bridge *bridge) static const struct drm_bridge_funcs dw_hdmi_bridge_funcs = { .attach = dw_hdmi_bridge_attach, + .detach = dw_hdmi_bridge_detach, .enable = dw_hdmi_bridge_enable, .disable = dw_hdmi_bridge_disable, .mode_set = dw_hdmi_bridge_mode_set, @@ -2373,9 +2397,11 @@ static irqreturn_t dw_hdmi_irq(int irq, void *dev_id) phy_stat & HDMI_PHY_HPD, phy_stat & HDMI_PHY_RX_SENSE); - if ((phy_stat & (HDMI_PHY_RX_SENSE | HDMI_PHY_HPD)) == 0) - cec_notifier_set_phys_addr(hdmi->cec_notifier, - CEC_PHYS_ADDR_INVALID); + if ((phy_stat & (HDMI_PHY_RX_SENSE | HDMI_PHY_HPD)) == 0) { + mutex_lock(&hdmi->cec_notifier_mutex); + cec_notifier_phys_addr_invalidate(hdmi->cec_notifier); + mutex_unlock(&hdmi->cec_notifier_mutex); + } } if (intr_stat & HDMI_IH_PHY_STAT0_HPD) { @@ -2561,6 +2587,7 @@ __dw_hdmi_probe(struct platform_device *pdev, mutex_init(&hdmi->mutex); mutex_init(&hdmi->audio_mutex); + mutex_init(&hdmi->cec_notifier_mutex); spin_lock_init(&hdmi->audio_lock); ddc_node = of_parse_phandle(np, "ddc-i2c-bus", 0); @@ -2693,12 +2720,6 @@ __dw_hdmi_probe(struct platform_device *pdev, if (ret) goto err_iahb; - hdmi->cec_notifier = cec_notifier_get(dev); - if (!hdmi->cec_notifier) { - ret = -ENOMEM; - goto err_iahb; - } - /* * To prevent overflows in HDMI_IH_FC_STAT2, set the clk regenerator * N and cts values before enabling phy @@ -2796,9 +2817,6 @@ __dw_hdmi_probe(struct platform_device *pdev, hdmi->ddc = NULL; } - if (hdmi->cec_notifier) - cec_notifier_put(hdmi->cec_notifier); - clk_disable_unprepare(hdmi->iahb_clk); if (hdmi->cec_clk) clk_disable_unprepare(hdmi->cec_clk); @@ -2820,9 +2838,6 @@ static void __dw_hdmi_remove(struct dw_hdmi *hdmi) /* Disable all interrupts */ hdmi_writeb(hdmi, ~0, HDMI_IH_MUTE_PHY_STAT0); - if (hdmi->cec_notifier) - cec_notifier_put(hdmi->cec_notifier); - clk_disable_unprepare(hdmi->iahb_clk); clk_disable_unprepare(hdmi->isfr_clk); if (hdmi->cec_clk)
Use the new cec_notifier_conn_(un)register() functions to (un)register the notifier for the HDMI connector, and fill in the cec_connector_info. Changes since v6: - move cec_notifier_conn_unregister to a bridge detach function, - add a mutex protecting a CEC notifier. Changes since v4: - typo fix Changes since v2: - removed unnecessary NULL check before a call to cec_notifier_conn_unregister, - use cec_notifier_phys_addr_invalidate to invalidate physical address. Changes since v1: Add memory barrier to make sure that the notifier becomes visible to the irq thread once it is fully constructed. Signed-off-by: Dariusz Marcinkiewicz <darekm@google.com> --- drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 45 +++++++++++++++-------- 1 file changed, 30 insertions(+), 15 deletions(-)