/**
 * hp3a_enable_histogram - Enables histogram harware.
 *
 * No return value.
 **/
void hp3a_enable_histogram(void)
{
	struct hp3a_internal_buffer *ibuffer;

	if (unlikely(g_tc.hist_hw_configured == 0))
		return;

	if (hp3a_dequeue(&g_tc.hist_stat_queue, &ibuffer) == 0) {
		if (g_tc.hist_hw_enable == 0) {
			/* Write histogram hardware registers. */
			hp3a_write_ispregs(isp_hist_regs);
			omap_writel(IRQ0STATUS_HIST_DONE_IRQ,
				ISP_IRQ0STATUS);
			/* Enable histogram hardware. */
			omap_writel(omap_readl(ISPHIST_PCR) | \
				(ISPHIST_PCR_EN), ISPHIST_PCR);

			g_tc.hist_hw_enable = 1;
			g_tc.hist_done = 0;
		}

		ibuffer->type = HISTOGRAM;
		hp3a_enqueue(&g_tc.hist_hw_queue, &ibuffer);
		hp3a_enqueue(&g_tc.ready_stats_queue, &ibuffer);
	} else if (g_tc.hist_hw_enable == 1) {
		g_tc.hist_hw_enable = 0;
		omap_writel(omap_readl(ISPHIST_PCR) & \
			~(ISPHIST_PCR_EN), ISPHIST_PCR);
	}
}
示例#2
0
/**
 * hp3a_update_framework- execute tasks between frames.
 *
 * No return value.
 **/
void hp3a_update_stats_pipe_done(void)
{
	struct hp3a_internal_buffer *ibuffer;

	hp3a_disable_raw();

	if (g_tc.v4l2_streaming == 0)
		return;

	/* RAW stat buffer processing. */
	if (g_tc.raw_hw_configured == 1) {
		if ((++g_tc.raw_cap_sched_count) == g_tc.raw_frequency) {
			if (omap_readl(ISPCCDC_PCR) & ISPCCDC_PCR_BUSY) {
				--g_tc.raw_cap_sched_count;
				return;
			}
			g_tc.raw_cap_sched_count = 0;
			ibuffer = NULL;
			if (hp3a_dequeue(&g_tc.raw_frame_queue, &ibuffer)
				== 0) {
				if (ibuffer->buffer_size >=
					g_tc.req_raw_buffer_size) {
					hp3a_enable_raw(ibuffer->isp_addr);
					ibuffer->type = BAYER;
					hp3a_enqueue(&g_tc.ready_stats_queue,
					&ibuffer);
				}
			}
		}
	}
}
示例#3
0
/**
 * hp3a_task - Tasks body, executes once per frame.
 * @work: Pointer to the  hp3a work structure.
 *
 * No return value.
 **/
