Subversion Repositories Kolibri OS

Rev

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

Rev Author Line No. Line
5078 serge 1
/*
2
 * Copyright 2013 Advanced Micro Devices, Inc.
3
 *
4
 * Permission is hereby granted, free of charge, to any person obtaining a
5
 * copy of this software and associated documentation files (the "Software"),
6
 * to deal in the Software without restriction, including without limitation
7
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8
 * and/or sell copies of the Software, and to permit persons to whom the
9
 * Software is furnished to do so, subject to the following conditions:
10
 *
11
 * The above copyright notice and this permission notice shall be included in
12
 * all copies or substantial portions of the Software.
13
 *
14
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17
 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18
 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19
 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20
 * OTHER DEALINGS IN THE SOFTWARE.
21
 *
22
 */
23
#include 
24
#include 
25
#include "radeon.h"
26
#include "sid.h"
27
 
28
static u32 dce6_endpoint_rreg(struct radeon_device *rdev,
29
			      u32 block_offset, u32 reg)
30
{
31
	unsigned long flags;
32
	u32 r;
33
 
34
	spin_lock_irqsave(&rdev->end_idx_lock, flags);
35
	WREG32(AZ_F0_CODEC_ENDPOINT_INDEX + block_offset, reg);
36
	r = RREG32(AZ_F0_CODEC_ENDPOINT_DATA + block_offset);
37
	spin_unlock_irqrestore(&rdev->end_idx_lock, flags);
38
 
39
	return r;
40
}
41
 
42
static void dce6_endpoint_wreg(struct radeon_device *rdev,
43
			       u32 block_offset, u32 reg, u32 v)
44
{
45
	unsigned long flags;
46
 
47
	spin_lock_irqsave(&rdev->end_idx_lock, flags);
48
	if (ASIC_IS_DCE8(rdev))
49
		WREG32(AZ_F0_CODEC_ENDPOINT_INDEX + block_offset, reg);
50
	else
51
		WREG32(AZ_F0_CODEC_ENDPOINT_INDEX + block_offset,
52
		       AZ_ENDPOINT_REG_WRITE_EN | AZ_ENDPOINT_REG_INDEX(reg));
53
	WREG32(AZ_F0_CODEC_ENDPOINT_DATA + block_offset, v);
54
	spin_unlock_irqrestore(&rdev->end_idx_lock, flags);
55
}
56
 
57
#define RREG32_ENDPOINT(block, reg) dce6_endpoint_rreg(rdev, (block), (reg))
58
#define WREG32_ENDPOINT(block, reg, v) dce6_endpoint_wreg(rdev, (block), (reg), (v))
59
 
60
 
61
static void dce6_afmt_get_connected_pins(struct radeon_device *rdev)
62
{
63
	int i;
64
	u32 offset, tmp;
65
 
66
	for (i = 0; i < rdev->audio.num_pins; i++) {
67
		offset = rdev->audio.pin[i].offset;
68
		tmp = RREG32_ENDPOINT(offset,
69
				      AZ_F0_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT);
70
		if (((tmp & PORT_CONNECTIVITY_MASK) >> PORT_CONNECTIVITY_SHIFT) == 1)
71
			rdev->audio.pin[i].connected = false;
72
		else
73
			rdev->audio.pin[i].connected = true;
74
	}
75
}
76
 
77
struct r600_audio_pin *dce6_audio_get_pin(struct radeon_device *rdev)
78
{
79
	int i;
80
 
81
	dce6_afmt_get_connected_pins(rdev);
82
 
83
	for (i = 0; i < rdev->audio.num_pins; i++) {
84
		if (rdev->audio.pin[i].connected)
85
			return &rdev->audio.pin[i];
86
	}
87
	DRM_ERROR("No connected audio pins found!\n");
88
	return NULL;
89
}
90
 
91
void dce6_afmt_select_pin(struct drm_encoder *encoder)
92
{
93
	struct radeon_device *rdev = encoder->dev->dev_private;
94
	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
95
	struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
96
	u32 offset;
97
 
98
	if (!dig || !dig->afmt || !dig->afmt->pin)
99
		return;
100
 
101
	offset = dig->afmt->offset;
102
 
103
	WREG32(AFMT_AUDIO_SRC_CONTROL + offset,
104
	       AFMT_AUDIO_SRC_SELECT(dig->afmt->pin->id));
105
}
106
 
107
void dce6_afmt_write_latency_fields(struct drm_encoder *encoder,
108
				    struct drm_display_mode *mode)
