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>
This commit is contained in:
parent
d63ec26a49
commit
9dc89a053d
@ -7,7 +7,10 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <common.h>
|
#include <common.h>
|
||||||
|
#include <atmel_lcd.h>
|
||||||
|
#include <dm.h>
|
||||||
#include <fdtdec.h>
|
#include <fdtdec.h>
|
||||||
|
#include <video.h>
|
||||||
#include <asm/io.h>
|
#include <asm/io.h>
|
||||||
#include <asm/arch/gpio.h>
|
#include <asm/arch/gpio.h>
|
||||||
#include <asm/arch/clk.h>
|
#include <asm/arch/clk.h>
|
||||||
@ -15,6 +18,21 @@
|
|||||||
#include <bmp_layout.h>
|
#include <bmp_layout.h>
|
||||||
#include <atmel_lcdc.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 */
|
/* configurable parameters */
|
||||||
#define ATMEL_LCDC_CVAL_DEFAULT 0xc8
|
#define ATMEL_LCDC_CVAL_DEFAULT 0xc8
|
||||||
#define ATMEL_LCDC_DMA_BURST_LEN 8
|
#define ATMEL_LCDC_DMA_BURST_LEN 8
|
||||||
@ -31,6 +49,7 @@
|
|||||||
#define lcdc_readl(mmio, reg) __raw_readl((mmio)+(reg))
|
#define lcdc_readl(mmio, reg) __raw_readl((mmio)+(reg))
|
||||||
#define lcdc_writel(mmio, reg, val) __raw_writel((val), (mmio)+(reg))
|
#define lcdc_writel(mmio, reg, val) __raw_writel((val), (mmio)+(reg))
|
||||||
|
|
||||||
|
#ifndef CONFIG_DM_VIDEO
|
||||||
ushort *configuration_get_cmap(void)
|
ushort *configuration_get_cmap(void)
|
||||||
{
|
{
|
||||||
return (ushort *)(panel_info.mmio + ATMEL_LCDC_LUT(0));
|
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);
|
lcd_setcolreg(i, cte.red, cte.green, cte.blue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static void atmel_fb_init(ulong addr, struct display_timing *timing, int bpix,
|
static void atmel_fb_init(ulong addr, struct display_timing *timing, int bpix,
|
||||||
bool tft, bool cont_pol_low, ulong lcdbase)
|
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);
|
(ATMEL_LCDC_GUARD_TIME << ATMEL_LCDC_GUARDT_OFFSET) | ATMEL_LCDC_PWR);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef CONFIG_DM_VIDEO
|
||||||
void lcd_ctrl_init(void *lcdbase)
|
void lcd_ctrl_init(void *lcdbase)
|
||||||
{
|
{
|
||||||
struct display_timing timing;
|
struct display_timing timing;
|
||||||
@ -221,3 +242,73 @@ ulong calc_fbsize(void)
|
|||||||
return ((panel_info.vl_col * panel_info.vl_row *
|
return ((panel_info.vl_col * panel_info.vl_row *
|
||||||
NBITS(panel_info.vl_bpix)) / 8) + PAGE_SIZE;
|
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
|
||||||
|
@ -10,6 +10,15 @@
|
|||||||
#ifndef _ATMEL_LCD_H_
|
#ifndef _ATMEL_LCD_H_
|
||||||
#define _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 {
|
typedef struct vidinfo {
|
||||||
ushort vl_col; /* Number of columns (i.e. 640) */
|
ushort vl_col; /* Number of columns (i.e. 640) */
|
||||||
ushort vl_row; /* Number of rows (i.e. 480) */
|
ushort vl_row; /* Number of rows (i.e. 480) */
|
||||||
|
Loading…
Reference in New Issue
Block a user