示例#1
0
void rot_dump_registers(struct rot_dev *rot)
{
	unsigned int tmp, i;

	rot_dbg("dump rotator registers\n");
	for (i = 0; i <= ROTATOR_DST; i += 0x4) {
		tmp = readl(rot->regs + i);
		rot_dbg("0x%08x: 0x%08x", i, tmp);
	}
}
示例#2
0
int rot_v4l2_g_fmt_mplane(struct file *file, void *priv,
			  struct v4l2_format *f)
{
	struct rot_ctx *ctx = priv;
	struct rot_fmt *rot_fmt;
	struct rot_frame *frame;
	struct v4l2_pix_format_mplane *pixm = &f->fmt.pix_mp;
	int i;

	frame = ctx_get_frame(ctx, f->type);
	if (IS_ERR(frame))
		return PTR_ERR(frame);

	rot_fmt = frame->rot_fmt;

	pixm->width		= frame->pix_mp.width;
	pixm->height		= frame->pix_mp.height;
	pixm->pixelformat	= frame->pix_mp.pixelformat;
	pixm->field		= V4L2_FIELD_NONE;
	pixm->num_planes	= frame->rot_fmt->num_planes;
	pixm->colorspace	= 0;

	for (i = 0; i < pixm->num_planes; ++i) {
		pixm->plane_fmt[i].bytesperline = (pixm->width *
				rot_fmt->bitperpixel[i]) >> 3;
		pixm->plane_fmt[i].sizeimage = pixm->plane_fmt[i].bytesperline
				* pixm->height;

		rot_dbg("[%d] plane: bytesperline %d, sizeimage %d\n", i,
				pixm->plane_fmt[i].bytesperline,
				pixm->plane_fmt[i].sizeimage);
	}

	return 0;
}
示例#3
0
void rot_watchdog(unsigned long arg)
{
	struct rot_dev *rot = (struct rot_dev *)arg;

	rot_dbg("timeout watchdog\n");
	if (test_bit(DEV_RUN, &rot->state)) {
		atomic_inc(&rot->wdt.cnt);
		rot_err("rotator is still running\n");
		rot->wdt.timer.expires = jiffies + ROT_TIMEOUT;
		add_timer(&rot->wdt.timer);
	} else {
		rot_dbg("rotator finished job\n");
	}

	if (atomic_read(&rot->wdt.cnt) >= ROT_WDT_CNT)
		queue_work(rot->wq, &rot->ws);
}
示例#4
0
static int rot_release(struct file *file)
{
	struct rot_ctx *ctx = file->private_data;
	struct rot_dev *rot = ctx->rot_dev;

	rot_dbg("refcnt= %d", atomic_read(&rot->m2m.in_use));

	v4l2_m2m_ctx_release(ctx->m2m_ctx);
	kfree(ctx);

	atomic_dec(&rot->m2m.in_use);

	return 0;
}
示例#5
0
int rot_v4l2_try_fmt_mplane(struct file *file, void *priv,
			    struct v4l2_format *f)
{
	struct rot_ctx *ctx = priv;
	struct rot_fmt *rot_fmt;
	struct v4l2_pix_format_mplane *pixm = &f->fmt.pix_mp;
	int i;

	if (!V4L2_TYPE_IS_MULTIPLANAR(f->type)) {
		rot_err("not supported format type\n");
		return -EINVAL;
	}

	rot_fmt = rot_find_format(f);
	if (!rot_fmt) {
		rot_err("not supported format values\n");
		return -EINVAL;
	}

	rot_bound_align_image(ctx, rot_fmt, &pixm->width, &pixm->height);

	pixm->num_planes = rot_fmt->num_planes;
	pixm->colorspace = 0;

	for (i = 0; i < pixm->num_planes; ++i) {
		pixm->plane_fmt[i].bytesperline = (pixm->width *
				rot_fmt->bitperpixel[i]) >> 3;
		pixm->plane_fmt[i].sizeimage = pixm->plane_fmt[i].bytesperline
				* pixm->height;

		rot_dbg("[%d] plane: bytesperline %d, sizeimage %d\n", i,
				pixm->plane_fmt[i].bytesperline,
				pixm->plane_fmt[i].sizeimage);
	}

