blob: f4f9cb297e36c49a94388840440552b612c91999 [file] [log] [blame]
Jerome Glisse771fe6b2009-06-05 14:42:42 +02001/*
2 * Copyright 2007-8 Advanced Micro Devices, Inc.
3 * Copyright 2008 Red Hat 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 shall be included in
13 * all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
19 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
20 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
21 * OTHER DEALINGS IN THE SOFTWARE.
22 *
23 * Authors: Dave Airlie
24 * Alex Deucher
25 */
26#include <drm/drmP.h>
27#include <drm/drm_crtc_helper.h>
28#include <drm/radeon_drm.h>
29#include "radeon_fixed.h"
30#include "radeon.h"
Dave Airlie4ce001a2009-08-13 16:32:14 +100031#include "atom.h"
Jerome Glisse771fe6b2009-06-05 14:42:42 +020032
Alex Deucher6b02af12009-12-04 10:40:41 -050033static void radeon_overscan_setup(struct drm_crtc *crtc,
34 struct drm_display_mode *mode)
35{
36 struct drm_device *dev = crtc->dev;
37 struct radeon_device *rdev = dev->dev_private;
38 struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
39
40 WREG32(RADEON_OVR_CLR + radeon_crtc->crtc_offset, 0);
41 WREG32(RADEON_OVR_WID_LEFT_RIGHT + radeon_crtc->crtc_offset, 0);
42 WREG32(RADEON_OVR_WID_TOP_BOTTOM + radeon_crtc->crtc_offset, 0);
43}
44
Jerome Glissec93bb852009-07-13 21:04:08 +020045static void radeon_legacy_rmx_mode_set(struct drm_crtc *crtc,
Alex Deucher310a82c2009-12-17 01:24:59 -050046 struct drm_display_mode *mode)
Jerome Glissec93bb852009-07-13 21:04:08 +020047{
48 struct drm_device *dev = crtc->dev;
49 struct radeon_device *rdev = dev->dev_private;
50 struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
51 int xres = mode->hdisplay;
52 int yres = mode->vdisplay;
53 bool hscale = true, vscale = true;
54 int hsync_wid;
55 int vsync_wid;
56 int hsync_start;
57 int blank_width;
58 u32 scale, inc, crtc_more_cntl;
59 u32 fp_horz_stretch, fp_vert_stretch, fp_horz_vert_active;
60 u32 fp_h_sync_strt_wid, fp_crtc_h_total_disp;
61 u32 fp_v_sync_strt_wid, fp_crtc_v_total_disp;
Alex Deucherde2103e2009-10-09 15:14:30 -040062 struct drm_display_mode *native_mode = &radeon_crtc->native_mode;
Jerome Glissec93bb852009-07-13 21:04:08 +020063
64 fp_vert_stretch = RREG32(RADEON_FP_VERT_STRETCH) &
65 (RADEON_VERT_STRETCH_RESERVED |
66 RADEON_VERT_AUTO_RATIO_INC);
67 fp_horz_stretch = RREG32(RADEON_FP_HORZ_STRETCH) &
68 (RADEON_HORZ_FP_LOOP_STRETCH |
69 RADEON_HORZ_AUTO_RATIO_INC);
70
71 crtc_more_cntl = 0;
72 if ((rdev->family == CHIP_RS100) ||
73 (rdev->family == CHIP_RS200)) {
74 /* This is to workaround the asic bug for RMX, some versions
75 of BIOS dosen't have this register initialized correctly. */
76 crtc_more_cntl |= RADEON_CRTC_H_CUTOFF_ACTIVE_EN;
77 }
78
79
80 fp_crtc_h_total_disp = ((((mode->crtc_htotal / 8) - 1) & 0x3ff)
81 | ((((mode->crtc_hdisplay / 8) - 1) & 0x1ff) << 16));
82
83 hsync_wid = (mode->crtc_hsync_end - mode->crtc_hsync_start) / 8;
84 if (!hsync_wid)
85 hsync_wid = 1;
86 hsync_start = mode->crtc_hsync_start - 8;
87
88 fp_h_sync_strt_wid = ((hsync_start & 0x1fff)
89 | ((hsync_wid & 0x3f) << 16)
90 | ((mode->flags & DRM_MODE_FLAG_NHSYNC)
91 ? RADEON_CRTC_H_SYNC_POL
92 : 0));
93
94 fp_crtc_v_total_disp = (((mode->crtc_vtotal - 1) & 0xffff)
95 | ((mode->crtc_vdisplay - 1) << 16));
96
97 vsync_wid = mode->crtc_vsync_end - mode->crtc_vsync_start;
98 if (!vsync_wid)
99 vsync_wid = 1;
100
101 fp_v_sync_strt_wid = (((mode->crtc_vsync_start - 1) & 0xfff)
102 | ((vsync_wid & 0x1f) << 16)
103 | ((mode->flags & DRM_MODE_FLAG_NVSYNC)
104 ? RADEON_CRTC_V_SYNC_POL
105 : 0));
106
107 fp_horz_vert_active = 0;
108
Alex Deucherde2103e2009-10-09 15:14:30 -0400109 if (native_mode->hdisplay == 0 ||
110 native_mode->vdisplay == 0) {
Jerome Glissec93bb852009-07-13 21:04:08 +0200111 hscale = false;
112 vscale = false;
113 } else {
Alex Deucherde2103e2009-10-09 15:14:30 -0400114 if (xres > native_mode->hdisplay)
115 xres = native_mode->hdisplay;
116 if (yres > native_mode->vdisplay)
117 yres = native_mode->vdisplay;
Jerome Glissec93bb852009-07-13 21:04:08 +0200118
Alex Deucherde2103e2009-10-09 15:14:30 -0400119 if (xres == native_mode->hdisplay)
Jerome Glissec93bb852009-07-13 21:04:08 +0200120 hscale = false;
Alex Deucherde2103e2009-10-09 15:14:30 -0400121 if (yres == native_mode->vdisplay)
Jerome Glissec93bb852009-07-13 21:04:08 +0200122 vscale = false;
123 }
124
125 switch (radeon_crtc->rmx_type) {
126 case RMX_FULL:
127 case RMX_ASPECT:
128 if (!hscale)
129 fp_horz_stretch |= ((xres/8-1) << 16);
130 else {
131 inc = (fp_horz_stretch & RADEON_HORZ_AUTO_RATIO_INC) ? 1 : 0;
132 scale = ((xres + inc) * RADEON_HORZ_STRETCH_RATIO_MAX)
Alex Deucherde2103e2009-10-09 15:14:30 -0400133 / native_mode->hdisplay + 1;
Jerome Glissec93bb852009-07-13 21:04:08 +0200134 fp_horz_stretch |= (((scale) & RADEON_HORZ_STRETCH_RATIO_MASK) |
135 RADEON_HORZ_STRETCH_BLEND |
136 RADEON_HORZ_STRETCH_ENABLE |
Alex Deucherde2103e2009-10-09 15:14:30 -0400137 ((native_mode->hdisplay/8-1) << 16));
Jerome Glissec93bb852009-07-13 21:04:08 +0200138 }
139
140 if (!vscale)
141 fp_vert_stretch |= ((yres-1) << 12);
142 else {
143 inc = (fp_vert_stretch & RADEON_VERT_AUTO_RATIO_INC) ? 1 : 0;
144 scale = ((yres + inc) * RADEON_VERT_STRETCH_RATIO_MAX)
Alex Deucherde2103e2009-10-09 15:14:30 -0400145 / native_mode->vdisplay + 1;
Jerome Glissec93bb852009-07-13 21:04:08 +0200146 fp_vert_stretch |= (((scale) & RADEON_VERT_STRETCH_RATIO_MASK) |
147 RADEON_VERT_STRETCH_ENABLE |
148 RADEON_VERT_STRETCH_BLEND |
Alex Deucherde2103e2009-10-09 15:14:30 -0400149 ((native_mode->vdisplay-1) << 12));
Jerome Glissec93bb852009-07-13 21:04:08 +0200150 }
151 break;
152 case RMX_CENTER:
153 fp_horz_stretch |= ((xres/8-1) << 16);
154 fp_vert_stretch |= ((yres-1) << 12);
155
156 crtc_more_cntl |= (RADEON_CRTC_AUTO_HORZ_CENTER_EN |
157 RADEON_CRTC_AUTO_VERT_CENTER_EN);
158
159 blank_width = (mode->crtc_hblank_end - mode->crtc_hblank_start) / 8;
160 if (blank_width > 110)
161 blank_width = 110;
162
163 fp_crtc_h_total_disp = (((blank_width) & 0x3ff)
164 | ((((mode->crtc_hdisplay / 8) - 1) & 0x1ff) << 16));
165
166 hsync_wid = (mode->crtc_hsync_end - mode->crtc_hsync_start) / 8;
167 if (!hsync_wid)
168 hsync_wid = 1;
169
170 fp_h_sync_strt_wid = ((((mode->crtc_hsync_start - mode->crtc_hblank_start) / 8) & 0x1fff)
171 | ((hsync_wid & 0x3f) << 16)
172 | ((mode->flags & DRM_MODE_FLAG_NHSYNC)
173 ? RADEON_CRTC_H_SYNC_POL
174 : 0));
175
176 fp_crtc_v_total_disp = (((mode->crtc_vblank_end - mode->crtc_vblank_start) & 0xffff)
177 | ((mode->crtc_vdisplay - 1) << 16));
178
179 vsync_wid = mode->crtc_vsync_end - mode->crtc_vsync_start;
180 if (!vsync_wid)
181 vsync_wid = 1;
182
183 fp_v_sync_strt_wid = ((((mode->crtc_vsync_start - mode->crtc_vblank_start) & 0xfff)
184 | ((vsync_wid & 0x1f) << 16)
185 | ((mode->flags & DRM_MODE_FLAG_NVSYNC)
186 ? RADEON_CRTC_V_SYNC_POL
187 : 0)));
188
Alex Deucherde2103e2009-10-09 15:14:30 -0400189 fp_horz_vert_active = (((native_mode->vdisplay) & 0xfff) |
190 (((native_mode->hdisplay / 8) & 0x1ff) << 16));
Jerome Glissec93bb852009-07-13 21:04:08 +0200191 break;
192 case RMX_OFF:
193 default:
194 fp_horz_stretch |= ((xres/8-1) << 16);
195 fp_vert_stretch |= ((yres-1) << 12);
196 break;
197 }
198
199 WREG32(RADEON_FP_HORZ_STRETCH, fp_horz_stretch);
200 WREG32(RADEON_FP_VERT_STRETCH, fp_vert_stretch);
201 WREG32(RADEON_CRTC_MORE_CNTL, crtc_more_cntl);
202 WREG32(RADEON_FP_HORZ_VERT_ACTIVE, fp_horz_vert_active);
203 WREG32(RADEON_FP_H_SYNC_STRT_WID, fp_h_sync_strt_wid);
204 WREG32(RADEON_FP_V_SYNC_STRT_WID, fp_v_sync_strt_wid);
205 WREG32(RADEON_FP_CRTC_H_TOTAL_DISP, fp_crtc_h_total_disp);
206 WREG32(RADEON_FP_CRTC_V_TOTAL_DISP, fp_crtc_v_total_disp);
207}
208
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200209void radeon_restore_common_regs(struct drm_device *dev)
210{
211 /* don't need this yet */
212}
213
214static void radeon_pll_wait_for_read_update_complete(struct drm_device *dev)
215{
216 struct radeon_device *rdev = dev->dev_private;
217 int i = 0;
218
219 /* FIXME: Certain revisions of R300 can't recover here. Not sure of
220 the cause yet, but this workaround will mask the problem for now.
221 Other chips usually will pass at the very first test, so the
222 workaround shouldn't have any effect on them. */
223 for (i = 0;
224 (i < 10000 &&
225 RREG32_PLL(RADEON_PPLL_REF_DIV) & RADEON_PPLL_ATOMIC_UPDATE_R);
226 i++);
227}
228
229static void radeon_pll_write_update(struct drm_device *dev)
230{
231 struct radeon_device *rdev = dev->dev_private;
232
233 while (RREG32_PLL(RADEON_PPLL_REF_DIV) & RADEON_PPLL_ATOMIC_UPDATE_R);
234
235 WREG32_PLL_P(RADEON_PPLL_REF_DIV,
236 RADEON_PPLL_ATOMIC_UPDATE_W,
237 ~(RADEON_PPLL_ATOMIC_UPDATE_W));
238}
239
240static void radeon_pll2_wait_for_read_update_complete(struct drm_device *dev)
241{
242 struct radeon_device *rdev = dev->dev_private;
243 int i = 0;
244
245
246 /* FIXME: Certain revisions of R300 can't recover here. Not sure of
247 the cause yet, but this workaround will mask the problem for now.
248 Other chips usually will pass at the very first test, so the
249 workaround shouldn't have any effect on them. */
250 for (i = 0;
251 (i < 10000 &&
252 RREG32_PLL(RADEON_P2PLL_REF_DIV) & RADEON_P2PLL_ATOMIC_UPDATE_R);
253 i++);
254}
255
256static void radeon_pll2_write_update(struct drm_device *dev)
257{
258 struct radeon_device *rdev = dev->dev_private;
259
260 while (RREG32_PLL(RADEON_P2PLL_REF_DIV) & RADEON_P2PLL_ATOMIC_UPDATE_R);
261
262 WREG32_PLL_P(RADEON_P2PLL_REF_DIV,
263 RADEON_P2PLL_ATOMIC_UPDATE_W,
264 ~(RADEON_P2PLL_ATOMIC_UPDATE_W));
265}
266
267static uint8_t radeon_compute_pll_gain(uint16_t ref_freq, uint16_t ref_div,
268 uint16_t fb_div)
269{
270 unsigned int vcoFreq;
271
272 if (!ref_div)
273 return 1;
274
275 vcoFreq = ((unsigned)ref_freq & fb_div) / ref_div;
276
277 /*
278 * This is horribly crude: the VCO frequency range is divided into
279 * 3 parts, each part having a fixed PLL gain value.
280 */
281 if (vcoFreq >= 30000)
282 /*
283 * [300..max] MHz : 7
284 */
285 return 7;
286 else if (vcoFreq >= 18000)
287 /*
288 * [180..300) MHz : 4
289 */
290 return 4;
291 else
292 /*
293 * [0..180) MHz : 1
294 */
295 return 1;
296}
297
298void radeon_crtc_dpms(struct drm_crtc *crtc, int mode)
299{
300 struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
301 struct drm_device *dev = crtc->dev;
302 struct radeon_device *rdev = dev->dev_private;
303 uint32_t mask;
304
305 if (radeon_crtc->crtc_id)
Alex Deucher8de21522009-12-03 12:15:54 -0500306 mask = (RADEON_CRTC2_DISP_DIS |
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200307 RADEON_CRTC2_VSYNC_DIS |
308 RADEON_CRTC2_HSYNC_DIS |
309 RADEON_CRTC2_DISP_REQ_EN_B);
310 else
311 mask = (RADEON_CRTC_DISPLAY_DIS |
312 RADEON_CRTC_VSYNC_DIS |
313 RADEON_CRTC_HSYNC_DIS);
314
315 switch (mode) {
316 case DRM_MODE_DPMS_ON:
317 if (radeon_crtc->crtc_id)
Alex Deucher8de21522009-12-03 12:15:54 -0500318 WREG32_P(RADEON_CRTC2_GEN_CNTL, RADEON_CRTC2_EN, ~(RADEON_CRTC2_EN | mask));
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200319 else {
320 WREG32_P(RADEON_CRTC_GEN_CNTL, RADEON_CRTC_EN, ~(RADEON_CRTC_EN |
321 RADEON_CRTC_DISP_REQ_EN_B));
322 WREG32_P(RADEON_CRTC_EXT_CNTL, 0, ~mask);
323 }
Michel Dänzer7ed220d2009-08-13 11:10:51 +0200324 drm_vblank_post_modeset(dev, radeon_crtc->crtc_id);
325 radeon_crtc_load_lut(crtc);
Alex Deuchera48b9b42010-04-22 14:03:55 -0400326 radeon_crtc->enabled = true;
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200327 break;
328 case DRM_MODE_DPMS_STANDBY:
329 case DRM_MODE_DPMS_SUSPEND:
330 case DRM_MODE_DPMS_OFF:
Michel Dänzer7ed220d2009-08-13 11:10:51 +0200331 drm_vblank_pre_modeset(dev, radeon_crtc->crtc_id);
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200332 if (radeon_crtc->crtc_id)
Alex Deucher8de21522009-12-03 12:15:54 -0500333 WREG32_P(RADEON_CRTC2_GEN_CNTL, mask, ~(RADEON_CRTC2_EN | mask));
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200334 else {
335 WREG32_P(RADEON_CRTC_GEN_CNTL, RADEON_CRTC_DISP_REQ_EN_B, ~(RADEON_CRTC_EN |
336 RADEON_CRTC_DISP_REQ_EN_B));
337 WREG32_P(RADEON_CRTC_EXT_CNTL, mask, ~mask);
338 }
Alex Deuchera48b9b42010-04-22 14:03:55 -0400339 radeon_crtc->enabled = false;
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200340 break;
341 }
Alex Deucher03214bd52010-03-16 17:42:46 -0400342
343 /* adjust pm to dpms change */
344 radeon_pm_compute_clocks(rdev);
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200345}
346
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200347int radeon_crtc_set_base(struct drm_crtc *crtc, int x, int y,
348 struct drm_framebuffer *old_fb)
349{
350 struct drm_device *dev = crtc->dev;
351 struct radeon_device *rdev = dev->dev_private;
352 struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
353 struct radeon_framebuffer *radeon_fb;
354 struct drm_gem_object *obj;
Jerome Glisse4c788672009-11-20 14:29:23 +0100355 struct radeon_bo *rbo;
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200356 uint64_t base;
357 uint32_t crtc_offset, crtc_offset_cntl, crtc_tile_x0_y0 = 0;
358 uint32_t crtc_pitch, pitch_pixels;
Dave Airliee024e112009-06-24 09:48:08 +1000359 uint32_t tiling_flags;
Dave Airlie41456df2009-09-16 10:15:21 +1000360 int format;
361 uint32_t gen_cntl_reg, gen_cntl_val;
Jerome Glisse4c788672009-11-20 14:29:23 +0100362 int r;
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200363
364 DRM_DEBUG("\n");
Jerome Glisse2de3b482009-11-17 14:08:55 -0800365 /* no fb bound */
366 if (!crtc->fb) {
367 DRM_DEBUG("No FB bound\n");
368 return 0;
369 }
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200370
371 radeon_fb = to_radeon_framebuffer(crtc->fb);
372
Dave Airlie41456df2009-09-16 10:15:21 +1000373 switch (crtc->fb->bits_per_pixel) {
374 case 8:
375 format = 2;
376 break;
377 case 15: /* 555 */
378 format = 3;
379 break;
380 case 16: /* 565 */
381 format = 4;
382 break;
383 case 24: /* RGB */
384 format = 5;
385 break;
386 case 32: /* xRGB */
387 format = 6;
388 break;
389 default:
390 return false;
391 }
392
Jerome Glisse4c788672009-11-20 14:29:23 +0100393 /* Pin framebuffer & get tilling informations */
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200394 obj = radeon_fb->obj;
Jerome Glisse4c788672009-11-20 14:29:23 +0100395 rbo = obj->driver_private;
396 r = radeon_bo_reserve(rbo, false);
397 if (unlikely(r != 0))
398 return r;
399 r = radeon_bo_pin(rbo, RADEON_GEM_DOMAIN_VRAM, &base);
400 if (unlikely(r != 0)) {
401 radeon_bo_unreserve(rbo);
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200402 return -EINVAL;
403 }
Jerome Glisse4c788672009-11-20 14:29:23 +0100404 radeon_bo_get_tiling_flags(rbo, &tiling_flags, NULL);
405 radeon_bo_unreserve(rbo);
406 if (tiling_flags & RADEON_TILING_MICRO)
407 DRM_ERROR("trying to scanout microtiled buffer\n");
408
Dave Airlie41623382009-07-09 15:04:19 +1000409 /* if scanout was in GTT this really wouldn't work */
410 /* crtc offset is from display base addr not FB location */
Jerome Glissed594e462010-02-17 21:54:29 +0000411 radeon_crtc->legacy_display_base_addr = rdev->mc.vram_start;
Dave Airlie41623382009-07-09 15:04:19 +1000412
413 base -= radeon_crtc->legacy_display_base_addr;
414
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200415 crtc_offset_cntl = 0;
416
417 pitch_pixels = crtc->fb->pitch / (crtc->fb->bits_per_pixel / 8);
418 crtc_pitch = (((pitch_pixels * crtc->fb->bits_per_pixel) +
419 ((crtc->fb->bits_per_pixel * 8) - 1)) /
420 (crtc->fb->bits_per_pixel * 8));
421 crtc_pitch |= crtc_pitch << 16;
422
Dave Airliee024e112009-06-24 09:48:08 +1000423
424 if (tiling_flags & RADEON_TILING_MACRO) {
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200425 if (ASIC_IS_R300(rdev))
426 crtc_offset_cntl |= (R300_CRTC_X_Y_MODE_EN |
427 R300_CRTC_MICRO_TILE_BUFFER_DIS |
428 R300_CRTC_MACRO_TILE_EN);
429 else
430 crtc_offset_cntl |= RADEON_CRTC_TILE_EN;
431 } else {
432 if (ASIC_IS_R300(rdev))
433 crtc_offset_cntl &= ~(R300_CRTC_X_Y_MODE_EN |
434 R300_CRTC_MICRO_TILE_BUFFER_DIS |
435 R300_CRTC_MACRO_TILE_EN);
436 else
437 crtc_offset_cntl &= ~RADEON_CRTC_TILE_EN;
438 }
439
Dave Airliee024e112009-06-24 09:48:08 +1000440 if (tiling_flags & RADEON_TILING_MACRO) {
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200441 if (ASIC_IS_R300(rdev)) {
442 crtc_tile_x0_y0 = x | (y << 16);
443 base &= ~0x7ff;
444 } else {
445 int byteshift = crtc->fb->bits_per_pixel >> 4;
Dave Airliee024e112009-06-24 09:48:08 +1000446 int tile_addr = (((y >> 3) * pitch_pixels + x) >> (8 - byteshift)) << 11;
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200447 base += tile_addr + ((x << byteshift) % 256) + ((y % 8) << 8);
448 crtc_offset_cntl |= (y % 16);
449 }
450 } else {
451 int offset = y * pitch_pixels + x;
452 switch (crtc->fb->bits_per_pixel) {
Dave Airlie41456df2009-09-16 10:15:21 +1000453 case 8:
454 offset *= 1;
455 break;
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200456 case 15:
457 case 16:
458 offset *= 2;
459 break;
460 case 24:
461 offset *= 3;
462 break;
463 case 32:
464 offset *= 4;
465 break;
466 default:
467 return false;
468 }
469 base += offset;
470 }
471
472 base &= ~7;
473
Dave Airlie41456df2009-09-16 10:15:21 +1000474 if (radeon_crtc->crtc_id == 1)
475 gen_cntl_reg = RADEON_CRTC2_GEN_CNTL;
476 else
477 gen_cntl_reg = RADEON_CRTC_GEN_CNTL;
478
479 gen_cntl_val = RREG32(gen_cntl_reg);
480 gen_cntl_val &= ~(0xf << 8);
481 gen_cntl_val |= (format << 8);
482 WREG32(gen_cntl_reg, gen_cntl_val);
483
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200484 crtc_offset = (u32)base;
485
Dave Airlie41623382009-07-09 15:04:19 +1000486 WREG32(RADEON_DISPLAY_BASE_ADDR + radeon_crtc->crtc_offset, radeon_crtc->legacy_display_base_addr);
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200487
488 if (ASIC_IS_R300(rdev)) {
489 if (radeon_crtc->crtc_id)
490 WREG32(R300_CRTC2_TILE_X0_Y0, crtc_tile_x0_y0);
491 else
492 WREG32(R300_CRTC_TILE_X0_Y0, crtc_tile_x0_y0);
493 }
494 WREG32(RADEON_CRTC_OFFSET_CNTL + radeon_crtc->crtc_offset, crtc_offset_cntl);
495 WREG32(RADEON_CRTC_OFFSET + radeon_crtc->crtc_offset, crtc_offset);
496 WREG32(RADEON_CRTC_PITCH + radeon_crtc->crtc_offset, crtc_pitch);
497
498 if (old_fb && old_fb != crtc->fb) {
499 radeon_fb = to_radeon_framebuffer(old_fb);
Jerome Glisse4c788672009-11-20 14:29:23 +0100500 rbo = radeon_fb->obj->driver_private;
501 r = radeon_bo_reserve(rbo, false);
502 if (unlikely(r != 0))
503 return r;
504 radeon_bo_unpin(rbo);
505 radeon_bo_unreserve(rbo);
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200506 }
Michel Dänzerf30f37d2009-10-08 10:44:09 +0200507
508 /* Bytes per pixel may have changed */
509 radeon_bandwidth_update(rdev);
510
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200511 return 0;
512}
513
514static bool radeon_set_crtc_timing(struct drm_crtc *crtc, struct drm_display_mode *mode)
515{
516 struct drm_device *dev = crtc->dev;
517 struct radeon_device *rdev = dev->dev_private;
518 struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
Dave Airlie4ce001a2009-08-13 16:32:14 +1000519 struct drm_encoder *encoder;
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200520 int format;
521 int hsync_start;
522 int hsync_wid;
523 int vsync_wid;
524 uint32_t crtc_h_total_disp;
525 uint32_t crtc_h_sync_strt_wid;
526 uint32_t crtc_v_total_disp;
527 uint32_t crtc_v_sync_strt_wid;
Dave Airlie4ce001a2009-08-13 16:32:14 +1000528 bool is_tv = false;
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200529
530 DRM_DEBUG("\n");
Dave Airlie4ce001a2009-08-13 16:32:14 +1000531 list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
532 if (encoder->crtc == crtc) {
533 struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
534 if (radeon_encoder->active_device & ATOM_DEVICE_TV_SUPPORT) {
535 is_tv = true;
536 DRM_INFO("crtc %d is connected to a TV\n", radeon_crtc->crtc_id);
537 break;
538 }
539 }
540 }
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200541
542 switch (crtc->fb->bits_per_pixel) {
Dave Airlie41456df2009-09-16 10:15:21 +1000543 case 8:
544 format = 2;
545 break;
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200546 case 15: /* 555 */
547 format = 3;
548 break;
549 case 16: /* 565 */
550 format = 4;
551 break;
552 case 24: /* RGB */
553 format = 5;
554 break;
555 case 32: /* xRGB */
556 format = 6;
557 break;
558 default:
559 return false;
560 }
561
562 crtc_h_total_disp = ((((mode->crtc_htotal / 8) - 1) & 0x3ff)
563 | ((((mode->crtc_hdisplay / 8) - 1) & 0x1ff) << 16));
564
565 hsync_wid = (mode->crtc_hsync_end - mode->crtc_hsync_start) / 8;
566 if (!hsync_wid)
567 hsync_wid = 1;
568 hsync_start = mode->crtc_hsync_start - 8;
569
570 crtc_h_sync_strt_wid = ((hsync_start & 0x1fff)
571 | ((hsync_wid & 0x3f) << 16)
572 | ((mode->flags & DRM_MODE_FLAG_NHSYNC)
573 ? RADEON_CRTC_H_SYNC_POL
574 : 0));
575
576 /* This works for double scan mode. */
577 crtc_v_total_disp = (((mode->crtc_vtotal - 1) & 0xffff)
578 | ((mode->crtc_vdisplay - 1) << 16));
579
580 vsync_wid = mode->crtc_vsync_end - mode->crtc_vsync_start;
581 if (!vsync_wid)
582 vsync_wid = 1;
583
584 crtc_v_sync_strt_wid = (((mode->crtc_vsync_start - 1) & 0xfff)
585 | ((vsync_wid & 0x1f) << 16)
586 | ((mode->flags & DRM_MODE_FLAG_NVSYNC)
587 ? RADEON_CRTC_V_SYNC_POL
588 : 0));
589
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200590 if (radeon_crtc->crtc_id) {
591 uint32_t crtc2_gen_cntl;
592 uint32_t disp2_merge_cntl;
593
Jerome Glisseee2215f2009-11-26 15:58:36 +0100594 /* if TV DAC is enabled for another crtc and keep it enabled */
595 crtc2_gen_cntl = RREG32(RADEON_CRTC2_GEN_CNTL) & 0x00718080;
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200596 crtc2_gen_cntl |= ((format << 8)
597 | RADEON_CRTC2_VSYNC_DIS
598 | RADEON_CRTC2_HSYNC_DIS
599 | RADEON_CRTC2_DISP_DIS
600 | RADEON_CRTC2_DISP_REQ_EN_B
601 | ((mode->flags & DRM_MODE_FLAG_DBLSCAN)
602 ? RADEON_CRTC2_DBL_SCAN_EN
603 : 0)
604 | ((mode->flags & DRM_MODE_FLAG_CSYNC)
605 ? RADEON_CRTC2_CSYNC_EN
606 : 0)
607 | ((mode->flags & DRM_MODE_FLAG_INTERLACE)
608 ? RADEON_CRTC2_INTERLACE_EN
609 : 0));
610
Alex Deucherd805f502010-03-11 10:38:07 -0500611 /* rs4xx chips seem to like to have the crtc enabled when the timing is set */
612 if ((rdev->family == CHIP_RS400) || (rdev->family == CHIP_RS480))
613 crtc2_gen_cntl |= RADEON_CRTC2_EN;
614
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200615 disp2_merge_cntl = RREG32(RADEON_DISP2_MERGE_CNTL);
616 disp2_merge_cntl &= ~RADEON_DISP2_RGB_OFFSET_EN;
617
618 WREG32(RADEON_DISP2_MERGE_CNTL, disp2_merge_cntl);
619 WREG32(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl);
Alex Deucher1b4d7d72009-10-15 01:33:35 -0400620
621 WREG32(RADEON_FP_H2_SYNC_STRT_WID, crtc_h_sync_strt_wid);
622 WREG32(RADEON_FP_V2_SYNC_STRT_WID, crtc_v_sync_strt_wid);
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200623 } else {
624 uint32_t crtc_gen_cntl;
625 uint32_t crtc_ext_cntl;
626 uint32_t disp_merge_cntl;
627
Jerome Glisseee2215f2009-11-26 15:58:36 +0100628 crtc_gen_cntl = RREG32(RADEON_CRTC_GEN_CNTL) & 0x00718000;
629 crtc_gen_cntl |= (RADEON_CRTC_EXT_DISP_EN
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200630 | (format << 8)
631 | RADEON_CRTC_DISP_REQ_EN_B
632 | ((mode->flags & DRM_MODE_FLAG_DBLSCAN)
633 ? RADEON_CRTC_DBL_SCAN_EN
634 : 0)
635 | ((mode->flags & DRM_MODE_FLAG_CSYNC)
636 ? RADEON_CRTC_CSYNC_EN
637 : 0)
638 | ((mode->flags & DRM_MODE_FLAG_INTERLACE)
639 ? RADEON_CRTC_INTERLACE_EN
640 : 0));
641
Alex Deucherd805f502010-03-11 10:38:07 -0500642 /* rs4xx chips seem to like to have the crtc enabled when the timing is set */
643 if ((rdev->family == CHIP_RS400) || (rdev->family == CHIP_RS480))
644 crtc_gen_cntl |= RADEON_CRTC_EN;
645
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200646 crtc_ext_cntl = RREG32(RADEON_CRTC_EXT_CNTL);
647 crtc_ext_cntl |= (RADEON_XCRT_CNT_EN |
648 RADEON_CRTC_VSYNC_DIS |
649 RADEON_CRTC_HSYNC_DIS |
650 RADEON_CRTC_DISPLAY_DIS);
651
652 disp_merge_cntl = RREG32(RADEON_DISP_MERGE_CNTL);
653 disp_merge_cntl &= ~RADEON_DISP_RGB_OFFSET_EN;
654
655 WREG32(RADEON_DISP_MERGE_CNTL, disp_merge_cntl);
656 WREG32(RADEON_CRTC_GEN_CNTL, crtc_gen_cntl);
657 WREG32(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl);
658 }
659
Dave Airlie4ce001a2009-08-13 16:32:14 +1000660 if (is_tv)
661 radeon_legacy_tv_adjust_crtc_reg(encoder, &crtc_h_total_disp,
662 &crtc_h_sync_strt_wid, &crtc_v_total_disp,
663 &crtc_v_sync_strt_wid);
664
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200665 WREG32(RADEON_CRTC_H_TOTAL_DISP + radeon_crtc->crtc_offset, crtc_h_total_disp);
666 WREG32(RADEON_CRTC_H_SYNC_STRT_WID + radeon_crtc->crtc_offset, crtc_h_sync_strt_wid);
667 WREG32(RADEON_CRTC_V_TOTAL_DISP + radeon_crtc->crtc_offset, crtc_v_total_disp);
668 WREG32(RADEON_CRTC_V_SYNC_STRT_WID + radeon_crtc->crtc_offset, crtc_v_sync_strt_wid);
669
670 return true;
671}
672
673static void radeon_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode)
674{
675 struct drm_device *dev = crtc->dev;
676 struct radeon_device *rdev = dev->dev_private;
677 struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
678 struct drm_encoder *encoder;
679 uint32_t feedback_div = 0;
680 uint32_t frac_fb_div = 0;
681 uint32_t reference_div = 0;
682 uint32_t post_divider = 0;
683 uint32_t freq = 0;
684 uint8_t pll_gain;
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200685 bool use_bios_divs = false;
686 /* PLL registers */
687 uint32_t pll_ref_div = 0;
688 uint32_t pll_fb_post_div = 0;
689 uint32_t htotal_cntl = 0;
Dave Airlie4ce001a2009-08-13 16:32:14 +1000690 bool is_tv = false;
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200691 struct radeon_pll *pll;
692
693 struct {
694 int divider;
695 int bitvalue;
696 } *post_div, post_divs[] = {
697 /* From RAGE 128 VR/RAGE 128 GL Register
698 * Reference Manual (Technical Reference
699 * Manual P/N RRG-G04100-C Rev. 0.04), page
700 * 3-17 (PLL_DIV_[3:0]).
701 */
702 { 1, 0 }, /* VCLK_SRC */
703 { 2, 1 }, /* VCLK_SRC/2 */
704 { 4, 2 }, /* VCLK_SRC/4 */
705 { 8, 3 }, /* VCLK_SRC/8 */
706 { 3, 4 }, /* VCLK_SRC/3 */
707 { 16, 5 }, /* VCLK_SRC/16 */
708 { 6, 6 }, /* VCLK_SRC/6 */
709 { 12, 7 }, /* VCLK_SRC/12 */
710 { 0, 0 }
711 };
712
713 if (radeon_crtc->crtc_id)
714 pll = &rdev->clock.p2pll;
715 else
716 pll = &rdev->clock.p1pll;
717
Alex Deucherfc103322010-01-19 17:16:10 -0500718 pll->flags = RADEON_PLL_LEGACY;
Alex Deucher383be5d2010-02-23 03:24:38 -0500719 if (radeon_new_pll == 1)
720 pll->algo = PLL_ALGO_NEW;
721 else
722 pll->algo = PLL_ALGO_LEGACY;
Alex Deucherfc103322010-01-19 17:16:10 -0500723
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200724 if (mode->clock > 200000) /* range limits??? */
Alex Deucherfc103322010-01-19 17:16:10 -0500725 pll->flags |= RADEON_PLL_PREFER_HIGH_FB_DIV;
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200726 else
Alex Deucherfc103322010-01-19 17:16:10 -0500727 pll->flags |= RADEON_PLL_PREFER_LOW_REF_DIV;
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200728
729 list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
730 if (encoder->crtc == crtc) {
Dave Airlie4ce001a2009-08-13 16:32:14 +1000731 struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
732
733 if (radeon_encoder->active_device & ATOM_DEVICE_TV_SUPPORT) {
734 is_tv = true;
735 break;
736 }
737
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200738 if (encoder->encoder_type != DRM_MODE_ENCODER_DAC)
Alex Deucherfc103322010-01-19 17:16:10 -0500739 pll->flags |= RADEON_PLL_NO_ODD_POST_DIV;
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200740 if (encoder->encoder_type == DRM_MODE_ENCODER_LVDS) {
Alex Deucher4c4f5412009-12-02 00:59:37 -0500741 if (!rdev->is_atom_bios) {
742 struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
743 struct radeon_encoder_lvds *lvds = (struct radeon_encoder_lvds *)radeon_encoder->enc_priv;
744 if (lvds) {
745 if (lvds->use_bios_dividers) {
746 pll_ref_div = lvds->panel_ref_divider;
747 pll_fb_post_div = (lvds->panel_fb_divider |
748 (lvds->panel_post_divider << 16));
749 htotal_cntl = 0;
750 use_bios_divs = true;
751 }
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200752 }
753 }
Alex Deucherfc103322010-01-19 17:16:10 -0500754 pll->flags |= RADEON_PLL_USE_REF_DIV;
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200755 }
756 }
757 }
758
759 DRM_DEBUG("\n");
760
761 if (!use_bios_divs) {
762 radeon_compute_pll(pll, mode->clock,
763 &freq, &feedback_div, &frac_fb_div,
Alex Deucherfc103322010-01-19 17:16:10 -0500764 &reference_div, &post_divider);
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200765
766 for (post_div = &post_divs[0]; post_div->divider; ++post_div) {
767 if (post_div->divider == post_divider)
768 break;
769 }
770
771 if (!post_div->divider)
772 post_div = &post_divs[0];
773
774 DRM_DEBUG("dc=%u, fd=%d, rd=%d, pd=%d\n",
775 (unsigned)freq,
776 feedback_div,
777 reference_div,
778 post_divider);
779
780 pll_ref_div = reference_div;
781#if defined(__powerpc__) && (0) /* TODO */
782 /* apparently programming this otherwise causes a hang??? */
783 if (info->MacModel == RADEON_MAC_IBOOK)
784 pll_fb_post_div = 0x000600ad;
785 else
786#endif
787 pll_fb_post_div = (feedback_div | (post_div->bitvalue << 16));
788
789 htotal_cntl = mode->htotal & 0x7;
790
791 }
792
793 pll_gain = radeon_compute_pll_gain(pll->reference_freq,
794 pll_ref_div & 0x3ff,
795 pll_fb_post_div & 0x7ff);
796
797 if (radeon_crtc->crtc_id) {
798 uint32_t pixclks_cntl = ((RREG32_PLL(RADEON_PIXCLKS_CNTL) &
799 ~(RADEON_PIX2CLK_SRC_SEL_MASK)) |
800 RADEON_PIX2CLK_SRC_SEL_P2PLLCLK);
801
Dave Airlie4ce001a2009-08-13 16:32:14 +1000802 if (is_tv) {
803 radeon_legacy_tv_adjust_pll2(encoder, &htotal_cntl,
804 &pll_ref_div, &pll_fb_post_div,
805 &pixclks_cntl);
806 }
807
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200808 WREG32_PLL_P(RADEON_PIXCLKS_CNTL,
809 RADEON_PIX2CLK_SRC_SEL_CPUCLK,
810 ~(RADEON_PIX2CLK_SRC_SEL_MASK));
811
812 WREG32_PLL_P(RADEON_P2PLL_CNTL,
813 RADEON_P2PLL_RESET
814 | RADEON_P2PLL_ATOMIC_UPDATE_EN
815 | ((uint32_t)pll_gain << RADEON_P2PLL_PVG_SHIFT),
816 ~(RADEON_P2PLL_RESET
817 | RADEON_P2PLL_ATOMIC_UPDATE_EN
818 | RADEON_P2PLL_PVG_MASK));
819
820 WREG32_PLL_P(RADEON_P2PLL_REF_DIV,
821 pll_ref_div,
822 ~RADEON_P2PLL_REF_DIV_MASK);
823
824 WREG32_PLL_P(RADEON_P2PLL_DIV_0,
825 pll_fb_post_div,
826 ~RADEON_P2PLL_FB0_DIV_MASK);
827
828 WREG32_PLL_P(RADEON_P2PLL_DIV_0,
829 pll_fb_post_div,
830 ~RADEON_P2PLL_POST0_DIV_MASK);
831
832 radeon_pll2_write_update(dev);
833 radeon_pll2_wait_for_read_update_complete(dev);
834
835 WREG32_PLL(RADEON_HTOTAL2_CNTL, htotal_cntl);
836
837 WREG32_PLL_P(RADEON_P2PLL_CNTL,
838 0,
839 ~(RADEON_P2PLL_RESET
840 | RADEON_P2PLL_SLEEP
841 | RADEON_P2PLL_ATOMIC_UPDATE_EN));
842
843 DRM_DEBUG("Wrote2: 0x%08x 0x%08x 0x%08x (0x%08x)\n",
844 (unsigned)pll_ref_div,
845 (unsigned)pll_fb_post_div,
846 (unsigned)htotal_cntl,
847 RREG32_PLL(RADEON_P2PLL_CNTL));
848 DRM_DEBUG("Wrote2: rd=%u, fd=%u, pd=%u\n",
849 (unsigned)pll_ref_div & RADEON_P2PLL_REF_DIV_MASK,
850 (unsigned)pll_fb_post_div & RADEON_P2PLL_FB0_DIV_MASK,
851 (unsigned)((pll_fb_post_div &
852 RADEON_P2PLL_POST0_DIV_MASK) >> 16));
853
854 mdelay(50); /* Let the clock to lock */
855
856 WREG32_PLL_P(RADEON_PIXCLKS_CNTL,
857 RADEON_PIX2CLK_SRC_SEL_P2PLLCLK,
858 ~(RADEON_PIX2CLK_SRC_SEL_MASK));
859
860 WREG32_PLL(RADEON_PIXCLKS_CNTL, pixclks_cntl);
861 } else {
Dave Airlie4ce001a2009-08-13 16:32:14 +1000862 uint32_t pixclks_cntl;
863
864
865 if (is_tv) {
866 pixclks_cntl = RREG32_PLL(RADEON_PIXCLKS_CNTL);
867 radeon_legacy_tv_adjust_pll1(encoder, &htotal_cntl, &pll_ref_div,
868 &pll_fb_post_div, &pixclks_cntl);
869 }
870
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200871 if (rdev->flags & RADEON_IS_MOBILITY) {
872 /* A temporal workaround for the occational blanking on certain laptop panels.
873 This appears to related to the PLL divider registers (fail to lock?).
874 It occurs even when all dividers are the same with their old settings.
875 In this case we really don't need to fiddle with PLL registers.
876 By doing this we can avoid the blanking problem with some panels.
877 */
878 if ((pll_ref_div == (RREG32_PLL(RADEON_PPLL_REF_DIV) & RADEON_PPLL_REF_DIV_MASK)) &&
879 (pll_fb_post_div == (RREG32_PLL(RADEON_PPLL_DIV_3) &
880 (RADEON_PPLL_POST3_DIV_MASK | RADEON_PPLL_FB3_DIV_MASK)))) {
881 WREG32_P(RADEON_CLOCK_CNTL_INDEX,
882 RADEON_PLL_DIV_SEL,
883 ~(RADEON_PLL_DIV_SEL));
884 r100_pll_errata_after_index(rdev);
885 return;
886 }
887 }
888
889 WREG32_PLL_P(RADEON_VCLK_ECP_CNTL,
890 RADEON_VCLK_SRC_SEL_CPUCLK,
891 ~(RADEON_VCLK_SRC_SEL_MASK));
892 WREG32_PLL_P(RADEON_PPLL_CNTL,
893 RADEON_PPLL_RESET
894 | RADEON_PPLL_ATOMIC_UPDATE_EN
895 | RADEON_PPLL_VGA_ATOMIC_UPDATE_EN
896 | ((uint32_t)pll_gain << RADEON_PPLL_PVG_SHIFT),
897 ~(RADEON_PPLL_RESET
898 | RADEON_PPLL_ATOMIC_UPDATE_EN
899 | RADEON_PPLL_VGA_ATOMIC_UPDATE_EN
900 | RADEON_PPLL_PVG_MASK));
901
902 WREG32_P(RADEON_CLOCK_CNTL_INDEX,
903 RADEON_PLL_DIV_SEL,
904 ~(RADEON_PLL_DIV_SEL));
905 r100_pll_errata_after_index(rdev);
906
907 if (ASIC_IS_R300(rdev) ||
908 (rdev->family == CHIP_RS300) ||
909 (rdev->family == CHIP_RS400) ||
910 (rdev->family == CHIP_RS480)) {
911 if (pll_ref_div & R300_PPLL_REF_DIV_ACC_MASK) {
912 /* When restoring console mode, use saved PPLL_REF_DIV
913 * setting.
914 */
915 WREG32_PLL_P(RADEON_PPLL_REF_DIV,
916 pll_ref_div,
917 0);
918 } else {
919 /* R300 uses ref_div_acc field as real ref divider */
920 WREG32_PLL_P(RADEON_PPLL_REF_DIV,
921 (pll_ref_div << R300_PPLL_REF_DIV_ACC_SHIFT),
922 ~R300_PPLL_REF_DIV_ACC_MASK);
923 }
924 } else
925 WREG32_PLL_P(RADEON_PPLL_REF_DIV,
926 pll_ref_div,
927 ~RADEON_PPLL_REF_DIV_MASK);
928
929 WREG32_PLL_P(RADEON_PPLL_DIV_3,
930 pll_fb_post_div,
931 ~RADEON_PPLL_FB3_DIV_MASK);
932
933 WREG32_PLL_P(RADEON_PPLL_DIV_3,
934 pll_fb_post_div,
935 ~RADEON_PPLL_POST3_DIV_MASK);
936
937 radeon_pll_write_update(dev);
938 radeon_pll_wait_for_read_update_complete(dev);
939
940 WREG32_PLL(RADEON_HTOTAL_CNTL, htotal_cntl);
941
942 WREG32_PLL_P(RADEON_PPLL_CNTL,
943 0,
944 ~(RADEON_PPLL_RESET
945 | RADEON_PPLL_SLEEP
946 | RADEON_PPLL_ATOMIC_UPDATE_EN
947 | RADEON_PPLL_VGA_ATOMIC_UPDATE_EN));
948
949 DRM_DEBUG("Wrote: 0x%08x 0x%08x 0x%08x (0x%08x)\n",
950 pll_ref_div,
951 pll_fb_post_div,
952 (unsigned)htotal_cntl,
953 RREG32_PLL(RADEON_PPLL_CNTL));
954 DRM_DEBUG("Wrote: rd=%d, fd=%d, pd=%d\n",
955 pll_ref_div & RADEON_PPLL_REF_DIV_MASK,
956 pll_fb_post_div & RADEON_PPLL_FB3_DIV_MASK,
957 (pll_fb_post_div & RADEON_PPLL_POST3_DIV_MASK) >> 16);
958
959 mdelay(50); /* Let the clock to lock */
960
961 WREG32_PLL_P(RADEON_VCLK_ECP_CNTL,
962 RADEON_VCLK_SRC_SEL_PPLLCLK,
963 ~(RADEON_VCLK_SRC_SEL_MASK));
964
Dave Airlie4ce001a2009-08-13 16:32:14 +1000965 if (is_tv)
966 WREG32_PLL(RADEON_PIXCLKS_CNTL, pixclks_cntl);
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200967 }
968}
969
970static bool radeon_crtc_mode_fixup(struct drm_crtc *crtc,
971 struct drm_display_mode *mode,
972 struct drm_display_mode *adjusted_mode)
973{
Alex Deucher03214bd52010-03-16 17:42:46 -0400974 struct drm_device *dev = crtc->dev;
975 struct radeon_device *rdev = dev->dev_private;
976
977 /* adjust pm to upcoming mode change */
978 radeon_pm_compute_clocks(rdev);
979
Jerome Glissec93bb852009-07-13 21:04:08 +0200980 if (!radeon_crtc_scaling_mode_fixup(crtc, mode, adjusted_mode))
981 return false;
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200982 return true;
983}
984
985static int radeon_crtc_mode_set(struct drm_crtc *crtc,
986 struct drm_display_mode *mode,
987 struct drm_display_mode *adjusted_mode,
988 int x, int y, struct drm_framebuffer *old_fb)
989{
Jerome Glissec93bb852009-07-13 21:04:08 +0200990 struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200991
992 /* TODO TV */
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200993 radeon_crtc_set_base(crtc, x, y, old_fb);
994 radeon_set_crtc_timing(crtc, adjusted_mode);
995 radeon_set_pll(crtc, adjusted_mode);
Alex Deucher6b02af12009-12-04 10:40:41 -0500996 radeon_overscan_setup(crtc, adjusted_mode);
Jerome Glissec93bb852009-07-13 21:04:08 +0200997 if (radeon_crtc->crtc_id == 0) {
Alex Deucher310a82c2009-12-17 01:24:59 -0500998 radeon_legacy_rmx_mode_set(crtc, adjusted_mode);
Jerome Glissec93bb852009-07-13 21:04:08 +0200999 } else {
1000 if (radeon_crtc->rmx_type != RMX_OFF) {
1001 /* FIXME: only first crtc has rmx what should we
1002 * do ?
1003 */
1004 DRM_ERROR("Mode need scaling but only first crtc can do that.\n");
1005 }
1006 }
Jerome Glisse771fe6b2009-06-05 14:42:42 +02001007 return 0;
1008}
1009
1010static void radeon_crtc_prepare(struct drm_crtc *crtc)
1011{
Pierre Ossmanec51efa2009-11-30 21:15:44 +01001012 struct drm_device *dev = crtc->dev;
1013 struct drm_crtc *crtci;
1014
1015 /*
1016 * The hardware wedges sometimes if you reconfigure one CRTC
1017 * whilst another is running (see fdo bug #24611).
1018 */
1019 list_for_each_entry(crtci, &dev->mode_config.crtc_list, head)
1020 radeon_crtc_dpms(crtci, DRM_MODE_DPMS_OFF);
Jerome Glisse771fe6b2009-06-05 14:42:42 +02001021}
1022
1023static void radeon_crtc_commit(struct drm_crtc *crtc)
1024{
Pierre Ossmanec51efa2009-11-30 21:15:44 +01001025 struct drm_device *dev = crtc->dev;
1026 struct drm_crtc *crtci;
1027
1028 /*
1029 * Reenable the CRTCs that should be running.
1030 */
1031 list_for_each_entry(crtci, &dev->mode_config.crtc_list, head) {
1032 if (crtci->enabled)
1033 radeon_crtc_dpms(crtci, DRM_MODE_DPMS_ON);
1034 }
Jerome Glisse771fe6b2009-06-05 14:42:42 +02001035}
1036
1037static const struct drm_crtc_helper_funcs legacy_helper_funcs = {
1038 .dpms = radeon_crtc_dpms,
1039 .mode_fixup = radeon_crtc_mode_fixup,
1040 .mode_set = radeon_crtc_mode_set,
1041 .mode_set_base = radeon_crtc_set_base,
1042 .prepare = radeon_crtc_prepare,
1043 .commit = radeon_crtc_commit,
Dave Airlie068143d2009-10-05 09:58:02 +10001044 .load_lut = radeon_crtc_load_lut,
Jerome Glisse771fe6b2009-06-05 14:42:42 +02001045};
1046
1047
1048void radeon_legacy_init_crtc(struct drm_device *dev,
1049 struct radeon_crtc *radeon_crtc)
1050{
1051 if (radeon_crtc->crtc_id == 1)
1052 radeon_crtc->crtc_offset = RADEON_CRTC2_H_TOTAL_DISP - RADEON_CRTC_H_TOTAL_DISP;
1053 drm_crtc_helper_add(&radeon_crtc->base, &legacy_helper_funcs);
1054}