xref: /openbmc/linux/drivers/gpu/drm/tegra/nvdec.c (revision 88c0292f)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright (c) 2015-2021, NVIDIA Corporation.
4  */
5 
6 #include <linux/clk.h>
7 #include <linux/delay.h>
8 #include <linux/host1x.h>
9 #include <linux/iommu.h>
10 #include <linux/module.h>
11 #include <linux/of.h>
12 #include <linux/of_device.h>
13 #include <linux/of_platform.h>
14 #include <linux/platform_device.h>
15 #include <linux/pm_runtime.h>
16 #include <linux/reset.h>
17 
18 #include <soc/tegra/pmc.h>
19 
20 #include "drm.h"
21 #include "falcon.h"
22 #include "vic.h"
23 
24 #define NVDEC_TFBIF_TRANSCFG			0x2c44
25 
26 struct nvdec_config {
27 	const char *firmware;
28 	unsigned int version;
29 	bool supports_sid;
30 };
31 
32 struct nvdec {
33 	struct falcon falcon;
34 
35 	void __iomem *regs;
36 	struct tegra_drm_client client;
37 	struct host1x_channel *channel;
38 	struct device *dev;
39 	struct clk *clk;
40 
41 	/* Platform configuration */
42 	const struct nvdec_config *config;
43 };
44 
45 static inline struct nvdec *to_nvdec(struct tegra_drm_client *client)
46 {
47 	return container_of(client, struct nvdec, client);
48 }
49 
50 static inline void nvdec_writel(struct nvdec *nvdec, u32 value,
51 				unsigned int offset)
52 {
53 	writel(value, nvdec->regs + offset);
54 }
55 
56 static int nvdec_boot(struct nvdec *nvdec)
57 {
58 #ifdef CONFIG_IOMMU_API
59 	struct iommu_fwspec *spec = dev_iommu_fwspec_get(nvdec->dev);
60 #endif
61 	int err;
62 
63 #ifdef CONFIG_IOMMU_API
64 	if (nvdec->config->supports_sid && spec) {
65 		u32 value;
66 
67 		value = TRANSCFG_ATT(1, TRANSCFG_SID_FALCON) | TRANSCFG_ATT(0, TRANSCFG_SID_HW);
68 		nvdec_writel(nvdec, value, NVDEC_TFBIF_TRANSCFG);
69 
70 		if (spec->num_ids > 0) {
71 			value = spec->ids[0] & 0xffff;
72 
73 			nvdec_writel(nvdec, value, VIC_THI_STREAMID0);
74 			nvdec_writel(nvdec, value, VIC_THI_STREAMID1);
75 		}
76 	}
77 #endif
78 
79 	err = falcon_boot(&nvdec->falcon);
80 	if (err < 0)
81 		return err;
82 
83 	err = falcon_wait_idle(&nvdec->falcon);
84 	if (err < 0) {
85 		dev_err(nvdec->dev, "falcon boot timed out\n");
86 		return err;
87 	}
88 
89 	return 0;
90 }
91 
92 static int nvdec_init(struct host1x_client *client)
93 {
94 	struct tegra_drm_client *drm = host1x_to_drm_client(client);
95 	struct drm_device *dev = dev_get_drvdata(client->host);
96 	struct tegra_drm *tegra = dev->dev_private;
97 	struct nvdec *nvdec = to_nvdec(drm);
98 	int err;
99 
100 	err = host1x_client_iommu_attach(client);
101 	if (err < 0 && err != -ENODEV) {
102 		dev_err(nvdec->dev, "failed to attach to domain: %d\n", err);
103 		return err;
104 	}
105 
106 	nvdec->channel = host1x_channel_request(client);
107 	if (!nvdec->channel) {
108 		err = -ENOMEM;
109 		goto detach;
110 	}
111 
112 	client->syncpts[0] = host1x_syncpt_request(client, 0);
113 	if (!client->syncpts[0]) {
114 		err = -ENOMEM;
115 		goto free_channel;
116 	}
117 
118 	pm_runtime_enable(client->dev);
119 	pm_runtime_use_autosuspend(client->dev);
120 	pm_runtime_set_autosuspend_delay(client->dev, 500);
121 
122 	err = tegra_drm_register_client(tegra, drm);
123 	if (err < 0)
124 		goto disable_rpm;
125 
126 	/*
127 	 * Inherit the DMA parameters (such as maximum segment size) from the
128 	 * parent host1x device.
129 	 */
130 	client->dev->dma_parms = client->host->dma_parms;
131 
132 	return 0;
133 
134 disable_rpm:
135 	pm_runtime_dont_use_autosuspend(client->dev);
136 	pm_runtime_force_suspend(client->dev);
137 
138 	host1x_syncpt_put(client->syncpts[0]);
139 free_channel:
140 	host1x_channel_put(nvdec->channel);
141 detach:
142 	host1x_client_iommu_detach(client);
143 
144 	return err;
145 }
146 
147 static int nvdec_exit(struct host1x_client *client)
148 {
149 	struct tegra_drm_client *drm = host1x_to_drm_client(client);
150 	struct drm_device *dev = dev_get_drvdata(client->host);
151 	struct tegra_drm *tegra = dev->dev_private;
152 	struct nvdec *nvdec = to_nvdec(drm);
153 	int err;
154 
155 	/* avoid a dangling pointer just in case this disappears */
156 	client->dev->dma_parms = NULL;
157 
158 	err = tegra_drm_unregister_client(tegra, drm);
159 	if (err < 0)
160 		return err;
161 
162 	pm_runtime_dont_use_autosuspend(client->dev);
163 	pm_runtime_force_suspend(client->dev);
164 
165 	host1x_syncpt_put(client->syncpts[0]);
166 	host1x_channel_put(nvdec->channel);
167 	host1x_client_iommu_detach(client);
168 
169 	nvdec->channel = NULL;
170 
171 	if (client->group) {
172 		dma_unmap_single(nvdec->dev, nvdec->falcon.firmware.phys,
173 				 nvdec->falcon.firmware.size, DMA_TO_DEVICE);
174 		tegra_drm_free(tegra, nvdec->falcon.firmware.size,
175 			       nvdec->falcon.firmware.virt,
176 			       nvdec->falcon.firmware.iova);
177 	} else {
178 		dma_free_coherent(nvdec->dev, nvdec->falcon.firmware.size,
179 				  nvdec->falcon.firmware.virt,
180 				  nvdec->falcon.firmware.iova);
181 	}
182 
183 	return 0;
184 }
185 
186 static const struct host1x_client_ops nvdec_client_ops = {
187 	.init = nvdec_init,
188 	.exit = nvdec_exit,
189 };
190 
191 static int nvdec_load_firmware(struct nvdec *nvdec)
192 {
193 	struct host1x_client *client = &nvdec->client.base;
194 	struct tegra_drm *tegra = nvdec->client.drm;
195 	dma_addr_t iova;
196 	size_t size;
197 	void *virt;
198 	int err;
199 
200 	if (nvdec->falcon.firmware.virt)
201 		return 0;
202 
203 	err = falcon_read_firmware(&nvdec->falcon, nvdec->config->firmware);
204 	if (err < 0)
205 		return err;
206 
207 	size = nvdec->falcon.firmware.size;
208 
209 	if (!client->group) {
210 		virt = dma_alloc_coherent(nvdec->dev, size, &iova, GFP_KERNEL);
211 
212 		err = dma_mapping_error(nvdec->dev, iova);
213 		if (err < 0)
214 			return err;
215 	} else {
216 		virt = tegra_drm_alloc(tegra, size, &iova);
217 	}
218 
219 	nvdec->falcon.firmware.virt = virt;
220 	nvdec->falcon.firmware.iova = iova;
221 
222 	err = falcon_load_firmware(&nvdec->falcon);
223 	if (err < 0)
224 		goto cleanup;
225 
226 	/*
227 	 * In this case we have received an IOVA from the shared domain, so we
228 	 * need to make sure to get the physical address so that the DMA API
229 	 * knows what memory pages to flush the cache for.
230 	 */
231 	if (client->group) {
232 		dma_addr_t phys;
233 
234 		phys = dma_map_single(nvdec->dev, virt, size, DMA_TO_DEVICE);
235 
236 		err = dma_mapping_error(nvdec->dev, phys);
237 		if (err < 0)
238 			goto cleanup;
239 
240 		nvdec->falcon.firmware.phys = phys;
241 	}
242 
243 	return 0;
244 
245 cleanup:
246 	if (!client->group)
247 		dma_free_coherent(nvdec->dev, size, virt, iova);
248 	else
249 		tegra_drm_free(tegra, size, virt, iova);
250 
251 	return err;
252 }
253 
254 
255 static __maybe_unused int nvdec_runtime_resume(struct device *dev)
256 {
257 	struct nvdec *nvdec = dev_get_drvdata(dev);
258 	int err;
259 
260 	err = clk_prepare_enable(nvdec->clk);
261 	if (err < 0)
262 		return err;
263 
264 	usleep_range(10, 20);
265 
266 	err = nvdec_load_firmware(nvdec);
267 	if (err < 0)
268 		goto disable;
269 
270 	err = nvdec_boot(nvdec);
271 	if (err < 0)
272 		goto disable;
273 
274 	return 0;
275 
276 disable:
277 	clk_disable_unprepare(nvdec->clk);
278 	return err;
279 }
280 
281 static __maybe_unused int nvdec_runtime_suspend(struct device *dev)
282 {
283 	struct nvdec *nvdec = dev_get_drvdata(dev);
284 
285 	host1x_channel_stop(nvdec->channel);
286 
287 	clk_disable_unprepare(nvdec->clk);
288 
289 	return 0;
290 }
291 
292 static int nvdec_open_channel(struct tegra_drm_client *client,
293 			    struct tegra_drm_context *context)
294 {
295 	struct nvdec *nvdec = to_nvdec(client);
296 
297 	context->channel = host1x_channel_get(nvdec->channel);
298 	if (!context->channel)
299 		return -ENOMEM;
300 
301 	return 0;
302 }
303 
304 static void nvdec_close_channel(struct tegra_drm_context *context)
305 {
306 	host1x_channel_put(context->channel);
307 }
308 
309 static const struct tegra_drm_client_ops nvdec_ops = {
310 	.open_channel = nvdec_open_channel,
311 	.close_channel = nvdec_close_channel,
312 	.submit = tegra_drm_submit,
313 };
314 
315 #define NVIDIA_TEGRA_210_NVDEC_FIRMWARE "nvidia/tegra210/nvdec.bin"
316 
317 static const struct nvdec_config nvdec_t210_config = {
318 	.firmware = NVIDIA_TEGRA_210_NVDEC_FIRMWARE,
319 	.version = 0x21,
320 	.supports_sid = false,
321 };
322 
323 #define NVIDIA_TEGRA_186_NVDEC_FIRMWARE "nvidia/tegra186/nvdec.bin"
324 
325 static const struct nvdec_config nvdec_t186_config = {
326 	.firmware = NVIDIA_TEGRA_186_NVDEC_FIRMWARE,
327 	.version = 0x18,
328 	.supports_sid = true,
329 };
330 
331 #define NVIDIA_TEGRA_194_NVDEC_FIRMWARE "nvidia/tegra194/nvdec.bin"
332 
333 static const struct nvdec_config nvdec_t194_config = {
334 	.firmware = NVIDIA_TEGRA_194_NVDEC_FIRMWARE,
335 	.version = 0x19,
336 	.supports_sid = true,
337 };
338 
339 static const struct of_device_id tegra_nvdec_of_match[] = {
340 	{ .compatible = "nvidia,tegra210-nvdec", .data = &nvdec_t210_config },
341 	{ .compatible = "nvidia,tegra186-nvdec", .data = &nvdec_t186_config },
342 	{ .compatible = "nvidia,tegra194-nvdec", .data = &nvdec_t194_config },
343 	{ },
344 };
345 MODULE_DEVICE_TABLE(of, tegra_nvdec_of_match);
346 
347 static int nvdec_probe(struct platform_device *pdev)
348 {
349 	struct device *dev = &pdev->dev;
350 	struct host1x_syncpt **syncpts;
351 	struct nvdec *nvdec;
352 	u32 host_class;
353 	int err;
354 
355 	/* inherit DMA mask from host1x parent */
356 	err = dma_coerce_mask_and_coherent(dev, *dev->parent->dma_mask);
357 	if (err < 0) {
358 		dev_err(&pdev->dev, "failed to set DMA mask: %d\n", err);
359 		return err;
360 	}
361 
362 	nvdec = devm_kzalloc(dev, sizeof(*nvdec), GFP_KERNEL);
363 	if (!nvdec)
364 		return -ENOMEM;
365 
366 	nvdec->config = of_device_get_match_data(dev);
367 
368 	syncpts = devm_kzalloc(dev, sizeof(*syncpts), GFP_KERNEL);
369 	if (!syncpts)
370 		return -ENOMEM;
371 
372 	nvdec->regs = devm_platform_get_and_ioremap_resource(pdev, 0, NULL);
373 	if (IS_ERR(nvdec->regs))
374 		return PTR_ERR(nvdec->regs);
375 
376 	nvdec->clk = devm_clk_get(dev, NULL);
377 	if (IS_ERR(nvdec->clk)) {
378 		dev_err(&pdev->dev, "failed to get clock\n");
379 		return PTR_ERR(nvdec->clk);
380 	}
381 
382 	err = clk_set_rate(nvdec->clk, ULONG_MAX);
383 	if (err < 0) {
384 		dev_err(&pdev->dev, "failed to set clock rate\n");
385 		return err;
386 	}
387 
388 	err = of_property_read_u32(dev->of_node, "nvidia,host1x-class", &host_class);
389 	if (err < 0)
390 		host_class = HOST1X_CLASS_NVDEC;
391 
392 	nvdec->falcon.dev = dev;
393 	nvdec->falcon.regs = nvdec->regs;
394 
395 	err = falcon_init(&nvdec->falcon);
396 	if (err < 0)
397 		return err;
398 
399 	platform_set_drvdata(pdev, nvdec);
400 
401 	INIT_LIST_HEAD(&nvdec->client.base.list);
402 	nvdec->client.base.ops = &nvdec_client_ops;
403 	nvdec->client.base.dev = dev;
404 	nvdec->client.base.class = host_class;
405 	nvdec->client.base.syncpts = syncpts;
406 	nvdec->client.base.num_syncpts = 1;
407 	nvdec->dev = dev;
408 
409 	INIT_LIST_HEAD(&nvdec->client.list);
410 	nvdec->client.version = nvdec->config->version;
411 	nvdec->client.ops = &nvdec_ops;
412 
413 	err = host1x_client_register(&nvdec->client.base);
414 	if (err < 0) {
415 		dev_err(dev, "failed to register host1x client: %d\n", err);
416 		goto exit_falcon;
417 	}
418 
419 	return 0;
420 
421 exit_falcon:
422 	falcon_exit(&nvdec->falcon);
423 
424 	return err;
425 }
426 
427 static int nvdec_remove(struct platform_device *pdev)
428 {
429 	struct nvdec *nvdec = platform_get_drvdata(pdev);
430 	int err;
431 
432 	err = host1x_client_unregister(&nvdec->client.base);
433 	if (err < 0) {
434 		dev_err(&pdev->dev, "failed to unregister host1x client: %d\n",
435 			err);
436 		return err;
437 	}
438 
439 	falcon_exit(&nvdec->falcon);
440 
441 	return 0;
442 }
443 
444 static const struct dev_pm_ops nvdec_pm_ops = {
445 	SET_RUNTIME_PM_OPS(nvdec_runtime_suspend, nvdec_runtime_resume, NULL)
446 	SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
447 				pm_runtime_force_resume)
448 };
449 
450 struct platform_driver tegra_nvdec_driver = {
451 	.driver = {
452 		.name = "tegra-nvdec",
453 		.of_match_table = tegra_nvdec_of_match,
454 		.pm = &nvdec_pm_ops
455 	},
456 	.probe = nvdec_probe,
457 	.remove = nvdec_remove,
458 };
459 
460 #if IS_ENABLED(CONFIG_ARCH_TEGRA_210_SOC)
461 MODULE_FIRMWARE(NVIDIA_TEGRA_210_NVDEC_FIRMWARE);
462 #endif
463 #if IS_ENABLED(CONFIG_ARCH_TEGRA_186_SOC)
464 MODULE_FIRMWARE(NVIDIA_TEGRA_186_NVDEC_FIRMWARE);
465 #endif
466 #if IS_ENABLED(CONFIG_ARCH_TEGRA_194_SOC)
467 MODULE_FIRMWARE(NVIDIA_TEGRA_194_NVDEC_FIRMWARE);
468 #endif
469