Esempio n. 1
0
File: dma.c Progetto: 1x23/unifi-gpl
static irqreturn_t iomd_dma_handle(int irq, void *dev_id, struct pt_regs *regs)
{
	dma_t *dma = (dma_t *)dev_id;
	unsigned long base = dma->dma_base;

	do {
		unsigned int status;

		status = iomd_readb(base + ST);
		if (!(status & DMA_ST_INT))
			return IRQ_HANDLED;

		if ((dma->state ^ status) & DMA_ST_AB)
			iomd_get_next_sg(&dma->cur_sg, dma);

		switch (status & (DMA_ST_OFL | DMA_ST_AB)) {
		case DMA_ST_OFL:			/* OIA */
		case DMA_ST_AB:				/* .IB */
			iomd_writel(dma->cur_sg.dma_address, base + CURA);
			iomd_writel(dma->cur_sg.length, base + ENDA);
			dma->state = DMA_ST_AB;
			break;

		case DMA_ST_OFL | DMA_ST_AB:		/* OIB */
		case 0:					/* .IA */
			iomd_writel(dma->cur_sg.dma_address, base + CURB);
			iomd_writel(dma->cur_sg.length, base + ENDB);
			dma->state = 0;
			break;
		}

		if (status & DMA_ST_OFL &&
		    dma->cur_sg.length == (DMA_END_S|DMA_END_L))
			break;
	} while (1);

	dma->state = ~DMA_ST_AB;
	disable_irq(irq);

	return IRQ_HANDLED;
}
Esempio n. 2
0
static irqreturn_t iomd_dma_handle(int irq, void *dev_id)
{
	struct iomd_dma *idma = dev_id;
	unsigned long base = idma->base;

	do {
		unsigned int status;

		status = iomd_readb(base + ST);
		if (!(status & DMA_ST_INT))
			return IRQ_HANDLED;

		if ((idma->state ^ status) & DMA_ST_AB)
			iomd_get_next_sg(&idma->cur_sg, idma);

		switch (status & (DMA_ST_OFL | DMA_ST_AB)) {
		case DMA_ST_OFL:			
		case DMA_ST_AB:				
			iomd_writel(idma->cur_sg.dma_address, base + CURA);
			iomd_writel(idma->cur_sg.length, base + ENDA);
			idma->state = DMA_ST_AB;
			break;

		case DMA_ST_OFL | DMA_ST_AB:		
		case 0:					
			iomd_writel(idma->cur_sg.dma_address, base + CURB);
			iomd_writel(idma->cur_sg.length, base + ENDB);
			idma->state = 0;
			break;
		}

		if (status & DMA_ST_OFL &&
		    idma->cur_sg.length == (DMA_END_S|DMA_END_L))
			break;
	} while (1);

	idma->state = ~DMA_ST_AB;
	disable_irq(irq);

	return IRQ_HANDLED;
}
Esempio n. 3
0
/* VIDC20 has a different set of rules from the VIDC:
 *  hcr  : must be multiple of 4
 *  hswr : must be even
 *  hdsr : must be even
 *  hder : must be even
 *  vcr  : >= 2, (interlace, must be odd)
 *  vswr : >= 1
 *  vdsr : >= 1
 *  vder : >= vdsr
 */
