brintos

brintos / linux-shallow public Read only

0
0
Text · 4.7 KiB · bb13267 Raw
211 lines · c
1// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)2/*3 * Wave5 series multi-standard codec IP - low level access functions4 *5 * Copyright (C) 2021-2023 CHIPS&MEDIA INC6 */7 8#include <linux/bug.h>9#include "wave5-vdi.h"10#include "wave5-vpu.h"11#include "wave5-regdefine.h"12#include <linux/delay.h>13 14static int wave5_vdi_allocate_common_memory(struct device *dev)15{16	struct vpu_device *vpu_dev = dev_get_drvdata(dev);17 18	if (!vpu_dev->common_mem.vaddr) {19		int ret;20 21		if (vpu_dev->product_code == WAVE515_CODE)22			vpu_dev->common_mem.size = WAVE515_SIZE_COMMON;23		else24			vpu_dev->common_mem.size = WAVE521_SIZE_COMMON;25 26		ret = wave5_vdi_allocate_dma_memory(vpu_dev, &vpu_dev->common_mem);27		if (ret) {28			dev_err(dev, "unable to allocate common buffer\n");29			return ret;30		}31	}32 33	dev_dbg(dev, "[VDI] common_mem: daddr=%pad size=%zu vaddr=0x%p\n",34		&vpu_dev->common_mem.daddr, vpu_dev->common_mem.size, vpu_dev->common_mem.vaddr);35 36	return 0;37}38 39int wave5_vdi_init(struct device *dev)40{41	struct vpu_device *vpu_dev = dev_get_drvdata(dev);42	int ret;43 44	ret = wave5_vdi_allocate_common_memory(dev);45	if (ret < 0) {46		dev_err(dev, "[VDI] failed to get vpu common buffer from driver\n");47		return ret;48	}49 50	if (!PRODUCT_CODE_W_SERIES(vpu_dev->product_code)) {51		WARN_ONCE(1, "unsupported product code: 0x%x\n", vpu_dev->product_code);52		return -EOPNOTSUPP;53	}54 55	/* if BIT processor is not running. */56	if (wave5_vdi_read_register(vpu_dev, W5_VCPU_CUR_PC) == 0) {57		int i;58 59		for (i = 0; i < 64; i++)60			wave5_vdi_write_register(vpu_dev, (i * 4) + 0x100, 0x0);61	}62 63	dev_dbg(dev, "[VDI] driver initialized successfully\n");64 65	return 0;66}67 68int wave5_vdi_release(struct device *dev)69{70	struct vpu_device *vpu_dev = dev_get_drvdata(dev);71 72	vpu_dev->vdb_register = NULL;73	wave5_vdi_free_dma_memory(vpu_dev, &vpu_dev->common_mem);74 75	return 0;76}77 78void wave5_vdi_write_register(struct vpu_device *vpu_dev, u32 addr, u32 data)79{80	writel(data, vpu_dev->vdb_register + addr);81}82 83unsigned int wave5_vdi_read_register(struct vpu_device *vpu_dev, u32 addr)84{85	return readl(vpu_dev->vdb_register + addr);86}87 88int wave5_vdi_clear_memory(struct vpu_device *vpu_dev, struct vpu_buf *vb)89{90	if (!vb || !vb->vaddr) {91		dev_err(vpu_dev->dev, "%s: unable to clear unmapped buffer\n", __func__);92		return -EINVAL;93	}94 95	memset(vb->vaddr, 0, vb->size);96	return vb->size;97}98 99int wave5_vdi_write_memory(struct vpu_device *vpu_dev, struct vpu_buf *vb, size_t offset,100			   u8 *data, size_t len)101{102	if (!vb || !vb->vaddr) {103		dev_err(vpu_dev->dev, "%s: unable to write to unmapped buffer\n", __func__);104		return -EINVAL;105	}106 107	if (offset > vb->size || len > vb->size || offset + len > vb->size) {108		dev_err(vpu_dev->dev, "%s: buffer too small\n", __func__);109		return -ENOSPC;110	}111 112	memcpy(vb->vaddr + offset, data, len);113 114	return len;115}116 117int wave5_vdi_allocate_dma_memory(struct vpu_device *vpu_dev, struct vpu_buf *vb)118{119	void *vaddr;120	dma_addr_t daddr;121 122	if (!vb->size) {123		dev_err(vpu_dev->dev, "%s: requested size==0\n", __func__);124		return -EINVAL;125	}126 127	vaddr = dma_alloc_coherent(vpu_dev->dev, vb->size, &daddr, GFP_KERNEL);128	if (!vaddr)129		return -ENOMEM;130	vb->vaddr = vaddr;131	vb->daddr = daddr;132 133	return 0;134}135 136int wave5_vdi_free_dma_memory(struct vpu_device *vpu_dev, struct vpu_buf *vb)137{138	if (vb->size == 0)139		return -EINVAL;140 141	if (!vb->vaddr)142		dev_err(vpu_dev->dev, "%s: requested free of unmapped buffer\n", __func__);143	else144		dma_free_coherent(vpu_dev->dev, vb->size, vb->vaddr, vb->daddr);145 146	memset(vb, 0, sizeof(*vb));147 148	return 0;149}150 151int wave5_vdi_allocate_array(struct vpu_device *vpu_dev, struct vpu_buf *array, unsigned int count,152			     size_t size)153{154	struct vpu_buf vb_buf;155	int i, ret = 0;156 157	vb_buf.size = size;158 159	for (i = 0; i < count; i++) {160		if (array[i].size == size)161			continue;162 163		if (array[i].size != 0)164			wave5_vdi_free_dma_memory(vpu_dev, &array[i]);165 166		ret = wave5_vdi_allocate_dma_memory(vpu_dev, &vb_buf);167		if (ret)168			return -ENOMEM;169		array[i] = vb_buf;170	}171 172	for (i = count; i < MAX_REG_FRAME; i++)173		wave5_vdi_free_dma_memory(vpu_dev, &array[i]);174 175	return 0;176}177 178void wave5_vdi_allocate_sram(struct vpu_device *vpu_dev)179{180	struct vpu_buf *vb = &vpu_dev->sram_buf;181	dma_addr_t daddr;182	void *vaddr;183	size_t size;184 185	if (!vpu_dev->sram_pool || vb->vaddr)186		return;187 188	size = min_t(size_t, vpu_dev->sram_size, gen_pool_avail(vpu_dev->sram_pool));189	vaddr = gen_pool_dma_alloc(vpu_dev->sram_pool, size, &daddr);190	if (vaddr) {191		vb->vaddr = vaddr;192		vb->daddr = daddr;193		vb->size = size;194	}195 196	dev_dbg(vpu_dev->dev, "%s: sram daddr: %pad, size: %zu, vaddr: 0x%p\n",197		__func__, &vb->daddr, vb->size, vb->vaddr);198}199 200void wave5_vdi_free_sram(struct vpu_device *vpu_dev)201{202	struct vpu_buf *vb = &vpu_dev->sram_buf;203 204	if (!vb->size || !vb->vaddr)205		return;206 207	gen_pool_free(vpu_dev->sram_pool, (unsigned long)vb->vaddr, vb->size);208 209	memset(vb, 0, sizeof(*vb));210}211