Exemplo n.º 1
0
/**
 * flush_dcache_ibuffer - Flushes dcache corresponding to a internal buffer.
 * @ibuffer: Pointer to internal buffer to be flushed from cache.
 *
 * No return value.
 **/
void flush_dcache_ibuffer(struct hp3a_internal_buffer  *ibuffer)
{
	int i;
	int nr_pages = NR_PAGES(ibuffer->user_addr, (unsigned long)ibuffer->buffer_size);

	for (i = 0; i < nr_pages; ++i) {
		flush_dcache_page(ibuffer->pages[i]);
	}
}
Exemplo n.º 2
0
/**
 * unmap_buffers_from_kernel - Unmaps memory from isp and kernel address space.
 * @ibuffer: Pointer to internal buffer to be unmapped.
 *
 * No return value.
 **/
void unmap_buffer_from_kernel(struct hp3a_internal_buffer *ibuffer)
{
	if (ibuffer->isp_addr) {
#if defined(CONFIG_VIDEO_OLDOMAP3)
		if (ispmmu_unmap(ibuffer->isp_addr) != 0) {
			printk(KERN_ERR "Error unmapping from ispmmu (0x%x)!",
				(unsigned int)ibuffer->isp_addr);
		}
#else
		ispmmu_vunmap(ibuffer->isp_addr);
#endif
		ibuffer->isp_addr = 0;
	}

	if (ibuffer->pages != NULL && ibuffer->buffer_size > 0) {
		unmap_user_memory(ibuffer->pages, NR_PAGES(ibuffer->user_addr,
				ibuffer->buffer_size));
		kfree(ibuffer->pages);
		ibuffer->pages = NULL;
	}
}
Exemplo n.º 3
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;
}