Пример #1
0
//------------------------------------------------------------------------
BOOLEAN verifyEDID(UINT8 *edid)
{
	if (edid == NULL || !edid_checksum(edid) ||	!edid_check_header(edid)) 
	{
		return FALSE;
	}
	return TRUE;
}
Пример #2
0
u8 edid_simple_parsing(struct hdmi_info *hdmi)
{
    u8 *edid_buf = hdmi->edid_buf;
    int i, index, ret = -EINVAL;
    struct edid_info_struct *edid_info = &hdmi->edid_info;
    unsigned v1, width, height, aspect;
    unsigned extensions;
    unsigned extension;

    EDID_DBG("%s\n", __func__);
    if (!edid_check_header(edid_buf))
    {
        pr_err("%s: incorrect header\n", __func__);
        return INCORRECT_EDID_HEADER;
    }

    // Retrieve the number of extensions in this EDID
    extensions = edid_buf[126];
    EDID_DBG("%s: extensions=%d\n", __func__, extensions);
    if (!extensions)
    {
        hdmi->edid_info.hdmi_sink = false;
        return NO_861_EXTENSIONS;
    }

    /* reset all supported */
    for (i = 0 ; i < ARRAY_SIZE(additional_timing_db); i++)
        additional_timing_db[i].supported = false;
    for (i = 0 ; i < ARRAY_SIZE(established_timing_db); i++)
        established_timing_db[i].supported = false;

    /* Block 0: established timing */
    pr_info("established timing: {%02x, %02x, %02x}\n",
            edid_buf[35], edid_buf[36], edid_buf[37]);

    v1 = edid_buf[35] | edid_buf[36] << 8;
    if (edid_buf[37] & 0x80)
        v1 |= 0x00010000;

    for (i = 0 ; i < 17; i++ )  // 17 bits defined in established timing
        established_timing_db[i].supported = ((v1 >>= 1) & 1) ;

    /* standard timing identification */
    for (i = 0; i < 8; i++) {
        width = (edid_buf[38 + (i * 2)] * 8) + 248;
        v1 = edid_buf[38 + (i * 2) + 1];
        switch (v1 >> 6) {
        case 0: height = width * 10 / 16; aspect = ASPECT(16, 10); break;
        case 1: height = width * 3 / 4; aspect = ASPECT(4, 3); break;
        case 2: height = width * 4 / 5; aspect = ASPECT(5, 4); break;
        case 3: height = width * 9 / 16; aspect = ASPECT(16, 9); break;
        }
        standard_timing_db[i].width = width;
        standard_timing_db[i].height = height;
        standard_timing_db[i].aspect = aspect;
        standard_timing_db[i].refresh_rate = (v1 & 0x3F) + 60;
        standard_timing_db[i].supported = true;
    }

    for (extension = 0; extension < extensions; extension++)
    {
        unsigned baseOffset = (extension + 1) * 0x80;
        unsigned dtdStart = 0;
        unsigned nativeFormats = 0;
        unsigned dbcOffset;

        EDID_DBG("Extension %d\n", extension +1);
        if (edid_buf[baseOffset] != 0x02)
        {
            EDID_DBG("  Extension is not CEA EDID format. Skipping.\n");
            continue;
        }

        if (edid_buf[baseOffset+1] < 0x03)
        {
            EDID_DBG("  CEA EDID Extension is below version 3. Skipping.\n");
            continue;
        }

        dtdStart = edid_buf[baseOffset+2];

        edid_info->under_scan  = edid_buf[baseOffset+3] & EDID_BIT(7);
        edid_info->basic_audio = edid_buf[baseOffset+3] & EDID_BIT(6);
        edid_info->ycbcr_4_4_4 = edid_buf[baseOffset+3] & EDID_BIT(5);
        edid_info->ycbcr_4_2_2 = edid_buf[baseOffset+3] & EDID_BIT(4);

        nativeFormats = edid_buf[baseOffset+3] & 0x04;
        dbcOffset = 4;

        while (dbcOffset < dtdStart)
        {
            unsigned blockType = edid_buf[baseOffset + dbcOffset] >> 5;
            unsigned blockLen = edid_buf[baseOffset + dbcOffset] & 0x1f;
            unsigned byte;

            EDID_DBG("  Block Type: %d  Block Length: %d\n", blockType, blockLen);

            // Check for an audio data block
            if (blockType == AUDIO_D_BLOCK)
            {
                edid_info->basic_audio = true;
                EDID_DBG("  CEA3 Audio Data Block found.\n");
                dbcOffset += blockLen + 1;
                continue;
            }

            // Check for a vendor data block
            if (blockType == VENDOR_SPEC_D_BLOCK)
            {
                EDID_DBG("  CEA3 Vendor Block found.\n");
                // This may be an HDMI vendor block, and if so, we need to parse it
                if (edid_buf[baseOffset + dbcOffset + 1] == 0x03 && 
                    edid_buf[baseOffset + dbcOffset + 2] == 0x0C && 
                    edid_buf[baseOffset + dbcOffset + 3] == 0x00 )
                {
                    // We found the HDMI block
                    EDID_DBG("  CEA3 HDMI Vendor Block found.\n");
                    hdmi->edid_info.hdmi_sink = true;
                }
                dbcOffset += blockLen + 1;
                continue;
            }
            if (blockType != VIDEO_D_BLOCK)
            {
                dbcOffset += blockLen + 1;
                continue;
            }

            // The block will be an array of indexes
            for (byte = 1; byte < blockLen; byte++)
            {
                index = edid_buf[baseOffset + dbcOffset + byte] & 0x7f;

                if (index > 63)
                {
                    EDID_DBG("Invalid index in EDID Video block. Ignoring.\n");
                }
                else
                {
                    additional_timing_db[index-1].supported = true;
                    EDID_DBG("%s\n", additional_timing_db[index-1].descrption);
                }
            }

            dbcOffset += blockLen + 1;
        }
    }

    // As a cheat, we're replacing the existing timings with our own "custom"
    // definition of these bytes.
    edid_buf[35] = 0;
    edid_buf[36] = 0;
    edid_buf[37] = 0;

    /* edid_buf[37] bit4: 480p, bit5: 576p, bit6: 720p */
    if (additional_timing_db[CEA_MODE_720X480P_60HZ_4_3].supported ||
        additional_timing_db[CEA_MODE_720X480P_60HZ_16_9].supported) {
        EDID_DBG("decide to support 480P\n");
        edid_buf[37] |= (1<<4);
    }

    if (additional_timing_db[CEA_MODE_720X576P_50HZ_4_3].supported ||
        additional_timing_db[CEA_MODE_720X576P_50HZ_16_9].supported) {
        EDID_DBG("decide to support 576P\n");
        edid_buf[37] |= (1<<5);
    }

    if (additional_timing_db[CEA_MODE_1280X720P_60HZ_16_9].supported) {
        EDID_DBG("decide to support 720P\n");
        edid_buf[37] |= (1<<6);
    }

    if (established_timing_db[ESTABLISHED_MODE_800X600_60HZ].supported) {
        EDID_DBG("decide to support 800x600\n");
        edid_buf[36] |= (1<<6);
    }

    if (established_timing_db[ESTABLISHED_MODE_640X480_60HZ].supported) {
        EDID_DBG("decide to support 640x480\n");
        edid_buf[35] |= (1<<5);
    }
    edid_fixup_compatibility_list(hdmi);

    return ret;
}