diff options
Diffstat (limited to 'drivers/gpu/drm/i915/intel_sprite.c')
-rw-r--r-- | drivers/gpu/drm/i915/intel_sprite.c | 243 |
1 files changed, 234 insertions, 9 deletions
diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index 1b6eb76beb7c..c7d25c5dd4e6 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c | |||
@@ -37,6 +37,174 @@ | |||
37 | #include "i915_drv.h" | 37 | #include "i915_drv.h" |
38 | 38 | ||
39 | static void | 39 | static void |
40 | vlv_update_plane(struct drm_plane *dplane, struct drm_framebuffer *fb, | ||
41 | struct drm_i915_gem_object *obj, int crtc_x, int crtc_y, | ||
42 | unsigned int crtc_w, unsigned int crtc_h, | ||
43 | uint32_t x, uint32_t y, | ||
44 | uint32_t src_w, uint32_t src_h) | ||
45 | { | ||
46 | struct drm_device *dev = dplane->dev; | ||
47 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
48 | struct intel_plane *intel_plane = to_intel_plane(dplane); | ||
49 | int pipe = intel_plane->pipe; | ||
50 | int plane = intel_plane->plane; | ||
51 | u32 sprctl; | ||
52 | unsigned long sprsurf_offset, linear_offset; | ||
53 | int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0); | ||
54 | |||
55 | sprctl = I915_READ(SPCNTR(pipe, plane)); | ||
56 | |||
57 | /* Mask out pixel format bits in case we change it */ | ||
58 | sprctl &= ~SP_PIXFORMAT_MASK; | ||
59 | sprctl &= ~SP_YUV_BYTE_ORDER_MASK; | ||
60 | sprctl &= ~SP_TILED; | ||
61 | |||
62 | switch (fb->pixel_format) { | ||
63 | case DRM_FORMAT_YUYV: | ||
64 | sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_YUYV; | ||
65 | break; | ||
66 | case DRM_FORMAT_YVYU: | ||
67 | sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_YVYU; | ||
68 | break; | ||
69 | case DRM_FORMAT_UYVY: | ||
70 | sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_UYVY; | ||
71 | break; | ||
72 | case DRM_FORMAT_VYUY: | ||
73 | sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_VYUY; | ||
74 | break; | ||
75 | case DRM_FORMAT_RGB565: | ||
76 | sprctl |= SP_FORMAT_BGR565; | ||
77 | break; | ||
78 | case DRM_FORMAT_XRGB8888: | ||
79 | sprctl |= SP_FORMAT_BGRX8888; | ||
80 | break; | ||
81 | case DRM_FORMAT_ARGB8888: | ||
82 | sprctl |= SP_FORMAT_BGRA8888; | ||
83 | break; | ||
84 | case DRM_FORMAT_XBGR2101010: | ||
85 | sprctl |= SP_FORMAT_RGBX1010102; | ||
86 | break; | ||
87 | case DRM_FORMAT_ABGR2101010: | ||
88 | sprctl |= SP_FORMAT_RGBA1010102; | ||
89 | break; | ||
90 | case DRM_FORMAT_XBGR8888: | ||
91 | sprctl |= SP_FORMAT_RGBX8888; | ||
92 | break; | ||
93 | case DRM_FORMAT_ABGR8888: | ||
94 | sprctl |= SP_FORMAT_RGBA8888; | ||
95 | break; | ||
96 | default: | ||
97 | /* | ||
98 | * If we get here one of the upper layers failed to filter | ||
99 | * out the unsupported plane formats | ||
100 | */ | ||
101 | BUG(); | ||
102 | break; | ||
103 | } | ||
104 | |||
105 | if (obj->tiling_mode != I915_TILING_NONE) | ||
106 | sprctl |= SP_TILED; | ||
107 | |||
108 | sprctl |= SP_ENABLE; | ||
109 | |||
110 | /* Sizes are 0 based */ | ||
111 | src_w--; | ||
112 | src_h--; | ||
113 | crtc_w--; | ||
114 | crtc_h--; | ||
115 | |||
116 | intel_update_sprite_watermarks(dev, pipe, crtc_w, pixel_size); | ||
117 | |||
118 | I915_WRITE(SPSTRIDE(pipe, plane), fb->pitches[0]); | ||
119 | I915_WRITE(SPPOS(pipe, plane), (crtc_y << 16) | crtc_x); | ||
120 | |||
121 | linear_offset = y * fb->pitches[0] + x * pixel_size; | ||
122 | sprsurf_offset = intel_gen4_compute_page_offset(&x, &y, | ||
123 | obj->tiling_mode, | ||
124 | pixel_size, | ||
125 | fb->pitches[0]); | ||
126 | linear_offset -= sprsurf_offset; | ||
127 | |||
128 | if (obj->tiling_mode != I915_TILING_NONE) | ||
129 | I915_WRITE(SPTILEOFF(pipe, plane), (y << 16) | x); | ||
130 | else | ||
131 | I915_WRITE(SPLINOFF(pipe, plane), linear_offset); | ||
132 | |||
133 | I915_WRITE(SPSIZE(pipe, plane), (crtc_h << 16) | crtc_w); | ||
134 | I915_WRITE(SPCNTR(pipe, plane), sprctl); | ||
135 | I915_MODIFY_DISPBASE(SPSURF(pipe, plane), obj->gtt_offset + | ||
136 | sprsurf_offset); | ||
137 | POSTING_READ(SPSURF(pipe, plane)); | ||
138 | } | ||
139 | |||
140 | static void | ||
141 | vlv_disable_plane(struct drm_plane *dplane) | ||
142 | { | ||
143 | struct drm_device *dev = dplane->dev; | ||
144 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
145 | struct intel_plane *intel_plane = to_intel_plane(dplane); | ||
146 | int pipe = intel_plane->pipe; | ||
147 | int plane = intel_plane->plane; | ||
148 | |||
149 | I915_WRITE(SPCNTR(pipe, plane), I915_READ(SPCNTR(pipe, plane)) & | ||
150 | ~SP_ENABLE); | ||
151 | /* Activate double buffered register update */ | ||
152 | I915_MODIFY_DISPBASE(SPSURF(pipe, plane), 0); | ||
153 | POSTING_READ(SPSURF(pipe, plane)); | ||
154 | } | ||
155 | |||
156 | static int | ||
157 | vlv_update_colorkey(struct drm_plane *dplane, | ||
158 | struct drm_intel_sprite_colorkey *key) | ||
159 | { | ||
160 | struct drm_device *dev = dplane->dev; | ||
161 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
162 | struct intel_plane *intel_plane = to_intel_plane(dplane); | ||
163 | int pipe = intel_plane->pipe; | ||
164 | int plane = intel_plane->plane; | ||
165 | u32 sprctl; | ||
166 | |||
167 | if (key->flags & I915_SET_COLORKEY_DESTINATION) | ||
168 | return -EINVAL; | ||
169 | |||
170 | I915_WRITE(SPKEYMINVAL(pipe, plane), key->min_value); | ||
171 | I915_WRITE(SPKEYMAXVAL(pipe, plane), key->max_value); | ||
172 | I915_WRITE(SPKEYMSK(pipe, plane), key->channel_mask); | ||
173 | |||
174 | sprctl = I915_READ(SPCNTR(pipe, plane)); | ||
175 | sprctl &= ~SP_SOURCE_KEY; | ||
176 | if (key->flags & I915_SET_COLORKEY_SOURCE) | ||
177 | sprctl |= SP_SOURCE_KEY; | ||
178 | I915_WRITE(SPCNTR(pipe, plane), sprctl); | ||
179 | |||
180 | POSTING_READ(SPKEYMSK(pipe, plane)); | ||
181 | |||
182 | return 0; | ||
183 | } | ||
184 | |||
185 | static void | ||
186 | vlv_get_colorkey(struct drm_plane *dplane, | ||
187 | struct drm_intel_sprite_colorkey *key) | ||
188 | { | ||
189 | struct drm_device *dev = dplane->dev; | ||
190 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
191 | struct intel_plane *intel_plane = to_intel_plane(dplane); | ||
192 | int pipe = intel_plane->pipe; | ||
193 | int plane = intel_plane->plane; | ||
194 | u32 sprctl; | ||
195 | |||
196 | key->min_value = I915_READ(SPKEYMINVAL(pipe, plane)); | ||
197 | key->max_value = I915_READ(SPKEYMAXVAL(pipe, plane)); | ||
198 | key->channel_mask = I915_READ(SPKEYMSK(pipe, plane)); | ||
199 | |||
200 | sprctl = I915_READ(SPCNTR(pipe, plane)); | ||
201 | if (sprctl & SP_SOURCE_KEY) | ||
202 | key->flags = I915_SET_COLORKEY_SOURCE; | ||
203 | else | ||
204 | key->flags = I915_SET_COLORKEY_NONE; | ||
205 | } | ||
206 | |||
207 | static void | ||
40 | ivb_update_plane(struct drm_plane *plane, struct drm_framebuffer *fb, | 208 | ivb_update_plane(struct drm_plane *plane, struct drm_framebuffer *fb, |
41 | struct drm_i915_gem_object *obj, int crtc_x, int crtc_y, | 209 | struct drm_i915_gem_object *obj, int crtc_x, int crtc_y, |
42 | unsigned int crtc_w, unsigned int crtc_h, | 210 | unsigned int crtc_w, unsigned int crtc_h, |
@@ -441,6 +609,15 @@ intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, | |||
441 | 609 | ||
442 | old_obj = intel_plane->obj; | 610 | old_obj = intel_plane->obj; |
443 | 611 | ||
612 | intel_plane->crtc_x = crtc_x; | ||
613 | intel_plane->crtc_y = crtc_y; | ||
614 | intel_plane->crtc_w = crtc_w; | ||
615 | intel_plane->crtc_h = crtc_h; | ||
616 | intel_plane->src_x = src_x; | ||
617 | intel_plane->src_y = src_y; | ||
618 | intel_plane->src_w = src_w; | ||
619 | intel_plane->src_h = src_h; | ||
620 | |||
444 | src_w = src_w >> 16; | 621 | src_w = src_w >> 16; |
445 | src_h = src_h >> 16; | 622 | src_h = src_h >> 16; |
446 | 623 | ||
@@ -513,6 +690,11 @@ intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, | |||
513 | 690 | ||
514 | mutex_lock(&dev->struct_mutex); | 691 | mutex_lock(&dev->struct_mutex); |
515 | 692 | ||
693 | /* Note that this will apply the VT-d workaround for scanouts, | ||
694 | * which is more restrictive than required for sprites. (The | ||
695 | * primary plane requires 256KiB alignment with 64 PTE padding, | ||
696 | * the sprite planes only require 128KiB alignment and 32 PTE padding. | ||
697 | */ | ||
516 | ret = intel_pin_and_fence_fb_obj(dev, obj, NULL); | 698 | ret = intel_pin_and_fence_fb_obj(dev, obj, NULL); |
517 | if (ret) | 699 | if (ret) |
518 | goto out_unlock; | 700 | goto out_unlock; |
@@ -568,6 +750,8 @@ intel_disable_plane(struct drm_plane *plane) | |||
568 | if (!intel_plane->obj) | 750 | if (!intel_plane->obj) |
569 | goto out; | 751 | goto out; |
570 | 752 | ||
753 | intel_wait_for_vblank(dev, intel_plane->pipe); | ||
754 | |||
571 | mutex_lock(&dev->struct_mutex); | 755 | mutex_lock(&dev->struct_mutex); |
572 | intel_unpin_fb_obj(intel_plane->obj); | 756 | intel_unpin_fb_obj(intel_plane->obj); |
573 | intel_plane->obj = NULL; | 757 | intel_plane->obj = NULL; |
@@ -647,6 +831,20 @@ out_unlock: | |||
647 | return ret; | 831 | return ret; |
648 | } | 832 | } |
649 | 833 | ||
834 | void intel_plane_restore(struct drm_plane *plane) | ||
835 | { | ||
836 | struct intel_plane *intel_plane = to_intel_plane(plane); | ||
837 | |||
838 | if (!plane->crtc || !plane->fb) | ||
839 | return; | ||
840 | |||
841 | intel_update_plane(plane, plane->crtc, plane->fb, | ||
842 | intel_plane->crtc_x, intel_plane->crtc_y, | ||
843 | intel_plane->crtc_w, intel_plane->crtc_h, | ||
844 | intel_plane->src_x, intel_plane->src_y, | ||
845 | intel_plane->src_w, intel_plane->src_h); | ||
846 | } | ||
847 | |||
650 | static const struct drm_plane_funcs intel_plane_funcs = { | 848 | static const struct drm_plane_funcs intel_plane_funcs = { |
651 | .update_plane = intel_update_plane, | 849 | .update_plane = intel_update_plane, |
652 | .disable_plane = intel_disable_plane, | 850 | .disable_plane = intel_disable_plane, |
@@ -670,8 +868,22 @@ static uint32_t snb_plane_formats[] = { | |||
670 | DRM_FORMAT_VYUY, | 868 | DRM_FORMAT_VYUY, |
671 | }; | 869 | }; |
672 | 870 | ||
871 | static uint32_t vlv_plane_formats[] = { | ||
872 | DRM_FORMAT_RGB565, | ||
873 | DRM_FORMAT_ABGR8888, | ||
874 | DRM_FORMAT_ARGB8888, | ||
875 | DRM_FORMAT_XBGR8888, | ||
876 | DRM_FORMAT_XRGB8888, | ||
877 | DRM_FORMAT_XBGR2101010, | ||
878 | DRM_FORMAT_ABGR2101010, | ||
879 | DRM_FORMAT_YUYV, | ||
880 | DRM_FORMAT_YVYU, | ||
881 | DRM_FORMAT_UYVY, | ||
882 | DRM_FORMAT_VYUY, | ||
883 | }; | ||
884 | |||
673 | int | 885 | int |
674 | intel_plane_init(struct drm_device *dev, enum pipe pipe) | 886 | intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane) |
675 | { | 887 | { |
676 | struct intel_plane *intel_plane; | 888 | struct intel_plane *intel_plane; |
677 | unsigned long possible_crtcs; | 889 | unsigned long possible_crtcs; |
@@ -710,14 +922,26 @@ intel_plane_init(struct drm_device *dev, enum pipe pipe) | |||
710 | intel_plane->can_scale = false; | 922 | intel_plane->can_scale = false; |
711 | else | 923 | else |
712 | intel_plane->can_scale = true; | 924 | intel_plane->can_scale = true; |
713 | intel_plane->max_downscale = 2; | 925 | |
714 | intel_plane->update_plane = ivb_update_plane; | 926 | if (IS_VALLEYVIEW(dev)) { |
715 | intel_plane->disable_plane = ivb_disable_plane; | 927 | intel_plane->max_downscale = 1; |
716 | intel_plane->update_colorkey = ivb_update_colorkey; | 928 | intel_plane->update_plane = vlv_update_plane; |
717 | intel_plane->get_colorkey = ivb_get_colorkey; | 929 | intel_plane->disable_plane = vlv_disable_plane; |
718 | 930 | intel_plane->update_colorkey = vlv_update_colorkey; | |
719 | plane_formats = snb_plane_formats; | 931 | intel_plane->get_colorkey = vlv_get_colorkey; |
720 | num_plane_formats = ARRAY_SIZE(snb_plane_formats); | 932 | |
933 | plane_formats = vlv_plane_formats; | ||
934 | num_plane_formats = ARRAY_SIZE(vlv_plane_formats); | ||
935 | } else { | ||
936 | intel_plane->max_downscale = 2; | ||
937 | intel_plane->update_plane = ivb_update_plane; | ||
938 | intel_plane->disable_plane = ivb_disable_plane; | ||
939 | intel_plane->update_colorkey = ivb_update_colorkey; | ||
940 | intel_plane->get_colorkey = ivb_get_colorkey; | ||
941 | |||
942 | plane_formats = snb_plane_formats; | ||
943 | num_plane_formats = ARRAY_SIZE(snb_plane_formats); | ||
944 | } | ||
721 | break; | 945 | break; |
722 | 946 | ||
723 | default: | 947 | default: |
@@ -726,6 +950,7 @@ intel_plane_init(struct drm_device *dev, enum pipe pipe) | |||
726 | } | 950 | } |
727 | 951 | ||
728 | intel_plane->pipe = pipe; | 952 | intel_plane->pipe = pipe; |
953 | intel_plane->plane = plane; | ||
729 | possible_crtcs = (1 << pipe); | 954 | possible_crtcs = (1 << pipe); |
730 | ret = drm_plane_init(dev, &intel_plane->base, possible_crtcs, | 955 | ret = drm_plane_init(dev, &intel_plane->base, possible_crtcs, |
731 | &intel_plane_funcs, | 956 | &intel_plane_funcs, |