Loading drivers/gpu/drm/tegra/dpaux.c +76 −40 Original line number Diff line number Diff line Loading @@ -15,6 +15,7 @@ #include <linux/pinctrl/pinconf-generic.h> #include <linux/pinctrl/pinctrl.h> #include <linux/pinctrl/pinmux.h> #include <linux/pm_runtime.h> #include <linux/platform_device.h> #include <linux/reset.h> #include <linux/regulator/consumer.h> Loading Loading @@ -467,52 +468,37 @@ static int tegra_dpaux_probe(struct platform_device *pdev) return PTR_ERR(dpaux->clk); } err = clk_prepare_enable(dpaux->clk); if (err < 0) { dev_err(&pdev->dev, "failed to enable module clock: %d\n", err); return err; } if (dpaux->rst) reset_control_deassert(dpaux->rst); dpaux->clk_parent = devm_clk_get(&pdev->dev, "parent"); if (IS_ERR(dpaux->clk_parent)) { dev_err(&pdev->dev, "failed to get parent clock: %ld\n", PTR_ERR(dpaux->clk_parent)); err = PTR_ERR(dpaux->clk_parent); goto assert_reset; } err = clk_prepare_enable(dpaux->clk_parent); if (err < 0) { dev_err(&pdev->dev, "failed to enable parent clock: %d\n", err); goto assert_reset; return PTR_ERR(dpaux->clk_parent); } err = clk_set_rate(dpaux->clk_parent, 270000000); if (err < 0) { dev_err(&pdev->dev, "failed to set clock to 270 MHz: %d\n", err); goto disable_parent_clk; return err; } dpaux->vdd = devm_regulator_get(&pdev->dev, "vdd"); if (IS_ERR(dpaux->vdd)) { dev_err(&pdev->dev, "failed to get VDD supply: %ld\n", PTR_ERR(dpaux->vdd)); err = PTR_ERR(dpaux->vdd); goto disable_parent_clk; return PTR_ERR(dpaux->vdd); } platform_set_drvdata(pdev, dpaux); pm_runtime_enable(&pdev->dev); pm_runtime_get_sync(&pdev->dev); err = devm_request_irq(dpaux->dev, dpaux->irq, tegra_dpaux_irq, 0, dev_name(dpaux->dev), dpaux); if (err < 0) { dev_err(dpaux->dev, "failed to request IRQ#%u: %d\n", dpaux->irq, err); goto disable_parent_clk; return err; } disable_irq(dpaux->irq); Loading @@ -522,7 +508,7 @@ static int tegra_dpaux_probe(struct platform_device *pdev) err = drm_dp_aux_register(&dpaux->aux); if (err < 0) goto disable_parent_clk; return err; /* * Assume that by default the DPAUX/I2C pads will be used for HDMI, Loading Loading @@ -560,45 +546,94 @@ static int tegra_dpaux_probe(struct platform_device *pdev) list_add_tail(&dpaux->list, &dpaux_list); mutex_unlock(&dpaux_lock); platform_set_drvdata(pdev, dpaux); return 0; disable_parent_clk: clk_disable_unprepare(dpaux->clk_parent); assert_reset: if (dpaux->rst) reset_control_assert(dpaux->rst); clk_disable_unprepare(dpaux->clk); return err; } static int tegra_dpaux_remove(struct platform_device *pdev) { struct tegra_dpaux *dpaux = platform_get_drvdata(pdev); cancel_work_sync(&dpaux->work); /* make sure pads are powered down when not in use */ tegra_dpaux_pad_power_down(dpaux); pm_runtime_put(&pdev->dev); pm_runtime_disable(&pdev->dev); drm_dp_aux_unregister(&dpaux->aux); mutex_lock(&dpaux_lock); list_del(&dpaux->list); mutex_unlock(&dpaux_lock); cancel_work_sync(&dpaux->work); return 0; } clk_disable_unprepare(dpaux->clk_parent); #ifdef CONFIG_PM static int tegra_dpaux_suspend(struct device *dev) { struct tegra_dpaux *dpaux = dev_get_drvdata(dev); int err = 0; if (dpaux->rst) { err = reset_control_assert(dpaux->rst); if (err < 0) { dev_err(dev, "failed to assert reset: %d\n", err); return err; } } if (dpaux->rst) reset_control_assert(dpaux->rst); usleep_range(1000, 2000); clk_disable_unprepare(dpaux->clk_parent); clk_disable_unprepare(dpaux->clk); return err; } static int tegra_dpaux_resume(struct device *dev) { struct tegra_dpaux *dpaux = dev_get_drvdata(dev); int err; err = clk_prepare_enable(dpaux->clk); if (err < 0) { dev_err(dev, "failed to enable clock: %d\n", err); return err; } err = clk_prepare_enable(dpaux->clk_parent); if (err < 0) { dev_err(dev, "failed to enable parent clock: %d\n", err); goto disable_clk; } usleep_range(1000, 2000); if (dpaux->rst) { err = reset_control_deassert(dpaux->rst); if (err < 0) { dev_err(dev, "failed to deassert reset: %d\n", err); goto disable_parent; } usleep_range(1000, 2000); } return 0; disable_parent: clk_disable_unprepare(dpaux->clk_parent); disable_clk: clk_disable_unprepare(dpaux->clk); return err; } #endif static const struct dev_pm_ops tegra_dpaux_pm_ops = { SET_RUNTIME_PM_OPS(tegra_dpaux_suspend, tegra_dpaux_resume, NULL) }; static const struct of_device_id tegra_dpaux_of_match[] = { { .compatible = "nvidia,tegra210-dpaux", }, Loading @@ -611,6 +646,7 @@ struct platform_driver tegra_dpaux_driver = { .driver = { .name = "tegra-dpaux", .of_match_table = tegra_dpaux_of_match, .pm = &tegra_dpaux_pm_ops, }, .probe = tegra_dpaux_probe, .remove = tegra_dpaux_remove, Loading Loading
drivers/gpu/drm/tegra/dpaux.c +76 −40 Original line number Diff line number Diff line Loading @@ -15,6 +15,7 @@ #include <linux/pinctrl/pinconf-generic.h> #include <linux/pinctrl/pinctrl.h> #include <linux/pinctrl/pinmux.h> #include <linux/pm_runtime.h> #include <linux/platform_device.h> #include <linux/reset.h> #include <linux/regulator/consumer.h> Loading Loading @@ -467,52 +468,37 @@ static int tegra_dpaux_probe(struct platform_device *pdev) return PTR_ERR(dpaux->clk); } err = clk_prepare_enable(dpaux->clk); if (err < 0) { dev_err(&pdev->dev, "failed to enable module clock: %d\n", err); return err; } if (dpaux->rst) reset_control_deassert(dpaux->rst); dpaux->clk_parent = devm_clk_get(&pdev->dev, "parent"); if (IS_ERR(dpaux->clk_parent)) { dev_err(&pdev->dev, "failed to get parent clock: %ld\n", PTR_ERR(dpaux->clk_parent)); err = PTR_ERR(dpaux->clk_parent); goto assert_reset; } err = clk_prepare_enable(dpaux->clk_parent); if (err < 0) { dev_err(&pdev->dev, "failed to enable parent clock: %d\n", err); goto assert_reset; return PTR_ERR(dpaux->clk_parent); } err = clk_set_rate(dpaux->clk_parent, 270000000); if (err < 0) { dev_err(&pdev->dev, "failed to set clock to 270 MHz: %d\n", err); goto disable_parent_clk; return err; } dpaux->vdd = devm_regulator_get(&pdev->dev, "vdd"); if (IS_ERR(dpaux->vdd)) { dev_err(&pdev->dev, "failed to get VDD supply: %ld\n", PTR_ERR(dpaux->vdd)); err = PTR_ERR(dpaux->vdd); goto disable_parent_clk; return PTR_ERR(dpaux->vdd); } platform_set_drvdata(pdev, dpaux); pm_runtime_enable(&pdev->dev); pm_runtime_get_sync(&pdev->dev); err = devm_request_irq(dpaux->dev, dpaux->irq, tegra_dpaux_irq, 0, dev_name(dpaux->dev), dpaux); if (err < 0) { dev_err(dpaux->dev, "failed to request IRQ#%u: %d\n", dpaux->irq, err); goto disable_parent_clk; return err; } disable_irq(dpaux->irq); Loading @@ -522,7 +508,7 @@ static int tegra_dpaux_probe(struct platform_device *pdev) err = drm_dp_aux_register(&dpaux->aux); if (err < 0) goto disable_parent_clk; return err; /* * Assume that by default the DPAUX/I2C pads will be used for HDMI, Loading Loading @@ -560,45 +546,94 @@ static int tegra_dpaux_probe(struct platform_device *pdev) list_add_tail(&dpaux->list, &dpaux_list); mutex_unlock(&dpaux_lock); platform_set_drvdata(pdev, dpaux); return 0; disable_parent_clk: clk_disable_unprepare(dpaux->clk_parent); assert_reset: if (dpaux->rst) reset_control_assert(dpaux->rst); clk_disable_unprepare(dpaux->clk); return err; } static int tegra_dpaux_remove(struct platform_device *pdev) { struct tegra_dpaux *dpaux = platform_get_drvdata(pdev); cancel_work_sync(&dpaux->work); /* make sure pads are powered down when not in use */ tegra_dpaux_pad_power_down(dpaux); pm_runtime_put(&pdev->dev); pm_runtime_disable(&pdev->dev); drm_dp_aux_unregister(&dpaux->aux); mutex_lock(&dpaux_lock); list_del(&dpaux->list); mutex_unlock(&dpaux_lock); cancel_work_sync(&dpaux->work); return 0; } clk_disable_unprepare(dpaux->clk_parent); #ifdef CONFIG_PM static int tegra_dpaux_suspend(struct device *dev) { struct tegra_dpaux *dpaux = dev_get_drvdata(dev); int err = 0; if (dpaux->rst) { err = reset_control_assert(dpaux->rst); if (err < 0) { dev_err(dev, "failed to assert reset: %d\n", err); return err; } } if (dpaux->rst) reset_control_assert(dpaux->rst); usleep_range(1000, 2000); clk_disable_unprepare(dpaux->clk_parent); clk_disable_unprepare(dpaux->clk); return err; } static int tegra_dpaux_resume(struct device *dev) { struct tegra_dpaux *dpaux = dev_get_drvdata(dev); int err; err = clk_prepare_enable(dpaux->clk); if (err < 0) { dev_err(dev, "failed to enable clock: %d\n", err); return err; } err = clk_prepare_enable(dpaux->clk_parent); if (err < 0) { dev_err(dev, "failed to enable parent clock: %d\n", err); goto disable_clk; } usleep_range(1000, 2000); if (dpaux->rst) { err = reset_control_deassert(dpaux->rst); if (err < 0) { dev_err(dev, "failed to deassert reset: %d\n", err); goto disable_parent; } usleep_range(1000, 2000); } return 0; disable_parent: clk_disable_unprepare(dpaux->clk_parent); disable_clk: clk_disable_unprepare(dpaux->clk); return err; } #endif static const struct dev_pm_ops tegra_dpaux_pm_ops = { SET_RUNTIME_PM_OPS(tegra_dpaux_suspend, tegra_dpaux_resume, NULL) }; static const struct of_device_id tegra_dpaux_of_match[] = { { .compatible = "nvidia,tegra210-dpaux", }, Loading @@ -611,6 +646,7 @@ struct platform_driver tegra_dpaux_driver = { .driver = { .name = "tegra-dpaux", .of_match_table = tegra_dpaux_of_match, .pm = &tegra_dpaux_pm_ops, }, .probe = tegra_dpaux_probe, .remove = tegra_dpaux_remove, Loading