brintos

brintos / linux-shallow public Read only

0
0
Text · 29.4 KiB · 016eb49 Raw
880 lines · c
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 a7 * copy of this software and associated documentation files (the "Software"),8 * to deal in the Software without restriction, including without limitation9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,10 * and/or sell copies of the Software, and to permit persons to whom the11 * Software is furnished to do so, subject to the following conditions:12 *13 * The above copyright notice and this permission notice shall be included in14 * all copies or substantial portions of the Software.15 *16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL19 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR20 * 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 OR22 * OTHER DEALINGS IN THE SOFTWARE.23 *24 * Authors: Dave Airlie25 *          Alex Deucher26 *          Jerome Glisse27 */28 29#include <linux/pci.h>30 31#include "atom.h"32#include "radeon.h"33#include "radeon_asic.h"34#include "radeon_audio.h"35#include "rs690d.h"36 37int rs690_mc_wait_for_idle(struct radeon_device *rdev)38{39	unsigned i;40	uint32_t tmp;41 42	for (i = 0; i < rdev->usec_timeout; i++) {43		/* read MC_STATUS */44		tmp = RREG32_MC(R_000090_MC_SYSTEM_STATUS);45		if (G_000090_MC_SYSTEM_IDLE(tmp))46			return 0;47		udelay(1);48	}49	return -1;50}51 52static void rs690_gpu_init(struct radeon_device *rdev)53{54	/* FIXME: is this correct ? */55	r420_pipes_init(rdev);56	if (rs690_mc_wait_for_idle(rdev)) {57		pr_warn("Failed to wait MC idle while programming pipes. Bad things might happen.\n");58	}59}60 61union igp_info {62	struct _ATOM_INTEGRATED_SYSTEM_INFO info;63	struct _ATOM_INTEGRATED_SYSTEM_INFO_V2 info_v2;64};65 66void rs690_pm_info(struct radeon_device *rdev)67{68	int index = GetIndexIntoMasterTable(DATA, IntegratedSystemInfo);69	union igp_info *info;70	uint16_t data_offset;71	uint8_t frev, crev;72	fixed20_12 tmp;73 74	if (atom_parse_data_header(rdev->mode_info.atom_context, index, NULL,75				   &frev, &crev, &data_offset)) {76		info = (union igp_info *)(rdev->mode_info.atom_context->bios + data_offset);77 78		/* Get various system informations from bios */79		switch (crev) {80		case 1:81			tmp.full = dfixed_const(100);82			rdev->pm.igp_sideport_mclk.full = dfixed_const(le32_to_cpu(info->info.ulBootUpMemoryClock));83			rdev->pm.igp_sideport_mclk.full = dfixed_div(rdev->pm.igp_sideport_mclk, tmp);84			if (le16_to_cpu(info->info.usK8MemoryClock))85				rdev->pm.igp_system_mclk.full = dfixed_const(le16_to_cpu(info->info.usK8MemoryClock));86			else if (rdev->clock.default_mclk) {87				rdev->pm.igp_system_mclk.full = dfixed_const(rdev->clock.default_mclk);88				rdev->pm.igp_system_mclk.full = dfixed_div(rdev->pm.igp_system_mclk, tmp);89			} else90				rdev->pm.igp_system_mclk.full = dfixed_const(400);91			rdev->pm.igp_ht_link_clk.full = dfixed_const(le16_to_cpu(info->info.usFSBClock));92			rdev->pm.igp_ht_link_width.full = dfixed_const(info->info.ucHTLinkWidth);93			break;94		case 2:95			tmp.full = dfixed_const(100);96			rdev->pm.igp_sideport_mclk.full = dfixed_const(le32_to_cpu(info->info_v2.ulBootUpSidePortClock));97			rdev->pm.igp_sideport_mclk.full = dfixed_div(rdev->pm.igp_sideport_mclk, tmp);98			if (le32_to_cpu(info->info_v2.ulBootUpUMAClock))99				rdev->pm.igp_system_mclk.full = dfixed_const(le32_to_cpu(info->info_v2.ulBootUpUMAClock));100			else if (rdev->clock.default_mclk)101				rdev->pm.igp_system_mclk.full = dfixed_const(rdev->clock.default_mclk);102			else103				rdev->pm.igp_system_mclk.full = dfixed_const(66700);104			rdev->pm.igp_system_mclk.full = dfixed_div(rdev->pm.igp_system_mclk, tmp);105			rdev->pm.igp_ht_link_clk.full = dfixed_const(le32_to_cpu(info->info_v2.ulHTLinkFreq));106			rdev->pm.igp_ht_link_clk.full = dfixed_div(rdev->pm.igp_ht_link_clk, tmp);107			rdev->pm.igp_ht_link_width.full = dfixed_const(le16_to_cpu(info->info_v2.usMinHTLinkWidth));108			break;109		default:110			/* We assume the slower possible clock ie worst case */111			rdev->pm.igp_sideport_mclk.full = dfixed_const(200);112			rdev->pm.igp_system_mclk.full = dfixed_const(200);113			rdev->pm.igp_ht_link_clk.full = dfixed_const(1000);114			rdev->pm.igp_ht_link_width.full = dfixed_const(8);115			DRM_ERROR("No integrated system info for your GPU, using safe default\n");116			break;117		}118	} else {119		/* We assume the slower possible clock ie worst case */120		rdev->pm.igp_sideport_mclk.full = dfixed_const(200);121		rdev->pm.igp_system_mclk.full = dfixed_const(200);122		rdev->pm.igp_ht_link_clk.full = dfixed_const(1000);123		rdev->pm.igp_ht_link_width.full = dfixed_const(8);124		DRM_ERROR("No integrated system info for your GPU, using safe default\n");125	}126	/* Compute various bandwidth */127	/* k8_bandwidth = (memory_clk / 2) * 2 * 8 * 0.5 = memory_clk * 4  */128	tmp.full = dfixed_const(4);129	rdev->pm.k8_bandwidth.full = dfixed_mul(rdev->pm.igp_system_mclk, tmp);130	/* ht_bandwidth = ht_clk * 2 * ht_width / 8 * 0.8131	 *              = ht_clk * ht_width / 5132	 */133	tmp.full = dfixed_const(5);134	rdev->pm.ht_bandwidth.full = dfixed_mul(rdev->pm.igp_ht_link_clk,135						rdev->pm.igp_ht_link_width);136	rdev->pm.ht_bandwidth.full = dfixed_div(rdev->pm.ht_bandwidth, tmp);137	if (tmp.full < rdev->pm.max_bandwidth.full) {138		/* HT link is a limiting factor */139		rdev->pm.max_bandwidth.full = tmp.full;140	}141	/* sideport_bandwidth = (sideport_clk / 2) * 2 * 2 * 0.7142	 *                    = (sideport_clk * 14) / 10143	 */144	tmp.full = dfixed_const(14);145	rdev->pm.sideport_bandwidth.full = dfixed_mul(rdev->pm.igp_sideport_mclk, tmp);146	tmp.full = dfixed_const(10);147	rdev->pm.sideport_bandwidth.full = dfixed_div(rdev->pm.sideport_bandwidth, tmp);148}149 150static void rs690_mc_init(struct radeon_device *rdev)151{152	u64 base;153	uint32_t h_addr, l_addr;154	unsigned long long k8_addr;155 156	rs400_gart_adjust_size(rdev);157	rdev->mc.vram_is_ddr = true;158	rdev->mc.vram_width = 128;159	rdev->mc.real_vram_size = RREG32(RADEON_CONFIG_MEMSIZE);160	rdev->mc.mc_vram_size = rdev->mc.real_vram_size;161	rdev->mc.aper_base = pci_resource_start(rdev->pdev, 0);162	rdev->mc.aper_size = pci_resource_len(rdev->pdev, 0);163	rdev->mc.visible_vram_size = rdev->mc.aper_size;164	base = RREG32_MC(R_000100_MCCFG_FB_LOCATION);165	base = G_000100_MC_FB_START(base) << 16;166	rdev->mc.igp_sideport_enabled = radeon_atombios_sideport_present(rdev);167	/* Some boards seem to be configured for 128MB of sideport memory,168	 * but really only have 64MB.  Just skip the sideport and use169	 * UMA memory.170	 */171	if (rdev->mc.igp_sideport_enabled &&172	    (rdev->mc.real_vram_size == (384 * 1024 * 1024))) {173		base += 128 * 1024 * 1024;174		rdev->mc.real_vram_size -= 128 * 1024 * 1024;175		rdev->mc.mc_vram_size = rdev->mc.real_vram_size;176	}177 178	/* Use K8 direct mapping for fast fb access. */ 179	rdev->fastfb_working = false;180	h_addr = G_00005F_K8_ADDR_EXT(RREG32_MC(R_00005F_MC_MISC_UMA_CNTL));181	l_addr = RREG32_MC(R_00001E_K8_FB_LOCATION);182	k8_addr = ((unsigned long long)h_addr) << 32 | l_addr;183#if defined(CONFIG_X86_32) && !defined(CONFIG_X86_PAE)184	if (k8_addr + rdev->mc.visible_vram_size < 0x100000000ULL)	185#endif186	{187		/* FastFB shall be used with UMA memory. Here it is simply disabled when sideport 188		 * memory is present.189		 */190		if (!rdev->mc.igp_sideport_enabled && radeon_fastfb == 1) {191			DRM_INFO("Direct mapping: aper base at 0x%llx, replaced by direct mapping base 0x%llx.\n", 192					(unsigned long long)rdev->mc.aper_base, k8_addr);193			rdev->mc.aper_base = (resource_size_t)k8_addr;194			rdev->fastfb_working = true;195		}196	}  197 198	rs690_pm_info(rdev);199	radeon_vram_location(rdev, &rdev->mc, base);200	rdev->mc.gtt_base_align = rdev->mc.gtt_size - 1;201	radeon_gtt_location(rdev, &rdev->mc);202	radeon_update_bandwidth_info(rdev);203}204 205void rs690_line_buffer_adjust(struct radeon_device *rdev,206			      struct drm_display_mode *mode1,207			      struct drm_display_mode *mode2)208{209	u32 tmp;210 211	/* Guess line buffer size to be 8192 pixels */212	u32 lb_size = 8192;213 214	/*215	 * Line Buffer Setup216	 * There is a single line buffer shared by both display controllers.217	 * R_006520_DC_LB_MEMORY_SPLIT controls how that line buffer is shared between218	 * the display controllers.  The paritioning can either be done219	 * manually or via one of four preset allocations specified in bits 1:0:220	 *  0 - line buffer is divided in half and shared between crtc221	 *  1 - D1 gets 3/4 of the line buffer, D2 gets 1/4222	 *  2 - D1 gets the whole buffer223	 *  3 - D1 gets 1/4 of the line buffer, D2 gets 3/4224	 * Setting bit 2 of R_006520_DC_LB_MEMORY_SPLIT controls switches to manual225	 * allocation mode. In manual allocation mode, D1 always starts at 0,226	 * D1 end/2 is specified in bits 14:4; D2 allocation follows D1.227	 */228	tmp = RREG32(R_006520_DC_LB_MEMORY_SPLIT) & C_006520_DC_LB_MEMORY_SPLIT;229	tmp &= ~C_006520_DC_LB_MEMORY_SPLIT_MODE;230	/* auto */231	if (mode1 && mode2) {232		if (mode1->hdisplay > mode2->hdisplay) {233			if (mode1->hdisplay > 2560)234				tmp |= V_006520_DC_LB_MEMORY_SPLIT_D1_3Q_D2_1Q;235			else236				tmp |= V_006520_DC_LB_MEMORY_SPLIT_D1HALF_D2HALF;237		} else if (mode2->hdisplay > mode1->hdisplay) {238			if (mode2->hdisplay > 2560)239				tmp |= V_006520_DC_LB_MEMORY_SPLIT_D1_1Q_D2_3Q;240			else241				tmp |= V_006520_DC_LB_MEMORY_SPLIT_D1HALF_D2HALF;242		} else243			tmp |= V_006520_DC_LB_MEMORY_SPLIT_D1HALF_D2HALF;244	} else if (mode1) {245		tmp |= V_006520_DC_LB_MEMORY_SPLIT_D1_ONLY;246	} else if (mode2) {247		tmp |= V_006520_DC_LB_MEMORY_SPLIT_D1_1Q_D2_3Q;248	}249	WREG32(R_006520_DC_LB_MEMORY_SPLIT, tmp);250 251	/* Save number of lines the linebuffer leads before the scanout */252	if (mode1)253		rdev->mode_info.crtcs[0]->lb_vblank_lead_lines = DIV_ROUND_UP(lb_size, mode1->crtc_hdisplay);254 255	if (mode2)256		rdev->mode_info.crtcs[1]->lb_vblank_lead_lines = DIV_ROUND_UP(lb_size, mode2->crtc_hdisplay);257}258 259struct rs690_watermark {260	u32        lb_request_fifo_depth;261	fixed20_12 num_line_pair;262	fixed20_12 estimated_width;263	fixed20_12 worst_case_latency;264	fixed20_12 consumption_rate;265	fixed20_12 active_time;266	fixed20_12 dbpp;267	fixed20_12 priority_mark_max;268	fixed20_12 priority_mark;269	fixed20_12 sclk;270};271 272static void rs690_crtc_bandwidth_compute(struct radeon_device *rdev,273					 struct radeon_crtc *crtc,274					 struct rs690_watermark *wm,275					 bool low)276{277	struct drm_display_mode *mode = &crtc->base.mode;278	fixed20_12 a, b, c;279	fixed20_12 pclk, request_fifo_depth, tolerable_latency, estimated_width;280	fixed20_12 consumption_time, line_time, chunk_time, read_delay_latency;281	fixed20_12 sclk, core_bandwidth, max_bandwidth;282	u32 selected_sclk;283 284	if (!crtc->base.enabled) {285		/* FIXME: wouldn't it better to set priority mark to maximum */286		wm->lb_request_fifo_depth = 4;287		return;288	}289 290	if (((rdev->family == CHIP_RS780) || (rdev->family == CHIP_RS880)) &&291	    (rdev->pm.pm_method == PM_METHOD_DPM) && rdev->pm.dpm_enabled)292		selected_sclk = radeon_dpm_get_sclk(rdev, low);293	else294		selected_sclk = rdev->pm.current_sclk;295 296	/* sclk in Mhz */297	a.full = dfixed_const(100);298	sclk.full = dfixed_const(selected_sclk);299	sclk.full = dfixed_div(sclk, a);300 301	/* core_bandwidth = sclk(Mhz) * 16 */302	a.full = dfixed_const(16);303	core_bandwidth.full = dfixed_div(rdev->pm.sclk, a);304 305	if (crtc->vsc.full > dfixed_const(2))306		wm->num_line_pair.full = dfixed_const(2);307	else308		wm->num_line_pair.full = dfixed_const(1);309 310	b.full = dfixed_const(mode->crtc_hdisplay);311	c.full = dfixed_const(256);312	a.full = dfixed_div(b, c);313	request_fifo_depth.full = dfixed_mul(a, wm->num_line_pair);314	request_fifo_depth.full = dfixed_ceil(request_fifo_depth);315	if (a.full < dfixed_const(4)) {316		wm->lb_request_fifo_depth = 4;317	} else {318		wm->lb_request_fifo_depth = dfixed_trunc(request_fifo_depth);319	}320 321	/* Determine consumption rate322	 *  pclk = pixel clock period(ns) = 1000 / (mode.clock / 1000)323	 *  vtaps = number of vertical taps,324	 *  vsc = vertical scaling ratio, defined as source/destination325	 *  hsc = horizontal scaling ration, defined as source/destination326	 */327	a.full = dfixed_const(mode->clock);328	b.full = dfixed_const(1000);329	a.full = dfixed_div(a, b);330	pclk.full = dfixed_div(b, a);331	if (crtc->rmx_type != RMX_OFF) {332		b.full = dfixed_const(2);333		if (crtc->vsc.full > b.full)334			b.full = crtc->vsc.full;335		b.full = dfixed_mul(b, crtc->hsc);336		c.full = dfixed_const(2);337		b.full = dfixed_div(b, c);338		consumption_time.full = dfixed_div(pclk, b);339	} else {340		consumption_time.full = pclk.full;341	}342	a.full = dfixed_const(1);343	wm->consumption_rate.full = dfixed_div(a, consumption_time);344 345 346	/* Determine line time347	 *  LineTime = total time for one line of displayhtotal348	 *  LineTime = total number of horizontal pixels349	 *  pclk = pixel clock period(ns)350	 */351	a.full = dfixed_const(crtc->base.mode.crtc_htotal);352	line_time.full = dfixed_mul(a, pclk);353 354	/* Determine active time355	 *  ActiveTime = time of active region of display within one line,356	 *  hactive = total number of horizontal active pixels357	 *  htotal = total number of horizontal pixels358	 */359	a.full = dfixed_const(crtc->base.mode.crtc_htotal);360	b.full = dfixed_const(crtc->base.mode.crtc_hdisplay);361	wm->active_time.full = dfixed_mul(line_time, b);362	wm->active_time.full = dfixed_div(wm->active_time, a);363 364	/* Maximun bandwidth is the minimun bandwidth of all component */365	max_bandwidth = core_bandwidth;366	if (rdev->mc.igp_sideport_enabled) {367		if (max_bandwidth.full > rdev->pm.sideport_bandwidth.full &&368			rdev->pm.sideport_bandwidth.full)369			max_bandwidth = rdev->pm.sideport_bandwidth;370		read_delay_latency.full = dfixed_const(370 * 800);371		a.full = dfixed_const(1000);372		b.full = dfixed_div(rdev->pm.igp_sideport_mclk, a);373		read_delay_latency.full = dfixed_div(read_delay_latency, b);374		read_delay_latency.full = dfixed_mul(read_delay_latency, a);375	} else {376		if (max_bandwidth.full > rdev->pm.k8_bandwidth.full &&377			rdev->pm.k8_bandwidth.full)378			max_bandwidth = rdev->pm.k8_bandwidth;379		if (max_bandwidth.full > rdev->pm.ht_bandwidth.full &&380			rdev->pm.ht_bandwidth.full)381			max_bandwidth = rdev->pm.ht_bandwidth;382		read_delay_latency.full = dfixed_const(5000);383	}384 385	/* sclk = system clocks(ns) = 1000 / max_bandwidth / 16 */386	a.full = dfixed_const(16);387	sclk.full = dfixed_mul(max_bandwidth, a);388	a.full = dfixed_const(1000);389	sclk.full = dfixed_div(a, sclk);390	/* Determine chunk time391	 * ChunkTime = the time it takes the DCP to send one chunk of data392	 * to the LB which consists of pipeline delay and inter chunk gap393	 * sclk = system clock(ns)394	 */395	a.full = dfixed_const(256 * 13);396	chunk_time.full = dfixed_mul(sclk, a);397	a.full = dfixed_const(10);398	chunk_time.full = dfixed_div(chunk_time, a);399 400	/* Determine the worst case latency401	 * NumLinePair = Number of line pairs to request(1=2 lines, 2=4 lines)402	 * WorstCaseLatency = worst case time from urgent to when the MC starts403	 *                    to return data404	 * READ_DELAY_IDLE_MAX = constant of 1us405	 * ChunkTime = time it takes the DCP to send one chunk of data to the LB406	 *             which consists of pipeline delay and inter chunk gap407	 */408	if (dfixed_trunc(wm->num_line_pair) > 1) {409		a.full = dfixed_const(3);410		wm->worst_case_latency.full = dfixed_mul(a, chunk_time);411		wm->worst_case_latency.full += read_delay_latency.full;412	} else {413		a.full = dfixed_const(2);414		wm->worst_case_latency.full = dfixed_mul(a, chunk_time);415		wm->worst_case_latency.full += read_delay_latency.full;416	}417 418	/* Determine the tolerable latency419	 * TolerableLatency = Any given request has only 1 line time420	 *                    for the data to be returned421	 * LBRequestFifoDepth = Number of chunk requests the LB can422	 *                      put into the request FIFO for a display423	 *  LineTime = total time for one line of display424	 *  ChunkTime = the time it takes the DCP to send one chunk425	 *              of data to the LB which consists of426	 *  pipeline delay and inter chunk gap427	 */428	if ((2+wm->lb_request_fifo_depth) >= dfixed_trunc(request_fifo_depth)) {429		tolerable_latency.full = line_time.full;430	} else {431		tolerable_latency.full = dfixed_const(wm->lb_request_fifo_depth - 2);432		tolerable_latency.full = request_fifo_depth.full - tolerable_latency.full;433		tolerable_latency.full = dfixed_mul(tolerable_latency, chunk_time);434		tolerable_latency.full = line_time.full - tolerable_latency.full;435	}436	/* We assume worst case 32bits (4 bytes) */437	wm->dbpp.full = dfixed_const(4 * 8);438 439	/* Determine the maximum priority mark440	 *  width = viewport width in pixels441	 */442	a.full = dfixed_const(16);443	wm->priority_mark_max.full = dfixed_const(crtc->base.mode.crtc_hdisplay);444	wm->priority_mark_max.full = dfixed_div(wm->priority_mark_max, a);445	wm->priority_mark_max.full = dfixed_ceil(wm->priority_mark_max);446 447	/* Determine estimated width */448	estimated_width.full = tolerable_latency.full - wm->worst_case_latency.full;449	estimated_width.full = dfixed_div(estimated_width, consumption_time);450	if (dfixed_trunc(estimated_width) > crtc->base.mode.crtc_hdisplay) {451		wm->priority_mark.full = dfixed_const(10);452	} else {453		a.full = dfixed_const(16);454		wm->priority_mark.full = dfixed_div(estimated_width, a);455		wm->priority_mark.full = dfixed_ceil(wm->priority_mark);456		wm->priority_mark.full = wm->priority_mark_max.full - wm->priority_mark.full;457	}458}459 460static void rs690_compute_mode_priority(struct radeon_device *rdev,461					struct rs690_watermark *wm0,462					struct rs690_watermark *wm1,463					struct drm_display_mode *mode0,464					struct drm_display_mode *mode1,465					u32 *d1mode_priority_a_cnt,466					u32 *d2mode_priority_a_cnt)467{468	fixed20_12 priority_mark02, priority_mark12, fill_rate;469	fixed20_12 a, b;470 471	*d1mode_priority_a_cnt = S_006548_D1MODE_PRIORITY_A_OFF(1);472	*d2mode_priority_a_cnt = S_006548_D1MODE_PRIORITY_A_OFF(1);473 474	if (mode0 && mode1) {475		if (dfixed_trunc(wm0->dbpp) > 64)476			a.full = dfixed_mul(wm0->dbpp, wm0->num_line_pair);477		else478			a.full = wm0->num_line_pair.full;479		if (dfixed_trunc(wm1->dbpp) > 64)480			b.full = dfixed_mul(wm1->dbpp, wm1->num_line_pair);481		else482			b.full = wm1->num_line_pair.full;483		a.full += b.full;484		fill_rate.full = dfixed_div(wm0->sclk, a);485		if (wm0->consumption_rate.full > fill_rate.full) {486			b.full = wm0->consumption_rate.full - fill_rate.full;487			b.full = dfixed_mul(b, wm0->active_time);488			a.full = dfixed_mul(wm0->worst_case_latency,489						wm0->consumption_rate);490			a.full = a.full + b.full;491			b.full = dfixed_const(16 * 1000);492			priority_mark02.full = dfixed_div(a, b);493		} else {494			a.full = dfixed_mul(wm0->worst_case_latency,495						wm0->consumption_rate);496			b.full = dfixed_const(16 * 1000);497			priority_mark02.full = dfixed_div(a, b);498		}499		if (wm1->consumption_rate.full > fill_rate.full) {500			b.full = wm1->consumption_rate.full - fill_rate.full;501			b.full = dfixed_mul(b, wm1->active_time);502			a.full = dfixed_mul(wm1->worst_case_latency,503						wm1->consumption_rate);504			a.full = a.full + b.full;505			b.full = dfixed_const(16 * 1000);506			priority_mark12.full = dfixed_div(a, b);507		} else {508			a.full = dfixed_mul(wm1->worst_case_latency,509						wm1->consumption_rate);510			b.full = dfixed_const(16 * 1000);511			priority_mark12.full = dfixed_div(a, b);512		}513		if (wm0->priority_mark.full > priority_mark02.full)514			priority_mark02.full = wm0->priority_mark.full;515		if (wm0->priority_mark_max.full > priority_mark02.full)516			priority_mark02.full = wm0->priority_mark_max.full;517		if (wm1->priority_mark.full > priority_mark12.full)518			priority_mark12.full = wm1->priority_mark.full;519		if (wm1->priority_mark_max.full > priority_mark12.full)520			priority_mark12.full = wm1->priority_mark_max.full;521		*d1mode_priority_a_cnt = dfixed_trunc(priority_mark02);522		*d2mode_priority_a_cnt = dfixed_trunc(priority_mark12);523		if (rdev->disp_priority == 2) {524			*d1mode_priority_a_cnt |= S_006548_D1MODE_PRIORITY_A_ALWAYS_ON(1);525			*d2mode_priority_a_cnt |= S_006D48_D2MODE_PRIORITY_A_ALWAYS_ON(1);526		}527	} else if (mode0) {528		if (dfixed_trunc(wm0->dbpp) > 64)529			a.full = dfixed_mul(wm0->dbpp, wm0->num_line_pair);530		else531			a.full = wm0->num_line_pair.full;532		fill_rate.full = dfixed_div(wm0->sclk, a);533		if (wm0->consumption_rate.full > fill_rate.full) {534			b.full = wm0->consumption_rate.full - fill_rate.full;535			b.full = dfixed_mul(b, wm0->active_time);536			a.full = dfixed_mul(wm0->worst_case_latency,537						wm0->consumption_rate);538			a.full = a.full + b.full;539			b.full = dfixed_const(16 * 1000);540			priority_mark02.full = dfixed_div(a, b);541		} else {542			a.full = dfixed_mul(wm0->worst_case_latency,543						wm0->consumption_rate);544			b.full = dfixed_const(16 * 1000);545			priority_mark02.full = dfixed_div(a, b);546		}547		if (wm0->priority_mark.full > priority_mark02.full)548			priority_mark02.full = wm0->priority_mark.full;549		if (wm0->priority_mark_max.full > priority_mark02.full)550			priority_mark02.full = wm0->priority_mark_max.full;551		*d1mode_priority_a_cnt = dfixed_trunc(priority_mark02);552		if (rdev->disp_priority == 2)553			*d1mode_priority_a_cnt |= S_006548_D1MODE_PRIORITY_A_ALWAYS_ON(1);554	} else if (mode1) {555		if (dfixed_trunc(wm1->dbpp) > 64)556			a.full = dfixed_mul(wm1->dbpp, wm1->num_line_pair);557		else558			a.full = wm1->num_line_pair.full;559		fill_rate.full = dfixed_div(wm1->sclk, a);560		if (wm1->consumption_rate.full > fill_rate.full) {561			b.full = wm1->consumption_rate.full - fill_rate.full;562			b.full = dfixed_mul(b, wm1->active_time);563			a.full = dfixed_mul(wm1->worst_case_latency,564						wm1->consumption_rate);565			a.full = a.full + b.full;566			b.full = dfixed_const(16 * 1000);567			priority_mark12.full = dfixed_div(a, b);568		} else {569			a.full = dfixed_mul(wm1->worst_case_latency,570						wm1->consumption_rate);571			b.full = dfixed_const(16 * 1000);572			priority_mark12.full = dfixed_div(a, b);573		}574		if (wm1->priority_mark.full > priority_mark12.full)575			priority_mark12.full = wm1->priority_mark.full;576		if (wm1->priority_mark_max.full > priority_mark12.full)577			priority_mark12.full = wm1->priority_mark_max.full;578		*d2mode_priority_a_cnt = dfixed_trunc(priority_mark12);579		if (rdev->disp_priority == 2)580			*d2mode_priority_a_cnt |= S_006D48_D2MODE_PRIORITY_A_ALWAYS_ON(1);581	}582}583 584void rs690_bandwidth_update(struct radeon_device *rdev)585{586	struct drm_display_mode *mode0 = NULL;587	struct drm_display_mode *mode1 = NULL;588	struct rs690_watermark wm0_high, wm0_low;589	struct rs690_watermark wm1_high, wm1_low;590	u32 tmp;591	u32 d1mode_priority_a_cnt, d1mode_priority_b_cnt;592	u32 d2mode_priority_a_cnt, d2mode_priority_b_cnt;593 594	if (!rdev->mode_info.mode_config_initialized)595		return;596 597	radeon_update_display_priority(rdev);598 599	if (rdev->mode_info.crtcs[0]->base.enabled)600		mode0 = &rdev->mode_info.crtcs[0]->base.mode;601	if (rdev->mode_info.crtcs[1]->base.enabled)602		mode1 = &rdev->mode_info.crtcs[1]->base.mode;603	/*604	 * Set display0/1 priority up in the memory controller for605	 * modes if the user specifies HIGH for displaypriority606	 * option.607	 */608	if ((rdev->disp_priority == 2) &&609	    ((rdev->family == CHIP_RS690) || (rdev->family == CHIP_RS740))) {610		tmp = RREG32_MC(R_000104_MC_INIT_MISC_LAT_TIMER);611		tmp &= C_000104_MC_DISP0R_INIT_LAT;612		tmp &= C_000104_MC_DISP1R_INIT_LAT;613		if (mode0)614			tmp |= S_000104_MC_DISP0R_INIT_LAT(1);615		if (mode1)616			tmp |= S_000104_MC_DISP1R_INIT_LAT(1);617		WREG32_MC(R_000104_MC_INIT_MISC_LAT_TIMER, tmp);618	}619	rs690_line_buffer_adjust(rdev, mode0, mode1);620 621	if ((rdev->family == CHIP_RS690) || (rdev->family == CHIP_RS740))622		WREG32(R_006C9C_DCP_CONTROL, 0);623	if ((rdev->family == CHIP_RS780) || (rdev->family == CHIP_RS880))624		WREG32(R_006C9C_DCP_CONTROL, 2);625 626	rs690_crtc_bandwidth_compute(rdev, rdev->mode_info.crtcs[0], &wm0_high, false);627	rs690_crtc_bandwidth_compute(rdev, rdev->mode_info.crtcs[1], &wm1_high, false);628 629	rs690_crtc_bandwidth_compute(rdev, rdev->mode_info.crtcs[0], &wm0_low, true);630	rs690_crtc_bandwidth_compute(rdev, rdev->mode_info.crtcs[1], &wm1_low, true);631 632	tmp = (wm0_high.lb_request_fifo_depth - 1);633	tmp |= (wm1_high.lb_request_fifo_depth - 1) << 16;634	WREG32(R_006D58_LB_MAX_REQ_OUTSTANDING, tmp);635 636	rs690_compute_mode_priority(rdev,637				    &wm0_high, &wm1_high,638				    mode0, mode1,639				    &d1mode_priority_a_cnt, &d2mode_priority_a_cnt);640	rs690_compute_mode_priority(rdev,641				    &wm0_low, &wm1_low,642				    mode0, mode1,643				    &d1mode_priority_b_cnt, &d2mode_priority_b_cnt);644 645	WREG32(R_006548_D1MODE_PRIORITY_A_CNT, d1mode_priority_a_cnt);646	WREG32(R_00654C_D1MODE_PRIORITY_B_CNT, d1mode_priority_b_cnt);647	WREG32(R_006D48_D2MODE_PRIORITY_A_CNT, d2mode_priority_a_cnt);648	WREG32(R_006D4C_D2MODE_PRIORITY_B_CNT, d2mode_priority_b_cnt);649}650 651uint32_t rs690_mc_rreg(struct radeon_device *rdev, uint32_t reg)652{653	unsigned long flags;654	uint32_t r;655 656	spin_lock_irqsave(&rdev->mc_idx_lock, flags);657	WREG32(R_000078_MC_INDEX, S_000078_MC_IND_ADDR(reg));658	r = RREG32(R_00007C_MC_DATA);659	WREG32(R_000078_MC_INDEX, ~C_000078_MC_IND_ADDR);660	spin_unlock_irqrestore(&rdev->mc_idx_lock, flags);661	return r;662}663 664void rs690_mc_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v)665{666	unsigned long flags;667 668	spin_lock_irqsave(&rdev->mc_idx_lock, flags);669	WREG32(R_000078_MC_INDEX, S_000078_MC_IND_ADDR(reg) |670		S_000078_MC_IND_WR_EN(1));671	WREG32(R_00007C_MC_DATA, v);672	WREG32(R_000078_MC_INDEX, 0x7F);673	spin_unlock_irqrestore(&rdev->mc_idx_lock, flags);674}675 676static void rs690_mc_program(struct radeon_device *rdev)677{678	struct rv515_mc_save save;679 680	/* Stops all mc clients */681	rv515_mc_stop(rdev, &save);682 683	/* Wait for mc idle */684	if (rs690_mc_wait_for_idle(rdev))685		dev_warn(rdev->dev, "Wait MC idle timeout before updating MC.\n");686	/* Program MC, should be a 32bits limited address space */687	WREG32_MC(R_000100_MCCFG_FB_LOCATION,688			S_000100_MC_FB_START(rdev->mc.vram_start >> 16) |689			S_000100_MC_FB_TOP(rdev->mc.vram_end >> 16));690	WREG32(R_000134_HDP_FB_LOCATION,691		S_000134_HDP_FB_START(rdev->mc.vram_start >> 16));692 693	rv515_mc_resume(rdev, &save);694}695 696static int rs690_startup(struct radeon_device *rdev)697{698	int r;699 700	rs690_mc_program(rdev);701	/* Resume clock */702	rv515_clock_startup(rdev);703	/* Initialize GPU configuration (# pipes, ...) */704	rs690_gpu_init(rdev);705	/* Initialize GART (initialize after TTM so we can allocate706	 * memory through TTM but finalize after TTM) */707	r = rs400_gart_enable(rdev);708	if (r)709		return r;710 711	/* allocate wb buffer */712	r = radeon_wb_init(rdev);713	if (r)714		return r;715 716	r = radeon_fence_driver_start_ring(rdev, RADEON_RING_TYPE_GFX_INDEX);717	if (r) {718		dev_err(rdev->dev, "failed initializing CP fences (%d).\n", r);719		return r;720	}721 722	/* Enable IRQ */723	if (!rdev->irq.installed) {724		r = radeon_irq_kms_init(rdev);725		if (r)726			return r;727	}728 729	rs600_irq_set(rdev);730	rdev->config.r300.hdp_cntl = RREG32(RADEON_HOST_PATH_CNTL);731	/* 1M ring buffer */732	r = r100_cp_init(rdev, 1024 * 1024);733	if (r) {734		dev_err(rdev->dev, "failed initializing CP (%d).\n", r);735		return r;736	}737 738	r = radeon_ib_pool_init(rdev);739	if (r) {740		dev_err(rdev->dev, "IB initialization failed (%d).\n", r);741		return r;742	}743 744	r = radeon_audio_init(rdev);745	if (r) {746		dev_err(rdev->dev, "failed initializing audio\n");747		return r;748	}749 750	return 0;751}752 753int rs690_resume(struct radeon_device *rdev)754{755	int r;756 757	/* Make sur GART are not working */758	rs400_gart_disable(rdev);759	/* Resume clock before doing reset */760	rv515_clock_startup(rdev);761	/* Reset gpu before posting otherwise ATOM will enter infinite loop */762	if (radeon_asic_reset(rdev)) {763		dev_warn(rdev->dev, "GPU reset failed ! (0xE40=0x%08X, 0x7C0=0x%08X)\n",764			RREG32(R_000E40_RBBM_STATUS),765			RREG32(R_0007C0_CP_STAT));766	}767	/* post */768	atom_asic_init(rdev->mode_info.atom_context);769	/* Resume clock after posting */770	rv515_clock_startup(rdev);771	/* Initialize surface registers */772	radeon_surface_init(rdev);773 774	rdev->accel_working = true;775	r = rs690_startup(rdev);776	if (r) {777		rdev->accel_working = false;778	}779	return r;780}781 782int rs690_suspend(struct radeon_device *rdev)783{784	radeon_pm_suspend(rdev);785	radeon_audio_fini(rdev);786	r100_cp_disable(rdev);787	radeon_wb_disable(rdev);788	rs600_irq_disable(rdev);789	rs400_gart_disable(rdev);790	return 0;791}792 793void rs690_fini(struct radeon_device *rdev)794{795	radeon_pm_fini(rdev);796	radeon_audio_fini(rdev);797	r100_cp_fini(rdev);798	radeon_wb_fini(rdev);799	radeon_ib_pool_fini(rdev);800	radeon_gem_fini(rdev);801	rs400_gart_fini(rdev);802	radeon_irq_kms_fini(rdev);803	radeon_fence_driver_fini(rdev);804	radeon_bo_fini(rdev);805	radeon_atombios_fini(rdev);806	kfree(rdev->bios);807	rdev->bios = NULL;808}809 810int rs690_init(struct radeon_device *rdev)811{812	int r;813 814	/* Disable VGA */815	rv515_vga_render_disable(rdev);816	/* Initialize scratch registers */817	radeon_scratch_init(rdev);818	/* Initialize surface registers */819	radeon_surface_init(rdev);820	/* restore some register to sane defaults */821	r100_restore_sanity(rdev);822	/* TODO: disable VGA need to use VGA request */823	/* BIOS*/824	if (!radeon_get_bios(rdev)) {825		if (ASIC_IS_AVIVO(rdev))826			return -EINVAL;827	}828	if (rdev->is_atom_bios) {829		r = radeon_atombios_init(rdev);830		if (r)831			return r;832	} else {833		dev_err(rdev->dev, "Expecting atombios for RV515 GPU\n");834		return -EINVAL;835	}836	/* Reset gpu before posting otherwise ATOM will enter infinite loop */837	if (radeon_asic_reset(rdev)) {838		dev_warn(rdev->dev,839			"GPU reset failed ! (0xE40=0x%08X, 0x7C0=0x%08X)\n",840			RREG32(R_000E40_RBBM_STATUS),841			RREG32(R_0007C0_CP_STAT));842	}843	/* check if cards are posted or not */844	if (radeon_boot_test_post_card(rdev) == false)845		return -EINVAL;846 847	/* Initialize clocks */848	radeon_get_clock_info(rdev_to_drm(rdev));849	/* initialize memory controller */850	rs690_mc_init(rdev);851	rv515_debugfs(rdev);852	/* Fence driver */853	radeon_fence_driver_init(rdev);854	/* Memory manager */855	r = radeon_bo_init(rdev);856	if (r)857		return r;858	r = rs400_gart_init(rdev);859	if (r)860		return r;861	rs600_set_safe_registers(rdev);862 863	/* Initialize power management */864	radeon_pm_init(rdev);865 866	rdev->accel_working = true;867	r = rs690_startup(rdev);868	if (r) {869		/* Somethings want wront with the accel init stop accel */870		dev_err(rdev->dev, "Disabling GPU acceleration\n");871		r100_cp_fini(rdev);872		radeon_wb_fini(rdev);873		radeon_ib_pool_fini(rdev);874		rs400_gart_fini(rdev);875		radeon_irq_kms_fini(rdev);876		rdev->accel_working = false;877	}878	return 0;879}880