Message ID | 1376500755-30227-8-git-send-email-damien.lespiau@intel.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
On Wed, Aug 14, 2013 at 06:19:10PM +0100, Damien Lespiau wrote: > Provide the same programming model than the other infoframe types. > > The generic _pack() function can't handle those yet as we need to move > the vendor OUI in the generic hdmi_vendor_infoframe structure to know > which kind of vendor infoframe we are dealing with. > > v2: Fix the value of Side-by-side (half), hmdi typo, pack 3D_Ext_Data > (Ville Syrjälä) > > Signed-off-by: Damien Lespiau <damien.lespiau@intel.com> > --- > drivers/video/hdmi.c | 88 ++++++++++++++++++++++++++++++++++++++++++++++++++++ > include/linux/hdmi.h | 26 ++++++++++++++++ > 2 files changed, 114 insertions(+) > > diff --git a/drivers/video/hdmi.c b/drivers/video/hdmi.c > index ac84215..59c4748 100644 > --- a/drivers/video/hdmi.c > +++ b/drivers/video/hdmi.c > @@ -286,6 +286,94 @@ ssize_t hdmi_audio_infoframe_pack(struct hdmi_audio_infoframe *frame, > EXPORT_SYMBOL(hdmi_audio_infoframe_pack); > > /** > + * hdmi_hdmi_infoframe_init() - initialize an HDMI vendor infoframe > + * @frame: HDMI vendor infoframe > + * > + * Returns 0 on success or a negative error code on failure. > + */ > +int hdmi_hdmi_infoframe_init(struct hdmi_hdmi_infoframe *frame) > +{ > + memset(frame, 0, sizeof(*frame)); > + > + frame->type = HDMI_INFOFRAME_TYPE_VENDOR; > + frame->version = 1; > + > + /* 0 is a valid value for s3d_struct, so we use a special "not set" > + * value */ > + frame->s3d_struct = HDMI_3D_STRUCTURE_INVALID; > + > + return 0; > +} > +EXPORT_SYMBOL(hdmi_hdmi_infoframe_init); > + > +/** > + * hdmi_hdmi_infoframe_pack() - write a HDMI vendor infoframe to binary buffer > + * @frame: HDMI infoframe > + * @buffer: destination buffer > + * @size: size of buffer > + * > + * Packs the information contained in the @frame structure into a binary > + * representation that can be written into the corresponding controller > + * registers. Also computes the checksum as required by section 5.3.5 of > + * the HDMI 1.4 specification. > + * > + * Returns the number of bytes packed into the binary buffer or a negative > + * error code on failure. > + */ > +ssize_t hdmi_hdmi_infoframe_pack(struct hdmi_hdmi_infoframe *frame, > + void *buffer, size_t size) > +{ > + u8 *ptr = buffer; > + size_t length; > + > + /* empty info frame */ > + if (frame->vic == 0 && frame->s3d_struct == HDMI_3D_STRUCTURE_INVALID) > + return -EINVAL; > + > + /* only one of those can be supplied */ > + if (frame->vic != 0 && frame->s3d_struct != HDMI_3D_STRUCTURE_INVALID) > + return -EINVAL; > + > + /* for side by side (half) we also need to provide 3D_Ext_Data */ > + if (frame->s3d_struct == HDMI_3D_STRUCTURE_SIDE_BY_SIDE_HALF) Could be >= for a bit of future proofing since the spec says we should send 3d_ext_data even for the reserved > 8 values. > + frame->length = 6; > + else > + frame->length = 5; > + > + length = HDMI_INFOFRAME_HEADER_SIZE + frame->length; > + > + if (size < length) > + return -ENOSPC; > + > + memset(buffer, 0, size); > + > + ptr[0] = frame->type; > + ptr[1] = frame->version; > + ptr[2] = frame->length; > + ptr[3] = 0; /* checksum */ > + > + /* HDMI OUI */ > + ptr[4] = 0x03; > + ptr[5] = 0x0c; > + ptr[6] = 0x00; > + > + if (frame->vic) { > + ptr[7] = 0x1 << 5; /* video format */ > + ptr[8] = frame->vic; > + } else { > + ptr[7] = 0x2 << 5; /* video format */ > + ptr[8] = (frame->s3d_struct & 0xf) << 4; > + if (frame->s3d_struct == HDMI_3D_STRUCTURE_SIDE_BY_SIDE_HALF) Could be >= here too. But whether or not you make those changes: Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com> > + ptr[9] = (frame->s3d_ext_data & 0xf) << 4; > + } > + > + hdmi_infoframe_checksum(buffer, length); > + > + return length; > +} > +EXPORT_SYMBOL(hdmi_hdmi_infoframe_pack); > + > +/** > * hdmi_vendor_infoframe_pack() - write a HDMI vendor infoframe to binary > * buffer > * @frame: HDMI vendor infoframe > diff --git a/include/linux/hdmi.h b/include/linux/hdmi.h > index b98340b..e733252 100644 > --- a/include/linux/hdmi.h > +++ b/include/linux/hdmi.h > @@ -234,11 +234,37 @@ struct hdmi_vendor_infoframe { > ssize_t hdmi_vendor_infoframe_pack(struct hdmi_vendor_infoframe *frame, > void *buffer, size_t size); > > +enum hdmi_3d_structure { > + HDMI_3D_STRUCTURE_INVALID = -1, > + HDMI_3D_STRUCTURE_FRAME_PACKING = 0, > + HDMI_3D_STRUCTURE_FIELD_ALTERNATIVE, > + HDMI_3D_STRUCTURE_LINE_ALTERNATIVE, > + HDMI_3D_STRUCTURE_SIDE_BY_SIDE_FULL, > + HDMI_3D_STRUCTURE_L_DEPTH, > + HDMI_3D_STRUCTURE_L_DEPTH_GFX_GFX_DEPTH, > + HDMI_3D_STRUCTURE_TOP_AND_BOTTOM, > + HDMI_3D_STRUCTURE_SIDE_BY_SIDE_HALF = 8, > +}; > + > +struct hdmi_hdmi_infoframe { > + enum hdmi_infoframe_type type; > + unsigned char version; > + unsigned char length; > + u8 vic; > + enum hdmi_3d_structure s3d_struct; > + unsigned int s3d_ext_data; > +}; > + > +int hdmi_hdmi_infoframe_init(struct hdmi_hdmi_infoframe *frame); > +ssize_t hdmi_hdmi_infoframe_pack(struct hdmi_hdmi_infoframe *frame, > + void *buffer, size_t size); > + > union hdmi_infoframe { > struct hdmi_any_infoframe any; > struct hdmi_avi_infoframe avi; > struct hdmi_spd_infoframe spd; > struct hdmi_vendor_infoframe vendor; > + struct hdmi_hdmi_infoframe hdmi; > struct hdmi_audio_infoframe audio; > }; > > -- > 1.8.3.1 > > _______________________________________________ > Intel-gfx mailing list > Intel-gfx@lists.freedesktop.org > http://lists.freedesktop.org/mailman/listinfo/intel-gfx
On Wed, Aug 14, 2013 at 06:19:10PM +0100, Damien Lespiau wrote: [...] > diff --git a/drivers/video/hdmi.c b/drivers/video/hdmi.c > index ac84215..59c4748 100644 > --- a/drivers/video/hdmi.c > +++ b/drivers/video/hdmi.c > @@ -286,6 +286,94 @@ ssize_t hdmi_audio_infoframe_pack(struct hdmi_audio_infoframe *frame, > EXPORT_SYMBOL(hdmi_audio_infoframe_pack); > > /** > + * hdmi_hdmi_infoframe_init() - initialize an HDMI vendor infoframe > + * @frame: HDMI vendor infoframe > + * > + * Returns 0 on success or a negative error code on failure. > + */ > +int hdmi_hdmi_infoframe_init(struct hdmi_hdmi_infoframe *frame) The hdmi_hdmi_ prefix is weird. Can't we come up with a better prefix? You refer to it as "HDMI vendor infoframe" in the comments, yet we already have struct hdmi_vendor_infoframe. Perhaps hdmi_3d_infoframe or hdmi_vendor_3d_infoframe would be better choices? > +{ > + memset(frame, 0, sizeof(*frame)); > + > + frame->type = HDMI_INFOFRAME_TYPE_VENDOR; > + frame->version = 1; > + > + /* 0 is a valid value for s3d_struct, so we use a special "not set" > + * value */ Nit: The block comment style is inconsistent again. > +/** > + * hdmi_hdmi_infoframe_pack() - write a HDMI vendor infoframe to binary buffer > + * @frame: HDMI infoframe > + * @buffer: destination buffer > + * @size: size of buffer > + * > + * Packs the information contained in the @frame structure into a binary > + * representation that can be written into the corresponding controller > + * registers. Also computes the checksum as required by section 5.3.5 of > + * the HDMI 1.4 specification. I need to dig up that version of the specification. This infoframe doesn't seem to exist in 1.3. Thierry
diff --git a/drivers/video/hdmi.c b/drivers/video/hdmi.c index ac84215..59c4748 100644 --- a/drivers/video/hdmi.c +++ b/drivers/video/hdmi.c @@ -286,6 +286,94 @@ ssize_t hdmi_audio_infoframe_pack(struct hdmi_audio_infoframe *frame, EXPORT_SYMBOL(hdmi_audio_infoframe_pack); /** + * hdmi_hdmi_infoframe_init() - initialize an HDMI vendor infoframe + * @frame: HDMI vendor infoframe + * + * Returns 0 on success or a negative error code on failure. + */ +int hdmi_hdmi_infoframe_init(struct hdmi_hdmi_infoframe *frame) +{ + memset(frame, 0, sizeof(*frame)); + + frame->type = HDMI_INFOFRAME_TYPE_VENDOR; + frame->version = 1; + + /* 0 is a valid value for s3d_struct, so we use a special "not set" + * value */ + frame->s3d_struct = HDMI_3D_STRUCTURE_INVALID; + + return 0; +} +EXPORT_SYMBOL(hdmi_hdmi_infoframe_init); + +/** + * hdmi_hdmi_infoframe_pack() - write a HDMI vendor infoframe to binary buffer + * @frame: HDMI infoframe + * @buffer: destination buffer + * @size: size of buffer + * + * Packs the information contained in the @frame structure into a binary + * representation that can be written into the corresponding controller + * registers. Also computes the checksum as required by section 5.3.5 of + * the HDMI 1.4 specification. + * + * Returns the number of bytes packed into the binary buffer or a negative + * error code on failure. + */ +ssize_t hdmi_hdmi_infoframe_pack(struct hdmi_hdmi_infoframe *frame, + void *buffer, size_t size) +{ + u8 *ptr = buffer; + size_t length; + + /* empty info frame */ + if (frame->vic == 0 && frame->s3d_struct == HDMI_3D_STRUCTURE_INVALID) + return -EINVAL; + + /* only one of those can be supplied */ + if (frame->vic != 0 && frame->s3d_struct != HDMI_3D_STRUCTURE_INVALID) + return -EINVAL; + + /* for side by side (half) we also need to provide 3D_Ext_Data */ + if (frame->s3d_struct == HDMI_3D_STRUCTURE_SIDE_BY_SIDE_HALF) + frame->length = 6; + else + frame->length = 5; + + length = HDMI_INFOFRAME_HEADER_SIZE + frame->length; + + if (size < length) + return -ENOSPC; + + memset(buffer, 0, size); + + ptr[0] = frame->type; + ptr[1] = frame->version; + ptr[2] = frame->length; + ptr[3] = 0; /* checksum */ + + /* HDMI OUI */ + ptr[4] = 0x03; + ptr[5] = 0x0c; + ptr[6] = 0x00; + + if (frame->vic) { + ptr[7] = 0x1 << 5; /* video format */ + ptr[8] = frame->vic; + } else { + ptr[7] = 0x2 << 5; /* video format */ + ptr[8] = (frame->s3d_struct & 0xf) << 4; + if (frame->s3d_struct == HDMI_3D_STRUCTURE_SIDE_BY_SIDE_HALF) + ptr[9] = (frame->s3d_ext_data & 0xf) << 4; + } + + hdmi_infoframe_checksum(buffer, length); + + return length; +} +EXPORT_SYMBOL(hdmi_hdmi_infoframe_pack); + +/** * hdmi_vendor_infoframe_pack() - write a HDMI vendor infoframe to binary * buffer * @frame: HDMI vendor infoframe diff --git a/include/linux/hdmi.h b/include/linux/hdmi.h index b98340b..e733252 100644 --- a/include/linux/hdmi.h +++ b/include/linux/hdmi.h @@ -234,11 +234,37 @@ struct hdmi_vendor_infoframe { ssize_t hdmi_vendor_infoframe_pack(struct hdmi_vendor_infoframe *frame, void *buffer, size_t size); +enum hdmi_3d_structure { + HDMI_3D_STRUCTURE_INVALID = -1, + HDMI_3D_STRUCTURE_FRAME_PACKING = 0, + HDMI_3D_STRUCTURE_FIELD_ALTERNATIVE, + HDMI_3D_STRUCTURE_LINE_ALTERNATIVE, + HDMI_3D_STRUCTURE_SIDE_BY_SIDE_FULL, + HDMI_3D_STRUCTURE_L_DEPTH, + HDMI_3D_STRUCTURE_L_DEPTH_GFX_GFX_DEPTH, + HDMI_3D_STRUCTURE_TOP_AND_BOTTOM, + HDMI_3D_STRUCTURE_SIDE_BY_SIDE_HALF = 8, +}; + +struct hdmi_hdmi_infoframe { + enum hdmi_infoframe_type type; + unsigned char version; + unsigned char length; + u8 vic; + enum hdmi_3d_structure s3d_struct; + unsigned int s3d_ext_data; +}; + +int hdmi_hdmi_infoframe_init(struct hdmi_hdmi_infoframe *frame); +ssize_t hdmi_hdmi_infoframe_pack(struct hdmi_hdmi_infoframe *frame, + void *buffer, size_t size); + union hdmi_infoframe { struct hdmi_any_infoframe any; struct hdmi_avi_infoframe avi; struct hdmi_spd_infoframe spd; struct hdmi_vendor_infoframe vendor; + struct hdmi_hdmi_infoframe hdmi; struct hdmi_audio_infoframe audio; };
Provide the same programming model than the other infoframe types. The generic _pack() function can't handle those yet as we need to move the vendor OUI in the generic hdmi_vendor_infoframe structure to know which kind of vendor infoframe we are dealing with. v2: Fix the value of Side-by-side (half), hmdi typo, pack 3D_Ext_Data (Ville Syrjälä) Signed-off-by: Damien Lespiau <damien.lespiau@intel.com> --- drivers/video/hdmi.c | 88 ++++++++++++++++++++++++++++++++++++++++++++++++++++ include/linux/hdmi.h | 26 ++++++++++++++++ 2 files changed, 114 insertions(+)