diff options
Diffstat (limited to 'drivers/video/sm501fb.c')
| -rw-r--r-- | drivers/video/sm501fb.c | 249 |
1 files changed, 230 insertions, 19 deletions
diff --git a/drivers/video/sm501fb.c b/drivers/video/sm501fb.c index 924d79462780..35370d0ecf03 100644 --- a/drivers/video/sm501fb.c +++ b/drivers/video/sm501fb.c | |||
| @@ -29,8 +29,8 @@ | |||
| 29 | #include <linux/platform_device.h> | 29 | #include <linux/platform_device.h> |
| 30 | #include <linux/clk.h> | 30 | #include <linux/clk.h> |
| 31 | #include <linux/console.h> | 31 | #include <linux/console.h> |
| 32 | #include <linux/io.h> | ||
| 32 | 33 | ||
| 33 | #include <asm/io.h> | ||
| 34 | #include <asm/uaccess.h> | 34 | #include <asm/uaccess.h> |
| 35 | #include <asm/div64.h> | 35 | #include <asm/div64.h> |
| 36 | 36 | ||
| @@ -66,6 +66,7 @@ struct sm501fb_info { | |||
| 66 | struct fb_info *fb[2]; /* fb info for both heads */ | 66 | struct fb_info *fb[2]; /* fb info for both heads */ |
| 67 | struct resource *fbmem_res; /* framebuffer resource */ | 67 | struct resource *fbmem_res; /* framebuffer resource */ |
| 68 | struct resource *regs_res; /* registers resource */ | 68 | struct resource *regs_res; /* registers resource */ |
| 69 | struct resource *regs2d_res; /* 2d registers resource */ | ||
| 69 | struct sm501_platdata_fb *pdata; /* our platform data */ | 70 | struct sm501_platdata_fb *pdata; /* our platform data */ |
| 70 | 71 | ||
| 71 | unsigned long pm_crt_ctrl; /* pm: crt ctrl save */ | 72 | unsigned long pm_crt_ctrl; /* pm: crt ctrl save */ |
| @@ -73,6 +74,7 @@ struct sm501fb_info { | |||
| 73 | int irq; | 74 | int irq; |
| 74 | int swap_endian; /* set to swap rgb=>bgr */ | 75 | int swap_endian; /* set to swap rgb=>bgr */ |
| 75 | void __iomem *regs; /* remapped registers */ | 76 | void __iomem *regs; /* remapped registers */ |
| 77 | void __iomem *regs2d; /* 2d remapped registers */ | ||
| 76 | void __iomem *fbmem; /* remapped framebuffer */ | 78 | void __iomem *fbmem; /* remapped framebuffer */ |
| 77 | size_t fbmem_len; /* length of remapped region */ | 79 | size_t fbmem_len; /* length of remapped region */ |
| 78 | }; | 80 | }; |
| @@ -123,9 +125,9 @@ static inline void sm501fb_sync_regs(struct sm501fb_info *info) | |||
| 123 | * This is an attempt to lay out memory for the two framebuffers and | 125 | * This is an attempt to lay out memory for the two framebuffers and |
| 124 | * everything else | 126 | * everything else |
| 125 | * | 127 | * |
| 126 | * |fbmem_res->start fbmem_res->end| | 128 | * |fbmem_res->start fbmem_res->end| |
| 127 | * | | | 129 | * | | |
| 128 | * |fb[0].fix.smem_start | |fb[1].fix.smem_start | 2K | | 130 | * |fb[0].fix.smem_start | |fb[1].fix.smem_start | 2K | |
| 129 | * |-> fb[0].fix.smem_len <-| spare |-> fb[1].fix.smem_len <-|-> cursors <-| | 131 | * |-> fb[0].fix.smem_len <-| spare |-> fb[1].fix.smem_len <-|-> cursors <-| |
| 130 | * | 132 | * |
| 131 | * The "spare" space is for the 2d engine data | 133 | * The "spare" space is for the 2d engine data |
| @@ -1246,7 +1248,173 @@ static ssize_t sm501fb_debug_show_pnl(struct device *dev, | |||
| 1246 | 1248 | ||
| 1247 | static DEVICE_ATTR(fbregs_pnl, 0444, sm501fb_debug_show_pnl, NULL); | 1249 | static DEVICE_ATTR(fbregs_pnl, 0444, sm501fb_debug_show_pnl, NULL); |
| 1248 | 1250 | ||
| 1249 | /* framebuffer ops */ | 1251 | /* acceleration operations */ |
| 1252 | static int sm501fb_sync(struct fb_info *info) | ||
| 1253 | { | ||
| 1254 | int count = 1000000; | ||
| 1255 | struct sm501fb_par *par = info->par; | ||
| 1256 | struct sm501fb_info *fbi = par->info; | ||
| 1257 | |||
| 1258 | /* wait for the 2d engine to be ready */ | ||
| 1259 | while ((count > 0) && | ||
| 1260 | (readl(fbi->regs + SM501_SYSTEM_CONTROL) & | ||
| 1261 | SM501_SYSCTRL_2D_ENGINE_STATUS) != 0) | ||
| 1262 | count--; | ||
| 1263 | |||
| 1264 | if (count <= 0) { | ||
| 1265 | dev_err(info->dev, "Timeout waiting for 2d engine sync\n"); | ||
| 1266 | return 1; | ||
| 1267 | } | ||
| 1268 | return 0; | ||
| 1269 | } | ||
| 1270 | |||
| 1271 | static void sm501fb_copyarea(struct fb_info *info, const struct fb_copyarea *area) | ||
| 1272 | { | ||
| 1273 | struct sm501fb_par *par = info->par; | ||
| 1274 | struct sm501fb_info *fbi = par->info; | ||
| 1275 | int width = area->width; | ||
| 1276 | int height = area->height; | ||
| 1277 | int sx = area->sx; | ||
| 1278 | int sy = area->sy; | ||
| 1279 | int dx = area->dx; | ||
| 1280 | int dy = area->dy; | ||
| 1281 | unsigned long rtl = 0; | ||
| 1282 | |||
| 1283 | /* source clip */ | ||
| 1284 | if ((sx >= info->var.xres_virtual) || | ||
| 1285 | (sy >= info->var.yres_virtual)) | ||
| 1286 | /* source Area not within virtual screen, skipping */ | ||
| 1287 | return; | ||
| 1288 | if ((sx + width) >= info->var.xres_virtual) | ||
| 1289 | width = info->var.xres_virtual - sx - 1; | ||
| 1290 | if ((sy + height) >= info->var.yres_virtual) | ||
| 1291 | height = info->var.yres_virtual - sy - 1; | ||
| 1292 | |||
| 1293 | /* dest clip */ | ||
| 1294 | if ((dx >= info->var.xres_virtual) || | ||
| 1295 | (dy >= info->var.yres_virtual)) | ||
| 1296 | /* Destination Area not within virtual screen, skipping */ | ||
| 1297 | return; | ||
| 1298 | if ((dx + width) >= info->var.xres_virtual) | ||
| 1299 | width = info->var.xres_virtual - dx - 1; | ||
| 1300 | if ((dy + height) >= info->var.yres_virtual) | ||
| 1301 | height = info->var.yres_virtual - dy - 1; | ||
| 1302 | |||
| 1303 | if ((sx < dx) || (sy < dy)) { | ||
| 1304 | rtl = 1 << 27; | ||
| 1305 | sx += width - 1; | ||
| 1306 | dx += width - 1; | ||
| 1307 | sy += height - 1; | ||
| 1308 | dy += height - 1; | ||
| 1309 | } | ||
| 1310 | |||
| 1311 | if (sm501fb_sync(info)) | ||
| 1312 | return; | ||
| 1313 | |||
| 1314 | /* set the base addresses */ | ||
| 1315 | writel(par->screen.sm_addr, fbi->regs2d + SM501_2D_SOURCE_BASE); | ||
| 1316 | writel(par->screen.sm_addr, fbi->regs2d + SM501_2D_DESTINATION_BASE); | ||
| 1317 | |||
| 1318 | /* set the window width */ | ||
| 1319 | writel((info->var.xres << 16) | info->var.xres, | ||
| 1320 | fbi->regs2d + SM501_2D_WINDOW_WIDTH); | ||
| 1321 | |||
| 1322 | /* set window stride */ | ||
| 1323 | writel((info->var.xres_virtual << 16) | info->var.xres_virtual, | ||
| 1324 | fbi->regs2d + SM501_2D_PITCH); | ||
| 1325 | |||
| 1326 | /* set data format */ | ||
| 1327 | switch (info->var.bits_per_pixel) { | ||
| 1328 | case 8: | ||
| 1329 | writel(0, fbi->regs2d + SM501_2D_STRETCH); | ||
| 1330 | break; | ||
| 1331 | case 16: | ||
| 1332 | writel(0x00100000, fbi->regs2d + SM501_2D_STRETCH); | ||
| 1333 | break; | ||
| 1334 | case 32: | ||
| 1335 | writel(0x00200000, fbi->regs2d + SM501_2D_STRETCH); | ||
| 1336 | break; | ||
| 1337 | } | ||
| 1338 | |||
| 1339 | /* 2d compare mask */ | ||
| 1340 | writel(0xffffffff, fbi->regs2d + SM501_2D_COLOR_COMPARE_MASK); | ||
| 1341 | |||
| 1342 | /* 2d mask */ | ||
| 1343 | writel(0xffffffff, fbi->regs2d + SM501_2D_MASK); | ||
| 1344 | |||
| 1345 | /* source and destination x y */ | ||
| 1346 | writel((sx << 16) | sy, fbi->regs2d + SM501_2D_SOURCE); | ||
| 1347 | writel((dx << 16) | dy, fbi->regs2d + SM501_2D_DESTINATION); | ||
| 1348 | |||
| 1349 | /* w/h */ | ||
| 1350 | writel((width << 16) | height, fbi->regs2d + SM501_2D_DIMENSION); | ||
| 1351 | |||
| 1352 | /* do area move */ | ||
| 1353 | writel(0x800000cc | rtl, fbi->regs2d + SM501_2D_CONTROL); | ||
| 1354 | } | ||
| 1355 | |||
| 1356 | static void sm501fb_fillrect(struct fb_info *info, const struct fb_fillrect *rect) | ||
| 1357 | { | ||
| 1358 | struct sm501fb_par *par = info->par; | ||
| 1359 | struct sm501fb_info *fbi = par->info; | ||
| 1360 | int width = rect->width, height = rect->height; | ||
| 1361 | |||
| 1362 | if ((rect->dx >= info->var.xres_virtual) || | ||
| 1363 | (rect->dy >= info->var.yres_virtual)) | ||
| 1364 | /* Rectangle not within virtual screen, skipping */ | ||
| 1365 | return; | ||
| 1366 | if ((rect->dx + width) >= info->var.xres_virtual) | ||
| 1367 | width = info->var.xres_virtual - rect->dx - 1; | ||
| 1368 | if ((rect->dy + height) >= info->var.yres_virtual) | ||
| 1369 | height = info->var.yres_virtual - rect->dy - 1; | ||
| 1370 | |||
| 1371 | if (sm501fb_sync(info)) | ||
| 1372 | return; | ||
| 1373 | |||
| 1374 | /* set the base addresses */ | ||
| 1375 | writel(par->screen.sm_addr, fbi->regs2d + SM501_2D_SOURCE_BASE); | ||
| 1376 | writel(par->screen.sm_addr, fbi->regs2d + SM501_2D_DESTINATION_BASE); | ||
| 1377 | |||
| 1378 | /* set the window width */ | ||
| 1379 | writel((info->var.xres << 16) | info->var.xres, | ||
| 1380 | fbi->regs2d + SM501_2D_WINDOW_WIDTH); | ||
| 1381 | |||
| 1382 | /* set window stride */ | ||
| 1383 | writel((info->var.xres_virtual << 16) | info->var.xres_virtual, | ||
| 1384 | fbi->regs2d + SM501_2D_PITCH); | ||
| 1385 | |||
| 1386 | /* set data format */ | ||
| 1387 | switch (info->var.bits_per_pixel) { | ||
| 1388 | case 8: | ||
| 1389 | writel(0, fbi->regs2d + SM501_2D_STRETCH); | ||
| 1390 | break; | ||
| 1391 | case 16: | ||
| 1392 | writel(0x00100000, fbi->regs2d + SM501_2D_STRETCH); | ||
| 1393 | break; | ||
| 1394 | case 32: | ||
| 1395 | writel(0x00200000, fbi->regs2d + SM501_2D_STRETCH); | ||
| 1396 | break; | ||
| 1397 | } | ||
| 1398 | |||
| 1399 | /* 2d compare mask */ | ||
| 1400 | writel(0xffffffff, fbi->regs2d + SM501_2D_COLOR_COMPARE_MASK); | ||
| 1401 | |||
| 1402 | /* 2d mask */ | ||
| 1403 | writel(0xffffffff, fbi->regs2d + SM501_2D_MASK); | ||
| 1404 | |||
| 1405 | /* colour */ | ||
| 1406 | writel(rect->color, fbi->regs2d + SM501_2D_FOREGROUND); | ||
| 1407 | |||
| 1408 | /* x y */ | ||
| 1409 | writel((rect->dx << 16) | rect->dy, fbi->regs2d + SM501_2D_DESTINATION); | ||
| 1410 | |||
| 1411 | /* w/h */ | ||
| 1412 | writel((width << 16) | height, fbi->regs2d + SM501_2D_DIMENSION); | ||
| 1413 | |||
| 1414 | /* do rectangle fill */ | ||
| 1415 | writel(0x800100cc, fbi->regs2d + SM501_2D_CONTROL); | ||
| 1416 | } | ||
| 1417 | |||
| 1250 | 1418 | ||
| 1251 | static struct fb_ops sm501fb_ops_crt = { | 1419 | static struct fb_ops sm501fb_ops_crt = { |
| 1252 | .owner = THIS_MODULE, | 1420 | .owner = THIS_MODULE, |
| @@ -1256,9 +1424,10 @@ static struct fb_ops sm501fb_ops_crt = { | |||
| 1256 | .fb_setcolreg = sm501fb_setcolreg, | 1424 | .fb_setcolreg = sm501fb_setcolreg, |
| 1257 | .fb_pan_display = sm501fb_pan_crt, | 1425 | .fb_pan_display = sm501fb_pan_crt, |
| 1258 | .fb_cursor = sm501fb_cursor, | 1426 | .fb_cursor = sm501fb_cursor, |
| 1259 | .fb_fillrect = cfb_fillrect, | 1427 | .fb_fillrect = sm501fb_fillrect, |
| 1260 | .fb_copyarea = cfb_copyarea, | 1428 | .fb_copyarea = sm501fb_copyarea, |
| 1261 | .fb_imageblit = cfb_imageblit, | 1429 | .fb_imageblit = cfb_imageblit, |
| 1430 | .fb_sync = sm501fb_sync, | ||
| 1262 | }; | 1431 | }; |
| 1263 | 1432 | ||
| 1264 | static struct fb_ops sm501fb_ops_pnl = { | 1433 | static struct fb_ops sm501fb_ops_pnl = { |
| @@ -1269,9 +1438,10 @@ static struct fb_ops sm501fb_ops_pnl = { | |||
| 1269 | .fb_blank = sm501fb_blank_pnl, | 1438 | .fb_blank = sm501fb_blank_pnl, |
| 1270 | .fb_setcolreg = sm501fb_setcolreg, | 1439 | .fb_setcolreg = sm501fb_setcolreg, |
| 1271 | .fb_cursor = sm501fb_cursor, | 1440 | .fb_cursor = sm501fb_cursor, |
| 1272 | .fb_fillrect = cfb_fillrect, | 1441 | .fb_fillrect = sm501fb_fillrect, |
| 1273 | .fb_copyarea = cfb_copyarea, | 1442 | .fb_copyarea = sm501fb_copyarea, |
| 1274 | .fb_imageblit = cfb_imageblit, | 1443 | .fb_imageblit = cfb_imageblit, |
| 1444 | .fb_sync = sm501fb_sync, | ||
| 1275 | }; | 1445 | }; |
| 1276 | 1446 | ||
| 1277 | /* sm501_init_cursor | 1447 | /* sm501_init_cursor |
| @@ -1329,7 +1499,8 @@ static int sm501fb_start(struct sm501fb_info *info, | |||
| 1329 | dev_warn(dev, "no irq for device\n"); | 1499 | dev_warn(dev, "no irq for device\n"); |
| 1330 | } | 1500 | } |
| 1331 | 1501 | ||
| 1332 | /* allocate, reserve and remap resources for registers */ | 1502 | /* allocate, reserve and remap resources for display |
| 1503 | * controller registers */ | ||
| 1333 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 1504 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| 1334 | if (res == NULL) { | 1505 | if (res == NULL) { |
| 1335 | dev_err(dev, "no resource definition for registers\n"); | 1506 | dev_err(dev, "no resource definition for registers\n"); |
| @@ -1338,7 +1509,7 @@ static int sm501fb_start(struct sm501fb_info *info, | |||
| 1338 | } | 1509 | } |
| 1339 | 1510 | ||
| 1340 | info->regs_res = request_mem_region(res->start, | 1511 | info->regs_res = request_mem_region(res->start, |
| 1341 | res->end - res->start, | 1512 | resource_size(res), |
| 1342 | pdev->name); | 1513 | pdev->name); |
| 1343 | 1514 | ||
| 1344 | if (info->regs_res == NULL) { | 1515 | if (info->regs_res == NULL) { |
| @@ -1347,37 +1518,63 @@ static int sm501fb_start(struct sm501fb_info *info, | |||
| 1347 | goto err_release; | 1518 | goto err_release; |
| 1348 | } | 1519 | } |
| 1349 | 1520 | ||
| 1350 | info->regs = ioremap(res->start, (res->end - res->start)+1); | 1521 | info->regs = ioremap(res->start, resource_size(res)); |
| 1351 | if (info->regs == NULL) { | 1522 | if (info->regs == NULL) { |
| 1352 | dev_err(dev, "cannot remap registers\n"); | 1523 | dev_err(dev, "cannot remap registers\n"); |
| 1353 | ret = -ENXIO; | 1524 | ret = -ENXIO; |
| 1354 | goto err_regs_res; | 1525 | goto err_regs_res; |
| 1355 | } | 1526 | } |
| 1356 | 1527 | ||
| 1528 | /* allocate, reserve and remap resources for 2d | ||
| 1529 | * controller registers */ | ||
| 1530 | res = platform_get_resource(pdev, IORESOURCE_MEM, 1); | ||
| 1531 | if (res == NULL) { | ||
| 1532 | dev_err(dev, "no resource definition for 2d registers\n"); | ||
| 1533 | ret = -ENOENT; | ||
| 1534 | goto err_regs_map; | ||
| 1535 | } | ||
| 1536 | |||
| 1537 | info->regs2d_res = request_mem_region(res->start, | ||
| 1538 | resource_size(res), | ||
| 1539 | pdev->name); | ||
| 1540 | |||
| 1541 | if (info->regs2d_res == NULL) { | ||
| 1542 | dev_err(dev, "cannot claim registers\n"); | ||
| 1543 | ret = -ENXIO; | ||
| 1544 | goto err_regs_map; | ||
| 1545 | } | ||
| 1546 | |||
| 1547 | info->regs2d = ioremap(res->start, resource_size(res)); | ||
| 1548 | if (info->regs2d == NULL) { | ||
| 1549 | dev_err(dev, "cannot remap registers\n"); | ||
| 1550 | ret = -ENXIO; | ||
| 1551 | goto err_regs2d_res; | ||
| 1552 | } | ||
| 1553 | |||
| 1357 | /* allocate, reserve resources for framebuffer */ | 1554 | /* allocate, reserve resources for framebuffer */ |
| 1358 | res = platform_get_resource(pdev, IORESOURCE_MEM, 2); | 1555 | res = platform_get_resource(pdev, IORESOURCE_MEM, 2); |
| 1359 | if (res == NULL) { | 1556 | if (res == NULL) { |
| 1360 | dev_err(dev, "no memory resource defined\n"); | 1557 | dev_err(dev, "no memory resource defined\n"); |
| 1361 | ret = -ENXIO; | 1558 | ret = -ENXIO; |
| 1362 | goto err_regs_map; | 1559 | goto err_regs2d_map; |
| 1363 | } | 1560 | } |
| 1364 | 1561 | ||
| 1365 | info->fbmem_res = request_mem_region(res->start, | 1562 | info->fbmem_res = request_mem_region(res->start, |
| 1366 | (res->end - res->start)+1, | 1563 | resource_size(res), |
| 1367 | pdev->name); | 1564 | pdev->name); |
| 1368 | if (info->fbmem_res == NULL) { | 1565 | if (info->fbmem_res == NULL) { |
| 1369 | dev_err(dev, "cannot claim framebuffer\n"); | 1566 | dev_err(dev, "cannot claim framebuffer\n"); |
| 1370 | ret = -ENXIO; | 1567 | ret = -ENXIO; |
| 1371 | goto err_regs_map; | 1568 | goto err_regs2d_map; |
| 1372 | } | 1569 | } |
| 1373 | 1570 | ||
| 1374 | info->fbmem = ioremap(res->start, (res->end - res->start)+1); | 1571 | info->fbmem = ioremap(res->start, resource_size(res)); |
| 1375 | if (info->fbmem == NULL) { | 1572 | if (info->fbmem == NULL) { |
| 1376 | dev_err(dev, "cannot remap framebuffer\n"); | 1573 | dev_err(dev, "cannot remap framebuffer\n"); |
| 1377 | goto err_mem_res; | 1574 | goto err_mem_res; |
| 1378 | } | 1575 | } |
| 1379 | 1576 | ||
| 1380 | info->fbmem_len = (res->end - res->start)+1; | 1577 | info->fbmem_len = resource_size(res); |
| 1381 | 1578 | ||
| 1382 | /* clear framebuffer memory - avoids garbage data on unused fb */ | 1579 | /* clear framebuffer memory - avoids garbage data on unused fb */ |
| 1383 | memset(info->fbmem, 0, info->fbmem_len); | 1580 | memset(info->fbmem, 0, info->fbmem_len); |
| @@ -1389,8 +1586,10 @@ static int sm501fb_start(struct sm501fb_info *info, | |||
| 1389 | /* enable display controller */ | 1586 | /* enable display controller */ |
| 1390 | sm501_unit_power(dev->parent, SM501_GATE_DISPLAY, 1); | 1587 | sm501_unit_power(dev->parent, SM501_GATE_DISPLAY, 1); |
| 1391 | 1588 | ||
| 1392 | /* setup cursors */ | 1589 | /* enable 2d controller */ |
| 1590 | sm501_unit_power(dev->parent, SM501_GATE_2D_ENGINE, 1); | ||
| 1393 | 1591 | ||
| 1592 | /* setup cursors */ | ||
| 1394 | sm501_init_cursor(info->fb[HEAD_CRT], SM501_DC_CRT_HWC_ADDR); | 1593 | sm501_init_cursor(info->fb[HEAD_CRT], SM501_DC_CRT_HWC_ADDR); |
| 1395 | sm501_init_cursor(info->fb[HEAD_PANEL], SM501_DC_PANEL_HWC_ADDR); | 1594 | sm501_init_cursor(info->fb[HEAD_PANEL], SM501_DC_PANEL_HWC_ADDR); |
| 1396 | 1595 | ||
| @@ -1400,6 +1599,13 @@ static int sm501fb_start(struct sm501fb_info *info, | |||
| 1400 | release_resource(info->fbmem_res); | 1599 | release_resource(info->fbmem_res); |
| 1401 | kfree(info->fbmem_res); | 1600 | kfree(info->fbmem_res); |
| 1402 | 1601 | ||
| 1602 | err_regs2d_map: | ||
| 1603 | iounmap(info->regs2d); | ||
| 1604 | |||
| 1605 | err_regs2d_res: | ||
| 1606 | release_resource(info->regs2d_res); | ||
| 1607 | kfree(info->regs2d_res); | ||
| 1608 | |||
| 1403 | err_regs_map: | 1609 | err_regs_map: |
| 1404 | iounmap(info->regs); | 1610 | iounmap(info->regs); |
| 1405 | 1611 | ||
| @@ -1420,6 +1626,10 @@ static void sm501fb_stop(struct sm501fb_info *info) | |||
| 1420 | release_resource(info->fbmem_res); | 1626 | release_resource(info->fbmem_res); |
| 1421 | kfree(info->fbmem_res); | 1627 | kfree(info->fbmem_res); |
| 1422 | 1628 | ||
| 1629 | iounmap(info->regs2d); | ||
| 1630 | release_resource(info->regs2d_res); | ||
| 1631 | kfree(info->regs2d_res); | ||
| 1632 | |||
| 1423 | iounmap(info->regs); | 1633 | iounmap(info->regs); |
| 1424 | release_resource(info->regs_res); | 1634 | release_resource(info->regs_res); |
| 1425 | kfree(info->regs_res); | 1635 | kfree(info->regs_res); |
| @@ -1486,7 +1696,8 @@ static int sm501fb_init_fb(struct fb_info *fb, | |||
| 1486 | par->ops.fb_cursor = NULL; | 1696 | par->ops.fb_cursor = NULL; |
| 1487 | 1697 | ||
| 1488 | fb->fbops = &par->ops; | 1698 | fb->fbops = &par->ops; |
| 1489 | fb->flags = FBINFO_FLAG_DEFAULT | | 1699 | fb->flags = FBINFO_FLAG_DEFAULT | FBINFO_READS_FAST | |
| 1700 | FBINFO_HWACCEL_COPYAREA | FBINFO_HWACCEL_FILLRECT | | ||
| 1490 | FBINFO_HWACCEL_XPAN | FBINFO_HWACCEL_YPAN; | 1701 | FBINFO_HWACCEL_XPAN | FBINFO_HWACCEL_YPAN; |
| 1491 | 1702 | ||
| 1492 | /* fixed data */ | 1703 | /* fixed data */ |
