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