Subversion Repositories Kolibri OS

Rev

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

Rev Author Line No. Line
1123 serge 1
/*
2
 * Copyright 2007-8 Advanced Micro Devices, Inc.
3
 * Copyright 2008 Red Hat Inc.
4
 *
5
 * Permission is hereby granted, free of charge, to any person obtaining a
6
 * copy of this software and associated documentation files (the "Software"),
7
 * to deal in the Software without restriction, including without limitation
8
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9
 * and/or sell copies of the Software, and to permit persons to whom the
10
 * Software is furnished to do so, subject to the following conditions:
11
 *
12
 * The above copyright notice and this permission notice shall be included in
13
 * all copies or substantial portions of the Software.
14
 *
15
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18
 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
19
 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
20
 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
21
 * OTHER DEALINGS IN THE SOFTWARE.
22
 *
23
 * Authors: Dave Airlie
24
 *          Alex Deucher
25
 */
1179 serge 26
#include 
27
#include 
28
#include 
1123 serge 29
#include "radeon_fixed.h"
30
#include "radeon.h"
31
#include "atom.h"
32
#include "atom-bits.h"
33
 
1179 serge 34
static void atombios_overscan_setup(struct drm_crtc *crtc,
35
				    struct drm_display_mode *mode,
36
				    struct drm_display_mode *adjusted_mode)
37
{
38
	struct drm_device *dev = crtc->dev;
39
	struct radeon_device *rdev = dev->dev_private;
40
	struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
41
	SET_CRTC_OVERSCAN_PS_ALLOCATION args;
42
	int index = GetIndexIntoMasterTable(COMMAND, SetCRTC_OverScan);
43
	int a1, a2;
44
 
45
	memset(&args, 0, sizeof(args));
46
 
47
	args.usOverscanRight = 0;
48
	args.usOverscanLeft = 0;
49
	args.usOverscanBottom = 0;
50
	args.usOverscanTop = 0;
51
	args.ucCRTC = radeon_crtc->crtc_id;
52
 
53
	switch (radeon_crtc->rmx_type) {
54
	case RMX_CENTER:
55
		args.usOverscanTop = (adjusted_mode->crtc_vdisplay - mode->crtc_vdisplay) / 2;
56
		args.usOverscanBottom = (adjusted_mode->crtc_vdisplay - mode->crtc_vdisplay) / 2;
57
		args.usOverscanLeft = (adjusted_mode->crtc_hdisplay - mode->crtc_hdisplay) / 2;
58
		args.usOverscanRight = (adjusted_mode->crtc_hdisplay - mode->crtc_hdisplay) / 2;
59
		atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
60
		break;
61
	case RMX_ASPECT:
62
		a1 = mode->crtc_vdisplay * adjusted_mode->crtc_hdisplay;
63
		a2 = adjusted_mode->crtc_vdisplay * mode->crtc_hdisplay;
64
 
65
		if (a1 > a2) {
66
			args.usOverscanLeft = (adjusted_mode->crtc_hdisplay - (a2 / mode->crtc_vdisplay)) / 2;
67
			args.usOverscanRight = (adjusted_mode->crtc_hdisplay - (a2 / mode->crtc_vdisplay)) / 2;
68
		} else if (a2 > a1) {
69
			args.usOverscanLeft = (adjusted_mode->crtc_vdisplay - (a1 / mode->crtc_hdisplay)) / 2;
70
			args.usOverscanRight = (adjusted_mode->crtc_vdisplay - (a1 / mode->crtc_hdisplay)) / 2;
71
		}
72
		atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
73
		break;
74
	case RMX_FULL:
75
	default:
76
		args.usOverscanRight = 0;
77
		args.usOverscanLeft = 0;
78
		args.usOverscanBottom = 0;
79
		args.usOverscanTop = 0;
80
		atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
81
		break;
82
	}
83
}
84
 
85
static void atombios_scaler_setup(struct drm_crtc *crtc)
86
{
87
	struct drm_device *dev = crtc->dev;
88
	struct radeon_device *rdev = dev->dev_private;
89
	struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
90
	ENABLE_SCALER_PS_ALLOCATION args;
91
	int index = GetIndexIntoMasterTable(COMMAND, EnableScaler);
92
 
93
	/* fixme - fill in enc_priv for atom dac */
94
	enum radeon_tv_std tv_std = TV_STD_NTSC;
95
	bool is_tv = false, is_cv = false;
96
	struct drm_encoder *encoder;
97
 
98
	if (!ASIC_IS_AVIVO(rdev) && radeon_crtc->crtc_id)
99
		return;
100
 
101
	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
102
		/* find tv std */
103
		if (encoder->crtc == crtc) {
104
			struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
105
			if (radeon_encoder->active_device & ATOM_DEVICE_TV_SUPPORT) {
106
				struct radeon_encoder_atom_dac *tv_dac = radeon_encoder->enc_priv;
107
				tv_std = tv_dac->tv_std;
108
				is_tv = true;
109
			}
110
		}
111
	}
112
 
113
	memset(&args, 0, sizeof(args));
114
 
115
	args.ucScaler = radeon_crtc->crtc_id;
116
 
