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

📄 davincifb.c

📁 TI davinci DM6446 LCD 驱动程序。
💻 C
📖 第 1 页 / 共 4 页
字号:
	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 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_pal_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 PAL  */
		dispc_reg_out(VENC_VMOD, 0x1043);

		/* 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;
}

/* Logic Product Development
 * Ryan Link
 * DSP_Team
 */
static void davincifb_lcd_rgb_config(int on)
{
	DBGENTER;

	if (on) {
		/* Reset video encoder module */
		dispc_reg_out(VENC_VMOD, 0);

		// set LCD_OE to be active, enable RGB666 mode
		dispc_reg_merge(PINMUX0, 0x01400000, 0x01400000);

		// turn off REC656 mode
		dispc_reg_out(VENC_YCCCTL, 0x0);
		
		set_lcd_timings(default_lcd_timing.h_valid, default_lcd_timing.v_valid,
				default_lcd_timing.h_interval,   default_lcd_timing.v_interval,
				default_lcd_timing.h_pulse, default_lcd_timing.v_pulse,
				default_lcd_timing.h_start, default_lcd_timing.v_start,
				default_lcd_timing.h_delay, default_lcd_timing.v_delay,
				default_lcd_timing.hsync_pol,
				default_lcd_timing.vsync_pol,
				default_lcd_timing.oe_pol);
		
		// enable LCD_OE set active high
		//dispc_reg_out(VENC_LCDOUT, 0x0001);

		/* Enable VCLK */
		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);
		dispc_reg_out(VENC_DCLKPTN0A, 0x3);
		dispc_reg_out(VENC_DCLKPTN1A, 0x0);
		dispc_reg_out(VENC_DCLKPTN2A, 0x0);
		dispc_reg_out(VENC_DCLKPTN3A, 0x0);
		dispc_reg_out(VENC_OSDCLK1, 3);
		
		/* Enable VCLK */
		dispc_reg_out(VENC_VIDCTL, 0x2000);

		/* Enable RGB mode and enable VENC  */
		dispc_reg_out(VENC_VMOD, 0x2013);
	}
	else {
		/* Reset video encoder module */
		dispc_reg_out(VENC_VMOD, 0);
	}
	DBGEXIT;
}

static inline void fix_default_var(struct dm_win_info *w,
				   u32 xres, u32 yres, u32 xpos, u32 ypos,
				   int n_buf)
{
	struct fb_var_screeninfo *v = &w->info.var;

	v->xres = xres;
	v->yres = yres;
	v->xres_virtual = v->xres;
	v->yres_virtual = v->yres * n_buf;
	x_pos(w) = xpos;
	y_pos(w) = ypos;
}

/*
 *  Cleanup
 */
static int davincifb_remove(struct device *dev)
{
	DBGENTER;

	free_irq(IRQ_VENCINT, &dm);

	/* Cleanup all framebuffers */
	if (dm->osd0) {
		unregister_framebuffer(&dm->osd0->info);
		mem_release(dm->osd0);
	}
	if (dm->osd1) {
		unregister_framebuffer(&dm->osd1->info);
		mem_release(dm->osd1);
	}
	if (dm->vid0) {
		unregister_framebuffer(&dm->vid0->info);
		mem_release(dm->vid0);
	}
	if (dm->vid1) {
		unregister_framebuffer(&dm->vid1->info);
		mem_release(dm->vid1);
	}

	/* Turn OFF the output device */
	dm->output_device_config(0);

	if (dm->mmio_base)
		iounmap((void *)dm->mmio_base);
	release_mem_region(dm->mmio_base_phys, dm->mmio_size);

	DBGEXIT;
	return 0;
}

/*
 *  Initialization
 */
