]> asedeno.scripts.mit.edu Git - linux.git/blob - drivers/gpu/drm/arm/display/komeda/komeda_crtc.c
Merge tag 'asm-generic-nommu' of git://git.kernel.org/pub/scm/linux/kernel/git/arnd...
[linux.git] / drivers / gpu / drm / arm / display / komeda / komeda_crtc.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * (C) COPYRIGHT 2018 ARM Limited. All rights reserved.
4  * Author: James.Qian.Wang <james.qian.wang@arm.com>
5  *
6  */
7 #include <linux/clk.h>
8 #include <linux/pm_runtime.h>
9 #include <linux/spinlock.h>
10
11 #include <drm/drm_atomic.h>
12 #include <drm/drm_atomic_helper.h>
13 #include <drm/drm_crtc_helper.h>
14 #include <drm/drm_plane_helper.h>
15 #include <drm/drm_print.h>
16 #include <drm/drm_vblank.h>
17
18 #include "komeda_dev.h"
19 #include "komeda_kms.h"
20
21 /**
22  * komeda_crtc_atomic_check - build display output data flow
23  * @crtc: DRM crtc
24  * @state: the crtc state object
25  *
26  * crtc_atomic_check is the final check stage, so beside build a display data
27  * pipeline according to the crtc_state, but still needs to release or disable
28  * the unclaimed pipeline resources.
29  *
30  * RETURNS:
31  * Zero for success or -errno
32  */
33 static int
34 komeda_crtc_atomic_check(struct drm_crtc *crtc,
35                          struct drm_crtc_state *state)
36 {
37         struct komeda_crtc *kcrtc = to_kcrtc(crtc);
38         struct komeda_crtc_state *kcrtc_st = to_kcrtc_st(state);
39         int err;
40
41         if (state->active) {
42                 err = komeda_build_display_data_flow(kcrtc, kcrtc_st);
43                 if (err)
44                         return err;
45         }
46
47         /* release unclaimed pipeline resources */
48         err = komeda_release_unclaimed_resources(kcrtc->master, kcrtc_st);
49         if (err)
50                 return err;
51
52         return 0;
53 }
54
55 static u32 komeda_calc_mclk(struct komeda_crtc_state *kcrtc_st)
56 {
57         unsigned long mclk = kcrtc_st->base.adjusted_mode.clock * 1000;
58
59         return mclk;
60 }
61
62 /* For active a crtc, mainly need two parts of preparation
63  * 1. adjust display operation mode.
64  * 2. enable needed clk
65  */
66 static int
67 komeda_crtc_prepare(struct komeda_crtc *kcrtc)
68 {
69         struct komeda_dev *mdev = kcrtc->base.dev->dev_private;
70         struct komeda_pipeline *master = kcrtc->master;
71         struct komeda_crtc_state *kcrtc_st = to_kcrtc_st(kcrtc->base.state);
72         unsigned long pxlclk_rate = kcrtc_st->base.adjusted_mode.clock * 1000;
73         u32 new_mode;
74         int err;
75
76         mutex_lock(&mdev->lock);
77
78         new_mode = mdev->dpmode | BIT(master->id);
79         if (WARN_ON(new_mode == mdev->dpmode)) {
80                 err = 0;
81                 goto unlock;
82         }
83
84         err = mdev->funcs->change_opmode(mdev, new_mode);
85         if (err) {
86                 DRM_ERROR("failed to change opmode: 0x%x -> 0x%x.\n,",
87                           mdev->dpmode, new_mode);
88                 goto unlock;
89         }
90
91         mdev->dpmode = new_mode;
92         /* Only need to enable mclk on single display mode, but no need to
93          * enable mclk it on dual display mode, since the dual mode always
94          * switch from single display mode, the mclk already enabled, no need
95          * to enable it again.
96          */
97         if (new_mode != KOMEDA_MODE_DUAL_DISP) {
98                 err = clk_set_rate(mdev->mclk, komeda_calc_mclk(kcrtc_st));
99                 if (err)
100                         DRM_ERROR("failed to set mclk.\n");
101                 err = clk_prepare_enable(mdev->mclk);
102                 if (err)
103                         DRM_ERROR("failed to enable mclk.\n");
104         }
105
106         err = clk_prepare_enable(master->aclk);
107         if (err)
108                 DRM_ERROR("failed to enable axi clk for pipe%d.\n", master->id);
109         err = clk_set_rate(master->pxlclk, pxlclk_rate);
110         if (err)
111                 DRM_ERROR("failed to set pxlclk for pipe%d\n", master->id);
112         err = clk_prepare_enable(master->pxlclk);
113         if (err)
114                 DRM_ERROR("failed to enable pxl clk for pipe%d.\n", master->id);
115
116 unlock:
117         mutex_unlock(&mdev->lock);
118
119         return err;
120 }
121
122 static int
123 komeda_crtc_unprepare(struct komeda_crtc *kcrtc)
124 {
125         struct komeda_dev *mdev = kcrtc->base.dev->dev_private;
126         struct komeda_pipeline *master = kcrtc->master;
127         u32 new_mode;
128         int err;
129
130         mutex_lock(&mdev->lock);
131
132         new_mode = mdev->dpmode & (~BIT(master->id));
133
134         if (WARN_ON(new_mode == mdev->dpmode)) {
135                 err = 0;
136                 goto unlock;
137         }
138
139         err = mdev->funcs->change_opmode(mdev, new_mode);
140         if (err) {
141                 DRM_ERROR("failed to change opmode: 0x%x -> 0x%x.\n,",
142                           mdev->dpmode, new_mode);
143                 goto unlock;
144         }
145
146         mdev->dpmode = new_mode;
147
148         clk_disable_unprepare(master->pxlclk);
149         clk_disable_unprepare(master->aclk);
150         if (new_mode == KOMEDA_MODE_INACTIVE)
151                 clk_disable_unprepare(mdev->mclk);
152
153 unlock:
154         mutex_unlock(&mdev->lock);
155
156         return err;
157 }
158
159 void komeda_crtc_handle_event(struct komeda_crtc   *kcrtc,
160                               struct komeda_events *evts)
161 {
162         struct drm_crtc *crtc = &kcrtc->base;
163         u32 events = evts->pipes[kcrtc->master->id];
164
165         if (events & KOMEDA_EVENT_VSYNC)
166                 drm_crtc_handle_vblank(crtc);
167
168         /* will handle it together with the write back support */
169         if (events & KOMEDA_EVENT_EOW)
170                 DRM_DEBUG("EOW.\n");
171
172         if (events & KOMEDA_EVENT_FLIP) {
173                 unsigned long flags;
174                 struct drm_pending_vblank_event *event;
175
176                 spin_lock_irqsave(&crtc->dev->event_lock, flags);
177                 if (kcrtc->disable_done) {
178                         complete_all(kcrtc->disable_done);
179                         kcrtc->disable_done = NULL;
180                 } else if (crtc->state->event) {
181                         event = crtc->state->event;
182                         /*
183                          * Consume event before notifying drm core that flip
184                          * happened.
185                          */
186                         crtc->state->event = NULL;
187                         drm_crtc_send_vblank_event(crtc, event);
188                 } else {
189                         DRM_WARN("CRTC[%d]: FLIP happen but no pending commit.\n",
190                                  drm_crtc_index(&kcrtc->base));
191                 }
192                 spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
193         }
194 }
195
196 static void
197 komeda_crtc_do_flush(struct drm_crtc *crtc,
198                      struct drm_crtc_state *old)
199 {
200         struct komeda_crtc *kcrtc = to_kcrtc(crtc);
201         struct komeda_crtc_state *kcrtc_st = to_kcrtc_st(crtc->state);
202         struct komeda_dev *mdev = kcrtc->base.dev->dev_private;
203         struct komeda_pipeline *master = kcrtc->master;
204
205         DRM_DEBUG_ATOMIC("CRTC%d_FLUSH: active_pipes: 0x%x, affected: 0x%x.\n",
206                          drm_crtc_index(crtc),
207                          kcrtc_st->active_pipes, kcrtc_st->affected_pipes);
208
209         /* step 1: update the pipeline/component state to HW */
210         if (has_bit(master->id, kcrtc_st->affected_pipes))
211                 komeda_pipeline_update(master, old->state);
212
213         /* step 2: notify the HW to kickoff the update */
214         mdev->funcs->flush(mdev, master->id, kcrtc_st->active_pipes);
215 }
216
217 static void
218 komeda_crtc_atomic_enable(struct drm_crtc *crtc,
219                           struct drm_crtc_state *old)
220 {
221         komeda_crtc_prepare(to_kcrtc(crtc));
222         drm_crtc_vblank_on(crtc);
223         komeda_crtc_do_flush(crtc, old);
224 }
225
226 static void
227 komeda_crtc_atomic_disable(struct drm_crtc *crtc,
228                            struct drm_crtc_state *old)
229 {
230         struct komeda_crtc *kcrtc = to_kcrtc(crtc);
231         struct komeda_crtc_state *old_st = to_kcrtc_st(old);
232         struct komeda_dev *mdev = crtc->dev->dev_private;
233         struct komeda_pipeline *master = kcrtc->master;
234         struct completion *disable_done = &crtc->state->commit->flip_done;
235         struct completion temp;
236         int timeout;
237
238         DRM_DEBUG_ATOMIC("CRTC%d_DISABLE: active_pipes: 0x%x, affected: 0x%x.\n",
239                          drm_crtc_index(crtc),
240                          old_st->active_pipes, old_st->affected_pipes);
241
242         if (has_bit(master->id, old_st->active_pipes))
243                 komeda_pipeline_disable(master, old->state);
244
245         /* crtc_disable has two scenarios according to the state->active switch.
246          * 1. active -> inactive
247          *    this commit is a disable commit. and the commit will be finished
248          *    or done after the disable operation. on this case we can directly
249          *    use the crtc->state->event to tracking the HW disable operation.
250          * 2. active -> active
251          *    the crtc->commit is not for disable, but a modeset operation when
252          *    crtc is active, such commit actually has been completed by 3
253          *    DRM operations:
254          *    crtc_disable, update_planes(crtc_flush), crtc_enable
255          *    so on this case the crtc->commit is for the whole process.
256          *    we can not use it for tracing the disable, we need a temporary
257          *    flip_done for tracing the disable. and crtc->state->event for
258          *    the crtc_enable operation.
259          *    That's also the reason why skip modeset commit in
260          *    komeda_crtc_atomic_flush()
261          */
262         if (crtc->state->active) {
263                 struct komeda_pipeline_state *pipe_st;
264                 /* clear the old active_comps to zero */
265                 pipe_st = komeda_pipeline_get_old_state(master, old->state);
266                 pipe_st->active_comps = 0;
267
268                 init_completion(&temp);
269                 kcrtc->disable_done = &temp;
270                 disable_done = &temp;
271         }
272
273         mdev->funcs->flush(mdev, master->id, 0);
274
275         /* wait the disable take affect.*/
276         timeout = wait_for_completion_timeout(disable_done, HZ);
277         if (timeout == 0) {
278                 DRM_ERROR("disable pipeline%d timeout.\n", kcrtc->master->id);
279                 if (crtc->state->active) {
280                         unsigned long flags;
281
282                         spin_lock_irqsave(&crtc->dev->event_lock, flags);
283                         kcrtc->disable_done = NULL;
284                         spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
285                 }
286         }
287
288         drm_crtc_vblank_off(crtc);
289         komeda_crtc_unprepare(kcrtc);
290 }
291
292 static void
293 komeda_crtc_atomic_flush(struct drm_crtc *crtc,
294                          struct drm_crtc_state *old)
295 {
296         /* commit with modeset will be handled in enable/disable */
297         if (drm_atomic_crtc_needs_modeset(crtc->state))
298                 return;
299
300         komeda_crtc_do_flush(crtc, old);
301 }
302
303 static enum drm_mode_status
304 komeda_crtc_mode_valid(struct drm_crtc *crtc, const struct drm_display_mode *m)
305 {
306         struct komeda_dev *mdev = crtc->dev->dev_private;
307         struct komeda_crtc *kcrtc = to_kcrtc(crtc);
308         struct komeda_pipeline *master = kcrtc->master;
309         long mode_clk, pxlclk;
310
311         if (m->flags & DRM_MODE_FLAG_INTERLACE)
312                 return MODE_NO_INTERLACE;
313
314         /* main clock/AXI clk must be faster than pxlclk*/
315         mode_clk = m->clock * 1000;
316         pxlclk = clk_round_rate(master->pxlclk, mode_clk);
317         if (pxlclk != mode_clk) {
318                 DRM_DEBUG_ATOMIC("pxlclk doesn't support %ld Hz\n", mode_clk);
319
320                 return MODE_NOCLOCK;
321         }
322
323         if (clk_round_rate(mdev->mclk, mode_clk) < pxlclk) {
324                 DRM_DEBUG_ATOMIC("mclk can't satisfy the requirement of %s-clk: %ld.\n",
325                                  m->name, pxlclk);
326
327                 return MODE_CLOCK_HIGH;
328         }
329
330         if (clk_round_rate(master->aclk, mode_clk) < pxlclk) {
331                 DRM_DEBUG_ATOMIC("aclk can't satisfy the requirement of %s-clk: %ld.\n",
332                                  m->name, pxlclk);
333
334                 return MODE_CLOCK_HIGH;
335         }
336
337         return MODE_OK;
338 }
339
340 static bool komeda_crtc_mode_fixup(struct drm_crtc *crtc,
341                                    const struct drm_display_mode *m,
342                                    struct drm_display_mode *adjusted_mode)
343 {
344         struct komeda_crtc *kcrtc = to_kcrtc(crtc);
345         struct komeda_pipeline *master = kcrtc->master;
346         long mode_clk = m->clock * 1000;
347
348         adjusted_mode->clock = clk_round_rate(master->pxlclk, mode_clk) / 1000;
349
350         return true;
351 }
352
353 static struct drm_crtc_helper_funcs komeda_crtc_helper_funcs = {
354         .atomic_check   = komeda_crtc_atomic_check,
355         .atomic_flush   = komeda_crtc_atomic_flush,
356         .atomic_enable  = komeda_crtc_atomic_enable,
357         .atomic_disable = komeda_crtc_atomic_disable,
358         .mode_valid     = komeda_crtc_mode_valid,
359         .mode_fixup     = komeda_crtc_mode_fixup,
360 };
361
362 static void komeda_crtc_reset(struct drm_crtc *crtc)
363 {
364         struct komeda_crtc_state *state;
365
366         if (crtc->state)
367                 __drm_atomic_helper_crtc_destroy_state(crtc->state);
368
369         kfree(to_kcrtc_st(crtc->state));
370         crtc->state = NULL;
371
372         state = kzalloc(sizeof(*state), GFP_KERNEL);
373         if (state) {
374                 crtc->state = &state->base;
375                 crtc->state->crtc = crtc;
376         }
377 }
378
379 static struct drm_crtc_state *
380 komeda_crtc_atomic_duplicate_state(struct drm_crtc *crtc)
381 {
382         struct komeda_crtc_state *old = to_kcrtc_st(crtc->state);
383         struct komeda_crtc_state *new;
384
385         new = kzalloc(sizeof(*new), GFP_KERNEL);
386         if (!new)
387                 return NULL;
388
389         __drm_atomic_helper_crtc_duplicate_state(crtc, &new->base);
390
391         new->affected_pipes = old->active_pipes;
392
393         return &new->base;
394 }
395
396 static void komeda_crtc_atomic_destroy_state(struct drm_crtc *crtc,
397                                              struct drm_crtc_state *state)
398 {
399         __drm_atomic_helper_crtc_destroy_state(state);
400         kfree(to_kcrtc_st(state));
401 }
402
403 static int komeda_crtc_vblank_enable(struct drm_crtc *crtc)
404 {
405         struct komeda_dev *mdev = crtc->dev->dev_private;
406         struct komeda_crtc *kcrtc = to_kcrtc(crtc);
407
408         mdev->funcs->on_off_vblank(mdev, kcrtc->master->id, true);
409         return 0;
410 }
411
412 static void komeda_crtc_vblank_disable(struct drm_crtc *crtc)
413 {
414         struct komeda_dev *mdev = crtc->dev->dev_private;
415         struct komeda_crtc *kcrtc = to_kcrtc(crtc);
416
417         mdev->funcs->on_off_vblank(mdev, kcrtc->master->id, false);
418 }
419
420 static const struct drm_crtc_funcs komeda_crtc_funcs = {
421         .gamma_set              = drm_atomic_helper_legacy_gamma_set,
422         .destroy                = drm_crtc_cleanup,
423         .set_config             = drm_atomic_helper_set_config,
424         .page_flip              = drm_atomic_helper_page_flip,
425         .reset                  = komeda_crtc_reset,
426         .atomic_duplicate_state = komeda_crtc_atomic_duplicate_state,
427         .atomic_destroy_state   = komeda_crtc_atomic_destroy_state,
428         .enable_vblank          = komeda_crtc_vblank_enable,
429         .disable_vblank         = komeda_crtc_vblank_disable,
430 };
431
432 int komeda_kms_setup_crtcs(struct komeda_kms_dev *kms,
433                            struct komeda_dev *mdev)
434 {
435         struct komeda_crtc *crtc;
436         struct komeda_pipeline *master;
437         char str[16];
438         int i;
439
440         kms->n_crtcs = 0;
441
442         for (i = 0; i < mdev->n_pipelines; i++) {
443                 crtc = &kms->crtcs[kms->n_crtcs];
444                 master = mdev->pipelines[i];
445
446                 crtc->master = master;
447                 crtc->slave  = NULL;
448
449                 if (crtc->slave)
450                         sprintf(str, "pipe-%d", crtc->slave->id);
451                 else
452                         sprintf(str, "None");
453
454                 DRM_INFO("crtc%d: master(pipe-%d) slave(%s) output: %s.\n",
455                          kms->n_crtcs, master->id, str,
456                          master->of_output_dev ?
457                          master->of_output_dev->full_name : "None");
458
459                 kms->n_crtcs++;
460         }
461
462         return 0;
463 }
464
465 static struct drm_plane *
466 get_crtc_primary(struct komeda_kms_dev *kms, struct komeda_crtc *crtc)
467 {
468         struct komeda_plane *kplane;
469         struct drm_plane *plane;
470
471         drm_for_each_plane(plane, &kms->base) {
472                 if (plane->type != DRM_PLANE_TYPE_PRIMARY)
473                         continue;
474
475                 kplane = to_kplane(plane);
476                 /* only master can be primary */
477                 if (kplane->layer->base.pipeline == crtc->master)
478                         return plane;
479         }
480
481         return NULL;
482 }
483
484 static int komeda_crtc_add(struct komeda_kms_dev *kms,
485                            struct komeda_crtc *kcrtc)
486 {
487         struct drm_crtc *crtc = &kcrtc->base;
488         int err;
489
490         err = drm_crtc_init_with_planes(&kms->base, crtc,
491                                         get_crtc_primary(kms, kcrtc), NULL,
492                                         &komeda_crtc_funcs, NULL);
493         if (err)
494                 return err;
495
496         drm_crtc_helper_add(crtc, &komeda_crtc_helper_funcs);
497         drm_crtc_vblank_reset(crtc);
498
499         crtc->port = kcrtc->master->of_output_port;
500
501         return 0;
502 }
503
504 int komeda_kms_add_crtcs(struct komeda_kms_dev *kms, struct komeda_dev *mdev)
505 {
506         int i, err;
507
508         for (i = 0; i < kms->n_crtcs; i++) {
509                 err = komeda_crtc_add(kms, &kms->crtcs[i]);
510                 if (err)
511                         return err;
512         }
513
514         return 0;
515 }