summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexandre Courbot <acourbot@nvidia.com>2014-10-01 19:05:04 +0900
committerThierry Reding <treding@nvidia.com>2014-12-19 10:20:06 +0100
commitc7ac3b5be0265c4ca714bd0e863c69c1a7506dce (patch)
tree8e93b729dad27c7010fbd249d8215f8ad4acfe0b
parent864b8f635b0f6cf7df6f34aea990309e9f069452 (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.c76
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_platform.h2
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 {