diff options
author | Maxime Ripard <maxime@cerno.tech> | 2021-05-11 13:35:52 +0200 |
---|---|---|
committer | Maxime Ripard <maxime@cerno.tech> | 2021-05-11 13:35:52 +0200 |
commit | c55b44c9386f3ee1b08752638559f19deaf6040d (patch) | |
tree | c843a21f45180387fcd9eb2625cc9d1f166a3156 /drivers/gpu/drm/i915/display/i9xx_plane.c | |
parent | MAINTAINERS: Update my e-mail (diff) | |
parent | Linux 5.13-rc1 (diff) | |
download | linux-c55b44c9386f3ee1b08752638559f19deaf6040d.tar.xz linux-c55b44c9386f3ee1b08752638559f19deaf6040d.zip |
Merge drm/drm-fixes into drm-misc-fixes
Start this new release drm-misc-fixes branch
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
Diffstat (limited to 'drivers/gpu/drm/i915/display/i9xx_plane.c')
-rw-r--r-- | drivers/gpu/drm/i915/display/i9xx_plane.c | 196 |
1 files changed, 156 insertions, 40 deletions
diff --git a/drivers/gpu/drm/i915/display/i9xx_plane.c b/drivers/gpu/drm/i915/display/i9xx_plane.c index e3e69e6cef65..456374ddf37a 100644 --- a/drivers/gpu/drm/i915/display/i9xx_plane.c +++ b/drivers/gpu/drm/i915/display/i9xx_plane.c @@ -11,6 +11,7 @@ #include "intel_atomic.h" #include "intel_atomic_plane.h" #include "intel_display_types.h" +#include "intel_fb.h" #include "intel_sprite.h" #include "i9xx_plane.h" @@ -128,7 +129,7 @@ static bool i9xx_plane_has_fbc(struct drm_i915_private *dev_priv, else if (IS_IVYBRIDGE(dev_priv)) return i9xx_plane == PLANE_A || i9xx_plane == PLANE_B || i9xx_plane == PLANE_C; - else if (INTEL_GEN(dev_priv) >= 4) + else if (DISPLAY_VER(dev_priv) >= 4) return i9xx_plane == PLANE_A || i9xx_plane == PLANE_B; else return i9xx_plane == PLANE_A; @@ -141,9 +142,9 @@ static bool i9xx_plane_has_windowing(struct intel_plane *plane) if (IS_CHERRYVIEW(dev_priv)) return i9xx_plane == PLANE_B; - else if (INTEL_GEN(dev_priv) >= 5 || IS_G4X(dev_priv)) + else if (DISPLAY_VER(dev_priv) >= 5 || IS_G4X(dev_priv)) return false; - else if (IS_GEN(dev_priv, 4)) + else if (IS_DISPLAY_VER(dev_priv, 4)) return i9xx_plane == PLANE_C; else return i9xx_plane == PLANE_B || @@ -161,8 +162,8 @@ static u32 i9xx_plane_ctl(const struct intel_crtc_state *crtc_state, dspcntr = DISPLAY_PLANE_ENABLE; - if (IS_G4X(dev_priv) || IS_GEN(dev_priv, 5) || - IS_GEN(dev_priv, 6) || IS_IVYBRIDGE(dev_priv)) + if (IS_G4X(dev_priv) || IS_IRONLAKE(dev_priv) || + IS_SANDYBRIDGE(dev_priv) || IS_IVYBRIDGE(dev_priv)) dspcntr |= DISPPLANE_TRICKLE_FEED_DISABLE; switch (fb->format->format) { @@ -210,7 +211,7 @@ static u32 i9xx_plane_ctl(const struct intel_crtc_state *crtc_state, return 0; } - if (INTEL_GEN(dev_priv) >= 4 && + if (DISPLAY_VER(dev_priv) >= 4 && fb->modifier == I915_FORMAT_MOD_X_TILED) dspcntr |= DISPPLANE_TILED; @@ -249,7 +250,7 @@ int i9xx_check_plane_surface(struct intel_plane_state *plane_state) intel_add_fb_offsets(&src_x, &src_y, plane_state, 0); - if (INTEL_GEN(dev_priv) >= 4) + if (DISPLAY_VER(dev_priv) >= 4) offset = intel_plane_compute_aligned_offset(&src_x, &src_y, plane_state, 0); else @@ -266,11 +267,11 @@ int i9xx_check_plane_surface(struct intel_plane_state *plane_state) * Linear surfaces seem to work just fine, even on hsw/bdw * despite them not using the linear offset anymore. */ - if (INTEL_GEN(dev_priv) >= 4 && fb->modifier == I915_FORMAT_MOD_X_TILED) { + if (DISPLAY_VER(dev_priv) >= 4 && fb->modifier == I915_FORMAT_MOD_X_TILED) { u32 alignment = intel_surf_alignment(fb, 0); int cpp = fb->format->cpp[0]; - while ((src_x + src_w) * cpp > plane_state->color_plane[0].stride) { + while ((src_x + src_w) * cpp > plane_state->view.color_plane[0].stride) { if (offset == 0) { drm_dbg_kms(&dev_priv->drm, "Unable to find suitable display surface offset due to X-tiling\n"); @@ -305,14 +306,14 @@ int i9xx_check_plane_surface(struct intel_plane_state *plane_state) if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) { drm_WARN_ON(&dev_priv->drm, src_x > 8191 || src_y > 4095); - } else if (INTEL_GEN(dev_priv) >= 4 && + } else if (DISPLAY_VER(dev_priv) >= 4 && fb->modifier == I915_FORMAT_MOD_X_TILED) { drm_WARN_ON(&dev_priv->drm, src_x > 4095 || src_y > 4095); } - plane_state->color_plane[0].offset = offset; - plane_state->color_plane[0].x = src_x; - plane_state->color_plane[0].y = src_y; + plane_state->view.color_plane[0].offset = offset; + plane_state->view.color_plane[0].x = src_x; + plane_state->view.color_plane[0].y = src_y; return 0; } @@ -363,7 +364,7 @@ static u32 i9xx_plane_ctl_crtc(const struct intel_crtc_state *crtc_state) if (crtc_state->csc_enable) dspcntr |= DISPPLANE_PIPE_CSC_ENABLE; - if (INTEL_GEN(dev_priv) < 5) + if (DISPLAY_VER(dev_priv) < 5) dspcntr |= DISPPLANE_SEL_PIPE(crtc->pipe); return dspcntr; @@ -423,8 +424,8 @@ static void i9xx_update_plane(struct intel_plane *plane, struct drm_i915_private *dev_priv = to_i915(plane->base.dev); enum i9xx_plane_id i9xx_plane = plane->i9xx_plane; u32 linear_offset; - int x = plane_state->color_plane[0].x; - int y = plane_state->color_plane[0].y; + int x = plane_state->view.color_plane[0].x; + int y = plane_state->view.color_plane[0].y; int crtc_x = plane_state->uapi.dst.x1; int crtc_y = plane_state->uapi.dst.y1; int crtc_w = drm_rect_width(&plane_state->uapi.dst); @@ -437,17 +438,17 @@ static void i9xx_update_plane(struct intel_plane *plane, linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0); - if (INTEL_GEN(dev_priv) >= 4) - dspaddr_offset = plane_state->color_plane[0].offset; + if (DISPLAY_VER(dev_priv) >= 4) + dspaddr_offset = plane_state->view.color_plane[0].offset; else dspaddr_offset = linear_offset; spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); intel_de_write_fw(dev_priv, DSPSTRIDE(i9xx_plane), - plane_state->color_plane[0].stride); + plane_state->view.color_plane[0].stride); - if (INTEL_GEN(dev_priv) < 4) { + if (DISPLAY_VER(dev_priv) < 4) { /* * PLANE_A doesn't actually have a full window * generator but let's assume we still need to @@ -468,7 +469,7 @@ static void i9xx_update_plane(struct intel_plane *plane, if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) { intel_de_write_fw(dev_priv, DSPOFFSET(i9xx_plane), (y << 16) | x); - } else if (INTEL_GEN(dev_priv) >= 4) { + } else if (DISPLAY_VER(dev_priv) >= 4) { intel_de_write_fw(dev_priv, DSPLINOFF(i9xx_plane), linear_offset); intel_de_write_fw(dev_priv, DSPTILEOFF(i9xx_plane), @@ -481,7 +482,7 @@ static void i9xx_update_plane(struct intel_plane *plane, * the control register just before the surface register. */ intel_de_write_fw(dev_priv, DSPCNTR(i9xx_plane), dspcntr); - if (INTEL_GEN(dev_priv) >= 4) + if (DISPLAY_VER(dev_priv) >= 4) intel_de_write_fw(dev_priv, DSPSURF(i9xx_plane), intel_plane_ggtt_offset(plane_state) + dspaddr_offset); else @@ -514,7 +515,7 @@ static void i9xx_disable_plane(struct intel_plane *plane, spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); intel_de_write_fw(dev_priv, DSPCNTR(i9xx_plane), dspcntr); - if (INTEL_GEN(dev_priv) >= 4) + if (DISPLAY_VER(dev_priv) >= 4) intel_de_write_fw(dev_priv, DSPSURF(i9xx_plane), 0); else intel_de_write_fw(dev_priv, DSPADDR(i9xx_plane), 0); @@ -530,7 +531,7 @@ g4x_primary_async_flip(struct intel_plane *plane, { struct drm_i915_private *dev_priv = to_i915(plane->base.dev); u32 dspcntr = plane_state->ctl | i9xx_plane_ctl_crtc(crtc_state); - u32 dspaddr_offset = plane_state->color_plane[0].offset; + u32 dspaddr_offset = plane_state->view.color_plane[0].offset; enum i9xx_plane_id i9xx_plane = plane->i9xx_plane; unsigned long irqflags; @@ -551,7 +552,7 @@ vlv_primary_async_flip(struct intel_plane *plane, bool async_flip) { struct drm_i915_private *dev_priv = to_i915(plane->base.dev); - u32 dspaddr_offset = plane_state->color_plane[0].offset; + u32 dspaddr_offset = plane_state->view.color_plane[0].offset; enum i9xx_plane_id i9xx_plane = plane->i9xx_plane; unsigned long irqflags; @@ -669,7 +670,7 @@ static bool i9xx_plane_get_hw_state(struct intel_plane *plane, ret = val & DISPLAY_PLANE_ENABLE; - if (INTEL_GEN(dev_priv) >= 5) + if (DISPLAY_VER(dev_priv) >= 5) *pipe = plane->pipe; else *pipe = (val & DISPPLANE_SEL_PIPE_MASK) >> @@ -729,7 +730,7 @@ i9xx_plane_max_stride(struct intel_plane *plane, { struct drm_i915_private *dev_priv = to_i915(plane->base.dev); - if (INTEL_GEN(dev_priv) >= 3) { + if (DISPLAY_VER(dev_priv) >= 3) { if (modifier == I915_FORMAT_MOD_X_TILED) return 8*1024; else @@ -770,10 +771,6 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe) int num_formats; int ret, zpos; - if (INTEL_GEN(dev_priv) >= 9) - return skl_universal_plane_create(dev_priv, pipe, - PLANE_PRIMARY); - plane = intel_plane_alloc(); if (IS_ERR(plane)) return plane; @@ -783,7 +780,7 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe) * On gen2/3 only plane A can do FBC, but the panel fitter and LVDS * port is hooked to pipe B. Hence we want plane A feeding pipe B. */ - if (HAS_FBC(dev_priv) && INTEL_GEN(dev_priv) < 4 && + if (HAS_FBC(dev_priv) && DISPLAY_VER(dev_priv) < 4 && INTEL_NUM_PIPES(dev_priv) == 2) plane->i9xx_plane = (enum i9xx_plane_id) !pipe; else @@ -801,7 +798,7 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe) if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) { formats = vlv_primary_formats; num_formats = ARRAY_SIZE(vlv_primary_formats); - } else if (INTEL_GEN(dev_priv) >= 4) { + } else if (DISPLAY_VER(dev_priv) >= 4) { /* * WaFP16GammaEnabling:ivb * "Workaround : When using the 64-bit format, the plane @@ -827,7 +824,7 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe) num_formats = ARRAY_SIZE(i8xx_primary_formats); } - if (INTEL_GEN(dev_priv) >= 4) + if (DISPLAY_VER(dev_priv) >= 4) plane_funcs = &i965_plane_funcs; else plane_funcs = &i8xx_plane_funcs; @@ -842,7 +839,7 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe) plane->min_cdclk = i9xx_plane_min_cdclk; if (HAS_GMCH(dev_priv)) { - if (INTEL_GEN(dev_priv) >= 4) + if (DISPLAY_VER(dev_priv) >= 4) plane->max_stride = i965_plane_max_stride; else plane->max_stride = i9xx_plane_max_stride; @@ -867,17 +864,17 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe) plane->async_flip = g4x_primary_async_flip; plane->enable_flip_done = bdw_primary_enable_flip_done; plane->disable_flip_done = bdw_primary_disable_flip_done; - } else if (INTEL_GEN(dev_priv) >= 7) { + } else if (DISPLAY_VER(dev_priv) >= 7) { plane->async_flip = g4x_primary_async_flip; plane->enable_flip_done = ivb_primary_enable_flip_done; plane->disable_flip_done = ivb_primary_disable_flip_done; - } else if (INTEL_GEN(dev_priv) >= 5) { + } else if (DISPLAY_VER(dev_priv) >= 5) { plane->async_flip = g4x_primary_async_flip; plane->enable_flip_done = ilk_primary_enable_flip_done; plane->disable_flip_done = ilk_primary_disable_flip_done; } - if (INTEL_GEN(dev_priv) >= 5 || IS_G4X(dev_priv)) + if (DISPLAY_VER(dev_priv) >= 5 || IS_G4X(dev_priv)) ret = drm_universal_plane_init(&dev_priv->drm, &plane->base, 0, plane_funcs, formats, num_formats, @@ -899,14 +896,14 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe) supported_rotations = DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180 | DRM_MODE_REFLECT_X; - } else if (INTEL_GEN(dev_priv) >= 4) { + } else if (DISPLAY_VER(dev_priv) >= 4) { supported_rotations = DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180; } else { supported_rotations = DRM_MODE_ROTATE_0; } - if (INTEL_GEN(dev_priv) >= 4) + if (DISPLAY_VER(dev_priv) >= 4) drm_plane_create_rotation_property(&plane->base, DRM_MODE_ROTATE_0, supported_rotations); @@ -924,3 +921,122 @@ fail: return ERR_PTR(ret); } +static int i9xx_format_to_fourcc(int format) +{ + switch (format) { + case DISPPLANE_8BPP: + return DRM_FORMAT_C8; + case DISPPLANE_BGRA555: + return DRM_FORMAT_ARGB1555; + case DISPPLANE_BGRX555: + return DRM_FORMAT_XRGB1555; + case DISPPLANE_BGRX565: + return DRM_FORMAT_RGB565; + default: + case DISPPLANE_BGRX888: + return DRM_FORMAT_XRGB8888; + case DISPPLANE_RGBX888: + return DRM_FORMAT_XBGR8888; + case DISPPLANE_BGRA888: + return DRM_FORMAT_ARGB8888; + case DISPPLANE_RGBA888: + return DRM_FORMAT_ABGR8888; + case DISPPLANE_BGRX101010: + return DRM_FORMAT_XRGB2101010; + case DISPPLANE_RGBX101010: + return DRM_FORMAT_XBGR2101010; + case DISPPLANE_BGRA101010: + return DRM_FORMAT_ARGB2101010; + case DISPPLANE_RGBA101010: + return DRM_FORMAT_ABGR2101010; + case DISPPLANE_RGBX161616: + return DRM_FORMAT_XBGR16161616F; + } +} + +void +i9xx_get_initial_plane_config(struct intel_crtc *crtc, + struct intel_initial_plane_config *plane_config) +{ + struct drm_device *dev = crtc->base.dev; + struct drm_i915_private *dev_priv = to_i915(dev); + struct intel_plane *plane = to_intel_plane(crtc->base.primary); + enum i9xx_plane_id i9xx_plane = plane->i9xx_plane; + enum pipe pipe; + u32 val, base, offset; + int fourcc, pixel_format; + unsigned int aligned_height; + struct drm_framebuffer *fb; + struct intel_framebuffer *intel_fb; + + if (!plane->get_hw_state(plane, &pipe)) + return; + + drm_WARN_ON(dev, pipe != crtc->pipe); + + intel_fb = kzalloc(sizeof(*intel_fb), GFP_KERNEL); + if (!intel_fb) { + drm_dbg_kms(&dev_priv->drm, "failed to alloc fb\n"); + return; + } + + fb = &intel_fb->base; + + fb->dev = dev; + + val = intel_de_read(dev_priv, DSPCNTR(i9xx_plane)); + + if (DISPLAY_VER(dev_priv) >= 4) { + if (val & DISPPLANE_TILED) { + plane_config->tiling = I915_TILING_X; + fb->modifier = I915_FORMAT_MOD_X_TILED; + } + + if (val & DISPPLANE_ROTATE_180) + plane_config->rotation = DRM_MODE_ROTATE_180; + } + + if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B && + val & DISPPLANE_MIRROR) + plane_config->rotation |= DRM_MODE_REFLECT_X; + + pixel_format = val & DISPPLANE_PIXFORMAT_MASK; + fourcc = i9xx_format_to_fourcc(pixel_format); + fb->format = drm_format_info(fourcc); + + if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) { + offset = intel_de_read(dev_priv, DSPOFFSET(i9xx_plane)); + base = intel_de_read(dev_priv, DSPSURF(i9xx_plane)) & 0xfffff000; + } else if (DISPLAY_VER(dev_priv) >= 4) { + if (plane_config->tiling) + offset = intel_de_read(dev_priv, + DSPTILEOFF(i9xx_plane)); + else + offset = intel_de_read(dev_priv, + DSPLINOFF(i9xx_plane)); + base = intel_de_read(dev_priv, DSPSURF(i9xx_plane)) & 0xfffff000; + } else { + base = intel_de_read(dev_priv, DSPADDR(i9xx_plane)); + } + plane_config->base = base; + + val = intel_de_read(dev_priv, PIPESRC(pipe)); + fb->width = ((val >> 16) & 0xfff) + 1; + fb->height = ((val >> 0) & 0xfff) + 1; + + val = intel_de_read(dev_priv, DSPSTRIDE(i9xx_plane)); + fb->pitches[0] = val & 0xffffffc0; + + aligned_height = intel_fb_align_height(fb, 0, fb->height); + + plane_config->size = fb->pitches[0] * aligned_height; + + drm_dbg_kms(&dev_priv->drm, + "%s/%s with fb: size=%dx%d@%d, offset=%x, pitch %d, size 0x%x\n", + crtc->base.name, plane->base.name, fb->width, fb->height, + fb->format->cpp[0] * 8, base, fb->pitches[0], + plane_config->size); + + plane_config->fb = intel_fb; +} + |