1254885Sdumbbell/*
2254885Sdumbbell * Copyright 2008 Advanced Micro Devices, Inc.
3254885Sdumbbell * Copyright 2008 Red Hat Inc.
4254885Sdumbbell * Copyright 2009 Christian K��nig.
5254885Sdumbbell *
6254885Sdumbbell * Permission is hereby granted, free of charge, to any person obtaining a
7254885Sdumbbell * copy of this software and associated documentation files (the "Software"),
8254885Sdumbbell * to deal in the Software without restriction, including without limitation
9254885Sdumbbell * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10254885Sdumbbell * and/or sell copies of the Software, and to permit persons to whom the
11254885Sdumbbell * Software is furnished to do so, subject to the following conditions:
12254885Sdumbbell *
13254885Sdumbbell * The above copyright notice and this permission notice shall be included in
14254885Sdumbbell * all copies or substantial portions of the Software.
15254885Sdumbbell *
16254885Sdumbbell * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17254885Sdumbbell * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18254885Sdumbbell * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19254885Sdumbbell * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
20254885Sdumbbell * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21254885Sdumbbell * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22254885Sdumbbell * OTHER DEALINGS IN THE SOFTWARE.
23254885Sdumbbell *
24254885Sdumbbell * Authors: Christian K��nig
25254885Sdumbbell */
26254885Sdumbbell
27254885Sdumbbell#include <sys/cdefs.h>
28254885Sdumbbell__FBSDID("$FreeBSD$");
29254885Sdumbbell
30254885Sdumbbell#include <dev/drm2/drmP.h>
31254885Sdumbbell#include <dev/drm2/radeon/radeon_drm.h>
32254885Sdumbbell#include "radeon.h"
33254885Sdumbbell#include "radeon_asic.h"
34254885Sdumbbell#include "r600d.h"
35254885Sdumbbell#include "atom.h"
36254885Sdumbbell
37254885Sdumbbell/*
38254885Sdumbbell * HDMI color format
39254885Sdumbbell */
40254885Sdumbbellenum r600_hdmi_color_format {
41254885Sdumbbell	RGB = 0,
42254885Sdumbbell	YCC_422 = 1,
43254885Sdumbbell	YCC_444 = 2
44254885Sdumbbell};
45254885Sdumbbell
46254885Sdumbbell/*
47254885Sdumbbell * IEC60958 status bits
48254885Sdumbbell */
49254885Sdumbbellenum r600_hdmi_iec_status_bits {
50254885Sdumbbell	AUDIO_STATUS_DIG_ENABLE   = 0x01,
51254885Sdumbbell	AUDIO_STATUS_V            = 0x02,
52254885Sdumbbell	AUDIO_STATUS_VCFG         = 0x04,
53254885Sdumbbell	AUDIO_STATUS_EMPHASIS     = 0x08,
54254885Sdumbbell	AUDIO_STATUS_COPYRIGHT    = 0x10,
55254885Sdumbbell	AUDIO_STATUS_NONAUDIO     = 0x20,
56254885Sdumbbell	AUDIO_STATUS_PROFESSIONAL = 0x40,
57254885Sdumbbell	AUDIO_STATUS_LEVEL        = 0x80
58254885Sdumbbell};
59254885Sdumbbell
60254885Sdumbbellstatic const struct radeon_hdmi_acr r600_hdmi_predefined_acr[] = {
61254885Sdumbbell    /*	     32kHz	  44.1kHz	48kHz    */
62254885Sdumbbell    /* Clock      N     CTS      N     CTS      N     CTS */
63254885Sdumbbell    {  25174,  4576,  28125,  7007,  31250,  6864,  28125 }, /*  25,20/1.001 MHz */
64254885Sdumbbell    {  25200,  4096,  25200,  6272,  28000,  6144,  25200 }, /*  25.20       MHz */
65254885Sdumbbell    {  27000,  4096,  27000,  6272,  30000,  6144,  27000 }, /*  27.00       MHz */
66254885Sdumbbell    {  27027,  4096,  27027,  6272,  30030,  6144,  27027 }, /*  27.00*1.001 MHz */
67254885Sdumbbell    {  54000,  4096,  54000,  6272,  60000,  6144,  54000 }, /*  54.00       MHz */
68254885Sdumbbell    {  54054,  4096,  54054,  6272,  60060,  6144,  54054 }, /*  54.00*1.001 MHz */
69254885Sdumbbell    {  74175, 11648, 210937, 17836, 234375, 11648, 140625 }, /*  74.25/1.001 MHz */
70254885Sdumbbell    {  74250,  4096,  74250,  6272,  82500,  6144,  74250 }, /*  74.25       MHz */
71254885Sdumbbell    { 148351, 11648, 421875,  8918, 234375,  5824, 140625 }, /* 148.50/1.001 MHz */
72254885Sdumbbell    { 148500,  4096, 148500,  6272, 165000,  6144, 148500 }, /* 148.50       MHz */
73254885Sdumbbell    {      0,  4096,      0,  6272,      0,  6144,      0 }  /* Other */
74254885Sdumbbell};
75254885Sdumbbell
76254885Sdumbbell/*
77254885Sdumbbell * calculate CTS value if it's not found in the table
78254885Sdumbbell */
79254885Sdumbbellstatic void r600_hdmi_calc_cts(uint32_t clock, int *CTS, int N, int freq)
80254885Sdumbbell{
81254885Sdumbbell	if (*CTS == 0)
82254885Sdumbbell		*CTS = clock * N / (128 * freq) * 1000;
83254885Sdumbbell	DRM_DEBUG("Using ACR timing N=%d CTS=%d for frequency %d\n",
84254885Sdumbbell		  N, *CTS, freq);
85254885Sdumbbell}
86254885Sdumbbell
87254885Sdumbbellstruct radeon_hdmi_acr r600_hdmi_acr(uint32_t clock)
88254885Sdumbbell{
89254885Sdumbbell	struct radeon_hdmi_acr res;
90254885Sdumbbell	u8 i;
91254885Sdumbbell
92254885Sdumbbell	for (i = 0; r600_hdmi_predefined_acr[i].clock != clock &&
93254885Sdumbbell	     r600_hdmi_predefined_acr[i].clock != 0; i++)
94254885Sdumbbell		;
95254885Sdumbbell	res = r600_hdmi_predefined_acr[i];
96254885Sdumbbell
97254885Sdumbbell	/* In case some CTS are missing */
98254885Sdumbbell	r600_hdmi_calc_cts(clock, &res.cts_32khz, res.n_32khz, 32000);
99254885Sdumbbell	r600_hdmi_calc_cts(clock, &res.cts_44_1khz, res.n_44_1khz, 44100);
100254885Sdumbbell	r600_hdmi_calc_cts(clock, &res.cts_48khz, res.n_48khz, 48000);
101254885Sdumbbell
102254885Sdumbbell	return res;
103254885Sdumbbell}
104254885Sdumbbell
105254885Sdumbbell/*
106254885Sdumbbell * update the N and CTS parameters for a given pixel clock rate
107254885Sdumbbell */
108254885Sdumbbellstatic void r600_hdmi_update_ACR(struct drm_encoder *encoder, uint32_t clock)
109254885Sdumbbell{
110254885Sdumbbell	struct drm_device *dev = encoder->dev;
111254885Sdumbbell	struct radeon_device *rdev = dev->dev_private;
112254885Sdumbbell	struct radeon_hdmi_acr acr = r600_hdmi_acr(clock);
113254885Sdumbbell	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
114254885Sdumbbell	struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
115254885Sdumbbell	uint32_t offset = dig->afmt->offset;
116254885Sdumbbell
117254885Sdumbbell	WREG32(HDMI0_ACR_32_0 + offset, HDMI0_ACR_CTS_32(acr.cts_32khz));
118254885Sdumbbell	WREG32(HDMI0_ACR_32_1 + offset, acr.n_32khz);
119254885Sdumbbell
120254885Sdumbbell	WREG32(HDMI0_ACR_44_0 + offset, HDMI0_ACR_CTS_44(acr.cts_44_1khz));
121254885Sdumbbell	WREG32(HDMI0_ACR_44_1 + offset, acr.n_44_1khz);
122254885Sdumbbell
123254885Sdumbbell	WREG32(HDMI0_ACR_48_0 + offset, HDMI0_ACR_CTS_48(acr.cts_48khz));
124254885Sdumbbell	WREG32(HDMI0_ACR_48_1 + offset, acr.n_48khz);
125254885Sdumbbell}
126254885Sdumbbell
127254885Sdumbbell/*
128254885Sdumbbell * calculate the crc for a given info frame
129254885Sdumbbell */
130254885Sdumbbellstatic void r600_hdmi_infoframe_checksum(uint8_t packetType,
131254885Sdumbbell					 uint8_t versionNumber,
132254885Sdumbbell					 uint8_t length,
133254885Sdumbbell					 uint8_t *frame)
134254885Sdumbbell{
135254885Sdumbbell	int i;
136254885Sdumbbell	frame[0] = packetType + versionNumber + length;
137254885Sdumbbell	for (i = 1; i <= length; i++)
138254885Sdumbbell		frame[0] += frame[i];
139254885Sdumbbell	frame[0] = 0x100 - frame[0];
140254885Sdumbbell}
141254885Sdumbbell
142254885Sdumbbell/*
143254885Sdumbbell * build a HDMI Video Info Frame
144254885Sdumbbell */
145254885Sdumbbellstatic void r600_hdmi_videoinfoframe(
146254885Sdumbbell	struct drm_encoder *encoder,
147254885Sdumbbell	enum r600_hdmi_color_format color_format,
148254885Sdumbbell	int active_information_present,
149254885Sdumbbell	uint8_t active_format_aspect_ratio,
150254885Sdumbbell	uint8_t scan_information,
151254885Sdumbbell	uint8_t colorimetry,
152254885Sdumbbell	uint8_t ex_colorimetry,
153254885Sdumbbell	uint8_t quantization,
154254885Sdumbbell	int ITC,
155254885Sdumbbell	uint8_t picture_aspect_ratio,
156254885Sdumbbell	uint8_t video_format_identification,
157254885Sdumbbell	uint8_t pixel_repetition,
158254885Sdumbbell	uint8_t non_uniform_picture_scaling,
159254885Sdumbbell	uint8_t bar_info_data_valid,
160254885Sdumbbell	uint16_t top_bar,
161254885Sdumbbell	uint16_t bottom_bar,
162254885Sdumbbell	uint16_t left_bar,
163254885Sdumbbell	uint16_t right_bar
164254885Sdumbbell)
165254885Sdumbbell{
166254885Sdumbbell	struct drm_device *dev = encoder->dev;
167254885Sdumbbell	struct radeon_device *rdev = dev->dev_private;
168254885Sdumbbell	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
169254885Sdumbbell	struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
170254885Sdumbbell	uint32_t offset = dig->afmt->offset;
171254885Sdumbbell
172254885Sdumbbell	uint8_t frame[14];
173254885Sdumbbell
174254885Sdumbbell	frame[0x0] = 0;
175254885Sdumbbell	frame[0x1] =
176254885Sdumbbell		(scan_information & 0x3) |
177254885Sdumbbell		((bar_info_data_valid & 0x3) << 2) |
178254885Sdumbbell		((active_information_present & 0x1) << 4) |
179254885Sdumbbell		((color_format & 0x3) << 5);
180254885Sdumbbell	frame[0x2] =
181254885Sdumbbell		(active_format_aspect_ratio & 0xF) |
182254885Sdumbbell		((picture_aspect_ratio & 0x3) << 4) |
183254885Sdumbbell		((colorimetry & 0x3) << 6);
184254885Sdumbbell	frame[0x3] =
185254885Sdumbbell		(non_uniform_picture_scaling & 0x3) |
186254885Sdumbbell		((quantization & 0x3) << 2) |
187254885Sdumbbell		((ex_colorimetry & 0x7) << 4) |
188254885Sdumbbell		((ITC & 0x1) << 7);
189254885Sdumbbell	frame[0x4] = (video_format_identification & 0x7F);
190254885Sdumbbell	frame[0x5] = (pixel_repetition & 0xF);
191254885Sdumbbell	frame[0x6] = (top_bar & 0xFF);
192254885Sdumbbell	frame[0x7] = (top_bar >> 8);
193254885Sdumbbell	frame[0x8] = (bottom_bar & 0xFF);
194254885Sdumbbell	frame[0x9] = (bottom_bar >> 8);
195254885Sdumbbell	frame[0xA] = (left_bar & 0xFF);
196254885Sdumbbell	frame[0xB] = (left_bar >> 8);
197254885Sdumbbell	frame[0xC] = (right_bar & 0xFF);
198254885Sdumbbell	frame[0xD] = (right_bar >> 8);
199254885Sdumbbell
200254885Sdumbbell	r600_hdmi_infoframe_checksum(0x82, 0x02, 0x0D, frame);
201254885Sdumbbell	/* Our header values (type, version, length) should be alright, Intel
202254885Sdumbbell	 * is using the same. Checksum function also seems to be OK, it works
203254885Sdumbbell	 * fine for audio infoframe. However calculated value is always lower
204254885Sdumbbell	 * by 2 in comparison to fglrx. It breaks displaying anything in case
205254885Sdumbbell	 * of TVs that strictly check the checksum. Hack it manually here to
206254885Sdumbbell	 * workaround this issue. */
207254885Sdumbbell	frame[0x0] += 2;
208254885Sdumbbell
209254885Sdumbbell	WREG32(HDMI0_AVI_INFO0 + offset,
210254885Sdumbbell		frame[0x0] | (frame[0x1] << 8) | (frame[0x2] << 16) | (frame[0x3] << 24));
211254885Sdumbbell	WREG32(HDMI0_AVI_INFO1 + offset,
212254885Sdumbbell		frame[0x4] | (frame[0x5] << 8) | (frame[0x6] << 16) | (frame[0x7] << 24));
213254885Sdumbbell	WREG32(HDMI0_AVI_INFO2 + offset,
214254885Sdumbbell		frame[0x8] | (frame[0x9] << 8) | (frame[0xA] << 16) | (frame[0xB] << 24));
215254885Sdumbbell	WREG32(HDMI0_AVI_INFO3 + offset,
216254885Sdumbbell		frame[0xC] | (frame[0xD] << 8));
217254885Sdumbbell}
218254885Sdumbbell
219254885Sdumbbell/*
220254885Sdumbbell * build a Audio Info Frame
221254885Sdumbbell */
222254885Sdumbbellstatic void r600_hdmi_audioinfoframe(
223254885Sdumbbell	struct drm_encoder *encoder,
224254885Sdumbbell	uint8_t channel_count,
225254885Sdumbbell	uint8_t coding_type,
226254885Sdumbbell	uint8_t sample_size,
227254885Sdumbbell	uint8_t sample_frequency,
228254885Sdumbbell	uint8_t format,
229254885Sdumbbell	uint8_t channel_allocation,
230254885Sdumbbell	uint8_t level_shift,
231254885Sdumbbell	int downmix_inhibit
232254885Sdumbbell)
233254885Sdumbbell{
234254885Sdumbbell	struct drm_device *dev = encoder->dev;
235254885Sdumbbell	struct radeon_device *rdev = dev->dev_private;
236254885Sdumbbell	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
237254885Sdumbbell	struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
238254885Sdumbbell	uint32_t offset = dig->afmt->offset;
239254885Sdumbbell
240254885Sdumbbell	uint8_t frame[11];
241254885Sdumbbell
242254885Sdumbbell	frame[0x0] = 0;
243254885Sdumbbell	frame[0x1] = (channel_count & 0x7) | ((coding_type & 0xF) << 4);
244254885Sdumbbell	frame[0x2] = (sample_size & 0x3) | ((sample_frequency & 0x7) << 2);
245254885Sdumbbell	frame[0x3] = format;
246254885Sdumbbell	frame[0x4] = channel_allocation;
247254885Sdumbbell	frame[0x5] = ((level_shift & 0xF) << 3) | ((downmix_inhibit & 0x1) << 7);
248254885Sdumbbell	frame[0x6] = 0;
249254885Sdumbbell	frame[0x7] = 0;
250254885Sdumbbell	frame[0x8] = 0;
251254885Sdumbbell	frame[0x9] = 0;
252254885Sdumbbell	frame[0xA] = 0;
253254885Sdumbbell
254254885Sdumbbell	r600_hdmi_infoframe_checksum(0x84, 0x01, 0x0A, frame);
255254885Sdumbbell
256254885Sdumbbell	WREG32(HDMI0_AUDIO_INFO0 + offset,
257254885Sdumbbell		frame[0x0] | (frame[0x1] << 8) | (frame[0x2] << 16) | (frame[0x3] << 24));
258254885Sdumbbell	WREG32(HDMI0_AUDIO_INFO1 + offset,
259254885Sdumbbell		frame[0x4] | (frame[0x5] << 8) | (frame[0x6] << 16) | (frame[0x8] << 24));
260254885Sdumbbell}
261254885Sdumbbell
262254885Sdumbbell/*
263254885Sdumbbell * test if audio buffer is filled enough to start playing
264254885Sdumbbell */
265254885Sdumbbellstatic bool r600_hdmi_is_audio_buffer_filled(struct drm_encoder *encoder)
266254885Sdumbbell{
267254885Sdumbbell	struct drm_device *dev = encoder->dev;
268254885Sdumbbell	struct radeon_device *rdev = dev->dev_private;
269254885Sdumbbell	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
270254885Sdumbbell	struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
271254885Sdumbbell	uint32_t offset = dig->afmt->offset;
272254885Sdumbbell
273254885Sdumbbell	return (RREG32(HDMI0_STATUS + offset) & 0x10) != 0;
274254885Sdumbbell}
275254885Sdumbbell
276254885Sdumbbell/*
277254885Sdumbbell * have buffer status changed since last call?
278254885Sdumbbell */
279254885Sdumbbellint r600_hdmi_buffer_status_changed(struct drm_encoder *encoder)
280254885Sdumbbell{
281254885Sdumbbell	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
282254885Sdumbbell	struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
283254885Sdumbbell	int status, result;
284254885Sdumbbell
285254885Sdumbbell	if (!dig->afmt || !dig->afmt->enabled)
286254885Sdumbbell		return 0;
287254885Sdumbbell
288254885Sdumbbell	status = r600_hdmi_is_audio_buffer_filled(encoder);
289254885Sdumbbell	result = dig->afmt->last_buffer_filled_status != status;
290254885Sdumbbell	dig->afmt->last_buffer_filled_status = status;
291254885Sdumbbell
292254885Sdumbbell	return result;
293254885Sdumbbell}
294254885Sdumbbell
295254885Sdumbbell/*
296254885Sdumbbell * write the audio workaround status to the hardware
297254885Sdumbbell */
298254885Sdumbbellstatic void r600_hdmi_audio_workaround(struct drm_encoder *encoder)
299254885Sdumbbell{
300254885Sdumbbell	struct drm_device *dev = encoder->dev;
301254885Sdumbbell	struct radeon_device *rdev = dev->dev_private;
302254885Sdumbbell	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
303254885Sdumbbell	struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
304254885Sdumbbell	uint32_t offset = dig->afmt->offset;
305254885Sdumbbell	bool hdmi_audio_workaround = false; /* FIXME */
306254885Sdumbbell	u32 value;
307254885Sdumbbell
308254885Sdumbbell	if (!hdmi_audio_workaround ||
309254885Sdumbbell	    r600_hdmi_is_audio_buffer_filled(encoder))
310254885Sdumbbell		value = 0; /* disable workaround */
311254885Sdumbbell	else
312254885Sdumbbell		value = HDMI0_AUDIO_TEST_EN; /* enable workaround */
313254885Sdumbbell	WREG32_P(HDMI0_AUDIO_PACKET_CONTROL + offset,
314254885Sdumbbell		 value, ~HDMI0_AUDIO_TEST_EN);
315254885Sdumbbell}
316254885Sdumbbell
317254885Sdumbbell
318254885Sdumbbell/*
319254885Sdumbbell * update the info frames with the data from the current display mode
320254885Sdumbbell */
321254885Sdumbbellvoid r600_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode *mode)
322254885Sdumbbell{
323254885Sdumbbell	struct drm_device *dev = encoder->dev;
324254885Sdumbbell	struct radeon_device *rdev = dev->dev_private;
325254885Sdumbbell	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
326254885Sdumbbell	struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
327254885Sdumbbell	uint32_t offset;
328254885Sdumbbell
329254885Sdumbbell	/* Silent, r600_hdmi_enable will raise WARN for us */
330254885Sdumbbell	if (!dig->afmt->enabled)
331254885Sdumbbell		return;
332254885Sdumbbell	offset = dig->afmt->offset;
333254885Sdumbbell
334254885Sdumbbell	r600_audio_set_clock(encoder, mode->clock);
335254885Sdumbbell
336254885Sdumbbell	WREG32(HDMI0_VBI_PACKET_CONTROL + offset,
337254885Sdumbbell	       HDMI0_NULL_SEND); /* send null packets when required */
338254885Sdumbbell
339254885Sdumbbell	WREG32(HDMI0_AUDIO_CRC_CONTROL + offset, 0x1000);
340254885Sdumbbell
341254885Sdumbbell	if (ASIC_IS_DCE32(rdev)) {
342254885Sdumbbell		WREG32(HDMI0_AUDIO_PACKET_CONTROL + offset,
343254885Sdumbbell		       HDMI0_AUDIO_DELAY_EN(1) | /* default audio delay */
344254885Sdumbbell		       HDMI0_AUDIO_PACKETS_PER_LINE(3)); /* should be suffient for all audio modes and small enough for all hblanks */
345254885Sdumbbell		WREG32(AFMT_AUDIO_PACKET_CONTROL + offset,
346254885Sdumbbell		       AFMT_AUDIO_SAMPLE_SEND | /* send audio packets */
347254885Sdumbbell		       AFMT_60958_CS_UPDATE); /* allow 60958 channel status fields to be updated */
348254885Sdumbbell	} else {
349254885Sdumbbell		WREG32(HDMI0_AUDIO_PACKET_CONTROL + offset,
350254885Sdumbbell		       HDMI0_AUDIO_SAMPLE_SEND | /* send audio packets */
351254885Sdumbbell		       HDMI0_AUDIO_DELAY_EN(1) | /* default audio delay */
352254885Sdumbbell		       HDMI0_AUDIO_PACKETS_PER_LINE(3) | /* should be suffient for all audio modes and small enough for all hblanks */
353254885Sdumbbell		       HDMI0_60958_CS_UPDATE); /* allow 60958 channel status fields to be updated */
354254885Sdumbbell	}
355254885Sdumbbell
356254885Sdumbbell	WREG32(HDMI0_ACR_PACKET_CONTROL + offset,
357254885Sdumbbell	       HDMI0_ACR_AUTO_SEND | /* allow hw to sent ACR packets when required */
358254885Sdumbbell	       HDMI0_ACR_SOURCE); /* select SW CTS value */
359254885Sdumbbell
360254885Sdumbbell	WREG32(HDMI0_VBI_PACKET_CONTROL + offset,
361254885Sdumbbell	       HDMI0_NULL_SEND | /* send null packets when required */
362254885Sdumbbell	       HDMI0_GC_SEND | /* send general control packets */
363254885Sdumbbell	       HDMI0_GC_CONT); /* send general control packets every frame */
364254885Sdumbbell
365254885Sdumbbell	/* TODO: HDMI0_AUDIO_INFO_UPDATE */
366254885Sdumbbell	WREG32(HDMI0_INFOFRAME_CONTROL0 + offset,
367254885Sdumbbell	       HDMI0_AVI_INFO_SEND | /* enable AVI info frames */
368254885Sdumbbell	       HDMI0_AVI_INFO_CONT | /* send AVI info frames every frame/field */
369254885Sdumbbell	       HDMI0_AUDIO_INFO_SEND | /* enable audio info frames (frames won't be set until audio is enabled) */
370254885Sdumbbell	       HDMI0_AUDIO_INFO_CONT); /* send audio info frames every frame/field */
371254885Sdumbbell
372254885Sdumbbell	WREG32(HDMI0_INFOFRAME_CONTROL1 + offset,
373254885Sdumbbell	       HDMI0_AVI_INFO_LINE(2) | /* anything other than 0 */
374254885Sdumbbell	       HDMI0_AUDIO_INFO_LINE(2)); /* anything other than 0 */
375254885Sdumbbell
376254885Sdumbbell	WREG32(HDMI0_GC + offset, 0); /* unset HDMI0_GC_AVMUTE */
377254885Sdumbbell
378254885Sdumbbell	r600_hdmi_videoinfoframe(encoder, RGB, 0, 0, 0, 0,
379254885Sdumbbell		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
380254885Sdumbbell
381254885Sdumbbell	r600_hdmi_update_ACR(encoder, mode->clock);
382254885Sdumbbell
383254885Sdumbbell	/* it's unknown what these bits do excatly, but it's indeed quite useful for debugging */
384254885Sdumbbell	WREG32(HDMI0_RAMP_CONTROL0 + offset, 0x00FFFFFF);
385254885Sdumbbell	WREG32(HDMI0_RAMP_CONTROL1 + offset, 0x007FFFFF);
386254885Sdumbbell	WREG32(HDMI0_RAMP_CONTROL2 + offset, 0x00000001);
387254885Sdumbbell	WREG32(HDMI0_RAMP_CONTROL3 + offset, 0x00000001);
388254885Sdumbbell
389254885Sdumbbell	r600_hdmi_audio_workaround(encoder);
390254885Sdumbbell}
391254885Sdumbbell
392254885Sdumbbell/*
393254885Sdumbbell * update settings with current parameters from audio engine
394254885Sdumbbell */
395254885Sdumbbellvoid r600_hdmi_update_audio_settings(struct drm_encoder *encoder)
396254885Sdumbbell{
397254885Sdumbbell	struct drm_device *dev = encoder->dev;
398254885Sdumbbell	struct radeon_device *rdev = dev->dev_private;
399254885Sdumbbell	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
400254885Sdumbbell	struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
401254885Sdumbbell	struct r600_audio audio = r600_audio_status(rdev);
402254885Sdumbbell	uint32_t offset;
403254885Sdumbbell	uint32_t iec;
404254885Sdumbbell
405254885Sdumbbell	if (!dig->afmt || !dig->afmt->enabled)
406254885Sdumbbell		return;
407254885Sdumbbell	offset = dig->afmt->offset;
408254885Sdumbbell
409254885Sdumbbell	DRM_DEBUG("%s with %d channels, %d Hz sampling rate, %d bits per sample,\n",
410254885Sdumbbell		 r600_hdmi_is_audio_buffer_filled(encoder) ? "playing" : "stopped",
411254885Sdumbbell		  audio.channels, audio.rate, audio.bits_per_sample);
412254885Sdumbbell	DRM_DEBUG("0x%02X IEC60958 status bits and 0x%02X category code\n",
413254885Sdumbbell		  (int)audio.status_bits, (int)audio.category_code);
414254885Sdumbbell
415254885Sdumbbell	iec = 0;
416254885Sdumbbell	if (audio.status_bits & AUDIO_STATUS_PROFESSIONAL)
417254885Sdumbbell		iec |= 1 << 0;
418254885Sdumbbell	if (audio.status_bits & AUDIO_STATUS_NONAUDIO)
419254885Sdumbbell		iec |= 1 << 1;
420254885Sdumbbell	if (audio.status_bits & AUDIO_STATUS_COPYRIGHT)
421254885Sdumbbell		iec |= 1 << 2;
422254885Sdumbbell	if (audio.status_bits & AUDIO_STATUS_EMPHASIS)
423254885Sdumbbell		iec |= 1 << 3;
424254885Sdumbbell
425254885Sdumbbell	iec |= HDMI0_60958_CS_CATEGORY_CODE(audio.category_code);
426254885Sdumbbell
427254885Sdumbbell	switch (audio.rate) {
428254885Sdumbbell	case 32000:
429254885Sdumbbell		iec |= HDMI0_60958_CS_SAMPLING_FREQUENCY(0x3);
430254885Sdumbbell		break;
431254885Sdumbbell	case 44100:
432254885Sdumbbell		iec |= HDMI0_60958_CS_SAMPLING_FREQUENCY(0x0);
433254885Sdumbbell		break;
434254885Sdumbbell	case 48000:
435254885Sdumbbell		iec |= HDMI0_60958_CS_SAMPLING_FREQUENCY(0x2);
436254885Sdumbbell		break;
437254885Sdumbbell	case 88200:
438254885Sdumbbell		iec |= HDMI0_60958_CS_SAMPLING_FREQUENCY(0x8);
439254885Sdumbbell		break;
440254885Sdumbbell	case 96000:
441254885Sdumbbell		iec |= HDMI0_60958_CS_SAMPLING_FREQUENCY(0xa);
442254885Sdumbbell		break;
443254885Sdumbbell	case 176400:
444254885Sdumbbell		iec |= HDMI0_60958_CS_SAMPLING_FREQUENCY(0xc);
445254885Sdumbbell		break;
446254885Sdumbbell	case 192000:
447254885Sdumbbell		iec |= HDMI0_60958_CS_SAMPLING_FREQUENCY(0xe);
448254885Sdumbbell		break;
449254885Sdumbbell	}
450254885Sdumbbell
451254885Sdumbbell	WREG32(HDMI0_60958_0 + offset, iec);
452254885Sdumbbell
453254885Sdumbbell	iec = 0;
454254885Sdumbbell	switch (audio.bits_per_sample) {
455254885Sdumbbell	case 16:
456254885Sdumbbell		iec |= HDMI0_60958_CS_WORD_LENGTH(0x2);
457254885Sdumbbell		break;
458254885Sdumbbell	case 20:
459254885Sdumbbell		iec |= HDMI0_60958_CS_WORD_LENGTH(0x3);
460254885Sdumbbell		break;
461254885Sdumbbell	case 24:
462254885Sdumbbell		iec |= HDMI0_60958_CS_WORD_LENGTH(0xb);
463254885Sdumbbell		break;
464254885Sdumbbell	}
465254885Sdumbbell	if (audio.status_bits & AUDIO_STATUS_V)
466254885Sdumbbell		iec |= 0x5 << 16;
467254885Sdumbbell	WREG32_P(HDMI0_60958_1 + offset, iec, ~0x5000f);
468254885Sdumbbell
469254885Sdumbbell	r600_hdmi_audioinfoframe(encoder, audio.channels - 1, 0, 0, 0, 0, 0, 0,
470254885Sdumbbell				 0);
471254885Sdumbbell
472254885Sdumbbell	r600_hdmi_audio_workaround(encoder);
473254885Sdumbbell}
474254885Sdumbbell
475254885Sdumbbell/*
476254885Sdumbbell * enable the HDMI engine
477254885Sdumbbell */
478254885Sdumbbellvoid r600_hdmi_enable(struct drm_encoder *encoder)
479254885Sdumbbell{
480254885Sdumbbell	struct drm_device *dev = encoder->dev;
481254885Sdumbbell	struct radeon_device *rdev = dev->dev_private;
482254885Sdumbbell	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
483254885Sdumbbell	struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
484254885Sdumbbell	uint32_t offset;
485254885Sdumbbell	u32 hdmi;
486254885Sdumbbell
487254885Sdumbbell	if (ASIC_IS_DCE6(rdev))
488254885Sdumbbell		return;
489254885Sdumbbell
490254885Sdumbbell	/* Silent, r600_hdmi_enable will raise WARN for us */
491254885Sdumbbell	if (dig->afmt->enabled)
492254885Sdumbbell		return;
493254885Sdumbbell	offset = dig->afmt->offset;
494254885Sdumbbell
495254885Sdumbbell	/* Older chipsets require setting HDMI and routing manually */
496280183Sdumbbell	if (ASIC_IS_DCE2(rdev) && !ASIC_IS_DCE3(rdev)) {
497254885Sdumbbell		hdmi = HDMI0_ERROR_ACK | HDMI0_ENABLE;
498254885Sdumbbell		switch (radeon_encoder->encoder_id) {
499254885Sdumbbell		case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
500254885Sdumbbell			WREG32_P(AVIVO_TMDSA_CNTL, AVIVO_TMDSA_CNTL_HDMI_EN,
501254885Sdumbbell				 ~AVIVO_TMDSA_CNTL_HDMI_EN);
502254885Sdumbbell			hdmi |= HDMI0_STREAM(HDMI0_STREAM_TMDSA);
503254885Sdumbbell			break;
504254885Sdumbbell		case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
505254885Sdumbbell			WREG32_P(AVIVO_LVTMA_CNTL, AVIVO_LVTMA_CNTL_HDMI_EN,
506254885Sdumbbell				 ~AVIVO_LVTMA_CNTL_HDMI_EN);
507254885Sdumbbell			hdmi |= HDMI0_STREAM(HDMI0_STREAM_LVTMA);
508254885Sdumbbell			break;
509254885Sdumbbell		case ENCODER_OBJECT_ID_INTERNAL_DDI:
510254885Sdumbbell			WREG32_P(DDIA_CNTL, DDIA_HDMI_EN, ~DDIA_HDMI_EN);
511254885Sdumbbell			hdmi |= HDMI0_STREAM(HDMI0_STREAM_DDIA);
512254885Sdumbbell			break;
513254885Sdumbbell		case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
514254885Sdumbbell			hdmi |= HDMI0_STREAM(HDMI0_STREAM_DVOA);
515254885Sdumbbell			break;
516254885Sdumbbell		default:
517254885Sdumbbell			dev_err(rdev->dev, "Invalid encoder for HDMI: 0x%X\n",
518254885Sdumbbell				radeon_encoder->encoder_id);
519254885Sdumbbell			break;
520254885Sdumbbell		}
521254885Sdumbbell		WREG32(HDMI0_CONTROL + offset, hdmi);
522254885Sdumbbell	}
523254885Sdumbbell
524254885Sdumbbell	if (rdev->irq.installed) {
525254885Sdumbbell		/* if irq is available use it */
526254885Sdumbbell		radeon_irq_kms_enable_afmt(rdev, dig->afmt->id);
527254885Sdumbbell	}
528254885Sdumbbell
529254885Sdumbbell	dig->afmt->enabled = true;
530254885Sdumbbell
531254885Sdumbbell	DRM_DEBUG("Enabling HDMI interface @ 0x%04X for encoder 0x%x\n",
532254885Sdumbbell		  offset, radeon_encoder->encoder_id);
533254885Sdumbbell}
534254885Sdumbbell
535254885Sdumbbell/*
536254885Sdumbbell * disable the HDMI engine
537254885Sdumbbell */
538254885Sdumbbellvoid r600_hdmi_disable(struct drm_encoder *encoder)
539254885Sdumbbell{
540254885Sdumbbell	struct drm_device *dev = encoder->dev;
541254885Sdumbbell	struct radeon_device *rdev = dev->dev_private;
542254885Sdumbbell	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
543254885Sdumbbell	struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
544254885Sdumbbell	uint32_t offset;
545254885Sdumbbell
546254885Sdumbbell	if (ASIC_IS_DCE6(rdev))
547254885Sdumbbell		return;
548254885Sdumbbell
549254885Sdumbbell	/* Called for ATOM_ENCODER_MODE_HDMI only */
550254885Sdumbbell	if (!dig || !dig->afmt) {
551254885Sdumbbell		return;
552254885Sdumbbell	}
553254885Sdumbbell	if (!dig->afmt->enabled)
554254885Sdumbbell		return;
555254885Sdumbbell	offset = dig->afmt->offset;
556254885Sdumbbell
557254885Sdumbbell	DRM_DEBUG("Disabling HDMI interface @ 0x%04X for encoder 0x%x\n",
558254885Sdumbbell		  offset, radeon_encoder->encoder_id);
559254885Sdumbbell
560254885Sdumbbell	/* disable irq */
561254885Sdumbbell	radeon_irq_kms_disable_afmt(rdev, dig->afmt->id);
562254885Sdumbbell
563254885Sdumbbell	/* Older chipsets not handled by AtomBIOS */
564280183Sdumbbell	if (ASIC_IS_DCE2(rdev) && !ASIC_IS_DCE3(rdev)) {
565254885Sdumbbell		switch (radeon_encoder->encoder_id) {
566254885Sdumbbell		case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
567254885Sdumbbell			WREG32_P(AVIVO_TMDSA_CNTL, 0,
568254885Sdumbbell				 ~AVIVO_TMDSA_CNTL_HDMI_EN);
569254885Sdumbbell			break;
570254885Sdumbbell		case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
571254885Sdumbbell			WREG32_P(AVIVO_LVTMA_CNTL, 0,
572254885Sdumbbell				 ~AVIVO_LVTMA_CNTL_HDMI_EN);
573254885Sdumbbell			break;
574254885Sdumbbell		case ENCODER_OBJECT_ID_INTERNAL_DDI:
575254885Sdumbbell			WREG32_P(DDIA_CNTL, 0, ~DDIA_HDMI_EN);
576254885Sdumbbell			break;
577254885Sdumbbell		case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
578254885Sdumbbell			break;
579254885Sdumbbell		default:
580254885Sdumbbell			dev_err(rdev->dev, "Invalid encoder for HDMI: 0x%X\n",
581254885Sdumbbell				radeon_encoder->encoder_id);
582254885Sdumbbell			break;
583254885Sdumbbell		}
584254885Sdumbbell		WREG32(HDMI0_CONTROL + offset, HDMI0_ERROR_ACK);
585254885Sdumbbell	}
586254885Sdumbbell
587254885Sdumbbell	dig->afmt->enabled = false;
588254885Sdumbbell}
589