Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/amd/display: Use adjusted DCN301 watermarks

[why]
If DCN30 watermark calc is used for DCN301, the calculated values are
wrong due to the data structure mismatch between DCN30 and DCN301.
However, using the original DCN301 watermark values causes underflow.

[how]
- Add DCN21-style watermark calculations
- Adjust DCN301 watermark values to remove the underflow

Reviewed-by: Zhan Liu <zhan.liu@amd.com>
Acked-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
Signed-off-by: Nikola Cornij <nikola.cornij@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>

authored by

Nikola Cornij and committed by
Alex Deucher
808643ea f777bb9a

+97 -3
+2 -2
drivers/gpu/drm/amd/display/dc/clk_mgr/dcn301/vg_clk_mgr.c
··· 582 582 .wm_inst = WM_A, 583 583 .wm_type = WM_TYPE_PSTATE_CHG, 584 584 .pstate_latency_us = 11.65333, 585 - .sr_exit_time_us = 5.32, 586 - .sr_enter_plus_exit_time_us = 6.38, 585 + .sr_exit_time_us = 7.95, 586 + .sr_enter_plus_exit_time_us = 9, 587 587 .valid = true, 588 588 }, 589 589 {
+95 -1
drivers/gpu/drm/amd/display/dc/dcn301/dcn301_resource.c
··· 1626 1626 dml_init_instance(&dc->dml, &dcn3_01_soc, &dcn3_01_ip, DML_PROJECT_DCN30); 1627 1627 } 1628 1628 1629 + static void calculate_wm_set_for_vlevel( 1630 + int vlevel, 1631 + struct wm_range_table_entry *table_entry, 1632 + struct dcn_watermarks *wm_set, 1633 + struct display_mode_lib *dml, 1634 + display_e2e_pipe_params_st *pipes, 1635 + int pipe_cnt) 1636 + { 1637 + double dram_clock_change_latency_cached = dml->soc.dram_clock_change_latency_us; 1638 + 1639 + ASSERT(vlevel < dml->soc.num_states); 1640 + /* only pipe 0 is read for voltage and dcf/soc clocks */ 1641 + pipes[0].clks_cfg.voltage = vlevel; 1642 + pipes[0].clks_cfg.dcfclk_mhz = dml->soc.clock_limits[vlevel].dcfclk_mhz; 1643 + pipes[0].clks_cfg.socclk_mhz = dml->soc.clock_limits[vlevel].socclk_mhz; 1644 + 1645 + dml->soc.dram_clock_change_latency_us = table_entry->pstate_latency_us; 1646 + dml->soc.sr_exit_time_us = table_entry->sr_exit_time_us; 1647 + dml->soc.sr_enter_plus_exit_time_us = table_entry->sr_enter_plus_exit_time_us; 1648 + 1649 + wm_set->urgent_ns = get_wm_urgent(dml, pipes, pipe_cnt) * 1000; 1650 + wm_set->cstate_pstate.cstate_enter_plus_exit_ns = get_wm_stutter_enter_exit(dml, pipes, pipe_cnt) * 1000; 1651 + wm_set->cstate_pstate.cstate_exit_ns = get_wm_stutter_exit(dml, pipes, pipe_cnt) * 1000; 1652 + wm_set->cstate_pstate.pstate_change_ns = get_wm_dram_clock_change(dml, pipes, pipe_cnt) * 1000; 1653 + wm_set->pte_meta_urgent_ns = get_wm_memory_trip(dml, pipes, pipe_cnt) * 1000; 1654 + wm_set->frac_urg_bw_nom = get_fraction_of_urgent_bandwidth(dml, pipes, pipe_cnt) * 1000; 1655 + wm_set->frac_urg_bw_flip = get_fraction_of_urgent_bandwidth_imm_flip(dml, pipes, pipe_cnt) * 1000; 1656 + wm_set->urgent_latency_ns = get_urgent_latency(dml, pipes, pipe_cnt) * 1000; 1657 + dml->soc.dram_clock_change_latency_us = dram_clock_change_latency_cached; 1658 + 1659 + } 1660 + 1661 + static void dcn301_calculate_wm_and_dlg( 1662 + struct dc *dc, struct dc_state *context, 1663 + display_e2e_pipe_params_st *pipes, 1664 + int pipe_cnt, 1665 + int vlevel_req) 1666 + { 1667 + int i, pipe_idx; 1668 + int vlevel, vlevel_max; 1669 + struct wm_range_table_entry *table_entry; 1670 + struct clk_bw_params *bw_params = dc->clk_mgr->bw_params; 1671 + 1672 + ASSERT(bw_params); 1673 + 1674 + vlevel_max = bw_params->clk_table.num_entries - 1; 1675 + 1676 + /* WM Set D */ 1677 + table_entry = &bw_params->wm_table.entries[WM_D]; 1678 + if (table_entry->wm_type == WM_TYPE_RETRAINING) 1679 + vlevel = 0; 1680 + else 1681 + vlevel = vlevel_max; 1682 + calculate_wm_set_for_vlevel(vlevel, table_entry, &context->bw_ctx.bw.dcn.watermarks.d, 1683 + &context->bw_ctx.dml, pipes, pipe_cnt); 1684 + /* WM Set C */ 1685 + table_entry = &bw_params->wm_table.entries[WM_C]; 1686 + vlevel = min(max(vlevel_req, 2), vlevel_max); 1687 + calculate_wm_set_for_vlevel(vlevel, table_entry, &context->bw_ctx.bw.dcn.watermarks.c, 1688 + &context->bw_ctx.dml, pipes, pipe_cnt); 1689 + /* WM Set B */ 1690 + table_entry = &bw_params->wm_table.entries[WM_B]; 1691 + vlevel = min(max(vlevel_req, 1), vlevel_max); 1692 + calculate_wm_set_for_vlevel(vlevel, table_entry, &context->bw_ctx.bw.dcn.watermarks.b, 1693 + &context->bw_ctx.dml, pipes, pipe_cnt); 1694 + 1695 + /* WM Set A */ 1696 + table_entry = &bw_params->wm_table.entries[WM_A]; 1697 + vlevel = min(vlevel_req, vlevel_max); 1698 + calculate_wm_set_for_vlevel(vlevel, table_entry, &context->bw_ctx.bw.dcn.watermarks.a, 1699 + &context->bw_ctx.dml, pipes, pipe_cnt); 1700 + 1701 + for (i = 0, pipe_idx = 0; i < dc->res_pool->pipe_count; i++) { 1702 + if (!context->res_ctx.pipe_ctx[i].stream) 1703 + continue; 1704 + 1705 + pipes[pipe_idx].clks_cfg.dispclk_mhz = get_dispclk_calculated(&context->bw_ctx.dml, pipes, pipe_cnt); 1706 + pipes[pipe_idx].clks_cfg.dppclk_mhz = get_dppclk_calculated(&context->bw_ctx.dml, pipes, pipe_cnt, pipe_idx); 1707 + 1708 + if (dc->config.forced_clocks) { 1709 + pipes[pipe_idx].clks_cfg.dispclk_mhz = context->bw_ctx.dml.soc.clock_limits[0].dispclk_mhz; 1710 + pipes[pipe_idx].clks_cfg.dppclk_mhz = context->bw_ctx.dml.soc.clock_limits[0].dppclk_mhz; 1711 + } 1712 + if (dc->debug.min_disp_clk_khz > pipes[pipe_idx].clks_cfg.dispclk_mhz * 1000) 1713 + pipes[pipe_idx].clks_cfg.dispclk_mhz = dc->debug.min_disp_clk_khz / 1000.0; 1714 + if (dc->debug.min_dpp_clk_khz > pipes[pipe_idx].clks_cfg.dppclk_mhz * 1000) 1715 + pipes[pipe_idx].clks_cfg.dppclk_mhz = dc->debug.min_dpp_clk_khz / 1000.0; 1716 + 1717 + pipe_idx++; 1718 + } 1719 + 1720 + dcn20_calculate_dlg_params(dc, context, pipes, pipe_cnt, vlevel); 1721 + } 1722 + 1629 1723 static struct resource_funcs dcn301_res_pool_funcs = { 1630 1724 .destroy = dcn301_destroy_resource_pool, 1631 1725 .link_enc_create = dcn301_link_encoder_create, 1632 1726 .panel_cntl_create = dcn301_panel_cntl_create, 1633 1727 .validate_bandwidth = dcn30_validate_bandwidth, 1634 - .calculate_wm_and_dlg = dcn30_calculate_wm_and_dlg, 1728 + .calculate_wm_and_dlg = dcn301_calculate_wm_and_dlg, 1635 1729 .update_soc_for_wm_a = dcn30_update_soc_for_wm_a, 1636 1730 .populate_dml_pipes = dcn30_populate_dml_pipes_from_context, 1637 1731 .acquire_idle_pipe_for_layer = dcn20_acquire_idle_pipe_for_layer,