diff options
author | Alexandre Courbot <acourbot@nvidia.com> | 2014-10-01 19:05:04 +0900 |
---|---|---|
committer | Thierry Reding <treding@nvidia.com> | 2014-12-19 10:20:06 +0100 |
commit | c7ac3b5be0265c4ca714bd0e863c69c1a7506dce (patch) | |
tree | 8e93b729dad27c7010fbd249d8215f8ad4acfe0b | |
parent | 864b8f635b0f6cf7df6f34aea990309e9f069452 (diff) |
platform: support for netlist firmwaresstaging/drm/nouveau
Netlists released by NVIDIA are made of a single file containing
firmwares that can potentially be used across different engines. It
therefore makes most sense to load a netlist once before engines are
probed and have them duplicate their firmwares so the netlist can
be freed at the end of probe.
This patch implements this mechanism and adds the lookup data for GK20A.
Signed-off-by: Alexandre Courbot <acourbot@nvidia.com>
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_platform.c | 76 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_platform.h | 2 |
2 files changed, 73 insertions, 5 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_platform.c b/drivers/gpu/drm/nouveau/nouveau_platform.c index b307bbedd4c..8871a21ad8f 100644 --- a/drivers/gpu/drm/nouveau/nouveau_platform.c +++ b/drivers/gpu/drm/nouveau/nouveau_platform.c @@ -25,6 +25,7 @@ #include <linux/module.h> #include <linux/platform_device.h> #include <linux/of.h> +#include <linux/of_device.h> #include <linux/reset.h> #include <linux/regulator/consumer.h> #include <soc/tegra/fuse.h> @@ -91,6 +92,52 @@ static int nouveau_platform_power_down(struct nouveau_platform_gpu *gpu) return 0; } +struct nouveau_platform_probe_data { + const char *soc; + const char *gpu; + bool use_ext_firmware; +}; + +static const struct firmware * +nouveau_platform_load_netlist_fw(struct platform_device *pdev) +{ + const struct of_device_id *match; + const struct nouveau_platform_probe_data *pdata; + const struct firmware *ctxsw_fw; + char f[32]; + int err; + + match = of_match_device(pdev->dev.driver->of_match_table, &pdev->dev); + if (!match) { + dev_warn(&pdev->dev, "cannot find OF match for device\n"); + return NULL; + } + pdata = match->data; + if (!pdata) { + dev_warn(&pdev->dev, "no probe data for device\n"); + return NULL; + } + + if (!pdata->use_ext_firmware) + return NULL; + + err = snprintf(f, sizeof(f), "nvidia/%s/%s_ctxsw.bin", pdata->soc, + pdata->gpu); + if (err >= sizeof(f)) { + dev_err(&pdev->dev, "firmware path too long (max %d)\n", + sizeof(f)); + return ERR_PTR(-ENOSPC); + } + + err = request_firmware(&ctxsw_fw, f, &pdev->dev); + if (err) { + dev_err(&pdev->dev, "error loading firmware: %d\n", err); + return ERR_PTR(err); + } + + return ctxsw_fw; +} + static int nouveau_platform_probe(struct platform_device *pdev) { struct nouveau_platform_gpu *gpu; @@ -118,9 +165,13 @@ static int nouveau_platform_probe(struct platform_device *pdev) if (IS_ERR(gpu->clk_pwr)) return PTR_ERR(gpu->clk_pwr); + gpu->ctxsw_fw = nouveau_platform_load_netlist_fw(pdev); + if (IS_ERR(gpu->ctxsw_fw)) + return PTR_ERR(gpu->ctxsw_fw); + err = nouveau_platform_power_up(gpu); if (err) - return err; + goto release_fw; drm = nouveau_platform_device_create(pdev, &device); if (IS_ERR(drm)) { @@ -135,16 +186,22 @@ static int nouveau_platform_probe(struct platform_device *pdev) if (err < 0) goto err_unref; - return 0; + /* + * we can release the firmware now since it has been consumed during + * probe + */ + goto release_fw; err_unref: drm_dev_unref(drm); - return 0; - power_down: nouveau_platform_power_down(gpu); +release_fw: + if (gpu->ctxsw_fw) + release_firmware(gpu->ctxsw_fw); + return err; } @@ -161,8 +218,17 @@ static int nouveau_platform_remove(struct platform_device *pdev) } #if IS_ENABLED(CONFIG_OF) +static struct nouveau_platform_probe_data gk20a_probe_data = { + .soc = "tegra124", + .gpu = "gk20a", + .use_ext_firmware = true, +}; + static const struct of_device_id nouveau_platform_match[] = { - { .compatible = "nvidia,gk20a" }, + { + .compatible = "nvidia,gk20a", + .data = &gk20a_probe_data, + }, { } }; diff --git a/drivers/gpu/drm/nouveau/nouveau_platform.h b/drivers/gpu/drm/nouveau/nouveau_platform.h index 58c28b5653d..9753a2ea342 100644 --- a/drivers/gpu/drm/nouveau/nouveau_platform.h +++ b/drivers/gpu/drm/nouveau/nouveau_platform.h @@ -35,6 +35,8 @@ struct nouveau_platform_gpu { struct clk *clk_pwr; struct regulator *vdd; + + const struct firmware *ctxsw_fw; }; struct nouveau_platform_device { |