blob: 72ca7d5c77811eb5fd8c25b887ed02669f0551d7 [file] [log] [blame]
// Copyright 2017 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "edid.h"
#include <lib/edid/edid.h>
#include <string.h>
namespace hi_display {
zx_status_t HiEdid::EdidGetNumDtd(const uint8_t* edid_buf_, uint8_t* num_dtd) {
const uint8_t* start_ext;
const uint8_t* start_dtd;
*num_dtd = 0;
edid::BaseEdid* EdidBuf = (edid::BaseEdid*)edid_buf_;
if (!EdidBuf->num_extensions) {
return ZX_OK;
}
// It has extension. Read from start of DTD until you hit 00 00
start_ext = &edid_buf_[128];
if (start_ext[0] != 0x2) {
zxlogf(ERROR, "%s: Unknown tag! %d\n", __FUNCTION__, start_ext[0]);
return ZX_ERR_WRONG_TYPE;
}
if (start_ext[2] == 0) {
zxlogf(ERROR, "%s: Invalid DTD pointer! 0x%x\n", __FUNCTION__, start_ext[2]);
return ZX_ERR_WRONG_TYPE;
}
int i = 0;
start_dtd = &start_ext[0] + start_ext[2];
while (start_dtd[i] != 0x0 && start_dtd[i + 1] != 0x0) {
++(*num_dtd);
i += 18;
}
return ZX_OK;
}
void HiEdid::EdidDumpDispTiming(const DisplayTiming* d) {
zxlogf(INFO, "%s\n", __FUNCTION__);
zxlogf(INFO, "pixel_clk = 0x%x\n", d->pixel_clk);
zxlogf(INFO, "HActive = 0x%x\n", d->HActive);
zxlogf(INFO, "HBlanking = 0x%x\n", d->HBlanking);
zxlogf(INFO, "VActive = 0x%x\n", d->VActive);
zxlogf(INFO, "VBlanking = 0x%x\n", d->VBlanking);
zxlogf(INFO, "HSyncOffset = 0x%x\n", d->HSyncOffset);
zxlogf(INFO, "HSyncPulseWidth = 0x%x\n", d->HSyncPulseWidth);
zxlogf(INFO, "VSyncOffset = 0x%x\n", d->VSyncOffset);
zxlogf(INFO, "VSyncPulseWidth = 0x%x\n", d->VSyncPulseWidth);
zxlogf(INFO, "HImageSize = 0x%x\n", d->HImageSize);
zxlogf(INFO, "VImageSize = 0x%x\n", d->VImageSize);
zxlogf(INFO, "HBorder = 0x%x\n", d->HBorder);
zxlogf(INFO, "VBorder = 0x%x\n", d->VBorder);
zxlogf(INFO, "Flags = 0x%x\n", d->Flags);
}
zx_status_t HiEdid::EdidParseStdDisplayTiming(const uint8_t* edid_buf_, DetailedTiming* raw,
DisplayTiming* d) {
const uint8_t* start_dtd;
uint8_t* s_r_dtd = (uint8_t*)raw;
start_dtd = &edid_buf_[0x36];
// populate raw structure first
memcpy(s_r_dtd, start_dtd, 18);
d->pixel_clk = static_cast<uint16_t>(raw->raw_pixel_clk[1] << 8 | raw->raw_pixel_clk[0]);
d->HActive = static_cast<uint16_t>((((raw->raw_Hact_HBlank & 0xf0) >> 4) << 8) |
raw->raw_Hact);
d->HBlanking = static_cast<uint16_t>(((raw->raw_Hact_HBlank & 0x0f) << 8) |
raw->raw_HBlank);
d->VActive = static_cast<uint16_t>((((raw->raw_Vact_VBlank & 0xf0) >> 4) << 8) |
raw->raw_Vact);
d->VBlanking = static_cast<uint16_t>(((raw->raw_Vact_VBlank & 0x0f) << 8) |
raw->raw_VBlank);
d->HSyncOffset = static_cast<uint16_t>((((raw->raw_HSync_VSync_OFF_PW & 0xc0) >> 6) << 8) |
raw->raw_HSyncOff);
d->HSyncPulseWidth = static_cast<uint16_t>((((raw->raw_HSync_VSync_OFF_PW & 0x30) >> 4) << 8) |
raw->raw_HSyncPW);
d->HImageSize = static_cast<uint16_t>((((raw->raw_H_V_ImageSize & 0xf0) >> 4) << 8) |
raw->raw_HImageSize);
d->VImageSize = static_cast<uint16_t>(((raw->raw_H_V_ImageSize & 0x0f) << 8) |
raw->raw_VImageSize);
d->VSyncOffset = static_cast<uint8_t>((((raw->raw_HSync_VSync_OFF_PW & 0x0c) >> 2) << 4) |
(raw->raw_VSyncOff_VSyncPW & 0xf0) >> 4);
d->VSyncPulseWidth = static_cast<uint8_t>(((raw->raw_HSync_VSync_OFF_PW & 0x03) << 4) |
(raw->raw_VSyncOff_VSyncPW & 0x0f));
d->HBorder = raw->raw_HBorder;
d->VBorder = raw->raw_VBorder;
d->Flags = raw->raw_Flags;
return ZX_OK;
}
zx_status_t HiEdid::EdidParseDisplayTiming(const uint8_t* edid_buf_, DetailedTiming* raw,
DisplayTiming* d, uint8_t num_dtd) {
const uint8_t* start_ext;
const uint8_t* start_dtd;
uint8_t* s_r_dtd = (uint8_t*)raw;
edid::BaseEdid* EdidBuf = (edid::BaseEdid*)edid_buf_;
if (!EdidBuf->num_extensions) {
return ZX_ERR_INVALID_ARGS;
}
// It has extension. Read from start of DTD until you hit 00 00
start_ext = &edid_buf_[128];
if (start_ext[0] != 0x2) {
zxlogf(ERROR, "%s: Unknown tag! %d\n", __FUNCTION__, start_ext[0]);
return ZX_ERR_WRONG_TYPE;
}
if (start_ext[2] == 0) {
zxlogf(ERROR, "%s: Invalid DTD pointer! 0x%x\n", __FUNCTION__, start_ext[2]);
return ZX_ERR_WRONG_TYPE;
}
start_dtd = &start_ext[0] + start_ext[2];
for (int i = 0; i < num_dtd; i++) {
// populate raw structure first
memcpy(s_r_dtd, start_dtd, 18);
d[i].pixel_clk = static_cast<uint16_t>(raw[i].raw_pixel_clk[1] << 8 |
raw[i].raw_pixel_clk[0]);
d[i].HActive = static_cast<uint16_t>((((raw[i].raw_Hact_HBlank & 0xf0) >> 4) << 8) |
raw[i].raw_Hact);
d[i].HBlanking = static_cast<uint16_t>(((raw[i].raw_Hact_HBlank & 0x0f) << 8) |
raw[i].raw_HBlank);
d[i].VActive = static_cast<uint16_t>((((raw[i].raw_Vact_VBlank & 0xf0) >> 4) << 8) |
raw[i].raw_Vact);
d[i].VBlanking = static_cast<uint16_t>(((raw[i].raw_Vact_VBlank & 0x0f) << 8) |
raw[i].raw_VBlank);
d[i].HImageSize = static_cast<uint16_t>((((raw[i].raw_H_V_ImageSize & 0xf0) >> 4) << 8) |
raw[i].raw_HImageSize);
d[i].VImageSize = static_cast<uint16_t>(((raw[i].raw_H_V_ImageSize & 0x0f) << 8) |
raw[i].raw_VImageSize);
d[i].HSyncPulseWidth =
static_cast<uint16_t>((((raw[i].raw_HSync_VSync_OFF_PW & 0x30) >> 4) << 8) |
raw[i].raw_HSyncPW);
d[i].HSyncOffset =
static_cast<uint16_t>((((raw[i].raw_HSync_VSync_OFF_PW & 0xc0) >> 6) << 8) |
raw[i].raw_HSyncOff);
d[i].VSyncOffset =
static_cast<uint8_t>((((raw[i].raw_HSync_VSync_OFF_PW & 0x0c) >> 2) << 4) |
(raw[i].raw_VSyncOff_VSyncPW & 0xf0) >> 4);
d[i].VSyncPulseWidth = static_cast<uint8_t>(((raw[i].raw_HSync_VSync_OFF_PW & 0x03) << 4) |
(raw[i].raw_VSyncOff_VSyncPW & 0x0f));
d[i].HBorder = raw[i].raw_HBorder;
d[i].VBorder = raw[i].raw_VBorder;
d[i].Flags = raw[i].raw_Flags;
s_r_dtd += 18;
start_dtd += 18;
}
return ZX_OK;
}
} // namespace hi_display