aboutsummaryrefslogtreecommitdiff
path: root/drivers/video
diff options
context:
space:
mode:
authorSimon Glass <sjg@chromium.org>2016-05-05 07:28:20 -0600
committerAndreas Bießmann <andreas@biessmann.org>2016-06-12 23:49:38 +0200
commit9dc89a053d29deea73c39ef49c9f1c6cb4c38820 (patch)
tree9728dbbf077f28024874885fd6abcedaf697301f /drivers/video
parentd63ec26a49a1ae8c0fd65c24e8c0b6c67b79cd01 (diff)
downloadu-boot-9dc89a053d29deea73c39ef49c9f1c6cb4c38820.zip
u-boot-9dc89a053d29deea73c39ef49c9f1c6cb4c38820.tar.gz
u-boot-9dc89a053d29deea73c39ef49c9f1c6cb4c38820.tar.bz2
at91: video: Support driver-model for the LCD driver
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>
Diffstat (limited to 'drivers/video')
-rw-r--r--drivers/video/atmel_lcdfb.c91
1 files changed, 91 insertions, 0 deletions
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