diff options
author | Thierry Reding <treding@nvidia.com> | 2013-10-14 14:26:42 +0200 |
---|---|---|
committer | Thierry Reding <treding@nvidia.com> | 2013-10-31 09:55:41 +0100 |
commit | 59d29c0ec93fe9879673b302a182fb3fb80896c3 (patch) | |
tree | 47158501586464399b9dd50da13cb7265166d7d3 /drivers/gpu/drm/tegra/output.c | |
parent | f002abc19acb6f7cdb3d320f3b6f1a565c0be63e (diff) | |
download | linux-stable-59d29c0ec93fe9879673b302a182fb3fb80896c3.tar.gz linux-stable-59d29c0ec93fe9879673b302a182fb3fb80896c3.tar.bz2 linux-stable-59d29c0ec93fe9879673b302a182fb3fb80896c3.zip |
drm/tegra: Allocate resources at probe time
Since the .init() and .exit() functions are executed whenever the DRM
driver is loaded or unloaded, care must be taken not to use them for
resource allocation. Otherwise deferred probing cannot be used, since
the .init() and .exit() are not run at probe time. Similarly the code
that frees resources must be run at .remove() time. If it is run from
the .exit() function, it can release resources multiple times.
To handle this more consistently, rename the tegra_output_parse_dt()
function to tegra_output_probe() and introduce tegra_output_remove()
which can be used to free output-related resources.
Signed-off-by: Thierry Reding <treding@nvidia.com>
Diffstat (limited to 'drivers/gpu/drm/tegra/output.c')
-rw-r--r-- | drivers/gpu/drm/tegra/output.c | 49 |
1 files changed, 25 insertions, 24 deletions
diff --git a/drivers/gpu/drm/tegra/output.c b/drivers/gpu/drm/tegra/output.c index 591d3b0186d8..708cbfffb059 100644 --- a/drivers/gpu/drm/tegra/output.c +++ b/drivers/gpu/drm/tegra/output.c @@ -161,7 +161,7 @@ static irqreturn_t hpd_irq(int irq, void *data) return IRQ_HANDLED; } -int tegra_output_parse_dt(struct tegra_output *output) +int tegra_output_probe(struct tegra_output *output) { enum of_gpio_flags flags; struct device_node *ddc; @@ -191,14 +191,6 @@ int tegra_output_parse_dt(struct tegra_output *output) output->hpd_gpio = of_get_named_gpio_flags(output->of_node, "nvidia,hpd-gpio", 0, &flags); - - return 0; -} - -int tegra_output_init(struct drm_device *drm, struct tegra_output *output) -{ - int connector, encoder, err; - if (gpio_is_valid(output->hpd_gpio)) { unsigned long flags; @@ -212,7 +204,8 @@ int tegra_output_init(struct drm_device *drm, struct tegra_output *output) err = gpio_to_irq(output->hpd_gpio); if (err < 0) { dev_err(output->dev, "gpio_to_irq(): %d\n", err); - goto free_hpd; + gpio_free(output->hpd_gpio); + return err; } output->hpd_irq = err; @@ -225,12 +218,33 @@ int tegra_output_init(struct drm_device *drm, struct tegra_output *output) if (err < 0) { dev_err(output->dev, "failed to request IRQ#%u: %d\n", output->hpd_irq, err); - goto free_hpd; + gpio_free(output->hpd_gpio); + return err; } output->connector.polled = DRM_CONNECTOR_POLL_HPD; } + return 0; +} + +int tegra_output_remove(struct tegra_output *output) +{ + if (gpio_is_valid(output->hpd_gpio)) { + free_irq(output->hpd_irq, output); + gpio_free(output->hpd_gpio); + } + + if (output->ddc) + put_device(&output->ddc->dev); + + return 0; +} + +int tegra_output_init(struct drm_device *drm, struct tegra_output *output) +{ + int connector, encoder; + switch (output->type) { case TEGRA_OUTPUT_RGB: connector = DRM_MODE_CONNECTOR_LVDS; @@ -261,22 +275,9 @@ int tegra_output_init(struct drm_device *drm, struct tegra_output *output) output->encoder.possible_crtcs = 0x3; return 0; - -free_hpd: - gpio_free(output->hpd_gpio); - - return err; } int tegra_output_exit(struct tegra_output *output) { - if (gpio_is_valid(output->hpd_gpio)) { - free_irq(output->hpd_irq, output); - gpio_free(output->hpd_gpio); - } - - if (output->ddc) - put_device(&output->ddc->dev); - return 0; } |