Subversion Repositories Kolibri OS

Rev

Rev 1129 | Rev 1221 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1117 serge 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
 */
1179 serge 28
#include 
1125 serge 29
#include "drmP.h"
30
#include "drm.h"
1117 serge 31
#include "radeon_drm.h"
32
#include "radeon_microcode.h"
33
#include "radeon_reg.h"
34
#include "radeon.h"
1179 serge 35
#include "r100d.h"
1117 serge 36
 
1179 serge 37
#include "r100_reg_safe.h"
38
#include "rn50_reg_safe.h"
1117 serge 39
/* This files gather functions specifics to:
40
 * r100,rv100,rs100,rv200,rs200,r200,rv250,rs300,rv280
41
 *
42
 * Some of these functions might be used by newer ASICs.
43
 */
1179 serge 44
int r200_init(struct radeon_device *rdev);
1117 serge 45
void r100_hdp_reset(struct radeon_device *rdev);
46
void r100_gpu_init(struct radeon_device *rdev);
47
int r100_gui_wait_for_idle(struct radeon_device *rdev);
48
int r100_mc_wait_for_idle(struct radeon_device *rdev);
49
void r100_gpu_wait_for_vsync(struct radeon_device *rdev);
50
void r100_gpu_wait_for_vsync2(struct radeon_device *rdev);
51
int r100_debugfs_mc_info_init(struct radeon_device *rdev);
52
 
1179 serge 53
 
1117 serge 54
/*
55
 * PCI GART
56
 */
57
void r100_pci_gart_tlb_flush(struct radeon_device *rdev)
58
{
59
	/* TODO: can we do somethings here ? */
60
	/* It seems hw only cache one entry so we should discard this
61
	 * entry otherwise if first GPU GART read hit this entry it
62
	 * could end up in wrong address. */
63
}
64
 
1179 serge 65
int r100_pci_gart_init(struct radeon_device *rdev)
1117 serge 66
{
67
	int r;
68
 
1179 serge 69
	if (rdev->gart.table.ram.ptr) {
70
		WARN(1, "R100 PCI GART already initialized.\n");
71
		return 0;
72
	}
1117 serge 73
	/* Initialize common gart structure */
74
	r = radeon_gart_init(rdev);
1179 serge 75
	if (r)
1117 serge 76
		return r;
77
		rdev->gart.table_size = rdev->gart.num_gpu_pages * 4;
1179 serge 78
	rdev->asic->gart_tlb_flush = &r100_pci_gart_tlb_flush;
79
	rdev->asic->gart_set_page = &r100_pci_gart_set_page;
80
	return radeon_gart_table_ram_alloc(rdev);
81
}
82
 
83
int r100_pci_gart_enable(struct radeon_device *rdev)
84
{
85
	uint32_t tmp;
86
 
1117 serge 87
	/* discard memory request outside of configured range */
88
	tmp = RREG32(RADEON_AIC_CNTL) | RADEON_DIS_OUT_OF_PCI_GART_ACCESS;
89
	WREG32(RADEON_AIC_CNTL, tmp);
90
	/* set address range for PCI address translate */
91
	WREG32(RADEON_AIC_LO_ADDR, rdev->mc.gtt_location);
92
	tmp = rdev->mc.gtt_location + rdev->mc.gtt_size - 1;
93
	WREG32(RADEON_AIC_HI_ADDR, tmp);
94
	/* Enable bus mastering */
95
	tmp = RREG32(RADEON_BUS_CNTL) & ~RADEON_BUS_MASTER_DIS;
96
	WREG32(RADEON_BUS_CNTL, tmp);
97
	/* set PCI GART page-table base address */
98
	WREG32(RADEON_AIC_PT_BASE, rdev->gart.table_addr);
99
	tmp = RREG32(RADEON_AIC_CNTL) | RADEON_PCIGART_TRANSLATE_EN;
100
	WREG32(RADEON_AIC_CNTL, tmp);
101
	r100_pci_gart_tlb_flush(rdev);
102
	rdev->gart.ready = true;
103
	return 0;
104
}
105
 
106
void r100_pci_gart_disable(struct radeon_device *rdev)
107
{
108
	uint32_t tmp;
109
 
110
	/* discard memory request outside of configured range */
111
	tmp = RREG32(RADEON_AIC_CNTL) | RADEON_DIS_OUT_OF_PCI_GART_ACCESS;
112
	WREG32(RADEON_AIC_CNTL, tmp & ~RADEON_PCIGART_TRANSLATE_EN);
113
	WREG32(RADEON_AIC_LO_ADDR, 0);
114
	WREG32(RADEON_AIC_HI_ADDR, 0);
115
}
116
 
117
int r100_pci_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr)
118
{
119
	if (i < 0 || i > rdev->gart.num_gpu_pages) {
120
		return -EINVAL;
121
	}
1179 serge 122
	rdev->gart.table.ram.ptr[i] = cpu_to_le32(lower_32_bits(addr));
1117 serge 123
	return 0;
124
}
125
 
1179 serge 126
void r100_pci_gart_fini(struct radeon_device *rdev)
1117 serge 127
{
128
		r100_pci_gart_disable(rdev);
1179 serge 129
	radeon_gart_table_ram_free(rdev);
130
	radeon_gart_fini(rdev);
1117 serge 131
}
132
 
133
 
134
/*
135
 * MC
136
 */
