예제 #1
0
/*
 * The following two functions absolutely depend on the fact, that
 * there can be only one camera on mx2 camera sensor interface
 */
static int mx2_camera_add_device(struct soc_camera_device *icd)
{
	struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
	struct mx2_camera_dev *pcdev = ici->priv;
	int ret;
	u32 csicr1;

	if (pcdev->icd)
		return -EBUSY;

	ret = clk_enable(pcdev->clk_csi);
	if (ret < 0)
		return ret;

	csicr1 = CSICR1_MCLKEN;

	if (mx27_camera_emma(pcdev)) {
		csicr1 |= CSICR1_PRP_IF_EN | CSICR1_FCC |
			CSICR1_RXFF_LEVEL(0);
	} else if (cpu_is_mx27())
		csicr1 |= CSICR1_SOF_INTEN | CSICR1_RXFF_LEVEL(2);

	pcdev->csicr1 = csicr1;
	writel(pcdev->csicr1, pcdev->base_csi + CSICR1);

	pcdev->icd = icd;

	dev_info(icd->parent, "Camera driver attached to camera %d\n",
		 icd->devnum);

	return 0;
}
예제 #2
0
void ipipe_mach_allow_hwtimer_uaccess(unsigned long aips1, unsigned long aips2)
{
	volatile unsigned long aips_reg;

	if (!cpu_is_mx27()) {
		/*
		 * S/W workaround: Clear the off platform peripheral modules
		 * Supervisor Protect bit for SDMA to access them.
		 */
		__raw_writel(0x0, aips1 + 0x40);
		__raw_writel(0x0, aips1 + 0x44);
		__raw_writel(0x0, aips1 + 0x48);
		__raw_writel(0x0, aips1 + 0x4C);
		aips_reg = __raw_readl(aips1 + 0x50);
		aips_reg &= 0x00FFFFFF;
		__raw_writel(aips_reg, aips1 + 0x50);

		__raw_writel(0x0, aips2 + 0x40);
		__raw_writel(0x0, aips2 + 0x44);
		__raw_writel(0x0, aips2 + 0x48);
		__raw_writel(0x0, aips2 + 0x4C);
		aips_reg = __raw_readl(aips2 + 0x50);
		aips_reg &= 0x00FFFFFF;
		__raw_writel(aips_reg, aips2 + 0x50);
	} else {
		aips_reg = __raw_readl(aips1 + 8);
		aips_reg &= ~(1 << aips2);
		__raw_writel(aips_reg, aips1 + 8);
	}
}
예제 #3
0
파일: pm-imx27.c 프로젝트: 020gzh/linux
static int __init mx27_pm_init(void)
{
	if (!cpu_is_mx27())
		return 0;

	suspend_set_ops(&mx27_suspend_ops);
	return 0;
}
예제 #4
0
static int mxc_audmux_v1_init(void)
{
#ifdef CONFIG_MACH_MX21
	if (cpu_is_mx21())
		audmux_base = MX21_IO_ADDRESS(MX21_AUDMUX_BASE_ADDR);
	else
#endif
#ifdef CONFIG_MACH_MX27
	if (cpu_is_mx27())
		audmux_base = MX27_IO_ADDRESS(MX27_AUDMUX_BASE_ADDR);
	else
#endif
		(void)0;

	return 0;
}
예제 #5
0
static int post_cpu_init(void)
{
#ifdef CONFIG_MACH_MX27
	if (cpu_is_mx27())
		ipipe_mach_allow_hwtimer_uaccess(MX27_IO_P2V(MX27_AIPI_BASE_ADDR), 3);
#endif /* CONFIG_MACH_MX27 */
#ifdef CONFIG_MACH_MX25
	if (cpu_is_mx25())
		ipipe_mach_allow_hwtimer_uaccess(MX25_AIPS1_BASE_ADDR_VIRT,
						 MX25_AIPS2_BASE_ADDR_VIRT);
#endif /* CONFIG_MACH_MX25 */
#ifdef CONFIG_MACH_MX31
	if (cpu_is_mx31())
		ipipe_mach_allow_hwtimer_uaccess(AIPS1_BASE_ADDR_VIRT,
						 AIPS2_BASE_ADDR_VIRT);
#endif /* CONFIG_MACH_MX31 */
	return 0;
}
static int imx_iomuxv1_init(void)
{
#ifdef CONFIG_ARCH_MX1
	if (cpu_is_mx1()) {
		imx_iomuxv1_baseaddr = MX1_IO_ADDRESS(MX1_GPIO_BASE_ADDR);
		imx_iomuxv1_numports = MX1_NUM_GPIO_PORT;
	} else
#endif
#ifdef CONFIG_MACH_MX21
	if (cpu_is_mx21()) {
		imx_iomuxv1_baseaddr = MX21_IO_ADDRESS(MX21_GPIO_BASE_ADDR);
		imx_iomuxv1_numports = MX21_NUM_GPIO_PORT;
	} else
#endif
#ifdef CONFIG_MACH_MX27
	if (cpu_is_mx27()) {
		imx_iomuxv1_baseaddr = MX27_IO_ADDRESS(MX27_GPIO_BASE_ADDR);
		imx_iomuxv1_numports = MX27_NUM_GPIO_PORT;
	} else
#endif
		return -ENODEV;

	return 0;
}
예제 #7
0
int mxc_initialize_usb_hw(int port, unsigned int flags)
{
	unsigned int v;
#if defined(CONFIG_ARCH_MX25)
	if (cpu_is_mx25()) {
		v = readl(MX25_IO_ADDRESS(MX25_OTG_BASE_ADDR +
				     USBCTRL_OTGBASE_OFFSET));

		switch (port) {
		case 0:	/* OTG port */
			v &= ~(MX35_OTG_SIC_MASK | MX35_OTG_PM_BIT);
			v |= (flags & MXC_EHCI_INTERFACE_MASK)
					<< MX35_OTG_SIC_SHIFT;
			if (!(flags & MXC_EHCI_POWER_PINS_ENABLED))
				v |= MX35_OTG_PM_BIT;

			break;
		case 1: /* H1 port */
			v &= ~(MX35_H1_SIC_MASK | MX35_H1_PM_BIT | MX35_H1_TLL_BIT |
				MX35_H1_USBTE_BIT | MX35_H1_IPPUE_DOWN_BIT | MX35_H1_IPPUE_UP_BIT);
			v |= (flags & MXC_EHCI_INTERFACE_MASK)
						<< MX35_H1_SIC_SHIFT;
			if (!(flags & MXC_EHCI_POWER_PINS_ENABLED))
				v |= MX35_H1_PM_BIT;

			if (!(flags & MXC_EHCI_TTL_ENABLED))
				v |= MX35_H1_TLL_BIT;

			if (flags & MXC_EHCI_INTERNAL_PHY)
				v |= MX35_H1_USBTE_BIT;

			if (flags & MXC_EHCI_IPPUE_DOWN)
				v |= MX35_H1_IPPUE_DOWN_BIT;

			if (flags & MXC_EHCI_IPPUE_UP)
				v |= MX35_H1_IPPUE_UP_BIT;

			break;
		default:
			return -EINVAL;
		}

		writel(v, MX25_IO_ADDRESS(MX25_OTG_BASE_ADDR +
				     USBCTRL_OTGBASE_OFFSET));
		return 0;
	}
#endif /* CONFIG_ARCH_MX25 */
#if defined(CONFIG_ARCH_MX3)
	if (cpu_is_mx31()) {
		v = readl(MX31_IO_ADDRESS(MX31_OTG_BASE_ADDR +
				     USBCTRL_OTGBASE_OFFSET));

		switch (port) {
		case 0:	/* OTG port */
			v &= ~(MX31_OTG_SIC_MASK | MX31_OTG_PM_BIT);
			v |= (flags & MXC_EHCI_INTERFACE_MASK)
					<< MX31_OTG_SIC_SHIFT;
			if (!(flags & MXC_EHCI_POWER_PINS_ENABLED))
				v |= MX31_OTG_PM_BIT;

			break;
		case 1: /* H1 port */
			v &= ~(MX31_H1_SIC_MASK | MX31_H1_PM_BIT | MX31_H1_DT_BIT);
			v |= (flags & MXC_EHCI_INTERFACE_MASK)
						<< MX31_H1_SIC_SHIFT;
			if (!(flags & MXC_EHCI_POWER_PINS_ENABLED))
				v |= MX31_H1_PM_BIT;

			if (!(flags & MXC_EHCI_TTL_ENABLED))
				v |= MX31_H1_DT_BIT;

			break;
		case 2:	/* H2 port */
			v &= ~(MX31_H2_SIC_MASK | MX31_H2_PM_BIT | MX31_H2_DT_BIT);
			v |= (flags & MXC_EHCI_INTERFACE_MASK)
						<< MX31_H2_SIC_SHIFT;
			if (!(flags & MXC_EHCI_POWER_PINS_ENABLED))
				v |= MX31_H2_PM_BIT;

			if (!(flags & MXC_EHCI_TTL_ENABLED))
				v |= MX31_H2_DT_BIT;

			break;
		default:
			return -EINVAL;
		}

		writel(v, MX31_IO_ADDRESS(MX31_OTG_BASE_ADDR +
				     USBCTRL_OTGBASE_OFFSET));
		return 0;
	}

	if (cpu_is_mx35()) {
		v = readl(MX35_IO_ADDRESS(MX35_OTG_BASE_ADDR +
				     USBCTRL_OTGBASE_OFFSET));

		switch (port) {
		case 0:	/* OTG port */
			v &= ~(MX35_OTG_SIC_MASK | MX35_OTG_PM_BIT);
			v |= (flags & MXC_EHCI_INTERFACE_MASK)
					<< MX35_OTG_SIC_SHIFT;
			if (!(flags & MXC_EHCI_POWER_PINS_ENABLED))
				v |= MX35_OTG_PM_BIT;

			break;
		case 1: /* H1 port */
			v &= ~(MX35_H1_SIC_MASK | MX35_H1_PM_BIT | MX35_H1_TLL_BIT |
				MX35_H1_USBTE_BIT | MX35_H1_IPPUE_DOWN_BIT | MX35_H1_IPPUE_UP_BIT);
			v |= (flags & MXC_EHCI_INTERFACE_MASK)
						<< MX35_H1_SIC_SHIFT;
			if (!(flags & MXC_EHCI_POWER_PINS_ENABLED))
				v |= MX35_H1_PM_BIT;

			if (!(flags & MXC_EHCI_TTL_ENABLED))
				v |= MX35_H1_TLL_BIT;

			if (flags & MXC_EHCI_INTERNAL_PHY)
				v |= MX35_H1_USBTE_BIT;

			if (flags & MXC_EHCI_IPPUE_DOWN)
				v |= MX35_H1_IPPUE_DOWN_BIT;

			if (flags & MXC_EHCI_IPPUE_UP)
				v |= MX35_H1_IPPUE_UP_BIT;

			break;
		default:
			return -EINVAL;
		}

		writel(v, MX35_IO_ADDRESS(MX35_OTG_BASE_ADDR +
				     USBCTRL_OTGBASE_OFFSET));
		return 0;
	}
#endif /* CONFIG_ARCH_MX3 */
#ifdef CONFIG_MACH_MX27
	if (cpu_is_mx27()) {
		/* On i.MX27 we can use the i.MX31 USBCTRL bits, they
		 * are identical
		 */
		v = readl(MX27_IO_ADDRESS(MX27_OTG_BASE_ADDR +
				     USBCTRL_OTGBASE_OFFSET));
		switch (port) {
		case 0:	/* OTG port */
			v &= ~(MX31_OTG_SIC_MASK | MX31_OTG_PM_BIT);
			v |= (flags & MXC_EHCI_INTERFACE_MASK)
					<< MX31_OTG_SIC_SHIFT;
			if (!(flags & MXC_EHCI_POWER_PINS_ENABLED))
				v |= MX31_OTG_PM_BIT;
			break;
		case 1: /* H1 port */
			v &= ~(MX31_H1_SIC_MASK | MX31_H1_PM_BIT | MX31_H1_DT_BIT);
			v |= (flags & MXC_EHCI_INTERFACE_MASK)
						<< MX31_H1_SIC_SHIFT;
			if (!(flags & MXC_EHCI_POWER_PINS_ENABLED))
				v |= MX31_H1_PM_BIT;

			if (!(flags & MXC_EHCI_TTL_ENABLED))
				v |= MX31_H1_DT_BIT;

			break;
		case 2:	/* H2 port */
			v &= ~(MX31_H2_SIC_MASK | MX31_H2_PM_BIT | MX31_H2_DT_BIT);
			v |= (flags & MXC_EHCI_INTERFACE_MASK)
						<< MX31_H2_SIC_SHIFT;
			if (!(flags & MXC_EHCI_POWER_PINS_ENABLED))
				v |= MX31_H2_PM_BIT;

			if (!(flags & MXC_EHCI_TTL_ENABLED))
				v |= MX31_H2_DT_BIT;

			break;
		default:
			return -EINVAL;
		}
		writel(v, MX27_IO_ADDRESS(MX27_OTG_BASE_ADDR +
				     USBCTRL_OTGBASE_OFFSET));
		return 0;
	}
#endif /* CONFIG_MACH_MX27 */
#ifdef CONFIG_ARCH_MX51
	if (cpu_is_mx51()) {
		void __iomem *usb_base;
		u32 usbotg_base;
		u32 usbother_base;
		int ret = 0;

		usb_base = ioremap(MX51_OTG_BASE_ADDR, SZ_4K);

		switch (port) {
		case 0:	/* OTG port */
			usbotg_base = usb_base + MXC_OTG_OFFSET;
			break;
		case 1:	/* Host 1 port */
			usbotg_base = usb_base + MXC_H1_OFFSET;
			break;
		default:
			printk(KERN_ERR"%s no such port %d\n", __func__, port);
			ret = -ENOENT;
			goto error;
		}
		usbother_base = usb_base + MX5_USBOTHER_REGS_OFFSET;

		switch (port) {
		case 0:	/*OTG port */
			if (flags & MXC_EHCI_INTERNAL_PHY) {
				v = __raw_readl(usbother_base + MXC_USB_PHY_CTR_FUNC_OFFSET);

				if (flags & MXC_EHCI_POWER_PINS_ENABLED)
					v |= (MXC_OTG_PHYCTRL_OC_DIS_BIT | MXC_OTG_UCTRL_OPM_BIT); /* OC/USBPWR is not used */
				else
					v &= ~(MXC_OTG_PHYCTRL_OC_DIS_BIT | MXC_OTG_UCTRL_OPM_BIT); /* OC/USBPWR is used */
				__raw_writel(v, usbother_base + MXC_USB_PHY_CTR_FUNC_OFFSET);

				v = __raw_readl(usbother_base + MXC_USBCTRL_OFFSET);
				if (flags & MXC_EHCI_WAKEUP_ENABLED)
					v |= MXC_OTG_UCTRL_OWIE_BIT;/* OTG wakeup enable */
				else
					v &= ~MXC_OTG_UCTRL_OWIE_BIT;/* OTG wakeup disable */
				__raw_writel(v, usbother_base + MXC_USBCTRL_OFFSET);
			}
			break;
		case 1:	/* Host 1 */
			/*Host ULPI */
			v = __raw_readl(usbother_base + MXC_USBCTRL_OFFSET);
			if (flags & MXC_EHCI_WAKEUP_ENABLED)
				v &= ~(MXC_H1_UCTRL_H1WIE_BIT | MXC_H1_UCTRL_H1UIE_BIT);/* HOST1 wakeup/ULPI intr disable */
			else
				v &= ~(MXC_H1_UCTRL_H1WIE_BIT | MXC_H1_UCTRL_H1UIE_BIT);/* HOST1 wakeup/ULPI intr disable */

			if (flags & MXC_EHCI_POWER_PINS_ENABLED)
				v &= ~MXC_H1_UCTRL_H1PM_BIT; /* HOST1 power mask used*/
			else
				v |= MXC_H1_UCTRL_H1PM_BIT; /* HOST1 power mask used*/
			__raw_writel(v, usbother_base + MXC_USBCTRL_OFFSET);

			v = __raw_readl(usbother_base + MXC_USB_PHY_CTR_FUNC_OFFSET);
			if (flags & MXC_EHCI_POWER_PINS_ENABLED)
				v &= ~MXC_H1_OC_DIS_BIT; /* OC is used */
			else
				v |= MXC_H1_OC_DIS_BIT; /* OC is not used */
			__raw_writel(v, usbother_base + MXC_USB_PHY_CTR_FUNC_OFFSET);

			v = __raw_readl(usbotg_base + MXC_USBCMD_OFFSET);
			if (flags & MXC_EHCI_ITC_NO_THRESHOLD)
				/* Interrupt Threshold Control:Immediate (no threshold) */
				v &= MXC_UCMD_ITC_NO_THRESHOLD_MASK;
			__raw_writel(v, usbotg_base + MXC_USBCMD_OFFSET);
			break;
		}

error:
		iounmap(usb_base);
		return ret;
	}
#endif
	printk(KERN_WARNING
		"%s() unable to setup USBCONTROL for this CPU\n", __func__);
	return -EINVAL;
}
예제 #8
0
static void mx2_videobuf_queue(struct videobuf_queue *vq,
			       struct videobuf_buffer *vb)
{
	struct soc_camera_device *icd = vq->priv_data;
	struct soc_camera_host *ici =
		to_soc_camera_host(icd->parent);
	struct mx2_camera_dev *pcdev = ici->priv;
	struct mx2_buffer *buf = container_of(vb, struct mx2_buffer, vb);
	unsigned long flags;

