On Wed, 28 Aug 2024, Hans Verkuil <hverkuil-ci...@xs4all.nl> wrote:
> Add new helpers to export received or transmitted HDMI InfoFrames to
> debugfs.
>
> This complements similar code in drm where the transmitted HDMI infoframes
> are exported to debugfs.
>
> The same names have been used as in drm, so this is consistent.
>
> The exported infoframes can be parsed with the edid-decode utility.
>
> Signed-off-by: Hans Verkuil <hverkuil-ci...@xs4all.nl>
> ---
>  drivers/media/v4l2-core/v4l2-dv-timings.c | 63 +++++++++++++++++++++++
>  include/media/v4l2-dv-timings.h           | 48 +++++++++++++++++
>  2 files changed, 111 insertions(+)
>
> diff --git a/drivers/media/v4l2-core/v4l2-dv-timings.c 
> b/drivers/media/v4l2-core/v4l2-dv-timings.c
> index 942d0005c55e..86a8627f4bcc 100644
> --- a/drivers/media/v4l2-core/v4l2-dv-timings.c
> +++ b/drivers/media/v4l2-core/v4l2-dv-timings.c
> @@ -1154,3 +1154,66 @@ int v4l2_phys_addr_validate(u16 phys_addr, u16 
> *parent, u16 *port)
>       return 0;
>  }
>  EXPORT_SYMBOL_GPL(v4l2_phys_addr_validate);
> +
> +#ifdef CONFIG_DEBUG_FS
> +
> +#define DEBUGFS_FOPS(type, flag)                                     \
> +static ssize_t                                                               
> \
> +infoframe_read_##type(struct file *filp,                             \
> +                   char __user *ubuf, size_t count, loff_t *ppos)    \
> +{                                                                    \
> +     struct v4l2_debugfs_if *infoframes = filp->private_data;        \
> +                                                                     \
> +     return infoframes->if_read((flag), infoframes->priv, filp,      \
> +                                ubuf, count, ppos);                  \
> +}                                                                    \
> +                                                                     \
> +static const struct file_operations infoframe_##type##_fops = {              
> \
> +     .owner   = THIS_MODULE,                                         \
> +     .open    = simple_open,                                         \
> +     .read    = infoframe_read_##type,                               \
> +}
> +
> +DEBUGFS_FOPS(avi, V4L2_DEBUGFS_IF_AVI);
> +DEBUGFS_FOPS(audio, V4L2_DEBUGFS_IF_AUDIO);
> +DEBUGFS_FOPS(spd, V4L2_DEBUGFS_IF_SPD);
> +DEBUGFS_FOPS(hdmi, V4L2_DEBUGFS_IF_HDMI);
> +
> +struct v4l2_debugfs_if *v4l2_debugfs_if_alloc(struct dentry *root, u32 
> if_types,
> +                                           void *priv,
> +                                           v4l2_debugfs_if_read_t if_read)
> +{
> +     struct v4l2_debugfs_if *infoframes;
> +
> +     if (IS_ERR_OR_NULL(root) || !if_types || !if_read)
> +             return NULL;
> +
> +     infoframes = kzalloc(sizeof(*infoframes), GFP_KERNEL);
> +     if (!infoframes)
> +             return NULL;
> +
> +     infoframes->if_dir = debugfs_create_dir("infoframes", root);
> +     infoframes->priv = priv;
> +     infoframes->if_read = if_read;
> +     if (if_types & V4L2_DEBUGFS_IF_AVI)
> +             debugfs_create_file("avi", 0400, infoframes->if_dir, 
> infoframes, &infoframe_avi_fops);
> +     if (if_types & V4L2_DEBUGFS_IF_AUDIO)
> +             debugfs_create_file("audio", 0400, infoframes->if_dir, 
> infoframes, &infoframe_audio_fops);
> +     if (if_types & V4L2_DEBUGFS_IF_SPD)
> +             debugfs_create_file("spd", 0400, infoframes->if_dir, 
> infoframes, &infoframe_spd_fops);
> +     if (if_types & V4L2_DEBUGFS_IF_HDMI)
> +             debugfs_create_file("hdmi", 0400, infoframes->if_dir, 
> infoframes, &infoframe_hdmi_fops);
> +     return infoframes;
> +}
> +EXPORT_SYMBOL_GPL(v4l2_debugfs_if_alloc);
> +
> +void v4l2_debugfs_if_free(struct v4l2_debugfs_if *infoframes)
> +{
> +     if (infoframes) {
> +             debugfs_remove_recursive(infoframes->if_dir);
> +             kfree(infoframes);
> +     }
> +}
> +EXPORT_SYMBOL_GPL(v4l2_debugfs_if_free);
> +
> +#endif
> diff --git a/include/media/v4l2-dv-timings.h b/include/media/v4l2-dv-timings.h
> index 8fa963326bf6..13830411bd6c 100644
> --- a/include/media/v4l2-dv-timings.h
> +++ b/include/media/v4l2-dv-timings.h
> @@ -8,6 +8,7 @@
>  #ifndef __V4L2_DV_TIMINGS_H
>  #define __V4L2_DV_TIMINGS_H
>  
> +#include <linux/debugfs.h>