117
	if (is_tv) {
118
		switch (tv_std) {
119
		case TV_STD_NTSC:
120
		default:
121
			args.ucTVStandard = ATOM_TV_NTSC;
122
			break;
123
		case TV_STD_PAL:
124
			args.ucTVStandard = ATOM_TV_PAL;
125
			break;
126
		case TV_STD_PAL_M:
127
			args.ucTVStandard = ATOM_TV_PALM;
128
			break;
129
		case TV_STD_PAL_60:
130
			args.ucTVStandard = ATOM_TV_PAL60;
131
			break;
132
		case TV_STD_NTSC_J:
133
			args.ucTVStandard = ATOM_TV_NTSCJ;
134
			break;
135
		case TV_STD_SCART_PAL:
136
			args.ucTVStandard = ATOM_TV_PAL; /* ??? */
137
			break;
138
		case TV_STD_SECAM:
139
			args.ucTVStandard = ATOM_TV_SECAM;
140
			break;
141
		case TV_STD_PAL_CN:
142
			args.ucTVStandard = ATOM_TV_PALCN;
143
			break;
144
		}
145
		args.ucEnable = SCALER_ENABLE_MULTITAP_MODE;
146
	} else if (is_cv) {
147
		args.ucTVStandard = ATOM_TV_CV;
148
		args.ucEnable = SCALER_ENABLE_MULTITAP_MODE;
149
	} else {
150
		switch (radeon_crtc->rmx_type) {
151
		case RMX_FULL:
152
			args.ucEnable = ATOM_SCALER_EXPANSION;
153
			break;
154
		case RMX_CENTER:
155
			args.ucEnable = ATOM_SCALER_CENTER;
156
			break;
157
		case RMX_ASPECT:
158
			args.ucEnable = ATOM_SCALER_EXPANSION;
159
			break;
160
		default:
161
			if (ASIC_IS_AVIVO(rdev))
162
				args.ucEnable = ATOM_SCALER_DISABLE;
163
			else
164
				args.ucEnable = ATOM_SCALER_CENTER;
165
			break;
166
		}
167
	}
168
	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
169
	if ((is_tv || is_cv)
170
	    && rdev->family >= CHIP_RV515 && rdev->family <= CHIP_R580) {
171
		atom_rv515_force_tv_scaler(rdev, radeon_crtc);
172
	}
173
}
174
 
1123 serge 175
static void atombios_lock_crtc(struct drm_crtc *crtc, int lock)
176
{
177
	struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
178
	struct drm_device *dev = crtc->dev;
179
	struct radeon_device *rdev = dev->dev_private;
180
	int index =
181
	    GetIndexIntoMasterTable(COMMAND, UpdateCRTC_DoubleBufferRegisters);
182
	ENABLE_CRTC_PS_ALLOCATION args;
183
 
184
	memset(&args, 0, sizeof(args));
185
 
186
	args.ucCRTC = radeon_crtc->crtc_id;
187
	args.ucEnable = lock;
188
 
189
	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
190
}
191
 
192
static void atombios_enable_crtc(struct drm_crtc *crtc, int state)
193
{
194
	struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
195
	struct drm_device *dev = crtc->dev;
196
	struct radeon_device *rdev = dev->dev_private;
197
	int index = GetIndexIntoMasterTable(COMMAND, EnableCRTC);
198
	ENABLE_CRTC_PS_ALLOCATION args;
199
 
200
	memset(&args, 0, sizeof(args));
201
 
202
	args.ucCRTC = radeon_crtc->crtc_id;
203
	args.ucEnable = state;
204
 
205
	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
206
}
207
 
208
static void atombios_enable_crtc_memreq(struct drm_crtc *crtc, int state)
209
{
210
	struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
211
	struct drm_device *dev = crtc->dev;
212
	struct radeon_device *rdev = dev->dev_private;
213
	int index = GetIndexIntoMasterTable(COMMAND, EnableCRTCMemReq);
214
	ENABLE_CRTC_PS_ALLOCATION args;
215
 
216
	memset(&args, 0, sizeof(args));
217
 
218
	args.ucCRTC = radeon_crtc->crtc_id;
219
	args.ucEnable = state;
220
 
221
	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
222
}
223
 
224
static void atombios_blank_crtc(struct drm_crtc *crtc, int state)
225
{
226
	struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
227
	struct drm_device *dev = crtc->dev;
228
	struct radeon_device *rdev = dev->dev_private;
229
	int index = GetIndexIntoMasterTable(COMMAND, BlankCRTC);
230
	BLANK_CRTC_PS_ALLOCATION args;
231
 
232
	memset(&args, 0, sizeof(args));
233
 
234
	args.ucCRTC = radeon_crtc->crtc_id;
235
	args.ucBlanking = state;
236
 
237
	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
238
}
239
 
