|
@@ -85,8 +85,6 @@ static const uint32_t intel_cursor_formats[] = {
|
|
|
DRM_FORMAT_ARGB8888,
|
|
|
};
|
|
|
|
|
|
-static void intel_crtc_update_cursor(struct drm_crtc *crtc, bool on);
|
|
|
-
|
|
|
static void i9xx_crtc_clock_get(struct intel_crtc *crtc,
|
|
|
struct intel_crtc_state *pipe_config);
|
|
|
static void ironlake_pch_clock_get(struct intel_crtc *crtc,
|
|
@@ -1152,11 +1150,6 @@ static void intel_wait_for_pipe_off(struct intel_crtc *crtc)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-static const char *state_string(bool enabled)
|
|
|
-{
|
|
|
- return enabled ? "on" : "off";
|
|
|
-}
|
|
|
-
|
|
|
/* Only for pre-ILK configs */
|
|
|
void assert_pll(struct drm_i915_private *dev_priv,
|
|
|
enum pipe pipe, bool state)
|
|
@@ -1168,7 +1161,7 @@ void assert_pll(struct drm_i915_private *dev_priv,
|
|
|
cur_state = !!(val & DPLL_VCO_ENABLE);
|
|
|
I915_STATE_WARN(cur_state != state,
|
|
|
"PLL state assertion failure (expected %s, current %s)\n",
|
|
|
- state_string(state), state_string(cur_state));
|
|
|
+ onoff(state), onoff(cur_state));
|
|
|
}
|
|
|
|
|
|
/* XXX: the dsi pll is shared between MIPI DSI ports */
|
|
@@ -1184,7 +1177,7 @@ static void assert_dsi_pll(struct drm_i915_private *dev_priv, bool state)
|
|
|
cur_state = val & DSI_PLL_VCO_EN;
|
|
|
I915_STATE_WARN(cur_state != state,
|
|
|
"DSI PLL state assertion failure (expected %s, current %s)\n",
|
|
|
- state_string(state), state_string(cur_state));
|
|
|
+ onoff(state), onoff(cur_state));
|
|
|
}
|
|
|
#define assert_dsi_pll_enabled(d) assert_dsi_pll(d, true)
|
|
|
#define assert_dsi_pll_disabled(d) assert_dsi_pll(d, false)
|
|
@@ -1208,14 +1201,13 @@ void assert_shared_dpll(struct drm_i915_private *dev_priv,
|
|
|
bool cur_state;
|
|
|
struct intel_dpll_hw_state hw_state;
|
|
|
|
|
|
- if (WARN (!pll,
|
|
|
- "asserting DPLL %s with no DPLL\n", state_string(state)))
|
|
|
+ if (WARN(!pll, "asserting DPLL %s with no DPLL\n", onoff(state)))
|
|
|
return;
|
|
|
|
|
|
cur_state = pll->get_hw_state(dev_priv, pll, &hw_state);
|
|
|
I915_STATE_WARN(cur_state != state,
|
|
|
"%s assertion failure (expected %s, current %s)\n",
|
|
|
- pll->name, state_string(state), state_string(cur_state));
|
|
|
+ pll->name, onoff(state), onoff(cur_state));
|
|
|
}
|
|
|
|
|
|
static void assert_fdi_tx(struct drm_i915_private *dev_priv,
|
|
@@ -1235,7 +1227,7 @@ static void assert_fdi_tx(struct drm_i915_private *dev_priv,
|
|
|
}
|
|
|
I915_STATE_WARN(cur_state != state,
|
|
|
"FDI TX state assertion failure (expected %s, current %s)\n",
|
|
|
- state_string(state), state_string(cur_state));
|
|
|
+ onoff(state), onoff(cur_state));
|
|
|
}
|
|
|
#define assert_fdi_tx_enabled(d, p) assert_fdi_tx(d, p, true)
|
|
|
#define assert_fdi_tx_disabled(d, p) assert_fdi_tx(d, p, false)
|
|
@@ -1250,7 +1242,7 @@ static void assert_fdi_rx(struct drm_i915_private *dev_priv,
|
|
|
cur_state = !!(val & FDI_RX_ENABLE);
|
|
|
I915_STATE_WARN(cur_state != state,
|
|
|
"FDI RX state assertion failure (expected %s, current %s)\n",
|
|
|
- state_string(state), state_string(cur_state));
|
|
|
+ onoff(state), onoff(cur_state));
|
|
|
}
|
|
|
#define assert_fdi_rx_enabled(d, p) assert_fdi_rx(d, p, true)
|
|
|
#define assert_fdi_rx_disabled(d, p) assert_fdi_rx(d, p, false)
|
|
@@ -1282,7 +1274,7 @@ void assert_fdi_rx_pll(struct drm_i915_private *dev_priv,
|
|
|
cur_state = !!(val & FDI_RX_PLL_ENABLE);
|
|
|
I915_STATE_WARN(cur_state != state,
|
|
|
"FDI RX PLL assertion failure (expected %s, current %s)\n",
|
|
|
- state_string(state), state_string(cur_state));
|
|
|
+ onoff(state), onoff(cur_state));
|
|
|
}
|
|
|
|
|
|
void assert_panel_unlocked(struct drm_i915_private *dev_priv,
|
|
@@ -1340,7 +1332,7 @@ static void assert_cursor(struct drm_i915_private *dev_priv,
|
|
|
|
|
|
I915_STATE_WARN(cur_state != state,
|
|
|
"cursor on pipe %c assertion failure (expected %s, current %s)\n",
|
|
|
- pipe_name(pipe), state_string(state), state_string(cur_state));
|
|
|
+ pipe_name(pipe), onoff(state), onoff(cur_state));
|
|
|
}
|
|
|
#define assert_cursor_enabled(d, p) assert_cursor(d, p, true)
|
|
|
#define assert_cursor_disabled(d, p) assert_cursor(d, p, false)
|
|
@@ -1367,7 +1359,7 @@ void assert_pipe(struct drm_i915_private *dev_priv,
|
|
|
|
|
|
I915_STATE_WARN(cur_state != state,
|
|
|
"pipe %c assertion failure (expected %s, current %s)\n",
|
|
|
- pipe_name(pipe), state_string(state), state_string(cur_state));
|
|
|
+ pipe_name(pipe), onoff(state), onoff(cur_state));
|
|
|
}
|
|
|
|
|
|
static void assert_plane(struct drm_i915_private *dev_priv,
|
|
@@ -1380,7 +1372,7 @@ static void assert_plane(struct drm_i915_private *dev_priv,
|
|
|
cur_state = !!(val & DISPLAY_PLANE_ENABLE);
|
|
|
I915_STATE_WARN(cur_state != state,
|
|
|
"plane %c assertion failure (expected %s, current %s)\n",
|
|
|
- plane_name(plane), state_string(state), state_string(cur_state));
|
|
|
+ plane_name(plane), onoff(state), onoff(cur_state));
|
|
|
}
|
|
|
|
|
|
#define assert_plane_enabled(d, p) assert_plane(d, p, true)
|
|
@@ -2153,6 +2145,17 @@ static void intel_enable_pipe(struct intel_crtc *crtc)
|
|
|
|
|
|
I915_WRITE(reg, val | PIPECONF_ENABLE);
|
|
|
POSTING_READ(reg);
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Until the pipe starts DSL will read as 0, which would cause
|
|
|
+ * an apparent vblank timestamp jump, which messes up also the
|
|
|
+ * frame count when it's derived from the timestamps. So let's
|
|
|
+ * wait for the pipe to start properly before we call
|
|
|
+ * drm_crtc_vblank_on()
|
|
|
+ */
|
|
|
+ if (dev->max_vblank_count == 0 &&
|
|
|
+ wait_for(intel_get_crtc_scanline(crtc) != crtc->scanline_offset, 50))
|
|
|
+ DRM_ERROR("pipe %c didn't start\n", pipe_name(pipe));
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -2214,67 +2217,75 @@ static bool need_vtd_wa(struct drm_device *dev)
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
-unsigned int
|
|
|
-intel_tile_height(struct drm_device *dev, uint32_t pixel_format,
|
|
|
- uint64_t fb_format_modifier, unsigned int plane)
|
|
|
+static unsigned int intel_tile_size(const struct drm_i915_private *dev_priv)
|
|
|
{
|
|
|
- unsigned int tile_height;
|
|
|
- uint32_t pixel_bytes;
|
|
|
+ return IS_GEN2(dev_priv) ? 2048 : 4096;
|
|
|
+}
|
|
|
|
|
|
- switch (fb_format_modifier) {
|
|
|
+static unsigned int intel_tile_width(const struct drm_i915_private *dev_priv,
|
|
|
+ uint64_t fb_modifier, unsigned int cpp)
|
|
|
+{
|
|
|
+ switch (fb_modifier) {
|
|
|
case DRM_FORMAT_MOD_NONE:
|
|
|
- tile_height = 1;
|
|
|
- break;
|
|
|
+ return cpp;
|
|
|
case I915_FORMAT_MOD_X_TILED:
|
|
|
- tile_height = IS_GEN2(dev) ? 16 : 8;
|
|
|
- break;
|
|
|
+ if (IS_GEN2(dev_priv))
|
|
|
+ return 128;
|
|
|
+ else
|
|
|
+ return 512;
|
|
|
case I915_FORMAT_MOD_Y_TILED:
|
|
|
- tile_height = 32;
|
|
|
- break;
|
|
|
+ if (IS_GEN2(dev_priv) || HAS_128_BYTE_Y_TILING(dev_priv))
|
|
|
+ return 128;
|
|
|
+ else
|
|
|
+ return 512;
|
|
|
case I915_FORMAT_MOD_Yf_TILED:
|
|
|
- pixel_bytes = drm_format_plane_cpp(pixel_format, plane);
|
|
|
- switch (pixel_bytes) {
|
|
|
- default:
|
|
|
+ switch (cpp) {
|
|
|
case 1:
|
|
|
- tile_height = 64;
|
|
|
- break;
|
|
|
+ return 64;
|
|
|
case 2:
|
|
|
case 4:
|
|
|
- tile_height = 32;
|
|
|
- break;
|
|
|
+ return 128;
|
|
|
case 8:
|
|
|
- tile_height = 16;
|
|
|
- break;
|
|
|
case 16:
|
|
|
- WARN_ONCE(1,
|
|
|
- "128-bit pixels are not supported for display!");
|
|
|
- tile_height = 16;
|
|
|
- break;
|
|
|
+ return 256;
|
|
|
+ default:
|
|
|
+ MISSING_CASE(cpp);
|
|
|
+ return cpp;
|
|
|
}
|
|
|
break;
|
|
|
default:
|
|
|
- MISSING_CASE(fb_format_modifier);
|
|
|
- tile_height = 1;
|
|
|
- break;
|
|
|
+ MISSING_CASE(fb_modifier);
|
|
|
+ return cpp;
|
|
|
}
|
|
|
+}
|
|
|
|
|
|
- return tile_height;
|
|
|
+unsigned int intel_tile_height(const struct drm_i915_private *dev_priv,
|
|
|
+ uint64_t fb_modifier, unsigned int cpp)
|
|
|
+{
|
|
|
+ if (fb_modifier == DRM_FORMAT_MOD_NONE)
|
|
|
+ return 1;
|
|
|
+ else
|
|
|
+ return intel_tile_size(dev_priv) /
|
|
|
+ intel_tile_width(dev_priv, fb_modifier, cpp);
|
|
|
}
|
|
|
|
|
|
unsigned int
|
|
|
intel_fb_align_height(struct drm_device *dev, unsigned int height,
|
|
|
- uint32_t pixel_format, uint64_t fb_format_modifier)
|
|
|
+ uint32_t pixel_format, uint64_t fb_modifier)
|
|
|
{
|
|
|
- return ALIGN(height, intel_tile_height(dev, pixel_format,
|
|
|
- fb_format_modifier, 0));
|
|
|
+ unsigned int cpp = drm_format_plane_cpp(pixel_format, 0);
|
|
|
+ unsigned int tile_height = intel_tile_height(to_i915(dev), fb_modifier, cpp);
|
|
|
+
|
|
|
+ return ALIGN(height, tile_height);
|
|
|
}
|
|
|
|
|
|
static void
|
|
|
intel_fill_fb_ggtt_view(struct i915_ggtt_view *view, struct drm_framebuffer *fb,
|
|
|
const struct drm_plane_state *plane_state)
|
|
|
{
|
|
|
+ struct drm_i915_private *dev_priv = to_i915(fb->dev);
|
|
|
struct intel_rotation_info *info = &view->params.rotation_info;
|
|
|
- unsigned int tile_height, tile_pitch;
|
|
|
+ unsigned int tile_size, tile_width, tile_height, cpp;
|
|
|
|
|
|
*view = i915_ggtt_view_normal;
|
|
|
|
|
@@ -2292,26 +2303,28 @@ intel_fill_fb_ggtt_view(struct i915_ggtt_view *view, struct drm_framebuffer *fb,
|
|
|
info->uv_offset = fb->offsets[1];
|
|
|
info->fb_modifier = fb->modifier[0];
|
|
|
|
|
|
- tile_height = intel_tile_height(fb->dev, fb->pixel_format,
|
|
|
- fb->modifier[0], 0);
|
|
|
- tile_pitch = PAGE_SIZE / tile_height;
|
|
|
- info->width_pages = DIV_ROUND_UP(fb->pitches[0], tile_pitch);
|
|
|
+ tile_size = intel_tile_size(dev_priv);
|
|
|
+
|
|
|
+ cpp = drm_format_plane_cpp(fb->pixel_format, 0);
|
|
|
+ tile_width = intel_tile_width(dev_priv, cpp, fb->modifier[0]);
|
|
|
+ tile_height = tile_size / tile_width;
|
|
|
+
|
|
|
+ info->width_pages = DIV_ROUND_UP(fb->pitches[0], tile_width);
|
|
|
info->height_pages = DIV_ROUND_UP(fb->height, tile_height);
|
|
|
- info->size = info->width_pages * info->height_pages * PAGE_SIZE;
|
|
|
+ info->size = info->width_pages * info->height_pages * tile_size;
|
|
|
|
|
|
if (info->pixel_format == DRM_FORMAT_NV12) {
|
|
|
- tile_height = intel_tile_height(fb->dev, fb->pixel_format,
|
|
|
- fb->modifier[0], 1);
|
|
|
- tile_pitch = PAGE_SIZE / tile_height;
|
|
|
- info->width_pages_uv = DIV_ROUND_UP(fb->pitches[0], tile_pitch);
|
|
|
- info->height_pages_uv = DIV_ROUND_UP(fb->height / 2,
|
|
|
- tile_height);
|
|
|
- info->size_uv = info->width_pages_uv * info->height_pages_uv *
|
|
|
- PAGE_SIZE;
|
|
|
+ cpp = drm_format_plane_cpp(fb->pixel_format, 1);
|
|
|
+ tile_width = intel_tile_width(dev_priv, fb->modifier[1], cpp);
|
|
|
+ tile_height = tile_size / tile_width;
|
|
|
+
|
|
|
+ info->width_pages_uv = DIV_ROUND_UP(fb->pitches[1], tile_width);
|
|
|
+ info->height_pages_uv = DIV_ROUND_UP(fb->height / 2, tile_height);
|
|
|
+ info->size_uv = info->width_pages_uv * info->height_pages_uv * tile_size;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-static unsigned int intel_linear_alignment(struct drm_i915_private *dev_priv)
|
|
|
+static unsigned int intel_linear_alignment(const struct drm_i915_private *dev_priv)
|
|
|
{
|
|
|
if (INTEL_INFO(dev_priv)->gen >= 9)
|
|
|
return 256 * 1024;
|
|
@@ -2324,6 +2337,25 @@ static unsigned int intel_linear_alignment(struct drm_i915_private *dev_priv)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+static unsigned int intel_surf_alignment(const struct drm_i915_private *dev_priv,
|
|
|
+ uint64_t fb_modifier)
|
|
|
+{
|
|
|
+ switch (fb_modifier) {
|
|
|
+ case DRM_FORMAT_MOD_NONE:
|
|
|
+ return intel_linear_alignment(dev_priv);
|
|
|
+ case I915_FORMAT_MOD_X_TILED:
|
|
|
+ if (INTEL_INFO(dev_priv)->gen >= 9)
|
|
|
+ return 256 * 1024;
|
|
|
+ return 0;
|
|
|
+ case I915_FORMAT_MOD_Y_TILED:
|
|
|
+ case I915_FORMAT_MOD_Yf_TILED:
|
|
|
+ return 1 * 1024 * 1024;
|
|
|
+ default:
|
|
|
+ MISSING_CASE(fb_modifier);
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
int
|
|
|
intel_pin_and_fence_fb_obj(struct drm_plane *plane,
|
|
|
struct drm_framebuffer *fb,
|
|
@@ -2338,29 +2370,7 @@ intel_pin_and_fence_fb_obj(struct drm_plane *plane,
|
|
|
|
|
|
WARN_ON(!mutex_is_locked(&dev->struct_mutex));
|
|
|
|
|
|
- switch (fb->modifier[0]) {
|
|
|
- case DRM_FORMAT_MOD_NONE:
|
|
|
- alignment = intel_linear_alignment(dev_priv);
|
|
|
- break;
|
|
|
- case I915_FORMAT_MOD_X_TILED:
|
|
|
- if (INTEL_INFO(dev)->gen >= 9)
|
|
|
- alignment = 256 * 1024;
|
|
|
- else {
|
|
|
- /* pin() will align the object as required by fence */
|
|
|
- alignment = 0;
|
|
|
- }
|
|
|
- break;
|
|
|
- case I915_FORMAT_MOD_Y_TILED:
|
|
|
- case I915_FORMAT_MOD_Yf_TILED:
|
|
|
- if (WARN_ONCE(INTEL_INFO(dev)->gen < 9,
|
|
|
- "Y tiling bo slipped through, driver bug!\n"))
|
|
|
- return -EINVAL;
|
|
|
- alignment = 1 * 1024 * 1024;
|
|
|
- break;
|
|
|
- default:
|
|
|
- MISSING_CASE(fb->modifier[0]);
|
|
|
- return -EINVAL;
|
|
|
- }
|
|
|
+ alignment = intel_surf_alignment(dev_priv, fb->modifier[0]);
|
|
|
|
|
|
intel_fill_fb_ggtt_view(&view, fb, plane_state);
|
|
|
|
|
@@ -2438,22 +2448,27 @@ static void intel_unpin_fb_obj(struct drm_framebuffer *fb,
|
|
|
|
|
|
/* Computes the linear offset to the base tile and adjusts x, y. bytes per pixel
|
|
|
* is assumed to be a power-of-two. */
|
|
|
-unsigned long intel_gen4_compute_page_offset(struct drm_i915_private *dev_priv,
|
|
|
- int *x, int *y,
|
|
|
- unsigned int tiling_mode,
|
|
|
- unsigned int cpp,
|
|
|
- unsigned int pitch)
|
|
|
-{
|
|
|
- if (tiling_mode != I915_TILING_NONE) {
|
|
|
+unsigned long intel_compute_tile_offset(struct drm_i915_private *dev_priv,
|
|
|
+ int *x, int *y,
|
|
|
+ uint64_t fb_modifier,
|
|
|
+ unsigned int cpp,
|
|
|
+ unsigned int pitch)
|
|
|
+{
|
|
|
+ if (fb_modifier != DRM_FORMAT_MOD_NONE) {
|
|
|
+ unsigned int tile_size, tile_width, tile_height;
|
|
|
unsigned int tile_rows, tiles;
|
|
|
|
|
|
- tile_rows = *y / 8;
|
|
|
- *y %= 8;
|
|
|
+ tile_size = intel_tile_size(dev_priv);
|
|
|
+ tile_width = intel_tile_width(dev_priv, fb_modifier, cpp);
|
|
|
+ tile_height = tile_size / tile_width;
|
|
|
|
|
|
- tiles = *x / (512/cpp);
|
|
|
- *x %= 512/cpp;
|
|
|
+ tile_rows = *y / tile_height;
|
|
|
+ *y %= tile_height;
|
|
|
|
|
|
- return tile_rows * pitch * 8 + tiles * 4096;
|
|
|
+ tiles = *x / (tile_width/cpp);
|
|
|
+ *x %= tile_width/cpp;
|
|
|
+
|
|
|
+ return tile_rows * pitch * tile_height + tiles * tile_size;
|
|
|
} else {
|
|
|
unsigned int alignment = intel_linear_alignment(dev_priv) - 1;
|
|
|
unsigned int offset;
|
|
@@ -2598,6 +2613,8 @@ intel_find_initial_plane_obj(struct intel_crtc *intel_crtc,
|
|
|
struct drm_plane_state *plane_state = primary->state;
|
|
|
struct drm_crtc_state *crtc_state = intel_crtc->base.state;
|
|
|
struct intel_plane *intel_plane = to_intel_plane(primary);
|
|
|
+ struct intel_plane_state *intel_state =
|
|
|
+ to_intel_plane_state(plane_state);
|
|
|
struct drm_framebuffer *fb;
|
|
|
|
|
|
if (!plane_config->fb)
|
|
@@ -2659,6 +2676,15 @@ valid_fb:
|
|
|
plane_state->crtc_w = fb->width;
|
|
|
plane_state->crtc_h = fb->height;
|
|
|
|
|
|
+ intel_state->src.x1 = plane_state->src_x;
|
|
|
+ intel_state->src.y1 = plane_state->src_y;
|
|
|
+ intel_state->src.x2 = plane_state->src_x + plane_state->src_w;
|
|
|
+ intel_state->src.y2 = plane_state->src_y + plane_state->src_h;
|
|
|
+ intel_state->dst.x1 = plane_state->crtc_x;
|
|
|
+ intel_state->dst.y1 = plane_state->crtc_y;
|
|
|
+ intel_state->dst.x2 = plane_state->crtc_x + plane_state->crtc_w;
|
|
|
+ intel_state->dst.y2 = plane_state->crtc_y + plane_state->crtc_h;
|
|
|
+
|
|
|
obj = intel_fb_obj(fb);
|
|
|
if (obj->tiling_mode != I915_TILING_NONE)
|
|
|
dev_priv->preserve_bios_swizzle = true;
|
|
@@ -2670,36 +2696,23 @@ valid_fb:
|
|
|
obj->frontbuffer_bits |= to_intel_plane(primary)->frontbuffer_bit;
|
|
|
}
|
|
|
|
|
|
-static void i9xx_update_primary_plane(struct drm_crtc *crtc,
|
|
|
- struct drm_framebuffer *fb,
|
|
|
- int x, int y)
|
|
|
+static void i9xx_update_primary_plane(struct drm_plane *primary,
|
|
|
+ const struct intel_crtc_state *crtc_state,
|
|
|
+ const struct intel_plane_state *plane_state)
|
|
|
{
|
|
|
- struct drm_device *dev = crtc->dev;
|
|
|
+ struct drm_device *dev = primary->dev;
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
- struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
|
|
- struct drm_plane *primary = crtc->primary;
|
|
|
- bool visible = to_intel_plane_state(primary->state)->visible;
|
|
|
- struct drm_i915_gem_object *obj;
|
|
|
+ struct intel_crtc *intel_crtc = to_intel_crtc(crtc_state->base.crtc);
|
|
|
+ struct drm_framebuffer *fb = plane_state->base.fb;
|
|
|
+ struct drm_i915_gem_object *obj = intel_fb_obj(fb);
|
|
|
int plane = intel_crtc->plane;
|
|
|
unsigned long linear_offset;
|
|
|
+ int x = plane_state->src.x1 >> 16;
|
|
|
+ int y = plane_state->src.y1 >> 16;
|
|
|
u32 dspcntr;
|
|
|
i915_reg_t reg = DSPCNTR(plane);
|
|
|
int pixel_size;
|
|
|
|
|
|
- if (!visible || !fb) {
|
|
|
- I915_WRITE(reg, 0);
|
|
|
- if (INTEL_INFO(dev)->gen >= 4)
|
|
|
- I915_WRITE(DSPSURF(plane), 0);
|
|
|
- else
|
|
|
- I915_WRITE(DSPADDR(plane), 0);
|
|
|
- POSTING_READ(reg);
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- obj = intel_fb_obj(fb);
|
|
|
- if (WARN_ON(obj == NULL))
|
|
|
- return;
|
|
|
-
|
|
|
pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
|
|
|
|
|
|
dspcntr = DISPPLANE_GAMMA_ENABLE;
|
|
@@ -2714,13 +2727,13 @@ static void i9xx_update_primary_plane(struct drm_crtc *crtc,
|
|
|
* which should always be the user's requested size.
|
|
|
*/
|
|
|
I915_WRITE(DSPSIZE(plane),
|
|
|
- ((intel_crtc->config->pipe_src_h - 1) << 16) |
|
|
|
- (intel_crtc->config->pipe_src_w - 1));
|
|
|
+ ((crtc_state->pipe_src_h - 1) << 16) |
|
|
|
+ (crtc_state->pipe_src_w - 1));
|
|
|
I915_WRITE(DSPPOS(plane), 0);
|
|
|
} else if (IS_CHERRYVIEW(dev) && plane == PLANE_B) {
|
|
|
I915_WRITE(PRIMSIZE(plane),
|
|
|
- ((intel_crtc->config->pipe_src_h - 1) << 16) |
|
|
|
- (intel_crtc->config->pipe_src_w - 1));
|
|
|
+ ((crtc_state->pipe_src_h - 1) << 16) |
|
|
|
+ (crtc_state->pipe_src_w - 1));
|
|
|
I915_WRITE(PRIMPOS(plane), 0);
|
|
|
I915_WRITE(PRIMCNSTALPHA(plane), 0);
|
|
|
}
|
|
@@ -2762,26 +2775,26 @@ static void i9xx_update_primary_plane(struct drm_crtc *crtc,
|
|
|
|
|
|
if (INTEL_INFO(dev)->gen >= 4) {
|
|
|
intel_crtc->dspaddr_offset =
|
|
|
- intel_gen4_compute_page_offset(dev_priv,
|
|
|
- &x, &y, obj->tiling_mode,
|
|
|
- pixel_size,
|
|
|
- fb->pitches[0]);
|
|
|
+ intel_compute_tile_offset(dev_priv, &x, &y,
|
|
|
+ fb->modifier[0],
|
|
|
+ pixel_size,
|
|
|
+ fb->pitches[0]);
|
|
|
linear_offset -= intel_crtc->dspaddr_offset;
|
|
|
} else {
|
|
|
intel_crtc->dspaddr_offset = linear_offset;
|
|
|
}
|
|
|
|
|
|
- if (crtc->primary->state->rotation == BIT(DRM_ROTATE_180)) {
|
|
|
+ if (plane_state->base.rotation == BIT(DRM_ROTATE_180)) {
|
|
|
dspcntr |= DISPPLANE_ROTATE_180;
|
|
|
|
|
|
- x += (intel_crtc->config->pipe_src_w - 1);
|
|
|
- y += (intel_crtc->config->pipe_src_h - 1);
|
|
|
+ x += (crtc_state->pipe_src_w - 1);
|
|
|
+ y += (crtc_state->pipe_src_h - 1);
|
|
|
|
|
|
/* Finding the last pixel of the last line of the display
|
|
|
data and adding to linear_offset*/
|
|
|
linear_offset +=
|
|
|
- (intel_crtc->config->pipe_src_h - 1) * fb->pitches[0] +
|
|
|
- (intel_crtc->config->pipe_src_w - 1) * pixel_size;
|
|
|
+ (crtc_state->pipe_src_h - 1) * fb->pitches[0] +
|
|
|
+ (crtc_state->pipe_src_w - 1) * pixel_size;
|
|
|
}
|
|
|
|
|
|
intel_crtc->adjusted_x = x;
|
|
@@ -2800,37 +2813,40 @@ static void i9xx_update_primary_plane(struct drm_crtc *crtc,
|
|
|
POSTING_READ(reg);
|
|
|
}
|
|
|
|
|
|
-static void ironlake_update_primary_plane(struct drm_crtc *crtc,
|
|
|
- struct drm_framebuffer *fb,
|
|
|
- int x, int y)
|
|
|
+static void i9xx_disable_primary_plane(struct drm_plane *primary,
|
|
|
+ struct drm_crtc *crtc)
|
|
|
{
|
|
|
struct drm_device *dev = crtc->dev;
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
|
|
- struct drm_plane *primary = crtc->primary;
|
|
|
- bool visible = to_intel_plane_state(primary->state)->visible;
|
|
|
- struct drm_i915_gem_object *obj;
|
|
|
int plane = intel_crtc->plane;
|
|
|
- unsigned long linear_offset;
|
|
|
- u32 dspcntr;
|
|
|
- i915_reg_t reg = DSPCNTR(plane);
|
|
|
- int pixel_size;
|
|
|
|
|
|
- if (!visible || !fb) {
|
|
|
- I915_WRITE(reg, 0);
|
|
|
+ I915_WRITE(DSPCNTR(plane), 0);
|
|
|
+ if (INTEL_INFO(dev_priv)->gen >= 4)
|
|
|
I915_WRITE(DSPSURF(plane), 0);
|
|
|
- POSTING_READ(reg);
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- obj = intel_fb_obj(fb);
|
|
|
- if (WARN_ON(obj == NULL))
|
|
|
- return;
|
|
|
+ else
|
|
|
+ I915_WRITE(DSPADDR(plane), 0);
|
|
|
+ POSTING_READ(DSPCNTR(plane));
|
|
|
+}
|
|
|
|
|
|
- pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
|
|
|
+static void ironlake_update_primary_plane(struct drm_plane *primary,
|
|
|
+ const struct intel_crtc_state *crtc_state,
|
|
|
+ const struct intel_plane_state *plane_state)
|
|
|
+{
|
|
|
+ struct drm_device *dev = primary->dev;
|
|
|
+ struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
+ struct intel_crtc *intel_crtc = to_intel_crtc(crtc_state->base.crtc);
|
|
|
+ struct drm_framebuffer *fb = plane_state->base.fb;
|
|
|
+ struct drm_i915_gem_object *obj = intel_fb_obj(fb);
|
|
|
+ int plane = intel_crtc->plane;
|
|
|
+ unsigned long linear_offset;
|
|
|
+ u32 dspcntr;
|
|
|
+ i915_reg_t reg = DSPCNTR(plane);
|
|
|
+ int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
|
|
|
+ int x = plane_state->src.x1 >> 16;
|
|
|
+ int y = plane_state->src.y1 >> 16;
|
|
|
|
|
|
dspcntr = DISPPLANE_GAMMA_ENABLE;
|
|
|
-
|
|
|
dspcntr |= DISPLAY_PLANE_ENABLE;
|
|
|
|
|
|
if (IS_HASWELL(dev) || IS_BROADWELL(dev))
|
|
@@ -2867,23 +2883,23 @@ static void ironlake_update_primary_plane(struct drm_crtc *crtc,
|
|
|
|
|
|
linear_offset = y * fb->pitches[0] + x * pixel_size;
|
|
|
intel_crtc->dspaddr_offset =
|
|
|
- intel_gen4_compute_page_offset(dev_priv,
|
|
|
- &x, &y, obj->tiling_mode,
|
|
|
- pixel_size,
|
|
|
- fb->pitches[0]);
|
|
|
+ intel_compute_tile_offset(dev_priv, &x, &y,
|
|
|
+ fb->modifier[0],
|
|
|
+ pixel_size,
|
|
|
+ fb->pitches[0]);
|
|
|
linear_offset -= intel_crtc->dspaddr_offset;
|
|
|
- if (crtc->primary->state->rotation == BIT(DRM_ROTATE_180)) {
|
|
|
+ if (plane_state->base.rotation == BIT(DRM_ROTATE_180)) {
|
|
|
dspcntr |= DISPPLANE_ROTATE_180;
|
|
|
|
|
|
if (!IS_HASWELL(dev) && !IS_BROADWELL(dev)) {
|
|
|
- x += (intel_crtc->config->pipe_src_w - 1);
|
|
|
- y += (intel_crtc->config->pipe_src_h - 1);
|
|
|
+ x += (crtc_state->pipe_src_w - 1);
|
|
|
+ y += (crtc_state->pipe_src_h - 1);
|
|
|
|
|
|
/* Finding the last pixel of the last line of the display
|
|
|
data and adding to linear_offset*/
|
|
|
linear_offset +=
|
|
|
- (intel_crtc->config->pipe_src_h - 1) * fb->pitches[0] +
|
|
|
- (intel_crtc->config->pipe_src_w - 1) * pixel_size;
|
|
|
+ (crtc_state->pipe_src_h - 1) * fb->pitches[0] +
|
|
|
+ (crtc_state->pipe_src_w - 1) * pixel_size;
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -2904,37 +2920,15 @@ static void ironlake_update_primary_plane(struct drm_crtc *crtc,
|
|
|
POSTING_READ(reg);
|
|
|
}
|
|
|
|
|
|
-u32 intel_fb_stride_alignment(struct drm_device *dev, uint64_t fb_modifier,
|
|
|
- uint32_t pixel_format)
|
|
|
+u32 intel_fb_stride_alignment(const struct drm_i915_private *dev_priv,
|
|
|
+ uint64_t fb_modifier, uint32_t pixel_format)
|
|
|
{
|
|
|
- u32 bits_per_pixel = drm_format_plane_cpp(pixel_format, 0) * 8;
|
|
|
-
|
|
|
- /*
|
|
|
- * The stride is either expressed as a multiple of 64 bytes
|
|
|
- * chunks for linear buffers or in number of tiles for tiled
|
|
|
- * buffers.
|
|
|
- */
|
|
|
- switch (fb_modifier) {
|
|
|
- case DRM_FORMAT_MOD_NONE:
|
|
|
- return 64;
|
|
|
- case I915_FORMAT_MOD_X_TILED:
|
|
|
- if (INTEL_INFO(dev)->gen == 2)
|
|
|
- return 128;
|
|
|
- return 512;
|
|
|
- case I915_FORMAT_MOD_Y_TILED:
|
|
|
- /* No need to check for old gens and Y tiling since this is
|
|
|
- * about the display engine and those will be blocked before
|
|
|
- * we get here.
|
|
|
- */
|
|
|
- return 128;
|
|
|
- case I915_FORMAT_MOD_Yf_TILED:
|
|
|
- if (bits_per_pixel == 8)
|
|
|
- return 64;
|
|
|
- else
|
|
|
- return 128;
|
|
|
- default:
|
|
|
- MISSING_CASE(fb_modifier);
|
|
|
+ if (fb_modifier == DRM_FORMAT_MOD_NONE) {
|
|
|
return 64;
|
|
|
+ } else {
|
|
|
+ int cpp = drm_format_plane_cpp(pixel_format, 0);
|
|
|
+
|
|
|
+ return intel_tile_width(dev_priv, fb_modifier, cpp);
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -3074,36 +3068,30 @@ u32 skl_plane_ctl_rotation(unsigned int rotation)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-static void skylake_update_primary_plane(struct drm_crtc *crtc,
|
|
|
- struct drm_framebuffer *fb,
|
|
|
- int x, int y)
|
|
|
+static void skylake_update_primary_plane(struct drm_plane *plane,
|
|
|
+ const struct intel_crtc_state *crtc_state,
|
|
|
+ const struct intel_plane_state *plane_state)
|
|
|
{
|
|
|
- struct drm_device *dev = crtc->dev;
|
|
|
+ struct drm_device *dev = plane->dev;
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
- struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
|
|
- struct drm_plane *plane = crtc->primary;
|
|
|
- bool visible = to_intel_plane_state(plane->state)->visible;
|
|
|
- struct drm_i915_gem_object *obj;
|
|
|
+ struct intel_crtc *intel_crtc = to_intel_crtc(crtc_state->base.crtc);
|
|
|
+ struct drm_framebuffer *fb = plane_state->base.fb;
|
|
|
+ struct drm_i915_gem_object *obj = intel_fb_obj(fb);
|
|
|
int pipe = intel_crtc->pipe;
|
|
|
u32 plane_ctl, stride_div, stride;
|
|
|
u32 tile_height, plane_offset, plane_size;
|
|
|
- unsigned int rotation;
|
|
|
+ unsigned int rotation = plane_state->base.rotation;
|
|
|
int x_offset, y_offset;
|
|
|
u32 surf_addr;
|
|
|
- struct intel_crtc_state *crtc_state = intel_crtc->config;
|
|
|
- struct intel_plane_state *plane_state;
|
|
|
- int src_x = 0, src_y = 0, src_w = 0, src_h = 0;
|
|
|
- int dst_x = 0, dst_y = 0, dst_w = 0, dst_h = 0;
|
|
|
- int scaler_id = -1;
|
|
|
-
|
|
|
- plane_state = to_intel_plane_state(plane->state);
|
|
|
-
|
|
|
- if (!visible || !fb) {
|
|
|
- I915_WRITE(PLANE_CTL(pipe, 0), 0);
|
|
|
- I915_WRITE(PLANE_SURF(pipe, 0), 0);
|
|
|
- POSTING_READ(PLANE_CTL(pipe, 0));
|
|
|
- return;
|
|
|
- }
|
|
|
+ int scaler_id = plane_state->scaler_id;
|
|
|
+ int src_x = plane_state->src.x1 >> 16;
|
|
|
+ int src_y = plane_state->src.y1 >> 16;
|
|
|
+ int src_w = drm_rect_width(&plane_state->src) >> 16;
|
|
|
+ int src_h = drm_rect_height(&plane_state->src) >> 16;
|
|
|
+ int dst_x = plane_state->dst.x1;
|
|
|
+ int dst_y = plane_state->dst.y1;
|
|
|
+ int dst_w = drm_rect_width(&plane_state->dst);
|
|
|
+ int dst_h = drm_rect_height(&plane_state->dst);
|
|
|
|
|
|
plane_ctl = PLANE_CTL_ENABLE |
|
|
|
PLANE_CTL_PIPE_GAMMA_ENABLE |
|
|
@@ -3112,41 +3100,27 @@ static void skylake_update_primary_plane(struct drm_crtc *crtc,
|
|
|
plane_ctl |= skl_plane_ctl_format(fb->pixel_format);
|
|
|
plane_ctl |= skl_plane_ctl_tiling(fb->modifier[0]);
|
|
|
plane_ctl |= PLANE_CTL_PLANE_GAMMA_DISABLE;
|
|
|
-
|
|
|
- rotation = plane->state->rotation;
|
|
|
plane_ctl |= skl_plane_ctl_rotation(rotation);
|
|
|
|
|
|
- obj = intel_fb_obj(fb);
|
|
|
- stride_div = intel_fb_stride_alignment(dev, fb->modifier[0],
|
|
|
+ stride_div = intel_fb_stride_alignment(dev_priv, fb->modifier[0],
|
|
|
fb->pixel_format);
|
|
|
surf_addr = intel_plane_obj_offset(to_intel_plane(plane), obj, 0);
|
|
|
|
|
|
WARN_ON(drm_rect_width(&plane_state->src) == 0);
|
|
|
|
|
|
- scaler_id = plane_state->scaler_id;
|
|
|
- src_x = plane_state->src.x1 >> 16;
|
|
|
- src_y = plane_state->src.y1 >> 16;
|
|
|
- src_w = drm_rect_width(&plane_state->src) >> 16;
|
|
|
- src_h = drm_rect_height(&plane_state->src) >> 16;
|
|
|
- dst_x = plane_state->dst.x1;
|
|
|
- dst_y = plane_state->dst.y1;
|
|
|
- dst_w = drm_rect_width(&plane_state->dst);
|
|
|
- dst_h = drm_rect_height(&plane_state->dst);
|
|
|
-
|
|
|
- WARN_ON(x != src_x || y != src_y);
|
|
|
-
|
|
|
if (intel_rotation_90_or_270(rotation)) {
|
|
|
+ int cpp = drm_format_plane_cpp(fb->pixel_format, 0);
|
|
|
+
|
|
|
/* stride = Surface height in tiles */
|
|
|
- tile_height = intel_tile_height(dev, fb->pixel_format,
|
|
|
- fb->modifier[0], 0);
|
|
|
+ tile_height = intel_tile_height(dev_priv, fb->modifier[0], cpp);
|
|
|
stride = DIV_ROUND_UP(fb->height, tile_height);
|
|
|
- x_offset = stride * tile_height - y - src_h;
|
|
|
- y_offset = x;
|
|
|
+ x_offset = stride * tile_height - src_y - src_h;
|
|
|
+ y_offset = src_x;
|
|
|
plane_size = (src_w - 1) << 16 | (src_h - 1);
|
|
|
} else {
|
|
|
stride = fb->pitches[0] / stride_div;
|
|
|
- x_offset = x;
|
|
|
- y_offset = y;
|
|
|
+ x_offset = src_x;
|
|
|
+ y_offset = src_y;
|
|
|
plane_size = (src_h - 1) << 16 | (src_w - 1);
|
|
|
}
|
|
|
plane_offset = y_offset << 16 | x_offset;
|
|
@@ -3179,20 +3153,30 @@ static void skylake_update_primary_plane(struct drm_crtc *crtc,
|
|
|
POSTING_READ(PLANE_SURF(pipe, 0));
|
|
|
}
|
|
|
|
|
|
-/* Assume fb object is pinned & idle & fenced and just update base pointers */
|
|
|
-static int
|
|
|
-intel_pipe_set_base_atomic(struct drm_crtc *crtc, struct drm_framebuffer *fb,
|
|
|
- int x, int y, enum mode_set_atomic state)
|
|
|
+static void skylake_disable_primary_plane(struct drm_plane *primary,
|
|
|
+ struct drm_crtc *crtc)
|
|
|
{
|
|
|
struct drm_device *dev = crtc->dev;
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
+ int pipe = to_intel_crtc(crtc)->pipe;
|
|
|
|
|
|
if (dev_priv->fbc.deactivate)
|
|
|
dev_priv->fbc.deactivate(dev_priv);
|
|
|
|
|
|
- dev_priv->display.update_primary_plane(crtc, fb, x, y);
|
|
|
+ I915_WRITE(PLANE_CTL(pipe, 0), 0);
|
|
|
+ I915_WRITE(PLANE_SURF(pipe, 0), 0);
|
|
|
+ POSTING_READ(PLANE_SURF(pipe, 0));
|
|
|
+}
|
|
|
|
|
|
- return 0;
|
|
|
+/* Assume fb object is pinned & idle & fenced and just update base pointers */
|
|
|
+static int
|
|
|
+intel_pipe_set_base_atomic(struct drm_crtc *crtc, struct drm_framebuffer *fb,
|
|
|
+ int x, int y, enum mode_set_atomic state)
|
|
|
+{
|
|
|
+ /* Support for kgdboc is disabled, this needs a major rework. */
|
|
|
+ DRM_ERROR("legacy panic handler not supported any more.\n");
|
|
|
+
|
|
|
+ return -ENODEV;
|
|
|
}
|
|
|
|
|
|
static void intel_complete_page_flips(struct drm_device *dev)
|
|
@@ -3219,8 +3203,10 @@ static void intel_update_primary_planes(struct drm_device *dev)
|
|
|
drm_modeset_lock_crtc(crtc, &plane->base);
|
|
|
plane_state = to_intel_plane_state(plane->base.state);
|
|
|
|
|
|
- if (crtc->state->active && plane_state->base.fb)
|
|
|
- plane->commit_plane(&plane->base, plane_state);
|
|
|
+ if (plane_state->visible)
|
|
|
+ plane->update_plane(&plane->base,
|
|
|
+ to_intel_crtc_state(crtc->state),
|
|
|
+ plane_state);
|
|
|
|
|
|
drm_modeset_unlock_crtc(crtc);
|
|
|
}
|
|
@@ -4452,7 +4438,7 @@ int skl_update_scaler_crtc(struct intel_crtc_state *state)
|
|
|
intel_crtc->base.base.id, intel_crtc->pipe, SKL_CRTC_INDEX);
|
|
|
|
|
|
return skl_update_scaler(state, !state->base.active, SKL_CRTC_INDEX,
|
|
|
- &state->scaler_state.scaler_id, DRM_ROTATE_0,
|
|
|
+ &state->scaler_state.scaler_id, BIT(DRM_ROTATE_0),
|
|
|
state->pipe_src_w, state->pipe_src_h,
|
|
|
adjusted_mode->crtc_hdisplay, adjusted_mode->crtc_vdisplay);
|
|
|
}
|
|
@@ -5370,6 +5356,7 @@ static void modeset_put_power_domains(struct drm_i915_private *dev_priv,
|
|
|
|
|
|
static void modeset_update_crtc_power_domains(struct drm_atomic_state *state)
|
|
|
{
|
|
|
+ struct intel_atomic_state *intel_state = to_intel_atomic_state(state);
|
|
|
struct drm_device *dev = state->dev;
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
unsigned long put_domains[I915_MAX_PIPES] = {};
|
|
@@ -5383,13 +5370,9 @@ static void modeset_update_crtc_power_domains(struct drm_atomic_state *state)
|
|
|
modeset_get_crtc_power_domains(crtc);
|
|
|
}
|
|
|
|
|
|
- if (dev_priv->display.modeset_commit_cdclk) {
|
|
|
- unsigned int cdclk = to_intel_atomic_state(state)->cdclk;
|
|
|
-
|
|
|
- if (cdclk != dev_priv->cdclk_freq &&
|
|
|
- !WARN_ON(!state->allow_modeset))
|
|
|
- dev_priv->display.modeset_commit_cdclk(state);
|
|
|
- }
|
|
|
+ if (dev_priv->display.modeset_commit_cdclk &&
|
|
|
+ intel_state->dev_cdclk != dev_priv->cdclk_freq)
|
|
|
+ dev_priv->display.modeset_commit_cdclk(state);
|
|
|
|
|
|
for (i = 0; i < I915_MAX_PIPES; i++)
|
|
|
if (put_domains[i])
|
|
@@ -6063,22 +6046,31 @@ static int broxton_calc_cdclk(struct drm_i915_private *dev_priv,
|
|
|
static int intel_mode_max_pixclk(struct drm_device *dev,
|
|
|
struct drm_atomic_state *state)
|
|
|
{
|
|
|
- struct intel_crtc *intel_crtc;
|
|
|
- struct intel_crtc_state *crtc_state;
|
|
|
- int max_pixclk = 0;
|
|
|
+ struct intel_atomic_state *intel_state = to_intel_atomic_state(state);
|
|
|
+ struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
+ struct drm_crtc *crtc;
|
|
|
+ struct drm_crtc_state *crtc_state;
|
|
|
+ unsigned max_pixclk = 0, i;
|
|
|
+ enum pipe pipe;
|
|
|
|
|
|
- for_each_intel_crtc(dev, intel_crtc) {
|
|
|
- crtc_state = intel_atomic_get_crtc_state(state, intel_crtc);
|
|
|
- if (IS_ERR(crtc_state))
|
|
|
- return PTR_ERR(crtc_state);
|
|
|
+ memcpy(intel_state->min_pixclk, dev_priv->min_pixclk,
|
|
|
+ sizeof(intel_state->min_pixclk));
|
|
|
|
|
|
- if (!crtc_state->base.enable)
|
|
|
- continue;
|
|
|
+ for_each_crtc_in_state(state, crtc, crtc_state, i) {
|
|
|
+ int pixclk = 0;
|
|
|
|
|
|
- max_pixclk = max(max_pixclk,
|
|
|
- crtc_state->base.adjusted_mode.crtc_clock);
|
|
|
+ if (crtc_state->enable)
|
|
|
+ pixclk = crtc_state->adjusted_mode.crtc_clock;
|
|
|
+
|
|
|
+ intel_state->min_pixclk[i] = pixclk;
|
|
|
}
|
|
|
|
|
|
+ if (!intel_state->active_crtcs)
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ for_each_pipe(dev_priv, pipe)
|
|
|
+ max_pixclk = max(intel_state->min_pixclk[pipe], max_pixclk);
|
|
|
+
|
|
|
return max_pixclk;
|
|
|
}
|
|
|
|
|
@@ -6087,13 +6079,18 @@ static int valleyview_modeset_calc_cdclk(struct drm_atomic_state *state)
|
|
|
struct drm_device *dev = state->dev;
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
int max_pixclk = intel_mode_max_pixclk(dev, state);
|
|
|
+ struct intel_atomic_state *intel_state =
|
|
|
+ to_intel_atomic_state(state);
|
|
|
|
|
|
if (max_pixclk < 0)
|
|
|
return max_pixclk;
|
|
|
|
|
|
- to_intel_atomic_state(state)->cdclk =
|
|
|
+ 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;
|
|
|
}
|
|
|
|
|
@@ -6102,13 +6099,18 @@ static int broxton_modeset_calc_cdclk(struct drm_atomic_state *state)
|
|
|
struct drm_device *dev = state->dev;
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
int max_pixclk = intel_mode_max_pixclk(dev, state);
|
|
|
+ struct intel_atomic_state *intel_state =
|
|
|
+ to_intel_atomic_state(state);
|
|
|
|
|
|
if (max_pixclk < 0)
|
|
|
return max_pixclk;
|
|
|
|
|
|
- to_intel_atomic_state(state)->cdclk =
|
|
|
+ intel_state->cdclk = intel_state->dev_cdclk =
|
|
|
broxton_calc_cdclk(dev_priv, max_pixclk);
|
|
|
|
|
|
+ if (!intel_state->active_crtcs)
|
|
|
+ intel_state->dev_cdclk = broxton_calc_cdclk(dev_priv, 0);
|
|
|
+
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
@@ -6151,8 +6153,10 @@ static void vlv_program_pfi_credits(struct drm_i915_private *dev_priv)
|
|
|
static void valleyview_modeset_commit_cdclk(struct drm_atomic_state *old_state)
|
|
|
{
|
|
|
struct drm_device *dev = old_state->dev;
|
|
|
- unsigned int req_cdclk = to_intel_atomic_state(old_state)->cdclk;
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
+ 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
|
|
@@ -6383,6 +6387,9 @@ static void intel_crtc_disable_noatomic(struct drm_crtc *crtc)
|
|
|
for_each_power_domain(domain, domains)
|
|
|
intel_display_power_put(dev_priv, domain);
|
|
|
intel_crtc->enabled_power_domains = 0;
|
|
|
+
|
|
|
+ dev_priv->active_crtcs &= ~(1 << intel_crtc->pipe);
|
|
|
+ dev_priv->min_pixclk[intel_crtc->pipe] = 0;
|
|
|
}
|
|
|
|
|
|
/*
|
|
@@ -7593,26 +7600,34 @@ static void chv_prepare_pll(struct intel_crtc *crtc,
|
|
|
* in cases where we need the PLL enabled even when @pipe is not going to
|
|
|
* be enabled.
|
|
|
*/
|
|
|
-void vlv_force_pll_on(struct drm_device *dev, enum pipe pipe,
|
|
|
- const struct dpll *dpll)
|
|
|
+int vlv_force_pll_on(struct drm_device *dev, enum pipe pipe,
|
|
|
+ const struct dpll *dpll)
|
|
|
{
|
|
|
struct intel_crtc *crtc =
|
|
|
to_intel_crtc(intel_get_crtc_for_pipe(dev, pipe));
|
|
|
- struct intel_crtc_state pipe_config = {
|
|
|
- .base.crtc = &crtc->base,
|
|
|
- .pixel_multiplier = 1,
|
|
|
- .dpll = *dpll,
|
|
|
- };
|
|
|
+ struct intel_crtc_state *pipe_config;
|
|
|
+
|
|
|
+ pipe_config = kzalloc(sizeof(*pipe_config), GFP_KERNEL);
|
|
|
+ if (!pipe_config)
|
|
|
+ return -ENOMEM;
|
|
|
+
|
|
|
+ pipe_config->base.crtc = &crtc->base;
|
|
|
+ pipe_config->pixel_multiplier = 1;
|
|
|
+ pipe_config->dpll = *dpll;
|
|
|
|
|
|
if (IS_CHERRYVIEW(dev)) {
|
|
|
- chv_compute_dpll(crtc, &pipe_config);
|
|
|
- chv_prepare_pll(crtc, &pipe_config);
|
|
|
- chv_enable_pll(crtc, &pipe_config);
|
|
|
+ chv_compute_dpll(crtc, pipe_config);
|
|
|
+ chv_prepare_pll(crtc, pipe_config);
|
|
|
+ chv_enable_pll(crtc, pipe_config);
|
|
|
} else {
|
|
|
- vlv_compute_dpll(crtc, &pipe_config);
|
|
|
- vlv_prepare_pll(crtc, &pipe_config);
|
|
|
- vlv_enable_pll(crtc, &pipe_config);
|
|
|
+ vlv_compute_dpll(crtc, pipe_config);
|
|
|
+ vlv_prepare_pll(crtc, pipe_config);
|
|
|
+ vlv_enable_pll(crtc, pipe_config);
|
|
|
}
|
|
|
+
|
|
|
+ kfree(pipe_config);
|
|
|
+
|
|
|
+ return 0;
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -9246,7 +9261,7 @@ skylake_get_initial_plane_config(struct intel_crtc *crtc,
|
|
|
fb->width = ((val >> 0) & 0x1fff) + 1;
|
|
|
|
|
|
val = I915_READ(PLANE_STRIDE(pipe, 0));
|
|
|
- stride_mult = intel_fb_stride_alignment(dev, fb->modifier[0],
|
|
|
+ stride_mult = intel_fb_stride_alignment(dev_priv, fb->modifier[0],
|
|
|
fb->pixel_format);
|
|
|
fb->pitches[0] = (val & 0x3ff) * stride_mult;
|
|
|
|
|
@@ -9662,14 +9677,14 @@ void hsw_disable_pc8(struct drm_i915_private *dev_priv)
|
|
|
val |= PCH_LP_PARTITION_LEVEL_DISABLE;
|
|
|
I915_WRITE(SOUTH_DSPCLK_GATE_D, val);
|
|
|
}
|
|
|
-
|
|
|
- intel_prepare_ddi(dev);
|
|
|
}
|
|
|
|
|
|
static void broxton_modeset_commit_cdclk(struct drm_atomic_state *old_state)
|
|
|
{
|
|
|
struct drm_device *dev = old_state->dev;
|
|
|
- unsigned int req_cdclk = to_intel_atomic_state(old_state)->cdclk;
|
|
|
+ struct intel_atomic_state *old_intel_state =
|
|
|
+ to_intel_atomic_state(old_state);
|
|
|
+ unsigned int req_cdclk = old_intel_state->dev_cdclk;
|
|
|
|
|
|
broxton_set_cdclk(dev, req_cdclk);
|
|
|
}
|
|
@@ -9677,29 +9692,41 @@ static void broxton_modeset_commit_cdclk(struct drm_atomic_state *old_state)
|
|
|
/* compute the max rate for new configuration */
|
|
|
static int ilk_max_pixel_rate(struct drm_atomic_state *state)
|
|
|
{
|
|
|
- struct intel_crtc *intel_crtc;
|
|
|
+ struct intel_atomic_state *intel_state = to_intel_atomic_state(state);
|
|
|
+ struct drm_i915_private *dev_priv = state->dev->dev_private;
|
|
|
+ struct drm_crtc *crtc;
|
|
|
+ struct drm_crtc_state *cstate;
|
|
|
struct intel_crtc_state *crtc_state;
|
|
|
- int max_pixel_rate = 0;
|
|
|
+ unsigned max_pixel_rate = 0, i;
|
|
|
+ enum pipe pipe;
|
|
|
|
|
|
- for_each_intel_crtc(state->dev, intel_crtc) {
|
|
|
- int pixel_rate;
|
|
|
+ memcpy(intel_state->min_pixclk, dev_priv->min_pixclk,
|
|
|
+ sizeof(intel_state->min_pixclk));
|
|
|
|
|
|
- crtc_state = intel_atomic_get_crtc_state(state, intel_crtc);
|
|
|
- if (IS_ERR(crtc_state))
|
|
|
- return PTR_ERR(crtc_state);
|
|
|
+ for_each_crtc_in_state(state, crtc, cstate, i) {
|
|
|
+ int pixel_rate;
|
|
|
|
|
|
- if (!crtc_state->base.enable)
|
|
|
+ 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);
|
|
|
|
|
|
/* pixel rate mustn't exceed 95% of cdclk with IPS on BDW */
|
|
|
- if (IS_BROADWELL(state->dev) && crtc_state->ips_enabled)
|
|
|
+ if (IS_BROADWELL(dev_priv) && crtc_state->ips_enabled)
|
|
|
pixel_rate = DIV_ROUND_UP(pixel_rate * 100, 95);
|
|
|
|
|
|
- max_pixel_rate = max(max_pixel_rate, pixel_rate);
|
|
|
+ intel_state->min_pixclk[i] = pixel_rate;
|
|
|
}
|
|
|
|
|
|
+ if (!intel_state->active_crtcs)
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ for_each_pipe(dev_priv, pipe)
|
|
|
+ max_pixel_rate = max(intel_state->min_pixclk[pipe], max_pixel_rate);
|
|
|
+
|
|
|
return max_pixel_rate;
|
|
|
}
|
|
|
|
|
@@ -9783,6 +9810,7 @@ static void broadwell_set_cdclk(struct drm_device *dev, int cdclk)
|
|
|
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;
|
|
|
|
|
@@ -9805,7 +9833,9 @@ static int broadwell_modeset_calc_cdclk(struct drm_atomic_state *state)
|
|
|
return -EINVAL;
|
|
|
}
|
|
|
|
|
|
- to_intel_atomic_state(state)->cdclk = cdclk;
|
|
|
+ intel_state->cdclk = intel_state->dev_cdclk = cdclk;
|
|
|
+ if (!intel_state->active_crtcs)
|
|
|
+ intel_state->dev_cdclk = 337500;
|
|
|
|
|
|
return 0;
|
|
|
}
|
|
@@ -9813,7 +9843,9 @@ static int broadwell_modeset_calc_cdclk(struct drm_atomic_state *state)
|
|
|
static void broadwell_modeset_commit_cdclk(struct drm_atomic_state *old_state)
|
|
|
{
|
|
|
struct drm_device *dev = old_state->dev;
|
|
|
- unsigned int req_cdclk = to_intel_atomic_state(old_state)->cdclk;
|
|
|
+ struct intel_atomic_state *old_intel_state =
|
|
|
+ to_intel_atomic_state(old_state);
|
|
|
+ unsigned req_cdclk = old_intel_state->dev_cdclk;
|
|
|
|
|
|
broadwell_set_cdclk(dev, req_cdclk);
|
|
|
}
|
|
@@ -10026,16 +10058,17 @@ static bool haswell_get_pipe_config(struct intel_crtc *crtc,
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
-static void i845_update_cursor(struct drm_crtc *crtc, u32 base, bool on)
|
|
|
+static void i845_update_cursor(struct drm_crtc *crtc, u32 base,
|
|
|
+ const struct intel_plane_state *plane_state)
|
|
|
{
|
|
|
struct drm_device *dev = crtc->dev;
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
|
|
uint32_t cntl = 0, size = 0;
|
|
|
|
|
|
- if (on) {
|
|
|
- unsigned int width = intel_crtc->base.cursor->state->crtc_w;
|
|
|
- unsigned int height = intel_crtc->base.cursor->state->crtc_h;
|
|
|
+ if (plane_state && plane_state->visible) {
|
|
|
+ unsigned int width = plane_state->base.crtc_w;
|
|
|
+ unsigned int height = plane_state->base.crtc_h;
|
|
|
unsigned int stride = roundup_pow_of_two(width) * 4;
|
|
|
|
|
|
switch (stride) {
|
|
@@ -10088,7 +10121,8 @@ static void i845_update_cursor(struct drm_crtc *crtc, u32 base, bool on)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-static void i9xx_update_cursor(struct drm_crtc *crtc, u32 base, bool on)
|
|
|
+static void i9xx_update_cursor(struct drm_crtc *crtc, u32 base,
|
|
|
+ const struct intel_plane_state *plane_state)
|
|
|
{
|
|
|
struct drm_device *dev = crtc->dev;
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
@@ -10096,9 +10130,9 @@ static void i9xx_update_cursor(struct drm_crtc *crtc, u32 base, bool on)
|
|
|
int pipe = intel_crtc->pipe;
|
|
|
uint32_t cntl = 0;
|
|
|
|
|
|
- if (on) {
|
|
|
+ if (plane_state && plane_state->visible) {
|
|
|
cntl = MCURSOR_GAMMA_ENABLE;
|
|
|
- switch (intel_crtc->base.cursor->state->crtc_w) {
|
|
|
+ switch (plane_state->base.crtc_w) {
|
|
|
case 64:
|
|
|
cntl |= CURSOR_MODE_64_ARGB_AX;
|
|
|
break;
|
|
@@ -10109,17 +10143,17 @@ static void i9xx_update_cursor(struct drm_crtc *crtc, u32 base, bool on)
|
|
|
cntl |= CURSOR_MODE_256_ARGB_AX;
|
|
|
break;
|
|
|
default:
|
|
|
- MISSING_CASE(intel_crtc->base.cursor->state->crtc_w);
|
|
|
+ MISSING_CASE(plane_state->base.crtc_w);
|
|
|
return;
|
|
|
}
|
|
|
cntl |= pipe << 28; /* Connect to correct pipe */
|
|
|
|
|
|
if (HAS_DDI(dev))
|
|
|
cntl |= CURSOR_PIPE_CSC_ENABLE;
|
|
|
- }
|
|
|
|
|
|
- if (crtc->cursor->state->rotation == BIT(DRM_ROTATE_180))
|
|
|
- cntl |= CURSOR_ROTATE_180;
|
|
|
+ if (plane_state->base.rotation == BIT(DRM_ROTATE_180))
|
|
|
+ cntl |= CURSOR_ROTATE_180;
|
|
|
+ }
|
|
|
|
|
|
if (intel_crtc->cursor_cntl != cntl) {
|
|
|
I915_WRITE(CURCNTR(pipe), cntl);
|
|
@@ -10136,56 +10170,45 @@ static void i9xx_update_cursor(struct drm_crtc *crtc, u32 base, bool on)
|
|
|
|
|
|
/* If no-part of the cursor is visible on the framebuffer, then the GPU may hang... */
|
|
|
static void intel_crtc_update_cursor(struct drm_crtc *crtc,
|
|
|
- bool on)
|
|
|
+ const struct intel_plane_state *plane_state)
|
|
|
{
|
|
|
struct drm_device *dev = crtc->dev;
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
|
|
int pipe = intel_crtc->pipe;
|
|
|
- struct drm_plane_state *cursor_state = crtc->cursor->state;
|
|
|
- int x = cursor_state->crtc_x;
|
|
|
- int y = cursor_state->crtc_y;
|
|
|
- u32 base = 0, pos = 0;
|
|
|
-
|
|
|
- base = intel_crtc->cursor_addr;
|
|
|
+ u32 base = intel_crtc->cursor_addr;
|
|
|
+ u32 pos = 0;
|
|
|
|
|
|
- if (x >= intel_crtc->config->pipe_src_w)
|
|
|
- on = false;
|
|
|
+ if (plane_state) {
|
|
|
+ int x = plane_state->base.crtc_x;
|
|
|
+ int y = plane_state->base.crtc_y;
|
|
|
|
|
|
- if (y >= intel_crtc->config->pipe_src_h)
|
|
|
- on = false;
|
|
|
-
|
|
|
- if (x < 0) {
|
|
|
- if (x + cursor_state->crtc_w <= 0)
|
|
|
- on = false;
|
|
|
-
|
|
|
- pos |= CURSOR_POS_SIGN << CURSOR_X_SHIFT;
|
|
|
- x = -x;
|
|
|
- }
|
|
|
- pos |= x << CURSOR_X_SHIFT;
|
|
|
+ if (x < 0) {
|
|
|
+ pos |= CURSOR_POS_SIGN << CURSOR_X_SHIFT;
|
|
|
+ x = -x;
|
|
|
+ }
|
|
|
+ pos |= x << CURSOR_X_SHIFT;
|
|
|
|
|
|
- if (y < 0) {
|
|
|
- if (y + cursor_state->crtc_h <= 0)
|
|
|
- on = false;
|
|
|
+ if (y < 0) {
|
|
|
+ pos |= CURSOR_POS_SIGN << CURSOR_Y_SHIFT;
|
|
|
+ y = -y;
|
|
|
+ }
|
|
|
+ pos |= y << CURSOR_Y_SHIFT;
|
|
|
|
|
|
- pos |= CURSOR_POS_SIGN << CURSOR_Y_SHIFT;
|
|
|
- y = -y;
|
|
|
+ /* ILK+ do this automagically */
|
|
|
+ if (HAS_GMCH_DISPLAY(dev) &&
|
|
|
+ plane_state->base.rotation == BIT(DRM_ROTATE_180)) {
|
|
|
+ base += (plane_state->base.crtc_h *
|
|
|
+ plane_state->base.crtc_w - 1) * 4;
|
|
|
+ }
|
|
|
}
|
|
|
- pos |= y << CURSOR_Y_SHIFT;
|
|
|
|
|
|
I915_WRITE(CURPOS(pipe), pos);
|
|
|
|
|
|
- /* ILK+ do this automagically */
|
|
|
- if (HAS_GMCH_DISPLAY(dev) &&
|
|
|
- crtc->cursor->state->rotation == BIT(DRM_ROTATE_180)) {
|
|
|
- base += (cursor_state->crtc_h *
|
|
|
- cursor_state->crtc_w - 1) * 4;
|
|
|
- }
|
|
|
-
|
|
|
if (IS_845G(dev) || IS_I865G(dev))
|
|
|
- i845_update_cursor(crtc, base, on);
|
|
|
+ i845_update_cursor(crtc, base, plane_state);
|
|
|
else
|
|
|
- i9xx_update_cursor(crtc, base, on);
|
|
|
+ i9xx_update_cursor(crtc, base, plane_state);
|
|
|
}
|
|
|
|
|
|
static bool cursor_size_ok(struct drm_device *dev,
|
|
@@ -10778,7 +10801,7 @@ struct drm_display_mode *intel_crtc_mode_get(struct drm_device *dev,
|
|
|
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
|
|
enum transcoder cpu_transcoder = intel_crtc->config->cpu_transcoder;
|
|
|
struct drm_display_mode *mode;
|
|
|
- struct intel_crtc_state pipe_config;
|
|
|
+ struct intel_crtc_state *pipe_config;
|
|
|
int htot = I915_READ(HTOTAL(cpu_transcoder));
|
|
|
int hsync = I915_READ(HSYNC(cpu_transcoder));
|
|
|
int vtot = I915_READ(VTOTAL(cpu_transcoder));
|
|
@@ -10789,6 +10812,12 @@ struct drm_display_mode *intel_crtc_mode_get(struct drm_device *dev,
|
|
|
if (!mode)
|
|
|
return NULL;
|
|
|
|
|
|
+ pipe_config = kzalloc(sizeof(*pipe_config), GFP_KERNEL);
|
|
|
+ if (!pipe_config) {
|
|
|
+ kfree(mode);
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+
|
|
|
/*
|
|
|
* Construct a pipe_config sufficient for getting the clock info
|
|
|
* back out of crtc_clock_get.
|
|
@@ -10796,14 +10825,14 @@ struct drm_display_mode *intel_crtc_mode_get(struct drm_device *dev,
|
|
|
* Note, if LVDS ever uses a non-1 pixel multiplier, we'll need
|
|
|
* to use a real value here instead.
|
|
|
*/
|
|
|
- pipe_config.cpu_transcoder = (enum transcoder) pipe;
|
|
|
- pipe_config.pixel_multiplier = 1;
|
|
|
- pipe_config.dpll_hw_state.dpll = I915_READ(DPLL(pipe));
|
|
|
- pipe_config.dpll_hw_state.fp0 = I915_READ(FP0(pipe));
|
|
|
- pipe_config.dpll_hw_state.fp1 = I915_READ(FP1(pipe));
|
|
|
- i9xx_crtc_clock_get(intel_crtc, &pipe_config);
|
|
|
-
|
|
|
- mode->clock = pipe_config.port_clock / pipe_config.pixel_multiplier;
|
|
|
+ pipe_config->cpu_transcoder = (enum transcoder) pipe;
|
|
|
+ pipe_config->pixel_multiplier = 1;
|
|
|
+ pipe_config->dpll_hw_state.dpll = I915_READ(DPLL(pipe));
|
|
|
+ pipe_config->dpll_hw_state.fp0 = I915_READ(FP0(pipe));
|
|
|
+ pipe_config->dpll_hw_state.fp1 = I915_READ(FP1(pipe));
|
|
|
+ i9xx_crtc_clock_get(intel_crtc, pipe_config);
|
|
|
+
|
|
|
+ mode->clock = pipe_config->port_clock / pipe_config->pixel_multiplier;
|
|
|
mode->hdisplay = (htot & 0xffff) + 1;
|
|
|
mode->htotal = ((htot & 0xffff0000) >> 16) + 1;
|
|
|
mode->hsync_start = (hsync & 0xffff) + 1;
|
|
@@ -10815,6 +10844,8 @@ struct drm_display_mode *intel_crtc_mode_get(struct drm_device *dev,
|
|
|
|
|
|
drm_mode_set_name(mode);
|
|
|
|
|
|
+ kfree(pipe_config);
|
|
|
+
|
|
|
return mode;
|
|
|
}
|
|
|
|
|
@@ -11319,13 +11350,12 @@ static void skl_do_mmio_flip(struct intel_crtc *intel_crtc,
|
|
|
*/
|
|
|
if (intel_rotation_90_or_270(rotation)) {
|
|
|
/* stride = Surface height in tiles */
|
|
|
- tile_height = intel_tile_height(dev, fb->pixel_format,
|
|
|
- fb->modifier[0], 0);
|
|
|
+ tile_height = intel_tile_height(dev_priv, fb->modifier[0], 0);
|
|
|
stride = DIV_ROUND_UP(fb->height, tile_height);
|
|
|
} else {
|
|
|
stride = fb->pitches[0] /
|
|
|
- intel_fb_stride_alignment(dev, fb->modifier[0],
|
|
|
- fb->pixel_format);
|
|
|
+ intel_fb_stride_alignment(dev_priv, fb->modifier[0],
|
|
|
+ fb->pixel_format);
|
|
|
}
|
|
|
|
|
|
/*
|
|
@@ -11660,9 +11690,11 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
|
|
|
obj->last_write_req);
|
|
|
} else {
|
|
|
if (!request) {
|
|
|
- ret = i915_gem_request_alloc(ring, ring->default_context, &request);
|
|
|
- if (ret)
|
|
|
+ request = i915_gem_request_alloc(ring, NULL);
|
|
|
+ if (IS_ERR(request)) {
|
|
|
+ ret = PTR_ERR(request);
|
|
|
goto cleanup_unpin;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
ret = dev_priv->display.queue_flip(dev, crtc, fb, obj, request,
|
|
@@ -11831,8 +11863,13 @@ int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state,
|
|
|
if (!was_crtc_enabled && WARN_ON(was_visible))
|
|
|
was_visible = false;
|
|
|
|
|
|
- if (!is_crtc_enabled && WARN_ON(visible))
|
|
|
- visible = false;
|
|
|
+ /*
|
|
|
+ * Visibility is calculated as if the crtc was on, but
|
|
|
+ * after scaler setup everything depends on it being off
|
|
|
+ * when the crtc isn't active.
|
|
|
+ */
|
|
|
+ if (!is_crtc_enabled)
|
|
|
+ to_intel_plane_state(plane_state)->visible = visible = false;
|
|
|
|
|
|
if (!was_visible && !visible)
|
|
|
return 0;
|
|
@@ -12529,19 +12566,22 @@ intel_compare_m_n(unsigned int m, unsigned int n,
|
|
|
|
|
|
BUILD_BUG_ON(DATA_LINK_M_N_MASK > INT_MAX);
|
|
|
|
|
|
- if (m > m2) {
|
|
|
- while (m > m2) {
|
|
|
+ if (n > n2) {
|
|
|
+ while (n > n2) {
|
|
|
m2 <<= 1;
|
|
|
n2 <<= 1;
|
|
|
}
|
|
|
- } else if (m < m2) {
|
|
|
- while (m < m2) {
|
|
|
+ } else if (n < n2) {
|
|
|
+ while (n < n2) {
|
|
|
m <<= 1;
|
|
|
n <<= 1;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- return m == m2 && n == n2;
|
|
|
+ if (n != n2)
|
|
|
+ return false;
|
|
|
+
|
|
|
+ return intel_fuzzy_clock_check(m, m2);
|
|
|
}
|
|
|
|
|
|
static bool
|
|
@@ -13216,15 +13256,27 @@ static int intel_modeset_all_pipes(struct drm_atomic_state *state)
|
|
|
|
|
|
static int intel_modeset_checks(struct drm_atomic_state *state)
|
|
|
{
|
|
|
- struct drm_device *dev = state->dev;
|
|
|
- struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
- int ret;
|
|
|
+ struct intel_atomic_state *intel_state = to_intel_atomic_state(state);
|
|
|
+ struct drm_i915_private *dev_priv = state->dev->dev_private;
|
|
|
+ struct drm_crtc *crtc;
|
|
|
+ struct drm_crtc_state *crtc_state;
|
|
|
+ int ret = 0, i;
|
|
|
|
|
|
if (!check_digital_port_conflicts(state)) {
|
|
|
DRM_DEBUG_KMS("rejecting conflicting digital port configuration\n");
|
|
|
return -EINVAL;
|
|
|
}
|
|
|
|
|
|
+ intel_state->modeset = true;
|
|
|
+ intel_state->active_crtcs = dev_priv->active_crtcs;
|
|
|
+
|
|
|
+ for_each_crtc_in_state(state, crtc, crtc_state, i) {
|
|
|
+ if (crtc_state->active)
|
|
|
+ intel_state->active_crtcs |= 1 << i;
|
|
|
+ else
|
|
|
+ intel_state->active_crtcs &= ~(1 << i);
|
|
|
+ }
|
|
|
+
|
|
|
/*
|
|
|
* See if the config requires any additional preparation, e.g.
|
|
|
* to adjust global state with pipes off. We need to do this
|
|
@@ -13233,22 +13285,19 @@ static int intel_modeset_checks(struct drm_atomic_state *state)
|
|
|
* adjusted_mode bits in the crtc directly.
|
|
|
*/
|
|
|
if (dev_priv->display.modeset_calc_cdclk) {
|
|
|
- unsigned int cdclk;
|
|
|
-
|
|
|
ret = dev_priv->display.modeset_calc_cdclk(state);
|
|
|
|
|
|
- cdclk = to_intel_atomic_state(state)->cdclk;
|
|
|
- if (!ret && cdclk != dev_priv->cdclk_freq)
|
|
|
+ if (!ret && intel_state->dev_cdclk != dev_priv->cdclk_freq)
|
|
|
ret = intel_modeset_all_pipes(state);
|
|
|
|
|
|
if (ret < 0)
|
|
|
return ret;
|
|
|
} else
|
|
|
- to_intel_atomic_state(state)->cdclk = dev_priv->cdclk_freq;
|
|
|
+ to_intel_atomic_state(state)->cdclk = dev_priv->atomic_cdclk_freq;
|
|
|
|
|
|
intel_modeset_clear_plls(state);
|
|
|
|
|
|
- if (IS_HASWELL(dev))
|
|
|
+ if (IS_HASWELL(dev_priv))
|
|
|
return haswell_mode_set_planes_workaround(state);
|
|
|
|
|
|
return 0;
|
|
@@ -13466,12 +13515,12 @@ static int intel_atomic_commit(struct drm_device *dev,
|
|
|
struct drm_atomic_state *state,
|
|
|
bool async)
|
|
|
{
|
|
|
+ struct intel_atomic_state *intel_state = to_intel_atomic_state(state);
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
struct drm_crtc_state *crtc_state;
|
|
|
struct drm_crtc *crtc;
|
|
|
- int ret = 0;
|
|
|
- int i;
|
|
|
- bool any_ms = false;
|
|
|
+ int ret = 0, i;
|
|
|
+ bool hw_check = intel_state->modeset;
|
|
|
|
|
|
ret = intel_atomic_prepare_commit(dev, state, async);
|
|
|
if (ret) {
|
|
@@ -13482,13 +13531,19 @@ static int intel_atomic_commit(struct drm_device *dev,
|
|
|
drm_atomic_helper_swap_state(dev, state);
|
|
|
dev_priv->wm.config = to_intel_atomic_state(state)->wm_config;
|
|
|
|
|
|
+ if (intel_state->modeset) {
|
|
|
+ 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;
|
|
|
+ }
|
|
|
+
|
|
|
for_each_crtc_in_state(state, crtc, crtc_state, i) {
|
|
|
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
|
|
|
|
|
if (!needs_modeset(crtc->state))
|
|
|
continue;
|
|
|
|
|
|
- any_ms = true;
|
|
|
intel_pre_plane_update(intel_crtc);
|
|
|
|
|
|
if (crtc_state->active) {
|
|
@@ -13513,7 +13568,7 @@ static int intel_atomic_commit(struct drm_device *dev,
|
|
|
* update the the output configuration. */
|
|
|
intel_modeset_update_crtc_state(state);
|
|
|
|
|
|
- if (any_ms) {
|
|
|
+ if (intel_state->modeset) {
|
|
|
intel_shared_dpll_commit(state);
|
|
|
|
|
|
drm_atomic_helper_update_legacy_modeset_state(state->dev, state);
|
|
@@ -13540,7 +13595,7 @@ static int intel_atomic_commit(struct drm_device *dev,
|
|
|
put_domains = modeset_get_crtc_power_domains(crtc);
|
|
|
|
|
|
/* make sure intel_modeset_check_state runs */
|
|
|
- any_ms = true;
|
|
|
+ hw_check = true;
|
|
|
}
|
|
|
|
|
|
if (!modeset)
|
|
@@ -13567,11 +13622,24 @@ static int intel_atomic_commit(struct drm_device *dev,
|
|
|
drm_atomic_helper_cleanup_planes(dev, state);
|
|
|
mutex_unlock(&dev->struct_mutex);
|
|
|
|
|
|
- if (any_ms)
|
|
|
+ if (hw_check)
|
|
|
intel_modeset_check_state(dev, state);
|
|
|
|
|
|
drm_atomic_state_free(state);
|
|
|
|
|
|
+ /* As one of the primary mmio accessors, KMS has a high likelihood
|
|
|
+ * of triggering bugs in unclaimed access. After we finish
|
|
|
+ * modesetting, see if an error has been flagged, and if so
|
|
|
+ * enable debugging for the next modeset - and hope we catch
|
|
|
+ * the culprit.
|
|
|
+ *
|
|
|
+ * XXX note that we assume display power is on at this point.
|
|
|
+ * This might hold true now but we need to add pm helper to check
|
|
|
+ * unclaimed only when the hardware is on, as atomic commits
|
|
|
+ * can happen also when the device is completely off.
|
|
|
+ */
|
|
|
+ intel_uncore_arm_unclaimed_mmio_detection(dev_priv);
|
|
|
+
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
@@ -13860,7 +13928,7 @@ skl_max_scale(struct intel_crtc *intel_crtc, struct intel_crtc_state *crtc_state
|
|
|
struct drm_i915_private *dev_priv;
|
|
|
int crtc_clock, cdclk;
|
|
|
|
|
|
- if (!intel_crtc || !crtc_state)
|
|
|
+ if (!intel_crtc || !crtc_state->base.enable)
|
|
|
return DRM_PLANE_HELPER_NO_SCALING;
|
|
|
|
|
|
dev = intel_crtc->base.dev;
|
|
@@ -13909,32 +13977,6 @@ intel_check_primary_plane(struct drm_plane *plane,
|
|
|
&state->visible);
|
|
|
}
|
|
|
|
|
|
-static void
|
|
|
-intel_commit_primary_plane(struct drm_plane *plane,
|
|
|
- struct intel_plane_state *state)
|
|
|
-{
|
|
|
- struct drm_crtc *crtc = state->base.crtc;
|
|
|
- struct drm_framebuffer *fb = state->base.fb;
|
|
|
- struct drm_device *dev = plane->dev;
|
|
|
- struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
-
|
|
|
- crtc = crtc ? crtc : plane->crtc;
|
|
|
-
|
|
|
- dev_priv->display.update_primary_plane(crtc, fb,
|
|
|
- state->src.x1 >> 16,
|
|
|
- state->src.y1 >> 16);
|
|
|
-}
|
|
|
-
|
|
|
-static void
|
|
|
-intel_disable_primary_plane(struct drm_plane *plane,
|
|
|
- struct drm_crtc *crtc)
|
|
|
-{
|
|
|
- struct drm_device *dev = plane->dev;
|
|
|
- struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
-
|
|
|
- dev_priv->display.update_primary_plane(crtc, NULL, 0, 0);
|
|
|
-}
|
|
|
-
|
|
|
static void intel_begin_crtc_commit(struct drm_crtc *crtc,
|
|
|
struct drm_crtc_state *old_crtc_state)
|
|
|
{
|
|
@@ -14019,20 +14061,33 @@ static struct drm_plane *intel_primary_plane_create(struct drm_device *dev,
|
|
|
primary->plane = pipe;
|
|
|
primary->frontbuffer_bit = INTEL_FRONTBUFFER_PRIMARY(pipe);
|
|
|
primary->check_plane = intel_check_primary_plane;
|
|
|
- primary->commit_plane = intel_commit_primary_plane;
|
|
|
- primary->disable_plane = intel_disable_primary_plane;
|
|
|
if (HAS_FBC(dev) && INTEL_INFO(dev)->gen < 4)
|
|
|
primary->plane = !pipe;
|
|
|
|
|
|
if (INTEL_INFO(dev)->gen >= 9) {
|
|
|
intel_primary_formats = skl_primary_formats;
|
|
|
num_formats = ARRAY_SIZE(skl_primary_formats);
|
|
|
+
|
|
|
+ primary->update_plane = skylake_update_primary_plane;
|
|
|
+ primary->disable_plane = skylake_disable_primary_plane;
|
|
|
+ } else if (HAS_PCH_SPLIT(dev)) {
|
|
|
+ intel_primary_formats = i965_primary_formats;
|
|
|
+ num_formats = ARRAY_SIZE(i965_primary_formats);
|
|
|
+
|
|
|
+ primary->update_plane = ironlake_update_primary_plane;
|
|
|
+ primary->disable_plane = i9xx_disable_primary_plane;
|
|
|
} else if (INTEL_INFO(dev)->gen >= 4) {
|
|
|
intel_primary_formats = i965_primary_formats;
|
|
|
num_formats = ARRAY_SIZE(i965_primary_formats);
|
|
|
+
|
|
|
+ primary->update_plane = i9xx_update_primary_plane;
|
|
|
+ primary->disable_plane = i9xx_disable_primary_plane;
|
|
|
} else {
|
|
|
intel_primary_formats = i8xx_primary_formats;
|
|
|
num_formats = ARRAY_SIZE(i8xx_primary_formats);
|
|
|
+
|
|
|
+ primary->update_plane = i9xx_update_primary_plane;
|
|
|
+ primary->disable_plane = i9xx_disable_primary_plane;
|
|
|
}
|
|
|
|
|
|
drm_universal_plane_init(dev, &primary->base, 0,
|
|
@@ -14131,22 +14186,23 @@ static void
|
|
|
intel_disable_cursor_plane(struct drm_plane *plane,
|
|
|
struct drm_crtc *crtc)
|
|
|
{
|
|
|
- intel_crtc_update_cursor(crtc, false);
|
|
|
+ struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
|
|
+
|
|
|
+ intel_crtc->cursor_addr = 0;
|
|
|
+ intel_crtc_update_cursor(crtc, NULL);
|
|
|
}
|
|
|
|
|
|
static void
|
|
|
-intel_commit_cursor_plane(struct drm_plane *plane,
|
|
|
- struct intel_plane_state *state)
|
|
|
+intel_update_cursor_plane(struct drm_plane *plane,
|
|
|
+ const struct intel_crtc_state *crtc_state,
|
|
|
+ const struct intel_plane_state *state)
|
|
|
{
|
|
|
- struct drm_crtc *crtc = state->base.crtc;
|
|
|
+ struct drm_crtc *crtc = crtc_state->base.crtc;
|
|
|
+ struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
|
|
struct drm_device *dev = plane->dev;
|
|
|
- struct intel_crtc *intel_crtc;
|
|
|
struct drm_i915_gem_object *obj = intel_fb_obj(state->base.fb);
|
|
|
uint32_t addr;
|
|
|
|
|
|
- crtc = crtc ? crtc : plane->crtc;
|
|
|
- intel_crtc = to_intel_crtc(crtc);
|
|
|
-
|
|
|
if (!obj)
|
|
|
addr = 0;
|
|
|
else if (!INTEL_INFO(dev)->cursor_needs_physical)
|
|
@@ -14155,9 +14211,7 @@ intel_commit_cursor_plane(struct drm_plane *plane,
|
|
|
addr = obj->phys_handle->busaddr;
|
|
|
|
|
|
intel_crtc->cursor_addr = addr;
|
|
|
-
|
|
|
- if (crtc->state->active)
|
|
|
- intel_crtc_update_cursor(crtc, state->visible);
|
|
|
+ intel_crtc_update_cursor(crtc, state);
|
|
|
}
|
|
|
|
|
|
static struct drm_plane *intel_cursor_plane_create(struct drm_device *dev,
|
|
@@ -14183,7 +14237,7 @@ static struct drm_plane *intel_cursor_plane_create(struct drm_device *dev,
|
|
|
cursor->plane = pipe;
|
|
|
cursor->frontbuffer_bit = INTEL_FRONTBUFFER_CURSOR(pipe);
|
|
|
cursor->check_plane = intel_check_cursor_plane;
|
|
|
- cursor->commit_plane = intel_commit_cursor_plane;
|
|
|
+ cursor->update_plane = intel_update_cursor_plane;
|
|
|
cursor->disable_plane = intel_disable_cursor_plane;
|
|
|
|
|
|
drm_universal_plane_init(dev, &cursor->base, 0,
|
|
@@ -14657,6 +14711,7 @@ static int intel_framebuffer_init(struct drm_device *dev,
|
|
|
struct drm_mode_fb_cmd2 *mode_cmd,
|
|
|
struct drm_i915_gem_object *obj)
|
|
|
{
|
|
|
+ struct drm_i915_private *dev_priv = to_i915(dev);
|
|
|
unsigned int aligned_height;
|
|
|
int ret;
|
|
|
u32 pitch_limit, stride_alignment;
|
|
@@ -14698,7 +14753,8 @@ static int intel_framebuffer_init(struct drm_device *dev,
|
|
|
return -EINVAL;
|
|
|
}
|
|
|
|
|
|
- stride_alignment = intel_fb_stride_alignment(dev, mode_cmd->modifier[0],
|
|
|
+ stride_alignment = intel_fb_stride_alignment(dev_priv,
|
|
|
+ mode_cmd->modifier[0],
|
|
|
mode_cmd->pixel_format);
|
|
|
if (mode_cmd->pitches[0] & (stride_alignment - 1)) {
|
|
|
DRM_DEBUG("pitch (%d) must be at least %u byte aligned\n",
|
|
@@ -14790,7 +14846,6 @@ static int intel_framebuffer_init(struct drm_device *dev,
|
|
|
|
|
|
drm_helper_mode_fill_fb_struct(&intel_fb->base, mode_cmd);
|
|
|
intel_fb->obj = obj;
|
|
|
- intel_fb->obj->framebuffer_references++;
|
|
|
|
|
|
ret = drm_framebuffer_init(dev, &intel_fb->base, &intel_fb_funcs);
|
|
|
if (ret) {
|
|
@@ -14798,6 +14853,8 @@ static int intel_framebuffer_init(struct drm_device *dev,
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
+ intel_fb->obj->framebuffer_references++;
|
|
|
+
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
@@ -14861,8 +14918,6 @@ static void intel_init_display(struct drm_device *dev)
|
|
|
haswell_crtc_compute_clock;
|
|
|
dev_priv->display.crtc_enable = haswell_crtc_enable;
|
|
|
dev_priv->display.crtc_disable = haswell_crtc_disable;
|
|
|
- dev_priv->display.update_primary_plane =
|
|
|
- skylake_update_primary_plane;
|
|
|
} else if (HAS_DDI(dev)) {
|
|
|
dev_priv->display.get_pipe_config = haswell_get_pipe_config;
|
|
|
dev_priv->display.get_initial_plane_config =
|
|
@@ -14871,8 +14926,6 @@ static void intel_init_display(struct drm_device *dev)
|
|
|
haswell_crtc_compute_clock;
|
|
|
dev_priv->display.crtc_enable = haswell_crtc_enable;
|
|
|
dev_priv->display.crtc_disable = haswell_crtc_disable;
|
|
|
- dev_priv->display.update_primary_plane =
|
|
|
- ironlake_update_primary_plane;
|
|
|
} else if (HAS_PCH_SPLIT(dev)) {
|
|
|
dev_priv->display.get_pipe_config = ironlake_get_pipe_config;
|
|
|
dev_priv->display.get_initial_plane_config =
|
|
@@ -14881,8 +14934,6 @@ static void intel_init_display(struct drm_device *dev)
|
|
|
ironlake_crtc_compute_clock;
|
|
|
dev_priv->display.crtc_enable = ironlake_crtc_enable;
|
|
|
dev_priv->display.crtc_disable = ironlake_crtc_disable;
|
|
|
- dev_priv->display.update_primary_plane =
|
|
|
- ironlake_update_primary_plane;
|
|
|
} else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
|
|
|
dev_priv->display.get_pipe_config = i9xx_get_pipe_config;
|
|
|
dev_priv->display.get_initial_plane_config =
|
|
@@ -14890,8 +14941,6 @@ static void intel_init_display(struct drm_device *dev)
|
|
|
dev_priv->display.crtc_compute_clock = i9xx_crtc_compute_clock;
|
|
|
dev_priv->display.crtc_enable = valleyview_crtc_enable;
|
|
|
dev_priv->display.crtc_disable = i9xx_crtc_disable;
|
|
|
- dev_priv->display.update_primary_plane =
|
|
|
- i9xx_update_primary_plane;
|
|
|
} else {
|
|
|
dev_priv->display.get_pipe_config = i9xx_get_pipe_config;
|
|
|
dev_priv->display.get_initial_plane_config =
|
|
@@ -14899,8 +14948,6 @@ static void intel_init_display(struct drm_device *dev)
|
|
|
dev_priv->display.crtc_compute_clock = i9xx_crtc_compute_clock;
|
|
|
dev_priv->display.crtc_enable = i9xx_crtc_enable;
|
|
|
dev_priv->display.crtc_disable = i9xx_crtc_disable;
|
|
|
- dev_priv->display.update_primary_plane =
|
|
|
- i9xx_update_primary_plane;
|
|
|
}
|
|
|
|
|
|
/* Returns the core display clock speed */
|
|
@@ -15206,12 +15253,89 @@ static void i915_disable_vga(struct drm_device *dev)
|
|
|
|
|
|
void intel_modeset_init_hw(struct drm_device *dev)
|
|
|
{
|
|
|
+ struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
+
|
|
|
intel_update_cdclk(dev);
|
|
|
- intel_prepare_ddi(dev);
|
|
|
+
|
|
|
+ dev_priv->atomic_cdclk_freq = dev_priv->cdclk_freq;
|
|
|
+
|
|
|
intel_init_clock_gating(dev);
|
|
|
intel_enable_gt_powersave(dev);
|
|
|
}
|
|
|
|
|
|
+/*
|
|
|
+ * Calculate what we think the watermarks should be for the state we've read
|
|
|
+ * out of the hardware and then immediately program those watermarks so that
|
|
|
+ * we ensure the hardware settings match our internal state.
|
|
|
+ *
|
|
|
+ * We can calculate what we think WM's should be by creating a duplicate of the
|
|
|
+ * current state (which was constructed during hardware readout) and running it
|
|
|
+ * through the atomic check code to calculate new watermark values in the
|
|
|
+ * state object.
|
|
|
+ */
|
|
|
+static void sanitize_watermarks(struct drm_device *dev)
|
|
|
+{
|
|
|
+ struct drm_i915_private *dev_priv = to_i915(dev);
|
|
|
+ struct drm_atomic_state *state;
|
|
|
+ struct drm_crtc *crtc;
|
|
|
+ struct drm_crtc_state *cstate;
|
|
|
+ struct drm_modeset_acquire_ctx ctx;
|
|
|
+ int ret;
|
|
|
+ int i;
|
|
|
+
|
|
|
+ /* Only supported on platforms that use atomic watermark design */
|
|
|
+ if (!dev_priv->display.program_watermarks)
|
|
|
+ return;
|
|
|
+
|
|
|
+ /*
|
|
|
+ * We need to hold connection_mutex before calling duplicate_state so
|
|
|
+ * that the connector loop is protected.
|
|
|
+ */
|
|
|
+ drm_modeset_acquire_init(&ctx, 0);
|
|
|
+retry:
|
|
|
+ ret = drm_modeset_lock_all_ctx(dev, &ctx);
|
|
|
+ if (ret == -EDEADLK) {
|
|
|
+ drm_modeset_backoff(&ctx);
|
|
|
+ goto retry;
|
|
|
+ } else if (WARN_ON(ret)) {
|
|
|
+ goto fail;
|
|
|
+ }
|
|
|
+
|
|
|
+ state = drm_atomic_helper_duplicate_state(dev, &ctx);
|
|
|
+ if (WARN_ON(IS_ERR(state)))
|
|
|
+ goto fail;
|
|
|
+
|
|
|
+ ret = intel_atomic_check(dev, state);
|
|
|
+ if (ret) {
|
|
|
+ /*
|
|
|
+ * If we fail here, it means that the hardware appears to be
|
|
|
+ * programmed in a way that shouldn't be possible, given our
|
|
|
+ * understanding of watermark requirements. This might mean a
|
|
|
+ * mistake in the hardware readout code or a mistake in the
|
|
|
+ * watermark calculations for a given platform. Raise a WARN
|
|
|
+ * so that this is noticeable.
|
|
|
+ *
|
|
|
+ * If this actually happens, we'll have to just leave the
|
|
|
+ * BIOS-programmed watermarks untouched and hope for the best.
|
|
|
+ */
|
|
|
+ WARN(true, "Could not determine valid watermarks for inherited state\n");
|
|
|
+ goto fail;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* Write calculated watermark values back */
|
|
|
+ to_i915(dev)->wm.config = to_intel_atomic_state(state)->wm_config;
|
|
|
+ for_each_crtc_in_state(state, crtc, cstate, i) {
|
|
|
+ struct intel_crtc_state *cs = to_intel_crtc_state(cstate);
|
|
|
+
|
|
|
+ dev_priv->display.program_watermarks(cs);
|
|
|
+ }
|
|
|
+
|
|
|
+ drm_atomic_state_free(state);
|
|
|
+fail:
|
|
|
+ drm_modeset_drop_locks(&ctx);
|
|
|
+ drm_modeset_acquire_fini(&ctx);
|
|
|
+}
|
|
|
+
|
|
|
void intel_modeset_init(struct drm_device *dev)
|
|
|
{
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
@@ -15332,6 +15456,13 @@ void intel_modeset_init(struct drm_device *dev)
|
|
|
*/
|
|
|
intel_find_initial_plane_obj(crtc, &plane_config);
|
|
|
}
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Make sure hardware watermarks really match the state we read out.
|
|
|
+ * 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);
|
|
|
}
|
|
|
|
|
|
static void intel_enable_pipe_a(struct drm_device *dev)
|
|
@@ -15604,16 +15735,40 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev)
|
|
|
struct intel_connector *connector;
|
|
|
int i;
|
|
|
|
|
|
+ dev_priv->active_crtcs = 0;
|
|
|
+
|
|
|
for_each_intel_crtc(dev, crtc) {
|
|
|
- __drm_atomic_helper_crtc_destroy_state(&crtc->base, crtc->base.state);
|
|
|
- memset(crtc->config, 0, sizeof(*crtc->config));
|
|
|
- crtc->config->base.crtc = &crtc->base;
|
|
|
+ struct intel_crtc_state *crtc_state = crtc->config;
|
|
|
+ int pixclk = 0;
|
|
|
|
|
|
- crtc->active = dev_priv->display.get_pipe_config(crtc,
|
|
|
- crtc->config);
|
|
|
+ __drm_atomic_helper_crtc_destroy_state(&crtc->base, &crtc_state->base);
|
|
|
+ memset(crtc_state, 0, sizeof(*crtc_state));
|
|
|
+ crtc_state->base.crtc = &crtc->base;
|
|
|
|
|
|
- crtc->base.state->active = crtc->active;
|
|
|
- crtc->base.enabled = crtc->active;
|
|
|
+ crtc_state->base.active = crtc_state->base.enable =
|
|
|
+ dev_priv->display.get_pipe_config(crtc, crtc_state);
|
|
|
+
|
|
|
+ crtc->base.enabled = crtc_state->base.enable;
|
|
|
+ crtc->active = crtc_state->base.active;
|
|
|
+
|
|
|
+ if (crtc_state->base.active) {
|
|
|
+ dev_priv->active_crtcs |= 1 << crtc->pipe;
|
|
|
+
|
|
|
+ if (IS_BROADWELL(dev_priv)) {
|
|
|
+ pixclk = ilk_pipe_pixel_rate(crtc_state);
|
|
|
+
|
|
|
+ /* pixel rate mustn't exceed 95% of cdclk with IPS on BDW */
|
|
|
+ if (crtc_state->ips_enabled)
|
|
|
+ pixclk = DIV_ROUND_UP(pixclk * 100, 95);
|
|
|
+ } else if (IS_VALLEYVIEW(dev_priv) ||
|
|
|
+ IS_CHERRYVIEW(dev_priv) ||
|
|
|
+ IS_BROXTON(dev_priv))
|
|
|
+ pixclk = crtc_state->base.adjusted_mode.crtc_clock;
|
|
|
+ else
|
|
|
+ WARN_ON(dev_priv->display.modeset_calc_cdclk);
|
|
|
+ }
|
|
|
+
|
|
|
+ dev_priv->min_pixclk[crtc->pipe] = pixclk;
|
|
|
|
|
|
readout_plane_state(crtc);
|
|
|
|
|
@@ -16117,7 +16272,7 @@ intel_display_print_error_state(struct drm_i915_error_state_buf *m,
|
|
|
for_each_pipe(dev_priv, i) {
|
|
|
err_printf(m, "Pipe [%d]:\n", i);
|
|
|
err_printf(m, " Power: %s\n",
|
|
|
- error->pipe[i].power_domain_on ? "on" : "off");
|
|
|
+ onoff(error->pipe[i].power_domain_on));
|
|
|
err_printf(m, " SRC: %08x\n", error->pipe[i].source);
|
|
|
err_printf(m, " STAT: %08x\n", error->pipe[i].stat);
|
|
|
|
|
@@ -16145,7 +16300,7 @@ intel_display_print_error_state(struct drm_i915_error_state_buf *m,
|
|
|
err_printf(m, "CPU transcoder: %c\n",
|
|
|
transcoder_name(error->transcoder[i].cpu_transcoder));
|
|
|
err_printf(m, " Power: %s\n",
|
|
|
- error->transcoder[i].power_domain_on ? "on" : "off");
|
|
|
+ onoff(error->transcoder[i].power_domain_on));
|
|
|
err_printf(m, " CONF: %08x\n", error->transcoder[i].conf);
|
|
|
err_printf(m, " HTOTAL: %08x\n", error->transcoder[i].htotal);
|
|
|
err_printf(m, " HBLANK: %08x\n", error->transcoder[i].hblank);
|