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