Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mattst88...
[sfrench/cifs-2.6.git] / drivers / gpu / drm / msm / mdp / mdp5 / mdp5_smp.c
1 /*
2  * Copyright (c) 2014, The Linux Foundation. All rights reserved.
3  * Copyright (C) 2013 Red Hat
4  * Author: Rob Clark <robdclark@gmail.com>
5  *
6  * This program is free software; you can redistribute it and/or modify it
7  * under the terms of the GNU General Public License version 2 as published by
8  * the Free Software Foundation.
9  *
10  * This program is distributed in the hope that it will be useful, but WITHOUT
11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
13  * more details.
14  *
15  * You should have received a copy of the GNU General Public License along with
16  * this program.  If not, see <http://www.gnu.org/licenses/>.
17  */
18
19
20 #include "mdp5_kms.h"
21 #include "mdp5_smp.h"
22
23
24 struct mdp5_smp {
25         struct drm_device *dev;
26
27         uint8_t reserved[MAX_CLIENTS]; /* fixed MMBs allocation per client */
28
29         int blk_cnt;
30         int blk_size;
31
32         /* register cache */
33         u32 alloc_w[22];
34         u32 alloc_r[22];
35         u32 pipe_reqprio_fifo_wm0[SSPP_MAX];
36         u32 pipe_reqprio_fifo_wm1[SSPP_MAX];
37         u32 pipe_reqprio_fifo_wm2[SSPP_MAX];
38 };
39
40 static inline
41 struct mdp5_kms *get_kms(struct mdp5_smp *smp)
42 {
43         struct msm_drm_private *priv = smp->dev->dev_private;
44
45         return to_mdp5_kms(to_mdp_kms(priv->kms));
46 }
47
48 static inline u32 pipe2client(enum mdp5_pipe pipe, int plane)
49 {
50 #define CID_UNUSED      0
51
52         if (WARN_ON(plane >= pipe2nclients(pipe)))
53                 return CID_UNUSED;
54
55         /*
56          * Note on SMP clients:
57          * For ViG pipes, fetch Y/Cr/Cb-components clients are always
58          * consecutive, and in that order.
59          *
60          * e.g.:
61          * if mdp5_cfg->smp.clients[SSPP_VIG0] = N,
62          *      Y  plane's client ID is N
63          *      Cr plane's client ID is N + 1
64          *      Cb plane's client ID is N + 2
65          */
66
67         return mdp5_cfg->smp.clients[pipe] + plane;
68 }
69
70 /* allocate blocks for the specified request: */
71 static int smp_request_block(struct mdp5_smp *smp,
72                 struct mdp5_smp_state *state,
73                 u32 cid, int nblks)
74 {
75         void *cs = state->client_state[cid];
76         int i, avail, cnt = smp->blk_cnt;
77         uint8_t reserved;
78
79         /* we shouldn't be requesting blocks for an in-use client: */
80         WARN_ON(bitmap_weight(cs, cnt) > 0);
81
82         reserved = smp->reserved[cid];
83
84         if (reserved) {
85                 nblks = max(0, nblks - reserved);
86                 DBG("%d MMBs allocated (%d reserved)", nblks, reserved);
87         }
88
89         avail = cnt - bitmap_weight(state->state, cnt);
90         if (nblks > avail) {
91                 dev_err(smp->dev->dev, "out of blks (req=%d > avail=%d)\n",
92                                 nblks, avail);
93                 return -ENOSPC;
94         }
95
96         for (i = 0; i < nblks; i++) {
97                 int blk = find_first_zero_bit(state->state, cnt);
98                 set_bit(blk, cs);
99                 set_bit(blk, state->state);
100         }
101
102         return 0;
103 }
104
105 static void set_fifo_thresholds(struct mdp5_smp *smp,
106                 enum mdp5_pipe pipe, int nblks)
107 {
108         u32 smp_entries_per_blk = smp->blk_size / (128 / BITS_PER_BYTE);
109         u32 val;
110
111         /* 1/4 of SMP pool that is being fetched */
112         val = (nblks * smp_entries_per_blk) / 4;
113
114         smp->pipe_reqprio_fifo_wm0[pipe] = val * 1;
115         smp->pipe_reqprio_fifo_wm1[pipe] = val * 2;
116         smp->pipe_reqprio_fifo_wm2[pipe] = val * 3;
117 }
118
119 /*
120  * NOTE: looks like if horizontal decimation is used (if we supported that)
121  * then the width used to calculate SMP block requirements is the post-
122  * decimated width.  Ie. SMP buffering sits downstream of decimation (which
123  * presumably happens during the dma from scanout buffer).
124  */
125 uint32_t mdp5_smp_calculate(struct mdp5_smp *smp,
126                 const struct mdp_format *format,
127                 u32 width, bool hdecim)
128 {
129         struct mdp5_kms *mdp5_kms = get_kms(smp);
130         int rev = mdp5_cfg_get_hw_rev(mdp5_kms->cfg);
131         int i, hsub, nplanes, nlines;
132         u32 fmt = format->base.pixel_format;
133         uint32_t blkcfg = 0;
134
135         nplanes = drm_format_num_planes(fmt);
136         hsub = drm_format_horz_chroma_subsampling(fmt);
137
138         /* different if BWC (compressed framebuffer?) enabled: */
139         nlines = 2;
140
141         /* Newer MDPs have split/packing logic, which fetches sub-sampled
142          * U and V components (splits them from Y if necessary) and packs
143          * them together, writes to SMP using a single client.
144          */
145         if ((rev > 0) && (format->chroma_sample > CHROMA_FULL)) {
146                 fmt = DRM_FORMAT_NV24;
147                 nplanes = 2;
148
149                 /* if decimation is enabled, HW decimates less on the
150                  * sub sampled chroma components
151                  */
152                 if (hdecim && (hsub > 1))
153                         hsub = 1;
154         }
155
156         for (i = 0; i < nplanes; i++) {
157                 int n, fetch_stride, cpp;
158
159                 cpp = drm_format_plane_cpp(fmt, i);
160                 fetch_stride = width * cpp / (i ? hsub : 1);
161
162                 n = DIV_ROUND_UP(fetch_stride * nlines, smp->blk_size);
163
164                 /* for hw rev v1.00 */
165                 if (rev == 0)
166                         n = roundup_pow_of_two(n);
167
168                 blkcfg |= (n << (8 * i));
169         }
170
171         return blkcfg;
172 }
173
174 int mdp5_smp_assign(struct mdp5_smp *smp, struct mdp5_smp_state *state,
175                 enum mdp5_pipe pipe, uint32_t blkcfg)
176 {
177         struct mdp5_kms *mdp5_kms = get_kms(smp);
178         struct drm_device *dev = mdp5_kms->dev;
179         int i, ret;
180
181         for (i = 0; i < pipe2nclients(pipe); i++) {
182                 u32 cid = pipe2client(pipe, i);
183                 int n = blkcfg & 0xff;
184
185                 if (!n)
186                         continue;
187
188                 DBG("%s[%d]: request %d SMP blocks", pipe2name(pipe), i, n);
189                 ret = smp_request_block(smp, state, cid, n);
190                 if (ret) {
191                         dev_err(dev->dev, "Cannot allocate %d SMP blocks: %d\n",
192                                         n, ret);
193                         return ret;
194                 }
195
196                 blkcfg >>= 8;
197         }
198
199         state->assigned |= (1 << pipe);
200
201         return 0;
202 }
203
204 /* Release SMP blocks for all clients of the pipe */
205 void mdp5_smp_release(struct mdp5_smp *smp, struct mdp5_smp_state *state,
206                 enum mdp5_pipe pipe)
207 {
208         int i;
209         int cnt = smp->blk_cnt;
210
211         for (i = 0; i < pipe2nclients(pipe); i++) {
212                 u32 cid = pipe2client(pipe, i);
213                 void *cs = state->client_state[cid];
214
215                 /* update global state: */
216                 bitmap_andnot(state->state, state->state, cs, cnt);
217
218                 /* clear client's state */
219                 bitmap_zero(cs, cnt);
220         }
221
222         state->released |= (1 << pipe);
223 }
224
225 /* NOTE: SMP_ALLOC_* regs are *not* double buffered, so release has to
226  * happen after scanout completes.
227  */
228 static unsigned update_smp_state(struct mdp5_smp *smp,
229                 u32 cid, mdp5_smp_state_t *assigned)
230 {
231         int cnt = smp->blk_cnt;
232         unsigned nblks = 0;
233         u32 blk, val;
234
235         for_each_set_bit(blk, *assigned, cnt) {
236                 int idx = blk / 3;
237                 int fld = blk % 3;
238
239                 val = smp->alloc_w[idx];
240
241                 switch (fld) {
242                 case 0:
243                         val &= ~MDP5_SMP_ALLOC_W_REG_CLIENT0__MASK;
244                         val |= MDP5_SMP_ALLOC_W_REG_CLIENT0(cid);
245                         break;
246                 case 1:
247                         val &= ~MDP5_SMP_ALLOC_W_REG_CLIENT1__MASK;
248                         val |= MDP5_SMP_ALLOC_W_REG_CLIENT1(cid);
249                         break;
250                 case 2:
251                         val &= ~MDP5_SMP_ALLOC_W_REG_CLIENT2__MASK;
252                         val |= MDP5_SMP_ALLOC_W_REG_CLIENT2(cid);
253                         break;
254                 }
255
256                 smp->alloc_w[idx] = val;
257                 smp->alloc_r[idx] = val;
258
259                 nblks++;
260         }
261
262         return nblks;
263 }
264
265 static void write_smp_alloc_regs(struct mdp5_smp *smp)
266 {
267         struct mdp5_kms *mdp5_kms = get_kms(smp);
268         int i, num_regs;
269
270         num_regs = smp->blk_cnt / 3 + 1;
271
272         for (i = 0; i < num_regs; i++) {
273                 mdp5_write(mdp5_kms, REG_MDP5_SMP_ALLOC_W_REG(i),
274                            smp->alloc_w[i]);
275                 mdp5_write(mdp5_kms, REG_MDP5_SMP_ALLOC_R_REG(i),
276                            smp->alloc_r[i]);
277         }
278 }
279
280 static void write_smp_fifo_regs(struct mdp5_smp *smp)
281 {
282         struct mdp5_kms *mdp5_kms = get_kms(smp);
283         int i;
284
285         for (i = 0; i < mdp5_kms->num_hwpipes; i++) {
286                 struct mdp5_hw_pipe *hwpipe = mdp5_kms->hwpipes[i];
287                 enum mdp5_pipe pipe = hwpipe->pipe;
288
289                 mdp5_write(mdp5_kms, REG_MDP5_PIPE_REQPRIO_FIFO_WM_0(pipe),
290                            smp->pipe_reqprio_fifo_wm0[pipe]);
291                 mdp5_write(mdp5_kms, REG_MDP5_PIPE_REQPRIO_FIFO_WM_1(pipe),
292                            smp->pipe_reqprio_fifo_wm1[pipe]);
293                 mdp5_write(mdp5_kms, REG_MDP5_PIPE_REQPRIO_FIFO_WM_2(pipe),
294                            smp->pipe_reqprio_fifo_wm2[pipe]);
295         }
296 }
297
298 void mdp5_smp_prepare_commit(struct mdp5_smp *smp, struct mdp5_smp_state *state)
299 {
300         enum mdp5_pipe pipe;
301
302         for_each_set_bit(pipe, &state->assigned, sizeof(state->assigned) * 8) {
303                 unsigned i, nblks = 0;
304
305                 for (i = 0; i < pipe2nclients(pipe); i++) {
306                         u32 cid = pipe2client(pipe, i);
307                         void *cs = state->client_state[cid];
308
309                         nblks += update_smp_state(smp, cid, cs);
310
311                         DBG("assign %s:%u, %u blks",
312                                 pipe2name(pipe), i, nblks);
313                 }
314
315                 set_fifo_thresholds(smp, pipe, nblks);
316         }
317
318         write_smp_alloc_regs(smp);
319         write_smp_fifo_regs(smp);
320
321         state->assigned = 0;
322 }
323
324 void mdp5_smp_complete_commit(struct mdp5_smp *smp, struct mdp5_smp_state *state)
325 {
326         enum mdp5_pipe pipe;
327
328         for_each_set_bit(pipe, &state->released, sizeof(state->released) * 8) {
329                 DBG("release %s", pipe2name(pipe));
330                 set_fifo_thresholds(smp, pipe, 0);
331         }
332
333         write_smp_fifo_regs(smp);
334
335         state->released = 0;
336 }
337
338 void mdp5_smp_dump(struct mdp5_smp *smp, struct drm_printer *p)
339 {
340         struct mdp5_kms *mdp5_kms = get_kms(smp);
341         struct mdp5_hw_pipe_state *hwpstate;
342         struct mdp5_smp_state *state;
343         int total = 0, i, j;
344
345         drm_printf(p, "name\tinuse\tplane\n");
346         drm_printf(p, "----\t-----\t-----\n");
347
348         if (drm_can_sleep())
349                 drm_modeset_lock(&mdp5_kms->state_lock, NULL);
350
351         /* grab these *after* we hold the state_lock */
352         hwpstate = &mdp5_kms->state->hwpipe;
353         state = &mdp5_kms->state->smp;
354
355         for (i = 0; i < mdp5_kms->num_hwpipes; i++) {
356                 struct mdp5_hw_pipe *hwpipe = mdp5_kms->hwpipes[i];
357                 struct drm_plane *plane = hwpstate->hwpipe_to_plane[hwpipe->idx];
358                 enum mdp5_pipe pipe = hwpipe->pipe;
359                 for (j = 0; j < pipe2nclients(pipe); j++) {
360                         u32 cid = pipe2client(pipe, j);
361                         void *cs = state->client_state[cid];
362                         int inuse = bitmap_weight(cs, smp->blk_cnt);
363
364                         drm_printf(p, "%s:%d\t%d\t%s\n",
365                                 pipe2name(pipe), j, inuse,
366                                 plane ? plane->name : NULL);
367
368                         total += inuse;
369                 }
370         }
371
372         drm_printf(p, "TOTAL:\t%d\t(of %d)\n", total, smp->blk_cnt);
373         drm_printf(p, "AVAIL:\t%d\n", smp->blk_cnt -
374                         bitmap_weight(state->state, smp->blk_cnt));
375
376         if (drm_can_sleep())
377                 drm_modeset_unlock(&mdp5_kms->state_lock);
378 }
379
380 void mdp5_smp_destroy(struct mdp5_smp *smp)
381 {
382         kfree(smp);
383 }
384
385 struct mdp5_smp *mdp5_smp_init(struct mdp5_kms *mdp5_kms, const struct mdp5_smp_block *cfg)
386 {
387         struct mdp5_smp_state *state = &mdp5_kms->state->smp;
388         struct mdp5_smp *smp = NULL;
389         int ret;
390
391         smp = kzalloc(sizeof(*smp), GFP_KERNEL);
392         if (unlikely(!smp)) {
393                 ret = -ENOMEM;
394                 goto fail;
395         }
396
397         smp->dev = mdp5_kms->dev;
398         smp->blk_cnt = cfg->mmb_count;
399         smp->blk_size = cfg->mmb_size;
400
401         /* statically tied MMBs cannot be re-allocated: */
402         bitmap_copy(state->state, cfg->reserved_state, smp->blk_cnt);
403         memcpy(smp->reserved, cfg->reserved, sizeof(smp->reserved));
404
405         return smp;
406 fail:
407         if (smp)
408                 mdp5_smp_destroy(smp);
409
410         return ERR_PTR(ret);
411 }