diff options
| author | Christian Koenig <deathsimple@vodafone.de> | 2009-10-11 17:49:13 -0400 |
|---|---|---|
| committer | Dave Airlie <airlied@redhat.com> | 2009-12-16 00:46:48 -0500 |
| commit | dafc3bd515d6079406986f7748b48adb3c7170f2 (patch) | |
| tree | e59a56d8a29a1823f197b2fd3b9f61b13a317b3a /drivers | |
| parent | 7923c615b811945a9d9f456c92a7a32c34167458 (diff) | |
drm/radeon/kms: HDMI support for R600 KMS
Adding basic HDMI support for R600 KMS, ported from radeonhd ddx.
[airlied:- checkpatch cleanups]
Signed-off-by: Christian Koenig <deathsimple@vodafone.de>
Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/gpu/drm/radeon/Makefile | 2 | ||||
| -rw-r--r-- | drivers/gpu/drm/radeon/r600.c | 5 | ||||
| -rw-r--r-- | drivers/gpu/drm/radeon/r600_audio.c | 267 | ||||
| -rw-r--r-- | drivers/gpu/drm/radeon/r600_hdmi.c | 506 | ||||
| -rw-r--r-- | drivers/gpu/drm/radeon/r600_reg.h | 74 | ||||
| -rw-r--r-- | drivers/gpu/drm/radeon/radeon.h | 24 | ||||
| -rw-r--r-- | drivers/gpu/drm/radeon/radeon_drv.c | 4 | ||||
| -rw-r--r-- | drivers/gpu/drm/radeon/radeon_encoders.c | 16 | ||||
| -rw-r--r-- | drivers/gpu/drm/radeon/radeon_mode.h | 3 |
9 files changed, 895 insertions, 6 deletions
diff --git a/drivers/gpu/drm/radeon/Makefile b/drivers/gpu/drm/radeon/Makefile index feb52eee4314..b5f5fe75e6af 100644 --- a/drivers/gpu/drm/radeon/Makefile +++ b/drivers/gpu/drm/radeon/Makefile | |||
| @@ -49,7 +49,7 @@ radeon-y += radeon_device.o radeon_kms.o \ | |||
| 49 | radeon_cs.o radeon_bios.o radeon_benchmark.o r100.o r300.o r420.o \ | 49 | radeon_cs.o radeon_bios.o radeon_benchmark.o r100.o r300.o r420.o \ |
| 50 | rs400.o rs600.o rs690.o rv515.o r520.o r600.o rv770.o radeon_test.o \ | 50 | rs400.o rs600.o rs690.o rv515.o r520.o r600.o rv770.o radeon_test.o \ |
| 51 | r200.o radeon_legacy_tv.o r600_cs.o r600_blit.o r600_blit_shaders.o \ | 51 | r200.o radeon_legacy_tv.o r600_cs.o r600_blit.o r600_blit_shaders.o \ |
| 52 | r600_blit_kms.o radeon_pm.o atombios_dp.o | 52 | r600_blit_kms.o radeon_pm.o atombios_dp.o r600_audio.o r600_hdmi.o |
| 53 | 53 | ||
| 54 | radeon-$(CONFIG_COMPAT) += radeon_ioc32.o | 54 | radeon-$(CONFIG_COMPAT) += radeon_ioc32.o |
| 55 | 55 | ||
diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index e145faac9904..5c6058c6ddde 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c | |||
| @@ -2067,6 +2067,10 @@ int r600_init(struct radeon_device *rdev) | |||
| 2067 | rdev->accel_working = false; | 2067 | rdev->accel_working = false; |
| 2068 | } | 2068 | } |
| 2069 | } | 2069 | } |
| 2070 | |||
| 2071 | r = r600_audio_init(rdev); | ||
| 2072 | if (r) | ||
| 2073 | return r; /* TODO error handling */ | ||
| 2070 | return 0; | 2074 | return 0; |
| 2071 | } | 2075 | } |
| 2072 | 2076 | ||
| @@ -2075,6 +2079,7 @@ void r600_fini(struct radeon_device *rdev) | |||
| 2075 | /* Suspend operations */ | 2079 | /* Suspend operations */ |
| 2076 | r600_suspend(rdev); | 2080 | r600_suspend(rdev); |
| 2077 | 2081 | ||
| 2082 | r600_audio_fini(rdev); | ||
| 2078 | r600_blit_fini(rdev); | 2083 | r600_blit_fini(rdev); |
| 2079 | r600_irq_fini(rdev); | 2084 | r600_irq_fini(rdev); |
| 2080 | radeon_irq_kms_fini(rdev); | 2085 | radeon_irq_kms_fini(rdev); |
diff --git a/drivers/gpu/drm/radeon/r600_audio.c b/drivers/gpu/drm/radeon/r600_audio.c new file mode 100644 index 000000000000..99e2c3891a7d --- /dev/null +++ b/drivers/gpu/drm/radeon/r600_audio.c | |||
| @@ -0,0 +1,267 @@ | |||
| 1 | /* | ||
| 2 | * Copyright 2008 Advanced Micro Devices, Inc. | ||
| 3 | * Copyright 2008 Red Hat Inc. | ||
| 4 | * Copyright 2009 Christian König. | ||
| 5 | * | ||
| 6 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
| 7 | * copy of this software and associated documentation files (the "Software"), | ||
| 8 | * to deal in the Software without restriction, including without limitation | ||
| 9 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
| 10 | * and/or sell copies of the Software, and to permit persons to whom the | ||
| 11 | * Software is furnished to do so, subject to the following conditions: | ||
| 12 | * | ||
| 13 | * The above copyright notice and this permission notice shall be included in | ||
| 14 | * all copies or substantial portions of the Software. | ||
| 15 | * | ||
| 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
| 19 | * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR | ||
| 20 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | ||
| 21 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | ||
| 22 | * OTHER DEALINGS IN THE SOFTWARE. | ||
| 23 | * | ||
| 24 | * Authors: Christian König | ||
| 25 | */ | ||
| 26 | #include "drmP.h" | ||
| 27 | #include "radeon.h" | ||
| 28 | #include "radeon_reg.h" | ||
| 29 | #include "atom.h" | ||
| 30 | |||
| 31 | #define AUDIO_TIMER_INTERVALL 100 /* 1/10 sekund should be enough */ | ||
| 32 | |||
| 33 | /* | ||
| 34 | * check if the chipset is supported | ||
| 35 | */ | ||
| 36 | static int r600_audio_chipset_supported(struct radeon_device *rdev) | ||
| 37 | { | ||
| 38 | return rdev->family >= CHIP_R600 | ||
| 39 | || rdev->family == CHIP_RS600 | ||
| 40 | || rdev->family == CHIP_RS690 | ||
| 41 | || rdev->family == CHIP_RS740; | ||
| 42 | } | ||
| 43 | |||
| 44 | /* | ||
| 45 | * current number of channels | ||
| 46 | */ | ||
| 47 | static int r600_audio_channels(struct radeon_device *rdev) | ||
| 48 | { | ||
| 49 | return (RREG32(R600_AUDIO_RATE_BPS_CHANNEL) & 0x7) + 1; | ||
| 50 | } | ||
| 51 | |||
| 52 | /* | ||
| 53 | * current bits per sample | ||
| 54 | */ | ||
| 55 | static int r600_audio_bits_per_sample(struct radeon_device *rdev) | ||
| 56 | { | ||
| 57 | uint32_t value = (RREG32(R600_AUDIO_RATE_BPS_CHANNEL) & 0xF0) >> 4; | ||
| 58 | switch (value) { | ||
| 59 | case 0x0: return 8; | ||
| 60 | case 0x1: return 16; | ||
| 61 | case 0x2: return 20; | ||
| 62 | case 0x3: return 24; | ||
| 63 | case 0x4: return 32; | ||
| 64 | } | ||
| 65 | |||
| 66 | DRM_ERROR("Unknown bits per sample 0x%x using 16 instead.\n", (int)value); | ||
| 67 | |||
| 68 | return 16; | ||
| 69 | } | ||
| 70 | |||
| 71 | /* | ||
| 72 | * current sampling rate in HZ | ||
| 73 | */ | ||
| 74 | static int r600_audio_rate(struct radeon_device *rdev) | ||
| 75 | { | ||
| 76 | uint32_t value = RREG32(R600_AUDIO_RATE_BPS_CHANNEL); | ||
| 77 | uint32_t result; | ||
| 78 | |||
| 79 | if (value & 0x4000) | ||
| 80 | result = 44100; | ||
| 81 | else | ||
| 82 | result = 48000; | ||
| 83 | |||
| 84 | result *= ((value >> 11) & 0x7) + 1; | ||
| 85 | result /= ((value >> 8) & 0x7) + 1; | ||
| 86 | |||
| 87 | return result; | ||
| 88 | } | ||
| 89 | |||
| 90 | /* | ||
| 91 | * iec 60958 status bits | ||
| 92 | */ | ||
| 93 | static uint8_t r600_audio_status_bits(struct radeon_device *rdev) | ||
| 94 | { | ||
| 95 | return RREG32(R600_AUDIO_STATUS_BITS) & 0xff; | ||
| 96 | } | ||
| 97 | |||
| 98 | /* | ||
| 99 | * iec 60958 category code | ||
| 100 | */ | ||
| 101 | static uint8_t r600_audio_category_code(struct radeon_device *rdev) | ||
| 102 | { | ||
| 103 | return (RREG32(R600_AUDIO_STATUS_BITS) >> 8) & 0xff; | ||
| 104 | } | ||
| 105 | |||
| 106 | /* | ||
| 107 | * update all hdmi interfaces with current audio parameters | ||
| 108 | */ | ||
| 109 | static void r600_audio_update_hdmi(unsigned long param) | ||
| 110 | { | ||
| 111 | struct radeon_device *rdev = (struct radeon_device *)param; | ||
| 112 | struct drm_device *dev = rdev->ddev; | ||
| 113 | |||
| 114 | int channels = r600_audio_channels(rdev); | ||
| 115 | int rate = r600_audio_rate(rdev); | ||
| 116 | int bps = r600_audio_bits_per_sample(rdev); | ||
| 117 | uint8_t status_bits = r600_audio_status_bits(rdev); | ||
| 118 | uint8_t category_code = r600_audio_category_code(rdev); | ||
| 119 | |||
| 120 | struct drm_encoder *encoder; | ||
| 121 | int changes = 0; | ||
| 122 | |||
| 123 | changes |= channels != rdev->audio_channels; | ||
| 124 | changes |= rate != rdev->audio_rate; | ||
| 125 | changes |= bps != rdev->audio_bits_per_sample; | ||
| 126 | changes |= status_bits != rdev->audio_status_bits; | ||
| 127 | changes |= category_code != rdev->audio_category_code; | ||
| 128 | |||
| 129 | if (changes) { | ||
| 130 | rdev->audio_channels = channels; | ||
| 131 | rdev->audio_rate = rate; | ||
| 132 | rdev->audio_bits_per_sample = bps; | ||
| 133 | rdev->audio_status_bits = status_bits; | ||
| 134 | rdev->audio_category_code = category_code; | ||
| 135 | } | ||
| 136 | |||
| 137 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { | ||
| 138 | if (changes || r600_hdmi_buffer_status_changed(encoder)) | ||