109
{
110
	struct radeon_device *rdev = encoder->dev->dev_private;
111
	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
112
	struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
113
	struct drm_connector *connector;
114
	struct radeon_connector *radeon_connector = NULL;
115
	u32 tmp = 0, offset;
116
 
117
	if (!dig || !dig->afmt || !dig->afmt->pin)
118
		return;
119
 
120
	offset = dig->afmt->pin->offset;
121
 
122
	list_for_each_entry(connector, &encoder->dev->mode_config.connector_list, head) {
123
		if (connector->encoder == encoder) {
124
			radeon_connector = to_radeon_connector(connector);
125
			break;
126
		}
127
	}
128
 
129
	if (!radeon_connector) {
130
		DRM_ERROR("Couldn't find encoder's connector\n");
131
		return;
132
	}
133
 
134
	if (mode->flags & DRM_MODE_FLAG_INTERLACE) {
135
		if (connector->latency_present[1])
136
			tmp = VIDEO_LIPSYNC(connector->video_latency[1]) |
137
				AUDIO_LIPSYNC(connector->audio_latency[1]);
138
		else
139
			tmp = VIDEO_LIPSYNC(0) | AUDIO_LIPSYNC(0);
140
	} else {
141
		if (connector->latency_present[0])
142
			tmp = VIDEO_LIPSYNC(connector->video_latency[0]) |
143
				AUDIO_LIPSYNC(connector->audio_latency[0]);
144
		else
145
			tmp = VIDEO_LIPSYNC(0) | AUDIO_LIPSYNC(0);
146
	}
147
	WREG32_ENDPOINT(offset, AZ_F0_CODEC_PIN_CONTROL_RESPONSE_LIPSYNC, tmp);
148
}
149
 
150
void dce6_afmt_write_speaker_allocation(struct drm_encoder *encoder)
151
{
152
	struct radeon_device *rdev = encoder->dev->dev_private;
153
	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
154
	struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
155
	struct drm_connector *connector;
156
	struct radeon_connector *radeon_connector = NULL;
157
	u32 offset, tmp;
158
	u8 *sadb;
159
	int sad_count;
160
 
161
	if (!dig || !dig->afmt || !dig->afmt->pin)
162
		return;
163
 
164
	offset = dig->afmt->pin->offset;
165
 
166
	list_for_each_entry(connector, &encoder->dev->mode_config.connector_list, head) {
167
		if (connector->encoder == encoder) {
168
			radeon_connector = to_radeon_connector(connector);
169
			break;
170
		}
171
	}
172
 
173
	if (!radeon_connector) {
174
		DRM_ERROR("Couldn't find encoder's connector\n");
175
		return;
176
	}
177
 
178
	sad_count = drm_edid_to_speaker_allocation(radeon_connector_edid(connector), &sadb);
5179 serge 179
	if (sad_count < 0) {
180
		DRM_DEBUG("Couldn't read Speaker Allocation Data Block: %d\n", sad_count);
181
		sad_count = 0;
5078 serge 182
	}
183
 
184
	/* program the speaker allocation */
185
	tmp = RREG32_ENDPOINT(offset, AZ_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER);
186
	tmp &= ~(DP_CONNECTION | SPEAKER_ALLOCATION_MASK);
187
	/* set HDMI mode */
188
	tmp |= HDMI_CONNECTION;
189
	if (sad_count)
190
		tmp |= SPEAKER_ALLOCATION(sadb[0]);
191
	else
192
		tmp |= SPEAKER_ALLOCATION(5); /* stereo */
193
	WREG32_ENDPOINT(offset, AZ_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER, tmp);
194
 
195
	kfree(sadb);
196
}
197
 
198
void dce6_afmt_write_sad_regs(struct drm_encoder *encoder)
199
{
200
	struct radeon_device *rdev = encoder->dev->dev_private;
201
	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
202
	struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
203
	u32 offset;
204
	struct drm_connector *connector;
205
	struct radeon_connector *radeon_connector = NULL;
206
	struct cea_sad *sads;
207
	int i, sad_count;
208
 
209
	static const u16 eld_reg_to_type[][2] = {
210
		{ AZ_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR0, HDMI_AUDIO_CODING_TYPE_PCM },
211
		{ AZ_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR1, HDMI_AUDIO_CODING_TYPE_AC3 },
212
		{ AZ_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR2, HDMI_AUDIO_CODING_TYPE_MPEG1 },
213
		{ AZ_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR3, HDMI_AUDIO_CODING_TYPE_MP3 },
214
		{ AZ_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR4, HDMI_AUDIO_CODING_TYPE_MPEG2 },
215
		{ AZ_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR5, HDMI_AUDIO_CODING_TYPE_AAC_LC },
216
		{ AZ_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR6, HDMI_AUDIO_CODING_TYPE_DTS },
217
		{ AZ_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR7, HDMI_AUDIO_CODING_TYPE_ATRAC },
218
		{ AZ_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR9, HDMI_AUDIO_CODING_TYPE_EAC3 },
219
		{ AZ_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR10, HDMI_AUDIO_CODING_TYPE_DTS_HD },
220
		{ AZ_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR11, HDMI_AUDIO_CODING_TYPE_MLP },
221
		{ AZ_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR13, HDMI_AUDIO_CODING_TYPE_WMA_PRO },
222
	};
223
 
224
	if (!dig || !dig->afmt || !dig->afmt->pin)
225
		return;
226
 
227
	offset = dig->afmt->pin->offset;
228
 
229
	list_for_each_entry(connector, &encoder->dev->mode_config.connector_list, head) {
230
		if (connector->encoder == encoder) {
231
			radeon_connector = to_radeon_connector(connector);
232
			break;
233
		}
234
	}
235
 
236
	if (!radeon_connector) {
237
		DRM_ERROR("Couldn't find encoder's connector\n");
238
		return;
239
	}
240
 
241
	sad_count = drm_edid_to_sad(radeon_connector_edid(connector), &sads);
242
	if (sad_count <= 0) {
243
		DRM_ERROR("Couldn't read SADs: %d\n", sad_count);
244
		return;
245
	}
246
	BUG_ON(!sads);
247
 
248
	for (i = 0; i < ARRAY_SIZE(eld_reg_to_type); i++) {
249
		u32 value = 0;
250
		u8 stereo_freqs = 0;
251
		int max_channels = -1;
252
		int j;
253
 
254
		for (j = 0; j < sad_count; j++) {
255
			struct cea_sad *sad = &sads[j];
256
 
257
			if (sad->format == eld_reg_to_type[i][1]) {
258
				if (sad->channels > max_channels) {
259
					value = MAX_CHANNELS(sad->channels) |
260
						DESCRIPTOR_BYTE_2(sad->byte2) |
261
						SUPPORTED_FREQUENCIES(sad->freq);
262
					max_channels = sad->channels;
263
				}
264
 
265
				if (sad->format == HDMI_AUDIO_CODING_TYPE_PCM)
266
					stereo_freqs |= sad->freq;
267
				else
268
					break;
269
			}
270
		}
271
 
272
		value |= SUPPORTED_FREQUENCIES_STEREO(stereo_freqs);
273
 
274
		WREG32_ENDPOINT(offset, eld_reg_to_type[i][0], value);
275
	}
276
 
277
	kfree(sads);
278
}
279
 
