All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/12] viafb output device rework - part 2
@ 2010-09-19  7:26 Florian Tobias Schandinat
  2010-09-19  7:26   ` Florian Tobias Schandinat
                   ` (11 more replies)
  0 siblings, 12 replies; 27+ messages in thread
From: Florian Tobias Schandinat @ 2010-09-19  7:26 UTC (permalink / raw)
  To: linux-fbdev; +Cc: linux-kernel, Florian Tobias Schandinat

Hi,

this part of the patch series has finally a huge impact on the user
experience:

- A new/extended interface in proc allows enabling/disabling of output
  devices during runtime

- The device initialization time is significant shorter after reducing
  I2C timing values to a sane limit

- A regression is fixed that prevented detection of VT1636 chips and
  therefore broke the framebuffer in such configurations

But it contains also a lot of changes in the background that will
(hopefully) lead to a better future.

The complete patch series until now can also be found at
	git://github.com/schandinat/linux-2.6.git viafb-s3v1

As usual, some tests were performed on CLE266, VX800 and VX855.

Any opinions/suggestions?


Have fun,

Florian Tobias Schandinat


Florian Tobias Schandinat (12):
  viafb: add interface for output device configuration
  viafb: limit LCD code impact
  viafb: introduce per output device power management
  viafb: vt1636 cleanup
  viafb: fix i2c_transfer error handling
  viafb: enable I2C for CRT
  viafb: reduce I2C timeout and delay
  viafb: add function to change sync polarity per device
  viafb: set sync polarity for all output devices
  viafb: add a mapping of supported output devices
  viafb: rename output devices
  viafb: add documentation for proc interface

 Documentation/fb/viafb.txt   |   48 ++++++++
 drivers/video/via/Makefile   |    2 +-
 drivers/video/via/dvi.c      |   25 +----
 drivers/video/via/global.h   |    1 -
 drivers/video/via/hw.c       |  265 ++++++++++++++++++++++++++++++++++++------
 drivers/video/via/hw.h       |   30 ++++-
 drivers/video/via/lcd.c      |   41 -------
 drivers/video/via/tbl1636.c  |   71 -----------
 drivers/video/via/tbl1636.h  |   34 ------
 drivers/video/via/via-core.c |    2 +-
 drivers/video/via/via_i2c.c  |   31 ++++-
 drivers/video/via/viafbdev.c |  225 ++++++++++++++++++++++++++++++++----
 drivers/video/via/viafbdev.h |    2 +
 drivers/video/via/vt1636.c   |  121 +++++++-------------
 14 files changed, 576 insertions(+), 322 deletions(-)
 delete mode 100644 drivers/video/via/tbl1636.c
 delete mode 100644 drivers/video/via/tbl1636.h


^ permalink raw reply	[flat|nested] 27+ messages in thread

* [PATCH 01/12] viafb: add interface for output device configuration
  2010-09-19  7:26 [PATCH 00/12] viafb output device rework - part 2 Florian Tobias Schandinat
@ 2010-09-19  7:26   ` Florian Tobias Schandinat
  2010-09-19  7:26   ` Florian Tobias Schandinat
                     ` (10 subsequent siblings)
  11 siblings, 0 replies; 27+ messages in thread
From: Florian Tobias Schandinat @ 2010-09-19  7:26 UTC (permalink / raw)
  To: linux-fbdev
  Cc: linux-kernel, Florian Tobias Schandinat, Joseph Chan,
	Jonathan Corbet, Andrew Morton

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>
Cc: Joseph Chan <JosephChan@via.com.tw>
Cc: Jonathan Corbet <corbet@lwn.net>
Cc: Andrew Morton <akpm@linux-foundation.org>
---
 drivers/video/via/hw.c       |   53 ++++++++++++++
 drivers/video/via/hw.h       |   10 +++
 drivers/video/via/viafbdev.c |  161 +++++++++++++++++++++++++++++++++++++-----
 drivers/video/via/viafbdev.h |    2 +
 4 files changed, 209 insertions(+), 17 deletions(-)

diff --git a/drivers/video/via/hw.c b/drivers/video/via/hw.c
index 0330323..e65edce 100644
--- a/drivers/video/via/hw.c
+++ b/drivers/video/via/hw.c
@@ -718,6 +718,16 @@ static struct rgbLUT palLUT_table[] = {
 								     0x00}
 };
 
+static struct via_device_mapping device_mapping[] = {
+	{VIA_6C, "6C"},
+	{VIA_93, "93"},
+	{VIA_96, "96"},
+	{VIA_CRT, "CRT"},
+	{VIA_DVP1, "DVP1"},
+	{VIA_LVDS1, "LVDS1"},
+	{VIA_LVDS2, "LVDS2"}
+};
+
 static void load_fix_bit_crtc_reg(void);
 static void __devinit init_gfx_chip_info(int chip_type);
 static void __devinit init_tmds_chip_info(void);
@@ -1026,6 +1036,49 @@ void via_set_source(u32 devices, u8 iga)
 		set_lvds2_source(iga);
 }
 
+u32 via_parse_odev(char *input, char **end)
+{
+	char *ptr = input;
+	u32 odev = 0;
+	bool next = true;
+	int i, len;
+
+	while (next) {
+		next = false;
+		for (i = 0; i < ARRAY_SIZE(device_mapping); i++) {
+			len = strlen(device_mapping[i].name);
+			if (!strncmp(ptr, device_mapping[i].name, len)) {
+				odev |= device_mapping[i].device;
+				ptr += len;
+				if (*ptr == ',') {
+					ptr++;
+					next = true;
+				}
+			}
+		}
+	}
+
+	*end = ptr;
+	return odev;
+}
+
+void via_odev_to_seq(struct seq_file *m, u32 odev)
+{
+	int i, count = 0;
+
+	for (i = 0; i < ARRAY_SIZE(device_mapping); i++) {
+		if (odev & device_mapping[i].device) {
+			if (count > 0)
+				seq_putc(m, ',');
+
+			seq_puts(m, device_mapping[i].name);
+			count++;
+		}
+	}
+
+	seq_putc(m, '\n');
+}
+
 static void load_fix_bit_crtc_reg(void)
 {
 	/* always set to 1 */
diff --git a/drivers/video/via/hw.h b/drivers/video/via/hw.h
index 45dee39..657dbd6 100644
--- a/drivers/video/via/hw.h
+++ b/drivers/video/via/hw.h
@@ -22,6 +22,8 @@
 #ifndef __HW_H__
 #define __HW_H__
 
+#include <linux/seq_file.h>
+
 #include "viamode.h"
 #include "global.h"
 #include "via_modesetting.h"
@@ -882,6 +884,11 @@ struct pci_device_id_info {
 	u32 chip_index;
 };
 
+struct via_device_mapping {
+	u32 device;
+	const char *name;
+};
+
 extern unsigned int viafb_second_virtual_xres;
 extern int viafb_SAMM_ON;
 extern int viafb_dual_fb;
@@ -899,6 +906,9 @@ void viafb_load_reg(int timing_value, int viafb_load_reg_num,
 	      int io_type);
 void viafb_crt_disable(void);
 void viafb_crt_enable(void);
+void via_set_source(u32 devices, u8 iga);
+u32 via_parse_odev(char *input, char **end);
+void via_odev_to_seq(struct seq_file *m, u32 odev);
 void init_ad9389(void);
 /* Access I/O Function */
 void viafb_lock_crt(void);
diff --git a/drivers/video/via/viafbdev.c b/drivers/video/via/viafbdev.c
index 5a947b0..5864092 100644
--- a/drivers/video/via/viafbdev.c
+++ b/drivers/video/via/viafbdev.c
@@ -1431,26 +1431,158 @@ static const struct file_operations viafb_vt1636_proc_fops = {
 	.write		= viafb_vt1636_proc_write,
 };
 
-static void viafb_init_proc(struct proc_dir_entry **viafb_entry)
+#endif /* CONFIG_FB_VIA_DIRECT_PROCFS */
+
+static ssize_t odev_update(const char __user *buffer, size_t count, u32 *odev)
+{
+	char buf[64], *ptr = buf;
+	u32 devices;
+	bool add, sub;
+
+	if (count < 1 || count > 63)
+		return -EINVAL;
+	if (copy_from_user(&buf[0], buffer, count))
+		return -EFAULT;
+	buf[count] = '\0';
+	add = buf[0] == '+';
+	sub = buf[0] == '-';
+	if (add || sub)
+		ptr++;
+	devices = via_parse_odev(ptr, &ptr);
+	if (*ptr == '\n')
+		ptr++;
+	if (*ptr != 0)
+		return -EINVAL;
+	if (add)
+		*odev |= devices;
+	else if (sub)
+		*odev &= ~devices;
+	else
+		*odev = devices;
+	return count;
+}
+
+static int viafb_iga1_odev_proc_show(struct seq_file *m, void *v)
+{
+	via_odev_to_seq(m, viaparinfo->shared->iga1_devices);
+	return 0;
+}
+
+static int viafb_iga1_odev_proc_open(struct inode *inode, struct file *file)
 {
-	*viafb_entry = proc_mkdir("viafb", NULL);
-	if (*viafb_entry) {
-		proc_create("dvp0", 0, *viafb_entry, &viafb_dvp0_proc_fops);
-		proc_create("dvp1", 0, *viafb_entry, &viafb_dvp1_proc_fops);
-		proc_create("dfph", 0, *viafb_entry, &viafb_dfph_proc_fops);
-		proc_create("dfpl", 0, *viafb_entry, &viafb_dfpl_proc_fops);
+	return single_open(file, viafb_iga1_odev_proc_show, NULL);
+}
+
+static ssize_t viafb_iga1_odev_proc_write(struct file *file,
+	const char __user *buffer, size_t count, loff_t *pos)
+{
+	u32 dev_on, dev_off, dev_old, dev_new;
+	ssize_t res;
+
+	dev_old = dev_new = viaparinfo->shared->iga1_devices;
+	res = odev_update(buffer, count, &dev_new);
+	if (res != count)
+		return res;
+	dev_off = dev_old & ~dev_new;
+	dev_on = dev_new & ~dev_old;
+	viaparinfo->shared->iga1_devices = dev_new;
+	viaparinfo->shared->iga2_devices &= ~dev_new;
+	via_set_source(dev_new, IGA1);
+	return res;
+}
+
+static const struct file_operations viafb_iga1_odev_proc_fops = {
+	.owner		= THIS_MODULE,
+	.open		= viafb_iga1_odev_proc_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+	.write		= viafb_iga1_odev_proc_write,
+};
+
+static int viafb_iga2_odev_proc_show(struct seq_file *m, void *v)
+{
+	via_odev_to_seq(m, viaparinfo->shared->iga2_devices);
+	return 0;
+}
+
+static int viafb_iga2_odev_proc_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, viafb_iga2_odev_proc_show, NULL);
+}
+
+static ssize_t viafb_iga2_odev_proc_write(struct file *file,
+	const char __user *buffer, size_t count, loff_t *pos)
+{
+	u32 dev_on, dev_off, dev_old, dev_new;
+	ssize_t res;
+
+	dev_old = dev_new = viaparinfo->shared->iga2_devices;
+	res = odev_update(buffer, count, &dev_new);
+	if (res != count)
+		return res;
+	dev_off = dev_old & ~dev_new;
+	dev_on = dev_new & ~dev_old;
+	viaparinfo->shared->iga2_devices = dev_new;
+	viaparinfo->shared->iga1_devices &= ~dev_new;
+	via_set_source(dev_new, IGA2);
+	return res;
+}
+
+static const struct file_operations viafb_iga2_odev_proc_fops = {
+	.owner		= THIS_MODULE,
+	.open		= viafb_iga2_odev_proc_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+	.write		= viafb_iga2_odev_proc_write,
+};
+
+static void viafb_init_proc(struct viafb_shared *shared)
+{
+	struct proc_dir_entry *iga1_entry, *iga2_entry,
+		*viafb_entry = proc_mkdir("viafb", NULL);
+
+	shared->proc_entry = viafb_entry;
+	if (viafb_entry) {
+#ifdef CONFIG_FB_VIA_DIRECT_PROCFS
+		proc_create("dvp0", 0, viafb_entry, &viafb_dvp0_proc_fops);
+		proc_create("dvp1", 0, viafb_entry, &viafb_dvp1_proc_fops);
+		proc_create("dfph", 0, viafb_entry, &viafb_dfph_proc_fops);
+		proc_create("dfpl", 0, viafb_entry, &viafb_dfpl_proc_fops);
 		if (VT1636_LVDS == viaparinfo->chip_info->lvds_chip_info.
 			lvds_chip_name || VT1636_LVDS ==
 		    viaparinfo->chip_info->lvds_chip_info2.lvds_chip_name) {
 			proc_create("vt1636", 0, *viafb_entry, &viafb_vt1636_proc_fops);
 		}
+#endif /* CONFIG_FB_VIA_DIRECT_PROCFS */
 
+		iga1_entry = proc_mkdir("iga1", viafb_entry);
+		shared->iga1_proc_entry = iga1_entry;
+		proc_create("output_devices", 0, iga1_entry,
+			&viafb_iga1_odev_proc_fops);
+		iga2_entry = proc_mkdir("iga2", viafb_entry);
+		shared->iga2_proc_entry = iga2_entry;
+		proc_create("output_devices", 0, iga2_entry,
+			&viafb_iga2_odev_proc_fops);
 	}
 }
-static void viafb_remove_proc(struct proc_dir_entry *viafb_entry)
+static void viafb_remove_proc(struct viafb_shared *shared)
 {
-	struct chip_information *chip_info = &viaparinfo->shared->chip_info;
+	struct chip_information *chip_info = &shared->chip_info;
+	struct proc_dir_entry *viafb_entry = shared->proc_entry,
+		*iga1_entry = shared->iga1_proc_entry,
+		*iga2_entry = shared->iga2_proc_entry;
 
+	if (!viafb_entry)
+		return;
+
+	remove_proc_entry("output_devices", iga2_entry);
+	remove_proc_entry("iga2", viafb_entry);
+	remove_proc_entry("output_devices", iga1_entry);
+	remove_proc_entry("iga1", viafb_entry);
+
+#ifdef CONFIG_FB_VIA_DIRECT_PROCFS
 	remove_proc_entry("dvp0", viafb_entry);/* parent dir */
 	remove_proc_entry("dvp1", viafb_entry);
 	remove_proc_entry("dfph", viafb_entry);
@@ -1458,12 +1590,11 @@ static void viafb_remove_proc(struct proc_dir_entry *viafb_entry)
 	if (chip_info->lvds_chip_info.lvds_chip_name == VT1636_LVDS
 		|| chip_info->lvds_chip_info2.lvds_chip_name == VT1636_LVDS)
 		remove_proc_entry("vt1636", viafb_entry);
+#endif /* CONFIG_FB_VIA_DIRECT_PROCFS */
 
 	remove_proc_entry("viafb", NULL);
 }
 
-#endif /* CONFIG_FB_VIA_DIRECT_PROCFS */
-
 static int parse_mode(const char *str, u32 *xres, u32 *yres)
 {
 	char *ptr;
@@ -1671,9 +1802,7 @@ int __devinit via_fb_pci_probe(struct viafb_dev *vdev)
 		  viafbinfo->node, viafbinfo->fix.id, default_var.xres,
 		  default_var.yres, default_var.bits_per_pixel);
 
-#ifdef CONFIG_FB_VIA_DIRECT_PROCFS
-	viafb_init_proc(&viaparinfo->shared->proc_entry);
-#endif
+	viafb_init_proc(viaparinfo->shared);
 	viafb_init_dac(IGA2);
 	return 0;
 
@@ -1700,9 +1829,7 @@ void __devexit via_fb_pci_remove(struct pci_dev *pdev)
 	unregister_framebuffer(viafbinfo);
 	if (viafb_dual_fb)
 		unregister_framebuffer(viafbinfo1);
-#ifdef CONFIG_FB_VIA_DIRECT_PROCFS
-	viafb_remove_proc(viaparinfo->shared->proc_entry);
-#endif
+	viafb_remove_proc(viaparinfo->shared);
 	framebuffer_release(viafbinfo);
 	if (viafb_dual_fb)
 		framebuffer_release(viafbinfo1);
diff --git a/drivers/video/via/viafbdev.h b/drivers/video/via/viafbdev.h
index 945a47a..d66f963 100644
--- a/drivers/video/via/viafbdev.h
+++ b/drivers/video/via/viafbdev.h
@@ -44,6 +44,8 @@ struct viafb_shared {
 	u32 iga2_devices;
 
 	struct proc_dir_entry *proc_entry;	/*viafb proc entry */
+	struct proc_dir_entry *iga1_proc_entry;
+	struct proc_dir_entry *iga2_proc_entry;
 	struct viafb_dev *vdev;			/* Global dev info */
 
 	/* All the information will be needed to set engine */
-- 
1.6.3.2


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH 01/12] viafb: add interface for output device configuration
@ 2010-09-19  7:26   ` Florian Tobias Schandinat
  0 siblings, 0 replies; 27+ messages in thread
From: Florian Tobias Schandinat @ 2010-09-19  7:26 UTC (permalink / raw)
  To: linux-fbdev
  Cc: linux-kernel, Florian Tobias Schandinat, Joseph Chan,
	Jonathan Corbet, Andrew Morton

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>
Cc: Joseph Chan <JosephChan@via.com.tw>
Cc: Jonathan Corbet <corbet@lwn.net>
Cc: Andrew Morton <akpm@linux-foundation.org>
---
 drivers/video/via/hw.c       |   53 ++++++++++++++
 drivers/video/via/hw.h       |   10 +++
 drivers/video/via/viafbdev.c |  161 +++++++++++++++++++++++++++++++++++++-----
 drivers/video/via/viafbdev.h |    2 +
 4 files changed, 209 insertions(+), 17 deletions(-)

diff --git a/drivers/video/via/hw.c b/drivers/video/via/hw.c
index 0330323..e65edce 100644
--- a/drivers/video/via/hw.c
+++ b/drivers/video/via/hw.c
@@ -718,6 +718,16 @@ static struct rgbLUT palLUT_table[] = {
 								     0x00}
 };
 
+static struct via_device_mapping device_mapping[] = {
+	{VIA_6C, "6C"},
+	{VIA_93, "93"},
+	{VIA_96, "96"},
+	{VIA_CRT, "CRT"},
+	{VIA_DVP1, "DVP1"},
+	{VIA_LVDS1, "LVDS1"},
+	{VIA_LVDS2, "LVDS2"}
+};
+
 static void load_fix_bit_crtc_reg(void);
 static void __devinit init_gfx_chip_info(int chip_type);
 static void __devinit init_tmds_chip_info(void);
@@ -1026,6 +1036,49 @@ void via_set_source(u32 devices, u8 iga)
 		set_lvds2_source(iga);
 }
 
