コード例 #1
0
static irqreturn_t pv_isr(int irq, void *dev_data)
{
	u32 pv_base, irq_stat;
	struct pv_dev *dev = dev_data;
	u32 schedule_wk = 0;

	pv_base = dev->base_addr;
	irq_stat = readl(pv_base + REG_PV_INTSTAT);

	if (irq_stat & VFP_END) {
#if 0
		if (!config->cont) {
			/*Since the PV will be disabled at the frame boundary,
			this will not be required. In case ASIC verification
			turns out to be negative, then we need to enable this*/
			pv_info("stopping PV\n");
			writel((readl(pv_base + REG_PV_C) | FIFOCLRC)
				& ~PVEN, pv_base + REG_PV_C);
			writel(readl(pv_base + REG_PV_VC) & ~VIDEN,
					pv_base + REG_PV_VC);
		}
#else
		if (PV_STOPPING == dev->state) {
			/*Change PV state to Stopped*/
			dev->state = PV_STOPPED;
			schedule_wk = 1;
		}
#endif
		writel(VFP_END, pv_base + REG_PV_INTSTAT);
		irq_stat = irq_stat & ~VFP_END;
		//disable_irq(dev->irq);
	}


	if (irq_stat & OF_UF) {
		dev->irq_stat |= OF_UF;
		schedule_work(&dev->err_work);
		writel(HVS_UF | HVS_OF | PV_UF, pv_base + REG_PV_STAT);
		writel(OF_UF, pv_base + REG_PV_INTSTAT);
		irq_stat = irq_stat & ~OF_UF;
	}

	if (irq_stat) {
		writel(irq_stat, pv_base + REG_PV_INTSTAT);
	}

	if (schedule_wk)
		schedule_work(&dev->eof_work);
	return IRQ_HANDLED;
}
コード例 #2
0
int pv_change_state(int event, struct pv_config_t *vid_config)
{
	u32 pv_base;
	struct pv_dev *dev;
	int ret = -EINVAL;

	if (!vid_config)
		return -EINVAL;

	dev = container_of(vid_config, struct pv_dev, vid_config);
	pv_base = dev->base_addr;

	switch (event) {
	case PV_VID_CONFIG:
#if 0
		int cnt = 100;
		while ((PV_STOPPING == dev->state) && cnt-- ) {
			if (readl(pv_base + REG_PV_STAT) & VID_IDLE_STAT)
				dev->state = PV_STOPPED;
			else
				usleep_range(1000, 1100);
		}
#endif
		if ((PV_STOPPED == dev->state)
			|| (PV_INIT_DONE == dev->state)) {
			pv_clk_enable(dev);
			ret = pv_vid_config(vid_config);
			pv_clk_disable(dev);
			dev->state = PV_CONFIGURED;
			ret = 0;
		} else {
			return -EBUSY;
		}
		break;
	case PV_START:
		if ((PV_STOPPED == dev->state)
			|| (PV_CONFIGURED == dev->state)) {
			pv_clk_enable(dev);
			writel((readl(pv_base + REG_PV_INTEN)
				& ~VFP_END), pv_base + REG_PV_INTEN);
#ifdef INT_4_LONG_PKT
			writel(VFP_START, (dev->base_addr + REG_PV_INTEN));//workaround 1
#endif
			writel(readl(pv_base + REG_PV_C) | PVEN,
				pv_base + REG_PV_C);
			writel(readl(pv_base + REG_PV_VC) | VIDEN,
					pv_base + REG_PV_VC);
			//enable_irq(dev->irq);
			if (!vid_config->cont) {
				printk("single shot enabled!!!\n");
				writel((readl(pv_base + REG_PV_INTEN)
				| VFP_END), pv_base + REG_PV_INTEN);
				dev->state = PV_STOPPING;
			} else {
				dev->state = PV_ENABLED;
			}
			ret = 0;
		} else {
			return -EBUSY;
		}
		break;
	case PV_STOP_EOF:
		if (PV_ENABLED == dev->state) {
			unsigned long flags;
			
			if (vid_config->cont) {
				spin_lock_irqsave(&lock, flags);
				writel(readl(pv_base + REG_PV_VC)
					& ~VIDEN,
					pv_base + REG_PV_VC);
				writel((readl(pv_base + REG_PV_INTEN)
					| VFP_END),
					pv_base + REG_PV_INTEN);
				dev->state = PV_STOPPING;
				spin_unlock_irqrestore(&lock, flags);
			} else {
				spin_lock_irqsave(&lock, flags);
				/* Stop after the currrent frame is txferd.
				Need to find out if there would be an
				interrupt at VFP_END in single-shot/cmd mode.
				+ VFP_END will be enabled for !cont mode.*/
				writel((readl(pv_base + REG_PV_INTEN)
					| VFP_END),
					pv_base + REG_PV_INTEN);
				dev->state = PV_STOPPING;
				spin_unlock_irqrestore(&lock, flags);
			}
			ret = 0;
		} else {
			return -EBUSY;
		}
		break;
	case PV_STOP_IMM:
		if ((PV_STOPPING == dev->state)
			|| (PV_ENABLED == dev->state)) {
			unsigned long flags;
			spin_lock_irqsave(&lock, flags);
			writel(readl(pv_base + REG_PV_VC) & ~VIDEN,
					pv_base + REG_PV_VC);
			writel(readl(pv_base + REG_PV_C) & ~PVEN,
					pv_base + REG_PV_C);
			/* Todo: Clear FIFO? */
			//disable_irq(dev->irq);
			pv_clk_disable(dev);
			dev->state = PV_STOPPED;
			spin_unlock_irqrestore(&lock, flags);
			ret = 0;
		} else {
			return -EBUSY;
		}
		break;
	case PV_RESET:
		/* Need to reset the PV block and take it to hardware
		reset state*/
		break;
	default:
		pv_info("Invalid option %d\n", dev->state);
		break;
	}
	return ret;
}