Lines Matching full:vpu

23  * VPU (video processor unit) is a tiny processor controlling video hardware
25 * VPU interfaces with other blocks by share memory and interrupt.
43 /* the size of share buffer between Host and VPU */
63 /* vpu inter-processor communication interrupt */
67 * enum vpu_fw_type - VPU firmware type
79 * struct vpu_mem - VPU extended program/data memory information
81 * @va: the kernel virtual memory address of VPU extended memory
82 * @pa: the physical memory address of VPU extended memory
91 * struct vpu_regs - VPU TCM and configuration registers
93 * @tcm: the register for VPU Tightly-Coupled Memory
94 * @cfg: the register for VPU configuration
95 * @irq: the irq number for VPU interrupt
104 * struct vpu_wdt_handler - VPU watchdog reset handler
115 * struct vpu_wdt - VPU watchdog workqueue
117 * @handler: VPU watchdog reset handler
118 * @ws: workstruct for VPU watchdog
119 * @wq: workqueue for VPU watchdog
128 * struct vpu_run - VPU initialization status
130 * @signaled: the signal of vpu initialization completed
131 * @fw_ver: VPU firmware version
136 * @wq: wait queue for VPU initialization status
147 * struct vpu_ipi_desc - VPU IPI descriptor
161 * AP and VPU
174 * struct mtk_vpu - vpu driver data
175 * @extmem: VPU extended memory information
176 * @reg: VPU TCM and configuration registers
177 * @run: VPU initialization status
178 * @wdt: VPU watchdog workqueue
179 * @ipi_desc: VPU IPI descriptor
180 * @recv_buf: VPU DTCM share buffer for receiving. The
182 * @send_buf: VPU DTCM share buffer for sending
183 * @dev: VPU struct device
184 * @clk: VPU clock on/off
185 * @fw_loaded: indicate VPU firmware loaded
186 * @enable_4GB: VPU 4GB mode on/off
188 * one client to use VPU service at a time. For example,
189 * suppose a client is using VPU to decode VP8.
193 * disabled if no other client is using VPU service
199 * interrupt to VPU
214 struct mutex vpu_mutex; /* for protecting vpu data data structure */
220 static inline void vpu_cfg_writel(struct mtk_vpu *vpu, u32 val, u32 offset) in vpu_cfg_writel() argument
222 writel(val, vpu->reg.cfg + offset); in vpu_cfg_writel()
225 static inline u32 vpu_cfg_readl(struct mtk_vpu *vpu, u32 offset) in vpu_cfg_readl() argument
227 return readl(vpu->reg.cfg + offset); in vpu_cfg_readl()
230 static inline bool vpu_running(struct mtk_vpu *vpu) in vpu_running() argument
232 return vpu_cfg_readl(vpu, VPU_RESET) & BIT(0); in vpu_running()
235 static void vpu_clock_disable(struct mtk_vpu *vpu) in vpu_clock_disable() argument
237 /* Disable VPU watchdog */ in vpu_clock_disable()
238 mutex_lock(&vpu->vpu_mutex); in vpu_clock_disable()
239 if (!--vpu->wdt_refcnt) in vpu_clock_disable()
240 vpu_cfg_writel(vpu, in vpu_clock_disable()
241 vpu_cfg_readl(vpu, VPU_WDT_REG) & ~(1L << 31), in vpu_clock_disable()
243 mutex_unlock(&vpu->vpu_mutex); in vpu_clock_disable()
245 clk_disable(vpu->clk); in vpu_clock_disable()
248 static int vpu_clock_enable(struct mtk_vpu *vpu) in vpu_clock_enable() argument
252 ret = clk_enable(vpu->clk); in vpu_clock_enable()
255 /* Enable VPU watchdog */ in vpu_clock_enable()
256 mutex_lock(&vpu->vpu_mutex); in vpu_clock_enable()
257 if (!vpu->wdt_refcnt++) in vpu_clock_enable()
258 vpu_cfg_writel(vpu, in vpu_clock_enable()
259 vpu_cfg_readl(vpu, VPU_WDT_REG) | (1L << 31), in vpu_clock_enable()
261 mutex_unlock(&vpu->vpu_mutex); in vpu_clock_enable()
270 struct mtk_vpu *vpu = platform_get_drvdata(pdev); in vpu_ipi_register() local
273 if (!vpu) { in vpu_ipi_register()
274 dev_err(&pdev->dev, "vpu device in not ready\n"); in vpu_ipi_register()
279 ipi_desc = vpu->ipi_desc; in vpu_ipi_register()
286 dev_err(&pdev->dev, "register vpu ipi id %d with invalid arguments\n", in vpu_ipi_register()
296 struct mtk_vpu *vpu = platform_get_drvdata(pdev); in vpu_ipi_send() local
297 struct share_obj __iomem *send_obj = vpu->send_buf; in vpu_ipi_send()
303 dev_err(vpu->dev, "failed to send ipi message\n"); in vpu_ipi_send()
307 ret = vpu_clock_enable(vpu); in vpu_ipi_send()
309 dev_err(vpu->dev, "failed to enable vpu clock\n"); in vpu_ipi_send()
312 if (!vpu_running(vpu)) { in vpu_ipi_send()
313 dev_err(vpu->dev, "vpu_ipi_send: VPU is not running\n"); in vpu_ipi_send()
318 mutex_lock(&vpu->vpu_mutex); in vpu_ipi_send()
320 /* Wait until VPU receives the last command */ in vpu_ipi_send()
324 dev_err(vpu->dev, "vpu_ipi_send: IPI timeout!\n"); in vpu_ipi_send()
328 } while (vpu_cfg_readl(vpu, HOST_TO_VPU)); in vpu_ipi_send()
334 vpu->ipi_id_ack[id] = false; in vpu_ipi_send()
335 /* send the command to VPU */ in vpu_ipi_send()
336 vpu_cfg_writel(vpu, 0x1, HOST_TO_VPU); in vpu_ipi_send()
338 mutex_unlock(&vpu->vpu_mutex); in vpu_ipi_send()
340 /* wait for VPU's ACK */ in vpu_ipi_send()
342 ret = wait_event_timeout(vpu->ack_wq, vpu->ipi_id_ack[id], timeout); in vpu_ipi_send()
343 vpu->ipi_id_ack[id] = false; in vpu_ipi_send()
345 dev_err(vpu->dev, "vpu ipi %d ack time out !", id); in vpu_ipi_send()
349 vpu_clock_disable(vpu); in vpu_ipi_send()
354 mutex_unlock(&vpu->vpu_mutex); in vpu_ipi_send()
356 vpu_clock_disable(vpu); in vpu_ipi_send()
365 struct mtk_vpu *vpu = container_of(wdt, struct mtk_vpu, wdt); in vpu_wdt_reset_func() local
369 dev_info(vpu->dev, "vpu reset\n"); in vpu_wdt_reset_func()
370 ret = vpu_clock_enable(vpu); in vpu_wdt_reset_func()
372 dev_err(vpu->dev, "[VPU] wdt enables clock failed %d\n", ret); in vpu_wdt_reset_func()
375 mutex_lock(&vpu->vpu_mutex); in vpu_wdt_reset_func()
376 vpu_cfg_writel(vpu, 0x0, VPU_RESET); in vpu_wdt_reset_func()
377 vpu->fw_loaded = false; in vpu_wdt_reset_func()
378 mutex_unlock(&vpu->vpu_mutex); in vpu_wdt_reset_func()
379 vpu_clock_disable(vpu); in vpu_wdt_reset_func()
384 dev_dbg(vpu->dev, "wdt handler func %d\n", index); in vpu_wdt_reset_func()
393 struct mtk_vpu *vpu = platform_get_drvdata(pdev); in vpu_wdt_reg_handler() local
396 if (!vpu) { in vpu_wdt_reg_handler()
397 dev_err(&pdev->dev, "vpu device in not ready\n"); in vpu_wdt_reg_handler()
401 handler = vpu->wdt.handler; in vpu_wdt_reg_handler()
404 dev_dbg(vpu->dev, "wdt register id %d\n", id); in vpu_wdt_reg_handler()
405 mutex_lock(&vpu->vpu_mutex); in vpu_wdt_reg_handler()
408 mutex_unlock(&vpu->vpu_mutex); in vpu_wdt_reg_handler()
412 dev_err(vpu->dev, "register vpu wdt handler failed\n"); in vpu_wdt_reg_handler()
419 struct mtk_vpu *vpu = platform_get_drvdata(pdev); in vpu_get_vdec_hw_capa() local
421 return vpu->run.dec_capability; in vpu_get_vdec_hw_capa()
427 struct mtk_vpu *vpu = platform_get_drvdata(pdev); in vpu_get_venc_hw_capa() local
429 return vpu->run.enc_capability; in vpu_get_venc_hw_capa()
436 struct mtk_vpu *vpu = platform_get_drvdata(pdev); in vpu_mapping_dm_addr() local
440 dev_err(vpu->dev, "invalid virtual data memory address\n"); in vpu_mapping_dm_addr()
445 return (__force void *)(dtcm_dmem_addr + vpu->reg.tcm + in vpu_mapping_dm_addr()
448 return vpu->extmem[D_FW].va + (dtcm_dmem_addr - VPU_DTCM_SIZE); in vpu_mapping_dm_addr()
458 vpu_node = of_parse_phandle(dev->of_node, "mediatek,vpu", 0); in vpu_get_plat_device()
460 dev_err(dev, "can't get vpu node\n"); in vpu_get_plat_device()
467 dev_err(dev, "vpu pdev failed\n"); in vpu_get_plat_device()
475 /* load vpu program/data memory */
476 static int load_requested_vpu(struct mtk_vpu *vpu, in load_requested_vpu() argument
489 ret = request_firmware(&vpu_fw, fw_new_name, vpu->dev); in load_requested_vpu()
491 dev_info(vpu->dev, "Failed to load %s, %d, retry\n", in load_requested_vpu()
494 ret = request_firmware(&vpu_fw, fw_name, vpu->dev); in load_requested_vpu()
496 dev_err(vpu->dev, "Failed to load %s, %d\n", fw_name, in load_requested_vpu()
503 dev_err(vpu->dev, "fw %s size %zu is abnormal\n", fw_name, in load_requested_vpu()
508 dev_dbg(vpu->dev, "Downloaded fw %s size: %zu.\n", in load_requested_vpu()
511 /* reset VPU */ in load_requested_vpu()
512 vpu_cfg_writel(vpu, 0x0, VPU_RESET); in load_requested_vpu()
516 dev_dbg(vpu->dev, "fw size %zu > limited fw size %zu\n", in load_requested_vpu()
519 dev_dbg(vpu->dev, "extra_fw_size %zu\n", extra_fw_size); in load_requested_vpu()
522 dest = (__force void *)vpu->reg.tcm; in load_requested_vpu()
528 dest = vpu->extmem[fw_type].va; in load_requested_vpu()
529 dev_dbg(vpu->dev, "download extended memory type %x\n", in load_requested_vpu()
541 struct mtk_vpu *vpu; in vpu_load_firmware() local
547 dev_err(dev, "VPU platform device is invalid\n"); in vpu_load_firmware()
551 vpu = platform_get_drvdata(pdev); in vpu_load_firmware()
552 run = &vpu->run; in vpu_load_firmware()
554 mutex_lock(&vpu->vpu_mutex); in vpu_load_firmware()
555 if (vpu->fw_loaded) { in vpu_load_firmware()
556 mutex_unlock(&vpu->vpu_mutex); in vpu_load_firmware()
559 mutex_unlock(&vpu->vpu_mutex); in vpu_load_firmware()
561 ret = vpu_clock_enable(vpu); in vpu_load_firmware()
567 mutex_lock(&vpu->vpu_mutex); in vpu_load_firmware()
570 dev_dbg(vpu->dev, "firmware request\n"); in vpu_load_firmware()
572 ret = load_requested_vpu(vpu, P_FW); in vpu_load_firmware()
579 ret = load_requested_vpu(vpu, D_FW); in vpu_load_firmware()
585 vpu->fw_loaded = true; in vpu_load_firmware()
586 /* boot up vpu */ in vpu_load_firmware()
587 vpu_cfg_writel(vpu, 0x1, VPU_RESET); in vpu_load_firmware()
595 dev_err(dev, "wait vpu initialization timeout!\n"); in vpu_load_firmware()
598 dev_err(dev, "wait vpu interrupted by a signal!\n"); in vpu_load_firmware()
603 dev_info(dev, "vpu is ready. Fw version %s\n", run->fw_ver); in vpu_load_firmware()
606 mutex_unlock(&vpu->vpu_mutex); in vpu_load_firmware()
607 vpu_clock_disable(vpu); in vpu_load_firmware()
615 struct mtk_vpu *vpu = priv; in vpu_init_ipi_handler() local
618 vpu->run.signaled = run->signaled; in vpu_init_ipi_handler()
619 strscpy(vpu->run.fw_ver, run->fw_ver, sizeof(vpu->run.fw_ver)); in vpu_init_ipi_handler()
620 vpu->run.dec_capability = run->dec_capability; in vpu_init_ipi_handler()
621 vpu->run.enc_capability = run->enc_capability; in vpu_init_ipi_handler()
622 wake_up_interruptible(&vpu->run.wq); in vpu_init_ipi_handler()
634 struct mtk_vpu *vpu = dev_get_drvdata(dev); in vpu_debug_read() local
636 ret = vpu_clock_enable(vpu); in vpu_debug_read()
638 dev_err(vpu->dev, "[VPU] enable clock failed %d\n", ret); in vpu_debug_read()
642 /* vpu register status */ in vpu_debug_read()
643 running = vpu_running(vpu); in vpu_debug_read()
644 pc = vpu_cfg_readl(vpu, VPU_PC_REG); in vpu_debug_read()
645 wdt = vpu_cfg_readl(vpu, VPU_WDT_REG); in vpu_debug_read()
646 host_to_vpu = vpu_cfg_readl(vpu, HOST_TO_VPU); in vpu_debug_read()
647 vpu_to_host = vpu_cfg_readl(vpu, VPU_TO_HOST); in vpu_debug_read()
648 vpu_clock_disable(vpu); in vpu_debug_read()
651 len = snprintf(buf, sizeof(buf), "VPU is running\n\n" in vpu_debug_read()
655 "Host to VPU: 0x%x\n" in vpu_debug_read()
656 "VPU to Host: 0x%x\n", in vpu_debug_read()
657 vpu->run.fw_ver, pc, wdt, in vpu_debug_read()
660 len = snprintf(buf, sizeof(buf), "VPU not running\n"); in vpu_debug_read()
672 static void vpu_free_ext_mem(struct mtk_vpu *vpu, u8 fw_type) in vpu_free_ext_mem() argument
674 struct device *dev = vpu->dev; in vpu_free_ext_mem()
677 dma_free_coherent(dev, fw_ext_size, vpu->extmem[fw_type].va, in vpu_free_ext_mem()
678 vpu->extmem[fw_type].pa); in vpu_free_ext_mem()
681 static int vpu_alloc_ext_mem(struct mtk_vpu *vpu, u32 fw_type) in vpu_alloc_ext_mem() argument
683 struct device *dev = vpu->dev; in vpu_alloc_ext_mem()
687 u32 offset_4gb = vpu->enable_4GB ? 0x40000000 : 0; in vpu_alloc_ext_mem()
689 vpu->extmem[fw_type].va = dma_alloc_coherent(dev, in vpu_alloc_ext_mem()
691 &vpu->extmem[fw_type].pa, in vpu_alloc_ext_mem()
693 if (!vpu->extmem[fw_type].va) { in vpu_alloc_ext_mem()
699 vpu_cfg_writel(vpu, 0x1, vpu_ext_mem0); in vpu_alloc_ext_mem()
700 vpu_cfg_writel(vpu, (vpu->extmem[fw_type].pa & 0xFFFFF000) + offset_4gb, in vpu_alloc_ext_mem()
705 (unsigned long long)vpu->extmem[fw_type].pa, in vpu_alloc_ext_mem()
706 vpu->extmem[fw_type].va); in vpu_alloc_ext_mem()
711 static void vpu_ipi_handler(struct mtk_vpu *vpu) in vpu_ipi_handler() argument
713 struct share_obj __iomem *rcv_obj = vpu->recv_buf; in vpu_ipi_handler()
714 struct vpu_ipi_desc *ipi_desc = vpu->ipi_desc; in vpu_ipi_handler()
723 vpu->ipi_id_ack[id] = true; in vpu_ipi_handler()
724 wake_up(&vpu->ack_wq); in vpu_ipi_handler()
727 dev_err(vpu->dev, "No such ipi id = %d\n", id); in vpu_ipi_handler()
731 static int vpu_ipi_init(struct mtk_vpu *vpu) in vpu_ipi_init() argument
733 /* Disable VPU to host interrupt */ in vpu_ipi_init()
734 vpu_cfg_writel(vpu, 0x0, VPU_TO_HOST); in vpu_ipi_init()
737 vpu->recv_buf = vpu->reg.tcm + VPU_DTCM_OFFSET; in vpu_ipi_init()
738 vpu->send_buf = vpu->recv_buf + 1; in vpu_ipi_init()
739 memset_io(vpu->recv_buf, 0, sizeof(struct share_obj)); in vpu_ipi_init()
740 memset_io(vpu->send_buf, 0, sizeof(struct share_obj)); in vpu_ipi_init()
747 struct mtk_vpu *vpu = priv; in vpu_irq_handler() local
756 ret = clk_enable(vpu->clk); in vpu_irq_handler()
758 dev_err(vpu->dev, "[VPU] enable clock failed %d\n", ret); in vpu_irq_handler()
761 vpu_to_host = vpu_cfg_readl(vpu, VPU_TO_HOST); in vpu_irq_handler()
763 vpu_ipi_handler(vpu); in vpu_irq_handler()
765 dev_err(vpu->dev, "vpu watchdog timeout! 0x%x", vpu_to_host); in vpu_irq_handler()
766 queue_work(vpu->wdt.wq, &vpu->wdt.ws); in vpu_irq_handler()
769 /* VPU won't send another interrupt until we set VPU_TO_HOST to 0. */ in vpu_irq_handler()
770 vpu_cfg_writel(vpu, 0x0, VPU_TO_HOST); in vpu_irq_handler()
771 clk_disable(vpu->clk); in vpu_irq_handler()
781 struct mtk_vpu *vpu; in mtk_vpu_probe() local
789 vpu = devm_kzalloc(dev, sizeof(*vpu), GFP_KERNEL); in mtk_vpu_probe()
790 if (!vpu) in mtk_vpu_probe()
793 vpu->dev = &pdev->dev; in mtk_vpu_probe()
795 vpu->reg.tcm = devm_ioremap_resource(dev, res); in mtk_vpu_probe()
796 if (IS_ERR((__force void *)vpu->reg.tcm)) in mtk_vpu_probe()
797 return PTR_ERR((__force void *)vpu->reg.tcm); in mtk_vpu_probe()
800 vpu->reg.cfg = devm_ioremap_resource(dev, res); in mtk_vpu_probe()
801 if (IS_ERR((__force void *)vpu->reg.cfg)) in mtk_vpu_probe()
802 return PTR_ERR((__force void *)vpu->reg.cfg); in mtk_vpu_probe()
804 /* Get VPU clock */ in mtk_vpu_probe()
805 vpu->clk = devm_clk_get(dev, "main"); in mtk_vpu_probe()
806 if (IS_ERR(vpu->clk)) { in mtk_vpu_probe()
807 dev_err(dev, "get vpu clock failed\n"); in mtk_vpu_probe()
808 return PTR_ERR(vpu->clk); in mtk_vpu_probe()
811 platform_set_drvdata(pdev, vpu); in mtk_vpu_probe()
813 ret = clk_prepare(vpu->clk); in mtk_vpu_probe()
815 dev_err(dev, "prepare vpu clock failed\n"); in mtk_vpu_probe()
819 /* VPU watchdog */ in mtk_vpu_probe()
820 vpu->wdt.wq = create_singlethread_workqueue("vpu_wdt"); in mtk_vpu_probe()
821 if (!vpu->wdt.wq) { in mtk_vpu_probe()
825 INIT_WORK(&vpu->wdt.ws, vpu_wdt_reset_func); in mtk_vpu_probe()
826 mutex_init(&vpu->vpu_mutex); in mtk_vpu_probe()
828 ret = vpu_clock_enable(vpu); in mtk_vpu_probe()
830 dev_err(dev, "enable vpu clock failed\n"); in mtk_vpu_probe()
834 dev_dbg(dev, "vpu ipi init\n"); in mtk_vpu_probe()
835 ret = vpu_ipi_init(vpu); in mtk_vpu_probe()
841 /* register vpu initialization IPI */ in mtk_vpu_probe()
843 "vpu_init", vpu); in mtk_vpu_probe()
855 vpu_cfg_writel(vpu, 0x2, VPU_TCM_CFG); in mtk_vpu_probe()
857 vpu->enable_4GB = !!(totalram_pages() > (SZ_2G >> PAGE_SHIFT)); in mtk_vpu_probe()
858 dev_info(dev, "4GB mode %u\n", vpu->enable_4GB); in mtk_vpu_probe()
860 if (vpu->enable_4GB) { in mtk_vpu_probe()
867 ret = vpu_alloc_ext_mem(vpu, D_FW); in mtk_vpu_probe()
873 ret = vpu_alloc_ext_mem(vpu, P_FW); in mtk_vpu_probe()
879 init_waitqueue_head(&vpu->run.wq); in mtk_vpu_probe()
880 init_waitqueue_head(&vpu->ack_wq); in mtk_vpu_probe()
888 vpu->reg.irq = platform_get_irq(pdev, 0); in mtk_vpu_probe()
889 ret = devm_request_irq(dev, vpu->reg.irq, vpu_irq_handler, 0, in mtk_vpu_probe()
890 pdev->name, vpu); in mtk_vpu_probe()
896 vpu_clock_disable(vpu); in mtk_vpu_probe()
902 vpu_free_ext_mem(vpu, P_FW); in mtk_vpu_probe()
904 vpu_free_ext_mem(vpu, D_FW); in mtk_vpu_probe()
910 memset(vpu->ipi_desc, 0, sizeof(struct vpu_ipi_desc) * IPI_MAX); in mtk_vpu_probe()
912 mutex_destroy(&vpu->vpu_mutex); in mtk_vpu_probe()
914 vpu_clock_disable(vpu); in mtk_vpu_probe()
916 destroy_workqueue(vpu->wdt.wq); in mtk_vpu_probe()
923 .compatible = "mediatek,mt8173-vpu",
931 struct mtk_vpu *vpu = platform_get_drvdata(pdev); in mtk_vpu_remove() local
936 if (vpu->wdt.wq) { in mtk_vpu_remove()
937 flush_workqueue(vpu->wdt.wq); in mtk_vpu_remove()
938 destroy_workqueue(vpu->wdt.wq); in mtk_vpu_remove()
940 vpu_free_ext_mem(vpu, P_FW); in mtk_vpu_remove()
941 vpu_free_ext_mem(vpu, D_FW); in mtk_vpu_remove()
942 mutex_destroy(&vpu->vpu_mutex); in mtk_vpu_remove()
943 clk_unprepare(vpu->clk); in mtk_vpu_remove()