aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu
diff options
context:
space:
mode:
authorMa Ling <ling.ma@intel.com>2009-05-18 04:12:46 -0400
committerEric Anholt <eric@anholt.net>2009-05-22 16:21:31 -0400
commit619ac3b75a1e9b2df66857f6a0fb466f1da5fa9e (patch)
tree2a67e21c57157bae694c1cc780fbbf36830144ca /drivers/gpu
parentad5b2a6db3eddc41358d8a73f5cfe1c38e7e3a19 (diff)
drm/i915: Use an I2C algo to do the flip to SDVO DDC bus.
Previously, we would set the control bus switch before calls were made to request EDID information over DDC. But recently the DDC code started doing multiple I2C transfers to get the EDID extensions as well. This tripped up SDVO, because the control bus switch is only in effect until the next STOP after a START. By doing our own algo, we can wrap each i2c transaction on the DDC I2C bus with the control bus switch it requires. freedesktop.org bug #21042 Signed-off-by: Ma Ling <ling.ma@intel.com> [anholt: Hand application for conflict, fixed error path] Signed-off-by: Eric Anholt <eric@anholt.net>
Diffstat (limited to 'drivers/gpu')
-rw-r--r--drivers/gpu/drm/i915/intel_sdvo.c67
1 files changed, 63 insertions, 4 deletions
diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c
index ded122c1ae2d..f3ef6bfd8ffc 100644
--- a/drivers/gpu/drm/i915/intel_sdvo.c
+++ b/drivers/gpu/drm/i915/intel_sdvo.c
@@ -1402,10 +1402,8 @@ static enum drm_connector_status intel_sdvo_detect(struct drm_connector *connect
1402static void intel_sdvo_get_ddc_modes(struct drm_connector *connector) 1402static void intel_sdvo_get_ddc_modes(struct drm_connector *connector)
1403{ 1403{
1404 struct intel_output *intel_output = to_intel_output(connector); 1404 struct intel_output *intel_output = to_intel_output(connector);
1405 struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv;
1406 1405
1407 /* set the bus switch and get the modes */ 1406 /* set the bus switch and get the modes */
1408 intel_sdvo_set_control_bus_switch(intel_output, sdvo_priv->ddc_bus);
1409 intel_ddc_get_modes(intel_output); 1407 intel_ddc_get_modes(intel_output);
1410 1408
1411#if 0 1409#if 0
@@ -1601,6 +1599,9 @@ static void intel_sdvo_destroy(struct drm_connector *connector)
1601 1599
1602 if (intel_output->i2c_bus) 1600 if (intel_output->i2c_bus)
1603 intel_i2c_destroy(intel_output->i2c_bus); 1601 intel_i2c_destroy(intel_output->i2c_bus);
1602 if (intel_output->ddc_bus)
1603 intel_i2c_destroy(intel_output->ddc_bus);
1604
1604 drm_sysfs_connector_remove(connector); 1605 drm_sysfs_connector_remove(connector);
1605 drm_connector_cleanup(connector); 1606 drm_connector_cleanup(connector);
1606 kfree(intel_output); 1607 kfree(intel_output);
@@ -1697,12 +1698,56 @@ intel_sdvo_get_digital_encoding_mode(struct intel_output *output)
1697 return true; 1698 return true;
1698} 1699}
1699 1700
1701static struct intel_output *
1702intel_sdvo_chan_to_intel_output(struct intel_i2c_chan *chan)
1703{
1704 struct drm_device *dev = chan->drm_dev;
1705 struct drm_connector *connector;
1706 struct intel_output *intel_output = NULL;
1707
1708 list_for_each_entry(connector,
1709 &dev->mode_config.connector_list, head) {
1710 if (to_intel_output(connector)->ddc_bus == chan) {
1711 intel_output = to_intel_output(connector);
1712 break;
1713 }
1714 }
1715 return intel_output;
1716}
1717
1718static int intel_sdvo_master_xfer(struct i2c_adapter *i2c_adap,
1719 struct i2c_msg msgs[], int num)
1720{
1721 struct intel_output *intel_output;
1722 struct intel_sdvo_priv *sdvo_priv;
1723 struct i2c_algo_bit_data *algo_data;
1724 struct i2c_algorithm *algo;
1725
1726 algo_data = (struct i2c_algo_bit_data *)i2c_adap->algo_data;
1727 intel_output =
1728 intel_sdvo_chan_to_intel_output(
1729 (struct intel_i2c_chan *)(algo_data->data));
1730 if (intel_output == NULL)
1731 return -EINVAL;
1732
1733 sdvo_priv = intel_output->dev_priv;
1734 algo = (struct i2c_algorithm *)intel_output->i2c_bus->adapter.algo;
1735
1736 intel_sdvo_set_control_bus_switch(intel_output, sdvo_priv->ddc_bus);
1737 return algo->master_xfer(i2c_adap, msgs, num);
1738}
1739
1740static struct i2c_algorithm intel_sdvo_i2c_bit_algo = {
1741 .master_xfer = intel_sdvo_master_xfer,
1742};
1743
1700bool intel_sdvo_init(struct drm_device *dev, int output_device) 1744bool intel_sdvo_init(struct drm_device *dev, int output_device)
1701{ 1745{
1702 struct drm_connector *connector; 1746 struct drm_connector *connector;
1703 struct intel_output *intel_output; 1747 struct intel_output *intel_output;
1704 struct intel_sdvo_priv *sdvo_priv; 1748 struct intel_sdvo_priv *sdvo_priv;
1705 struct intel_i2c_chan *i2cbus = NULL; 1749 struct intel_i2c_chan *i2cbus = NULL;
1750 struct intel_i2c_chan *ddcbus = NULL;
1706 int connector_type; 1751 int connector_type;
1707 u8 ch[0x40]; 1752 u8 ch[0x40];
1708 int i; 1753 int i;
@@ -1748,6 +1793,20 @@ bool intel_sdvo_init(struct drm_device *dev, int output_device)
1748 } 1793 }
1749 } 1794 }
1750 1795
1796 /* setup the DDC bus. */
1797 if (output_device == SDVOB)
1798 ddcbus = intel_i2c_create(dev, GPIOE, "SDVOB DDC BUS");
1799 else
1800 ddcbus = intel_i2c_create(dev, GPIOE, "SDVOC DDC BUS");
1801
1802 if (ddcbus == NULL)
1803 goto err_i2c;
1804
1805 intel_sdvo_i2c_bit_algo.functionality =
1806 intel_output->i2c_bus->adapter.algo->functionality;
1807 ddcbus->adapter.algo = &intel_sdvo_i2c_bit_algo;
1808 intel_output->ddc_bus = ddcbus;
1809
1751 /* In defaut case sdvo lvds is false */ 1810 /* In defaut case sdvo lvds is false */
1752 sdvo_priv->is_lvds = false; 1811 sdvo_priv->is_lvds = false;
1753 intel_sdvo_get_capabilities(intel_output, &sdvo_priv->caps); 1812 intel_sdvo_get_capabilities(intel_output, &sdvo_priv->caps);
@@ -1862,11 +1921,11 @@ bool intel_sdvo_init(struct drm_device *dev, int output_device)
1862 sdvo_priv->caps.output_flags & 1921 sdvo_priv->caps.output_flags &
1863 (SDVO_OUTPUT_TMDS1 | SDVO_OUTPUT_RGB1) ? 'Y' : 'N'); 1922 (SDVO_OUTPUT_TMDS1 | SDVO_OUTPUT_RGB1) ? 'Y' : 'N');
1864 1923
1865 intel_output->ddc_bus = i2cbus;
1866
1867 return true; 1924 return true;
1868 1925
1869err_i2c: 1926err_i2c:
1927 if (ddcbus != NULL)
1928 intel_i2c_destroy(intel_output->ddc_bus);
1870 intel_i2c_destroy(intel_output->i2c_bus); 1929 intel_i2c_destroy(intel_output->i2c_bus);
1871err_inteloutput: 1930err_inteloutput:
1872 kfree(intel_output); 1931 kfree(intel_output);