static void hp3a_task(struct work_struct *work)
{
	/* Place holder for deferred tasks. */
	struct hp3a_sensor_param_internal sensor_param;
	struct hp3a_sensor_param_internal empty_param = {
		.exposure = 0,
		.gain = 0,
		.fps = 0};
	struct cam_sensor_settings sensor_settings = {
		.flags = 0,
		.exposure = 0,
		.gain = 0,
		.regs = 0,
		.fps = 0,
		.reg_data = 0};
	unsigned long irqflags = 0;

	/**
	 * Setup exposure and gain for next frame.
	 */
	if (hp3a_dequeue(&g_tc.sensor_write_queue,
			&sensor_param) == 0) {
		sensor_settings.exposure = sensor_param.exposure;
		sensor_settings.gain = sensor_param.gain;
		sensor_settings.fps = sensor_param.fps;

		if (sensor_param.fps)
			sensor_settings.flags |= OMAP34XXCAM_SET_FPS;

		if (sensor_param.exposure)
			sensor_settings.flags |= OMAP34XXCAM_SET_EXPOSURE;

		if (sensor_param.gain)
			sensor_settings.flags |= OMAP34XXCAM_SET_GAIN;

		if (sensor_settings.flags == 0)
			return;

		/**
		 * Write and read sensor settings.
		 */
		omap34xxcam_sensor_settings(sensor_param.v4l2_dev,
					&sensor_settings);

		spin_lock_irqsave(&g_tc.stats_lock, irqflags);
		/* Initialize memory. */
		memset(&sensor_param, 0, sizeof(sensor_param));

		if (g_tc.sensor_current.fps != sensor_settings.fps) {
			empty_param.frame_id = g_tc.frame_count + 1;
			empty_param.gain = 0;
			empty_param.exposure = -1;
			hp3a_enqueue( \
				&g_tc.sensor_read_queue,
				&empty_param);
			sensor_param.frame_id = \
				(g_tc.frame_count + 2);
			if (g_tc.sensor_current.exposure != \
				sensor_settings.exposure) {
				sensor_param.exposure = \
					sensor_settings.exposure;
				g_tc.sensor_current.exposure = \
					sensor_settings.exposure;
			}
			if (g_tc.sensor_current.gain != sensor_settings.gain) {
				sensor_param.gain = sensor_settings.gain;
				g_tc.sensor_current.gain = \
					sensor_settings.gain;
			}
			sensor_param.fps = sensor_settings.fps;
			/* Queue new value for stats collecton. */
			hp3a_enqueue( \
				&g_tc.sensor_read_queue,
				&sensor_param);
			g_tc.sensor_current.fps = sensor_settings.fps;
		} else {
			if (g_tc.sensor_current.gain != sensor_settings.gain) {
				if (g_tc.gain_sync > 1) {
					empty_param.frame_id = \
						g_tc.frame_count + 1;
					empty_param.gain = -1;
					hp3a_enqueue( \
						&g_tc.sensor_read_queue,
						&empty_param);
				}
				sensor_param.frame_id = \
					(g_tc.frame_count + g_tc.gain_sync);
				sensor_param.gain = sensor_settings.gain;
				/* Queue new value for stats collecton. */
				hp3a_enqueue( \
					&g_tc.sensor_read_queue,
					&sensor_param);
				/* Save new programmed in gain value. */
				g_tc.sensor_current.gain = sensor_settings.gain;
			}

			if (g_tc.sensor_current.exposure != \
				sensor_settings.exposure) {
				if (g_tc.exposure_sync > 1) {
					empty_param.frame_id = \
						g_tc.frame_count + 1;
					empty_param.gain = 0;
					empty_param.exposure = -1;
					hp3a_enqueue( \
						&g_tc.sensor_read_queue,
						&empty_param);
				}
				sensor_param.frame_id = \
					(g_tc.frame_count + g_tc.exposure_sync);
				sensor_param.exposure = \
					sensor_settings.exposure;
				sensor_param.gain = 0;
				/* Queue new value for stats collecton. */
				hp3a_enqueue( \
					&g_tc.sensor_read_queue,
					&sensor_param);
				/* Save new programmed in exposure value. */
				g_tc.sensor_current.exposure = \
					sensor_settings.exposure;
			}
		}
		spin_unlock_irqrestore(&g_tc.stats_lock, irqflags);
	}
}
示例#4
0
/**
 * hp3a_update_framework- execute tasks between frames.
 *
 * No return value.
 **/
