kolibrios/drivers/video/drm/radeon/rdisplay.c

208 lines
5.0 KiB
C
Raw Normal View History

#include <stdint.h>
#include <drm/drmP.h>
#include <drm.h>
#include <drm_mm.h>
#include "radeon_drm.h"
#include "radeon.h"
#include "radeon_object.h"
#include "display.h"
display_t *rdisplay;
static cursor_t* __stdcall select_cursor(cursor_t *cursor);
static void __stdcall move_cursor(cursor_t *cursor, int x, int y);
int init_cursor(cursor_t *cursor)
{
struct radeon_device *rdev;
uint32_t *bits;
uint32_t *src;
int i,j;
int r;
rdev = (struct radeon_device *)rdisplay->ddev->dev_private;
r = radeon_object_create(rdev, NULL, CURSOR_WIDTH*CURSOR_HEIGHT*4,
false,
RADEON_GEM_DOMAIN_VRAM,
false, &cursor->robj);
if (unlikely(r != 0))
return r;
radeon_object_pin(cursor->robj, TTM_PL_FLAG_VRAM, NULL);
r = radeon_object_kmap(cursor->robj, &bits);
if (r) {
DRM_ERROR("radeon: failed to map cursor (%d).\n", r);
return r;
};
src = cursor->data;
for(i = 0; i < 32; i++)
{
for(j = 0; j < 32; j++)
*bits++ = *src++;
for(j = 32; j < CURSOR_WIDTH; j++)
*bits++ = 0;
}
for(i = 0; i < CURSOR_WIDTH*(CURSOR_HEIGHT-32); i++)
*bits++ = 0;
radeon_object_kunmap(cursor->robj);
return 0;
};
static void radeon_show_cursor()
{
struct radeon_device *rdev = (struct radeon_device *)rdisplay->ddev->dev_private;
if (ASIC_IS_AVIVO(rdev)) {
WREG32(RADEON_MM_INDEX, AVIVO_D1CUR_CONTROL);
WREG32(RADEON_MM_DATA, AVIVO_D1CURSOR_EN |
(AVIVO_D1CURSOR_MODE_24BPP << AVIVO_D1CURSOR_MODE_SHIFT));
} else {
WREG32(RADEON_MM_INDEX, RADEON_CRTC_GEN_CNTL);
WREG32_P(RADEON_MM_DATA, (RADEON_CRTC_CUR_EN |
(RADEON_CRTC_CUR_MODE_24BPP << RADEON_CRTC_CUR_MODE_SHIFT)),
~(RADEON_CRTC_CUR_EN | RADEON_CRTC_CUR_MODE_MASK));
}
}
cursor_t* __stdcall select_cursor(cursor_t *cursor)
{
struct radeon_device *rdev;
cursor_t *old;
uint32_t gpu_addr;
rdev = (struct radeon_device *)rdisplay->ddev->dev_private;
old = rdisplay->cursor;
rdisplay->cursor = cursor;
gpu_addr = cursor->robj->gpu_addr;
if (ASIC_IS_AVIVO(rdev))
WREG32(AVIVO_D1CUR_SURFACE_ADDRESS, gpu_addr);
else {
WREG32(RADEON_CUR_OFFSET, gpu_addr - rdev->mc.vram_location);
}
return old;
};
static void radeon_lock_cursor(bool lock)
{
struct radeon_device *rdev;
rdev = (struct radeon_device *)rdisplay->ddev->dev_private;
uint32_t cur_lock;
if (ASIC_IS_AVIVO(rdev)) {
cur_lock = RREG32(AVIVO_D1CUR_UPDATE);
if (lock)
cur_lock |= AVIVO_D1CURSOR_UPDATE_LOCK;
else
cur_lock &= ~AVIVO_D1CURSOR_UPDATE_LOCK;
WREG32(AVIVO_D1CUR_UPDATE, cur_lock);
} else {
cur_lock = RREG32(RADEON_CUR_OFFSET);
if (lock)
cur_lock |= RADEON_CUR_LOCK;
else
cur_lock &= ~RADEON_CUR_LOCK;
WREG32(RADEON_CUR_OFFSET, cur_lock);
}
}
void __stdcall move_cursor(cursor_t *cursor, int x, int y)
{
struct radeon_device *rdev;
rdev = (struct radeon_device *)rdisplay->ddev->dev_private;
int hot_x = cursor->hot_x;
int hot_y = cursor->hot_y;
radeon_lock_cursor(true);
if (ASIC_IS_AVIVO(rdev))
{
int w = 32;
int i = 0;
WREG32(AVIVO_D1CUR_POSITION, (x << 16) | y);
WREG32(AVIVO_D1CUR_HOT_SPOT, (hot_x << 16) | hot_y);
WREG32(AVIVO_D1CUR_SIZE, ((w - 1) << 16) | 31);
} else {
uint32_t gpu_addr;
WREG32(RADEON_CUR_HORZ_VERT_OFF,
(RADEON_CUR_LOCK | (hot_x << 16) | (hot_y << 16)));
WREG32(RADEON_CUR_HORZ_VERT_POSN,
(RADEON_CUR_LOCK | (x << 16) | y));
gpu_addr = cursor->robj->gpu_addr;
/* offset is from DISP(2)_BASE_ADDRESS */
WREG32(RADEON_CUR_OFFSET,
(gpu_addr - rdev->mc.vram_location + (hot_y * 256)));
}
radeon_lock_cursor(false);
}
void __stdcall restore_cursor(int x, int y)
{
};
bool init_display(struct radeon_device *rdev, mode_t *usermode)
{
struct drm_device *dev;
cursor_t *cursor;
bool retval = false;
u32_t ifl;
ENTER();
rdisplay = GetDisplay();
dev = rdisplay->ddev = rdev->ddev;
ifl = safe_cli();
{
list_for_each_entry(cursor, &rdisplay->cursors, list)
{
init_cursor(cursor);
};
};
safe_sti(ifl);
ifl = safe_cli();
{
rdisplay->restore_cursor(0,0);
rdisplay->init_cursor = init_cursor;
rdisplay->select_cursor = select_cursor;
rdisplay->show_cursor = NULL;
rdisplay->move_cursor = move_cursor;
rdisplay->restore_cursor = restore_cursor;
select_cursor(rdisplay->cursor);
radeon_show_cursor();
};
safe_sti(ifl);
LEAVE();
return retval;
};