From patchwork Tue Feb 4 13:40:50 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jani Nikula X-Patchwork-Id: 3576181 Return-Path: X-Original-To: patchwork-intel-gfx@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 3C0D19F2F5 for ; Tue, 4 Feb 2014 13:37:48 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 15CF52017B for ; Tue, 4 Feb 2014 13:37:47 +0000 (UTC) Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by mail.kernel.org (Postfix) with ESMTP id 4E5B720149 for ; Tue, 4 Feb 2014 13:37:45 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 7115AFB71A; Tue, 4 Feb 2014 05:37:38 -0800 (PST) X-Original-To: intel-gfx@lists.freedesktop.org Delivered-To: intel-gfx@lists.freedesktop.org Received: from mga02.intel.com (mga02.intel.com [134.134.136.20]) by gabe.freedesktop.org (Postfix) with ESMTP id 9E41DFA89E; Tue, 4 Feb 2014 05:37:36 -0800 (PST) Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by orsmga101.jf.intel.com with ESMTP; 04 Feb 2014 05:37:35 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="4.95,779,1384329600"; d="scan'208";a="469646186" Received: from jnikula-mobl1.fi.intel.com (HELO localhost) ([10.237.72.185]) by fmsmga001.fm.intel.com with ESMTP; 04 Feb 2014 05:37:33 -0800 From: Jani Nikula To: intel-gfx@lists.freedesktop.org Date: Tue, 4 Feb 2014 15:40:50 +0200 Message-Id: X-Mailer: git-send-email 1.7.9.5 In-Reply-To: References: In-Reply-To: References: Organization: Intel Finland Oy - BIC 0357606-4 - Westendinkatu 7, 02160 Espoo Cc: jani.nikula@intel.com, Thierry Reding , dri-devel@lists.freedesktop.org Subject: [Intel-gfx] [RFC PATCH 7/7] drm/i915/dp: use the new drm helpers for dp i2c-over-aux X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.13 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: intel-gfx-bounces@lists.freedesktop.org Errors-To: intel-gfx-bounces@lists.freedesktop.org X-Spam-Status: No, score=-4.8 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_MED, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP The main differences are: * Many of the native aux differences mentioned in the relevant commit apply. * Native aux and i2c-over-aux defer timeouts are increased to be safe for all use cases instead of depending on DP device type and properties. * i2c start/stop/reset are not done. * i2c device name changes from port based to connector kernel device name based, for example DPDDC-A -> card0-DP-1. Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/intel_dp.c | 180 ++++---------------------------------- drivers/gpu/drm/i915/intel_drv.h | 2 - 2 files changed, 19 insertions(+), 163 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 0a8a2b189ed0..9edfa3ec2dee 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -639,155 +639,13 @@ intel_dp_aux_transfer(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg) return ret; } -static int -intel_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode, - uint8_t write_byte, uint8_t *read_byte) -{ - struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data; - struct intel_dp *intel_dp = container_of(adapter, - struct intel_dp, - adapter); - uint16_t address = algo_data->address; - uint8_t msg[5]; - uint8_t reply[2]; - unsigned retry; - int msg_bytes; - int reply_bytes; - int ret; - - /* Set up the command byte */ - if (mode & MODE_I2C_READ) - msg[0] = DP_AUX_I2C_READ << 4; - else - msg[0] = DP_AUX_I2C_WRITE << 4; - - if (!(mode & MODE_I2C_STOP)) - msg[0] |= DP_AUX_I2C_MOT << 4; - - msg[1] = address >> 8; - msg[2] = address; - - switch (mode) { - case MODE_I2C_WRITE: - msg[3] = 0; - msg[4] = write_byte; - msg_bytes = 5; - reply_bytes = 1; - break; - case MODE_I2C_READ: - msg[3] = 0; - msg_bytes = 4; - reply_bytes = 2; - break; - default: - msg_bytes = 3; - reply_bytes = 1; - break; - } - - /* - * DP1.2 sections 2.7.7.1.5.6.1 and 2.7.7.1.6.6.1: A DP Source device is - * required to retry at least seven times upon receiving AUX_DEFER - * before giving up the AUX transaction. - */ - for (retry = 0; retry < 7; retry++) { - ret = intel_dp_aux_ch(intel_dp, - msg, msg_bytes, - reply, reply_bytes); - if (ret < 0) { - DRM_DEBUG_KMS("aux_ch failed %d\n", ret); - goto out; - } - - switch ((reply[0] >> 4) & DP_AUX_NATIVE_REPLY_MASK) { - case DP_AUX_NATIVE_REPLY_ACK: - /* I2C-over-AUX Reply field is only valid - * when paired with AUX ACK. - */ - break; - case DP_AUX_NATIVE_REPLY_NACK: - DRM_DEBUG_KMS("aux_ch native nack\n"); - ret = -EREMOTEIO; - goto out; - case DP_AUX_NATIVE_REPLY_DEFER: - /* - * For now, just give more slack to branch devices. We - * could check the DPCD for I2C bit rate capabilities, - * and if available, adjust the interval. We could also - * be more careful with DP-to-Legacy adapters where a - * long legacy cable may force very low I2C bit rates. - */ - if (intel_dp->dpcd[DP_DOWNSTREAMPORT_PRESENT] & - DP_DWN_STRM_PORT_PRESENT) - usleep_range(500, 600); - else - usleep_range(300, 400); - continue; - default: - DRM_ERROR("aux_ch invalid native reply 0x%02x\n", - reply[0]); - ret = -EREMOTEIO; - goto out; - } - - switch ((reply[0] >> 4) & DP_AUX_I2C_REPLY_MASK) { - case DP_AUX_I2C_REPLY_ACK: - if (mode == MODE_I2C_READ) { - *read_byte = reply[1]; - } - ret = reply_bytes - 1; - goto out; - case DP_AUX_I2C_REPLY_NACK: - DRM_DEBUG_KMS("aux_i2c nack\n"); - ret = -EREMOTEIO; - goto out; - case DP_AUX_I2C_REPLY_DEFER: - DRM_DEBUG_KMS("aux_i2c defer\n"); - udelay(100); - break; - default: - DRM_ERROR("aux_i2c invalid reply 0x%02x\n", reply[0]); - ret = -EREMOTEIO; - goto out; - } - } - - DRM_ERROR("too many retries, giving up\n"); - ret = -EREMOTEIO; - -out: - return ret; -} - -static int -intel_dp_i2c_init(struct intel_dp *intel_dp, - struct intel_connector *intel_connector, const char *name) -{ - int ret; - - DRM_DEBUG_KMS("i2c_init %s\n", name); - intel_dp->algo.running = false; - intel_dp->algo.address = 0; - intel_dp->algo.aux_ch = intel_dp_i2c_aux_ch; - - memset(&intel_dp->adapter, '\0', sizeof(intel_dp->adapter)); - intel_dp->adapter.owner = THIS_MODULE; - intel_dp->adapter.class = I2C_CLASS_DDC; - strncpy(intel_dp->adapter.name, name, sizeof(intel_dp->adapter.name) - 1); - intel_dp->adapter.name[sizeof(intel_dp->adapter.name) - 1] = '\0'; - intel_dp->adapter.algo_data = &intel_dp->algo; - intel_dp->adapter.dev.parent = intel_connector->base.kdev; - - ret = i2c_dp_aux_add_bus(&intel_dp->adapter); - return ret; -} - static void intel_dp_aux_init(struct intel_dp *intel_dp, struct intel_connector *connector) { struct drm_device *dev = intel_dp_to_dev(intel_dp); struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); enum port port = intel_dig_port->port; + int ret; if (HAS_DDI(dev)) { switch (port) { @@ -812,6 +670,15 @@ intel_dp_aux_init(struct intel_dp *intel_dp, struct intel_connector *connector) intel_dp->aux.dev = connector->base.kdev; intel_dp->aux.transfer = intel_dp_aux_transfer; + + /* drm_dp_aux_register_i2c_bus() uses dev_name(), log the connection */ + DRM_DEBUG_KMS("registering DPDDC-%c bus for %s\n", + port_name(port), dev_name(intel_dp->aux.dev)); + + ret = drm_dp_aux_register_i2c_bus(&intel_dp->aux); + + WARN(ret, "drm_dp_aux_register_i2c_bus() failed with error %d for port %c\n", + ret, port_name(port)); } static void @@ -3073,7 +2940,7 @@ intel_dp_detect_dpcd(struct intel_dp *intel_dp) } /* If no HPD, poke DDC gently */ - if (drm_probe_ddc(&intel_dp->adapter)) + if (drm_probe_ddc(&intel_dp->aux.ddc)) return connector_status_connected; /* Well we tried, say unknown for unreliable port types */ @@ -3237,7 +3104,7 @@ intel_dp_detect(struct drm_connector *connector, bool force) if (intel_dp->force_audio != HDMI_AUDIO_AUTO) { intel_dp->has_audio = (intel_dp->force_audio == HDMI_AUDIO_ON); } else { - edid = intel_dp_get_edid(connector, &intel_dp->adapter); + edid = intel_dp_get_edid(connector, &intel_dp->aux.ddc); if (edid) { intel_dp->has_audio = drm_detect_monitor_audio(edid); kfree(edid); @@ -3263,7 +3130,7 @@ static int intel_dp_get_modes(struct drm_connector *connector) /* We should parse the EDID data and find out if it has an audio sink */ - ret = intel_dp_get_edid_modes(connector, &intel_dp->adapter); + ret = intel_dp_get_edid_modes(connector, &intel_dp->aux.ddc); if (ret) return ret; @@ -3287,7 +3154,7 @@ intel_dp_detect_audio(struct drm_connector *connector) struct edid *edid; bool has_audio = false; - edid = intel_dp_get_edid(connector, &intel_dp->adapter); + edid = intel_dp_get_edid(connector, &intel_dp->aux.ddc); if (edid) { has_audio = drm_detect_monitor_audio(edid); kfree(edid); @@ -3407,7 +3274,7 @@ void intel_dp_encoder_destroy(struct drm_encoder *encoder) struct intel_dp *intel_dp = &intel_dig_port->dp; struct drm_device *dev = intel_dp_to_dev(intel_dp); - i2c_del_adapter(&intel_dp->adapter); + drm_dp_aux_unregister_i2c_bus(&intel_dp->aux); drm_encoder_cleanup(encoder); if (is_edp(intel_dp)) { cancel_delayed_work_sync(&intel_dp->panel_vdd_work); @@ -3719,7 +3586,7 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp, /* We now know it's not a ghost, init power sequence regs. */ intel_dp_init_panel_power_sequencer_registers(dev, intel_dp, power_seq); - edid = drm_get_edid(connector, &intel_dp->adapter); + edid = drm_get_edid(connector, &intel_dp->aux.ddc); if (edid) { if (drm_add_edid_modes(connector, edid)) { drm_mode_connector_update_edid_property(connector, @@ -3767,8 +3634,7 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port, struct drm_i915_private *dev_priv = dev->dev_private; enum port port = intel_dig_port->port; struct edp_power_seq power_seq = { 0 }; - const char *name = NULL; - int type, error; + int type; /* intel_dp vfuncs */ if (IS_VALLEYVIEW(dev)) @@ -3820,23 +3686,19 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port, else intel_connector->get_hw_state = intel_connector_get_hw_state; - /* Set up the DDC bus. */ + /* Set up the hotplug pin. */ switch (port) { case PORT_A: intel_encoder->hpd_pin = HPD_PORT_A; - name = "DPDDC-A"; break; case PORT_B: intel_encoder->hpd_pin = HPD_PORT_B; - name = "DPDDC-B"; break; case PORT_C: intel_encoder->hpd_pin = HPD_PORT_C; - name = "DPDDC-C"; break; case PORT_D: intel_encoder->hpd_pin = HPD_PORT_D; - name = "DPDDC-D"; break; default: BUG(); @@ -3849,14 +3711,10 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port, intel_dp_aux_init(intel_dp, intel_connector); - error = intel_dp_i2c_init(intel_dp, intel_connector, name); - WARN(error, "intel_dp_i2c_init failed with error %d for port %c\n", - error, port_name(port)); - intel_dp->psr_setup_done = false; if (!intel_edp_init_connector(intel_dp, intel_connector, &power_seq)) { - i2c_del_adapter(&intel_dp->adapter); + drm_dp_aux_unregister_i2c_bus(&intel_dp->aux); if (is_edp(intel_dp)) { cancel_delayed_work_sync(&intel_dp->panel_vdd_work); mutex_lock(&dev->mode_config.mutex); diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 75a1329297d9..dedf1e8c937c 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -477,8 +477,6 @@ struct intel_dp { uint8_t dpcd[DP_RECEIVER_CAP_SIZE]; uint8_t psr_dpcd[EDP_PSR_RECEIVER_CAP_SIZE]; uint8_t downstream_ports[DP_MAX_DOWNSTREAM_PORTS]; - struct i2c_adapter adapter; - struct i2c_algo_dp_aux_data algo; struct drm_dp_aux aux; uint8_t train_set[4]; int panel_power_up_delay;