static int davincifb_probe(struct device *dev)
{
	struct platform_device *pdev;
	struct fb_info *info;

	DBGENTER;

	pdev = to_platform_device(dev);
	if (pdev->num_resources != 0) {
		dev_err(dev, "probed for an unknown device\n");
		return -ENODEV;
	}

	if (dmparams.windows == 0)
		return 0;	/* user disabled all windows through bootargs */
	dm->dev = dev;
	dm->mmio_base_phys = OSD_REG_BASE;
	dm->mmio_size = OSD_REG_SIZE;

	if (!request_mem_region
	    (dm->mmio_base_phys, dm->mmio_size, DAVINCIFB_DRIVER)) {
		dev_err(dev, ": cannot reserve MMIO region\n");
		RETURN(-ENODEV);
	}

	/* map the regions */
	dm->mmio_base =
	    (unsigned long)ioremap(dm->mmio_base_phys, dm->mmio_size);
	if (!dm->mmio_base) {
		dev_err(dev, ": cannot map MMIO\n");
		goto release_mmio;
	}

	/* initialize the vsync wait queue */
	init_waitqueue_head(&dm->vsync_wait);
	dm->timeout = HZ / 5;

	if ((dmparams.output == NTSC) && (dmparams.format == COMPOSITE))
		dm->output_device_config = davincifb_ntsc_composite_config;
	else if ((dmparams.output == NTSC) && (dmparams.format == SVIDEO))
		dm->output_device_config = davincifb_ntsc_svideo_config;
	else if ((dmparams.output == NTSC) && (dmparams.format == COMPONENT))
		dm->output_device_config = davincifb_ntsc_component_config;
	else if ((dmparams.output == PAL) && (dmparams.format == COMPOSITE))
		dm->output_device_config = davincifb_pal_composite_config;
	else if ((dmparams.output == PAL) && (dmparams.format == SVIDEO))
		dm->output_device_config = davincifb_pal_svideo_config;
	else if ((dmparams.output == PAL) && (dmparams.format == COMPONENT))
		dm->output_device_config = davincifb_pal_component_config;
	// Logic Product Development - Ryan Link - DSP_Team
	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");
		dm->output_device_config = NULL;
	}

	printk("Setting Up Clocks for DM420 OSD\n");

	/* Initialize the VPSS Clock Control register */
	dispc_reg_out(VPSS_CLKCTL, 0x18);

	/* Set Base Pixel X and Base Pixel Y */
	dispc_reg_out(OSD_BASEPX, BASEX);
	dispc_reg_out(OSD_BASEPY, BASEY);

	/* Reset OSD registers to default. */
	dispc_reg_out(OSD_MODE, 0);
	dispc_reg_out(OSD_OSDWIN0MD, 0);

	/* Set blue background color */
	set_bg_color(0, 162);

	/* Field Inversion Workaround */
	dispc_reg_out(OSD_MODE, 0x200);

	/* Setup VID0 framebuffer */
	if (!(dmparams.windows & (1 << VID0))) {
		printk(KERN_WARNING "No video/osd windows will be enabled "
		       "because Video0 is disabled\n");
		return 0;	/* background will still be shown */
	}
	/* Setup VID0 framebuffer */
	if (!mem_alloc(&dm->vid0, VID0_FB_PHY, VID0_FB_SIZE, VID0_FBNAME)) {
		dm->vid0->dm = dm;
		fix_default_var(dm->vid0,
				dmparams.vid0_xres, dmparams.vid0_yres,
				dmparams.vid0_xpos, dmparams.vid0_ypos,
				TRIPLE_BUF);
		info = init_fb_info(dm->vid0, &vid0_default_var, VID0_FBNAME);
		if (davincifb_check_var(&info->var, info)) {
			dev_err(dev, ": invalid default video mode\n");
			goto exit;
		}
		memset((void *)dm->vid0->fb_base, 0x88, dm->vid0->fb_size);
	} else
		goto exit;

	/* Setup OSD0 framebuffer */
	if ((dmparams.windows & (1 << OSD0)) &&
	    (!mem_alloc(&dm->osd0, OSD0_FB_PHY, OSD0_FB_SIZE, OSD0_FBNAME))) {
		dm->osd0->dm = dm;
		fix_default_var(dm->osd0,
				dmparams.osd0_xres, dmparams.osd0_yres,
				dmparams.osd0_xpos, dmparams.osd0_ypos,
				DOUBLE_BUF);
		info = init_fb_info(dm->osd0, &osd0_default_var, OSD0_FBNAME);
		if (davincifb_check_var(&info->var, info)) {
			dev_err(dev, ": invalid default video mode\n");
			mem_release(dm->osd0);
		} else
			memset((void *)dm->osd0->fb_base, 0, dm->osd0->fb_size);
	}

	/* Setup OSD1 framebuffer */
	if ((dmparams.windows & (1 << OSD1)) &&
	    (!mem_alloc(&dm->osd1, OSD1_FB_PHY, OSD1_FB_SIZE, OSD1_FBNAME))) {
		dm->osd1->dm = dm;
		fix_default_var(dm->osd1,
				dmparams.osd1_xres, dmparams.osd1_yres,
				dmparams.osd1_xpos, dmparams.osd1_ypos,
				DOUBLE_BUF);
		info = init_fb_info(dm->osd1, &osd1_default_var, OSD1_FBNAME);
		if (davincifb_check_var(&info->var, info)) {
			dev_err(dev, ": invalid default video mode\n");
			mem_release(dm->osd1);
		} else
			/* Set blend factor to show OSD windows */
			memset((void *)dm->osd1->fb_base, 0xff,
			       dm->osd1->fb_size);
	}

	/* Setup VID1 framebuffer */
	if ((dmparams.windows & (1 << VID1)) &&
	    (!mem_alloc(&dm->vid1, VID1_FB_PHY, VID1_FB_SIZE, VID1_FBNAME))) {
		dm->vid1->dm = dm;
		fix_default_var(dm->vid1,
				dmparams.vid1_xres, dmparams.vid1_yres,
				dmparams.vid1_xpos, dmparams.vid1_ypos,
				TRIPLE_BUF);
		info = init_fb_info(dm->vid1, &vid1_default_var, VID1_FBNAME);
		if (davincifb_check_var(&info->var, info)) {
			dev_err(dev,
				VID1_FBNAME ": invalid default video mode\n");
			mem_release(dm->vid1);
		} else
			memset((void *)dm->vid1->fb_base, 0x88,
			       dm->vid1->fb_size);
	}

	/* Register OSD0 framebuffer */
	if (dm->osd0) {
		info = &dm->osd0->info;
		if (register_framebuffer(info) < 0) {
			dev_err(dev, OSD0_FBNAME
				"Unable to register OSD0 framebuffer\n");
			mem_release(dm->osd0);
		} else {
			printk(KERN_INFO "fb%d: %s frame buffer device\n",
			       info->node, info->fix.id);
			davincifb_set_par(info);
		}
	}

	/* Register VID0 framebuffer */
	info = &dm->vid0->info;
	if (register_framebuffer(info) < 0) {
		dev_err(dev,
			VID0_FBNAME "Unable to register VID0 framebuffer\n");
		goto exit;
	} else {
		printk(KERN_INFO "fb%d: %s frame buffer device\n",
		       info->node, info->fix.id);
		davincifb_set_par(info);
	}

	/* Register OSD1 framebuffer */
	if (dm->osd1) {
		info = &dm->osd1->info;
		if (register_framebuffer(info) < 0) {
			dev_err(dev, OSD1_FBNAME
				"Unable to register OSD1 framebuffer\n");
			mem_release(dm->osd1);
		} else {
			printk(KERN_INFO "fb%d: %s frame buffer device\n",
			       info->node, info->fix.id);
			davincifb_set_par(info);
		}
	}

	/* Register VID1 framebuffer */
	if (dm->vid1) {
		info = &dm->vid1->info;
		if (register_framebuffer(info) < 0) {
			mem_release(dm->vid1);
			dev_err(dev, VID1_FBNAME
				"Unable to register VID1 framebuffer\n");
			mem_release(dm->vid1);
		} else {
			printk(KERN_INFO "fb%d: %s frame buffer device\n",
			       info->node, info->fix.id);
			davincifb_set_par(info);
		}
	}

	/* install our interrupt service routine */
	if (request_irq(IRQ_VENCINT, davincifb_isr, SA_SHIRQ, DAVINCIFB_DRIVER,
			dm)) {
		dev_err(dev, DAVINCIFB_DRIVER
			": could not install interrupt service routine\n");
		goto exit;
	}

	/* Turn ON the output device */
	dm->output_device_config(1);

	RETURN(0);

      exit:
	davincifb_remove(dev);
	RETURN(-ENODEV);

      unmap_mmio:
	iounmap((void *)dm->mmio_base);
      release_mmio:
	release_mem_region(dm->mmio_base_phys, dm->mmio_size);
	RETURN(-ENODEV);
}

