aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/via
diff options
context:
space:
mode:
authorFlorian Tobias Schandinat <FlorianSchandinat@gmx.de>2010-09-04 21:33:28 -0400
committerFlorian Tobias Schandinat <FlorianSchandinat@gmx.de>2010-09-23 22:14:59 -0400
commit2a9183923af1f6f4da66aeabf9fa5af0dc58ccec (patch)
tree710f8f8fc1b5f922e4c6405abf60eedaff5eb715 /drivers/video/via
parentcd7e9103e983ff0f518ac0e85cee265027ccbfa4 (diff)
viafb: add interface for output device configuration
This patch extends the proc entry to contain a possibility to view and change the output devices for each IGA. This is useful for debugging output problems as it provides a reliable way to query which low level devices are active after VIAs output device configuration nightmare happended. It's as well suitable for daily use as one can change the output configuration on the fly for example to connect a projector. At the moment it's still unstable. The reason is that we have to handle a bunch of undocumented output devices (those without a proper name) and that this patch is the first step to collect and verify the needed information. Basically the only configuration change that is expected to work at the moment is switching output devices between IGA1 and IGA2. Signed-off-by: Florian Tobias Schandinat <FlorianSchandinat@gmx.de> Acked-by: Jonathan Corbet <corbet@lwn.net> Cc: Joseph Chan <JosephChan@via.com.tw> Cc: Andrew Morton <akpm@linux-foundation.org>
Diffstat (limited to 'drivers/video/via')
-rw-r--r--drivers/video/via/hw.c53
-rw-r--r--drivers/video/via/hw.h10
-rw-r--r--drivers/video/via/viafbdev.c175
-rw-r--r--drivers/video/via/viafbdev.h2
4 files changed, 216 insertions, 24 deletions
diff --git a/drivers/video/via/hw.c b/drivers/video/via/hw.c
index 03303232e543..e65edcea46eb 100644
--- a/drivers/video/via/hw.c
+++ b/drivers/video/via/hw.c
@@ -718,6 +718,16 @@ static struct rgbLUT palLUT_table[] = {
718 0x00} 718 0x00}
719}; 719};
720 720
721static struct via_device_mapping device_mapping[] = {
722 {VIA_6C, "6C"},
723 {VIA_93, "93"},
724 {VIA_96, "96"},
725 {VIA_CRT, "CRT"},
726 {VIA_DVP1, "DVP1"},
727 {VIA_LVDS1, "LVDS1"},
728 {VIA_LVDS2, "LVDS2"}
729};
730
721static void load_fix_bit_crtc_reg(void); 731static void load_fix_bit_crtc_reg(void);
722static void __devinit init_gfx_chip_info(int chip_type); 732static void __devinit init_gfx_chip_info(int chip_type);
723static void __devinit init_tmds_chip_info(void); 733static void __devinit init_tmds_chip_info(void);
@@ -1026,6 +1036,49 @@ void via_set_source(u32 devices, u8 iga)
1026 set_lvds2_source(iga); 1036 set_lvds2_source(iga);
1027} 1037}
1028 1038
1039u32 via_parse_odev(char *input, char **end)
1040{
1041 char *ptr = input;
1042 u32 odev = 0;
1043 bool next = true;
1044 int i, len;
1045
1046 while (next) {
1047 next = false;
1048 for (i = 0; i < ARRAY_SIZE(device_mapping); i++) {
1049 len = strlen(device_mapping[i].name);
1050 if (!strncmp(ptr, device_mapping[i].name, len)) {
1051 odev |= device_mapping[i].device;
1052 ptr += len;
1053 if (*ptr == ',') {
1054 ptr++;
1055 next = true;
1056 }
1057 }
1058 }
1059 }
1060
1061 *end = ptr;
1062 return odev;
1063}
1064
1065void via_odev_to_seq(struct seq_file *m, u32 odev)
1066{
1067 int i, count = 0;
1068
1069 for (i = 0; i < ARRAY_SIZE(device_mapping); i++) {
1070 if (odev & device_mapping[i].device) {
1071 if (count > 0)
1072 seq_putc(m, ',');
1073
1074 seq_puts(m, device_mapping[i].name);
1075 count++;
1076 }
1077 }
1078
1079 seq_putc(m, '\n');
1080}
1081
1029static void load_fix_bit_crtc_reg(void) 1082static void load_fix_bit_crtc_reg(void)
1030{ 1083{
1031 /* always set to 1 */ 1084 /* always set to 1 */
diff --git a/drivers/video/via/hw.h b/drivers/video/via/hw.h
index 45dee39a8b23..657dbd64a089 100644
--- a/drivers/video/via/hw.h
+++ b/drivers/video/via/hw.h
@@ -22,6 +22,8 @@
22#ifndef __HW_H__ 22#ifndef __HW_H__
23#define __HW_H__ 23#define __HW_H__
24 24
25#include <linux/seq_file.h>
26
25#include "viamode.h" 27#include "viamode.h"
26#include "global.h" 28#include "global.h"
27#include "via_modesetting.h" 29#include "via_modesetting.h"
@@ -882,6 +884,11 @@ struct pci_device_id_info {
882 u32 chip_index; 884 u32 chip_index;
883}; 885};
884 886
887struct via_device_mapping {
888 u32 device;
889 const char *name;
890};
891
885extern unsigned int viafb_second_virtual_xres; 892extern unsigned int viafb_second_virtual_xres;
886extern int viafb_SAMM_ON; 893extern int viafb_SAMM_ON;
887extern int viafb_dual_fb; 894extern int viafb_dual_fb;
@@ -899,6 +906,9 @@ void viafb_load_reg(int timing_value, int viafb_load_reg_num,
899 int io_type); 906 int io_type);
900void viafb_crt_disable(void); 907void viafb_crt_disable(void);
901void viafb_crt_enable(void); 908void viafb_crt_enable(void);
909void via_set_source(u32 devices, u8 iga);
910u32 via_parse_odev(char *input, char **end);
911void via_odev_to_seq(struct seq_file *m, u32 odev);
902void init_ad9389(void); 912void init_ad9389(void);
903/* Access I/O Function */ 913/* Access I/O Function */
904void viafb_lock_crt(void); 914void viafb_lock_crt(void);
diff --git a/drivers/video/via/viafbdev.c b/drivers/video/via/viafbdev.c
index 5a947b096269..80ce43a318bb 100644
--- a/drivers/video/via/viafbdev.c
+++ b/drivers/video/via/viafbdev.c
@@ -1431,38 +1431,169 @@ static const struct file_operations viafb_vt1636_proc_fops = {
1431 .write = viafb_vt1636_proc_write, 1431 .write = viafb_vt1636_proc_write,
1432}; 1432};
1433 1433
1434static void viafb_init_proc(struct proc_dir_entry **viafb_entry) 1434#endif /* CONFIG_FB_VIA_DIRECT_PROCFS */
1435
1436static ssize_t odev_update(const char __user *buffer, size_t count, u32 *odev)
1435{ 1437{
1436 *viafb_entry = proc_mkdir("viafb", NULL); 1438 char buf[64], *ptr = buf;
1437 if (*viafb_entry) { 1439 u32 devices;
1438 proc_create("dvp0", 0, *viafb_entry, &viafb_dvp0_proc_fops); 1440 bool add, sub;
1439 proc_create("dvp1", 0, *viafb_entry, &viafb_dvp1_proc_fops); 1441
1440 proc_create("dfph", 0, *viafb_entry, &viafb_dfph_proc_fops); 1442 if (count < 1 || count > 63)
1441 proc_create("dfpl", 0, *viafb_entry, &viafb_dfpl_proc_fops); 1443 return -EINVAL;
1442 if (VT1636_LVDS == viaparinfo->chip_info->lvds_chip_info. 1444 if (copy_from_user(&buf[0], buffer, count))
1443 lvds_chip_name || VT1636_LVDS == 1445 return -EFAULT;
1444 viaparinfo->chip_info->lvds_chip_info2.lvds_chip_name) { 1446 buf[count] = '\0';
1445 proc_create("vt1636", 0, *viafb_entry, &viafb_vt1636_proc_fops); 1447 add = buf[0] == '+';
1446 } 1448 sub = buf[0] == '-';
1449 if (add || sub)
1450 ptr++;
1451 devices = via_parse_odev(ptr, &ptr);
1452 if (*ptr == '\n')
1453 ptr++;
1454 if (*ptr != 0)
1455 return -EINVAL;
1456 if (add)
1457 *odev |= devices;
1458 else if (sub)
1459 *odev &= ~devices;
1460 else
1461 *odev = devices;
1462 return count;
1463}
1464
1465static int viafb_iga1_odev_proc_show(struct seq_file *m, void *v)
1466{
1467 via_odev_to_seq(m, viaparinfo->shared->iga1_devices);
1468 return 0;
1469}
1470
1471static int viafb_iga1_odev_proc_open(struct inode *inode, struct file *file)
1472{
1473 return single_open(file, viafb_iga1_odev_proc_show, NULL);
1474}
1475
1476static ssize_t viafb_iga1_odev_proc_write(struct file *file,
1477 const char __user *buffer, size_t count, loff_t *pos)
1478{
1479 u32 dev_on, dev_off, dev_old, dev_new;
1480 ssize_t res;
1481
1482 dev_old = dev_new = viaparinfo->shared->iga1_devices;
1483 res = odev_update(buffer, count, &dev_new);
1484 if (res != count)
1485 return res;
1486 dev_off = dev_old & ~dev_new;
1487 dev_on = dev_new & ~dev_old;
1488 viaparinfo->shared->iga1_devices = dev_new;
1489 viaparinfo->shared->iga2_devices &= ~dev_new;
1490 via_set_source(dev_new, IGA1);
1491 return res;
1492}
1493
1494static const struct file_operations viafb_iga1_odev_proc_fops = {
1495 .owner = THIS_MODULE,
1496 .open = viafb_iga1_odev_proc_open,
1497 .read = seq_read,
1498 .llseek = seq_lseek,
1499 .release = single_release,
1500 .write = viafb_iga1_odev_proc_write,
1501};
1502
1503static int viafb_iga2_odev_proc_show(struct seq_file *m, void *v)
1504{
1505 via_odev_to_seq(m, viaparinfo->shared->iga2_devices);
1506 return 0;
1507}
1508
1509static int viafb_iga2_odev_proc_open(struct inode *inode, struct file *file)
1510{
1511 return single_open(file, viafb_iga2_odev_proc_show, NULL);
1512}
1513
1514static ssize_t viafb_iga2_odev_proc_write(struct file *file,
1515 const char __user *buffer, size_t count, loff_t *pos)
1516{
1517 u32 dev_on, dev_off, dev_old, dev_new;
1518 ssize_t res;
1519
1520 dev_old = dev_new = viaparinfo->shared->iga2_devices;
1521 res = odev_update(buffer, count, &dev_new);
1522 if (res != count)
1523 return res;
1524 dev_off = dev_old & ~dev_new;
1525 dev_on = dev_new & ~dev_old;
1526 viaparinfo->shared->iga2_devices = dev_new;
1527 viaparinfo->shared->iga1_devices &= ~dev_new;
1528 via_set_source(dev_new, IGA2);
1529 return res;
1530}
1531
1532static const struct file_operations viafb_iga2_odev_proc_fops = {
1533 .owner = THIS_MODULE,
1534 .open = viafb_iga2_odev_proc_open,
1535 .read = seq_read,
1536 .llseek = seq_lseek,
1537 .release = single_release,
1538 .write = viafb_iga2_odev_proc_write,
1539};
1540
1541#define IS_VT1636(lvds_chip) ((lvds_chip).lvds_chip_name == VT1636_LVDS)
1542static void viafb_init_proc(struct viafb_shared *shared)
1543{
1544 struct proc_dir_entry *iga1_entry, *iga2_entry,
1545 *viafb_entry = proc_mkdir("viafb", NULL);
1546
1547 shared->proc_entry = viafb_entry;
1548 if (viafb_entry) {
1549#ifdef CONFIG_FB_VIA_DIRECT_PROCFS
1550 proc_create("dvp0", 0, viafb_entry, &viafb_dvp0_proc_fops);
1551 proc_create("dvp1", 0, viafb_entry, &viafb_dvp1_proc_fops);
1552 proc_create("dfph", 0, viafb_entry, &viafb_dfph_proc_fops);
1553 proc_create("dfpl", 0, viafb_entry, &viafb_dfpl_proc_fops);
1554 if (IS_VT1636(shared->chip_info.lvds_chip_info)
1555 || IS_VT1636(shared->chip_info.lvds_chip_info2))
1556 proc_create("vt1636", 0, viafb_entry,
1557 &viafb_vt1636_proc_fops);
1558#endif /* CONFIG_FB_VIA_DIRECT_PROCFS */
1447 1559
1560 iga1_entry = proc_mkdir("iga1", viafb_entry);
1561 shared->iga1_proc_entry = iga1_entry;
1562 proc_create("output_devices", 0, iga1_entry,
1563 &viafb_iga1_odev_proc_fops);
1564 iga2_entry = proc_mkdir("iga2", viafb_entry);
1565 shared->iga2_proc_entry = iga2_entry;
1566 proc_create("output_devices", 0, iga2_entry,
1567 &viafb_iga2_odev_proc_fops);
1448 } 1568 }
1449} 1569}
1450static void viafb_remove_proc(struct proc_dir_entry *viafb_entry) 1570static void viafb_remove_proc(struct viafb_shared *shared)
1451{ 1571{
1452 struct chip_information *chip_info = &viaparinfo->shared->chip_info; 1572 struct proc_dir_entry *viafb_entry = shared->proc_entry,
1573 *iga1_entry = shared->iga1_proc_entry,
1574 *iga2_entry = shared->iga2_proc_entry;
1453 1575
1576 if (!viafb_entry)
1577 return;
1578
1579 remove_proc_entry("output_devices", iga2_entry);
1580 remove_proc_entry("iga2", viafb_entry);
1581 remove_proc_entry("output_devices", iga1_entry);
1582 remove_proc_entry("iga1", viafb_entry);
1583
1584#ifdef CONFIG_FB_VIA_DIRECT_PROCFS
1454 remove_proc_entry("dvp0", viafb_entry);/* parent dir */ 1585 remove_proc_entry("dvp0", viafb_entry);/* parent dir */
1455 remove_proc_entry("dvp1", viafb_entry); 1586 remove_proc_entry("dvp1", viafb_entry);
1456 remove_proc_entry("dfph", viafb_entry); 1587 remove_proc_entry("dfph", viafb_entry);
1457 remove_proc_entry("dfpl", viafb_entry); 1588 remove_proc_entry("dfpl", viafb_entry);
1458 if (chip_info->lvds_chip_info.lvds_chip_name == VT1636_LVDS 1589 if (IS_VT1636(shared->chip_info.lvds_chip_info)
1459 || chip_info->lvds_chip_info2.lvds_chip_name == VT1636_LVDS) 1590 || IS_VT1636(shared->chip_info.lvds_chip_info2))
1460 remove_proc_entry("vt1636", viafb_entry); 1591 remove_proc_entry("vt1636", viafb_entry);
1592#endif /* CONFIG_FB_VIA_DIRECT_PROCFS */
1461 1593
1462 remove_proc_entry("viafb", NULL); 1594 remove_proc_entry("viafb", NULL);
1463} 1595}
1464 1596#undef IS_VT1636
1465#endif /* CONFIG_FB_VIA_DIRECT_PROCFS */
1466 1597
1467static int parse_mode(const char *str, u32 *xres, u32 *yres) 1598static int parse_mode(const char *str, u32 *xres, u32 *yres)
1468{ 1599{
@@ -1671,9 +1802,7 @@ int __devinit via_fb_pci_probe(struct viafb_dev *vdev)
1671 viafbinfo->node, viafbinfo->fix.id, default_var.xres, 1802 viafbinfo->node, viafbinfo->fix.id, default_var.xres,
1672 default_var.yres, default_var.bits_per_pixel); 1803 default_var.yres, default_var.bits_per_pixel);
1673 1804
1674#ifdef CONFIG_FB_VIA_DIRECT_PROCFS 1805 viafb_init_proc(viaparinfo->shared);
1675 viafb_init_proc(&viaparinfo->shared->proc_entry);
1676#endif
1677 viafb_init_dac(IGA2); 1806 viafb_init_dac(IGA2);
1678 return 0; 1807 return 0;
1679 1808
@@ -1700,9 +1829,7 @@ void __devexit via_fb_pci_remove(struct pci_dev *pdev)
1700 unregister_framebuffer(viafbinfo); 1829 unregister_framebuffer(viafbinfo);
1701 if (viafb_dual_fb) 1830 if (viafb_dual_fb)
1702 unregister_framebuffer(viafbinfo1); 1831 unregister_framebuffer(viafbinfo1);
1703#ifdef CONFIG_FB_VIA_DIRECT_PROCFS 1832 viafb_remove_proc(viaparinfo->shared);
1704 viafb_remove_proc(viaparinfo->shared->proc_entry);
1705#endif
1706 framebuffer_release(viafbinfo); 1833 framebuffer_release(viafbinfo);
1707 if (viafb_dual_fb) 1834 if (viafb_dual_fb)
1708 framebuffer_release(viafbinfo1); 1835 framebuffer_release(viafbinfo1);
diff --git a/drivers/video/via/viafbdev.h b/drivers/video/via/viafbdev.h
index 945a47a63c4d..d66f963e930e 100644
--- a/drivers/video/via/viafbdev.h
+++ b/drivers/video/via/viafbdev.h
@@ -44,6 +44,8 @@ struct viafb_shared {
44 u32 iga2_devices; 44 u32 iga2_devices;
45 45
46 struct proc_dir_entry *proc_entry; /*viafb proc entry */ 46 struct proc_dir_entry *proc_entry; /*viafb proc entry */
47 struct proc_dir_entry *iga1_proc_entry;
48 struct proc_dir_entry *iga2_proc_entry;
47 struct viafb_dev *vdev; /* Global dev info */ 49 struct viafb_dev *vdev; /* Global dev info */
48 50
49 /* All the information will be needed to set engine */ 51 /* All the information will be needed to set engine */