Esempio n. 1
0
int mt9v111_set_autoexposure(struct usb_sn9c20x *dev)
{
	__u16 buf[1];
	int ret = 0;

	/* Switch to IFP-register address space: */
	ret = mt9v111_select_address_space(dev, MT9V111_ADDRESSSPACE_IFP);
	if (ret < 0)
		return -11;	/* -EAGAIN */
	/* Read current value of IFP-register 0x06: */
	ret = sn9c20x_read_i2c_data16(dev, 1, MT9V111_IFPREG_OPMODECTL, buf);
	if (ret < 0) {
		UDIA_ERROR("Error: setting of auto exposure failed: "
			"error while reading from IFP-register 0x06\n");
		return ret;
	}

	/* Set new value for register 0x06: */

	if (dev->vsettings.auto_exposure) {
		buf[0] |= MT9V111_IFP_OPMODE_AUTOEXPOSURE;
	} else {
		buf[0] &= ~MT9V111_IFP_OPMODE_AUTOEXPOSURE;
	}

	/* Write new value to IFP-register 0x06: */
	ret = sn9c20x_write_i2c_data16(dev, 1, MT9V111_IFPREG_OPMODECTL, buf);
	if (ret < 0) {
		UDIA_ERROR("Error: setting of auto exposure failed: "
			"error while writing to IFP-register 0x06\n");
		return ret;
	}
	return 0;
}
/**
 * @brief Dequeue a video buffer.
 *
 * @param queue
 * @param v4l2_buf
 * @param nonblocking
 *
 * @return 0 or negative error code
 *
 * If nonblocking is false, block until a buffer is
 * available.
 */
int microdia_dequeue_buffer(struct microdia_video_queue *queue,
	struct v4l2_buffer *v4l2_buf, int nonblocking)
{
	struct microdia_buffer *buf;
	int ret = 0;

	if (v4l2_buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
	    v4l2_buf->memory != V4L2_MEMORY_MMAP) {
		UDIA_ERROR("[E] Invalid buffer type (%u) "
			"and/or memory (%u).\n", v4l2_buf->type,
			v4l2_buf->memory);
		return -EINVAL;
	}

	mutex_lock(&queue->mutex);
	if (list_empty(&queue->mainqueue)) {
		UDIA_ERROR("[E] Empty buffer queue.\n");
		ret = -EINVAL;
		goto done;
	}

	buf = list_first_entry(&queue->mainqueue, struct microdia_buffer,
			       stream);

	ret = microdia_queue_waiton(buf, nonblocking);
	if (ret < 0)
		goto done;

	UDIA_DEBUG("Dequeuing buffer %u (%u, %u bytes).\n",
		buf->buf.index, buf->state, buf->buf.bytesused);

	switch (buf->state) {
	case MICRODIA_BUF_STATE_ERROR:
		UDIA_WARNING("[W] Corrupted data (transmission error).\n");
		ret = -EIO;
	case MICRODIA_BUF_STATE_DONE:
		buf->state = MICRODIA_BUF_STATE_IDLE;
		break;

	case MICRODIA_BUF_STATE_IDLE:
	case MICRODIA_BUF_STATE_QUEUED:
	case MICRODIA_BUF_STATE_ACTIVE:
	default:
		UDIA_ERROR("[E] Invalid buffer state %u "
			"(driver bug?).\n", buf->state);
		ret = -EINVAL;
		goto done;
	}

