Lines Matching refs:g2d

264 static inline void g2d_hw_reset(struct g2d_data *g2d)  in g2d_hw_reset()  argument
266 writel(G2D_R | G2D_SFRCLEAR, g2d->regs + G2D_SOFT_RESET); in g2d_hw_reset()
267 clear_bit(G2D_BIT_ENGINE_BUSY, &g2d->flags); in g2d_hw_reset()
270 static int g2d_init_cmdlist(struct g2d_data *g2d) in g2d_init_cmdlist() argument
272 struct device *dev = g2d->dev; in g2d_init_cmdlist()
278 g2d->cmdlist_dma_attrs = DMA_ATTR_WRITE_COMBINE; in g2d_init_cmdlist()
280 g2d->cmdlist_pool_virt = dma_alloc_attrs(to_dma_dev(g2d->drm_dev), in g2d_init_cmdlist()
282 &g2d->cmdlist_pool, GFP_KERNEL, in g2d_init_cmdlist()
283 g2d->cmdlist_dma_attrs); in g2d_init_cmdlist()
284 if (!g2d->cmdlist_pool_virt) { in g2d_init_cmdlist()
299 g2d->cmdlist_pool_virt + nr * G2D_CMDLIST_SIZE; in g2d_init_cmdlist()
301 g2d->cmdlist_pool + nr * G2D_CMDLIST_SIZE; in g2d_init_cmdlist()
307 list_add_tail(&node[nr].list, &g2d->free_cmdlist); in g2d_init_cmdlist()
313 dma_free_attrs(to_dma_dev(g2d->drm_dev), G2D_CMDLIST_POOL_SIZE, in g2d_init_cmdlist()
314 g2d->cmdlist_pool_virt, in g2d_init_cmdlist()
315 g2d->cmdlist_pool, g2d->cmdlist_dma_attrs); in g2d_init_cmdlist()
319 static void g2d_fini_cmdlist(struct g2d_data *g2d) in g2d_fini_cmdlist() argument
321 kfree(g2d->cmdlist_node); in g2d_fini_cmdlist()
323 if (g2d->cmdlist_pool_virt && g2d->cmdlist_pool) { in g2d_fini_cmdlist()
324 dma_free_attrs(to_dma_dev(g2d->drm_dev), in g2d_fini_cmdlist()
326 g2d->cmdlist_pool_virt, in g2d_fini_cmdlist()
327 g2d->cmdlist_pool, g2d->cmdlist_dma_attrs); in g2d_fini_cmdlist()
331 static struct g2d_cmdlist_node *g2d_get_cmdlist(struct g2d_data *g2d) in g2d_get_cmdlist() argument
333 struct device *dev = g2d->dev; in g2d_get_cmdlist()
336 mutex_lock(&g2d->cmdlist_mutex); in g2d_get_cmdlist()
337 if (list_empty(&g2d->free_cmdlist)) { in g2d_get_cmdlist()
339 mutex_unlock(&g2d->cmdlist_mutex); in g2d_get_cmdlist()
343 node = list_first_entry(&g2d->free_cmdlist, struct g2d_cmdlist_node, in g2d_get_cmdlist()
346 mutex_unlock(&g2d->cmdlist_mutex); in g2d_get_cmdlist()
351 static void g2d_put_cmdlist(struct g2d_data *g2d, struct g2d_cmdlist_node *node) in g2d_put_cmdlist() argument
353 mutex_lock(&g2d->cmdlist_mutex); in g2d_put_cmdlist()
354 list_move_tail(&node->list, &g2d->free_cmdlist); in g2d_put_cmdlist()
355 mutex_unlock(&g2d->cmdlist_mutex); in g2d_put_cmdlist()
378 static void g2d_userptr_put_dma_addr(struct g2d_data *g2d, in g2d_userptr_put_dma_addr() argument
399 dma_unmap_sgtable(to_dma_dev(g2d->drm_dev), g2d_userptr->sgt, in g2d_userptr_put_dma_addr()
414 static dma_addr_t *g2d_userptr_get_dma_addr(struct g2d_data *g2d, in g2d_userptr_get_dma_addr() argument
428 DRM_DEV_ERROR(g2d->dev, "invalid userptr size.\n"); in g2d_userptr_get_dma_addr()
483 DRM_DEV_ERROR(g2d->dev, in g2d_userptr_get_dma_addr()
503 DRM_DEV_ERROR(g2d->dev, "failed to get sgt from pages.\n"); in g2d_userptr_get_dma_addr()
509 ret = dma_map_sgtable(to_dma_dev(g2d->drm_dev), sgt, in g2d_userptr_get_dma_addr()
512 DRM_DEV_ERROR(g2d->dev, "failed to map sgt with dma region.\n"); in g2d_userptr_get_dma_addr()
521 if (g2d->current_pool + (npages << PAGE_SHIFT) < g2d->max_pool) { in g2d_userptr_get_dma_addr()
522 g2d->current_pool += npages << PAGE_SHIFT; in g2d_userptr_get_dma_addr()
548 static void g2d_userptr_free_all(struct g2d_data *g2d, struct drm_file *filp) in g2d_userptr_free_all() argument
555 g2d_userptr_put_dma_addr(g2d, g2d_userptr, true); in g2d_userptr_free_all()
557 g2d->current_pool = 0; in g2d_userptr_free_all()
560 static enum g2d_reg_type g2d_get_reg_type(struct g2d_data *g2d, int reg_offset) in g2d_get_reg_type() argument
593 DRM_DEV_ERROR(g2d->dev, "Unknown register offset![%d]\n", in g2d_get_reg_type()
628 static bool g2d_check_buf_desc_is_valid(struct g2d_data *g2d, in g2d_check_buf_desc_is_valid() argument
646 DRM_DEV_ERROR(g2d->dev, "width[%d] is out of range!\n", width); in g2d_check_buf_desc_is_valid()
653 DRM_DEV_ERROR(g2d->dev, in g2d_check_buf_desc_is_valid()
673 DRM_DEV_ERROR(g2d->dev, "last engine access position [%lu] " in g2d_check_buf_desc_is_valid()
681 static int g2d_map_cmdlist_gem(struct g2d_data *g2d, in g2d_map_cmdlist_gem() argument
704 reg_type = g2d_get_reg_type(g2d, offset); in g2d_map_cmdlist_gem()
721 if (!g2d_check_buf_desc_is_valid(g2d, buf_desc, in g2d_map_cmdlist_gem()
739 if (!g2d_check_buf_desc_is_valid(g2d, buf_desc, in g2d_map_cmdlist_gem()
746 addr = g2d_userptr_get_dma_addr(g2d, in g2d_map_cmdlist_gem()
768 static void g2d_unmap_cmdlist_gem(struct g2d_data *g2d, in g2d_unmap_cmdlist_gem() argument
788 g2d_userptr_put_dma_addr(g2d, obj, false); in g2d_unmap_cmdlist_gem()
799 static void g2d_dma_start(struct g2d_data *g2d, in g2d_dma_start() argument
806 set_bit(G2D_BIT_ENGINE_BUSY, &g2d->flags); in g2d_dma_start()
807 writel_relaxed(node->dma_addr, g2d->regs + G2D_DMA_SFR_BASE_ADDR); in g2d_dma_start()
808 writel_relaxed(G2D_DMA_START, g2d->regs + G2D_DMA_COMMAND); in g2d_dma_start()
811 static struct g2d_runqueue_node *g2d_get_runqueue_node(struct g2d_data *g2d) in g2d_get_runqueue_node() argument
815 if (list_empty(&g2d->runqueue)) in g2d_get_runqueue_node()
818 runqueue_node = list_first_entry(&g2d->runqueue, in g2d_get_runqueue_node()
824 static void g2d_free_runqueue_node(struct g2d_data *g2d, in g2d_free_runqueue_node() argument
829 mutex_lock(&g2d->cmdlist_mutex); in g2d_free_runqueue_node()
835 g2d_unmap_cmdlist_gem(g2d, node, runqueue_node->filp); in g2d_free_runqueue_node()
836 list_splice_tail_init(&runqueue_node->run_cmdlist, &g2d->free_cmdlist); in g2d_free_runqueue_node()
837 mutex_unlock(&g2d->cmdlist_mutex); in g2d_free_runqueue_node()
839 kmem_cache_free(g2d->runqueue_slab, runqueue_node); in g2d_free_runqueue_node()
849 static void g2d_remove_runqueue_nodes(struct g2d_data *g2d, struct drm_file *file) in g2d_remove_runqueue_nodes() argument
853 if (list_empty(&g2d->runqueue)) in g2d_remove_runqueue_nodes()
856 list_for_each_entry_safe(node, n, &g2d->runqueue, list) { in g2d_remove_runqueue_nodes()
861 g2d_free_runqueue_node(g2d, node); in g2d_remove_runqueue_nodes()
867 struct g2d_data *g2d = container_of(work, struct g2d_data, in g2d_runqueue_worker() local
875 if (test_bit(G2D_BIT_ENGINE_BUSY, &g2d->flags)) in g2d_runqueue_worker()
878 mutex_lock(&g2d->runqueue_mutex); in g2d_runqueue_worker()
880 runqueue_node = g2d->runqueue_node; in g2d_runqueue_worker()
881 g2d->runqueue_node = NULL; in g2d_runqueue_worker()
884 pm_runtime_mark_last_busy(g2d->dev); in g2d_runqueue_worker()
885 pm_runtime_put_autosuspend(g2d->dev); in g2d_runqueue_worker()
889 g2d_free_runqueue_node(g2d, runqueue_node); in g2d_runqueue_worker()
892 if (!test_bit(G2D_BIT_SUSPEND_RUNQUEUE, &g2d->flags)) { in g2d_runqueue_worker()
893 g2d->runqueue_node = g2d_get_runqueue_node(g2d); in g2d_runqueue_worker()
895 if (g2d->runqueue_node) { in g2d_runqueue_worker()
898 ret = pm_runtime_resume_and_get(g2d->dev); in g2d_runqueue_worker()
900 dev_err(g2d->dev, "failed to enable G2D device.\n"); in g2d_runqueue_worker()
904 g2d_dma_start(g2d, g2d->runqueue_node); in g2d_runqueue_worker()
909 mutex_unlock(&g2d->runqueue_mutex); in g2d_runqueue_worker()
912 static void g2d_finish_event(struct g2d_data *g2d, u32 cmdlist_no) in g2d_finish_event() argument
914 struct drm_device *drm_dev = g2d->drm_dev; in g2d_finish_event()
915 struct g2d_runqueue_node *runqueue_node = g2d->runqueue_node; in g2d_finish_event()
935 struct g2d_data *g2d = dev_id; in g2d_irq_handler() local
938 pending = readl_relaxed(g2d->regs + G2D_INTC_PEND); in g2d_irq_handler()
940 writel_relaxed(pending, g2d->regs + G2D_INTC_PEND); in g2d_irq_handler()
943 u32 cmdlist_no = readl_relaxed(g2d->regs + G2D_DMA_STATUS); in g2d_irq_handler()
948 g2d_finish_event(g2d, cmdlist_no); in g2d_irq_handler()
950 writel_relaxed(0, g2d->regs + G2D_DMA_HOLD_CMD); in g2d_irq_handler()
953 g2d->regs + G2D_DMA_COMMAND); in g2d_irq_handler()
958 clear_bit(G2D_BIT_ENGINE_BUSY, &g2d->flags); in g2d_irq_handler()
959 queue_work(g2d->g2d_workq, &g2d->runqueue_work); in g2d_irq_handler()
974 static void g2d_wait_finish(struct g2d_data *g2d, struct drm_file *file) in g2d_wait_finish() argument
976 struct device *dev = g2d->dev; in g2d_wait_finish()
981 mutex_lock(&g2d->runqueue_mutex); in g2d_wait_finish()
984 if (!g2d->runqueue_node) in g2d_wait_finish()
987 runqueue_node = g2d->runqueue_node; in g2d_wait_finish()
993 mutex_unlock(&g2d->runqueue_mutex); in g2d_wait_finish()
996 while (tries-- && (g2d->runqueue_node == runqueue_node)) in g2d_wait_finish()
999 mutex_lock(&g2d->runqueue_mutex); in g2d_wait_finish()
1001 if (g2d->runqueue_node != runqueue_node) in g2d_wait_finish()
1005 g2d_hw_reset(g2d); in g2d_wait_finish()
1017 g2d_free_runqueue_node(g2d, runqueue_node); in g2d_wait_finish()
1020 mutex_unlock(&g2d->runqueue_mutex); in g2d_wait_finish()
1023 static int g2d_check_reg_offset(struct g2d_data *g2d, in g2d_check_reg_offset() argument
1056 reg_type = g2d_get_reg_type(g2d, reg_offset); in g2d_check_reg_offset()
1070 reg_type = g2d_get_reg_type(g2d, reg_offset); in g2d_check_reg_offset()
1080 reg_type = g2d_get_reg_type(g2d, reg_offset); in g2d_check_reg_offset()
1092 reg_type = g2d_get_reg_type(g2d, reg_offset); in g2d_check_reg_offset()
1105 reg_type = g2d_get_reg_type(g2d, reg_offset); in g2d_check_reg_offset()
1123 dev_err(g2d->dev, "Bad register offset: 0x%lx\n", cmdlist->data[index]); in g2d_check_reg_offset()
1144 struct g2d_data *g2d = dev_get_drvdata(priv->g2d_dev); in exynos_g2d_set_cmdlist_ioctl() local
1153 node = g2d_get_cmdlist(g2d); in exynos_g2d_set_cmdlist_ioctl()
1164 dev_err(g2d->dev, "number of submitted G2D commands exceeds limit\n"); in exynos_g2d_set_cmdlist_ioctl()
1232 dev_err(g2d->dev, "cmdlist size is too big\n"); in exynos_g2d_set_cmdlist_ioctl()
1247 ret = g2d_check_reg_offset(g2d, node, req->cmd_nr, false); in exynos_g2d_set_cmdlist_ioctl()
1266 ret = g2d_check_reg_offset(g2d, node, req->cmd_buf_nr, true); in exynos_g2d_set_cmdlist_ioctl()
1270 ret = g2d_map_cmdlist_gem(g2d, node, drm_dev, file); in exynos_g2d_set_cmdlist_ioctl()
1289 g2d_unmap_cmdlist_gem(g2d, node, file); in exynos_g2d_set_cmdlist_ioctl()
1294 g2d_put_cmdlist(g2d, node); in exynos_g2d_set_cmdlist_ioctl()
1303 struct g2d_data *g2d = dev_get_drvdata(priv->g2d_dev); in exynos_g2d_exec_ioctl() local
1309 runqueue_node = kmem_cache_alloc(g2d->runqueue_slab, GFP_KERNEL); in exynos_g2d_exec_ioctl()
1324 dev_err(g2d->dev, "there is no inuse cmdlist\n"); in exynos_g2d_exec_ioctl()
1325 kmem_cache_free(g2d->runqueue_slab, runqueue_node); in exynos_g2d_exec_ioctl()
1329 mutex_lock(&g2d->runqueue_mutex); in exynos_g2d_exec_ioctl()
1332 list_add_tail(&runqueue_node->list, &g2d->runqueue); in exynos_g2d_exec_ioctl()
1333 mutex_unlock(&g2d->runqueue_mutex); in exynos_g2d_exec_ioctl()
1336 queue_work(g2d->g2d_workq, &g2d->runqueue_work); in exynos_g2d_exec_ioctl()
1342 g2d_free_runqueue_node(g2d, runqueue_node); in exynos_g2d_exec_ioctl()
1363 struct g2d_data *g2d; in g2d_close() local
1369 g2d = dev_get_drvdata(priv->g2d_dev); in g2d_close()
1372 mutex_lock(&g2d->runqueue_mutex); in g2d_close()
1373 g2d_remove_runqueue_nodes(g2d, file); in g2d_close()
1374 mutex_unlock(&g2d->runqueue_mutex); in g2d_close()
1381 g2d_wait_finish(g2d, file); in g2d_close()
1389 mutex_lock(&g2d->cmdlist_mutex); in g2d_close()
1391 g2d_unmap_cmdlist_gem(g2d, node, file); in g2d_close()
1392 list_move_tail(&node->list, &g2d->free_cmdlist); in g2d_close()
1394 mutex_unlock(&g2d->cmdlist_mutex); in g2d_close()
1397 g2d_userptr_free_all(g2d, file); in g2d_close()
1402 struct g2d_data *g2d = dev_get_drvdata(dev); in g2d_bind() local
1407 g2d->drm_dev = drm_dev; in g2d_bind()
1410 ret = g2d_init_cmdlist(g2d); in g2d_bind()
1416 ret = exynos_drm_register_dma(drm_dev, dev, &g2d->dma_priv); in g2d_bind()
1419 g2d_fini_cmdlist(g2d); in g2d_bind()
1431 struct g2d_data *g2d = dev_get_drvdata(dev); in g2d_unbind() local
1436 set_bit(G2D_BIT_SUSPEND_RUNQUEUE, &g2d->flags); in g2d_unbind()
1437 g2d_wait_finish(g2d, NULL); in g2d_unbind()
1440 cancel_work_sync(&g2d->runqueue_work); in g2d_unbind()
1441 exynos_drm_unregister_dma(g2d->drm_dev, dev, &g2d->dma_priv); in g2d_unbind()
1452 struct g2d_data *g2d; in g2d_probe() local
1455 g2d = devm_kzalloc(dev, sizeof(*g2d), GFP_KERNEL); in g2d_probe()
1456 if (!g2d) in g2d_probe()
1459 g2d->runqueue_slab = kmem_cache_create("g2d_runqueue_slab", in g2d_probe()
1461 if (!g2d->runqueue_slab) in g2d_probe()
1464 g2d->dev = dev; in g2d_probe()
1466 g2d->g2d_workq = create_singlethread_workqueue("g2d"); in g2d_probe()
1467 if (!g2d->g2d_workq) { in g2d_probe()
1473 INIT_WORK(&g2d->runqueue_work, g2d_runqueue_worker); in g2d_probe()
1474 INIT_LIST_HEAD(&g2d->free_cmdlist); in g2d_probe()
1475 INIT_LIST_HEAD(&g2d->runqueue); in g2d_probe()
1477 mutex_init(&g2d->cmdlist_mutex); in g2d_probe()
1478 mutex_init(&g2d->runqueue_mutex); in g2d_probe()
1480 g2d->gate_clk = devm_clk_get(dev, "fimg2d"); in g2d_probe()
1481 if (IS_ERR(g2d->gate_clk)) { in g2d_probe()
1483 ret = PTR_ERR(g2d->gate_clk); in g2d_probe()
1490 clear_bit(G2D_BIT_SUSPEND_RUNQUEUE, &g2d->flags); in g2d_probe()
1491 clear_bit(G2D_BIT_ENGINE_BUSY, &g2d->flags); in g2d_probe()
1493 g2d->regs = devm_platform_ioremap_resource(pdev, 0); in g2d_probe()
1494 if (IS_ERR(g2d->regs)) { in g2d_probe()
1495 ret = PTR_ERR(g2d->regs); in g2d_probe()
1499 g2d->irq = platform_get_irq(pdev, 0); in g2d_probe()
1500 if (g2d->irq < 0) { in g2d_probe()
1501 ret = g2d->irq; in g2d_probe()
1505 ret = devm_request_irq(dev, g2d->irq, g2d_irq_handler, 0, in g2d_probe()
1506 "drm_g2d", g2d); in g2d_probe()
1512 g2d->max_pool = MAX_POOL; in g2d_probe()
1514 platform_set_drvdata(pdev, g2d); in g2d_probe()
1527 destroy_workqueue(g2d->g2d_workq); in g2d_probe()
1529 kmem_cache_destroy(g2d->runqueue_slab); in g2d_probe()
1535 struct g2d_data *g2d = platform_get_drvdata(pdev); in g2d_remove() local
1540 g2d_remove_runqueue_nodes(g2d, NULL); in g2d_remove()
1545 g2d_fini_cmdlist(g2d); in g2d_remove()
1546 destroy_workqueue(g2d->g2d_workq); in g2d_remove()
1547 kmem_cache_destroy(g2d->runqueue_slab); in g2d_remove()
1552 struct g2d_data *g2d = dev_get_drvdata(dev); in g2d_suspend() local
1558 set_bit(G2D_BIT_SUSPEND_RUNQUEUE, &g2d->flags); in g2d_suspend()
1559 g2d_wait_finish(g2d, NULL); in g2d_suspend()
1560 flush_work(&g2d->runqueue_work); in g2d_suspend()
1567 struct g2d_data *g2d = dev_get_drvdata(dev); in g2d_resume() local
1569 clear_bit(G2D_BIT_SUSPEND_RUNQUEUE, &g2d->flags); in g2d_resume()
1570 queue_work(g2d->g2d_workq, &g2d->runqueue_work); in g2d_resume()
1577 struct g2d_data *g2d = dev_get_drvdata(dev); in g2d_runtime_suspend() local
1579 clk_disable_unprepare(g2d->gate_clk); in g2d_runtime_suspend()
1586 struct g2d_data *g2d = dev_get_drvdata(dev); in g2d_runtime_resume() local
1589 ret = clk_prepare_enable(g2d->gate_clk); in g2d_runtime_resume()