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>
This commit is contained in:
Ville Syrjälä 2022-11-18 12:55:22 +02:00
parent c584f86c62
commit d82b9a898d

View file

@ -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];
/*
* 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
* 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);
}
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);
}
if (!intel_dvo_probe(dev_priv, intel_dvo)) {
kfree(intel_dvo);
intel_connector_free(intel_connector);
return;
}
kfree(intel_dvo);
intel_connector_free(intel_connector);
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;
if (intel_dvo->dev.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(&intel_dvo->dev),
"DVO %c", port_name(intel_encoder->port));
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) {
/*
* 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);
}
}