280
static int dce6_audio_chipset_supported(struct radeon_device *rdev)
281
{
282
	return !ASIC_IS_NODCE(rdev);
283
}
284
 
285
void dce6_audio_enable(struct radeon_device *rdev,
286
		       struct r600_audio_pin *pin,
287
		       bool enable)
288
{
289
	if (!pin)
290
		return;
291
 
292
	WREG32_ENDPOINT(pin->offset, AZ_F0_CODEC_PIN_CONTROL_HOTPLUG_CONTROL,
293
			enable ? AUDIO_ENABLED : 0);
294
}
295
 
296
static const u32 pin_offsets[7] =
297
{
298
	(0x5e00 - 0x5e00),
299
	(0x5e18 - 0x5e00),
300
	(0x5e30 - 0x5e00),
301
	(0x5e48 - 0x5e00),
302
	(0x5e60 - 0x5e00),
303
	(0x5e78 - 0x5e00),
304
	(0x5e90 - 0x5e00),
305
};
306
 
307
int dce6_audio_init(struct radeon_device *rdev)
308
{
309
	int i;
310
 
311
	if (!radeon_audio || !dce6_audio_chipset_supported(rdev))
312
		return 0;
313
 
314
	rdev->audio.enabled = true;
315
 
316
	if (ASIC_IS_DCE81(rdev)) /* KV: 4 streams, 7 endpoints */
317
		rdev->audio.num_pins = 7;
318
	else if (ASIC_IS_DCE83(rdev)) /* KB: 2 streams, 3 endpoints */
319
		rdev->audio.num_pins = 3;
320
	else if (ASIC_IS_DCE8(rdev)) /* BN/HW: 6 streams, 7 endpoints */
321
		rdev->audio.num_pins = 7;
322
	else if (ASIC_IS_DCE61(rdev)) /* TN: 4 streams, 6 endpoints */
323
		rdev->audio.num_pins = 6;
324
	else if (ASIC_IS_DCE64(rdev)) /* OL: 2 streams, 2 endpoints */
325
		rdev->audio.num_pins = 2;
326
	else /* SI: 6 streams, 6 endpoints */
327
		rdev->audio.num_pins = 6;
328
 
329
	for (i = 0; i < rdev->audio.num_pins; i++) {
330
		rdev->audio.pin[i].channels = -1;
331
		rdev->audio.pin[i].rate = -1;
332
		rdev->audio.pin[i].bits_per_sample = -1;
333
		rdev->audio.pin[i].status_bits = 0;
334
		rdev->audio.pin[i].category_code = 0;
335
		rdev->audio.pin[i].connected = false;
336
		rdev->audio.pin[i].offset = pin_offsets[i];
337
		rdev->audio.pin[i].id = i;
338
		/* disable audio.  it will be set up later */
339
		dce6_audio_enable(rdev, &rdev->audio.pin[i], false);
340
	}
341
 
342
	return 0;
343
}
344
 
345
void dce6_audio_fini(struct radeon_device *rdev)
346
{
347
	int i;
348
 
349
	if (!rdev->audio.enabled)
350
		return;
351
 
352
	for (i = 0; i < rdev->audio.num_pins; i++)
353
		dce6_audio_enable(rdev, &rdev->audio.pin[i], false);
354
 
355
	rdev->audio.enabled = false;
356
}