Beispiel #1
0
/* Get buffer to userspace. */
static struct ispstat_buffer *ispstat_buf_get(struct ispstat *stat,
					      struct ispstat_data *data)
{
	int rval = 0;
	unsigned long flags;
	struct ispstat_buffer *buf;

	spin_lock_irqsave(&stat->isp->stat_lock, flags);

	while (1) {
		buf = ispstat_buf_find_oldest(stat);
		if (!buf) {
			spin_unlock_irqrestore(&stat->isp->stat_lock, flags);
			dev_dbg(stat->isp->dev, "%s: cannot find a buffer.\n",
				stat->subdev.name);
			return ERR_PTR(-EBUSY);
		}
		if (ispstat_buf_check_magic(stat, buf)) {
			dev_dbg(stat->isp->dev, "%s: current buffer has "
				"corrupted data\n.", stat->subdev.name);
			/* Mark empty because it doesn't have valid data. */
			buf->empty = 1;
		} else {
			/* Buffer isn't corrupted. */
			break;
		}
	}

	stat->locked_buf = buf;

	spin_unlock_irqrestore(&stat->isp->stat_lock, flags);

	if (buf->buf_size > data->buf_size) {
		dev_warn(stat->isp->dev, "%s: userspace's buffer size is "
					 "not enough.\n", stat->subdev.name);
		ispstat_buf_release(stat);
		return ERR_PTR(-EINVAL);
	}

	ispstat_buf_sync_for_cpu(stat, buf);

	rval = copy_to_user(data->buf,
			    buf->virt_addr,
			    buf->buf_size);

	if (rval) {
		dev_info(stat->isp->dev,
			 "%s: failed copying %d bytes of stat data\n",
			 stat->subdev.name, rval);
		buf = ERR_PTR(-EFAULT);
		ispstat_buf_release(stat);
	}

	return buf;
}
Beispiel #2
0
/*
 * ispstat_request_statistics - Request statistics.
 * @data: Pointer to return statistics data.
 *
 * Returns 0 if successful.
 */
int ispstat_request_statistics(struct ispstat *stat,
			       struct ispstat_data *data)
{
	struct ispstat_buffer *buf;

	if (stat->state != ISPSTAT_ENABLED) {
		dev_dbg(stat->isp->dev, "%s: engine not enabled.\n",
			stat->subdev.name);
		return -EINVAL;
	}

	buf = ispstat_buf_get(stat, data);
	if (IS_ERR(buf))
		return PTR_ERR(buf);

	data->ts = buf->ts;
	data->config_counter = buf->config_counter;
	data->frame_number = buf->frame_number;
	data->buf_size = buf->buf_size;

	/*
	 * Deprecated. Number of new buffers is always equal to number of
	 * queued events without error flag. By setting it to 0, userspace
	 * won't try to request new buffer without receiving new event.
	 * This field must go away in future.
	 */
	data->new_bufs = 0;

	buf->empty = 1;
	ispstat_buf_release(stat);

	return 0;
}
Beispiel #3
0
/*
 * This API allows the user to update White Balance gains, as well as
 * exposure time and analog gain. It is also used to request frame
 * statistics.
 */
int isp_af_request_statistics(struct isp_af_device *isp_af,
			      struct isp_af_data *afdata)
{
	struct device *dev = to_device(isp_af);
	struct ispstat_buffer *buf;

	if (!isp_af->config.af_config) {
		dev_dbg(dev, "af: statistics requested while af engine"
			     " is not configured\n");
		return -EINVAL;
	}

	if (afdata->update & REQUEST_STATISTICS) {
		buf = ispstat_buf_get(&isp_af->stat,
			      (void *)afdata->af_statistics_buf,
			      afdata->frame_number);
		if (IS_ERR(buf))
			return PTR_ERR(buf);

		afdata->xtrastats.ts = buf->ts;
		afdata->config_counter = buf->config_counter;
		afdata->frame_number = buf->frame_number;

		ispstat_buf_release(&isp_af->stat);
	}

	afdata->curr_frame = isp_af->stat.frame_number;

	return 0;
}
Beispiel #4
0
/**
 * isph3a_aewb_stats_available - Check for stats available of specified frame.
 * @aewbdata: Pointer to return AE AWB statistics data
 *
 * Returns 0 if successful, or -1 if statistics are unavailable.
 **/
static int isph3a_aewb_get_stats(struct isp_h3a_device *isp_h3a,
				 struct isph3a_aewb_data *aewbdata)
{
	unsigned long irqflags;
	struct ispstat_buffer *buf;

	buf = ispstat_buf_get(&isp_h3a->stat,
			      (void *)aewbdata->h3a_aewb_statistics_buf,
			      aewbdata->frame_number);

	if (IS_ERR(buf))
		return PTR_ERR(buf);

	spin_lock_irqsave(isp_h3a->lock, irqflags);

	aewbdata->ts = buf->ts;
	aewbdata->config_counter = buf->config_counter;
	aewbdata->frame_number = buf->frame_number;

	spin_unlock_irqrestore(isp_h3a->lock, irqflags);

	ispstat_buf_release(&isp_h3a->stat);

	return 0;
}
Beispiel #5
0
/**
 * isph3a_aewb_stats_available - Check for stats available of specified frame.
 * @aewbdata: Pointer to return AE AWB statistics data
 *
 * Returns 0 if successful, or -1 if statistics are unavailable.
 **/
static int isph3a_aewb_get_stats(struct isp_h3a_device *isp_h3a,
				 struct isph3a_aewb_data *aewbdata)
{
	struct ispstat_buffer *buf;

	buf = ispstat_buf_get(&isp_h3a->stat,
			      (void *)aewbdata->h3a_aewb_statistics_buf,
			      aewbdata->frame_number);

	if (IS_ERR(buf))
		return PTR_ERR(buf);

	aewbdata->ts = buf->ts;
	aewbdata->config_counter = buf->config_counter;
	aewbdata->frame_number = buf->frame_number;

	ispstat_buf_release(&isp_h3a->stat);

	return 0;
}
Beispiel #6
0
/**
 * ispstat_stats_available - Check for stats available of specified frame.
 * @aewbdata: Pointer to return AE AWB statistics data
 *
 * Returns 0 if successful, or -1 if statistics are unavailable.
 **/
struct ispstat_buffer *ispstat_buf_get(struct ispstat *stat,
				       void __user *ptr,
				       unsigned int frame_number)
{
	int rval = 0;
	unsigned long flags;
	struct ispstat_buffer *buf;

	spin_lock_irqsave(&stat->lock, flags);

	buf = ispstat_buf_find(stat, frame_number);
	if (!buf) {
		spin_unlock_irqrestore(&stat->lock, flags);
		dev_dbg(stat->dev, "%s: cannot find requested buffer. "
				"frame_number = %d\n", stat->tag, frame_number);
		return ERR_PTR(-EBUSY);
	}

	stat->locked_buf = buf;

	spin_unlock_irqrestore(&stat->lock, flags);

	rval = copy_to_user((void *)ptr,
			    buf->virt_addr,
			    buf->buf_size);

	if (rval) {
		dev_info(stat->dev,
			 "%s: failed copying %d bytes of stat data\n",
			 stat->tag, rval);
		buf = ERR_PTR(-EFAULT);
		ispstat_buf_release(stat);
	}

	return buf;
}