Subversion Repositories Kolibri OS

Rev

Rev 1268 | Rev 1404 | 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
 
1123 serge 308
	printk("executing set crtc dtd timing\n");
1268 serge 309
	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
1123 serge 310
}
311
 
1268 serge 312
static void atombios_crtc_set_timing(struct drm_crtc *crtc,
313
				     struct drm_display_mode *mode)
1123 serge 314
{
1268 serge 315
	struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
1123 serge 316
	struct drm_device *dev = crtc->dev;
317
	struct radeon_device *rdev = dev->dev_private;
1268 serge 318
	SET_CRTC_TIMING_PARAMETERS_PS_ALLOCATION args;
1123 serge 319
	int index = GetIndexIntoMasterTable(COMMAND, SetCRTC_Timing);
1268 serge 320
	u16 misc = 0;
1123 serge 321
 
1268 serge 322
	memset(&args, 0, sizeof(args));
323
	args.usH_Total = cpu_to_le16(mode->crtc_htotal);
324
	args.usH_Disp = cpu_to_le16(mode->crtc_hdisplay);
325
	args.usH_SyncStart = cpu_to_le16(mode->crtc_hsync_start);
326
	args.usH_SyncWidth =
327
		cpu_to_le16(mode->crtc_hsync_end - mode->crtc_hsync_start);
328
	args.usV_Total = cpu_to_le16(mode->crtc_vtotal);
329
	args.usV_Disp = cpu_to_le16(mode->crtc_vdisplay);
330
	args.usV_SyncStart = cpu_to_le16(mode->crtc_vsync_start);
331
	args.usV_SyncWidth =
332
		cpu_to_le16(mode->crtc_vsync_end - mode->crtc_vsync_start);
1123 serge 333
 
1268 serge 334
	if (mode->flags & DRM_MODE_FLAG_NVSYNC)
335
		misc |= ATOM_VSYNC_POLARITY;
336
	if (mode->flags & DRM_MODE_FLAG_NHSYNC)
337
		misc |= ATOM_HSYNC_POLARITY;
338
	if (mode->flags & DRM_MODE_FLAG_CSYNC)
339
		misc |= ATOM_COMPOSITESYNC;
340
	if (mode->flags & DRM_MODE_FLAG_INTERLACE)
341
		misc |= ATOM_INTERLACE;
342
	if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
343
		misc |= ATOM_DOUBLE_CLOCK_MODE;
344
 
345
	args.susModeMiscInfo.usAccess = cpu_to_le16(misc);
346
	args.ucCRTC = radeon_crtc->crtc_id;
347
 
1123 serge 348
	printk("executing set crtc timing\n");
1268 serge 349
	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
1123 serge 350
}
351
 
1268 serge 352
static void atombios_set_ss(struct drm_crtc *crtc, int enable)
353
{
354
	struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
355
	struct drm_device *dev = crtc->dev;
356
	struct radeon_device *rdev = dev->dev_private;
357
	struct drm_encoder *encoder = NULL;
358
	struct radeon_encoder *radeon_encoder = NULL;
359
	struct radeon_encoder_atom_dig *dig = NULL;
360
	int index = GetIndexIntoMasterTable(COMMAND, EnableSpreadSpectrumOnPPLL);
361
	ENABLE_SPREAD_SPECTRUM_ON_PPLL_PS_ALLOCATION args;
362
	ENABLE_LVDS_SS_PARAMETERS legacy_args;
363
	uint16_t percentage = 0;
364
	uint8_t type = 0, step = 0, delay = 0, range = 0;
365
 
366
	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
367
		if (encoder->crtc == crtc) {
368
			radeon_encoder = to_radeon_encoder(encoder);
369
			/* only enable spread spectrum on LVDS */
370
			if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
371
				dig = radeon_encoder->enc_priv;
372
				if (dig && dig->ss) {
373
					percentage = dig->ss->percentage;
374
					type = dig->ss->type;
375
					step = dig->ss->step;
376
					delay = dig->ss->delay;
377
					range = dig->ss->range;
378
				} else if (enable)
379
					return;
380
			} else if (enable)
381
				return;
382
			break;
383
		}
