unsigned int kgsl_g12_cmdstream_readtimestamp(struct kgsl_device *device,
			     enum kgsl_timestamp_type type)
{
	struct kgsl_g12_device *g12_device = KGSL_G12_DEVICE(device);
	/* get current EOP timestamp */
	return g12_device->timestamp;
}
int kgsl_g12_cmdstream_init(struct kgsl_device *device)
{
	struct kgsl_g12_device *g12_device = KGSL_G12_DEVICE(device);
	memset(&g12_device->ringbuffer, 0, sizeof(struct kgsl_g12_ringbuffer));
	g12_device->ringbuffer.prevctx = KGSL_G12_INVALID_CONTEXT;
	return kgsl_sharedmem_alloc_coherent(&g12_device->ringbuffer.cmdbufdesc,
					     KGSL_G12_RB_SIZE);
}
int
kgsl_g12_drawctxt_destroy(struct kgsl_device *device,
			  struct kgsl_context *context)
{
	struct kgsl_g12_device *g12_device = KGSL_G12_DEVICE(device);

	if (g12_device->ringbuffer.prevctx == context->id)
		g12_device->ringbuffer.prevctx = KGSL_G12_INVALID_CONTEXT;

	return 0;
}
int
kgsl_g12_drawctxt_destroy(struct kgsl_device *device,
			  struct kgsl_context *context)
{
	struct kgsl_g12_device *g12_device = KGSL_G12_DEVICE(device);

	if (g12_device->ringbuffer.prevctx == context->id) {
		kgsl_g12_idle(device, KGSL_TIMEOUT_DEFAULT);
		g12_device->ringbuffer.prevctx = KGSL_G12_INVALID_CONTEXT;
	}

	return 0;
}
int kgsl_g12_cmdstream_start(struct kgsl_device *device)
{
	struct kgsl_g12_device *g12_device = KGSL_G12_DEVICE(device);
	int result;
	unsigned int cmd = VGV3_NEXTCMD_JUMP << VGV3_NEXTCMD_NEXTCMD_FSHIFT;

	g12_device->timestamp = 0;
	g12_device->current_timestamp = 0;

	addmarker(&g12_device->ringbuffer, 0);

	result = kgsl_g12_cmdwindow_write(device, KGSL_CMDWINDOW_2D,
			ADDR_VGV3_MODE, 4);
	if (result != 0)
		return result;

	result = kgsl_g12_cmdwindow_write(device, KGSL_CMDWINDOW_2D,
			ADDR_VGV3_NEXTADDR,
			g12_device->ringbuffer.cmdbufdesc.gpuaddr);
	if (result != 0)
		return result;

	result = kgsl_g12_cmdwindow_write(device, KGSL_CMDWINDOW_2D,
			ADDR_VGV3_NEXTCMD, cmd | 5);
	if (result != 0)
		return result;

	result = kgsl_g12_cmdwindow_write(device, KGSL_CMDWINDOW_2D,
			ADDR_VGV3_WRITEADDR, device->memstore.gpuaddr);

	if (result != 0)
		return result;

	cmd = (int)(((1) & VGV3_CONTROL_MARKADD_FMASK)
			<< VGV3_CONTROL_MARKADD_FSHIFT);

	result = kgsl_g12_cmdwindow_write(device, KGSL_CMDWINDOW_2D,
			ADDR_VGV3_CONTROL, cmd);

	if (result != 0)
		return result;

	result = kgsl_g12_cmdwindow_write(device, KGSL_CMDWINDOW_2D,
			ADDR_VGV3_CONTROL, 0);
	if (result != 0)
		return result;

	return result;
}
int
kgsl_g12_drawctxt_destroy(struct kgsl_device *device,
			  struct kgsl_context *context)
{
	struct kgsl_g12_device *g12_device = KGSL_G12_DEVICE(device);

	kgsl_g12_idle(device, KGSL_TIMEOUT_DEFAULT);

	if (g12_device->ringbuffer.prevctx == context->id) {
		g12_device->ringbuffer.prevctx = KGSL_G12_INVALID_CONTEXT;
		device->mmu.hwpagetable = device->mmu.defaultpagetable;
		kgsl_setstate(device, KGSL_MMUFLAGS_PTUPDATE);
	}

