Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/tegra: Boot VIC during runtime PM resume

With the new UAPI implementation, engines are powered on and off
when there are active jobs, and the core code handles channel
allocation. To accommodate that, boot the engine as part of
runtime PM instead of using the open_channel callback, which is
not used by the new submit path.

Signed-off-by: Mikko Perttunen <mperttunen@nvidia.com>
Signed-off-by: Thierry Reding <treding@nvidia.com>

authored by

Mikko Perttunen and committed by
Thierry Reding
99166123 57e20395

+53 -63
+53 -63
drivers/gpu/drm/tegra/vic.c
··· 29 29 30 30 struct vic { 31 31 struct falcon falcon; 32 - bool booted; 33 32 34 33 void __iomem *regs; 35 34 struct tegra_drm_client client; ··· 51 52 writel(value, vic->regs + offset); 52 53 } 53 54 54 - static int vic_runtime_resume(struct device *dev) 55 - { 56 - struct vic *vic = dev_get_drvdata(dev); 57 - int err; 58 - 59 - err = clk_prepare_enable(vic->clk); 60 - if (err < 0) 61 - return err; 62 - 63 - usleep_range(10, 20); 64 - 65 - err = reset_control_deassert(vic->rst); 66 - if (err < 0) 67 - goto disable; 68 - 69 - usleep_range(10, 20); 70 - 71 - return 0; 72 - 73 - disable: 74 - clk_disable_unprepare(vic->clk); 75 - return err; 76 - } 77 - 78 - static int vic_runtime_suspend(struct device *dev) 79 - { 80 - struct vic *vic = dev_get_drvdata(dev); 81 - int err; 82 - 83 - err = reset_control_assert(vic->rst); 84 - if (err < 0) 85 - return err; 86 - 87 - usleep_range(2000, 4000); 88 - 89 - clk_disable_unprepare(vic->clk); 90 - 91 - vic->booted = false; 92 - 93 - return 0; 94 - } 95 - 96 55 static int vic_boot(struct vic *vic) 97 56 { 98 57 #ifdef CONFIG_IOMMU_API ··· 59 102 u32 fce_ucode_size, fce_bin_data_offset; 60 103 void *hdr; 61 104 int err = 0; 62 - 63 - if (vic->booted) 64 - return 0; 65 105 66 106 #ifdef CONFIG_IOMMU_API 67 107 if (vic->config->supports_sid && spec) { ··· 121 167 "failed to set application ID and FCE base\n"); 122 168 return err; 123 169 } 124 - 125 - vic->booted = true; 126 170 127 171 return 0; 128 172 } ··· 275 323 return err; 276 324 } 277 325 326 + 327 + static int vic_runtime_resume(struct device *dev) 328 + { 329 + struct vic *vic = dev_get_drvdata(dev); 330 + int err; 331 + 332 + err = clk_prepare_enable(vic->clk); 333 + if (err < 0) 334 + return err; 335 + 336 + usleep_range(10, 20); 337 + 338 + err = reset_control_deassert(vic->rst); 339 + if (err < 0) 340 + goto disable; 341 + 342 + usleep_range(10, 20); 343 + 344 + err = vic_load_firmware(vic); 345 + if (err < 0) 346 + goto assert; 347 + 348 + err = vic_boot(vic); 349 + if (err < 0) 350 + goto assert; 351 + 352 + return 0; 353 + 354 + assert: 355 + reset_control_assert(vic->rst); 356 + disable: 357 + clk_disable_unprepare(vic->clk); 358 + return err; 359 + } 360 + 361 + static int vic_runtime_suspend(struct device *dev) 362 + { 363 + struct vic *vic = dev_get_drvdata(dev); 364 + int err; 365 + 366 + err = reset_control_assert(vic->rst); 367 + if (err < 0) 368 + return err; 369 + 370 + usleep_range(2000, 4000); 371 + 372 + clk_disable_unprepare(vic->clk); 373 + 374 + return 0; 375 + } 376 + 278 377 static int vic_open_channel(struct tegra_drm_client *client, 279 378 struct tegra_drm_context *context) 280 379 { ··· 336 333 if (err < 0) 337 334 return err; 338 335 339 - err = vic_load_firmware(vic); 340 - if (err < 0) 341 - goto rpm_put; 342 - 343 - err = vic_boot(vic); 344 - if (err < 0) 345 - goto rpm_put; 346 - 347 336 context->channel = host1x_channel_get(vic->channel); 348 337 if (!context->channel) { 349 - err = -ENOMEM; 350 - goto rpm_put; 338 + pm_runtime_put(vic->dev); 339 + return -ENOMEM; 351 340 } 352 341 353 342 return 0; 354 - 355 - rpm_put: 356 - pm_runtime_put(vic->dev); 357 - return err; 358 343 } 359 344 360 345 static void vic_close_channel(struct tegra_drm_context *context) ··· 350 359 struct vic *vic = to_vic(context->client); 351 360 352 361 host1x_channel_put(context->channel); 353 - 354 362 pm_runtime_put(vic->dev); 355 363 } 356 364