first and last commit

This commit is contained in:
Chris Nutter committed 2023-07-08 13:03:17 -07:00
commit 1bf4efd552
2612 files changed
+636500

No files matched your search

+691
View File
@@ -0,0 +1,691 @@
/*
* Copyright (C) 2010, 2015 Apple Inc. All rights reserved.
*
* This document is the property of Apple Inc.
* It is considered confidential and proprietary.
*
* This document may not be reproduced or transmitted in any form,
* in whole or in part, without the express written permission of
* Apple Inc.
*/
#include <debug.h>
#include <drivers/displayport/displayport.h>
#include <drivers/displayport.h>
#include <sys/task.h>
#if WITH_HW_MCU
#include <drivers/process_edid.h>
#endif
#include "dpcd.h"
/////////////////////////////////////////
////////// debug support
#define DP_DEBUG_MASK ( \
DP_DEBUG_INIT | \
DP_DEBUG_ERROR | \
DP_DEBUG_INFO | \
DP_DEBUG_TRAINING | \
0)
#undef DP_DEBUG_MASK
#define DP_DEBUG_MASK (DP_DEBUG_INIT | DP_DEBUG_ERROR)
#define DP_DEBUG_INIT (1<<16) // initialisation
#define DP_DEBUG_ERROR (1<<17) // errors
#define DP_DEBUG_INFO (1<<18) // info
#define DP_DEBUG_TRAINING (1<<19) // link training
#define DP_DEBUG_ALWAYS (1<<31) // unconditional output
#define debug(_fac, _fmt, _args...) \
do { \
if ((DP_DEBUG_ ## _fac) & (DP_DEBUG_MASK | DP_DEBUG_ALWAYS)) \
dprintf(DEBUG_CRITICAL, "DPC: %s, %d: " _fmt, __FUNCTION__, __LINE__, ##_args); \
} while(0)
/////////////////////////////////////////
////////// consts, macros
#define kMaxRetry 5
#define kClockRecoveryDelay 100
#define kEQDelay 400
#define kMaxClockRecoveryIterations 100
#define require(assertion, exception_label) \
do { \
if (__builtin_expect(!(assertion), 0)) \
{ \
goto exception_label; \
} \
} while (0)
#define require_action(assertion, exception_label, action) \
do { \
if (__builtin_expect(!(assertion), 0)) \
{ \
{ \
action; \
} \
goto exception_label; \
} \
} while (0)
#define require_noerr(error_code, exception_label) \
do { \
if (__builtin_expect(0 != (error_code), 0)) \
{ \
goto exception_label; \
} \
} while (0)
#define require_noerr_action(error_code, exception_label, action) \
do { \
if (__builtin_expect(0 != (error_code), 0)) \
{ \
{ \
action; \
} \
goto exception_label; \
} \
} while (0)
/////////////////////////////////////////
////////// typedefs, enums, structs
enum {
kLinkTrainingStateIdle,
kLinkTrainingStateStart,
kLinkTrainingStateClockRecovery,
kLinkTrainingStateEQTraining
};
/////////////////////////////////////////
////////// local variables
static u_int8_t dp_link_clock_recovery_retry[kDPMaxLanes];
static bool dp_link_voltage_swing_max[kDPMaxLanes];
static bool dp_link_eq_max[kDPMaxLanes];
static u_int8_t dp_link_eq_retry;
static u_int32_t dp_link_clock_recovery_iterations;
static u_int8_t dp_link_eq_iterations;
static struct video_link_data dp_video_data;
static int eq_pattern = kDPTrainingPattern2;
static dp_t dp_link_config = {
.mode = kDPControllerMode_Master,
.type = kDPControllerType_DP,
.min_link_rate = 0x6,
.max_link_rate = 0x6,
.lanes = 4,
.ssc = 0,
.alpm = 0,
.vrr_enable = 0,
.vrr_on = 0,
};
/////////////////////////////////////////
////////// local functions declaration
static int run_link_training_state_machine(struct dp_link_train_data *data);
static int process_link_state_start(struct dp_link_train_data *data, u_int32_t *state);
static int process_link_state_clock_recovery(struct dp_link_train_data *data, u_int32_t *state);
static int process_link_state_eq_training(struct dp_link_train_data *data, u_int32_t *state);
static int process_link_state_eq_training_internal(struct dp_link_train_data *data, uint32_t lane, bool *done);
static int process_link_state_clock_recovery_internal(struct dp_link_train_data * data, uint32_t lane, bool *p_done);
/////////////////////////////////////////
////////// DisplayPort global functions
int displayport_init(dp_t *dp)
{
// defaults to External display, and Master mode
if ( dp_controller_start(dp) != 0 )
return -1;
return 0;
}
int displayport_init_with_timing_info(struct display_timing *timing_info)
{
memcpy(&dp_link_config, timing_info->display_config, sizeof(dp_t));
displayport_set_timings(timing_info);
if ( dp_controller_start(&dp_link_config) != 0 )
return -1;
return 0;
}
int displayport_set_timings(struct display_timing *timing_info)
{
u_int8_t mode;
memcpy(&dp_link_config, timing_info->display_config, sizeof(dp_t));
mode = dp_link_config.mode;
bzero(&dp_video_data, sizeof(struct video_link_data));
dp_video_data.mirror_mode = (mode == kDPControllerMode_Slave) ? true : false;
dp_video_data.test_mode = 0;
dp_video_data.color.depth = 8;
dp_video_data.color.space = kDisplayColorSpacesRGB;
dp_video_data.color.range = kDisplayColorDynamicRangeVESA;
dp_video_data.color.coefficient = kDisplayColorCoefficientITU601;
dp_video_data.timing.axis[0].total = timing_info->h_active + timing_info->h_back_porch +
timing_info->h_front_porch + timing_info->h_pulse_width;
dp_video_data.timing.axis[0].active = timing_info->h_active;
dp_video_data.timing.axis[0].sync_width = timing_info->h_pulse_width;
dp_video_data.timing.axis[0].back_porch = timing_info->h_back_porch;
dp_video_data.timing.axis[0].front_porch = timing_info->h_front_porch;
dp_video_data.timing.axis[0].sync_rate = 0;
// Hsync polarity: 0->negative, 1->positive.
dp_video_data.timing.axis[0].sync_polarity = timing_info->neg_hsync ? 0 : 1;
dp_video_data.timing.axis[1].total = timing_info->v_active + timing_info->v_back_porch +
timing_info->v_front_porch + timing_info->v_pulse_width;
dp_video_data.timing.axis[1].active = timing_info->v_active;
dp_video_data.timing.axis[1].sync_width = timing_info->v_pulse_width;
dp_video_data.timing.axis[1].back_porch = timing_info->v_back_porch;
dp_video_data.timing.axis[1].front_porch = timing_info->v_front_porch;
dp_video_data.timing.axis[1].sync_rate = (60 << 16);
// Vsync polarity: 0->negative, 1->positive.
dp_video_data.timing.axis[1].sync_polarity = timing_info->neg_vsync ? 0 : 1;
debug(INFO, "vTotal:%d hTotal:%d\n", dp_video_data.timing.axis[1].total, dp_video_data.timing.axis[0].total);
#if WITH_HW_MCU
// Restrict EDID choices to timings matching these, otherwise the
// framebuffer dimensions will mismatch.
restrict_edid(dp_video_data.timing.axis[0].active,
dp_video_data.timing.axis[1].active);
#endif
return 0;
}
void displayport_quiesce()
{
dp_controller_stop();
}
int displayport_start_video(void)
{
#if WITH_HW_MCU && WITH_HW_HOOVER
int downstream_type = get_edid_downstream_type();
if (downstream_type == kDPDownstreamTypeDVI) {
uint8_t data;
dp_controller_read_bytes_dpcd(DPCD_ADDR_HDMI_DVI_MODE_SELECT, &data, sizeof(data));
data |= DPCD_ADDR_HDMI_DVI_MODE_SELECT_DVI;
debug(INFO, "Reprogramming Hoover to be in DVI mode: data 0x%x\n", data);
dp_controller_write_bytes_dpcd(DPCD_ADDR_HDMI_DVI_MODE_SELECT, &data, sizeof(data));
}
#endif
return dp_controller_start_video(&dp_video_data);
}
int displayport_enable_alpm(bool enable)
{
return dp_controller_enable_alpm(enable, &dp_video_data);
}
#if WITH_HW_DISPLAY_EDP
int displayport_get_raw_panel_id(u_int8_t *raw_panel_id)
{
//caller is responsible for waiting for HPD
return dp_device_get_raw_panel_id(raw_panel_id);
}
#endif // WITH_HW_DISPLAY_EDP
bool displayport_video_configured()
{
return dp_controller_video_configured();
}
/////////////////////////////////////////
////////// controller global functions
int dp_controller_train_link(struct dp_link_train_data *data)
{
int ret;
u_int32_t lc;
u_int32_t lr;
u_int32_t retry = 0;
ret = -1;
lc = data->lane_count;
lr = data->link_rate;
do {
data->lane_count = __min((dp_controller_get_max_lane_count()), lc);
data->link_rate = __min((dp_controller_get_max_link_rate()), lr);
do {
// check if the device has sufficient bandwidth
if ( data->lane_count < dp_controller_get_min_lane_count() ) {
ret = -1;
break;
}
ret = run_link_training_state_machine(data);
if ( ret != 0 ) {
if ( !data->fast ) {
data->link_rate = __min((dp_controller_get_max_link_rate()), lr);
data->lane_count = data->lane_count/2;
} else {
data->fast = false;
}
}
} while ( ret != 0 );
} while ( ret != 0 && ++retry < 5 );
return 0;
}
/////////////////////////////////////////
////////// controller local functions
static int run_link_training_state_machine(struct dp_link_train_data *data)
{
u_int32_t state = kLinkTrainingStateStart;
int ret;
debug(TRAINING, "Preparing to establish new link\n");
// establish link training
do {
switch(state) {
case kLinkTrainingStateStart:
ret = process_link_state_start(data, &state);
break;
case kLinkTrainingStateClockRecovery:
ret = process_link_state_clock_recovery(data, &state);
break;
case kLinkTrainingStateEQTraining:
ret = process_link_state_eq_training(data, &state);
break;
default:
break;
}
debug(TRAINING, "Performing Link training state=%d result=%d\n", state, ret);
if ( ret != 0 )
state = kLinkTrainingStateIdle;
} while ( state != kLinkTrainingStateIdle );
debug(TRAINING, "Link training result=%d\n", ret);
return ret;
}
static int process_link_state_start(struct dp_link_train_data *data, u_int32_t *state)
{
int ret;
u_int32_t index;
#if DISPLAYPORT_VERSION > 2
eq_pattern = dp_device_get_supports_training_pattern3() ? kDPTrainingPattern3 : kDPTrainingPattern2;
#endif
ret = -1;
debug(TRAINING, "Begining START phase of link traing. Initial lanecount=%d linkRate=%u bps\n",
data->lane_count, data->link_rate);
bzero(dp_link_clock_recovery_retry, sizeof(dp_link_clock_recovery_retry));
bzero(dp_link_voltage_swing_max, sizeof(dp_link_voltage_swing_max));
bzero(dp_link_eq_max, sizeof(dp_link_eq_max));
dp_link_eq_retry = 0;
dp_link_clock_recovery_iterations = 0;
dp_link_eq_iterations = 0;
// Set link rate and count as you want to establish
// set device
ret = dp_device_set_enhanced_mode(data->enhanced_mode);
require_noerr_action(ret, exit, debug(ERROR, "Failed to set device enhanced mode\n"));
ret = dp_device_set_ASSR(data->assr);
require_noerr_action(ret, exit, debug(ERROR, "Failed to set device assr\n"));
ret = dp_device_set_downspread(data->downspread);
require_noerr_action(ret, exit, debug(ERROR, "Failed to set device downspread\n"));
ret = dp_device_set_link_rate(data->link_rate);
require_noerr_action(ret, exit, debug(ERROR, "Failed to set device link rate\n"));
ret = dp_device_set_lane_count(data->lane_count);
require_noerr_action(ret, exit, debug(ERROR, "Failed to set device lane count\n"));
// set controller
ret = dp_controller_set_link_rate(data->link_rate);
require_noerr_action(ret, exit, debug(ERROR, "Failed to set controller link rate\n"));
ret = dp_controller_set_enhanced_mode(data->enhanced_mode);
require_noerr_action(ret, exit, debug(ERROR, "Failed to set controller enhanced mode\n"));
ret = dp_controller_set_ASSR(data->assr);
require_noerr_action(ret, exit, debug(ERROR, "Failed to set controller assr\n"));
ret = dp_controller_set_downspread(data->downspread);
require_noerr_action(ret, exit, debug(ERROR, "Failed to set controller downspread\n"));
ret = dp_controller_set_lane_count(data->lane_count);
require_noerr_action(ret, exit, debug(ERROR, "Failed to set controller lane count\n"));
for ( index=0; index<data->lane_count; index++) {
ret = dp_controller_set_adjustment_levels(index, kDPVoltageLevelMin, kDPEQLevelMin, NULL, NULL);
if ( ret != 0 ) {
debug(ERROR, "Failed to set controller adjustment\n");
goto exit;
}
ret = dp_device_set_adjustment_levels(index, kDPVoltageLevelMin, kDPEQLevelMin, false, false);
if ( ret != 0 ) {
debug(ERROR, "Failed to set device adjustment\n");
goto exit;
}
}
require_noerr_action(ret, exit, debug(ERROR, "Failed to adjustment levels\n"));
ret = dp_controller_set_training_pattern(kDPTrainingPattern1, false);
require_noerr_action(ret, exit, debug(ERROR, "Failed to set controller training pattern\n"));
ret = dp_device_set_training_pattern(kDPTrainingPattern1, false);
require_noerr_action(ret, exit, debug(ERROR, "Failed to set device training pattern\n"));
require(!data->fast, train_fast);
*state = kLinkTrainingStateClockRecovery;
return ret;
train_fast:
debug(TRAINING, "Skipping to fast link training\n");
task_sleep(1 * 1000);
ret = dp_controller_set_training_pattern(eq_pattern, false);
require_noerr_action(ret, exit, debug(ERROR, "Failed to set controller training pattern\n"));
ret = dp_device_set_training_pattern(eq_pattern, false);
require_noerr_action(ret, exit, debug(ERROR, "Failed to set device training pattern\n"));
task_sleep(1 * 1000);
ret = dp_controller_set_training_pattern(kDPTrainingPatternNone, true);
require_noerr_action(ret, exit, debug(ERROR, "Failed to set controller training pattern\n"));
ret = dp_device_set_training_pattern(kDPTrainingPatternNone, true);
require_noerr_action(ret, exit, debug(ERROR, "Failed to set device training pattern\n"));
exit:
*state = kLinkTrainingStateIdle;
return ret;
}
static int process_link_state_clock_recovery(struct dp_link_train_data *data, u_int32_t *state)
{
uint32_t lane;
uint32_t alignment_status;
bool done = true;
bool succeed = true;
int ret = 0;
spin(kClockRecoveryDelay);
ret = dp_device_get_alignment_status_mask(&alignment_status);
require_noerr(ret, exit);
for ( lane=0; lane<data->lane_count; lane++ ) {
ret = process_link_state_clock_recovery_internal(data, lane, &done);
succeed &= ( ret == 0 );
}
if ( !done ) {
ret = dp_device_set_training_pattern(kDPTrainingPattern1, false);
require_noerr(ret, exit);
}
if ( !succeed ) {
debug(TRAINING, "loop failed: linkRate=%u bps\n", data->link_rate);
// traing pattern : Set to Normal
ret = dp_controller_set_training_pattern(kDPTrainingPatternNone, true);
require_noerr(ret, exit);
ret = dp_device_set_training_pattern(kDPTrainingPatternNone, true);
require_noerr(ret, exit);
// reduce bit rate
if ( (data->link_rate > dp_controller_get_min_link_rate()) && (data->link_rate == kLinkRate270Gbps) ) {
data->link_rate = kLinkRate162Gbps;
debug(TRAINING, "retry @ linkRate=%d\n", data->link_rate);
*state = kLinkTrainingStateStart;
}
// already in reduced bit-rate
else {
ret = -1;
}
}
else if ( done ) {
// set training pattern 2 for EQ
ret = dp_controller_set_training_pattern(eq_pattern, false);
require_noerr(ret, exit);
// set the training pattern
ret = dp_device_set_training_pattern(eq_pattern, false);
require_noerr(ret, exit);
*state = kLinkTrainingStateEQTraining;
}
exit:
if (++dp_link_clock_recovery_iterations > kMaxClockRecoveryIterations) {
debug(TRAINING, "Max clock recovery iterations exceeded\n");
ret = -1;
}
return ret;
}
static int process_link_state_clock_recovery_internal(struct dp_link_train_data * data, uint32_t lane,
bool *p_done)
{
int ret = 0;
bool done = false;
uint32_t lane_status = 0;
uint32_t eq = kDPEQLevelMin;
uint32_t voltage_swing = kDPVoltageLevelMin;
uint32_t phy_eq;
uint32_t phy_voltage_swing;
// might as well read the values for lane
ret = dp_device_get_lane_status_mask(lane, &lane_status);
require_noerr(ret, exit);
debug(TRAINING, "Reading lane status: lane=%d status=0x%08x\n",lane, lane_status);
require_action(!(lane_status & kDPLaneStatusFlagClockRecoveryDone), exit, done = true);
ret = dp_device_get_requested_adjustment_levels(lane, &voltage_swing, &eq);
require_noerr(ret, exit);
ret = dp_controller_get_adjustment_levels(lane, &phy_voltage_swing, &phy_eq);
require_noerr(ret, exit);
debug(TRAINING, "Reading lane adjust request: Lane%d: voltage=%d eq=%d\n",lane, voltage_swing, eq);
debug(TRAINING, "Current phy lane properties: Lane%d: voltage=%d eq=%d\n",lane, phy_voltage_swing, phy_eq);
data->lane[lane].voltage = voltage_swing;
data->lane[lane].eq = eq;
// lane same voltage count
if (phy_voltage_swing == voltage_swing)
dp_link_clock_recovery_retry[lane]++;
else
dp_link_clock_recovery_retry[lane] = 0;
debug(TRAINING, "_linkClockRecoveryRetry[%d]=%d\n", lane, dp_link_clock_recovery_retry[lane]);
require_action((dp_link_clock_recovery_retry[lane] < kMaxRetry) && !dp_link_voltage_swing_max[lane],
exit, ret=-1);
// increase voltage swing as requested,write an updated value
debug(TRAINING, "Setting lane adjust request: Lane%d: voltage=%d eq=%d\n",lane, voltage_swing, eq);
// set voltage drive ONLY on the PHY
ret = dp_controller_set_adjustment_levels(lane, voltage_swing, eq, &dp_link_voltage_swing_max[lane],
&dp_link_eq_max[lane]);
require_noerr(ret, exit);
// set voltage drive and EQ on the SINK
ret = dp_device_set_adjustment_levels(lane, voltage_swing, eq, dp_link_voltage_swing_max[lane],
dp_link_eq_max[lane]);
exit:
*p_done &= done;
return ret;
}
static int process_link_state_eq_training(struct dp_link_train_data *data, u_int32_t *state)
{
uint32_t lane;
uint32_t alignment_status;
bool done = true;
bool succeed = true;
bool abort = false;
bool clear = false;
bool reduce = false;
bool restart = false;
int ret = 0;
debug(TRAINING, "Begining EQ phase of link traing\n");
spin(kEQDelay);
dp_link_eq_retry++;
ret = dp_device_get_alignment_status_mask(&alignment_status);
require_noerr(ret, exit);
debug(TRAINING, "alignment_status=0x%08x\n", alignment_status);
// process the eq state for each lane
for ( lane=0; lane<data->lane_count; lane++ ) {
ret = process_link_state_eq_training_internal(data, lane, &done);
if ( ret == 0 )
continue;
abort = (ret == -1);
succeed = false;
break;
}
require(!abort, exit);
done &= (alignment_status & kDPAlignmentStatusFlagsDone) != 0;
// reapply the training pattern
// this does a bulk write
if ( !done ) {
ret = dp_device_set_training_pattern(eq_pattern, false);
require_noerr(ret, exit);
}
if ( done ) {
debug(TRAINING, "Link trainking success @ %d lanes and %u Gbps\n", data->lane_count,
data->link_rate);
clear = true;
*state = kLinkTrainingStateIdle;
} else if ( !abort && (!succeed || dp_link_eq_retry > kMaxRetry) ) {
reduce = true;
}
if ( reduce ) {
debug(TRAINING, "loop failed: laneCount=%d linkRate=%u Gbps\n", data->lane_count, data->link_rate);
clear = true;
// reduce bit rate and restart
if ( (data->link_rate > dp_controller_get_min_link_rate()) && (data->link_rate == kLinkRate270Gbps) ) {
data->link_rate = kLinkRate162Gbps;
debug(TRAINING, "retry @ linkRate=%d\n", data->link_rate);
restart = true;
}
// already in reduced bit-rate
else {
ret = -1;
}
}
if ( restart ) {
*state = kLinkTrainingStateStart;
}
if ( clear ) {
// traing pattern : Set to Normal
dp_controller_set_training_pattern(kDPTrainingPatternNone, true);
dp_device_set_training_pattern(kDPTrainingPatternNone, true);
}
exit:
return ret;
}
static int process_link_state_eq_training_internal(struct dp_link_train_data *data, uint32_t lane, bool *p_done)
{
int ret = 0;
bool done = false;
uint32_t lane_status = 0;
uint32_t eq;
uint32_t voltage_swing;
uint32_t phy_eq;
uint32_t phy_voltage_swing;
// might as well read the values for lane
ret = dp_device_get_lane_status_mask(lane, &lane_status);
require_noerr(ret, exit);
debug(TRAINING, "Reading lane status: lane=%d lane_status=0x%08x\n",lane, lane_status);
require_action(lane_status & kDPLaneStatusFlagClockRecoveryDone, exit, ret = -1);
done = (lane_status & (kDPLaneStatusFlagsEQDone|kDPLaneStatusFlagsSymbolLocked))==(kDPLaneStatusFlagsEQDone|kDPLaneStatusFlagsSymbolLocked);
require(!done, exit);
ret = dp_device_get_requested_adjustment_levels(lane, &voltage_swing, &eq);
require_noerr(ret, exit);
ret = dp_controller_get_adjustment_levels(lane, &phy_voltage_swing, &phy_eq);
require_noerr(ret, exit);
debug(TRAINING, "Reading lane adjust request: Lane%d: voltage=%d eq=%d\n",lane, voltage_swing, eq);
debug(TRAINING, "Current phy lane properties: Lane%d: voltage=%d eq=%d\n",lane, phy_voltage_swing, phy_eq);
data->lane[lane].voltage = voltage_swing;
data->lane[lane].eq = eq;
// set voltage drive and EQ on the PHY
ret = dp_controller_set_adjustment_levels(lane, voltage_swing, eq,
&dp_link_voltage_swing_max[lane], &dp_link_eq_max[lane]);
require_noerr(ret, exit);
// set voltage drive and EQ on the SINK
ret = dp_device_set_adjustment_levels(lane, voltage_swing, eq,
dp_link_voltage_swing_max[lane], dp_link_eq_max[lane]);
exit:
*p_done &= done;
return ret;
}
+163
View File
@@ -0,0 +1,163 @@
/*
* Copyright (C) 2010, 2015 Apple Inc. All rights reserved.
*
* This document is the property of Apple Inc.
* It is considered confidential and proprietary.
*
* This document may not be reproduced or transmitted in any form,
* in whole or in part, without the express written permission of
* Apple Inc.
*/
#include <debug.h>
#include <sys.h>
#include <sys/menu.h>
#include <sys/task.h>
#include <platform/int.h>
#include <platform/soc/hwisr.h>
#include <drivers/display.h>
#include <drivers/displayport/displayport.h>
#include <drivers/displayport.h>
#if defined(WITH_MENU) && WITH_MENU
static struct video_link_data dp_video_data;
int do_dp(int argc, struct cmd_arg *args)
{
if (argc < 2) {
puts("not enough arguments.\n");
goto usage;
}
if (strcmp("start", args[1].str) == 0) {
static struct display_timing timing_list[] =
{
#if SUB_TARGET_J1 || SUB_TARGET_J2 || SUB_TARGET_J2A
{ "ipad3", 0, 252200000, 264, 2048, 5, 150, 5, 1536, 9, 3, 1, 0, 0, 0, 0, 24, DISPLAY_TYPE_EDP, NULL },
#endif
#if WITH_HW_DISPLAY_DISPLAYPORT
{ "720p", 0, 00000000, 243, 1280, 220, 110, 40, 720, 20, 5, 5, 0, 0, 0, 0, 24, DISPLAY_TYPE_DP, NULL },
#endif
};
#if SUB_TARGET_J1 || SUB_TARGET_J2 || SUB_TARGET_J2A
dp_t dp = {
.mode = 0x1,
.type = 0x1,
.min_link_rate = 0x6,
.max_link_rate = 0x6,
.lanes = 0x4,
.ssc = 0x0,
.alpm = 0x0,
.vrr_enable = 0x0,
.vrr_on = 0x0,
};
#elif WITH_HW_DISPLAY_DISPLAYPORT
dp_t dp = {
.mode = 0x1,
.type = 0x1,
.min_link_rate = 0x6,
.max_link_rate = 0x6,
.lanes = 0x2,
.ssc = 0x0,
.alpm = 0x0,
.vrr_enable = 0x0,
};
#else
dp_t dp;
#endif
timing_list[0].display_config = (void *)&dp;
displayport_init(&dp);
bzero(&dp_video_data, sizeof(struct video_link_data));
dp_video_data.mirror_mode = false;
dp_video_data.test_mode = 0;
dp_video_data.color.depth = 8;
dp_video_data.color.space = kDisplayColorSpacesRGB;
dp_video_data.color.range = kDisplayColorDynamicRangeVESA;
dp_video_data.color.coefficient = kDisplayColorCoefficientITU601;
dp_video_data.timing.axis[0].total = timing_list[0].h_active + timing_list[0].h_back_porch + timing_list[0].h_front_porch + timing_list[0].h_pulse_width;
dp_video_data.timing.axis[0].active = timing_list[0].h_active;
dp_video_data.timing.axis[0].sync_width = timing_list[0].h_pulse_width;
dp_video_data.timing.axis[0].back_porch = timing_list[0].h_back_porch;
dp_video_data.timing.axis[0].front_porch = timing_list[0].h_front_porch;
dp_video_data.timing.axis[0].sync_rate = 0;
dp_video_data.timing.axis[0].sync_polarity = 0;
dp_video_data.timing.axis[1].total = timing_list[0].v_active + timing_list[0].v_back_porch + timing_list[0].v_front_porch + timing_list[0].v_pulse_width;
dp_video_data.timing.axis[1].active = timing_list[0].v_active;
dp_video_data.timing.axis[1].sync_width = timing_list[0].v_pulse_width;
dp_video_data.timing.axis[1].back_porch = timing_list[0].v_back_porch;
dp_video_data.timing.axis[1].front_porch = timing_list[0].v_front_porch;
dp_video_data.timing.axis[1].sync_rate = 60 << 16;
dp_video_data.timing.axis[1].sync_polarity = 0;
} else if (strcmp("stop", args[1].str) == 0) {
displayport_quiesce();
} else if (strcmp("video", args[1].str) == 0) {
if (strcmp("logo", args[2].str) == 0) {
dp_video_data.mirror_mode = false;
dp_video_data.test_mode = 0;
dp_controller_start_video(&dp_video_data);
}
if (strcmp("bist", args[2].str) == 0) {
dp_video_data.mirror_mode = false;
dp_video_data.test_mode = 1;
dp_controller_start_video(&dp_video_data);
}
if (strcmp("mirror", args[2].str) == 0) {
dp_video_data.mirror_mode = true;
dp_video_data.test_mode = 0;
dp_controller_start_video(&dp_video_data);
}
} else if (strcmp("dpcd", args[1].str) == 0) {
uint8_t data[16];
int len = args[3].n;
uint32_t intr = 0;
if (len > 16)
len = 16;
printf("dpcd read %d bytes from 0x%x\n", len, args[2].n);
#if WITH_HW_DISPLAY_DISPLAYPORT
intr = INT_DPORT0;
#elif WITH_HW_DISPLAY_EDP
intr = INT_EDP0;
#endif
//cuz AppleTV only defines display in iBoot but declares drivers in iBEC
if (intr) mask_int(intr);
dp_controller_read_bytes_dpcd(args[2].n, data, len);
if (intr) unmask_int(intr);
for (int i=0; i < len; i++) {
printf("0x%02x ", data[i]);
}
printf("\n");
} else {
puts("unrecognized command.\n");
goto usage;
}
return 0;
usage:
printf("%s start\n", args[0].str);
printf("%s video logo\n", args[0].str);
printf("%s video bist\n", args[0].str);
printf("%s video mirror\n", args[0].str);
printf("%s stop\n", args[0].str);
printf("%s dpcd <addr> <len>. Len is max 16 bytes\n", args[0].str);
return -1;
}
MENU_COMMAND_DEVELOPMENT(dp, do_dp, "displayport stuff", NULL);
#endif
+810
View File
@@ -0,0 +1,810 @@
/*
* Copyright (C) 2010-2015 Apple Inc. All rights reserved.
*
* This document is the property of Apple Inc.
* It is considered confidential and proprietary.
*
* This document may not be reproduced or transmitted in any form,
* in whole or in part, without the express written permission of
* Apple Inc.
*/
#include <debug.h>
#include <drivers/displayport/displayport.h>
#include <drivers/displayport.h>
#include <sys/task.h>
#include "dpcd.h"
#if WITH_HW_MCU
#include <drivers/mcu.h>
#include <drivers/process_edid.h>
#endif
/////////////////////////////////////////
////////// debug support
#define DP_DEBUG_MASK ( \
DP_DEBUG_INIT | \
DP_DEBUG_ERROR | \
DP_DEBUG_INFO | \
DP_DEBUG_TRAINING | \
0)
#undef DP_DEBUG_MASK
#define DP_DEBUG_MASK (DP_DEBUG_INIT | DP_DEBUG_ERROR)
#define DP_DEBUG_INIT (1<<16) // initialisation
#define DP_DEBUG_INFO (1<<17) // info
#define DP_DEBUG_TRAINING (1<<18) // link training
#define DP_DEBUG_WAIT (1<<19) // start wait
#define DP_DEBUG_ERROR (1<<20) // error
#define DP_DEBUG_ALWAYS (1<<31) // unconditional output
#define debug(_fac, _fmt, _args...) \
do { \
if ((DP_DEBUG_ ## _fac) & (DP_DEBUG_MASK | DP_DEBUG_ALWAYS)) \
dprintf(DEBUG_CRITICAL, "DPD: %s, %d: " _fmt, __FUNCTION__, __LINE__, ##_args); \
} while(0)
/////////////////////////////////////////
////////// consts
#define kDPDeviceMaxCapabilityBytes 0x0c
#define kDPDeviceMaxDownstreamPorts 16
#define kEDPRawPanelIdReadTimeout (1 * 1000 * 1000)
/////////////////////////////////////////
////////// typedefs, enums, structs
#define require_action(assertion, exception_label, action) \
do { \
if (__builtin_expect(!(assertion), 0)) \
{ \
{ \
action; \
} \
goto exception_label; \
} \
} while (0)
#define require_noerr(error_code, exception_label) \
do { \
if (__builtin_expect(0 != (error_code), 0)) \
{ \
goto exception_label; \
} \
} while (0)
/////////////////////////////////////////
////////// local variables
static uint8_t dp_device_downstream_port_capability_bytes[kDPDeviceMaxDownstreamPorts];
static uint8_t dp_device_capability_bytes[kDPDeviceMaxCapabilityBytes];
static u_int32_t dp_device_voltage_adjustment_level[kDPMaxLanes];
static u_int32_t dp_device_eq_adjustment_level[kDPMaxLanes];
static uint8_t dp_device_adjustment_bytes[5];
static uint8_t dp_device_lane_status_mask[kDPMaxLanes];
static bool alpm_enabled;
#if WITH_HW_DISPLAY_EDP
static u_int8_t dp_device_raw_panel_id[kEDPRawPanelIdLength];
#endif // WITH_HW_DISPLAY_EDP
/////////////////////////////////////////
////////// local functions declaration
static int set_power(bool enable);
static int train_link();
static int enable_alpm(bool enable);
static int cache_capabilities();
static int update_lane_status_mask();
static int update_requested_adjustment_levels();
static int read_raw_panel_id();
static struct task_event dp_device_start_event =
EVENT_STATIC_INIT(dp_device_start_event, false, EVENT_FLAG_AUTO_UNSIGNAL);
static bool dp_device_started;
static bool dp_device_start_error;
static utime_t dp_device_started_time;
static struct task_event dp_device_raw_panel_id_ready_event;
extern utime_t gPowerOnTime;
/////////////////////////////////////////
////////// dp-device global functions
int dp_device_start(bool edp_panel)
{
int ret = -1;
if ( dp_device_started )
return 0;
debug(INIT, "starting\n");
event_init(&dp_device_raw_panel_id_ready_event, EVENT_FLAG_AUTO_UNSIGNAL, false);
if ( set_power(true) != 0 ) {
debug(ERROR, "failed to set power\n");
goto exit;
}
if ( cache_capabilities() != 0 ) {
debug(ERROR, "failed to cache capabilities\n");
goto exit;
}
#if WITH_HW_DISPLAY_EDP
if ( edp_panel ) {
if ( read_raw_panel_id() != 0 ) {
debug(ERROR, "failed to read raw panel id\n");
goto exit;
} else {
debug(INFO, "successfully read panel id: ");
for ( unsigned i=0; i<sizeof(dp_device_raw_panel_id); i++)
debug(INFO, "%02x ", dp_device_raw_panel_id[i]);
debug(INFO, "\n");
}
event_signal(&dp_device_raw_panel_id_ready_event);
}
#endif // WITH_HW_DISPLAY_EDP
if ( train_link() != 0 ) {
debug(ERROR, "failed to train link\n");
goto exit;
}
#if WITH_HW_MCU
uint8_t sink_count;
dp_device_get_sink_count(&sink_count);
if (sink_count == 0) {
debug(ERROR, "sink count is 0\n");
goto exit;
}
// Trained link first, validate timings vs trained bandwidth.
if ( obtain_edid() == 0 ) {
// Enable info frames if HDMI endpoint connected, so
// we get the right color space.
if (get_edid_downstream_type() == kDPDownstreamTypeHDMI) {
debug(ALWAYS, "Sending AVI info frames\n");
#if WITH_HW_BS
(void) mcu_send_info_frames(true);
#endif
}
} else {
// Non-fatal.
debug(ERROR, "Couldn't get EDID\n");
}
#endif
if ( displayport_start_video() != 0 ) {
debug(ERROR, "failed to start video\n");
goto exit;
}
alpm_enabled = false;
if (enable_alpm(true) != 0) {
debug(ERROR, "failed enable alpm\n");
goto exit;
}
if ( dp_device_hdcp_enable(false) != 0 ) {
debug(ERROR, "failed to Disable HDCP\n");
goto exit;
}
debug(ALWAYS, "HDCP Disabled\n");
dp_device_started = true;
ret = 0;
exit:
if (ret != 0) {
dp_device_start_error = true;
debug(ERROR, "error starting device\n");
}
dp_device_started_time = system_time();
event_signal(&dp_device_start_event);
return ret;
}
int dp_device_wait_started(utime_t timeout)
{
utime_t wait_start = system_time();
if (dp_device_started || dp_device_start_error) {
debug(WAIT, "DisplayPort done with %d usecs to spare\n",
(int) (wait_start - dp_device_started_time));
goto exit;
}
while (!dp_device_started && !dp_device_start_error) {
utime_t now = system_time();
if (now >= timeout) {
debug(WAIT, "Timeout waiting for displayport start\n");
return -1;
}
event_wait_timeout(&dp_device_start_event, timeout - now);
}
debug(WAIT, "Delayed boot by %lld usecs\n", system_time() - wait_start);
exit:
debug(WAIT, "Started waiting %lld usecs after power on\n",
wait_start - gPowerOnTime);
return dp_device_start_error ? -1 : 0;
}
void dp_device_stop()
{
if ( !dp_device_started )
return;
set_power(false);
dp_device_started = false;
alpm_enabled = false;
}
bool dp_device_is_alpm_enabled()
{
return alpm_enabled;
}
#if WITH_HW_DISPLAY_EDP
int dp_device_get_raw_panel_id(u_int8_t *raw_panel_id)
{
if (event_wait_timeout(&dp_device_raw_panel_id_ready_event, kEDPRawPanelIdReadTimeout) == false)
return -1;
if (raw_panel_id == NULL)
return -1;
memset(raw_panel_id, 0, kEDPRawPanelIdLength);
memcpy(raw_panel_id, dp_device_raw_panel_id, kEDPRawPanelIdLength);
return 0;
}
#endif // WITH_HW_DISPLAY_EDP
int dp_device_get_alignment_status_mask(u_int32_t *mask)
{
int ret;
uint8_t value;
ret = dp_controller_read_bytes_dpcd(DPCD_ADDR_LANE_ALIGN_STATUS_UPDATED, &value, 1);
update_lane_status_mask();
update_requested_adjustment_levels();
if ( mask )
*mask = value;
return ret;
}
int dp_device_get_lane_status_mask(uint32_t lane, uint32_t *mask)
{
if ( lane > dp_device_get_max_lane_count() )
return -1;
*mask = dp_device_lane_status_mask[lane];
return 0;
}
int dp_device_get_training_pattern(uint32_t *value, bool *scramble)
{
int ret = 0;
uint8_t val;
ret = dp_controller_read_bytes_dpcd(DPCD_ADDR_TRAINING_PATTERN_SET, &val, 1);
if ( ret == 0 ) {
if ( value )
*value = (u_int32_t)(val & DPCD_ADDR_PATTERN_SET_MASK);
if ( scramble )
*scramble = (val & DPCD_ADDR_TRAINING_PATTERN_SET_SCRMB_DISABLE) == 0;
}
return ret;
}
int dp_device_set_training_pattern(uint32_t value, bool scramble)
{
uint8_t reg_val = value & DPCD_ADDR_PATTERN_SET_MASK;
if ( !scramble )
reg_val |= DPCD_ADDR_TRAINING_PATTERN_SET_SCRMB_DISABLE;
dp_device_adjustment_bytes[0] = reg_val;
return dp_controller_write_bytes_dpcd(DPCD_ADDR_TRAINING_PATTERN_SET, dp_device_adjustment_bytes, 5);
}
int dp_device_get_requested_adjustment_levels(uint32_t lane, u_int32_t *voltage, u_int32_t *eq)
{
if ( lane > dp_device_get_max_lane_count() )
return -1;
*voltage = dp_device_voltage_adjustment_level[lane];
*eq = dp_device_eq_adjustment_level[lane];
return 0;
}
int dp_device_set_adjustment_levels(uint32_t lane, u_int32_t voltage_swing, u_int32_t eq,
bool voltage_max_reached, bool eq_max_reached)
{
uint8_t value;
if ( lane > dp_device_get_max_lane_count() )
return -1;
value = (eq << DPCD_ADDR_TRAINNIG_SET_PRE_EMPH_SHIFT) |
(voltage_swing << DPCD_ADDR_TRAINNIG_SET_VOL_SWING_SHIFT);
if (voltage_max_reached) {
value |= DPCD_ADDR_TRAINNIG_SET_VOL_SWING_MAX;
}
if ( eq_max_reached ) {
value |= DPCD_ADDR_TRAINNIG_SET_PRE_EMPH_MAX;
}
dp_device_adjustment_bytes[lane+1] = value;
return 0;
}
int dp_device_get_enhanced_mode(bool * value)
{
int ret = 0;
uint8_t val = 0;
ret = dp_controller_read_bytes_dpcd(DPCD_ADDR_LANE_COUNT_SET, &val, 1);
if ( ret == 0 ) {
*value = val & DPCD_ADDR_LANE_COUNT_SET_ENHANCED;
}
return ret;
}
int dp_device_get_sink_count(uint8_t * value)
{
int ret = 0;
uint8_t val = 0;
ret = dp_controller_read_bytes_dpcd(DPCD_ADDR_SINK_COUNT, &val, 1);
if ( ret == 0 ) {
*value = val;
}
return ret;
}
int dp_device_set_enhanced_mode(bool value)
{
uint32_t lane_count = 0;
dp_device_get_lane_count(&lane_count);
lane_count &= DPCD_ADDR_LANE_COUNT_SET_COUNT_MASK;
if ( value )
lane_count |= DPCD_ADDR_LANE_COUNT_SET_ENHANCED;
return dp_controller_write_bytes_dpcd(DPCD_ADDR_LANE_COUNT_SET, (uint8_t *)&lane_count, 1);
}
int dp_device_get_ASSR(bool * value)
{
int ret = 0;
uint8_t val = 0;
ret = dp_controller_read_bytes_dpcd(DPCD_ADDR_RECEIVER_EDP_CONFIG, &val, 1);
if ( ret == 0 ) {
*value = val & DPCD_ADDR_RECEIVER_EDP_CONFIG_ASSR_ENABLE;
}
return ret;
}
int dp_device_set_ASSR(bool value)
{
uint8_t val = 0;
if ( value )
val |= DPCD_ADDR_RECEIVER_EDP_CONFIG_ASSR_ENABLE;
return dp_controller_write_bytes_dpcd(DPCD_ADDR_RECEIVER_EDP_CONFIG, (uint8_t *)&val, 1);
}
int dp_device_get_downspread(bool * value)
{
int ret = 0;
uint8_t val = 0;
ret = dp_controller_read_bytes_dpcd(DPCD_ADDR_DOWNSPREAD_CTRL, &val, 1);
if ( ret == 0 ) {
*value = val & DPCD_ADDR_DOWNSPREAD_ENABLE;
}
return ret;
}
int dp_device_set_downspread(bool value)
{
uint8_t reg_val = 0;
reg_val = value ? DPCD_ADDR_DOWNSPREAD_ENABLE : 0;
return dp_controller_write_bytes_dpcd(DPCD_ADDR_DOWNSPREAD_CTRL, (uint8_t *)&reg_val, 1);
}
int dp_device_get_lane_count(uint32_t * value)
{
int ret = 0;
uint8_t val;
ret = dp_controller_read_bytes_dpcd(DPCD_ADDR_LANE_COUNT_SET, &val, 1);
if ( ret == 0 ) {
*value = val & DPCD_ADDR_LANE_COUNT_SET_COUNT_MASK;
}
return ret;
}
int dp_device_set_lane_count(uint32_t value)
{
bool enhanced_mode = false;
value &= DPCD_ADDR_LANE_COUNT_SET_COUNT_MASK;
dp_device_get_enhanced_mode(&enhanced_mode);
if ( enhanced_mode )
value |= DPCD_ADDR_LANE_COUNT_SET_ENHANCED;
return dp_controller_write_bytes_dpcd(DPCD_ADDR_LANE_COUNT_SET, (uint8_t *)&value, 1);
}
int dp_device_get_link_rate(u_int32_t * value)
{
return dp_controller_read_bytes_dpcd(DPCD_ADDR_LINK_BW_SET, (uint8_t*)value, 1);
}
int dp_device_set_link_rate(u_int32_t value)
{
return dp_controller_write_bytes_dpcd(DPCD_ADDR_LINK_BW_SET, (uint8_t *)&value, 1);
}
int dp_device_hdcp_enable(bool enable)
{
#if WITH_HW_HOOVER
uint8_t value;
dp_controller_read_bytes_dpcd(DPCD_ADDR_HDMI_DVI_MODE_SELECT, &value, 1);
if (!enable) value |= DPCD_HDCP_DISABLE;
return dp_controller_write_bytes_dpcd(DPCD_ADDR_HDMI_DVI_MODE_SELECT, &value, 1);
#else
return 0;
#endif
}
int dp_device_get_downstream_port_type(int *ret_value)
{
#if WITH_HW_MCU
// BlueSteel is reporting DP, but we know for sure it's HDMI.
if (ret_value) *ret_value = kDPDownstreamTypeHDMI;
return 0;
#else
int ret = 0;
int value = kDPDownstreamTypeOther;
if (dp_device_get_revision() == 0x11) {
value = dp_device_downstream_port_capability_bytes[0] & 0x07;
}
if (value == kDPDownstreamTypeDP) {
uint8_t reg_val;
ret = dp_controller_read_bytes_dpcd(DPCD_ADDR_DOWNSTREAMPORT_PRESENT, &reg_val, 1);
if (ret != 0) goto exit;
switch (((reg_val >> 1 ) & 3)) {
case 0:
value = kDPDownstreamTypeDP;
break;
case 1:
value = kDPDownstreamTypeVGA;
break;
case 2:
value = kDPDownstreamTypeHDMI;
break;
case 3:
value = kDPDownstreamTypeOther;
break;
}
}
exit:
if (ret_value) *ret_value = value;
return ret;
#endif
}
int dp_device_enable_alpm(bool enable)
{
uint8_t alpm_data = enable;
return dp_controller_write_bytes_dpcd(DPCD_ADDR_ALPM_CTRL, &alpm_data, 1);
}
/////////////////////////////////////////
////////// dp-device local functions
static int set_power(bool state)
{
int ret;
u_int8_t byte;
bool current_state;
ret = dp_controller_read_bytes_dpcd(DPCD_ADDR_SINK_POWER_STATE, &byte, 1);
debug(INFO, "Read sink power state: ret=%d\n", ret);
require_noerr(ret, exit);
current_state = (byte == DPCD_ADDR_SINK_POWER_STATE_ON);
require_action(state != current_state, exit, debug(INFO, "power level already = %d\n", state));
debug(INFO, "setting power level = %d\n", state);
byte = state ? DPCD_ADDR_SINK_POWER_STATE_ON : DPCD_ADDR_SINK_POWER_STATE_OFF;
ret = dp_controller_write_bytes_dpcd(DPCD_ADDR_SINK_POWER_STATE, &byte, 1);
// see DportV1.1a section 5.2.5
if ( state )
task_sleep(20 * 1000);
exit:
return ret;
}
static int cache_capabilities()
{
int ret;
ret = dp_controller_read_bytes_dpcd(DPCD_ADDR_DPCD_REV, dp_device_capability_bytes,
(uint32_t)sizeof(dp_device_capability_bytes));
if ( ret != 0 ) {
debug(ERROR, "failed to read capabilities\n");
return -1;
}
ret = dp_controller_read_bytes_dpcd(DPCD_ADDR_DOWNSTREAMPORT_0_CAPS,
dp_device_downstream_port_capability_bytes,
(uint32_t)sizeof(dp_device_downstream_port_capability_bytes));
if ( ret != 0 ) {
debug(ERROR, "failed to read downstream ports capabilities\n");
return -1;
}
return 0;
}
#if WITH_HW_DISPLAY_EDP
static int read_raw_panel_id()
{
int ret;
ret = dp_controller_read_bytes_dpcd(DPCP_ADDR_VENDOR_BYTES, dp_device_raw_panel_id, kEDPRawPanelIdLength);
if (ret != 0) {
debug(ERROR, "failed to read raw panel id\n");
return -1;
}
return 0;
}
#endif // WITH_HW_DISPLAY_EDP
u_int32_t dp_device_get_revision()
{
return dp_device_capability_bytes[DPCD_ADDR_DPCD_REV];
}
u_int32_t dp_device_get_max_lane_count()
{
return dp_device_capability_bytes[DPCD_ADDR_MAX_LANE_COUNT] & DPCD_ADDR_LANE_COUNT_SET_COUNT_MASK;
}
u_int32_t dp_device_get_max_link_rate()
{
return dp_device_capability_bytes[DPCD_ADDR_MAX_LINK_RATE];
}
bool dp_device_get_supports_enhanced_mode()
{
if ( dp_device_get_revision() < 0x11 )
return false;
return dp_device_capability_bytes[DPCD_ADDR_MAX_LANE_COUNT] & DPCD_ADDR_LANE_COUNT_SET_ENHANCED;
}
bool dp_device_get_supports_training_pattern3()
{
if ( dp_device_get_revision() < 0x12 )
return false;
return dp_device_capability_bytes[DPCD_ADDR_MAX_LANE_COUNT] & DPCD_ADDR_LANE_COUNT_TPS3_SUPPORTED;
}
bool dp_device_get_supports_fast_link_training()
{
int ret;
uint8_t value = 0;
ret = dp_controller_read_bytes_dpcd(DPCD_ADDR_MAX_DOWNSPREAD, &value, 1);
require_noerr(ret, exit);
exit:
#if WITH_HW_HOOVER
return (false);
#else
return (value & (1<<6) ? true : false);
#endif
}
bool dp_device_get_supports_alpm()
{
int ret;
uint8_t value = 0;
ret = dp_controller_read_bytes_dpcd(DPCD_ADDR_ALPM_CAP, &value, 1);
require_noerr(ret, exit);
exit:
return (value & 1 ? true : false);
}
bool dp_device_get_supports_assr()
{
int ret;
uint8_t value = 0;
ret = dp_controller_read_bytes_dpcd(DPCD_ADDR_ALTERNATE_SCRAMBLE, &value, 1);
require_noerr(ret, exit);
exit:
return (value & DPCD_ADDR_ALTERNATE_SCRAMBLER_RESET_CAP ? true : false);
}
bool dp_device_get_supports_downspread()
{
int ret;
uint8_t value = 0;
if ( dp_device_get_revision() >= 0x11 )
return true;
ret = dp_controller_read_bytes_dpcd(DPCD_ADDR_MAX_DOWNSPREAD, &value, 1);
require_noerr(ret, exit);
exit:
return (value & (1<<0) ? true : false);
}
#define min(a,b) ((a) < (b) ? (a) : (b))
#define max(a,b) ((a) > (b) ? (a) : (b))
static int train_link()
{
struct dp_link_train_data data;
int ret;
uint8_t ignore[8];
bzero(&data, sizeof(struct dp_link_train_data));
// collect data needed for link training
data.lane_count = dp_device_get_max_lane_count();
data.link_rate = dp_device_get_max_link_rate();
data.enhanced_mode = dp_device_get_supports_enhanced_mode();
data.assr = dp_device_get_supports_assr();
data.fast = dp_device_get_supports_fast_link_training() && dp_controller_get_supports_fast_link_training();
data.downspread = min(dp_device_get_supports_downspread(),dp_controller_get_supports_downspread());
debug(INIT, "lane_count: %d, link_rate: %d, enhanced_mode: %d, assr: %d, fast: %d downspread: %d\n",
data.lane_count, data.link_rate, data.enhanced_mode, data.assr, data.fast, data.downspread);
if ( !data.lane_count || !data.link_rate ) {
return -1;
}
ret = dp_controller_train_link(&data);
if ( ret != 0 )
return -1;
// clear error bits
dp_controller_read_bytes_dpcd(DPCD_ADDR_SYMBOL_ERROR_COUNT_LANE0_BYTE0, ignore, sizeof(ignore));
return 0;
}
static int enable_alpm(bool enable)
{
bool supports_alpm;
int ret = 0;
supports_alpm = dp_device_get_supports_alpm() && dp_controller_get_supports_alpm();
printf("supports_alpm %d\n", supports_alpm);
if (supports_alpm) {
ret = dp_device_enable_alpm(enable);
if (ret != 0) {
debug(ERROR, "Failed to %s device alpm\n", enable ? "enable" : "disable");
return ret;
}
ret = displayport_enable_alpm(enable);
if (ret != 0) {
debug(ERROR, "Failed to %s controller alpm\n", enable ? "enable" : "disable");
}
alpm_enabled =true;
}
return ret;
}
static int update_lane_status_mask()
{
int ret = 0;
uint8_t value, lane;
for (lane=0; lane<dp_device_get_max_lane_count(); lane++) {
if ( !(lane % 2) )
ret = dp_controller_read_bytes_dpcd(DPCD_ADDR_LANE0_1_STATUS+(lane>>1), &value, 1);
if ( ret != 0 )
break;
if ( lane % 2 )
dp_device_lane_status_mask[lane] = (value >> DPCD_ADDR_LANEX_Y_STATUS_Y_SHIFT) &
kDPLaneStatusFlagsMask;
else
dp_device_lane_status_mask[lane] = (value >> DPCD_ADDR_LANEX_Y_STATUS_X_SHIFT) &
kDPLaneStatusFlagsMask;
}
return ret;
}
static int update_requested_adjustment_levels()
{
int ret;
uint8_t value, lane;
ret = 0;
for (lane=0; lane<dp_device_get_max_lane_count(); lane++) {
if ( !(lane % 2) )
ret = dp_controller_read_bytes_dpcd(DPCD_ADDR_ADJUST_REQUEST_LANE0_1+(lane>>1), &value, 1);
if ( ret != 0 )
break;
if ( lane % 2 ) {
dp_device_eq_adjustment_level[lane] = ((value & DPCD_ADDR_ADJUST_REQUEST_LANEX_Y_PRE_EMP_Y_MASK) >> DPCD_ADDR_ADJUST_REQUEST_LANEX_Y_PRE_EMP_Y_SHIFT);
dp_device_voltage_adjustment_level[lane] = ((value & DPCD_ADDR_ADJUST_REQUEST_LANEX_Y_VOL_SWG_Y_MASK) >> DPCD_ADDR_ADJUST_REQUEST_LANEX_Y_VOL_SWG_Y_SHIFT);
}
else {
dp_device_eq_adjustment_level[lane] = ((value & DPCD_ADDR_ADJUST_REQUEST_LANEX_Y_PRE_EMP_X_MASK) >> DPCD_ADDR_ADJUST_REQUEST_LANEX_Y_PRE_EMP_X_SHIFT);
dp_device_voltage_adjustment_level[lane] = ((value & DPCD_ADDR_ADJUST_REQUEST_LANEX_Y_VOL_SWG_X_MASK) >> DPCD_ADDR_ADJUST_REQUEST_LANEX_Y_VOL_SWG_X_SHIFT);
}
}
return ret;
}
+261
View File
@@ -0,0 +1,261 @@
/*
* Copyright (C) 2010-2014 Apple Inc. All rights reserved.
*
* This document is the property of Apple Inc.
* It is considered confidential and proprietary.
*
* This document may not be reproduced or transmitted in any form,
* in whole or in part, without the express written permission of
* Apple Inc.
*/
#define DPCD_ADDR_DPCD_REV 0x00000
#define DPCD_ADDR_DPCD_REV_MAJOR_SHIFT 4
#define DPCD_ADDR_DPCD_REV_MAJOR_MASK (0xf << DPCD_ADDR_DPCD_REV_MAJOR_SHIFT)
#define DPCD_ADDR_DPCD_REV_MINOR_SHIFT 0
#define DPCD_ADDR_DPCD_REV_MINOR_MASK (0xf << DPCD_ADDR_DPCD_REV_MINOR_SHIFT)
#define DPCD_ADDR_MAX_LINK_RATE 0x00001
#define DPCD_ADDR_MAX_LANE_COUNT 0x00002
#define DPCD_ADDR_MAX_DOWNSPREAD 0x00003
#define DPCD_ADDR_NORP 0x00004
#define DPCD_ADDR_DOWNSTREAMPORT_PRESENT 0x00005
#define DPCD_ADDR_RECEIVE_PORT0_CAP_0 0x00008
#define DPCD_ADDR_RECEIVE_PORT0_CAP_0_EDID (1 << 1)
#define DPCD_ADDR_DOWNSTREAMPORT_COUNT 0x00007
#define DPCD_ADDR_RECEIVE_PORT0_CAP_1 0x00009
#define DPCD_ADDR_RECEIVE_PORT0_CAP_2 0x0000a
#define DPCD_ADDR_RECEIVE_PORT0_CAP_3 0x0000b
#define DPCD_ADDR_ALTERNATE_SCRAMBLE 0x0000d
#define DPCD_ADDR_ALTERNATE_SCRAMBLER_RESET_CAP (1 << 0)
#define DPCD_ADDR_FRAMING_CHANGE_CAP (1 << 1)
#define DPCD_ADDR_INVERTED_TRAINING_BIT_CAP (1 << 2)
#define DPCD_ADDR_DOWNSTREAMPORT_0_CAPS 0x00080
#define DPCD_ADDR_ALPM_CAP 0x0002e
#define DPCD_ADDR_LINK_BW_SET 0x00100
#define DPCD_ADDR_LANE_COUNT_SET 0x00101
#define DPCD_ADDR_LANE_COUNT_SET_ENHANCED (1 << 7)
#define DPCD_ADDR_LANE_COUNT_SET_COUNT_MASK (0x1f)
#define DPCD_ADDR_LANE_COUNT_TPS3_SUPPORTED (1 << 6)
#define DPCD_ADDR_TRAINING_PATTERN_SET 0x00102
#define DPCD_ADDR_PATTERN_SET_MASK 0x3
#define DPCD_ADDR_QUALITY_PATTERN_SHIFT 2
#define DPCD_ADDR_TRAINING_PATTERN_SET_SCRMB_DISABLE (1 << 5)
#define DPCD_ADDR_TRAINNIG_LANE0_SET 0x00103
#define DPCD_ADDR_TRAINNIG_LANE1_SET 0x00104
#define DPCD_ADDR_TRAINNIG_LANE2_SET 0x00105
#define DPCD_ADDR_TRAINNIG_LANE3_SET 0x00106
#define DPCD_ADDR_TRAINNIG_SET_VOL_SWING_SHIFT 0
#define DPCD_ADDR_TRAINNIG_SET_VOL_SWING_MASK (0x3 << DPCD_ADDR_TRAINNIG_SET_VOL_SWING_SHIFT)
#define DPCD_ADDR_TRAINNIG_SET_VOL_SWING_MAX (0x1 << 2)
#define DPCD_ADDR_TRAINNIG_SET_PRE_EMPH_SHIFT 3
#define DPCD_ADDR_TRAINNIG_SET_PRE_EMPH_MASK (0x3 << DPCD_ADDR_TRAINNIG_SET_PRE_EMPH_SHIFT)
#define DPCD_ADDR_TRAINNIG_SET_PRE_EMPH_MAX (0x1 << 5)
#define DPCD_ADDR_DOWNSPREAD_CTRL 0x00107
#define DPCD_ADDR_DOWNSPREAD_ENABLE (1 << 4)
// eDP (DPCD 1.2)
#define DPCD_ADDR_RECEIVER_EDP_CONFIG 0x0010a
#define DPCD_ADDR_RECEIVER_EDP_CONFIG_ASSR_ENABLE (1<<0)
#define DPCD_ADDR_ALPM_CTRL 0x00116
#define DPCD_ADDR_ALPM_ENABLE (1 << 0)
#define DPCD_ADDR_ALPM_ALPM_LOCK_ERROR_IRQ_HPD (1 << 1)
#define DPCD_ADDR_SINK_COUNT 0x00200
#define DPCD_ADDR_DEVICE_SERVICE_IRQ_VECTOR 0x00201
#define DPCD_IRQ_VECTOR_REMOTE_COMMAND (1 << 0)
#define DPCD_IRQ_VECTOR_AUTOMATED_TEST (1 << 1)
#define DPCD_IRQ_VECTOR_CP_IRQ (1 << 2)
#define DPCD_IRQ_VECTOR_SINK_SPECIFIC (1 << 6)
#define DPCD_ADDR_LANE0_1_STATUS 0x00202
#define DPCD_ADDR_LANE2_3_STATUS 0x00203
#define DPCD_ADDR_LANEX_Y_STATUS_X_SHIFT (0)
#define DPCD_ADDR_LANEX_Y_STATUS_Y_SHIFT (4)
#define DPCD_ADDR_LANE_ALIGN_STATUS_UPDATED 0x00204
#define DPCD_ADDR_SINK_STATUS 0x00205
#define DPCD_ADDR_ADJUST_REQUEST_LANE0_1 0x00206
#define DPCD_ADDR_ADJUST_REQUEST_LANE2_3 0x00207
#define DPCD_ADDR_ADJUST_REQUEST_LANEX_Y_VOL_SWG_X_SHIFT 0
#define DPCD_ADDR_ADJUST_REQUEST_LANEX_Y_VOL_SWG_X_MASK (0x3 << DPCD_ADDR_ADJUST_REQUEST_LANEX_Y_VOL_SWG_X_SHIFT)
#define DPCD_ADDR_ADJUST_REQUEST_LANEX_Y_PRE_EMP_X_SHIFT 2
#define DPCD_ADDR_ADJUST_REQUEST_LANEX_Y_PRE_EMP_X_MASK (0x3 << DPCD_ADDR_ADJUST_REQUEST_LANEX_Y_PRE_EMP_X_SHIFT)
#define DPCD_ADDR_ADJUST_REQUEST_LANEX_Y_VOL_SWG_Y_SHIFT 4
#define DPCD_ADDR_ADJUST_REQUEST_LANEX_Y_VOL_SWG_Y_MASK (0x3 << DPCD_ADDR_ADJUST_REQUEST_LANEX_Y_VOL_SWG_Y_SHIFT)
#define DPCD_ADDR_ADJUST_REQUEST_LANEX_Y_PRE_EMP_Y_SHIFT 6
#define DPCD_ADDR_ADJUST_REQUEST_LANEX_Y_PRE_EMP_Y_MASK (0x3 << DPCD_ADDR_ADJUST_REQUEST_LANEX_Y_PRE_EMP_Y_SHIFT)
#define DPCD_ADDR_TRAINING_SCORE_LANE0 0x00208
#define DPCD_ADDR_TRAINING_SCORE_LANE1 0x00209
#define DPCD_ADDR_TRAINING_SCORE_LANE2 0x0020a
#define DPCD_ADDR_TRAINING_SCORE_LANE3 0x0020b
#define DPCD_ADDR_SYMBOL_ERROR_COUNT_LANE0_BYTE0 0x00210
#define DPCD_ADDR_SYMBOL_ERROR_COUNT_LANE0_BYTE1 0x00211
#define DPCD_ADDR_SYMBOL_ERROR_COUNT_LANE1_BYTE0 0x00212
#define DPCD_ADDR_SYMBOL_ERROR_COUNT_LANE1_BYTE1 0x00213
#define DPCD_ADDR_SYMBOL_ERROR_COUNT_LANE2_BYTE0 0x00214
#define DPCD_ADDR_SYMBOL_ERROR_COUNT_LANE2_BYTE1 0x00215
#define DPCD_ADDR_SYMBOL_ERROR_COUNT_LANE3_BYTE0 0x00216
#define DPCD_ADDR_SYMBOL_ERROR_COUNT_LANE3_BYTE1 0x00217
#define DPCD_ADDR_TEST_REQUEST 0x00218
#define DPCD_ADDR_TEST_REQUEST_LINK (1 << 0)
#define DPCD_ADDR_TEST_REQUEST_PATTERN (1 << 1)
#define DPCD_ADDR_TEST_REQUEST_EDID (1 << 2)
#define DPCD_ADDR_TEST_REQUEST_PHY (1 << 3)
#define DPCD_ADDR_TEST_LINK_RATE 0x00219
#define DPCD_ADDR_TEST_LANE_COUNT 0x00220
#define DPCD_ADDR_TEST_PATTERN 0x00221
#define DPCD_ADDR_TEST_H_TOTAL_H 0x00222
#define DPCD_ADDR_TEST_H_TOTAL_L 0x00223
#define DPCD_ADDR_TEST_V_TOTAL_H 0x00224
#define DPCD_ADDR_TEST_V_TOTAL_L 0x00225
#define DPCD_ADDR_TEST_H_START_H 0x00226
#define DPCD_ADDR_TEST_H_START_L 0x00227
#define DPCD_ADDR_TEST_V_START_H 0x00228
#define DPCD_ADDR_TEST_V_START_L 0x00229
#define DPCD_ADDR_TEST_HSYNC_H 0x0022a
#define DPCD_ADDR_TEST_HSYNC_L 0x0022b
#define DPCD_ADDR_TEST_VSYNC_H 0x0022c
#define DPCD_ADDR_TEST_VSYNC_L 0x0022d
#define DPCD_ADDR_TEST_H_WIDTH_H 0x0022e
#define DPCD_ADDR_TEST_H_WIDTH_L 0x0022f
#define DPCD_ADDR_TEST_V_HEGHT_H 0x00230
#define DPCD_ADDR_TEST_V_HEGHT_L 0x00231
#define DPCD_ADDR_TEST_PHY 0x00248
#define DPCD_ADDR_TEST_PHY_SEL_MASK 3
#define DPCD_ADDR_TEST_RESPONSE 0x00260
#define DPCD_ADDR_TEST_RESPONSE_ACK (1 << 0)
#define DPCD_ADDR_TEST_RESPONSE_NACK (1 << 1)
#define DPCD_ADDR_TEST_RESPONSE_EDID (1 << 2)
#define DPCD_ADDR_TEST_EDID_CHECKSUM 0x00261
#define DPCD_ADDR_SOURCE_IEEE_OUI_7_0 0x00300
#define DPCD_ADDR_SOURCE_IEEE_OUI_15_8 0x00301
#define DPCD_ADDR_SOURCE_IEEE_OUI_23_16 0x00302
#define DPCD_ADDR_SOURCE_DEVICE_ID_BYTE_0 0x00303
#define DPCD_ADDR_SINK_IEEE_OUI_7_0 0x00400
#define DPCD_ADDR_SINK_IEEE_OUI_15_8 0x00401
#define DPCD_ADDR_SINK_IEEE_OUI_23_16 0x00402
#define DPCD_ADDR_SINK_DEVICE_ID_BYTE_0 0x00403
#define DPCP_ADDR_VENDOR_BYTES 0x00430
#define DPCD_ADDR_BRANCH_IEEE_OUI_7_0 0x00500
#define DPCD_ADDR_BRANCH_IEEE_OUI_15_8 0x00501
#define DPCD_ADDR_BRANCH_IEEE_OUI_23_16 0x00502
#define DPCD_ADDR_BRANCH_DEVICE_ID_BYTE_0 0x00503
#define DPCD_ADDR_HDMI_DVI_MODE_SELECT 0x00519
#define DPCD_HDMI_DVI_SELECT_DEFAULT 0x00
#define DPCD_ADDR_HDMI_DVI_MODE_SELECT_DVI 0x01
#define DPCD_HDCP_ENABLE 0x00
#define DPCD_HDCP_DISABLE 0x02
#define DPCD_ADDR_SINK_POWER_STATE 0x00600
#define DPCD_ADDR_SINK_POWER_STATE_ON 0x1
#define DPCD_ADDR_SINK_POWER_STATE_OFF 0x2
#define DPCD_ADDR_HDCP_BKSV_0 0x68000
#define DPCD_ADDR_HDCP_BKSV_1 0x68001
#define DPCD_ADDR_HDCP_BKSV_2 0x68002
#define DPCD_ADDR_HDCP_BKSV_3 0x68003
#define DPCD_ADDR_HDCP_BKSV_4 0x68004
#define DPCD_ADDR_HDCP_R0_0 0x68005
#define DPCD_ADDR_HDCP_R0_1 0x68006
#define DPCD_ADDR_HDCP_AKSV_0 0x68007
#define DPCD_ADDR_HDCP_AKSV_1 0x68008
#define DPCD_ADDR_HDCP_AKSV_2 0x68009
#define DPCD_ADDR_HDCP_AKSV_3 0x6800a
#define DPCD_ADDR_HDCP_AKSV_4 0x6800b
#define DPCD_ADDR_HDCP_AN_0 0x6800c
#define DPCD_ADDR_HDCP_AN_1 0x6800d
#define DPCD_ADDR_HDCP_AN_2 0x6800e
#define DPCD_ADDR_HDCP_AN_3 0x6800f
#define DPCD_ADDR_HDCP_AN_4 0x68010
#define DPCD_ADDR_HDCP_AN_5 0x68011
#define DPCD_ADDR_HDCP_AN_6 0x68012
#define DPCD_ADDR_HDCP_AN_7 0x68013
#define DPCD_ADDR_HDCP_H0_0 0x68014
#define DPCD_ADDR_HDCP_H0_1 0x68015
#define DPCD_ADDR_HDCP_H0_2 0x68016
#define DPCD_ADDR_HDCP_H0_3 0x68017
#define DPCD_ADDR_HDCP_H1_0 0x68018
#define DPCD_ADDR_HDCP_H1_1 0x68019
#define DPCD_ADDR_HDCP_H1_2 0x6801a
#define DPCD_ADDR_HDCP_H1_3 0x6801b
#define DPCD_ADDR_HDCP_H2_0 0x6801c
#define DPCD_ADDR_HDCP_H2_1 0x6801d
#define DPCD_ADDR_HDCP_H2_2 0x6801e
#define DPCD_ADDR_HDCP_H2_3 0x6801f
#define DPCD_ADDR_HDCP_H3_0 0x68020
#define DPCD_ADDR_HDCP_H3_1 0x68021
#define DPCD_ADDR_HDCP_H3_2 0x68022
#define DPCD_ADDR_HDCP_H3_3 0x68023
#define DPCD_ADDR_HDCP_H4_0 0x68024
#define DPCD_ADDR_HDCP_H4_1 0x68025
#define DPCD_ADDR_HDCP_H4_2 0x68026
#define DPCD_ADDR_HDCP_H4_3 0x68027
#define DPCD_ADDR_HDCP_BCAPS 0x68028
#define DPCD_ADDR_HDCP_BCAPS_HDCP_CAPABLE (1 << 0)
#define DPCD_ADDR_HDCP_BCAPS_IS_REPEATER (1 << 1)
#define DPCD_ADDR_HDCP_STATUS 0x68029
#define DPCD_ADDR_HDCP_STATUS_LINK_INTEGRITY_FAILURE (1 << 2)
#define DPCD_ADDR_HDCP_STATUS_R0PRIME_AVAILABLE (1 << 1)
#define DPCD_ADDR_HDCP_STATUS_READY (1 << 0)
#define DPCD_ADDR_HDCP_BINFO_0 0x6802a
#define DPCD_ADDR_HDCP_BINFO_1 0x6802b
#define DPCD_ADDR_HDCP_INFO_MAX_CASCADE_EXCEEDED (1 << 11)
#define DPCD_ADDR_HDCP_INFO_MAX_DEVS_EXCEEDED (1 << 7)
#define DPCD_ADDR_HDCP_KSV_FIFO_0 0x6802c
#define DPCD_ADDR_HDCP_KSV_FIFO_1 0x6802d
#define DPCD_ADDR_HDCP_KSV_FIFO_2 0x6802e
#define DPCD_ADDR_HDCP_KSV_FIFO_3 0x6802f
#define DPCD_ADDR_HDCP_KSV_FIFO_4 0x68030
#define DPCD_ADDR_HDCP_KSV_FIFO_5 0x68031
#define DPCD_ADDR_HDCP_KSV_FIFO_6 0x68032
#define DPCD_ADDR_HDCP_KSV_FIFO_7 0x68033
#define DPCD_ADDR_HDCP_KSV_FIFO_8 0x68034
#define DPCD_ADDR_HDCP_KSV_FIFO_9 0x68035
#define DPCD_ADDR_HDCP_KSV_FIFO_10 0x68036
#define DPCD_ADDR_HDCP_KSV_FIFO_11 0x68037
#define DPCD_ADDR_HDCP_KSV_FIFO_12 0x68038
#define DPCD_ADDR_HDCP_KSV_FIFO_13 0x68039
#define DPCD_ADDR_HDCP_KSV_FIFO_14 0x6803a
#define DPCD_ADDR_HDCP_RSVD 0x6803b
+377
View File
@@ -0,0 +1,377 @@
/*
*
* @APPLE_LICENSE_HEADER_START@
*
* Copyright (c) 1999-2009 Apple Computer, Inc. All Rights Reserved.
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPLE_LICENSE_HEADER_END@
*/
#ifndef _IOKIT_EDID_H
#define _IOKIT_EDID_H
#define kEDIDEstablishedTimingsCount 24
#define kEDIDEstablishedTimingsIIICount 48
typedef struct __attribute__((packed)) _EDIDDetailedHeader {
uint8_t header[2];
}EDIDDetailedHeader;
//__packed
typedef struct __attribute__((packed)) _EDIDDetailedTiming {
uint8_t pixelClock[2];
uint8_t hor_addr_low;
uint8_t hor_blank_low;
uint8_t hor_addr_blank_high;
uint8_t ver_addr_low;
uint8_t ver_blank_low;
uint8_t ver_addr_blank_high;
uint8_t hor_fporch; // #8
uint8_t hor_sync;
uint8_t ver_fporch_sync;
uint8_t hor_ver_porch_sync_high;
uint8_t inmm[3]; // in milimeter
uint8_t hor_border;
uint8_t ver_border;
uint8_t detailed;
} EDIDDetailedTiming;
typedef struct __attribute__((packed)) _EDIDString{
uint8_t flag;
char string[13];
} EDIDString;
typedef enum {
kEDIDDetailedRangeFlagRateOffsetVerticalMin = (1<<0),
kEDIDDetailedRangeFlagRateOffsetVerticalMax = (1<<1),
kEDIDDetailedRangeFlagRateOffsetHorizontalMin = (1<<2),
kEDIDDetailedRangeFlagRateOffsetHorizontalMax = (1<<3)
} EDIDDetailedRangeFlags;
enum {
kEDIDDetailedRangeVideoTimingTypeGTF = 0,
kEDIDDetailedRangeVideoTimingTypeRangeLimitsOnly = 1,
kEDIDDetailedRangeVideoTimingTypeSecondaryGTF = 2,
kEDIDDetailedRangeVideoTimingTypeCVT = 4
};
typedef uint8_t EDIDDetailedRangeVideoTimingType;
typedef enum {
kEDIDSupportedAspectFlag15_9 = (1<<3),
kEDIDSupportedAspectFlag5_4 = (1<<4),
kEDIDSupportedAspectFlag16_10 = (1<<5),
kEDIDSupportedAspectFlag16_9 = (1<<6),
kEDIDSupportedAspectFlag4_3 = (1<<7)
} EDIDSupportedAspectFlags;
typedef enum {
kEDIDPreferredAspectType4_3,
kEDIDPreferredAspectType16_9,
kEDIDPreferredAspectType16_10,
kEDIDPreferredAspectType5_4,
kEDIDPreferredAspectType15_9,
kEDIDPreferredAspectTypeShift = 5,
kEDIDPreferredAspectTypeMask = 0x7,
} EDIDPreferredAspectType;
typedef enum {
kEDIDCVTBlankingFlagStandard = (1<<3),
kEDIDCVTBlankingFlagReduced = (1<<4),
} EDIDCVTBlankingFlags;
typedef enum {
kEDIDDigitalScalingFlagVerticalStretch = (1<<4),
kEDIDDigitalScalingFlagVerticalShrink = (1<<5),
kEDIDDigitalScalingFlagHorizontalStretch = (1<<6),
kEDIDDigitalScalingFlagHorizontalShrink = (1<<7)
} EDIDDigitalScalingFlags;
typedef struct __attribute__((packed)) _EDIDDetailedRangeGTF {
uint8_t reserved;
uint8_t breakFrequency; // horizontal freq / 2 (khz)
uint8_t c; // c*2
uint8_t m[2];
uint8_t k;
uint8_t j; // j*2
} EDIDDetailedRangeGTF;
typedef struct __attribute__((packed)) _EDIDDetailedRangeCVT {
uint8_t version;
// Max. Pix Clk = [(range.maxPixelClockRate) × 10] – [(Byte 12: bits 7-2) × 0.25MHz]
uint8_t precision_activeMaxMSB; // pixel clock precision * 0.25Mhz (bits 7-2) | max active pixels per line MSB (bits 1-0)
uint8_t activeMaxLSB; // max active pixels per line MSB
uint8_t supportedFlags;
uint8_t preferredFlags;
uint8_t scaling;
uint8_t verticalRefreshRate; //hz
} EDIDDetailedRangeCVT;
typedef struct __attribute__((packed)) _EDIDDetailedRange{
uint8_t flag;
uint8_t minVerticalRate;
uint8_t maxVerticalRate;
uint8_t minHorizontalRate;
uint8_t maxHorizontalRate;
uint8_t maxPixelClockRate;
struct {
EDIDDetailedRangeVideoTimingType type;
union {
EDIDDetailedRangeGTF gtf;
EDIDDetailedRangeCVT cvt;
} data;
}timing;
} EDIDDetailedRange;
typedef struct __attribute__((packed)) _EDIDDetailedWhitePoint {
uint8_t index;
uint8_t xyLSB;
uint8_t x;
uint8_t y;
uint8_t gamma;
} EDIDDetailedWhitePoint;
typedef struct __attribute__((packed)) _EDIDDetailedColorPoint {
EDIDDetailedWhitePoint whitePoint[2];
} EDIDDetailedColorPoint;
typedef struct __attribute__((packed)) _EDIDDetailedEstablishedTimingsIII {
uint8_t data[6];
} EDIDDetailedEstablishedTimingsIII;
typedef struct __attribute__((packed)) _EDIDDetailedDescriptor {
uint8_t zero[2];
uint8_t flag;
uint8_t type;
union {
EDIDString name;
EDIDDetailedRange range;
EDIDDetailedColorPoint color;
uint8_t standard[12];
uint8_t cvt[12];
EDIDDetailedEstablishedTimingsIII established;
}data;
}EDIDDetailedDescriptor;
typedef struct __attribute__((packed)) EDIDDetailed {
union {
EDIDDetailedHeader header;
EDIDDetailedTiming timing;
EDIDDetailedDescriptor descriptor;
} data;
} EDIDDetailed;
typedef struct __attribute__((packed)) _EDIDHeader {
uint8_t header[8];
} EDIDHeader;
typedef enum {
kEDIDStandardFeatureFlagGTF = (1<<0),
kEDIDStandardFeatureFlagPreferredNative = (1<<1),
kEDIDStandardFeatureFlagSRGB = (1<<2),
kEDIDStandardFeatureFlagColorDepth = (3<<3),
kEDIDStandardFeatureFlagActiveOff = (1<<5),
kEDIDStandardFeatureFlagSuspend = (1<<6),
kEDIDStandardFeatureFlagStandby = (1<<7)
} EDIDStandardFeatureFlags;
// STANDARD STUFF
typedef struct __attribute__((packed)) _EDIDStandard {
uint8_t header[8];
// Vender / Product
uint8_t vendorID[2];
uint8_t productID[2];
uint8_t serialNumber[4];
uint8_t weekOfManu;
uint8_t yearOfManu;
// EDID structure version / rev.
uint8_t version;
uint8_t revision;
// Basic Display Parameters / Features
uint8_t videoInputDef;
uint8_t maxHorzSize; // cm
uint8_t maxVertSize; // cm
uint8_t dispTransferChr;
uint8_t feature;
// Color Characteristics
uint8_t redGreenLowBits;
uint8_t blueWhiteLowBits;
uint8_t redX;
uint8_t redY;
uint8_t greenX;
uint8_t greenY;
uint8_t blueX;
uint8_t blueY;
uint8_t whiteX;
uint8_t whiteY;
// Established Timings
uint8_t established[3];
// Standard Timing Identification
uint8_t standard[16];
EDIDDetailed preferred;
EDIDDetailed detailed[3];
// Extra
uint8_t extensionFlag;
uint8_t checksum;
} EDIDStandard;
typedef struct __attribute__((packed)) _EDIDEXTHeader {
uint8_t tag;
uint8_t revision;
} EDIDEXTHeader;
typedef struct __attribute__((packed)) _EDIDCVT {
uint8_t data[3];
} EDIDCVT;
// CEA STUFF
typedef enum {
kEDIDCEA3DataBlockTypeReserved,
kEDIDCEA3DataBlockTypeAudio,
kEDIDCEA3DataBlockTypeVideo,
kEDIDCEA3DataBlockTypeVenderSpecific,
kEDIDCEA3DataBlockTypeSpeakerAllocation,
kEDIDCEA3DataBlockTypeVESADTC,
kEDIDCEA3DataBlockTypeReserved1,
kEDIDCEA3DataBlockTypeExtended
} EDIDCEA3DataBlockType;
typedef struct __attribute__((packed)) _EDIDCEA3DataBlockAudio {
uint8_t descriptor[0];
} EDIDCEA3DataBlockAudio;
typedef struct __attribute__((packed)) _EDIDCEA3DataBlockVideo {
uint8_t descriptor[0];
} EDIDCEA3DataBlockVideo;
typedef struct __attribute__((packed)) _EDIDCEA3DataBlockVendorSpecific {
uint8_t ieeeOui[3];
uint8_t data[0];
} EDIDCEA3DataBlockVendorSpecific;
typedef struct __attribute__((packed)) _EDIDCEA3DataBlockSpeakerAllocation {
uint8_t data[3];
} EDIDCEA3DataBlockSpeakerAllocation;
typedef struct __attribute__((packed)) _EDIDCEA3DataBlockExtended {
uint8_t tag;
uint8_t data[31];
} EDIDCEA3DataBlockExtended;
typedef struct __attribute__((packed)) _EDIDCEA3DataBlock {
uint8_t flags;
union {
EDIDCEA3DataBlockAudio audio;
EDIDCEA3DataBlockVideo video;
EDIDCEA3DataBlockVendorSpecific vendor;
EDIDCEA3DataBlockSpeakerAllocation speaker;
EDIDCEA3DataBlockExtended extended;
} data;
} EDIDCEA3DataBlock;
typedef struct __attribute__((packed)) _EDIDCEA_1 {
struct {
uint8_t tag;
uint8_t revision;
uint8_t dataOffset;
uint8_t reserved;
} header;
uint8_t data[123];
uint8_t checksum;
} EDIDCEA_1;
typedef struct __attribute__((packed)) _EDIDCEA_2 {
struct {
uint8_t tag;
uint8_t revision;
uint8_t dataOffset;
uint8_t detailedFlags;
} header;
uint8_t data[123];
uint8_t checksum;
} EDIDCEA_2;
typedef struct __attribute__((packed)) _EDIDCEA_3 {
struct {
uint8_t tag;
uint8_t revision;
uint8_t dataLength;
uint8_t detailedFlags;
} header;
uint8_t data[123];
uint8_t checksum;
} EDIDCEA_3;
typedef struct __attribute__((packed)) _EDIDCEA {
union {
EDIDEXTHeader header;
EDIDCEA_1 cea1;
EDIDCEA_2 cea2;
EDIDCEA_3 cea3;
} data;
} EDIDCEA;
typedef struct __attribute__((packed)) _EDIDVTB{
EDIDEXTHeader header;
uint8_t dtbCount;
uint8_t cvtCount;
uint8_t stCount;
uint8_t data[122];
uint8_t checksum;
} EDIDVTB;
typedef enum {
kEDIDTypeCEA = 0x02,
KEDIDTypeVTB = 0x10,
kEDIDTypeDI = 0x40,
} EDIDType;
// __packed
typedef struct __attribute__((packed)) _EDID{
union {
EDIDHeader header;
EDIDStandard standard;
EDIDCEA cea;
EDIDVTB vtb;
} data;
} EDID;
#endif /* _IOKIT_EDID_H */
File diff suppressed because it is too large. Load diff
+18
View File
@@ -0,0 +1,18 @@
# Copyright (C) 2009 Apple Computer, Inc. All rights reserved.
#
# This document is the property of Apple Computer, Inc.
# It is considered confidential and proprietary.
#
# This document may not be reproduced or transmitted in any form,
# in whole or in part, without the express written permission of
# Apple Computer, Inc.
#
LOCAL_DIR := $(GET_LOCAL_DIR)
GLOBAL_INCLUDES +=
ALL_OBJS += \
$(LOCAL_DIR)/controller.o \
$(LOCAL_DIR)/device.o \
$(LOCAL_DIR)/debug.o \
$(LOCAL_DIR)/process_edid.o