aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/video')
-rw-r--r--drivers/video/omap2/dss/dsi.c181
1 files changed, 181 insertions, 0 deletions
diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
index e2aaf5a167fa..f2d835fc4dc3 100644
--- a/drivers/video/omap2/dss/dsi.c
+++ b/drivers/video/omap2/dss/dsi.c
@@ -3665,6 +3665,186 @@ static void dsi_config_blanking_modes(struct omap_dss_device *dssdev)
3665 dsi_write_reg(dsidev, DSI_CTRL, r); 3665 dsi_write_reg(dsidev, DSI_CTRL, r);
3666} 3666}
3667 3667
3668/*
3669 * According to section 'HS Command Mode Interleaving' in OMAP TRM, Scenario 3
3670 * results in maximum transition time for data and clock lanes to enter and
3671 * exit HS mode. Hence, this is the scenario where the least amount of command
3672 * mode data can be interleaved. We program the minimum amount of TXBYTECLKHS
3673 * clock cycles that can be used to interleave command mode data in HS so that
3674 * all scenarios are satisfied.
3675 */
3676static int dsi_compute_interleave_hs(int blank, bool ddr_alwon, int enter_hs,
3677 int exit_hs, int exiths_clk, int ddr_pre, int ddr_post)
3678{
3679 int transition;
3680
3681 /*
3682 * If DDR_CLK_ALWAYS_ON is set, we need to consider HS mode transition
3683 * time of data lanes only, if it isn't set, we need to consider HS
3684 * transition time of both data and clock lanes. HS transition time
3685 * of Scenario 3 is considered.
3686 */
3687 if (ddr_alwon) {
3688 transition = enter_hs + exit_hs + max(enter_hs, 2) + 1;
3689 } else {
3690 int trans1, trans2;
3691 trans1 = ddr_pre + enter_hs + exit_hs + max(enter_hs, 2) + 1;
3692 trans2 = ddr_pre + enter_hs + exiths_clk + ddr_post + ddr_pre +
3693 enter_hs + 1;
3694 transition = max(trans1, trans2);
3695 }
3696
3697 return blank > transition ? blank - transition : 0;
3698}
3699
3700/*
3701 * According to section 'LP Command Mode Interleaving' in OMAP TRM, Scenario 1
3702 * results in maximum transition time for data lanes to enter and exit LP mode.
3703 * Hence, this is the scenario where the least amount of command mode data can
3704 * be interleaved. We program the minimum amount of bytes that can be
3705 * interleaved in LP so that all scenarios are satisfied.
3706 */
3707static int dsi_compute_interleave_lp(int blank, int enter_hs, int exit_hs,
3708 int lp_clk_div, int tdsi_fclk)
3709{
3710 int trans_lp; /* time required for a LP transition, in TXBYTECLKHS */
3711 int tlp_avail; /* time left for interleaving commands, in CLKIN4DDR */
3712 int ttxclkesc; /* period of LP transmit escape clock, in CLKIN4DDR */
3713 int thsbyte_clk = 16; /* Period of TXBYTECLKHS clock, in CLKIN4DDR */
3714 int lp_inter; /* cmd mode data that can be interleaved, in bytes */
3715
3716 /* maximum LP transition time according to Scenario 1 */
3717 trans_lp = exit_hs + max(enter_hs, 2) + 1;
3718
3719 /* CLKIN4DDR = 16 * TXBYTECLKHS */
3720 tlp_avail = thsbyte_clk * (blank - trans_lp);
3721
3722 ttxclkesc = tdsi_fclk / lp_clk_div;
3723
3724 lp_inter = ((tlp_avail - 8 * thsbyte_clk - 5 * tdsi_fclk) / ttxclkesc -
3725 26) / 16;
3726
3727 return max(lp_inter, 0);
3728}
3729
3730static void dsi_config_cmd_mode_interleaving(struct omap_dss_device *dssdev)
3731{
3732 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
3733 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
3734 int blanking_mode;
3735 int hfp_blanking_mode, hbp_blanking_mode, hsa_blanking_mode;
3736 int hsa, hfp, hbp, width_bytes, bllp, lp_clk_div;
3737 int ddr_clk_pre, ddr_clk_post, enter_hs_mode_lat, exit_hs_mode_lat;
3738 int tclk_trail, ths_exit, exiths_clk;
3739 bool ddr_alwon;
3740 struct omap_video_timings *timings = &dssdev->panel.timings;
3741 int bpp = dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt);
3742 int ndl = dsi->num_lanes_used - 1;
3743 int dsi_fclk_hsdiv = dssdev->clocks.dsi.regm_dsi + 1;
3744 int hsa_interleave_hs = 0, hsa_interleave_lp = 0;
3745 int hfp_interleave_hs = 0, hfp_interleave_lp = 0;
3746 int hbp_interleave_hs = 0, hbp_interleave_lp = 0;
3747 int bl_interleave_hs = 0, bl_interleave_lp = 0;
3748 u32 r;
3749
3750 r = dsi_read_reg(dsidev, DSI_CTRL);
3751 blanking_mode = FLD_GET(r, 20, 20);
3752 hfp_blanking_mode = FLD_GET(r, 21, 21);
3753 hbp_blanking_mode = FLD_GET(r, 22, 22);
3754 hsa_blanking_mode = FLD_GET(r, 23, 23);
3755
3756 r = dsi_read_reg(dsidev, DSI_VM_TIMING1);
3757 hbp = FLD_GET(r, 11, 0);
3758 hfp = FLD_GET(r, 23, 12);
3759 hsa = FLD_GET(r, 31, 24);
3760
3761 r = dsi_read_reg(dsidev, DSI_CLK_TIMING);
3762 ddr_clk_post = FLD_GET(r, 7, 0);
3763 ddr_clk_pre = FLD_GET(r, 15, 8);
3764
3765 r = dsi_read_reg(dsidev, DSI_VM_TIMING7);
3766 exit_hs_mode_lat = FLD_GET(r, 15, 0);
3767 enter_hs_mode_lat = FLD_GET(r, 31, 16);
3768
3769 r = dsi_read_reg(dsidev, DSI_CLK_CTRL);
3770 lp_clk_div = FLD_GET(r, 12, 0);
3771 ddr_alwon = FLD_GET(r, 13, 13);
3772
3773 r = dsi_read_reg(dsidev, DSI_DSIPHY_CFG0);
3774 ths_exit = FLD_GET(r, 7, 0);
3775
3776 r = dsi_read_reg(dsidev, DSI_DSIPHY_CFG1);
3777 tclk_trail = FLD_GET(r, 15, 8);
3778
3779 exiths_clk = ths_exit + tclk_trail;
3780
3781 width_bytes = DIV_ROUND_UP(timings->x_res * bpp, 8);
3782 bllp = hbp + hfp + hsa + DIV_ROUND_UP(width_bytes + 6, ndl);
3783
3784 if (!hsa_blanking_mode) {
3785 hsa_interleave_hs = dsi_compute_interleave_hs(hsa, ddr_alwon,
3786 enter_hs_mode_lat, exit_hs_mode_lat,
3787 exiths_clk, ddr_clk_pre, ddr_clk_post);
3788 hsa_interleave_lp = dsi_compute_interleave_lp(hsa,
3789 enter_hs_mode_lat, exit_hs_mode_lat,
3790 lp_clk_div, dsi_fclk_hsdiv);
3791 }
3792
3793 if (!hfp_blanking_mode) {
3794 hfp_interleave_hs = dsi_compute_interleave_hs(hfp, ddr_alwon,
3795 enter_hs_mode_lat, exit_hs_mode_lat,
3796 exiths_clk, ddr_clk_pre, ddr_clk_post);
3797 hfp_interleave_lp = dsi_compute_interleave_lp(hfp,
3798 enter_hs_mode_lat, exit_hs_mode_lat,
3799 lp_clk_div, dsi_fclk_hsdiv);
3800 }
3801
3802 if (!hbp_blanking_mode) {
3803 hbp_interleave_hs = dsi_compute_interleave_hs(hbp, ddr_alwon,
3804 enter_hs_mode_lat, exit_hs_mode_lat,
3805 exiths_clk, ddr_clk_pre, ddr_clk_post);
3806
3807 hbp_interleave_lp = dsi_compute_interleave_lp(hbp,
3808 enter_hs_mode_lat, exit_hs_mode_lat,
3809 lp_clk_div, dsi_fclk_hsdiv);
3810 }
3811
3812 if (!blanking_mode) {
3813 bl_interleave_hs = dsi_compute_interleave_hs(bllp, ddr_alwon,
3814 enter_hs_mode_lat, exit_hs_mode_lat,
3815 exiths_clk, ddr_clk_pre, ddr_clk_post);
3816
3817 bl_interleave_lp = dsi_compute_interleave_lp(bllp,
3818 enter_hs_mode_lat, exit_hs_mode_lat,
3819 lp_clk_div, dsi_fclk_hsdiv);
3820 }
3821
3822 DSSDBG("DSI HS interleaving(TXBYTECLKHS) HSA %d, HFP %d, HBP %d, BLLP %d\n",
3823 hsa_interleave_hs, hfp_interleave_hs, hbp_interleave_hs,
3824 bl_interleave_hs);
3825
3826 DSSDBG("DSI LP interleaving(bytes) HSA %d, HFP %d, HBP %d, BLLP %d\n",
3827 hsa_interleave_lp, hfp_interleave_lp, hbp_interleave_lp,
3828 bl_interleave_lp);
3829
3830 r = dsi_read_reg(dsidev, DSI_VM_TIMING4);
3831 r = FLD_MOD(r, hsa_interleave_hs, 23, 16);
3832 r = FLD_MOD(r, hfp_interleave_hs, 15, 8);
3833 r = FLD_MOD(r, hbp_interleave_hs, 7, 0);
3834 dsi_write_reg(dsidev, DSI_VM_TIMING4, r);
3835
3836 r = dsi_read_reg(dsidev, DSI_VM_TIMING5);
3837 r = FLD_MOD(r, hsa_interleave_lp, 23, 16);
3838 r = FLD_MOD(r, hfp_interleave_lp, 15, 8);
3839 r = FLD_MOD(r, hbp_interleave_lp, 7, 0);
3840 dsi_write_reg(dsidev, DSI_VM_TIMING5, r);
3841
3842 r = dsi_read_reg(dsidev, DSI_VM_TIMING6);
3843 r = FLD_MOD(r, bl_interleave_hs, 31, 15);
3844 r = FLD_MOD(r, bl_interleave_lp, 16, 0);
3845 dsi_write_reg(dsidev, DSI_VM_TIMING6, r);
3846}
3847
3668static int dsi_proto_config(struct omap_dss_device *dssdev) 3848static int dsi_proto_config(struct omap_dss_device *dssdev)
3669{ 3849{
3670 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); 3850 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
@@ -3723,6 +3903,7 @@ static int dsi_proto_config(struct omap_dss_device *dssdev)
3723 if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_VIDEO_MODE) { 3903 if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_VIDEO_MODE) {
3724 dsi_config_vp_sync_events(dssdev); 3904 dsi_config_vp_sync_events(dssdev);
3725 dsi_config_blanking_modes(dssdev); 3905 dsi_config_blanking_modes(dssdev);
3906 dsi_config_cmd_mode_interleaving(dssdev);
3726 } 3907 }
3727 3908
3728 dsi_vc_initial_config(dsidev, 0); 3909 dsi_vc_initial_config(dsidev, 0);