	return 0;
}
示例#6
0
void rot_work(struct work_struct *work)
{
	struct rot_dev *rot = container_of(work, struct rot_dev, ws);
	struct rot_ctx *ctx;
	unsigned long flags;
	struct vb2_buffer *src_vb, *dst_vb;

	spin_lock_irqsave(&rot->slock, flags);

	if (atomic_read(&rot->wdt.cnt) >= ROT_WDT_CNT) {
		rot_dbg("wakeup blocked process\n");
		ctx = v4l2_m2m_get_curr_priv(rot->m2m.m2m_dev);
		if (!ctx || !ctx->m2m_ctx) {
			rot_err("current ctx is NULL\n");
			goto wq_unlock;
		}
		src_vb = v4l2_m2m_src_buf_remove(ctx->m2m_ctx);
		dst_vb = v4l2_m2m_dst_buf_remove(ctx->m2m_ctx);

		if (src_vb && dst_vb) {
			v4l2_m2m_buf_done(src_vb, VB2_BUF_STATE_ERROR);
			v4l2_m2m_buf_done(dst_vb, VB2_BUF_STATE_ERROR);

			v4l2_m2m_job_finish(rot->m2m.m2m_dev, ctx->m2m_ctx);
		}
		rot->m2m.ctx = NULL;
		atomic_set(&rot->wdt.cnt, 0);
		clear_bit(DEV_RUN, &rot->state);
		clear_bit(CTX_RUN, &ctx->flags);
	}

wq_unlock:
	spin_unlock_irqrestore(&rot->slock, flags);

	pm_runtime_put(&rot->pdev->dev);
}
示例#7
0
static irqreturn_t rot_irq_handler(int irq, void *priv)
{
	struct rot_dev *rot = priv;
	struct rot_ctx *ctx;
	struct vb2_buffer *src_vb, *dst_vb;
	unsigned int irq_src;

	spin_lock(&rot->slock);

	clear_bit(DEV_RUN, &rot->state);
	if (timer_pending(&rot->wdt.timer))
		del_timer(&rot->wdt.timer);

	rot_hwget_irq_src(rot, &irq_src);
	rot_hwset_irq_clear(rot, &irq_src);

	if (irq_src != ISR_PEND_DONE) {
		rot_err("####################\n");
		rot_err("set SFR illegally\n");
		rot_err("maybe the result is wrong\n");
		rot_err("####################\n");
		rot_dump_register(rot);
	}

	ctx = v4l2_m2m_get_curr_priv(rot->m2m.m2m_dev);
	if (!ctx || !ctx->m2m_ctx) {
		rot_err("current ctx is NULL\n");
		goto isr_unlock;
	}

	clear_bit(CTX_RUN, &ctx->flags);
	rot->m2m.ctx = NULL;

	src_vb = v4l2_m2m_src_buf_remove(ctx->m2m_ctx);
	dst_vb = v4l2_m2m_dst_buf_remove(ctx->m2m_ctx);

	if (src_vb && dst_vb) {
		v4l2_m2m_buf_done(src_vb, VB2_BUF_STATE_DONE);
		v4l2_m2m_buf_done(dst_vb, VB2_BUF_STATE_DONE);

		if (test_bit(DEV_SUSPEND, &rot->state)) {
			rot_dbg("wake up blocked process by suspend\n");
			wake_up(&rot->irq.wait);
		} else {
			v4l2_m2m_job_finish(rot->m2m.m2m_dev, ctx->m2m_ctx);
		}

		/* Wake up from CTX_ABORT state */
		if (test_and_clear_bit(CTX_ABORT, &ctx->flags))
			wake_up(&rot->irq.wait);

		queue_work(rot->wq, &rot->ws);
	} else {
		rot_err("failed to get the buffer done\n");
	}

isr_unlock:
	spin_unlock(&rot->slock);

	return IRQ_HANDLED;
}
示例#8
0
static void rot_m2m_device_run(void *priv)
{
	struct rot_ctx *ctx = priv;
	struct rot_frame *s_frame, *d_frame;
	struct rot_dev *rot;
	unsigned long flags, tmp;
	u32 degree = 0, flip = 0;

	spin_lock_irqsave(&ctx->slock, flags);

	rot = ctx->rot_dev;

	if (test_bit(DEV_RUN, &rot->state)) {
		rot_err("Rotate is already in progress\n");
		goto run_unlock;
	}

	if (test_bit(DEV_SUSPEND, &rot->state)) {
		rot_err("Rotate is in suspend state\n");
		goto run_unlock;
	}

	if (test_bit(CTX_ABORT, &ctx->flags)) {
		rot_dbg("aborted rot device run\n");
		goto run_unlock;
	}

	pm_runtime_get_sync(&ctx->rot_dev->pdev->dev);

	if (rot->m2m.ctx != ctx)
		rot->m2m.ctx = ctx;

	s_frame = &ctx->s_frame;
	d_frame = &ctx->d_frame;

	/* Configuration rotator registers */
	rot_hwset_image_format(rot, s_frame->rot_fmt->pixelformat);
	rot_mapping_flip(ctx, &degree, &flip);
	rot_hwset_flip(rot, flip);
	rot_hwset_rotation(rot, degree);

	if (ctx->rotation == 90 || ctx->rotation == 270) {
		tmp                     = d_frame->pix_mp.height;
		d_frame->pix_mp.height  = d_frame->pix_mp.width;
		d_frame->pix_mp.width   = tmp;
	}

	rot_hwset_src_imgsize(rot, s_frame);
	rot_hwset_dst_imgsize(rot, d_frame);

	rot_hwset_src_crop(rot, &s_frame->crop);
	rot_hwset_dst_crop(rot, &d_frame->crop);

	rot_set_frame_addr(ctx);

	/* Enable rotator interrupt */
	rot_hwset_irq_frame_done(rot, 1);
	rot_hwset_irq_illegal_config(rot, 1);

	set_bit(DEV_RUN, &rot->state);
	set_bit(CTX_RUN, &ctx->flags);

	/* Start rotate operation */
	rot_hwset_start(rot);

	/* Start watchdog timer */
	rot->wdt.timer.expires = jiffies + ROT_TIMEOUT;
	if (timer_pending(&rot->wdt.timer) == 0)
		add_timer(&rot->wdt.timer);
	else
		mod_timer(&rot->wdt.timer, rot->wdt.timer.expires);

run_unlock:
	spin_unlock_irqrestore(&ctx->slock, flags);
}