240
void atombios_crtc_dpms(struct drm_crtc *crtc, int mode)
241
{
242
	struct drm_device *dev = crtc->dev;
243
	struct radeon_device *rdev = dev->dev_private;
1321 serge 244
	struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
1123 serge 245
 
246
	switch (mode) {
247
	case DRM_MODE_DPMS_ON:
1268 serge 248
		atombios_enable_crtc(crtc, 1);
1123 serge 249
		if (ASIC_IS_DCE3(rdev))
250
			atombios_enable_crtc_memreq(crtc, 1);
251
		atombios_blank_crtc(crtc, 0);
1321 serge 252
		radeon_crtc_load_lut(crtc);
1123 serge 253
		break;
254
	case DRM_MODE_DPMS_STANDBY:
255
	case DRM_MODE_DPMS_SUSPEND:
256
	case DRM_MODE_DPMS_OFF:
257
		atombios_blank_crtc(crtc, 1);
258
		if (ASIC_IS_DCE3(rdev))
259
			atombios_enable_crtc_memreq(crtc, 0);
1268 serge 260
		atombios_enable_crtc(crtc, 0);
1123 serge 261
		break;
262
	}
263
}
264
 
265
static void
266
atombios_set_crtc_dtd_timing(struct drm_crtc *crtc,
1268 serge 267
			     struct drm_display_mode *mode)
1123 serge 268
{
1268 serge 269
	struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
1123 serge 270
	struct drm_device *dev = crtc->dev;
271
	struct radeon_device *rdev = dev->dev_private;
1268 serge 272
	SET_CRTC_USING_DTD_TIMING_PARAMETERS args;
1123 serge 273
	int index = GetIndexIntoMasterTable(COMMAND, SetCRTC_UsingDTDTiming);
1268 serge 274
	u16 misc = 0;
1123 serge 275
 
1268 serge 276
	memset(&args, 0, sizeof(args));
277
	args.usH_Size = cpu_to_le16(mode->crtc_hdisplay);
278
	args.usH_Blanking_Time =
279
		cpu_to_le16(mode->crtc_hblank_end - mode->crtc_hdisplay);
280
	args.usV_Size = cpu_to_le16(mode->crtc_vdisplay);
281
	args.usV_Blanking_Time =
282
	    cpu_to_le16(mode->crtc_vblank_end - mode->crtc_vdisplay);
283
	args.usH_SyncOffset =
284
		cpu_to_le16(mode->crtc_hsync_start - mode->crtc_hdisplay);
285
	args.usH_SyncWidth =
286
		cpu_to_le16(mode->crtc_hsync_end - mode->crtc_hsync_start);
287
	args.usV_SyncOffset =
288
		cpu_to_le16(mode->crtc_vsync_start - mode->crtc_vdisplay);
289
	args.usV_SyncWidth =
290
		cpu_to_le16(mode->crtc_vsync_end - mode->crtc_vsync_start);
291
	/*args.ucH_Border = mode->hborder;*/
292
	/*args.ucV_Border = mode->vborder;*/
1123 serge 293
 
1268 serge 294
	if (mode->flags & DRM_MODE_FLAG_NVSYNC)
295
		misc |= ATOM_VSYNC_POLARITY;
296
	if (mode->flags & DRM_MODE_FLAG_NHSYNC)
297
		misc |= ATOM_HSYNC_POLARITY;
298
	if (mode->flags & DRM_MODE_FLAG_CSYNC)
299
		misc |= ATOM_COMPOSITESYNC;
300
	if (mode->flags & DRM_MODE_FLAG_INTERLACE)
301
		misc |= ATOM_INTERLACE;
302
	if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
303
		misc |= ATOM_DOUBLE_CLOCK_MODE;
304
 
305
	args.susModeMiscInfo.usAccess = cpu_to_le16(misc);
306
	args.ucCRTC = radeon_crtc->crtc_id;
307
 
308
	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
1123 serge 309
}
310
 
1268 serge 311
static void atombios_crtc_set_timing(struct drm_crtc *crtc,
312
				     struct drm_display_mode *mode)
1123 serge 313
{
1268 serge 314
	struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
1123 serge 315
	struct drm_device *dev = crtc->dev;
316
	struct radeon_device *rdev = dev->dev_private;
1268 serge 317
	SET_CRTC_TIMING_PARAMETERS_PS_ALLOCATION args;
1123 serge 318
	int index = GetIndexIntoMasterTable(COMMAND, SetCRTC_Timing);
1268 serge 319
	u16 misc = 0;
1123 serge 320
 
1268 serge 321
	memset(&args, 0, sizeof(args));
322
	args.usH_Total = cpu_to_le16(mode->crtc_htotal);
323
	args.usH_Disp = cpu_to_le16(mode->crtc_hdisplay);
324
	args.usH_SyncStart = cpu_to_le16(mode->crtc_hsync_start);
325
	args.usH_SyncWidth =
326
		cpu_to_le16(mode->crtc_hsync_end - mode->crtc_hsync_start);
327
	args.usV_Total = cpu_to_le16(mode->crtc_vtotal);
328
	args.usV_Disp = cpu_to_le16(mode->crtc_vdisplay);
329
	args.usV_SyncStart = cpu_to_le16(mode->crtc_vsync_start);
330
	args.usV_SyncWidth =
331
		cpu_to_le16(mode->crtc_vsync_end - mode->crtc_vsync_start);
1123 serge 332
 
1268 serge 333
	if (mode->flags & DRM_MODE_FLAG_NVSYNC)
334
		misc |= ATOM_VSYNC_POLARITY;
335
	if (mode->flags & DRM_MODE_FLAG_NHSYNC)
336
		misc |= ATOM_HSYNC_POLARITY;
337
	if (mode->flags & DRM_MODE_FLAG_CSYNC)
338
		misc |= ATOM_COMPOSITESYNC;
339
	if (mode->flags & DRM_MODE_FLAG_INTERLACE)
340
		misc |= ATOM_INTERLACE;
341
	if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
342
		misc |= ATOM_DOUBLE_CLOCK_MODE;
343
 
344
	args.susModeMiscInfo.usAccess = cpu_to_le16(misc);
345
	args.ucCRTC = radeon_crtc->crtc_id;
346
 
347
	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
1123 serge 348
}
349
 
