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

📄 ipu_prp_enc.c

📁 LINUX下的ov2640驱动程序
💻 C
字号:
/* * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved. *//* * The code contained herein is licensed under the GNU General Public * License. You may obtain a copy of the GNU General Public License * Version 2 or later at the following locations: * * http://www.opensource.org/licenses/gpl-license.html * http://www.gnu.org/copyleft/gpl.html *//*! * @file ipu_prp_enc.c * * @brief IPU Use case for PRP-ENC * * @ingroup IPU */#include "mxc_v4l2_capture.h"#include <asm/arch/ipu.h>#include "ipu_prp_sw.h"#include <linux/dma-mapping.h>static ipu_rotate_mode_t grotation = IPU_ROTATE_NONE;/* * Function definitions *//*! * IPU ENC callback function. * * @param irq       int irq line * @param dev_id    void * device id * * @return status   IRQ_HANDLED for handled */static irqreturn_t prp_enc_callback(int irq, void *dev_id){	cam_data *cam = (cam_data *) dev_id;	if (cam->enc_callback == NULL)		return IRQ_HANDLED;	cam->enc_callback(irq, dev_id);	return IRQ_HANDLED;}/*! * PrpENC enable channel setup function * * @param cam       struct cam_data * mxc capture instance * * @return  status */static int prp_enc_setup(cam_data * cam){	ipu_channel_params_t enc;	int err = 0;	dma_addr_t dummy = 0xdeadbeaf;	if (!cam) {		printk(KERN_ERR "cam private is NULL\n");		return -ENXIO;	}	ipu_csi_get_window_size(&enc.csi_prp_enc_mem.in_width,				&enc.csi_prp_enc_mem.in_height);	enc.csi_prp_enc_mem.in_pixel_fmt = IPU_PIX_FMT_UYVY;	enc.csi_prp_enc_mem.out_width = cam->v2f.fmt.pix.width;	enc.csi_prp_enc_mem.out_height = cam->v2f.fmt.pix.height;	if (cam->rotation >= IPU_ROTATE_90_RIGHT) {		enc.csi_prp_enc_mem.out_width = cam->v2f.fmt.pix.height;		enc.csi_prp_enc_mem.out_height = cam->v2f.fmt.pix.width;	}	if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_YUV420) {		enc.csi_prp_enc_mem.out_pixel_fmt = IPU_PIX_FMT_YUV420P;		pr_info("YUV420\n");	} else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_YUV422P) {		enc.csi_prp_enc_mem.out_pixel_fmt = IPU_PIX_FMT_YUV422P;		pr_info("YUV422P\n");	} else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_BGR24) {		enc.csi_prp_enc_mem.out_pixel_fmt = IPU_PIX_FMT_BGR24;		pr_info("BGR24\n");	} else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_RGB24) {		enc.csi_prp_enc_mem.out_pixel_fmt = IPU_PIX_FMT_RGB24;		pr_info("RGB24\n");	} else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_RGB565) {		enc.csi_prp_enc_mem.out_pixel_fmt = IPU_PIX_FMT_RGB565;		pr_info("RGB565\n");	} else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_BGR32) {		enc.csi_prp_enc_mem.out_pixel_fmt = IPU_PIX_FMT_BGR32;		pr_info("BGR32\n");	} else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_RGB32) {		enc.csi_prp_enc_mem.out_pixel_fmt = IPU_PIX_FMT_RGB32;		pr_info("RGB32\n");	} else {		printk(KERN_ERR "format not supported\n");		return -EINVAL;	}	//ipu_uninit_channel(CSI_PRP_ENC_MEM);	err = ipu_init_channel(CSI_PRP_ENC_MEM, &enc);	if (err != 0) {		printk(KERN_ERR "ipu_init_channel %d\n", err);		return err;	}	ipu_csi_enable_mclk(CSI_MCLK_ENC, true, true);	grotation = cam->rotation;	if (cam->rotation >= IPU_ROTATE_90_RIGHT) {		if (cam->rot_enc_bufs_vaddr[0]) {			dma_free_coherent(0, cam->rot_enc_buf_size[0],					  cam->rot_enc_bufs_vaddr[0],					  cam->rot_enc_bufs[0]);		}		if (cam->rot_enc_bufs_vaddr[1]) {			dma_free_coherent(0, cam->rot_enc_buf_size[1],					  cam->rot_enc_bufs_vaddr[1],					  cam->rot_enc_bufs[1]);		}		cam->rot_enc_buf_size[0] =		    PAGE_ALIGN(cam->v2f.fmt.pix.sizeimage);		cam->rot_enc_bufs_vaddr[0] =		    (void *)dma_alloc_coherent(0, cam->rot_enc_buf_size[0],					       &cam->rot_enc_bufs[0],					       GFP_DMA | GFP_KERNEL);		if (!cam->rot_enc_bufs_vaddr[0]) {			printk(KERN_ERR "alloc enc_bufs0\n");			return -ENOMEM;		}		cam->rot_enc_buf_size[1] =		    PAGE_ALIGN(cam->v2f.fmt.pix.sizeimage);		cam->rot_enc_bufs_vaddr[1] =		    (void *)dma_alloc_coherent(0, cam->rot_enc_buf_size[1],					       &cam->rot_enc_bufs[1],					       GFP_DMA | GFP_KERNEL);		if (!cam->rot_enc_bufs_vaddr[1]) {			dma_free_coherent(0, cam->rot_enc_buf_size[0],					  cam->rot_enc_bufs_vaddr[0],					  cam->rot_enc_bufs[0]);			cam->rot_enc_bufs_vaddr[0] = NULL;			cam->rot_enc_bufs[0] = 0;			printk(KERN_ERR "alloc enc_bufs1\n");			return -ENOMEM;		}		err = ipu_init_channel_buffer(CSI_PRP_ENC_MEM,					      IPU_OUTPUT_BUFFER,					      enc.csi_prp_enc_mem.out_pixel_fmt,					      enc.csi_prp_enc_mem.out_width,					      enc.csi_prp_enc_mem.out_height,					      enc.csi_prp_enc_mem.out_width,					      IPU_ROTATE_NONE,					      cam->rot_enc_bufs[0],					      cam->rot_enc_bufs[1], 0, 0);		if (err != 0) {			printk(KERN_ERR "CSI_PRP_ENC_MEM err\n");			return err;		}		//ipu_uninit_channel(MEM_ROT_ENC_MEM);		err = ipu_init_channel(MEM_ROT_ENC_MEM, NULL);		if (err != 0) {			printk(KERN_ERR "MEM_ROT_ENC_MEM channel err\n");			return err;		}		err = ipu_init_channel_buffer(MEM_ROT_ENC_MEM, IPU_INPUT_BUFFER,					      enc.csi_prp_enc_mem.out_pixel_fmt,					      enc.csi_prp_enc_mem.out_width,					      enc.csi_prp_enc_mem.out_height,					      enc.csi_prp_enc_mem.out_width,					      cam->rotation,					      cam->rot_enc_bufs[0],					      cam->rot_enc_bufs[1], 0, 0);		if (err != 0) {			printk(KERN_ERR "MEM_ROT_ENC_MEM input buffer\n");			return err;		}		err =		    ipu_init_channel_buffer(MEM_ROT_ENC_MEM, IPU_OUTPUT_BUFFER,					    enc.csi_prp_enc_mem.out_pixel_fmt,					    enc.csi_prp_enc_mem.out_height,					    enc.csi_prp_enc_mem.out_width,					    cam->v2f.fmt.pix.bytesperline /					    bytes_per_pixel(enc.csi_prp_enc_mem.							    out_pixel_fmt),					    IPU_ROTATE_NONE, dummy, dummy,					    cam->offset.u_offset,					    cam->offset.v_offset);		if (err != 0) {			printk(KERN_ERR "MEM_ROT_ENC_MEM output buffer\n");			return err;		}		err = ipu_link_channels(CSI_PRP_ENC_MEM, MEM_ROT_ENC_MEM);		if (err < 0) {			printk(KERN_ERR			       "link CSI_PRP_ENC_MEM-MEM_ROT_ENC_MEM\n");			return err;		}		err = ipu_enable_channel(CSI_PRP_ENC_MEM);		if (err < 0) {			printk(KERN_ERR "ipu_enable_channel CSI_PRP_ENC_MEM\n");			return err;		}		err = ipu_enable_channel(MEM_ROT_ENC_MEM);		if (err < 0) {			printk(KERN_ERR "ipu_enable_channel MEM_ROT_ENC_MEM\n");			return err;		}		ipu_select_buffer(CSI_PRP_ENC_MEM, IPU_OUTPUT_BUFFER, 0);		ipu_select_buffer(CSI_PRP_ENC_MEM, IPU_OUTPUT_BUFFER, 1);	} else {		err =		    ipu_init_channel_buffer(CSI_PRP_ENC_MEM, IPU_OUTPUT_BUFFER,					    enc.csi_prp_enc_mem.out_pixel_fmt,					    enc.csi_prp_enc_mem.out_width,					    enc.csi_prp_enc_mem.out_height,					    cam->v2f.fmt.pix.bytesperline /					    bytes_per_pixel(enc.csi_prp_enc_mem.							    out_pixel_fmt),					    cam->rotation, dummy, dummy,					    cam->offset.u_offset,					    cam->offset.v_offset);		if (err != 0) {			printk(KERN_ERR "CSI_PRP_ENC_MEM output buffer\n");			return err;		}		err = ipu_enable_channel(CSI_PRP_ENC_MEM);		if (err < 0) {			printk(KERN_ERR "ipu_enable_channel CSI_PRP_ENC_MEM\n");			return err;		}	}	return err;}/*! * function to update physical buffer address for encorder IDMA channel * * @param eba         physical buffer address for encorder IDMA channel * @param buffer_num  int buffer 0 or buffer 1 * * @return  status */static int prp_enc_eba_update(dma_addr_t eba, int *buffer_num){	int err = 0;	pr_debug("eba %x\n", eba);	if (grotation >= IPU_ROTATE_90_RIGHT) {		err = ipu_update_channel_buffer(MEM_ROT_ENC_MEM,						IPU_OUTPUT_BUFFER, *buffer_num,						eba);	} else {		err = ipu_update_channel_buffer(CSI_PRP_ENC_MEM,						IPU_OUTPUT_BUFFER, *buffer_num,						eba);	}	if (err != 0) {		printk(KERN_ERR "err %d buffer_num %d\n", err, *buffer_num);		return err;	}	if (grotation >= IPU_ROTATE_90_RIGHT) {		ipu_select_buffer(MEM_ROT_ENC_MEM, IPU_OUTPUT_BUFFER,				  *buffer_num);	} else {		ipu_select_buffer(CSI_PRP_ENC_MEM, IPU_OUTPUT_BUFFER,				  *buffer_num);	}	*buffer_num = (*buffer_num == 0) ? 1 : 0;	return 0;}/*! * Enable encoder task * @param private       struct cam_data * mxc capture instance * * @return  status */static int prp_enc_enabling_tasks(void *private){	cam_data *cam = (cam_data *) private;	int err = 0;	if (cam->rotation >= IPU_ROTATE_90_RIGHT) {		err = ipu_request_irq(IPU_IRQ_PRP_ENC_ROT_OUT_EOF,				      prp_enc_callback, 0, "Mxc Camera", cam);	} else {		err = ipu_request_irq(IPU_IRQ_PRP_ENC_OUT_EOF,				      prp_enc_callback, 0, "Mxc Camera", cam);	}	if (err != 0) {		printk(KERN_ERR "Error registering rot irq\n");		return err;	}	err = prp_enc_setup(cam);	if (err != 0) {		printk(KERN_ERR "prp_enc_setup %d\n", err);		return err;	}	return err;}/*! * Disable encoder task * @param private       struct cam_data * mxc capture instance * * @return  int */static int prp_enc_disabling_tasks(void *private){	cam_data *cam = (cam_data *) private;	int err = 0;	if (cam->rotation >= IPU_ROTATE_90_RIGHT) {		ipu_free_irq(IPU_IRQ_PRP_ENC_ROT_OUT_EOF, cam);	} else {		ipu_free_irq(IPU_IRQ_PRP_ENC_OUT_EOF, cam);	}	if (cam->rotation >= IPU_ROTATE_90_RIGHT) {		ipu_unlink_channels(CSI_PRP_ENC_MEM, MEM_ROT_ENC_MEM);	}	err = ipu_disable_channel(CSI_PRP_ENC_MEM, true);	if (cam->rotation >= IPU_ROTATE_90_RIGHT) {		err |= ipu_disable_channel(MEM_ROT_ENC_MEM, true);	}	ipu_uninit_channel(CSI_PRP_ENC_MEM);	if (cam->rotation >= IPU_ROTATE_90_RIGHT) {		ipu_uninit_channel(MEM_ROT_ENC_MEM);	}	ipu_csi_enable_mclk(CSI_MCLK_ENC, false, false);	return err;}/*! * function to select PRP-ENC as the working path * * @param private       struct cam_data * mxc capture instance * * @return  int */int prp_enc_select(void *private){	cam_data *cam = (cam_data *) private;	int err = 0;	if (cam) {		cam->enc_update_eba = prp_enc_eba_update;		cam->enc_enable = prp_enc_enabling_tasks;		cam->enc_disable = prp_enc_disabling_tasks;	} else {		err = -EIO;	}	return err;}/*! * function to de-select PRP-ENC as the working path * * @param private       struct cam_data * mxc capture instance * * @return  int */int prp_enc_deselect(void *private){	cam_data *cam = (cam_data *) private;	int err = 0;	//err = prp_enc_disabling_tasks(cam);	if (cam) {		cam->enc_update_eba = NULL;		cam->enc_enable = NULL;		cam->enc_disable = NULL;		if (cam->rot_enc_bufs_vaddr[0]) {			dma_free_coherent(0, cam->rot_enc_buf_size[0],					  cam->rot_enc_bufs_vaddr[0],					  cam->rot_enc_bufs[0]);			cam->rot_enc_bufs_vaddr[0] = NULL;			cam->rot_enc_bufs[0] = 0;		}		if (cam->rot_enc_bufs_vaddr[1]) {			dma_free_coherent(0, cam->rot_enc_buf_size[1],					  cam->rot_enc_bufs_vaddr[1],					  cam->rot_enc_bufs[1]);			cam->rot_enc_bufs_vaddr[1] = NULL;			cam->rot_enc_bufs[1] = 0;		}	}	return err;}/*! * Init the Encorder channels * * @return  Error code indicating success or failure */__init int prp_enc_init(void){	return 0;}/*! * Deinit the Encorder channels * */void __exit prp_enc_exit(void){}module_init(prp_enc_init);module_exit(prp_enc_exit);EXPORT_SYMBOL(prp_enc_select);EXPORT_SYMBOL(prp_enc_deselect);MODULE_AUTHOR("Freescale Semiconductor, Inc.");MODULE_DESCRIPTION("IPU PRP ENC Driver");MODULE_LICENSE("GPL");

⌨️ 快捷键说明

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