From patchwork Mon Oct 20 12:50:04 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: vandana.kannan@intel.com X-Patchwork-Id: 5105231 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 B8BEE9F374 for ; Mon, 20 Oct 2014 12:35:54 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 7969120148 for ; Mon, 20 Oct 2014 12:35:53 +0000 (UTC) Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by mail.kernel.org (Postfix) with ESMTP id A1CDD2015E for ; Mon, 20 Oct 2014 12:35:51 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 2D63389E19; Mon, 20 Oct 2014 05:35:51 -0700 (PDT) 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 EB7FE89E19 for ; Mon, 20 Oct 2014 05:35:48 -0700 (PDT) Received: from orsmga002.jf.intel.com ([10.7.209.21]) by orsmga101.jf.intel.com with ESMTP; 20 Oct 2014 05:35:29 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.04,756,1406617200"; d="scan'208";a="621838671" Received: from vkannan-desktop.iind.intel.com ([10.223.25.137]) by orsmga002.jf.intel.com with ESMTP; 20 Oct 2014 05:34:46 -0700 From: Vandana Kannan To: intel-gfx@lists.freedesktop.org Date: Mon, 20 Oct 2014 18:20:04 +0530 Message-Id: <1413809409-8569-3-git-send-email-vandana.kannan@intel.com> X-Mailer: git-send-email 2.0.1 In-Reply-To: <1413809409-8569-1-git-send-email-vandana.kannan@intel.com> References: <1413809409-8569-1-git-send-email-vandana.kannan@intel.com> Subject: [Intel-gfx] [RFC 2/7] drm/i915: Setup PPS in intel_panel X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" X-Spam-Status: No, score=-5.6 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 Moving intel_dp_setup_panel_power_sequencer code to intel_panel.c to make PPS code generic in future patches. This patches substitutes references to intel_dp_setup_panel_power_sequencer with a new function in intel_panel.c. Signed-off-by: Vandana Kannan --- drivers/gpu/drm/i915/intel_dp.c | 121 +++---------------------------------- drivers/gpu/drm/i915/intel_drv.h | 11 ++++ drivers/gpu/drm/i915/intel_panel.c | 103 +++++++++++++++++++++++++++++++ 3 files changed, 124 insertions(+), 111 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 2dfdc26..5b5d90a40 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -282,10 +282,6 @@ intel_hrawclk(struct drm_device *dev) } static void -intel_dp_init_panel_power_sequencer(struct drm_device *dev, - struct intel_dp *intel_dp, - struct edp_power_seq *out); -static void intel_dp_init_panel_power_sequencer_registers(struct drm_device *dev, struct intel_dp *intel_dp, struct edp_power_seq *out); @@ -419,6 +415,7 @@ vlv_initial_power_sequencer_setup(struct intel_dp *intel_dp) struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); struct drm_device *dev = intel_dig_port->base.base.dev; struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_connector *intel_connector = intel_dp->attached_connector; struct edp_power_seq power_seq; enum port port = intel_dig_port->port; @@ -447,7 +444,7 @@ vlv_initial_power_sequencer_setup(struct intel_dp *intel_dp) DRM_DEBUG_KMS("initial power sequencer for port %c: pipe %c\n", port_name(port), pipe_name(intel_dp->pps_pipe)); - intel_dp_init_panel_power_sequencer(dev, intel_dp, &power_seq); + intel_panel_setup_panel_power_sequencer(intel_connector); intel_dp_init_panel_power_sequencer_registers(dev, intel_dp, &power_seq); } @@ -4725,113 +4722,13 @@ static void intel_dp_init_panel_power_timestamps(struct intel_dp *intel_dp) } static void -intel_dp_init_panel_power_sequencer(struct drm_device *dev, - struct intel_dp *intel_dp, - struct edp_power_seq *out) -{ - struct drm_i915_private *dev_priv = dev->dev_private; - struct edp_power_seq cur, vbt, spec, final; - u32 pp_on, pp_off, pp_div, pp; - int pp_ctrl_reg, pp_on_reg, pp_off_reg, pp_div_reg; - - lockdep_assert_held(&dev_priv->pps_mutex); - - if (HAS_PCH_SPLIT(dev)) { - pp_ctrl_reg = PCH_PP_CONTROL; - pp_on_reg = PCH_PP_ON_DELAYS; - pp_off_reg = PCH_PP_OFF_DELAYS; - pp_div_reg = PCH_PP_DIVISOR; - } else { - enum pipe pipe = vlv_power_sequencer_pipe(intel_dp); - - pp_ctrl_reg = VLV_PIPE_PP_CONTROL(pipe); - pp_on_reg = VLV_PIPE_PP_ON_DELAYS(pipe); - pp_off_reg = VLV_PIPE_PP_OFF_DELAYS(pipe); - pp_div_reg = VLV_PIPE_PP_DIVISOR(pipe); - } - - /* Workaround: Need to write PP_CONTROL with the unlock key as - * the very first thing. */ - pp = ironlake_get_pp_control(intel_dp); - I915_WRITE(pp_ctrl_reg, pp); - - pp_on = I915_READ(pp_on_reg); - pp_off = I915_READ(pp_off_reg); - pp_div = I915_READ(pp_div_reg); - - /* Pull timing values out of registers */ - cur.t1_t3 = (pp_on & PANEL_POWER_UP_DELAY_MASK) >> - PANEL_POWER_UP_DELAY_SHIFT; - - cur.t8 = (pp_on & PANEL_LIGHT_ON_DELAY_MASK) >> - PANEL_LIGHT_ON_DELAY_SHIFT; - - cur.t9 = (pp_off & PANEL_LIGHT_OFF_DELAY_MASK) >> - PANEL_LIGHT_OFF_DELAY_SHIFT; - - cur.t10 = (pp_off & PANEL_POWER_DOWN_DELAY_MASK) >> - PANEL_POWER_DOWN_DELAY_SHIFT; - - cur.t11_t12 = ((pp_div & PANEL_POWER_CYCLE_DELAY_MASK) >> - PANEL_POWER_CYCLE_DELAY_SHIFT) * 1000; - - DRM_DEBUG_KMS("cur t1_t3 %d t8 %d t9 %d t10 %d t11_t12 %d\n", - cur.t1_t3, cur.t8, cur.t9, cur.t10, cur.t11_t12); - - vbt = dev_priv->vbt.edp_pps; - - /* Upper limits from eDP 1.3 spec. Note that we use the clunky units of - * our hw here, which are all in 100usec. */ - spec.t1_t3 = 210 * 10; - spec.t8 = 50 * 10; /* no limit for t8, use t7 instead */ - spec.t9 = 50 * 10; /* no limit for t9, make it symmetric with t8 */ - spec.t10 = 500 * 10; - /* This one is special and actually in units of 100ms, but zero - * based in the hw (so we need to add 100 ms). But the sw vbt - * table multiplies it with 1000 to make it in units of 100usec, - * too. */ - spec.t11_t12 = (510 + 100) * 10; - - DRM_DEBUG_KMS("vbt t1_t3 %d t8 %d t9 %d t10 %d t11_t12 %d\n", - vbt.t1_t3, vbt.t8, vbt.t9, vbt.t10, vbt.t11_t12); - - /* Use the max of the register settings and vbt. If both are - * unset, fall back to the spec limits. */ -#define assign_final(field) final.field = (max(cur.field, vbt.field) == 0 ? \ - spec.field : \ - max(cur.field, vbt.field)) - assign_final(t1_t3); - assign_final(t8); - assign_final(t9); - assign_final(t10); - assign_final(t11_t12); -#undef assign_final - -#define get_delay(field) (DIV_ROUND_UP(final.field, 10)) - intel_dp->panel_power_up_delay = get_delay(t1_t3); - intel_dp->backlight_on_delay = get_delay(t8); - intel_dp->backlight_off_delay = get_delay(t9); - intel_dp->panel_power_down_delay = get_delay(t10); - intel_dp->panel_power_cycle_delay = get_delay(t11_t12); -#undef get_delay - - DRM_DEBUG_KMS("panel power up delay %d, power down delay %d, power cycle delay %d\n", - intel_dp->panel_power_up_delay, intel_dp->panel_power_down_delay, - intel_dp->panel_power_cycle_delay); - - DRM_DEBUG_KMS("backlight on delay %d, off delay %d\n", - intel_dp->backlight_on_delay, intel_dp->backlight_off_delay); - - if (out) - *out = final; -} - -static void intel_dp_init_panel_power_sequencer_registers(struct drm_device *dev, struct intel_dp *intel_dp, struct edp_power_seq *seq) { struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_connector *intel_connector = intel_dp->attached_connector; + struct intel_panel *panel = &intel_connector->panel; u32 pp_on, pp_off, pp_div, port_sel = 0; int div = HAS_PCH_SPLIT(dev) ? intel_pch_rawclk(dev) : intel_hrawclk(dev); int pp_on_reg, pp_off_reg, pp_div_reg; @@ -4859,14 +4756,16 @@ intel_dp_init_panel_power_sequencer_registers(struct drm_device *dev, * do the manual sleep, and once when we disable the panel and wait for * the PP_STATUS bit to become zero. */ - pp_on = (seq->t1_t3 << PANEL_POWER_UP_DELAY_SHIFT) | + pp_on = (panel->pps.panel_power_up_delay << + PANEL_POWER_UP_DELAY_SHIFT) | (1 << PANEL_LIGHT_ON_DELAY_SHIFT); pp_off = (1 << PANEL_LIGHT_OFF_DELAY_SHIFT) | - (seq->t10 << PANEL_POWER_DOWN_DELAY_SHIFT); + (panel->pps.panel_power_down_delay << + PANEL_POWER_DOWN_DELAY_SHIFT); /* Compute the divisor for the pp clock, simply match the Bspec * formula. */ pp_div = ((100 * div)/2 - 1) << PP_REFERENCE_DIVIDER_SHIFT; - pp_div |= (DIV_ROUND_UP(seq->t11_t12, 1000) + pp_div |= (DIV_ROUND_UP(panel->pps.panel_power_cycle_delay, 1000) << PANEL_POWER_CYCLE_DELAY_SHIFT); /* Haswell doesn't have any port selection bits for the panel @@ -5095,7 +4994,7 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp, if (IS_VALLEYVIEW(dev)) vlv_initial_power_sequencer_setup(intel_dp); intel_dp_init_panel_power_timestamps(intel_dp); - intel_dp_init_panel_power_sequencer(dev, intel_dp, power_seq); + intel_panel_setup_panel_power_sequencer(intel_connector); intel_dp_init_panel_power_sequencer_registers(dev, intel_dp, power_seq); pps_unlock(intel_dp); diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index abe2b00..76fa3b3 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -186,6 +186,15 @@ struct intel_panel { } backlight; void (*backlight_power)(struct intel_connector *, bool enable); + + /* PPS */ + struct { + int panel_power_up_delay; + int panel_power_down_delay; + int panel_power_cycle_delay; + int backlight_on_delay; + int backlight_off_delay; + } pps; }; struct intel_connector { @@ -1090,6 +1099,8 @@ extern struct drm_display_mode *intel_find_panel_downclock( struct drm_device *dev, struct drm_display_mode *fixed_mode, struct drm_connector *connector); +void intel_panel_setup_panel_power_sequencer( + struct intel_connector *connector); /* intel_runtime_pm.c */ int intel_power_domains_init(struct drm_i915_private *); diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c index d48d1bc..c213ae3 100644 --- a/drivers/gpu/drm/i915/intel_panel.c +++ b/drivers/gpu/drm/i915/intel_panel.c @@ -1346,6 +1346,109 @@ void intel_panel_init_backlight_funcs(struct drm_device *dev) } } +void +intel_panel_setup_panel_power_sequencer(struct intel_connector *connector) +{ + struct intel_panel *panel = &connector->panel; + struct drm_device *dev = connector->base.dev; + struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_encoder *encoder = connector->base.encoder; + struct intel_digital_port *intel_dig_port = enc_to_dig_port(encoder); + struct edp_power_seq cur, vbt, spec, final; + u32 pp_on, pp_off, pp_div, pp; + int pp_ctrl_reg, pp_on_reg, pp_off_reg, pp_div_reg; + + lockdep_assert_held(&dev_priv->pps_mutex); + + if (HAS_PCH_SPLIT(dev)) { + pp_ctrl_reg = PCH_PP_CONTROL; + pp_on_reg = PCH_PP_ON_DELAYS; + pp_off_reg = PCH_PP_OFF_DELAYS; + pp_div_reg = PCH_PP_DIVISOR; + } else { + enum pipe pipe = vlv_power_sequencer_pipe(&intel_dig_port->dp); + + pp_ctrl_reg = VLV_PIPE_PP_CONTROL(pipe); + pp_on_reg = VLV_PIPE_PP_ON_DELAYS(pipe); + pp_off_reg = VLV_PIPE_PP_OFF_DELAYS(pipe); + pp_div_reg = VLV_PIPE_PP_DIVISOR(pipe); + } + + /* Workaround: Need to write PP_CONTROL with the unlock key as + * the very first thing. */ + pp = ironlake_get_pp_control(&intel_dig_port->dp); + I915_WRITE(pp_ctrl_reg, pp); + + pp_on = I915_READ(pp_on_reg); + pp_off = I915_READ(pp_off_reg); + pp_div = I915_READ(pp_div_reg); + + /* Pull timing values out of registers */ + cur.t1_t3 = (pp_on & PANEL_POWER_UP_DELAY_MASK) >> + PANEL_POWER_UP_DELAY_SHIFT; + + cur.t8 = (pp_on & PANEL_LIGHT_ON_DELAY_MASK) >> + PANEL_LIGHT_ON_DELAY_SHIFT; + + cur.t9 = (pp_off & PANEL_LIGHT_OFF_DELAY_MASK) >> + PANEL_LIGHT_OFF_DELAY_SHIFT; + + cur.t10 = (pp_off & PANEL_POWER_DOWN_DELAY_MASK) >> + PANEL_POWER_DOWN_DELAY_SHIFT; + + cur.t11_t12 = ((pp_div & PANEL_POWER_CYCLE_DELAY_MASK) >> + PANEL_POWER_CYCLE_DELAY_SHIFT) * 1000; + + DRM_DEBUG_KMS("cur t1_t3 %d t8 %d t9 %d t10 %d t11_t12 %d\n", + cur.t1_t3, cur.t8, cur.t9, cur.t10, cur.t11_t12); + + vbt = dev_priv->vbt.edp_pps; + + /* Upper limits from eDP 1.3 spec. Note that we use the clunky units of + * our hw here, which are all in 100usec. */ + spec.t1_t3 = 210 * 10; + spec.t8 = 50 * 10; /* no limit for t8, use t7 instead */ + spec.t9 = 50 * 10; /* no limit for t9, make it symmetric with t8 */ + spec.t10 = 500 * 10; + /* This one is special and actually in units of 100ms, but zero + * based in the hw (so we need to add 100 ms). But the sw vbt + * table multiplies it with 1000 to make it in units of 100usec, + * too. */ + spec.t11_t12 = (510 + 100) * 10; + + DRM_DEBUG_KMS("vbt t1_t3 %d t8 %d t9 %d t10 %d t11_t12 %d\n", + vbt.t1_t3, vbt.t8, vbt.t9, vbt.t10, vbt.t11_t12); + + /* Use the max of the register settings and vbt. If both are + * unset, fall back to the spec limits. */ +#define assign_final(field) final.field = (max(cur.field, vbt.field) == 0 ? \ + spec.field : \ + max(cur.field, vbt.field)) + assign_final(t1_t3); + assign_final(t8); + assign_final(t9); + assign_final(t10); + assign_final(t11_t12); +#undef assign_final + +#define get_delay(field) (DIV_ROUND_UP(final.field, 10)) + panel->pps.panel_power_up_delay = get_delay(t1_t3); + panel->pps.backlight_on_delay = get_delay(t8); + panel->pps.backlight_off_delay = get_delay(t9); + panel->pps.panel_power_down_delay = get_delay(t10); + panel->pps.panel_power_cycle_delay = get_delay(t11_t12); +#undef get_delay + + DRM_DEBUG_KMS("panel power up delay %d, power down delay %d, power cycle delay %d\n", + panel->pps.panel_power_up_delay, + panel->pps.panel_power_down_delay, + panel->pps.panel_power_cycle_delay); + + DRM_DEBUG_KMS("backlight on delay %d, off delay %d\n", + panel->pps.backlight_on_delay, + panel->pps.backlight_off_delay); +} + int intel_panel_init(struct intel_panel *panel, struct drm_display_mode *fixed_mode, struct drm_display_mode *downclock_mode)