1247
1249
static DEVICE_ATTR(fbregs_pnl, 0444, sm501fb_debug_show_pnl, NULL);
1249
/* framebuffer ops */
1251
/* acceleration operations */
1252
static int sm501fb_sync(struct fb_info *info)
1254
int count = 1000000;
1255
struct sm501fb_par *par = info->par;
1256
struct sm501fb_info *fbi = par->info;
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)
1265
dev_err(info->dev, "Timeout waiting for 2d engine sync\n");
1271
static void sm501fb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
1273
struct sm501fb_par *par = info->par;
1274
struct sm501fb_info *fbi = par->info;
1275
int width = area->width;
1276
int height = area->height;
1281
unsigned long rtl = 0;
1284
if ((sx >= info->var.xres_virtual) ||
1285
(sy >= info->var.yres_virtual))
1286
/* source Area not within virtual screen, skipping */
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;
1294
if ((dx >= info->var.xres_virtual) ||
1295
(dy >= info->var.yres_virtual))
1296
/* Destination Area not within virtual screen, skipping */
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;
1303
if ((sx < dx) || (sy < dy)) {
1311
if (sm501fb_sync(info))
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);
1318
/* set the window width */
1319
writel((info->var.xres << 16) | info->var.xres,
1320
fbi->regs2d + SM501_2D_WINDOW_WIDTH);
1322
/* set window stride */
1323
writel((info->var.xres_virtual << 16) | info->var.xres_virtual,
1324
fbi->regs2d + SM501_2D_PITCH);
1326
/* set data format */
1327
switch (info->var.bits_per_pixel) {
1329
writel(0, fbi->regs2d + SM501_2D_STRETCH);
1332
writel(0x00100000, fbi->regs2d + SM501_2D_STRETCH);
1335
writel(0x00200000, fbi->regs2d + SM501_2D_STRETCH);
1339
/* 2d compare mask */
1340
writel(0xffffffff, fbi->regs2d + SM501_2D_COLOR_COMPARE_MASK);
1343
writel(0xffffffff, fbi->regs2d + SM501_2D_MASK);
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);
1350
writel((width << 16) | height, fbi->regs2d + SM501_2D_DIMENSION);
1353
writel(0x800000cc | rtl, fbi->regs2d + SM501_2D_CONTROL);
1356
static void sm501fb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
1358
struct sm501fb_par *par = info->par;
1359
struct sm501fb_info *fbi = par->info;
1360
int width = rect->width, height = rect->height;
1362
if ((rect->dx >= info->var.xres_virtual) ||
1363
(rect->dy >= info->var.yres_virtual))
1364
/* Rectangle not within virtual screen, skipping */
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;
1371
if (sm501fb_sync(info))
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);
1378
/* set the window width */
1379
writel((info->var.xres << 16) | info->var.xres,
1380
fbi->regs2d + SM501_2D_WINDOW_WIDTH);
1382
/* set window stride */
1383
writel((info->var.xres_virtual << 16) | info->var.xres_virtual,
1384
fbi->regs2d + SM501_2D_PITCH);
1386
/* set data format */
1387
switch (info->var.bits_per_pixel) {
1389
writel(0, fbi->regs2d + SM501_2D_STRETCH);
1392
writel(0x00100000, fbi->regs2d + SM501_2D_STRETCH);
1395
writel(0x00200000, fbi->regs2d + SM501_2D_STRETCH);
1399
/* 2d compare mask */
1400
writel(0xffffffff, fbi->regs2d + SM501_2D_COLOR_COMPARE_MASK);
1403
writel(0xffffffff, fbi->regs2d + SM501_2D_MASK);
1406
writel(rect->color, fbi->regs2d + SM501_2D_FOREGROUND);
1409
writel((rect->dx << 16) | rect->dy, fbi->regs2d + SM501_2D_DESTINATION);
1412
writel((width << 16) | height, fbi->regs2d + SM501_2D_DIMENSION);
1414
/* do rectangle fill */
1415
writel(0x800100cc, fbi->regs2d + SM501_2D_CONTROL);
1251
1419
static struct fb_ops sm501fb_ops_crt = {
1252
1420
.owner = THIS_MODULE,
1347
1518
goto err_release;
1350
info->regs = ioremap(res->start, (res->end - res->start)+1);
1521
info->regs = ioremap(res->start, resource_size(res));
1351
1522
if (info->regs == NULL) {
1352
1523
dev_err(dev, "cannot remap registers\n");
1354
1525
goto err_regs_res;
1528
/* allocate, reserve and remap resources for 2d
1529
* controller registers */
1530
res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
1532
dev_err(dev, "no resource definition for 2d registers\n");
1537
info->regs2d_res = request_mem_region(res->start,
1541
if (info->regs2d_res == NULL) {
1542
dev_err(dev, "cannot claim registers\n");
1547
info->regs2d = ioremap(res->start, resource_size(res));
1548
if (info->regs2d == NULL) {
1549
dev_err(dev, "cannot remap registers\n");
1551
goto err_regs2d_res;
1357
1554
/* allocate, reserve resources for framebuffer */
1358
1555
res = platform_get_resource(pdev, IORESOURCE_MEM, 2);
1359
1556
if (res == NULL) {
1360
1557
dev_err(dev, "no memory resource defined\n");
1559
goto err_regs2d_map;
1365
1562
info->fbmem_res = request_mem_region(res->start,
1366
(res->end - res->start)+1,
1368
1565
if (info->fbmem_res == NULL) {
1369
1566
dev_err(dev, "cannot claim framebuffer\n");
1568
goto err_regs2d_map;
1374
info->fbmem = ioremap(res->start, (res->end - res->start)+1);
1571
info->fbmem = ioremap(res->start, resource_size(res));
1375
1572
if (info->fbmem == NULL) {
1376
1573
dev_err(dev, "cannot remap framebuffer\n");
1377
1574
goto err_mem_res;
1380
info->fbmem_len = (res->end - res->start)+1;
1577
info->fbmem_len = resource_size(res);
1382
1579
/* clear framebuffer memory - avoids garbage data on unused fb */
1383
1580
memset(info->fbmem, 0, info->fbmem_len);