r600_hdmi.c 17.8 KB
Newer Older
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
/*
 * Copyright 2008 Advanced Micro Devices, Inc.
 * Copyright 2008 Red Hat Inc.
 * Copyright 2009 Christian König.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 *
 * Authors: Christian König
 */
26
#include <linux/hdmi.h>
27 28
#include <drm/drmP.h>
#include <drm/radeon_drm.h>
29
#include "radeon.h"
30
#include "radeon_asic.h"
31
#include "r600d.h"
32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
#include "atom.h"

/*
 * HDMI color format
 */
enum r600_hdmi_color_format {
	RGB = 0,
	YCC_422 = 1,
	YCC_444 = 2
};

/*
 * IEC60958 status bits
 */
enum r600_hdmi_iec_status_bits {
	AUDIO_STATUS_DIG_ENABLE   = 0x01,
48 49
	AUDIO_STATUS_V            = 0x02,
	AUDIO_STATUS_VCFG         = 0x04,
50 51 52 53
	AUDIO_STATUS_EMPHASIS     = 0x08,
	AUDIO_STATUS_COPYRIGHT    = 0x10,
	AUDIO_STATUS_NONAUDIO     = 0x20,
	AUDIO_STATUS_PROFESSIONAL = 0x40,
54
	AUDIO_STATUS_LEVEL        = 0x80
55 56
};

57
static const struct radeon_hdmi_acr r600_hdmi_predefined_acr[] = {
58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75
    /*	     32kHz	  44.1kHz	48kHz    */
    /* Clock      N     CTS      N     CTS      N     CTS */
    {  25174,  4576,  28125,  7007,  31250,  6864,  28125 }, /*  25,20/1.001 MHz */
    {  25200,  4096,  25200,  6272,  28000,  6144,  25200 }, /*  25.20       MHz */
    {  27000,  4096,  27000,  6272,  30000,  6144,  27000 }, /*  27.00       MHz */
    {  27027,  4096,  27027,  6272,  30030,  6144,  27027 }, /*  27.00*1.001 MHz */
    {  54000,  4096,  54000,  6272,  60000,  6144,  54000 }, /*  54.00       MHz */
    {  54054,  4096,  54054,  6272,  60060,  6144,  54054 }, /*  54.00*1.001 MHz */
    {  74175, 11648, 210937, 17836, 234375, 11648, 140625 }, /*  74.25/1.001 MHz */
    {  74250,  4096,  74250,  6272,  82500,  6144,  74250 }, /*  74.25       MHz */
    { 148351, 11648, 421875,  8918, 234375,  5824, 140625 }, /* 148.50/1.001 MHz */
    { 148500,  4096, 148500,  6272, 165000,  6144, 148500 }, /* 148.50       MHz */
    {      0,  4096,      0,  6272,      0,  6144,      0 }  /* Other */
};

/*
 * calculate CTS value if it's not found in the table
 */
76
static void r600_hdmi_calc_cts(uint32_t clock, int *CTS, int N, int freq)
77 78
{
	if (*CTS == 0)
79
		*CTS = clock * N / (128 * freq) * 1000;
80 81 82 83
	DRM_DEBUG("Using ACR timing N=%d CTS=%d for frequency %d\n",
		  N, *CTS, freq);
}

84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101
struct radeon_hdmi_acr r600_hdmi_acr(uint32_t clock)
{
	struct radeon_hdmi_acr res;
	u8 i;

	for (i = 0; r600_hdmi_predefined_acr[i].clock != clock &&
	     r600_hdmi_predefined_acr[i].clock != 0; i++)
		;
	res = r600_hdmi_predefined_acr[i];

	/* In case some CTS are missing */
	r600_hdmi_calc_cts(clock, &res.cts_32khz, res.n_32khz, 32000);
	r600_hdmi_calc_cts(clock, &res.cts_44_1khz, res.n_44_1khz, 44100);
	r600_hdmi_calc_cts(clock, &res.cts_48khz, res.n_48khz, 48000);

	return res;
}

102 103 104 105 106 107 108
/*
 * update the N and CTS parameters for a given pixel clock rate
 */