	dev_dbg(icd->parent, "%s (vb=0x%p) 0x%08lx %d\n", __func__,
		vb, vb->baddr, vb->bsize);

	spin_lock_irqsave(&pcdev->lock, flags);

	vb->state = VIDEOBUF_QUEUED;
	list_add_tail(&vb->queue, &pcdev->capture);

	if (mx27_camera_emma(pcdev)) {
		goto out;
#ifdef CONFIG_MACH_MX27
	} else if (cpu_is_mx27()) {
		int ret;

		if (pcdev->active == NULL) {
			ret = imx_dma_setup_single(pcdev->dma,
					videobuf_to_dma_contig(vb), vb->size,
					(u32)pcdev->base_dma + 0x10,
					DMA_MODE_READ);
			if (ret) {
				vb->state = VIDEOBUF_ERROR;
				wake_up(&vb->done);
				goto out;
			}

			vb->state = VIDEOBUF_ACTIVE;
			pcdev->active = buf;
		}
#endif
	} else { /* cpu_is_mx25() */
		u32 csicr3, dma_inten = 0;

		if (pcdev->fb1_active == NULL) {
			writel(videobuf_to_dma_contig(vb),
					pcdev->base_csi + CSIDMASA_FB1);
			pcdev->fb1_active = buf;
			dma_inten = CSICR1_FB1_DMA_INTEN;
		} else if (pcdev->fb2_active == NULL) {
			writel(videobuf_to_dma_contig(vb),
					pcdev->base_csi + CSIDMASA_FB2);
			pcdev->fb2_active = buf;
			dma_inten = CSICR1_FB2_DMA_INTEN;
		}

		if (dma_inten) {
			list_del(&vb->queue);
			vb->state = VIDEOBUF_ACTIVE;

			csicr3 = readl(pcdev->base_csi + CSICR3);

			/* Reflash DMA */
			writel(csicr3 | CSICR3_DMA_REFLASH_RFF,
					pcdev->base_csi + CSICR3);

			/* clear & enable interrupts */
			writel(dma_inten, pcdev->base_csi + CSISR);
			pcdev->csicr1 |= dma_inten;
			writel(pcdev->csicr1, pcdev->base_csi + CSICR1);

			/* enable DMA */
			csicr3 |= CSICR3_DMA_REQ_EN_RFF | CSICR3_RXFF_LEVEL(1);
			writel(csicr3, pcdev->base_csi + CSICR3);
		}
	}

out:
	spin_unlock_irqrestore(&pcdev->lock, flags);
}
예제 #9
0
static int __devinit spi_imx_probe(struct platform_device *pdev)
{
	struct spi_imx_master *mxc_platform_info;
	struct spi_master *master;
	struct spi_imx_data *spi_imx;
	struct resource *res;
	int i, ret;

	mxc_platform_info = dev_get_platdata(&pdev->dev);
	if (!mxc_platform_info) {
		dev_err(&pdev->dev, "can't get the platform data\n");
		return -EINVAL;
	}

	master = spi_alloc_master(&pdev->dev, sizeof(struct spi_imx_data));
	if (!master)
		return -ENOMEM;

	platform_set_drvdata(pdev, master);

	master->bus_num = pdev->id;
	master->num_chipselect = mxc_platform_info->num_chipselect;

	spi_imx = spi_master_get_devdata(master);
	spi_imx->bitbang.master = spi_master_get(master);
	spi_imx->chipselect = mxc_platform_info->chipselect;

	for (i = 0; i < master->num_chipselect; i++) {
		if (spi_imx->chipselect[i] < 0)
			continue;
		ret = gpio_request(spi_imx->chipselect[i], DRIVER_NAME);
		if (ret) {
			while (i > 0) {
				i--;
				if (spi_imx->chipselect[i] >= 0)
					gpio_free(spi_imx->chipselect[i]);
			}
			dev_err(&pdev->dev, "can't get cs gpios\n");
			goto out_master_put;
		}
	}

	spi_imx->bitbang.chipselect = spi_imx_chipselect;
	spi_imx->bitbang.setup_transfer = spi_imx_setupxfer;
	spi_imx->bitbang.txrx_bufs = spi_imx_transfer;
	spi_imx->bitbang.master->setup = spi_imx_setup;
	spi_imx->bitbang.master->cleanup = spi_imx_cleanup;
	spi_imx->bitbang.master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;

	init_completion(&spi_imx->xfer_done);

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (!res) {
		dev_err(&pdev->dev, "can't get platform resource\n");
		ret = -ENOMEM;
		goto out_gpio_free;
	}

	if (!request_mem_region(res->start, resource_size(res), pdev->name)) {
		dev_err(&pdev->dev, "request_mem_region failed\n");
		ret = -EBUSY;
		goto out_gpio_free;
	}

	spi_imx->base = ioremap(res->start, resource_size(res));
	if (!spi_imx->base) {
		ret = -EINVAL;
		goto out_release_mem;
	}

	spi_imx->irq = platform_get_irq(pdev, 0);
	if (spi_imx->irq <= 0) {
		ret = -EINVAL;
		goto out_iounmap;
	}

	ret = request_irq(spi_imx->irq, spi_imx_isr, 0, DRIVER_NAME, spi_imx);
	if (ret) {
		dev_err(&pdev->dev, "can't get irq%d: %d\n", spi_imx->irq, ret);
		goto out_iounmap;
	}

	if (cpu_is_mx25() || cpu_is_mx31() || cpu_is_mx35()) {
		spi_imx->intctrl = mx31_intctrl;
		spi_imx->config = mx31_config;
		spi_imx->trigger = mx31_trigger;
		spi_imx->rx_available = mx31_rx_available;
	} else  if (cpu_is_mx27() || cpu_is_mx21()) {
		spi_imx->intctrl = mx27_intctrl;
		spi_imx->config = mx27_config;
		spi_imx->trigger = mx27_trigger;
		spi_imx->rx_available = mx27_rx_available;
	} else if (cpu_is_mx1()) {
		spi_imx->intctrl = mx1_intctrl;
		spi_imx->config = mx1_config;
		spi_imx->trigger = mx1_trigger;
		spi_imx->rx_available = mx1_rx_available;
	} else
		BUG();

	spi_imx->clk = clk_get(&pdev->dev, NULL);
	if (IS_ERR(spi_imx->clk)) {
		dev_err(&pdev->dev, "unable to get clock\n");
		ret = PTR_ERR(spi_imx->clk);
		goto out_free_irq;
	}

	clk_enable(spi_imx->clk);
	spi_imx->spi_clk = clk_get_rate(spi_imx->clk);

	if (cpu_is_mx1() || cpu_is_mx21() || cpu_is_mx27())
		writel(1, spi_imx->base + MXC_RESET);

	/* drain receive buffer */
	if (cpu_is_mx25() || cpu_is_mx31() || cpu_is_mx35())
		while (readl(spi_imx->base + MX3_CSPISTAT) & MX3_CSPISTAT_RR)
			readl(spi_imx->base + MXC_CSPIRXDATA);

	spi_imx->intctrl(spi_imx, 0);

	ret = spi_bitbang_start(&spi_imx->bitbang);
	if (ret) {
		dev_err(&pdev->dev, "bitbang start failed with %d\n", ret);
		goto out_clk_put;
	}

	dev_info(&pdev->dev, "probed\n");

	return ret;

out_clk_put:
	clk_disable(spi_imx->clk);
	clk_put(spi_imx->clk);
out_free_irq:
	free_irq(spi_imx->irq, spi_imx);
out_iounmap:
	iounmap(spi_imx->base);
out_release_mem:
	release_mem_region(res->start, resource_size(res));
out_gpio_free:
	for (i = 0; i < master->num_chipselect; i++)
		if (spi_imx->chipselect[i] >= 0)
			gpio_free(spi_imx->chipselect[i]);
out_master_put:
	spi_master_put(master);
	kfree(master);
	platform_set_drvdata(pdev, NULL);
	return ret;
}
int
parse_args(int argc, char *argv[], int i)
{
	int status = 0, opt, val;

	input_arg[i].cmd.chromaInterleave = 1;
	if (cpu_is_mx6x())
		input_arg[i].cmd.bs_mode = 1;

	do {
		opt = getopt(argc, argv, options);
		switch (opt)
		{
		case 'i':
			strncpy(input_arg[i].cmd.input, optarg, MAX_PATH);
			input_arg[i].cmd.src_scheme = PATH_FILE;
			break;
		case 'o':
			if (input_arg[i].cmd.dst_scheme == PATH_NET) {
				warn_msg("-o ignored because of -n\n");
				break;
			}
			strncpy(input_arg[i].cmd.output, optarg, MAX_PATH);
			input_arg[i].cmd.dst_scheme = PATH_FILE;
			break;
		case 'x':
			val = atoi(optarg);
			if ((input_arg[i].mode == ENCODE) || (input_arg[i].mode == LOOPBACK))
				input_arg[i].cmd.video_node_capture = val;
			else {
				if (val == 1) {
					input_arg[i].cmd.dst_scheme = PATH_IPU;
					info_msg("Display through IPU LIB\n");
					if (cpu_is_mx6x())
						warn_msg("IPU lib is OBSOLETE, please try other renderer\n");
#ifdef BUILD_FOR_ANDROID
				} else if (val == 2) {
					input_arg[i].cmd.dst_scheme = PATH_G2D;
					info_msg("Display through G2D\n");
#endif
				} else {
					input_arg[i].cmd.dst_scheme = PATH_V4L2;
					info_msg("Display through V4L2\n");
					input_arg[i].cmd.video_node = val;
				}
				if (cpu_is_mx27() &&
					(input_arg[i].cmd.dst_scheme == PATH_IPU)) {
					input_arg[i].cmd.dst_scheme = PATH_V4L2;
					warn_msg("ipu lib disp only support in ipuv3\n");
				}
			}
			break;
		case 'n':
			if (input_arg[i].mode == ENCODE) {
				/* contains the ip address */
				strncpy(input_arg[i].cmd.output, optarg, 64);
				input_arg[i].cmd.dst_scheme = PATH_NET;
			} else {
				warn_msg("-n option used only for encode\n");
			}
			break;
		case 'p':
			input_arg[i].cmd.port = atoi(optarg);
			break;
		case 'r':
			input_arg[i].cmd.rot_angle = atoi(optarg);
			if (input_arg[i].cmd.rot_angle)
				input_arg[i].cmd.rot_en = 1;
			break;
		case 'u':
			input_arg[i].cmd.ext_rot_en = atoi(optarg);
			/* ipu/gpu rotation will override vpu rotation */
			if (input_arg[i].cmd.ext_rot_en)
				input_arg[i].cmd.rot_en = 0;
			break;
		case 'f':
			input_arg[i].cmd.format = atoi(optarg);
			break;
		case 'c':
			input_arg[i].cmd.count = atoi(optarg);
			break;
		case 'v':
			input_arg[i].cmd.vdi_motion = optarg[0];
			break;
		case 'w':
			input_arg[i].cmd.width = atoi(optarg);
			break;
		case 'h':
			input_arg[i].cmd.height = atoi(optarg);
			break;
		case 'j':
			input_arg[i].cmd.loff = atoi(optarg);
			break;
		case 'k':
			input_arg[i].cmd.toff = atoi(optarg);
			break;
		case 'g':
			input_arg[i].cmd.gop = atoi(optarg);
			break;
		case 's':
			if (cpu_is_mx6x())
				input_arg[i].cmd.bs_mode = atoi(optarg);
			else
				input_arg[i].cmd.prescan = atoi(optarg);
			break;
		case 'b':
			input_arg[i].cmd.bitrate = atoi(optarg);
			break;
		case 'd':
			input_arg[i].cmd.deblock_en = atoi(optarg);
			break;
		case 'e':
			input_arg[i].cmd.dering_en = atoi(optarg);
			break;
		case 'm':
			input_arg[i].cmd.mirror = atoi(optarg);
			if (input_arg[i].cmd.mirror)
				input_arg[i].cmd.rot_en = 1;
			break;
		case 't':
			input_arg[i].cmd.chromaInterleave = atoi(optarg);
			break;
		case 'l':
			input_arg[i].cmd.mp4_h264Class = atoi(optarg);
			break;
		case 'a':
			input_arg[i].cmd.fps = atoi(optarg);
			break;
		case 'y':
			input_arg[i].cmd.mapType = atoi(optarg);
			break;
		case 'q':
			input_arg[i].cmd.quantParam = atoi(optarg);
			break;
		case -1:
			break;
		default:
			status = -1;
			break;
		}
	} while ((opt != -1) && (status == 0));

	optind = 1;
	return status;
}
예제 #11
0
파일: display.c 프로젝트: githubzorro/myd1
struct vpu_display *
v4l_display_open(struct decode *dec, int nframes, struct rot rotation, Rect cropRect)
{
	int width = dec->picwidth;
	int height = dec->picheight;
	int left = cropRect.left;
	int top = cropRect.top;
	int right = cropRect.right;
	int bottom = cropRect.bottom;
	int disp_width = dec->cmdl->width;
	int disp_height = dec->cmdl->height;
	int disp_left =  dec->cmdl->loff;
	int disp_top =  dec->cmdl->toff;
	int fd = -1, err = 0, out = 0, i = 0;
	char v4l_device[80], node[8];
	struct v4l2_cropcap cropcap = {0};
	struct v4l2_crop crop = {0};
	struct v4l2_framebuffer fb = {0};
	struct v4l2_format fmt = {0};
	struct v4l2_requestbuffers reqbuf = {0};
	struct v4l2_mxc_offset off = {0};
	struct v4l2_rect icrop = {0};
	struct vpu_display *disp;
	int fd_fb;
	char *tv_mode, *test_mode;
	char motion_mode = dec->cmdl->vdi_motion;
	struct mxcfb_gbl_alpha alpha;

	int ratio = 1;

	if (cpu_is_mx27()) {
		out = 0;
	} else {
		out = 3;
#ifdef BUILD_FOR_ANDROID
		fd_fb = open("/dev/graphics/fb0", O_RDWR, 0);
#else
		fd_fb = open("/dev/fb0", O_RDWR, 0);
#endif
		if (fd_fb < 0) {
			err_msg("unable to open fb0\n");
			return NULL;
		}
		alpha.alpha = 0;
		alpha.enable = 1;
		if (ioctl(fd_fb, MXCFB_SET_GBL_ALPHA, &alpha) < 0) {
			err_msg("set alpha blending failed\n");
			return NULL;
		}
		close(fd_fb);
	}
	dprintf(3, "rot_en:%d; rot_angle:%d; ipu_rot_en:%d\n", rotation.rot_en,
			rotation.rot_angle, rotation.ipu_rot_en);

	tv_mode = getenv("VPU_TV_MODE");

	if (tv_mode) {
		err = system("/bin/echo 1 > /sys/class/graphics/fb1/blank");
		if (!strcmp(tv_mode, "NTSC")) {
			err = system("/bin/echo U:720x480i-60 > /sys/class/graphics/fb1/mode");
			out = 5;
		} else if (!strcmp(tv_mode, "PAL")) {
			err = system("/bin/echo U:720x576i-50 > /sys/class/graphics/fb1/mode");
			out = 5;
		} else if (!strcmp(tv_mode, "720P")) {
			err = system("/bin/echo U:1280x720p-60 > /sys/class/graphics/fb1/mode");
			out = 5;
		} else {
			out = 3;
			warn_msg("VPU_TV_MODE should be set to NTSC, PAL, or 720P.\n"
				 "\tDefault display is LCD if not set this environment "
				 "or set wrong string.\n");
		}
		err = system("/bin/echo 0 > /sys/class/graphics/fb1/blank");
		if (err == -1) {
			warn_msg("set tv mode error\n");
		}
		/* make sure tvout init done */
		sleep(2);
	}

	if (rotation.rot_en) {
		if (rotation.rot_angle == 90 || rotation.rot_angle == 270) {
			i = width;
			width = height;
			height = i;
		}
		dprintf(3, "VPU rot: width = %d; height = %d\n", width, height);
	}

	disp = (struct vpu_display *)calloc(1, sizeof(struct vpu_display));
       	if (disp == NULL) {
		err_msg("falied to allocate vpu_display\n");
		return NULL;
	}

	if (!dec->cmdl->video_node) {
		if (cpu_is_mx6x())
			dec->cmdl->video_node = 17; /* fg for mx6x */
		else
			dec->cmdl->video_node = 16;
	}
	sprintf(node, "%d", dec->cmdl->video_node);
	strcpy(v4l_device, "/dev/video");
	strcat(v4l_device, node);

	fd = open(v4l_device, O_RDWR, 0);
	if (fd < 0) {
		err_msg("unable to open %s\n", v4l_device);
		goto err;
	}

	info_msg("v4l output to %s\n", v4l_device);

	if (!cpu_is_mx6x()) {
		err = ioctl(fd, VIDIOC_S_OUTPUT, &out);
		if (err < 0) {
			err_msg("VIDIOC_S_OUTPUT failed\n");
			goto err;
		}
	}

	cropcap.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
	err = ioctl(fd, VIDIOC_CROPCAP, &cropcap);
	if (err < 0) {
		err_msg("VIDIOC_CROPCAP failed\n");
		goto err;
	}
	dprintf(1, "cropcap.bounds.width = %d\n\tcropcap.bound.height = %d\n\t" \
		"cropcap.defrect.width = %d\n\tcropcap.defrect.height = %d\n",
		cropcap.bounds.width, cropcap.bounds.height,
		cropcap.defrect.width, cropcap.defrect.height);

	if (rotation.ipu_rot_en == 0) {
		ratio = calculate_ratio(width, height, cropcap.bounds.width,
				cropcap.bounds.height);
		dprintf(3, "VPU rot: ratio = %d\n", ratio);
	}

	crop.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
	crop.c.top = disp_top;
	crop.c.left = disp_left;
	crop.c.width = width / ratio;
	crop.c.height = height / ratio;

	if ((disp_width != 0) && (disp_height!= 0 )) {
		crop.c.width = disp_width;
		crop.c.height = disp_height;
	} else if (!cpu_is_mx27()) {
		crop.c.width = cropcap.bounds.width;
		crop.c.height = cropcap.bounds.height;
	}

	info_msg("Display to %d %d, top offset %d, left offset %d\n",
			crop.c.width, crop.c.height, disp_top, disp_left);

	dprintf(1, "crop.c.width/height: %d/%d\n", crop.c.width, crop.c.height);

	err = ioctl(fd, VIDIOC_S_CROP, &crop);
	if (err < 0) {
		err_msg("VIDIOC_S_CROP failed\n");
		goto err;
	}

	/* Set VDI motion algorithm. */
	if (motion_mode) {
		struct v4l2_control ctrl;
		ctrl.id = V4L2_CID_MXC_MOTION;
		if (motion_mode == 'h') {
			ctrl.value = HIGH_MOTION;
		} else if (motion_mode == 'l') {
			ctrl.value = LOW_MOTION;
		} else if (motion_mode == 'm') {
			ctrl.value = MED_MOTION;
		} else {
			ctrl.value = MED_MOTION;
			info_msg("%c unknown motion mode, medium, the default is used\n",motion_mode);
		}
		err = ioctl(fd, VIDIOC_S_CTRL, &ctrl);
		if (err < 0) {
			err_msg("VIDIOC_S_CTRL failed\n");
			goto err;
		}
	}

	if (cpu_is_mx6x()) {
		/* Set rotation via new V4L2 interface on 2.6.38 kernel */
		struct v4l2_control ctrl;

		ctrl.id = V4L2_CID_ROTATE;
		if (rotation.ipu_rot_en)
			ctrl.value = rotation.rot_angle;
		else
			ctrl.value = 0;
		err = ioctl(fd, VIDIOC_S_CTRL, &ctrl);
		if (err < 0) {
			err_msg("VIDIOC_S_CTRL failed\n");
			goto err;
		}
	} else if (rotation.ipu_rot_en && (rotation.rot_angle != 0)) {
		/* Set rotation via V4L2 i/f */
		struct v4l2_control ctrl;
		ctrl.id = V4L2_CID_PRIVATE_BASE;
		if (rotation.rot_angle == 90)
			ctrl.value = V4L2_MXC_ROTATE_90_RIGHT;
		else if (rotation.rot_angle == 180)
			ctrl.value = V4L2_MXC_ROTATE_180;
		else if (rotation.rot_angle == 270)
			ctrl.value = V4L2_MXC_ROTATE_90_LEFT;
		err = ioctl(fd, VIDIOC_S_CTRL, &ctrl);
		if (err < 0) {
			err_msg("VIDIOC_S_CTRL failed\n");
			goto err;
		}
	} else {
		struct v4l2_control ctrl;
		ctrl.id = V4L2_CID_PRIVATE_BASE;
		ctrl.value = 0;
		err = ioctl(fd, VIDIOC_S_CTRL, &ctrl);
		if (err < 0) {
			err_msg("VIDIOC_S_CTRL failed\n");
			goto err;
		}
	}

	if (cpu_is_mx27()) {
		fb.capability = V4L2_FBUF_CAP_EXTERNOVERLAY;
		fb.flags = V4L2_FBUF_FLAG_PRIMARY;

		err = ioctl(fd, VIDIOC_S_FBUF, &fb);
		if (err < 0) {
			err_msg("VIDIOC_S_FBUF failed\n");
			goto err;
		}
	}

	fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;

	/*
	 * Just consider one case:
	 * (top,left) = (0,0)
	 */
	if (top || left) {
		err_msg("This case is not covered in this demo for simplicity:\n"
			"croping rectangle (top, left) != (0, 0); "
			"top/left = %d/%d\n", top, left);
		goto err;
	} else if (right || bottom) {
		if (cpu_is_mx6x()) {
			/* This is aligned with new V4L interface on 2.6.38 kernel */
			fmt.fmt.pix.width = width;
			fmt.fmt.pix.height = height;
			icrop.left = left;
			icrop.top = top;
			icrop.width = right - left;
			icrop.height = bottom - top;
			fmt.fmt.pix.priv =  (unsigned long)&icrop;
		} else {
			fmt.fmt.pix.width = right - left;
			fmt.fmt.pix.height = bottom - top;
			fmt.fmt.pix.bytesperline = width;
			off.u_offset = width * height;
			off.v_offset = off.u_offset + width * height / 4;
			fmt.fmt.pix.priv = (unsigned long) &off;
			fmt.fmt.pix.sizeimage = width * height * 3 / 2;
		}
	} else {
		fmt.fmt.pix.width = width;
		fmt.fmt.pix.height = height;
		fmt.fmt.pix.bytesperline = width;
	}
	dprintf(1, "fmt.fmt.pix.width = %d\n\tfmt.fmt.pix.height = %d\n",
				fmt.fmt.pix.width, fmt.fmt.pix.height);

	fmt.fmt.pix.field = V4L2_FIELD_ANY;

	if (dec->cmdl->mapType == LINEAR_FRAME_MAP) {
		if (dec->cmdl->chromaInterleave == 0) {
			if (dec->mjpg_fmt == MODE420)
				fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUV420;
			else if (dec->mjpg_fmt == MODE422)
				fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUV422P;
			else {
				err_msg("Display cannot support this MJPG format\n");
				goto err;
			}
		} else {
			if (dec->mjpg_fmt == MODE420) {
				info_msg("Display: NV12\n");
				fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_NV12;
			}
			else if (dec->mjpg_fmt == MODE422) {
				info_msg("Display: NV16\n");
				fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_NV16;
			}
			else {
				err_msg("Display cannot support this MJPG format\n");
				goto err;
			}
		}
	}
	else if (dec->cmdl->mapType == TILED_FRAME_MB_RASTER_MAP) {
		fmt.fmt.pix.pixelformat = IPU_PIX_FMT_TILED_NV12;
	}
	else if (dec->cmdl->mapType == TILED_FIELD_MB_RASTER_MAP) {
		fmt.fmt.pix.pixelformat = IPU_PIX_FMT_TILED_NV12F;
	}
	else {
		err_msg("Display cannot support mapType = %d\n", dec->cmdl->mapType);
		goto err;
	}
	err = ioctl(fd, VIDIOC_S_FMT, &fmt);
	if (err < 0) {
		err_msg("VIDIOC_S_FMT failed\n");
		goto err;
	}

	err = ioctl(fd, VIDIOC_G_FMT, &fmt);
	if (err < 0) {
		err_msg("VIDIOC_G_FMT failed\n");
		goto err;
	}

	reqbuf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
	reqbuf.memory = V4L2_MEMORY_MMAP;
	reqbuf.count = nframes;

	err = ioctl(fd, VIDIOC_REQBUFS, &reqbuf);
	if (err < 0) {
		err_msg("VIDIOC_REQBUFS failed\n");
		goto err;
	}

	if (reqbuf.count < nframes) {
		err_msg("VIDIOC_REQBUFS: not enough buffers\n");
		goto err;
	}

	for (i = 0; i < nframes; i++) {
		struct v4l2_buffer buffer = {0};
		struct v4l_buf *buf;

		buf = calloc(1, sizeof(struct v4l_buf));
		if (buf == NULL) {
			v4l_free_bufs(i, disp);
			goto err;
		}

		disp->buffers[i] = buf;

		buffer.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
		buffer.memory = V4L2_MEMORY_MMAP;
		buffer.index = i;

		err = ioctl(fd, VIDIOC_QUERYBUF, &buffer);
		if (err < 0) {
			err_msg("VIDIOC_QUERYBUF: not enough buffers\n");
			v4l_free_bufs(i, disp);
			goto err;
		}
		buf->start = mmap(NULL, buffer.length, PROT_READ | PROT_WRITE,
				MAP_SHARED, fd, buffer.m.offset);

		if (cpu_is_mx6x()) {
			/*
			 * Workaround for new V4L interface change, this change
			 * will be removed after V4L driver is updated for this.
			 * Need to call QUERYBUF ioctl again after mmap.
			 */
			err = ioctl(fd, VIDIOC_QUERYBUF, &buffer);
			if (err < 0) {
				err_msg("VIDIOC_QUERYBUF: not enough buffers\n");
				v4l_free_bufs(i, disp);
				goto err;
			}
		}
		buf->offset = buffer.m.offset;
		buf->length = buffer.length;
		dprintf(3, "V4L2buf phy addr: %08x, size = %d\n",
				    (unsigned int)buf->offset, buf->length);

		if (buf->start == MAP_FAILED) {
			err_msg("mmap failed\n");
			v4l_free_bufs(i, disp);
			goto err;
		}

	}

	disp->fd = fd;
	disp->nframes = nframes;

	/*
	 * Use environment VIDEO_PERFORMANCE_TEST to select different mode.
	 * When doing performance test, video decoding and display are in different
	 * threads and default display fps is controlled by cmd. Display will
	 * show the frame immediately if user doesn't input fps with -a option.
	 * This is different from normal unit test.
	 */
	test_mode = getenv("VIDEO_PERFORMANCE_TEST");
	if (test_mode && !strcmp(test_mode, "1") && (dec->cmdl->dst_scheme == PATH_V4L2))
		vpu_v4l_performance_test = 1;

	if (vpu_v4l_performance_test) {
		dec->disp = disp;
		sem_init(&disp->avaiable_decoding_frame, 0,
			    dec->regfbcount - dec->minfbcount);
		sem_init(&disp->avaiable_dequeue_frame, 0, 0);
		pthread_mutex_init(&v4l_mutex, NULL);
		/* start v4l disp loop thread */
		pthread_create(&(disp->v4l_disp_loop_thread), NULL,
				    (void *)v4l_disp_loop_thread, (void *)dec);
	}

	return disp;
err:
	close(fd);
	free(disp);
	return NULL;
}
예제 #12
0
static int __devinit spi_imx_probe(struct platform_device *pdev)
{
	struct spi_imx_master *mxc_platform_info;
	struct spi_master *master;
	struct spi_imx_data *spi_imx;
	struct resource *res;
	int i, ret;

	mxc_platform_info = dev_get_platdata(&pdev->dev);
	if (!mxc_platform_info) {
		dev_err(&pdev->dev, "can't get the platform data\n");
		return -EINVAL;
	}

	master = spi_alloc_master(&pdev->dev, sizeof(struct spi_imx_data));
	if (!master)
		return -ENOMEM;

	platform_set_drvdata(pdev, master);

	master->bus_num = pdev->id;
	master->num_chipselect = mxc_platform_info->num_chipselect;

	spi_imx = spi_master_get_devdata(master);
	spi_imx->bitbang.master = spi_master_get(master);
	spi_imx->chipselect = mxc_platform_info->chipselect;

	for (i = 0; i < master->num_chipselect; i++) {
		if (spi_imx->chipselect[i] < 0)
			continue;
		ret = gpio_request(spi_imx->chipselect[i], DRIVER_NAME);
		if (ret) {
			while (i > 0) {
				i--;
				if (spi_imx->chipselect[i] >= 0)
					gpio_free(spi_imx->chipselect[i]);
			}
			dev_err(&pdev->dev, "can't get cs gpios\n");
			goto out_master_put;
		}
	}

	spi_imx->bitbang.chipselect = spi_imx_chipselect;
	spi_imx->bitbang.setup_transfer = spi_imx_setupxfer;
	spi_imx->bitbang.txrx_bufs = spi_imx_transfer;
	spi_imx->bitbang.master->setup = spi_imx_setup;
	spi_imx->bitbang.master->cleanup = spi_imx_cleanup;
	spi_imx->bitbang.master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;

	init_completion(&spi_imx->xfer_done);

	if (pdev->id_entry->driver_data == SPI_IMX_VER_AUTODETECT) {
		if (cpu_is_mx25() || cpu_is_mx35())
			spi_imx->devtype_data =
				spi_imx_devtype_data[SPI_IMX_VER_0_7];
		else if (cpu_is_mx25() || cpu_is_mx31() || cpu_is_mx35())
			spi_imx->devtype_data =
				spi_imx_devtype_data[SPI_IMX_VER_0_4];
		else if (cpu_is_mx27() || cpu_is_mx21())
			spi_imx->devtype_data =
				spi_imx_devtype_data[SPI_IMX_VER_0_0];
		else if (cpu_is_mx1())
			spi_imx->devtype_data =
				spi_imx_devtype_data[SPI_IMX_VER_IMX1];
		else
			BUG();
	} else
		spi_imx->devtype_data =
			spi_imx_devtype_data[pdev->id_entry->driver_data];

	if (!spi_imx->devtype_data.intctrl) {
		dev_err(&pdev->dev, "no support for this device compiled in\n");
		ret = -ENODEV;
		goto out_gpio_free;
	}

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (!res) {
		dev_err(&pdev->dev, "can't get platform resource\n");
		ret = -ENOMEM;
		goto out_gpio_free;
	}

	if (!request_mem_region(res->start, resource_size(res), pdev->name)) {
		dev_err(&pdev->dev, "request_mem_region failed\n");
		ret = -EBUSY;
		goto out_gpio_free;
	}

	spi_imx->base = ioremap(res->start, resource_size(res));
	if (!spi_imx->base) {
		ret = -EINVAL;
		goto out_release_mem;
	}

	spi_imx->irq = platform_get_irq(pdev, 0);
	if (spi_imx->irq <= 0) {
		ret = -EINVAL;
		goto out_iounmap;
	}

	ret = request_irq(spi_imx->irq, spi_imx_isr, 0, DRIVER_NAME, spi_imx);
	if (ret) {
		dev_err(&pdev->dev, "can't get irq%d: %d\n", spi_imx->irq, ret);
		goto out_iounmap;
	}

	spi_imx->clk = clk_get(&pdev->dev, NULL);
	if (IS_ERR(spi_imx->clk)) {
		dev_err(&pdev->dev, "unable to get clock\n");
		ret = PTR_ERR(spi_imx->clk);
		goto out_free_irq;
	}

	clk_enable(spi_imx->clk);
	spi_imx->spi_clk = clk_get_rate(spi_imx->clk);

	spi_imx->devtype_data.reset(spi_imx);

	spi_imx->devtype_data.intctrl(spi_imx, 0);

	ret = spi_bitbang_start(&spi_imx->bitbang);
	if (ret) {
		dev_err(&pdev->dev, "bitbang start failed with %d\n", ret);
		goto out_clk_put;
	}

	dev_info(&pdev->dev, "probed\n");

	return ret;

out_clk_put:
	clk_disable(spi_imx->clk);
	clk_put(spi_imx->clk);
out_free_irq:
	free_irq(spi_imx->irq, spi_imx);
out_iounmap:
	iounmap(spi_imx->base);
out_release_mem:
	release_mem_region(res->start, resource_size(res));
out_gpio_free:
	for (i = 0; i < master->num_chipselect; i++)
		if (spi_imx->chipselect[i] >= 0)
			gpio_free(spi_imx->chipselect[i]);
out_master_put:
	spi_master_put(master);
	kfree(master);
	platform_set_drvdata(pdev, NULL);
	return ret;
}
예제 #13
0
struct vpu_display* v4l_display_open(struct DecodingInstance *dec, int nframes, int w, int h, int x, int y)
{

