Rev 6937 | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
5060 | serge | 1 | #include |
2338 | Serge | 2 | #include "intel_drv.h" |
6937 | serge | 3 | #include |
6660 | serge | 4 | #include |
6937 | serge | 5 | #include "i915_drv.h" |
2338 | Serge | 6 | |
7 | #include |
||
5354 | serge | 8 | #include |
2338 | Serge | 9 | |
6937 | serge | 10 | int printf ( const char * format, ... ); |
11 | |||
6283 | serge | 12 | void init_system_cursors(struct drm_device *dev); |
2338 | Serge | 13 | |
5354 | serge | 14 | display_t *os_display; |
2338 | Serge | 15 | |
5354 | serge | 16 | u32 cmd_buffer; |
17 | u32 cmd_offset; |
||
2340 | Serge | 18 | |
2351 | Serge | 19 | void init_render(); |
20 | int sna_init(); |
||
21 | |||
3031 | serge | 22 | static char *manufacturer_name(unsigned char *x) |
23 | { |
||
24 | static char name[4]; |
||
25 | |||
26 | name[0] = ((x[0] & 0x7C) >> 2) + '@'; |
||
27 | name[1] = ((x[0] & 0x03) << 3) + ((x[1] & 0xE0) >> 5) + '@'; |
||
28 | name[2] = (x[1] & 0x1F) + '@'; |
||
29 | name[3] = 0; |
||
30 | |||
31 | return name; |
||
32 | } |
||
33 | |||
6088 | serge | 34 | static int count_connector_modes(struct drm_connector* connector) |
35 | { |
||
36 | struct drm_display_mode *mode; |
||
37 | int count = 0; |
||
38 | |||
39 | list_for_each_entry(mode, &connector->modes, head) |
||
40 | count++; |
||
41 | |||
42 | return count; |
||
43 | }; |
||
44 | |||
6283 | serge | 45 | struct drm_framebuffer *get_framebuffer(struct drm_device *dev, struct drm_display_mode *mode, int tiling) |
46 | { |
||
6320 | serge | 47 | struct drm_i915_private *dev_priv = dev->dev_private; |
48 | struct intel_fbdev *ifbdev = dev_priv->fbdev; |
||
49 | struct intel_framebuffer *intel_fb = ifbdev->fb; |
||
50 | struct drm_framebuffer *fb = &intel_fb->base; |
||
6283 | serge | 51 | struct drm_i915_gem_object *obj = NULL; |
52 | int stride, size; |
||
53 | |||
54 | stride = mode->hdisplay *4; |
||
55 | |||
6320 | serge | 56 | if(IS_GEN3(dev)) |
57 | tiling = 0; |
||
58 | |||
6283 | serge | 59 | if(tiling) |
60 | { |
||
61 | int gen3size; |
||
62 | |||
6937 | serge | 63 | stride = ALIGN(stride, 512); |
6283 | serge | 64 | size = stride * ALIGN(mode->vdisplay, 8); |
6937 | serge | 65 | size = ALIGN(size, 4096); |
6283 | serge | 66 | } |
67 | else |
||
68 | { |
||
69 | stride = ALIGN(stride, 64); |
||
70 | size = stride * ALIGN(mode->vdisplay, 2); |
||
71 | } |
||
72 | |||
6296 | serge | 73 | DRM_DEBUG_KMS("size %x stride %x\n", size, stride); |
6283 | serge | 74 | |
75 | if(intel_fb == NULL || size > intel_fb->obj->base.size) |
||
76 | { |
||
77 | struct drm_mode_fb_cmd2 mode_cmd = {}; |
||
78 | int ret; |
||
79 | |||
80 | DRM_DEBUG_KMS("remove old framebuffer\n"); |
||
6320 | serge | 81 | set_fake_framebuffer(); |
6283 | serge | 82 | drm_framebuffer_remove(fb); |
83 | ifbdev->fb = NULL; |
||
84 | fb = NULL; |
||
85 | DRM_DEBUG_KMS("create new framebuffer\n"); |
||
86 | |||
87 | mode_cmd.width = mode->hdisplay; |
||
88 | mode_cmd.height = mode->vdisplay; |
||
89 | |||
90 | mode_cmd.pitches[0] = stride; |
||
91 | mode_cmd.pixel_format = DRM_FORMAT_XRGB8888; |
||
92 | |||
93 | mutex_lock(&dev->struct_mutex); |
||
94 | |||
95 | /* If the FB is too big, just don't use it since fbdev is not very |
||
96 | * important and we should probably use that space with FBC or other |
||
97 | * features. */ |
||
98 | if (size * 2 < dev_priv->gtt.stolen_usable_size) |
||
99 | obj = i915_gem_object_create_stolen(dev, size); |
||
100 | if (obj == NULL) |
||
101 | obj = i915_gem_alloc_object(dev, size); |
||
102 | if (!obj) { |
||
103 | DRM_ERROR("failed to allocate framebuffer\n"); |
||
104 | ret = -ENOMEM; |
||
105 | goto out; |
||
106 | } |
||
107 | |||
108 | fb = __intel_framebuffer_create(dev, &mode_cmd, obj); |
||
109 | if (IS_ERR(fb)) { |
||
110 | ret = PTR_ERR(fb); |
||
111 | goto out_unref; |
||
112 | } |
||
113 | |||
114 | /* Flush everything out, we'll be doing GTT only from now on */ |
||
6937 | serge | 115 | ret = intel_pin_and_fence_fb_obj(NULL, fb, NULL); |
6283 | serge | 116 | if (ret) { |
117 | DRM_ERROR("failed to pin obj: %d\n", ret); |
||
118 | goto out_fb; |
||
119 | } |
||
120 | mutex_unlock(&dev->struct_mutex); |
||
121 | ifbdev->fb = to_intel_framebuffer(fb); |
||
122 | } |
||
123 | |||
124 | obj = ifbdev->fb->obj; |
||
125 | |||
126 | if(tiling) |
||
127 | { |
||
128 | obj->tiling_mode = I915_TILING_X; |
||
129 | fb->modifier[0] = I915_FORMAT_MOD_X_TILED; |
||
130 | obj->fence_dirty = true; |
||
131 | obj->stride = stride; |
||
132 | }; |
||
133 | |||
6296 | serge | 134 | if (obj->base.name == 0) |
135 | { |
||
136 | int ret; |
||
137 | |||
138 | mutex_lock(&dev->object_name_lock); |
||
139 | idr_preload(GFP_KERNEL); |
||
140 | ret = idr_alloc(&dev->object_name_idr, &obj->base, 1, 0, GFP_NOWAIT); |
||
141 | idr_preload_end(); |
||
142 | mutex_unlock(&dev->object_name_lock); |
||
143 | obj->base.name = ret; |
||
144 | obj->base.handle_count++; |
||
145 | DRM_DEBUG_KMS("%s allocate fb name %d\n", __FUNCTION__, obj->base.name ); |
||
146 | } |
||
147 | |||
6283 | serge | 148 | fb->width = mode->hdisplay; |
149 | fb->height = mode->vdisplay; |
||
150 | |||
151 | fb->pitches[0] = |
||
152 | fb->pitches[1] = |
||
153 | fb->pitches[2] = |
||
154 | fb->pitches[3] = stride; |
||
155 | |||
156 | fb->bits_per_pixel = 32; |
||
157 | fb->depth = 24; |
||
6320 | serge | 158 | |
6283 | serge | 159 | return fb; |
160 | |||
161 | out_fb: |
||
162 | drm_framebuffer_remove(fb); |
||
163 | out_unref: |
||
164 | drm_gem_object_unreference(&obj->base); |
||
165 | out: |
||
166 | mutex_unlock(&dev->struct_mutex); |
||
167 | return NULL; |
||
168 | } |
||
169 | |||
5060 | serge | 170 | static int set_mode(struct drm_device *dev, struct drm_connector *connector, |
171 | struct drm_crtc *crtc, videomode_t *reqmode, bool strict) |
||
3031 | serge | 172 | { |
6296 | serge | 173 | struct drm_i915_private *dev_priv = dev->dev_private; |
174 | struct drm_mode_config *config = &dev->mode_config; |
||
175 | struct drm_display_mode *mode = NULL, *tmpmode; |
||
6088 | serge | 176 | struct drm_connector *tmpc; |
6296 | serge | 177 | struct drm_framebuffer *fb = NULL; |
3031 | serge | 178 | struct drm_mode_set set; |
6283 | serge | 179 | char con_edid[128]; |
3031 | serge | 180 | int ret; |
181 | |||
5060 | serge | 182 | drm_modeset_lock_all(dev); |
3031 | serge | 183 | |
6088 | serge | 184 | list_for_each_entry(tmpc, &dev->mode_config.connector_list, head) |
185 | { |
||
186 | const struct drm_connector_funcs *f = tmpc->funcs; |
||
187 | if(tmpc == connector) |
||
188 | continue; |
||
189 | f->dpms(tmpc, DRM_MODE_DPMS_OFF); |
||
190 | }; |
||
191 | |||
3031 | serge | 192 | list_for_each_entry(tmpmode, &connector->modes, head) |
193 | { |
||
5060 | serge | 194 | if( (tmpmode->hdisplay == reqmode->width) && |
195 | (tmpmode->vdisplay == reqmode->height) && |
||
3031 | serge | 196 | (drm_mode_vrefresh(tmpmode) == reqmode->freq) ) |
197 | { |
||
198 | mode = tmpmode; |
||
199 | goto do_set; |
||
200 | } |
||
201 | }; |
||
202 | |||
203 | if( (mode == NULL) && (strict == false) ) |
||
204 | { |
||
205 | list_for_each_entry(tmpmode, &connector->modes, head) |
||
206 | { |
||
5060 | serge | 207 | if( (tmpmode->hdisplay == reqmode->width) && |
208 | (tmpmode->vdisplay == reqmode->height) ) |
||
3031 | serge | 209 | { |
210 | mode = tmpmode; |
||
211 | goto do_set; |
||
212 | } |
||
213 | }; |
||
214 | }; |
||
215 | |||
6283 | serge | 216 | out: |
217 | drm_modeset_unlock_all(dev); |
||
3037 | serge | 218 | DRM_ERROR("%s failed\n", __FUNCTION__); |
3031 | serge | 219 | return -1; |
220 | |||
221 | do_set: |
||
222 | |||
6283 | serge | 223 | drm_modeset_unlock_all(dev); |
6088 | serge | 224 | |
6283 | serge | 225 | fb = get_framebuffer(dev, mode, 1); |
226 | if(fb == NULL) |
||
227 | { |
||
228 | DRM_ERROR("%s failed\n", __FUNCTION__); |
||
229 | return -1; |
||
230 | }; |
||
231 | drm_framebuffer_reference(fb); |
||
3031 | serge | 232 | |
6283 | serge | 233 | drm_modeset_lock_all(dev); |
6088 | serge | 234 | |
235 | memcpy(con_edid, connector->edid_blob_ptr->data, 128); |
||
6283 | serge | 236 | |
237 | DRM_DEBUG_KMS("set mode %dx%d: crtc %d connector %s\n" |
||
238 | "monitor: %s model %x serial number %u\n", |
||
239 | mode->hdisplay, mode->vdisplay, |
||
240 | crtc->base.id, connector->name, |
||
6296 | serge | 241 | manufacturer_name(con_edid + 0x08), |
242 | (unsigned short)(con_edid[0x0A] + (con_edid[0x0B] << 8)), |
||
243 | (unsigned int)(con_edid[0x0C] + (con_edid[0x0D] << 8) |
||
244 | + (con_edid[0x0E] << 16) + (con_edid[0x0F] << 24))); |
||
6088 | serge | 245 | |
3031 | serge | 246 | drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V); |
247 | |||
248 | crtc->enabled = true; |
||
249 | os_display->crtc = crtc; |
||
250 | |||
6283 | serge | 251 | DRM_DEBUG_KMS("fb:%p %dx%dx pitch %d format %x\n", |
6084 | serge | 252 | fb,fb->width,fb->height,fb->pitches[0],fb->pixel_format); |
253 | |||
3031 | serge | 254 | set.crtc = crtc; |
255 | set.x = 0; |
||
256 | set.y = 0; |
||
257 | set.mode = mode; |
||
258 | set.connectors = &connector; |
||
259 | set.num_connectors = 1; |
||
260 | set.fb = fb; |
||
261 | |||
5060 | serge | 262 | ret = drm_mode_set_config_internal(&set); |
263 | |||
3031 | serge | 264 | if ( !ret ) |
265 | { |
||
6283 | serge | 266 | struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb); |
267 | struct kos_framebuffer *kfb = intel_fb->private; |
||
6320 | serge | 268 | kolibri_framebuffer_update(dev, kfb); |
6283 | serge | 269 | DRM_DEBUG_KMS("kolibri framebuffer %p\n", kfb); |
270 | |||
271 | os_display->width = mode->hdisplay; |
||
272 | os_display->height = mode->vdisplay; |
||
3031 | serge | 273 | os_display->vrefresh = drm_mode_vrefresh(mode); |
6283 | serge | 274 | sysSetFramebuffer(intel_fb->private); |
275 | sysSetScreen(mode->hdisplay, mode->vdisplay, fb->pitches[0]); |
||
3031 | serge | 276 | |
6283 | serge | 277 | os_display->connector = connector; |
278 | os_display->crtc = connector->encoder->crtc; |
||
279 | os_display->supported_modes = count_connector_modes(connector); |
||
3031 | serge | 280 | |
6283 | serge | 281 | crtc->cursor_x = os_display->width/2; |
282 | crtc->cursor_y = os_display->height/2; |
||
283 | |||
284 | os_display->select_cursor(os_display->cursor); |
||
285 | |||
3037 | serge | 286 | DRM_DEBUG_KMS("new mode %d x %d pitch %d\n", |
6283 | serge | 287 | mode->hdisplay, mode->vdisplay, fb->pitches[0]); |
3031 | serge | 288 | } |
289 | else |
||
290 | DRM_ERROR("failed to set mode %d_%d on crtc %p\n", |
||
291 | fb->width, fb->height, crtc); |
||
292 | |||
6283 | serge | 293 | drm_framebuffer_unreference(fb); |
6084 | serge | 294 | drm_modeset_unlock_all(dev); |
295 | |||
3031 | serge | 296 | return ret; |
297 | } |
||
298 | |||
6088 | serge | 299 | static int set_mode_ex(struct drm_device *dev, |
300 | struct drm_connector *connector, struct drm_display_mode *mode) |
||
2338 | Serge | 301 | { |
6088 | serge | 302 | struct drm_i915_private *dev_priv = dev->dev_private; |
303 | struct drm_connector *tmpc; |
||
304 | struct drm_mode_config *config = &dev->mode_config; |
||
305 | struct drm_framebuffer *fb = NULL; |
||
306 | struct drm_mode_set set; |
||
6283 | serge | 307 | struct drm_crtc *crtc = NULL; |
308 | |||
6088 | serge | 309 | char con_edid[128]; |
310 | int stride; |
||
311 | int ret; |
||
2338 | Serge | 312 | |
6283 | serge | 313 | fb = get_framebuffer(dev, mode, 1); |
314 | if(fb == NULL) |
||
315 | { |
||
316 | DRM_ERROR("%s failed\n", __FUNCTION__); |
||
317 | return -1; |
||
318 | }; |
||
319 | drm_framebuffer_reference(fb); |
||
320 | |||
6088 | serge | 321 | drm_modeset_lock_all(dev); |
322 | |||
323 | list_for_each_entry(tmpc, &dev->mode_config.connector_list, head) |
||
2338 | Serge | 324 | { |
6088 | serge | 325 | const struct drm_connector_funcs *f = tmpc->funcs; |
326 | if(tmpc == connector) |
||
327 | continue; |
||
328 | f->dpms(tmpc, DRM_MODE_DPMS_OFF); |
||
2338 | Serge | 329 | }; |
6088 | serge | 330 | |
6283 | serge | 331 | crtc = connector->encoder->crtc; |
6088 | serge | 332 | |
333 | memcpy(con_edid, connector->edid_blob_ptr->data, 128); |
||
334 | DRM_DEBUG_KMS("set mode %dx%d: crtc %d connector %s\n" |
||
335 | "monitor: %s model %x serial number %u\n", |
||
6283 | serge | 336 | mode->hdisplay, mode->vdisplay, |
6088 | serge | 337 | connector->encoder->crtc->base.id, connector->name, |
338 | manufacturer_name(con_edid + 0x08), |
||
339 | (unsigned short)(con_edid[0x0A] + (con_edid[0x0B] << 8)), |
||
340 | (unsigned int)(con_edid[0x0C] + (con_edid[0x0D] << 8) |
||
341 | + (con_edid[0x0E] << 16) + (con_edid[0x0F] << 24))); |
||
342 | |||
6283 | serge | 343 | drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V); |
344 | |||
345 | crtc->enabled = true; |
||
346 | os_display->crtc = crtc; |
||
347 | |||
6088 | serge | 348 | DRM_DEBUG_KMS("use framebuffer %p %dx%d pitch %d format %x\n", |
349 | fb,fb->width,fb->height,fb->pitches[0],fb->pixel_format); |
||
350 | |||
6283 | serge | 351 | set.crtc = crtc; |
6088 | serge | 352 | set.x = 0; |
353 | set.y = 0; |
||
354 | set.mode = mode; |
||
355 | set.connectors = &connector; |
||
356 | set.num_connectors = 1; |
||
357 | set.fb = fb; |
||
358 | |||
359 | ret = drm_mode_set_config_internal(&set); |
||
360 | if ( !ret ) |
||
361 | { |
||
6283 | serge | 362 | struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb); |
363 | struct kos_framebuffer *kfb = intel_fb->private; |
||
6320 | serge | 364 | kolibri_framebuffer_update(dev, kfb); |
6283 | serge | 365 | DRM_DEBUG_KMS("kolibri framebuffer %p\n", kfb); |
6088 | serge | 366 | |
6283 | serge | 367 | os_display->width = mode->hdisplay; |
368 | os_display->height = mode->vdisplay; |
||
6088 | serge | 369 | os_display->vrefresh = drm_mode_vrefresh(mode); |
6283 | serge | 370 | sysSetFramebuffer(intel_fb->private); |
371 | sysSetScreen(mode->hdisplay, mode->vdisplay, fb->pitches[0]); |
||
6088 | serge | 372 | |
373 | os_display->connector = connector; |
||
374 | os_display->crtc = connector->encoder->crtc; |
||
375 | os_display->supported_modes = count_connector_modes(connector); |
||
376 | |||
377 | crtc->cursor_x = os_display->width/2; |
||
378 | crtc->cursor_y = os_display->height/2; |
||
379 | |||
6283 | serge | 380 | os_display->select_cursor(os_display->cursor); |
6088 | serge | 381 | |
382 | DRM_DEBUG_KMS("new mode %d x %d pitch %d\n", |
||
6283 | serge | 383 | mode->hdisplay, mode->vdisplay, fb->pitches[0]); |
6088 | serge | 384 | } |
385 | else |
||
386 | DRM_ERROR(" failed to set mode %d_%d on crtc %p\n", |
||
387 | fb->width, fb->height, connector->encoder->crtc); |
||
388 | |||
6283 | serge | 389 | drm_framebuffer_unreference(fb); |
6088 | serge | 390 | drm_modeset_unlock_all(dev); |
391 | return ret; |
||
392 | } |
||
393 | |||
394 | static int set_cmdline_mode(struct drm_device *dev, struct drm_connector *connector) |
||
395 | { |
||
396 | struct drm_display_mode *mode; |
||
397 | int retval; |
||
398 | |||
399 | mode = drm_mode_create_from_cmdline_mode(dev, &connector->cmdline_mode); |
||
400 | if(mode == NULL) |
||
401 | return EINVAL; |
||
402 | |||
403 | retval = set_mode_ex(dev, connector, mode); |
||
404 | |||
405 | drm_mode_destroy(dev, mode); |
||
406 | return retval; |
||
2338 | Serge | 407 | }; |
408 | |||
5060 | serge | 409 | static struct drm_crtc *get_possible_crtc(struct drm_device *dev, struct drm_encoder *encoder) |
3031 | serge | 410 | { |
5060 | serge | 411 | struct drm_crtc *tmp_crtc; |
412 | int crtc_mask = 1; |
||
3031 | serge | 413 | |
5060 | serge | 414 | list_for_each_entry(tmp_crtc, &dev->mode_config.crtc_list, head) |
3031 | serge | 415 | { |
5060 | serge | 416 | if (encoder->possible_crtcs & crtc_mask) |
6084 | serge | 417 | { |
5060 | serge | 418 | encoder->crtc = tmp_crtc; |
419 | DRM_DEBUG_KMS("use CRTC %p ID %d\n", tmp_crtc, tmp_crtc->base.id); |
||
420 | return tmp_crtc; |
||
421 | }; |
||
422 | crtc_mask <<= 1; |
||
3031 | serge | 423 | }; |
5060 | serge | 424 | return NULL; |
3031 | serge | 425 | }; |
426 | |||
6088 | serge | 427 | static int check_connector(struct drm_device *dev, struct drm_connector *connector) |
2338 | Serge | 428 | { |
6088 | serge | 429 | const struct drm_connector_helper_funcs *connector_funcs; |
4560 | Serge | 430 | struct drm_encoder *encoder; |
5060 | serge | 431 | struct drm_crtc *crtc; |
2338 | Serge | 432 | |
6088 | serge | 433 | if( connector->status != connector_status_connected) |
434 | return -EINVAL; |
||
435 | |||
436 | encoder = connector->encoder; |
||
437 | |||
438 | if(encoder == NULL) |
||
439 | { |
||
440 | connector_funcs = connector->helper_private; |
||
441 | encoder = connector_funcs->best_encoder(connector); |
||
442 | |||
443 | if( encoder == NULL) |
||
444 | { |
||
445 | DRM_DEBUG_KMS("CONNECTOR %s ID: %d no active encoders\n", |
||
446 | connector->name, connector->base.id); |
||
447 | return -EINVAL; |
||
448 | }; |
||
6131 | serge | 449 | connector->encoder = encoder; |
6088 | serge | 450 | } |
451 | |||
452 | crtc = encoder->crtc; |
||
453 | if(crtc == NULL) |
||
454 | crtc = get_possible_crtc(dev, encoder); |
||
455 | |||
456 | if(crtc != NULL) |
||
457 | { |
||
6131 | serge | 458 | DRM_DEBUG_KMS("%s connector: %p encode: %p crtc: %p\n",__FUNCTION__, |
459 | connector, encoder, crtc); |
||
6088 | serge | 460 | return 0; |
461 | } |
||
462 | else |
||
463 | DRM_DEBUG_KMS("No CRTC for encoder %d\n", encoder->base.id); |
||
464 | return -EINVAL; |
||
465 | } |
||
466 | |||
467 | static struct drm_connector* get_cmdline_connector(struct drm_device *dev, const char *cmdline) |
||
468 | { |
||
469 | struct drm_connector *connector; |
||
470 | |||
5060 | serge | 471 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) |
2338 | Serge | 472 | { |
6088 | serge | 473 | int name_len = __builtin_strlen(connector->name); |
474 | |||
475 | if (name_len == 0) |
||
2338 | Serge | 476 | continue; |
477 | |||
6088 | serge | 478 | if (__builtin_strncmp(connector->name, cmdline, name_len)) |
479 | continue; |
||
5060 | serge | 480 | |
6088 | serge | 481 | if(check_connector(dev, connector) == 0) |
482 | return connector; |
||
483 | } |
||
484 | return NULL; |
||
485 | } |
||
5060 | serge | 486 | |
2338 | Serge | 487 | |
6088 | serge | 488 | static int choose_config(struct drm_device *dev, struct drm_connector **boot_connector, |
489 | struct drm_crtc **boot_crtc) |
||
490 | { |
||
6103 | serge | 491 | struct drm_connector *connector; |
4371 | Serge | 492 | |
6088 | serge | 493 | if((i915.cmdline_mode != NULL) && (*i915.cmdline_mode != 0)) |
494 | { |
||
495 | connector = get_cmdline_connector(dev, i915.cmdline_mode); |
||
496 | if(connector != NULL) |
||
5060 | serge | 497 | { |
498 | *boot_connector = connector; |
||
6088 | serge | 499 | *boot_crtc = connector->encoder->crtc; |
5060 | serge | 500 | return 0; |
501 | } |
||
6088 | serge | 502 | } |
5060 | serge | 503 | |
6088 | serge | 504 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) |
505 | { |
||
506 | if(check_connector(dev, connector) == 0) |
||
507 | { |
||
508 | *boot_connector = connector; |
||
509 | *boot_crtc = connector->encoder->crtc; |
||
510 | return 0; |
||
511 | }; |
||
2338 | Serge | 512 | }; |
513 | |||
5060 | serge | 514 | return -ENOENT; |
4398 | Serge | 515 | }; |
2338 | Serge | 516 | |
6103 | serge | 517 | |
5060 | serge | 518 | static int get_boot_mode(struct drm_connector *connector, videomode_t *usermode) |
4371 | Serge | 519 | { |
520 | struct drm_display_mode *mode; |
||
521 | |||
522 | list_for_each_entry(mode, &connector->modes, head) |
||
523 | { |
||
5060 | serge | 524 | if( os_display->width == mode->hdisplay && |
525 | os_display->height == mode->vdisplay && |
||
4371 | Serge | 526 | drm_mode_vrefresh(mode) == 60) |
527 | { |
||
528 | usermode->width = os_display->width; |
||
529 | usermode->height = os_display->height; |
||
530 | usermode->freq = 60; |
||
531 | return 1; |
||
532 | } |
||
533 | } |
||
534 | return 0; |
||
535 | } |
||
536 | |||
537 | int init_display_kms(struct drm_device *dev, videomode_t *usermode) |
||
538 | { |
||
539 | struct drm_connector_helper_funcs *connector_funcs; |
||
5060 | serge | 540 | struct drm_connector *connector = NULL; |
541 | struct drm_crtc *crtc = NULL; |
||
6283 | serge | 542 | struct drm_plane *plane; |
4371 | Serge | 543 | |
6296 | serge | 544 | int ret; |
4371 | Serge | 545 | |
6283 | serge | 546 | drm_for_each_plane(plane, dev) |
547 | { |
||
548 | drm_plane_helper_disable(plane); |
||
549 | }; |
||
550 | |||
4371 | Serge | 551 | mutex_lock(&dev->mode_config.mutex); |
5060 | serge | 552 | ret = choose_config(dev, &connector, &crtc); |
553 | if(ret) |
||
4371 | Serge | 554 | { |
6088 | serge | 555 | mutex_unlock(&dev->mode_config.mutex); |
4371 | Serge | 556 | DRM_DEBUG_KMS("No active connectors!\n"); |
557 | return -1; |
||
558 | }; |
||
559 | |||
2338 | Serge | 560 | os_display = GetDisplay(); |
561 | os_display->ddev = dev; |
||
562 | os_display->connector = connector; |
||
563 | os_display->crtc = crtc; |
||
564 | os_display->supported_modes = count_connector_modes(connector); |
||
6088 | serge | 565 | mutex_unlock(&dev->mode_config.mutex); |
2338 | Serge | 566 | |
6283 | serge | 567 | init_system_cursors(dev); |
6088 | serge | 568 | |
569 | ret = -1; |
||
570 | |||
571 | if(connector->cmdline_mode.specified == true) |
||
572 | ret = set_cmdline_mode(dev, connector); |
||
573 | |||
574 | if(ret !=0) |
||
4280 | Serge | 575 | { |
6088 | serge | 576 | mutex_lock(&dev->mode_config.mutex); |
577 | |||
578 | if( (usermode->width == 0) || |
||
579 | (usermode->height == 0)) |
||
4371 | Serge | 580 | { |
6088 | serge | 581 | if( !get_boot_mode(connector, usermode)) |
582 | { |
||
583 | struct drm_display_mode *mode; |
||
4280 | Serge | 584 | |
6088 | serge | 585 | mode = list_entry(connector->modes.next, typeof(*mode), head); |
586 | usermode->width = mode->hdisplay; |
||
587 | usermode->height = mode->vdisplay; |
||
588 | usermode->freq = drm_mode_vrefresh(mode); |
||
589 | }; |
||
4280 | Serge | 590 | }; |
6088 | serge | 591 | mutex_unlock(&dev->mode_config.mutex); |
592 | |||
593 | set_mode(dev, os_display->connector, os_display->crtc, usermode, false); |
||
4280 | Serge | 594 | }; |
595 | |||
6088 | serge | 596 | return ret; |
2338 | Serge | 597 | }; |
598 | |||
599 | |||
6088 | serge | 600 | int set_cmdline_mode_ext(struct drm_device *dev, const char *cmdline) |
601 | { |
||
602 | struct drm_connector_helper_funcs *connector_funcs; |
||
603 | struct drm_connector *connector; |
||
6103 | serge | 604 | struct drm_cmdline_mode cmd_mode = {0}; |
6088 | serge | 605 | struct drm_display_mode *mode; |
606 | char *mode_option; |
||
607 | int retval = 0; |
||
608 | char con_edid[128]; |
||
609 | |||
610 | if((cmdline == NULL) || (*cmdline == 0)) |
||
611 | return EINVAL; |
||
612 | |||
613 | mutex_lock(&dev->mode_config.mutex); |
||
614 | connector = get_cmdline_connector(dev, cmdline); |
||
615 | mutex_unlock(&dev->mode_config.mutex); |
||
616 | |||
617 | if(connector == NULL) |
||
618 | return EINVAL; |
||
619 | |||
620 | mode_option = __builtin_strchr(cmdline,':'); |
||
621 | if(mode_option == NULL) |
||
622 | return EINVAL; |
||
623 | |||
624 | mode_option++; |
||
625 | |||
626 | if( !drm_mode_parse_command_line_for_connector(mode_option, connector, &cmd_mode)) |
||
627 | return EINVAL; |
||
628 | |||
629 | DRM_DEBUG_KMS("cmdline mode for connector %s %dx%d@%dHz%s%s%s\n", |
||
630 | connector->name, |
||
631 | cmd_mode.xres, cmd_mode.yres, |
||
632 | cmd_mode.refresh_specified ? cmd_mode.refresh : 60, |
||
633 | cmd_mode.rb ? " reduced blanking" : "", |
||
634 | cmd_mode.margins ? " with margins" : "", |
||
635 | cmd_mode.interlace ? " interlaced" : ""); |
||
636 | |||
637 | mode = drm_mode_create_from_cmdline_mode(dev, &cmd_mode); |
||
638 | if(mode == NULL) |
||
639 | return EINVAL; |
||
640 | |||
641 | memcpy(con_edid, connector->edid_blob_ptr->data, 128); |
||
642 | DRM_DEBUG_KMS("connector: %s monitor: %s model %x serial number %u\n", |
||
643 | connector->name, |
||
644 | manufacturer_name(con_edid + 0x08), |
||
645 | (unsigned short)(con_edid[0x0A] + (con_edid[0x0B] << 8)), |
||
646 | (unsigned int)(con_edid[0x0C] + (con_edid[0x0D] << 8) |
||
647 | + (con_edid[0x0E] << 16) + (con_edid[0x0F] << 24))); |
||
648 | |||
649 | retval = set_mode_ex(dev, connector, mode); |
||
650 | |||
651 | drm_mode_destroy(dev, mode); |
||
652 | |||
653 | return retval; |
||
654 | } |
||
655 | |||
6103 | serge | 656 | void list_connectors(struct drm_device *dev) |
657 | { |
||
658 | struct drm_connector *connector; |
||
659 | char con_edid[128]; |
||
660 | |||
661 | mutex_lock(&dev->mode_config.mutex); |
||
662 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) |
||
663 | { |
||
664 | if( connector->status != connector_status_connected) |
||
665 | continue; |
||
666 | |||
667 | memcpy(con_edid, connector->edid_blob_ptr->data, 128); |
||
668 | |||
669 | if(connector == os_display->connector) |
||
670 | { |
||
671 | printf("%s mode %dx%d connected %s model %x serial number %u\n", |
||
672 | connector->name, os_display->width, os_display->height, |
||
673 | manufacturer_name(con_edid + 0x08), |
||
674 | (unsigned short)(con_edid[0x0A] + (con_edid[0x0B] << 8)), |
||
675 | (unsigned int)(con_edid[0x0C] + (con_edid[0x0D] << 8) |
||
676 | + (con_edid[0x0E] << 16) + (con_edid[0x0F] << 24))); |
||
677 | continue; |
||
678 | } |
||
679 | else |
||
680 | { |
||
681 | printf("%s connected: %s model %x serial number %u\n", |
||
682 | connector->name, manufacturer_name(con_edid + 0x08), |
||
683 | (unsigned short)(con_edid[0x0A] + (con_edid[0x0B] << 8)), |
||
684 | (unsigned int)(con_edid[0x0C] + (con_edid[0x0D] << 8) |
||
685 | + (con_edid[0x0E] << 16) + (con_edid[0x0F] << 24))); |
||
686 | } |
||
687 | }; |
||
688 | mutex_unlock(&dev->mode_config.mutex); |
||
689 | } |
||
690 | |||
691 | int list_connector_modes(struct drm_device *dev, const char* name) |
||
692 | { |
||
693 | struct drm_connector *connector; |
||
694 | struct drm_display_mode *drmmode; |
||
695 | |||
696 | mutex_lock(&dev->mode_config.mutex); |
||
697 | |||
698 | connector = get_cmdline_connector(dev, name); |
||
699 | if(connector == NULL) |
||
700 | { |
||
701 | mutex_unlock(&dev->mode_config.mutex); |
||
702 | return EINVAL; |
||
703 | }; |
||
704 | |||
705 | printf("connector %s probed modes :\n", connector->name); |
||
706 | |||
707 | list_for_each_entry(drmmode, &connector->modes, head) |
||
708 | { |
||
709 | printf("%dx%d@%d\n", drmmode->hdisplay, drmmode->vdisplay, drm_mode_vrefresh(drmmode)); |
||
710 | }; |
||
711 | |||
712 | mutex_unlock(&dev->mode_config.mutex); |
||
713 | return 0; |
||
714 | }; |
||
715 | |||
2338 | Serge | 716 | int get_videomodes(videomode_t *mode, int *count) |
717 | { |
||
718 | int err = -1; |
||
719 | |||
3031 | serge | 720 | // dbgprintf("mode %x count %d\n", mode, *count); |
2338 | Serge | 721 | |
722 | if( *count == 0 ) |
||
723 | { |
||
724 | *count = os_display->supported_modes; |
||
725 | err = 0; |
||
726 | } |
||
727 | else if( mode != NULL ) |
||
728 | { |
||
729 | struct drm_display_mode *drmmode; |
||
730 | int i = 0; |
||
731 | |||
732 | if( *count > os_display->supported_modes) |
||
733 | *count = os_display->supported_modes; |
||
734 | |||
735 | list_for_each_entry(drmmode, &os_display->connector->modes, head) |
||
736 | { |
||
737 | if( i < *count) |
||
738 | { |
||
5060 | serge | 739 | mode->width = drmmode->hdisplay; |
740 | mode->height = drmmode->vdisplay; |
||
2338 | Serge | 741 | mode->bpp = 32; |
742 | mode->freq = drm_mode_vrefresh(drmmode); |
||
743 | i++; |
||
744 | mode++; |
||
745 | } |
||
746 | else break; |
||
747 | }; |
||
748 | *count = i; |
||
749 | err = 0; |
||
750 | }; |
||
751 | return err; |
||
752 | }; |
||
753 | |||
754 | int set_user_mode(videomode_t *mode) |
||
755 | { |
||
756 | |||
3031 | serge | 757 | // dbgprintf("width %d height %d vrefresh %d\n", |
758 | // mode->width, mode->height, mode->freq); |
||
2338 | Serge | 759 | |
760 | if( (mode->width != 0) && |
||
761 | (mode->height != 0) && |
||
762 | (mode->freq != 0 ) && |
||
763 | ( (mode->width != os_display->width) || |
||
764 | (mode->height != os_display->height) || |
||
765 | (mode->freq != os_display->vrefresh) ) ) |
||
766 | { |
||
5060 | serge | 767 | return set_mode(os_display->ddev, os_display->connector, os_display->crtc, mode, true); |
2338 | Serge | 768 | }; |
769 | |||
5060 | serge | 770 | return -1; |
2338 | Serge | 771 | }; |
772 | |||
4126 | Serge | 773 | void i915_dpms(struct drm_device *dev, int mode) |
774 | { |
||
4371 | Serge | 775 | const struct drm_connector_funcs *f = os_display->connector->funcs; |
4126 | Serge | 776 | |
777 | f->dpms(os_display->connector, mode); |
||
778 | }; |
||
779 | |||
6283 | serge | 780 | |
781 | int i915_fbinfo(struct drm_i915_fb_info *fb) |
||
2338 | Serge | 782 | { |
6283 | serge | 783 | u32 ifl; |
2342 | Serge | 784 | |
6283 | serge | 785 | ifl = safe_cli(); |
786 | { |
||
787 | struct drm_i915_private *dev_priv = os_display->ddev->dev_private; |
||
788 | struct intel_crtc *crtc = to_intel_crtc(os_display->crtc); |
||
789 | struct kos_framebuffer *kfb = os_display->current_lfb; |
||
790 | struct intel_framebuffer *intel_fb = (struct intel_framebuffer*)kfb->private; |
||
791 | struct drm_i915_gem_object *obj = intel_fb->obj; |
||
3037 | serge | 792 | |
6283 | serge | 793 | fb->name = obj->base.name; |
794 | fb->width = os_display->width; |
||
795 | fb->height = os_display->height; |
||
6320 | serge | 796 | fb->pitch = os_display->lfb_pitch; |
6283 | serge | 797 | fb->tiling = obj->tiling_mode; |
798 | fb->crtc = crtc->base.base.id; |
||
799 | fb->pipe = crtc->pipe; |
||
800 | } |
||
801 | safe_sti(ifl); |
||
6296 | serge | 802 | |
6283 | serge | 803 | return 0; |
804 | } |
||
3037 | serge | 805 | |
6296 | serge | 806 | |
3277 | Serge | 807 | typedef struct |
808 | { |
||
809 | int left; |
||
810 | int top; |
||
811 | int right; |
||
812 | int bottom; |
||
813 | }rect_t; |
||
3263 | Serge | 814 | |
3277 | Serge | 815 | |
816 | #define CURRENT_TASK (0x80003000) |
||
817 | |||
818 | void FASTCALL GetWindowRect(rect_t *rc)__asm__("GetWindowRect"); |
||
819 | |||
820 | int i915_mask_update(struct drm_device *dev, void *data, |
||
821 | struct drm_file *file) |
||
822 | { |
||
823 | struct drm_i915_mask *mask = data; |
||
824 | struct drm_gem_object *obj; |
||
825 | static unsigned int mask_seqno[256]; |
||
826 | rect_t winrc; |
||
827 | u32 slot; |
||
4371 | Serge | 828 | int ret=0; |
3277 | Serge | 829 | |
830 | obj = drm_gem_object_lookup(dev, file, mask->handle); |
||
831 | if (obj == NULL) |
||
832 | return -ENOENT; |
||
833 | |||
834 | if (!obj->filp) { |
||
835 | drm_gem_object_unreference_unlocked(obj); |
||
836 | return -EINVAL; |
||
837 | } |
||
838 | |||
839 | GetWindowRect(&winrc); |
||
840 | { |
||
3298 | Serge | 841 | // static warn_count; |
3277 | Serge | 842 | |
3290 | Serge | 843 | mask->width = winrc.right - winrc.left + 1; |
844 | mask->height = winrc.bottom - winrc.top + 1; |
||
845 | mask->bo_pitch = (mask->width+15) & ~15; |
||
846 | |||
3298 | Serge | 847 | #if 0 |
3277 | Serge | 848 | if(warn_count < 1) |
849 | { |
||
850 | printf("left %d top %d right %d bottom %d\n", |
||
851 | winrc.left, winrc.top, winrc.right, winrc.bottom); |
||
5060 | serge | 852 | printf("mask pitch %d data %p\n", mask->bo_pitch, mask->bo_map); |
3277 | Serge | 853 | warn_count++; |
854 | }; |
||
3298 | Serge | 855 | #endif |
856 | |||
4104 | Serge | 857 | }; |
3277 | Serge | 858 | |
3290 | Serge | 859 | |
3277 | Serge | 860 | slot = *((u8*)CURRENT_TASK); |
861 | |||
862 | if( mask_seqno[slot] != os_display->mask_seqno) |
||
863 | { |
||
864 | u8* src_offset; |
||
865 | u8* dst_offset; |
||
866 | u32 ifl; |
||
867 | |||
868 | ret = i915_mutex_lock_interruptible(dev); |
||
869 | if (ret) |
||
4371 | Serge | 870 | goto err1; |
3277 | Serge | 871 | |
872 | ret = i915_gem_object_set_to_cpu_domain(to_intel_bo(obj), true); |
||
4398 | Serge | 873 | if(ret != 0 ) |
3277 | Serge | 874 | { |
4371 | Serge | 875 | dbgprintf("%s: i915_gem_object_set_to_cpu_domain failed\n", __FUNCTION__); |
876 | goto err2; |
||
3277 | Serge | 877 | }; |
878 | |||
879 | // printf("width %d height %d\n", winrc.right, winrc.bottom); |
||
880 | |||
881 | // slot = 0x01; |
||
882 | |||
5354 | serge | 883 | src_offset = os_display->win_map; |
884 | src_offset+= winrc.top*os_display->width + winrc.left; |
||
3277 | Serge | 885 | |
886 | dst_offset = (u8*)mask->bo_map; |
||
887 | |||
5354 | serge | 888 | u32 tmp_h = mask->height; |
3277 | Serge | 889 | |
890 | ifl = safe_cli(); |
||
891 | { |
||
892 | mask_seqno[slot] = os_display->mask_seqno; |
||
893 | |||
894 | slot|= (slot<<8)|(slot<<16)|(slot<<24); |
||
895 | |||
896 | __asm__ __volatile__ ( |
||
4560 | Serge | 897 | "movd %[slot], %%xmm6 \n" |
3277 | Serge | 898 | "punpckldq %%xmm6, %%xmm6 \n" |
899 | "punpcklqdq %%xmm6, %%xmm6 \n" |
||
900 | :: [slot] "m" (slot) |
||
901 | :"xmm6"); |
||
902 | |||
903 | while( tmp_h--) |
||
904 | { |
||
4398 | Serge | 905 | int tmp_w = mask->width; |
3277 | Serge | 906 | |
907 | u8* tmp_src = src_offset; |
||
908 | u8* tmp_dst = dst_offset; |
||
909 | |||
910 | src_offset+= os_display->width; |
||
911 | dst_offset+= mask->bo_pitch; |
||
912 | |||
913 | while(tmp_w >= 64) |
||
914 | { |
||
915 | __asm__ __volatile__ ( |
||
916 | "movdqu (%0), %%xmm0 \n" |
||
917 | "movdqu 16(%0), %%xmm1 \n" |
||
918 | "movdqu 32(%0), %%xmm2 \n" |
||
919 | "movdqu 48(%0), %%xmm3 \n" |
||
920 | "pcmpeqb %%xmm6, %%xmm0 \n" |
||
921 | "pcmpeqb %%xmm6, %%xmm1 \n" |
||
922 | "pcmpeqb %%xmm6, %%xmm2 \n" |
||
923 | "pcmpeqb %%xmm6, %%xmm3 \n" |
||
924 | "movdqa %%xmm0, (%%edi) \n" |
||
925 | "movdqa %%xmm1, 16(%%edi) \n" |
||
926 | "movdqa %%xmm2, 32(%%edi) \n" |
||
927 | "movdqa %%xmm3, 48(%%edi) \n" |
||
928 | |||
929 | :: "r" (tmp_src), "D" (tmp_dst) |
||
930 | :"xmm0","xmm1","xmm2","xmm3"); |
||
931 | tmp_w -= 64; |
||
932 | tmp_src += 64; |
||
933 | tmp_dst += 64; |
||
934 | } |
||
935 | |||
936 | if( tmp_w >= 32 ) |
||
937 | { |
||
938 | __asm__ __volatile__ ( |
||
939 | "movdqu (%0), %%xmm0 \n" |
||
940 | "movdqu 16(%0), %%xmm1 \n" |
||
941 | "pcmpeqb %%xmm6, %%xmm0 \n" |
||
942 | "pcmpeqb %%xmm6, %%xmm1 \n" |
||
943 | "movdqa %%xmm0, (%%edi) \n" |
||
944 | "movdqa %%xmm1, 16(%%edi) \n" |
||
945 | |||
946 | :: "r" (tmp_src), "D" (tmp_dst) |
||
947 | :"xmm0","xmm1"); |
||
948 | tmp_w -= 32; |
||
949 | tmp_src += 32; |
||
950 | tmp_dst += 32; |
||
951 | } |
||
952 | |||
4398 | Serge | 953 | if( tmp_w >= 16 ) |
3277 | Serge | 954 | { |
955 | __asm__ __volatile__ ( |
||
956 | "movdqu (%0), %%xmm0 \n" |
||
957 | "pcmpeqb %%xmm6, %%xmm0 \n" |
||
958 | "movdqa %%xmm0, (%%edi) \n" |
||
959 | :: "r" (tmp_src), "D" (tmp_dst) |
||
960 | :"xmm0"); |
||
961 | tmp_w -= 16; |
||
962 | tmp_src += 16; |
||
963 | tmp_dst += 16; |
||
964 | } |
||
4398 | Serge | 965 | |
966 | if( tmp_w >= 8 ) |
||
967 | { |
||
968 | __asm__ __volatile__ ( |
||
969 | "movq (%0), %%xmm0 \n" |
||
970 | "pcmpeqb %%xmm6, %%xmm0 \n" |
||
971 | "movq %%xmm0, (%%edi) \n" |
||
972 | :: "r" (tmp_src), "D" (tmp_dst) |
||
973 | :"xmm0"); |
||
974 | tmp_w -= 8; |
||
975 | tmp_src += 8; |
||
976 | tmp_dst += 8; |
||
977 | } |
||
978 | if( tmp_w >= 4 ) |
||
979 | { |
||
980 | __asm__ __volatile__ ( |
||
981 | "movd (%0), %%xmm0 \n" |
||
982 | "pcmpeqb %%xmm6, %%xmm0 \n" |
||
983 | "movd %%xmm0, (%%edi) \n" |
||
984 | :: "r" (tmp_src), "D" (tmp_dst) |
||
985 | :"xmm0"); |
||
986 | tmp_w -= 4; |
||
987 | tmp_src += 4; |
||
988 | tmp_dst += 4; |
||
989 | } |
||
990 | while(tmp_w--) |
||
991 | *tmp_dst++ = (*tmp_src++ == (u8)slot) ? 0xFF:0x00; |
||
3277 | Serge | 992 | }; |
993 | }; |
||
994 | safe_sti(ifl); |
||
4371 | Serge | 995 | |
996 | ret = i915_gem_object_set_to_gtt_domain(to_intel_bo(obj), false); |
||
4539 | Serge | 997 | } |
998 | |||
999 | err2: |
||
1000 | mutex_unlock(&dev->struct_mutex); |
||
1001 | err1: |
||
1002 | drm_gem_object_unreference(obj); |
||
1003 | |||
1004 | return ret; |
||
1005 | } |
||
1006 | |||
1007 | int i915_mask_update_ex(struct drm_device *dev, void *data, |
||
1008 | struct drm_file *file) |
||
1009 | { |
||
1010 | struct drm_i915_mask_update *mask = data; |
||
1011 | struct drm_gem_object *obj; |
||
1012 | static unsigned int mask_seqno[256]; |
||
6660 | serge | 1013 | static int warn_count; |
4539 | Serge | 1014 | |
1015 | rect_t win; |
||
1016 | u32 winw,winh; |
||
1017 | u32 ml,mt,mr,mb; |
||
1018 | u32 slot; |
||
1019 | int ret = 0; |
||
1020 | slot = *((u8*)CURRENT_TASK); |
||
1021 | |||
6084 | serge | 1022 | if( mask->forced == 0 && mask_seqno[slot] == os_display->mask_seqno) |
4539 | Serge | 1023 | return 0; |
1024 | |||
6084 | serge | 1025 | if(mask->forced) |
1026 | memset((void*)mask->bo_map,0,mask->width * mask->height); |
||
5367 | serge | 1027 | |
4539 | Serge | 1028 | GetWindowRect(&win); |
1029 | win.right+= 1; |
||
1030 | win.bottom+= 1; |
||
1031 | |||
1032 | winw = win.right - win.left; |
||
1033 | winh = win.bottom - win.top; |
||
1034 | |||
1035 | if(mask->dx >= winw || |
||
1036 | mask->dy >= winh) |
||
1037 | return 1; |
||
1038 | |||
1039 | ml = win.left + mask->dx; |
||
1040 | mt = win.top + mask->dy; |
||
1041 | mr = ml + mask->width; |
||
1042 | mb = mt + mask->height; |
||
1043 | |||
1044 | if( ml >= win.right || mt >= win.bottom || |
||
1045 | mr < win.left || mb < win.top ) |
||
1046 | return 1; |
||
1047 | |||
1048 | if( mr > win.right ) |
||
1049 | mr = win.right; |
||
1050 | |||
1051 | if( mb > win.bottom ) |
||
1052 | mb = win.bottom; |
||
1053 | |||
1054 | mask->width = mr - ml; |
||
1055 | mask->height = mb - mt; |
||
1056 | |||
1057 | if( mask->width == 0 || |
||
1058 | mask->height== 0 ) |
||
1059 | return 1; |
||
1060 | |||
6131 | serge | 1061 | ret = i915_mutex_lock_interruptible(dev); |
1062 | if (ret) |
||
1063 | return ret; |
||
1064 | |||
4539 | Serge | 1065 | obj = drm_gem_object_lookup(dev, file, mask->handle); |
1066 | if (obj == NULL) |
||
6131 | serge | 1067 | { |
1068 | ret = -ENOENT; |
||
1069 | goto unlock; |
||
1070 | } |
||
4539 | Serge | 1071 | |
6131 | serge | 1072 | if (!obj->filp) |
1073 | { |
||
1074 | ret = -ENOENT; |
||
1075 | goto out; |
||
4539 | Serge | 1076 | } |
1077 | |||
6084 | serge | 1078 | #if 0 |
1079 | if(warn_count < 100) |
||
4539 | Serge | 1080 | { |
1081 | printf("left %d top %d right %d bottom %d\n", |
||
1082 | ml, mt, mr, mb); |
||
1083 | warn_count++; |
||
1084 | }; |
||
1085 | #endif |
||
1086 | |||
1087 | |||
1088 | #if 1 |
||
1089 | |||
1090 | { |
||
1091 | u8* src_offset; |
||
1092 | u8* dst_offset; |
||
1093 | u32 ifl; |
||
1094 | |||
1095 | i915_gem_object_set_to_cpu_domain(to_intel_bo(obj), true); |
||
1096 | |||
5354 | serge | 1097 | src_offset = os_display->win_map; |
1098 | src_offset+= mt*os_display->width + ml; |
||
4539 | Serge | 1099 | dst_offset = (u8*)mask->bo_map; |
1100 | |||
5354 | serge | 1101 | u32 tmp_h = mask->height; |
4539 | Serge | 1102 | |
1103 | ifl = safe_cli(); |
||
4371 | Serge | 1104 | { |
4539 | Serge | 1105 | mask_seqno[slot] = os_display->mask_seqno; |
1106 | |||
1107 | slot|= (slot<<8)|(slot<<16)|(slot<<24); |
||
1108 | |||
1109 | __asm__ __volatile__ ( |
||
1110 | "movd %[slot], %%xmm6 \n" |
||
1111 | "punpckldq %%xmm6, %%xmm6 \n" |
||
1112 | "punpcklqdq %%xmm6, %%xmm6 \n" |
||
1113 | :: [slot] "m" (slot) |
||
1114 | :"xmm6"); |
||
1115 | |||
1116 | while( tmp_h--) |
||
1117 | { |
||
1118 | int tmp_w = mask->width; |
||
1119 | |||
1120 | u8* tmp_src = src_offset; |
||
1121 | u8* tmp_dst = dst_offset; |
||
1122 | |||
1123 | src_offset+= os_display->width; |
||
1124 | dst_offset+= mask->bo_pitch; |
||
1125 | |||
1126 | while(tmp_w >= 64) |
||
1127 | { |
||
1128 | __asm__ __volatile__ ( |
||
1129 | "movdqu (%0), %%xmm0 \n" |
||
1130 | "movdqu 16(%0), %%xmm1 \n" |
||
1131 | "movdqu 32(%0), %%xmm2 \n" |
||
1132 | "movdqu 48(%0), %%xmm3 \n" |
||
1133 | "pcmpeqb %%xmm6, %%xmm0 \n" |
||
1134 | "pcmpeqb %%xmm6, %%xmm1 \n" |
||
1135 | "pcmpeqb %%xmm6, %%xmm2 \n" |
||
1136 | "pcmpeqb %%xmm6, %%xmm3 \n" |
||
1137 | "movdqa %%xmm0, (%%edi) \n" |
||
1138 | "movdqa %%xmm1, 16(%%edi) \n" |
||
1139 | "movdqa %%xmm2, 32(%%edi) \n" |
||
1140 | "movdqa %%xmm3, 48(%%edi) \n" |
||
1141 | |||
1142 | :: "r" (tmp_src), "D" (tmp_dst) |
||
1143 | :"xmm0","xmm1","xmm2","xmm3"); |
||
1144 | tmp_w -= 64; |
||
1145 | tmp_src += 64; |
||
1146 | tmp_dst += 64; |
||
1147 | } |
||
1148 | |||
1149 | if( tmp_w >= 32 ) |
||
1150 | { |
||
1151 | __asm__ __volatile__ ( |
||
1152 | "movdqu (%0), %%xmm0 \n" |
||
1153 | "movdqu 16(%0), %%xmm1 \n" |
||
1154 | "pcmpeqb %%xmm6, %%xmm0 \n" |
||
1155 | "pcmpeqb %%xmm6, %%xmm1 \n" |
||
1156 | "movdqa %%xmm0, (%%edi) \n" |
||
1157 | "movdqa %%xmm1, 16(%%edi) \n" |
||
1158 | |||
1159 | :: "r" (tmp_src), "D" (tmp_dst) |
||
1160 | :"xmm0","xmm1"); |
||
1161 | tmp_w -= 32; |
||
1162 | tmp_src += 32; |
||
1163 | tmp_dst += 32; |
||
1164 | } |
||
1165 | |||
1166 | if( tmp_w >= 16 ) |
||
1167 | { |
||
1168 | __asm__ __volatile__ ( |
||
1169 | "movdqu (%0), %%xmm0 \n" |
||
1170 | "pcmpeqb %%xmm6, %%xmm0 \n" |
||
1171 | "movdqa %%xmm0, (%%edi) \n" |
||
1172 | :: "r" (tmp_src), "D" (tmp_dst) |
||
1173 | :"xmm0"); |
||
1174 | tmp_w -= 16; |
||
1175 | tmp_src += 16; |
||
1176 | tmp_dst += 16; |
||
1177 | } |
||
1178 | |||
1179 | if( tmp_w >= 8 ) |
||
1180 | { |
||
1181 | __asm__ __volatile__ ( |
||
1182 | "movq (%0), %%xmm0 \n" |
||
1183 | "pcmpeqb %%xmm6, %%xmm0 \n" |
||
1184 | "movq %%xmm0, (%%edi) \n" |
||
1185 | :: "r" (tmp_src), "D" (tmp_dst) |
||
1186 | :"xmm0"); |
||
1187 | tmp_w -= 8; |
||
1188 | tmp_src += 8; |
||
1189 | tmp_dst += 8; |
||
1190 | } |
||
1191 | if( tmp_w >= 4 ) |
||
4560 | Serge | 1192 | { |
4539 | Serge | 1193 | __asm__ __volatile__ ( |
1194 | "movd (%0), %%xmm0 \n" |
||
1195 | "pcmpeqb %%xmm6, %%xmm0 \n" |
||
1196 | "movd %%xmm0, (%%edi) \n" |
||
1197 | :: "r" (tmp_src), "D" (tmp_dst) |
||
1198 | :"xmm0"); |
||
1199 | tmp_w -= 4; |
||
1200 | tmp_src += 4; |
||
1201 | tmp_dst += 4; |
||
1202 | } |
||
1203 | while(tmp_w--) |
||
1204 | *tmp_dst++ = (*tmp_src++ == (u8)slot) ? 0xFF:0x00; |
||
1205 | }; |
||
4371 | Serge | 1206 | }; |
4539 | Serge | 1207 | safe_sti(ifl); |
1208 | |||
1209 | i915_gem_object_set_to_gtt_domain(to_intel_bo(obj), false); |
||
3277 | Serge | 1210 | } |
4539 | Serge | 1211 | #endif |
3277 | Serge | 1212 | |
6131 | serge | 1213 | out: |
3277 | Serge | 1214 | drm_gem_object_unreference(obj); |
1215 | |||
6131 | serge | 1216 | unlock: |
1217 | mutex_unlock(&dev->struct_mutex); |
||
1218 | |||
4371 | Serge | 1219 | return ret; |
3277 | Serge | 1220 | } |
1221 | |||
1222 | |||
1223 | |||
2360 | Serge | 1224 | |
3031 | serge | 1225 | #define NSEC_PER_SEC 1000000000L |
2360 | Serge | 1226 | |
3031 | serge | 1227 | void getrawmonotonic(struct timespec *ts) |
1228 | { |
||
1229 | u32 tmp = GetTimerTicks(); |
||
2360 | Serge | 1230 | |
3031 | serge | 1231 | ts->tv_sec = tmp/100; |
1232 | ts->tv_nsec = (tmp - ts->tv_sec*100)*10000000; |
||
1233 | } |
||
2360 | Serge | 1234 | |
6084 | serge | 1235 | void prepare_to_wait(wait_queue_head_t *q, wait_queue_t *wait, int state) |
3031 | serge | 1236 | { |
3480 | Serge | 1237 | unsigned long flags; |
3031 | serge | 1238 | |
3480 | Serge | 1239 | // wait->flags &= ~WQ_FLAG_EXCLUSIVE; |
1240 | spin_lock_irqsave(&q->lock, flags); |
||
1241 | if (list_empty(&wait->task_list)) |
||
1242 | __add_wait_queue(q, wait); |
||
1243 | spin_unlock_irqrestore(&q->lock, flags); |
||
1244 | } |
||
1245 | |||
1246 | /** |
||
1247 | * finish_wait - clean up after waiting in a queue |
||
1248 | * @q: waitqueue waited on |
||
1249 | * @wait: wait descriptor |
||
1250 | * |
||
1251 | * Sets current thread back to running state and removes |
||
1252 | * the wait descriptor from the given waitqueue if still |
||
1253 | * queued. |
||
1254 | */ |
||
1255 | void finish_wait(wait_queue_head_t *q, wait_queue_t *wait) |
||
1256 | { |
||
1257 | unsigned long flags; |
||
1258 | |||
1259 | // __set_current_state(TASK_RUNNING); |
||
1260 | /* |
||
1261 | * We can check for list emptiness outside the lock |
||
1262 | * IFF: |
||
1263 | * - we use the "careful" check that verifies both |
||
1264 | * the next and prev pointers, so that there cannot |
||
1265 | * be any half-pending updates in progress on other |
||
1266 | * CPU's that we haven't seen yet (and that might |
||
1267 | * still change the stack area. |
||
1268 | * and |
||
1269 | * - all other users take the lock (ie we can only |
||
1270 | * have _one_ other CPU that looks at or modifies |
||
1271 | * the list). |
||
1272 | */ |
||
1273 | if (!list_empty_careful(&wait->task_list)) { |
||
1274 | spin_lock_irqsave(&q->lock, flags); |
||
1275 | list_del_init(&wait->task_list); |
||
1276 | spin_unlock_irqrestore(&q->lock, flags); |
||
1277 | } |
||
1278 | |||
1279 | DestroyEvent(wait->evnt); |
||
1280 | } |
||
1281 | |||
1282 | int autoremove_wake_function(wait_queue_t *wait, unsigned mode, int sync, void *key) |
||
1283 | { |
||
1284 | list_del_init(&wait->task_list); |
||
1285 | return 1; |
||
1286 | }24); |