Subversion Repositories Kolibri OS

Rev

Rev 3192 | Rev 5078 | 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 
1963 serge 29
#include 
2997 Serge 30
#include 
31
#include 
1117 serge 32
#include "radeon_reg.h"
33
#include "radeon.h"
1963 serge 34
#include "radeon_asic.h"
1179 serge 35
#include "r100d.h"
1221 serge 36
#include "rs100d.h"
37
#include "rv200d.h"
38
#include "rv250d.h"
1963 serge 39
#include "atom.h"
1117 serge 40
 
1221 serge 41
#include 
2997 Serge 42
#include 
1221 serge 43
 
1179 serge 44
#include "r100_reg_safe.h"
45
#include "rn50_reg_safe.h"
1221 serge 46
 
47
/* Firmware Names */
48
#define FIRMWARE_R100		"radeon/R100_cp.bin"
49
#define FIRMWARE_R200		"radeon/R200_cp.bin"
50
#define FIRMWARE_R300		"radeon/R300_cp.bin"
51
#define FIRMWARE_R420		"radeon/R420_cp.bin"
52
#define FIRMWARE_RS690		"radeon/RS690_cp.bin"
53
#define FIRMWARE_RS600		"radeon/RS600_cp.bin"
54
#define FIRMWARE_R520		"radeon/R520_cp.bin"
55
 
56
MODULE_FIRMWARE(FIRMWARE_R100);
57
MODULE_FIRMWARE(FIRMWARE_R200);
58
MODULE_FIRMWARE(FIRMWARE_R300);
59
MODULE_FIRMWARE(FIRMWARE_R420);
60
MODULE_FIRMWARE(FIRMWARE_RS690);
61
MODULE_FIRMWARE(FIRMWARE_RS600);
62
MODULE_FIRMWARE(FIRMWARE_R520);
63
 
64
 
1117 serge 65
/* This files gather functions specifics to:
66
 * r100,rv100,rs100,rv200,rs200,r200,rv250,rs300,rv280
2997 Serge 67
 * and others in some cases.
1117 serge 68
 */
69
 
3764 Serge 70
static bool r100_is_in_vblank(struct radeon_device *rdev, int crtc)
71
{
72
	if (crtc == 0) {
73
		if (RREG32(RADEON_CRTC_STATUS) & RADEON_CRTC_VBLANK_CUR)
74
			return true;
75
		else
76
			return false;
77
	} else {
78
		if (RREG32(RADEON_CRTC2_STATUS) & RADEON_CRTC2_VBLANK_CUR)
79
			return true;
80
		else
81
			return false;
82
	}
83
}
84
 
85
static bool r100_is_counter_moving(struct radeon_device *rdev, int crtc)
86
{
87
	u32 vline1, vline2;
88
 
89
	if (crtc == 0) {
90
		vline1 = (RREG32(RADEON_CRTC_VLINE_CRNT_VLINE) >> 16) & RADEON_CRTC_V_TOTAL;
91
		vline2 = (RREG32(RADEON_CRTC_VLINE_CRNT_VLINE) >> 16) & RADEON_CRTC_V_TOTAL;
92
	} else {
93
		vline1 = (RREG32(RADEON_CRTC2_VLINE_CRNT_VLINE) >> 16) & RADEON_CRTC_V_TOTAL;
94
		vline2 = (RREG32(RADEON_CRTC2_VLINE_CRNT_VLINE) >> 16) & RADEON_CRTC_V_TOTAL;
95
	}
96
	if (vline1 != vline2)
97
		return true;
98
	else
99
		return false;
100
}
101
 
2997 Serge 102
/**
103
 * r100_wait_for_vblank - vblank wait asic callback.
104
 *
105
 * @rdev: radeon_device pointer
106
 * @crtc: crtc to wait for vblank on
107
 *
108
 * Wait for vblank on the requested crtc (r1xx-r4xx).
109
 */
110
void r100_wait_for_vblank(struct radeon_device *rdev, int crtc)
111
{
3764 Serge 112
	unsigned i = 0;
2997 Serge 113
 
114
	if (crtc >= rdev->num_crtc)
115
		return;
116
 
117
	if (crtc == 0) {
3764 Serge 118
		if (!(RREG32(RADEON_CRTC_GEN_CNTL) & RADEON_CRTC_EN))
119
			return;
120
	} else {
121
		if (!(RREG32(RADEON_CRTC2_GEN_CNTL) & RADEON_CRTC2_EN))
122
			return;
123
	}
124
 
125
	/* depending on when we hit vblank, we may be close to active; if so,
126
	 * wait for another frame.
127
	 */
128
	while (r100_is_in_vblank(rdev, crtc)) {
129
		if (i++ % 100 == 0) {
130
			if (!r100_is_counter_moving(rdev, crtc))
2997 Serge 131
					break;
132
			}
133
		}
3764 Serge 134
 
135
	while (!r100_is_in_vblank(rdev, crtc)) {
136
		if (i++ % 100 == 0) {
137
			if (!r100_is_counter_moving(rdev, crtc))
2997 Serge 138
					break;
139
		}
140
	}
141
}
1963 serge 142
u32 r100_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base)
143
{
144
	struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id];
