diff options
author | Krzysztof Helt <krzysztof.h1@wp.pl> | 2007-10-16 04:28:53 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-10-16 12:43:16 -0400 |
commit | 8f5d050af1da13455068cefbaf3c1bc306d6fe0b (patch) | |
tree | 8bb467007c47dbe822b62d3d4bff7dec69fc53c3 /drivers/video/pm2fb.c | |
parent | 5a258d032d8dff1c5e28ce64c47ac4577c2c5a70 (diff) |
pm2fb: Permedia 2V hardware cursor support
This patch adds hardware cursor support for Permedia 2V chips.
The hardware cursor is disabled by default. It does not blink - the
same issue is mentioned in the x11 driver.
Signed-off-by: Krzysztof Helt <krzysztof.h1@wp.pl>
Signed-off-by: Antonino Daplas <adaplas@gmail.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/video/pm2fb.c')
-rw-r--r-- | drivers/video/pm2fb.c | 137 |
1 files changed, 137 insertions, 0 deletions
diff --git a/drivers/video/pm2fb.c b/drivers/video/pm2fb.c index 19cbde192956..53dd639e9753 100644 --- a/drivers/video/pm2fb.c +++ b/drivers/video/pm2fb.c | |||
@@ -66,6 +66,7 @@ | |||
66 | /* | 66 | /* |
67 | * Driver data | 67 | * Driver data |
68 | */ | 68 | */ |
69 | static int hwcursor; | ||
69 | static char *mode __devinitdata; | 70 | static char *mode __devinitdata; |
70 | 71 | ||
71 | /* | 72 | /* |
@@ -1245,6 +1246,136 @@ static void pm2fb_imageblit(struct fb_info *info, const struct fb_image *image) | |||
1245 | pm2_WR(par, PM2R_SCISSOR_MODE, 0); | 1246 | pm2_WR(par, PM2R_SCISSOR_MODE, 0); |
1246 | } | 1247 | } |
1247 | 1248 | ||
1249 | /* | ||
1250 | * Hardware cursor support. | ||
1251 | */ | ||
1252 | static const u8 cursor_bits_lookup[16] = { | ||
1253 | 0x00, 0x40, 0x10, 0x50, 0x04, 0x44, 0x14, 0x54, | ||
1254 | 0x01, 0x41, 0x11, 0x51, 0x05, 0x45, 0x15, 0x55 | ||
1255 | }; | ||
1256 | |||
1257 | static int pm2vfb_cursor(struct fb_info *info, struct fb_cursor *cursor) | ||
1258 | { | ||
1259 | struct pm2fb_par *par = info->par; | ||
1260 | u8 mode; | ||
1261 | |||
1262 | if (!hwcursor) | ||
1263 | return -EINVAL; /* just to force soft_cursor() call */ | ||
1264 | |||
1265 | /* Too large of a cursor or wrong bpp :-( */ | ||
1266 | if (cursor->image.width > 64 || | ||
1267 | cursor->image.height > 64 || | ||
1268 | cursor->image.depth > 1) | ||
1269 | return -EINVAL; | ||
1270 | |||
1271 | mode = PM2F_CURSORMODE_TYPE_X; | ||
1272 | if (cursor->enable) | ||
1273 | mode |= PM2F_CURSORMODE_CURSOR_ENABLE; | ||
1274 | |||
1275 | pm2v_RDAC_WR(par, PM2VI_RD_CURSOR_MODE, mode); | ||
1276 | |||
1277 | /* | ||
1278 | * If the cursor is not be changed this means either we want the | ||
1279 | * current cursor state (if enable is set) or we want to query what | ||
1280 | * we can do with the cursor (if enable is not set) | ||
1281 | */ | ||
1282 | if (!cursor->set) | ||
1283 | return 0; | ||
1284 | |||
1285 | if (cursor->set & FB_CUR_SETPOS) { | ||
1286 | int x = cursor->image.dx - info->var.xoffset; | ||
1287 | int y = cursor->image.dy - info->var.yoffset; | ||
1288 | |||
1289 | pm2v_RDAC_WR(par, PM2VI_RD_CURSOR_X_LOW, x & 0xff); | ||
1290 | pm2v_RDAC_WR(par, PM2VI_RD_CURSOR_X_HIGH, (x >> 8) & 0xf); | ||
1291 | pm2v_RDAC_WR(par, PM2VI_RD_CURSOR_Y_LOW, y & 0xff); | ||
1292 | pm2v_RDAC_WR(par, PM2VI_RD_CURSOR_Y_HIGH, (y >> 8) & 0xf); | ||
1293 | } | ||
1294 | |||
1295 | if (cursor->set & FB_CUR_SETHOT) { | ||
1296 | pm2v_RDAC_WR(par, PM2VI_RD_CURSOR_X_HOT, | ||
1297 | cursor->hot.x & 0x3f); | ||
1298 | pm2v_RDAC_WR(par, PM2VI_RD_CURSOR_Y_HOT, | ||
1299 | cursor->hot.y & 0x3f); | ||
1300 | } | ||
1301 | |||
1302 | if (cursor->set & FB_CUR_SETCMAP) { | ||
1303 | u32 fg_idx = cursor->image.fg_color; | ||
1304 | u32 bg_idx = cursor->image.bg_color; | ||
1305 | struct fb_cmap cmap = info->cmap; | ||
1306 | |||
1307 | /* the X11 driver says one should use these color registers */ | ||
1308 | pm2_WR(par, PM2VR_RD_INDEX_HIGH, PM2VI_RD_CURSOR_PALETTE >> 8); | ||
1309 | pm2v_RDAC_WR(par, PM2VI_RD_CURSOR_PALETTE + 0, | ||
1310 | cmap.red[bg_idx] >> 8 ); | ||
1311 | pm2v_RDAC_WR(par, PM2VI_RD_CURSOR_PALETTE + 1, | ||
1312 | cmap.green[bg_idx] >> 8 ); | ||
1313 | pm2v_RDAC_WR(par, PM2VI_RD_CURSOR_PALETTE + 2, | ||
1314 | cmap.blue[bg_idx] >> 8 ); | ||
1315 | |||
1316 | pm2v_RDAC_WR(par, PM2VI_RD_CURSOR_PALETTE + 3, | ||
1317 | cmap.red[fg_idx] >> 8 ); | ||
1318 | pm2v_RDAC_WR(par, PM2VI_RD_CURSOR_PALETTE + 4, | ||
1319 | cmap.green[fg_idx] >> 8 ); | ||
1320 | pm2v_RDAC_WR(par, PM2VI_RD_CURSOR_PALETTE + 5, | ||
1321 | cmap.blue[fg_idx] >> 8 ); | ||
1322 | pm2_WR(par, PM2VR_RD_INDEX_HIGH, 0); | ||
1323 | } | ||
1324 | |||
1325 | if (cursor->set & (FB_CUR_SETSHAPE | FB_CUR_SETIMAGE)) { | ||
1326 | u8 *bitmap = (u8 *)cursor->image.data; | ||
1327 | u8 *mask = (u8 *)cursor->mask; | ||
1328 | int i; | ||
1329 | int pos = PM2VI_RD_CURSOR_PATTERN; | ||
1330 | |||
1331 | for (i = 0; i < cursor->image.height; i++) { | ||
1332 | int j = (cursor->image.width + 7) >> 3; | ||
1333 | int k = 8 - j; | ||
1334 | |||
1335 | pm2_WR(par, PM2VR_RD_INDEX_HIGH, pos >> 8); | ||
1336 | |||
1337 | for (; j > 0; j--) { | ||
1338 | u8 data = *bitmap ^ *mask; | ||
1339 | |||
1340 | if (cursor->rop == ROP_COPY) | ||
1341 | data = *mask & *bitmap; | ||
1342 | /* Upper 4 bits of bitmap data */ | ||
1343 | pm2v_RDAC_WR(par, pos++, | ||
1344 | cursor_bits_lookup[data >> 4] | | ||
1345 | (cursor_bits_lookup[*mask >> 4] << 1)); | ||
1346 | /* Lower 4 bits of bitmap */ | ||
1347 | pm2v_RDAC_WR(par, pos++, | ||
1348 | cursor_bits_lookup[data & 0xf] | | ||
1349 | (cursor_bits_lookup[*mask & 0xf] << 1)); | ||
1350 | bitmap++; | ||
1351 | mask++; | ||
1352 | } | ||
1353 | for (; k > 0; k--) { | ||
1354 | pm2v_RDAC_WR(par, pos++, 0); | ||
1355 | pm2v_RDAC_WR(par, pos++, 0); | ||
1356 | } | ||
1357 | } | ||
1358 | |||
1359 | while (pos < (1024 + PM2VI_RD_CURSOR_PATTERN)) { | ||
1360 | pm2_WR(par, PM2VR_RD_INDEX_HIGH, pos >> 8); | ||
1361 | pm2v_RDAC_WR(par, pos++, 0); | ||
1362 | } | ||
1363 | |||
1364 | pm2_WR(par, PM2VR_RD_INDEX_HIGH, 0); | ||
1365 | } | ||
1366 | return 0; | ||
1367 | } | ||
1368 | |||
1369 | static int pm2fb_cursor(struct fb_info *info, struct fb_cursor *cursor) | ||
1370 | { | ||
1371 | struct pm2fb_par *par = info->par; | ||
1372 | |||
1373 | if (par->type == PM2_TYPE_PERMEDIA2V) | ||
1374 | return pm2vfb_cursor(info, cursor); | ||
1375 | |||
1376 | return -ENXIO; | ||
1377 | } | ||
1378 | |||
1248 | /* ------------ Hardware Independent Functions ------------ */ | 1379 | /* ------------ Hardware Independent Functions ------------ */ |
1249 | 1380 | ||
1250 | /* | 1381 | /* |
@@ -1262,6 +1393,7 @@ static struct fb_ops pm2fb_ops = { | |||
1262 | .fb_copyarea = pm2fb_copyarea, | 1393 | .fb_copyarea = pm2fb_copyarea, |
1263 | .fb_imageblit = pm2fb_imageblit, | 1394 | .fb_imageblit = pm2fb_imageblit, |
1264 | .fb_sync = pm2fb_sync, | 1395 | .fb_sync = pm2fb_sync, |
1396 | .fb_cursor = pm2fb_cursor, | ||
1265 | }; | 1397 | }; |
1266 | 1398 | ||
1267 | /* | 1399 | /* |
@@ -1550,6 +1682,8 @@ static int __init pm2fb_setup(char *options) | |||
1550 | lowhsync = 1; | 1682 | lowhsync = 1; |
1551 | else if (!strcmp(this_opt, "lowvsync")) | 1683 | else if (!strcmp(this_opt, "lowvsync")) |
1552 | lowvsync = 1; | 1684 | lowvsync = 1; |
1685 | else if (!strncmp(this_opt, "hwcursor=", 9)) | ||
1686 | hwcursor = simple_strtoul(this_opt + 9, NULL, 0); | ||
1553 | #ifdef CONFIG_MTRR | 1687 | #ifdef CONFIG_MTRR |
1554 | else if (!strncmp(this_opt, "nomtrr", 6)) | 1688 | else if (!strncmp(this_opt, "nomtrr", 6)) |
1555 | nomtrr = 1; | 1689 | nomtrr = 1; |
@@ -1601,6 +1735,9 @@ module_param(lowvsync, bool, 0); | |||
1601 | MODULE_PARM_DESC(lowvsync, "Force vertical sync low regardless of mode"); | 1735 | MODULE_PARM_DESC(lowvsync, "Force vertical sync low regardless of mode"); |
1602 | module_param(noaccel, bool, 0); | 1736 | module_param(noaccel, bool, 0); |
1603 | MODULE_PARM_DESC(noaccel, "Disable acceleration"); | 1737 | MODULE_PARM_DESC(noaccel, "Disable acceleration"); |
1738 | module_param(hwcursor, int, 0644); | ||
1739 | MODULE_PARM_DESC(hwcursor, "Enable hardware cursor " | ||
1740 | "(1=enable, 0=disable, default=0)"); | ||
1604 | #ifdef CONFIG_MTRR | 1741 | #ifdef CONFIG_MTRR |
1605 | module_param(nomtrr, bool, 0); | 1742 | module_param(nomtrr, bool, 0); |
1606 | MODULE_PARM_DESC(nomtrr, "Disable MTRR support (0 or 1=disabled) (default=0)"); | 1743 | MODULE_PARM_DESC(nomtrr, "Disable MTRR support (0 or 1=disabled) (default=0)"); |