<div dir="auto">The flux capacitor stopped fluxing...</div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Fri, Nov 3, 2023, 5:06 AM Hans Verkuil <<a href="mailto:hverkuil@xs4all.nl">hverkuil@xs4all.nl</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Hi Maxime,<br>
<br>
Thank you for posting v3, this time it runs fine on my RPi 4, thank you for<br>
fixing that.<br>
<br>
I'll start working on a conformity checker for this.<br>
<br>
I have a few remarks:<br>
<br>
On 31/10/2023 17:48, Maxime Ripard wrote:<br>
> There has been some discussions recently about the infoframes sent by<br>
> drivers and if they were properly generated.<br>
> <br>
> In parallel, there's been some interest in creating an infoframe-decode<br>
> tool similar to edid-decode.<br>
> <br>
> Both would be much easier if we were to expose the infoframes programmed<br>
> in the hardware. It won't be perfect since we have no guarantee that<br>
> it's actually what goes through the wire, but it's the best we can do.<br>
> <br>
> Signed-off-by: Maxime Ripard <<a href="mailto:mripard@kernel.org" target="_blank" rel="noreferrer">mripard@kernel.org</a>><br>
> ---<br>
>  drivers/gpu/drm/drm_debugfs.c | 110 ++++++++++++++++++++++++++++++++++++++++++<br>
>  1 file changed, 110 insertions(+)<br>
> <br>
> diff --git a/drivers/gpu/drm/drm_debugfs.c b/drivers/gpu/drm/drm_debugfs.c<br>
> index 2de43ff3ce0a..3c65b1d3f926 100644<br>
> --- a/drivers/gpu/drm/drm_debugfs.c<br>
> +++ b/drivers/gpu/drm/drm_debugfs.c<br>
> @@ -538,6 +538,114 @@ static const struct file_operations drm_connector_fops = {<br>
>       .write = connector_write<br>
>  };<br>
>  <br>
> +struct debugfs_wrapper {<br>
> +     struct drm_connector *connector;<br>
> +     struct drm_connector_hdmi_infoframe *frame;<br>
> +};<br>
> +<br>
> +#define HDMI_MAX_INFOFRAME_SIZE              29<br>
> +<br>
> +static ssize_t<br>
> +infoframe_read(struct file *filp, char __user *ubuf, size_t count, loff_t *ppos)<br>
> +{<br>
> +     const struct debugfs_wrapper *wrapper = filp->private_data;<br>
> +     struct drm_connector *connector = wrapper->connector;<br>
> +     struct drm_connector_hdmi_infoframe *infoframe = wrapper->frame;<br>
> +     union hdmi_infoframe *frame = &infoframe->data;<br>
> +     u8 buf[HDMI_MAX_INFOFRAME_SIZE];<br>
> +     ssize_t len = 0;<br>
> +<br>
> +     mutex_lock(&connector->hdmi.infoframes.lock);<br>
> +<br>
> +     if (!infoframe->set)<br>
> +             goto out;<br>
> +<br>
> +     len = hdmi_infoframe_pack(frame, buf, sizeof(buf));<br>
> +     if (len < 0)<br>
> +             goto out;<br>
> +<br>
> +     len = simple_read_from_buffer(ubuf, count, ppos, buf, len);<br>
> +<br>
> +out:<br>
> +     mutex_unlock(&connector->hdmi.infoframes.lock);<br>
> +     return len;<br>
> +}<br>
> +<br>
> +static const struct file_operations infoframe_fops = {<br>
> +     .owner   = THIS_MODULE,<br>
> +     .open    = simple_open,<br>
> +     .read    = infoframe_read,<br>
> +};<br>
> +<br>
> +static int create_hdmi_infoframe_file(struct drm_connector *connector,<br>
> +                                   struct dentry *parent,<br>
> +                                   const char *filename,<br>
> +                                   struct drm_connector_hdmi_infoframe *frame)<br>
> +{<br>
> +     struct drm_device *dev = connector->dev;<br>
> +     struct debugfs_wrapper *wrapper;<br>
> +     struct dentry *file;<br>
> +<br>
> +     wrapper = drmm_kzalloc(dev, sizeof(*wrapper), GFP_KERNEL);<br>
> +     if (!wrapper)<br>
> +             return -ENOMEM;<br>
> +<br>
> +     wrapper->connector = connector;<br>
> +     wrapper->frame = frame;<br>
> +<br>
> +     file = debugfs_create_file(filename, 0400, parent, wrapper, &infoframe_fops);<br>
> +     if (IS_ERR(file))<br>
> +             return PTR_ERR(file);<br>
> +<br>
> +     return 0;<br>
> +}<br>
> +<br>
> +#define CREATE_HDMI_INFOFRAME_FILE(c, p, i)          \<br>
> +     create_hdmi_infoframe_file(c, p, #i, &(c)->hdmi.infoframes.i)<br>
> +<br>
> +static int create_hdmi_infoframe_files(struct drm_connector *connector,<br>
> +                                    struct dentry *parent)<br>
> +{<br>
> +     int ret;<br>
> +<br>
> +     ret = CREATE_HDMI_INFOFRAME_FILE(connector, parent, audio);<br>
> +     if (ret)<br>
> +             return ret;<br>
> +<br>
> +     ret = CREATE_HDMI_INFOFRAME_FILE(connector, parent, avi);<br>
> +     if (ret)<br>
> +             return ret;<br>
> +<br>
> +     ret = CREATE_HDMI_INFOFRAME_FILE(connector, parent, drm);<br>
<br>
Hmm, I had to look into the code to figure out that 'drm' stands for<br>
Dynamic Range and Mastering InfoFrame. While entirely correct, it is<br>
also very confusing in the context of the 'drm' subsystem.<br>
<br>
I am not quite certain what the best approach is here.<br>
<br>
Internally in the drm code it is talking about 'hdr' or 'hdr metadata',<br>
but that's a bit confusing as well since there is also an HDR Dynamic<br>
Metadata Extended InfoFrame defined in CTA-861, even though support for<br>
that is not (yet) implemented in drm.<br>
<br>
At minimum there should be a comment in the code explaining what drm<br>
stands for in this context.<br>
<br>
One option to consider is renaming this file to hdr_drm, thus indicating<br>
that this is HDR related.<br>
<br>
> +     if (ret)<br>
> +             return ret;<br>
> +<br>
> +     ret = CREATE_HDMI_INFOFRAME_FILE(connector, parent, spd);<br>
> +     if (ret)<br>
> +             return ret;<br>
> +<br>
> +     ret = CREATE_HDMI_INFOFRAME_FILE(connector, parent, vendor);<br>
<br>
There may be multiple vendor specific InfoFrames in the future, so how<br>
would that be handled? Perhaps add a comment here that currently only one<br>
vendor specific InfoFrame is supported, but suggest how to handle multiple<br>
VSIFs in the future.<br>
<br>
What would actually be nice (although probably not that easy to fix) is if<br>
the name of the file would be "vendor-XXXXXX' where 'XXXXXX' is the IEEE OUI<br>
number.<br>
<br>
Regards,<br>
<br>
        Hans<br>
<br>
> +     if (ret)<br>
> +             return ret;<br>
> +<br>
> +     return 0;<br>
> +}<br>
> +<br>
> +static void hdmi_debugfs_add(struct drm_connector *connector)<br>
> +{<br>
> +     struct dentry *dir;<br>
> +<br>
> +     if (!(connector->connector_type == DRM_MODE_CONNECTOR_HDMIA ||<br>
> +           connector->connector_type == DRM_MODE_CONNECTOR_HDMIB))<br>
> +             return;<br>
> +<br>
> +     dir = debugfs_create_dir("infoframes", connector->debugfs_entry);<br>
> +     if (IS_ERR(dir))<br>
> +             return;<br>
> +<br>
> +     create_hdmi_infoframe_files(connector, dir);<br>
> +}<br>
> +<br>
>  void drm_debugfs_connector_add(struct drm_connector *connector)<br>
>  {<br>
>       struct drm_minor *minor = connector->dev->primary;<br>
> @@ -565,6 +673,8 @@ void drm_debugfs_connector_add(struct drm_connector *connector)<br>
>       debugfs_create_file("output_bpc", 0444, root, connector,<br>
>                           &output_bpc_fops);<br>
>  <br>
> +     hdmi_debugfs_add(connector);<br>
> +<br>
>       if (connector->funcs->debugfs_init)<br>
>               connector->funcs->debugfs_init(connector, root);<br>
>  }<br>
> <br>
<br>
</blockquote></div>