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 obj
= drm_gem_object_lookup(dev
, file_priv
, handle
);
77 ret
= mgag200_bo_reserve(pixels_1
, true);
79 WREG8(MGA_CURPOSXL
, 0);
80 WREG8(MGA_CURPOSXH
, 0);
83 ret
= mgag200_bo_reserve(pixels_2
, true);
85 WREG8(MGA_CURPOSXL
, 0);
86 WREG8(MGA_CURPOSXH
, 0);
87 mgag200_bo_unreserve(pixels_1
);
92 mga_hide_cursor(mdev
);
97 /* Move cursor buffers into VRAM if they aren't already */
98 if (!pixels_1
->pin_count
) {
99 ret
= mgag200_bo_pin(pixels_1
, TTM_PL_FLAG_VRAM
,
100 &mdev
->cursor
.pixels_1_gpu_addr
);
104 if (!pixels_2
->pin_count
) {
105 ret
= mgag200_bo_pin(pixels_2
, TTM_PL_FLAG_VRAM
,
106 &mdev
->cursor
.pixels_2_gpu_addr
);
108 mgag200_bo_unpin(pixels_1
);
113 bo
= gem_to_mga_bo(obj
);
114 ret
= mgag200_bo_reserve(bo
, true);
116 dev_err(&dev
->pdev
->dev
, "failed to reserve user bo\n");
119 if (!bo
->kmap
.virtual) {
120 ret
= ttm_bo_kmap(&bo
->bo
, 0, bo
->bo
.num_pages
, &bo
->kmap
);
122 dev_err(&dev
->pdev
->dev
, "failed to kmap user buffer updates\n");
127 memset(&colour_set
[0], 0, sizeof(uint32_t)*16);
128 /* width*height*4 = 16384 */
129 for (i
= 0; i
< 16384; i
+= 4) {
130 this_colour
= ioread32(bo
->kmap
.virtual + i
);
131 /* No transparency */
132 if (this_colour
>>24 != 0xff &&
133 this_colour
>>24 != 0x0) {
134 if (warn_transparent
) {
135 dev_info(&dev
->pdev
->dev
, "Video card doesn't support cursors with partial transparency.\n");
136 dev_info(&dev
->pdev
->dev
, "Not enabling hardware cursor.\n");
137 warn_transparent
= false; /* Only tell the user once. */
142 /* Don't need to store transparent pixels as colours */
143 if (this_colour
>>24 == 0x0)
146 for (palette_iter
= &colour_set
[0]; palette_iter
!= next_space
; palette_iter
++) {
147 if (*palette_iter
== this_colour
) {
154 /* We only support 4bit paletted cursors */
155 if (colour_count
>= 16) {
157 dev_info(&dev
->pdev
->dev
, "Video card only supports cursors with up to 16 colours.\n");
158 dev_info(&dev
->pdev
->dev
, "Not enabling hardware cursor.\n");
159 warn_palette
= false; /* Only tell the user once. */
164 *next_space
= this_colour
;
169 /* Program colours from cursor icon into palette */
170 for (i
= 0; i
< colour_count
; i
++) {
172 reg_index
= 0x8 + i
*0x4;
174 reg_index
= 0x60 + i
*0x3;
175 WREG_DAC(reg_index
, colour_set
[i
] & 0xff);
176 WREG_DAC(reg_index
+1, colour_set
[i
]>>8 & 0xff);
177 WREG_DAC(reg_index
+2, colour_set
[i
]>>16 & 0xff);
178 BUG_ON((colour_set
[i
]>>24 & 0xff) != 0xff);
181 /* Map up-coming buffer to write colour indices */
182 if (!pixels_prev
->kmap
.virtual) {
183 ret
= ttm_bo_kmap(&pixels_prev
->bo
, 0,
184 pixels_prev
->bo
.num_pages
,
187 dev_err(&dev
->pdev
->dev
, "failed to kmap cursor updates\n");
192 /* now write colour indices into hardware cursor buffer */
193 for (row
= 0; row
< 64; row
++) {
194 memset(&this_row
[0], 0, 48);
195 for (col
= 0; col
< 64; col
++) {
196 this_colour
= ioread32(bo
->kmap
.virtual + 4*(col
+ 64*row
));
197 /* write transparent pixels */
198 if (this_colour
>>24 == 0x0) {
199 this_row
[47 - col
/8] |= 0x80>>(col
%8);
203 /* write colour index here */
204 for (i
= 0; i
< colour_count
; i
++) {
205 if (colour_set
[i
] == this_colour
) {
207 this_row
[col
/2] |= i
<<4;
209 this_row
[col
/2] |= i
;
214 memcpy_toio(pixels_prev
->kmap
.virtual + row
*48, &this_row
[0], 48);
217 /* Program gpu address of cursor buffer */
218 if (pixels_prev
== pixels_1
)
219 gpu_addr
= mdev
->cursor
.pixels_1_gpu_addr
;
221 gpu_addr
= mdev
->cursor
.pixels_2_gpu_addr
;
222 WREG_DAC(MGA1064_CURSOR_BASE_ADR_LOW
, (u8
)((gpu_addr
>>10) & 0xff));
223 WREG_DAC(MGA1064_CURSOR_BASE_ADR_HI
, (u8
)((gpu_addr
>>18) & 0x3f));
225 /* Adjust cursor control register to turn on the cursor */
226 WREG_DAC(MGA1064_CURSOR_CTL
, 4); /* 16-colour palletized cursor mode */
228 /* Now swap internal buffer pointers */
229 if (mdev
->cursor
.pixels_1
== mdev
->cursor
.pixels_prev
) {
230 mdev
->cursor
.pixels_prev
= mdev
->cursor
.pixels_2
;
231 mdev
->cursor
.pixels_current
= mdev
->cursor
.pixels_1
;
232 } else if (mdev
->cursor
.pixels_1
== mdev
->cursor
.pixels_current
) {
233 mdev
->cursor
.pixels_prev
= mdev
->cursor
.pixels_1
;
234 mdev
->cursor
.pixels_current
= mdev
->cursor
.pixels_2
;
240 ttm_bo_kunmap(&pixels_prev
->kmap
);
242 ttm_bo_kunmap(&bo
->kmap
);
244 mgag200_bo_unreserve(bo
);
247 mga_hide_cursor(mdev
);
248 mgag200_bo_unreserve(pixels_1
);
250 mgag200_bo_unreserve(pixels_2
);
252 drm_gem_object_unreference_unlocked(obj
);
257 int mga_crtc_cursor_move(struct drm_crtc
*crtc
, int x
, int y
)
259 struct mga_device
*mdev
= (struct mga_device
*)crtc
->dev
->dev_private
;
260 /* Our origin is at (64,64) */
269 WREG8(MGA_CURPOSXL
, x
& 0xff);
270 WREG8(MGA_CURPOSXH
, (x
>>8) & 0xff);
272 WREG8(MGA_CURPOSYL
, y
& 0xff);
273 WREG8(MGA_CURPOSYH
, (y
>>8) & 0xff);