aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/sm501fb.c
diff options
context:
space:
mode:
authorBen Dooks <ben-linux@fluff.org>2008-07-24 00:31:36 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2008-07-24 13:47:40 -0400
commit9b599fb2fc23386dfd2965bf7d10b2b0f628b208 (patch)
treeaad37295d1c6e5246bd31d785bef92755a9b2d89 /drivers/video/sm501fb.c
parent206c5d69d0540024faffd423fc703f1e457332d7 (diff)
sm501: restructure init to allow only 1 fb on an SM501
Add the ability to register only one of the two possible main framebuffer devices on the SM501 by passing platform data for only the framebuffer that you are interested in having. As a side note, we update the init sequence to commonise the code that is executed twice, and fix a pair of missing frees that we didn't do on framebuffer exit, such as freeing the fb's cmap. Signed-off-by: Ben Dooks <ben-linux@fluff.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/video/sm501fb.c')
-rw-r--r--drivers/video/sm501fb.c264
1 files changed, 149 insertions, 115 deletions
diff --git a/drivers/video/sm501fb.c b/drivers/video/sm501fb.c
index 122a0f8495c8..b473cf665d83 100644
--- a/drivers/video/sm501fb.c
+++ b/drivers/video/sm501fb.c
@@ -143,6 +143,8 @@ static int sm501_alloc_mem(struct sm501fb_info *inf, struct sm501_mem *mem,
143 unsigned int why, size_t size) 143 unsigned int why, size_t size)
144{ 144{
145 unsigned int ptr = 0; 145 unsigned int ptr = 0;
146 unsigned int end;
147 struct fb_info *fbi;
146 148
147 switch (why) { 149 switch (why) {
148 case SM501_MEMF_CURSOR: 150 case SM501_MEMF_CURSOR:
@@ -152,7 +154,9 @@ static int sm501_alloc_mem(struct sm501fb_info *inf, struct sm501_mem *mem,
152 154
153 case SM501_MEMF_PANEL: 155 case SM501_MEMF_PANEL:
154 ptr = inf->fbmem_len - size; 156 ptr = inf->fbmem_len - size;
155 if (ptr < inf->fb[0]->fix.smem_len) 157 fbi = inf->fb[0];
158
159 if (fbi && ptr < fbi->fix.smem_len)
156 return -ENOMEM; 160 return -ENOMEM;
157 161
158 break; 162 break;
@@ -162,11 +166,18 @@ static int sm501_alloc_mem(struct sm501fb_info *inf, struct sm501_mem *mem,
162 break; 166 break;
163 167
164 case SM501_MEMF_ACCEL: 168 case SM501_MEMF_ACCEL:
165 ptr = inf->fb[0]->fix.smem_len; 169 fbi = inf->fb[0];
170 ptr = fbi ? fbi->fix.smem_len : 0;
171
172 fbi = inf->fb[1];
173 if (fbi)
174 end = (fbi->fix.smem_start - inf->fbmem_res->start);
175 else
176 end = inf->fbmem_len;
166 177
167 if ((ptr + size) > 178 if ((ptr + size) > end)
168 (inf->fb[1]->fix.smem_start - inf->fbmem_res->start))
169 return -ENOMEM; 179 return -ENOMEM;
180
170 break; 181 break;
171 182
172 default: 183 default:
@@ -1228,39 +1239,6 @@ static struct fb_ops sm501fb_ops_pnl = {
1228 .fb_imageblit = cfb_imageblit, 1239 .fb_imageblit = cfb_imageblit,
1229}; 1240};
1230 1241
1231/* sm501fb_info_alloc
1232 *
1233 * creates and initialises an sm501fb_info structure
1234*/
1235
1236static struct sm501fb_info *sm501fb_info_alloc(struct fb_info *fbinfo_crt,
1237 struct fb_info *fbinfo_pnl)
1238{
1239 struct sm501fb_info *info;
1240 struct sm501fb_par *par;
1241
1242 info = kzalloc(sizeof(struct sm501fb_info), GFP_KERNEL);
1243 if (info) {
1244 /* set the references back */
1245
1246 par = fbinfo_crt->par;
1247 par->info = info;
1248 par->head = HEAD_CRT;
1249 fbinfo_crt->pseudo_palette = &par->pseudo_palette;
1250
1251 par = fbinfo_pnl->par;
1252 par->info = info;
1253 par->head = HEAD_PANEL;
1254 fbinfo_pnl->pseudo_palette = &par->pseudo_palette;
1255
1256 /* store the two fbs into our info */
1257 info->fb[HEAD_CRT] = fbinfo_crt;
1258 info->fb[HEAD_PANEL] = fbinfo_pnl;
1259 }
1260
1261 return info;
1262}
1263
1264/* sm501_init_cursor 1242/* sm501_init_cursor
1265 * 1243 *
1266 * initialise hw cursor parameters 1244 * initialise hw cursor parameters
@@ -1268,10 +1246,16 @@ static struct sm501fb_info *sm501fb_info_alloc(struct fb_info *fbinfo_crt,
1268 1246
1269static int sm501_init_cursor(struct fb_info *fbi, unsigned int reg_base) 1247static int sm501_init_cursor(struct fb_info *fbi, unsigned int reg_base)
1270{ 1248{
1271 struct sm501fb_par *par = fbi->par; 1249 struct sm501fb_par *par;
1272 struct sm501fb_info *info = par->info; 1250 struct sm501fb_info *info;
1273 int ret; 1251 int ret;
1274 1252
1253 if (fbi == NULL)
1254 return 0;
1255
1256 par = fbi->par;
1257 info = par->info;
1258
1275 par->cursor_regs = info->regs + reg_base; 1259 par->cursor_regs = info->regs + reg_base;
1276 1260
1277 ret = sm501_alloc_mem(info, &par->cursor, SM501_MEMF_CURSOR, 1024); 1261 ret = sm501_alloc_mem(info, &par->cursor, SM501_MEMF_CURSOR, 1024);
@@ -1299,13 +1283,10 @@ static int sm501fb_start(struct sm501fb_info *info,
1299 struct platform_device *pdev) 1283 struct platform_device *pdev)
1300{ 1284{
1301 struct resource *res; 1285 struct resource *res;
1302 struct device *dev; 1286 struct device *dev = &pdev->dev;
1303 int k; 1287 int k;
1304 int ret; 1288 int ret;
1305 1289
1306 info->dev = dev = &pdev->dev;
1307 platform_set_drvdata(pdev, info);
1308
1309 info->irq = ret = platform_get_irq(pdev, 0); 1290 info->irq = ret = platform_get_irq(pdev, 0);
1310 if (ret < 0) { 1291 if (ret < 0) {
1311 /* we currently do not use the IRQ */ 1292 /* we currently do not use the IRQ */
@@ -1408,11 +1389,6 @@ static void sm501fb_stop(struct sm501fb_info *info)
1408 kfree(info->regs_res); 1389 kfree(info->regs_res);
1409} 1390}
1410 1391
1411static void sm501fb_info_release(struct sm501fb_info *info)
1412{
1413 kfree(info);
1414}
1415
1416static int sm501fb_init_fb(struct fb_info *fb, 1392static int sm501fb_init_fb(struct fb_info *fb,
1417 enum sm501_controller head, 1393 enum sm501_controller head,
1418 const char *fbname) 1394 const char *fbname)
@@ -1557,36 +1533,93 @@ static struct sm501_platdata_fb sm501fb_def_pdata = {
1557static char driver_name_crt[] = "sm501fb-crt"; 1533static char driver_name_crt[] = "sm501fb-crt";
1558static char driver_name_pnl[] = "sm501fb-panel"; 1534static char driver_name_pnl[] = "sm501fb-panel";
1559 1535
1560static int __init sm501fb_probe(struct platform_device *pdev) 1536static int __devinit sm501fb_probe_one(struct sm501fb_info *info,
1537 enum sm501_controller head)
1561{ 1538{
1562 struct sm501fb_info *info; 1539 unsigned char *name = (head == HEAD_CRT) ? "crt" : "panel";
1563 struct device *dev = &pdev->dev; 1540 struct sm501_platdata_fbsub *pd;
1564 struct fb_info *fbinfo_crt; 1541 struct sm501fb_par *par;
1565 struct fb_info *fbinfo_pnl; 1542 struct fb_info *fbi;
1566 int ret;
1567 1543
1568 /* allocate our framebuffers */ 1544 pd = (head == HEAD_CRT) ? info->pdata->fb_crt : info->pdata->fb_pnl;
1569 1545
1570 fbinfo_crt = framebuffer_alloc(sizeof(struct sm501fb_par), dev); 1546 /* Do not initialise if we've not been given any platform data */
1571 if (fbinfo_crt == NULL) { 1547 if (pd == NULL) {
1572 dev_err(dev, "cannot allocate crt framebuffer\n"); 1548 dev_info(info->dev, "no data for fb %s (disabled)\n", name);
1549 return 0;
1550 }
1551
1552 fbi = framebuffer_alloc(sizeof(struct sm501fb_par), info->dev);
1553 if (fbi == NULL) {
1554 dev_err(info->dev, "cannot allocate %s framebuffer\n", name);
1573 return -ENOMEM; 1555 return -ENOMEM;
1574 } 1556 }
1575 1557
1576 fbinfo_pnl = framebuffer_alloc(sizeof(struct sm501fb_par), dev); 1558 par = fbi->par;
1577 if (fbinfo_pnl == NULL) { 1559 par->info = info;
1578 dev_err(dev, "cannot allocate panel framebuffer\n"); 1560 par->head = head;
1579 ret = -ENOMEM; 1561 fbi->pseudo_palette = &par->pseudo_palette;
1580 goto fbinfo_crt_alloc_fail; 1562
1563 info->fb[head] = fbi;
1564
1565 return 0;
1566}
1567
1568/* Free up anything allocated by sm501fb_init_fb */
1569
1570static void sm501_free_init_fb(struct sm501fb_info *info,
1571 enum sm501_controller head)
1572{
1573 struct fb_info *fbi = info->fb[head];
1574
1575 fb_dealloc_cmap(&fbi->cmap);
1576}
1577
1578static int __devinit sm501fb_start_one(struct sm501fb_info *info,
1579 enum sm501_controller head,
1580 const char *drvname)
1581{
1582 struct fb_info *fbi = info->fb[head];
1583 int ret;
1584
1585 if (!fbi)
1586 return 0;
1587
1588 ret = sm501fb_init_fb(info->fb[head], head, drvname);
1589 if (ret) {
1590 dev_err(info->dev, "cannot initialise fb %s\n", drvname);
1591 return ret;
1592 }
1593
1594 ret = register_framebuffer(info->fb[head]);
1595 if (ret) {
1596 dev_err(info->dev, "failed to register fb %s\n", drvname);
1597 sm501_free_init_fb(info, head);
1598 return ret;
1581 } 1599 }
1582 1600
1583 info = sm501fb_info_alloc(fbinfo_crt, fbinfo_pnl); 1601 dev_info(info->dev, "fb%d: %s frame buffer\n", fbi->node, fbi->fix.id);
1584 if (info == NULL) { 1602
1585 dev_err(dev, "cannot allocate par\n"); 1603 return 0;
1586 ret = -ENOMEM; 1604}
1587 goto sm501fb_alloc_fail; 1605
1606static int __devinit sm501fb_probe(struct platform_device *pdev)
1607{
1608 struct sm501fb_info *info;
1609 struct device *dev = &pdev->dev;
1610 int ret;
1611
1612 /* allocate our framebuffers */
1613
1614 info = kzalloc(sizeof(struct sm501fb_info), GFP_KERNEL);
1615 if (!info) {
1616 dev_err(dev, "failed to allocate state\n");
1617 return -ENOMEM;
1588 } 1618 }
1589 1619
1620 info->dev = dev = &pdev->dev;
1621 platform_set_drvdata(pdev, info);
1622
1590 if (dev->parent->platform_data) { 1623 if (dev->parent->platform_data) {
1591 struct sm501_platdata *pd = dev->parent->platform_data; 1624 struct sm501_platdata *pd = dev->parent->platform_data;
1592 info->pdata = pd->fb; 1625 info->pdata = pd->fb;
@@ -1597,90 +1630,88 @@ static int __init sm501fb_probe(struct platform_device *pdev)
1597 info->pdata = &sm501fb_def_pdata; 1630 info->pdata = &sm501fb_def_pdata;
1598 } 1631 }
1599 1632
1600 /* start the framebuffers */ 1633 /* probe for the presence of each panel */
1601 1634
1602 ret = sm501fb_start(info, pdev); 1635 ret = sm501fb_probe_one(info, HEAD_CRT);
1603 if (ret) { 1636 if (ret < 0) {
1604 dev_err(dev, "cannot initialise SM501\n"); 1637 dev_err(dev, "failed to probe CRT\n");
1605 goto sm501fb_start_fail; 1638 goto err_alloc;
1606 } 1639 }
1607 1640
1608 /* CRT framebuffer setup */ 1641 ret = sm501fb_probe_one(info, HEAD_PANEL);
1642 if (ret < 0) {
1643 dev_err(dev, "failed to probe PANEL\n");
1644 goto err_probed_crt;
1645 }
1609 1646
1610 ret = sm501fb_init_fb(fbinfo_crt, HEAD_CRT, driver_name_crt); 1647 if (info->fb[HEAD_PANEL] == NULL &&
1611 if (ret) { 1648 info->fb[HEAD_CRT] == NULL) {
1612 dev_err(dev, "cannot initialise CRT fb\n"); 1649 dev_err(dev, "no framebuffers found\n");
1613 goto sm501fb_start_fail; 1650 goto err_alloc;
1614 } 1651 }
1615 1652
1616 /* Panel framebuffer setup */ 1653 /* get the resources for both of the framebuffers */
1617 1654
1618 ret = sm501fb_init_fb(fbinfo_pnl, HEAD_PANEL, driver_name_pnl); 1655 ret = sm501fb_start(info, pdev);
1619 if (ret) { 1656 if (ret) {
1620 dev_err(dev, "cannot initialise Panel fb\n"); 1657 dev_err(dev, "cannot initialise SM501\n");
1621 goto sm501fb_start_fail; 1658 goto err_probed_panel;
1622 } 1659 }
1623 1660
1624 /* register framebuffers */ 1661 ret = sm501fb_start_one(info, HEAD_CRT, driver_name_crt);
1625 1662 if (ret) {
1626 ret = register_framebuffer(fbinfo_crt); 1663 dev_err(dev, "failed to start CRT\n");
1627 if (ret < 0) { 1664 goto err_started;
1628 dev_err(dev, "failed to register CRT fb (%d)\n", ret);
1629 goto register_crt_fail;
1630 } 1665 }
1631 1666
1632 ret = register_framebuffer(fbinfo_pnl); 1667 ret = sm501fb_start_one(info, HEAD_PANEL, driver_name_pnl);
1633 if (ret < 0) { 1668 if (ret) {
1634 dev_err(dev, "failed to register panel fb (%d)\n", ret); 1669 dev_err(dev, "failed to start Panel\n");
1635 goto register_pnl_fail; 1670 goto err_started_crt;
1636 } 1671 }
1637 1672
1638 dev_info(dev, "fb%d: %s frame buffer device\n",
1639 fbinfo_crt->node, fbinfo_crt->fix.id);
1640
1641 dev_info(dev, "fb%d: %s frame buffer device\n",
1642 fbinfo_pnl->node, fbinfo_pnl->fix.id);
1643
1644 /* create device files */ 1673 /* create device files */
1645 1674
1646 ret = device_create_file(dev, &dev_attr_crt_src); 1675 ret = device_create_file(dev, &dev_attr_crt_src);
1647 if (ret) 1676 if (ret)
1648 goto crtsrc_fail; 1677 goto err_started_panel;
1649 1678
1650 ret = device_create_file(dev, &dev_attr_fbregs_pnl); 1679 ret = device_create_file(dev, &dev_attr_fbregs_pnl);
1651 if (ret) 1680 if (ret)
1652 goto fbregs_pnl_fail; 1681 goto err_attached_crtsrc_file;
1653 1682
1654 ret = device_create_file(dev, &dev_attr_fbregs_crt); 1683 ret = device_create_file(dev, &dev_attr_fbregs_crt);
1655 if (ret) 1684 if (ret)
1656 goto fbregs_crt_fail; 1685 goto err_attached_pnlregs_file;
1657 1686
1658 /* we registered, return ok */ 1687 /* we registered, return ok */
1659 return 0; 1688 return 0;
1660 1689
1661 fbregs_crt_fail: 1690err_attached_pnlregs_file:
1662 device_remove_file(dev, &dev_attr_fbregs_pnl); 1691 device_remove_file(dev, &dev_attr_fbregs_pnl);
1663 1692
1664 fbregs_pnl_fail: 1693err_attached_crtsrc_file:
1665 device_remove_file(dev, &dev_attr_crt_src); 1694 device_remove_file(dev, &dev_attr_crt_src);
1666 1695
1667 crtsrc_fail: 1696err_started_panel:
1668 unregister_framebuffer(fbinfo_pnl); 1697 unregister_framebuffer(info->fb[HEAD_PANEL]);
1698 sm501_free_init_fb(info, HEAD_PANEL);
1669 1699
1670 register_pnl_fail: 1700err_started_crt:
1671 unregister_framebuffer(fbinfo_crt); 1701 unregister_framebuffer(info->fb[HEAD_CRT]);
1702 sm501_free_init_fb(info, HEAD_CRT);
1672 1703
1673 register_crt_fail: 1704err_started:
1674 sm501fb_stop(info); 1705 sm501fb_stop(info);
1675 1706
1676 sm501fb_start_fail: 1707err_probed_panel:
1677 sm501fb_info_release(info); 1708 framebuffer_release(info->fb[HEAD_PANEL]);
1678 1709
1679 sm501fb_alloc_fail: 1710err_probed_crt:
1680 framebuffer_release(fbinfo_pnl); 1711 framebuffer_release(info->fb[HEAD_CRT]);
1681 1712
1682 fbinfo_crt_alloc_fail: 1713err_alloc:
1683 framebuffer_release(fbinfo_crt); 1714 kfree(info);
1684 1715
1685 return ret; 1716 return ret;
1686} 1717}
@@ -1699,11 +1730,14 @@ static int sm501fb_remove(struct platform_device *pdev)
1699 device_remove_file(&pdev->dev, &dev_attr_fbregs_pnl); 1730 device_remove_file(&pdev->dev, &dev_attr_fbregs_pnl);
1700 device_remove_file(&pdev->dev, &dev_attr_crt_src); 1731 device_remove_file(&pdev->dev, &dev_attr_crt_src);
1701 1732
1733 sm501_free_init_fb(info, HEAD_CRT);
1734 sm501_free_init_fb(info, HEAD_PANEL);
1735
1702 unregister_framebuffer(fbinfo_crt); 1736 unregister_framebuffer(fbinfo_crt);
1703 unregister_framebuffer(fbinfo_pnl); 1737 unregister_framebuffer(fbinfo_pnl);
1704 1738
1705 sm501fb_stop(info); 1739 sm501fb_stop(info);
1706 sm501fb_info_release(info); 1740 kfree(info);
1707 1741
1708 framebuffer_release(fbinfo_pnl); 1742 framebuffer_release(fbinfo_pnl);
1709 framebuffer_release(fbinfo_crt); 1743 framebuffer_release(fbinfo_crt);