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

📄 cafe_ccic.c

📁 trident tm5600的linux驱动
💻 C
📖 第 1 页 / 共 4 页
字号:
	i2c_set_adapdata(adap, cam);	ret = i2c_add_adapter(adap);	if (ret)		printk(KERN_ERR "Unable to register cafe i2c adapter\n");	return ret;}static void cafe_smbus_shutdown(struct cafe_camera *cam){	i2c_del_adapter(&cam->i2c_adapter);}/* ------------------------------------------------------------------- *//* * Deal with the controller. *//* * Do everything we think we need to have the interface operating * according to the desired format. */static void cafe_ctlr_dma(struct cafe_camera *cam){	/*	 * Store the first two Y buffers (we aren't supporting	 * planar formats for now, so no UV bufs).  Then either	 * set the third if it exists, or tell the controller	 * to just use two.	 */	cafe_reg_write(cam, REG_Y0BAR, cam->dma_handles[0]);	cafe_reg_write(cam, REG_Y1BAR, cam->dma_handles[1]);	if (cam->nbufs > 2) {		cafe_reg_write(cam, REG_Y2BAR, cam->dma_handles[2]);		cafe_reg_clear_bit(cam, REG_CTRL1, C1_TWOBUFS);	}	else		cafe_reg_set_bit(cam, REG_CTRL1, C1_TWOBUFS);	cafe_reg_write(cam, REG_UBAR, 0); /* 32 bits only for now */}static void cafe_ctlr_image(struct cafe_camera *cam){	int imgsz;	struct v4l2_pix_format *fmt = &cam->pix_format;	imgsz = ((fmt->height << IMGSZ_V_SHIFT) & IMGSZ_V_MASK) |		(fmt->bytesperline & IMGSZ_H_MASK);	cafe_reg_write(cam, REG_IMGSIZE, imgsz);	cafe_reg_write(cam, REG_IMGOFFSET, 0);	/* YPITCH just drops the last two bits */	cafe_reg_write_mask(cam, REG_IMGPITCH, fmt->bytesperline,			IMGP_YP_MASK);	/*	 * Tell the controller about the image format we are using.	 */	switch (cam->pix_format.pixelformat) {	case V4L2_PIX_FMT_YUYV:	    cafe_reg_write_mask(cam, REG_CTRL0,			    C0_DF_YUV|C0_YUV_PACKED|C0_YUVE_YUYV,			    C0_DF_MASK);	    break;	case V4L2_PIX_FMT_RGB444:	    cafe_reg_write_mask(cam, REG_CTRL0,			    C0_DF_RGB|C0_RGBF_444|C0_RGB4_XRGB,			    C0_DF_MASK);		/* Alpha value? */	    break;	case V4L2_PIX_FMT_RGB565:	    cafe_reg_write_mask(cam, REG_CTRL0,			    C0_DF_RGB|C0_RGBF_565|C0_RGB5_BGGR,			    C0_DF_MASK);	    break;	default:	    cam_err(cam, "Unknown format %x\n", cam->pix_format.pixelformat);	    break;	}	/*	 * Make sure it knows we want to use hsync/vsync.	 */	cafe_reg_write_mask(cam, REG_CTRL0, C0_SIF_HVSYNC,			C0_SIFM_MASK);}/* * Configure the controller for operation; caller holds the * device mutex. */static int cafe_ctlr_configure(struct cafe_camera *cam){	unsigned long flags;	spin_lock_irqsave(&cam->dev_lock, flags);	cafe_ctlr_dma(cam);	cafe_ctlr_image(cam);	cafe_set_config_needed(cam, 0);	spin_unlock_irqrestore(&cam->dev_lock, flags);	return 0;}static void cafe_ctlr_irq_enable(struct cafe_camera *cam){	/*	 * Clear any pending interrupts, since we do not	 * expect to have I/O active prior to enabling.	 */	cafe_reg_write(cam, REG_IRQSTAT, FRAMEIRQS);	cafe_reg_set_bit(cam, REG_IRQMASK, FRAMEIRQS);}static void cafe_ctlr_irq_disable(struct cafe_camera *cam){	cafe_reg_clear_bit(cam, REG_IRQMASK, FRAMEIRQS);}/* * Make the controller start grabbing images.  Everything must * be set up before doing this. */static void cafe_ctlr_start(struct cafe_camera *cam){	/* set_bit performs a read, so no other barrier should be	   needed here */	cafe_reg_set_bit(cam, REG_CTRL0, C0_ENABLE);}static void cafe_ctlr_stop(struct cafe_camera *cam){	cafe_reg_clear_bit(cam, REG_CTRL0, C0_ENABLE);}static void cafe_ctlr_init(struct cafe_camera *cam){	unsigned long flags;	spin_lock_irqsave(&cam->dev_lock, flags);	/*	 * Added magic to bring up the hardware on the B-Test board	 */	cafe_reg_write(cam, 0x3038, 0x8);	cafe_reg_write(cam, 0x315c, 0x80008);	/*	 * Go through the dance needed to wake the device up.	 * Note that these registers are global and shared	 * with the NAND and SD devices.  Interaction between the	 * three still needs to be examined.	 */	cafe_reg_write(cam, REG_GL_CSR, GCSR_SRS|GCSR_MRS); /* Needed? */	cafe_reg_write(cam, REG_GL_CSR, GCSR_SRC|GCSR_MRC);	cafe_reg_write(cam, REG_GL_CSR, GCSR_SRC|GCSR_MRS);	/*	 * Here we must wait a bit for the controller to come around.	 */	spin_unlock_irqrestore(&cam->dev_lock, flags);	msleep(5);	spin_lock_irqsave(&cam->dev_lock, flags);	cafe_reg_write(cam, REG_GL_CSR, GCSR_CCIC_EN|GCSR_SRC|GCSR_MRC);	cafe_reg_set_bit(cam, REG_GL_IMASK, GIMSK_CCIC_EN);	/*	 * Make sure it's not powered down.	 */	cafe_reg_clear_bit(cam, REG_CTRL1, C1_PWRDWN);	/*	 * Turn off the enable bit.  It sure should be off anyway,	 * but it's good to be sure.	 */	cafe_reg_clear_bit(cam, REG_CTRL0, C0_ENABLE);	/*	 * Mask all interrupts.	 */	cafe_reg_write(cam, REG_IRQMASK, 0);	/*	 * Clock the sensor appropriately.  Controller clock should	 * be 48MHz, sensor "typical" value is half that.	 */	cafe_reg_write_mask(cam, REG_CLKCTRL, 2, CLK_DIV_MASK);	spin_unlock_irqrestore(&cam->dev_lock, flags);}/* * Stop the controller, and don't return until we're really sure that no * further DMA is going on. */static void cafe_ctlr_stop_dma(struct cafe_camera *cam){	unsigned long flags;	/*	 * Theory: stop the camera controller (whether it is operating	 * or not).  Delay briefly just in case we race with the SOF	 * interrupt, then wait until no DMA is active.	 */	spin_lock_irqsave(&cam->dev_lock, flags);	cafe_ctlr_stop(cam);	spin_unlock_irqrestore(&cam->dev_lock, flags);	mdelay(1);	wait_event_timeout(cam->iowait,			!test_bit(CF_DMA_ACTIVE, &cam->flags), HZ);	if (test_bit(CF_DMA_ACTIVE, &cam->flags))		cam_err(cam, "Timeout waiting for DMA to end\n");		/* This would be bad news - what now? */	spin_lock_irqsave(&cam->dev_lock, flags);	cam->state = S_IDLE;	cafe_ctlr_irq_disable(cam);	spin_unlock_irqrestore(&cam->dev_lock, flags);}/* * Power up and down. */static void cafe_ctlr_power_up(struct cafe_camera *cam){	unsigned long flags;	spin_lock_irqsave(&cam->dev_lock, flags);	cafe_reg_clear_bit(cam, REG_CTRL1, C1_PWRDWN);	/*	 * Part one of the sensor dance: turn the global	 * GPIO signal on.	 */	cafe_reg_write(cam, REG_GL_FCR, GFCR_GPIO_ON);	cafe_reg_write(cam, REG_GL_GPIOR, GGPIO_OUT|GGPIO_VAL);	/*	 * Put the sensor into operational mode (assumes OLPC-style	 * wiring).  Control 0 is reset - set to 1 to operate.	 * Control 1 is power down, set to 0 to operate.	 */	cafe_reg_write(cam, REG_GPR, GPR_C1EN|GPR_C0EN); /* pwr up, reset *///	mdelay(1); /* Marvell says 1ms will do it */	cafe_reg_write(cam, REG_GPR, GPR_C1EN|GPR_C0EN|GPR_C0);//	mdelay(1); /* Enough? */	spin_unlock_irqrestore(&cam->dev_lock, flags);	msleep(5); /* Just to be sure */}static void cafe_ctlr_power_down(struct cafe_camera *cam){	unsigned long flags;	spin_lock_irqsave(&cam->dev_lock, flags);	cafe_reg_write(cam, REG_GPR, GPR_C1EN|GPR_C0EN|GPR_C1);	cafe_reg_write(cam, REG_GL_FCR, GFCR_GPIO_ON);	cafe_reg_write(cam, REG_GL_GPIOR, GGPIO_OUT);	cafe_reg_set_bit(cam, REG_CTRL1, C1_PWRDWN);	spin_unlock_irqrestore(&cam->dev_lock, flags);}/* -------------------------------------------------------------------- *//* * Communications with the sensor. */static int __cafe_cam_cmd(struct cafe_camera *cam, int cmd, void *arg){	struct i2c_client *sc = cam->sensor;	int ret;	if (sc == NULL || sc->driver == NULL || sc->driver->command == NULL)		return -EINVAL;	ret = sc->driver->command(sc, cmd, arg);	if (ret == -EPERM) /* Unsupported command */		return 0;	return ret;}static int __cafe_cam_reset(struct cafe_camera *cam){	int zero = 0;	return __cafe_cam_cmd(cam, VIDIOC_INT_RESET, &zero);}/* * We have found the sensor on the i2c.  Let's try to have a * conversation. */static int cafe_cam_init(struct cafe_camera *cam){	struct v4l2_chip_ident chip = { V4L2_CHIP_MATCH_I2C_ADDR, 0, 0, 0 };	int ret;	mutex_lock(&cam->s_mutex);	if (cam->state != S_NOTREADY)		cam_warn(cam, "Cam init with device in funky state %d",				cam->state);	ret = __cafe_cam_reset(cam);	if (ret)		goto out;	chip.match_chip = cam->sensor->addr;	ret = __cafe_cam_cmd(cam, VIDIOC_G_CHIP_IDENT, &chip);	if (ret)		goto out;	cam->sensor_type = chip.ident;//	if (cam->sensor->addr != OV7xx0_SID) {	if (cam->sensor_type != V4L2_IDENT_OV7670) {		cam_err(cam, "Unsupported sensor type %d", cam->sensor->addr);		ret = -EINVAL;		goto out;	}/* Get/set parameters? */	ret = 0;	cam->state = S_IDLE;  out:	cafe_ctlr_power_down(cam);	mutex_unlock(&cam->s_mutex);	return ret;}/* * Configure the sensor to match the parameters we have.  Caller should * hold s_mutex */static int cafe_cam_set_flip(struct cafe_camera *cam){	struct v4l2_control ctrl;	memset(&ctrl, 0, sizeof(ctrl));	ctrl.id = V4L2_CID_VFLIP;	ctrl.value = flip;	return __cafe_cam_cmd(cam, VIDIOC_S_CTRL, &ctrl);}static int cafe_cam_configure(struct cafe_camera *cam){	struct v4l2_format fmt;	int ret, zero = 0;	if (cam->state != S_IDLE)		return -EINVAL;	fmt.fmt.pix = cam->pix_format;	ret = __cafe_cam_cmd(cam, VIDIOC_INT_INIT, &zero);	if (ret == 0)		ret = __cafe_cam_cmd(cam, VIDIOC_S_FMT, &fmt);	/*	 * OV7670 does weird things if flip is set *before* format...	 */	ret += cafe_cam_set_flip(cam);	return ret;}/* -------------------------------------------------------------------- *//* * DMA buffer management.  These functions need s_mutex held. *//* FIXME: this is inefficient as hell, since dma_alloc_coherent just * does a get_free_pages() call, and we waste a good chunk of an orderN * allocation.  Should try to allocate the whole set in one chunk. */static int cafe_alloc_dma_bufs(struct cafe_camera *cam, int loadtime){	int i;	cafe_set_config_needed(cam, 1);	if (loadtime)		cam->dma_buf_size = dma_buf_size;	else		cam->dma_buf_size = cam->pix_format.sizeimage;	if (n_dma_bufs > 3)		n_dma_bufs = 3;	cam->nbufs = 0;	for (i = 0; i < n_dma_bufs; i++) {		cam->dma_bufs[i] = dma_alloc_coherent(&cam->pdev->dev,				cam->dma_buf_size, cam->dma_handles + i,				GFP_KERNEL);		if (cam->dma_bufs[i] == NULL) {			cam_warn(cam, "Failed to allocate DMA buffer\n");			break;		}		/* For debug, remove eventually */		memset(cam->dma_bufs[i], 0xcc, cam->dma_buf_size);		(cam->nbufs)++;	}	switch (cam->nbufs) {	case 1:	    dma_free_coherent(&cam->pdev->dev, cam->dma_buf_size,			    cam->dma_bufs[0], cam->dma_handles[0]);	    cam->nbufs = 0;	case 0:	    cam_err(cam, "Insufficient DMA buffers, cannot operate\n");	    return -ENOMEM;	case 2:	    if (n_dma_bufs > 2)		    cam_warn(cam, "Will limp along with only 2 buffers\n");	    break;	}	return 0;}static void cafe_free_dma_bufs(struct cafe_camera *cam){	int i;	for (i = 0; i < cam->nbufs; i++) {		dma_free_coherent(&cam->pdev->dev, cam->dma_buf_size,				cam->dma_bufs[i], cam->dma_handles[i]);		cam->dma_bufs[i] = NULL;	}	cam->nbufs = 0;}/* ----------------------------------------------------------------------- *//* * Here starts the V4L2 interface code. *//* * Read an image from the device. */static ssize_t cafe_deliver_buffer(struct cafe_camera *cam,		char __user *buffer, size_t len, loff_t *pos){	int bufno;	unsigned long flags;	spin_lock_irqsave(&cam->dev_lock, flags);	if (cam->next_buf < 0) {		cam_err(cam, "deliver_buffer: No next buffer\n");		spin_unlock_irqrestore(&cam->dev_lock, flags);		return -EIO;	}	bufno = cam->next_buf;	clear_bit(bufno, &cam->flags);	if (++(cam->next_buf) >= cam->nbufs)		cam->next_buf = 0;	if (! test_bit(cam->next_buf, &cam->flags))		cam->next_buf = -1;	cam->specframes = 0;	spin_unlock_irqrestore(&cam->dev_lock, flags);	if (len > cam->pix_format.sizeimage)		len = cam->pix_format.sizeimage;	if (copy_to_user(buffer, cam->dma_bufs[bufno], len))		return -EFAULT;	(*pos) += len;	return len;}/* * Get everything ready, and start grabbing frames. */static int cafe_read_setup(struct cafe_camera *cam, enum cafe_state state){	int ret;	unsigned long flags;	/*	 * Configuration.  If we still don't have DMA buffers,	 * make one last, desperate attempt.	 */	if (cam->nbufs == 0)		if (cafe_alloc_dma_bufs(cam, 0))			return -ENOMEM;	if (cafe_needs_config(cam)) {		cafe_cam_configure(cam);		ret = cafe_ctlr_configure(cam);		if (ret)			return ret;	}	/*	 * Turn it loose.	 */	spin_lock_irqsave(&cam->dev_lock, flags);	cafe_reset_buffers(cam);	cafe_ctlr_irq_enable(cam);	cam->state = state;	cafe_ctlr_start(cam);	spin_unlock_irqrestore(&cam->dev_lock, flags);	return 0;}static ssize_t cafe_v4l_read(struct file *filp,		char __user *buffer, size_t len, loff_t *pos){	struct cafe_camera *cam = filp->private_data;	int ret = 0;	/*	 * Perhaps we're in speculative read mode and already	 * have data?	 */	mutex_lock(&cam->s_mutex);	if (cam->state == S_SPECREAD) {		if (cam->next_buf >= 0) {			ret = cafe_deliver_buffer(cam, buffer, len, pos);			if (ret != 0)				goto out_unlock;		}	} else if (cam->state == S_FLAKED || cam->state == S_NOTREADY) {		ret = -EIO;		goto out_unlock;	} else if (cam->state != S_IDLE) {		ret = -EBUSY;		goto out_unlock;	}	/*	 * v4l2: multiple processes can open the device, but only	 * one gets to grab data from it.	 */	if (cam->owner && cam->owner != filp) {		ret = -EBUSY;		goto out_unlock;	}	cam->owner = filp;	/*	 * Do setup if need be.	 */	if (cam->state != S_SPECREAD) {		ret = cafe_read_setup(cam, S_SINGLEREAD);		if (ret)			goto out_unlock;	}	/*	 * Wait for something to happen.  This should probably	 * be interruptible (FIXME).	 */	wait_event_timeout(cam->iowait, cam->next_buf >= 0, HZ);	if (cam->next_buf < 0) {		cam_err(cam, "read() operation timed out\n");		cafe_ctlr_stop_dma(cam);		ret = -EIO;		goto out_unlock;	}	/*	 * Give them their data and we should be done.	 */	ret = cafe_deliver_buffer(cam, buffer, len, pos);  out_unlock:	mutex_unlock(&cam->s_mutex);	return ret;}/* * Streaming I/O support. */static int cafe_vidioc_streamon(struct file *filp, void *priv,		enum v4l2_buf_type type){	struct cafe_camera *cam = filp->private_data;	int ret = -EINVAL;	if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE)		goto out;	mutex_lock(&cam->s_mutex);	if (cam->state != S_IDLE || cam->n_sbufs == 0)		goto out_unlock;	cam->sequence = 0;	ret = cafe_read_setup(cam, S_STREAMING);  out_unlock:	mutex_unlock(&cam->s_mutex);  out:	return ret;}

⌨️ 快捷键说明

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