⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 davincifb.c

📁 TI davinci DM6446 LCD 驱动程序。
💻 C
📖 第 1 页 / 共 4 页
字号:
	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 + -