Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 156531
b: refs/heads/master
c: fb7a46f
h: refs/heads/master
i:
  156529: a1101b0
  156527: a0923ee
v: v3
  • Loading branch information
ling.ma@intel.com authored and Eric Anholt committed Jul 29, 2009
1 parent df947a6 commit daa88c0
Show file tree
Hide file tree
Showing 2 changed files with 154 additions and 79 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: bcae2ca81c4a085e3e0e8941b7c64f9aeb6fc05c
refs/heads/master: fb7a46f3cc7d7dcf7c5edb3a38c84e3f730d7adb
231 changes: 153 additions & 78 deletions trunk/drivers/gpu/drm/i915/intel_sdvo.c
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,12 @@ struct intel_sdvo_priv {
/* Pixel clock limitations reported by the SDVO device, in kHz */
int pixel_clock_min, pixel_clock_max;

/*
* For multiple function SDVO device,
* this is for current attached outputs.
*/
uint16_t attached_output;

/**
* This is set if we're going to treat the device as TV-out.
*
Expand Down Expand Up @@ -114,6 +120,9 @@ struct intel_sdvo_priv {
u32 save_SDVOX;
};

static bool
intel_sdvo_output_setup(struct intel_output *intel_output, uint16_t flags);

/**
* Writes the SDVOB or SDVOC with the given value, but always writes both
* SDVOB and SDVOC to work around apparent hardware issues (according to
Expand Down Expand Up @@ -1435,6 +1444,39 @@ void intel_sdvo_set_hotplug(struct drm_connector *connector, int on)
intel_sdvo_read_response(intel_output, &response, 2);
}

static bool
intel_sdvo_multifunc_encoder(struct intel_output *intel_output)
{
struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv;
int caps = 0;

if (sdvo_priv->caps.output_flags &
(SDVO_OUTPUT_TMDS0 | SDVO_OUTPUT_TMDS1))
caps++;
if (sdvo_priv->caps.output_flags &
(SDVO_OUTPUT_RGB0 | SDVO_OUTPUT_RGB1))
caps++;
if (sdvo_priv->caps.output_flags &
(SDVO_OUTPUT_SVID0 | SDVO_OUTPUT_SVID0))
caps++;
if (sdvo_priv->caps.output_flags &
(SDVO_OUTPUT_CVBS0 | SDVO_OUTPUT_CVBS1))
caps++;
if (sdvo_priv->caps.output_flags &
(SDVO_OUTPUT_YPRPB0 | SDVO_OUTPUT_YPRPB1))
caps++;

if (sdvo_priv->caps.output_flags &
(SDVO_OUTPUT_SCART0 | SDVO_OUTPUT_SCART1))
caps++;

if (sdvo_priv->caps.output_flags &
(SDVO_OUTPUT_LVDS0 | SDVO_OUTPUT_LVDS1))
caps++;

return (caps > 1);
}

static void
intel_sdvo_hdmi_sink_detect(struct drm_connector *connector)
{
Expand All @@ -1453,23 +1495,31 @@ intel_sdvo_hdmi_sink_detect(struct drm_connector *connector)

static enum drm_connector_status intel_sdvo_detect(struct drm_connector *connector)
{
u8 response[2];
uint16_t response;
u8 status;
struct intel_output *intel_output = to_intel_output(connector);
struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv;

intel_sdvo_write_cmd(intel_output, SDVO_CMD_GET_ATTACHED_DISPLAYS, NULL, 0);
status = intel_sdvo_read_response(intel_output, &response, 2);

DRM_DEBUG("SDVO response %d %d\n", response[0], response[1]);
DRM_DEBUG("SDVO response %d %d\n", response & 0xff, response >> 8);

if (status != SDVO_CMD_STATUS_SUCCESS)
return connector_status_unknown;

if ((response[0] != 0) || (response[1] != 0)) {
intel_sdvo_hdmi_sink_detect(connector);
return connector_status_connected;
} else
if (response == 0)
return connector_status_disconnected;

if (intel_sdvo_multifunc_encoder(intel_output) &&
sdvo_priv->attached_output != response) {
if (sdvo_priv->controlled_output != response &&
intel_sdvo_output_setup(intel_output, response) != true)
return connector_status_unknown;
sdvo_priv->attached_output = response;
}
intel_sdvo_hdmi_sink_detect(connector);
return connector_status_connected;
}

static void intel_sdvo_get_ddc_modes(struct drm_connector *connector)
Expand Down Expand Up @@ -1866,16 +1916,101 @@ intel_sdvo_get_slave_addr(struct drm_device *dev, int output_device)
return 0x72;
}

static bool
intel_sdvo_output_setup(struct intel_output *intel_output, uint16_t flags)
{
struct drm_connector *connector = &intel_output->base;
struct drm_encoder *encoder = &intel_output->enc;
struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv;
bool ret = true, registered = false;

sdvo_priv->is_tv = false;
intel_output->needs_tv_clock = false;
sdvo_priv->is_lvds = false;

if (device_is_registered(&connector->kdev)) {
drm_sysfs_connector_remove(connector);
registered = true;
}

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;

encoder->encoder_type = DRM_MODE_ENCODER_TMDS;
connector->connector_type = DRM_MODE_CONNECTOR_DVID;

if (intel_sdvo_get_supp_encode(intel_output,
&sdvo_priv->encode) &&
intel_sdvo_get_digital_encoding_mode(intel_output) &&
sdvo_priv->is_hdmi) {
/* enable hdmi encoding mode if supported */
intel_sdvo_set_encode(intel_output, SDVO_ENCODE_HDMI);
intel_sdvo_set_colorimetry(intel_output,
SDVO_COLORIMETRY_RGB256);
connector->connector_type = DRM_MODE_CONNECTOR_HDMIA;
}
} 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_output->needs_tv_clock = true;
} 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;
} 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;
} 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;
} 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;
} else {

unsigned char bytes[2];

sdvo_priv->controlled_output = 0;
memcpy(bytes, &sdvo_priv->caps.output_flags, 2);
DRM_DEBUG_KMS(I915_SDVO,
"%s: Unknown SDVO output type (0x%02x%02x)\n",
SDVO_NAME(sdvo_priv),
bytes[0], bytes[1]);
ret = false;
}

