| /* vim: set noet ts=8 sts=8 sw=8 : */ |
| /* |
| * Copyright © 2010 Saleem Abdulrasool <compnerd@compnerd.org>. |
| * Copyright © 2010 Genesi USA, Inc. <matt@genesi-usa.com>. |
| * All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions are met: |
| * |
| * 1. Redistributions of source code must retain the above copyright notice, |
| * this list of conditions and the following disclaimer. |
| * |
| * 2. Redistributions in binary form must reproduce the above copyright notice, |
| * this list of conditions and the following disclaimer in the documentation |
| * and/or other materials provided with the distribution. |
| * |
| * 3. The name of the author may not be used to endorse or promote products |
| * derived from this software without specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED |
| * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
| * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO |
| * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
| * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; |
| * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, |
| * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR |
| * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF |
| * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| /* Header file for EIA CEA 861-E structures and definitions */ |
| |
| #ifndef LINUX_CEA861_H |
| #define LINUX_CEA861_H |
| |
| #include <linux/edid.h> |
| |
| |
| #if !defined(__LITTLE_ENDIAN_BITFIELD) |
| #warning "structures defined and packed for little-endian byte order" |
| #endif |
| |
| |
| #define CEA861_NO_DTDS_PRESENT (0x04) |
| |
| static const u8 CEA861_OUI_REGISTRATION_ID_HDMI_LSB[] = { 0x03, 0x0C, 0x00 }; |
| |
| |
| enum cea861_data_block_type { |
| CEA861_DATA_BLOCK_TYPE_RESERVED0, |
| CEA861_DATA_BLOCK_TYPE_AUDIO, |
| CEA861_DATA_BLOCK_TYPE_VIDEO, |
| CEA861_DATA_BLOCK_TYPE_VENDOR_SPECIFIC, |
| CEA861_DATA_BLOCK_TYPE_SPEAKER_ALLOCATION, |
| CEA861_DATA_BLOCK_TYPE_VESA_DTC, |
| CEA861_DATA_BLOCK_TYPE_RESERVED6, |
| CEA861_DATA_BLOCK_TYPE_EXTENDED, |
| }; |
| |
| |
| struct __packed cea861_data_block_header { |
| unsigned length : 5; |
| unsigned tag : 3; |
| }; |
| |
| /* if header->tag is not 0x7 this will work without any definition */ |
| struct __packed cea861_data_block_generic { |
| struct cea861_data_block_header header; |
| u8 data[31]; |
| }; |
| |
| struct __packed cea861_vendor_specific_data_block { |
| struct cea861_data_block_header header; |
| |
| u8 ieee_registration[3]; |
| u8 data[28]; |
| }; |
| |
| #define CEA861_SVD_NATIVE_FLAG (1 << 7) |
| |
| struct __packed cea861_video_data_block { |
| struct cea861_data_block_header header; |
| |
| /* |
| * actual length in header, the index stops us from walking out of |
| * spec but not out of bounds |
| */ |
| u8 svd[31]; |
| }; |
| |
| struct __packed cea861_timing_block { |
| /* CEA Extension Header */ |
| u8 tag; |
| u8 revision; |
| u8 dtd_offset; |
| |
| /* Global Declarations */ |
| #if defined(__LITTLE_ENDIAN_BITFIELD) |
| unsigned native_dtds : 4; |
| unsigned yuv_422_supported : 1; |
| unsigned yuv_444_supported : 1; |
| unsigned basic_audio_supported : 1; |
| unsigned underscan_supported : 1; |
| #else |
| unsigned underscan_supported : 1; |
| unsigned basic_audio_supported : 1; |
| unsigned yuv_444_supported : 1; |
| unsigned yuv_422_supported : 1; |
| unsigned native_dtds : 4; |
| #endif |
| |
| u8 data[123]; |
| |
| u8 checksum; |
| }; |
| |
| |
| /* HDMI Constants and Structures */ |
| |
| #define HDMI_PACKET_TYPE_INFO_FRAME (0x80) |
| #define HDMI_PACKET_CHECKSUM (0x100) |
| |
| struct __packed hdmi_vsdb { |
| struct cea861_data_block_header header; |
| |
| u8 ieee_registration[3]; |
| unsigned port_configuration_b : 4; |
| unsigned port_configuration_a : 4; |
| unsigned port_configuration_d : 4; |
| unsigned port_configuration_c : 4; |
| |
| /* extension fields */ |
| unsigned dvi_dual_link : 1; |
| unsigned : 1; |
| unsigned : 1; |
| unsigned yuv_444_supported : 1; |
| unsigned colour_depth_30_bit : 1; |
| unsigned colour_depth_36_bit : 1; |
| unsigned colour_depth_48_bit : 1; |
| unsigned audio_info_supported : 1; |
| |
| u8 max_tmds_clock; |
| |
| unsigned : 1; |
| unsigned : 1; |
| unsigned : 1; |
| unsigned : 1; |
| unsigned : 1; |
| unsigned : 1; |
| unsigned interlaced_latency_fields : 1; |
| unsigned latency_fields : 1; |
| |
| u8 video_latency; |
| u8 audio_latency; |
| u8 interlaced_video_latency; |
| u8 interlaced_audio_latency; |
| |
| u8 reserved[]; |
| }; |
| |
| |
| |
| |
| /* if header->tag == 0x7 then extended_tag is valid so we can cast the header to this, |
| * find the tag and then recast it to the appropriate structure (ugh!) |
| */ |
| struct __packed cea861_data_block_extended { |
| struct cea861_data_block_header header; |
| u8 extension_tag; |
| }; |
| |
| /* we're missing a few.. */ |
| enum cea861_data_block_extension_type { |
| CEA861_DATA_BLOCK_EXTENSION_VIDEO_CAPABILITY, |
| CEA861_DATA_BLOCK_EXTENSION_COLORIMETRY = 5, |
| CEA861_DATA_BLOCK_EXTENSION_CEA_MISC_AUDIO = 16, |
| }; |
| |
| struct __packed cea861_video_capability_block { |
| struct cea861_data_block_extended header; |
| unsigned ce_overunder_behavior : 2; |
| unsigned it_overunder_behavior : 2; |
| unsigned pt_overunder_behavior : 2; |
| unsigned quant_range_rgb : 1; |
| unsigned quant_range_ycc : 1; |
| }; |
| |
| |
| |
| /* InfoFrame type constants */ |
| enum info_frame_type { |
| INFO_FRAME_TYPE_RESERVED, |
| INFO_FRAME_TYPE_VENDOR_SPECIFIC, |
| INFO_FRAME_TYPE_AUXILIARY_VIDEO_INFO, |
| INFO_FRAME_TYPE_SOURCE_PRODUCT_DESCRIPTION, |
| INFO_FRAME_TYPE_AUDIO, |
| INFO_FRAME_TYPE_MPEG, |
| }; |
| |
| /* Common InfoFrame header information */ |
| struct __packed info_frame_header { |
| u8 type; |
| u8 version; |
| u8 length; |
| u8 chksum; |
| }; |
| |
| /* AVI InfoFrame (v2) */ |
| #define CEA861_AVI_INFO_FRAME_VERSION (0x02) |
| |
| enum scan_information { |
| SCAN_INFORMATION_UNKNOWN, |
| SCAN_INFORMATION_OVERSCANNED, |
| SCAN_INFORMATION_UNDERSCANNED, |
| SCAN_INFORMATION_RESERVED, |
| }; |
| |
| enum bar_info { |
| BAR_INFO_INVALID, |
| BAR_INFO_VERTICAL, |
| BAR_INFO_HORIZONTAL, |
| BAR_INFO_BOTH, |
| }; |
| |
| enum pixel_format { |
| PIXEL_FORMAT_RGB, /* default */ |
| PIXEL_FORMAT_YUV_422, |
| PIXEL_FORMAT_YUV_444, |
| }; |
| |
| enum active_format_description { |
| ACTIVE_FORMAT_DESCRIPTION_UNSCALED = 0x08, |
| ACTIVE_FORMAT_DESCRIPTION_4_3_CENTERED = 0x09, |
| ACTIVE_FORMAT_DESCRIPTION_16_9_CENTERED = 0x10, |
| ACTIVE_FORMAT_DESCRIPTION_14_9_CENTERED = 0x11, |
| }; |
| |
| enum picture_aspect_ratio { |
| PICTURE_ASPECT_RATIO_UNSCALED, |
| PICTURE_ASPECT_RATIO_4_3, |
| PICTURE_ASPECT_RATIO_16_9, |
| }; |
| |
| enum colorimetry { |
| COLORIMETRY_UNKNOWN, |
| COLORIMETRY_BT601, |
| COLORIMETRY_BT709, |
| COLORIMETRY_EXTENDED, |
| }; |
| |
| enum non_uniform_picture_scaling { |
| NON_UNIFORM_PICTURE_SCALING_NONE, |
| NON_UNIFORM_PICTURE_SCALING_HORIZONTAL, |
| NON_UNIFORM_PICTURE_SCALING_VERTICAL, |
| NON_UNIFORM_PICTURE_SCALING_BOTH, |
| }; |
| |
| /* quantization range are the same flag values for RGB and YCC */ |
| enum quantization_range { |
| QUANTIZATION_RANGE_LIMITED, |
| QUANTIZATION_RANGE_FULL, |
| }; |
| |
| enum extended_colorimetry { |
| EXTENDED_COLORIMETRY_BT601, |
| EXTENDED_COLORIMETRY_BT709, |
| }; |
| |
| enum video_format { |
| VIDEO_FORMAT_UNKNOWN, |
| }; |
| |
| struct __packed avi_info_frame { |
| struct info_frame_header header; |
| |
| unsigned scan_information : 2; |
| unsigned bar_info : 2; |
| unsigned active_format_info_valid : 1; |
| unsigned pixel_format : 2; |
| unsigned dbyte1_reserved0 : 1; |
| |
| unsigned active_format_description : 4; |
| unsigned picture_aspect_ratio : 2; |
| unsigned colorimetry : 2; |
| |
| unsigned non_uniform_picture_scaling : 2; |
| unsigned rgb_quantization_range : 2; |
| unsigned extended_colorimetry : 3; |
| unsigned it_content_present : 1; |
| |
| unsigned video_format : 7; |
| unsigned dbyte4_reserved0 : 1; |
| |
| unsigned pixel_repetition_factor : 4; /* value - 1 */ |
| unsigned content_type : 2; |
| unsigned ycc_quantizaton_range : 2; |
| |
| u16 end_of_top_bar; |
| u16 start_of_bottom_bar; |
| u16 end_of_left_bar; |
| u16 start_of_right_bar; |
| }; |
| |
| |
| /* SPD InfoFrame */ |
| #define CEA861_SPD_INFO_FRAME_VERSION (0x01) |
| |
| enum spd_source_information { |
| SPD_SOURCE_UNKNOWN, |
| SPD_SOURCE_DIGITAL_STB, |
| SPD_SOURCE_DVD_PLAYER, |
| SPD_SOURCE_D_VHS, |
| SPD_SOURCE_HDD_VIDEORECORDER, |
| SPD_SOURCE_DVC, |
| SPD_SOURCE_DSC, |
| SPD_SOURCE_VIDEOCD, |
| SPD_SOURCE_GAME, |
| SPD_SOURCE_PC_GENERAL, |
| SPD_SOURCE_BLURAY_SACD, |
| SPD_SOURCE_HD_DVD, |
| SPD_SOURCE_PMP, |
| }; |
| |
| struct __packed spd_info_frame { |
| struct info_frame_header header; |
| |
| u8 vendor[8]; |
| u8 description[16]; |
| u8 source_device_info; |
| }; |
| |
| |
| /* Audio InfoFrame */ |
| #define CEA861_AUDIO_INFO_FRAME_VERSION (0x01) |
| |
| enum audio_coding_type { |
| CODING_TYPE_REFER_STREAM_HEADER, |
| CODING_TYPE_PCM, |
| CODING_TYPE_AC3, |
| CODING_TYPE_MPEG1_LAYER12, |
| CODING_TYPE_MP3, |
| CODING_TYPE_MPEG2, |
| CODING_TYPE_AAC_LC, |
| CODING_TYPE_DTS, |
| CODING_TYPE_ATRAC, |
| CODING_TYPE_DSD, |
| CODING_TYPE_E_AC3, |
| CODING_TYPE_DTS_HD, |
| CODING_TYPE_MLP, |
| CODING_TYPE_DST, |
| CODING_TYPE_WMA_PRO, |
| CODING_TYPE_EXTENDED, |
| }; |
| |
| enum audio_sample_frequency { |
| FREQUENCY_REFER_STREAM_HEADER, |
| FREQUENCY_32_KHZ, |
| FREQUENCY_44_1_KHZ, |
| FREQUENCY_CD = FREQUENCY_44_1_KHZ, |
| FREQUENCY_48_KHZ, |
| FREQUENCY_88_2_KHZ, |
| FREQUENCY_96_KHZ, |
| FREQUENCY_176_4_KHZ, |
| FREQUENCY_192_KHZ, |
| }; |
| |
| enum audio_sample_size { |
| SAMPLE_SIZE_REFER_STREAM_HEADER, |
| SAMPLE_SIZE_16_BIT, |
| SAMPLE_SIZE_20_BIT, |
| SAMPLE_SIZE_24_BIT, |
| }; |
| |
| enum audio_coding_extended_type { |
| CODING_TYPE_HE_AAC = 1, |
| CODING_TYPE_HE_AACv2, |
| CODING_TYPE_MPEG_SURROUND, |
| }; |
| |
| /* TODO define speaker allocation bits */ |
| |
| #define CHANNEL_COUNT_REFER_STREAM_HEADER (0x00) |
| #define CHANNEL_ALLOCATION_STEREO (0x00) |
| |
| enum audio_downmix { |
| DOWNMIX_PERMITTED, |
| DOWNMIX_PROHIBITED, |
| }; |
| |
| enum audio_lfe_level { |
| LFE_LEVEL_UNKNOWN, |
| LFE_LEVEL_0dB, |
| LFE_LEVEL_PLUS10dB, |
| LFE_LEVEL_RESERVED, |
| }; |
| |
| struct __packed audio_info_frame { |
| struct info_frame_header header; |
| |
| unsigned channel_count : 3; |
| unsigned future13 : 1; |
| unsigned coding_type : 4; |
| |
| unsigned sample_size : 2; |
| unsigned sample_frequency : 3; |
| unsigned future25 : 1; |
| unsigned future26 : 1; |
| unsigned future27 : 1; |
| |
| unsigned format_code_extension : 5; |
| unsigned future35 : 1; |
| unsigned future36 : 1; |
| unsigned future37 : 1; |
| |
| u8 channel_allocation; |
| |
| unsigned lfe_playback_level : 2; |
| unsigned future52 : 1; |
| unsigned level_shift : 4; /* 0-15dB */ |
| unsigned down_mix_inhibit : 1; |
| |
| u8 future_byte_6_10[5]; |
| }; |
| |
| static inline void cea861_checksum_hdmi_info_frame(u8 * const info_frame) |
| { |
| struct info_frame_header * const header = |
| (struct info_frame_header *) info_frame; |
| |
| int i; |
| u8 crc; |
| |
| crc = (HDMI_PACKET_TYPE_INFO_FRAME + header->type) + |
| header->version + (header->length - 1); |
| |
| for (i = 1; i < header->length; i++) |
| crc += info_frame[i]; |
| |
| header->chksum = HDMI_PACKET_CHECKSUM - crc; |
| } |
| |
| #endif /* LINUX_CEA861_H */ |
| |