+u32 via_parse_odev(char *input, char **end)
+{
+	char *ptr = input;
+	u32 odev = 0;
+	bool next = true;
+	int i, len;
+
+	while (next) {
+		next = false;
+		for (i = 0; i < ARRAY_SIZE(device_mapping); i++) {
+			len = strlen(device_mapping[i].name);
+			if (!strncmp(ptr, device_mapping[i].name, len)) {
+				odev |= device_mapping[i].device;
+				ptr += len;
+				if (*ptr = ',') {
+					ptr++;
+					next = true;
+				}
+			}
+		}
+	}
+
+	*end = ptr;
+	return odev;
+}
+
+void via_odev_to_seq(struct seq_file *m, u32 odev)
+{
+	int i, count = 0;
+
+	for (i = 0; i < ARRAY_SIZE(device_mapping); i++) {
+		if (odev & device_mapping[i].device) {
+			if (count > 0)
+				seq_putc(m, ',');
+
+			seq_puts(m, device_mapping[i].name);
+			count++;
+		}
+	}
+
+	seq_putc(m, '\n');
+}
+
 static void load_fix_bit_crtc_reg(void)
 {
 	/* always set to 1 */
diff --git a/drivers/video/via/hw.h b/drivers/video/via/hw.h
index 45dee39..657dbd6 100644
--- a/drivers/video/via/hw.h
+++ b/drivers/video/via/hw.h
@@ -22,6 +22,8 @@
 #ifndef __HW_H__
 #define __HW_H__
 
+#include <linux/seq_file.h>
+
 #include "viamode.h"
 #include "global.h"
 #include "via_modesetting.h"
@@ -882,6 +884,11 @@ struct pci_device_id_info {
 	u32 chip_index;
 };
 
+struct via_device_mapping {
+	u32 device;
+	const char *name;
+};
+
 extern unsigned int viafb_second_virtual_xres;
 extern int viafb_SAMM_ON;
 extern int viafb_dual_fb;
@@ -899,6 +906,9 @@ void viafb_load_reg(int timing_value, int viafb_load_reg_num,
 	      int io_type);
 void viafb_crt_disable(void);
 void viafb_crt_enable(void);
+void via_set_source(u32 devices, u8 iga);
+u32 via_parse_odev(char *input, char **end);
+void via_odev_to_seq(struct seq_file *m, u32 odev);
 void init_ad9389(void);
 /* Access I/O Function */
 void viafb_lock_crt(void);
diff --git a/drivers/video/via/viafbdev.c b/drivers/video/via/viafbdev.c
index 5a947b0..5864092 100644
--- a/drivers/video/via/viafbdev.c
+++ b/drivers/video/via/viafbdev.c
@@ -1431,26 +1431,158 @@ static const struct file_operations viafb_vt1636_proc_fops = {
 	.write		= viafb_vt1636_proc_write,
 };
 
-static void viafb_init_proc(struct proc_dir_entry **viafb_entry)
+#endif /* CONFIG_FB_VIA_DIRECT_PROCFS */
+
+static ssize_t odev_update(const char __user *buffer, size_t count, u32 *odev)
+{
+	char buf[64], *ptr = buf;
+	u32 devices;
+	bool add, sub;
+
+	if (count < 1 || count > 63)
+		return -EINVAL;
+	if (copy_from_user(&buf[0], buffer, count))
+		return -EFAULT;
+	buf[count] = '\0';
+	add = buf[0] = '+';
+	sub = buf[0] = '-';
+	if (add || sub)
+		ptr++;
+	devices = via_parse_odev(ptr, &ptr);
+	if (*ptr = '\n')
+		ptr++;
+	if (*ptr != 0)
+		return -EINVAL;
+	if (add)
+		*odev |= devices;
+	else if (sub)
+		*odev &= ~devices;
+	else
+		*odev = devices;
+	return count;
+}
+
+static int viafb_iga1_odev_proc_show(struct seq_file *m, void *v)
+{
+	via_odev_to_seq(m, viaparinfo->shared->iga1_devices);
+	return 0;
+}
+
+static int viafb_iga1_odev_proc_open(struct inode *inode, struct file *file)
 {
-	*viafb_entry = proc_mkdir("viafb", NULL);
-	if (*viafb_entry) {
-		proc_create("dvp0", 0, *viafb_entry, &viafb_dvp0_proc_fops);
-		proc_create("dvp1", 0, *viafb_entry, &viafb_dvp1_proc_fops);
-		proc_create("dfph", 0, *viafb_entry, &viafb_dfph_proc_fops);
-		proc_create("dfpl", 0, *viafb_entry, &viafb_dfpl_proc_fops);
+	return single_open(file, viafb_iga1_odev_proc_show, NULL);
+}
+
+static ssize_t viafb_iga1_odev_proc_write(struct file *file,
+	const char __user *buffer, size_t count, loff_t *pos)
+{
+	u32 dev_on, dev_off, dev_old, dev_new;
+	ssize_t res;
+
+	dev_old = dev_new = viaparinfo->shared->iga1_devices;
+	res = odev_update(buffer, count, &dev_new);
+	if (res != count)
+		return res;
+	dev_off = dev_old & ~dev_new;
+	dev_on = dev_new & ~dev_old;
+	viaparinfo->shared->iga1_devices = dev_new;
+	viaparinfo->shared->iga2_devices &= ~dev_new;
+	via_set_source(dev_new, IGA1);
+	return res;
+}
+
+static const struct file_operations viafb_iga1_odev_proc_fops = {
+	.owner		= THIS_MODULE,
+	.open		= viafb_iga1_odev_proc_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+	.write		= viafb_iga1_odev_proc_write,
+};
+
+static int viafb_iga2_odev_proc_show(struct seq_file *m, void *v)
+{
+	via_odev_to_seq(m, viaparinfo->shared->iga2_devices);
+	return 0;
+}
+
+static int viafb_iga2_odev_proc_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, viafb_iga2_odev_proc_show, NULL);
+}
+
+static ssize_t viafb_iga2_odev_proc_write(struct file *file,
+	const char __user *buffer, size_t count, loff_t *pos)
+{
+	u32 dev_on, dev_off, dev_old, dev_new;
+	ssize_t res;
+
+	dev_old = dev_new = viaparinfo->shared->iga2_devices;
+	res = odev_update(buffer, count, &dev_new);
+	if (res != count)
+		return res;
+	dev_off = dev_old & ~dev_new;
+	dev_on = dev_new & ~dev_old;
+	viaparinfo->shared->iga2_devices = dev_new;
+	viaparinfo->shared->iga1_devices &= ~dev_new;
+	via_set_source(dev_new, IGA2);
+	return res;
+}
+
+static const struct file_operations viafb_iga2_odev_proc_fops = {
+	.owner		= THIS_MODULE,
+	.open		= viafb_iga2_odev_proc_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+	.write		= viafb_iga2_odev_proc_write,
+};
+
+static void viafb_init_proc(struct viafb_shared *shared)
+{
+	struct proc_dir_entry *iga1_entry, *iga2_entry,
+		*viafb_entry = proc_mkdir("viafb", NULL);
+
+	shared->proc_entry = viafb_entry;
+	if (viafb_entry) {
+#ifdef CONFIG_FB_VIA_DIRECT_PROCFS
+		proc_create("dvp0", 0, viafb_entry, &viafb_dvp0_proc_fops);
+		proc_create("dvp1", 0, viafb_entry, &viafb_dvp1_proc_fops);
+		proc_create("dfph", 0, viafb_entry, &viafb_dfph_proc_fops);
+		proc_create("dfpl", 0, viafb_entry, &viafb_dfpl_proc_fops);
 		if (VT1636_LVDS = viaparinfo->chip_info->lvds_chip_info.
 			lvds_chip_name || VT1636_LVDS =
 		    viaparinfo->chip_info->lvds_chip_info2.lvds_chip_name) {
 			proc_create("vt1636", 0, *viafb_entry, &viafb_vt1636_proc_fops);
 		}
+#endif /* CONFIG_FB_VIA_DIRECT_PROCFS */
 
+		iga1_entry = proc_mkdir("iga1", viafb_entry);
+		shared->iga1_proc_entry = iga1_entry;
+		proc_create("output_devices", 0, iga1_entry,
+			&viafb_iga1_odev_proc_fops);
+		iga2_entry = proc_mkdir("iga2", viafb_entry);
+		shared->iga2_proc_entry = iga2_entry;
+		proc_create("output_devices", 0, iga2_entry,
+			&viafb_iga2_odev_proc_fops);
 	}
 }
-static void viafb_remove_proc(struct proc_dir_entry *viafb_entry)
+static void viafb_remove_proc(struct viafb_shared *shared)
 {
-	struct chip_information *chip_info = &viaparinfo->shared->chip_info;
+	struct chip_information *chip_info = &shared->chip_info;
+	struct proc_dir_entry *viafb_entry = shared->proc_entry,
+		*iga1_entry = shared->iga1_proc_entry,
+		*iga2_entry = shared->iga2_proc_entry;
 
+	if (!viafb_entry)
+		return;
+
+	remove_proc_entry("output_devices", iga2_entry);
+	remove_proc_entry("iga2", viafb_entry);
+	remove_proc_entry("output_devices", iga1_entry);
+	remove_proc_entry("iga1", viafb_entry);
+
+#ifdef CONFIG_FB_VIA_DIRECT_PROCFS
 	remove_proc_entry("dvp0", viafb_entry);/* parent dir */
 	remove_proc_entry("dvp1", viafb_entry);
 	remove_proc_entry("dfph", viafb_entry);
@@ -1458,12 +1590,11 @@ static void viafb_remove_proc(struct proc_dir_entry *viafb_entry)
 	if (chip_info->lvds_chip_info.lvds_chip_name = VT1636_LVDS
 		|| chip_info->lvds_chip_info2.lvds_chip_name = VT1636_LVDS)
 		remove_proc_entry("vt1636", viafb_entry);
+#endif /* CONFIG_FB_VIA_DIRECT_PROCFS */
 
 	remove_proc_entry("viafb", NULL);
 }
 
-#endif /* CONFIG_FB_VIA_DIRECT_PROCFS */
-
 static int parse_mode(const char *str, u32 *xres, u32 *yres)
 {
 	char *ptr;
@@ -1671,9 +1802,7 @@ int __devinit via_fb_pci_probe(struct viafb_dev *vdev)
 		  viafbinfo->node, viafbinfo->fix.id, default_var.xres,
 		  default_var.yres, default_var.bits_per_pixel);
 
-#ifdef CONFIG_FB_VIA_DIRECT_PROCFS
-	viafb_init_proc(&viaparinfo->shared->proc_entry);
-#endif
+	viafb_init_proc(viaparinfo->shared);
 	viafb_init_dac(IGA2);
 	return 0;
 
@@ -1700,9 +1829,7 @@ void __devexit via_fb_pci_remove(struct pci_dev *pdev)
 	unregister_framebuffer(viafbinfo);
 	if (viafb_dual_fb)
 		unregister_framebuffer(viafbinfo1);
-#ifdef CONFIG_FB_VIA_DIRECT_PROCFS
-	viafb_remove_proc(viaparinfo->shared->proc_entry);
-#endif
+	viafb_remove_proc(viaparinfo->shared);
 	framebuffer_release(viafbinfo);
 	if (viafb_dual_fb)
 		framebuffer_release(viafbinfo1);
diff --git a/drivers/video/via/viafbdev.h b/drivers/video/via/viafbdev.h
index 945a47a..d66f963 100644
--- a/drivers/video/via/viafbdev.h
+++ b/drivers/video/via/viafbdev.h
@@ -44,6 +44,8 @@ struct viafb_shared {
 	u32 iga2_devices;
 
 	struct proc_dir_entry *proc_entry;	/*viafb proc entry */
+	struct proc_dir_entry *iga1_proc_entry;
+	struct proc_dir_entry *iga2_proc_entry;
 	struct viafb_dev *vdev;			/* Global dev info */
 
 	/* All the information will be needed to set engine */
-- 
1.6.3.2


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH 02/12] viafb: limit LCD code impact
  2010-09-19  7:26 [PATCH 00/12] viafb output device rework - part 2 Florian Tobias Schandinat
@ 2010-09-19  7:26   ` Florian Tobias Schandinat
  2010-09-19  7:26   ` Florian Tobias Schandinat
                     ` (10 subsequent siblings)
  11 siblings, 0 replies; 27+ messages in thread
From: Florian Tobias Schandinat @ 2010-09-19  7:26 UTC (permalink / raw)
  To: linux-fbdev; +Cc: linux-kernel, Florian Tobias Schandinat, Joseph Chan

viafb: limit LCD code impact

This patch cleans the LCD code up. It forbids overwritting global
decissions like what IGA should be used as the source and whether to
enable the second display channel. Additionally it removes a bit code
duplication.

Signed-off-by: Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
Cc: Joseph Chan <JosephChan@via.com.tw>
---
 drivers/video/via/lcd.c |   31 -------------------------------
 1 files changed, 0 insertions(+), 31 deletions(-)

diff --git a/drivers/video/via/lcd.c b/drivers/video/via/lcd.c
index e99f933..b7d5535 100644
--- a/drivers/video/via/lcd.c
+++ b/drivers/video/via/lcd.c
@@ -818,19 +818,12 @@ void viafb_lcd_disable(void)
 		viafb_write_reg_mask(SR3D, VIASR, 0x00, 0x20);
 		/* 24 bit DI data paht off */
 		viafb_write_reg_mask(CR91, VIACR, 0x80, 0x80);
-		/* Simultaneout disabled   */
-		viafb_write_reg_mask(CR6B, VIACR, 0x00, 0x08);
 	}
 
 	/* Disable expansion bit   */
 	viafb_write_reg_mask(CR79, VIACR, 0x00, 0x01);
-	/* CRT path set to IGA1    */
-	viafb_write_reg_mask(SR16, VIASR, 0x00, 0x40);
 	/* Simultaneout disabled   */
 	viafb_write_reg_mask(CR6B, VIACR, 0x00, 0x08);
-	/* IGA2 path disabled      */
-	viafb_write_reg_mask(CR6A, VIACR, 0x00, 0x80);
-
 }
 
 static void set_lcd_output_path(int set_iga, int output_interface)
@@ -892,33 +885,9 @@ void viafb_lcd_enable(void)
 		viafb_write_reg_mask(SR3D, VIASR, 0x20, 0x20);
 		/* 24 bit DI data paht on  */
 		viafb_write_reg_mask(CR91, VIACR, 0x00, 0x80);
-
-		/* Set data source selection bit by iga path */
-		if (viaparinfo->lvds_setting_info->iga_path == IGA1) {
-			/* DFP-H set to IGA1       */
-			viafb_write_reg_mask(CR97, VIACR, 0x00, 0x10);
-			/* DFP-L set to IGA1       */
-			viafb_write_reg_mask(CR99, VIACR, 0x00, 0x10);
-		} else {
-			/* DFP-H set to IGA2       */
-			viafb_write_reg_mask(CR97, VIACR, 0x10, 0x10);
-			/* DFP-L set to IGA2       */
-			viafb_write_reg_mask(CR99, VIACR, 0x10, 0x10);
-		}
 		/* LCD enabled             */
 		viafb_write_reg_mask(CR6A, VIACR, 0x48, 0x48);
 	}
-
-	if (viaparinfo->lvds_setting_info->iga_path == IGA1) {
-		/* CRT path set to IGA2    */
-		viafb_write_reg_mask(SR16, VIASR, 0x40, 0x40);
-		/* IGA2 path disabled      */
-		viafb_write_reg_mask(CR6A, VIACR, 0x00, 0x80);
-		/* IGA2 path enabled       */
-	} else {		/* IGA2 */
-		viafb_write_reg_mask(CR6A, VIACR, 0x80, 0x80);
-	}
-
 }
 
 static void lcd_powersequence_off(void)
-- 
1.6.3.2


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH 02/12] viafb: limit LCD code impact
@ 2010-09-19  7:26   ` Florian Tobias Schandinat
  0 siblings, 0 replies; 27+ messages in thread
From: Florian Tobias Schandinat @ 2010-09-19  7:26 UTC (permalink / raw)
  To: linux-fbdev; +Cc: linux-kernel, Florian Tobias Schandinat, Joseph Chan

viafb: limit LCD code impact

This patch cleans the LCD code up. It forbids overwritting global
decissions like what IGA should be used as the source and whether to
enable the second display channel. Additionally it removes a bit code
duplication.

Signed-off-by: Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
Cc: Joseph Chan <JosephChan@via.com.tw>
---
 drivers/video/via/lcd.c |   31 -------------------------------
 1 files changed, 0 insertions(+), 31 deletions(-)

diff --git a/drivers/video/via/lcd.c b/drivers/video/via/lcd.c
index e99f933..b7d5535 100644
--- a/drivers/video/via/lcd.c
+++ b/drivers/video/via/lcd.c
@@ -818,19 +818,12 @@ void viafb_lcd_disable(void)
 		viafb_write_reg_mask(SR3D, VIASR, 0x00, 0x20);
 		/* 24 bit DI data paht off */
 		viafb_write_reg_mask(CR91, VIACR, 0x80, 0x80);
-		/* Simultaneout disabled   */
-		viafb_write_reg_mask(CR6B, VIACR, 0x00, 0x08);
 	}
 
 	/* Disable expansion bit   */
 	viafb_write_reg_mask(CR79, VIACR, 0x00, 0x01);
-	/* CRT path set to IGA1    */
-	viafb_write_reg_mask(SR16, VIASR, 0x00, 0x40);
 	/* Simultaneout disabled   */
 	viafb_write_reg_mask(CR6B, VIACR, 0x00, 0x08);
-	/* IGA2 path disabled      */
-	viafb_write_reg_mask(CR6A, VIACR, 0x00, 0x80);
-
 }
 
 static void set_lcd_output_path(int set_iga, int output_interface)
@@ -892,33 +885,9 @@ void viafb_lcd_enable(void)
 		viafb_write_reg_mask(SR3D, VIASR, 0x20, 0x20);
 		/* 24 bit DI data paht on  */
 		viafb_write_reg_mask(CR91, VIACR, 0x00, 0x80);
-
-		/* Set data source selection bit by iga path */
-		if (viaparinfo->lvds_setting_info->iga_path = IGA1) {
-			/* DFP-H set to IGA1       */
-			viafb_write_reg_mask(CR97, VIACR, 0x00, 0x10);
-			/* DFP-L set to IGA1       */
-			viafb_write_reg_mask(CR99, VIACR, 0x00, 0x10);
-		} else {
-			/* DFP-H set to IGA2       */
-			viafb_write_reg_mask(CR97, VIACR, 0x10, 0x10);
-			/* DFP-L set to IGA2       */
-			viafb_write_reg_mask(CR99, VIACR, 0x10, 0x10);
-		}
 		/* LCD enabled             */
 		viafb_write_reg_mask(CR6A, VIACR, 0x48, 0x48);
 	}
-
-	if (viaparinfo->lvds_setting_info->iga_path = IGA1) {
-		/* CRT path set to IGA2    */
-		viafb_write_reg_mask(SR16, VIASR, 0x40, 0x40);
-		/* IGA2 path disabled      */
-		viafb_write_reg_mask(CR6A, VIACR, 0x00, 0x80);
-		/* IGA2 path enabled       */
-	} else {		/* IGA2 */
-		viafb_write_reg_mask(CR6A, VIACR, 0x80, 0x80);
-	}
-
 }
 
 static void lcd_powersequence_off(void)
-- 
1.6.3.2


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH 03/12] viafb: introduce per output device power management
  2010-09-19  7:26 [PATCH 00/12] viafb output device rework - part 2 Florian Tobias Schandinat
