|
|
@@ -37,6 +37,7 @@
|
|
|
#include "intel_frontbuffer.h"
|
|
|
#include <drm/i915_drm.h>
|
|
|
#include "i915_drv.h"
|
|
|
+#include "i915_gem_clflush.h"
|
|
|
#include "intel_dsi.h"
|
|
|
#include "i915_trace.h"
|
|
|
#include <drm/drm_atomic.h>
|
|
|
@@ -96,10 +97,9 @@ static void i9xx_crtc_clock_get(struct intel_crtc *crtc,
|
|
|
static void ironlake_pch_clock_get(struct intel_crtc *crtc,
|
|
|
struct intel_crtc_state *pipe_config);
|
|
|
|
|
|
-static int intel_framebuffer_init(struct drm_device *dev,
|
|
|
- struct intel_framebuffer *ifb,
|
|
|
- struct drm_mode_fb_cmd2 *mode_cmd,
|
|
|
- struct drm_i915_gem_object *obj);
|
|
|
+static int intel_framebuffer_init(struct intel_framebuffer *ifb,
|
|
|
+ struct drm_i915_gem_object *obj,
|
|
|
+ struct drm_mode_fb_cmd2 *mode_cmd);
|
|
|
static void i9xx_set_pipeconf(struct intel_crtc *intel_crtc);
|
|
|
static void intel_set_pipe_timings(struct intel_crtc *intel_crtc);
|
|
|
static void intel_set_pipe_src_size(struct intel_crtc *intel_crtc);
|
|
|
@@ -122,9 +122,6 @@ static void ironlake_pfit_disable(struct intel_crtc *crtc, bool force);
|
|
|
static void ironlake_pfit_enable(struct intel_crtc *crtc);
|
|
|
static void intel_modeset_setup_hw_state(struct drm_device *dev);
|
|
|
static void intel_pre_disable_primary_noatomic(struct drm_crtc *crtc);
|
|
|
-static int ilk_max_pixel_rate(struct drm_atomic_state *state);
|
|
|
-static int glk_calc_cdclk(int max_pixclk);
|
|
|
-static int bxt_calc_cdclk(int max_pixclk);
|
|
|
|
|
|
struct intel_limit {
|
|
|
struct {
|
|
|
@@ -138,7 +135,7 @@ struct intel_limit {
|
|
|
};
|
|
|
|
|
|
/* returns HPLL frequency in kHz */
|
|
|
-static int valleyview_get_vco(struct drm_i915_private *dev_priv)
|
|
|
+int vlv_get_hpll_vco(struct drm_i915_private *dev_priv)
|
|
|
{
|
|
|
int hpll_freq, vco_freq[] = { 800, 1600, 2000, 2400 };
|
|
|
|
|
|
@@ -170,73 +167,16 @@ int vlv_get_cck_clock(struct drm_i915_private *dev_priv,
|
|
|
return DIV_ROUND_CLOSEST(ref_freq << 1, divider + 1);
|
|
|
}
|
|
|
|
|
|
-static int vlv_get_cck_clock_hpll(struct drm_i915_private *dev_priv,
|
|
|
- const char *name, u32 reg)
|
|
|
+int vlv_get_cck_clock_hpll(struct drm_i915_private *dev_priv,
|
|
|
+ const char *name, u32 reg)
|
|
|
{
|
|
|
if (dev_priv->hpll_freq == 0)
|
|
|
- dev_priv->hpll_freq = valleyview_get_vco(dev_priv);
|
|
|
+ dev_priv->hpll_freq = vlv_get_hpll_vco(dev_priv);
|
|
|
|
|
|
return vlv_get_cck_clock(dev_priv, name, reg,
|
|
|
dev_priv->hpll_freq);
|
|
|
}
|
|
|
|
|
|
-static int
|
|
|
-intel_pch_rawclk(struct drm_i915_private *dev_priv)
|
|
|
-{
|
|
|
- return (I915_READ(PCH_RAWCLK_FREQ) & RAWCLK_FREQ_MASK) * 1000;
|
|
|
-}
|
|
|
-
|
|
|
-static int
|
|
|
-intel_vlv_hrawclk(struct drm_i915_private *dev_priv)
|
|
|
-{
|
|
|
- /* RAWCLK_FREQ_VLV register updated from power well code */
|
|
|
- return vlv_get_cck_clock_hpll(dev_priv, "hrawclk",
|
|
|
- CCK_DISPLAY_REF_CLOCK_CONTROL);
|
|
|
-}
|
|
|
-
|
|
|
-static int
|
|
|
-intel_g4x_hrawclk(struct drm_i915_private *dev_priv)
|
|
|
-{
|
|
|
- uint32_t clkcfg;
|
|
|
-
|
|
|
- /* hrawclock is 1/4 the FSB frequency */
|
|
|
- clkcfg = I915_READ(CLKCFG);
|
|
|
- switch (clkcfg & CLKCFG_FSB_MASK) {
|
|
|
- case CLKCFG_FSB_400:
|
|
|
- return 100000;
|
|
|
- case CLKCFG_FSB_533:
|
|
|
- return 133333;
|
|
|
- case CLKCFG_FSB_667:
|
|
|
- return 166667;
|
|
|
- case CLKCFG_FSB_800:
|
|
|
- return 200000;
|
|
|
- case CLKCFG_FSB_1067:
|
|
|
- return 266667;
|
|
|
- case CLKCFG_FSB_1333:
|
|
|
- return 333333;
|
|
|
- /* these two are just a guess; one of them might be right */
|
|
|
- case CLKCFG_FSB_1600:
|
|
|
- case CLKCFG_FSB_1600_ALT:
|
|
|
- return 400000;
|
|
|
- default:
|
|
|
- return 133333;
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-void intel_update_rawclk(struct drm_i915_private *dev_priv)
|
|
|
-{
|
|
|
- if (HAS_PCH_SPLIT(dev_priv))
|
|
|
- dev_priv->rawclk_freq = intel_pch_rawclk(dev_priv);
|
|
|
- else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
|
|
|
- dev_priv->rawclk_freq = intel_vlv_hrawclk(dev_priv);
|
|
|
- else if (IS_G4X(dev_priv) || IS_PINEVIEW(dev_priv))
|
|
|
- dev_priv->rawclk_freq = intel_g4x_hrawclk(dev_priv);
|
|
|
- else
|
|
|
- return; /* no rawclk on other platforms, or no need to know it */
|
|
|
-
|
|
|
- DRM_DEBUG_DRIVER("rawclk rate: %d kHz\n", dev_priv->rawclk_freq);
|
|
|
-}
|
|
|
-
|
|
|
static void intel_update_czclk(struct drm_i915_private *dev_priv)
|
|
|
{
|
|
|
if (!(IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)))
|
|
|
@@ -2112,11 +2052,13 @@ static void intel_tile_dims(const struct drm_i915_private *dev_priv,
|
|
|
}
|
|
|
|
|
|
unsigned int
|
|
|
-intel_fb_align_height(struct drm_device *dev, unsigned int height,
|
|
|
- uint32_t pixel_format, uint64_t fb_modifier)
|
|
|
+intel_fb_align_height(struct drm_i915_private *dev_priv,
|
|
|
+ unsigned int height,
|
|
|
+ uint32_t pixel_format,
|
|
|
+ uint64_t fb_modifier)
|
|
|
{
|
|
|
unsigned int cpp = drm_format_plane_cpp(pixel_format, 0);
|
|
|
- unsigned int tile_height = intel_tile_height(to_i915(dev), fb_modifier, cpp);
|
|
|
+ unsigned int tile_height = intel_tile_height(dev_priv, fb_modifier, cpp);
|
|
|
|
|
|
return ALIGN(height, tile_height);
|
|
|
}
|
|
|
@@ -2682,15 +2624,13 @@ intel_alloc_initial_plane_obj(struct intel_crtc *crtc,
|
|
|
return false;
|
|
|
|
|
|
mutex_lock(&dev->struct_mutex);
|
|
|
-
|
|
|
obj = i915_gem_object_create_stolen_for_preallocated(dev_priv,
|
|
|
base_aligned,
|
|
|
base_aligned,
|
|
|
size_aligned);
|
|
|
- if (!obj) {
|
|
|
- mutex_unlock(&dev->struct_mutex);
|
|
|
+ mutex_unlock(&dev->struct_mutex);
|
|
|
+ if (!obj)
|
|
|
return false;
|
|
|
- }
|
|
|
|
|
|
if (plane_config->tiling == I915_TILING_X)
|
|
|
obj->tiling_and_stride = fb->pitches[0] | I915_TILING_X;
|
|
|
@@ -2702,20 +2642,17 @@ intel_alloc_initial_plane_obj(struct intel_crtc *crtc,
|
|
|
mode_cmd.modifier[0] = fb->modifier;
|
|
|
mode_cmd.flags = DRM_MODE_FB_MODIFIERS;
|
|
|
|
|
|
- if (intel_framebuffer_init(dev, to_intel_framebuffer(fb),
|
|
|
- &mode_cmd, obj)) {
|
|
|
+ if (intel_framebuffer_init(to_intel_framebuffer(fb), obj, &mode_cmd)) {
|
|
|
DRM_DEBUG_KMS("intel fb init failed\n");
|
|
|
goto out_unref_obj;
|
|
|
}
|
|
|
|
|
|
- mutex_unlock(&dev->struct_mutex);
|
|
|
|
|
|
DRM_DEBUG_KMS("initial plane fb obj %p\n", obj);
|
|
|
return true;
|
|
|
|
|
|
out_unref_obj:
|
|
|
i915_gem_object_put(obj);
|
|
|
- mutex_unlock(&dev->struct_mutex);
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
@@ -2733,6 +2670,29 @@ update_state_fb(struct drm_plane *plane)
|
|
|
drm_framebuffer_reference(plane->state->fb);
|
|
|
}
|
|
|
|
|
|
+static void
|
|
|
+intel_set_plane_visible(struct intel_crtc_state *crtc_state,
|
|
|
+ struct intel_plane_state *plane_state,
|
|
|
+ bool visible)
|
|
|
+{
|
|
|
+ struct intel_plane *plane = to_intel_plane(plane_state->base.plane);
|
|
|
+
|
|
|
+ plane_state->base.visible = visible;
|
|
|
+
|
|
|
+ /* FIXME pre-g4x don't work like this */
|
|
|
+ if (visible) {
|
|
|
+ crtc_state->base.plane_mask |= BIT(drm_plane_index(&plane->base));
|
|
|
+ crtc_state->active_planes |= BIT(plane->id);
|
|
|
+ } else {
|
|
|
+ crtc_state->base.plane_mask &= ~BIT(drm_plane_index(&plane->base));
|
|
|
+ crtc_state->active_planes &= ~BIT(plane->id);
|
|
|
+ }
|
|
|
+
|
|
|
+ DRM_DEBUG_KMS("%s active planes 0x%x\n",
|
|
|
+ crtc_state->base.crtc->name,
|
|
|
+ crtc_state->active_planes);
|
|
|
+}
|
|
|
+
|
|
|
static void
|
|
|
intel_find_initial_plane_obj(struct intel_crtc *intel_crtc,
|
|
|
struct intel_initial_plane_config *plane_config)
|
|
|
@@ -2790,9 +2750,11 @@ intel_find_initial_plane_obj(struct intel_crtc *intel_crtc,
|
|
|
* simplest solution is to just disable the primary plane now and
|
|
|
* pretend the BIOS never had it enabled.
|
|
|
*/
|
|
|
- plane_state->visible = false;
|
|
|
- crtc_state->plane_mask &= ~(1 << drm_plane_index(primary));
|
|
|
+ intel_set_plane_visible(to_intel_crtc_state(crtc_state),
|
|
|
+ to_intel_plane_state(plane_state),
|
|
|
+ false);
|
|
|
intel_pre_disable_primary_noatomic(&intel_crtc->base);
|
|
|
+ trace_intel_disable_plane(primary, intel_crtc);
|
|
|
intel_plane->disable_plane(primary, &intel_crtc->base);
|
|
|
|
|
|
return;
|
|
|
@@ -2831,7 +2793,11 @@ valid_fb:
|
|
|
drm_framebuffer_reference(fb);
|
|
|
primary->fb = primary->state->fb = fb;
|
|
|
primary->crtc = primary->state->crtc = &intel_crtc->base;
|
|
|
- intel_crtc->base.state->plane_mask |= (1 << drm_plane_index(primary));
|
|
|
+
|
|
|
+ intel_set_plane_visible(to_intel_crtc_state(crtc_state),
|
|
|
+ to_intel_plane_state(plane_state),
|
|
|
+ true);
|
|
|
+
|
|
|
atomic_or(to_intel_plane(primary)->frontbuffer_bit,
|
|
|
&obj->frontbuffer_bits);
|
|
|
}
|
|
|
@@ -3386,13 +3352,22 @@ static void skylake_update_primary_plane(struct drm_plane *plane,
|
|
|
int dst_w = drm_rect_width(&plane_state->base.dst);
|
|
|
int dst_h = drm_rect_height(&plane_state->base.dst);
|
|
|
|
|
|
- plane_ctl = PLANE_CTL_ENABLE |
|
|
|
- PLANE_CTL_PIPE_GAMMA_ENABLE |
|
|
|
- PLANE_CTL_PIPE_CSC_ENABLE;
|
|
|
+ plane_ctl = PLANE_CTL_ENABLE;
|
|
|
+
|
|
|
+ if (IS_GEMINILAKE(dev_priv)) {
|
|
|
+ I915_WRITE(PLANE_COLOR_CTL(pipe, plane_id),
|
|
|
+ PLANE_COLOR_PIPE_GAMMA_ENABLE |
|
|
|
+ PLANE_COLOR_PIPE_CSC_ENABLE |
|
|
|
+ PLANE_COLOR_PLANE_GAMMA_DISABLE);
|
|
|
+ } else {
|
|
|
+ plane_ctl |=
|
|
|
+ PLANE_CTL_PIPE_GAMMA_ENABLE |
|
|
|
+ PLANE_CTL_PIPE_CSC_ENABLE |
|
|
|
+ PLANE_CTL_PLANE_GAMMA_DISABLE;
|
|
|
+ }
|
|
|
|
|
|
plane_ctl |= skl_plane_ctl_format(fb->format->format);
|
|
|
plane_ctl |= skl_plane_ctl_tiling(fb->modifier);
|
|
|
- plane_ctl |= PLANE_CTL_PLANE_GAMMA_DISABLE;
|
|
|
plane_ctl |= skl_plane_ctl_rotation(rotation);
|
|
|
|
|
|
/* Sizes are 0 based */
|
|
|
@@ -3473,10 +3448,14 @@ static void intel_update_primary_planes(struct drm_device *dev)
|
|
|
struct intel_plane_state *plane_state =
|
|
|
to_intel_plane_state(plane->base.state);
|
|
|
|
|
|
- if (plane_state->base.visible)
|
|
|
+ if (plane_state->base.visible) {
|
|
|
+ trace_intel_update_plane(&plane->base,
|
|
|
+ to_intel_crtc(crtc));
|
|
|
+
|
|
|
plane->update_plane(&plane->base,
|
|
|
to_intel_crtc_state(crtc->state),
|
|
|
plane_state);
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -3505,7 +3484,8 @@ __intel_display_resume(struct drm_device *dev,
|
|
|
}
|
|
|
|
|
|
/* ignore any reset values/BIOS leftovers in the WM registers */
|
|
|
- to_intel_atomic_state(state)->skip_intermediate_wm = true;
|
|
|
+ if (!HAS_GMCH_DISPLAY(to_i915(dev)))
|
|
|
+ to_intel_atomic_state(state)->skip_intermediate_wm = true;
|
|
|
|
|
|
ret = drm_atomic_helper_commit_duplicated_state(state, ctx);
|
|
|
|
|
|
@@ -3701,12 +3681,11 @@ static void intel_update_pipe_config(struct intel_crtc *crtc,
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-static void intel_fdi_normal_train(struct drm_crtc *crtc)
|
|
|
+static void intel_fdi_normal_train(struct intel_crtc *crtc)
|
|
|
{
|
|
|
- struct drm_device *dev = crtc->dev;
|
|
|
+ struct drm_device *dev = crtc->base.dev;
|
|
|
struct drm_i915_private *dev_priv = to_i915(dev);
|
|
|
- struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
|
|
- int pipe = intel_crtc->pipe;
|
|
|
+ int pipe = crtc->pipe;
|
|
|
i915_reg_t reg;
|
|
|
u32 temp;
|
|
|
|
|
|
@@ -3744,12 +3723,12 @@ static void intel_fdi_normal_train(struct drm_crtc *crtc)
|
|
|
}
|
|
|
|
|
|
/* The FDI link training functions for ILK/Ibexpeak. */
|
|
|
-static void ironlake_fdi_link_train(struct drm_crtc *crtc)
|
|
|
+static void ironlake_fdi_link_train(struct intel_crtc *crtc,
|
|
|
+ const struct intel_crtc_state *crtc_state)
|
|
|
{
|
|
|
- struct drm_device *dev = crtc->dev;
|
|
|
+ struct drm_device *dev = crtc->base.dev;
|
|
|
struct drm_i915_private *dev_priv = to_i915(dev);
|
|
|
- struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
|
|
- int pipe = intel_crtc->pipe;
|
|
|
+ int pipe = crtc->pipe;
|
|
|
i915_reg_t reg;
|
|
|
u32 temp, tries;
|
|
|
|
|
|
@@ -3770,7 +3749,7 @@ static void ironlake_fdi_link_train(struct drm_crtc *crtc)
|
|
|
reg = FDI_TX_CTL(pipe);
|
|
|
temp = I915_READ(reg);
|
|
|
temp &= ~FDI_DP_PORT_WIDTH_MASK;
|
|
|
- temp |= FDI_DP_PORT_WIDTH(intel_crtc->config->fdi_lanes);
|
|
|
+ temp |= FDI_DP_PORT_WIDTH(crtc_state->fdi_lanes);
|
|
|
temp &= ~FDI_LINK_TRAIN_NONE;
|
|
|
temp |= FDI_LINK_TRAIN_PATTERN_1;
|
|
|
I915_WRITE(reg, temp | FDI_TX_ENABLE);
|
|
|
@@ -3845,12 +3824,12 @@ static const int snb_b_fdi_train_param[] = {
|
|
|
};
|
|
|
|
|
|
/* The FDI link training functions for SNB/Cougarpoint. */
|
|
|
-static void gen6_fdi_link_train(struct drm_crtc *crtc)
|
|
|
+static void gen6_fdi_link_train(struct intel_crtc *crtc,
|
|
|
+ const struct intel_crtc_state *crtc_state)
|
|
|
{
|
|
|
- struct drm_device *dev = crtc->dev;
|
|
|
+ struct drm_device *dev = crtc->base.dev;
|
|
|
struct drm_i915_private *dev_priv = to_i915(dev);
|
|
|
- struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
|
|
- int pipe = intel_crtc->pipe;
|
|
|
+ int pipe = crtc->pipe;
|
|
|
i915_reg_t reg;
|
|
|
u32 temp, i, retry;
|
|
|
|
|
|
@@ -3869,7 +3848,7 @@ static void gen6_fdi_link_train(struct drm_crtc *crtc)
|
|
|
reg = FDI_TX_CTL(pipe);
|
|
|
temp = I915_READ(reg);
|
|
|
temp &= ~FDI_DP_PORT_WIDTH_MASK;
|
|
|
- temp |= FDI_DP_PORT_WIDTH(intel_crtc->config->fdi_lanes);
|
|
|
+ temp |= FDI_DP_PORT_WIDTH(crtc_state->fdi_lanes);
|
|
|
temp &= ~FDI_LINK_TRAIN_NONE;
|
|
|
temp |= FDI_LINK_TRAIN_PATTERN_1;
|
|
|
temp &= ~FDI_LINK_TRAIN_VOL_EMP_MASK;
|
|
|
@@ -3978,12 +3957,12 @@ static void gen6_fdi_link_train(struct drm_crtc *crtc)
|
|
|
}
|
|
|
|
|
|
/* Manual link training for Ivy Bridge A0 parts */
|
|
|
-static void ivb_manual_fdi_link_train(struct drm_crtc *crtc)
|
|
|
+static void ivb_manual_fdi_link_train(struct intel_crtc *crtc,
|
|
|
+ const struct intel_crtc_state *crtc_state)
|
|
|
{
|
|
|
- struct drm_device *dev = crtc->dev;
|
|
|
+ struct drm_device *dev = crtc->base.dev;
|
|
|
struct drm_i915_private *dev_priv = to_i915(dev);
|
|
|
- struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
|
|
- int pipe = intel_crtc->pipe;
|
|
|
+ int pipe = crtc->pipe;
|
|
|
i915_reg_t reg;
|
|
|
u32 temp, i, j;
|
|
|
|
|
|
@@ -4021,7 +4000,7 @@ static void ivb_manual_fdi_link_train(struct drm_crtc *crtc)
|
|
|
reg = FDI_TX_CTL(pipe);
|
|
|
temp = I915_READ(reg);
|
|
|
temp &= ~FDI_DP_PORT_WIDTH_MASK;
|
|
|
- temp |= FDI_DP_PORT_WIDTH(intel_crtc->config->fdi_lanes);
|
|
|
+ temp |= FDI_DP_PORT_WIDTH(crtc_state->fdi_lanes);
|
|
|
temp |= FDI_LINK_TRAIN_PATTERN_1_IVB;
|
|
|
temp &= ~FDI_LINK_TRAIN_VOL_EMP_MASK;
|
|
|
temp |= snb_b_fdi_train_param[j/2];
|
|
|
@@ -4308,10 +4287,10 @@ void lpt_disable_iclkip(struct drm_i915_private *dev_priv)
|
|
|
}
|
|
|
|
|
|
/* Program iCLKIP clock to the desired frequency */
|
|
|
-static void lpt_program_iclkip(struct drm_crtc *crtc)
|
|
|
+static void lpt_program_iclkip(struct intel_crtc *crtc)
|
|
|
{
|
|
|
- struct drm_i915_private *dev_priv = to_i915(crtc->dev);
|
|
|
- int clock = to_intel_crtc(crtc)->config->base.adjusted_mode.crtc_clock;
|
|
|
+ struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
|
|
|
+ int clock = crtc->config->base.adjusted_mode.crtc_clock;
|
|
|
u32 divsel, phaseinc, auxdiv, phasedir = 0;
|
|
|
u32 temp;
|
|
|
|
|
|
@@ -4492,12 +4471,12 @@ static void ivybridge_update_fdi_bc_bifurcation(struct intel_crtc *intel_crtc)
|
|
|
|
|
|
/* Return which DP Port should be selected for Transcoder DP control */
|
|
|
static enum port
|
|
|
-intel_trans_dp_port_sel(struct drm_crtc *crtc)
|
|
|
+intel_trans_dp_port_sel(struct intel_crtc *crtc)
|
|
|
{
|
|
|
- struct drm_device *dev = crtc->dev;
|
|
|
+ struct drm_device *dev = crtc->base.dev;
|
|
|
struct intel_encoder *encoder;
|
|
|
|
|
|
- for_each_encoder_on_crtc(dev, crtc, encoder) {
|
|
|
+ for_each_encoder_on_crtc(dev, &crtc->base, encoder) {
|
|
|
if (encoder->type == INTEL_OUTPUT_DP ||
|
|
|
encoder->type == INTEL_OUTPUT_EDP)
|
|
|
return enc_to_dig_port(&encoder->base)->port;
|
|
|
@@ -4514,18 +4493,18 @@ intel_trans_dp_port_sel(struct drm_crtc *crtc)
|
|
|
* - DP transcoding bits
|
|
|
* - transcoder
|
|
|
*/
|
|
|
-static void ironlake_pch_enable(struct drm_crtc *crtc)
|
|
|
+static void ironlake_pch_enable(const struct intel_crtc_state *crtc_state)
|
|
|
{
|
|
|
- struct drm_device *dev = crtc->dev;
|
|
|
+ struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
|
|
|
+ struct drm_device *dev = crtc->base.dev;
|
|
|
struct drm_i915_private *dev_priv = to_i915(dev);
|
|
|
- struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
|
|
- int pipe = intel_crtc->pipe;
|
|
|
+ int pipe = crtc->pipe;
|
|
|
u32 temp;
|
|
|
|
|
|
assert_pch_transcoder_disabled(dev_priv, pipe);
|
|
|
|
|
|
if (IS_IVYBRIDGE(dev_priv))
|
|
|
- ivybridge_update_fdi_bc_bifurcation(intel_crtc);
|
|
|
+ ivybridge_update_fdi_bc_bifurcation(crtc);
|
|
|
|
|
|
/* Write the TU size bits before fdi link training, so that error
|
|
|
* detection works. */
|
|
|
@@ -4533,7 +4512,7 @@ static void ironlake_pch_enable(struct drm_crtc *crtc)
|
|
|
I915_READ(PIPE_DATA_M1(pipe)) & TU_SIZE_MASK);
|
|
|
|
|
|
/* For PCH output, training FDI link */
|
|
|
- dev_priv->display.fdi_link_train(crtc);
|
|
|
+ dev_priv->display.fdi_link_train(crtc, crtc_state);
|
|
|
|
|
|
/* We need to program the right clock selection before writing the pixel
|
|
|
* mutliplier into the DPLL. */
|
|
|
@@ -4543,7 +4522,7 @@ static void ironlake_pch_enable(struct drm_crtc *crtc)
|
|
|
temp = I915_READ(PCH_DPLL_SEL);
|
|
|
temp |= TRANS_DPLL_ENABLE(pipe);
|
|
|
sel = TRANS_DPLLB_SEL(pipe);
|
|
|
- if (intel_crtc->config->shared_dpll ==
|
|
|
+ if (crtc_state->shared_dpll ==
|
|
|
intel_get_shared_dpll_by_id(dev_priv, DPLL_ID_PCH_PLL_B))
|
|
|
temp |= sel;
|
|
|
else
|
|
|
@@ -4558,19 +4537,19 @@ static void ironlake_pch_enable(struct drm_crtc *crtc)
|
|
|
* Note that enable_shared_dpll tries to do the right thing, but
|
|
|
* get_shared_dpll unconditionally resets the pll - we need that to have
|
|
|
* the right LVDS enable sequence. */
|
|
|
- intel_enable_shared_dpll(intel_crtc);
|
|
|
+ intel_enable_shared_dpll(crtc);
|
|
|
|
|
|
/* set transcoder timing, panel must allow it */
|
|
|
assert_panel_unlocked(dev_priv, pipe);
|
|
|
- ironlake_pch_transcoder_set_timings(intel_crtc, pipe);
|
|
|
+ ironlake_pch_transcoder_set_timings(crtc, pipe);
|
|
|
|
|
|
intel_fdi_normal_train(crtc);
|
|
|
|
|
|
/* For PCH DP, enable TRANS_DP_CTL */
|
|
|
if (HAS_PCH_CPT(dev_priv) &&
|
|
|
- intel_crtc_has_dp_encoder(intel_crtc->config)) {
|
|
|
+ intel_crtc_has_dp_encoder(crtc_state)) {
|
|
|
const struct drm_display_mode *adjusted_mode =
|
|
|
- &intel_crtc->config->base.adjusted_mode;
|
|
|
+ &crtc_state->base.adjusted_mode;
|
|
|
u32 bpc = (I915_READ(PIPECONF(pipe)) & PIPECONF_BPC_MASK) >> 5;
|
|
|
i915_reg_t reg = TRANS_DP_CTL(pipe);
|
|
|
temp = I915_READ(reg);
|
|
|
@@ -4605,19 +4584,18 @@ static void ironlake_pch_enable(struct drm_crtc *crtc)
|
|
|
ironlake_enable_pch_transcoder(dev_priv, pipe);
|
|
|
}
|
|
|
|
|
|
-static void lpt_pch_enable(struct drm_crtc *crtc)
|
|
|
+static void lpt_pch_enable(const struct intel_crtc_state *crtc_state)
|
|
|
{
|
|
|
- struct drm_device *dev = crtc->dev;
|
|
|
- struct drm_i915_private *dev_priv = to_i915(dev);
|
|
|
- struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
|
|
- enum transcoder cpu_transcoder = intel_crtc->config->cpu_transcoder;
|
|
|
+ struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
|
|
|
+ struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
|
|
|
+ enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
|
|
|
|
|
|
assert_pch_transcoder_disabled(dev_priv, TRANSCODER_A);
|
|
|
|
|
|
lpt_program_iclkip(crtc);
|
|
|
|
|
|
/* Set transcoder timing. */
|
|
|
- ironlake_pch_transcoder_set_timings(intel_crtc, PIPE_A);
|
|
|
+ ironlake_pch_transcoder_set_timings(crtc, PIPE_A);
|
|
|
|
|
|
lpt_enable_pch_transcoder(dev_priv, cpu_transcoder);
|
|
|
}
|
|
|
@@ -5026,8 +5004,6 @@ static void intel_post_plane_update(struct intel_crtc_state *old_crtc_state)
|
|
|
|
|
|
intel_frontbuffer_flip(to_i915(crtc->base.dev), pipe_config->fb_bits);
|
|
|
|
|
|
- crtc->wm.cxsr_allowed = true;
|
|
|
-
|
|
|
if (pipe_config->update_wm_post && pipe_config->base.active)
|
|
|
intel_update_watermarks(crtc);
|
|
|
|
|
|
@@ -5074,22 +5050,18 @@ static void intel_pre_plane_update(struct intel_crtc_state *old_crtc_state)
|
|
|
intel_pre_disable_primary(&crtc->base);
|
|
|
}
|
|
|
|
|
|
- if (pipe_config->disable_cxsr && HAS_GMCH_DISPLAY(dev_priv)) {
|
|
|
- crtc->wm.cxsr_allowed = false;
|
|
|
-
|
|
|
- /*
|
|
|
- * Vblank time updates from the shadow to live plane control register
|
|
|
- * are blocked if the memory self-refresh mode is active at that
|
|
|
- * moment. So to make sure the plane gets truly disabled, disable
|
|
|
- * first the self-refresh mode. The self-refresh enable bit in turn
|
|
|
- * will be checked/applied by the HW only at the next frame start
|
|
|
- * event which is after the vblank start event, so we need to have a
|
|
|
- * wait-for-vblank between disabling the plane and the pipe.
|
|
|
- */
|
|
|
- if (old_crtc_state->base.active &&
|
|
|
- intel_set_memory_cxsr(dev_priv, false))
|
|
|
- intel_wait_for_vblank(dev_priv, crtc->pipe);
|
|
|
- }
|
|
|
+ /*
|
|
|
+ * Vblank time updates from the shadow to live plane control register
|
|
|
+ * are blocked if the memory self-refresh mode is active at that
|
|
|
+ * moment. So to make sure the plane gets truly disabled, disable
|
|
|
+ * first the self-refresh mode. The self-refresh enable bit in turn
|
|
|
+ * will be checked/applied by the HW only at the next frame start
|
|
|
+ * event which is after the vblank start event, so we need to have a
|
|
|
+ * wait-for-vblank between disabling the plane and the pipe.
|
|
|
+ */
|
|
|
+ if (HAS_GMCH_DISPLAY(dev_priv) && old_crtc_state->base.active &&
|
|
|
+ pipe_config->disable_cxsr && intel_set_memory_cxsr(dev_priv, false))
|
|
|
+ intel_wait_for_vblank(dev_priv, crtc->pipe);
|
|
|
|
|
|
/*
|
|
|
* IVB workaround: must disable low power watermarks for at least
|
|
|
@@ -5344,7 +5316,7 @@ static void ironlake_crtc_enable(struct intel_crtc_state *pipe_config,
|
|
|
intel_enable_pipe(intel_crtc);
|
|
|
|
|
|
if (intel_crtc->config->has_pch_encoder)
|
|
|
- ironlake_pch_enable(crtc);
|
|
|
+ ironlake_pch_enable(pipe_config);
|
|
|
|
|
|
assert_vblank_disabled(crtc);
|
|
|
drm_crtc_vblank_on(crtc);
|
|
|
@@ -5426,10 +5398,10 @@ static void haswell_crtc_enable(struct intel_crtc_state *pipe_config,
|
|
|
intel_encoders_pre_enable(crtc, pipe_config, old_state);
|
|
|
|
|
|
if (intel_crtc->config->has_pch_encoder)
|
|
|
- dev_priv->display.fdi_link_train(crtc);
|
|
|
+ dev_priv->display.fdi_link_train(intel_crtc, pipe_config);
|
|
|
|
|
|
if (!transcoder_is_dsi(cpu_transcoder))
|
|
|
- intel_ddi_enable_pipe_clock(intel_crtc);
|
|
|
+ intel_ddi_enable_pipe_clock(pipe_config);
|
|
|
|
|
|
if (INTEL_GEN(dev_priv) >= 9)
|
|
|
skylake_pfit_enable(intel_crtc);
|
|
|
@@ -5442,9 +5414,9 @@ static void haswell_crtc_enable(struct intel_crtc_state *pipe_config,
|
|
|
*/
|
|
|
intel_color_load_luts(&pipe_config->base);
|
|
|
|
|
|
- intel_ddi_set_pipe_settings(crtc);
|
|
|
+ intel_ddi_set_pipe_settings(pipe_config);
|
|
|
if (!transcoder_is_dsi(cpu_transcoder))
|
|
|
- intel_ddi_enable_transcoder_func(crtc);
|
|
|
+ intel_ddi_enable_transcoder_func(pipe_config);
|
|
|
|
|
|
if (dev_priv->display.initial_watermarks != NULL)
|
|
|
dev_priv->display.initial_watermarks(old_intel_state, pipe_config);
|
|
|
@@ -5454,10 +5426,10 @@ static void haswell_crtc_enable(struct intel_crtc_state *pipe_config,
|
|
|
intel_enable_pipe(intel_crtc);
|
|
|
|
|
|
if (intel_crtc->config->has_pch_encoder)
|
|
|
- lpt_pch_enable(crtc);
|
|
|
+ lpt_pch_enable(pipe_config);
|
|
|
|
|
|
if (intel_crtc_has_type(intel_crtc->config, INTEL_OUTPUT_DP_MST))
|
|
|
- intel_ddi_set_vc_payload_alloc(crtc, true);
|
|
|
+ intel_ddi_set_vc_payload_alloc(pipe_config, true);
|
|
|
|
|
|
assert_vblank_disabled(crtc);
|
|
|
drm_crtc_vblank_on(crtc);
|
|
|
@@ -5579,7 +5551,7 @@ static void haswell_crtc_disable(struct intel_crtc_state *old_crtc_state,
|
|
|
intel_disable_pipe(intel_crtc);
|
|
|
|
|
|
if (intel_crtc_has_type(intel_crtc->config, INTEL_OUTPUT_DP_MST))
|
|
|
- intel_ddi_set_vc_payload_alloc(crtc, false);
|
|
|
+ intel_ddi_set_vc_payload_alloc(intel_crtc->config, false);
|
|
|
|
|
|
if (!transcoder_is_dsi(cpu_transcoder))
|
|
|
intel_ddi_disable_transcoder_func(dev_priv, cpu_transcoder);
|
|
|
@@ -5590,7 +5562,7 @@ static void haswell_crtc_disable(struct intel_crtc_state *old_crtc_state,
|
|
|
ironlake_pfit_disable(intel_crtc, false);
|
|
|
|
|
|
if (!transcoder_is_dsi(cpu_transcoder))
|
|
|
- intel_ddi_disable_pipe_clock(intel_crtc);
|
|
|
+ intel_ddi_disable_pipe_clock(intel_crtc->config);
|
|
|
|
|
|
intel_encoders_post_disable(crtc, old_crtc_state, old_state);
|
|
|
|
|
|
@@ -5623,7 +5595,7 @@ static void i9xx_pfit_enable(struct intel_crtc *crtc)
|
|
|
I915_WRITE(BCLRPAT(crtc->pipe), 0);
|
|
|
}
|
|
|
|
|
|
-static enum intel_display_power_domain port_to_power_domain(enum port port)
|
|
|
+enum intel_display_power_domain intel_port_to_power_domain(enum port port)
|
|
|
{
|
|
|
switch (port) {
|
|
|
case PORT_A:
|
|
|
@@ -5642,91 +5614,15 @@ static enum intel_display_power_domain port_to_power_domain(enum port port)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-static enum intel_display_power_domain port_to_aux_power_domain(enum port port)
|
|
|
-{
|
|
|
- switch (port) {
|
|
|
- case PORT_A:
|
|
|
- return POWER_DOMAIN_AUX_A;
|
|
|
- case PORT_B:
|
|
|
- return POWER_DOMAIN_AUX_B;
|
|
|
- case PORT_C:
|
|
|
- return POWER_DOMAIN_AUX_C;
|
|
|
- case PORT_D:
|
|
|
- return POWER_DOMAIN_AUX_D;
|
|
|
- case PORT_E:
|
|
|
- /* FIXME: Check VBT for actual wiring of PORT E */
|
|
|
- return POWER_DOMAIN_AUX_D;
|
|
|
- default:
|
|
|
- MISSING_CASE(port);
|
|
|
- return POWER_DOMAIN_AUX_A;
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-enum intel_display_power_domain
|
|
|
-intel_display_port_power_domain(struct intel_encoder *intel_encoder)
|
|
|
-{
|
|
|
- struct drm_i915_private *dev_priv = to_i915(intel_encoder->base.dev);
|
|
|
- struct intel_digital_port *intel_dig_port;
|
|
|
-
|
|
|
- switch (intel_encoder->type) {
|
|
|
- case INTEL_OUTPUT_UNKNOWN:
|
|
|
- /* Only DDI platforms should ever use this output type */
|
|
|
- WARN_ON_ONCE(!HAS_DDI(dev_priv));
|
|
|
- case INTEL_OUTPUT_DP:
|
|
|
- case INTEL_OUTPUT_HDMI:
|
|
|
- case INTEL_OUTPUT_EDP:
|
|
|
- intel_dig_port = enc_to_dig_port(&intel_encoder->base);
|
|
|
- return port_to_power_domain(intel_dig_port->port);
|
|
|
- case INTEL_OUTPUT_DP_MST:
|
|
|
- intel_dig_port = enc_to_mst(&intel_encoder->base)->primary;
|
|
|
- return port_to_power_domain(intel_dig_port->port);
|
|
|
- case INTEL_OUTPUT_ANALOG:
|
|
|
- return POWER_DOMAIN_PORT_CRT;
|
|
|
- case INTEL_OUTPUT_DSI:
|
|
|
- return POWER_DOMAIN_PORT_DSI;
|
|
|
- default:
|
|
|
- return POWER_DOMAIN_PORT_OTHER;
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-enum intel_display_power_domain
|
|
|
-intel_display_port_aux_power_domain(struct intel_encoder *intel_encoder)
|
|
|
-{
|
|
|
- struct drm_i915_private *dev_priv = to_i915(intel_encoder->base.dev);
|
|
|
- struct intel_digital_port *intel_dig_port;
|
|
|
-
|
|
|
- switch (intel_encoder->type) {
|
|
|
- case INTEL_OUTPUT_UNKNOWN:
|
|
|
- case INTEL_OUTPUT_HDMI:
|
|
|
- /*
|
|
|
- * Only DDI platforms should ever use these output types.
|
|
|
- * We can get here after the HDMI detect code has already set
|
|
|
- * the type of the shared encoder. Since we can't be sure
|
|
|
- * what's the status of the given connectors, play safe and
|
|
|
- * run the DP detection too.
|
|
|
- */
|
|
|
- WARN_ON_ONCE(!HAS_DDI(dev_priv));
|
|
|
- case INTEL_OUTPUT_DP:
|
|
|
- case INTEL_OUTPUT_EDP:
|
|
|
- intel_dig_port = enc_to_dig_port(&intel_encoder->base);
|
|
|
- return port_to_aux_power_domain(intel_dig_port->port);
|
|
|
- case INTEL_OUTPUT_DP_MST:
|
|
|
- intel_dig_port = enc_to_mst(&intel_encoder->base)->primary;
|
|
|
- return port_to_aux_power_domain(intel_dig_port->port);
|
|
|
- default:
|
|
|
- MISSING_CASE(intel_encoder->type);
|
|
|
- return POWER_DOMAIN_AUX_A;
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-static unsigned long get_crtc_power_domains(struct drm_crtc *crtc,
|
|
|
- struct intel_crtc_state *crtc_state)
|
|
|
+static u64 get_crtc_power_domains(struct drm_crtc *crtc,
|
|
|
+ struct intel_crtc_state *crtc_state)
|
|
|
{
|
|
|
struct drm_device *dev = crtc->dev;
|
|
|
+ struct drm_i915_private *dev_priv = to_i915(dev);
|
|
|
struct drm_encoder *encoder;
|
|
|
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
|
|
enum pipe pipe = intel_crtc->pipe;
|
|
|
- unsigned long mask;
|
|
|
+ u64 mask;
|
|
|
enum transcoder transcoder = crtc_state->cpu_transcoder;
|
|
|
|
|
|
if (!crtc_state->base.active)
|
|
|
@@ -5736,28 +5632,31 @@ static unsigned long get_crtc_power_domains(struct drm_crtc *crtc,
|
|
|
mask |= BIT(POWER_DOMAIN_TRANSCODER(transcoder));
|
|
|
if (crtc_state->pch_pfit.enabled ||
|
|
|
crtc_state->pch_pfit.force_thru)
|
|
|
- mask |= BIT(POWER_DOMAIN_PIPE_PANEL_FITTER(pipe));
|
|
|
+ mask |= BIT_ULL(POWER_DOMAIN_PIPE_PANEL_FITTER(pipe));
|
|
|
|
|
|
drm_for_each_encoder_mask(encoder, dev, crtc_state->base.encoder_mask) {
|
|
|
struct intel_encoder *intel_encoder = to_intel_encoder(encoder);
|
|
|
|
|
|
- mask |= BIT(intel_display_port_power_domain(intel_encoder));
|
|
|
+ mask |= BIT_ULL(intel_encoder->power_domain);
|
|
|
}
|
|
|
|
|
|
+ if (HAS_DDI(dev_priv) && crtc_state->has_audio)
|
|
|
+ mask |= BIT(POWER_DOMAIN_AUDIO);
|
|
|
+
|
|
|
if (crtc_state->shared_dpll)
|
|
|
- mask |= BIT(POWER_DOMAIN_PLLS);
|
|
|
+ mask |= BIT_ULL(POWER_DOMAIN_PLLS);
|
|
|
|
|
|
return mask;
|
|
|
}
|
|
|
|
|
|
-static unsigned long
|
|
|
+static u64
|
|
|
modeset_get_crtc_power_domains(struct drm_crtc *crtc,
|
|
|
struct intel_crtc_state *crtc_state)
|
|
|
{
|
|
|
struct drm_i915_private *dev_priv = to_i915(crtc->dev);
|
|
|
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
|
|
enum intel_display_power_domain domain;
|
|
|
- unsigned long domains, new_domains, old_domains;
|
|
|
+ u64 domains, new_domains, old_domains;
|
|
|
|
|
|
old_domains = intel_crtc->enabled_power_domains;
|
|
|
intel_crtc->enabled_power_domains = new_domains =
|
|
|
@@ -5772,7 +5671,7 @@ modeset_get_crtc_power_domains(struct drm_crtc *crtc,
|
|
|
}
|
|
|
|
|
|
static void modeset_put_power_domains(struct drm_i915_private *dev_priv,
|
|
|
- unsigned long domains)
|
|
|
+ u64 domains)
|
|
|
{
|
|
|
enum intel_display_power_domain domain;
|
|
|
|
|
|
@@ -5780,1032 +5679,122 @@ static void modeset_put_power_domains(struct drm_i915_private *dev_priv,
|
|
|
intel_display_power_put(dev_priv, domain);
|
|
|
}
|
|
|
|
|
|
-static int intel_compute_max_dotclk(struct drm_i915_private *dev_priv)
|
|
|
+static void valleyview_crtc_enable(struct intel_crtc_state *pipe_config,
|
|
|
+ struct drm_atomic_state *old_state)
|
|
|
{
|
|
|
- int max_cdclk_freq = dev_priv->max_cdclk_freq;
|
|
|
+ struct intel_atomic_state *old_intel_state =
|
|
|
+ to_intel_atomic_state(old_state);
|
|
|
+ struct drm_crtc *crtc = pipe_config->base.crtc;
|
|
|
+ struct drm_device *dev = crtc->dev;
|
|
|
+ struct drm_i915_private *dev_priv = to_i915(dev);
|
|
|
+ struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
|
|
+ int pipe = intel_crtc->pipe;
|
|
|
|
|
|
- if (IS_GEMINILAKE(dev_priv))
|
|
|
- return 2 * max_cdclk_freq;
|
|
|
- else if (INTEL_INFO(dev_priv)->gen >= 9 ||
|
|
|
- IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
|
|
|
- return max_cdclk_freq;
|
|
|
- else if (IS_CHERRYVIEW(dev_priv))
|
|
|
- return max_cdclk_freq*95/100;
|
|
|
- else if (INTEL_INFO(dev_priv)->gen < 4)
|
|
|
- return 2*max_cdclk_freq*90/100;
|
|
|
- else
|
|
|
- return max_cdclk_freq*90/100;
|
|
|
-}
|
|
|
+ if (WARN_ON(intel_crtc->active))
|
|
|
+ return;
|
|
|
|
|
|
-static int skl_calc_cdclk(int max_pixclk, int vco);
|
|
|
+ if (intel_crtc_has_dp_encoder(intel_crtc->config))
|
|
|
+ intel_dp_set_m_n(intel_crtc, M1_N1);
|
|
|
|
|
|
-static void intel_update_max_cdclk(struct drm_i915_private *dev_priv)
|
|
|
-{
|
|
|
- if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) {
|
|
|
- u32 limit = I915_READ(SKL_DFSM) & SKL_DFSM_CDCLK_LIMIT_MASK;
|
|
|
- int max_cdclk, vco;
|
|
|
+ intel_set_pipe_timings(intel_crtc);
|
|
|
+ intel_set_pipe_src_size(intel_crtc);
|
|
|
|
|
|
- vco = dev_priv->skl_preferred_vco_freq;
|
|
|
- WARN_ON(vco != 8100000 && vco != 8640000);
|
|
|
+ if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B) {
|
|
|
+ struct drm_i915_private *dev_priv = to_i915(dev);
|
|
|
|
|
|
- /*
|
|
|
- * Use the lower (vco 8640) cdclk values as a
|
|
|
- * first guess. skl_calc_cdclk() will correct it
|
|
|
- * if the preferred vco is 8100 instead.
|
|
|
- */
|
|
|
- if (limit == SKL_DFSM_CDCLK_LIMIT_675)
|
|
|
- max_cdclk = 617143;
|
|
|
- else if (limit == SKL_DFSM_CDCLK_LIMIT_540)
|
|
|
- max_cdclk = 540000;
|
|
|
- else if (limit == SKL_DFSM_CDCLK_LIMIT_450)
|
|
|
- max_cdclk = 432000;
|
|
|
- else
|
|
|
- max_cdclk = 308571;
|
|
|
-
|
|
|
- dev_priv->max_cdclk_freq = skl_calc_cdclk(max_cdclk, vco);
|
|
|
- } else if (IS_GEMINILAKE(dev_priv)) {
|
|
|
- dev_priv->max_cdclk_freq = 316800;
|
|
|
- } else if (IS_BROXTON(dev_priv)) {
|
|
|
- dev_priv->max_cdclk_freq = 624000;
|
|
|
- } else if (IS_BROADWELL(dev_priv)) {
|
|
|
- /*
|
|
|
- * FIXME with extra cooling we can allow
|
|
|
- * 540 MHz for ULX and 675 Mhz for ULT.
|
|
|
- * How can we know if extra cooling is
|
|
|
- * available? PCI ID, VTB, something else?
|
|
|
- */
|
|
|
- if (I915_READ(FUSE_STRAP) & HSW_CDCLK_LIMIT)
|
|
|
- dev_priv->max_cdclk_freq = 450000;
|
|
|
- else if (IS_BDW_ULX(dev_priv))
|
|
|
- dev_priv->max_cdclk_freq = 450000;
|
|
|
- else if (IS_BDW_ULT(dev_priv))
|
|
|
- dev_priv->max_cdclk_freq = 540000;
|
|
|
- else
|
|
|
- dev_priv->max_cdclk_freq = 675000;
|
|
|
- } else if (IS_CHERRYVIEW(dev_priv)) {
|
|
|
- dev_priv->max_cdclk_freq = 320000;
|
|
|
- } else if (IS_VALLEYVIEW(dev_priv)) {
|
|
|
- dev_priv->max_cdclk_freq = 400000;
|
|
|
- } else {
|
|
|
- /* otherwise assume cdclk is fixed */
|
|
|
- dev_priv->max_cdclk_freq = dev_priv->cdclk_freq;
|
|
|
+ I915_WRITE(CHV_BLEND(pipe), CHV_BLEND_LEGACY);
|
|
|
+ I915_WRITE(CHV_CANVAS(pipe), 0);
|
|
|
}
|
|
|
|
|
|
- dev_priv->max_dotclk_freq = intel_compute_max_dotclk(dev_priv);
|
|
|
+ i9xx_set_pipeconf(intel_crtc);
|
|
|
|
|
|
- DRM_DEBUG_DRIVER("Max CD clock rate: %d kHz\n",
|
|
|
- dev_priv->max_cdclk_freq);
|
|
|
+ intel_crtc->active = true;
|
|
|
|
|
|
- DRM_DEBUG_DRIVER("Max dotclock rate: %d kHz\n",
|
|
|
- dev_priv->max_dotclk_freq);
|
|
|
-}
|
|
|
+ intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true);
|
|
|
|
|
|
-static void intel_update_cdclk(struct drm_i915_private *dev_priv)
|
|
|
-{
|
|
|
- dev_priv->cdclk_freq = dev_priv->display.get_display_clock_speed(dev_priv);
|
|
|
+ intel_encoders_pre_pll_enable(crtc, pipe_config, old_state);
|
|
|
|
|
|
- if (INTEL_GEN(dev_priv) >= 9)
|
|
|
- DRM_DEBUG_DRIVER("Current CD clock rate: %d kHz, VCO: %d kHz, ref: %d kHz\n",
|
|
|
- dev_priv->cdclk_freq, dev_priv->cdclk_pll.vco,
|
|
|
- dev_priv->cdclk_pll.ref);
|
|
|
- else
|
|
|
- DRM_DEBUG_DRIVER("Current CD clock rate: %d kHz\n",
|
|
|
- dev_priv->cdclk_freq);
|
|
|
+ if (IS_CHERRYVIEW(dev_priv)) {
|
|
|
+ chv_prepare_pll(intel_crtc, intel_crtc->config);
|
|
|
+ chv_enable_pll(intel_crtc, intel_crtc->config);
|
|
|
+ } else {
|
|
|
+ vlv_prepare_pll(intel_crtc, intel_crtc->config);
|
|
|
+ vlv_enable_pll(intel_crtc, intel_crtc->config);
|
|
|
+ }
|
|
|
|
|
|
- /*
|
|
|
- * 9:0 CMBUS [sic] CDCLK frequency (cdfreq):
|
|
|
- * Programmng [sic] note: bit[9:2] should be programmed to the number
|
|
|
- * of cdclk that generates 4MHz reference clock freq which is used to
|
|
|
- * generate GMBus clock. This will vary with the cdclk freq.
|
|
|
- */
|
|
|
- if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
|
|
|
- I915_WRITE(GMBUSFREQ_VLV, DIV_ROUND_UP(dev_priv->cdclk_freq, 1000));
|
|
|
-}
|
|
|
+ intel_encoders_pre_enable(crtc, pipe_config, old_state);
|
|
|
|
|
|
-/* convert from kHz to .1 fixpoint MHz with -1MHz offset */
|
|
|
-static int skl_cdclk_decimal(int cdclk)
|
|
|
-{
|
|
|
- return DIV_ROUND_CLOSEST(cdclk - 1000, 500);
|
|
|
-}
|
|
|
+ i9xx_pfit_enable(intel_crtc);
|
|
|
|
|
|
-static int bxt_de_pll_vco(struct drm_i915_private *dev_priv, int cdclk)
|
|
|
-{
|
|
|
- int ratio;
|
|
|
+ intel_color_load_luts(&pipe_config->base);
|
|
|
|
|
|
- if (cdclk == dev_priv->cdclk_pll.ref)
|
|
|
- return 0;
|
|
|
+ dev_priv->display.initial_watermarks(old_intel_state,
|
|
|
+ pipe_config);
|
|
|
+ intel_enable_pipe(intel_crtc);
|
|
|
|
|
|
- switch (cdclk) {
|
|
|
- default:
|
|
|
- MISSING_CASE(cdclk);
|
|
|
- case 144000:
|
|
|
- case 288000:
|
|
|
- case 384000:
|
|
|
- case 576000:
|
|
|
- ratio = 60;
|
|
|
- break;
|
|
|
- case 624000:
|
|
|
- ratio = 65;
|
|
|
- break;
|
|
|
- }
|
|
|
+ assert_vblank_disabled(crtc);
|
|
|
+ drm_crtc_vblank_on(crtc);
|
|
|
|
|
|
- return dev_priv->cdclk_pll.ref * ratio;
|
|
|
+ intel_encoders_enable(crtc, pipe_config, old_state);
|
|
|
}
|
|
|
|
|
|
-static int glk_de_pll_vco(struct drm_i915_private *dev_priv, int cdclk)
|
|
|
+static void i9xx_set_pll_dividers(struct intel_crtc *crtc)
|
|
|
{
|
|
|
- int ratio;
|
|
|
-
|
|
|
- if (cdclk == dev_priv->cdclk_pll.ref)
|
|
|
- return 0;
|
|
|
-
|
|
|
- switch (cdclk) {
|
|
|
- default:
|
|
|
- MISSING_CASE(cdclk);
|
|
|
- case 79200:
|
|
|
- case 158400:
|
|
|
- case 316800:
|
|
|
- ratio = 33;
|
|
|
- break;
|
|
|
- }
|
|
|
+ struct drm_device *dev = crtc->base.dev;
|
|
|
+ struct drm_i915_private *dev_priv = to_i915(dev);
|
|
|
|
|
|
- return dev_priv->cdclk_pll.ref * ratio;
|
|
|
+ I915_WRITE(FP0(crtc->pipe), crtc->config->dpll_hw_state.fp0);
|
|
|
+ I915_WRITE(FP1(crtc->pipe), crtc->config->dpll_hw_state.fp1);
|
|
|
}
|
|
|
|
|
|
-static void bxt_de_pll_disable(struct drm_i915_private *dev_priv)
|
|
|
+static void i9xx_crtc_enable(struct intel_crtc_state *pipe_config,
|
|
|
+ struct drm_atomic_state *old_state)
|
|
|
{
|
|
|
- I915_WRITE(BXT_DE_PLL_ENABLE, 0);
|
|
|
+ struct drm_crtc *crtc = pipe_config->base.crtc;
|
|
|
+ struct drm_device *dev = crtc->dev;
|
|
|
+ struct drm_i915_private *dev_priv = to_i915(dev);
|
|
|
+ struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
|
|
+ enum pipe pipe = intel_crtc->pipe;
|
|
|
|
|
|
- /* Timeout 200us */
|
|
|
- if (intel_wait_for_register(dev_priv,
|
|
|
- BXT_DE_PLL_ENABLE, BXT_DE_PLL_LOCK, 0,
|
|
|
- 1))
|
|
|
- DRM_ERROR("timeout waiting for DE PLL unlock\n");
|
|
|
+ if (WARN_ON(intel_crtc->active))
|
|
|
+ return;
|
|
|
|
|
|
- dev_priv->cdclk_pll.vco = 0;
|
|
|
-}
|
|
|
+ i9xx_set_pll_dividers(intel_crtc);
|
|
|
|
|
|
-static void bxt_de_pll_enable(struct drm_i915_private *dev_priv, int vco)
|
|
|
-{
|
|
|
- int ratio = DIV_ROUND_CLOSEST(vco, dev_priv->cdclk_pll.ref);
|
|
|
- u32 val;
|
|
|
+ if (intel_crtc_has_dp_encoder(intel_crtc->config))
|
|
|
+ intel_dp_set_m_n(intel_crtc, M1_N1);
|
|
|
|
|
|
- val = I915_READ(BXT_DE_PLL_CTL);
|
|
|
- val &= ~BXT_DE_PLL_RATIO_MASK;
|
|
|
- val |= BXT_DE_PLL_RATIO(ratio);
|
|
|
- I915_WRITE(BXT_DE_PLL_CTL, val);
|
|
|
+ intel_set_pipe_timings(intel_crtc);
|
|
|
+ intel_set_pipe_src_size(intel_crtc);
|
|
|
|
|
|
- I915_WRITE(BXT_DE_PLL_ENABLE, BXT_DE_PLL_PLL_ENABLE);
|
|
|
+ i9xx_set_pipeconf(intel_crtc);
|
|
|
|
|
|
- /* Timeout 200us */
|
|
|
- if (intel_wait_for_register(dev_priv,
|
|
|
- BXT_DE_PLL_ENABLE,
|
|
|
- BXT_DE_PLL_LOCK,
|
|
|
- BXT_DE_PLL_LOCK,
|
|
|
- 1))
|
|
|
- DRM_ERROR("timeout waiting for DE PLL lock\n");
|
|
|
+ intel_crtc->active = true;
|
|
|
|
|
|
- dev_priv->cdclk_pll.vco = vco;
|
|
|
-}
|
|
|
+ if (!IS_GEN2(dev_priv))
|
|
|
+ intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true);
|
|
|
|
|
|
-static void bxt_set_cdclk(struct drm_i915_private *dev_priv, int cdclk)
|
|
|
-{
|
|
|
- u32 val, divider;
|
|
|
- int vco, ret;
|
|
|
+ intel_encoders_pre_enable(crtc, pipe_config, old_state);
|
|
|
|
|
|
- if (IS_GEMINILAKE(dev_priv))
|
|
|
- vco = glk_de_pll_vco(dev_priv, cdclk);
|
|
|
- else
|
|
|
- vco = bxt_de_pll_vco(dev_priv, cdclk);
|
|
|
+ i9xx_enable_pll(intel_crtc);
|
|
|
|
|
|
- DRM_DEBUG_DRIVER("Changing CDCLK to %d kHz (VCO %d kHz)\n", cdclk, vco);
|
|
|
+ i9xx_pfit_enable(intel_crtc);
|
|
|
|
|
|
- /* cdclk = vco / 2 / div{1,1.5,2,4} */
|
|
|
- switch (DIV_ROUND_CLOSEST(vco, cdclk)) {
|
|
|
- case 8:
|
|
|
- divider = BXT_CDCLK_CD2X_DIV_SEL_4;
|
|
|
- break;
|
|
|
- case 4:
|
|
|
- divider = BXT_CDCLK_CD2X_DIV_SEL_2;
|
|
|
- break;
|
|
|
- case 3:
|
|
|
- WARN(IS_GEMINILAKE(dev_priv), "Unsupported divider\n");
|
|
|
- divider = BXT_CDCLK_CD2X_DIV_SEL_1_5;
|
|
|
- break;
|
|
|
- case 2:
|
|
|
- divider = BXT_CDCLK_CD2X_DIV_SEL_1;
|
|
|
- break;
|
|
|
- default:
|
|
|
- WARN_ON(cdclk != dev_priv->cdclk_pll.ref);
|
|
|
- WARN_ON(vco != 0);
|
|
|
+ intel_color_load_luts(&pipe_config->base);
|
|
|
|
|
|
- divider = BXT_CDCLK_CD2X_DIV_SEL_1;
|
|
|
- break;
|
|
|
- }
|
|
|
+ intel_update_watermarks(intel_crtc);
|
|
|
+ intel_enable_pipe(intel_crtc);
|
|
|
|
|
|
- /* Inform power controller of upcoming frequency change */
|
|
|
- mutex_lock(&dev_priv->rps.hw_lock);
|
|
|
- ret = sandybridge_pcode_write(dev_priv, HSW_PCODE_DE_WRITE_FREQ_REQ,
|
|
|
- 0x80000000);
|
|
|
- mutex_unlock(&dev_priv->rps.hw_lock);
|
|
|
+ assert_vblank_disabled(crtc);
|
|
|
+ drm_crtc_vblank_on(crtc);
|
|
|
|
|
|
- if (ret) {
|
|
|
- DRM_ERROR("PCode CDCLK freq change notify failed (err %d, freq %d)\n",
|
|
|
- ret, cdclk);
|
|
|
- return;
|
|
|
- }
|
|
|
+ intel_encoders_enable(crtc, pipe_config, old_state);
|
|
|
+}
|
|
|
|
|
|
- if (dev_priv->cdclk_pll.vco != 0 &&
|
|
|
- dev_priv->cdclk_pll.vco != vco)
|
|
|
- bxt_de_pll_disable(dev_priv);
|
|
|
-
|
|
|
- if (dev_priv->cdclk_pll.vco != vco)
|
|
|
- bxt_de_pll_enable(dev_priv, vco);
|
|
|
-
|
|
|
- val = divider | skl_cdclk_decimal(cdclk);
|
|
|
- /*
|
|
|
- * FIXME if only the cd2x divider needs changing, it could be done
|
|
|
- * without shutting off the pipe (if only one pipe is active).
|
|
|
- */
|
|
|
- val |= BXT_CDCLK_CD2X_PIPE_NONE;
|
|
|
- /*
|
|
|
- * Disable SSA Precharge when CD clock frequency < 500 MHz,
|
|
|
- * enable otherwise.
|
|
|
- */
|
|
|
- if (cdclk >= 500000)
|
|
|
- val |= BXT_CDCLK_SSA_PRECHARGE_ENABLE;
|
|
|
- I915_WRITE(CDCLK_CTL, val);
|
|
|
-
|
|
|
- mutex_lock(&dev_priv->rps.hw_lock);
|
|
|
- ret = sandybridge_pcode_write(dev_priv, HSW_PCODE_DE_WRITE_FREQ_REQ,
|
|
|
- DIV_ROUND_UP(cdclk, 25000));
|
|
|
- mutex_unlock(&dev_priv->rps.hw_lock);
|
|
|
-
|
|
|
- if (ret) {
|
|
|
- DRM_ERROR("PCode CDCLK freq set failed, (err %d, freq %d)\n",
|
|
|
- ret, cdclk);
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- intel_update_cdclk(dev_priv);
|
|
|
-}
|
|
|
-
|
|
|
-static void bxt_sanitize_cdclk(struct drm_i915_private *dev_priv)
|
|
|
-{
|
|
|
- u32 cdctl, expected;
|
|
|
-
|
|
|
- intel_update_cdclk(dev_priv);
|
|
|
-
|
|
|
- if (dev_priv->cdclk_pll.vco == 0 ||
|
|
|
- dev_priv->cdclk_freq == dev_priv->cdclk_pll.ref)
|
|
|
- goto sanitize;
|
|
|
-
|
|
|
- /* DPLL okay; verify the cdclock
|
|
|
- *
|
|
|
- * Some BIOS versions leave an incorrect decimal frequency value and
|
|
|
- * set reserved MBZ bits in CDCLK_CTL at least during exiting from S4,
|
|
|
- * so sanitize this register.
|
|
|
- */
|
|
|
- cdctl = I915_READ(CDCLK_CTL);
|
|
|
- /*
|
|
|
- * Let's ignore the pipe field, since BIOS could have configured the
|
|
|
- * dividers both synching to an active pipe, or asynchronously
|
|
|
- * (PIPE_NONE).
|
|
|
- */
|
|
|
- cdctl &= ~BXT_CDCLK_CD2X_PIPE_NONE;
|
|
|
-
|
|
|
- expected = (cdctl & BXT_CDCLK_CD2X_DIV_SEL_MASK) |
|
|
|
- skl_cdclk_decimal(dev_priv->cdclk_freq);
|
|
|
- /*
|
|
|
- * Disable SSA Precharge when CD clock frequency < 500 MHz,
|
|
|
- * enable otherwise.
|
|
|
- */
|
|
|
- if (dev_priv->cdclk_freq >= 500000)
|
|
|
- expected |= BXT_CDCLK_SSA_PRECHARGE_ENABLE;
|
|
|
-
|
|
|
- if (cdctl == expected)
|
|
|
- /* All well; nothing to sanitize */
|
|
|
- return;
|
|
|
-
|
|
|
-sanitize:
|
|
|
- DRM_DEBUG_KMS("Sanitizing cdclk programmed by pre-os\n");
|
|
|
-
|
|
|
- /* force cdclk programming */
|
|
|
- dev_priv->cdclk_freq = 0;
|
|
|
-
|
|
|
- /* force full PLL disable + enable */
|
|
|
- dev_priv->cdclk_pll.vco = -1;
|
|
|
-}
|
|
|
-
|
|
|
-void bxt_init_cdclk(struct drm_i915_private *dev_priv)
|
|
|
-{
|
|
|
- int cdclk;
|
|
|
-
|
|
|
- bxt_sanitize_cdclk(dev_priv);
|
|
|
-
|
|
|
- if (dev_priv->cdclk_freq != 0 && dev_priv->cdclk_pll.vco != 0)
|
|
|
- return;
|
|
|
-
|
|
|
- /*
|
|
|
- * FIXME:
|
|
|
- * - The initial CDCLK needs to be read from VBT.
|
|
|
- * Need to make this change after VBT has changes for BXT.
|
|
|
- */
|
|
|
- if (IS_GEMINILAKE(dev_priv))
|
|
|
- cdclk = glk_calc_cdclk(0);
|
|
|
- else
|
|
|
- cdclk = bxt_calc_cdclk(0);
|
|
|
-
|
|
|
- bxt_set_cdclk(dev_priv, cdclk);
|
|
|
-}
|
|
|
-
|
|
|
-void bxt_uninit_cdclk(struct drm_i915_private *dev_priv)
|
|
|
-{
|
|
|
- bxt_set_cdclk(dev_priv, dev_priv->cdclk_pll.ref);
|
|
|
-}
|
|
|
-
|
|
|
-static int skl_calc_cdclk(int max_pixclk, int vco)
|
|
|
-{
|
|
|
- if (vco == 8640000) {
|
|
|
- if (max_pixclk > 540000)
|
|
|
- return 617143;
|
|
|
- else if (max_pixclk > 432000)
|
|
|
- return 540000;
|
|
|
- else if (max_pixclk > 308571)
|
|
|
- return 432000;
|
|
|
- else
|
|
|
- return 308571;
|
|
|
- } else {
|
|
|
- if (max_pixclk > 540000)
|
|
|
- return 675000;
|
|
|
- else if (max_pixclk > 450000)
|
|
|
- return 540000;
|
|
|
- else if (max_pixclk > 337500)
|
|
|
- return 450000;
|
|
|
- else
|
|
|
- return 337500;
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-static void
|
|
|
-skl_dpll0_update(struct drm_i915_private *dev_priv)
|
|
|
-{
|
|
|
- u32 val;
|
|
|
-
|
|
|
- dev_priv->cdclk_pll.ref = 24000;
|
|
|
- dev_priv->cdclk_pll.vco = 0;
|
|
|
-
|
|
|
- val = I915_READ(LCPLL1_CTL);
|
|
|
- if ((val & LCPLL_PLL_ENABLE) == 0)
|
|
|
- return;
|
|
|
-
|
|
|
- if (WARN_ON((val & LCPLL_PLL_LOCK) == 0))
|
|
|
- return;
|
|
|
-
|
|
|
- val = I915_READ(DPLL_CTRL1);
|
|
|
-
|
|
|
- if (WARN_ON((val & (DPLL_CTRL1_HDMI_MODE(SKL_DPLL0) |
|
|
|
- DPLL_CTRL1_SSC(SKL_DPLL0) |
|
|
|
- DPLL_CTRL1_OVERRIDE(SKL_DPLL0))) !=
|
|
|
- DPLL_CTRL1_OVERRIDE(SKL_DPLL0)))
|
|
|
- return;
|
|
|
-
|
|
|
- switch (val & DPLL_CTRL1_LINK_RATE_MASK(SKL_DPLL0)) {
|
|
|
- case DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_810, SKL_DPLL0):
|
|
|
- case DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1350, SKL_DPLL0):
|
|
|
- case DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1620, SKL_DPLL0):
|
|
|
- case DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_2700, SKL_DPLL0):
|
|
|
- dev_priv->cdclk_pll.vco = 8100000;
|
|
|
- break;
|
|
|
- case DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1080, SKL_DPLL0):
|
|
|
- case DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_2160, SKL_DPLL0):
|
|
|
- dev_priv->cdclk_pll.vco = 8640000;
|
|
|
- break;
|
|
|
- default:
|
|
|
- MISSING_CASE(val & DPLL_CTRL1_LINK_RATE_MASK(SKL_DPLL0));
|
|
|
- break;
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-void skl_set_preferred_cdclk_vco(struct drm_i915_private *dev_priv, int vco)
|
|
|
-{
|
|
|
- bool changed = dev_priv->skl_preferred_vco_freq != vco;
|
|
|
-
|
|
|
- dev_priv->skl_preferred_vco_freq = vco;
|
|
|
-
|
|
|
- if (changed)
|
|
|
- intel_update_max_cdclk(dev_priv);
|
|
|
-}
|
|
|
-
|
|
|
-static void
|
|
|
-skl_dpll0_enable(struct drm_i915_private *dev_priv, int vco)
|
|
|
-{
|
|
|
- int min_cdclk = skl_calc_cdclk(0, vco);
|
|
|
- u32 val;
|
|
|
-
|
|
|
- WARN_ON(vco != 8100000 && vco != 8640000);
|
|
|
-
|
|
|
- /* select the minimum CDCLK before enabling DPLL 0 */
|
|
|
- val = CDCLK_FREQ_337_308 | skl_cdclk_decimal(min_cdclk);
|
|
|
- I915_WRITE(CDCLK_CTL, val);
|
|
|
- POSTING_READ(CDCLK_CTL);
|
|
|
-
|
|
|
- /*
|
|
|
- * We always enable DPLL0 with the lowest link rate possible, but still
|
|
|
- * taking into account the VCO required to operate the eDP panel at the
|
|
|
- * desired frequency. The usual DP link rates operate with a VCO of
|
|
|
- * 8100 while the eDP 1.4 alternate link rates need a VCO of 8640.
|
|
|
- * The modeset code is responsible for the selection of the exact link
|
|
|
- * rate later on, with the constraint of choosing a frequency that
|
|
|
- * works with vco.
|
|
|
- */
|
|
|
- val = I915_READ(DPLL_CTRL1);
|
|
|
-
|
|
|
- val &= ~(DPLL_CTRL1_HDMI_MODE(SKL_DPLL0) | DPLL_CTRL1_SSC(SKL_DPLL0) |
|
|
|
- DPLL_CTRL1_LINK_RATE_MASK(SKL_DPLL0));
|
|
|
- val |= DPLL_CTRL1_OVERRIDE(SKL_DPLL0);
|
|
|
- if (vco == 8640000)
|
|
|
- val |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1080,
|
|
|
- SKL_DPLL0);
|
|
|
- else
|
|
|
- val |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_810,
|
|
|
- SKL_DPLL0);
|
|
|
-
|
|
|
- I915_WRITE(DPLL_CTRL1, val);
|
|
|
- POSTING_READ(DPLL_CTRL1);
|
|
|
-
|
|
|
- I915_WRITE(LCPLL1_CTL, I915_READ(LCPLL1_CTL) | LCPLL_PLL_ENABLE);
|
|
|
-
|
|
|
- if (intel_wait_for_register(dev_priv,
|
|
|
- LCPLL1_CTL, LCPLL_PLL_LOCK, LCPLL_PLL_LOCK,
|
|
|
- 5))
|
|
|
- DRM_ERROR("DPLL0 not locked\n");
|
|
|
-
|
|
|
- dev_priv->cdclk_pll.vco = vco;
|
|
|
-
|
|
|
- /* We'll want to keep using the current vco from now on. */
|
|
|
- skl_set_preferred_cdclk_vco(dev_priv, vco);
|
|
|
-}
|
|
|
-
|
|
|
-static void
|
|
|
-skl_dpll0_disable(struct drm_i915_private *dev_priv)
|
|
|
-{
|
|
|
- I915_WRITE(LCPLL1_CTL, I915_READ(LCPLL1_CTL) & ~LCPLL_PLL_ENABLE);
|
|
|
- if (intel_wait_for_register(dev_priv,
|
|
|
- LCPLL1_CTL, LCPLL_PLL_LOCK, 0,
|
|
|
- 1))
|
|
|
- DRM_ERROR("Couldn't disable DPLL0\n");
|
|
|
-
|
|
|
- dev_priv->cdclk_pll.vco = 0;
|
|
|
-}
|
|
|
-
|
|
|
-static void skl_set_cdclk(struct drm_i915_private *dev_priv, int cdclk, int vco)
|
|
|
-{
|
|
|
- u32 freq_select, pcu_ack;
|
|
|
- int ret;
|
|
|
-
|
|
|
- WARN_ON((cdclk == 24000) != (vco == 0));
|
|
|
-
|
|
|
- DRM_DEBUG_DRIVER("Changing CDCLK to %d kHz (VCO %d kHz)\n", cdclk, vco);
|
|
|
-
|
|
|
- mutex_lock(&dev_priv->rps.hw_lock);
|
|
|
- ret = skl_pcode_request(dev_priv, SKL_PCODE_CDCLK_CONTROL,
|
|
|
- SKL_CDCLK_PREPARE_FOR_CHANGE,
|
|
|
- SKL_CDCLK_READY_FOR_CHANGE,
|
|
|
- SKL_CDCLK_READY_FOR_CHANGE, 3);
|
|
|
- mutex_unlock(&dev_priv->rps.hw_lock);
|
|
|
- if (ret) {
|
|
|
- DRM_ERROR("Failed to inform PCU about cdclk change (%d)\n",
|
|
|
- ret);
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- /* set CDCLK_CTL */
|
|
|
- switch (cdclk) {
|
|
|
- case 450000:
|
|
|
- case 432000:
|
|
|
- freq_select = CDCLK_FREQ_450_432;
|
|
|
- pcu_ack = 1;
|
|
|
- break;
|
|
|
- case 540000:
|
|
|
- freq_select = CDCLK_FREQ_540;
|
|
|
- pcu_ack = 2;
|
|
|
- break;
|
|
|
- case 308571:
|
|
|
- case 337500:
|
|
|
- default:
|
|
|
- freq_select = CDCLK_FREQ_337_308;
|
|
|
- pcu_ack = 0;
|
|
|
- break;
|
|
|
- case 617143:
|
|
|
- case 675000:
|
|
|
- freq_select = CDCLK_FREQ_675_617;
|
|
|
- pcu_ack = 3;
|
|
|
- break;
|
|
|
- }
|
|
|
-
|
|
|
- if (dev_priv->cdclk_pll.vco != 0 &&
|
|
|
- dev_priv->cdclk_pll.vco != vco)
|
|
|
- skl_dpll0_disable(dev_priv);
|
|
|
-
|
|
|
- if (dev_priv->cdclk_pll.vco != vco)
|
|
|
- skl_dpll0_enable(dev_priv, vco);
|
|
|
-
|
|
|
- I915_WRITE(CDCLK_CTL, freq_select | skl_cdclk_decimal(cdclk));
|
|
|
- POSTING_READ(CDCLK_CTL);
|
|
|
-
|
|
|
- /* inform PCU of the change */
|
|
|
- mutex_lock(&dev_priv->rps.hw_lock);
|
|
|
- sandybridge_pcode_write(dev_priv, SKL_PCODE_CDCLK_CONTROL, pcu_ack);
|
|
|
- mutex_unlock(&dev_priv->rps.hw_lock);
|
|
|
-
|
|
|
- intel_update_cdclk(dev_priv);
|
|
|
-}
|
|
|
-
|
|
|
-static void skl_sanitize_cdclk(struct drm_i915_private *dev_priv);
|
|
|
-
|
|
|
-void skl_uninit_cdclk(struct drm_i915_private *dev_priv)
|
|
|
-{
|
|
|
- skl_set_cdclk(dev_priv, dev_priv->cdclk_pll.ref, 0);
|
|
|
-}
|
|
|
-
|
|
|
-void skl_init_cdclk(struct drm_i915_private *dev_priv)
|
|
|
-{
|
|
|
- int cdclk, vco;
|
|
|
-
|
|
|
- skl_sanitize_cdclk(dev_priv);
|
|
|
-
|
|
|
- if (dev_priv->cdclk_freq != 0 && dev_priv->cdclk_pll.vco != 0) {
|
|
|
- /*
|
|
|
- * Use the current vco as our initial
|
|
|
- * guess as to what the preferred vco is.
|
|
|
- */
|
|
|
- if (dev_priv->skl_preferred_vco_freq == 0)
|
|
|
- skl_set_preferred_cdclk_vco(dev_priv,
|
|
|
- dev_priv->cdclk_pll.vco);
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- vco = dev_priv->skl_preferred_vco_freq;
|
|
|
- if (vco == 0)
|
|
|
- vco = 8100000;
|
|
|
- cdclk = skl_calc_cdclk(0, vco);
|
|
|
-
|
|
|
- skl_set_cdclk(dev_priv, cdclk, vco);
|
|
|
-}
|
|
|
-
|
|
|
-static void skl_sanitize_cdclk(struct drm_i915_private *dev_priv)
|
|
|
-{
|
|
|
- uint32_t cdctl, expected;
|
|
|
-
|
|
|
- /*
|
|
|
- * check if the pre-os intialized the display
|
|
|
- * There is SWF18 scratchpad register defined which is set by the
|
|
|
- * pre-os which can be used by the OS drivers to check the status
|
|
|
- */
|
|
|
- if ((I915_READ(SWF_ILK(0x18)) & 0x00FFFFFF) == 0)
|
|
|
- goto sanitize;
|
|
|
-
|
|
|
- intel_update_cdclk(dev_priv);
|
|
|
- /* Is PLL enabled and locked ? */
|
|
|
- if (dev_priv->cdclk_pll.vco == 0 ||
|
|
|
- dev_priv->cdclk_freq == dev_priv->cdclk_pll.ref)
|
|
|
- goto sanitize;
|
|
|
-
|
|
|
- /* DPLL okay; verify the cdclock
|
|
|
- *
|
|
|
- * Noticed in some instances that the freq selection is correct but
|
|
|
- * decimal part is programmed wrong from BIOS where pre-os does not
|
|
|
- * enable display. Verify the same as well.
|
|
|
- */
|
|
|
- cdctl = I915_READ(CDCLK_CTL);
|
|
|
- expected = (cdctl & CDCLK_FREQ_SEL_MASK) |
|
|
|
- skl_cdclk_decimal(dev_priv->cdclk_freq);
|
|
|
- if (cdctl == expected)
|
|
|
- /* All well; nothing to sanitize */
|
|
|
- return;
|
|
|
-
|
|
|
-sanitize:
|
|
|
- DRM_DEBUG_KMS("Sanitizing cdclk programmed by pre-os\n");
|
|
|
-
|
|
|
- /* force cdclk programming */
|
|
|
- dev_priv->cdclk_freq = 0;
|
|
|
- /* force full PLL disable + enable */
|
|
|
- dev_priv->cdclk_pll.vco = -1;
|
|
|
-}
|
|
|
-
|
|
|
-/* Adjust CDclk dividers to allow high res or save power if possible */
|
|
|
-static void valleyview_set_cdclk(struct drm_device *dev, int cdclk)
|
|
|
-{
|
|
|
- struct drm_i915_private *dev_priv = to_i915(dev);
|
|
|
- u32 val, cmd;
|
|
|
-
|
|
|
- WARN_ON(dev_priv->display.get_display_clock_speed(dev_priv)
|
|
|
- != dev_priv->cdclk_freq);
|
|
|
-
|
|
|
- if (cdclk >= 320000) /* jump to highest voltage for 400MHz too */
|
|
|
- cmd = 2;
|
|
|
- else if (cdclk == 266667)
|
|
|
- cmd = 1;
|
|
|
- else
|
|
|
- cmd = 0;
|
|
|
-
|
|
|
- mutex_lock(&dev_priv->rps.hw_lock);
|
|
|
- val = vlv_punit_read(dev_priv, PUNIT_REG_DSPFREQ);
|
|
|
- val &= ~DSPFREQGUAR_MASK;
|
|
|
- val |= (cmd << DSPFREQGUAR_SHIFT);
|
|
|
- vlv_punit_write(dev_priv, PUNIT_REG_DSPFREQ, val);
|
|
|
- if (wait_for((vlv_punit_read(dev_priv, PUNIT_REG_DSPFREQ) &
|
|
|
- DSPFREQSTAT_MASK) == (cmd << DSPFREQSTAT_SHIFT),
|
|
|
- 50)) {
|
|
|
- DRM_ERROR("timed out waiting for CDclk change\n");
|
|
|
- }
|
|
|
- mutex_unlock(&dev_priv->rps.hw_lock);
|
|
|
-
|
|
|
- mutex_lock(&dev_priv->sb_lock);
|
|
|
-
|
|
|
- if (cdclk == 400000) {
|
|
|
- u32 divider;
|
|
|
-
|
|
|
- divider = DIV_ROUND_CLOSEST(dev_priv->hpll_freq << 1, cdclk) - 1;
|
|
|
-
|
|
|
- /* adjust cdclk divider */
|
|
|
- val = vlv_cck_read(dev_priv, CCK_DISPLAY_CLOCK_CONTROL);
|
|
|
- val &= ~CCK_FREQUENCY_VALUES;
|
|
|
- val |= divider;
|
|
|
- vlv_cck_write(dev_priv, CCK_DISPLAY_CLOCK_CONTROL, val);
|
|
|
-
|
|
|
- if (wait_for((vlv_cck_read(dev_priv, CCK_DISPLAY_CLOCK_CONTROL) &
|
|
|
- CCK_FREQUENCY_STATUS) == (divider << CCK_FREQUENCY_STATUS_SHIFT),
|
|
|
- 50))
|
|
|
- DRM_ERROR("timed out waiting for CDclk change\n");
|
|
|
- }
|
|
|
-
|
|
|
- /* adjust self-refresh exit latency value */
|
|
|
- val = vlv_bunit_read(dev_priv, BUNIT_REG_BISOC);
|
|
|
- val &= ~0x7f;
|
|
|
-
|
|
|
- /*
|
|
|
- * For high bandwidth configs, we set a higher latency in the bunit
|
|
|
- * so that the core display fetch happens in time to avoid underruns.
|
|
|
- */
|
|
|
- if (cdclk == 400000)
|
|
|
- val |= 4500 / 250; /* 4.5 usec */
|
|
|
- else
|
|
|
- val |= 3000 / 250; /* 3.0 usec */
|
|
|
- vlv_bunit_write(dev_priv, BUNIT_REG_BISOC, val);
|
|
|
-
|
|
|
- mutex_unlock(&dev_priv->sb_lock);
|
|
|
-
|
|
|
- intel_update_cdclk(dev_priv);
|
|
|
-}
|
|
|
-
|
|
|
-static void cherryview_set_cdclk(struct drm_device *dev, int cdclk)
|
|
|
-{
|
|
|
- struct drm_i915_private *dev_priv = to_i915(dev);
|
|
|
- u32 val, cmd;
|
|
|
-
|
|
|
- WARN_ON(dev_priv->display.get_display_clock_speed(dev_priv)
|
|
|
- != dev_priv->cdclk_freq);
|
|
|
-
|
|
|
- switch (cdclk) {
|
|
|
- case 333333:
|
|
|
- case 320000:
|
|
|
- case 266667:
|
|
|
- case 200000:
|
|
|
- break;
|
|
|
- default:
|
|
|
- MISSING_CASE(cdclk);
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- /*
|
|
|
- * Specs are full of misinformation, but testing on actual
|
|
|
- * hardware has shown that we just need to write the desired
|
|
|
- * CCK divider into the Punit register.
|
|
|
- */
|
|
|
- cmd = DIV_ROUND_CLOSEST(dev_priv->hpll_freq << 1, cdclk) - 1;
|
|
|
-
|
|
|
- mutex_lock(&dev_priv->rps.hw_lock);
|
|
|
- val = vlv_punit_read(dev_priv, PUNIT_REG_DSPFREQ);
|
|
|
- val &= ~DSPFREQGUAR_MASK_CHV;
|
|
|
- val |= (cmd << DSPFREQGUAR_SHIFT_CHV);
|
|
|
- vlv_punit_write(dev_priv, PUNIT_REG_DSPFREQ, val);
|
|
|
- if (wait_for((vlv_punit_read(dev_priv, PUNIT_REG_DSPFREQ) &
|
|
|
- DSPFREQSTAT_MASK_CHV) == (cmd << DSPFREQSTAT_SHIFT_CHV),
|
|
|
- 50)) {
|
|
|
- DRM_ERROR("timed out waiting for CDclk change\n");
|
|
|
- }
|
|
|
- mutex_unlock(&dev_priv->rps.hw_lock);
|
|
|
-
|
|
|
- intel_update_cdclk(dev_priv);
|
|
|
-}
|
|
|
-
|
|
|
-static int valleyview_calc_cdclk(struct drm_i915_private *dev_priv,
|
|
|
- int max_pixclk)
|
|
|
-{
|
|
|
- int freq_320 = (dev_priv->hpll_freq << 1) % 320000 != 0 ? 333333 : 320000;
|
|
|
- int limit = IS_CHERRYVIEW(dev_priv) ? 95 : 90;
|
|
|
-
|
|
|
- /*
|
|
|
- * Really only a few cases to deal with, as only 4 CDclks are supported:
|
|
|
- * 200MHz
|
|
|
- * 267MHz
|
|
|
- * 320/333MHz (depends on HPLL freq)
|
|
|
- * 400MHz (VLV only)
|
|
|
- * So we check to see whether we're above 90% (VLV) or 95% (CHV)
|
|
|
- * of the lower bin and adjust if needed.
|
|
|
- *
|
|
|
- * We seem to get an unstable or solid color picture at 200MHz.
|
|
|
- * Not sure what's wrong. For now use 200MHz only when all pipes
|
|
|
- * are off.
|
|
|
- */
|
|
|
- if (!IS_CHERRYVIEW(dev_priv) &&
|
|
|
- max_pixclk > freq_320*limit/100)
|
|
|
- return 400000;
|
|
|
- else if (max_pixclk > 266667*limit/100)
|
|
|
- return freq_320;
|
|
|
- else if (max_pixclk > 0)
|
|
|
- return 266667;
|
|
|
- else
|
|
|
- return 200000;
|
|
|
-}
|
|
|
-
|
|
|
-static int glk_calc_cdclk(int max_pixclk)
|
|
|
-{
|
|
|
- if (max_pixclk > 2 * 158400)
|
|
|
- return 316800;
|
|
|
- else if (max_pixclk > 2 * 79200)
|
|
|
- return 158400;
|
|
|
- else
|
|
|
- return 79200;
|
|
|
-}
|
|
|
-
|
|
|
-static int bxt_calc_cdclk(int max_pixclk)
|
|
|
-{
|
|
|
- if (max_pixclk > 576000)
|
|
|
- return 624000;
|
|
|
- else if (max_pixclk > 384000)
|
|
|
- return 576000;
|
|
|
- else if (max_pixclk > 288000)
|
|
|
- return 384000;
|
|
|
- else if (max_pixclk > 144000)
|
|
|
- return 288000;
|
|
|
- else
|
|
|
- return 144000;
|
|
|
-}
|
|
|
-
|
|
|
-/* Compute the max pixel clock for new configuration. */
|
|
|
-static int intel_mode_max_pixclk(struct drm_device *dev,
|
|
|
- struct drm_atomic_state *state)
|
|
|
-{
|
|
|
- struct intel_atomic_state *intel_state = to_intel_atomic_state(state);
|
|
|
- struct drm_i915_private *dev_priv = to_i915(dev);
|
|
|
- struct drm_crtc *crtc;
|
|
|
- struct drm_crtc_state *crtc_state;
|
|
|
- unsigned max_pixclk = 0, i;
|
|
|
- enum pipe pipe;
|
|
|
-
|
|
|
- memcpy(intel_state->min_pixclk, dev_priv->min_pixclk,
|
|
|
- sizeof(intel_state->min_pixclk));
|
|
|
-
|
|
|
- for_each_crtc_in_state(state, crtc, crtc_state, i) {
|
|
|
- int pixclk = 0;
|
|
|
-
|
|
|
- if (crtc_state->enable)
|
|
|
- pixclk = crtc_state->adjusted_mode.crtc_clock;
|
|
|
-
|
|
|
- intel_state->min_pixclk[i] = pixclk;
|
|
|
- }
|
|
|
-
|
|
|
- for_each_pipe(dev_priv, pipe)
|
|
|
- max_pixclk = max(intel_state->min_pixclk[pipe], max_pixclk);
|
|
|
-
|
|
|
- return max_pixclk;
|
|
|
-}
|
|
|
-
|
|
|
-static int valleyview_modeset_calc_cdclk(struct drm_atomic_state *state)
|
|
|
-{
|
|
|
- struct drm_device *dev = state->dev;
|
|
|
- struct drm_i915_private *dev_priv = to_i915(dev);
|
|
|
- int max_pixclk = intel_mode_max_pixclk(dev, state);
|
|
|
- struct intel_atomic_state *intel_state =
|
|
|
- to_intel_atomic_state(state);
|
|
|
-
|
|
|
- intel_state->cdclk = intel_state->dev_cdclk =
|
|
|
- valleyview_calc_cdclk(dev_priv, max_pixclk);
|
|
|
-
|
|
|
- if (!intel_state->active_crtcs)
|
|
|
- intel_state->dev_cdclk = valleyview_calc_cdclk(dev_priv, 0);
|
|
|
-
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
-static int bxt_modeset_calc_cdclk(struct drm_atomic_state *state)
|
|
|
-{
|
|
|
- struct drm_i915_private *dev_priv = to_i915(state->dev);
|
|
|
- int max_pixclk = ilk_max_pixel_rate(state);
|
|
|
- struct intel_atomic_state *intel_state =
|
|
|
- to_intel_atomic_state(state);
|
|
|
- int cdclk;
|
|
|
-
|
|
|
- if (IS_GEMINILAKE(dev_priv))
|
|
|
- cdclk = glk_calc_cdclk(max_pixclk);
|
|
|
- else
|
|
|
- cdclk = bxt_calc_cdclk(max_pixclk);
|
|
|
-
|
|
|
- intel_state->cdclk = intel_state->dev_cdclk = cdclk;
|
|
|
-
|
|
|
- if (!intel_state->active_crtcs) {
|
|
|
- if (IS_GEMINILAKE(dev_priv))
|
|
|
- cdclk = glk_calc_cdclk(0);
|
|
|
- else
|
|
|
- cdclk = bxt_calc_cdclk(0);
|
|
|
-
|
|
|
- intel_state->dev_cdclk = cdclk;
|
|
|
- }
|
|
|
-
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
-static void vlv_program_pfi_credits(struct drm_i915_private *dev_priv)
|
|
|
-{
|
|
|
- unsigned int credits, default_credits;
|
|
|
-
|
|
|
- if (IS_CHERRYVIEW(dev_priv))
|
|
|
- default_credits = PFI_CREDIT(12);
|
|
|
- else
|
|
|
- default_credits = PFI_CREDIT(8);
|
|
|
-
|
|
|
- if (dev_priv->cdclk_freq >= dev_priv->czclk_freq) {
|
|
|
- /* CHV suggested value is 31 or 63 */
|
|
|
- if (IS_CHERRYVIEW(dev_priv))
|
|
|
- credits = PFI_CREDIT_63;
|
|
|
- else
|
|
|
- credits = PFI_CREDIT(15);
|
|
|
- } else {
|
|
|
- credits = default_credits;
|
|
|
- }
|
|
|
-
|
|
|
- /*
|
|
|
- * WA - write default credits before re-programming
|
|
|
- * FIXME: should we also set the resend bit here?
|
|
|
- */
|
|
|
- I915_WRITE(GCI_CONTROL, VGA_FAST_MODE_DISABLE |
|
|
|
- default_credits);
|
|
|
-
|
|
|
- I915_WRITE(GCI_CONTROL, VGA_FAST_MODE_DISABLE |
|
|
|
- credits | PFI_CREDIT_RESEND);
|
|
|
-
|
|
|
- /*
|
|
|
- * FIXME is this guaranteed to clear
|
|
|
- * immediately or should we poll for it?
|
|
|
- */
|
|
|
- WARN_ON(I915_READ(GCI_CONTROL) & PFI_CREDIT_RESEND);
|
|
|
-}
|
|
|
-
|
|
|
-static void valleyview_modeset_commit_cdclk(struct drm_atomic_state *old_state)
|
|
|
-{
|
|
|
- struct drm_device *dev = old_state->dev;
|
|
|
- struct drm_i915_private *dev_priv = to_i915(dev);
|
|
|
- struct intel_atomic_state *old_intel_state =
|
|
|
- to_intel_atomic_state(old_state);
|
|
|
- unsigned req_cdclk = old_intel_state->dev_cdclk;
|
|
|
-
|
|
|
- /*
|
|
|
- * FIXME: We can end up here with all power domains off, yet
|
|
|
- * with a CDCLK frequency other than the minimum. To account
|
|
|
- * for this take the PIPE-A power domain, which covers the HW
|
|
|
- * blocks needed for the following programming. This can be
|
|
|
- * removed once it's guaranteed that we get here either with
|
|
|
- * the minimum CDCLK set, or the required power domains
|
|
|
- * enabled.
|
|
|
- */
|
|
|
- intel_display_power_get(dev_priv, POWER_DOMAIN_PIPE_A);
|
|
|
-
|
|
|
- if (IS_CHERRYVIEW(dev_priv))
|
|
|
- cherryview_set_cdclk(dev, req_cdclk);
|
|
|
- else
|
|
|
- valleyview_set_cdclk(dev, req_cdclk);
|
|
|
-
|
|
|
- vlv_program_pfi_credits(dev_priv);
|
|
|
-
|
|
|
- intel_display_power_put(dev_priv, POWER_DOMAIN_PIPE_A);
|
|
|
-}
|
|
|
-
|
|
|
-static void valleyview_crtc_enable(struct intel_crtc_state *pipe_config,
|
|
|
- struct drm_atomic_state *old_state)
|
|
|
-{
|
|
|
- struct drm_crtc *crtc = pipe_config->base.crtc;
|
|
|
- struct drm_device *dev = crtc->dev;
|
|
|
- struct drm_i915_private *dev_priv = to_i915(dev);
|
|
|
- struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
|
|
- int pipe = intel_crtc->pipe;
|
|
|
-
|
|
|
- if (WARN_ON(intel_crtc->active))
|
|
|
- return;
|
|
|
-
|
|
|
- if (intel_crtc_has_dp_encoder(intel_crtc->config))
|
|
|
- intel_dp_set_m_n(intel_crtc, M1_N1);
|
|
|
-
|
|
|
- intel_set_pipe_timings(intel_crtc);
|
|
|
- intel_set_pipe_src_size(intel_crtc);
|
|
|
-
|
|
|
- if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B) {
|
|
|
- struct drm_i915_private *dev_priv = to_i915(dev);
|
|
|
-
|
|
|
- I915_WRITE(CHV_BLEND(pipe), CHV_BLEND_LEGACY);
|
|
|
- I915_WRITE(CHV_CANVAS(pipe), 0);
|
|
|
- }
|
|
|
-
|
|
|
- i9xx_set_pipeconf(intel_crtc);
|
|
|
-
|
|
|
- intel_crtc->active = true;
|
|
|
-
|
|
|
- intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true);
|
|
|
-
|
|
|
- intel_encoders_pre_pll_enable(crtc, pipe_config, old_state);
|
|
|
-
|
|
|
- if (IS_CHERRYVIEW(dev_priv)) {
|
|
|
- chv_prepare_pll(intel_crtc, intel_crtc->config);
|
|
|
- chv_enable_pll(intel_crtc, intel_crtc->config);
|
|
|
- } else {
|
|
|
- vlv_prepare_pll(intel_crtc, intel_crtc->config);
|
|
|
- vlv_enable_pll(intel_crtc, intel_crtc->config);
|
|
|
- }
|
|
|
-
|
|
|
- intel_encoders_pre_enable(crtc, pipe_config, old_state);
|
|
|
-
|
|
|
- i9xx_pfit_enable(intel_crtc);
|
|
|
-
|
|
|
- intel_color_load_luts(&pipe_config->base);
|
|
|
-
|
|
|
- intel_update_watermarks(intel_crtc);
|
|
|
- intel_enable_pipe(intel_crtc);
|
|
|
-
|
|
|
- assert_vblank_disabled(crtc);
|
|
|
- drm_crtc_vblank_on(crtc);
|
|
|
-
|
|
|
- intel_encoders_enable(crtc, pipe_config, old_state);
|
|
|
-}
|
|
|
-
|
|
|
-static void i9xx_set_pll_dividers(struct intel_crtc *crtc)
|
|
|
-{
|
|
|
- struct drm_device *dev = crtc->base.dev;
|
|
|
- struct drm_i915_private *dev_priv = to_i915(dev);
|
|
|
-
|
|
|
- I915_WRITE(FP0(crtc->pipe), crtc->config->dpll_hw_state.fp0);
|
|
|
- I915_WRITE(FP1(crtc->pipe), crtc->config->dpll_hw_state.fp1);
|
|
|
-}
|
|
|
-
|
|
|
-static void i9xx_crtc_enable(struct intel_crtc_state *pipe_config,
|
|
|
- struct drm_atomic_state *old_state)
|
|
|
-{
|
|
|
- struct drm_crtc *crtc = pipe_config->base.crtc;
|
|
|
- struct drm_device *dev = crtc->dev;
|
|
|
- struct drm_i915_private *dev_priv = to_i915(dev);
|
|
|
- struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
|
|
- enum pipe pipe = intel_crtc->pipe;
|
|
|
-
|
|
|
- if (WARN_ON(intel_crtc->active))
|
|
|
- return;
|
|
|
-
|
|
|
- i9xx_set_pll_dividers(intel_crtc);
|
|
|
-
|
|
|
- if (intel_crtc_has_dp_encoder(intel_crtc->config))
|
|
|
- intel_dp_set_m_n(intel_crtc, M1_N1);
|
|
|
-
|
|
|
- intel_set_pipe_timings(intel_crtc);
|
|
|
- intel_set_pipe_src_size(intel_crtc);
|
|
|
-
|
|
|
- i9xx_set_pipeconf(intel_crtc);
|
|
|
-
|
|
|
- intel_crtc->active = true;
|
|
|
-
|
|
|
- if (!IS_GEN2(dev_priv))
|
|
|
- intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true);
|
|
|
-
|
|
|
- intel_encoders_pre_enable(crtc, pipe_config, old_state);
|
|
|
-
|
|
|
- i9xx_enable_pll(intel_crtc);
|
|
|
-
|
|
|
- i9xx_pfit_enable(intel_crtc);
|
|
|
-
|
|
|
- intel_color_load_luts(&pipe_config->base);
|
|
|
-
|
|
|
- intel_update_watermarks(intel_crtc);
|
|
|
- intel_enable_pipe(intel_crtc);
|
|
|
-
|
|
|
- assert_vblank_disabled(crtc);
|
|
|
- drm_crtc_vblank_on(crtc);
|
|
|
-
|
|
|
- intel_encoders_enable(crtc, pipe_config, old_state);
|
|
|
-}
|
|
|
-
|
|
|
-static void i9xx_pfit_disable(struct intel_crtc *crtc)
|
|
|
-{
|
|
|
- struct drm_device *dev = crtc->base.dev;
|
|
|
- struct drm_i915_private *dev_priv = to_i915(dev);
|
|
|
+static void i9xx_pfit_disable(struct intel_crtc *crtc)
|
|
|
+{
|
|
|
+ struct drm_device *dev = crtc->base.dev;
|
|
|
+ struct drm_i915_private *dev_priv = to_i915(dev);
|
|
|
|
|
|
if (!crtc->config->gmch_pfit.control)
|
|
|
return;
|
|
|
@@ -6857,6 +5846,9 @@ static void i9xx_crtc_disable(struct intel_crtc_state *old_crtc_state,
|
|
|
|
|
|
if (!IS_GEN2(dev_priv))
|
|
|
intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, false);
|
|
|
+
|
|
|
+ if (!dev_priv->display.initial_watermarks)
|
|
|
+ intel_update_watermarks(intel_crtc);
|
|
|
}
|
|
|
|
|
|
static void intel_crtc_disable_noatomic(struct drm_crtc *crtc)
|
|
|
@@ -6865,7 +5857,7 @@ static void intel_crtc_disable_noatomic(struct drm_crtc *crtc)
|
|
|
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
|
|
struct drm_i915_private *dev_priv = to_i915(crtc->dev);
|
|
|
enum intel_display_power_domain domain;
|
|
|
- unsigned long domains;
|
|
|
+ u64 domains;
|
|
|
struct drm_atomic_state *state;
|
|
|
struct intel_crtc_state *crtc_state;
|
|
|
int ret;
|
|
|
@@ -7173,7 +6165,7 @@ static bool pipe_config_supports_ips(struct drm_i915_private *dev_priv,
|
|
|
*
|
|
|
* Should measure whether using a lower cdclk w/o IPS
|
|
|
*/
|
|
|
- return ilk_pipe_pixel_rate(pipe_config) <=
|
|
|
+ return pipe_config->pixel_rate <=
|
|
|
dev_priv->max_cdclk_freq * 95 / 100;
|
|
|
}
|
|
|
|
|
|
@@ -7188,490 +6180,118 @@ static void hsw_compute_ips_config(struct intel_crtc *crtc,
|
|
|
pipe_config_supports_ips(dev_priv, pipe_config);
|
|
|
}
|
|
|
|
|
|
-static bool intel_crtc_supports_double_wide(const struct intel_crtc *crtc)
|
|
|
-{
|
|
|
- const struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
|
|
|
-
|
|
|
- /* GDG double wide on either pipe, otherwise pipe A only */
|
|
|
- return INTEL_INFO(dev_priv)->gen < 4 &&
|
|
|
- (crtc->pipe == PIPE_A || IS_I915G(dev_priv));
|
|
|
-}
|
|
|
-
|
|
|
-static int intel_crtc_compute_config(struct intel_crtc *crtc,
|
|
|
- struct intel_crtc_state *pipe_config)
|
|
|
-{
|
|
|
- struct drm_device *dev = crtc->base.dev;
|
|
|
- struct drm_i915_private *dev_priv = to_i915(dev);
|
|
|
- const struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode;
|
|
|
- int clock_limit = dev_priv->max_dotclk_freq;
|
|
|
-
|
|
|
- if (INTEL_GEN(dev_priv) < 4) {
|
|
|
- clock_limit = dev_priv->max_cdclk_freq * 9 / 10;
|
|
|
-
|
|
|
- /*
|
|
|
- * Enable double wide mode when the dot clock
|
|
|
- * is > 90% of the (display) core speed.
|
|
|
- */
|
|
|
- if (intel_crtc_supports_double_wide(crtc) &&
|
|
|
- adjusted_mode->crtc_clock > clock_limit) {
|
|
|
- clock_limit = dev_priv->max_dotclk_freq;
|
|
|
- pipe_config->double_wide = true;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- if (adjusted_mode->crtc_clock > clock_limit) {
|
|
|
- DRM_DEBUG_KMS("requested pixel clock (%d kHz) too high (max: %d kHz, double wide: %s)\n",
|
|
|
- adjusted_mode->crtc_clock, clock_limit,
|
|
|
- yesno(pipe_config->double_wide));
|
|
|
- return -EINVAL;
|
|
|
- }
|
|
|
-
|
|
|
- /*
|
|
|
- * Pipe horizontal size must be even in:
|
|
|
- * - DVO ganged mode
|
|
|
- * - LVDS dual channel mode
|
|
|
- * - Double wide pipe
|
|
|
- */
|
|
|
- if ((intel_crtc_has_type(pipe_config, INTEL_OUTPUT_LVDS) &&
|
|
|
- intel_is_dual_link_lvds(dev)) || pipe_config->double_wide)
|
|
|
- pipe_config->pipe_src_w &= ~1;
|
|
|
-
|
|
|
- /* Cantiga+ cannot handle modes with a hsync front porch of 0.
|
|
|
- * WaPruneModeWithIncorrectHsyncOffset:ctg,elk,ilk,snb,ivb,vlv,hsw.
|
|
|
- */
|
|
|
- if ((INTEL_GEN(dev_priv) > 4 || IS_G4X(dev_priv)) &&
|
|
|
- adjusted_mode->crtc_hsync_start == adjusted_mode->crtc_hdisplay)
|
|
|
- return -EINVAL;
|
|
|
-
|
|
|
- if (HAS_IPS(dev_priv))
|
|
|
- hsw_compute_ips_config(crtc, pipe_config);
|
|
|
-
|
|
|
- if (pipe_config->has_pch_encoder)
|
|
|
- return ironlake_fdi_compute_config(crtc, pipe_config);
|
|
|
-
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
-static int skylake_get_display_clock_speed(struct drm_i915_private *dev_priv)
|
|
|
-{
|
|
|
- u32 cdctl;
|
|
|
-
|
|
|
- skl_dpll0_update(dev_priv);
|
|
|
-
|
|
|
- if (dev_priv->cdclk_pll.vco == 0)
|
|
|
- return dev_priv->cdclk_pll.ref;
|
|
|
-
|
|
|
- cdctl = I915_READ(CDCLK_CTL);
|
|
|
-
|
|
|
- if (dev_priv->cdclk_pll.vco == 8640000) {
|
|
|
- switch (cdctl & CDCLK_FREQ_SEL_MASK) {
|
|
|
- case CDCLK_FREQ_450_432:
|
|
|
- return 432000;
|
|
|
- case CDCLK_FREQ_337_308:
|
|
|
- return 308571;
|
|
|
- case CDCLK_FREQ_540:
|
|
|
- return 540000;
|
|
|
- case CDCLK_FREQ_675_617:
|
|
|
- return 617143;
|
|
|
- default:
|
|
|
- MISSING_CASE(cdctl & CDCLK_FREQ_SEL_MASK);
|
|
|
- }
|
|
|
- } else {
|
|
|
- switch (cdctl & CDCLK_FREQ_SEL_MASK) {
|
|
|
- case CDCLK_FREQ_450_432:
|
|
|
- return 450000;
|
|
|
- case CDCLK_FREQ_337_308:
|
|
|
- return 337500;
|
|
|
- case CDCLK_FREQ_540:
|
|
|
- return 540000;
|
|
|
- case CDCLK_FREQ_675_617:
|
|
|
- return 675000;
|
|
|
- default:
|
|
|
- MISSING_CASE(cdctl & CDCLK_FREQ_SEL_MASK);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- return dev_priv->cdclk_pll.ref;
|
|
|
-}
|
|
|
-
|
|
|
-static void bxt_de_pll_update(struct drm_i915_private *dev_priv)
|
|
|
-{
|
|
|
- u32 val;
|
|
|
-
|
|
|
- dev_priv->cdclk_pll.ref = 19200;
|
|
|
- dev_priv->cdclk_pll.vco = 0;
|
|
|
-
|
|
|
- val = I915_READ(BXT_DE_PLL_ENABLE);
|
|
|
- if ((val & BXT_DE_PLL_PLL_ENABLE) == 0)
|
|
|
- return;
|
|
|
-
|
|
|
- if (WARN_ON((val & BXT_DE_PLL_LOCK) == 0))
|
|
|
- return;
|
|
|
-
|
|
|
- val = I915_READ(BXT_DE_PLL_CTL);
|
|
|
- dev_priv->cdclk_pll.vco = (val & BXT_DE_PLL_RATIO_MASK) *
|
|
|
- dev_priv->cdclk_pll.ref;
|
|
|
-}
|
|
|
-
|
|
|
-static int broxton_get_display_clock_speed(struct drm_i915_private *dev_priv)
|
|
|
-{
|
|
|
- u32 divider;
|
|
|
- int div, vco;
|
|
|
-
|
|
|
- bxt_de_pll_update(dev_priv);
|
|
|
-
|
|
|
- vco = dev_priv->cdclk_pll.vco;
|
|
|
- if (vco == 0)
|
|
|
- return dev_priv->cdclk_pll.ref;
|
|
|
-
|
|
|
- divider = I915_READ(CDCLK_CTL) & BXT_CDCLK_CD2X_DIV_SEL_MASK;
|
|
|
-
|
|
|
- switch (divider) {
|
|
|
- case BXT_CDCLK_CD2X_DIV_SEL_1:
|
|
|
- div = 2;
|
|
|
- break;
|
|
|
- case BXT_CDCLK_CD2X_DIV_SEL_1_5:
|
|
|
- WARN(IS_GEMINILAKE(dev_priv), "Unsupported divider\n");
|
|
|
- div = 3;
|
|
|
- break;
|
|
|
- case BXT_CDCLK_CD2X_DIV_SEL_2:
|
|
|
- div = 4;
|
|
|
- break;
|
|
|
- case BXT_CDCLK_CD2X_DIV_SEL_4:
|
|
|
- div = 8;
|
|
|
- break;
|
|
|
- default:
|
|
|
- MISSING_CASE(divider);
|
|
|
- return dev_priv->cdclk_pll.ref;
|
|
|
- }
|
|
|
-
|
|
|
- return DIV_ROUND_CLOSEST(vco, div);
|
|
|
-}
|
|
|
-
|
|
|
-static int broadwell_get_display_clock_speed(struct drm_i915_private *dev_priv)
|
|
|
-{
|
|
|
- uint32_t lcpll = I915_READ(LCPLL_CTL);
|
|
|
- uint32_t freq = lcpll & LCPLL_CLK_FREQ_MASK;
|
|
|
-
|
|
|
- if (lcpll & LCPLL_CD_SOURCE_FCLK)
|
|
|
- return 800000;
|
|
|
- else if (I915_READ(FUSE_STRAP) & HSW_CDCLK_LIMIT)
|
|
|
- return 450000;
|
|
|
- else if (freq == LCPLL_CLK_FREQ_450)
|
|
|
- return 450000;
|
|
|
- else if (freq == LCPLL_CLK_FREQ_54O_BDW)
|
|
|
- return 540000;
|
|
|
- else if (freq == LCPLL_CLK_FREQ_337_5_BDW)
|
|
|
- return 337500;
|
|
|
- else
|
|
|
- return 675000;
|
|
|
-}
|
|
|
-
|
|
|
-static int haswell_get_display_clock_speed(struct drm_i915_private *dev_priv)
|
|
|
-{
|
|
|
- uint32_t lcpll = I915_READ(LCPLL_CTL);
|
|
|
- uint32_t freq = lcpll & LCPLL_CLK_FREQ_MASK;
|
|
|
-
|
|
|
- if (lcpll & LCPLL_CD_SOURCE_FCLK)
|
|
|
- return 800000;
|
|
|
- else if (I915_READ(FUSE_STRAP) & HSW_CDCLK_LIMIT)
|
|
|
- return 450000;
|
|
|
- else if (freq == LCPLL_CLK_FREQ_450)
|
|
|
- return 450000;
|
|
|
- else if (IS_HSW_ULT(dev_priv))
|
|
|
- return 337500;
|
|
|
- else
|
|
|
- return 540000;
|
|
|
-}
|
|
|
-
|
|
|
-static int valleyview_get_display_clock_speed(struct drm_i915_private *dev_priv)
|
|
|
-{
|
|
|
- return vlv_get_cck_clock_hpll(dev_priv, "cdclk",
|
|
|
- CCK_DISPLAY_CLOCK_CONTROL);
|
|
|
-}
|
|
|
-
|
|
|
-static int ilk_get_display_clock_speed(struct drm_i915_private *dev_priv)
|
|
|
-{
|
|
|
- return 450000;
|
|
|
-}
|
|
|
-
|
|
|
-static int i945_get_display_clock_speed(struct drm_i915_private *dev_priv)
|
|
|
-{
|
|
|
- return 400000;
|
|
|
-}
|
|
|
-
|
|
|
-static int i915_get_display_clock_speed(struct drm_i915_private *dev_priv)
|
|
|
-{
|
|
|
- return 333333;
|
|
|
-}
|
|
|
-
|
|
|
-static int i9xx_misc_get_display_clock_speed(struct drm_i915_private *dev_priv)
|
|
|
-{
|
|
|
- return 200000;
|
|
|
-}
|
|
|
-
|
|
|
-static int pnv_get_display_clock_speed(struct drm_i915_private *dev_priv)
|
|
|
-{
|
|
|
- struct pci_dev *pdev = dev_priv->drm.pdev;
|
|
|
- u16 gcfgc = 0;
|
|
|
-
|
|
|
- pci_read_config_word(pdev, GCFGC, &gcfgc);
|
|
|
-
|
|
|
- switch (gcfgc & GC_DISPLAY_CLOCK_MASK) {
|
|
|
- case GC_DISPLAY_CLOCK_267_MHZ_PNV:
|
|
|
- return 266667;
|
|
|
- case GC_DISPLAY_CLOCK_333_MHZ_PNV:
|
|
|
- return 333333;
|
|
|
- case GC_DISPLAY_CLOCK_444_MHZ_PNV:
|
|
|
- return 444444;
|
|
|
- case GC_DISPLAY_CLOCK_200_MHZ_PNV:
|
|
|
- return 200000;
|
|
|
- default:
|
|
|
- DRM_ERROR("Unknown pnv display core clock 0x%04x\n", gcfgc);
|
|
|
- case GC_DISPLAY_CLOCK_133_MHZ_PNV:
|
|
|
- return 133333;
|
|
|
- case GC_DISPLAY_CLOCK_167_MHZ_PNV:
|
|
|
- return 166667;
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-static int i915gm_get_display_clock_speed(struct drm_i915_private *dev_priv)
|
|
|
-{
|
|
|
- struct pci_dev *pdev = dev_priv->drm.pdev;
|
|
|
- u16 gcfgc = 0;
|
|
|
-
|
|
|
- pci_read_config_word(pdev, GCFGC, &gcfgc);
|
|
|
-
|
|
|
- if (gcfgc & GC_LOW_FREQUENCY_ENABLE)
|
|
|
- return 133333;
|
|
|
- else {
|
|
|
- switch (gcfgc & GC_DISPLAY_CLOCK_MASK) {
|
|
|
- case GC_DISPLAY_CLOCK_333_MHZ:
|
|
|
- return 333333;
|
|
|
- default:
|
|
|
- case GC_DISPLAY_CLOCK_190_200_MHZ:
|
|
|
- return 190000;
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-static int i865_get_display_clock_speed(struct drm_i915_private *dev_priv)
|
|
|
+static bool intel_crtc_supports_double_wide(const struct intel_crtc *crtc)
|
|
|
{
|
|
|
- return 266667;
|
|
|
+ const struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
|
|
|
+
|
|
|
+ /* GDG double wide on either pipe, otherwise pipe A only */
|
|
|
+ return INTEL_INFO(dev_priv)->gen < 4 &&
|
|
|
+ (crtc->pipe == PIPE_A || IS_I915G(dev_priv));
|
|
|
}
|
|
|
|
|
|
-static int i85x_get_display_clock_speed(struct drm_i915_private *dev_priv)
|
|
|
+static uint32_t ilk_pipe_pixel_rate(const struct intel_crtc_state *pipe_config)
|
|
|
{
|
|
|
- struct pci_dev *pdev = dev_priv->drm.pdev;
|
|
|
- u16 hpllcc = 0;
|
|
|
+ uint32_t pixel_rate;
|
|
|
+
|
|
|
+ pixel_rate = pipe_config->base.adjusted_mode.crtc_clock;
|
|
|
|
|
|
/*
|
|
|
- * 852GM/852GMV only supports 133 MHz and the HPLLCC
|
|
|
- * encoding is different :(
|
|
|
- * FIXME is this the right way to detect 852GM/852GMV?
|
|
|
+ * We only use IF-ID interlacing. If we ever use
|
|
|
+ * PF-ID we'll need to adjust the pixel_rate here.
|
|
|
*/
|
|
|
- if (pdev->revision == 0x1)
|
|
|
- return 133333;
|
|
|
|
|
|
- pci_bus_read_config_word(pdev->bus,
|
|
|
- PCI_DEVFN(0, 3), HPLLCC, &hpllcc);
|
|
|
+ if (pipe_config->pch_pfit.enabled) {
|
|
|
+ uint64_t pipe_w, pipe_h, pfit_w, pfit_h;
|
|
|
+ uint32_t pfit_size = pipe_config->pch_pfit.size;
|
|
|
|
|
|
- /* Assume that the hardware is in the high speed state. This
|
|
|
- * should be the default.
|
|
|
- */
|
|
|
- switch (hpllcc & GC_CLOCK_CONTROL_MASK) {
|
|
|
- case GC_CLOCK_133_200:
|
|
|
- case GC_CLOCK_133_200_2:
|
|
|
- case GC_CLOCK_100_200:
|
|
|
- return 200000;
|
|
|
- case GC_CLOCK_166_250:
|
|
|
- return 250000;
|
|
|
- case GC_CLOCK_100_133:
|
|
|
- return 133333;
|
|
|
- case GC_CLOCK_133_266:
|
|
|
- case GC_CLOCK_133_266_2:
|
|
|
- case GC_CLOCK_166_266:
|
|
|
- return 266667;
|
|
|
- }
|
|
|
-
|
|
|
- /* Shouldn't happen */
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
-static int i830_get_display_clock_speed(struct drm_i915_private *dev_priv)
|
|
|
-{
|
|
|
- return 133333;
|
|
|
-}
|
|
|
+ pipe_w = pipe_config->pipe_src_w;
|
|
|
+ pipe_h = pipe_config->pipe_src_h;
|
|
|
|
|
|
-static unsigned int intel_hpll_vco(struct drm_i915_private *dev_priv)
|
|
|
-{
|
|
|
- static const unsigned int blb_vco[8] = {
|
|
|
- [0] = 3200000,
|
|
|
- [1] = 4000000,
|
|
|
- [2] = 5333333,
|
|
|
- [3] = 4800000,
|
|
|
- [4] = 6400000,
|
|
|
- };
|
|
|
- static const unsigned int pnv_vco[8] = {
|
|
|
- [0] = 3200000,
|
|
|
- [1] = 4000000,
|
|
|
- [2] = 5333333,
|
|
|
- [3] = 4800000,
|
|
|
- [4] = 2666667,
|
|
|
- };
|
|
|
- static const unsigned int cl_vco[8] = {
|
|
|
- [0] = 3200000,
|
|
|
- [1] = 4000000,
|
|
|
- [2] = 5333333,
|
|
|
- [3] = 6400000,
|
|
|
- [4] = 3333333,
|
|
|
- [5] = 3566667,
|
|
|
- [6] = 4266667,
|
|
|
- };
|
|
|
- static const unsigned int elk_vco[8] = {
|
|
|
- [0] = 3200000,
|
|
|
- [1] = 4000000,
|
|
|
- [2] = 5333333,
|
|
|
- [3] = 4800000,
|
|
|
- };
|
|
|
- static const unsigned int ctg_vco[8] = {
|
|
|
- [0] = 3200000,
|
|
|
- [1] = 4000000,
|
|
|
- [2] = 5333333,
|
|
|
- [3] = 6400000,
|
|
|
- [4] = 2666667,
|
|
|
- [5] = 4266667,
|
|
|
- };
|
|
|
- const unsigned int *vco_table;
|
|
|
- unsigned int vco;
|
|
|
- uint8_t tmp = 0;
|
|
|
-
|
|
|
- /* FIXME other chipsets? */
|
|
|
- if (IS_GM45(dev_priv))
|
|
|
- vco_table = ctg_vco;
|
|
|
- else if (IS_G4X(dev_priv))
|
|
|
- vco_table = elk_vco;
|
|
|
- else if (IS_I965GM(dev_priv))
|
|
|
- vco_table = cl_vco;
|
|
|
- else if (IS_PINEVIEW(dev_priv))
|
|
|
- vco_table = pnv_vco;
|
|
|
- else if (IS_G33(dev_priv))
|
|
|
- vco_table = blb_vco;
|
|
|
- else
|
|
|
- return 0;
|
|
|
+ pfit_w = (pfit_size >> 16) & 0xFFFF;
|
|
|
+ pfit_h = pfit_size & 0xFFFF;
|
|
|
+ if (pipe_w < pfit_w)
|
|
|
+ pipe_w = pfit_w;
|
|
|
+ if (pipe_h < pfit_h)
|
|
|
+ pipe_h = pfit_h;
|
|
|
|
|
|
- tmp = I915_READ(IS_MOBILE(dev_priv) ? HPLLVCO_MOBILE : HPLLVCO);
|
|
|
+ if (WARN_ON(!pfit_w || !pfit_h))
|
|
|
+ return pixel_rate;
|
|
|
|
|
|
- vco = vco_table[tmp & 0x7];
|
|
|
- if (vco == 0)
|
|
|
- DRM_ERROR("Bad HPLL VCO (HPLLVCO=0x%02x)\n", tmp);
|
|
|
- else
|
|
|
- DRM_DEBUG_KMS("HPLL VCO %u kHz\n", vco);
|
|
|
+ pixel_rate = div_u64((uint64_t) pixel_rate * pipe_w * pipe_h,
|
|
|
+ pfit_w * pfit_h);
|
|
|
+ }
|
|
|
|
|
|
- return vco;
|
|
|
+ return pixel_rate;
|
|
|
}
|
|
|
|
|
|
-static int gm45_get_display_clock_speed(struct drm_i915_private *dev_priv)
|
|
|
+static void intel_crtc_compute_pixel_rate(struct intel_crtc_state *crtc_state)
|
|
|
{
|
|
|
- struct pci_dev *pdev = dev_priv->drm.pdev;
|
|
|
- unsigned int cdclk_sel, vco = intel_hpll_vco(dev_priv);
|
|
|
- uint16_t tmp = 0;
|
|
|
-
|
|
|
- pci_read_config_word(pdev, GCFGC, &tmp);
|
|
|
-
|
|
|
- cdclk_sel = (tmp >> 12) & 0x1;
|
|
|
+ struct drm_i915_private *dev_priv = to_i915(crtc_state->base.crtc->dev);
|
|
|
|
|
|
- switch (vco) {
|
|
|
- case 2666667:
|
|
|
- case 4000000:
|
|
|
- case 5333333:
|
|
|
- return cdclk_sel ? 333333 : 222222;
|
|
|
- case 3200000:
|
|
|
- return cdclk_sel ? 320000 : 228571;
|
|
|
- default:
|
|
|
- DRM_ERROR("Unable to determine CDCLK. HPLL VCO=%u, CFGC=0x%04x\n", vco, tmp);
|
|
|
- return 222222;
|
|
|
- }
|
|
|
+ if (HAS_GMCH_DISPLAY(dev_priv))
|
|
|
+ /* FIXME calculate proper pipe pixel rate for GMCH pfit */
|
|
|
+ crtc_state->pixel_rate =
|
|
|
+ crtc_state->base.adjusted_mode.crtc_clock;
|
|
|
+ else
|
|
|
+ crtc_state->pixel_rate =
|
|
|
+ ilk_pipe_pixel_rate(crtc_state);
|
|
|
}
|
|
|
|
|
|
-static int i965gm_get_display_clock_speed(struct drm_i915_private *dev_priv)
|
|
|
+static int intel_crtc_compute_config(struct intel_crtc *crtc,
|
|
|
+ struct intel_crtc_state *pipe_config)
|
|
|
{
|
|
|
- struct pci_dev *pdev = dev_priv->drm.pdev;
|
|
|
- static const uint8_t div_3200[] = { 16, 10, 8 };
|
|
|
- static const uint8_t div_4000[] = { 20, 12, 10 };
|
|
|
- static const uint8_t div_5333[] = { 24, 16, 14 };
|
|
|
- const uint8_t *div_table;
|
|
|
- unsigned int cdclk_sel, vco = intel_hpll_vco(dev_priv);
|
|
|
- uint16_t tmp = 0;
|
|
|
-
|
|
|
- pci_read_config_word(pdev, GCFGC, &tmp);
|
|
|
-
|
|
|
- cdclk_sel = ((tmp >> 8) & 0x1f) - 1;
|
|
|
+ struct drm_device *dev = crtc->base.dev;
|
|
|
+ struct drm_i915_private *dev_priv = to_i915(dev);
|
|
|
+ const struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode;
|
|
|
+ int clock_limit = dev_priv->max_dotclk_freq;
|
|
|
|
|
|
- if (cdclk_sel >= ARRAY_SIZE(div_3200))
|
|
|
- goto fail;
|
|
|
+ if (INTEL_GEN(dev_priv) < 4) {
|
|
|
+ clock_limit = dev_priv->max_cdclk_freq * 9 / 10;
|
|
|
|
|
|
- switch (vco) {
|
|
|
- case 3200000:
|
|
|
- div_table = div_3200;
|
|
|
- break;
|
|
|
- case 4000000:
|
|
|
- div_table = div_4000;
|
|
|
- break;
|
|
|
- case 5333333:
|
|
|
- div_table = div_5333;
|
|
|
- break;
|
|
|
- default:
|
|
|
- goto fail;
|
|
|
+ /*
|
|
|
+ * Enable double wide mode when the dot clock
|
|
|
+ * is > 90% of the (display) core speed.
|
|
|
+ */
|
|
|
+ if (intel_crtc_supports_double_wide(crtc) &&
|
|
|
+ adjusted_mode->crtc_clock > clock_limit) {
|
|
|
+ clock_limit = dev_priv->max_dotclk_freq;
|
|
|
+ pipe_config->double_wide = true;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
- return DIV_ROUND_CLOSEST(vco, div_table[cdclk_sel]);
|
|
|
-
|
|
|
-fail:
|
|
|
- DRM_ERROR("Unable to determine CDCLK. HPLL VCO=%u kHz, CFGC=0x%04x\n", vco, tmp);
|
|
|
- return 200000;
|
|
|
-}
|
|
|
-
|
|
|
-static int g33_get_display_clock_speed(struct drm_i915_private *dev_priv)
|
|
|
-{
|
|
|
- struct pci_dev *pdev = dev_priv->drm.pdev;
|
|
|
- static const uint8_t div_3200[] = { 12, 10, 8, 7, 5, 16 };
|
|
|
- static const uint8_t div_4000[] = { 14, 12, 10, 8, 6, 20 };
|
|
|
- static const uint8_t div_4800[] = { 20, 14, 12, 10, 8, 24 };
|
|
|
- static const uint8_t div_5333[] = { 20, 16, 12, 12, 8, 28 };
|
|
|
- const uint8_t *div_table;
|
|
|
- unsigned int cdclk_sel, vco = intel_hpll_vco(dev_priv);
|
|
|
- uint16_t tmp = 0;
|
|
|
+ if (adjusted_mode->crtc_clock > clock_limit) {
|
|
|
+ DRM_DEBUG_KMS("requested pixel clock (%d kHz) too high (max: %d kHz, double wide: %s)\n",
|
|
|
+ adjusted_mode->crtc_clock, clock_limit,
|
|
|
+ yesno(pipe_config->double_wide));
|
|
|
+ return -EINVAL;
|
|
|
+ }
|
|
|
|
|
|
- pci_read_config_word(pdev, GCFGC, &tmp);
|
|
|
+ /*
|
|
|
+ * Pipe horizontal size must be even in:
|
|
|
+ * - DVO ganged mode
|
|
|
+ * - LVDS dual channel mode
|
|
|
+ * - Double wide pipe
|
|
|
+ */
|
|
|
+ if ((intel_crtc_has_type(pipe_config, INTEL_OUTPUT_LVDS) &&
|
|
|
+ intel_is_dual_link_lvds(dev)) || pipe_config->double_wide)
|
|
|
+ pipe_config->pipe_src_w &= ~1;
|
|
|
|
|
|
- cdclk_sel = (tmp >> 4) & 0x7;
|
|
|
+ /* Cantiga+ cannot handle modes with a hsync front porch of 0.
|
|
|
+ * WaPruneModeWithIncorrectHsyncOffset:ctg,elk,ilk,snb,ivb,vlv,hsw.
|
|
|
+ */
|
|
|
+ if ((INTEL_GEN(dev_priv) > 4 || IS_G4X(dev_priv)) &&
|
|
|
+ adjusted_mode->crtc_hsync_start == adjusted_mode->crtc_hdisplay)
|
|
|
+ return -EINVAL;
|
|
|
|
|
|
- if (cdclk_sel >= ARRAY_SIZE(div_3200))
|
|
|
- goto fail;
|
|
|
+ intel_crtc_compute_pixel_rate(pipe_config);
|
|
|
|
|
|
- switch (vco) {
|
|
|
- case 3200000:
|
|
|
- div_table = div_3200;
|
|
|
- break;
|
|
|
- case 4000000:
|
|
|
- div_table = div_4000;
|
|
|
- break;
|
|
|
- case 4800000:
|
|
|
- div_table = div_4800;
|
|
|
- break;
|
|
|
- case 5333333:
|
|
|
- div_table = div_5333;
|
|
|
- break;
|
|
|
- default:
|
|
|
- goto fail;
|
|
|
- }
|
|
|
+ if (HAS_IPS(dev_priv))
|
|
|
+ hsw_compute_ips_config(crtc, pipe_config);
|
|
|
|
|
|
- return DIV_ROUND_CLOSEST(vco, div_table[cdclk_sel]);
|
|
|
+ if (pipe_config->has_pch_encoder)
|
|
|
+ return ironlake_fdi_compute_config(crtc, pipe_config);
|
|
|
|
|
|
-fail:
|
|
|
- DRM_ERROR("Unable to determine CDCLK. HPLL VCO=%u kHz, CFGC=0x%08x\n", vco, tmp);
|
|
|
- return 190476;
|
|
|
+ return 0;
|
|
|
}
|
|
|
|
|
|
static void
|
|
|
@@ -8768,7 +7388,8 @@ i9xx_get_initial_plane_config(struct intel_crtc *crtc,
|
|
|
val = I915_READ(DSPSTRIDE(pipe));
|
|
|
fb->pitches[0] = val & 0xffffffc0;
|
|
|
|
|
|
- aligned_height = intel_fb_align_height(dev, fb->height,
|
|
|
+ aligned_height = intel_fb_align_height(dev_priv,
|
|
|
+ fb->height,
|
|
|
fb->format->format,
|
|
|
fb->modifier);
|
|
|
|
|
|
@@ -9809,7 +8430,8 @@ skylake_get_initial_plane_config(struct intel_crtc *crtc,
|
|
|
fb->format->format);
|
|
|
fb->pitches[0] = (val & 0x3ff) * stride_mult;
|
|
|
|
|
|
- aligned_height = intel_fb_align_height(dev, fb->height,
|
|
|
+ aligned_height = intel_fb_align_height(dev_priv,
|
|
|
+ fb->height,
|
|
|
fb->format->format,
|
|
|
fb->modifier);
|
|
|
|
|
|
@@ -9907,7 +8529,8 @@ ironlake_get_initial_plane_config(struct intel_crtc *crtc,
|
|
|
val = I915_READ(DSPSTRIDE(pipe));
|
|
|
fb->pitches[0] = val & 0xffffffc0;
|
|
|
|
|
|
- aligned_height = intel_fb_align_height(dev, fb->height,
|
|
|
+ aligned_height = intel_fb_align_height(dev_priv,
|
|
|
+ fb->height,
|
|
|
fb->format->format,
|
|
|
fb->modifier);
|
|
|
|
|
|
@@ -10166,312 +8789,73 @@ static void hsw_restore_lcpll(struct drm_i915_private *dev_priv)
|
|
|
5))
|
|
|
DRM_ERROR("LCPLL not locked yet\n");
|
|
|
|
|
|
- if (val & LCPLL_CD_SOURCE_FCLK) {
|
|
|
- val = I915_READ(LCPLL_CTL);
|
|
|
- val &= ~LCPLL_CD_SOURCE_FCLK;
|
|
|
- I915_WRITE(LCPLL_CTL, val);
|
|
|
-
|
|
|
- if (wait_for_us((I915_READ(LCPLL_CTL) &
|
|
|
- LCPLL_CD_SOURCE_FCLK_DONE) == 0, 1))
|
|
|
- DRM_ERROR("Switching back to LCPLL failed\n");
|
|
|
- }
|
|
|
-
|
|
|
- intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL);
|
|
|
- intel_update_cdclk(dev_priv);
|
|
|
-}
|
|
|
-
|
|
|
-/*
|
|
|
- * Package states C8 and deeper are really deep PC states that can only be
|
|
|
- * reached when all the devices on the system allow it, so even if the graphics
|
|
|
- * device allows PC8+, it doesn't mean the system will actually get to these
|
|
|
- * states. Our driver only allows PC8+ when going into runtime PM.
|
|
|
- *
|
|
|
- * The requirements for PC8+ are that all the outputs are disabled, the power
|
|
|
- * well is disabled and most interrupts are disabled, and these are also
|
|
|
- * requirements for runtime PM. When these conditions are met, we manually do
|
|
|
- * the other conditions: disable the interrupts, clocks and switch LCPLL refclk
|
|
|
- * to Fclk. If we're in PC8+ and we get an non-hotplug interrupt, we can hard
|
|
|
- * hang the machine.
|
|
|
- *
|
|
|
- * When we really reach PC8 or deeper states (not just when we allow it) we lose
|
|
|
- * the state of some registers, so when we come back from PC8+ we need to
|
|
|
- * restore this state. We don't get into PC8+ if we're not in RC6, so we don't
|
|
|
- * need to take care of the registers kept by RC6. Notice that this happens even
|
|
|
- * if we don't put the device in PCI D3 state (which is what currently happens
|
|
|
- * because of the runtime PM support).
|
|
|
- *
|
|
|
- * For more, read "Display Sequences for Package C8" on the hardware
|
|
|
- * documentation.
|
|
|
- */
|
|
|
-void hsw_enable_pc8(struct drm_i915_private *dev_priv)
|
|
|
-{
|
|
|
- uint32_t val;
|
|
|
-
|
|
|
- DRM_DEBUG_KMS("Enabling package C8+\n");
|
|
|
-
|
|
|
- if (HAS_PCH_LPT_LP(dev_priv)) {
|
|
|
- val = I915_READ(SOUTH_DSPCLK_GATE_D);
|
|
|
- val &= ~PCH_LP_PARTITION_LEVEL_DISABLE;
|
|
|
- I915_WRITE(SOUTH_DSPCLK_GATE_D, val);
|
|
|
- }
|
|
|
-
|
|
|
- lpt_disable_clkout_dp(dev_priv);
|
|
|
- hsw_disable_lcpll(dev_priv, true, true);
|
|
|
-}
|
|
|
-
|
|
|
-void hsw_disable_pc8(struct drm_i915_private *dev_priv)
|
|
|
-{
|
|
|
- uint32_t val;
|
|
|
-
|
|
|
- DRM_DEBUG_KMS("Disabling package C8+\n");
|
|
|
-
|
|
|
- hsw_restore_lcpll(dev_priv);
|
|
|
- lpt_init_pch_refclk(dev_priv);
|
|
|
-
|
|
|
- if (HAS_PCH_LPT_LP(dev_priv)) {
|
|
|
- val = I915_READ(SOUTH_DSPCLK_GATE_D);
|
|
|
- val |= PCH_LP_PARTITION_LEVEL_DISABLE;
|
|
|
- I915_WRITE(SOUTH_DSPCLK_GATE_D, val);
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-static void bxt_modeset_commit_cdclk(struct drm_atomic_state *old_state)
|
|
|
-{
|
|
|
- struct drm_device *dev = old_state->dev;
|
|
|
- struct intel_atomic_state *old_intel_state =
|
|
|
- to_intel_atomic_state(old_state);
|
|
|
- unsigned int req_cdclk = old_intel_state->dev_cdclk;
|
|
|
-
|
|
|
- bxt_set_cdclk(to_i915(dev), req_cdclk);
|
|
|
-}
|
|
|
-
|
|
|
-static int bdw_adjust_min_pipe_pixel_rate(struct intel_crtc_state *crtc_state,
|
|
|
- int pixel_rate)
|
|
|
-{
|
|
|
- struct drm_i915_private *dev_priv = to_i915(crtc_state->base.crtc->dev);
|
|
|
-
|
|
|
- /* pixel rate mustn't exceed 95% of cdclk with IPS on BDW */
|
|
|
- if (IS_BROADWELL(dev_priv) && crtc_state->ips_enabled)
|
|
|
- pixel_rate = DIV_ROUND_UP(pixel_rate * 100, 95);
|
|
|
-
|
|
|
- /* BSpec says "Do not use DisplayPort with CDCLK less than
|
|
|
- * 432 MHz, audio enabled, port width x4, and link rate
|
|
|
- * HBR2 (5.4 GHz), or else there may be audio corruption or
|
|
|
- * screen corruption."
|
|
|
- */
|
|
|
- if (intel_crtc_has_dp_encoder(crtc_state) &&
|
|
|
- crtc_state->has_audio &&
|
|
|
- crtc_state->port_clock >= 540000 &&
|
|
|
- crtc_state->lane_count == 4)
|
|
|
- pixel_rate = max(432000, pixel_rate);
|
|
|
-
|
|
|
- return pixel_rate;
|
|
|
-}
|
|
|
-
|
|
|
-/* compute the max rate for new configuration */
|
|
|
-static int ilk_max_pixel_rate(struct drm_atomic_state *state)
|
|
|
-{
|
|
|
- struct intel_atomic_state *intel_state = to_intel_atomic_state(state);
|
|
|
- struct drm_i915_private *dev_priv = to_i915(state->dev);
|
|
|
- struct drm_crtc *crtc;
|
|
|
- struct drm_crtc_state *cstate;
|
|
|
- struct intel_crtc_state *crtc_state;
|
|
|
- unsigned max_pixel_rate = 0, i;
|
|
|
- enum pipe pipe;
|
|
|
-
|
|
|
- memcpy(intel_state->min_pixclk, dev_priv->min_pixclk,
|
|
|
- sizeof(intel_state->min_pixclk));
|
|
|
-
|
|
|
- for_each_crtc_in_state(state, crtc, cstate, i) {
|
|
|
- int pixel_rate;
|
|
|
-
|
|
|
- crtc_state = to_intel_crtc_state(cstate);
|
|
|
- if (!crtc_state->base.enable) {
|
|
|
- intel_state->min_pixclk[i] = 0;
|
|
|
- continue;
|
|
|
- }
|
|
|
-
|
|
|
- pixel_rate = ilk_pipe_pixel_rate(crtc_state);
|
|
|
-
|
|
|
- if (IS_BROADWELL(dev_priv) || IS_GEN9(dev_priv))
|
|
|
- pixel_rate = bdw_adjust_min_pipe_pixel_rate(crtc_state,
|
|
|
- pixel_rate);
|
|
|
-
|
|
|
- intel_state->min_pixclk[i] = pixel_rate;
|
|
|
- }
|
|
|
-
|
|
|
- for_each_pipe(dev_priv, pipe)
|
|
|
- max_pixel_rate = max(intel_state->min_pixclk[pipe], max_pixel_rate);
|
|
|
-
|
|
|
- return max_pixel_rate;
|
|
|
-}
|
|
|
-
|
|
|
-static void broadwell_set_cdclk(struct drm_device *dev, int cdclk)
|
|
|
-{
|
|
|
- struct drm_i915_private *dev_priv = to_i915(dev);
|
|
|
- uint32_t val, data;
|
|
|
- int ret;
|
|
|
-
|
|
|
- if (WARN((I915_READ(LCPLL_CTL) &
|
|
|
- (LCPLL_PLL_DISABLE | LCPLL_PLL_LOCK |
|
|
|
- LCPLL_CD_CLOCK_DISABLE | LCPLL_ROOT_CD_CLOCK_DISABLE |
|
|
|
- LCPLL_CD2X_CLOCK_DISABLE | LCPLL_POWER_DOWN_ALLOW |
|
|
|
- LCPLL_CD_SOURCE_FCLK)) != LCPLL_PLL_LOCK,
|
|
|
- "trying to change cdclk frequency with cdclk not enabled\n"))
|
|
|
- return;
|
|
|
-
|
|
|
- mutex_lock(&dev_priv->rps.hw_lock);
|
|
|
- ret = sandybridge_pcode_write(dev_priv,
|
|
|
- BDW_PCODE_DISPLAY_FREQ_CHANGE_REQ, 0x0);
|
|
|
- mutex_unlock(&dev_priv->rps.hw_lock);
|
|
|
- if (ret) {
|
|
|
- DRM_ERROR("failed to inform pcode about cdclk change\n");
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- val = I915_READ(LCPLL_CTL);
|
|
|
- val |= LCPLL_CD_SOURCE_FCLK;
|
|
|
- I915_WRITE(LCPLL_CTL, val);
|
|
|
-
|
|
|
- if (wait_for_us(I915_READ(LCPLL_CTL) &
|
|
|
- LCPLL_CD_SOURCE_FCLK_DONE, 1))
|
|
|
- DRM_ERROR("Switching to FCLK failed\n");
|
|
|
-
|
|
|
- val = I915_READ(LCPLL_CTL);
|
|
|
- val &= ~LCPLL_CLK_FREQ_MASK;
|
|
|
-
|
|
|
- switch (cdclk) {
|
|
|
- case 450000:
|
|
|
- val |= LCPLL_CLK_FREQ_450;
|
|
|
- data = 0;
|
|
|
- break;
|
|
|
- case 540000:
|
|
|
- val |= LCPLL_CLK_FREQ_54O_BDW;
|
|
|
- data = 1;
|
|
|
- break;
|
|
|
- case 337500:
|
|
|
- val |= LCPLL_CLK_FREQ_337_5_BDW;
|
|
|
- data = 2;
|
|
|
- break;
|
|
|
- case 675000:
|
|
|
- val |= LCPLL_CLK_FREQ_675_BDW;
|
|
|
- data = 3;
|
|
|
- break;
|
|
|
- default:
|
|
|
- WARN(1, "invalid cdclk frequency\n");
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- I915_WRITE(LCPLL_CTL, val);
|
|
|
-
|
|
|
- val = I915_READ(LCPLL_CTL);
|
|
|
- val &= ~LCPLL_CD_SOURCE_FCLK;
|
|
|
- I915_WRITE(LCPLL_CTL, val);
|
|
|
-
|
|
|
- if (wait_for_us((I915_READ(LCPLL_CTL) &
|
|
|
- LCPLL_CD_SOURCE_FCLK_DONE) == 0, 1))
|
|
|
- DRM_ERROR("Switching back to LCPLL failed\n");
|
|
|
-
|
|
|
- mutex_lock(&dev_priv->rps.hw_lock);
|
|
|
- sandybridge_pcode_write(dev_priv, HSW_PCODE_DE_WRITE_FREQ_REQ, data);
|
|
|
- mutex_unlock(&dev_priv->rps.hw_lock);
|
|
|
-
|
|
|
- I915_WRITE(CDCLK_FREQ, DIV_ROUND_CLOSEST(cdclk, 1000) - 1);
|
|
|
-
|
|
|
- intel_update_cdclk(dev_priv);
|
|
|
-
|
|
|
- WARN(cdclk != dev_priv->cdclk_freq,
|
|
|
- "cdclk requested %d kHz but got %d kHz\n",
|
|
|
- cdclk, dev_priv->cdclk_freq);
|
|
|
-}
|
|
|
-
|
|
|
-static int broadwell_calc_cdclk(int max_pixclk)
|
|
|
-{
|
|
|
- if (max_pixclk > 540000)
|
|
|
- return 675000;
|
|
|
- else if (max_pixclk > 450000)
|
|
|
- return 540000;
|
|
|
- else if (max_pixclk > 337500)
|
|
|
- return 450000;
|
|
|
- else
|
|
|
- return 337500;
|
|
|
-}
|
|
|
-
|
|
|
-static int broadwell_modeset_calc_cdclk(struct drm_atomic_state *state)
|
|
|
-{
|
|
|
- struct drm_i915_private *dev_priv = to_i915(state->dev);
|
|
|
- struct intel_atomic_state *intel_state = to_intel_atomic_state(state);
|
|
|
- int max_pixclk = ilk_max_pixel_rate(state);
|
|
|
- int cdclk;
|
|
|
-
|
|
|
- /*
|
|
|
- * FIXME should also account for plane ratio
|
|
|
- * once 64bpp pixel formats are supported.
|
|
|
- */
|
|
|
- cdclk = broadwell_calc_cdclk(max_pixclk);
|
|
|
-
|
|
|
- if (cdclk > dev_priv->max_cdclk_freq) {
|
|
|
- DRM_DEBUG_KMS("requested cdclk (%d kHz) exceeds max (%d kHz)\n",
|
|
|
- cdclk, dev_priv->max_cdclk_freq);
|
|
|
- return -EINVAL;
|
|
|
- }
|
|
|
-
|
|
|
- intel_state->cdclk = intel_state->dev_cdclk = cdclk;
|
|
|
- if (!intel_state->active_crtcs)
|
|
|
- intel_state->dev_cdclk = broadwell_calc_cdclk(0);
|
|
|
-
|
|
|
- return 0;
|
|
|
-}
|
|
|
+ if (val & LCPLL_CD_SOURCE_FCLK) {
|
|
|
+ val = I915_READ(LCPLL_CTL);
|
|
|
+ val &= ~LCPLL_CD_SOURCE_FCLK;
|
|
|
+ I915_WRITE(LCPLL_CTL, val);
|
|
|
|
|
|
-static void broadwell_modeset_commit_cdclk(struct drm_atomic_state *old_state)
|
|
|
-{
|
|
|
- struct drm_device *dev = old_state->dev;
|
|
|
- struct intel_atomic_state *old_intel_state =
|
|
|
- to_intel_atomic_state(old_state);
|
|
|
- unsigned req_cdclk = old_intel_state->dev_cdclk;
|
|
|
+ if (wait_for_us((I915_READ(LCPLL_CTL) &
|
|
|
+ LCPLL_CD_SOURCE_FCLK_DONE) == 0, 1))
|
|
|
+ DRM_ERROR("Switching back to LCPLL failed\n");
|
|
|
+ }
|
|
|
|
|
|
- broadwell_set_cdclk(dev, req_cdclk);
|
|
|
+ intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL);
|
|
|
+ intel_update_cdclk(dev_priv);
|
|
|
}
|
|
|
|
|
|
-static int skl_modeset_calc_cdclk(struct drm_atomic_state *state)
|
|
|
+/*
|
|
|
+ * Package states C8 and deeper are really deep PC states that can only be
|
|
|
+ * reached when all the devices on the system allow it, so even if the graphics
|
|
|
+ * device allows PC8+, it doesn't mean the system will actually get to these
|
|
|
+ * states. Our driver only allows PC8+ when going into runtime PM.
|
|
|
+ *
|
|
|
+ * The requirements for PC8+ are that all the outputs are disabled, the power
|
|
|
+ * well is disabled and most interrupts are disabled, and these are also
|
|
|
+ * requirements for runtime PM. When these conditions are met, we manually do
|
|
|
+ * the other conditions: disable the interrupts, clocks and switch LCPLL refclk
|
|
|
+ * to Fclk. If we're in PC8+ and we get an non-hotplug interrupt, we can hard
|
|
|
+ * hang the machine.
|
|
|
+ *
|
|
|
+ * When we really reach PC8 or deeper states (not just when we allow it) we lose
|
|
|
+ * the state of some registers, so when we come back from PC8+ we need to
|
|
|
+ * restore this state. We don't get into PC8+ if we're not in RC6, so we don't
|
|
|
+ * need to take care of the registers kept by RC6. Notice that this happens even
|
|
|
+ * if we don't put the device in PCI D3 state (which is what currently happens
|
|
|
+ * because of the runtime PM support).
|
|
|
+ *
|
|
|
+ * For more, read "Display Sequences for Package C8" on the hardware
|
|
|
+ * documentation.
|
|
|
+ */
|
|
|
+void hsw_enable_pc8(struct drm_i915_private *dev_priv)
|
|
|
{
|
|
|
- struct intel_atomic_state *intel_state = to_intel_atomic_state(state);
|
|
|
- struct drm_i915_private *dev_priv = to_i915(state->dev);
|
|
|
- const int max_pixclk = ilk_max_pixel_rate(state);
|
|
|
- int vco = intel_state->cdclk_pll_vco;
|
|
|
- int cdclk;
|
|
|
+ uint32_t val;
|
|
|
|
|
|
- /*
|
|
|
- * FIXME should also account for plane ratio
|
|
|
- * once 64bpp pixel formats are supported.
|
|
|
- */
|
|
|
- cdclk = skl_calc_cdclk(max_pixclk, vco);
|
|
|
+ DRM_DEBUG_KMS("Enabling package C8+\n");
|
|
|
|
|
|
- /*
|
|
|
- * FIXME move the cdclk caclulation to
|
|
|
- * compute_config() so we can fail gracegully.
|
|
|
- */
|
|
|
- if (cdclk > dev_priv->max_cdclk_freq) {
|
|
|
- DRM_ERROR("requested cdclk (%d kHz) exceeds max (%d kHz)\n",
|
|
|
- cdclk, dev_priv->max_cdclk_freq);
|
|
|
- cdclk = dev_priv->max_cdclk_freq;
|
|
|
+ if (HAS_PCH_LPT_LP(dev_priv)) {
|
|
|
+ val = I915_READ(SOUTH_DSPCLK_GATE_D);
|
|
|
+ val &= ~PCH_LP_PARTITION_LEVEL_DISABLE;
|
|
|
+ I915_WRITE(SOUTH_DSPCLK_GATE_D, val);
|
|
|
}
|
|
|
|
|
|
- intel_state->cdclk = intel_state->dev_cdclk = cdclk;
|
|
|
- if (!intel_state->active_crtcs)
|
|
|
- intel_state->dev_cdclk = skl_calc_cdclk(0, vco);
|
|
|
-
|
|
|
- return 0;
|
|
|
+ lpt_disable_clkout_dp(dev_priv);
|
|
|
+ hsw_disable_lcpll(dev_priv, true, true);
|
|
|
}
|
|
|
|
|
|
-static void skl_modeset_commit_cdclk(struct drm_atomic_state *old_state)
|
|
|
+void hsw_disable_pc8(struct drm_i915_private *dev_priv)
|
|
|
{
|
|
|
- struct drm_i915_private *dev_priv = to_i915(old_state->dev);
|
|
|
- struct intel_atomic_state *intel_state = to_intel_atomic_state(old_state);
|
|
|
- unsigned int req_cdclk = intel_state->dev_cdclk;
|
|
|
- unsigned int req_vco = intel_state->cdclk_pll_vco;
|
|
|
+ uint32_t val;
|
|
|
+
|
|
|
+ DRM_DEBUG_KMS("Disabling package C8+\n");
|
|
|
+
|
|
|
+ hsw_restore_lcpll(dev_priv);
|
|
|
+ lpt_init_pch_refclk(dev_priv);
|
|
|
|
|
|
- skl_set_cdclk(dev_priv, req_cdclk, req_vco);
|
|
|
+ if (HAS_PCH_LPT_LP(dev_priv)) {
|
|
|
+ val = I915_READ(SOUTH_DSPCLK_GATE_D);
|
|
|
+ val |= PCH_LP_PARTITION_LEVEL_DISABLE;
|
|
|
+ I915_WRITE(SOUTH_DSPCLK_GATE_D, val);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
static int haswell_crtc_compute_clock(struct intel_crtc *crtc,
|
|
|
@@ -10565,7 +8949,7 @@ static void haswell_get_ddi_pll(struct drm_i915_private *dev_priv,
|
|
|
|
|
|
static bool hsw_get_transcoder_state(struct intel_crtc *crtc,
|
|
|
struct intel_crtc_state *pipe_config,
|
|
|
- unsigned long *power_domain_mask)
|
|
|
+ u64 *power_domain_mask)
|
|
|
{
|
|
|
struct drm_device *dev = crtc->base.dev;
|
|
|
struct drm_i915_private *dev_priv = to_i915(dev);
|
|
|
@@ -10607,7 +8991,7 @@ static bool hsw_get_transcoder_state(struct intel_crtc *crtc,
|
|
|
power_domain = POWER_DOMAIN_TRANSCODER(pipe_config->cpu_transcoder);
|
|
|
if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
|
|
|
return false;
|
|
|
- *power_domain_mask |= BIT(power_domain);
|
|
|
+ *power_domain_mask |= BIT_ULL(power_domain);
|
|
|
|
|
|
tmp = I915_READ(PIPECONF(pipe_config->cpu_transcoder));
|
|
|
|
|
|
@@ -10616,7 +9000,7 @@ static bool hsw_get_transcoder_state(struct intel_crtc *crtc,
|
|
|
|
|
|
static bool bxt_get_dsi_transcoder_state(struct intel_crtc *crtc,
|
|
|
struct intel_crtc_state *pipe_config,
|
|
|
- unsigned long *power_domain_mask)
|
|
|
+ u64 *power_domain_mask)
|
|
|
{
|
|
|
struct drm_device *dev = crtc->base.dev;
|
|
|
struct drm_i915_private *dev_priv = to_i915(dev);
|
|
|
@@ -10634,7 +9018,7 @@ static bool bxt_get_dsi_transcoder_state(struct intel_crtc *crtc,
|
|
|
power_domain = POWER_DOMAIN_TRANSCODER(cpu_transcoder);
|
|
|
if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
|
|
|
continue;
|
|
|
- *power_domain_mask |= BIT(power_domain);
|
|
|
+ *power_domain_mask |= BIT_ULL(power_domain);
|
|
|
|
|
|
/*
|
|
|
* The PLL needs to be enabled with a valid divider
|
|
|
@@ -10674,7 +9058,7 @@ static void haswell_get_ddi_port_state(struct intel_crtc *crtc,
|
|
|
|
|
|
port = (tmp & TRANS_DDI_PORT_MASK) >> TRANS_DDI_PORT_SHIFT;
|
|
|
|
|
|
- if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv))
|
|
|
+ if (IS_GEN9_BC(dev_priv))
|
|
|
skylake_get_ddi_pll(dev_priv, port, pipe_config);
|
|
|
else if (IS_GEN9_LP(dev_priv))
|
|
|
bxt_get_ddi_pll(dev_priv, port, pipe_config);
|
|
|
@@ -10709,13 +9093,13 @@ static bool haswell_get_pipe_config(struct intel_crtc *crtc,
|
|
|
{
|
|
|
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
|
|
|
enum intel_display_power_domain power_domain;
|
|
|
- unsigned long power_domain_mask;
|
|
|
+ u64 power_domain_mask;
|
|
|
bool active;
|
|
|
|
|
|
power_domain = POWER_DOMAIN_PIPE(crtc->pipe);
|
|
|
if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
|
|
|
return false;
|
|
|
- power_domain_mask = BIT(power_domain);
|
|
|
+ power_domain_mask = BIT_ULL(power_domain);
|
|
|
|
|
|
pipe_config->shared_dpll = NULL;
|
|
|
|
|
|
@@ -10749,7 +9133,7 @@ static bool haswell_get_pipe_config(struct intel_crtc *crtc,
|
|
|
|
|
|
power_domain = POWER_DOMAIN_PIPE_PANEL_FITTER(crtc->pipe);
|
|
|
if (intel_display_power_get_if_enabled(dev_priv, power_domain)) {
|
|
|
- power_domain_mask |= BIT(power_domain);
|
|
|
+ power_domain_mask |= BIT_ULL(power_domain);
|
|
|
if (INTEL_GEN(dev_priv) >= 9)
|
|
|
skylake_get_pfit_config(crtc, pipe_config);
|
|
|
else
|
|
|
@@ -10972,9 +9356,8 @@ static struct drm_display_mode load_detect_mode = {
|
|
|
};
|
|
|
|
|
|
struct drm_framebuffer *
|
|
|
-__intel_framebuffer_create(struct drm_device *dev,
|
|
|
- struct drm_mode_fb_cmd2 *mode_cmd,
|
|
|
- struct drm_i915_gem_object *obj)
|
|
|
+intel_framebuffer_create(struct drm_i915_gem_object *obj,
|
|
|
+ struct drm_mode_fb_cmd2 *mode_cmd)
|
|
|
{
|
|
|
struct intel_framebuffer *intel_fb;
|
|
|
int ret;
|
|
|
@@ -10983,7 +9366,7 @@ __intel_framebuffer_create(struct drm_device *dev,
|
|
|
if (!intel_fb)
|
|
|
return ERR_PTR(-ENOMEM);
|
|
|
|
|
|
- ret = intel_framebuffer_init(dev, intel_fb, mode_cmd, obj);
|
|
|
+ ret = intel_framebuffer_init(intel_fb, obj, mode_cmd);
|
|
|
if (ret)
|
|
|
goto err;
|
|
|
|
|
|
@@ -10994,23 +9377,6 @@ err:
|
|
|
return ERR_PTR(ret);
|
|
|
}
|
|
|
|
|
|
-static struct drm_framebuffer *
|
|
|
-intel_framebuffer_create(struct drm_device *dev,
|
|
|
- struct drm_mode_fb_cmd2 *mode_cmd,
|
|
|
- struct drm_i915_gem_object *obj)
|
|
|
-{
|
|
|
- struct drm_framebuffer *fb;
|
|
|
- int ret;
|
|
|
-
|
|
|
- ret = i915_mutex_lock_interruptible(dev);
|
|
|
- if (ret)
|
|
|
- return ERR_PTR(ret);
|
|
|
- fb = __intel_framebuffer_create(dev, mode_cmd, obj);
|
|
|
- mutex_unlock(&dev->struct_mutex);
|
|
|
-
|
|
|
- return fb;
|
|
|
-}
|
|
|
-
|
|
|
static u32
|
|
|
intel_framebuffer_pitch_for_width(int width, int bpp)
|
|
|
{
|
|
|
@@ -11045,7 +9411,7 @@ intel_framebuffer_create_for_mode(struct drm_device *dev,
|
|
|
bpp);
|
|
|
mode_cmd.pixel_format = drm_mode_legacy_fb_format(bpp, depth);
|
|
|
|
|
|
- fb = intel_framebuffer_create(dev, &mode_cmd, obj);
|
|
|
+ fb = intel_framebuffer_create(obj, &mode_cmd);
|
|
|
if (IS_ERR(fb))
|
|
|
i915_gem_object_put(obj);
|
|
|
|
|
|
@@ -11731,14 +10097,12 @@ static int intel_gen2_queue_flip(struct drm_device *dev,
|
|
|
struct drm_i915_gem_request *req,
|
|
|
uint32_t flags)
|
|
|
{
|
|
|
- struct intel_ring *ring = req->ring;
|
|
|
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
|
|
- u32 flip_mask;
|
|
|
- int ret;
|
|
|
+ u32 flip_mask, *cs;
|
|
|
|
|
|
- ret = intel_ring_begin(req, 6);
|
|
|
- if (ret)
|
|
|
- return ret;
|
|
|
+ cs = intel_ring_begin(req, 6);
|
|
|
+ if (IS_ERR(cs))
|
|
|
+ return PTR_ERR(cs);
|
|
|
|
|
|
/* Can't queue multiple flips, so wait for the previous
|
|
|
* one to finish before executing the next.
|
|
|
@@ -11747,13 +10111,12 @@ static int intel_gen2_queue_flip(struct drm_device *dev,
|
|
|
flip_mask = MI_WAIT_FOR_PLANE_B_FLIP;
|
|
|
else
|
|
|
flip_mask = MI_WAIT_FOR_PLANE_A_FLIP;
|
|
|
- intel_ring_emit(ring, MI_WAIT_FOR_EVENT | flip_mask);
|
|
|
- intel_ring_emit(ring, MI_NOOP);
|
|
|
- intel_ring_emit(ring, MI_DISPLAY_FLIP |
|
|
|
- MI_DISPLAY_FLIP_PLANE(intel_crtc->plane));
|
|
|
- intel_ring_emit(ring, fb->pitches[0]);
|
|
|
- intel_ring_emit(ring, intel_crtc->flip_work->gtt_offset);
|
|
|
- intel_ring_emit(ring, 0); /* aux display base address, unused */
|
|
|
+ *cs++ = MI_WAIT_FOR_EVENT | flip_mask;
|
|
|
+ *cs++ = MI_NOOP;
|
|
|
+ *cs++ = MI_DISPLAY_FLIP | MI_DISPLAY_FLIP_PLANE(intel_crtc->plane);
|
|
|
+ *cs++ = fb->pitches[0];
|
|
|
+ *cs++ = intel_crtc->flip_work->gtt_offset;
|
|
|
+ *cs++ = 0; /* aux display base address, unused */
|
|
|
|
|
|
return 0;
|
|
|
}
|
|
|
@@ -11765,26 +10128,23 @@ static int intel_gen3_queue_flip(struct drm_device *dev,
|
|
|
struct drm_i915_gem_request *req,
|
|
|
uint32_t flags)
|
|
|
{
|
|
|
- struct intel_ring *ring = req->ring;
|
|
|
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
|
|
- u32 flip_mask;
|
|
|
- int ret;
|
|
|
+ u32 flip_mask, *cs;
|
|
|
|
|
|
- ret = intel_ring_begin(req, 6);
|
|
|
- if (ret)
|
|
|
- return ret;
|
|
|
+ cs = intel_ring_begin(req, 6);
|
|
|
+ if (IS_ERR(cs))
|
|
|
+ return PTR_ERR(cs);
|
|
|
|
|
|
if (intel_crtc->plane)
|
|
|
flip_mask = MI_WAIT_FOR_PLANE_B_FLIP;
|
|
|
else
|
|
|
flip_mask = MI_WAIT_FOR_PLANE_A_FLIP;
|
|
|
- intel_ring_emit(ring, MI_WAIT_FOR_EVENT | flip_mask);
|
|
|
- intel_ring_emit(ring, MI_NOOP);
|
|
|
- intel_ring_emit(ring, MI_DISPLAY_FLIP_I915 |
|
|
|
- MI_DISPLAY_FLIP_PLANE(intel_crtc->plane));
|
|
|
- intel_ring_emit(ring, fb->pitches[0]);
|
|
|
- intel_ring_emit(ring, intel_crtc->flip_work->gtt_offset);
|
|
|
- intel_ring_emit(ring, MI_NOOP);
|
|
|
+ *cs++ = MI_WAIT_FOR_EVENT | flip_mask;
|
|
|
+ *cs++ = MI_NOOP;
|
|
|
+ *cs++ = MI_DISPLAY_FLIP_I915 | MI_DISPLAY_FLIP_PLANE(intel_crtc->plane);
|
|
|
+ *cs++ = fb->pitches[0];
|
|
|
+ *cs++ = intel_crtc->flip_work->gtt_offset;
|
|
|
+ *cs++ = MI_NOOP;
|
|
|
|
|
|
return 0;
|
|
|
}
|
|
|
@@ -11796,25 +10156,22 @@ static int intel_gen4_queue_flip(struct drm_device *dev,
|
|
|
struct drm_i915_gem_request *req,
|
|
|
uint32_t flags)
|
|
|
{
|
|
|
- struct intel_ring *ring = req->ring;
|
|
|
struct drm_i915_private *dev_priv = to_i915(dev);
|
|
|
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
|
|
- uint32_t pf, pipesrc;
|
|
|
- int ret;
|
|
|
+ u32 pf, pipesrc, *cs;
|
|
|
|
|
|
- ret = intel_ring_begin(req, 4);
|
|
|
- if (ret)
|
|
|
- return ret;
|
|
|
+ cs = intel_ring_begin(req, 4);
|
|
|
+ if (IS_ERR(cs))
|
|
|
+ return PTR_ERR(cs);
|
|
|
|
|
|
/* i965+ uses the linear or tiled offsets from the
|
|
|
* Display Registers (which do not change across a page-flip)
|
|
|
* so we need only reprogram the base address.
|
|
|
*/
|
|
|
- intel_ring_emit(ring, MI_DISPLAY_FLIP |
|
|
|
- MI_DISPLAY_FLIP_PLANE(intel_crtc->plane));
|
|
|
- intel_ring_emit(ring, fb->pitches[0]);
|
|
|
- intel_ring_emit(ring, intel_crtc->flip_work->gtt_offset |
|
|
|
- intel_fb_modifier_to_tiling(fb->modifier));
|
|
|
+ *cs++ = MI_DISPLAY_FLIP | MI_DISPLAY_FLIP_PLANE(intel_crtc->plane);
|
|
|
+ *cs++ = fb->pitches[0];
|
|
|
+ *cs++ = intel_crtc->flip_work->gtt_offset |
|
|
|
+ intel_fb_modifier_to_tiling(fb->modifier);
|
|
|
|
|
|
/* XXX Enabling the panel-fitter across page-flip is so far
|
|
|
* untested on non-native modes, so ignore it for now.
|
|
|
@@ -11822,7 +10179,7 @@ static int intel_gen4_queue_flip(struct drm_device *dev,
|
|
|
*/
|
|
|
pf = 0;
|
|
|
pipesrc = I915_READ(PIPESRC(intel_crtc->pipe)) & 0x0fff0fff;
|
|
|
- intel_ring_emit(ring, pf | pipesrc);
|
|
|
+ *cs++ = pf | pipesrc;
|
|
|
|
|
|
return 0;
|
|
|
}
|
|
|
@@ -11834,21 +10191,17 @@ static int intel_gen6_queue_flip(struct drm_device *dev,
|
|
|
struct drm_i915_gem_request *req,
|
|
|
uint32_t flags)
|
|
|
{
|
|
|
- struct intel_ring *ring = req->ring;
|
|
|
struct drm_i915_private *dev_priv = to_i915(dev);
|
|
|
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
|
|
- uint32_t pf, pipesrc;
|
|
|
- int ret;
|
|
|
+ u32 pf, pipesrc, *cs;
|
|
|
|
|
|
- ret = intel_ring_begin(req, 4);
|
|
|
- if (ret)
|
|
|
- return ret;
|
|
|
+ cs = intel_ring_begin(req, 4);
|
|
|
+ if (IS_ERR(cs))
|
|
|
+ return PTR_ERR(cs);
|
|
|
|
|
|
- intel_ring_emit(ring, MI_DISPLAY_FLIP |
|
|
|
- MI_DISPLAY_FLIP_PLANE(intel_crtc->plane));
|
|
|
- intel_ring_emit(ring, fb->pitches[0] |
|
|
|
- intel_fb_modifier_to_tiling(fb->modifier));
|
|
|
- intel_ring_emit(ring, intel_crtc->flip_work->gtt_offset);
|
|
|
+ *cs++ = MI_DISPLAY_FLIP | MI_DISPLAY_FLIP_PLANE(intel_crtc->plane);
|
|
|
+ *cs++ = fb->pitches[0] | intel_fb_modifier_to_tiling(fb->modifier);
|
|
|
+ *cs++ = intel_crtc->flip_work->gtt_offset;
|
|
|
|
|
|
/* Contrary to the suggestions in the documentation,
|
|
|
* "Enable Panel Fitter" does not seem to be required when page
|
|
|
@@ -11858,7 +10211,7 @@ static int intel_gen6_queue_flip(struct drm_device *dev,
|
|
|
*/
|
|
|
pf = 0;
|
|
|
pipesrc = I915_READ(PIPESRC(intel_crtc->pipe)) & 0x0fff0fff;
|
|
|
- intel_ring_emit(ring, pf | pipesrc);
|
|
|
+ *cs++ = pf | pipesrc;
|
|
|
|
|
|
return 0;
|
|
|
}
|
|
|
@@ -11871,9 +10224,8 @@ static int intel_gen7_queue_flip(struct drm_device *dev,
|
|
|
uint32_t flags)
|
|
|
{
|
|
|
struct drm_i915_private *dev_priv = to_i915(dev);
|
|
|
- struct intel_ring *ring = req->ring;
|
|
|
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
|
|
- uint32_t plane_bit = 0;
|
|
|
+ u32 *cs, plane_bit = 0;
|
|
|
int len, ret;
|
|
|
|
|
|
switch (intel_crtc->plane) {
|
|
|
@@ -11917,9 +10269,9 @@ static int intel_gen7_queue_flip(struct drm_device *dev,
|
|
|
if (ret)
|
|
|
return ret;
|
|
|
|
|
|
- ret = intel_ring_begin(req, len);
|
|
|
- if (ret)
|
|
|
- return ret;
|
|
|
+ cs = intel_ring_begin(req, len);
|
|
|
+ if (IS_ERR(cs))
|
|
|
+ return PTR_ERR(cs);
|
|
|
|
|
|
/* Unmask the flip-done completion message. Note that the bspec says that
|
|
|
* we should do this for both the BCS and RCS, and that we must not unmask
|
|
|
@@ -11931,31 +10283,28 @@ static int intel_gen7_queue_flip(struct drm_device *dev,
|
|
|
* to zero does lead to lockups within MI_DISPLAY_FLIP.
|
|
|
*/
|
|
|
if (req->engine->id == RCS) {
|
|
|
- intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(1));
|
|
|
- intel_ring_emit_reg(ring, DERRMR);
|
|
|
- intel_ring_emit(ring, ~(DERRMR_PIPEA_PRI_FLIP_DONE |
|
|
|
- DERRMR_PIPEB_PRI_FLIP_DONE |
|
|
|
- DERRMR_PIPEC_PRI_FLIP_DONE));
|
|
|
+ *cs++ = MI_LOAD_REGISTER_IMM(1);
|
|
|
+ *cs++ = i915_mmio_reg_offset(DERRMR);
|
|
|
+ *cs++ = ~(DERRMR_PIPEA_PRI_FLIP_DONE |
|
|
|
+ DERRMR_PIPEB_PRI_FLIP_DONE |
|
|
|
+ DERRMR_PIPEC_PRI_FLIP_DONE);
|
|
|
if (IS_GEN8(dev_priv))
|
|
|
- intel_ring_emit(ring, MI_STORE_REGISTER_MEM_GEN8 |
|
|
|
- MI_SRM_LRM_GLOBAL_GTT);
|
|
|
+ *cs++ = MI_STORE_REGISTER_MEM_GEN8 |
|
|
|
+ MI_SRM_LRM_GLOBAL_GTT;
|
|
|
else
|
|
|
- intel_ring_emit(ring, MI_STORE_REGISTER_MEM |
|
|
|
- MI_SRM_LRM_GLOBAL_GTT);
|
|
|
- intel_ring_emit_reg(ring, DERRMR);
|
|
|
- intel_ring_emit(ring,
|
|
|
- i915_ggtt_offset(req->engine->scratch) + 256);
|
|
|
+ *cs++ = MI_STORE_REGISTER_MEM | MI_SRM_LRM_GLOBAL_GTT;
|
|
|
+ *cs++ = i915_mmio_reg_offset(DERRMR);
|
|
|
+ *cs++ = i915_ggtt_offset(req->engine->scratch) + 256;
|
|
|
if (IS_GEN8(dev_priv)) {
|
|
|
- intel_ring_emit(ring, 0);
|
|
|
- intel_ring_emit(ring, MI_NOOP);
|
|
|
+ *cs++ = 0;
|
|
|
+ *cs++ = MI_NOOP;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- intel_ring_emit(ring, MI_DISPLAY_FLIP_I915 | plane_bit);
|
|
|
- intel_ring_emit(ring, fb->pitches[0] |
|
|
|
- intel_fb_modifier_to_tiling(fb->modifier));
|
|
|
- intel_ring_emit(ring, intel_crtc->flip_work->gtt_offset);
|
|
|
- intel_ring_emit(ring, (MI_NOOP));
|
|
|
+ *cs++ = MI_DISPLAY_FLIP_I915 | plane_bit;
|
|
|
+ *cs++ = fb->pitches[0] | intel_fb_modifier_to_tiling(fb->modifier);
|
|
|
+ *cs++ = intel_crtc->flip_work->gtt_offset;
|
|
|
+ *cs++ = MI_NOOP;
|
|
|
|
|
|
return 0;
|
|
|
}
|
|
|
@@ -12147,6 +10496,7 @@ void intel_check_page_flip(struct drm_i915_private *dev_priv, int pipe)
|
|
|
spin_unlock(&dev->event_lock);
|
|
|
}
|
|
|
|
|
|
+__maybe_unused
|
|
|
static int intel_crtc_page_flip(struct drm_crtc *crtc,
|
|
|
struct drm_framebuffer *fb,
|
|
|
struct drm_pending_vblank_event *event,
|
|
|
@@ -12441,11 +10791,11 @@ int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state,
|
|
|
struct intel_crtc_state *pipe_config = to_intel_crtc_state(crtc_state);
|
|
|
struct drm_crtc *crtc = crtc_state->crtc;
|
|
|
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
|
|
- struct drm_plane *plane = plane_state->plane;
|
|
|
+ struct intel_plane *plane = to_intel_plane(plane_state->plane);
|
|
|
struct drm_device *dev = crtc->dev;
|
|
|
struct drm_i915_private *dev_priv = to_i915(dev);
|
|
|
struct intel_plane_state *old_plane_state =
|
|
|
- to_intel_plane_state(plane->state);
|
|
|
+ to_intel_plane_state(plane->base.state);
|
|
|
bool mode_changed = needs_modeset(crtc_state);
|
|
|
bool was_crtc_enabled = crtc->state->active;
|
|
|
bool is_crtc_enabled = crtc_state->active;
|
|
|
@@ -12453,7 +10803,7 @@ int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state,
|
|
|
struct drm_framebuffer *fb = plane_state->fb;
|
|
|
int ret;
|
|
|
|
|
|
- if (INTEL_GEN(dev_priv) >= 9 && plane->type != DRM_PLANE_TYPE_CURSOR) {
|
|
|
+ if (INTEL_GEN(dev_priv) >= 9 && plane->id != PLANE_CURSOR) {
|
|
|
ret = skl_update_scaler_plane(
|
|
|
to_intel_crtc_state(crtc_state),
|
|
|
to_intel_plane_state(plane_state));
|
|
|
@@ -12477,8 +10827,10 @@ int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state,
|
|
|
* per-plane wm computation to the .check_plane() hook, and
|
|
|
* only combine the results from all planes in the current place?
|
|
|
*/
|
|
|
- if (!is_crtc_enabled)
|
|
|
+ if (!is_crtc_enabled) {
|
|
|
plane_state->visible = visible = false;
|
|
|
+ to_intel_crtc_state(crtc_state)->active_planes &= ~BIT(plane->id);
|
|
|
+ }
|
|
|
|
|
|
if (!was_visible && !visible)
|
|
|
return 0;
|
|
|
@@ -12490,41 +10842,39 @@ int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state,
|
|
|
turn_on = visible && (!was_visible || mode_changed);
|
|
|
|
|
|
DRM_DEBUG_ATOMIC("[CRTC:%d:%s] has [PLANE:%d:%s] with fb %i\n",
|
|
|
- intel_crtc->base.base.id,
|
|
|
- intel_crtc->base.name,
|
|
|
- plane->base.id, plane->name,
|
|
|
+ intel_crtc->base.base.id, intel_crtc->base.name,
|
|
|
+ plane->base.base.id, plane->base.name,
|
|
|
fb ? fb->base.id : -1);
|
|
|
|
|
|
DRM_DEBUG_ATOMIC("[PLANE:%d:%s] visible %i -> %i, off %i, on %i, ms %i\n",
|
|
|
- plane->base.id, plane->name,
|
|
|
+ plane->base.base.id, plane->base.name,
|
|
|
was_visible, visible,
|
|
|
turn_off, turn_on, mode_changed);
|
|
|
|
|
|
if (turn_on) {
|
|
|
- pipe_config->update_wm_pre = true;
|
|
|
+ if (INTEL_GEN(dev_priv) < 5)
|
|
|
+ pipe_config->update_wm_pre = true;
|
|
|
|
|
|
/* must disable cxsr around plane enable/disable */
|
|
|
- if (plane->type != DRM_PLANE_TYPE_CURSOR)
|
|
|
+ if (plane->id != PLANE_CURSOR)
|
|
|
pipe_config->disable_cxsr = true;
|
|
|
} else if (turn_off) {
|
|
|
- pipe_config->update_wm_post = true;
|
|
|
+ if (INTEL_GEN(dev_priv) < 5)
|
|
|
+ pipe_config->update_wm_post = true;
|
|
|
|
|
|
/* must disable cxsr around plane enable/disable */
|
|
|
- if (plane->type != DRM_PLANE_TYPE_CURSOR)
|
|
|
+ if (plane->id != PLANE_CURSOR)
|
|
|
pipe_config->disable_cxsr = true;
|
|
|
- } else if (intel_wm_need_update(plane, plane_state)) {
|
|
|
- /* FIXME bollocks */
|
|
|
- pipe_config->update_wm_pre = true;
|
|
|
- pipe_config->update_wm_post = true;
|
|
|
+ } else if (intel_wm_need_update(&plane->base, plane_state)) {
|
|
|
+ if (INTEL_GEN(dev_priv) < 5) {
|
|
|
+ /* FIXME bollocks */
|
|
|
+ pipe_config->update_wm_pre = true;
|
|
|
+ pipe_config->update_wm_post = true;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
- /* Pre-gen9 platforms need two-step watermark updates */
|
|
|
- if ((pipe_config->update_wm_pre || pipe_config->update_wm_post) &&
|
|
|
- INTEL_GEN(dev_priv) < 9 && dev_priv->display.optimize_watermarks)
|
|
|
- to_intel_crtc_state(crtc_state)->wm.need_postvbl_update = true;
|
|
|
-
|
|
|
if (visible || was_visible)
|
|
|
- pipe_config->fb_bits |= to_intel_plane(plane)->frontbuffer_bit;
|
|
|
+ pipe_config->fb_bits |= plane->frontbuffer_bit;
|
|
|
|
|
|
/*
|
|
|
* WaCxSRDisabledForSpriteScaling:ivb
|
|
|
@@ -12532,7 +10882,7 @@ int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state,
|
|
|
* cstate->update_wm was already set above, so this flag will
|
|
|
* take effect when we commit and program watermarks.
|
|
|
*/
|
|
|
- if (plane->type == DRM_PLANE_TYPE_OVERLAY && IS_IVYBRIDGE(dev_priv) &&
|
|
|
+ if (plane->id == PLANE_SPRITE0 && IS_IVYBRIDGE(dev_priv) &&
|
|
|
needs_scaling(to_intel_plane_state(plane_state)) &&
|
|
|
!needs_scaling(old_plane_state))
|
|
|
pipe_config->disable_lp_wm = true;
|
|
|
@@ -12642,7 +10992,7 @@ static int intel_crtc_atomic_check(struct drm_crtc *crtc,
|
|
|
ret = skl_update_scaler_crtc(pipe_config);
|
|
|
|
|
|
if (!ret)
|
|
|
- ret = intel_atomic_setup_scalers(dev, intel_crtc,
|
|
|
+ ret = intel_atomic_setup_scalers(dev_priv, intel_crtc,
|
|
|
pipe_config);
|
|
|
}
|
|
|
|
|
|
@@ -12800,9 +11150,10 @@ static void intel_dump_pipe_config(struct intel_crtc *crtc,
|
|
|
DRM_DEBUG_KMS("adjusted mode:\n");
|
|
|
drm_mode_debug_printmodeline(&pipe_config->base.adjusted_mode);
|
|
|
intel_dump_crtc_timings(&pipe_config->base.adjusted_mode);
|
|
|
- DRM_DEBUG_KMS("port clock: %d, pipe src size: %dx%d\n",
|
|
|
+ DRM_DEBUG_KMS("port clock: %d, pipe src size: %dx%d, pixel rate %d\n",
|
|
|
pipe_config->port_clock,
|
|
|
- pipe_config->pipe_src_w, pipe_config->pipe_src_h);
|
|
|
+ pipe_config->pipe_src_w, pipe_config->pipe_src_h,
|
|
|
+ pipe_config->pixel_rate);
|
|
|
|
|
|
if (INTEL_GEN(dev_priv) >= 9)
|
|
|
DRM_DEBUG_KMS("num_scalers: %d, scaler_users: 0x%x, scaler_id: %d\n",
|
|
|
@@ -12920,10 +11271,13 @@ static bool check_digital_port_conflicts(struct drm_atomic_state *state)
|
|
|
static void
|
|
|
clear_intel_crtc_state(struct intel_crtc_state *crtc_state)
|
|
|
{
|
|
|
+ struct drm_i915_private *dev_priv =
|
|
|
+ to_i915(crtc_state->base.crtc->dev);
|
|
|
struct drm_crtc_state tmp_state;
|
|
|
struct intel_crtc_scaler_state scaler_state;
|
|
|
struct intel_dpll_hw_state dpll_hw_state;
|
|
|
struct intel_shared_dpll *shared_dpll;
|
|
|
+ struct intel_crtc_wm_state wm_state;
|
|
|
bool force_thru;
|
|
|
|
|
|
/* FIXME: before the switch to atomic started, a new pipe_config was
|
|
|
@@ -12936,6 +11290,8 @@ clear_intel_crtc_state(struct intel_crtc_state *crtc_state)
|
|
|
shared_dpll = crtc_state->shared_dpll;
|
|
|
dpll_hw_state = crtc_state->dpll_hw_state;
|
|
|
force_thru = crtc_state->pch_pfit.force_thru;
|
|
|
+ if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
|
|
|
+ wm_state = crtc_state->wm;
|
|
|
|
|
|
memset(crtc_state, 0, sizeof *crtc_state);
|
|
|
|
|
|
@@ -12944,6 +11300,8 @@ clear_intel_crtc_state(struct intel_crtc_state *crtc_state)
|
|
|
crtc_state->shared_dpll = shared_dpll;
|
|
|
crtc_state->dpll_hw_state = dpll_hw_state;
|
|
|
crtc_state->pch_pfit.force_thru = force_thru;
|
|
|
+ if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
|
|
|
+ crtc_state->wm = wm_state;
|
|
|
}
|
|
|
|
|
|
static int
|
|
|
@@ -13060,8 +11418,11 @@ encoder_retry:
|
|
|
}
|
|
|
|
|
|
/* Dithering seems to not pass-through bits correctly when it should, so
|
|
|
- * only enable it on 6bpc panels. */
|
|
|
- pipe_config->dither = pipe_config->pipe_bpp == 6*3;
|
|
|
+ * only enable it on 6bpc panels and when its not a compliance
|
|
|
+ * test requesting 6bpc video pattern.
|
|
|
+ */
|
|
|
+ pipe_config->dither = (pipe_config->pipe_bpp == 6*3) &&
|
|
|
+ !pipe_config->dither_force_disable;
|
|
|
DRM_DEBUG_KMS("hw max bpp: %i, pipe bpp: %i, dithering: %i\n",
|
|
|
base_bpp, pipe_config->pipe_bpp, pipe_config->dither);
|
|
|
|
|
|
@@ -13375,6 +11736,7 @@ intel_pipe_config_compare(struct drm_i915_private *dev_priv,
|
|
|
}
|
|
|
|
|
|
PIPE_CONF_CHECK_I(scaler_state.scaler_id);
|
|
|
+ PIPE_CONF_CHECK_CLOCK_FUZZY(pixel_rate);
|
|
|
}
|
|
|
|
|
|
/* BDW+ don't expose a synchronous way to read the state */
|
|
|
@@ -13666,6 +12028,8 @@ verify_crtc_state(struct drm_crtc *crtc,
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ intel_crtc_compute_pixel_rate(pipe_config);
|
|
|
+
|
|
|
if (!new_crtc_state->active)
|
|
|
return;
|
|
|
|
|
|
@@ -13993,6 +12357,8 @@ static int intel_modeset_checks(struct drm_atomic_state *state)
|
|
|
|
|
|
intel_state->modeset = true;
|
|
|
intel_state->active_crtcs = dev_priv->active_crtcs;
|
|
|
+ intel_state->cdclk.logical = dev_priv->cdclk.logical;
|
|
|
+ intel_state->cdclk.actual = dev_priv->cdclk.actual;
|
|
|
|
|
|
for_each_crtc_in_state(state, crtc, crtc_state, i) {
|
|
|
if (crtc_state->active)
|
|
|
@@ -14012,38 +12378,35 @@ static int intel_modeset_checks(struct drm_atomic_state *state)
|
|
|
* adjusted_mode bits in the crtc directly.
|
|
|
*/
|
|
|
if (dev_priv->display.modeset_calc_cdclk) {
|
|
|
- if (!intel_state->cdclk_pll_vco)
|
|
|
- intel_state->cdclk_pll_vco = dev_priv->cdclk_pll.vco;
|
|
|
- if (!intel_state->cdclk_pll_vco)
|
|
|
- intel_state->cdclk_pll_vco = dev_priv->skl_preferred_vco_freq;
|
|
|
-
|
|
|
ret = dev_priv->display.modeset_calc_cdclk(state);
|
|
|
if (ret < 0)
|
|
|
return ret;
|
|
|
|
|
|
/*
|
|
|
- * Writes to dev_priv->atomic_cdclk_freq must protected by
|
|
|
+ * Writes to dev_priv->cdclk.logical must protected by
|
|
|
* holding all the crtc locks, even if we don't end up
|
|
|
* touching the hardware
|
|
|
*/
|
|
|
- if (intel_state->cdclk != dev_priv->atomic_cdclk_freq) {
|
|
|
+ if (!intel_cdclk_state_compare(&dev_priv->cdclk.logical,
|
|
|
+ &intel_state->cdclk.logical)) {
|
|
|
ret = intel_lock_all_pipes(state);
|
|
|
if (ret < 0)
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
/* All pipes must be switched off while we change the cdclk. */
|
|
|
- if (intel_state->dev_cdclk != dev_priv->cdclk_freq ||
|
|
|
- intel_state->cdclk_pll_vco != dev_priv->cdclk_pll.vco) {
|
|
|
+ if (!intel_cdclk_state_compare(&dev_priv->cdclk.actual,
|
|
|
+ &intel_state->cdclk.actual)) {
|
|
|
ret = intel_modeset_all_pipes(state);
|
|
|
if (ret < 0)
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
- DRM_DEBUG_KMS("New cdclk calculated to be atomic %u, actual %u\n",
|
|
|
- intel_state->cdclk, intel_state->dev_cdclk);
|
|
|
+ DRM_DEBUG_KMS("New cdclk calculated to be logical %u kHz, actual %u kHz\n",
|
|
|
+ intel_state->cdclk.logical.cdclk,
|
|
|
+ intel_state->cdclk.actual.cdclk);
|
|
|
} else {
|
|
|
- to_intel_atomic_state(state)->cdclk = dev_priv->atomic_cdclk_freq;
|
|
|
+ to_intel_atomic_state(state)->cdclk.logical = dev_priv->cdclk.logical;
|
|
|
}
|
|
|
|
|
|
intel_modeset_clear_plls(state);
|
|
|
@@ -14146,7 +12509,7 @@ static int intel_atomic_check(struct drm_device *dev,
|
|
|
if (ret)
|
|
|
return ret;
|
|
|
} else {
|
|
|
- intel_state->cdclk = dev_priv->atomic_cdclk_freq;
|
|
|
+ intel_state->cdclk.logical = dev_priv->cdclk.logical;
|
|
|
}
|
|
|
|
|
|
ret = drm_atomic_helper_check_planes(dev, state);
|
|
|
@@ -14253,12 +12616,7 @@ static bool needs_vblank_wait(struct intel_crtc_state *crtc_state)
|
|
|
if (crtc_state->update_wm_post)
|
|
|
return true;
|
|
|
|
|
|
- /*
|
|
|
- * cxsr is re-enabled after vblank.
|
|
|
- * This is already handled by crtc_state->update_wm_post,
|
|
|
- * but added for clarity.
|
|
|
- */
|
|
|
- if (crtc_state->disable_cxsr)
|
|
|
+ if (crtc_state->wm.need_postvbl_update)
|
|
|
return true;
|
|
|
|
|
|
return false;
|
|
|
@@ -14380,6 +12738,24 @@ static void skl_update_crtcs(struct drm_atomic_state *state,
|
|
|
} while (progress);
|
|
|
}
|
|
|
|
|
|
+static void intel_atomic_helper_free_state(struct drm_i915_private *dev_priv)
|
|
|
+{
|
|
|
+ struct intel_atomic_state *state, *next;
|
|
|
+ struct llist_node *freed;
|
|
|
+
|
|
|
+ freed = llist_del_all(&dev_priv->atomic_helper.free_list);
|
|
|
+ llist_for_each_entry_safe(state, next, freed, freed)
|
|
|
+ drm_atomic_state_put(&state->base);
|
|
|
+}
|
|
|
+
|
|
|
+static void intel_atomic_helper_free_state_worker(struct work_struct *work)
|
|
|
+{
|
|
|
+ struct drm_i915_private *dev_priv =
|
|
|
+ container_of(work, typeof(*dev_priv), atomic_helper.free_work);
|
|
|
+
|
|
|
+ intel_atomic_helper_free_state(dev_priv);
|
|
|
+}
|
|
|
+
|
|
|
static void intel_atomic_commit_tail(struct drm_atomic_state *state)
|
|
|
{
|
|
|
struct drm_device *dev = state->dev;
|
|
|
@@ -14389,7 +12765,7 @@ static void intel_atomic_commit_tail(struct drm_atomic_state *state)
|
|
|
struct drm_crtc *crtc;
|
|
|
struct intel_crtc_state *intel_cstate;
|
|
|
bool hw_check = intel_state->modeset;
|
|
|
- unsigned long put_domains[I915_MAX_PIPES] = {};
|
|
|
+ u64 put_domains[I915_MAX_PIPES] = {};
|
|
|
unsigned crtc_vblank_mask = 0;
|
|
|
int i;
|
|
|
|
|
|
@@ -14433,12 +12809,12 @@ static void intel_atomic_commit_tail(struct drm_atomic_state *state)
|
|
|
/*
|
|
|
* Make sure we don't call initial_watermarks
|
|
|
* for ILK-style watermark updates.
|
|
|
+ *
|
|
|
+ * No clue what this is supposed to achieve.
|
|
|
*/
|
|
|
- if (dev_priv->display.atomic_update_watermarks)
|
|
|
+ if (INTEL_GEN(dev_priv) >= 9)
|
|
|
dev_priv->display.initial_watermarks(intel_state,
|
|
|
to_intel_crtc_state(crtc->state));
|
|
|
- else
|
|
|
- intel_update_watermarks(intel_crtc);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
@@ -14450,10 +12826,7 @@ static void intel_atomic_commit_tail(struct drm_atomic_state *state)
|
|
|
if (intel_state->modeset) {
|
|
|
drm_atomic_helper_update_legacy_modeset_state(state->dev, state);
|
|
|
|
|
|
- if (dev_priv->display.modeset_commit_cdclk &&
|
|
|
- (intel_state->dev_cdclk != dev_priv->cdclk_freq ||
|
|
|
- intel_state->cdclk_pll_vco != dev_priv->cdclk_pll.vco))
|
|
|
- dev_priv->display.modeset_commit_cdclk(state);
|
|
|
+ intel_set_cdclk(dev_priv, &dev_priv->cdclk.actual);
|
|
|
|
|
|
/*
|
|
|
* SKL workaround: bspec recommends we disable the SAGV when we
|
|
|
@@ -14546,6 +12919,8 @@ static void intel_atomic_commit_tail(struct drm_atomic_state *state)
|
|
|
* can happen also when the device is completely off.
|
|
|
*/
|
|
|
intel_uncore_arm_unclaimed_mmio_detection(dev_priv);
|
|
|
+
|
|
|
+ intel_atomic_helper_free_state(dev_priv);
|
|
|
}
|
|
|
|
|
|
static void intel_atomic_commit_work(struct work_struct *work)
|
|
|
@@ -14615,6 +12990,17 @@ static int intel_atomic_commit(struct drm_device *dev,
|
|
|
struct drm_i915_private *dev_priv = to_i915(dev);
|
|
|
int ret = 0;
|
|
|
|
|
|
+ /*
|
|
|
+ * The intel_legacy_cursor_update() fast path takes care
|
|
|
+ * of avoiding the vblank waits for simple cursor
|
|
|
+ * movement and flips. For cursor on/off and size changes,
|
|
|
+ * we want to perform the vblank waits so that watermark
|
|
|
+ * updates happen during the correct frames. Gen9+ have
|
|
|
+ * double buffered watermarks and so shouldn't need this.
|
|
|
+ */
|
|
|
+ if (INTEL_GEN(dev_priv) < 9)
|
|
|
+ state->legacy_cursor_update = false;
|
|
|
+
|
|
|
ret = drm_atomic_helper_setup_commit(state, nonblock);
|
|
|
if (ret)
|
|
|
return ret;
|
|
|
@@ -14639,7 +13025,8 @@ static int intel_atomic_commit(struct drm_device *dev,
|
|
|
memcpy(dev_priv->min_pixclk, intel_state->min_pixclk,
|
|
|
sizeof(intel_state->min_pixclk));
|
|
|
dev_priv->active_crtcs = intel_state->active_crtcs;
|
|
|
- dev_priv->atomic_cdclk_freq = intel_state->cdclk;
|
|
|
+ dev_priv->cdclk.logical = intel_state->cdclk.logical;
|
|
|
+ dev_priv->cdclk.actual = intel_state->cdclk.actual;
|
|
|
}
|
|
|
|
|
|
drm_atomic_state_get(state);
|
|
|
@@ -14739,7 +13126,7 @@ static const struct drm_crtc_funcs intel_crtc_funcs = {
|
|
|
.set_config = drm_atomic_helper_set_config,
|
|
|
.set_property = drm_atomic_helper_crtc_set_property,
|
|
|
.destroy = intel_crtc_destroy,
|
|
|
- .page_flip = intel_crtc_page_flip,
|
|
|
+ .page_flip = drm_atomic_helper_page_flip,
|
|
|
.atomic_duplicate_state = intel_crtc_duplicate_state,
|
|
|
.atomic_destroy_state = intel_crtc_destroy_state,
|
|
|
.set_crc_source = intel_crtc_set_crc_source,
|
|
|
@@ -14771,6 +13158,29 @@ intel_prepare_plane_fb(struct drm_plane *plane,
|
|
|
struct drm_i915_gem_object *old_obj = intel_fb_obj(plane->state->fb);
|
|
|
int ret;
|
|
|
|
|
|
+ if (obj) {
|
|
|
+ if (plane->type == DRM_PLANE_TYPE_CURSOR &&
|
|
|
+ INTEL_INFO(dev_priv)->cursor_needs_physical) {
|
|
|
+ const int align = IS_I830(dev_priv) ? 16 * 1024 : 256;
|
|
|
+
|
|
|
+ ret = i915_gem_object_attach_phys(obj, align);
|
|
|
+ if (ret) {
|
|
|
+ DRM_DEBUG_KMS("failed to attach phys object\n");
|
|
|
+ return ret;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ struct i915_vma *vma;
|
|
|
+
|
|
|
+ vma = intel_pin_and_fence_fb_obj(fb, new_state->rotation);
|
|
|
+ if (IS_ERR(vma)) {
|
|
|
+ DRM_DEBUG_KMS("failed to pin object\n");
|
|
|
+ return PTR_ERR(vma);
|
|
|
+ }
|
|
|
+
|
|
|
+ to_intel_plane_state(new_state)->vma = vma;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
if (!obj && !old_obj)
|
|
|
return 0;
|
|
|
|
|
|
@@ -14823,26 +13233,6 @@ intel_prepare_plane_fb(struct drm_plane *plane,
|
|
|
i915_gem_object_wait_priority(obj, 0, I915_PRIORITY_DISPLAY);
|
|
|
}
|
|
|
|
|
|
- if (plane->type == DRM_PLANE_TYPE_CURSOR &&
|
|
|
- INTEL_INFO(dev_priv)->cursor_needs_physical) {
|
|
|
- int align = IS_I830(dev_priv) ? 16 * 1024 : 256;
|
|
|
- ret = i915_gem_object_attach_phys(obj, align);
|
|
|
- if (ret) {
|
|
|
- DRM_DEBUG_KMS("failed to attach phys object\n");
|
|
|
- return ret;
|
|
|
- }
|
|
|
- } else {
|
|
|
- struct i915_vma *vma;
|
|
|
-
|
|
|
- vma = intel_pin_and_fence_fb_obj(fb, new_state->rotation);
|
|
|
- if (IS_ERR(vma)) {
|
|
|
- DRM_DEBUG_KMS("failed to pin object\n");
|
|
|
- return PTR_ERR(vma);
|
|
|
- }
|
|
|
-
|
|
|
- to_intel_plane_state(new_state)->vma = vma;
|
|
|
- }
|
|
|
-
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
@@ -14870,16 +13260,22 @@ intel_cleanup_plane_fb(struct drm_plane *plane,
|
|
|
int
|
|
|
skl_max_scale(struct intel_crtc *intel_crtc, struct intel_crtc_state *crtc_state)
|
|
|
{
|
|
|
+ struct drm_i915_private *dev_priv;
|
|
|
int max_scale;
|
|
|
- int crtc_clock, cdclk;
|
|
|
+ int crtc_clock, max_dotclk;
|
|
|
|
|
|
if (!intel_crtc || !crtc_state->base.enable)
|
|
|
return DRM_PLANE_HELPER_NO_SCALING;
|
|
|
|
|
|
+ dev_priv = to_i915(intel_crtc->base.dev);
|
|
|
+
|
|
|
crtc_clock = crtc_state->base.adjusted_mode.crtc_clock;
|
|
|
- cdclk = to_intel_atomic_state(crtc_state->base.state)->cdclk;
|
|
|
+ max_dotclk = to_intel_atomic_state(crtc_state->base.state)->cdclk.logical.cdclk;
|
|
|
|
|
|
- if (WARN_ON_ONCE(!crtc_clock || cdclk < crtc_clock))
|
|
|
+ if (IS_GEMINILAKE(dev_priv))
|
|
|
+ max_dotclk *= 2;
|
|
|
+
|
|
|
+ if (WARN_ON_ONCE(!crtc_clock || max_dotclk < crtc_clock))
|
|
|
return DRM_PLANE_HELPER_NO_SCALING;
|
|
|
|
|
|
/*
|
|
|
@@ -14888,7 +13284,8 @@ skl_max_scale(struct intel_crtc *intel_crtc, struct intel_crtc_state *crtc_state
|
|
|
* or
|
|
|
* cdclk/crtc_clock
|
|
|
*/
|
|
|
- max_scale = min((1 << 16) * 3 - 1, (1 << 8) * ((cdclk << 8) / crtc_clock));
|
|
|
+ max_scale = min((1 << 16) * 3 - 1,
|
|
|
+ (1 << 8) * ((max_dotclk << 8) / crtc_clock));
|
|
|
|
|
|
return max_scale;
|
|
|
}
|
|
|
@@ -15038,8 +13435,7 @@ intel_legacy_cursor_update(struct drm_plane *plane,
|
|
|
old_plane_state->src_h != src_h ||
|
|
|
old_plane_state->crtc_w != crtc_w ||
|
|
|
old_plane_state->crtc_h != crtc_h ||
|
|
|
- !old_plane_state->visible ||
|
|
|
- old_plane_state->fb->modifier != fb->modifier)
|
|
|
+ !old_plane_state->fb != !fb)
|
|
|
goto slow;
|
|
|
|
|
|
new_plane_state = intel_plane_duplicate_state(plane);
|
|
|
@@ -15062,10 +13458,6 @@ intel_legacy_cursor_update(struct drm_plane *plane,
|
|
|
if (ret)
|
|
|
goto out_free;
|
|
|
|
|
|
- /* Visibility changed, must take slowpath. */
|
|
|
- if (!new_plane_state->visible)
|
|
|
- goto slow_free;
|
|
|
-
|
|
|
ret = mutex_lock_interruptible(&dev_priv->drm.struct_mutex);
|
|
|
if (ret)
|
|
|
goto out_free;
|
|
|
@@ -15105,9 +13497,15 @@ intel_legacy_cursor_update(struct drm_plane *plane,
|
|
|
new_plane_state->fb = old_fb;
|
|
|
to_intel_plane_state(new_plane_state)->vma = old_vma;
|
|
|
|
|
|
- intel_plane->update_plane(plane,
|
|
|
- to_intel_crtc_state(crtc->state),
|
|
|
- to_intel_plane_state(plane->state));
|
|
|
+ if (plane->state->visible) {
|
|
|
+ trace_intel_update_plane(plane, to_intel_crtc(crtc));
|
|
|
+ intel_plane->update_plane(plane,
|
|
|
+ to_intel_crtc_state(crtc->state),
|
|
|
+ to_intel_plane_state(plane->state));
|
|
|
+ } else {
|
|
|
+ trace_intel_disable_plane(plane, to_intel_crtc(crtc));
|
|
|
+ intel_plane->disable_plane(plane, crtc);
|
|
|
+ }
|
|
|
|
|
|
intel_cleanup_plane_fb(plane, new_plane_state);
|
|
|
|
|
|
@@ -15117,8 +13515,6 @@ out_free:
|
|
|
intel_plane_destroy_state(plane, new_plane_state);
|
|
|
return ret;
|
|
|
|
|
|
-slow_free:
|
|
|
- intel_plane_destroy_state(plane, new_plane_state);
|
|
|
slow:
|
|
|
return drm_atomic_helper_update_plane(plane, crtc, fb,
|
|
|
crtc_x, crtc_y, crtc_w, crtc_h,
|
|
|
@@ -15492,8 +13888,6 @@ static int intel_crtc_init(struct drm_i915_private *dev_priv, enum pipe pipe)
|
|
|
intel_crtc->cursor_cntl = ~0;
|
|
|
intel_crtc->cursor_size = ~0;
|
|
|
|
|
|
- intel_crtc->wm.cxsr_allowed = true;
|
|
|
-
|
|
|
/* initialize shared scalers */
|
|
|
intel_crtc_init_scalers(intel_crtc, crtc_state);
|
|
|
|
|
|
@@ -15681,7 +14075,7 @@ static void intel_setup_outputs(struct drm_i915_private *dev_priv)
|
|
|
*/
|
|
|
found = I915_READ(DDI_BUF_CTL(PORT_A)) & DDI_INIT_DISPLAY_DETECTED;
|
|
|
/* WaIgnoreDDIAStrap: skl */
|
|
|
- if (found || IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv))
|
|
|
+ if (found || IS_GEN9_BC(dev_priv))
|
|
|
intel_ddi_init(dev_priv, PORT_A);
|
|
|
|
|
|
/* DDI B, C and D detection is indicated by the SFUSE_STRAP
|
|
|
@@ -15697,7 +14091,7 @@ static void intel_setup_outputs(struct drm_i915_private *dev_priv)
|
|
|
/*
|
|
|
* On SKL we don't have a way to detect DDI-E so we rely on VBT.
|
|
|
*/
|
|
|
- if ((IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) &&
|
|
|
+ if (IS_GEN9_BC(dev_priv) &&
|
|
|
(dev_priv->vbt.ddi_port_info[PORT_E].supports_dp ||
|
|
|
dev_priv->vbt.ddi_port_info[PORT_E].supports_dvi ||
|
|
|
dev_priv->vbt.ddi_port_info[PORT_E].supports_hdmi))
|
|
|
@@ -15830,14 +14224,16 @@ static void intel_setup_outputs(struct drm_i915_private *dev_priv)
|
|
|
|
|
|
static void intel_user_framebuffer_destroy(struct drm_framebuffer *fb)
|
|
|
{
|
|
|
- struct drm_device *dev = fb->dev;
|
|
|
struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
|
|
|
|
|
|
drm_framebuffer_cleanup(fb);
|
|
|
- mutex_lock(&dev->struct_mutex);
|
|
|
+
|
|
|
+ i915_gem_object_lock(intel_fb->obj);
|
|
|
WARN_ON(!intel_fb->obj->framebuffer_references--);
|
|
|
+ i915_gem_object_unlock(intel_fb->obj);
|
|
|
+
|
|
|
i915_gem_object_put(intel_fb->obj);
|
|
|
- mutex_unlock(&dev->struct_mutex);
|
|
|
+
|
|
|
kfree(intel_fb);
|
|
|
}
|
|
|
|
|
|
@@ -15862,15 +14258,10 @@ static int intel_user_framebuffer_dirty(struct drm_framebuffer *fb,
|
|
|
struct drm_clip_rect *clips,
|
|
|
unsigned num_clips)
|
|
|
{
|
|
|
- struct drm_device *dev = fb->dev;
|
|
|
- struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
|
|
|
- struct drm_i915_gem_object *obj = intel_fb->obj;
|
|
|
+ struct drm_i915_gem_object *obj = intel_fb_obj(fb);
|
|
|
|
|
|
- mutex_lock(&dev->struct_mutex);
|
|
|
- if (obj->pin_display && obj->cache_dirty)
|
|
|
- i915_gem_clflush_object(obj, true);
|
|
|
- intel_fb_obj_flush(obj, false, ORIGIN_DIRTYFB);
|
|
|
- mutex_unlock(&dev->struct_mutex);
|
|
|
+ i915_gem_object_flush_if_display(obj);
|
|
|
+ intel_fb_obj_flush(obj, ORIGIN_DIRTYFB);
|
|
|
|
|
|
return 0;
|
|
|
}
|
|
|
@@ -15885,7 +14276,7 @@ static
|
|
|
u32 intel_fb_pitch_limit(struct drm_i915_private *dev_priv,
|
|
|
uint64_t fb_modifier, uint32_t pixel_format)
|
|
|
{
|
|
|
- u32 gen = INTEL_INFO(dev_priv)->gen;
|
|
|
+ u32 gen = INTEL_GEN(dev_priv);
|
|
|
|
|
|
if (gen >= 9) {
|
|
|
int cpp = drm_format_plane_cpp(pixel_format, 0);
|
|
|
@@ -15894,8 +14285,7 @@ u32 intel_fb_pitch_limit(struct drm_i915_private *dev_priv,
|
|
|
* pixels and 32K bytes."
|
|
|
*/
|
|
|
return min(8192 * cpp, 32768);
|
|
|
- } else if (gen >= 5 && !IS_VALLEYVIEW(dev_priv) &&
|
|
|
- !IS_CHERRYVIEW(dev_priv)) {
|
|
|
+ } else if (gen >= 5 && !HAS_GMCH_DISPLAY(dev_priv)) {
|
|
|
return 32*1024;
|
|
|
} else if (gen >= 4) {
|
|
|
if (fb_modifier == I915_FORMAT_MOD_X_TILED)
|
|
|
@@ -15913,18 +14303,21 @@ u32 intel_fb_pitch_limit(struct drm_i915_private *dev_priv,
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-static int intel_framebuffer_init(struct drm_device *dev,
|
|
|
- struct intel_framebuffer *intel_fb,
|
|
|
- struct drm_mode_fb_cmd2 *mode_cmd,
|
|
|
- struct drm_i915_gem_object *obj)
|
|
|
+static int intel_framebuffer_init(struct intel_framebuffer *intel_fb,
|
|
|
+ struct drm_i915_gem_object *obj,
|
|
|
+ struct drm_mode_fb_cmd2 *mode_cmd)
|
|
|
{
|
|
|
- struct drm_i915_private *dev_priv = to_i915(dev);
|
|
|
- unsigned int tiling = i915_gem_object_get_tiling(obj);
|
|
|
- int ret;
|
|
|
- u32 pitch_limit, stride_alignment;
|
|
|
+ struct drm_i915_private *dev_priv = to_i915(obj->base.dev);
|
|
|
struct drm_format_name_buf format_name;
|
|
|
+ u32 pitch_limit, stride_alignment;
|
|
|
+ unsigned int tiling, stride;
|
|
|
+ int ret = -EINVAL;
|
|
|
|
|
|
- WARN_ON(!mutex_is_locked(&dev->struct_mutex));
|
|
|
+ i915_gem_object_lock(obj);
|
|
|
+ obj->framebuffer_references++;
|
|
|
+ tiling = i915_gem_object_get_tiling(obj);
|
|
|
+ stride = i915_gem_object_get_stride(obj);
|
|
|
+ i915_gem_object_unlock(obj);
|
|
|
|
|
|
if (mode_cmd->flags & DRM_MODE_FB_MODIFIERS) {
|
|
|
/*
|
|
|
@@ -15934,14 +14327,14 @@ static int intel_framebuffer_init(struct drm_device *dev,
|
|
|
if (tiling != I915_TILING_NONE &&
|
|
|
tiling != intel_fb_modifier_to_tiling(mode_cmd->modifier[0])) {
|
|
|
DRM_DEBUG("tiling_mode doesn't match fb modifier\n");
|
|
|
- return -EINVAL;
|
|
|
+ goto err;
|
|
|
}
|
|
|
} else {
|
|
|
if (tiling == I915_TILING_X) {
|
|
|
mode_cmd->modifier[0] = I915_FORMAT_MOD_X_TILED;
|
|
|
} else if (tiling == I915_TILING_Y) {
|
|
|
DRM_DEBUG("No Y tiling for legacy addfb\n");
|
|
|
- return -EINVAL;
|
|
|
+ goto err;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -15952,7 +14345,7 @@ static int intel_framebuffer_init(struct drm_device *dev,
|
|
|
if (INTEL_GEN(dev_priv) < 9) {
|
|
|
DRM_DEBUG("Unsupported tiling 0x%llx!\n",
|
|
|
mode_cmd->modifier[0]);
|
|
|
- return -EINVAL;
|
|
|
+ goto err;
|
|
|
}
|
|
|
case DRM_FORMAT_MOD_NONE:
|
|
|
case I915_FORMAT_MOD_X_TILED:
|
|
|
@@ -15960,7 +14353,7 @@ static int intel_framebuffer_init(struct drm_device *dev,
|
|
|
default:
|
|
|
DRM_DEBUG("Unsupported fb modifier 0x%llx!\n",
|
|
|
mode_cmd->modifier[0]);
|
|
|
- return -EINVAL;
|
|
|
+ goto err;
|
|
|
}
|
|
|
|
|
|
/*
|
|
|
@@ -15970,7 +14363,7 @@ static int intel_framebuffer_init(struct drm_device *dev,
|
|
|
if (INTEL_INFO(dev_priv)->gen < 4 &&
|
|
|
tiling != intel_fb_modifier_to_tiling(mode_cmd->modifier[0])) {
|
|
|
DRM_DEBUG("tiling_mode must match fb modifier exactly on gen2/3\n");
|
|
|
- return -EINVAL;
|
|
|
+ goto err;
|
|
|
}
|
|
|
|
|
|
stride_alignment = intel_fb_stride_alignment(dev_priv,
|
|
|
@@ -15979,7 +14372,7 @@ static int intel_framebuffer_init(struct drm_device *dev,
|
|
|
if (mode_cmd->pitches[0] & (stride_alignment - 1)) {
|
|
|
DRM_DEBUG("pitch (%d) must be at least %u byte aligned\n",
|
|
|
mode_cmd->pitches[0], stride_alignment);
|
|
|
- return -EINVAL;
|
|
|
+ goto err;
|
|
|
}
|
|
|
|
|
|
pitch_limit = intel_fb_pitch_limit(dev_priv, mode_cmd->modifier[0],
|
|
|
@@ -15989,19 +14382,17 @@ static int intel_framebuffer_init(struct drm_device *dev,
|
|
|
mode_cmd->modifier[0] != DRM_FORMAT_MOD_NONE ?
|
|
|
"tiled" : "linear",
|
|
|
mode_cmd->pitches[0], pitch_limit);
|
|
|
- return -EINVAL;
|
|
|
+ goto err;
|
|
|
}
|
|
|
|
|
|
/*
|
|
|
* If there's a fence, enforce that
|
|
|
* the fb pitch and fence stride match.
|
|
|
*/
|
|
|
- if (tiling != I915_TILING_NONE &&
|
|
|
- mode_cmd->pitches[0] != i915_gem_object_get_stride(obj)) {
|
|
|
+ if (tiling != I915_TILING_NONE && mode_cmd->pitches[0] != stride) {
|
|
|
DRM_DEBUG("pitch (%d) must match tiling stride (%d)\n",
|
|
|
- mode_cmd->pitches[0],
|
|
|
- i915_gem_object_get_stride(obj));
|
|
|
- return -EINVAL;
|
|
|
+ mode_cmd->pitches[0], stride);
|
|
|
+ goto err;
|
|
|
}
|
|
|
|
|
|
/* Reject formats not supported by any plane early. */
|
|
|
@@ -16015,7 +14406,7 @@ static int intel_framebuffer_init(struct drm_device *dev,
|
|
|
if (INTEL_GEN(dev_priv) > 3) {
|
|
|
DRM_DEBUG("unsupported pixel format: %s\n",
|
|
|
drm_get_format_name(mode_cmd->pixel_format, &format_name));
|
|
|
- return -EINVAL;
|
|
|
+ goto err;
|
|
|
}
|
|
|
break;
|
|
|
case DRM_FORMAT_ABGR8888:
|
|
|
@@ -16023,7 +14414,7 @@ static int intel_framebuffer_init(struct drm_device *dev,
|
|
|
INTEL_GEN(dev_priv) < 9) {
|
|
|
DRM_DEBUG("unsupported pixel format: %s\n",
|
|
|
drm_get_format_name(mode_cmd->pixel_format, &format_name));
|
|
|
- return -EINVAL;
|
|
|
+ goto err;
|
|
|
}
|
|
|
break;
|
|
|
case DRM_FORMAT_XBGR8888:
|
|
|
@@ -16032,14 +14423,14 @@ static int intel_framebuffer_init(struct drm_device *dev,
|
|
|
if (INTEL_GEN(dev_priv) < 4) {
|
|
|
DRM_DEBUG("unsupported pixel format: %s\n",
|
|
|
drm_get_format_name(mode_cmd->pixel_format, &format_name));
|
|
|
- return -EINVAL;
|
|
|
+ goto err;
|
|
|
}
|
|
|
break;
|
|
|
case DRM_FORMAT_ABGR2101010:
|
|
|
if (!IS_VALLEYVIEW(dev_priv) && !IS_CHERRYVIEW(dev_priv)) {
|
|
|
DRM_DEBUG("unsupported pixel format: %s\n",
|
|
|
drm_get_format_name(mode_cmd->pixel_format, &format_name));
|
|
|
- return -EINVAL;
|
|
|
+ goto err;
|
|
|
}
|
|
|
break;
|
|
|
case DRM_FORMAT_YUYV:
|
|
|
@@ -16049,35 +14440,42 @@ static int intel_framebuffer_init(struct drm_device *dev,
|
|
|
if (INTEL_GEN(dev_priv) < 5) {
|
|
|
DRM_DEBUG("unsupported pixel format: %s\n",
|
|
|
drm_get_format_name(mode_cmd->pixel_format, &format_name));
|
|
|
- return -EINVAL;
|
|
|
+ goto err;
|
|
|
}
|
|
|
break;
|
|
|
default:
|
|
|
DRM_DEBUG("unsupported pixel format: %s\n",
|
|
|
drm_get_format_name(mode_cmd->pixel_format, &format_name));
|
|
|
- return -EINVAL;
|
|
|
+ goto err;
|
|
|
}
|
|
|
|
|
|
/* FIXME need to adjust LINOFF/TILEOFF accordingly. */
|
|
|
if (mode_cmd->offsets[0] != 0)
|
|
|
- return -EINVAL;
|
|
|
+ goto err;
|
|
|
|
|
|
- drm_helper_mode_fill_fb_struct(dev, &intel_fb->base, mode_cmd);
|
|
|
+ drm_helper_mode_fill_fb_struct(&dev_priv->drm,
|
|
|
+ &intel_fb->base, mode_cmd);
|
|
|
intel_fb->obj = obj;
|
|
|
|
|
|
ret = intel_fill_fb_info(dev_priv, &intel_fb->base);
|
|
|
if (ret)
|
|
|
- return ret;
|
|
|
+ goto err;
|
|
|
|
|
|
- ret = drm_framebuffer_init(dev, &intel_fb->base, &intel_fb_funcs);
|
|
|
+ ret = drm_framebuffer_init(obj->base.dev,
|
|
|
+ &intel_fb->base,
|
|
|
+ &intel_fb_funcs);
|
|
|
if (ret) {
|
|
|
DRM_ERROR("framebuffer init failed %d\n", ret);
|
|
|
- return ret;
|
|
|
+ goto err;
|
|
|
}
|
|
|
|
|
|
- intel_fb->obj->framebuffer_references++;
|
|
|
-
|
|
|
return 0;
|
|
|
+
|
|
|
+err:
|
|
|
+ i915_gem_object_lock(obj);
|
|
|
+ obj->framebuffer_references--;
|
|
|
+ i915_gem_object_unlock(obj);
|
|
|
+ return ret;
|
|
|
}
|
|
|
|
|
|
static struct drm_framebuffer *
|
|
|
@@ -16093,7 +14491,7 @@ intel_user_framebuffer_create(struct drm_device *dev,
|
|
|
if (!obj)
|
|
|
return ERR_PTR(-ENOENT);
|
|
|
|
|
|
- fb = intel_framebuffer_create(dev, &mode_cmd, obj);
|
|
|
+ fb = intel_framebuffer_create(obj, &mode_cmd);
|
|
|
if (IS_ERR(fb))
|
|
|
i915_gem_object_put(obj);
|
|
|
|
|
|
@@ -16127,6 +14525,8 @@ static const struct drm_mode_config_funcs intel_mode_funcs = {
|
|
|
*/
|
|
|
void intel_init_display_hooks(struct drm_i915_private *dev_priv)
|
|
|
{
|
|
|
+ intel_init_cdclk_hooks(dev_priv);
|
|
|
+
|
|
|
if (INTEL_INFO(dev_priv)->gen >= 9) {
|
|
|
dev_priv->display.get_pipe_config = haswell_get_pipe_config;
|
|
|
dev_priv->display.get_initial_plane_config =
|
|
|
@@ -16195,62 +14595,6 @@ void intel_init_display_hooks(struct drm_i915_private *dev_priv)
|
|
|
dev_priv->display.crtc_disable = i9xx_crtc_disable;
|
|
|
}
|
|
|
|
|
|
- /* Returns the core display clock speed */
|
|
|
- if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv))
|
|
|
- dev_priv->display.get_display_clock_speed =
|
|
|
- skylake_get_display_clock_speed;
|
|
|
- else if (IS_GEN9_LP(dev_priv))
|
|
|
- dev_priv->display.get_display_clock_speed =
|
|
|
- broxton_get_display_clock_speed;
|
|
|
- else if (IS_BROADWELL(dev_priv))
|
|
|
- dev_priv->display.get_display_clock_speed =
|
|
|
- broadwell_get_display_clock_speed;
|
|
|
- else if (IS_HASWELL(dev_priv))
|
|
|
- dev_priv->display.get_display_clock_speed =
|
|
|
- haswell_get_display_clock_speed;
|
|
|
- else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
|
|
|
- dev_priv->display.get_display_clock_speed =
|
|
|
- valleyview_get_display_clock_speed;
|
|
|
- else if (IS_GEN5(dev_priv))
|
|
|
- dev_priv->display.get_display_clock_speed =
|
|
|
- ilk_get_display_clock_speed;
|
|
|
- else if (IS_I945G(dev_priv) || IS_I965G(dev_priv) ||
|
|
|
- IS_GEN6(dev_priv) || IS_IVYBRIDGE(dev_priv))
|
|
|
- dev_priv->display.get_display_clock_speed =
|
|
|
- i945_get_display_clock_speed;
|
|
|
- else if (IS_GM45(dev_priv))
|
|
|
- dev_priv->display.get_display_clock_speed =
|
|
|
- gm45_get_display_clock_speed;
|
|
|
- else if (IS_I965GM(dev_priv))
|
|
|
- dev_priv->display.get_display_clock_speed =
|
|
|
- i965gm_get_display_clock_speed;
|
|
|
- else if (IS_PINEVIEW(dev_priv))
|
|
|
- dev_priv->display.get_display_clock_speed =
|
|
|
- pnv_get_display_clock_speed;
|
|
|
- else if (IS_G33(dev_priv) || IS_G4X(dev_priv))
|
|
|
- dev_priv->display.get_display_clock_speed =
|
|
|
- g33_get_display_clock_speed;
|
|
|
- else if (IS_I915G(dev_priv))
|
|
|
- dev_priv->display.get_display_clock_speed =
|
|
|
- i915_get_display_clock_speed;
|
|
|
- else if (IS_I945GM(dev_priv) || IS_I845G(dev_priv))
|
|
|
- dev_priv->display.get_display_clock_speed =
|
|
|
- i9xx_misc_get_display_clock_speed;
|
|
|
- else if (IS_I915GM(dev_priv))
|
|
|
- dev_priv->display.get_display_clock_speed =
|
|
|
- i915gm_get_display_clock_speed;
|
|
|
- else if (IS_I865G(dev_priv))
|
|
|
- dev_priv->display.get_display_clock_speed =
|
|
|
- i865_get_display_clock_speed;
|
|
|
- else if (IS_I85X(dev_priv))
|
|
|
- dev_priv->display.get_display_clock_speed =
|
|
|
- i85x_get_display_clock_speed;
|
|
|
- else { /* 830 */
|
|
|
- WARN(!IS_I830(dev_priv), "Unknown platform. Assuming 133 MHz CDCLK\n");
|
|
|
- dev_priv->display.get_display_clock_speed =
|
|
|
- i830_get_display_clock_speed;
|
|
|
- }
|
|
|
-
|
|
|
if (IS_GEN5(dev_priv)) {
|
|
|
dev_priv->display.fdi_link_train = ironlake_fdi_link_train;
|
|
|
} else if (IS_GEN6(dev_priv)) {
|
|
|
@@ -16262,28 +14606,6 @@ void intel_init_display_hooks(struct drm_i915_private *dev_priv)
|
|
|
dev_priv->display.fdi_link_train = hsw_fdi_link_train;
|
|
|
}
|
|
|
|
|
|
- if (IS_BROADWELL(dev_priv)) {
|
|
|
- dev_priv->display.modeset_commit_cdclk =
|
|
|
- broadwell_modeset_commit_cdclk;
|
|
|
- dev_priv->display.modeset_calc_cdclk =
|
|
|
- broadwell_modeset_calc_cdclk;
|
|
|
- } else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
|
|
|
- dev_priv->display.modeset_commit_cdclk =
|
|
|
- valleyview_modeset_commit_cdclk;
|
|
|
- dev_priv->display.modeset_calc_cdclk =
|
|
|
- valleyview_modeset_calc_cdclk;
|
|
|
- } else if (IS_GEN9_LP(dev_priv)) {
|
|
|
- dev_priv->display.modeset_commit_cdclk =
|
|
|
- bxt_modeset_commit_cdclk;
|
|
|
- dev_priv->display.modeset_calc_cdclk =
|
|
|
- bxt_modeset_calc_cdclk;
|
|
|
- } else if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) {
|
|
|
- dev_priv->display.modeset_commit_cdclk =
|
|
|
- skl_modeset_commit_cdclk;
|
|
|
- dev_priv->display.modeset_calc_cdclk =
|
|
|
- skl_modeset_calc_cdclk;
|
|
|
- }
|
|
|
-
|
|
|
if (dev_priv->info.gen >= 9)
|
|
|
dev_priv->display.update_crtcs = skl_update_crtcs;
|
|
|
else
|
|
|
@@ -16510,8 +14832,7 @@ void intel_modeset_init_hw(struct drm_device *dev)
|
|
|
struct drm_i915_private *dev_priv = to_i915(dev);
|
|
|
|
|
|
intel_update_cdclk(dev_priv);
|
|
|
-
|
|
|
- dev_priv->atomic_cdclk_freq = dev_priv->cdclk_freq;
|
|
|
+ dev_priv->cdclk.logical = dev_priv->cdclk.actual = dev_priv->cdclk.hw;
|
|
|
|
|
|
intel_init_clock_gating(dev_priv);
|
|
|
}
|
|
|
@@ -16566,7 +14887,8 @@ retry:
|
|
|
* intermediate watermarks (since we don't trust the current
|
|
|
* watermarks).
|
|
|
*/
|
|
|
- intel_state->skip_intermediate_wm = true;
|
|
|
+ if (!HAS_GMCH_DISPLAY(dev_priv))
|
|
|
+ intel_state->skip_intermediate_wm = true;
|
|
|
|
|
|
ret = intel_atomic_check(dev, state);
|
|
|
if (ret) {
|
|
|
@@ -16600,18 +14922,6 @@ fail:
|
|
|
drm_modeset_acquire_fini(&ctx);
|
|
|
}
|
|
|
|
|
|
-static void intel_atomic_helper_free_state(struct work_struct *work)
|
|
|
-{
|
|
|
- struct drm_i915_private *dev_priv =
|
|
|
- container_of(work, typeof(*dev_priv), atomic_helper.free_work);
|
|
|
- struct intel_atomic_state *state, *next;
|
|
|
- struct llist_node *freed;
|
|
|
-
|
|
|
- freed = llist_del_all(&dev_priv->atomic_helper.free_list);
|
|
|
- llist_for_each_entry_safe(state, next, freed, freed)
|
|
|
- drm_atomic_state_put(&state->base);
|
|
|
-}
|
|
|
-
|
|
|
int intel_modeset_init(struct drm_device *dev)
|
|
|
{
|
|
|
struct drm_i915_private *dev_priv = to_i915(dev);
|
|
|
@@ -16632,7 +14942,7 @@ int intel_modeset_init(struct drm_device *dev)
|
|
|
dev->mode_config.funcs = &intel_mode_funcs;
|
|
|
|
|
|
INIT_WORK(&dev_priv->atomic_helper.free_work,
|
|
|
- intel_atomic_helper_free_state);
|
|
|
+ intel_atomic_helper_free_state_worker);
|
|
|
|
|
|
intel_init_quirks(dev);
|
|
|
|
|
|
@@ -16697,12 +15007,11 @@ int intel_modeset_init(struct drm_device *dev)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- intel_update_czclk(dev_priv);
|
|
|
- intel_update_cdclk(dev_priv);
|
|
|
- dev_priv->atomic_cdclk_freq = dev_priv->cdclk_freq;
|
|
|
-
|
|
|
intel_shared_dpll_init(dev);
|
|
|
|
|
|
+ intel_update_czclk(dev_priv);
|
|
|
+ intel_modeset_init_hw(dev);
|
|
|
+
|
|
|
if (dev_priv->max_cdclk_freq == 0)
|
|
|
intel_update_max_cdclk(dev_priv);
|
|
|
|
|
|
@@ -16742,7 +15051,8 @@ int intel_modeset_init(struct drm_device *dev)
|
|
|
* Note that we need to do this after reconstructing the BIOS fb's
|
|
|
* since the watermark calculation done here will use pstate->fb.
|
|
|
*/
|
|
|
- sanitize_watermarks(dev);
|
|
|
+ if (!HAS_GMCH_DISPLAY(dev_priv))
|
|
|
+ sanitize_watermarks(dev);
|
|
|
|
|
|
return 0;
|
|
|
}
|
|
|
@@ -16844,6 +15154,7 @@ static void intel_sanitize_crtc(struct intel_crtc *crtc)
|
|
|
if (plane->base.type == DRM_PLANE_TYPE_PRIMARY)
|
|
|
continue;
|
|
|
|
|
|
+ trace_intel_disable_plane(&plane->base, crtc);
|
|
|
plane->disable_plane(&plane->base, &crtc->base);
|
|
|
}
|
|
|
}
|
|
|
@@ -16990,15 +15301,14 @@ static bool primary_get_hw_state(struct intel_plane *plane)
|
|
|
/* FIXME read out full plane state for all planes */
|
|
|
static void readout_plane_state(struct intel_crtc *crtc)
|
|
|
{
|
|
|
- struct drm_plane *primary = crtc->base.primary;
|
|
|
- struct intel_plane_state *plane_state =
|
|
|
- to_intel_plane_state(primary->state);
|
|
|
+ struct intel_plane *primary = to_intel_plane(crtc->base.primary);
|
|
|
+ bool visible;
|
|
|
|
|
|
- plane_state->base.visible = crtc->active &&
|
|
|
- primary_get_hw_state(to_intel_plane(primary));
|
|
|
+ visible = crtc->active && primary_get_hw_state(primary);
|
|
|
|
|
|
- if (plane_state->base.visible)
|
|
|
- crtc->base.state->plane_mask |= 1 << drm_plane_index(primary);
|
|
|
+ intel_set_plane_visible(to_intel_crtc_state(crtc->base.state),
|
|
|
+ to_intel_plane_state(primary->base.state),
|
|
|
+ visible);
|
|
|
}
|
|
|
|
|
|
static void intel_modeset_readout_hw_state(struct drm_device *dev)
|
|
|
@@ -17131,10 +15441,11 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev)
|
|
|
*/
|
|
|
crtc_state->base.mode.private_flags = I915_MODE_FLAG_INHERITED;
|
|
|
|
|
|
- if (INTEL_GEN(dev_priv) >= 9 || IS_BROADWELL(dev_priv))
|
|
|
- pixclk = ilk_pipe_pixel_rate(crtc_state);
|
|
|
- else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
|
|
|
- pixclk = crtc_state->base.adjusted_mode.crtc_clock;
|
|
|
+ intel_crtc_compute_pixel_rate(crtc_state);
|
|
|
+
|
|
|
+ if (INTEL_GEN(dev_priv) >= 9 || IS_BROADWELL(dev_priv) ||
|
|
|
+ IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
|
|
|
+ pixclk = crtc_state->pixel_rate;
|
|
|
else
|
|
|
WARN_ON(dev_priv->display.modeset_calc_cdclk);
|
|
|
|
|
|
@@ -17152,6 +15463,24 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+static void
|
|
|
+get_encoder_power_domains(struct drm_i915_private *dev_priv)
|
|
|
+{
|
|
|
+ struct intel_encoder *encoder;
|
|
|
+
|
|
|
+ for_each_intel_encoder(&dev_priv->drm, encoder) {
|
|
|
+ u64 get_domains;
|
|
|
+ enum intel_display_power_domain domain;
|
|
|
+
|
|
|
+ if (!encoder->get_power_domains)
|
|
|
+ continue;
|
|
|
+
|
|
|
+ get_domains = encoder->get_power_domains(encoder);
|
|
|
+ for_each_power_domain(domain, get_domains)
|
|
|
+ intel_display_power_get(dev_priv, domain);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
/* Scan out the current hw modeset state,
|
|
|
* and sanitizes it to the current state
|
|
|
*/
|
|
|
@@ -17167,6 +15496,8 @@ intel_modeset_setup_hw_state(struct drm_device *dev)
|
|
|
intel_modeset_readout_hw_state(dev);
|
|
|
|
|
|
/* HW state is read out, now we need to sanitize this mess. */
|
|
|
+ get_encoder_power_domains(dev_priv);
|
|
|
+
|
|
|
for_each_intel_encoder(dev, encoder) {
|
|
|
intel_sanitize_encoder(encoder);
|
|
|
}
|
|
|
@@ -17193,15 +15524,17 @@ intel_modeset_setup_hw_state(struct drm_device *dev)
|
|
|
pll->on = false;
|
|
|
}
|
|
|
|
|
|
- if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
|
|
|
+ if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
|
|
|
vlv_wm_get_hw_state(dev);
|
|
|
- else if (IS_GEN9(dev_priv))
|
|
|
+ vlv_wm_sanitize(dev_priv);
|
|
|
+ } else if (IS_GEN9(dev_priv)) {
|
|
|
skl_wm_get_hw_state(dev);
|
|
|
- else if (HAS_PCH_SPLIT(dev_priv))
|
|
|
+ } else if (HAS_PCH_SPLIT(dev_priv)) {
|
|
|
ilk_wm_get_hw_state(dev);
|
|
|
+ }
|
|
|
|
|
|
for_each_intel_crtc(dev, crtc) {
|
|
|
- unsigned long put_domains;
|
|
|
+ u64 put_domains;
|
|
|
|
|
|
put_domains = modeset_get_crtc_power_domains(&crtc->base, crtc->config);
|
|
|
if (WARN_ON(put_domains))
|
|
|
@@ -17209,6 +15542,8 @@ intel_modeset_setup_hw_state(struct drm_device *dev)
|
|
|
}
|
|
|
intel_display_set_init_power(dev_priv, false);
|
|
|
|
|
|
+ intel_power_domains_verify_state(dev_priv);
|
|
|
+
|
|
|
intel_fbc_init_pipe_state(dev_priv);
|
|
|
}
|
|
|
|
|
|
@@ -17259,8 +15594,6 @@ void intel_modeset_gem_init(struct drm_device *dev)
|
|
|
|
|
|
intel_init_gt_powersave(dev_priv);
|
|
|
|
|
|
- intel_modeset_init_hw(dev);
|
|
|
-
|
|
|
intel_setup_overlay(dev_priv);
|
|
|
}
|
|
|
|
|
|
@@ -17492,9 +15825,9 @@ intel_display_capture_error_state(struct drm_i915_private *dev_priv)
|
|
|
|
|
|
void
|
|
|
intel_display_print_error_state(struct drm_i915_error_state_buf *m,
|
|
|
- struct drm_i915_private *dev_priv,
|
|
|
struct intel_display_error_state *error)
|
|
|
{
|
|
|
+ struct drm_i915_private *dev_priv = m->i915;
|
|
|
int i;
|
|
|
|
|
|
if (!error)
|