From 988c70156ce1ae146e4105a3d21ec16c5894162b Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Fri, 27 Mar 2015 00:20:19 +0200 Subject: drm/i915: rename GMBUS_PORT_* macros as GMBUS_PIN_* MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The specs refer to pin pairs. Start moving towards using pin rather than port all around to avoid confusion. No functional changes. Signed-off-by: Jani Nikula Reviewed-by: Ville Syrjälä Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_sdvo.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu/drm/i915/intel_sdvo.c') diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index f5b7e1e7c5e0..3e0e9b0e3503 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c @@ -2294,7 +2294,7 @@ intel_sdvo_select_i2c_bus(struct drm_i915_private *dev_priv, if (mapping->initialized && intel_gmbus_is_port_valid(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); -- cgit v1.2.3 From 0184df465efc3b0a09e6999437ca4925567acf28 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Fri, 27 Mar 2015 00:20:20 +0200 Subject: drm/i915: refer to pin instead of port in the intel_i2c.c interfaces MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rename intel_gmbus_is_port_valid to intel_gmbus_is_valid_pin, and rename port parameters to pin as well. This matches usage all around, as usually a pin is passed to the validity check function. No functional changes. Signed-off-by: Jani Nikula Reviewed-by: Ville Syrjälä Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 8 ++++---- drivers/gpu/drm/i915/intel_bios.c | 2 +- drivers/gpu/drm/i915/intel_dvo.c | 2 +- drivers/gpu/drm/i915/intel_i2c.c | 8 ++++---- drivers/gpu/drm/i915/intel_lvds.c | 2 +- drivers/gpu/drm/i915/intel_sdvo.c | 2 +- 6 files changed, 12 insertions(+), 12 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_sdvo.c') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index dca3a4d32a11..b0390c8c9595 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -3065,13 +3065,13 @@ void i915_teardown_sysfs(struct drm_device *dev_priv); /* intel_i2c.c */ extern int intel_setup_gmbus(struct drm_device *dev); extern void intel_teardown_gmbus(struct drm_device *dev); -static inline bool intel_gmbus_is_port_valid(unsigned port) +static inline bool intel_gmbus_is_valid_pin(unsigned int pin) { - return (port >= GMBUS_PIN_SSC && port <= GMBUS_PIN_DPD); + return (pin >= GMBUS_PIN_SSC && pin <= GMBUS_PIN_DPD); } -extern struct i2c_adapter *intel_gmbus_get_adapter( - struct drm_i915_private *dev_priv, unsigned port); +extern struct i2c_adapter * +intel_gmbus_get_adapter(struct drm_i915_private *dev_priv, unsigned int pin); extern void intel_gmbus_set_speed(struct i2c_adapter *adapter, int speed); extern void intel_gmbus_force_bit(struct i2c_adapter *adapter, bool force_bit); static inline bool intel_gmbus_is_forced_bit(struct i2c_adapter *adapter) diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c index 40c8375a4477..333f40793435 100644 --- a/drivers/gpu/drm/i915/intel_bios.c +++ b/drivers/gpu/drm/i915/intel_bios.c @@ -438,7 +438,7 @@ parse_general_definitions(struct drm_i915_private *dev_priv, if (block_size >= sizeof(*general)) { int bus_pin = general->crt_ddc_gmbus_pin; DRM_DEBUG_KMS("crt_ddc_bus_pin: %d\n", bus_pin); - if (intel_gmbus_is_port_valid(bus_pin)) + if (intel_gmbus_is_valid_pin(bus_pin)) dev_priv->vbt.crt_ddc_pin = bus_pin; } else { DRM_DEBUG_KMS("BDB_GD too small (%d). Invalid.\n", diff --git a/drivers/gpu/drm/i915/intel_dvo.c b/drivers/gpu/drm/i915/intel_dvo.c index 447cdc76c960..bfedea3826d7 100644 --- a/drivers/gpu/drm/i915/intel_dvo.c +++ b/drivers/gpu/drm/i915/intel_dvo.c @@ -502,7 +502,7 @@ void intel_dvo_init(struct drm_device *dev) * special cases, but otherwise default to what's defined * in the spec. */ - if (intel_gmbus_is_port_valid(dvo->gpio)) + if (intel_gmbus_is_valid_pin(dvo->gpio)) gpio = dvo->gpio; else if (dvo->type == INTEL_DVO_CHIP_LVDS) gpio = GMBUS_PIN_SSC; diff --git a/drivers/gpu/drm/i915/intel_i2c.c b/drivers/gpu/drm/i915/intel_i2c.c index b31088a551f2..b0003a2bd854 100644 --- a/drivers/gpu/drm/i915/intel_i2c.c +++ b/drivers/gpu/drm/i915/intel_i2c.c @@ -574,12 +574,12 @@ err: } struct i2c_adapter *intel_gmbus_get_adapter(struct drm_i915_private *dev_priv, - unsigned port) + unsigned int pin) { - WARN_ON(!intel_gmbus_is_port_valid(port)); + WARN_ON(!intel_gmbus_is_valid_pin(pin)); /* -1 to map pin pair to gmbus index */ - return (intel_gmbus_is_port_valid(port)) ? - &dev_priv->gmbus[port - 1].adapter : NULL; + return (intel_gmbus_is_valid_pin(pin)) ? + &dev_priv->gmbus[pin - 1].adapter : NULL; } void intel_gmbus_set_speed(struct i2c_adapter *adapter, int speed) diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index 875916152645..d61aa78ed7e3 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c @@ -781,7 +781,7 @@ static bool lvds_is_present_in_vbt(struct drm_device *dev, child->device_type != DEVICE_TYPE_LFP) continue; - if (intel_gmbus_is_port_valid(child->i2c_pin)) + if (intel_gmbus_is_valid_pin(child->i2c_pin)) *i2c_pin = child->i2c_pin; /* However, we cannot trust the BIOS writers to populate diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index 3e0e9b0e3503..124992e48abd 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c @@ -2291,7 +2291,7 @@ intel_sdvo_select_i2c_bus(struct drm_i915_private *dev_priv, 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(mapping->i2c_pin)) pin = mapping->i2c_pin; else pin = GMBUS_PIN_DPB; -- cgit v1.2.3 From 88ac7939d2a6cb67e338e72cf6aaff2ae526b026 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Fri, 27 Mar 2015 00:20:22 +0200 Subject: drm/i915: base gmbus pin validity check on the gmbus pin map array MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This will be helpful for adding future platforms. It is better to keep the information in the single point of truth (the table) instead of duplicating it into the validity function. While at it, add dev_priv parameter to the function, also to prepare for adding future platform support. Signed-off-by: Jani Nikula Reviewed-by: Ville Syrjälä Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 6 ++---- drivers/gpu/drm/i915/intel_bios.c | 2 +- drivers/gpu/drm/i915/intel_dvo.c | 2 +- drivers/gpu/drm/i915/intel_i2c.c | 14 ++++++++++---- drivers/gpu/drm/i915/intel_lvds.c | 2 +- drivers/gpu/drm/i915/intel_sdvo.c | 3 ++- 6 files changed, 17 insertions(+), 12 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_sdvo.c') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 0ad11d9c123f..d63997bc80e4 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -3064,10 +3064,8 @@ void i915_teardown_sysfs(struct drm_device *dev_priv); /* intel_i2c.c */ extern int intel_setup_gmbus(struct drm_device *dev); extern void intel_teardown_gmbus(struct drm_device *dev); -static inline bool intel_gmbus_is_valid_pin(unsigned int pin) -{ - return (pin >= GMBUS_PIN_SSC && pin <= GMBUS_PIN_DPD); -} +extern bool intel_gmbus_is_valid_pin(struct drm_i915_private *dev_priv, + unsigned int pin); extern struct i2c_adapter * intel_gmbus_get_adapter(struct drm_i915_private *dev_priv, unsigned int pin); diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c index 333f40793435..ad2f3b0d922f 100644 --- a/drivers/gpu/drm/i915/intel_bios.c +++ b/drivers/gpu/drm/i915/intel_bios.c @@ -438,7 +438,7 @@ parse_general_definitions(struct drm_i915_private *dev_priv, if (block_size >= sizeof(*general)) { int bus_pin = general->crt_ddc_gmbus_pin; DRM_DEBUG_KMS("crt_ddc_bus_pin: %d\n", bus_pin); - if (intel_gmbus_is_valid_pin(bus_pin)) + if (intel_gmbus_is_valid_pin(dev_priv, bus_pin)) dev_priv->vbt.crt_ddc_pin = bus_pin; } else { DRM_DEBUG_KMS("BDB_GD too small (%d). Invalid.\n", diff --git a/drivers/gpu/drm/i915/intel_dvo.c b/drivers/gpu/drm/i915/intel_dvo.c index bfedea3826d7..9a27ec7100ef 100644 --- a/drivers/gpu/drm/i915/intel_dvo.c +++ b/drivers/gpu/drm/i915/intel_dvo.c @@ -502,7 +502,7 @@ void intel_dvo_init(struct drm_device *dev) * special cases, but otherwise default to what's defined * in the spec. */ - if (intel_gmbus_is_valid_pin(dvo->gpio)) + if (intel_gmbus_is_valid_pin(dev_priv, dvo->gpio)) gpio = dvo->gpio; else if (dvo->type == INTEL_DVO_CHIP_LVDS) gpio = GMBUS_PIN_SSC; diff --git a/drivers/gpu/drm/i915/intel_i2c.c b/drivers/gpu/drm/i915/intel_i2c.c index ff47a8fdcb6d..ec9cc8cf642e 100644 --- a/drivers/gpu/drm/i915/intel_i2c.c +++ b/drivers/gpu/drm/i915/intel_i2c.c @@ -49,6 +49,12 @@ static const struct gmbus_pin gmbus_pins[] = { [GMBUS_PIN_DPD] = { "dpd", GPIOF }, }; +bool intel_gmbus_is_valid_pin(struct drm_i915_private *dev_priv, + unsigned int pin) +{ + return pin < ARRAY_SIZE(gmbus_pins) && gmbus_pins[pin].reg; +} + /* Intel GPIO access functions */ #define I2C_RISEFALL_TIME 10 @@ -534,7 +540,7 @@ int intel_setup_gmbus(struct drm_device *dev) init_waitqueue_head(&dev_priv->gmbus_wait_queue); for (pin = 0; pin < ARRAY_SIZE(dev_priv->gmbus); pin++) { - if (!intel_gmbus_is_valid_pin(pin)) + if (!intel_gmbus_is_valid_pin(dev_priv, pin)) continue; bus = &dev_priv->gmbus[pin]; @@ -571,7 +577,7 @@ int intel_setup_gmbus(struct drm_device *dev) err: while (--pin) { - if (!intel_gmbus_is_valid_pin(pin)) + if (!intel_gmbus_is_valid_pin(dev_priv, pin)) continue; bus = &dev_priv->gmbus[pin]; @@ -583,7 +589,7 @@ err: struct i2c_adapter *intel_gmbus_get_adapter(struct drm_i915_private *dev_priv, unsigned int pin) { - if (WARN_ON(!intel_gmbus_is_valid_pin(pin))) + if (WARN_ON(!intel_gmbus_is_valid_pin(dev_priv, pin))) return NULL; return &dev_priv->gmbus[pin].adapter; @@ -613,7 +619,7 @@ void intel_teardown_gmbus(struct drm_device *dev) unsigned int pin; for (pin = 0; pin < ARRAY_SIZE(dev_priv->gmbus); pin++) { - if (!intel_gmbus_is_valid_pin(pin)) + if (!intel_gmbus_is_valid_pin(dev_priv, pin)) continue; bus = &dev_priv->gmbus[pin]; diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index d61aa78ed7e3..314a5d56ace2 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c @@ -781,7 +781,7 @@ static bool lvds_is_present_in_vbt(struct drm_device *dev, child->device_type != DEVICE_TYPE_LFP) continue; - if (intel_gmbus_is_valid_pin(child->i2c_pin)) + if (intel_gmbus_is_valid_pin(dev_priv, child->i2c_pin)) *i2c_pin = child->i2c_pin; /* However, we cannot trust the BIOS writers to populate diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index 124992e48abd..b121796c86aa 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c @@ -2291,7 +2291,8 @@ intel_sdvo_select_i2c_bus(struct drm_i915_private *dev_priv, else mapping = &dev_priv->sdvo_mappings[1]; - if (mapping->initialized && intel_gmbus_is_valid_pin(mapping->i2c_pin)) + if (mapping->initialized && + intel_gmbus_is_valid_pin(dev_priv, mapping->i2c_pin)) pin = mapping->i2c_pin; else pin = GMBUS_PIN_DPB; -- cgit v1.2.3 From 9bdbd0b911086d03a27e1fe9531b41f5411ccfac Mon Sep 17 00:00:00 2001 From: Ander Conselvan de Oliveira Date: Fri, 10 Apr 2015 10:59:10 +0300 Subject: drm/i915: Allocate connector state together with the connectors Connector states were being allocated in intel_setup_outputs() in loop over all connectors. That meant hot-added connectors would have a NULL state. Since the change to use a struct drm_atomic_state for the legacy modeset, connector states are necessary for the i915 driver to function properly, so that would lead to oopses. v2: Fix test for intel_connector_init() success in lvds and sdvo (PRTS) Signed-off-by: Ander Conselvan de Oliveira Reported-and-tested-by: Nicolas Kalkhof Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_crt.c | 2 +- drivers/gpu/drm/i915/intel_ddi.c | 4 +-- drivers/gpu/drm/i915/intel_display.c | 62 ++++++++++++++++-------------------- drivers/gpu/drm/i915/intel_dp.c | 2 +- drivers/gpu/drm/i915/intel_dp_mst.c | 2 +- drivers/gpu/drm/i915/intel_drv.h | 2 ++ drivers/gpu/drm/i915/intel_dsi.c | 2 +- drivers/gpu/drm/i915/intel_dvo.c | 2 +- drivers/gpu/drm/i915/intel_hdmi.c | 2 +- drivers/gpu/drm/i915/intel_lvds.c | 6 ++++ drivers/gpu/drm/i915/intel_sdvo.c | 22 +++++++++++-- drivers/gpu/drm/i915/intel_tv.c | 2 +- 12 files changed, 64 insertions(+), 46 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_sdvo.c') diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c index fa5699c8452b..93bb5159d093 100644 --- a/drivers/gpu/drm/i915/intel_crt.c +++ b/drivers/gpu/drm/i915/intel_crt.c @@ -851,7 +851,7 @@ void intel_crt_init(struct drm_device *dev) if (!crt) return; - intel_connector = kzalloc(sizeof(*intel_connector), GFP_KERNEL); + intel_connector = intel_connector_alloc(); if (!intel_connector) { kfree(crt); return; diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 8c692d8a3ef6..486f6fa68db1 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -2101,7 +2101,7 @@ intel_ddi_init_dp_connector(struct intel_digital_port *intel_dig_port) struct intel_connector *connector; enum port port = intel_dig_port->port; - connector = kzalloc(sizeof(*connector), GFP_KERNEL); + connector = intel_connector_alloc(); if (!connector) return NULL; @@ -2120,7 +2120,7 @@ intel_ddi_init_hdmi_connector(struct intel_digital_port *intel_dig_port) struct intel_connector *connector; enum port port = intel_dig_port->port; - connector = kzalloc(sizeof(*connector), GFP_KERNEL); + connector = intel_connector_alloc(); if (!connector) return NULL; diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index a0be6ab7ba7b..4a074aa685e6 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -5685,6 +5685,34 @@ static void intel_connector_check_state(struct intel_connector *connector) } } +int intel_connector_init(struct intel_connector *connector) +{ + struct drm_connector_state *connector_state; + + connector_state = kzalloc(sizeof *connector_state, GFP_KERNEL); + if (!connector_state) + return -ENOMEM; + + connector->base.state = connector_state; + return 0; +} + +struct intel_connector *intel_connector_alloc(void) +{ + struct intel_connector *connector; + + connector = kzalloc(sizeof *connector, GFP_KERNEL); + if (!connector) + return NULL; + + if (intel_connector_init(connector) < 0) { + kfree(connector); + return NULL; + } + + return connector; +} + /* Even simpler default implementation, if there's really no special case to * consider. */ void intel_connector_dpms(struct drm_connector *connector, int mode) @@ -13187,7 +13215,6 @@ static void intel_setup_outputs(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; struct intel_encoder *encoder; - struct drm_connector *connector; bool dpd_is_edp = false; intel_lvds_init(dev); @@ -13323,39 +13350,6 @@ static void intel_setup_outputs(struct drm_device *dev) if (SUPPORTS_TV(dev)) intel_tv_init(dev); - /* - * FIXME: We don't have full atomic support yet, but we want to be - * able to enable/test plane updates via the atomic interface in the - * meantime. However as soon as we flip DRIVER_ATOMIC on, the DRM core - * will take some atomic codepaths to lookup properties during - * drmModeGetConnector() that unconditionally dereference - * connector->state. - * - * We create a dummy connector state here for each connector to ensure - * the DRM core doesn't try to dereference a NULL connector->state. - * The actual connector properties will never be updated or contain - * useful information, but since we're doing this specifically for - * testing/debug of the plane operations (and only when a specific - * kernel module option is given), that shouldn't really matter. - * - * We are also relying on these states to convert the legacy mode set - * to use a drm_atomic_state struct. The states are kept consistent - * with actual state, so that it is safe to rely on that instead of - * the staged config. - * - * Once atomic support for crtc's + connectors lands, this loop should - * be removed since we'll be setting up real connector state, which - * will contain Intel-specific properties. - */ - list_for_each_entry(connector, - &dev->mode_config.connector_list, - head) { - if (!WARN_ON(connector->state)) { - connector->state = kzalloc(sizeof(*connector->state), - GFP_KERNEL); - } - } - intel_psr_init(dev); for_each_intel_encoder(dev, encoder) { diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 1b87969536ff..589cd92d5c30 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -5602,7 +5602,7 @@ intel_dp_init(struct drm_device *dev, int output_reg, enum port port) if (!intel_dig_port) return; - intel_connector = kzalloc(sizeof(*intel_connector), GFP_KERNEL); + intel_connector = intel_connector_alloc(); if (!intel_connector) { kfree(intel_dig_port); return; diff --git a/drivers/gpu/drm/i915/intel_dp_mst.c b/drivers/gpu/drm/i915/intel_dp_mst.c index adcc5e641347..73350894e2c9 100644 --- a/drivers/gpu/drm/i915/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/intel_dp_mst.c @@ -415,7 +415,7 @@ static struct drm_connector *intel_dp_add_mst_connector(struct drm_dp_mst_topolo struct drm_connector *connector; int i; - intel_connector = kzalloc(sizeof(*intel_connector), GFP_KERNEL); + intel_connector = intel_connector_alloc(); if (!intel_connector) return NULL; diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 7a0aa2431bc0..638024fcc8ff 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -928,6 +928,8 @@ void intel_crtc_restore_mode(struct drm_crtc *crtc); void intel_crtc_control(struct drm_crtc *crtc, bool enable); void intel_crtc_update_dpms(struct drm_crtc *crtc); void intel_encoder_destroy(struct drm_encoder *encoder); +int intel_connector_init(struct intel_connector *); +struct intel_connector *intel_connector_alloc(void); void intel_connector_dpms(struct drm_connector *, int mode); bool intel_connector_get_hw_state(struct intel_connector *connector); void intel_modeset_check_state(struct drm_device *dev); diff --git a/drivers/gpu/drm/i915/intel_dsi.c b/drivers/gpu/drm/i915/intel_dsi.c index 572251e9810b..51966426addf 100644 --- a/drivers/gpu/drm/i915/intel_dsi.c +++ b/drivers/gpu/drm/i915/intel_dsi.c @@ -1007,7 +1007,7 @@ void intel_dsi_init(struct drm_device *dev) if (!intel_dsi) return; - intel_connector = kzalloc(sizeof(*intel_connector), GFP_KERNEL); + intel_connector = intel_connector_alloc(); if (!intel_connector) { kfree(intel_dsi); return; diff --git a/drivers/gpu/drm/i915/intel_dvo.c b/drivers/gpu/drm/i915/intel_dvo.c index 9a27ec7100ef..7c9f85285aea 100644 --- a/drivers/gpu/drm/i915/intel_dvo.c +++ b/drivers/gpu/drm/i915/intel_dvo.c @@ -469,7 +469,7 @@ void intel_dvo_init(struct drm_device *dev) if (!intel_dvo) return; - intel_connector = kzalloc(sizeof(*intel_connector), GFP_KERNEL); + intel_connector = intel_connector_alloc(); if (!intel_connector) { kfree(intel_dvo); return; diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index 26222e6c1ff3..02252d9a0cc3 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c @@ -1755,7 +1755,7 @@ void intel_hdmi_init(struct drm_device *dev, int hdmi_reg, enum port port) if (!intel_dig_port) return; - intel_connector = kzalloc(sizeof(*intel_connector), GFP_KERNEL); + intel_connector = intel_connector_alloc(); if (!intel_connector) { kfree(intel_dig_port); return; diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index 314a5d56ace2..9a9df0fa67f9 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c @@ -946,6 +946,12 @@ void intel_lvds_init(struct drm_device *dev) return; } + if (intel_connector_init(&lvds_connector->base) < 0) { + kfree(lvds_connector); + kfree(lvds_encoder); + return; + } + lvds_encoder->attached_connector = lvds_connector; intel_encoder = &lvds_encoder->base; diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index b121796c86aa..10cd33252838 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c @@ -2427,6 +2427,22 @@ intel_sdvo_add_hdmi_properties(struct intel_sdvo *intel_sdvo, } } +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) { @@ -2438,7 +2454,7 @@ intel_sdvo_dvi_init(struct intel_sdvo *intel_sdvo, int device) 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; @@ -2492,7 +2508,7 @@ intel_sdvo_tv_init(struct intel_sdvo *intel_sdvo, int type) 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; @@ -2571,7 +2587,7 @@ intel_sdvo_lvds_init(struct intel_sdvo *intel_sdvo, int device) 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; diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c index bc1d9d740904..8b9d325bda3c 100644 --- a/drivers/gpu/drm/i915/intel_tv.c +++ b/drivers/gpu/drm/i915/intel_tv.c @@ -1621,7 +1621,7 @@ intel_tv_init(struct drm_device *dev) return; } - intel_connector = kzalloc(sizeof(*intel_connector), GFP_KERNEL); + intel_connector = intel_connector_alloc(); if (!intel_connector) { kfree(intel_tv); return; -- cgit v1.2.3 From abab6311a5784a94a35beda54d4b25312cfc77f3 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Tue, 5 May 2015 17:17:32 +0300 Subject: drm/i915: Use POSTING_READ() in intel_sdvo_write_sdvox() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use POSTING_READ() in intel_sdvo_write_sdvox() as appropriate. Signed-off-by: Ville Syrjälä Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_sdvo.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_sdvo.c') diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index 10cd33252838..0a0625761f42 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c @@ -242,7 +242,7 @@ static void intel_sdvo_write_sdvox(struct intel_sdvo *intel_sdvo, u32 val) 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); return; } @@ -259,9 +259,9 @@ static void intel_sdvo_write_sdvox(struct intel_sdvo *intel_sdvo, u32 val) 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); } } -- cgit v1.2.3 From e8504ee293f62b380b55b727d2da7aa429db8f8d Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Tue, 5 May 2015 17:17:33 +0300 Subject: drm/i915: Write the SDVO reg twice on IBX MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On IBX the SDVO/HDMI register write may be masked when enabling the port, so it may need to written twice. The HDMI code does this, but the SDVO code does not. Add the workaround to the SDVO code as well. Signed-off-by: Ville Syrjälä Reviewed-by: Jesse Barnes Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_sdvo.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers/gpu/drm/i915/intel_sdvo.c') diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index 0a0625761f42..e3e9c98eaf52 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c @@ -243,6 +243,14 @@ static void intel_sdvo_write_sdvox(struct intel_sdvo *intel_sdvo, u32 val) if (intel_sdvo->sdvo_reg == PCH_SDVOB) { I915_WRITE(intel_sdvo->sdvo_reg, val); 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; } -- cgit v1.2.3 From 1612c8bd4cef20dd06e8622bb8ab9bbe9f90c0e5 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Tue, 5 May 2015 17:17:34 +0300 Subject: drm/i915: Fix the IBX transcoder B workarounds MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently the IBX transcoder B workarounds are not working correctly. Well, the HDMI one seems to be working somewhat, but the DP one is definitely busted. After a bit of experimentation it looks like the best way to make this work is first disable the port on transcoder B, and then re-enable it transcoder A, and immediately disable it again. We can also clean up the code by noting that we can't be called without a valid crtc. And also note that port A on ILK does not need the workaround, so let's check for that one too. Signed-off-by: Ville Syrjälä Reviewed-by: Jesse Barnes Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_dp.c | 37 ++++++++++++++++------------- drivers/gpu/drm/i915/intel_hdmi.c | 50 ++++++++++++++++++--------------------- drivers/gpu/drm/i915/intel_sdvo.c | 41 +++++++++++++------------------- 3 files changed, 60 insertions(+), 68 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_sdvo.c') diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index d86e1f951666..abd442af4127 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -3843,6 +3843,7 @@ static void intel_dp_link_down(struct intel_dp *intel_dp) { struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); + struct intel_crtc *crtc = to_intel_crtc(intel_dig_port->base.base.crtc); enum port port = intel_dig_port->port; struct drm_device *dev = intel_dig_port->base.base.dev; struct drm_i915_private *dev_priv = dev->dev_private; @@ -3859,34 +3860,38 @@ intel_dp_link_down(struct intel_dp *intel_dp) if ((IS_GEN7(dev) && port == PORT_A) || (HAS_PCH_CPT(dev) && port != PORT_A)) { DP &= ~DP_LINK_TRAIN_MASK_CPT; - I915_WRITE(intel_dp->output_reg, DP | DP_LINK_TRAIN_PAT_IDLE_CPT); + DP |= DP_LINK_TRAIN_PAT_IDLE_CPT; } else { if (IS_CHERRYVIEW(dev)) DP &= ~DP_LINK_TRAIN_MASK_CHV; else DP &= ~DP_LINK_TRAIN_MASK; - I915_WRITE(intel_dp->output_reg, DP | DP_LINK_TRAIN_PAT_IDLE); + DP |= DP_LINK_TRAIN_PAT_IDLE; } + I915_WRITE(intel_dp->output_reg, DP); POSTING_READ(intel_dp->output_reg); - if (HAS_PCH_IBX(dev) && - I915_READ(intel_dp->output_reg) & DP_PIPEB_SELECT) { - /* Hardware workaround: leaving our transcoder select - * set to transcoder B while it's off will prevent the - * corresponding HDMI output on transcoder A. - * - * Combine this with another hardware workaround: - * transcoder select bit can only be cleared while the - * port is enabled. - */ - DP &= ~DP_PIPEB_SELECT; + DP &= ~(DP_PORT_EN | DP_AUDIO_OUTPUT_ENABLE); + I915_WRITE(intel_dp->output_reg, DP); + POSTING_READ(intel_dp->output_reg); + + /* + * HW workaround for IBX, we need to move the port + * to transcoder A after disabling it to allow the + * matching HDMI port to be enabled on transcoder A. + */ + if (HAS_PCH_IBX(dev) && crtc->pipe == PIPE_B && port != PORT_A) { + /* always enable with pattern 1 (as per spec) */ + DP &= ~(DP_PIPEB_SELECT | DP_LINK_TRAIN_MASK); + DP |= DP_PORT_EN | DP_LINK_TRAIN_PAT_1; + I915_WRITE(intel_dp->output_reg, DP); + POSTING_READ(intel_dp->output_reg); + + DP &= ~DP_PORT_EN; I915_WRITE(intel_dp->output_reg, DP); POSTING_READ(intel_dp->output_reg); } - DP &= ~DP_AUDIO_OUTPUT_ENABLE; - I915_WRITE(intel_dp->output_reg, DP & ~DP_PORT_EN); - POSTING_READ(intel_dp->output_reg); msleep(intel_dp->panel_power_down_delay); } diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index d148e09db901..fb2dc84e1061 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c @@ -873,41 +873,37 @@ static void intel_disable_hdmi(struct intel_encoder *encoder) struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base); struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc); u32 temp; - u32 enable_bits = SDVO_ENABLE | SDVO_AUDIO_ENABLE; if (crtc->config->has_audio) intel_audio_codec_disable(encoder); temp = I915_READ(intel_hdmi->hdmi_reg); - /* HW workaround for IBX, we need to move the port to transcoder A - * before disabling it. */ - if (HAS_PCH_IBX(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_PIPE_B_SELECT; - I915_WRITE(intel_hdmi->hdmi_reg, temp); - POSTING_READ(intel_hdmi->hdmi_reg); - - /* Again we need to write this twice. */ - I915_WRITE(intel_hdmi->hdmi_reg, temp); - POSTING_READ(intel_hdmi->hdmi_reg); - - /* Transcoder selection bits only update - * effectively on vblank. */ - if (crtc) - intel_wait_for_vblank(dev, pipe); - else - msleep(50); - } - } - - temp &= ~enable_bits; - + temp &= ~(SDVO_ENABLE | SDVO_AUDIO_ENABLE); I915_WRITE(intel_hdmi->hdmi_reg, temp); POSTING_READ(intel_hdmi->hdmi_reg); + + /* + * 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) && crtc->pipe == PIPE_B) { + temp &= ~SDVO_PIPE_B_SELECT; + temp |= SDVO_ENABLE; + /* + * HW workaround, need to write this twice for issue + * that may result in first write getting masked. + */ + I915_WRITE(intel_hdmi->hdmi_reg, temp); + POSTING_READ(intel_hdmi->hdmi_reg); + I915_WRITE(intel_hdmi->hdmi_reg, temp); + POSTING_READ(intel_hdmi->hdmi_reg); + + temp &= ~SDVO_ENABLE; + I915_WRITE(intel_hdmi->hdmi_reg, temp); + POSTING_READ(intel_hdmi->hdmi_reg); + } } static int hdmi_portclock_limit(struct intel_hdmi *hdmi, bool respect_dvi_limit) diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index e3e9c98eaf52..4a876914f212 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c @@ -1437,6 +1437,7 @@ static void intel_disable_sdvo(struct intel_encoder *encoder) { 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); @@ -1445,32 +1446,22 @@ static void intel_disable_sdvo(struct intel_encoder *encoder) 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_PIPE_B_SELECT; - I915_WRITE(intel_sdvo->sdvo_reg, temp); - POSTING_READ(intel_sdvo->sdvo_reg); - - /* 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); - } - } - intel_sdvo_write_sdvox(intel_sdvo, temp & ~SDVO_ENABLE); + 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; + temp |= SDVO_ENABLE; + intel_sdvo_write_sdvox(intel_sdvo, temp); + + temp &= ~SDVO_ENABLE; + intel_sdvo_write_sdvox(intel_sdvo, temp); } } -- cgit v1.2.3 From 3c65d1d1bb92ea959e8bce3eeae90fe5c3daa58a Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Tue, 5 May 2015 17:17:36 +0300 Subject: drm/i915: Disable SDVO port after the pipe on PCH platforms MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit While at it also remove the redundant/unneeded w/a like done for hdmi already. Signed-off-by: Ville Syrjälä Reviewed-by: Jesse Barnes [danvet: Mention that this also removes the unneeded w/a, as suggested by Jesse.] Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_sdvo.c | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_sdvo.c') diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index 4a876914f212..d24ef75596a1 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c @@ -1465,6 +1465,15 @@ static void intel_disable_sdvo(struct intel_encoder *encoder) } } +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) { struct drm_device *dev = encoder->base.dev; @@ -1477,14 +1486,9 @@ static void intel_enable_sdvo(struct intel_encoder *encoder) 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); @@ -2987,7 +2991,12 @@ bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob) } intel_encoder->compute_config = intel_sdvo_compute_config; - intel_encoder->disable = intel_disable_sdvo; + 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; -- cgit v1.2.3