diff options
Diffstat (limited to 'drivers/gpu/drm/tegra/dsi.c')
-rw-r--r-- | drivers/gpu/drm/tegra/dsi.c | 248 |
1 files changed, 141 insertions, 107 deletions
diff --git a/drivers/gpu/drm/tegra/dsi.c b/drivers/gpu/drm/tegra/dsi.c index d1239ebc190f..3d228ad90e0f 100644 --- a/drivers/gpu/drm/tegra/dsi.c +++ b/drivers/gpu/drm/tegra/dsi.c | |||
@@ -13,6 +13,7 @@ | |||
13 | #include <linux/of.h> | 13 | #include <linux/of.h> |
14 | #include <linux/of_platform.h> | 14 | #include <linux/of_platform.h> |
15 | #include <linux/platform_device.h> | 15 | #include <linux/platform_device.h> |
16 | #include <linux/pm_runtime.h> | ||
16 | #include <linux/reset.h> | 17 | #include <linux/reset.h> |
17 | 18 | ||
18 | #include <linux/regulator/consumer.h> | 19 | #include <linux/regulator/consumer.h> |
@@ -677,6 +678,45 @@ static void tegra_dsi_ganged_disable(struct tegra_dsi *dsi) | |||
677 | tegra_dsi_writel(dsi, 0, DSI_GANGED_MODE_CONTROL); | 678 | tegra_dsi_writel(dsi, 0, DSI_GANGED_MODE_CONTROL); |
678 | } | 679 | } |
679 | 680 | ||
681 | static int tegra_dsi_pad_enable(struct tegra_dsi *dsi) | ||
682 | { | ||
683 | u32 value; | ||
684 | |||
685 | value = DSI_PAD_CONTROL_VS1_PULLDN(0) | DSI_PAD_CONTROL_VS1_PDIO(0); | ||
686 | tegra_dsi_writel(dsi, value, DSI_PAD_CONTROL_0); | ||
687 | |||
688 | return 0; | ||
689 | } | ||
690 | |||
691 | static int tegra_dsi_pad_calibrate(struct tegra_dsi *dsi) | ||
692 | { | ||
693 | u32 value; | ||
694 | |||
695 | /* | ||
696 | * XXX Is this still needed? The module reset is deasserted right | ||
697 | * before this function is called. | ||
698 | */ | ||
699 | tegra_dsi_writel(dsi, 0, DSI_PAD_CONTROL_0); | ||
700 | tegra_dsi_writel(dsi, 0, DSI_PAD_CONTROL_1); | ||
701 | tegra_dsi_writel(dsi, 0, DSI_PAD_CONTROL_2); | ||
702 | tegra_dsi_writel(dsi, 0, DSI_PAD_CONTROL_3); | ||
703 | tegra_dsi_writel(dsi, 0, DSI_PAD_CONTROL_4); | ||
704 | |||
705 | /* start calibration */ | ||
706 | tegra_dsi_pad_enable(dsi); | ||
707 | |||
708 | value = DSI_PAD_SLEW_UP(0x7) | DSI_PAD_SLEW_DN(0x7) | | ||
709 | DSI_PAD_LP_UP(0x1) | DSI_PAD_LP_DN(0x1) | | ||
710 | DSI_PAD_OUT_CLK(0x0); | ||
711 | tegra_dsi_writel(dsi, value, DSI_PAD_CONTROL_2); | ||
712 | |||
713 | value = DSI_PAD_PREEMP_PD_CLK(0x3) | DSI_PAD_PREEMP_PU_CLK(0x3) | | ||
714 | DSI_PAD_PREEMP_PD(0x03) | DSI_PAD_PREEMP_PU(0x3); | ||
715 | tegra_dsi_writel(dsi, value, DSI_PAD_CONTROL_3); | ||
716 | |||
717 | return tegra_mipi_calibrate(dsi->mipi); | ||
718 | } | ||
719 | |||
680 | static void tegra_dsi_set_timeout(struct tegra_dsi *dsi, unsigned long bclk, | 720 | static void tegra_dsi_set_timeout(struct tegra_dsi *dsi, unsigned long bclk, |
681 | unsigned int vrefresh) | 721 | unsigned int vrefresh) |
682 | { | 722 | { |
@@ -794,7 +834,6 @@ tegra_dsi_connector_mode_valid(struct drm_connector *connector, | |||
794 | static const struct drm_connector_helper_funcs tegra_dsi_connector_helper_funcs = { | 834 | static const struct drm_connector_helper_funcs tegra_dsi_connector_helper_funcs = { |
795 | .get_modes = tegra_output_connector_get_modes, | 835 | .get_modes = tegra_output_connector_get_modes, |
796 | .mode_valid = tegra_dsi_connector_mode_valid, | 836 | .mode_valid = tegra_dsi_connector_mode_valid, |
797 | .best_encoder = tegra_output_connector_best_encoder, | ||
798 | }; | 837 | }; |
799 | 838 | ||
800 | static const struct drm_encoder_funcs tegra_dsi_encoder_funcs = { | 839 | static const struct drm_encoder_funcs tegra_dsi_encoder_funcs = { |
@@ -837,7 +876,7 @@ static void tegra_dsi_encoder_disable(struct drm_encoder *encoder) | |||
837 | 876 | ||
838 | tegra_dsi_disable(dsi); | 877 | tegra_dsi_disable(dsi); |
839 | 878 | ||
840 | return; | 879 | pm_runtime_put(dsi->dev); |
841 | } | 880 | } |
842 | 881 | ||
843 | static void tegra_dsi_encoder_enable(struct drm_encoder *encoder) | 882 | static void tegra_dsi_encoder_enable(struct drm_encoder *encoder) |
@@ -848,6 +887,13 @@ static void tegra_dsi_encoder_enable(struct drm_encoder *encoder) | |||
848 | struct tegra_dsi *dsi = to_dsi(output); | 887 | struct tegra_dsi *dsi = to_dsi(output); |
849 | struct tegra_dsi_state *state; | 888 | struct tegra_dsi_state *state; |
850 | u32 value; | 889 | u32 value; |
890 | int err; | ||
891 | |||
892 | pm_runtime_get_sync(dsi->dev); | ||
893 | |||
894 | err = tegra_dsi_pad_calibrate(dsi); | ||
895 | if (err < 0) | ||
896 | dev_err(dsi->dev, "MIPI calibration failed: %d\n", err); | ||
851 | 897 | ||
852 | state = tegra_dsi_get_state(dsi); | 898 | state = tegra_dsi_get_state(dsi); |
853 | 899 | ||
@@ -876,8 +922,6 @@ static void tegra_dsi_encoder_enable(struct drm_encoder *encoder) | |||
876 | 922 | ||
877 | if (output->panel) | 923 | if (output->panel) |
878 | drm_panel_enable(output->panel); | 924 | drm_panel_enable(output->panel); |
879 | |||
880 | return; | ||
881 | } | 925 | } |
882 | 926 | ||
883 | static int | 927 | static int |
@@ -967,55 +1011,12 @@ static const struct drm_encoder_helper_funcs tegra_dsi_encoder_helper_funcs = { | |||
967 | .atomic_check = tegra_dsi_encoder_atomic_check, | 1011 | .atomic_check = tegra_dsi_encoder_atomic_check, |
968 | }; | 1012 | }; |
969 | 1013 | ||
970 | static int tegra_dsi_pad_enable(struct tegra_dsi *dsi) | ||
971 | { | ||
972 | u32 value; | ||
973 | |||
974 | value = DSI_PAD_CONTROL_VS1_PULLDN(0) | DSI_PAD_CONTROL_VS1_PDIO(0); | ||
975 | tegra_dsi_writel(dsi, value, DSI_PAD_CONTROL_0); | ||
976 | |||
977 | return 0; | ||
978 | } | ||
979 | |||
980 | static int tegra_dsi_pad_calibrate(struct tegra_dsi *dsi) | ||
981 | { | ||
982 | u32 value; | ||
983 | |||
984 | tegra_dsi_writel(dsi, 0, DSI_PAD_CONTROL_0); | ||
985 | tegra_dsi_writel(dsi, 0, DSI_PAD_CONTROL_1); | ||
986 | tegra_dsi_writel(dsi, 0, DSI_PAD_CONTROL_2); | ||
987 | tegra_dsi_writel(dsi, 0, DSI_PAD_CONTROL_3); | ||
988 | tegra_dsi_writel(dsi, 0, DSI_PAD_CONTROL_4); | ||
989 | |||
990 | /* start calibration */ | ||
991 | tegra_dsi_pad_enable(dsi); | ||
992 | |||
993 | value = DSI_PAD_SLEW_UP(0x7) | DSI_PAD_SLEW_DN(0x7) | | ||
994 | DSI_PAD_LP_UP(0x1) | DSI_PAD_LP_DN(0x1) | | ||
995 | DSI_PAD_OUT_CLK(0x0); | ||
996 | tegra_dsi_writel(dsi, value, DSI_PAD_CONTROL_2); | ||
997 | |||
998 | value = DSI_PAD_PREEMP_PD_CLK(0x3) | DSI_PAD_PREEMP_PU_CLK(0x3) | | ||
999 | DSI_PAD_PREEMP_PD(0x03) | DSI_PAD_PREEMP_PU(0x3); | ||
1000 | tegra_dsi_writel(dsi, value, DSI_PAD_CONTROL_3); | ||
1001 | |||
1002 | return tegra_mipi_calibrate(dsi->mipi); | ||
1003 | } | ||
1004 | |||
1005 | static int tegra_dsi_init(struct host1x_client *client) | 1014 | static int tegra_dsi_init(struct host1x_client *client) |
1006 | { | 1015 | { |
1007 | struct drm_device *drm = dev_get_drvdata(client->parent); | 1016 | struct drm_device *drm = dev_get_drvdata(client->parent); |
1008 | struct tegra_dsi *dsi = host1x_client_to_dsi(client); | 1017 | struct tegra_dsi *dsi = host1x_client_to_dsi(client); |
1009 | int err; | 1018 | int err; |
1010 | 1019 | ||
1011 | reset_control_deassert(dsi->rst); | ||
1012 | |||
1013 | err = tegra_dsi_pad_calibrate(dsi); | ||
1014 | if (err < 0) { | ||
1015 | dev_err(dsi->dev, "MIPI calibration failed: %d\n", err); | ||
1016 | goto reset; | ||
1017 | } | ||
1018 | |||
1019 | /* Gangsters must not register their own outputs. */ | 1020 | /* Gangsters must not register their own outputs. */ |
1020 | if (!dsi->master) { | 1021 | if (!dsi->master) { |
1021 | dsi->output.dev = client->dev; | 1022 | dsi->output.dev = client->dev; |
@@ -1038,12 +1039,9 @@ static int tegra_dsi_init(struct host1x_client *client) | |||
1038 | drm_connector_register(&dsi->output.connector); | 1039 | drm_connector_register(&dsi->output.connector); |
1039 | 1040 | ||
1040 | err = tegra_output_init(drm, &dsi->output); | 1041 | err = tegra_output_init(drm, &dsi->output); |
1041 | if (err < 0) { | 1042 | if (err < 0) |
1042 | dev_err(client->dev, | 1043 | dev_err(dsi->dev, "failed to initialize output: %d\n", |
1043 | "failed to initialize output: %d\n", | ||
1044 | err); | 1044 | err); |
1045 | goto reset; | ||
1046 | } | ||
1047 | 1045 | ||
1048 | dsi->output.encoder.possible_crtcs = 0x3; | 1046 | dsi->output.encoder.possible_crtcs = 0x3; |
1049 | } | 1047 | } |
@@ -1055,10 +1053,6 @@ static int tegra_dsi_init(struct host1x_client *client) | |||
1055 | } | 1053 | } |
1056 | 1054 | ||
1057 | return 0; | 1055 | return 0; |
1058 | |||
1059 | reset: | ||
1060 | reset_control_assert(dsi->rst); | ||
1061 | return err; | ||
1062 | } | 1056 | } |
1063 | 1057 | ||
1064 | static int tegra_dsi_exit(struct host1x_client *client) | 1058 | static int tegra_dsi_exit(struct host1x_client *client) |
@@ -1070,7 +1064,7 @@ static int tegra_dsi_exit(struct host1x_client *client) | |||
1070 | if (IS_ENABLED(CONFIG_DEBUG_FS)) | 1064 | if (IS_ENABLED(CONFIG_DEBUG_FS)) |
1071 | tegra_dsi_debugfs_exit(dsi); | 1065 | tegra_dsi_debugfs_exit(dsi); |
1072 | 1066 | ||
1073 | reset_control_assert(dsi->rst); | 1067 | regulator_disable(dsi->vdd); |
1074 | 1068 | ||
1075 | return 0; | 1069 | return 0; |
1076 | } | 1070 | } |
@@ -1494,74 +1488,50 @@ static int tegra_dsi_probe(struct platform_device *pdev) | |||
1494 | dsi->format = MIPI_DSI_FMT_RGB888; | 1488 | dsi->format = MIPI_DSI_FMT_RGB888; |
1495 | dsi->lanes = 4; | 1489 | dsi->lanes = 4; |
1496 | 1490 | ||
1497 | dsi->rst = devm_reset_control_get(&pdev->dev, "dsi"); | 1491 | if (!pdev->dev.pm_domain) { |
1498 | if (IS_ERR(dsi->rst)) | 1492 | dsi->rst = devm_reset_control_get(&pdev->dev, "dsi"); |
1499 | return PTR_ERR(dsi->rst); | 1493 | if (IS_ERR(dsi->rst)) |
1494 | return PTR_ERR(dsi->rst); | ||
1495 | } | ||
1500 | 1496 | ||
1501 | dsi->clk = devm_clk_get(&pdev->dev, NULL); | 1497 | dsi->clk = devm_clk_get(&pdev->dev, NULL); |
1502 | if (IS_ERR(dsi->clk)) { | 1498 | if (IS_ERR(dsi->clk)) { |
1503 | dev_err(&pdev->dev, "cannot get DSI clock\n"); | 1499 | dev_err(&pdev->dev, "cannot get DSI clock\n"); |
1504 | err = PTR_ERR(dsi->clk); | 1500 | return PTR_ERR(dsi->clk); |
1505 | goto reset; | ||
1506 | } | ||
1507 | |||
1508 | err = clk_prepare_enable(dsi->clk); | ||
1509 | if (err < 0) { | ||
1510 | dev_err(&pdev->dev, "cannot enable DSI clock\n"); | ||
1511 | goto reset; | ||
1512 | } | 1501 | } |
1513 | 1502 | ||
1514 | dsi->clk_lp = devm_clk_get(&pdev->dev, "lp"); | 1503 | dsi->clk_lp = devm_clk_get(&pdev->dev, "lp"); |
1515 | if (IS_ERR(dsi->clk_lp)) { | 1504 | if (IS_ERR(dsi->clk_lp)) { |
1516 | dev_err(&pdev->dev, "cannot get low-power clock\n"); | 1505 | dev_err(&pdev->dev, "cannot get low-power clock\n"); |
1517 | err = PTR_ERR(dsi->clk_lp); | 1506 | return PTR_ERR(dsi->clk_lp); |
1518 | goto disable_clk; | ||
1519 | } | ||
1520 | |||
1521 | err = clk_prepare_enable(dsi->clk_lp); | ||
1522 | if (err < 0) { | ||
1523 | dev_err(&pdev->dev, "cannot enable low-power clock\n"); | ||
1524 | goto disable_clk; | ||
1525 | } | 1507 | } |
1526 | 1508 | ||
1527 | dsi->clk_parent = devm_clk_get(&pdev->dev, "parent"); | 1509 | dsi->clk_parent = devm_clk_get(&pdev->dev, "parent"); |
1528 | if (IS_ERR(dsi->clk_parent)) { | 1510 | if (IS_ERR(dsi->clk_parent)) { |
1529 | dev_err(&pdev->dev, "cannot get parent clock\n"); | 1511 | dev_err(&pdev->dev, "cannot get parent clock\n"); |
1530 | err = PTR_ERR(dsi->clk_parent); | 1512 | return PTR_ERR(dsi->clk_parent); |
1531 | goto disable_clk_lp; | ||
1532 | } | 1513 | } |
1533 | 1514 | ||
1534 | dsi->vdd = devm_regulator_get(&pdev->dev, "avdd-dsi-csi"); | 1515 | dsi->vdd = devm_regulator_get(&pdev->dev, "avdd-dsi-csi"); |
1535 | if (IS_ERR(dsi->vdd)) { | 1516 | if (IS_ERR(dsi->vdd)) { |
1536 | dev_err(&pdev->dev, "cannot get VDD supply\n"); | 1517 | dev_err(&pdev->dev, "cannot get VDD supply\n"); |
1537 | err = PTR_ERR(dsi->vdd); | 1518 | return PTR_ERR(dsi->vdd); |
1538 | goto disable_clk_lp; | ||
1539 | } | ||
1540 | |||
1541 | err = regulator_enable(dsi->vdd); | ||
1542 | if (err < 0) { | ||
1543 | dev_err(&pdev->dev, "cannot enable VDD supply\n"); | ||
1544 | goto disable_clk_lp; | ||
1545 | } | 1519 | } |
1546 | 1520 | ||
1547 | err = tegra_dsi_setup_clocks(dsi); | 1521 | err = tegra_dsi_setup_clocks(dsi); |
1548 | if (err < 0) { | 1522 | if (err < 0) { |
1549 | dev_err(&pdev->dev, "cannot setup clocks\n"); | 1523 | dev_err(&pdev->dev, "cannot setup clocks\n"); |
1550 | goto disable_vdd; | 1524 | return err; |
1551 | } | 1525 | } |
1552 | 1526 | ||
1553 | regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 1527 | regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
1554 | dsi->regs = devm_ioremap_resource(&pdev->dev, regs); | 1528 | dsi->regs = devm_ioremap_resource(&pdev->dev, regs); |
1555 | if (IS_ERR(dsi->regs)) { | 1529 | if (IS_ERR(dsi->regs)) |
1556 | err = PTR_ERR(dsi->regs); | 1530 | return PTR_ERR(dsi->regs); |
1557 | goto disable_vdd; | ||
1558 | } | ||
1559 | 1531 | ||
1560 | dsi->mipi = tegra_mipi_request(&pdev->dev); | 1532 | dsi->mipi = tegra_mipi_request(&pdev->dev); |
1561 | if (IS_ERR(dsi->mipi)) { | 1533 | if (IS_ERR(dsi->mipi)) |
1562 | err = PTR_ERR(dsi->mipi); | 1534 | return PTR_ERR(dsi->mipi); |
1563 | goto disable_vdd; | ||
1564 | } | ||
1565 | 1535 | ||
1566 | dsi->host.ops = &tegra_dsi_host_ops; | 1536 | dsi->host.ops = &tegra_dsi_host_ops; |
1567 | dsi->host.dev = &pdev->dev; | 1537 | dsi->host.dev = &pdev->dev; |
@@ -1572,6 +1542,9 @@ static int tegra_dsi_probe(struct platform_device *pdev) | |||
1572 | goto mipi_free; | 1542 | goto mipi_free; |
1573 | } | 1543 | } |
1574 | 1544 | ||
1545 | platform_set_drvdata(pdev, dsi); | ||
1546 | pm_runtime_enable(&pdev->dev); | ||
1547 | |||
1575 | INIT_LIST_HEAD(&dsi->client.list); | 1548 | INIT_LIST_HEAD(&dsi->client.list); |
1576 | dsi->client.ops = &dsi_client_ops; | 1549 | dsi->client.ops = &dsi_client_ops; |
1577 | dsi->client.dev = &pdev->dev; | 1550 | dsi->client.dev = &pdev->dev; |
@@ -1583,22 +1556,12 @@ static int tegra_dsi_probe(struct platform_device *pdev) | |||
1583 | goto unregister; | 1556 | goto unregister; |
1584 | } | 1557 | } |
1585 | 1558 | ||
1586 | platform_set_drvdata(pdev, dsi); | ||
1587 | |||
1588 | return 0; | 1559 | return 0; |
1589 | 1560 | ||
1590 | unregister: | 1561 | unregister: |
1591 | mipi_dsi_host_unregister(&dsi->host); | 1562 | mipi_dsi_host_unregister(&dsi->host); |
1592 | mipi_free: | 1563 | mipi_free: |
1593 | tegra_mipi_free(dsi->mipi); | 1564 | tegra_mipi_free(dsi->mipi); |
1594 | disable_vdd: | ||
1595 | regulator_disable(dsi->vdd); | ||
1596 | disable_clk_lp: | ||
1597 | clk_disable_unprepare(dsi->clk_lp); | ||
1598 | disable_clk: | ||
1599 | clk_disable_unprepare(dsi->clk); | ||
1600 | reset: | ||
1601 | reset_control_assert(dsi->rst); | ||
1602 | return err; | 1565 | return err; |
1603 | } | 1566 | } |
1604 | 1567 | ||
@@ -1607,6 +1570,8 @@ static int tegra_dsi_remove(struct platform_device *pdev) | |||
1607 | struct tegra_dsi *dsi = platform_get_drvdata(pdev); | 1570 | struct tegra_dsi *dsi = platform_get_drvdata(pdev); |
1608 | int err; | 1571 | int err; |
1609 | 1572 | ||
1573 | pm_runtime_disable(&pdev->dev); | ||
1574 | |||
1610 | err = host1x_client_unregister(&dsi->client); | 1575 | err = host1x_client_unregister(&dsi->client); |
1611 | if (err < 0) { | 1576 | if (err < 0) { |
1612 | dev_err(&pdev->dev, "failed to unregister host1x client: %d\n", | 1577 | dev_err(&pdev->dev, "failed to unregister host1x client: %d\n", |
@@ -1619,14 +1584,82 @@ static int tegra_dsi_remove(struct platform_device *pdev) | |||
1619 | mipi_dsi_host_unregister(&dsi->host); | 1584 | mipi_dsi_host_unregister(&dsi->host); |
1620 | tegra_mipi_free(dsi->mipi); | 1585 | tegra_mipi_free(dsi->mipi); |
1621 | 1586 | ||
1622 | regulator_disable(dsi->vdd); | 1587 | return 0; |
1588 | } | ||
1589 | |||
1590 | #ifdef CONFIG_PM | ||
1591 | static int tegra_dsi_suspend(struct device *dev) | ||
1592 | { | ||
1593 | struct tegra_dsi *dsi = dev_get_drvdata(dev); | ||
1594 | int err; | ||
1595 | |||
1596 | if (dsi->rst) { | ||
1597 | err = reset_control_assert(dsi->rst); | ||
1598 | if (err < 0) { | ||
1599 | dev_err(dev, "failed to assert reset: %d\n", err); | ||
1600 | return err; | ||
1601 | } | ||
1602 | } | ||
1603 | |||
1604 | usleep_range(1000, 2000); | ||
1605 | |||
1623 | clk_disable_unprepare(dsi->clk_lp); | 1606 | clk_disable_unprepare(dsi->clk_lp); |
1624 | clk_disable_unprepare(dsi->clk); | 1607 | clk_disable_unprepare(dsi->clk); |
1625 | reset_control_assert(dsi->rst); | 1608 | |
1609 | regulator_disable(dsi->vdd); | ||
1626 | 1610 | ||
1627 | return 0; | 1611 | return 0; |
1628 | } | 1612 | } |
1629 | 1613 | ||
1614 | static int tegra_dsi_resume(struct device *dev) | ||
1615 | { | ||
1616 | struct tegra_dsi *dsi = dev_get_drvdata(dev); | ||
1617 | int err; | ||
1618 | |||
1619 | err = regulator_enable(dsi->vdd); | ||
1620 | if (err < 0) { | ||
1621 | dev_err(dsi->dev, "failed to enable VDD supply: %d\n", err); | ||
1622 | return err; | ||
1623 | } | ||
1624 | |||
1625 | err = clk_prepare_enable(dsi->clk); | ||
1626 | if (err < 0) { | ||
1627 | dev_err(dev, "cannot enable DSI clock: %d\n", err); | ||
1628 | goto disable_vdd; | ||
1629 | } | ||
1630 | |||
1631 | err = clk_prepare_enable(dsi->clk_lp); | ||
1632 | if (err < 0) { | ||
1633 | dev_err(dev, "cannot enable low-power clock: %d\n", err); | ||
1634 | goto disable_clk; | ||
1635 | } | ||
1636 | |||
1637 | usleep_range(1000, 2000); | ||
1638 | |||
1639 | if (dsi->rst) { | ||
1640 | err = reset_control_deassert(dsi->rst); | ||
1641 | if (err < 0) { | ||
1642 | dev_err(dev, "cannot assert reset: %d\n", err); | ||
1643 | goto disable_clk_lp; | ||
1644 | } | ||
1645 | } | ||
1646 | |||
1647 | return 0; | ||
1648 | |||
1649 | disable_clk_lp: | ||
1650 | clk_disable_unprepare(dsi->clk_lp); | ||
1651 | disable_clk: | ||
1652 | clk_disable_unprepare(dsi->clk); | ||
1653 | disable_vdd: | ||
1654 | regulator_disable(dsi->vdd); | ||
1655 | return err; | ||
1656 | } | ||
1657 | #endif | ||
1658 | |||
1659 | static const struct dev_pm_ops tegra_dsi_pm_ops = { | ||
1660 | SET_RUNTIME_PM_OPS(tegra_dsi_suspend, tegra_dsi_resume, NULL) | ||
1661 | }; | ||
1662 | |||
1630 | static const struct of_device_id tegra_dsi_of_match[] = { | 1663 | static const struct of_device_id tegra_dsi_of_match[] = { |
1631 | { .compatible = "nvidia,tegra210-dsi", }, | 1664 | { .compatible = "nvidia,tegra210-dsi", }, |
1632 | { .compatible = "nvidia,tegra132-dsi", }, | 1665 | { .compatible = "nvidia,tegra132-dsi", }, |
@@ -1640,6 +1673,7 @@ struct platform_driver tegra_dsi_driver = { | |||
1640 | .driver = { | 1673 | .driver = { |
1641 | .name = "tegra-dsi", | 1674 | .name = "tegra-dsi", |
1642 | .of_match_table = tegra_dsi_of_match, | 1675 | .of_match_table = tegra_dsi_of_match, |
1676 | .pm = &tegra_dsi_pm_ops, | ||
1643 | }, | 1677 | }, |
1644 | .probe = tegra_dsi_probe, | 1678 | .probe = tegra_dsi_probe, |
1645 | .remove = tegra_dsi_remove, | 1679 | .remove = tegra_dsi_remove, |