From patchwork Wed Oct 31 16:54:35 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sean Paul X-Patchwork-Id: 1680361 Return-Path: X-Original-To: patchwork-linux-fbdev@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork2.kernel.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by patchwork2.kernel.org (Postfix) with ESMTP id A12D1DFE75 for ; Wed, 31 Oct 2012 16:54:45 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1758120Ab2JaQyo (ORCPT ); Wed, 31 Oct 2012 12:54:44 -0400 Received: from mail-qc0-f174.google.com ([209.85.216.174]:44304 "EHLO mail-qc0-f174.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1758181Ab2JaQyn (ORCPT ); Wed, 31 Oct 2012 12:54:43 -0400 Received: by mail-qc0-f174.google.com with SMTP id o22so1094554qcr.19 for ; Wed, 31 Oct 2012 09:54:42 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:x-mailer:in-reply-to:references; bh=38zuuW7Is7m1hrOLhFiM3TpojjIUpOQcTNcYStBTDaA=; b=bv9d7HFtXt1jk0XLjChvfKZn8KA015s2rPKyYrzcZjSY7AcIaC24GJT4CdR0lrnGxR OeZjk/+ICf/wulmQivlJLD3RMUmX5BgP3mb4GUNPXekvwbG4QcwZD8a4rU0qW2yNCpEa 8QNjO669SHGPtWbZ385TJ6jmZO19yR5DE+bCE= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=from:to:cc:subject:date:message-id:x-mailer:in-reply-to:references :x-gm-message-state; bh=38zuuW7Is7m1hrOLhFiM3TpojjIUpOQcTNcYStBTDaA=; b=ICl+3dTM2fQUEp+s0VysMljuzzla/b6/uhg2gfr/rQheNiCHsgVxKDK90NMT4t+4n0 e7fpFxaK7gL+xs4yeg8C5PJRRiwqF6qlz8wksRNXk039MKmkU8V1ueR3/PQQqnPnCY7H IQa46UJYlMttECdVF0n3zPg6jIWEMpNLU7vcnjbTIeh8wd3ci/n5zNrROqn6fJHkZAuf /snO3rrl6Q0r49GSmUBypW3wyG39a8ru0YDbNIfNDz6KZbkEEaHbKW7/7JQ2p0hBtNU2 QlHCN+6e7ZsiBUDnQPGDZQ3KW7X4xNffQS6htHQ0i9mJZbODkvNhj6gpewgzBkI++W2o ztjw== Received: by 10.229.206.85 with SMTP id ft21mr6166815qcb.61.1351702482489; Wed, 31 Oct 2012 09:54:42 -0700 (PDT) Received: from seanpaul-linux2.cnc.corp.google.com (seanpaul-linux2.cnc.corp.google.com [172.29.92.76]) by mx.google.com with ESMTPS id o10sm1980933qaj.14.2012.10.31.09.54.41 (version=TLSv1/SSLv3 cipher=OTHER); Wed, 31 Oct 2012 09:54:41 -0700 (PDT) From: Sean Paul To: jg1.han@samsung.com, linux-fbdev@vger.kernel.org Cc: Sean Paul Subject: [PATCH] video: exynos_dp: Clean up SW link training Date: Wed, 31 Oct 2012 12:54:35 -0400 Message-Id: <1351702475-31324-1-git-send-email-seanpaul@chromium.org> X-Mailer: git-send-email 1.7.7.3 In-Reply-To: <005001cd7eb7$1cbe7050$563b50f0$%han@samsung.com> References: <005001cd7eb7$1cbe7050$563b50f0$%han@samsung.com> X-Gm-Message-State: ALoCoQmiOL2mKM3Q0wjVQuhZCwLSGfIWMOYzeyjo3AJDwoFJd/7kssGoWsgqTcQeVGYF53WCtm2U Sender: linux-fbdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-fbdev@vger.kernel.org Clean up some of the SW training code to make it more clear and reduce duplicate code. Signed-off-by: Sean Paul --- drivers/video/exynos/exynos_dp_core.c | 279 +++++++++++++-------------------- 1 files changed, 112 insertions(+), 167 deletions(-) Thanks for the pointer. There are still places where the code can be either simplified, or duplication removed. Below is a rebased patch for your review. Sean diff --git a/drivers/video/exynos/exynos_dp_core.c b/drivers/video/exynos/exynos_dp_core.c index 44820f2..b126e8a 100644 --- a/drivers/video/exynos/exynos_dp_core.c +++ b/drivers/video/exynos/exynos_dp_core.c @@ -276,7 +276,7 @@ static int exynos_dp_link_start(struct exynos_dp_device *dp) /* Set sink to D0 (Sink Not Ready) mode. */ retval = exynos_dp_write_byte_to_dpcd(dp, DPCD_ADDR_SINK_POWER_STATE, - DPCD_SET_POWER_STATE_D0); + DPCD_SET_POWER_STATE_D0); if (retval) return retval; @@ -301,17 +301,18 @@ static int exynos_dp_link_start(struct exynos_dp_device *dp) exynos_dp_set_training_pattern(dp, TRAINING_PTN1); /* Set RX training pattern */ - exynos_dp_write_byte_to_dpcd(dp, - DPCD_ADDR_TRAINING_PATTERN_SET, - DPCD_SCRAMBLING_DISABLED | - DPCD_TRAINING_PATTERN_1); + retval = exynos_dp_write_byte_to_dpcd(dp, + DPCD_ADDR_TRAINING_PATTERN_SET, + DPCD_SCRAMBLING_DISABLED | DPCD_TRAINING_PATTERN_1); + if (retval) + return retval; for (lane = 0; lane < lane_count; lane++) buf[lane] = DPCD_PRE_EMPHASIS_PATTERN2_LEVEL0 | DPCD_VOLTAGE_SWING_PATTERN1_LEVEL0; - retval = exynos_dp_write_bytes_to_dpcd(dp, - DPCD_ADDR_TRAINING_LANE0_SET, - lane_count, buf); + + retval = exynos_dp_write_bytes_to_dpcd(dp, DPCD_ADDR_TRAINING_LANE0_SET, + lane_count, buf); return retval; } @@ -337,18 +338,17 @@ static int exynos_dp_clock_recovery_ok(u8 link_status[2], int lane_count) return 0; } -static int exynos_dp_channel_eq_ok(u8 link_align[3], int lane_count) +static int exynos_dp_channel_eq_ok(u8 link_status[2], u8 link_align, + int lane_count) { int lane; - u8 lane_align; u8 lane_status; - lane_align = link_align[2]; - if ((lane_align & DPCD_INTERLANE_ALIGN_DONE) == 0) + if ((link_align & DPCD_INTERLANE_ALIGN_DONE) == 0) return -EINVAL; for (lane = 0; lane < lane_count; lane++) { - lane_status = exynos_dp_get_lane_status(link_align, lane); + lane_status = exynos_dp_get_lane_status(link_status, lane); lane_status &= DPCD_CHANNEL_EQ_BITS; if (lane_status != DPCD_CHANNEL_EQ_BITS) return -EINVAL; @@ -432,22 +432,47 @@ static void exynos_dp_reduce_link_rate(struct exynos_dp_device *dp) dp->link_train.lt_state = FAILED; } +static void exynos_dp_get_adjust_training_lane(struct exynos_dp_device *dp, + u8 adjust_request[2]) +{ + int lane, lane_count; + u8 voltage_swing, pre_emphasis, training_lane; + + lane_count = dp->link_train.lane_count; + for (lane = 0; lane < lane_count; lane++) { + voltage_swing = exynos_dp_get_adjust_request_voltage( + adjust_request, lane); + pre_emphasis = exynos_dp_get_adjust_request_pre_emphasis( + adjust_request, lane); + training_lane = DPCD_VOLTAGE_SWING_SET(voltage_swing) | + DPCD_PRE_EMPHASIS_SET(pre_emphasis); + + if (voltage_swing == VOLTAGE_LEVEL_3) + training_lane |= DPCD_MAX_SWING_REACHED; + if (pre_emphasis == PRE_EMPHASIS_LEVEL_3) + training_lane |= DPCD_MAX_PRE_EMPHASIS_REACHED; + + dp->link_train.training_lane[lane] = training_lane; + } +} + static int exynos_dp_process_clock_recovery(struct exynos_dp_device *dp) { - u8 link_status[2]; int lane, lane_count, retval; - - u8 adjust_request[2]; - u8 voltage_swing; - u8 pre_emphasis; - u8 training_lane; + u8 voltage_swing, pre_emphasis, training_lane; + u8 link_status[2], adjust_request[2]; usleep_range(100, 101); lane_count = dp->link_train.lane_count; retval = exynos_dp_read_bytes_from_dpcd(dp, DPCD_ADDR_LANE0_1_STATUS, - 2, link_status); + 2, link_status); + if (retval) + return retval; + + retval = exynos_dp_read_bytes_from_dpcd(dp, + DPCD_ADDR_ADJUST_REQUEST_LANE0_1, 2, adjust_request); if (retval) return retval; @@ -455,43 +480,9 @@ static int exynos_dp_process_clock_recovery(struct exynos_dp_device *dp) /* set training pattern 2 for EQ */ exynos_dp_set_training_pattern(dp, TRAINING_PTN2); - for (lane = 0; lane < lane_count; lane++) { - retval = exynos_dp_read_bytes_from_dpcd(dp, - DPCD_ADDR_ADJUST_REQUEST_LANE0_1, - 2, adjust_request); - if (retval) - return retval; - - voltage_swing = exynos_dp_get_adjust_request_voltage( - adjust_request, lane); - pre_emphasis = exynos_dp_get_adjust_request_pre_emphasis( - adjust_request, lane); - training_lane = DPCD_VOLTAGE_SWING_SET(voltage_swing) | - DPCD_PRE_EMPHASIS_SET(pre_emphasis); - - if (voltage_swing == VOLTAGE_LEVEL_3) - training_lane |= DPCD_MAX_SWING_REACHED; - if (pre_emphasis == PRE_EMPHASIS_LEVEL_3) - training_lane |= DPCD_MAX_PRE_EMPHASIS_REACHED; - - dp->link_train.training_lane[lane] = training_lane; - - exynos_dp_set_lane_link_training(dp, - dp->link_train.training_lane[lane], - lane); - } - retval = exynos_dp_write_byte_to_dpcd(dp, DPCD_ADDR_TRAINING_PATTERN_SET, - DPCD_SCRAMBLING_DISABLED | - DPCD_TRAINING_PATTERN_2); - if (retval) - return retval; - - retval = exynos_dp_write_bytes_to_dpcd(dp, - DPCD_ADDR_TRAINING_LANE0_SET, - lane_count, - dp->link_train.training_lane); + DPCD_SCRAMBLING_DISABLED | DPCD_TRAINING_PATTERN_2); if (retval) return retval; @@ -501,73 +492,49 @@ static int exynos_dp_process_clock_recovery(struct exynos_dp_device *dp) for (lane = 0; lane < lane_count; lane++) { training_lane = exynos_dp_get_lane_link_training( dp, lane); - retval = exynos_dp_read_bytes_from_dpcd(dp, - DPCD_ADDR_ADJUST_REQUEST_LANE0_1, - 2, adjust_request); - if (retval) - return retval; - voltage_swing = exynos_dp_get_adjust_request_voltage( adjust_request, lane); pre_emphasis = exynos_dp_get_adjust_request_pre_emphasis( adjust_request, lane); - if (voltage_swing == VOLTAGE_LEVEL_3 || - pre_emphasis == PRE_EMPHASIS_LEVEL_3) { - dev_err(dp->dev, "voltage or pre emphasis reached max level\n"); - goto reduce_link_rate; - } - - if ((DPCD_VOLTAGE_SWING_GET(training_lane) == - voltage_swing) && - (DPCD_PRE_EMPHASIS_GET(training_lane) == - pre_emphasis)) { + if (DPCD_VOLTAGE_SWING_GET(training_lane) == + voltage_swing && + DPCD_PRE_EMPHASIS_GET(training_lane) == + pre_emphasis) dp->link_train.cr_loop[lane]++; - if (dp->link_train.cr_loop[lane] == MAX_CR_LOOP) { - dev_err(dp->dev, "CR Max loop\n"); - goto reduce_link_rate; - } - } - training_lane = DPCD_VOLTAGE_SWING_SET(voltage_swing) | - DPCD_PRE_EMPHASIS_SET(pre_emphasis); - - if (voltage_swing == VOLTAGE_LEVEL_3) - training_lane |= DPCD_MAX_SWING_REACHED; - if (pre_emphasis == PRE_EMPHASIS_LEVEL_3) - training_lane |= DPCD_MAX_PRE_EMPHASIS_REACHED; - - dp->link_train.training_lane[lane] = training_lane; - - exynos_dp_set_lane_link_training(dp, - dp->link_train.training_lane[lane], lane); + if (dp->link_train.cr_loop[lane] == MAX_CR_LOOP || + voltage_swing == VOLTAGE_LEVEL_3 || + pre_emphasis == PRE_EMPHASIS_LEVEL_3) { + dev_err(dp->dev, "CR Max reached (%d,%d,%d)\n", + dp->link_train.cr_loop[lane], + voltage_swing, pre_emphasis); + exynos_dp_reduce_link_rate(dp); + return -EIO; + } } + } + + exynos_dp_get_adjust_training_lane(dp, adjust_request); - retval = exynos_dp_write_bytes_to_dpcd(dp, - DPCD_ADDR_TRAINING_LANE0_SET, lane_count, - dp->link_train.training_lane); + for (lane = 0; lane < lane_count; lane++) { + exynos_dp_set_lane_link_training(dp, + dp->link_train.training_lane[lane], lane); + retval = exynos_dp_write_byte_to_dpcd(dp, + DPCD_ADDR_TRAINING_LANE0_SET + lane, + dp->link_train.training_lane[lane]); if (retval) return retval; } return retval; - -reduce_link_rate: - exynos_dp_reduce_link_rate(dp); - return -EIO; } static int exynos_dp_process_equalizer_training(struct exynos_dp_device *dp) { - u8 link_status[2]; - u8 link_align[3]; int lane, lane_count, retval; u32 reg; - - u8 adjust_request[2]; - u8 voltage_swing; - u8 pre_emphasis; - u8 training_lane; + u8 link_align, link_status[2], adjust_request[2]; usleep_range(400, 401); @@ -578,85 +545,63 @@ static int exynos_dp_process_equalizer_training(struct exynos_dp_device *dp) if (retval) return retval; - if (exynos_dp_clock_recovery_ok(link_status, lane_count) == 0) { - link_align[0] = link_status[0]; - link_align[1] = link_status[1]; - - exynos_dp_read_byte_from_dpcd(dp, - DPCD_ADDR_LANE_ALIGN_STATUS_UPDATED, - &link_align[2]); - - for (lane = 0; lane < lane_count; lane++) { - retval = exynos_dp_read_bytes_from_dpcd(dp, - DPCD_ADDR_ADJUST_REQUEST_LANE0_1, - 2, adjust_request); - if (retval) - return retval; + if (exynos_dp_clock_recovery_ok(link_status, lane_count)) { + exynos_dp_reduce_link_rate(dp); + return -EIO; + } - voltage_swing = exynos_dp_get_adjust_request_voltage( - adjust_request, lane); - pre_emphasis = exynos_dp_get_adjust_request_pre_emphasis( - adjust_request, lane); - training_lane = DPCD_VOLTAGE_SWING_SET(voltage_swing) | - DPCD_PRE_EMPHASIS_SET(pre_emphasis); + retval = exynos_dp_read_bytes_from_dpcd(dp, + DPCD_ADDR_ADJUST_REQUEST_LANE0_1, 2, adjust_request); + if (retval) + return retval; - if (voltage_swing == VOLTAGE_LEVEL_3) - training_lane |= DPCD_MAX_SWING_REACHED; - if (pre_emphasis == PRE_EMPHASIS_LEVEL_3) - training_lane |= DPCD_MAX_PRE_EMPHASIS_REACHED; + retval = exynos_dp_read_byte_from_dpcd(dp, + DPCD_ADDR_LANE_ALIGN_STATUS_UPDATED, &link_align); + if (retval) + return retval; - dp->link_train.training_lane[lane] = training_lane; - } + exynos_dp_get_adjust_training_lane(dp, adjust_request); - if (exynos_dp_channel_eq_ok(link_align, lane_count) == 0) { - /* traing pattern Set to Normal */ - exynos_dp_training_pattern_dis(dp); + if (!exynos_dp_channel_eq_ok(link_status, link_align, lane_count)) { + /* traing pattern Set to Normal */ + exynos_dp_training_pattern_dis(dp); - dev_info(dp->dev, "Link Training success!\n"); + dev_info(dp->dev, "Link Training success!\n"); - exynos_dp_get_link_bandwidth(dp, ®); - dp->link_train.link_rate = reg; - dev_dbg(dp->dev, "final bandwidth = %.2x\n", - dp->link_train.link_rate); + exynos_dp_get_link_bandwidth(dp, ®); + dp->link_train.link_rate = reg; + dev_dbg(dp->dev, "final bandwidth = %.2x\n", + dp->link_train.link_rate); - exynos_dp_get_lane_count(dp, ®); - dp->link_train.lane_count = reg; - dev_dbg(dp->dev, "final lane count = %.2x\n", - dp->link_train.lane_count); + exynos_dp_get_lane_count(dp, ®); + dp->link_train.lane_count = reg; + dev_dbg(dp->dev, "final lane count = %.2x\n", + dp->link_train.lane_count); - /* set enhanced mode if available */ - exynos_dp_set_enhanced_mode(dp); - dp->link_train.lt_state = FINISHED; - } else { - /* not all locked */ - dp->link_train.eq_loop++; + /* set enhanced mode if available */ + exynos_dp_set_enhanced_mode(dp); + dp->link_train.lt_state = FINISHED; - if (dp->link_train.eq_loop > MAX_EQ_LOOP) { - dev_err(dp->dev, "EQ Max loop\n"); - goto reduce_link_rate; - } + return 0; + } - for (lane = 0; lane < lane_count; lane++) - exynos_dp_set_lane_link_training(dp, - dp->link_train.training_lane[lane], - lane); + /* not all locked */ + dp->link_train.eq_loop++; - retval = exynos_dp_write_bytes_to_dpcd(dp, - DPCD_ADDR_TRAINING_LANE0_SET, - lane_count, - dp->link_train.training_lane); - if (retval) - return retval; - } - } else { - goto reduce_link_rate; + if (dp->link_train.eq_loop > MAX_EQ_LOOP) { + dev_err(dp->dev, "EQ Max loop\n"); + exynos_dp_reduce_link_rate(dp); + return -EIO; } - return 0; + for (lane = 0; lane < lane_count; lane++) + exynos_dp_set_lane_link_training(dp, + dp->link_train.training_lane[lane], lane); -reduce_link_rate: - exynos_dp_reduce_link_rate(dp); - return -EIO; + retval = exynos_dp_write_bytes_to_dpcd(dp, DPCD_ADDR_TRAINING_LANE0_SET, + lane_count, dp->link_train.training_lane); + + return retval; } static void exynos_dp_get_max_rx_bandwidth(struct exynos_dp_device *dp,