	int width = dec->picwidth;
	int height = dec->picheight;

	int fd = -1, err = 0, out = 0, i = 0;
	char v4l_device[32] = "/dev/video16";
	struct v4l2_format fmt = {};
	struct v4l2_requestbuffers reqbuf = {};
	struct vpu_display *disp;
	int fd_fb;
	char *tv_mode;
	char motion_mode = 0;
	struct mxcfb_gbl_alpha alpha;

	if (cpu_is_mx27()) {
		out = 0;
	} else {
		out = 3;
#ifdef BUILD_FOR_ANDROID
		fd_fb = open("/dev/graphics/fb0", O_RDWR, 0);
#else
		fd_fb = open("/dev/fb0", O_RDWR, 0);
#endif
		if (fd_fb < 0) {
			fputs("unable to open fb0\n", stderr);
			return NULL;
		}
		alpha.alpha = 0;
		alpha.enable = 1;
		if (ioctl(fd_fb, MXCFB_SET_GBL_ALPHA, &alpha) < 0) {
			fputs("set alpha blending failed\n", stderr);
			return NULL;
		}
		close(fd_fb);
	}

	tv_mode = getenv("VPU_TV_MODE");

	if (tv_mode) {
		err = system("/bin/echo 1 > /sys/class/graphics/fb1/blank");
		if (!strcmp(tv_mode, "NTSC")) {
			err = system("/bin/echo U:720x480i-60 > /sys/class/graphics/fb1/mode");
			out = 5;
		} else if (!strcmp(tv_mode, "PAL")) {
			err = system("/bin/echo U:720x576i-50 > /sys/class/graphics/fb1/mode");
			out = 5;
		} else if (!strcmp(tv_mode, "720P")) {
			err = system("/bin/echo U:1280x720p-60 > /sys/class/graphics/fb1/mode");
			out = 5;
		} else {
			out = 3;
			fputs("VPU_TV_MODE should be set to NTSC, PAL, or 720P.\n"
				 "\tDefault display is LCD if not set this environment "
				 "or set wrong string.\n", stderr);
		}
		err = system("/bin/echo 0 > /sys/class/graphics/fb1/blank");
		if (err == -1)
		{
			fputs("set tv mode error\n", stderr);
		}
		/* make sure tvout init done */
		sleep(2);
	}