static void r600_hdmi_update_ACR(struct drm_encoder *encoder, uint32_t clock)
{
	struct drm_device *dev = encoder->dev;
	struct radeon_device *rdev = dev->dev_private;
109
	struct radeon_hdmi_acr acr = r600_hdmi_acr(clock);
110 111 112
	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
	struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
	uint32_t offset = dig->afmt->offset;
113

114 115
	WREG32(HDMI0_ACR_32_0 + offset, HDMI0_ACR_CTS_32(acr.cts_32khz));
	WREG32(HDMI0_ACR_32_1 + offset, acr.n_32khz);
116

117 118
	WREG32(HDMI0_ACR_44_0 + offset, HDMI0_ACR_CTS_44(acr.cts_44_1khz));
	WREG32(HDMI0_ACR_44_1 + offset, acr.n_44_1khz);
119

120 121
	WREG32(HDMI0_ACR_48_0 + offset, HDMI0_ACR_CTS_48(acr.cts_48khz));
	WREG32(HDMI0_ACR_48_1 + offset, acr.n_48khz);
122 123 124 125 126
}

/*
 * build a HDMI Video Info Frame
 */
127 128
static void r600_hdmi_update_avi_infoframe(struct drm_encoder *encoder,
					   void *buffer, size_t size)
129 130 131
{
	struct drm_device *dev = encoder->dev;
	struct radeon_device *rdev = dev->dev_private;
132 133 134
	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
	struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
	uint32_t offset = dig->afmt->offset;
135
	uint8_t *frame = buffer + 3;
136
	uint8_t *header = buffer;
137

138
	WREG32(HDMI0_AVI_INFO0 + offset,
139
		frame[0x0] | (frame[0x1] << 8) | (frame[0x2] << 16) | (frame[0x3] << 24));
140
	WREG32(HDMI0_AVI_INFO1 + offset,
141
		frame[0x4] | (frame[0x5] << 8) | (frame[0x6] << 16) | (frame[0x7] << 24));
142
	WREG32(HDMI0_AVI_INFO2 + offset,
143
		frame[0x8] | (frame[0x9] << 8) | (frame[0xA] << 16) | (frame[0xB] << 24));
144
	WREG32(HDMI0_AVI_INFO3 + offset,
145
		frame[0xC] | (frame[0xD] << 8) | (header[1] << 24));
146 147 148 149 150
}

/*
 * build a Audio Info Frame
 */
151 152
static void r600_hdmi_update_audio_infoframe(struct drm_encoder *encoder,
					     const void *buffer, size_t size)
153 154 155
{
	struct drm_device *dev = encoder->dev;
	struct radeon_device *rdev = dev->dev_private;
156 157 158
	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
	struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
	uint32_t offset = dig->afmt->offset;
159
	const u8 *frame = buffer + 3;
160

161
	WREG32(HDMI0_AUDIO_INFO0 + offset,
162
		frame[0x0] | (frame[0x1] << 8) | (frame[0x2] << 16) | (frame[0x3] << 24));
163
	WREG32(HDMI0_AUDIO_INFO1 + offset,
164 165 166 167 168 169
		frame[0x4] | (frame[0x5] << 8) | (frame[0x6] << 16) | (frame[0x8] << 24));
}

/*
 * test if audio buffer is filled enough to start playing
 */
170
static bool r600_hdmi_is_audio_buffer_filled(struct drm_encoder *encoder)
171 172 173
{
	struct drm_device *dev = encoder->dev;
	struct radeon_device *rdev = dev->dev_private;
174 175 176
	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
	struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
	uint32_t offset = dig->afmt->offset;
177

178
	return (RREG32(HDMI0_STATUS + offset) & 0x10) != 0;
179 180 181 182 183 184 185 186
}

/*
 * have buffer status changed since last call?
 */
int r600_hdmi_buffer_status_changed(struct drm_encoder *encoder)
{
	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
187
	struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
188 189
	int status, result;

190
	if (!dig->afmt || !dig->afmt->enabled)
191 192 193
		return 0;

	status = r600_hdmi_is_audio_buffer_filled(encoder);
194 195
	result = dig->afmt->last_buffer_filled_status != status;
	dig->afmt->last_buffer_filled_status = status;
196 197 198 199 200 201 202

	return result;
}

/*
 * write the audio workaround status to the hardware
 */
203
static void r600_hdmi_audio_workaround(struct drm_encoder *encoder)
204 205 206 207
{
	struct drm_device *dev = encoder->dev;
	struct radeon_device *rdev = dev->dev_private;
	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
208 209 210 211 212 213 214 215 216 217 218 219
	struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
	uint32_t offset = dig->afmt->offset;
	bool hdmi_audio_workaround = false; /* FIXME */
	u32 value;

	if (!hdmi_audio_workaround ||
	    r600_hdmi_is_audio_buffer_filled(encoder))
		value = 0; /* disable workaround */
	else
		value = HDMI0_AUDIO_TEST_EN; /* enable workaround */
	WREG32_P(HDMI0_AUDIO_PACKET_CONTROL + offset,
		 value, ~HDMI0_AUDIO_TEST_EN);
220 221
}

222 223 224 225 226 227
void r600_audio_set_dto(struct drm_encoder *encoder, u32 clock)
{
	struct drm_device *dev = encoder->dev;
	struct radeon_device *rdev = dev->dev_private;
	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
	struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
228
	u32 base_rate = 24000;
229 230 231 232 233
	u32 max_ratio = clock / base_rate;
	u32 dto_phase;
	u32 dto_modulo = clock;
	u32 wallclock_ratio;
	u32 dto_cntl;
234 235 236 237

	if (!dig || !dig->afmt)
		return;

238 239 240 241 242 243 244 245 246 247 248 249 250 251
	if (max_ratio >= 8) {
		dto_phase = 192 * 1000;
		wallclock_ratio = 3;
	} else if (max_ratio >= 4) {
		dto_phase = 96 * 1000;
		wallclock_ratio = 2;
	} else if (max_ratio >= 2) {
		dto_phase = 48 * 1000;
		wallclock_ratio = 1;
	} else {
		dto_phase = 24 * 1000;
		wallclock_ratio = 0;
	}

252 253 254 255 256 257 258 259
	/* there are two DTOs selected by DCCG_AUDIO_DTO_SELECT.
	 * doesn't matter which one you use.  Just use the first one.
	 */
	/* XXX two dtos; generally use dto0 for hdmi */
	/* Express [24MHz / target pixel clock] as an exact rational
	 * number (coefficient of two integer numbers.  DCCG_AUDIO_DTOx_PHASE
	 * is the numerator, DCCG_AUDIO_DTOx_MODULE is the denominator
	 */
260 261 262 263
	if (ASIC_IS_DCE3(rdev)) {
		/* according to the reg specs, this should DCE3.2 only, but in
		 * practice it seems to cover DCE3.0 as well.
		 */
264
		if (dig->dig_encoder == 0) {
265 266 267 268 269
			dto_cntl = RREG32(DCCG_AUDIO_DTO0_CNTL) & ~DCCG_AUDIO_DTO_WALLCLOCK_RATIO_MASK;
			dto_cntl |= DCCG_AUDIO_DTO_WALLCLOCK_RATIO(wallclock_ratio);
			WREG32(DCCG_AUDIO_DTO0_CNTL, dto_cntl);
			WREG32(DCCG_AUDIO_DTO0_PHASE, dto_phase);
			WREG32(DCCG_AUDIO_DTO0_MODULE, dto_modulo);
270 271
			WREG32(DCCG_AUDIO_DTO_SELECT, 0); /* select DTO0 */
		} else {
272 273 274 275 276
			dto_cntl = RREG32(DCCG_AUDIO_DTO1_CNTL) & ~DCCG_AUDIO_DTO_WALLCLOCK_RATIO_MASK;
			dto_cntl |= DCCG_AUDIO_DTO_WALLCLOCK_RATIO(wallclock_ratio);
			WREG32(DCCG_AUDIO_DTO1_CNTL, dto_cntl);
			WREG32(DCCG_AUDIO_DTO1_PHASE, dto_phase);
			WREG32(DCCG_AUDIO_DTO1_MODULE, dto_modulo);
277 278
			WREG32(DCCG_AUDIO_DTO_SELECT, 1); /* select DTO1 */
		}
279 280
	} else {
		/* according to the reg specs, this should be DCE2.0 and DCE3.0 */
281 282
		WREG32(AUDIO_DTO, AUDIO_DTO_PHASE(base_rate / 10) |
		       AUDIO_DTO_MODULE(clock / 10));
283
	}
284
}
285 286 287 288 289 290 291 292