1268 serge 350
static void atombios_set_ss(struct drm_crtc *crtc, int enable)
351
{
352
	struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
353
	struct drm_device *dev = crtc->dev;
354
	struct radeon_device *rdev = dev->dev_private;
355
	struct drm_encoder *encoder = NULL;
356
	struct radeon_encoder *radeon_encoder = NULL;
357
	struct radeon_encoder_atom_dig *dig = NULL;
358
	int index = GetIndexIntoMasterTable(COMMAND, EnableSpreadSpectrumOnPPLL);
359
	ENABLE_SPREAD_SPECTRUM_ON_PPLL_PS_ALLOCATION args;
360
	ENABLE_LVDS_SS_PARAMETERS legacy_args;
361
	uint16_t percentage = 0;
362
	uint8_t type = 0, step = 0, delay = 0, range = 0;
363
 
364
	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
365
		if (encoder->crtc == crtc) {
366
			radeon_encoder = to_radeon_encoder(encoder);
367
			/* only enable spread spectrum on LVDS */
368
			if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
369
				dig = radeon_encoder->enc_priv;
370
				if (dig && dig->ss) {
371
					percentage = dig->ss->percentage;
372
					type = dig->ss->type;
373
					step = dig->ss->step;
374
					delay = dig->ss->delay;
375
					range = dig->ss->range;
376
				} else if (enable)
377
					return;
378
			} else if (enable)
379
				return;
380
			break;
381
		}
382
	}
383
 
384
	if (!radeon_encoder)
385
		return;
386
 
387
	if (ASIC_IS_AVIVO(rdev)) {
388
		memset(&args, 0, sizeof(args));
389
		args.usSpreadSpectrumPercentage = cpu_to_le16(percentage);
390
		args.ucSpreadSpectrumType = type;
391
		args.ucSpreadSpectrumStep = step;
392
		args.ucSpreadSpectrumDelay = delay;
393
		args.ucSpreadSpectrumRange = range;
394
		args.ucPpll = radeon_crtc->crtc_id ? ATOM_PPLL2 : ATOM_PPLL1;
395
		args.ucEnable = enable;
396
		atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
397
	} else {
398
		memset(&legacy_args, 0, sizeof(legacy_args));
399
		legacy_args.usSpreadSpectrumPercentage = cpu_to_le16(percentage);
400
		legacy_args.ucSpreadSpectrumType = type;
401
		legacy_args.ucSpreadSpectrumStepSize_Delay = (step & 3) << 2;
402
		legacy_args.ucSpreadSpectrumStepSize_Delay |= (delay & 7) << 4;
403
		legacy_args.ucEnable = enable;
404
		atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&legacy_args);
405
	}
406
}
407
 
1404 serge 408
union adjust_pixel_clock {
409
	ADJUST_DISPLAY_PLL_PS_ALLOCATION v1;
410
};
411
 
412
static u32 atombios_adjust_pll(struct drm_crtc *crtc,
413
			       struct drm_display_mode *mode,
414
			       struct radeon_pll *pll)
1123 serge 415
{
416
	struct drm_device *dev = crtc->dev;
417
	struct radeon_device *rdev = dev->dev_private;
418
	struct drm_encoder *encoder = NULL;
419
	struct radeon_encoder *radeon_encoder = NULL;
1404 serge 420
	u32 adjusted_clock = mode->clock;
1123 serge 421
 
1404 serge 422
	/* reset the pll flags */
423
	pll->flags = 0;
1123 serge 424
 
425
	if (ASIC_IS_AVIVO(rdev)) {
1179 serge 426
		if ((rdev->family == CHIP_RS600) ||
427
		    (rdev->family == CHIP_RS690) ||
428
		    (rdev->family == CHIP_RS740))
1404 serge 429
			pll->flags |= (RADEON_PLL_USE_FRAC_FB_DIV |
1179 serge 430
				      RADEON_PLL_PREFER_CLOSEST_LOWER);
431
 
1123 serge 432
		if (ASIC_IS_DCE32(rdev) && mode->clock > 200000)	/* range limits??? */
1404 serge 433
			pll->flags |= RADEON_PLL_PREFER_HIGH_FB_DIV;
1123 serge 434
		else
1404 serge 435
			pll->flags |= RADEON_PLL_PREFER_LOW_REF_DIV;
1123 serge 436
	} else {
1404 serge 437
		pll->flags |= RADEON_PLL_LEGACY;
1123 serge 438
 
439
		if (mode->clock > 200000)	/* range limits??? */
1404 serge 440
			pll->flags |= RADEON_PLL_PREFER_HIGH_FB_DIV;
1123 serge 441
		else
1404 serge 442
			pll->flags |= RADEON_PLL_PREFER_LOW_REF_DIV;
1123 serge 443
 
444
	}
445
 
446
	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
447
		if (encoder->crtc == crtc) {
1404 serge 448
			radeon_encoder = to_radeon_encoder(encoder);
449
			if (ASIC_IS_AVIVO(rdev)) {
450
				/* DVO wants 2x pixel clock if the DVO chip is in 12 bit mode */
451
				if (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1)
452
					adjusted_clock = mode->clock * 2;
453
			} else {
454
				if (encoder->encoder_type != DRM_MODE_ENCODER_DAC)
455
					pll->flags |= RADEON_PLL_NO_ODD_POST_DIV;
456
				if (encoder->encoder_type == DRM_MODE_ENCODER_LVDS)
457
					pll->flags |= RADEON_PLL_USE_REF_DIV;
1123 serge 458
			}
1179 serge 459
			break;
1123 serge 460
		}
461
	}
