dect
/
linux-2.6
Archived
13
0
Fork 0

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:
Chris Wilson 2010-08-04 13:50:23 +01:00 committed by Eric Anholt
parent 94113cecae
commit ea5b213ad4
10 changed files with 894 additions and 995 deletions

View File

@ -30,20 +30,17 @@
#include "intel_drv.h"
struct intel_dvo_device {
char *name;
const char *name;
int type;
/* DVOA/B/C output register */
u32 dvo_reg;
/* GPIO register used for i2c bus to control this device */
u32 gpio;
int slave_addr;
struct i2c_adapter *i2c_bus;
const struct intel_dvo_dev_ops *dev_ops;
void *dev_priv;
struct drm_display_mode *panel_fixed_mode;
bool panel_wants_dither;
struct i2c_adapter *i2c_bus;
};
struct intel_dvo_dev_ops {

View File

@ -508,17 +508,8 @@ static const struct drm_connector_helper_funcs intel_crt_connector_helper_funcs
.best_encoder = intel_attached_encoder,
};
static void intel_crt_enc_destroy(struct drm_encoder *encoder)
{
struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
intel_i2c_destroy(intel_encoder->ddc_bus);
drm_encoder_cleanup(encoder);
kfree(intel_encoder);
}
static const struct drm_encoder_funcs intel_crt_enc_funcs = {
.destroy = intel_crt_enc_destroy,
.destroy = intel_encoder_destroy,
};
void intel_crt_init(struct drm_device *dev)

View File

@ -2537,6 +2537,20 @@ void intel_encoder_commit (struct drm_encoder *encoder)
encoder_funcs->dpms(encoder, DRM_MODE_DPMS_ON);
}
void intel_encoder_destroy(struct drm_encoder *encoder)
{
struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
if (intel_encoder->ddc_bus)
intel_i2c_destroy(intel_encoder->ddc_bus);
if (intel_encoder->i2c_bus)
intel_i2c_destroy(intel_encoder->i2c_bus);
drm_encoder_cleanup(encoder);
kfree(intel_encoder);
}
static bool intel_crtc_mode_fixup(struct drm_crtc *crtc,
struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode)

View File

@ -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 =

View File