145
	u32 tmp = ((u32)crtc_base) | RADEON_CRTC_OFFSET__OFFSET_LOCK;
2997 Serge 146
	int i;
1963 serge 147
 
148
	/* Lock the graphics update lock */
149
	/* update the scanout addresses */
150
	WREG32(RADEON_CRTC_OFFSET + radeon_crtc->crtc_offset, tmp);
151
 
152
	/* Wait for update_pending to go high. */
2997 Serge 153
	for (i = 0; i < rdev->usec_timeout; i++) {
154
		if (RREG32(RADEON_CRTC_OFFSET + radeon_crtc->crtc_offset) & RADEON_CRTC_OFFSET__GUI_TRIG_OFFSET)
155
			break;
156
		udelay(1);
157
	}
1963 serge 158
	DRM_DEBUG("Update pending now high. Unlocking vupdate_lock.\n");
159
 
160
	/* Unlock the lock, so double-buffering can take place inside vblank */
161
	tmp &= ~RADEON_CRTC_OFFSET__OFFSET_LOCK;
162
	WREG32(RADEON_CRTC_OFFSET + radeon_crtc->crtc_offset, tmp);
163
 
164
	/* Return current update_pending status: */
165
	return RREG32(RADEON_CRTC_OFFSET + radeon_crtc->crtc_offset) & RADEON_CRTC_OFFSET__GUI_TRIG_OFFSET;
166
}
167
bool r100_gui_idle(struct radeon_device *rdev)
168
{
169
	if (RREG32(RADEON_RBBM_STATUS) & RADEON_RBBM_ACTIVE)
170
		return false;
171
	else
172
		return true;
173
}
174
 
1321 serge 175
/* hpd for digital panel detect/disconnect */
2997 Serge 176
/**
177
 * r100_hpd_sense - hpd sense callback.
178
 *
179
 * @rdev: radeon_device pointer
180
 * @hpd: hpd (hotplug detect) pin
181
 *
182
 * Checks if a digital monitor is connected (r1xx-r4xx).
183
 * Returns true if connected, false if not connected.
184
 */
1321 serge 185
bool r100_hpd_sense(struct radeon_device *rdev, enum radeon_hpd_id hpd)
186
{
187
	bool connected = false;
188
 
189
	switch (hpd) {
190
	case RADEON_HPD_1:
191
		if (RREG32(RADEON_FP_GEN_CNTL) & RADEON_FP_DETECT_SENSE)
192
			connected = true;
193
		break;
194
	case RADEON_HPD_2:
195
		if (RREG32(RADEON_FP2_GEN_CNTL) & RADEON_FP2_DETECT_SENSE)
196
			connected = true;
197
		break;
198
	default:
199
		break;
200
	}
201
	return connected;
202
}
203
 
2997 Serge 204
/**
205
 * r100_hpd_set_polarity - hpd set polarity callback.
206
 *
207
 * @rdev: radeon_device pointer
208
 * @hpd: hpd (hotplug detect) pin
209
 *
210
 * Set the polarity of the hpd pin (r1xx-r4xx).
211
 */
1321 serge 212
void r100_hpd_set_polarity(struct radeon_device *rdev,
213
			   enum radeon_hpd_id hpd)
214
{
215
	u32 tmp;
216
	bool connected = r100_hpd_sense(rdev, hpd);
217
 
218
	switch (hpd) {
219
	case RADEON_HPD_1:
220
		tmp = RREG32(RADEON_FP_GEN_CNTL);
221
		if (connected)
222
			tmp &= ~RADEON_FP_DETECT_INT_POL;
223
		else
224
			tmp |= RADEON_FP_DETECT_INT_POL;
225
		WREG32(RADEON_FP_GEN_CNTL, tmp);
226
		break;
227
	case RADEON_HPD_2:
228
		tmp = RREG32(RADEON_FP2_GEN_CNTL);
229
		if (connected)
230
			tmp &= ~RADEON_FP2_DETECT_INT_POL;
231
		else
232
			tmp |= RADEON_FP2_DETECT_INT_POL;
233
		WREG32(RADEON_FP2_GEN_CNTL, tmp);
234
		break;
235
	default:
236
		break;
237
	}
238
}
239
 
2997 Serge 240
/**
241
 * r100_hpd_init - hpd setup callback.
242
 *