Re: [PATCH 2/3] hdmi: added unpack and logging functions for InfoFrames

2014-12-01 Thread Thierry Reding
On Fri, Nov 28, 2014 at 03:50:50PM +0100, Hans Verkuil wrote:
 From: Martin Bugge marbu...@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 marbu...@cisco.com
 Signed-off-by: Hans Verkuil hans.verk...@cisco.com
 ---
  drivers/video/hdmi.c | 622 
 ++-
  include/linux/hdmi.h |   3 +
  2 files changed, 618 insertions(+), 7 deletions(-)
 
 diff --git a/drivers/video/hdmi.c b/drivers/video/hdmi.c
 index 9e758a8..9f0f554 100644
 --- a/drivers/video/hdmi.c
 +++ b/drivers/video/hdmi.c
 @@ -27,10 +27,10 @@
  #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)
 +static u8 hdmi_infoframe_calc_checksum(u8 *ptr, size_t size)

I'd personally keep the name here.

 @@ -434,3 +441,604 @@ hdmi_infoframe_pack(union hdmi_infoframe *frame, void 
 *buffer, size_t size)
   return length;
  }
  EXPORT_SYMBOL(hdmi_infoframe_pack);
 +
 +static const char *hdmi_infoframe_type_txt(enum hdmi_infoframe_type type)

Perhaps: hdmi_infoframe_type_get_name()?

 +{
 + switch (type) {
 + case HDMI_INFOFRAME_TYPE_VENDOR: return Vendor;
 + case HDMI_INFOFRAME_TYPE_AVI: return Auxiliary Video Information 
 (AVI);
 + case HDMI_INFOFRAME_TYPE_SPD: return Source Product Description (SPD);
 + case HDMI_INFOFRAME_TYPE_AUDIO: return Audio;

I'd prefer case ...: and return ...; on separate lines for
readability.

 + }
 + return Invalid/Unknown;
 +}

Maybe include the numerical value here? Of course that either means that
callers must pass in a buffer or we sacrifice thread-safety. The buffer
could be optional, somewhat like this:

const char *hdmi_infoframe_get_name(char *buffer, size_t length,
enum hdmi_infoframe_type type)
{
const char *name = NULL;

switch (type) {
case HDMI_INFOFRAME_TYPE_VENDOR:
name = Vendor;
break;
...
}

if (buffer) {
if (!name)
snprintf(buffer, length, unknown (%d), type);
else
snprintf(buffer, length, name);

name = buffer;
}

return name;
}

That way the function would be generally useful and could even be made
publicly available.

 +static void hdmi_infoframe_log_header(struct device *dev, void *f)
 +{
 + struct hdmi_any_infoframe *frame = f;
 + dev_info(dev, HDMI infoframe: %s, version %d, length %d\n,
 + hdmi_infoframe_type_txt(frame-type), frame-version, 
 frame-length);
 +}
 +
 +static const char *hdmi_colorspace_txt(enum hdmi_colorspace colorspace)
 +{
 + switch (colorspace) {
 + case HDMI_COLORSPACE_RGB: return RGB;
 + case HDMI_COLORSPACE_YUV422: return YCbCr 4:2:2;
 + case HDMI_COLORSPACE_YUV444: return YCbCr 4:4:4;
 + case HDMI_COLORSPACE_YUV420: return YCbCr 4:2:0;
 + case HDMI_COLORSPACE_IDO_DEFINED: return IDO Defined;
 + }
 + return Future;
 +}

Similar comments as for the above.

 +static const char *hdmi_scan_mode_txt(enum hdmi_scan_mode scan_mode)
 +{
 + switch(scan_mode) {
 + case HDMI_SCAN_MODE_NONE: return No Data;
 + case HDMI_SCAN_MODE_OVERSCAN: return Composed for overscanned display;
 + case HDMI_SCAN_MODE_UNDERSCAN: return Composed for underscanned 
 display;
 + }
 + return Future;
 +}

This isn't really a name any more, I think it should either stick to
names like None, Overscan, Underscan or it should return a
description, in which case hdmi_scan_mode_get_description() might be
more accurate for a name.

 +static const char *hdmi_colorimetry_txt(enum hdmi_colorimetry colorimetry)
 +{
 + switch(colorimetry) {
 + case HDMI_COLORIMETRY_NONE: return No Data;
 + case HDMI_COLORIMETRY_ITU_601: return ITU601;
 + case HDMI_COLORIMETRY_ITU_709: return ITU709;
 + case HDMI_COLORIMETRY_EXTENDED: return Extended;
 + }
 + return Invalid/Unknown;
 +}

