xref: /linux/drivers/gpu/drm/radeon/rs690.c (revision 6000fc4d6f3e55ad52cce8d76317187fe01af2aa)
1 /*
2  * Copyright 2008 Advanced Micro Devices, Inc.
3  * Copyright 2008 Red Hat Inc.
4  * Copyright 2009 Jerome Glisse.
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a
7  * copy of this software and associated documentation files (the "Software"),
8  * to deal in the Software without restriction, including without limitation
9  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10  * and/or sell copies of the Software, and to permit persons to whom the
11  * Software is furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
20  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22  * OTHER DEALINGS IN THE SOFTWARE.
23  *
24  * Authors: Dave Airlie
25  *          Alex Deucher
26  *          Jerome Glisse
27  */
28 #include "drmP.h"
29 #include "radeon_reg.h"
30 #include "radeon.h"
31 #include "rs690r.h"
32 #include "atom.h"
33 #include "atom-bits.h"
34 
35 /* rs690,rs740 depends on : */
36 void r100_hdp_reset(struct radeon_device *rdev);
37 int r300_mc_wait_for_idle(struct radeon_device *rdev);
38 void r420_pipes_init(struct radeon_device *rdev);
39 void rs400_gart_disable(struct radeon_device *rdev);
40 int rs400_gart_enable(struct radeon_device *rdev);
41 void rs400_gart_adjust_size(struct radeon_device *rdev);
42 void rs600_mc_disable_clients(struct radeon_device *rdev);
43 void rs600_disable_vga(struct radeon_device *rdev);
44 
45 /* This files gather functions specifics to :
46  * rs690,rs740
47  *
48  * Some of these functions might be used by newer ASICs.
49  */
50 void rs690_gpu_init(struct radeon_device *rdev);
51 int rs690_mc_wait_for_idle(struct radeon_device *rdev);
52 
53 
54 /*
55  * MC functions.
56  */
57 int rs690_mc_init(struct radeon_device *rdev)
58 {
59 	uint32_t tmp;
60 	int r;
61 
62 	if (r100_debugfs_rbbm_init(rdev)) {
63 		DRM_ERROR("Failed to register debugfs file for RBBM !\n");
64 	}
65 
66 	rs690_gpu_init(rdev);
67 	rs400_gart_disable(rdev);
68 
69 	/* Setup GPU memory space */
70 	rdev->mc.gtt_location = rdev->mc.mc_vram_size;
71 	rdev->mc.gtt_location += (rdev->mc.gtt_size - 1);
72 	rdev->mc.gtt_location &= ~(rdev->mc.gtt_size - 1);
73 	rdev->mc.vram_location = 0xFFFFFFFFUL;
74 	r = radeon_mc_setup(rdev);
75 	if (r) {
76 		return r;
77 	}
78 
79 	/* Program GPU memory space */
80 	rs600_mc_disable_clients(rdev);
81 	if (rs690_mc_wait_for_idle(rdev)) {
82 		printk(KERN_WARNING "Failed to wait MC idle while "
83 		       "programming pipes. Bad things might happen.\n");
84 	}
85 	tmp = rdev->mc.vram_location + rdev->mc.mc_vram_size - 1;
86 	tmp = REG_SET(RS690_MC_FB_TOP, tmp >> 16);
87 	tmp |= REG_SET(RS690_MC_FB_START, rdev->mc.vram_location >> 16);
88 	WREG32_MC(RS690_MCCFG_FB_LOCATION, tmp);
89 	/* FIXME: Does this reg exist on RS480,RS740 ? */
90 	WREG32(0x310, rdev->mc.vram_location);
91 	WREG32(RS690_HDP_FB_LOCATION, rdev->mc.vram_location >> 16);
92 	return 0;
93 }
94 
95 void rs690_mc_fini(struct radeon_device *rdev)
96 {
97 	rs400_gart_disable(rdev);
98 	radeon_gart_table_ram_free(rdev);
99 	radeon_gart_fini(rdev);
100 }
101 
102 
103 /*
104  * Global GPU functions
105  */
106 int rs690_mc_wait_for_idle(struct radeon_device *rdev)
107 {
108 	unsigned i;
109 	uint32_t tmp;
110 
111 	for (i = 0; i < rdev->usec_timeout; i++) {
112 		/* read MC_STATUS */
113 		tmp = RREG32_MC(RS690_MC_STATUS);
114 		if (tmp & RS690_MC_STATUS_IDLE) {
115 			return 0;
116 		}
117 		DRM_UDELAY(1);
118 	}
119 	return -1;
120 }
121 
122 void rs690_errata(struct radeon_device *rdev)
123 {
124 	rdev->pll_errata = 0;
125 }
126 
127 void rs690_gpu_init(struct radeon_device *rdev)
128 {
129 	/* FIXME: HDP same place on rs690 ? */
130 	r100_hdp_reset(rdev);
131 	rs600_disable_vga(rdev);
132 	/* FIXME: is this correct ? */
133 	r420_pipes_init(rdev);
134 	if (rs690_mc_wait_for_idle(rdev)) {
135 		printk(KERN_WARNING "Failed to wait MC idle while "
136 		       "programming pipes. Bad things might happen.\n");
137 	}
138 }
139 
140 
141 /*
142  * VRAM info.
143  */
144 void rs690_pm_info(struct radeon_device *rdev)
145 {
146 	int index = GetIndexIntoMasterTable(DATA, IntegratedSystemInfo);
147 	struct _ATOM_INTEGRATED_SYSTEM_INFO *info;
148 	struct _ATOM_INTEGRATED_SYSTEM_INFO_V2 *info_v2;
149 	void *ptr;
150 	uint16_t data_offset;
151 	uint8_t frev, crev;
152 	fixed20_12 tmp;
153 
154 	atom_parse_data_header(rdev->mode_info.atom_context, index, NULL,
155 			       &frev, &crev, &data_offset);
156 	ptr = rdev->mode_info.atom_context->bios + data_offset;
157 	info = (struct _ATOM_INTEGRATED_SYSTEM_INFO *)ptr;
158 	info_v2 = (struct _ATOM_INTEGRATED_SYSTEM_INFO_V2 *)ptr;
159 	/* Get various system informations from bios */
160 	switch (crev) {
161 	case 1:
162 		tmp.full = rfixed_const(100);
163 		rdev->pm.igp_sideport_mclk.full = rfixed_const(info->ulBootUpMemoryClock);
164 		rdev->pm.igp_sideport_mclk.full = rfixed_div(rdev->pm.igp_sideport_mclk, tmp);
165 		rdev->pm.igp_system_mclk.full = rfixed_const(le16_to_cpu(info->usK8MemoryClock));
166 		rdev->pm.igp_ht_link_clk.full = rfixed_const(le16_to_cpu(info->usFSBClock));
167 		rdev->pm.igp_ht_link_width.full = rfixed_const(info->ucHTLinkWidth);
168 		break;
169 	case 2:
170 		tmp.full = rfixed_const(100);
171 		rdev->pm.igp_sideport_mclk.full = rfixed_const(info_v2->ulBootUpSidePortClock);
172 		rdev->pm.igp_sideport_mclk.full = rfixed_div(rdev->pm.igp_sideport_mclk, tmp);
173 		rdev->pm.igp_system_mclk.full = rfixed_const(info_v2->ulBootUpUMAClock);
174 		rdev->pm.igp_system_mclk.full = rfixed_div(rdev->pm.igp_system_mclk, tmp);
175 		rdev->pm.igp_ht_link_clk.full = rfixed_const(info_v2->ulHTLinkFreq);
176 		rdev->pm.igp_ht_link_clk.full = rfixed_div(rdev->pm.igp_ht_link_clk, tmp);
177 		rdev->pm.igp_ht_link_width.full = rfixed_const(le16_to_cpu(info_v2->usMinHTLinkWidth));
178 		break;
179 	default:
180 		tmp.full = rfixed_const(100);
181 		/* We assume the slower possible clock ie worst case */
182 		/* DDR 333Mhz */
183 		rdev->pm.igp_sideport_mclk.full = rfixed_const(333);
184 		/* FIXME: system clock ? */
185 		rdev->pm.igp_system_mclk.full = rfixed_const(100);
186 		rdev->pm.igp_system_mclk.full = rfixed_div(rdev->pm.igp_system_mclk, tmp);
187 		rdev->pm.igp_ht_link_clk.full = rfixed_const(200);
188 		rdev->pm.igp_ht_link_width.full = rfixed_const(8);
189 		DRM_ERROR("No integrated system info for your GPU, using safe default\n");
190 		break;
191 	}
192 	/* Compute various bandwidth */
193 	/* k8_bandwidth = (memory_clk / 2) * 2 * 8 * 0.5 = memory_clk * 4  */
194 	tmp.full = rfixed_const(4);
195 	rdev->pm.k8_bandwidth.full = rfixed_mul(rdev->pm.igp_system_mclk, tmp);
196 	/* ht_bandwidth = ht_clk * 2 * ht_width / 8 * 0.8
197 	 *              = ht_clk * ht_width / 5
198 	 */
199 	tmp.full = rfixed_const(5);
200 	rdev->pm.ht_bandwidth.full = rfixed_mul(rdev->pm.igp_ht_link_clk,
201 						rdev->pm.igp_ht_link_width);
202 	rdev->pm.ht_bandwidth.full = rfixed_div(rdev->pm.ht_bandwidth, tmp);
203 	if (tmp.full < rdev->pm.max_bandwidth.full) {
204 		/* HT link is a limiting factor */
205 		rdev->pm.max_bandwidth.full = tmp.full;
206 	}
207 	/* sideport_bandwidth = (sideport_clk / 2) * 2 * 2 * 0.7
208 	 *                    = (sideport_clk * 14) / 10
209 	 */
210 	tmp.full = rfixed_const(14);
211 	rdev->pm.sideport_bandwidth.full = rfixed_mul(rdev->pm.igp_sideport_mclk, tmp);
212 	tmp.full = rfixed_const(10);
213 	rdev->pm.sideport_bandwidth.full = rfixed_div(rdev->pm.sideport_bandwidth, tmp);
214 }
215 
216 void rs690_vram_info(struct radeon_device *rdev)
217 {
218 	uint32_t tmp;
219 	fixed20_12 a;
220 
221 	rs400_gart_adjust_size(rdev);
222 	/* DDR for all card after R300 & IGP */
223 	rdev->mc.vram_is_ddr = true;
224 	/* FIXME: is this correct for RS690/RS740 ? */
225 	tmp = RREG32(RADEON_MEM_CNTL);
226 	if (tmp & R300_MEM_NUM_CHANNELS_MASK) {
227 		rdev->mc.vram_width = 128;
228 	} else {
229 		rdev->mc.vram_width = 64;
230 	}
231 	rdev->mc.real_vram_size = RREG32(RADEON_CONFIG_MEMSIZE);
232 	rdev->mc.mc_vram_size = rdev->mc.real_vram_size;
233 
234 	rdev->mc.aper_base = drm_get_resource_start(rdev->ddev, 0);
235 	rdev->mc.aper_size = drm_get_resource_len(rdev->ddev, 0);
236 	rs690_pm_info(rdev);
237 	/* FIXME: we should enforce default clock in case GPU is not in
238 	 * default setup
239 	 */
240 	a.full = rfixed_const(100);
241 	rdev->pm.sclk.full = rfixed_const(rdev->clock.default_sclk);
242 	rdev->pm.sclk.full = rfixed_div(rdev->pm.sclk, a);
243 	a.full = rfixed_const(16);
244 	/* core_bandwidth = sclk(Mhz) * 16 */
245 	rdev->pm.core_bandwidth.full = rfixed_div(rdev->pm.sclk, a);
246 }
247 
248 void rs690_line_buffer_adjust(struct radeon_device *rdev,
249 			      struct drm_display_mode *mode1,
250 			      struct drm_display_mode *mode2)
251 {
252 	u32 tmp;
253 
254 	/*
255 	 * Line Buffer Setup
256 	 * There is a single line buffer shared by both display controllers.
257 	 * DC_LB_MEMORY_SPLIT controls how that line buffer is shared between
258 	 * the display controllers.  The paritioning can either be done
259 	 * manually or via one of four preset allocations specified in bits 1:0:
260 	 *  0 - line buffer is divided in half and shared between crtc
261 	 *  1 - D1 gets 3/4 of the line buffer, D2 gets 1/4
262 	 *  2 - D1 gets the whole buffer
263 	 *  3 - D1 gets 1/4 of the line buffer, D2 gets 3/4
264 	 * Setting bit 2 of DC_LB_MEMORY_SPLIT controls switches to manual
265 	 * allocation mode. In manual allocation mode, D1 always starts at 0,
266 	 * D1 end/2 is specified in bits 14:4; D2 allocation follows D1.
267 	 */
268 	tmp = RREG32(DC_LB_MEMORY_SPLIT) & ~DC_LB_MEMORY_SPLIT_MASK;
269 	tmp &= ~DC_LB_MEMORY_SPLIT_SHIFT_MODE;
270 	/* auto */
271 	if (mode1 && mode2) {
272 		if (mode1->hdisplay > mode2->hdisplay) {
273 			if (mode1->hdisplay > 2560)
274 				tmp |= DC_LB_MEMORY_SPLIT_D1_3Q_D2_1Q;
275 			else
276 				tmp |= DC_LB_MEMORY_SPLIT_D1HALF_D2HALF;
277 		} else if (mode2->hdisplay > mode1->hdisplay) {
278 			if (mode2->hdisplay > 2560)
279 				tmp |= DC_LB_MEMORY_SPLIT_D1_1Q_D2_3Q;
280 			else
281 				tmp |= DC_LB_MEMORY_SPLIT_D1HALF_D2HALF;
282 		} else
283 			tmp |= AVIVO_DC_LB_MEMORY_SPLIT_D1HALF_D2HALF;
284 	} else if (mode1) {
285 		tmp |= DC_LB_MEMORY_SPLIT_D1_ONLY;
286 	} else if (mode2) {
287 		tmp |= DC_LB_MEMORY_SPLIT_D1_1Q_D2_3Q;
288 	}
289 	WREG32(DC_LB_MEMORY_SPLIT, tmp);
290 }
291 
292 struct rs690_watermark {
293 	u32        lb_request_fifo_depth;
294 	fixed20_12 num_line_pair;
295 	fixed20_12 estimated_width;
296 	fixed20_12 worst_case_latency;
297 	fixed20_12 consumption_rate;
298 	fixed20_12 active_time;
299 	fixed20_12 dbpp;
300 	fixed20_12 priority_mark_max;
301 	fixed20_12 priority_mark;
302 	fixed20_12 sclk;
303 };
304 
305 void rs690_crtc_bandwidth_compute(struct radeon_device *rdev,
306 				  struct radeon_crtc *crtc,
307 				  struct rs690_watermark *wm)
308 {
309 	struct drm_display_mode *mode = &crtc->base.mode;
310 	fixed20_12 a, b, c;
311 	fixed20_12 pclk, request_fifo_depth, tolerable_latency, estimated_width;
312 	fixed20_12 consumption_time, line_time, chunk_time, read_delay_latency;
313 	/* FIXME: detect IGP with sideport memory, i don't think there is any
314 	 * such product available
315 	 */
316 	bool sideport = false;
317 
318 	if (!crtc->base.enabled) {
319 		/* FIXME: wouldn't it better to set priority mark to maximum */
320 		wm->lb_request_fifo_depth = 4;
321 		return;
322 	}
323 
324 	if (crtc->vsc.full > rfixed_const(2))
325 		wm->num_line_pair.full = rfixed_const(2);
326 	else
327 		wm->num_line_pair.full = rfixed_const(1);
328 
329 	b.full = rfixed_const(mode->crtc_hdisplay);
330 	c.full = rfixed_const(256);
331 	a.full = rfixed_mul(wm->num_line_pair, b);
332 	request_fifo_depth.full = rfixed_div(a, c);
333 	if (a.full < rfixed_const(4)) {
334 		wm->lb_request_fifo_depth = 4;
335 	} else {
336 		wm->lb_request_fifo_depth = rfixed_trunc(request_fifo_depth);
337 	}
338 
339 	/* Determine consumption rate
340 	 *  pclk = pixel clock period(ns) = 1000 / (mode.clock / 1000)
341 	 *  vtaps = number of vertical taps,
342 	 *  vsc = vertical scaling ratio, defined as source/destination
343 	 *  hsc = horizontal scaling ration, defined as source/destination
344 	 */
345 	a.full = rfixed_const(mode->clock);
346 	b.full = rfixed_const(1000);
347 	a.full = rfixed_div(a, b);
348 	pclk.full = rfixed_div(b, a);
349 	if (crtc->rmx_type != RMX_OFF) {
350 		b.full = rfixed_const(2);
351 		if (crtc->vsc.full > b.full)
352 			b.full = crtc->vsc.full;
353 		b.full = rfixed_mul(b, crtc->hsc);
354 		c.full = rfixed_const(2);
355 		b.full = rfixed_div(b, c);
356 		consumption_time.full = rfixed_div(pclk, b);
357 	} else {
358 		consumption_time.full = pclk.full;
359 	}
360 	a.full = rfixed_const(1);
361 	wm->consumption_rate.full = rfixed_div(a, consumption_time);
362 
363 
364 	/* Determine line time
365 	 *  LineTime = total time for one line of displayhtotal
366 	 *  LineTime = total number of horizontal pixels
367 	 *  pclk = pixel clock period(ns)
368 	 */
369 	a.full = rfixed_const(crtc->base.mode.crtc_htotal);
370 	line_time.full = rfixed_mul(a, pclk);
371 
372 	/* Determine active time
373 	 *  ActiveTime = time of active region of display within one line,
374 	 *  hactive = total number of horizontal active pixels
375 	 *  htotal = total number of horizontal pixels
376 	 */
377 	a.full = rfixed_const(crtc->base.mode.crtc_htotal);
378 	b.full = rfixed_const(crtc->base.mode.crtc_hdisplay);
379 	wm->active_time.full = rfixed_mul(line_time, b);
380 	wm->active_time.full = rfixed_div(wm->active_time, a);
381 
382 	/* Maximun bandwidth is the minimun bandwidth of all component */
383 	rdev->pm.max_bandwidth = rdev->pm.core_bandwidth;
384 	if (sideport) {
385 		if (rdev->pm.max_bandwidth.full > rdev->pm.sideport_bandwidth.full &&
386 			rdev->pm.sideport_bandwidth.full)
387 			rdev->pm.max_bandwidth = rdev->pm.sideport_bandwidth;
388 		read_delay_latency.full = rfixed_const(370 * 800 * 1000);
389 		read_delay_latency.full = rfixed_div(read_delay_latency,
390 			rdev->pm.igp_sideport_mclk);
391 	} else {
392 		if (rdev->pm.max_bandwidth.full > rdev->pm.k8_bandwidth.full &&
393 			rdev->pm.k8_bandwidth.full)
394 			rdev->pm.max_bandwidth = rdev->pm.k8_bandwidth;
395 		if (rdev->pm.max_bandwidth.full > rdev->pm.ht_bandwidth.full &&
396 			rdev->pm.ht_bandwidth.full)
397 			rdev->pm.max_bandwidth = rdev->pm.ht_bandwidth;
398 		read_delay_latency.full = rfixed_const(5000);
399 	}
400 
401 	/* sclk = system clocks(ns) = 1000 / max_bandwidth / 16 */
402 	a.full = rfixed_const(16);
403 	rdev->pm.sclk.full = rfixed_mul(rdev->pm.max_bandwidth, a);
404 	a.full = rfixed_const(1000);
405 	rdev->pm.sclk.full = rfixed_div(a, rdev->pm.sclk);
406 	/* Determine chunk time
407 	 * ChunkTime = the time it takes the DCP to send one chunk of data
408 	 * to the LB which consists of pipeline delay and inter chunk gap
409 	 * sclk = system clock(ns)
410 	 */
411 	a.full = rfixed_const(256 * 13);
412 	chunk_time.full = rfixed_mul(rdev->pm.sclk, a);
413 	a.full = rfixed_const(10);
414 	chunk_time.full = rfixed_div(chunk_time, a);
415 
416 	/* Determine the worst case latency
417 	 * NumLinePair = Number of line pairs to request(1=2 lines, 2=4 lines)
418 	 * WorstCaseLatency = worst case time from urgent to when the MC starts
419 	 *                    to return data
420 	 * READ_DELAY_IDLE_MAX = constant of 1us
421 	 * ChunkTime = time it takes the DCP to send one chunk of data to the LB
422 	 *             which consists of pipeline delay and inter chunk gap
423 	 */
424 	if (rfixed_trunc(wm->num_line_pair) > 1) {
425 		a.full = rfixed_const(3);
426 		wm->worst_case_latency.full = rfixed_mul(a, chunk_time);
427 		wm->worst_case_latency.full += read_delay_latency.full;
428 	} else {
429 		a.full = rfixed_const(2);
430 		wm->worst_case_latency.full = rfixed_mul(a, chunk_time);
431 		wm->worst_case_latency.full += read_delay_latency.full;
432 	}
433 
434 	/* Determine the tolerable latency
435 	 * TolerableLatency = Any given request has only 1 line time
436 	 *                    for the data to be returned
437 	 * LBRequestFifoDepth = Number of chunk requests the LB can
438 	 *                      put into the request FIFO for a display
439 	 *  LineTime = total time for one line of display
440 	 *  ChunkTime = the time it takes the DCP to send one chunk
441 	 *              of data to the LB which consists of
442 	 *  pipeline delay and inter chunk gap
443 	 */
444 	if ((2+wm->lb_request_fifo_depth) >= rfixed_trunc(request_fifo_depth)) {
445 		tolerable_latency.full = line_time.full;
446 	} else {
447 		tolerable_latency.full = rfixed_const(wm->lb_request_fifo_depth - 2);
448 		tolerable_latency.full = request_fifo_depth.full - tolerable_latency.full;
449 		tolerable_latency.full = rfixed_mul(tolerable_latency, chunk_time);
450 		tolerable_latency.full = line_time.full - tolerable_latency.full;
451 	}
452 	/* We assume worst case 32bits (4 bytes) */
453 	wm->dbpp.full = rfixed_const(4 * 8);
454 
455 	/* Determine the maximum priority mark
456 	 *  width = viewport width in pixels
457 	 */
458 	a.full = rfixed_const(16);
459 	wm->priority_mark_max.full = rfixed_const(crtc->base.mode.crtc_hdisplay);
460 	wm->priority_mark_max.full = rfixed_div(wm->priority_mark_max, a);
461 
462 	/* Determine estimated width */
463 	estimated_width.full = tolerable_latency.full - wm->worst_case_latency.full;
464 	estimated_width.full = rfixed_div(estimated_width, consumption_time);
465 	if (rfixed_trunc(estimated_width) > crtc->base.mode.crtc_hdisplay) {
466 		wm->priority_mark.full = rfixed_const(10);
467 	} else {
468 		a.full = rfixed_const(16);
469 		wm->priority_mark.full = rfixed_div(estimated_width, a);
470 		wm->priority_mark.full = wm->priority_mark_max.full - wm->priority_mark.full;
471 	}
472 }
473 
474 void rs690_bandwidth_update(struct radeon_device *rdev)
475 {
476 	struct drm_display_mode *mode0 = NULL;
477 	struct drm_display_mode *mode1 = NULL;
478 	struct rs690_watermark wm0;
479 	struct rs690_watermark wm1;
480 	u32 tmp;
481 	fixed20_12 priority_mark02, priority_mark12, fill_rate;
482 	fixed20_12 a, b;
483 
484 	if (rdev->mode_info.crtcs[0]->base.enabled)
485 		mode0 = &rdev->mode_info.crtcs[0]->base.mode;
486 	if (rdev->mode_info.crtcs[1]->base.enabled)
487 		mode1 = &rdev->mode_info.crtcs[1]->base.mode;
488 	/*
489 	 * Set display0/1 priority up in the memory controller for
490 	 * modes if the user specifies HIGH for displaypriority
491 	 * option.
492 	 */
493 	if (rdev->disp_priority == 2) {
494 		tmp = RREG32_MC(MC_INIT_MISC_LAT_TIMER);
495 		tmp &= ~MC_DISP1R_INIT_LAT_MASK;
496 		tmp &= ~MC_DISP0R_INIT_LAT_MASK;
497 		if (mode1)
498 			tmp |= (1 << MC_DISP1R_INIT_LAT_SHIFT);
499 		if (mode0)
500 			tmp |= (1 << MC_DISP0R_INIT_LAT_SHIFT);
501 		WREG32_MC(MC_INIT_MISC_LAT_TIMER, tmp);
502 	}
503 	rs690_line_buffer_adjust(rdev, mode0, mode1);
504 
505 	if ((rdev->family == CHIP_RS690) || (rdev->family == CHIP_RS740))
506 		WREG32(DCP_CONTROL, 0);
507 	if ((rdev->family == CHIP_RS780) || (rdev->family == CHIP_RS880))
508 		WREG32(DCP_CONTROL, 2);
509 
510 	rs690_crtc_bandwidth_compute(rdev, rdev->mode_info.crtcs[0], &wm0);
511 	rs690_crtc_bandwidth_compute(rdev, rdev->mode_info.crtcs[1], &wm1);
512 
513 	tmp = (wm0.lb_request_fifo_depth - 1);
514 	tmp |= (wm1.lb_request_fifo_depth - 1) << 16;
515 	WREG32(LB_MAX_REQ_OUTSTANDING, tmp);
516 
517 	if (mode0 && mode1) {
518 		if (rfixed_trunc(wm0.dbpp) > 64)
519 			a.full = rfixed_mul(wm0.dbpp, wm0.num_line_pair);
520 		else
521 			a.full = wm0.num_line_pair.full;
522 		if (rfixed_trunc(wm1.dbpp) > 64)
523 			b.full = rfixed_mul(wm1.dbpp, wm1.num_line_pair);
524 		else
525 			b.full = wm1.num_line_pair.full;
526 		a.full += b.full;
527 		fill_rate.full = rfixed_div(wm0.sclk, a);
528 		if (wm0.consumption_rate.full > fill_rate.full) {
529 			b.full = wm0.consumption_rate.full - fill_rate.full;
530 			b.full = rfixed_mul(b, wm0.active_time);
531 			a.full = rfixed_mul(wm0.worst_case_latency,
532 						wm0.consumption_rate);
533 			a.full = a.full + b.full;
534 			b.full = rfixed_const(16 * 1000);
535 			priority_mark02.full = rfixed_div(a, b);
536 		} else {
537 			a.full = rfixed_mul(wm0.worst_case_latency,
538 						wm0.consumption_rate);
539 			b.full = rfixed_const(16 * 1000);
540 			priority_mark02.full = rfixed_div(a, b);
541 		}
542 		if (wm1.consumption_rate.full > fill_rate.full) {
543 			b.full = wm1.consumption_rate.full - fill_rate.full;
544 			b.full = rfixed_mul(b, wm1.active_time);
545 			a.full = rfixed_mul(wm1.worst_case_latency,
546 						wm1.consumption_rate);
547 			a.full = a.full + b.full;
548 			b.full = rfixed_const(16 * 1000);
549 			priority_mark12.full = rfixed_div(a, b);
550 		} else {
551 			a.full = rfixed_mul(wm1.worst_case_latency,
552 						wm1.consumption_rate);
553 			b.full = rfixed_const(16 * 1000);
554 			priority_mark12.full = rfixed_div(a, b);
555 		}
556 		if (wm0.priority_mark.full > priority_mark02.full)
557 			priority_mark02.full = wm0.priority_mark.full;
558 		if (rfixed_trunc(priority_mark02) < 0)
559 			priority_mark02.full = 0;
560 		if (wm0.priority_mark_max.full > priority_mark02.full)
561 			priority_mark02.full = wm0.priority_mark_max.full;
562 		if (wm1.priority_mark.full > priority_mark12.full)
563 			priority_mark12.full = wm1.priority_mark.full;
564 		if (rfixed_trunc(priority_mark12) < 0)
565 			priority_mark12.full = 0;
566 		if (wm1.priority_mark_max.full > priority_mark12.full)
567 			priority_mark12.full = wm1.priority_mark_max.full;
568 		WREG32(D1MODE_PRIORITY_A_CNT, rfixed_trunc(priority_mark02));
569 		WREG32(D1MODE_PRIORITY_B_CNT, rfixed_trunc(priority_mark02));
570 		WREG32(D2MODE_PRIORITY_A_CNT, rfixed_trunc(priority_mark12));
571 		WREG32(D2MODE_PRIORITY_B_CNT, rfixed_trunc(priority_mark12));
572 	} else if (mode0) {
573 		if (rfixed_trunc(wm0.dbpp) > 64)
574 			a.full = rfixed_mul(wm0.dbpp, wm0.num_line_pair);
575 		else
576 			a.full = wm0.num_line_pair.full;
577 		fill_rate.full = rfixed_div(wm0.sclk, a);
578 		if (wm0.consumption_rate.full > fill_rate.full) {
579 			b.full = wm0.consumption_rate.full - fill_rate.full;
580 			b.full = rfixed_mul(b, wm0.active_time);
581 			a.full = rfixed_mul(wm0.worst_case_latency,
582 						wm0.consumption_rate);
583 			a.full = a.full + b.full;
584 			b.full = rfixed_const(16 * 1000);
585 			priority_mark02.full = rfixed_div(a, b);
586 		} else {
587 			a.full = rfixed_mul(wm0.worst_case_latency,
588 						wm0.consumption_rate);
589 			b.full = rfixed_const(16 * 1000);
590 			priority_mark02.full = rfixed_div(a, b);
591 		}
592 		if (wm0.priority_mark.full > priority_mark02.full)
593 			priority_mark02.full = wm0.priority_mark.full;
594 		if (rfixed_trunc(priority_mark02) < 0)
595 			priority_mark02.full = 0;
596 		if (wm0.priority_mark_max.full > priority_mark02.full)
597 			priority_mark02.full = wm0.priority_mark_max.full;
598 		WREG32(D1MODE_PRIORITY_A_CNT, rfixed_trunc(priority_mark02));
599 		WREG32(D1MODE_PRIORITY_B_CNT, rfixed_trunc(priority_mark02));
600 		WREG32(D2MODE_PRIORITY_A_CNT, MODE_PRIORITY_OFF);
601 		WREG32(D2MODE_PRIORITY_B_CNT, MODE_PRIORITY_OFF);
602 	} else {
603 		if (rfixed_trunc(wm1.dbpp) > 64)
604 			a.full = rfixed_mul(wm1.dbpp, wm1.num_line_pair);
605 		else
606 			a.full = wm1.num_line_pair.full;
607 		fill_rate.full = rfixed_div(wm1.sclk, a);
608 		if (wm1.consumption_rate.full > fill_rate.full) {
609 			b.full = wm1.consumption_rate.full - fill_rate.full;
610 			b.full = rfixed_mul(b, wm1.active_time);
611 			a.full = rfixed_mul(wm1.worst_case_latency,
612 						wm1.consumption_rate);
613 			a.full = a.full + b.full;
614 			b.full = rfixed_const(16 * 1000);
615 			priority_mark12.full = rfixed_div(a, b);
616 		} else {
617 			a.full = rfixed_mul(wm1.worst_case_latency,
618 						wm1.consumption_rate);
619 			b.full = rfixed_const(16 * 1000);
620 			priority_mark12.full = rfixed_div(a, b);
621 		}
622 		if (wm1.priority_mark.full > priority_mark12.full)
623 			priority_mark12.full = wm1.priority_mark.full;
624 		if (rfixed_trunc(priority_mark12) < 0)
625 			priority_mark12.full = 0;
626 		if (wm1.priority_mark_max.full > priority_mark12.full)
627 			priority_mark12.full = wm1.priority_mark_max.full;
628 		WREG32(D1MODE_PRIORITY_A_CNT, MODE_PRIORITY_OFF);
629 		WREG32(D1MODE_PRIORITY_B_CNT, MODE_PRIORITY_OFF);
630 		WREG32(D2MODE_PRIORITY_A_CNT, rfixed_trunc(priority_mark12));
631 		WREG32(D2MODE_PRIORITY_B_CNT, rfixed_trunc(priority_mark12));
632 	}
633 }
634 
635 /*
636  * Indirect registers accessor
637  */
638 uint32_t rs690_mc_rreg(struct radeon_device *rdev, uint32_t reg)
639 {
640 	uint32_t r;
641 
642 	WREG32(RS690_MC_INDEX, (reg & RS690_MC_INDEX_MASK));
643 	r = RREG32(RS690_MC_DATA);
644 	WREG32(RS690_MC_INDEX, RS690_MC_INDEX_MASK);
645 	return r;
646 }
647 
648 void rs690_mc_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v)
649 {
650 	WREG32(RS690_MC_INDEX,
651 	       RS690_MC_INDEX_WR_EN | ((reg) & RS690_MC_INDEX_MASK));
652 	WREG32(RS690_MC_DATA, v);
653 	WREG32(RS690_MC_INDEX, RS690_MC_INDEX_WR_ACK);
654 }
655 
656 static const unsigned rs690_reg_safe_bm[219] = {
657 	0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,
658 	0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,
659 	0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,
660 	0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,
661 	0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,
662 	0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,
663 	0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,
664 	0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,
665 	0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,
666 	0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,
667 	0x17FF1FFF,0xFFFFFFFC,0xFFFFFFFF,0xFF30FFBF,
668 	0xFFFFFFF8,0xC3E6FFFF,0xFFFFF6DF,0xFFFFFFFF,
669 	0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,
670 	0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,
671 	0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFF03F,
672 	0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,
673 	0xFFFFFFFF,0xFFFFEFCE,0xF00EBFFF,0x007C0000,
674 	0xF0000078,0xFF000009,0xFFFFFFFF,0xFFFFFFFF,
675 	0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,
676 	0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,
677 	0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,
678 	0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,
679 	0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,
680 	0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,
681 	0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,
682 	0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,
683 	0xFFFFF7FF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,
684 	0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,
685 	0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,
686 	0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,
687 	0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,
688 	0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,
689 	0xFFFFFC78,0xFFFFFFFF,0xFFFFFFFE,0xFFFFFFFF,
690 	0x38FF8F50,0xFFF88082,0xF000000C,0xFAE009FF,
691 	0x0000FFFF,0xFFFFFFFF,0xFFFFFFFF,0x00000000,
692 	0x00000000,0x0000C100,0x00000000,0x00000000,
693 	0x00000000,0x00000000,0x00000000,0x00000000,
694 	0x00000000,0xFFFF0000,0xFFFFFFFF,0xFF80FFFF,
695 	0x00000000,0x00000000,0x00000000,0x00000000,
696 	0x0003FC01,0xFFFFFFF8,0xFE800B19,0xFFFFFFFF,
697 	0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,
698 	0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,
699 	0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,
700 	0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,
701 	0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,
702 	0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,
703 	0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,
704 	0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,
705 	0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,
706 	0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,
707 	0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,
708 	0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,
709 	0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,
710 	0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,
711 	0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,
712 };
713 
714 int rs690_init(struct radeon_device *rdev)
715 {
716 	rdev->config.r300.reg_safe_bm = rs690_reg_safe_bm;
717 	rdev->config.r300.reg_safe_bm_size = ARRAY_SIZE(rs690_reg_safe_bm);
718 	return 0;
719 }
720