i.MX fb: Add support for overlay framebuffer
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
This commit is contained in:
parent
b96916ac9b
commit
e9dc699882
|
@ -1,11 +1,15 @@
|
||||||
menu "Video drivers "
|
menu "Video drivers "
|
||||||
|
|
||||||
config VIDEO
|
config VIDEO
|
||||||
bool "Enable Framebuffersupport"
|
bool "Enable Framebuffer support"
|
||||||
|
|
||||||
config DRIVER_VIDEO_IMX
|
config DRIVER_VIDEO_IMX
|
||||||
bool "i.MX framebuffer driver"
|
bool "i.MX framebuffer driver"
|
||||||
depends on ARCH_IMX
|
depends on ARCH_IMX
|
||||||
depends on VIDEO
|
depends on VIDEO
|
||||||
|
|
||||||
|
config IMXFB_DRIVER_VIDEO_IMX_OVERLAY
|
||||||
|
bool "i.MX framebuffer overlay support"
|
||||||
|
depends on DRIVER_VIDEO_IMX && (ARCH_IMX27 || ARCH_IMX21)
|
||||||
|
|
||||||
endmenu
|
endmenu
|
||||||
|
|
|
@ -114,6 +114,17 @@
|
||||||
#define LCDISR_EOF (1<<1)
|
#define LCDISR_EOF (1<<1)
|
||||||
#define LCDISR_BOF (1<<0)
|
#define LCDISR_BOF (1<<0)
|
||||||
|
|
||||||
|
#define LCDC_LGWSAR 0x50
|
||||||
|
#define LCDC_LGWSR 0x54
|
||||||
|
#define LCDC_LGWVPWR 0x58
|
||||||
|
#define LCDC_LGWPOR 0x5c
|
||||||
|
#define LCDC_LGWPR 0x60
|
||||||
|
#define LCDC_LGWCR 0x64
|
||||||
|
#define LGWCR_GWAV(alpha) (((alpha) & 0xff) << 24)
|
||||||
|
#define LGWCR_GWE (1 << 22)
|
||||||
|
|
||||||
|
#define LCDC_LGWDCR 0x68
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* These are the bitfields for each
|
* These are the bitfields for each
|
||||||
* display depth that we support.
|
* display depth that we support.
|
||||||
|
@ -139,6 +150,12 @@ struct imxfb_info {
|
||||||
struct imx_fb_videomode *mode;
|
struct imx_fb_videomode *mode;
|
||||||
|
|
||||||
struct fb_info info;
|
struct fb_info info;
|
||||||
|
struct device_d *dev;
|
||||||
|
|
||||||
|
|
||||||
|
struct fb_info overlay;
|
||||||
|
struct param_d param_alpha;
|
||||||
|
char alpha_string[4];
|
||||||
};
|
};
|
||||||
|
|
||||||
#define IMX_NAME "IMX"
|
#define IMX_NAME "IMX"
|
||||||
|
@ -354,6 +371,127 @@ static struct fb_ops imxfb_ops = {
|
||||||
.fb_disable = imxfb_disable_controller,
|
.fb_disable = imxfb_disable_controller,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifdef CONFIG_IMXFB_DRIVER_VIDEO_IMX_OVERLAY
|
||||||
|
static void imxfb_overlay_enable_controller(struct fb_info *overlay)
|
||||||
|
{
|
||||||
|
struct imxfb_info *fbi = overlay->priv;
|
||||||
|
unsigned int tmp;
|
||||||
|
|
||||||
|
tmp = readl(fbi->regs + LCDC_LGWCR);
|
||||||
|
tmp |= LGWCR_GWE;
|
||||||
|
writel(tmp , fbi->regs + LCDC_LGWCR);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void imxfb_overlay_disable_controller(struct fb_info *overlay)
|
||||||
|
{
|
||||||
|
struct imxfb_info *fbi = overlay->priv;
|
||||||
|
unsigned int tmp;
|
||||||
|
|
||||||
|
tmp = readl(fbi->regs + LCDC_LGWCR);
|
||||||
|
tmp &= ~LGWCR_GWE;
|
||||||
|
writel(tmp , fbi->regs + LCDC_LGWCR);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int imxfb_overlay_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
|
||||||
|
u_int trans, struct fb_info *info)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct fb_ops imxfb_overlay_ops = {
|
||||||
|
.fb_setcolreg = imxfb_overlay_setcolreg,
|
||||||
|
.fb_enable = imxfb_overlay_enable_controller,
|
||||||
|
.fb_disable = imxfb_overlay_disable_controller,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int imxfb_alpha_set(struct device_d *dev, struct param_d *param,
|
||||||
|
const char *val)
|
||||||
|
{
|
||||||
|
struct fb_info *overlay = dev->priv;
|
||||||
|
struct imxfb_info *fbi = overlay->priv;
|
||||||
|
int alpha;
|
||||||
|
unsigned int tmp;
|
||||||
|
|
||||||
|
alpha = simple_strtoul(val, NULL, 0);
|
||||||
|
alpha &= 0xff;
|
||||||
|
|
||||||
|
tmp = readl(fbi->regs + LCDC_LGWCR);
|
||||||
|
tmp &= ~LGWCR_GWAV(0xff);
|
||||||
|
tmp |= LGWCR_GWAV(alpha);
|
||||||
|
writel(tmp , fbi->regs + LCDC_LGWCR);
|
||||||
|
|
||||||
|
sprintf(fbi->alpha_string, "%d", alpha);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int imxfb_register_overlay(struct imxfb_info *fbi)
|
||||||
|
{
|
||||||
|
struct fb_info *overlay;
|
||||||
|
struct imxfb_rgb *rgb;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
overlay = &fbi->overlay;
|
||||||
|
|
||||||
|
overlay->priv = fbi;
|
||||||
|
overlay->mode = fbi->info.mode;
|
||||||
|
overlay->xres = fbi->info.xres;
|
||||||
|
overlay->yres = fbi->info.yres;
|
||||||
|
overlay->bits_per_pixel = fbi->info.bits_per_pixel;
|
||||||
|
overlay->fbops = &imxfb_overlay_ops;
|
||||||
|
|
||||||
|
overlay->screen_base = xzalloc(overlay->xres * overlay->yres *
|
||||||
|
(overlay->bits_per_pixel >> 3));
|
||||||
|
|
||||||
|
writel((unsigned long)overlay->screen_base, fbi->regs + LCDC_LGWSAR);
|
||||||
|
writel(SIZE_XMAX(overlay->xres) | SIZE_YMAX(overlay->yres),
|
||||||
|
fbi->regs + LCDC_LGWSR);
|
||||||
|
writel(VPW_VPW(overlay->xres * overlay->bits_per_pixel / 8 / 4),
|
||||||
|
fbi->regs + LCDC_LGWVPWR);
|
||||||
|
writel(0, fbi->regs + LCDC_LGWPR);
|
||||||
|
writel(LGWCR_GWAV(0x0), fbi->regs + LCDC_LGWCR);
|
||||||
|
|
||||||
|
switch (overlay->bits_per_pixel) {
|
||||||
|
case 32:
|
||||||
|
rgb = &def_rgb_18;
|
||||||
|
break;
|
||||||
|
case 16:
|
||||||
|
default:
|
||||||
|
if (fbi->pcr & PCR_TFT)
|
||||||
|
rgb = &def_rgb_16_tft;
|
||||||
|
else
|
||||||
|
rgb = &def_rgb_16_stn;
|
||||||
|
break;
|
||||||
|
case 8:
|
||||||
|
rgb = &def_rgb_8;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copy the RGB parameters for this display
|
||||||
|
* from the machine specific parameters.
|
||||||
|
*/
|
||||||
|
overlay->red = rgb->red;
|
||||||
|
overlay->green = rgb->green;
|
||||||
|
overlay->blue = rgb->blue;
|
||||||
|
overlay->transp = rgb->transp;
|
||||||
|
|
||||||
|
ret = register_framebuffer(overlay);
|
||||||
|
if (ret < 0) {
|
||||||
|
dev_err(fbi->dev, "failed to register framebuffer\n");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
fbi->param_alpha.set = imxfb_alpha_set;
|
||||||
|
fbi->param_alpha.name = "alpha";
|
||||||
|
sprintf(fbi->alpha_string, "%d", 0);
|
||||||
|
fbi->param_alpha.value = fbi->alpha_string;
|
||||||
|
dev_add_param(&overlay->dev, &fbi->param_alpha);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static int imxfb_probe(struct device_d *dev)
|
static int imxfb_probe(struct device_d *dev)
|
||||||
{
|
{
|
||||||
struct imxfb_info *fbi;
|
struct imxfb_info *fbi;
|
||||||
|
@ -364,6 +502,11 @@ static int imxfb_probe(struct device_d *dev)
|
||||||
if (!pdata)
|
if (!pdata)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
|
#ifdef CONFIG_ARCH_IMX27
|
||||||
|
PCCR0 &= ~PCCR0_LCDC_EN;
|
||||||
|
PCCR1 &= ~PCCR1_HCLK_LCDC;
|
||||||
|
#endif
|
||||||
|
|
||||||
fbi = xzalloc(sizeof(*fbi));
|
fbi = xzalloc(sizeof(*fbi));
|
||||||
info = &fbi->info;
|
info = &fbi->info;
|
||||||
|
|
||||||
|
@ -373,6 +516,7 @@ static int imxfb_probe(struct device_d *dev)
|
||||||
fbi->pwmr = pdata->pwmr;
|
fbi->pwmr = pdata->pwmr;
|
||||||
fbi->lscr1 = pdata->lscr1;
|
fbi->lscr1 = pdata->lscr1;
|
||||||
fbi->dmacr = pdata->dmacr;
|
fbi->dmacr = pdata->dmacr;
|
||||||
|
fbi->dev = dev;
|
||||||
info->priv = fbi;
|
info->priv = fbi;
|
||||||
info->mode = &pdata->mode->mode;
|
info->mode = &pdata->mode->mode;
|
||||||
info->xres = pdata->mode->mode.xres;
|
info->xres = pdata->mode->mode.xres;
|
||||||
|
@ -392,6 +536,10 @@ static int imxfb_probe(struct device_d *dev)
|
||||||
dev_err(dev, "failed to register framebuffer\n");
|
dev_err(dev, "failed to register framebuffer\n");
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
#ifdef CONFIG_IMXFB_DRIVER_VIDEO_IMX_OVERLAY
|
||||||
|
imxfb_register_overlay(fbi);
|
||||||
|
#endif
|
||||||
|
imxfb_enable_controller(info);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue