[PATCHv2 2/3] hdmi: added unpack and logging functions for InfoFrames
Thierry Reding
thierry.reding at gmail.com
Thu Dec 18 00:19:29 PST 2014
On Tue, Dec 02, 2014 at 01:08:45PM +0100, Hans Verkuil wrote:
> From: Martin Bugge <marbugge at cisco.com>
>
> When receiving video it is very useful to be able to unpack the InfoFrames.
> Logging is useful as well, both for transmitters and receivers.
>
> Especially when implementing the VIDIOC_LOG_STATUS ioctl (supported by many
> V4L2 drivers) for a receiver it is important to be able to easily log what
> the InfoFrame contains. This greatly simplifies debugging.
>
> Signed-off-by: Martin Bugge <marbugge at cisco.com>
> Signed-off-by: Hans Verkuil <hans.verkuil at cisco.com>
> ---
> drivers/video/hdmi.c | 819 ++++++++++++++++++++++++++++++++++++++++++++++++++-
> include/linux/hdmi.h | 4 +
> 2 files changed, 816 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/video/hdmi.c b/drivers/video/hdmi.c
> index 9e758a8..5f7ab47 100644
> --- a/drivers/video/hdmi.c
> +++ b/drivers/video/hdmi.c
> @@ -27,10 +27,12 @@
> #include <linux/export.h>
> #include <linux/hdmi.h>
> #include <linux/string.h>
> +#include <linux/device.h>
>
> -static void hdmi_infoframe_checksum(void *buffer, size_t size)
> +#define hdmi_log(fmt, ...) dev_printk(level, dev, fmt, ##__VA_ARGS__)
I personally dislike macros like these that make assumptions about the
environment. While somewhat longer, directly using dev_printk() would in
my opinion be clearer.
But I realize this is somewhat bikesheddy, so don't consider it a hard
objection.
> +
> +static u8 hdmi_infoframe_checksum(u8 *ptr, size_t size)
> {
> - u8 *ptr = buffer;
For consistency with the other functions I'd prefer this to take void *
instead of u8 *. That'd also clean up the diff in this part a little.
> u8 csum = 0;
> size_t i;
>
> @@ -38,7 +40,14 @@ static void hdmi_infoframe_checksum(void *buffer, size_t size)
> for (i = 0; i < size; i++)
> csum += ptr[i];
>
> - ptr[3] = 256 - csum;
> + return 256 - csum;
> +}
> +
> +static void hdmi_infoframe_set_checksum(void *buffer, size_t size)
> +{
> + u8 *ptr = buffer;
> + /* update checksum */
I think checkpatch warns these days about missing blank lines after the
declaration block. But perhaps it is tricked by the comment immediately
following.
Nit: I don't think the comment adds any value.
> +static void hdmi_infoframe_log_header(const char *level,
> + struct device *dev, void *f)
Perhaps rather than pass a void *, make this take a hdmi_any_infoframe *
and require callers to explicitly cast.
This is an internal API and therefore less likely to be abused, so again
rather bikesheddy.
> +static const char *hdmi_nups_get_name(enum hdmi_nups nups)
> +{
> + switch (nups) {
> + case HDMI_NUPS_UNKNOWN:
> + return "No Known Non-uniform Scaling";
s/No Known/Unknown/?
> +static void hdmi_avi_infoframe_log(const char *level,
> + struct device *dev,
> + struct hdmi_avi_infoframe *frame)
> +{
> + hdmi_infoframe_log_header(level, dev, frame);
> +
> + hdmi_log(" colorspace: %s\n",
> + hdmi_colorspace_get_name(frame->colorspace));
> + hdmi_log(" scan mode: %s\n",
> + hdmi_scan_mode_get_name(frame->scan_mode));
> + hdmi_log(" colorimetry: %s\n",
> + hdmi_colorimetry_get_name(frame->colorimetry));
> + hdmi_log(" picture aspect: %s\n",
> + hdmi_picture_aspect_get_name(frame->picture_aspect));
> + hdmi_log(" active aspect: %s\n",
> + hdmi_active_aspect_get_name(frame->active_aspect));
> + hdmi_log(" itc: %s\n", frame->itc ? "IT Content" : "No Data");
> + hdmi_log(" extended colorimetry: %s\n",
> + hdmi_extended_colorimetry_get_name(frame->extended_colorimetry));
> + hdmi_log(" quantization range: %s\n",
> + hdmi_quantization_range_get_name(frame->quantization_range));
> + hdmi_log(" nups: %s\n", hdmi_nups_get_name(frame->nups));
> + hdmi_log(" video code: %d\n", frame->video_code);
This could be "%u".
> + hdmi_log(" ycc quantization range: %s\n",
> + hdmi_ycc_quantization_range_get_name(frame->ycc_quantization_range));
> + hdmi_log(" hdmi content type: %s\n",
> + hdmi_content_type_get_name(frame->content_type));
> + hdmi_log(" pixel repeat: %d\n", frame->pixel_repeat);
> + hdmi_log(" bar top %d, bottom %d, left %d, right %d\n",
> + frame->top_bar, frame->bottom_bar,
> + frame->left_bar, frame->right_bar);
Same here.
> +static const char *
> +hdmi_audio_coding_type_get_name(enum hdmi_audio_coding_type coding_type)
> +{
> + switch (coding_type) {
> + case HDMI_AUDIO_CODING_TYPE_STREAM:
> + return "Refer to Stream Header";
[...]
> + case HDMI_AUDIO_CODING_TYPE_CXT:
> + return "Refer to CXT";
These aren't really names, but I can't come up with anything better.
> +static const char *
> +hdmi_audio_coding_type_ext_get_name(enum hdmi_audio_coding_type_ext ctx)
> +{
> + if (ctx < 0 || ctx > 0x1f)
> + return "Invalid";
> +
> + switch (ctx) {
> + case HDMI_AUDIO_CODING_TYPE_EXT_STREAM:
> + return "Stream";
CEA-861-E describes this as: "Refer to Audio Coding Type (CT) field in
Data Byte 1". Maybe "Refer to CT"?
I wonder if we should also update the name of the symbolic constant to
reflect that (HDMI_AUDIO_CODING_TYPE_EXT_CT?).
> +static void hdmi_audio_infoframe_log(const char *level,
> + struct device *dev,
> + struct hdmi_audio_infoframe *frame)
> +{
> + hdmi_infoframe_log_header(level, dev, frame);
> +
> + if (frame->channels)
> + hdmi_log(" channels: %d ch\n", frame->channels - 1);
I'd leave out the "ch" at the end, also perhaps "%d" -> "%u".
> + else
> + hdmi_log(" channels: Refer to stream header\n");
> + hdmi_log(" coding type: %s\n",
> + hdmi_audio_coding_type_get_name(frame->coding_type));
> + hdmi_log(" sample size: %s\n",
> + hdmi_audio_sample_size_get_name(frame->sample_size));
> + hdmi_log(" sample frequency: %s\n",
> + hdmi_audio_sample_frequency_get_name(frame->sample_frequency));
> + hdmi_log(" coding type ext: %s\n",
> + hdmi_audio_coding_type_ext_get_name(frame->coding_type_ext));
> + hdmi_log(" channel allocation: %d\n",
> + frame->channel_allocation);
The table for this is rather huge, so it's probably not a good idea to
return a string representation, but perhaps printing in hex would make
it easier to relate to the specification?
> + hdmi_log(" level shift value: %d db\n",
> + frame->level_shift_value);
Could be "%u" again. Also "db" -> "dB".
> +hdmi_vendor_any_infoframe_log(const char *level,
> + struct device *dev,
> + union hdmi_vendor_any_infoframe *frame)
> +{
[...]
> + if (hvf->vic)
> + hdmi_log(" HDMI VIC: %d\n", hvf->vic);
%u
> + if (hvf->s3d_struct != HDMI_3D_STRUCTURE_INVALID) {
> + hdmi_log(" 3D structure: %s\n",
> + hdmi_3d_structure_get_name(hvf->s3d_struct));
> + if (hvf->s3d_struct >= HDMI_3D_STRUCTURE_SIDE_BY_SIDE_HALF)
> + hdmi_log(" 3D extension data: %d\n",
> + hvf->s3d_ext_data);
%u
> +static int hdmi_avi_infoframe_unpack(struct hdmi_avi_infoframe *frame,
> + void *buffer)
> +{
> + u8 *ptr = buffer;
> + int ret;
> +
> + if (ptr[0] != HDMI_INFOFRAME_TYPE_AVI ||
> + ptr[1] != 2 ||
> + ptr[2] != HDMI_AVI_INFOFRAME_SIZE)
> + return -EINVAL;
> +
> + if (hdmi_infoframe_checksum(buffer, HDMI_INFOFRAME_SIZE(AVI)) != 0)
You use the parameterized HDMI_INFOFRAME_SIZE() here, but the plain
macro above. Perhaps make those consistent?
> +static int hdmi_spd_infoframe_unpack(struct hdmi_spd_infoframe *frame,
> + void *buffer)
> +{
> + u8 *ptr = buffer;
> + int ret;
> +
> + if (ptr[0] != HDMI_INFOFRAME_TYPE_SPD ||
> + ptr[1] != 1 ||
> + ptr[2] != HDMI_SPD_INFOFRAME_SIZE) {
> + return -EINVAL;
> + }
> +
> + if (hdmi_infoframe_checksum(buffer, HDMI_INFOFRAME_SIZE(SPD)) != 0)
> + return -EINVAL;
Same here.
> +static int hdmi_audio_infoframe_unpack(struct hdmi_audio_infoframe *frame,
> + void *buffer)
> +{
> + u8 *ptr = buffer;
> + int ret;
> +
> + if (ptr[0] != HDMI_INFOFRAME_TYPE_AUDIO ||
> + ptr[1] != 1 ||
> + ptr[2] != HDMI_AUDIO_INFOFRAME_SIZE) {
> + return -EINVAL;
> + }
> +
> + if (hdmi_infoframe_checksum(buffer, HDMI_INFOFRAME_SIZE(AUDIO)) != 0)
> + return -EINVAL;
And here.
> +static int
> +hdmi_vendor_any_infoframe_unpack(union hdmi_vendor_any_infoframe *frame,
> + void *buffer)
> +{
[...]
> + /* HDMI OUI */
> + if ((ptr[0] != 0x03) ||
> + (ptr[1] != 0x0c) ||
> + (ptr[2] != 0x00))
> + return -EINVAL;
It'd be nice if this would actually use the HDMI_IEEE_OUI constant. The
_pack() function hardcodes this too, so I guess it's fine and something
that could be cleaned up later on if somebody cares enough.
Thierry
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.freedesktop.org/archives/dri-devel/attachments/20141218/4a9a740c/attachment.sig>
More information about the dri-devel
mailing list