1/*
2 * Copyright © 2007 Red Hat, Inc.
3 * Copyright 2007  Advanced Micro Devices, 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 (including the next
13 * paragraph) shall be included in all copies or substantial portions of the
14 * Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 * SOFTWARE.
23 *
24 * Authors:
25 *    Dave Airlie <airlied@redhat.com>
26 *    Alex Deucher <alexander.deucher@amd.com>
27 *
28 */
29/*
30 * avivo crtc handling functions.
31 */
32#ifdef HAVE_CONFIG_H
33#include "config.h"
34#endif
35/* DPMS */
36#ifdef HAVE_XEXTPROTO_71
37#include <X11/extensions/dpmsconst.h>
38#else
39#define DPMS_SERVER
40#include <X11/extensions/dpms.h>
41#endif
42
43#include <math.h>
44#include "radeon.h"
45#include "radeon_reg.h"
46#include "radeon_macros.h"
47#include "radeon_atombios.h"
48
49#ifdef XF86DRI
50#define _XF86DRI_SERVER_
51#include "radeon_drm.h"
52#include "sarea.h"
53#endif
54
55extern int
56atombios_get_encoder_mode(xf86OutputPtr output);
57
58extern void
59RADEONInitCrtcBase(xf86CrtcPtr crtc, RADEONSavePtr save,
60		   int x, int y);
61extern void
62RADEONInitCrtc2Base(xf86CrtcPtr crtc, RADEONSavePtr save,
63		    int x, int y);
64extern void
65RADEONRestoreCrtcBase(ScrnInfoPtr pScrn,
66		      RADEONSavePtr restore);
67extern void
68RADEONRestoreCrtc2Base(ScrnInfoPtr pScrn,
69		       RADEONSavePtr restore);
70extern void
71RADEONInitCommonRegisters(RADEONSavePtr save, RADEONInfoPtr info);
72extern void
73RADEONInitSurfaceCntl(xf86CrtcPtr crtc, RADEONSavePtr save);
74
75AtomBiosResult
76atombios_lock_crtc(atomBiosHandlePtr atomBIOS, int crtc, int lock)
77{
78    ENABLE_CRTC_PS_ALLOCATION crtc_data;
79    AtomBiosArgRec data;
80    unsigned char *space;
81
82    crtc_data.ucCRTC = crtc;
83    crtc_data.ucEnable = lock;
84
85    data.exec.index = GetIndexIntoMasterTable(COMMAND, UpdateCRTC_DoubleBufferRegisters);
86    data.exec.dataSpace = (void *)&space;
87    data.exec.pspace = &crtc_data;
88
89    if (RHDAtomBiosFunc(atomBIOS->pScrn, atomBIOS, ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) {
90/*	ErrorF("%s CRTC %d success\n", lock? "Lock":"Unlock", crtc); */
91	return ATOM_SUCCESS ;
92    }
93
94    ErrorF("Lock CRTC failed\n");
95    return ATOM_NOT_IMPLEMENTED;
96}
97
98static AtomBiosResult
99atombios_enable_crtc(atomBiosHandlePtr atomBIOS, int crtc, int state)
100{
101    ENABLE_CRTC_PS_ALLOCATION crtc_data;
102    AtomBiosArgRec data;
103    unsigned char *space;
104
105    crtc_data.ucCRTC = crtc;
106    crtc_data.ucEnable = state;
107
108    data.exec.index = GetIndexIntoMasterTable(COMMAND, EnableCRTC);
109    data.exec.dataSpace = (void *)&space;
110    data.exec.pspace = &crtc_data;
111
112    if (RHDAtomBiosFunc(atomBIOS->pScrn, atomBIOS, ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) {
113/*	ErrorF("%s CRTC %d success\n", state? "Enable":"Disable", crtc); */
114	return ATOM_SUCCESS ;
115    }
116
117    ErrorF("Enable CRTC failed\n");
118    return ATOM_NOT_IMPLEMENTED;
119}
120
121static AtomBiosResult
122atombios_enable_crtc_memreq(atomBiosHandlePtr atomBIOS, int crtc, int state)
123{
124    ENABLE_CRTC_PS_ALLOCATION crtc_data;
125    AtomBiosArgRec data;
126    unsigned char *space;
127
128    crtc_data.ucCRTC = crtc;
129    crtc_data.ucEnable = state;
130
131    data.exec.index = GetIndexIntoMasterTable(COMMAND, EnableCRTCMemReq);
132    data.exec.dataSpace = (void *)&space;
133    data.exec.pspace = &crtc_data;
134
135    if (RHDAtomBiosFunc(atomBIOS->pScrn, atomBIOS, ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) {
136/*	ErrorF("%s CRTC memreq %d success\n", state? "Enable":"Disable", crtc); */
137	return ATOM_SUCCESS ;
138    }
139
140    ErrorF("Enable CRTC memreq failed\n");
141    return ATOM_NOT_IMPLEMENTED;
142}
143
144static AtomBiosResult
145atombios_blank_crtc(atomBiosHandlePtr atomBIOS, int crtc, int state)
146{
147    BLANK_CRTC_PS_ALLOCATION crtc_data;
148    unsigned char *space;
149    AtomBiosArgRec data;
150
151    memset(&crtc_data, 0, sizeof(crtc_data));
152    crtc_data.ucCRTC = crtc;
153    crtc_data.ucBlanking = state;
154
155    data.exec.index = GetIndexIntoMasterTable(COMMAND, BlankCRTC);
156    data.exec.dataSpace = (void *)&space;
157    data.exec.pspace = &crtc_data;
158
159    if (RHDAtomBiosFunc(atomBIOS->pScrn, atomBIOS, ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) {
160/*	ErrorF("%s CRTC %d success\n", state? "Blank":"Unblank", crtc); */
161	return ATOM_SUCCESS ;
162    }
163
164    ErrorF("Blank CRTC failed\n");
165    return ATOM_NOT_IMPLEMENTED;
166}
167
168void
169atombios_crtc_dpms(xf86CrtcPtr crtc, int mode)
170{
171    RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private;
172    RADEONInfoPtr  info = RADEONPTR(crtc->scrn);
173    switch (mode) {
174    case DPMSModeOn:
175	atombios_enable_crtc(info->atomBIOS, radeon_crtc->crtc_id, 1);
176	if (IS_DCE3_VARIANT)
177	    atombios_enable_crtc_memreq(info->atomBIOS, radeon_crtc->crtc_id, 1);
178	atombios_blank_crtc(info->atomBIOS, radeon_crtc->crtc_id, 0);
179	break;
180    case DPMSModeStandby:
181    case DPMSModeSuspend:
182    case DPMSModeOff:
183	atombios_blank_crtc(info->atomBIOS, radeon_crtc->crtc_id, 1);
184	if (IS_DCE3_VARIANT)
185	    atombios_enable_crtc_memreq(info->atomBIOS, radeon_crtc->crtc_id, 0);
186	atombios_enable_crtc(info->atomBIOS, radeon_crtc->crtc_id, 0);
187	break;
188    }
189}
190
191static AtomBiosResult
192atombios_set_crtc_timing(xf86CrtcPtr crtc, DisplayModePtr mode)
193{
194    RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private;
195    RADEONInfoPtr  info = RADEONPTR(crtc->scrn);
196    AtomBiosArgRec data;
197    unsigned char *space;
198    uint16_t misc = 0;
199    SET_CRTC_TIMING_PARAMETERS_PS_ALLOCATION param;
200    memset(&param, 0, sizeof(param));
201
202    param.usH_Total		= cpu_to_le16(mode->CrtcHTotal);
203    param.usH_Disp		= cpu_to_le16(mode->CrtcHDisplay);
204    param.usH_SyncStart		= cpu_to_le16(mode->CrtcHSyncStart);
205    param.usH_SyncWidth		= cpu_to_le16(mode->CrtcHSyncEnd - mode->CrtcHSyncStart);
206    param.usV_Total		= cpu_to_le16(mode->CrtcVTotal);
207    param.usV_Disp		= cpu_to_le16(mode->CrtcVDisplay);
208    param.usV_SyncStart		= cpu_to_le16(mode->CrtcVSyncStart);
209    param.usV_SyncWidth		= cpu_to_le16(mode->CrtcVSyncEnd - mode->CrtcVSyncStart);
210
211    if (mode->Flags & V_NVSYNC)
212	misc |= ATOM_VSYNC_POLARITY;
213
214    if (mode->Flags & V_NHSYNC)
215	misc |= ATOM_HSYNC_POLARITY;
216
217    if (mode->Flags & V_CSYNC)
218	misc |= ATOM_COMPOSITESYNC;
219
220    if (mode->Flags & V_INTERLACE)
221	misc |= ATOM_INTERLACE;
222
223    if (mode->Flags & V_DBLSCAN)
224	misc |= ATOM_DOUBLE_CLOCK_MODE;
225
226    param.susModeMiscInfo.usAccess      = cpu_to_le16(misc);
227    param.ucCRTC			= radeon_crtc->crtc_id;
228
229    data.exec.index = GetIndexIntoMasterTable(COMMAND, SetCRTC_Timing);
230    data.exec.dataSpace = (void *)&space;
231    data.exec.pspace = &param;
232
233    if (RHDAtomBiosFunc(info->atomBIOS->pScrn, info->atomBIOS, ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) {
234/*	ErrorF("Set CRTC Timing success\n"); */
235	return ATOM_SUCCESS ;
236    }
237
238    ErrorF("Set CRTC Timing failed\n");
239    return ATOM_NOT_IMPLEMENTED;
240}
241
242static AtomBiosResult
243atombios_set_crtc_dtd_timing(xf86CrtcPtr crtc, DisplayModePtr mode)
244{
245    RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private;
246    RADEONInfoPtr  info = RADEONPTR(crtc->scrn);
247    AtomBiosArgRec data;
248    unsigned char *space;
249    uint16_t misc = 0;
250    SET_CRTC_USING_DTD_TIMING_PARAMETERS param;
251    memset(&param, 0, sizeof(param));
252
253    param.usH_Size          = cpu_to_le16(mode->CrtcHDisplay);
254    param.usH_Blanking_Time = cpu_to_le16(mode->CrtcHBlankEnd - mode->CrtcHDisplay);
255    param.usV_Size          = cpu_to_le16(mode->CrtcVDisplay);
256    param.usV_Blanking_Time = cpu_to_le16(mode->CrtcVBlankEnd - mode->CrtcVDisplay);
257    param.usH_SyncOffset    = cpu_to_le16(mode->CrtcHSyncStart - mode->CrtcHDisplay);
258    param.usH_SyncWidth     = cpu_to_le16(mode->CrtcHSyncEnd - mode->CrtcHSyncStart);
259    param.usV_SyncOffset    = cpu_to_le16(mode->CrtcVSyncStart - mode->CrtcVDisplay);
260    param.usV_SyncWidth     = cpu_to_le16(mode->CrtcVSyncEnd - mode->CrtcVSyncStart);
261
262    if (mode->Flags & V_NVSYNC)
263	misc |= ATOM_VSYNC_POLARITY;
264
265    if (mode->Flags & V_NHSYNC)
266	misc |= ATOM_HSYNC_POLARITY;
267
268    if (mode->Flags & V_CSYNC)
269	misc |= ATOM_COMPOSITESYNC;
270
271    if (mode->Flags & V_INTERLACE)
272	misc |= ATOM_INTERLACE;
273
274    if (mode->Flags & V_DBLSCAN)
275	misc |= ATOM_DOUBLE_CLOCK_MODE;
276
277    param.susModeMiscInfo.usAccess = cpu_to_le16(misc);
278    param.ucCRTC= radeon_crtc->crtc_id;
279
280    data.exec.index = GetIndexIntoMasterTable(COMMAND, SetCRTC_UsingDTDTiming);
281    data.exec.dataSpace = (void *)&space;
282    data.exec.pspace = &param;
283
284    if (RHDAtomBiosFunc(info->atomBIOS->pScrn, info->atomBIOS, ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) {
285/*	ErrorF("Set DTD CRTC Timing success\n"); */
286	return ATOM_SUCCESS ;
287    }
288
289    ErrorF("Set DTD CRTC Timing failed\n");
290    return ATOM_NOT_IMPLEMENTED;
291}
292
293static void
294atombios_pick_pll(xf86CrtcPtr crtc)
295{
296    RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private;
297    RADEONInfoPtr info = RADEONPTR(crtc->scrn);
298    xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn);
299    xf86OutputPtr output;
300    RADEONOutputPrivatePtr radeon_output;
301    int o, c;
302    uint32_t pll_use_mask = 0;
303    Bool is_dp = FALSE;
304
305    if (IS_DCE4_VARIANT) {
306	for (o = 0; o < xf86_config->num_output; o++) {
307	    output = xf86_config->output[o];
308	    if (output->crtc == crtc) {
309		int mode = atombios_get_encoder_mode(output);
310		radeon_output = output->driver_private;
311
312		if (mode == ATOM_ENCODER_MODE_DP) {
313		    is_dp = TRUE;
314		    break;
315		} else {
316		    for (c = 0; c < xf86_config->num_crtc; c++) {
317			xf86CrtcPtr test_crtc = xf86_config->crtc[c];
318			RADEONCrtcPrivatePtr radeon_test_crtc = test_crtc->driver_private;
319
320			if (crtc != test_crtc && (radeon_test_crtc->pll_id >= 0))
321			    pll_use_mask |= (1 << radeon_test_crtc->pll_id);
322
323		    }
324		}
325	    }
326	}
327	/* DP clock comes from DCPLL, DP PHY CLK comes from ext source
328	 * setting ATOM_PPLL_INVALID skips the PPLL programming for DP
329	 */
330	if (is_dp)
331	    radeon_crtc->pll_id = ATOM_PPLL_INVALID;
332	else if (!(pll_use_mask & 1))
333	    radeon_crtc->pll_id = ATOM_PPLL1;
334	else
335	    radeon_crtc->pll_id = ATOM_PPLL2;
336    } else
337	radeon_crtc->pll_id = radeon_crtc->crtc_id;
338
339/*    ErrorF("Picked PLL %d\n", radeon_crtc->pll_id); */
340
341    for (o = 0; o < xf86_config->num_output; o++) {
342	output = xf86_config->output[o];
343	if (output->crtc == crtc) {
344	    radeon_output = output->driver_private;
345	    radeon_output->pll_id = radeon_crtc->pll_id;
346	}
347    }
348}
349
350union adjust_pixel_clock {
351	ADJUST_DISPLAY_PLL_PS_ALLOCATION v1;
352	ADJUST_DISPLAY_PLL_PS_ALLOCATION_V3 v3;
353};
354
355static uint32_t atombios_adjust_pll(xf86CrtcPtr crtc, DisplayModePtr mode, int *pll_flags_p)
356{
357    RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private;
358    ScrnInfoPtr pScrn = crtc->scrn;
359    RADEONInfoPtr  info = RADEONPTR(pScrn);
360    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn);
361    uint32_t adjusted_clock = mode->Clock;
362    RADEONOutputPrivatePtr radeon_output = NULL;
363    radeon_encoder_ptr radeon_encoder = NULL;
364    xf86OutputPtr output;
365    int pll_flags = 0;
366    int i;
367
368    if (IS_AVIVO_VARIANT) {
369	if (xf86ReturnOptValBool(info->Options, OPTION_NEW_PLL, TRUE))
370	    radeon_crtc->pll_algo = RADEON_PLL_NEW;
371	else
372	    radeon_crtc->pll_algo = RADEON_PLL_OLD;
373    } else {
374	if (xf86ReturnOptValBool(info->Options, OPTION_NEW_PLL, FALSE))
375	    radeon_crtc->pll_algo = RADEON_PLL_NEW;
376	else
377	    radeon_crtc->pll_algo = RADEON_PLL_OLD;
378    }
379
380    if (IS_AVIVO_VARIANT) {
381	if ((info->ChipFamily == CHIP_FAMILY_RS600) ||
382	    (info->ChipFamily == CHIP_FAMILY_RS690) ||
383	    (info->ChipFamily == CHIP_FAMILY_RS740))
384	    pll_flags |= /*RADEON_PLL_USE_FRAC_FB_DIV |*/
385		RADEON_PLL_PREFER_CLOSEST_LOWER;
386	if (IS_DCE32_VARIANT && mode->Clock > 200000) /* range limits??? */
387	    pll_flags |= RADEON_PLL_PREFER_HIGH_FB_DIV;
388	else
389	    pll_flags |= RADEON_PLL_PREFER_LOW_REF_DIV;
390    } else {
391	pll_flags |= RADEON_PLL_LEGACY;
392
393	if (mode->Clock > 200000) /* range limits??? */
394	    pll_flags |= RADEON_PLL_PREFER_HIGH_FB_DIV;
395	else
396	    pll_flags |= RADEON_PLL_PREFER_LOW_REF_DIV;
397    }
398
399    for (i = 0; i < xf86_config->num_output; i++) {
400	output = xf86_config->output[i];
401	if (output->crtc == crtc) {
402	    radeon_output = output->driver_private;
403	    radeon_encoder = radeon_get_encoder(output);
404	    if (IS_AVIVO_VARIANT) {
405		/* DVO wants 2x pixel clock if the DVO chip is in 12 bit mode */
406		if (radeon_encoder &&
407		    (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1) &&
408		    !IS_DCE3_VARIANT)
409		    adjusted_clock *= 2;
410		if (radeon_output->active_device &
411		    (ATOM_DEVICE_CV_SUPPORT | ATOM_DEVICE_TV_SUPPORT)) {
412		    pll_flags |= RADEON_PLL_PREFER_CLOSEST_LOWER;
413		    radeon_crtc->pll_algo = RADEON_PLL_OLD;
414		}
415	    } else {
416		if (radeon_output->active_device & (ATOM_DEVICE_LCD_SUPPORT |
417						    ATOM_DEVICE_DFP_SUPPORT))
418		    pll_flags |= RADEON_PLL_NO_ODD_POST_DIV;
419		if (radeon_output->active_device & (ATOM_DEVICE_LCD_SUPPORT))
420		    pll_flags |= (RADEON_PLL_USE_BIOS_DIVS | RADEON_PLL_USE_REF_DIV);
421	    }
422    	    if (IS_DCE3_VARIANT)
423		break;
424	}
425    }
426
427    if (IS_DCE3_VARIANT) {
428	union adjust_pixel_clock args;
429	int major, minor, index;
430	AtomBiosArgRec data;
431	unsigned char *space;
432
433	memset(&args, 0, sizeof(args));
434
435	index = GetIndexIntoMasterTable(COMMAND, AdjustDisplayPll);
436
437	atombios_get_command_table_version(info->atomBIOS, index, &major, &minor);
438
439	data.exec.index = index;
440	data.exec.dataSpace = (void *)&space;
441	data.exec.pspace = &args;
442
443	switch(major) {
444	case 1:
445	    switch(minor) {
446	    case 1:
447	    case 2:
448		args.v1.usPixelClock = cpu_to_le16(adjusted_clock / 10);
449		args.v1.ucTransmitterID = radeon_encoder->encoder_id;
450		args.v1.ucEncodeMode = atombios_get_encoder_mode(output);
451
452/*		ErrorF("before %d\n", args.v1.usPixelClock); */
453		if (RHDAtomBiosFunc(info->atomBIOS->pScrn, info->atomBIOS, ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) {
454		    adjusted_clock = le16_to_cpu(args.v1.usPixelClock) * 10;
455		}
456/*		ErrorF("after %d\n", args.v1.usPixelClock); */
457		break;
458	    case 3:
459		args.v3.sInput.usPixelClock = cpu_to_le16(adjusted_clock / 10);
460		args.v3.sInput.ucTransmitterID = radeon_encoder->encoder_id;
461		args.v3.sInput.ucEncodeMode = atombios_get_encoder_mode(output);
462		args.v3.sInput.ucDispPllConfig = 0;
463		if (radeon_output->coherent_mode || (args.v3.sInput.ucEncodeMode == ATOM_ENCODER_MODE_DP))
464		    args.v3.sInput.ucDispPllConfig |= DISPPLL_CONFIG_COHERENT_MODE;
465		if (adjusted_clock > 165000)
466		    args.v3.sInput.ucDispPllConfig |= DISPPLL_CONFIG_DUAL_LINK;
467		// if SS
468		//    args.v3.sInput.ucDispPllConfig |= DISPPLL_CONFIG_SS_ENABLE;
469
470/*		ErrorF("before %d 0x%x\n", args.v3.sInput.usPixelClock, args.v3.sInput.ucDispPllConfig); */
471		if (RHDAtomBiosFunc(info->atomBIOS->pScrn, info->atomBIOS, ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) {
472		    adjusted_clock = args.v3.sOutput.ulDispPllFreq * 10;
473		    if (args.v3.sOutput.ucRefDiv) {
474			pll_flags |= RADEON_PLL_USE_REF_DIV;
475			info->pll.reference_div = args.v3.sOutput.ucRefDiv;
476		    }
477		    if (args.v3.sOutput.ucPostDiv) {
478			pll_flags |= RADEON_PLL_USE_POST_DIV;
479			info->pll.post_div = args.v3.sOutput.ucPostDiv;
480		    }
481/*		    ErrorF("after %d %d %d\n", args.v3.sOutput.ulDispPllFreq,
482			   args.v3.sOutput.ucRefDiv, args.v3.sOutput.ucPostDiv); */
483		}
484		break;
485	    default:
486		ErrorF("%s: Unknown table version %d %d\n", __func__, major, minor);
487		goto out;
488	    }
489	    break;
490	default:
491	    ErrorF("%s: Unknown table version %d %d\n", __func__, major, minor);
492	    goto out;
493	}
494    }
495out:
496    *pll_flags_p = pll_flags;
497    return adjusted_clock;
498}
499
500union set_pixel_clock {
501	SET_PIXEL_CLOCK_PS_ALLOCATION base;
502	PIXEL_CLOCK_PARAMETERS v1;
503	PIXEL_CLOCK_PARAMETERS_V2 v2;
504	PIXEL_CLOCK_PARAMETERS_V3 v3;
505	PIXEL_CLOCK_PARAMETERS_V5 v5;
506};
507
508static void
509atombios_crtc_set_dcpll(xf86CrtcPtr crtc)
510{
511    RADEONInfoPtr  info = RADEONPTR(crtc->scrn);
512    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn);
513    xf86OutputPtr output = NULL;
514    RADEONOutputPrivatePtr radeon_output = NULL;
515    radeon_encoder_ptr radeon_encoder = NULL;
516    int index;
517    int major, minor, i;
518    union set_pixel_clock args;
519    AtomBiosArgRec data;
520    unsigned char *space;
521
522    memset(&args, 0, sizeof(args));
523
524    for (i = 0; i < xf86_config->num_output; i++) {
525	output = xf86_config->output[i];
526	if (output->crtc == crtc) {
527	    radeon_output = output->driver_private;
528	    radeon_encoder = radeon_get_encoder(output);
529	    break;
530	}
531    }
532
533    if (radeon_output == NULL) {
534	xf86DrvMsg(crtc->scrn->scrnIndex, X_ERROR, "No output assigned to crtc!\n");
535	return;
536    }
537
538    if (radeon_encoder == NULL) {
539	xf86DrvMsg(crtc->scrn->scrnIndex, X_ERROR, "No encoder assigned to output!\n");
540	return;
541    }
542
543    index = GetIndexIntoMasterTable(COMMAND, SetPixelClock);
544    atombios_get_command_table_version(info->atomBIOS, index, &major, &minor);
545
546    /*ErrorF("table is %d %d\n", major, minor);*/
547    switch(major) {
548    case 1:
549	switch(minor) {
550	case 5:
551	    args.v5.ucCRTC = ATOM_CRTC_INVALID;
552	    /* XXX: get this from the firmwareinfo table */
553	    args.v5.usPixelClock = info->default_dispclk;
554	    args.v5.ucPpll = ATOM_DCPLL;
555	    break;
556	default:
557	    ErrorF("Unknown table version\n");
558	    exit(-1);
559	}
560	break;
561    default:
562	ErrorF("Unknown table version\n");
563	exit(-1);
564    }
565
566    data.exec.index = index;
567    data.exec.dataSpace = (void *)&space;
568    data.exec.pspace = &args;
569
570    if (RHDAtomBiosFunc(info->atomBIOS->pScrn, info->atomBIOS, ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) {
571/*	ErrorF("Set DCPLL success\n"); */
572	return;
573    }
574
575    ErrorF("Set DCPLL failed\n");
576    return;
577}
578
579static void
580atombios_crtc_set_pll(xf86CrtcPtr crtc, DisplayModePtr mode)
581{
582    RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private;
583    ScrnInfoPtr pScrn = crtc->scrn;
584    RADEONInfoPtr  info = RADEONPTR(pScrn);
585    unsigned char *RADEONMMIO = info->MMIO;
586    int index;
587    uint32_t sclock;
588    uint32_t ref_div = 0, fb_div = 0, frac_fb_div = 0, post_div = 0;
589    int major, minor;
590    union set_pixel_clock args;
591    xf86OutputPtr output = NULL;
592    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn);
593    radeon_encoder_ptr radeon_encoder = NULL;
594    int pll_flags = 0;
595    uint32_t temp;
596    AtomBiosArgRec data;
597    unsigned char *space;
598    int i;
599
600    memset(&args, 0, sizeof(args));
601
602    if (IS_DCE4_VARIANT) {
603	/* XXX 6 crtcs, but only 2 plls */
604	switch (radeon_crtc->pll_id) {
605	case ATOM_PPLL1:
606	    temp = INREG(EVERGREEN_P1PLL_SS_CNTL);
607	    OUTREG(EVERGREEN_P1PLL_SS_CNTL, temp & ~EVERGREEN_PxPLL_SS_EN);
608	    break;
609	case ATOM_PPLL2:
610	    temp = INREG(EVERGREEN_P2PLL_SS_CNTL);
611	    OUTREG(EVERGREEN_P2PLL_SS_CNTL, temp & ~EVERGREEN_PxPLL_SS_EN);
612	    break;
613	}
614    } else {
615	if (radeon_crtc->crtc_id == 0) {
616	    temp = INREG(AVIVO_P1PLL_INT_SS_CNTL);
617	    OUTREG(AVIVO_P1PLL_INT_SS_CNTL, temp & ~1);
618	} else {
619	    temp = INREG(AVIVO_P2PLL_INT_SS_CNTL);
620	    OUTREG(AVIVO_P2PLL_INT_SS_CNTL, temp & ~1);
621	}
622    }
623
624    if (IS_DCE3_VARIANT) {
625	for (i = 0; i < xf86_config->num_output; i++) {
626	    output = xf86_config->output[i];
627	    if (output->crtc == crtc) {
628		radeon_encoder = radeon_get_encoder(output);
629		break;
630	    }
631	}
632
633	if (output->driver_private == NULL) {
634	    xf86DrvMsg(crtc->scrn->scrnIndex, X_ERROR, "No output assigned to crtc!\n");
635	    return;
636	}
637	if (radeon_encoder == NULL) {
638	    xf86DrvMsg(crtc->scrn->scrnIndex, X_ERROR, "No encoder assigned to output!\n");
639	    return;
640	}
641    }
642
643    sclock = atombios_adjust_pll(crtc, mode, &pll_flags);
644
645    RADEONComputePLL(crtc, &info->pll, sclock, &temp,
646		     &fb_div, &frac_fb_div, &ref_div, &post_div, pll_flags);
647    sclock = temp; /* 10 khz */
648
649    xf86DrvMsg(crtc->scrn->scrnIndex, X_INFO,
650	       "crtc(%d) Clock: mode %d, PLL %lu\n",
651	       radeon_crtc->crtc_id, mode->Clock, (long unsigned int)sclock * 10);
652    xf86DrvMsg(crtc->scrn->scrnIndex, X_INFO,
653	       "crtc(%d) PLL  : refdiv %u, fbdiv 0x%X(%u), fracfbdiv %u, pdiv %u\n",
654	       radeon_crtc->crtc_id, (unsigned int)ref_div, (unsigned int)fb_div,
655	       (unsigned int)fb_div, (unsigned int)frac_fb_div, (unsigned int)post_div);
656
657    index = GetIndexIntoMasterTable(COMMAND, SetPixelClock);
658    atombios_get_command_table_version(info->atomBIOS, index, &major, &minor);
659
660    /*ErrorF("table is %d %d\n", major, minor);*/
661    switch(major) {
662    case 1:
663	switch(minor) {
664	case 1:
665	case 2:
666	    args.v2.usPixelClock = cpu_to_le16(mode->Clock / 10);
667	    args.v2.usRefDiv = cpu_to_le16(ref_div);
668	    args.v2.usFbDiv = cpu_to_le16(fb_div);
669	    args.v2.ucFracFbDiv = frac_fb_div;
670	    args.v2.ucPostDiv = post_div;
671	    args.v2.ucPpll = radeon_crtc->pll_id;
672	    args.v2.ucCRTC = radeon_crtc->crtc_id;
673	    args.v2.ucRefDivSrc = 1;
674	    break;
675	case 3:
676	    args.v3.usPixelClock = cpu_to_le16(mode->Clock / 10);
677	    args.v3.usRefDiv = cpu_to_le16(ref_div);
678	    args.v3.usFbDiv = cpu_to_le16(fb_div);
679	    args.v3.ucFracFbDiv = frac_fb_div;
680	    args.v3.ucPostDiv = post_div;
681	    args.v3.ucPpll = radeon_crtc->pll_id;
682	    args.v3.ucMiscInfo = (radeon_crtc->crtc_id << 2);
683	    args.v3.ucTransmitterId = radeon_encoder->encoder_id;
684	    args.v3.ucEncoderMode = atombios_get_encoder_mode(output);
685	    break;
686	case 5:
687	    args.v5.ucCRTC = radeon_crtc->crtc_id;
688	    args.v5.usPixelClock = cpu_to_le16(mode->Clock / 10);
689	    args.v5.ucRefDiv = ref_div;
690	    args.v5.usFbDiv = cpu_to_le16(fb_div);
691	    args.v5.ulFbDivDecFrac = cpu_to_le32(frac_fb_div * 100000);
692	    args.v5.ucPostDiv = post_div;
693	    args.v5.ucPpll = radeon_crtc->pll_id;
694	    args.v5.ucMiscInfo = 0; //HDMI depth
695	    args.v5.ucTransmitterID = radeon_encoder->encoder_id;
696	    args.v5.ucEncoderMode = atombios_get_encoder_mode(output);
697	    break;
698	default:
699	    ErrorF("Unknown table version\n");
700	    exit(-1);
701	}
702	break;
703    default:
704	ErrorF("Unknown table version\n");
705	exit(-1);
706    }
707
708    data.exec.index = index;
709    data.exec.dataSpace = (void *)&space;
710    data.exec.pspace = &args;
711
712    if (RHDAtomBiosFunc(info->atomBIOS->pScrn, info->atomBIOS, ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) {
713/*	ErrorF("Set CRTC %d PLL success\n", radeon_crtc->crtc_id); */
714	return;
715    }
716
717    ErrorF("Set CRTC %d PLL failed\n", radeon_crtc->crtc_id);
718    return;
719}
720
721static void evergreen_set_base_format(xf86CrtcPtr crtc,
722				      DisplayModePtr mode,
723				      DisplayModePtr adjusted_mode,
724				      int x, int y)
725{
726    ScrnInfoPtr pScrn = crtc->scrn;
727    RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private;
728    RADEONInfoPtr  info = RADEONPTR(pScrn);
729    unsigned char *RADEONMMIO = info->MMIO;
730    uint64_t fb_location = crtc->scrn->fbOffset + info->fbLocation;
731    uint32_t fb_format;
732    uint32_t fb_swap = EVERGREEN_GRPH_ENDIAN_SWAP(EVERGREEN_GRPH_ENDIAN_NONE);
733
734    switch (crtc->scrn->bitsPerPixel) {
735    case 15:
736	fb_format = (EVERGREEN_GRPH_DEPTH(EVERGREEN_GRPH_DEPTH_16BPP) |
737		     EVERGREEN_GRPH_FORMAT(EVERGREEN_GRPH_FORMAT_ARGB1555));
738	break;
739    case 16:
740	fb_format = (EVERGREEN_GRPH_DEPTH(EVERGREEN_GRPH_DEPTH_16BPP) |
741		     EVERGREEN_GRPH_FORMAT(EVERGREEN_GRPH_FORMAT_ARGB565));
742#if X_BYTE_ORDER == X_BIG_ENDIAN
743	fb_swap = EVERGREEN_GRPH_ENDIAN_SWAP(EVERGREEN_GRPH_ENDIAN_8IN16);
744#endif
745	break;
746    case 24:
747    case 32:
748	fb_format = (EVERGREEN_GRPH_DEPTH(EVERGREEN_GRPH_DEPTH_32BPP) |
749		     EVERGREEN_GRPH_FORMAT(EVERGREEN_GRPH_FORMAT_ARGB8888));
750#if X_BYTE_ORDER == X_BIG_ENDIAN
751	fb_swap = EVERGREEN_GRPH_ENDIAN_SWAP(EVERGREEN_GRPH_ENDIAN_8IN32);
752#endif
753	break;
754    default:
755	FatalError("Unsupported screen depth: %d\n", xf86GetDepth());
756    }
757
758    switch (radeon_crtc->crtc_id) {
759    case 0:
760    default:
761	OUTREG(AVIVO_D1VGA_CONTROL, 0);
762	break;
763    case 1:
764	OUTREG(AVIVO_D2VGA_CONTROL, 0);
765	break;
766    case 2:
767	OUTREG(EVERGREEN_D3VGA_CONTROL, 0);
768	break;
769    case 3:
770	OUTREG(EVERGREEN_D4VGA_CONTROL, 0);
771	break;
772    case 4:
773	OUTREG(EVERGREEN_D5VGA_CONTROL, 0);
774	break;
775    case 5:
776	OUTREG(EVERGREEN_D6VGA_CONTROL, 0);
777	break;
778    }
779
780    /* setup fb format and location
781     */
782    if (crtc->rotatedData != NULL) {
783	/* x/y offset is already included */
784	x = 0;
785	y = 0;
786	fb_location = fb_location + (char *)crtc->rotatedData - (char *)info->FB;
787    }
788
789
790    OUTREG(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + radeon_crtc->crtc_offset,
791	   (fb_location >> 32) & 0xf);
792    OUTREG(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + radeon_crtc->crtc_offset,
793	   (fb_location >> 32) & 0xf);
794    OUTREG(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + radeon_crtc->crtc_offset,
795	   fb_location & EVERGREEN_GRPH_SURFACE_ADDRESS_MASK);
796    OUTREG(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + radeon_crtc->crtc_offset,
797	   fb_location & EVERGREEN_GRPH_SURFACE_ADDRESS_MASK);
798    OUTREG(EVERGREEN_GRPH_CONTROL + radeon_crtc->crtc_offset, fb_format);
799    OUTREG(EVERGREEN_GRPH_SWAP_CONTROL + radeon_crtc->crtc_offset, fb_swap);
800
801    OUTREG(EVERGREEN_GRPH_SURFACE_OFFSET_X + radeon_crtc->crtc_offset, 0);
802    OUTREG(EVERGREEN_GRPH_SURFACE_OFFSET_Y + radeon_crtc->crtc_offset, 0);
803    OUTREG(EVERGREEN_GRPH_X_START + radeon_crtc->crtc_offset, 0);
804    OUTREG(EVERGREEN_GRPH_Y_START + radeon_crtc->crtc_offset, 0);
805    OUTREG(EVERGREEN_GRPH_X_END + radeon_crtc->crtc_offset, info->virtualX);
806    OUTREG(EVERGREEN_GRPH_Y_END + radeon_crtc->crtc_offset, info->virtualY);
807    OUTREG(EVERGREEN_GRPH_PITCH + radeon_crtc->crtc_offset,
808	   crtc->scrn->displayWidth);
809    OUTREG(EVERGREEN_GRPH_ENABLE + radeon_crtc->crtc_offset, 1);
810
811    OUTREG(EVERGREEN_DESKTOP_HEIGHT + radeon_crtc->crtc_offset, mode->VDisplay);
812    x &= ~3;
813    y &= ~1;
814    OUTREG(EVERGREEN_VIEWPORT_START + radeon_crtc->crtc_offset, (x << 16) | y);
815    OUTREG(EVERGREEN_VIEWPORT_SIZE + radeon_crtc->crtc_offset, (mode->HDisplay << 16) | mode->VDisplay);
816
817    if (adjusted_mode->Flags & V_INTERLACE)
818	OUTREG(EVERGREEN_DATA_FORMAT + radeon_crtc->crtc_offset, EVERGREEN_INTERLEAVE_EN);
819    else
820	OUTREG(EVERGREEN_DATA_FORMAT + radeon_crtc->crtc_offset, 0);
821
822}
823
824static void avivo_set_base_format(xf86CrtcPtr crtc,
825				  DisplayModePtr mode,
826				  DisplayModePtr adjusted_mode,
827				  int x, int y)
828{
829    ScrnInfoPtr pScrn = crtc->scrn;
830    RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private;
831    RADEONInfoPtr  info = RADEONPTR(pScrn);
832    unsigned char *RADEONMMIO = info->MMIO;
833    uint64_t fb_location = crtc->scrn->fbOffset + info->fbLocation;
834    uint32_t fb_format;
835#if X_BYTE_ORDER == X_BIG_ENDIAN
836    uint32_t fb_swap = R600_D1GRPH_SWAP_ENDIAN_NONE;
837#endif
838
839    switch (crtc->scrn->bitsPerPixel) {
840    case 15:
841	fb_format = AVIVO_D1GRPH_CONTROL_DEPTH_16BPP | AVIVO_D1GRPH_CONTROL_16BPP_ARGB1555;
842	break;
843    case 16:
844	fb_format = AVIVO_D1GRPH_CONTROL_DEPTH_16BPP | AVIVO_D1GRPH_CONTROL_16BPP_RGB565;
845#if X_BYTE_ORDER == X_BIG_ENDIAN
846	fb_swap = R600_D1GRPH_SWAP_ENDIAN_16BIT;
847#endif
848	break;
849    case 24:
850    case 32:
851	fb_format = AVIVO_D1GRPH_CONTROL_DEPTH_32BPP | AVIVO_D1GRPH_CONTROL_32BPP_ARGB8888;
852#if X_BYTE_ORDER == X_BIG_ENDIAN
853	fb_swap = R600_D1GRPH_SWAP_ENDIAN_32BIT;
854#endif
855	break;
856    default:
857	FatalError("Unsupported screen depth: %d\n", xf86GetDepth());
858    }
859
860    if (info->tilingEnabled && (crtc->rotatedData == NULL)) {
861	fb_format |= AVIVO_D1GRPH_MACRO_ADDRESS_MODE;
862    }
863
864    if (radeon_crtc->crtc_id == 0)
865	OUTREG(AVIVO_D1VGA_CONTROL, 0);
866    else
867	OUTREG(AVIVO_D2VGA_CONTROL, 0);
868
869    /* setup fb format and location
870     */
871    if (crtc->rotatedData != NULL) {
872	/* x/y offset is already included */
873	x = 0;
874	y = 0;
875	fb_location = fb_location + (char *)crtc->rotatedData - (char *)info->FB;
876    }
877
878    if (info->ChipFamily >= CHIP_FAMILY_RV770) {
879	if (radeon_crtc->crtc_id) {
880	    OUTREG(R700_D2GRPH_PRIMARY_SURFACE_ADDRESS_HIGH, (fb_location >> 32) & 0xf);
881	    OUTREG(R700_D2GRPH_SECONDARY_SURFACE_ADDRESS_HIGH, (fb_location >> 32) & 0xf);
882	} else {
883	    OUTREG(R700_D1GRPH_PRIMARY_SURFACE_ADDRESS_HIGH, (fb_location >> 32) & 0xf);
884	    OUTREG(R700_D1GRPH_SECONDARY_SURFACE_ADDRESS_HIGH, (fb_location >> 32) & 0xf);
885	}
886    }
887    OUTREG(AVIVO_D1GRPH_PRIMARY_SURFACE_ADDRESS + radeon_crtc->crtc_offset,
888	   fb_location & 0xffffffff);
889    OUTREG(AVIVO_D1GRPH_SECONDARY_SURFACE_ADDRESS + radeon_crtc->crtc_offset,
890	   fb_location & 0xffffffff);
891    OUTREG(AVIVO_D1GRPH_CONTROL + radeon_crtc->crtc_offset, fb_format);
892
893#if X_BYTE_ORDER == X_BIG_ENDIAN
894    if (info->ChipFamily >= CHIP_FAMILY_R600)
895	OUTREG(R600_D1GRPH_SWAP_CONTROL + radeon_crtc->crtc_offset, fb_swap);
896#endif
897
898    OUTREG(AVIVO_D1GRPH_SURFACE_OFFSET_X + radeon_crtc->crtc_offset, 0);
899    OUTREG(AVIVO_D1GRPH_SURFACE_OFFSET_Y + radeon_crtc->crtc_offset, 0);
900    OUTREG(AVIVO_D1GRPH_X_START + radeon_crtc->crtc_offset, 0);
901    OUTREG(AVIVO_D1GRPH_Y_START + radeon_crtc->crtc_offset, 0);
902    OUTREG(AVIVO_D1GRPH_X_END + radeon_crtc->crtc_offset, info->virtualX);
903    OUTREG(AVIVO_D1GRPH_Y_END + radeon_crtc->crtc_offset, info->virtualY);
904    OUTREG(AVIVO_D1GRPH_PITCH + radeon_crtc->crtc_offset,
905	   crtc->scrn->displayWidth);
906    OUTREG(AVIVO_D1GRPH_ENABLE + radeon_crtc->crtc_offset, 1);
907
908    OUTREG(AVIVO_D1MODE_DESKTOP_HEIGHT + radeon_crtc->crtc_offset, mode->VDisplay);
909    x &= ~3;
910    y &= ~1;
911    OUTREG(AVIVO_D1MODE_VIEWPORT_START + radeon_crtc->crtc_offset, (x << 16) | y);
912    OUTREG(AVIVO_D1MODE_VIEWPORT_SIZE + radeon_crtc->crtc_offset,
913	   (mode->HDisplay << 16) | mode->VDisplay);
914
915    if (mode->Flags & V_INTERLACE)
916	OUTREG(AVIVO_D1MODE_DATA_FORMAT + radeon_crtc->crtc_offset,
917	       AVIVO_D1MODE_INTERLEAVE_EN);
918    else
919	OUTREG(AVIVO_D1MODE_DATA_FORMAT + radeon_crtc->crtc_offset, 0);
920}
921
922static void legacy_set_base_format(xf86CrtcPtr crtc,
923				   DisplayModePtr mode,
924				   DisplayModePtr adjusted_mode,
925				   int x, int y)
926{
927    ScrnInfoPtr pScrn = crtc->scrn;
928    RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private;
929    RADEONInfoPtr  info = RADEONPTR(pScrn);
930    unsigned char *RADEONMMIO = info->MMIO;
931    int format = 0;
932    uint32_t crtc_gen_cntl, crtc2_gen_cntl, crtc_pitch;
933
934    RADEONInitCommonRegisters(info->ModeReg, info);
935    RADEONInitSurfaceCntl(crtc, info->ModeReg);
936    RADEONRestoreCommonRegisters(pScrn, info->ModeReg);
937
938    switch (info->CurrentLayout.pixel_code) {
939    case 4:  format = 1; break;
940    case 8:  format = 2; break;
941    case 15: format = 3; break;      /*  555 */
942    case 16: format = 4; break;      /*  565 */
943    case 24: format = 5; break;      /*  RGB */
944    case 32: format = 6; break;      /* xRGB */
945    default:
946	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
947		   "Unsupported pixel depth (%d)\n",
948		   info->CurrentLayout.bitsPerPixel);
949    }
950
951    crtc_pitch  = (((pScrn->displayWidth * pScrn->bitsPerPixel) +
952		    ((pScrn->bitsPerPixel * 8) -1)) /
953		       (pScrn->bitsPerPixel * 8));
954    crtc_pitch |= crtc_pitch << 16;
955
956    switch (radeon_crtc->crtc_id) {
957    case 0:
958	crtc_gen_cntl = INREG(RADEON_CRTC_GEN_CNTL) & 0xfffff0ff;
959	crtc_gen_cntl |= (format << 8);
960	OUTREG(RADEON_CRTC_GEN_CNTL, crtc_gen_cntl);
961	OUTREG(RADEON_CRTC_PITCH, crtc_pitch);
962	RADEONInitCrtcBase(crtc, info->ModeReg, x, y);
963	RADEONRestoreCrtcBase(pScrn, info->ModeReg);
964	break;
965    case 1:
966	crtc2_gen_cntl = INREG(RADEON_CRTC2_GEN_CNTL) & 0xfffff0ff;
967	crtc2_gen_cntl |= (format << 8);
968	OUTREG(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl);
969	OUTREG(RADEON_CRTC2_PITCH, crtc_pitch);
970	RADEONInitCrtc2Base(crtc, info->ModeReg, x, y);
971	RADEONRestoreCrtc2Base(pScrn, info->ModeReg);
972	OUTREG(RADEON_FP_H2_SYNC_STRT_WID,   INREG(RADEON_CRTC2_H_SYNC_STRT_WID));
973	OUTREG(RADEON_FP_V2_SYNC_STRT_WID,   INREG(RADEON_CRTC2_V_SYNC_STRT_WID));
974	break;
975    }
976}
977
978void
979atombios_crtc_mode_set(xf86CrtcPtr crtc,
980		       DisplayModePtr mode,
981		       DisplayModePtr adjusted_mode,
982		       int x, int y)
983{
984    ScrnInfoPtr pScrn = crtc->scrn;
985    RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private;
986    RADEONInfoPtr  info = RADEONPTR(pScrn);
987    Bool tilingChanged = FALSE;
988
989    if (info->allowColorTiling) {
990	radeon_crtc->can_tile = (mode->Flags & (V_DBLSCAN | V_INTERLACE)) ? FALSE : TRUE;
991	tilingChanged = RADEONSetTiling(pScrn);
992    }
993
994/*    ErrorF("Mode %dx%d - %d %d %d\n", adjusted_mode->CrtcHDisplay, adjusted_mode->CrtcVDisplay,
995	   adjusted_mode->CrtcHTotal, adjusted_mode->CrtcVTotal, adjusted_mode->Flags); */
996
997    RADEONInitMemMapRegisters(pScrn, info->ModeReg, info);
998    RADEONRestoreMemMapRegisters(pScrn, info->ModeReg);
999
1000    if (IS_DCE4_VARIANT)
1001	atombios_crtc_set_dcpll(crtc);
1002    atombios_pick_pll(crtc);
1003    atombios_crtc_set_pll(crtc, adjusted_mode);
1004    if (IS_DCE4_VARIANT)
1005	atombios_set_crtc_dtd_timing(crtc, adjusted_mode);
1006    else {
1007	atombios_set_crtc_timing(crtc, adjusted_mode);
1008	if (!IS_AVIVO_VARIANT && (radeon_crtc->crtc_id == 0))
1009	    atombios_set_crtc_dtd_timing(crtc, adjusted_mode);
1010    }
1011
1012    if (IS_DCE4_VARIANT)
1013	evergreen_set_base_format(crtc, mode, adjusted_mode, x, y);
1014    else if (IS_AVIVO_VARIANT)
1015	avivo_set_base_format(crtc, mode, adjusted_mode, x, y);
1016    else
1017	legacy_set_base_format(crtc, mode, adjusted_mode, x, y);
1018
1019    if (info->DispPriority)
1020	RADEONInitDispBandwidth(pScrn);
1021
1022    radeon_crtc->initialized = TRUE;
1023
1024    if (tilingChanged) {
1025	/* need to redraw front buffer, I guess this can be considered a hack ? */
1026	/* if this is called during ScreenInit() we don't have pScrn->pScreen yet */
1027	if (pScrn->pScreen)
1028	    xf86EnableDisableFBAccess(XF86_ENABLEDISABLEFB_ARG(pScrn), FALSE);
1029	RADEONChangeSurfaces(pScrn);
1030	if (pScrn->pScreen)
1031	    xf86EnableDisableFBAccess(XF86_ENABLEDISABLEFB_ARG(pScrn), TRUE);
1032	/* xf86SetRootClip would do, but can't access that here */
1033    }
1034
1035}
1036
1037/* Calculate display buffer watermark to prevent buffer underflow */
1038void
1039RADEONInitDispBandwidthAVIVO(ScrnInfoPtr pScrn,
1040			      DisplayModePtr mode1, int pixel_bytes1,
1041			      DisplayModePtr mode2, int pixel_bytes2)
1042{
1043    RADEONInfoPtr info = RADEONPTR(pScrn);
1044    RADEONEntPtr pRADEONEnt   = RADEONEntPriv(pScrn);
1045    unsigned char *RADEONMMIO = info->MMIO;
1046
1047    uint32_t dc_lb_memory_split;
1048    float available_bandwidth = 0;
1049    float read_delay_latency = 1000;
1050    int i;
1051    Bool sideport = FALSE;
1052
1053    /*
1054     * Set display0/1 priority up in the memory controller for
1055     * modes if the user specifies HIGH for displaypriority
1056     * option.
1057     */
1058    if (info->DispPriority == 2) {
1059	uint32_t mc_init_misc_lat_timer = 0;
1060	if (info->ChipFamily == CHIP_FAMILY_RV515)
1061	    mc_init_misc_lat_timer = INMC(pScrn, RV515_MC_INIT_MISC_LAT_TIMER);
1062	else if ((info->ChipFamily == CHIP_FAMILY_RS690) ||
1063		 (info->ChipFamily == CHIP_FAMILY_RS740))
1064	    mc_init_misc_lat_timer = INMC(pScrn, RS690_MC_INIT_MISC_LAT_TIMER);
1065
1066	mc_init_misc_lat_timer &= ~(R300_MC_DISP1R_INIT_LAT_MASK << R300_MC_DISP1R_INIT_LAT_SHIFT);
1067	mc_init_misc_lat_timer &= ~(R300_MC_DISP0R_INIT_LAT_MASK << R300_MC_DISP0R_INIT_LAT_SHIFT);
1068
1069	if (pRADEONEnt->pCrtc[1]->enabled)
1070	    mc_init_misc_lat_timer |= (1 << R300_MC_DISP1R_INIT_LAT_SHIFT); /* display 1 */
1071	if (pRADEONEnt->pCrtc[0]->enabled)
1072	    mc_init_misc_lat_timer |= (1 << R300_MC_DISP0R_INIT_LAT_SHIFT); /* display 0 */
1073
1074	if (info->ChipFamily == CHIP_FAMILY_RV515)
1075	    OUTMC(pScrn, RV515_MC_INIT_MISC_LAT_TIMER, mc_init_misc_lat_timer);
1076	else if ((info->ChipFamily == CHIP_FAMILY_RS690) ||
1077		 (info->ChipFamily == CHIP_FAMILY_RS740))
1078	    OUTMC(pScrn, RS690_MC_INIT_MISC_LAT_TIMER, mc_init_misc_lat_timer);
1079    }
1080
1081    /*
1082     * Line Buffer Setup
1083     * There is a single line buffer shared by both display controllers.
1084     * DC_LB_MEMORY_SPLIT controls how that line buffer is shared between the display
1085     * controllers.  The paritioning can either be done manually or via one of four
1086     * preset allocations specified in bits 1:0:
1087     * 0 - line buffer is divided in half and shared between each display controller
1088     * 1 - D1 gets 3/4 of the line buffer, D2 gets 1/4
1089     * 2 - D1 gets the whole buffer
1090     * 3 - D1 gets 1/4 of the line buffer, D2 gets 3/4
1091     * Setting bit 2 of DC_LB_MEMORY_SPLIT controls switches to manual allocation mode.
1092     * In manual allocation mode, D1 always starts at 0, D1 end/2 is specified in bits
1093     * 14:4; D2 allocation follows D1.
1094     */
1095
1096    dc_lb_memory_split = INREG(AVIVO_DC_LB_MEMORY_SPLIT) & ~AVIVO_DC_LB_MEMORY_SPLIT_MASK;
1097    dc_lb_memory_split &= ~AVIVO_DC_LB_MEMORY_SPLIT_SHIFT_MODE;
1098    /* auto */
1099    if (mode1 && mode2) {
1100	if (mode1->HDisplay > mode2->HDisplay) {
1101	    if (mode1->HDisplay > 2560)
1102		dc_lb_memory_split |= AVIVO_DC_LB_MEMORY_SPLIT_D1_3Q_D2_1Q;
1103	    else
1104		dc_lb_memory_split |= AVIVO_DC_LB_MEMORY_SPLIT_D1HALF_D2HALF;
1105	} else if (mode2->HDisplay > mode1->HDisplay) {
1106	    if (mode2->HDisplay > 2560)
1107		dc_lb_memory_split |= AVIVO_DC_LB_MEMORY_SPLIT_D1_1Q_D2_3Q;
1108	    else
1109		dc_lb_memory_split |= AVIVO_DC_LB_MEMORY_SPLIT_D1HALF_D2HALF;
1110	} else
1111	    dc_lb_memory_split |= AVIVO_DC_LB_MEMORY_SPLIT_D1HALF_D2HALF;
1112    } else if (mode1) {
1113	dc_lb_memory_split |= AVIVO_DC_LB_MEMORY_SPLIT_D1_ONLY;
1114    } else if (mode2) {
1115	dc_lb_memory_split |= AVIVO_DC_LB_MEMORY_SPLIT_D1_1Q_D2_3Q;
1116    }
1117    OUTREG(AVIVO_DC_LB_MEMORY_SPLIT, dc_lb_memory_split);
1118#if 0
1119    /* manual */
1120    dc_lb_memory_split |= AVIVO_DC_LB_MEMORY_SPLIT_SHIFT_MODE;
1121    dc_lb_memory_split &= ~(AVIVO_DC_LB_DISP1_END_ADR_MASK << AVIVO_DC_LB_DISP1_END_ADR_SHIFT);
1122    if (mode1) {
1123	dc_lb_memory_split |= ((((mode1->HDisplay / 2) + 64 /*???*/) & AVIVO_DC_LB_DISP1_END_ADR_MASK)
1124			       << AVIVO_DC_LB_DISP1_END_ADR_SHIFT);
1125    } else if (mode2) {
1126	dc_lb_memory_split |= (0 << AVIVO_DC_LB_DISP1_END_ADR_SHIFT);
1127    }
1128    OUTREG(AVIVO_DC_LB_MEMORY_SPLIT, dc_lb_memory_split);
1129#endif
1130
1131    /* fixme
1132     * Still need to implement the actual watermark calculation
1133     * for rs600.  This just allows us to force high display
1134     * priority.
1135     */
1136    if (info->ChipFamily == CHIP_FAMILY_RS600) {
1137	if (info->DispPriority == 2) {
1138	    uint32_t priority_cnt;
1139
1140	    if (mode1) {
1141		priority_cnt = INREG(AVIVO_D1MODE_PRIORITY_A_CNT);
1142		priority_cnt |= AVIVO_DxMODE_PRIORITY_ALWAYS_ON;
1143		OUTREG(AVIVO_D1MODE_PRIORITY_A_CNT, priority_cnt);
1144
1145		priority_cnt = INREG(AVIVO_D1MODE_PRIORITY_B_CNT);
1146		priority_cnt |= AVIVO_DxMODE_PRIORITY_ALWAYS_ON;
1147		OUTREG(AVIVO_D1MODE_PRIORITY_B_CNT, priority_cnt);
1148	    }
1149
1150	    if (mode2) {
1151		priority_cnt = INREG(AVIVO_D2MODE_PRIORITY_A_CNT);
1152		priority_cnt |= AVIVO_DxMODE_PRIORITY_ALWAYS_ON;
1153		OUTREG(AVIVO_D2MODE_PRIORITY_A_CNT, priority_cnt);
1154
1155		priority_cnt = INREG(AVIVO_D2MODE_PRIORITY_B_CNT);
1156		priority_cnt |= AVIVO_DxMODE_PRIORITY_ALWAYS_ON;
1157		OUTREG(AVIVO_D2MODE_PRIORITY_B_CNT, priority_cnt);
1158	    }
1159	}
1160	return;
1161    }
1162
1163    /* IGP bandwidth - get from integrated systems table
1164     * SYSTEM_MEMORY_BANDWIDTH (Mbyte/s) = SYSTEM_MEMORY_CLOCK (MHz) * (1+DDR) * 8 * EFF * Num of channels
1165     * SIDEPORT_MEMORY_BANDWIDTH = SIDEPORT_MEMORY_CLOCK * 2(byte) * 2(DDR) * 0.7(Eff)
1166     * CORE_CLOCK_BANDWIDTH (Mbyte/s) = SCLK (MHz) * 16 / Dynamic Engine clock Divider
1167     * HT_LINK_BANDWIDTH = HT_LINK_CLOCK * 2 * HT_LINK_WIDTH/8 * HT_LINK_EFF
1168     * system read delay
1169     * READ_DLY_MAX_LATENCY: 5000 ns
1170     * sideport read delay
1171     * READ_DLY_MAX_LATENCY: 370 * MCLK + 800 ns
1172     * MCLK is the sideport memory clock period in ns (MCLK = 1000 / MCLKfreq MHz)
1173     */
1174
1175    if (info->IsIGP) {
1176	float core_clock_bandwidth = ((float)info->pm.mode[info->pm.current_mode].sclk / 100) * 16 / 1;
1177
1178	if (sideport) {
1179	    float sideport_memory_bandwidth = (info->igp_sideport_mclk / 2) * 2 * 2 * 0.7;
1180	    float mclk = 1000 / info->igp_sideport_mclk;
1181	    read_delay_latency = 370 * mclk * 800;
1182	    available_bandwidth = MIN(sideport_memory_bandwidth, core_clock_bandwidth);
1183	} else {
1184	    float system_memory_bandwidth = (info->igp_system_mclk / 2) * (1 + 1) * 8 * 0.5 * 1;
1185	    float ht_link_bandwidth = info->igp_ht_link_clk * 2 * (info->igp_ht_link_width / 8) * 0.8;
1186	    read_delay_latency = 5000;
1187	    available_bandwidth = MIN(system_memory_bandwidth, MIN(ht_link_bandwidth, core_clock_bandwidth));
1188	}
1189    }
1190
1191    /* calculate for each display */
1192    for (i = 0; i < 2; i++) {
1193	DisplayModePtr current = NULL;
1194	//RADEONCrtcPrivatePtr radeon_crtc = pRADEONEnt->Controller[i];
1195	float pclk, sclk, sclkfreq = 0;
1196	float consumption_time, consumption_rate;
1197	int num_line_pair, request_fifo_depth, lb_request_fifo_depth;
1198	int max_req;
1199	uint32_t lb_max_req_outstanding, priority_cnt;
1200	float line_time, active_time, chunk_time;
1201	float worst_case_latency, tolerable_latency;
1202	float fill_rate;
1203	int priority_mark_max, priority_mark, priority_mark2;
1204	int width, estimated_width;
1205	/* FIXME: handle the scalers better */
1206	Bool d1_scale_en = pRADEONEnt->Controller[0]->scaler_enabled;
1207	Bool d2_scale_en = pRADEONEnt->Controller[1]->scaler_enabled;
1208	float vtaps1 = 2; /* XXX */
1209	float vsc1 = pRADEONEnt->Controller[0]->vsc;
1210	float hsc1 = pRADEONEnt->Controller[0]->hsc;
1211	float vtaps2 = 2; /* XXX */
1212	float vsc2 = pRADEONEnt->Controller[1]->vsc;
1213	float hsc2 = pRADEONEnt->Controller[1]->hsc;
1214
1215	if (i == 0)
1216	    current = mode1;
1217	else
1218	    current = mode2;
1219
1220	if (current == NULL)
1221	    continue;
1222
1223	/* Determine consumption rate
1224	   pclk = pixel clock period(ns)
1225	   vtaps = number of vertical taps,
1226	   vsc = vertical scaling ratio, defined as source/destination
1227	   hsc = horizontal scaling ration, defined as source/destination
1228	*/
1229
1230	pclk = 1000 / ((float)current->Clock / 1000);
1231
1232	if (i == 0) {
1233	    if (d1_scale_en)
1234		consumption_time = pclk / ((MAX(vtaps1, vsc1) * hsc1) / vtaps1);
1235	    else
1236		consumption_time = pclk;
1237	} else {
1238	    if (d2_scale_en)
1239		consumption_time = pclk / ((MAX(vtaps2, vsc2) * hsc2) / vtaps2);
1240	    else
1241		consumption_time = pclk;
1242	}
1243
1244	consumption_rate = 1 / consumption_time;
1245
1246	/* Determine request line buffer fifo depth
1247	   NumLinePair = Number of line pairs to request(1 = 2 lines, 2 = 4 lines)
1248	   LBRequestFifoDepth = Number of chunk requests the LB can put into the request FIFO for a display
1249	   width = viewport width in pixels
1250	*/
1251	if (i == 0) {
1252	    if (vsc1 > 2)
1253		num_line_pair = 2;
1254	    else
1255		num_line_pair = 1;
1256	} else {
1257	    if (vsc2 > 2)
1258		num_line_pair = 2;
1259	    else
1260		num_line_pair = 1;
1261	}
1262
1263	width = current->CrtcHDisplay;
1264	request_fifo_depth = ceil(width/256) * num_line_pair;
1265	if (request_fifo_depth < 4)
1266	    lb_request_fifo_depth = 4;
1267	else
1268	    lb_request_fifo_depth = request_fifo_depth;
1269
1270	if (info->IsIGP) {
1271	    if ((info->ChipFamily == CHIP_FAMILY_RS690) ||
1272		(info->ChipFamily == CHIP_FAMILY_RS740))
1273		OUTREG(RS690_DCP_CONTROL, 0);
1274	    else if ((info->ChipFamily == CHIP_FAMILY_RS780) ||
1275		     (info->ChipFamily == CHIP_FAMILY_RS880))
1276		OUTREG(RS690_DCP_CONTROL, 2);
1277	    max_req = lb_request_fifo_depth - 1;
1278	} else
1279	    max_req = lb_request_fifo_depth;
1280
1281	/*ErrorF("max_req %d: 0x%x\n", i, max_req);*/
1282
1283	lb_max_req_outstanding = INREG(AVIVO_LB_MAX_REQ_OUTSTANDING);
1284	if (i == 0) {
1285	    lb_max_req_outstanding &= ~(AVIVO_LB_D1_MAX_REQ_OUTSTANDING_MASK << AVIVO_LB_D1_MAX_REQ_OUTSTANDING_SHIFT);
1286	    lb_max_req_outstanding |= (max_req & AVIVO_LB_D1_MAX_REQ_OUTSTANDING_MASK) << AVIVO_LB_D1_MAX_REQ_OUTSTANDING_SHIFT;
1287	} else {
1288	    lb_max_req_outstanding &= ~(AVIVO_LB_D2_MAX_REQ_OUTSTANDING_MASK << AVIVO_LB_D2_MAX_REQ_OUTSTANDING_SHIFT);
1289	    lb_max_req_outstanding |= (max_req & AVIVO_LB_D2_MAX_REQ_OUTSTANDING_MASK) << AVIVO_LB_D2_MAX_REQ_OUTSTANDING_SHIFT;
1290	}
1291	OUTREG(AVIVO_LB_MAX_REQ_OUTSTANDING, lb_max_req_outstanding);
1292
1293	/* Determine line time
1294	   LineTime = total time for one line of displayhtotal = total number of horizontal pixels
1295	   pclk = pixel clock period(ns)
1296	*/
1297	line_time = current->CrtcHTotal * pclk;
1298
1299	/* Determine active time
1300	   ActiveTime = time of active region of display within one line,
1301	   hactive = total number of horizontal active pixels
1302	   htotal = total number of horizontal pixels
1303	*/
1304	active_time = line_time * current->CrtcHDisplay / current->CrtcHTotal;
1305
1306	/* Determine chunk time
1307	   ChunkTime = the time it takes the DCP to send one chunk of data
1308	   to the LB which consists of pipeline delay and inter chunk gap
1309	   sclk = system clock(ns)
1310	*/
1311	if (info->IsIGP) {
1312	    sclk = 1000 / (available_bandwidth / 16);
1313	    /* Sclkfreq = sclk in MHz = 1000/sclk (because sclk is in ns). */
1314	    sclkfreq = 1000 / sclk;
1315	    chunk_time = sclk * 256 * 1.3;
1316	} else {
1317	    sclk = 1000 / ((float)info->pm.mode[info->pm.current_mode].sclk / 100);
1318	    chunk_time = sclk * 600;
1319	}
1320
1321	/* Determine the worst case latency
1322	   NumLinePair = Number of line pairs to request(1 = 2 lines, 2 = 4 lines)
1323	   WorstCaseLatency = The worst case time from urgent to when the MC starts
1324	   to return data
1325	   READ_DELAY_IDLE_MAX = constant of 1us
1326	   ChunkTime = the time it takes the DCP to send one chunk of data to the LB
1327	   which consists of pipeline delay and
1328	   inter chunk gap
1329	*/
1330	if (info->IsIGP) {
1331	    if (num_line_pair > 1)
1332		worst_case_latency = read_delay_latency + 3 * chunk_time;
1333	    else
1334		worst_case_latency = read_delay_latency + 2 * chunk_time;
1335	} else {
1336	    if (num_line_pair > 1)
1337		worst_case_latency = read_delay_latency + 3 * chunk_time;
1338	    else
1339		worst_case_latency = read_delay_latency + chunk_time;
1340	}
1341
1342	/* Determine the tolerable latency
1343	   TolerableLatency = Any given request has only 1 line time for the data to be returned
1344	   LBRequestFifoDepth = Number of chunk requests the LB can put into the request FIFO for a display
1345	   LineTime = total time for one line of display
1346	   ChunkTime = the time it takes the DCP to send one chunk of data to the LB which consists of
1347	   pipeline delay and inter chunk gap
1348	*/
1349	if ((2 + lb_request_fifo_depth) >= request_fifo_depth)
1350	    tolerable_latency = line_time;
1351	else
1352	    tolerable_latency = line_time - (request_fifo_depth - lb_request_fifo_depth - 2) * chunk_time;
1353
1354	if (mode1 && mode2) {
1355	    int d1bpp, d2bpp;
1356	    int d1_graph_enable = 1;
1357	    int d2_graph_enable = 1;
1358	    int d1_ovl_enable = 0;
1359	    int d2_ovl_enable = 0;
1360	    int d1grph_depth, d2grph_depth;
1361	    int d1ovl_depth = 0;
1362	    int d2ovl_depth = 0;
1363	    int d1_num_line_pair, d2_num_line_pair;
1364	    float d1_fill_rate_coeff, d2_fill_rate_coeff;
1365
1366	    switch (pixel_bytes1) {
1367	    case 2:
1368		d1grph_depth = 1;
1369		break;
1370	    case 4:
1371		d1grph_depth = 2;
1372		break;
1373	    default:
1374		d1grph_depth = 0;
1375		break;
1376	    }
1377
1378	    switch (pixel_bytes2) {
1379	    case 2:
1380		d2grph_depth = 1;
1381		break;
1382	    case 4:
1383		d2grph_depth = 2;
1384		break;
1385	    default:
1386		d2grph_depth = 0;
1387		break;
1388	    }
1389
1390	    /* If both displays are active, determine line buffer fill rate */
1391	    if (d1_scale_en && (vsc1 > 2))
1392		d1_num_line_pair = 2;
1393	    else
1394		d1_num_line_pair = 1;
1395
1396	    if (d2_scale_en && (vsc2 > 2))
1397		d2_num_line_pair = 2;
1398	    else
1399		d2_num_line_pair = 1;
1400
1401	    if (info->IsIGP) {
1402		d1bpp = (d1_graph_enable * pow(2, d1grph_depth) * 8) + (d1_ovl_enable * pow(2, d1ovl_depth) * 8);
1403		d2bpp = (d2_graph_enable * pow(2, d2grph_depth) * 8) + (d2_ovl_enable * pow(2, d2ovl_depth) * 8);
1404
1405		if (d1bpp > 64)
1406		    d1_fill_rate_coeff = d1bpp * d1_num_line_pair;
1407		else
1408		    d1_fill_rate_coeff = d1_num_line_pair;
1409
1410		if (d2bpp > 64)
1411		    d2_fill_rate_coeff = d2bpp * d2_num_line_pair;
1412		else
1413		    d2_fill_rate_coeff = d2_num_line_pair;
1414
1415		fill_rate = sclkfreq / (d1_fill_rate_coeff + d2_fill_rate_coeff);
1416	    } else {
1417		d1bpp = (d1grph_depth + d1ovl_depth) * 16;
1418		d2bpp = (d2grph_depth + d2ovl_depth) * 16;
1419
1420		if (d1bpp > 64)
1421		    d1_fill_rate_coeff = d1bpp / d1_num_line_pair;
1422		else
1423		    d1_fill_rate_coeff = d1_num_line_pair;
1424
1425		if (d2bpp > 64)
1426		    d2_fill_rate_coeff = d2bpp / d2_num_line_pair;
1427		else
1428		    d2_fill_rate_coeff = d2_num_line_pair;
1429
1430		fill_rate = sclk / (d1_fill_rate_coeff + d2_fill_rate_coeff);
1431
1432		/* Convert line buffer fill rate from period to frequency */
1433		fill_rate = 1 / fill_rate;
1434	    }
1435	} else {
1436	    int dxbpp;
1437	    int dx_grph_enable = 1;
1438	    int dx_ovl_enable = 0;
1439	    int dxgrph_depth;
1440	    int dxovl_depth = 0;
1441	    int cpp;
1442
1443	    if (i == 0)
1444		cpp = pixel_bytes1;
1445	    else
1446		cpp = pixel_bytes2;
1447
1448	    switch (cpp) {
1449	    case 2:
1450		dxgrph_depth = 1;
1451		break;
1452	    case 4:
1453		dxgrph_depth = 2;
1454		break;
1455	    default:
1456		dxgrph_depth = 0;
1457		break;
1458	    }
1459
1460	    /* If only one display active, the line buffer fill rate becomes */
1461	    if (info->IsIGP) {
1462		dxbpp = (dx_grph_enable * pow(2, dxgrph_depth) * 8) + (dx_ovl_enable * pow(2, dxovl_depth) * 8);
1463		if (dxbpp > 64)
1464		    fill_rate = sclkfreq / dxbpp / num_line_pair;
1465		else
1466		    fill_rate = sclkfreq / num_line_pair;
1467	    } else {
1468		dxbpp = (dxgrph_depth + dxovl_depth) * 16;
1469
1470		if (dxbpp > 64)
1471		    fill_rate = sclk / dxbpp / num_line_pair;
1472		else
1473		    fill_rate = sclk / num_line_pair;
1474
1475		/* Convert line buffer fill rate from period to frequency */
1476		fill_rate = 1 / fill_rate;
1477	    }
1478	}
1479
1480	/* Determine the maximum priority mark
1481	   width = viewport width in pixels
1482	*/
1483	priority_mark_max = ceil(width/16);
1484
1485	/* Determine estimated width */
1486	estimated_width = (tolerable_latency - worst_case_latency) / consumption_time;
1487
1488	/* Determine priority mark based on active time */
1489	if (info->IsIGP) {
1490	    if (estimated_width > width)
1491		priority_mark = 10;
1492	    else
1493		priority_mark = priority_mark_max - ceil(estimated_width / 16);
1494	} else {
1495	    if (estimated_width > width)
1496		priority_mark = priority_mark_max;
1497	    else
1498		priority_mark = priority_mark_max - ceil(estimated_width / 16);
1499	}
1500
1501	/* Determine priority mark 2 based on worst case latency,
1502	   consumption rate, fill rate and active time
1503	*/
1504	if (info->IsIGP) {
1505	    if (consumption_rate > fill_rate)
1506		priority_mark2 = ceil((worst_case_latency * consumption_rate + (consumption_rate - fill_rate) * active_time) / 1000 / 16);
1507	    else
1508		priority_mark2 = ceil(worst_case_latency * consumption_rate / 1000 / 16);
1509	} else {
1510	    if (consumption_rate > fill_rate)
1511		priority_mark2 = ceil(worst_case_latency * consumption_rate + (consumption_rate - fill_rate) * active_time / 16);
1512	    else
1513		priority_mark2 = ceil(worst_case_latency * consumption_rate / 16);
1514	}
1515
1516	/* Determine final priority mark and clamp if necessary */
1517	priority_mark = max(priority_mark, priority_mark2);
1518	if (priority_mark < 0)
1519	    priority_mark = 0;
1520	else if (priority_mark > priority_mark_max)
1521	    priority_mark = priority_mark_max;
1522
1523	priority_cnt = priority_mark & AVIVO_DxMODE_PRIORITY_MARK_MASK;
1524
1525	if (info->DispPriority == 2)
1526	    priority_cnt |= AVIVO_DxMODE_PRIORITY_ALWAYS_ON;
1527
1528	/*ErrorF("priority_mark %d: 0x%x\n", i, priority_mark);*/
1529
1530	/* Determine which display to program priority mark for */
1531	/* FIXME: program DxMODE_PRIORITY_B_CNT for slower sclk */
1532	if (i == 0) {
1533	    OUTREG(AVIVO_D1MODE_PRIORITY_A_CNT, priority_cnt);
1534	    OUTREG(AVIVO_D1MODE_PRIORITY_B_CNT, priority_cnt);
1535	} else {
1536	    OUTREG(AVIVO_D2MODE_PRIORITY_A_CNT, priority_cnt);
1537	    OUTREG(AVIVO_D2MODE_PRIORITY_B_CNT, priority_cnt);
1538	}
1539    }
1540
1541}
1542