diff options
author | Ville Syrjälä <ville.syrjala@linux.intel.com> | 2022-11-18 13:55:22 +0300 |
---|---|---|
committer | Ville Syrjälä <ville.syrjala@linux.intel.com> | 2022-11-19 12:10:22 +0300 |
commit | d82b9a898d52a30adbedd158222f162489db52ac (patch) | |
tree | bbf9e0271f26e513ff1bb4cd59e61e8e1cb0b4ac /drivers/gpu/drm/i915/display/intel_dvo.c | |
parent | c584f86c6242dff11d3e8f7b1646e5470a132784 (diff) | |
download | linux-d82b9a898d52a30adbedd158222f162489db52ac.tar.xz |
drm/i915/dvo: Flatten intel_dvo_init()
The loop over intel_dvo_devices[] makes intel_dvo_init()
an ugly mess. Pull the i2c device probe out to a separate
function so that we can get rid of the loop and flatten
the code.
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20221118105525.27254-7-ville.syrjala@linux.intel.com
Reviewed-by: Jani Nikula <jani.nikula@intel.com>
Diffstat (limited to 'drivers/gpu/drm/i915/display/intel_dvo.c')
-rw-r--r-- | drivers/gpu/drm/i915/display/intel_dvo.c | 217 |
1 files changed, 117 insertions, 100 deletions
diff --git a/drivers/gpu/drm/i915/display/intel_dvo.c b/drivers/gpu/drm/i915/display/intel_dvo.c index 87ee913cf89b..bccbda50113c 100644 --- a/drivers/gpu/drm/i915/display/intel_dvo.c +++ b/drivers/gpu/drm/i915/display/intel_dvo.c @@ -415,12 +415,88 @@ static int intel_dvo_connector_type(const struct intel_dvo_device *dvo) } } +static bool intel_dvo_init_dev(struct drm_i915_private *dev_priv, + struct intel_dvo *intel_dvo, + const struct intel_dvo_device *dvo) +{ + struct i2c_adapter *i2c; + u32 dpll[I915_MAX_PIPES]; + enum pipe pipe; + int gpio; + bool ret; + + /* + * Allow the I2C driver info to specify the GPIO to be used in + * special cases, but otherwise default to what's defined + * in the spec. + */ + 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; + else + gpio = GMBUS_PIN_DPB; + + /* + * Set up the I2C bus necessary for the chip we're probing. + * It appears that everything is on GPIOE except for panels + * on i830 laptops, which are on GPIOB (DVOA). + */ + i2c = intel_gmbus_get_adapter(dev_priv, gpio); + + intel_dvo->dev = *dvo; + + /* + * GMBUS NAK handling seems to be unstable, hence let the + * transmitter detection run in bit banging mode for now. + */ + intel_gmbus_force_bit(i2c, true); + + /* + * ns2501 requires the DVO 2x clock before it will + * respond to i2c accesses, so make sure we have + * the clock enabled before we attempt to initialize + * the device. + */ + for_each_pipe(dev_priv, pipe) { + dpll[pipe] = intel_de_read(dev_priv, DPLL(pipe)); + intel_de_write(dev_priv, DPLL(pipe), + dpll[pipe] | DPLL_DVO_2X_MODE); + } + + ret = dvo->dev_ops->init(&intel_dvo->dev, i2c); + + /* restore the DVO 2x clock state to original */ + for_each_pipe(dev_priv, pipe) { + intel_de_write(dev_priv, DPLL(pipe), dpll[pipe]); + } + + intel_gmbus_force_bit(i2c, false); + + return ret; +} + +static bool intel_dvo_probe(struct drm_i915_private *dev_priv, + struct intel_dvo *intel_dvo) +{ + int i; + + /* Now, try to find a controller */ + for (i = 0; i < ARRAY_SIZE(intel_dvo_devices); i++) { + if (intel_dvo_init_dev(dev_priv, intel_dvo, + &intel_dvo_devices[i])) + return true; + } + + return false; +} + void intel_dvo_init(struct drm_i915_private *dev_priv) { struct intel_encoder *intel_encoder; struct intel_dvo *intel_dvo; struct intel_connector *intel_connector; - int i; + struct drm_connector *connector; intel_dvo = kzalloc(sizeof(*intel_dvo), GFP_KERNEL); if (!intel_dvo) @@ -432,6 +508,8 @@ void intel_dvo_init(struct drm_i915_private *dev_priv) return; } + connector = &intel_connector->base; + intel_dvo->attached_connector = intel_connector; intel_encoder = &intel_dvo->base; @@ -444,112 +522,51 @@ void intel_dvo_init(struct drm_i915_private *dev_priv) intel_encoder->pre_enable = intel_dvo_pre_enable; intel_connector->get_hw_state = intel_dvo_connector_get_hw_state; - /* Now, try to find a controller */ - for (i = 0; i < ARRAY_SIZE(intel_dvo_devices); i++) { - struct drm_connector *connector = &intel_connector->base; - const struct intel_dvo_device *dvo = &intel_dvo_devices[i]; - struct i2c_adapter *i2c; - int gpio; - bool dvoinit; - enum pipe pipe; - u32 dpll[I915_MAX_PIPES]; + if (!intel_dvo_probe(dev_priv, intel_dvo)) { + kfree(intel_dvo); + intel_connector_free(intel_connector); + return; + } - /* - * Allow the I2C driver info to specify the GPIO to be used in - * special cases, but otherwise default to what's defined - * in the spec. - */ - 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; - else - gpio = GMBUS_PIN_DPB; + intel_encoder->type = INTEL_OUTPUT_DVO; + intel_encoder->power_domain = POWER_DOMAIN_PORT_OTHER; + intel_encoder->port = intel_dvo_port(intel_dvo->dev.dvo_reg); + intel_encoder->pipe_mask = ~0; - /* - * Set up the I2C bus necessary for the chip we're probing. - * It appears that everything is on GPIOE except for panels - * on i830 laptops, which are on GPIOB (DVOA). - */ - i2c = intel_gmbus_get_adapter(dev_priv, gpio); + if (intel_dvo->dev.type != INTEL_DVO_CHIP_LVDS) + intel_encoder->cloneable = BIT(INTEL_OUTPUT_ANALOG) | + BIT(INTEL_OUTPUT_DVO); - intel_dvo->dev = *dvo; + drm_encoder_init(&dev_priv->drm, &intel_encoder->base, + &intel_dvo_enc_funcs, + intel_dvo_encoder_type(&intel_dvo->dev), + "DVO %c", port_name(intel_encoder->port)); - /* - * GMBUS NAK handling seems to be unstable, hence let the - * transmitter detection run in bit banging mode for now. - */ - intel_gmbus_force_bit(i2c, true); + if (intel_dvo->dev.type == INTEL_DVO_CHIP_TMDS) + intel_connector->polled = DRM_CONNECTOR_POLL_CONNECT | + DRM_CONNECTOR_POLL_DISCONNECT; + + drm_connector_init(&dev_priv->drm, connector, + &intel_dvo_connector_funcs, + intel_dvo_connector_type(&intel_dvo->dev)); + drm_connector_helper_add(connector, + &intel_dvo_connector_helper_funcs); + connector->display_info.subpixel_order = SubPixelHorizontalRGB; + + intel_connector_attach_encoder(intel_connector, intel_encoder); + if (intel_dvo->dev.type == INTEL_DVO_CHIP_LVDS) { /* - * ns2501 requires the DVO 2x clock before it will - * respond to i2c accesses, so make sure we have - * have the clock enabled before we attempt to - * initialize the device. + * For our LVDS chipsets, we should hopefully be able + * to dig the fixed panel mode out of the BIOS data. + * However, it's in a different format from the BIOS + * data on chipsets with integrated LVDS (stored in AIM + * headers, likely), so for now, just get the current + * mode being output through DVO. */ - for_each_pipe(dev_priv, pipe) { - dpll[pipe] = intel_de_read(dev_priv, DPLL(pipe)); - intel_de_write(dev_priv, DPLL(pipe), - dpll[pipe] | DPLL_DVO_2X_MODE); - } - - dvoinit = dvo->dev_ops->init(&intel_dvo->dev, i2c); - - /* restore the DVO 2x clock state to original */ - for_each_pipe(dev_priv, pipe) { - intel_de_write(dev_priv, DPLL(pipe), dpll[pipe]); - } - - intel_gmbus_force_bit(i2c, false); - - if (!dvoinit) - continue; - - intel_encoder->type = INTEL_OUTPUT_DVO; - intel_encoder->power_domain = POWER_DOMAIN_PORT_OTHER; - intel_encoder->port = intel_dvo_port(dvo->dvo_reg); - intel_encoder->pipe_mask = ~0; - - if (dvo->type != INTEL_DVO_CHIP_LVDS) - intel_encoder->cloneable = BIT(INTEL_OUTPUT_ANALOG) | - BIT(INTEL_OUTPUT_DVO); - - drm_encoder_init(&dev_priv->drm, &intel_encoder->base, - &intel_dvo_enc_funcs, - intel_dvo_encoder_type(dvo), - "DVO %c", port_name(intel_encoder->port)); - - if (dvo->type == INTEL_DVO_CHIP_TMDS) - intel_connector->polled = DRM_CONNECTOR_POLL_CONNECT | - DRM_CONNECTOR_POLL_DISCONNECT; - - drm_connector_init(&dev_priv->drm, connector, - &intel_dvo_connector_funcs, - intel_dvo_connector_type(dvo)); - - drm_connector_helper_add(connector, - &intel_dvo_connector_helper_funcs); - connector->display_info.subpixel_order = SubPixelHorizontalRGB; - - intel_connector_attach_encoder(intel_connector, intel_encoder); - if (dvo->type == INTEL_DVO_CHIP_LVDS) { - /* - * For our LVDS chipsets, we should hopefully be able - * to dig the fixed panel mode out of the BIOS data. - * However, it's in a different format from the BIOS - * data on chipsets with integrated LVDS (stored in AIM - * headers, likely), so for now, just get the current - * mode being output through DVO. - */ - intel_panel_add_encoder_fixed_mode(intel_connector, - intel_encoder); - - intel_panel_init(intel_connector); - } + intel_panel_add_encoder_fixed_mode(intel_connector, + intel_encoder); - return; + intel_panel_init(intel_connector); } - - kfree(intel_dvo); - intel_connector_free(intel_connector); } |