2 * Copyright (c) 2015, The Linux Foundation. All rights reserved.
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 and
6 * only version 2 as published by the Free Software Foundation.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
17 #include "drm_crtc_helper.h"
19 struct mdp5_cmd_encoder
{
20 struct drm_encoder base
;
21 struct mdp5_interface intf
;
25 #define to_mdp5_cmd_encoder(x) container_of(x, struct mdp5_cmd_encoder, base)
27 static struct mdp5_kms
*get_kms(struct drm_encoder
*encoder
)
29 struct msm_drm_private
*priv
= encoder
->dev
->dev_private
;
30 return to_mdp5_kms(to_mdp_kms(priv
->kms
));
33 #ifdef CONFIG_MSM_BUS_SCALING
34 #include <mach/board.h>
35 #include <linux/msm-bus.h>
36 #include <linux/msm-bus-board.h>
37 #define MDP_BUS_VECTOR_ENTRY(ab_val, ib_val) \
39 .src = MSM_BUS_MASTER_MDP_PORT0, \
40 .dst = MSM_BUS_SLAVE_EBI_CH0, \
45 static struct msm_bus_vectors mdp_bus_vectors
[] = {
46 MDP_BUS_VECTOR_ENTRY(0, 0),
47 MDP_BUS_VECTOR_ENTRY(2000000000, 2000000000),
49 static struct msm_bus_paths mdp_bus_usecases
[] = { {
51 .vectors
= &mdp_bus_vectors
[0],
54 .vectors
= &mdp_bus_vectors
[1],
56 static struct msm_bus_scale_pdata mdp_bus_scale_table
= {
57 .usecase
= mdp_bus_usecases
,
58 .num_usecases
= ARRAY_SIZE(mdp_bus_usecases
),
62 static void bs_init(struct mdp5_cmd_encoder
*mdp5_cmd_enc
)
64 mdp5_cmd_enc
->bsc
= msm_bus_scale_register_client(
65 &mdp_bus_scale_table
);
66 DBG("bus scale client: %08x", mdp5_cmd_enc
->bsc
);
69 static void bs_fini(struct mdp5_cmd_encoder
*mdp5_cmd_enc
)
71 if (mdp5_cmd_enc
->bsc
) {
72 msm_bus_scale_unregister_client(mdp5_cmd_enc
->bsc
);
73 mdp5_cmd_enc
->bsc
= 0;
77 static void bs_set(struct mdp5_cmd_encoder
*mdp5_cmd_enc
, int idx
)
79 if (mdp5_cmd_enc
->bsc
) {
80 DBG("set bus scaling: %d", idx
);
81 /* HACK: scaling down, and then immediately back up
82 * seems to leave things broken (underflow).. so
86 msm_bus_scale_client_update_request(mdp5_cmd_enc
->bsc
, idx
);
90 static void bs_init(struct mdp5_cmd_encoder
*mdp5_cmd_enc
) {}
91 static void bs_fini(struct mdp5_cmd_encoder
*mdp5_cmd_enc
) {}
92 static void bs_set(struct mdp5_cmd_encoder
*mdp5_cmd_enc
, int idx
) {}
95 #define VSYNC_CLK_RATE 19200000
96 static int pingpong_tearcheck_setup(struct drm_encoder
*encoder
,
97 struct drm_display_mode
*mode
)
99 struct mdp5_kms
*mdp5_kms
= get_kms(encoder
);
100 struct device
*dev
= encoder
->dev
->dev
;
101 u32 total_lines_x100
, vclks_line
, cfg
;
102 long vsync_clk_speed
;
103 int pp_id
= GET_PING_PONG_ID(mdp5_crtc_get_lm(encoder
->crtc
));
105 if (IS_ERR_OR_NULL(mdp5_kms
->vsync_clk
)) {
106 dev_err(dev
, "vsync_clk is not initialized\n");
110 total_lines_x100
= mode
->vtotal
* mode
->vrefresh
;
111 if (!total_lines_x100
) {
112 dev_err(dev
, "%s: vtotal(%d) or vrefresh(%d) is 0\n",
113 __func__
, mode
->vtotal
, mode
->vrefresh
);
117 vsync_clk_speed
= clk_round_rate(mdp5_kms
->vsync_clk
, VSYNC_CLK_RATE
);
118 if (vsync_clk_speed
<= 0) {
119 dev_err(dev
, "vsync_clk round rate failed %ld\n",
123 vclks_line
= vsync_clk_speed
* 100 / total_lines_x100
;
125 cfg
= MDP5_PP_SYNC_CONFIG_VSYNC_COUNTER_EN
126 | MDP5_PP_SYNC_CONFIG_VSYNC_IN_EN
;
127 cfg
|= MDP5_PP_SYNC_CONFIG_VSYNC_COUNT(vclks_line
);
129 mdp5_write(mdp5_kms
, REG_MDP5_PP_SYNC_CONFIG_VSYNC(pp_id
), cfg
);
131 REG_MDP5_PP_SYNC_CONFIG_HEIGHT(pp_id
), 0xfff0);
133 REG_MDP5_PP_VSYNC_INIT_VAL(pp_id
), mode
->vdisplay
);
134 mdp5_write(mdp5_kms
, REG_MDP5_PP_RD_PTR_IRQ(pp_id
), mode
->vdisplay
+ 1);
135 mdp5_write(mdp5_kms
, REG_MDP5_PP_START_POS(pp_id
), mode
->vdisplay
);
136 mdp5_write(mdp5_kms
, REG_MDP5_PP_SYNC_THRESH(pp_id
),
137 MDP5_PP_SYNC_THRESH_START(4) |
138 MDP5_PP_SYNC_THRESH_CONTINUE(4));
143 static int pingpong_tearcheck_enable(struct drm_encoder
*encoder
)
145 struct mdp5_kms
*mdp5_kms
= get_kms(encoder
);
146 int pp_id
= GET_PING_PONG_ID(mdp5_crtc_get_lm(encoder
->crtc
));
149 ret
= clk_set_rate(mdp5_kms
->vsync_clk
,
150 clk_round_rate(mdp5_kms
->vsync_clk
, VSYNC_CLK_RATE
));
152 dev_err(encoder
->dev
->dev
,
153 "vsync_clk clk_set_rate failed, %d\n", ret
);
156 ret
= clk_prepare_enable(mdp5_kms
->vsync_clk
);
158 dev_err(encoder
->dev
->dev
,
159 "vsync_clk clk_prepare_enable failed, %d\n", ret
);
163 mdp5_write(mdp5_kms
, REG_MDP5_PP_TEAR_CHECK_EN(pp_id
), 1);
168 static void pingpong_tearcheck_disable(struct drm_encoder
*encoder
)
170 struct mdp5_kms
*mdp5_kms
= get_kms(encoder
);
171 int pp_id
= GET_PING_PONG_ID(mdp5_crtc_get_lm(encoder
->crtc
));
173 mdp5_write(mdp5_kms
, REG_MDP5_PP_TEAR_CHECK_EN(pp_id
), 0);
174 clk_disable_unprepare(mdp5_kms
->vsync_clk
);
177 static void mdp5_cmd_encoder_destroy(struct drm_encoder
*encoder
)
179 struct mdp5_cmd_encoder
*mdp5_cmd_enc
= to_mdp5_cmd_encoder(encoder
);
180 bs_fini(mdp5_cmd_enc
);
181 drm_encoder_cleanup(encoder
);
185 static const struct drm_encoder_funcs mdp5_cmd_encoder_funcs
= {
186 .destroy
= mdp5_cmd_encoder_destroy
,
189 static bool mdp5_cmd_encoder_mode_fixup(struct drm_encoder
*encoder
,
190 const struct drm_display_mode
*mode
,
191 struct drm_display_mode
*adjusted_mode
)
196 static void mdp5_cmd_encoder_mode_set(struct drm_encoder
*encoder
,
197 struct drm_display_mode
*mode
,
198 struct drm_display_mode
*adjusted_mode
)
200 struct mdp5_cmd_encoder
*mdp5_cmd_enc
= to_mdp5_cmd_encoder(encoder
);
202 mode
= adjusted_mode
;
204 DBG("set mode: %d:\"%s\" %d %d %d %d %d %d %d %d %d %d 0x%x 0x%x",
205 mode
->base
.id
, mode
->name
,
206 mode
->vrefresh
, mode
->clock
,
207 mode
->hdisplay
, mode
->hsync_start
,
208 mode
->hsync_end
, mode
->htotal
,
209 mode
->vdisplay
, mode
->vsync_start
,
210 mode
->vsync_end
, mode
->vtotal
,
211 mode
->type
, mode
->flags
);
212 pingpong_tearcheck_setup(encoder
, mode
);
213 mdp5_crtc_set_intf(encoder
->crtc
, &mdp5_cmd_enc
->intf
);
216 static void mdp5_cmd_encoder_disable(struct drm_encoder
*encoder
)
218 struct mdp5_cmd_encoder
*mdp5_cmd_enc
= to_mdp5_cmd_encoder(encoder
);
219 struct mdp5_kms
*mdp5_kms
= get_kms(encoder
);
220 struct mdp5_ctl
*ctl
= mdp5_crtc_get_ctl(encoder
->crtc
);
221 struct mdp5_interface
*intf
= &mdp5_cmd_enc
->intf
;
222 int lm
= mdp5_crtc_get_lm(encoder
->crtc
);
224 if (WARN_ON(!mdp5_cmd_enc
->enabled
))
227 /* Wait for the last frame done */
228 mdp_irq_wait(&mdp5_kms
->base
, lm2ppdone(lm
));
229 pingpong_tearcheck_disable(encoder
);
231 mdp5_ctl_set_encoder_state(ctl
, false);
232 mdp5_ctl_commit(ctl
, mdp_ctl_flush_mask_encoder(intf
));
234 bs_set(mdp5_cmd_enc
, 0);
236 mdp5_cmd_enc
->enabled
= false;
239 static void mdp5_cmd_encoder_enable(struct drm_encoder
*encoder
)
241 struct mdp5_cmd_encoder
*mdp5_cmd_enc
= to_mdp5_cmd_encoder(encoder
);
242 struct mdp5_ctl
*ctl
= mdp5_crtc_get_ctl(encoder
->crtc
);
243 struct mdp5_interface
*intf
= &mdp5_cmd_enc
->intf
;
245 if (WARN_ON(mdp5_cmd_enc
->enabled
))
248 bs_set(mdp5_cmd_enc
, 1);
249 if (pingpong_tearcheck_enable(encoder
))
252 mdp5_ctl_commit(ctl
, mdp_ctl_flush_mask_encoder(intf
));
254 mdp5_ctl_set_encoder_state(ctl
, true);
256 mdp5_cmd_enc
->enabled
= true;
259 static const struct drm_encoder_helper_funcs mdp5_cmd_encoder_helper_funcs
= {
260 .mode_fixup
= mdp5_cmd_encoder_mode_fixup
,
261 .mode_set
= mdp5_cmd_encoder_mode_set
,
262 .disable
= mdp5_cmd_encoder_disable
,
263 .enable
= mdp5_cmd_encoder_enable
,
266 int mdp5_cmd_encoder_set_split_display(struct drm_encoder
*encoder
,
267 struct drm_encoder
*slave_encoder
)
269 struct mdp5_cmd_encoder
*mdp5_cmd_enc
= to_mdp5_cmd_encoder(encoder
);
270 struct mdp5_kms
*mdp5_kms
;
274 if (!encoder
|| !slave_encoder
)
277 mdp5_kms
= get_kms(encoder
);
278 intf_num
= mdp5_cmd_enc
->intf
.num
;
280 /* Switch slave encoder's trigger MUX, to use the master's
281 * start signal for the slave encoder
284 data
|= MDP5_SPLIT_DPL_UPPER_INTF2_SW_TRG_MUX
;
285 else if (intf_num
== 2)
286 data
|= MDP5_SPLIT_DPL_UPPER_INTF1_SW_TRG_MUX
;
290 /* Smart Panel, Sync mode */
291 data
|= MDP5_SPLIT_DPL_UPPER_SMART_PANEL
;
293 /* Make sure clocks are on when connectors calling this function. */
294 mdp5_enable(mdp5_kms
);
295 mdp5_write(mdp5_kms
, REG_MDP5_SPLIT_DPL_UPPER
, data
);
297 mdp5_write(mdp5_kms
, REG_MDP5_SPLIT_DPL_LOWER
,
298 MDP5_SPLIT_DPL_LOWER_SMART_PANEL
);
299 mdp5_write(mdp5_kms
, REG_MDP5_SPLIT_DPL_EN
, 1);
300 mdp5_disable(mdp5_kms
);
305 /* initialize command mode encoder */
306 struct drm_encoder
*mdp5_cmd_encoder_init(struct drm_device
*dev
,
307 struct mdp5_interface
*intf
)
309 struct drm_encoder
*encoder
= NULL
;
310 struct mdp5_cmd_encoder
*mdp5_cmd_enc
;
313 if (WARN_ON((intf
->type
!= INTF_DSI
) &&
314 (intf
->mode
!= MDP5_INTF_DSI_MODE_COMMAND
))) {
319 mdp5_cmd_enc
= kzalloc(sizeof(*mdp5_cmd_enc
), GFP_KERNEL
);
325 memcpy(&mdp5_cmd_enc
->intf
, intf
, sizeof(mdp5_cmd_enc
->intf
));
326 encoder
= &mdp5_cmd_enc
->base
;
328 drm_encoder_init(dev
, encoder
, &mdp5_cmd_encoder_funcs
,
329 DRM_MODE_ENCODER_DSI
);
331 drm_encoder_helper_add(encoder
, &mdp5_cmd_encoder_helper_funcs
);
333 bs_init(mdp5_cmd_enc
);
339 mdp5_cmd_encoder_destroy(encoder
);