384
	}
385
 
386
	if (!radeon_encoder)
387
		return;
388
 
389
	if (ASIC_IS_AVIVO(rdev)) {
390
		memset(&args, 0, sizeof(args));
391
		args.usSpreadSpectrumPercentage = cpu_to_le16(percentage);
392
		args.ucSpreadSpectrumType = type;
393
		args.ucSpreadSpectrumStep = step;
394
		args.ucSpreadSpectrumDelay = delay;
395
		args.ucSpreadSpectrumRange = range;
396
		args.ucPpll = radeon_crtc->crtc_id ? ATOM_PPLL2 : ATOM_PPLL1;
397
		args.ucEnable = enable;
398
		atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
399
	} else {
400
		memset(&legacy_args, 0, sizeof(legacy_args));
401
		legacy_args.usSpreadSpectrumPercentage = cpu_to_le16(percentage);
402
		legacy_args.ucSpreadSpectrumType = type;
403
		legacy_args.ucSpreadSpectrumStepSize_Delay = (step & 3) << 2;
404
		legacy_args.ucSpreadSpectrumStepSize_Delay |= (delay & 7) << 4;
405
		legacy_args.ucEnable = enable;
406
		atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&legacy_args);
407
	}
408
}
409
 
1123 serge 410
void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode)
411
{
412
	struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
413
	struct drm_device *dev = crtc->dev;
414
	struct radeon_device *rdev = dev->dev_private;
415
	struct drm_encoder *encoder = NULL;
416
	struct radeon_encoder *radeon_encoder = NULL;
417
	uint8_t frev, crev;
1268 serge 418
	int index;
1123 serge 419
	SET_PIXEL_CLOCK_PS_ALLOCATION args;
420
	PIXEL_CLOCK_PARAMETERS *spc1_ptr;
421
	PIXEL_CLOCK_PARAMETERS_V2 *spc2_ptr;
422
	PIXEL_CLOCK_PARAMETERS_V3 *spc3_ptr;
1268 serge 423
	uint32_t pll_clock = mode->clock;
424
	uint32_t adjusted_clock;
1123 serge 425
	uint32_t ref_div = 0, fb_div = 0, frac_fb_div = 0, post_div = 0;
426
	struct radeon_pll *pll;
427
	int pll_flags = 0;
428
 
429
	memset(&args, 0, sizeof(args));
430
 
431
	if (ASIC_IS_AVIVO(rdev)) {
1179 serge 432
		if ((rdev->family == CHIP_RS600) ||
433
		    (rdev->family == CHIP_RS690) ||
434
		    (rdev->family == CHIP_RS740))
435
			pll_flags |= (RADEON_PLL_USE_FRAC_FB_DIV |
436
				      RADEON_PLL_PREFER_CLOSEST_LOWER);
437
 
1123 serge 438
		if (ASIC_IS_DCE32(rdev) && mode->clock > 200000)	/* range limits??? */
439
			pll_flags |= RADEON_PLL_PREFER_HIGH_FB_DIV;
440
		else
441
			pll_flags |= RADEON_PLL_PREFER_LOW_REF_DIV;
442
	} else {
443
		pll_flags |= RADEON_PLL_LEGACY;
444
 
445
		if (mode->clock > 200000)	/* range limits??? */
446
			pll_flags |= RADEON_PLL_PREFER_HIGH_FB_DIV;
447
		else
448
			pll_flags |= RADEON_PLL_PREFER_LOW_REF_DIV;
449
 
450
	}
451
 
452
	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
453
		if (encoder->crtc == crtc) {
454
			if (!ASIC_IS_AVIVO(rdev)) {
455
				if (encoder->encoder_type !=
456
				    DRM_MODE_ENCODER_DAC)
457
					pll_flags |= RADEON_PLL_NO_ODD_POST_DIV;
1321 serge 458
				if (encoder->encoder_type ==
459
					DRM_MODE_ENCODER_LVDS)
1123 serge 460
					pll_flags |= RADEON_PLL_USE_REF_DIV;
461
			}
462
			radeon_encoder = to_radeon_encoder(encoder);
1179 serge 463
			break;
1123 serge 464
		}
465
	}
466
 
1268 serge 467
	/* DCE3+ has an AdjustDisplayPll that will adjust the pixel clock
468
	 * accordingly based on the encoder/transmitter to work around
469
	 * special hw requirements.
470
	 */
471
	if (ASIC_IS_DCE3(rdev)) {
472
		ADJUST_DISPLAY_PLL_PS_ALLOCATION adjust_pll_args;
473
 
474
		if (!encoder)
475
			return;
476
 
477
		memset(&adjust_pll_args, 0, sizeof(adjust_pll_args));
478
		adjust_pll_args.usPixelClock = cpu_to_le16(mode->clock / 10);
479
		adjust_pll_args.ucTransmitterID = radeon_encoder->encoder_id;
480
		adjust_pll_args.ucEncodeMode = atombios_get_encoder_mode(encoder);
481
 
482
		index = GetIndexIntoMasterTable(COMMAND, AdjustDisplayPll);
483
		atom_execute_table(rdev->mode_info.atom_context,
484
				   index, (uint32_t *)&adjust_pll_args);
485
		adjusted_clock = le16_to_cpu(adjust_pll_args.usPixelClock) * 10;
486
	} else {
487
		/* DVO wants 2x pixel clock if the DVO chip is in 12 bit mode */
488
		if (ASIC_IS_AVIVO(rdev) &&
489
		    (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1))
490
			adjusted_clock = mode->clock * 2;
491
		else
492
			adjusted_clock = mode->clock;
493
	}
494
 
1123 serge 495
	if (radeon_crtc->crtc_id == 0)
496
		pll = &rdev->clock.p1pll;
497
	else
498
		pll = &rdev->clock.p2pll;
499
 
1321 serge 500
	if (ASIC_IS_AVIVO(rdev)) {
501
		if (radeon_new_pll)
502
			radeon_compute_pll_avivo(pll, adjusted_clock, &pll_clock,
503
						 &fb_div, &frac_fb_div,
504
						 &ref_div, &post_div, pll_flags);
505
		else
506
			radeon_compute_pll(pll, adjusted_clock, &pll_clock,
507
					   &fb_div, &frac_fb_div,
508
					   &ref_div, &post_div, pll_flags);
509
	} else
1268 serge 510
	radeon_compute_pll(pll, adjusted_clock, &pll_clock, &fb_div, &frac_fb_div,
1123 serge 511
			   &ref_div, &post_div, pll_flags);
512
 
1268 serge 513
	index = GetIndexIntoMasterTable(COMMAND, SetPixelClock);
1123 serge 514
	atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev,
515
			      &crev);
516
 
