/**
 * 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);
	}
}
Ejemplo n.º 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);
				}
			}
		}
	}
}
Ejemplo n.º 3
0
/**
 * hp3a_histogram_isr - ISR for the histogram done interrupt.
 *
 * No return value.
 **/
static void hp3a_histogram_isr(unsigned long status, isp_vbq_callback_ptr arg1,
	void *arg2)
{
	u32 *hist_buffer;
	u32 i;
	struct hp3a_internal_buffer *ibuffer = NULL;

	if (unlikely((HIST_DONE & status) != HIST_DONE)) {
		return;
	}

	omap_writel(omap_readl(ISPHIST_PCR) & ~(ISPHIST_PCR_EN), ISPHIST_PCR);

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

	if (hp3a_dequeue(&g_tc.hist_hw_queue,  &ibuffer) == 0) {
		/* If there is a buffer available then fill it. */
		hist_buffer = (u32 *)phys_to_virt(page_to_phys(ibuffer->pages[0]));

		omap_writel((omap_readl(ISPHIST_CNT)) | \
			ISPHIST_CNT_CLR_EN, ISPHIST_CNT);
		for (i = g_tc.hist_bin_size; i--;) {
			*hist_buffer = omap_readl(ISPHIST_DATA);
			++hist_buffer;
		}
		omap_writel((omap_readl(ISPHIST_CNT)) & ~ISPHIST_CNT_CLR_EN,
			ISPHIST_CNT);
	} else {
		/* There are no buffers availavle so just clear internal histogram memory. */
		for (i = g_tc.hist_bin_size; i--;) {
			omap_writel(0, ISPHIST_DATA);
		}
	}

	/* Set memory HW memory address and enable. */
	omap_writel(0, ISPHIST_ADDR);

	if (g_tc.hist_hw_enable == 1) {
		/* Enable histogram. */
		omap_writel(omap_readl(ISPHIST_PCR) | (ISPHIST_PCR_EN),
			ISPHIST_PCR);
	}

	g_tc.hist_done = 1;

	/* Release the tasks waiting for stats. */
	wake_up(&g_tc.stats_done);
}
Ejemplo n.º 4
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);
	}
}
Ejemplo n.º 5
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);
}