/* ------------------------------------------------------------------------- */

    /*
     *  Frame buffer operations
     */
static struct fb_ops davincifb_ops = {
	.owner = THIS_MODULE,
	.fb_check_var = davincifb_check_var,
	.fb_set_par = davincifb_set_par,
	.fb_setcolreg = davincifb_setcolreg,
	.fb_blank = davincifb_blank,
	.fb_pan_display = davincifb_pan_display,
	.fb_fillrect = cfb_fillrect,
	.fb_copyarea = cfb_copyarea,
	.fb_imageblit = cfb_imageblit,
	.fb_cursor = soft_cursor,
	.fb_rotate = NULL,
	.fb_sync = NULL,
	.fb_ioctl = davincifb_ioctl,
};

static void davincifb_release_dev(struct device *dev)
{
}

static u64 davincifb_dmamask = ~(u32) 0;

static struct platform_device davincifb_device = {
	.name = DAVINCIFB_DEVICE,
	.id = 0,
	.dev = {
		.release = davincifb_release_dev,
		.dma_mask = &davincifb_dmamask,
		.coherent_dma_mask = 0xffffffff,
		},
	.num_resources = 0,
};

static struct device_driver davincifb_driver = {
	.name = DAVINCIFB_DRIVER,
	.bus = &platform_bus_type,
	.probe = davincifb_probe,
	.remove = davincifb_remove,
	.suspend = NULL,
	.resume = NULL,
};

