diff options
author | Patrik Jakobsson <patrik.r.jakobsson@gmail.com> | 2013-07-10 17:43:01 -0400 |
---|---|---|
committer | Patrik Jakobsson <patrik.r.jakobsson@gmail.com> | 2013-07-23 19:47:27 -0400 |
commit | 38945be630a5848ffc75f2f9027cbb211dec3982 (patch) | |
tree | 8ea9c516686ef6f718e7579fe4f28ead00991266 | |
parent | b1255b884914920f4086448ec4930e814e97afde (diff) |
drm/gma500: Add generic cursor functions
Signed-off-by: Patrik Jakobsson <patrik.r.jakobsson@gmail.com>
-rw-r--r-- | drivers/gpu/drm/gma500/gma_display.c | 151 | ||||
-rw-r--r-- | drivers/gpu/drm/gma500/gma_display.h | 5 |
2 files changed, 156 insertions, 0 deletions
diff --git a/drivers/gpu/drm/gma500/gma_display.c b/drivers/gpu/drm/gma500/gma_display.c index 7a0888a64a33..40894c206098 100644 --- a/drivers/gpu/drm/gma500/gma_display.c +++ b/drivers/gpu/drm/gma500/gma_display.c | |||
@@ -327,6 +327,157 @@ void gma_crtc_dpms(struct drm_crtc *crtc, int mode) | |||
327 | REG_WRITE(DSPARB, 0x3F3E); | 327 | REG_WRITE(DSPARB, 0x3F3E); |
328 | } | 328 | } |
329 | 329 | ||
330 | int gma_crtc_cursor_set(struct drm_crtc *crtc, | ||
331 | struct drm_file *file_priv, | ||
332 | uint32_t handle, | ||
333 | uint32_t width, uint32_t height) | ||
334 | { | ||
335 | struct drm_device *dev = crtc->dev; | ||
336 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
337 | struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); | ||
338 | int pipe = psb_intel_crtc->pipe; | ||
339 | uint32_t control = (pipe == 0) ? CURACNTR : CURBCNTR; | ||
340 | uint32_t base = (pipe == 0) ? CURABASE : CURBBASE; | ||
341 | uint32_t temp; | ||
342 | size_t addr = 0; | ||
343 | struct gtt_range *gt; | ||
344 | struct gtt_range *cursor_gt = psb_intel_crtc->cursor_gt; | ||
345 | struct drm_gem_object *obj; | ||
346 | void *tmp_dst, *tmp_src; | ||
347 | int ret = 0, i, cursor_pages; | ||
348 | |||
349 | /* If we didn't get a handle then turn the cursor off */ | ||
350 | if (!handle) { | ||
351 | temp = CURSOR_MODE_DISABLE; | ||
352 | |||
353 | if (gma_power_begin(dev, false)) { | ||
354 | REG_WRITE(control, temp); | ||
355 | REG_WRITE(base, 0); | ||
356 | gma_power_end(dev); | ||
357 | } | ||
358 | |||
359 | /* Unpin the old GEM object */ | ||
360 | if (psb_intel_crtc->cursor_obj) { | ||
361 | gt = container_of(psb_intel_crtc->cursor_obj, | ||
362 | struct gtt_range, gem); | ||
363 | psb_gtt_unpin(gt); | ||
364 | drm_gem_object_unreference(psb_intel_crtc->cursor_obj); | ||
365 | psb_intel_crtc->cursor_obj = NULL; | ||
366 | } | ||
367 | |||
368 | return 0; | ||
369 | } | ||
370 | |||
371 | /* Currently we only support 64x64 cursors */ | ||
372 | if (width != 64 || height != 64) { | ||
373 | dev_dbg(dev->dev, "We currently only support 64x64 cursors\n"); | ||
374 | return -EINVAL; | ||
375 | } | ||
376 | |||
377 | obj = drm_gem_object_lookup(dev, file_priv, handle); | ||
378 | if (!obj) | ||
379 | return -ENOENT; | ||
380 | |||
381 | if (obj->size < width * height * 4) { | ||
382 | dev_dbg(dev->dev, "Buffer is too small\n"); | ||
383 | ret = -ENOMEM; | ||
384 | goto unref_cursor; | ||
385 | } | ||
386 | |||
387 | gt = container_of(obj, struct gtt_range, gem); | ||
388 | |||
389 | /* Pin the memory into the GTT */ | ||
390 | ret = psb_gtt_pin(gt); | ||
391 | if (ret) { | ||
392 | dev_err(dev->dev, "Can not pin down handle 0x%x\n", handle); | ||
393 | goto unref_cursor; | ||
394 | } | ||
395 | |||
396 | if (dev_priv->ops->cursor_needs_phys) { | ||
397 | if (cursor_gt == NULL) { | ||
398 | dev_err(dev->dev, "No hardware cursor mem available"); | ||
399 | ret = -ENOMEM; | ||
400 | goto unref_cursor; | ||
401 | } | ||
402 | |||
403 | /* Prevent overflow */ | ||
404 | if (gt->npage > 4) | ||
405 | cursor_pages = 4; | ||
406 | else | ||
407 | cursor_pages = gt->npage; | ||
408 | |||
409 | /* Copy the cursor to cursor mem */ | ||
410 | tmp_dst = dev_priv->vram_addr + cursor_gt->offset; | ||
411 | for (i = 0; i < cursor_pages; i++) { | ||
412 | tmp_src = kmap(gt->pages[i]); | ||
413 | memcpy(tmp_dst, tmp_src, PAGE_SIZE); | ||
414 | kunmap(gt->pages[i]); | ||
415 | tmp_dst += PAGE_SIZE; | ||
416 | } | ||
417 | |||
418 | addr = psb_intel_crtc->cursor_addr; | ||
419 | } else { | ||
420 | addr = gt->offset; | ||
421 | psb_intel_crtc->cursor_addr = addr; | ||
422 | } | ||
423 | |||
424 | temp = 0; | ||
425 | /* set the pipe for the cursor */ | ||
426 | temp |= (pipe << 28); | ||
427 | temp |= CURSOR_MODE_64_ARGB_AX | MCURSOR_GAMMA_ENABLE; | ||
428 | |||
429 | if (gma_power_begin(dev, false)) { | ||
430 | REG_WRITE(control, temp); | ||
431 | REG_WRITE(base, addr); | ||
432 | gma_power_end(dev); | ||
433 | } | ||
434 | |||
435 | /* unpin the old bo */ | ||
436 | if (psb_intel_crtc->cursor_obj) { | ||
437 | gt = container_of(psb_intel_crtc->cursor_obj, | ||
438 | struct gtt_range, gem); | ||
439 | psb_gtt_unpin(gt); | ||
440 | drm_gem_object_unreference(psb_intel_crtc->cursor_obj); | ||
441 | } | ||
442 | |||
443 | psb_intel_crtc->cursor_obj = obj; | ||
444 | return ret; | ||
445 | |||
446 | unref_cursor: | ||
447 | drm_gem_object_unreference(obj); | ||
448 | return ret; | ||
449 | } | ||
450 | |||
451 | int gma_crtc_cursor_move(struct drm_crtc *crtc, int x, int y) | ||
452 | { | ||
453 | struct drm_device *dev = crtc->dev; | ||
454 | struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); | ||
455 | int pipe = psb_intel_crtc->pipe; | ||
456 | uint32_t temp = 0; | ||
457 | uint32_t addr; | ||
458 | |||
459 | if (x < 0) { | ||
460 | temp |= (CURSOR_POS_SIGN << CURSOR_X_SHIFT); | ||
461 | x = -x; | ||
462 | } | ||
463 | if (y < 0) { | ||
464 | temp |= (CURSOR_POS_SIGN << CURSOR_Y_SHIFT); | ||
465 | y = -y; | ||
466 | } | ||
467 | |||
468 | temp |= ((x & CURSOR_POS_MASK) << CURSOR_X_SHIFT); | ||
469 | temp |= ((y & CURSOR_POS_MASK) << CURSOR_Y_SHIFT); | ||
470 | |||
471 | addr = psb_intel_crtc->cursor_addr; | ||
472 | |||
473 | if (gma_power_begin(dev, false)) { | ||
474 | REG_WRITE((pipe == 0) ? CURAPOS : CURBPOS, temp); | ||
475 | REG_WRITE((pipe == 0) ? CURABASE : CURBBASE, addr); | ||
476 | gma_power_end(dev); | ||
477 | } | ||
478 | return 0; | ||
479 | } | ||
480 | |||
330 | bool gma_crtc_mode_fixup(struct drm_crtc *crtc, | 481 | bool gma_crtc_mode_fixup(struct drm_crtc *crtc, |
331 | const struct drm_display_mode *mode, | 482 | const struct drm_display_mode *mode, |
332 | struct drm_display_mode *adjusted_mode) | 483 | struct drm_display_mode *adjusted_mode) |
diff --git a/drivers/gpu/drm/gma500/gma_display.h b/drivers/gpu/drm/gma500/gma_display.h index 665164d41224..0d3b6074ca99 100644 --- a/drivers/gpu/drm/gma500/gma_display.h +++ b/drivers/gpu/drm/gma500/gma_display.h | |||
@@ -64,6 +64,11 @@ extern bool gma_pipe_has_type(struct drm_crtc *crtc, int type); | |||
64 | extern void gma_wait_for_vblank(struct drm_device *dev); | 64 | extern void gma_wait_for_vblank(struct drm_device *dev); |
65 | extern int gma_pipe_set_base(struct drm_crtc *crtc, int x, int y, | 65 | extern int gma_pipe_set_base(struct drm_crtc *crtc, int x, int y, |
66 | struct drm_framebuffer *old_fb); | 66 | struct drm_framebuffer *old_fb); |
67 | extern int gma_crtc_cursor_set(struct drm_crtc *crtc, | ||
68 | struct drm_file *file_priv, | ||
69 | uint32_t handle, | ||
70 | uint32_t width, uint32_t height); | ||
71 | extern int gma_crtc_cursor_move(struct drm_crtc *crtc, int x, int y); | ||
67 | extern void gma_crtc_load_lut(struct drm_crtc *crtc); | 72 | extern void gma_crtc_load_lut(struct drm_crtc *crtc); |
68 | extern void gma_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green, | 73 | extern void gma_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green, |
69 | u16 *blue, u32 start, u32 size); | 74 | u16 *blue, u32 start, u32 size); |