mirror of
https://github.com/genesi/linux-legacy.git
synced 2026-09-20 21:54:23 +00:00
Merge branch 'efikasb-10.08.00' of gitorious.org:efikamx/linux-kernel into efikasb-10.08.00
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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 */
|
||||
|
||||
Reference in New Issue
Block a user