]> Git Repo - linux.git/blob - drivers/gpu/drm/tegra/nvdec.c
Merge tag 'drm-next-2023-05-05' of git://anongit.freedesktop.org/drm/drm
[linux.git] / drivers / gpu / drm / tegra / nvdec.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright (c) 2015-2022, NVIDIA Corporation.
4  */
5
6 #include <linux/clk.h>
7 #include <linux/delay.h>
8 #include <linux/dma-mapping.h>
9 #include <linux/host1x.h>
10 #include <linux/iommu.h>
11 #include <linux/iopoll.h>
12 #include <linux/module.h>
13 #include <linux/of.h>
14 #include <linux/of_device.h>
15 #include <linux/of_platform.h>
16 #include <linux/platform_device.h>
17 #include <linux/pm_runtime.h>
18 #include <linux/reset.h>
19
20 #include <soc/tegra/mc.h>
21
22 #include "drm.h"
23 #include "falcon.h"
24 #include "riscv.h"
25 #include "vic.h"
26
27 #define NVDEC_FALCON_DEBUGINFO                  0x1094
28 #define NVDEC_TFBIF_TRANSCFG                    0x2c44
29
30 struct nvdec_config {
31         const char *firmware;
32         unsigned int version;
33         bool supports_sid;
34         bool has_riscv;
35         bool has_extra_clocks;
36 };
37
38 struct nvdec {
39         struct falcon falcon;
40
41         void __iomem *regs;
42         struct tegra_drm_client client;
43         struct host1x_channel *channel;
44         struct device *dev;
45         struct clk_bulk_data clks[3];
46         unsigned int num_clks;
47         struct reset_control *reset;
48
49         /* Platform configuration */
50         const struct nvdec_config *config;
51
52         /* RISC-V specific data */
53         struct tegra_drm_riscv riscv;
54         phys_addr_t carveout_base;
55 };
56
57 static inline struct nvdec *to_nvdec(struct tegra_drm_client *client)
58 {
59         return container_of(client, struct nvdec, client);
60 }
61
62 static inline void nvdec_writel(struct nvdec *nvdec, u32 value,
63                                 unsigned int offset)
64 {
65         writel(value, nvdec->regs + offset);
66 }
67
68 static int nvdec_boot_falcon(struct nvdec *nvdec)
69 {
70         u32 stream_id;
71         int err;
72
73         if (nvdec->config->supports_sid && tegra_dev_iommu_get_stream_id(nvdec->dev, &stream_id)) {
74                 u32 value;
75
76                 value = TRANSCFG_ATT(1, TRANSCFG_SID_FALCON) | TRANSCFG_ATT(0, TRANSCFG_SID_HW);
77                 nvdec_writel(nvdec, value, NVDEC_TFBIF_TRANSCFG);
78
79                 nvdec_writel(nvdec, stream_id, VIC_THI_STREAMID0);
80                 nvdec_writel(nvdec, stream_id, VIC_THI_STREAMID1);
81         }
82
83         err = falcon_boot(&nvdec->falcon);
84         if (err < 0)
85                 return err;
86
87         err = falcon_wait_idle(&nvdec->falcon);
88         if (err < 0) {
89                 dev_err(nvdec->dev, "falcon boot timed out\n");
90                 return err;
91         }
92
93         return 0;
94 }
95
96 static int nvdec_wait_debuginfo(struct nvdec *nvdec, const char *phase)
97 {
98         int err;
99         u32 val;
100
101         err = readl_poll_timeout(nvdec->regs + NVDEC_FALCON_DEBUGINFO, val, val == 0x0, 10, 100000);
102         if (err) {
103                 dev_err(nvdec->dev, "failed to boot %s, debuginfo=0x%x\n", phase, val);
104                 return err;
105         }
106
107         return 0;
108 }
109
110 static int nvdec_boot_riscv(struct nvdec *nvdec)
111 {
112         int err;
113
114         err = reset_control_acquire(nvdec->reset);
115         if (err)
116                 return err;
117
118         nvdec_writel(nvdec, 0xabcd1234, NVDEC_FALCON_DEBUGINFO);
119
120         err = tegra_drm_riscv_boot_bootrom(&nvdec->riscv, nvdec->carveout_base, 1,
121                                            &nvdec->riscv.bl_desc);
122         if (err) {
123                 dev_err(nvdec->dev, "failed to execute bootloader\n");
124                 goto release_reset;
125         }
126
127         err = nvdec_wait_debuginfo(nvdec, "bootloader");
128         if (err)
129                 goto release_reset;
130
131         err = reset_control_reset(nvdec->reset);
132         if (err)
133                 goto release_reset;
134
135         nvdec_writel(nvdec, 0xabcd1234, NVDEC_FALCON_DEBUGINFO);
136
137         err = tegra_drm_riscv_boot_bootrom(&nvdec->riscv, nvdec->carveout_base, 1,
138                                            &nvdec->riscv.os_desc);
139         if (err) {
140                 dev_err(nvdec->dev, "failed to execute firmware\n");
141                 goto release_reset;
142         }
143
144         err = nvdec_wait_debuginfo(nvdec, "firmware");
145         if (err)
146                 goto release_reset;
147
148 release_reset:
149         reset_control_release(nvdec->reset);
150
151         return err;
152 }
153
154 static int nvdec_init(struct host1x_client *client)
155 {
156         struct tegra_drm_client *drm = host1x_to_drm_client(client);
157         struct drm_device *dev = dev_get_drvdata(client->host);
158         struct tegra_drm *tegra = dev->dev_private;
159         struct nvdec *nvdec = to_nvdec(drm);
160         int err;
161
162         err = host1x_client_iommu_attach(client);
163         if (err < 0 && err != -ENODEV) {
164                 dev_err(nvdec->dev, "failed to attach to domain: %d\n", err);
165                 return err;
166         }
167
168         nvdec->channel = host1x_channel_request(client);
169         if (!nvdec->channel) {
170                 err = -ENOMEM;
171                 goto detach;
172         }
173
174         client->syncpts[0] = host1x_syncpt_request(client, 0);
175         if (!client->syncpts[0]) {
176                 err = -ENOMEM;
177                 goto free_channel;
178         }
179
180         pm_runtime_enable(client->dev);
181         pm_runtime_use_autosuspend(client->dev);
182         pm_runtime_set_autosuspend_delay(client->dev, 500);
183
184         err = tegra_drm_register_client(tegra, drm);
185         if (err < 0)
186                 goto disable_rpm;
187
188         /*
189          * Inherit the DMA parameters (such as maximum segment size) from the
190          * parent host1x device.
191          */
192         client->dev->dma_parms = client->host->dma_parms;
193
194         return 0;
195
196 disable_rpm:
197         pm_runtime_dont_use_autosuspend(client->dev);
198         pm_runtime_force_suspend(client->dev);
199
200         host1x_syncpt_put(client->syncpts[0]);
201 free_channel:
202         host1x_channel_put(nvdec->channel);
203 detach:
204         host1x_client_iommu_detach(client);
205
206         return err;
207 }
208
209 static int nvdec_exit(struct host1x_client *client)
210 {
211         struct tegra_drm_client *drm = host1x_to_drm_client(client);
212         struct drm_device *dev = dev_get_drvdata(client->host);
213         struct tegra_drm *tegra = dev->dev_private;
214         struct nvdec *nvdec = to_nvdec(drm);
215         int err;
216
217         /* avoid a dangling pointer just in case this disappears */
218         client->dev->dma_parms = NULL;
219
220         err = tegra_drm_unregister_client(tegra, drm);
221         if (err < 0)
222                 return err;
223
224         pm_runtime_dont_use_autosuspend(client->dev);
225         pm_runtime_force_suspend(client->dev);
226
227         host1x_syncpt_put(client->syncpts[0]);
228         host1x_channel_put(nvdec->channel);
229         host1x_client_iommu_detach(client);
230
231         nvdec->channel = NULL;
232
233         if (client->group) {
234                 dma_unmap_single(nvdec->dev, nvdec->falcon.firmware.phys,
235                                  nvdec->falcon.firmware.size, DMA_TO_DEVICE);
236                 tegra_drm_free(tegra, nvdec->falcon.firmware.size,
237                                nvdec->falcon.firmware.virt,
238                                nvdec->falcon.firmware.iova);
239         } else {
240                 dma_free_coherent(nvdec->dev, nvdec->falcon.firmware.size,
241                                   nvdec->falcon.firmware.virt,
242                                   nvdec->falcon.firmware.iova);
243         }
244
245         return 0;
246 }
247
248 static const struct host1x_client_ops nvdec_client_ops = {
249         .init = nvdec_init,
250         .exit = nvdec_exit,
251 };
252
253 static int nvdec_load_falcon_firmware(struct nvdec *nvdec)
254 {
255         struct host1x_client *client = &nvdec->client.base;
256         struct tegra_drm *tegra = nvdec->client.drm;
257         dma_addr_t iova;
258         size_t size;
259         void *virt;
260         int err;
261
262         if (nvdec->falcon.firmware.virt)
263                 return 0;
264
265         err = falcon_read_firmware(&nvdec->falcon, nvdec->config->firmware);
266         if (err < 0)
267                 return err;
268
269         size = nvdec->falcon.firmware.size;
270
271         if (!client->group) {
272                 virt = dma_alloc_coherent(nvdec->dev, size, &iova, GFP_KERNEL);
273
274                 err = dma_mapping_error(nvdec->dev, iova);
275                 if (err < 0)
276                         return err;
277         } else {
278                 virt = tegra_drm_alloc(tegra, size, &iova);
279         }
280
281         nvdec->falcon.firmware.virt = virt;
282         nvdec->falcon.firmware.iova = iova;
283
284         err = falcon_load_firmware(&nvdec->falcon);
285         if (err < 0)
286                 goto cleanup;
287
288         /*
289          * In this case we have received an IOVA from the shared domain, so we
290          * need to make sure to get the physical address so that the DMA API
291          * knows what memory pages to flush the cache for.
292          */
293         if (client->group) {
294                 dma_addr_t phys;
295
296                 phys = dma_map_single(nvdec->dev, virt, size, DMA_TO_DEVICE);
297
298                 err = dma_mapping_error(nvdec->dev, phys);
299                 if (err < 0)
300                         goto cleanup;
301
302                 nvdec->falcon.firmware.phys = phys;
303         }
304
305         return 0;
306
307 cleanup:
308         if (!client->group)
309                 dma_free_coherent(nvdec->dev, size, virt, iova);
310         else
311                 tegra_drm_free(tegra, size, virt, iova);
312
313         return err;
314 }
315
316 static __maybe_unused int nvdec_runtime_resume(struct device *dev)
317 {
318         struct nvdec *nvdec = dev_get_drvdata(dev);
319         int err;
320
321         err = clk_bulk_prepare_enable(nvdec->num_clks, nvdec->clks);
322         if (err < 0)
323                 return err;
324
325         usleep_range(10, 20);
326
327         if (nvdec->config->has_riscv) {
328                 err = nvdec_boot_riscv(nvdec);
329                 if (err < 0)
330                         goto disable;
331         } else {
332                 err = nvdec_load_falcon_firmware(nvdec);
333                 if (err < 0)
334                         goto disable;
335
336                 err = nvdec_boot_falcon(nvdec);
337                 if (err < 0)
338                         goto disable;
339         }
340
341         return 0;
342
343 disable:
344         clk_bulk_disable_unprepare(nvdec->num_clks, nvdec->clks);
345         return err;
346 }
347
348 static __maybe_unused int nvdec_runtime_suspend(struct device *dev)
349 {
350         struct nvdec *nvdec = dev_get_drvdata(dev);
351
352         host1x_channel_stop(nvdec->channel);
353
354         clk_bulk_disable_unprepare(nvdec->num_clks, nvdec->clks);
355
356         return 0;
357 }
358
359 static int nvdec_open_channel(struct tegra_drm_client *client,
360                             struct tegra_drm_context *context)
361 {
362         struct nvdec *nvdec = to_nvdec(client);
363
364         context->channel = host1x_channel_get(nvdec->channel);
365         if (!context->channel)
366                 return -ENOMEM;
367
368         return 0;
369 }
370
371 static void nvdec_close_channel(struct tegra_drm_context *context)
372 {
373         host1x_channel_put(context->channel);
374 }
375
376 static int nvdec_can_use_memory_ctx(struct tegra_drm_client *client, bool *supported)
377 {
378         *supported = true;
379
380         return 0;
381 }
382
383 static const struct tegra_drm_client_ops nvdec_ops = {
384         .open_channel = nvdec_open_channel,
385         .close_channel = nvdec_close_channel,
386         .submit = tegra_drm_submit,
387         .get_streamid_offset = tegra_drm_get_streamid_offset_thi,
388         .can_use_memory_ctx = nvdec_can_use_memory_ctx,
389 };
390
391 #define NVIDIA_TEGRA_210_NVDEC_FIRMWARE "nvidia/tegra210/nvdec.bin"
392
393 static const struct nvdec_config nvdec_t210_config = {
394         .firmware = NVIDIA_TEGRA_210_NVDEC_FIRMWARE,
395         .version = 0x21,
396         .supports_sid = false,
397 };
398
399 #define NVIDIA_TEGRA_186_NVDEC_FIRMWARE "nvidia/tegra186/nvdec.bin"
400
401 static const struct nvdec_config nvdec_t186_config = {
402         .firmware = NVIDIA_TEGRA_186_NVDEC_FIRMWARE,
403         .version = 0x18,
404         .supports_sid = true,
405 };
406
407 #define NVIDIA_TEGRA_194_NVDEC_FIRMWARE "nvidia/tegra194/nvdec.bin"
408
409 static const struct nvdec_config nvdec_t194_config = {
410         .firmware = NVIDIA_TEGRA_194_NVDEC_FIRMWARE,
411         .version = 0x19,
412         .supports_sid = true,
413 };
414
415 static const struct nvdec_config nvdec_t234_config = {
416         .version = 0x23,
417         .supports_sid = true,
418         .has_riscv = true,
419         .has_extra_clocks = true,
420 };
421
422 static const struct of_device_id tegra_nvdec_of_match[] = {
423         { .compatible = "nvidia,tegra210-nvdec", .data = &nvdec_t210_config },
424         { .compatible = "nvidia,tegra186-nvdec", .data = &nvdec_t186_config },
425         { .compatible = "nvidia,tegra194-nvdec", .data = &nvdec_t194_config },
426         { .compatible = "nvidia,tegra234-nvdec", .data = &nvdec_t234_config },
427         { },
428 };
429 MODULE_DEVICE_TABLE(of, tegra_nvdec_of_match);
430
431 static int nvdec_probe(struct platform_device *pdev)
432 {
433         struct device *dev = &pdev->dev;
434         struct host1x_syncpt **syncpts;
435         struct nvdec *nvdec;
436         u32 host_class;
437         int err;
438
439         /* inherit DMA mask from host1x parent */
440         err = dma_coerce_mask_and_coherent(dev, *dev->parent->dma_mask);
441         if (err < 0) {
442                 dev_err(&pdev->dev, "failed to set DMA mask: %d\n", err);
443                 return err;
444         }
445
446         nvdec = devm_kzalloc(dev, sizeof(*nvdec), GFP_KERNEL);
447         if (!nvdec)
448                 return -ENOMEM;
449
450         nvdec->config = of_device_get_match_data(dev);
451
452         syncpts = devm_kzalloc(dev, sizeof(*syncpts), GFP_KERNEL);
453         if (!syncpts)
454                 return -ENOMEM;
455
456         nvdec->regs = devm_platform_get_and_ioremap_resource(pdev, 0, NULL);
457         if (IS_ERR(nvdec->regs))
458                 return PTR_ERR(nvdec->regs);
459
460         nvdec->clks[0].id = "nvdec";
461         nvdec->num_clks = 1;
462
463         if (nvdec->config->has_extra_clocks) {
464                 nvdec->num_clks = 3;
465                 nvdec->clks[1].id = "fuse";
466                 nvdec->clks[2].id = "tsec_pka";
467         }
468
469         err = devm_clk_bulk_get(dev, nvdec->num_clks, nvdec->clks);
470         if (err) {
471                 dev_err(&pdev->dev, "failed to get clock(s)\n");
472                 return err;
473         }
474
475         err = clk_set_rate(nvdec->clks[0].clk, ULONG_MAX);
476         if (err < 0) {
477                 dev_err(&pdev->dev, "failed to set clock rate\n");
478                 return err;
479         }
480
481         err = of_property_read_u32(dev->of_node, "nvidia,host1x-class", &host_class);
482         if (err < 0)
483                 host_class = HOST1X_CLASS_NVDEC;
484
485         if (nvdec->config->has_riscv) {
486                 struct tegra_mc *mc;
487
488                 mc = devm_tegra_memory_controller_get(dev);
489                 if (IS_ERR(mc)) {
490                         dev_err_probe(dev, PTR_ERR(mc),
491                                 "failed to get memory controller handle\n");
492                         return PTR_ERR(mc);
493                 }
494
495                 err = tegra_mc_get_carveout_info(mc, 1, &nvdec->carveout_base, NULL);
496                 if (err) {
497                         dev_err(dev, "failed to get carveout info: %d\n", err);
498                         return err;
499                 }
500
501                 nvdec->reset = devm_reset_control_get_exclusive_released(dev, "nvdec");
502                 if (IS_ERR(nvdec->reset)) {
503                         dev_err_probe(dev, PTR_ERR(nvdec->reset), "failed to get reset\n");
504                         return PTR_ERR(nvdec->reset);
505                 }
506
507                 nvdec->riscv.dev = dev;
508                 nvdec->riscv.regs = nvdec->regs;
509
510                 err = tegra_drm_riscv_read_descriptors(&nvdec->riscv);
511                 if (err < 0)
512                         return err;
513         } else {
514                 nvdec->falcon.dev = dev;
515                 nvdec->falcon.regs = nvdec->regs;
516
517                 err = falcon_init(&nvdec->falcon);
518                 if (err < 0)
519                         return err;
520         }
521
522         platform_set_drvdata(pdev, nvdec);
523
524         INIT_LIST_HEAD(&nvdec->client.base.list);
525         nvdec->client.base.ops = &nvdec_client_ops;
526         nvdec->client.base.dev = dev;
527         nvdec->client.base.class = host_class;
528         nvdec->client.base.syncpts = syncpts;
529         nvdec->client.base.num_syncpts = 1;
530         nvdec->dev = dev;
531
532         INIT_LIST_HEAD(&nvdec->client.list);
533         nvdec->client.version = nvdec->config->version;
534         nvdec->client.ops = &nvdec_ops;
535
536         err = host1x_client_register(&nvdec->client.base);
537         if (err < 0) {
538                 dev_err(dev, "failed to register host1x client: %d\n", err);
539                 goto exit_falcon;
540         }
541
542         return 0;
543
544 exit_falcon:
545         falcon_exit(&nvdec->falcon);
546
547         return err;
548 }
549
550 static void nvdec_remove(struct platform_device *pdev)
551 {
552         struct nvdec *nvdec = platform_get_drvdata(pdev);
553
554         host1x_client_unregister(&nvdec->client.base);
555
556         falcon_exit(&nvdec->falcon);
557 }
558
559 static const struct dev_pm_ops nvdec_pm_ops = {
560         SET_RUNTIME_PM_OPS(nvdec_runtime_suspend, nvdec_runtime_resume, NULL)
561         SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
562                                 pm_runtime_force_resume)
563 };
564
565 struct platform_driver tegra_nvdec_driver = {
566         .driver = {
567                 .name = "tegra-nvdec",
568                 .of_match_table = tegra_nvdec_of_match,
569                 .pm = &nvdec_pm_ops
570         },
571         .probe = nvdec_probe,
572         .remove_new = nvdec_remove,
573 };
574
575 #if IS_ENABLED(CONFIG_ARCH_TEGRA_210_SOC)
576 MODULE_FIRMWARE(NVIDIA_TEGRA_210_NVDEC_FIRMWARE);
577 #endif
578 #if IS_ENABLED(CONFIG_ARCH_TEGRA_186_SOC)
579 MODULE_FIRMWARE(NVIDIA_TEGRA_186_NVDEC_FIRMWARE);
580 #endif
581 #if IS_ENABLED(CONFIG_ARCH_TEGRA_194_SOC)
582 MODULE_FIRMWARE(NVIDIA_TEGRA_194_NVDEC_FIRMWARE);
583 #endif
This page took 0.066871 seconds and 4 git commands to generate.