517
	switch (frev) {
518
	case 1:
519
		switch (crev) {
520
		case 1:
521
			spc1_ptr = (PIXEL_CLOCK_PARAMETERS *) & args.sPCLKInput;
1268 serge 522
			spc1_ptr->usPixelClock = cpu_to_le16(mode->clock / 10);
1123 serge 523
			spc1_ptr->usRefDiv = cpu_to_le16(ref_div);
524
			spc1_ptr->usFbDiv = cpu_to_le16(fb_div);
525
			spc1_ptr->ucFracFbDiv = frac_fb_div;
526
			spc1_ptr->ucPostDiv = post_div;
527
			spc1_ptr->ucPpll =
528
			    radeon_crtc->crtc_id ? ATOM_PPLL2 : ATOM_PPLL1;
529
			spc1_ptr->ucCRTC = radeon_crtc->crtc_id;
530
			spc1_ptr->ucRefDivSrc = 1;
531
			break;
532
		case 2:
533
			spc2_ptr =
534
			    (PIXEL_CLOCK_PARAMETERS_V2 *) & args.sPCLKInput;
1268 serge 535
			spc2_ptr->usPixelClock = cpu_to_le16(mode->clock / 10);
1123 serge 536
			spc2_ptr->usRefDiv = cpu_to_le16(ref_div);
537
			spc2_ptr->usFbDiv = cpu_to_le16(fb_div);
538
			spc2_ptr->ucFracFbDiv = frac_fb_div;
539
			spc2_ptr->ucPostDiv = post_div;
540
			spc2_ptr->ucPpll =
541
			    radeon_crtc->crtc_id ? ATOM_PPLL2 : ATOM_PPLL1;
542
			spc2_ptr->ucCRTC = radeon_crtc->crtc_id;
543
			spc2_ptr->ucRefDivSrc = 1;
544
			break;
545
		case 3:
546
			if (!encoder)
547
				return;
548
			spc3_ptr =
549
			    (PIXEL_CLOCK_PARAMETERS_V3 *) & args.sPCLKInput;
1268 serge 550
			spc3_ptr->usPixelClock = cpu_to_le16(mode->clock / 10);
1123 serge 551
			spc3_ptr->usRefDiv = cpu_to_le16(ref_div);
552
			spc3_ptr->usFbDiv = cpu_to_le16(fb_div);
553
			spc3_ptr->ucFracFbDiv = frac_fb_div;
554
			spc3_ptr->ucPostDiv = post_div;
555
			spc3_ptr->ucPpll =
556
			    radeon_crtc->crtc_id ? ATOM_PPLL2 : ATOM_PPLL1;
557
			spc3_ptr->ucMiscInfo = (radeon_crtc->crtc_id << 2);
558
			spc3_ptr->ucTransmitterId = radeon_encoder->encoder_id;
559
			spc3_ptr->ucEncoderMode =
560
			    atombios_get_encoder_mode(encoder);
561
			break;
562
		default:
563
			DRM_ERROR("Unknown table version %d %d\n", frev, crev);
564
			return;
565
		}
566
		break;
567
	default:
568
		DRM_ERROR("Unknown table version %d %d\n", frev, crev);
569
		return;
570
	}
571
 
572
	printk("executing set pll\n");
573
	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
574
}
575
 
576
int atombios_crtc_set_base(struct drm_crtc *crtc, int x, int y,
577
			   struct drm_framebuffer *old_fb)