	disp = (struct vpu_display *)calloc(1, sizeof(struct vpu_display));
       	if (disp == NULL) {
       		fputs("falied to allocate vpu_display\n", stderr);
		return NULL;
	}

	fd = open(v4l_device, O_RDWR, 0);
	if (fd < 0) {
		fprintf(stderr, "unable to open %s\n", v4l_device);
		goto err;
	}

	err = ioctl(fd, VIDIOC_S_OUTPUT, &out);
	if (err < 0) {
		fputs("VIDIOC_S_OUTPUT failed\n", stderr);
		goto err;
	}

	/* Set VDI motion algorithm. */
	if (motion_mode) {
		struct v4l2_control ctrl;
		ctrl.id = V4L2_CID_MXC_MOTION;
		if (motion_mode == 'h') {
			ctrl.value = HIGH_MOTION;
		} else if (motion_mode == 'l') {
			ctrl.value = LOW_MOTION;
		} else if (motion_mode == 'm') {
			ctrl.value = MED_MOTION;
		} else {
			ctrl.value = MED_MOTION;
		}
		err = ioctl(fd, VIDIOC_S_CTRL, &ctrl);
		if (err < 0) {
			fputs("VIDIOC_S_CTRL failed\n", stderr);
			goto err;
		}
	}


	struct v4l2_control ctrl;
	ctrl.id = V4L2_CID_PRIVATE_BASE;
	ctrl.value = 0;
	err = ioctl(fd, VIDIOC_S_CTRL, &ctrl);
	if (err < 0) {
		fputs("VIDIOC_S_CTRL failed\n", stderr);
		goto err;
	}

	fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;

	/*
	 * Just consider one case:
	 * (top,left) = (0,0)
	 */

	fmt.fmt.pix.width = width;
	fmt.fmt.pix.height = height;
	fmt.fmt.pix.bytesperline = width;

	dprintf(1, "fmt.fmt.pix.width = %d\n\tfmt.fmt.pix.height = %d\n",
				fmt.fmt.pix.width, fmt.fmt.pix.height);

	fmt.fmt.pix.field = V4L2_FIELD_ANY;

	if(dec->mjpg_fmt == MODE420)
		fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUV420;
	else if(dec->mjpg_fmt == MODE422)
		fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUV422P;
	else
	{
		goto err;
	}

	err = ioctl(fd, VIDIOC_S_FMT, &fmt);
	if (err < 0) {
		goto err;
	}

	err = ioctl(fd, VIDIOC_G_FMT, &fmt);
	if (err < 0) {
		goto err;
	}

	reqbuf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
	reqbuf.memory = V4L2_MEMORY_MMAP;
	reqbuf.count = nframes;

	err = ioctl(fd, VIDIOC_REQBUFS, &reqbuf);
	if (err < 0) {
		goto err;
	}

	if (reqbuf.count < nframes) {
		goto err;
	}

	for (i = 0; i < nframes; i++) {
		struct v4l2_buffer buffer = {0};
		struct v4l_buf *buf;

		buf = calloc(1, sizeof(struct v4l_buf));
		if (buf == NULL) {
			v4l_free_bufs(i, disp);
			goto err;
		}

		disp->buffers[i] = buf;

		buffer.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
		buffer.memory = V4L2_MEMORY_MMAP;
		buffer.index = i;

		err = ioctl(fd, VIDIOC_QUERYBUF, &buffer);
		if (err < 0) {
			v4l_free_bufs(i, disp);
			goto err;
		}

		buf->offset = buffer.m.offset;
		buf->length = buffer.length;
		dprintf(3, "V4L2buf phy addr: %08x, size = %d\n",
					(unsigned int)buf->offset, buf->length);
		buf->start = mmap(NULL, buffer.length, PROT_READ | PROT_WRITE,
				MAP_SHARED, fd, buffer.m.offset);

		if (buf->start == MAP_FAILED) {
			v4l_free_bufs(i, disp);
			goto err;
		}

	}

	disp->fd = fd;
	disp->nframes = nframes;

	/*
	 * Use environment VIDEO_PERFORMANCE_TEST to select different mode.
	 * When doing performance test, video decoding and display are in different
	 * threads and default display fps is controlled by cmd. Display will
	 * show the frame immediately if user doesn't input fps with -a option.
	 * This is different from normal unit test.
	 */

	return disp;
err:
	close(fd);
	free(disp);
	return NULL;
}