Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1179 serge 1
/*
2
 * Copyright 2007-8 Advanced Micro Devices, Inc.
3
 * Copyright 2008 Red Hat Inc.
4
 *
5
 * Permission is hereby granted, free of charge, to any person obtaining a
6
 * copy of this software and associated documentation files (the "Software"),
7
 * to deal in the Software without restriction, including without limitation
8
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9
 * and/or sell copies of the Software, and to permit persons to whom the
10
 * Software is furnished to do so, subject to the following conditions:
11
 *
12
 * The above copyright notice and this permission notice shall be included in
13
 * all copies or substantial portions of the Software.
14
 *
15
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18
 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
19
 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
20
 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
21
 * OTHER DEALINGS IN THE SOFTWARE.
22
 *
23
 * Authors: Dave Airlie
24
 *          Alex Deucher
25
 */
26
#include "drmP.h"
27
#include "radeon_drm.h"
28
#include "radeon.h"
29
 
30
#define CURSOR_WIDTH 64
31
#define CURSOR_HEIGHT 64
32
 
33
static void radeon_lock_cursor(struct drm_crtc *crtc, bool lock)
34
{
35
	struct radeon_device *rdev = crtc->dev->dev_private;
36
	struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
37
	uint32_t cur_lock;
38
 
39
	if (ASIC_IS_AVIVO(rdev)) {
40
		cur_lock = RREG32(AVIVO_D1CUR_UPDATE + radeon_crtc->crtc_offset);
41
		if (lock)
42
			cur_lock |= AVIVO_D1CURSOR_UPDATE_LOCK;
43
		else
44
			cur_lock &= ~AVIVO_D1CURSOR_UPDATE_LOCK;
45
		WREG32(AVIVO_D1CUR_UPDATE + radeon_crtc->crtc_offset, cur_lock);
46
	} else {
47
		cur_lock = RREG32(RADEON_CUR_OFFSET + radeon_crtc->crtc_offset);
48
		if (lock)
49
			cur_lock |= RADEON_CUR_LOCK;
50
		else
51
			cur_lock &= ~RADEON_CUR_LOCK;
52
		WREG32(RADEON_CUR_OFFSET + radeon_crtc->crtc_offset, cur_lock);
53
	}
54
}
55
 
56
static void radeon_hide_cursor(struct drm_crtc *crtc)
57
{
58
	struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
59
	struct radeon_device *rdev = crtc->dev->dev_private;
60
 
61
	if (ASIC_IS_AVIVO(rdev)) {
62
		WREG32(RADEON_MM_INDEX, AVIVO_D1CUR_CONTROL + radeon_crtc->crtc_offset);
63
		WREG32(RADEON_MM_DATA, (AVIVO_D1CURSOR_MODE_24BPP << AVIVO_D1CURSOR_MODE_SHIFT));
64
	} else {
65
		switch (radeon_crtc->crtc_id) {
66
		case 0:
67
			WREG32(RADEON_MM_INDEX, RADEON_CRTC_GEN_CNTL);
68
			break;
69
		case 1:
70
			WREG32(RADEON_MM_INDEX, RADEON_CRTC2_GEN_CNTL);
71
			break;
72
		default:
73
			return;
74
		}
75
		WREG32_P(RADEON_MM_DATA, 0, ~RADEON_CRTC_CUR_EN);
76
	}
77
}
78
 
79
static void radeon_show_cursor(struct drm_crtc *crtc)
80
{
81
	struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
82
	struct radeon_device *rdev = crtc->dev->dev_private;
83
 
84
	if (ASIC_IS_AVIVO(rdev)) {
85
		WREG32(RADEON_MM_INDEX, AVIVO_D1CUR_CONTROL + radeon_crtc->crtc_offset);
86
		WREG32(RADEON_MM_DATA, AVIVO_D1CURSOR_EN |
87
			     (AVIVO_D1CURSOR_MODE_24BPP << AVIVO_D1CURSOR_MODE_SHIFT));
88
	} else {
89
		switch (radeon_crtc->crtc_id) {
90
		case 0:
91
			WREG32(RADEON_MM_INDEX, RADEON_CRTC_GEN_CNTL);
92
			break;
93
		case 1:
94
			WREG32(RADEON_MM_INDEX, RADEON_CRTC2_GEN_CNTL);
95
			break;
96
		default:
97
			return;
98
		}
99
 
100
		WREG32_P(RADEON_MM_DATA, (RADEON_CRTC_CUR_EN |
101
					  (RADEON_CRTC_CUR_MODE_24BPP << RADEON_CRTC_CUR_MODE_SHIFT)),
102
			 ~(RADEON_CRTC_CUR_EN | RADEON_CRTC_CUR_MODE_MASK));
103
	}
104
}
105
 
106
static void radeon_set_cursor(struct drm_crtc *crtc, struct drm_gem_object *obj,
107
			      uint32_t gpu_addr)
108
{
109
	struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
110
	struct radeon_device *rdev = crtc->dev->dev_private;
111
 
112
	if (ASIC_IS_AVIVO(rdev))
113
		WREG32(AVIVO_D1CUR_SURFACE_ADDRESS + radeon_crtc->crtc_offset, gpu_addr);
114
	else {
115
		radeon_crtc->legacy_cursor_offset = gpu_addr - radeon_crtc->legacy_display_base_addr;
116
		/* offset is from DISP(2)_BASE_ADDRESS */
117
		WREG32(RADEON_CUR_OFFSET + radeon_crtc->crtc_offset, radeon_crtc->legacy_cursor_offset);
118
	}
119
}
120
 
121
#if 0
122
 
123
int radeon_crtc_cursor_set(struct drm_crtc *crtc,
124
			   struct drm_file *file_priv,
125
			   uint32_t handle,
126
			   uint32_t width,
127
			   uint32_t height)