These are names again, so same comments as for the infoframe type. And
perhaps No Data - None in that case.

 +
 +static const char *hdmi_picture_aspect_txt(enum hdmi_picture_aspect 
 picture_aspect)
 +{
 + switch (picture_aspect) {
 + case HDMI_PICTURE_ASPECT_NONE: return No Data;
 + case HDMI_PICTURE_ASPECT_4_3: return 4:3;
 + case HDMI_PICTURE_ASPECT_16_9: return 16:9;
 + }
 + return Future;
 +}

Same here.

 +static const 

Re: [PATCH 2/3] hdmi: added unpack and logging functions for InfoFrames

2014-12-01 Thread Hans Verkuil
Hi Thierry,

Thanks for the review, see my comments below.

On 12/01/2014 02:15 PM, Thierry Reding wrote:
 On Fri, Nov 28, 2014 at 03:50:50PM +0100, Hans Verkuil wrote:
 From: Martin Bugge marbu...@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 marbu...@cisco.com
 Signed-off-by: Hans Verkuil hans.verk...@cisco.com
 ---
  drivers/video/hdmi.c | 622 
 ++-
  include/linux/hdmi.h |   3 +
  2 files changed, 618 insertions(+), 7 deletions(-)

 diff --git a/drivers/video/hdmi.c b/drivers/video/hdmi.c
 index 9e758a8..9f0f554 100644
 --- a/drivers/video/hdmi.c
 +++ b/drivers/video/hdmi.c
 @@ -27,10 +27,10 @@
  #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)
 +static u8 hdmi_infoframe_calc_checksum(u8 *ptr, size_t size)
 
 I'd personally keep the name here.

I'll do that.

 
 @@ -434,3 +441,604 @@ hdmi_infoframe_pack(union hdmi_infoframe *frame, void 
 *buffer, size_t size)
  return length;
  }
  EXPORT_SYMBOL(hdmi_infoframe_pack);
 +
 +static const char *hdmi_infoframe_type_txt(enum hdmi_infoframe_type type)
 
 Perhaps: hdmi_infoframe_type_get_name()?

I think that's better as well, I'll change it.

 
 +{
 +switch (type) {
 +case HDMI_INFOFRAME_TYPE_VENDOR: return Vendor;
 +case HDMI_INFOFRAME_TYPE_AVI: return Auxiliary Video Information 
 (AVI);
 +case HDMI_INFOFRAME_TYPE_SPD: return Source Product Description (SPD);
 +case HDMI_INFOFRAME_TYPE_AUDIO: return Audio;
 
 I'd prefer case ...: and return ...; on separate lines for
 readability.

I actually think that makes it *less* readable. If you really want that, then 
I'll
change it, but I would suggest that you try it yourself first to see if it is
really more readable for you. It isn't for me, so I'll keep this for the next
version.

 
 +}
 +return Invalid/Unknown;
 +}
 
 Maybe include the numerical value here? Of course that either means that
 callers must pass in a buffer or we sacrifice thread-safety. The buffer
 could be optional, somewhat like this:
 
   const char *hdmi_infoframe_get_name(char *buffer, size_t length,
   enum hdmi_infoframe_type type)
   {
   const char *name = NULL;
 
   switch (type) {
   case HDMI_INFOFRAME_TYPE_VENDOR:
   name = Vendor;
   break;
   ...
   }
 
   if (buffer) {
   if (!name)
   snprintf(buffer, length, unknown (%d), type);
   else
   snprintf(buffer, length, name);
 
   name = buffer;
   }
 
   return name;
   }
 
 That way the function would be generally useful and could even be made
 publicly available.

