aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/pm2fb.c
diff options
context:
space:
mode:
authorKrzysztof Helt <krzysztof.h1@wp.pl>2007-10-16 04:28:53 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-10-16 12:43:16 -0400
commit8f5d050af1da13455068cefbaf3c1bc306d6fe0b (patch)
tree8bb467007c47dbe822b62d3d4bff7dec69fc53c3 /drivers/video/pm2fb.c
parent5a258d032d8dff1c5e28ce64c47ac4577c2c5a70 (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.c137
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 */
69static int hwcursor;
69static char *mode __devinitdata; 70static 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 */
1252static 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
1257static 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
1369static 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);
1601MODULE_PARM_DESC(lowvsync, "Force vertical sync low regardless of mode"); 1735MODULE_PARM_DESC(lowvsync, "Force vertical sync low regardless of mode");
1602module_param(noaccel, bool, 0); 1736module_param(noaccel, bool, 0);
1603MODULE_PARM_DESC(noaccel, "Disable acceleration"); 1737MODULE_PARM_DESC(noaccel, "Disable acceleration");
1738module_param(hwcursor, int, 0644);
1739MODULE_PARM_DESC(hwcursor, "Enable hardware cursor "
1740 "(1=enable, 0=disable, default=0)");
1604#ifdef CONFIG_MTRR 1741#ifdef CONFIG_MTRR
1605module_param(nomtrr, bool, 0); 1742module_param(nomtrr, bool, 0);
1606MODULE_PARM_DESC(nomtrr, "Disable MTRR support (0 or 1=disabled) (default=0)"); 1743MODULE_PARM_DESC(nomtrr, "Disable MTRR support (0 or 1=disabled) (default=0)");