a519dbc5ecb65317b766ce92023a276303a23403
[linux-2.6-microblaze.git] / drivers / gpu / drm / amd / display / dc / core / dc_link_hwss.c
1 /* Copyright 2015 Advanced Micro Devices, Inc. */
2
3
4 #include "dm_services.h"
5 #include "dc.h"
6 #include "inc/core_types.h"
7 #include "include/ddc_service_types.h"
8 #include "include/i2caux_interface.h"
9 #include "link_hwss.h"
10 #include "hw_sequencer.h"
11 #include "dc_link_dp.h"
12 #include "dc_link_ddc.h"
13 #include "dm_helpers.h"
14 #include "dpcd_defs.h"
15 #ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
16 #include "dsc.h"
17 #endif
18 #if defined(CONFIG_DRM_AMD_DC_DCN2_0)
19 #include "resource.h"
20 #endif
21
22 enum dc_status core_link_read_dpcd(
23         struct dc_link *link,
24         uint32_t address,
25         uint8_t *data,
26         uint32_t size)
27 {
28         if (!link->aux_access_disabled &&
29                         !dm_helpers_dp_read_dpcd(link->ctx,
30                         link, address, data, size)) {
31                 return DC_ERROR_UNEXPECTED;
32         }
33
34         return DC_OK;
35 }
36
37 enum dc_status core_link_write_dpcd(
38         struct dc_link *link,
39         uint32_t address,
40         const uint8_t *data,
41         uint32_t size)
42 {
43         if (!link->aux_access_disabled &&
44                         !dm_helpers_dp_write_dpcd(link->ctx,
45                         link, address, data, size)) {
46                 return DC_ERROR_UNEXPECTED;
47         }
48
49         return DC_OK;
50 }
51
52 void dp_receiver_power_ctrl(struct dc_link *link, bool on)
53 {
54         uint8_t state;
55
56         state = on ? DP_POWER_STATE_D0 : DP_POWER_STATE_D3;
57
58         if (link->sync_lt_in_progress)
59                 return;
60
61         core_link_write_dpcd(link, DP_SET_POWER, &state,
62                         sizeof(state));
63 }
64
65 void dp_enable_link_phy(
66         struct dc_link *link,
67         enum signal_type signal,
68         enum clock_source_id clock_source,
69         const struct dc_link_settings *link_settings)
70 {
71         struct link_encoder *link_enc = link->link_enc;
72         struct dc  *core_dc = link->ctx->dc;
73         struct dmcu *dmcu = core_dc->res_pool->dmcu;
74
75         struct pipe_ctx *pipes =
76                         link->dc->current_state->res_ctx.pipe_ctx;
77         struct clock_source *dp_cs =
78                         link->dc->res_pool->dp_clock_source;
79         unsigned int i;
80         /* If the current pixel clock source is not DTO(happens after
81          * switching from HDMI passive dongle to DP on the same connector),
82          * switch the pixel clock source to DTO.
83          */
84         for (i = 0; i < MAX_PIPES; i++) {
85                 if (pipes[i].stream != NULL &&
86                         pipes[i].stream->link == link) {
87                         if (pipes[i].clock_source != NULL &&
88                                         pipes[i].clock_source->id != CLOCK_SOURCE_ID_DP_DTO) {
89                                 pipes[i].clock_source = dp_cs;
90                                 pipes[i].stream_res.pix_clk_params.requested_pix_clk_100hz =
91                                                 pipes[i].stream->timing.pix_clk_100hz;
92                                 pipes[i].clock_source->funcs->program_pix_clk(
93                                                         pipes[i].clock_source,
94                                                         &pipes[i].stream_res.pix_clk_params,
95                                                         &pipes[i].pll_settings);
96                         }
97                 }
98         }
99
100         if (dmcu != NULL && dmcu->funcs->lock_phy)
101                 dmcu->funcs->lock_phy(dmcu);
102
103         if (dc_is_dp_sst_signal(signal)) {
104                 link_enc->funcs->enable_dp_output(
105                                                 link_enc,
106                                                 link_settings,
107                                                 clock_source);
108         } else {
109                 link_enc->funcs->enable_dp_mst_output(
110                                                 link_enc,
111                                                 link_settings,
112                                                 clock_source);
113         }
114
115         if (dmcu != NULL && dmcu->funcs->unlock_phy)
116                 dmcu->funcs->unlock_phy(dmcu);
117
118         link->cur_link_settings = *link_settings;
119
120         dp_receiver_power_ctrl(link, true);
121 }
122
123 bool edp_receiver_ready_T9(struct dc_link *link)
124 {
125         unsigned int tries = 0;
126         unsigned char sinkstatus = 0;
127         unsigned char edpRev = 0;
128         enum dc_status result = DC_OK;
129         result = core_link_read_dpcd(link, DP_EDP_DPCD_REV, &edpRev, sizeof(edpRev));
130         if (edpRev < DP_EDP_12)
131                 return true;
132         /* start from eDP version 1.2, SINK_STAUS indicate the sink is ready.*/
133         do {
134                 sinkstatus = 1;
135                 result = core_link_read_dpcd(link, DP_SINK_STATUS, &sinkstatus, sizeof(sinkstatus));
136                 if (sinkstatus == 0)
137                         break;
138                 if (result != DC_OK)
139                         break;
140                 udelay(100); //MAx T9
141         } while (++tries < 50);
142
143         if (link->local_sink->edid_caps.panel_patch.extra_delay_backlight_off > 0)
144                 udelay(link->local_sink->edid_caps.panel_patch.extra_delay_backlight_off * 1000);
145
146         return result;
147 }
148 bool edp_receiver_ready_T7(struct dc_link *link)
149 {
150         unsigned int tries = 0;
151         unsigned char sinkstatus = 0;
152         unsigned char edpRev = 0;
153         enum dc_status result = DC_OK;
154
155         result = core_link_read_dpcd(link, DP_EDP_DPCD_REV, &edpRev, sizeof(edpRev));
156         if (result == DC_OK && edpRev < DP_EDP_12)
157                 return true;
158         /* start from eDP version 1.2, SINK_STAUS indicate the sink is ready.*/
159         do {
160                 sinkstatus = 0;
161                 result = core_link_read_dpcd(link, DP_SINK_STATUS, &sinkstatus, sizeof(sinkstatus));
162                 if (sinkstatus == 1)
163                         break;
164                 if (result != DC_OK)
165                         break;
166                 udelay(25); //MAx T7 is 50ms
167         } while (++tries < 300);
168
169         if (link->local_sink->edid_caps.panel_patch.extra_t7_ms > 0)
170                 udelay(link->local_sink->edid_caps.panel_patch.extra_t7_ms * 1000);
171
172         return result;
173 }
174
175 void dp_disable_link_phy(struct dc_link *link, enum signal_type signal)
176 {
177         struct dc  *core_dc = link->ctx->dc;
178         struct dmcu *dmcu = core_dc->res_pool->dmcu;
179
180         if (!link->wa_flags.dp_keep_receiver_powered)
181                 dp_receiver_power_ctrl(link, false);
182
183         if (signal == SIGNAL_TYPE_EDP) {
184                 link->link_enc->funcs->disable_output(link->link_enc, signal);
185                 link->dc->hwss.edp_power_control(link, false);
186         } else {
187                 if (dmcu != NULL && dmcu->funcs->lock_phy)
188                         dmcu->funcs->lock_phy(dmcu);
189
190                 link->link_enc->funcs->disable_output(link->link_enc, signal);
191
192                 if (dmcu != NULL && dmcu->funcs->unlock_phy)
193                         dmcu->funcs->unlock_phy(dmcu);
194         }
195
196         /* Clear current link setting.*/
197         memset(&link->cur_link_settings, 0,
198                         sizeof(link->cur_link_settings));
199 }
200
201 void dp_disable_link_phy_mst(struct dc_link *link, enum signal_type signal)
202 {
203         /* MST disable link only when no stream use the link */
204         if (link->mst_stream_alloc_table.stream_count > 0)
205                 return;
206
207         dp_disable_link_phy(link, signal);
208
209         /* set the sink to SST mode after disabling the link */
210         dp_enable_mst_on_sink(link, false);
211 }
212
213 bool dp_set_hw_training_pattern(
214         struct dc_link *link,
215         enum dc_dp_training_pattern pattern)
216 {
217         enum dp_test_pattern test_pattern = DP_TEST_PATTERN_UNSUPPORTED;
218
219         switch (pattern) {
220         case DP_TRAINING_PATTERN_SEQUENCE_1:
221                 test_pattern = DP_TEST_PATTERN_TRAINING_PATTERN1;
222                 break;
223         case DP_TRAINING_PATTERN_SEQUENCE_2:
224                 test_pattern = DP_TEST_PATTERN_TRAINING_PATTERN2;
225                 break;
226         case DP_TRAINING_PATTERN_SEQUENCE_3:
227                 test_pattern = DP_TEST_PATTERN_TRAINING_PATTERN3;
228                 break;
229         case DP_TRAINING_PATTERN_SEQUENCE_4:
230                 test_pattern = DP_TEST_PATTERN_TRAINING_PATTERN4;
231                 break;
232         default:
233                 break;
234         }
235
236         dp_set_hw_test_pattern(link, test_pattern, NULL, 0);
237
238         return true;
239 }
240
241 void dp_set_hw_lane_settings(
242         struct dc_link *link,
243         const struct link_training_settings *link_settings)
244 {
245         struct link_encoder *encoder = link->link_enc;
246
247         /* call Encoder to set lane settings */
248         encoder->funcs->dp_set_lane_settings(encoder, link_settings);
249 }
250
251 void dp_set_hw_test_pattern(
252         struct dc_link *link,
253         enum dp_test_pattern test_pattern,
254         uint8_t *custom_pattern,
255         uint32_t custom_pattern_size)
256 {
257         struct encoder_set_dp_phy_pattern_param pattern_param = {0};
258         struct link_encoder *encoder = link->link_enc;
259
260         pattern_param.dp_phy_pattern = test_pattern;
261         pattern_param.custom_pattern = custom_pattern;
262         pattern_param.custom_pattern_size = custom_pattern_size;
263         pattern_param.dp_panel_mode = dp_get_panel_mode(link);
264
265         encoder->funcs->dp_set_phy_pattern(encoder, &pattern_param);
266 }
267
268 void dp_retrain_link_dp_test(struct dc_link *link,
269                         struct dc_link_settings *link_setting,
270                         bool skip_video_pattern)
271 {
272         struct pipe_ctx *pipes =
273                         &link->dc->current_state->res_ctx.pipe_ctx[0];
274         unsigned int i;
275
276         for (i = 0; i < MAX_PIPES; i++) {
277                 if (pipes[i].stream != NULL &&
278                         !pipes[i].top_pipe && !pipes[i].prev_odm_pipe &&
279                         pipes[i].stream->link != NULL &&
280                         pipes[i].stream_res.stream_enc != NULL &&
281                         pipes[i].stream->link == link) {
282                         udelay(100);
283
284                         pipes[i].stream_res.stream_enc->funcs->dp_blank(
285                                         pipes[i].stream_res.stream_enc);
286
287                         /* disable any test pattern that might be active */
288                         dp_set_hw_test_pattern(link,
289                                         DP_TEST_PATTERN_VIDEO_MODE, NULL, 0);
290
291                         dp_receiver_power_ctrl(link, false);
292
293                         link->dc->hwss.disable_stream(&pipes[i]);
294                         if ((&pipes[i])->stream_res.audio && !link->dc->debug.az_endpoint_mute_only)
295                                 (&pipes[i])->stream_res.audio->funcs->az_disable((&pipes[i])->stream_res.audio);
296
297                         link->link_enc->funcs->disable_output(
298                                         link->link_enc,
299                                         SIGNAL_TYPE_DISPLAY_PORT);
300
301                         /* Clear current link setting. */
302                         memset(&link->cur_link_settings, 0,
303                                 sizeof(link->cur_link_settings));
304
305                         link->link_enc->funcs->enable_dp_output(
306                                                 link->link_enc,
307                                                 link_setting,
308                                                 pipes[i].clock_source->id);
309                         link->cur_link_settings = *link_setting;
310
311                         dp_receiver_power_ctrl(link, true);
312
313                         perform_link_training_with_retries(
314                                         link,
315                                         link_setting,
316                                         skip_video_pattern,
317                                         LINK_TRAINING_ATTEMPTS);
318
319
320                         link->dc->hwss.enable_stream(&pipes[i]);
321
322                         link->dc->hwss.unblank_stream(&pipes[i],
323                                         link_setting);
324
325                         if (pipes[i].stream_res.audio) {
326                                 /* notify audio driver for
327                                  * audio modes of monitor */
328                                 pipes[i].stream_res.audio->funcs->az_enable(
329                                                 pipes[i].stream_res.audio);
330
331                                 /* un-mute audio */
332                                 /* TODO: audio should be per stream rather than
333                                  * per link */
334                                 pipes[i].stream_res.stream_enc->funcs->
335                                 audio_mute_control(
336                                         pipes[i].stream_res.stream_enc, false);
337                         }
338                 }
339         }
340 }
341
342 #ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
343 #define DC_LOGGER \
344         dsc->ctx->logger
345 static void dsc_optc_config_log(struct display_stream_compressor *dsc,
346                 struct dsc_optc_config *config)
347 {
348         uint32_t precision = 1 << 28;
349         uint32_t bytes_per_pixel_int = config->bytes_per_pixel / precision;
350         uint32_t bytes_per_pixel_mod = config->bytes_per_pixel % precision;
351         uint64_t ll_bytes_per_pix_fraq = bytes_per_pixel_mod;
352
353         /* 7 fractional digits decimal precision for bytes per pixel is enough because DSC
354          * bits per pixel precision is 1/16th of a pixel, which means bytes per pixel precision is
355          * 1/16/8 = 1/128 of a byte, or 0.0078125 decimal
356          */
357         ll_bytes_per_pix_fraq *= 10000000;
358         ll_bytes_per_pix_fraq /= precision;
359
360         DC_LOG_DSC("\tbytes_per_pixel 0x%08x (%d.%07d)",
361                         config->bytes_per_pixel, bytes_per_pixel_int, (uint32_t)ll_bytes_per_pix_fraq);
362         DC_LOG_DSC("\tis_pixel_format_444 %d", config->is_pixel_format_444);
363         DC_LOG_DSC("\tslice_width %d", config->slice_width);
364 }
365
366 static bool dp_set_dsc_on_rx(struct pipe_ctx *pipe_ctx, bool enable)
367 {
368         struct dc *core_dc = pipe_ctx->stream->ctx->dc;
369         struct dc_stream_state *stream = pipe_ctx->stream;
370         bool result = false;
371
372         if (IS_FPGA_MAXIMUS_DC(core_dc->ctx->dce_environment))
373                 result = true;
374         else
375                 result = dm_helpers_dp_write_dsc_enable(core_dc->ctx, stream, enable);
376         return result;
377 }
378
379 /* The stream with these settings can be sent (unblanked) only after DSC was enabled on RX first,
380  * i.e. after dp_enable_dsc_on_rx() had been called
381  */
382 void dp_set_dsc_on_stream(struct pipe_ctx *pipe_ctx, bool enable)
383 {
384         struct display_stream_compressor *dsc = pipe_ctx->stream_res.dsc;
385         struct dc *core_dc = pipe_ctx->stream->ctx->dc;
386         struct dc_stream_state *stream = pipe_ctx->stream;
387         struct pipe_ctx *odm_pipe;
388         int opp_cnt = 1;
389
390         for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe)
391                 opp_cnt++;
392
393         if (enable) {
394                 struct dsc_config dsc_cfg;
395                 struct dsc_optc_config dsc_optc_cfg;
396                 enum optc_dsc_mode optc_dsc_mode;
397
398                 /* Enable DSC hw block */
399                 dsc_cfg.pic_width = (stream->timing.h_addressable + stream->timing.h_border_left + stream->timing.h_border_right) / opp_cnt;
400                 dsc_cfg.pic_height = stream->timing.v_addressable + stream->timing.v_border_top + stream->timing.v_border_bottom;
401                 dsc_cfg.pixel_encoding = stream->timing.pixel_encoding;
402                 dsc_cfg.color_depth = stream->timing.display_color_depth;
403                 dsc_cfg.dc_dsc_cfg = stream->timing.dsc_cfg;
404                 ASSERT(dsc_cfg.dc_dsc_cfg.num_slices_h % opp_cnt == 0);
405                 dsc_cfg.dc_dsc_cfg.num_slices_h /= opp_cnt;
406
407                 dsc->funcs->dsc_set_config(dsc, &dsc_cfg, &dsc_optc_cfg);
408                 dsc->funcs->dsc_enable(dsc, pipe_ctx->stream_res.opp->inst);
409                 for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) {
410                         struct display_stream_compressor *odm_dsc = odm_pipe->stream_res.dsc;
411
412                         odm_dsc->funcs->dsc_set_config(odm_dsc, &dsc_cfg, &dsc_optc_cfg);
413                         odm_dsc->funcs->dsc_enable(odm_dsc, odm_pipe->stream_res.opp->inst);
414                 }
415                 dsc_cfg.dc_dsc_cfg.num_slices_h *= opp_cnt;
416                 dsc_cfg.pic_width *= opp_cnt;
417
418                 optc_dsc_mode = dsc_optc_cfg.is_pixel_format_444 ? OPTC_DSC_ENABLED_444 : OPTC_DSC_ENABLED_NATIVE_SUBSAMPLED;
419
420                 /* Enable DSC in encoder */
421                 if (dc_is_dp_signal(stream->signal) && !IS_FPGA_MAXIMUS_DC(core_dc->ctx->dce_environment)) {
422                         DC_LOG_DSC("Setting stream encoder DSC config for engine %d:", (int)pipe_ctx->stream_res.stream_enc->id);
423                         dsc_optc_config_log(dsc, &dsc_optc_cfg);
424                         pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_config(pipe_ctx->stream_res.stream_enc,
425                                                                         optc_dsc_mode,
426                                                                         dsc_optc_cfg.bytes_per_pixel,
427                                                                         dsc_optc_cfg.slice_width);
428
429                         /* PPS SDP is set elsewhere because it has to be done after DIG FE is connected to DIG BE */
430                 }
431
432                 /* Enable DSC in OPTC */
433                 DC_LOG_DSC("Setting optc DSC config for tg instance %d:", pipe_ctx->stream_res.tg->inst);
434                 dsc_optc_config_log(dsc, &dsc_optc_cfg);
435                 pipe_ctx->stream_res.tg->funcs->set_dsc_config(pipe_ctx->stream_res.tg,
436                                                         optc_dsc_mode,
437                                                         dsc_optc_cfg.bytes_per_pixel,
438                                                         dsc_optc_cfg.slice_width);
439         } else {
440                 /* disable DSC in OPTC */
441                 pipe_ctx->stream_res.tg->funcs->set_dsc_config(
442                                 pipe_ctx->stream_res.tg,
443                                 OPTC_DSC_DISABLED, 0, 0);
444
445                 /* disable DSC in stream encoder */
446                 if (dc_is_dp_signal(stream->signal) && !IS_FPGA_MAXIMUS_DC(core_dc->ctx->dce_environment)) {
447                         pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_config(
448                                         pipe_ctx->stream_res.stream_enc,
449                                         OPTC_DSC_DISABLED, 0, 0);
450
451                         pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_pps_info_packet(
452                                         pipe_ctx->stream_res.stream_enc, false, NULL);
453                 }
454
455                 /* disable DSC block */
456                 pipe_ctx->stream_res.dsc->funcs->dsc_disable(pipe_ctx->stream_res.dsc);
457                 for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe)
458                         odm_pipe->stream_res.dsc->funcs->dsc_disable(odm_pipe->stream_res.dsc);
459         }
460 }
461
462 bool dp_set_dsc_enable(struct pipe_ctx *pipe_ctx, bool enable)
463 {
464         struct display_stream_compressor *dsc = pipe_ctx->stream_res.dsc;
465         bool result = false;
466
467         if (!pipe_ctx->stream->timing.flags.DSC)
468                 goto out;
469         if (!dsc)
470                 goto out;
471
472         if (enable) {
473                 if (dp_set_dsc_on_rx(pipe_ctx, true)) {
474                         dp_set_dsc_on_stream(pipe_ctx, true);
475                         result = true;
476                 }
477         } else {
478                 dp_set_dsc_on_rx(pipe_ctx, false);
479                 dp_set_dsc_on_stream(pipe_ctx, false);
480                 result = true;
481         }
482 out:
483         return result;
484 }
485
486 bool dp_set_dsc_pps_sdp(struct pipe_ctx *pipe_ctx, bool enable)
487 {
488         struct display_stream_compressor *dsc = pipe_ctx->stream_res.dsc;
489         struct dc *core_dc = pipe_ctx->stream->ctx->dc;
490         struct dc_stream_state *stream = pipe_ctx->stream;
491
492         if (!pipe_ctx->stream->timing.flags.DSC || !dsc)
493                 return false;
494
495         if (enable) {
496                 struct dsc_config dsc_cfg;
497                 uint8_t dsc_packed_pps[128];
498
499                 /* Enable DSC hw block */
500                 dsc_cfg.pic_width = stream->timing.h_addressable + stream->timing.h_border_left + stream->timing.h_border_right;
501                 dsc_cfg.pic_height = stream->timing.v_addressable + stream->timing.v_border_top + stream->timing.v_border_bottom;
502                 dsc_cfg.pixel_encoding = stream->timing.pixel_encoding;
503                 dsc_cfg.color_depth = stream->timing.display_color_depth;
504                 dsc_cfg.dc_dsc_cfg = stream->timing.dsc_cfg;
505
506                 DC_LOG_DSC(" ");
507                 dsc->funcs->dsc_get_packed_pps(dsc, &dsc_cfg, &dsc_packed_pps[0]);
508                 if (dc_is_dp_signal(stream->signal) && !IS_FPGA_MAXIMUS_DC(core_dc->ctx->dce_environment)) {
509                         DC_LOG_DSC("Setting stream encoder DSC PPS SDP for engine %d\n", (int)pipe_ctx->stream_res.stream_enc->id);
510                         pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_pps_info_packet(
511                                                                         pipe_ctx->stream_res.stream_enc,
512                                                                         true,
513                                                                         &dsc_packed_pps[0]);
514                 }
515         } else {
516                 /* disable DSC PPS in stream encoder */
517                 if (dc_is_dp_signal(stream->signal) && !IS_FPGA_MAXIMUS_DC(core_dc->ctx->dce_environment)) {
518                         pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_pps_info_packet(
519                                                 pipe_ctx->stream_res.stream_enc, false, NULL);
520                 }
521         }
522
523         return true;
524 }
525
526
527 bool dp_update_dsc_config(struct pipe_ctx *pipe_ctx)
528 {
529         struct display_stream_compressor *dsc = pipe_ctx->stream_res.dsc;
530
531         if (!pipe_ctx->stream->timing.flags.DSC)
532                 return false;
533         if (!dsc)
534                 return false;
535
536         dp_set_dsc_on_stream(pipe_ctx, true);
537         dp_set_dsc_pps_sdp(pipe_ctx, true);
538         return true;
539 }
540 #endif
541