[PATCH] dovefb: add more config options to the display controller (DCON)
Brad Figg
brad.figg at canonical.com
Tue Aug 17 02:26:33 UTC 2010
On 08/16/2010 07:05 PM, Eric Miao wrote:
> On Tue, Aug 17, 2010 at 2:56 AM, Brad Figg<brad.figg at canonical.com> wrote:
>> On 08/16/2010 01:20 AM, Eric Miao wrote:
>>> 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_ */
>>>
>>
>> Eric,
>>
>> I can't tell if this is a request to have this patch applied to
>> Lucid or this is just a discussion of a potential patch.
>>
>
> Brad,
>
> Sorry I should have made it clear. It was supposed to be RFC only
> and not targeting for Lucid.
>
> And since it's a small feature enhancement, I'd expect this to be in
> Maverick if the review is positive. This will be used in hedley to
> enable their quite unique display configuration though.
Eric,
No problem. Just wanted to make sure so there was no misunderstanding.
Brad
--
Brad Figg brad.figg at canonical.com http://www.canonical.com
More information about the kernel-team
mailing list