I would do this only where it makes sense. Some of these fields have only one or
two reserved bits left, and in that case is it easier to just say something
like Reserved (3) and do that for each reserved value.

 
 +static void hdmi_infoframe_log_header(struct device *dev, void *f)
 +{
 +struct hdmi_any_infoframe *frame = f;
 +dev_info(dev, HDMI infoframe: %s, version %d, length %d\n,
 +hdmi_infoframe_type_txt(frame-type), frame-version, 
 frame-length);
 +}
 +
 +static const char *hdmi_colorspace_txt(enum hdmi_colorspace colorspace)
 +{
 +switch (colorspace) {
 +case HDMI_COLORSPACE_RGB: return RGB;
 +case HDMI_COLORSPACE_YUV422: return YCbCr 4:2:2;
 +case HDMI_COLORSPACE_YUV444: return YCbCr 4:4:4;
 +case HDMI_COLORSPACE_YUV420: return YCbCr 4:2:0;
 +case HDMI_COLORSPACE_IDO_DEFINED: return IDO Defined;
 +}
 +return Future;
 +}
 
 Similar comments as for the above.
 
 +static const char *hdmi_scan_mode_txt(enum hdmi_scan_mode scan_mode)
 +{
 +switch(scan_mode) {
 +case HDMI_SCAN_MODE_NONE: return No Data;
 +case HDMI_SCAN_MODE_OVERSCAN: return Composed for overscanned display;
 +case HDMI_SCAN_MODE_UNDERSCAN: return Composed for underscanned 
 display;
 +}
 +return Future;
 +}
 
 This isn't really a name any more, I think it should either stick to
 names like None, Overscan, Underscan

