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

📄 dma.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
	int active;	unsigned long addr, size;	int rotate, data_type, xres, yres;	int vxres;	int mirror;	int xscale, yscale;	int ext_ctrl;	int src_port;	int single_transfer;} lcd_dma;void omap_set_lcd_dma_b1(unsigned long addr, u16 fb_xres, u16 fb_yres,			 int data_type){	lcd_dma.addr = addr;	lcd_dma.data_type = data_type;	lcd_dma.xres = fb_xres;	lcd_dma.yres = fb_yres;}void omap_set_lcd_dma_src_port(int port){	lcd_dma.src_port = port;}void omap_set_lcd_dma_ext_controller(int external){	lcd_dma.ext_ctrl = external;}void omap_set_lcd_dma_single_transfer(int single){	lcd_dma.single_transfer = single;}void omap_set_lcd_dma_b1_rotation(int rotate){	if (omap_dma_in_1510_mode()) {		printk(KERN_ERR "DMA rotation is not supported in 1510 mode\n");		BUG();		return;	}	lcd_dma.rotate = rotate;}void omap_set_lcd_dma_b1_mirror(int mirror){	if (omap_dma_in_1510_mode()) {		printk(KERN_ERR "DMA mirror is not supported in 1510 mode\n");		BUG();	}	lcd_dma.mirror = mirror;}void omap_set_lcd_dma_b1_vxres(unsigned long vxres){	if (omap_dma_in_1510_mode()) {		printk(KERN_ERR "DMA virtual resulotion is not supported "				"in 1510 mode\n");		BUG();	}	lcd_dma.vxres = vxres;}void omap_set_lcd_dma_b1_scale(unsigned int xscale, unsigned int yscale){	if (omap_dma_in_1510_mode()) {		printk(KERN_ERR "DMA scale is not supported in 1510 mode\n");		BUG();	}	lcd_dma.xscale = xscale;	lcd_dma.yscale = yscale;}static void set_b1_regs(void){	unsigned long top, bottom;	int es;	u16 w;	unsigned long en, fn;	long ei, fi;	unsigned long vxres;	unsigned int xscale, yscale;	switch (lcd_dma.data_type) {	case OMAP_DMA_DATA_TYPE_S8:		es = 1;		break;	case OMAP_DMA_DATA_TYPE_S16:		es = 2;		break;	case OMAP_DMA_DATA_TYPE_S32:		es = 4;		break;	default:		BUG();		return;	}	vxres = lcd_dma.vxres ? lcd_dma.vxres : lcd_dma.xres;	xscale = lcd_dma.xscale ? lcd_dma.xscale : 1;	yscale = lcd_dma.yscale ? lcd_dma.yscale : 1;	BUG_ON(vxres < lcd_dma.xres);#define PIXADDR(x,y) (lcd_dma.addr + ((y) * vxres * yscale + (x) * xscale) * es)#define PIXSTEP(sx, sy, dx, dy) (PIXADDR(dx, dy) - PIXADDR(sx, sy) - es + 1)	switch (lcd_dma.rotate) {	case 0:		if (!lcd_dma.mirror) {			top = PIXADDR(0, 0);			bottom = PIXADDR(lcd_dma.xres - 1, lcd_dma.yres - 1);			/* 1510 DMA requires the bottom address to be 2 more			 * than the actual last memory access location. */			if (omap_dma_in_1510_mode() &&			    lcd_dma.data_type == OMAP_DMA_DATA_TYPE_S32)				bottom += 2;			ei = PIXSTEP(0, 0, 1, 0);			fi = PIXSTEP(lcd_dma.xres - 1, 0, 0, 1);		} else {			top = PIXADDR(lcd_dma.xres - 1, 0);			bottom = PIXADDR(0, lcd_dma.yres - 1);			ei = PIXSTEP(1, 0, 0, 0);			fi = PIXSTEP(0, 0, lcd_dma.xres - 1, 1);		}		en = lcd_dma.xres;		fn = lcd_dma.yres;		break;	case 90:		if (!lcd_dma.mirror) {			top = PIXADDR(0, lcd_dma.yres - 1);			bottom = PIXADDR(lcd_dma.xres - 1, 0);			ei = PIXSTEP(0, 1, 0, 0);			fi = PIXSTEP(0, 0, 1, lcd_dma.yres - 1);		} else {			top = PIXADDR(lcd_dma.xres - 1, lcd_dma.yres - 1);			bottom = PIXADDR(0, 0);			ei = PIXSTEP(0, 1, 0, 0);			fi = PIXSTEP(1, 0, 0, lcd_dma.yres - 1);		}		en = lcd_dma.yres;		fn = lcd_dma.xres;		break;	case 180:		if (!lcd_dma.mirror) {			top = PIXADDR(lcd_dma.xres - 1, lcd_dma.yres - 1);			bottom = PIXADDR(0, 0);			ei = PIXSTEP(1, 0, 0, 0);			fi = PIXSTEP(0, 1, lcd_dma.xres - 1, 0);		} else {			top = PIXADDR(0, lcd_dma.yres - 1);			bottom = PIXADDR(lcd_dma.xres - 1, 0);			ei = PIXSTEP(0, 0, 1, 0);			fi = PIXSTEP(lcd_dma.xres - 1, 1, 0, 0);		}		en = lcd_dma.xres;		fn = lcd_dma.yres;		break;	case 270:		if (!lcd_dma.mirror) {			top = PIXADDR(lcd_dma.xres - 1, 0);			bottom = PIXADDR(0, lcd_dma.yres - 1);			ei = PIXSTEP(0, 0, 0, 1);			fi = PIXSTEP(1, lcd_dma.yres - 1, 0, 0);		} else {			top = PIXADDR(0, 0);			bottom = PIXADDR(lcd_dma.xres - 1, lcd_dma.yres - 1);			ei = PIXSTEP(0, 0, 0, 1);			fi = PIXSTEP(0, lcd_dma.yres - 1, 1, 0);		}		en = lcd_dma.yres;		fn = lcd_dma.xres;		break;	default:		BUG();		return;	/* Suppress warning about uninitialized vars */	}	if (omap_dma_in_1510_mode()) {		omap_writew(top >> 16, OMAP1510_DMA_LCD_TOP_F1_U);		omap_writew(top, OMAP1510_DMA_LCD_TOP_F1_L);		omap_writew(bottom >> 16, OMAP1510_DMA_LCD_BOT_F1_U);		omap_writew(bottom, OMAP1510_DMA_LCD_BOT_F1_L);		return;	}	/* 1610 regs */	omap_writew(top >> 16, OMAP1610_DMA_LCD_TOP_B1_U);	omap_writew(top, OMAP1610_DMA_LCD_TOP_B1_L);	omap_writew(bottom >> 16, OMAP1610_DMA_LCD_BOT_B1_U);	omap_writew(bottom, OMAP1610_DMA_LCD_BOT_B1_L);	omap_writew(en, OMAP1610_DMA_LCD_SRC_EN_B1);	omap_writew(fn, OMAP1610_DMA_LCD_SRC_FN_B1);	w = omap_readw(OMAP1610_DMA_LCD_CSDP);	w &= ~0x03;	w |= lcd_dma.data_type;	omap_writew(w, OMAP1610_DMA_LCD_CSDP);	w = omap_readw(OMAP1610_DMA_LCD_CTRL);	/* Always set the source port as SDRAM for now*/	w &= ~(0x03 << 6);	if (lcd_dma.callback != NULL)		w |= 1 << 1;		/* Block interrupt enable */	else		w &= ~(1 << 1);	omap_writew(w, OMAP1610_DMA_LCD_CTRL);	if (!(lcd_dma.rotate || lcd_dma.mirror ||	      lcd_dma.vxres || lcd_dma.xscale || lcd_dma.yscale))		return;	w = omap_readw(OMAP1610_DMA_LCD_CCR);	/* Set the double-indexed addressing mode */	w |= (0x03 << 12);	omap_writew(w, OMAP1610_DMA_LCD_CCR);	omap_writew(ei, OMAP1610_DMA_LCD_SRC_EI_B1);	omap_writew(fi >> 16, OMAP1610_DMA_LCD_SRC_FI_B1_U);	omap_writew(fi, OMAP1610_DMA_LCD_SRC_FI_B1_L);}static irqreturn_t lcd_dma_irq_handler(int irq, void *dev_id){	u16 w;	w = omap_readw(OMAP1610_DMA_LCD_CTRL);	if (unlikely(!(w & (1 << 3)))) {		printk(KERN_WARNING "Spurious LCD DMA IRQ\n");		return IRQ_NONE;	}	/* Ack the IRQ */	w |= (1 << 3);	omap_writew(w, OMAP1610_DMA_LCD_CTRL);	lcd_dma.active = 0;	if (lcd_dma.callback != NULL)		lcd_dma.callback(w, lcd_dma.cb_data);	return IRQ_HANDLED;}int omap_request_lcd_dma(void (* callback)(u16 status, void *data),			 void *data){	spin_lock_irq(&lcd_dma.lock);	if (lcd_dma.reserved) {		spin_unlock_irq(&lcd_dma.lock);		printk(KERN_ERR "LCD DMA channel already reserved\n");		BUG();		return -EBUSY;	}	lcd_dma.reserved = 1;	spin_unlock_irq(&lcd_dma.lock);	lcd_dma.callback = callback;	lcd_dma.cb_data = data;	lcd_dma.active = 0;	lcd_dma.single_transfer = 0;	lcd_dma.rotate = 0;	lcd_dma.vxres = 0;	lcd_dma.mirror = 0;	lcd_dma.xscale = 0;	lcd_dma.yscale = 0;	lcd_dma.ext_ctrl = 0;	lcd_dma.src_port = 0;	return 0;}void omap_free_lcd_dma(void){	spin_lock(&lcd_dma.lock);	if (!lcd_dma.reserved) {		spin_unlock(&lcd_dma.lock);		printk(KERN_ERR "LCD DMA is not reserved\n");		BUG();		return;	}	if (!enable_1510_mode)		omap_writew(omap_readw(OMAP1610_DMA_LCD_CCR) & ~1,			    OMAP1610_DMA_LCD_CCR);	lcd_dma.reserved = 0;	spin_unlock(&lcd_dma.lock);}void omap_enable_lcd_dma(void){	u16 w;	/* Set the Enable bit only if an external controller is	 * connected. Otherwise the OMAP internal controller will	 * start the transfer when it gets enabled.	 */	if (enable_1510_mode || !lcd_dma.ext_ctrl)		return;	w = omap_readw(OMAP1610_DMA_LCD_CTRL);	w |= 1 << 8;	omap_writew(w, OMAP1610_DMA_LCD_CTRL);	lcd_dma.active = 1;	w = omap_readw(OMAP1610_DMA_LCD_CCR);	w |= 1 << 7;	omap_writew(w, OMAP1610_DMA_LCD_CCR);}void omap_setup_lcd_dma(void){	BUG_ON(lcd_dma.active);	if (!enable_1510_mode) {		/* Set some reasonable defaults */		omap_writew(0x5440, OMAP1610_DMA_LCD_CCR);		omap_writew(0x9102, OMAP1610_DMA_LCD_CSDP);		omap_writew(0x0004, OMAP1610_DMA_LCD_LCH_CTRL);	}	set_b1_regs();	if (!enable_1510_mode) {		u16 w;		w = omap_readw(OMAP1610_DMA_LCD_CCR);		/* If DMA was already active set the end_prog bit to have		 * the programmed register set loaded into the active		 * register set.		 */		w |= 1 << 11;		/* End_prog */		if (!lcd_dma.single_transfer)	        	w |= (3 << 8);	/* Auto_init, repeat */		omap_writew(w, OMAP1610_DMA_LCD_CCR);	}}void omap_stop_lcd_dma(void){	u16 w;	lcd_dma.active = 0;	if (enable_1510_mode || !lcd_dma.ext_ctrl)		return;	w = omap_readw(OMAP1610_DMA_LCD_CCR);	w &= ~(1 << 7);	omap_writew(w, OMAP1610_DMA_LCD_CCR);	w = omap_readw(OMAP1610_DMA_LCD_CTRL);	w &= ~(1 << 8);	omap_writew(w, OMAP1610_DMA_LCD_CTRL);}/*----------------------------------------------------------------------------*/static int __init omap_init_dma(void){	int ch, r;	if (cpu_is_omap15xx()) {		printk(KERN_INFO "DMA support for OMAP15xx initialized\n");		dma_chan_count = 9;		enable_1510_mode = 1;	} else if (cpu_is_omap16xx() || cpu_is_omap730()) {		printk(KERN_INFO "OMAP DMA hardware version %d\n",		       omap_readw(OMAP_DMA_HW_ID));		printk(KERN_INFO "DMA capabilities: %08x:%08x:%04x:%04x:%04x\n",		       (omap_readw(OMAP_DMA_CAPS_0_U) << 16) |		       omap_readw(OMAP_DMA_CAPS_0_L),		       (omap_readw(OMAP_DMA_CAPS_1_U) << 16) |		       omap_readw(OMAP_DMA_CAPS_1_L),		       omap_readw(OMAP_DMA_CAPS_2), omap_readw(OMAP_DMA_CAPS_3),		       omap_readw(OMAP_DMA_CAPS_4));		if (!enable_1510_mode) {			u16 w;			/* Disable OMAP 3.0/3.1 compatibility mode. */			w = omap_readw(OMAP_DMA_GSCR);			w |= 1 << 3;			omap_writew(w, OMAP_DMA_GSCR);			dma_chan_count = 16;		} else			dma_chan_count = 9;		if (cpu_is_omap16xx()) {			u16 w;			/* this would prevent OMAP sleep */			w = omap_readw(OMAP1610_DMA_LCD_CTRL);			w &= ~(1 << 8);			omap_writew(w, OMAP1610_DMA_LCD_CTRL);		}	} else if (cpu_is_omap24xx()) {		u8 revision = omap_readb(OMAP_DMA4_REVISION);		printk(KERN_INFO "OMAP DMA hardware revision %d.%d\n",		       revision >> 4, revision & 0xf);		dma_chan_count = OMAP_LOGICAL_DMA_CH_COUNT;	} else {		dma_chan_count = 0;		return 0;	}	memset(&lcd_dma, 0, sizeof(lcd_dma));	spin_lock_init(&lcd_dma.lock);	spin_lock_init(&dma_chan_lock);	memset(&dma_chan, 0, sizeof(dma_chan));	for (ch = 0; ch < dma_chan_count; ch++) {		omap_clear_dma(ch);		dma_chan[ch].dev_id = -1;		dma_chan[ch].next_lch = -1;		if (ch >= 6 && enable_1510_mode)			continue;		if (cpu_class_is_omap1()) {			/* request_irq() doesn't like dev_id (ie. ch) being			 * zero, so we have to kludge around this. */			r = request_irq(omap1_dma_irq[ch],					omap1_dma_irq_handler, 0, "DMA",					(void *) (ch + 1));			if (r != 0) {				int i;				printk(KERN_ERR "unable to request IRQ %d "				       "for DMA (error %d)\n",				       omap1_dma_irq[ch], r);				for (i = 0; i < ch; i++)					free_irq(omap1_dma_irq[i],						 (void *) (i + 1));				return r;			}		}	}	if (cpu_is_omap24xx())		setup_irq(INT_24XX_SDMA_IRQ0, &omap24xx_dma_irq);	/* FIXME: Update LCD DMA to work on 24xx */	if (cpu_class_is_omap1()) {		r = request_irq(INT_DMA_LCD, lcd_dma_irq_handler, 0,				"LCD DMA", NULL);		if (r != 0) {			int i;			printk(KERN_ERR "unable to request IRQ for LCD DMA "			       "(error %d)\n", r);			for (i = 0; i < dma_chan_count; i++)				free_irq(omap1_dma_irq[i], (void *) (i + 1));			return r;		}	}	return 0;}arch_initcall(omap_init_dma);EXPORT_SYMBOL(omap_get_dma_src_pos);EXPORT_SYMBOL(omap_get_dma_dst_pos);EXPORT_SYMBOL(omap_get_dma_src_addr_counter);EXPORT_SYMBOL(omap_clear_dma);EXPORT_SYMBOL(omap_set_dma_priority);EXPORT_SYMBOL(omap_request_dma);EXPORT_SYMBOL(omap_free_dma);EXPORT_SYMBOL(omap_start_dma);EXPORT_SYMBOL(omap_stop_dma);EXPORT_SYMBOL(omap_set_dma_callback);EXPORT_SYMBOL(omap_enable_dma_irq);EXPORT_SYMBOL(omap_disable_dma_irq);EXPORT_SYMBOL(omap_set_dma_transfer_params);EXPORT_SYMBOL(omap_set_dma_color_mode);EXPORT_SYMBOL(omap_set_dma_write_mode);EXPORT_SYMBOL(omap_set_dma_src_params);EXPORT_SYMBOL(omap_set_dma_src_index);EXPORT_SYMBOL(omap_set_dma_src_data_pack);EXPORT_SYMBOL(omap_set_dma_src_burst_mode);EXPORT_SYMBOL(omap_set_dma_dest_params);EXPORT_SYMBOL(omap_set_dma_dest_index);EXPORT_SYMBOL(omap_set_dma_dest_data_pack);EXPORT_SYMBOL(omap_set_dma_dest_burst_mode);EXPORT_SYMBOL(omap_set_dma_params);EXPORT_SYMBOL(omap_dma_link_lch);EXPORT_SYMBOL(omap_dma_unlink_lch);EXPORT_SYMBOL(omap_request_lcd_dma);EXPORT_SYMBOL(omap_free_lcd_dma);EXPORT_SYMBOL(omap_enable_lcd_dma);EXPORT_SYMBOL(omap_setup_lcd_dma);EXPORT_SYMBOL(omap_stop_lcd_dma);EXPORT_SYMBOL(omap_set_lcd_dma_b1);EXPORT_SYMBOL(omap_set_lcd_dma_single_transfer);EXPORT_SYMBOL(omap_set_lcd_dma_ext_controller);EXPORT_SYMBOL(omap_set_lcd_dma_b1_rotation);EXPORT_SYMBOL(omap_set_lcd_dma_b1_vxres);EXPORT_SYMBOL(omap_set_lcd_dma_b1_scale);EXPORT_SYMBOL(omap_set_lcd_dma_b1_mirror);

⌨️ 快捷键说明

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