1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (c) 2015, The Linux Foundation. All rights reserved.
6 #include <drm/drm_crtc.h>
7 #include <drm/drm_probe_helper.h>
11 static struct mdp5_kms
*get_kms(struct drm_encoder
*encoder
)
13 struct msm_drm_private
*priv
= encoder
->dev
->dev_private
;
14 return to_mdp5_kms(to_mdp_kms(priv
->kms
));
17 #define VSYNC_CLK_RATE 19200000
18 static int pingpong_tearcheck_setup(struct drm_encoder
*encoder
,
19 struct drm_display_mode
*mode
)
21 struct mdp5_kms
*mdp5_kms
= get_kms(encoder
);
22 struct device
*dev
= encoder
->dev
->dev
;
23 u32 total_lines_x100
, vclks_line
, cfg
;
25 struct mdp5_hw_mixer
*mixer
= mdp5_crtc_get_mixer(encoder
->crtc
);
26 int pp_id
= mixer
->pp
;
28 if (IS_ERR_OR_NULL(mdp5_kms
->vsync_clk
)) {
29 DRM_DEV_ERROR(dev
, "vsync_clk is not initialized\n");
33 total_lines_x100
= mode
->vtotal
* drm_mode_vrefresh(mode
);
34 if (!total_lines_x100
) {
35 DRM_DEV_ERROR(dev
, "%s: vtotal(%d) or vrefresh(%d) is 0\n",
36 __func__
, mode
->vtotal
, drm_mode_vrefresh(mode
));
40 vsync_clk_speed
= clk_round_rate(mdp5_kms
->vsync_clk
, VSYNC_CLK_RATE
);
41 if (vsync_clk_speed
<= 0) {
42 DRM_DEV_ERROR(dev
, "vsync_clk round rate failed %ld\n",
46 vclks_line
= vsync_clk_speed
* 100 / total_lines_x100
;
48 cfg
= MDP5_PP_SYNC_CONFIG_VSYNC_COUNTER_EN
49 | MDP5_PP_SYNC_CONFIG_VSYNC_IN_EN
;
50 cfg
|= MDP5_PP_SYNC_CONFIG_VSYNC_COUNT(vclks_line
);
52 mdp5_write(mdp5_kms
, REG_MDP5_PP_SYNC_CONFIG_VSYNC(pp_id
), cfg
);
54 REG_MDP5_PP_SYNC_CONFIG_HEIGHT(pp_id
), 0xfff0);
56 REG_MDP5_PP_VSYNC_INIT_VAL(pp_id
), mode
->vdisplay
);
57 mdp5_write(mdp5_kms
, REG_MDP5_PP_RD_PTR_IRQ(pp_id
), mode
->vdisplay
+ 1);
58 mdp5_write(mdp5_kms
, REG_MDP5_PP_START_POS(pp_id
), mode
->vdisplay
);
59 mdp5_write(mdp5_kms
, REG_MDP5_PP_SYNC_THRESH(pp_id
),
60 MDP5_PP_SYNC_THRESH_START(4) |
61 MDP5_PP_SYNC_THRESH_CONTINUE(4));
66 static int pingpong_tearcheck_enable(struct drm_encoder
*encoder
)
68 struct mdp5_kms
*mdp5_kms
= get_kms(encoder
);
69 struct mdp5_hw_mixer
*mixer
= mdp5_crtc_get_mixer(encoder
->crtc
);
70 int pp_id
= mixer
->pp
;
73 ret
= clk_set_rate(mdp5_kms
->vsync_clk
,
74 clk_round_rate(mdp5_kms
->vsync_clk
, VSYNC_CLK_RATE
));
76 DRM_DEV_ERROR(encoder
->dev
->dev
,
77 "vsync_clk clk_set_rate failed, %d\n", ret
);
80 ret
= clk_prepare_enable(mdp5_kms
->vsync_clk
);
82 DRM_DEV_ERROR(encoder
->dev
->dev
,
83 "vsync_clk clk_prepare_enable failed, %d\n", ret
);
87 mdp5_write(mdp5_kms
, REG_MDP5_PP_TEAR_CHECK_EN(pp_id
), 1);
92 static void pingpong_tearcheck_disable(struct drm_encoder
*encoder
)
94 struct mdp5_kms
*mdp5_kms
= get_kms(encoder
);
95 struct mdp5_hw_mixer
*mixer
= mdp5_crtc_get_mixer(encoder
->crtc
);
96 int pp_id
= mixer
->pp
;
98 mdp5_write(mdp5_kms
, REG_MDP5_PP_TEAR_CHECK_EN(pp_id
), 0);
99 clk_disable_unprepare(mdp5_kms
->vsync_clk
);
102 void mdp5_cmd_encoder_mode_set(struct drm_encoder
*encoder
,
103 struct drm_display_mode
*mode
,
104 struct drm_display_mode
*adjusted_mode
)
106 mode
= adjusted_mode
;
108 DBG("set mode: " DRM_MODE_FMT
, DRM_MODE_ARG(mode
));
109 pingpong_tearcheck_setup(encoder
, mode
);
110 mdp5_crtc_set_pipeline(encoder
->crtc
);
113 void mdp5_cmd_encoder_disable(struct drm_encoder
*encoder
)
115 struct mdp5_encoder
*mdp5_cmd_enc
= to_mdp5_encoder(encoder
);
116 struct mdp5_ctl
*ctl
= mdp5_cmd_enc
->ctl
;
117 struct mdp5_interface
*intf
= mdp5_cmd_enc
->intf
;
118 struct mdp5_pipeline
*pipeline
= mdp5_crtc_get_pipeline(encoder
->crtc
);
120 if (WARN_ON(!mdp5_cmd_enc
->enabled
))
123 pingpong_tearcheck_disable(encoder
);
125 mdp5_ctl_set_encoder_state(ctl
, pipeline
, false);
126 mdp5_ctl_commit(ctl
, pipeline
, mdp_ctl_flush_mask_encoder(intf
), true);
128 mdp5_cmd_enc
->enabled
= false;
131 void mdp5_cmd_encoder_enable(struct drm_encoder
*encoder
)
133 struct mdp5_encoder
*mdp5_cmd_enc
= to_mdp5_encoder(encoder
);
134 struct mdp5_ctl
*ctl
= mdp5_cmd_enc
->ctl
;
135 struct mdp5_interface
*intf
= mdp5_cmd_enc
->intf
;
136 struct mdp5_pipeline
*pipeline
= mdp5_crtc_get_pipeline(encoder
->crtc
);
138 if (WARN_ON(mdp5_cmd_enc
->enabled
))
141 if (pingpong_tearcheck_enable(encoder
))
144 mdp5_ctl_commit(ctl
, pipeline
, mdp_ctl_flush_mask_encoder(intf
), true);
146 mdp5_ctl_set_encoder_state(ctl
, pipeline
, true);
148 mdp5_cmd_enc
->enabled
= true;
151 int mdp5_cmd_encoder_set_split_display(struct drm_encoder
*encoder
,
152 struct drm_encoder
*slave_encoder
)
154 struct mdp5_encoder
*mdp5_cmd_enc
= to_mdp5_encoder(encoder
);
155 struct mdp5_kms
*mdp5_kms
;
160 if (!encoder
|| !slave_encoder
)
163 mdp5_kms
= get_kms(encoder
);
164 intf_num
= mdp5_cmd_enc
->intf
->num
;
166 /* Switch slave encoder's trigger MUX, to use the master's
167 * start signal for the slave encoder
170 data
|= MDP5_SPLIT_DPL_UPPER_INTF2_SW_TRG_MUX
;
171 else if (intf_num
== 2)
172 data
|= MDP5_SPLIT_DPL_UPPER_INTF1_SW_TRG_MUX
;
176 /* Smart Panel, Sync mode */
177 data
|= MDP5_SPLIT_DPL_UPPER_SMART_PANEL
;
179 dev
= &mdp5_kms
->pdev
->dev
;
181 /* Make sure clocks are on when connectors calling this function. */
182 pm_runtime_get_sync(dev
);
183 mdp5_write(mdp5_kms
, REG_MDP5_SPLIT_DPL_UPPER
, data
);
185 mdp5_write(mdp5_kms
, REG_MDP5_SPLIT_DPL_LOWER
,
186 MDP5_SPLIT_DPL_LOWER_SMART_PANEL
);
187 mdp5_write(mdp5_kms
, REG_MDP5_SPLIT_DPL_EN
, 1);
188 pm_runtime_put_sync(dev
);