I agree with that, I'll change it.

 or it should return a
 description, in which case hdmi_scan_mode_get_description() might be
 more accurate for a name.
 
 +static const char *hdmi_colorimetry_txt(enum hdmi_colorimetry colorimetry)
 +{
 +switch(colorimetry) {
 +case HDMI_COLORIMETRY_NONE: return No Data;
 +

Re: [PATCH 2/3] hdmi: added unpack and logging functions for InfoFrames

2014-12-01 Thread Thierry Reding
On Mon, Dec 01, 2014 at 02:48:47PM +0100, Hans Verkuil wrote:
 Hi Thierry,
 
 Thanks for the review, see my comments below.
 
 On 12/01/2014 02:15 PM, Thierry Reding wrote:
  On Fri, Nov 28, 2014 at 03:50:50PM +0100, Hans Verkuil wrote:
[...]
  +{
  +  switch (type) {
  +  case HDMI_INFOFRAME_TYPE_VENDOR: return Vendor;
  +  case HDMI_INFOFRAME_TYPE_AVI: return Auxiliary Video Information 
  (AVI);
  +  case HDMI_INFOFRAME_TYPE_SPD: return Source Product Description (SPD);
  +  case HDMI_INFOFRAME_TYPE_AUDIO: return Audio;
  
  I'd prefer case ...: and return ...; on separate lines for
  readability.
 
 I actually think that makes it *less* readable. If you really want that, then 
 I'll
 change it, but I would suggest that you try it yourself first to see if it is
 really more readable for you. It isn't for me, so I'll keep this for the next
 version.

I did, and I still think separate lines are more readable, especially if
you throw in a blank line after the return ...;. Anyway, I could keep
my OCD in check if it weren't for the fact that half of these are the
cause for checkpatch to complain. And then if you change the ones that
checkpatch wants you to change, all the others would be inconsistent and
then I'd complain about the inconsistency...

checkpatch flagged a couple other issues, please make sure to address
those as well.

  Maybe include the numerical value here? Of course that either means that
  callers must pass in a buffer or we sacrifice thread-safety. The buffer
  could be optional, somewhat like this:
  
  const char *hdmi_infoframe_get_name(char *buffer, size_t length,
  enum hdmi_infoframe_type type)
  {
  const char *name = NULL;
  
  switch (type) {
  case HDMI_INFOFRAME_TYPE_VENDOR:
  name = Vendor;
  break;
  ...
  }
  
  if (buffer) {
  if (!name)
  snprintf(buffer, length, unknown (%d), type);
  else
  snprintf(buffer, length, name);
  
  name = buffer;
  }
  
  return name;
  }
  
  That way the function would be generally useful and could even be made
  publicly available.
 
 I would do this only where it makes sense. Some of these fields have only one 
 or
 two reserved bits left, and in that case is it easier to just say something
 like Reserved (3) and do that for each reserved value.

Okay.

  +/**
  + * hdmi_infoframe_log() - log info of HDMI infoframe
  + * @dev: device
  + * @frame: HDMI infoframe
  + */
  +void hdmi_infoframe_log(struct device *dev, union hdmi_infoframe *frame)
  +{
  +  switch (frame-any.type) {
  +  case HDMI_INFOFRAME_TYPE_AVI:
  +  hdmi_avi_infoframe_log(dev, frame-avi);
  +  break;
  +  case HDMI_INFOFRAME_TYPE_SPD:
  +  hdmi_spd_infoframe_log(dev, frame-spd);
  +  break;
  +  case HDMI_INFOFRAME_TYPE_AUDIO:
  +  hdmi_audio_infoframe_log(dev, frame-audio);
  +  break;
  +  case HDMI_INFOFRAME_TYPE_VENDOR:
  +  hdmi_vendor_any_infoframe_log(dev, frame-vendor);
  +  break;
  +  default:
  +  WARN(1, Bad infoframe type %d\n, frame-any.type);
  
  Does it make sense for this to be WARN? It's perfectly legal for future
  devices to expose new types of infoframes. Perhaps even expected. But if
  we want to keep this here to help get bug reports so that we don't
  forget to update this code, then maybe we should do the same wherever we
  query the name of enum values above.
 
 I'll drop the WARN from the log function. I think it should also be dropped
 from the unpack. The only place it makes sense is for pack() since there the
 data comes from the driver, not from an external source.

Sounds good.

Thierry


pgpQTn1nRD50A.pgp
Description: PGP signature


Re: [PATCH 2/3] hdmi: added unpack and logging functions for InfoFrames

2014-12-01 Thread Daniel Vetter
On Mon, Dec 01, 2014 at 04:33:31PM +0100, Thierry Reding wrote:
 On Mon, Dec 01, 2014 at 02:48:47PM +0100, Hans Verkuil wrote:
  Hi Thierry,
  
  Thanks for the review, see my comments below.
  
  On 12/01/2014 02:15 PM, Thierry Reding wrote:
   On Fri, Nov 28, 2014 at 03:50:50PM +0100, Hans Verkuil wrote:
 [...]
   +{
   +switch (type) {
   +case HDMI_INFOFRAME_TYPE_VENDOR: return Vendor;
   +case HDMI_INFOFRAME_TYPE_AVI: return Auxiliary Video 
   Information (AVI);
   +case HDMI_INFOFRAME_TYPE_SPD: return Source Product 
   Description (SPD);
   +case HDMI_INFOFRAME_TYPE_AUDIO: return Audio;
   
   I'd prefer case ...: and return ...; on separate lines for
   readability.
  
  I actually think that makes it *less* readable. If you really want that, 
  then I'll
  change it, but I would suggest that you try it yourself first to see if it 
  is
  really more readable for you. It isn't for me, so I'll keep this for the 
  next
  version.
 
 I did, and I still think separate lines are more readable, especially if
 you throw in a blank line after the return ...;. Anyway, I could keep
 my OCD in check if it weren't for the fact that half of these are the
 cause for checkpatch to complain. And then if you change the ones that
 checkpatch wants you to change, all the others would be inconsistent and
 then I'd complain about the inconsistency...

Throwing in my own unasked-for bikshed opinion ;-)

I agree with Thierry that it's more readable since this way the key and
the value can be lined up easily. That's also possible with the
single-line case/return like you do with some more tabs, but usually means
all the lines overflow the 80 limit badly. So only really works for small
defines/values. So my rule of thumb is
- go with single-line case/return and align them
- but break the lines if they would be too long.

Now back to doing useful stuff for me.

Cheers, Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch
--
To unsubscribe from this list: send the line unsubscribe linux-media in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 2/3] hdmi: added unpack and logging functions for InfoFrames

2014-11-28 Thread Hans Verkuil
From: Martin Bugge marbu...@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 marbu...@cisco.com
Signed-off-by: Hans Verkuil hans.verk...@cisco.com
---
 drivers/video/hdmi.c | 622 ++-
 include/linux/hdmi.h |   3 +
 2 files changed, 618 insertions(+), 7 deletions(-)

diff --git a/drivers/video/hdmi.c b/drivers/video/hdmi.c
index 9e758a8..9f0f554 100644
--- a/drivers/video/hdmi.c
+++ b/drivers/video/hdmi.c
@@ -27,10 +27,10 @@
 #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)
+static u8 hdmi_infoframe_calc_checksum(u8 *ptr, size_t size)
 {
-   u8 *ptr = buffer;
u8 csum = 0;
size_t i;
 
@@ -38,7 +38,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 */
+   ptr[3] = hdmi_infoframe_calc_checksum(buffer, size);
 }
 
 /**
@@ -136,7 +143,7 @@ ssize_t hdmi_avi_infoframe_pack(struct hdmi_avi_infoframe 
*frame, void *buffer,
ptr[11] = frame-right_bar  0xff;
ptr[12] = (frame-right_bar  8)  0xff;
 
-   hdmi_infoframe_checksum(buffer, length);
+   hdmi_infoframe_set_checksum(buffer, length);
 
return length;
 }
@@ -206,7 +213,7 @@ ssize_t hdmi_spd_infoframe_pack(struct hdmi_spd_infoframe 
*frame, void *buffer,
 
ptr[24] = frame-sdi;
 
-   hdmi_infoframe_checksum(buffer, length);
+   hdmi_infoframe_set_checksum(buffer, length);
 
return length;
 }
@@ -281,7 +288,7 @@ ssize_t hdmi_audio_infoframe_pack(struct 
hdmi_audio_infoframe *frame,
if (frame-downmix_inhibit)
ptr[4] |= BIT(7);
 
-   hdmi_infoframe_checksum(buffer, length);
+   hdmi_infoframe_set_checksum(buffer, length);
 
return length;
 }
@@ -373,7 +380,7 @@ ssize_t hdmi_vendor_infoframe_pack(struct 
hdmi_vendor_infoframe *frame,
ptr[9] = (frame-s3d_ext_data  0xf)  4;
}
 
-   hdmi_infoframe_checksum(buffer, length);
+   hdmi_infoframe_set_checksum(buffer, length);
 
return length;
 }
@@ -434,3 +441,604 @@ hdmi_infoframe_pack(union hdmi_infoframe *frame, void 
*buffer, size_t size)
return length;
 }
 EXPORT_SYMBOL(hdmi_infoframe_pack);
+
+static const char *hdmi_infoframe_type_txt(enum hdmi_infoframe_type type)
+{
+   switch (type) {
+   case HDMI_INFOFRAME_TYPE_VENDOR: return Vendor;
+   case HDMI_INFOFRAME_TYPE_AVI: return Auxiliary Video Information 
(AVI);
+   case HDMI_INFOFRAME_TYPE_SPD: return Source Product Description (SPD);
+   case HDMI_INFOFRAME_TYPE_AUDIO: return Audio;
+   }
+   return Invalid/Unknown;
+}
+
+static void hdmi_infoframe_log_header(struct device *dev, void *f)
+{
+   struct hdmi_any_infoframe *frame = f;
+   dev_info(dev, HDMI infoframe: %s, version %d, length %d\n,
+   hdmi_infoframe_type_txt(frame-type), frame-version, 
frame-length);
+}
+
+static const char *hdmi_colorspace_txt(enum hdmi_colorspace colorspace)
+{
+   switch (colorspace) {
+   case HDMI_COLORSPACE_RGB: return RGB;
+   case HDMI_COLORSPACE_YUV422: return YCbCr 4:2:2;
+   case HDMI_COLORSPACE_YUV444: return YCbCr 4:4:4;
+   case HDMI_COLORSPACE_YUV420: return YCbCr 4:2:0;
+   case HDMI_COLORSPACE_IDO_DEFINED: return IDO Defined;
+   }
+   return Future;
+}
+
+static const char *hdmi_scan_mode_txt(enum hdmi_scan_mode scan_mode)
+{
+   switch(scan_mode) {
+   case HDMI_SCAN_MODE_NONE: return No Data;
+   case HDMI_SCAN_MODE_OVERSCAN: return Composed for overscanned display;
+   case HDMI_SCAN_MODE_UNDERSCAN: return Composed for underscanned 
display;
+   }
+   return Future;
+}
+
+static const char *hdmi_colorimetry_txt(enum hdmi_colorimetry colorimetry)
+{
+   switch(colorimetry) {
+   case HDMI_COLORIMETRY_NONE: return No Data;
+   case HDMI_COLORIMETRY_ITU_601: return ITU601;
+   case HDMI_COLORIMETRY_ITU_709: return ITU709;
+   case HDMI_COLORIMETRY_EXTENDED: return Extended;
+   }
+   return Invalid/Unknown;
+}
+
+static const char *hdmi_picture_aspect_txt(enum hdmi_picture_aspect 
picture_aspect)
+{
+   switch (picture_aspect) {
+   case HDMI_PICTURE_ASPECT_NONE: return No Data;
+   case HDMI_PICTURE_ASPECT_4_3: return 4:3;
+   case HDMI_PICTURE_ASPECT_16_9: return 16:9;
+   }
+