Beispiel #1
0
static void _tegra_dc_disable(struct tegra_dc *dc)
{
	int i;

	disable_irq(dc->irq);

	if (dc->out_ops && dc->out_ops->disable)
		dc->out_ops->disable(dc);

	clk_disable(dc->emc_clk);
	clk_disable(dc->clk);
	tegra_dvfs_set_rate(dc->clk, 0);

	if (dc->out && dc->out->disable)
		dc->out->disable();

	/* flush any pending syncpt waits */
	for (i = 0; i < dc->n_windows; i++) {
		while (dc->syncpt[i].min < dc->syncpt[i].max) {
			dc->syncpt[i].min++;
			nvhost_syncpt_cpu_incr(&dc->ndev->host->syncpt,
				dc->syncpt[i].id);
		}
	}

	tegra_dc_io_end(dc);
}
Beispiel #2
0
/**
 * Increment syncpoint value from cpu, updating cache
 */
void nvhost_syncpt_incr(struct nvhost_syncpt *sp, u32 id)
{
	nvhost_syncpt_incr_max(sp, id, 1);
	nvhost_module_busy(&syncpt_to_dev(sp)->mod);
	nvhost_syncpt_cpu_incr(sp, id);
	nvhost_module_idle(&syncpt_to_dev(sp)->mod);
}
Beispiel #3
0
/**
 * Increment syncpoint value from cpu, updating cache
 */
void nvhost_syncpt_incr(struct nvhost_syncpt *sp, u32 id)
{
	if (nvhost_syncpt_client_managed(sp, id))
		nvhost_syncpt_incr_max(sp, id, 1);
	nvhost_module_busy(syncpt_to_dev(sp)->dev);
	nvhost_syncpt_cpu_incr(sp, id);
	nvhost_module_idle(syncpt_to_dev(sp)->dev);
}
Beispiel #4
0
void tegra_dc_incr_syncpt_min(struct tegra_dc *dc, int i, u32 val)
{
	mutex_lock(&dc->lock);
	while (dc->syncpt[i].min < val) {
		dc->syncpt[i].min++;
		nvhost_syncpt_cpu_incr(&dc->ndev->host->syncpt,
			dc->syncpt[i].id);
	}
	mutex_unlock(&dc->lock);
}
void nvhost_syncpt_cpu_incr_ext(struct platform_device *dev, u32 id)
{
	struct platform_device *pdev;
	struct nvhost_syncpt *sp;

	BUG_ON(!nvhost_get_parent(dev));

	/* get the parent */
	pdev = to_platform_device(dev->dev.parent);
	sp = &(nvhost_get_host(pdev)->syncpt);

	nvhost_syncpt_cpu_incr(sp, id);
}
Beispiel #6
0
static void ctx3d_save_service(struct nvhost_hwctx *nctx)
{
	struct host1x_hwctx *ctx = to_host1x_hwctx(nctx);

	u32 *ptr = (u32 *)ctx->restore_virt + RESTORE_BEGIN_SIZE;
	unsigned int pending = 0;

	ptr = save_regs_v0(ptr, &pending, nctx->channel,
			ctxsave_regs_3d_global,
			ARRAY_SIZE(ctxsave_regs_3d_global));

	wmb();
	nvhost_syncpt_cpu_incr(&nvhost_get_host(nctx->channel->dev)->syncpt,
			host1x_hwctx_handler(ctx)->syncpt);
}
Beispiel #7
0
/**
 * Increment syncpoint value from cpu, updating cache
 */
int nvhost_syncpt_incr(struct nvhost_syncpt *sp, u32 id)
{
	int err;

	err = nvhost_module_busy(syncpt_to_dev(sp)->dev);
	if (err)
		return err;

	if (nvhost_syncpt_client_managed(sp, id))
		nvhost_syncpt_incr_max(sp, id, 1);
	nvhost_syncpt_cpu_incr(sp, id);
	nvhost_module_idle(syncpt_to_dev(sp)->dev);

	return 0;
}
void nvhost_syncpt_cpu_incr_ext(struct platform_device *dev, u32 id)
{
	struct platform_device *pdev;
	struct nvhost_syncpt *sp;

	if (!nvhost_get_parent(dev)) {
		dev_err(&dev->dev, "Incr called with wrong dev\n");
		return;
	}

	/* get the parent */
	pdev = to_platform_device(dev->dev.parent);
	sp = &(nvhost_get_host(pdev)->syncpt);

	nvhost_syncpt_cpu_incr(sp, id);
}
/**
 * Increment syncpoint value from cpu, updating cache
 */
