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

📄 pxa_camera.c

📁 trident tm5600的linux驱动
💻 C
📖 第 1 页 / 共 3 页
字号:
		bpp = 0x40;		break;	case SOCAM_DATAWIDTH_9:		icd->buswidth = 9;		dw = 3;		bpp = 0x20;		break;	default:		/* Actually it can only be 8 now,		 * default is just to silence compiler warnings */	case SOCAM_DATAWIDTH_8:		icd->buswidth = 8;		dw = 2;		bpp = 0;	}	if (pcdev->platform_flags & PXA_CAMERA_PCLK_EN)		cicr4 |= CICR4_PCLK_EN;	if (pcdev->platform_flags & PXA_CAMERA_MCLK_EN)		cicr4 |= CICR4_MCLK_EN;	if (common_flags & SOCAM_PCLK_SAMPLE_FALLING)		cicr4 |= CICR4_PCP;	if (common_flags & SOCAM_HSYNC_ACTIVE_LOW)		cicr4 |= CICR4_HSP;	if (common_flags & SOCAM_VSYNC_ACTIVE_LOW)		cicr4 |= CICR4_VSP;	cicr0 = CICR0;	if (cicr0 & CICR0_ENB)		CICR0 = cicr0 & ~CICR0_ENB;	cicr1 = CICR1_PPL_VAL(icd->width - 1) | bpp | dw;	switch (pixfmt) {	case V4L2_PIX_FMT_YUV422P:		pcdev->channels = 3;		cicr1 |= CICR1_YCBCR_F;	case V4L2_PIX_FMT_YUYV:		cicr1 |= CICR1_COLOR_SP_VAL(2);		break;	case V4L2_PIX_FMT_RGB555:		cicr1 |= CICR1_RGB_BPP_VAL(1) | CICR1_RGBT_CONV_VAL(2) |			CICR1_TBIT | CICR1_COLOR_SP_VAL(1);		break;	case V4L2_PIX_FMT_RGB565:		cicr1 |= CICR1_COLOR_SP_VAL(1) | CICR1_RGB_BPP_VAL(2);		break;	}	CICR1 = cicr1;	CICR2 = 0;	CICR3 = CICR3_LPF_VAL(icd->height - 1) |		CICR3_BFW_VAL(min((unsigned short)255, icd->y_skip_top));	CICR4 = mclk_get_divisor(pcdev) | cicr4;	/* CIF interrupts are not used, only DMA */	CICR0 = (pcdev->platform_flags & PXA_CAMERA_MASTER ?		 CICR0_SIM_MP : (CICR0_SL_CAP_EN | CICR0_SIM_SP)) |		CICR0_DMAEN | CICR0_IRQ_MASK | (cicr0 & CICR0_ENB);	return 0;}static int pxa_camera_try_bus_param(struct soc_camera_device *icd, __u32 pixfmt){	struct soc_camera_host *ici =		to_soc_camera_host(icd->dev.parent);	struct pxa_camera_dev *pcdev = ici->priv;	unsigned long bus_flags, camera_flags;	int ret = test_platform_param(pcdev, icd->buswidth, &bus_flags);	if (ret < 0)		return ret;	camera_flags = icd->ops->query_bus_param(icd);	return soc_camera_bus_param_compatible(camera_flags, bus_flags) ? 0 : -EINVAL;}static int pxa_camera_set_fmt_cap(struct soc_camera_device *icd,				  __u32 pixfmt, struct v4l2_rect *rect){	return icd->ops->set_fmt_cap(icd, pixfmt, rect);}static int pxa_camera_try_fmt_cap(struct soc_camera_device *icd,				  struct v4l2_format *f){	/* limit to pxa hardware capabilities */	if (f->fmt.pix.height < 32)		f->fmt.pix.height = 32;	if (f->fmt.pix.height > 2048)		f->fmt.pix.height = 2048;	if (f->fmt.pix.width < 48)		f->fmt.pix.width = 48;	if (f->fmt.pix.width > 2048)		f->fmt.pix.width = 2048;	f->fmt.pix.width &= ~0x01;	/* limit to sensor capabilities */	return icd->ops->try_fmt_cap(icd, f);}static int pxa_camera_reqbufs(struct soc_camera_file *icf,			      struct v4l2_requestbuffers *p){	int i;	/* This is for locking debugging only. I removed spinlocks and now I	 * check whether .prepare is ever called on a linked buffer, or whether	 * a dma IRQ can occur for an in-work or unlinked buffer. Until now	 * it hadn't triggered */	for (i = 0; i < p->count; i++) {		struct pxa_buffer *buf = container_of(icf->vb_vidq.bufs[i],						      struct pxa_buffer, vb);		buf->inwork = 0;		INIT_LIST_HEAD(&buf->vb.queue);	}	return 0;}static unsigned int pxa_camera_poll(struct file *file, poll_table *pt){	struct soc_camera_file *icf = file->private_data;	struct pxa_buffer *buf;	buf = list_entry(icf->vb_vidq.stream.next, struct pxa_buffer,			 vb.stream);	poll_wait(file, &buf->vb.done, pt);	if (buf->vb.state == VIDEOBUF_DONE ||	    buf->vb.state == VIDEOBUF_ERROR)		return POLLIN|POLLRDNORM;	return 0;}static int pxa_camera_querycap(struct soc_camera_host *ici,			       struct v4l2_capability *cap){	/* cap->name is set by the firendly caller:-> */	strlcpy(cap->card, pxa_cam_driver_description, sizeof(cap->card));	cap->version = PXA_CAM_VERSION_CODE;	cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;	return 0;}static int pxa_camera_suspend(struct soc_camera_device *icd, pm_message_t state){	struct soc_camera_host *ici =		to_soc_camera_host(icd->dev.parent);	struct pxa_camera_dev *pcdev = ici->priv;	int i = 0, ret = 0;	pcdev->save_cicr[i++] = CICR0;	pcdev->save_cicr[i++] = CICR1;	pcdev->save_cicr[i++] = CICR2;	pcdev->save_cicr[i++] = CICR3;	pcdev->save_cicr[i++] = CICR4;	if ((pcdev->icd) && (pcdev->icd->ops->suspend))		ret = pcdev->icd->ops->suspend(pcdev->icd, state);	return ret;}static int pxa_camera_resume(struct soc_camera_device *icd){	struct soc_camera_host *ici =		to_soc_camera_host(icd->dev.parent);	struct pxa_camera_dev *pcdev = ici->priv;	int i = 0, ret = 0;	DRCMR(68) = pcdev->dma_chans[0] | DRCMR_MAPVLD;	DRCMR(69) = pcdev->dma_chans[1] | DRCMR_MAPVLD;	DRCMR(70) = pcdev->dma_chans[2] | DRCMR_MAPVLD;	CICR0 = pcdev->save_cicr[i++] & ~CICR0_ENB;	CICR1 = pcdev->save_cicr[i++];	CICR2 = pcdev->save_cicr[i++];	CICR3 = pcdev->save_cicr[i++];	CICR4 = pcdev->save_cicr[i++];	if ((pcdev->icd) && (pcdev->icd->ops->resume))		ret = pcdev->icd->ops->resume(pcdev->icd);	/* Restart frame capture if active buffer exists */	if (!ret && pcdev->active) {		/* Reset the FIFOs */		CIFR |= CIFR_RESET_F;		/* Enable End-Of-Frame Interrupt */		CICR0 &= ~CICR0_EOFM;		/* Restart the Capture Interface */		CICR0 |= CICR0_ENB;	}	return ret;}static struct soc_camera_host_ops pxa_soc_camera_host_ops = {	.owner		= THIS_MODULE,	.add		= pxa_camera_add_device,	.remove		= pxa_camera_remove_device,	.suspend	= pxa_camera_suspend,	.resume		= pxa_camera_resume,	.set_fmt_cap	= pxa_camera_set_fmt_cap,	.try_fmt_cap	= pxa_camera_try_fmt_cap,	.init_videobuf	= pxa_camera_init_videobuf,	.reqbufs	= pxa_camera_reqbufs,	.poll		= pxa_camera_poll,	.querycap	= pxa_camera_querycap,	.try_bus_param	= pxa_camera_try_bus_param,	.set_bus_param	= pxa_camera_set_bus_param,};/* Should be allocated dynamically too, but we have only one. */static struct soc_camera_host pxa_soc_camera_host = {	.drv_name		= PXA_CAM_DRV_NAME,	.ops			= &pxa_soc_camera_host_ops,};static int pxa_camera_probe(struct platform_device *pdev){	struct pxa_camera_dev *pcdev;	struct resource *res;	void __iomem *base;	int irq;	int err = 0;	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);	irq = platform_get_irq(pdev, 0);	if (!res || irq < 0) {		err = -ENODEV;		goto exit;	}	pcdev = kzalloc(sizeof(*pcdev), GFP_KERNEL);	if (!pcdev) {		dev_err(&pdev->dev, "Could not allocate pcdev\n");		err = -ENOMEM;		goto exit;	}	pcdev->clk = clk_get(&pdev->dev, "CAMCLK");	if (IS_ERR(pcdev->clk)) {		err = PTR_ERR(pcdev->clk);		goto exit_kfree;	}	dev_set_drvdata(&pdev->dev, pcdev);	pcdev->res = res;	pcdev->pdata = pdev->dev.platform_data;	pcdev->platform_flags = pcdev->pdata->flags;	if (!(pcdev->platform_flags & (PXA_CAMERA_DATAWIDTH_8 |			PXA_CAMERA_DATAWIDTH_9 | PXA_CAMERA_DATAWIDTH_10))) {		/* Platform hasn't set available data widths. This is bad.		 * Warn and use a default. */		dev_warn(&pdev->dev, "WARNING! Platform hasn't set available "			 "data widths, using default 10 bit\n");		pcdev->platform_flags |= PXA_CAMERA_DATAWIDTH_10;	}	pcdev->platform_mclk_10khz = pcdev->pdata->mclk_10khz;	if (!pcdev->platform_mclk_10khz) {		dev_warn(&pdev->dev,			 "mclk_10khz == 0! Please, fix your platform data. "			 "Using default 20MHz\n");		pcdev->platform_mclk_10khz = 2000;	}	INIT_LIST_HEAD(&pcdev->capture);	spin_lock_init(&pcdev->lock);	/*	 * Request the regions.	 */	if (!request_mem_region(res->start, res->end - res->start + 1,				PXA_CAM_DRV_NAME)) {		err = -EBUSY;		goto exit_clk;	}	base = ioremap(res->start, res->end - res->start + 1);	if (!base) {		err = -ENOMEM;		goto exit_release;	}	pcdev->irq = irq;	pcdev->base = base;	pcdev->dev = &pdev->dev;	/* request dma */	err = pxa_request_dma("CI_Y", DMA_PRIO_HIGH,			      pxa_camera_dma_irq_y, pcdev);	if (err < 0) {		dev_err(pcdev->dev, "Can't request DMA for Y\n");		goto exit_iounmap;	}	pcdev->dma_chans[0] = err;	dev_dbg(pcdev->dev, "got DMA channel %d\n", pcdev->dma_chans[0]);	err = pxa_request_dma("CI_U", DMA_PRIO_HIGH,			      pxa_camera_dma_irq_u, pcdev);	if (err < 0) {		dev_err(pcdev->dev, "Can't request DMA for U\n");		goto exit_free_dma_y;	}	pcdev->dma_chans[1] = err;	dev_dbg(pcdev->dev, "got DMA channel (U) %d\n", pcdev->dma_chans[1]);	err = pxa_request_dma("CI_V", DMA_PRIO_HIGH,			      pxa_camera_dma_irq_v, pcdev);	if (err < 0) {		dev_err(pcdev->dev, "Can't request DMA for V\n");		goto exit_free_dma_u;	}	pcdev->dma_chans[2] = err;	dev_dbg(pcdev->dev, "got DMA channel (V) %d\n", pcdev->dma_chans[2]);	DRCMR(68) = pcdev->dma_chans[0] | DRCMR_MAPVLD;	DRCMR(69) = pcdev->dma_chans[1] | DRCMR_MAPVLD;	DRCMR(70) = pcdev->dma_chans[2] | DRCMR_MAPVLD;	/* request irq */	err = request_irq(pcdev->irq, pxa_camera_irq, 0, PXA_CAM_DRV_NAME,			  pcdev);	if (err) {		dev_err(pcdev->dev, "Camera interrupt register failed \n");		goto exit_free_dma;	}	pxa_soc_camera_host.priv	= pcdev;	pxa_soc_camera_host.dev.parent	= &pdev->dev;	pxa_soc_camera_host.nr		= pdev->id;	err = soc_camera_host_register(&pxa_soc_camera_host);	if (err)		goto exit_free_irq;	return 0;exit_free_irq:	free_irq(pcdev->irq, pcdev);exit_free_dma:	pxa_free_dma(pcdev->dma_chans[2]);exit_free_dma_u:	pxa_free_dma(pcdev->dma_chans[1]);exit_free_dma_y:	pxa_free_dma(pcdev->dma_chans[0]);exit_iounmap:	iounmap(base);exit_release:	release_mem_region(res->start, res->end - res->start + 1);exit_clk:	clk_put(pcdev->clk);exit_kfree:	kfree(pcdev);exit:	return err;}static int __devexit pxa_camera_remove(struct platform_device *pdev){	struct pxa_camera_dev *pcdev = platform_get_drvdata(pdev);	struct resource *res;	clk_put(pcdev->clk);	pxa_free_dma(pcdev->dma_chans[0]);	pxa_free_dma(pcdev->dma_chans[1]);	pxa_free_dma(pcdev->dma_chans[2]);	free_irq(pcdev->irq, pcdev);	soc_camera_host_unregister(&pxa_soc_camera_host);	iounmap(pcdev->base);	res = pcdev->res;	release_mem_region(res->start, res->end - res->start + 1);	kfree(pcdev);	dev_info(&pdev->dev, "PXA Camera driver unloaded\n");	return 0;}static struct platform_driver pxa_camera_driver = {	.driver 	= {		.name	= PXA_CAM_DRV_NAME,	},	.probe		= pxa_camera_probe,	.remove		= __exit_p(pxa_camera_remove),};static int __devinit pxa_camera_init(void){	return platform_driver_register(&pxa_camera_driver);}static void __exit pxa_camera_exit(void){	platform_driver_unregister(&pxa_camera_driver);}module_init(pxa_camera_init);module_exit(pxa_camera_exit);MODULE_DESCRIPTION("PXA27x SoC Camera Host driver");MODULE_AUTHOR("Guennadi Liakhovetski <kernel@pengutronix.de>");MODULE_LICENSE("GPL");

⌨️ 快捷键说明

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