Subversion Repositories Kolibri OS

Rev

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