128
{
129
	struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
130
	struct drm_gem_object *obj;
131
	uint64_t gpu_addr;
132
	int ret;
133
 
134
	if (!handle) {
135
		/* turn off cursor */
136
		radeon_hide_cursor(crtc);
137
		obj = NULL;
138
		goto unpin;
139
	}
140
 
141
	if ((width > CURSOR_WIDTH) || (height > CURSOR_HEIGHT)) {
142
		DRM_ERROR("bad cursor width or height %d x %d\n", width, height);
143
		return -EINVAL;
144
	}
145
 
146
	radeon_crtc->cursor_width = width;
147
	radeon_crtc->cursor_height = height;
148
 
149
	obj = drm_gem_object_lookup(crtc->dev, file_priv, handle);
150
	if (!obj) {
151
		DRM_ERROR("Cannot find cursor object %x for crtc %d\n", handle, radeon_crtc->crtc_id);
152
		return -EINVAL;
153
	}
154
 
155
	ret = radeon_gem_object_pin(obj, RADEON_GEM_DOMAIN_VRAM, &gpu_addr);
156
	if (ret)
157
		goto fail;
158
 
159
	radeon_lock_cursor(crtc, true);
160
	/* XXX only 27 bit offset for legacy cursor */
161
	radeon_set_cursor(crtc, obj, gpu_addr);
162
	radeon_show_cursor(crtc);
163
	radeon_lock_cursor(crtc, false);
164
 
165
unpin:
166
	if (radeon_crtc->cursor_bo) {
167
		radeon_gem_object_unpin(radeon_crtc->cursor_bo);
168
		mutex_lock(&crtc->dev->struct_mutex);
169
		drm_gem_object_unreference(radeon_crtc->cursor_bo);
170
		mutex_unlock(&crtc->dev->struct_mutex);
171
	}
172
 
173
	radeon_crtc->cursor_bo = obj;
174
	return 0;
175
fail:
176
	mutex_lock(&crtc->dev->struct_mutex);
177
	drm_gem_object_unreference(obj);
178
	mutex_unlock(&crtc->dev->struct_mutex);
179
 
180
	return 0;
181
}
182
#endif
183
 
184
int radeon_crtc_cursor_move(struct drm_crtc *crtc,
185
			    int x, int y)
186
{
187
	struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
188
	struct radeon_device *rdev = crtc->dev->dev_private;
189
	int xorigin = 0, yorigin = 0;
190
 
191
	if (x < 0)
192
		xorigin = -x + 1;
193
	if (y < 0)
194
		yorigin = -y + 1;
195
	if (xorigin >= CURSOR_WIDTH)
196
		xorigin = CURSOR_WIDTH - 1;
197
	if (yorigin >= CURSOR_HEIGHT)
198
		yorigin = CURSOR_HEIGHT - 1;
199
 
200
	radeon_lock_cursor(crtc, true);
201
	if (ASIC_IS_AVIVO(rdev)) {
202
		int w = radeon_crtc->cursor_width;
203
		int i = 0;
204
		struct drm_crtc *crtc_p;
205
 
206
		/* avivo cursor are offset into the total surface */
207
		x += crtc->x;
208
		y += crtc->y;
209
		DRM_DEBUG("x %d y %d c->x %d c->y %d\n", x, y, crtc->x, crtc->y);
210
 
211
		/* avivo cursor image can't end on 128 pixel boundry or
212
		 * go past the end of the frame if both crtcs are enabled
213
		 */
214
		list_for_each_entry(crtc_p, &crtc->dev->mode_config.crtc_list, head) {
215
			if (crtc_p->enabled)
216
				i++;
217
		}
218
		if (i > 1) {
219
			int cursor_end, frame_end;
220
 
221
			cursor_end = x - xorigin + w;
222
			frame_end = crtc->x + crtc->mode.crtc_hdisplay;
223
			if (cursor_end >= frame_end) {
224
				w = w - (cursor_end - frame_end);
225
				if (!(frame_end & 0x7f))
226
					w--;
227
			} else {
228
				if (!(cursor_end & 0x7f))
229
					w--;
230
			}
231
			if (w <= 0)
232
				w = 1;
233
		}
234
 
235
		WREG32(AVIVO_D1CUR_POSITION + radeon_crtc->crtc_offset,
236
			     ((xorigin ? 0 : x) << 16) |
237
			     (yorigin ? 0 : y));
238
		WREG32(AVIVO_D1CUR_HOT_SPOT + radeon_crtc->crtc_offset, (xorigin << 16) | yorigin);
239
		WREG32(AVIVO_D1CUR_SIZE + radeon_crtc->crtc_offset,
240
		       ((w - 1) << 16) | (radeon_crtc->cursor_height - 1));
241
	} else {
242
		if (crtc->mode.flags & DRM_MODE_FLAG_DBLSCAN)
243
			y *= 2;
244
 
245
		WREG32(RADEON_CUR_HORZ_VERT_OFF + radeon_crtc->crtc_offset,
246
		       (RADEON_CUR_LOCK
247
			| (xorigin << 16)
248
			| yorigin));
249
		WREG32(RADEON_CUR_HORZ_VERT_POSN + radeon_crtc->crtc_offset,
250
		       (RADEON_CUR_LOCK
251
			| ((xorigin ? 0 : x) << 16)
252
			| (yorigin ? 0 : y)));
253
		/* offset is from DISP(2)_BASE_ADDRESS */
254
		WREG32(RADEON_CUR_OFFSET + radeon_crtc->crtc_offset, (radeon_crtc->legacy_cursor_offset +
255
								      (yorigin * 256)));
256
	}
257
	radeon_lock_cursor(crtc, false);
258
 
259
	return 0;
260
}