1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun * Copyright 2014 Advanced Micro Devices, Inc.
3*4882a593Smuzhiyun *
4*4882a593Smuzhiyun * Permission is hereby granted, free of charge, to any person obtaining a
5*4882a593Smuzhiyun * copy of this software and associated documentation files (the "Software"),
6*4882a593Smuzhiyun * to deal in the Software without restriction, including without limitation
7*4882a593Smuzhiyun * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8*4882a593Smuzhiyun * and/or sell copies of the Software, and to permit persons to whom the
9*4882a593Smuzhiyun * Software is furnished to do so, subject to the following conditions:
10*4882a593Smuzhiyun *
11*4882a593Smuzhiyun * The above copyright notice and this permission notice shall be included in
12*4882a593Smuzhiyun * all copies or substantial portions of the Software.
13*4882a593Smuzhiyun *
14*4882a593Smuzhiyun * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15*4882a593Smuzhiyun * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16*4882a593Smuzhiyun * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17*4882a593Smuzhiyun * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18*4882a593Smuzhiyun * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19*4882a593Smuzhiyun * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20*4882a593Smuzhiyun * OTHER DEALINGS IN THE SOFTWARE.
21*4882a593Smuzhiyun *
22*4882a593Smuzhiyun * Authors: Slava Grigorev <slava.grigorev@amd.com>
23*4882a593Smuzhiyun */
24*4882a593Smuzhiyun
25*4882a593Smuzhiyun #include <linux/gcd.h>
26*4882a593Smuzhiyun
27*4882a593Smuzhiyun #include <drm/drm_crtc.h>
28*4882a593Smuzhiyun #include "radeon.h"
29*4882a593Smuzhiyun #include "atom.h"
30*4882a593Smuzhiyun #include "radeon_audio.h"
31*4882a593Smuzhiyun
32*4882a593Smuzhiyun void r600_audio_enable(struct radeon_device *rdev, struct r600_audio_pin *pin,
33*4882a593Smuzhiyun u8 enable_mask);
34*4882a593Smuzhiyun void dce4_audio_enable(struct radeon_device *rdev, struct r600_audio_pin *pin,
35*4882a593Smuzhiyun u8 enable_mask);
36*4882a593Smuzhiyun void dce6_audio_enable(struct radeon_device *rdev, struct r600_audio_pin *pin,
37*4882a593Smuzhiyun u8 enable_mask);
38*4882a593Smuzhiyun u32 dce6_endpoint_rreg(struct radeon_device *rdev, u32 offset, u32 reg);
39*4882a593Smuzhiyun void dce6_endpoint_wreg(struct radeon_device *rdev,
40*4882a593Smuzhiyun u32 offset, u32 reg, u32 v);
41*4882a593Smuzhiyun void dce3_2_afmt_write_sad_regs(struct drm_encoder *encoder,
42*4882a593Smuzhiyun struct cea_sad *sads, int sad_count);
43*4882a593Smuzhiyun void evergreen_hdmi_write_sad_regs(struct drm_encoder *encoder,
44*4882a593Smuzhiyun struct cea_sad *sads, int sad_count);
45*4882a593Smuzhiyun void dce6_afmt_write_sad_regs(struct drm_encoder *encoder,
46*4882a593Smuzhiyun struct cea_sad *sads, int sad_count);
47*4882a593Smuzhiyun void dce3_2_afmt_hdmi_write_speaker_allocation(struct drm_encoder *encoder,
48*4882a593Smuzhiyun u8 *sadb, int sad_count);
49*4882a593Smuzhiyun void dce3_2_afmt_dp_write_speaker_allocation(struct drm_encoder *encoder,
50*4882a593Smuzhiyun u8 *sadb, int sad_count);
51*4882a593Smuzhiyun void dce4_afmt_hdmi_write_speaker_allocation(struct drm_encoder *encoder,
52*4882a593Smuzhiyun u8 *sadb, int sad_count);
53*4882a593Smuzhiyun void dce4_afmt_dp_write_speaker_allocation(struct drm_encoder *encoder,
54*4882a593Smuzhiyun u8 *sadb, int sad_count);
55*4882a593Smuzhiyun void dce6_afmt_hdmi_write_speaker_allocation(struct drm_encoder *encoder,
56*4882a593Smuzhiyun u8 *sadb, int sad_count);
57*4882a593Smuzhiyun void dce6_afmt_dp_write_speaker_allocation(struct drm_encoder *encoder,
58*4882a593Smuzhiyun u8 *sadb, int sad_count);
59*4882a593Smuzhiyun void dce4_afmt_write_latency_fields(struct drm_encoder *encoder,
60*4882a593Smuzhiyun struct drm_connector *connector, struct drm_display_mode *mode);
61*4882a593Smuzhiyun void dce6_afmt_write_latency_fields(struct drm_encoder *encoder,
62*4882a593Smuzhiyun struct drm_connector *connector, struct drm_display_mode *mode);
63*4882a593Smuzhiyun struct r600_audio_pin* r600_audio_get_pin(struct radeon_device *rdev);
64*4882a593Smuzhiyun struct r600_audio_pin* dce6_audio_get_pin(struct radeon_device *rdev);
65*4882a593Smuzhiyun void dce6_afmt_select_pin(struct drm_encoder *encoder);
66*4882a593Smuzhiyun void r600_hdmi_audio_set_dto(struct radeon_device *rdev,
67*4882a593Smuzhiyun struct radeon_crtc *crtc, unsigned int clock);
68*4882a593Smuzhiyun void dce3_2_audio_set_dto(struct radeon_device *rdev,
69*4882a593Smuzhiyun struct radeon_crtc *crtc, unsigned int clock);
70*4882a593Smuzhiyun void dce4_hdmi_audio_set_dto(struct radeon_device *rdev,
71*4882a593Smuzhiyun struct radeon_crtc *crtc, unsigned int clock);
72*4882a593Smuzhiyun void dce4_dp_audio_set_dto(struct radeon_device *rdev,
73*4882a593Smuzhiyun struct radeon_crtc *crtc, unsigned int clock);
74*4882a593Smuzhiyun void dce6_hdmi_audio_set_dto(struct radeon_device *rdev,
75*4882a593Smuzhiyun struct radeon_crtc *crtc, unsigned int clock);
76*4882a593Smuzhiyun void dce6_dp_audio_set_dto(struct radeon_device *rdev,
77*4882a593Smuzhiyun struct radeon_crtc *crtc, unsigned int clock);
78*4882a593Smuzhiyun void r600_set_avi_packet(struct radeon_device *rdev, u32 offset,
79*4882a593Smuzhiyun unsigned char *buffer, size_t size);
80*4882a593Smuzhiyun void evergreen_set_avi_packet(struct radeon_device *rdev, u32 offset,
81*4882a593Smuzhiyun unsigned char *buffer, size_t size);
82*4882a593Smuzhiyun void r600_hdmi_update_acr(struct drm_encoder *encoder, long offset,
83*4882a593Smuzhiyun const struct radeon_hdmi_acr *acr);
84*4882a593Smuzhiyun void dce3_2_hdmi_update_acr(struct drm_encoder *encoder, long offset,
85*4882a593Smuzhiyun const struct radeon_hdmi_acr *acr);
86*4882a593Smuzhiyun void evergreen_hdmi_update_acr(struct drm_encoder *encoder, long offset,
87*4882a593Smuzhiyun const struct radeon_hdmi_acr *acr);
88*4882a593Smuzhiyun void r600_set_vbi_packet(struct drm_encoder *encoder, u32 offset);
89*4882a593Smuzhiyun void dce4_set_vbi_packet(struct drm_encoder *encoder, u32 offset);
90*4882a593Smuzhiyun void dce4_hdmi_set_color_depth(struct drm_encoder *encoder,
91*4882a593Smuzhiyun u32 offset, int bpc);
92*4882a593Smuzhiyun void r600_set_audio_packet(struct drm_encoder *encoder, u32 offset);
93*4882a593Smuzhiyun void dce3_2_set_audio_packet(struct drm_encoder *encoder, u32 offset);
94*4882a593Smuzhiyun void dce4_set_audio_packet(struct drm_encoder *encoder, u32 offset);
95*4882a593Smuzhiyun void r600_set_mute(struct drm_encoder *encoder, u32 offset, bool mute);
96*4882a593Smuzhiyun void dce3_2_set_mute(struct drm_encoder *encoder, u32 offset, bool mute);
97*4882a593Smuzhiyun void dce4_set_mute(struct drm_encoder *encoder, u32 offset, bool mute);
98*4882a593Smuzhiyun static void radeon_audio_hdmi_mode_set(struct drm_encoder *encoder,
99*4882a593Smuzhiyun struct drm_display_mode *mode);
100*4882a593Smuzhiyun static void radeon_audio_dp_mode_set(struct drm_encoder *encoder,
101*4882a593Smuzhiyun struct drm_display_mode *mode);
102*4882a593Smuzhiyun void r600_hdmi_enable(struct drm_encoder *encoder, bool enable);
103*4882a593Smuzhiyun void evergreen_hdmi_enable(struct drm_encoder *encoder, bool enable);
104*4882a593Smuzhiyun void evergreen_dp_enable(struct drm_encoder *encoder, bool enable);
105*4882a593Smuzhiyun
106*4882a593Smuzhiyun static const u32 pin_offsets[7] =
107*4882a593Smuzhiyun {
108*4882a593Smuzhiyun (0x5e00 - 0x5e00),
109*4882a593Smuzhiyun (0x5e18 - 0x5e00),
110*4882a593Smuzhiyun (0x5e30 - 0x5e00),
111*4882a593Smuzhiyun (0x5e48 - 0x5e00),
112*4882a593Smuzhiyun (0x5e60 - 0x5e00),
113*4882a593Smuzhiyun (0x5e78 - 0x5e00),
114*4882a593Smuzhiyun (0x5e90 - 0x5e00),
115*4882a593Smuzhiyun };
116*4882a593Smuzhiyun
radeon_audio_rreg(struct radeon_device * rdev,u32 offset,u32 reg)117*4882a593Smuzhiyun static u32 radeon_audio_rreg(struct radeon_device *rdev, u32 offset, u32 reg)
118*4882a593Smuzhiyun {
119*4882a593Smuzhiyun return RREG32(reg);
120*4882a593Smuzhiyun }
121*4882a593Smuzhiyun
radeon_audio_wreg(struct radeon_device * rdev,u32 offset,u32 reg,u32 v)122*4882a593Smuzhiyun static void radeon_audio_wreg(struct radeon_device *rdev, u32 offset,
123*4882a593Smuzhiyun u32 reg, u32 v)
124*4882a593Smuzhiyun {
125*4882a593Smuzhiyun WREG32(reg, v);
126*4882a593Smuzhiyun }
127*4882a593Smuzhiyun
128*4882a593Smuzhiyun static struct radeon_audio_basic_funcs r600_funcs = {
129*4882a593Smuzhiyun .endpoint_rreg = radeon_audio_rreg,
130*4882a593Smuzhiyun .endpoint_wreg = radeon_audio_wreg,
131*4882a593Smuzhiyun .enable = r600_audio_enable,
132*4882a593Smuzhiyun };
133*4882a593Smuzhiyun
134*4882a593Smuzhiyun static struct radeon_audio_basic_funcs dce32_funcs = {
135*4882a593Smuzhiyun .endpoint_rreg = radeon_audio_rreg,
136*4882a593Smuzhiyun .endpoint_wreg = radeon_audio_wreg,
137*4882a593Smuzhiyun .enable = r600_audio_enable,
138*4882a593Smuzhiyun };
139*4882a593Smuzhiyun
140*4882a593Smuzhiyun static struct radeon_audio_basic_funcs dce4_funcs = {
141*4882a593Smuzhiyun .endpoint_rreg = radeon_audio_rreg,
142*4882a593Smuzhiyun .endpoint_wreg = radeon_audio_wreg,
143*4882a593Smuzhiyun .enable = dce4_audio_enable,
144*4882a593Smuzhiyun };
145*4882a593Smuzhiyun
146*4882a593Smuzhiyun static struct radeon_audio_basic_funcs dce6_funcs = {
147*4882a593Smuzhiyun .endpoint_rreg = dce6_endpoint_rreg,
148*4882a593Smuzhiyun .endpoint_wreg = dce6_endpoint_wreg,
149*4882a593Smuzhiyun .enable = dce6_audio_enable,
150*4882a593Smuzhiyun };
151*4882a593Smuzhiyun
152*4882a593Smuzhiyun static struct radeon_audio_funcs r600_hdmi_funcs = {
153*4882a593Smuzhiyun .get_pin = r600_audio_get_pin,
154*4882a593Smuzhiyun .set_dto = r600_hdmi_audio_set_dto,
155*4882a593Smuzhiyun .update_acr = r600_hdmi_update_acr,
156*4882a593Smuzhiyun .set_vbi_packet = r600_set_vbi_packet,
157*4882a593Smuzhiyun .set_avi_packet = r600_set_avi_packet,
158*4882a593Smuzhiyun .set_audio_packet = r600_set_audio_packet,
159*4882a593Smuzhiyun .set_mute = r600_set_mute,
160*4882a593Smuzhiyun .mode_set = radeon_audio_hdmi_mode_set,
161*4882a593Smuzhiyun .dpms = r600_hdmi_enable,
162*4882a593Smuzhiyun };
163*4882a593Smuzhiyun
164*4882a593Smuzhiyun static struct radeon_audio_funcs dce32_hdmi_funcs = {
165*4882a593Smuzhiyun .get_pin = r600_audio_get_pin,
166*4882a593Smuzhiyun .write_sad_regs = dce3_2_afmt_write_sad_regs,
167*4882a593Smuzhiyun .write_speaker_allocation = dce3_2_afmt_hdmi_write_speaker_allocation,
168*4882a593Smuzhiyun .set_dto = dce3_2_audio_set_dto,
169*4882a593Smuzhiyun .update_acr = dce3_2_hdmi_update_acr,
170*4882a593Smuzhiyun .set_vbi_packet = r600_set_vbi_packet,
171*4882a593Smuzhiyun .set_avi_packet = r600_set_avi_packet,
172*4882a593Smuzhiyun .set_audio_packet = dce3_2_set_audio_packet,
173*4882a593Smuzhiyun .set_mute = dce3_2_set_mute,
174*4882a593Smuzhiyun .mode_set = radeon_audio_hdmi_mode_set,
175*4882a593Smuzhiyun .dpms = r600_hdmi_enable,
176*4882a593Smuzhiyun };
177*4882a593Smuzhiyun
178*4882a593Smuzhiyun static struct radeon_audio_funcs dce32_dp_funcs = {
179*4882a593Smuzhiyun .get_pin = r600_audio_get_pin,
180*4882a593Smuzhiyun .write_sad_regs = dce3_2_afmt_write_sad_regs,
181*4882a593Smuzhiyun .write_speaker_allocation = dce3_2_afmt_dp_write_speaker_allocation,
182*4882a593Smuzhiyun .set_dto = dce3_2_audio_set_dto,
183*4882a593Smuzhiyun .set_avi_packet = r600_set_avi_packet,
184*4882a593Smuzhiyun .set_audio_packet = dce3_2_set_audio_packet,
185*4882a593Smuzhiyun };
186*4882a593Smuzhiyun
187*4882a593Smuzhiyun static struct radeon_audio_funcs dce4_hdmi_funcs = {
188*4882a593Smuzhiyun .get_pin = r600_audio_get_pin,
189*4882a593Smuzhiyun .write_sad_regs = evergreen_hdmi_write_sad_regs,
190*4882a593Smuzhiyun .write_speaker_allocation = dce4_afmt_hdmi_write_speaker_allocation,
191*4882a593Smuzhiyun .write_latency_fields = dce4_afmt_write_latency_fields,
192*4882a593Smuzhiyun .set_dto = dce4_hdmi_audio_set_dto,
193*4882a593Smuzhiyun .update_acr = evergreen_hdmi_update_acr,
194*4882a593Smuzhiyun .set_vbi_packet = dce4_set_vbi_packet,
195*4882a593Smuzhiyun .set_color_depth = dce4_hdmi_set_color_depth,
196*4882a593Smuzhiyun .set_avi_packet = evergreen_set_avi_packet,
197*4882a593Smuzhiyun .set_audio_packet = dce4_set_audio_packet,
198*4882a593Smuzhiyun .set_mute = dce4_set_mute,
199*4882a593Smuzhiyun .mode_set = radeon_audio_hdmi_mode_set,
200*4882a593Smuzhiyun .dpms = evergreen_hdmi_enable,
201*4882a593Smuzhiyun };
202*4882a593Smuzhiyun
203*4882a593Smuzhiyun static struct radeon_audio_funcs dce4_dp_funcs = {
204*4882a593Smuzhiyun .get_pin = r600_audio_get_pin,
205*4882a593Smuzhiyun .write_sad_regs = evergreen_hdmi_write_sad_regs,
206*4882a593Smuzhiyun .write_speaker_allocation = dce4_afmt_dp_write_speaker_allocation,
207*4882a593Smuzhiyun .write_latency_fields = dce4_afmt_write_latency_fields,
208*4882a593Smuzhiyun .set_dto = dce4_dp_audio_set_dto,
209*4882a593Smuzhiyun .set_avi_packet = evergreen_set_avi_packet,
210*4882a593Smuzhiyun .set_audio_packet = dce4_set_audio_packet,
211*4882a593Smuzhiyun .mode_set = radeon_audio_dp_mode_set,
212*4882a593Smuzhiyun .dpms = evergreen_dp_enable,
213*4882a593Smuzhiyun };
214*4882a593Smuzhiyun
215*4882a593Smuzhiyun static struct radeon_audio_funcs dce6_hdmi_funcs = {
216*4882a593Smuzhiyun .select_pin = dce6_afmt_select_pin,
217*4882a593Smuzhiyun .get_pin = dce6_audio_get_pin,
218*4882a593Smuzhiyun .write_sad_regs = dce6_afmt_write_sad_regs,
219*4882a593Smuzhiyun .write_speaker_allocation = dce6_afmt_hdmi_write_speaker_allocation,
220*4882a593Smuzhiyun .write_latency_fields = dce6_afmt_write_latency_fields,
221*4882a593Smuzhiyun .set_dto = dce6_hdmi_audio_set_dto,
222*4882a593Smuzhiyun .update_acr = evergreen_hdmi_update_acr,
223*4882a593Smuzhiyun .set_vbi_packet = dce4_set_vbi_packet,
224*4882a593Smuzhiyun .set_color_depth = dce4_hdmi_set_color_depth,
225*4882a593Smuzhiyun .set_avi_packet = evergreen_set_avi_packet,
226*4882a593Smuzhiyun .set_audio_packet = dce4_set_audio_packet,
227*4882a593Smuzhiyun .set_mute = dce4_set_mute,
228*4882a593Smuzhiyun .mode_set = radeon_audio_hdmi_mode_set,
229*4882a593Smuzhiyun .dpms = evergreen_hdmi_enable,
230*4882a593Smuzhiyun };
231*4882a593Smuzhiyun
232*4882a593Smuzhiyun static struct radeon_audio_funcs dce6_dp_funcs = {
233*4882a593Smuzhiyun .select_pin = dce6_afmt_select_pin,
234*4882a593Smuzhiyun .get_pin = dce6_audio_get_pin,
235*4882a593Smuzhiyun .write_sad_regs = dce6_afmt_write_sad_regs,
236*4882a593Smuzhiyun .write_speaker_allocation = dce6_afmt_dp_write_speaker_allocation,
237*4882a593Smuzhiyun .write_latency_fields = dce6_afmt_write_latency_fields,
238*4882a593Smuzhiyun .set_dto = dce6_dp_audio_set_dto,
239*4882a593Smuzhiyun .set_avi_packet = evergreen_set_avi_packet,
240*4882a593Smuzhiyun .set_audio_packet = dce4_set_audio_packet,
241*4882a593Smuzhiyun .mode_set = radeon_audio_dp_mode_set,
242*4882a593Smuzhiyun .dpms = evergreen_dp_enable,
243*4882a593Smuzhiyun };
244*4882a593Smuzhiyun
radeon_audio_enable(struct radeon_device * rdev,struct r600_audio_pin * pin,u8 enable_mask)245*4882a593Smuzhiyun static void radeon_audio_enable(struct radeon_device *rdev,
246*4882a593Smuzhiyun struct r600_audio_pin *pin, u8 enable_mask)
247*4882a593Smuzhiyun {
248*4882a593Smuzhiyun struct drm_encoder *encoder;
249*4882a593Smuzhiyun struct radeon_encoder *radeon_encoder;
250*4882a593Smuzhiyun struct radeon_encoder_atom_dig *dig;
251*4882a593Smuzhiyun int pin_count = 0;
252*4882a593Smuzhiyun
253*4882a593Smuzhiyun if (!pin)
254*4882a593Smuzhiyun return;
255*4882a593Smuzhiyun
256*4882a593Smuzhiyun if (rdev->mode_info.mode_config_initialized) {
257*4882a593Smuzhiyun list_for_each_entry(encoder, &rdev->ddev->mode_config.encoder_list, head) {
258*4882a593Smuzhiyun if (radeon_encoder_is_digital(encoder)) {
259*4882a593Smuzhiyun radeon_encoder = to_radeon_encoder(encoder);
260*4882a593Smuzhiyun dig = radeon_encoder->enc_priv;
261*4882a593Smuzhiyun if (dig->pin == pin)
262*4882a593Smuzhiyun pin_count++;
263*4882a593Smuzhiyun }
264*4882a593Smuzhiyun }
265*4882a593Smuzhiyun
266*4882a593Smuzhiyun if ((pin_count > 1) && (enable_mask == 0))
267*4882a593Smuzhiyun return;
268*4882a593Smuzhiyun }
269*4882a593Smuzhiyun
270*4882a593Smuzhiyun if (rdev->audio.funcs->enable)
271*4882a593Smuzhiyun rdev->audio.funcs->enable(rdev, pin, enable_mask);
272*4882a593Smuzhiyun }
273*4882a593Smuzhiyun
radeon_audio_interface_init(struct radeon_device * rdev)274*4882a593Smuzhiyun static void radeon_audio_interface_init(struct radeon_device *rdev)
275*4882a593Smuzhiyun {
276*4882a593Smuzhiyun if (ASIC_IS_DCE6(rdev)) {
277*4882a593Smuzhiyun rdev->audio.funcs = &dce6_funcs;
278*4882a593Smuzhiyun rdev->audio.hdmi_funcs = &dce6_hdmi_funcs;
279*4882a593Smuzhiyun rdev->audio.dp_funcs = &dce6_dp_funcs;
280*4882a593Smuzhiyun } else if (ASIC_IS_DCE4(rdev)) {
281*4882a593Smuzhiyun rdev->audio.funcs = &dce4_funcs;
282*4882a593Smuzhiyun rdev->audio.hdmi_funcs = &dce4_hdmi_funcs;
283*4882a593Smuzhiyun rdev->audio.dp_funcs = &dce4_dp_funcs;
284*4882a593Smuzhiyun } else if (ASIC_IS_DCE32(rdev)) {
285*4882a593Smuzhiyun rdev->audio.funcs = &dce32_funcs;
286*4882a593Smuzhiyun rdev->audio.hdmi_funcs = &dce32_hdmi_funcs;
287*4882a593Smuzhiyun rdev->audio.dp_funcs = &dce32_dp_funcs;
288*4882a593Smuzhiyun } else {
289*4882a593Smuzhiyun rdev->audio.funcs = &r600_funcs;
290*4882a593Smuzhiyun rdev->audio.hdmi_funcs = &r600_hdmi_funcs;
291*4882a593Smuzhiyun rdev->audio.dp_funcs = NULL;
292*4882a593Smuzhiyun }
293*4882a593Smuzhiyun }
294*4882a593Smuzhiyun
radeon_audio_chipset_supported(struct radeon_device * rdev)295*4882a593Smuzhiyun static int radeon_audio_chipset_supported(struct radeon_device *rdev)
296*4882a593Smuzhiyun {
297*4882a593Smuzhiyun return ASIC_IS_DCE2(rdev) && !ASIC_IS_NODCE(rdev);
298*4882a593Smuzhiyun }
299*4882a593Smuzhiyun
radeon_audio_init(struct radeon_device * rdev)300*4882a593Smuzhiyun int radeon_audio_init(struct radeon_device *rdev)
301*4882a593Smuzhiyun {
302*4882a593Smuzhiyun int i;
303*4882a593Smuzhiyun
304*4882a593Smuzhiyun if (!radeon_audio || !radeon_audio_chipset_supported(rdev))
305*4882a593Smuzhiyun return 0;
306*4882a593Smuzhiyun
307*4882a593Smuzhiyun rdev->audio.enabled = true;
308*4882a593Smuzhiyun
309*4882a593Smuzhiyun if (ASIC_IS_DCE83(rdev)) /* KB: 2 streams, 3 endpoints */
310*4882a593Smuzhiyun rdev->audio.num_pins = 3;
311*4882a593Smuzhiyun else if (ASIC_IS_DCE81(rdev)) /* KV: 4 streams, 7 endpoints */
312*4882a593Smuzhiyun rdev->audio.num_pins = 7;
313*4882a593Smuzhiyun else if (ASIC_IS_DCE8(rdev)) /* BN/HW: 6 streams, 7 endpoints */
314*4882a593Smuzhiyun rdev->audio.num_pins = 7;
315*4882a593Smuzhiyun else if (ASIC_IS_DCE64(rdev)) /* OL: 2 streams, 2 endpoints */
316*4882a593Smuzhiyun rdev->audio.num_pins = 2;
317*4882a593Smuzhiyun else if (ASIC_IS_DCE61(rdev)) /* TN: 4 streams, 6 endpoints */
318*4882a593Smuzhiyun rdev->audio.num_pins = 6;
319*4882a593Smuzhiyun else if (ASIC_IS_DCE6(rdev)) /* SI: 6 streams, 6 endpoints */
320*4882a593Smuzhiyun rdev->audio.num_pins = 6;
321*4882a593Smuzhiyun else
322*4882a593Smuzhiyun rdev->audio.num_pins = 1;
323*4882a593Smuzhiyun
324*4882a593Smuzhiyun for (i = 0; i < rdev->audio.num_pins; i++) {
325*4882a593Smuzhiyun rdev->audio.pin[i].channels = -1;
326*4882a593Smuzhiyun rdev->audio.pin[i].rate = -1;
327*4882a593Smuzhiyun rdev->audio.pin[i].bits_per_sample = -1;
328*4882a593Smuzhiyun rdev->audio.pin[i].status_bits = 0;
329*4882a593Smuzhiyun rdev->audio.pin[i].category_code = 0;
330*4882a593Smuzhiyun rdev->audio.pin[i].connected = false;
331*4882a593Smuzhiyun rdev->audio.pin[i].offset = pin_offsets[i];
332*4882a593Smuzhiyun rdev->audio.pin[i].id = i;
333*4882a593Smuzhiyun }
334*4882a593Smuzhiyun
335*4882a593Smuzhiyun radeon_audio_interface_init(rdev);
336*4882a593Smuzhiyun
337*4882a593Smuzhiyun /* disable audio. it will be set up later */
338*4882a593Smuzhiyun for (i = 0; i < rdev->audio.num_pins; i++)
339*4882a593Smuzhiyun radeon_audio_enable(rdev, &rdev->audio.pin[i], 0);
340*4882a593Smuzhiyun
341*4882a593Smuzhiyun return 0;
342*4882a593Smuzhiyun }
343*4882a593Smuzhiyun
radeon_audio_endpoint_rreg(struct radeon_device * rdev,u32 offset,u32 reg)344*4882a593Smuzhiyun u32 radeon_audio_endpoint_rreg(struct radeon_device *rdev, u32 offset, u32 reg)
345*4882a593Smuzhiyun {
346*4882a593Smuzhiyun if (rdev->audio.funcs->endpoint_rreg)
347*4882a593Smuzhiyun return rdev->audio.funcs->endpoint_rreg(rdev, offset, reg);
348*4882a593Smuzhiyun
349*4882a593Smuzhiyun return 0;
350*4882a593Smuzhiyun }
351*4882a593Smuzhiyun
radeon_audio_endpoint_wreg(struct radeon_device * rdev,u32 offset,u32 reg,u32 v)352*4882a593Smuzhiyun void radeon_audio_endpoint_wreg(struct radeon_device *rdev, u32 offset,
353*4882a593Smuzhiyun u32 reg, u32 v)
354*4882a593Smuzhiyun {
355*4882a593Smuzhiyun if (rdev->audio.funcs->endpoint_wreg)
356*4882a593Smuzhiyun rdev->audio.funcs->endpoint_wreg(rdev, offset, reg, v);
357*4882a593Smuzhiyun }
358*4882a593Smuzhiyun
radeon_audio_write_sad_regs(struct drm_encoder * encoder)359*4882a593Smuzhiyun static void radeon_audio_write_sad_regs(struct drm_encoder *encoder)
360*4882a593Smuzhiyun {
361*4882a593Smuzhiyun struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
362*4882a593Smuzhiyun struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
363*4882a593Smuzhiyun struct cea_sad *sads;
364*4882a593Smuzhiyun int sad_count;
365*4882a593Smuzhiyun
366*4882a593Smuzhiyun if (!connector)
367*4882a593Smuzhiyun return;
368*4882a593Smuzhiyun
369*4882a593Smuzhiyun sad_count = drm_edid_to_sad(radeon_connector_edid(connector), &sads);
370*4882a593Smuzhiyun if (sad_count < 0)
371*4882a593Smuzhiyun DRM_ERROR("Couldn't read SADs: %d\n", sad_count);
372*4882a593Smuzhiyun if (sad_count <= 0)
373*4882a593Smuzhiyun return;
374*4882a593Smuzhiyun BUG_ON(!sads);
375*4882a593Smuzhiyun
376*4882a593Smuzhiyun if (radeon_encoder->audio && radeon_encoder->audio->write_sad_regs)
377*4882a593Smuzhiyun radeon_encoder->audio->write_sad_regs(encoder, sads, sad_count);
378*4882a593Smuzhiyun
379*4882a593Smuzhiyun kfree(sads);
380*4882a593Smuzhiyun }
381*4882a593Smuzhiyun
radeon_audio_write_speaker_allocation(struct drm_encoder * encoder)382*4882a593Smuzhiyun static void radeon_audio_write_speaker_allocation(struct drm_encoder *encoder)
383*4882a593Smuzhiyun {
384*4882a593Smuzhiyun struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
385*4882a593Smuzhiyun struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
386*4882a593Smuzhiyun u8 *sadb = NULL;
387*4882a593Smuzhiyun int sad_count;
388*4882a593Smuzhiyun
389*4882a593Smuzhiyun if (!connector)
390*4882a593Smuzhiyun return;
391*4882a593Smuzhiyun
392*4882a593Smuzhiyun sad_count = drm_edid_to_speaker_allocation(radeon_connector_edid(connector),
393*4882a593Smuzhiyun &sadb);
394*4882a593Smuzhiyun if (sad_count < 0) {
395*4882a593Smuzhiyun DRM_DEBUG("Couldn't read Speaker Allocation Data Block: %d\n",
396*4882a593Smuzhiyun sad_count);
397*4882a593Smuzhiyun sad_count = 0;
398*4882a593Smuzhiyun }
399*4882a593Smuzhiyun
400*4882a593Smuzhiyun if (radeon_encoder->audio && radeon_encoder->audio->write_speaker_allocation)
401*4882a593Smuzhiyun radeon_encoder->audio->write_speaker_allocation(encoder, sadb, sad_count);
402*4882a593Smuzhiyun
403*4882a593Smuzhiyun kfree(sadb);
404*4882a593Smuzhiyun }
405*4882a593Smuzhiyun
radeon_audio_write_latency_fields(struct drm_encoder * encoder,struct drm_display_mode * mode)406*4882a593Smuzhiyun static void radeon_audio_write_latency_fields(struct drm_encoder *encoder,
407*4882a593Smuzhiyun struct drm_display_mode *mode)
408*4882a593Smuzhiyun {
409*4882a593Smuzhiyun struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
410*4882a593Smuzhiyun struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
411*4882a593Smuzhiyun
412*4882a593Smuzhiyun if (!connector)
413*4882a593Smuzhiyun return;
414*4882a593Smuzhiyun
415*4882a593Smuzhiyun if (radeon_encoder->audio && radeon_encoder->audio->write_latency_fields)
416*4882a593Smuzhiyun radeon_encoder->audio->write_latency_fields(encoder, connector, mode);
417*4882a593Smuzhiyun }
418*4882a593Smuzhiyun
radeon_audio_get_pin(struct drm_encoder * encoder)419*4882a593Smuzhiyun struct r600_audio_pin* radeon_audio_get_pin(struct drm_encoder *encoder)
420*4882a593Smuzhiyun {
421*4882a593Smuzhiyun struct radeon_device *rdev = encoder->dev->dev_private;
422*4882a593Smuzhiyun struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
423*4882a593Smuzhiyun
424*4882a593Smuzhiyun if (radeon_encoder->audio && radeon_encoder->audio->get_pin)
425*4882a593Smuzhiyun return radeon_encoder->audio->get_pin(rdev);
426*4882a593Smuzhiyun
427*4882a593Smuzhiyun return NULL;
428*4882a593Smuzhiyun }
429*4882a593Smuzhiyun
radeon_audio_select_pin(struct drm_encoder * encoder)430*4882a593Smuzhiyun static void radeon_audio_select_pin(struct drm_encoder *encoder)
431*4882a593Smuzhiyun {
432*4882a593Smuzhiyun struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
433*4882a593Smuzhiyun
434*4882a593Smuzhiyun if (radeon_encoder->audio && radeon_encoder->audio->select_pin)
435*4882a593Smuzhiyun radeon_encoder->audio->select_pin(encoder);
436*4882a593Smuzhiyun }
437*4882a593Smuzhiyun
radeon_audio_detect(struct drm_connector * connector,struct drm_encoder * encoder,enum drm_connector_status status)438*4882a593Smuzhiyun void radeon_audio_detect(struct drm_connector *connector,
439*4882a593Smuzhiyun struct drm_encoder *encoder,
440*4882a593Smuzhiyun enum drm_connector_status status)
441*4882a593Smuzhiyun {
442*4882a593Smuzhiyun struct drm_device *dev = connector->dev;
443*4882a593Smuzhiyun struct radeon_device *rdev = dev->dev_private;
444*4882a593Smuzhiyun struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
445*4882a593Smuzhiyun struct radeon_encoder_atom_dig *dig;
446*4882a593Smuzhiyun
447*4882a593Smuzhiyun if (!radeon_audio_chipset_supported(rdev))
448*4882a593Smuzhiyun return;
449*4882a593Smuzhiyun
450*4882a593Smuzhiyun if (!radeon_encoder_is_digital(encoder))
451*4882a593Smuzhiyun return;
452*4882a593Smuzhiyun
453*4882a593Smuzhiyun dig = radeon_encoder->enc_priv;
454*4882a593Smuzhiyun
455*4882a593Smuzhiyun if (status == connector_status_connected) {
456*4882a593Smuzhiyun if (connector->connector_type == DRM_MODE_CONNECTOR_DisplayPort) {
457*4882a593Smuzhiyun struct radeon_connector *radeon_connector = to_radeon_connector(connector);
458*4882a593Smuzhiyun
459*4882a593Smuzhiyun if (radeon_dp_getsinktype(radeon_connector) ==
460*4882a593Smuzhiyun CONNECTOR_OBJECT_ID_DISPLAYPORT)
461*4882a593Smuzhiyun radeon_encoder->audio = rdev->audio.dp_funcs;
462*4882a593Smuzhiyun else
463*4882a593Smuzhiyun radeon_encoder->audio = rdev->audio.hdmi_funcs;
464*4882a593Smuzhiyun } else {
465*4882a593Smuzhiyun radeon_encoder->audio = rdev->audio.hdmi_funcs;
466*4882a593Smuzhiyun }
467*4882a593Smuzhiyun
468*4882a593Smuzhiyun if (drm_detect_monitor_audio(radeon_connector_edid(connector))) {
469*4882a593Smuzhiyun if (!dig->pin)
470*4882a593Smuzhiyun dig->pin = radeon_audio_get_pin(encoder);
471*4882a593Smuzhiyun radeon_audio_enable(rdev, dig->pin, 0xf);
472*4882a593Smuzhiyun } else {
473*4882a593Smuzhiyun radeon_audio_enable(rdev, dig->pin, 0);
474*4882a593Smuzhiyun dig->pin = NULL;
475*4882a593Smuzhiyun }
476*4882a593Smuzhiyun } else {
477*4882a593Smuzhiyun radeon_audio_enable(rdev, dig->pin, 0);
478*4882a593Smuzhiyun dig->pin = NULL;
479*4882a593Smuzhiyun }
480*4882a593Smuzhiyun }
481*4882a593Smuzhiyun
radeon_audio_fini(struct radeon_device * rdev)482*4882a593Smuzhiyun void radeon_audio_fini(struct radeon_device *rdev)
483*4882a593Smuzhiyun {
484*4882a593Smuzhiyun int i;
485*4882a593Smuzhiyun
486*4882a593Smuzhiyun if (!rdev->audio.enabled)
487*4882a593Smuzhiyun return;
488*4882a593Smuzhiyun
489*4882a593Smuzhiyun for (i = 0; i < rdev->audio.num_pins; i++)
490*4882a593Smuzhiyun radeon_audio_enable(rdev, &rdev->audio.pin[i], 0);
491*4882a593Smuzhiyun
492*4882a593Smuzhiyun rdev->audio.enabled = false;
493*4882a593Smuzhiyun }
494*4882a593Smuzhiyun
radeon_audio_set_dto(struct drm_encoder * encoder,unsigned int clock)495*4882a593Smuzhiyun static void radeon_audio_set_dto(struct drm_encoder *encoder, unsigned int clock)
496*4882a593Smuzhiyun {
497*4882a593Smuzhiyun struct radeon_device *rdev = encoder->dev->dev_private;
498*4882a593Smuzhiyun struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
499*4882a593Smuzhiyun struct radeon_crtc *crtc = to_radeon_crtc(encoder->crtc);
500*4882a593Smuzhiyun
501*4882a593Smuzhiyun if (radeon_encoder->audio && radeon_encoder->audio->set_dto)
502*4882a593Smuzhiyun radeon_encoder->audio->set_dto(rdev, crtc, clock);
503*4882a593Smuzhiyun }
504*4882a593Smuzhiyun
radeon_audio_set_avi_packet(struct drm_encoder * encoder,struct drm_display_mode * mode)505*4882a593Smuzhiyun static int radeon_audio_set_avi_packet(struct drm_encoder *encoder,
506*4882a593Smuzhiyun struct drm_display_mode *mode)
507*4882a593Smuzhiyun {
508*4882a593Smuzhiyun struct radeon_device *rdev = encoder->dev->dev_private;
509*4882a593Smuzhiyun struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
510*4882a593Smuzhiyun struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
511*4882a593Smuzhiyun struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
512*4882a593Smuzhiyun u8 buffer[HDMI_INFOFRAME_HEADER_SIZE + HDMI_AVI_INFOFRAME_SIZE];
513*4882a593Smuzhiyun struct hdmi_avi_infoframe frame;
514*4882a593Smuzhiyun int err;
515*4882a593Smuzhiyun
516*4882a593Smuzhiyun if (!connector)
517*4882a593Smuzhiyun return -EINVAL;
518*4882a593Smuzhiyun
519*4882a593Smuzhiyun err = drm_hdmi_avi_infoframe_from_display_mode(&frame, connector, mode);
520*4882a593Smuzhiyun if (err < 0) {
521*4882a593Smuzhiyun DRM_ERROR("failed to setup AVI infoframe: %d\n", err);
522*4882a593Smuzhiyun return err;
523*4882a593Smuzhiyun }
524*4882a593Smuzhiyun
525*4882a593Smuzhiyun if (radeon_encoder->output_csc != RADEON_OUTPUT_CSC_BYPASS) {
526*4882a593Smuzhiyun drm_hdmi_avi_infoframe_quant_range(&frame, connector, mode,
527*4882a593Smuzhiyun radeon_encoder->output_csc == RADEON_OUTPUT_CSC_TVRGB ?
528*4882a593Smuzhiyun HDMI_QUANTIZATION_RANGE_LIMITED :
529*4882a593Smuzhiyun HDMI_QUANTIZATION_RANGE_FULL);
530*4882a593Smuzhiyun }
531*4882a593Smuzhiyun
532*4882a593Smuzhiyun err = hdmi_avi_infoframe_pack(&frame, buffer, sizeof(buffer));
533*4882a593Smuzhiyun if (err < 0) {
534*4882a593Smuzhiyun DRM_ERROR("failed to pack AVI infoframe: %d\n", err);
535*4882a593Smuzhiyun return err;
536*4882a593Smuzhiyun }
537*4882a593Smuzhiyun
538*4882a593Smuzhiyun if (dig && dig->afmt && radeon_encoder->audio &&
539*4882a593Smuzhiyun radeon_encoder->audio->set_avi_packet)
540*4882a593Smuzhiyun radeon_encoder->audio->set_avi_packet(rdev, dig->afmt->offset,
541*4882a593Smuzhiyun buffer, sizeof(buffer));
542*4882a593Smuzhiyun
543*4882a593Smuzhiyun return 0;
544*4882a593Smuzhiyun }
545*4882a593Smuzhiyun
546*4882a593Smuzhiyun /*
547*4882a593Smuzhiyun * calculate CTS and N values if they are not found in the table
548*4882a593Smuzhiyun */
radeon_audio_calc_cts(unsigned int clock,int * CTS,int * N,int freq)549*4882a593Smuzhiyun static void radeon_audio_calc_cts(unsigned int clock, int *CTS, int *N, int freq)
550*4882a593Smuzhiyun {
551*4882a593Smuzhiyun int n, cts;
552*4882a593Smuzhiyun unsigned long div, mul;
553*4882a593Smuzhiyun
554*4882a593Smuzhiyun /* Safe, but overly large values */
555*4882a593Smuzhiyun n = 128 * freq;
556*4882a593Smuzhiyun cts = clock * 1000;
557*4882a593Smuzhiyun
558*4882a593Smuzhiyun /* Smallest valid fraction */
559*4882a593Smuzhiyun div = gcd(n, cts);
560*4882a593Smuzhiyun
561*4882a593Smuzhiyun n /= div;
562*4882a593Smuzhiyun cts /= div;
563*4882a593Smuzhiyun
564*4882a593Smuzhiyun /*
565*4882a593Smuzhiyun * The optimal N is 128*freq/1000. Calculate the closest larger
566*4882a593Smuzhiyun * value that doesn't truncate any bits.
567*4882a593Smuzhiyun */
568*4882a593Smuzhiyun mul = ((128*freq/1000) + (n-1))/n;
569*4882a593Smuzhiyun
570*4882a593Smuzhiyun n *= mul;
571*4882a593Smuzhiyun cts *= mul;
572*4882a593Smuzhiyun
573*4882a593Smuzhiyun /* Check that we are in spec (not always possible) */
574*4882a593Smuzhiyun if (n < (128*freq/1500))
575*4882a593Smuzhiyun pr_warn("Calculated ACR N value is too small. You may experience audio problems.\n");
576*4882a593Smuzhiyun if (n > (128*freq/300))
577*4882a593Smuzhiyun pr_warn("Calculated ACR N value is too large. You may experience audio problems.\n");
578*4882a593Smuzhiyun
579*4882a593Smuzhiyun *N = n;
580*4882a593Smuzhiyun *CTS = cts;
581*4882a593Smuzhiyun
582*4882a593Smuzhiyun DRM_DEBUG("Calculated ACR timing N=%d CTS=%d for frequency %d\n",
583*4882a593Smuzhiyun *N, *CTS, freq);
584*4882a593Smuzhiyun }
585*4882a593Smuzhiyun
radeon_audio_acr(unsigned int clock)586*4882a593Smuzhiyun static const struct radeon_hdmi_acr* radeon_audio_acr(unsigned int clock)
587*4882a593Smuzhiyun {
588*4882a593Smuzhiyun static struct radeon_hdmi_acr res;
589*4882a593Smuzhiyun u8 i;
590*4882a593Smuzhiyun
591*4882a593Smuzhiyun static const struct radeon_hdmi_acr hdmi_predefined_acr[] = {
592*4882a593Smuzhiyun /* 32kHz 44.1kHz 48kHz */
593*4882a593Smuzhiyun /* Clock N CTS N CTS N CTS */
594*4882a593Smuzhiyun { 25175, 4096, 25175, 28224, 125875, 6144, 25175 }, /* 25,20/1.001 MHz */
595*4882a593Smuzhiyun { 25200, 4096, 25200, 6272, 28000, 6144, 25200 }, /* 25.20 MHz */
596*4882a593Smuzhiyun { 27000, 4096, 27000, 6272, 30000, 6144, 27000 }, /* 27.00 MHz */
597*4882a593Smuzhiyun { 27027, 4096, 27027, 6272, 30030, 6144, 27027 }, /* 27.00*1.001 MHz */
598*4882a593Smuzhiyun { 54000, 4096, 54000, 6272, 60000, 6144, 54000 }, /* 54.00 MHz */
599*4882a593Smuzhiyun { 54054, 4096, 54054, 6272, 60060, 6144, 54054 }, /* 54.00*1.001 MHz */
600*4882a593Smuzhiyun { 74176, 4096, 74176, 5733, 75335, 6144, 74176 }, /* 74.25/1.001 MHz */
601*4882a593Smuzhiyun { 74250, 4096, 74250, 6272, 82500, 6144, 74250 }, /* 74.25 MHz */
602*4882a593Smuzhiyun { 148352, 4096, 148352, 5733, 150670, 6144, 148352 }, /* 148.50/1.001 MHz */
603*4882a593Smuzhiyun { 148500, 4096, 148500, 6272, 165000, 6144, 148500 }, /* 148.50 MHz */
604*4882a593Smuzhiyun };
605*4882a593Smuzhiyun
606*4882a593Smuzhiyun /* Precalculated values for common clocks */
607*4882a593Smuzhiyun for (i = 0; i < ARRAY_SIZE(hdmi_predefined_acr); i++)
608*4882a593Smuzhiyun if (hdmi_predefined_acr[i].clock == clock)
609*4882a593Smuzhiyun return &hdmi_predefined_acr[i];
610*4882a593Smuzhiyun
611*4882a593Smuzhiyun /* And odd clocks get manually calculated */
612*4882a593Smuzhiyun radeon_audio_calc_cts(clock, &res.cts_32khz, &res.n_32khz, 32000);
613*4882a593Smuzhiyun radeon_audio_calc_cts(clock, &res.cts_44_1khz, &res.n_44_1khz, 44100);
614*4882a593Smuzhiyun radeon_audio_calc_cts(clock, &res.cts_48khz, &res.n_48khz, 48000);
615*4882a593Smuzhiyun
616*4882a593Smuzhiyun return &res;
617*4882a593Smuzhiyun }
618*4882a593Smuzhiyun
619*4882a593Smuzhiyun /*
620*4882a593Smuzhiyun * update the N and CTS parameters for a given pixel clock rate
621*4882a593Smuzhiyun */
radeon_audio_update_acr(struct drm_encoder * encoder,unsigned int clock)622*4882a593Smuzhiyun static void radeon_audio_update_acr(struct drm_encoder *encoder, unsigned int clock)
623*4882a593Smuzhiyun {
624*4882a593Smuzhiyun const struct radeon_hdmi_acr *acr = radeon_audio_acr(clock);
625*4882a593Smuzhiyun struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
626*4882a593Smuzhiyun struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
627*4882a593Smuzhiyun
628*4882a593Smuzhiyun if (!dig || !dig->afmt)
629*4882a593Smuzhiyun return;
630*4882a593Smuzhiyun
631*4882a593Smuzhiyun if (radeon_encoder->audio && radeon_encoder->audio->update_acr)
632*4882a593Smuzhiyun radeon_encoder->audio->update_acr(encoder, dig->afmt->offset, acr);
633*4882a593Smuzhiyun }
634*4882a593Smuzhiyun
radeon_audio_set_vbi_packet(struct drm_encoder * encoder)635*4882a593Smuzhiyun static void radeon_audio_set_vbi_packet(struct drm_encoder *encoder)
636*4882a593Smuzhiyun {
637*4882a593Smuzhiyun struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
638*4882a593Smuzhiyun struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
639*4882a593Smuzhiyun
640*4882a593Smuzhiyun if (!dig || !dig->afmt)
641*4882a593Smuzhiyun return;
642*4882a593Smuzhiyun
643*4882a593Smuzhiyun if (radeon_encoder->audio && radeon_encoder->audio->set_vbi_packet)
644*4882a593Smuzhiyun radeon_encoder->audio->set_vbi_packet(encoder, dig->afmt->offset);
645*4882a593Smuzhiyun }
646*4882a593Smuzhiyun
radeon_hdmi_set_color_depth(struct drm_encoder * encoder)647*4882a593Smuzhiyun static void radeon_hdmi_set_color_depth(struct drm_encoder *encoder)
648*4882a593Smuzhiyun {
649*4882a593Smuzhiyun int bpc = 8;
650*4882a593Smuzhiyun struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
651*4882a593Smuzhiyun struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
652*4882a593Smuzhiyun
653*4882a593Smuzhiyun if (!dig || !dig->afmt)
654*4882a593Smuzhiyun return;
655*4882a593Smuzhiyun
656*4882a593Smuzhiyun if (encoder->crtc) {
657*4882a593Smuzhiyun struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
658*4882a593Smuzhiyun bpc = radeon_crtc->bpc;
659*4882a593Smuzhiyun }
660*4882a593Smuzhiyun
661*4882a593Smuzhiyun if (radeon_encoder->audio && radeon_encoder->audio->set_color_depth)
662*4882a593Smuzhiyun radeon_encoder->audio->set_color_depth(encoder, dig->afmt->offset, bpc);
663*4882a593Smuzhiyun }
664*4882a593Smuzhiyun
radeon_audio_set_audio_packet(struct drm_encoder * encoder)665*4882a593Smuzhiyun static void radeon_audio_set_audio_packet(struct drm_encoder *encoder)
666*4882a593Smuzhiyun {
667*4882a593Smuzhiyun struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
668*4882a593Smuzhiyun struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
669*4882a593Smuzhiyun
670*4882a593Smuzhiyun if (!dig || !dig->afmt)
671*4882a593Smuzhiyun return;
672*4882a593Smuzhiyun
673*4882a593Smuzhiyun if (radeon_encoder->audio && radeon_encoder->audio->set_audio_packet)
674*4882a593Smuzhiyun radeon_encoder->audio->set_audio_packet(encoder, dig->afmt->offset);
675*4882a593Smuzhiyun }
676*4882a593Smuzhiyun
radeon_audio_set_mute(struct drm_encoder * encoder,bool mute)677*4882a593Smuzhiyun static void radeon_audio_set_mute(struct drm_encoder *encoder, bool mute)
678*4882a593Smuzhiyun {
679*4882a593Smuzhiyun struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
680*4882a593Smuzhiyun struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
681*4882a593Smuzhiyun
682*4882a593Smuzhiyun if (!dig || !dig->afmt)
683*4882a593Smuzhiyun return;
684*4882a593Smuzhiyun
685*4882a593Smuzhiyun if (radeon_encoder->audio && radeon_encoder->audio->set_mute)
686*4882a593Smuzhiyun radeon_encoder->audio->set_mute(encoder, dig->afmt->offset, mute);
687*4882a593Smuzhiyun }
688*4882a593Smuzhiyun
689*4882a593Smuzhiyun /*
690*4882a593Smuzhiyun * update the info frames with the data from the current display mode
691*4882a593Smuzhiyun */
radeon_audio_hdmi_mode_set(struct drm_encoder * encoder,struct drm_display_mode * mode)692*4882a593Smuzhiyun static void radeon_audio_hdmi_mode_set(struct drm_encoder *encoder,
693*4882a593Smuzhiyun struct drm_display_mode *mode)
694*4882a593Smuzhiyun {
695*4882a593Smuzhiyun struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
696*4882a593Smuzhiyun struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
697*4882a593Smuzhiyun struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
698*4882a593Smuzhiyun
699*4882a593Smuzhiyun if (!dig || !dig->afmt)
700*4882a593Smuzhiyun return;
701*4882a593Smuzhiyun
702*4882a593Smuzhiyun if (!connector)
703*4882a593Smuzhiyun return;
704*4882a593Smuzhiyun
705*4882a593Smuzhiyun if (drm_detect_monitor_audio(radeon_connector_edid(connector))) {
706*4882a593Smuzhiyun radeon_audio_set_mute(encoder, true);
707*4882a593Smuzhiyun
708*4882a593Smuzhiyun radeon_audio_write_speaker_allocation(encoder);
709*4882a593Smuzhiyun radeon_audio_write_sad_regs(encoder);
710*4882a593Smuzhiyun radeon_audio_write_latency_fields(encoder, mode);
711*4882a593Smuzhiyun radeon_audio_set_dto(encoder, mode->clock);
712*4882a593Smuzhiyun radeon_audio_set_vbi_packet(encoder);
713*4882a593Smuzhiyun radeon_hdmi_set_color_depth(encoder);
714*4882a593Smuzhiyun radeon_audio_update_acr(encoder, mode->clock);
715*4882a593Smuzhiyun radeon_audio_set_audio_packet(encoder);
716*4882a593Smuzhiyun radeon_audio_select_pin(encoder);
717*4882a593Smuzhiyun
718*4882a593Smuzhiyun if (radeon_audio_set_avi_packet(encoder, mode) < 0)
719*4882a593Smuzhiyun return;
720*4882a593Smuzhiyun
721*4882a593Smuzhiyun radeon_audio_set_mute(encoder, false);
722*4882a593Smuzhiyun } else {
723*4882a593Smuzhiyun radeon_hdmi_set_color_depth(encoder);
724*4882a593Smuzhiyun
725*4882a593Smuzhiyun if (radeon_audio_set_avi_packet(encoder, mode) < 0)
726*4882a593Smuzhiyun return;
727*4882a593Smuzhiyun }
728*4882a593Smuzhiyun }
729*4882a593Smuzhiyun
radeon_audio_dp_mode_set(struct drm_encoder * encoder,struct drm_display_mode * mode)730*4882a593Smuzhiyun static void radeon_audio_dp_mode_set(struct drm_encoder *encoder,
731*4882a593Smuzhiyun struct drm_display_mode *mode)
732*4882a593Smuzhiyun {
733*4882a593Smuzhiyun struct drm_device *dev = encoder->dev;
734*4882a593Smuzhiyun struct radeon_device *rdev = dev->dev_private;
735*4882a593Smuzhiyun struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
736*4882a593Smuzhiyun struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
737*4882a593Smuzhiyun struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
738*4882a593Smuzhiyun
739*4882a593Smuzhiyun if (!dig || !dig->afmt)
740*4882a593Smuzhiyun return;
741*4882a593Smuzhiyun
742*4882a593Smuzhiyun if (!connector)
743*4882a593Smuzhiyun return;
744*4882a593Smuzhiyun
745*4882a593Smuzhiyun if (drm_detect_monitor_audio(radeon_connector_edid(connector))) {
746*4882a593Smuzhiyun radeon_audio_write_speaker_allocation(encoder);
747*4882a593Smuzhiyun radeon_audio_write_sad_regs(encoder);
748*4882a593Smuzhiyun radeon_audio_write_latency_fields(encoder, mode);
749*4882a593Smuzhiyun radeon_audio_set_dto(encoder, rdev->clock.vco_freq * 10);
750*4882a593Smuzhiyun radeon_audio_set_audio_packet(encoder);
751*4882a593Smuzhiyun radeon_audio_select_pin(encoder);
752*4882a593Smuzhiyun
753*4882a593Smuzhiyun if (radeon_audio_set_avi_packet(encoder, mode) < 0)
754*4882a593Smuzhiyun return;
755*4882a593Smuzhiyun }
756*4882a593Smuzhiyun }
757*4882a593Smuzhiyun
radeon_audio_mode_set(struct drm_encoder * encoder,struct drm_display_mode * mode)758*4882a593Smuzhiyun void radeon_audio_mode_set(struct drm_encoder *encoder,
759*4882a593Smuzhiyun struct drm_display_mode *mode)
760*4882a593Smuzhiyun {
761*4882a593Smuzhiyun struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
762*4882a593Smuzhiyun
763*4882a593Smuzhiyun if (radeon_encoder->audio && radeon_encoder->audio->mode_set)
764*4882a593Smuzhiyun radeon_encoder->audio->mode_set(encoder, mode);
765*4882a593Smuzhiyun }
766*4882a593Smuzhiyun
radeon_audio_dpms(struct drm_encoder * encoder,int mode)767*4882a593Smuzhiyun void radeon_audio_dpms(struct drm_encoder *encoder, int mode)
768*4882a593Smuzhiyun {
769*4882a593Smuzhiyun struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
770*4882a593Smuzhiyun
771*4882a593Smuzhiyun if (radeon_encoder->audio && radeon_encoder->audio->dpms)
772*4882a593Smuzhiyun radeon_encoder->audio->dpms(encoder, mode == DRM_MODE_DPMS_ON);
773*4882a593Smuzhiyun }
774*4882a593Smuzhiyun
radeon_audio_decode_dfs_div(unsigned int div)775*4882a593Smuzhiyun unsigned int radeon_audio_decode_dfs_div(unsigned int div)
776*4882a593Smuzhiyun {
777*4882a593Smuzhiyun if (div >= 8 && div < 64)
778*4882a593Smuzhiyun return (div - 8) * 25 + 200;
779*4882a593Smuzhiyun else if (div >= 64 && div < 96)
780*4882a593Smuzhiyun return (div - 64) * 50 + 1600;
781*4882a593Smuzhiyun else if (div >= 96 && div < 128)
782*4882a593Smuzhiyun return (div - 96) * 100 + 3200;
783*4882a593Smuzhiyun else
784*4882a593Smuzhiyun return 0;
785*4882a593Smuzhiyun }
786