void nvhost_syncpt_incr(struct nvhost_syncpt *sp, u32 id)
{
#ifdef CONFIG_MACH_N1
	u32 min, max;

	max = nvhost_syncpt_incr_max(sp, id, 1);
	min = nvhost_syncpt_incr_min(sp, id, 1);
	if (sp->restore_needed) {
		/* XXX restore_needed used only for logging (to be removed in final checkin) */
		dev_warn(&syncpt_to_dev(sp)->pdev->dev,
				 "syncpoint id %d (%s) incremented min = %d, max = %d while nvhost suspended\n",
				 id, nvhost_syncpt_name(id), min, max);
	}
#else
	nvhost_syncpt_incr_max(sp, id, 1);
#endif
	nvhost_module_busy(&syncpt_to_dev(sp)->mod);
	nvhost_syncpt_cpu_incr(sp, id);
	nvhost_module_idle(&syncpt_to_dev(sp)->mod);
}
Beispiel #10
0
static void ctx3d_save_service(struct nvhost_hwctx *ctx)
{
	const struct hwctx_reginfo *r;
	const struct hwctx_reginfo *rend;
	unsigned int pending = 0;
	u32 *ptr = (u32 *)ctx->save_cpu_data + RESTORE_BEGIN_SIZE;

	BUG_ON(!ctx->save_cpu_data);

	r = ctxsave_regs_3d;
	rend = ctxsave_regs_3d + ARRAY_SIZE(ctxsave_regs_3d);
	for ( ; r != rend; ++r) {
		u32 count = r->count;
		switch (r->type) {
		case HWCTX_REGINFO_DIRECT:
			ptr += RESTORE_DIRECT_SIZE;
			break;
		case HWCTX_REGINFO_INDIRECT:
			ptr += RESTORE_INDOFFSET_SIZE + RESTORE_INDDATA_SIZE;
			break;
		case HWCTX_REGINFO_INDIRECT_OFFSET:
			ptr += RESTORE_INDOFFSET_SIZE;
			continue; /* INDIRECT_DATA follows with real count */
		case HWCTX_REGINFO_INDIRECT_DATA:
			ptr += RESTORE_INDDATA_SIZE;
			break;
		}
		restore_registers_from_fifo(ptr, count, ctx->channel, &pending);
		ptr += count;
	}

	BUG_ON((u32)((ptr + RESTORE_END_SIZE) - (u32*)ctx->save_cpu_data)
		!= context_restore_size);

	wmb();
	nvhost_syncpt_cpu_incr(&ctx->channel->dev->syncpt, NVSYNCPT_3D);
}
Beispiel #11
0
void nvhost_syncpt_cpu_incr_ext(struct nvhost_device *dev, u32 id)
{
	struct nvhost_syncpt *sp = &(nvhost_get_host(dev)->syncpt);
	nvhost_syncpt_cpu_incr(sp, id);
}
Beispiel #12
0
int nvhost_gr3d_t20_read_reg(
	struct nvhost_device *dev,
	struct nvhost_channel *channel,
	struct nvhost_hwctx *hwctx,
	u32 offset,
	u32 *value)
{
	struct host1x_hwctx *hwctx_to_save = NULL;
	struct nvhost_hwctx_handler *h = hwctx->h;
	struct host1x_hwctx_handler *p = to_host1x_hwctx_handler(h);
	bool need_restore = false;
	u32 syncpt_incrs = 4;
	unsigned int pending = 0;
	DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wq);
	void *ref;
	void *ctx_waiter, *read_waiter, *completed_waiter;
	struct nvhost_job *job;
	u32 syncval;
	int err;

	if (hwctx->has_timedout)
		return -ETIMEDOUT;

	ctx_waiter = nvhost_intr_alloc_waiter();
	read_waiter = nvhost_intr_alloc_waiter();
	completed_waiter = nvhost_intr_alloc_waiter();
	if (!ctx_waiter || !read_waiter || !completed_waiter) {
		err = -ENOMEM;
		goto done;
	}

	job = nvhost_job_alloc(channel, hwctx,
			NULL,
			nvhost_get_host(dev)->memmgr, 0, 0);
	if (!job) {
		err = -ENOMEM;
		goto done;
	}

	/* keep module powered */
	nvhost_module_busy(dev);

	/* get submit lock */
	err = mutex_lock_interruptible(&channel->submitlock);
	if (err) {
		nvhost_module_idle(dev);
		return err;
	}

	/* context switch */
	if (channel->cur_ctx != hwctx) {
		hwctx_to_save = channel->cur_ctx ?
			to_host1x_hwctx(channel->cur_ctx) : NULL;
		if (hwctx_to_save) {
			syncpt_incrs += hwctx_to_save->save_incrs;
			hwctx_to_save->hwctx.valid = true;
			nvhost_job_get_hwctx(job, &hwctx_to_save->hwctx);
		}
		channel->cur_ctx = hwctx;
		if (channel->cur_ctx && channel->cur_ctx->valid) {
			need_restore = true;
			syncpt_incrs += to_host1x_hwctx(channel->cur_ctx)
				->restore_incrs;
		}
	}

	syncval = nvhost_syncpt_incr_max(&nvhost_get_host(dev)->syncpt,
		p->syncpt, syncpt_incrs);

	job->syncpt_id = p->syncpt;
	job->syncpt_incrs = syncpt_incrs;
	job->syncpt_end = syncval;

	/* begin a CDMA submit */
	nvhost_cdma_begin(&channel->cdma, job);

	/* push save buffer (pre-gather setup depends on unit) */
	if (hwctx_to_save)
		h->save_push(&hwctx_to_save->hwctx, &channel->cdma);

	/* gather restore buffer */
	if (need_restore)
		nvhost_cdma_push(&channel->cdma,
			nvhost_opcode_gather(to_host1x_hwctx(channel->cur_ctx)
				->restore_size),
			to_host1x_hwctx(channel->cur_ctx)->restore_phys);

	/* Switch to 3D - wait for it to complete what it was doing */
	nvhost_cdma_push(&channel->cdma,
		nvhost_opcode_setclass(NV_GRAPHICS_3D_CLASS_ID, 0, 0),
		nvhost_opcode_imm_incr_syncpt(
			host1x_uclass_incr_syncpt_cond_op_done_v(),
			p->syncpt));
	nvhost_cdma_push(&channel->cdma,
		nvhost_opcode_setclass(NV_HOST1X_CLASS_ID,
			host1x_uclass_wait_syncpt_base_r(), 1),
		nvhost_class_host_wait_syncpt_base(p->syncpt,
			p->waitbase, 1));
	/*  Tell 3D to send register value to FIFO */
	nvhost_cdma_push(&channel->cdma,
		nvhost_opcode_nonincr(host1x_uclass_indoff_r(), 1),
		nvhost_class_host_indoff_reg_read(
			host1x_uclass_indoff_indmodid_gr3d_v(),
			offset, false));
	nvhost_cdma_push(&channel->cdma,
		nvhost_opcode_imm(host1x_uclass_inddata_r(), 0),
		NVHOST_OPCODE_NOOP);
	/*  Increment syncpt to indicate that FIFO can be read */
	nvhost_cdma_push(&channel->cdma,
		nvhost_opcode_imm_incr_syncpt(
			host1x_uclass_incr_syncpt_cond_immediate_v(),
			p->syncpt),
		NVHOST_OPCODE_NOOP);
	/*  Wait for value to be read from FIFO */
	nvhost_cdma_push(&channel->cdma,
		nvhost_opcode_nonincr(host1x_uclass_wait_syncpt_base_r(), 1),
		nvhost_class_host_wait_syncpt_base(p->syncpt,
			p->waitbase, 3));
	/*  Indicate submit complete */
	nvhost_cdma_push(&channel->cdma,
		nvhost_opcode_nonincr(host1x_uclass_incr_syncpt_base_r(), 1),
		nvhost_class_host_incr_syncpt_base(p->waitbase, 4));
	nvhost_cdma_push(&channel->cdma,
		NVHOST_OPCODE_NOOP,
		nvhost_opcode_imm_incr_syncpt(
			host1x_uclass_incr_syncpt_cond_immediate_v(),
			p->syncpt));

	/* end CDMA submit  */
	nvhost_cdma_end(&channel->cdma, job);
	nvhost_job_put(job);
	job = NULL;

	/*
	 * schedule a context save interrupt (to drain the host FIFO
	 * if necessary, and to release the restore buffer)
	 */
	if (hwctx_to_save) {
		err = nvhost_intr_add_action(
			&nvhost_get_host(dev)->intr,
			p->syncpt,
			syncval - syncpt_incrs
				+ hwctx_to_save->save_incrs
				- 1,
			NVHOST_INTR_ACTION_CTXSAVE, hwctx_to_save,
			ctx_waiter,
			NULL);
		ctx_waiter = NULL;
		WARN(err, "Failed to set context save interrupt");
	}

	/* Wait for FIFO to be ready */
	err = nvhost_intr_add_action(&nvhost_get_host(dev)->intr,
			p->syncpt, syncval - 2,
			NVHOST_INTR_ACTION_WAKEUP, &wq,
			read_waiter,
			&ref);
	read_waiter = NULL;
	WARN(err, "Failed to set wakeup interrupt");
	wait_event(wq,
		nvhost_syncpt_is_expired(&nvhost_get_host(dev)->syncpt,
				p->syncpt, syncval - 2));
	nvhost_intr_put_ref(&nvhost_get_host(dev)->intr, p->syncpt,
			ref);

	/* Read the register value from FIFO */
	err = nvhost_channel_drain_read_fifo(channel, value, 1, &pending);

	/* Indicate we've read the value */
	nvhost_syncpt_cpu_incr(&nvhost_get_host(dev)->syncpt,
			p->syncpt);

	/* Schedule a submit complete interrupt */
	err = nvhost_intr_add_action(&nvhost_get_host(dev)->intr,
			p->syncpt, syncval,
			NVHOST_INTR_ACTION_SUBMIT_COMPLETE, channel,
			completed_waiter, NULL);
	completed_waiter = NULL;
	WARN(err, "Failed to set submit complete interrupt");

	mutex_unlock(&channel->submitlock);

done:
	kfree(ctx_waiter);
	kfree(read_waiter);
	kfree(completed_waiter);
	return err;
}
Beispiel #13
0
void nvhost_syncpt_cpu_incr_ext(struct platform_device *dev, u32 id)
{
	struct nvhost_master *master = nvhost_get_host(dev);
	struct nvhost_syncpt *sp = &master->syncpt;
	nvhost_syncpt_cpu_incr(sp, id);
}