Message ID | 1462454902-6093-17-git-send-email-sjg@chromium.org |
---|---|
State | Awaiting Upstream |
Delegated to: | Andreas Bießmann |
Headers | show |
On 05.05.16 15:28, Simon Glass wrote: > Add driver-model support to this driver. Most features can be controlled > from the device tree. > > Signed-off-by: Simon Glass <sjg@chromium.org> Reviewed-by: Andreas Bießmann <andreas@biessmann.org> > --- > > Changes in v2: None > > drivers/video/atmel_lcdfb.c | 91 +++++++++++++++++++++++++++++++++++++++++++++ > include/atmel_lcd.h | 9 +++++ > 2 files changed, 100 insertions(+) > > diff --git a/drivers/video/atmel_lcdfb.c b/drivers/video/atmel_lcdfb.c > index 37838a8..39cd7ca 100644 > --- a/drivers/video/atmel_lcdfb.c > +++ b/drivers/video/atmel_lcdfb.c > @@ -7,7 +7,10 @@ > */ > > #include <common.h> > +#include <atmel_lcd.h> > +#include <dm.h> > #include <fdtdec.h> > +#include <video.h> > #include <asm/io.h> > #include <asm/arch/gpio.h> > #include <asm/arch/clk.h> > @@ -15,6 +18,21 @@ > #include <bmp_layout.h> > #include <atmel_lcdc.h> > > +DECLARE_GLOBAL_DATA_PTR; > + > +#ifdef CONFIG_DM_VIDEO > +enum { > + /* Maximum LCD size we support */ > + LCD_MAX_WIDTH = 1366, > + LCD_MAX_HEIGHT = 768, > + LCD_MAX_LOG2_BPP = VIDEO_BPP16, > +}; > +#endif > + > +struct atmel_fb_priv { > + struct display_timing timing; > +}; > + > /* configurable parameters */ > #define ATMEL_LCDC_CVAL_DEFAULT 0xc8 > #define ATMEL_LCDC_DMA_BURST_LEN 8 > @@ -31,6 +49,7 @@ > #define lcdc_readl(mmio, reg) __raw_readl((mmio)+(reg)) > #define lcdc_writel(mmio, reg, val) __raw_writel((val), (mmio)+(reg)) > > +#ifndef CONFIG_DM_VIDEO > ushort *configuration_get_cmap(void) > { > return (ushort *)(panel_info.mmio + ATMEL_LCDC_LUT(0)); > @@ -91,6 +110,7 @@ void lcd_set_cmap(struct bmp_image *bmp, unsigned colors) > lcd_setcolreg(i, cte.red, cte.green, cte.blue); > } > } > +#endif > > static void atmel_fb_init(ulong addr, struct display_timing *timing, int bpix, > bool tft, bool cont_pol_low, ulong lcdbase) > @@ -190,6 +210,7 @@ static void atmel_fb_init(ulong addr, struct display_timing *timing, int bpix, > (ATMEL_LCDC_GUARD_TIME << ATMEL_LCDC_GUARDT_OFFSET) | ATMEL_LCDC_PWR); > } > > +#ifndef CONFIG_DM_VIDEO > void lcd_ctrl_init(void *lcdbase) > { > struct display_timing timing; > @@ -221,3 +242,73 @@ ulong calc_fbsize(void) > return ((panel_info.vl_col * panel_info.vl_row * > NBITS(panel_info.vl_bpix)) / 8) + PAGE_SIZE; > } > +#endif > + > +#ifdef CONFIG_DM_VIDEO > +static int atmel_fb_lcd_probe(struct udevice *dev) > +{ > + struct video_uc_platdata *uc_plat = dev_get_uclass_platdata(dev); > + struct video_priv *uc_priv = dev_get_uclass_priv(dev); > + struct atmel_fb_priv *priv = dev_get_priv(dev); > + struct display_timing *timing = &priv->timing; > + > + /* > + * For now some values are hard-coded. We could use the device tree > + * bindings in simple-framebuffer.txt to specify the format/bpp and > + * some Atmel-specific binding for tft and cont_pol_low. > + */ > + atmel_fb_init(ATMEL_BASE_LCDC, timing, VIDEO_BPP16, true, false, > + uc_plat->base); > + uc_priv->xsize = timing->hactive.typ; > + uc_priv->ysize = timing->vactive.typ; > + uc_priv->bpix = VIDEO_BPP16; > + video_set_flush_dcache(dev, true); > + debug("LCD frame buffer at %lx, size %x, %dx%d pixels\n", uc_plat->base, > + uc_plat->size, uc_priv->xsize, uc_priv->ysize); > + > + return 0; > +} > + > +static int atmel_fb_ofdata_to_platdata(struct udevice *dev) > +{ > + struct atmel_lcd_platdata *plat = dev_get_platdata(dev); > + struct atmel_fb_priv *priv = dev_get_priv(dev); > + struct display_timing *timing = &priv->timing; > + const void *blob = gd->fdt_blob; > + > + if (fdtdec_decode_display_timing(blob, dev->of_offset, > + plat->timing_index, timing)) { > + debug("%s: Failed to decode display timing\n", __func__); > + return -EINVAL; > + } > + > + return 0; > +} > + > +static int atmel_fb_lcd_bind(struct udevice *dev) > +{ > + struct video_uc_platdata *uc_plat = dev_get_uclass_platdata(dev); > + > + uc_plat->size = LCD_MAX_WIDTH * LCD_MAX_HEIGHT * > + (1 << VIDEO_BPP16) / 8; > + debug("%s: Frame buffer size %x\n", __func__, uc_plat->size); > + > + return 0; > +} > + > +static const struct udevice_id atmel_fb_lcd_ids[] = { > + { .compatible = "atmel,at91sam9g45-lcdc" }, > + { } > +}; > + > +U_BOOT_DRIVER(atmel_fb) = { > + .name = "atmel_fb", > + .id = UCLASS_VIDEO, > + .of_match = atmel_fb_lcd_ids, > + .bind = atmel_fb_lcd_bind, > + .ofdata_to_platdata = atmel_fb_ofdata_to_platdata, > + .probe = atmel_fb_lcd_probe, > + .platdata_auto_alloc_size = sizeof(struct atmel_lcd_platdata), > + .priv_auto_alloc_size = sizeof(struct atmel_fb_priv), > +}; > +#endif > diff --git a/include/atmel_lcd.h b/include/atmel_lcd.h > index 6993128..8a2f46f 100644 > --- a/include/atmel_lcd.h > +++ b/include/atmel_lcd.h > @@ -10,6 +10,15 @@ > #ifndef _ATMEL_LCD_H_ > #define _ATMEL_LCD_H_ > > +/** > + * struct atmel_lcd_platdata - platform data for Atmel LCDs with driver model > + * > + * @timing_index: Index of LCD timing to use in device tree node > + */ > +struct atmel_lcd_platdata { > + int timing_index; > +}; > + > typedef struct vidinfo { > ushort vl_col; /* Number of columns (i.e. 640) */ > ushort vl_row; /* Number of rows (i.e. 480) */ >
Dear Simon Glass, Simon Glass <sjg@chromium.org> writes: >Add driver-model support to this driver. Most features can be controlled >from the device tree. > >Signed-off-by: Simon Glass <sjg@chromium.org> >Reviewed-by: Andreas Bießmann <andreas@biessmann.org> >--- > >Changes in v2: None > > drivers/video/atmel_lcdfb.c | 91 +++++++++++++++++++++++++++++++++++++++++++++ > include/atmel_lcd.h | 9 +++++ > 2 files changed, 100 insertions(+) applied to u-boot-atmel/master, thanks! Best regards, Andreas Bießmann
diff --git a/drivers/video/atmel_lcdfb.c b/drivers/video/atmel_lcdfb.c index 37838a8..39cd7ca 100644 --- a/drivers/video/atmel_lcdfb.c +++ b/drivers/video/atmel_lcdfb.c @@ -7,7 +7,10 @@ */ #include <common.h> +#include <atmel_lcd.h> +#include <dm.h> #include <fdtdec.h> +#include <video.h> #include <asm/io.h> #include <asm/arch/gpio.h> #include <asm/arch/clk.h> @@ -15,6 +18,21 @@ #include <bmp_layout.h> #include <atmel_lcdc.h> +DECLARE_GLOBAL_DATA_PTR; + +#ifdef CONFIG_DM_VIDEO +enum { + /* Maximum LCD size we support */ + LCD_MAX_WIDTH = 1366, + LCD_MAX_HEIGHT = 768, + LCD_MAX_LOG2_BPP = VIDEO_BPP16, +}; +#endif + +struct atmel_fb_priv { + struct display_timing timing; +}; + /* configurable parameters */ #define ATMEL_LCDC_CVAL_DEFAULT 0xc8 #define ATMEL_LCDC_DMA_BURST_LEN 8 @@ -31,6 +49,7 @@ #define lcdc_readl(mmio, reg) __raw_readl((mmio)+(reg)) #define lcdc_writel(mmio, reg, val) __raw_writel((val), (mmio)+(reg)) +#ifndef CONFIG_DM_VIDEO ushort *configuration_get_cmap(void) { return (ushort *)(panel_info.mmio + ATMEL_LCDC_LUT(0)); @@ -91,6 +110,7 @@ void lcd_set_cmap(struct bmp_image *bmp, unsigned colors) lcd_setcolreg(i, cte.red, cte.green, cte.blue); } } +#endif static void atmel_fb_init(ulong addr, struct display_timing *timing, int bpix, bool tft, bool cont_pol_low, ulong lcdbase) @@ -190,6 +210,7 @@ static void atmel_fb_init(ulong addr, struct display_timing *timing, int bpix, (ATMEL_LCDC_GUARD_TIME << ATMEL_LCDC_GUARDT_OFFSET) | ATMEL_LCDC_PWR); } +#ifndef CONFIG_DM_VIDEO void lcd_ctrl_init(void *lcdbase) { struct display_timing timing; @@ -221,3 +242,73 @@ ulong calc_fbsize(void) return ((panel_info.vl_col * panel_info.vl_row * NBITS(panel_info.vl_bpix)) / 8) + PAGE_SIZE; } +#endif + +#ifdef CONFIG_DM_VIDEO +static int atmel_fb_lcd_probe(struct udevice *dev) +{ + struct video_uc_platdata *uc_plat = dev_get_uclass_platdata(dev); + struct video_priv *uc_priv = dev_get_uclass_priv(dev); + struct atmel_fb_priv *priv = dev_get_priv(dev); + struct display_timing *timing = &priv->timing; + + /* + * For now some values are hard-coded. We could use the device tree + * bindings in simple-framebuffer.txt to specify the format/bpp and + * some Atmel-specific binding for tft and cont_pol_low. + */ + atmel_fb_init(ATMEL_BASE_LCDC, timing, VIDEO_BPP16, true, false, + uc_plat->base); + uc_priv->xsize = timing->hactive.typ; + uc_priv->ysize = timing->vactive.typ; + uc_priv->bpix = VIDEO_BPP16; + video_set_flush_dcache(dev, true); + debug("LCD frame buffer at %lx, size %x, %dx%d pixels\n", uc_plat->base, + uc_plat->size, uc_priv->xsize, uc_priv->ysize); + + return 0; +} + +static int atmel_fb_ofdata_to_platdata(struct udevice *dev) +{ + struct atmel_lcd_platdata *plat = dev_get_platdata(dev); + struct atmel_fb_priv *priv = dev_get_priv(dev); + struct display_timing *timing = &priv->timing; + const void *blob = gd->fdt_blob; + + if (fdtdec_decode_display_timing(blob, dev->of_offset, + plat->timing_index, timing)) { + debug("%s: Failed to decode display timing\n", __func__); + return -EINVAL; + } + + return 0; +} + +static int atmel_fb_lcd_bind(struct udevice *dev) +{ + struct video_uc_platdata *uc_plat = dev_get_uclass_platdata(dev); + + uc_plat->size = LCD_MAX_WIDTH * LCD_MAX_HEIGHT * + (1 << VIDEO_BPP16) / 8; + debug("%s: Frame buffer size %x\n", __func__, uc_plat->size); + + return 0; +} + +static const struct udevice_id atmel_fb_lcd_ids[] = { + { .compatible = "atmel,at91sam9g45-lcdc" }, + { } +}; + +U_BOOT_DRIVER(atmel_fb) = { + .name = "atmel_fb", + .id = UCLASS_VIDEO, + .of_match = atmel_fb_lcd_ids, + .bind = atmel_fb_lcd_bind, + .ofdata_to_platdata = atmel_fb_ofdata_to_platdata, + .probe = atmel_fb_lcd_probe, + .platdata_auto_alloc_size = sizeof(struct atmel_lcd_platdata), + .priv_auto_alloc_size = sizeof(struct atmel_fb_priv), +}; +#endif diff --git a/include/atmel_lcd.h b/include/atmel_lcd.h index 6993128..8a2f46f 100644 --- a/include/atmel_lcd.h +++ b/include/atmel_lcd.h @@ -10,6 +10,15 @@ #ifndef _ATMEL_LCD_H_ #define _ATMEL_LCD_H_ +/** + * struct atmel_lcd_platdata - platform data for Atmel LCDs with driver model + * + * @timing_index: Index of LCD timing to use in device tree node + */ +struct atmel_lcd_platdata { + int timing_index; +}; + typedef struct vidinfo { ushort vl_col; /* Number of columns (i.e. 640) */ ushort vl_row; /* Number of rows (i.e. 480) */
Add driver-model support to this driver. Most features can be controlled from the device tree. Signed-off-by: Simon Glass <sjg@chromium.org> --- Changes in v2: None drivers/video/atmel_lcdfb.c | 91 +++++++++++++++++++++++++++++++++++++++++++++ include/atmel_lcd.h | 9 +++++ 2 files changed, 100 insertions(+)