Rev 4075 | Rev 4111 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 4075 | Rev 4080 | ||
---|---|---|---|
1 | /************************************************************************** |
1 | /************************************************************************** |
2 | * |
2 | * |
3 | * Copyright © 2011 VMware, Inc., Palo Alto, CA., USA |
3 | * Copyright © 2011 VMware, Inc., Palo Alto, CA., USA |
4 | * All Rights Reserved. |
4 | * All Rights Reserved. |
5 | * |
5 | * |
6 | * Permission is hereby granted, free of charge, to any person obtaining a |
6 | * Permission is hereby granted, free of charge, to any person obtaining a |
7 | * copy of this software and associated documentation files (the |
7 | * copy of this software and associated documentation files (the |
8 | * "Software"), to deal in the Software without restriction, including |
8 | * "Software"), to deal in the Software without restriction, including |
9 | * without limitation the rights to use, copy, modify, merge, publish, |
9 | * without limitation the rights to use, copy, modify, merge, publish, |
10 | * distribute, sub license, and/or sell copies of the Software, and to |
10 | * distribute, sub license, and/or sell copies of the Software, and to |
11 | * permit persons to whom the Software is furnished to do so, subject to |
11 | * permit persons to whom the Software is furnished to do so, subject to |
12 | * the following conditions: |
12 | * the following conditions: |
13 | * |
13 | * |
14 | * The above copyright notice and this permission notice (including the |
14 | * The above copyright notice and this permission notice (including the |
15 | * next paragraph) shall be included in all copies or substantial portions |
15 | * next paragraph) shall be included in all copies or substantial portions |
16 | * of the Software. |
16 | * of the Software. |
17 | * |
17 | * |
18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
20 | * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL |
20 | * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL |
21 | * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, |
21 | * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, |
22 | * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR |
22 | * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR |
23 | * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE |
23 | * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE |
24 | * USE OR OTHER DEALINGS IN THE SOFTWARE. |
24 | * USE OR OTHER DEALINGS IN THE SOFTWARE. |
25 | * |
25 | * |
26 | **************************************************************************/ |
26 | **************************************************************************/ |
27 | 27 | ||
28 | #include "vmwgfx_kms.h" |
28 | #include "vmwgfx_kms.h" |
29 | 29 | ||
30 | 30 | ||
31 | #define vmw_crtc_to_sou(x) \ |
31 | #define vmw_crtc_to_sou(x) \ |
32 | container_of(x, struct vmw_screen_object_unit, base.crtc) |
32 | container_of(x, struct vmw_screen_object_unit, base.crtc) |
33 | #define vmw_encoder_to_sou(x) \ |
33 | #define vmw_encoder_to_sou(x) \ |
34 | container_of(x, struct vmw_screen_object_unit, base.encoder) |
34 | container_of(x, struct vmw_screen_object_unit, base.encoder) |
35 | #define vmw_connector_to_sou(x) \ |
35 | #define vmw_connector_to_sou(x) \ |
36 | container_of(x, struct vmw_screen_object_unit, base.connector) |
36 | container_of(x, struct vmw_screen_object_unit, base.connector) |
37 | 37 | ||
38 | struct vmw_screen_object_display { |
38 | struct vmw_screen_object_display { |
39 | unsigned num_implicit; |
39 | unsigned num_implicit; |
40 | 40 | ||
41 | struct vmw_framebuffer *implicit_fb; |
41 | struct vmw_framebuffer *implicit_fb; |
42 | }; |
42 | }; |
43 | 43 | ||
44 | /** |
44 | /** |
45 | * Display unit using screen objects. |
45 | * Display unit using screen objects. |
46 | */ |
46 | */ |
47 | struct vmw_screen_object_unit { |
47 | struct vmw_screen_object_unit { |
48 | struct vmw_display_unit base; |
48 | struct vmw_display_unit base; |
49 | 49 | ||
50 | unsigned long buffer_size; /**< Size of allocated buffer */ |
50 | unsigned long buffer_size; /**< Size of allocated buffer */ |
51 | struct vmw_dma_buffer *buffer; /**< Backing store buffer */ |
51 | struct vmw_dma_buffer *buffer; /**< Backing store buffer */ |
52 | 52 | ||
53 | bool defined; |
53 | bool defined; |
54 | bool active_implicit; |
54 | bool active_implicit; |
55 | }; |
55 | }; |
56 | 56 | ||
57 | static void vmw_sou_destroy(struct vmw_screen_object_unit *sou) |
57 | static void vmw_sou_destroy(struct vmw_screen_object_unit *sou) |
58 | { |
58 | { |
59 | // vmw_display_unit_cleanup(&sou->base); |
59 | // vmw_display_unit_cleanup(&sou->base); |
60 | kfree(sou); |
60 | kfree(sou); |
61 | } |
61 | } |
62 | 62 | ||
63 | 63 | ||
64 | /* |
64 | /* |
65 | * Screen Object Display Unit CRTC functions |
65 | * Screen Object Display Unit CRTC functions |
66 | */ |
66 | */ |
67 | 67 | ||
68 | static void vmw_sou_crtc_destroy(struct drm_crtc *crtc) |
68 | static void vmw_sou_crtc_destroy(struct drm_crtc *crtc) |
69 | { |
69 | { |
70 | vmw_sou_destroy(vmw_crtc_to_sou(crtc)); |
70 | vmw_sou_destroy(vmw_crtc_to_sou(crtc)); |
71 | } |
71 | } |
72 | 72 | ||
73 | static void vmw_sou_del_active(struct vmw_private *vmw_priv, |
73 | static void vmw_sou_del_active(struct vmw_private *vmw_priv, |
74 | struct vmw_screen_object_unit *sou) |
74 | struct vmw_screen_object_unit *sou) |
75 | { |
75 | { |
76 | struct vmw_screen_object_display *ld = vmw_priv->sou_priv; |
76 | struct vmw_screen_object_display *ld = vmw_priv->sou_priv; |
77 | 77 | ||
78 | if (sou->active_implicit) { |
78 | if (sou->active_implicit) { |
79 | if (--(ld->num_implicit) == 0) |
79 | if (--(ld->num_implicit) == 0) |
80 | ld->implicit_fb = NULL; |
80 | ld->implicit_fb = NULL; |
81 | sou->active_implicit = false; |
81 | sou->active_implicit = false; |
82 | } |
82 | } |
83 | } |
83 | } |
84 | 84 | ||
85 | static void vmw_sou_add_active(struct vmw_private *vmw_priv, |
85 | static void vmw_sou_add_active(struct vmw_private *vmw_priv, |
86 | struct vmw_screen_object_unit *sou, |
86 | struct vmw_screen_object_unit *sou, |
87 | struct vmw_framebuffer *vfb) |
87 | struct vmw_framebuffer *vfb) |
88 | { |
88 | { |
89 | struct vmw_screen_object_display *ld = vmw_priv->sou_priv; |
89 | struct vmw_screen_object_display *ld = vmw_priv->sou_priv; |
90 | 90 | ||
91 | BUG_ON(!ld->num_implicit && ld->implicit_fb); |
91 | BUG_ON(!ld->num_implicit && ld->implicit_fb); |
92 | 92 | ||
93 | if (!sou->active_implicit && sou->base.is_implicit) { |
93 | if (!sou->active_implicit && sou->base.is_implicit) { |
94 | ld->implicit_fb = vfb; |
94 | ld->implicit_fb = vfb; |
95 | sou->active_implicit = true; |
95 | sou->active_implicit = true; |
96 | ld->num_implicit++; |
96 | ld->num_implicit++; |
97 | } |
97 | } |
98 | } |
98 | } |
99 | 99 | ||
100 | /** |
100 | /** |
101 | * Send the fifo command to create a screen. |
101 | * Send the fifo command to create a screen. |
102 | */ |
102 | */ |
103 | static int vmw_sou_fifo_create(struct vmw_private *dev_priv, |
103 | int vmw_sou_fifo_create(struct vmw_private *dev_priv, |
104 | struct vmw_screen_object_unit *sou, |
104 | struct vmw_screen_object_unit *sou, |
105 | uint32_t x, uint32_t y, |
105 | uint32_t x, uint32_t y, |
106 | struct drm_display_mode *mode) |
106 | struct drm_display_mode *mode) |
107 | { |
107 | { |
108 | size_t fifo_size; |
108 | size_t fifo_size; |
109 | 109 | ||
110 | struct { |
110 | struct { |
111 | struct { |
111 | struct { |
112 | uint32_t cmdType; |
112 | uint32_t cmdType; |
113 | } header; |
113 | } header; |
114 | SVGAScreenObject obj; |
114 | SVGAScreenObject obj; |
115 | } *cmd; |
115 | } *cmd; |
116 | 116 | ||
- | 117 | // BUG_ON(!sou->buffer); |
|
- | 118 | ||
117 | BUG_ON(!sou->buffer); |
119 | ENTER(); |
118 | 120 | ||
119 | fifo_size = sizeof(*cmd); |
121 | fifo_size = sizeof(*cmd); |
120 | cmd = vmw_fifo_reserve(dev_priv, fifo_size); |
122 | cmd = vmw_fifo_reserve(dev_priv, fifo_size); |
121 | /* The hardware has hung, nothing we can do about it here. */ |
123 | /* The hardware has hung, nothing we can do about it here. */ |
122 | if (unlikely(cmd == NULL)) { |
124 | if (unlikely(cmd == NULL)) { |
123 | DRM_ERROR("Fifo reserve failed.\n"); |
125 | DRM_ERROR("Fifo reserve failed.\n"); |
124 | return -ENOMEM; |
126 | return -ENOMEM; |
125 | } |
127 | } |
126 | 128 | ||
127 | memset(cmd, 0, fifo_size); |
129 | memset(cmd, 0, fifo_size); |
128 | cmd->header.cmdType = SVGA_CMD_DEFINE_SCREEN; |
130 | cmd->header.cmdType = SVGA_CMD_DEFINE_SCREEN; |
129 | cmd->obj.structSize = sizeof(SVGAScreenObject); |
131 | cmd->obj.structSize = sizeof(SVGAScreenObject); |
130 | cmd->obj.id = sou->base.unit; |
132 | cmd->obj.id = sou->base.unit; |
131 | cmd->obj.flags = SVGA_SCREEN_HAS_ROOT | |
133 | cmd->obj.flags = SVGA_SCREEN_HAS_ROOT | |
132 | (sou->base.unit == 0 ? SVGA_SCREEN_IS_PRIMARY : 0); |
134 | (sou->base.unit == 0 ? SVGA_SCREEN_IS_PRIMARY : 0); |
133 | cmd->obj.size.width = mode->hdisplay; |
135 | cmd->obj.size.width = mode->hdisplay; |
134 | cmd->obj.size.height = mode->vdisplay; |
136 | cmd->obj.size.height = mode->vdisplay; |
135 | if (sou->base.is_implicit) { |
137 | if (sou->base.is_implicit) { |
136 | cmd->obj.root.x = x; |
138 | cmd->obj.root.x = x; |
137 | cmd->obj.root.y = y; |
139 | cmd->obj.root.y = y; |
138 | } else { |
140 | } else { |
139 | cmd->obj.root.x = sou->base.gui_x; |
141 | cmd->obj.root.x = sou->base.gui_x; |
140 | cmd->obj.root.y = sou->base.gui_y; |
142 | cmd->obj.root.y = sou->base.gui_y; |
141 | } |
143 | } |
142 | 144 | ||
143 | /* Ok to assume that buffer is pinned in vram */ |
145 | /* Ok to assume that buffer is pinned in vram */ |
144 | vmw_bo_get_guest_ptr(&sou->buffer->base, &cmd->obj.backingStore.ptr); |
146 | // vmw_bo_get_guest_ptr(&sou->buffer->base, &cmd->obj.backingStore.ptr); |
- | 147 | ||
- | 148 | cmd->obj.backingStore.ptr.gmrId = SVGA_GMR_FRAMEBUFFER; |
|
- | 149 | cmd->obj.backingStore.ptr.offset = 0; |
|
145 | cmd->obj.backingStore.pitch = mode->hdisplay * 4; |
150 | cmd->obj.backingStore.pitch = mode->hdisplay * 4; |
146 | 151 | ||
147 | vmw_fifo_commit(dev_priv, fifo_size); |
152 | vmw_fifo_commit(dev_priv, fifo_size); |
148 | 153 | ||
149 | sou->defined = true; |
154 | sou->defined = true; |
- | 155 | ||
- | 156 | LEAVE(); |
|
150 | 157 | ||
151 | return 0; |
158 | return 0; |
152 | } |
159 | } |
153 | 160 | ||
154 | /** |
161 | /** |
155 | * Send the fifo command to destroy a screen. |
162 | * Send the fifo command to destroy a screen. |
156 | */ |
163 | */ |
157 | static int vmw_sou_fifo_destroy(struct vmw_private *dev_priv, |
164 | static int vmw_sou_fifo_destroy(struct vmw_private *dev_priv, |
158 | struct vmw_screen_object_unit *sou) |
165 | struct vmw_screen_object_unit *sou) |
159 | { |
166 | { |
160 | size_t fifo_size; |
167 | size_t fifo_size; |
161 | int ret; |
168 | int ret; |
162 | 169 | ||
163 | struct { |
170 | struct { |
164 | struct { |
171 | struct { |
165 | uint32_t cmdType; |
172 | uint32_t cmdType; |
166 | } header; |
173 | } header; |
167 | SVGAFifoCmdDestroyScreen body; |
174 | SVGAFifoCmdDestroyScreen body; |
168 | } *cmd; |
175 | } *cmd; |
169 | 176 | ||
170 | /* no need to do anything */ |
177 | /* no need to do anything */ |
171 | if (unlikely(!sou->defined)) |
178 | if (unlikely(!sou->defined)) |
172 | return 0; |
179 | return 0; |
173 | 180 | ||
174 | fifo_size = sizeof(*cmd); |
181 | fifo_size = sizeof(*cmd); |
175 | cmd = vmw_fifo_reserve(dev_priv, fifo_size); |
182 | cmd = vmw_fifo_reserve(dev_priv, fifo_size); |
176 | /* the hardware has hung, nothing we can do about it here */ |
183 | /* the hardware has hung, nothing we can do about it here */ |
177 | if (unlikely(cmd == NULL)) { |
184 | if (unlikely(cmd == NULL)) { |
178 | DRM_ERROR("Fifo reserve failed.\n"); |
185 | DRM_ERROR("Fifo reserve failed.\n"); |
179 | return -ENOMEM; |
186 | return -ENOMEM; |
180 | } |
187 | } |
181 | 188 | ||
182 | memset(cmd, 0, fifo_size); |
189 | memset(cmd, 0, fifo_size); |
183 | cmd->header.cmdType = SVGA_CMD_DESTROY_SCREEN; |
190 | cmd->header.cmdType = SVGA_CMD_DESTROY_SCREEN; |
184 | cmd->body.screenId = sou->base.unit; |
191 | cmd->body.screenId = sou->base.unit; |
185 | 192 | ||
186 | vmw_fifo_commit(dev_priv, fifo_size); |
193 | vmw_fifo_commit(dev_priv, fifo_size); |
187 | 194 | ||
188 | /* Force sync */ |
195 | /* Force sync */ |
189 | ret = vmw_fallback_wait(dev_priv, false, true, 0, false, 3*HZ); |
196 | ret = vmw_fallback_wait(dev_priv, false, true, 0, false, 3*HZ); |
190 | if (unlikely(ret != 0)) |
197 | if (unlikely(ret != 0)) |
191 | DRM_ERROR("Failed to sync with HW"); |
198 | DRM_ERROR("Failed to sync with HW"); |
192 | else |
199 | else |
193 | sou->defined = false; |
200 | sou->defined = false; |
194 | 201 | ||
195 | return ret; |
202 | return ret; |
196 | } |
203 | } |
197 | 204 | ||
198 | /** |
205 | /** |
199 | * Free the backing store. |
206 | * Free the backing store. |
200 | */ |
207 | */ |
201 | static void vmw_sou_backing_free(struct vmw_private *dev_priv, |
208 | static void vmw_sou_backing_free(struct vmw_private *dev_priv, |
202 | struct vmw_screen_object_unit *sou) |
209 | struct vmw_screen_object_unit *sou) |
203 | { |
210 | { |
204 | struct ttm_buffer_object *bo; |
211 | struct ttm_buffer_object *bo; |
205 | 212 | ||
206 | if (unlikely(sou->buffer == NULL)) |
213 | if (unlikely(sou->buffer == NULL)) |
207 | return; |
214 | return; |
208 | 215 | ||
209 | bo = &sou->buffer->base; |
216 | bo = &sou->buffer->base; |
210 | ttm_bo_unref(&bo); |
217 | ttm_bo_unref(&bo); |
211 | sou->buffer = NULL; |
218 | sou->buffer = NULL; |
212 | sou->buffer_size = 0; |
219 | sou->buffer_size = 0; |
213 | } |
220 | } |
214 | 221 | ||
215 | /** |
222 | /** |
216 | * Allocate the backing store for the buffer. |
223 | * Allocate the backing store for the buffer. |
217 | */ |
224 | */ |
218 | static int vmw_sou_backing_alloc(struct vmw_private *dev_priv, |
225 | static int vmw_sou_backing_alloc(struct vmw_private *dev_priv, |
219 | struct vmw_screen_object_unit *sou, |
226 | struct vmw_screen_object_unit *sou, |
220 | unsigned long size) |
227 | unsigned long size) |
221 | { |
228 | { |
222 | int ret; |
229 | int ret; |
223 | 230 | ||
224 | if (sou->buffer_size == size) |
231 | if (sou->buffer_size == size) |
225 | return 0; |
232 | return 0; |
226 | 233 | ||
227 | if (sou->buffer) |
234 | if (sou->buffer) |
228 | vmw_sou_backing_free(dev_priv, sou); |
235 | vmw_sou_backing_free(dev_priv, sou); |
229 | 236 | ||
230 | sou->buffer = kzalloc(sizeof(*sou->buffer), GFP_KERNEL); |
237 | sou->buffer = kzalloc(sizeof(*sou->buffer), GFP_KERNEL); |
231 | if (unlikely(sou->buffer == NULL)) |
238 | if (unlikely(sou->buffer == NULL)) |
232 | return -ENOMEM; |
239 | return -ENOMEM; |
233 | 240 | ||
234 | /* After we have alloced the backing store might not be able to |
241 | /* After we have alloced the backing store might not be able to |
235 | * resume the overlays, this is preferred to failing to alloc. |
242 | * resume the overlays, this is preferred to failing to alloc. |
236 | */ |
243 | */ |
237 | // vmw_overlay_pause_all(dev_priv); |
244 | // vmw_overlay_pause_all(dev_priv); |
238 | ret = vmw_dmabuf_init(dev_priv, sou->buffer, size, |
245 | ret = vmw_dmabuf_init(dev_priv, sou->buffer, size, |
239 | &vmw_vram_ne_placement, |
246 | &vmw_vram_ne_placement, |
240 | false, &vmw_dmabuf_bo_free); |
247 | false, &vmw_dmabuf_bo_free); |
241 | // vmw_overlay_resume_all(dev_priv); |
248 | // vmw_overlay_resume_all(dev_priv); |
242 | 249 | ||
243 | if (unlikely(ret != 0)) |
250 | if (unlikely(ret != 0)) |
244 | sou->buffer = NULL; /* vmw_dmabuf_init frees on error */ |
251 | sou->buffer = NULL; /* vmw_dmabuf_init frees on error */ |
245 | else |
252 | else |
246 | sou->buffer_size = size; |
253 | sou->buffer_size = size; |
247 | 254 | ||
248 | return ret; |
255 | return ret; |
249 | } |
256 | } |
250 | 257 | ||
251 | static int vmw_sou_crtc_set_config(struct drm_mode_set *set) |
258 | static int vmw_sou_crtc_set_config(struct drm_mode_set *set) |
252 | { |
259 | { |
253 | struct vmw_private *dev_priv; |
260 | struct vmw_private *dev_priv; |
254 | struct vmw_screen_object_unit *sou; |
261 | struct vmw_screen_object_unit *sou; |
255 | struct drm_connector *connector; |
262 | struct drm_connector *connector; |
256 | struct drm_display_mode *mode; |
263 | struct drm_display_mode *mode; |
257 | struct drm_encoder *encoder; |
264 | struct drm_encoder *encoder; |
258 | struct vmw_framebuffer *vfb; |
265 | struct vmw_framebuffer *vfb; |
259 | struct drm_framebuffer *fb; |
266 | struct drm_framebuffer *fb; |
260 | struct drm_crtc *crtc; |
267 | struct drm_crtc *crtc; |
261 | int ret = 0; |
268 | int ret = 0; |
262 | 269 | ||
263 | if (!set) |
270 | if (!set) |
264 | return -EINVAL; |
271 | return -EINVAL; |
265 | 272 | ||
266 | if (!set->crtc) |
273 | if (!set->crtc) |
267 | return -EINVAL; |
274 | return -EINVAL; |
268 | 275 | ||
269 | /* get the sou */ |
276 | /* get the sou */ |
270 | crtc = set->crtc; |
277 | crtc = set->crtc; |
271 | sou = vmw_crtc_to_sou(crtc); |
278 | sou = vmw_crtc_to_sou(crtc); |
272 | vfb = set->fb ? vmw_framebuffer_to_vfb(set->fb) : NULL; |
279 | vfb = set->fb ? vmw_framebuffer_to_vfb(set->fb) : NULL; |
273 | dev_priv = vmw_priv(crtc->dev); |
280 | dev_priv = vmw_priv(crtc->dev); |
274 | 281 | ||
275 | if (set->num_connectors > 1) { |
282 | if (set->num_connectors > 1) { |
276 | DRM_ERROR("to many connectors\n"); |
283 | DRM_ERROR("to many connectors\n"); |
277 | return -EINVAL; |
284 | return -EINVAL; |
278 | } |
285 | } |
279 | 286 | ||
280 | if (set->num_connectors == 1 && |
287 | if (set->num_connectors == 1 && |
281 | set->connectors[0] != &sou->base.connector) { |
288 | set->connectors[0] != &sou->base.connector) { |
282 | DRM_ERROR("connector doesn't match %p %p\n", |
289 | DRM_ERROR("connector doesn't match %p %p\n", |
283 | set->connectors[0], &sou->base.connector); |
290 | set->connectors[0], &sou->base.connector); |
284 | return -EINVAL; |
291 | return -EINVAL; |
285 | } |
292 | } |
286 | 293 | ||
287 | /* sou only supports one fb active at the time */ |
294 | /* sou only supports one fb active at the time */ |
288 | if (sou->base.is_implicit && |
295 | if (sou->base.is_implicit && |
289 | dev_priv->sou_priv->implicit_fb && vfb && |
296 | dev_priv->sou_priv->implicit_fb && vfb && |
290 | !(dev_priv->sou_priv->num_implicit == 1 && |
297 | !(dev_priv->sou_priv->num_implicit == 1 && |
291 | sou->active_implicit) && |
298 | sou->active_implicit) && |
292 | dev_priv->sou_priv->implicit_fb != vfb) { |
299 | dev_priv->sou_priv->implicit_fb != vfb) { |
293 | DRM_ERROR("Multiple framebuffers not supported\n"); |
300 | DRM_ERROR("Multiple framebuffers not supported\n"); |
294 | return -EINVAL; |
301 | return -EINVAL; |
295 | } |
302 | } |
296 | 303 | ||
297 | /* since they always map one to one these are safe */ |
304 | /* since they always map one to one these are safe */ |
298 | connector = &sou->base.connector; |
305 | connector = &sou->base.connector; |
299 | encoder = &sou->base.encoder; |
306 | encoder = &sou->base.encoder; |
300 | 307 | ||
301 | /* should we turn the crtc off */ |
308 | /* should we turn the crtc off */ |
302 | if (set->num_connectors == 0 || !set->mode || !set->fb) { |
309 | if (set->num_connectors == 0 || !set->mode || !set->fb) { |
303 | ret = vmw_sou_fifo_destroy(dev_priv, sou); |
310 | ret = vmw_sou_fifo_destroy(dev_priv, sou); |
304 | /* the hardware has hung don't do anything more */ |
311 | /* the hardware has hung don't do anything more */ |
305 | if (unlikely(ret != 0)) |
312 | if (unlikely(ret != 0)) |
306 | return ret; |
313 | return ret; |
307 | 314 | ||
308 | connector->encoder = NULL; |
315 | connector->encoder = NULL; |
309 | encoder->crtc = NULL; |
316 | encoder->crtc = NULL; |
310 | crtc->fb = NULL; |
317 | crtc->fb = NULL; |
311 | crtc->x = 0; |
318 | crtc->x = 0; |
312 | crtc->y = 0; |
319 | crtc->y = 0; |
313 | 320 | ||
314 | vmw_sou_del_active(dev_priv, sou); |
321 | vmw_sou_del_active(dev_priv, sou); |
315 | 322 | ||
316 | vmw_sou_backing_free(dev_priv, sou); |
323 | vmw_sou_backing_free(dev_priv, sou); |
317 | 324 | ||
318 | return 0; |
325 | return 0; |
319 | } |
326 | } |
320 | 327 | ||
321 | 328 | ||
322 | /* we now know we want to set a mode */ |
329 | /* we now know we want to set a mode */ |
323 | mode = set->mode; |
330 | mode = set->mode; |
324 | fb = set->fb; |
331 | fb = set->fb; |
325 | 332 | ||
326 | if (set->x + mode->hdisplay > fb->width || |
333 | if (set->x + mode->hdisplay > fb->width || |
327 | set->y + mode->vdisplay > fb->height) { |
334 | set->y + mode->vdisplay > fb->height) { |
328 | DRM_ERROR("set outside of framebuffer\n"); |
335 | DRM_ERROR("set outside of framebuffer\n"); |
329 | return -EINVAL; |
336 | return -EINVAL; |
330 | } |
337 | } |
331 | 338 | ||
332 | // vmw_fb_off(dev_priv); |
339 | // vmw_fb_off(dev_priv); |
333 | 340 | ||
334 | if (mode->hdisplay != crtc->mode.hdisplay || |
341 | if (mode->hdisplay != crtc->mode.hdisplay || |
335 | mode->vdisplay != crtc->mode.vdisplay) { |
342 | mode->vdisplay != crtc->mode.vdisplay) { |
336 | /* no need to check if depth is different, because backing |
343 | /* no need to check if depth is different, because backing |
337 | * store depth is forced to 4 by the device. |
344 | * store depth is forced to 4 by the device. |
338 | */ |
345 | */ |
339 | 346 | ||
340 | ret = vmw_sou_fifo_destroy(dev_priv, sou); |
347 | ret = vmw_sou_fifo_destroy(dev_priv, sou); |
341 | /* the hardware has hung don't do anything more */ |
348 | /* the hardware has hung don't do anything more */ |
342 | if (unlikely(ret != 0)) |
349 | if (unlikely(ret != 0)) |
343 | return ret; |
350 | return ret; |
344 | 351 | ||
345 | vmw_sou_backing_free(dev_priv, sou); |
352 | vmw_sou_backing_free(dev_priv, sou); |
346 | } |
353 | } |
347 | 354 | ||
348 | if (!sou->buffer) { |
355 | if (!sou->buffer) { |
349 | /* forced to depth 4 by the device */ |
356 | /* forced to depth 4 by the device */ |
350 | size_t size = mode->hdisplay * mode->vdisplay * 4; |
357 | size_t size = mode->hdisplay * mode->vdisplay * 4; |
351 | ret = vmw_sou_backing_alloc(dev_priv, sou, size); |
358 | ret = vmw_sou_backing_alloc(dev_priv, sou, size); |
352 | if (unlikely(ret != 0)) |
359 | if (unlikely(ret != 0)) |
353 | return ret; |
360 | return ret; |
354 | } |
361 | } |
355 | 362 | ||
356 | ret = vmw_sou_fifo_create(dev_priv, sou, set->x, set->y, mode); |
363 | ret = vmw_sou_fifo_create(dev_priv, sou, set->x, set->y, mode); |
357 | if (unlikely(ret != 0)) { |
364 | if (unlikely(ret != 0)) { |
358 | /* |
365 | /* |
359 | * We are in a bit of a situation here, the hardware has |
366 | * We are in a bit of a situation here, the hardware has |
360 | * hung and we may or may not have a buffer hanging of |
367 | * hung and we may or may not have a buffer hanging of |
361 | * the screen object, best thing to do is not do anything |
368 | * the screen object, best thing to do is not do anything |
362 | * if we where defined, if not just turn the crtc of. |
369 | * if we where defined, if not just turn the crtc of. |
363 | * Not what userspace wants but it needs to htfu. |
370 | * Not what userspace wants but it needs to htfu. |
364 | */ |
371 | */ |
365 | if (sou->defined) |
372 | if (sou->defined) |
366 | return ret; |
373 | return ret; |
367 | 374 | ||
368 | connector->encoder = NULL; |
375 | connector->encoder = NULL; |
369 | encoder->crtc = NULL; |
376 | encoder->crtc = NULL; |
370 | crtc->fb = NULL; |
377 | crtc->fb = NULL; |
371 | crtc->x = 0; |
378 | crtc->x = 0; |
372 | crtc->y = 0; |
379 | crtc->y = 0; |
373 | 380 | ||
374 | return ret; |
381 | return ret; |
375 | } |
382 | } |
376 | 383 | ||
377 | vmw_sou_add_active(dev_priv, sou, vfb); |
384 | vmw_sou_add_active(dev_priv, sou, vfb); |
378 | 385 | ||
379 | connector->encoder = encoder; |
386 | connector->encoder = encoder; |
380 | encoder->crtc = crtc; |
387 | encoder->crtc = crtc; |
381 | crtc->mode = *mode; |
388 | crtc->mode = *mode; |
382 | crtc->fb = fb; |
389 | crtc->fb = fb; |
383 | crtc->x = set->x; |
390 | crtc->x = set->x; |
384 | crtc->y = set->y; |
391 | crtc->y = set->y; |
385 | 392 | ||
386 | return 0; |
393 | return 0; |
387 | } |
394 | } |
388 | 395 | ||
389 | static struct drm_crtc_funcs vmw_screen_object_crtc_funcs = { |
396 | static struct drm_crtc_funcs vmw_screen_object_crtc_funcs = { |
390 | .save = vmw_du_crtc_save, |
397 | .save = vmw_du_crtc_save, |
391 | .restore = vmw_du_crtc_restore, |
398 | .restore = vmw_du_crtc_restore, |
392 | // .cursor_set = vmw_du_crtc_cursor_set, |
399 | // .cursor_set = vmw_du_crtc_cursor_set, |
393 | // .cursor_move = vmw_du_crtc_cursor_move, |
400 | // .cursor_move = vmw_du_crtc_cursor_move, |
394 | .gamma_set = vmw_du_crtc_gamma_set, |
401 | .gamma_set = vmw_du_crtc_gamma_set, |
395 | .destroy = vmw_sou_crtc_destroy, |
402 | .destroy = vmw_sou_crtc_destroy, |
396 | .set_config = vmw_sou_crtc_set_config, |
403 | .set_config = vmw_sou_crtc_set_config, |
397 | // .page_flip = vmw_du_page_flip, |
404 | // .page_flip = vmw_du_page_flip, |
398 | }; |
405 | }; |
399 | 406 | ||
400 | /* |
407 | /* |
401 | * Screen Object Display Unit encoder functions |
408 | * Screen Object Display Unit encoder functions |
402 | */ |
409 | */ |
403 | 410 | ||
404 | static void vmw_sou_encoder_destroy(struct drm_encoder *encoder) |
411 | static void vmw_sou_encoder_destroy(struct drm_encoder *encoder) |
405 | { |
412 | { |
406 | vmw_sou_destroy(vmw_encoder_to_sou(encoder)); |
413 | vmw_sou_destroy(vmw_encoder_to_sou(encoder)); |
407 | } |
414 | } |
408 | 415 | ||
409 | static struct drm_encoder_funcs vmw_screen_object_encoder_funcs = { |
416 | static struct drm_encoder_funcs vmw_screen_object_encoder_funcs = { |
410 | .destroy = vmw_sou_encoder_destroy, |
417 | .destroy = vmw_sou_encoder_destroy, |
411 | }; |
418 | }; |
412 | 419 | ||
413 | /* |
420 | /* |
414 | * Screen Object Display Unit connector functions |
421 | * Screen Object Display Unit connector functions |
415 | */ |
422 | */ |
416 | 423 | ||
417 | static void vmw_sou_connector_destroy(struct drm_connector *connector) |
424 | static void vmw_sou_connector_destroy(struct drm_connector *connector) |
418 | { |
425 | { |
419 | vmw_sou_destroy(vmw_connector_to_sou(connector)); |
426 | vmw_sou_destroy(vmw_connector_to_sou(connector)); |
420 | } |
427 | } |
421 | 428 | ||
422 | static struct drm_connector_funcs vmw_legacy_connector_funcs = { |
429 | static struct drm_connector_funcs vmw_legacy_connector_funcs = { |
423 | .dpms = vmw_du_connector_dpms, |
430 | .dpms = vmw_du_connector_dpms, |
424 | .save = vmw_du_connector_save, |
431 | .save = vmw_du_connector_save, |
425 | .restore = vmw_du_connector_restore, |
432 | .restore = vmw_du_connector_restore, |
426 | .detect = vmw_du_connector_detect, |
433 | .detect = vmw_du_connector_detect, |
427 | .fill_modes = vmw_du_connector_fill_modes, |
434 | .fill_modes = vmw_du_connector_fill_modes, |
428 | .set_property = vmw_du_connector_set_property, |
435 | .set_property = vmw_du_connector_set_property, |
429 | .destroy = vmw_sou_connector_destroy, |
436 | .destroy = vmw_sou_connector_destroy, |
430 | }; |
437 | }; |
431 | 438 | ||
432 | static int vmw_sou_init(struct vmw_private *dev_priv, unsigned unit) |
439 | static int vmw_sou_init(struct vmw_private *dev_priv, unsigned unit) |
433 | { |
440 | { |
434 | struct vmw_screen_object_unit *sou; |
441 | struct vmw_screen_object_unit *sou; |
435 | struct drm_device *dev = dev_priv->dev; |
442 | struct drm_device *dev = dev_priv->dev; |
436 | struct drm_connector *connector; |
443 | struct drm_connector *connector; |
437 | struct drm_encoder *encoder; |
444 | struct drm_encoder *encoder; |
438 | struct drm_crtc *crtc; |
445 | struct drm_crtc *crtc; |
- | 446 | ||
- | 447 | ENTER(); |
|
439 | 448 | ||
440 | sou = kzalloc(sizeof(*sou), GFP_KERNEL); |
449 | sou = kzalloc(sizeof(*sou), GFP_KERNEL); |
441 | if (!sou) |
450 | if (!sou) |
442 | return -ENOMEM; |
451 | return -ENOMEM; |
443 | 452 | ||
444 | sou->base.unit = unit; |
453 | sou->base.unit = unit; |
445 | crtc = &sou->base.crtc; |
454 | crtc = &sou->base.crtc; |
446 | encoder = &sou->base.encoder; |
455 | encoder = &sou->base.encoder; |
447 | connector = &sou->base.connector; |
456 | connector = &sou->base.connector; |
448 | 457 | ||
449 | sou->active_implicit = false; |
458 | sou->active_implicit = false; |
450 | 459 | ||
451 | sou->base.pref_active = (unit == 0); |
460 | sou->base.pref_active = (unit == 0); |
452 | sou->base.pref_width = dev_priv->initial_width; |
461 | sou->base.pref_width = dev_priv->initial_width; |
453 | sou->base.pref_height = dev_priv->initial_height; |
462 | sou->base.pref_height = dev_priv->initial_height; |
454 | sou->base.pref_mode = NULL; |
463 | sou->base.pref_mode = NULL; |
455 | sou->base.is_implicit = true; |
464 | sou->base.is_implicit = true; |
456 | 465 | ||
457 | drm_connector_init(dev, connector, &vmw_legacy_connector_funcs, |
466 | drm_connector_init(dev, connector, &vmw_legacy_connector_funcs, |
458 | DRM_MODE_CONNECTOR_VIRTUAL); |
467 | DRM_MODE_CONNECTOR_VIRTUAL); |
459 | connector->status = vmw_du_connector_detect(connector, true); |
468 | connector->status = vmw_du_connector_detect(connector, true); |
460 | 469 | ||
461 | drm_encoder_init(dev, encoder, &vmw_screen_object_encoder_funcs, |
470 | drm_encoder_init(dev, encoder, &vmw_screen_object_encoder_funcs, |
462 | DRM_MODE_ENCODER_VIRTUAL); |
471 | DRM_MODE_ENCODER_VIRTUAL); |
463 | drm_mode_connector_attach_encoder(connector, encoder); |
472 | drm_mode_connector_attach_encoder(connector, encoder); |
464 | encoder->possible_crtcs = (1 << unit); |
473 | encoder->possible_crtcs = (1 << unit); |
465 | encoder->possible_clones = 0; |
474 | encoder->possible_clones = 0; |
466 | 475 | ||
467 | drm_crtc_init(dev, crtc, &vmw_screen_object_crtc_funcs); |
476 | drm_crtc_init(dev, crtc, &vmw_screen_object_crtc_funcs); |
468 | 477 | ||
469 | drm_mode_crtc_set_gamma_size(crtc, 256); |
478 | drm_mode_crtc_set_gamma_size(crtc, 256); |
470 | 479 | ||
471 | drm_object_attach_property(&connector->base, |
480 | drm_object_attach_property(&connector->base, |
472 | dev->mode_config.dirty_info_property, |
481 | dev->mode_config.dirty_info_property, |
473 | 1); |
482 | 1); |
474 | 483 | LEAVE(); |
|
475 | return 0; |
484 | return 0; |
476 | } |
485 | } |
477 | 486 | ||
478 | int vmw_kms_init_screen_object_display(struct vmw_private *dev_priv) |
487 | int vmw_kms_init_screen_object_display(struct vmw_private *dev_priv) |
479 | { |
488 | { |
480 | struct drm_device *dev = dev_priv->dev; |
489 | struct drm_device *dev = dev_priv->dev; |
481 | int i, ret; |
490 | int i, ret; |
482 | 491 | ||
483 | ENTER(); |
492 | ENTER(); |
484 | 493 | ||
485 | if (dev_priv->sou_priv) { |
494 | if (dev_priv->sou_priv) { |
486 | DRM_INFO("sou system already on\n"); |
495 | DRM_INFO("sou system already on\n"); |
487 | return -EINVAL; |
496 | return -EINVAL; |
488 | } |
497 | } |
489 | 498 | ||
490 | if (!(dev_priv->capabilities & SVGA_CAP_SCREEN_OBJECT_2)) { |
499 | if (!(dev_priv->capabilities & SVGA_CAP_SCREEN_OBJECT_2)) { |
491 | DRM_INFO("Not using screen objects," |
500 | DRM_INFO("Not using screen objects," |
492 | " missing cap SCREEN_OBJECT_2\n"); |
501 | " missing cap SCREEN_OBJECT_2\n"); |
493 | return -ENOSYS; |
502 | return -ENOSYS; |
494 | } |
503 | } |
495 | 504 | ||
496 | ret = -ENOMEM; |
505 | ret = -ENOMEM; |
497 | dev_priv->sou_priv = kmalloc(sizeof(*dev_priv->sou_priv), GFP_KERNEL); |
506 | dev_priv->sou_priv = kmalloc(sizeof(*dev_priv->sou_priv), GFP_KERNEL); |
498 | if (unlikely(!dev_priv->sou_priv)) |
507 | if (unlikely(!dev_priv->sou_priv)) |
499 | goto err_no_mem; |
508 | goto err_no_mem; |
500 | 509 | ||
501 | dev_priv->sou_priv->num_implicit = 0; |
510 | dev_priv->sou_priv->num_implicit = 0; |
502 | dev_priv->sou_priv->implicit_fb = NULL; |
511 | dev_priv->sou_priv->implicit_fb = NULL; |
503 | 512 | ||
504 | // ret = drm_vblank_init(dev, VMWGFX_NUM_DISPLAY_UNITS); |
513 | // ret = drm_vblank_init(dev, VMWGFX_NUM_DISPLAY_UNITS); |
505 | // if (unlikely(ret != 0)) |
514 | // if (unlikely(ret != 0)) |
506 | // goto err_free; |
515 | // goto err_free; |
507 | 516 | ||
508 | ret = drm_mode_create_dirty_info_property(dev); |
517 | ret = drm_mode_create_dirty_info_property(dev); |
509 | if (unlikely(ret != 0)) |
518 | if (unlikely(ret != 0)) |
510 | goto err_vblank_cleanup; |
519 | goto err_vblank_cleanup; |
511 | 520 | ||
512 | for (i = 0; i < VMWGFX_NUM_DISPLAY_UNITS; ++i) |
521 | for (i = 0; i < VMWGFX_NUM_DISPLAY_UNITS; ++i) |
513 | vmw_sou_init(dev_priv, i); |
522 | vmw_sou_init(dev_priv, i); |
514 | 523 | ||
515 | DRM_INFO("Screen objects system initialized\n"); |
524 | DRM_INFO("Screen objects system initialized\n"); |
516 | 525 | ||
517 | LEAVE(); |
526 | LEAVE(); |
518 | return 0; |
527 | return 0; |
519 | 528 | ||
520 | err_vblank_cleanup: |
529 | err_vblank_cleanup: |
521 | // drm_vblank_cleanup(dev); |
530 | // drm_vblank_cleanup(dev); |
522 | err_free: |
531 | err_free: |
523 | kfree(dev_priv->sou_priv); |
532 | kfree(dev_priv->sou_priv); |
524 | dev_priv->sou_priv = NULL; |
533 | dev_priv->sou_priv = NULL; |
525 | err_no_mem: |
534 | err_no_mem: |
526 | return ret; |
535 | return ret; |
527 | } |
536 | } |
528 | 537 | ||
529 | int vmw_kms_close_screen_object_display(struct vmw_private *dev_priv) |
538 | int vmw_kms_close_screen_object_display(struct vmw_private *dev_priv) |
530 | { |
539 | { |
531 | struct drm_device *dev = dev_priv->dev; |
540 | struct drm_device *dev = dev_priv->dev; |
532 | 541 | ||
533 | if (!dev_priv->sou_priv) |
542 | if (!dev_priv->sou_priv) |
534 | return -ENOSYS; |
543 | return -ENOSYS; |
535 | 544 | ||
536 | // drm_vblank_cleanup(dev); |
545 | // drm_vblank_cleanup(dev); |
537 | 546 | ||
538 | kfree(dev_priv->sou_priv); |
547 | kfree(dev_priv->sou_priv); |
539 | 548 | ||
540 | return 0; |
549 | return 0; |
541 | } |
550 | } |
542 | 551 | ||
543 | /** |
552 | /** |
544 | * Returns if this unit can be page flipped. |
553 | * Returns if this unit can be page flipped. |
545 | * Must be called with the mode_config mutex held. |
554 | * Must be called with the mode_config mutex held. |
546 | */ |
555 | */ |
547 | bool vmw_kms_screen_object_flippable(struct vmw_private *dev_priv, |
556 | bool vmw_kms_screen_object_flippable(struct vmw_private *dev_priv, |
548 | struct drm_crtc *crtc) |
557 | struct drm_crtc *crtc) |
549 | { |
558 | { |
550 | struct vmw_screen_object_unit *sou = vmw_crtc_to_sou(crtc); |
559 | struct vmw_screen_object_unit *sou = vmw_crtc_to_sou(crtc); |
551 | 560 | ||
552 | if (!sou->base.is_implicit) |
561 | if (!sou->base.is_implicit) |
553 | return true; |
562 | return true; |
554 | 563 | ||
555 | if (dev_priv->sou_priv->num_implicit != 1) |
564 | if (dev_priv->sou_priv->num_implicit != 1) |
556 | return false; |
565 | return false; |
557 | 566 | ||
558 | return true; |
567 | return true; |
559 | } |
568 | } |
560 | 569 | ||
561 | /** |
570 | /** |
562 | * Update the implicit fb to the current fb of this crtc. |
571 | * Update the implicit fb to the current fb of this crtc. |
563 | * Must be called with the mode_config mutex held. |
572 | * Must be called with the mode_config mutex held. |
564 | */ |
573 | */ |
565 | void vmw_kms_screen_object_update_implicit_fb(struct vmw_private *dev_priv, |
574 | void vmw_kms_screen_object_update_implicit_fb(struct vmw_private *dev_priv, |
566 | struct drm_crtc *crtc) |
575 | struct drm_crtc *crtc) |
567 | { |
576 | { |
568 | struct vmw_screen_object_unit *sou = vmw_crtc_to_sou(crtc); |
577 | struct vmw_screen_object_unit *sou = vmw_crtc_to_sou(crtc); |
569 | 578 | ||
570 | BUG_ON(!sou->base.is_implicit); |
579 | BUG_ON(!sou->base.is_implicit); |
571 | 580 | ||
572 | dev_priv->sou_priv->implicit_fb = |
581 | dev_priv->sou_priv->implicit_fb = |
573 | vmw_framebuffer_to_vfb(sou->base.crtc.fb); |
582 | vmw_framebuffer_to_vfb(sou->base.crtc.fb); |
574 | }>><>>> |
583 | } |
- | 584 | ||
- | 585 | #include "bitmap.h" |
|
- | 586 | ||
- | 587 | typedef struct |
|
- | 588 | { |
|
- | 589 | kobj_t header; |
|
- | 590 | ||
- | 591 | uint32_t *data; |
|
- | 592 | uint32_t hot_x; |
|
- | 593 | uint32_t hot_y; |
|
- | 594 | ||
- | 595 | struct list_head list; |
|
- | 596 | // struct drm_i915_gem_object *cobj; |
|
- | 597 | }cursor_t; |
|
- | 598 | ||
- | 599 | ||
- | 600 | struct tag_display |
|
- | 601 | { |
|
- | 602 | int x; |
|
- | 603 | int y; |
|
- | 604 | int width; |
|
- | 605 | int height; |
|
- | 606 | int bpp; |
|
- | 607 | int vrefresh; |
|
- | 608 | int pitch; |
|
- | 609 | int lfb; |
|
- | 610 | ||
- | 611 | int supported_modes; |
|
- | 612 | struct drm_device *ddev; |
|
- | 613 | struct drm_connector *connector; |
|
- | 614 | struct drm_crtc *crtc; |
|
- | 615 | ||
- | 616 | struct list_head cursors; |
|
- | 617 | ||
- | 618 | cursor_t *cursor; |
|
- | 619 | int (*init_cursor)(cursor_t*); |
|
- | 620 | cursor_t* (__stdcall *select_cursor)(cursor_t*); |
|
- | 621 | void (*show_cursor)(int show); |
|
- | 622 | void (__stdcall *move_cursor)(cursor_t *cursor, int x, int y); |
|
- | 623 | void (__stdcall *restore_cursor)(int x, int y); |
|
- | 624 | void (*disable_mouse)(void); |
|
- | 625 | u32 mask_seqno; |
|
- | 626 | u32 check_mouse; |
|
- | 627 | u32 check_m_pixel; |
|
- | 628 | u32 dirty; |
|
- | 629 | void (*update)(void); |
|
- | 630 | }; |
|
- | 631 | ||
- | 632 | extern struct drm_device *main_device; |
|
- | 633 | ||
- | 634 | bool set_mode(struct drm_device *dev, struct drm_connector *connector, |
|
- | 635 | videomode_t *reqmode, bool strict) |
|
- | 636 | { |
|
- | 637 | struct drm_display_mode *mode = NULL, *tmpmode; |
|
- | 638 | struct vmw_private *dev_priv = vmw_priv(main_device); |
|
- | 639 | struct vmw_screen_object_unit *sou; |
|
- | 640 | display_t *os_display; |
|
- | 641 | ||
- | 642 | bool ret = false; |
|
- | 643 | ||
- | 644 | ENTER(); |
|
- | 645 | ||
- | 646 | // dbgprintf("width %d height %d vrefresh %d\n", |
|
- | 647 | // reqmode->width, reqmode->height, reqmode->freq); |
|
- | 648 | ||
- | 649 | list_for_each_entry(tmpmode, &connector->modes, head) |
|
- | 650 | { |
|
- | 651 | if( (drm_mode_width(tmpmode) == reqmode->width) && |
|
- | 652 | (drm_mode_height(tmpmode) == reqmode->height) && |
|
- | 653 | (drm_mode_vrefresh(tmpmode) == reqmode->freq) ) |
|
- | 654 | { |
|
- | 655 | mode = tmpmode; |
|
- | 656 | goto do_set; |
|
- | 657 | } |
|
- | 658 | }; |
|
- | 659 | ||
- | 660 | if( (mode == NULL) && (strict == false) ) |
|
- | 661 | { |
|
- | 662 | list_for_each_entry(tmpmode, &connector->modes, head) |
|
- | 663 | { |
|
- | 664 | if( (drm_mode_width(tmpmode) == reqmode->width) && |
|
- | 665 | (drm_mode_height(tmpmode) == reqmode->height) ) |
|
- | 666 | { |
|
- | 667 | mode = tmpmode; |
|
- | 668 | goto do_set; |
|
- | 669 | } |
|
- | 670 | }; |
|
- | 671 | }; |
|
- | 672 | ||
- | 673 | do_set: |
|
- | 674 | ||
- | 675 | if( mode != NULL ) |
|
- | 676 | { |
|
- | 677 | struct drm_framebuffer *fb; |
|
- | 678 | struct drm_encoder *encoder; |
|
- | 679 | struct drm_crtc *crtc; |
|
- | 680 | ||
- | 681 | // char con_edid[128]; |
|
- | 682 | const char *con_name; |
|
- | 683 | const char *enc_name; |
|
- | 684 | ||
- | 685 | encoder = connector->encoder; |
|
- | 686 | crtc = encoder->crtc; |
|
- | 687 | ||
- | 688 | ||
- | 689 | // fb = list_first_entry(&dev->mode_config.fb_kernel_list, |
|
- | 690 | // struct drm_framebuffer, filp_head); |
|
- | 691 | ||
- | 692 | // memcpy(con_edid, connector->edid_blob_ptr->data, 128); |
|
- | 693 | ||
- | 694 | // dbgprintf("Manufacturer: %s Model %x Serial Number %u\n", |
|
- | 695 | // manufacturer_name(con_edid + 0x08), |
|
- | 696 | // (unsigned short)(con_edid[0x0A] + (con_edid[0x0B] << 8)), |
|
- | 697 | // (unsigned int)(con_edid[0x0C] + (con_edid[0x0D] << 8) |
|
- | 698 | // + (con_edid[0x0E] << 16) + (con_edid[0x0F] << 24))); |
|
- | 699 | ||
- | 700 | con_name = drm_get_connector_name(connector); |
|
- | 701 | enc_name = drm_get_encoder_name(encoder); |
|
- | 702 | ||
- | 703 | dbgprintf("set mode %d %d connector %s encoder %s\n", |
|
- | 704 | mode->hdisplay, mode->vdisplay, con_name, enc_name); |
|
- | 705 | ||
- | 706 | os_display = GetDisplay(); |
|
- | 707 | ||
- | 708 | #if 0 |
|
- | 709 | sou = vmw_crtc_to_sou(crtc); |
|
- | 710 | sou->defined = true; |
|
- | 711 | ||
- | 712 | ret = vmw_sou_fifo_destroy(dev_priv, sou); |
|
- | 713 | if (unlikely(ret != 0)) |
|
- | 714 | return ret; |
|
- | 715 | ||
- | 716 | ret = vmw_sou_fifo_create(dev_priv, sou, 0, 0, mode); |
|
- | 717 | ||
- | 718 | #else /* sledgehammer */ |
|
- | 719 | ||
- | 720 | vmw_write(dev_priv,SVGA_REG_WIDTH, mode->hdisplay); |
|
- | 721 | vmw_write(dev_priv,SVGA_REG_HEIGHT, mode->vdisplay); |
|
- | 722 | vmw_write(dev_priv,SVGA_REG_BITS_PER_PIXEL, 32); |
|
- | 723 | ret = 0; |
|
- | 724 | #endif |
|
- | 725 | if (ret == 0) |
|
- | 726 | { |
|
- | 727 | os_display->width = mode->hdisplay; |
|
- | 728 | os_display->height = mode->vdisplay; |
|
- | 729 | os_display->pitch = mode->hdisplay*4; |
|
- | 730 | os_display->vrefresh = drm_mode_vrefresh(mode); |
|
- | 731 | ||
- | 732 | sysSetScreen(os_display->width, os_display->height, os_display->pitch); |
|
- | 733 | ||
- | 734 | dbgprintf("new mode %d x %d pitch %d\n", |
|
- | 735 | os_display->width, os_display->height, os_display->pitch); |
|
- | 736 | } |
|
- | 737 | else |
|
- | 738 | DRM_ERROR("failed to set mode %d_%d on crtc %p\n", |
|
- | 739 | os_display->width, os_display->height, crtc); |
|
- | 740 | } |
|
- | 741 | ||
- | 742 | LEAVE(); |
|
- | 743 | return ret; |
|
- | 744 | };><>><>><>><>>><>>> |