if (ret && registered)
ret = drm_sysfs_connector_add(connector) == 0 ? true : false;


return ret;

}

bool intel_sdvo_init(struct drm_device *dev, int output_device)
{
struct drm_connector *connector;
struct intel_output *intel_output;
struct intel_sdvo_priv *sdvo_priv;

int connector_type;
u8 ch[0x40];
int i;
int encoder_type;

intel_output = kcalloc(sizeof(struct intel_output)+sizeof(struct intel_sdvo_priv), 1, GFP_KERNEL);
if (!intel_output) {
Expand Down Expand Up @@ -1925,88 +2060,28 @@ bool intel_sdvo_init(struct drm_device *dev, int output_device)
intel_output->ddc_bus->algo = &intel_sdvo_i2c_bit_algo;

/* In defaut case sdvo lvds is false */
sdvo_priv->is_lvds = false;
intel_sdvo_get_capabilities(intel_output, &sdvo_priv->caps);

if (sdvo_priv->caps.output_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;

encoder_type = DRM_MODE_ENCODER_TMDS;
connector_type = DRM_MODE_CONNECTOR_DVID;

if (intel_sdvo_get_supp_encode(intel_output,
&sdvo_priv->encode) &&
intel_sdvo_get_digital_encoding_mode(intel_output) &&
sdvo_priv->is_hdmi) {
/* enable hdmi encoding mode if supported */
intel_sdvo_set_encode(intel_output, SDVO_ENCODE_HDMI);
intel_sdvo_set_colorimetry(intel_output,
SDVO_COLORIMETRY_RGB256);
connector_type = DRM_MODE_CONNECTOR_HDMIA;
}
}
else if (sdvo_priv->caps.output_flags & SDVO_OUTPUT_SVID0)
{
sdvo_priv->controlled_output = SDVO_OUTPUT_SVID0;
encoder_type = DRM_MODE_ENCODER_TVDAC;
connector_type = DRM_MODE_CONNECTOR_SVIDEO;
sdvo_priv->is_tv = true;
intel_output->needs_tv_clock = true;
}
else if (sdvo_priv->caps.output_flags & SDVO_OUTPUT_RGB0)
{
sdvo_priv->controlled_output = SDVO_OUTPUT_RGB0;
encoder_type = DRM_MODE_ENCODER_DAC;
connector_type = DRM_MODE_CONNECTOR_VGA;
}
else if (sdvo_priv->caps.output_flags & SDVO_OUTPUT_RGB1)
{
sdvo_priv->controlled_output = SDVO_OUTPUT_RGB1;
encoder_type = DRM_MODE_ENCODER_DAC;
connector_type = DRM_MODE_CONNECTOR_VGA;
}
else if (sdvo_priv->caps.output_flags & SDVO_OUTPUT_LVDS0)
{
sdvo_priv->controlled_output = SDVO_OUTPUT_LVDS0;
encoder_type = DRM_MODE_ENCODER_LVDS;
connector_type = DRM_MODE_CONNECTOR_LVDS;
sdvo_priv->is_lvds = true;
}
else if (sdvo_priv->caps.output_flags & SDVO_OUTPUT_LVDS1)
{
sdvo_priv->controlled_output = SDVO_OUTPUT_LVDS1;
encoder_type = DRM_MODE_ENCODER_LVDS;
connector_type = DRM_MODE_CONNECTOR_LVDS;
sdvo_priv->is_lvds = true;
}
else
{
unsigned char bytes[2];

sdvo_priv->controlled_output = 0;
memcpy (bytes, &sdvo_priv->caps.output_flags, 2);
DRM_DEBUG_KMS(I915_SDVO,
"%s: Unknown SDVO output type (0x%02x%02x)\n",
SDVO_NAME(sdvo_priv),
bytes[0], bytes[1]);
encoder_type = DRM_MODE_ENCODER_NONE;
connector_type = DRM_MODE_CONNECTOR_Unknown;
if (intel_sdvo_output_setup(intel_output,
sdvo_priv->caps.output_flags) != true) {
DRM_DEBUG("SDVO output failed to setup on SDVO%c\n",
output_device == SDVOB ? 'B' : 'C');
goto err_i2c;
}


connector = &intel_output->base;
drm_connector_init(dev, connector, &intel_sdvo_connector_funcs,
connector_type);
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_output->enc, &intel_sdvo_enc_funcs, encoder_type);
drm_encoder_init(dev, &intel_output->enc,
&intel_sdvo_enc_funcs, intel_output->enc.encoder_type);

drm_encoder_helper_add(&intel_output->enc, &intel_sdvo_helper_funcs);

drm_mode_connector_attach_encoder(&intel_output->base, &intel_output->enc);
Expand Down

0 comments on commit daa88c0

Please sign in to comment.