void hp3a_update_stats_readout_done(void)
{
	int i;
	bool allow_exp_update = true;
	bool allow_gain_update = true;
	struct hp3a_internal_buffer *ibuffer;
	struct hp3a_sensor_param_internal sensor_param;

	if (unlikely(g_tc.v4l2_streaming == 0)) {
		hp3a_disable_histogram();
		hp3a_disable_af();
		return;
	}

	/* Reuse stats buffers. */
	if (g_tc.histogram_buffer != NULL) {
		g_tc.hist_done = 0;
		hp3a_enqueue(&g_tc.hist_stat_queue,
			 &g_tc.histogram_buffer);
		g_tc.histogram_buffer = NULL;
	}

	if (g_tc.af_buffer  != NULL) {
		hp3a_enqueue(&g_tc.af_stat_queue,
			&g_tc.af_buffer);
		g_tc.af_buffer = NULL;
	}

	if (g_tc.raw_buffer != NULL) {
		hp3a_enqueue(&g_tc.raw_frame_queue,
				&g_tc.raw_buffer);
		g_tc.raw_buffer = NULL;
	}

	/* Process ready stats. */
	for (i = MAX_STAT_BUFFERS_PER_FRAME; i--;) {
		ibuffer = NULL;
		if (hp3a_dequeue(&g_tc.ready_stats_queue, &ibuffer) == 0) {
			if (ibuffer->type == HISTOGRAM &&
					g_tc.histogram_buffer == NULL)
				g_tc.histogram_buffer = ibuffer;
			else if (ibuffer->type == PAXEL &&
						g_tc.af_buffer == NULL)
				g_tc.af_buffer = ibuffer;
			else if (ibuffer->type == BAYER &&
						g_tc.raw_buffer == NULL)
				g_tc.raw_buffer = ibuffer;
			else {
				printk(KERN_ERR "hp3a: Error unknown "
				"buffer type(%d)\n", ibuffer->type);
			}
		} else {
			break;
		}
	}

	for (i = QUEUE_COUNT(g_tc.sensor_read_queue); i--;) {
		if (hp3a_dequeue(&g_tc.sensor_read_queue, &sensor_param) == 0) {
			if (sensor_param.frame_id == g_tc.frame_count) {
				if (sensor_param.exposure == (u32)-1) {
					g_tc.sensor_stats.exposure = 0;
					allow_exp_update = false;
				} else if (sensor_param.exposure && allow_exp_update) {
					g_tc.sensor_stats.exposure = sensor_param.exposure;
				}
				if (sensor_param.gain == (u16)-1) {
					g_tc.sensor_stats.gain = 0;
					allow_gain_update = false;
				} else if (sensor_param.gain && allow_gain_update) {
					g_tc.sensor_stats.gain = sensor_param.gain;
				}
				if (sensor_param.fps) {
					g_tc.sensor_stats.fps = \
						sensor_param.fps;
				}
			} else if (sensor_param.frame_id > g_tc.frame_count) {
				hp3a_enqueue(&g_tc.sensor_read_queue,
								&sensor_param);
			}
		} else {
			break;
		}
	}

	/* Histogram buffer processing and HW configuration. */
	hp3a_enable_histogram();
	/* AF stat buffer processing and HW configuration. */
	hp3a_enable_af();

	/* Notify threads waiting for stats. */
	complete(&g_tc.frame_done);
}
示例#5
0
/**
 * hp3a_collect_statsistics - Collect 3A statistics.
 * @work: Pointer to the  hp3a statistics structure.
 *
 * No return value.
 **/
int hp3a_collect_statistics(struct hp3a_statistics *stat)
{
	unsigned long irqflags = 0;

	if (unlikely(g_tc.v4l2_streaming == 0))
		return -1;

	/* Initialize buffer indexes. */
	stat->hist_stat_index = -1;
	stat->af_stat_index = -1;
	stat->raw_frame_index = -1;
	stat->exposure = 0;
	stat->gain = 0;
	stat->fps = 0;

	if (wait_for_completion_timeout(
		&g_tc.frame_done, msecs_to_jiffies(4)) != 0 &&
		g_tc.v4l2_streaming == 1) {
		g_tc.frame_done.done = 0;

		/* Wait for all stats tasks to be done. */
		if (g_tc.hist_done == 0) {
			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);

		/* Frame meta data. */
		stat->frame_id = g_tc.frame_count;
		stat->exposure = g_tc.sensor_stats.exposure;
		stat->gain = g_tc.sensor_stats.gain;
		stat->fps = g_tc.sensor_stats.fps;

		/* Raw bayer frame. */
		if (g_tc.raw_buffer != NULL) {
			stat->raw_frame_index = g_tc.raw_buffer->index;
			stat->raw_width = g_tc.raw_width;
			stat->raw_height = g_tc.raw_height;
			g_tc.raw_buffer = NULL;
		}

		/* AF Paxel. */
		if (g_tc.af_buffer != NULL) {
			stat->af_stat_index = g_tc.af_buffer->index;
			g_tc.af_buffer = NULL;
		}

		/* Histogram. */
		if (g_tc.histogram_buffer != NULL) {
			if (g_tc.hist_done == 1) {
				stat->hist_stat_index = \
					g_tc.histogram_buffer->index;
			} else {
				hp3a_enqueue(&g_tc.hist_stat_queue,
					&g_tc.histogram_buffer);
			}
			g_tc.histogram_buffer = NULL;
		}

		g_tc.hist_done = 0;
		spin_unlock_irqrestore(&g_tc.stats_lock, irqflags);
	} else {
		stat->frame_id = g_tc.frame_count;
	}

	return 0;
}
示例#6
0
/**
 * hp3a_set_sensor_param - Set sensor specific params.
 * @param: Pointer the structure containing sensor parameters.
 * @fh: Pointer to a hp3a_fh stucture.
 *
 * Return 0 on success,  less than 0 otherwise.
 **/
