xref: /linux/drivers/media/platform/chips-media/wave5/wave5-vdi.c (revision 55d0969c451159cff86949b38c39171cab962069)
1 // SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
2 /*
3  * Wave5 series multi-standard codec IP - low level access functions
4  *
5  * Copyright (C) 2021-2023 CHIPS&MEDIA INC
6  */
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 
14 static 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 		else
24 			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 
39 int 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 
68 int 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 
78 void wave5_vdi_write_register(struct vpu_device *vpu_dev, u32 addr, u32 data)
79 {
80 	writel(data, vpu_dev->vdb_register + addr);
81 }
82 
83 unsigned int wave5_vdi_read_register(struct vpu_device *vpu_dev, u32 addr)
84 {
85 	return readl(vpu_dev->vdb_register + addr);
86 }
87 
88 int 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 
99 int 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 
117 int 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 
136 int 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 	else
144 		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 
151 int 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 
178 void 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 
200 void 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