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; }
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)); }