Commit 890f3359 authored by Chris Wilson's avatar Chris Wilson

drm/i915/i2c: Track the parent encoder rather than just the dev

The SDVO proxy i2c adapter wants to be able to use information stored in
the encoder, so pass that through intel_i2c rather than iterate over all
known encoders every time.
Signed-off-by: default avatarChris Wilson <chris@chris-wilson.co.uk>
parent 2cf34d7b
...@@ -445,19 +445,17 @@ static void intel_crt_destroy(struct drm_connector *connector) ...@@ -445,19 +445,17 @@ static void intel_crt_destroy(struct drm_connector *connector)
static int intel_crt_get_modes(struct drm_connector *connector) static int intel_crt_get_modes(struct drm_connector *connector)
{ {
int ret;
struct intel_encoder *encoder = intel_attached_encoder(connector); struct intel_encoder *encoder = intel_attached_encoder(connector);
struct i2c_adapter *ddc_bus; struct i2c_adapter *ddc_bus;
struct drm_device *dev = connector->dev; struct drm_device *dev = connector->dev;
int ret;
ret = intel_ddc_get_modes(connector, encoder->ddc_bus); ret = intel_ddc_get_modes(connector, encoder->ddc_bus);
if (ret || !IS_G4X(dev)) if (ret || !IS_G4X(dev))
goto end; goto end;
/* Try to probe digital port for output in DVI-I -> VGA mode. */ /* Try to probe digital port for output in DVI-I -> VGA mode. */
ddc_bus = intel_i2c_create(connector->dev, GPIOD, "CRTDDC_D"); ddc_bus = intel_i2c_create(encoder, GPIOD, "CRTDDC_D");
if (!ddc_bus) { if (!ddc_bus) {
dev_printk(KERN_ERR, &connector->dev->pdev->dev, dev_printk(KERN_ERR, &connector->dev->pdev->dev,
"DDC bus registration failed for CRTDDC_D.\n"); "DDC bus registration failed for CRTDDC_D.\n");
...@@ -545,7 +543,8 @@ void intel_crt_init(struct drm_device *dev) ...@@ -545,7 +543,8 @@ void intel_crt_init(struct drm_device *dev)
if (dev_priv->crt_ddc_bus != 0) if (dev_priv->crt_ddc_bus != 0)
i2c_reg = dev_priv->crt_ddc_bus; i2c_reg = dev_priv->crt_ddc_bus;
} }
intel_encoder->ddc_bus = intel_i2c_create(dev, i2c_reg, "CRTDDC_A"); intel_encoder->ddc_bus = intel_i2c_create(intel_encoder,
i2c_reg, "CRTDDC_A");
if (!intel_encoder->ddc_bus) { if (!intel_encoder->ddc_bus) {
dev_printk(KERN_ERR, &dev->pdev->dev, "DDC bus registration " dev_printk(KERN_ERR, &dev->pdev->dev, "DDC bus registration "
"failed.\n"); "failed.\n");
......
...@@ -128,7 +128,7 @@ intel_mode_get_pixel_multiplier(const struct drm_display_mode *mode) ...@@ -128,7 +128,7 @@ intel_mode_get_pixel_multiplier(const struct drm_display_mode *mode)
} }
struct intel_i2c_chan { struct intel_i2c_chan {
struct drm_device *drm_dev; /* for getting at dev. private (mmio etc.) */ struct intel_encoder *encoder;
u32 reg; /* GPIO reg */ u32 reg; /* GPIO reg */
struct i2c_adapter adapter; struct i2c_adapter adapter;
struct i2c_algo_bit_data algo; struct i2c_algo_bit_data algo;
...@@ -206,7 +206,8 @@ struct intel_unpin_work { ...@@ -206,7 +206,8 @@ struct intel_unpin_work {
bool enable_stall_check; bool enable_stall_check;
}; };
struct i2c_adapter *intel_i2c_create(struct drm_device *dev, const u32 reg, struct i2c_adapter *intel_i2c_create(struct intel_encoder *encoder,
const u32 reg,
const char *name); const char *name);
void intel_i2c_destroy(struct i2c_adapter *adapter); void intel_i2c_destroy(struct i2c_adapter *adapter);
int intel_ddc_get_modes(struct drm_connector *c, struct i2c_adapter *adapter); int intel_ddc_get_modes(struct drm_connector *c, struct i2c_adapter *adapter);
......
...@@ -362,7 +362,8 @@ void intel_dvo_init(struct drm_device *dev) ...@@ -362,7 +362,8 @@ void intel_dvo_init(struct drm_device *dev)
intel_encoder = &intel_dvo->base; intel_encoder = &intel_dvo->base;
/* Set up the DDC bus */ /* Set up the DDC bus */
intel_encoder->ddc_bus = intel_i2c_create(dev, GPIOD, "DVODDC_D"); intel_encoder->ddc_bus = intel_i2c_create(intel_encoder,
GPIOD, "DVODDC_D");
if (!intel_encoder->ddc_bus) if (!intel_encoder->ddc_bus)
goto free_intel; goto free_intel;
...@@ -389,10 +390,10 @@ void intel_dvo_init(struct drm_device *dev) ...@@ -389,10 +390,10 @@ void intel_dvo_init(struct drm_device *dev)
*/ */
if (i2cbus != NULL) if (i2cbus != NULL)
intel_i2c_destroy(i2cbus); intel_i2c_destroy(i2cbus);
if (!(i2cbus = intel_i2c_create(dev, gpio, i2cbus = intel_i2c_create(intel_encoder, gpio,
gpio == GPIOB ? "DVOI2C_B" : "DVOI2C_E"))) { gpio == GPIOB ? "DVOI2C_B" : "DVOI2C_E");
if (i2cbus == NULL)
continue; continue;
}
intel_dvo->dev = *dvo; intel_dvo->dev = *dvo;
ret = dvo->dev_ops->init(&intel_dvo->dev, i2cbus); ret = dvo->dev_ops->init(&intel_dvo->dev, i2cbus);
......
...@@ -243,26 +243,28 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_reg) ...@@ -243,26 +243,28 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_reg)
/* Set up the DDC bus. */ /* Set up the DDC bus. */
if (sdvox_reg == SDVOB) { if (sdvox_reg == SDVOB) {
intel_encoder->clone_mask = (1 << INTEL_HDMIB_CLONE_BIT); intel_encoder->clone_mask = (1 << INTEL_HDMIB_CLONE_BIT);
intel_encoder->ddc_bus = intel_i2c_create(dev, GPIOE, "HDMIB"); intel_encoder->ddc_bus = intel_i2c_create(intel_encoder,
GPIOE, "HDMIB");
dev_priv->hotplug_supported_mask |= HDMIB_HOTPLUG_INT_STATUS; dev_priv->hotplug_supported_mask |= HDMIB_HOTPLUG_INT_STATUS;
} else if (sdvox_reg == SDVOC) { } else if (sdvox_reg == SDVOC) {
intel_encoder->clone_mask = (1 << INTEL_HDMIC_CLONE_BIT); intel_encoder->clone_mask = (1 << INTEL_HDMIC_CLONE_BIT);
intel_encoder->ddc_bus = intel_i2c_create(dev, GPIOD, "HDMIC"); intel_encoder->ddc_bus = intel_i2c_create(intel_encoder,
GPIOD, "HDMIC");
dev_priv->hotplug_supported_mask |= HDMIC_HOTPLUG_INT_STATUS; dev_priv->hotplug_supported_mask |= HDMIC_HOTPLUG_INT_STATUS;
} else if (sdvox_reg == HDMIB) { } else if (sdvox_reg == HDMIB) {
intel_encoder->clone_mask = (1 << INTEL_HDMID_CLONE_BIT); intel_encoder->clone_mask = (1 << INTEL_HDMID_CLONE_BIT);
intel_encoder->ddc_bus = intel_i2c_create(dev, PCH_GPIOE, intel_encoder->ddc_bus = intel_i2c_create(intel_encoder,
"HDMIB"); PCH_GPIOE, "HDMIB");
dev_priv->hotplug_supported_mask |= HDMIB_HOTPLUG_INT_STATUS; dev_priv->hotplug_supported_mask |= HDMIB_HOTPLUG_INT_STATUS;
} else if (sdvox_reg == HDMIC) { } else if (sdvox_reg == HDMIC) {
intel_encoder->clone_mask = (1 << INTEL_HDMIE_CLONE_BIT); intel_encoder->clone_mask = (1 << INTEL_HDMIE_CLONE_BIT);
intel_encoder->ddc_bus = intel_i2c_create(dev, PCH_GPIOD, intel_encoder->ddc_bus = intel_i2c_create(intel_encoder,
"HDMIC"); PCH_GPIOD, "HDMIC");
dev_priv->hotplug_supported_mask |= HDMIC_HOTPLUG_INT_STATUS; dev_priv->hotplug_supported_mask |= HDMIC_HOTPLUG_INT_STATUS;
} else if (sdvox_reg == HDMID) { } else if (sdvox_reg == HDMID) {
intel_encoder->clone_mask = (1 << INTEL_HDMIF_CLONE_BIT); intel_encoder->clone_mask = (1 << INTEL_HDMIF_CLONE_BIT);
intel_encoder->ddc_bus = intel_i2c_create(dev, PCH_GPIOF, intel_encoder->ddc_bus = intel_i2c_create(intel_encoder,
"HDMID"); PCH_GPIOF, "HDMID");
dev_priv->hotplug_supported_mask |= HDMID_HOTPLUG_INT_STATUS; dev_priv->hotplug_supported_mask |= HDMID_HOTPLUG_INT_STATUS;
} }
if (!intel_encoder->ddc_bus) if (!intel_encoder->ddc_bus)
......
...@@ -58,25 +58,31 @@ void intel_i2c_quirk_set(struct drm_device *dev, bool enable) ...@@ -58,25 +58,31 @@ void intel_i2c_quirk_set(struct drm_device *dev, bool enable)
#define I2C_RISEFALL_TIME 20 #define I2C_RISEFALL_TIME 20
static inline struct drm_i915_private *
get_dev_priv(struct intel_i2c_chan *chan)
{
return chan->encoder->base.dev->dev_private;
}
static int get_clock(void *data) static int get_clock(void *data)
{ {
struct intel_i2c_chan *chan = data; struct intel_i2c_chan *chan = data;
struct drm_i915_private *dev_priv = chan->drm_dev->dev_private; struct drm_i915_private *dev_priv = get_dev_priv(chan);
return (I915_READ(chan->reg) & GPIO_CLOCK_VAL_IN) != 0; return (I915_READ(chan->reg) & GPIO_CLOCK_VAL_IN) != 0;
} }
static int get_data(void *data) static int get_data(void *data)
{ {
struct intel_i2c_chan *chan = data; struct intel_i2c_chan *chan = data;
struct drm_i915_private *dev_priv = chan->drm_dev->dev_private; struct drm_i915_private *dev_priv = get_dev_priv(chan);
return (I915_READ(chan->reg) & GPIO_DATA_VAL_IN) != 0; return (I915_READ(chan->reg) & GPIO_DATA_VAL_IN) != 0;
} }
static void set_clock(void *data, int state_high) static void set_clock(void *data, int state_high)
{ {
struct intel_i2c_chan *chan = data; struct intel_i2c_chan *chan = data;
struct drm_device *dev = chan->drm_dev; struct drm_i915_private *dev_priv = get_dev_priv(chan);
struct drm_i915_private *dev_priv = chan->drm_dev->dev_private; struct drm_device *dev = dev_priv->dev;
u32 reserved = 0, clock_bits; u32 reserved = 0, clock_bits;
/* On most chips, these bits must be preserved in software. */ /* On most chips, these bits must be preserved in software. */
...@@ -96,8 +102,8 @@ static void set_clock(void *data, int state_high) ...@@ -96,8 +102,8 @@ static void set_clock(void *data, int state_high)
static void set_data(void *data, int state_high) static void set_data(void *data, int state_high)
{ {
struct intel_i2c_chan *chan = data; struct intel_i2c_chan *chan = data;
struct drm_device *dev = chan->drm_dev; struct drm_i915_private *dev_priv = get_dev_priv(chan);
struct drm_i915_private *dev_priv = chan->drm_dev->dev_private; struct drm_device *dev = dev_priv->dev;
u32 reserved = 0, data_bits; u32 reserved = 0, data_bits;
/* On most chips, these bits must be preserved in software. */ /* On most chips, these bits must be preserved in software. */
...@@ -153,16 +159,18 @@ intel_i2c_reset_gmbus(struct drm_device *dev) ...@@ -153,16 +159,18 @@ intel_i2c_reset_gmbus(struct drm_device *dev)
* %GPIOH * %GPIOH
* see PRM for details on how these different busses are used. * see PRM for details on how these different busses are used.
*/ */
struct i2c_adapter *intel_i2c_create(struct drm_device *dev, const u32 reg, struct i2c_adapter *intel_i2c_create(struct intel_encoder *encoder,
const u32 reg,
const char *name) const char *name)
{ {
struct intel_i2c_chan *chan; struct intel_i2c_chan *chan;
struct drm_device *dev = encoder->base.dev;
chan = kzalloc(sizeof(struct intel_i2c_chan), GFP_KERNEL); chan = kzalloc(sizeof(struct intel_i2c_chan), GFP_KERNEL);
if (!chan) if (!chan)
goto out_free; goto out_free;
chan->drm_dev = dev; chan->encoder = encoder;
chan->reg = reg; chan->reg = reg;
snprintf(chan->adapter.name, I2C_NAME_SIZE, "intel drm %s", name); snprintf(chan->adapter.name, I2C_NAME_SIZE, "intel drm %s", name);
chan->adapter.owner = THIS_MODULE; chan->adapter.owner = THIS_MODULE;
...@@ -178,7 +186,7 @@ struct i2c_adapter *intel_i2c_create(struct drm_device *dev, const u32 reg, ...@@ -178,7 +186,7 @@ struct i2c_adapter *intel_i2c_create(struct drm_device *dev, const u32 reg,
i2c_set_adapdata(&chan->adapter, chan); i2c_set_adapdata(&chan->adapter, chan);
if(i2c_bit_add_bus(&chan->adapter)) if (i2c_bit_add_bus(&chan->adapter))
goto out_free; goto out_free;
intel_i2c_reset_gmbus(dev); intel_i2c_reset_gmbus(dev);
......
...@@ -899,7 +899,8 @@ void intel_lvds_init(struct drm_device *dev) ...@@ -899,7 +899,8 @@ void intel_lvds_init(struct drm_device *dev)
*/ */
/* Set up the DDC bus. */ /* Set up the DDC bus. */
intel_encoder->ddc_bus = intel_i2c_create(dev, gpio, "LVDSDDC_C"); intel_encoder->ddc_bus = intel_i2c_create(intel_encoder,
gpio, "LVDSDDC_C");
if (!intel_encoder->ddc_bus) { if (!intel_encoder->ddc_bus) {
dev_printk(KERN_ERR, &dev->pdev->dev, "DDC bus registration " dev_printk(KERN_ERR, &dev->pdev->dev, "DDC bus registration "
"failed.\n"); "failed.\n");
......
...@@ -184,7 +184,7 @@ struct intel_sdvo_connector { ...@@ -184,7 +184,7 @@ struct intel_sdvo_connector {
u32 cur_dot_crawl, max_dot_crawl; u32 cur_dot_crawl, max_dot_crawl;
}; };
static struct intel_sdvo *enc_to_intel_sdvo(struct drm_encoder *encoder) static struct intel_sdvo *to_intel_sdvo(struct drm_encoder *encoder)
{ {
return container_of(encoder, struct intel_sdvo, base.base); return container_of(encoder, struct intel_sdvo, base.base);
} }
...@@ -1051,7 +1051,7 @@ static bool intel_sdvo_mode_fixup(struct drm_encoder *encoder, ...@@ -1051,7 +1051,7 @@ static bool intel_sdvo_mode_fixup(struct drm_encoder *encoder,
struct drm_display_mode *mode, struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode) struct drm_display_mode *adjusted_mode)
{ {
struct intel_sdvo *intel_sdvo = enc_to_intel_sdvo(encoder); struct intel_sdvo *intel_sdvo = to_intel_sdvo(encoder);
int multiplier; int multiplier;
/* We need to construct preferred input timings based on our /* We need to construct preferred input timings based on our
...@@ -1093,7 +1093,7 @@ static void intel_sdvo_mode_set(struct drm_encoder *encoder, ...@@ -1093,7 +1093,7 @@ static void intel_sdvo_mode_set(struct drm_encoder *encoder,
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_crtc *crtc = encoder->crtc; struct drm_crtc *crtc = encoder->crtc;
struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
struct intel_sdvo *intel_sdvo = enc_to_intel_sdvo(encoder); struct intel_sdvo *intel_sdvo = to_intel_sdvo(encoder);
u32 sdvox; u32 sdvox;
struct intel_sdvo_in_out_map in_out; struct intel_sdvo_in_out_map in_out;
struct intel_sdvo_dtd input_dtd; struct intel_sdvo_dtd input_dtd;
...@@ -1200,7 +1200,7 @@ static void intel_sdvo_dpms(struct drm_encoder *encoder, int mode) ...@@ -1200,7 +1200,7 @@ static void intel_sdvo_dpms(struct drm_encoder *encoder, int mode)
{ {
struct drm_device *dev = encoder->dev; struct drm_device *dev = encoder->dev;
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_sdvo *intel_sdvo = enc_to_intel_sdvo(encoder); struct intel_sdvo *intel_sdvo = to_intel_sdvo(encoder);
struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc);
u32 temp; u32 temp;
...@@ -1899,7 +1899,7 @@ static const struct drm_connector_helper_funcs intel_sdvo_connector_helper_funcs ...@@ -1899,7 +1899,7 @@ static const struct drm_connector_helper_funcs intel_sdvo_connector_helper_funcs
static void intel_sdvo_enc_destroy(struct drm_encoder *encoder) static void intel_sdvo_enc_destroy(struct drm_encoder *encoder)
{ {
struct intel_sdvo *intel_sdvo = enc_to_intel_sdvo(encoder); struct intel_sdvo *intel_sdvo = to_intel_sdvo(encoder);
if (intel_sdvo->analog_ddc_bus) if (intel_sdvo->analog_ddc_bus)
intel_i2c_destroy(intel_sdvo->analog_ddc_bus); intel_i2c_destroy(intel_sdvo->analog_ddc_bus);
...@@ -1984,35 +1984,15 @@ intel_sdvo_get_digital_encoding_mode(struct intel_sdvo *intel_sdvo, int device) ...@@ -1984,35 +1984,15 @@ intel_sdvo_get_digital_encoding_mode(struct intel_sdvo *intel_sdvo, int device)
&intel_sdvo->is_hdmi, 1); &intel_sdvo->is_hdmi, 1);
} }
static struct intel_sdvo *
intel_sdvo_chan_to_intel_sdvo(struct intel_i2c_chan *chan)
{
struct drm_device *dev = chan->drm_dev;
struct drm_encoder *encoder;
list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
struct intel_sdvo *intel_sdvo = enc_to_intel_sdvo(encoder);
if (intel_sdvo->base.ddc_bus == &chan->adapter)
return intel_sdvo;
}
return NULL;
}
static int intel_sdvo_master_xfer(struct i2c_adapter *i2c_adap, static int intel_sdvo_master_xfer(struct i2c_adapter *i2c_adap,
struct i2c_msg msgs[], int num) struct i2c_msg msgs[], int num)
{ {
struct intel_sdvo *intel_sdvo; struct intel_sdvo *intel_sdvo;
struct i2c_algo_bit_data *algo_data;
const struct i2c_algorithm *algo; const struct i2c_algorithm *algo;
algo_data = (struct i2c_algo_bit_data *)i2c_adap->algo_data; intel_sdvo = container_of(i2c_adap->algo_data,
intel_sdvo = struct intel_sdvo,
intel_sdvo_chan_to_intel_sdvo((struct intel_i2c_chan *) base);
(algo_data->data));
if (intel_sdvo == NULL)
return -EINVAL;
algo = intel_sdvo->base.i2c_bus->algo; algo = intel_sdvo->base.i2c_bus->algo;
intel_sdvo_set_control_bus_switch(intel_sdvo, intel_sdvo->ddc_bus); intel_sdvo_set_control_bus_switch(intel_sdvo, intel_sdvo->ddc_bus);
...@@ -2560,9 +2540,13 @@ bool intel_sdvo_init(struct drm_device *dev, int sdvo_reg) ...@@ -2560,9 +2540,13 @@ bool intel_sdvo_init(struct drm_device *dev, int sdvo_reg)
/* setup the DDC bus. */ /* setup the DDC bus. */
if (IS_SDVOB(sdvo_reg)) if (IS_SDVOB(sdvo_reg))
intel_encoder->i2c_bus = intel_i2c_create(dev, i2c_reg, "SDVOCTRL_E for SDVOB"); intel_encoder->i2c_bus =
intel_i2c_create(intel_encoder,
i2c_reg, "SDVOCTRL_E for SDVOB");
else else
intel_encoder->i2c_bus = intel_i2c_create(dev, i2c_reg, "SDVOCTRL_E for SDVOC"); intel_encoder->i2c_bus =
intel_i2c_create(intel_encoder,
i2c_reg, "SDVOCTRL_E for SDVOC");
if (!intel_encoder->i2c_bus) if (!intel_encoder->i2c_bus)
goto err_inteloutput; goto err_inteloutput;
...@@ -2583,14 +2567,20 @@ bool intel_sdvo_init(struct drm_device *dev, int sdvo_reg) ...@@ -2583,14 +2567,20 @@ bool intel_sdvo_init(struct drm_device *dev, int sdvo_reg)
/* setup the DDC bus. */ /* setup the DDC bus. */
if (IS_SDVOB(sdvo_reg)) { if (IS_SDVOB(sdvo_reg)) {
intel_encoder->ddc_bus = intel_i2c_create(dev, ddc_reg, "SDVOB DDC BUS"); intel_encoder->ddc_bus =
intel_sdvo->analog_ddc_bus = intel_i2c_create(dev, analog_ddc_reg, intel_i2c_create(intel_encoder,
"SDVOB/VGA DDC BUS"); ddc_reg, "SDVOB DDC BUS");
intel_sdvo->analog_ddc_bus =
intel_i2c_create(intel_encoder,
analog_ddc_reg, "SDVOB/VGA DDC BUS");
dev_priv->hotplug_supported_mask |= SDVOB_HOTPLUG_INT_STATUS; dev_priv->hotplug_supported_mask |= SDVOB_HOTPLUG_INT_STATUS;
} else { } else {
intel_encoder->ddc_bus = intel_i2c_create(dev, ddc_reg, "SDVOC DDC BUS"); intel_encoder->ddc_bus =
intel_sdvo->analog_ddc_bus = intel_i2c_create(dev, analog_ddc_reg, intel_i2c_create(intel_encoder,
"SDVOC/VGA DDC BUS"); ddc_reg, "SDVOC DDC BUS");
intel_sdvo->analog_ddc_bus =
intel_i2c_create(intel_encoder,
analog_ddc_reg, "SDVOC/VGA DDC BUS");
dev_priv->hotplug_supported_mask |= SDVOC_HOTPLUG_INT_STATUS; dev_priv->hotplug_supported_mask |= SDVOC_HOTPLUG_INT_STATUS;
} }
if (intel_encoder->ddc_bus == NULL || intel_sdvo->analog_ddc_bus == NULL) if (intel_encoder->ddc_bus == NULL || intel_sdvo->analog_ddc_bus == NULL)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment