Subversion Repositories Kolibri OS

Rev

Rev 1403 | Rev 2997 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 1403 Rev 1963
Line 24... Line 24...
24
 * Authors: Christian König
24
 * Authors: Christian König
25
 */
25
 */
26
#include "drmP.h"
26
#include "drmP.h"
27
#include "radeon_drm.h"
27
#include "radeon_drm.h"
28
#include "radeon.h"
28
#include "radeon.h"
-
 
29
#include "radeon_asic.h"
29
#include "atom.h"
30
#include "atom.h"
Line 30... Line 31...
30
 
31
 
31
/*
32
/*
32
 * HDMI color format
33
 * HDMI color format
Line 288... Line 289...
288
	uint32_t offset = radeon_encoder->hdmi_offset;
289
	uint32_t offset = radeon_encoder->hdmi_offset;
Line 289... Line 290...
289
 
290
 
290
	if (!offset)
291
	if (!offset)
Line -... Line 292...
-
 
292
		return;
291
		return;
293
 
292
 
-
 
293
	if (r600_hdmi_is_audio_buffer_filled(encoder)) {
-
 
Line 294... Line 294...
294
		/* disable audio workaround and start delivering of audio frames */
294
	if (!radeon_encoder->hdmi_audio_workaround ||
295
		WREG32_P(offset+R600_HDMI_CNTL, 0x00000001, ~0x00001001);
-
 
296
 
295
		r600_hdmi_is_audio_buffer_filled(encoder)) {
Line 297... Line 296...
297
	} else if (radeon_encoder->hdmi_audio_workaround) {
296
 
298
		/* enable audio workaround and start delivering of audio frames */
297
		/* disable audio workaround */
299
		WREG32_P(offset+R600_HDMI_CNTL, 0x00001001, ~0x00001001);
298
		WREG32_P(offset+R600_HDMI_CNTL, 0x00000001, ~0x00001001);
300
 
299
 
301
	} else {
300
	} else {
Line 302... Line 301...
302
		/* disable audio workaround and stop delivering of audio frames */
301
		/* enable audio workaround */
Line 312... Line 311...
312
{
311
{
313
	struct drm_device *dev = encoder->dev;
312
	struct drm_device *dev = encoder->dev;
314
	struct radeon_device *rdev = dev->dev_private;
313
	struct radeon_device *rdev = dev->dev_private;
315
	uint32_t offset = to_radeon_encoder(encoder)->hdmi_offset;
314
	uint32_t offset = to_radeon_encoder(encoder)->hdmi_offset;
Line -... Line 315...
-
 
315
 
-
 
316
	if (ASIC_IS_DCE4(rdev))
-
 
317
		return;
316
 
318
 
317
	if (!offset)
319
	if (!offset)
Line 318... Line 320...
318
		return;
320
		return;
Line 330... Line 332...
330
	WREG32(offset+R600_HDMI_VERSION, 0x202);
332
	WREG32(offset+R600_HDMI_VERSION, 0x202);
Line 331... Line 333...
331
 
333
 
332
	r600_hdmi_videoinfoframe(encoder, RGB, 0, 0, 0, 0,
334
	r600_hdmi_videoinfoframe(encoder, RGB, 0, 0, 0, 0,
Line 333... Line 335...
333
		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
335
		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
334
 
336
 
335
	/* it's unknown what these bits do excatly, but it's indeed quite usefull for debugging */
337
	/* it's unknown what these bits do excatly, but it's indeed quite useful for debugging */
336
	WREG32(offset+R600_HDMI_AUDIO_DEBUG_0, 0x00FFFFFF);
338
	WREG32(offset+R600_HDMI_AUDIO_DEBUG_0, 0x00FFFFFF);
337
	WREG32(offset+R600_HDMI_AUDIO_DEBUG_1, 0x007FFFFF);
339
	WREG32(offset+R600_HDMI_AUDIO_DEBUG_1, 0x007FFFFF);
Line 338... Line 340...
338
	WREG32(offset+R600_HDMI_AUDIO_DEBUG_2, 0x00000001);
340
	WREG32(offset+R600_HDMI_AUDIO_DEBUG_2, 0x00000001);
Line 339... Line 341...
339
	WREG32(offset+R600_HDMI_AUDIO_DEBUG_3, 0x00000001);
341
	WREG32(offset+R600_HDMI_AUDIO_DEBUG_3, 0x00000001);
340
 
342
 
341
	r600_hdmi_audio_workaround(encoder);
-
 
342
 
-
 
343
	/* audio packets per line, does anyone know how to calc this ? */
-
 
344
	WREG32_P(offset+R600_HDMI_CNTL, 0x00040000, ~0x001F0000);
343
	r600_hdmi_audio_workaround(encoder);
Line 345... Line 344...
345
 
344
 
346
	/* update? reset? don't realy know */
345
	/* audio packets per line, does anyone know how to calc this ? */
347
	WREG32_P(offset+R600_HDMI_CNTL, 0x14000000, ~0x14000000);
346
	WREG32_P(offset+R600_HDMI_CNTL, 0x00040000, ~0x001F0000);
348
}
347
}
349
 
-
 
350
/*
-
 
351
 * update settings with current parameters from audio engine
-
 
352
 */
-
 
353
void r600_hdmi_update_audio_settings(struct drm_encoder *encoder,
-
 
354
				     int channels,
348
 
355
				     int rate,
349
/*
356
				     int bps,
350
 * update settings with current parameters from audio engine
357
				     uint8_t status_bits,
351
 */
Line -... Line 352...
-
 
352
void r600_hdmi_update_audio_settings(struct drm_encoder *encoder)
-
 
353
{
-
 
354
	struct drm_device *dev = encoder->dev;
-
 
355
	struct radeon_device *rdev = dev->dev_private;
-
 
356
	uint32_t offset = to_radeon_encoder(encoder)->hdmi_offset;
-
 
357
 
358
				     uint8_t category_code)
358
	int channels = r600_audio_channels(rdev);
Line 359... Line 359...
359
{
359
	int rate = r600_audio_rate(rdev);
360
	struct drm_device *dev = encoder->dev;
360
	int bps = r600_audio_bits_per_sample(rdev);
Line 410... Line 410...
410
	/* 0x021 or 0x031 sets the audio frame length */
410
	/* 0x021 or 0x031 sets the audio frame length */
411
	WREG32(offset+R600_HDMI_AUDIOCNTL, 0x31);
411
	WREG32(offset+R600_HDMI_AUDIOCNTL, 0x31);
412
	r600_hdmi_audioinfoframe(encoder, channels-1, 0, 0, 0, 0, 0, 0, 0);
412
	r600_hdmi_audioinfoframe(encoder, channels-1, 0, 0, 0, 0, 0, 0, 0);
Line 413... Line 413...
413
 
413
 
-
 
414
	r600_hdmi_audio_workaround(encoder);
-
 
415
}
-
 
416
 
-
 
417
static int r600_hdmi_find_free_block(struct drm_device *dev)
-
 
418
{
-
 
419
	struct radeon_device *rdev = dev->dev_private;
-
 
420
	struct drm_encoder *encoder;
-
 
421
	struct radeon_encoder *radeon_encoder;
-
 
422
	bool free_blocks[3] = { true, true, true };
-
 
423
 
-
 
424
	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
-
 
425
		radeon_encoder = to_radeon_encoder(encoder);
-
 
426
		switch (radeon_encoder->hdmi_offset) {
-
 
427
		case R600_HDMI_BLOCK1:
-
 
428
			free_blocks[0] = false;
-
 
429
			break;
-
 
430
		case R600_HDMI_BLOCK2:
-
 
431
			free_blocks[1] = false;
-
 
432
			break;
-
 
433
		case R600_HDMI_BLOCK3:
-
 
434
			free_blocks[2] = false;
-
 
435
			break;
-
 
436
		}
Line -... Line 437...
-
 
437
	}
-
 
438
 
-
 
439
	if (rdev->family == CHIP_RS600 || rdev->family == CHIP_RS690 ||
-
 
440
	    rdev->family == CHIP_RS740) {
-
 
441
		return free_blocks[0] ? R600_HDMI_BLOCK1 : 0;
-
 
442
	} else if (rdev->family >= CHIP_R600) {
-
 
443
		if (free_blocks[0])
-
 
444
			return R600_HDMI_BLOCK1;
-
 
445
		else if (free_blocks[1])
-
 
446
			return R600_HDMI_BLOCK2;
-
 
447
	}
-
 
448
	return 0;
-
 
449
}
-
 
450
 
414
	r600_hdmi_audio_workaround(encoder);
451
static void r600_hdmi_assign_block(struct drm_encoder *encoder)
-
 
452
{
-
 
453
	struct drm_device *dev = encoder->dev;
-
 
454
	struct radeon_device *rdev = dev->dev_private;
-
 
455
	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
-
 
456
	struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
-
 
457
 
-
 
458
	if (!dig) {
-
 
459
		dev_err(rdev->dev, "Enabling HDMI on non-dig encoder\n");
-
 
460
		return;
-
 
461
	}
-
 
462
 
-
 
463
	if (ASIC_IS_DCE4(rdev)) {
-
 
464
		/* TODO */
-
 
465
	} else if (ASIC_IS_DCE3(rdev)) {
-
 
466
		radeon_encoder->hdmi_offset = dig->dig_encoder ?
-
 
467
			R600_HDMI_BLOCK3 : R600_HDMI_BLOCK1;
415
 
468
		if (ASIC_IS_DCE32(rdev))
-
 
469
			radeon_encoder->hdmi_config_offset = dig->dig_encoder ?
-
 
470
				R600_HDMI_CONFIG2 : R600_HDMI_CONFIG1;
-
 
471
	} else if (rdev->family >= CHIP_R600 || rdev->family == CHIP_RS600 ||
-
 
472
		   rdev->family == CHIP_RS690 || rdev->family == CHIP_RS740) {
416
	/* update? reset? don't realy know */
473
		radeon_encoder->hdmi_offset = r600_hdmi_find_free_block(dev);
Line 417... Line 474...
417
	WREG32_P(offset+R600_HDMI_CNTL, 0x04000000, ~0x04000000);
474
	}
418
}
475
}
419
 
476
 
420
/*
477
/*
421
 * enable/disable the HDMI engine
478
 * enable the HDMI engine
422
 */
479
 */
423
void r600_hdmi_enable(struct drm_encoder *encoder, int enable)
480
void r600_hdmi_enable(struct drm_encoder *encoder)
424
{
481
{
425
	struct drm_device *dev = encoder->dev;
482
	struct drm_device *dev = encoder->dev;
Line 426... Line 483...
426
	struct radeon_device *rdev = dev->dev_private;
483
	struct radeon_device *rdev = dev->dev_private;
427
	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
484
	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
Line -... Line 485...
-
 
485
	uint32_t offset;
-
 
486
 
-
 
487
	if (ASIC_IS_DCE4(rdev))
428
	uint32_t offset = to_radeon_encoder(encoder)->hdmi_offset;
488
		return;
-
 
489
 
-
 
490
	if (!radeon_encoder->hdmi_offset) {
-
 
491
		r600_hdmi_assign_block(encoder);
-
 
492
		if (!radeon_encoder->hdmi_offset) {
Line -... Line 493...
-
 
493
			dev_warn(rdev->dev, "Could not find HDMI block for "
-
 
494
				"0x%x encoder\n", radeon_encoder->encoder_id);
429
 
495
		return;
430
	if (!offset)
496
		}
431
		return;
497
	}
432
 
498
 
433
	DRM_DEBUG("%s HDMI interface @ 0x%04X\n", enable ? "Enabling" : "Disabling", offset);
499
	offset = radeon_encoder->hdmi_offset;
434
 
500
	if (ASIC_IS_DCE32(rdev) && !ASIC_IS_DCE4(rdev)) {
435
	/* some version of atombios ignore the enable HDMI flag
501
		WREG32_P(radeon_encoder->hdmi_config_offset + 0x4, 0x1, ~0x1);
436
	 * so enabling/disabling HDMI was moved here for TMDS1+2 */
-
 
437
	switch (radeon_encoder->encoder_id) {
502
	} else if (rdev->family >= CHIP_R600 && !ASIC_IS_DCE3(rdev)) {
438
	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
503
	switch (radeon_encoder->encoder_id) {
439
		WREG32_P(AVIVO_TMDSA_CNTL, enable ? 0x4 : 0x0, ~0x4);
504
	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
440
		WREG32(offset+R600_HDMI_ENABLE, enable ? 0x101 : 0x0);
-
 
441
		break;
-
 
442
 
-
 
443
	case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
-
 
444
		WREG32_P(AVIVO_LVTMA_CNTL, enable ? 0x4 : 0x0, ~0x4);
-
 
445
		WREG32(offset+R600_HDMI_ENABLE, enable ? 0x105 : 0x0);
-
 
446
		break;
-
 
447
 
-
 
448
	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
505
			WREG32_P(AVIVO_TMDSA_CNTL, 0x4, ~0x4);
449
	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
-
 
450
	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
506
			WREG32(offset + R600_HDMI_ENABLE, 0x101);
451
	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
507
		break;
452
		/* This part is doubtfull in my opinion */
508
	case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
453
		WREG32(offset+R600_HDMI_ENABLE, enable ? 0x110 : 0x0);
509
			WREG32_P(AVIVO_LVTMA_CNTL, 0x4, ~0x4);
454
		break;
510
			WREG32(offset + R600_HDMI_ENABLE, 0x105);
-
 
511
		break;
-
 
512
	default:
-
 
513
			dev_err(rdev->dev, "Unknown HDMI output type\n");
-
 
514
		break;
-
 
515
	}
-
 
516
	}
-
 
517
#if 0
-
 
518
	if (rdev->irq.installed
-
 
519
	    && rdev->family != CHIP_RS600
-
 
520
	    && rdev->family != CHIP_RS690
-
 
521
	    && rdev->family != CHIP_RS740) {
-
 
522
 
-
 
523
		/* if irq is available use it */
-
 
524
		rdev->irq.hdmi[offset == R600_HDMI_BLOCK1 ? 0 : 1] = true;
-
 
525
		radeon_irq_set(rdev);
-
 
526
 
-
 
527
		r600_audio_disable_polling(encoder);
-
 
528
	} else {
-
 
529
		/* if not fallback to polling */
Line 455... Line 530...
455
 
530
		r600_audio_enable_polling(encoder);
456
	default:
531
	}
457
		DRM_ERROR("unknown HDMI output type\n");
532
#endif
458
		break;
533
	DRM_DEBUG("Enabling HDMI interface @ 0x%04X for encoder 0x%x\n",
459
	}
534
		radeon_encoder->hdmi_offset, radeon_encoder->encoder_id);
-
 
535
}
-
 
536
 
460
}
537
/*
-
 
538
 * disable the HDMI engine
-
 
539
 */
-
 
540
void r600_hdmi_disable(struct drm_encoder *encoder)
-
 
541
{
Line -... Line 542...
-
 
542
	struct drm_device *dev = encoder->dev;
-
 
543
	struct radeon_device *rdev = dev->dev_private;
-
 
544
	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
-
 
545
	uint32_t offset;
-
 
546
 
-
 
547
	if (ASIC_IS_DCE4(rdev))
-
 
548
		return;
-
 
549
 
-
 
550
	offset = radeon_encoder->hdmi_offset;
-
 
551
	if (!offset) {
-
 
552
		dev_err(rdev->dev, "Disabling not enabled HDMI\n");
-
 
553
		return;
461
 
554
	}
462
/*
555
 
463
 * determin at which register offset the HDMI encoder is
556
	DRM_DEBUG("Disabling HDMI interface @ 0x%04X for encoder 0x%x\n",
464
 */
-
 
465
void r600_hdmi_init(struct drm_encoder *encoder)
557
		offset, radeon_encoder->encoder_id);
466
{
558
 
467
	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
-
 
468
 
559
	if (ASIC_IS_DCE32(rdev) && !ASIC_IS_DCE4(rdev)) {
469
	switch (radeon_encoder->encoder_id) {
-
 
470
	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
-
 
471
	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
560
		WREG32_P(radeon_encoder->hdmi_config_offset + 0x4, 0, ~0x1);
472
	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
-
 
473
		radeon_encoder->hdmi_offset = R600_HDMI_TMDS1;
-
 
474
		break;
561
	} else if (rdev->family >= CHIP_R600 && !ASIC_IS_DCE3(rdev)) {
475
 
562
	switch (radeon_encoder->encoder_id) {
476
	case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
563
	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
477
		switch (r600_audio_tmds_index(encoder)) {
564
			WREG32_P(AVIVO_TMDSA_CNTL, 0, ~0x4);
478
		case 0:
565
			WREG32(offset + R600_HDMI_ENABLE, 0);
479
			radeon_encoder->hdmi_offset = R600_HDMI_TMDS1;
566
		break;
480
			break;
-
 
481
		case 1:
-
 
482
			radeon_encoder->hdmi_offset = R600_HDMI_TMDS2;
-
 
483
			break;
-
 
484
		default:
-
 
485
			radeon_encoder->hdmi_offset = 0;
-
 
486
			break;
-
 
487
		}
-
 
488
	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
-
 
489
		radeon_encoder->hdmi_offset = R600_HDMI_TMDS2;
-
 
490
		break;
-
 
491
 
567
	case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
Line 492... Line -...
492
	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
-
 
493
		radeon_encoder->hdmi_offset = R600_HDMI_DIG;
568
			WREG32_P(AVIVO_LVTMA_CNTL, 0, ~0x4);
494
		break;
-
 
495
 
-
 
496
	default:
569
			WREG32(offset + R600_HDMI_ENABLE, 0);
497
		radeon_encoder->hdmi_offset = 0;
570
			break;