@ 2010-09-19  7:26   ` Florian Tobias Schandinat
  2010-09-19  7:26   ` Florian Tobias Schandinat
                     ` (10 subsequent siblings)
  11 siblings, 0 replies; 27+ messages in thread
From: Florian Tobias Schandinat @ 2010-09-19  7:26 UTC (permalink / raw)
  To: linux-fbdev; +Cc: linux-kernel, Florian Tobias Schandinat, Joseph Chan

viafb: introduce per output device power management

This patch moves common parts of dvi.c, lcd.c and vt1636.c to hw.c to
start a per output device power management. There should be no runtime
changes aside that this patch enables the proc interface to enable/disable
devices when needed which greatly increases the chances that changes to
the output device configuration will work. However the power management is
not yet complete so it might fail on some configurations. As this area is
quite complex and touches undocumented things there is a slight chance of
regressions.

Signed-off-by: Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
Cc: Joseph Chan <JosephChan@via.com.tw>
---
 drivers/video/via/dvi.c      |   25 +--------
 drivers/video/via/hw.c       |  132 +++++++++++++++++++++++++++++++++++++----
 drivers/video/via/hw.h       |    9 ++-
 drivers/video/via/lcd.c      |   10 ---
 drivers/video/via/viafbdev.c |   16 +++--
 drivers/video/via/vt1636.c   |   56 ------------------
 6 files changed, 137 insertions(+), 111 deletions(-)

diff --git a/drivers/video/via/dvi.c b/drivers/video/via/dvi.c
index 7c82f6f..84e21b3 100644
--- a/drivers/video/via/dvi.c
+++ b/drivers/video/via/dvi.c
@@ -470,26 +470,6 @@ static void __devinit dvi_get_panel_size_from_DDCv2(
 void viafb_dvi_disable(void)
 {
 	if (viaparinfo->chip_info->
-		tmds_chip_info.output_interface == INTERFACE_DVP0)
-		viafb_write_reg(SR1E, VIASR,
-		viafb_read_reg(VIASR, SR1E) & (~0xC0));
-
-	if (viaparinfo->chip_info->
-		tmds_chip_info.output_interface == INTERFACE_DVP1)
-		viafb_write_reg(SR1E, VIASR,
-		viafb_read_reg(VIASR, SR1E) & (~0x30));
-
-	if (viaparinfo->chip_info->
-		tmds_chip_info.output_interface == INTERFACE_DFP_HIGH)
-		viafb_write_reg(SR2A, VIASR,
-		viafb_read_reg(VIASR, SR2A) & (~0x0C));
-
-	if (viaparinfo->chip_info->
-		tmds_chip_info.output_interface == INTERFACE_DFP_LOW)
-		viafb_write_reg(SR2A, VIASR,
-		viafb_read_reg(VIASR, SR2A) & (~0x03));
-
-	if (viaparinfo->chip_info->
 		tmds_chip_info.output_interface == INTERFACE_TMDS)
 		/* Turn off TMDS power. */
 		viafb_write_reg(CRD2, VIACR,
@@ -571,7 +551,6 @@ void viafb_dvi_enable(void)
 	case INTERFACE_DVP0:
 		viafb_write_reg_mask(CR6B, VIACR, 0x01, BIT0);
 		viafb_write_reg_mask(CR6C, VIACR, 0x21, BIT0 + BIT5);
-		viafb_write_reg_mask(SR1E, VIASR, 0xC0, BIT7 + BIT6);
 		dvi_patch_skew_dvp0();
 		if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266)
 			tmds_register_write(0x88, 0x3b);
@@ -585,7 +564,6 @@ void viafb_dvi_enable(void)
 		if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266)
 			viafb_write_reg_mask(CR93, VIACR, 0x21, BIT0 + BIT5);
 
-		viafb_write_reg_mask(SR1E, VIASR, 0x30, BIT4 + BIT5);
 		/*fix dvi cann't be enabled with MB VT5718C4 - Al Zhang */
 		if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266)
 			tmds_register_write(0x88, 0x3b);
@@ -616,14 +594,13 @@ void viafb_dvi_enable(void)
 		if (viaparinfo->chip_info->gfx_chip_name != UNICHROME_CLE266)
 			via_write_reg_mask(VIACR, CR97, 0x03, 0x03);
 
-		viafb_write_reg_mask(SR2A, VIASR, 0x0C, BIT2 + BIT3);
 		via_write_reg_mask(VIACR, 0x91, 0x00, 0x20);
 		break;
 
 	case INTERFACE_DFP_LOW:
 		if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266)
 			break;
-		viafb_write_reg_mask(SR2A, VIASR, 0x03, BIT0 + BIT1);
+
 		dvi_patch_skew_dvp_low();
 		via_write_reg_mask(VIACR, 0x91, 0x00, 0x20);
 		break;
diff --git a/drivers/video/via/hw.c b/drivers/video/via/hw.c
index e65edce..132d811 100644
--- a/drivers/video/via/hw.c
+++ b/drivers/video/via/hw.c
@@ -1036,6 +1036,121 @@ void via_set_source(u32 devices, u8 iga)
 		set_lvds2_source(iga);
 }
 
+static void set_crt_state(u8 state)
+{
+	u8 value;
+
+	switch (state) {
+	case VIA_STATE_ON:
+		value = 0x00;
+		break;
+	case VIA_STATE_STANDBY:
+		value = 0x10;
+		break;
+	case VIA_STATE_SUSPEND:
+		value = 0x20;
+		break;
+	case VIA_STATE_OFF:
+		value = 0x30;
+		break;
+	default:
+		return;
+	}
+
+	via_write_reg_mask(VIACR, 0x36, value, 0x30);
+}
+
+static void set_96_state(u8 state)
+{
+	u8 value;
+
+	switch (state) {
+	case VIA_STATE_ON:
+		value = 0xC0;
+		break;
+	case VIA_STATE_OFF:
+		value = 0x00;
+		break;
+	default:
+		return;
+	}
+
+	via_write_reg_mask(VIASR, 0x1E, value, 0xC0);
+}
+
+static void set_dvp1_state(u8 state)
+{
+	u8 value;
+
+	switch (state) {
+	case VIA_STATE_ON:
+		value = 0x30;
+		break;
+	case VIA_STATE_OFF:
+		value = 0x00;
+		break;
+	default:
+		return;
+	}
+
+	via_write_reg_mask(VIASR, 0x1E, value, 0x30);
+}
+
+static void set_lvds1_state(u8 state)
+{
+	u8 value;
+
+	switch (state) {
+	case VIA_STATE_ON:
+		value = 0x03;
+		break;
+	case VIA_STATE_OFF:
+		value = 0x00;
+		break;
+	default:
+		return;
+	}
+
+	via_write_reg_mask(VIASR, 0x2A, value, 0x03);
+}
+
+static void set_lvds2_state(u8 state)
+{
+	u8 value;
+
+	switch (state) {
+	case VIA_STATE_ON:
+		value = 0x0C;
+		break;
+	case VIA_STATE_OFF:
+		value = 0x00;
+		break;
+	default:
+		return;
+	}
+
+	via_write_reg_mask(VIASR, 0x2A, value, 0x0C);
+}
+
+void via_set_state(u32 devices, u8 state)
+{
+	/*
+	TODO: Can we enable/disable these devices? How?
+	if (devices & VIA_6C)
+	if (devices & VIA_93)
+	*/
+	if (devices & VIA_96)
+		set_96_state(state);
+	if (devices & VIA_CRT)
+		set_crt_state(state);
+	if (devices & VIA_DVP1)
+		set_dvp1_state(state);
+	if (devices & VIA_LVDS1)
+		set_lvds1_state(state);
+	if (devices & VIA_LVDS2)
+		set_lvds2_state(state);
+}
+
 u32 via_parse_odev(char *input, char **end)
 {
 	char *ptr = input;
@@ -2224,6 +2339,8 @@ int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp,
 {
 	int i, j;
 	int port;
+	u32 devices = viaparinfo->shared->iga1_devices
+		| viaparinfo->shared->iga2_devices;
 	u8 value, index, mask;
 	struct crt_mode_table *crt_timing;
 	struct crt_mode_table *crt_timing1 = NULL;
@@ -2271,6 +2388,7 @@ int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp,
 	}
 
 	device_off();
+	via_set_state(devices, VIA_STATE_OFF);
 
 	/* Fill VPIT Parameters */
 	/* Write Misc Register */
@@ -2430,6 +2548,7 @@ int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp,
 			viafb_DeviceStatus = CRT_Device;
 	}
 	device_on();
+	via_set_state(devices, VIA_STATE_ON);
 	device_screen_on();
 	return 1;
 }
@@ -2470,31 +2589,18 @@ int viafb_get_refresh(int hres, int vres, u32 long_refresh)
 
 static void device_off(void)
 {
-	viafb_crt_disable();
 	viafb_dvi_disable();
 	viafb_lcd_disable();
 }
 
 static void device_on(void)
 {
-	if (viafb_CRT_ON == 1)
-		viafb_crt_enable();
 	if (viafb_DVI_ON == 1)
 		viafb_dvi_enable();
 	if (viafb_LCD_ON == 1)
 		viafb_lcd_enable();
 }
 
-void viafb_crt_disable(void)
-{
-	viafb_write_reg_mask(CR36, VIACR, BIT5 + BIT4, BIT5 + BIT4);
-}
-
-void viafb_crt_enable(void)
-{
-	viafb_write_reg_mask(CR36, VIACR, 0x0, BIT5 + BIT4);
-}
-
 static void enable_second_display_channel(void)
 {
 	/* to enable second display channel. */
diff --git a/drivers/video/via/hw.h b/drivers/video/via/hw.h
index 657dbd6..b067cbb 100644
--- a/drivers/video/via/hw.h
+++ b/drivers/video/via/hw.h
@@ -41,6 +41,12 @@
 #define VIA_LVDS1	0x00000040
 #define VIA_LVDS2	0x00000080
 
+/* VIA output device power states */
+#define VIA_STATE_ON		0
+#define VIA_STATE_STANDBY	1
+#define VIA_STATE_SUSPEND	2
+#define VIA_STATE_OFF		3
+
 /***************************************************
 * Definition IGA1 Design Method of CRTC Registers *
 ****************************************************/
@@ -904,9 +910,8 @@ void viafb_set_vclock(u32 CLK, int set_iga);
 void viafb_load_reg(int timing_value, int viafb_load_reg_num,
 	struct io_register *reg,
 	      int io_type);
-void viafb_crt_disable(void);
-void viafb_crt_enable(void);
 void via_set_source(u32 devices, u8 iga);
+void via_set_state(u32 devices, u8 state);
 u32 via_parse_odev(char *input, char **end);
 void via_odev_to_seq(struct seq_file *m, u32 odev);
 void init_ad9389(void);
diff --git a/drivers/video/via/lcd.c b/drivers/video/via/lcd.c
index b7d5535..de19e47 100644
--- a/drivers/video/via/lcd.c
+++ b/drivers/video/via/lcd.c
@@ -703,9 +703,6 @@ static void integrated_lvds_disable(struct lvds_setting_information
 		viafb_write_reg_mask(CR91, VIACR, 0xC0, BIT6 + BIT7);
 	}
 
-	/* Turn DFP High/Low Pad off. */
-	viafb_write_reg_mask(SR2A, VIASR, 0, BIT0 + BIT1 + BIT2 + BIT3);
-
 	/* Power off LVDS channel. */
 	switch (plvds_chip_info->output_interface) {
 	case INTERFACE_LVDS0:
@@ -761,9 +758,6 @@ static void integrated_lvds_enable(struct lvds_setting_information
 		break;
 	}
 
-	/* Turn DFP High/Low pad on. */
-	viafb_write_reg_mask(SR2A, VIASR, 0x0F, BIT0 + BIT1 + BIT2 + BIT3);
-
 	/* Power on LVDS channel. */
 	switch (plvds_chip_info->output_interface) {
 	case INTERFACE_LVDS0:
@@ -812,8 +806,6 @@ void viafb_lcd_disable(void)
 		viafb_disable_lvds_vt1636(viaparinfo->lvds_setting_info,
 				    &viaparinfo->chip_info->lvds_chip_info);
 	} else {
-		/* DFP-HL pad off          */
-		viafb_write_reg_mask(SR2A, VIASR, 0x00, 0x0F);
 		/* Backlight off           */
 		viafb_write_reg_mask(SR3D, VIASR, 0x00, 0x20);
 		/* 24 bit DI data paht off */
@@ -879,8 +871,6 @@ void viafb_lcd_enable(void)
 		viafb_enable_lvds_vt1636(viaparinfo->lvds_setting_info,
 				   &viaparinfo->chip_info->lvds_chip_info);
 	} else {
-		/* DFP-HL pad on           */
-		viafb_write_reg_mask(SR2A, VIASR, 0x0F, 0x0F);
 		/* Backlight on            */
 		viafb_write_reg_mask(SR3D, VIASR, 0x20, 0x20);
 		/* 24 bit DI data paht on  */
diff --git a/drivers/video/via/viafbdev.c b/drivers/video/via/viafbdev.c
index 5864092..ce6f13a 100644
--- a/drivers/video/via/viafbdev.c
+++ b/drivers/video/via/viafbdev.c
@@ -332,22 +332,22 @@ static int viafb_blank(int blank_mode, struct fb_info *info)
 	case FB_BLANK_UNBLANK:
 		/* Screen: On, HSync: On, VSync: On */
 		/* control CRT monitor power management */
-		viafb_write_reg_mask(CR36, VIACR, 0x00, BIT4 + BIT5);
+		via_set_state(VIA_CRT, VIA_STATE_ON);
 		break;
 	case FB_BLANK_HSYNC_SUSPEND:
 		/* Screen: Off, HSync: Off, VSync: On */
 		/* control CRT monitor power management */
-		viafb_write_reg_mask(CR36, VIACR, 0x10, BIT4 + BIT5);
+		via_set_state(VIA_CRT, VIA_STATE_STANDBY);
 		break;
 	case FB_BLANK_VSYNC_SUSPEND:
 		/* Screen: Off, HSync: On, VSync: Off */
 		/* control CRT monitor power management */
-		viafb_write_reg_mask(CR36, VIACR, 0x20, BIT4 + BIT5);
+		via_set_state(VIA_CRT, VIA_STATE_SUSPEND);
 		break;
 	case FB_BLANK_POWERDOWN:
 		/* Screen: Off, HSync: Off, VSync: Off */
 		/* control CRT monitor power management */
-		viafb_write_reg_mask(CR36, VIACR, 0x30, BIT4 + BIT5);
+		via_set_state(VIA_CRT, VIA_STATE_OFF);
 		break;
 	}
 
@@ -457,7 +457,7 @@ static int viafb_ioctl(struct fb_info *info, u_int cmd, u_long arg)
 		if (copy_from_user(&gpu32, argp, sizeof(gpu32)))
 			return -EFAULT;
 		if (gpu32 & CRT_Device)
-			viafb_crt_enable();
+			via_set_state(VIA_CRT, VIA_STATE_ON);
 		if (gpu32 & DVI_Device)
 			viafb_dvi_enable();
 		if (gpu32 & LCD_Device)
@@ -467,7 +467,7 @@ static int viafb_ioctl(struct fb_info *info, u_int cmd, u_long arg)
 		if (copy_from_user(&gpu32, argp, sizeof(gpu32)))
 			return -EFAULT;
 		if (gpu32 & CRT_Device)
-			viafb_crt_disable();
+			via_set_state(VIA_CRT, VIA_STATE_OFF);
 		if (gpu32 & DVI_Device)
 			viafb_dvi_disable();
 		if (gpu32 & LCD_Device)
@@ -1487,7 +1487,9 @@ static ssize_t viafb_iga1_odev_proc_write(struct file *file,
 	dev_on = dev_new & ~dev_old;
 	viaparinfo->shared->iga1_devices = dev_new;
 	viaparinfo->shared->iga2_devices &= ~dev_new;
+	via_set_state(dev_off, VIA_STATE_OFF);
 	via_set_source(dev_new, IGA1);
+	via_set_state(dev_on, VIA_STATE_ON);
 	return res;
 }
 
@@ -1525,7 +1527,9 @@ static ssize_t viafb_iga2_odev_proc_write(struct file *file,
 	dev_on = dev_new & ~dev_old;
 	viaparinfo->shared->iga2_devices = dev_new;
 	viaparinfo->shared->iga1_devices &= ~dev_new;
+	via_set_state(dev_off, VIA_STATE_OFF);
 	via_set_source(dev_new, IGA2);
+	via_set_state(dev_on, VIA_STATE_ON);
 	return res;
 }
 
diff --git a/drivers/video/via/vt1636.c b/drivers/video/via/vt1636.c
index d65bf1a..90aad12 100644
--- a/drivers/video/via/vt1636.c
+++ b/drivers/video/via/vt1636.c
@@ -92,34 +92,6 @@ void viafb_enable_lvds_vt1636(struct lvds_setting_information
 
 	viafb_gpio_i2c_write_mask_lvds(plvds_setting_info, plvds_chip_info,
 				 VDD_ON_TBL_VT1636[0]);
-
-	/* Pad on: */
-	switch (plvds_chip_info->output_interface) {
-	case INTERFACE_DVP0:
-		{
-			viafb_write_reg_mask(SR1E, VIASR, 0xC0, 0xC0);
-			break;
-		}
-
-	case INTERFACE_DVP1:
-		{
-			viafb_write_reg_mask(SR1E, VIASR, 0x30, 0x30);
-			break;
-		}
-
-	case INTERFACE_DFP_LOW:
-		{
-			viafb_write_reg_mask(SR2A, VIASR, 0x03, 0x03);
-			break;
-		}
-
-	case INTERFACE_DFP_HIGH:
-		{
-			viafb_write_reg_mask(SR2A, VIASR, 0x03, 0x0C);
-			break;
-		}
-
-	}
 }
 
 void viafb_disable_lvds_vt1636(struct lvds_setting_information
@@ -129,34 +101,6 @@ void viafb_disable_lvds_vt1636(struct lvds_setting_information
 
 	viafb_gpio_i2c_write_mask_lvds(plvds_setting_info, plvds_chip_info,
 				 VDD_OFF_TBL_VT1636[0]);
-
-	/* Pad off: */
-	switch (plvds_chip_info->output_interface) {
-	case INTERFACE_DVP0:
-		{
-			viafb_write_reg_mask(SR1E, VIASR, 0x00, 0xC0);
-			break;
-		}
-
-	case INTERFACE_DVP1:
-		{
-			viafb_write_reg_mask(SR1E, VIASR, 0x00, 0x30);
-			break;
-		}
-
-	case INTERFACE_DFP_LOW:
-		{
-			viafb_write_reg_mask(SR2A, VIASR, 0x00, 0x03);
-			break;
-		}
-
-	case INTERFACE_DFP_HIGH:
-		{
-			viafb_write_reg_mask(SR2A, VIASR, 0x00, 0x0C);
-			break;
-		}
-
-	}
 }
 
 bool viafb_lvds_identify_vt1636(u8 i2c_adapter)
-- 
1.6.3.2


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH 03/12] viafb: introduce per output device power management
@ 2010-09-19  7:26   ` Florian Tobias Schandinat
  0 siblings, 0 replies; 27+ messages in thread
From: Florian Tobias Schandinat @ 2010-09-19  7:26 UTC (permalink / raw)
  To: linux-fbdev; +Cc: linux-kernel, Florian Tobias Schandinat, Joseph Chan

viafb: introduce per output device power management

This patch moves common parts of dvi.c, lcd.c and vt1636.c to hw.c to
start a per output device power management. There should be no runtime
changes aside that this patch enables the proc interface to enable/disable
devices when needed which greatly increases the chances that changes to
the output device configuration will work. However the power management is
not yet complete so it might fail on some configurations. As this area is
quite complex and touches undocumented things there is a slight chance of
regressions.

Signed-off-by: Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
Cc: Joseph Chan <JosephChan@via.com.tw>
---
 drivers/video/via/dvi.c      |   25 +--------
 drivers/video/via/hw.c       |  132 +++++++++++++++++++++++++++++++++++++----
 drivers/video/via/hw.h       |    9 ++-
 drivers/video/via/lcd.c      |   10 ---
 drivers/video/via/viafbdev.c |   16 +++--
 drivers/video/via/vt1636.c   |   56 ------------------
 6 files changed, 137 insertions(+), 111 deletions(-)

diff --git a/drivers/video/via/dvi.c b/drivers/video/via/dvi.c
index 7c82f6f..84e21b3 100644
--- a/drivers/video/via/dvi.c
+++ b/drivers/video/via/dvi.c
@@ -470,26 +470,6 @@ static void __devinit dvi_get_panel_size_from_DDCv2(
 void viafb_dvi_disable(void)
 {
 	if (viaparinfo->chip_info->
-		tmds_chip_info.output_interface = INTERFACE_DVP0)
-		viafb_write_reg(SR1E, VIASR,
-		viafb_read_reg(VIASR, SR1E) & (~0xC0));
-
-	if (viaparinfo->chip_info->
-		tmds_chip_info.output_interface = INTERFACE_DVP1)
-		viafb_write_reg(SR1E, VIASR,
-		viafb_read_reg(VIASR, SR1E) & (~0x30));
-
-	if (viaparinfo->chip_info->
-		tmds_chip_info.output_interface = INTERFACE_DFP_HIGH)
-		viafb_write_reg(SR2A, VIASR,
-		viafb_read_reg(VIASR, SR2A) & (~0x0C));
-
-	if (viaparinfo->chip_info->
-		tmds_chip_info.output_interface = INTERFACE_DFP_LOW)
-		viafb_write_reg(SR2A, VIASR,
-		viafb_read_reg(VIASR, SR2A) & (~0x03));
-
-	if (viaparinfo->chip_info->
 		tmds_chip_info.output_interface = INTERFACE_TMDS)
 		/* Turn off TMDS power. */
 		viafb_write_reg(CRD2, VIACR,
@@ -571,7 +551,6 @@ void viafb_dvi_enable(void)
 	case INTERFACE_DVP0:
 		viafb_write_reg_mask(CR6B, VIACR, 0x01, BIT0);
 		viafb_write_reg_mask(CR6C, VIACR, 0x21, BIT0 + BIT5);
-		viafb_write_reg_mask(SR1E, VIASR, 0xC0, BIT7 + BIT6);
 		dvi_patch_skew_dvp0();
 		if (viaparinfo->chip_info->gfx_chip_name = UNICHROME_CLE266)
 			tmds_register_write(0x88, 0x3b);
@@ -585,7 +564,6 @@ void viafb_dvi_enable(void)
 		if (viaparinfo->chip_info->gfx_chip_name = UNICHROME_CLE266)
 			viafb_write_reg_mask(CR93, VIACR, 0x21, BIT0 + BIT5);
 
-		viafb_write_reg_mask(SR1E, VIASR, 0x30, BIT4 + BIT5);
 		/*fix dvi cann't be enabled with MB VT5718C4 - Al Zhang */
 		if (viaparinfo->chip_info->gfx_chip_name = UNICHROME_CLE266)
 			tmds_register_write(0x88, 0x3b);
@@ -616,14 +594,13 @@ void viafb_dvi_enable(void)
 		if (viaparinfo->chip_info->gfx_chip_name != UNICHROME_CLE266)
 			via_write_reg_mask(VIACR, CR97, 0x03, 0x03);
 
-		viafb_write_reg_mask(SR2A, VIASR, 0x0C, BIT2 + BIT3);
 		via_write_reg_mask(VIACR, 0x91, 0x00, 0x20);
 		break;
 
 	case INTERFACE_DFP_LOW:
 		if (viaparinfo->chip_info->gfx_chip_name = UNICHROME_CLE266)
 			break;
-		viafb_write_reg_mask(SR2A, VIASR, 0x03, BIT0 + BIT1);
+
 		dvi_patch_skew_dvp_low();
 		via_write_reg_mask(VIACR, 0x91, 0x00, 0x20);
 		break;
diff --git a/drivers/video/via/hw.c b/drivers/video/via/hw.c
index e65edce..132d811 100644
--- a/drivers/video/via/hw.c
+++ b/drivers/video/via/hw.c
@@ -1036,6 +1036,121 @@ void via_set_source(u32 devices, u8 iga)
 		set_lvds2_source(iga);
 }
 
+static void set_crt_state(u8 state)
+{
+	u8 value;
+
+	switch (state) {
+	case VIA_STATE_ON:
+		value = 0x00;
+		break;
+	case VIA_STATE_STANDBY:
+		value = 0x10;
+		break;
+	case VIA_STATE_SUSPEND:
+		value = 0x20;
+		break;
+	case VIA_STATE_OFF:
+		value = 0x30;
+		break;
+	default:
+		return;
+	}
+
+	via_write_reg_mask(VIACR, 0x36, value, 0x30);
+}
+
+static void set_96_state(u8 state)
+{
+	u8 value;
+
+	switch (state) {
+	case VIA_STATE_ON:
+		value = 0xC0;
+		break;
+	case VIA_STATE_OFF:
+		value = 0x00;
+		break;
+	default:
+		return;
+	}
+
+	via_write_reg_mask(VIASR, 0x1E, value, 0xC0);
+}
+
+static void set_dvp1_state(u8 state)
+{
+	u8 value;
+
+	switch (state) {
+	case VIA_STATE_ON:
+		value = 0x30;
+		break;
+	case VIA_STATE_OFF:
+		value = 0x00;
+		break;
+	default:
+		return;
+	}
+
+	via_write_reg_mask(VIASR, 0x1E, value, 0x30);
+}
+
+static void set_lvds1_state(u8 state)
+{
+	u8 value;
+
+	switch (state) {
+	case VIA_STATE_ON:
+		value = 0x03;
+		break;
+	case VIA_STATE_OFF:
+		value = 0x00;
+		break;
+	default:
+		return;
+	}
+
+	via_write_reg_mask(VIASR, 0x2A, value, 0x03);
+}
+
+static void set_lvds2_state(u8 state)
+{
+	u8 value;
+
+	switch (state) {
+	case VIA_STATE_ON:
+		value = 0x0C;
+		break;
+	case VIA_STATE_OFF:
+		value = 0x00;
+		break;
+	default:
+		return;
+	}
+
+	via_write_reg_mask(VIASR, 0x2A, value, 0x0C);
+}
+
+void via_set_state(u32 devices, u8 state)
+{
+	/*
+	TODO: Can we enable/disable these devices? How?
+	if (devices & VIA_6C)
+	if (devices & VIA_93)
+	*/
+	if (devices & VIA_96)
+		set_96_state(state);
+	if (devices & VIA_CRT)
+		set_crt_state(state);
+	if (devices & VIA_DVP1)
+		set_dvp1_state(state);
+	if (devices & VIA_LVDS1)
+		set_lvds1_state(state);
+	if (devices & VIA_LVDS2)
+		set_lvds2_state(state);
+}
+
 u32 via_parse_odev(char *input, char **end)
 {
 	char *ptr = input;
@@ -2224,6 +2339,8 @@ int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp,
 {
 	int i, j;
 	int port;
+	u32 devices = viaparinfo->shared->iga1_devices
+		| viaparinfo->shared->iga2_devices;
 	u8 value, index, mask;
 	struct crt_mode_table *crt_timing;
 	struct crt_mode_table *crt_timing1 = NULL;
@@ -2271,6 +2388,7 @@ int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp,
 	}
 
 	device_off();
+	via_set_state(devices, VIA_STATE_OFF);
 
 	/* Fill VPIT Parameters */
 	/* Write Misc Register */
@@ -2430,6 +2548,7 @@ int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp,
 			viafb_DeviceStatus = CRT_Device;
 	}
 	device_on();
+	via_set_state(devices, VIA_STATE_ON);
 	device_screen_on();
 	return 1;
 }
@@ -2470,31 +2589,18 @@ int viafb_get_refresh(int hres, int vres, u32 long_refresh)
 
 static void device_off(void)
 {
-	viafb_crt_disable();
 	viafb_dvi_disable();
 	viafb_lcd_disable();
 }
 
 static void device_on(void)
 {
-	if (viafb_CRT_ON = 1)
-		viafb_crt_enable();
 	if (viafb_DVI_ON = 1)
 		viafb_dvi_enable();
 	if (viafb_LCD_ON = 1)
 		viafb_lcd_enable();
 }
 
-void viafb_crt_disable(void)
-{
-	viafb_write_reg_mask(CR36, VIACR, BIT5 + BIT4, BIT5 + BIT4);
-}
-
-void viafb_crt_enable(void)
-{
-	viafb_write_reg_mask(CR36, VIACR, 0x0, BIT5 + BIT4);
-}
-
 static void enable_second_display_channel(void)
 {
 	/* to enable second display channel. */
diff --git a/drivers/video/via/hw.h b/drivers/video/via/hw.h
index 657dbd6..b067cbb 100644
--- a/drivers/video/via/hw.h
+++ b/drivers/video/via/hw.h
@@ -41,6 +41,12 @@
 #define VIA_LVDS1	0x00000040
 #define VIA_LVDS2	0x00000080
 
+/* VIA output device power states */
+#define VIA_STATE_ON		0
+#define VIA_STATE_STANDBY	1
+#define VIA_STATE_SUSPEND	2
+#define VIA_STATE_OFF		3
+
 /***************************************************
 * Definition IGA1 Design Method of CRTC Registers *
 ****************************************************/
@@ -904,9 +910,8 @@ void viafb_set_vclock(u32 CLK, int set_iga);
 void viafb_load_reg(int timing_value, int viafb_load_reg_num,
 	struct io_register *reg,
 	      int io_type);
-void viafb_crt_disable(void);
-void viafb_crt_enable(void);
 void via_set_source(u32 devices, u8 iga);
+void via_set_state(u32 devices, u8 state);
 u32 via_parse_odev(char *input, char **end);
 void via_odev_to_seq(struct seq_file *m, u32 odev);
 void init_ad9389(void);
diff --git a/drivers/video/via/lcd.c b/drivers/video/via/lcd.c
index b7d5535..de19e47 100644
--- a/drivers/video/via/lcd.c
+++ b/drivers/video/via/lcd.c
@@ -703,9 +703,6 @@ static void integrated_lvds_disable(struct lvds_setting_information
 		viafb_write_reg_mask(CR91, VIACR, 0xC0, BIT6 + BIT7);
 	}
 
-	/* Turn DFP High/Low Pad off. */
-	viafb_write_reg_mask(SR2A, VIASR, 0, BIT0 + BIT1 + BIT2 + BIT3);
-
 	/* Power off LVDS channel. */
 	switch (plvds_chip_info->output_interface) {
 	case INTERFACE_LVDS0:
@@ -761,9 +758,6 @@ static void integrated_lvds_enable(struct lvds_setting_information
 		break;
 	}
 
-	/* Turn DFP High/Low pad on. */
-	viafb_write_reg_mask(SR2A, VIASR, 0x0F, BIT0 + BIT1 + BIT2 + BIT3);
-
 	/* Power on LVDS channel. */
 	switch (plvds_chip_info->output_interface) {
 	case INTERFACE_LVDS0:
@@ -812,8 +806,6 @@ void viafb_lcd_disable(void)
 		viafb_disable_lvds_vt1636(viaparinfo->lvds_setting_info,
 				    &viaparinfo->chip_info->lvds_chip_info);
 	} else {
-		/* DFP-HL pad off          */
-		viafb_write_reg_mask(SR2A, VIASR, 0x00, 0x0F);
 		/* Backlight off           */
 		viafb_write_reg_mask(SR3D, VIASR, 0x00, 0x20);
 		/* 24 bit DI data paht off */
@@ -879,8 +871,6 @@ void viafb_lcd_enable(void)
 		viafb_enable_lvds_vt1636(viaparinfo->lvds_setting_info,
 				   &viaparinfo->chip_info->lvds_chip_info);
 	} else {
-		/* DFP-HL pad on           */
-		viafb_write_reg_mask(SR2A, VIASR, 0x0F, 0x0F);
 		/* Backlight on            */
 		viafb_write_reg_mask(SR3D, VIASR, 0x20, 0x20);
 		/* 24 bit DI data paht on  */
diff --git a/drivers/video/via/viafbdev.c b/drivers/video/via/viafbdev.c
index 5864092..ce6f13a 100644
--- a/drivers/video/via/viafbdev.c
+++ b/drivers/video/via/viafbdev.c
@@ -332,22 +332,22 @@ static int viafb_blank(int blank_mode, struct fb_info *info)
 	case FB_BLANK_UNBLANK:
 		/* Screen: On, HSync: On, VSync: On */
 		/* control CRT monitor power management */
-		viafb_write_reg_mask(CR36, VIACR, 0x00, BIT4 + BIT5);
+		via_set_state(VIA_CRT, VIA_STATE_ON);
 		break;
 	case FB_BLANK_HSYNC_SUSPEND:
 		/* Screen: Off, HSync: Off, VSync: On */
 		/* control CRT monitor power management */
-		viafb_write_reg_mask(CR36, VIACR, 0x10, BIT4 + BIT5);
+		via_set_state(VIA_CRT, VIA_STATE_STANDBY);
 		break;
 	case FB_BLANK_VSYNC_SUSPEND:
 		/* Screen: Off, HSync: On, VSync: Off */
 		/* control CRT monitor power management */
-		viafb_write_reg_mask(CR36, VIACR, 0x20, BIT4 + BIT5);
+		via_set_state(VIA_CRT, VIA_STATE_SUSPEND);
 		break;
 	case FB_BLANK_POWERDOWN:
 		/* Screen: Off, HSync: Off, VSync: Off */
 		/* control CRT monitor power management */
-		viafb_write_reg_mask(CR36, VIACR, 0x30, BIT4 + BIT5);
+		via_set_state(VIA_CRT, VIA_STATE_OFF);
 		break;
 	}
 
@@ -457,7 +457,7 @@ static int viafb_ioctl(struct fb_info *info, u_int cmd, u_long arg)
 		if (copy_from_user(&gpu32, argp, sizeof(gpu32)))
 			return -EFAULT;
 		if (gpu32 & CRT_Device)
-			viafb_crt_enable();
+			via_set_state(VIA_CRT, VIA_STATE_ON);
 		if (gpu32 & DVI_Device)
 			viafb_dvi_enable();
 		if (gpu32 & LCD_Device)
@@ -467,7 +467,7 @@ static int viafb_ioctl(struct fb_info *info, u_int cmd, u_long arg)
 		if (copy_from_user(&gpu32, argp, sizeof(gpu32)))
 			return -EFAULT;
 		if (gpu32 & CRT_Device)
-			viafb_crt_disable();
+			via_set_state(VIA_CRT, VIA_STATE_OFF);
 		if (gpu32 & DVI_Device)
 			viafb_dvi_disable();
 		if (gpu32 & LCD_Device)
@@ -1487,7 +1487,9 @@ static ssize_t viafb_iga1_odev_proc_write(struct file *file,
 	dev_on = dev_new & ~dev_old;
 	viaparinfo->shared->iga1_devices = dev_new;
 	viaparinfo->shared->iga2_devices &= ~dev_new;
+	via_set_state(dev_off, VIA_STATE_OFF);
 	via_set_source(dev_new, IGA1);
+	via_set_state(dev_on, VIA_STATE_ON);
 	return res;
 }
 
@@ -1525,7 +1527,9 @@ static ssize_t viafb_iga2_odev_proc_write(struct file *file,
 	dev_on = dev_new & ~dev_old;
 	viaparinfo->shared->iga2_devices = dev_new;
 	viaparinfo->shared->iga1_devices &= ~dev_new;
+	via_set_state(dev_off, VIA_STATE_OFF);
 	via_set_source(dev_new, IGA2);
+	via_set_state(dev_on, VIA_STATE_ON);
 	return res;
 }
 
diff --git a/drivers/video/via/vt1636.c b/drivers/video/via/vt1636.c
index d65bf1a..90aad12 100644
--- a/drivers/video/via/vt1636.c
+++ b/drivers/video/via/vt1636.c
@@ -92,34 +92,6 @@ void viafb_enable_lvds_vt1636(struct lvds_setting_information
 
 	viafb_gpio_i2c_write_mask_lvds(plvds_setting_info, plvds_chip_info,
 				 VDD_ON_TBL_VT1636[0]);
-
-	/* Pad on: */
-	switch (plvds_chip_info->output_interface) {
-	case INTERFACE_DVP0:
-		{
-			viafb_write_reg_mask(SR1E, VIASR, 0xC0, 0xC0);
-			break;
-		}
-
-	case INTERFACE_DVP1:
-		{
-			viafb_write_reg_mask(SR1E, VIASR, 0x30, 0x30);
-			break;
-		}
-
-	case INTERFACE_DFP_LOW:
-		{
-			viafb_write_reg_mask(SR2A, VIASR, 0x03, 0x03);
-			break;
-		}
-
-	case INTERFACE_DFP_HIGH:
-		{
-			viafb_write_reg_mask(SR2A, VIASR, 0x03, 0x0C);
-			break;
-		}
-
-	}
 }
 
 void viafb_disable_lvds_vt1636(struct lvds_setting_information
@@ -129,34 +101,6 @@ void viafb_disable_lvds_vt1636(struct lvds_setting_information
 
 	viafb_gpio_i2c_write_mask_lvds(plvds_setting_info, plvds_chip_info,
 				 VDD_OFF_TBL_VT1636[0]);
-
-	/* Pad off: */
-	switch (plvds_chip_info->output_interface) {
-	case INTERFACE_DVP0:
-		{
-			viafb_write_reg_mask(SR1E, VIASR, 0x00, 0xC0);
-			break;
-		}
-
-	case INTERFACE_DVP1:
-		{
-			viafb_write_reg_mask(SR1E, VIASR, 0x00, 0x30);
-			break;
-		}
-
-	case INTERFACE_DFP_LOW:
-		{
-			viafb_write_reg_mask(SR2A, VIASR, 0x00, 0x03);
-			break;
-		}
-
-	case INTERFACE_DFP_HIGH:
-		{
-			viafb_write_reg_mask(SR2A, VIASR, 0x00, 0x0C);
-			break;
-		}
-
-	}
 }
 
 bool viafb_lvds_identify_vt1636(u8 i2c_adapter)
-- 
1.6.3.2


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH 04/12] viafb: vt1636 cleanup
  2010-09-19  7:26 [PATCH 00/12] viafb output device rework - part 2 Florian Tobias Schandinat
                   ` (2 preceding siblings ...)
  2010-09-19  7:26   ` Florian Tobias Schandinat
@ 2010-09-19  7:26 ` Florian Tobias Schandinat
  2010-09-19  7:33   ` Florian Tobias Schandinat
                   ` (7 subsequent siblings)
  11 siblings, 0 replies; 27+ messages in thread
From: Florian Tobias Schandinat @ 2010-09-19  7:26 UTC (permalink / raw)
  To: linux-fbdev; +Cc: linux-kernel, Florian Tobias Schandinat, Joseph Chan

viafb: vt1636 cleanup

This patch merges tbl1636 into vt1636 and cleans it up as the data was
only used there anyway. No runtime changes are expected.

Signed-off-by: Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
Cc: Joseph Chan <JosephChan@via.com.tw>
---
 drivers/video/via/Makefile  |    2 +-
 drivers/video/via/global.h  |    1 -
 drivers/video/via/tbl1636.c |   71 -------------------------------------------
 drivers/video/via/tbl1636.h |   34 --------------------
 drivers/video/via/vt1636.c  |   65 +++++++++++++++++++++++++--------------
 5 files changed, 42 insertions(+), 131 deletions(-)
 delete mode 100644 drivers/video/via/tbl1636.c
 delete mode 100644 drivers/video/via/tbl1636.h

diff --git a/drivers/video/via/Makefile b/drivers/video/via/Makefile
index d496adb..96f01ee 100644
--- a/drivers/video/via/Makefile
+++ b/drivers/video/via/Makefile
@@ -5,5 +5,5 @@
 obj-$(CONFIG_FB_VIA) += viafb.o
 
 viafb-y	:=viafbdev.o hw.o via_i2c.o dvi.o lcd.o ioctl.o accel.o \
-	via_utility.o vt1636.o global.o tblDPASetting.o viamode.o tbl1636.o \
+	via_utility.o vt1636.o global.o tblDPASetting.o viamode.o \
 	via-core.o via-gpio.o via_modesetting.o
diff --git a/drivers/video/via/global.h b/drivers/video/via/global.h
index 28221a0..38ef5ac 100644
--- a/drivers/video/via/global.h
+++ b/drivers/video/via/global.h
@@ -48,7 +48,6 @@
 #include "via_utility.h"
 #include "vt1636.h"
 #include "tblDPASetting.h"
-#include "tbl1636.h"
 
 /* External struct*/
 
diff --git a/drivers/video/via/tbl1636.c b/drivers/video/via/tbl1636.c
deleted file mode 100644
index 2d84534..0000000
--- a/drivers/video/via/tbl1636.c
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
- * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
-
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public
- * License as published by the Free Software Foundation;
- * either version 2, or (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
- * the implied warranty of MERCHANTABILITY or FITNESS FOR
- * A PARTICULAR PURPOSE.See the GNU General Public License
- * for more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#include "global.h"
-struct IODATA COMMON_INIT_TBL_VT1636[] = {
-/*  Index, Mask, Value */
-	/* Set panel power sequence timing */
-	{0x10, 0xC0, 0x00},
-	/* T1: VDD on - Data on. Each increment is 1 ms. (50ms = 031h) */
-	{0x0B, 0xFF, 0x40},
-	/* T2: Data on - Backlight on. Each increment is 2 ms. (210ms = 068h) */
-	{0x0C, 0xFF, 0x31},
-	/* T3: Backlight off -Data off. Each increment is 2 ms. (210ms = 068h)*/
-	{0x0D, 0xFF, 0x31},
-	/* T4: Data off - VDD off. Each increment is 1 ms. (50ms = 031h) */
-	{0x0E, 0xFF, 0x68},
-	/* T5: VDD off - VDD on. Each increment is 100 ms. (500ms = 04h) */
-	{0x0F, 0xFF, 0x68},
-	/* LVDS output power up */
-	{0x09, 0xA0, 0xA0},
-	/* turn on back light */
-	{0x10, 0x33, 0x13}
-};
-
-struct IODATA DUAL_CHANNEL_ENABLE_TBL_VT1636[] = {
-/*  Index, Mask, Value */
-	{0x08, 0xF0, 0xE0}	/* Input Data Mode Select */
-};
-
-struct IODATA SINGLE_CHANNEL_ENABLE_TBL_VT1636[] = {
-/*  Index, Mask, Value */
-	{0x08, 0xF0, 0x00}	/* Input Data Mode Select */
-};
-
-struct IODATA DITHERING_ENABLE_TBL_VT1636[] = {
-/*  Index, Mask, Value */
-	{0x0A, 0x70, 0x50}
-};
-
-struct IODATA DITHERING_DISABLE_TBL_VT1636[] = {
-/*  Index, Mask, Value */
-	{0x0A, 0x70, 0x00}
-};
-
-struct IODATA VDD_ON_TBL_VT1636[] = {
-/*  Index, Mask, Value */
-	{0x10, 0x20, 0x20}
-};
-
-struct IODATA VDD_OFF_TBL_VT1636[] = {
-/*  Index, Mask, Value */
-	{0x10, 0x20, 0x00}
-};
diff --git a/drivers/video/via/tbl1636.h b/drivers/video/via/tbl1636.h
deleted file mode 100644
index d906055..0000000
--- a/drivers/video/via/tbl1636.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
- * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
-
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public
- * License as published by the Free Software Foundation;
- * either version 2, or (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
- * the implied warranty of MERCHANTABILITY or FITNESS FOR
- * A PARTICULAR PURPOSE.See the GNU General Public License
- * for more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#ifndef _TBL1636_H_
-#define _TBL1636_H_
-#include "hw.h"
-
-extern struct IODATA COMMON_INIT_TBL_VT1636[8];
-extern struct IODATA DUAL_CHANNEL_ENABLE_TBL_VT1636[1];
-extern struct IODATA SINGLE_CHANNEL_ENABLE_TBL_VT1636[1];
-extern struct IODATA DITHERING_ENABLE_TBL_VT1636[1];
-extern struct IODATA DITHERING_DISABLE_TBL_VT1636[1];
-extern struct IODATA VDD_ON_TBL_VT1636[1];
-extern struct IODATA VDD_OFF_TBL_VT1636[1];
-
-#endif /* _VIA_TBL1636_H_ */
diff --git a/drivers/video/via/vt1636.c b/drivers/video/via/vt1636.c
index 90aad12..60e4192 100644
--- a/drivers/video/via/vt1636.c
+++ b/drivers/video/via/vt1636.c
@@ -23,6 +23,34 @@
 #include <linux/via_i2c.h>
 #include "global.h"
 
+static const struct IODATA common_init_data[] = {
+/*  Index, Mask, Value */
+	/* Set panel power sequence timing */
+	{0x10, 0xC0, 0x00},
+	/* T1: VDD on - Data on. Each increment is 1 ms. (50ms = 031h) */
+	{0x0B, 0xFF, 0x40},
+	/* T2: Data on - Backlight on. Each increment is 2 ms. (210ms = 068h) */
+	{0x0C, 0xFF, 0x31},
+	/* T3: Backlight off -Data off. Each increment is 2 ms. (210ms = 068h)*/
+	{0x0D, 0xFF, 0x31},
+	/* T4: Data off - VDD off. Each increment is 1 ms. (50ms = 031h) */
+	{0x0E, 0xFF, 0x68},
+	/* T5: VDD off - VDD on. Each increment is 100 ms. (500ms = 04h) */
+	{0x0F, 0xFF, 0x68},
+	/* LVDS output power up */
+	{0x09, 0xA0, 0xA0},
+	/* turn on back light */
+	{0x10, 0x33, 0x13}
+};
+
+/* Index, Mask, Value */
+static const struct IODATA dual_channel_enable_data = {0x08, 0xF0, 0xE0};
+static const struct IODATA single_channel_enable_data = {0x08, 0xF0, 0x00};
+static const struct IODATA dithering_enable_data = {0x0A, 0x70, 0x50};
+static const struct IODATA dithering_disable_data = {0x0A, 0x70, 0x00};
+static const struct IODATA vdd_on_data = {0x10, 0x20, 0x20};
+static const struct IODATA vdd_off_data = {0x10, 0x20, 0x00};
+
 u8 viafb_gpio_i2c_read_lvds(struct lvds_setting_information
 	*plvds_setting_info, struct lvds_chip_information *plvds_chip_info,
 	u8 index)
@@ -55,52 +83,41 @@ void viafb_init_lvds_vt1636(struct lvds_setting_information
 	int reg_num, i;
 
 	/* Common settings: */
-	reg_num = ARRAY_SIZE(COMMON_INIT_TBL_VT1636);
-
-	for (i = 0; i < reg_num; i++) {
+	reg_num = ARRAY_SIZE(common_init_data);
+	for (i = 0; i < reg_num; i++)
 		viafb_gpio_i2c_write_mask_lvds(plvds_setting_info,
-					 plvds_chip_info,
-					 COMMON_INIT_TBL_VT1636[i]);
-	}
+			plvds_chip_info, common_init_data[i]);
 
 	/* Input Data Mode Select */
-	if (plvds_setting_info->device_lcd_dualedge) {
+	if (plvds_setting_info->device_lcd_dualedge)
 		viafb_gpio_i2c_write_mask_lvds(plvds_setting_info,
-					 plvds_chip_info,
-					 DUAL_CHANNEL_ENABLE_TBL_VT1636[0]);
-	} else {
+			plvds_chip_info, dual_channel_enable_data);
+	else
 		viafb_gpio_i2c_write_mask_lvds(plvds_setting_info,
-					 plvds_chip_info,
-					 SINGLE_CHANNEL_ENABLE_TBL_VT1636[0]);
-	}
+			plvds_chip_info, single_channel_enable_data);
 
-	if (plvds_setting_info->LCDDithering) {
+	if (plvds_setting_info->LCDDithering)
 		viafb_gpio_i2c_write_mask_lvds(plvds_setting_info,
-					 plvds_chip_info,
-					 DITHERING_ENABLE_TBL_VT1636[0]);
-	} else {
+			plvds_chip_info, dithering_enable_data);
+	else
 		viafb_gpio_i2c_write_mask_lvds(plvds_setting_info,
-					 plvds_chip_info,
-					 DITHERING_DISABLE_TBL_VT1636[0]);
-	}
+			plvds_chip_info, dithering_disable_data);
 }
 
 void viafb_enable_lvds_vt1636(struct lvds_setting_information
 			*plvds_setting_info,
 			struct lvds_chip_information *plvds_chip_info)
 {
-
 	viafb_gpio_i2c_write_mask_lvds(plvds_setting_info, plvds_chip_info,
-				 VDD_ON_TBL_VT1636[0]);
+		vdd_on_data);
 }
 
 void viafb_disable_lvds_vt1636(struct lvds_setting_information
 			 *plvds_setting_info,
 			 struct lvds_chip_information *plvds_chip_info)
 {
-
 	viafb_gpio_i2c_write_mask_lvds(plvds_setting_info, plvds_chip_info,
-				 VDD_OFF_TBL_VT1636[0]);
+		vdd_off_data);
 }
 
 bool viafb_lvds_identify_vt1636(u8 i2c_adapter)
-- 
1.6.3.2


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH 05/12] viafb: fix i2c_transfer error handling
  2010-09-19  7:26 [PATCH 00/12] viafb output device rework - part 2 Florian Tobias Schandinat
@ 2010-09-19  7:33   ` Florian Tobias Schandinat
  2010-09-19  7:26   ` Florian Tobias Schandinat
                     ` (10 subsequent siblings)
  11 siblings, 0 replies; 27+ messages in thread
From: Florian Tobias Schandinat @ 2010-09-19  7:33 UTC (permalink / raw)
  To: linux-fbdev
  Cc: linux-kernel, Florian Tobias Schandinat, Joseph Chan, Jonathan Corbet

viafb: fix i2c_transfer error handling

i2c_transfer returns negative errno on error and number of messages
processed on success. Just returning this value would give a poor
interface as it is not obvious that you must compare with 2 after reading
1 or n bytes and with 1 after writing 1 byte to determine if it was
successful. To avoid this error prone interface convert the error code
of a successful read/write to zero and all other non-negative values to
an negative error code.
This fixes a regression introduced by
	via: Rationalize vt1636 detection
which resulted in no longer detecting a VT1636 chip and therefore has
broken the output in configurations wich contain this chip.

Signed-off-by: Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
Cc: Joseph Chan <JosephChan@via.com.tw>
Cc: Jonathan Corbet <corbet@lwn.net>
---
 drivers/video/via/via_i2c.c |   27 ++++++++++++++++++++++++---
 1 files changed, 24 insertions(+), 3 deletions(-)

diff --git a/drivers/video/via/via_i2c.c b/drivers/video/via/via_i2c.c
index da9e4ca..021112e 100644
--- a/drivers/video/via/via_i2c.c
+++ b/drivers/video/via/via_i2c.c
@@ -114,6 +114,7 @@ static void via_i2c_setsda(void *data, int state)
 
 int viafb_i2c_readbyte(u8 adap, u8 slave_addr, u8 index, u8 *pdata)
 {
+	int ret;
 	u8 mm1[] = {0x00};
 	struct i2c_msg msgs[2];
 
@@ -126,11 +127,18 @@ int viafb_i2c_readbyte(u8 adap, u8 slave_addr, u8 index, u8 *pdata)
 	mm1[0] = index;
 	msgs[0].len = 1; msgs[1].len = 1;
 	msgs[0].buf = mm1; msgs[1].buf = pdata;
-	return i2c_transfer(&via_i2c_par[adap].adapter, msgs, 2);
+	ret = i2c_transfer(&via_i2c_par[adap].adapter, msgs, 2);
+	if (ret == 2)
+		ret = 0;
+	else if (ret >= 0)
+		ret = -EIO;
+
+	return ret;
 }
 
 int viafb_i2c_writebyte(u8 adap, u8 slave_addr, u8 index, u8 data)
 {
+	int ret;
 	u8 msg[2] = { index, data };
 	struct i2c_msg msgs;
 
@@ -140,11 +148,18 @@ int viafb_i2c_writebyte(u8 adap, u8 slave_addr, u8 index, u8 data)
 	msgs.addr = slave_addr / 2;
 	msgs.len = 2;
 	msgs.buf = msg;
-	return i2c_transfer(&via_i2c_par[adap].adapter, &msgs, 1);
+	ret = i2c_transfer(&via_i2c_par[adap].adapter, &msgs, 1);
+	if (ret == 1)
+		ret = 0;
+	else if (ret >= 0)
+		ret = -EIO;
+
+	return ret;
 }
 
 int viafb_i2c_readbytes(u8 adap, u8 slave_addr, u8 index, u8 *buff, int buff_len)
 {
+	int ret;
 	u8 mm1[] = {0x00};
 	struct i2c_msg msgs[2];
 
@@ -156,7 +171,13 @@ int viafb_i2c_readbytes(u8 adap, u8 slave_addr, u8 index, u8 *buff, int buff_len
 	mm1[0] = index;
 	msgs[0].len = 1; msgs[1].len = buff_len;
 	msgs[0].buf = mm1; msgs[1].buf = buff;
-	return i2c_transfer(&via_i2c_par[adap].adapter, msgs, 2);
+	ret = i2c_transfer(&via_i2c_par[adap].adapter, msgs, 2);
+	if (ret == 2)
+		ret = 0;
+	else if (ret >= 0)
+		ret = -EIO;
+
+	return ret;
 }
 
 /*
-- 
1.6.3.2


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH 05/12] viafb: fix i2c_transfer error handling
@ 2010-09-19  7:33   ` Florian Tobias Schandinat
  0 siblings, 0 replies; 27+ messages in thread
From: Florian Tobias Schandinat @ 2010-09-19  7:33 UTC (permalink / raw)
  To: linux-fbdev
  Cc: linux-kernel, Florian Tobias Schandinat, Joseph Chan, Jonathan Corbet

viafb: fix i2c_transfer error handling

i2c_transfer returns negative errno on error and number of messages
processed on success. Just returning this value would give a poor
interface as it is not obvious that you must compare with 2 after reading
1 or n bytes and with 1 after writing 1 byte to determine if it was
successful. To avoid this error prone interface convert the error code
of a successful read/write to zero and all other non-negative values to
an negative error code.
This fixes a regression introduced by
	via: Rationalize vt1636 detection
which resulted in no longer detecting a VT1636 chip and therefore has
broken the output in configurations wich contain this chip.

Signed-off-by: Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
Cc: Joseph Chan <JosephChan@via.com.tw>
Cc: Jonathan Corbet <corbet@lwn.net>
---
 drivers/video/via/via_i2c.c |   27 ++++++++++++++++++++++++---
 1 files changed, 24 insertions(+), 3 deletions(-)

diff --git a/drivers/video/via/via_i2c.c b/drivers/video/via/via_i2c.c
index da9e4ca..021112e 100644
--- a/drivers/video/via/via_i2c.c
+++ b/drivers/video/via/via_i2c.c
@@ -114,6 +114,7 @@ static void via_i2c_setsda(void *data, int state)
 
 int viafb_i2c_readbyte(u8 adap, u8 slave_addr, u8 index, u8 *pdata)
 {
+	int ret;
 	u8 mm1[] = {0x00};
 	struct i2c_msg msgs[2];
 
@@ -126,11 +127,18 @@ int viafb_i2c_readbyte(u8 adap, u8 slave_addr, u8 index, u8 *pdata)
 	mm1[0] = index;
 	msgs[0].len = 1; msgs[1].len = 1;
 	msgs[0].buf = mm1; msgs[1].buf = pdata;
-	return i2c_transfer(&via_i2c_par[adap].adapter, msgs, 2);
+	ret = i2c_transfer(&via_i2c_par[adap].adapter, msgs, 2);
+	if (ret = 2)
+		ret = 0;
+	else if (ret >= 0)
+		ret = -EIO;
+
+	return ret;
 }
 
 int viafb_i2c_writebyte(u8 adap, u8 slave_addr, u8 index, u8 data)
 {
+	int ret;
 	u8 msg[2] = { index, data };
 	struct i2c_msg msgs;
 
@@ -140,11 +148,18 @@ int viafb_i2c_writebyte(u8 adap, u8 slave_addr, u8 index, u8 data)
 	msgs.addr = slave_addr / 2;
 	msgs.len = 2;
 	msgs.buf = msg;
-	return i2c_transfer(&via_i2c_par[adap].adapter, &msgs, 1);
+	ret = i2c_transfer(&via_i2c_par[adap].adapter, &msgs, 1);
+	if (ret = 1)
+		ret = 0;
+	else if (ret >= 0)
+		ret = -EIO;
+
+	return ret;
 }
 
 int viafb_i2c_readbytes(u8 adap, u8 slave_addr, u8 index, u8 *buff, int buff_len)
 {
+	int ret;
 	u8 mm1[] = {0x00};
 	struct i2c_msg msgs[2];
 
@@ -156,7 +171,13 @@ int viafb_i2c_readbytes(u8 adap, u8 slave_addr, u8 index, u8 *buff, int buff_len
 	mm1[0] = index;
 	msgs[0].len = 1; msgs[1].len = buff_len;
 	msgs[0].buf = mm1; msgs[1].buf = buff;
-	return i2c_transfer(&via_i2c_par[adap].adapter, msgs, 2);
+	ret = i2c_transfer(&via_i2c_par[adap].adapter, msgs, 2);
+	if (ret = 2)
+		ret = 0;
+	else if (ret >= 0)
+		ret = -EIO;
+
+	return ret;
 }
 
 /*
-- 
1.6.3.2


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH 06/12] viafb: enable I2C for CRT
  2010-09-19  7:33   ` Florian Tobias Schandinat
@ 2010-09-19  7:33   ` Florian Tobias Schandinat
  -1 siblings, 0 replies; 27+ messages in thread
From: Florian Tobias Schandinat @ 2010-09-19  7:33 UTC (permalink / raw)
  To: linux-fbdev
  Cc: linux-kernel, Florian Tobias Schandinat, Joseph Chan, Jonathan Corbet

viafb: enable I2C for CRT

This patch enables the I2C port to talk with the CRT. This allows adding
EDID reading and parsing capability for CRTs.
Just a small preparation, no notable changes in user experience yet.

Signed-off-by: Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
Cc: Joseph Chan <JosephChan@via.com.tw>
Cc: Jonathan Corbet <corbet@lwn.net>
---
 drivers/video/via/via-core.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/video/via/via-core.c b/drivers/video/via/via-core.c
index 66f4030..69101ab 100644
--- a/drivers/video/via/via-core.c
+++ b/drivers/video/via/via-core.c
@@ -20,7 +20,7 @@
  * The default port config.
  */
 static struct via_port_cfg adap_configs[] = {
-	[VIA_PORT_26]	= { VIA_PORT_I2C,  VIA_MODE_OFF, VIASR, 0x26 },
+	[VIA_PORT_26]	= { VIA_PORT_I2C,  VIA_MODE_I2C, VIASR, 0x26 },
 	[VIA_PORT_31]	= { VIA_PORT_I2C,  VIA_MODE_I2C, VIASR, 0x31 },
 	[VIA_PORT_25]	= { VIA_PORT_GPIO, VIA_MODE_GPIO, VIASR, 0x25 },
 	[VIA_PORT_2C]	= { VIA_PORT_GPIO, VIA_MODE_I2C, VIASR, 0x2c },
-- 
1.6.3.2


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH 06/12] viafb: enable I2C for CRT
@ 2010-09-19  7:33   ` Florian Tobias Schandinat
  0 siblings, 0 replies; 27+ messages in thread
From: Florian Tobias Schandinat @ 2010-09-19  7:33 UTC (permalink / raw)
  To: linux-fbdev
  Cc: linux-kernel, Florian Tobias Schandinat, Joseph Chan, Jonathan Corbet

viafb: enable I2C for CRT

This patch enables the I2C port to talk with the CRT. This allows adding
EDID reading and parsing capability for CRTs.
Just a small preparation, no notable changes in user experience yet.

Signed-off-by: Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
Cc: Joseph Chan <JosephChan@via.com.tw>
Cc: Jonathan Corbet <corbet@lwn.net>
---
 drivers/video/via/via-core.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/video/via/via-core.c b/drivers/video/via/via-core.c
index 66f4030..69101ab 100644
--- a/drivers/video/via/via-core.c
+++ b/drivers/video/via/via-core.c
@@ -20,7 +20,7 @@
  * The default port config.
  */
 static struct via_port_cfg adap_configs[] = {
-	[VIA_PORT_26]	= { VIA_PORT_I2C,  VIA_MODE_OFF, VIASR, 0x26 },
+	[VIA_PORT_26]	= { VIA_PORT_I2C,  VIA_MODE_I2C, VIASR, 0x26 },
 	[VIA_PORT_31]	= { VIA_PORT_I2C,  VIA_MODE_I2C, VIASR, 0x31 },
 	[VIA_PORT_25]	= { VIA_PORT_GPIO, VIA_MODE_GPIO, VIASR, 0x25 },
 	[VIA_PORT_2C]	= { VIA_PORT_GPIO, VIA_MODE_I2C, VIASR, 0x2c },
-- 
1.6.3.2


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH 07/12] viafb: reduce I2C timeout and delay
  2010-09-19  7:33   ` Florian Tobias Schandinat
@ 2010-09-19  7:33   ` Florian Tobias Schandinat
  -1 siblings, 0 replies; 27+ messages in thread
From: Florian Tobias Schandinat @ 2010-09-19  7:33 UTC (permalink / raw)
  To: linux-fbdev
  Cc: linux-kernel, Florian Tobias Schandinat, Joseph Chan, Jonathan Corbet

viafb: reduce I2C timeout and delay

This patch reduces the value for I2C timeout and udelay.
The udelay was reduced to 10 (old: 40) which is still very high as for
standard-mode I2C even 5 should work. This gives a speedup of factor 4
when talking to I2C devices.
The timeout was reduced to 2 (old: 20) which is taken from the radeon
driver so it should work as well. This gives a speedup of factor 10 when
detecting that there is no I2C device we want to talk to.
This causes a huge improvement of device initialization time.

Signed-off-by: Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
Cc: Joseph Chan <JosephChan@via.com.tw>
Cc: Jonathan Corbet <corbet@lwn.net>
---
 drivers/video/via/via_i2c.c |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/video/via/via_i2c.c b/drivers/video/via/via_i2c.c
index 021112e..3844b55 100644
--- a/drivers/video/via/via_i2c.c
+++ b/drivers/video/via/via_i2c.c
@@ -202,8 +202,8 @@ static int create_i2c_bus(struct i2c_adapter *adapter,
 	algo->setscl = via_i2c_setscl;
 	algo->getsda = via_i2c_getsda;
 	algo->getscl = via_i2c_getscl;
-	algo->udelay = 40;
-	algo->timeout = 20;
+	algo->udelay = 10;
+	algo->timeout = 2;
 	algo->data = adap_cfg;
 
 	sprintf(adapter->name, "viafb i2c io_port idx 0x%02x",
-- 
1.6.3.2


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH 07/12] viafb: reduce I2C timeout and delay
@ 2010-09-19  7:33   ` Florian Tobias Schandinat
  0 siblings, 0 replies; 27+ messages in thread
From: Florian Tobias Schandinat @ 2010-09-19  7:33 UTC (permalink / raw)
  To: linux-fbdev
  Cc: linux-kernel, Florian Tobias Schandinat, Joseph Chan, Jonathan Corbet

viafb: reduce I2C timeout and delay

This patch reduces the value for I2C timeout and udelay.
The udelay was reduced to 10 (old: 40) which is still very high as for
standard-mode I2C even 5 should work. This gives a speedup of factor 4
when talking to I2C devices.
The timeout was reduced to 2 (old: 20) which is taken from the radeon
driver so it should work as well. This gives a speedup of factor 10 when
detecting that there is no I2C device we want to talk to.
This causes a huge improvement of device initialization time.

Signed-off-by: Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
Cc: Joseph Chan <JosephChan@via.com.tw>
Cc: Jonathan Corbet <corbet@lwn.net>
---
 drivers/video/via/via_i2c.c |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/video/via/via_i2c.c b/drivers/video/via/via_i2c.c
index 021112e..3844b55 100644
--- a/drivers/video/via/via_i2c.c
+++ b/drivers/video/via/via_i2c.c
@@ -202,8 +202,8 @@ static int create_i2c_bus(struct i2c_adapter *adapter,
 	algo->setscl = via_i2c_setscl;
 	algo->getsda = via_i2c_getsda;
 	algo->getscl = via_i2c_getscl;
-	algo->udelay = 40;
-	algo->timeout = 20;
+	algo->udelay = 10;
+	algo->timeout = 2;
 	algo->data = adap_cfg;
 
 	sprintf(adapter->name, "viafb i2c io_port idx 0x%02x",
-- 
1.6.3.2


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH 08/12] viafb: add function to change sync polarity per device
  2010-09-19  7:33   ` Florian Tobias Schandinat
@ 2010-09-19  7:33   ` Florian Tobias Schandinat
  -1 siblings, 0 replies; 27+ messages in thread
From: Florian Tobias Schandinat @ 2010-09-19  7:33 UTC (permalink / raw)
  To: linux-fbdev; +Cc: linux-kernel, Florian Tobias Schandinat, Joseph Chan

viafb: add function to change sync polarity per device

At the moment only the sync polarity for CRT is handled but there are
also bits for controlling the sync polarity for other output devices.
Add a function to change those similar to the other output device
functions.
There is no runtime change yet as the code still handles only CRT.

Signed-off-by: Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
Cc: Joseph Chan <JosephChan@via.com.tw>
---
 drivers/video/via/hw.c |   24 +++++++++++++++++++++---
 drivers/video/via/hw.h |    5 +++++
 2 files changed, 26 insertions(+), 3 deletions(-)

diff --git a/drivers/video/via/hw.c b/drivers/video/via/hw.c
index 132d811..d6bbb0a 100644
--- a/drivers/video/via/hw.c
+++ b/drivers/video/via/hw.c
@@ -1151,6 +1151,24 @@ void via_set_state(u32 devices, u8 state)
 		set_lvds2_state(state);
 }
 
+void via_set_sync_polarity(u32 devices, u8 polarity)
+{
+	if (polarity & ~(VIA_HSYNC_NEGATIVE | VIA_VSYNC_NEGATIVE)) {
+		printk(KERN_WARNING "viafb: Unsupported polarity: %d\n",
+			polarity);
+		return;
+	}
+
+	if (devices & VIA_CRT)
+		via_write_misc_reg_mask(polarity << 6, 0xC0);
+	if (devices & VIA_DVP1)
+		via_write_reg_mask(VIACR, 0x9B, polarity << 5, 0x60);
+	if (devices & VIA_LVDS1)
+		via_write_reg_mask(VIACR, 0x99, polarity << 5, 0x60);
+	if (devices & VIA_LVDS2)
+		via_write_reg_mask(VIACR, 0x97, polarity << 5, 0x60);
+}
+
 u32 via_parse_odev(char *input, char **end)
 {
 	char *ptr = input;
@@ -2026,10 +2044,10 @@ void viafb_fill_crtc_timing(struct crt_mode_table *crt_table,
 
 	/* update polarity for CRT timing */
 	if (crt_table[index].h_sync_polarity == NEGATIVE)
-		polarity |= BIT6;
+		polarity |= VIA_HSYNC_NEGATIVE;
 	if (crt_table[index].v_sync_polarity == NEGATIVE)
-		polarity |= BIT7;
-	via_write_misc_reg_mask(polarity, BIT6 | BIT7);
+		polarity |= VIA_VSYNC_NEGATIVE;
+	via_set_sync_polarity(VIA_CRT, polarity);
 
 	if (set_iga == IGA1) {
 		viafb_unlock_crt();
diff --git a/drivers/video/via/hw.h b/drivers/video/via/hw.h
index b067cbb..ad6f9b1 100644
--- a/drivers/video/via/hw.h
+++ b/drivers/video/via/hw.h
@@ -47,6 +47,10 @@
 #define VIA_STATE_SUSPEND	2
 #define VIA_STATE_OFF		3
 
+/* VIA output device sync polarity */
+#define VIA_HSYNC_NEGATIVE	0x01
+#define VIA_VSYNC_NEGATIVE	0x02
+
 /***************************************************
 * Definition IGA1 Design Method of CRTC Registers *
 ****************************************************/
@@ -912,6 +916,7 @@ void viafb_load_reg(int timing_value, int viafb_load_reg_num,
 	      int io_type);
 void via_set_source(u32 devices, u8 iga);
 void via_set_state(u32 devices, u8 state);
+void via_set_sync_polarity(u32 devices, u8 polarity);
 u32 via_parse_odev(char *input, char **end);
 void via_odev_to_seq(struct seq_file *m, u32 odev);
 void init_ad9389(void);
-- 
1.6.3.2


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH 08/12] viafb: add function to change sync polarity per device
@ 2010-09-19  7:33   ` Florian Tobias Schandinat
  0 siblings, 0 replies; 27+ messages in thread
From: Florian Tobias Schandinat @ 2010-09-19  7:33 UTC (permalink / raw)
  To: linux-fbdev; +Cc: linux-kernel, Florian Tobias Schandinat, Joseph Chan

viafb: add function to change sync polarity per device

At the moment only the sync polarity for CRT is handled but there are
also bits for controlling the sync polarity for other output devices.
Add a function to change those similar to the other output device
functions.
There is no runtime change yet as the code still handles only CRT.

Signed-off-by: Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
Cc: Joseph Chan <JosephChan@via.com.tw>
---
 drivers/video/via/hw.c |   24 +++++++++++++++++++++---
 drivers/video/via/hw.h |    5 +++++
 2 files changed, 26 insertions(+), 3 deletions(-)

diff --git a/drivers/video/via/hw.c b/drivers/video/via/hw.c
index 132d811..d6bbb0a 100644
--- a/drivers/video/via/hw.c
+++ b/drivers/video/via/hw.c
@@ -1151,6 +1151,24 @@ void via_set_state(u32 devices, u8 state)
 		set_lvds2_state(state);
 }
 
+void via_set_sync_polarity(u32 devices, u8 polarity)
+{
+	if (polarity & ~(VIA_HSYNC_NEGATIVE | VIA_VSYNC_NEGATIVE)) {
+		printk(KERN_WARNING "viafb: Unsupported polarity: %d\n",
+			polarity);
+		return;
+	}
+
+	if (devices & VIA_CRT)
+		via_write_misc_reg_mask(polarity << 6, 0xC0);
+	if (devices & VIA_DVP1)
+		via_write_reg_mask(VIACR, 0x9B, polarity << 5, 0x60);
+	if (devices & VIA_LVDS1)
+		via_write_reg_mask(VIACR, 0x99, polarity << 5, 0x60);
+	if (devices & VIA_LVDS2)
+		via_write_reg_mask(VIACR, 0x97, polarity << 5, 0x60);
+}
+
 u32 via_parse_odev(char *input, char **end)
 {
 	char *ptr = input;
@@ -2026,10 +2044,10 @@ void viafb_fill_crtc_timing(struct crt_mode_table *crt_table,
 
 	/* update polarity for CRT timing */
 	if (crt_table[index].h_sync_polarity = NEGATIVE)
-		polarity |= BIT6;
+		polarity |= VIA_HSYNC_NEGATIVE;
 	if (crt_table[index].v_sync_polarity = NEGATIVE)
-		polarity |= BIT7;
-	via_write_misc_reg_mask(polarity, BIT6 | BIT7);
+		polarity |= VIA_VSYNC_NEGATIVE;
+	via_set_sync_polarity(VIA_CRT, polarity);
 
 	if (set_iga = IGA1) {
 		viafb_unlock_crt();
diff --git a/drivers/video/via/hw.h b/drivers/video/via/hw.h
index b067cbb..ad6f9b1 100644
--- a/drivers/video/via/hw.h
+++ b/drivers/video/via/hw.h
@@ -47,6 +47,10 @@
 #define VIA_STATE_SUSPEND	2
 #define VIA_STATE_OFF		3
 
+/* VIA output device sync polarity */
+#define VIA_HSYNC_NEGATIVE	0x01
+#define VIA_VSYNC_NEGATIVE	0x02
+
 /***************************************************
 * Definition IGA1 Design Method of CRTC Registers *
 ****************************************************/
@@ -912,6 +916,7 @@ void viafb_load_reg(int timing_value, int viafb_load_reg_num,
 	      int io_type);
 void via_set_source(u32 devices, u8 iga);
 void via_set_state(u32 devices, u8 state);
+void via_set_sync_polarity(u32 devices, u8 polarity);
 u32 via_parse_odev(char *input, char **end);
 void via_odev_to_seq(struct seq_file *m, u32 odev);
 void init_ad9389(void);
-- 
1.6.3.2


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH 09/12] viafb: set sync polarity for all output devices
  2010-09-19  7:33   ` Florian Tobias Schandinat
@ 2010-09-19  7:33   ` Florian Tobias Schandinat
  -1 siblings, 0 replies; 27+ messages in thread
From: Florian Tobias Schandinat @ 2010-09-19  7:33 UTC (permalink / raw)
  To: linux-fbdev; +Cc: linux-kernel, Florian Tobias Schandinat, Joseph Chan

viafb: set sync polarity for all output devices

This patch sets the sync polarity for all output devices, not only CRT.
This may give some people a working screen but only if lcd scaling and
centering are not used as it is currently too dificult to propagate a
different resolution (from what the application thinks) to the correct
output device. Hopefully this does not introduce regressions as the
polarity of non-CRT devices was completly ignored before.

Signed-off-by: Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
Cc: Joseph Chan <JosephChan@via.com.tw>
---
 drivers/video/via/hw.c |   34 +++++++++++++++++++++++++---------
 1 files changed, 25 insertions(+), 9 deletions(-)

diff --git a/drivers/video/via/hw.c b/drivers/video/via/hw.c
index d6bbb0a..00fecb5 100644
--- a/drivers/video/via/hw.c
+++ b/drivers/video/via/hw.c
@@ -2014,7 +2014,6 @@ void viafb_fill_crtc_timing(struct crt_mode_table *crt_table,
 	int index = 0;
 	int h_addr, v_addr;
 	u32 pll_D_N;
-	u8 polarity = 0;
 
 	for (i = 0; i < video_mode->mode_array; i++) {
 		index = i;
@@ -2041,14 +2040,6 @@ void viafb_fill_crtc_timing(struct crt_mode_table *crt_table,
 
 	h_addr = crt_reg.hor_addr;
 	v_addr = crt_reg.ver_addr;
-
-	/* update polarity for CRT timing */
-	if (crt_table[index].h_sync_polarity == NEGATIVE)
-		polarity |= VIA_HSYNC_NEGATIVE;
-	if (crt_table[index].v_sync_polarity == NEGATIVE)
-		polarity |= VIA_VSYNC_NEGATIVE;
-	via_set_sync_polarity(VIA_CRT, polarity);
-
 	if (set_iga == IGA1) {
 		viafb_unlock_crt();
 		viafb_write_reg(CR09, VIACR, 0x00);	/*initial CR09=0 */
@@ -2352,6 +2343,17 @@ static void set_display_channel(void)
 	}
 }
 
+static u8 get_sync(struct fb_info *info)
+{
+	u8 polarity = 0;
+
+	if (!(info->var.sync & FB_SYNC_HOR_HIGH_ACT))
+		polarity |= VIA_HSYNC_NEGATIVE;
+	if (!(info->var.sync & FB_SYNC_VERT_HIGH_ACT))
+		polarity |= VIA_VSYNC_NEGATIVE;
+	return polarity;
+}
+
 int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp,
 	struct VideoModeTable *vmode_tbl1, int video_bpp1)
 {
@@ -2566,6 +2568,15 @@ int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp,
 			viafb_DeviceStatus = CRT_Device;
 	}
 	device_on();
+	if (!viafb_dual_fb)
+		via_set_sync_polarity(devices, get_sync(viafbinfo));
+	else {
+		via_set_sync_polarity(viaparinfo->shared->iga1_devices,
+			get_sync(viafbinfo));
+		via_set_sync_polarity(viaparinfo->shared->iga2_devices,
+			get_sync(viafbinfo1));
+	}
+
 	via_set_state(devices, VIA_STATE_ON);
 	device_screen_on();
 	return 1;
@@ -2719,4 +2730,9 @@ void viafb_fill_var_timing_info(struct fb_var_screeninfo *var, int refresh,
 	    crt_reg.ver_total - (crt_reg.ver_sync_start + crt_reg.ver_sync_end);
 	var->lower_margin = crt_reg.ver_sync_start - crt_reg.ver_addr;
 	var->vsync_len = crt_reg.ver_sync_end;
+	var->sync = 0;
+	if (crt_timing[index].h_sync_polarity == POSITIVE)
+		var->sync |= FB_SYNC_HOR_HIGH_ACT;
+	if (crt_timing[index].v_sync_polarity == POSITIVE)
+		var->sync |= FB_SYNC_VERT_HIGH_ACT;
 }
-- 
1.6.3.2


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH 09/12] viafb: set sync polarity for all output devices
@ 2010-09-19  7:33   ` Florian Tobias Schandinat
  0 siblings, 0 replies; 27+ messages in thread
From: Florian Tobias Schandinat @ 2010-09-19  7:33 UTC (permalink / raw)
  To: linux-fbdev; +Cc: linux-kernel, Florian Tobias Schandinat, Joseph Chan

viafb: set sync polarity for all output devices

This patch sets the sync polarity for all output devices, not only CRT.
This may give some people a working screen but only if lcd scaling and
centering are not used as it is currently too dificult to propagate a
different resolution (from what the application thinks) to the correct
output device. Hopefully this does not introduce regressions as the
polarity of non-CRT devices was completly ignored before.

Signed-off-by: Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
Cc: Joseph Chan <JosephChan@via.com.tw>
---
 drivers/video/via/hw.c |   34 +++++++++++++++++++++++++---------
 1 files changed, 25 insertions(+), 9 deletions(-)

diff --git a/drivers/video/via/hw.c b/drivers/video/via/hw.c
index d6bbb0a..00fecb5 100644
--- a/drivers/video/via/hw.c
+++ b/drivers/video/via/hw.c
@@ -2014,7 +2014,6 @@ void viafb_fill_crtc_timing(struct crt_mode_table *crt_table,
 	int index = 0;
 	int h_addr, v_addr;
 	u32 pll_D_N;
-	u8 polarity = 0;
 
 	for (i = 0; i < video_mode->mode_array; i++) {
 		index = i;
@@ -2041,14 +2040,6 @@ void viafb_fill_crtc_timing(struct crt_mode_table *crt_table,
 
 	h_addr = crt_reg.hor_addr;
 	v_addr = crt_reg.ver_addr;
-
-	/* update polarity for CRT timing */
-	if (crt_table[index].h_sync_polarity = NEGATIVE)
-		polarity |= VIA_HSYNC_NEGATIVE;
-	if (crt_table[index].v_sync_polarity = NEGATIVE)
-		polarity |= VIA_VSYNC_NEGATIVE;
-	via_set_sync_polarity(VIA_CRT, polarity);
-
 	if (set_iga = IGA1) {
 		viafb_unlock_crt();
 		viafb_write_reg(CR09, VIACR, 0x00);	/*initial CR09=0 */
@@ -2352,6 +2343,17 @@ static void set_display_channel(void)
 	}
 }
 
+static u8 get_sync(struct fb_info *info)
+{
+	u8 polarity = 0;
+
+	if (!(info->var.sync & FB_SYNC_HOR_HIGH_ACT))
+		polarity |= VIA_HSYNC_NEGATIVE;
+	if (!(info->var.sync & FB_SYNC_VERT_HIGH_ACT))
+		polarity |= VIA_VSYNC_NEGATIVE;
+	return polarity;
+}
+
 int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp,
 	struct VideoModeTable *vmode_tbl1, int video_bpp1)
 {
@@ -2566,6 +2568,15 @@ int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp,
 			viafb_DeviceStatus = CRT_Device;
 	}
 	device_on();
+	if (!viafb_dual_fb)
+		via_set_sync_polarity(devices, get_sync(viafbinfo));
+	else {
+		via_set_sync_polarity(viaparinfo->shared->iga1_devices,
+			get_sync(viafbinfo));
+		via_set_sync_polarity(viaparinfo->shared->iga2_devices,
+			get_sync(viafbinfo1));
+	}
+
 	via_set_state(devices, VIA_STATE_ON);
 	device_screen_on();
 	return 1;
@@ -2719,4 +2730,9 @@ void viafb_fill_var_timing_info(struct fb_var_screeninfo *var, int refresh,
 	    crt_reg.ver_total - (crt_reg.ver_sync_start + crt_reg.ver_sync_end);
 	var->lower_margin = crt_reg.ver_sync_start - crt_reg.ver_addr;
 	var->vsync_len = crt_reg.ver_sync_end;
+	var->sync = 0;
+	if (crt_timing[index].h_sync_polarity = POSITIVE)
+		var->sync |= FB_SYNC_HOR_HIGH_ACT;
+	if (crt_timing[index].v_sync_polarity = POSITIVE)
+		var->sync |= FB_SYNC_VERT_HIGH_ACT;
 }
-- 
1.6.3.2


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH 10/12] viafb: add a mapping of supported output devices
  2010-09-19  7:26 [PATCH 00/12] viafb output device rework - part 2 Florian Tobias Schandinat
                   ` (8 preceding siblings ...)
  2010-09-19  7:33   ` Florian Tobias Schandinat
@ 2010-09-19  7:39 ` Florian Tobias Schandinat
  2010-09-19  7:39   ` Florian Tobias Schandinat
  2010-09-19  7:39   ` Florian Tobias Schandinat
  11 siblings, 0 replies; 27+ messages in thread
From: Florian Tobias Schandinat @ 2010-09-19  7:39 UTC (permalink / raw)
  To: linux-fbdev
  Cc: linux-kernel, Florian Tobias Schandinat, Joseph Chan,
	Jonathan Corbet, Andrew Morton

viafb: add a mapping of supported output devices

This patch maps supported output devices to IGP versions. This list may
contain errors as most of it is derived of the driver source but it should
be correct enough to provide a good help. The devices are exported via a
proc entry in the same format as those showing the output devices per IGA.

Signed-off-by: Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
Cc: Joseph Chan <JosephChan@via.com.tw>
Cc: Jonathan Corbet <corbet@lwn.net>
Cc: Andrew Morton <akpm@linux-foundation.org>
---
 drivers/video/via/viafbdev.c |   48 ++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 48 insertions(+), 0 deletions(-)

diff --git a/drivers/video/via/viafbdev.c b/drivers/video/via/viafbdev.c
index ce6f13a..17f228a 100644
--- a/drivers/video/via/viafbdev.c
+++ b/drivers/video/via/viafbdev.c
@@ -56,6 +56,31 @@ static int viafb_pan_display(struct fb_var_screeninfo *var,
 
 static struct fb_ops viafb_ops;
 
+/* supported output devices on each IGP
+ * only CX700, VX800, VX855 were documented
+ * VIA_CRT should be everywhere
+ * VIA_6C can be onle pre-CX700 (probably only on CLE266) as 6C is used for PLL
+ * source selection on CX700 and later
+ * K400 seems to support VIA_96, VIA_DVP1, VIA_LVDS{1,2} as in viamode.c
+ */
+static const u32 supported_odev_map[] = {
+	[UNICHROME_CLE266]	= VIA_CRT | VIA_6C | VIA_93,
+	[UNICHROME_K400]	= VIA_CRT | VIA_96 | VIA_DVP1 | VIA_LVDS1
+				| VIA_LVDS2,
+	[UNICHROME_K800]	= VIA_CRT | VIA_96 | VIA_DVP1 | VIA_LVDS1
+				| VIA_LVDS2,
+	[UNICHROME_PM800]	= VIA_CRT | VIA_96 | VIA_DVP1 | VIA_LVDS1
+				| VIA_LVDS2,
+	[UNICHROME_CN700]	= VIA_CRT | VIA_96 | VIA_DVP1 | VIA_LVDS1
+				| VIA_LVDS2,
+	[UNICHROME_CX700]	= VIA_CRT | VIA_DVP1 | VIA_LVDS1 | VIA_LVDS2,
+	[UNICHROME_CN750]	= VIA_CRT | VIA_DVP1 | VIA_LVDS1 | VIA_LVDS2,
+	[UNICHROME_K8M890]	= VIA_CRT | VIA_DVP1 | VIA_LVDS1 | VIA_LVDS2,
+	[UNICHROME_P4M890]	= VIA_CRT | VIA_DVP1 | VIA_LVDS1 | VIA_LVDS2,
+	[UNICHROME_P4M900]	= VIA_CRT | VIA_DVP1 | VIA_LVDS1 | VIA_LVDS2,
+	[UNICHROME_VX800]	= VIA_CRT | VIA_DVP1 | VIA_LVDS1 | VIA_LVDS2,
+	[UNICHROME_VX855]	= VIA_CRT | VIA_DVP1 | VIA_LVDS1 | VIA_LVDS2,
+};
 
 static void viafb_fill_var_color_info(struct fb_var_screeninfo *var, u8 depth)
 {
@@ -1433,6 +1458,26 @@ static const struct file_operations viafb_vt1636_proc_fops = {
 
 #endif /* CONFIG_FB_VIA_DIRECT_PROCFS */
 
+static int viafb_sup_odev_proc_show(struct seq_file *m, void *v)
+{
+	via_odev_to_seq(m, supported_odev_map[
+		viaparinfo->shared->chip_info.gfx_chip_name]);
+	return 0;
+}
+
+static int viafb_sup_odev_proc_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, viafb_sup_odev_proc_show, NULL);
+}
+
+static const struct file_operations viafb_sup_odev_proc_fops = {
+	.owner		= THIS_MODULE,
+	.open		= viafb_sup_odev_proc_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
 static ssize_t odev_update(const char __user *buffer, size_t count, u32 *odev)
 {
 	char buf[64], *ptr = buf;
@@ -1561,6 +1606,8 @@ static void viafb_init_proc(struct viafb_shared *shared)
 		}
 #endif /* CONFIG_FB_VIA_DIRECT_PROCFS */
 
+		proc_create("supported_output_devices", 0, viafb_entry,
+			&viafb_sup_odev_proc_fops);
 		iga1_entry = proc_mkdir("iga1", viafb_entry);
 		shared->iga1_proc_entry = iga1_entry;
 		proc_create("output_devices", 0, iga1_entry,
@@ -1585,6 +1632,7 @@ static void viafb_remove_proc(struct viafb_shared *shared)
 	remove_proc_entry("iga2", viafb_entry);
 	remove_proc_entry("output_devices", iga1_entry);
 	remove_proc_entry("iga1", viafb_entry);
+	remove_proc_entry("supported_output_devices", viafb_entry);
 
 #ifdef CONFIG_FB_VIA_DIRECT_PROCFS
 	remove_proc_entry("dvp0", viafb_entry);/* parent dir */
-- 
1.6.3.2


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH 11/12] viafb: rename output devices
  2010-09-19  7:39 ` [PATCH 10/12] viafb: add a mapping of supported " Florian Tobias Schandinat
@ 2010-09-19  7:39   ` Florian Tobias Schandinat
  -1 siblings, 0 replies; 27+ messages in thread
From: Florian Tobias Schandinat @ 2010-09-19  7:39 UTC (permalink / raw)
  To: linux-fbdev
  Cc: linux-kernel, Florian Tobias Schandinat, Joseph Chan,
	Jonathan Corbet, Andrew Morton

viafb: rename output devices

Now it looks like we finally know enough about the output devices to give
them proper names. As VIA_96 is often referred to as DVP0 rename it to
VIA_DVP0. As VIA_6C and VIA_93 seem to exist only on CLE266 and "replace"
DVP0 and DVP1 there rename them to VIA_LDVP0 and VIA_LDVP1 (L as legacy).
The proc names were changed accordingly which should be harmless as they
were just introduced and not beyond RFC state.
This patch should make things a bit more comfortable and less scary.

Signed-off-by: Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
Cc: Joseph Chan <JosephChan@via.com.tw>
Cc: Jonathan Corbet <corbet@lwn.net>
Cc: Andrew Morton <akpm@linux-foundation.org>
---
 drivers/video/via/hw.c       |   44 +++++++++++++++++++++---------------------
 drivers/video/via/hw.h       |    6 ++--
 drivers/video/via/viafbdev.c |   10 ++++----
 3 files changed, 30 insertions(+), 30 deletions(-)

diff --git a/drivers/video/via/hw.c b/drivers/video/via/hw.c
index 00fecb5..7d7010a 100644
--- a/drivers/video/via/hw.c
+++ b/drivers/video/via/hw.c
@@ -719,9 +719,9 @@ static struct rgbLUT palLUT_table[] = {
 };
 
 static struct via_device_mapping device_mapping[] = {
-	{VIA_6C, "6C"},
-	{VIA_93, "93"},
-	{VIA_96, "96"},
+	{VIA_LDVP0, "LDVP0"},
+	{VIA_LDVP1, "LDVP1"},
+	{VIA_DVP0, "DVP0"},
 	{VIA_CRT, "CRT"},
 	{VIA_DVP1, "DVP1"},
 	{VIA_LVDS1, "LVDS1"},
@@ -763,11 +763,11 @@ static u32 get_dvi_devices(int output_interface)
 {
 	switch (output_interface) {
 	case INTERFACE_DVP0:
-		return VIA_96 | VIA_6C;
+		return VIA_DVP0 | VIA_LDVP0;
 
 	case INTERFACE_DVP1:
 		if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266)
-			return VIA_93;
+			return VIA_LDVP1;
 		else
 			return VIA_DVP1;
 
@@ -775,7 +775,7 @@ static u32 get_dvi_devices(int output_interface)
 		if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266)
 			return 0;
 		else
-			return VIA_LVDS2 | VIA_96;
+			return VIA_LVDS2 | VIA_DVP0;
 
 	case INTERFACE_DFP_LOW:
 		if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266)
@@ -794,13 +794,13 @@ static u32 get_lcd_devices(int output_interface)
 {
 	switch (output_interface) {
 	case INTERFACE_DVP0:
-		return VIA_96;
+		return VIA_DVP0;
 
 	case INTERFACE_DVP1:
 		return VIA_DVP1;
 
 	case INTERFACE_DFP_HIGH:
-		return VIA_LVDS2 | VIA_96;
+		return VIA_LVDS2 | VIA_DVP0;
 
 	case INTERFACE_DFP_LOW:
 		return VIA_LVDS1 | VIA_DVP1;
@@ -988,17 +988,17 @@ static void set_crt_source(u8 iga)
 	via_write_reg_mask(VIASR, 0x16, value, 0x40);
 }
 
-static inline void set_6C_source(u8 iga)
+static inline void set_ldvp0_source(u8 iga)
 {
 	set_source_common(0x6C, 7, iga);
 }
 
-static inline void set_93_source(u8 iga)
+static inline void set_ldvp1_source(u8 iga)
 {
 	set_source_common(0x93, 7, iga);
 }
 
-static inline void set_96_source(u8 iga)
+static inline void set_dvp0_source(u8 iga)
 {
 	set_source_common(0x96, 4, iga);
 }
@@ -1020,12 +1020,12 @@ static inline void set_lvds2_source(u8 iga)
 
 void via_set_source(u32 devices, u8 iga)
 {
-	if (devices & VIA_6C)
-		set_6C_source(iga);
-	if (devices & VIA_93)
-		set_93_source(iga);
-	if (devices & VIA_96)
-		set_96_source(iga);
+	if (devices & VIA_LDVP0)
+		set_ldvp0_source(iga);
+	if (devices & VIA_LDVP1)
+		set_ldvp1_source(iga);
+	if (devices & VIA_DVP0)
+		set_dvp0_source(iga);
 	if (devices & VIA_CRT)
 		set_crt_source(iga);
 	if (devices & VIA_DVP1)
@@ -1060,7 +1060,7 @@ static void set_crt_state(u8 state)
 	via_write_reg_mask(VIACR, 0x36, value, 0x30);
 }
 
-static void set_96_state(u8 state)
+static void set_dvp0_state(u8 state)
 {
 	u8 value;
 
@@ -1136,11 +1136,11 @@ void via_set_state(u32 devices, u8 state)
 {
 	/*
 	TODO: Can we enable/disable these devices? How?
-	if (devices & VIA_6C)
-	if (devices & VIA_93)
+	if (devices & VIA_LDVP0)
+	if (devices & VIA_LDVP1)
 	*/
-	if (devices & VIA_96)
-		set_96_state(state);
+	if (devices & VIA_DVP0)
+		set_dvp0_state(state);
 	if (devices & VIA_CRT)
 		set_crt_state(state);
 	if (devices & VIA_DVP1)
diff --git a/drivers/video/via/hw.h b/drivers/video/via/hw.h
index ad6f9b1..b764409 100644
--- a/drivers/video/via/hw.h
+++ b/drivers/video/via/hw.h
@@ -33,9 +33,9 @@
 #define viafb_write_reg_mask(i, p, d, m)	via_write_reg_mask(p, i, d, m)
 
 /* VIA output devices */
-#define VIA_6C		0x00000001
-#define VIA_93		0x00000002
-#define VIA_96		0x00000004
+#define VIA_LDVP0	0x00000001
+#define VIA_LDVP1	0x00000002
+#define VIA_DVP0	0x00000004
 #define VIA_CRT		0x00000010
 #define VIA_DVP1	0x00000020
 #define VIA_LVDS1	0x00000040
diff --git a/drivers/video/via/viafbdev.c b/drivers/video/via/viafbdev.c
index 17f228a..145645d 100644
--- a/drivers/video/via/viafbdev.c
+++ b/drivers/video/via/viafbdev.c
@@ -64,14 +64,14 @@ static struct fb_ops viafb_ops;
  * K400 seems to support VIA_96, VIA_DVP1, VIA_LVDS{1,2} as in viamode.c
  */
 static const u32 supported_odev_map[] = {
-	[UNICHROME_CLE266]	= VIA_CRT | VIA_6C | VIA_93,
-	[UNICHROME_K400]	= VIA_CRT | VIA_96 | VIA_DVP1 | VIA_LVDS1
+	[UNICHROME_CLE266]	= VIA_CRT | VIA_LDVP0 | VIA_LDVP1,
+	[UNICHROME_K400]	= VIA_CRT | VIA_DVP0 | VIA_DVP1 | VIA_LVDS1
 				| VIA_LVDS2,
-	[UNICHROME_K800]	= VIA_CRT | VIA_96 | VIA_DVP1 | VIA_LVDS1
+	[UNICHROME_K800]	= VIA_CRT | VIA_DVP0 | VIA_DVP1 | VIA_LVDS1
 				| VIA_LVDS2,
-	[UNICHROME_PM800]	= VIA_CRT | VIA_96 | VIA_DVP1 | VIA_LVDS1
+	[UNICHROME_PM800]	= VIA_CRT | VIA_DVP0 | VIA_DVP1 | VIA_LVDS1
 				| VIA_LVDS2,
-	[UNICHROME_CN700]	= VIA_CRT | VIA_96 | VIA_DVP1 | VIA_LVDS1
+	[UNICHROME_CN700]	= VIA_CRT | VIA_DVP0 | VIA_DVP1 | VIA_LVDS1
 				| VIA_LVDS2,
 	[UNICHROME_CX700]	= VIA_CRT | VIA_DVP1 | VIA_LVDS1 | VIA_LVDS2,
 	[UNICHROME_CN750]	= VIA_CRT | VIA_DVP1 | VIA_LVDS1 | VIA_LVDS2,
-- 
1.6.3.2


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH 11/12] viafb: rename output devices
@ 2010-09-19  7:39   ` Florian Tobias Schandinat
  0 siblings, 0 replies; 27+ messages in thread
From: Florian Tobias Schandinat @ 2010-09-19  7:39 UTC (permalink / raw)
  To: linux-fbdev
  Cc: linux-kernel, Florian Tobias Schandinat, Joseph Chan,
	Jonathan Corbet, Andrew Morton

viafb: rename output devices

Now it looks like we finally know enough about the output devices to give
them proper names. As VIA_96 is often referred to as DVP0 rename it to
VIA_DVP0. As VIA_6C and VIA_93 seem to exist only on CLE266 and "replace"
DVP0 and DVP1 there rename them to VIA_LDVP0 and VIA_LDVP1 (L as legacy).
The proc names were changed accordingly which should be harmless as they
were just introduced and not beyond RFC state.
This patch should make things a bit more comfortable and less scary.

Signed-off-by: Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
Cc: Joseph Chan <JosephChan@via.com.tw>
Cc: Jonathan Corbet <corbet@lwn.net>
Cc: Andrew Morton <akpm@linux-foundation.org>
---
 drivers/video/via/hw.c       |   44 +++++++++++++++++++++---------------------
 drivers/video/via/hw.h       |    6 ++--
 drivers/video/via/viafbdev.c |   10 ++++----
 3 files changed, 30 insertions(+), 30 deletions(-)

diff --git a/drivers/video/via/hw.c b/drivers/video/via/hw.c
index 00fecb5..7d7010a 100644
--- a/drivers/video/via/hw.c
+++ b/drivers/video/via/hw.c
@@ -719,9 +719,9 @@ static struct rgbLUT palLUT_table[] = {
 };
 
 static struct via_device_mapping device_mapping[] = {
-	{VIA_6C, "6C"},
-	{VIA_93, "93"},
-	{VIA_96, "96"},
+	{VIA_LDVP0, "LDVP0"},
+	{VIA_LDVP1, "LDVP1"},
+	{VIA_DVP0, "DVP0"},
 	{VIA_CRT, "CRT"},
 	{VIA_DVP1, "DVP1"},
 	{VIA_LVDS1, "LVDS1"},
@@ -763,11 +763,11 @@ static u32 get_dvi_devices(int output_interface)
 {
 	switch (output_interface) {
 	case INTERFACE_DVP0:
-		return VIA_96 | VIA_6C;
+		return VIA_DVP0 | VIA_LDVP0;
 
 	case INTERFACE_DVP1:
 		if (viaparinfo->chip_info->gfx_chip_name = UNICHROME_CLE266)
-			return VIA_93;
+			return VIA_LDVP1;
 		else
 			return VIA_DVP1;
 
@@ -775,7 +775,7 @@ static u32 get_dvi_devices(int output_interface)
 		if (viaparinfo->chip_info->gfx_chip_name = UNICHROME_CLE266)
 			return 0;
 		else
-			return VIA_LVDS2 | VIA_96;
+			return VIA_LVDS2 | VIA_DVP0;
 
 	case INTERFACE_DFP_LOW:
 		if (viaparinfo->chip_info->gfx_chip_name = UNICHROME_CLE266)
@@ -794,13 +794,13 @@ static u32 get_lcd_devices(int output_interface)
 {
 	switch (output_interface) {
 	case INTERFACE_DVP0:
-		return VIA_96;
+		return VIA_DVP0;
 
 	case INTERFACE_DVP1:
 		return VIA_DVP1;
 
 	case INTERFACE_DFP_HIGH:
-		return VIA_LVDS2 | VIA_96;
+		return VIA_LVDS2 | VIA_DVP0;
 
 	case INTERFACE_DFP_LOW:
 		return VIA_LVDS1 | VIA_DVP1;
@@ -988,17 +988,17 @@ static void set_crt_source(u8 iga)
 	via_write_reg_mask(VIASR, 0x16, value, 0x40);
 }
 
-static inline void set_6C_source(u8 iga)
+static inline void set_ldvp0_source(u8 iga)
 {
 	set_source_common(0x6C, 7, iga);
 }
 
-static inline void set_93_source(u8 iga)
+static inline void set_ldvp1_source(u8 iga)
 {
 	set_source_common(0x93, 7, iga);
 }
 
-static inline void set_96_source(u8 iga)
+static inline void set_dvp0_source(u8 iga)
 {
 	set_source_common(0x96, 4, iga);
 }
@@ -1020,12 +1020,12 @@ static inline void set_lvds2_source(u8 iga)
 
 void via_set_source(u32 devices, u8 iga)
 {
-	if (devices & VIA_6C)
-		set_6C_source(iga);
-	if (devices & VIA_93)
-		set_93_source(iga);
-	if (devices & VIA_96)
-		set_96_source(iga);
+	if (devices & VIA_LDVP0)
+		set_ldvp0_source(iga);
+	if (devices & VIA_LDVP1)
+		set_ldvp1_source(iga);
+	if (devices & VIA_DVP0)
+		set_dvp0_source(iga);
 	if (devices & VIA_CRT)
 		set_crt_source(iga);
 	if (devices & VIA_DVP1)
@@ -1060,7 +1060,7 @@ static void set_crt_state(u8 state)
 	via_write_reg_mask(VIACR, 0x36, value, 0x30);
 }
 
-static void set_96_state(u8 state)
+static void set_dvp0_state(u8 state)
 {
 	u8 value;
 
@@ -1136,11 +1136,11 @@ void via_set_state(u32 devices, u8 state)
 {
 	/*
 	TODO: Can we enable/disable these devices? How?
-	if (devices & VIA_6C)
-	if (devices & VIA_93)
+	if (devices & VIA_LDVP0)
+	if (devices & VIA_LDVP1)
 	*/
-	if (devices & VIA_96)
-		set_96_state(state);
+	if (devices & VIA_DVP0)
+		set_dvp0_state(state);
 	if (devices & VIA_CRT)
 		set_crt_state(state);
 	if (devices & VIA_DVP1)
diff --git a/drivers/video/via/hw.h b/drivers/video/via/hw.h
index ad6f9b1..b764409 100644
--- a/drivers/video/via/hw.h
+++ b/drivers/video/via/hw.h
@@ -33,9 +33,9 @@
 #define viafb_write_reg_mask(i, p, d, m)	via_write_reg_mask(p, i, d, m)
 
 /* VIA output devices */
-#define VIA_6C		0x00000001
-#define VIA_93		0x00000002
-#define VIA_96		0x00000004
+#define VIA_LDVP0	0x00000001
+#define VIA_LDVP1	0x00000002
+#define VIA_DVP0	0x00000004
 #define VIA_CRT		0x00000010
 #define VIA_DVP1	0x00000020
 #define VIA_LVDS1	0x00000040
diff --git a/drivers/video/via/viafbdev.c b/drivers/video/via/viafbdev.c
index 17f228a..145645d 100644
--- a/drivers/video/via/viafbdev.c
+++ b/drivers/video/via/viafbdev.c
@@ -64,14 +64,14 @@ static struct fb_ops viafb_ops;
  * K400 seems to support VIA_96, VIA_DVP1, VIA_LVDS{1,2} as in viamode.c
  */
 static const u32 supported_odev_map[] = {
-	[UNICHROME_CLE266]	= VIA_CRT | VIA_6C | VIA_93,
-	[UNICHROME_K400]	= VIA_CRT | VIA_96 | VIA_DVP1 | VIA_LVDS1
+	[UNICHROME_CLE266]	= VIA_CRT | VIA_LDVP0 | VIA_LDVP1,
+	[UNICHROME_K400]	= VIA_CRT | VIA_DVP0 | VIA_DVP1 | VIA_LVDS1
 				| VIA_LVDS2,
-	[UNICHROME_K800]	= VIA_CRT | VIA_96 | VIA_DVP1 | VIA_LVDS1
+	[UNICHROME_K800]	= VIA_CRT | VIA_DVP0 | VIA_DVP1 | VIA_LVDS1
 				| VIA_LVDS2,
-	[UNICHROME_PM800]	= VIA_CRT | VIA_96 | VIA_DVP1 | VIA_LVDS1
+	[UNICHROME_PM800]	= VIA_CRT | VIA_DVP0 | VIA_DVP1 | VIA_LVDS1
 				| VIA_LVDS2,
-	[UNICHROME_CN700]	= VIA_CRT | VIA_96 | VIA_DVP1 | VIA_LVDS1
+	[UNICHROME_CN700]	= VIA_CRT | VIA_DVP0 | VIA_DVP1 | VIA_LVDS1
 				| VIA_LVDS2,
 	[UNICHROME_CX700]	= VIA_CRT | VIA_DVP1 | VIA_LVDS1 | VIA_LVDS2,
 	[UNICHROME_CN750]	= VIA_CRT | VIA_DVP1 | VIA_LVDS1 | VIA_LVDS2,
-- 
1.6.3.2


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH 12/12] viafb: add documentation for proc interface
  2010-09-19  7:39 ` [PATCH 10/12] viafb: add a mapping of supported " Florian Tobias Schandinat
@ 2010-09-19  7:39   ` Florian Tobias Schandinat
  -1 siblings, 0 replies; 27+ messages in thread
From: Florian Tobias Schandinat @ 2010-09-19  7:39 UTC (permalink / raw)
  To: linux-fbdev
  Cc: linux-kernel, Florian Tobias Schandinat, Joseph Chan,
	Jonathan Corbet, Andrew Morton

viafb: add documentation for proc interface

This patch adds documentation for the new proc interface that allows
modification of the output device configuration. Should be stable and
useful enough now for daily use.

Signed-off-by: Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
Cc: Joseph Chan <JosephChan@via.com.tw>
Cc: Jonathan Corbet <corbet@lwn.net>
Cc: Andrew Morton <akpm@linux-foundation.org>
---
 Documentation/fb/viafb.txt |   48 ++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 48 insertions(+), 0 deletions(-)

diff --git a/Documentation/fb/viafb.txt b/Documentation/fb/viafb.txt
index f3e046a..1a2e8aa 100644
--- a/Documentation/fb/viafb.txt
+++ b/Documentation/fb/viafb.txt
@@ -197,6 +197,54 @@ Notes:
        example,
            # fbset -depth 16
 
+
+[Configure viafb via /proc]
+---------------------------
+    The following files exist in /proc/viafb
+
+    supported_output_devices
+
+        This read-only file contains a full ',' seperated list containing all
+        output devices that could be available on your platform. It is likely
+        that not all of those have a connector on your hardware but it should
+        provide a good starting point to figure out which of those names match
+        a real connector.
+        Example:
+        # cat /proc/viafb/supported_output_devices
+
+    iga1/output_devices
+    iga2/output_devices
+
+        These two files are readable and writable. iga1 and iga2 are the two
+        independent units that produce the screen image. Those images can be
+        forwarded to one or more output devices. Reading those files is a way
+        to query which output devices are currently used by an iga.
+        Example:
+        # cat /proc/viafb/iga1/output_devices
+        If there are no output devices printed the output of this iga is lost.
+        This can happen for example if only one (the other) iga is used.
+        Writing to these files allows adjusting the output devices during
+        runtime. One can add new devices, remove existing ones or switch
+        between igas. Essentially you can write a ',' seperated list of device
+        names (or a single one) in the same format as the output to those
+        files. You can add a '+' or '-' as a prefix allowing simple addition
+        and removal of devices. So a prefix '+' adds the devices from your list
+        to the already existing ones, '-' removes the listed devices from the
+        existing ones and if no prefix is given it replaces all existing ones
+        with the listed ones. If you remove devices they are expected to turn
+        off. If you add devices that are already part of the other iga they are
+        removed there and added to the new one.
+        Examples:
+        Add CRT as output device to iga1
+        # echo +CRT > /proc/viafb/iga1/output_devices
+
+        Remove (turn off) DVP1 and LVDS1 as output devices of iga2
+        # echo -DVP1,LVDS1 > /proc/viafb/iga2/output_devices
+
+        Replace all iga1 output devices by CRT
+        # echo CRT > /proc/viafb/iga1/output_devices
+
+
 [Bootup with viafb]:
 --------------------
     Add the following line to your grub.conf:
-- 
1.6.3.2


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH 12/12] viafb: add documentation for proc interface
@ 2010-09-19  7:39   ` Florian Tobias Schandinat
  0 siblings, 0 replies; 27+ messages in thread
From: Florian Tobias Schandinat @ 2010-09-19  7:39 UTC (permalink / raw)
  To: linux-fbdev
  Cc: linux-kernel, Florian Tobias Schandinat, Joseph Chan,
	Jonathan Corbet, Andrew Morton

viafb: add documentation for proc interface

This patch adds documentation for the new proc interface that allows
modification of the output device configuration. Should be stable and
useful enough now for daily use.

Signed-off-by: Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
Cc: Joseph Chan <JosephChan@via.com.tw>
Cc: Jonathan Corbet <corbet@lwn.net>
Cc: Andrew Morton <akpm@linux-foundation.org>
---
 Documentation/fb/viafb.txt |   48 ++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 48 insertions(+), 0 deletions(-)

diff --git a/Documentation/fb/viafb.txt b/Documentation/fb/viafb.txt
index f3e046a..1a2e8aa 100644
--- a/Documentation/fb/viafb.txt
+++ b/Documentation/fb/viafb.txt
@@ -197,6 +197,54 @@ Notes:
        example,
            # fbset -depth 16
 
+
+[Configure viafb via /proc]
+---------------------------
+    The following files exist in /proc/viafb
+
+    supported_output_devices
+
+        This read-only file contains a full ',' seperated list containing all
+        output devices that could be available on your platform. It is likely
+        that not all of those have a connector on your hardware but it should
+        provide a good starting point to figure out which of those names match
+        a real connector.
+        Example:
+        # cat /proc/viafb/supported_output_devices
+
+    iga1/output_devices
+    iga2/output_devices
+
+        These two files are readable and writable. iga1 and iga2 are the two
+        independent units that produce the screen image. Those images can be
+        forwarded to one or more output devices. Reading those files is a way
+        to query which output devices are currently used by an iga.
+        Example:
+        # cat /proc/viafb/iga1/output_devices
+        If there are no output devices printed the output of this iga is lost.
+        This can happen for example if only one (the other) iga is used.
+        Writing to these files allows adjusting the output devices during
+        runtime. One can add new devices, remove existing ones or switch
+        between igas. Essentially you can write a ',' seperated list of device
+        names (or a single one) in the same format as the output to those
+        files. You can add a '+' or '-' as a prefix allowing simple addition
+        and removal of devices. So a prefix '+' adds the devices from your list
+        to the already existing ones, '-' removes the listed devices from the
+        existing ones and if no prefix is given it replaces all existing ones
+        with the listed ones. If you remove devices they are expected to turn
+        off. If you add devices that are already part of the other iga they are
+        removed there and added to the new one.
+        Examples:
+        Add CRT as output device to iga1
+        # echo +CRT > /proc/viafb/iga1/output_devices
+
+        Remove (turn off) DVP1 and LVDS1 as output devices of iga2
+        # echo -DVP1,LVDS1 > /proc/viafb/iga2/output_devices
+
+        Replace all iga1 output devices by CRT
+        # echo CRT > /proc/viafb/iga1/output_devices
+
+
 [Bootup with viafb]:
 --------------------
     Add the following line to your grub.conf:
-- 
1.6.3.2


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* Re: [PATCH 05/12] viafb: fix i2c_transfer error handling
  2010-09-19  7:33   ` Florian Tobias Schandinat
@ 2010-09-20 12:43     ` Jonathan Corbet
  -1 siblings, 0 replies; 27+ messages in thread
From: Jonathan Corbet @ 2010-09-20 12:43 UTC (permalink / raw)
  To: Florian Tobias Schandinat; +Cc: linux-fbdev, linux-kernel, Joseph Chan

On Sun, 19 Sep 2010 07:33:46 +0000
Florian Tobias Schandinat <FlorianSchandinat@gmx.de> wrote:

> i2c_transfer returns negative errno on error and number of messages
> processed on success. Just returning this value would give a poor
> interface as it is not obvious that you must compare with 2 after reading
> 1 or n bytes and with 1 after writing 1 byte to determine if it was
> successful. To avoid this error prone interface convert the error code
> of a successful read/write to zero and all other non-negative values to
> an negative error code.
> This fixes a regression introduced by
> 	via: Rationalize vt1636 detection
> which resulted in no longer detecting a VT1636 chip and therefore has
> broken the output in configurations wich contain this chip.

>From a quick look, all of these patches look like improvements to me.
This one, since it's a regression fix, should probably have a 
Cc: stable@kernel.org in it as well.

Acked-by: Jonathan Corbet <corbet@lwn.net>

jon

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH 05/12] viafb: fix i2c_transfer error handling
@ 2010-09-20 12:43     ` Jonathan Corbet
  0 siblings, 0 replies; 27+ messages in thread
From: Jonathan Corbet @ 2010-09-20 12:43 UTC (permalink / raw)
  To: Florian Tobias Schandinat; +Cc: linux-fbdev, linux-kernel, Joseph Chan

On Sun, 19 Sep 2010 07:33:46 +0000
Florian Tobias Schandinat <FlorianSchandinat@gmx.de> wrote:

> i2c_transfer returns negative errno on error and number of messages
> processed on success. Just returning this value would give a poor
> interface as it is not obvious that you must compare with 2 after reading
> 1 or n bytes and with 1 after writing 1 byte to determine if it was
> successful. To avoid this error prone interface convert the error code
> of a successful read/write to zero and all other non-negative values to
> an negative error code.
> This fixes a regression introduced by
> 	via: Rationalize vt1636 detection
> which resulted in no longer detecting a VT1636 chip and therefore has
> broken the output in configurations wich contain this chip.

From a quick look, all of these patches look like improvements to me.
This one, since it's a regression fix, should probably have a 
Cc: stable@kernel.org in it as well.

Acked-by: Jonathan Corbet <corbet@lwn.net>

jon

^ permalink raw reply	[flat|nested] 27+ messages in thread

* [PATCH v2] viafb: add interface for output device configuration
  2010-09-19  7:26   ` Florian Tobias Schandinat
@ 2010-09-21  1:27     ` Florian Tobias Schandinat
  -1 siblings, 0 replies; 27+ messages in thread
From: Florian Tobias Schandinat @ 2010-09-21  1:27 UTC (permalink / raw)
  To: linux-fbdev
  Cc: linux-kernel, Florian Tobias Schandinat, Joseph Chan, Andrew Morton

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>
---
v2: fix a build failure when FB_VIA_DIRECT_PROCFS is selected and a
    compile warning when it is not
---
 drivers/video/via/hw.c       |   53 +++++++++++++
 drivers/video/via/hw.h       |   10 +++
 drivers/video/via/viafbdev.c |  175 ++++++++++++++++++++++++++++++++++++------
 drivers/video/via/viafbdev.h |    2 +
 4 files changed, 216 insertions(+), 24 deletions(-)

diff --git a/drivers/video/via/hw.c b/drivers/video/via/hw.c
index 0330323..e65edce 100644
--- a/drivers/video/via/hw.c
+++ b/drivers/video/via/hw.c
@@ -718,6 +718,16 @@ static struct rgbLUT palLUT_table[] = {
 								     0x00}
 };
 
+static struct via_device_mapping device_mapping[] = {
+	{VIA_6C, "6C"},
+	{VIA_93, "93"},
+	{VIA_96, "96"},
+	{VIA_CRT, "CRT"},
+	{VIA_DVP1, "DVP1"},
+	{VIA_LVDS1, "LVDS1"},
+	{VIA_LVDS2, "LVDS2"}
+};
+
 static void load_fix_bit_crtc_reg(void);
 static void __devinit init_gfx_chip_info(int chip_type);
 static void __devinit init_tmds_chip_info(void);
@@ -1026,6 +1036,49 @@ void via_set_source(u32 devices, u8 iga)
 		set_lvds2_source(iga);
 }
 
+u32 via_parse_odev(char *input, char **end)
+{
+	char *ptr = input;
+	u32 odev = 0;
+	bool next = true;
+	int i, len;
+
+	while (next) {
+		next = false;
+		for (i = 0; i < ARRAY_SIZE(device_mapping); i++) {
+			len = strlen(device_mapping[i].name);
+			if (!strncmp(ptr, device_mapping[i].name, len)) {
+				odev |= device_mapping[i].device;
+				ptr += len;
+				if (*ptr == ',') {
+					ptr++;
+					next = true;
+				}
+			}
+		}
+	}
+
+	*end = ptr;
+	return odev;
+}
+
+void via_odev_to_seq(struct seq_file *m, u32 odev)
+{
+	int i, count = 0;
+
+	for (i = 0; i < ARRAY_SIZE(device_mapping); i++) {
+		if (odev & device_mapping[i].device) {
+			if (count > 0)
+				seq_putc(m, ',');
+
+			seq_puts(m, device_mapping[i].name);
+			count++;
+		}
+	}
+
+	seq_putc(m, '\n');
+}
+
 static void load_fix_bit_crtc_reg(void)
 {
 	/* always set to 1 */
diff --git a/drivers/video/via/hw.h b/drivers/video/via/hw.h
index 45dee39..657dbd6 100644
--- a/drivers/video/via/hw.h
+++ b/drivers/video/via/hw.h
@@ -22,6 +22,8 @@
 #ifndef __HW_H__
 #define __HW_H__
 
+#include <linux/seq_file.h>
+
 #include "viamode.h"
 #include "global.h"
 #include "via_modesetting.h"
@@ -882,6 +884,11 @@ struct pci_device_id_info {
 	u32 chip_index;
 };
 
+struct via_device_mapping {
+	u32 device;
+	const char *name;
+};
+
 extern unsigned int viafb_second_virtual_xres;
 extern int viafb_SAMM_ON;
 extern int viafb_dual_fb;
@@ -899,6 +906,9 @@ void viafb_load_reg(int timing_value, int viafb_load_reg_num,
 	      int io_type);
 void viafb_crt_disable(void);
 void viafb_crt_enable(void);
+void via_set_source(u32 devices, u8 iga);
+u32 via_parse_odev(char *input, char **end);
+void via_odev_to_seq(struct seq_file *m, u32 odev);
 void init_ad9389(void);
 /* Access I/O Function */
 void viafb_lock_crt(void);
diff --git a/drivers/video/via/viafbdev.c b/drivers/video/via/viafbdev.c
index 5a947b0..80ce43a 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 = {
 	.write		= viafb_vt1636_proc_write,
 };
 
-static void viafb_init_proc(struct proc_dir_entry **viafb_entry)
+#endif /* CONFIG_FB_VIA_DIRECT_PROCFS */
+
+static ssize_t odev_update(const char __user *buffer, size_t count, u32 *odev)
 {
-	*viafb_entry = proc_mkdir("viafb", NULL);
-	if (*viafb_entry) {
-		proc_create("dvp0", 0, *viafb_entry, &viafb_dvp0_proc_fops);
-		proc_create("dvp1", 0, *viafb_entry, &viafb_dvp1_proc_fops);
-		proc_create("dfph", 0, *viafb_entry, &viafb_dfph_proc_fops);
-		proc_create("dfpl", 0, *viafb_entry, &viafb_dfpl_proc_fops);
-		if (VT1636_LVDS == viaparinfo->chip_info->lvds_chip_info.
-			lvds_chip_name || VT1636_LVDS ==
-		    viaparinfo->chip_info->lvds_chip_info2.lvds_chip_name) {
-			proc_create("vt1636", 0, *viafb_entry, &viafb_vt1636_proc_fops);
-		}
+	char buf[64], *ptr = buf;
+	u32 devices;
+	bool add, sub;
+
+	if (count < 1 || count > 63)
+		return -EINVAL;
+	if (copy_from_user(&buf[0], buffer, count))
+		return -EFAULT;
+	buf[count] = '\0';
+	add = buf[0] == '+';
+	sub = buf[0] == '-';
+	if (add || sub)
+		ptr++;
+	devices = via_parse_odev(ptr, &ptr);
+	if (*ptr == '\n')
+		ptr++;
+	if (*ptr != 0)
+		return -EINVAL;
+	if (add)
+		*odev |= devices;
+	else if (sub)
+		*odev &= ~devices;
+	else
+		*odev = devices;
+	return count;
+}
+
+static int viafb_iga1_odev_proc_show(struct seq_file *m, void *v)
+{
+	via_odev_to_seq(m, viaparinfo->shared->iga1_devices);
+	return 0;
+}
+
+static int viafb_iga1_odev_proc_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, viafb_iga1_odev_proc_show, NULL);
+}
+
+static ssize_t viafb_iga1_odev_proc_write(struct file *file,
+	const char __user *buffer, size_t count, loff_t *pos)
+{
+	u32 dev_on, dev_off, dev_old, dev_new;
+	ssize_t res;
+
+	dev_old = dev_new = viaparinfo->shared->iga1_devices;
+	res = odev_update(buffer, count, &dev_new);
+	if (res != count)
+		return res;
+	dev_off = dev_old & ~dev_new;
+	dev_on = dev_new & ~dev_old;
+	viaparinfo->shared->iga1_devices = dev_new;
+	viaparinfo->shared->iga2_devices &= ~dev_new;
+	via_set_source(dev_new, IGA1);
+	return res;
+}
+
+static const struct file_operations viafb_iga1_odev_proc_fops = {
+	.owner		= THIS_MODULE,
+	.open		= viafb_iga1_odev_proc_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+	.write		= viafb_iga1_odev_proc_write,
+};
+
+static int viafb_iga2_odev_proc_show(struct seq_file *m, void *v)
+{
+	via_odev_to_seq(m, viaparinfo->shared->iga2_devices);
+	return 0;
+}
+
+static int viafb_iga2_odev_proc_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, viafb_iga2_odev_proc_show, NULL);
+}
+
+static ssize_t viafb_iga2_odev_proc_write(struct file *file,
+	const char __user *buffer, size_t count, loff_t *pos)
+{
+	u32 dev_on, dev_off, dev_old, dev_new;
+	ssize_t res;
+
+	dev_old = dev_new = viaparinfo->shared->iga2_devices;
+	res = odev_update(buffer, count, &dev_new);
+	if (res != count)
+		return res;
+	dev_off = dev_old & ~dev_new;
+	dev_on = dev_new & ~dev_old;
+	viaparinfo->shared->iga2_devices = dev_new;
+	viaparinfo->shared->iga1_devices &= ~dev_new;
+	via_set_source(dev_new, IGA2);
+	return res;
+}
+
+static const struct file_operations viafb_iga2_odev_proc_fops = {
+	.owner		= THIS_MODULE,
+	.open		= viafb_iga2_odev_proc_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+	.write		= viafb_iga2_odev_proc_write,
+};
+
+#define IS_VT1636(lvds_chip)	((lvds_chip).lvds_chip_name == VT1636_LVDS)
+static void viafb_init_proc(struct viafb_shared *shared)
+{
+	struct proc_dir_entry *iga1_entry, *iga2_entry,
+		*viafb_entry = proc_mkdir("viafb", NULL);
+
+	shared->proc_entry = viafb_entry;
+	if (viafb_entry) {
+#ifdef CONFIG_FB_VIA_DIRECT_PROCFS
+		proc_create("dvp0", 0, viafb_entry, &viafb_dvp0_proc_fops);
+		proc_create("dvp1", 0, viafb_entry, &viafb_dvp1_proc_fops);
+		proc_create("dfph", 0, viafb_entry, &viafb_dfph_proc_fops);
+		proc_create("dfpl", 0, viafb_entry, &viafb_dfpl_proc_fops);
+		if (IS_VT1636(shared->chip_info.lvds_chip_info)
+			|| IS_VT1636(shared->chip_info.lvds_chip_info2))
+			proc_create("vt1636", 0, viafb_entry,
+				&viafb_vt1636_proc_fops);
+#endif /* CONFIG_FB_VIA_DIRECT_PROCFS */
 
+		iga1_entry = proc_mkdir("iga1", viafb_entry);
+		shared->iga1_proc_entry = iga1_entry;
+		proc_create("output_devices", 0, iga1_entry,
+			&viafb_iga1_odev_proc_fops);
+		iga2_entry = proc_mkdir("iga2", viafb_entry);
+		shared->iga2_proc_entry = iga2_entry;
+		proc_create("output_devices", 0, iga2_entry,
+			&viafb_iga2_odev_proc_fops);
 	}
 }
-static void viafb_remove_proc(struct proc_dir_entry *viafb_entry)
+static void viafb_remove_proc(struct viafb_shared *shared)
 {
-	struct chip_information *chip_info = &viaparinfo->shared->chip_info;
+	struct proc_dir_entry *viafb_entry = shared->proc_entry,
+		*iga1_entry = shared->iga1_proc_entry,
+		*iga2_entry = shared->iga2_proc_entry;
 
+	if (!viafb_entry)
+		return;
+
+	remove_proc_entry("output_devices", iga2_entry);
+	remove_proc_entry("iga2", viafb_entry);
+	remove_proc_entry("output_devices", iga1_entry);
+	remove_proc_entry("iga1", viafb_entry);
+
+#ifdef CONFIG_FB_VIA_DIRECT_PROCFS
 	remove_proc_entry("dvp0", viafb_entry);/* parent dir */
 	remove_proc_entry("dvp1", viafb_entry);
 	remove_proc_entry("dfph", viafb_entry);
 	remove_proc_entry("dfpl", viafb_entry);
-	if (chip_info->lvds_chip_info.lvds_chip_name == VT1636_LVDS
-		|| chip_info->lvds_chip_info2.lvds_chip_name == VT1636_LVDS)
+	if (IS_VT1636(shared->chip_info.lvds_chip_info)
+		|| IS_VT1636(shared->chip_info.lvds_chip_info2))
 		remove_proc_entry("vt1636", viafb_entry);
+#endif /* CONFIG_FB_VIA_DIRECT_PROCFS */
 
 	remove_proc_entry("viafb", NULL);
 }
-
-#endif /* CONFIG_FB_VIA_DIRECT_PROCFS */
+#undef IS_VT1636
 
 static int parse_mode(const char *str, u32 *xres, u32 *yres)
 {
@@ -1671,9 +1802,7 @@ int __devinit via_fb_pci_probe(struct viafb_dev *vdev)
 		  viafbinfo->node, viafbinfo->fix.id, default_var.xres,
 		  default_var.yres, default_var.bits_per_pixel);
 
-#ifdef CONFIG_FB_VIA_DIRECT_PROCFS
-	viafb_init_proc(&viaparinfo->shared->proc_entry);
-#endif
+	viafb_init_proc(viaparinfo->shared);
 	viafb_init_dac(IGA2);
 	return 0;
 
@@ -1700,9 +1829,7 @@ void __devexit via_fb_pci_remove(struct pci_dev *pdev)
 	unregister_framebuffer(viafbinfo);
 	if (viafb_dual_fb)
 		unregister_framebuffer(viafbinfo1);
-#ifdef CONFIG_FB_VIA_DIRECT_PROCFS
-	viafb_remove_proc(viaparinfo->shared->proc_entry);
-#endif
+	viafb_remove_proc(viaparinfo->shared);
 	framebuffer_release(viafbinfo);
 	if (viafb_dual_fb)
 		framebuffer_release(viafbinfo1);
diff --git a/drivers/video/via/viafbdev.h b/drivers/video/via/viafbdev.h
index 945a47a..d66f963 100644
--- a/drivers/video/via/viafbdev.h
+++ b/drivers/video/via/viafbdev.h
@@ -44,6 +44,8 @@ struct viafb_shared {
 	u32 iga2_devices;
 
 	struct proc_dir_entry *proc_entry;	/*viafb proc entry */
+	struct proc_dir_entry *iga1_proc_entry;
+	struct proc_dir_entry *iga2_proc_entry;
 	struct viafb_dev *vdev;			/* Global dev info */
 
 	/* All the information will be needed to set engine */
-- 
1.6.3.2


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v2] viafb: add interface for output device configuration
@ 2010-09-21  1:27     ` Florian Tobias Schandinat
  0 siblings, 0 replies; 27+ messages in thread
From: Florian Tobias Schandinat @ 2010-09-21  1:27 UTC (permalink / raw)
  To: linux-fbdev
  Cc: linux-kernel, Florian Tobias Schandinat, Joseph Chan, Andrew Morton

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>
---
v2: fix a build failure when FB_VIA_DIRECT_PROCFS is selected and a
    compile warning when it is not
---
 drivers/video/via/hw.c       |   53 +++++++++++++
 drivers/video/via/hw.h       |   10 +++
 drivers/video/via/viafbdev.c |  175 ++++++++++++++++++++++++++++++++++++------
 drivers/video/via/viafbdev.h |    2 +
 4 files changed, 216 insertions(+), 24 deletions(-)

diff --git a/drivers/video/via/hw.c b/drivers/video/via/hw.c
index 0330323..e65edce 100644
--- a/drivers/video/via/hw.c
+++ b/drivers/video/via/hw.c
@@ -718,6 +718,16 @@ static struct rgbLUT palLUT_table[] = {
 								     0x00}
 };
 
+static struct via_device_mapping device_mapping[] = {
+	{VIA_6C, "6C"},
+	{VIA_93, "93"},
+	{VIA_96, "96"},
+	{VIA_CRT, "CRT"},
+	{VIA_DVP1, "DVP1"},
+	{VIA_LVDS1, "LVDS1"},
+	{VIA_LVDS2, "LVDS2"}
+};
+
 static void load_fix_bit_crtc_reg(void);
 static void __devinit init_gfx_chip_info(int chip_type);
 static void __devinit init_tmds_chip_info(void);
@@ -1026,6 +1036,49 @@ void via_set_source(u32 devices, u8 iga)
 		set_lvds2_source(iga);
 }
 
+u32 via_parse_odev(char *input, char **end)
+{
+	char *ptr = input;
+	u32 odev = 0;
+	bool next = true;
+	int i, len;
+
+	while (next) {
+		next = false;
+		for (i = 0; i < ARRAY_SIZE(device_mapping); i++) {
+			len = strlen(device_mapping[i].name);
+			if (!strncmp(ptr, device_mapping[i].name, len)) {
+				odev |= device_mapping[i].device;
+				ptr += len;
+				if (*ptr = ',') {
+					ptr++;
+					next = true;
+				}
+			}
+		}
+	}
+
+	*end = ptr;
+	return odev;
+}
+
+void via_odev_to_seq(struct seq_file *m, u32 odev)
+{
+	int i, count = 0;
+
+	for (i = 0; i < ARRAY_SIZE(device_mapping); i++) {
+		if (odev & device_mapping[i].device) {
+			if (count > 0)
+				seq_putc(m, ',');
+
+			seq_puts(m, device_mapping[i].name);
+			count++;
+		}
+	}
+
+	seq_putc(m, '\n');
+}
+
 static void load_fix_bit_crtc_reg(void)
 {
 	/* always set to 1 */
diff --git a/drivers/video/via/hw.h b/drivers/video/via/hw.h
index 45dee39..657dbd6 100644
--- a/drivers/video/via/hw.h
+++ b/drivers/video/via/hw.h
@@ -22,6 +22,8 @@
 #ifndef __HW_H__
 #define __HW_H__
 
+#include <linux/seq_file.h>
+
 #include "viamode.h"
 #include "global.h"
 #include "via_modesetting.h"
@@ -882,6 +884,11 @@ struct pci_device_id_info {
 	u32 chip_index;
 };
 
+struct via_device_mapping {
+	u32 device;
+	const char *name;
+};
+
 extern unsigned int viafb_second_virtual_xres;
 extern int viafb_SAMM_ON;
 extern int viafb_dual_fb;
@@ -899,6 +906,9 @@ void viafb_load_reg(int timing_value, int viafb_load_reg_num,
 	      int io_type);
 void viafb_crt_disable(void);
 void viafb_crt_enable(void);
+void via_set_source(u32 devices, u8 iga);
+u32 via_parse_odev(char *input, char **end);
+void via_odev_to_seq(struct seq_file *m, u32 odev);
 void init_ad9389(void);
 /* Access I/O Function */
 void viafb_lock_crt(void);
diff --git a/drivers/video/via/viafbdev.c b/drivers/video/via/viafbdev.c
index 5a947b0..80ce43a 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 = {
 	.write		= viafb_vt1636_proc_write,
 };
 
-static void viafb_init_proc(struct proc_dir_entry **viafb_entry)
+#endif /* CONFIG_FB_VIA_DIRECT_PROCFS */
+
+static ssize_t odev_update(const char __user *buffer, size_t count, u32 *odev)
 {
-	*viafb_entry = proc_mkdir("viafb", NULL);
-	if (*viafb_entry) {
-		proc_create("dvp0", 0, *viafb_entry, &viafb_dvp0_proc_fops);
-		proc_create("dvp1", 0, *viafb_entry, &viafb_dvp1_proc_fops);
-		proc_create("dfph", 0, *viafb_entry, &viafb_dfph_proc_fops);
-		proc_create("dfpl", 0, *viafb_entry, &viafb_dfpl_proc_fops);
-		if (VT1636_LVDS = viaparinfo->chip_info->lvds_chip_info.
-			lvds_chip_name || VT1636_LVDS =
-		    viaparinfo->chip_info->lvds_chip_info2.lvds_chip_name) {
-			proc_create("vt1636", 0, *viafb_entry, &viafb_vt1636_proc_fops);
-		}
+	char buf[64], *ptr = buf;
+	u32 devices;
+	bool add, sub;
+
+	if (count < 1 || count > 63)
+		return -EINVAL;
+	if (copy_from_user(&buf[0], buffer, count))
+		return -EFAULT;
+	buf[count] = '\0';
+	add = buf[0] = '+';
+	sub = buf[0] = '-';
+	if (add || sub)
+		ptr++;
+	devices = via_parse_odev(ptr, &ptr);
+	if (*ptr = '\n')
+		ptr++;
+	if (*ptr != 0)
+		return -EINVAL;
+	if (add)
+		*odev |= devices;
+	else if (sub)
+		*odev &= ~devices;
+	else
+		*odev = devices;
+	return count;
+}
+
+static int viafb_iga1_odev_proc_show(struct seq_file *m, void *v)
+{
+	via_odev_to_seq(m, viaparinfo->shared->iga1_devices);
+	return 0;
+}
+
+static int viafb_iga1_odev_proc_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, viafb_iga1_odev_proc_show, NULL);
+}
+
+static ssize_t viafb_iga1_odev_proc_write(struct file *file,
+	const char __user *buffer, size_t count, loff_t *pos)
+{
+	u32 dev_on, dev_off, dev_old, dev_new;
+	ssize_t res;
+
+	dev_old = dev_new = viaparinfo->shared->iga1_devices;
+	res = odev_update(buffer, count, &dev_new);
+	if (res != count)
+		return res;
+	dev_off = dev_old & ~dev_new;
+	dev_on = dev_new & ~dev_old;
+	viaparinfo->shared->iga1_devices = dev_new;
+	viaparinfo->shared->iga2_devices &= ~dev_new;
+	via_set_source(dev_new, IGA1);
+	return res;
+}
+
+static const struct file_operations viafb_iga1_odev_proc_fops = {
+	.owner		= THIS_MODULE,
+	.open		= viafb_iga1_odev_proc_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+	.write		= viafb_iga1_odev_proc_write,
+};
+
+static int viafb_iga2_odev_proc_show(struct seq_file *m, void *v)
+{
+	via_odev_to_seq(m, viaparinfo->shared->iga2_devices);
+	return 0;
+}
+
+static int viafb_iga2_odev_proc_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, viafb_iga2_odev_proc_show, NULL);
+}
+
+static ssize_t viafb_iga2_odev_proc_write(struct file *file,
+	const char __user *buffer, size_t count, loff_t *pos)
+{
+	u32 dev_on, dev_off, dev_old, dev_new;
+	ssize_t res;
+
+	dev_old = dev_new = viaparinfo->shared->iga2_devices;
+	res = odev_update(buffer, count, &dev_new);
+	if (res != count)
+		return res;
+	dev_off = dev_old & ~dev_new;
+	dev_on = dev_new & ~dev_old;
+	viaparinfo->shared->iga2_devices = dev_new;
+	viaparinfo->shared->iga1_devices &= ~dev_new;
+	via_set_source(dev_new, IGA2);
+	return res;
+}
+
+static const struct file_operations viafb_iga2_odev_proc_fops = {
+	.owner		= THIS_MODULE,
+	.open		= viafb_iga2_odev_proc_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+	.write		= viafb_iga2_odev_proc_write,
+};
+
+#define IS_VT1636(lvds_chip)	((lvds_chip).lvds_chip_name = VT1636_LVDS)
+static void viafb_init_proc(struct viafb_shared *shared)
+{
+	struct proc_dir_entry *iga1_entry, *iga2_entry,
+		*viafb_entry = proc_mkdir("viafb", NULL);
+
+	shared->proc_entry = viafb_entry;
+	if (viafb_entry) {
+#ifdef CONFIG_FB_VIA_DIRECT_PROCFS
+		proc_create("dvp0", 0, viafb_entry, &viafb_dvp0_proc_fops);
+		proc_create("dvp1", 0, viafb_entry, &viafb_dvp1_proc_fops);
+		proc_create("dfph", 0, viafb_entry, &viafb_dfph_proc_fops);
+		proc_create("dfpl", 0, viafb_entry, &viafb_dfpl_proc_fops);
+		if (IS_VT1636(shared->chip_info.lvds_chip_info)
+			|| IS_VT1636(shared->chip_info.lvds_chip_info2))
+			proc_create("vt1636", 0, viafb_entry,
+				&viafb_vt1636_proc_fops);
+#endif /* CONFIG_FB_VIA_DIRECT_PROCFS */
 
+		iga1_entry = proc_mkdir("iga1", viafb_entry);
+		shared->iga1_proc_entry = iga1_entry;
+		proc_create("output_devices", 0, iga1_entry,
+			&viafb_iga1_odev_proc_fops);
+		iga2_entry = proc_mkdir("iga2", viafb_entry);
+		shared->iga2_proc_entry = iga2_entry;
+		proc_create("output_devices", 0, iga2_entry,
+			&viafb_iga2_odev_proc_fops);
 	}
 }
-static void viafb_remove_proc(struct proc_dir_entry *viafb_entry)
+static void viafb_remove_proc(struct viafb_shared *shared)
 {
-	struct chip_information *chip_info = &viaparinfo->shared->chip_info;
+	struct proc_dir_entry *viafb_entry = shared->proc_entry,
+		*iga1_entry = shared->iga1_proc_entry,
+		*iga2_entry = shared->iga2_proc_entry;
 
+	if (!viafb_entry)
+		return;
+
+	remove_proc_entry("output_devices", iga2_entry);
+	remove_proc_entry("iga2", viafb_entry);
+	remove_proc_entry("output_devices", iga1_entry);
+	remove_proc_entry("iga1", viafb_entry);
+
+#ifdef CONFIG_FB_VIA_DIRECT_PROCFS
 	remove_proc_entry("dvp0", viafb_entry);/* parent dir */
 	remove_proc_entry("dvp1", viafb_entry);
 	remove_proc_entry("dfph", viafb_entry);
 	remove_proc_entry("dfpl", viafb_entry);
-	if (chip_info->lvds_chip_info.lvds_chip_name = VT1636_LVDS
-		|| chip_info->lvds_chip_info2.lvds_chip_name = VT1636_LVDS)
+	if (IS_VT1636(shared->chip_info.lvds_chip_info)
+		|| IS_VT1636(shared->chip_info.lvds_chip_info2))
 		remove_proc_entry("vt1636", viafb_entry);
+#endif /* CONFIG_FB_VIA_DIRECT_PROCFS */
 
 	remove_proc_entry("viafb", NULL);
 }
-
-#endif /* CONFIG_FB_VIA_DIRECT_PROCFS */
+#undef IS_VT1636
 
 static int parse_mode(const char *str, u32 *xres, u32 *yres)
 {
@@ -1671,9 +1802,7 @@ int __devinit via_fb_pci_probe(struct viafb_dev *vdev)
 		  viafbinfo->node, viafbinfo->fix.id, default_var.xres,
 		  default_var.yres, default_var.bits_per_pixel);
 
-#ifdef CONFIG_FB_VIA_DIRECT_PROCFS
-	viafb_init_proc(&viaparinfo->shared->proc_entry);
-#endif
+	viafb_init_proc(viaparinfo->shared);
 	viafb_init_dac(IGA2);
 	return 0;
 
@@ -1700,9 +1829,7 @@ void __devexit via_fb_pci_remove(struct pci_dev *pdev)
 	unregister_framebuffer(viafbinfo);
 	if (viafb_dual_fb)
 		unregister_framebuffer(viafbinfo1);
-#ifdef CONFIG_FB_VIA_DIRECT_PROCFS
-	viafb_remove_proc(viaparinfo->shared->proc_entry);
-#endif
+	viafb_remove_proc(viaparinfo->shared);
 	framebuffer_release(viafbinfo);
 	if (viafb_dual_fb)
 		framebuffer_release(viafbinfo1);
diff --git a/drivers/video/via/viafbdev.h b/drivers/video/via/viafbdev.h
index 945a47a..d66f963 100644
--- a/drivers/video/via/viafbdev.h
+++ b/drivers/video/via/viafbdev.h
@@ -44,6 +44,8 @@ struct viafb_shared {
 	u32 iga2_devices;
 
 	struct proc_dir_entry *proc_entry;	/*viafb proc entry */
+	struct proc_dir_entry *iga1_proc_entry;
+	struct proc_dir_entry *iga2_proc_entry;
 	struct viafb_dev *vdev;			/* Global dev info */
 
 	/* All the information will be needed to set engine */
-- 
1.6.3.2


^ permalink raw reply related	[flat|nested] 27+ messages in thread

end of thread, other threads:[~2010-09-21  1:27 UTC | newest]

Thread overview: 27+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-09-19  7:26 [PATCH 00/12] viafb output device rework - part 2 Florian Tobias Schandinat
2010-09-19  7:26 ` [PATCH 01/12] viafb: add interface for output device configuration Florian Tobias Schandinat
2010-09-19  7:26   ` Florian Tobias Schandinat
2010-09-21  1:27   ` [PATCH v2] " Florian Tobias Schandinat
2010-09-21  1:27     ` Florian Tobias Schandinat
2010-09-19  7:26 ` [PATCH 02/12] viafb: limit LCD code impact Florian Tobias Schandinat
2010-09-19  7:26   ` Florian Tobias Schandinat
2010-09-19  7:26 ` [PATCH 03/12] viafb: introduce per output device power management Florian Tobias Schandinat
2010-09-19  7:26   ` Florian Tobias Schandinat
2010-09-19  7:26 ` [PATCH 04/12] viafb: vt1636 cleanup Florian Tobias Schandinat
2010-09-19  7:33 ` [PATCH 05/12] viafb: fix i2c_transfer error handling Florian Tobias Schandinat
2010-09-19  7:33   ` Florian Tobias Schandinat
2010-09-20 12:43   ` Jonathan Corbet
2010-09-20 12:43     ` Jonathan Corbet
2010-09-19  7:33 ` [PATCH 06/12] viafb: enable I2C for CRT Florian Tobias Schandinat
2010-09-19  7:33   ` Florian Tobias Schandinat
2010-09-19  7:33 ` [PATCH 07/12] viafb: reduce I2C timeout and delay Florian Tobias Schandinat
2010-09-19  7:33   ` Florian Tobias Schandinat
2010-09-19  7:33 ` [PATCH 08/12] viafb: add function to change sync polarity per device Florian Tobias Schandinat
2010-09-19  7:33   ` Florian Tobias Schandinat
2010-09-19  7:33 ` [PATCH 09/12] viafb: set sync polarity for all output devices Florian Tobias Schandinat
2010-09-19  7:33   ` Florian Tobias Schandinat
2010-09-19  7:39 ` [PATCH 10/12] viafb: add a mapping of supported " Florian Tobias Schandinat
2010-09-19  7:39 ` [PATCH 11/12] viafb: rename " Florian Tobias Schandinat
2010-09-19  7:39   ` Florian Tobias Schandinat
2010-09-19  7:39 ` [PATCH 12/12] viafb: add documentation for proc interface Florian Tobias Schandinat
2010-09-19  7:39   ` Florian Tobias Schandinat

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.