.. | .. |
---|
28 | 28 | #include <linux/version.h> |
---|
29 | 29 | #include <linux/i2c.h> |
---|
30 | 30 | |
---|
31 | | -#include <drm/drmP.h> |
---|
32 | | -#include <drm/drm_crtc_helper.h> |
---|
| 31 | +#include <drm/drm_probe_helper.h> |
---|
33 | 32 | #include <drm/amdgpu_drm.h> |
---|
34 | 33 | #include <drm/drm_edid.h> |
---|
35 | 34 | |
---|
.. | .. |
---|
38 | 37 | #include "dc.h" |
---|
39 | 38 | #include "amdgpu_dm.h" |
---|
40 | 39 | #include "amdgpu_dm_irq.h" |
---|
| 40 | +#include "amdgpu_dm_mst_types.h" |
---|
41 | 41 | |
---|
42 | 42 | #include "dm_helpers.h" |
---|
43 | 43 | |
---|
.. | .. |
---|
98 | 98 | (struct edid *) edid->raw_edid); |
---|
99 | 99 | |
---|
100 | 100 | sad_count = drm_edid_to_sad((struct edid *) edid->raw_edid, &sads); |
---|
101 | | - if (sad_count <= 0) { |
---|
102 | | - DRM_INFO("SADs count is: %d, don't need to read it\n", |
---|
103 | | - sad_count); |
---|
| 101 | + if (sad_count <= 0) |
---|
104 | 102 | return result; |
---|
105 | | - } |
---|
106 | 103 | |
---|
107 | 104 | edid_caps->audio_mode_count = sad_count < DC_MAX_AUDIO_DESC_COUNT ? sad_count : DC_MAX_AUDIO_DESC_COUNT; |
---|
108 | 105 | for (i = 0; i < edid_caps->audio_mode_count; ++i) { |
---|
.. | .. |
---|
184 | 181 | bool enable) |
---|
185 | 182 | { |
---|
186 | 183 | struct amdgpu_dm_connector *aconnector; |
---|
| 184 | + struct dm_connector_state *dm_conn_state; |
---|
187 | 185 | struct drm_dp_mst_topology_mgr *mst_mgr; |
---|
188 | 186 | struct drm_dp_mst_port *mst_port; |
---|
189 | | - int slots = 0; |
---|
190 | 187 | bool ret; |
---|
191 | | - int clock; |
---|
192 | | - int bpp = 0; |
---|
193 | | - int pbn = 0; |
---|
194 | 188 | |
---|
195 | | - aconnector = stream->sink->priv; |
---|
| 189 | + aconnector = (struct amdgpu_dm_connector *)stream->dm_stream_context; |
---|
| 190 | + /* Accessing the connector state is required for vcpi_slots allocation |
---|
| 191 | + * and directly relies on behaviour in commit check |
---|
| 192 | + * that blocks before commit guaranteeing that the state |
---|
| 193 | + * is not gonna be swapped while still in use in commit tail */ |
---|
196 | 194 | |
---|
197 | 195 | if (!aconnector || !aconnector->mst_port) |
---|
198 | 196 | return false; |
---|
| 197 | + |
---|
| 198 | + dm_conn_state = to_dm_connector_state(aconnector->base.state); |
---|
199 | 199 | |
---|
200 | 200 | mst_mgr = &aconnector->mst_port->mst_mgr; |
---|
201 | 201 | |
---|
.. | .. |
---|
205 | 205 | mst_port = aconnector->port; |
---|
206 | 206 | |
---|
207 | 207 | if (enable) { |
---|
208 | | - clock = stream->timing.pix_clk_khz; |
---|
209 | 208 | |
---|
210 | | - switch (stream->timing.display_color_depth) { |
---|
211 | | - |
---|
212 | | - case COLOR_DEPTH_666: |
---|
213 | | - bpp = 6; |
---|
214 | | - break; |
---|
215 | | - case COLOR_DEPTH_888: |
---|
216 | | - bpp = 8; |
---|
217 | | - break; |
---|
218 | | - case COLOR_DEPTH_101010: |
---|
219 | | - bpp = 10; |
---|
220 | | - break; |
---|
221 | | - case COLOR_DEPTH_121212: |
---|
222 | | - bpp = 12; |
---|
223 | | - break; |
---|
224 | | - case COLOR_DEPTH_141414: |
---|
225 | | - bpp = 14; |
---|
226 | | - break; |
---|
227 | | - case COLOR_DEPTH_161616: |
---|
228 | | - bpp = 16; |
---|
229 | | - break; |
---|
230 | | - default: |
---|
231 | | - ASSERT(bpp != 0); |
---|
232 | | - break; |
---|
233 | | - } |
---|
234 | | - |
---|
235 | | - bpp = bpp * 3; |
---|
236 | | - |
---|
237 | | - /* TODO need to know link rate */ |
---|
238 | | - |
---|
239 | | - pbn = drm_dp_calc_pbn_mode(clock, bpp); |
---|
240 | | - |
---|
241 | | - slots = drm_dp_find_vcpi_slots(mst_mgr, pbn); |
---|
242 | | - ret = drm_dp_mst_allocate_vcpi(mst_mgr, mst_port, pbn, slots); |
---|
243 | | - |
---|
| 209 | + ret = drm_dp_mst_allocate_vcpi(mst_mgr, mst_port, |
---|
| 210 | + dm_conn_state->pbn, |
---|
| 211 | + dm_conn_state->vcpi_slots); |
---|
244 | 212 | if (!ret) |
---|
245 | 213 | return false; |
---|
246 | 214 | |
---|
.. | .. |
---|
261 | 229 | return true; |
---|
262 | 230 | } |
---|
263 | 231 | |
---|
| 232 | +/* |
---|
| 233 | + * poll pending down reply |
---|
| 234 | + */ |
---|
| 235 | +void dm_helpers_dp_mst_poll_pending_down_reply( |
---|
| 236 | + struct dc_context *ctx, |
---|
| 237 | + const struct dc_link *link) |
---|
| 238 | +{} |
---|
264 | 239 | |
---|
265 | 240 | /* |
---|
266 | 241 | * Clear payload allocation table before enable MST DP link. |
---|
.. | .. |
---|
274 | 249 | * Polls for ACT (allocation change trigger) handled and sends |
---|
275 | 250 | * ALLOCATE_PAYLOAD message. |
---|
276 | 251 | */ |
---|
277 | | -bool dm_helpers_dp_mst_poll_for_allocation_change_trigger( |
---|
| 252 | +enum act_return_status dm_helpers_dp_mst_poll_for_allocation_change_trigger( |
---|
278 | 253 | struct dc_context *ctx, |
---|
279 | 254 | const struct dc_stream_state *stream) |
---|
280 | 255 | { |
---|
.. | .. |
---|
282 | 257 | struct drm_dp_mst_topology_mgr *mst_mgr; |
---|
283 | 258 | int ret; |
---|
284 | 259 | |
---|
285 | | - aconnector = stream->sink->priv; |
---|
| 260 | + aconnector = (struct amdgpu_dm_connector *)stream->dm_stream_context; |
---|
286 | 261 | |
---|
287 | 262 | if (!aconnector || !aconnector->mst_port) |
---|
288 | | - return false; |
---|
| 263 | + return ACT_FAILED; |
---|
289 | 264 | |
---|
290 | 265 | mst_mgr = &aconnector->mst_port->mst_mgr; |
---|
291 | 266 | |
---|
292 | 267 | if (!mst_mgr->mst_state) |
---|
293 | | - return false; |
---|
| 268 | + return ACT_FAILED; |
---|
294 | 269 | |
---|
295 | 270 | ret = drm_dp_check_act_status(mst_mgr); |
---|
296 | 271 | |
---|
297 | 272 | if (ret) |
---|
298 | | - return false; |
---|
| 273 | + return ACT_FAILED; |
---|
299 | 274 | |
---|
300 | | - return true; |
---|
| 275 | + return ACT_SUCCESS; |
---|
301 | 276 | } |
---|
302 | 277 | |
---|
303 | 278 | bool dm_helpers_dp_mst_send_payload_allocation( |
---|
.. | .. |
---|
309 | 284 | struct drm_dp_mst_topology_mgr *mst_mgr; |
---|
310 | 285 | struct drm_dp_mst_port *mst_port; |
---|
311 | 286 | |
---|
312 | | - aconnector = stream->sink->priv; |
---|
| 287 | + aconnector = (struct amdgpu_dm_connector *)stream->dm_stream_context; |
---|
313 | 288 | |
---|
314 | 289 | if (!aconnector || !aconnector->mst_port) |
---|
315 | 290 | return false; |
---|
.. | .. |
---|
330 | 305 | return true; |
---|
331 | 306 | } |
---|
332 | 307 | |
---|
333 | | -void dm_dtn_log_begin(struct dc_context *ctx) |
---|
334 | | -{} |
---|
| 308 | +void dm_dtn_log_begin(struct dc_context *ctx, |
---|
| 309 | + struct dc_log_buffer_ctx *log_ctx) |
---|
| 310 | +{ |
---|
| 311 | + static const char msg[] = "[dtn begin]\n"; |
---|
| 312 | + |
---|
| 313 | + if (!log_ctx) { |
---|
| 314 | + pr_info("%s", msg); |
---|
| 315 | + return; |
---|
| 316 | + } |
---|
| 317 | + |
---|
| 318 | + dm_dtn_log_append_v(ctx, log_ctx, "%s", msg); |
---|
| 319 | +} |
---|
335 | 320 | |
---|
336 | 321 | void dm_dtn_log_append_v(struct dc_context *ctx, |
---|
337 | | - const char *pMsg, ...) |
---|
338 | | -{} |
---|
| 322 | + struct dc_log_buffer_ctx *log_ctx, |
---|
| 323 | + const char *msg, ...) |
---|
| 324 | +{ |
---|
| 325 | + va_list args; |
---|
| 326 | + size_t total; |
---|
| 327 | + int n; |
---|
339 | 328 | |
---|
340 | | -void dm_dtn_log_end(struct dc_context *ctx) |
---|
341 | | -{} |
---|
| 329 | + if (!log_ctx) { |
---|
| 330 | + /* No context, redirect to dmesg. */ |
---|
| 331 | + struct va_format vaf; |
---|
| 332 | + |
---|
| 333 | + vaf.fmt = msg; |
---|
| 334 | + vaf.va = &args; |
---|
| 335 | + |
---|
| 336 | + va_start(args, msg); |
---|
| 337 | + pr_info("%pV", &vaf); |
---|
| 338 | + va_end(args); |
---|
| 339 | + |
---|
| 340 | + return; |
---|
| 341 | + } |
---|
| 342 | + |
---|
| 343 | + /* Measure the output. */ |
---|
| 344 | + va_start(args, msg); |
---|
| 345 | + n = vsnprintf(NULL, 0, msg, args); |
---|
| 346 | + va_end(args); |
---|
| 347 | + |
---|
| 348 | + if (n <= 0) |
---|
| 349 | + return; |
---|
| 350 | + |
---|
| 351 | + /* Reallocate the string buffer as needed. */ |
---|
| 352 | + total = log_ctx->pos + n + 1; |
---|
| 353 | + |
---|
| 354 | + if (total > log_ctx->size) { |
---|
| 355 | + char *buf = (char *)kvcalloc(total, sizeof(char), GFP_KERNEL); |
---|
| 356 | + |
---|
| 357 | + if (buf) { |
---|
| 358 | + memcpy(buf, log_ctx->buf, log_ctx->pos); |
---|
| 359 | + kfree(log_ctx->buf); |
---|
| 360 | + |
---|
| 361 | + log_ctx->buf = buf; |
---|
| 362 | + log_ctx->size = total; |
---|
| 363 | + } |
---|
| 364 | + } |
---|
| 365 | + |
---|
| 366 | + if (!log_ctx->buf) |
---|
| 367 | + return; |
---|
| 368 | + |
---|
| 369 | + /* Write the formatted string to the log buffer. */ |
---|
| 370 | + va_start(args, msg); |
---|
| 371 | + n = vscnprintf( |
---|
| 372 | + log_ctx->buf + log_ctx->pos, |
---|
| 373 | + log_ctx->size - log_ctx->pos, |
---|
| 374 | + msg, |
---|
| 375 | + args); |
---|
| 376 | + va_end(args); |
---|
| 377 | + |
---|
| 378 | + if (n > 0) |
---|
| 379 | + log_ctx->pos += n; |
---|
| 380 | +} |
---|
| 381 | + |
---|
| 382 | +void dm_dtn_log_end(struct dc_context *ctx, |
---|
| 383 | + struct dc_log_buffer_ctx *log_ctx) |
---|
| 384 | +{ |
---|
| 385 | + static const char msg[] = "[dtn end]\n"; |
---|
| 386 | + |
---|
| 387 | + if (!log_ctx) { |
---|
| 388 | + pr_info("%s", msg); |
---|
| 389 | + return; |
---|
| 390 | + } |
---|
| 391 | + |
---|
| 392 | + dm_dtn_log_append_v(ctx, log_ctx, "%s", msg); |
---|
| 393 | +} |
---|
342 | 394 | |
---|
343 | 395 | bool dm_helpers_dp_mst_start_top_mgr( |
---|
344 | 396 | struct dc_context *ctx, |
---|
.. | .. |
---|
348 | 400 | struct amdgpu_dm_connector *aconnector = link->priv; |
---|
349 | 401 | |
---|
350 | 402 | if (!aconnector) { |
---|
351 | | - DRM_ERROR("Failed to found connector for link!"); |
---|
352 | | - return false; |
---|
| 403 | + DRM_ERROR("Failed to find connector for link!"); |
---|
| 404 | + return false; |
---|
353 | 405 | } |
---|
354 | 406 | |
---|
355 | 407 | if (boot) { |
---|
.. | .. |
---|
371 | 423 | struct amdgpu_dm_connector *aconnector = link->priv; |
---|
372 | 424 | |
---|
373 | 425 | if (!aconnector) { |
---|
374 | | - DRM_ERROR("Failed to found connector for link!"); |
---|
375 | | - return; |
---|
| 426 | + DRM_ERROR("Failed to find connector for link!"); |
---|
| 427 | + return; |
---|
376 | 428 | } |
---|
377 | 429 | |
---|
378 | 430 | DRM_INFO("DM_MST: stopping TM on aconnector: %p [id: %d]\n", |
---|
.. | .. |
---|
393 | 445 | struct amdgpu_dm_connector *aconnector = link->priv; |
---|
394 | 446 | |
---|
395 | 447 | if (!aconnector) { |
---|
396 | | - DRM_ERROR("Failed to found connector for link!"); |
---|
| 448 | + DC_LOG_DC("Failed to find connector for link!\n"); |
---|
397 | 449 | return false; |
---|
398 | 450 | } |
---|
399 | 451 | |
---|
.. | .. |
---|
411 | 463 | struct amdgpu_dm_connector *aconnector = link->priv; |
---|
412 | 464 | |
---|
413 | 465 | if (!aconnector) { |
---|
414 | | - DRM_ERROR("Failed to found connector for link!"); |
---|
| 466 | + DRM_ERROR("Failed to find connector for link!"); |
---|
415 | 467 | return false; |
---|
416 | 468 | } |
---|
417 | 469 | |
---|
.. | .. |
---|
431 | 483 | bool result; |
---|
432 | 484 | |
---|
433 | 485 | if (!aconnector) { |
---|
434 | | - DRM_ERROR("Failed to found connector for link!"); |
---|
| 486 | + DRM_ERROR("Failed to find connector for link!"); |
---|
435 | 487 | return false; |
---|
436 | 488 | } |
---|
437 | 489 | |
---|
.. | .. |
---|
453 | 505 | |
---|
454 | 506 | return result; |
---|
455 | 507 | } |
---|
| 508 | +bool dm_helpers_dp_write_dsc_enable( |
---|
| 509 | + struct dc_context *ctx, |
---|
| 510 | + const struct dc_stream_state *stream, |
---|
| 511 | + bool enable |
---|
| 512 | +) |
---|
| 513 | +{ |
---|
| 514 | + uint8_t enable_dsc = enable ? 1 : 0; |
---|
| 515 | + struct amdgpu_dm_connector *aconnector; |
---|
| 516 | + |
---|
| 517 | + if (!stream) |
---|
| 518 | + return false; |
---|
| 519 | + |
---|
| 520 | + if (stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) { |
---|
| 521 | + aconnector = (struct amdgpu_dm_connector *)stream->dm_stream_context; |
---|
| 522 | + |
---|
| 523 | + if (!aconnector->dsc_aux) |
---|
| 524 | + return false; |
---|
| 525 | + |
---|
| 526 | + return (drm_dp_dpcd_write(aconnector->dsc_aux, DP_DSC_ENABLE, &enable_dsc, 1) >= 0); |
---|
| 527 | + } |
---|
| 528 | + |
---|
| 529 | + if (stream->signal == SIGNAL_TYPE_DISPLAY_PORT) |
---|
| 530 | + return dm_helpers_dp_write_dpcd(ctx, stream->link, DP_DSC_ENABLE, &enable_dsc, 1); |
---|
| 531 | + |
---|
| 532 | + return false; |
---|
| 533 | +} |
---|
456 | 534 | |
---|
457 | 535 | bool dm_helpers_is_dp_sink_present(struct dc_link *link) |
---|
458 | 536 | { |
---|
.. | .. |
---|
460 | 538 | struct amdgpu_dm_connector *aconnector = link->priv; |
---|
461 | 539 | |
---|
462 | 540 | if (!aconnector) { |
---|
463 | | - BUG_ON("Failed to found connector for link!"); |
---|
| 541 | + BUG_ON("Failed to find connector for link!"); |
---|
464 | 542 | return true; |
---|
465 | 543 | } |
---|
466 | 544 | |
---|
.. | .. |
---|
476 | 554 | struct dc_sink *sink) |
---|
477 | 555 | { |
---|
478 | 556 | struct amdgpu_dm_connector *aconnector = link->priv; |
---|
| 557 | + struct drm_connector *connector = &aconnector->base; |
---|
479 | 558 | struct i2c_adapter *ddc; |
---|
480 | 559 | int retry = 3; |
---|
481 | 560 | enum dc_edid_status edid_status; |
---|
.. | .. |
---|
493 | 572 | |
---|
494 | 573 | edid = drm_get_edid(&aconnector->base, ddc); |
---|
495 | 574 | |
---|
| 575 | + /* DP Compliance Test 4.2.2.6 */ |
---|
| 576 | + if (link->aux_mode && connector->edid_corrupt) |
---|
| 577 | + drm_dp_send_real_edid_checksum(&aconnector->dm_dp_aux.aux, connector->real_edid_checksum); |
---|
| 578 | + |
---|
| 579 | + if (!edid && connector->edid_corrupt) { |
---|
| 580 | + connector->edid_corrupt = false; |
---|
| 581 | + return EDID_BAD_CHECKSUM; |
---|
| 582 | + } |
---|
| 583 | + |
---|
496 | 584 | if (!edid) |
---|
497 | 585 | return EDID_NO_RESPONSE; |
---|
498 | 586 | |
---|
.. | .. |
---|
501 | 589 | |
---|
502 | 590 | /* We don't need the original edid anymore */ |
---|
503 | 591 | kfree(edid); |
---|
| 592 | + |
---|
| 593 | + /* connector->display_info will be parsed from EDID and saved |
---|
| 594 | + * into drm_connector->display_info from edid by call stack |
---|
| 595 | + * below: |
---|
| 596 | + * drm_parse_ycbcr420_deep_color_info |
---|
| 597 | + * drm_parse_hdmi_forum_vsdb |
---|
| 598 | + * drm_parse_cea_ext |
---|
| 599 | + * drm_add_display_info |
---|
| 600 | + * drm_connector_update_edid_property |
---|
| 601 | + * |
---|
| 602 | + * drm_connector->display_info will be used by amdgpu_dm funcs, |
---|
| 603 | + * like fill_stream_properties_from_drm_display_mode |
---|
| 604 | + */ |
---|
| 605 | + amdgpu_dm_update_connector_after_detect(aconnector); |
---|
504 | 606 | |
---|
505 | 607 | edid_status = dm_helpers_parse_edid_caps( |
---|
506 | 608 | ctx, |
---|
.. | .. |
---|
513 | 615 | DRM_ERROR("EDID err: %d, on connector: %s", |
---|
514 | 616 | edid_status, |
---|
515 | 617 | aconnector->base.name); |
---|
516 | | - if (link->aux_mode) { |
---|
517 | | - union test_request test_request = { {0} }; |
---|
518 | | - union test_response test_response = { {0} }; |
---|
519 | 618 | |
---|
520 | | - dm_helpers_dp_read_dpcd(ctx, |
---|
521 | | - link, |
---|
522 | | - DP_TEST_REQUEST, |
---|
523 | | - &test_request.raw, |
---|
524 | | - sizeof(union test_request)); |
---|
525 | | - |
---|
526 | | - if (!test_request.bits.EDID_READ) |
---|
527 | | - return edid_status; |
---|
528 | | - |
---|
529 | | - test_response.bits.EDID_CHECKSUM_WRITE = 1; |
---|
530 | | - |
---|
531 | | - dm_helpers_dp_write_dpcd(ctx, |
---|
532 | | - link, |
---|
533 | | - DP_TEST_EDID_CHECKSUM, |
---|
534 | | - &sink->dc_edid.raw_edid[sink->dc_edid.length-1], |
---|
535 | | - 1); |
---|
536 | | - |
---|
537 | | - dm_helpers_dp_write_dpcd(ctx, |
---|
538 | | - link, |
---|
539 | | - DP_TEST_RESPONSE, |
---|
540 | | - &test_response.raw, |
---|
541 | | - sizeof(test_response)); |
---|
542 | | - |
---|
543 | | - } |
---|
| 619 | + /* DP Compliance Test 4.2.2.3 */ |
---|
| 620 | + if (link->aux_mode) |
---|
| 621 | + drm_dp_send_real_edid_checksum(&aconnector->dm_dp_aux.aux, sink->dc_edid.raw_edid[sink->dc_edid.length-1]); |
---|
544 | 622 | |
---|
545 | 623 | return edid_status; |
---|
546 | 624 | } |
---|
.. | .. |
---|
549 | 627 | { |
---|
550 | 628 | /* TODO: something */ |
---|
551 | 629 | } |
---|
| 630 | +#ifdef CONFIG_DRM_AMD_DC_DCN3_0 |
---|
| 631 | + |
---|
| 632 | +void *dm_helpers_allocate_gpu_mem( |
---|
| 633 | + struct dc_context *ctx, |
---|
| 634 | + enum dc_gpu_mem_alloc_type type, |
---|
| 635 | + size_t size, |
---|
| 636 | + long long *addr) |
---|
| 637 | +{ |
---|
| 638 | + // TODO |
---|
| 639 | + return NULL; |
---|
| 640 | +} |
---|
| 641 | + |
---|
| 642 | +void dm_helpers_free_gpu_mem( |
---|
| 643 | + struct dc_context *ctx, |
---|
| 644 | + enum dc_gpu_mem_alloc_type type, |
---|
| 645 | + void *pvMem) |
---|
| 646 | +{ |
---|
| 647 | + // TODO |
---|
| 648 | +} |
---|
| 649 | +#endif |
---|