diff --git a/drivers/video/atmel_lcdfb.c b/drivers/video/atmel_lcdfb.c index 7c05e85..d343c5c 100644 --- a/drivers/video/atmel_lcdfb.c +++ b/drivers/video/atmel_lcdfb.c @@ -23,7 +23,6 @@ #include #include #include -#include #include #include @@ -34,12 +33,12 @@ #define ATMEL_LCDC_DMA_BURST_LEN 8 /* words */ #define ATMEL_LCDC_FIFO_SIZE 512 /* words */ -static unsigned long compute_hozval(unsigned long xres, unsigned long lcdcon2) +static unsigned long compute_hozval(struct atmel_lcdfb_info *sinfo, + unsigned long xres, unsigned long lcdcon2) { unsigned long value; - if (!(cpu_is_at91sam9261() || cpu_is_at91sam9g10() - || cpu_is_at32ap7000())) + if (!sinfo->have_hozval) return xres; value = xres; @@ -133,7 +132,7 @@ lcdc_writel(sinfo, ATMEL_LCDC_DMAFRMCFG, value); /* Set pixel clock */ - if (cpu_is_at91sam9g45() && !cpu_is_at91sam9g45es()) + if (sinfo->have_alt_pixclock) pix_factor = 1; clk_value_khz = clk_get_rate(sinfo->lcdc_clk) / 1000; @@ -191,7 +190,7 @@ lcdc_writel(sinfo, ATMEL_LCDC_TIM2, value); /* Horizontal value (aka line size) */ - hozval_linesz = compute_hozval(mode->xres, + hozval_linesz = compute_hozval(sinfo, mode->xres, lcdc_readl(sinfo, ATMEL_LCDC_LCDCON2)); /* Display size */ @@ -243,14 +242,39 @@ return atmel_lcdc_register(dev, &atmel_lcdfb_data); } +static struct atmel_lcdfb_config at91sam9261_config = { + .have_hozval = true, + .have_intensity_bit = true, +}; + +static struct atmel_lcdfb_config at91sam9263_config = { + .have_intensity_bit = true, +}; + +static struct atmel_lcdfb_config at91sam9g10_config = { + .have_hozval = true, +}; + +static struct atmel_lcdfb_config at91sam9g45_config = { + .have_alt_pixclock = true, +}; + +static struct atmel_lcdfb_config at91sam9rl_config = { + .have_intensity_bit = true, +}; + +static struct atmel_lcdfb_config at32ap_config = { + .have_hozval = true, +}; + static __maybe_unused struct of_device_id atmel_lcdfb_compatible[] = { - { .compatible = "atmel,at91sam9261-lcdc", }, - { .compatible = "atmel,at91sam9263-lcdc", }, - { .compatible = "atmel,at91sam9g10-lcdc", }, - { .compatible = "atmel,at91sam9g45-lcdc", }, + { .compatible = "atmel,at91sam9261-lcdc", .data = &at91sam9261_config, }, + { .compatible = "atmel,at91sam9263-lcdc", .data = &at91sam9263_config, }, + { .compatible = "atmel,at91sam9g10-lcdc", .data = &at91sam9g10_config, }, + { .compatible = "atmel,at91sam9g45-lcdc", .data = &at91sam9g45_config, }, { .compatible = "atmel,at91sam9g45es-lcdc", }, - { .compatible = "atmel,at91sam9rl-lcdc", }, - { .compatible = "atmel,at32ap-lcdc", }, + { .compatible = "atmel,at91sam9rl-lcdc", .data = &at91sam9rl_config, }, + { .compatible = "atmel,at32ap-lcdc", .data = &at32ap_config, }, { /* sentinel */ } }; diff --git a/drivers/video/atmel_lcdfb.h b/drivers/video/atmel_lcdfb.h index a011d42..b845892 100644 --- a/drivers/video/atmel_lcdfb.h +++ b/drivers/video/atmel_lcdfb.h @@ -4,6 +4,12 @@ struct atmel_lcdfb_info; +struct atmel_lcdfb_config { + bool have_alt_pixclock; + bool have_hozval; + bool have_intensity_bit; +}; + struct atmel_lcdfb_devdata { void (*start)(struct atmel_lcdfb_info *sinfo); void (*stop)(struct atmel_lcdfb_info *sinfo, u32 flags); @@ -24,7 +30,9 @@ unsigned int lcdcon2; unsigned int dmacon; unsigned int lcd_wiring_mode; + bool have_alt_pixclock; bool have_intensity_bit; + bool have_hozval; int gpio_power_control; bool gpio_power_control_active_low; diff --git a/drivers/video/atmel_lcdfb_core.c b/drivers/video/atmel_lcdfb_core.c index 45b0c63..c6ece5b 100644 --- a/drivers/video/atmel_lcdfb_core.c +++ b/drivers/video/atmel_lcdfb_core.c @@ -27,6 +27,8 @@ #include #include +#include + #include "atmel_lcdfb.h" static void atmel_lcdfb_start_clock(struct atmel_lcdfb_info *sinfo) @@ -130,7 +132,7 @@ = info->bits_per_pixel; break; case 16: - /* Older SOCs use IBGR:555 rather than BGR:565. */ + /* Older SOCs use BGR:555 rather than BGR:565. */ if (sinfo->have_intensity_bit) info->green.length = 5; else @@ -280,9 +282,7 @@ } /* - * Syntax: atmel,lcd-wiring-mode: lcd wiring mode "RGB", "BRG", "IRGB", "IBRG" - * The optional "I" indicates that green has an intensity bit as used by some - * older displays + * Syntax: atmel,lcd-wiring-mode: lcd wiring mode "RGB", "BGR" */ static int of_get_wiring_mode(struct device_node *np, struct atmel_lcdfb_info *sinfo) @@ -294,22 +294,13 @@ if (ret < 0) { /* Not present, use defaults */ sinfo->lcd_wiring_mode = ATMEL_LCDC_WIRING_BGR; - sinfo->have_intensity_bit = false; return 0; } if (!strcasecmp(mode, "BGR")) { sinfo->lcd_wiring_mode = ATMEL_LCDC_WIRING_BGR; - sinfo->have_intensity_bit = false; } else if (!strcasecmp(mode, "RGB")) { sinfo->lcd_wiring_mode = ATMEL_LCDC_WIRING_RGB; - sinfo->have_intensity_bit = false; - } else if (!strcasecmp(mode, "IBGR")) { - sinfo->lcd_wiring_mode = ATMEL_LCDC_WIRING_BGR; - sinfo->have_intensity_bit = true; - } else if (!strcasecmp(mode, "IRGB")) { - sinfo->lcd_wiring_mode = ATMEL_LCDC_WIRING_RGB; - sinfo->have_intensity_bit = true; } else { return -ENODEV; } @@ -338,8 +329,17 @@ struct fb_info *info = &sinfo->info; struct display_timings *modes; struct device_node *display; + struct atmel_lcdfb_config *config; int ret; + /* Driver data - optional */ + ret = dev_get_drvdata(dev, (const void **)&config); + if (!ret) { + sinfo->have_hozval = config->have_hozval; + sinfo->have_intensity_bit = config->have_intensity_bit; + sinfo->have_alt_pixclock = config->have_alt_pixclock; + } + /* Required properties */ display = of_parse_phandle(dev->device_node, "display", 0); if (!display) { @@ -415,7 +415,13 @@ sinfo->lcdcon2 = pdata->default_lcdcon2; sinfo->dmacon = pdata->default_dmacon; sinfo->lcd_wiring_mode = pdata->lcd_wiring_mode; + + sinfo->have_alt_pixclock = cpu_is_at91sam9g45() && + !cpu_is_at91sam9g45es(); sinfo->have_intensity_bit = pdata->have_intensity_bit; + sinfo->have_hozval = cpu_is_at91sam9261() || + cpu_is_at91sam9g10() || + cpu_is_at32ap7000(); info = &sinfo->info; info->modes.modes = pdata->mode_list;