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