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