📄 davincifb.c
字号:
if (info->fix.visual == FB_VISUAL_TRUECOLOR) {
u32 v;
if (regno >= 16)
RETURN(1);
red >>= (16 - info->var.red.length);
green >>= (16 - info->var.green.length);
blue >>= (16 - info->var.blue.length);
v = (red << info->var.red.offset) |
(green << info->var.green.offset) |
(blue << info->var.blue.offset);
switch (info->var.bits_per_pixel) {
case 16:
((u16 *) (info->pseudo_palette))[regno] = v;
break;
default:
RETURN(1);
}
RETURN(0);
}
RETURN(0);
}
/**
* davincifb_pan_display - NOT a required function. Pans the display.
* @var: frame buffer variable screen structure
* @info: frame buffer structure that represents a single frame buffer
*
* Pan (or wrap, depending on the `vmode' field) the display using the
* `xoffset' and `yoffset' fields of the `var' structure.
* If the values don't fit, return -EINVAL.
*
* Returns negative errno on error, or zero on success.
*/
static int davincifb_pan_display(struct fb_var_screeninfo *var,
struct fb_info *info)
{
struct dm_win_info *w = (struct dm_win_info *)info->par;
u32 start = 0, offset = 0;
DBGENTER;
if (var->xoffset > var->xres_virtual - var->xres)
RETURN(-EINVAL);
if (var->yoffset > var->yres_virtual - var->yres)
RETURN(-EINVAL);
if ((var->xres_virtual * var->bits_per_pixel / 8) % 32)
RETURN(-EINVAL);
offset = var->yoffset * info->fix.line_length +
var->xoffset * var->bits_per_pixel / 8;
start = (u32) w->fb_base_phys + offset;
if ((dispc_reg_in(VENC_VSTAT) & 0x00000010)==0x10)
set_sdram_params(info->fix.id, start, info->fix.line_length);
else
{
//this will get done in the ISR.Set a flag and retur
w->sdram_address = start;
}
RETURN(0);
}
/**
* davincifb_blank - NOT a required function. Blanks the display.
* @blank_mode: the blank mode we want.
* @info: frame buffer structure that represents a single frame buffer
*
* Blank the screen if blank_mode != 0, else unblank. Return 0 if
* blanking succeeded, != 0 if un-/blanking failed due to e.g. a
* video mode which doesn't support it. Implements VESA suspend
* and powerdown modes on hardware that supports disabling hsync/vsync:
* blank_mode == 2: suspend vsync
* blank_mode == 3: suspend hsync
* blank_mode == 4: powerdown
*
* Returns negative errno on error, or zero on success.
*
*/
static int davincifb_blank(int blank_mode, struct fb_info *info)
{
DBGENTER;
/* ... */
RETURN(0);
}
static int parse_win_params(char *wp,
int *xres, int *yres, int *xpos, int *ypos)
{
char *s;
if ((s = strsep(&wp, "x")) == NULL)
return -EINVAL;
*xres = simple_strtoul(s, NULL, 0);
if ((s = strsep(&wp, "@")) == NULL)
return -EINVAL;
*yres = simple_strtoul(s, NULL, 0);
if ((s = strsep(&wp, ",")) == NULL)
return -EINVAL;
*xpos = simple_strtoul(s, NULL, 0);
if ((s = strsep(&wp, ":")) == NULL)
return -EINVAL;
*ypos = simple_strtoul(s, NULL, 0);
return 0;
}
/*
* Pass boot-time options by adding the following string to the boot params:
* video=davincifb:[option[:option]]
* Valid options:
* output=[lcd|ntsc|pal]
* format=[composite|s-video|component|rgb]
* vid0=[off|MxN@X,Y]
* vid1=[off|MxN@X,Y]
* osd0=[off|MxN@X,Y]
* osd1=[off|MxN@X,Y]
* MxN specify the window resolution (displayed size)
* X,Y specify the window position
* M, N, X, Y are integers
* M, X should be multiples of 16
*/
#ifndef MODULE
int __init davincifb_setup(char *options)
{
char *this_opt;
u32 xres, yres, xpos, ypos;
int format_yres = 480;
DBGENTER;
printk("davincifb: Options \"%s\"\n", options);
if (!options || !*options)
return 0;
while ((this_opt = strsep(&options, ":")) != NULL) {
if (!*this_opt)
continue;
if (!strncmp(this_opt, "output=", 7)) {
if (!strncmp(this_opt + 7, "lcd", 3)) {
dmparams.output = LCD;
dmparams.format = 0;
} 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))
dmparams.format = SVIDEO;
else if (!strncmp(this_opt + 7, "component", 9))
dmparams.format = COMPONENT;
else if (!strncmp(this_opt + 7, "rgb", 3))
dmparams.format = RGB;
} else if (!strncmp(this_opt, "vid0=", 5)) {
if (!strncmp(this_opt + 5, "off", 3))
dmparams.windows &= ~(1 << VID0);
else if (!parse_win_params(this_opt + 5,
&xres, &yres, &xpos,
&ypos)) {
dmparams.vid0_xres = xres;
dmparams.vid0_yres = yres;
dmparams.vid0_xpos = xpos;
dmparams.vid0_ypos = ypos;
}
} else if (!strncmp(this_opt, "vid1=", 5)) {
if (!strncmp(this_opt + 5, "off", 3))
dmparams.windows &= ~(1 << VID1);
else if (!parse_win_params(this_opt + 5,
&xres, &yres, &xpos,
&ypos)) {
dmparams.vid1_xres = xres;
dmparams.vid1_yres = yres;
dmparams.vid1_xpos = xpos;
dmparams.vid1_ypos = ypos;
}
} else if (!strncmp(this_opt, "osd0=", 5)) {
if (!strncmp(this_opt + 5, "off", 3))
dmparams.windows &= ~(1 << OSD0);
else if (!parse_win_params(this_opt + 5,
&xres, &yres, &xpos,
&ypos)) {
dmparams.osd0_xres = xres;
dmparams.osd0_yres = yres;
dmparams.osd0_xpos = xpos;
dmparams.osd0_ypos = ypos;
}
} else if (!strncmp(this_opt, "osd1=", 5)) {
if (!strncmp(this_opt + 5, "off", 3))
dmparams.windows &= ~(1 << OSD1);
else if (!parse_win_params(this_opt + 5,
&xres, &yres, &xpos,
&ypos)) {
dmparams.osd1_xres = xres;
dmparams.osd1_yres = yres;
dmparams.osd1_xpos = xpos;
dmparams.osd1_ypos = ypos;
}
}
}
printk(KERN_INFO "DaVinci: "
"Output on %s%s, Enabled windows: %s %s %s %s\n",
(dmparams.output == LCD) ? "LCD" :
(dmparams.output == NTSC) ? "NTSC" :
(dmparams.output == PAL) ? "PAL" : "unknown device!",
(dmparams.format == 0) ? "" :
(dmparams.format == COMPOSITE) ? " in COMPOSITE format" :
(dmparams.format == SVIDEO) ? " in SVIDEO format" :
(dmparams.format == COMPONENT) ? " in COMPONENT format" :
(dmparams.format == RGB) ? " in RGB format" : "",
(dmparams.windows & (1 << VID0)) ? "Video0" : "",
(dmparams.windows & (1 << VID1)) ? "Video1" : "",
(dmparams.windows & (1 << OSD0)) ? "OSD0" : "",
(dmparams.windows & (1 << OSD1)) ? "OSD1" : "");
if (dmparams.output == NTSC) {
format_yres = 480;
} else if (dmparams.output == PAL) {
format_yres = 576;
} else {
printk(KERN_INFO
"DaVinci:invalid format..defaulting width to 480\n");
}
dmparams.osd0_yres = osd0_default_var.yres = format_yres;
dmparams.osd1_yres = osd1_default_var.yres = format_yres;
dmparams.vid0_yres = vid0_default_var.yres = format_yres;
dmparams.vid1_yres = vid1_default_var.yres = format_yres;
osd0_default_var.yres_virtual = format_yres * DOUBLE_BUF;
osd1_default_var.yres_virtual = format_yres * DOUBLE_BUF;
vid0_default_var.yres_virtual = format_yres * TRIPLE_BUF;
vid1_default_var.yres_virtual = format_yres * TRIPLE_BUF;
if (dmparams.windows & (1 << VID0))
printk(KERN_INFO "Setting Video0 size %dx%d, "
"position (%d,%d)\n",
dmparams.vid0_xres, dmparams.vid0_yres,
dmparams.vid0_xpos, dmparams.vid0_ypos);
if (dmparams.windows & (1 << VID1))
printk(KERN_INFO "Setting Video1 size %dx%d, "
"position (%d,%d)\n",
dmparams.vid1_xres, dmparams.vid1_yres,
dmparams.vid1_xpos, dmparams.vid1_ypos);
if (dmparams.windows & (1 << OSD0))
printk(KERN_INFO "Setting OSD0 size %dx%d, "
"position (%d,%d)\n",
dmparams.osd0_xres, dmparams.osd0_yres,
dmparams.osd0_xpos, dmparams.osd0_ypos);
if (dmparams.windows & (1 << OSD1))
printk(KERN_INFO "Setting OSD1 size %dx%d, "
"position (%d,%d)\n",
dmparams.osd1_xres, dmparams.osd1_yres,
dmparams.osd1_xpos, dmparams.osd1_ypos);
RETURN(0);
}
#endif
static int mem_release(struct dm_win_info *w)
{
DBGENTER;
if (!w->alloc_fb_mem) {
iounmap((void *)w->fb_base);
release_mem_region(w->fb_base_phys, w->fb_size);
} else
dma_free_coherent(NULL, w->fb_size, (void *)w->fb_base,
w->fb_base_phys);
kfree(w);
RETURN(0);
}
static int mem_alloc(struct dm_win_info **win, dma_addr_t fb_base_phys,
unsigned long fb_size, char *fbname)
{
struct dm_win_info *w;
struct device *dev = dm->dev;
DBGENTER;
w = kmalloc(sizeof(struct dm_win_info), GFP_KERNEL);
if (!w) {
dev_err(dev, "%s: could not allocate memory\n", fbname);
RETURN(-ENOMEM);
}
memset(w, 0, sizeof(struct dm_win_info));
w->fb_base_phys = fb_base_phys;
w->fb_size = fb_size;
/* A null base address indicates that the framebuffer memory should be
* dynamically allocated.
*/
if (!w->fb_base_phys)
w->alloc_fb_mem = 1;
if (!w->alloc_fb_mem) {
if (!request_mem_region(w->fb_base_phys, w->fb_size, fbname)) {
dev_err(dev, "%s: cannot reserve FB region\n", fbname);
goto free_par;
}
w->fb_base =
(unsigned long)ioremap(w->fb_base_phys, w->fb_size);
if (!w->fb_base) {
dev_err(dev, "%s: cannot map framebuffer\n", fbname);
goto release_fb;
}
} else {
/* allocate coherent memory for the framebuffer */
w->fb_base = (unsigned long)dma_alloc_coherent(dev,
w->fb_size,
&w->fb_base_phys,
GFP_KERNEL |
GFP_DMA);
if (!w->fb_base) {
dev_err(dev, "%s: cannot allocate framebuffer\n",
fbname);
goto free_par;
}
dev_dbg(dev, "Framebuffer allocated at 0x%x "
"mapped to 0x%x, size %dk\n",
(unsigned)w->fb_base_phys, (unsigned)w->fb_base,
(unsigned)w->fb_size / 1024);
}
*win = w;
RETURN(0);
release_fb:
if (!w->alloc_fb_mem)
release_mem_region(w->fb_base_phys, w->fb_size);
free_par:
kfree(w);
RETURN(-ENOMEM);
}
static struct fb_info *init_fb_info(struct dm_win_info *w,
struct fb_var_screeninfo *var, char *id)
{
struct fb_info *info = &(w->info);
struct dm_info *dm = w->dm;
DBGENTER;
/* initialize the fb_info structure */
info->flags = FBINFO_DEFAULT;
info->fbops = &davincifb_ops;
info->screen_base = (char *)(w->fb_base);
/* info->currcon = -1; */
info->pseudo_palette = w->pseudo_palette;
info->par = w;
/* Initialize variable screeninfo.
* The variable screeninfo can be directly specified by the user
* via an ioctl.
*/
memcpy(&info->var, var, sizeof(info->var));
info->var.activate = FB_ACTIVATE_NOW;
/* Initialize fixed screeninfo.
* The fixed screeninfo cannot be directly specified by the user, but
* it may change to reflect changes to the var info.
*/
strlcpy(info->fix.id, id, sizeof(info->fix.id));
info->fix.smem_start = w->fb_base_phys;
info->fix.line_length =
(info->var.xres_virtual * info->var.bits_per_pixel) / 8;
info->fix.smem_len = w->fb_size;
info->fix.type = FB_TYPE_PACKED_PIXELS;
info->fix.visual = (info->var.bits_per_pixel <= 8) ?
FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
info->fix.xpanstep = 0;
info->fix.ypanstep = 0;
info->fix.ywrapstep = 0;
// Logic Product Development - Ryan Link - DSP_Team
if(dmparams.output == LCD && dmparams.format == RGB){
info->fix.type_aux = 1; // no interlacing
}
else{
info->fix.type_aux = 0; // interlacing
}
info->fix.mmio_start = dm->mmio_base_phys;
info->fix.mmio_len = dm->mmio_size;
info->fix.accel = FB_ACCEL_NONE;
w->sdram_address = NULL;
DBGEXIT;
return info;
}
static void davincifb_ntsc_composite_config(int on)
{
DBGENTER;
if (on) {
/* Reset video encoder module */
dispc_reg_out(VENC_VMOD, 0);
/* Enable Composite output and start video encoder */
dispc_reg_out(VENC_VMOD, (VENC_VMOD_VIE | VENC_VMOD_VENC));
/* Set REC656 Mode */
dispc_reg_out(VENC_YCCCTL, 0x1);
/* Enable output mode and NTSC */
dispc_reg_out(VENC_VMOD, 0x1003);
/* Enable all DACs */
dispc_reg_out(VENC_DACTST, 0);
} else {
/* Reset video encoder module */
dispc_reg_out(VENC_VMOD, 0);
}
DBGEXIT;
}
static void davincifb_ntsc_svideo_config(int on)
{
DBGENTER;
if (on) {
/* Reset video encoder module */
dispc_reg_out(VENC_VMOD, 0);
/* Enable Composite output and start video encoder */
dispc_reg_out(VENC_VMOD, (VENC_VMOD_VIE | VENC_VMOD_VENC));
/* Set REC656 Mode */
dispc_reg_out(VENC_YCCCTL, 0x1);
/* Enable output mode and NTSC */
dispc_reg_out(VENC_VMOD, 0x1003);
/* Enable S-Video Output; DAC B: S-Video Y, DAC C: S-Video C */
dispc_reg_out(VENC_DACSEL, 0x210);
/* Enable all DACs */
dispc_reg_out(VENC_DACTST, 0);
} else {
/* Reset video encoder module */
dispc_reg_out(VENC_VMOD, 0);
}
DBGEXIT;
}
static void davincifb_ntsc_component_config(int on)
{
DBGENTER;
if (on) {
/* Reset video encoder module */
dispc_reg_out(VENC_VMOD, 0);
/* Enable Composite output and start video encoder */
dispc_reg_out(VENC_VMOD, (VENC_VMOD_VIE | VENC_VMOD_VENC));
/* Set REC656 Mode */
dispc_reg_out(VENC_YCCCTL, 0x1);
/* Enable output mode and NTSC */
dispc_reg_out(VENC_VMOD, 0x1003);
/* Enable Component output; DAC A: Y, DAC B: Pb, DAC C: Pr */
dispc_reg_out(VENC_DACSEL, 0x543);
/* Enable all DACs */
dispc_reg_out(VENC_DACTST, 0);
} else {
/* Reset video encoder module */
dispc_reg_out(VENC_VMOD, 0);
}
DBGEXIT;
}
static void davincifb_pal_composite_config(int on)
{
DBGENTER;
if (on) {
/* Reset video encoder module */
dispc_reg_out(VENC_VMOD, 0);
/* Enable Composite output and start video encoder */
dispc_reg_out(VENC_VMOD, (VENC_VMOD_VIE | VENC_VMOD_VENC));
/* Set REC656 Mode */
dispc_reg_out(VENC_YCCCTL, 0x1);
/* Enable output mode and PAL */
dispc_reg_out(VENC_VMOD, 0x1043);
/* Enable all DACs */
dispc_reg_out(VENC_DACTST, 0);
} else {
/* Reset video encoder module */
dispc_reg_out(VENC_VMOD, 0);
}
DBGEXIT;
}
static void davincifb_pal_svideo_config(int on)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -