1/*	$NetBSD: amdgpu_clk_mgr.c,v 1.2 2021/12/18 23:45:01 riastradh Exp $	*/
2
3/*
4 * Copyright 2012-16 Advanced Micro Devices, Inc.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 * OTHER DEALINGS IN THE SOFTWARE.
23 *
24 * Authors: AMD
25 *
26 */
27
28#include <sys/cdefs.h>
29__KERNEL_RCSID(0, "$NetBSD: amdgpu_clk_mgr.c,v 1.2 2021/12/18 23:45:01 riastradh Exp $");
30
31#include <linux/slab.h>
32
33#include "dal_asic_id.h"
34#include "dc_types.h"
35#include "dccg.h"
36#include "clk_mgr_internal.h"
37
38#include "dce100/dce_clk_mgr.h"
39#include "dce110/dce110_clk_mgr.h"
40#include "dce112/dce112_clk_mgr.h"
41#include "dce120/dce120_clk_mgr.h"
42#include "dcn10/rv1_clk_mgr.h"
43#include "dcn10/rv2_clk_mgr.h"
44#include "dcn20/dcn20_clk_mgr.h"
45#include "dcn21/rn_clk_mgr.h"
46
47
48int clk_mgr_helper_get_active_display_cnt(
49		struct dc *dc,
50		struct dc_state *context)
51{
52	int i, display_count;
53
54	display_count = 0;
55	for (i = 0; i < context->stream_count; i++) {
56		const struct dc_stream_state *stream = context->streams[i];
57
58		/*
59		 * Only notify active stream or virtual stream.
60		 * Need to notify virtual stream to work around
61		 * headless case. HPD does not fire when system is in
62		 * S0i2.
63		 */
64		if (!stream->dpms_off || stream->signal == SIGNAL_TYPE_VIRTUAL)
65			display_count++;
66	}
67
68	return display_count;
69}
70
71void clk_mgr_exit_optimized_pwr_state(const struct dc *dc, struct clk_mgr *clk_mgr)
72{
73	struct dc_link *edp_link = get_edp_link(dc);
74
75	if (dc->hwss.exit_optimized_pwr_state)
76		dc->hwss.exit_optimized_pwr_state(dc, dc->current_state);
77
78	if (edp_link) {
79		clk_mgr->psr_allow_active_cache = edp_link->psr_allow_active;
80		dc_link_set_psr_allow_active(edp_link, false, false);
81	}
82
83}
84
85void clk_mgr_optimize_pwr_state(const struct dc *dc, struct clk_mgr *clk_mgr)
86{
87	struct dc_link *edp_link = get_edp_link(dc);
88
89	if (edp_link)
90		dc_link_set_psr_allow_active(edp_link, clk_mgr->psr_allow_active_cache, false);
91
92	if (dc->hwss.optimize_pwr_state)
93		dc->hwss.optimize_pwr_state(dc, dc->current_state);
94
95}
96
97struct clk_mgr *dc_clk_mgr_create(struct dc_context *ctx, struct pp_smu_funcs *pp_smu, struct dccg *dccg)
98{
99	struct hw_asic_id asic_id = ctx->asic_id;
100
101	struct clk_mgr_internal *clk_mgr = kzalloc(sizeof(*clk_mgr), GFP_KERNEL);
102
103	if (clk_mgr == NULL) {
104		BREAK_TO_DEBUGGER();
105		return NULL;
106	}
107
108	switch (asic_id.chip_family) {
109	case FAMILY_CI:
110	case FAMILY_KV:
111		dce_clk_mgr_construct(ctx, clk_mgr);
112		break;
113	case FAMILY_CZ:
114		dce110_clk_mgr_construct(ctx, clk_mgr);
115		break;
116	case FAMILY_VI:
117		if (ASIC_REV_IS_TONGA_P(asic_id.hw_internal_rev) ||
118				ASIC_REV_IS_FIJI_P(asic_id.hw_internal_rev)) {
119			dce_clk_mgr_construct(ctx, clk_mgr);
120			break;
121		}
122		if (ASIC_REV_IS_POLARIS10_P(asic_id.hw_internal_rev) ||
123				ASIC_REV_IS_POLARIS11_M(asic_id.hw_internal_rev) ||
124				ASIC_REV_IS_POLARIS12_V(asic_id.hw_internal_rev)) {
125			dce112_clk_mgr_construct(ctx, clk_mgr);
126			break;
127		}
128		if (ASIC_REV_IS_VEGAM(asic_id.hw_internal_rev)) {
129			dce112_clk_mgr_construct(ctx, clk_mgr);
130			break;
131		}
132		break;
133	case FAMILY_AI:
134		if (ASICREV_IS_VEGA20_P(asic_id.hw_internal_rev))
135			dce121_clk_mgr_construct(ctx, clk_mgr);
136		else
137			dce120_clk_mgr_construct(ctx, clk_mgr);
138		break;
139
140#if defined(CONFIG_DRM_AMD_DC_DCN)
141	case FAMILY_RV:
142		if (ASICREV_IS_DALI(asic_id.hw_internal_rev) ||
143				ASICREV_IS_POLLOCK(asic_id.hw_internal_rev)) {
144			/* TEMP: this check has to come before ASICREV_IS_RENOIR */
145			/* which also incorrectly returns true for Dali/Pollock*/
146			rv2_clk_mgr_construct(ctx, clk_mgr, pp_smu);
147			break;
148		}
149		if (ASICREV_IS_RENOIR(asic_id.hw_internal_rev)) {
150			rn_clk_mgr_construct(ctx, clk_mgr, pp_smu, dccg);
151			break;
152		}
153		if (ASICREV_IS_RAVEN2(asic_id.hw_internal_rev)) {
154			rv2_clk_mgr_construct(ctx, clk_mgr, pp_smu);
155			break;
156		}
157		if (ASICREV_IS_RAVEN(asic_id.hw_internal_rev) ||
158				ASICREV_IS_PICASSO(asic_id.hw_internal_rev)) {
159			rv1_clk_mgr_construct(ctx, clk_mgr, pp_smu);
160			break;
161		}
162		break;
163
164	case FAMILY_NV:
165		dcn20_clk_mgr_construct(ctx, clk_mgr, pp_smu, dccg);
166		break;
167#endif	/* Family RV and NV*/
168
169	default:
170		ASSERT(0); /* Unknown Asic */
171		break;
172	}
173
174	return &clk_mgr->base;
175}
176
177void dc_destroy_clk_mgr(struct clk_mgr *clk_mgr_base)
178{
179	struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base);
180
181	kfree(clk_mgr);
182}
183
184