[PATCH] dovefb: add more config options to the display controller (DCON)

Eric Miao eric.miao at canonical.com
Mon Aug 16 08:20:04 UTC 2010


It would be good if all the possibilities of PortA and PortB combinations in the
Display Controller can be exposed, instead of simply having either port_a or
port_b being enabled or not. Idea?

One more thing is - can be decide lcd0_enable and lcd1_enable depending
on the dovefb_mach_info * pointer passed to clcd_platform_init(), it seems to
get overly designed to have these two parameters. And lcd0_enable/lcd1_enable
seems to have no relationship with DCON configuration, and some of the code
can be clean'ed up?

Green?


commit 84a7f186460e6b5d1428de51cd7093404724125d
Author: Eric Miao <eric.miao at canonical.com>
Date:   Sat Aug 14 21:06:46 2010 +0800

    dovefb: add more config options to the display controller (DCON)

    Signed-off-by: Eric Miao <eric.miao at canonical.com>

diff --git a/arch/arm/mach-dove/clcd.c b/arch/arm/mach-dove/clcd.c
index 70e9f7d..b1a8364 100755
--- a/arch/arm/mach-dove/clcd.c
+++ b/arch/arm/mach-dove/clcd.c
@@ -528,8 +528,7 @@ static struct resource dcon_res[] = {
 };

 static struct dovedcon_mach_info dcon_data = {
-	.port_a = 1,
-	.port_b = 1,
+	.mode	= PORTA_ENABLE | PORTB_ENABLE,
 };

 static struct platform_device dcon_platform_device = {
@@ -565,7 +564,8 @@ int clcd_platform_init(struct dovefb_mach_info
*lcd0_dmi_data,
 		       struct dovefb_mach_info *lcd0_vid_dmi_data,
 		       struct dovefb_mach_info *lcd1_dmi_data,
 		       struct dovefb_mach_info *lcd1_vid_dmi_data,
-		       struct dovebl_platform_data *backlight_data)
+		       struct dovebl_platform_data *backlight_data,
+		       struct dovedcon_mach_info *dcon)
 {
 	u32 total_x, total_y, i;
 	u64 div_result;
@@ -632,16 +632,21 @@ int clcd_platform_init(struct dovefb_mach_info
*lcd0_dmi_data,
 		lcd_accurate_clock = 0;

 #ifdef CONFIG_FB_DOVE_DCON
-	if (lcd0_enable || lcd1_enable) {
-		if (lcd0_enable)
-			dcon_data.port_a = 1;
-		if (lcd1_enable)
-			dcon_data.port_b = 1;
+	if (dcon)
+		memcpy(&dcon_data, dcon, sizeof(*dcon));
+	else {
+		/* generate default according to cmdline */
+		if (lcd0_enable || lcd1_enable) {
+			if (lcd0_enable)
+				dcon_data.mode |= PORTA_ENABLE;
+			if (lcd1_enable)
+				dcon_data.mode |= PORTB_ENABLE;
 #ifdef CONFIG_FB_DOVE_CLCD_DCONB_BYPASS0
-		dcon_data.port_b = 1;
+			dcon_data.mode |= PORTB_LCD0_BYPASS;
 #endif
-		platform_device_register(&dcon_platform_device);
+		}
 	}
+	platform_device_register(&dcon_platform_device);
 #endif

 #ifdef CONFIG_BACKLIGHT_DOVE
diff --git a/arch/arm/mach-dove/dove-db-setup.c
b/arch/arm/mach-dove/dove-db-setup.c
index 52d66fe..bd38ca0 100755
--- a/arch/arm/mach-dove/dove-db-setup.c
+++ b/arch/arm/mach-dove/dove-db-setup.c
@@ -381,7 +381,7 @@ void __init dove_db_clcd_init(void) {
 	}
 	clcd_platform_init(lcd0_dmi, lcd0_vid_dmi,
 			   &dove_db_lcd1_dmi, &dove_db_lcd1_vid_dmi,
-			   &dove_db_backlight_data);
+			   &dove_db_backlight_data, NULL);

 #endif /* CONFIG_FB_DOVE */
 }
diff --git a/arch/arm/mach-dove/dove-front-panel-common.c
b/arch/arm/mach-dove/dove-front-panel-common.c
index 3fddf67..9b97a22 100755
--- a/arch/arm/mach-dove/dove-front-panel-common.c
+++ b/arch/arm/mach-dove/dove-front-panel-common.c
@@ -237,6 +237,6 @@ void __init dove_fp_clcd_init(void) {
 #ifdef CONFIG_FB_DOVE
 	clcd_platform_init(&dove_lcd0_dmi, &dove_lcd0_vid_dmi,
 			   &dove_lcd1_dmi, &dove_lcd1_vid_dmi,
-			   &fp_backlight_data);
+			   &fp_backlight_data, NULL);
 #endif /* CONFIG_FB_DOVE */
 }
