From: Davide Bonfanti <davide.bonfa...@bticino.it> Signed-off-by: Davide Bonfanti <davide.bonfa...@bticino.it> --- drivers/video/davincifb.c | 167 +++++++++++++++++++++++++++++++++++++++++---- include/video/davincifb.h | 17 ++++- 2 files changed, 165 insertions(+), 19 deletions(-)
diff --git a/drivers/video/davincifb.c b/drivers/video/davincifb.c index 2a7b2c9..24d1424 100644 --- a/drivers/video/davincifb.c +++ b/drivers/video/davincifb.c @@ -29,12 +29,15 @@ #include <linux/interrupt.h> #include <linux/platform_device.h> +#include <media/davinci/vpss.h> #include <asm/irq.h> #include <asm/uaccess.h> #include <video/davincifb.h> #include <asm/system.h> +#include <mach/dm365.h> +#include <mach/cputype.h> #define MODULE_NAME "davincifb" /* Output Format Selection */ @@ -286,6 +289,10 @@ static irqreturn_t davincifb_isr(int irq, void *arg) dm->vid1->info.fix.line_length); dm->vid1->sdram_address = 0; } + if (dm->osd0->info.var.vmode == FB_VMODE_NONINTERLACED) { + ++dm->vsync_cnt; + wake_up_interruptible(&dm->vsync_wait); + } return IRQ_HANDLED; } else { ++dm->vsync_cnt; @@ -631,21 +638,29 @@ static void set_sdram_params(char *id, u32 addr, u32 line_length) /* The parameters to be written to the registers should be in * multiple of 32 bytes */ - addr = addr; /* div by 32 */ - line_length = line_length / 32; + addr = (addr - DAVINCI_DDR_BASE) >> 5; /* div by 32 */ + line_length = line_length >> 5; if (is_win(id, VID0)) { - dispc_reg_out(OSD_VIDWIN0ADR, addr); - dispc_reg_out(OSD_VIDWIN0OFST, line_length); + dispc_reg_out(OSD_VIDWIN0ADR, addr & 0xFFFF); + dispc_reg_merge(OSD_VIDWINADH, (addr & 0x7F0000) >> 16, 0x7F); + dispc_reg_out(OSD_VIDWIN0OFST, line_length | 0x1000); + /* From docs it's not clear why bit12 is needed */ } else if (is_win(id, VID1)) { - dispc_reg_out(OSD_VIDWIN1ADR, addr); - dispc_reg_out(OSD_VIDWIN1OFST, line_length); + dispc_reg_out(OSD_VIDWIN1ADR, addr & 0xFFFF); + dispc_reg_merge(OSD_VIDWINADH, (addr & 0x7F0000) >> 8, 0x7F00); + dispc_reg_out(OSD_VIDWIN1OFST, line_length | 0x1000); + /* From docs it's not clear why bit12 is needed */ } else if (is_win(id, OSD0)) { - dispc_reg_out(OSD_OSDWIN0ADR, addr); - dispc_reg_out(OSD_OSDWIN0OFST, line_length); + dispc_reg_out(OSD_OSDWIN0ADR, addr & 0xFFFF); + dispc_reg_out(OSD_OSDWIN0OFST, line_length | 0x1000); + dispc_reg_merge(OSD_OSDWINADH, (addr & 0x7F0000) >> 16, 0x7F); + /* From docs it's not clear why bit12 is needed */ } else if (is_win(id, OSD1)) { - dispc_reg_out(OSD_OSDWIN1ADR, addr); - dispc_reg_out(OSD_OSDWIN1OFST, line_length); + dispc_reg_out(OSD_OSDWIN1ADR, addr & 0xFFFF); + dispc_reg_merge(OSD_OSDWINADH, (addr & 0x7F0000) >> 8, 0x7F00); + dispc_reg_out(OSD_OSDWIN1OFST, line_length | 0x1000); + /* From docs it's not clear why bit12 is needed */ } } @@ -980,14 +995,12 @@ int __init davincifb_setup(char *options) if (!strncmp(this_opt, "output=", 7)) { if (!strncmp(this_opt + 7, "lcd", 3)) { dmparams.output = LCD; - dmparams.format = 0; + dmparams.format = RGB; } else if (!strncmp(this_opt + 7, "ntsc", 4)) dmparams.output = NTSC; else if (!strncmp(this_opt + 7, "pal", 3)) dmparams.output = PAL; } else if (!strncmp(this_opt, "format=", 7)) { - if (dmparams.output == LCD) - continue; if (!strncmp(this_opt + 7, "composite", 9)) dmparams.format = COMPOSITE; else if (!strncmp(this_opt + 7, "s-video", 7)) @@ -1060,7 +1073,9 @@ int __init davincifb_setup(char *options) format_yres = 480; } else if (dmparams.output == PAL) { format_yres = 576; - } else { + } else if (dmparams.output == LCD) + format_yres = dmparams.osd0_yres; + else { printk(KERN_INFO "DaVinci:invalid format..defaulting width to 480\n"); } @@ -1180,7 +1195,10 @@ static struct fb_info *init_fb_info(struct dm_win_info *w, struct dm_info *dm = w->dm; /* initialize the fb_info structure */ - info->flags = FBINFO_DEFAULT; + info->flags = FBINFO_DEFAULT | + FBINFO_HWACCEL_COPYAREA | FBINFO_HWACCEL_FILLRECT | + FBINFO_HWACCEL_IMAGEBLIT | FBINFO_HWACCEL_XPAN | + FBINFO_HWACCEL_YPAN; info->fbops = &davincifb_ops; info->screen_base = (char *)(w->fb_base); info->pseudo_palette = w->pseudo_palette; @@ -1388,6 +1406,123 @@ static void davincifb_pal_component_config(int on) } } +int dm365_set_pixelclock(int pixclock) +{ + u32 pllfreq; + int ret; + struct clk *clk6; + + pixclock /= 1000; + pllfreq = 1000000000 / pixclock; + + clk6 = clk_get(dm->dev, "pll1_sysclk6"); + if (clk_set_rate(clk6, pllfreq)) { + dispc_reg_out(VENC_DCLKCTL, 0x03); + dispc_reg_out(VENC_DCLKPTN0, 0x03); + dispc_reg_out(VENC_DCLKPTN1, 0x0); + dispc_reg_out(VENC_DCLKPTN2, 0x0); + dispc_reg_out(VENC_DCLKPTN3, 0x0); + ret = 4; + clk_set_rate(clk6, pllfreq * 4); + } else { + dispc_reg_out(VENC_DCLKCTL, 0x801); + dispc_reg_out(VENC_DCLKPTN0, 0x03); + dispc_reg_out(VENC_DCLKPTN1, 0x0); + dispc_reg_out(VENC_DCLKPTN2, 0x0); + dispc_reg_out(VENC_DCLKPTN3, 0x0); + ret = 1; + } + pllfreq = clk_get_rate(clk6); + return ret; +} + +static void davincifb_lcd_rgb_config(int on) +{ + u32 divisor = 1; + + if (on) { + /* Reset video encoder module */ + dispc_reg_out(VENC_VMOD, 0x0); + dispc_reg_out(VENC_VIDCTL, 0x0); + + if (cpu_is_davinci_dm365()) { + divisor = \ + dm365_set_pixelclock(dm->osd0->info.var.pixclock); + } + + /* set hsync pulse width */ + dispc_reg_out(VENC_HSPLS, (dm->osd0->info.var.hsync_len) * \ + divisor); + /* set vsync pulse width */ + dispc_reg_out(VENC_VSPLS, dm->osd0->info.var.vsync_len); + /* set horizontal interval */ + dispc_reg_out(VENC_HINT, ((dm->osd0->info.var.left_margin + \ + dm->osd0->info.var.right_margin + dm->osd0->info.var.width) * \ + divisor) - 1); + /* set horizontal data valid start position */ + dispc_reg_out(VENC_HSTART, (dm->osd0->info.var.left_margin) * \ + divisor); + /* set Horizontal data valid range */ + dispc_reg_out(VENC_HVALID, (dm->osd0->info.var.width) * \ + divisor); + /* set Vertical interval */ + dispc_reg_out(VENC_VINT, dm->osd0->info.var.upper_margin + \ + dm->osd0->info.var.lower_margin + \ + dm->osd0->info.var.height - 1); + /* set Vertical data valid start position */ + dispc_reg_out(VENC_VSTART, dm->osd0->info.var.upper_margin); + /* set Horizontal data valid range */ + dispc_reg_out(VENC_VVALID, dm->osd0->info.var.height); + /* Enable VCLK */ + dispc_reg_out(VENC_OSDCLK1, 3); + dispc_reg_out(VENC_LCDOUT, 0x81); + dispc_reg_out(VENC_OSDCLK0, 0x0); + dispc_reg_out(VENC_OSDCLK1, 0xFFFF); + dispc_reg_out(VENC_CLKCTL, 0x10); + dispc_reg_out(VENC_SYNCCTL, 0x0F); + dispc_reg_merge(VENC_VIDCTL, \ + ((dm->osd0->info.var.sync & FB_SYNC_PIXCLOCK_HIGH_ACT) \ + == FB_SYNC_PIXCLOCK_HIGH_ACT) << 14, VENC_VIDCTL_VCLKP); + dispc_reg_merge(VENC_SYNCCTL, \ + ((dm->osd0->info.var.sync & FB_SYNC_VERT_HIGH_ACT) \ + != FB_SYNC_VERT_HIGH_ACT) << 3, VENC_SYNCCTL_VPL); + dispc_reg_merge(VENC_SYNCCTL, \ + ((dm->osd0->info.var.sync & FB_SYNC_HOR_HIGH_ACT) \ + != FB_SYNC_HOR_HIGH_ACT) << 2, VENC_SYNCCTL_HPL); + + /* set osd window */ + dispc_reg_out(OSD_VIDWINMD, 0x22); + dispc_reg_out(OSD_OSDWIN0MD, 0x2933); + dispc_reg_out(OSD_OSDWIN0XP, dm->osd0->info.var.xoffset); + dispc_reg_out(OSD_OSDWIN0YP, dm->osd0->info.var.yoffset); + dispc_reg_out(OSD_OSDWIN0XL, dm->osd0->info.var.xres * \ + divisor); + dispc_reg_out(OSD_OSDWIN0YL, dm->osd0->info.var.yres); + + /* Set RGB565 mode */ + dispc_reg_merge(OSD_OSDWIN0MD, OSD_OSDWIN0MD_RGB0E, \ + OSD_OSDWIN0MD_RGB0E); + dispc_reg_merge(OSD_OSDWIN0MD, on, OSD_OSDWIN0MD_OACT0); + + dispc_reg_merge(VENC_VIDCTL, VENC_VIDCTL_VCLKE, \ + VENC_VIDCTL_VCLKE); + /* set origin position */ + /* Values manually defined + dispc_reg_out(OSD_BASEPX, 0x32); + dispc_reg_out(OSD_BASEPY, 0x08);*/ + dispc_reg_out(OSD_BASEPX, 20 + dm->osd0->info.var.left_margin); + dispc_reg_out(OSD_BASEPY, dm->osd0->info.var.upper_margin); + + dispc_reg_out(VENC_VMOD, (VENC_VMOD_VDMD_RGB666 << \ + VENC_VMOD_VDMD_SHIFT) | VENC_VMOD_ITLCL | \ + VENC_VMOD_HDMD | VENC_VMOD_VIE | VENC_VMOD_VENC \ + | VENC_VMOD_VMD); + } else { + /* Reset video encoder module */ + dispc_reg_out(VENC_VMOD, 0); + } +} + static inline void fix_default_var(struct dm_win_info *w, u32 xres, u32 yres, u32 xpos, u32 ypos, int n_buf) @@ -1487,6 +1622,8 @@ static int davincifb_probe(struct platform_device *pdev) dm->output_device_config = davincifb_pal_svideo_config; else if ((dmparams.output == PAL) && (dmparams.format == COMPONENT)) dm->output_device_config = davincifb_pal_component_config; + else if ((dmparams.output == LCD) && (dmparams.format == RGB)) + dm->output_device_config = davincifb_lcd_rgb_config; /* Add support for other displays here */ else { printk(KERN_WARNING "Unsupported output device!\n"); diff --git a/include/video/davincifb.h b/include/video/davincifb.h index c3ecdd8..c4e8127 100644 --- a/include/video/davincifb.h +++ b/include/video/davincifb.h @@ -14,12 +14,12 @@ #define _DAVINCIFB_H_ #include <mach/io.h> +#include <linux/fb.h> /* Base registers */ -#define VPBE_REG_BASE 0x01c72780 -#define VENC_REG_BASE 0x01c72400 -#define OSD_REG_BASE 0x01c72600 -#define OSD_REG_SIZE 0x00000180 +#define VENC_REG_BASE 0x01C71E00 +#define OSD_REG_BASE 0x01C71C00 +#define OSD_REG_SIZE 0x00000100 /* VPBE Global Registers */ #define VPBE_PID (VPBE_BASE + 0x0) @@ -107,6 +107,7 @@ #define VENC_HVLDCL0 (VENC_REG_BASE + 0x134) #define VENC_HVLDCL1 (VENC_REG_BASE + 0x138) #define VENC_OSDHAD (VENC_REG_BASE + 0x13C) +#define VENC_CLKCTL (VENC_REG_BASE + 0x140) #define VID0 0 #define VID1 1 @@ -125,9 +126,11 @@ #define OSD_VIDWIN1OFST (OSD_REG_BASE + 0x1C) #define OSD_OSDWIN0OFST (OSD_REG_BASE + 0x20) #define OSD_OSDWIN1OFST (OSD_REG_BASE + 0x24) +#define OSD_VIDWINADH (OSD_REG_BASE + 0x28) #define OSD_WINADR(i) (OSD_REG_BASE + 0x2C + (i)*0x4) #define OSD_VIDWIN0ADR (OSD_REG_BASE + 0x2C) #define OSD_VIDWIN1ADR (OSD_REG_BASE + 0x30) +#define OSD_OSDWINADH (OSD_REG_BASE + 0x34) #define OSD_OSDWIN0ADR (OSD_REG_BASE + 0x38) #define OSD_OSDWIN1ADR (OSD_REG_BASE + 0x3C) #define OSD_BASEPX (OSD_REG_BASE + 0x40) @@ -202,6 +205,12 @@ #define VENC_VMOD_BLNK (1 << 3) #define VENC_VMOD_VIE (1 << 1) #define VENC_VMOD_VENC (1 << 0) + +#define VENC_VIDCTL_VCLKE (1 << 13) +#define VENC_VIDCTL_VCLKP (1 << 14) +#define VENC_SYNCCTL_HPL (1 << 2) +#define VENC_SYNCCTL_VPL (1 << 3) + /* other VENC registers' bit positions not defined yet */ #define OSD_MODE_CS (1 << 15) -- 1.7.0.4 _______________________________________________ Davinci-linux-open-source mailing list Davinci-linux-open-source@linux.davincidsp.com http://linux.davincidsp.com/mailman/listinfo/davinci-linux-open-source