2012-11-21 18:29:29 +04:00
/*
* Copyright ( C ) 2012 Avionic Design GmbH
*
2013-04-08 16:48:19 +04:00
* Permission is hereby granted , free of charge , to any person obtaining a
* copy of this software and associated documentation files ( the " Software " ) ,
* to deal in the Software without restriction , including without limitation
* the rights to use , copy , modify , merge , publish , distribute , sub license ,
* and / or sell copies of the Software , and to permit persons to whom the
* Software is furnished to do so , subject to the following conditions :
*
* The above copyright notice and this permission notice ( including the
* next paragraph ) shall be included in all copies or substantial portions
* of the Software .
*
* THE SOFTWARE IS PROVIDED " AS IS " , WITHOUT WARRANTY OF ANY KIND , EXPRESS OR
* IMPLIED , INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY ,
* FITNESS FOR A PARTICULAR PURPOSE AND NON - INFRINGEMENT . IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM , DAMAGES OR OTHER
* LIABILITY , WHETHER IN AN ACTION OF CONTRACT , TORT OR OTHERWISE , ARISING
* FROM , OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE .
2012-11-21 18:29:29 +04:00
*/
# include <linux/bitops.h>
# include <linux/errno.h>
# include <linux/export.h>
# include <linux/hdmi.h>
# include <linux/string.h>
static void hdmi_infoframe_checksum ( void * buffer , size_t size )
{
u8 * ptr = buffer ;
u8 csum = 0 ;
size_t i ;
/* compute checksum */
for ( i = 0 ; i < size ; i + + )
csum + = ptr [ i ] ;
ptr [ 3 ] = 256 - csum ;
}
/**
* hdmi_avi_infoframe_init ( ) - initialize an HDMI AVI infoframe
* @ frame : HDMI AVI infoframe
*
* Returns 0 on success or a negative error code on failure .
*/
int hdmi_avi_infoframe_init ( struct hdmi_avi_infoframe * frame )
{
memset ( frame , 0 , sizeof ( * frame ) ) ;
frame - > type = HDMI_INFOFRAME_TYPE_AVI ;
frame - > version = 2 ;
frame - > length = 13 ;
return 0 ;
}
EXPORT_SYMBOL ( hdmi_avi_infoframe_init ) ;
/**
* hdmi_avi_infoframe_pack ( ) - write HDMI AVI infoframe to binary buffer
* @ frame : HDMI AVI 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_avi_infoframe_pack ( struct hdmi_avi_infoframe * frame , void * buffer ,
size_t size )
{
u8 * ptr = buffer ;
size_t length ;
length = HDMI_INFOFRAME_HEADER_SIZE + frame - > length ;
if ( size < length )
return - ENOSPC ;
memset ( buffer , 0 , length ) ;
ptr [ 0 ] = frame - > type ;
ptr [ 1 ] = frame - > version ;
ptr [ 2 ] = frame - > length ;
ptr [ 3 ] = 0 ; /* checksum */
/* start infoframe payload */
ptr + = HDMI_INFOFRAME_HEADER_SIZE ;
ptr [ 0 ] = ( ( frame - > colorspace & 0x3 ) < < 5 ) | ( frame - > scan_mode & 0x3 ) ;
if ( frame - > active_info_valid )
ptr [ 0 ] | = BIT ( 4 ) ;
if ( frame - > horizontal_bar_valid )
ptr [ 0 ] | = BIT ( 3 ) ;
if ( frame - > vertical_bar_valid )
ptr [ 0 ] | = BIT ( 2 ) ;
ptr [ 1 ] = ( ( frame - > colorimetry & 0x3 ) < < 6 ) |
( ( frame - > picture_aspect & 0x3 ) < < 4 ) |
( frame - > active_aspect & 0xf ) ;
ptr [ 2 ] = ( ( frame - > extended_colorimetry & 0x7 ) < < 4 ) |
( ( frame - > quantization_range & 0x3 ) < < 2 ) |
( frame - > nups & 0x3 ) ;
if ( frame - > itc )
ptr [ 2 ] | = BIT ( 7 ) ;
ptr [ 3 ] = frame - > video_code & 0x7f ;
ptr [ 4 ] = ( ( frame - > ycc_quantization_range & 0x3 ) < < 6 ) |
( ( frame - > content_type & 0x3 ) < < 4 ) |
( frame - > pixel_repeat & 0xf ) ;
ptr [ 5 ] = frame - > top_bar & 0xff ;
ptr [ 6 ] = ( frame - > top_bar > > 8 ) & 0xff ;
ptr [ 7 ] = frame - > bottom_bar & 0xff ;
ptr [ 8 ] = ( frame - > bottom_bar > > 8 ) & 0xff ;
ptr [ 9 ] = frame - > left_bar & 0xff ;
ptr [ 10 ] = ( frame - > left_bar > > 8 ) & 0xff ;
ptr [ 11 ] = frame - > right_bar & 0xff ;
ptr [ 12 ] = ( frame - > right_bar > > 8 ) & 0xff ;
hdmi_infoframe_checksum ( buffer , length ) ;
return length ;
}
EXPORT_SYMBOL ( hdmi_avi_infoframe_pack ) ;
/**
* hdmi_spd_infoframe_init ( ) - initialize an HDMI SPD infoframe
* @ frame : HDMI SPD infoframe
* @ vendor : vendor string
* @ product : product string
*
* Returns 0 on success or a negative error code on failure .
*/
int hdmi_spd_infoframe_init ( struct hdmi_spd_infoframe * frame ,
const char * vendor , const char * product )
{
memset ( frame , 0 , sizeof ( * frame ) ) ;
frame - > type = HDMI_INFOFRAME_TYPE_SPD ;
frame - > version = 1 ;
frame - > length = 25 ;
strncpy ( frame - > vendor , vendor , sizeof ( frame - > vendor ) ) ;
strncpy ( frame - > product , product , sizeof ( frame - > product ) ) ;
return 0 ;
}
EXPORT_SYMBOL ( hdmi_spd_infoframe_init ) ;
/**
* hdmi_spd_infoframe_pack ( ) - write HDMI SPD infoframe to binary buffer
* @ frame : HDMI SPD 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_spd_infoframe_pack ( struct hdmi_spd_infoframe * frame , void * buffer ,
size_t size )
{
u8 * ptr = buffer ;
size_t length ;
length = HDMI_INFOFRAME_HEADER_SIZE + frame - > length ;
if ( size < length )
return - ENOSPC ;
memset ( buffer , 0 , length ) ;
ptr [ 0 ] = frame - > type ;
ptr [ 1 ] = frame - > version ;
ptr [ 2 ] = frame - > length ;
ptr [ 3 ] = 0 ; /* checksum */
/* start infoframe payload */
ptr + = HDMI_INFOFRAME_HEADER_SIZE ;
memcpy ( ptr , frame - > vendor , sizeof ( frame - > vendor ) ) ;
memcpy ( ptr + 8 , frame - > product , sizeof ( frame - > product ) ) ;
ptr [ 24 ] = frame - > sdi ;
hdmi_infoframe_checksum ( buffer , length ) ;
return length ;
}
EXPORT_SYMBOL ( hdmi_spd_infoframe_pack ) ;
/**
* hdmi_audio_infoframe_init ( ) - initialize an HDMI audio infoframe
* @ frame : HDMI audio infoframe
*
* Returns 0 on success or a negative error code on failure .
*/
int hdmi_audio_infoframe_init ( struct hdmi_audio_infoframe * frame )
{
memset ( frame , 0 , sizeof ( * frame ) ) ;
frame - > type = HDMI_INFOFRAME_TYPE_AUDIO ;
frame - > version = 1 ;
frame - > length = 10 ;
return 0 ;
}
EXPORT_SYMBOL ( hdmi_audio_infoframe_init ) ;
/**
* hdmi_audio_infoframe_pack ( ) - write HDMI audio infoframe to binary buffer
* @ frame : HDMI audio 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_audio_infoframe_pack ( struct hdmi_audio_infoframe * frame ,
void * buffer , size_t size )
{
unsigned char channels ;
u8 * ptr = buffer ;
size_t length ;
length = HDMI_INFOFRAME_HEADER_SIZE + frame - > length ;
if ( size < length )
return - ENOSPC ;
memset ( buffer , 0 , length ) ;
if ( frame - > channels > = 2 )
channels = frame - > channels - 1 ;
else
channels = 0 ;
ptr [ 0 ] = frame - > type ;
ptr [ 1 ] = frame - > version ;
ptr [ 2 ] = frame - > length ;
ptr [ 3 ] = 0 ; /* checksum */
/* start infoframe payload */
ptr + = HDMI_INFOFRAME_HEADER_SIZE ;
ptr [ 0 ] = ( ( frame - > coding_type & 0xf ) < < 4 ) | ( channels & 0x7 ) ;
ptr [ 1 ] = ( ( frame - > sample_frequency & 0x7 ) < < 2 ) |
( frame - > sample_size & 0x3 ) ;
ptr [ 2 ] = frame - > coding_type_ext & 0x1f ;
ptr [ 3 ] = frame - > channel_allocation ;
ptr [ 4 ] = ( frame - > level_shift_value & 0xf ) < < 3 ;
if ( frame - > downmix_inhibit )
ptr [ 4 ] | = BIT ( 7 ) ;
hdmi_infoframe_checksum ( buffer , length ) ;
return length ;
}
EXPORT_SYMBOL ( hdmi_audio_infoframe_pack ) ;
/**
* hdmi_vendor_infoframe_pack ( ) - write a HDMI vendor infoframe to binary
* buffer
* @ frame : HDMI vendor 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_vendor_infoframe_pack ( struct hdmi_vendor_infoframe * frame ,
void * buffer , size_t size )
{
u8 * ptr = buffer ;
size_t length ;
length = HDMI_INFOFRAME_HEADER_SIZE + frame - > length ;
if ( size < length )
return - ENOSPC ;
memset ( buffer , 0 , length ) ;
ptr [ 0 ] = frame - > type ;
ptr [ 1 ] = frame - > version ;
ptr [ 2 ] = frame - > length ;
ptr [ 3 ] = 0 ; /* checksum */
memcpy ( & ptr [ HDMI_INFOFRAME_HEADER_SIZE ] , frame - > data , frame - > length ) ;
hdmi_infoframe_checksum ( buffer , length ) ;
return length ;
}
EXPORT_SYMBOL ( hdmi_vendor_infoframe_pack ) ;