]> Git Repo - J-linux.git/blob - drivers/gpu/drm/loongson/lsdc_crtc.c
Merge tag 'kbuild-v6.9' of git://git.kernel.org/pub/scm/linux/kernel/git/masahiroy...
[J-linux.git] / drivers / gpu / drm / loongson / lsdc_crtc.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (C) 2023 Loongson Technology Corporation Limited
4  */
5
6 #include <linux/delay.h>
7
8 #include <drm/drm_atomic.h>
9 #include <drm/drm_atomic_helper.h>
10 #include <drm/drm_debugfs.h>
11 #include <drm/drm_vblank.h>
12
13 #include "lsdc_drv.h"
14
15 /*
16  * After the CRTC soft reset, the vblank counter would be reset to zero.
17  * But the address and other settings in the CRTC register remain the same
18  * as before.
19  */
20
21 static void lsdc_crtc0_soft_reset(struct lsdc_crtc *lcrtc)
22 {
23         struct lsdc_device *ldev = lcrtc->ldev;
24         u32 val;
25
26         val = lsdc_rreg32(ldev, LSDC_CRTC0_CFG_REG);
27
28         val &= CFG_VALID_BITS_MASK;
29
30         /* Soft reset bit, active low */
31         val &= ~CFG_RESET_N;
32
33         val &= ~CFG_PIX_FMT_MASK;
34
35         lsdc_wreg32(ldev, LSDC_CRTC0_CFG_REG, val);
36
37         udelay(1);
38
39         val |= CFG_RESET_N | LSDC_PF_XRGB8888 | CFG_OUTPUT_ENABLE;
40
41         lsdc_wreg32(ldev, LSDC_CRTC0_CFG_REG, val);
42
43         /* Wait about a vblank time */
44         mdelay(20);
45 }
46
47 static void lsdc_crtc1_soft_reset(struct lsdc_crtc *lcrtc)
48 {
49         struct lsdc_device *ldev = lcrtc->ldev;
50         u32 val;
51
52         val = lsdc_rreg32(ldev, LSDC_CRTC1_CFG_REG);
53
54         val &= CFG_VALID_BITS_MASK;
55
56         /* Soft reset bit, active low */
57         val &= ~CFG_RESET_N;
58
59         val &= ~CFG_PIX_FMT_MASK;
60
61         lsdc_wreg32(ldev, LSDC_CRTC1_CFG_REG, val);
62
63         udelay(1);
64
65         val |= CFG_RESET_N | LSDC_PF_XRGB8888 | CFG_OUTPUT_ENABLE;
66
67         lsdc_wreg32(ldev, LSDC_CRTC1_CFG_REG, val);
68
69         /* Wait about a vblank time */
70         msleep(20);
71 }
72
73 static void lsdc_crtc0_enable(struct lsdc_crtc *lcrtc)
74 {
75         struct lsdc_device *ldev = lcrtc->ldev;
76         u32 val;
77
78         val = lsdc_rreg32(ldev, LSDC_CRTC0_CFG_REG);
79
80         /*
81          * This may happen in extremely rare cases, but a soft reset can
82          * bring it back to normal. We add a warning here, hoping to catch
83          * something if it happens.
84          */
85         if (val & CRTC_ANCHORED) {
86                 drm_warn(&ldev->base, "%s stall\n", lcrtc->base.name);
87                 return lsdc_crtc0_soft_reset(lcrtc);
88         }
89
90         lsdc_wreg32(ldev, LSDC_CRTC0_CFG_REG, val | CFG_OUTPUT_ENABLE);
91 }
92
93 static void lsdc_crtc0_disable(struct lsdc_crtc *lcrtc)
94 {
95         struct lsdc_device *ldev = lcrtc->ldev;
96
97         lsdc_ureg32_clr(ldev, LSDC_CRTC0_CFG_REG, CFG_OUTPUT_ENABLE);
98
99         udelay(9);
100 }
101
102 static void lsdc_crtc1_enable(struct lsdc_crtc *lcrtc)
103 {
104         struct lsdc_device *ldev = lcrtc->ldev;
105         u32 val;
106
107         /*
108          * This may happen in extremely rare cases, but a soft reset can
109          * bring it back to normal. We add a warning here, hoping to catch
110          * something if it happens.
111          */
112         val = lsdc_rreg32(ldev, LSDC_CRTC1_CFG_REG);
113         if (val & CRTC_ANCHORED) {
114                 drm_warn(&ldev->base, "%s stall\n", lcrtc->base.name);
115                 return lsdc_crtc1_soft_reset(lcrtc);
116         }
117
118         lsdc_wreg32(ldev, LSDC_CRTC1_CFG_REG, val | CFG_OUTPUT_ENABLE);
119 }
120
121 static void lsdc_crtc1_disable(struct lsdc_crtc *lcrtc)
122 {
123         struct lsdc_device *ldev = lcrtc->ldev;
124
125         lsdc_ureg32_clr(ldev, LSDC_CRTC1_CFG_REG, CFG_OUTPUT_ENABLE);
126
127         udelay(9);
128 }
129
130 /* All Loongson display controllers have hardware scanout position recoders */
131
132 static void lsdc_crtc0_scan_pos(struct lsdc_crtc *lcrtc, int *hpos, int *vpos)
133 {
134         struct lsdc_device *ldev = lcrtc->ldev;
135         u32 val;
136
137         val = lsdc_rreg32(ldev, LSDC_CRTC0_SCAN_POS_REG);
138
139         *hpos = val >> 16;
140         *vpos = val & 0xffff;
141 }
142
143 static void lsdc_crtc1_scan_pos(struct lsdc_crtc *lcrtc, int *hpos, int *vpos)
144 {
145         struct lsdc_device *ldev = lcrtc->ldev;
146         u32 val;
147
148         val = lsdc_rreg32(ldev, LSDC_CRTC1_SCAN_POS_REG);
149
150         *hpos = val >> 16;
151         *vpos = val & 0xffff;
152 }
153
154 static void lsdc_crtc0_enable_vblank(struct lsdc_crtc *lcrtc)
155 {
156         struct lsdc_device *ldev = lcrtc->ldev;
157
158         lsdc_ureg32_set(ldev, LSDC_INT_REG, INT_CRTC0_VSYNC_EN);
159 }
160
161 static void lsdc_crtc0_disable_vblank(struct lsdc_crtc *lcrtc)
162 {
163         struct lsdc_device *ldev = lcrtc->ldev;
164
165         lsdc_ureg32_clr(ldev, LSDC_INT_REG, INT_CRTC0_VSYNC_EN);
166 }
167
168 static void lsdc_crtc1_enable_vblank(struct lsdc_crtc *lcrtc)
169 {
170         struct lsdc_device *ldev = lcrtc->ldev;
171
172         lsdc_ureg32_set(ldev, LSDC_INT_REG, INT_CRTC1_VSYNC_EN);
173 }
174
175 static void lsdc_crtc1_disable_vblank(struct lsdc_crtc *lcrtc)
176 {
177         struct lsdc_device *ldev = lcrtc->ldev;
178
179         lsdc_ureg32_clr(ldev, LSDC_INT_REG, INT_CRTC1_VSYNC_EN);
180 }
181
182 static void lsdc_crtc0_flip(struct lsdc_crtc *lcrtc)
183 {
184         struct lsdc_device *ldev = lcrtc->ldev;
185
186         lsdc_ureg32_set(ldev, LSDC_CRTC0_CFG_REG, CFG_PAGE_FLIP);
187 }
188
189 static void lsdc_crtc1_flip(struct lsdc_crtc *lcrtc)
190 {
191         struct lsdc_device *ldev = lcrtc->ldev;
192
193         lsdc_ureg32_set(ldev, LSDC_CRTC1_CFG_REG, CFG_PAGE_FLIP);
194 }
195
196 /*
197  * CRTC0 clone from CRTC1 or CRTC1 clone from CRTC0 using hardware logic
198  * This may be useful for custom cloning (TWIN) applications. Saving the
199  * bandwidth compared with the clone (mirroring) display mode provided by
200  * drm core.
201  */
202
203 static void lsdc_crtc0_clone(struct lsdc_crtc *lcrtc)
204 {
205         struct lsdc_device *ldev = lcrtc->ldev;
206
207         lsdc_ureg32_set(ldev, LSDC_CRTC0_CFG_REG, CFG_HW_CLONE);
208 }
209
210 static void lsdc_crtc1_clone(struct lsdc_crtc *lcrtc)
211 {
212         struct lsdc_device *ldev = lcrtc->ldev;
213
214         lsdc_ureg32_set(ldev, LSDC_CRTC1_CFG_REG, CFG_HW_CLONE);
215 }
216
217 static void lsdc_crtc0_set_mode(struct lsdc_crtc *lcrtc,
218                                 const struct drm_display_mode *mode)
219 {
220         struct lsdc_device *ldev = lcrtc->ldev;
221
222         lsdc_wreg32(ldev, LSDC_CRTC0_HDISPLAY_REG,
223                     (mode->crtc_htotal << 16) | mode->crtc_hdisplay);
224
225         lsdc_wreg32(ldev, LSDC_CRTC0_VDISPLAY_REG,
226                     (mode->crtc_vtotal << 16) | mode->crtc_vdisplay);
227
228         lsdc_wreg32(ldev, LSDC_CRTC0_HSYNC_REG,
229                     (mode->crtc_hsync_end << 16) | mode->crtc_hsync_start | HSYNC_EN);
230
231         lsdc_wreg32(ldev, LSDC_CRTC0_VSYNC_REG,
232                     (mode->crtc_vsync_end << 16) | mode->crtc_vsync_start | VSYNC_EN);
233 }
234
235 static void lsdc_crtc1_set_mode(struct lsdc_crtc *lcrtc,
236                                 const struct drm_display_mode *mode)
237 {
238         struct lsdc_device *ldev = lcrtc->ldev;
239
240         lsdc_wreg32(ldev, LSDC_CRTC1_HDISPLAY_REG,
241                     (mode->crtc_htotal << 16) | mode->crtc_hdisplay);
242
243         lsdc_wreg32(ldev, LSDC_CRTC1_VDISPLAY_REG,
244                     (mode->crtc_vtotal << 16) | mode->crtc_vdisplay);
245
246         lsdc_wreg32(ldev, LSDC_CRTC1_HSYNC_REG,
247                     (mode->crtc_hsync_end << 16) | mode->crtc_hsync_start | HSYNC_EN);
248
249         lsdc_wreg32(ldev, LSDC_CRTC1_VSYNC_REG,
250                     (mode->crtc_vsync_end << 16) | mode->crtc_vsync_start | VSYNC_EN);
251 }
252
253 /*
254  * This is required for S3 support.
255  * After resuming from suspend, LSDC_CRTCx_CFG_REG (x = 0 or 1) is filled
256  * with garbage value, which causes the CRTC hang there.
257  *
258  * This function provides minimal settings for the affected registers.
259  * This overrides the firmware's settings on startup, making the CRTC work
260  * on our own, similar to the functional of GPU POST (Power On Self Test).
261  * Only touch CRTC hardware-related parts.
262  */
263
264 static void lsdc_crtc0_reset(struct lsdc_crtc *lcrtc)
265 {
266         struct lsdc_device *ldev = lcrtc->ldev;
267
268         lsdc_wreg32(ldev, LSDC_CRTC0_CFG_REG, CFG_RESET_N | LSDC_PF_XRGB8888);
269 }
270
271 static void lsdc_crtc1_reset(struct lsdc_crtc *lcrtc)
272 {
273         struct lsdc_device *ldev = lcrtc->ldev;
274
275         lsdc_wreg32(ldev, LSDC_CRTC1_CFG_REG, CFG_RESET_N | LSDC_PF_XRGB8888);
276 }
277
278 static const struct lsdc_crtc_hw_ops ls7a1000_crtc_hw_ops[2] = {
279         {
280                 .enable = lsdc_crtc0_enable,
281                 .disable = lsdc_crtc0_disable,
282                 .enable_vblank = lsdc_crtc0_enable_vblank,
283                 .disable_vblank = lsdc_crtc0_disable_vblank,
284                 .flip = lsdc_crtc0_flip,
285                 .clone = lsdc_crtc0_clone,
286                 .set_mode = lsdc_crtc0_set_mode,
287                 .get_scan_pos = lsdc_crtc0_scan_pos,
288                 .soft_reset = lsdc_crtc0_soft_reset,
289                 .reset = lsdc_crtc0_reset,
290         },
291         {
292                 .enable = lsdc_crtc1_enable,
293                 .disable = lsdc_crtc1_disable,
294                 .enable_vblank = lsdc_crtc1_enable_vblank,
295                 .disable_vblank = lsdc_crtc1_disable_vblank,
296                 .flip = lsdc_crtc1_flip,
297                 .clone = lsdc_crtc1_clone,
298                 .set_mode = lsdc_crtc1_set_mode,
299                 .get_scan_pos = lsdc_crtc1_scan_pos,
300                 .soft_reset = lsdc_crtc1_soft_reset,
301                 .reset = lsdc_crtc1_reset,
302         },
303 };
304
305 /*
306  * The 32-bit hardware vblank counter has been available since LS7A2000
307  * and LS2K2000. The counter increases even though the CRTC is disabled,
308  * it will be reset only if the CRTC is being soft reset.
309  * Those registers are also readable for ls7a1000, but its value does not
310  * change.
311  */
312
313 static u32 lsdc_crtc0_get_vblank_count(struct lsdc_crtc *lcrtc)
314 {
315         struct lsdc_device *ldev = lcrtc->ldev;
316
317         return lsdc_rreg32(ldev, LSDC_CRTC0_VSYNC_COUNTER_REG);
318 }
319
320 static u32 lsdc_crtc1_get_vblank_count(struct lsdc_crtc *lcrtc)
321 {
322         struct lsdc_device *ldev = lcrtc->ldev;
323
324         return lsdc_rreg32(ldev, LSDC_CRTC1_VSYNC_COUNTER_REG);
325 }
326
327 /*
328  * The DMA step bit fields are available since LS7A2000/LS2K2000, for
329  * supporting odd resolutions. But a large DMA step save the bandwidth.
330  * The larger, the better. Behavior of writing those bits on LS7A1000
331  * or LS2K1000 is underfined.
332  */
333
334 static void lsdc_crtc0_set_dma_step(struct lsdc_crtc *lcrtc,
335                                     enum lsdc_dma_steps dma_step)
336 {
337         struct lsdc_device *ldev = lcrtc->ldev;
338         u32 val = lsdc_rreg32(ldev, LSDC_CRTC0_CFG_REG);
339
340         val &= ~CFG_DMA_STEP_MASK;
341         val |= dma_step << CFG_DMA_STEP_SHIFT;
342
343         lsdc_wreg32(ldev, LSDC_CRTC0_CFG_REG, val);
344 }
345
346 static void lsdc_crtc1_set_dma_step(struct lsdc_crtc *lcrtc,
347                                     enum lsdc_dma_steps dma_step)
348 {
349         struct lsdc_device *ldev = lcrtc->ldev;
350         u32 val = lsdc_rreg32(ldev, LSDC_CRTC1_CFG_REG);
351
352         val &= ~CFG_DMA_STEP_MASK;
353         val |= dma_step << CFG_DMA_STEP_SHIFT;
354
355         lsdc_wreg32(ldev, LSDC_CRTC1_CFG_REG, val);
356 }
357
358 static const struct lsdc_crtc_hw_ops ls7a2000_crtc_hw_ops[2] = {
359         {
360                 .enable = lsdc_crtc0_enable,
361                 .disable = lsdc_crtc0_disable,
362                 .enable_vblank = lsdc_crtc0_enable_vblank,
363                 .disable_vblank = lsdc_crtc0_disable_vblank,
364                 .flip = lsdc_crtc0_flip,
365                 .clone = lsdc_crtc0_clone,
366                 .set_mode = lsdc_crtc0_set_mode,
367                 .soft_reset = lsdc_crtc0_soft_reset,
368                 .get_scan_pos = lsdc_crtc0_scan_pos,
369                 .set_dma_step = lsdc_crtc0_set_dma_step,
370                 .get_vblank_counter = lsdc_crtc0_get_vblank_count,
371                 .reset = lsdc_crtc0_reset,
372         },
373         {
374                 .enable = lsdc_crtc1_enable,
375                 .disable = lsdc_crtc1_disable,
376                 .enable_vblank = lsdc_crtc1_enable_vblank,
377                 .disable_vblank = lsdc_crtc1_disable_vblank,
378                 .flip = lsdc_crtc1_flip,
379                 .clone = lsdc_crtc1_clone,
380                 .set_mode = lsdc_crtc1_set_mode,
381                 .get_scan_pos = lsdc_crtc1_scan_pos,
382                 .soft_reset = lsdc_crtc1_soft_reset,
383                 .set_dma_step = lsdc_crtc1_set_dma_step,
384                 .get_vblank_counter = lsdc_crtc1_get_vblank_count,
385                 .reset = lsdc_crtc1_reset,
386         },
387 };
388
389 static void lsdc_crtc_reset(struct drm_crtc *crtc)
390 {
391         struct lsdc_crtc *lcrtc = to_lsdc_crtc(crtc);
392         const struct lsdc_crtc_hw_ops *ops = lcrtc->hw_ops;
393         struct lsdc_crtc_state *priv_crtc_state;
394
395         if (crtc->state)
396                 crtc->funcs->atomic_destroy_state(crtc, crtc->state);
397
398         priv_crtc_state = kzalloc(sizeof(*priv_crtc_state), GFP_KERNEL);
399
400         if (!priv_crtc_state)
401                 __drm_atomic_helper_crtc_reset(crtc, NULL);
402         else
403                 __drm_atomic_helper_crtc_reset(crtc, &priv_crtc_state->base);
404
405         /* Reset the CRTC hardware, this is required for S3 support */
406         ops->reset(lcrtc);
407 }
408
409 static void lsdc_crtc_atomic_destroy_state(struct drm_crtc *crtc,
410                                            struct drm_crtc_state *state)
411 {
412         struct lsdc_crtc_state *priv_state = to_lsdc_crtc_state(state);
413
414         __drm_atomic_helper_crtc_destroy_state(&priv_state->base);
415
416         kfree(priv_state);
417 }
418
419 static struct drm_crtc_state *
420 lsdc_crtc_atomic_duplicate_state(struct drm_crtc *crtc)
421 {
422         struct lsdc_crtc_state *new_priv_state;
423         struct lsdc_crtc_state *old_priv_state;
424
425         new_priv_state = kzalloc(sizeof(*new_priv_state), GFP_KERNEL);
426         if (!new_priv_state)
427                 return NULL;
428
429         __drm_atomic_helper_crtc_duplicate_state(crtc, &new_priv_state->base);
430
431         old_priv_state = to_lsdc_crtc_state(crtc->state);
432
433         memcpy(&new_priv_state->pparms, &old_priv_state->pparms,
434                sizeof(new_priv_state->pparms));
435
436         return &new_priv_state->base;
437 }
438
439 static u32 lsdc_crtc_get_vblank_counter(struct drm_crtc *crtc)
440 {
441         struct lsdc_crtc *lcrtc = to_lsdc_crtc(crtc);
442
443         /* 32-bit hardware vblank counter */
444         return lcrtc->hw_ops->get_vblank_counter(lcrtc);
445 }
446
447 static int lsdc_crtc_enable_vblank(struct drm_crtc *crtc)
448 {
449         struct lsdc_crtc *lcrtc = to_lsdc_crtc(crtc);
450
451         if (!lcrtc->has_vblank)
452                 return -EINVAL;
453
454         lcrtc->hw_ops->enable_vblank(lcrtc);
455
456         return 0;
457 }
458
459 static void lsdc_crtc_disable_vblank(struct drm_crtc *crtc)
460 {
461         struct lsdc_crtc *lcrtc = to_lsdc_crtc(crtc);
462
463         if (!lcrtc->has_vblank)
464                 return;
465
466         lcrtc->hw_ops->disable_vblank(lcrtc);
467 }
468
469 /*
470  * CRTC related debugfs
471  * Primary planes and cursor planes belong to the CRTC as well.
472  * For the sake of convenience, plane-related registers are also add here.
473  */
474
475 #define REG_DEF(reg) { \
476         .name = __stringify_1(LSDC_##reg##_REG), \
477         .offset = LSDC_##reg##_REG, \
478 }
479
480 static const struct lsdc_reg32 lsdc_crtc_regs_array[2][21] = {
481         [0] = {
482                 REG_DEF(CRTC0_CFG),
483                 REG_DEF(CRTC0_FB_ORIGIN),
484                 REG_DEF(CRTC0_DVO_CONF),
485                 REG_DEF(CRTC0_HDISPLAY),
486                 REG_DEF(CRTC0_HSYNC),
487                 REG_DEF(CRTC0_VDISPLAY),
488                 REG_DEF(CRTC0_VSYNC),
489                 REG_DEF(CRTC0_GAMMA_INDEX),
490                 REG_DEF(CRTC0_GAMMA_DATA),
491                 REG_DEF(CRTC0_SYNC_DEVIATION),
492                 REG_DEF(CRTC0_VSYNC_COUNTER),
493                 REG_DEF(CRTC0_SCAN_POS),
494                 REG_DEF(CRTC0_STRIDE),
495                 REG_DEF(CRTC0_FB1_ADDR_HI),
496                 REG_DEF(CRTC0_FB1_ADDR_LO),
497                 REG_DEF(CRTC0_FB0_ADDR_HI),
498                 REG_DEF(CRTC0_FB0_ADDR_LO),
499                 REG_DEF(CURSOR0_CFG),
500                 REG_DEF(CURSOR0_POSITION),
501                 REG_DEF(CURSOR0_BG_COLOR),
502                 REG_DEF(CURSOR0_FG_COLOR),
503         },
504         [1] = {
505                 REG_DEF(CRTC1_CFG),
506                 REG_DEF(CRTC1_FB_ORIGIN),
507                 REG_DEF(CRTC1_DVO_CONF),
508                 REG_DEF(CRTC1_HDISPLAY),
509                 REG_DEF(CRTC1_HSYNC),
510                 REG_DEF(CRTC1_VDISPLAY),
511                 REG_DEF(CRTC1_VSYNC),
512                 REG_DEF(CRTC1_GAMMA_INDEX),
513                 REG_DEF(CRTC1_GAMMA_DATA),
514                 REG_DEF(CRTC1_SYNC_DEVIATION),
515                 REG_DEF(CRTC1_VSYNC_COUNTER),
516                 REG_DEF(CRTC1_SCAN_POS),
517                 REG_DEF(CRTC1_STRIDE),
518                 REG_DEF(CRTC1_FB1_ADDR_HI),
519                 REG_DEF(CRTC1_FB1_ADDR_LO),
520                 REG_DEF(CRTC1_FB0_ADDR_HI),
521                 REG_DEF(CRTC1_FB0_ADDR_LO),
522                 REG_DEF(CURSOR1_CFG),
523                 REG_DEF(CURSOR1_POSITION),
524                 REG_DEF(CURSOR1_BG_COLOR),
525                 REG_DEF(CURSOR1_FG_COLOR),
526         },
527 };
528
529 static int lsdc_crtc_show_regs(struct seq_file *m, void *arg)
530 {
531         struct drm_info_node *node = (struct drm_info_node *)m->private;
532         struct lsdc_crtc *lcrtc = (struct lsdc_crtc *)node->info_ent->data;
533         struct lsdc_device *ldev = lcrtc->ldev;
534         unsigned int i;
535
536         for (i = 0; i < lcrtc->nreg; i++) {
537                 const struct lsdc_reg32 *preg = &lcrtc->preg[i];
538                 u32 offset = preg->offset;
539
540                 seq_printf(m, "%s (0x%04x): 0x%08x\n",
541                            preg->name, offset, lsdc_rreg32(ldev, offset));
542         }
543
544         return 0;
545 }
546
547 static int lsdc_crtc_show_scan_position(struct seq_file *m, void *arg)
548 {
549         struct drm_info_node *node = (struct drm_info_node *)m->private;
550         struct lsdc_crtc *lcrtc = (struct lsdc_crtc *)node->info_ent->data;
551         int x, y;
552
553         lcrtc->hw_ops->get_scan_pos(lcrtc, &x, &y);
554         seq_printf(m, "Scanout position: x: %08u, y: %08u\n", x, y);
555
556         return 0;
557 }
558
559 static int lsdc_crtc_show_vblank_counter(struct seq_file *m, void *arg)
560 {
561         struct drm_info_node *node = (struct drm_info_node *)m->private;
562         struct lsdc_crtc *lcrtc = (struct lsdc_crtc *)node->info_ent->data;
563
564         if (lcrtc->hw_ops->get_vblank_counter)
565                 seq_printf(m, "%s vblank counter: %08u\n\n", lcrtc->base.name,
566                            lcrtc->hw_ops->get_vblank_counter(lcrtc));
567
568         return 0;
569 }
570
571 static int lsdc_pixpll_show_clock(struct seq_file *m, void *arg)
572 {
573         struct drm_info_node *node = (struct drm_info_node *)m->private;
574         struct lsdc_crtc *lcrtc = (struct lsdc_crtc *)node->info_ent->data;
575         struct lsdc_pixpll *pixpll = &lcrtc->pixpll;
576         const struct lsdc_pixpll_funcs *funcs = pixpll->funcs;
577         struct drm_crtc *crtc = &lcrtc->base;
578         struct drm_display_mode *mode = &crtc->state->mode;
579         struct drm_printer printer = drm_seq_file_printer(m);
580         unsigned int out_khz;
581
582         out_khz = funcs->get_rate(pixpll);
583
584         seq_printf(m, "%s: %dx%d@%d\n", crtc->name,
585                    mode->hdisplay, mode->vdisplay, drm_mode_vrefresh(mode));
586
587         seq_printf(m, "Pixel clock required: %d kHz\n", mode->clock);
588         seq_printf(m, "Actual frequency output: %u kHz\n", out_khz);
589         seq_printf(m, "Diff: %d kHz\n", out_khz - mode->clock);
590
591         funcs->print(pixpll, &printer);
592
593         return 0;
594 }
595
596 static struct drm_info_list lsdc_crtc_debugfs_list[2][4] = {
597         [0] = {
598                 { "regs", lsdc_crtc_show_regs, 0, NULL },
599                 { "pixclk", lsdc_pixpll_show_clock, 0, NULL },
600                 { "scanpos", lsdc_crtc_show_scan_position, 0, NULL },
601                 { "vblanks", lsdc_crtc_show_vblank_counter, 0, NULL },
602         },
603         [1] = {
604                 { "regs", lsdc_crtc_show_regs, 0, NULL },
605                 { "pixclk", lsdc_pixpll_show_clock, 0, NULL },
606                 { "scanpos", lsdc_crtc_show_scan_position, 0, NULL },
607                 { "vblanks", lsdc_crtc_show_vblank_counter, 0, NULL },
608         },
609 };
610
611 /* operate manually */
612
613 static int lsdc_crtc_man_op_show(struct seq_file *m, void *data)
614 {
615         seq_puts(m, "soft_reset: soft reset this CRTC\n");
616         seq_puts(m, "enable: enable this CRTC\n");
617         seq_puts(m, "disable: disable this CRTC\n");
618         seq_puts(m, "flip: trigger the page flip\n");
619         seq_puts(m, "clone: clone the another crtc with hardware logic\n");
620
621         return 0;
622 }
623
624 static int lsdc_crtc_man_op_open(struct inode *inode, struct file *file)
625 {
626         struct drm_crtc *crtc = inode->i_private;
627
628         return single_open(file, lsdc_crtc_man_op_show, crtc);
629 }
630
631 static ssize_t lsdc_crtc_man_op_write(struct file *file,
632                                       const char __user *ubuf,
633                                       size_t len,
634                                       loff_t *offp)
635 {
636         struct seq_file *m = file->private_data;
637         struct lsdc_crtc *lcrtc = m->private;
638         const struct lsdc_crtc_hw_ops *ops = lcrtc->hw_ops;
639         char buf[16];
640
641         if (len > sizeof(buf) - 1)
642                 return -EINVAL;
643
644         if (copy_from_user(buf, ubuf, len))
645                 return -EFAULT;
646
647         buf[len] = '\0';
648
649         if (sysfs_streq(buf, "soft_reset"))
650                 ops->soft_reset(lcrtc);
651         else if (sysfs_streq(buf, "enable"))
652                 ops->enable(lcrtc);
653         else if (sysfs_streq(buf, "disable"))
654                 ops->disable(lcrtc);
655         else if (sysfs_streq(buf, "flip"))
656                 ops->flip(lcrtc);
657         else if (sysfs_streq(buf, "clone"))
658                 ops->clone(lcrtc);
659
660         return len;
661 }
662
663 static const struct file_operations lsdc_crtc_man_op_fops = {
664         .owner = THIS_MODULE,
665         .open = lsdc_crtc_man_op_open,
666         .read = seq_read,
667         .llseek = seq_lseek,
668         .release = single_release,
669         .write = lsdc_crtc_man_op_write,
670 };
671
672 static int lsdc_crtc_late_register(struct drm_crtc *crtc)
673 {
674         struct lsdc_display_pipe *dispipe = crtc_to_display_pipe(crtc);
675         struct lsdc_crtc *lcrtc = to_lsdc_crtc(crtc);
676         struct drm_minor *minor = crtc->dev->primary;
677         unsigned int index = dispipe->index;
678         unsigned int i;
679
680         lcrtc->preg = lsdc_crtc_regs_array[index];
681         lcrtc->nreg = ARRAY_SIZE(lsdc_crtc_regs_array[index]);
682         lcrtc->p_info_list = lsdc_crtc_debugfs_list[index];
683         lcrtc->n_info_list = ARRAY_SIZE(lsdc_crtc_debugfs_list[index]);
684
685         for (i = 0; i < lcrtc->n_info_list; ++i)
686                 lcrtc->p_info_list[i].data = lcrtc;
687
688         drm_debugfs_create_files(lcrtc->p_info_list, lcrtc->n_info_list,
689                                  crtc->debugfs_entry, minor);
690
691         /* Manual operations supported */
692         debugfs_create_file("ops", 0644, crtc->debugfs_entry, lcrtc,
693                             &lsdc_crtc_man_op_fops);
694
695         return 0;
696 }
697
698 static void lsdc_crtc_atomic_print_state(struct drm_printer *p,
699                                          const struct drm_crtc_state *state)
700 {
701         const struct lsdc_crtc_state *priv_state;
702         const struct lsdc_pixpll_parms *pparms;
703
704         priv_state = container_of_const(state, struct lsdc_crtc_state, base);
705         pparms = &priv_state->pparms;
706
707         drm_printf(p, "\tInput clock divider = %u\n", pparms->div_ref);
708         drm_printf(p, "\tMedium clock multiplier = %u\n", pparms->loopc);
709         drm_printf(p, "\tOutput clock divider = %u\n", pparms->div_out);
710 }
711
712 static const struct drm_crtc_funcs ls7a1000_crtc_funcs = {
713         .reset = lsdc_crtc_reset,
714         .destroy = drm_crtc_cleanup,
715         .set_config = drm_atomic_helper_set_config,
716         .page_flip = drm_atomic_helper_page_flip,
717         .atomic_duplicate_state = lsdc_crtc_atomic_duplicate_state,
718         .atomic_destroy_state = lsdc_crtc_atomic_destroy_state,
719         .late_register = lsdc_crtc_late_register,
720         .enable_vblank = lsdc_crtc_enable_vblank,
721         .disable_vblank = lsdc_crtc_disable_vblank,
722         .get_vblank_timestamp = drm_crtc_vblank_helper_get_vblank_timestamp,
723         .atomic_print_state = lsdc_crtc_atomic_print_state,
724 };
725
726 static const struct drm_crtc_funcs ls7a2000_crtc_funcs = {
727         .reset = lsdc_crtc_reset,
728         .destroy = drm_crtc_cleanup,
729         .set_config = drm_atomic_helper_set_config,
730         .page_flip = drm_atomic_helper_page_flip,
731         .atomic_duplicate_state = lsdc_crtc_atomic_duplicate_state,
732         .atomic_destroy_state = lsdc_crtc_atomic_destroy_state,
733         .late_register = lsdc_crtc_late_register,
734         .get_vblank_counter = lsdc_crtc_get_vblank_counter,
735         .enable_vblank = lsdc_crtc_enable_vblank,
736         .disable_vblank = lsdc_crtc_disable_vblank,
737         .get_vblank_timestamp = drm_crtc_vblank_helper_get_vblank_timestamp,
738         .atomic_print_state = lsdc_crtc_atomic_print_state,
739 };
740
741 static enum drm_mode_status
742 lsdc_crtc_mode_valid(struct drm_crtc *crtc, const struct drm_display_mode *mode)
743 {
744         struct drm_device *ddev = crtc->dev;
745         struct lsdc_device *ldev = to_lsdc(ddev);
746         const struct lsdc_desc *descp = ldev->descp;
747         unsigned int pitch;
748
749         if (mode->hdisplay > descp->max_width)
750                 return MODE_BAD_HVALUE;
751
752         if (mode->vdisplay > descp->max_height)
753                 return MODE_BAD_VVALUE;
754
755         if (mode->clock > descp->max_pixel_clk) {
756                 drm_dbg_kms(ddev, "mode %dx%d, pixel clock=%d is too high\n",
757                             mode->hdisplay, mode->vdisplay, mode->clock);
758                 return MODE_CLOCK_HIGH;
759         }
760
761         /* 4 for DRM_FORMAT_XRGB8888 */
762         pitch = mode->hdisplay * 4;
763
764         if (pitch % descp->pitch_align) {
765                 drm_dbg_kms(ddev, "align to %u bytes is required: %u\n",
766                             descp->pitch_align, pitch);
767                 return MODE_BAD_WIDTH;
768         }
769
770         return MODE_OK;
771 }
772
773 static int lsdc_pixpll_atomic_check(struct drm_crtc *crtc,
774                                     struct drm_crtc_state *state)
775 {
776         struct lsdc_crtc *lcrtc = to_lsdc_crtc(crtc);
777         struct lsdc_pixpll *pixpll = &lcrtc->pixpll;
778         const struct lsdc_pixpll_funcs *pfuncs = pixpll->funcs;
779         struct lsdc_crtc_state *priv_state = to_lsdc_crtc_state(state);
780         unsigned int clock = state->mode.clock;
781         int ret;
782
783         ret = pfuncs->compute(pixpll, clock, &priv_state->pparms);
784         if (ret) {
785                 drm_warn(crtc->dev, "Failed to find PLL params for %ukHz\n",
786                          clock);
787                 return -EINVAL;
788         }
789
790         return 0;
791 }
792
793 static int lsdc_crtc_helper_atomic_check(struct drm_crtc *crtc,
794                                          struct drm_atomic_state *state)
795 {
796         struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
797
798         if (!crtc_state->enable)
799                 return 0;
800
801         return lsdc_pixpll_atomic_check(crtc, crtc_state);
802 }
803
804 static void lsdc_crtc_mode_set_nofb(struct drm_crtc *crtc)
805 {
806         struct lsdc_crtc *lcrtc = to_lsdc_crtc(crtc);
807         const struct lsdc_crtc_hw_ops *crtc_hw_ops = lcrtc->hw_ops;
808         struct lsdc_pixpll *pixpll = &lcrtc->pixpll;
809         const struct lsdc_pixpll_funcs *pixpll_funcs = pixpll->funcs;
810         struct drm_crtc_state *state = crtc->state;
811         struct drm_display_mode *mode = &state->mode;
812         struct lsdc_crtc_state *priv_state = to_lsdc_crtc_state(state);
813
814         pixpll_funcs->update(pixpll, &priv_state->pparms);
815
816         if (crtc_hw_ops->set_dma_step) {
817                 unsigned int width_in_bytes = mode->hdisplay * 4;
818                 enum lsdc_dma_steps dma_step;
819
820                 /*
821                  * Using DMA step as large as possible, for improving
822                  * hardware DMA efficiency.
823                  */
824                 if (width_in_bytes % 256 == 0)
825                         dma_step = LSDC_DMA_STEP_256_BYTES;
826                 else if (width_in_bytes % 128 == 0)
827                         dma_step = LSDC_DMA_STEP_128_BYTES;
828                 else if (width_in_bytes % 64 == 0)
829                         dma_step = LSDC_DMA_STEP_64_BYTES;
830                 else  /* width_in_bytes % 32 == 0 */
831                         dma_step = LSDC_DMA_STEP_32_BYTES;
832
833                 crtc_hw_ops->set_dma_step(lcrtc, dma_step);
834         }
835
836         crtc_hw_ops->set_mode(lcrtc, mode);
837 }
838
839 static void lsdc_crtc_send_vblank(struct drm_crtc *crtc)
840 {
841         struct drm_device *ddev = crtc->dev;
842         unsigned long flags;
843
844         if (!crtc->state || !crtc->state->event)
845                 return;
846
847         drm_dbg(ddev, "Send vblank manually\n");
848
849         spin_lock_irqsave(&ddev->event_lock, flags);
850         drm_crtc_send_vblank_event(crtc, crtc->state->event);
851         crtc->state->event = NULL;
852         spin_unlock_irqrestore(&ddev->event_lock, flags);
853 }
854
855 static void lsdc_crtc_atomic_enable(struct drm_crtc *crtc,
856                                     struct drm_atomic_state *state)
857 {
858         struct lsdc_crtc *lcrtc = to_lsdc_crtc(crtc);
859
860         if (lcrtc->has_vblank)
861                 drm_crtc_vblank_on(crtc);
862
863         lcrtc->hw_ops->enable(lcrtc);
864 }
865
866 static void lsdc_crtc_atomic_disable(struct drm_crtc *crtc,
867                                      struct drm_atomic_state *state)
868 {
869         struct lsdc_crtc *lcrtc = to_lsdc_crtc(crtc);
870
871         if (lcrtc->has_vblank)
872                 drm_crtc_vblank_off(crtc);
873
874         lcrtc->hw_ops->disable(lcrtc);
875
876         /*
877          * Make sure we issue a vblank event after disabling the CRTC if
878          * someone was waiting it.
879          */
880         lsdc_crtc_send_vblank(crtc);
881 }
882
883 static void lsdc_crtc_atomic_flush(struct drm_crtc *crtc,
884                                    struct drm_atomic_state *state)
885 {
886         spin_lock_irq(&crtc->dev->event_lock);
887         if (crtc->state->event) {
888                 if (drm_crtc_vblank_get(crtc) == 0)
889                         drm_crtc_arm_vblank_event(crtc, crtc->state->event);
890                 else
891                         drm_crtc_send_vblank_event(crtc, crtc->state->event);
892                 crtc->state->event = NULL;
893         }
894         spin_unlock_irq(&crtc->dev->event_lock);
895 }
896
897 static bool lsdc_crtc_get_scanout_position(struct drm_crtc *crtc,
898                                            bool in_vblank_irq,
899                                            int *vpos,
900                                            int *hpos,
901                                            ktime_t *stime,
902                                            ktime_t *etime,
903                                            const struct drm_display_mode *mode)
904 {
905         struct lsdc_crtc *lcrtc = to_lsdc_crtc(crtc);
906         const struct lsdc_crtc_hw_ops *ops = lcrtc->hw_ops;
907         int vsw, vbp, vactive_start, vactive_end, vfp_end;
908         int x, y;
909
910         vsw = mode->crtc_vsync_end - mode->crtc_vsync_start;
911         vbp = mode->crtc_vtotal - mode->crtc_vsync_end;
912
913         vactive_start = vsw + vbp + 1;
914         vactive_end = vactive_start + mode->crtc_vdisplay;
915
916         /* last scan line before VSYNC */
917         vfp_end = mode->crtc_vtotal;
918
919         if (stime)
920                 *stime = ktime_get();
921
922         ops->get_scan_pos(lcrtc, &x, &y);
923
924         if (y > vactive_end)
925                 y = y - vfp_end - vactive_start;
926         else
927                 y -= vactive_start;
928
929         *vpos = y;
930         *hpos = 0;
931
932         if (etime)
933                 *etime = ktime_get();
934
935         return true;
936 }
937
938 static const struct drm_crtc_helper_funcs lsdc_crtc_helper_funcs = {
939         .mode_valid = lsdc_crtc_mode_valid,
940         .mode_set_nofb = lsdc_crtc_mode_set_nofb,
941         .atomic_enable = lsdc_crtc_atomic_enable,
942         .atomic_disable = lsdc_crtc_atomic_disable,
943         .atomic_check = lsdc_crtc_helper_atomic_check,
944         .atomic_flush = lsdc_crtc_atomic_flush,
945         .get_scanout_position = lsdc_crtc_get_scanout_position,
946 };
947
948 int ls7a1000_crtc_init(struct drm_device *ddev,
949                        struct drm_crtc *crtc,
950                        struct drm_plane *primary,
951                        struct drm_plane *cursor,
952                        unsigned int index,
953                        bool has_vblank)
954 {
955         struct lsdc_crtc *lcrtc = to_lsdc_crtc(crtc);
956         int ret;
957
958         ret = lsdc_pixpll_init(&lcrtc->pixpll, ddev, index);
959         if (ret) {
960                 drm_err(ddev, "pixel pll init failed: %d\n", ret);
961                 return ret;
962         }
963
964         lcrtc->ldev = to_lsdc(ddev);
965         lcrtc->has_vblank = has_vblank;
966         lcrtc->hw_ops = &ls7a1000_crtc_hw_ops[index];
967
968         ret = drm_crtc_init_with_planes(ddev, crtc, primary, cursor,
969                                         &ls7a1000_crtc_funcs,
970                                         "LS-CRTC-%d", index);
971         if (ret) {
972                 drm_err(ddev, "crtc init with planes failed: %d\n", ret);
973                 return ret;
974         }
975
976         drm_crtc_helper_add(crtc, &lsdc_crtc_helper_funcs);
977
978         ret = drm_mode_crtc_set_gamma_size(crtc, 256);
979         if (ret)
980                 return ret;
981
982         drm_crtc_enable_color_mgmt(crtc, 0, false, 256);
983
984         return 0;
985 }
986
987 int ls7a2000_crtc_init(struct drm_device *ddev,
988                        struct drm_crtc *crtc,
989                        struct drm_plane *primary,
990                        struct drm_plane *cursor,
991                        unsigned int index,
992                        bool has_vblank)
993 {
994         struct lsdc_crtc *lcrtc = to_lsdc_crtc(crtc);
995         int ret;
996
997         ret = lsdc_pixpll_init(&lcrtc->pixpll, ddev, index);
998         if (ret) {
999                 drm_err(ddev, "crtc init with pll failed: %d\n", ret);
1000                 return ret;
1001         }
1002
1003         lcrtc->ldev = to_lsdc(ddev);
1004         lcrtc->has_vblank = has_vblank;
1005         lcrtc->hw_ops = &ls7a2000_crtc_hw_ops[index];
1006
1007         ret = drm_crtc_init_with_planes(ddev, crtc, primary, cursor,
1008                                         &ls7a2000_crtc_funcs,
1009                                         "LS-CRTC-%u", index);
1010         if (ret) {
1011                 drm_err(ddev, "crtc init with planes failed: %d\n", ret);
1012                 return ret;
1013         }
1014
1015         drm_crtc_helper_add(crtc, &lsdc_crtc_helper_funcs);
1016
1017         ret = drm_mode_crtc_set_gamma_size(crtc, 256);
1018         if (ret)
1019                 return ret;
1020
1021         drm_crtc_enable_color_mgmt(crtc, 0, false, 256);
1022
1023         return 0;
1024 }
This page took 0.088041 seconds and 4 git commands to generate.