30,6 → 30,7 |
#include <linux/delay.h> |
#include <linux/export.h> |
#include <drm/drmP.h> |
#include <drm/drm_atomic_helper.h> |
#include <drm/drm_crtc.h> |
#include <drm/drm_edid.h> |
#include "intel_drv.h" |
52,7 → 53,7 |
#define IS_DIGITAL(c) (c->output_flag & (SDVO_TMDS_MASK | SDVO_LVDS_MASK)) |
|
|
static const char *tv_format_names[] = { |
static const char * const tv_format_names[] = { |
"NTSC_M" , "NTSC_J" , "NTSC_443", |
"PAL_B" , "PAL_D" , "PAL_G" , |
"PAL_H" , "PAL_I" , "PAL_M" , |
62,7 → 63,7 |
"SECAM_60" |
}; |
|
#define TV_FORMAT_NUM (sizeof(tv_format_names) / sizeof(*tv_format_names)) |
#define TV_FORMAT_NUM ARRAY_SIZE(tv_format_names) |
|
struct intel_sdvo { |
struct intel_encoder base; |
106,6 → 107,11 |
bool color_range_auto; |
|
/** |
* HDMI user specified aspect ratio |
*/ |
enum hdmi_picture_aspect aspect_ratio; |
|
/** |
* This is set if we're going to treat the device as TV-out. |
* |
* While we have these nice friendly flags for output types that ought |
241,7 → 247,15 |
|
if (intel_sdvo->sdvo_reg == PCH_SDVOB) { |
I915_WRITE(intel_sdvo->sdvo_reg, val); |
I915_READ(intel_sdvo->sdvo_reg); |
POSTING_READ(intel_sdvo->sdvo_reg); |
/* |
* HW workaround, need to write this twice for issue |
* that may result in first write getting masked. |
*/ |
if (HAS_PCH_IBX(dev)) { |
I915_WRITE(intel_sdvo->sdvo_reg, val); |
POSTING_READ(intel_sdvo->sdvo_reg); |
} |
return; |
} |
|
258,9 → 272,9 |
for (i = 0; i < 2; i++) |
{ |
I915_WRITE(GEN3_SDVOB, bval); |
I915_READ(GEN3_SDVOB); |
POSTING_READ(GEN3_SDVOB); |
I915_WRITE(GEN3_SDVOC, cval); |
I915_READ(GEN3_SDVOC); |
POSTING_READ(GEN3_SDVOC); |
} |
} |
|
443,7 → 457,7 |
DRM_DEBUG_KMS("%s: W: %02X %s\n", SDVO_NAME(intel_sdvo), cmd, buffer); |
} |
|
static const char *cmd_status_names[] = { |
static const char * const cmd_status_names[] = { |
"Power on", |
"Success", |
"Not supported", |
594,11 → 608,11 |
return false; |
} |
|
static int intel_sdvo_get_pixel_multiplier(struct drm_display_mode *mode) |
static int intel_sdvo_get_pixel_multiplier(const struct drm_display_mode *adjusted_mode) |
{ |
if (mode->clock >= 100000) |
if (adjusted_mode->crtc_clock >= 100000) |
return 1; |
else if (mode->clock >= 50000) |
else if (adjusted_mode->crtc_clock >= 50000) |
return 2; |
else |
return 4; |
1007,7 → 1021,7 |
} |
|
if (intel_sdvo->rgb_quant_range_selectable) { |
if (intel_crtc->config.limited_color_range) |
if (intel_crtc->config->limited_color_range) |
frame.avi.quantization_range = |
HDMI_QUANTIZATION_RANGE_LIMITED; |
else |
1085,7 → 1099,7 |
return true; |
} |
|
static void i9xx_adjust_sdvo_tv_clock(struct intel_crtc_config *pipe_config) |
static void i9xx_adjust_sdvo_tv_clock(struct intel_crtc_state *pipe_config) |
{ |
unsigned dotclock = pipe_config->port_clock; |
struct dpll *clock = &pipe_config->dpll; |
1112,11 → 1126,11 |
} |
|
static bool intel_sdvo_compute_config(struct intel_encoder *encoder, |
struct intel_crtc_config *pipe_config) |
struct intel_crtc_state *pipe_config) |
{ |
struct intel_sdvo *intel_sdvo = to_sdvo(encoder); |
struct drm_display_mode *adjusted_mode = &pipe_config->adjusted_mode; |
struct drm_display_mode *mode = &pipe_config->requested_mode; |
struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode; |
struct drm_display_mode *mode = &pipe_config->base.mode; |
|
DRM_DEBUG_KMS("forcing bpc to 8 for SDVO\n"); |
pipe_config->pipe_bpp = 8*3; |
1172,6 → 1186,10 |
if (intel_sdvo->is_tv) |
i9xx_adjust_sdvo_tv_clock(pipe_config); |
|
/* Set user selected PAR to incoming mode's member */ |
if (intel_sdvo->is_hdmi) |
adjusted_mode->picture_aspect_ratio = intel_sdvo->aspect_ratio; |
|
return true; |
} |
|
1180,9 → 1198,8 |
struct drm_device *dev = intel_encoder->base.dev; |
struct drm_i915_private *dev_priv = dev->dev_private; |
struct intel_crtc *crtc = to_intel_crtc(intel_encoder->base.crtc); |
struct drm_display_mode *adjusted_mode = |
&crtc->config.adjusted_mode; |
struct drm_display_mode *mode = &crtc->config.requested_mode; |
const struct drm_display_mode *adjusted_mode = &crtc->config->base.adjusted_mode; |
struct drm_display_mode *mode = &crtc->config->base.mode; |
struct intel_sdvo *intel_sdvo = to_sdvo(intel_encoder); |
u32 sdvox; |
struct intel_sdvo_in_out_map in_out; |
1224,7 → 1241,7 |
if (!intel_sdvo_set_target_input(intel_sdvo)) |
return; |
|
if (crtc->config.has_hdmi_sink) { |
if (crtc->config->has_hdmi_sink) { |
intel_sdvo_set_encode(intel_sdvo, SDVO_ENCODE_HDMI); |
intel_sdvo_set_colorimetry(intel_sdvo, |
SDVO_COLORIMETRY_RGB256); |
1244,9 → 1261,9 |
DRM_INFO("Setting input timings on %s failed\n", |
SDVO_NAME(intel_sdvo)); |
|
switch (crtc->config.pixel_multiplier) { |
switch (crtc->config->pixel_multiplier) { |
default: |
WARN(1, "unknown pixel mutlipler specified\n"); |
WARN(1, "unknown pixel multiplier specified\n"); |
case 1: rate = SDVO_CLOCK_RATE_MULT_1X; break; |
case 2: rate = SDVO_CLOCK_RATE_MULT_2X; break; |
case 4: rate = SDVO_CLOCK_RATE_MULT_4X; break; |
1259,7 → 1276,7 |
/* The real mode polarity is set by the SDVO commands, using |
* struct intel_sdvo_dtd. */ |
sdvox = SDVO_VSYNC_ACTIVE_HIGH | SDVO_HSYNC_ACTIVE_HIGH; |
if (!HAS_PCH_SPLIT(dev) && crtc->config.limited_color_range) |
if (!HAS_PCH_SPLIT(dev) && crtc->config->limited_color_range) |
sdvox |= HDMI_COLOR_RANGE_16_235; |
if (INTEL_INFO(dev)->gen < 5) |
sdvox |= SDVO_BORDER_ENABLE; |
1289,7 → 1306,7 |
} else if (IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev)) { |
/* done in crtc_mode_set as it lives inside the dpll register */ |
} else { |
sdvox |= (crtc->config.pixel_multiplier - 1) |
sdvox |= (crtc->config->pixel_multiplier - 1) |
<< SDVO_PORT_MULTIPLY_SHIFT; |
} |
|
1338,7 → 1355,7 |
} |
|
static void intel_sdvo_get_config(struct intel_encoder *encoder, |
struct intel_crtc_config *pipe_config) |
struct intel_crtc_state *pipe_config) |
{ |
struct drm_device *dev = encoder->base.dev; |
struct drm_i915_private *dev_priv = dev->dev_private; |
1370,7 → 1387,7 |
flags |= DRM_MODE_FLAG_NVSYNC; |
} |
|
pipe_config->adjusted_mode.flags |= flags; |
pipe_config->base.adjusted_mode.flags |= flags; |
|
/* |
* pixel multiplier readout is tricky: Only on i915g/gm it is stored in |
1392,7 → 1409,7 |
if (HAS_PCH_SPLIT(dev)) |
ironlake_check_encoder_dotclock(pipe_config, dotclock); |
|
pipe_config->adjusted_mode.crtc_clock = dotclock; |
pipe_config->base.adjusted_mode.crtc_clock = dotclock; |
|
/* Cross check the port pixel multiplier with the sdvo encoder state. */ |
if (intel_sdvo_get_value(intel_sdvo, SDVO_CMD_GET_CLOCK_RATE_MULT, |
1428,6 → 1445,7 |
{ |
struct drm_i915_private *dev_priv = encoder->base.dev->dev_private; |
struct intel_sdvo *intel_sdvo = to_sdvo(encoder); |
struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc); |
u32 temp; |
|
intel_sdvo_set_active_outputs(intel_sdvo, 0); |
1436,33 → 1454,32 |
DRM_MODE_DPMS_OFF); |
|
temp = I915_READ(intel_sdvo->sdvo_reg); |
if ((temp & SDVO_ENABLE) != 0) { |
/* HW workaround for IBX, we need to move the port to |
* transcoder A before disabling it. */ |
if (HAS_PCH_IBX(encoder->base.dev)) { |
struct drm_crtc *crtc = encoder->base.crtc; |
int pipe = crtc ? to_intel_crtc(crtc)->pipe : -1; |
|
if (temp & SDVO_PIPE_B_SELECT) { |
temp &= ~SDVO_ENABLE; |
intel_sdvo_write_sdvox(intel_sdvo, temp); |
|
/* |
* HW workaround for IBX, we need to move the port |
* to transcoder A after disabling it to allow the |
* matching DP port to be enabled on transcoder A. |
*/ |
if (HAS_PCH_IBX(dev_priv) && crtc->pipe == PIPE_B) { |
temp &= ~SDVO_PIPE_B_SELECT; |
I915_WRITE(intel_sdvo->sdvo_reg, temp); |
POSTING_READ(intel_sdvo->sdvo_reg); |
temp |= SDVO_ENABLE; |
intel_sdvo_write_sdvox(intel_sdvo, temp); |
|
/* Again we need to write this twice. */ |
I915_WRITE(intel_sdvo->sdvo_reg, temp); |
POSTING_READ(intel_sdvo->sdvo_reg); |
|
/* Transcoder selection bits only update |
* effectively on vblank. */ |
if (crtc) |
intel_wait_for_vblank(encoder->base.dev, pipe); |
else |
msleep(50); |
temp &= ~SDVO_ENABLE; |
intel_sdvo_write_sdvox(intel_sdvo, temp); |
} |
} |
|
intel_sdvo_write_sdvox(intel_sdvo, temp & ~SDVO_ENABLE); |
static void pch_disable_sdvo(struct intel_encoder *encoder) |
{ |
} |
|
static void pch_post_disable_sdvo(struct intel_encoder *encoder) |
{ |
intel_disable_sdvo(encoder); |
} |
|
static void intel_enable_sdvo(struct intel_encoder *encoder) |
1477,14 → 1494,9 |
bool success; |
|
temp = I915_READ(intel_sdvo->sdvo_reg); |
if ((temp & SDVO_ENABLE) == 0) { |
/* HW workaround for IBX, we need to move the port |
* to transcoder A before disabling it, so restore it here. */ |
if (HAS_PCH_IBX(dev)) |
temp |= SDVO_PIPE_SEL(intel_crtc->pipe); |
temp |= SDVO_ENABLE; |
intel_sdvo_write_sdvox(intel_sdvo, temp); |
|
intel_sdvo_write_sdvox(intel_sdvo, temp | SDVO_ENABLE); |
} |
for (i = 0; i < 2; i++) |
intel_wait_for_vblank(dev, intel_crtc->pipe); |
|
1504,51 → 1516,6 |
intel_sdvo_set_active_outputs(intel_sdvo, intel_sdvo->attached_output); |
} |
|
/* Special dpms function to support cloning between dvo/sdvo/crt. */ |
static void intel_sdvo_dpms(struct drm_connector *connector, int mode) |
{ |
struct drm_crtc *crtc; |
struct intel_sdvo *intel_sdvo = intel_attached_sdvo(connector); |
|
/* dvo supports only 2 dpms states. */ |
if (mode != DRM_MODE_DPMS_ON) |
mode = DRM_MODE_DPMS_OFF; |
|
if (mode == connector->dpms) |
return; |
|
connector->dpms = mode; |
|
/* Only need to change hw state when actually enabled */ |
crtc = intel_sdvo->base.base.crtc; |
if (!crtc) { |
intel_sdvo->base.connectors_active = false; |
return; |
} |
|
/* We set active outputs manually below in case pipe dpms doesn't change |
* due to cloning. */ |
if (mode != DRM_MODE_DPMS_ON) { |
intel_sdvo_set_active_outputs(intel_sdvo, 0); |
if (0) |
intel_sdvo_set_encoder_power_state(intel_sdvo, mode); |
|
intel_sdvo->base.connectors_active = false; |
|
intel_crtc_update_dpms(crtc); |
} else { |
intel_sdvo->base.connectors_active = true; |
|
intel_crtc_update_dpms(crtc); |
|
if (0) |
intel_sdvo_set_encoder_power_state(intel_sdvo, mode); |
intel_sdvo_set_active_outputs(intel_sdvo, intel_sdvo->attached_output); |
} |
|
intel_modeset_check_state(connector->dev); |
} |
|
static enum drm_mode_status |
intel_sdvo_mode_valid(struct drm_connector *connector, |
struct drm_display_mode *mode) |
1617,6 → 1584,9 |
struct drm_device *dev = intel_sdvo->base.base.dev; |
uint16_t hotplug; |
|
if (!I915_HAS_HOTPLUG(dev)) |
return 0; |
|
/* HW Erratum: SDVO Hotplug is broken on all i945G chips, there's noise |
* on the line. */ |
if (IS_I945G(dev) || IS_I945GM(dev)) |
2082,6 → 2052,23 |
goto done; |
} |
|
if (property == connector->dev->mode_config.aspect_ratio_property) { |
switch (val) { |
case DRM_MODE_PICTURE_ASPECT_NONE: |
intel_sdvo->aspect_ratio = HDMI_PICTURE_ASPECT_NONE; |
break; |
case DRM_MODE_PICTURE_ASPECT_4_3: |
intel_sdvo->aspect_ratio = HDMI_PICTURE_ASPECT_4_3; |
break; |
case DRM_MODE_PICTURE_ASPECT_16_9: |
intel_sdvo->aspect_ratio = HDMI_PICTURE_ASPECT_16_9; |
break; |
default: |
return -EINVAL; |
} |
goto done; |
} |
|
#define CHECK_PROPERTY(name, NAME) \ |
if (intel_sdvo_connector->name == property) { \ |
if (intel_sdvo_connector->cur_##name == temp_value) return 0; \ |
2183,11 → 2170,14 |
} |
|
static const struct drm_connector_funcs intel_sdvo_connector_funcs = { |
.dpms = intel_sdvo_dpms, |
.dpms = drm_atomic_helper_connector_dpms, |
.detect = intel_sdvo_detect, |
.fill_modes = drm_helper_probe_single_connector_modes, |
.set_property = intel_sdvo_set_property, |
.atomic_get_property = intel_connector_atomic_get_property, |
.destroy = intel_sdvo_destroy, |
.atomic_destroy_state = drm_atomic_helper_connector_destroy_state, |
.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, |
}; |
|
static const struct drm_connector_helper_funcs intel_sdvo_connector_helper_funcs = { |
2257,7 → 2247,7 |
*/ |
static void |
intel_sdvo_select_ddc_bus(struct drm_i915_private *dev_priv, |
struct intel_sdvo *sdvo, u32 reg) |
struct intel_sdvo *sdvo) |
{ |
struct sdvo_device_mapping *mapping; |
|
2274,7 → 2264,7 |
|
static void |
intel_sdvo_select_i2c_bus(struct drm_i915_private *dev_priv, |
struct intel_sdvo *sdvo, u32 reg) |
struct intel_sdvo *sdvo) |
{ |
struct sdvo_device_mapping *mapping; |
u8 pin; |
2284,10 → 2274,11 |
else |
mapping = &dev_priv->sdvo_mappings[1]; |
|
if (mapping->initialized && intel_gmbus_is_port_valid(mapping->i2c_pin)) |
if (mapping->initialized && |
intel_gmbus_is_valid_pin(dev_priv, mapping->i2c_pin)) |
pin = mapping->i2c_pin; |
else |
pin = GMBUS_PORT_DPB; |
pin = GMBUS_PIN_DPB; |
|
sdvo->i2c = intel_gmbus_get_adapter(dev_priv, pin); |
|
2409,8 → 2400,26 |
intel_attach_broadcast_rgb_property(&connector->base.base); |
intel_sdvo->color_range_auto = true; |
} |
intel_attach_aspect_ratio_property(&connector->base.base); |
intel_sdvo->aspect_ratio = HDMI_PICTURE_ASPECT_NONE; |
} |
|
static struct intel_sdvo_connector *intel_sdvo_connector_alloc(void) |
{ |
struct intel_sdvo_connector *sdvo_connector; |
|
sdvo_connector = kzalloc(sizeof(*sdvo_connector), GFP_KERNEL); |
if (!sdvo_connector) |
return NULL; |
|
if (intel_connector_init(&sdvo_connector->base) < 0) { |
kfree(sdvo_connector); |
return NULL; |
} |
|
return sdvo_connector; |
} |
|
static bool |
intel_sdvo_dvi_init(struct intel_sdvo *intel_sdvo, int device) |
{ |
2422,7 → 2431,7 |
|
DRM_DEBUG_KMS("initialising DVI device %d\n", device); |
|
intel_sdvo_connector = kzalloc(sizeof(*intel_sdvo_connector), GFP_KERNEL); |
intel_sdvo_connector = intel_sdvo_connector_alloc(); |
if (!intel_sdvo_connector) |
return false; |
|
2476,7 → 2485,7 |
|
DRM_DEBUG_KMS("initialising TV type %d\n", type); |
|
intel_sdvo_connector = kzalloc(sizeof(*intel_sdvo_connector), GFP_KERNEL); |
intel_sdvo_connector = intel_sdvo_connector_alloc(); |
if (!intel_sdvo_connector) |
return false; |
|
2519,7 → 2528,7 |
|
DRM_DEBUG_KMS("initialising analog device %d\n", device); |
|
intel_sdvo_connector = kzalloc(sizeof(*intel_sdvo_connector), GFP_KERNEL); |
intel_sdvo_connector = intel_sdvo_connector_alloc(); |
if (!intel_sdvo_connector) |
return false; |
|
2555,7 → 2564,7 |
|
DRM_DEBUG_KMS("initialising LVDS device %d\n", device); |
|
intel_sdvo_connector = kzalloc(sizeof(*intel_sdvo_connector), GFP_KERNEL); |
intel_sdvo_connector = intel_sdvo_connector_alloc(); |
if (!intel_sdvo_connector) |
return false; |
|
2935,7 → 2944,7 |
intel_sdvo->sdvo_reg = sdvo_reg; |
intel_sdvo->is_sdvob = is_sdvob; |
intel_sdvo->slave_addr = intel_sdvo_get_slave_addr(dev, intel_sdvo) >> 1; |
intel_sdvo_select_i2c_bus(dev_priv, intel_sdvo, sdvo_reg); |
intel_sdvo_select_i2c_bus(dev_priv, intel_sdvo); |
if (!intel_sdvo_init_ddc_proxy(intel_sdvo, dev)) |
goto err_i2c_bus; |
|
2956,7 → 2965,12 |
} |
|
intel_encoder->compute_config = intel_sdvo_compute_config; |
if (HAS_PCH_SPLIT(dev)) { |
intel_encoder->disable = pch_disable_sdvo; |
intel_encoder->post_disable = pch_post_disable_sdvo; |
} else { |
intel_encoder->disable = intel_disable_sdvo; |
} |
intel_encoder->pre_enable = intel_sdvo_pre_enable; |
intel_encoder->enable = intel_enable_sdvo; |
intel_encoder->get_hw_state = intel_sdvo_get_hw_state; |
2992,7 → 3006,7 |
*/ |
intel_sdvo->base.cloneable = 0; |
|
intel_sdvo_select_ddc_bus(dev_priv, intel_sdvo, sdvo_reg); |
intel_sdvo_select_ddc_bus(dev_priv, intel_sdvo); |
|
/* Set the input timing to the screen. Assume always input 0. */ |
if (!intel_sdvo_set_target_input(intel_sdvo)) |