462
 
1268 serge 463
	/* DCE3+ has an AdjustDisplayPll that will adjust the pixel clock
464
	 * accordingly based on the encoder/transmitter to work around
465
	 * special hw requirements.
466
	 */
467
	if (ASIC_IS_DCE3(rdev)) {
1404 serge 468
		union adjust_pixel_clock args;
469
		struct radeon_encoder_atom_dig *dig;
470
		u8 frev, crev;
471
		int index;
1268 serge 472
 
1404 serge 473
		if (!radeon_encoder->enc_priv)
474
			return adjusted_clock;
475
		dig = radeon_encoder->enc_priv;
1268 serge 476
 
1404 serge 477
		index = GetIndexIntoMasterTable(COMMAND, AdjustDisplayPll);
478
		atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev,
479
				      &crev);
1268 serge 480
 
1404 serge 481
		memset(&args, 0, sizeof(args));
482
 
483
		switch (frev) {
484
		case 1:
485
			switch (crev) {
486
			case 1:
487
			case 2:
488
				args.v1.usPixelClock = cpu_to_le16(mode->clock / 10);
489
				args.v1.ucTransmitterID = radeon_encoder->encoder_id;
490
				args.v1.ucEncodeMode = atombios_get_encoder_mode(encoder);
491
 
1268 serge 492
		atom_execute_table(rdev->mode_info.atom_context,
1404 serge 493
						   index, (uint32_t *)&args);
494
				adjusted_clock = le16_to_cpu(args.v1.usPixelClock) * 10;
495
				break;
496
			default:
497
				DRM_ERROR("Unknown table version %d %d\n", frev, crev);
498
				return adjusted_clock;
499
			}
500
			break;
501
		default:
502
			DRM_ERROR("Unknown table version %d %d\n", frev, crev);
503
			return adjusted_clock;
504
		}
1268 serge 505
	}
1404 serge 506
	return adjusted_clock;
507
}
1268 serge 508
 
1404 serge 509
union set_pixel_clock {
510
	SET_PIXEL_CLOCK_PS_ALLOCATION base;
511
	PIXEL_CLOCK_PARAMETERS v1;
512
	PIXEL_CLOCK_PARAMETERS_V2 v2;
513
	PIXEL_CLOCK_PARAMETERS_V3 v3;
514
};
515
 
516
void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode)
517
{
518
	struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
519
	struct drm_device *dev = crtc->dev;
520
	struct radeon_device *rdev = dev->dev_private;
521
	struct drm_encoder *encoder = NULL;
522
	struct radeon_encoder *radeon_encoder = NULL;
523
	u8 frev, crev;
524
	int index;
525
	union set_pixel_clock args;
526
	u32 pll_clock = mode->clock;
527
	u32 ref_div = 0, fb_div = 0, frac_fb_div = 0, post_div = 0;
528
	struct radeon_pll *pll;
529
	u32 adjusted_clock;
530
 
531
	memset(&args, 0, sizeof(args));
532
 
533
	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
534
		if (encoder->crtc == crtc) {
535
			radeon_encoder = to_radeon_encoder(encoder);
536
			break;
537
		}
538
	}
539
 
540
	if (!radeon_encoder)
541
		return;
542
 
1123 serge 543
	if (radeon_crtc->crtc_id == 0)
544
		pll = &rdev->clock.p1pll;
545
	else
546
		pll = &rdev->clock.p2pll;
547
 
1404 serge 548
	/* adjust pixel clock as needed */
549
	adjusted_clock = atombios_adjust_pll(crtc, mode, pll);
550
 
1321 serge 551
	if (ASIC_IS_AVIVO(rdev)) {
552
		if (radeon_new_pll)
553
			radeon_compute_pll_avivo(pll, adjusted_clock, &pll_clock,
554
						 &fb_div, &frac_fb_div,
1404 serge 555
						 &ref_div, &post_div);
1321 serge 556
		else
557
			radeon_compute_pll(pll, adjusted_clock, &pll_clock,
558
					   &fb_div, &frac_fb_div,
1404 serge 559
					   &ref_div, &post_div);
1321 serge 560
	} else
1268 serge 561
	radeon_compute_pll(pll, adjusted_clock, &pll_clock, &fb_div, &frac_fb_div,
1404 serge 562
				   &ref_div, &post_div);