Please don't include headers from headers if you can get by with forward
declarations.

I recently discovered a lot of drm depending on getting seq_file.h and
debugfs.h via media/cec.h...

BR,
Jani.


>  #include <linux/videodev2.h>
>  
>  /**
> @@ -251,4 +252,51 @@ void v4l2_set_edid_phys_addr(u8 *edid, unsigned int 
> size, u16 phys_addr);
>  u16 v4l2_phys_addr_for_input(u16 phys_addr, u8 input);
>  int v4l2_phys_addr_validate(u16 phys_addr, u16 *parent, u16 *port);
>  
> +/* Add support for exporting InfoFrames to debugfs */
> +
> +/*
> + * HDMI InfoFrames start with a 3 byte header, then a checksum,
> + * followed by the actual IF payload.
> + *
> + * The payload length is limited to 30 bytes according to the HDMI spec,
> + * but since the length is encoded in 5 bits, it can be 31 bytes 
> theoretically.
> + * So set the max length as 31 + 3 (header) + 1 (checksum) = 35.
> + */
> +#define V4L2_DEBUGFS_IF_MAX_LEN (35)
> +
> +#define V4L2_DEBUGFS_IF_AVI  BIT(0)
> +#define V4L2_DEBUGFS_IF_AUDIO        BIT(1)
> +#define V4L2_DEBUGFS_IF_SPD  BIT(2)
> +#define V4L2_DEBUGFS_IF_HDMI BIT(3)
> +
> +typedef ssize_t (*v4l2_debugfs_if_read_t)(u32 type, void *priv,
> +                                       struct file *filp, char __user *ubuf,
> +                                       size_t count, loff_t *ppos);
> +
> +struct v4l2_debugfs_if {
> +     struct dentry *if_dir;
> +     void *priv;
> +
> +     v4l2_debugfs_if_read_t if_read;
> +};
> +
> +#ifdef CONFIG_DEBUG_FS
> +struct v4l2_debugfs_if *v4l2_debugfs_if_alloc(struct dentry *root, u32 
> if_types,
> +                                           void *priv,
> +                                           v4l2_debugfs_if_read_t if_read);
> +void v4l2_debugfs_if_free(struct v4l2_debugfs_if *infoframes);
> +#else
> +static inline
> +struct v4l2_debugfs_if *v4l2_debugfs_if_alloc(struct dentry *root, u32 
> if_types,
> +                                           void *priv,
> +                                           v4l2_debugfs_if_read_t if_read)
> +{
> +     return NULL;
> +}
> +
> +static inline void v4l2_debugfs_if_free(struct v4l2_debugfs_if *infoframes)
> +{
> +}
> +#endif
> +
>  #endif

-- 
Jani Nikula, Intel

Reply via email to