Subversion Repositories Kolibri OS

Rev

Rev 1963 | Rev 2997 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1403 serge 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"
2005 serge 29
#include "radeon_asic.h"
1403 serge 30
#include "atom.h"
31
 
32
#define AUDIO_TIMER_INTERVALL 100 /* 1/10 sekund should be enough */
33
 
34
/*
35
 * check if the chipset is supported
36
 */
37
static int r600_audio_chipset_supported(struct radeon_device *rdev)
38
{
1963 serge 39
	return (rdev->family >= CHIP_R600 && rdev->family < CHIP_CEDAR)
1403 serge 40
		|| rdev->family == CHIP_RS600
41
		|| rdev->family == CHIP_RS690
42
		|| rdev->family == CHIP_RS740;
43
}
44
 
45
/*
46
 * current number of channels
47
 */
1963 serge 48
int r600_audio_channels(struct radeon_device *rdev)
1403 serge 49
{
50
	return (RREG32(R600_AUDIO_RATE_BPS_CHANNEL) & 0x7) + 1;
51
}
52
 
53
/*
54
 * current bits per sample
55
 */
1963 serge 56
int r600_audio_bits_per_sample(struct radeon_device *rdev)
1403 serge 57
{
58
	uint32_t value = (RREG32(R600_AUDIO_RATE_BPS_CHANNEL) & 0xF0) >> 4;
59
	switch (value) {
60
	case 0x0: return  8;
61
	case 0x1: return 16;
62
	case 0x2: return 20;
63
	case 0x3: return 24;
64
	case 0x4: return 32;
65
	}
66
 
1963 serge 67
	dev_err(rdev->dev, "Unknown bits per sample 0x%x using 16 instead\n",
68
		(int)value);
1403 serge 69
 
70
	return 16;
71
}
72
 
73
/*
74
 * current sampling rate in HZ
75
 */
1963 serge 76
int r600_audio_rate(struct radeon_device *rdev)
1403 serge 77
{
78
	uint32_t value = RREG32(R600_AUDIO_RATE_BPS_CHANNEL);
79
	uint32_t result;
80
 
81
	if (value & 0x4000)
82
		result = 44100;
83
	else
84
		result = 48000;
85
 
86
	result *= ((value >> 11) & 0x7) + 1;
87
	result /= ((value >> 8) & 0x7) + 1;
88
 
89
	return result;
90
}
91
 
92
/*
93
 * iec 60958 status bits
94
 */
1963 serge 95
uint8_t r600_audio_status_bits(struct radeon_device *rdev)
1403 serge 96
{
97
	return RREG32(R600_AUDIO_STATUS_BITS) & 0xff;
98
}
99
 
100
/*
101
 * iec 60958 category code
102
 */
1963 serge 103
uint8_t r600_audio_category_code(struct radeon_device *rdev)
1403 serge 104
{
105
	return (RREG32(R600_AUDIO_STATUS_BITS) >> 8) & 0xff;
106
}
107
 
108
/*
109
 * update all hdmi interfaces with current audio parameters
110
 */
111
static void r600_audio_update_hdmi(unsigned long param)
112
{
113
	struct radeon_device *rdev = (struct radeon_device *)param;
114
	struct drm_device *dev = rdev->ddev;
115
 
116
	int channels = r600_audio_channels(rdev);
117
	int rate = r600_audio_rate(rdev);
118
	int bps = r600_audio_bits_per_sample(rdev);
119
	uint8_t status_bits = r600_audio_status_bits(rdev);
120
	uint8_t category_code = r600_audio_category_code(rdev);
121
 
122
	struct drm_encoder *encoder;
1963 serge 123
	int changes = 0, still_going = 0;
1403 serge 124
 
125
	changes |= channels != rdev->audio_channels;
126
	changes |= rate != rdev->audio_rate;
127
	changes |= bps != rdev->audio_bits_per_sample;
128
	changes |= status_bits != rdev->audio_status_bits;
129
	changes |= category_code != rdev->audio_category_code;
130
 
131
	if (changes) {
132
		rdev->audio_channels = channels;
133
		rdev->audio_rate = rate;
134
		rdev->audio_bits_per_sample = bps;
135
		rdev->audio_status_bits = status_bits;
136
		rdev->audio_category_code = category_code;
137
	}
138
 
139
	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
1963 serge 140
		struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
141
		still_going |= radeon_encoder->audio_polling_active;
1403 serge 142
		if (changes || r600_hdmi_buffer_status_changed(encoder))
1963 serge 143
			r600_hdmi_update_audio_settings(encoder);
1403 serge 144
	}