578
{
1246 serge 579
    ENTER();
580
 
1123 serge 581
	struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
582
	struct drm_device *dev = crtc->dev;
583
	struct radeon_device *rdev = dev->dev_private;
584
	struct radeon_framebuffer *radeon_fb;
585
	struct drm_gem_object *obj;
1321 serge 586
	struct radeon_bo *rbo;
1123 serge 587
	uint64_t fb_location;
1179 serge 588
	uint32_t fb_format, fb_pitch_pixels, tiling_flags;
1321 serge 589
	int r;
1123 serge 590
 
1321 serge 591
	/* no fb bound */
592
	if (!crtc->fb) {
593
		DRM_DEBUG("No FB bound\n");
594
		return 0;
595
	}
1123 serge 596
 
597
	radeon_fb = to_radeon_framebuffer(crtc->fb);
598
 
1321 serge 599
	/* Pin framebuffer & get tilling informations */
1123 serge 600
	obj = radeon_fb->obj;
601
	obj_priv = obj->driver_private;
602
 
1179 serge 603
//	if (radeon_gem_object_pin(obj, RADEON_GEM_DOMAIN_VRAM, &fb_location)) {
604
//		return -EINVAL;
605
//	}
1123 serge 606
 
1246 serge 607
    fb_location = rdev->mc.vram_location;
1321 serge 608
    tiling_flags = 0;
1126 serge 609
 
1123 serge 610
	switch (crtc->fb->bits_per_pixel) {
1179 serge 611
	case 8:
612
		fb_format =
613
		    AVIVO_D1GRPH_CONTROL_DEPTH_8BPP |
614
		    AVIVO_D1GRPH_CONTROL_8BPP_INDEXED;
615
		break;
1123 serge 616
	case 15:
617
		fb_format =
618
		    AVIVO_D1GRPH_CONTROL_DEPTH_16BPP |
619
		    AVIVO_D1GRPH_CONTROL_16BPP_ARGB1555;
620
		break;
621
	case 16:
622
		fb_format =
623
		    AVIVO_D1GRPH_CONTROL_DEPTH_16BPP |
624
		    AVIVO_D1GRPH_CONTROL_16BPP_RGB565;
625
		break;
626
	case 24:
627
	case 32:
628
		fb_format =
629
		    AVIVO_D1GRPH_CONTROL_DEPTH_32BPP |
630
		    AVIVO_D1GRPH_CONTROL_32BPP_ARGB8888;
631
		break;
632
	default:
633
		DRM_ERROR("Unsupported screen depth %d\n",
634
			  crtc->fb->bits_per_pixel);
635
		return -EINVAL;
636
	}
637
 
1321 serge 638
	if (tiling_flags & RADEON_TILING_MACRO)
639
		fb_format |= AVIVO_D1GRPH_MACRO_ADDRESS_MODE;
1179 serge 640
 
1321 serge 641
	if (tiling_flags & RADEON_TILING_MICRO)
642
		fb_format |= AVIVO_D1GRPH_TILED;
1179 serge 643
 
1123 serge 644
	if (radeon_crtc->crtc_id == 0)
645
		WREG32(AVIVO_D1VGA_CONTROL, 0);
646
	else
647
		WREG32(AVIVO_D2VGA_CONTROL, 0);
1268 serge 648
 
649
	if (rdev->family >= CHIP_RV770) {
650
		if (radeon_crtc->crtc_id) {
651
			WREG32(R700_D2GRPH_PRIMARY_SURFACE_ADDRESS_HIGH, 0);
652
			WREG32(R700_D2GRPH_SECONDARY_SURFACE_ADDRESS_HIGH, 0);
653
		} else {
654
			WREG32(R700_D1GRPH_PRIMARY_SURFACE_ADDRESS_HIGH, 0);
655
			WREG32(R700_D1GRPH_SECONDARY_SURFACE_ADDRESS_HIGH, 0);
656
		}
657
	}
1123 serge 658
	WREG32(AVIVO_D1GRPH_PRIMARY_SURFACE_ADDRESS + radeon_crtc->crtc_offset,
659
	       (u32) fb_location);
660
	WREG32(AVIVO_D1GRPH_SECONDARY_SURFACE_ADDRESS +
661
	       radeon_crtc->crtc_offset, (u32) fb_location);
662
	WREG32(AVIVO_D1GRPH_CONTROL + radeon_crtc->crtc_offset, fb_format);
663
 
664
	WREG32(AVIVO_D1GRPH_SURFACE_OFFSET_X + radeon_crtc->crtc_offset, 0);
665
	WREG32(AVIVO_D1GRPH_SURFACE_OFFSET_Y + radeon_crtc->crtc_offset, 0);
666
	WREG32(AVIVO_D1GRPH_X_START + radeon_crtc->crtc_offset, 0);
667
	WREG32(AVIVO_D1GRPH_Y_START + radeon_crtc->crtc_offset, 0);
668
	WREG32(AVIVO_D1GRPH_X_END + radeon_crtc->crtc_offset, crtc->fb->width);
669
	WREG32(AVIVO_D1GRPH_Y_END + radeon_crtc->crtc_offset, crtc->fb->height);
670
 
671
	fb_pitch_pixels = crtc->fb->pitch / (crtc->fb->bits_per_pixel / 8);
672
	WREG32(AVIVO_D1GRPH_PITCH + radeon_crtc->crtc_offset, fb_pitch_pixels);
673
	WREG32(AVIVO_D1GRPH_ENABLE + radeon_crtc->crtc_offset, 1);
674
 
675
	WREG32(AVIVO_D1MODE_DESKTOP_HEIGHT + radeon_crtc->crtc_offset,
676
	       crtc->mode.vdisplay);
677
	x &= ~3;
678
	y &= ~1;
679
	WREG32(AVIVO_D1MODE_VIEWPORT_START + radeon_crtc->crtc_offset,
680
	       (x << 16) | y);
681
	WREG32(AVIVO_D1MODE_VIEWPORT_SIZE + radeon_crtc->crtc_offset,
682
	       (crtc->mode.hdisplay << 16) | crtc->mode.vdisplay);
683
 
684
	if (crtc->mode.flags & DRM_MODE_FLAG_INTERLACE)
685
		WREG32(AVIVO_D1MODE_DATA_FORMAT + radeon_crtc->crtc_offset,
686
		       AVIVO_D1MODE_INTERLEAVE_EN);
687
	else
688
		WREG32(AVIVO_D1MODE_DATA_FORMAT + radeon_crtc->crtc_offset, 0);
689
 
1246 serge 690
//   if (old_fb && old_fb != crtc->fb) {
1179 serge 691
//       radeon_fb = to_radeon_framebuffer(old_fb);
1123 serge 692
//       radeon_gem_object_unpin(radeon_fb->obj);
1246 serge 693
//   }
694
 
1268 serge 695
	/* Bytes per pixel may have changed */
696
	radeon_bandwidth_update(rdev);
697
 
1246 serge 698
    LEAVE();
699
 
1123 serge 700
	return 0;
701
}
702
 
