aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThierry Reding <treding@nvidia.com>2014-12-02 11:30:23 -0500
committerThierry Reding <treding@nvidia.com>2015-01-27 04:14:48 -0500
commit5b901e78b24539f4a1e194e8058f26ab38623c37 (patch)
treeb6ba3d3a32ae2448f744ef10a8f75dcc66aa20dd
parent596827196f5fad8ac77201058978128f6c06f234 (diff)
drm/tegra: dsi: Demidlayer
Implement encoder and connector within the DSI driver itself using the Tegra output helpers rather than using the Tegra output as midlayer. By doing so one level of indirection is removed and output drivers become more flexible while keeping the majority of the advantages provided by the common output helpers. Signed-off-by: Thierry Reding <treding@nvidia.com>
-rw-r--r--drivers/gpu/drm/tegra/drm.h1
-rw-r--r--drivers/gpu/drm/tegra/dsi.c358
-rw-r--r--drivers/gpu/drm/tegra/output.c5
3 files changed, 195 insertions, 169 deletions
diff --git a/drivers/gpu/drm/tegra/drm.h b/drivers/gpu/drm/tegra/drm.h
index 95b6aebfaf00..ae3daa436ee6 100644
--- a/drivers/gpu/drm/tegra/drm.h
+++ b/drivers/gpu/drm/tegra/drm.h
@@ -193,7 +193,6 @@ struct tegra_output_ops {
193}; 193};
194 194
195enum tegra_output_type { 195enum tegra_output_type {
196 TEGRA_OUTPUT_DSI,
197 TEGRA_OUTPUT_EDP, 196 TEGRA_OUTPUT_EDP,
198}; 197};
199 198
diff --git a/drivers/gpu/drm/tegra/dsi.c b/drivers/gpu/drm/tegra/dsi.c
index 4c0dfe92402a..0b476e1c005a 100644
--- a/drivers/gpu/drm/tegra/dsi.c
+++ b/drivers/gpu/drm/tegra/dsi.c
@@ -51,7 +51,6 @@ struct tegra_dsi {
51 struct mipi_dsi_host host; 51 struct mipi_dsi_host host;
52 52
53 struct regulator *vdd; 53 struct regulator *vdd;
54 bool enabled;
55 54
56 unsigned int video_fifo_depth; 55 unsigned int video_fifo_depth;
57 unsigned int host_fifo_depth; 56 unsigned int host_fifo_depth;
@@ -628,46 +627,6 @@ static int tegra_dsi_configure(struct tegra_dsi *dsi, unsigned int pipe,
628 return 0; 627 return 0;
629} 628}
630 629
631static int tegra_output_dsi_enable(struct tegra_output *output)
632{
633 struct tegra_dc *dc = to_tegra_dc(output->encoder.crtc);
634 const struct drm_display_mode *mode = &dc->base.mode;
635 struct tegra_dsi *dsi = to_dsi(output);
636 u32 value;
637 int err;
638
639 if (dsi->enabled)
640 return 0;
641
642 err = tegra_dsi_configure(dsi, dc->pipe, mode);
643 if (err < 0)
644 return err;
645
646 /* enable display controller */
647 value = tegra_dc_readl(dc, DC_DISP_DISP_WIN_OPTIONS);
648 value |= DSI_ENABLE;
649 tegra_dc_writel(dc, value, DC_DISP_DISP_WIN_OPTIONS);
650
651 value = tegra_dc_readl(dc, DC_CMD_DISPLAY_COMMAND);
652 value &= ~DISP_CTRL_MODE_MASK;
653 value |= DISP_CTRL_MODE_C_DISPLAY;
654 tegra_dc_writel(dc, value, DC_CMD_DISPLAY_COMMAND);
655
656 value = tegra_dc_readl(dc, DC_CMD_DISPLAY_POWER_CONTROL);
657 value |= PW0_ENABLE | PW1_ENABLE | PW2_ENABLE | PW3_ENABLE |
658 PW4_ENABLE | PM0_ENABLE | PM1_ENABLE;
659 tegra_dc_writel(dc, value, DC_CMD_DISPLAY_POWER_CONTROL);
660
661 tegra_dc_commit(dc);
662
663 /* enable DSI controller */
664 tegra_dsi_enable(dsi);
665
666 dsi->enabled = true;
667
668 return 0;
669}
670
671static int tegra_dsi_wait_idle(struct tegra_dsi *dsi, unsigned long timeout) 630static int tegra_dsi_wait_idle(struct tegra_dsi *dsi, unsigned long timeout)
672{ 631{
673 u32 value; 632 u32 value;
@@ -704,6 +663,29 @@ static void tegra_dsi_ganged_disable(struct tegra_dsi *dsi)
704 tegra_dsi_writel(dsi, 0, DSI_GANGED_MODE_CONTROL); 663 tegra_dsi_writel(dsi, 0, DSI_GANGED_MODE_CONTROL);
705} 664}
706 665
666static void tegra_dsi_set_timeout(struct tegra_dsi *dsi, unsigned long bclk,
667 unsigned int vrefresh)
668{
669 unsigned int timeout;
670 u32 value;
671
672 /* one frame high-speed transmission timeout */
673 timeout = (bclk / vrefresh) / 512;
674 value = DSI_TIMEOUT_LRX(0x2000) | DSI_TIMEOUT_HTX(timeout);
675 tegra_dsi_writel(dsi, value, DSI_TIMEOUT_0);
676
677 /* 2 ms peripheral timeout for panel */
678 timeout = 2 * bclk / 512 * 1000;
679 value = DSI_TIMEOUT_PR(timeout) | DSI_TIMEOUT_TA(0x2000);
680 tegra_dsi_writel(dsi, value, DSI_TIMEOUT_1);
681
682 value = DSI_TALLY_TA(0) | DSI_TALLY_LRX(0) | DSI_TALLY_HTX(0);
683 tegra_dsi_writel(dsi, value, DSI_TO_TALLY);
684
685 if (dsi->slave)
686 tegra_dsi_set_timeout(dsi->slave, bclk, vrefresh);
687}
688
707static void tegra_dsi_disable(struct tegra_dsi *dsi) 689static void tegra_dsi_disable(struct tegra_dsi *dsi)
708{ 690{
709 u32 value; 691 u32 value;
@@ -747,82 +729,51 @@ static void tegra_dsi_soft_reset(struct tegra_dsi *dsi)
747 tegra_dsi_soft_reset(dsi->slave); 729 tegra_dsi_soft_reset(dsi->slave);
748} 730}
749 731
750static int tegra_output_dsi_disable(struct tegra_output *output) 732static void tegra_dsi_connector_dpms(struct drm_connector *connector, int mode)
751{ 733{
752 struct tegra_dc *dc = to_tegra_dc(output->encoder.crtc);
753 struct tegra_dsi *dsi = to_dsi(output);
754 u32 value;
755 int err;
756
757 if (!dsi->enabled)
758 return 0;
759
760 tegra_dsi_video_disable(dsi);
761
762 /*
763 * The following accesses registers of the display controller, so make
764 * sure it's only executed when the output is attached to one.
765 */
766 if (dc) {
767 value = tegra_dc_readl(dc, DC_CMD_DISPLAY_POWER_CONTROL);
768 value &= ~(PW0_ENABLE | PW1_ENABLE | PW2_ENABLE | PW3_ENABLE |
769 PW4_ENABLE | PM0_ENABLE | PM1_ENABLE);
770 tegra_dc_writel(dc, value, DC_CMD_DISPLAY_POWER_CONTROL);
771
772 value = tegra_dc_readl(dc, DC_DISP_DISP_WIN_OPTIONS);
773 value &= ~DSI_ENABLE;
774 tegra_dc_writel(dc, value, DC_DISP_DISP_WIN_OPTIONS);
775
776 tegra_dc_commit(dc);
777 }
778
779 err = tegra_dsi_wait_idle(dsi, 100);
780 if (err < 0)
781 dev_dbg(dsi->dev, "failed to idle DSI: %d\n", err);
782
783 tegra_dsi_soft_reset(dsi);
784 tegra_dsi_disable(dsi);
785
786 dsi->enabled = false;
787
788 return 0;
789} 734}
790 735
791static void tegra_dsi_set_timeout(struct tegra_dsi *dsi, unsigned long bclk, 736static const struct drm_connector_funcs tegra_dsi_connector_funcs = {
792 unsigned int vrefresh) 737 .dpms = tegra_dsi_connector_dpms,
793{ 738 .detect = tegra_output_connector_detect,
794 unsigned int timeout; 739 .fill_modes = drm_helper_probe_single_connector_modes,
795 u32 value; 740 .destroy = tegra_output_connector_destroy,
741};
796 742
797 /* one frame high-speed transmission timeout */ 743static enum drm_mode_status
798 timeout = (bclk / vrefresh) / 512; 744tegra_dsi_connector_mode_valid(struct drm_connector *connector,
799 value = DSI_TIMEOUT_LRX(0x2000) | DSI_TIMEOUT_HTX(timeout); 745 struct drm_display_mode *mode)
800 tegra_dsi_writel(dsi, value, DSI_TIMEOUT_0); 746{
747 return MODE_OK;
748}
801 749
802 /* 2 ms peripheral timeout for panel */ 750static const struct drm_connector_helper_funcs tegra_dsi_connector_helper_funcs = {
803 timeout = 2 * bclk / 512 * 1000; 751 .get_modes = tegra_output_connector_get_modes,
804 value = DSI_TIMEOUT_PR(timeout) | DSI_TIMEOUT_TA(0x2000); 752 .mode_valid = tegra_dsi_connector_mode_valid,
805 tegra_dsi_writel(dsi, value, DSI_TIMEOUT_1); 753 .best_encoder = tegra_output_connector_best_encoder,
754};
806 755
807 value = DSI_TALLY_TA(0) | DSI_TALLY_LRX(0) | DSI_TALLY_HTX(0); 756static const struct drm_encoder_funcs tegra_dsi_encoder_funcs = {
808 tegra_dsi_writel(dsi, value, DSI_TO_TALLY); 757 .destroy = tegra_output_encoder_destroy,
758};
809 759
810 if (dsi->slave) 760static void tegra_dsi_encoder_dpms(struct drm_encoder *encoder, int mode)
811 tegra_dsi_set_timeout(dsi->slave, bclk, vrefresh); 761{
812} 762}
813 763
814static int tegra_output_dsi_setup_clock(struct tegra_output *output, 764static bool tegra_dsi_encoder_mode_fixup(struct drm_encoder *encoder,
815 struct clk *clk, unsigned long pclk, 765 const struct drm_display_mode *mode,
816 unsigned int *divp) 766 struct drm_display_mode *adjusted)
817{ 767{
818 struct tegra_dc *dc = to_tegra_dc(output->encoder.crtc); 768 struct tegra_output *output = encoder_to_output(encoder);
819 struct drm_display_mode *mode = &dc->base.mode; 769 struct tegra_dc *dc = to_tegra_dc(encoder->crtc);
770 unsigned int mul, div, scdiv, vrefresh, lanes;
820 struct tegra_dsi *dsi = to_dsi(output); 771 struct tegra_dsi *dsi = to_dsi(output);
821 unsigned int mul, div, vrefresh, lanes; 772 unsigned long pclk, bclk, plld;
822 unsigned long bclk, plld;
823 int err; 773 int err;
824 774
825 lanes = tegra_dsi_get_lanes(dsi); 775 lanes = tegra_dsi_get_lanes(dsi);
776 pclk = mode->clock * 1000;
826 777
827 err = tegra_dsi_get_muldiv(dsi->format, &mul, &div); 778 err = tegra_dsi_get_muldiv(dsi->format, &mul, &div);
828 if (err < 0) 779 if (err < 0)
@@ -847,19 +798,6 @@ static int tegra_output_dsi_setup_clock(struct tegra_output *output,
847 */ 798 */
848 plld /= 2; 799 plld /= 2;
849 800
850 err = clk_set_parent(clk, dsi->clk_parent);
851 if (err < 0) {
852 dev_err(dsi->dev, "failed to set parent clock: %d\n", err);
853 return err;
854 }
855
856 err = clk_set_rate(dsi->clk_parent, plld);
857 if (err < 0) {
858 dev_err(dsi->dev, "failed to set base clock rate to %lu Hz\n",
859 plld);
860 return err;
861 }
862
863 /* 801 /*
864 * Derive pixel clock from bit clock using the shift clock divider. 802 * Derive pixel clock from bit clock using the shift clock divider.
865 * Note that this is only half of what we would expect, but we need 803 * Note that this is only half of what we would expect, but we need
@@ -870,39 +808,132 @@ static int tegra_output_dsi_setup_clock(struct tegra_output *output,
870 * not working properly otherwise. Perhaps the PLLs cannot generate 808 * not working properly otherwise. Perhaps the PLLs cannot generate
871 * frequencies sufficiently high. 809 * frequencies sufficiently high.
872 */ 810 */
873 *divp = ((8 * mul) / (div * lanes)) - 2; 811 scdiv = ((8 * mul) / (div * lanes)) - 2;
812
813 err = tegra_dc_setup_clock(dc, dsi->clk_parent, plld, scdiv);
814 if (err < 0) {
815 dev_err(output->dev, "failed to setup DC clock: %d\n", err);
816 return false;
817 }
818
819 err = clk_set_rate(dsi->clk_parent, plld);
820 if (err < 0) {
821 dev_err(dsi->dev, "failed to set clock rate to %lu Hz\n",
822 plld);
823 return false;
824 }
874 825
875 /*
876 * XXX: Move the below somewhere else so that we don't need to have
877 * access to the vrefresh in this function?
878 */
879 tegra_dsi_set_timeout(dsi, bclk, vrefresh); 826 tegra_dsi_set_timeout(dsi, bclk, vrefresh);
880 827
881 err = tegra_dsi_set_phy_timing(dsi); 828 err = tegra_dsi_set_phy_timing(dsi);
882 if (err < 0) 829 if (err < 0) {
883 return err; 830 dev_err(dsi->dev, "failed to setup D-PHY timing: %d\n", err);
831 return false;
832 }
884 833
885 return 0; 834 return true;
835}
836
837static void tegra_dsi_encoder_prepare(struct drm_encoder *encoder)
838{
839}
840
841static void tegra_dsi_encoder_commit(struct drm_encoder *encoder)
842{
886} 843}
887 844
888static int tegra_output_dsi_check_mode(struct tegra_output *output, 845static void tegra_dsi_encoder_mode_set(struct drm_encoder *encoder,
889 struct drm_display_mode *mode, 846 struct drm_display_mode *mode,
890 enum drm_mode_status *status) 847 struct drm_display_mode *adjusted)
848{
849 struct tegra_output *output = encoder_to_output(encoder);
850 struct tegra_dc *dc = to_tegra_dc(encoder->crtc);
851 struct tegra_dsi *dsi = to_dsi(output);
852 u32 value;
853 int err;
854
855
856 err = tegra_dsi_configure(dsi, dc->pipe, mode);
857 if (err < 0) {
858 dev_err(dsi->dev, "failed to configure DSI: %d\n", err);
859 return;
860 }
861
862 if (output->panel)
863 drm_panel_prepare(output->panel);
864
865 /* enable display controller */
866 value = tegra_dc_readl(dc, DC_DISP_DISP_WIN_OPTIONS);
867 value |= DSI_ENABLE;
868 tegra_dc_writel(dc, value, DC_DISP_DISP_WIN_OPTIONS);
869
870 value = tegra_dc_readl(dc, DC_CMD_DISPLAY_COMMAND);
871 value &= ~DISP_CTRL_MODE_MASK;
872 value |= DISP_CTRL_MODE_C_DISPLAY;
873 tegra_dc_writel(dc, value, DC_CMD_DISPLAY_COMMAND);
874
875 value = tegra_dc_readl(dc, DC_CMD_DISPLAY_POWER_CONTROL);
876 value |= PW0_ENABLE | PW1_ENABLE | PW2_ENABLE | PW3_ENABLE |
877 PW4_ENABLE | PM0_ENABLE | PM1_ENABLE;
878 tegra_dc_writel(dc, value, DC_CMD_DISPLAY_POWER_CONTROL);
879
880 tegra_dc_commit(dc);
881
882 /* enable DSI controller */
883 tegra_dsi_enable(dsi);
884
885 if (output->panel)
886 drm_panel_enable(output->panel);
887
888 return;
889}
890
891static void tegra_dsi_encoder_disable(struct drm_encoder *encoder)
891{ 892{
893 struct tegra_output *output = encoder_to_output(encoder);
894 struct tegra_dc *dc = to_tegra_dc(encoder->crtc);
895 struct tegra_dsi *dsi = to_dsi(output);
896 u32 value;
897 int err;
898
899 if (output->panel)
900 drm_panel_disable(output->panel);
901
902 tegra_dsi_video_disable(dsi);
903
892 /* 904 /*
893 * FIXME: For now, always assume that the mode is okay. 905 * The following accesses registers of the display controller, so make
906 * sure it's only executed when the output is attached to one.
894 */ 907 */
908 if (dc) {
909 value = tegra_dc_readl(dc, DC_DISP_DISP_WIN_OPTIONS);
910 value &= ~DSI_ENABLE;
911 tegra_dc_writel(dc, value, DC_DISP_DISP_WIN_OPTIONS);
895 912
896 *status = MODE_OK; 913 tegra_dc_commit(dc);
914 }
897 915
898 return 0; 916 err = tegra_dsi_wait_idle(dsi, 100);
917 if (err < 0)
918 dev_dbg(dsi->dev, "failed to idle DSI: %d\n", err);
919
920 tegra_dsi_soft_reset(dsi);
921
922 if (output->panel)
923 drm_panel_unprepare(output->panel);
924
925 tegra_dsi_disable(dsi);
926
927 return;
899} 928}
900 929
901static const struct tegra_output_ops dsi_ops = { 930static const struct drm_encoder_helper_funcs tegra_dsi_encoder_helper_funcs = {
902 .enable = tegra_output_dsi_enable, 931 .dpms = tegra_dsi_encoder_dpms,
903 .disable = tegra_output_dsi_disable, 932 .mode_fixup = tegra_dsi_encoder_mode_fixup,
904 .setup_clock = tegra_output_dsi_setup_clock, 933 .prepare = tegra_dsi_encoder_prepare,
905 .check_mode = tegra_output_dsi_check_mode, 934 .commit = tegra_dsi_encoder_commit,
935 .mode_set = tegra_dsi_encoder_mode_set,
936 .disable = tegra_dsi_encoder_disable,
906}; 937};
907 938
908static int tegra_dsi_pad_enable(struct tegra_dsi *dsi) 939static int tegra_dsi_pad_enable(struct tegra_dsi *dsi)
@@ -952,15 +983,30 @@ static int tegra_dsi_init(struct host1x_client *client)
952 983
953 /* Gangsters must not register their own outputs. */ 984 /* Gangsters must not register their own outputs. */
954 if (!dsi->master) { 985 if (!dsi->master) {
955 dsi->output.type = TEGRA_OUTPUT_DSI;
956 dsi->output.dev = client->dev; 986 dsi->output.dev = client->dev;
957 dsi->output.ops = &dsi_ops;
958 987
959 err = tegra_output_init(drm, &dsi->output); 988 drm_connector_init(drm, &dsi->output.connector,
960 if (err < 0) { 989 &tegra_dsi_connector_funcs,
961 dev_err(client->dev, "output setup failed: %d\n", err); 990 DRM_MODE_CONNECTOR_DSI);
962 return err; 991 drm_connector_helper_add(&dsi->output.connector,
963 } 992 &tegra_dsi_connector_helper_funcs);
993 dsi->output.connector.dpms = DRM_MODE_DPMS_OFF;
994
995 if (dsi->output.panel)
996 drm_panel_attach(dsi->output.panel,
997 &dsi->output.connector);
998
999 drm_encoder_init(drm, &dsi->output.encoder,
1000 &tegra_dsi_encoder_funcs,
1001 DRM_MODE_ENCODER_DSI);
1002 drm_encoder_helper_add(&dsi->output.encoder,
1003 &tegra_dsi_encoder_helper_funcs);
1004
1005 drm_mode_connector_attach_encoder(&dsi->output.connector,
1006 &dsi->output.encoder);
1007 drm_connector_register(&dsi->output.connector);
1008
1009 dsi->output.encoder.possible_crtcs = 0x3;
964 } 1010 }
965 1011
966 if (IS_ENABLED(CONFIG_DEBUG_FS)) { 1012 if (IS_ENABLED(CONFIG_DEBUG_FS)) {
@@ -981,28 +1027,14 @@ static int tegra_dsi_exit(struct host1x_client *client)
981 struct tegra_dsi *dsi = host1x_client_to_dsi(client); 1027 struct tegra_dsi *dsi = host1x_client_to_dsi(client);
982 int err; 1028 int err;
983 1029
1030 tegra_output_exit(&dsi->output);
1031
984 if (IS_ENABLED(CONFIG_DEBUG_FS)) { 1032 if (IS_ENABLED(CONFIG_DEBUG_FS)) {
985 err = tegra_dsi_debugfs_exit(dsi); 1033 err = tegra_dsi_debugfs_exit(dsi);
986 if (err < 0) 1034 if (err < 0)
987 dev_err(dsi->dev, "debugfs cleanup failed: %d\n", err); 1035 dev_err(dsi->dev, "debugfs cleanup failed: %d\n", err);
988 } 1036 }
989 1037
990 if (!dsi->master) {
991 err = tegra_output_disable(&dsi->output);
992 if (err < 0) {
993 dev_err(client->dev, "output failed to disable: %d\n",
994 err);
995 return err;
996 }
997
998 err = tegra_output_exit(&dsi->output);
999 if (err < 0) {
1000 dev_err(client->dev, "output cleanup failed: %d\n",
1001 err);
1002 return err;
1003 }
1004 }
1005
1006 reset_control_assert(dsi->rst); 1038 reset_control_assert(dsi->rst);
1007 1039
1008 return 0; 1040 return 0;
@@ -1547,6 +1579,12 @@ static int tegra_dsi_remove(struct platform_device *pdev)
1547 return err; 1579 return err;
1548 } 1580 }
1549 1581
1582 err = tegra_output_remove(&dsi->output);
1583 if (err < 0) {
1584 dev_err(&pdev->dev, "failed to remove output: %d\n", err);
1585 return err;
1586 }
1587
1550 mipi_dsi_host_unregister(&dsi->host); 1588 mipi_dsi_host_unregister(&dsi->host);
1551 tegra_mipi_free(dsi->mipi); 1589 tegra_mipi_free(dsi->mipi);
1552 1590
@@ -1555,12 +1593,6 @@ static int tegra_dsi_remove(struct platform_device *pdev)
1555 clk_disable_unprepare(dsi->clk); 1593 clk_disable_unprepare(dsi->clk);
1556 reset_control_assert(dsi->rst); 1594 reset_control_assert(dsi->rst);
1557 1595
1558 err = tegra_output_remove(&dsi->output);
1559 if (err < 0) {
1560 dev_err(&pdev->dev, "failed to remove output: %d\n", err);
1561 return err;
1562 }
1563
1564 return 0; 1596 return 0;
1565} 1597}
1566 1598
diff --git a/drivers/gpu/drm/tegra/output.c b/drivers/gpu/drm/tegra/output.c
index c7ebe8ea3868..81de885226ff 100644
--- a/drivers/gpu/drm/tegra/output.c
+++ b/drivers/gpu/drm/tegra/output.c
@@ -274,11 +274,6 @@ int tegra_output_init(struct drm_device *drm, struct tegra_output *output)
274 int connector, encoder; 274 int connector, encoder;
275 275
276 switch (output->type) { 276 switch (output->type) {
277 case TEGRA_OUTPUT_DSI:
278 connector = DRM_MODE_CONNECTOR_DSI;
279 encoder = DRM_MODE_ENCODER_DSI;
280 break;
281
282 case TEGRA_OUTPUT_EDP: 277 case TEGRA_OUTPUT_EDP:
283 connector = DRM_MODE_CONNECTOR_eDP; 278 connector = DRM_MODE_CONNECTOR_eDP;
284 encoder = DRM_MODE_ENCODER_TMDS; 279 encoder = DRM_MODE_ENCODER_TMDS;