Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v3.11-rc1 275 lines 7.4 kB view raw
1/* 2 * Copyright 2013 Matrox Graphics 3 * 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. 7 * 8 * Author: Christopher Harvey <charvey@matrox.com> 9 */ 10 11#include <drm/drmP.h> 12#include "mgag200_drv.h" 13 14static bool warn_transparent = true; 15static bool warn_palette = true; 16 17/* 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 20*/ 21static void mga_hide_cursor(struct mga_device *mdev) 22{ 23 WREG8(MGA_CURPOSXL, 0); 24 WREG8(MGA_CURPOSXH, 0); 25 mgag200_bo_unpin(mdev->cursor.pixels_1); 26 mgag200_bo_unpin(mdev->cursor.pixels_2); 27} 28 29int mga_crtc_cursor_set(struct drm_crtc *crtc, 30 struct drm_file *file_priv, 31 uint32_t handle, 32 uint32_t width, 33 uint32_t height) 34{ 35 struct drm_device *dev = (struct drm_device *)file_priv->minor->dev; 36 struct mga_device *mdev = (struct mga_device *)dev->dev_private; 37 struct mgag200_bo *pixels_1 = mdev->cursor.pixels_1; 38 struct mgag200_bo *pixels_2 = mdev->cursor.pixels_2; 39 struct mgag200_bo *pixels_current = mdev->cursor.pixels_current; 40 struct mgag200_bo *pixels_prev = mdev->cursor.pixels_prev; 41 struct drm_gem_object *obj; 42 struct mgag200_bo *bo = NULL; 43 int ret = 0; 44 unsigned int i, row, col; 45 uint32_t colour_set[16]; 46 uint32_t *next_space = &colour_set[0]; 47 uint32_t *palette_iter; 48 uint32_t this_colour; 49 bool found = false; 50 int colour_count = 0; 51 u64 gpu_addr; 52 u8 reg_index; 53 u8 this_row[48]; 54 55 if (!pixels_1 || !pixels_2) { 56 WREG8(MGA_CURPOSXL, 0); 57 WREG8(MGA_CURPOSXH, 0); 58 return -ENOTSUPP; /* Didn't allocate space for cursors */ 59 } 60 61 if ((width != 64 || height != 64) && handle) { 62 WREG8(MGA_CURPOSXL, 0); 63 WREG8(MGA_CURPOSXH, 0); 64 return -EINVAL; 65 } 66 67 BUG_ON(pixels_1 != pixels_current && pixels_1 != pixels_prev); 68 BUG_ON(pixels_2 != pixels_current && pixels_2 != pixels_prev); 69 BUG_ON(pixels_current == pixels_prev); 70 71 ret = mgag200_bo_reserve(pixels_1, true); 72 if (ret) { 73 WREG8(MGA_CURPOSXL, 0); 74 WREG8(MGA_CURPOSXH, 0); 75 return ret; 76 } 77 ret = mgag200_bo_reserve(pixels_2, true); 78 if (ret) { 79 WREG8(MGA_CURPOSXL, 0); 80 WREG8(MGA_CURPOSXH, 0); 81 mgag200_bo_unreserve(pixels_1); 82 return ret; 83 } 84 85 if (!handle) { 86 mga_hide_cursor(mdev); 87 ret = 0; 88 goto out1; 89 } 90 91 /* Move cursor buffers into VRAM if they aren't already */ 92 if (!pixels_1->pin_count) { 93 ret = mgag200_bo_pin(pixels_1, TTM_PL_FLAG_VRAM, 94 &mdev->cursor.pixels_1_gpu_addr); 95 if (ret) 96 goto out1; 97 } 98 if (!pixels_2->pin_count) { 99 ret = mgag200_bo_pin(pixels_2, TTM_PL_FLAG_VRAM, 100 &mdev->cursor.pixels_2_gpu_addr); 101 if (ret) { 102 mgag200_bo_unpin(pixels_1); 103 goto out1; 104 } 105 } 106 107 mutex_lock(&dev->struct_mutex); 108 obj = drm_gem_object_lookup(dev, file_priv, handle); 109 if (!obj) { 110 mutex_unlock(&dev->struct_mutex); 111 ret = -ENOENT; 112 goto out1; 113 } 114 drm_gem_object_unreference(obj); 115 mutex_unlock(&dev->struct_mutex); 116 117 bo = gem_to_mga_bo(obj); 118 ret = mgag200_bo_reserve(bo, true); 119 if (ret) { 120 dev_err(&dev->pdev->dev, "failed to reserve user bo\n"); 121 goto out1; 122 } 123 if (!bo->kmap.virtual) { 124 ret = ttm_bo_kmap(&bo->bo, 0, bo->bo.num_pages, &bo->kmap); 125 if (ret) { 126 dev_err(&dev->pdev->dev, "failed to kmap user buffer updates\n"); 127 goto out2; 128 } 129 } 130 131 memset(&colour_set[0], 0, sizeof(uint32_t)*16); 132 /* width*height*4 = 16384 */ 133 for (i = 0; i < 16384; i += 4) { 134 this_colour = ioread32(bo->kmap.virtual + i); 135 /* No transparency */ 136 if (this_colour>>24 != 0xff && 137 this_colour>>24 != 0x0) { 138 if (warn_transparent) { 139 dev_info(&dev->pdev->dev, "Video card doesn't support cursors with partial transparency.\n"); 140 dev_info(&dev->pdev->dev, "Not enabling hardware cursor.\n"); 141 warn_transparent = false; /* Only tell the user once. */ 142 } 143 ret = -EINVAL; 144 goto out3; 145 } 146 /* Don't need to store transparent pixels as colours */ 147 if (this_colour>>24 == 0x0) 148 continue; 149 found = false; 150 for (palette_iter = &colour_set[0]; palette_iter != next_space; palette_iter++) { 151 if (*palette_iter == this_colour) { 152 found = true; 153 break; 154 } 155 } 156 if (found) 157 continue; 158 /* We only support 4bit paletted cursors */ 159 if (colour_count >= 16) { 160 if (warn_palette) { 161 dev_info(&dev->pdev->dev, "Video card only supports cursors with up to 16 colours.\n"); 162 dev_info(&dev->pdev->dev, "Not enabling hardware cursor.\n"); 163 warn_palette = false; /* Only tell the user once. */ 164 } 165 ret = -EINVAL; 166 goto out3; 167 } 168 *next_space = this_colour; 169 next_space++; 170 colour_count++; 171 } 172 173 /* Program colours from cursor icon into palette */ 174 for (i = 0; i < colour_count; i++) { 175 if (i <= 2) 176 reg_index = 0x8 + i*0x4; 177 else 178 reg_index = 0x60 + i*0x3; 179 WREG_DAC(reg_index, colour_set[i] & 0xff); 180 WREG_DAC(reg_index+1, colour_set[i]>>8 & 0xff); 181 WREG_DAC(reg_index+2, colour_set[i]>>16 & 0xff); 182 BUG_ON((colour_set[i]>>24 & 0xff) != 0xff); 183 } 184 185 /* Map up-coming buffer to write colour indices */ 186 if (!pixels_prev->kmap.virtual) { 187 ret = ttm_bo_kmap(&pixels_prev->bo, 0, 188 pixels_prev->bo.num_pages, 189 &pixels_prev->kmap); 190 if (ret) { 191 dev_err(&dev->pdev->dev, "failed to kmap cursor updates\n"); 192 goto out3; 193 } 194 } 195 196 /* now write colour indices into hardware cursor buffer */ 197 for (row = 0; row < 64; row++) { 198 memset(&this_row[0], 0, 48); 199 for (col = 0; col < 64; col++) { 200 this_colour = ioread32(bo->kmap.virtual + 4*(col + 64*row)); 201 /* write transparent pixels */ 202 if (this_colour>>24 == 0x0) { 203 this_row[47 - col/8] |= 0x80>>(col%8); 204 continue; 205 } 206 207 /* write colour index here */ 208 for (i = 0; i < colour_count; i++) { 209 if (colour_set[i] == this_colour) { 210 if (col % 2) 211 this_row[col/2] |= i<<4; 212 else 213 this_row[col/2] |= i; 214 break; 215 } 216 } 217 } 218 memcpy_toio(pixels_prev->kmap.virtual + row*48, &this_row[0], 48); 219 } 220 221 /* Program gpu address of cursor buffer */ 222 if (pixels_prev == pixels_1) 223 gpu_addr = mdev->cursor.pixels_1_gpu_addr; 224 else 225 gpu_addr = mdev->cursor.pixels_2_gpu_addr; 226 WREG_DAC(MGA1064_CURSOR_BASE_ADR_LOW, (u8)((gpu_addr>>10) & 0xff)); 227 WREG_DAC(MGA1064_CURSOR_BASE_ADR_HI, (u8)((gpu_addr>>18) & 0x3f)); 228 229 /* Adjust cursor control register to turn on the cursor */ 230 WREG_DAC(MGA1064_CURSOR_CTL, 4); /* 16-colour palletized cursor mode */ 231 232 /* Now swap internal buffer pointers */ 233 if (mdev->cursor.pixels_1 == mdev->cursor.pixels_prev) { 234 mdev->cursor.pixels_prev = mdev->cursor.pixels_2; 235 mdev->cursor.pixels_current = mdev->cursor.pixels_1; 236 } else if (mdev->cursor.pixels_1 == mdev->cursor.pixels_current) { 237 mdev->cursor.pixels_prev = mdev->cursor.pixels_1; 238 mdev->cursor.pixels_current = mdev->cursor.pixels_2; 239 } else { 240 BUG(); 241 } 242 ret = 0; 243 244 ttm_bo_kunmap(&pixels_prev->kmap); 245 out3: 246 ttm_bo_kunmap(&bo->kmap); 247 out2: 248 mgag200_bo_unreserve(bo); 249 out1: 250 if (ret) 251 mga_hide_cursor(mdev); 252 mgag200_bo_unreserve(pixels_1); 253 mgag200_bo_unreserve(pixels_2); 254 return ret; 255} 256 257int mga_crtc_cursor_move(struct drm_crtc *crtc, int x, int y) 258{ 259 struct mga_device *mdev = (struct mga_device *)crtc->dev->dev_private; 260 /* Our origin is at (64,64) */ 261 x += 64; 262 y += 64; 263 264 BUG_ON(x <= 0); 265 BUG_ON(y <= 0); 266 BUG_ON(x & ~0xffff); 267 BUG_ON(y & ~0xffff); 268 269 WREG8(MGA_CURPOSXL, x & 0xff); 270 WREG8(MGA_CURPOSXH, (x>>8) & 0xff); 271 272 WREG8(MGA_CURPOSYL, y & 0xff); 273 WREG8(MGA_CURPOSYH, (y>>8) & 0xff); 274 return 0; 275}