@@ -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
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 */
}
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 */
}
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 */
}
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 */
}
@@ -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);
@@ -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)
@@ -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);