	list_del(&buf->stream);
	__microdia_query_buffer(buf, v4l2_buf);

done:
	mutex_unlock(&queue->mutex);
	return ret;
}
Esempio n. 3
0
int mt9v111_select_address_space(struct usb_sn9c20x *dev, __u8 address_space)
{
	__u8 buf[2];
	int retI2C;
	int k;

	/* check if selection is valid: */
	if ((address_space != MT9V111_ADDRESSSPACE_IFP) &&
		(address_space != MT9V111_ADDRESSSPACE_SENSOR)) {
			UDIA_WARNING("invalid register address space "
				"selection for sensor MT9V111/MI0360SOC !\n");
			return -1;
	}
	/* read address space slection register: */
	k = 0;
	retI2C = -1;
	while ((k < 3) && (retI2C != 0)) {
		retI2C = sn9c20x_read_i2c_data(dev, 2, 0x01, buf);
		if (retI2C != 0 && k < 2)
			udelay(1000);
		k++;
	}
	if (retI2C != 0) {
		UDIA_ERROR("MT9V111/MI0360SOC (I2C-slave 0x5c): "
			"read of reg0x01 (address space selection) failed !\n");
		return -1;
	}
	/* check current address space: */
	if ((buf[0] != 0x00) || (buf[1] != address_space)) {
		k = 0;
		retI2C = -1;
		while ((k < 3) && (retI2C != 0)) {
			/* switch address space: */
			buf[0] = 0x00; buf[1] = address_space;
			retI2C = sn9c20x_write_i2c_data(dev, 2, 0x01, buf);
			if (retI2C != 0 && k < 2)
				udelay(1000);
			k++;
		}
		if (retI2C != 0) {
			if (address_space == MT9V111_ADDRESSSPACE_IFP)
				UDIA_ERROR("MT9V111/MI0360SOC "
					"(I2C-slave 0x5c): switch to IFP "
					"address space failed !\n");
			else
				UDIA_ERROR("MT9V111/MI0360SOC "
					"(I2C-slave 0x5c): switch to sensor "
					"core address space failed !\n");
			return -1;
		}
	}
	return 0;
}
Esempio n. 4
0
int mt9m111_set_autoexposure(struct usb_sn9c20x *dev)
{
	int ret;
	__u16 data, page;

	ret = 0;
	page = 1;
	ret |= sn9c20x_write_i2c_data16(dev, 1, 0xF0, &page);
	ret |= sn9c20x_read_i2c_data16(dev, 1, 0x06, &data);


	if (dev->vsettings.auto_exposure == 1) {
		data |= 0x7000;
	} else if (dev->vsettings.auto_exposure == 0) {
		data &= ~0x7000;
	} else
		return -EINVAL;

	ret |= sn9c20x_write_i2c_data16(dev, 1, 0x06, &data);
	page = 0;
	ret |= sn9c20x_write_i2c_data16(dev, 1, 0xF0, &page);

	if (ret < 0) {
		UDIA_ERROR("Error: setting of auto exposure failed: "
			"error while writing to IFP-register 0x06\n");
		return ret;
	}
	return 0;
}
/**
 * @brief Queue a video buffer.
 *
 * @param queue
 * @param v4l2_buf
 *
 * @return 0 or negative error code
 *
 * Attempting to queue a buffer that has already been
 * queued will return -EINVAL.
 */
int microdia_queue_buffer(struct microdia_video_queue *queue,
	struct v4l2_buffer *v4l2_buf)
{
	struct microdia_buffer *buf;
	unsigned long flags;
	int ret = 0;

	UDIA_DEBUG("Queuing buffer %u.\n", v4l2_buf->index);

	if (v4l2_buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
	    v4l2_buf->memory != V4L2_MEMORY_MMAP) {
		UDIA_ERROR("[E] Invalid buffer type (%u) "
			"and/or memory (%u).\n", v4l2_buf->type,
			v4l2_buf->memory);
		return -EINVAL;
	}

	mutex_lock(&queue->mutex);
	if (v4l2_buf->index >= queue->count)  {
		UDIA_ERROR("[E] Out of range index.\n");
		ret = -EINVAL;
		goto done;
	}

	buf = &queue->buffer[v4l2_buf->index];
	if (buf->state != MICRODIA_BUF_STATE_IDLE) {
		UDIA_ERROR("[E] Invalid buffer state "
			"(%u).\n", buf->state);
		ret = -EINVAL;
		goto done;
	}

	buf->state = MICRODIA_BUF_STATE_QUEUED;
	buf->buf.bytesused = 0;
	list_add_tail(&buf->stream, &queue->mainqueue);
	spin_lock_irqsave(&queue->irqlock, flags);
	list_add_tail(&buf->queue, &queue->irqqueue);
	spin_unlock_irqrestore(&queue->irqlock, flags);

done:
	mutex_unlock(&queue->mutex);
	return ret;
}