9c602168cffce680b046da29f86949f26882b357
[platform/kernel/linux-starfive.git] / drivers / media / platform / chips-media / wave5 / wave5-vpu.c
1 // SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
2 /*
3  * Wave5 series multi-standard codec IP - platform driver
4  *
5  * Copyright (C) 2021 CHIPS&MEDIA INC
6  */
7 #include <linux/kernel.h>
8 #include <linux/module.h>
9 #include <linux/platform_device.h>
10 #include <linux/clk.h>
11 #include <linux/of_address.h>
12 #include <linux/firmware.h>
13 #include <linux/interrupt.h>
14 #include "wave5-vpu.h"
15 #include "wave5-regdefine.h"
16 #include "wave5-vpuconfig.h"
17 #include "wave5.h"
18
19 #define VPU_PLATFORM_DEVICE_NAME "vdec"
20 #define VPU_CLK_NAME "vcodec"
21
22 #define WAVE5_IS_ENC BIT(0)
23 #define WAVE5_IS_DEC BIT(1)
24
25 struct wave5_match_data {
26         int flags;
27         const char *fw_name;
28 };
29
30 int wave5_vpu_wait_interrupt(struct vpu_instance *inst, unsigned int timeout)
31 {
32         int ret;
33
34         ret = wait_for_completion_timeout(&inst->irq_done,
35                                           msecs_to_jiffies(timeout));
36         if (!ret)
37                 return -ETIMEDOUT;
38
39         reinit_completion(&inst->irq_done);
40
41         return 0;
42 }
43
44 static void wave5_vpu_get_interrupt_for_inst(struct vpu_instance *inst, u32 status)
45 {
46         struct vpu_device *dev = inst->dev;
47         u32 seq_done;
48         u32 cmd_done;
49         int val;
50
51         seq_done = wave5_vdi_readl(dev, W5_RET_SEQ_DONE_INSTANCE_INFO);
52         cmd_done = wave5_vdi_readl(dev, W5_RET_QUEUE_CMD_DONE_INST);
53
54         if (status & BIT(INT_WAVE5_INIT_SEQ)) {
55                 if (seq_done & BIT(inst->id)) {
56                         seq_done &= ~BIT(inst->id);
57                         wave5_vdi_write_register(dev, W5_RET_SEQ_DONE_INSTANCE_INFO, seq_done);
58                         val = BIT(INT_WAVE5_INIT_SEQ);
59                         kfifo_in(&inst->irq_status, &val, sizeof(int));
60                 }
61         }
62         if (status & BIT(INT_WAVE5_ENC_SET_PARAM)) {
63                 if (seq_done & BIT(inst->id)) {
64                         seq_done &= ~BIT(inst->id);
65                         wave5_vdi_write_register(dev, W5_RET_SEQ_DONE_INSTANCE_INFO, seq_done);
66                         val = BIT(INT_WAVE5_ENC_SET_PARAM);
67                         kfifo_in(&inst->irq_status, &val, sizeof(int));
68                 }
69         }
70         if (status & BIT(INT_WAVE5_DEC_PIC) ||
71             status & BIT(INT_WAVE5_ENC_PIC)) {
72                 if (cmd_done & BIT(inst->id)) {
73                         cmd_done &= ~BIT(inst->id);
74                         wave5_vdi_write_register(dev, W5_RET_QUEUE_CMD_DONE_INST, cmd_done);
75                         val = BIT(INT_WAVE5_DEC_PIC);
76                         kfifo_in(&inst->irq_status, &val, sizeof(int));
77                 }
78         }
79 }
80
81 static irqreturn_t wave5_vpu_irq(int irq, void *dev_id)
82 {
83         struct vpu_device *dev = dev_id;
84
85         if (wave5_vdi_readl(dev, W5_VPU_VPU_INT_STS)) {
86                 struct vpu_instance *inst;
87                 u32 irq_status = wave5_vdi_readl(dev, W5_VPU_VINT_REASON);
88
89                 list_for_each_entry(inst, &dev->instances, list) {
90                         wave5_vpu_get_interrupt_for_inst(inst, irq_status);
91                 }
92
93                 wave5_vdi_write_register(dev, W5_VPU_VINT_REASON_CLR, irq_status);
94                 wave5_vdi_write_register(dev, W5_VPU_VINT_CLEAR, 0x1);
95
96                 return IRQ_WAKE_THREAD;
97         }
98
99         return IRQ_HANDLED;
100 }
101
102 static irqreturn_t wave5_vpu_irq_thread(int irq, void *dev_id)
103 {
104         struct vpu_device *dev = dev_id;
105         struct vpu_instance *inst;
106         int irq_status, ret;
107         u32 val;
108
109         list_for_each_entry(inst, &dev->instances, list) {
110                 while (kfifo_len(&inst->irq_status)) {
111                         struct vpu_instance *curr;
112
113                         curr = v4l2_m2m_get_curr_priv(inst->v4l2_m2m_dev);
114                         if (curr) {
115                                 inst->ops->finish_process(inst);
116                         } else {
117                                 ret = kfifo_out(&inst->irq_status, &irq_status, sizeof(int));
118                                 if (!ret)
119                                         break;
120
121                                 val = wave5_vdi_readl(dev, W5_VPU_VINT_REASON_USR);
122                                 val &= ~irq_status;
123                                 wave5_vdi_write_register(dev, W5_VPU_VINT_REASON_USR, val);
124                                 complete(&inst->irq_done);
125                         }
126                 }
127         }
128
129         return IRQ_HANDLED;
130 }
131
132 static int wave5_vpu_load_firmware(struct device *dev, const char *fw_name)
133 {
134         const struct firmware *fw;
135         int ret;
136         u32 revision;
137         unsigned int product_id;
138
139         ret = request_firmware(&fw, fw_name, dev);
140         if (ret) {
141                 dev_err(dev, "request_firmware, fail: %d\n", ret);
142                 return ret;
143         }
144
145         ret = wave5_vpu_init_with_bitcode(dev, (u8 *)fw->data, fw->size);
146         if (ret) {
147                 dev_err(dev, "vpu_init_with_bitcode, fail: %d\n", ret);
148                 goto release_fw;
149         }
150         release_firmware(fw);
151
152         ret = wave5_vpu_get_version_info(dev, &revision, &product_id);
153         if (ret) {
154                 dev_err(dev, "vpu_get_version_info fail: %d\n", ret);
155                 goto err_without_release;
156         }
157
158         dev_dbg(dev, "%s: enum product_id: %08x, fw revision: %u\n",
159                 __func__, product_id, revision);
160
161         return 0;
162
163 release_fw:
164         release_firmware(fw);
165 err_without_release:
166         return ret;
167 }
168
169 static int wave5_vpu_probe(struct platform_device *pdev)
170 {
171         int ret;
172         struct vpu_device *dev;
173         struct device_node *np;
174         const struct wave5_match_data *match_data;
175         struct resource sram;
176
177         match_data = device_get_match_data(&pdev->dev);
178         if (!match_data) {
179                 dev_err(&pdev->dev, "missing device match data\n");
180                 return -EINVAL;
181         }
182
183         /* physical addresses limited to 32 bits */
184         dma_set_mask(&pdev->dev, DMA_BIT_MASK(32));
185         dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
186
187         dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
188         if (!dev)
189                 return -ENOMEM;
190
191         dev->vdb_register = devm_platform_ioremap_resource(pdev, 0);
192         if (IS_ERR(dev->vdb_register))
193                 return PTR_ERR(dev->vdb_register);
194         ida_init(&dev->inst_ida);
195
196         mutex_init(&dev->dev_lock);
197         mutex_init(&dev->hw_lock);
198         dev_set_drvdata(&pdev->dev, dev);
199         dev->dev = &pdev->dev;
200
201         ret = devm_clk_bulk_get_all(&pdev->dev, &dev->clks);
202
203         /* continue without clock, assume externally managed */
204         if (ret < 0) {
205                 dev_warn(&pdev->dev, "Getting clocks, fail: %d\n", ret);
206                 ret = 0;
207         }
208         dev->num_clks = ret;
209
210         ret = clk_bulk_prepare_enable(dev->num_clks, dev->clks);
211         if (ret) {
212                 dev_err(&pdev->dev, "Enabling clocks, fail: %d\n", ret);
213                 return ret;
214         }
215
216         np = of_parse_phandle(pdev->dev.of_node, "sram", 0);
217         if (!np) {
218                 dev_warn(&pdev->dev, "sram node not found\n");
219         } else {
220                 ret = of_address_to_resource(np, 0, &sram);
221                 if (ret) {
222                         dev_err(&pdev->dev, "sram resource not available\n");
223                         goto err_put_node;
224                 }
225                 dev->sram_buf.daddr = sram.start;
226                 dev->sram_buf.size = resource_size(&sram);
227                 dev_dbg(&pdev->dev, "%s: sram daddr: %pad, size: 0x%lx\n",
228                         __func__, &dev->sram_buf.daddr, dev->sram_buf.size);
229         }
230
231         dev->product_code = wave5_vdi_readl(dev, VPU_PRODUCT_CODE_REGISTER);
232         ret = wave5_vdi_init(&pdev->dev);
233         if (ret < 0) {
234                 dev_err(&pdev->dev, "wave5_vdi_init, fail: %d\n", ret);
235                 goto err_clk_dis;
236         }
237         dev->product = wave5_vpu_get_product_id(dev);
238
239         INIT_LIST_HEAD(&dev->instances);
240         ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev);
241         if (ret) {
242                 dev_err(&pdev->dev, "v4l2_device_register, fail: %d\n", ret);
243                 goto err_vdi_release;
244         }
245
246         if (match_data->flags & WAVE5_IS_DEC) {
247                 ret = wave5_vpu_dec_register_device(dev);
248                 if (ret) {
249                         dev_err(&pdev->dev, "wave5_vpu_dec_register_device, fail: %d\n", ret);
250                         goto err_v4l2_unregister;
251                 }
252         }
253         if (match_data->flags & WAVE5_IS_ENC) {
254                 ret = wave5_vpu_enc_register_device(dev);
255                 if (ret) {
256                         dev_err(&pdev->dev, "wave5_vpu_enc_register_device, fail: %d\n", ret);
257                         goto err_dec_unreg;
258                 }
259         }
260
261         dev->irq = platform_get_irq(pdev, 0);
262         if (dev->irq < 0) {
263                 dev_err(&pdev->dev, "failed to get irq resource\n");
264                 ret = -ENXIO;
265                 goto err_enc_unreg;
266         }
267
268         ret = devm_request_threaded_irq(&pdev->dev, dev->irq, wave5_vpu_irq,
269                                         wave5_vpu_irq_thread, 0, "vpu_irq", dev);
270         if (ret) {
271                 dev_err(&pdev->dev, "Register interrupt handler, fail: %d\n", ret);
272                 goto err_enc_unreg;
273         }
274
275         ret = wave5_vpu_load_firmware(&pdev->dev, match_data->fw_name);
276         if (ret) {
277                 dev_err(&pdev->dev, "wave5_vpu_load_firmware, fail: %d\n", ret);
278                 goto err_enc_unreg;
279         }
280
281         dev_dbg(&pdev->dev, "Added wave5 driver with caps: %s %s and product code: 0x%x\n",
282                 (match_data->flags & WAVE5_IS_ENC) ? "'ENCODE'" : "",
283                 (match_data->flags & WAVE5_IS_DEC) ? "'DECODE'" : "",
284                 dev->product_code);
285         return 0;
286
287 err_enc_unreg:
288         if (match_data->flags & WAVE5_IS_ENC)
289                 wave5_vpu_enc_unregister_device(dev);
290 err_dec_unreg:
291         if (match_data->flags & WAVE5_IS_DEC)
292                 wave5_vpu_dec_unregister_device(dev);
293 err_v4l2_unregister:
294         v4l2_device_unregister(&dev->v4l2_dev);
295 err_vdi_release:
296         wave5_vdi_release(&pdev->dev);
297 err_clk_dis:
298         clk_bulk_disable_unprepare(dev->num_clks, dev->clks);
299 err_put_node:
300         of_node_put(np);
301
302         return ret;
303 }
304
305 static int wave5_vpu_remove(struct platform_device *pdev)
306 {
307         struct vpu_device *dev = dev_get_drvdata(&pdev->dev);
308
309         clk_bulk_disable_unprepare(dev->num_clks, dev->clks);
310         wave5_vpu_enc_unregister_device(dev);
311         wave5_vpu_dec_unregister_device(dev);
312         v4l2_device_unregister(&dev->v4l2_dev);
313         wave5_vdi_release(&pdev->dev);
314         ida_destroy(&dev->inst_ida);
315
316         return 0;
317 }
318
319 static const struct wave5_match_data wave511_data = {
320         .flags = WAVE5_IS_DEC,
321         .fw_name = "wave511_dec_fw.bin",
322 };
323
324 static const struct wave5_match_data wave521_data = {
325         .flags = WAVE5_IS_ENC,
326         .fw_name = "wave521_enc_fw.bin",
327 };
328
329 static const struct wave5_match_data wave521c_data = {
330         .flags = WAVE5_IS_ENC | WAVE5_IS_DEC,
331         .fw_name = "wave521c_codec_fw.bin",
332 };
333
334 static const struct wave5_match_data default_match_data = {
335         .flags = WAVE5_IS_ENC | WAVE5_IS_DEC,
336         .fw_name = "chagall.bin",
337 };
338
339 static const struct of_device_id wave5_dt_ids[] = {
340         { .compatible = "cnm,cm511-vpu", .data = &wave511_data },
341         { .compatible = "cnm,cm517-vpu", .data = &default_match_data },
342         { .compatible = "cnm,cm521-vpu", .data = &wave521_data },
343         { .compatible = "cnm,cm521c-vpu", .data = &wave521c_data },
344         { .compatible = "cnm,cm521c-dual-vpu", .data = &wave521c_data },
345         { .compatible = "cnm,cm521e1-vpu", .data = &default_match_data },
346         { .compatible = "cnm,cm537-vpu", .data = &default_match_data },
347         { /* sentinel */ }
348 };
349 MODULE_DEVICE_TABLE(of, wave5_dt_ids);
350
351 static struct platform_driver wave5_vpu_driver = {
352         .driver = {
353                 .name = VPU_PLATFORM_DEVICE_NAME,
354                 .of_match_table = of_match_ptr(wave5_dt_ids),
355                 },
356         .probe = wave5_vpu_probe,
357         .remove = wave5_vpu_remove,
358 };
359
360 module_platform_driver(wave5_vpu_driver);
361 MODULE_DESCRIPTION("chips&media VPU V4L2 driver");
362 MODULE_LICENSE("Dual BSD/GPL");