/*
 * update the info frames with the data from the current display mode
 */
void r600_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode *mode)
{
	struct drm_device *dev = encoder->dev;
	struct radeon_device *rdev = dev->dev_private;
293 294
	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
	struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
295 296
	u8 buffer[HDMI_INFOFRAME_HEADER_SIZE + HDMI_AVI_INFOFRAME_SIZE];
	struct hdmi_avi_infoframe frame;
297
	uint32_t offset;
298
	ssize_t err;
299

300 301 302
	if (!dig || !dig->afmt)
		return;

303 304
	/* Silent, r600_hdmi_enable will raise WARN for us */
	if (!dig->afmt->enabled)
305
		return;
306
	offset = dig->afmt->offset;
307

308
	r600_audio_set_dto(encoder, mode->clock);
309

310 311 312
	WREG32(HDMI0_VBI_PACKET_CONTROL + offset,
	       HDMI0_NULL_SEND); /* send null packets when required */

313
	WREG32(HDMI0_AUDIO_CRC_CONTROL + offset, 0x1000);
314

315 316 317 318 319 320 321 322 323 324 325 326 327 328
	if (ASIC_IS_DCE32(rdev)) {
		WREG32(HDMI0_AUDIO_PACKET_CONTROL + offset,
		       HDMI0_AUDIO_DELAY_EN(1) | /* default audio delay */
		       HDMI0_AUDIO_PACKETS_PER_LINE(3)); /* should be suffient for all audio modes and small enough for all hblanks */
		WREG32(AFMT_AUDIO_PACKET_CONTROL + offset,
		       AFMT_AUDIO_SAMPLE_SEND | /* send audio packets */
		       AFMT_60958_CS_UPDATE); /* allow 60958 channel status fields to be updated */
	} else {
		WREG32(HDMI0_AUDIO_PACKET_CONTROL + offset,
		       HDMI0_AUDIO_SAMPLE_SEND | /* send audio packets */
		       HDMI0_AUDIO_DELAY_EN(1) | /* default audio delay */
		       HDMI0_AUDIO_PACKETS_PER_LINE(3) | /* should be suffient for all audio modes and small enough for all hblanks */
		       HDMI0_60958_CS_UPDATE); /* allow 60958 channel status fields to be updated */
	}
329

330 331 332
	WREG32(HDMI0_ACR_PACKET_CONTROL + offset,
	       HDMI0_ACR_AUTO_SEND | /* allow hw to sent ACR packets when required */
	       HDMI0_ACR_SOURCE); /* select SW CTS value */
333

334 335 336 337
	WREG32(HDMI0_VBI_PACKET_CONTROL + offset,
	       HDMI0_NULL_SEND | /* send null packets when required */
	       HDMI0_GC_SEND | /* send general control packets */
	       HDMI0_GC_CONT); /* send general control packets every frame */
338

339 340 341 342 343 344
	/* TODO: HDMI0_AUDIO_INFO_UPDATE */
	WREG32(HDMI0_INFOFRAME_CONTROL0 + offset,
	       HDMI0_AVI_INFO_SEND | /* enable AVI info frames */
	       HDMI0_AVI_INFO_CONT | /* send AVI info frames every frame/field */
	       HDMI0_AUDIO_INFO_SEND | /* enable audio info frames (frames won't be set until audio is enabled) */
	       HDMI0_AUDIO_INFO_CONT); /* send audio info frames every frame/field */
345

346 347 348 349 350
	WREG32(HDMI0_INFOFRAME_CONTROL1 + offset,
	       HDMI0_AVI_INFO_LINE(2) | /* anything other than 0 */
	       HDMI0_AUDIO_INFO_LINE(2)); /* anything other than 0 */

	WREG32(HDMI0_GC + offset, 0); /* unset HDMI0_GC_AVMUTE */
351

352 353 354 355 356
	err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode);
	if (err < 0) {
		DRM_ERROR("failed to setup AVI infoframe: %zd\n", err);
		return;
	}
357