@ -102,7 +102,6 @@ struct intel_encoder {
struct i2c_adapter *ddc_bus;
bool load_detect_temp;
bool needs_tv_clock;
void *dev_priv;
void (*hot_plug)(struct intel_encoder *);
int crtc_mask;
int clone_mask;
@ -192,6 +191,7 @@ extern int intel_panel_fitter_pipe (struct drm_device *dev);
extern void intel_crtc_load_lut(struct drm_crtc *crtc);
extern void intel_encoder_prepare (struct drm_encoder *encoder);
extern void intel_encoder_commit (struct drm_encoder *encoder);
extern void intel_encoder_destroy(struct drm_encoder *encoder);
extern struct drm_encoder *intel_attached_encoder(struct drm_connector *connector);

View File

@ -38,7 +38,7 @@
#define CH7xxx_ADDR 0x76
#define TFP410_ADDR 0x38
static struct intel_dvo_device intel_dvo_devices[] = {
static const struct intel_dvo_device intel_dvo_devices[] = {
{
.type = INTEL_DVO_CHIP_TMDS,
.name = "sil164",
@ -77,20 +77,33 @@ static struct intel_dvo_device intel_dvo_devices[] = {
}
};
struct intel_dvo {
struct intel_encoder base;
struct intel_dvo_device dev;
struct drm_display_mode *panel_fixed_mode;
bool panel_wants_dither;
};
static struct intel_dvo *enc_to_intel_dvo(struct drm_encoder *encoder)
{
return container_of(enc_to_intel_encoder(encoder), struct intel_dvo, base);
}
static void intel_dvo_dpms(struct drm_encoder *encoder, int mode)
{
struct drm_i915_private *dev_priv = encoder->dev->dev_private;
struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
struct intel_dvo_device *dvo = intel_encoder->dev_priv;
u32 dvo_reg = dvo->dvo_reg;
struct intel_dvo *intel_dvo = enc_to_intel_dvo(encoder);
u32 dvo_reg = intel_dvo->dev.dvo_reg;
u32 temp = I915_READ(dvo_reg);
if (mode == DRM_MODE_DPMS_ON) {
I915_WRITE(dvo_reg, temp | DVO_ENABLE);
I915_READ(dvo_reg);
dvo->dev_ops->dpms(dvo, mode);
intel_dvo->dev.dev_ops->dpms(&intel_dvo->dev, mode);
} else {
dvo->dev_ops->dpms(dvo, mode);
intel_dvo->dev.dev_ops->dpms(&intel_dvo->dev, mode);
I915_WRITE(dvo_reg, temp & ~DVO_ENABLE);
I915_READ(dvo_reg);
}
@ -100,38 +113,36 @@ static int intel_dvo_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_dvo_device *dvo = intel_encoder->dev_priv;
struct intel_dvo *intel_dvo = enc_to_intel_dvo(encoder);
if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
return MODE_NO_DBLESCAN;
/* XXX: Validate clock range */
if (dvo->panel_fixed_mode) {
if (mode->hdisplay > dvo->panel_fixed_mode->hdisplay)
if (intel_dvo->panel_fixed_mode) {
if (mode->hdisplay > intel_dvo->panel_fixed_mode->hdisplay)
return MODE_PANEL;
if (mode->vdisplay > dvo->panel_fixed_mode->vdisplay)
if (mode->vdisplay > intel_dvo->panel_fixed_mode->vdisplay)
return MODE_PANEL;
}
return dvo->dev_ops->mode_valid(dvo, mode);
return intel_dvo->dev.dev_ops->mode_valid(&intel_dvo->dev, mode);
}
static bool intel_dvo_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_dvo_device *dvo = intel_encoder->dev_priv;
struct intel_dvo *intel_dvo = enc_to_intel_dvo(encoder);
/* If we have timings from the BIOS for the panel, put them in
* to the adjusted mode. The CRTC will be set up for this mode,
* with the panel scaling set up to source from the H/VDisplay
* of the original mode.
*/
if (dvo->panel_fixed_mode != NULL) {
#define C(x) adjusted_mode->x = dvo->panel_fixed_mode->x
if (intel_dvo->panel_fixed_mode != NULL) {
#define C(x) adjusted_mode->x = intel_dvo->panel_fixed_mode->x
C(hdisplay);
C(hsync_start);
C(hsync_end);
@ -145,8 +156,8 @@ static bool intel_dvo_mode_fixup(struct drm_encoder *encoder,
#undef C
}
if (dvo->dev_ops->mode_fixup)
return dvo->dev_ops->mode_fixup(dvo, mode, adjusted_mode);
if (intel_dvo->dev.dev_ops->mode_fixup)
return intel_dvo->dev.dev_ops->mode_fixup(&intel_dvo->dev, mode, adjusted_mode);
return true;
}
@ -158,11 +169,10 @@ static void intel_dvo_mode_set(struct drm_encoder *encoder,
struct drm_device *dev = encoder->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc);
struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
struct intel_dvo_device *dvo = intel_encoder->dev_priv;
struct intel_dvo *intel_dvo = enc_to_intel_dvo(encoder);
int pipe = intel_crtc->pipe;
u32 dvo_val;
u32 dvo_reg = dvo->dvo_reg, dvo_srcdim_reg;
u32 dvo_reg = intel_dvo->dev.dvo_reg, dvo_srcdim_reg;
int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B;
switch (dvo_reg) {
@ -178,7 +188,7 @@ static void intel_dvo_mode_set(struct drm_encoder *encoder,
break;
}
dvo->dev_ops->mode_set(dvo, mode, adjusted_mode);
intel_dvo->dev.dev_ops->mode_set(&intel_dvo->dev, mode, adjusted_mode);
/* Save the data order, since I don't know what it should be set to. */
dvo_val = I915_READ(dvo_reg) &
@ -214,40 +224,38 @@ static void intel_dvo_mode_set(struct drm_encoder *encoder,
static enum drm_connector_status intel_dvo_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_dvo_device *dvo = intel_encoder->dev_priv;
struct intel_dvo *intel_dvo = enc_to_intel_dvo(encoder);
return dvo->dev_ops->detect(dvo);
return intel_dvo->dev.dev_ops->detect(&intel_dvo->dev);
}
static int intel_dvo_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 intel_dvo_device *dvo = intel_encoder->dev_priv;
struct intel_dvo *intel_dvo = enc_to_intel_dvo(encoder);
/* We should probably have an i2c driver get_modes function for those
* devices which will have a fixed set of modes determined by the chip
* (TV-out, for example), but for now with just TMDS and LVDS,
* that's not the case.
*/
intel_ddc_get_modes(connector, intel_encoder->ddc_bus);
intel_ddc_get_modes(connector, intel_dvo->base.ddc_bus);
if (!list_empty(&connector->probed_modes))
return 1;
if (dvo->panel_fixed_mode != NULL) {
if (intel_dvo->panel_fixed_mode != NULL) {
struct drm_display_mode *mode;
mode = drm_mode_duplicate(connector->dev, dvo->panel_fixed_mode);
mode = drm_mode_duplicate(connector->dev, intel_dvo->panel_fixed_mode);
if (mode) {
drm_mode_probed_add(connector, mode);
return 1;
}
}
return 0;
}
static void intel_dvo_destroy (struct drm_connector *connector)
static void intel_dvo_destroy(struct drm_connector *connector)
{
drm_sysfs_connector_remove(connector);
drm_connector_cleanup(connector);
@ -277,28 +285,20 @@ static const struct drm_connector_helper_funcs intel_dvo_connector_helper_funcs
static void intel_dvo_enc_destroy(struct drm_encoder *encoder)
{
struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
struct intel_dvo_device *dvo = intel_encoder->dev_priv;
struct intel_dvo *intel_dvo = enc_to_intel_dvo(encoder);
if (dvo) {
if (dvo->dev_ops->destroy)
dvo->dev_ops->destroy(dvo);
if (dvo->panel_fixed_mode)
kfree(dvo->panel_fixed_mode);
}
if (intel_encoder->i2c_bus)
intel_i2c_destroy(intel_encoder->i2c_bus);
if (intel_encoder->ddc_bus)
intel_i2c_destroy(intel_encoder->ddc_bus);
drm_encoder_cleanup(encoder);
kfree(intel_encoder);
if (intel_dvo->dev.dev_ops->destroy)
intel_dvo->dev.dev_ops->destroy(&intel_dvo->dev);
kfree(intel_dvo->panel_fixed_mode);
intel_encoder_destroy(encoder);
}
static const struct drm_encoder_funcs intel_dvo_enc_funcs = {
.destroy = intel_dvo_enc_destroy,
};
/**
* Attempts to get a fixed panel timing for LVDS (currently only the i830).
*
@ -306,15 +306,13 @@ static const struct drm_encoder_funcs intel_dvo_enc_funcs = {
* chip being on DVOB/C and having multiple pipes.
*/
static struct drm_display_mode *
intel_dvo_get_current_mode (struct drm_connector *connector)
intel_dvo_get_current_mode(struct drm_connector *connector)
{
struct drm_device *dev = connector->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_encoder *encoder = intel_attached_encoder(connector);
struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
struct intel_dvo_device *dvo = intel_encoder->dev_priv;
uint32_t dvo_reg = dvo->dvo_reg;
uint32_t dvo_val = I915_READ(dvo_reg);
struct intel_dvo *intel_dvo = enc_to_intel_dvo(encoder);
uint32_t dvo_val = I915_READ(intel_dvo->dev.dvo_reg);
struct drm_display_mode *mode = NULL;
/* If the DVO port is active, that'll be the LVDS, so we can pull out
@ -327,7 +325,6 @@ intel_dvo_get_current_mode (struct drm_connector *connector)
crtc = intel_get_crtc_from_pipe(dev, pipe);
if (crtc) {
mode = intel_crtc_mode_get(dev, crtc);
if (mode) {
mode->type |= DRM_MODE_TYPE_PREFERRED;
if (dvo_val & DVO_HSYNC_ACTIVE_HIGH)
@ -337,28 +334,32 @@ intel_dvo_get_current_mode (struct drm_connector *connector)
}
}
}
return mode;
}
void intel_dvo_init(struct drm_device *dev)
{
struct intel_encoder *intel_encoder;
struct intel_dvo *intel_dvo;
struct intel_connector *intel_connector;
struct intel_dvo_device *dvo;
struct i2c_adapter *i2cbus = NULL;
int ret = 0;
int i;
int encoder_type = DRM_MODE_ENCODER_NONE;
intel_encoder = kzalloc (sizeof(struct intel_encoder), GFP_KERNEL);
if (!intel_encoder)
intel_dvo = kzalloc(sizeof(struct intel_dvo), GFP_KERNEL);
if (!intel_dvo)
return;
intel_connector = kzalloc(sizeof(struct intel_connector), GFP_KERNEL);
if (!intel_connector) {
kfree(intel_encoder);
kfree(intel_dvo);
return;
}
intel_encoder = &intel_dvo->base;
/* Set up the DDC bus */
intel_encoder->ddc_bus = intel_i2c_create(dev, GPIOD, "DVODDC_D");
if (!intel_encoder->ddc_bus)
@ -367,10 +368,9 @@ void intel_dvo_init(struct drm_device *dev)
/* Now, try to find a controller */
for (i = 0; i < ARRAY_SIZE(intel_dvo_devices); i++) {
struct drm_connector *connector = &intel_connector->base;
const struct intel_dvo_device *dvo = &intel_dvo_devices[i];
int gpio;
dvo = &intel_dvo_devices[i];
/* Allow the I2C driver info to specify the GPIO to be used in
* special cases, but otherwise default to what's defined
* in the spec.
@ -393,11 +393,8 @@ void intel_dvo_init(struct drm_device *dev)
continue;
}
if (dvo->dev_ops!= NULL)
ret = dvo->dev_ops->init(dvo, i2cbus);
else
ret = false;
intel_dvo->dev = *dvo;
ret = dvo->dev_ops->init(&intel_dvo->dev, i2cbus);
if (!ret)
continue;
@ -429,9 +426,6 @@ void intel_dvo_init(struct drm_device *dev)
connector->interlace_allowed = false;
connector->doublescan_allowed = false;
intel_encoder->dev_priv = dvo;
intel_encoder->i2c_bus = i2cbus;
drm_encoder_init(dev, &intel_encoder->enc,
&intel_dvo_enc_funcs, encoder_type);
drm_encoder_helper_add(&intel_encoder->enc,
@ -447,9 +441,9 @@ void intel_dvo_init(struct drm_device *dev)
* headers, likely), so for now, just get the current
* mode being output through DVO.
*/
dvo->panel_fixed_mode =
intel_dvo->panel_fixed_mode =
intel_dvo_get_current_mode(connector);
dvo->panel_wants_dither = true;
intel_dvo->panel_wants_dither = true;
}
drm_sysfs_connector_add(connector);
@ -461,6 +455,6 @@ void intel_dvo_init(struct drm_device *dev)
if (i2cbus != NULL)
intel_i2c_destroy(i2cbus);
free_intel:
kfree(intel_encoder);
kfree(intel_dvo);
kfree(intel_connector);
}

View File

@ -37,11 +37,17 @@
#include "i915_drm.h"
#include "i915_drv.h"
struct intel_hdmi_priv {
struct intel_hdmi {
struct intel_encoder base;
u32 sdvox_reg;
bool has_hdmi_sink;
};
static struct intel_hdmi *enc_to_intel_hdmi(struct drm_encoder *encoder)
{
return container_of(enc_to_intel_encoder(encoder), struct intel_hdmi, base);
}
static void intel_hdmi_mode_set(struct drm_encoder *encoder,
struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode)
@ -50,8 +56,7 @@ static void intel_hdmi_mode_set(struct drm_encoder *encoder,
struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_crtc *crtc = encoder->crtc;
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
struct intel_hdmi_priv *hdmi_priv = intel_encoder->dev_priv;
struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
u32 sdvox;
sdvox = SDVO_ENCODING_HDMI | SDVO_BORDER_ENABLE;
@ -60,7 +65,7 @@ static void intel_hdmi_mode_set(struct drm_encoder *encoder,
if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC)
sdvox |= SDVO_HSYNC_ACTIVE_HIGH;
if (hdmi_priv->has_hdmi_sink) {
if (intel_hdmi->has_hdmi_sink) {
sdvox |= SDVO_AUDIO_ENABLE;
if (HAS_PCH_CPT(dev))
sdvox |= HDMI_MODE_SELECT;
@ -73,26 +78,25 @@ static void intel_hdmi_mode_set(struct drm_encoder *encoder,
sdvox |= SDVO_PIPE_B_SELECT;
}
I915_WRITE(hdmi_priv->sdvox_reg, sdvox);
POSTING_READ(hdmi_priv->sdvox_reg);
I915_WRITE(intel_hdmi->sdvox_reg, sdvox);
POSTING_READ(intel_hdmi->sdvox_reg);
}
static void intel_hdmi_dpms(struct drm_encoder *encoder, int mode)
{
struct drm_device *dev = encoder->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
struct intel_hdmi_priv *hdmi_priv = intel_encoder->dev_priv;
struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
u32 temp;
temp = I915_READ(hdmi_priv->sdvox_reg);
temp = I915_READ(intel_hdmi->sdvox_reg);
/* HW workaround, need to toggle enable bit off and on for 12bpc, but
* we do this anyway which shows more stable in testing.
*/
if (HAS_PCH_SPLIT(dev)) {
I915_WRITE(hdmi_priv->sdvox_reg, temp & ~SDVO_ENABLE);
POSTING_READ(hdmi_priv->sdvox_reg);
I915_WRITE(intel_hdmi->sdvox_reg, temp & ~SDVO_ENABLE);
POSTING_READ(intel_hdmi->sdvox_reg);
}
if (mode != DRM_MODE_DPMS_ON) {
@ -101,15 +105,15 @@ static void intel_hdmi_dpms(struct drm_encoder *encoder, int mode)
temp |= SDVO_ENABLE;
}
I915_WRITE(hdmi_priv->sdvox_reg, temp);
POSTING_READ(hdmi_priv->sdvox_reg);
I915_WRITE(intel_hdmi->sdvox_reg, temp);
POSTING_READ(intel_hdmi->sdvox_reg);
/* HW workaround, need to write this twice for issue that may result
* in first write getting masked.
*/
if (HAS_PCH_SPLIT(dev)) {
I915_WRITE(hdmi_priv->sdvox_reg, temp);
POSTING_READ(hdmi_priv->sdvox_reg);
I915_WRITE(intel_hdmi->sdvox_reg, temp);
POSTING_READ(intel_hdmi->sdvox_reg);
}
}
@ -138,19 +142,17 @@ static enum drm_connector_status
intel_hdmi_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_hdmi_priv *hdmi_priv = intel_encoder->dev_priv;
struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
struct edid *edid = NULL;
enum drm_connector_status status = connector_status_disconnected;
hdmi_priv->has_hdmi_sink = false;
edid = drm_get_edid(connector,
intel_encoder->ddc_bus);
intel_hdmi->has_hdmi_sink = false;
edid = drm_get_edid(connector, intel_hdmi->base.ddc_bus);
if (edid) {
if (edid->input & DRM_EDID_INPUT_DIGITAL) {
status = connector_status_connected;
hdmi_priv->has_hdmi_sink = drm_detect_hdmi_monitor(edid);
intel_hdmi->has_hdmi_sink = drm_detect_hdmi_monitor(edid);
}
connector->display_info.raw_edid = NULL;
kfree(edid);
@ -162,13 +164,13 @@ intel_hdmi_detect(struct drm_connector *connector)
static int intel_hdmi_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 intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
/* We should parse the EDID data and find out if it's an HDMI sink so
* we can send audio to it.
*/
return intel_ddc_get_modes(connector, intel_encoder->ddc_bus);
return intel_ddc_get_modes(connector, intel_hdmi->base.ddc_bus);
}
static void intel_hdmi_destroy(struct drm_connector *connector)
@ -199,18 +201,8 @@ static const struct drm_connector_helper_funcs intel_hdmi_connector_helper_funcs
.best_encoder = intel_attached_encoder,
};
static void intel_hdmi_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_hdmi_enc_funcs = {
.destroy = intel_hdmi_enc_destroy,
.destroy = intel_encoder_destroy,
};
void intel_hdmi_init(struct drm_device *dev, int sdvox_reg)
@ -219,21 +211,19 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_reg)
struct drm_connector *connector;
struct intel_encoder *intel_encoder;
struct intel_connector *intel_connector;
struct intel_hdmi_priv *hdmi_priv;
struct intel_hdmi *intel_hdmi;
intel_encoder = kcalloc(sizeof(struct intel_encoder) +
sizeof(struct intel_hdmi_priv), 1, GFP_KERNEL);
if (!intel_encoder)
intel_hdmi = kzalloc(sizeof(struct intel_hdmi), GFP_KERNEL);
if (!intel_hdmi)
return;
intel_connector = kzalloc(sizeof(struct intel_connector), GFP_KERNEL);
if (!intel_connector) {
kfree(intel_encoder);
kfree(intel_hdmi);
return;
}
hdmi_priv = (struct intel_hdmi_priv *)(intel_encoder + 1);
intel_encoder = &intel_hdmi->base;
connector = &intel_connector->base;
drm_connector_init(dev, connector, &intel_hdmi_connector_funcs,
DRM_MODE_CONNECTOR_HDMIA);
@ -274,8 +264,7 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_reg)
if (!intel_encoder->ddc_bus)
goto err_connector;
hdmi_priv->sdvox_reg = sdvox_reg;
intel_encoder->dev_priv = hdmi_priv;
intel_hdmi->sdvox_reg = sdvox_reg;
drm_encoder_init(dev, &intel_encoder->enc, &intel_hdmi_enc_funcs,
DRM_MODE_ENCODER_TMDS);
@ -298,7 +287,7 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_reg)
err_connector:
drm_connector_cleanup(connector);
kfree(intel_encoder);
kfree(intel_hdmi);
kfree(intel_connector);
return;

View File

@ -41,12 +41,18 @@
#include <linux/acpi.h>
/* Private structure for the integrated LVDS support */
struct intel_lvds_priv {
struct intel_lvds {
struct intel_encoder base;
int fitting_mode;
u32 pfit_control;
u32 pfit_pgm_ratios;
};
static struct intel_lvds *enc_to_intel_lvds(struct drm_encoder *encoder)
{
return container_of(enc_to_intel_encoder(encoder), struct intel_lvds, base);
}
/**
* Sets the backlight level.
*
@ -219,9 +225,8 @@ static bool intel_lvds_mode_fixup(struct drm_encoder *encoder,
struct drm_device *dev = encoder->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc);
struct intel_lvds *intel_lvds = enc_to_intel_lvds(encoder);
struct drm_encoder *tmp_encoder;
struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
struct intel_lvds_priv *lvds_priv = intel_encoder->dev_priv;
u32 pfit_control = 0, pfit_pgm_ratios = 0, border = 0;
/* Should never happen!! */
@ -293,7 +298,7 @@ static bool intel_lvds_mode_fixup(struct drm_encoder *encoder,
I915_WRITE(BCLRPAT_B, 0);
}
switch (lvds_priv->fitting_mode) {
switch (intel_lvds->fitting_mode) {
case DRM_MODE_SCALE_CENTER:
/*
* For centered modes, we have to calculate border widths &
@ -378,8 +383,8 @@ static bool intel_lvds_mode_fixup(struct drm_encoder *encoder,
}
out:
lvds_priv->pfit_control = pfit_control;
lvds_priv->pfit_pgm_ratios = pfit_pgm_ratios;
intel_lvds->pfit_control = pfit_control;
intel_lvds->pfit_pgm_ratios = pfit_pgm_ratios;
dev_priv->lvds_border_bits = border;
/*
@ -427,8 +432,7 @@ static void intel_lvds_mode_set(struct drm_encoder *encoder,
{
struct drm_device *dev = encoder->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
struct intel_lvds_priv *lvds_priv = intel_encoder->dev_priv;
struct intel_lvds *intel_lvds = enc_to_intel_lvds(encoder);
/*
* The LVDS pin pair will already have been turned on in the
@ -444,8 +448,8 @@ static void intel_lvds_mode_set(struct drm_encoder *encoder,
* screen. Should be enabled before the pipe is enabled, according to
* register description and PRM.
*/
I915_WRITE(PFIT_PGM_RATIOS, lvds_priv->pfit_pgm_ratios);
I915_WRITE(PFIT_CONTROL, lvds_priv->pfit_control);
I915_WRITE(PFIT_PGM_RATIOS, intel_lvds->pfit_pgm_ratios);
I915_WRITE(PFIT_CONTROL, intel_lvds->pfit_control);
}
/**
@ -600,18 +604,17 @@ static int intel_lvds_set_property(struct drm_connector *connector,
connector->encoder) {
struct drm_crtc *crtc = connector->encoder->crtc;
struct drm_encoder *encoder = connector->encoder;
struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
struct intel_lvds_priv *lvds_priv = intel_encoder->dev_priv;
struct intel_lvds *intel_lvds = enc_to_intel_lvds(encoder);
if (value == DRM_MODE_SCALE_NONE) {
DRM_DEBUG_KMS("no scaling not supported\n");
return 0;
}
if (lvds_priv->fitting_mode == value) {
if (intel_lvds->fitting_mode == value) {
/* the LVDS scaling property is not changed */
return 0;
}
lvds_priv->fitting_mode = value;
intel_lvds->fitting_mode = value;
if (crtc && crtc->enabled) {
/*
* If the CRTC is enabled, the display will be changed
@ -647,19 +650,8 @@ static const struct drm_connector_funcs intel_lvds_connector_funcs = {
.destroy = intel_lvds_destroy,
};
static void intel_lvds_enc_destroy(struct drm_encoder *encoder)
{
struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
if (intel_encoder->ddc_bus)
intel_i2c_destroy(intel_encoder->ddc_bus);
drm_encoder_cleanup(encoder);
kfree(intel_encoder);
}
static const struct drm_encoder_funcs intel_lvds_enc_funcs = {
.destroy = intel_lvds_enc_destroy,
.destroy = intel_encoder_destroy,
};
static int __init intel_no_lvds_dmi_callback(const struct dmi_system_id *id)
@ -843,13 +835,13 @@ static int lvds_is_present_in_vbt(struct drm_device *dev)
void intel_lvds_init(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_lvds *intel_lvds;
struct intel_encoder *intel_encoder;
struct intel_connector *intel_connector;
struct drm_connector *connector;
struct drm_encoder *encoder;
struct drm_display_mode *scan; /* *modes, *bios_mode; */
struct drm_crtc *crtc;
struct intel_lvds_priv *lvds_priv;
u32 lvds;
int pipe, gpio = GPIOC;
@ -872,20 +864,20 @@ void intel_lvds_init(struct drm_device *dev)
gpio = PCH_GPIOC;
}
intel_encoder = kzalloc(sizeof(struct intel_encoder) +
sizeof(struct intel_lvds_priv), GFP_KERNEL);
if (!intel_encoder) {
intel_lvds = kzalloc(sizeof(struct intel_lvds), GFP_KERNEL);
if (!intel_lvds) {
return;
}
intel_connector = kzalloc(sizeof(struct intel_connector), GFP_KERNEL);
if (!intel_connector) {
kfree(intel_encoder);
kfree(intel_lvds);
return;
}
connector = &intel_connector->base;
intel_encoder = &intel_lvds->base;
encoder = &intel_encoder->enc;
connector = &intel_connector->base;
drm_connector_init(dev, &intel_connector->base, &intel_lvds_connector_funcs,
DRM_MODE_CONNECTOR_LVDS);
@ -905,8 +897,6 @@ void intel_lvds_init(struct drm_device *dev)
connector->interlace_allowed = false;
connector->doublescan_allowed = false;
lvds_priv = (struct intel_lvds_priv *)(intel_encoder + 1);
intel_encoder->dev_priv = lvds_priv;
/* create the scaling mode property */
drm_mode_create_scaling_mode_property(dev);
/*
@ -916,7 +906,7 @@ void intel_lvds_init(struct drm_device *dev)
drm_connector_attach_property(&intel_connector->base,
dev->mode_config.scaling_mode_property,
DRM_MODE_SCALE_ASPECT);
lvds_priv->fitting_mode = DRM_MODE_SCALE_ASPECT;
intel_lvds->fitting_mode = DRM_MODE_SCALE_ASPECT;
/*
* LVDS discovery:
* 1) check for EDID on DDC
@ -1024,6 +1014,6 @@ failed:
intel_i2c_destroy(intel_encoder->ddc_bus);
drm_connector_cleanup(connector);
drm_encoder_cleanup(encoder);
kfree(intel_encoder);
kfree(intel_lvds);
kfree(intel_connector);
}

File diff suppressed because it is too large Load Diff

View File

@ -44,7 +44,9 @@ enum tv_margin {
};
/** Private structure for the integrated TV support */
struct intel_tv_priv {
struct intel_tv {
struct intel_encoder base;
int type;
char *tv_format;
int margin[4];
@ -896,6 +898,11 @@ static const struct tv_mode tv_modes[] = {
},
};
static struct intel_tv *enc_to_intel_tv(struct drm_encoder *encoder)
{
return container_of(enc_to_intel_encoder(encoder), struct intel_tv, base);
}
static void
intel_tv_dpms(struct drm_encoder *encoder, int mode)
{
@ -929,19 +936,17 @@ intel_tv_mode_lookup (char *tv_format)
}
static const struct tv_mode *
intel_tv_mode_find (struct intel_encoder *intel_encoder)
intel_tv_mode_find (struct intel_tv *intel_tv)
{
struct intel_tv_priv *tv_priv = intel_encoder->dev_priv;
return intel_tv_mode_lookup(tv_priv->tv_format);
return intel_tv_mode_lookup(intel_tv->tv_format);
}
static enum drm_mode_status
intel_tv_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);
const struct tv_mode *tv_mode = intel_tv_mode_find(intel_encoder);
struct intel_tv *intel_tv = enc_to_intel_tv(encoder);
const struct tv_mode *tv_mode = intel_tv_mode_find(intel_tv);
/* Ensure TV refresh is close to desired refresh */
if (tv_mode && abs(tv_mode->refresh - drm_mode_vrefresh(mode) * 1000)
@ -957,8 +962,8 @@ intel_tv_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode,
{
struct drm_device *dev = encoder->dev;
struct drm_mode_config *drm_config = &dev->mode_config;
struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
const struct tv_mode *tv_mode = intel_tv_mode_find (intel_encoder);
struct intel_tv *intel_tv = enc_to_intel_tv(encoder);
const struct tv_mode *tv_mode = intel_tv_mode_find(intel_tv);
struct drm_encoder *other_encoder;
if (!tv_mode)
@ -983,9 +988,8 @@ intel_tv_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_crtc *crtc = encoder->crtc;
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
struct intel_tv_priv *tv_priv = intel_encoder->dev_priv;
const struct tv_mode *tv_mode = intel_tv_mode_find(intel_encoder);
struct intel_tv *intel_tv = enc_to_intel_tv(encoder);
const struct tv_mode *tv_mode = intel_tv_mode_find(intel_tv);
u32 tv_ctl;
u32 hctl1, hctl2, hctl3;
u32 vctl1, vctl2, vctl3, vctl4, vctl5, vctl6, vctl7;
@ -1001,7 +1005,7 @@ intel_tv_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
tv_ctl = I915_READ(TV_CTL);
tv_ctl &= TV_CTL_SAVE;
switch (tv_priv->type) {
switch (intel_tv->type) {
default:
case DRM_MODE_CONNECTOR_Unknown:
case DRM_MODE_CONNECTOR_Composite:
@ -1168,12 +1172,12 @@ intel_tv_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
else
ysize = 2*tv_mode->nbr_end + 1;
xpos += tv_priv->margin[TV_MARGIN_LEFT];
ypos += tv_priv->margin[TV_MARGIN_TOP];
xsize -= (tv_priv->margin[TV_MARGIN_LEFT] +
tv_priv->margin[TV_MARGIN_RIGHT]);
ysize -= (tv_priv->margin[TV_MARGIN_TOP] +
tv_priv->margin[TV_MARGIN_BOTTOM]);
xpos += intel_tv->margin[TV_MARGIN_LEFT];
ypos += intel_tv->margin[TV_MARGIN_TOP];
xsize -= (intel_tv->margin[TV_MARGIN_LEFT] +
intel_tv->margin[TV_MARGIN_RIGHT]);
ysize -= (intel_tv->margin[TV_MARGIN_TOP] +
intel_tv->margin[TV_MARGIN_BOTTOM]);
I915_WRITE(TV_WIN_POS, (xpos<<16)|ypos);
I915_WRITE(TV_WIN_SIZE, (xsize<<16)|ysize);
@ -1222,9 +1226,9 @@ static const struct drm_display_mode reported_modes[] = {
* \return false if TV is disconnected.
*/
static int
intel_tv_detect_type (struct drm_crtc *crtc, struct intel_encoder *intel_encoder)
intel_tv_detect_type (struct intel_tv *intel_tv)
{
struct drm_encoder *encoder = &intel_encoder->enc;
struct drm_encoder *encoder = &intel_tv->base.enc;
struct drm_device *dev = encoder->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
unsigned long irqflags;
@ -1304,12 +1308,11 @@ intel_tv_detect_type (struct drm_crtc *crtc, struct intel_encoder *intel_encoder
static void intel_tv_find_better_format(struct drm_connector *connector)
{
struct drm_encoder *encoder = intel_attached_encoder(connector);
struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
struct intel_tv_priv *tv_priv = intel_encoder->dev_priv;
const struct tv_mode *tv_mode = intel_tv_mode_find(intel_encoder);
struct intel_tv *intel_tv = enc_to_intel_tv(encoder);
const struct tv_mode *tv_mode = intel_tv_mode_find(intel_tv);
int i;
if ((tv_priv->type == DRM_MODE_CONNECTOR_Component) ==
if ((intel_tv->type == DRM_MODE_CONNECTOR_Component) ==
tv_mode->component_only)
return;
@ -1317,12 +1320,12 @@ static void intel_tv_find_better_format(struct drm_connector *connector)
for (i = 0; i < sizeof(tv_modes) / sizeof(*tv_modes); i++) {
tv_mode = tv_modes + i;
if ((tv_priv->type == DRM_MODE_CONNECTOR_Component) ==
if ((intel_tv->type == DRM_MODE_CONNECTOR_Component) ==
tv_mode->component_only)
break;
}
tv_priv->tv_format = tv_mode->name;
intel_tv->tv_format = tv_mode->name;
drm_connector_property_set_value(connector,
connector->dev->mode_config.tv_mode_property, i);
}
@ -1336,31 +1339,31 @@ static void intel_tv_find_better_format(struct drm_connector *connector)
static enum drm_connector_status
intel_tv_detect(struct drm_connector *connector)
{
struct drm_crtc *crtc;
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_tv_priv *tv_priv = intel_encoder->dev_priv;
int dpms_mode;
int type = tv_priv->type;
struct intel_tv *intel_tv = enc_to_intel_tv(encoder);
int type;
mode = reported_modes[0];
drm_mode_set_crtcinfo(&mode, CRTC_INTERLACE_HALVE_V);
if (encoder->crtc && encoder->crtc->enabled) {
type = intel_tv_detect_type(encoder->crtc, intel_encoder);
type = intel_tv_detect_type(intel_tv);
} else {
crtc = intel_get_load_detect_pipe(intel_encoder, connector,
struct drm_crtc *crtc;
int dpms_mode;
crtc = intel_get_load_detect_pipe(&intel_tv->base, connector,
&mode, &dpms_mode);
if (crtc) {
type = intel_tv_detect_type(crtc, intel_encoder);
intel_release_load_detect_pipe(intel_encoder, connector,
type = intel_tv_detect_type(intel_tv);
intel_release_load_detect_pipe(&intel_tv->base, connector,
dpms_mode);
} else
type = -1;
}
tv_priv->type = type;
intel_tv->type = type;
if (type < 0)
return connector_status_disconnected;
@ -1391,8 +1394,8 @@ intel_tv_chose_preferred_modes(struct drm_connector *connector,
struct drm_display_mode *mode_ptr)
{
struct drm_encoder *encoder = intel_attached_encoder(connector);
struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
const struct tv_mode *tv_mode = intel_tv_mode_find(intel_encoder);
struct intel_tv *intel_tv = enc_to_intel_tv(encoder);
const struct tv_mode *tv_mode = intel_tv_mode_find(intel_tv);
if (tv_mode->nbr_end < 480 && mode_ptr->vdisplay == 480)
mode_ptr->type |= DRM_MODE_TYPE_PREFERRED;
@ -1417,8 +1420,8 @@ intel_tv_get_modes(struct drm_connector *connector)
{
struct drm_display_mode *mode_ptr;
struct drm_encoder *encoder = intel_attached_encoder(connector);
struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
const struct tv_mode *tv_mode = intel_tv_mode_find(intel_encoder);
struct intel_tv *intel_tv = enc_to_intel_tv(encoder);
const struct tv_mode *tv_mode = intel_tv_mode_find(intel_tv);
int j, count = 0;
u64 tmp;
@ -1483,8 +1486,7 @@ intel_tv_set_property(struct drm_connector *connector, struct drm_property *prop
{
struct drm_device *dev = connector->dev;
struct drm_encoder *encoder = intel_attached_encoder(connector);
struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
struct intel_tv_priv *tv_priv = intel_encoder->dev_priv;
struct intel_tv *intel_tv = enc_to_intel_tv(encoder);
struct drm_crtc *crtc = encoder->crtc;
int ret = 0;
bool changed = false;
@ -1494,30 +1496,30 @@ intel_tv_set_property(struct drm_connector *connector, struct drm_property *prop
goto out;
if (property == dev->mode_config.tv_left_margin_property &&
tv_priv->margin[TV_MARGIN_LEFT] != val) {
tv_priv->margin[TV_MARGIN_LEFT] = val;
intel_tv->margin[TV_MARGIN_LEFT] != val) {
intel_tv->margin[TV_MARGIN_LEFT] = val;
changed = true;
} else if (property == dev->mode_config.tv_right_margin_property &&
tv_priv->margin[TV_MARGIN_RIGHT] != val) {
tv_priv->margin[TV_MARGIN_RIGHT] = val;
intel_tv->margin[TV_MARGIN_RIGHT] != val) {
intel_tv->margin[TV_MARGIN_RIGHT] = val;
changed = true;
} else if (property == dev->mode_config.tv_top_margin_property &&
tv_priv->margin[TV_MARGIN_TOP] != val) {
tv_priv->margin[TV_MARGIN_TOP] = val;
intel_tv->margin[TV_MARGIN_TOP] != val) {
intel_tv->margin[TV_MARGIN_TOP] = val;
changed = true;
} else if (property == dev->mode_config.tv_bottom_margin_property &&
tv_priv->margin[TV_MARGIN_BOTTOM] != val) {
tv_priv->margin[TV_MARGIN_BOTTOM] = val;
intel_tv->margin[TV_MARGIN_BOTTOM] != val) {
intel_tv->margin[TV_MARGIN_BOTTOM] = val;
changed = true;
} else if (property == dev->mode_config.tv_mode_property) {
if (val >= ARRAY_SIZE(tv_modes)) {
ret = -EINVAL;
goto out;
}
if (!strcmp(tv_priv->tv_format, tv_modes[val].name))
if (!strcmp(intel_tv->tv_format, tv_modes[val].name))
goto out;
tv_priv->tv_format = tv_modes[val].name;
intel_tv->tv_format = tv_modes[val].name;
changed = true;
} else {
ret = -EINVAL;
@ -1553,16 +1555,8 @@ static const struct drm_connector_helper_funcs intel_tv_connector_helper_funcs =
.best_encoder = intel_attached_encoder,
};
static void intel_tv_enc_destroy(struct drm_encoder *encoder)
{
struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
drm_encoder_cleanup(encoder);
kfree(intel_encoder);
}
static const struct drm_encoder_funcs intel_tv_enc_funcs = {
.destroy = intel_tv_enc_destroy,
.destroy = intel_encoder_destroy,
};
/*
@ -1606,9 +1600,9 @@ intel_tv_init(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_connector *connector;
struct intel_tv *intel_tv;
struct intel_encoder *intel_encoder;
struct intel_connector *intel_connector;
struct intel_tv_priv *tv_priv;
u32 tv_dac_on, tv_dac_off, save_tv_dac;
char **tv_format_names;
int i, initial_mode = 0;
@ -1647,18 +1641,18 @@ intel_tv_init(struct drm_device *dev)
(tv_dac_off & TVDAC_STATE_CHG_EN) != 0)
return;
intel_encoder = kzalloc(sizeof(struct intel_encoder) +
sizeof(struct intel_tv_priv), GFP_KERNEL);
if (!intel_encoder) {
intel_tv = kzalloc(sizeof(struct intel_tv), GFP_KERNEL);
if (!intel_tv) {
return;
}
intel_connector = kzalloc(sizeof(struct intel_connector), GFP_KERNEL);
if (!intel_connector) {
kfree(intel_encoder);
kfree(intel_tv);
return;
}
intel_encoder = &intel_tv->base;
connector = &intel_connector->base;
drm_connector_init(dev, connector, &intel_tv_connector_funcs,
@ -1668,22 +1662,20 @@ intel_tv_init(struct drm_device *dev)
DRM_MODE_ENCODER_TVDAC);
drm_mode_connector_attach_encoder(&intel_connector->base, &intel_encoder->enc);
tv_priv = (struct intel_tv_priv *)(intel_encoder + 1);
intel_encoder->type = INTEL_OUTPUT_TVOUT;
intel_encoder->crtc_mask = (1 << 0) | (1 << 1);
intel_encoder->clone_mask = (1 << INTEL_TV_CLONE_BIT);
intel_encoder->enc.possible_crtcs = ((1 << 0) | (1 << 1));
intel_encoder->enc.possible_clones = (1 << INTEL_OUTPUT_TVOUT);
intel_encoder->dev_priv = tv_priv;
tv_priv->type = DRM_MODE_CONNECTOR_Unknown;
intel_tv->type = DRM_MODE_CONNECTOR_Unknown;
/* BIOS margin values */
tv_priv->margin[TV_MARGIN_LEFT] = 54;
tv_priv->margin[TV_MARGIN_TOP] = 36;
tv_priv->margin[TV_MARGIN_RIGHT] = 46;
tv_priv->margin[TV_MARGIN_BOTTOM] = 37;
intel_tv->margin[TV_MARGIN_LEFT] = 54;
intel_tv->margin[TV_MARGIN_TOP] = 36;
intel_tv->margin[TV_MARGIN_RIGHT] = 46;
intel_tv->margin[TV_MARGIN_BOTTOM] = 37;
tv_priv->tv_format = kstrdup(tv_modes[initial_mode].name, GFP_KERNEL);
intel_tv->tv_format = kstrdup(tv_modes[initial_mode].name, GFP_KERNEL);
drm_encoder_helper_add(&intel_encoder->enc, &intel_tv_helper_funcs);
drm_connector_helper_add(connector, &intel_tv_connector_helper_funcs);
@ -1703,16 +1695,16 @@ intel_tv_init(struct drm_device *dev)
initial_mode);
drm_connector_attach_property(connector,
dev->mode_config.tv_left_margin_property,
tv_priv->margin[TV_MARGIN_LEFT]);
intel_tv->margin[TV_MARGIN_LEFT]);
drm_connector_attach_property(connector,
dev->mode_config.tv_top_margin_property,
tv_priv->margin[TV_MARGIN_TOP]);
intel_tv->margin[TV_MARGIN_TOP]);
drm_connector_attach_property(connector,
dev->mode_config.tv_right_margin_property,
tv_priv->margin[TV_MARGIN_RIGHT]);
intel_tv->margin[TV_MARGIN_RIGHT]);
drm_connector_attach_property(connector,
dev->mode_config.tv_bottom_margin_property,
tv_priv->margin[TV_MARGIN_BOTTOM]);
intel_tv->margin[TV_MARGIN_BOTTOM]);
out:
drm_sysfs_connector_add(connector);
}