	return 0;
}
示例#7
0
irqreturn_t kgsl_g12_isr(int irq, void *data)
{
	irqreturn_t result = IRQ_NONE;
	unsigned int status;
	struct kgsl_device *device = (struct kgsl_device *) data;
	struct kgsl_g12_device *g12_device = KGSL_G12_DEVICE(device);

	kgsl_g12_regread_isr(device, ADDR_VGC_IRQSTATUS >> 2, &status);

	if (status & GSL_VGC_INT_MASK) {
		kgsl_g12_regwrite_isr(device,
			ADDR_VGC_IRQSTATUS >> 2, status & GSL_VGC_INT_MASK);

		result = IRQ_HANDLED;

		if (status & REG_VGC_IRQSTATUS__FIFO_MASK)
			KGSL_DRV_ERR("g12 fifo interrupt\n");
		if (status & REG_VGC_IRQSTATUS__MH_MASK)
			kgsl_mh_intrcallback(device);
		if (status & REG_VGC_IRQSTATUS__G2D_MASK) {
			int count;

			KGSL_DRV_VDBG("g12 g2d interrupt\n");
			kgsl_g12_regread_isr(device,
					 ADDR_VGC_IRQ_ACTIVE_CNT >> 2,
					 &count);

			count >>= 8;
			count &= 255;
			g12_device->timestamp += count;

			wake_up_interruptible(&(g12_device->wait_timestamp_wq));

			atomic_notifier_call_chain(
				&(device->ts_notifier_list),
				device->id, NULL);
		}
int
kgsl_g12_cmdstream_issueibcmds(struct kgsl_device_private *dev_priv,
			struct kgsl_context *context,
			struct kgsl_ibdesc *ibdesc,
			unsigned int numibs,
			uint32_t *timestamp,
			unsigned int ctrl)
{
	int result = 0;
	unsigned int ofs        = PACKETSIZE_STATESTREAM * sizeof(unsigned int);
	unsigned int cnt        = 5;
	unsigned int nextaddr   = 0;
	unsigned int index	= 0;
	unsigned int nextindex;
	unsigned int nextcnt    = KGSL_G12_STREAM_END_CMD | 5;
	struct kgsl_memdesc tmp = {0};
	unsigned int cmd;
	struct kgsl_device *device = dev_priv->device;
	struct kgsl_pagetable *pagetable = dev_priv->process_priv->pagetable;
	struct kgsl_g12_device *g12_device = KGSL_G12_DEVICE(device);
	unsigned int sizedwords;

	if (device->state & KGSL_STATE_HUNG) {
		return -EINVAL;
		goto error;
	}
	if (numibs != 1) {
		KGSL_DRV_ERR(device, "Invalid number of ibs: %d\n", numibs);
		result = -EINVAL;
		goto error;
	}
	cmd = ibdesc[0].gpuaddr;
	sizedwords = ibdesc[0].sizedwords;

	tmp.hostptr = (void *)*timestamp;

	KGSL_CMD_INFO(device, "ctxt %d ibaddr 0x%08x sizedwords %d\n",
		context->id, cmd, sizedwords);
	/* context switch */
	if ((context->id != (int)g12_device->ringbuffer.prevctx) ||
	    (ctrl & KGSL_CONTEXT_CTX_SWITCH)) {
		KGSL_CMD_INFO(device, "context switch %d -> %d\n",
			context->id, g12_device->ringbuffer.prevctx);
		kgsl_mmu_setstate(device, pagetable);
		cnt = PACKETSIZE_STATESTREAM;
		ofs = 0;
	}
	kgsl_g12_setstate(device, kgsl_pt_get_flags(device->mmu.hwpagetable,
						    device->id));

	result = wait_event_interruptible_timeout(device->wait_queue,
				  room_in_rb(g12_device),
				  msecs_to_jiffies(KGSL_TIMEOUT_DEFAULT));
	if (result <= 0) {
		KGSL_CMD_ERR(device, "wait_event_interruptible_timeout "
			"failed: %d\n", result);
		goto error;
	}
	result = 0;

	index = g12_device->current_timestamp % KGSL_G12_PACKET_COUNT;
	g12_device->current_timestamp++;
	nextindex = g12_device->current_timestamp % KGSL_G12_PACKET_COUNT;
	*timestamp = g12_device->current_timestamp;

	g12_device->ringbuffer.prevctx = context->id;

	addcmd(&g12_device->ringbuffer, index, cmd + ofs, cnt);

	/* Make sure the next ringbuffer entry has a marker */
	addmarker(&g12_device->ringbuffer, nextindex);

	nextaddr = g12_device->ringbuffer.cmdbufdesc.gpuaddr
		+ rb_offset(nextindex);

	tmp.hostptr = (void *)(tmp.hostptr +
			(sizedwords * sizeof(unsigned int)));
	tmp.size = 12;

	kgsl_sharedmem_writel(&tmp, 4, nextaddr);
	kgsl_sharedmem_writel(&tmp, 8, nextcnt);

	/* sync memory before activating the hardware for the new command*/
	mb();

	cmd = (int)(((2) & VGV3_CONTROL_MARKADD_FMASK)
		<< VGV3_CONTROL_MARKADD_FSHIFT);

	kgsl_g12_cmdwindow_write(device,
				KGSL_CMDWINDOW_2D, ADDR_VGV3_CONTROL, cmd);
	kgsl_g12_cmdwindow_write(device,
				KGSL_CMDWINDOW_2D, ADDR_VGV3_CONTROL, 0);
error:
	return result;
}
void kgsl_g12_cmdstream_close(struct kgsl_device *device)
{
	struct kgsl_g12_device *g12_device = KGSL_G12_DEVICE(device);
	kgsl_sharedmem_free(&g12_device->ringbuffer.cmdbufdesc);
	memset(&g12_device->ringbuffer, 0, sizeof(struct kgsl_g12_ringbuffer));
}