145
 
146
//   mod_timer(&rdev->audio_timer,
147
//       jiffies + msecs_to_jiffies(AUDIO_TIMER_INTERVALL));
148
}
149
 
150
/*
1430 serge 151
 * turn on/off audio engine
152
 */
153
static void r600_audio_engine_enable(struct radeon_device *rdev, bool enable)
154
{
1963 serge 155
	DRM_INFO("%s audio support\n", enable ? "Enabling" : "Disabling");
1430 serge 156
	WREG32_P(R600_AUDIO_ENABLE, enable ? 0x81000000 : 0x0, ~0x81000000);
1963 serge 157
	rdev->audio_enabled = enable;
1430 serge 158
}
159
 
160
/*
1403 serge 161
 * initialize the audio vars and register the update timer
162
 */
163
int r600_audio_init(struct radeon_device *rdev)
164
{
1430 serge 165
	if (!radeon_audio || !r600_audio_chipset_supported(rdev))
1403 serge 166
		return 0;
167
 
1430 serge 168
	r600_audio_engine_enable(rdev, true);
1403 serge 169
 
170
	rdev->audio_channels = -1;
171
	rdev->audio_rate = -1;
172
	rdev->audio_bits_per_sample = -1;
173
	rdev->audio_status_bits = 0;
174
	rdev->audio_category_code = 0;
175
 
176
//   setup_timer(
177
//       &rdev->audio_timer,
178
//       r600_audio_update_hdmi,
179
//       (unsigned long)rdev);
180
 
181
//   mod_timer(&rdev->audio_timer, jiffies + 1);
182
 
183
	return 0;
184
}
185
 
186
/*
187
 * atach the audio codec to the clock source of the encoder
188
 */
189
void r600_audio_set_clock(struct drm_encoder *encoder, int clock)
190
{
191
	struct drm_device *dev = encoder->dev;
192
	struct radeon_device *rdev = dev->dev_private;
193
	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
1963 serge 194
	struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
1403 serge 195
	int base_rate = 48000;
196
 
197
	switch (radeon_encoder->encoder_id) {
198
	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
199
	case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
200
		WREG32_P(R600_AUDIO_TIMING, 0, ~0x301);
201
		break;
202
	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
203
	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
204
	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
205
	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
206
		WREG32_P(R600_AUDIO_TIMING, 0x100, ~0x301);
207
		break;
208
	default:
1963 serge 209
		dev_err(rdev->dev, "Unsupported encoder type 0x%02X\n",
1403 serge 210
			  radeon_encoder->encoder_id);
211
		return;
212
	}
213
 
1963 serge 214
	switch (dig->dig_encoder) {
1403 serge 215
	case 0:
1963 serge 216
		WREG32(R600_AUDIO_PLL1_MUL, base_rate * 50);
217
		WREG32(R600_AUDIO_PLL1_DIV, clock * 100);
1403 serge 218
		WREG32(R600_AUDIO_CLK_SRCSEL, 0);
219
		break;
220
 
221
	case 1:
1963 serge 222
		WREG32(R600_AUDIO_PLL2_MUL, base_rate * 50);
223
		WREG32(R600_AUDIO_PLL2_DIV, clock * 100);
1403 serge 224
		WREG32(R600_AUDIO_CLK_SRCSEL, 1);
225
		break;
1963 serge 226
	default:
227
		dev_err(rdev->dev, "Unsupported DIG on encoder 0x%02X\n",
228
			  radeon_encoder->encoder_id);
229
		return;
1403 serge 230
	}
231
}
232
 
233
/*
234
 * release the audio timer
235
 * TODO: How to do this correctly on SMP systems?
236
 */
237
void r600_audio_fini(struct radeon_device *rdev)
238
{
1963 serge 239
	if (!rdev->audio_enabled)
1403 serge 240
		return;
241
 
1430 serge 242
//	del_timer(&rdev->audio_timer);
1403 serge 243
 
1430 serge 244
	r600_audio_engine_enable(rdev, false);
1403 serge 245
}