int hp3a_set_sensor_param(struct hp3a_sensor_param *param, struct hp3a_fh *fh)
{
	int ret = -1;
	struct hp3a_sensor_param_internal sensor_param = {
		.exposure = 0,
		.gain = 0,
		.fps = 0};
	unsigned long irqflags = 0;

	if (likely(fh->v4l2_dev > -1)) {
		if (likely(g_tc.v4l2_streaming == 1)) {
			sensor_param.v4l2_dev = fh->v4l2_dev;
			ret = 0;

			spin_lock_irqsave(&g_tc.stats_lock, irqflags);
			if (!(g_tc.sensor_stats.exposure &&
					g_tc.sensor_stats.gain) &&
					!QUEUE_COUNT(g_tc.sensor_write_queue)) {
				memset(&g_tc.sensor_current, 0, \
					sizeof(g_tc.sensor_current));
				memset(&g_tc.sensor_requested, 0, \
					sizeof(g_tc.sensor_requested));
			}
			if (param->fps &&
					g_tc.sensor_requested.fps != \
					param->fps) {
				sensor_param.fps = param->fps;
				sensor_param.exposure = param->exposure;
				sensor_param.gain = param->gain;
				ret = hp3a_enqueue( \
						&g_tc.sensor_write_queue,
						&sensor_param);
				sensor_param.fps = 0;
				sensor_param.exposure = 0;
				sensor_param.gain = 0;
				if (!ret) {
					g_tc.sensor_requested.fps = \
						param->fps;
					g_tc.sensor_requested.exposure =
							param->exposure;
					g_tc.sensor_requested.gain = \
						param->gain;
				}
			}
			if (param->exposure &&
				(g_tc.sensor_requested.exposure != \
				param->exposure)) {
				sensor_param.exposure = param->exposure;
				ret = hp3a_enqueue( \
					&g_tc.sensor_write_queue,
					&sensor_param);
				sensor_param.exposure = 0;
				if (!ret) {
					g_tc.sensor_requested.exposure = \
						param->exposure;
				}
			}
			if (param->gain &&
				(g_tc.sensor_requested.gain != \
					param->gain)) {
				sensor_param.gain = param->gain;
				ret = hp3a_enqueue( \
						&g_tc.sensor_write_queue,
						&sensor_param);
				if (!ret) {
					g_tc.sensor_requested.gain = \
						param->gain;
				}
			}
			spin_unlock_irqrestore(&g_tc.stats_lock, irqflags);
		} else {
			struct cam_sensor_settings sensor_settings = {
			.flags = 0,
			.exposure = 0,
			.gain = 0,
			.fps = 0,
			.regs = 0,
			.reg_data = 0};

			sensor_settings.exposure = param->exposure;
			sensor_settings.gain = param->gain;
			sensor_settings.fps = param->fps;
			sensor_settings.flags = (OMAP34XXCAM_SET_GAIN | \
						OMAP34XXCAM_SET_EXPOSURE);

			/**
			* Write and read sensor settings.
			*/
			ret = omap34xxcam_sensor_settings(fh->v4l2_dev,
							&sensor_settings);
		}
	} else {
		dev_err(fh->device->dev,
			"hp3a: Invalid sensor id(%d)\n",
			fh->v4l2_dev);
	}

	return ret;
}

/**
 * hp3a_set_hardpipe_param - Set hard pipe specific params to be programmed.
 * @param: Pointer the structure containing hard pipe parameters.
 * @fh: Pointer to a hp3a_fh stucture.
 *
 * Return 0 on success,  less than 0 otherwise.
 **/
int hp3a_set_hardpipe_param(struct hp3a_hardpipe_param *param,
				struct hp3a_fh *fh)
{
	unsigned long irqflags = 0;

	spin_lock_irqsave(&g_tc.hardpipe_lock, irqflags);
	memcpy(&g_tc.hpipe_param, param, sizeof(struct hp3a_hardpipe_param));
	g_tc.update_hardpipe = 1;
	spin_unlock_irqrestore(&g_tc.hardpipe_lock, irqflags);

	if (g_tc.v4l2_streaming == 0)
		hp3a_update_hardpipe();

	return 0;
}