From patchwork Tue Aug 4 09:20:22 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tino Keitel X-Patchwork-Id: 39074 Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by demeter.kernel.org (8.14.2/8.14.2) with ESMTP id n749KSQo010812 for ; Tue, 4 Aug 2009 09:20:28 GMT Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 08AE79F3A1; Tue, 4 Aug 2009 02:20:28 -0700 (PDT) X-Original-To: intel-gfx@lists.freedesktop.org Delivered-To: intel-gfx@lists.freedesktop.org Received: from eazy.amigager.de (eazy.amigager.de [213.239.192.238]) by gabe.freedesktop.org (Postfix) with ESMTP id C01639E759 for ; Tue, 4 Aug 2009 02:20:25 -0700 (PDT) Received: from mac.home (port-87-234-80-138.dynamic.qsc.de [87.234.80.138]) by eazy.amigager.de (Postfix) with ESMTP id 134DAC8C091; Tue, 4 Aug 2009 11:20:24 +0200 (CEST) Received: from scorpion by mac.home with local (Exim 4.69) (envelope-from ) id 1MYGBy-0002Pu-TW; Tue, 04 Aug 2009 11:20:23 +0200 Date: Tue, 4 Aug 2009 11:20:22 +0200 From: Tino Keitel To: ling.ma@intel.com Message-ID: <20090804092022.GA9260@mac.home> Mail-Followup-To: ling.ma@intel.com, intel-gfx@lists.freedesktop.org References: <1246289453-11898-1-git-send-email-ling.ma@intel.com> <1246289453-11898-2-git-send-email-ling.ma@intel.com> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <1246289453-11898-2-git-send-email-ling.ma@intel.com> User-Agent: Mutt/1.5.20 (2009-06-14) Cc: intel-gfx@lists.freedesktop.org Subject: Re: [Intel-gfx] [PATCH 2/2] fetch edid for mac mini through CRT DDC X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.9 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: intel-gfx-bounces@lists.freedesktop.org Errors-To: intel-gfx-bounces@lists.freedesktop.org On Mon, Jun 29, 2009 at 23:30:53 +0800, ling.ma@intel.com wrote: > For Mac mini we will try to fetch EDID through the analog, > when we can not do through SDVO DDC. In this patch we always > will steal CRT DDC only if it is not effective. This one seems to be for the userspace driver. There is a similar patch for KMS, submitted by Keith Packard with the subject "drm/i915: sdvo: check GPIOA for SDVO DDC (vga DDC) when GPIOE fails", which works for me and also gives me a framebuffer console with the native LCD resolution. I just tested the patch from Keith Packard again with 2.6.31-rc5. The driver now seems to be stable enough to work on my Mac mini so I can confirm that this patch works for me. I doesn't apply cleanly to 2.6.31-rc5, so I attached a rebased patch. Regards, Tino diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index 4f0c309..4f3747e 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c @@ -107,6 +107,9 @@ struct intel_sdvo_priv { /* DDC bus used by this SDVO output */ uint8_t ddc_bus; + /* Mac mini hack -- use the same DDC as the analog connector */ + struct i2c_adapter *analog_ddc_bus; + int save_sdvo_mult; u16 save_active_outputs; struct intel_sdvo_dtd save_input_dtd_1, save_input_dtd_2; @@ -1435,6 +1438,33 @@ void intel_sdvo_set_hotplug(struct drm_connector *connector, int on) intel_sdvo_read_response(intel_output, &response, 2); } +static struct drm_connector * +intel_find_analog_connector(struct drm_device *dev) +{ + struct drm_connector *connector; + struct intel_output *intel_output; + list_for_each_entry(connector, &dev->mode_config.connector_list, head) { + intel_output = to_intel_output(connector); + if (intel_output->type == INTEL_OUTPUT_ANALOG) + return connector; + } + return NULL; +} + +static int +intel_analog_is_connected(struct drm_device *dev) +{ + struct drm_connector *analog_connector; + analog_connector = intel_find_analog_connector(dev); + + if (!analog_connector) + return false; + if (analog_connector->funcs->detect(analog_connector) == + connector_status_disconnected) + return false; + return true; +} + static void intel_sdvo_hdmi_sink_detect(struct drm_connector *connector) { @@ -1444,6 +1474,11 @@ intel_sdvo_hdmi_sink_detect(struct drm_connector *connector) edid = drm_get_edid(&intel_output->base, intel_output->ddc_bus); + if (edid == NULL && + sdvo_priv->analog_ddc_bus && + !intel_analog_is_connected(intel_output->base.dev)) + edid = drm_get_edid(&intel_output->base, + sdvo_priv->analog_ddc_bus); if (edid != NULL) { sdvo_priv->is_hdmi = drm_detect_hdmi_monitor(edid); kfree(edid); @@ -1475,31 +1510,33 @@ static enum drm_connector_status intel_sdvo_detect(struct drm_connector *connect static void intel_sdvo_get_ddc_modes(struct drm_connector *connector) { struct intel_output *intel_output = to_intel_output(connector); + struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv; + int num_modes; /* set the bus switch and get the modes */ - intel_ddc_get_modes(intel_output); + num_modes = intel_ddc_get_modes(intel_output); -#if 0 - struct drm_device *dev = encoder->dev; - struct drm_i915_private *dev_priv = dev->dev_private; - /* Mac mini hack. On this device, I get DDC through the analog, which - * load-detects as disconnected. I fail to DDC through the SDVO DDC, - * but it does load-detect as connected. So, just steal the DDC bits - * from analog when we fail at finding it the right way. + /* + * Mac mini hack. On this device, the DVI-I connector shares one DDC + * link between analog and digital outputs. So, if the regular SDVO + * DDC fails, check to see if the analog output is disconnected, in which + * case we'll look there for the digital DDC data. */ - crt = xf86_config->output[0]; - intel_output = crt->driver_private; - if (intel_output->type == I830_OUTPUT_ANALOG && - crt->funcs->detect(crt) == XF86OutputStatusDisconnected) { - I830I2CInit(pScrn, &intel_output->pDDCBus, GPIOA, "CRTDDC_A"); - edid_mon = xf86OutputGetEDID(crt, intel_output->pDDCBus); - xf86DestroyI2CBusRec(intel_output->pDDCBus, true, true); - } - if (edid_mon) { - xf86OutputSetEDID(output, edid_mon); - modes = xf86OutputGetEDIDModes(output); + if (num_modes == 0 && + sdvo_priv->analog_ddc_bus && + !intel_analog_is_connected(intel_output->base.dev)) + { + struct i2c_adapter *digital_ddc_bus; + + /* Switch to the analog ddc bus and try that + */ + digital_ddc_bus = intel_output->ddc_bus; + intel_output->ddc_bus = sdvo_priv->analog_ddc_bus; + + (void) intel_ddc_get_modes(intel_output); + + intel_output->ddc_bus = digital_ddc_bus; } -#endif } /** @@ -1687,6 +1724,8 @@ static void intel_sdvo_destroy(struct drm_connector *connector) if (sdvo_priv->sdvo_lvds_fixed_mode != NULL) drm_mode_destroy(connector->dev, sdvo_priv->sdvo_lvds_fixed_mode); + if (sdvo_priv->analog_ddc_bus) + intel_i2c_destroy(sdvo_priv->analog_ddc_bus); drm_sysfs_connector_remove(connector); drm_connector_cleanup(connector); @@ -1913,10 +1952,13 @@ bool intel_sdvo_init(struct drm_device *dev, int output_device) } /* setup the DDC bus. */ - if (output_device == SDVOB) + if (output_device == SDVOB) { intel_output->ddc_bus = intel_i2c_create(dev, GPIOE, "SDVOB DDC BUS"); - else + sdvo_priv->analog_ddc_bus = intel_i2c_create(dev, GPIOA, "SDVOB/VGA DDC BUS"); + } else { intel_output->ddc_bus = intel_i2c_create(dev, GPIOE, "SDVOC DDC BUS"); + sdvo_priv->analog_ddc_bus = intel_i2c_create(dev, GPIOA, "SDVOC/VGA DDC BUS"); + } if (intel_output->ddc_bus == NULL) goto err_i2c; @@ -2042,6 +2084,8 @@ bool intel_sdvo_init(struct drm_device *dev, int output_device) return true; err_i2c: + if (sdvo_priv->analog_ddc_bus != NULL) + intel_i2c_destroy(sdvo_priv->analog_ddc_bus); if (intel_output->ddc_bus != NULL) intel_i2c_destroy(intel_output->ddc_bus); if (intel_output->i2c_bus != NULL)