1123 serge 563
 
1268 serge 564
	index = GetIndexIntoMasterTable(COMMAND, SetPixelClock);
1123 serge 565
	atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev,
566
			      &crev);
567
 
568
	switch (frev) {
569
	case 1:
570
		switch (crev) {
571
		case 1:
1404 serge 572
			args.v1.usPixelClock = cpu_to_le16(mode->clock / 10);
573
			args.v1.usRefDiv = cpu_to_le16(ref_div);
574
			args.v1.usFbDiv = cpu_to_le16(fb_div);
575
			args.v1.ucFracFbDiv = frac_fb_div;
576
			args.v1.ucPostDiv = post_div;
577
			args.v1.ucPpll =
1123 serge 578
			    radeon_crtc->crtc_id ? ATOM_PPLL2 : ATOM_PPLL1;
1404 serge 579
			args.v1.ucCRTC = radeon_crtc->crtc_id;
580
			args.v1.ucRefDivSrc = 1;
1123 serge 581
			break;
582
		case 2:
1404 serge 583
			args.v2.usPixelClock = cpu_to_le16(mode->clock / 10);
584
			args.v2.usRefDiv = cpu_to_le16(ref_div);
585
			args.v2.usFbDiv = cpu_to_le16(fb_div);
586
			args.v2.ucFracFbDiv = frac_fb_div;
587
			args.v2.ucPostDiv = post_div;
588
			args.v2.ucPpll =
1123 serge 589
			    radeon_crtc->crtc_id ? ATOM_PPLL2 : ATOM_PPLL1;
1404 serge 590
			args.v2.ucCRTC = radeon_crtc->crtc_id;
591
			args.v2.ucRefDivSrc = 1;
1123 serge 592
			break;
593
		case 3:
1404 serge 594
			args.v3.usPixelClock = cpu_to_le16(mode->clock / 10);
595
			args.v3.usRefDiv = cpu_to_le16(ref_div);
596
			args.v3.usFbDiv = cpu_to_le16(fb_div);
597
			args.v3.ucFracFbDiv = frac_fb_div;
598
			args.v3.ucPostDiv = post_div;
599
			args.v3.ucPpll =
1123 serge 600
			    radeon_crtc->crtc_id ? ATOM_PPLL2 : ATOM_PPLL1;
1404 serge 601
			args.v3.ucMiscInfo = (radeon_crtc->crtc_id << 2);
602
			args.v3.ucTransmitterId = radeon_encoder->encoder_id;
603
			args.v3.ucEncoderMode =
1123 serge 604
			    atombios_get_encoder_mode(encoder);
605
			break;
606
		default:
607
			DRM_ERROR("Unknown table version %d %d\n", frev, crev);
608
			return;
609
		}
610
		break;
611
	default:
612
		DRM_ERROR("Unknown table version %d %d\n", frev, crev);
613
		return;
614
	}
615
 
616
	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
617
}
618
 
1404 serge 619
static int avivo_crtc_set_base(struct drm_crtc *crtc, int x, int y,
1123 serge 620
			   struct drm_framebuffer *old_fb)
