diff mbox

[U-Boot,v2,16/18] at91: video: Support driver-model for the LCD driver

Message ID 1462454902-6093-17-git-send-email-sjg@chromium.org
State Awaiting Upstream
Delegated to: Andreas Bießmann
Headers show

Commit Message

Simon Glass May 5, 2016, 1:28 p.m. UTC
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(+)

Comments

Andreas Bießmann June 4, 2016, 8:11 p.m. UTC | #1
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) */
>
Andreas Bießmann June 12, 2016, 10:01 p.m. UTC | #2
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 mbox

Patch

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) */