358 359 360 361 362 363 364
	err = hdmi_avi_infoframe_pack(&frame, buffer, sizeof(buffer));
	if (err < 0) {
		DRM_ERROR("failed to pack AVI infoframe: %zd\n", err);
		return;
	}

	r600_hdmi_update_avi_infoframe(encoder, buffer, sizeof(buffer));
365 366
	r600_hdmi_update_ACR(encoder, mode->clock);

L
Lucas De Marchi 已提交
367
	/* it's unknown what these bits do excatly, but it's indeed quite useful for debugging */
368 369 370 371
	WREG32(HDMI0_RAMP_CONTROL0 + offset, 0x00FFFFFF);
	WREG32(HDMI0_RAMP_CONTROL1 + offset, 0x007FFFFF);
	WREG32(HDMI0_RAMP_CONTROL2 + offset, 0x00000001);
	WREG32(HDMI0_RAMP_CONTROL3 + offset, 0x00000001);
372 373 374 375 376 377 378

	r600_hdmi_audio_workaround(encoder);
}

/*
 * update settings with current parameters from audio engine
 */
379
void r600_hdmi_update_audio_settings(struct drm_encoder *encoder)
380 381 382
{
	struct drm_device *dev = encoder->dev;
	struct radeon_device *rdev = dev->dev_private;
383 384
	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
	struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
385
	struct r600_audio audio = r600_audio_status(rdev);
386 387
	uint8_t buffer[HDMI_INFOFRAME_HEADER_SIZE + HDMI_AUDIO_INFOFRAME_SIZE];
	struct hdmi_audio_infoframe frame;
388
	uint32_t offset;
389
	uint32_t iec;
390
	ssize_t err;
391

392
	if (!dig->afmt || !dig->afmt->enabled)
393
		return;
394
	offset = dig->afmt->offset;
395 396 397

	DRM_DEBUG("%s with %d channels, %d Hz sampling rate, %d bits per sample,\n",
		 r600_hdmi_is_audio_buffer_filled(encoder) ? "playing" : "stopped",
398
		  audio.channels, audio.rate, audio.bits_per_sample);
399
	DRM_DEBUG("0x%02X IEC60958 status bits and 0x%02X category code\n",
400
		  (int)audio.status_bits, (int)audio.category_code);
401 402

	iec = 0;
403
	if (audio.status_bits & AUDIO_STATUS_PROFESSIONAL)
404
		iec |= 1 << 0;
405
	if (audio.status_bits & AUDIO_STATUS_NONAUDIO)
406
		iec |= 1 << 1;
407
	if (audio.status_bits & AUDIO_STATUS_COPYRIGHT)
408
		iec |= 1 << 2;
409
	if (audio.status_bits & AUDIO_STATUS_EMPHASIS)
410 411
		iec |= 1 << 3;

412
	iec |= HDMI0_60958_CS_CATEGORY_CODE(audio.category_code);
413

414
	switch (audio.rate) {
415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435
	case 32000:
		iec |= HDMI0_60958_CS_SAMPLING_FREQUENCY(0x3);
		break;
	case 44100:
		iec |= HDMI0_60958_CS_SAMPLING_FREQUENCY(0x0);
		break;
	case 48000:
		iec |= HDMI0_60958_CS_SAMPLING_FREQUENCY(0x2);
		break;
	case 88200:
		iec |= HDMI0_60958_CS_SAMPLING_FREQUENCY(0x8);
		break;
	case 96000:
		iec |= HDMI0_60958_CS_SAMPLING_FREQUENCY(0xa);
		break;
	case 176400:
		iec |= HDMI0_60958_CS_SAMPLING_FREQUENCY(0xc);
		break;
	case 192000:
		iec |= HDMI0_60958_CS_SAMPLING_FREQUENCY(0xe);
		break;
436 437
	}

438
	WREG32(HDMI0_60958_0 + offset, iec);
439 440

	iec = 0;
441
	switch (audio.bits_per_sample) {
442 443 444 445 446 447 448 449 450
	case 16:
		iec |= HDMI0_60958_CS_WORD_LENGTH(0x2);
		break;
	case 20:
		iec |= HDMI0_60958_CS_WORD_LENGTH(0x3);
		break;
	case 24:
		iec |= HDMI0_60958_CS_WORD_LENGTH(0xb);
		break;
451
	}
452
	if (audio.status_bits & AUDIO_STATUS_V)
453
		iec |= 0x5 << 16;
454
	WREG32_P(HDMI0_60958_1 + offset, iec, ~0x5000f);
455

456 457 458 459 460 461 462 463 464 465 466 467 468
	err = hdmi_audio_infoframe_init(&frame);
	if (err < 0) {
		DRM_ERROR("failed to setup audio infoframe\n");
		return;
	}

	frame.channels = audio.channels;

	err = hdmi_audio_infoframe_pack(&frame, buffer, sizeof(buffer));
	if (err < 0) {
		DRM_ERROR("failed to pack audio infoframe\n");
		return;
	}
469

470
	r600_hdmi_update_audio_infoframe(encoder, buffer, sizeof(buffer));
471 472 473 474
	r600_hdmi_audio_workaround(encoder);
}