621
{
1246 serge 622
    ENTER();
623
 
1123 serge 624
	struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
625
	struct drm_device *dev = crtc->dev;
626
	struct radeon_device *rdev = dev->dev_private;
627
	struct radeon_framebuffer *radeon_fb;
628
	struct drm_gem_object *obj;
1321 serge 629
	struct radeon_bo *rbo;
1123 serge 630
	uint64_t fb_location;
1179 serge 631
	uint32_t fb_format, fb_pitch_pixels, tiling_flags;
1321 serge 632
	int r;
1123 serge 633
 
1321 serge 634
	/* no fb bound */
635
	if (!crtc->fb) {
636
		DRM_DEBUG("No FB bound\n");
637
		return 0;
638
	}
1123 serge 639
 
640
	radeon_fb = to_radeon_framebuffer(crtc->fb);
641
 
1321 serge 642
	/* Pin framebuffer & get tilling informations */
1123 serge 643
	obj = radeon_fb->obj;
1404 serge 644
	rbo = obj->driver_private;
645
	r = radeon_bo_reserve(rbo, false);
646
	if (unlikely(r != 0))
647
		return r;
648
	r = radeon_bo_pin(rbo, RADEON_GEM_DOMAIN_VRAM, &fb_location);
649
	if (unlikely(r != 0)) {
650
		radeon_bo_unreserve(rbo);
651
		return -EINVAL;
652
	}
653
	radeon_bo_get_tiling_flags(rbo, &tiling_flags, NULL);
654
	radeon_bo_unreserve(rbo);
1123 serge 655
 
656
	switch (crtc->fb->bits_per_pixel) {
1179 serge 657
	case 8:
658
		fb_format =
659
		    AVIVO_D1GRPH_CONTROL_DEPTH_8BPP |
660
		    AVIVO_D1GRPH_CONTROL_8BPP_INDEXED;
661
		break;
1123 serge 662
	case 15:
663
		fb_format =
664
		    AVIVO_D1GRPH_CONTROL_DEPTH_16BPP |
665
		    AVIVO_D1GRPH_CONTROL_16BPP_ARGB1555;
666
		break;
667
	case 16:
668
		fb_format =
669
		    AVIVO_D1GRPH_CONTROL_DEPTH_16BPP |
670
		    AVIVO_D1GRPH_CONTROL_16BPP_RGB565;
671
		break;
672
	case 24:
673
	case 32:
674
		fb_format =
675
		    AVIVO_D1GRPH_CONTROL_DEPTH_32BPP |
676
		    AVIVO_D1GRPH_CONTROL_32BPP_ARGB8888;
677
		break;
678
	default:
679
		DRM_ERROR("Unsupported screen depth %d\n",
680
			  crtc->fb->bits_per_pixel);
681
		return -EINVAL;
682
	}
683
 
1321 serge 684
	if (tiling_flags & RADEON_TILING_MACRO)
685
		fb_format |= AVIVO_D1GRPH_MACRO_ADDRESS_MODE;
1179 serge 686
 
1321 serge 687
	if (tiling_flags & RADEON_TILING_MICRO)
688
		fb_format |= AVIVO_D1GRPH_TILED;
1179 serge 689
 
1123 serge 690
	if (radeon_crtc->crtc_id == 0)
691
		WREG32(AVIVO_D1VGA_CONTROL, 0);
692
	else
693
		WREG32(AVIVO_D2VGA_CONTROL, 0);
1268 serge 694
 
695
	if (rdev->family >= CHIP_RV770) {
696
		if (radeon_crtc->crtc_id) {
697
			WREG32(R700_D2GRPH_PRIMARY_SURFACE_ADDRESS_HIGH, 0);
698
			WREG32(R700_D2GRPH_SECONDARY_SURFACE_ADDRESS_HIGH, 0);
699
		} else {
700
			WREG32(R700_D1GRPH_PRIMARY_SURFACE_ADDRESS_HIGH, 0);
701
			WREG32(R700_D1GRPH_SECONDARY_SURFACE_ADDRESS_HIGH, 0);
702
		}
703
	}
1123 serge 704
	WREG32(AVIVO_D1GRPH_PRIMARY_SURFACE_ADDRESS + radeon_crtc->crtc_offset,
705
	       (u32) fb_location);
706
	WREG32(AVIVO_D1GRPH_SECONDARY_SURFACE_ADDRESS +
707
	       radeon_crtc->crtc_offset, (u32) fb_location);
708
	WREG32(AVIVO_D1GRPH_CONTROL + radeon_crtc->crtc_offset, fb_format);
709
 
710
	WREG32(AVIVO_D1GRPH_SURFACE_OFFSET_X + radeon_crtc->crtc_offset, 0);
711
	WREG32(AVIVO_D1GRPH_SURFACE_OFFSET_Y + radeon_crtc->crtc_offset, 0);
712
	WREG32(AVIVO_D1GRPH_X_START + radeon_crtc->crtc_offset, 0);
713
	WREG32(AVIVO_D1GRPH_Y_START + radeon_crtc->crtc_offset, 0);
714
	WREG32(AVIVO_D1GRPH_X_END + radeon_crtc->crtc_offset, crtc->fb->width);
715
	WREG32(AVIVO_D1GRPH_Y_END + radeon_crtc->crtc_offset, crtc->fb->height);
716
 
717
	fb_pitch_pixels = crtc->fb->pitch / (crtc->fb->bits_per_pixel / 8);
718
	WREG32(AVIVO_D1GRPH_PITCH + radeon_crtc->crtc_offset, fb_pitch_pixels);
719
	WREG32(AVIVO_D1GRPH_ENABLE + radeon_crtc->crtc_offset, 1);
720
 
721
	WREG32(AVIVO_D1MODE_DESKTOP_HEIGHT + radeon_crtc->crtc_offset,
722
	       crtc->mode.vdisplay);
723
	x &= ~3;
724
	y &= ~1;
725
	WREG32(AVIVO_D1MODE_VIEWPORT_START + radeon_crtc->crtc_offset,
726
	       (x << 16) | y);
727
	WREG32(AVIVO_D1MODE_VIEWPORT_SIZE + radeon_crtc->crtc_offset,
728
	       (crtc->mode.hdisplay << 16) | crtc->mode.vdisplay);
729
 
730
	if (crtc->mode.flags & DRM_MODE_FLAG_INTERLACE)
731
		WREG32(AVIVO_D1MODE_DATA_FORMAT + radeon_crtc->crtc_offset,
732
		       AVIVO_D1MODE_INTERLEAVE_EN);
733
	else
734
		WREG32(AVIVO_D1MODE_DATA_FORMAT + radeon_crtc->crtc_offset, 0);
735
 
1404 serge 736
	if (old_fb && old_fb != crtc->fb) {
737
		radeon_fb = to_radeon_framebuffer(old_fb);
738
		rbo = radeon_fb->obj->driver_private;
739
		r = radeon_bo_reserve(rbo, false);
740
		if (unlikely(r != 0))
741
			return r;
742
		radeon_bo_unpin(rbo);
743
		radeon_bo_unreserve(rbo);
744
	}
1246 serge 745
 
1268 serge 746
	/* Bytes per pixel may have changed */
747
	radeon_bandwidth_update(rdev);
748
 
1246 serge 749
    LEAVE();
750
 
1123 serge 751
	return 0;
752
}
753
 
