diff options
author | Maxime Ripard <maxime.ripard@bootlin.com> | 2019-01-21 10:45:51 -0500 |
---|---|---|
committer | Maxime Ripard <maxime.ripard@bootlin.com> | 2019-02-07 03:41:27 -0500 |
commit | 4dad3e7f12f702980f42033cf8f93525f95d8db9 (patch) | |
tree | 417ec958925cd95b7ab4989eb66323d8c00837ab | |
parent | 5d134abf9530de2f453a2a5c97d5e165bcc95b83 (diff) |
drm/bridge: cdns: Separate DSI and D-PHY configuration
The current configuration of the DSI bridge and its associated D-PHY is
intertwined. In order to ease the future conversion to the phy framework
for the D-PHY part, let's split the configuration in two.
Reviewed-by: Paul Kocialkowski <paul.kocialkowski@bootlin.com>
Signed-off-by: Maxime Ripard <maxime.ripard@bootlin.com>
Link: https://patchwork.freedesktop.org/patch/msgid/0b3bea44e05745b65c23af7926ca546bc80a1bcc.1548085432.git-series.maxime.ripard@bootlin.com
-rw-r--r-- | drivers/gpu/drm/bridge/cdns-dsi.c | 101 |
1 files changed, 73 insertions, 28 deletions
diff --git a/drivers/gpu/drm/bridge/cdns-dsi.c b/drivers/gpu/drm/bridge/cdns-dsi.c index 924abe82ea3c..0f5bb3dca828 100644 --- a/drivers/gpu/drm/bridge/cdns-dsi.c +++ b/drivers/gpu/drm/bridge/cdns-dsi.c | |||
@@ -547,6 +547,15 @@ bridge_to_cdns_dsi_input(struct drm_bridge *bridge) | |||
547 | return container_of(bridge, struct cdns_dsi_input, bridge); | 547 | return container_of(bridge, struct cdns_dsi_input, bridge); |
548 | } | 548 | } |
549 | 549 | ||
550 | static unsigned int mode_to_dpi_hfp(const struct drm_display_mode *mode, | ||
551 | bool mode_valid_check) | ||
552 | { | ||
553 | if (mode_valid_check) | ||
554 | return mode->hsync_start - mode->hdisplay; | ||
555 | |||
556 | return mode->crtc_hsync_start - mode->crtc_hdisplay; | ||
557 | } | ||
558 | |||
550 | static int cdns_dsi_get_dphy_pll_cfg(struct cdns_dphy *dphy, | 559 | static int cdns_dsi_get_dphy_pll_cfg(struct cdns_dphy *dphy, |
551 | struct cdns_dphy_cfg *cfg, | 560 | struct cdns_dphy_cfg *cfg, |
552 | unsigned int dpi_htotal, | 561 | unsigned int dpi_htotal, |
@@ -733,14 +742,12 @@ static unsigned int dpi_to_dsi_timing(unsigned int dpi_timing, | |||
733 | static int cdns_dsi_mode2cfg(struct cdns_dsi *dsi, | 742 | static int cdns_dsi_mode2cfg(struct cdns_dsi *dsi, |
734 | const struct drm_display_mode *mode, | 743 | const struct drm_display_mode *mode, |
735 | struct cdns_dsi_cfg *dsi_cfg, | 744 | struct cdns_dsi_cfg *dsi_cfg, |
736 | struct cdns_dphy_cfg *dphy_cfg, | ||
737 | bool mode_valid_check) | 745 | bool mode_valid_check) |
738 | { | 746 | { |
739 | unsigned long dsi_htotal = 0, dsi_hss_hsa_hse_hbp = 0; | ||
740 | struct cdns_dsi_output *output = &dsi->output; | 747 | struct cdns_dsi_output *output = &dsi->output; |
741 | unsigned int dsi_hfp_ext = 0, dpi_hfp, tmp; | 748 | unsigned int tmp; |
742 | bool sync_pulse = false; | 749 | bool sync_pulse = false; |
743 | int bpp, nlanes, ret; | 750 | int bpp, nlanes; |
744 | 751 | ||
745 | memset(dsi_cfg, 0, sizeof(*dsi_cfg)); | 752 | memset(dsi_cfg, 0, sizeof(*dsi_cfg)); |
746 | 753 | ||
@@ -759,8 +766,6 @@ static int cdns_dsi_mode2cfg(struct cdns_dsi *dsi, | |||
759 | mode->crtc_hsync_end : mode->crtc_hsync_start); | 766 | mode->crtc_hsync_end : mode->crtc_hsync_start); |
760 | 767 | ||
761 | dsi_cfg->hbp = dpi_to_dsi_timing(tmp, bpp, DSI_HBP_FRAME_OVERHEAD); | 768 | dsi_cfg->hbp = dpi_to_dsi_timing(tmp, bpp, DSI_HBP_FRAME_OVERHEAD); |
762 | dsi_htotal += dsi_cfg->hbp + DSI_HBP_FRAME_OVERHEAD; | ||
763 | dsi_hss_hsa_hse_hbp += dsi_cfg->hbp + DSI_HBP_FRAME_OVERHEAD; | ||
764 | 769 | ||
765 | if (sync_pulse) { | 770 | if (sync_pulse) { |
766 | if (mode_valid_check) | 771 | if (mode_valid_check) |
@@ -770,49 +775,91 @@ static int cdns_dsi_mode2cfg(struct cdns_dsi *dsi, | |||
770 | 775 | ||
771 | dsi_cfg->hsa = dpi_to_dsi_timing(tmp, bpp, | 776 | dsi_cfg->hsa = dpi_to_dsi_timing(tmp, bpp, |
772 | DSI_HSA_FRAME_OVERHEAD); | 777 | DSI_HSA_FRAME_OVERHEAD); |
773 | dsi_htotal += dsi_cfg->hsa + DSI_HSA_FRAME_OVERHEAD; | ||
774 | dsi_hss_hsa_hse_hbp += dsi_cfg->hsa + DSI_HSA_FRAME_OVERHEAD; | ||
775 | } | 778 | } |
776 | 779 | ||
777 | dsi_cfg->hact = dpi_to_dsi_timing(mode_valid_check ? | 780 | dsi_cfg->hact = dpi_to_dsi_timing(mode_valid_check ? |
778 | mode->hdisplay : mode->crtc_hdisplay, | 781 | mode->hdisplay : mode->crtc_hdisplay, |
779 | bpp, 0); | 782 | bpp, 0); |
780 | dsi_htotal += dsi_cfg->hact; | 783 | dsi_cfg->hfp = dpi_to_dsi_timing(mode_to_dpi_hfp(mode, mode_valid_check), |
784 | bpp, DSI_HFP_FRAME_OVERHEAD); | ||
781 | 785 | ||
782 | if (mode_valid_check) | 786 | return 0; |
783 | dpi_hfp = mode->hsync_start - mode->hdisplay; | 787 | } |
784 | else | 788 | |
785 | dpi_hfp = mode->crtc_hsync_start - mode->crtc_hdisplay; | 789 | static int cdns_dphy_validate(struct cdns_dsi *dsi, |
790 | struct cdns_dsi_cfg *dsi_cfg, | ||
791 | struct cdns_dphy_cfg *dphy_cfg, | ||
792 | const struct drm_display_mode *mode, | ||
793 | bool mode_valid_check) | ||
794 | { | ||
795 | struct cdns_dsi_output *output = &dsi->output; | ||
796 | unsigned long dsi_htotal; | ||
797 | unsigned int dsi_hfp_ext = 0; | ||
798 | |||
799 | int ret; | ||
800 | |||
801 | dsi_htotal = dsi_cfg->hbp + DSI_HBP_FRAME_OVERHEAD; | ||
802 | if (output->dev->mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE) | ||
803 | dsi_htotal += dsi_cfg->hsa + DSI_HSA_FRAME_OVERHEAD; | ||
786 | 804 | ||
787 | dsi_cfg->hfp = dpi_to_dsi_timing(dpi_hfp, bpp, DSI_HFP_FRAME_OVERHEAD); | 805 | dsi_htotal += dsi_cfg->hact; |
788 | dsi_htotal += dsi_cfg->hfp + DSI_HFP_FRAME_OVERHEAD; | 806 | dsi_htotal += dsi_cfg->hfp + DSI_HFP_FRAME_OVERHEAD; |
789 | 807 | ||
790 | if (mode_valid_check) | 808 | if (mode_valid_check) |
791 | ret = cdns_dsi_get_dphy_pll_cfg(dsi->dphy, dphy_cfg, | 809 | ret = cdns_dsi_get_dphy_pll_cfg(dsi->dphy, dphy_cfg, |
792 | mode->htotal, bpp, | 810 | mode->htotal, |
811 | mipi_dsi_pixel_format_to_bpp(output->dev->format), | ||
793 | mode->clock * 1000, | 812 | mode->clock * 1000, |
794 | dsi_htotal, nlanes, | 813 | dsi_htotal, |
814 | output->dev->lanes, | ||
795 | &dsi_hfp_ext); | 815 | &dsi_hfp_ext); |
796 | else | 816 | else |
797 | ret = cdns_dsi_get_dphy_pll_cfg(dsi->dphy, dphy_cfg, | 817 | ret = cdns_dsi_get_dphy_pll_cfg(dsi->dphy, dphy_cfg, |
798 | mode->crtc_htotal, bpp, | 818 | mode->crtc_htotal, |
819 | mipi_dsi_pixel_format_to_bpp(output->dev->format), | ||
799 | mode->crtc_clock * 1000, | 820 | mode->crtc_clock * 1000, |
800 | dsi_htotal, nlanes, | 821 | dsi_htotal, |
822 | output->dev->lanes, | ||
801 | &dsi_hfp_ext); | 823 | &dsi_hfp_ext); |
802 | |||
803 | if (ret) | 824 | if (ret) |
804 | return ret; | 825 | return ret; |
805 | 826 | ||
806 | dsi_cfg->hfp += dsi_hfp_ext; | 827 | dsi_cfg->hfp += dsi_hfp_ext; |
807 | dsi_htotal += dsi_hfp_ext; | 828 | dsi_cfg->htotal = dsi_htotal + dsi_hfp_ext; |
808 | dsi_cfg->htotal = dsi_htotal; | 829 | |
830 | return 0; | ||
831 | } | ||
832 | |||
833 | static int cdns_dsi_check_conf(struct cdns_dsi *dsi, | ||
834 | const struct drm_display_mode *mode, | ||
835 | struct cdns_dsi_cfg *dsi_cfg, | ||
836 | struct cdns_dphy_cfg *dphy_cfg, | ||
837 | bool mode_valid_check) | ||
838 | { | ||
839 | struct cdns_dsi_output *output = &dsi->output; | ||
840 | unsigned long dsi_hss_hsa_hse_hbp; | ||
841 | unsigned int nlanes = output->dev->lanes; | ||
842 | int ret; | ||
843 | |||
844 | ret = cdns_dsi_mode2cfg(dsi, mode, dsi_cfg, mode_valid_check); | ||
845 | if (ret) | ||
846 | return ret; | ||
847 | |||
848 | ret = cdns_dphy_validate(dsi, dsi_cfg, dphy_cfg, mode, mode_valid_check); | ||
849 | if (ret) | ||
850 | return ret; | ||
851 | |||
852 | dsi_hss_hsa_hse_hbp = dsi_cfg->hbp + DSI_HBP_FRAME_OVERHEAD; | ||
853 | if (output->dev->mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE) | ||
854 | dsi_hss_hsa_hse_hbp += dsi_cfg->hsa + DSI_HSA_FRAME_OVERHEAD; | ||
809 | 855 | ||
810 | /* | 856 | /* |
811 | * Make sure DPI(HFP) > DSI(HSS+HSA+HSE+HBP) to guarantee that the FIFO | 857 | * Make sure DPI(HFP) > DSI(HSS+HSA+HSE+HBP) to guarantee that the FIFO |
812 | * is empty before we start a receiving a new line on the DPI | 858 | * is empty before we start a receiving a new line on the DPI |
813 | * interface. | 859 | * interface. |
814 | */ | 860 | */ |
815 | if ((u64)dphy_cfg->lane_bps * dpi_hfp * nlanes < | 861 | if ((u64)dphy_cfg->lane_bps * |
862 | mode_to_dpi_hfp(mode, mode_valid_check) * nlanes < | ||
816 | (u64)dsi_hss_hsa_hse_hbp * | 863 | (u64)dsi_hss_hsa_hse_hbp * |
817 | (mode_valid_check ? mode->clock : mode->crtc_clock) * 1000) | 864 | (mode_valid_check ? mode->clock : mode->crtc_clock) * 1000) |
818 | return -EINVAL; | 865 | return -EINVAL; |
@@ -844,7 +891,7 @@ cdns_dsi_bridge_mode_valid(struct drm_bridge *bridge, | |||
844 | struct cdns_dsi_output *output = &dsi->output; | 891 | struct cdns_dsi_output *output = &dsi->output; |
845 | struct cdns_dphy_cfg dphy_cfg; | 892 | struct cdns_dphy_cfg dphy_cfg; |
846 | struct cdns_dsi_cfg dsi_cfg; | 893 | struct cdns_dsi_cfg dsi_cfg; |
847 | int bpp, nlanes, ret; | 894 | int bpp, ret; |
848 | 895 | ||
849 | /* | 896 | /* |
850 | * VFP_DSI should be less than VFP_DPI and VFP_DSI should be at | 897 | * VFP_DSI should be less than VFP_DPI and VFP_DSI should be at |
@@ -862,11 +909,9 @@ cdns_dsi_bridge_mode_valid(struct drm_bridge *bridge, | |||
862 | if ((mode->hdisplay * bpp) % 32) | 909 | if ((mode->hdisplay * bpp) % 32) |
863 | return MODE_H_ILLEGAL; | 910 | return MODE_H_ILLEGAL; |
864 | 911 | ||
865 | nlanes = output->dev->lanes; | 912 | ret = cdns_dsi_check_conf(dsi, mode, &dsi_cfg, &dphy_cfg, true); |
866 | |||
867 | ret = cdns_dsi_mode2cfg(dsi, mode, &dsi_cfg, &dphy_cfg, true); | ||
868 | if (ret) | 913 | if (ret) |
869 | return MODE_CLOCK_RANGE; | 914 | return MODE_BAD; |
870 | 915 | ||
871 | return MODE_OK; | 916 | return MODE_OK; |
872 | } | 917 | } |
@@ -992,7 +1037,7 @@ static void cdns_dsi_bridge_enable(struct drm_bridge *bridge) | |||
992 | bpp = mipi_dsi_pixel_format_to_bpp(output->dev->format); | 1037 | bpp = mipi_dsi_pixel_format_to_bpp(output->dev->format); |
993 | nlanes = output->dev->lanes; | 1038 | nlanes = output->dev->lanes; |
994 | 1039 | ||
995 | WARN_ON_ONCE(cdns_dsi_mode2cfg(dsi, mode, &dsi_cfg, &dphy_cfg, false)); | 1040 | WARN_ON_ONCE(cdns_dsi_check_conf(dsi, mode, &dsi_cfg, &dphy_cfg, false)); |
996 | 1041 | ||
997 | cdns_dsi_hs_init(dsi, &dphy_cfg); | 1042 | cdns_dsi_hs_init(dsi, &dphy_cfg); |
998 | cdns_dsi_init_link(dsi); | 1043 | cdns_dsi_init_link(dsi); |