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