100a16d02SDave Airlie // SPDX-License-Identifier: MIT
200a16d02SDave Airlie /*
300a16d02SDave Airlie * Copyright © 2020 Intel Corporation
400a16d02SDave Airlie */
500a16d02SDave Airlie #include <linux/kernel.h>
600a16d02SDave Airlie
700a16d02SDave Airlie #include <drm/drm_atomic_helper.h>
890bb087fSVille Syrjälä #include <drm/drm_blend.h>
900a16d02SDave Airlie #include <drm/drm_fourcc.h>
1000a16d02SDave Airlie
11801543b2SJani Nikula #include "i915_reg.h"
12801543b2SJani Nikula #include "i9xx_plane.h"
1300a16d02SDave Airlie #include "intel_atomic.h"
1400a16d02SDave Airlie #include "intel_atomic_plane.h"
157785ae0bSVille Syrjälä #include "intel_de.h"
162b874a02SJani Nikula #include "intel_display_irq.h"
1700a16d02SDave Airlie #include "intel_display_types.h"
183cee6269SImre Deak #include "intel_fb.h"
19825bd833SVille Syrjälä #include "intel_fbc.h"
2000a16d02SDave Airlie #include "intel_sprite.h"
2100a16d02SDave Airlie
2200a16d02SDave Airlie /* Primary plane formats for gen <= 3 */
2300a16d02SDave Airlie static const u32 i8xx_primary_formats[] = {
2400a16d02SDave Airlie DRM_FORMAT_C8,
2500a16d02SDave Airlie DRM_FORMAT_XRGB1555,
2600a16d02SDave Airlie DRM_FORMAT_RGB565,
2700a16d02SDave Airlie DRM_FORMAT_XRGB8888,
2800a16d02SDave Airlie };
2900a16d02SDave Airlie
3000a16d02SDave Airlie /* Primary plane formats for ivb (no fp16 due to hw issue) */
3100a16d02SDave Airlie static const u32 ivb_primary_formats[] = {
3200a16d02SDave Airlie DRM_FORMAT_C8,
3300a16d02SDave Airlie DRM_FORMAT_RGB565,
3400a16d02SDave Airlie DRM_FORMAT_XRGB8888,
3500a16d02SDave Airlie DRM_FORMAT_XBGR8888,
3600a16d02SDave Airlie DRM_FORMAT_XRGB2101010,
3700a16d02SDave Airlie DRM_FORMAT_XBGR2101010,
3800a16d02SDave Airlie };
3900a16d02SDave Airlie
4000a16d02SDave Airlie /* Primary plane formats for gen >= 4, except ivb */
4100a16d02SDave Airlie static const u32 i965_primary_formats[] = {
4200a16d02SDave Airlie DRM_FORMAT_C8,
4300a16d02SDave Airlie DRM_FORMAT_RGB565,
4400a16d02SDave Airlie DRM_FORMAT_XRGB8888,
4500a16d02SDave Airlie DRM_FORMAT_XBGR8888,
4600a16d02SDave Airlie DRM_FORMAT_XRGB2101010,
4700a16d02SDave Airlie DRM_FORMAT_XBGR2101010,
4800a16d02SDave Airlie DRM_FORMAT_XBGR16161616F,
4900a16d02SDave Airlie };
5000a16d02SDave Airlie
5100a16d02SDave Airlie /* Primary plane formats for vlv/chv */
5200a16d02SDave Airlie static const u32 vlv_primary_formats[] = {
5300a16d02SDave Airlie DRM_FORMAT_C8,
5400a16d02SDave Airlie DRM_FORMAT_RGB565,
5500a16d02SDave Airlie DRM_FORMAT_XRGB8888,
5600a16d02SDave Airlie DRM_FORMAT_XBGR8888,
5700a16d02SDave Airlie DRM_FORMAT_ARGB8888,
5800a16d02SDave Airlie DRM_FORMAT_ABGR8888,
5900a16d02SDave Airlie DRM_FORMAT_XRGB2101010,
6000a16d02SDave Airlie DRM_FORMAT_XBGR2101010,
6100a16d02SDave Airlie DRM_FORMAT_ARGB2101010,
6200a16d02SDave Airlie DRM_FORMAT_ABGR2101010,
6300a16d02SDave Airlie DRM_FORMAT_XBGR16161616F,
6400a16d02SDave Airlie };
6500a16d02SDave Airlie
i8xx_plane_format_mod_supported(struct drm_plane * _plane,u32 format,u64 modifier)6600a16d02SDave Airlie static bool i8xx_plane_format_mod_supported(struct drm_plane *_plane,
6700a16d02SDave Airlie u32 format, u64 modifier)
6800a16d02SDave Airlie {
69e2b83294SImre Deak if (!intel_fb_plane_supports_modifier(to_intel_plane(_plane), modifier))
7000a16d02SDave Airlie return false;
7100a16d02SDave Airlie
7200a16d02SDave Airlie switch (format) {
7300a16d02SDave Airlie case DRM_FORMAT_C8:
7400a16d02SDave Airlie case DRM_FORMAT_RGB565:
7500a16d02SDave Airlie case DRM_FORMAT_XRGB1555:
7600a16d02SDave Airlie case DRM_FORMAT_XRGB8888:
7700a16d02SDave Airlie return modifier == DRM_FORMAT_MOD_LINEAR ||
7800a16d02SDave Airlie modifier == I915_FORMAT_MOD_X_TILED;
7900a16d02SDave Airlie default:
8000a16d02SDave Airlie return false;
8100a16d02SDave Airlie }
8200a16d02SDave Airlie }
8300a16d02SDave Airlie
i965_plane_format_mod_supported(struct drm_plane * _plane,u32 format,u64 modifier)8400a16d02SDave Airlie static bool i965_plane_format_mod_supported(struct drm_plane *_plane,
8500a16d02SDave Airlie u32 format, u64 modifier)
8600a16d02SDave Airlie {
87e2b83294SImre Deak if (!intel_fb_plane_supports_modifier(to_intel_plane(_plane), modifier))
8800a16d02SDave Airlie return false;
8900a16d02SDave Airlie
9000a16d02SDave Airlie switch (format) {
9100a16d02SDave Airlie case DRM_FORMAT_C8:
9200a16d02SDave Airlie case DRM_FORMAT_RGB565:
9300a16d02SDave Airlie case DRM_FORMAT_XRGB8888:
9400a16d02SDave Airlie case DRM_FORMAT_XBGR8888:
9500a16d02SDave Airlie case DRM_FORMAT_ARGB8888:
9600a16d02SDave Airlie case DRM_FORMAT_ABGR8888:
9700a16d02SDave Airlie case DRM_FORMAT_XRGB2101010:
9800a16d02SDave Airlie case DRM_FORMAT_XBGR2101010:
9900a16d02SDave Airlie case DRM_FORMAT_ARGB2101010:
10000a16d02SDave Airlie case DRM_FORMAT_ABGR2101010:
10100a16d02SDave Airlie case DRM_FORMAT_XBGR16161616F:
10200a16d02SDave Airlie return modifier == DRM_FORMAT_MOD_LINEAR ||
10300a16d02SDave Airlie modifier == I915_FORMAT_MOD_X_TILED;
10400a16d02SDave Airlie default:
10500a16d02SDave Airlie return false;
10600a16d02SDave Airlie }
10700a16d02SDave Airlie }
10800a16d02SDave Airlie
i9xx_plane_has_fbc(struct drm_i915_private * dev_priv,enum i9xx_plane_id i9xx_plane)10900a16d02SDave Airlie static bool i9xx_plane_has_fbc(struct drm_i915_private *dev_priv,
11000a16d02SDave Airlie enum i9xx_plane_id i9xx_plane)
11100a16d02SDave Airlie {
11200a16d02SDave Airlie if (!HAS_FBC(dev_priv))
11300a16d02SDave Airlie return false;
11400a16d02SDave Airlie
11500a16d02SDave Airlie if (IS_BROADWELL(dev_priv) || IS_HASWELL(dev_priv))
11600a16d02SDave Airlie return i9xx_plane == PLANE_A; /* tied to pipe A */
11700a16d02SDave Airlie else if (IS_IVYBRIDGE(dev_priv))
11800a16d02SDave Airlie return i9xx_plane == PLANE_A || i9xx_plane == PLANE_B ||
11900a16d02SDave Airlie i9xx_plane == PLANE_C;
120005e9537SMatt Roper else if (DISPLAY_VER(dev_priv) >= 4)
12100a16d02SDave Airlie return i9xx_plane == PLANE_A || i9xx_plane == PLANE_B;
12200a16d02SDave Airlie else
12300a16d02SDave Airlie return i9xx_plane == PLANE_A;
12400a16d02SDave Airlie }
12500a16d02SDave Airlie
i9xx_plane_fbc(struct drm_i915_private * dev_priv,enum i9xx_plane_id i9xx_plane)126825bd833SVille Syrjälä static struct intel_fbc *i9xx_plane_fbc(struct drm_i915_private *dev_priv,
127825bd833SVille Syrjälä enum i9xx_plane_id i9xx_plane)
128825bd833SVille Syrjälä {
129825bd833SVille Syrjälä if (i9xx_plane_has_fbc(dev_priv, i9xx_plane))
13080b3842fSJani Nikula return dev_priv->display.fbc[INTEL_FBC_A];
131825bd833SVille Syrjälä else
132825bd833SVille Syrjälä return NULL;
133825bd833SVille Syrjälä }
134825bd833SVille Syrjälä
i9xx_plane_has_windowing(struct intel_plane * plane)13500a16d02SDave Airlie static bool i9xx_plane_has_windowing(struct intel_plane *plane)
13600a16d02SDave Airlie {
13700a16d02SDave Airlie struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
13800a16d02SDave Airlie enum i9xx_plane_id i9xx_plane = plane->i9xx_plane;
13900a16d02SDave Airlie
14000a16d02SDave Airlie if (IS_CHERRYVIEW(dev_priv))
14100a16d02SDave Airlie return i9xx_plane == PLANE_B;
142005e9537SMatt Roper else if (DISPLAY_VER(dev_priv) >= 5 || IS_G4X(dev_priv))
14300a16d02SDave Airlie return false;
14493e7e61eSLucas De Marchi else if (DISPLAY_VER(dev_priv) == 4)
14500a16d02SDave Airlie return i9xx_plane == PLANE_C;
14600a16d02SDave Airlie else
14700a16d02SDave Airlie return i9xx_plane == PLANE_B ||
14800a16d02SDave Airlie i9xx_plane == PLANE_C;
14900a16d02SDave Airlie }
15000a16d02SDave Airlie
i9xx_plane_ctl(const struct intel_crtc_state * crtc_state,const struct intel_plane_state * plane_state)15100a16d02SDave Airlie static u32 i9xx_plane_ctl(const struct intel_crtc_state *crtc_state,
15200a16d02SDave Airlie const struct intel_plane_state *plane_state)
15300a16d02SDave Airlie {
15400a16d02SDave Airlie struct drm_i915_private *dev_priv =
15500a16d02SDave Airlie to_i915(plane_state->uapi.plane->dev);
15600a16d02SDave Airlie const struct drm_framebuffer *fb = plane_state->hw.fb;
15700a16d02SDave Airlie unsigned int rotation = plane_state->hw.rotation;
15800a16d02SDave Airlie u32 dspcntr;
15900a16d02SDave Airlie
160428cb15dSVille Syrjälä dspcntr = DISP_ENABLE;
16100a16d02SDave Airlie
162d47d29a6SMatt Roper if (IS_G4X(dev_priv) || IS_IRONLAKE(dev_priv) ||
163d47d29a6SMatt Roper IS_SANDYBRIDGE(dev_priv) || IS_IVYBRIDGE(dev_priv))
164428cb15dSVille Syrjälä dspcntr |= DISP_TRICKLE_FEED_DISABLE;
16500a16d02SDave Airlie
16600a16d02SDave Airlie switch (fb->format->format) {
16700a16d02SDave Airlie case DRM_FORMAT_C8:
168428cb15dSVille Syrjälä dspcntr |= DISP_FORMAT_8BPP;
16900a16d02SDave Airlie break;
17000a16d02SDave Airlie case DRM_FORMAT_XRGB1555:
171428cb15dSVille Syrjälä dspcntr |= DISP_FORMAT_BGRX555;
17200a16d02SDave Airlie break;
17300a16d02SDave Airlie case DRM_FORMAT_ARGB1555:
174428cb15dSVille Syrjälä dspcntr |= DISP_FORMAT_BGRA555;
17500a16d02SDave Airlie break;
17600a16d02SDave Airlie case DRM_FORMAT_RGB565:
177428cb15dSVille Syrjälä dspcntr |= DISP_FORMAT_BGRX565;
17800a16d02SDave Airlie break;
17900a16d02SDave Airlie case DRM_FORMAT_XRGB8888:
180428cb15dSVille Syrjälä dspcntr |= DISP_FORMAT_BGRX888;
18100a16d02SDave Airlie break;
18200a16d02SDave Airlie case DRM_FORMAT_XBGR8888:
183428cb15dSVille Syrjälä dspcntr |= DISP_FORMAT_RGBX888;
18400a16d02SDave Airlie break;
18500a16d02SDave Airlie case DRM_FORMAT_ARGB8888:
186428cb15dSVille Syrjälä dspcntr |= DISP_FORMAT_BGRA888;
18700a16d02SDave Airlie break;
18800a16d02SDave Airlie case DRM_FORMAT_ABGR8888:
189428cb15dSVille Syrjälä dspcntr |= DISP_FORMAT_RGBA888;
19000a16d02SDave Airlie break;
19100a16d02SDave Airlie case DRM_FORMAT_XRGB2101010:
192428cb15dSVille Syrjälä dspcntr |= DISP_FORMAT_BGRX101010;
19300a16d02SDave Airlie break;
19400a16d02SDave Airlie case DRM_FORMAT_XBGR2101010:
195428cb15dSVille Syrjälä dspcntr |= DISP_FORMAT_RGBX101010;
19600a16d02SDave Airlie break;
19700a16d02SDave Airlie case DRM_FORMAT_ARGB2101010:
198428cb15dSVille Syrjälä dspcntr |= DISP_FORMAT_BGRA101010;
19900a16d02SDave Airlie break;
20000a16d02SDave Airlie case DRM_FORMAT_ABGR2101010:
201428cb15dSVille Syrjälä dspcntr |= DISP_FORMAT_RGBA101010;
20200a16d02SDave Airlie break;
20300a16d02SDave Airlie case DRM_FORMAT_XBGR16161616F:
204428cb15dSVille Syrjälä dspcntr |= DISP_FORMAT_RGBX161616;
20500a16d02SDave Airlie break;
20600a16d02SDave Airlie default:
20700a16d02SDave Airlie MISSING_CASE(fb->format->format);
20800a16d02SDave Airlie return 0;
20900a16d02SDave Airlie }
21000a16d02SDave Airlie
211005e9537SMatt Roper if (DISPLAY_VER(dev_priv) >= 4 &&
21200a16d02SDave Airlie fb->modifier == I915_FORMAT_MOD_X_TILED)
213428cb15dSVille Syrjälä dspcntr |= DISP_TILED;
21400a16d02SDave Airlie
21500a16d02SDave Airlie if (rotation & DRM_MODE_ROTATE_180)
216428cb15dSVille Syrjälä dspcntr |= DISP_ROTATE_180;
21700a16d02SDave Airlie
21800a16d02SDave Airlie if (rotation & DRM_MODE_REFLECT_X)
219428cb15dSVille Syrjälä dspcntr |= DISP_MIRROR;
22000a16d02SDave Airlie
22100a16d02SDave Airlie return dspcntr;
22200a16d02SDave Airlie }
22300a16d02SDave Airlie
i9xx_check_plane_surface(struct intel_plane_state * plane_state)22400a16d02SDave Airlie int i9xx_check_plane_surface(struct intel_plane_state *plane_state)
22500a16d02SDave Airlie {
22600a16d02SDave Airlie struct drm_i915_private *dev_priv =
22700a16d02SDave Airlie to_i915(plane_state->uapi.plane->dev);
22800a16d02SDave Airlie const struct drm_framebuffer *fb = plane_state->hw.fb;
22900a16d02SDave Airlie int src_x, src_y, src_w;
23000a16d02SDave Airlie u32 offset;
23100a16d02SDave Airlie int ret;
23200a16d02SDave Airlie
23300a16d02SDave Airlie ret = intel_plane_compute_gtt(plane_state);
23400a16d02SDave Airlie if (ret)
23500a16d02SDave Airlie return ret;
23600a16d02SDave Airlie
23700a16d02SDave Airlie if (!plane_state->uapi.visible)
23800a16d02SDave Airlie return 0;
23900a16d02SDave Airlie
24000a16d02SDave Airlie src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
24100a16d02SDave Airlie src_x = plane_state->uapi.src.x1 >> 16;
24200a16d02SDave Airlie src_y = plane_state->uapi.src.y1 >> 16;
24300a16d02SDave Airlie
24400a16d02SDave Airlie /* Undocumented hardware limit on i965/g4x/vlv/chv */
24500a16d02SDave Airlie if (HAS_GMCH(dev_priv) && fb->format->cpp[0] == 8 && src_w > 2048)
24600a16d02SDave Airlie return -EINVAL;
24700a16d02SDave Airlie
24800a16d02SDave Airlie intel_add_fb_offsets(&src_x, &src_y, plane_state, 0);
24900a16d02SDave Airlie
250005e9537SMatt Roper if (DISPLAY_VER(dev_priv) >= 4)
25100a16d02SDave Airlie offset = intel_plane_compute_aligned_offset(&src_x, &src_y,
25200a16d02SDave Airlie plane_state, 0);
25300a16d02SDave Airlie else
25400a16d02SDave Airlie offset = 0;
25500a16d02SDave Airlie
25600a16d02SDave Airlie /*
25759fb8218SVille Syrjälä * When using an X-tiled surface the plane starts to
25859fb8218SVille Syrjälä * misbehave if the x offset + width exceeds the stride.
25959fb8218SVille Syrjälä * hsw/bdw: underrun galore
26059fb8218SVille Syrjälä * ilk/snb/ivb: wrap to the next tile row mid scanout
26159fb8218SVille Syrjälä * i965/g4x: so far appear immune to this
26259fb8218SVille Syrjälä * vlv/chv: TODO check
26359fb8218SVille Syrjälä *
26459fb8218SVille Syrjälä * Linear surfaces seem to work just fine, even on hsw/bdw
26559fb8218SVille Syrjälä * despite them not using the linear offset anymore.
26659fb8218SVille Syrjälä */
267005e9537SMatt Roper if (DISPLAY_VER(dev_priv) >= 4 && fb->modifier == I915_FORMAT_MOD_X_TILED) {
26859fb8218SVille Syrjälä u32 alignment = intel_surf_alignment(fb, 0);
26959fb8218SVille Syrjälä int cpp = fb->format->cpp[0];
27059fb8218SVille Syrjälä
271be6c1dd5SImre Deak while ((src_x + src_w) * cpp > plane_state->view.color_plane[0].mapping_stride) {
27259fb8218SVille Syrjälä if (offset == 0) {
27359fb8218SVille Syrjälä drm_dbg_kms(&dev_priv->drm,
27459fb8218SVille Syrjälä "Unable to find suitable display surface offset due to X-tiling\n");
27559fb8218SVille Syrjälä return -EINVAL;
27659fb8218SVille Syrjälä }
27759fb8218SVille Syrjälä
27859fb8218SVille Syrjälä offset = intel_plane_adjust_aligned_offset(&src_x, &src_y, plane_state, 0,
27959fb8218SVille Syrjälä offset, offset - alignment);
28059fb8218SVille Syrjälä }
28159fb8218SVille Syrjälä }
28259fb8218SVille Syrjälä
28359fb8218SVille Syrjälä /*
28400a16d02SDave Airlie * Put the final coordinates back so that the src
28500a16d02SDave Airlie * coordinate checks will see the right values.
28600a16d02SDave Airlie */
28700a16d02SDave Airlie drm_rect_translate_to(&plane_state->uapi.src,
28800a16d02SDave Airlie src_x << 16, src_y << 16);
28900a16d02SDave Airlie
29000a16d02SDave Airlie /* HSW/BDW do this automagically in hardware */
29100a16d02SDave Airlie if (!IS_HASWELL(dev_priv) && !IS_BROADWELL(dev_priv)) {
29200a16d02SDave Airlie unsigned int rotation = plane_state->hw.rotation;
29300a16d02SDave Airlie int src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
29400a16d02SDave Airlie int src_h = drm_rect_height(&plane_state->uapi.src) >> 16;
29500a16d02SDave Airlie
29600a16d02SDave Airlie if (rotation & DRM_MODE_ROTATE_180) {
29700a16d02SDave Airlie src_x += src_w - 1;
29800a16d02SDave Airlie src_y += src_h - 1;
29900a16d02SDave Airlie } else if (rotation & DRM_MODE_REFLECT_X) {
30000a16d02SDave Airlie src_x += src_w - 1;
30100a16d02SDave Airlie }
30200a16d02SDave Airlie }
30300a16d02SDave Airlie
3042aa0f4faSVille Syrjälä if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) {
3052aa0f4faSVille Syrjälä drm_WARN_ON(&dev_priv->drm, src_x > 8191 || src_y > 4095);
306005e9537SMatt Roper } else if (DISPLAY_VER(dev_priv) >= 4 &&
3072aa0f4faSVille Syrjälä fb->modifier == I915_FORMAT_MOD_X_TILED) {
3082aa0f4faSVille Syrjälä drm_WARN_ON(&dev_priv->drm, src_x > 4095 || src_y > 4095);
3092aa0f4faSVille Syrjälä }
3102aa0f4faSVille Syrjälä
31161169987SImre Deak plane_state->view.color_plane[0].offset = offset;
31261169987SImre Deak plane_state->view.color_plane[0].x = src_x;
31361169987SImre Deak plane_state->view.color_plane[0].y = src_y;
31400a16d02SDave Airlie
31500a16d02SDave Airlie return 0;
31600a16d02SDave Airlie }
31700a16d02SDave Airlie
31800a16d02SDave Airlie static int
i9xx_plane_check(struct intel_crtc_state * crtc_state,struct intel_plane_state * plane_state)31900a16d02SDave Airlie i9xx_plane_check(struct intel_crtc_state *crtc_state,
32000a16d02SDave Airlie struct intel_plane_state *plane_state)
32100a16d02SDave Airlie {
32200a16d02SDave Airlie struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
32300a16d02SDave Airlie int ret;
32400a16d02SDave Airlie
32500a16d02SDave Airlie ret = chv_plane_check_rotation(plane_state);
32600a16d02SDave Airlie if (ret)
32700a16d02SDave Airlie return ret;
32800a16d02SDave Airlie
32900a16d02SDave Airlie ret = intel_atomic_plane_check_clipping(plane_state, crtc_state,
330cce32e4eSThomas Zimmermann DRM_PLANE_NO_SCALING,
331cce32e4eSThomas Zimmermann DRM_PLANE_NO_SCALING,
33200a16d02SDave Airlie i9xx_plane_has_windowing(plane));
33300a16d02SDave Airlie if (ret)
33400a16d02SDave Airlie return ret;
33500a16d02SDave Airlie
33600a16d02SDave Airlie ret = i9xx_check_plane_surface(plane_state);
33700a16d02SDave Airlie if (ret)
33800a16d02SDave Airlie return ret;
33900a16d02SDave Airlie
34000a16d02SDave Airlie if (!plane_state->uapi.visible)
34100a16d02SDave Airlie return 0;
34200a16d02SDave Airlie
34300a16d02SDave Airlie ret = intel_plane_check_src_coordinates(plane_state);
34400a16d02SDave Airlie if (ret)
34500a16d02SDave Airlie return ret;
34600a16d02SDave Airlie
34700a16d02SDave Airlie plane_state->ctl = i9xx_plane_ctl(crtc_state, plane_state);
34800a16d02SDave Airlie
34900a16d02SDave Airlie return 0;
35000a16d02SDave Airlie }
35100a16d02SDave Airlie
i9xx_plane_ctl_crtc(const struct intel_crtc_state * crtc_state)35200a16d02SDave Airlie static u32 i9xx_plane_ctl_crtc(const struct intel_crtc_state *crtc_state)
35300a16d02SDave Airlie {
35400a16d02SDave Airlie struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
35500a16d02SDave Airlie struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
35600a16d02SDave Airlie u32 dspcntr = 0;
35700a16d02SDave Airlie
35800a16d02SDave Airlie if (crtc_state->gamma_enable)
359428cb15dSVille Syrjälä dspcntr |= DISP_PIPE_GAMMA_ENABLE;
36000a16d02SDave Airlie
36100a16d02SDave Airlie if (crtc_state->csc_enable)
362428cb15dSVille Syrjälä dspcntr |= DISP_PIPE_CSC_ENABLE;
36300a16d02SDave Airlie
364005e9537SMatt Roper if (DISPLAY_VER(dev_priv) < 5)
365428cb15dSVille Syrjälä dspcntr |= DISP_PIPE_SEL(crtc->pipe);
36600a16d02SDave Airlie
36700a16d02SDave Airlie return dspcntr;
36800a16d02SDave Airlie }
36900a16d02SDave Airlie
i9xx_plane_ratio(const struct intel_crtc_state * crtc_state,const struct intel_plane_state * plane_state,unsigned int * num,unsigned int * den)37000a16d02SDave Airlie static void i9xx_plane_ratio(const struct intel_crtc_state *crtc_state,
37100a16d02SDave Airlie const struct intel_plane_state *plane_state,
37200a16d02SDave Airlie unsigned int *num, unsigned int *den)
37300a16d02SDave Airlie {
37400a16d02SDave Airlie const struct drm_framebuffer *fb = plane_state->hw.fb;
37500a16d02SDave Airlie unsigned int cpp = fb->format->cpp[0];
37600a16d02SDave Airlie
37700a16d02SDave Airlie /*
37800a16d02SDave Airlie * g4x bspec says 64bpp pixel rate can't exceed 80%
37900a16d02SDave Airlie * of cdclk when the sprite plane is enabled on the
38000a16d02SDave Airlie * same pipe. ilk/snb bspec says 64bpp pixel rate is
38100a16d02SDave Airlie * never allowed to exceed 80% of cdclk. Let's just go
38200a16d02SDave Airlie * with the ilk/snb limit always.
38300a16d02SDave Airlie */
38400a16d02SDave Airlie if (cpp == 8) {
38500a16d02SDave Airlie *num = 10;
38600a16d02SDave Airlie *den = 8;
38700a16d02SDave Airlie } else {
38800a16d02SDave Airlie *num = 1;
38900a16d02SDave Airlie *den = 1;
39000a16d02SDave Airlie }
39100a16d02SDave Airlie }
39200a16d02SDave Airlie
i9xx_plane_min_cdclk(const struct intel_crtc_state * crtc_state,const struct intel_plane_state * plane_state)39300a16d02SDave Airlie static int i9xx_plane_min_cdclk(const struct intel_crtc_state *crtc_state,
39400a16d02SDave Airlie const struct intel_plane_state *plane_state)
39500a16d02SDave Airlie {
39600a16d02SDave Airlie unsigned int pixel_rate;
39700a16d02SDave Airlie unsigned int num, den;
39800a16d02SDave Airlie
39900a16d02SDave Airlie /*
40000a16d02SDave Airlie * Note that crtc_state->pixel_rate accounts for both
40100a16d02SDave Airlie * horizontal and vertical panel fitter downscaling factors.
40200a16d02SDave Airlie * Pre-HSW bspec tells us to only consider the horizontal
40300a16d02SDave Airlie * downscaling factor here. We ignore that and just consider
40400a16d02SDave Airlie * both for simplicity.
40500a16d02SDave Airlie */
40600a16d02SDave Airlie pixel_rate = crtc_state->pixel_rate;
40700a16d02SDave Airlie
40800a16d02SDave Airlie i9xx_plane_ratio(crtc_state, plane_state, &num, &den);
40900a16d02SDave Airlie
41000a16d02SDave Airlie /* two pixels per clock with double wide pipe */
41100a16d02SDave Airlie if (crtc_state->double_wide)
41200a16d02SDave Airlie den *= 2;
41300a16d02SDave Airlie
41400a16d02SDave Airlie return DIV_ROUND_UP(pixel_rate * num, den);
41500a16d02SDave Airlie }
41600a16d02SDave Airlie
i9xx_plane_update_noarm(struct intel_plane * plane,const struct intel_crtc_state * crtc_state,const struct intel_plane_state * plane_state)4174d0d77deSVille Syrjälä static void i9xx_plane_update_noarm(struct intel_plane *plane,
4184d0d77deSVille Syrjälä const struct intel_crtc_state *crtc_state,
4194d0d77deSVille Syrjälä const struct intel_plane_state *plane_state)
4204d0d77deSVille Syrjälä {
4214d0d77deSVille Syrjälä struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
4224d0d77deSVille Syrjälä enum i9xx_plane_id i9xx_plane = plane->i9xx_plane;
4234d0d77deSVille Syrjälä
4244d0d77deSVille Syrjälä intel_de_write_fw(dev_priv, DSPSTRIDE(i9xx_plane),
4254d0d77deSVille Syrjälä plane_state->view.color_plane[0].mapping_stride);
4264d0d77deSVille Syrjälä
4274d0d77deSVille Syrjälä if (DISPLAY_VER(dev_priv) < 4) {
4284d0d77deSVille Syrjälä int crtc_x = plane_state->uapi.dst.x1;
4294d0d77deSVille Syrjälä int crtc_y = plane_state->uapi.dst.y1;
4304d0d77deSVille Syrjälä int crtc_w = drm_rect_width(&plane_state->uapi.dst);
4314d0d77deSVille Syrjälä int crtc_h = drm_rect_height(&plane_state->uapi.dst);
4324d0d77deSVille Syrjälä
4334d0d77deSVille Syrjälä /*
4344d0d77deSVille Syrjälä * PLANE_A doesn't actually have a full window
4354d0d77deSVille Syrjälä * generator but let's assume we still need to
4364d0d77deSVille Syrjälä * program whatever is there.
4374d0d77deSVille Syrjälä */
4384d0d77deSVille Syrjälä intel_de_write_fw(dev_priv, DSPPOS(i9xx_plane),
439428cb15dSVille Syrjälä DISP_POS_Y(crtc_y) | DISP_POS_X(crtc_x));
4404d0d77deSVille Syrjälä intel_de_write_fw(dev_priv, DSPSIZE(i9xx_plane),
441428cb15dSVille Syrjälä DISP_HEIGHT(crtc_h - 1) | DISP_WIDTH(crtc_w - 1));
4424d0d77deSVille Syrjälä }
4434d0d77deSVille Syrjälä }
4444d0d77deSVille Syrjälä
i9xx_plane_update_arm(struct intel_plane * plane,const struct intel_crtc_state * crtc_state,const struct intel_plane_state * plane_state)4458ac80733SVille Syrjälä static void i9xx_plane_update_arm(struct intel_plane *plane,
44600a16d02SDave Airlie const struct intel_crtc_state *crtc_state,
44700a16d02SDave Airlie const struct intel_plane_state *plane_state)
44800a16d02SDave Airlie {
44900a16d02SDave Airlie struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
45000a16d02SDave Airlie enum i9xx_plane_id i9xx_plane = plane->i9xx_plane;
45161169987SImre Deak int x = plane_state->view.color_plane[0].x;
45261169987SImre Deak int y = plane_state->view.color_plane[0].y;
4534d0d77deSVille Syrjälä u32 dspcntr, dspaddr_offset, linear_offset;
45400a16d02SDave Airlie
45500a16d02SDave Airlie dspcntr = plane_state->ctl | i9xx_plane_ctl_crtc(crtc_state);
45600a16d02SDave Airlie
45700a16d02SDave Airlie linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0);
45800a16d02SDave Airlie
459005e9537SMatt Roper if (DISPLAY_VER(dev_priv) >= 4)
46061169987SImre Deak dspaddr_offset = plane_state->view.color_plane[0].offset;
46100a16d02SDave Airlie else
46200a16d02SDave Airlie dspaddr_offset = linear_offset;
46300a16d02SDave Airlie
4644d0d77deSVille Syrjälä if (IS_CHERRYVIEW(dev_priv) && i9xx_plane == PLANE_B) {
4654d0d77deSVille Syrjälä int crtc_x = plane_state->uapi.dst.x1;
4664d0d77deSVille Syrjälä int crtc_y = plane_state->uapi.dst.y1;
4674d0d77deSVille Syrjälä int crtc_w = drm_rect_width(&plane_state->uapi.dst);
4684d0d77deSVille Syrjälä int crtc_h = drm_rect_height(&plane_state->uapi.dst);
46900a16d02SDave Airlie
47000a16d02SDave Airlie intel_de_write_fw(dev_priv, PRIMPOS(i9xx_plane),
471428cb15dSVille Syrjälä PRIM_POS_Y(crtc_y) | PRIM_POS_X(crtc_x));
47200a16d02SDave Airlie intel_de_write_fw(dev_priv, PRIMSIZE(i9xx_plane),
473428cb15dSVille Syrjälä PRIM_HEIGHT(crtc_h - 1) | PRIM_WIDTH(crtc_w - 1));
47400a16d02SDave Airlie intel_de_write_fw(dev_priv, PRIMCNSTALPHA(i9xx_plane), 0);
47500a16d02SDave Airlie }
47600a16d02SDave Airlie
47700a16d02SDave Airlie if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) {
47800a16d02SDave Airlie intel_de_write_fw(dev_priv, DSPOFFSET(i9xx_plane),
479428cb15dSVille Syrjälä DISP_OFFSET_Y(y) | DISP_OFFSET_X(x));
480005e9537SMatt Roper } else if (DISPLAY_VER(dev_priv) >= 4) {
48100a16d02SDave Airlie intel_de_write_fw(dev_priv, DSPLINOFF(i9xx_plane),
48200a16d02SDave Airlie linear_offset);
48300a16d02SDave Airlie intel_de_write_fw(dev_priv, DSPTILEOFF(i9xx_plane),
484428cb15dSVille Syrjälä DISP_OFFSET_Y(y) | DISP_OFFSET_X(x));
48500a16d02SDave Airlie }
48600a16d02SDave Airlie
48700a16d02SDave Airlie /*
48800a16d02SDave Airlie * The control register self-arms if the plane was previously
48900a16d02SDave Airlie * disabled. Try to make the plane enable atomic by writing
49000a16d02SDave Airlie * the control register just before the surface register.
49100a16d02SDave Airlie */
49200a16d02SDave Airlie intel_de_write_fw(dev_priv, DSPCNTR(i9xx_plane), dspcntr);
4937ad9993bSVille Syrjälä
494005e9537SMatt Roper if (DISPLAY_VER(dev_priv) >= 4)
49500a16d02SDave Airlie intel_de_write_fw(dev_priv, DSPSURF(i9xx_plane),
49600a16d02SDave Airlie intel_plane_ggtt_offset(plane_state) + dspaddr_offset);
49700a16d02SDave Airlie else
49800a16d02SDave Airlie intel_de_write_fw(dev_priv, DSPADDR(i9xx_plane),
49900a16d02SDave Airlie intel_plane_ggtt_offset(plane_state) + dspaddr_offset);
50000a16d02SDave Airlie }
50100a16d02SDave Airlie
i830_plane_update_arm(struct intel_plane * plane,const struct intel_crtc_state * crtc_state,const struct intel_plane_state * plane_state)5024d0d77deSVille Syrjälä static void i830_plane_update_arm(struct intel_plane *plane,
5034d0d77deSVille Syrjälä const struct intel_crtc_state *crtc_state,
5044d0d77deSVille Syrjälä const struct intel_plane_state *plane_state)
5054d0d77deSVille Syrjälä {
5064d0d77deSVille Syrjälä /*
5074d0d77deSVille Syrjälä * On i830/i845 all registers are self-arming [ALM040].
5084d0d77deSVille Syrjälä *
5094d0d77deSVille Syrjälä * Additional breakage on i830 causes register reads to return
5104d0d77deSVille Syrjälä * the last latched value instead of the last written value [ALM026].
5114d0d77deSVille Syrjälä */
5124d0d77deSVille Syrjälä i9xx_plane_update_noarm(plane, crtc_state, plane_state);
5134d0d77deSVille Syrjälä i9xx_plane_update_arm(plane, crtc_state, plane_state);
5144d0d77deSVille Syrjälä }
5154d0d77deSVille Syrjälä
i9xx_plane_disable_arm(struct intel_plane * plane,const struct intel_crtc_state * crtc_state)5168ac80733SVille Syrjälä static void i9xx_plane_disable_arm(struct intel_plane *plane,
51700a16d02SDave Airlie const struct intel_crtc_state *crtc_state)
51800a16d02SDave Airlie {
51900a16d02SDave Airlie struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
52000a16d02SDave Airlie enum i9xx_plane_id i9xx_plane = plane->i9xx_plane;
52100a16d02SDave Airlie u32 dspcntr;
52200a16d02SDave Airlie
52300a16d02SDave Airlie /*
52400a16d02SDave Airlie * DSPCNTR pipe gamma enable on g4x+ and pipe csc
52500a16d02SDave Airlie * enable on ilk+ affect the pipe bottom color as
52600a16d02SDave Airlie * well, so we must configure them even if the plane
52700a16d02SDave Airlie * is disabled.
52800a16d02SDave Airlie *
52900a16d02SDave Airlie * On pre-g4x there is no way to gamma correct the
53000a16d02SDave Airlie * pipe bottom color but we'll keep on doing this
53100a16d02SDave Airlie * anyway so that the crtc state readout works correctly.
53200a16d02SDave Airlie */
53300a16d02SDave Airlie dspcntr = i9xx_plane_ctl_crtc(crtc_state);
53400a16d02SDave Airlie
53500a16d02SDave Airlie intel_de_write_fw(dev_priv, DSPCNTR(i9xx_plane), dspcntr);
5367ad9993bSVille Syrjälä
537005e9537SMatt Roper if (DISPLAY_VER(dev_priv) >= 4)
53800a16d02SDave Airlie intel_de_write_fw(dev_priv, DSPSURF(i9xx_plane), 0);
53900a16d02SDave Airlie else
54000a16d02SDave Airlie intel_de_write_fw(dev_priv, DSPADDR(i9xx_plane), 0);
54100a16d02SDave Airlie }
54200a16d02SDave Airlie
543cda195f1SVille Syrjälä static void
g4x_primary_async_flip(struct intel_plane * plane,const struct intel_crtc_state * crtc_state,const struct intel_plane_state * plane_state,bool async_flip)544cda195f1SVille Syrjälä g4x_primary_async_flip(struct intel_plane *plane,
545cda195f1SVille Syrjälä const struct intel_crtc_state *crtc_state,
546cda195f1SVille Syrjälä const struct intel_plane_state *plane_state,
547cda195f1SVille Syrjälä bool async_flip)
548cda195f1SVille Syrjälä {
549cda195f1SVille Syrjälä struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
550cda195f1SVille Syrjälä u32 dspcntr = plane_state->ctl | i9xx_plane_ctl_crtc(crtc_state);
55161169987SImre Deak u32 dspaddr_offset = plane_state->view.color_plane[0].offset;
552cda195f1SVille Syrjälä enum i9xx_plane_id i9xx_plane = plane->i9xx_plane;
553cda195f1SVille Syrjälä
554cda195f1SVille Syrjälä if (async_flip)
555428cb15dSVille Syrjälä dspcntr |= DISP_ASYNC_FLIP;
556cda195f1SVille Syrjälä
557cda195f1SVille Syrjälä intel_de_write_fw(dev_priv, DSPCNTR(i9xx_plane), dspcntr);
5587ad9993bSVille Syrjälä
559cda195f1SVille Syrjälä intel_de_write_fw(dev_priv, DSPSURF(i9xx_plane),
560cda195f1SVille Syrjälä intel_plane_ggtt_offset(plane_state) + dspaddr_offset);
561cda195f1SVille Syrjälä }
562cda195f1SVille Syrjälä
563cda195f1SVille Syrjälä static void
vlv_primary_async_flip(struct intel_plane * plane,const struct intel_crtc_state * crtc_state,const struct intel_plane_state * plane_state,bool async_flip)5646ede6b06SVille Syrjälä vlv_primary_async_flip(struct intel_plane *plane,
5656ede6b06SVille Syrjälä const struct intel_crtc_state *crtc_state,
5666ede6b06SVille Syrjälä const struct intel_plane_state *plane_state,
5676ede6b06SVille Syrjälä bool async_flip)
5686ede6b06SVille Syrjälä {
5696ede6b06SVille Syrjälä struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
57061169987SImre Deak u32 dspaddr_offset = plane_state->view.color_plane[0].offset;
5716ede6b06SVille Syrjälä enum i9xx_plane_id i9xx_plane = plane->i9xx_plane;
5726ede6b06SVille Syrjälä
5736ede6b06SVille Syrjälä intel_de_write_fw(dev_priv, DSPADDR_VLV(i9xx_plane),
5746ede6b06SVille Syrjälä intel_plane_ggtt_offset(plane_state) + dspaddr_offset);
5756ede6b06SVille Syrjälä }
5766ede6b06SVille Syrjälä
5776ede6b06SVille Syrjälä static void
bdw_primary_enable_flip_done(struct intel_plane * plane)578cda195f1SVille Syrjälä bdw_primary_enable_flip_done(struct intel_plane *plane)
579cda195f1SVille Syrjälä {
580cda195f1SVille Syrjälä struct drm_i915_private *i915 = to_i915(plane->base.dev);
581cda195f1SVille Syrjälä enum pipe pipe = plane->pipe;
582cda195f1SVille Syrjälä
583cda195f1SVille Syrjälä spin_lock_irq(&i915->irq_lock);
584cda195f1SVille Syrjälä bdw_enable_pipe_irq(i915, pipe, GEN8_PIPE_PRIMARY_FLIP_DONE);
585cda195f1SVille Syrjälä spin_unlock_irq(&i915->irq_lock);
586cda195f1SVille Syrjälä }
587cda195f1SVille Syrjälä
588cda195f1SVille Syrjälä static void
bdw_primary_disable_flip_done(struct intel_plane * plane)589cda195f1SVille Syrjälä bdw_primary_disable_flip_done(struct intel_plane *plane)
590cda195f1SVille Syrjälä {
591cda195f1SVille Syrjälä struct drm_i915_private *i915 = to_i915(plane->base.dev);
592cda195f1SVille Syrjälä enum pipe pipe = plane->pipe;
593cda195f1SVille Syrjälä
594cda195f1SVille Syrjälä spin_lock_irq(&i915->irq_lock);
595cda195f1SVille Syrjälä bdw_disable_pipe_irq(i915, pipe, GEN8_PIPE_PRIMARY_FLIP_DONE);
596cda195f1SVille Syrjälä spin_unlock_irq(&i915->irq_lock);
597cda195f1SVille Syrjälä }
598cda195f1SVille Syrjälä
5992a636e24SVille Syrjälä static void
ivb_primary_enable_flip_done(struct intel_plane * plane)6002a636e24SVille Syrjälä ivb_primary_enable_flip_done(struct intel_plane *plane)
6012a636e24SVille Syrjälä {
6022a636e24SVille Syrjälä struct drm_i915_private *i915 = to_i915(plane->base.dev);
6032a636e24SVille Syrjälä
6042a636e24SVille Syrjälä spin_lock_irq(&i915->irq_lock);
6052a636e24SVille Syrjälä ilk_enable_display_irq(i915, DE_PLANE_FLIP_DONE_IVB(plane->i9xx_plane));
6062a636e24SVille Syrjälä spin_unlock_irq(&i915->irq_lock);
6072a636e24SVille Syrjälä }
6082a636e24SVille Syrjälä
6092a636e24SVille Syrjälä static void
ivb_primary_disable_flip_done(struct intel_plane * plane)6102a636e24SVille Syrjälä ivb_primary_disable_flip_done(struct intel_plane *plane)
6112a636e24SVille Syrjälä {
6122a636e24SVille Syrjälä struct drm_i915_private *i915 = to_i915(plane->base.dev);
6132a636e24SVille Syrjälä
6142a636e24SVille Syrjälä spin_lock_irq(&i915->irq_lock);
6152a636e24SVille Syrjälä ilk_disable_display_irq(i915, DE_PLANE_FLIP_DONE_IVB(plane->i9xx_plane));
6162a636e24SVille Syrjälä spin_unlock_irq(&i915->irq_lock);
6172a636e24SVille Syrjälä }
6182a636e24SVille Syrjälä
6194bb18054SVille Syrjälä static void
ilk_primary_enable_flip_done(struct intel_plane * plane)6204bb18054SVille Syrjälä ilk_primary_enable_flip_done(struct intel_plane *plane)
6214bb18054SVille Syrjälä {
6224bb18054SVille Syrjälä struct drm_i915_private *i915 = to_i915(plane->base.dev);
6234bb18054SVille Syrjälä
6244bb18054SVille Syrjälä spin_lock_irq(&i915->irq_lock);
6254bb18054SVille Syrjälä ilk_enable_display_irq(i915, DE_PLANE_FLIP_DONE(plane->i9xx_plane));
6264bb18054SVille Syrjälä spin_unlock_irq(&i915->irq_lock);
6274bb18054SVille Syrjälä }
6284bb18054SVille Syrjälä
6294bb18054SVille Syrjälä static void
ilk_primary_disable_flip_done(struct intel_plane * plane)6304bb18054SVille Syrjälä ilk_primary_disable_flip_done(struct intel_plane *plane)
6314bb18054SVille Syrjälä {
6324bb18054SVille Syrjälä struct drm_i915_private *i915 = to_i915(plane->base.dev);
6334bb18054SVille Syrjälä
6344bb18054SVille Syrjälä spin_lock_irq(&i915->irq_lock);
6354bb18054SVille Syrjälä ilk_disable_display_irq(i915, DE_PLANE_FLIP_DONE(plane->i9xx_plane));
6364bb18054SVille Syrjälä spin_unlock_irq(&i915->irq_lock);
6374bb18054SVille Syrjälä }
6384bb18054SVille Syrjälä
6396ede6b06SVille Syrjälä static void
vlv_primary_enable_flip_done(struct intel_plane * plane)6406ede6b06SVille Syrjälä vlv_primary_enable_flip_done(struct intel_plane *plane)
6416ede6b06SVille Syrjälä {
6426ede6b06SVille Syrjälä struct drm_i915_private *i915 = to_i915(plane->base.dev);
6436ede6b06SVille Syrjälä enum pipe pipe = plane->pipe;
6446ede6b06SVille Syrjälä
6456ede6b06SVille Syrjälä spin_lock_irq(&i915->irq_lock);
6466ede6b06SVille Syrjälä i915_enable_pipestat(i915, pipe, PLANE_FLIP_DONE_INT_STATUS_VLV);
6476ede6b06SVille Syrjälä spin_unlock_irq(&i915->irq_lock);
6486ede6b06SVille Syrjälä }
6496ede6b06SVille Syrjälä
6506ede6b06SVille Syrjälä static void
vlv_primary_disable_flip_done(struct intel_plane * plane)6516ede6b06SVille Syrjälä vlv_primary_disable_flip_done(struct intel_plane *plane)
6526ede6b06SVille Syrjälä {
6536ede6b06SVille Syrjälä struct drm_i915_private *i915 = to_i915(plane->base.dev);
6546ede6b06SVille Syrjälä enum pipe pipe = plane->pipe;
6556ede6b06SVille Syrjälä
6566ede6b06SVille Syrjälä spin_lock_irq(&i915->irq_lock);
6576ede6b06SVille Syrjälä i915_disable_pipestat(i915, pipe, PLANE_FLIP_DONE_INT_STATUS_VLV);
6586ede6b06SVille Syrjälä spin_unlock_irq(&i915->irq_lock);
6596ede6b06SVille Syrjälä }
6606ede6b06SVille Syrjälä
i9xx_plane_get_hw_state(struct intel_plane * plane,enum pipe * pipe)66100a16d02SDave Airlie static bool i9xx_plane_get_hw_state(struct intel_plane *plane,
66200a16d02SDave Airlie enum pipe *pipe)
66300a16d02SDave Airlie {
66400a16d02SDave Airlie struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
66500a16d02SDave Airlie enum intel_display_power_domain power_domain;
66600a16d02SDave Airlie enum i9xx_plane_id i9xx_plane = plane->i9xx_plane;
66700a16d02SDave Airlie intel_wakeref_t wakeref;
66800a16d02SDave Airlie bool ret;
66900a16d02SDave Airlie u32 val;
67000a16d02SDave Airlie
67100a16d02SDave Airlie /*
67200a16d02SDave Airlie * Not 100% correct for planes that can move between pipes,
67300a16d02SDave Airlie * but that's only the case for gen2-4 which don't have any
67400a16d02SDave Airlie * display power wells.
67500a16d02SDave Airlie */
67600a16d02SDave Airlie power_domain = POWER_DOMAIN_PIPE(plane->pipe);
67700a16d02SDave Airlie wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
67800a16d02SDave Airlie if (!wakeref)
67900a16d02SDave Airlie return false;
68000a16d02SDave Airlie
68100a16d02SDave Airlie val = intel_de_read(dev_priv, DSPCNTR(i9xx_plane));
68200a16d02SDave Airlie
683428cb15dSVille Syrjälä ret = val & DISP_ENABLE;
68400a16d02SDave Airlie
685005e9537SMatt Roper if (DISPLAY_VER(dev_priv) >= 5)
68600a16d02SDave Airlie *pipe = plane->pipe;
68700a16d02SDave Airlie else
688428cb15dSVille Syrjälä *pipe = REG_FIELD_GET(DISP_PIPE_SEL_MASK, val);
68900a16d02SDave Airlie
69000a16d02SDave Airlie intel_display_power_put(dev_priv, power_domain, wakeref);
69100a16d02SDave Airlie
69200a16d02SDave Airlie return ret;
69300a16d02SDave Airlie }
69400a16d02SDave Airlie
695cb807055SVille Syrjälä static unsigned int
hsw_primary_max_stride(struct intel_plane * plane,u32 pixel_format,u64 modifier,unsigned int rotation)696cb807055SVille Syrjälä hsw_primary_max_stride(struct intel_plane *plane,
697cb807055SVille Syrjälä u32 pixel_format, u64 modifier,
698cb807055SVille Syrjälä unsigned int rotation)
699cb807055SVille Syrjälä {
700cb807055SVille Syrjälä const struct drm_format_info *info = drm_format_info(pixel_format);
701cb807055SVille Syrjälä int cpp = info->cpp[0];
702cb807055SVille Syrjälä
703cb807055SVille Syrjälä /* Limit to 8k pixels to guarantee OFFSET.x doesn't get too big. */
704cb807055SVille Syrjälä return min(8192 * cpp, 32 * 1024);
705cb807055SVille Syrjälä }
706cb807055SVille Syrjälä
707cb807055SVille Syrjälä static unsigned int
ilk_primary_max_stride(struct intel_plane * plane,u32 pixel_format,u64 modifier,unsigned int rotation)708cb807055SVille Syrjälä ilk_primary_max_stride(struct intel_plane *plane,
709cb807055SVille Syrjälä u32 pixel_format, u64 modifier,
710cb807055SVille Syrjälä unsigned int rotation)
711cb807055SVille Syrjälä {
712cb807055SVille Syrjälä const struct drm_format_info *info = drm_format_info(pixel_format);
713cb807055SVille Syrjälä int cpp = info->cpp[0];
714cb807055SVille Syrjälä
715cb807055SVille Syrjälä /* Limit to 4k pixels to guarantee TILEOFF.x doesn't get too big. */
716cb807055SVille Syrjälä if (modifier == I915_FORMAT_MOD_X_TILED)
717cb807055SVille Syrjälä return min(4096 * cpp, 32 * 1024);
718cb807055SVille Syrjälä else
719cb807055SVille Syrjälä return 32 * 1024;
720cb807055SVille Syrjälä }
721cb807055SVille Syrjälä
72200a16d02SDave Airlie unsigned int
i965_plane_max_stride(struct intel_plane * plane,u32 pixel_format,u64 modifier,unsigned int rotation)723cb807055SVille Syrjälä i965_plane_max_stride(struct intel_plane *plane,
724cb807055SVille Syrjälä u32 pixel_format, u64 modifier,
725cb807055SVille Syrjälä unsigned int rotation)
726cb807055SVille Syrjälä {
727cb807055SVille Syrjälä const struct drm_format_info *info = drm_format_info(pixel_format);
728cb807055SVille Syrjälä int cpp = info->cpp[0];
729cb807055SVille Syrjälä
730cb807055SVille Syrjälä /* Limit to 4k pixels to guarantee TILEOFF.x doesn't get too big. */
731cb807055SVille Syrjälä if (modifier == I915_FORMAT_MOD_X_TILED)
732cb807055SVille Syrjälä return min(4096 * cpp, 16 * 1024);
733cb807055SVille Syrjälä else
734cb807055SVille Syrjälä return 32 * 1024;
735cb807055SVille Syrjälä }
736cb807055SVille Syrjälä
737cb807055SVille Syrjälä static unsigned int
i9xx_plane_max_stride(struct intel_plane * plane,u32 pixel_format,u64 modifier,unsigned int rotation)73800a16d02SDave Airlie i9xx_plane_max_stride(struct intel_plane *plane,
73900a16d02SDave Airlie u32 pixel_format, u64 modifier,
74000a16d02SDave Airlie unsigned int rotation)
74100a16d02SDave Airlie {
74200a16d02SDave Airlie struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
74300a16d02SDave Airlie
744005e9537SMatt Roper if (DISPLAY_VER(dev_priv) >= 3) {
74500a16d02SDave Airlie if (modifier == I915_FORMAT_MOD_X_TILED)
74600a16d02SDave Airlie return 8*1024;
74700a16d02SDave Airlie else
74800a16d02SDave Airlie return 16*1024;
74900a16d02SDave Airlie } else {
75000a16d02SDave Airlie if (plane->i9xx_plane == PLANE_C)
75100a16d02SDave Airlie return 4*1024;
75200a16d02SDave Airlie else
75300a16d02SDave Airlie return 8*1024;
75400a16d02SDave Airlie }
75500a16d02SDave Airlie }
75600a16d02SDave Airlie
75700a16d02SDave Airlie static const struct drm_plane_funcs i965_plane_funcs = {
75800a16d02SDave Airlie .update_plane = drm_atomic_helper_update_plane,
75900a16d02SDave Airlie .disable_plane = drm_atomic_helper_disable_plane,
76000a16d02SDave Airlie .destroy = intel_plane_destroy,
76100a16d02SDave Airlie .atomic_duplicate_state = intel_plane_duplicate_state,
76200a16d02SDave Airlie .atomic_destroy_state = intel_plane_destroy_state,
76300a16d02SDave Airlie .format_mod_supported = i965_plane_format_mod_supported,
76400a16d02SDave Airlie };
76500a16d02SDave Airlie
76600a16d02SDave Airlie static const struct drm_plane_funcs i8xx_plane_funcs = {
76700a16d02SDave Airlie .update_plane = drm_atomic_helper_update_plane,
76800a16d02SDave Airlie .disable_plane = drm_atomic_helper_disable_plane,
76900a16d02SDave Airlie .destroy = intel_plane_destroy,
77000a16d02SDave Airlie .atomic_duplicate_state = intel_plane_duplicate_state,
77100a16d02SDave Airlie .atomic_destroy_state = intel_plane_destroy_state,
77200a16d02SDave Airlie .format_mod_supported = i8xx_plane_format_mod_supported,
77300a16d02SDave Airlie };
77400a16d02SDave Airlie
77500a16d02SDave Airlie struct intel_plane *
intel_primary_plane_create(struct drm_i915_private * dev_priv,enum pipe pipe)77600a16d02SDave Airlie intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe)
77700a16d02SDave Airlie {
77800a16d02SDave Airlie struct intel_plane *plane;
77900a16d02SDave Airlie const struct drm_plane_funcs *plane_funcs;
78000a16d02SDave Airlie unsigned int supported_rotations;
781e2b83294SImre Deak const u64 *modifiers;
78200a16d02SDave Airlie const u32 *formats;
78300a16d02SDave Airlie int num_formats;
78400a16d02SDave Airlie int ret, zpos;
78500a16d02SDave Airlie
78600a16d02SDave Airlie plane = intel_plane_alloc();
78700a16d02SDave Airlie if (IS_ERR(plane))
78800a16d02SDave Airlie return plane;
78900a16d02SDave Airlie
79000a16d02SDave Airlie plane->pipe = pipe;
79100a16d02SDave Airlie /*
79200a16d02SDave Airlie * On gen2/3 only plane A can do FBC, but the panel fitter and LVDS
79300a16d02SDave Airlie * port is hooked to pipe B. Hence we want plane A feeding pipe B.
79400a16d02SDave Airlie */
795005e9537SMatt Roper if (HAS_FBC(dev_priv) && DISPLAY_VER(dev_priv) < 4 &&
79600a16d02SDave Airlie INTEL_NUM_PIPES(dev_priv) == 2)
79700a16d02SDave Airlie plane->i9xx_plane = (enum i9xx_plane_id) !pipe;
79800a16d02SDave Airlie else
79900a16d02SDave Airlie plane->i9xx_plane = (enum i9xx_plane_id) pipe;
80000a16d02SDave Airlie plane->id = PLANE_PRIMARY;
80100a16d02SDave Airlie plane->frontbuffer_bit = INTEL_FRONTBUFFER(pipe, plane->id);
80200a16d02SDave Airlie
803825bd833SVille Syrjälä intel_fbc_add_plane(i9xx_plane_fbc(dev_priv, plane->i9xx_plane), plane);
80400a16d02SDave Airlie
80500a16d02SDave Airlie if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
80600a16d02SDave Airlie formats = vlv_primary_formats;
80700a16d02SDave Airlie num_formats = ARRAY_SIZE(vlv_primary_formats);
808005e9537SMatt Roper } else if (DISPLAY_VER(dev_priv) >= 4) {
80900a16d02SDave Airlie /*
81000a16d02SDave Airlie * WaFP16GammaEnabling:ivb
81100a16d02SDave Airlie * "Workaround : When using the 64-bit format, the plane
81200a16d02SDave Airlie * output on each color channel has one quarter amplitude.
81300a16d02SDave Airlie * It can be brought up to full amplitude by using pipe
81400a16d02SDave Airlie * gamma correction or pipe color space conversion to
81500a16d02SDave Airlie * multiply the plane output by four."
81600a16d02SDave Airlie *
81700a16d02SDave Airlie * There is no dedicated plane gamma for the primary plane,
81800a16d02SDave Airlie * and using the pipe gamma/csc could conflict with other
81900a16d02SDave Airlie * planes, so we choose not to expose fp16 on IVB primary
82000a16d02SDave Airlie * planes. HSW primary planes no longer have this problem.
82100a16d02SDave Airlie */
82200a16d02SDave Airlie if (IS_IVYBRIDGE(dev_priv)) {
82300a16d02SDave Airlie formats = ivb_primary_formats;
82400a16d02SDave Airlie num_formats = ARRAY_SIZE(ivb_primary_formats);
82500a16d02SDave Airlie } else {
82600a16d02SDave Airlie formats = i965_primary_formats;
82700a16d02SDave Airlie num_formats = ARRAY_SIZE(i965_primary_formats);
82800a16d02SDave Airlie }
82900a16d02SDave Airlie } else {
83000a16d02SDave Airlie formats = i8xx_primary_formats;
83100a16d02SDave Airlie num_formats = ARRAY_SIZE(i8xx_primary_formats);
83200a16d02SDave Airlie }
83300a16d02SDave Airlie
834005e9537SMatt Roper if (DISPLAY_VER(dev_priv) >= 4)
83500a16d02SDave Airlie plane_funcs = &i965_plane_funcs;
83600a16d02SDave Airlie else
83700a16d02SDave Airlie plane_funcs = &i8xx_plane_funcs;
83800a16d02SDave Airlie
83900a16d02SDave Airlie if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
84000a16d02SDave Airlie plane->min_cdclk = vlv_plane_min_cdclk;
84100a16d02SDave Airlie else if (IS_BROADWELL(dev_priv) || IS_HASWELL(dev_priv))
84200a16d02SDave Airlie plane->min_cdclk = hsw_plane_min_cdclk;
84300a16d02SDave Airlie else if (IS_IVYBRIDGE(dev_priv))
84400a16d02SDave Airlie plane->min_cdclk = ivb_plane_min_cdclk;
84500a16d02SDave Airlie else
84600a16d02SDave Airlie plane->min_cdclk = i9xx_plane_min_cdclk;
84700a16d02SDave Airlie
848cb807055SVille Syrjälä if (HAS_GMCH(dev_priv)) {
849005e9537SMatt Roper if (DISPLAY_VER(dev_priv) >= 4)
850cb807055SVille Syrjälä plane->max_stride = i965_plane_max_stride;
851cb807055SVille Syrjälä else
85200a16d02SDave Airlie plane->max_stride = i9xx_plane_max_stride;
853cb807055SVille Syrjälä } else {
854cb807055SVille Syrjälä if (IS_BROADWELL(dev_priv) || IS_HASWELL(dev_priv))
855cb807055SVille Syrjälä plane->max_stride = hsw_primary_max_stride;
856cb807055SVille Syrjälä else
857cb807055SVille Syrjälä plane->max_stride = ilk_primary_max_stride;
858cb807055SVille Syrjälä }
859cb807055SVille Syrjälä
8604d0d77deSVille Syrjälä if (IS_I830(dev_priv) || IS_I845G(dev_priv)) {
8614d0d77deSVille Syrjälä plane->update_arm = i830_plane_update_arm;
8624d0d77deSVille Syrjälä } else {
8634d0d77deSVille Syrjälä plane->update_noarm = i9xx_plane_update_noarm;
8648ac80733SVille Syrjälä plane->update_arm = i9xx_plane_update_arm;
8654d0d77deSVille Syrjälä }
8668ac80733SVille Syrjälä plane->disable_arm = i9xx_plane_disable_arm;
86700a16d02SDave Airlie plane->get_hw_state = i9xx_plane_get_hw_state;
86800a16d02SDave Airlie plane->check_plane = i9xx_plane_check;
86900a16d02SDave Airlie
8706ede6b06SVille Syrjälä if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
8716ede6b06SVille Syrjälä plane->async_flip = vlv_primary_async_flip;
8726ede6b06SVille Syrjälä plane->enable_flip_done = vlv_primary_enable_flip_done;
8736ede6b06SVille Syrjälä plane->disable_flip_done = vlv_primary_disable_flip_done;
8746ede6b06SVille Syrjälä } else if (IS_BROADWELL(dev_priv)) {
875cda195f1SVille Syrjälä plane->need_async_flip_disable_wa = true;
876cda195f1SVille Syrjälä plane->async_flip = g4x_primary_async_flip;
877cda195f1SVille Syrjälä plane->enable_flip_done = bdw_primary_enable_flip_done;
878cda195f1SVille Syrjälä plane->disable_flip_done = bdw_primary_disable_flip_done;
879005e9537SMatt Roper } else if (DISPLAY_VER(dev_priv) >= 7) {
8802a636e24SVille Syrjälä plane->async_flip = g4x_primary_async_flip;
8812a636e24SVille Syrjälä plane->enable_flip_done = ivb_primary_enable_flip_done;
8822a636e24SVille Syrjälä plane->disable_flip_done = ivb_primary_disable_flip_done;
883005e9537SMatt Roper } else if (DISPLAY_VER(dev_priv) >= 5) {
8844bb18054SVille Syrjälä plane->async_flip = g4x_primary_async_flip;
8854bb18054SVille Syrjälä plane->enable_flip_done = ilk_primary_enable_flip_done;
8864bb18054SVille Syrjälä plane->disable_flip_done = ilk_primary_disable_flip_done;
887cda195f1SVille Syrjälä }
888cda195f1SVille Syrjälä
88910a657ddSImre Deak modifiers = intel_fb_plane_get_modifiers(dev_priv, INTEL_PLANE_CAP_TILING_X);
890e2b83294SImre Deak
891005e9537SMatt Roper if (DISPLAY_VER(dev_priv) >= 5 || IS_G4X(dev_priv))
89200a16d02SDave Airlie ret = drm_universal_plane_init(&dev_priv->drm, &plane->base,
89300a16d02SDave Airlie 0, plane_funcs,
89400a16d02SDave Airlie formats, num_formats,
895e2b83294SImre Deak modifiers,
89600a16d02SDave Airlie DRM_PLANE_TYPE_PRIMARY,
89700a16d02SDave Airlie "primary %c", pipe_name(pipe));
89800a16d02SDave Airlie else
89900a16d02SDave Airlie ret = drm_universal_plane_init(&dev_priv->drm, &plane->base,
90000a16d02SDave Airlie 0, plane_funcs,
90100a16d02SDave Airlie formats, num_formats,
902e2b83294SImre Deak modifiers,
90300a16d02SDave Airlie DRM_PLANE_TYPE_PRIMARY,
90400a16d02SDave Airlie "plane %c",
90500a16d02SDave Airlie plane_name(plane->i9xx_plane));
906e2b83294SImre Deak
907e2b83294SImre Deak kfree(modifiers);
908e2b83294SImre Deak
90900a16d02SDave Airlie if (ret)
91000a16d02SDave Airlie goto fail;
91100a16d02SDave Airlie
91200a16d02SDave Airlie if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B) {
91300a16d02SDave Airlie supported_rotations =
91400a16d02SDave Airlie DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180 |
91500a16d02SDave Airlie DRM_MODE_REFLECT_X;
916005e9537SMatt Roper } else if (DISPLAY_VER(dev_priv) >= 4) {
91700a16d02SDave Airlie supported_rotations =
91800a16d02SDave Airlie DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180;
91900a16d02SDave Airlie } else {
92000a16d02SDave Airlie supported_rotations = DRM_MODE_ROTATE_0;
92100a16d02SDave Airlie }
92200a16d02SDave Airlie
923005e9537SMatt Roper if (DISPLAY_VER(dev_priv) >= 4)
92400a16d02SDave Airlie drm_plane_create_rotation_property(&plane->base,
92500a16d02SDave Airlie DRM_MODE_ROTATE_0,
92600a16d02SDave Airlie supported_rotations);
92700a16d02SDave Airlie
92800a16d02SDave Airlie zpos = 0;
92900a16d02SDave Airlie drm_plane_create_zpos_immutable_property(&plane->base, zpos);
93000a16d02SDave Airlie
931d372ba42SJani Nikula intel_plane_helper_add(plane);
93200a16d02SDave Airlie
93300a16d02SDave Airlie return plane;
93400a16d02SDave Airlie
93500a16d02SDave Airlie fail:
93600a16d02SDave Airlie intel_plane_free(plane);
93700a16d02SDave Airlie
93800a16d02SDave Airlie return ERR_PTR(ret);
93900a16d02SDave Airlie }
94000a16d02SDave Airlie
i9xx_format_to_fourcc(int format)9412a301449SDave Airlie static int i9xx_format_to_fourcc(int format)
9422a301449SDave Airlie {
9432a301449SDave Airlie switch (format) {
944428cb15dSVille Syrjälä case DISP_FORMAT_8BPP:
9452a301449SDave Airlie return DRM_FORMAT_C8;
946428cb15dSVille Syrjälä case DISP_FORMAT_BGRA555:
9472a301449SDave Airlie return DRM_FORMAT_ARGB1555;
948428cb15dSVille Syrjälä case DISP_FORMAT_BGRX555:
9492a301449SDave Airlie return DRM_FORMAT_XRGB1555;
950428cb15dSVille Syrjälä case DISP_FORMAT_BGRX565:
9512a301449SDave Airlie return DRM_FORMAT_RGB565;
9522a301449SDave Airlie default:
953428cb15dSVille Syrjälä case DISP_FORMAT_BGRX888:
9542a301449SDave Airlie return DRM_FORMAT_XRGB8888;
955428cb15dSVille Syrjälä case DISP_FORMAT_RGBX888:
9562a301449SDave Airlie return DRM_FORMAT_XBGR8888;
957428cb15dSVille Syrjälä case DISP_FORMAT_BGRA888:
9582a301449SDave Airlie return DRM_FORMAT_ARGB8888;
959428cb15dSVille Syrjälä case DISP_FORMAT_RGBA888:
9602a301449SDave Airlie return DRM_FORMAT_ABGR8888;
961428cb15dSVille Syrjälä case DISP_FORMAT_BGRX101010:
9622a301449SDave Airlie return DRM_FORMAT_XRGB2101010;
963428cb15dSVille Syrjälä case DISP_FORMAT_RGBX101010:
9642a301449SDave Airlie return DRM_FORMAT_XBGR2101010;
965428cb15dSVille Syrjälä case DISP_FORMAT_BGRA101010:
9662a301449SDave Airlie return DRM_FORMAT_ARGB2101010;
967428cb15dSVille Syrjälä case DISP_FORMAT_RGBA101010:
9682a301449SDave Airlie return DRM_FORMAT_ABGR2101010;
969428cb15dSVille Syrjälä case DISP_FORMAT_RGBX161616:
9702a301449SDave Airlie return DRM_FORMAT_XBGR16161616F;
9712a301449SDave Airlie }
9722a301449SDave Airlie }
9732a301449SDave Airlie
9742a301449SDave Airlie void
i9xx_get_initial_plane_config(struct intel_crtc * crtc,struct intel_initial_plane_config * plane_config)9752a301449SDave Airlie i9xx_get_initial_plane_config(struct intel_crtc *crtc,
9762a301449SDave Airlie struct intel_initial_plane_config *plane_config)
9772a301449SDave Airlie {
9782a301449SDave Airlie struct drm_device *dev = crtc->base.dev;
9792a301449SDave Airlie struct drm_i915_private *dev_priv = to_i915(dev);
9802a301449SDave Airlie struct intel_plane *plane = to_intel_plane(crtc->base.primary);
9812a301449SDave Airlie enum i9xx_plane_id i9xx_plane = plane->i9xx_plane;
9822a301449SDave Airlie enum pipe pipe;
9832a301449SDave Airlie u32 val, base, offset;
9842a301449SDave Airlie int fourcc, pixel_format;
9852a301449SDave Airlie unsigned int aligned_height;
9862a301449SDave Airlie struct drm_framebuffer *fb;
9872a301449SDave Airlie struct intel_framebuffer *intel_fb;
9882a301449SDave Airlie
9892a301449SDave Airlie if (!plane->get_hw_state(plane, &pipe))
9902a301449SDave Airlie return;
9912a301449SDave Airlie
9922a301449SDave Airlie drm_WARN_ON(dev, pipe != crtc->pipe);
9932a301449SDave Airlie
9942a301449SDave Airlie intel_fb = kzalloc(sizeof(*intel_fb), GFP_KERNEL);
9952a301449SDave Airlie if (!intel_fb) {
9962a301449SDave Airlie drm_dbg_kms(&dev_priv->drm, "failed to alloc fb\n");
9972a301449SDave Airlie return;
9982a301449SDave Airlie }
9992a301449SDave Airlie
10002a301449SDave Airlie fb = &intel_fb->base;
10012a301449SDave Airlie
10022a301449SDave Airlie fb->dev = dev;
10032a301449SDave Airlie
10042a301449SDave Airlie val = intel_de_read(dev_priv, DSPCNTR(i9xx_plane));
10052a301449SDave Airlie
1006005e9537SMatt Roper if (DISPLAY_VER(dev_priv) >= 4) {
1007428cb15dSVille Syrjälä if (val & DISP_TILED) {
10082a301449SDave Airlie plane_config->tiling = I915_TILING_X;
10092a301449SDave Airlie fb->modifier = I915_FORMAT_MOD_X_TILED;
10102a301449SDave Airlie }
10112a301449SDave Airlie
1012428cb15dSVille Syrjälä if (val & DISP_ROTATE_180)
10132a301449SDave Airlie plane_config->rotation = DRM_MODE_ROTATE_180;
10142a301449SDave Airlie }
10152a301449SDave Airlie
10162a301449SDave Airlie if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B &&
1017428cb15dSVille Syrjälä val & DISP_MIRROR)
10182a301449SDave Airlie plane_config->rotation |= DRM_MODE_REFLECT_X;
10192a301449SDave Airlie
1020428cb15dSVille Syrjälä pixel_format = val & DISP_FORMAT_MASK;
10212a301449SDave Airlie fourcc = i9xx_format_to_fourcc(pixel_format);
10222a301449SDave Airlie fb->format = drm_format_info(fourcc);
10232a301449SDave Airlie
10242a301449SDave Airlie if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) {
10252a301449SDave Airlie offset = intel_de_read(dev_priv, DSPOFFSET(i9xx_plane));
1026428cb15dSVille Syrjälä base = intel_de_read(dev_priv, DSPSURF(i9xx_plane)) & DISP_ADDR_MASK;
1027005e9537SMatt Roper } else if (DISPLAY_VER(dev_priv) >= 4) {
10282a301449SDave Airlie if (plane_config->tiling)
10292a301449SDave Airlie offset = intel_de_read(dev_priv,
10302a301449SDave Airlie DSPTILEOFF(i9xx_plane));
10312a301449SDave Airlie else
10322a301449SDave Airlie offset = intel_de_read(dev_priv,
10332a301449SDave Airlie DSPLINOFF(i9xx_plane));
1034428cb15dSVille Syrjälä base = intel_de_read(dev_priv, DSPSURF(i9xx_plane)) & DISP_ADDR_MASK;
10352a301449SDave Airlie } else {
1036*47e157a5SJani Nikula offset = 0;
10372a301449SDave Airlie base = intel_de_read(dev_priv, DSPADDR(i9xx_plane));
10382a301449SDave Airlie }
10392a301449SDave Airlie plane_config->base = base;
10402a301449SDave Airlie
1041*47e157a5SJani Nikula drm_WARN_ON(&dev_priv->drm, offset != 0);
1042*47e157a5SJani Nikula
10432a301449SDave Airlie val = intel_de_read(dev_priv, PIPESRC(pipe));
104462236df2SVille Syrjälä fb->width = REG_FIELD_GET(PIPESRC_WIDTH_MASK, val) + 1;
104562236df2SVille Syrjälä fb->height = REG_FIELD_GET(PIPESRC_HEIGHT_MASK, val) + 1;
10462a301449SDave Airlie
10472a301449SDave Airlie val = intel_de_read(dev_priv, DSPSTRIDE(i9xx_plane));
10482a301449SDave Airlie fb->pitches[0] = val & 0xffffffc0;
10492a301449SDave Airlie
10502a301449SDave Airlie aligned_height = intel_fb_align_height(fb, 0, fb->height);
10512a301449SDave Airlie
10522a301449SDave Airlie plane_config->size = fb->pitches[0] * aligned_height;
10532a301449SDave Airlie
10542a301449SDave Airlie drm_dbg_kms(&dev_priv->drm,
10552a301449SDave Airlie "%s/%s with fb: size=%dx%d@%d, offset=%x, pitch %d, size 0x%x\n",
10562a301449SDave Airlie crtc->base.name, plane->base.name, fb->width, fb->height,
10572a301449SDave Airlie fb->format->cpp[0] * 8, base, fb->pitches[0],
10582a301449SDave Airlie plane_config->size);
10592a301449SDave Airlie
10602a301449SDave Airlie plane_config->fb = intel_fb;
10612a301449SDave Airlie }
1062