aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/tegra/dsi.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/tegra/dsi.c')
-rw-r--r--drivers/gpu/drm/tegra/dsi.c127
1 files changed, 65 insertions, 62 deletions
diff --git a/drivers/gpu/drm/tegra/dsi.c b/drivers/gpu/drm/tegra/dsi.c
index dc97c0b3681d..f0a138ef68ce 100644
--- a/drivers/gpu/drm/tegra/dsi.c
+++ b/drivers/gpu/drm/tegra/dsi.c
@@ -119,6 +119,16 @@ static int tegra_dsi_show_regs(struct seq_file *s, void *data)
119{ 119{
120 struct drm_info_node *node = s->private; 120 struct drm_info_node *node = s->private;
121 struct tegra_dsi *dsi = node->info_ent->data; 121 struct tegra_dsi *dsi = node->info_ent->data;
122 struct drm_crtc *crtc = dsi->output.encoder.crtc;
123 struct drm_device *drm = node->minor->dev;
124 int err = 0;
125
126 drm_modeset_lock_all(drm);
127
128 if (!crtc || !crtc->state->active) {
129 err = -EBUSY;
130 goto unlock;
131 }
122 132
123#define DUMP_REG(name) \ 133#define DUMP_REG(name) \
124 seq_printf(s, "%-32s %#05x %08x\n", #name, name, \ 134 seq_printf(s, "%-32s %#05x %08x\n", #name, name, \
@@ -208,7 +218,9 @@ static int tegra_dsi_show_regs(struct seq_file *s, void *data)
208 218
209#undef DUMP_REG 219#undef DUMP_REG
210 220
211 return 0; 221unlock:
222 drm_modeset_unlock_all(drm);
223 return err;
212} 224}
213 225
214static struct drm_info_list debugfs_files[] = { 226static struct drm_info_list debugfs_files[] = {
@@ -548,14 +560,19 @@ static void tegra_dsi_configure(struct tegra_dsi *dsi, unsigned int pipe,
548 560
549 /* horizontal sync width */ 561 /* horizontal sync width */
550 hsw = (mode->hsync_end - mode->hsync_start) * mul / div; 562 hsw = (mode->hsync_end - mode->hsync_start) * mul / div;
551 hsw -= 10;
552 563
553 /* horizontal back porch */ 564 /* horizontal back porch */
554 hbp = (mode->htotal - mode->hsync_end) * mul / div; 565 hbp = (mode->htotal - mode->hsync_end) * mul / div;
555 hbp -= 14; 566
567 if ((dsi->flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE) == 0)
568 hbp += hsw;
556 569
557 /* horizontal front porch */ 570 /* horizontal front porch */
558 hfp = (mode->hsync_start - mode->hdisplay) * mul / div; 571 hfp = (mode->hsync_start - mode->hdisplay) * mul / div;
572
573 /* subtract packet overhead */
574 hsw -= 10;
575 hbp -= 14;
559 hfp -= 8; 576 hfp -= 8;
560 577
561 tegra_dsi_writel(dsi, hsw << 16 | 0, DSI_PKT_LEN_0_1); 578 tegra_dsi_writel(dsi, hsw << 16 | 0, DSI_PKT_LEN_0_1);
@@ -726,11 +743,6 @@ static void tegra_dsi_soft_reset(struct tegra_dsi *dsi)
726 tegra_dsi_soft_reset(dsi->slave); 743 tegra_dsi_soft_reset(dsi->slave);
727} 744}
728 745
729static int tegra_dsi_connector_dpms(struct drm_connector *connector, int mode)
730{
731 return 0;
732}
733
734static void tegra_dsi_connector_reset(struct drm_connector *connector) 746static void tegra_dsi_connector_reset(struct drm_connector *connector)
735{ 747{
736 struct tegra_dsi_state *state; 748 struct tegra_dsi_state *state;
@@ -757,7 +769,7 @@ tegra_dsi_connector_duplicate_state(struct drm_connector *connector)
757} 769}
758 770
759static const struct drm_connector_funcs tegra_dsi_connector_funcs = { 771static const struct drm_connector_funcs tegra_dsi_connector_funcs = {
760 .dpms = tegra_dsi_connector_dpms, 772 .dpms = drm_atomic_helper_connector_dpms,
761 .reset = tegra_dsi_connector_reset, 773 .reset = tegra_dsi_connector_reset,
762 .detect = tegra_output_connector_detect, 774 .detect = tegra_output_connector_detect,
763 .fill_modes = drm_helper_probe_single_connector_modes, 775 .fill_modes = drm_helper_probe_single_connector_modes,
@@ -783,22 +795,48 @@ static const struct drm_encoder_funcs tegra_dsi_encoder_funcs = {
783 .destroy = tegra_output_encoder_destroy, 795 .destroy = tegra_output_encoder_destroy,
784}; 796};
785 797
786static void tegra_dsi_encoder_dpms(struct drm_encoder *encoder, int mode) 798static void tegra_dsi_encoder_disable(struct drm_encoder *encoder)
787{ 799{
788} 800 struct tegra_output *output = encoder_to_output(encoder);
801 struct tegra_dc *dc = to_tegra_dc(encoder->crtc);
802 struct tegra_dsi *dsi = to_dsi(output);
803 u32 value;
804 int err;
789 805
790static void tegra_dsi_encoder_prepare(struct drm_encoder *encoder) 806 if (output->panel)
791{ 807 drm_panel_disable(output->panel);
792}
793 808
794static void tegra_dsi_encoder_commit(struct drm_encoder *encoder) 809 tegra_dsi_video_disable(dsi);
795{ 810
811 /*
812 * The following accesses registers of the display controller, so make
813 * sure it's only executed when the output is attached to one.
814 */
815 if (dc) {
816 value = tegra_dc_readl(dc, DC_DISP_DISP_WIN_OPTIONS);
817 value &= ~DSI_ENABLE;
818 tegra_dc_writel(dc, value, DC_DISP_DISP_WIN_OPTIONS);
819
820 tegra_dc_commit(dc);
821 }
822
823 err = tegra_dsi_wait_idle(dsi, 100);
824 if (err < 0)
825 dev_dbg(dsi->dev, "failed to idle DSI: %d\n", err);
826
827 tegra_dsi_soft_reset(dsi);
828
829 if (output->panel)
830 drm_panel_unprepare(output->panel);
831
832 tegra_dsi_disable(dsi);
833
834 return;
796} 835}
797 836
798static void tegra_dsi_encoder_mode_set(struct drm_encoder *encoder, 837static void tegra_dsi_encoder_enable(struct drm_encoder *encoder)
799 struct drm_display_mode *mode,
800 struct drm_display_mode *adjusted)
801{ 838{
839 struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode;
802 struct tegra_output *output = encoder_to_output(encoder); 840 struct tegra_output *output = encoder_to_output(encoder);
803 struct tegra_dc *dc = to_tegra_dc(encoder->crtc); 841 struct tegra_dc *dc = to_tegra_dc(encoder->crtc);
804 struct tegra_dsi *dsi = to_dsi(output); 842 struct tegra_dsi *dsi = to_dsi(output);
@@ -836,45 +874,6 @@ static void tegra_dsi_encoder_mode_set(struct drm_encoder *encoder,
836 return; 874 return;
837} 875}
838 876
839static void tegra_dsi_encoder_disable(struct drm_encoder *encoder)
840{
841 struct tegra_output *output = encoder_to_output(encoder);
842 struct tegra_dc *dc = to_tegra_dc(encoder->crtc);
843 struct tegra_dsi *dsi = to_dsi(output);
844 u32 value;
845 int err;
846
847 if (output->panel)
848 drm_panel_disable(output->panel);
849
850 tegra_dsi_video_disable(dsi);
851
852 /*
853 * The following accesses registers of the display controller, so make
854 * sure it's only executed when the output is attached to one.
855 */
856 if (dc) {
857 value = tegra_dc_readl(dc, DC_DISP_DISP_WIN_OPTIONS);
858 value &= ~DSI_ENABLE;
859 tegra_dc_writel(dc, value, DC_DISP_DISP_WIN_OPTIONS);
860
861 tegra_dc_commit(dc);
862 }
863
864 err = tegra_dsi_wait_idle(dsi, 100);
865 if (err < 0)
866 dev_dbg(dsi->dev, "failed to idle DSI: %d\n", err);
867
868 tegra_dsi_soft_reset(dsi);
869
870 if (output->panel)
871 drm_panel_unprepare(output->panel);
872
873 tegra_dsi_disable(dsi);
874
875 return;
876}
877
878static int 877static int
879tegra_dsi_encoder_atomic_check(struct drm_encoder *encoder, 878tegra_dsi_encoder_atomic_check(struct drm_encoder *encoder,
880 struct drm_crtc_state *crtc_state, 879 struct drm_crtc_state *crtc_state,
@@ -957,11 +956,8 @@ tegra_dsi_encoder_atomic_check(struct drm_encoder *encoder,
957} 956}
958 957
959static const struct drm_encoder_helper_funcs tegra_dsi_encoder_helper_funcs = { 958static const struct drm_encoder_helper_funcs tegra_dsi_encoder_helper_funcs = {
960 .dpms = tegra_dsi_encoder_dpms,
961 .prepare = tegra_dsi_encoder_prepare,
962 .commit = tegra_dsi_encoder_commit,
963 .mode_set = tegra_dsi_encoder_mode_set,
964 .disable = tegra_dsi_encoder_disable, 959 .disable = tegra_dsi_encoder_disable,
960 .enable = tegra_dsi_encoder_enable,
965 .atomic_check = tegra_dsi_encoder_atomic_check, 961 .atomic_check = tegra_dsi_encoder_atomic_check,
966}; 962};
967 963
@@ -993,6 +989,10 @@ static int tegra_dsi_pad_calibrate(struct tegra_dsi *dsi)
993 DSI_PAD_OUT_CLK(0x0); 989 DSI_PAD_OUT_CLK(0x0);
994 tegra_dsi_writel(dsi, value, DSI_PAD_CONTROL_2); 990 tegra_dsi_writel(dsi, value, DSI_PAD_CONTROL_2);
995 991
992 value = DSI_PAD_PREEMP_PD_CLK(0x3) | DSI_PAD_PREEMP_PU_CLK(0x3) |
993 DSI_PAD_PREEMP_PD(0x03) | DSI_PAD_PREEMP_PU(0x3);
994 tegra_dsi_writel(dsi, value, DSI_PAD_CONTROL_3);
995
996 return tegra_mipi_calibrate(dsi->mipi); 996 return tegra_mipi_calibrate(dsi->mipi);
997} 997}
998 998
@@ -1622,6 +1622,9 @@ static int tegra_dsi_remove(struct platform_device *pdev)
1622} 1622}
1623 1623
1624static const struct of_device_id tegra_dsi_of_match[] = { 1624static const struct of_device_id tegra_dsi_of_match[] = {
1625 { .compatible = "nvidia,tegra210-dsi", },
1626 { .compatible = "nvidia,tegra132-dsi", },
1627 { .compatible = "nvidia,tegra124-dsi", },
1625 { .compatible = "nvidia,tegra114-dsi", }, 1628 { .compatible = "nvidia,tegra114-dsi", },
1626 { }, 1629 { },
1627}; 1630};