703
int atombios_crtc_mode_set(struct drm_crtc *crtc,
704
			   struct drm_display_mode *mode,
705
			   struct drm_display_mode *adjusted_mode,
706
			   int x, int y, struct drm_framebuffer *old_fb)
707
{
708
	struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
709
	struct drm_device *dev = crtc->dev;
710
	struct radeon_device *rdev = dev->dev_private;
711
 
712
	/* TODO color tiling */
713
 
1268 serge 714
	atombios_set_ss(crtc, 0);
1123 serge 715
	atombios_crtc_set_pll(crtc, adjusted_mode);
1268 serge 716
	atombios_set_ss(crtc, 1);
717
	atombios_crtc_set_timing(crtc, adjusted_mode);
1123 serge 718
 
719
	if (ASIC_IS_AVIVO(rdev))
720
		atombios_crtc_set_base(crtc, x, y, old_fb);
721
	else {
1268 serge 722
		if (radeon_crtc->crtc_id == 0)
723
			atombios_set_crtc_dtd_timing(crtc, adjusted_mode);
1123 serge 724
		radeon_crtc_set_base(crtc, x, y, old_fb);
725
		radeon_legacy_atom_set_surface(crtc);
726
	}
1179 serge 727
	atombios_overscan_setup(crtc, mode, adjusted_mode);
728
	atombios_scaler_setup(crtc);
1123 serge 729
	return 0;
730
}
731
 
732
static bool atombios_crtc_mode_fixup(struct drm_crtc *crtc,
733
				     struct drm_display_mode *mode,
734
				     struct drm_display_mode *adjusted_mode)
735
{
1179 serge 736
	if (!radeon_crtc_scaling_mode_fixup(crtc, mode, adjusted_mode))
737
		return false;
1123 serge 738
	return true;
739
}
740
 
741
static void atombios_crtc_prepare(struct drm_crtc *crtc)
742
{
743
	atombios_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);
744
	atombios_lock_crtc(crtc, 1);
745
}
746
 
747
static void atombios_crtc_commit(struct drm_crtc *crtc)
748
{
749
	atombios_crtc_dpms(crtc, DRM_MODE_DPMS_ON);
750
	atombios_lock_crtc(crtc, 0);
751
}
752
 
753
static const struct drm_crtc_helper_funcs atombios_helper_funcs = {
754
	.dpms = atombios_crtc_dpms,
755
	.mode_fixup = atombios_crtc_mode_fixup,
756
	.mode_set = atombios_crtc_mode_set,
757
	.mode_set_base = atombios_crtc_set_base,
758
	.prepare = atombios_crtc_prepare,
759
	.commit = atombios_crtc_commit,
1221 serge 760
	.load_lut = radeon_crtc_load_lut,
1123 serge 761
};
762
 
763
void radeon_atombios_init_crtc(struct drm_device *dev,
764
			       struct radeon_crtc *radeon_crtc)
765
{
766
	if (radeon_crtc->crtc_id == 1)
767
		radeon_crtc->crtc_offset =
768
		    AVIVO_D2CRTC_H_TOTAL - AVIVO_D1CRTC_H_TOTAL;
769
	drm_crtc_helper_add(&radeon_crtc->base, &atombios_helper_funcs);
770
}