diff options
author | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
---|---|---|
committer | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
commit | c71c03bda1e86c9d5198c5d83f712e695c4f2a1e (patch) | |
tree | ecb166cb3e2b7e2adb3b5e292245fefd23381ac8 /drivers/gpu/drm/i915/intel_overlay.c | |
parent | ea53c912f8a86a8567697115b6a0d8152beee5c8 (diff) | |
parent | 6a00f206debf8a5c8899055726ad127dbeeed098 (diff) |
Merge branch 'mpi-master' into wip-k-fmlpwip-k-fmlp
Conflicts:
litmus/sched_cedf.c
Diffstat (limited to 'drivers/gpu/drm/i915/intel_overlay.c')
-rw-r--r-- | drivers/gpu/drm/i915/intel_overlay.c | 1066 |
1 files changed, 583 insertions, 483 deletions
diff --git a/drivers/gpu/drm/i915/intel_overlay.c b/drivers/gpu/drm/i915/intel_overlay.c index 1d306a458be6..9e2959bc91cd 100644 --- a/drivers/gpu/drm/i915/intel_overlay.c +++ b/drivers/gpu/drm/i915/intel_overlay.c | |||
@@ -170,91 +170,180 @@ struct overlay_registers { | |||
170 | u16 RESERVEDG[0x100 / 2 - N_HORIZ_UV_TAPS * N_PHASES]; | 170 | u16 RESERVEDG[0x100 / 2 - N_HORIZ_UV_TAPS * N_PHASES]; |
171 | }; | 171 | }; |
172 | 172 | ||
173 | /* overlay flip addr flag */ | 173 | struct intel_overlay { |
174 | #define OFC_UPDATE 0x1 | 174 | struct drm_device *dev; |
175 | 175 | struct intel_crtc *crtc; | |
176 | #define OVERLAY_NONPHYSICAL(dev) (IS_G33(dev) || IS_I965G(dev)) | 176 | struct drm_i915_gem_object *vid_bo; |
177 | #define OVERLAY_EXISTS(dev) (!IS_G4X(dev) && !IS_IRONLAKE(dev) && !IS_GEN6(dev)) | 177 | struct drm_i915_gem_object *old_vid_bo; |
178 | 178 | int active; | |
179 | int pfit_active; | ||
180 | u32 pfit_vscale_ratio; /* shifted-point number, (1<<12) == 1.0 */ | ||
181 | u32 color_key; | ||
182 | u32 brightness, contrast, saturation; | ||
183 | u32 old_xscale, old_yscale; | ||
184 | /* register access */ | ||
185 | u32 flip_addr; | ||
186 | struct drm_i915_gem_object *reg_bo; | ||
187 | /* flip handling */ | ||
188 | uint32_t last_flip_req; | ||
189 | void (*flip_tail)(struct intel_overlay *); | ||
190 | }; | ||
179 | 191 | ||
180 | static struct overlay_registers *intel_overlay_map_regs_atomic(struct intel_overlay *overlay) | 192 | static struct overlay_registers * |
193 | intel_overlay_map_regs(struct intel_overlay *overlay) | ||
181 | { | 194 | { |
182 | drm_i915_private_t *dev_priv = overlay->dev->dev_private; | 195 | drm_i915_private_t *dev_priv = overlay->dev->dev_private; |
183 | struct overlay_registers *regs; | 196 | struct overlay_registers *regs; |
184 | 197 | ||
185 | /* no recursive mappings */ | 198 | if (OVERLAY_NEEDS_PHYSICAL(overlay->dev)) |
186 | BUG_ON(overlay->virt_addr); | 199 | regs = overlay->reg_bo->phys_obj->handle->vaddr; |
200 | else | ||
201 | regs = io_mapping_map_wc(dev_priv->mm.gtt_mapping, | ||
202 | overlay->reg_bo->gtt_offset); | ||
187 | 203 | ||
188 | if (OVERLAY_NONPHYSICAL(overlay->dev)) { | 204 | return regs; |
189 | regs = io_mapping_map_atomic_wc(dev_priv->mm.gtt_mapping, | 205 | } |
190 | overlay->reg_bo->gtt_offset, | ||
191 | KM_USER0); | ||
192 | 206 | ||
193 | if (!regs) { | 207 | static void intel_overlay_unmap_regs(struct intel_overlay *overlay, |
194 | DRM_ERROR("failed to map overlay regs in GTT\n"); | 208 | struct overlay_registers *regs) |
195 | return NULL; | 209 | { |
196 | } | 210 | if (!OVERLAY_NEEDS_PHYSICAL(overlay->dev)) |
197 | } else | 211 | io_mapping_unmap(regs); |
198 | regs = overlay->reg_bo->phys_obj->handle->vaddr; | 212 | } |
213 | |||
214 | static int intel_overlay_do_wait_request(struct intel_overlay *overlay, | ||
215 | struct drm_i915_gem_request *request, | ||
216 | void (*tail)(struct intel_overlay *)) | ||
217 | { | ||
218 | struct drm_device *dev = overlay->dev; | ||
219 | drm_i915_private_t *dev_priv = dev->dev_private; | ||
220 | int ret; | ||
199 | 221 | ||
200 | return overlay->virt_addr = regs; | 222 | BUG_ON(overlay->last_flip_req); |
223 | ret = i915_add_request(LP_RING(dev_priv), NULL, request); | ||
224 | if (ret) { | ||
225 | kfree(request); | ||
226 | return ret; | ||
227 | } | ||
228 | overlay->last_flip_req = request->seqno; | ||
229 | overlay->flip_tail = tail; | ||
230 | ret = i915_wait_request(LP_RING(dev_priv), overlay->last_flip_req); | ||
231 | if (ret) | ||
232 | return ret; | ||
233 | |||
234 | overlay->last_flip_req = 0; | ||
235 | return 0; | ||
201 | } | 236 | } |
202 | 237 | ||
203 | static void intel_overlay_unmap_regs_atomic(struct intel_overlay *overlay) | 238 | /* Workaround for i830 bug where pipe a must be enable to change control regs */ |
239 | static int | ||
240 | i830_activate_pipe_a(struct drm_device *dev) | ||
204 | { | 241 | { |
205 | if (OVERLAY_NONPHYSICAL(overlay->dev)) | 242 | drm_i915_private_t *dev_priv = dev->dev_private; |
206 | io_mapping_unmap_atomic(overlay->virt_addr, KM_USER0); | 243 | struct intel_crtc *crtc; |
244 | struct drm_crtc_helper_funcs *crtc_funcs; | ||
245 | struct drm_display_mode vesa_640x480 = { | ||
246 | DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 25175, 640, 656, | ||
247 | 752, 800, 0, 480, 489, 492, 525, 0, | ||
248 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) | ||
249 | }, *mode; | ||
250 | |||
251 | crtc = to_intel_crtc(dev_priv->pipe_to_crtc_mapping[0]); | ||
252 | if (crtc->dpms_mode == DRM_MODE_DPMS_ON) | ||
253 | return 0; | ||
207 | 254 | ||
208 | overlay->virt_addr = NULL; | 255 | /* most i8xx have pipe a forced on, so don't trust dpms mode */ |
256 | if (I915_READ(_PIPEACONF) & PIPECONF_ENABLE) | ||
257 | return 0; | ||
209 | 258 | ||
210 | return; | 259 | crtc_funcs = crtc->base.helper_private; |
260 | if (crtc_funcs->dpms == NULL) | ||
261 | return 0; | ||
262 | |||
263 | DRM_DEBUG_DRIVER("Enabling pipe A in order to enable overlay\n"); | ||
264 | |||
265 | mode = drm_mode_duplicate(dev, &vesa_640x480); | ||
266 | drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V); | ||
267 | if(!drm_crtc_helper_set_mode(&crtc->base, mode, | ||
268 | crtc->base.x, crtc->base.y, | ||
269 | crtc->base.fb)) | ||
270 | return 0; | ||
271 | |||
272 | crtc_funcs->dpms(&crtc->base, DRM_MODE_DPMS_ON); | ||
273 | return 1; | ||
274 | } | ||
275 | |||
276 | static void | ||
277 | i830_deactivate_pipe_a(struct drm_device *dev) | ||
278 | { | ||
279 | drm_i915_private_t *dev_priv = dev->dev_private; | ||
280 | struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[0]; | ||
281 | struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; | ||
282 | |||
283 | crtc_funcs->dpms(crtc, DRM_MODE_DPMS_OFF); | ||
211 | } | 284 | } |
212 | 285 | ||
213 | /* overlay needs to be disable in OCMD reg */ | 286 | /* overlay needs to be disable in OCMD reg */ |
214 | static int intel_overlay_on(struct intel_overlay *overlay) | 287 | static int intel_overlay_on(struct intel_overlay *overlay) |
215 | { | 288 | { |
216 | struct drm_device *dev = overlay->dev; | 289 | struct drm_device *dev = overlay->dev; |
290 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
291 | struct drm_i915_gem_request *request; | ||
292 | int pipe_a_quirk = 0; | ||
217 | int ret; | 293 | int ret; |
218 | drm_i915_private_t *dev_priv = dev->dev_private; | ||
219 | 294 | ||
220 | BUG_ON(overlay->active); | 295 | BUG_ON(overlay->active); |
221 | |||
222 | overlay->active = 1; | 296 | overlay->active = 1; |
223 | overlay->hw_wedged = NEEDS_WAIT_FOR_FLIP; | ||
224 | 297 | ||
225 | BEGIN_LP_RING(4); | 298 | if (IS_I830(dev)) { |
299 | pipe_a_quirk = i830_activate_pipe_a(dev); | ||
300 | if (pipe_a_quirk < 0) | ||
301 | return pipe_a_quirk; | ||
302 | } | ||
303 | |||
304 | request = kzalloc(sizeof(*request), GFP_KERNEL); | ||
305 | if (request == NULL) { | ||
306 | ret = -ENOMEM; | ||
307 | goto out; | ||
308 | } | ||
309 | |||
310 | ret = BEGIN_LP_RING(4); | ||
311 | if (ret) { | ||
312 | kfree(request); | ||
313 | goto out; | ||
314 | } | ||
315 | |||
226 | OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_ON); | 316 | OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_ON); |
227 | OUT_RING(overlay->flip_addr | OFC_UPDATE); | 317 | OUT_RING(overlay->flip_addr | OFC_UPDATE); |
228 | OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP); | 318 | OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP); |
229 | OUT_RING(MI_NOOP); | 319 | OUT_RING(MI_NOOP); |
230 | ADVANCE_LP_RING(); | 320 | ADVANCE_LP_RING(); |
231 | 321 | ||
232 | overlay->last_flip_req = | 322 | ret = intel_overlay_do_wait_request(overlay, request, NULL); |
233 | i915_add_request(dev, NULL, 0, &dev_priv->render_ring); | 323 | out: |
234 | if (overlay->last_flip_req == 0) | 324 | if (pipe_a_quirk) |
235 | return -ENOMEM; | 325 | i830_deactivate_pipe_a(dev); |
236 | 326 | ||
237 | ret = i915_do_wait_request(dev, | 327 | return ret; |
238 | overlay->last_flip_req, 1, &dev_priv->render_ring); | ||
239 | if (ret != 0) | ||
240 | return ret; | ||
241 | |||
242 | overlay->hw_wedged = 0; | ||
243 | overlay->last_flip_req = 0; | ||
244 | return 0; | ||
245 | } | 328 | } |
246 | 329 | ||
247 | /* overlay needs to be enabled in OCMD reg */ | 330 | /* overlay needs to be enabled in OCMD reg */ |
248 | static void intel_overlay_continue(struct intel_overlay *overlay, | 331 | static int intel_overlay_continue(struct intel_overlay *overlay, |
249 | bool load_polyphase_filter) | 332 | bool load_polyphase_filter) |
250 | { | 333 | { |
251 | struct drm_device *dev = overlay->dev; | 334 | struct drm_device *dev = overlay->dev; |
252 | drm_i915_private_t *dev_priv = dev->dev_private; | 335 | drm_i915_private_t *dev_priv = dev->dev_private; |
336 | struct drm_i915_gem_request *request; | ||
253 | u32 flip_addr = overlay->flip_addr; | 337 | u32 flip_addr = overlay->flip_addr; |
254 | u32 tmp; | 338 | u32 tmp; |
339 | int ret; | ||
255 | 340 | ||
256 | BUG_ON(!overlay->active); | 341 | BUG_ON(!overlay->active); |
257 | 342 | ||
343 | request = kzalloc(sizeof(*request), GFP_KERNEL); | ||
344 | if (request == NULL) | ||
345 | return -ENOMEM; | ||
346 | |||
258 | if (load_polyphase_filter) | 347 | if (load_polyphase_filter) |
259 | flip_addr |= OFC_UPDATE; | 348 | flip_addr |= OFC_UPDATE; |
260 | 349 | ||
@@ -263,226 +352,154 @@ static void intel_overlay_continue(struct intel_overlay *overlay, | |||
263 | if (tmp & (1 << 17)) | 352 | if (tmp & (1 << 17)) |
264 | DRM_DEBUG("overlay underrun, DOVSTA: %x\n", tmp); | 353 | DRM_DEBUG("overlay underrun, DOVSTA: %x\n", tmp); |
265 | 354 | ||
266 | BEGIN_LP_RING(2); | 355 | ret = BEGIN_LP_RING(2); |
356 | if (ret) { | ||
357 | kfree(request); | ||
358 | return ret; | ||
359 | } | ||
267 | OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_CONTINUE); | 360 | OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_CONTINUE); |
268 | OUT_RING(flip_addr); | 361 | OUT_RING(flip_addr); |
269 | ADVANCE_LP_RING(); | 362 | ADVANCE_LP_RING(); |
270 | 363 | ||
271 | overlay->last_flip_req = | 364 | ret = i915_add_request(LP_RING(dev_priv), NULL, request); |
272 | i915_add_request(dev, NULL, 0, &dev_priv->render_ring); | 365 | if (ret) { |
366 | kfree(request); | ||
367 | return ret; | ||
368 | } | ||
369 | |||
370 | overlay->last_flip_req = request->seqno; | ||
371 | return 0; | ||
273 | } | 372 | } |
274 | 373 | ||
275 | static int intel_overlay_wait_flip(struct intel_overlay *overlay) | 374 | static void intel_overlay_release_old_vid_tail(struct intel_overlay *overlay) |
276 | { | 375 | { |
277 | struct drm_device *dev = overlay->dev; | 376 | struct drm_i915_gem_object *obj = overlay->old_vid_bo; |
278 | drm_i915_private_t *dev_priv = dev->dev_private; | ||
279 | int ret; | ||
280 | u32 tmp; | ||
281 | |||
282 | if (overlay->last_flip_req != 0) { | ||
283 | ret = i915_do_wait_request(dev, overlay->last_flip_req, | ||
284 | 1, &dev_priv->render_ring); | ||
285 | if (ret == 0) { | ||
286 | overlay->last_flip_req = 0; | ||
287 | |||
288 | tmp = I915_READ(ISR); | ||
289 | 377 | ||
290 | if (!(tmp & I915_OVERLAY_PLANE_FLIP_PENDING_INTERRUPT)) | 378 | i915_gem_object_unpin(obj); |
291 | return 0; | 379 | drm_gem_object_unreference(&obj->base); |
292 | } | ||
293 | } | ||
294 | 380 | ||
295 | /* synchronous slowpath */ | 381 | overlay->old_vid_bo = NULL; |
296 | overlay->hw_wedged = RELEASE_OLD_VID; | 382 | } |
297 | 383 | ||
298 | BEGIN_LP_RING(2); | 384 | static void intel_overlay_off_tail(struct intel_overlay *overlay) |
299 | OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP); | 385 | { |
300 | OUT_RING(MI_NOOP); | 386 | struct drm_i915_gem_object *obj = overlay->vid_bo; |
301 | ADVANCE_LP_RING(); | ||
302 | 387 | ||
303 | overlay->last_flip_req = | 388 | /* never have the overlay hw on without showing a frame */ |
304 | i915_add_request(dev, NULL, 0, &dev_priv->render_ring); | 389 | BUG_ON(!overlay->vid_bo); |
305 | if (overlay->last_flip_req == 0) | ||
306 | return -ENOMEM; | ||
307 | 390 | ||
308 | ret = i915_do_wait_request(dev, overlay->last_flip_req, | 391 | i915_gem_object_unpin(obj); |
309 | 1, &dev_priv->render_ring); | 392 | drm_gem_object_unreference(&obj->base); |
310 | if (ret != 0) | 393 | overlay->vid_bo = NULL; |
311 | return ret; | ||
312 | 394 | ||
313 | overlay->hw_wedged = 0; | 395 | overlay->crtc->overlay = NULL; |
314 | overlay->last_flip_req = 0; | 396 | overlay->crtc = NULL; |
315 | return 0; | 397 | overlay->active = 0; |
316 | } | 398 | } |
317 | 399 | ||
318 | /* overlay needs to be disabled in OCMD reg */ | 400 | /* overlay needs to be disabled in OCMD reg */ |
319 | static int intel_overlay_off(struct intel_overlay *overlay) | 401 | static int intel_overlay_off(struct intel_overlay *overlay) |
320 | { | 402 | { |
321 | u32 flip_addr = overlay->flip_addr; | ||
322 | struct drm_device *dev = overlay->dev; | 403 | struct drm_device *dev = overlay->dev; |
323 | drm_i915_private_t *dev_priv = dev->dev_private; | 404 | struct drm_i915_private *dev_priv = dev->dev_private; |
405 | u32 flip_addr = overlay->flip_addr; | ||
406 | struct drm_i915_gem_request *request; | ||
324 | int ret; | 407 | int ret; |
325 | 408 | ||
326 | BUG_ON(!overlay->active); | 409 | BUG_ON(!overlay->active); |
327 | 410 | ||
411 | request = kzalloc(sizeof(*request), GFP_KERNEL); | ||
412 | if (request == NULL) | ||
413 | return -ENOMEM; | ||
414 | |||
328 | /* According to intel docs the overlay hw may hang (when switching | 415 | /* According to intel docs the overlay hw may hang (when switching |
329 | * off) without loading the filter coeffs. It is however unclear whether | 416 | * off) without loading the filter coeffs. It is however unclear whether |
330 | * this applies to the disabling of the overlay or to the switching off | 417 | * this applies to the disabling of the overlay or to the switching off |
331 | * of the hw. Do it in both cases */ | 418 | * of the hw. Do it in both cases */ |
332 | flip_addr |= OFC_UPDATE; | 419 | flip_addr |= OFC_UPDATE; |
333 | 420 | ||
421 | ret = BEGIN_LP_RING(6); | ||
422 | if (ret) { | ||
423 | kfree(request); | ||
424 | return ret; | ||
425 | } | ||
334 | /* wait for overlay to go idle */ | 426 | /* wait for overlay to go idle */ |
335 | overlay->hw_wedged = SWITCH_OFF_STAGE_1; | ||
336 | |||
337 | BEGIN_LP_RING(4); | ||
338 | OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_CONTINUE); | 427 | OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_CONTINUE); |
339 | OUT_RING(flip_addr); | 428 | OUT_RING(flip_addr); |
340 | OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP); | 429 | OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP); |
341 | OUT_RING(MI_NOOP); | ||
342 | ADVANCE_LP_RING(); | ||
343 | |||
344 | overlay->last_flip_req = | ||
345 | i915_add_request(dev, NULL, 0, &dev_priv->render_ring); | ||
346 | if (overlay->last_flip_req == 0) | ||
347 | return -ENOMEM; | ||
348 | |||
349 | ret = i915_do_wait_request(dev, overlay->last_flip_req, | ||
350 | 1, &dev_priv->render_ring); | ||
351 | if (ret != 0) | ||
352 | return ret; | ||
353 | |||
354 | /* turn overlay off */ | 430 | /* turn overlay off */ |
355 | overlay->hw_wedged = SWITCH_OFF_STAGE_2; | 431 | OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_OFF); |
356 | |||
357 | BEGIN_LP_RING(4); | ||
358 | OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_OFF); | ||
359 | OUT_RING(flip_addr); | 432 | OUT_RING(flip_addr); |
360 | OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP); | 433 | OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP); |
361 | OUT_RING(MI_NOOP); | ||
362 | ADVANCE_LP_RING(); | 434 | ADVANCE_LP_RING(); |
363 | 435 | ||
364 | overlay->last_flip_req = | 436 | return intel_overlay_do_wait_request(overlay, request, |
365 | i915_add_request(dev, NULL, 0, &dev_priv->render_ring); | 437 | intel_overlay_off_tail); |
366 | if (overlay->last_flip_req == 0) | ||
367 | return -ENOMEM; | ||
368 | |||
369 | ret = i915_do_wait_request(dev, overlay->last_flip_req, | ||
370 | 1, &dev_priv->render_ring); | ||
371 | if (ret != 0) | ||
372 | return ret; | ||
373 | |||
374 | overlay->hw_wedged = 0; | ||
375 | overlay->last_flip_req = 0; | ||
376 | return ret; | ||
377 | } | ||
378 | |||
379 | static void intel_overlay_off_tail(struct intel_overlay *overlay) | ||
380 | { | ||
381 | struct drm_gem_object *obj; | ||
382 | |||
383 | /* never have the overlay hw on without showing a frame */ | ||
384 | BUG_ON(!overlay->vid_bo); | ||
385 | obj = &overlay->vid_bo->base; | ||
386 | |||
387 | i915_gem_object_unpin(obj); | ||
388 | drm_gem_object_unreference(obj); | ||
389 | overlay->vid_bo = NULL; | ||
390 | |||
391 | overlay->crtc->overlay = NULL; | ||
392 | overlay->crtc = NULL; | ||
393 | overlay->active = 0; | ||
394 | } | 438 | } |
395 | 439 | ||
396 | /* recover from an interruption due to a signal | 440 | /* recover from an interruption due to a signal |
397 | * We have to be careful not to repeat work forever an make forward progess. */ | 441 | * We have to be careful not to repeat work forever an make forward progess. */ |
398 | int intel_overlay_recover_from_interrupt(struct intel_overlay *overlay, | 442 | static int intel_overlay_recover_from_interrupt(struct intel_overlay *overlay) |
399 | int interruptible) | ||
400 | { | 443 | { |
401 | struct drm_device *dev = overlay->dev; | 444 | struct drm_device *dev = overlay->dev; |
402 | struct drm_gem_object *obj; | ||
403 | drm_i915_private_t *dev_priv = dev->dev_private; | 445 | drm_i915_private_t *dev_priv = dev->dev_private; |
404 | u32 flip_addr; | ||
405 | int ret; | 446 | int ret; |
406 | 447 | ||
407 | if (overlay->hw_wedged == HW_WEDGED) | 448 | if (overlay->last_flip_req == 0) |
408 | return -EIO; | 449 | return 0; |
409 | |||
410 | if (overlay->last_flip_req == 0) { | ||
411 | overlay->last_flip_req = | ||
412 | i915_add_request(dev, NULL, 0, &dev_priv->render_ring); | ||
413 | if (overlay->last_flip_req == 0) | ||
414 | return -ENOMEM; | ||
415 | } | ||
416 | 450 | ||
417 | ret = i915_do_wait_request(dev, overlay->last_flip_req, | 451 | ret = i915_wait_request(LP_RING(dev_priv), overlay->last_flip_req); |
418 | interruptible, &dev_priv->render_ring); | 452 | if (ret) |
419 | if (ret != 0) | ||
420 | return ret; | 453 | return ret; |
421 | 454 | ||
422 | switch (overlay->hw_wedged) { | 455 | if (overlay->flip_tail) |
423 | case RELEASE_OLD_VID: | 456 | overlay->flip_tail(overlay); |
424 | obj = &overlay->old_vid_bo->base; | ||
425 | i915_gem_object_unpin(obj); | ||
426 | drm_gem_object_unreference(obj); | ||
427 | overlay->old_vid_bo = NULL; | ||
428 | break; | ||
429 | case SWITCH_OFF_STAGE_1: | ||
430 | flip_addr = overlay->flip_addr; | ||
431 | flip_addr |= OFC_UPDATE; | ||
432 | |||
433 | overlay->hw_wedged = SWITCH_OFF_STAGE_2; | ||
434 | |||
435 | BEGIN_LP_RING(4); | ||
436 | OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_OFF); | ||
437 | OUT_RING(flip_addr); | ||
438 | OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP); | ||
439 | OUT_RING(MI_NOOP); | ||
440 | ADVANCE_LP_RING(); | ||
441 | |||
442 | overlay->last_flip_req = i915_add_request(dev, NULL, | ||
443 | 0, &dev_priv->render_ring); | ||
444 | if (overlay->last_flip_req == 0) | ||
445 | return -ENOMEM; | ||
446 | |||
447 | ret = i915_do_wait_request(dev, overlay->last_flip_req, | ||
448 | interruptible, &dev_priv->render_ring); | ||
449 | if (ret != 0) | ||
450 | return ret; | ||
451 | |||
452 | case SWITCH_OFF_STAGE_2: | ||
453 | intel_overlay_off_tail(overlay); | ||
454 | break; | ||
455 | default: | ||
456 | BUG_ON(overlay->hw_wedged != NEEDS_WAIT_FOR_FLIP); | ||
457 | } | ||
458 | 457 | ||
459 | overlay->hw_wedged = 0; | ||
460 | overlay->last_flip_req = 0; | 458 | overlay->last_flip_req = 0; |
461 | return 0; | 459 | return 0; |
462 | } | 460 | } |
463 | 461 | ||
464 | /* Wait for pending overlay flip and release old frame. | 462 | /* Wait for pending overlay flip and release old frame. |
465 | * Needs to be called before the overlay register are changed | 463 | * Needs to be called before the overlay register are changed |
466 | * via intel_overlay_(un)map_regs_atomic */ | 464 | * via intel_overlay_(un)map_regs |
465 | */ | ||
467 | static int intel_overlay_release_old_vid(struct intel_overlay *overlay) | 466 | static int intel_overlay_release_old_vid(struct intel_overlay *overlay) |
468 | { | 467 | { |
468 | struct drm_device *dev = overlay->dev; | ||
469 | drm_i915_private_t *dev_priv = dev->dev_private; | ||
469 | int ret; | 470 | int ret; |
470 | struct drm_gem_object *obj; | ||
471 | 471 | ||
472 | /* only wait if there is actually an old frame to release to | 472 | /* Only wait if there is actually an old frame to release to |
473 | * guarantee forward progress */ | 473 | * guarantee forward progress. |
474 | */ | ||
474 | if (!overlay->old_vid_bo) | 475 | if (!overlay->old_vid_bo) |
475 | return 0; | 476 | return 0; |
476 | 477 | ||
477 | ret = intel_overlay_wait_flip(overlay); | 478 | if (I915_READ(ISR) & I915_OVERLAY_PLANE_FLIP_PENDING_INTERRUPT) { |
478 | if (ret != 0) | 479 | struct drm_i915_gem_request *request; |
479 | return ret; | ||
480 | 480 | ||
481 | obj = &overlay->old_vid_bo->base; | 481 | /* synchronous slowpath */ |
482 | i915_gem_object_unpin(obj); | 482 | request = kzalloc(sizeof(*request), GFP_KERNEL); |
483 | drm_gem_object_unreference(obj); | 483 | if (request == NULL) |
484 | overlay->old_vid_bo = NULL; | 484 | return -ENOMEM; |
485 | |||
486 | ret = BEGIN_LP_RING(2); | ||
487 | if (ret) { | ||
488 | kfree(request); | ||
489 | return ret; | ||
490 | } | ||
491 | |||
492 | OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP); | ||
493 | OUT_RING(MI_NOOP); | ||
494 | ADVANCE_LP_RING(); | ||
495 | |||
496 | ret = intel_overlay_do_wait_request(overlay, request, | ||
497 | intel_overlay_release_old_vid_tail); | ||
498 | if (ret) | ||
499 | return ret; | ||
500 | } | ||
485 | 501 | ||
502 | intel_overlay_release_old_vid_tail(overlay); | ||
486 | return 0; | 503 | return 0; |
487 | } | 504 | } |
488 | 505 | ||
@@ -506,65 +523,65 @@ struct put_image_params { | |||
506 | static int packed_depth_bytes(u32 format) | 523 | static int packed_depth_bytes(u32 format) |
507 | { | 524 | { |
508 | switch (format & I915_OVERLAY_DEPTH_MASK) { | 525 | switch (format & I915_OVERLAY_DEPTH_MASK) { |
509 | case I915_OVERLAY_YUV422: | 526 | case I915_OVERLAY_YUV422: |
510 | return 4; | 527 | return 4; |
511 | case I915_OVERLAY_YUV411: | 528 | case I915_OVERLAY_YUV411: |
512 | /* return 6; not implemented */ | 529 | /* return 6; not implemented */ |
513 | default: | 530 | default: |
514 | return -EINVAL; | 531 | return -EINVAL; |
515 | } | 532 | } |
516 | } | 533 | } |
517 | 534 | ||
518 | static int packed_width_bytes(u32 format, short width) | 535 | static int packed_width_bytes(u32 format, short width) |
519 | { | 536 | { |
520 | switch (format & I915_OVERLAY_DEPTH_MASK) { | 537 | switch (format & I915_OVERLAY_DEPTH_MASK) { |
521 | case I915_OVERLAY_YUV422: | 538 | case I915_OVERLAY_YUV422: |
522 | return width << 1; | 539 | return width << 1; |
523 | default: | 540 | default: |
524 | return -EINVAL; | 541 | return -EINVAL; |
525 | } | 542 | } |
526 | } | 543 | } |
527 | 544 | ||
528 | static int uv_hsubsampling(u32 format) | 545 | static int uv_hsubsampling(u32 format) |
529 | { | 546 | { |
530 | switch (format & I915_OVERLAY_DEPTH_MASK) { | 547 | switch (format & I915_OVERLAY_DEPTH_MASK) { |
531 | case I915_OVERLAY_YUV422: | 548 | case I915_OVERLAY_YUV422: |
532 | case I915_OVERLAY_YUV420: | 549 | case I915_OVERLAY_YUV420: |
533 | return 2; | 550 | return 2; |
534 | case I915_OVERLAY_YUV411: | 551 | case I915_OVERLAY_YUV411: |
535 | case I915_OVERLAY_YUV410: | 552 | case I915_OVERLAY_YUV410: |
536 | return 4; | 553 | return 4; |
537 | default: | 554 | default: |
538 | return -EINVAL; | 555 | return -EINVAL; |
539 | } | 556 | } |
540 | } | 557 | } |
541 | 558 | ||
542 | static int uv_vsubsampling(u32 format) | 559 | static int uv_vsubsampling(u32 format) |
543 | { | 560 | { |
544 | switch (format & I915_OVERLAY_DEPTH_MASK) { | 561 | switch (format & I915_OVERLAY_DEPTH_MASK) { |
545 | case I915_OVERLAY_YUV420: | 562 | case I915_OVERLAY_YUV420: |
546 | case I915_OVERLAY_YUV410: | 563 | case I915_OVERLAY_YUV410: |
547 | return 2; | 564 | return 2; |
548 | case I915_OVERLAY_YUV422: | 565 | case I915_OVERLAY_YUV422: |
549 | case I915_OVERLAY_YUV411: | 566 | case I915_OVERLAY_YUV411: |
550 | return 1; | 567 | return 1; |
551 | default: | 568 | default: |
552 | return -EINVAL; | 569 | return -EINVAL; |
553 | } | 570 | } |
554 | } | 571 | } |
555 | 572 | ||
556 | static u32 calc_swidthsw(struct drm_device *dev, u32 offset, u32 width) | 573 | static u32 calc_swidthsw(struct drm_device *dev, u32 offset, u32 width) |
557 | { | 574 | { |
558 | u32 mask, shift, ret; | 575 | u32 mask, shift, ret; |
559 | if (IS_I9XX(dev)) { | 576 | if (IS_GEN2(dev)) { |
560 | mask = 0x3f; | ||
561 | shift = 6; | ||
562 | } else { | ||
563 | mask = 0x1f; | 577 | mask = 0x1f; |
564 | shift = 5; | 578 | shift = 5; |
579 | } else { | ||
580 | mask = 0x3f; | ||
581 | shift = 6; | ||
565 | } | 582 | } |
566 | ret = ((offset + width + mask) >> shift) - (offset >> shift); | 583 | ret = ((offset + width + mask) >> shift) - (offset >> shift); |
567 | if (IS_I9XX(dev)) | 584 | if (!IS_GEN2(dev)) |
568 | ret <<= 1; | 585 | ret <<= 1; |
569 | ret -=1; | 586 | ret -=1; |
570 | return ret << 2; | 587 | return ret << 2; |
@@ -587,7 +604,9 @@ static const u16 y_static_hcoeffs[N_HORIZ_Y_TAPS * N_PHASES] = { | |||
587 | 0x3020, 0xb340, 0x1fb8, 0x34a0, 0xb060, | 604 | 0x3020, 0xb340, 0x1fb8, 0x34a0, 0xb060, |
588 | 0x3020, 0xb240, 0x1fe0, 0x32e0, 0xb040, | 605 | 0x3020, 0xb240, 0x1fe0, 0x32e0, 0xb040, |
589 | 0x3020, 0xb140, 0x1ff8, 0x3160, 0xb020, | 606 | 0x3020, 0xb140, 0x1ff8, 0x3160, 0xb020, |
590 | 0xb000, 0x3000, 0x0800, 0x3000, 0xb000}; | 607 | 0xb000, 0x3000, 0x0800, 0x3000, 0xb000 |
608 | }; | ||
609 | |||
591 | static const u16 uv_static_hcoeffs[N_HORIZ_UV_TAPS * N_PHASES] = { | 610 | static const u16 uv_static_hcoeffs[N_HORIZ_UV_TAPS * N_PHASES] = { |
592 | 0x3000, 0x1800, 0x1800, 0xb000, 0x18d0, 0x2e60, | 611 | 0x3000, 0x1800, 0x1800, 0xb000, 0x18d0, 0x2e60, |
593 | 0xb000, 0x1990, 0x2ce0, 0xb020, 0x1a68, 0x2b40, | 612 | 0xb000, 0x1990, 0x2ce0, 0xb020, 0x1a68, 0x2b40, |
@@ -597,7 +616,8 @@ static const u16 uv_static_hcoeffs[N_HORIZ_UV_TAPS * N_PHASES] = { | |||
597 | 0xb100, 0x1eb8, 0x3620, 0xb100, 0x1f18, 0x34a0, | 616 | 0xb100, 0x1eb8, 0x3620, 0xb100, 0x1f18, 0x34a0, |
598 | 0xb100, 0x1f68, 0x3360, 0xb0e0, 0x1fa8, 0x3240, | 617 | 0xb100, 0x1f68, 0x3360, 0xb0e0, 0x1fa8, 0x3240, |
599 | 0xb0c0, 0x1fe0, 0x3140, 0xb060, 0x1ff0, 0x30a0, | 618 | 0xb0c0, 0x1fe0, 0x3140, 0xb060, 0x1ff0, 0x30a0, |
600 | 0x3000, 0x0800, 0x3000}; | 619 | 0x3000, 0x0800, 0x3000 |
620 | }; | ||
601 | 621 | ||
602 | static void update_polyphase_filter(struct overlay_registers *regs) | 622 | static void update_polyphase_filter(struct overlay_registers *regs) |
603 | { | 623 | { |
@@ -630,29 +650,31 @@ static bool update_scaling_factors(struct intel_overlay *overlay, | |||
630 | yscale = 1 << FP_SHIFT; | 650 | yscale = 1 << FP_SHIFT; |
631 | 651 | ||
632 | /*if (params->format & I915_OVERLAY_YUV_PLANAR) {*/ | 652 | /*if (params->format & I915_OVERLAY_YUV_PLANAR) {*/ |
633 | xscale_UV = xscale/uv_hscale; | 653 | xscale_UV = xscale/uv_hscale; |
634 | yscale_UV = yscale/uv_vscale; | 654 | yscale_UV = yscale/uv_vscale; |
635 | /* make the Y scale to UV scale ratio an exact multiply */ | 655 | /* make the Y scale to UV scale ratio an exact multiply */ |
636 | xscale = xscale_UV * uv_hscale; | 656 | xscale = xscale_UV * uv_hscale; |
637 | yscale = yscale_UV * uv_vscale; | 657 | yscale = yscale_UV * uv_vscale; |
638 | /*} else { | 658 | /*} else { |
639 | xscale_UV = 0; | 659 | xscale_UV = 0; |
640 | yscale_UV = 0; | 660 | yscale_UV = 0; |
641 | }*/ | 661 | }*/ |
642 | 662 | ||
643 | if (xscale != overlay->old_xscale || yscale != overlay->old_yscale) | 663 | if (xscale != overlay->old_xscale || yscale != overlay->old_yscale) |
644 | scale_changed = true; | 664 | scale_changed = true; |
645 | overlay->old_xscale = xscale; | 665 | overlay->old_xscale = xscale; |
646 | overlay->old_yscale = yscale; | 666 | overlay->old_yscale = yscale; |
647 | 667 | ||
648 | regs->YRGBSCALE = ((yscale & FRACT_MASK) << 20) | 668 | regs->YRGBSCALE = (((yscale & FRACT_MASK) << 20) | |
649 | | ((xscale >> FP_SHIFT) << 16) | 669 | ((xscale >> FP_SHIFT) << 16) | |
650 | | ((xscale & FRACT_MASK) << 3); | 670 | ((xscale & FRACT_MASK) << 3)); |
651 | regs->UVSCALE = ((yscale_UV & FRACT_MASK) << 20) | 671 | |
652 | | ((xscale_UV >> FP_SHIFT) << 16) | 672 | regs->UVSCALE = (((yscale_UV & FRACT_MASK) << 20) | |
653 | | ((xscale_UV & FRACT_MASK) << 3); | 673 | ((xscale_UV >> FP_SHIFT) << 16) | |
654 | regs->UVSCALEV = ((yscale >> FP_SHIFT) << 16) | 674 | ((xscale_UV & FRACT_MASK) << 3)); |
655 | | ((yscale_UV >> FP_SHIFT) << 0); | 675 | |
676 | regs->UVSCALEV = ((((yscale >> FP_SHIFT) << 16) | | ||
677 | ((yscale_UV >> FP_SHIFT) << 0))); | ||
656 | 678 | ||
657 | if (scale_changed) | 679 | if (scale_changed) |
658 | update_polyphase_filter(regs); | 680 | update_polyphase_filter(regs); |
@@ -664,22 +686,28 @@ static void update_colorkey(struct intel_overlay *overlay, | |||
664 | struct overlay_registers *regs) | 686 | struct overlay_registers *regs) |
665 | { | 687 | { |
666 | u32 key = overlay->color_key; | 688 | u32 key = overlay->color_key; |
689 | |||
667 | switch (overlay->crtc->base.fb->bits_per_pixel) { | 690 | switch (overlay->crtc->base.fb->bits_per_pixel) { |
668 | case 8: | 691 | case 8: |
669 | regs->DCLRKV = 0; | 692 | regs->DCLRKV = 0; |
670 | regs->DCLRKM = CLK_RGB8I_MASK | DST_KEY_ENABLE; | 693 | regs->DCLRKM = CLK_RGB8I_MASK | DST_KEY_ENABLE; |
671 | case 16: | 694 | break; |
672 | if (overlay->crtc->base.fb->depth == 15) { | 695 | |
673 | regs->DCLRKV = RGB15_TO_COLORKEY(key); | 696 | case 16: |
674 | regs->DCLRKM = CLK_RGB15_MASK | DST_KEY_ENABLE; | 697 | if (overlay->crtc->base.fb->depth == 15) { |
675 | } else { | 698 | regs->DCLRKV = RGB15_TO_COLORKEY(key); |
676 | regs->DCLRKV = RGB16_TO_COLORKEY(key); | 699 | regs->DCLRKM = CLK_RGB15_MASK | DST_KEY_ENABLE; |
677 | regs->DCLRKM = CLK_RGB16_MASK | DST_KEY_ENABLE; | 700 | } else { |
678 | } | 701 | regs->DCLRKV = RGB16_TO_COLORKEY(key); |
679 | case 24: | 702 | regs->DCLRKM = CLK_RGB16_MASK | DST_KEY_ENABLE; |
680 | case 32: | 703 | } |
681 | regs->DCLRKV = key; | 704 | break; |
682 | regs->DCLRKM = CLK_RGB24_MASK | DST_KEY_ENABLE; | 705 | |
706 | case 24: | ||
707 | case 32: | ||
708 | regs->DCLRKV = key; | ||
709 | regs->DCLRKM = CLK_RGB24_MASK | DST_KEY_ENABLE; | ||
710 | break; | ||
683 | } | 711 | } |
684 | } | 712 | } |
685 | 713 | ||
@@ -689,53 +717,52 @@ static u32 overlay_cmd_reg(struct put_image_params *params) | |||
689 | 717 | ||
690 | if (params->format & I915_OVERLAY_YUV_PLANAR) { | 718 | if (params->format & I915_OVERLAY_YUV_PLANAR) { |
691 | switch (params->format & I915_OVERLAY_DEPTH_MASK) { | 719 | switch (params->format & I915_OVERLAY_DEPTH_MASK) { |
692 | case I915_OVERLAY_YUV422: | 720 | case I915_OVERLAY_YUV422: |
693 | cmd |= OCMD_YUV_422_PLANAR; | 721 | cmd |= OCMD_YUV_422_PLANAR; |
694 | break; | 722 | break; |
695 | case I915_OVERLAY_YUV420: | 723 | case I915_OVERLAY_YUV420: |
696 | cmd |= OCMD_YUV_420_PLANAR; | 724 | cmd |= OCMD_YUV_420_PLANAR; |
697 | break; | 725 | break; |
698 | case I915_OVERLAY_YUV411: | 726 | case I915_OVERLAY_YUV411: |
699 | case I915_OVERLAY_YUV410: | 727 | case I915_OVERLAY_YUV410: |
700 | cmd |= OCMD_YUV_410_PLANAR; | 728 | cmd |= OCMD_YUV_410_PLANAR; |
701 | break; | 729 | break; |
702 | } | 730 | } |
703 | } else { /* YUV packed */ | 731 | } else { /* YUV packed */ |
704 | switch (params->format & I915_OVERLAY_DEPTH_MASK) { | 732 | switch (params->format & I915_OVERLAY_DEPTH_MASK) { |
705 | case I915_OVERLAY_YUV422: | 733 | case I915_OVERLAY_YUV422: |
706 | cmd |= OCMD_YUV_422_PACKED; | 734 | cmd |= OCMD_YUV_422_PACKED; |
707 | break; | 735 | break; |
708 | case I915_OVERLAY_YUV411: | 736 | case I915_OVERLAY_YUV411: |
709 | cmd |= OCMD_YUV_411_PACKED; | 737 | cmd |= OCMD_YUV_411_PACKED; |
710 | break; | 738 | break; |
711 | } | 739 | } |
712 | 740 | ||
713 | switch (params->format & I915_OVERLAY_SWAP_MASK) { | 741 | switch (params->format & I915_OVERLAY_SWAP_MASK) { |
714 | case I915_OVERLAY_NO_SWAP: | 742 | case I915_OVERLAY_NO_SWAP: |
715 | break; | 743 | break; |
716 | case I915_OVERLAY_UV_SWAP: | 744 | case I915_OVERLAY_UV_SWAP: |
717 | cmd |= OCMD_UV_SWAP; | 745 | cmd |= OCMD_UV_SWAP; |
718 | break; | 746 | break; |
719 | case I915_OVERLAY_Y_SWAP: | 747 | case I915_OVERLAY_Y_SWAP: |
720 | cmd |= OCMD_Y_SWAP; | 748 | cmd |= OCMD_Y_SWAP; |
721 | break; | 749 | break; |
722 | case I915_OVERLAY_Y_AND_UV_SWAP: | 750 | case I915_OVERLAY_Y_AND_UV_SWAP: |
723 | cmd |= OCMD_Y_AND_UV_SWAP; | 751 | cmd |= OCMD_Y_AND_UV_SWAP; |
724 | break; | 752 | break; |
725 | } | 753 | } |
726 | } | 754 | } |
727 | 755 | ||
728 | return cmd; | 756 | return cmd; |
729 | } | 757 | } |
730 | 758 | ||
731 | int intel_overlay_do_put_image(struct intel_overlay *overlay, | 759 | static int intel_overlay_do_put_image(struct intel_overlay *overlay, |
732 | struct drm_gem_object *new_bo, | 760 | struct drm_i915_gem_object *new_bo, |
733 | struct put_image_params *params) | 761 | struct put_image_params *params) |
734 | { | 762 | { |
735 | int ret, tmp_width; | 763 | int ret, tmp_width; |
736 | struct overlay_registers *regs; | 764 | struct overlay_registers *regs; |
737 | bool scale_changed = false; | 765 | bool scale_changed = false; |
738 | struct drm_i915_gem_object *bo_priv = to_intel_bo(new_bo); | ||
739 | struct drm_device *dev = overlay->dev; | 766 | struct drm_device *dev = overlay->dev; |
740 | 767 | ||
741 | BUG_ON(!mutex_is_locked(&dev->struct_mutex)); | 768 | BUG_ON(!mutex_is_locked(&dev->struct_mutex)); |
@@ -746,7 +773,7 @@ int intel_overlay_do_put_image(struct intel_overlay *overlay, | |||
746 | if (ret != 0) | 773 | if (ret != 0) |
747 | return ret; | 774 | return ret; |
748 | 775 | ||
749 | ret = i915_gem_object_pin(new_bo, PAGE_SIZE); | 776 | ret = i915_gem_object_pin(new_bo, PAGE_SIZE, true); |
750 | if (ret != 0) | 777 | if (ret != 0) |
751 | return ret; | 778 | return ret; |
752 | 779 | ||
@@ -754,25 +781,29 @@ int intel_overlay_do_put_image(struct intel_overlay *overlay, | |||
754 | if (ret != 0) | 781 | if (ret != 0) |
755 | goto out_unpin; | 782 | goto out_unpin; |
756 | 783 | ||
784 | ret = i915_gem_object_put_fence(new_bo); | ||
785 | if (ret) | ||
786 | goto out_unpin; | ||
787 | |||
757 | if (!overlay->active) { | 788 | if (!overlay->active) { |
758 | regs = intel_overlay_map_regs_atomic(overlay); | 789 | regs = intel_overlay_map_regs(overlay); |
759 | if (!regs) { | 790 | if (!regs) { |
760 | ret = -ENOMEM; | 791 | ret = -ENOMEM; |
761 | goto out_unpin; | 792 | goto out_unpin; |
762 | } | 793 | } |
763 | regs->OCONFIG = OCONF_CC_OUT_8BIT; | 794 | regs->OCONFIG = OCONF_CC_OUT_8BIT; |
764 | if (IS_I965GM(overlay->dev)) | 795 | if (IS_GEN4(overlay->dev)) |
765 | regs->OCONFIG |= OCONF_CSC_MODE_BT709; | 796 | regs->OCONFIG |= OCONF_CSC_MODE_BT709; |
766 | regs->OCONFIG |= overlay->crtc->pipe == 0 ? | 797 | regs->OCONFIG |= overlay->crtc->pipe == 0 ? |
767 | OCONF_PIPE_A : OCONF_PIPE_B; | 798 | OCONF_PIPE_A : OCONF_PIPE_B; |
768 | intel_overlay_unmap_regs_atomic(overlay); | 799 | intel_overlay_unmap_regs(overlay, regs); |
769 | 800 | ||
770 | ret = intel_overlay_on(overlay); | 801 | ret = intel_overlay_on(overlay); |
771 | if (ret != 0) | 802 | if (ret != 0) |
772 | goto out_unpin; | 803 | goto out_unpin; |
773 | } | 804 | } |
774 | 805 | ||
775 | regs = intel_overlay_map_regs_atomic(overlay); | 806 | regs = intel_overlay_map_regs(overlay); |
776 | if (!regs) { | 807 | if (!regs) { |
777 | ret = -ENOMEM; | 808 | ret = -ENOMEM; |
778 | goto out_unpin; | 809 | goto out_unpin; |
@@ -788,9 +819,9 @@ int intel_overlay_do_put_image(struct intel_overlay *overlay, | |||
788 | 819 | ||
789 | regs->SWIDTH = params->src_w; | 820 | regs->SWIDTH = params->src_w; |
790 | regs->SWIDTHSW = calc_swidthsw(overlay->dev, | 821 | regs->SWIDTHSW = calc_swidthsw(overlay->dev, |
791 | params->offset_Y, tmp_width); | 822 | params->offset_Y, tmp_width); |
792 | regs->SHEIGHT = params->src_h; | 823 | regs->SHEIGHT = params->src_h; |
793 | regs->OBUF_0Y = bo_priv->gtt_offset + params-> offset_Y; | 824 | regs->OBUF_0Y = new_bo->gtt_offset + params-> offset_Y; |
794 | regs->OSTRIDE = params->stride_Y; | 825 | regs->OSTRIDE = params->stride_Y; |
795 | 826 | ||
796 | if (params->format & I915_OVERLAY_YUV_PLANAR) { | 827 | if (params->format & I915_OVERLAY_YUV_PLANAR) { |
@@ -799,13 +830,13 @@ int intel_overlay_do_put_image(struct intel_overlay *overlay, | |||
799 | u32 tmp_U, tmp_V; | 830 | u32 tmp_U, tmp_V; |
800 | regs->SWIDTH |= (params->src_w/uv_hscale) << 16; | 831 | regs->SWIDTH |= (params->src_w/uv_hscale) << 16; |
801 | tmp_U = calc_swidthsw(overlay->dev, params->offset_U, | 832 | tmp_U = calc_swidthsw(overlay->dev, params->offset_U, |
802 | params->src_w/uv_hscale); | 833 | params->src_w/uv_hscale); |
803 | tmp_V = calc_swidthsw(overlay->dev, params->offset_V, | 834 | tmp_V = calc_swidthsw(overlay->dev, params->offset_V, |
804 | params->src_w/uv_hscale); | 835 | params->src_w/uv_hscale); |
805 | regs->SWIDTHSW |= max_t(u32, tmp_U, tmp_V) << 16; | 836 | regs->SWIDTHSW |= max_t(u32, tmp_U, tmp_V) << 16; |
806 | regs->SHEIGHT |= (params->src_h/uv_vscale) << 16; | 837 | regs->SHEIGHT |= (params->src_h/uv_vscale) << 16; |
807 | regs->OBUF_0U = bo_priv->gtt_offset + params->offset_U; | 838 | regs->OBUF_0U = new_bo->gtt_offset + params->offset_U; |
808 | regs->OBUF_0V = bo_priv->gtt_offset + params->offset_V; | 839 | regs->OBUF_0V = new_bo->gtt_offset + params->offset_V; |
809 | regs->OSTRIDE |= params->stride_UV << 16; | 840 | regs->OSTRIDE |= params->stride_UV << 16; |
810 | } | 841 | } |
811 | 842 | ||
@@ -815,12 +846,14 @@ int intel_overlay_do_put_image(struct intel_overlay *overlay, | |||
815 | 846 | ||
816 | regs->OCMD = overlay_cmd_reg(params); | 847 | regs->OCMD = overlay_cmd_reg(params); |
817 | 848 | ||
818 | intel_overlay_unmap_regs_atomic(overlay); | 849 | intel_overlay_unmap_regs(overlay, regs); |
819 | 850 | ||
820 | intel_overlay_continue(overlay, scale_changed); | 851 | ret = intel_overlay_continue(overlay, scale_changed); |
852 | if (ret) | ||
853 | goto out_unpin; | ||
821 | 854 | ||
822 | overlay->old_vid_bo = overlay->vid_bo; | 855 | overlay->old_vid_bo = overlay->vid_bo; |
823 | overlay->vid_bo = to_intel_bo(new_bo); | 856 | overlay->vid_bo = new_bo; |
824 | 857 | ||
825 | return 0; | 858 | return 0; |
826 | 859 | ||
@@ -831,18 +864,16 @@ out_unpin: | |||
831 | 864 | ||
832 | int intel_overlay_switch_off(struct intel_overlay *overlay) | 865 | int intel_overlay_switch_off(struct intel_overlay *overlay) |
833 | { | 866 | { |
834 | int ret; | ||
835 | struct overlay_registers *regs; | 867 | struct overlay_registers *regs; |
836 | struct drm_device *dev = overlay->dev; | 868 | struct drm_device *dev = overlay->dev; |
869 | int ret; | ||
837 | 870 | ||
838 | BUG_ON(!mutex_is_locked(&dev->struct_mutex)); | 871 | BUG_ON(!mutex_is_locked(&dev->struct_mutex)); |
839 | BUG_ON(!mutex_is_locked(&dev->mode_config.mutex)); | 872 | BUG_ON(!mutex_is_locked(&dev->mode_config.mutex)); |
840 | 873 | ||
841 | if (overlay->hw_wedged) { | 874 | ret = intel_overlay_recover_from_interrupt(overlay); |
842 | ret = intel_overlay_recover_from_interrupt(overlay, 1); | 875 | if (ret != 0) |
843 | if (ret != 0) | 876 | return ret; |
844 | return ret; | ||
845 | } | ||
846 | 877 | ||
847 | if (!overlay->active) | 878 | if (!overlay->active) |
848 | return 0; | 879 | return 0; |
@@ -851,33 +882,29 @@ int intel_overlay_switch_off(struct intel_overlay *overlay) | |||
851 | if (ret != 0) | 882 | if (ret != 0) |
852 | return ret; | 883 | return ret; |
853 | 884 | ||
854 | regs = intel_overlay_map_regs_atomic(overlay); | 885 | regs = intel_overlay_map_regs(overlay); |
855 | regs->OCMD = 0; | 886 | regs->OCMD = 0; |
856 | intel_overlay_unmap_regs_atomic(overlay); | 887 | intel_overlay_unmap_regs(overlay, regs); |
857 | 888 | ||
858 | ret = intel_overlay_off(overlay); | 889 | ret = intel_overlay_off(overlay); |
859 | if (ret != 0) | 890 | if (ret != 0) |
860 | return ret; | 891 | return ret; |
861 | 892 | ||
862 | intel_overlay_off_tail(overlay); | 893 | intel_overlay_off_tail(overlay); |
863 | |||
864 | return 0; | 894 | return 0; |
865 | } | 895 | } |
866 | 896 | ||
867 | static int check_overlay_possible_on_crtc(struct intel_overlay *overlay, | 897 | static int check_overlay_possible_on_crtc(struct intel_overlay *overlay, |
868 | struct intel_crtc *crtc) | 898 | struct intel_crtc *crtc) |
869 | { | 899 | { |
870 | drm_i915_private_t *dev_priv = overlay->dev->dev_private; | 900 | drm_i915_private_t *dev_priv = overlay->dev->dev_private; |
871 | u32 pipeconf; | ||
872 | int pipeconf_reg = (crtc->pipe == 0) ? PIPEACONF : PIPEBCONF; | ||
873 | 901 | ||
874 | if (!crtc->base.enabled || crtc->dpms_mode != DRM_MODE_DPMS_ON) | 902 | if (!crtc->active) |
875 | return -EINVAL; | 903 | return -EINVAL; |
876 | 904 | ||
877 | pipeconf = I915_READ(pipeconf_reg); | ||
878 | |||
879 | /* can't use the overlay with double wide pipe */ | 905 | /* can't use the overlay with double wide pipe */ |
880 | if (!IS_I965G(overlay->dev) && pipeconf & PIPEACONF_DOUBLE_WIDE) | 906 | if (INTEL_INFO(overlay->dev)->gen < 4 && |
907 | (I915_READ(PIPECONF(crtc->pipe)) & (PIPECONF_DOUBLE_WIDE | PIPECONF_ENABLE)) != PIPECONF_ENABLE) | ||
881 | return -EINVAL; | 908 | return -EINVAL; |
882 | 909 | ||
883 | return 0; | 910 | return 0; |
@@ -886,20 +913,22 @@ static int check_overlay_possible_on_crtc(struct intel_overlay *overlay, | |||
886 | static void update_pfit_vscale_ratio(struct intel_overlay *overlay) | 913 | static void update_pfit_vscale_ratio(struct intel_overlay *overlay) |
887 | { | 914 | { |
888 | struct drm_device *dev = overlay->dev; | 915 | struct drm_device *dev = overlay->dev; |
889 | drm_i915_private_t *dev_priv = dev->dev_private; | 916 | drm_i915_private_t *dev_priv = dev->dev_private; |
890 | u32 ratio; | ||
891 | u32 pfit_control = I915_READ(PFIT_CONTROL); | 917 | u32 pfit_control = I915_READ(PFIT_CONTROL); |
918 | u32 ratio; | ||
892 | 919 | ||
893 | /* XXX: This is not the same logic as in the xorg driver, but more in | 920 | /* XXX: This is not the same logic as in the xorg driver, but more in |
894 | * line with the intel documentation for the i965 */ | 921 | * line with the intel documentation for the i965 |
895 | if (!IS_I965G(dev) && (pfit_control & VERT_AUTO_SCALE)) { | 922 | */ |
896 | ratio = I915_READ(PFIT_AUTO_RATIOS) >> PFIT_VERT_SCALE_SHIFT; | 923 | if (INTEL_INFO(dev)->gen >= 4) { |
897 | } else { /* on i965 use the PGM reg to read out the autoscaler values */ | 924 | /* on i965 use the PGM reg to read out the autoscaler values */ |
898 | ratio = I915_READ(PFIT_PGM_RATIOS); | 925 | ratio = I915_READ(PFIT_PGM_RATIOS) >> PFIT_VERT_SCALE_SHIFT_965; |
899 | if (IS_I965G(dev)) | 926 | } else { |
900 | ratio >>= PFIT_VERT_SCALE_SHIFT_965; | 927 | if (pfit_control & VERT_AUTO_SCALE) |
928 | ratio = I915_READ(PFIT_AUTO_RATIOS); | ||
901 | else | 929 | else |
902 | ratio >>= PFIT_VERT_SCALE_SHIFT; | 930 | ratio = I915_READ(PFIT_PGM_RATIOS); |
931 | ratio >>= PFIT_VERT_SCALE_SHIFT; | ||
903 | } | 932 | } |
904 | 933 | ||
905 | overlay->pfit_vscale_ratio = ratio; | 934 | overlay->pfit_vscale_ratio = ratio; |
@@ -910,12 +939,10 @@ static int check_overlay_dst(struct intel_overlay *overlay, | |||
910 | { | 939 | { |
911 | struct drm_display_mode *mode = &overlay->crtc->base.mode; | 940 | struct drm_display_mode *mode = &overlay->crtc->base.mode; |
912 | 941 | ||
913 | if ((rec->dst_x < mode->crtc_hdisplay) | 942 | if (rec->dst_x < mode->crtc_hdisplay && |
914 | && (rec->dst_x + rec->dst_width | 943 | rec->dst_x + rec->dst_width <= mode->crtc_hdisplay && |
915 | <= mode->crtc_hdisplay) | 944 | rec->dst_y < mode->crtc_vdisplay && |
916 | && (rec->dst_y < mode->crtc_vdisplay) | 945 | rec->dst_y + rec->dst_height <= mode->crtc_vdisplay) |
917 | && (rec->dst_y + rec->dst_height | ||
918 | <= mode->crtc_vdisplay)) | ||
919 | return 0; | 946 | return 0; |
920 | else | 947 | else |
921 | return -EINVAL; | 948 | return -EINVAL; |
@@ -938,55 +965,61 @@ static int check_overlay_scaling(struct put_image_params *rec) | |||
938 | 965 | ||
939 | static int check_overlay_src(struct drm_device *dev, | 966 | static int check_overlay_src(struct drm_device *dev, |
940 | struct drm_intel_overlay_put_image *rec, | 967 | struct drm_intel_overlay_put_image *rec, |
941 | struct drm_gem_object *new_bo) | 968 | struct drm_i915_gem_object *new_bo) |
942 | { | 969 | { |
943 | u32 stride_mask; | ||
944 | int depth; | ||
945 | int uv_hscale = uv_hsubsampling(rec->flags); | 970 | int uv_hscale = uv_hsubsampling(rec->flags); |
946 | int uv_vscale = uv_vsubsampling(rec->flags); | 971 | int uv_vscale = uv_vsubsampling(rec->flags); |
947 | size_t tmp; | 972 | u32 stride_mask; |
973 | int depth; | ||
974 | u32 tmp; | ||
948 | 975 | ||
949 | /* check src dimensions */ | 976 | /* check src dimensions */ |
950 | if (IS_845G(dev) || IS_I830(dev)) { | 977 | if (IS_845G(dev) || IS_I830(dev)) { |
951 | if (rec->src_height > IMAGE_MAX_HEIGHT_LEGACY | 978 | if (rec->src_height > IMAGE_MAX_HEIGHT_LEGACY || |
952 | || rec->src_width > IMAGE_MAX_WIDTH_LEGACY) | 979 | rec->src_width > IMAGE_MAX_WIDTH_LEGACY) |
953 | return -EINVAL; | 980 | return -EINVAL; |
954 | } else { | 981 | } else { |
955 | if (rec->src_height > IMAGE_MAX_HEIGHT | 982 | if (rec->src_height > IMAGE_MAX_HEIGHT || |
956 | || rec->src_width > IMAGE_MAX_WIDTH) | 983 | rec->src_width > IMAGE_MAX_WIDTH) |
957 | return -EINVAL; | 984 | return -EINVAL; |
958 | } | 985 | } |
986 | |||
959 | /* better safe than sorry, use 4 as the maximal subsampling ratio */ | 987 | /* better safe than sorry, use 4 as the maximal subsampling ratio */ |
960 | if (rec->src_height < N_VERT_Y_TAPS*4 | 988 | if (rec->src_height < N_VERT_Y_TAPS*4 || |
961 | || rec->src_width < N_HORIZ_Y_TAPS*4) | 989 | rec->src_width < N_HORIZ_Y_TAPS*4) |
962 | return -EINVAL; | 990 | return -EINVAL; |
963 | 991 | ||
964 | /* check alignment constraints */ | 992 | /* check alignment constraints */ |
965 | switch (rec->flags & I915_OVERLAY_TYPE_MASK) { | 993 | switch (rec->flags & I915_OVERLAY_TYPE_MASK) { |
966 | case I915_OVERLAY_RGB: | 994 | case I915_OVERLAY_RGB: |
967 | /* not implemented */ | 995 | /* not implemented */ |
996 | return -EINVAL; | ||
997 | |||
998 | case I915_OVERLAY_YUV_PACKED: | ||
999 | if (uv_vscale != 1) | ||
968 | return -EINVAL; | 1000 | return -EINVAL; |
969 | case I915_OVERLAY_YUV_PACKED: | 1001 | |
970 | depth = packed_depth_bytes(rec->flags); | 1002 | depth = packed_depth_bytes(rec->flags); |
971 | if (uv_vscale != 1) | 1003 | if (depth < 0) |
972 | return -EINVAL; | 1004 | return depth; |
973 | if (depth < 0) | 1005 | |
974 | return depth; | 1006 | /* ignore UV planes */ |
975 | /* ignore UV planes */ | 1007 | rec->stride_UV = 0; |
976 | rec->stride_UV = 0; | 1008 | rec->offset_U = 0; |
977 | rec->offset_U = 0; | 1009 | rec->offset_V = 0; |
978 | rec->offset_V = 0; | 1010 | /* check pixel alignment */ |
979 | /* check pixel alignment */ | 1011 | if (rec->offset_Y % depth) |
980 | if (rec->offset_Y % depth) | ||
981 | return -EINVAL; | ||
982 | break; | ||
983 | case I915_OVERLAY_YUV_PLANAR: | ||
984 | if (uv_vscale < 0 || uv_hscale < 0) | ||
985 | return -EINVAL; | ||
986 | /* no offset restrictions for planar formats */ | ||
987 | break; | ||
988 | default: | ||
989 | return -EINVAL; | 1012 | return -EINVAL; |
1013 | break; | ||
1014 | |||
1015 | case I915_OVERLAY_YUV_PLANAR: | ||
1016 | if (uv_vscale < 0 || uv_hscale < 0) | ||
1017 | return -EINVAL; | ||
1018 | /* no offset restrictions for planar formats */ | ||
1019 | break; | ||
1020 | |||
1021 | default: | ||
1022 | return -EINVAL; | ||
990 | } | 1023 | } |
991 | 1024 | ||
992 | if (rec->src_width % uv_hscale) | 1025 | if (rec->src_width % uv_hscale) |
@@ -1000,47 +1033,74 @@ static int check_overlay_src(struct drm_device *dev, | |||
1000 | 1033 | ||
1001 | if (rec->stride_Y & stride_mask || rec->stride_UV & stride_mask) | 1034 | if (rec->stride_Y & stride_mask || rec->stride_UV & stride_mask) |
1002 | return -EINVAL; | 1035 | return -EINVAL; |
1003 | if (IS_I965G(dev) && rec->stride_Y < 512) | 1036 | if (IS_GEN4(dev) && rec->stride_Y < 512) |
1004 | return -EINVAL; | 1037 | return -EINVAL; |
1005 | 1038 | ||
1006 | tmp = (rec->flags & I915_OVERLAY_TYPE_MASK) == I915_OVERLAY_YUV_PLANAR ? | 1039 | tmp = (rec->flags & I915_OVERLAY_TYPE_MASK) == I915_OVERLAY_YUV_PLANAR ? |
1007 | 4 : 8; | 1040 | 4096 : 8192; |
1008 | if (rec->stride_Y > tmp*1024 || rec->stride_UV > 2*1024) | 1041 | if (rec->stride_Y > tmp || rec->stride_UV > 2*1024) |
1009 | return -EINVAL; | 1042 | return -EINVAL; |
1010 | 1043 | ||
1011 | /* check buffer dimensions */ | 1044 | /* check buffer dimensions */ |
1012 | switch (rec->flags & I915_OVERLAY_TYPE_MASK) { | 1045 | switch (rec->flags & I915_OVERLAY_TYPE_MASK) { |
1013 | case I915_OVERLAY_RGB: | 1046 | case I915_OVERLAY_RGB: |
1014 | case I915_OVERLAY_YUV_PACKED: | 1047 | case I915_OVERLAY_YUV_PACKED: |
1015 | /* always 4 Y values per depth pixels */ | 1048 | /* always 4 Y values per depth pixels */ |
1016 | if (packed_width_bytes(rec->flags, rec->src_width) | 1049 | if (packed_width_bytes(rec->flags, rec->src_width) > rec->stride_Y) |
1017 | > rec->stride_Y) | 1050 | return -EINVAL; |
1018 | return -EINVAL; | 1051 | |
1019 | 1052 | tmp = rec->stride_Y*rec->src_height; | |
1020 | tmp = rec->stride_Y*rec->src_height; | 1053 | if (rec->offset_Y + tmp > new_bo->base.size) |
1021 | if (rec->offset_Y + tmp > new_bo->size) | 1054 | return -EINVAL; |
1022 | return -EINVAL; | 1055 | break; |
1023 | break; | 1056 | |
1024 | case I915_OVERLAY_YUV_PLANAR: | 1057 | case I915_OVERLAY_YUV_PLANAR: |
1025 | if (rec->src_width > rec->stride_Y) | 1058 | if (rec->src_width > rec->stride_Y) |
1026 | return -EINVAL; | 1059 | return -EINVAL; |
1027 | if (rec->src_width/uv_hscale > rec->stride_UV) | 1060 | if (rec->src_width/uv_hscale > rec->stride_UV) |
1028 | return -EINVAL; | 1061 | return -EINVAL; |
1029 | 1062 | ||
1030 | tmp = rec->stride_Y*rec->src_height; | 1063 | tmp = rec->stride_Y * rec->src_height; |
1031 | if (rec->offset_Y + tmp > new_bo->size) | 1064 | if (rec->offset_Y + tmp > new_bo->base.size) |
1032 | return -EINVAL; | 1065 | return -EINVAL; |
1033 | tmp = rec->stride_UV*rec->src_height; | 1066 | |
1034 | tmp /= uv_vscale; | 1067 | tmp = rec->stride_UV * (rec->src_height / uv_vscale); |
1035 | if (rec->offset_U + tmp > new_bo->size | 1068 | if (rec->offset_U + tmp > new_bo->base.size || |
1036 | || rec->offset_V + tmp > new_bo->size) | 1069 | rec->offset_V + tmp > new_bo->base.size) |
1037 | return -EINVAL; | 1070 | return -EINVAL; |
1038 | break; | 1071 | break; |
1039 | } | 1072 | } |
1040 | 1073 | ||
1041 | return 0; | 1074 | return 0; |
1042 | } | 1075 | } |
1043 | 1076 | ||
1077 | /** | ||
1078 | * Return the pipe currently connected to the panel fitter, | ||
1079 | * or -1 if the panel fitter is not present or not in use | ||
1080 | */ | ||
1081 | static int intel_panel_fitter_pipe(struct drm_device *dev) | ||
1082 | { | ||
1083 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
1084 | u32 pfit_control; | ||
1085 | |||
1086 | /* i830 doesn't have a panel fitter */ | ||
1087 | if (IS_I830(dev)) | ||
1088 | return -1; | ||
1089 | |||
1090 | pfit_control = I915_READ(PFIT_CONTROL); | ||
1091 | |||
1092 | /* See if the panel fitter is in use */ | ||
1093 | if ((pfit_control & PFIT_ENABLE) == 0) | ||
1094 | return -1; | ||
1095 | |||
1096 | /* 965 can place panel fitter on either pipe */ | ||
1097 | if (IS_GEN4(dev)) | ||
1098 | return (pfit_control >> 29) & 0x3; | ||
1099 | |||
1100 | /* older chips can only use pipe 1 */ | ||
1101 | return 1; | ||
1102 | } | ||
1103 | |||
1044 | int intel_overlay_put_image(struct drm_device *dev, void *data, | 1104 | int intel_overlay_put_image(struct drm_device *dev, void *data, |
1045 | struct drm_file *file_priv) | 1105 | struct drm_file *file_priv) |
1046 | { | 1106 | { |
@@ -1049,7 +1109,7 @@ int intel_overlay_put_image(struct drm_device *dev, void *data, | |||
1049 | struct intel_overlay *overlay; | 1109 | struct intel_overlay *overlay; |
1050 | struct drm_mode_object *drmmode_obj; | 1110 | struct drm_mode_object *drmmode_obj; |
1051 | struct intel_crtc *crtc; | 1111 | struct intel_crtc *crtc; |
1052 | struct drm_gem_object *new_bo; | 1112 | struct drm_i915_gem_object *new_bo; |
1053 | struct put_image_params *params; | 1113 | struct put_image_params *params; |
1054 | int ret; | 1114 | int ret; |
1055 | 1115 | ||
@@ -1081,16 +1141,16 @@ int intel_overlay_put_image(struct drm_device *dev, void *data, | |||
1081 | return -ENOMEM; | 1141 | return -ENOMEM; |
1082 | 1142 | ||
1083 | drmmode_obj = drm_mode_object_find(dev, put_image_rec->crtc_id, | 1143 | drmmode_obj = drm_mode_object_find(dev, put_image_rec->crtc_id, |
1084 | DRM_MODE_OBJECT_CRTC); | 1144 | DRM_MODE_OBJECT_CRTC); |
1085 | if (!drmmode_obj) { | 1145 | if (!drmmode_obj) { |
1086 | ret = -ENOENT; | 1146 | ret = -ENOENT; |
1087 | goto out_free; | 1147 | goto out_free; |
1088 | } | 1148 | } |
1089 | crtc = to_intel_crtc(obj_to_crtc(drmmode_obj)); | 1149 | crtc = to_intel_crtc(obj_to_crtc(drmmode_obj)); |
1090 | 1150 | ||
1091 | new_bo = drm_gem_object_lookup(dev, file_priv, | 1151 | new_bo = to_intel_bo(drm_gem_object_lookup(dev, file_priv, |
1092 | put_image_rec->bo_handle); | 1152 | put_image_rec->bo_handle)); |
1093 | if (!new_bo) { | 1153 | if (&new_bo->base == NULL) { |
1094 | ret = -ENOENT; | 1154 | ret = -ENOENT; |
1095 | goto out_free; | 1155 | goto out_free; |
1096 | } | 1156 | } |
@@ -1098,12 +1158,16 @@ int intel_overlay_put_image(struct drm_device *dev, void *data, | |||
1098 | mutex_lock(&dev->mode_config.mutex); | 1158 | mutex_lock(&dev->mode_config.mutex); |
1099 | mutex_lock(&dev->struct_mutex); | 1159 | mutex_lock(&dev->struct_mutex); |
1100 | 1160 | ||
1101 | if (overlay->hw_wedged) { | 1161 | if (new_bo->tiling_mode) { |
1102 | ret = intel_overlay_recover_from_interrupt(overlay, 1); | 1162 | DRM_ERROR("buffer used for overlay image can not be tiled\n"); |
1103 | if (ret != 0) | 1163 | ret = -EINVAL; |
1104 | goto out_unlock; | 1164 | goto out_unlock; |
1105 | } | 1165 | } |
1106 | 1166 | ||
1167 | ret = intel_overlay_recover_from_interrupt(overlay); | ||
1168 | if (ret != 0) | ||
1169 | goto out_unlock; | ||
1170 | |||
1107 | if (overlay->crtc != crtc) { | 1171 | if (overlay->crtc != crtc) { |
1108 | struct drm_display_mode *mode = &crtc->base.mode; | 1172 | struct drm_display_mode *mode = &crtc->base.mode; |
1109 | ret = intel_overlay_switch_off(overlay); | 1173 | ret = intel_overlay_switch_off(overlay); |
@@ -1117,9 +1181,9 @@ int intel_overlay_put_image(struct drm_device *dev, void *data, | |||
1117 | overlay->crtc = crtc; | 1181 | overlay->crtc = crtc; |
1118 | crtc->overlay = overlay; | 1182 | crtc->overlay = overlay; |
1119 | 1183 | ||
1120 | if (intel_panel_fitter_pipe(dev) == crtc->pipe | 1184 | /* line too wide, i.e. one-line-mode */ |
1121 | /* and line to wide, i.e. one-line-mode */ | 1185 | if (mode->hdisplay > 1024 && |
1122 | && mode->hdisplay > 1024) { | 1186 | intel_panel_fitter_pipe(dev) == crtc->pipe) { |
1123 | overlay->pfit_active = 1; | 1187 | overlay->pfit_active = 1; |
1124 | update_pfit_vscale_ratio(overlay); | 1188 | update_pfit_vscale_ratio(overlay); |
1125 | } else | 1189 | } else |
@@ -1132,10 +1196,10 @@ int intel_overlay_put_image(struct drm_device *dev, void *data, | |||
1132 | 1196 | ||
1133 | if (overlay->pfit_active) { | 1197 | if (overlay->pfit_active) { |
1134 | params->dst_y = ((((u32)put_image_rec->dst_y) << 12) / | 1198 | params->dst_y = ((((u32)put_image_rec->dst_y) << 12) / |
1135 | overlay->pfit_vscale_ratio); | 1199 | overlay->pfit_vscale_ratio); |
1136 | /* shifting right rounds downwards, so add 1 */ | 1200 | /* shifting right rounds downwards, so add 1 */ |
1137 | params->dst_h = ((((u32)put_image_rec->dst_height) << 12) / | 1201 | params->dst_h = ((((u32)put_image_rec->dst_height) << 12) / |
1138 | overlay->pfit_vscale_ratio) + 1; | 1202 | overlay->pfit_vscale_ratio) + 1; |
1139 | } else { | 1203 | } else { |
1140 | params->dst_y = put_image_rec->dst_y; | 1204 | params->dst_y = put_image_rec->dst_y; |
1141 | params->dst_h = put_image_rec->dst_height; | 1205 | params->dst_h = put_image_rec->dst_height; |
@@ -1147,8 +1211,8 @@ int intel_overlay_put_image(struct drm_device *dev, void *data, | |||
1147 | params->src_h = put_image_rec->src_height; | 1211 | params->src_h = put_image_rec->src_height; |
1148 | params->src_scan_w = put_image_rec->src_scan_width; | 1212 | params->src_scan_w = put_image_rec->src_scan_width; |
1149 | params->src_scan_h = put_image_rec->src_scan_height; | 1213 | params->src_scan_h = put_image_rec->src_scan_height; |
1150 | if (params->src_scan_h > params->src_h | 1214 | if (params->src_scan_h > params->src_h || |
1151 | || params->src_scan_w > params->src_w) { | 1215 | params->src_scan_w > params->src_w) { |
1152 | ret = -EINVAL; | 1216 | ret = -EINVAL; |
1153 | goto out_unlock; | 1217 | goto out_unlock; |
1154 | } | 1218 | } |
@@ -1182,7 +1246,7 @@ int intel_overlay_put_image(struct drm_device *dev, void *data, | |||
1182 | out_unlock: | 1246 | out_unlock: |
1183 | mutex_unlock(&dev->struct_mutex); | 1247 | mutex_unlock(&dev->struct_mutex); |
1184 | mutex_unlock(&dev->mode_config.mutex); | 1248 | mutex_unlock(&dev->mode_config.mutex); |
1185 | drm_gem_object_unreference_unlocked(new_bo); | 1249 | drm_gem_object_unreference_unlocked(&new_bo->base); |
1186 | out_free: | 1250 | out_free: |
1187 | kfree(params); | 1251 | kfree(params); |
1188 | 1252 | ||
@@ -1204,7 +1268,7 @@ static bool check_gamma_bounds(u32 gamma1, u32 gamma2) | |||
1204 | return false; | 1268 | return false; |
1205 | 1269 | ||
1206 | for (i = 0; i < 3; i++) { | 1270 | for (i = 0; i < 3; i++) { |
1207 | if (((gamma1 >> i * 8) & 0xff) >= ((gamma2 >> i*8) & 0xff)) | 1271 | if (((gamma1 >> i*8) & 0xff) >= ((gamma2 >> i*8) & 0xff)) |
1208 | return false; | 1272 | return false; |
1209 | } | 1273 | } |
1210 | 1274 | ||
@@ -1225,16 +1289,18 @@ static bool check_gamma5_errata(u32 gamma5) | |||
1225 | 1289 | ||
1226 | static int check_gamma(struct drm_intel_overlay_attrs *attrs) | 1290 | static int check_gamma(struct drm_intel_overlay_attrs *attrs) |
1227 | { | 1291 | { |
1228 | if (!check_gamma_bounds(0, attrs->gamma0) | 1292 | if (!check_gamma_bounds(0, attrs->gamma0) || |
1229 | || !check_gamma_bounds(attrs->gamma0, attrs->gamma1) | 1293 | !check_gamma_bounds(attrs->gamma0, attrs->gamma1) || |
1230 | || !check_gamma_bounds(attrs->gamma1, attrs->gamma2) | 1294 | !check_gamma_bounds(attrs->gamma1, attrs->gamma2) || |
1231 | || !check_gamma_bounds(attrs->gamma2, attrs->gamma3) | 1295 | !check_gamma_bounds(attrs->gamma2, attrs->gamma3) || |
1232 | || !check_gamma_bounds(attrs->gamma3, attrs->gamma4) | 1296 | !check_gamma_bounds(attrs->gamma3, attrs->gamma4) || |
1233 | || !check_gamma_bounds(attrs->gamma4, attrs->gamma5) | 1297 | !check_gamma_bounds(attrs->gamma4, attrs->gamma5) || |
1234 | || !check_gamma_bounds(attrs->gamma5, 0x00ffffff)) | 1298 | !check_gamma_bounds(attrs->gamma5, 0x00ffffff)) |
1235 | return -EINVAL; | 1299 | return -EINVAL; |
1300 | |||
1236 | if (!check_gamma5_errata(attrs->gamma5)) | 1301 | if (!check_gamma5_errata(attrs->gamma5)) |
1237 | return -EINVAL; | 1302 | return -EINVAL; |
1303 | |||
1238 | return 0; | 1304 | return 0; |
1239 | } | 1305 | } |
1240 | 1306 | ||
@@ -1261,13 +1327,14 @@ int intel_overlay_attrs(struct drm_device *dev, void *data, | |||
1261 | mutex_lock(&dev->mode_config.mutex); | 1327 | mutex_lock(&dev->mode_config.mutex); |
1262 | mutex_lock(&dev->struct_mutex); | 1328 | mutex_lock(&dev->struct_mutex); |
1263 | 1329 | ||
1330 | ret = -EINVAL; | ||
1264 | if (!(attrs->flags & I915_OVERLAY_UPDATE_ATTRS)) { | 1331 | if (!(attrs->flags & I915_OVERLAY_UPDATE_ATTRS)) { |
1265 | attrs->color_key = overlay->color_key; | 1332 | attrs->color_key = overlay->color_key; |
1266 | attrs->brightness = overlay->brightness; | 1333 | attrs->brightness = overlay->brightness; |
1267 | attrs->contrast = overlay->contrast; | 1334 | attrs->contrast = overlay->contrast; |
1268 | attrs->saturation = overlay->saturation; | 1335 | attrs->saturation = overlay->saturation; |
1269 | 1336 | ||
1270 | if (IS_I9XX(dev)) { | 1337 | if (!IS_GEN2(dev)) { |
1271 | attrs->gamma0 = I915_READ(OGAMC0); | 1338 | attrs->gamma0 = I915_READ(OGAMC0); |
1272 | attrs->gamma1 = I915_READ(OGAMC1); | 1339 | attrs->gamma1 = I915_READ(OGAMC1); |
1273 | attrs->gamma2 = I915_READ(OGAMC2); | 1340 | attrs->gamma2 = I915_READ(OGAMC2); |
@@ -1275,29 +1342,20 @@ int intel_overlay_attrs(struct drm_device *dev, void *data, | |||
1275 | attrs->gamma4 = I915_READ(OGAMC4); | 1342 | attrs->gamma4 = I915_READ(OGAMC4); |
1276 | attrs->gamma5 = I915_READ(OGAMC5); | 1343 | attrs->gamma5 = I915_READ(OGAMC5); |
1277 | } | 1344 | } |
1278 | ret = 0; | ||
1279 | } else { | 1345 | } else { |
1280 | overlay->color_key = attrs->color_key; | 1346 | if (attrs->brightness < -128 || attrs->brightness > 127) |
1281 | if (attrs->brightness >= -128 && attrs->brightness <= 127) { | ||
1282 | overlay->brightness = attrs->brightness; | ||
1283 | } else { | ||
1284 | ret = -EINVAL; | ||
1285 | goto out_unlock; | 1347 | goto out_unlock; |
1286 | } | 1348 | if (attrs->contrast > 255) |
1287 | if (attrs->contrast <= 255) { | ||
1288 | overlay->contrast = attrs->contrast; | ||
1289 | } else { | ||
1290 | ret = -EINVAL; | ||
1291 | goto out_unlock; | 1349 | goto out_unlock; |
1292 | } | 1350 | if (attrs->saturation > 1023) |
1293 | if (attrs->saturation <= 1023) { | ||
1294 | overlay->saturation = attrs->saturation; | ||
1295 | } else { | ||
1296 | ret = -EINVAL; | ||
1297 | goto out_unlock; | 1351 | goto out_unlock; |
1298 | } | ||
1299 | 1352 | ||
1300 | regs = intel_overlay_map_regs_atomic(overlay); | 1353 | overlay->color_key = attrs->color_key; |
1354 | overlay->brightness = attrs->brightness; | ||
1355 | overlay->contrast = attrs->contrast; | ||
1356 | overlay->saturation = attrs->saturation; | ||
1357 | |||
1358 | regs = intel_overlay_map_regs(overlay); | ||
1301 | if (!regs) { | 1359 | if (!regs) { |
1302 | ret = -ENOMEM; | 1360 | ret = -ENOMEM; |
1303 | goto out_unlock; | 1361 | goto out_unlock; |
@@ -1305,13 +1363,11 @@ int intel_overlay_attrs(struct drm_device *dev, void *data, | |||
1305 | 1363 | ||
1306 | update_reg_attrs(overlay, regs); | 1364 | update_reg_attrs(overlay, regs); |
1307 | 1365 | ||
1308 | intel_overlay_unmap_regs_atomic(overlay); | 1366 | intel_overlay_unmap_regs(overlay, regs); |
1309 | 1367 | ||
1310 | if (attrs->flags & I915_OVERLAY_UPDATE_GAMMA) { | 1368 | if (attrs->flags & I915_OVERLAY_UPDATE_GAMMA) { |
1311 | if (!IS_I9XX(dev)) { | 1369 | if (IS_GEN2(dev)) |
1312 | ret = -EINVAL; | ||
1313 | goto out_unlock; | 1370 | goto out_unlock; |
1314 | } | ||
1315 | 1371 | ||
1316 | if (overlay->active) { | 1372 | if (overlay->active) { |
1317 | ret = -EBUSY; | 1373 | ret = -EBUSY; |
@@ -1319,7 +1375,7 @@ int intel_overlay_attrs(struct drm_device *dev, void *data, | |||
1319 | } | 1375 | } |
1320 | 1376 | ||
1321 | ret = check_gamma(attrs); | 1377 | ret = check_gamma(attrs); |
1322 | if (ret != 0) | 1378 | if (ret) |
1323 | goto out_unlock; | 1379 | goto out_unlock; |
1324 | 1380 | ||
1325 | I915_WRITE(OGAMC0, attrs->gamma0); | 1381 | I915_WRITE(OGAMC0, attrs->gamma0); |
@@ -1329,9 +1385,9 @@ int intel_overlay_attrs(struct drm_device *dev, void *data, | |||
1329 | I915_WRITE(OGAMC4, attrs->gamma4); | 1385 | I915_WRITE(OGAMC4, attrs->gamma4); |
1330 | I915_WRITE(OGAMC5, attrs->gamma5); | 1386 | I915_WRITE(OGAMC5, attrs->gamma5); |
1331 | } | 1387 | } |
1332 | ret = 0; | ||
1333 | } | 1388 | } |
1334 | 1389 | ||
1390 | ret = 0; | ||
1335 | out_unlock: | 1391 | out_unlock: |
1336 | mutex_unlock(&dev->struct_mutex); | 1392 | mutex_unlock(&dev->struct_mutex); |
1337 | mutex_unlock(&dev->mode_config.mutex); | 1393 | mutex_unlock(&dev->mode_config.mutex); |
@@ -1343,39 +1399,50 @@ void intel_setup_overlay(struct drm_device *dev) | |||
1343 | { | 1399 | { |
1344 | drm_i915_private_t *dev_priv = dev->dev_private; | 1400 | drm_i915_private_t *dev_priv = dev->dev_private; |
1345 | struct intel_overlay *overlay; | 1401 | struct intel_overlay *overlay; |
1346 | struct drm_gem_object *reg_bo; | 1402 | struct drm_i915_gem_object *reg_bo; |
1347 | struct overlay_registers *regs; | 1403 | struct overlay_registers *regs; |
1348 | int ret; | 1404 | int ret; |
1349 | 1405 | ||
1350 | if (!OVERLAY_EXISTS(dev)) | 1406 | if (!HAS_OVERLAY(dev)) |
1351 | return; | 1407 | return; |
1352 | 1408 | ||
1353 | overlay = kzalloc(sizeof(struct intel_overlay), GFP_KERNEL); | 1409 | overlay = kzalloc(sizeof(struct intel_overlay), GFP_KERNEL); |
1354 | if (!overlay) | 1410 | if (!overlay) |
1355 | return; | 1411 | return; |
1412 | |||
1413 | mutex_lock(&dev->struct_mutex); | ||
1414 | if (WARN_ON(dev_priv->overlay)) | ||
1415 | goto out_free; | ||
1416 | |||
1356 | overlay->dev = dev; | 1417 | overlay->dev = dev; |
1357 | 1418 | ||
1358 | reg_bo = i915_gem_alloc_object(dev, PAGE_SIZE); | 1419 | reg_bo = i915_gem_alloc_object(dev, PAGE_SIZE); |
1359 | if (!reg_bo) | 1420 | if (!reg_bo) |
1360 | goto out_free; | 1421 | goto out_free; |
1361 | overlay->reg_bo = to_intel_bo(reg_bo); | 1422 | overlay->reg_bo = reg_bo; |
1362 | 1423 | ||
1363 | if (OVERLAY_NONPHYSICAL(dev)) { | 1424 | if (OVERLAY_NEEDS_PHYSICAL(dev)) { |
1364 | ret = i915_gem_object_pin(reg_bo, PAGE_SIZE); | ||
1365 | if (ret) { | ||
1366 | DRM_ERROR("failed to pin overlay register bo\n"); | ||
1367 | goto out_free_bo; | ||
1368 | } | ||
1369 | overlay->flip_addr = overlay->reg_bo->gtt_offset; | ||
1370 | } else { | ||
1371 | ret = i915_gem_attach_phys_object(dev, reg_bo, | 1425 | ret = i915_gem_attach_phys_object(dev, reg_bo, |
1372 | I915_GEM_PHYS_OVERLAY_REGS, | 1426 | I915_GEM_PHYS_OVERLAY_REGS, |
1373 | 0); | 1427 | PAGE_SIZE); |
1374 | if (ret) { | 1428 | if (ret) { |
1375 | DRM_ERROR("failed to attach phys overlay regs\n"); | 1429 | DRM_ERROR("failed to attach phys overlay regs\n"); |
1376 | goto out_free_bo; | 1430 | goto out_free_bo; |
1377 | } | 1431 | } |
1378 | overlay->flip_addr = overlay->reg_bo->phys_obj->handle->busaddr; | 1432 | overlay->flip_addr = reg_bo->phys_obj->handle->busaddr; |
1433 | } else { | ||
1434 | ret = i915_gem_object_pin(reg_bo, PAGE_SIZE, true); | ||
1435 | if (ret) { | ||
1436 | DRM_ERROR("failed to pin overlay register bo\n"); | ||
1437 | goto out_free_bo; | ||
1438 | } | ||
1439 | overlay->flip_addr = reg_bo->gtt_offset; | ||
1440 | |||
1441 | ret = i915_gem_object_set_to_gtt_domain(reg_bo, true); | ||
1442 | if (ret) { | ||
1443 | DRM_ERROR("failed to move overlay register bo into the GTT\n"); | ||
1444 | goto out_unpin_bo; | ||
1445 | } | ||
1379 | } | 1446 | } |
1380 | 1447 | ||
1381 | /* init all values */ | 1448 | /* init all values */ |
@@ -1384,42 +1451,51 @@ void intel_setup_overlay(struct drm_device *dev) | |||
1384 | overlay->contrast = 75; | 1451 | overlay->contrast = 75; |
1385 | overlay->saturation = 146; | 1452 | overlay->saturation = 146; |
1386 | 1453 | ||
1387 | regs = intel_overlay_map_regs_atomic(overlay); | 1454 | regs = intel_overlay_map_regs(overlay); |
1388 | if (!regs) | 1455 | if (!regs) |
1389 | goto out_free_bo; | 1456 | goto out_unpin_bo; |
1390 | 1457 | ||
1391 | memset(regs, 0, sizeof(struct overlay_registers)); | 1458 | memset(regs, 0, sizeof(struct overlay_registers)); |
1392 | update_polyphase_filter(regs); | 1459 | update_polyphase_filter(regs); |
1393 | |||
1394 | update_reg_attrs(overlay, regs); | 1460 | update_reg_attrs(overlay, regs); |
1395 | 1461 | ||
1396 | intel_overlay_unmap_regs_atomic(overlay); | 1462 | intel_overlay_unmap_regs(overlay, regs); |
1397 | 1463 | ||
1398 | dev_priv->overlay = overlay; | 1464 | dev_priv->overlay = overlay; |
1465 | mutex_unlock(&dev->struct_mutex); | ||
1399 | DRM_INFO("initialized overlay support\n"); | 1466 | DRM_INFO("initialized overlay support\n"); |
1400 | return; | 1467 | return; |
1401 | 1468 | ||
1469 | out_unpin_bo: | ||
1470 | if (!OVERLAY_NEEDS_PHYSICAL(dev)) | ||
1471 | i915_gem_object_unpin(reg_bo); | ||
1402 | out_free_bo: | 1472 | out_free_bo: |
1403 | drm_gem_object_unreference(reg_bo); | 1473 | drm_gem_object_unreference(®_bo->base); |
1404 | out_free: | 1474 | out_free: |
1475 | mutex_unlock(&dev->struct_mutex); | ||
1405 | kfree(overlay); | 1476 | kfree(overlay); |
1406 | return; | 1477 | return; |
1407 | } | 1478 | } |
1408 | 1479 | ||
1409 | void intel_cleanup_overlay(struct drm_device *dev) | 1480 | void intel_cleanup_overlay(struct drm_device *dev) |
1410 | { | 1481 | { |
1411 | drm_i915_private_t *dev_priv = dev->dev_private; | 1482 | drm_i915_private_t *dev_priv = dev->dev_private; |
1412 | 1483 | ||
1413 | if (dev_priv->overlay) { | 1484 | if (!dev_priv->overlay) |
1414 | /* The bo's should be free'd by the generic code already. | 1485 | return; |
1415 | * Furthermore modesetting teardown happens beforehand so the | ||
1416 | * hardware should be off already */ | ||
1417 | BUG_ON(dev_priv->overlay->active); | ||
1418 | 1486 | ||
1419 | kfree(dev_priv->overlay); | 1487 | /* The bo's should be free'd by the generic code already. |
1420 | } | 1488 | * Furthermore modesetting teardown happens beforehand so the |
1489 | * hardware should be off already */ | ||
1490 | BUG_ON(dev_priv->overlay->active); | ||
1491 | |||
1492 | drm_gem_object_unreference_unlocked(&dev_priv->overlay->reg_bo->base); | ||
1493 | kfree(dev_priv->overlay); | ||
1421 | } | 1494 | } |
1422 | 1495 | ||
1496 | #ifdef CONFIG_DEBUG_FS | ||
1497 | #include <linux/seq_file.h> | ||
1498 | |||
1423 | struct intel_overlay_error_state { | 1499 | struct intel_overlay_error_state { |
1424 | struct overlay_registers regs; | 1500 | struct overlay_registers regs; |
1425 | unsigned long base; | 1501 | unsigned long base; |
@@ -1427,6 +1503,29 @@ struct intel_overlay_error_state { | |||
1427 | u32 isr; | 1503 | u32 isr; |
1428 | }; | 1504 | }; |
1429 | 1505 | ||
1506 | static struct overlay_registers * | ||
1507 | intel_overlay_map_regs_atomic(struct intel_overlay *overlay) | ||
1508 | { | ||
1509 | drm_i915_private_t *dev_priv = overlay->dev->dev_private; | ||
1510 | struct overlay_registers *regs; | ||
1511 | |||
1512 | if (OVERLAY_NEEDS_PHYSICAL(overlay->dev)) | ||
1513 | regs = overlay->reg_bo->phys_obj->handle->vaddr; | ||
1514 | else | ||
1515 | regs = io_mapping_map_atomic_wc(dev_priv->mm.gtt_mapping, | ||
1516 | overlay->reg_bo->gtt_offset); | ||
1517 | |||
1518 | return regs; | ||
1519 | } | ||
1520 | |||
1521 | static void intel_overlay_unmap_regs_atomic(struct intel_overlay *overlay, | ||
1522 | struct overlay_registers *regs) | ||
1523 | { | ||
1524 | if (!OVERLAY_NEEDS_PHYSICAL(overlay->dev)) | ||
1525 | io_mapping_unmap_atomic(regs); | ||
1526 | } | ||
1527 | |||
1528 | |||
1430 | struct intel_overlay_error_state * | 1529 | struct intel_overlay_error_state * |
1431 | intel_overlay_capture_error_state(struct drm_device *dev) | 1530 | intel_overlay_capture_error_state(struct drm_device *dev) |
1432 | { | 1531 | { |
@@ -1444,17 +1543,17 @@ intel_overlay_capture_error_state(struct drm_device *dev) | |||
1444 | 1543 | ||
1445 | error->dovsta = I915_READ(DOVSTA); | 1544 | error->dovsta = I915_READ(DOVSTA); |
1446 | error->isr = I915_READ(ISR); | 1545 | error->isr = I915_READ(ISR); |
1447 | if (OVERLAY_NONPHYSICAL(overlay->dev)) | 1546 | if (OVERLAY_NEEDS_PHYSICAL(overlay->dev)) |
1448 | error->base = (long) overlay->reg_bo->gtt_offset; | ||
1449 | else | ||
1450 | error->base = (long) overlay->reg_bo->phys_obj->handle->vaddr; | 1547 | error->base = (long) overlay->reg_bo->phys_obj->handle->vaddr; |
1548 | else | ||
1549 | error->base = (long) overlay->reg_bo->gtt_offset; | ||
1451 | 1550 | ||
1452 | regs = intel_overlay_map_regs_atomic(overlay); | 1551 | regs = intel_overlay_map_regs_atomic(overlay); |
1453 | if (!regs) | 1552 | if (!regs) |
1454 | goto err; | 1553 | goto err; |
1455 | 1554 | ||
1456 | memcpy_fromio(&error->regs, regs, sizeof(struct overlay_registers)); | 1555 | memcpy_fromio(&error->regs, regs, sizeof(struct overlay_registers)); |
1457 | intel_overlay_unmap_regs_atomic(overlay); | 1556 | intel_overlay_unmap_regs_atomic(overlay, regs); |
1458 | 1557 | ||
1459 | return error; | 1558 | return error; |
1460 | 1559 | ||
@@ -1515,3 +1614,4 @@ intel_overlay_print_error_state(struct seq_file *m, struct intel_overlay_error_s | |||
1515 | P(UVSCALEV); | 1614 | P(UVSCALEV); |
1516 | #undef P | 1615 | #undef P |
1517 | } | 1616 | } |
1617 | #endif | ||