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