@@ -36,6 +36,17 @@
#include "i915_drv.h"
#include "intel_sdvo_regs.h"
+#define SDVO_TMDS_MASK (SDVO_OUTPUT_TMDS0 | SDVO_OUTPUT_TMDS1)
+#define SDVO_RGB_MASK (SDVO_OUTPUT_RGB0 | SDVO_OUTPUT_RGB1)
+#define SDVO_LVDS_MASK (SDVO_OUTPUT_LVDS0 | SDVO_OUTPUT_LVDS1)
+#define SDVO_TV_MASK (SDVO_OUTPUT_CVBS0 | SDVO_OUTPUT_SVID0)
+
+#define SDVO_OUTPUT_MASK (SDVO_TMDS_MASK | SDVO_RGB_MASK | SDVO_LVDS_MASK |\
+ SDVO_TV_MASK)
+
+#define SDVO_CONNECTOR_IS_TV(c) (c->output_flag & SDVO_TV_MASK)
+#define SDVO_CONNECTOR_IS_LVDS(c) (c->output_flag & SDVO_LVDS_MASK)
+
static char *tv_format_names[] = {
"NTSC_M" , "NTSC_J" , "NTSC_443",
"PAL_B" , "PAL_D" , "PAL_G" ,
@@ -48,7 +59,7 @@ static char *tv_format_names[] = {
#define TV_FORMAT_NUM (sizeof(tv_format_names) / sizeof(*tv_format_names))
-struct intel_sdvo_priv {
+struct intel_sdvo_encoder {
u8 slave_addr;
/* Register for the SDVO device: SDVOB or SDVOC */
@@ -72,6 +83,9 @@ struct intel_sdvo_priv {
*/
uint16_t attached_output;
+ /* DDC bus used by this SDVO output */
+ uint8_t ddc_bus;
+
/**
* This is set if we're going to treat the device as TV-out.
*
@@ -81,15 +95,6 @@ struct intel_sdvo_priv {
*/
bool is_tv;
- /* This is for current tv format name */
- char *tv_format_name;
-
- /* This contains all current supported TV format */
- char *tv_format_supported[TV_FORMAT_NUM];
- int format_supported_num;
- struct drm_property *tv_format_property;
- struct drm_property *tv_format_name_property[TV_FORMAT_NUM];
-
/**
* This is set if we treat the device as HDMI, instead of DVI.
*/
@@ -101,38 +106,50 @@ struct intel_sdvo_priv {
bool is_lvds;
/**
- * This is sdvo flags for input timing.
- */
- uint8_t sdvo_flags;
-
- /**
* This is sdvo fixed pannel mode pointer
*/
struct drm_display_mode *sdvo_lvds_fixed_mode;
- /**
- * Returned SDTV resolutions allowed for the current format, if the
- * device reported it.
- */
- struct intel_sdvo_sdtv_resolution_reply sdtv_resolutions;
-
/*
* supported encoding mode, used to determine whether HDMI is
* supported
*/
struct intel_sdvo_encode encode;
- /* DDC bus used by this SDVO output */
- uint8_t ddc_bus;
+ /**
+ * This is sdvo flags for input timing.
+ */
+ uint8_t sdvo_flags;
- /* Mac mini hack -- use the same DDC as the analog connector */
- struct i2c_adapter *analog_ddc_bus;
+ /* This is for current tv format name */
+ char *tv_format_name;
int save_sdvo_mult;
u16 save_active_outputs;
struct intel_sdvo_dtd save_input_dtd_1, save_input_dtd_2;
struct intel_sdvo_dtd save_output_dtd[16];
u32 save_SDVOX;
+};
+
+struct intel_sdvo_connector {
+ /* Mark the type of connector */
+ uint16_t output_flag;
+
+ /* This contains all current supported TV format */
+ char *tv_format_supported[TV_FORMAT_NUM];
+ int format_supported_num;
+ struct drm_property *tv_format_property;
+ struct drm_property *tv_format_name_property[TV_FORMAT_NUM];
+
+ /**
+ * Returned SDTV resolutions allowed for the current format, if the
+ * device reported it.
+ */
+ struct intel_sdvo_sdtv_resolution_reply sdtv_resolutions;
+
+ /* Mac mini hack -- use the same DDC as the analog connector */
+ struct i2c_adapter *analog_ddc_bus;
+
/* add the property for the SDVO-TV */
struct drm_property *left_property;
struct drm_property *right_property;
@@ -160,8 +177,13 @@ struct intel_sdvo_priv {
};
static bool
-intel_sdvo_output_setup(struct intel_encoder *intel_encoder,
- struct intel_connector *intel_connector, uint16_t flags);
+intel_sdvo_output_setup(struct intel_encoder *intel_encoder);
+static void
+intel_sdvo_tv_create_property(struct drm_encoder *encoder,
+ struct drm_connector *connector);
+static void
+intel_sdvo_create_enhance_property(struct drm_encoder *encoder,
+ struct drm_connector *connector);
/**
* Writes the SDVOB or SDVOC with the given value, but always writes both
@@ -172,11 +194,11 @@ static void intel_sdvo_write_sdvox(struct intel_encoder *intel_encoder, u32 val)
{
struct drm_device *dev = intel_encoder->base.dev;
struct drm_i915_private *dev_priv = dev->dev_private;
- struct intel_sdvo_priv *sdvo_priv = intel_encoder->dev_priv;
+ struct intel_sdvo_encoder *sdvo_encoder = intel_encoder->dev_priv;
u32 bval = val, cval = val;
int i;
- if (sdvo_priv->output_device == SDVOB) {
+ if (sdvo_encoder->output_device == SDVOB) {
cval = I915_READ(SDVOC);
} else {
bval = I915_READ(SDVOB);
@@ -198,20 +220,20 @@ static void intel_sdvo_write_sdvox(struct intel_encoder *intel_encoder, u32 val)
static bool intel_sdvo_read_byte(struct intel_encoder *intel_encoder, u8 addr,
u8 *ch)
{
- struct intel_sdvo_priv *sdvo_priv = intel_encoder->dev_priv;
+ struct intel_sdvo_encoder *sdvo_encoder = intel_encoder->dev_priv;
u8 out_buf[2];
u8 buf[2];
int ret;
struct i2c_msg msgs[] = {
{
- .addr = sdvo_priv->slave_addr >> 1,
+ .addr = sdvo_encoder->slave_addr >> 1,
.flags = 0,
.len = 1,
.buf = out_buf,
},
{
- .addr = sdvo_priv->slave_addr >> 1,
+ .addr = sdvo_encoder->slave_addr >> 1,
.flags = I2C_M_RD,
.len = 1,
.buf = buf,
@@ -234,11 +256,11 @@ static bool intel_sdvo_read_byte(struct intel_encoder *intel_encoder, u8 addr,
static bool intel_sdvo_write_byte(struct intel_encoder *intel_encoder, int addr,
u8 ch)
{
- struct intel_sdvo_priv *sdvo_priv = intel_encoder->dev_priv;
+ struct intel_sdvo_encoder *sdvo_encoder = intel_encoder->dev_priv;
u8 out_buf[2];
struct i2c_msg msgs[] = {
{
- .addr = sdvo_priv->slave_addr >> 1,
+ .addr = sdvo_encoder->slave_addr >> 1,
.flags = 0,
.len = 2,
.buf = out_buf,
@@ -357,11 +379,11 @@ static const struct _sdvo_cmd_name {
static void intel_sdvo_debug_write(struct intel_encoder *intel_encoder, u8 cmd,
void *args, int args_len)
{
- struct intel_sdvo_priv *sdvo_priv = intel_encoder->dev_priv;
+ struct intel_sdvo_encoder *sdvo_encoder = intel_encoder->dev_priv;
int i;
DRM_DEBUG_KMS("%s: W: %02X ",
- SDVO_NAME(sdvo_priv), cmd);
+ SDVO_NAME(sdvo_encoder), cmd);
for (i = 0; i < args_len; i++)
DRM_LOG_KMS("%02X ", ((u8 *)args)[i]);
for (; i < 8; i++)
@@ -406,10 +428,10 @@ static void intel_sdvo_debug_response(struct intel_encoder *intel_encoder,
void *response, int response_len,
u8 status)
{
- struct intel_sdvo_priv *sdvo_priv = intel_encoder->dev_priv;
+ struct intel_sdvo_encoder *sdvo_encoder = intel_encoder->dev_priv;
int i;
- DRM_DEBUG_KMS("%s: R: ", SDVO_NAME(sdvo_priv));
+ DRM_DEBUG_KMS("%s: R: ", SDVO_NAME(sdvo_encoder));
for (i = 0; i < response_len; i++)
DRM_LOG_KMS("%02X ", ((u8 *)response)[i]);
for (; i < 8; i++)
@@ -471,24 +493,24 @@ static int intel_sdvo_get_pixel_multiplier(struct drm_display_mode *mode)
static void intel_sdvo_set_control_bus_switch(struct intel_encoder *intel_encoder,
u8 target)
{
- struct intel_sdvo_priv *sdvo_priv = intel_encoder->dev_priv;
+ struct intel_sdvo_encoder *sdvo_encoder = intel_encoder->dev_priv;
u8 out_buf[2], cmd_buf[2], ret_value[2], ret;
struct i2c_msg msgs[] = {
{
- .addr = sdvo_priv->slave_addr >> 1,
+ .addr = sdvo_encoder->slave_addr >> 1,
.flags = 0,
.len = 2,
.buf = out_buf,
},
/* the following two are to read the response */
{
- .addr = sdvo_priv->slave_addr >> 1,
+ .addr = sdvo_encoder->slave_addr >> 1,
.flags = 0,
.len = 1,
.buf = cmd_buf,
},
{
- .addr = sdvo_priv->slave_addr >> 1,
+ .addr = sdvo_encoder->slave_addr >> 1,
.flags = I2C_M_RD,
.len = 1,
.buf = ret_value,
@@ -717,7 +739,7 @@ intel_sdvo_create_preferred_input_timing(struct intel_encoder *intel_encoder,
uint16_t height)
{
struct intel_sdvo_preferred_input_timing_args args;
- struct intel_sdvo_priv *sdvo_priv = intel_encoder->dev_priv;
+ struct intel_sdvo_encoder *sdvo_encoder = intel_encoder->dev_priv;
uint8_t status;
memset(&args, 0, sizeof(args));
@@ -726,9 +748,9 @@ intel_sdvo_create_preferred_input_timing(struct intel_encoder *intel_encoder,
args.height = height;
args.interlace = 0;
- if (sdvo_priv->is_lvds &&
- (sdvo_priv->sdvo_lvds_fixed_mode->hdisplay != width ||
- sdvo_priv->sdvo_lvds_fixed_mode->vdisplay != height))
+ if (sdvo_encoder->is_lvds &&
+ (sdvo_encoder->sdvo_lvds_fixed_mode->hdisplay != width ||
+ sdvo_encoder->sdvo_lvds_fixed_mode->vdisplay != height))
args.scaled = 1;
intel_sdvo_write_cmd(intel_encoder, SDVO_CMD_CREATE_PREFERRED_INPUT_TIMING,
@@ -1051,12 +1073,12 @@ static void intel_sdvo_set_tv_format(struct intel_encoder *intel_encoder)
{
struct intel_sdvo_tv_format format;
- struct intel_sdvo_priv *sdvo_priv = intel_encoder->dev_priv;
+ struct intel_sdvo_encoder *sdvo_encoder = intel_encoder->dev_priv;
uint32_t format_map, i;
uint8_t status;
for (i = 0; i < TV_FORMAT_NUM; i++)
- if (tv_format_names[i] == sdvo_priv->tv_format_name)
+ if (tv_format_names[i] == sdvo_encoder->tv_format_name)
break;
format_map = 1 << i;
@@ -1070,7 +1092,7 @@ static void intel_sdvo_set_tv_format(struct intel_encoder *intel_encoder)
status = intel_sdvo_read_response(intel_encoder, NULL, 0);
if (status != SDVO_CMD_STATUS_SUCCESS)
DRM_DEBUG_KMS("%s: Failed to set TV format\n",
- SDVO_NAME(sdvo_priv));
+ SDVO_NAME(sdvo_encoder));
}
static bool intel_sdvo_mode_fixup(struct drm_encoder *encoder,
@@ -1078,9 +1100,9 @@ static bool intel_sdvo_mode_fixup(struct drm_encoder *encoder,
struct drm_display_mode *adjusted_mode)
{
struct intel_encoder *intel_encoder = to_intel_encoder(encoder);
- struct intel_sdvo_priv *dev_priv = intel_encoder->dev_priv;
+ struct intel_sdvo_encoder *sdvo_encoder = intel_encoder->dev_priv;
- if (dev_priv->is_tv) {
+ if (sdvo_encoder->is_tv) {
struct intel_sdvo_dtd output_dtd;
bool success;
@@ -1094,7 +1116,7 @@ static bool intel_sdvo_mode_fixup(struct drm_encoder *encoder,
/* Set output timings */
intel_sdvo_get_dtd_from_mode(&output_dtd, mode);
intel_sdvo_set_target_output(intel_encoder,
- dev_priv->controlled_output);
+ sdvo_encoder->attached_output);
intel_sdvo_set_output_timing(intel_encoder, &output_dtd);
/* Set the input timing to the screen. Assume always input 0. */
@@ -1111,7 +1133,7 @@ static bool intel_sdvo_mode_fixup(struct drm_encoder *encoder,
intel_sdvo_get_preferred_input_timing(intel_encoder,
&input_dtd);
intel_sdvo_get_mode_from_dtd(adjusted_mode, &input_dtd);
- dev_priv->sdvo_flags = input_dtd.part2.sdvo_flags;
+ sdvo_encoder->sdvo_flags = input_dtd.part2.sdvo_flags;
drm_mode_set_crtcinfo(adjusted_mode, 0);
@@ -1122,23 +1144,22 @@ static bool intel_sdvo_mode_fixup(struct drm_encoder *encoder,
} else {
return false;
}
- } else if (dev_priv->is_lvds) {
+ } else if (sdvo_encoder->is_lvds) {
struct intel_sdvo_dtd output_dtd;
bool success;
- drm_mode_set_crtcinfo(dev_priv->sdvo_lvds_fixed_mode, 0);
+ drm_mode_set_crtcinfo(sdvo_encoder->sdvo_lvds_fixed_mode, 0);
/* Set output timings */
intel_sdvo_get_dtd_from_mode(&output_dtd,
- dev_priv->sdvo_lvds_fixed_mode);
+ sdvo_encoder->sdvo_lvds_fixed_mode);
intel_sdvo_set_target_output(intel_encoder,
- dev_priv->controlled_output);
+ sdvo_encoder->attached_output);
intel_sdvo_set_output_timing(intel_encoder, &output_dtd);
/* Set the input timing to the screen. Assume always input 0. */
intel_sdvo_set_target_input(intel_encoder, true, false);
-
success = intel_sdvo_create_preferred_input_timing(
intel_encoder,
mode->clock / 10,
@@ -1151,7 +1172,7 @@ static bool intel_sdvo_mode_fixup(struct drm_encoder *encoder,
intel_sdvo_get_preferred_input_timing(intel_encoder,
&input_dtd);
intel_sdvo_get_mode_from_dtd(adjusted_mode, &input_dtd);
- dev_priv->sdvo_flags = input_dtd.part2.sdvo_flags;
+ sdvo_encoder->sdvo_flags = input_dtd.part2.sdvo_flags;
drm_mode_set_crtcinfo(adjusted_mode, 0);
@@ -1181,7 +1202,7 @@ static void intel_sdvo_mode_set(struct drm_encoder *encoder,
struct drm_crtc *crtc = encoder->crtc;
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
struct intel_encoder *intel_encoder = to_intel_encoder(encoder);
- struct intel_sdvo_priv *sdvo_priv = intel_encoder->dev_priv;
+ struct intel_sdvo_encoder *sdvo_encoder = intel_encoder->dev_priv;
u32 sdvox = 0;
int sdvo_pixel_multiply;
struct intel_sdvo_in_out_map in_out;
@@ -1197,40 +1218,40 @@ static void intel_sdvo_mode_set(struct drm_encoder *encoder,
* channel on the motherboard. In a two-input device, the first input
* will be SDVOB and the second SDVOC.
*/
- in_out.in0 = sdvo_priv->controlled_output;
+ in_out.in0 = sdvo_encoder->attached_output;
in_out.in1 = 0;
intel_sdvo_write_cmd(intel_encoder, SDVO_CMD_SET_IN_OUT_MAP,
&in_out, sizeof(in_out));
status = intel_sdvo_read_response(intel_encoder, NULL, 0);
- if (sdvo_priv->is_hdmi) {
+ if (sdvo_encoder->is_hdmi) {
intel_sdvo_set_avi_infoframe(intel_encoder, mode);
sdvox |= SDVO_AUDIO_ENABLE;
}
/* We have tried to get input timing in mode_fixup, and filled into
adjusted_mode */
- if (sdvo_priv->is_tv || sdvo_priv->is_lvds) {
+ if (sdvo_encoder->is_tv || sdvo_encoder->is_lvds) {
intel_sdvo_get_dtd_from_mode(&input_dtd, adjusted_mode);
- input_dtd.part2.sdvo_flags = sdvo_priv->sdvo_flags;
+ input_dtd.part2.sdvo_flags = sdvo_encoder->sdvo_flags;
} else
intel_sdvo_get_dtd_from_mode(&input_dtd, mode);
/* If it's a TV, we already set the output timing in mode_fixup.
* Otherwise, the output timing is equal to the input timing.
*/
- if (!sdvo_priv->is_tv && !sdvo_priv->is_lvds) {
+ if (!sdvo_encoder->is_tv && !sdvo_encoder->is_lvds) {
/* Set the output timing to the screen */
intel_sdvo_set_target_output(intel_encoder,
- sdvo_priv->controlled_output);
+ sdvo_encoder->attached_output);
intel_sdvo_set_output_timing(intel_encoder, &input_dtd);
}
/* Set the input timing to the screen. Assume always input 0. */
intel_sdvo_set_target_input(intel_encoder, true, false);
- if (sdvo_priv->is_tv)
+ if (sdvo_encoder->is_tv)
intel_sdvo_set_tv_format(intel_encoder);
/* We would like to use intel_sdvo_create_preferred_input_timing() to
@@ -1272,8 +1293,8 @@ static void intel_sdvo_mode_set(struct drm_encoder *encoder,
SDVO_VSYNC_ACTIVE_HIGH |
SDVO_HSYNC_ACTIVE_HIGH;
} else {
- sdvox |= I915_READ(sdvo_priv->output_device);
- switch (sdvo_priv->output_device) {
+ sdvox |= I915_READ(sdvo_encoder->output_device);
+ switch (sdvo_encoder->output_device) {
case SDVOB:
sdvox &= SDVOB_PRESERVE_MASK;
break;
@@ -1295,7 +1316,7 @@ static void intel_sdvo_mode_set(struct drm_encoder *encoder,
sdvox |= (sdvo_pixel_multiply - 1) << SDVO_PORT_MULTIPLY_SHIFT;
}
- if (sdvo_priv->sdvo_flags & SDVO_NEED_TO_STALL)
+ if (sdvo_encoder->sdvo_flags & SDVO_NEED_TO_STALL)
sdvox |= SDVO_STALL_SELECT;
intel_sdvo_write_sdvox(intel_encoder, sdvox);
}
@@ -1305,7 +1326,7 @@ static void intel_sdvo_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 = to_intel_encoder(encoder);
- struct intel_sdvo_priv *sdvo_priv = intel_encoder->dev_priv;
+ struct intel_sdvo_encoder *sdvo_encoder = intel_encoder->dev_priv;
u32 temp;
if (mode != DRM_MODE_DPMS_ON) {
@@ -1314,7 +1335,7 @@ static void intel_sdvo_dpms(struct drm_encoder *encoder, int mode)
intel_sdvo_set_encoder_power_state(intel_encoder, mode);
if (mode == DRM_MODE_DPMS_OFF) {
- temp = I915_READ(sdvo_priv->output_device);
+ temp = I915_READ(sdvo_encoder->output_device);
if ((temp & SDVO_ENABLE) != 0) {
intel_sdvo_write_sdvox(intel_encoder, temp & ~SDVO_ENABLE);
}
@@ -1324,7 +1345,7 @@ static void intel_sdvo_dpms(struct drm_encoder *encoder, int mode)
int i;
u8 status;
- temp = I915_READ(sdvo_priv->output_device);
+ temp = I915_READ(sdvo_encoder->output_device);
if ((temp & SDVO_ENABLE) == 0)
intel_sdvo_write_sdvox(intel_encoder, temp | SDVO_ENABLE);
for (i = 0; i < 2; i++)
@@ -1340,12 +1361,12 @@ static void intel_sdvo_dpms(struct drm_encoder *encoder, int mode)
*/
if (status == SDVO_CMD_STATUS_SUCCESS && !input1) {
DRM_DEBUG_KMS("First %s output reported failure to "
- "sync\n", SDVO_NAME(sdvo_priv));
+ "sync\n", SDVO_NAME(sdvo_encoder));
}
if (0)
intel_sdvo_set_encoder_power_state(intel_encoder, mode);
- intel_sdvo_set_active_outputs(intel_encoder, sdvo_priv->controlled_output);
+ intel_sdvo_set_active_outputs(intel_encoder, sdvo_encoder->attached_output);
}
return;
}
@@ -1356,39 +1377,39 @@ static void intel_sdvo_save(struct drm_connector *connector)
struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_encoder *encoder = intel_best_encoder(connector);
struct intel_encoder *intel_encoder = to_intel_encoder(encoder);
- struct intel_sdvo_priv *sdvo_priv = intel_encoder->dev_priv;
+ struct intel_sdvo_encoder *sdvo_encoder = intel_encoder->dev_priv;
int o;
- sdvo_priv->save_sdvo_mult = intel_sdvo_get_clock_rate_mult(intel_encoder);
- intel_sdvo_get_active_outputs(intel_encoder, &sdvo_priv->save_active_outputs);
+ sdvo_encoder->save_sdvo_mult = intel_sdvo_get_clock_rate_mult(intel_encoder);
+ intel_sdvo_get_active_outputs(intel_encoder, &sdvo_encoder->save_active_outputs);
- if (sdvo_priv->caps.sdvo_inputs_mask & 0x1) {
+ if (sdvo_encoder->caps.sdvo_inputs_mask & 0x1) {
intel_sdvo_set_target_input(intel_encoder, true, false);
intel_sdvo_get_input_timing(intel_encoder,
- &sdvo_priv->save_input_dtd_1);
+ &sdvo_encoder->save_input_dtd_1);
}
- if (sdvo_priv->caps.sdvo_inputs_mask & 0x2) {
+ if (sdvo_encoder->caps.sdvo_inputs_mask & 0x2) {
intel_sdvo_set_target_input(intel_encoder, false, true);
intel_sdvo_get_input_timing(intel_encoder,
- &sdvo_priv->save_input_dtd_2);
+ &sdvo_encoder->save_input_dtd_2);
}
for (o = SDVO_OUTPUT_FIRST; o <= SDVO_OUTPUT_LAST; o++)
{
u16 this_output = (1 << o);
- if (sdvo_priv->caps.output_flags & this_output)
+ if (sdvo_encoder->caps.output_flags & this_output)
{
intel_sdvo_set_target_output(intel_encoder, this_output);
intel_sdvo_get_output_timing(intel_encoder,
- &sdvo_priv->save_output_dtd[o]);
+ &sdvo_encoder->save_output_dtd[o]);
}
}
- if (sdvo_priv->is_tv) {
+ if (sdvo_encoder->is_tv) {
/* XXX: Save TV format/enhancements. */
}
- sdvo_priv->save_SDVOX = I915_READ(sdvo_priv->output_device);
+ sdvo_encoder->save_SDVOX = I915_READ(sdvo_encoder->output_device);
}
static void intel_sdvo_restore(struct drm_connector *connector)
@@ -1396,7 +1417,7 @@ static void intel_sdvo_restore(struct drm_connector *connector)
struct drm_device *dev = connector->dev;
struct drm_encoder *encoder = intel_best_encoder(connector);
struct intel_encoder *intel_encoder = to_intel_encoder(encoder);
- struct intel_sdvo_priv *sdvo_priv = intel_encoder->dev_priv;
+ struct intel_sdvo_encoder *sdvo_encoder = intel_encoder->dev_priv;
int o;
int i;
bool input1, input2;
@@ -1407,41 +1428,41 @@ static void intel_sdvo_restore(struct drm_connector *connector)
for (o = SDVO_OUTPUT_FIRST; o <= SDVO_OUTPUT_LAST; o++)
{
u16 this_output = (1 << o);
- if (sdvo_priv->caps.output_flags & this_output) {
+ if (sdvo_encoder->caps.output_flags & this_output) {
intel_sdvo_set_target_output(intel_encoder, this_output);
- intel_sdvo_set_output_timing(intel_encoder, &sdvo_priv->save_output_dtd[o]);
+ intel_sdvo_set_output_timing(intel_encoder, &sdvo_encoder->save_output_dtd[o]);
}
}
- if (sdvo_priv->caps.sdvo_inputs_mask & 0x1) {
+ if (sdvo_encoder->caps.sdvo_inputs_mask & 0x1) {
intel_sdvo_set_target_input(intel_encoder, true, false);
- intel_sdvo_set_input_timing(intel_encoder, &sdvo_priv->save_input_dtd_1);
+ intel_sdvo_set_input_timing(intel_encoder, &sdvo_encoder->save_input_dtd_1);
}
- if (sdvo_priv->caps.sdvo_inputs_mask & 0x2) {
+ if (sdvo_encoder->caps.sdvo_inputs_mask & 0x2) {
intel_sdvo_set_target_input(intel_encoder, false, true);
- intel_sdvo_set_input_timing(intel_encoder, &sdvo_priv->save_input_dtd_2);
+ intel_sdvo_set_input_timing(intel_encoder, &sdvo_encoder->save_input_dtd_2);
}
- intel_sdvo_set_clock_rate_mult(intel_encoder, sdvo_priv->save_sdvo_mult);
+ intel_sdvo_set_clock_rate_mult(intel_encoder, sdvo_encoder->save_sdvo_mult);
- if (sdvo_priv->is_tv) {
+ if (sdvo_encoder->is_tv) {
/* XXX: Restore TV format/enhancements. */
}
- intel_sdvo_write_sdvox(intel_encoder, sdvo_priv->save_SDVOX);
+ intel_sdvo_write_sdvox(intel_encoder, sdvo_encoder->save_SDVOX);
- if (sdvo_priv->save_SDVOX & SDVO_ENABLE)
+ if (sdvo_encoder->save_SDVOX & SDVO_ENABLE)
{
for (i = 0; i < 2; i++)
intel_wait_for_vblank(dev);
status = intel_sdvo_get_trained_inputs(intel_encoder, &input1, &input2);
if (status == SDVO_CMD_STATUS_SUCCESS && !input1)
DRM_DEBUG_KMS("First %s output reported failure to "
- "sync\n", SDVO_NAME(sdvo_priv));
+ "sync\n", SDVO_NAME(sdvo_encoder));
}
- intel_sdvo_set_active_outputs(intel_encoder, sdvo_priv->save_active_outputs);
+ intel_sdvo_set_active_outputs(intel_encoder, sdvo_encoder->save_active_outputs);
}
static int intel_sdvo_mode_valid(struct drm_connector *connector,
@@ -1449,25 +1470,25 @@ static int intel_sdvo_mode_valid(struct drm_connector *connector,
{
struct drm_encoder *encoder = intel_best_encoder(connector);
struct intel_encoder *intel_encoder = to_intel_encoder(encoder);
- struct intel_sdvo_priv *sdvo_priv = intel_encoder->dev_priv;
+ struct intel_sdvo_encoder *sdvo_encoder = intel_encoder->dev_priv;
if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
return MODE_NO_DBLESCAN;
- if (sdvo_priv->pixel_clock_min > mode->clock)
+ if (sdvo_encoder->pixel_clock_min > mode->clock)
return MODE_CLOCK_LOW;
- if (sdvo_priv->pixel_clock_max < mode->clock)
+ if (sdvo_encoder->pixel_clock_max < mode->clock)
return MODE_CLOCK_HIGH;
- if (sdvo_priv->is_lvds == true) {
- if (sdvo_priv->sdvo_lvds_fixed_mode == NULL)
+ if (sdvo_encoder->is_lvds == true) {
+ if (sdvo_encoder->sdvo_lvds_fixed_mode == NULL)
return MODE_PANEL;
- if (mode->hdisplay > sdvo_priv->sdvo_lvds_fixed_mode->hdisplay)
+ if (mode->hdisplay > sdvo_encoder->sdvo_lvds_fixed_mode->hdisplay)
return MODE_PANEL;
- if (mode->vdisplay > sdvo_priv->sdvo_lvds_fixed_mode->vdisplay)
+ if (mode->vdisplay > sdvo_encoder->sdvo_lvds_fixed_mode->vdisplay)
return MODE_PANEL;
}
@@ -1563,30 +1584,30 @@ void intel_sdvo_set_hotplug(struct drm_connector *connector, int on)
static bool
intel_sdvo_multifunc_encoder(struct intel_encoder *intel_encoder)
{
- struct intel_sdvo_priv *sdvo_priv = intel_encoder->dev_priv;
+ struct intel_sdvo_encoder *sdvo_encoder = intel_encoder->dev_priv;
int caps = 0;
- if (sdvo_priv->caps.output_flags &
+ if (sdvo_encoder->caps.output_flags &
(SDVO_OUTPUT_TMDS0 | SDVO_OUTPUT_TMDS1))
caps++;
- if (sdvo_priv->caps.output_flags &
+ if (sdvo_encoder->caps.output_flags &
(SDVO_OUTPUT_RGB0 | SDVO_OUTPUT_RGB1))
caps++;
- if (sdvo_priv->caps.output_flags &
+ if (sdvo_encoder->caps.output_flags &
(SDVO_OUTPUT_SVID0 | SDVO_OUTPUT_SVID1))
caps++;
- if (sdvo_priv->caps.output_flags &
+ if (sdvo_encoder->caps.output_flags &
(SDVO_OUTPUT_CVBS0 | SDVO_OUTPUT_CVBS1))
caps++;
- if (sdvo_priv->caps.output_flags &
+ if (sdvo_encoder->caps.output_flags &
(SDVO_OUTPUT_YPRPB0 | SDVO_OUTPUT_YPRPB1))
caps++;
- if (sdvo_priv->caps.output_flags &
+ if (sdvo_encoder->caps.output_flags &
(SDVO_OUTPUT_SCART0 | SDVO_OUTPUT_SCART1))
caps++;
- if (sdvo_priv->caps.output_flags &
+ if (sdvo_encoder->caps.output_flags &
(SDVO_OUTPUT_LVDS0 | SDVO_OUTPUT_LVDS1))
caps++;
@@ -1629,7 +1650,8 @@ intel_sdvo_hdmi_sink_detect(struct drm_connector *connector, u16 response)
struct drm_encoder *encoder = intel_best_encoder(connector);
struct intel_encoder *intel_encoder = to_intel_encoder(encoder);
struct intel_connector *intel_connector = to_intel_connector(connector);
- struct intel_sdvo_priv *sdvo_priv = intel_encoder->dev_priv;
+ struct intel_sdvo_encoder *sdvo_encoder = intel_encoder->dev_priv;
+ struct intel_sdvo_connector *sdvo_connector = intel_connector->dev_priv;
enum drm_connector_status status = connector_status_connected;
struct edid *edid = NULL;
@@ -1638,43 +1660,44 @@ intel_sdvo_hdmi_sink_detect(struct drm_connector *connector, u16 response)
/* This is only applied to SDVO cards with multiple outputs */
if (edid == NULL && intel_sdvo_multifunc_encoder(intel_encoder)) {
uint8_t saved_ddc, temp_ddc;
- saved_ddc = sdvo_priv->ddc_bus;
- temp_ddc = sdvo_priv->ddc_bus >> 1;
+ saved_ddc = sdvo_encoder->ddc_bus;
+ temp_ddc = sdvo_encoder->ddc_bus >> 1;
/*
* Don't use the 1 as the argument of DDC bus switch to get
* the EDID. It is used for SDVO SPD ROM.
*/
while(temp_ddc > 1) {
- sdvo_priv->ddc_bus = temp_ddc;
+ sdvo_encoder->ddc_bus = temp_ddc;
edid = drm_get_edid(connector, intel_connector->ddc_bus);
if (edid) {
/*
* When we can get the EDID, maybe it is the
* correct DDC bus. Update it.
*/
- sdvo_priv->ddc_bus = temp_ddc;
+ sdvo_encoder->ddc_bus = temp_ddc;
break;
}
temp_ddc >>= 1;
}
if (edid == NULL)
- sdvo_priv->ddc_bus = saved_ddc;
+ sdvo_encoder->ddc_bus = saved_ddc;
}
/* when there is no edid and no monitor is connected with VGA
* port, try to use the CRT ddc to read the EDID for DVI-connector
*/
if (edid == NULL &&
- sdvo_priv->analog_ddc_bus &&
+ sdvo_connector->analog_ddc_bus &&
!intel_analog_is_connected(connector->dev))
edid = drm_get_edid(connector,
- sdvo_priv->analog_ddc_bus);
+ sdvo_connector->analog_ddc_bus);
+
if (edid != NULL) {
/* Don't report the output as connected if it's a DVI-I
* connector with a non-digital EDID coming out.
*/
if (response & (SDVO_OUTPUT_TMDS0 | SDVO_OUTPUT_TMDS1)) {
if (edid->input & DRM_EDID_INPUT_DIGITAL)
- sdvo_priv->is_hdmi =
+ sdvo_encoder->is_hdmi =
drm_detect_hdmi_monitor(edid);
else
status = connector_status_disconnected;
@@ -1696,11 +1719,13 @@ static enum drm_connector_status intel_sdvo_detect(struct drm_connector *connect
struct drm_encoder *encoder = intel_best_encoder(connector);
struct intel_encoder *intel_encoder = to_intel_encoder(encoder);
struct intel_connector *intel_connector = to_intel_connector(connector);
- struct intel_sdvo_priv *sdvo_priv = intel_encoder->dev_priv;
+ struct intel_sdvo_encoder *sdvo_encoder = intel_encoder->dev_priv;
+ struct intel_sdvo_connector *sdvo_connector = intel_connector->dev_priv;
+ enum drm_connector_status ret;
intel_sdvo_write_cmd(intel_encoder,
SDVO_CMD_GET_ATTACHED_DISPLAYS, NULL, 0);
- if (sdvo_priv->is_tv) {
+ if (sdvo_encoder->is_tv) {
/* add 30ms delay when the output type is SDVO-TV */
mdelay(30);
}
@@ -1714,23 +1739,36 @@ static enum drm_connector_status intel_sdvo_detect(struct drm_connector *connect
if (response == 0)
return connector_status_disconnected;
- if (intel_sdvo_multifunc_encoder(intel_encoder) &&
- sdvo_priv->attached_output != response) {
- if (sdvo_priv->controlled_output != response &&
- intel_sdvo_output_setup(intel_encoder, intel_connector,
- response) != true)
- return connector_status_unknown;
- sdvo_priv->attached_output = response;
+ sdvo_encoder->attached_output = response;
+
+ if ((sdvo_connector->output_flag & response) == 0)
+ ret = connector_status_disconnected;
+ else if (response & (SDVO_OUTPUT_TMDS0 | SDVO_OUTPUT_TMDS1))
+ ret = intel_sdvo_hdmi_sink_detect(connector, response);
+ else
+ ret = connector_status_connected;
+
+ /* May update encoder flag for like clock for SDVO TV, etc.*/
+ if (ret == connector_status_connected) {
+ sdvo_encoder->is_tv = false;
+ sdvo_encoder->is_lvds = false;
+ intel_encoder->needs_tv_clock = false;
+
+ if (response & SDVO_TV_MASK) {
+ sdvo_encoder->is_tv = true;
+ intel_encoder->needs_tv_clock = true;
+ }
+ if (response & SDVO_LVDS_MASK)
+ sdvo_encoder->is_lvds = true;
}
- return intel_sdvo_hdmi_sink_detect(connector, response);
+
+ return ret;
}
static void intel_sdvo_get_ddc_modes(struct drm_connector *connector)
{
- struct drm_encoder *encoder = intel_best_encoder(connector);
- struct intel_encoder *intel_encoder = to_intel_encoder(encoder);
struct intel_connector *intel_connector = to_intel_connector(connector);
- struct intel_sdvo_priv *sdvo_priv = intel_encoder->dev_priv;
+ struct intel_sdvo_connector *sdvo_connector = intel_connector->dev_priv;
int num_modes;
/* set the bus switch and get the modes */
@@ -1743,14 +1781,14 @@ static void intel_sdvo_get_ddc_modes(struct drm_connector *connector)
* which case we'll look there for the digital DDC data.
*/
if (num_modes == 0 &&
- sdvo_priv->analog_ddc_bus &&
+ sdvo_connector->analog_ddc_bus &&
!intel_analog_is_connected(intel_connector->base.dev)) {
struct i2c_adapter *digital_ddc_bus;
/* Switch to the analog ddc bus and try that
*/
digital_ddc_bus = intel_connector->ddc_bus;
- intel_connector->ddc_bus = sdvo_priv->analog_ddc_bus;
+ intel_connector->ddc_bus = sdvo_connector->analog_ddc_bus;
(void) intel_ddc_get_modes(intel_connector);
@@ -1827,7 +1865,7 @@ static void intel_sdvo_get_tv_modes(struct drm_connector *connector)
{
struct drm_encoder *encoder = intel_best_encoder(connector);
struct intel_encoder *intel_encoder = to_intel_encoder(encoder);
- struct intel_sdvo_priv *sdvo_priv = intel_encoder->dev_priv;
+ struct intel_sdvo_encoder *sdvo_encoder = intel_encoder->dev_priv;
struct intel_sdvo_sdtv_resolution_request tv_res;
uint32_t reply = 0, format_map = 0;
int i;
@@ -1838,7 +1876,7 @@ static void intel_sdvo_get_tv_modes(struct drm_connector *connector)
* format.
*/
for (i = 0; i < TV_FORMAT_NUM; i++)
- if (tv_format_names[i] == sdvo_priv->tv_format_name)
+ if (tv_format_names[i] == sdvo_encoder->tv_format_name)
break;
format_map = (1 << i);
@@ -1847,7 +1885,7 @@ static void intel_sdvo_get_tv_modes(struct drm_connector *connector)
sizeof(format_map) ? sizeof(format_map) :
sizeof(struct intel_sdvo_sdtv_resolution_request));
- intel_sdvo_set_target_output(intel_encoder, sdvo_priv->controlled_output);
+ intel_sdvo_set_target_output(intel_encoder, sdvo_encoder->attached_output);
intel_sdvo_write_cmd(intel_encoder, SDVO_CMD_GET_SDTV_RESOLUTION_SUPPORT,
&tv_res, sizeof(tv_res));
@@ -1871,7 +1909,7 @@ static void intel_sdvo_get_lvds_modes(struct drm_connector *connector)
struct drm_encoder *encoder = intel_best_encoder(connector);
struct intel_encoder *intel_encoder = to_intel_encoder(encoder);
struct intel_connector *intel_connector = to_intel_connector(connector);
- struct intel_sdvo_priv *sdvo_priv = intel_encoder->dev_priv;
+ struct intel_sdvo_encoder *sdvo_encoder = intel_encoder->dev_priv;
struct drm_i915_private *dev_priv = connector->dev->dev_private;
struct drm_display_mode *newmode;
@@ -1899,7 +1937,7 @@ static void intel_sdvo_get_lvds_modes(struct drm_connector *connector)
end:
list_for_each_entry(newmode, &connector->probed_modes, head) {
if (newmode->type & DRM_MODE_TYPE_PREFERRED) {
- sdvo_priv->sdvo_lvds_fixed_mode =
+ sdvo_encoder->sdvo_lvds_fixed_mode =
drm_mode_duplicate(connector->dev, newmode);
break;
}
@@ -1909,13 +1947,12 @@ end:
static int intel_sdvo_get_modes(struct drm_connector *connector)
{
- struct drm_encoder *encoder = intel_best_encoder(connector);
- struct intel_encoder *intel_encoder = to_intel_encoder(encoder);
- struct intel_sdvo_priv *sdvo_priv = intel_encoder->dev_priv;
+ struct intel_connector *intel_connector = to_intel_connector(connector);
+ struct intel_sdvo_connector *sdvo_connector = intel_connector->dev_priv;
- if (sdvo_priv->is_tv)
+ if (SDVO_CONNECTOR_IS_TV(sdvo_connector))
intel_sdvo_get_tv_modes(connector);
- else if (sdvo_priv->is_lvds == true)
+ else if (SDVO_CONNECTOR_IS_LVDS(sdvo_connector))
intel_sdvo_get_lvds_modes(connector);
else
intel_sdvo_get_ddc_modes(connector);
@@ -1928,65 +1965,56 @@ static int intel_sdvo_get_modes(struct drm_connector *connector)
static
void intel_sdvo_destroy_enhance_property(struct drm_connector *connector)
{
- struct drm_encoder *encoder = intel_best_encoder(connector);
- struct intel_encoder *intel_encoder = to_intel_encoder(encoder);
- struct intel_sdvo_priv *sdvo_priv = intel_encoder->dev_priv;
+ struct intel_connector *intel_connector = to_intel_connector(connector);
+ struct intel_sdvo_connector *sdvo_connector = intel_connector->dev_priv;
struct drm_device *dev = connector->dev;
- if (sdvo_priv->is_tv) {
- if (sdvo_priv->left_property)
- drm_property_destroy(dev, sdvo_priv->left_property);
- if (sdvo_priv->right_property)
- drm_property_destroy(dev, sdvo_priv->right_property);
- if (sdvo_priv->top_property)
- drm_property_destroy(dev, sdvo_priv->top_property);
- if (sdvo_priv->bottom_property)
- drm_property_destroy(dev, sdvo_priv->bottom_property);
- if (sdvo_priv->hpos_property)
- drm_property_destroy(dev, sdvo_priv->hpos_property);
- if (sdvo_priv->vpos_property)
- drm_property_destroy(dev, sdvo_priv->vpos_property);
- }
- if (sdvo_priv->is_tv) {
- if (sdvo_priv->saturation_property)
+ if (SDVO_CONNECTOR_IS_TV(sdvo_connector)) {
+ if (sdvo_connector->left_property)
+ drm_property_destroy(dev, sdvo_connector->left_property);
+ if (sdvo_connector->right_property)
+ drm_property_destroy(dev, sdvo_connector->right_property);
+ if (sdvo_connector->top_property)
+ drm_property_destroy(dev, sdvo_connector->top_property);
+ if (sdvo_connector->bottom_property)
+ drm_property_destroy(dev, sdvo_connector->bottom_property);
+ if (sdvo_connector->hpos_property)
+ drm_property_destroy(dev, sdvo_connector->hpos_property);
+ if (sdvo_connector->vpos_property)
+ drm_property_destroy(dev, sdvo_connector->vpos_property);
+ if (sdvo_connector->saturation_property)
drm_property_destroy(dev,
- sdvo_priv->saturation_property);
- if (sdvo_priv->contrast_property)
+ sdvo_connector->saturation_property);
+ if (sdvo_connector->contrast_property)
drm_property_destroy(dev,
- sdvo_priv->contrast_property);
- if (sdvo_priv->hue_property)
- drm_property_destroy(dev, sdvo_priv->hue_property);
+ sdvo_connector->contrast_property);
+ if (sdvo_connector->hue_property)
+ drm_property_destroy(dev, sdvo_connector->hue_property);
}
- if (sdvo_priv->is_tv || sdvo_priv->is_lvds) {
- if (sdvo_priv->brightness_property)
+ if (SDVO_CONNECTOR_IS_TV(sdvo_connector) ||
+ SDVO_CONNECTOR_IS_LVDS(sdvo_connector)) {
+ if (sdvo_connector->brightness_property)
drm_property_destroy(dev,
- sdvo_priv->brightness_property);
+ sdvo_connector->brightness_property);
}
return;
}
static void intel_sdvo_destroy(struct drm_connector *connector)
{
- struct drm_encoder *encoder = intel_best_encoder(connector);
- struct intel_encoder *intel_encoder = to_intel_encoder(encoder);
struct intel_connector *intel_connector = to_intel_connector(connector);
- struct intel_sdvo_priv *sdvo_priv = intel_encoder->dev_priv;
+ struct intel_sdvo_connector *sdvo_connector = intel_connector->dev_priv;
if (intel_connector->ddc_bus)
intel_i2c_destroy(intel_connector->ddc_bus);
- if (sdvo_priv->analog_ddc_bus)
- intel_i2c_destroy(sdvo_priv->analog_ddc_bus);
-
- if (sdvo_priv->sdvo_lvds_fixed_mode != NULL)
- drm_mode_destroy(connector->dev,
- sdvo_priv->sdvo_lvds_fixed_mode);
+ if (sdvo_connector->analog_ddc_bus)
+ intel_i2c_destroy(sdvo_connector->analog_ddc_bus);
- if (sdvo_priv->tv_format_property)
+ if (sdvo_connector->tv_format_property)
drm_property_destroy(connector->dev,
- sdvo_priv->tv_format_property);
+ sdvo_connector->tv_format_property);
- if (sdvo_priv->is_tv || sdvo_priv->is_lvds)
- intel_sdvo_destroy_enhance_property(connector);
+ intel_sdvo_destroy_enhance_property(connector);
drm_sysfs_connector_remove(connector);
drm_connector_cleanup(connector);
@@ -2001,7 +2029,9 @@ intel_sdvo_set_property(struct drm_connector *connector,
{
struct drm_encoder *encoder = intel_best_encoder(connector);
struct intel_encoder *intel_encoder = to_intel_encoder(encoder);
- struct intel_sdvo_priv *sdvo_priv = intel_encoder->dev_priv;
+ struct intel_sdvo_encoder *sdvo_encoder = intel_encoder->dev_priv;
+ struct intel_connector *intel_connector = to_intel_connector(connector);
+ struct intel_sdvo_connector *sdvo_connector = intel_connector->dev_priv;
struct drm_crtc *crtc = encoder->crtc;
int ret = 0;
bool changed = false;
@@ -2012,101 +2042,102 @@ intel_sdvo_set_property(struct drm_connector *connector,
if (ret < 0)
goto out;
- if (property == sdvo_priv->tv_format_property) {
+ if (property == sdvo_connector->tv_format_property) {
if (val >= TV_FORMAT_NUM) {
ret = -EINVAL;
goto out;
}
- if (sdvo_priv->tv_format_name ==
- sdvo_priv->tv_format_supported[val])
+ if (sdvo_encoder->tv_format_name ==
+ sdvo_connector->tv_format_supported[val])
goto out;
- sdvo_priv->tv_format_name = sdvo_priv->tv_format_supported[val];
+ sdvo_encoder->tv_format_name = sdvo_connector->tv_format_supported[val];
changed = true;
}
- if (sdvo_priv->is_tv || sdvo_priv->is_lvds) {
+ if (SDVO_CONNECTOR_IS_TV(sdvo_connector) ||
+ SDVO_CONNECTOR_IS_LVDS(sdvo_connector)) {
cmd = 0;
temp_value = val;
- if (sdvo_priv->left_property == property) {
+ if (sdvo_connector->left_property == property) {
drm_connector_property_set_value(connector,
- sdvo_priv->right_property, val);
- if (sdvo_priv->left_margin == temp_value)
+ sdvo_connector->right_property, val);
+ if (sdvo_connector->left_margin == temp_value)
goto out;
- sdvo_priv->left_margin = temp_value;
- sdvo_priv->right_margin = temp_value;
- temp_value = sdvo_priv->max_hscan -
- sdvo_priv->left_margin;
+ sdvo_connector->left_margin = temp_value;
+ sdvo_connector->right_margin = temp_value;
+ temp_value = sdvo_connector->max_hscan -
+ sdvo_connector->left_margin;
cmd = SDVO_CMD_SET_OVERSCAN_H;
- } else if (sdvo_priv->right_property == property) {
+ } else if (sdvo_connector->right_property == property) {
drm_connector_property_set_value(connector,
- sdvo_priv->left_property, val);
- if (sdvo_priv->right_margin == temp_value)
+ sdvo_connector->left_property, val);
+ if (sdvo_connector->right_margin == temp_value)
goto out;
- sdvo_priv->left_margin = temp_value;
- sdvo_priv->right_margin = temp_value;
- temp_value = sdvo_priv->max_hscan -
- sdvo_priv->left_margin;
+ sdvo_connector->left_margin = temp_value;
+ sdvo_connector->right_margin = temp_value;
+ temp_value = sdvo_connector->max_hscan -
+ sdvo_connector->left_margin;
cmd = SDVO_CMD_SET_OVERSCAN_H;
- } else if (sdvo_priv->top_property == property) {
+ } else if (sdvo_connector->top_property == property) {
drm_connector_property_set_value(connector,
- sdvo_priv->bottom_property, val);
- if (sdvo_priv->top_margin == temp_value)
+ sdvo_connector->bottom_property, val);
+ if (sdvo_connector->top_margin == temp_value)
goto out;
- sdvo_priv->top_margin = temp_value;
- sdvo_priv->bottom_margin = temp_value;
- temp_value = sdvo_priv->max_vscan -
- sdvo_priv->top_margin;
+ sdvo_connector->top_margin = temp_value;
+ sdvo_connector->bottom_margin = temp_value;
+ temp_value = sdvo_connector->max_vscan -
+ sdvo_connector->top_margin;
cmd = SDVO_CMD_SET_OVERSCAN_V;
- } else if (sdvo_priv->bottom_property == property) {
+ } else if (sdvo_connector->bottom_property == property) {
drm_connector_property_set_value(connector,
- sdvo_priv->top_property, val);
- if (sdvo_priv->bottom_margin == temp_value)
+ sdvo_connector->top_property, val);
+ if (sdvo_connector->bottom_margin == temp_value)
goto out;
- sdvo_priv->top_margin = temp_value;
- sdvo_priv->bottom_margin = temp_value;
- temp_value = sdvo_priv->max_vscan -
- sdvo_priv->top_margin;
+ sdvo_connector->top_margin = temp_value;
+ sdvo_connector->bottom_margin = temp_value;
+ temp_value = sdvo_connector->max_vscan -
+ sdvo_connector->top_margin;
cmd = SDVO_CMD_SET_OVERSCAN_V;
- } else if (sdvo_priv->hpos_property == property) {
- if (sdvo_priv->cur_hpos == temp_value)
+ } else if (sdvo_connector->hpos_property == property) {
+ if (sdvo_connector->cur_hpos == temp_value)
goto out;
cmd = SDVO_CMD_SET_POSITION_H;
- sdvo_priv->cur_hpos = temp_value;
- } else if (sdvo_priv->vpos_property == property) {
- if (sdvo_priv->cur_vpos == temp_value)
+ sdvo_connector->cur_hpos = temp_value;
+ } else if (sdvo_connector->vpos_property == property) {
+ if (sdvo_connector->cur_vpos == temp_value)
goto out;
cmd = SDVO_CMD_SET_POSITION_V;
- sdvo_priv->cur_vpos = temp_value;
- } else if (sdvo_priv->saturation_property == property) {
- if (sdvo_priv->cur_saturation == temp_value)
+ sdvo_connector->cur_vpos = temp_value;
+ } else if (sdvo_connector->saturation_property == property) {
+ if (sdvo_connector->cur_saturation == temp_value)
goto out;
cmd = SDVO_CMD_SET_SATURATION;
- sdvo_priv->cur_saturation = temp_value;
- } else if (sdvo_priv->contrast_property == property) {
- if (sdvo_priv->cur_contrast == temp_value)
+ sdvo_connector->cur_saturation = temp_value;
+ } else if (sdvo_connector->contrast_property == property) {
+ if (sdvo_connector->cur_contrast == temp_value)
goto out;
cmd = SDVO_CMD_SET_CONTRAST;
- sdvo_priv->cur_contrast = temp_value;
- } else if (sdvo_priv->hue_property == property) {
- if (sdvo_priv->cur_hue == temp_value)
+ sdvo_connector->cur_contrast = temp_value;
+ } else if (sdvo_connector->hue_property == property) {
+ if (sdvo_connector->cur_hue == temp_value)
goto out;
cmd = SDVO_CMD_SET_HUE;
- sdvo_priv->cur_hue = temp_value;
- } else if (sdvo_priv->brightness_property == property) {
- if (sdvo_priv->cur_brightness == temp_value)
+ sdvo_connector->cur_hue = temp_value;
+ } else if (sdvo_connector->brightness_property == property) {
+ if (sdvo_connector->cur_brightness == temp_value)
goto out;
cmd = SDVO_CMD_SET_BRIGHTNESS;
- sdvo_priv->cur_brightness = temp_value;
+ sdvo_connector->cur_brightness = temp_value;
}
if (cmd) {
intel_sdvo_write_cmd(intel_encoder, cmd, &temp_value, 2);
@@ -2153,9 +2184,15 @@ static const struct drm_connector_helper_funcs intel_sdvo_connector_helper_funcs
static void intel_sdvo_enc_destroy(struct drm_encoder *encoder)
{
struct intel_encoder *intel_encoder = to_intel_encoder(encoder);
+ struct intel_sdvo_encoder *sdvo_encoder = intel_encoder->dev_priv;
if (intel_encoder->i2c_bus)
intel_i2c_destroy(intel_encoder->i2c_bus);
+
+ if (sdvo_encoder->sdvo_lvds_fixed_mode != NULL)
+ drm_mode_destroy(encoder->dev,
+ sdvo_encoder->sdvo_lvds_fixed_mode);
+
drm_encoder_cleanup(encoder);
kfree(encoder);
}
@@ -2173,7 +2210,7 @@ static const struct drm_encoder_funcs intel_sdvo_enc_funcs = {
* outputs, then LVDS outputs.
*/
static void
-intel_sdvo_select_ddc_bus(struct intel_sdvo_priv *dev_priv)
+intel_sdvo_select_ddc_bus(struct intel_sdvo_encoder *dev_priv)
{
uint16_t mask = 0;
unsigned int num_bits;
@@ -2210,15 +2247,18 @@ intel_sdvo_select_ddc_bus(struct intel_sdvo_priv *dev_priv)
}
static bool
-intel_sdvo_get_digital_encoding_mode(struct intel_encoder *intel_encoder)
+intel_sdvo_get_digital_encoding_mode(struct intel_encoder *intel_encoder, int device)
{
- struct intel_sdvo_priv *sdvo_priv = intel_encoder->dev_priv;
+ struct intel_sdvo_encoder *sdvo_encoder = intel_encoder->dev_priv;
uint8_t status;
- intel_sdvo_set_target_output(intel_encoder, sdvo_priv->controlled_output);
+ if (device == 0)
+ intel_sdvo_set_target_output(intel_encoder, SDVO_OUTPUT_TMDS0);
+ else
+ intel_sdvo_set_target_output(intel_encoder, SDVO_OUTPUT_TMDS1);
intel_sdvo_write_cmd(intel_encoder, SDVO_CMD_GET_ENCODE, NULL, 0);
- status = intel_sdvo_read_response(intel_encoder, &sdvo_priv->is_hdmi, 1);
+ status = intel_sdvo_read_response(intel_encoder, &sdvo_encoder->is_hdmi, 1);
if (status != SDVO_CMD_STATUS_SUCCESS)
return false;
return true;
@@ -2229,16 +2269,13 @@ intel_sdvo_chan_to_intel_connector(struct intel_i2c_chan *chan)
{
struct drm_device *dev = chan->drm_dev;
struct drm_connector *connector;
- struct intel_connector *intel_connector = NULL;
- list_for_each_entry(connector,
- &dev->mode_config.connector_list, head) {
+ list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
if (to_intel_connector(connector)->ddc_bus == &chan->adapter) {
- intel_connector = to_intel_connector(connector);
- break;
+ return to_intel_connector(connector);
}
}
- return intel_connector;
+ return NULL;
}
static int intel_sdvo_master_xfer(struct i2c_adapter *i2c_adap,
@@ -2248,7 +2285,7 @@ static int intel_sdvo_master_xfer(struct i2c_adapter *i2c_adap,
struct drm_encoder *encoder;
struct intel_encoder *intel_encoder;
struct intel_connector *intel_connector;
- struct intel_sdvo_priv *sdvo_priv;
+ struct intel_sdvo_encoder *sdvo_encoder;
struct i2c_algo_bit_data *algo_data;
const struct i2c_algorithm *algo;
@@ -2263,10 +2300,10 @@ static int intel_sdvo_master_xfer(struct i2c_adapter *i2c_adap,
encoder = intel_best_encoder(connector);
intel_encoder = to_intel_encoder(encoder);
- sdvo_priv = intel_encoder->dev_priv;
+ sdvo_encoder = intel_encoder->dev_priv;
algo = intel_encoder->i2c_bus->algo;
- intel_sdvo_set_control_bus_switch(intel_encoder, sdvo_priv->ddc_bus);
+ intel_sdvo_set_control_bus_switch(intel_encoder, sdvo_encoder->ddc_bus);
return algo->master_xfer(i2c_adap, msgs, num);
}
@@ -2312,125 +2349,266 @@ intel_sdvo_get_slave_addr(struct drm_device *dev, int output_device)
}
static bool
-intel_sdvo_output_setup(struct intel_encoder *intel_encoder,
- struct intel_connector *intel_connector,
- uint16_t flags)
+intel_sdvo_connector_alloc (struct drm_device *dev, struct intel_connector **ret)
+{
+ struct intel_connector *intel_connector;
+ struct intel_sdvo_connector *sdvo_connector;
+ struct drm_connector *connector;
+
+ *ret = kzalloc(sizeof(*intel_connector) +
+ sizeof(*sdvo_connector), GFP_KERNEL);
+ if (!*ret)
+ return false;
+ intel_connector = *ret;
+ connector = &intel_connector->base;
+ sdvo_connector = (struct intel_sdvo_connector *)(intel_connector + 1);
+ intel_connector->dev_priv = sdvo_connector;
+
+ intel_connector->ddc_bus = intel_i2c_create(dev, GPIOE, "SDVO DDC BUS");
+ sdvo_connector->analog_ddc_bus = intel_i2c_create(dev, GPIOA,
+ "SDVO/VGA DDC BUS");
+ if (!intel_connector->ddc_bus || !sdvo_connector->analog_ddc_bus) {
+ kfree(intel_connector);
+ return false;
+ }
+ /* Wrap with our custom algo which switches to DDC mode */
+ intel_connector->ddc_bus->algo = &intel_sdvo_i2c_bit_algo;
+ return true;
+}
+
+static void
+intel_sdvo_connector_create (struct drm_encoder *encoder, struct drm_connector *connector)
+{
+ drm_connector_init(encoder->dev, connector, &intel_sdvo_connector_funcs,
+ connector->connector_type);
+
+ drm_connector_helper_add(connector, &intel_sdvo_connector_helper_funcs);
+
+ connector->interlace_allowed = 0;
+ connector->doublescan_allowed = 0;
+ connector->display_info.subpixel_order = SubPixelHorizontalRGB;
+
+ drm_mode_connector_attach_encoder(connector, encoder);
+ drm_sysfs_connector_add(connector);
+}
+
+static bool
+intel_sdvo_dvi_init(struct intel_encoder *intel_encoder, int device)
{
struct drm_encoder *encoder = &intel_encoder->base;
- struct drm_connector *connector = &intel_connector->base;
- struct intel_sdvo_priv *sdvo_priv = intel_encoder->dev_priv;
- bool ret = true, registered = false;
+ struct intel_sdvo_encoder *sdvo_encoder = intel_encoder->dev_priv;
+ struct drm_connector *connector;
+ struct intel_connector *intel_connector;
+ struct intel_sdvo_connector *sdvo_connector;
- sdvo_priv->is_tv = false;
- intel_encoder->needs_tv_clock = false;
- sdvo_priv->is_lvds = false;
+ if (!intel_sdvo_connector_alloc(encoder->dev, &intel_connector))
+ return false;
- if (device_is_registered(&connector->kdev)) {
- drm_sysfs_connector_remove(connector);
- registered = true;
- }
+ sdvo_connector = intel_connector->dev_priv;
- if (flags &
- (SDVO_OUTPUT_TMDS0 | SDVO_OUTPUT_TMDS1)) {
- if (sdvo_priv->caps.output_flags & SDVO_OUTPUT_TMDS0)
- sdvo_priv->controlled_output = SDVO_OUTPUT_TMDS0;
- else
- sdvo_priv->controlled_output = SDVO_OUTPUT_TMDS1;
+ if (device == 0) {
+ sdvo_encoder->controlled_output |= SDVO_OUTPUT_TMDS0;
+ sdvo_connector->output_flag = SDVO_OUTPUT_TMDS0;
+ } else if (device == 1) {
+ sdvo_encoder->controlled_output |= SDVO_OUTPUT_TMDS1;
+ sdvo_connector->output_flag = SDVO_OUTPUT_TMDS1;
+ }
- encoder->encoder_type = DRM_MODE_ENCODER_TMDS;
- connector->connector_type = DRM_MODE_CONNECTOR_DVID;
+ connector = &intel_connector->base;
+ encoder->encoder_type = DRM_MODE_ENCODER_TMDS;
+ connector->connector_type = DRM_MODE_CONNECTOR_DVID;
- if (intel_sdvo_get_supp_encode(intel_encoder,
- &sdvo_priv->encode) &&
- intel_sdvo_get_digital_encoding_mode(intel_encoder) &&
- sdvo_priv->is_hdmi) {
+ if (intel_sdvo_get_supp_encode(intel_encoder, &sdvo_encoder->encode)
+ && intel_sdvo_get_digital_encoding_mode(intel_encoder, device)
+ && sdvo_encoder->is_hdmi) {
/* enable hdmi encoding mode if supported */
intel_sdvo_set_encode(intel_encoder, SDVO_ENCODE_HDMI);
intel_sdvo_set_colorimetry(intel_encoder,
SDVO_COLORIMETRY_RGB256);
connector->connector_type = DRM_MODE_CONNECTOR_HDMIA;
- intel_encoder->clone_mask =
- (1 << INTEL_SDVO_NON_TV_CLONE_BIT) |
- (1 << INTEL_ANALOG_CLONE_BIT);
- }
- } else if (flags & SDVO_OUTPUT_SVID0) {
-
- sdvo_priv->controlled_output = SDVO_OUTPUT_SVID0;
- encoder->encoder_type = DRM_MODE_ENCODER_TVDAC;
- connector->connector_type = DRM_MODE_CONNECTOR_SVIDEO;
- sdvo_priv->is_tv = true;
- intel_encoder->needs_tv_clock = true;
- intel_encoder->clone_mask = 1 << INTEL_SDVO_TV_CLONE_BIT;
- } else if (flags & SDVO_OUTPUT_RGB0) {
-
- sdvo_priv->controlled_output = SDVO_OUTPUT_RGB0;
- encoder->encoder_type = DRM_MODE_ENCODER_DAC;
- connector->connector_type = DRM_MODE_CONNECTOR_VGA;
- intel_encoder->clone_mask = (1 << INTEL_SDVO_NON_TV_CLONE_BIT) |
- (1 << INTEL_ANALOG_CLONE_BIT);
- } else if (flags & SDVO_OUTPUT_RGB1) {
-
- sdvo_priv->controlled_output = SDVO_OUTPUT_RGB1;
- encoder->encoder_type = DRM_MODE_ENCODER_DAC;
- connector->connector_type = DRM_MODE_CONNECTOR_VGA;
- intel_encoder->clone_mask = (1 << INTEL_SDVO_NON_TV_CLONE_BIT) |
- (1 << INTEL_ANALOG_CLONE_BIT);
- } else if (flags & SDVO_OUTPUT_CVBS0) {
-
- sdvo_priv->controlled_output = SDVO_OUTPUT_CVBS0;
- encoder->encoder_type = DRM_MODE_ENCODER_TVDAC;
- connector->connector_type = DRM_MODE_CONNECTOR_SVIDEO;
- sdvo_priv->is_tv = true;
- intel_encoder->needs_tv_clock = true;
- intel_encoder->clone_mask = 1 << INTEL_SDVO_TV_CLONE_BIT;
- } else if (flags & SDVO_OUTPUT_LVDS0) {
-
- sdvo_priv->controlled_output = SDVO_OUTPUT_LVDS0;
- encoder->encoder_type = DRM_MODE_ENCODER_LVDS;
- connector->connector_type = DRM_MODE_CONNECTOR_LVDS;
- sdvo_priv->is_lvds = true;
- intel_encoder->clone_mask = (1 << INTEL_ANALOG_CLONE_BIT) |
- (1 << INTEL_SDVO_LVDS_CLONE_BIT);
- } else if (flags & SDVO_OUTPUT_LVDS1) {
-
- sdvo_priv->controlled_output = SDVO_OUTPUT_LVDS1;
- encoder->encoder_type = DRM_MODE_ENCODER_LVDS;
- connector->connector_type = DRM_MODE_CONNECTOR_LVDS;
- sdvo_priv->is_lvds = true;
- intel_encoder->clone_mask = (1 << INTEL_ANALOG_CLONE_BIT) |
- (1 << INTEL_SDVO_LVDS_CLONE_BIT);
- } else {
+ }
+ intel_encoder->clone_mask = (1 << INTEL_SDVO_NON_TV_CLONE_BIT) |
+ (1 << INTEL_ANALOG_CLONE_BIT);
+
+ intel_sdvo_connector_create(encoder, connector);
+
+ return true;
+}
+
+static bool
+intel_sdvo_tv_init(struct intel_encoder *intel_encoder, int type)
+{
+ struct drm_encoder *encoder = &intel_encoder->base;
+ struct intel_sdvo_encoder *sdvo_encoder = intel_encoder->dev_priv;
+ struct drm_connector *connector;
+ struct intel_connector *intel_connector;
+ struct intel_sdvo_connector *sdvo_connector;
+
+ if (!intel_sdvo_connector_alloc(encoder->dev, &intel_connector))
+ return false;
+
+ connector = &intel_connector->base;
+ encoder->encoder_type = DRM_MODE_ENCODER_TVDAC;
+ connector->connector_type = DRM_MODE_CONNECTOR_SVIDEO;
+ sdvo_connector = intel_connector->dev_priv;
+
+ sdvo_encoder->controlled_output |= type;
+ sdvo_connector->output_flag = type;
+
+ sdvo_encoder->is_tv = true;
+ intel_encoder->needs_tv_clock = true;
+ intel_encoder->clone_mask = 1 << INTEL_SDVO_TV_CLONE_BIT;
+
+ intel_sdvo_connector_create(encoder, connector);
+
+ intel_sdvo_tv_create_property(encoder, connector);
+
+ intel_sdvo_create_enhance_property(encoder, connector);
+
+ return true;
+}
+
+static bool
+intel_sdvo_analog_init(struct intel_encoder *intel_encoder, int device)
+{
+ struct drm_encoder *encoder = &intel_encoder->base;
+ struct intel_sdvo_encoder *sdvo_encoder = intel_encoder->dev_priv;
+ struct drm_connector *connector;
+ struct intel_connector *intel_connector;
+ struct intel_sdvo_connector *sdvo_connector;
+
+ if (!intel_sdvo_connector_alloc(encoder->dev, &intel_connector))
+ return false;
+
+ connector = &intel_connector->base;
+ encoder->encoder_type = DRM_MODE_ENCODER_DAC;
+ connector->connector_type = DRM_MODE_CONNECTOR_VGA;
+ sdvo_connector = intel_connector->dev_priv;
+
+ if (device == 0) {
+ sdvo_encoder->controlled_output |= SDVO_OUTPUT_RGB0;
+ sdvo_connector->output_flag = SDVO_OUTPUT_RGB0;
+ } else if (device == 1) {
+ sdvo_encoder->controlled_output |= SDVO_OUTPUT_RGB1;
+ sdvo_connector->output_flag = SDVO_OUTPUT_RGB1;
+ }
+
+ intel_encoder->clone_mask = (1 << INTEL_SDVO_NON_TV_CLONE_BIT) |
+ (1 << INTEL_ANALOG_CLONE_BIT);
+
+ intel_sdvo_connector_create(encoder, connector);
+ return true;
+}
+
+static bool
+intel_sdvo_lvds_init(struct intel_encoder *intel_encoder, int device)
+{
+ struct drm_encoder *encoder = &intel_encoder->base;
+ struct intel_sdvo_encoder *sdvo_encoder = intel_encoder->dev_priv;
+ struct drm_connector *connector;
+ struct intel_connector *intel_connector;
+ struct intel_sdvo_connector *sdvo_connector;
+
+ if (!intel_sdvo_connector_alloc(encoder->dev, &intel_connector))
+ return false;
+
+ connector = &intel_connector->base;
+ encoder->encoder_type = DRM_MODE_ENCODER_LVDS;
+ connector->connector_type = DRM_MODE_CONNECTOR_LVDS;
+ sdvo_connector = intel_connector->dev_priv;
+
+ sdvo_encoder->is_lvds = true;
+
+ if (device == 0) {
+ sdvo_encoder->controlled_output |= SDVO_OUTPUT_LVDS0;
+ sdvo_connector->output_flag = SDVO_OUTPUT_LVDS0;
+ } else if (device == 1) {
+ sdvo_encoder->controlled_output |= SDVO_OUTPUT_LVDS1;
+ sdvo_connector->output_flag = SDVO_OUTPUT_LVDS1;
+ }
+
+ intel_encoder->clone_mask = (1 << INTEL_ANALOG_CLONE_BIT) |
+ (1 << INTEL_SDVO_LVDS_CLONE_BIT);
+
+ intel_sdvo_connector_create(encoder, connector);
+ intel_sdvo_create_enhance_property(encoder, connector);
+ return true;
+}
+
+static bool
+intel_sdvo_output_setup(struct intel_encoder *intel_encoder)
+{
+ struct intel_sdvo_encoder *sdvo_encoder = intel_encoder->dev_priv;
+ int flags = sdvo_encoder->caps.output_flags;
+
+ intel_encoder->needs_tv_clock = false;
+ sdvo_encoder->is_tv = false;
+ sdvo_encoder->is_lvds = false;
+
+ /* SDVO requires XXX1 function may not exist unless it has XXX0 function.*/
+
+ if (flags & SDVO_OUTPUT_TMDS0)
+ if (!intel_sdvo_dvi_init(intel_encoder, 0))
+ return false;
+
+ if ((flags & SDVO_TMDS_MASK) == SDVO_TMDS_MASK)
+ if (!intel_sdvo_dvi_init(intel_encoder, 1))
+ return false;
+
+ /* TV has no XXX1 function block */
+ if (flags & SDVO_OUTPUT_SVID0)
+ if (!intel_sdvo_tv_init(intel_encoder, SDVO_OUTPUT_SVID0))
+ return false;
+
+ if (flags & SDVO_OUTPUT_CVBS0)
+ if (!intel_sdvo_tv_init(intel_encoder, SDVO_OUTPUT_CVBS0))
+ return false;
+
+ if (flags & SDVO_OUTPUT_RGB0)
+ if (!intel_sdvo_analog_init(intel_encoder, 0))
+ return false;
+
+ if ((flags & SDVO_RGB_MASK) == SDVO_RGB_MASK)
+ if (!intel_sdvo_analog_init(intel_encoder, 1))
+ return false;
+
+ if (flags & SDVO_OUTPUT_LVDS0)
+ if (!intel_sdvo_lvds_init(intel_encoder, 0))
+ return false;
+
+ if ((flags & SDVO_LVDS_MASK) == SDVO_LVDS_MASK)
+ if (!intel_sdvo_lvds_init(intel_encoder, 1))
+ return false;
+ if ((flags & SDVO_OUTPUT_MASK) == 0) {
unsigned char bytes[2];
- sdvo_priv->controlled_output = 0;
- memcpy(bytes, &sdvo_priv->caps.output_flags, 2);
+ sdvo_encoder->controlled_output = 0;
+ memcpy(bytes, &sdvo_encoder->caps.output_flags, 2);
DRM_DEBUG_KMS("%s: Unknown SDVO output type (0x%02x%02x)\n",
- SDVO_NAME(sdvo_priv),
+ SDVO_NAME(sdvo_encoder),
bytes[0], bytes[1]);
- ret = false;
+ return false;
}
intel_encoder->crtc_mask = (1 << 0) | (1 << 1);
- if (ret && registered)
- ret = drm_sysfs_connector_add(connector) == 0 ? true : false;
-
-
- return ret;
+ return true;
}
-static void intel_sdvo_tv_create_property(struct drm_connector *connector)
+static void intel_sdvo_tv_create_property(struct drm_encoder *encoder,
+ struct drm_connector *connector)
{
- struct drm_encoder *encoder = intel_best_encoder(connector);
struct intel_encoder *intel_encoder = to_intel_encoder(encoder);
- struct intel_sdvo_priv *sdvo_priv = intel_encoder->dev_priv;
+ struct intel_connector *intel_connector = to_intel_connector(connector);
+ struct intel_sdvo_encoder *sdvo_encoder = intel_encoder->dev_priv;
+ struct intel_sdvo_connector *sdvo_connector = intel_connector->dev_priv;
struct intel_sdvo_tv_format format;
uint32_t format_map, i;
uint8_t status;
intel_sdvo_set_target_output(intel_encoder,
- sdvo_priv->controlled_output);
+ sdvo_encoder->attached_output);
intel_sdvo_write_cmd(intel_encoder,
SDVO_CMD_GET_SUPPORTED_TV_FORMATS, NULL, 0);
@@ -2445,36 +2623,37 @@ static void intel_sdvo_tv_create_property(struct drm_connector *connector)
if (format_map == 0)
return;
- sdvo_priv->format_supported_num = 0;
+ sdvo_connector->format_supported_num = 0;
for (i = 0 ; i < TV_FORMAT_NUM; i++)
if (format_map & (1 << i)) {
- sdvo_priv->tv_format_supported
- [sdvo_priv->format_supported_num++] =
+ sdvo_connector->tv_format_supported
+ [sdvo_connector->format_supported_num++] =
tv_format_names[i];
}
- sdvo_priv->tv_format_property =
+ sdvo_connector->tv_format_property =
drm_property_create(
connector->dev, DRM_MODE_PROP_ENUM,
- "mode", sdvo_priv->format_supported_num);
+ "mode", sdvo_connector->format_supported_num);
- for (i = 0; i < sdvo_priv->format_supported_num; i++)
+ for (i = 0; i < sdvo_connector->format_supported_num; i++)
drm_property_add_enum(
- sdvo_priv->tv_format_property, i,
- i, sdvo_priv->tv_format_supported[i]);
+ sdvo_connector->tv_format_property, i,
+ i, sdvo_connector->tv_format_supported[i]);
- sdvo_priv->tv_format_name = sdvo_priv->tv_format_supported[0];
+ sdvo_encoder->tv_format_name = sdvo_connector->tv_format_supported[0];
drm_connector_attach_property(
- connector, sdvo_priv->tv_format_property, 0);
+ connector, sdvo_connector->tv_format_property, 0);
}
-static void intel_sdvo_create_enhance_property(struct drm_connector *connector)
+static void intel_sdvo_create_enhance_property(struct drm_encoder *encoder,
+ struct drm_connector *connector)
{
- struct drm_encoder *encoder = intel_best_encoder(connector);
struct intel_encoder *intel_encoder = to_intel_encoder(encoder);
- struct intel_sdvo_priv *sdvo_priv = intel_encoder->dev_priv;
+ struct intel_connector *intel_connector = to_intel_connector(connector);
+ struct intel_sdvo_connector *sdvo_connector = intel_connector->dev_priv;
struct intel_sdvo_enhancements_reply sdvo_data;
struct drm_device *dev = connector->dev;
uint8_t status;
@@ -2493,7 +2672,7 @@ static void intel_sdvo_create_enhance_property(struct drm_connector *connector)
DRM_DEBUG_KMS("No enhancement is supported\n");
return;
}
- if (sdvo_priv->is_tv) {
+ if (SDVO_CONNECTOR_IS_TV(sdvo_connector)) {
/* when horizontal overscan is supported, Add the left/right
* property
*/
@@ -2515,25 +2694,25 @@ static void intel_sdvo_create_enhance_property(struct drm_connector *connector)
DRM_DEBUG_KMS("Incorrect SDVO h_overscan\n");
return;
}
- sdvo_priv->max_hscan = data_value[0];
- sdvo_priv->left_margin = data_value[0] - response;
- sdvo_priv->right_margin = sdvo_priv->left_margin;
- sdvo_priv->left_property =
+ sdvo_connector->max_hscan = data_value[0];
+ sdvo_connector->left_margin = data_value[0] - response;
+ sdvo_connector->right_margin = sdvo_connector->left_margin;
+ sdvo_connector->left_property =
drm_property_create(dev, DRM_MODE_PROP_RANGE,
"left_margin", 2);
- sdvo_priv->left_property->values[0] = 0;
- sdvo_priv->left_property->values[1] = data_value[0];
+ sdvo_connector->left_property->values[0] = 0;
+ sdvo_connector->left_property->values[1] = data_value[0];
drm_connector_attach_property(connector,
- sdvo_priv->left_property,
- sdvo_priv->left_margin);
- sdvo_priv->right_property =
+ sdvo_connector->left_property,
+ sdvo_connector->left_margin);
+ sdvo_connector->right_property =
drm_property_create(dev, DRM_MODE_PROP_RANGE,
"right_margin", 2);
- sdvo_priv->right_property->values[0] = 0;
- sdvo_priv->right_property->values[1] = data_value[0];
+ sdvo_connector->right_property->values[0] = 0;
+ sdvo_connector->right_property->values[1] = data_value[0];
drm_connector_attach_property(connector,
- sdvo_priv->right_property,
- sdvo_priv->right_margin);
+ sdvo_connector->right_property,
+ sdvo_connector->right_margin);
DRM_DEBUG_KMS("h_overscan: max %d, "
"default %d, current %d\n",
data_value[0], data_value[1], response);
@@ -2556,25 +2735,25 @@ static void intel_sdvo_create_enhance_property(struct drm_connector *connector)
DRM_DEBUG_KMS("Incorrect SDVO v_overscan\n");
return;
}
- sdvo_priv->max_vscan = data_value[0];
- sdvo_priv->top_margin = data_value[0] - response;
- sdvo_priv->bottom_margin = sdvo_priv->top_margin;
- sdvo_priv->top_property =
+ sdvo_connector->max_vscan = data_value[0];
+ sdvo_connector->top_margin = data_value[0] - response;
+ sdvo_connector->bottom_margin = sdvo_connector->top_margin;
+ sdvo_connector->top_property =
drm_property_create(dev, DRM_MODE_PROP_RANGE,
"top_margin", 2);
- sdvo_priv->top_property->values[0] = 0;
- sdvo_priv->top_property->values[1] = data_value[0];
+ sdvo_connector->top_property->values[0] = 0;
+ sdvo_connector->top_property->values[1] = data_value[0];
drm_connector_attach_property(connector,
- sdvo_priv->top_property,
- sdvo_priv->top_margin);
- sdvo_priv->bottom_property =
+ sdvo_connector->top_property,
+ sdvo_connector->top_margin);
+ sdvo_connector->bottom_property =
drm_property_create(dev, DRM_MODE_PROP_RANGE,
"bottom_margin", 2);
- sdvo_priv->bottom_property->values[0] = 0;
- sdvo_priv->bottom_property->values[1] = data_value[0];
+ sdvo_connector->bottom_property->values[0] = 0;
+ sdvo_connector->bottom_property->values[1] = data_value[0];
drm_connector_attach_property(connector,
- sdvo_priv->bottom_property,
- sdvo_priv->bottom_margin);
+ sdvo_connector->bottom_property,
+ sdvo_connector->bottom_margin);
DRM_DEBUG_KMS("v_overscan: max %d, "
"default %d, current %d\n",
data_value[0], data_value[1], response);
@@ -2596,16 +2775,16 @@ static void intel_sdvo_create_enhance_property(struct drm_connector *connector)
DRM_DEBUG_KMS("Incorrect SDVO get h_postion\n");
return;
}
- sdvo_priv->max_hpos = data_value[0];
- sdvo_priv->cur_hpos = response;
- sdvo_priv->hpos_property =
+ sdvo_connector->max_hpos = data_value[0];
+ sdvo_connector->cur_hpos = response;
+ sdvo_connector->hpos_property =
drm_property_create(dev, DRM_MODE_PROP_RANGE,
"hpos", 2);
- sdvo_priv->hpos_property->values[0] = 0;
- sdvo_priv->hpos_property->values[1] = data_value[0];
+ sdvo_connector->hpos_property->values[0] = 0;
+ sdvo_connector->hpos_property->values[1] = data_value[0];
drm_connector_attach_property(connector,
- sdvo_priv->hpos_property,
- sdvo_priv->cur_hpos);
+ sdvo_connector->hpos_property,
+ sdvo_connector->cur_hpos);
DRM_DEBUG_KMS("h_position: max %d, "
"default %d, current %d\n",
data_value[0], data_value[1], response);
@@ -2627,22 +2806,20 @@ static void intel_sdvo_create_enhance_property(struct drm_connector *connector)
DRM_DEBUG_KMS("Incorrect SDVO get v_postion\n");
return;
}
- sdvo_priv->max_vpos = data_value[0];
- sdvo_priv->cur_vpos = response;
- sdvo_priv->vpos_property =
+ sdvo_connector->max_vpos = data_value[0];
+ sdvo_connector->cur_vpos = response;
+ sdvo_connector->vpos_property =
drm_property_create(dev, DRM_MODE_PROP_RANGE,
"vpos", 2);
- sdvo_priv->vpos_property->values[0] = 0;
- sdvo_priv->vpos_property->values[1] = data_value[0];
+ sdvo_connector->vpos_property->values[0] = 0;
+ sdvo_connector->vpos_property->values[1] = data_value[0];
drm_connector_attach_property(connector,
- sdvo_priv->vpos_property,
- sdvo_priv->cur_vpos);
+ sdvo_connector->vpos_property,
+ sdvo_connector->cur_vpos);
DRM_DEBUG_KMS("v_position: max %d, "
"default %d, current %d\n",
data_value[0], data_value[1], response);
}
- }
- if (sdvo_priv->is_tv) {
if (sdvo_data.saturation) {
intel_sdvo_write_cmd(intel_encoder,
SDVO_CMD_GET_MAX_SATURATION, NULL, 0);
@@ -2660,17 +2837,17 @@ static void intel_sdvo_create_enhance_property(struct drm_connector *connector)
DRM_DEBUG_KMS("Incorrect SDVO get sat\n");
return;
}
- sdvo_priv->max_saturation = data_value[0];
- sdvo_priv->cur_saturation = response;
- sdvo_priv->saturation_property =
+ sdvo_connector->max_saturation = data_value[0];
+ sdvo_connector->cur_saturation = response;
+ sdvo_connector->saturation_property =
drm_property_create(dev, DRM_MODE_PROP_RANGE,
"saturation", 2);
- sdvo_priv->saturation_property->values[0] = 0;
- sdvo_priv->saturation_property->values[1] =
+ sdvo_connector->saturation_property->values[0] = 0;
+ sdvo_connector->saturation_property->values[1] =
data_value[0];
drm_connector_attach_property(connector,
- sdvo_priv->saturation_property,
- sdvo_priv->cur_saturation);
+ sdvo_connector->saturation_property,
+ sdvo_connector->cur_saturation);
DRM_DEBUG_KMS("saturation: max %d, "
"default %d, current %d\n",
data_value[0], data_value[1], response);
@@ -2692,16 +2869,16 @@ static void intel_sdvo_create_enhance_property(struct drm_connector *connector)
DRM_DEBUG_KMS("Incorrect SDVO get contrast\n");
return;
}
- sdvo_priv->max_contrast = data_value[0];
- sdvo_priv->cur_contrast = response;
- sdvo_priv->contrast_property =
+ sdvo_connector->max_contrast = data_value[0];
+ sdvo_connector->cur_contrast = response;
+ sdvo_connector->contrast_property =
drm_property_create(dev, DRM_MODE_PROP_RANGE,
"contrast", 2);
- sdvo_priv->contrast_property->values[0] = 0;
- sdvo_priv->contrast_property->values[1] = data_value[0];
+ sdvo_connector->contrast_property->values[0] = 0;
+ sdvo_connector->contrast_property->values[1] = data_value[0];
drm_connector_attach_property(connector,
- sdvo_priv->contrast_property,
- sdvo_priv->cur_contrast);
+ sdvo_connector->contrast_property,
+ sdvo_connector->cur_contrast);
DRM_DEBUG_KMS("contrast: max %d, "
"default %d, current %d\n",
data_value[0], data_value[1], response);
@@ -2723,22 +2900,24 @@ static void intel_sdvo_create_enhance_property(struct drm_connector *connector)
DRM_DEBUG_KMS("Incorrect SDVO get hue\n");
return;
}
- sdvo_priv->max_hue = data_value[0];
- sdvo_priv->cur_hue = response;
- sdvo_priv->hue_property =
+ sdvo_connector->max_hue = data_value[0];
+ sdvo_connector->cur_hue = response;
+ sdvo_connector->hue_property =
drm_property_create(dev, DRM_MODE_PROP_RANGE,
"hue", 2);
- sdvo_priv->hue_property->values[0] = 0;
- sdvo_priv->hue_property->values[1] =
+ sdvo_connector->hue_property->values[0] = 0;
+ sdvo_connector->hue_property->values[1] =
data_value[0];
drm_connector_attach_property(connector,
- sdvo_priv->hue_property,
- sdvo_priv->cur_hue);
+ sdvo_connector->hue_property,
+ sdvo_connector->cur_hue);
DRM_DEBUG_KMS("hue: max %d, default %d, current %d\n",
data_value[0], data_value[1], response);
}
}
- if (sdvo_priv->is_tv || sdvo_priv->is_lvds) {
+
+ if (SDVO_CONNECTOR_IS_TV(sdvo_connector) ||
+ SDVO_CONNECTOR_IS_LVDS(sdvo_connector)) {
if (sdvo_data.brightness) {
intel_sdvo_write_cmd(intel_encoder,
SDVO_CMD_GET_MAX_BRIGHTNESS, NULL, 0);
@@ -2756,17 +2935,17 @@ static void intel_sdvo_create_enhance_property(struct drm_connector *connector)
DRM_DEBUG_KMS("Incorrect SDVO get brigh\n");
return;
}
- sdvo_priv->max_brightness = data_value[0];
- sdvo_priv->cur_brightness = response;
- sdvo_priv->brightness_property =
+ sdvo_connector->max_brightness = data_value[0];
+ sdvo_connector->cur_brightness = response;
+ sdvo_connector->brightness_property =
drm_property_create(dev, DRM_MODE_PROP_RANGE,
"brightness", 2);
- sdvo_priv->brightness_property->values[0] = 0;
- sdvo_priv->brightness_property->values[1] =
+ sdvo_connector->brightness_property->values[0] = 0;
+ sdvo_connector->brightness_property->values[1] =
data_value[0];
drm_connector_attach_property(connector,
- sdvo_priv->brightness_property,
- sdvo_priv->cur_brightness);
+ sdvo_connector->brightness_property,
+ sdvo_connector->cur_brightness);
DRM_DEBUG_KMS("brightness: max %d, "
"default %d, current %d\n",
data_value[0], data_value[1], response);
@@ -2778,23 +2957,21 @@ static void intel_sdvo_create_enhance_property(struct drm_connector *connector)
bool intel_sdvo_init(struct drm_device *dev, int output_device)
{
struct drm_i915_private *dev_priv = dev->dev_private;
- struct drm_connector *connector;
- struct intel_connector *intel_connector;
+ struct drm_encoder *encoder;
struct intel_encoder *intel_encoder;
- struct intel_sdvo_priv *sdvo_priv;
+ struct intel_sdvo_encoder *sdvo_encoder;
u8 ch[0x40];
int i;
- intel_connector = kzalloc(sizeof(*intel_connector), GFP_KERNEL);
- intel_encoder = kzalloc(sizeof(*intel_encoder) + sizeof(*sdvo_priv), GFP_KERNEL);
+ intel_encoder = kzalloc(sizeof(*intel_encoder) + sizeof(*sdvo_encoder), GFP_KERNEL);
- if (!intel_connector || !intel_encoder)
+ if (!intel_encoder)
return false;
- sdvo_priv = (struct intel_sdvo_priv *)(intel_encoder + 1);
- sdvo_priv->output_device = output_device;
+ sdvo_encoder = (struct intel_sdvo_encoder *)(intel_encoder + 1);
+ sdvo_encoder->output_device = output_device;
- intel_encoder->dev_priv = sdvo_priv;
+ intel_encoder->dev_priv = sdvo_encoder;
intel_encoder->type = INTEL_OUTPUT_SDVO;
/* setup the DDC bus. */
@@ -2804,9 +2981,9 @@ bool intel_sdvo_init(struct drm_device *dev, int output_device)
intel_encoder->i2c_bus = intel_i2c_create(dev, GPIOE, "SDVOCTRL_E for SDVOC");
if (!intel_encoder->i2c_bus)
- goto err_inteloutput;
+ goto err;
- sdvo_priv->slave_addr = intel_sdvo_get_slave_addr(dev, output_device);
+ sdvo_encoder->slave_addr = intel_sdvo_get_slave_addr(dev, output_device);
/* Save the bit-banging i2c functionality for use by the DDC wrapper */
intel_sdvo_i2c_bit_algo.functionality = intel_encoder->i2c_bus->algo->functionality;
@@ -2816,102 +2993,59 @@ bool intel_sdvo_init(struct drm_device *dev, int output_device)
if (!intel_sdvo_read_byte(intel_encoder, i, &ch[i])) {
DRM_DEBUG_KMS("No SDVO device found on SDVO%c\n",
output_device == SDVOB ? 'B' : 'C');
- goto err_i2c;
+ goto err;
}
}
- /* setup the DDC bus. */
- if (output_device == SDVOB) {
- intel_connector->ddc_bus = intel_i2c_create(dev, GPIOE, "SDVOB DDC BUS");
- sdvo_priv->analog_ddc_bus = intel_i2c_create(dev, GPIOA,
- "SDVOB/VGA DDC BUS");
+ if (output_device == SDVOB)
dev_priv->hotplug_supported_mask |= SDVOB_HOTPLUG_INT_STATUS;
- } else {
- intel_connector->ddc_bus = intel_i2c_create(dev, GPIOE, "SDVOC DDC BUS");
- sdvo_priv->analog_ddc_bus = intel_i2c_create(dev, GPIOA,
- "SDVOC/VGA DDC BUS");
+ else
dev_priv->hotplug_supported_mask |= SDVOC_HOTPLUG_INT_STATUS;
- }
- if (intel_connector->ddc_bus == NULL)
- goto err_i2c;
-
- /* Wrap with our custom algo which switches to DDC mode */
- intel_connector->ddc_bus->algo = &intel_sdvo_i2c_bit_algo;
+ encoder = &intel_encoder->base;
+ /* encoder type will be decided later */
+ drm_encoder_init(dev, encoder, &intel_sdvo_enc_funcs, 0);
+ drm_encoder_helper_add(encoder, &intel_sdvo_helper_funcs);
/* In default case sdvo lvds is false */
- intel_sdvo_get_capabilities(intel_encoder, &sdvo_priv->caps);
+ intel_sdvo_get_capabilities(intel_encoder, &sdvo_encoder->caps);
- if (intel_sdvo_output_setup(intel_encoder, intel_connector,
- sdvo_priv->caps.output_flags) != true) {
+ if (intel_sdvo_output_setup(intel_encoder) != true) {
DRM_DEBUG_KMS("SDVO output failed to setup on SDVO%c\n",
output_device == SDVOB ? 'B' : 'C');
- goto err_i2c;
+ goto err;
}
-
- connector = &intel_connector->base;
- drm_connector_init(dev, connector, &intel_sdvo_connector_funcs,
- connector->connector_type);
-
- drm_connector_helper_add(connector, &intel_sdvo_connector_helper_funcs);
- connector->interlace_allowed = 0;
- connector->doublescan_allowed = 0;
- connector->display_info.subpixel_order = SubPixelHorizontalRGB;
-
- drm_encoder_init(dev, &intel_encoder->base,
- &intel_sdvo_enc_funcs, intel_encoder->base.encoder_type);
-
- drm_encoder_helper_add(&intel_encoder->base, &intel_sdvo_helper_funcs);
-
- drm_mode_connector_attach_encoder(&intel_connector->base, &intel_encoder->base);
- if (sdvo_priv->is_tv)
- intel_sdvo_tv_create_property(connector);
-
- if (sdvo_priv->is_tv || sdvo_priv->is_lvds)
- intel_sdvo_create_enhance_property(connector);
-
- drm_sysfs_connector_add(connector);
-
- intel_sdvo_select_ddc_bus(sdvo_priv);
+ intel_sdvo_select_ddc_bus(sdvo_encoder);
/* Set the input timing to the screen. Assume always input 0. */
intel_sdvo_set_target_input(intel_encoder, true, false);
intel_sdvo_get_input_pixel_clock_range(intel_encoder,
- &sdvo_priv->pixel_clock_min,
- &sdvo_priv->pixel_clock_max);
+ &sdvo_encoder->pixel_clock_min,
+ &sdvo_encoder->pixel_clock_max);
DRM_DEBUG_KMS("%s device VID/DID: %02X:%02X.%02X, "
"clock range %dMHz - %dMHz, "
"input 1: %c, input 2: %c, "
"output 1: %c, output 2: %c\n",
- SDVO_NAME(sdvo_priv),
- sdvo_priv->caps.vendor_id, sdvo_priv->caps.device_id,
- sdvo_priv->caps.device_rev_id,
- sdvo_priv->pixel_clock_min / 1000,
- sdvo_priv->pixel_clock_max / 1000,
- (sdvo_priv->caps.sdvo_inputs_mask & 0x1) ? 'Y' : 'N',
- (sdvo_priv->caps.sdvo_inputs_mask & 0x2) ? 'Y' : 'N',
+ SDVO_NAME(sdvo_encoder),
+ sdvo_encoder->caps.vendor_id, sdvo_encoder->caps.device_id,
+ sdvo_encoder->caps.device_rev_id,
+ sdvo_encoder->pixel_clock_min / 1000,
+ sdvo_encoder->pixel_clock_max / 1000,
+ (sdvo_encoder->caps.sdvo_inputs_mask & 0x1) ? 'Y' : 'N',
+ (sdvo_encoder->caps.sdvo_inputs_mask & 0x2) ? 'Y' : 'N',
/* check currently supported outputs */
- sdvo_priv->caps.output_flags &
+ sdvo_encoder->caps.output_flags &
(SDVO_OUTPUT_TMDS0 | SDVO_OUTPUT_RGB0) ? 'Y' : 'N',
- sdvo_priv->caps.output_flags &
+ sdvo_encoder->caps.output_flags &
(SDVO_OUTPUT_TMDS1 | SDVO_OUTPUT_RGB1) ? 'Y' : 'N');
return true;
-err_i2c:
- if (sdvo_priv->analog_ddc_bus != NULL)
- intel_i2c_destroy(sdvo_priv->analog_ddc_bus);
- if (intel_connector->ddc_bus != NULL)
- intel_i2c_destroy(intel_connector->ddc_bus);
- if (intel_encoder->i2c_bus != NULL)
- intel_i2c_destroy(intel_encoder->i2c_bus);
-err_inteloutput:
+err:
kfree(intel_encoder);
- kfree(intel_connector);
-
return false;
}