示例#1
0
/**
 * hp3a_framework_stop - Stops hp3a framework.
 *
 * No return value.
 **/
void hp3a_framework_stop(struct hp3a_fh *fh)
{
	int i;
	struct hp3a_internal_buffer *temp;
	unsigned long irqflags = 0;

	hp3a_stream_off();
	wait_event_interruptible_timeout(g_tc.stats_done,
		(g_tc.hist_done == 1), msecs_to_jiffies(8));

	spin_lock_irqsave(&g_tc.stats_lock, irqflags);
	g_tc.hist_hw_configured = 0;
	g_tc.af_hw_configured = 0;
	g_tc.raw_hw_configured = 0;
	g_tc.hist_hw_enable = 0;
	g_tc.hist_done = 0;
	g_tc.af_hw_enable = 0;

	/* Need to flush queue. */
	hp3a_flush_queue(&g_tc.sensor_write_queue);
	hp3a_flush_queue(&g_tc.sensor_read_queue);
	hp3a_flush_queue(&g_tc.raw_frame_queue);
	hp3a_flush_queue(&g_tc.af_stat_queue);
	hp3a_flush_queue(&g_tc.hist_stat_queue);

	temp = fh->buffers;
	fh->buffers = NULL;

	/* Initialize configs to default. */
	g_tc.raw_frequency = MIN_RAW_CAPTURE_INTERVAL;
	g_tc.hist_hw_configured = 0;
	g_tc.af_hw_configured = 0;
	g_tc.raw_hw_configured = 0;
	g_tc.histogram_buffer = NULL;
	g_tc.af_buffer  = NULL;
	g_tc.raw_buffer  = NULL;
	spin_unlock_irqrestore(&g_tc.stats_lock, irqflags);

	if (temp) {
	/* Internal buffer clean up. */
	for (i = 0; i < fh->buffer_count; ++i)
		unmap_buffer_from_kernel(&(temp[i]));
	kfree(temp);
	}
	fh->buffer_count = 0;

	/* Release any task waiting for stats. */
	complete(&g_tc.frame_done);
	g_tc.hist_done = 1;
	wake_up_all(&g_tc.stats_done);
}
示例#2
0
 /**
 * hp3a_unlocked_ioctl - I/O control function for hp3a module
 * @inode: Inode structure associated with the Resizer Wrapper.
 * @file: File structure associated with the hp3a driver.
 * @cmd: Type of command to execute.
 * @arg: Argument to send to requested command.
 *
 * Returns 0 if successful, -1 if bad command passed or access is denied,
 * -EFAULT if copy_from_user() or copy_to_user()  fails,
 * -EINVAL if parameter validation fails or parameter structure is not present.
 **/
