GNU Linux-libre 4.9.288-gnu1
[releases.git] / drivers / gpu / drm / msm / mdp / mdp5 / mdp5_cmd_encoder.c
1 /*
2  * Copyright (c) 2015, The Linux Foundation. All rights reserved.
3  *
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.
7  *
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.
12  */
13
14 #include "mdp5_kms.h"
15
16 #include "drm_crtc.h"
17 #include "drm_crtc_helper.h"
18
19 struct mdp5_cmd_encoder {
20         struct drm_encoder base;
21         struct mdp5_interface intf;
22         bool enabled;
23         uint32_t bsc;
24
25         struct mdp5_ctl *ctl;
26 };
27 #define to_mdp5_cmd_encoder(x) container_of(x, struct mdp5_cmd_encoder, base)
28
29 static struct mdp5_kms *get_kms(struct drm_encoder *encoder)
30 {
31         struct msm_drm_private *priv = encoder->dev->dev_private;
32         return to_mdp5_kms(to_mdp_kms(priv->kms));
33 }
34
35 #ifdef DOWNSTREAM_CONFIG_MSM_BUS_SCALING
36 #include <mach/board.h>
37 #include <linux/msm-bus.h>
38 #include <linux/msm-bus-board.h>
39 #define MDP_BUS_VECTOR_ENTRY(ab_val, ib_val)            \
40         {                                               \
41                 .src = MSM_BUS_MASTER_MDP_PORT0,        \
42                 .dst = MSM_BUS_SLAVE_EBI_CH0,           \
43                 .ab = (ab_val),                         \
44                 .ib = (ib_val),                         \
45         }
46
47 static struct msm_bus_vectors mdp_bus_vectors[] = {
48         MDP_BUS_VECTOR_ENTRY(0, 0),
49         MDP_BUS_VECTOR_ENTRY(2000000000, 2000000000),
50 };
51 static struct msm_bus_paths mdp_bus_usecases[] = { {
52                 .num_paths = 1,
53                 .vectors = &mdp_bus_vectors[0],
54 }, {
55                 .num_paths = 1,
56                 .vectors = &mdp_bus_vectors[1],
57 } };
58 static struct msm_bus_scale_pdata mdp_bus_scale_table = {
59         .usecase = mdp_bus_usecases,
60         .num_usecases = ARRAY_SIZE(mdp_bus_usecases),
61         .name = "mdss_mdp",
62 };
63
64 static void bs_init(struct mdp5_cmd_encoder *mdp5_cmd_enc)
65 {
66         mdp5_cmd_enc->bsc = msm_bus_scale_register_client(
67                         &mdp_bus_scale_table);
68         DBG("bus scale client: %08x", mdp5_cmd_enc->bsc);
69 }
70
71 static void bs_fini(struct mdp5_cmd_encoder *mdp5_cmd_enc)
72 {
73         if (mdp5_cmd_enc->bsc) {
74                 msm_bus_scale_unregister_client(mdp5_cmd_enc->bsc);
75                 mdp5_cmd_enc->bsc = 0;
76         }
77 }
78
79 static void bs_set(struct mdp5_cmd_encoder *mdp5_cmd_enc, int idx)
80 {
81         if (mdp5_cmd_enc->bsc) {
82                 DBG("set bus scaling: %d", idx);
83                 /* HACK: scaling down, and then immediately back up
84                  * seems to leave things broken (underflow).. so
85                  * never disable:
86                  */
87                 idx = 1;
88                 msm_bus_scale_client_update_request(mdp5_cmd_enc->bsc, idx);
89         }
90 }
91 #else
92 static void bs_init(struct mdp5_cmd_encoder *mdp5_cmd_enc) {}
93 static void bs_fini(struct mdp5_cmd_encoder *mdp5_cmd_enc) {}
94 static void bs_set(struct mdp5_cmd_encoder *mdp5_cmd_enc, int idx) {}
95 #endif
96
97 #define VSYNC_CLK_RATE 19200000
98 static int pingpong_tearcheck_setup(struct drm_encoder *encoder,
99                                         struct drm_display_mode *mode)
100 {
101         struct mdp5_kms *mdp5_kms = get_kms(encoder);
102         struct device *dev = encoder->dev->dev;
103         u32 total_lines_x100, vclks_line, cfg;
104         long vsync_clk_speed;
105         int pp_id = GET_PING_PONG_ID(mdp5_crtc_get_lm(encoder->crtc));
106
107         if (IS_ERR_OR_NULL(mdp5_kms->vsync_clk)) {
108                 dev_err(dev, "vsync_clk is not initialized\n");
109                 return -EINVAL;
110         }
111
112         total_lines_x100 = mode->vtotal * mode->vrefresh;
113         if (!total_lines_x100) {
114                 dev_err(dev, "%s: vtotal(%d) or vrefresh(%d) is 0\n",
115                                 __func__, mode->vtotal, mode->vrefresh);
116                 return -EINVAL;
117         }
118
119         vsync_clk_speed = clk_round_rate(mdp5_kms->vsync_clk, VSYNC_CLK_RATE);
120         if (vsync_clk_speed <= 0) {
121                 dev_err(dev, "vsync_clk round rate failed %ld\n",
122                                                         vsync_clk_speed);
123                 return -EINVAL;
124         }
125         vclks_line = vsync_clk_speed * 100 / total_lines_x100;
126
127         cfg = MDP5_PP_SYNC_CONFIG_VSYNC_COUNTER_EN
128                 | MDP5_PP_SYNC_CONFIG_VSYNC_IN_EN;
129         cfg |= MDP5_PP_SYNC_CONFIG_VSYNC_COUNT(vclks_line);
130
131         /*
132          * Tearcheck emits a blanking signal every vclks_line * vtotal * 2 ticks on
133          * the vsync_clk equating to roughly half the desired panel refresh rate.
134          * This is only necessary as stability fallback if interrupts from the
135          * panel arrive too late or not at all, but is currently used by default
136          * because these panel interrupts are not wired up yet.
137          */
138         mdp5_write(mdp5_kms, REG_MDP5_PP_SYNC_CONFIG_VSYNC(pp_id), cfg);
139         mdp5_write(mdp5_kms,
140                 REG_MDP5_PP_SYNC_CONFIG_HEIGHT(pp_id), (2 * mode->vtotal));
141
142         mdp5_write(mdp5_kms,
143                 REG_MDP5_PP_VSYNC_INIT_VAL(pp_id), mode->vdisplay);
144         mdp5_write(mdp5_kms, REG_MDP5_PP_RD_PTR_IRQ(pp_id), mode->vdisplay + 1);
145         mdp5_write(mdp5_kms, REG_MDP5_PP_START_POS(pp_id), mode->vdisplay);
146         mdp5_write(mdp5_kms, REG_MDP5_PP_SYNC_THRESH(pp_id),
147                         MDP5_PP_SYNC_THRESH_START(4) |
148                         MDP5_PP_SYNC_THRESH_CONTINUE(4));
149
150         return 0;
151 }
152
153 static int pingpong_tearcheck_enable(struct drm_encoder *encoder)
154 {
155         struct mdp5_kms *mdp5_kms = get_kms(encoder);
156         int pp_id = GET_PING_PONG_ID(mdp5_crtc_get_lm(encoder->crtc));
157         int ret;
158
159         ret = clk_set_rate(mdp5_kms->vsync_clk,
160                 clk_round_rate(mdp5_kms->vsync_clk, VSYNC_CLK_RATE));
161         if (ret) {
162                 dev_err(encoder->dev->dev,
163                         "vsync_clk clk_set_rate failed, %d\n", ret);
164                 return ret;
165         }
166         ret = clk_prepare_enable(mdp5_kms->vsync_clk);
167         if (ret) {
168                 dev_err(encoder->dev->dev,
169                         "vsync_clk clk_prepare_enable failed, %d\n", ret);
170                 return ret;
171         }
172
173         mdp5_write(mdp5_kms, REG_MDP5_PP_TEAR_CHECK_EN(pp_id), 1);
174
175         return 0;
176 }
177
178 static void pingpong_tearcheck_disable(struct drm_encoder *encoder)
179 {
180         struct mdp5_kms *mdp5_kms = get_kms(encoder);
181         int pp_id = GET_PING_PONG_ID(mdp5_crtc_get_lm(encoder->crtc));
182
183         mdp5_write(mdp5_kms, REG_MDP5_PP_TEAR_CHECK_EN(pp_id), 0);
184         clk_disable_unprepare(mdp5_kms->vsync_clk);
185 }
186
187 static void mdp5_cmd_encoder_destroy(struct drm_encoder *encoder)
188 {
189         struct mdp5_cmd_encoder *mdp5_cmd_enc = to_mdp5_cmd_encoder(encoder);
190         bs_fini(mdp5_cmd_enc);
191         drm_encoder_cleanup(encoder);
192         kfree(mdp5_cmd_enc);
193 }
194
195 static const struct drm_encoder_funcs mdp5_cmd_encoder_funcs = {
196         .destroy = mdp5_cmd_encoder_destroy,
197 };
198
199 static void mdp5_cmd_encoder_mode_set(struct drm_encoder *encoder,
200                 struct drm_display_mode *mode,
201                 struct drm_display_mode *adjusted_mode)
202 {
203         struct mdp5_cmd_encoder *mdp5_cmd_enc = to_mdp5_cmd_encoder(encoder);
204
205         mode = adjusted_mode;
206
207         DBG("set mode: %d:\"%s\" %d %d %d %d %d %d %d %d %d %d 0x%x 0x%x",
208                         mode->base.id, mode->name,
209                         mode->vrefresh, mode->clock,
210                         mode->hdisplay, mode->hsync_start,
211                         mode->hsync_end, mode->htotal,
212                         mode->vdisplay, mode->vsync_start,
213                         mode->vsync_end, mode->vtotal,
214                         mode->type, mode->flags);
215         pingpong_tearcheck_setup(encoder, mode);
216         mdp5_crtc_set_pipeline(encoder->crtc, &mdp5_cmd_enc->intf,
217                                 mdp5_cmd_enc->ctl);
218 }
219
220 static void mdp5_cmd_encoder_disable(struct drm_encoder *encoder)
221 {
222         struct mdp5_cmd_encoder *mdp5_cmd_enc = to_mdp5_cmd_encoder(encoder);
223         struct mdp5_ctl *ctl = mdp5_cmd_enc->ctl;
224         struct mdp5_interface *intf = &mdp5_cmd_enc->intf;
225
226         if (WARN_ON(!mdp5_cmd_enc->enabled))
227                 return;
228
229         pingpong_tearcheck_disable(encoder);
230
231         mdp5_ctl_set_encoder_state(ctl, false);
232         mdp5_ctl_commit(ctl, mdp_ctl_flush_mask_encoder(intf));
233
234         bs_set(mdp5_cmd_enc, 0);
235
236         mdp5_cmd_enc->enabled = false;
237 }
238
239 static void mdp5_cmd_encoder_enable(struct drm_encoder *encoder)
240 {
241         struct mdp5_cmd_encoder *mdp5_cmd_enc = to_mdp5_cmd_encoder(encoder);
242         struct mdp5_ctl *ctl = mdp5_cmd_enc->ctl;
243         struct mdp5_interface *intf = &mdp5_cmd_enc->intf;
244
245         if (WARN_ON(mdp5_cmd_enc->enabled))
246                 return;
247
248         bs_set(mdp5_cmd_enc, 1);
249         if (pingpong_tearcheck_enable(encoder))
250                 return;
251
252         mdp5_ctl_commit(ctl, mdp_ctl_flush_mask_encoder(intf));
253
254         mdp5_ctl_set_encoder_state(ctl, true);
255
256         mdp5_cmd_enc->enabled = true;
257 }
258
259 static const struct drm_encoder_helper_funcs mdp5_cmd_encoder_helper_funcs = {
260         .mode_set = mdp5_cmd_encoder_mode_set,
261         .disable = mdp5_cmd_encoder_disable,
262         .enable = mdp5_cmd_encoder_enable,
263 };
264
265 int mdp5_cmd_encoder_set_split_display(struct drm_encoder *encoder,
266                                         struct drm_encoder *slave_encoder)
267 {
268         struct mdp5_cmd_encoder *mdp5_cmd_enc = to_mdp5_cmd_encoder(encoder);
269         struct mdp5_kms *mdp5_kms;
270         int intf_num;
271         u32 data = 0;
272
273         if (!encoder || !slave_encoder)
274                 return -EINVAL;
275
276         mdp5_kms = get_kms(encoder);
277         intf_num = mdp5_cmd_enc->intf.num;
278
279         /* Switch slave encoder's trigger MUX, to use the master's
280          * start signal for the slave encoder
281          */
282         if (intf_num == 1)
283                 data |= MDP5_SPLIT_DPL_UPPER_INTF2_SW_TRG_MUX;
284         else if (intf_num == 2)
285                 data |= MDP5_SPLIT_DPL_UPPER_INTF1_SW_TRG_MUX;
286         else
287                 return -EINVAL;
288
289         /* Smart Panel, Sync mode */
290         data |= MDP5_SPLIT_DPL_UPPER_SMART_PANEL;
291
292         /* Make sure clocks are on when connectors calling this function. */
293         mdp5_enable(mdp5_kms);
294         mdp5_write(mdp5_kms, REG_MDP5_SPLIT_DPL_UPPER, data);
295
296         mdp5_write(mdp5_kms, REG_MDP5_SPLIT_DPL_LOWER,
297                    MDP5_SPLIT_DPL_LOWER_SMART_PANEL);
298         mdp5_write(mdp5_kms, REG_MDP5_SPLIT_DPL_EN, 1);
299         mdp5_disable(mdp5_kms);
300
301         return 0;
302 }
303
304 /* initialize command mode encoder */
305 struct drm_encoder *mdp5_cmd_encoder_init(struct drm_device *dev,
306                         struct mdp5_interface *intf, struct mdp5_ctl *ctl)
307 {
308         struct drm_encoder *encoder = NULL;
309         struct mdp5_cmd_encoder *mdp5_cmd_enc;
310         int ret;
311
312         if (WARN_ON((intf->type != INTF_DSI) &&
313                 (intf->mode != MDP5_INTF_DSI_MODE_COMMAND))) {
314                 ret = -EINVAL;
315                 goto fail;
316         }
317
318         mdp5_cmd_enc = kzalloc(sizeof(*mdp5_cmd_enc), GFP_KERNEL);
319         if (!mdp5_cmd_enc) {
320                 ret = -ENOMEM;
321                 goto fail;
322         }
323
324         memcpy(&mdp5_cmd_enc->intf, intf, sizeof(mdp5_cmd_enc->intf));
325         encoder = &mdp5_cmd_enc->base;
326         mdp5_cmd_enc->ctl = ctl;
327
328         drm_encoder_init(dev, encoder, &mdp5_cmd_encoder_funcs,
329                         DRM_MODE_ENCODER_DSI, NULL);
330
331         drm_encoder_helper_add(encoder, &mdp5_cmd_encoder_helper_funcs);
332
333         bs_init(mdp5_cmd_enc);
334
335         return encoder;
336
337 fail:
338         if (encoder)
339                 mdp5_cmd_encoder_destroy(encoder);
340
341         return ERR_PTR(ret);
342 }