aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/via/viafbdev.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/video/via/viafbdev.c')
-rw-r--r--drivers/video/via/viafbdev.c294
1 files changed, 258 insertions, 36 deletions
diff --git a/drivers/video/via/viafbdev.c b/drivers/video/via/viafbdev.c
index bdd0e4130f4e..d298cfccd6fc 100644
--- a/drivers/video/via/viafbdev.c
+++ b/drivers/video/via/viafbdev.c
@@ -56,6 +56,32 @@ static int viafb_pan_display(struct fb_var_screeninfo *var,
56 56
57static struct fb_ops viafb_ops; 57static struct fb_ops viafb_ops;
58 58
59/* supported output devices on each IGP
60 * only CX700, VX800, VX855, VX900 were documented
61 * VIA_CRT should be everywhere
62 * VIA_6C can be onle pre-CX700 (probably only on CLE266) as 6C is used for PLL
63 * source selection on CX700 and later
64 * K400 seems to support VIA_96, VIA_DVP1, VIA_LVDS{1,2} as in viamode.c
65 */
66static const u32 supported_odev_map[] = {
67 [UNICHROME_CLE266] = VIA_CRT | VIA_LDVP0 | VIA_LDVP1,
68 [UNICHROME_K400] = VIA_CRT | VIA_DVP0 | VIA_DVP1 | VIA_LVDS1
69 | VIA_LVDS2,
70 [UNICHROME_K800] = VIA_CRT | VIA_DVP0 | VIA_DVP1 | VIA_LVDS1
71 | VIA_LVDS2,
72 [UNICHROME_PM800] = VIA_CRT | VIA_DVP0 | VIA_DVP1 | VIA_LVDS1
73 | VIA_LVDS2,
74 [UNICHROME_CN700] = VIA_CRT | VIA_DVP0 | VIA_DVP1 | VIA_LVDS1
75 | VIA_LVDS2,
76 [UNICHROME_CX700] = VIA_CRT | VIA_DVP1 | VIA_LVDS1 | VIA_LVDS2,
77 [UNICHROME_CN750] = VIA_CRT | VIA_DVP1 | VIA_LVDS1 | VIA_LVDS2,
78 [UNICHROME_K8M890] = VIA_CRT | VIA_DVP1 | VIA_LVDS1 | VIA_LVDS2,
79 [UNICHROME_P4M890] = VIA_CRT | VIA_DVP1 | VIA_LVDS1 | VIA_LVDS2,
80 [UNICHROME_P4M900] = VIA_CRT | VIA_DVP1 | VIA_LVDS1 | VIA_LVDS2,
81 [UNICHROME_VX800] = VIA_CRT | VIA_DVP1 | VIA_LVDS1 | VIA_LVDS2,
82 [UNICHROME_VX855] = VIA_CRT | VIA_DVP1 | VIA_LVDS1 | VIA_LVDS2,
83 [UNICHROME_VX900] = VIA_CRT | VIA_DVP1 | VIA_LVDS1 | VIA_LVDS2,
84};
59 85
60static void viafb_fill_var_color_info(struct fb_var_screeninfo *var, u8 depth) 86static void viafb_fill_var_color_info(struct fb_var_screeninfo *var, u8 depth)
61{ 87{
@@ -332,22 +358,22 @@ static int viafb_blank(int blank_mode, struct fb_info *info)
332 case FB_BLANK_UNBLANK: 358 case FB_BLANK_UNBLANK:
333 /* Screen: On, HSync: On, VSync: On */ 359 /* Screen: On, HSync: On, VSync: On */
334 /* control CRT monitor power management */ 360 /* control CRT monitor power management */
335 viafb_write_reg_mask(CR36, VIACR, 0x00, BIT4 + BIT5); 361 via_set_state(VIA_CRT, VIA_STATE_ON);
336 break; 362 break;
337 case FB_BLANK_HSYNC_SUSPEND: 363 case FB_BLANK_HSYNC_SUSPEND:
338 /* Screen: Off, HSync: Off, VSync: On */ 364 /* Screen: Off, HSync: Off, VSync: On */
339 /* control CRT monitor power management */ 365 /* control CRT monitor power management */
340 viafb_write_reg_mask(CR36, VIACR, 0x10, BIT4 + BIT5); 366 via_set_state(VIA_CRT, VIA_STATE_STANDBY);
341 break; 367 break;
342 case FB_BLANK_VSYNC_SUSPEND: 368 case FB_BLANK_VSYNC_SUSPEND:
343 /* Screen: Off, HSync: On, VSync: Off */ 369 /* Screen: Off, HSync: On, VSync: Off */
344 /* control CRT monitor power management */ 370 /* control CRT monitor power management */
345 viafb_write_reg_mask(CR36, VIACR, 0x20, BIT4 + BIT5); 371 via_set_state(VIA_CRT, VIA_STATE_SUSPEND);
346 break; 372 break;
347 case FB_BLANK_POWERDOWN: 373 case FB_BLANK_POWERDOWN:
348 /* Screen: Off, HSync: Off, VSync: Off */ 374 /* Screen: Off, HSync: Off, VSync: Off */
349 /* control CRT monitor power management */ 375 /* control CRT monitor power management */
350 viafb_write_reg_mask(CR36, VIACR, 0x30, BIT4 + BIT5); 376 via_set_state(VIA_CRT, VIA_STATE_OFF);
351 break; 377 break;
352 } 378 }
353 379
@@ -457,7 +483,7 @@ static int viafb_ioctl(struct fb_info *info, u_int cmd, u_long arg)
457 if (copy_from_user(&gpu32, argp, sizeof(gpu32))) 483 if (copy_from_user(&gpu32, argp, sizeof(gpu32)))
458 return -EFAULT; 484 return -EFAULT;
459 if (gpu32 & CRT_Device) 485 if (gpu32 & CRT_Device)
460 viafb_crt_enable(); 486 via_set_state(VIA_CRT, VIA_STATE_ON);
461 if (gpu32 & DVI_Device) 487 if (gpu32 & DVI_Device)
462 viafb_dvi_enable(); 488 viafb_dvi_enable();
463 if (gpu32 & LCD_Device) 489 if (gpu32 & LCD_Device)
@@ -467,7 +493,7 @@ static int viafb_ioctl(struct fb_info *info, u_int cmd, u_long arg)
467 if (copy_from_user(&gpu32, argp, sizeof(gpu32))) 493 if (copy_from_user(&gpu32, argp, sizeof(gpu32)))
468 return -EFAULT; 494 return -EFAULT;
469 if (gpu32 & CRT_Device) 495 if (gpu32 & CRT_Device)
470 viafb_crt_disable(); 496 via_set_state(VIA_CRT, VIA_STATE_OFF);
471 if (gpu32 & DVI_Device) 497 if (gpu32 & DVI_Device)
472 viafb_dvi_disable(); 498 viafb_dvi_disable();
473 if (gpu32 & LCD_Device) 499 if (gpu32 & LCD_Device)
@@ -787,7 +813,8 @@ static int viafb_cursor(struct fb_info *info, struct fb_cursor *cursor)
787 bg_color = cursor->image.bg_color; 813 bg_color = cursor->image.bg_color;
788 if (chip_name == UNICHROME_CX700 || 814 if (chip_name == UNICHROME_CX700 ||
789 chip_name == UNICHROME_VX800 || 815 chip_name == UNICHROME_VX800 ||
790 chip_name == UNICHROME_VX855) { 816 chip_name == UNICHROME_VX855 ||
817 chip_name == UNICHROME_VX900) {
791 fg_color = 818 fg_color =
792 ((info->cmap.red[fg_color] & 0xFFC0) << 14) | 819 ((info->cmap.red[fg_color] & 0xFFC0) << 14) |
793 ((info->cmap.green[fg_color] & 0xFFC0) << 4) | 820 ((info->cmap.green[fg_color] & 0xFFC0) << 4) |
@@ -961,7 +988,7 @@ static void retrieve_device_setting(struct viafb_ioctl_setting
961 setting_info->lcd_attributes.lcd_mode = viafb_lcd_mode; 988 setting_info->lcd_attributes.lcd_mode = viafb_lcd_mode;
962} 989}
963 990
964static int parse_active_dev(void) 991static int __init parse_active_dev(void)
965{ 992{
966 viafb_CRT_ON = STATE_OFF; 993 viafb_CRT_ON = STATE_OFF;
967 viafb_DVI_ON = STATE_OFF; 994 viafb_DVI_ON = STATE_OFF;
@@ -1031,7 +1058,7 @@ static int parse_active_dev(void)
1031 return 0; 1058 return 0;
1032} 1059}
1033 1060
1034static int parse_port(char *opt_str, int *output_interface) 1061static int __devinit parse_port(char *opt_str, int *output_interface)
1035{ 1062{
1036 if (!strncmp(opt_str, "DVP0", 4)) 1063 if (!strncmp(opt_str, "DVP0", 4))
1037 *output_interface = INTERFACE_DVP0; 1064 *output_interface = INTERFACE_DVP0;
@@ -1048,7 +1075,7 @@ static int parse_port(char *opt_str, int *output_interface)
1048 return 0; 1075 return 0;
1049} 1076}
1050 1077
1051static void parse_lcd_port(void) 1078static void __devinit parse_lcd_port(void)
1052{ 1079{
1053 parse_port(viafb_lcd_port, &viaparinfo->chip_info->lvds_chip_info. 1080 parse_port(viafb_lcd_port, &viaparinfo->chip_info->lvds_chip_info.
1054 output_interface); 1081 output_interface);
@@ -1061,7 +1088,7 @@ static void parse_lcd_port(void)
1061 output_interface); 1088 output_interface);
1062} 1089}
1063 1090
1064static void parse_dvi_port(void) 1091static void __devinit parse_dvi_port(void)
1065{ 1092{
1066 parse_port(viafb_dvi_port, &viaparinfo->chip_info->tmds_chip_info. 1093 parse_port(viafb_dvi_port, &viaparinfo->chip_info->tmds_chip_info.
1067 output_interface); 1094 output_interface);
@@ -1431,38 +1458,196 @@ static const struct file_operations viafb_vt1636_proc_fops = {
1431 .write = viafb_vt1636_proc_write, 1458 .write = viafb_vt1636_proc_write,
1432}; 1459};
1433 1460
1434static void viafb_init_proc(struct proc_dir_entry **viafb_entry) 1461#endif /* CONFIG_FB_VIA_DIRECT_PROCFS */
1462
1463static int viafb_sup_odev_proc_show(struct seq_file *m, void *v)
1435{ 1464{
1436 *viafb_entry = proc_mkdir("viafb", NULL); 1465 via_odev_to_seq(m, supported_odev_map[
1437 if (*viafb_entry) { 1466 viaparinfo->shared->chip_info.gfx_chip_name]);
1438 proc_create("dvp0", 0, *viafb_entry, &viafb_dvp0_proc_fops); 1467 return 0;
1439 proc_create("dvp1", 0, *viafb_entry, &viafb_dvp1_proc_fops); 1468}
1440 proc_create("dfph", 0, *viafb_entry, &viafb_dfph_proc_fops); 1469
1441 proc_create("dfpl", 0, *viafb_entry, &viafb_dfpl_proc_fops); 1470static int viafb_sup_odev_proc_open(struct inode *inode, struct file *file)
1442 if (VT1636_LVDS == viaparinfo->chip_info->lvds_chip_info. 1471{
1443 lvds_chip_name || VT1636_LVDS == 1472 return single_open(file, viafb_sup_odev_proc_show, NULL);
1444 viaparinfo->chip_info->lvds_chip_info2.lvds_chip_name) { 1473}
1445 proc_create("vt1636", 0, *viafb_entry, &viafb_vt1636_proc_fops); 1474
1446 } 1475static const struct file_operations viafb_sup_odev_proc_fops = {
1476 .owner = THIS_MODULE,
1477 .open = viafb_sup_odev_proc_open,
1478 .read = seq_read,
1479 .llseek = seq_lseek,
1480 .release = single_release,
1481};
1482
1483static ssize_t odev_update(const char __user *buffer, size_t count, u32 *odev)
1484{
1485 char buf[64], *ptr = buf;
1486 u32 devices;
1487 bool add, sub;
1488
1489 if (count < 1 || count > 63)
1490 return -EINVAL;
1491 if (copy_from_user(&buf[0], buffer, count))
1492 return -EFAULT;
1493 buf[count] = '\0';
1494 add = buf[0] == '+';
1495 sub = buf[0] == '-';
1496 if (add || sub)
1497 ptr++;
1498 devices = via_parse_odev(ptr, &ptr);
1499 if (*ptr == '\n')
1500 ptr++;
1501 if (*ptr != 0)
1502 return -EINVAL;
1503 if (add)
1504 *odev |= devices;
1505 else if (sub)
1506 *odev &= ~devices;
1507 else
1508 *odev = devices;
1509 return count;
1510}
1511
1512static int viafb_iga1_odev_proc_show(struct seq_file *m, void *v)
1513{
1514 via_odev_to_seq(m, viaparinfo->shared->iga1_devices);
1515 return 0;
1516}
1517
1518static int viafb_iga1_odev_proc_open(struct inode *inode, struct file *file)
1519{
1520 return single_open(file, viafb_iga1_odev_proc_show, NULL);
1521}
1522
1523static ssize_t viafb_iga1_odev_proc_write(struct file *file,
1524 const char __user *buffer, size_t count, loff_t *pos)
1525{
1526 u32 dev_on, dev_off, dev_old, dev_new;
1527 ssize_t res;
1528
1529 dev_old = dev_new = viaparinfo->shared->iga1_devices;
1530 res = odev_update(buffer, count, &dev_new);
1531 if (res != count)
1532 return res;
1533 dev_off = dev_old & ~dev_new;
1534 dev_on = dev_new & ~dev_old;
1535 viaparinfo->shared->iga1_devices = dev_new;
1536 viaparinfo->shared->iga2_devices &= ~dev_new;
1537 via_set_state(dev_off, VIA_STATE_OFF);
1538 via_set_source(dev_new, IGA1);
1539 via_set_state(dev_on, VIA_STATE_ON);
1540 return res;
1541}
1542
1543static const struct file_operations viafb_iga1_odev_proc_fops = {
1544 .owner = THIS_MODULE,
1545 .open = viafb_iga1_odev_proc_open,
1546 .read = seq_read,
1547 .llseek = seq_lseek,
1548 .release = single_release,
1549 .write = viafb_iga1_odev_proc_write,
1550};
1551
1552static int viafb_iga2_odev_proc_show(struct seq_file *m, void *v)
1553{
1554 via_odev_to_seq(m, viaparinfo->shared->iga2_devices);
1555 return 0;
1556}
1447 1557
1558static int viafb_iga2_odev_proc_open(struct inode *inode, struct file *file)
1559{
1560 return single_open(file, viafb_iga2_odev_proc_show, NULL);
1561}
1562
1563static ssize_t viafb_iga2_odev_proc_write(struct file *file,
1564 const char __user *buffer, size_t count, loff_t *pos)
1565{
1566 u32 dev_on, dev_off, dev_old, dev_new;
1567 ssize_t res;
1568
1569 dev_old = dev_new = viaparinfo->shared->iga2_devices;
1570 res = odev_update(buffer, count, &dev_new);
1571 if (res != count)
1572 return res;
1573 dev_off = dev_old & ~dev_new;
1574 dev_on = dev_new & ~dev_old;
1575 viaparinfo->shared->iga2_devices = dev_new;
1576 viaparinfo->shared->iga1_devices &= ~dev_new;
1577 via_set_state(dev_off, VIA_STATE_OFF);
1578 via_set_source(dev_new, IGA2);
1579 via_set_state(dev_on, VIA_STATE_ON);
1580 return res;
1581}
1582
1583static const struct file_operations viafb_iga2_odev_proc_fops = {
1584 .owner = THIS_MODULE,
1585 .open = viafb_iga2_odev_proc_open,
1586 .read = seq_read,
1587 .llseek = seq_lseek,
1588 .release = single_release,
1589 .write = viafb_iga2_odev_proc_write,
1590};
1591
1592#define IS_VT1636(lvds_chip) ((lvds_chip).lvds_chip_name == VT1636_LVDS)
1593static void viafb_init_proc(struct viafb_shared *shared)
1594{
1595 struct proc_dir_entry *iga1_entry, *iga2_entry,
1596 *viafb_entry = proc_mkdir("viafb", NULL);
1597
1598 shared->proc_entry = viafb_entry;
1599 if (viafb_entry) {
1600#ifdef CONFIG_FB_VIA_DIRECT_PROCFS
1601 proc_create("dvp0", 0, viafb_entry, &viafb_dvp0_proc_fops);
1602 proc_create("dvp1", 0, viafb_entry, &viafb_dvp1_proc_fops);
1603 proc_create("dfph", 0, viafb_entry, &viafb_dfph_proc_fops);
1604 proc_create("dfpl", 0, viafb_entry, &viafb_dfpl_proc_fops);
1605 if (IS_VT1636(shared->chip_info.lvds_chip_info)
1606 || IS_VT1636(shared->chip_info.lvds_chip_info2))
1607 proc_create("vt1636", 0, viafb_entry,
1608 &viafb_vt1636_proc_fops);
1609#endif /* CONFIG_FB_VIA_DIRECT_PROCFS */
1610
1611 proc_create("supported_output_devices", 0, viafb_entry,
1612 &viafb_sup_odev_proc_fops);
1613 iga1_entry = proc_mkdir("iga1", viafb_entry);
1614 shared->iga1_proc_entry = iga1_entry;
1615 proc_create("output_devices", 0, iga1_entry,
1616 &viafb_iga1_odev_proc_fops);
1617 iga2_entry = proc_mkdir("iga2", viafb_entry);
1618 shared->iga2_proc_entry = iga2_entry;
1619 proc_create("output_devices", 0, iga2_entry,
1620 &viafb_iga2_odev_proc_fops);
1448 } 1621 }
1449} 1622}
1450static void viafb_remove_proc(struct proc_dir_entry *viafb_entry) 1623static void viafb_remove_proc(struct viafb_shared *shared)
1451{ 1624{
1452 struct chip_information *chip_info = &viaparinfo->shared->chip_info; 1625 struct proc_dir_entry *viafb_entry = shared->proc_entry,
1626 *iga1_entry = shared->iga1_proc_entry,
1627 *iga2_entry = shared->iga2_proc_entry;
1453 1628
1629 if (!viafb_entry)
1630 return;
1631
1632 remove_proc_entry("output_devices", iga2_entry);
1633 remove_proc_entry("iga2", viafb_entry);
1634 remove_proc_entry("output_devices", iga1_entry);
1635 remove_proc_entry("iga1", viafb_entry);
1636 remove_proc_entry("supported_output_devices", viafb_entry);
1637
1638#ifdef CONFIG_FB_VIA_DIRECT_PROCFS
1454 remove_proc_entry("dvp0", viafb_entry);/* parent dir */ 1639 remove_proc_entry("dvp0", viafb_entry);/* parent dir */
1455 remove_proc_entry("dvp1", viafb_entry); 1640 remove_proc_entry("dvp1", viafb_entry);
1456 remove_proc_entry("dfph", viafb_entry); 1641 remove_proc_entry("dfph", viafb_entry);
1457 remove_proc_entry("dfpl", viafb_entry); 1642 remove_proc_entry("dfpl", viafb_entry);
1458 if (chip_info->lvds_chip_info.lvds_chip_name == VT1636_LVDS 1643 if (IS_VT1636(shared->chip_info.lvds_chip_info)
1459 || chip_info->lvds_chip_info2.lvds_chip_name == VT1636_LVDS) 1644 || IS_VT1636(shared->chip_info.lvds_chip_info2))
1460 remove_proc_entry("vt1636", viafb_entry); 1645 remove_proc_entry("vt1636", viafb_entry);
1646#endif /* CONFIG_FB_VIA_DIRECT_PROCFS */
1461 1647
1462 remove_proc_entry("viafb", NULL); 1648 remove_proc_entry("viafb", NULL);
1463} 1649}
1464 1650#undef IS_VT1636
1465#endif /* CONFIG_FB_VIA_DIRECT_PROCFS */
1466 1651
1467static int parse_mode(const char *str, u32 *xres, u32 *yres) 1652static int parse_mode(const char *str, u32 *xres, u32 *yres)
1468{ 1653{
@@ -1486,6 +1671,47 @@ static int parse_mode(const char *str, u32 *xres, u32 *yres)
1486} 1671}
1487 1672
1488 1673
1674#ifdef CONFIG_PM
1675int viafb_suspend(struct pci_dev *pdev, pm_message_t state)
1676{
1677 if (state.event == PM_EVENT_SUSPEND) {
1678 acquire_console_sem();
1679 fb_set_suspend(viafbinfo, 1);
1680
1681 viafb_sync(viafbinfo);
1682
1683 pci_save_state(pdev);
1684 pci_disable_device(pdev);
1685 pci_set_power_state(pdev, pci_choose_state(pdev, state));
1686 release_console_sem();
1687 }
1688
1689 return 0;
1690}
1691
1692int viafb_resume(struct pci_dev *pdev)
1693{
1694 acquire_console_sem();
1695 pci_set_power_state(pdev, PCI_D0);
1696 pci_restore_state(pdev);
1697 if (pci_enable_device(pdev))
1698 goto fail;
1699 pci_set_master(pdev);
1700 if (viaparinfo->shared->vdev->engine_mmio)
1701 viafb_reset_engine(viaparinfo);
1702 viafb_set_par(viafbinfo);
1703 if (viafb_dual_fb)
1704 viafb_set_par(viafbinfo1);
1705 fb_set_suspend(viafbinfo, 0);
1706
1707fail:
1708 release_console_sem();
1709 return 0;
1710}
1711
1712#endif
1713
1714
1489int __devinit via_fb_pci_probe(struct viafb_dev *vdev) 1715int __devinit via_fb_pci_probe(struct viafb_dev *vdev)
1490{ 1716{
1491 u32 default_xres, default_yres; 1717 u32 default_xres, default_yres;
@@ -1544,7 +1770,7 @@ int __devinit via_fb_pci_probe(struct viafb_dev *vdev)
1544 viafbinfo->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN; 1770 viafbinfo->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
1545 1771
1546 viafbinfo->pseudo_palette = pseudo_pal; 1772 viafbinfo->pseudo_palette = pseudo_pal;
1547 if (viafb_accel && !viafb_init_engine(viafbinfo)) { 1773 if (viafb_accel && !viafb_setup_engine(viafbinfo)) {
1548 viafbinfo->flags |= FBINFO_HWACCEL_COPYAREA | 1774 viafbinfo->flags |= FBINFO_HWACCEL_COPYAREA |
1549 FBINFO_HWACCEL_FILLRECT | FBINFO_HWACCEL_IMAGEBLIT; 1775 FBINFO_HWACCEL_FILLRECT | FBINFO_HWACCEL_IMAGEBLIT;
1550 default_var.accel_flags = FB_ACCELF_TEXT; 1776 default_var.accel_flags = FB_ACCELF_TEXT;
@@ -1671,9 +1897,7 @@ int __devinit via_fb_pci_probe(struct viafb_dev *vdev)
1671 viafbinfo->node, viafbinfo->fix.id, default_var.xres, 1897 viafbinfo->node, viafbinfo->fix.id, default_var.xres,
1672 default_var.yres, default_var.bits_per_pixel); 1898 default_var.yres, default_var.bits_per_pixel);
1673 1899
1674#ifdef CONFIG_FB_VIA_DIRECT_PROCFS 1900 viafb_init_proc(viaparinfo->shared);
1675 viafb_init_proc(&viaparinfo->shared->proc_entry);
1676#endif
1677 viafb_init_dac(IGA2); 1901 viafb_init_dac(IGA2);
1678 return 0; 1902 return 0;
1679 1903
@@ -1700,9 +1924,7 @@ void __devexit via_fb_pci_remove(struct pci_dev *pdev)
1700 unregister_framebuffer(viafbinfo); 1924 unregister_framebuffer(viafbinfo);
1701 if (viafb_dual_fb) 1925 if (viafb_dual_fb)
1702 unregister_framebuffer(viafbinfo1); 1926 unregister_framebuffer(viafbinfo1);
1703#ifdef CONFIG_FB_VIA_DIRECT_PROCFS 1927 viafb_remove_proc(viaparinfo->shared);
1704 viafb_remove_proc(viaparinfo->shared->proc_entry);
1705#endif
1706 framebuffer_release(viafbinfo); 1928 framebuffer_release(viafbinfo);
1707 if (viafb_dual_fb) 1929 if (viafb_dual_fb)
1708 framebuffer_release(viafbinfo1); 1930 framebuffer_release(viafbinfo1);