From: Jani Nikula <jani.nikula@linux.intel.com>
To: "Alvin Šipraga" <alvin@pqrs.dk>,
"Andrzej Hajda" <andrzej.hajda@intel.com>,
"Neil Armstrong" <neil.armstrong@linaro.org>,
"Robert Foss" <rfoss@kernel.org>,
"Laurent Pinchart" <Laurent.pinchart@ideasonboard.com>,
"Jonas Karlman" <jonas@kwiboo.se>,
"Jernej Skrabec" <jernej.skrabec@gmail.com>,
"David Airlie" <airlied@gmail.com>,
"Daniel Vetter" <daniel@ffwll.ch>,
"Hans Verkuil" <hverkuil-cisco@xs4all.nl>
Cc: dri-devel@lists.freedesktop.org, linux-kernel@vger.kernel.org,
"Alvin Šipraga" <alsi@bang-olufsen.dk>
Subject: Re: [PATCH v3 2/2] drm/bridge: adv7511: get edid in hpd_work to update CEC phys address
Date: Tue, 05 Mar 2024 18:18:50 +0200 [thread overview]
Message-ID: <87cys81wk5.fsf@intel.com> (raw)
In-Reply-To: <20240219-adv7511-cec-edid-v3-2-445aed2f1cd7@bang-olufsen.dk>
On Mon, 19 Feb 2024, Alvin Šipraga <alvin@pqrs.dk> wrote:
> From: Alvin Šipraga <alsi@bang-olufsen.dk>
>
> The adv7511 driver is solely responsible for setting the physical
> address of its CEC adapter. To do this, it must read the EDID. However,
> EDID is only read when either the drm_bridge_funcs :: get_edid or
> drm_connector_helper_funcs :: get_modes ops are called. Without loss of
> generality, it cannot be assumed that these ops are called when a sink
> gets attached. Therefore there exist scenarios in which the CEC physical
> address will be invalid (f.f.f.f), rendering the CEC adapter inoperable.
>
> Address this problem by always fetching the EDID in the HPD work when we
> detect a connection. The CEC physical address is set in the process.
> This is done by moving the EDID DRM helper into an internal helper
> function so that it can be cleanly called from an earlier section of
> the code. The EDID getter has not changed in practice.
>
> Reviewed-by: Robert Foss <rfoss@kernel.org>
> Signed-off-by: Alvin Šipraga <alsi@bang-olufsen.dk>
> ---
> drivers/gpu/drm/bridge/adv7511/adv7511_drv.c | 73 ++++++++++++++++++----------
> 1 file changed, 47 insertions(+), 26 deletions(-)
>
> diff --git a/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c b/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c
> index 5ffc5904bd59..d823b372ff43 100644
> --- a/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c
> +++ b/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c
> @@ -542,6 +542,36 @@ static int adv7511_get_edid_block(void *data, u8 *buf, unsigned int block,
> return 0;
> }
>
> +static struct edid *__adv7511_get_edid(struct adv7511 *adv7511,
> + struct drm_connector *connector)
> +{
> + struct edid *edid;
> +
> + /* Reading the EDID only works if the device is powered */
> + if (!adv7511->powered) {
> + unsigned int edid_i2c_addr =
> + (adv7511->i2c_edid->addr << 1);
> +
> + __adv7511_power_on(adv7511);
> +
> + /* Reset the EDID_I2C_ADDR register as it might be cleared */
> + regmap_write(adv7511->regmap, ADV7511_REG_EDID_I2C_ADDR,
> + edid_i2c_addr);
> + }
> +
> + edid = drm_do_get_edid(connector, adv7511_get_edid_block, adv7511);
> +
> + if (!adv7511->powered)
> + __adv7511_power_off(adv7511);
> +
> + adv7511_set_config_csc(adv7511, connector, adv7511->rgb,
> + drm_detect_hdmi_monitor(edid));
> +
> + cec_s_phys_addr_from_edid(adv7511->cec_adap, edid);
It really would be better to do drm_edid_read_custom(),
drm_edid_connector_update(), and cec_s_phys_addr() with the physical
address from connector->display_info.source_physical_address initialized
by drm_edid_connector_update().
The point is, cec_s_phys_addr_from_edid() has its own duplicate EDID
parsing, which is slightly different from drm_edid_connector_update()
and of course redundant.
BR,
Jani.
> +
> + return edid;
> +}
> +
> /* -----------------------------------------------------------------------------
> * Hotplug handling
> */
> @@ -595,8 +625,23 @@ static void adv7511_hpd_work(struct work_struct *work)
> adv7511->connector.status = status;
>
> if (adv7511->connector.dev) {
> - if (status == connector_status_disconnected)
> + if (status == connector_status_disconnected) {
> cec_phys_addr_invalidate(adv7511->cec_adap);
> + } else {
> + struct edid *edid;
> +
> + /*
> + * Get the updated EDID so that the CEC
> + * subsystem gets informed of any change in CEC
> + * address. The helper returns a newly allocated
> + * edid structure, so free it to prevent
> + * leakage.
> + */
> + edid = __adv7511_get_edid(adv7511,
> + &adv7511->connector);
> + kfree(edid);
> + }
> +
> drm_kms_helper_hotplug_event(adv7511->connector.dev);
> } else {
> drm_bridge_hpd_notify(&adv7511->bridge, status);
> @@ -611,31 +656,7 @@ static void adv7511_hpd_work(struct work_struct *work)
> static struct edid *adv7511_get_edid(struct adv7511 *adv7511,
> struct drm_connector *connector)
> {
> - struct edid *edid;
> -
> - /* Reading the EDID only works if the device is powered */
> - if (!adv7511->powered) {
> - unsigned int edid_i2c_addr =
> - (adv7511->i2c_edid->addr << 1);
> -
> - __adv7511_power_on(adv7511);
> -
> - /* Reset the EDID_I2C_ADDR register as it might be cleared */
> - regmap_write(adv7511->regmap, ADV7511_REG_EDID_I2C_ADDR,
> - edid_i2c_addr);
> - }
> -
> - edid = drm_do_get_edid(connector, adv7511_get_edid_block, adv7511);
> -
> - if (!adv7511->powered)
> - __adv7511_power_off(adv7511);
> -
> - adv7511_set_config_csc(adv7511, connector, adv7511->rgb,
> - drm_detect_hdmi_monitor(edid));
> -
> - cec_s_phys_addr_from_edid(adv7511->cec_adap, edid);
> -
> - return edid;
> + return __adv7511_get_edid(adv7511, connector);
> }
>
> static int adv7511_get_modes(struct adv7511 *adv7511,
--
Jani Nikula, Intel
prev parent reply other threads:[~2024-03-05 16:19 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-02-19 20:12 [PATCH v3 0/2] drm/bridge: adv7511: get edid in hpd_work to update CEC phys address Alvin Šipraga
2024-02-19 20:12 ` [PATCH v3 1/2] drm/bridge: adv7511: rearrange hotplug work code Alvin Šipraga
2024-03-05 15:17 ` Laurent Pinchart
2024-02-19 20:12 ` [PATCH v3 2/2] drm/bridge: adv7511: get edid in hpd_work to update CEC phys address Alvin Šipraga
2024-03-05 15:05 ` Robert Foss
2024-03-05 16:10 ` Jani Nikula
2024-03-05 15:22 ` Laurent Pinchart
2024-03-05 16:18 ` Jani Nikula [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=87cys81wk5.fsf@intel.com \
--to=jani.nikula@linux.intel.com \
--cc=Laurent.pinchart@ideasonboard.com \
--cc=airlied@gmail.com \
--cc=alsi@bang-olufsen.dk \
--cc=alvin@pqrs.dk \
--cc=andrzej.hajda@intel.com \
--cc=daniel@ffwll.ch \
--cc=dri-devel@lists.freedesktop.org \
--cc=hverkuil-cisco@xs4all.nl \
--cc=jernej.skrabec@gmail.com \
--cc=jonas@kwiboo.se \
--cc=linux-kernel@vger.kernel.org \
--cc=neil.armstrong@linaro.org \
--cc=rfoss@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.