static void acornfb_set_timing(struct fb_info *info)
{
	struct fb_var_screeninfo *var = &info->var;
	struct vidc_timing vidc;
	u_int vcr, fsize;
	u_int ext_ctl, dat_ctl;
	u_int words_per_line;

	memset(&vidc, 0, sizeof(vidc));

	vidc.h_sync_width	= var->hsync_len - 8;
	vidc.h_border_start	= vidc.h_sync_width + var->left_margin + 8 - 12;
	vidc.h_display_start	= vidc.h_border_start + 12 - 18;
	vidc.h_display_end	= vidc.h_display_start + var->xres;
	vidc.h_border_end	= vidc.h_display_end + 18 - 12;
	vidc.h_cycle		= vidc.h_border_end + var->right_margin + 12 - 8;
	vidc.h_interlace	= vidc.h_cycle / 2;
	vidc.v_sync_width	= var->vsync_len - 1;
	vidc.v_border_start	= vidc.v_sync_width + var->upper_margin;
	vidc.v_display_start	= vidc.v_border_start;
	vidc.v_display_end	= vidc.v_display_start + var->yres;
	vidc.v_border_end	= vidc.v_display_end;
	vidc.control		= acornfb_default_control();

	vcr = var->vsync_len + var->upper_margin + var->yres +
	      var->lower_margin;

	if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
		vidc.v_cycle = (vcr - 3) / 2;
		vidc.control |= VIDC20_CTRL_INT;
	} else
		vidc.v_cycle = vcr - 2;

	switch (var->bits_per_pixel) {
	case  1: vidc.control |= VIDC20_CTRL_1BPP;	break;
	case  2: vidc.control |= VIDC20_CTRL_2BPP;	break;
	case  4: vidc.control |= VIDC20_CTRL_4BPP;	break;
	default:
	case  8: vidc.control |= VIDC20_CTRL_8BPP;	break;
	case 16: vidc.control |= VIDC20_CTRL_16BPP;	break;
	case 32: vidc.control |= VIDC20_CTRL_32BPP;	break;
	}

	acornfb_vidc20_find_rates(&vidc, var);
	fsize = var->vsync_len + var->upper_margin + var->lower_margin - 1;

	if (memcmp(&current_vidc, &vidc, sizeof(vidc))) {
		current_vidc = vidc;

		vidc_writel(VIDC20_CTRL| vidc.control);
		vidc_writel(0xd0000000 | vidc.pll_ctl);
		vidc_writel(0x80000000 | vidc.h_cycle);
		vidc_writel(0x81000000 | vidc.h_sync_width);
		vidc_writel(0x82000000 | vidc.h_border_start);
		vidc_writel(0x83000000 | vidc.h_display_start);
		vidc_writel(0x84000000 | vidc.h_display_end);
		vidc_writel(0x85000000 | vidc.h_border_end);
		vidc_writel(0x86000000);
		vidc_writel(0x87000000 | vidc.h_interlace);
		vidc_writel(0x90000000 | vidc.v_cycle);
		vidc_writel(0x91000000 | vidc.v_sync_width);
		vidc_writel(0x92000000 | vidc.v_border_start);
		vidc_writel(0x93000000 | vidc.v_display_start);
		vidc_writel(0x94000000 | vidc.v_display_end);
		vidc_writel(0x95000000 | vidc.v_border_end);
		vidc_writel(0x96000000);
		vidc_writel(0x97000000);
	}

	iomd_writel(fsize, IOMD_FSIZE);

	ext_ctl = acornfb_default_econtrol();

	if (var->sync & FB_SYNC_COMP_HIGH_ACT) /* should be FB_SYNC_COMP */
		ext_ctl |= VIDC20_ECTL_HS_NCSYNC | VIDC20_ECTL_VS_NCSYNC;
	else {
		if (var->sync & FB_SYNC_HOR_HIGH_ACT)
			ext_ctl |= VIDC20_ECTL_HS_HSYNC;
		else
			ext_ctl |= VIDC20_ECTL_HS_NHSYNC;

		if (var->sync & FB_SYNC_VERT_HIGH_ACT)
			ext_ctl |= VIDC20_ECTL_VS_VSYNC;
		else
			ext_ctl |= VIDC20_ECTL_VS_NVSYNC;
	}

	vidc_writel(VIDC20_ECTL | ext_ctl);

	words_per_line = var->xres * var->bits_per_pixel / 32;

	if (current_par.using_vram && info->fix.smem_len == 2048*1024)
		words_per_line /= 2;

	/* RiscPC doesn't use the VIDC's VRAM control. */
	dat_ctl = VIDC20_DCTL_VRAM_DIS | VIDC20_DCTL_SNA | words_per_line;

	/* The data bus width is dependent on both the type
	 * and amount of video memory.
	 *     DRAM	32bit low
	 * 1MB VRAM	32bit
	 * 2MB VRAM	64bit
	 */
	if (current_par.using_vram && current_par.vram_half_sam == 2048)
		dat_ctl |= VIDC20_DCTL_BUS_D63_0;
	else
		dat_ctl |= VIDC20_DCTL_BUS_D31_0;

	vidc_writel(VIDC20_DCTL | dat_ctl);

#ifdef DEBUG_MODE_SELECTION
	printk(KERN_DEBUG "VIDC registers for %dx%dx%d:\n", var->xres,
	       var->yres, var->bits_per_pixel);
	printk(KERN_DEBUG " H-cycle          : %d\n", vidc.h_cycle);
	printk(KERN_DEBUG " H-sync-width     : %d\n", vidc.h_sync_width);
	printk(KERN_DEBUG " H-border-start   : %d\n", vidc.h_border_start);
	printk(KERN_DEBUG " H-display-start  : %d\n", vidc.h_display_start);
	printk(KERN_DEBUG " H-display-end    : %d\n", vidc.h_display_end);
	printk(KERN_DEBUG " H-border-end     : %d\n", vidc.h_border_end);
	printk(KERN_DEBUG " H-interlace      : %d\n", vidc.h_interlace);
	printk(KERN_DEBUG " V-cycle          : %d\n", vidc.v_cycle);
	printk(KERN_DEBUG " V-sync-width     : %d\n", vidc.v_sync_width);
	printk(KERN_DEBUG " V-border-start   : %d\n", vidc.v_border_start);
	printk(KERN_DEBUG " V-display-start  : %d\n", vidc.v_display_start);
	printk(KERN_DEBUG " V-display-end    : %d\n", vidc.v_display_end);
	printk(KERN_DEBUG " V-border-end     : %d\n", vidc.v_border_end);
	printk(KERN_DEBUG " Ext Ctrl  (C)    : 0x%08X\n", ext_ctl);
	printk(KERN_DEBUG " PLL Ctrl  (D)    : 0x%08X\n", vidc.pll_ctl);
	printk(KERN_DEBUG " Ctrl      (E)    : 0x%08X\n", vidc.control);
	printk(KERN_DEBUG " Data Ctrl (F)    : 0x%08X\n", dat_ctl);
	printk(KERN_DEBUG " Fsize            : 0x%08X\n", fsize);
#endif
}
Esempio n. 4
0
static inline void iomd_setup_dma_b(struct scatterlist *sg, dma_t *dma)
{
	iomd_writel(sg->dma_address, dma->dma_base + CURB);
	iomd_writel(sg->length, dma->dma_base + ENDB);
}