diff --git a/arch/arm/mach-dove/dove-rd-avng-setup.c
b/arch/arm/mach-dove/dove-rd-avng-setup.c
index a5e832e..947935a 100755
--- a/arch/arm/mach-dove/dove-rd-avng-setup.c
+++ b/arch/arm/mach-dove/dove-rd-avng-setup.c
@@ -230,7 +230,7 @@ void __init dove_rd_avng_clcd_init(void) {
 #ifdef CONFIG_FB_DOVE
 	clcd_platform_init(&dove_rd_avng_lcd0_dmi, &dove_rd_avng_lcd0_vid_dmi,
 			   &dove_rd_avng_lcd1_dmi, &dove_rd_avng_lcd1_vid_dmi,
-			   &dove_rd_avng_backlight_data);
+			   &dove_rd_avng_backlight_data, NULL);
 #endif /* CONFIG_FB_DOVE */
 }

diff --git a/arch/arm/mach-dove/dove-videoplug-setup.c
b/arch/arm/mach-dove/dove-videoplug-setup.c
index 37a366e..ff226a1 100644
--- a/arch/arm/mach-dove/dove-videoplug-setup.c
+++ b/arch/arm/mach-dove/dove-videoplug-setup.c
@@ -129,7 +129,7 @@ static struct dove_ssp_platform_data
dove_ssp_platform_data = {
 void __init dove_videoplug_clcd_init(void) {
 #ifdef CONFIG_FB_DOVE
 	clcd_platform_init(&dove_videoplug_lcd0_dmi, &dove_videoplug_lcd0_vid_dmi,
-			   NULL, NULL, NULL);
+			   NULL, NULL, NULL, NULL);
 #endif /* CONFIG_FB_DOVE */
 }

diff --git a/drivers/video/marvell/dovedcon.c b/drivers/video/marvell/dovedcon.c
index 1f3fa24..4de60c8 100755
--- a/drivers/video/marvell/dovedcon.c
+++ b/drivers/video/marvell/dovedcon.c
@@ -15,7 +15,18 @@

 #include <video/dovedcon.h>

+#define DCON_CTRL0_VGA_CLK_DISABLE	(1 << 25)
+#define DCON_CTRL0_DCON_CLK_DISABLE	(1 << 24)
+#define DCON_CTRL0_DCON_RESET		(1 << 23)
+#define DCON_CTRL0_OUTPUT_DELAY		(1 << 22)
+#define DCON_CTRL0_LCD_DISABLE		(1 << 17)
+#define DCON_CTRL0_REVERSE_SCAN		(1 << 10)
+#define DCON_CTRL0_PORTB_SELECT		(3 << 8)
+#define DCON_CTRL0_PORTA_SELECT		(3 << 6)
+#define DCON_CTRL0_LBUF_EN		(1 << 5)
+
 #define VGA_CHANNEL_DEFAULT	0x90C78
+
 static int dovedcon_enable(struct dovedcon_info *ddi)
 {
 	unsigned int channel_ctrl;
@@ -30,36 +41,44 @@ static int dovedcon_enable(struct dovedcon_info *ddi)
 	/* enable lcd0 pass to PortB */
 	ctrl0 &= ~(0x3 << 8);
 	ctrl0 |= (0x1 << 8);
-	ddi->port_b = 1;
+	ddi->mode |= PORTB_ENABLE;
 #endif
-	
-	/*
-	 * Enable VGA clock, clear it to enable.
-	 */
-	ctrl0 &= ~(ddi->port_b << 25);	
-		
-	/*
-	 * Enable LCD clock, clear it to enable
-	 */
-	ctrl0 &= ~(ddi->port_a << 24);	

-	/*
-	 * Enable LCD Parallel Interface, clear it to enable
-	 */
-	ctrl0 &= ~(0x1 << 17);	
+	/* Enable DCON clock if either port is enabled */
+	if (ddi->mode & (PORTA_ENABLE | PORTB_ENABLE))
+		ctrl0 &= ~DCON_CTRL0_DCON_CLK_DISABLE;

-	writel(ctrl0, ddi->reg_base+DCON_CTRL0);
+	if (ddi->mode & PORTA_ENABLE) {
+		/* Enable LCD Parallel Interface on PortA */
+		ctrl0 &= ~DCON_CTRL0_LCD_DISABLE;
+
+		/* Configure PortA mode */
+		ctrl0 &= ~DCON_CTRL0_PORTA_SELECT;
+		ctrl0 |= PORTA_MODE(ddi->mode) << 6;
+	}
+
+	if (ddi->mode & PORTB_ENABLE) {
+		/* Enable VGA clock on PortB */
+		ctrl0 &= ~DCON_CTRL0_VGA_CLK_DISABLE;
+
+		/* Configure PortB mode */
+		ctrl0 &= ~DCON_CTRL0_PORTB_SELECT;
+		ctrl0 |= PORTB_MODE(ddi->mode) << 8;
+	}
+
+	writel(ctrl0, ddi->reg_base + DCON_CTRL0);

 	/*
 	 * Configure VGA data channel and power on them.
 	 */
-	if (ddi->port_b) {
+	if (ddi->mode & PORTB_ENABLE) {
 		channel_ctrl = VGA_CHANNEL_DEFAULT;
-		writel(channel_ctrl, ddi->reg_base+DCON_VGA_DAC_CHANNEL_A_CTRL);
-		writel(channel_ctrl, ddi->reg_base+DCON_VGA_DAC_CHANNEL_B_CTRL);
-		writel(channel_ctrl, ddi->reg_base+DCON_VGA_DAC_CHANNEL_C_CTRL);
+		writel(channel_ctrl, ddi->reg_base + DCON_VGA_DAC_CHANNEL_A_CTRL);
+		writel(channel_ctrl, ddi->reg_base + DCON_VGA_DAC_CHANNEL_B_CTRL);
+		writel(channel_ctrl, ddi->reg_base + DCON_VGA_DAC_CHANNEL_C_CTRL);
 	}

+	pr_debug("%s: DCON_CTRL0 = 0x%08x\n", __func__, ctrl0);
 	return 0;
 }

@@ -171,7 +190,7 @@ static ssize_t dcon_show_pa_clk(struct device *dev,

 	ddi = dev_get_drvdata(dev);

-	return sprintf(buf, "%d\n", ddi->port_a);
+	return sprintf(buf, "%d\n", (ddi->mode & PORTA_ENABLE) ? 1 : 0);
 }

 static ssize_t dcon_ena_pa_clk(struct device *dev,
@@ -179,38 +198,26 @@ static ssize_t dcon_ena_pa_clk(struct device *dev,
 {
 	int rc;
 	struct dovedcon_info *ddi;
-	unsigned long ena_clk;
+	unsigned long ena_clk, ctrl0;

 	ddi = dev_get_drvdata(dev);
 	rc = strict_strtoul(buf, 0, &ena_clk);
 	if (rc)
 		return rc;

-	rc = -ENXIO;
-	
-	if (ddi->port_a != ena_clk) {
-		unsigned int ctrl0;
-
-		ddi->port_a = ena_clk;
-
-		/*
-		 * Get current configuration of CTRL0
-		 */
-		ctrl0 = readl(ddi->reg_base+DCON_CTRL0);
-
-		/* enable or disable LCD clk. */
-		if (0 == ddi->port_a)
-			ctrl0 |= (0x1 << 24);
-		else
-			ctrl0 &= ~(0x1 << 24);
-
-		/* Apply setting. */
-		writel(ctrl0, ddi->reg_base+DCON_CTRL0);
+	if ((ddi->mode & PORTA_ENABLE) && !ena_clk) {
+		ctrl0 = readl(ddi->reg_base + DCON_CTRL0);
+		ctrl0 &= ~DCON_CTRL0_DCON_CLK_DISABLE;
+		writel(ctrl0, ddi->reg_base + DCON_CTRL0);
 	}

-	rc = count;
+	if (ena_clk && !(ddi->mode & PORTA_ENABLE)) {
+		ctrl0 = readl(ddi->reg_base + DCON_CTRL0);
+		ctrl0 |= DCON_CTRL0_DCON_CLK_DISABLE;
+		writel(ctrl0, ddi->reg_base + DCON_CTRL0);
+	}

-	return rc;
+	return count;
 }

 static ssize_t dcon_show_pb_clk(struct device *dev,
@@ -220,7 +227,7 @@ static ssize_t dcon_show_pb_clk(struct device *dev,

 	ddi = dev_get_drvdata(dev);

-	return sprintf(buf, "%d\n", ddi->port_b);
+	return sprintf(buf, "%d\n", (ddi->mode & PORTB_ENABLE) ? 1 : 0);
 }

 static ssize_t dcon_ena_pb_clk(struct device *dev,
@@ -228,36 +235,26 @@ static ssize_t dcon_ena_pb_clk(struct device *dev,
 {
 	int rc;
 	struct dovedcon_info *ddi;
-	unsigned long ena_clk;
+	unsigned long ena_clk, ctrl0;

 	ddi = dev_get_drvdata(dev);
 	rc = strict_strtoul(buf, 0, &ena_clk);
 	if (rc)
 		return rc;

-	if (ddi->port_b != ena_clk) {
-		unsigned int ctrl0;
-
-		ddi->port_b = ena_clk;
-
-		/*
-		 * Get current configuration of CTRL0
-		 */
-		ctrl0 = readl(ddi->reg_base+DCON_CTRL0);
-
-		/* enable or disable LCD clk. */
-		if (0 == ddi->port_b)
-			ctrl0 |= (0x1 << 25);
-		else
-			ctrl0 &= ~(0x1 << 25);
-
-		/* Apply setting. */
-		writel(ctrl0, ddi->reg_base+DCON_CTRL0);
+	if ((ddi->mode & PORTB_ENABLE) && !ena_clk) {
+		ctrl0 = readl(ddi->reg_base + DCON_CTRL0);
+		ctrl0 &= ~DCON_CTRL0_VGA_CLK_DISABLE;
+		writel(ctrl0, ddi->reg_base + DCON_CTRL0);
 	}

-	rc = count;
+	if (ena_clk && !(ddi->mode & PORTB_ENABLE)) {
+		ctrl0 = readl(ddi->reg_base + DCON_CTRL0);
+		ctrl0 |= DCON_CTRL0_VGA_CLK_DISABLE;
+		writel(ctrl0, ddi->reg_base + DCON_CTRL0);
+	}

-	return rc;
+	return count;
 }

 static ssize_t dcon_show_pa_mode(struct device *dev,
@@ -576,8 +573,7 @@ static int __init dovedcon_probe(struct
platform_device *pdev)
 	if (!IS_ERR(ddi->clk))
 		clk_enable(ddi->clk);

-	ddi->port_a = ddmi->port_a;
-	ddi->port_b = ddmi->port_b;
+	ddi->mode = ddmi->mode;

 	/* Initialize DCON hardware */
 	dovedcon_enable(ddi);
diff --git a/include/video/dovedcon.h b/include/video/dovedcon.h
index a9ec18b..3bfa02d 100644
--- a/include/video/dovedcon.h
+++ b/include/video/dovedcon.h
@@ -43,17 +43,29 @@

 #ifdef __KERNEL__

+#define PORTA_ENABLE		(1 << 15)
+#define PORTA_LCD0_BYPASS	(PORTA_ENABLE | 0)
+#define PORTA_OLPC_MODE		(PORTA_ENABLE | 1)
+#define PORTA_DUAL_VIEW		(PORTA_ENABLE | 2)
+#define PORTA_EXT_DCON		(PORTA_ENABLE | 3)
+
+#define PORTB_ENABLE		(1 << 31)
+#define PORTB_LCD1_BYPASS	(PORTB_ENABLE | (0 << 16))
+#define PORTB_LCD0_BYPASS	(PORTB_ENABLE | (1 << 16))
+#define PORTB_DCON_COPY		(PORTB_ENABLE | (3 << 16))
+
+#define PORTA_MODE(m)		((m) & 0xf)
+#define PORTB_MODE(m)		(((m) >> 16) & 0xf)
+
 struct dovedcon_mach_info {
-	unsigned int port_a;
-	unsigned int port_b;
+	uint32_t	mode;
 };

 struct dovedcon_info {
 	void			*reg_base;
 	struct clk		*clk;
-	struct notifier_block fb_notif;
-	unsigned int port_a;
-	unsigned int port_b;
+	uint32_t		mode;
+	struct notifier_block	fb_notif;
 };

 #define to_dcon_device(obj) container_of(obj, struct dovedcon_info, dev)
diff --git a/include/video/dovefb.h b/include/video/dovefb.h
index 8f9f058..b2fb7c4 100755
--- a/include/video/dovefb.h
+++ b/include/video/dovefb.h
@@ -20,6 +20,7 @@
 /*              Header Files                      */
 /* ---------------------------------------------- */
 #include <linux/fb.h>
+#include <video/dovedcon.h>

 /* ---------------------------------------------- */
 /*              IOCTL Definition                  */
@@ -476,7 +477,8 @@ int clcd_platform_init(struct dovefb_mach_info
*lcd0_dmi_data,
 		       struct dovefb_mach_info *lcd0_vid_dmi_data,
 		       struct dovefb_mach_info *lcd1_dmi_data,
 		       struct dovefb_mach_info *lcd1_vid_dmi_data,
-		       struct dovebl_platform_data *backlight_data);
+		       struct dovebl_platform_data *backlight_data,
+		       struct dovedcon_mach_info *dcon);


 #endif /* _KERNEL_ */




More information about the kernel-team mailing list