On 28/08/2024 17:08, Jani Nikula wrote: > On Wed, 28 Aug 2024, Hans Verkuil <hverkuil-cisco@xxxxxxxxx> 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-cisco@xxxxxxxxx> >> --- >> 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 >