long hp3a_unlocked_ioctl(struct file *file, unsigned int cmd,
	unsigned long arg)
{
	int ret = -1;
	struct hp3a_fh *fh = file->private_data;
	struct hp3a_dev *device = fh->device;

	if (unlikely(_IOC_TYPE(cmd) != OMAP3_HP3A_MAGIC)) {
		dev_err(device->dev, "Bad command value (%d)\n", cmd);
		return  -ENOTTY;
	}

	switch (cmd) {
	/*
	 * Gets all statistics.
	 */
	case HP3A_G_STATISTICS: {
		struct hp3a_statistics statistics;

		ret = hp3a_collect_statistics(&statistics);
		if (SUCCEEDED(ret)) {
			if (copy_to_user((struct hp3a_statistics *)arg,
				&statistics,
				sizeof(struct hp3a_statistics)) != 0)
				ret = -EFAULT;
		}
		break;
	}
	/*
	 * Set sensor parameters.
	 */
	case HP3A_S_SENSOR_PARAM: {
		struct hp3a_sensor_param sensor_param;

		if (copy_from_user(&sensor_param,
				(struct hp3a_sensor_param *)arg,
				sizeof(struct hp3a_sensor_param)) == 0) {
			ret = hp3a_set_sensor_param(&sensor_param, fh);
		} else {
			ret = -EFAULT;
		}

		break;
	}
	/*
	 * Set ISP/Hardpipe parameters
	 */
	case HP3A_S_HARDPIPE_PARAM: {
		struct hp3a_hardpipe_param hpipe_param;

		if (copy_from_user(&hpipe_param,
				(struct hp3a_hardpipe_param *)arg,
				sizeof(struct hp3a_hardpipe_param)) == 0) {
			ret = hp3a_set_hardpipe_param(&hpipe_param, fh);
		} else {
			ret = -EFAULT;
		}

		break;
	}
	/*
	 * Queue histogram stat buffer.
	 */
	case HP3A_QBUF_HISTQ: {
		struct hp3a_internal_buffer *ibuffer;
		int index = (int)arg;

		if (index < fh->buffer_count && index > -1) {
			ibuffer = &(fh->buffers[index]);
			ret = hp3a_enqueue_irqsave(&g_tc.hist_stat_queue,
				&ibuffer);
		}

		break;
	}
	/*
	 * Queue AF stat buffer.
	 */
	case HP3A_QBUF_AFQ: {
		struct hp3a_internal_buffer *ibuffer;
		int index = (int)arg;

		if (index < fh->buffer_count && index > -1) {
			ibuffer = &(fh->buffers[index]);
			if (ibuffer->isp_addr == 0) {
				ibuffer->isp_addr =
					ispmmu_map_pages(ibuffer->pages,
					NR_PAGES((unsigned long)ibuffer->user_addr,
					ibuffer->buffer_size));
				if (ibuffer->isp_addr == 0) {
					dev_err(device->dev , \
						"isp mmu fail to map memory\n");
					return -EFAULT;
				}
			}
			flush_dcache_ibuffer(ibuffer);
			ret = hp3a_enqueue_irqsave(&g_tc.af_stat_queue,
				&ibuffer);
		}

		break;
	}
	/*
	 * Queue RAW frame buffer.
	 */
	case HP3A_QBUF_RAWQ: {
		struct hp3a_internal_buffer *ibuffer ;
		int index = (int)arg;

		if (index < fh->buffer_count && index > -1) {
			ibuffer = &(fh->buffers[index]);
			if (ibuffer->isp_addr == 0) {
				ibuffer->isp_addr =
					ispmmu_map_pages(ibuffer->pages,
					NR_PAGES((unsigned long)ibuffer->user_addr,
					ibuffer->buffer_size));
				if (ibuffer->isp_addr == 0) {
					dev_err(device->dev , \
						"isp mmu fail to map memory\n");
					return -EFAULT;
				}
			}
			ret = hp3a_enqueue_irqsave(&g_tc.raw_frame_queue,
				&ibuffer);
		}

		break;
	}
	/*
	 * Request for array of buffer placeholders.
	 */
	case HP3A_REQBUF: {
		struct hp3a_request_bufffers req_buf;
		int i;

		if (copy_from_user(&req_buf,
				(struct hp3a_request_bufffers *)arg,
				sizeof(struct hp3a_request_bufffers)) == 0) {
			ret = -1;
			if (req_buf.count > 0) {
				fh->buffers = kzalloc(req_buf.count * \
					sizeof(struct hp3a_internal_buffer),
					GFP_KERNEL);
				if (fh->buffers) {
					fh->buffer_count = req_buf.count;
					for (i = 0; i < fh->buffer_count; ++i)
						fh->buffers[i].index = i;
					ret = 0;
				}
			}
		} else {
			ret = -EFAULT;
		}

		break;
	}
	/*
	 * Install buffers into internal list and map to kernel space.
	 */
	case HP3A_INSTALL_BUF: {
		struct hp3a_buffer buffer;

		if (copy_from_user(&buffer,
				(struct hp3a_buffer *)arg,
				sizeof(struct hp3a_buffer)) == 0) {
			ret = -1;
			if (buffer.index >= 0 && buffer.index <
				fh->buffer_count) {
				if (fh->buffers[buffer.index].buffer_size
					==	0) {
					ret = map_user_to_kernel(&buffer,
						&(fh->buffers[buffer.index]));
				}
			}
		} else {
			ret = -EFAULT;
		}

		break;
	}
	/*
	 * Remove buffers from internal list and unmap from kernel space.
	 */
	case HP3A_UNINSTALL_BUF: {
		struct hp3a_buffer buffer;

		if (copy_from_user(&buffer,
				(struct hp3a_buffer *)arg,
				sizeof(struct hp3a_buffer)) == 0) {
			ret = -1;
			if (buffer.index >= 0 && buffer.index <
				fh->buffer_count) {
				if (fh->buffers[buffer.index].buffer_size &&
					fh->buffers[buffer.index].pages) {
					unmap_buffer_from_kernel(
						&(fh->buffers[buffer.index]));
					ret = 0;
				}
			}
		} else {
			ret = -EFAULT;
		}

		break;
	}
	/*
	 * Configure Histogram hardware.
	 */
	case HP3A_CONFIG_HIST: {
		struct hp3a_histogram_config config;

		if (copy_from_user(&config,
				(struct hp3a_histogram_config *)arg,
				sizeof(struct hp3a_histogram_config)) == 0) {
			ret = hp3a_config_histogram(&config, fh);
		} else {
			ret = -EFAULT;
		}

		break;
	}
	/*
	 * Configure Histogram hardware.
	 */
   case HP3A_CONFIG_AF: {
		struct hp3a_af_config config;

		if (copy_from_user(&config,
				(struct hp3a_af_config *)arg,
				sizeof(struct hp3a_af_config)) == 0) {
			ret = hp3a_config_af(&config, fh);
		} else {
			ret = -EFAULT;
		}

      break;
   }
	/*
	 * Configure raw hardware.
	 */
	case HP3A_CONFIG_RAW: {
		struct hp3a_raw_config config;

		if (copy_from_user(&config,
				(struct hp3a_raw_config *)arg,
				sizeof(struct hp3a_raw_config)) == 0) {

			ret = hp3a_configure_raw(&config);
			if (SUCCEEDED(ret)) {
				if (copy_to_user((struct hp3a_raw_config *)arg,
					&config,
					sizeof(struct hp3a_raw_config)) != 0)
					ret = -EFAULT;
			}
		} else {
			ret = -EFAULT;
		}

		break;
	}
	/*
	 * Flush histogram queue.
	 */
	case HP3A_FLUSH_HISTQ: {
		hp3a_flush_queue_irqsave(&g_tc.hist_stat_queue);
		ret = 0;
		break;
	}
	/*
	 * Flush AF queue.
	 */
	case HP3A_FLUSH_AFQ:	{
		hp3a_flush_queue_irqsave(&g_tc.af_stat_queue);
		ret = 0;
		break;
	}
	/*
	 * Flush RAW queue.
	 */
	case HP3A_FLUSH_RAWQ: {
		hp3a_flush_queue_irqsave(&g_tc.raw_frame_queue);
		ret = 0;
		break;
	}
	/*
	 * Set V4L2 device specific index.
	 */
	case HP3A_S_V4L2_DEV_INDEX: {
		fh->v4l2_dev = (int)arg;
		g_tc.default_v4l2_dev = fh->v4l2_dev;
		ret = 0;
		break;
	}
	/*
	 * Read ISP registers.
	 */
	case HP3A_READ_ISP_REGS: {
		ret = hp3a_read_ispregs_to_user((struct hp3a_reg_page *)arg);
		break;
	}
	case HP3A_READ_ISP_REG: {
		ret = hp3a_read_ispreg_to_user((struct hp3a_reg *)arg);
		break;
	}
	default:
		break;
	}

	return (long)ret;
}