1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27#include "dc_bios_types.h"
28#include "hw_shared.h"
29#include "dcn31_apg.h"
30#include "reg_helper.h"
31
32#define DC_LOGGER \
33 apg31->base.ctx->logger
34
35#define REG(reg)\
36 (apg31->regs->reg)
37
38#undef FN
39#define FN(reg_name, field_name) \
40 apg31->apg_shift->field_name, apg31->apg_mask->field_name
41
42
43#define CTX \
44 apg31->base.ctx
45
46
47static void apg31_enable(
48 struct apg *apg)
49{
50 struct dcn31_apg *apg31 = DCN31_APG_FROM_APG(apg);
51
52
53 REG_UPDATE(APG_CONTROL, APG_RESET, 1);
54 REG_WAIT(APG_CONTROL,
55 APG_RESET_DONE, 1,
56 1, 10);
57 REG_UPDATE(APG_CONTROL, APG_RESET, 0);
58 REG_WAIT(APG_CONTROL,
59 APG_RESET_DONE, 0,
60 1, 10);
61
62
63 REG_UPDATE(APG_CONTROL2, APG_ENABLE, 1);
64}
65
66static void apg31_disable(
67 struct apg *apg)
68{
69 struct dcn31_apg *apg31 = DCN31_APG_FROM_APG(apg);
70
71
72 REG_UPDATE(APG_CONTROL2, APG_ENABLE, 0);
73}
74
75static union audio_cea_channels speakers_to_channels(
76 struct audio_speaker_flags speaker_flags)
77{
78 union audio_cea_channels cea_channels = {0};
79
80
81 cea_channels.channels.FL = speaker_flags.FL_FR;
82 cea_channels.channels.FR = speaker_flags.FL_FR;
83 cea_channels.channels.LFE = speaker_flags.LFE;
84 cea_channels.channels.FC = speaker_flags.FC;
85
86
87
88
89 if (speaker_flags.RL_RR) {
90 cea_channels.channels.RL_RC = speaker_flags.RL_RR;
91 cea_channels.channels.RR = speaker_flags.RL_RR;
92 cea_channels.channels.RC_RLC_FLC = speaker_flags.RC;
93 } else {
94 cea_channels.channels.RL_RC = speaker_flags.RC;
95 }
96
97
98 if (speaker_flags.FLC_FRC) {
99 cea_channels.channels.RC_RLC_FLC = speaker_flags.FLC_FRC;
100 cea_channels.channels.RRC_FRC = speaker_flags.FLC_FRC;
101 } else {
102 cea_channels.channels.RC_RLC_FLC = speaker_flags.RLC_RRC;
103 cea_channels.channels.RRC_FRC = speaker_flags.RLC_RRC;
104 }
105
106 return cea_channels;
107}
108
109static void apg31_se_audio_setup(
110 struct apg *apg,
111 unsigned int az_inst,
112 struct audio_info *audio_info)
113{
114 struct dcn31_apg *apg31 = DCN31_APG_FROM_APG(apg);
115
116 uint32_t speakers = 0;
117 uint32_t channels = 0;
118
119 ASSERT(audio_info);
120
121 if (audio_info == NULL)
122 return;
123
124 speakers = audio_info->flags.info.ALLSPEAKERS;
125 channels = speakers_to_channels(audio_info->flags.speaker_flags).all;
126
127
128 REG_UPDATE(APG_CONTROL2, APG_DP_AUDIO_STREAM_ID, 0);
129
130
131
132 REG_UPDATE(APG_DBG_GEN_CONTROL, APG_DBG_AUDIO_CHANNEL_ENABLE, 0xFF);
133
134
135
136 REG_UPDATE(APG_MEM_PWR, APG_MEM_PWR_FORCE, 0);
137
138 apg31_enable(apg);
139}
140
141static void apg31_audio_mute_control(
142 struct apg *apg,
143 bool mute)
144{
145 if (mute)
146 apg31_disable(apg);
147 else
148 apg31_enable(apg);
149}
150
151static struct apg_funcs dcn31_apg_funcs = {
152 .se_audio_setup = apg31_se_audio_setup,
153 .audio_mute_control = apg31_audio_mute_control,
154 .enable_apg = apg31_enable,
155 .disable_apg = apg31_disable,
156};
157
158void apg31_construct(struct dcn31_apg *apg31,
159 struct dc_context *ctx,
160 uint32_t inst,
161 const struct dcn31_apg_registers *apg_regs,
162 const struct dcn31_apg_shift *apg_shift,
163 const struct dcn31_apg_mask *apg_mask)
164{
165 apg31->base.ctx = ctx;
166
167 apg31->base.inst = inst;
168 apg31->base.funcs = &dcn31_apg_funcs;
169
170 apg31->regs = apg_regs;
171 apg31->apg_shift = apg_shift;
172 apg31->apg_mask = apg_mask;
173}
174