/* Register both the driver and the device */
int __init davincifb_init(void)
{
	int r = 0;
	struct device *dev = &davincifb_device.dev;

	DBGENTER;

#ifndef MODULE
	{
		/* handle options for "dm64xxfb" for backwards compatability */
		char *option;
		char *names[] = { "davincifb", "dm64xxfb" };
		int i, num_names = 2, done = 0;

		for (i = 0; i < num_names && !done; i++) {
			if (fb_get_options(names[i], &option)) {
				printk(DAVINCIFB_DRIVER
				       ": Disabled on command-line.\n");
				r = -ENODEV;
				goto exit;
			} else if (option) {
				davincifb_setup(option);
				done = 1;
			}
		}
	}
#endif

	/* Register the device with LDM */
	if (platform_device_register(&davincifb_device)) {
		dev_err(dev, "failed to register davincifb device\n");
		r = -ENODEV;
		goto exit;
	}
	/* Register the driver with LDM */
	if (driver_register(&davincifb_driver)) {
		dev_err(dev, "failed to register davincifb driver\n");
		platform_device_unregister(&davincifb_device);
		r = -ENODEV;
		goto exit;
	}

      exit:
	DBGEXIT;
	return r;
}

static void __exit davincifb_cleanup(void)
{
	DBGENTER;

	driver_unregister(&davincifb_driver);
	platform_device_unregister(&davincifb_device);

	DBGEXIT;
}

module_init(davincifb_init);
module_exit(davincifb_cleanup);

MODULE_DESCRIPTION("Framebuffer driver for TI DaVinci");
MODULE_AUTHOR("Texas Instruments");
MODULE_LICENSE("GPL");

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -