Merge tag 'nand/for-4.16' of git://git.infradead.org/linux-mtd into mtd/next
[linux-2.6-microblaze.git] / drivers / gpu / drm / amd / display / dc / dce110 / dce110_timing_generator_v.c
1 #include "dm_services.h"
2
3 /* include DCE11 register header files */
4 #include "dce/dce_11_0_d.h"
5 #include "dce/dce_11_0_sh_mask.h"
6
7 #include "dc_types.h"
8 #include "dc_bios_types.h"
9 #include "dc.h"
10
11 #include "include/grph_object_id.h"
12 #include "include/logger_interface.h"
13 #include "dce110_timing_generator.h"
14 #include "dce110_timing_generator_v.h"
15
16 #include "timing_generator.h"
17
18 /** ********************************************************************************
19  *
20  * DCE11 Timing Generator Implementation
21  *
22  **********************************************************************************/
23
24 /**
25 * Enable CRTCV
26 */
27
28 static bool dce110_timing_generator_v_enable_crtc(struct timing_generator *tg)
29 {
30 /*
31 * Set MASTER_UPDATE_MODE to 0
32 * This is needed for DRR, and also suggested to be default value by Syed.
33 */
34
35         uint32_t value;
36
37         value = 0;
38         set_reg_field_value(value, 0,
39                         CRTCV_MASTER_UPDATE_MODE, MASTER_UPDATE_MODE);
40         dm_write_reg(tg->ctx,
41                         mmCRTCV_MASTER_UPDATE_MODE, value);
42
43         /* TODO: may want this on for looking for underflow */
44         value = 0;
45         dm_write_reg(tg->ctx, mmCRTCV_MASTER_UPDATE_MODE, value);
46
47         value = 0;
48         set_reg_field_value(value, 1,
49                         CRTCV_MASTER_EN, CRTC_MASTER_EN);
50         dm_write_reg(tg->ctx,
51                         mmCRTCV_MASTER_EN, value);
52
53         return true;
54 }
55
56 static bool dce110_timing_generator_v_disable_crtc(struct timing_generator *tg)
57 {
58         uint32_t value;
59
60         value = dm_read_reg(tg->ctx,
61                         mmCRTCV_CONTROL);
62         set_reg_field_value(value, 0,
63                         CRTCV_CONTROL, CRTC_DISABLE_POINT_CNTL);
64         set_reg_field_value(value, 0,
65                                 CRTCV_CONTROL, CRTC_MASTER_EN);
66         dm_write_reg(tg->ctx,
67                         mmCRTCV_CONTROL, value);
68         /*
69          * TODO: call this when adding stereo support
70          * tg->funcs->disable_stereo(tg);
71          */
72         return true;
73 }
74
75 static void dce110_timing_generator_v_blank_crtc(struct timing_generator *tg)
76 {
77         uint32_t addr = mmCRTCV_BLANK_CONTROL;
78         uint32_t value = dm_read_reg(tg->ctx, addr);
79
80         set_reg_field_value(
81                 value,
82                 1,
83                 CRTCV_BLANK_CONTROL,
84                 CRTC_BLANK_DATA_EN);
85
86         set_reg_field_value(
87                 value,
88                 0,
89                 CRTCV_BLANK_CONTROL,
90                 CRTC_BLANK_DE_MODE);
91
92         dm_write_reg(tg->ctx, addr, value);
93 }
94
95 static void dce110_timing_generator_v_unblank_crtc(struct timing_generator *tg)
96 {
97         uint32_t addr = mmCRTCV_BLANK_CONTROL;
98         uint32_t value = dm_read_reg(tg->ctx, addr);
99
100         set_reg_field_value(
101                 value,
102                 0,
103                 CRTCV_BLANK_CONTROL,
104                 CRTC_BLANK_DATA_EN);
105
106         set_reg_field_value(
107                 value,
108                 0,
109                 CRTCV_BLANK_CONTROL,
110                 CRTC_BLANK_DE_MODE);
111
112         dm_write_reg(tg->ctx, addr, value);
113 }
114
115 static bool dce110_timing_generator_v_is_in_vertical_blank(
116                 struct timing_generator *tg)
117 {
118         uint32_t addr = 0;
119         uint32_t value = 0;
120         uint32_t field = 0;
121
122         addr = mmCRTCV_STATUS;
123         value = dm_read_reg(tg->ctx, addr);
124         field = get_reg_field_value(value, CRTCV_STATUS, CRTC_V_BLANK);
125         return field == 1;
126 }
127
128 static bool dce110_timing_generator_v_is_counter_moving(struct timing_generator *tg)
129 {
130         uint32_t value;
131         uint32_t h1 = 0;
132         uint32_t h2 = 0;
133         uint32_t v1 = 0;
134         uint32_t v2 = 0;
135
136         value = dm_read_reg(tg->ctx, mmCRTCV_STATUS_POSITION);
137
138         h1 = get_reg_field_value(
139                         value,
140                         CRTCV_STATUS_POSITION,
141                         CRTC_HORZ_COUNT);
142
143         v1 = get_reg_field_value(
144                         value,
145                         CRTCV_STATUS_POSITION,
146                         CRTC_VERT_COUNT);
147
148         value = dm_read_reg(tg->ctx, mmCRTCV_STATUS_POSITION);
149
150         h2 = get_reg_field_value(
151                         value,
152                         CRTCV_STATUS_POSITION,
153                         CRTC_HORZ_COUNT);
154
155         v2 = get_reg_field_value(
156                         value,
157                         CRTCV_STATUS_POSITION,
158                         CRTC_VERT_COUNT);
159
160         if (h1 == h2 && v1 == v2)
161                 return false;
162         else
163                 return true;
164 }
165
166 static void dce110_timing_generator_v_wait_for_vblank(struct timing_generator *tg)
167 {
168         /* We want to catch beginning of VBlank here, so if the first try are
169          * in VBlank, we might be very close to Active, in this case wait for
170          * another frame
171          */
172         while (dce110_timing_generator_v_is_in_vertical_blank(tg)) {
173                 if (!dce110_timing_generator_v_is_counter_moving(tg)) {
174                         /* error - no point to wait if counter is not moving */
175                         break;
176                 }
177         }
178
179         while (!dce110_timing_generator_v_is_in_vertical_blank(tg)) {
180                 if (!dce110_timing_generator_v_is_counter_moving(tg)) {
181                         /* error - no point to wait if counter is not moving */
182                         break;
183                 }
184         }
185 }
186
187 /**
188 * Wait till we are in VActive (anywhere in VActive)
189 */
190 static void dce110_timing_generator_v_wait_for_vactive(struct timing_generator *tg)
191 {
192         while (dce110_timing_generator_v_is_in_vertical_blank(tg)) {
193                 if (!dce110_timing_generator_v_is_counter_moving(tg)) {
194                         /* error - no point to wait if counter is not moving */
195                         break;
196                 }
197         }
198 }
199
200 static void dce110_timing_generator_v_wait_for_state(struct timing_generator *tg,
201         enum crtc_state state)
202 {
203         switch (state) {
204         case CRTC_STATE_VBLANK:
205                 dce110_timing_generator_v_wait_for_vblank(tg);
206                 break;
207
208         case CRTC_STATE_VACTIVE:
209                 dce110_timing_generator_v_wait_for_vactive(tg);
210                 break;
211
212         default:
213                 break;
214         }
215 }
216
217 static void dce110_timing_generator_v_program_blanking(
218         struct timing_generator *tg,
219         const struct dc_crtc_timing *timing)
220 {
221         uint32_t vsync_offset = timing->v_border_bottom +
222                         timing->v_front_porch;
223         uint32_t v_sync_start = timing->v_addressable + vsync_offset;
224
225         uint32_t hsync_offset = timing->h_border_right +
226                         timing->h_front_porch;
227         uint32_t h_sync_start = timing->h_addressable + hsync_offset;
228
229         struct dc_context *ctx = tg->ctx;
230         uint32_t value = 0;
231         uint32_t addr = 0;
232         uint32_t tmp = 0;
233
234         addr = mmCRTCV_H_TOTAL;
235         value = dm_read_reg(ctx, addr);
236         set_reg_field_value(
237                 value,
238                 timing->h_total - 1,
239                 CRTCV_H_TOTAL,
240                 CRTC_H_TOTAL);
241         dm_write_reg(ctx, addr, value);
242
243         addr = mmCRTCV_V_TOTAL;
244         value = dm_read_reg(ctx, addr);
245         set_reg_field_value(
246                 value,
247                 timing->v_total - 1,
248                 CRTCV_V_TOTAL,
249                 CRTC_V_TOTAL);
250         dm_write_reg(ctx, addr, value);
251
252         addr = mmCRTCV_H_BLANK_START_END;
253         value = dm_read_reg(ctx, addr);
254
255         tmp = timing->h_total -
256                 (h_sync_start + timing->h_border_left);
257
258         set_reg_field_value(
259                 value,
260                 tmp,
261                 CRTCV_H_BLANK_START_END,
262                 CRTC_H_BLANK_END);
263
264         tmp = tmp + timing->h_addressable +
265                 timing->h_border_left + timing->h_border_right;
266
267         set_reg_field_value(
268                 value,
269                 tmp,
270                 CRTCV_H_BLANK_START_END,
271                 CRTC_H_BLANK_START);
272
273         dm_write_reg(ctx, addr, value);
274
275         addr = mmCRTCV_V_BLANK_START_END;
276         value = dm_read_reg(ctx, addr);
277
278         tmp = timing->v_total - (v_sync_start + timing->v_border_top);
279
280         set_reg_field_value(
281                 value,
282                 tmp,
283                 CRTCV_V_BLANK_START_END,
284                 CRTC_V_BLANK_END);
285
286         tmp = tmp + timing->v_addressable + timing->v_border_top +
287                 timing->v_border_bottom;
288
289         set_reg_field_value(
290                 value,
291                 tmp,
292                 CRTCV_V_BLANK_START_END,
293                 CRTC_V_BLANK_START);
294
295         dm_write_reg(ctx, addr, value);
296
297         addr = mmCRTCV_H_SYNC_A;
298         value = 0;
299         set_reg_field_value(
300                 value,
301                 timing->h_sync_width,
302                 CRTCV_H_SYNC_A,
303                 CRTC_H_SYNC_A_END);
304         dm_write_reg(ctx, addr, value);
305
306         addr = mmCRTCV_H_SYNC_A_CNTL;
307         value = dm_read_reg(ctx, addr);
308         if (timing->flags.HSYNC_POSITIVE_POLARITY) {
309                 set_reg_field_value(
310                         value,
311                         0,
312                         CRTCV_H_SYNC_A_CNTL,
313                         CRTC_H_SYNC_A_POL);
314         } else {
315                 set_reg_field_value(
316                         value,
317                         1,
318                         CRTCV_H_SYNC_A_CNTL,
319                         CRTC_H_SYNC_A_POL);
320         }
321         dm_write_reg(ctx, addr, value);
322
323         addr = mmCRTCV_V_SYNC_A;
324         value = 0;
325         set_reg_field_value(
326                 value,
327                 timing->v_sync_width,
328                 CRTCV_V_SYNC_A,
329                 CRTC_V_SYNC_A_END);
330         dm_write_reg(ctx, addr, value);
331
332         addr = mmCRTCV_V_SYNC_A_CNTL;
333         value = dm_read_reg(ctx, addr);
334         if (timing->flags.VSYNC_POSITIVE_POLARITY) {
335                 set_reg_field_value(
336                         value,
337                         0,
338                         CRTCV_V_SYNC_A_CNTL,
339                         CRTC_V_SYNC_A_POL);
340         } else {
341                 set_reg_field_value(
342                         value,
343                         1,
344                         CRTCV_V_SYNC_A_CNTL,
345                         CRTC_V_SYNC_A_POL);
346         }
347         dm_write_reg(ctx, addr, value);
348
349         addr = mmCRTCV_INTERLACE_CONTROL;
350         value = dm_read_reg(ctx, addr);
351         set_reg_field_value(
352                 value,
353                 timing->flags.INTERLACE,
354                 CRTCV_INTERLACE_CONTROL,
355                 CRTC_INTERLACE_ENABLE);
356         dm_write_reg(ctx, addr, value);
357 }
358
359 static void dce110_timing_generator_v_enable_advanced_request(
360         struct timing_generator *tg,
361         bool enable,
362         const struct dc_crtc_timing *timing)
363 {
364         uint32_t addr = mmCRTCV_START_LINE_CONTROL;
365         uint32_t value = dm_read_reg(tg->ctx, addr);
366
367         if (enable) {
368                 if ((timing->v_sync_width + timing->v_front_porch) <= 3) {
369                         set_reg_field_value(
370                                 value,
371                                 3,
372                                 CRTCV_START_LINE_CONTROL,
373                                 CRTC_ADVANCED_START_LINE_POSITION);
374                 } else {
375                         set_reg_field_value(
376                                 value,
377                                 4,
378                                 CRTCV_START_LINE_CONTROL,
379                                 CRTC_ADVANCED_START_LINE_POSITION);
380                 }
381                 set_reg_field_value(
382                         value,
383                         0,
384                         CRTCV_START_LINE_CONTROL,
385                         CRTC_LEGACY_REQUESTOR_EN);
386         } else {
387                 set_reg_field_value(
388                         value,
389                         2,
390                         CRTCV_START_LINE_CONTROL,
391                         CRTC_ADVANCED_START_LINE_POSITION);
392                 set_reg_field_value(
393                         value,
394                         1,
395                         CRTCV_START_LINE_CONTROL,
396                         CRTC_LEGACY_REQUESTOR_EN);
397         }
398
399         dm_write_reg(tg->ctx, addr, value);
400 }
401
402 static void dce110_timing_generator_v_set_blank(struct timing_generator *tg,
403                 bool enable_blanking)
404 {
405         if (enable_blanking)
406                 dce110_timing_generator_v_blank_crtc(tg);
407         else
408                 dce110_timing_generator_v_unblank_crtc(tg);
409 }
410
411 static void dce110_timing_generator_v_program_timing(struct timing_generator *tg,
412         const struct dc_crtc_timing *timing,
413         bool use_vbios)
414 {
415         if (use_vbios)
416                 dce110_timing_generator_program_timing_generator(tg, timing);
417         else
418                 dce110_timing_generator_v_program_blanking(tg, timing);
419 }
420
421 static void dce110_timing_generator_v_program_blank_color(
422                 struct timing_generator *tg,
423                 const struct tg_color *black_color)
424 {
425         uint32_t addr = mmCRTCV_BLACK_COLOR;
426         uint32_t value = dm_read_reg(tg->ctx, addr);
427
428         set_reg_field_value(
429                 value,
430                 black_color->color_b_cb,
431                 CRTCV_BLACK_COLOR,
432                 CRTC_BLACK_COLOR_B_CB);
433         set_reg_field_value(
434                 value,
435                 black_color->color_g_y,
436                 CRTCV_BLACK_COLOR,
437                 CRTC_BLACK_COLOR_G_Y);
438         set_reg_field_value(
439                 value,
440                 black_color->color_r_cr,
441                 CRTCV_BLACK_COLOR,
442                 CRTC_BLACK_COLOR_R_CR);
443
444         dm_write_reg(tg->ctx, addr, value);
445 }
446
447 static void dce110_timing_generator_v_set_overscan_color_black(
448         struct timing_generator *tg,
449         const struct tg_color *color)
450 {
451         struct dc_context *ctx = tg->ctx;
452         uint32_t addr;
453         uint32_t value = 0;
454
455         set_reg_field_value(
456                         value,
457                         color->color_b_cb,
458                         CRTC_OVERSCAN_COLOR,
459                         CRTC_OVERSCAN_COLOR_BLUE);
460
461         set_reg_field_value(
462                         value,
463                         color->color_r_cr,
464                         CRTC_OVERSCAN_COLOR,
465                         CRTC_OVERSCAN_COLOR_RED);
466
467         set_reg_field_value(
468                         value,
469                         color->color_g_y,
470                         CRTC_OVERSCAN_COLOR,
471                         CRTC_OVERSCAN_COLOR_GREEN);
472
473         addr = mmCRTCV_OVERSCAN_COLOR;
474         dm_write_reg(ctx, addr, value);
475         addr = mmCRTCV_BLACK_COLOR;
476         dm_write_reg(ctx, addr, value);
477         /* This is desirable to have a constant DAC output voltage during the
478          * blank time that is higher than the 0 volt reference level that the
479          * DAC outputs when the NBLANK signal
480          * is asserted low, such as for output to an analog TV. */
481         addr = mmCRTCV_BLANK_DATA_COLOR;
482         dm_write_reg(ctx, addr, value);
483
484         /* TO DO we have to program EXT registers and we need to know LB DATA
485          * format because it is used when more 10 , i.e. 12 bits per color
486          *
487          * m_mmDxCRTC_OVERSCAN_COLOR_EXT
488          * m_mmDxCRTC_BLACK_COLOR_EXT
489          * m_mmDxCRTC_BLANK_DATA_COLOR_EXT
490          */
491 }
492
493 static void dce110_tg_v_program_blank_color(struct timing_generator *tg,
494                 const struct tg_color *black_color)
495 {
496         uint32_t addr = mmCRTCV_BLACK_COLOR;
497         uint32_t value = dm_read_reg(tg->ctx, addr);
498
499         set_reg_field_value(
500                 value,
501                 black_color->color_b_cb,
502                 CRTCV_BLACK_COLOR,
503                 CRTC_BLACK_COLOR_B_CB);
504         set_reg_field_value(
505                 value,
506                 black_color->color_g_y,
507                 CRTCV_BLACK_COLOR,
508                 CRTC_BLACK_COLOR_G_Y);
509         set_reg_field_value(
510                 value,
511                 black_color->color_r_cr,
512                 CRTCV_BLACK_COLOR,
513                 CRTC_BLACK_COLOR_R_CR);
514
515         dm_write_reg(tg->ctx, addr, value);
516
517         addr = mmCRTCV_BLANK_DATA_COLOR;
518         dm_write_reg(tg->ctx, addr, value);
519 }
520
521 static void dce110_timing_generator_v_set_overscan_color(struct timing_generator *tg,
522         const struct tg_color *overscan_color)
523 {
524         struct dc_context *ctx = tg->ctx;
525         uint32_t value = 0;
526         uint32_t addr;
527
528         set_reg_field_value(
529                 value,
530                 overscan_color->color_b_cb,
531                 CRTCV_OVERSCAN_COLOR,
532                 CRTC_OVERSCAN_COLOR_BLUE);
533
534         set_reg_field_value(
535                 value,
536                 overscan_color->color_g_y,
537                 CRTCV_OVERSCAN_COLOR,
538                 CRTC_OVERSCAN_COLOR_GREEN);
539
540         set_reg_field_value(
541                 value,
542                 overscan_color->color_r_cr,
543                 CRTCV_OVERSCAN_COLOR,
544                 CRTC_OVERSCAN_COLOR_RED);
545
546         addr = mmCRTCV_OVERSCAN_COLOR;
547         dm_write_reg(ctx, addr, value);
548 }
549
550 static void dce110_timing_generator_v_set_colors(struct timing_generator *tg,
551         const struct tg_color *blank_color,
552         const struct tg_color *overscan_color)
553 {
554         if (blank_color != NULL)
555                 dce110_tg_v_program_blank_color(tg, blank_color);
556         if (overscan_color != NULL)
557                 dce110_timing_generator_v_set_overscan_color(tg, overscan_color);
558 }
559
560 static void dce110_timing_generator_v_set_early_control(
561                 struct timing_generator *tg,
562                 uint32_t early_cntl)
563 {
564         uint32_t regval;
565         uint32_t address = mmCRTC_CONTROL;
566
567         regval = dm_read_reg(tg->ctx, address);
568         set_reg_field_value(regval, early_cntl,
569                         CRTCV_CONTROL, CRTC_HBLANK_EARLY_CONTROL);
570         dm_write_reg(tg->ctx, address, regval);
571 }
572
573 static uint32_t dce110_timing_generator_v_get_vblank_counter(struct timing_generator *tg)
574 {
575         uint32_t addr = mmCRTCV_STATUS_FRAME_COUNT;
576         uint32_t value = dm_read_reg(tg->ctx, addr);
577         uint32_t field = get_reg_field_value(
578                         value, CRTCV_STATUS_FRAME_COUNT, CRTC_FRAME_COUNT);
579
580         return field;
581 }
582
583 static bool dce110_timing_generator_v_did_triggered_reset_occur(
584         struct timing_generator *tg)
585 {
586         dm_logger_write(tg->ctx->logger, LOG_ERROR,
587                                         "Timing Sync not supported on underlay pipe\n");
588         return false;
589 }
590
591 static void dce110_timing_generator_v_setup_global_swap_lock(
592         struct timing_generator *tg,
593         const struct dcp_gsl_params *gsl_params)
594 {
595         dm_logger_write(tg->ctx->logger, LOG_ERROR,
596                                         "Timing Sync not supported on underlay pipe\n");
597         return;
598 }
599
600 static void dce110_timing_generator_v_enable_reset_trigger(
601         struct timing_generator *tg,
602         int source_tg_inst)
603 {
604         dm_logger_write(tg->ctx->logger, LOG_ERROR,
605                                         "Timing Sync not supported on underlay pipe\n");
606         return;
607 }
608
609 static void dce110_timing_generator_v_disable_reset_trigger(
610         struct timing_generator *tg)
611 {
612         dm_logger_write(tg->ctx->logger, LOG_ERROR,
613                                                 "Timing Sync not supported on underlay pipe\n");
614         return;
615 }
616
617 static void dce110_timing_generator_v_tear_down_global_swap_lock(
618         struct timing_generator *tg)
619 {
620         dm_logger_write(tg->ctx->logger, LOG_ERROR,
621                                                 "Timing Sync not supported on underlay pipe\n");
622         return;
623 }
624
625 static void dce110_timing_generator_v_disable_vga(
626         struct timing_generator *tg)
627 {
628         return;
629 }
630
631 static bool dce110_tg_v_is_blanked(struct timing_generator *tg)
632 {
633         /* Signal comes from the primary pipe, underlay is never blanked. */
634         return false;
635 }
636
637 /** ********************************************************************************************
638  *
639  * DCE11 Timing Generator Constructor / Destructor
640  *
641  *********************************************************************************************/
642 static const struct timing_generator_funcs dce110_tg_v_funcs = {
643                 .validate_timing = dce110_tg_validate_timing,
644                 .program_timing = dce110_timing_generator_v_program_timing,
645                 .enable_crtc = dce110_timing_generator_v_enable_crtc,
646                 .disable_crtc = dce110_timing_generator_v_disable_crtc,
647                 .is_counter_moving = dce110_timing_generator_v_is_counter_moving,
648                 .get_position = NULL, /* Not to be implemented for underlay*/
649                 .get_frame_count = dce110_timing_generator_v_get_vblank_counter,
650                 .set_early_control = dce110_timing_generator_v_set_early_control,
651                 .wait_for_state = dce110_timing_generator_v_wait_for_state,
652                 .set_blank = dce110_timing_generator_v_set_blank,
653                 .is_blanked = dce110_tg_v_is_blanked,
654                 .set_colors = dce110_timing_generator_v_set_colors,
655                 .set_overscan_blank_color =
656                                 dce110_timing_generator_v_set_overscan_color_black,
657                 .set_blank_color = dce110_timing_generator_v_program_blank_color,
658                 .disable_vga = dce110_timing_generator_v_disable_vga,
659                 .did_triggered_reset_occur =
660                                 dce110_timing_generator_v_did_triggered_reset_occur,
661                 .setup_global_swap_lock =
662                                 dce110_timing_generator_v_setup_global_swap_lock,
663                 .enable_reset_trigger = dce110_timing_generator_v_enable_reset_trigger,
664                 .disable_reset_trigger = dce110_timing_generator_v_disable_reset_trigger,
665                 .tear_down_global_swap_lock =
666                                 dce110_timing_generator_v_tear_down_global_swap_lock,
667                 .enable_advanced_request =
668                                 dce110_timing_generator_v_enable_advanced_request
669 };
670
671 void dce110_timing_generator_v_construct(
672         struct dce110_timing_generator *tg110,
673         struct dc_context *ctx)
674 {
675         tg110->controller_id = CONTROLLER_ID_UNDERLAY0;
676
677         tg110->base.funcs = &dce110_tg_v_funcs;
678
679         tg110->base.ctx = ctx;
680         tg110->base.bp = ctx->dc_bios;
681
682         tg110->max_h_total = CRTC_H_TOTAL__CRTC_H_TOTAL_MASK + 1;
683         tg110->max_v_total = CRTC_V_TOTAL__CRTC_V_TOTAL_MASK + 1;
684
685         tg110->min_h_blank = 56;
686         tg110->min_h_front_porch = 4;
687         tg110->min_h_back_porch = 4;
688 }