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 if (!handle
|| !file_priv
) {
74 mga_hide_cursor(mdev
);
78 obj
= drm_gem_object_lookup(file_priv
, handle
);
82 ret
= mgag200_bo_reserve(pixels_1
, true);
84 WREG8(MGA_CURPOSXL
, 0);
85 WREG8(MGA_CURPOSXH
, 0);
88 ret
= mgag200_bo_reserve(pixels_2
, true);
90 WREG8(MGA_CURPOSXL
, 0);
91 WREG8(MGA_CURPOSXH
, 0);
92 mgag200_bo_unreserve(pixels_1
);
96 /* Move cursor buffers into VRAM if they aren't already */
97 if (!pixels_1
->pin_count
) {
98 ret
= mgag200_bo_pin(pixels_1
, TTM_PL_FLAG_VRAM
,
99 &mdev
->cursor
.pixels_1_gpu_addr
);
103 if (!pixels_2
->pin_count
) {
104 ret
= mgag200_bo_pin(pixels_2
, TTM_PL_FLAG_VRAM
,
105 &mdev
->cursor
.pixels_2_gpu_addr
);
107 mgag200_bo_unpin(pixels_1
);
112 bo
= gem_to_mga_bo(obj
);
113 ret
= mgag200_bo_reserve(bo
, true);
115 dev_err(&dev
->pdev
->dev
, "failed to reserve user bo\n");
118 if (!bo
->kmap
.virtual) {
119 ret
= ttm_bo_kmap(&bo
->bo
, 0, bo
->bo
.num_pages
, &bo
->kmap
);
121 dev_err(&dev
->pdev
->dev
, "failed to kmap user buffer updates\n");
126 memset(&colour_set
[0], 0, sizeof(uint32_t)*16);
127 /* width*height*4 = 16384 */
128 for (i
= 0; i
< 16384; i
+= 4) {
129 this_colour
= ioread32(bo
->kmap
.virtual + i
);
130 /* No transparency */
131 if (this_colour
>>24 != 0xff &&
132 this_colour
>>24 != 0x0) {
133 if (warn_transparent
) {
134 dev_info(&dev
->pdev
->dev
, "Video card doesn't support cursors with partial transparency.\n");
135 dev_info(&dev
->pdev
->dev
, "Not enabling hardware cursor.\n");
136 warn_transparent
= false; /* Only tell the user once. */
141 /* Don't need to store transparent pixels as colours */
142 if (this_colour
>>24 == 0x0)
145 for (palette_iter
= &colour_set
[0]; palette_iter
!= next_space
; palette_iter
++) {
146 if (*palette_iter
== this_colour
) {
153 /* We only support 4bit paletted cursors */
154 if (colour_count
>= 16) {
156 dev_info(&dev
->pdev
->dev
, "Video card only supports cursors with up to 16 colours.\n");
157 dev_info(&dev
->pdev
->dev
, "Not enabling hardware cursor.\n");
158 warn_palette
= false; /* Only tell the user once. */
163 *next_space
= this_colour
;
168 /* Program colours from cursor icon into palette */
169 for (i
= 0; i
< colour_count
; i
++) {
171 reg_index
= 0x8 + i
*0x4;
173 reg_index
= 0x60 + i
*0x3;
174 WREG_DAC(reg_index
, colour_set
[i
] & 0xff);
175 WREG_DAC(reg_index
+1, colour_set
[i
]>>8 & 0xff);
176 WREG_DAC(reg_index
+2, colour_set
[i
]>>16 & 0xff);
177 BUG_ON((colour_set
[i
]>>24 & 0xff) != 0xff);
180 /* Map up-coming buffer to write colour indices */
181 if (!pixels_prev
->kmap
.virtual) {
182 ret
= ttm_bo_kmap(&pixels_prev
->bo
, 0,
183 pixels_prev
->bo
.num_pages
,
186 dev_err(&dev
->pdev
->dev
, "failed to kmap cursor updates\n");
191 /* now write colour indices into hardware cursor buffer */
192 for (row
= 0; row
< 64; row
++) {
193 memset(&this_row
[0], 0, 48);
194 for (col
= 0; col
< 64; col
++) {
195 this_colour
= ioread32(bo
->kmap
.virtual + 4*(col
+ 64*row
));
196 /* write transparent pixels */
197 if (this_colour
>>24 == 0x0) {
198 this_row
[47 - col
/8] |= 0x80>>(col
%8);
202 /* write colour index here */
203 for (i
= 0; i
< colour_count
; i
++) {
204 if (colour_set
[i
] == this_colour
) {
206 this_row
[col
/2] |= i
<<4;
208 this_row
[col
/2] |= i
;
213 memcpy_toio(pixels_prev
->kmap
.virtual + row
*48, &this_row
[0], 48);
216 /* Program gpu address of cursor buffer */
217 if (pixels_prev
== pixels_1
)
218 gpu_addr
= mdev
->cursor
.pixels_1_gpu_addr
;
220 gpu_addr
= mdev
->cursor
.pixels_2_gpu_addr
;
221 WREG_DAC(MGA1064_CURSOR_BASE_ADR_LOW
, (u8
)((gpu_addr
>>10) & 0xff));
222 WREG_DAC(MGA1064_CURSOR_BASE_ADR_HI
, (u8
)((gpu_addr
>>18) & 0x3f));
224 /* Adjust cursor control register to turn on the cursor */
225 WREG_DAC(MGA1064_CURSOR_CTL
, 4); /* 16-colour palletized cursor mode */
227 /* Now swap internal buffer pointers */
228 if (mdev
->cursor
.pixels_1
== mdev
->cursor
.pixels_prev
) {
229 mdev
->cursor
.pixels_prev
= mdev
->cursor
.pixels_2
;
230 mdev
->cursor
.pixels_current
= mdev
->cursor
.pixels_1
;
231 } else if (mdev
->cursor
.pixels_1
== mdev
->cursor
.pixels_current
) {
232 mdev
->cursor
.pixels_prev
= mdev
->cursor
.pixels_1
;
233 mdev
->cursor
.pixels_current
= mdev
->cursor
.pixels_2
;
239 ttm_bo_kunmap(&pixels_prev
->kmap
);
241 ttm_bo_kunmap(&bo
->kmap
);
243 mgag200_bo_unreserve(bo
);
246 mga_hide_cursor(mdev
);
247 mgag200_bo_unreserve(pixels_1
);
249 mgag200_bo_unreserve(pixels_2
);
251 drm_gem_object_unreference_unlocked(obj
);
256 int mga_crtc_cursor_move(struct drm_crtc
*crtc
, int x
, int y
)
258 struct mga_device
*mdev
= (struct mga_device
*)crtc
->dev
->dev_private
;
259 /* Our origin is at (64,64) */
268 WREG8(MGA_CURPOSXL
, x
& 0xff);
269 WREG8(MGA_CURPOSXH
, (x
>>8) & 0xff);
271 WREG8(MGA_CURPOSYL
, y
& 0xff);
272 WREG8(MGA_CURPOSYH
, (y
>>8) & 0xff);