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  		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  
wave5_vdi_init(struct device * dev)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  
wave5_vdi_release(struct device * dev)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  
wave5_vdi_write_register(struct vpu_device * vpu_dev,u32 addr,u32 data)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  
wave5_vdi_read_register(struct vpu_device * vpu_dev,u32 addr)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  
wave5_vdi_clear_memory(struct vpu_device * vpu_dev,struct vpu_buf * vb)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  
wave5_vdi_write_memory(struct vpu_device * vpu_dev,struct vpu_buf * vb,size_t offset,u8 * data,size_t len)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  
wave5_vdi_allocate_dma_memory(struct vpu_device * vpu_dev,struct vpu_buf * vb)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  
wave5_vdi_free_dma_memory(struct vpu_device * vpu_dev,struct vpu_buf * vb)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  
wave5_vdi_allocate_array(struct vpu_device * vpu_dev,struct vpu_buf * array,unsigned int count,size_t size)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  
wave5_vdi_allocate_sram(struct vpu_device * vpu_dev)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  
wave5_vdi_free_sram(struct vpu_device * vpu_dev)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