137
void r100_mc_disable_clients(struct radeon_device *rdev)
138
{
139
	uint32_t ov0_scale_cntl, crtc_ext_cntl, crtc_gen_cntl, crtc2_gen_cntl;
140
 
141
	/* FIXME: is this function correct for rs100,rs200,rs300 ? */
1128 serge 142
	if (r100_gui_wait_for_idle(rdev)) {
143
		printk(KERN_WARNING "Failed to wait GUI idle while "
144
		       "programming pipes. Bad things might happen.\n");
145
	}
1117 serge 146
 
147
	/* stop display and memory access */
148
	ov0_scale_cntl = RREG32(RADEON_OV0_SCALE_CNTL);
149
	WREG32(RADEON_OV0_SCALE_CNTL, ov0_scale_cntl & ~RADEON_SCALER_ENABLE);
150
	crtc_ext_cntl = RREG32(RADEON_CRTC_EXT_CNTL);
151
	WREG32(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl | RADEON_CRTC_DISPLAY_DIS);
152
	crtc_gen_cntl = RREG32(RADEON_CRTC_GEN_CNTL);
153
 
154
	r100_gpu_wait_for_vsync(rdev);
155
 
156
	WREG32(RADEON_CRTC_GEN_CNTL,
157
	       (crtc_gen_cntl & ~(RADEON_CRTC_CUR_EN | RADEON_CRTC_ICON_EN)) |
158
	       RADEON_CRTC_DISP_REQ_EN_B | RADEON_CRTC_EXT_DISP_EN);
159
 
160
	if (!(rdev->flags & RADEON_SINGLE_CRTC)) {
161
		crtc2_gen_cntl = RREG32(RADEON_CRTC2_GEN_CNTL);
162
 
163
		r100_gpu_wait_for_vsync2(rdev);
164
		WREG32(RADEON_CRTC2_GEN_CNTL,
165
		       (crtc2_gen_cntl &
166
		        ~(RADEON_CRTC2_CUR_EN | RADEON_CRTC2_ICON_EN)) |
167
		       RADEON_CRTC2_DISP_REQ_EN_B);
168
	}
169
 
170
	udelay(500);
171
}
172
 
173
void r100_mc_setup(struct radeon_device *rdev)
174
{
175
	uint32_t tmp;
176
	int r;
177
 
1129 serge 178
	r = r100_debugfs_mc_info_init(rdev);
179
	if (r) {
180
		DRM_ERROR("Failed to register debugfs file for R100 MC !\n");
181
	}
1117 serge 182
	/* Write VRAM size in case we are limiting it */
1179 serge 183
	WREG32(RADEON_CONFIG_MEMSIZE, rdev->mc.real_vram_size);
184
	/* Novell bug 204882 for RN50/M6/M7 with 8/16/32MB VRAM,
185
	 * if the aperture is 64MB but we have 32MB VRAM
186
	 * we report only 32MB VRAM but we have to set MC_FB_LOCATION
187
	 * to 64MB, otherwise the gpu accidentially dies */
188
	tmp = rdev->mc.vram_location + rdev->mc.mc_vram_size - 1;
1117 serge 189
	tmp = REG_SET(RADEON_MC_FB_TOP, tmp >> 16);
190
	tmp |= REG_SET(RADEON_MC_FB_START, rdev->mc.vram_location >> 16);
191
	WREG32(RADEON_MC_FB_LOCATION, tmp);
192
 
193
	/* Enable bus mastering */
194
	tmp = RREG32(RADEON_BUS_CNTL) & ~RADEON_BUS_MASTER_DIS;
195
	WREG32(RADEON_BUS_CNTL, tmp);
196
 
197
	if (rdev->flags & RADEON_IS_AGP) {
1179 serge 198
        tmp = rdev->mc.gtt_location + rdev->mc.gtt_size - 1;
1117 serge 199
		tmp = REG_SET(RADEON_MC_AGP_TOP, tmp >> 16);
200
		tmp |= REG_SET(RADEON_MC_AGP_START, rdev->mc.gtt_location >> 16);
201
		WREG32(RADEON_MC_AGP_LOCATION, tmp);
202
		WREG32(RADEON_AGP_BASE, rdev->mc.agp_base);
203
	} else {
204
		WREG32(RADEON_MC_AGP_LOCATION, 0x0FFFFFFF);
205
		WREG32(RADEON_AGP_BASE, 0);
206
	}
207
 
208
	tmp = RREG32(RADEON_HOST_PATH_CNTL) & RADEON_HDP_APER_CNTL;
209
	tmp |= (7 << 28);
210
	WREG32(RADEON_HOST_PATH_CNTL, tmp | RADEON_HDP_SOFT_RESET | RADEON_HDP_READ_BUFFER_INVALIDATE);
211
	(void)RREG32(RADEON_HOST_PATH_CNTL);
212
	WREG32(RADEON_HOST_PATH_CNTL, tmp);
213
	(void)RREG32(RADEON_HOST_PATH_CNTL);
214
}
215
 
216
int r100_mc_init(struct radeon_device *rdev)
217
{
218
	int r;
219
 
1129 serge 220
	if (r100_debugfs_rbbm_init(rdev)) {
221
		DRM_ERROR("Failed to register debugfs file for RBBM !\n");
222
	}
1117 serge 223
 
224
	r100_gpu_init(rdev);
225
	/* Disable gart which also disable out of gart access */
226
	r100_pci_gart_disable(rdev);
227
 
228
	/* Setup GPU memory space */
229
	rdev->mc.gtt_location = 0xFFFFFFFFUL;
230
	r = radeon_mc_setup(rdev);
231
	if (r) {
232
		return r;
233
	}
234
 
235
	r100_mc_disable_clients(rdev);
236
	if (r100_mc_wait_for_idle(rdev)) {
237
       printk(KERN_WARNING "Failed to wait MC idle while