drm/i915: Subclass intel_encoder.
Subclass intel_encoder to reduce the pointer dance through intel_encoder->dev_priv. 10 files changed, 896 insertions(+), 997 deletions(-) Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Signed-off-by: Eric Anholt <eric@anholt.net>
This commit is contained in:

committed by
Eric Anholt

parent
94113cecae
commit
ea5b213ad4
@@ -42,10 +42,11 @@
|
||||
|
||||
#define DP_LINK_CONFIGURATION_SIZE 9
|
||||
|
||||
#define IS_eDP(i) ((i)->type == INTEL_OUTPUT_EDP)
|
||||
#define IS_PCH_eDP(dp_priv) ((dp_priv)->is_pch_edp)
|
||||
#define IS_eDP(i) ((i)->base.type == INTEL_OUTPUT_EDP)
|
||||
#define IS_PCH_eDP(i) ((i)->is_pch_edp)
|
||||
|
||||
struct intel_dp_priv {
|
||||
struct intel_dp {
|
||||
struct intel_encoder base;
|
||||
uint32_t output_reg;
|
||||
uint32_t DP;
|
||||
uint8_t link_configuration[DP_LINK_CONFIGURATION_SIZE];
|
||||
@@ -54,40 +55,39 @@ struct intel_dp_priv {
|
||||
uint8_t link_bw;
|
||||
uint8_t lane_count;
|
||||
uint8_t dpcd[4];
|
||||
struct intel_encoder *intel_encoder;
|
||||
struct i2c_adapter adapter;
|
||||
struct i2c_algo_dp_aux_data algo;
|
||||
bool is_pch_edp;
|
||||
};
|
||||
|
||||
static void
|
||||
intel_dp_link_train(struct intel_encoder *intel_encoder, uint32_t DP,
|
||||
uint8_t link_configuration[DP_LINK_CONFIGURATION_SIZE]);
|
||||
static struct intel_dp *enc_to_intel_dp(struct drm_encoder *encoder)
|
||||
{
|
||||
return container_of(enc_to_intel_encoder(encoder), struct intel_dp, base);
|
||||
}
|
||||
|
||||
static void
|
||||
intel_dp_link_down(struct intel_encoder *intel_encoder, uint32_t DP);
|
||||
static void intel_dp_link_train(struct intel_dp *intel_dp);
|
||||
static void intel_dp_link_down(struct intel_dp *intel_dp);
|
||||
|
||||
void
|
||||
intel_edp_link_config (struct intel_encoder *intel_encoder,
|
||||
int *lane_num, int *link_bw)
|
||||
int *lane_num, int *link_bw)
|
||||
{
|
||||
struct intel_dp_priv *dp_priv = intel_encoder->dev_priv;
|
||||
struct intel_dp *intel_dp = container_of(intel_encoder, struct intel_dp, base);
|
||||
|
||||
*lane_num = dp_priv->lane_count;
|
||||
if (dp_priv->link_bw == DP_LINK_BW_1_62)
|
||||
*lane_num = intel_dp->lane_count;
|
||||
if (intel_dp->link_bw == DP_LINK_BW_1_62)
|
||||
*link_bw = 162000;
|
||||
else if (dp_priv->link_bw == DP_LINK_BW_2_7)
|
||||
else if (intel_dp->link_bw == DP_LINK_BW_2_7)
|
||||
*link_bw = 270000;
|
||||
}
|
||||
|
||||
static int
|
||||
intel_dp_max_lane_count(struct intel_encoder *intel_encoder)
|
||||
intel_dp_max_lane_count(struct intel_dp *intel_dp)
|
||||
{
|
||||
struct intel_dp_priv *dp_priv = intel_encoder->dev_priv;
|
||||
int max_lane_count = 4;
|
||||
|
||||
if (dp_priv->dpcd[0] >= 0x11) {
|
||||
max_lane_count = dp_priv->dpcd[2] & 0x1f;
|
||||
if (intel_dp->dpcd[0] >= 0x11) {
|
||||
max_lane_count = intel_dp->dpcd[2] & 0x1f;
|
||||
switch (max_lane_count) {
|
||||
case 1: case 2: case 4:
|
||||
break;
|
||||
@@ -99,10 +99,9 @@ intel_dp_max_lane_count(struct intel_encoder *intel_encoder)
|
||||
}
|
||||
|
||||
static int
|
||||
intel_dp_max_link_bw(struct intel_encoder *intel_encoder)
|
||||
intel_dp_max_link_bw(struct intel_dp *intel_dp)
|
||||
{
|
||||
struct intel_dp_priv *dp_priv = intel_encoder->dev_priv;
|
||||
int max_link_bw = dp_priv->dpcd[1];
|
||||
int max_link_bw = intel_dp->dpcd[1];
|
||||
|
||||
switch (max_link_bw) {
|
||||
case DP_LINK_BW_1_62:
|
||||
@@ -126,13 +125,11 @@ intel_dp_link_clock(uint8_t link_bw)
|
||||
|
||||
/* I think this is a fiction */
|
||||
static int
|
||||
intel_dp_link_required(struct drm_device *dev,
|
||||
struct intel_encoder *intel_encoder, int pixel_clock)
|
||||
intel_dp_link_required(struct drm_device *dev, struct intel_dp *intel_dp, int pixel_clock)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct intel_dp_priv *dp_priv = intel_encoder->dev_priv;
|
||||
|
||||
if (IS_eDP(intel_encoder) || IS_PCH_eDP(dp_priv))
|
||||
if (IS_eDP(intel_dp) || IS_PCH_eDP(intel_dp))
|
||||
return (pixel_clock * dev_priv->edp_bpp) / 8;
|
||||
else
|
||||
return pixel_clock * 3;
|
||||
@@ -149,14 +146,13 @@ intel_dp_mode_valid(struct drm_connector *connector,
|
||||
struct drm_display_mode *mode)
|
||||
{
|
||||
struct drm_encoder *encoder = intel_attached_encoder(connector);
|
||||
struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
|
||||
struct intel_dp_priv *dp_priv = intel_encoder->dev_priv;
|
||||
struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
|
||||
struct drm_device *dev = connector->dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
int max_link_clock = intel_dp_link_clock(intel_dp_max_link_bw(intel_encoder));
|
||||
int max_lanes = intel_dp_max_lane_count(intel_encoder);
|
||||
int max_link_clock = intel_dp_link_clock(intel_dp_max_link_bw(intel_dp));
|
||||
int max_lanes = intel_dp_max_lane_count(intel_dp);
|
||||
|
||||
if ((IS_eDP(intel_encoder) || IS_PCH_eDP(dp_priv)) &&
|
||||
if ((IS_eDP(intel_dp) || IS_PCH_eDP(intel_dp)) &&
|
||||
dev_priv->panel_fixed_mode) {
|
||||
if (mode->hdisplay > dev_priv->panel_fixed_mode->hdisplay)
|
||||
return MODE_PANEL;
|
||||
@@ -167,8 +163,8 @@ intel_dp_mode_valid(struct drm_connector *connector,
|
||||
|
||||
/* only refuse the mode on non eDP since we have seen some wierd eDP panels
|
||||
which are outside spec tolerances but somehow work by magic */
|
||||
if (!IS_eDP(intel_encoder) &&
|
||||
(intel_dp_link_required(connector->dev, intel_encoder, mode->clock)
|
||||
if (!IS_eDP(intel_dp) &&
|
||||
(intel_dp_link_required(connector->dev, intel_dp, mode->clock)
|
||||
> intel_dp_max_data_rate(max_link_clock, max_lanes)))
|
||||
return MODE_CLOCK_HIGH;
|
||||
|
||||
@@ -232,13 +228,12 @@ intel_hrawclk(struct drm_device *dev)
|
||||
}
|
||||
|
||||
static int
|
||||
intel_dp_aux_ch(struct intel_encoder *intel_encoder,
|
||||
intel_dp_aux_ch(struct intel_dp *intel_dp,
|
||||
uint8_t *send, int send_bytes,
|
||||
uint8_t *recv, int recv_size)
|
||||
{
|
||||
struct intel_dp_priv *dp_priv = intel_encoder->dev_priv;
|
||||
uint32_t output_reg = dp_priv->output_reg;
|
||||
struct drm_device *dev = intel_encoder->enc.dev;
|
||||
uint32_t output_reg = intel_dp->output_reg;
|
||||
struct drm_device *dev = intel_dp->base.enc.dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
uint32_t ch_ctl = output_reg + 0x10;
|
||||
uint32_t ch_data = ch_ctl + 4;
|
||||
@@ -253,7 +248,7 @@ intel_dp_aux_ch(struct intel_encoder *intel_encoder,
|
||||
* and would like to run at 2MHz. So, take the
|
||||
* hrawclk value and divide by 2 and use that
|
||||
*/
|
||||
if (IS_eDP(intel_encoder)) {
|
||||
if (IS_eDP(intel_dp)) {
|
||||
if (IS_GEN6(dev))
|
||||
aux_clock_divider = 200; /* SNB eDP input clock at 400Mhz */
|
||||
else
|
||||
@@ -344,7 +339,7 @@ intel_dp_aux_ch(struct intel_encoder *intel_encoder,
|
||||
|
||||
/* Write data to the aux channel in native mode */
|
||||
static int
|
||||
intel_dp_aux_native_write(struct intel_encoder *intel_encoder,
|
||||
intel_dp_aux_native_write(struct intel_dp *intel_dp,
|
||||
uint16_t address, uint8_t *send, int send_bytes)
|
||||
{
|
||||
int ret;
|
||||
@@ -361,7 +356,7 @@ intel_dp_aux_native_write(struct intel_encoder *intel_encoder,
|
||||
memcpy(&msg[4], send, send_bytes);
|
||||
msg_bytes = send_bytes + 4;
|
||||
for (;;) {
|
||||
ret = intel_dp_aux_ch(intel_encoder, msg, msg_bytes, &ack, 1);
|
||||
ret = intel_dp_aux_ch(intel_dp, msg, msg_bytes, &ack, 1);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_ACK)
|
||||
@@ -376,15 +371,15 @@ intel_dp_aux_native_write(struct intel_encoder *intel_encoder,
|
||||
|
||||
/* Write a single byte to the aux channel in native mode */
|
||||
static int
|
||||
intel_dp_aux_native_write_1(struct intel_encoder *intel_encoder,
|
||||
intel_dp_aux_native_write_1(struct intel_dp *intel_dp,
|
||||
uint16_t address, uint8_t byte)
|
||||
{
|
||||
return intel_dp_aux_native_write(intel_encoder, address, &byte, 1);
|
||||
return intel_dp_aux_native_write(intel_dp, address, &byte, 1);
|
||||
}
|
||||
|
||||
/* read bytes from a native aux channel */
|
||||
static int
|
||||
intel_dp_aux_native_read(struct intel_encoder *intel_encoder,
|
||||
intel_dp_aux_native_read(struct intel_dp *intel_dp,
|
||||
uint16_t address, uint8_t *recv, int recv_bytes)
|
||||
{
|
||||
uint8_t msg[4];
|
||||
@@ -403,7 +398,7 @@ intel_dp_aux_native_read(struct intel_encoder *intel_encoder,
|
||||
reply_bytes = recv_bytes + 1;
|
||||
|
||||
for (;;) {
|
||||
ret = intel_dp_aux_ch(intel_encoder, msg, msg_bytes,
|
||||
ret = intel_dp_aux_ch(intel_dp, msg, msg_bytes,
|
||||
reply, reply_bytes);
|
||||
if (ret == 0)
|
||||
return -EPROTO;
|
||||
@@ -426,10 +421,9 @@ intel_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode,
|
||||
uint8_t write_byte, uint8_t *read_byte)
|
||||
{
|
||||
struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data;
|
||||
struct intel_dp_priv *dp_priv = container_of(adapter,
|
||||
struct intel_dp_priv,
|
||||
adapter);
|
||||
struct intel_encoder *intel_encoder = dp_priv->intel_encoder;
|
||||
struct intel_dp *intel_dp = container_of(adapter,
|
||||
struct intel_dp,
|
||||
adapter);
|
||||
uint16_t address = algo_data->address;
|
||||
uint8_t msg[5];
|
||||
uint8_t reply[2];
|
||||
@@ -468,7 +462,7 @@ intel_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode,
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
ret = intel_dp_aux_ch(intel_encoder,
|
||||
ret = intel_dp_aux_ch(intel_dp,
|
||||
msg, msg_bytes,
|
||||
reply, reply_bytes);
|
||||
if (ret < 0) {
|
||||
@@ -496,41 +490,38 @@ intel_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode,
|
||||
}
|
||||
|
||||
static int
|
||||
intel_dp_i2c_init(struct intel_encoder *intel_encoder,
|
||||
intel_dp_i2c_init(struct intel_dp *intel_dp,
|
||||
struct intel_connector *intel_connector, const char *name)
|
||||
{
|
||||
struct intel_dp_priv *dp_priv = intel_encoder->dev_priv;
|
||||
|
||||
DRM_DEBUG_KMS("i2c_init %s\n", name);
|
||||
dp_priv->algo.running = false;
|
||||
dp_priv->algo.address = 0;
|
||||
dp_priv->algo.aux_ch = intel_dp_i2c_aux_ch;
|
||||
intel_dp->algo.running = false;
|
||||
intel_dp->algo.address = 0;
|
||||
intel_dp->algo.aux_ch = intel_dp_i2c_aux_ch;
|
||||
|
||||
memset(&dp_priv->adapter, '\0', sizeof (dp_priv->adapter));
|
||||
dp_priv->adapter.owner = THIS_MODULE;
|
||||
dp_priv->adapter.class = I2C_CLASS_DDC;
|
||||
strncpy (dp_priv->adapter.name, name, sizeof(dp_priv->adapter.name) - 1);
|
||||
dp_priv->adapter.name[sizeof(dp_priv->adapter.name) - 1] = '\0';
|
||||
dp_priv->adapter.algo_data = &dp_priv->algo;
|
||||
dp_priv->adapter.dev.parent = &intel_connector->base.kdev;
|
||||
|
||||
return i2c_dp_aux_add_bus(&dp_priv->adapter);
|
||||
memset(&intel_dp->adapter, '\0', sizeof (intel_dp->adapter));
|
||||
intel_dp->adapter.owner = THIS_MODULE;
|
||||
intel_dp->adapter.class = I2C_CLASS_DDC;
|
||||
strncpy (intel_dp->adapter.name, name, sizeof(intel_dp->adapter.name) - 1);
|
||||
intel_dp->adapter.name[sizeof(intel_dp->adapter.name) - 1] = '\0';
|
||||
intel_dp->adapter.algo_data = &intel_dp->algo;
|
||||
intel_dp->adapter.dev.parent = &intel_connector->base.kdev;
|
||||
|
||||
return i2c_dp_aux_add_bus(&intel_dp->adapter);
|
||||
}
|
||||
|
||||
static bool
|
||||
intel_dp_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode,
|
||||
struct drm_display_mode *adjusted_mode)
|
||||
{
|
||||
struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
|
||||
struct intel_dp_priv *dp_priv = intel_encoder->dev_priv;
|
||||
struct drm_device *dev = encoder->dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
|
||||
int lane_count, clock;
|
||||
int max_lane_count = intel_dp_max_lane_count(intel_encoder);
|
||||
int max_clock = intel_dp_max_link_bw(intel_encoder) == DP_LINK_BW_2_7 ? 1 : 0;
|
||||
int max_lane_count = intel_dp_max_lane_count(intel_dp);
|
||||
int max_clock = intel_dp_max_link_bw(intel_dp) == DP_LINK_BW_2_7 ? 1 : 0;
|
||||
static int bws[2] = { DP_LINK_BW_1_62, DP_LINK_BW_2_7 };
|
||||
|
||||
if ((IS_eDP(intel_encoder) || IS_PCH_eDP(dp_priv)) &&
|
||||
if ((IS_eDP(intel_dp) || IS_PCH_eDP(intel_dp)) &&
|
||||
dev_priv->panel_fixed_mode) {
|
||||
struct drm_display_mode *fixed_mode = dev_priv->panel_fixed_mode;
|
||||
|
||||
@@ -558,28 +549,28 @@ intel_dp_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode,
|
||||
for (clock = 0; clock <= max_clock; clock++) {
|
||||
int link_avail = intel_dp_max_data_rate(intel_dp_link_clock(bws[clock]), lane_count);
|
||||
|
||||
if (intel_dp_link_required(encoder->dev, intel_encoder, mode->clock)
|
||||
if (intel_dp_link_required(encoder->dev, intel_dp, mode->clock)
|
||||
<= link_avail) {
|
||||
dp_priv->link_bw = bws[clock];
|
||||
dp_priv->lane_count = lane_count;
|
||||
adjusted_mode->clock = intel_dp_link_clock(dp_priv->link_bw);
|
||||
intel_dp->link_bw = bws[clock];
|
||||
intel_dp->lane_count = lane_count;
|
||||
adjusted_mode->clock = intel_dp_link_clock(intel_dp->link_bw);
|
||||
DRM_DEBUG_KMS("Display port link bw %02x lane "
|
||||
"count %d clock %d\n",
|
||||
dp_priv->link_bw, dp_priv->lane_count,
|
||||
intel_dp->link_bw, intel_dp->lane_count,
|
||||
adjusted_mode->clock);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (IS_eDP(intel_encoder) || IS_PCH_eDP(dp_priv)) {
|
||||
if (IS_eDP(intel_dp) || IS_PCH_eDP(intel_dp)) {
|
||||
/* okay we failed just pick the highest */
|
||||
dp_priv->lane_count = max_lane_count;
|
||||
dp_priv->link_bw = bws[max_clock];
|
||||
adjusted_mode->clock = intel_dp_link_clock(dp_priv->link_bw);
|
||||
intel_dp->lane_count = max_lane_count;
|
||||
intel_dp->link_bw = bws[max_clock];
|
||||
adjusted_mode->clock = intel_dp_link_clock(intel_dp->link_bw);
|
||||
DRM_DEBUG_KMS("Force picking display port link bw %02x lane "
|
||||
"count %d clock %d\n",
|
||||
dp_priv->link_bw, dp_priv->lane_count,
|
||||
intel_dp->link_bw, intel_dp->lane_count,
|
||||
adjusted_mode->clock);
|
||||
return true;
|
||||
}
|
||||
@@ -626,17 +617,14 @@ bool intel_pch_has_edp(struct drm_crtc *crtc)
|
||||
struct drm_encoder *encoder;
|
||||
|
||||
list_for_each_entry(encoder, &mode_config->encoder_list, head) {
|
||||
struct intel_encoder *intel_encoder;
|
||||
struct intel_dp_priv *dp_priv;
|
||||
struct intel_dp *intel_dp;
|
||||
|
||||
if (!encoder || encoder->crtc != crtc)
|
||||
if (encoder->crtc != crtc)
|
||||
continue;
|
||||
|
||||
intel_encoder = enc_to_intel_encoder(encoder);
|
||||
dp_priv = intel_encoder->dev_priv;
|
||||
|
||||
if (intel_encoder->type == INTEL_OUTPUT_DISPLAYPORT)
|
||||
return dp_priv->is_pch_edp;
|
||||
intel_dp = enc_to_intel_dp(encoder);
|
||||
if (intel_dp->base.type == INTEL_OUTPUT_DISPLAYPORT)
|
||||
return intel_dp->is_pch_edp;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -657,18 +645,15 @@ intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode,
|
||||
* Find the lane count in the intel_encoder private
|
||||
*/
|
||||
list_for_each_entry(encoder, &mode_config->encoder_list, head) {
|
||||
struct intel_encoder *intel_encoder;
|
||||
struct intel_dp_priv *dp_priv;
|
||||
struct intel_dp *intel_dp;
|
||||
|
||||
if (encoder->crtc != crtc)
|
||||
continue;
|
||||
|
||||
intel_encoder = enc_to_intel_encoder(encoder);
|
||||
dp_priv = intel_encoder->dev_priv;
|
||||
|
||||
if (intel_encoder->type == INTEL_OUTPUT_DISPLAYPORT) {
|
||||
lane_count = dp_priv->lane_count;
|
||||
if (IS_PCH_eDP(dp_priv))
|
||||
intel_dp = enc_to_intel_dp(encoder);
|
||||
if (intel_dp->base.type == INTEL_OUTPUT_DISPLAYPORT) {
|
||||
lane_count = intel_dp->lane_count;
|
||||
if (IS_PCH_eDP(intel_dp))
|
||||
bpp = dev_priv->edp_bpp;
|
||||
break;
|
||||
}
|
||||
@@ -724,61 +709,60 @@ intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
|
||||
struct drm_display_mode *adjusted_mode)
|
||||
{
|
||||
struct drm_device *dev = encoder->dev;
|
||||
struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
|
||||
struct intel_dp_priv *dp_priv = intel_encoder->dev_priv;
|
||||
struct drm_crtc *crtc = intel_encoder->enc.crtc;
|
||||
struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
|
||||
struct drm_crtc *crtc = intel_dp->base.enc.crtc;
|
||||
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
||||
|
||||
dp_priv->DP = (DP_VOLTAGE_0_4 |
|
||||
intel_dp->DP = (DP_VOLTAGE_0_4 |
|
||||
DP_PRE_EMPHASIS_0);
|
||||
|
||||
if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC)
|
||||
dp_priv->DP |= DP_SYNC_HS_HIGH;
|
||||
intel_dp->DP |= DP_SYNC_HS_HIGH;
|
||||
if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC)
|
||||
dp_priv->DP |= DP_SYNC_VS_HIGH;
|
||||
intel_dp->DP |= DP_SYNC_VS_HIGH;
|
||||
|
||||
if (HAS_PCH_CPT(dev) && !IS_eDP(intel_encoder))
|
||||
dp_priv->DP |= DP_LINK_TRAIN_OFF_CPT;
|
||||
if (HAS_PCH_CPT(dev) && !IS_eDP(intel_dp))
|
||||
intel_dp->DP |= DP_LINK_TRAIN_OFF_CPT;
|
||||
else
|
||||
dp_priv->DP |= DP_LINK_TRAIN_OFF;
|
||||
intel_dp->DP |= DP_LINK_TRAIN_OFF;
|
||||
|
||||
switch (dp_priv->lane_count) {
|
||||
switch (intel_dp->lane_count) {
|
||||
case 1:
|
||||
dp_priv->DP |= DP_PORT_WIDTH_1;
|
||||
intel_dp->DP |= DP_PORT_WIDTH_1;
|
||||
break;
|
||||
case 2:
|
||||
dp_priv->DP |= DP_PORT_WIDTH_2;
|
||||
intel_dp->DP |= DP_PORT_WIDTH_2;
|
||||
break;
|
||||
case 4:
|
||||
dp_priv->DP |= DP_PORT_WIDTH_4;
|
||||
intel_dp->DP |= DP_PORT_WIDTH_4;
|
||||
break;
|
||||
}
|
||||
if (dp_priv->has_audio)
|
||||
dp_priv->DP |= DP_AUDIO_OUTPUT_ENABLE;
|
||||
if (intel_dp->has_audio)
|
||||
intel_dp->DP |= DP_AUDIO_OUTPUT_ENABLE;
|
||||
|
||||
memset(dp_priv->link_configuration, 0, DP_LINK_CONFIGURATION_SIZE);
|
||||
dp_priv->link_configuration[0] = dp_priv->link_bw;
|
||||
dp_priv->link_configuration[1] = dp_priv->lane_count;
|
||||
memset(intel_dp->link_configuration, 0, DP_LINK_CONFIGURATION_SIZE);
|
||||
intel_dp->link_configuration[0] = intel_dp->link_bw;
|
||||
intel_dp->link_configuration[1] = intel_dp->lane_count;
|
||||
|
||||
/*
|
||||
* Check for DPCD version > 1.1 and enhanced framing support
|
||||
*/
|
||||
if (dp_priv->dpcd[0] >= 0x11 && (dp_priv->dpcd[2] & DP_ENHANCED_FRAME_CAP)) {
|
||||
dp_priv->link_configuration[1] |= DP_LANE_COUNT_ENHANCED_FRAME_EN;
|
||||
dp_priv->DP |= DP_ENHANCED_FRAMING;
|
||||
if (intel_dp->dpcd[0] >= 0x11 && (intel_dp->dpcd[2] & DP_ENHANCED_FRAME_CAP)) {
|
||||
intel_dp->link_configuration[1] |= DP_LANE_COUNT_ENHANCED_FRAME_EN;
|
||||
intel_dp->DP |= DP_ENHANCED_FRAMING;
|
||||
}
|
||||
|
||||
/* CPT DP's pipe select is decided in TRANS_DP_CTL */
|
||||
if (intel_crtc->pipe == 1 && !HAS_PCH_CPT(dev))
|
||||
dp_priv->DP |= DP_PIPEB_SELECT;
|
||||
intel_dp->DP |= DP_PIPEB_SELECT;
|
||||
|
||||
if (IS_eDP(intel_encoder)) {
|
||||
if (IS_eDP(intel_dp)) {
|
||||
/* don't miss out required setting for eDP */
|
||||
dp_priv->DP |= DP_PLL_ENABLE;
|
||||
intel_dp->DP |= DP_PLL_ENABLE;
|
||||
if (adjusted_mode->clock < 200000)
|
||||
dp_priv->DP |= DP_PLL_FREQ_160MHZ;
|
||||
intel_dp->DP |= DP_PLL_FREQ_160MHZ;
|
||||
else
|
||||
dp_priv->DP |= DP_PLL_FREQ_270MHZ;
|
||||
intel_dp->DP |= DP_PLL_FREQ_270MHZ;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -852,30 +836,29 @@ static void ironlake_edp_backlight_off (struct drm_device *dev)
|
||||
static void
|
||||
intel_dp_dpms(struct drm_encoder *encoder, int mode)
|
||||
{
|
||||
struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
|
||||
struct intel_dp_priv *dp_priv = intel_encoder->dev_priv;
|
||||
struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
|
||||
struct drm_device *dev = encoder->dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
uint32_t dp_reg = I915_READ(dp_priv->output_reg);
|
||||
uint32_t dp_reg = I915_READ(intel_dp->output_reg);
|
||||
|
||||
if (mode != DRM_MODE_DPMS_ON) {
|
||||
if (dp_reg & DP_PORT_EN) {
|
||||
intel_dp_link_down(intel_encoder, dp_priv->DP);
|
||||
if (IS_eDP(intel_encoder) || IS_PCH_eDP(dp_priv)) {
|
||||
intel_dp_link_down(intel_dp);
|
||||
if (IS_eDP(intel_dp) || IS_PCH_eDP(intel_dp)) {
|
||||
ironlake_edp_backlight_off(dev);
|
||||
ironlake_edp_panel_off(dev);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (!(dp_reg & DP_PORT_EN)) {
|
||||
intel_dp_link_train(intel_encoder, dp_priv->DP, dp_priv->link_configuration);
|
||||
if (IS_eDP(intel_encoder) || IS_PCH_eDP(dp_priv)) {
|
||||
intel_dp_link_train(intel_dp);
|
||||
if (IS_eDP(intel_dp) || IS_PCH_eDP(intel_dp)) {
|
||||
ironlake_edp_panel_on(dev);
|
||||
ironlake_edp_backlight_on(dev);
|
||||
}
|
||||
}
|
||||
}
|
||||
dp_priv->dpms_mode = mode;
|
||||
intel_dp->dpms_mode = mode;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -883,12 +866,12 @@ intel_dp_dpms(struct drm_encoder *encoder, int mode)
|
||||
* link status information
|
||||
*/
|
||||
static bool
|
||||
intel_dp_get_link_status(struct intel_encoder *intel_encoder,
|
||||
intel_dp_get_link_status(struct intel_dp *intel_dp,
|
||||
uint8_t link_status[DP_LINK_STATUS_SIZE])
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = intel_dp_aux_native_read(intel_encoder,
|
||||
ret = intel_dp_aux_native_read(intel_dp,
|
||||
DP_LANE0_1_STATUS,
|
||||
link_status, DP_LINK_STATUS_SIZE);
|
||||
if (ret != DP_LINK_STATUS_SIZE)
|
||||
@@ -965,7 +948,7 @@ intel_dp_pre_emphasis_max(uint8_t voltage_swing)
|
||||
}
|
||||
|
||||
static void
|
||||
intel_get_adjust_train(struct intel_encoder *intel_encoder,
|
||||
intel_get_adjust_train(struct intel_dp *intel_dp,
|
||||
uint8_t link_status[DP_LINK_STATUS_SIZE],
|
||||
int lane_count,
|
||||
uint8_t train_set[4])
|
||||
@@ -1101,27 +1084,26 @@ intel_channel_eq_ok(uint8_t link_status[DP_LINK_STATUS_SIZE], int lane_count)
|
||||
}
|
||||
|
||||
static bool
|
||||
intel_dp_set_link_train(struct intel_encoder *intel_encoder,
|
||||
intel_dp_set_link_train(struct intel_dp *intel_dp,
|
||||
uint32_t dp_reg_value,
|
||||
uint8_t dp_train_pat,
|
||||
uint8_t train_set[4],
|
||||
bool first)
|
||||
{
|
||||
struct drm_device *dev = intel_encoder->enc.dev;
|
||||
struct drm_device *dev = intel_dp->base.enc.dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct intel_dp_priv *dp_priv = intel_encoder->dev_priv;
|
||||
int ret;
|
||||
|
||||
I915_WRITE(dp_priv->output_reg, dp_reg_value);
|
||||
POSTING_READ(dp_priv->output_reg);
|
||||
I915_WRITE(intel_dp->output_reg, dp_reg_value);
|
||||
POSTING_READ(intel_dp->output_reg);
|
||||
if (first)
|
||||
intel_wait_for_vblank(dev);
|
||||
|
||||
intel_dp_aux_native_write_1(intel_encoder,
|
||||
intel_dp_aux_native_write_1(intel_dp,
|
||||
DP_TRAINING_PATTERN_SET,
|
||||
dp_train_pat);
|
||||
|
||||
ret = intel_dp_aux_native_write(intel_encoder,
|
||||
ret = intel_dp_aux_native_write(intel_dp,
|
||||
DP_TRAINING_LANE0_SET, train_set, 4);
|
||||
if (ret != 4)
|
||||
return false;
|
||||
@@ -1130,12 +1112,10 @@ intel_dp_set_link_train(struct intel_encoder *intel_encoder,
|
||||
}
|
||||
|
||||
static void
|
||||
intel_dp_link_train(struct intel_encoder *intel_encoder, uint32_t DP,
|
||||
uint8_t link_configuration[DP_LINK_CONFIGURATION_SIZE])
|
||||
intel_dp_link_train(struct intel_dp *intel_dp)
|
||||
{
|
||||
struct drm_device *dev = intel_encoder->enc.dev;
|
||||
struct drm_device *dev = intel_dp->base.enc.dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct intel_dp_priv *dp_priv = intel_encoder->dev_priv;
|
||||
uint8_t train_set[4];
|
||||
uint8_t link_status[DP_LINK_STATUS_SIZE];
|
||||
int i;
|
||||
@@ -1145,13 +1125,15 @@ intel_dp_link_train(struct intel_encoder *intel_encoder, uint32_t DP,
|
||||
bool first = true;
|
||||
int tries;
|
||||
u32 reg;
|
||||
uint32_t DP = intel_dp->DP;
|
||||
|
||||
/* Write the link configuration data */
|
||||
intel_dp_aux_native_write(intel_encoder, DP_LINK_BW_SET,
|
||||
link_configuration, DP_LINK_CONFIGURATION_SIZE);
|
||||
intel_dp_aux_native_write(intel_dp, DP_LINK_BW_SET,
|
||||
intel_dp->link_configuration,
|
||||
DP_LINK_CONFIGURATION_SIZE);
|
||||
|
||||
DP |= DP_PORT_EN;
|
||||
if (HAS_PCH_CPT(dev) && !IS_eDP(intel_encoder))
|
||||
if (HAS_PCH_CPT(dev) && !IS_eDP(intel_dp))
|
||||
DP &= ~DP_LINK_TRAIN_MASK_CPT;
|
||||
else
|
||||
DP &= ~DP_LINK_TRAIN_MASK;
|
||||
@@ -1162,39 +1144,39 @@ intel_dp_link_train(struct intel_encoder *intel_encoder, uint32_t DP,
|
||||
for (;;) {
|
||||
/* Use train_set[0] to set the voltage and pre emphasis values */
|
||||
uint32_t signal_levels;
|
||||
if (IS_GEN6(dev) && IS_eDP(intel_encoder)) {
|
||||
if (IS_GEN6(dev) && IS_eDP(intel_dp)) {
|
||||
signal_levels = intel_gen6_edp_signal_levels(train_set[0]);
|
||||
DP = (DP & ~EDP_LINK_TRAIN_VOL_EMP_MASK_SNB) | signal_levels;
|
||||
} else {
|
||||
signal_levels = intel_dp_signal_levels(train_set[0], dp_priv->lane_count);
|
||||
signal_levels = intel_dp_signal_levels(train_set[0], intel_dp->lane_count);
|
||||
DP = (DP & ~(DP_VOLTAGE_MASK|DP_PRE_EMPHASIS_MASK)) | signal_levels;
|
||||
}
|
||||
|
||||
if (HAS_PCH_CPT(dev) && !IS_eDP(intel_encoder))
|
||||
if (HAS_PCH_CPT(dev) && !IS_eDP(intel_dp))
|
||||
reg = DP | DP_LINK_TRAIN_PAT_1_CPT;
|
||||
else
|
||||
reg = DP | DP_LINK_TRAIN_PAT_1;
|
||||
|
||||
if (!intel_dp_set_link_train(intel_encoder, reg,
|
||||
if (!intel_dp_set_link_train(intel_dp, reg,
|
||||
DP_TRAINING_PATTERN_1, train_set, first))
|
||||
break;
|
||||
first = false;
|
||||
/* Set training pattern 1 */
|
||||
|
||||
udelay(100);
|
||||
if (!intel_dp_get_link_status(intel_encoder, link_status))
|
||||
if (!intel_dp_get_link_status(intel_dp, link_status))
|
||||
break;
|
||||
|
||||
if (intel_clock_recovery_ok(link_status, dp_priv->lane_count)) {
|
||||
if (intel_clock_recovery_ok(link_status, intel_dp->lane_count)) {
|
||||
clock_recovery = true;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Check to see if we've tried the max voltage */
|
||||
for (i = 0; i < dp_priv->lane_count; i++)
|
||||
for (i = 0; i < intel_dp->lane_count; i++)
|
||||
if ((train_set[i] & DP_TRAIN_MAX_SWING_REACHED) == 0)
|
||||
break;
|
||||
if (i == dp_priv->lane_count)
|
||||
if (i == intel_dp->lane_count)
|
||||
break;
|
||||
|
||||
/* Check to see if we've tried the same voltage 5 times */
|
||||
@@ -1207,7 +1189,7 @@ intel_dp_link_train(struct intel_encoder *intel_encoder, uint32_t DP,
|
||||
voltage = train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK;
|
||||
|
||||
/* Compute new train_set as requested by target */
|
||||
intel_get_adjust_train(intel_encoder, link_status, dp_priv->lane_count, train_set);
|
||||
intel_get_adjust_train(intel_dp, link_status, intel_dp->lane_count, train_set);
|
||||
}
|
||||
|
||||
/* channel equalization */
|
||||
@@ -1217,30 +1199,30 @@ intel_dp_link_train(struct intel_encoder *intel_encoder, uint32_t DP,
|
||||
/* Use train_set[0] to set the voltage and pre emphasis values */
|
||||
uint32_t signal_levels;
|
||||
|
||||
if (IS_GEN6(dev) && IS_eDP(intel_encoder)) {
|
||||
if (IS_GEN6(dev) && IS_eDP(intel_dp)) {
|
||||
signal_levels = intel_gen6_edp_signal_levels(train_set[0]);
|
||||
DP = (DP & ~EDP_LINK_TRAIN_VOL_EMP_MASK_SNB) | signal_levels;
|
||||
} else {
|
||||
signal_levels = intel_dp_signal_levels(train_set[0], dp_priv->lane_count);
|
||||
signal_levels = intel_dp_signal_levels(train_set[0], intel_dp->lane_count);
|
||||
DP = (DP & ~(DP_VOLTAGE_MASK|DP_PRE_EMPHASIS_MASK)) | signal_levels;
|
||||
}
|
||||
|
||||
if (HAS_PCH_CPT(dev) && !IS_eDP(intel_encoder))
|
||||
if (HAS_PCH_CPT(dev) && !IS_eDP(intel_dp))
|
||||
reg = DP | DP_LINK_TRAIN_PAT_2_CPT;
|
||||
else
|
||||
reg = DP | DP_LINK_TRAIN_PAT_2;
|
||||
|
||||
/* channel eq pattern */
|
||||
if (!intel_dp_set_link_train(intel_encoder, reg,
|
||||
if (!intel_dp_set_link_train(intel_dp, reg,
|
||||
DP_TRAINING_PATTERN_2, train_set,
|
||||
false))
|
||||
break;
|
||||
|
||||
udelay(400);
|
||||
if (!intel_dp_get_link_status(intel_encoder, link_status))
|
||||
if (!intel_dp_get_link_status(intel_dp, link_status))
|
||||
break;
|
||||
|
||||
if (intel_channel_eq_ok(link_status, dp_priv->lane_count)) {
|
||||
if (intel_channel_eq_ok(link_status, intel_dp->lane_count)) {
|
||||
channel_eq = true;
|
||||
break;
|
||||
}
|
||||
@@ -1250,53 +1232,53 @@ intel_dp_link_train(struct intel_encoder *intel_encoder, uint32_t DP,
|
||||
break;
|
||||
|
||||
/* Compute new train_set as requested by target */
|
||||
intel_get_adjust_train(intel_encoder, link_status, dp_priv->lane_count, train_set);
|
||||
intel_get_adjust_train(intel_dp, link_status, intel_dp->lane_count, train_set);
|
||||
++tries;
|
||||
}
|
||||
|
||||
if (HAS_PCH_CPT(dev) && !IS_eDP(intel_encoder))
|
||||
if (HAS_PCH_CPT(dev) && !IS_eDP(intel_dp))
|
||||
reg = DP | DP_LINK_TRAIN_OFF_CPT;
|
||||
else
|
||||
reg = DP | DP_LINK_TRAIN_OFF;
|
||||
|
||||
I915_WRITE(dp_priv->output_reg, reg);
|
||||
POSTING_READ(dp_priv->output_reg);
|
||||
intel_dp_aux_native_write_1(intel_encoder,
|
||||
I915_WRITE(intel_dp->output_reg, reg);
|
||||
POSTING_READ(intel_dp->output_reg);
|
||||
intel_dp_aux_native_write_1(intel_dp,
|
||||
DP_TRAINING_PATTERN_SET, DP_TRAINING_PATTERN_DISABLE);
|
||||
}
|
||||
|
||||
static void
|
||||
intel_dp_link_down(struct intel_encoder *intel_encoder, uint32_t DP)
|
||||
intel_dp_link_down(struct intel_dp *intel_dp)
|
||||
{
|
||||
struct drm_device *dev = intel_encoder->enc.dev;
|
||||
struct drm_device *dev = intel_dp->base.enc.dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct intel_dp_priv *dp_priv = intel_encoder->dev_priv;
|
||||
uint32_t DP = intel_dp->DP;
|
||||
|
||||
DRM_DEBUG_KMS("\n");
|
||||
|
||||
if (IS_eDP(intel_encoder)) {
|
||||
if (IS_eDP(intel_dp)) {
|
||||
DP &= ~DP_PLL_ENABLE;
|
||||
I915_WRITE(dp_priv->output_reg, DP);
|
||||
POSTING_READ(dp_priv->output_reg);
|
||||
I915_WRITE(intel_dp->output_reg, DP);
|
||||
POSTING_READ(intel_dp->output_reg);
|
||||
udelay(100);
|
||||
}
|
||||
|
||||
if (HAS_PCH_CPT(dev) && !IS_eDP(intel_encoder)) {
|
||||
if (HAS_PCH_CPT(dev) && !IS_eDP(intel_dp)) {
|
||||
DP &= ~DP_LINK_TRAIN_MASK_CPT;
|
||||
I915_WRITE(dp_priv->output_reg, DP | DP_LINK_TRAIN_PAT_IDLE_CPT);
|
||||
POSTING_READ(dp_priv->output_reg);
|
||||
I915_WRITE(intel_dp->output_reg, DP | DP_LINK_TRAIN_PAT_IDLE_CPT);
|
||||
POSTING_READ(intel_dp->output_reg);
|
||||
} else {
|
||||
DP &= ~DP_LINK_TRAIN_MASK;
|
||||
I915_WRITE(dp_priv->output_reg, DP | DP_LINK_TRAIN_PAT_IDLE);
|
||||
POSTING_READ(dp_priv->output_reg);
|
||||
I915_WRITE(intel_dp->output_reg, DP | DP_LINK_TRAIN_PAT_IDLE);
|
||||
POSTING_READ(intel_dp->output_reg);
|
||||
}
|
||||
|
||||
udelay(17000);
|
||||
|
||||
if (IS_eDP(intel_encoder))
|
||||
if (IS_eDP(intel_dp))
|
||||
DP |= DP_LINK_TRAIN_OFF;
|
||||
I915_WRITE(dp_priv->output_reg, DP & ~DP_PORT_EN);
|
||||
POSTING_READ(dp_priv->output_reg);
|
||||
I915_WRITE(intel_dp->output_reg, DP & ~DP_PORT_EN);
|
||||
POSTING_READ(intel_dp->output_reg);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1309,41 +1291,39 @@ intel_dp_link_down(struct intel_encoder *intel_encoder, uint32_t DP)
|
||||
*/
|
||||
|
||||
static void
|
||||
intel_dp_check_link_status(struct intel_encoder *intel_encoder)
|
||||
intel_dp_check_link_status(struct intel_dp *intel_dp)
|
||||
{
|
||||
struct intel_dp_priv *dp_priv = intel_encoder->dev_priv;
|
||||
uint8_t link_status[DP_LINK_STATUS_SIZE];
|
||||
|
||||
if (!intel_encoder->enc.crtc)
|
||||
if (!intel_dp->base.enc.crtc)
|
||||
return;
|
||||
|
||||
if (!intel_dp_get_link_status(intel_encoder, link_status)) {
|
||||
intel_dp_link_down(intel_encoder, dp_priv->DP);
|
||||
if (!intel_dp_get_link_status(intel_dp, link_status)) {
|
||||
intel_dp_link_down(intel_dp);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!intel_channel_eq_ok(link_status, dp_priv->lane_count))
|
||||
intel_dp_link_train(intel_encoder, dp_priv->DP, dp_priv->link_configuration);
|
||||
if (!intel_channel_eq_ok(link_status, intel_dp->lane_count))
|
||||
intel_dp_link_train(intel_dp);
|
||||
}
|
||||
|
||||
static enum drm_connector_status
|
||||
ironlake_dp_detect(struct drm_connector *connector)
|
||||
{
|
||||
struct drm_encoder *encoder = intel_attached_encoder(connector);
|
||||
struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
|
||||
struct intel_dp_priv *dp_priv = intel_encoder->dev_priv;
|
||||
struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
|
||||
enum drm_connector_status status;
|
||||
|
||||
status = connector_status_disconnected;
|
||||
if (intel_dp_aux_native_read(intel_encoder,
|
||||
0x000, dp_priv->dpcd,
|
||||
sizeof (dp_priv->dpcd)) == sizeof (dp_priv->dpcd))
|
||||
if (intel_dp_aux_native_read(intel_dp,
|
||||
0x000, intel_dp->dpcd,
|
||||
sizeof (intel_dp->dpcd)) == sizeof (intel_dp->dpcd))
|
||||
{
|
||||
if (dp_priv->dpcd[0] != 0)
|
||||
if (intel_dp->dpcd[0] != 0)
|
||||
status = connector_status_connected;
|
||||
}
|
||||
DRM_DEBUG_KMS("DPCD: %hx%hx%hx%hx\n", dp_priv->dpcd[0],
|
||||
dp_priv->dpcd[1], dp_priv->dpcd[2], dp_priv->dpcd[3]);
|
||||
DRM_DEBUG_KMS("DPCD: %hx%hx%hx%hx\n", intel_dp->dpcd[0],
|
||||
intel_dp->dpcd[1], intel_dp->dpcd[2], intel_dp->dpcd[3]);
|
||||
return status;
|
||||
}
|
||||
|
||||
@@ -1357,19 +1337,18 @@ static enum drm_connector_status
|
||||
intel_dp_detect(struct drm_connector *connector)
|
||||
{
|
||||
struct drm_encoder *encoder = intel_attached_encoder(connector);
|
||||
struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
|
||||
struct drm_device *dev = intel_encoder->enc.dev;
|
||||
struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
|
||||
struct drm_device *dev = intel_dp->base.enc.dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct intel_dp_priv *dp_priv = intel_encoder->dev_priv;
|
||||
uint32_t temp, bit;
|
||||
enum drm_connector_status status;
|
||||
|
||||
dp_priv->has_audio = false;
|
||||
intel_dp->has_audio = false;
|
||||
|
||||
if (HAS_PCH_SPLIT(dev))
|
||||
return ironlake_dp_detect(connector);
|
||||
|
||||
switch (dp_priv->output_reg) {
|
||||
switch (intel_dp->output_reg) {
|
||||
case DP_B:
|
||||
bit = DPB_HOTPLUG_INT_STATUS;
|
||||
break;
|
||||
@@ -1389,11 +1368,11 @@ intel_dp_detect(struct drm_connector *connector)
|
||||
return connector_status_disconnected;
|
||||
|
||||
status = connector_status_disconnected;
|
||||
if (intel_dp_aux_native_read(intel_encoder,
|
||||
0x000, dp_priv->dpcd,
|
||||
sizeof (dp_priv->dpcd)) == sizeof (dp_priv->dpcd))
|
||||
if (intel_dp_aux_native_read(intel_dp,
|
||||
0x000, intel_dp->dpcd,
|
||||
sizeof (intel_dp->dpcd)) == sizeof (intel_dp->dpcd))
|
||||
{
|
||||
if (dp_priv->dpcd[0] != 0)
|
||||
if (intel_dp->dpcd[0] != 0)
|
||||
status = connector_status_connected;
|
||||
}
|
||||
return status;
|
||||
@@ -1402,18 +1381,17 @@ intel_dp_detect(struct drm_connector *connector)
|
||||
static int intel_dp_get_modes(struct drm_connector *connector)
|
||||
{
|
||||
struct drm_encoder *encoder = intel_attached_encoder(connector);
|
||||
struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
|
||||
struct drm_device *dev = intel_encoder->enc.dev;
|
||||
struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
|
||||
struct drm_device *dev = intel_dp->base.enc.dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct intel_dp_priv *dp_priv = intel_encoder->dev_priv;
|
||||
int ret;
|
||||
|
||||
/* We should parse the EDID data and find out if it has an audio sink
|
||||
*/
|
||||
|
||||
ret = intel_ddc_get_modes(connector, intel_encoder->ddc_bus);
|
||||
ret = intel_ddc_get_modes(connector, intel_dp->base.ddc_bus);
|
||||
if (ret) {
|
||||
if ((IS_eDP(intel_encoder) || IS_PCH_eDP(dp_priv)) &&
|
||||
if ((IS_eDP(intel_dp) || IS_PCH_eDP(intel_dp)) &&
|
||||
!dev_priv->panel_fixed_mode) {
|
||||
struct drm_display_mode *newmode;
|
||||
list_for_each_entry(newmode, &connector->probed_modes,
|
||||
@@ -1430,7 +1408,7 @@ static int intel_dp_get_modes(struct drm_connector *connector)
|
||||
}
|
||||
|
||||
/* if eDP has no EDID, try to use fixed panel mode from VBT */
|
||||
if (IS_eDP(intel_encoder) || IS_PCH_eDP(dp_priv)) {
|
||||
if (IS_eDP(intel_dp) || IS_PCH_eDP(intel_dp)) {
|
||||
if (dev_priv->panel_fixed_mode != NULL) {
|
||||
struct drm_display_mode *mode;
|
||||
mode = drm_mode_duplicate(dev, dev_priv->panel_fixed_mode);
|
||||
@@ -1470,27 +1448,17 @@ static const struct drm_connector_helper_funcs intel_dp_connector_helper_funcs =
|
||||
.best_encoder = intel_attached_encoder,
|
||||
};
|
||||
|
||||
static void intel_dp_enc_destroy(struct drm_encoder *encoder)
|
||||
{
|
||||
struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
|
||||
|
||||
if (intel_encoder->i2c_bus)
|
||||
intel_i2c_destroy(intel_encoder->i2c_bus);
|
||||
drm_encoder_cleanup(encoder);
|
||||
kfree(intel_encoder);
|
||||
}
|
||||
|
||||
static const struct drm_encoder_funcs intel_dp_enc_funcs = {
|
||||
.destroy = intel_dp_enc_destroy,
|
||||
.destroy = intel_encoder_destroy,
|
||||
};
|
||||
|
||||
void
|
||||
intel_dp_hot_plug(struct intel_encoder *intel_encoder)
|
||||
{
|
||||
struct intel_dp_priv *dp_priv = intel_encoder->dev_priv;
|
||||
struct intel_dp *intel_dp = container_of(intel_encoder, struct intel_dp, base);
|
||||
|
||||
if (dp_priv->dpms_mode == DRM_MODE_DPMS_ON)
|
||||
intel_dp_check_link_status(intel_encoder);
|
||||
if (intel_dp->dpms_mode == DRM_MODE_DPMS_ON)
|
||||
intel_dp_check_link_status(intel_dp);
|
||||
}
|
||||
|
||||
/* Return which DP Port should be selected for Transcoder DP control */
|
||||
@@ -1500,18 +1468,18 @@ intel_trans_dp_port_sel (struct drm_crtc *crtc)
|
||||
struct drm_device *dev = crtc->dev;
|
||||
struct drm_mode_config *mode_config = &dev->mode_config;
|
||||
struct drm_encoder *encoder;
|
||||
struct intel_encoder *intel_encoder = NULL;
|
||||
|
||||
list_for_each_entry(encoder, &mode_config->encoder_list, head) {
|
||||
struct intel_dp *intel_dp;
|
||||
|
||||
if (encoder->crtc != crtc)
|
||||
continue;
|
||||
|
||||
intel_encoder = enc_to_intel_encoder(encoder);
|
||||
if (intel_encoder->type == INTEL_OUTPUT_DISPLAYPORT) {
|
||||
struct intel_dp_priv *dp_priv = intel_encoder->dev_priv;
|
||||
return dp_priv->output_reg;
|
||||
}
|
||||
intel_dp = enc_to_intel_dp(encoder);
|
||||
if (intel_dp->base.type == INTEL_OUTPUT_DISPLAYPORT)
|
||||
return intel_dp->output_reg;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -1540,30 +1508,28 @@ intel_dp_init(struct drm_device *dev, int output_reg)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct drm_connector *connector;
|
||||
struct intel_dp *intel_dp;
|
||||
struct intel_encoder *intel_encoder;
|
||||
struct intel_connector *intel_connector;
|
||||
struct intel_dp_priv *dp_priv;
|
||||
const char *name = NULL;
|
||||
int type;
|
||||
|
||||
intel_encoder = kcalloc(sizeof(struct intel_encoder) +
|
||||
sizeof(struct intel_dp_priv), 1, GFP_KERNEL);
|
||||
if (!intel_encoder)
|
||||
intel_dp = kzalloc(sizeof(struct intel_dp), GFP_KERNEL);
|
||||
if (!intel_dp)
|
||||
return;
|
||||
|
||||
intel_connector = kzalloc(sizeof(struct intel_connector), GFP_KERNEL);
|
||||
if (!intel_connector) {
|
||||
kfree(intel_encoder);
|
||||
kfree(intel_dp);
|
||||
return;
|
||||
}
|
||||
intel_encoder = &intel_dp->base;
|
||||
|
||||
dp_priv = (struct intel_dp_priv *)(intel_encoder + 1);
|
||||
|
||||
if (HAS_PCH_SPLIT(dev) && (output_reg == PCH_DP_D))
|
||||
if (HAS_PCH_SPLIT(dev) && output_reg == PCH_DP_D)
|
||||
if (intel_dpd_is_edp(dev))
|
||||
dp_priv->is_pch_edp = true;
|
||||
intel_dp->is_pch_edp = true;
|
||||
|
||||
if (output_reg == DP_A || IS_PCH_eDP(dp_priv)) {
|
||||
if (output_reg == DP_A || IS_PCH_eDP(intel_dp)) {
|
||||
type = DRM_MODE_CONNECTOR_eDP;
|
||||
intel_encoder->type = INTEL_OUTPUT_EDP;
|
||||
} else {
|
||||
@@ -1584,18 +1550,16 @@ intel_dp_init(struct drm_device *dev, int output_reg)
|
||||
else if (output_reg == DP_D || output_reg == PCH_DP_D)
|
||||
intel_encoder->clone_mask = (1 << INTEL_DP_D_CLONE_BIT);
|
||||
|
||||
if (IS_eDP(intel_encoder))
|
||||
if (IS_eDP(intel_dp))
|
||||
intel_encoder->clone_mask = (1 << INTEL_EDP_CLONE_BIT);
|
||||
|
||||
intel_encoder->crtc_mask = (1 << 0) | (1 << 1);
|
||||
connector->interlace_allowed = true;
|
||||
connector->doublescan_allowed = 0;
|
||||
|
||||
dp_priv->intel_encoder = intel_encoder;
|
||||
dp_priv->output_reg = output_reg;
|
||||
dp_priv->has_audio = false;
|
||||
dp_priv->dpms_mode = DRM_MODE_DPMS_ON;
|
||||
intel_encoder->dev_priv = dp_priv;
|
||||
intel_dp->output_reg = output_reg;
|
||||
intel_dp->has_audio = false;
|
||||
intel_dp->dpms_mode = DRM_MODE_DPMS_ON;
|
||||
|
||||
drm_encoder_init(dev, &intel_encoder->enc, &intel_dp_enc_funcs,
|
||||
DRM_MODE_ENCODER_TMDS);
|
||||
@@ -1630,12 +1594,12 @@ intel_dp_init(struct drm_device *dev, int output_reg)
|
||||
break;
|
||||
}
|
||||
|
||||
intel_dp_i2c_init(intel_encoder, intel_connector, name);
|
||||
intel_dp_i2c_init(intel_dp, intel_connector, name);
|
||||
|
||||
intel_encoder->ddc_bus = &dp_priv->adapter;
|
||||
intel_encoder->ddc_bus = &intel_dp->adapter;
|
||||
intel_encoder->hot_plug = intel_dp_hot_plug;
|
||||
|
||||
if (output_reg == DP_A || IS_PCH_eDP(dp_priv)) {
|
||||
if (output_reg == DP_A || IS_PCH_eDP(intel_dp)) {
|
||||
/* initialize panel mode from VBT if available for eDP */
|
||||
if (dev_priv->lfp_lvds_vbt_mode) {
|
||||
dev_priv->panel_fixed_mode =
|
||||
|
Reference in New Issue
Block a user