File Index
Files and directories
Sign in
FILE

wave5-vdi.c

File preview with syntax highlighting.

linux-6.19.14/drivers/media/platform/chips-media/wave5/wave5-vdi.c C
  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
 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		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
 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	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
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}
~/ Read-only file preview.