int kgsl_g12_cmdstream_start(struct kgsl_device *device) { struct kgsl_g12_device *g12_device = (struct 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_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; }
int kgsl_g12_cmdstream_issueibcmds(struct kgsl_device_private *dev_priv, int drawctxt_index, uint32_t ibaddr, int sizedwords, uint32_t *timestamp, unsigned int ctrl) { unsigned 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 = (struct kgsl_g12_device *) device; cmd = ibaddr; tmp.hostptr = (void *)*timestamp; KGSL_CMD_INFO("ctxt %d ibaddr 0x%08x sizedwords %d", drawctxt_index, ibaddr, sizedwords); /* context switch */ if (drawctxt_index != (int)g12_device->ringbuffer.prevctx) { KGSL_CMD_INFO("context switch %d -> %d", drawctxt_index, 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(g12_device->wait_timestamp_wq, room_in_rb(g12_device), msecs_to_jiffies(KGSL_TIMEOUT_DEFAULT)); if (result < 0) { KGSL_CMD_ERR("failed waiting for ringbuffer. result %d", 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 = drawctxt_index; 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); 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; }
int kgsl_g12_drawctxt_create(struct kgsl_device *device, uint32_t ctxt_id_mask, unsigned int *drawctxt_id) { int i; int cmd; int result; unsigned int ctx_id; if (g_z1xx.numcontext == 0) { for (i = 0; i < GSL_HAL_NUMCMDBUFFERS; i++) { int flags = 0; if (kgsl_sharedmem_alloc(flags, GSL_HAL_CMDBUFFERSIZE, &g_z1xx.cmdbufdesc[i]) != 0) return -ENOMEM; g_z1xx.cmdbuf[i] = kzalloc(GSL_HAL_CMDBUFFERSIZE, GFP_KERNEL); g_z1xx.curr = i; g_z1xx.offs = 0; addmarker(&g_z1xx); kgsl_sharedmem_write(&g_z1xx.cmdbufdesc[i], 0, g_z1xx.cmdbuf[i], (512 + 13) * sizeof(unsigned int)); } g_z1xx.curr = 0; cmd = (int)(((VGV3_NEXTCMD_JUMP) & VGV3_NEXTCMD_NEXTCMD_FMASK) << VGV3_NEXTCMD_NEXTCMD_FSHIFT); /* set cmd stream buffer to hw */ 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, g_z1xx.cmdbufdesc[0].physaddr); if (result != 0) return result; result = kgsl_g12_cmdwindow_write(device, KGSL_CMDWINDOW_2D, ADDR_VGV3_NEXTCMD, cmd | 5); 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; } ctx_id = ffz(ctxt_id_mask); g_z1xx.numcontext++; if (g_z1xx.numcontext > KGSL_G12_CONTEXT_MAX) { *drawctxt_id = 0; return KGSL_FAILURE; } *drawctxt_id = ctx_id; return KGSL_SUCCESS; }