Merge branch 'efikasb-10.08.00' of gitorious.org:efikamx/linux-kernel into efikasb-10.08.00

This commit is contained in:
Matt Sealey
2011-01-20 11:04:13 -06:00
3 changed files with 163 additions and 65 deletions

View File

@@ -197,9 +197,9 @@ static int siihdmi_read_edid(struct siihdmi_tx *tx, u8 *edid, size_t size)
/* step 1: (potentially) disable HDCP */
/* step 2: request the DDC bus */
ctrl = i2c_smbus_read_byte_data(tx->client, SIIHDMI_TPI_REG_SYS_CTRL);
/* step 2: request the DDC bus */
ret = i2c_smbus_write_byte_data(tx->client,
SIIHDMI_TPI_REG_SYS_CTRL,
ctrl | SIIHDMI_SYS_CTRL_DDC_BUS_REQUEST);
@@ -256,12 +256,57 @@ static int siihdmi_read_edid(struct siihdmi_tx *tx, u8 *edid, size_t size)
return 0;
}
static void siihdmi_parse_cea861_timing_block(struct siihdmi_tx *tx,
const struct edid_extension *ext)
{
const struct cea861_timing_block * const cea =
(struct cea861_timing_block *) ext;
const u8 offset = offsetof(struct cea861_timing_block, data);
u8 index = 0;
BUILD_BUG_ON(sizeof(*cea) != sizeof(*ext));
tx->enable_audio = cea->basic_audio_supported;
if (cea->underscan_supported)
tx->pixel_mapping = PIXEL_MAPPING_UNDERSCANNED;
if (cea->dtd_offset == CEA81_NO_DTDS_PRESENT)
return;
do {
const struct cea861_data_block_header * const header =
(struct cea861_data_block_header *) &cea->data[index];
switch (header->tag) {
case CEA861_DATA_BLOCK_TYPE_VENDOR_SPECIFIC: {
const struct cea861_vendor_specific_data_block * const vsdb =
(struct cea861_vendor_specific_data_block *) header;
if (!memcmp(vsdb->ieee_registration,
CEA861_OUI_REGISTRATION_ID_HDMI_LSB,
sizeof(vsdb->ieee_registration)))
tx->connection_type = CONNECTION_TYPE_HDMI;
}
break;
default:
break;
}
index = index + header->length + sizeof(header);
} while (index < cea->dtd_offset - offset);
}
static void siihdmi_detect_sink(struct siihdmi_tx *tx)
{
u8 edid[EDID_BLOCK_SIZE << 1];
const struct edid_block0 * const block0 = (struct edid_block0 *) edid;
const struct edid_extension * const block1 =
(struct edid_extension *) edid + EDID_BLOCK_SIZE;
u8 *edid;
struct edid_extension *extensions, *extension;
struct edid_block0 block0;
u32 length;
u8 i;
BUILD_BUG_ON(sizeof(block0) != EDID_BLOCK_SIZE);
BUILD_BUG_ON(sizeof(*extension) != EDID_BLOCK_SIZE);
/* defaults */
tx->connection_type = CONNECTION_TYPE_DVI;
@@ -269,31 +314,38 @@ static void siihdmi_detect_sink(struct siihdmi_tx *tx)
tx->enable_audio = false;
/* use EDID to identify sink characteristics */
if (siihdmi_read_edid(tx, edid, sizeof(edid)) < 0)
if (siihdmi_read_edid(tx, (u8 *) &block0, sizeof(block0)) < 0)
return;
if (!block0->extensions)
if (!block0.extensions)
return;
switch (block1->tag) {
case EDID_EXTENSION_CEA: {
const struct cea_timing_block *ctb =
(struct cea_timing_block *) block1;
/* need to allocate space for block 0 as well as the extensions */
length = (block0.extensions + 1) * EDID_BLOCK_SIZE;
tx->enable_audio = ctb->basic_audio_supported;
edid = kzalloc(length, GFP_KERNEL);
if (!edid)
return;
if (ctb->underscan_supported)
tx->pixel_mapping = PIXEL_MAPPING_UNDERSCANNED;
if (siihdmi_read_edid(tx, edid, length) < 0)
goto out;
if (!memcmp(ctb->ieee_registration,
CEA861_OUI_REGISTRATION_ID_HDMI,
sizeof(ctb->ieee_registration)))
tx->connection_type = CONNECTION_TYPE_HDMI;
extensions = (struct edid_extension *) edid + sizeof(block0);
for (i = 0; i < block0.extensions; i++) {
extension = &extensions[i];
switch (extension->tag) {
case EDID_EXTENSION_CEA:
siihdmi_parse_cea861_timing_block(tx, extension);
break;
default:
break;
}
break;
default:
break;
}
out:
kfree(edid);
}
static inline unsigned long siihdmi_ps_to_hz(const unsigned long ps)

View File

@@ -29,27 +29,59 @@
* 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
/* Header file for EIA CEA 861-E structures and definitions */
#include <linux/edid.h>
#define CEA861_DTD_NOT_PRESENT (0x04)
/* NOTE: This is placed inot the EDID in little-endian order */
static const u8 CEA861_OUI_REGISTRATION_ID_HDMI[] = { 0x00, 0x0C, 0x03 };
#if !defined(__LITTLE_ENDIAN_BITFIELD)
#warning "structures defined and packed for little-endian byte order"
#endif
struct __packed cea_timing_block {
#define CEA81_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;
};
struct __packed cea861_vendor_specific_data_block {
struct cea861_data_block_header header;
u8 extended_tag;
u8 ieee_registration[3];
u8 data[];
};
struct __packed cea861_timing_block {
/* CEA Extension Header */
u8 tag;
u8 revision;
u8 dtd_start_offset;
u8 dtd_offset;
/* Global Declarations */
#if defined(__LITTLE_ENDIAN_BITFIELD)
unsigned dtd_block_count : 4;
unsigned native_dtds : 4;
unsigned yuv_422_supported : 1;
unsigned yuv_444_supported : 1;
unsigned basic_audio_supported : 1;
@@ -59,46 +91,58 @@ struct __packed cea_timing_block {
unsigned basic_audio_supported : 1;
unsigned yuv_444_supported : 1;
unsigned yuv_422_supported : 1;
unsigned dtd_block_count : 4;
unsigned native_dtds : 4;
#endif
/* CEA Data Block Collection */
/* Video Data Block */
u8 video_data_start_offset;
u8 short_video_descriptor[7];
/* Audio Data Block */
u8 audio_data_start_offset;
u8 audio_format;
u8 frequency;
u8 bit_rate;
/* Speaker Allocation Block */
u8 speaker_allocation_start_offset;
u8 speaker_designation;
u8 reserved[2];
/* Vendor Specific Data Block */
u8 vendor_specific_offset;
u8 ieee_registration[3];
u8 component_source[2];
struct edid_detailed_timing_descriptor dtb[4];
u8 padding[29];
u8 data[123];
u8 checksum;
};
#if !defined(__LITTLE_ENDIAN_BITFIELD)
#warning "structures defined and packed for little-endian byte order"
#endif
/* 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_id[3];
unsigned port_configuration_a : 4;
unsigned port_configuration_b : 4;
unsigned port_configuration_c : 4;
unsigned port_configuration_d : 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[];
};
/* InfoFrame type constants */
enum info_frame_type {
INFO_FRAME_TYPE_RESERVED,

View File

@@ -38,7 +38,8 @@
#define EDID_BLOCK_SIZE (0x80)
#define EDID_MAX_EXTENSIONS (0xfe)
#define EDID_MAGIC (0x00ffffffffffff00)
static const u8 EDID_HEADER[8] = { 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00 };
enum edid_extension_type {
@@ -198,7 +199,7 @@ struct __packed edid_block0 {
u8 header[8];
/* vendor/product identification */
struct {
struct __packed {
unsigned id0 : 5;
unsigned id1 : 5;
unsigned id2 : 5;
@@ -215,7 +216,7 @@ struct __packed edid_block0 {
u8 revision;
/* basic display parameters and features */
struct {
struct __packed {
unsigned dfp_1x_vsync_serration : 1; /* VESA DFP 1.x */
unsigned green_video_sync : 1;
unsigned composite_sync : 1;
@@ -227,9 +228,10 @@ struct __packed edid_block0 {
u8 maximum_horizontal_image_size; /* cm */
u8 maximum_vertical_image_size; /* cm */
u8 display_transfer_characteristics; /* gamma = (value + 100) / 100 */
struct {
struct __packed {
unsigned default_gtf : 1; /* generalised timing formula */
unsigned preferred_timing_mode : 1;
unsigned standard_default_color_space : 1;
@@ -260,7 +262,7 @@ struct __packed edid_block0 {
u8 white_y;
/* established timings */
struct {
struct __packed {
unsigned timing_800x600_60 : 1;
unsigned timing_800x600_56 : 1;
unsigned timing_640x480_75 : 1;
@@ -279,13 +281,13 @@ struct __packed edid_block0 {
unsigned timing_800x600_72 : 1;
} established_timings;
struct {
struct __packed {
unsigned reserved : 7;
unsigned timing_1152x870_75 : 1;
} manufacturer_timings;
/* standard timing id */
struct {
struct __packed {
u8 horizontal_active_pixels; /* = (value + 31) * 8 */
unsigned refresh_rate : 6; /* = value + 60 */