/*
475
 * enable the HDMI engine
476
 */
477
void r600_hdmi_enable(struct drm_encoder *encoder, bool enable)
478
{
479 480
	struct drm_device *dev = encoder->dev;
	struct radeon_device *rdev = dev->dev_private;
481
	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
482
	struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
483
	u32 hdmi = HDMI0_ERROR_ACK;
484

485 486 487
	if (!dig || !dig->afmt)
		return;

488
	/* Silent, r600_hdmi_enable will raise WARN for us */
489 490 491
	if (enable && dig->afmt->enabled)
		return;
	if (!enable && !dig->afmt->enabled)
492
		return;
493 494

	/* Older chipsets require setting HDMI and routing manually */
495 496 497
	if (!ASIC_IS_DCE3(rdev)) {
		if (enable)
			hdmi |= HDMI0_ENABLE;
498 499
		switch (radeon_encoder->encoder_id) {
		case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
500 501 502 503 504 505
			if (enable) {
				WREG32_OR(AVIVO_TMDSA_CNTL, AVIVO_TMDSA_CNTL_HDMI_EN);
				hdmi |= HDMI0_STREAM(HDMI0_STREAM_TMDSA);
			} else {
				WREG32_AND(AVIVO_TMDSA_CNTL, ~AVIVO_TMDSA_CNTL_HDMI_EN);
			}
506 507
			break;
		case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
508 509 510 511 512 513
			if (enable) {
				WREG32_OR(AVIVO_LVTMA_CNTL, AVIVO_LVTMA_CNTL_HDMI_EN);
				hdmi |= HDMI0_STREAM(HDMI0_STREAM_LVTMA);
			} else {
				WREG32_AND(AVIVO_LVTMA_CNTL, ~AVIVO_LVTMA_CNTL_HDMI_EN);
			}
514 515
			break;
		case ENCODER_OBJECT_ID_INTERNAL_DDI:
516 517 518 519 520 521
			if (enable) {
				WREG32_OR(DDIA_CNTL, DDIA_HDMI_EN);
				hdmi |= HDMI0_STREAM(HDMI0_STREAM_DDIA);
			} else {
				WREG32_AND(DDIA_CNTL, ~DDIA_HDMI_EN);
			}
522 523
			break;
		case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
524 525
			if (enable)
				hdmi |= HDMI0_STREAM(HDMI0_STREAM_DVOA);
526 527
			break;
		default:
528 529
			dev_err(rdev->dev, "Invalid encoder for HDMI: 0x%X\n",
				radeon_encoder->encoder_id);
530 531
			break;
		}
532
		WREG32(HDMI0_CONTROL + dig->afmt->offset, hdmi);
533
	}
534

535
	if (rdev->irq.installed) {
536
		/* if irq is available use it */
537
		/* XXX: shouldn't need this on any asics.  Double check DCE2/3 */
538
		if (enable)
539
			radeon_irq_kms_enable_afmt(rdev, dig->afmt->id);
540 541
		else
			radeon_irq_kms_disable_afmt(rdev, dig->afmt->id);
542
	}
543

544
	dig->afmt->enabled = enable;
545

546 547
	DRM_DEBUG("%sabling HDMI interface @ 0x%04X for encoder 0x%x\n",
		  enable ? "En" : "Dis", dig->afmt->offset, radeon_encoder->encoder_id);
548
}
549