1404 serge 754
int atombios_crtc_set_base(struct drm_crtc *crtc, int x, int y,
755
			   struct drm_framebuffer *old_fb)
756
{
757
	struct drm_device *dev = crtc->dev;
758
	struct radeon_device *rdev = dev->dev_private;
759
 
760
	if (ASIC_IS_AVIVO(rdev))
761
		return avivo_crtc_set_base(crtc, x, y, old_fb);
762
	else
763
		return radeon_crtc_set_base(crtc, x, y, old_fb);
764
}
765
 
766
/* properly set additional regs when using atombios */
767
static void radeon_legacy_atom_fixup(struct drm_crtc *crtc)
768
{
769
	struct drm_device *dev = crtc->dev;
770
	struct radeon_device *rdev = dev->dev_private;
771
	struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
772
	u32 disp_merge_cntl;
773
 
774
	switch (radeon_crtc->crtc_id) {
775
	case 0:
776
		disp_merge_cntl = RREG32(RADEON_DISP_MERGE_CNTL);
777
		disp_merge_cntl &= ~RADEON_DISP_RGB_OFFSET_EN;
778
		WREG32(RADEON_DISP_MERGE_CNTL, disp_merge_cntl);
779
		break;
780
	case 1:
781
		disp_merge_cntl = RREG32(RADEON_DISP2_MERGE_CNTL);
782
		disp_merge_cntl &= ~RADEON_DISP2_RGB_OFFSET_EN;
783
		WREG32(RADEON_DISP2_MERGE_CNTL, disp_merge_cntl);
784
		WREG32(RADEON_FP_H2_SYNC_STRT_WID,   RREG32(RADEON_CRTC2_H_SYNC_STRT_WID));
785
		WREG32(RADEON_FP_V2_SYNC_STRT_WID,   RREG32(RADEON_CRTC2_V_SYNC_STRT_WID));
786
		break;
787
	}
788
}
789
 
1123 serge 790
int atombios_crtc_mode_set(struct drm_crtc *crtc,
791
			   struct drm_display_mode *mode,
792
			   struct drm_display_mode *adjusted_mode,
793
			   int x, int y, struct drm_framebuffer *old_fb)
794
{
795
	struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
796
	struct drm_device *dev = crtc->dev;
797
	struct radeon_device *rdev = dev->dev_private;
798
 
799
	/* TODO color tiling */
800
 
1268 serge 801
	atombios_set_ss(crtc, 0);
1123 serge 802
	atombios_crtc_set_pll(crtc, adjusted_mode);
1268 serge 803
	atombios_set_ss(crtc, 1);
804
	atombios_crtc_set_timing(crtc, adjusted_mode);
1123 serge 805
 
806
	if (ASIC_IS_AVIVO(rdev))
807
		atombios_crtc_set_base(crtc, x, y, old_fb);
808
	else {
1268 serge 809
		if (radeon_crtc->crtc_id == 0)
810
			atombios_set_crtc_dtd_timing(crtc, adjusted_mode);
1404 serge 811
		atombios_crtc_set_base(crtc, x, y, old_fb);
812
		radeon_legacy_atom_fixup(crtc);
1123 serge 813
	}
1179 serge 814
	atombios_overscan_setup(crtc, mode, adjusted_mode);
815
	atombios_scaler_setup(crtc);
1123 serge 816
	return 0;
817
}
818
 
819
static bool atombios_crtc_mode_fixup(struct drm_crtc *crtc,
820
				     struct drm_display_mode *mode,
821
				     struct drm_display_mode *adjusted_mode)
822
{
1179 serge 823
	if (!radeon_crtc_scaling_mode_fixup(crtc, mode, adjusted_mode))
824
		return false;
1123 serge 825
	return true;
826
}
827
 
828
static void atombios_crtc_prepare(struct drm_crtc *crtc)
829
{
1404 serge 830
	atombios_lock_crtc(crtc, 1);
1123 serge 831
	atombios_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);
832
}
833
 
834
static void atombios_crtc_commit(struct drm_crtc *crtc)
835
{
836
	atombios_crtc_dpms(crtc, DRM_MODE_DPMS_ON);
837
	atombios_lock_crtc(crtc, 0);
838
}
839
 
840
static const struct drm_crtc_helper_funcs atombios_helper_funcs = {
841
	.dpms = atombios_crtc_dpms,
842
	.mode_fixup = atombios_crtc_mode_fixup,
843
	.mode_set = atombios_crtc_mode_set,
844
	.mode_set_base = atombios_crtc_set_base,
845
	.prepare = atombios_crtc_prepare,
846
	.commit = atombios_crtc_commit,
1221 serge 847
	.load_lut = radeon_crtc_load_lut,
1123 serge 848
};
849
 
850
void radeon_atombios_init_crtc(struct drm_device *dev,
851
			       struct radeon_crtc *radeon_crtc)
852
{
853
	if (radeon_crtc->crtc_id == 1)
854
		radeon_crtc->crtc_offset =
855
		    AVIVO_D2CRTC_H_TOTAL - AVIVO_D1CRTC_H_TOTAL;
856
	drm_crtc_helper_add(&radeon_crtc->base, &atombios_helper_funcs);
857
}