2 * Copyright 2013 Matrox Graphics
4 * This file is subject to the terms and conditions of the GNU General
5 * Public License version 2. See the file COPYING in the main
6 * directory of this archive for more details.
8 * Author: Christopher Harvey <charvey@matrox.com>
12 #include "mgag200_drv.h"
14 static bool warn_transparent
= true;
15 static bool warn_palette
= true;
18 Hide the cursor off screen. We can't disable the cursor hardware because it
19 takes too long to re-activate and causes momentary corruption
21 static void mga_hide_cursor(struct mga_device
*mdev
)
23 WREG8(MGA_CURPOSXL
, 0);
24 WREG8(MGA_CURPOSXH
, 0);
25 if (mdev
->cursor
.pixels_1
->pin_count
)
26 mgag200_bo_unpin(mdev
->cursor
.pixels_1
);
27 if (mdev
->cursor
.pixels_2
->pin_count
)
28 mgag200_bo_unpin(mdev
->cursor
.pixels_2
);
31 int mga_crtc_cursor_set(struct drm_crtc
*crtc
,
32 struct drm_file
*file_priv
,
37 struct drm_device
*dev
= crtc
->dev
;
38 struct mga_device
*mdev
= (struct mga_device
*)dev
->dev_private
;
39 struct mgag200_bo
*pixels_1
= mdev
->cursor
.pixels_1
;
40 struct mgag200_bo
*pixels_2
= mdev
->cursor
.pixels_2
;
41 struct mgag200_bo
*pixels_current
= mdev
->cursor
.pixels_current
;
42 struct mgag200_bo
*pixels_prev
= mdev
->cursor
.pixels_prev
;
43 struct drm_gem_object
*obj
;
44 struct mgag200_bo
*bo
= NULL
;
46 unsigned int i
, row
, col
;
47 uint32_t colour_set
[16];
48 uint32_t *next_space
= &colour_set
[0];
49 uint32_t *palette_iter
;
57 if (!pixels_1
|| !pixels_2
) {
58 WREG8(MGA_CURPOSXL
, 0);
59 WREG8(MGA_CURPOSXH
, 0);
60 return -ENOTSUPP
; /* Didn't allocate space for cursors */
63 if ((width
!= 64 || height
!= 64) && handle
) {
64 WREG8(MGA_CURPOSXL
, 0);
65 WREG8(MGA_CURPOSXH
, 0);
69 BUG_ON(pixels_1
!= pixels_current
&& pixels_1
!= pixels_prev
);
70 BUG_ON(pixels_2
!= pixels_current
&& pixels_2
!= pixels_prev
);
71 BUG_ON(pixels_current
== pixels_prev
);
73 ret
= mgag200_bo_reserve(pixels_1
, true);
75 WREG8(MGA_CURPOSXL
, 0);
76 WREG8(MGA_CURPOSXH
, 0);
79 ret
= mgag200_bo_reserve(pixels_2
, true);
81 WREG8(MGA_CURPOSXL
, 0);
82 WREG8(MGA_CURPOSXH
, 0);
83 mgag200_bo_unreserve(pixels_1
);
88 mga_hide_cursor(mdev
);
93 /* Move cursor buffers into VRAM if they aren't already */
94 if (!pixels_1
->pin_count
) {
95 ret
= mgag200_bo_pin(pixels_1
, TTM_PL_FLAG_VRAM
,
96 &mdev
->cursor
.pixels_1_gpu_addr
);
100 if (!pixels_2
->pin_count
) {
101 ret
= mgag200_bo_pin(pixels_2
, TTM_PL_FLAG_VRAM
,
102 &mdev
->cursor
.pixels_2_gpu_addr
);
104 mgag200_bo_unpin(pixels_1
);
109 mutex_lock(&dev
->struct_mutex
);
110 obj
= drm_gem_object_lookup(dev
, file_priv
, handle
);
112 mutex_unlock(&dev
->struct_mutex
);
116 drm_gem_object_unreference(obj
);
117 mutex_unlock(&dev
->struct_mutex
);
119 bo
= gem_to_mga_bo(obj
);
120 ret
= mgag200_bo_reserve(bo
, true);
122 dev_err(&dev
->pdev
->dev
, "failed to reserve user bo\n");
125 if (!bo
->kmap
.virtual) {
126 ret
= ttm_bo_kmap(&bo
->bo
, 0, bo
->bo
.num_pages
, &bo
->kmap
);
128 dev_err(&dev
->pdev
->dev
, "failed to kmap user buffer updates\n");
133 memset(&colour_set
[0], 0, sizeof(uint32_t)*16);
134 /* width*height*4 = 16384 */
135 for (i
= 0; i
< 16384; i
+= 4) {
136 this_colour
= ioread32(bo
->kmap
.virtual + i
);
137 /* No transparency */
138 if (this_colour
>>24 != 0xff &&
139 this_colour
>>24 != 0x0) {
140 if (warn_transparent
) {
141 dev_info(&dev
->pdev
->dev
, "Video card doesn't support cursors with partial transparency.\n");
142 dev_info(&dev
->pdev
->dev
, "Not enabling hardware cursor.\n");
143 warn_transparent
= false; /* Only tell the user once. */
148 /* Don't need to store transparent pixels as colours */
149 if (this_colour
>>24 == 0x0)
152 for (palette_iter
= &colour_set
[0]; palette_iter
!= next_space
; palette_iter
++) {
153 if (*palette_iter
== this_colour
) {
160 /* We only support 4bit paletted cursors */
161 if (colour_count
>= 16) {
163 dev_info(&dev
->pdev
->dev
, "Video card only supports cursors with up to 16 colours.\n");
164 dev_info(&dev
->pdev
->dev
, "Not enabling hardware cursor.\n");
165 warn_palette
= false; /* Only tell the user once. */
170 *next_space
= this_colour
;
175 /* Program colours from cursor icon into palette */
176 for (i
= 0; i
< colour_count
; i
++) {
178 reg_index
= 0x8 + i
*0x4;
180 reg_index
= 0x60 + i
*0x3;
181 WREG_DAC(reg_index
, colour_set
[i
] & 0xff);
182 WREG_DAC(reg_index
+1, colour_set
[i
]>>8 & 0xff);
183 WREG_DAC(reg_index
+2, colour_set
[i
]>>16 & 0xff);
184 BUG_ON((colour_set
[i
]>>24 & 0xff) != 0xff);
187 /* Map up-coming buffer to write colour indices */
188 if (!pixels_prev
->kmap
.virtual) {
189 ret
= ttm_bo_kmap(&pixels_prev
->bo
, 0,
190 pixels_prev
->bo
.num_pages
,
193 dev_err(&dev
->pdev
->dev
, "failed to kmap cursor updates\n");
198 /* now write colour indices into hardware cursor buffer */
199 for (row
= 0; row
< 64; row
++) {
200 memset(&this_row
[0], 0, 48);
201 for (col
= 0; col
< 64; col
++) {
202 this_colour
= ioread32(bo
->kmap
.virtual + 4*(col
+ 64*row
));
203 /* write transparent pixels */
204 if (this_colour
>>24 == 0x0) {
205 this_row
[47 - col
/8] |= 0x80>>(col
%8);
209 /* write colour index here */
210 for (i
= 0; i
< colour_count
; i
++) {
211 if (colour_set
[i
] == this_colour
) {
213 this_row
[col
/2] |= i
<<4;
215 this_row
[col
/2] |= i
;
220 memcpy_toio(pixels_prev
->kmap
.virtual + row
*48, &this_row
[0], 48);
223 /* Program gpu address of cursor buffer */
224 if (pixels_prev
== pixels_1
)
225 gpu_addr
= mdev
->cursor
.pixels_1_gpu_addr
;
227 gpu_addr
= mdev
->cursor
.pixels_2_gpu_addr
;
228 WREG_DAC(MGA1064_CURSOR_BASE_ADR_LOW
, (u8
)((gpu_addr
>>10) & 0xff));
229 WREG_DAC(MGA1064_CURSOR_BASE_ADR_HI
, (u8
)((gpu_addr
>>18) & 0x3f));
231 /* Adjust cursor control register to turn on the cursor */
232 WREG_DAC(MGA1064_CURSOR_CTL
, 4); /* 16-colour palletized cursor mode */
234 /* Now swap internal buffer pointers */
235 if (mdev
->cursor
.pixels_1
== mdev
->cursor
.pixels_prev
) {
236 mdev
->cursor
.pixels_prev
= mdev
->cursor
.pixels_2
;
237 mdev
->cursor
.pixels_current
= mdev
->cursor
.pixels_1
;
238 } else if (mdev
->cursor
.pixels_1
== mdev
->cursor
.pixels_current
) {
239 mdev
->cursor
.pixels_prev
= mdev
->cursor
.pixels_1
;
240 mdev
->cursor
.pixels_current
= mdev
->cursor
.pixels_2
;
246 ttm_bo_kunmap(&pixels_prev
->kmap
);
248 ttm_bo_kunmap(&bo
->kmap
);
250 mgag200_bo_unreserve(bo
);
253 mga_hide_cursor(mdev
);
254 mgag200_bo_unreserve(pixels_1
);
255 mgag200_bo_unreserve(pixels_2
);
259 int mga_crtc_cursor_move(struct drm_crtc
*crtc
, int x
, int y
)
261 struct mga_device
*mdev
= (struct mga_device
*)crtc
->dev
->dev_private
;
262 /* Our origin is at (64,64) */
271 WREG8(MGA_CURPOSXL
, x
& 0xff);
272 WREG8(MGA_CURPOSXH
, (x
>>8) & 0xff);
274 WREG8(MGA_CURPOSYL
, y
& 0xff);
275 WREG8(MGA_CURPOSYH
, (y
>>8) & 0xff);