On 28/08/2024 17:08, Jani Nikula wrote:
> 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.

Done.

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

Patches are welcome!

Regards,

        Hans

> 
> 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
> 

Reply via email to