1 1.3 riastrad /* $NetBSD: radeon_legacy_crtc.c,v 1.4 2021/12/18 23:45:43 riastradh Exp $ */ 2 1.3 riastrad 3 1.1 riastrad /* 4 1.1 riastrad * Copyright 2007-8 Advanced Micro Devices, Inc. 5 1.1 riastrad * Copyright 2008 Red Hat Inc. 6 1.1 riastrad * 7 1.1 riastrad * Permission is hereby granted, free of charge, to any person obtaining a 8 1.1 riastrad * copy of this software and associated documentation files (the "Software"), 9 1.1 riastrad * to deal in the Software without restriction, including without limitation 10 1.1 riastrad * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11 1.1 riastrad * and/or sell copies of the Software, and to permit persons to whom the 12 1.1 riastrad * Software is furnished to do so, subject to the following conditions: 13 1.1 riastrad * 14 1.1 riastrad * The above copyright notice and this permission notice shall be included in 15 1.1 riastrad * all copies or substantial portions of the Software. 16 1.1 riastrad * 17 1.1 riastrad * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 1.1 riastrad * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 1.1 riastrad * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 1.1 riastrad * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 21 1.1 riastrad * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 22 1.1 riastrad * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23 1.1 riastrad * OTHER DEALINGS IN THE SOFTWARE. 24 1.1 riastrad * 25 1.1 riastrad * Authors: Dave Airlie 26 1.1 riastrad * Alex Deucher 27 1.1 riastrad */ 28 1.4 riastrad 29 1.3 riastrad #include <sys/cdefs.h> 30 1.3 riastrad __KERNEL_RCSID(0, "$NetBSD: radeon_legacy_crtc.c,v 1.4 2021/12/18 23:45:43 riastradh Exp $"); 31 1.3 riastrad 32 1.1 riastrad #include <drm/drm_crtc_helper.h> 33 1.4 riastrad #include <drm/drm_fb_helper.h> 34 1.4 riastrad #include <drm/drm_fixed.h> 35 1.4 riastrad #include <drm/drm_fourcc.h> 36 1.4 riastrad #include <drm/drm_vblank.h> 37 1.1 riastrad #include <drm/radeon_drm.h> 38 1.4 riastrad 39 1.4 riastrad #include "atom.h" 40 1.1 riastrad #include "radeon.h" 41 1.1 riastrad 42 1.1 riastrad static void radeon_overscan_setup(struct drm_crtc *crtc, 43 1.1 riastrad struct drm_display_mode *mode) 44 1.1 riastrad { 45 1.1 riastrad struct drm_device *dev = crtc->dev; 46 1.1 riastrad struct radeon_device *rdev = dev->dev_private; 47 1.1 riastrad struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); 48 1.1 riastrad 49 1.1 riastrad WREG32(RADEON_OVR_CLR + radeon_crtc->crtc_offset, 0); 50 1.1 riastrad WREG32(RADEON_OVR_WID_LEFT_RIGHT + radeon_crtc->crtc_offset, 0); 51 1.1 riastrad WREG32(RADEON_OVR_WID_TOP_BOTTOM + radeon_crtc->crtc_offset, 0); 52 1.1 riastrad } 53 1.1 riastrad 54 1.1 riastrad static void radeon_legacy_rmx_mode_set(struct drm_crtc *crtc, 55 1.1 riastrad struct drm_display_mode *mode) 56 1.1 riastrad { 57 1.1 riastrad struct drm_device *dev = crtc->dev; 58 1.1 riastrad struct radeon_device *rdev = dev->dev_private; 59 1.1 riastrad struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); 60 1.1 riastrad int xres = mode->hdisplay; 61 1.1 riastrad int yres = mode->vdisplay; 62 1.1 riastrad bool hscale = true, vscale = true; 63 1.1 riastrad int hsync_wid; 64 1.1 riastrad int vsync_wid; 65 1.1 riastrad int hsync_start; 66 1.1 riastrad int blank_width; 67 1.1 riastrad u32 scale, inc, crtc_more_cntl; 68 1.1 riastrad u32 fp_horz_stretch, fp_vert_stretch, fp_horz_vert_active; 69 1.1 riastrad u32 fp_h_sync_strt_wid, fp_crtc_h_total_disp; 70 1.1 riastrad u32 fp_v_sync_strt_wid, fp_crtc_v_total_disp; 71 1.1 riastrad struct drm_display_mode *native_mode = &radeon_crtc->native_mode; 72 1.1 riastrad 73 1.1 riastrad fp_vert_stretch = RREG32(RADEON_FP_VERT_STRETCH) & 74 1.1 riastrad (RADEON_VERT_STRETCH_RESERVED | 75 1.1 riastrad RADEON_VERT_AUTO_RATIO_INC); 76 1.1 riastrad fp_horz_stretch = RREG32(RADEON_FP_HORZ_STRETCH) & 77 1.1 riastrad (RADEON_HORZ_FP_LOOP_STRETCH | 78 1.1 riastrad RADEON_HORZ_AUTO_RATIO_INC); 79 1.1 riastrad 80 1.1 riastrad crtc_more_cntl = 0; 81 1.1 riastrad if ((rdev->family == CHIP_RS100) || 82 1.1 riastrad (rdev->family == CHIP_RS200)) { 83 1.1 riastrad /* This is to workaround the asic bug for RMX, some versions 84 1.1 riastrad of BIOS dosen't have this register initialized correctly. */ 85 1.1 riastrad crtc_more_cntl |= RADEON_CRTC_H_CUTOFF_ACTIVE_EN; 86 1.1 riastrad } 87 1.1 riastrad 88 1.1 riastrad 89 1.1 riastrad fp_crtc_h_total_disp = ((((mode->crtc_htotal / 8) - 1) & 0x3ff) 90 1.1 riastrad | ((((mode->crtc_hdisplay / 8) - 1) & 0x1ff) << 16)); 91 1.1 riastrad 92 1.1 riastrad hsync_wid = (mode->crtc_hsync_end - mode->crtc_hsync_start) / 8; 93 1.1 riastrad if (!hsync_wid) 94 1.1 riastrad hsync_wid = 1; 95 1.1 riastrad hsync_start = mode->crtc_hsync_start - 8; 96 1.1 riastrad 97 1.1 riastrad fp_h_sync_strt_wid = ((hsync_start & 0x1fff) 98 1.1 riastrad | ((hsync_wid & 0x3f) << 16) 99 1.1 riastrad | ((mode->flags & DRM_MODE_FLAG_NHSYNC) 100 1.1 riastrad ? RADEON_CRTC_H_SYNC_POL 101 1.1 riastrad : 0)); 102 1.1 riastrad 103 1.1 riastrad fp_crtc_v_total_disp = (((mode->crtc_vtotal - 1) & 0xffff) 104 1.1 riastrad | ((mode->crtc_vdisplay - 1) << 16)); 105 1.1 riastrad 106 1.1 riastrad vsync_wid = mode->crtc_vsync_end - mode->crtc_vsync_start; 107 1.1 riastrad if (!vsync_wid) 108 1.1 riastrad vsync_wid = 1; 109 1.1 riastrad 110 1.1 riastrad fp_v_sync_strt_wid = (((mode->crtc_vsync_start - 1) & 0xfff) 111 1.1 riastrad | ((vsync_wid & 0x1f) << 16) 112 1.1 riastrad | ((mode->flags & DRM_MODE_FLAG_NVSYNC) 113 1.1 riastrad ? RADEON_CRTC_V_SYNC_POL 114 1.1 riastrad : 0)); 115 1.1 riastrad 116 1.1 riastrad fp_horz_vert_active = 0; 117 1.1 riastrad 118 1.1 riastrad if (native_mode->hdisplay == 0 || 119 1.1 riastrad native_mode->vdisplay == 0) { 120 1.1 riastrad hscale = false; 121 1.1 riastrad vscale = false; 122 1.1 riastrad } else { 123 1.1 riastrad if (xres > native_mode->hdisplay) 124 1.1 riastrad xres = native_mode->hdisplay; 125 1.1 riastrad if (yres > native_mode->vdisplay) 126 1.1 riastrad yres = native_mode->vdisplay; 127 1.1 riastrad 128 1.1 riastrad if (xres == native_mode->hdisplay) 129 1.1 riastrad hscale = false; 130 1.1 riastrad if (yres == native_mode->vdisplay) 131 1.1 riastrad vscale = false; 132 1.1 riastrad } 133 1.1 riastrad 134 1.1 riastrad switch (radeon_crtc->rmx_type) { 135 1.1 riastrad case RMX_FULL: 136 1.1 riastrad case RMX_ASPECT: 137 1.1 riastrad if (!hscale) 138 1.1 riastrad fp_horz_stretch |= ((xres/8-1) << 16); 139 1.1 riastrad else { 140 1.1 riastrad inc = (fp_horz_stretch & RADEON_HORZ_AUTO_RATIO_INC) ? 1 : 0; 141 1.1 riastrad scale = ((xres + inc) * RADEON_HORZ_STRETCH_RATIO_MAX) 142 1.1 riastrad / native_mode->hdisplay + 1; 143 1.1 riastrad fp_horz_stretch |= (((scale) & RADEON_HORZ_STRETCH_RATIO_MASK) | 144 1.1 riastrad RADEON_HORZ_STRETCH_BLEND | 145 1.1 riastrad RADEON_HORZ_STRETCH_ENABLE | 146 1.1 riastrad ((native_mode->hdisplay/8-1) << 16)); 147 1.1 riastrad } 148 1.1 riastrad 149 1.1 riastrad if (!vscale) 150 1.1 riastrad fp_vert_stretch |= ((yres-1) << 12); 151 1.1 riastrad else { 152 1.1 riastrad inc = (fp_vert_stretch & RADEON_VERT_AUTO_RATIO_INC) ? 1 : 0; 153 1.1 riastrad scale = ((yres + inc) * RADEON_VERT_STRETCH_RATIO_MAX) 154 1.1 riastrad / native_mode->vdisplay + 1; 155 1.1 riastrad fp_vert_stretch |= (((scale) & RADEON_VERT_STRETCH_RATIO_MASK) | 156 1.1 riastrad RADEON_VERT_STRETCH_ENABLE | 157 1.1 riastrad RADEON_VERT_STRETCH_BLEND | 158 1.1 riastrad ((native_mode->vdisplay-1) << 12)); 159 1.1 riastrad } 160 1.1 riastrad break; 161 1.1 riastrad case RMX_CENTER: 162 1.1 riastrad fp_horz_stretch |= ((xres/8-1) << 16); 163 1.1 riastrad fp_vert_stretch |= ((yres-1) << 12); 164 1.1 riastrad 165 1.1 riastrad crtc_more_cntl |= (RADEON_CRTC_AUTO_HORZ_CENTER_EN | 166 1.1 riastrad RADEON_CRTC_AUTO_VERT_CENTER_EN); 167 1.1 riastrad 168 1.1 riastrad blank_width = (mode->crtc_hblank_end - mode->crtc_hblank_start) / 8; 169 1.1 riastrad if (blank_width > 110) 170 1.1 riastrad blank_width = 110; 171 1.1 riastrad 172 1.1 riastrad fp_crtc_h_total_disp = (((blank_width) & 0x3ff) 173 1.1 riastrad | ((((mode->crtc_hdisplay / 8) - 1) & 0x1ff) << 16)); 174 1.1 riastrad 175 1.1 riastrad hsync_wid = (mode->crtc_hsync_end - mode->crtc_hsync_start) / 8; 176 1.1 riastrad if (!hsync_wid) 177 1.1 riastrad hsync_wid = 1; 178 1.1 riastrad 179 1.1 riastrad fp_h_sync_strt_wid = ((((mode->crtc_hsync_start - mode->crtc_hblank_start) / 8) & 0x1fff) 180 1.1 riastrad | ((hsync_wid & 0x3f) << 16) 181 1.1 riastrad | ((mode->flags & DRM_MODE_FLAG_NHSYNC) 182 1.1 riastrad ? RADEON_CRTC_H_SYNC_POL 183 1.1 riastrad : 0)); 184 1.1 riastrad 185 1.1 riastrad fp_crtc_v_total_disp = (((mode->crtc_vblank_end - mode->crtc_vblank_start) & 0xffff) 186 1.1 riastrad | ((mode->crtc_vdisplay - 1) << 16)); 187 1.1 riastrad 188 1.1 riastrad vsync_wid = mode->crtc_vsync_end - mode->crtc_vsync_start; 189 1.1 riastrad if (!vsync_wid) 190 1.1 riastrad vsync_wid = 1; 191 1.1 riastrad 192 1.1 riastrad fp_v_sync_strt_wid = ((((mode->crtc_vsync_start - mode->crtc_vblank_start) & 0xfff) 193 1.1 riastrad | ((vsync_wid & 0x1f) << 16) 194 1.1 riastrad | ((mode->flags & DRM_MODE_FLAG_NVSYNC) 195 1.1 riastrad ? RADEON_CRTC_V_SYNC_POL 196 1.1 riastrad : 0))); 197 1.1 riastrad 198 1.1 riastrad fp_horz_vert_active = (((native_mode->vdisplay) & 0xfff) | 199 1.1 riastrad (((native_mode->hdisplay / 8) & 0x1ff) << 16)); 200 1.1 riastrad break; 201 1.1 riastrad case RMX_OFF: 202 1.1 riastrad default: 203 1.1 riastrad fp_horz_stretch |= ((xres/8-1) << 16); 204 1.1 riastrad fp_vert_stretch |= ((yres-1) << 12); 205 1.1 riastrad break; 206 1.1 riastrad } 207 1.1 riastrad 208 1.1 riastrad WREG32(RADEON_FP_HORZ_STRETCH, fp_horz_stretch); 209 1.1 riastrad WREG32(RADEON_FP_VERT_STRETCH, fp_vert_stretch); 210 1.1 riastrad WREG32(RADEON_CRTC_MORE_CNTL, crtc_more_cntl); 211 1.1 riastrad WREG32(RADEON_FP_HORZ_VERT_ACTIVE, fp_horz_vert_active); 212 1.1 riastrad WREG32(RADEON_FP_H_SYNC_STRT_WID, fp_h_sync_strt_wid); 213 1.1 riastrad WREG32(RADEON_FP_V_SYNC_STRT_WID, fp_v_sync_strt_wid); 214 1.1 riastrad WREG32(RADEON_FP_CRTC_H_TOTAL_DISP, fp_crtc_h_total_disp); 215 1.1 riastrad WREG32(RADEON_FP_CRTC_V_TOTAL_DISP, fp_crtc_v_total_disp); 216 1.1 riastrad } 217 1.1 riastrad 218 1.1 riastrad static void radeon_pll_wait_for_read_update_complete(struct drm_device *dev) 219 1.1 riastrad { 220 1.1 riastrad struct radeon_device *rdev = dev->dev_private; 221 1.1 riastrad int i = 0; 222 1.1 riastrad 223 1.1 riastrad /* FIXME: Certain revisions of R300 can't recover here. Not sure of 224 1.1 riastrad the cause yet, but this workaround will mask the problem for now. 225 1.1 riastrad Other chips usually will pass at the very first test, so the 226 1.1 riastrad workaround shouldn't have any effect on them. */ 227 1.1 riastrad for (i = 0; 228 1.1 riastrad (i < 10000 && 229 1.1 riastrad RREG32_PLL(RADEON_PPLL_REF_DIV) & RADEON_PPLL_ATOMIC_UPDATE_R); 230 1.1 riastrad i++); 231 1.1 riastrad } 232 1.1 riastrad 233 1.1 riastrad static void radeon_pll_write_update(struct drm_device *dev) 234 1.1 riastrad { 235 1.1 riastrad struct radeon_device *rdev = dev->dev_private; 236 1.1 riastrad 237 1.1 riastrad while (RREG32_PLL(RADEON_PPLL_REF_DIV) & RADEON_PPLL_ATOMIC_UPDATE_R); 238 1.1 riastrad 239 1.1 riastrad WREG32_PLL_P(RADEON_PPLL_REF_DIV, 240 1.1 riastrad RADEON_PPLL_ATOMIC_UPDATE_W, 241 1.1 riastrad ~(RADEON_PPLL_ATOMIC_UPDATE_W)); 242 1.1 riastrad } 243 1.1 riastrad 244 1.1 riastrad static void radeon_pll2_wait_for_read_update_complete(struct drm_device *dev) 245 1.1 riastrad { 246 1.1 riastrad struct radeon_device *rdev = dev->dev_private; 247 1.1 riastrad int i = 0; 248 1.1 riastrad 249 1.1 riastrad 250 1.1 riastrad /* FIXME: Certain revisions of R300 can't recover here. Not sure of 251 1.1 riastrad the cause yet, but this workaround will mask the problem for now. 252 1.1 riastrad Other chips usually will pass at the very first test, so the 253 1.1 riastrad workaround shouldn't have any effect on them. */ 254 1.1 riastrad for (i = 0; 255 1.1 riastrad (i < 10000 && 256 1.1 riastrad RREG32_PLL(RADEON_P2PLL_REF_DIV) & RADEON_P2PLL_ATOMIC_UPDATE_R); 257 1.1 riastrad i++); 258 1.1 riastrad } 259 1.1 riastrad 260 1.1 riastrad static void radeon_pll2_write_update(struct drm_device *dev) 261 1.1 riastrad { 262 1.1 riastrad struct radeon_device *rdev = dev->dev_private; 263 1.1 riastrad 264 1.1 riastrad while (RREG32_PLL(RADEON_P2PLL_REF_DIV) & RADEON_P2PLL_ATOMIC_UPDATE_R); 265 1.1 riastrad 266 1.1 riastrad WREG32_PLL_P(RADEON_P2PLL_REF_DIV, 267 1.1 riastrad RADEON_P2PLL_ATOMIC_UPDATE_W, 268 1.1 riastrad ~(RADEON_P2PLL_ATOMIC_UPDATE_W)); 269 1.1 riastrad } 270 1.1 riastrad 271 1.1 riastrad static uint8_t radeon_compute_pll_gain(uint16_t ref_freq, uint16_t ref_div, 272 1.1 riastrad uint16_t fb_div) 273 1.1 riastrad { 274 1.1 riastrad unsigned int vcoFreq; 275 1.1 riastrad 276 1.1 riastrad if (!ref_div) 277 1.1 riastrad return 1; 278 1.1 riastrad 279 1.1 riastrad vcoFreq = ((unsigned)ref_freq * fb_div) / ref_div; 280 1.1 riastrad 281 1.1 riastrad /* 282 1.1 riastrad * This is horribly crude: the VCO frequency range is divided into 283 1.1 riastrad * 3 parts, each part having a fixed PLL gain value. 284 1.1 riastrad */ 285 1.1 riastrad if (vcoFreq >= 30000) 286 1.1 riastrad /* 287 1.1 riastrad * [300..max] MHz : 7 288 1.1 riastrad */ 289 1.1 riastrad return 7; 290 1.1 riastrad else if (vcoFreq >= 18000) 291 1.1 riastrad /* 292 1.1 riastrad * [180..300) MHz : 4 293 1.1 riastrad */ 294 1.1 riastrad return 4; 295 1.1 riastrad else 296 1.1 riastrad /* 297 1.1 riastrad * [0..180) MHz : 1 298 1.1 riastrad */ 299 1.1 riastrad return 1; 300 1.1 riastrad } 301 1.1 riastrad 302 1.1 riastrad static void radeon_crtc_dpms(struct drm_crtc *crtc, int mode) 303 1.1 riastrad { 304 1.1 riastrad struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); 305 1.1 riastrad struct drm_device *dev = crtc->dev; 306 1.1 riastrad struct radeon_device *rdev = dev->dev_private; 307 1.1 riastrad uint32_t crtc_ext_cntl = 0; 308 1.1 riastrad uint32_t mask; 309 1.1 riastrad 310 1.1 riastrad if (radeon_crtc->crtc_id) 311 1.1 riastrad mask = (RADEON_CRTC2_DISP_DIS | 312 1.1 riastrad RADEON_CRTC2_VSYNC_DIS | 313 1.1 riastrad RADEON_CRTC2_HSYNC_DIS | 314 1.1 riastrad RADEON_CRTC2_DISP_REQ_EN_B); 315 1.1 riastrad else 316 1.1 riastrad mask = (RADEON_CRTC_DISPLAY_DIS | 317 1.1 riastrad RADEON_CRTC_VSYNC_DIS | 318 1.1 riastrad RADEON_CRTC_HSYNC_DIS); 319 1.1 riastrad 320 1.1 riastrad /* 321 1.1 riastrad * On all dual CRTC GPUs this bit controls the CRTC of the primary DAC. 322 1.1 riastrad * Therefore it is set in the DAC DMPS function. 323 1.1 riastrad * This is different for GPU's with a single CRTC but a primary and a 324 1.1 riastrad * TV DAC: here it controls the single CRTC no matter where it is 325 1.1 riastrad * routed. Therefore we set it here. 326 1.1 riastrad */ 327 1.1 riastrad if (rdev->flags & RADEON_SINGLE_CRTC) 328 1.1 riastrad crtc_ext_cntl = RADEON_CRTC_CRT_ON; 329 1.1 riastrad 330 1.1 riastrad switch (mode) { 331 1.1 riastrad case DRM_MODE_DPMS_ON: 332 1.1 riastrad radeon_crtc->enabled = true; 333 1.1 riastrad /* adjust pm to dpms changes BEFORE enabling crtcs */ 334 1.1 riastrad radeon_pm_compute_clocks(rdev); 335 1.1 riastrad if (radeon_crtc->crtc_id) 336 1.1 riastrad WREG32_P(RADEON_CRTC2_GEN_CNTL, RADEON_CRTC2_EN, ~(RADEON_CRTC2_EN | mask)); 337 1.1 riastrad else { 338 1.1 riastrad WREG32_P(RADEON_CRTC_GEN_CNTL, RADEON_CRTC_EN, ~(RADEON_CRTC_EN | 339 1.1 riastrad RADEON_CRTC_DISP_REQ_EN_B)); 340 1.1 riastrad WREG32_P(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl, ~(mask | crtc_ext_cntl)); 341 1.1 riastrad } 342 1.4 riastrad if (dev->num_crtcs > radeon_crtc->crtc_id) 343 1.4 riastrad drm_crtc_vblank_on(crtc); 344 1.1 riastrad radeon_crtc_load_lut(crtc); 345 1.1 riastrad break; 346 1.1 riastrad case DRM_MODE_DPMS_STANDBY: 347 1.1 riastrad case DRM_MODE_DPMS_SUSPEND: 348 1.1 riastrad case DRM_MODE_DPMS_OFF: 349 1.4 riastrad if (dev->num_crtcs > radeon_crtc->crtc_id) 350 1.4 riastrad drm_crtc_vblank_off(crtc); 351 1.1 riastrad if (radeon_crtc->crtc_id) 352 1.1 riastrad WREG32_P(RADEON_CRTC2_GEN_CNTL, mask, ~(RADEON_CRTC2_EN | mask)); 353 1.1 riastrad else { 354 1.1 riastrad WREG32_P(RADEON_CRTC_GEN_CNTL, RADEON_CRTC_DISP_REQ_EN_B, ~(RADEON_CRTC_EN | 355 1.1 riastrad RADEON_CRTC_DISP_REQ_EN_B)); 356 1.1 riastrad WREG32_P(RADEON_CRTC_EXT_CNTL, mask, ~(mask | crtc_ext_cntl)); 357 1.1 riastrad } 358 1.1 riastrad radeon_crtc->enabled = false; 359 1.1 riastrad /* adjust pm to dpms changes AFTER disabling crtcs */ 360 1.1 riastrad radeon_pm_compute_clocks(rdev); 361 1.1 riastrad break; 362 1.1 riastrad } 363 1.1 riastrad } 364 1.1 riastrad 365 1.1 riastrad int radeon_crtc_set_base(struct drm_crtc *crtc, int x, int y, 366 1.1 riastrad struct drm_framebuffer *old_fb) 367 1.1 riastrad { 368 1.1 riastrad return radeon_crtc_do_set_base(crtc, old_fb, x, y, 0); 369 1.1 riastrad } 370 1.1 riastrad 371 1.1 riastrad int radeon_crtc_set_base_atomic(struct drm_crtc *crtc, 372 1.1 riastrad struct drm_framebuffer *fb, 373 1.1 riastrad int x, int y, enum mode_set_atomic state) 374 1.1 riastrad { 375 1.1 riastrad return radeon_crtc_do_set_base(crtc, fb, x, y, 1); 376 1.1 riastrad } 377 1.1 riastrad 378 1.1 riastrad int radeon_crtc_do_set_base(struct drm_crtc *crtc, 379 1.1 riastrad struct drm_framebuffer *fb, 380 1.1 riastrad int x, int y, int atomic) 381 1.1 riastrad { 382 1.1 riastrad struct drm_device *dev = crtc->dev; 383 1.1 riastrad struct radeon_device *rdev = dev->dev_private; 384 1.1 riastrad struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); 385 1.1 riastrad struct drm_framebuffer *target_fb; 386 1.1 riastrad struct drm_gem_object *obj; 387 1.1 riastrad struct radeon_bo *rbo; 388 1.1 riastrad uint64_t base; 389 1.1 riastrad uint32_t crtc_offset, crtc_offset_cntl, crtc_tile_x0_y0 = 0; 390 1.1 riastrad uint32_t crtc_pitch, pitch_pixels; 391 1.1 riastrad uint32_t tiling_flags; 392 1.1 riastrad int format; 393 1.1 riastrad uint32_t gen_cntl_reg, gen_cntl_val; 394 1.1 riastrad int r; 395 1.1 riastrad 396 1.1 riastrad DRM_DEBUG_KMS("\n"); 397 1.1 riastrad /* no fb bound */ 398 1.1 riastrad if (!atomic && !crtc->primary->fb) { 399 1.1 riastrad DRM_DEBUG_KMS("No FB bound\n"); 400 1.1 riastrad return 0; 401 1.1 riastrad } 402 1.1 riastrad 403 1.4 riastrad if (atomic) 404 1.1 riastrad target_fb = fb; 405 1.4 riastrad else 406 1.1 riastrad target_fb = crtc->primary->fb; 407 1.1 riastrad 408 1.4 riastrad switch (target_fb->format->cpp[0] * 8) { 409 1.1 riastrad case 8: 410 1.1 riastrad format = 2; 411 1.1 riastrad break; 412 1.1 riastrad case 15: /* 555 */ 413 1.1 riastrad format = 3; 414 1.1 riastrad break; 415 1.1 riastrad case 16: /* 565 */ 416 1.1 riastrad format = 4; 417 1.1 riastrad break; 418 1.1 riastrad case 24: /* RGB */ 419 1.1 riastrad format = 5; 420 1.1 riastrad break; 421 1.1 riastrad case 32: /* xRGB */ 422 1.1 riastrad format = 6; 423 1.1 riastrad break; 424 1.1 riastrad default: 425 1.1 riastrad return false; 426 1.1 riastrad } 427 1.1 riastrad 428 1.1 riastrad /* Pin framebuffer & get tilling informations */ 429 1.4 riastrad obj = target_fb->obj[0]; 430 1.1 riastrad rbo = gem_to_radeon_bo(obj); 431 1.2 riastrad if (atomic) { 432 1.2 riastrad /* 433 1.2 riastrad * If you want to do this in atomic, better have it 434 1.2 riastrad * pinned ahead of time. 435 1.2 riastrad */ 436 1.2 riastrad BUG_ON(rbo->pin_count == 0); 437 1.2 riastrad base = radeon_bo_gpu_offset(rbo); 438 1.2 riastrad tiling_flags = 0; 439 1.2 riastrad goto pinned; 440 1.2 riastrad } 441 1.1 riastrad retry: 442 1.1 riastrad r = radeon_bo_reserve(rbo, false); 443 1.1 riastrad if (unlikely(r != 0)) 444 1.1 riastrad return r; 445 1.1 riastrad /* Only 27 bit offset for legacy CRTC */ 446 1.1 riastrad r = radeon_bo_pin_restricted(rbo, RADEON_GEM_DOMAIN_VRAM, 1 << 27, 447 1.1 riastrad &base); 448 1.1 riastrad if (unlikely(r != 0)) { 449 1.1 riastrad radeon_bo_unreserve(rbo); 450 1.1 riastrad 451 1.1 riastrad /* On old GPU like RN50 with little vram pining can fails because 452 1.1 riastrad * current fb is taking all space needed. So instead of unpining 453 1.1 riastrad * the old buffer after pining the new one, first unpin old one 454 1.1 riastrad * and then retry pining new one. 455 1.1 riastrad * 456 1.1 riastrad * As only master can set mode only master can pin and it is 457 1.1 riastrad * unlikely the master client will race with itself especialy 458 1.1 riastrad * on those old gpu with single crtc. 459 1.1 riastrad * 460 1.1 riastrad * We don't shutdown the display controller because new buffer 461 1.1 riastrad * will end up in same spot. 462 1.1 riastrad */ 463 1.2 riastrad if (fb && fb != crtc->primary->fb) { 464 1.1 riastrad struct radeon_bo *old_rbo; 465 1.1 riastrad unsigned long nsize, osize; 466 1.1 riastrad 467 1.4 riastrad old_rbo = gem_to_radeon_bo(fb->obj[0]); 468 1.1 riastrad osize = radeon_bo_size(old_rbo); 469 1.1 riastrad nsize = radeon_bo_size(rbo); 470 1.1 riastrad if (nsize <= osize && !radeon_bo_reserve(old_rbo, false)) { 471 1.1 riastrad radeon_bo_unpin(old_rbo); 472 1.1 riastrad radeon_bo_unreserve(old_rbo); 473 1.1 riastrad fb = NULL; 474 1.1 riastrad goto retry; 475 1.1 riastrad } 476 1.1 riastrad } 477 1.1 riastrad return -EINVAL; 478 1.1 riastrad } 479 1.1 riastrad radeon_bo_get_tiling_flags(rbo, &tiling_flags, NULL); 480 1.1 riastrad radeon_bo_unreserve(rbo); 481 1.2 riastrad pinned: 482 1.1 riastrad if (tiling_flags & RADEON_TILING_MICRO) 483 1.1 riastrad DRM_ERROR("trying to scanout microtiled buffer\n"); 484 1.1 riastrad 485 1.1 riastrad /* if scanout was in GTT this really wouldn't work */ 486 1.1 riastrad /* crtc offset is from display base addr not FB location */ 487 1.1 riastrad radeon_crtc->legacy_display_base_addr = rdev->mc.vram_start; 488 1.1 riastrad 489 1.1 riastrad base -= radeon_crtc->legacy_display_base_addr; 490 1.1 riastrad 491 1.1 riastrad crtc_offset_cntl = 0; 492 1.1 riastrad 493 1.4 riastrad pitch_pixels = target_fb->pitches[0] / target_fb->format->cpp[0]; 494 1.4 riastrad crtc_pitch = DIV_ROUND_UP(pitch_pixels * target_fb->format->cpp[0] * 8, 495 1.4 riastrad target_fb->format->cpp[0] * 8 * 8); 496 1.1 riastrad crtc_pitch |= crtc_pitch << 16; 497 1.1 riastrad 498 1.1 riastrad crtc_offset_cntl |= RADEON_CRTC_GUI_TRIG_OFFSET_LEFT_EN; 499 1.1 riastrad if (tiling_flags & RADEON_TILING_MACRO) { 500 1.1 riastrad if (ASIC_IS_R300(rdev)) 501 1.1 riastrad crtc_offset_cntl |= (R300_CRTC_X_Y_MODE_EN | 502 1.1 riastrad R300_CRTC_MICRO_TILE_BUFFER_DIS | 503 1.1 riastrad R300_CRTC_MACRO_TILE_EN); 504 1.1 riastrad else 505 1.1 riastrad crtc_offset_cntl |= RADEON_CRTC_TILE_EN; 506 1.1 riastrad } else { 507 1.1 riastrad if (ASIC_IS_R300(rdev)) 508 1.1 riastrad crtc_offset_cntl &= ~(R300_CRTC_X_Y_MODE_EN | 509 1.1 riastrad R300_CRTC_MICRO_TILE_BUFFER_DIS | 510 1.1 riastrad R300_CRTC_MACRO_TILE_EN); 511 1.1 riastrad else 512 1.1 riastrad crtc_offset_cntl &= ~RADEON_CRTC_TILE_EN; 513 1.1 riastrad } 514 1.1 riastrad 515 1.1 riastrad if (tiling_flags & RADEON_TILING_MACRO) { 516 1.1 riastrad if (ASIC_IS_R300(rdev)) { 517 1.1 riastrad crtc_tile_x0_y0 = x | (y << 16); 518 1.1 riastrad base &= ~0x7ff; 519 1.1 riastrad } else { 520 1.4 riastrad int byteshift = target_fb->format->cpp[0] * 8 >> 4; 521 1.1 riastrad int tile_addr = (((y >> 3) * pitch_pixels + x) >> (8 - byteshift)) << 11; 522 1.1 riastrad base += tile_addr + ((x << byteshift) % 256) + ((y % 8) << 8); 523 1.1 riastrad crtc_offset_cntl |= (y % 16); 524 1.1 riastrad } 525 1.1 riastrad } else { 526 1.1 riastrad int offset = y * pitch_pixels + x; 527 1.4 riastrad switch (target_fb->format->cpp[0] * 8) { 528 1.1 riastrad case 8: 529 1.1 riastrad offset *= 1; 530 1.1 riastrad break; 531 1.1 riastrad case 15: 532 1.1 riastrad case 16: 533 1.1 riastrad offset *= 2; 534 1.1 riastrad break; 535 1.1 riastrad case 24: 536 1.1 riastrad offset *= 3; 537 1.1 riastrad break; 538 1.1 riastrad case 32: 539 1.1 riastrad offset *= 4; 540 1.1 riastrad break; 541 1.1 riastrad default: 542 1.1 riastrad return false; 543 1.1 riastrad } 544 1.1 riastrad base += offset; 545 1.1 riastrad } 546 1.1 riastrad 547 1.1 riastrad base &= ~7; 548 1.1 riastrad 549 1.1 riastrad if (radeon_crtc->crtc_id == 1) 550 1.1 riastrad gen_cntl_reg = RADEON_CRTC2_GEN_CNTL; 551 1.1 riastrad else 552 1.1 riastrad gen_cntl_reg = RADEON_CRTC_GEN_CNTL; 553 1.1 riastrad 554 1.1 riastrad gen_cntl_val = RREG32(gen_cntl_reg); 555 1.1 riastrad gen_cntl_val &= ~(0xf << 8); 556 1.1 riastrad gen_cntl_val |= (format << 8); 557 1.1 riastrad gen_cntl_val &= ~RADEON_CRTC_VSTAT_MODE_MASK; 558 1.1 riastrad WREG32(gen_cntl_reg, gen_cntl_val); 559 1.1 riastrad 560 1.1 riastrad crtc_offset = (u32)base; 561 1.1 riastrad 562 1.1 riastrad WREG32(RADEON_DISPLAY_BASE_ADDR + radeon_crtc->crtc_offset, radeon_crtc->legacy_display_base_addr); 563 1.1 riastrad 564 1.1 riastrad if (ASIC_IS_R300(rdev)) { 565 1.1 riastrad if (radeon_crtc->crtc_id) 566 1.1 riastrad WREG32(R300_CRTC2_TILE_X0_Y0, crtc_tile_x0_y0); 567 1.1 riastrad else 568 1.1 riastrad WREG32(R300_CRTC_TILE_X0_Y0, crtc_tile_x0_y0); 569 1.1 riastrad } 570 1.1 riastrad WREG32(RADEON_CRTC_OFFSET_CNTL + radeon_crtc->crtc_offset, crtc_offset_cntl); 571 1.1 riastrad WREG32(RADEON_CRTC_OFFSET + radeon_crtc->crtc_offset, crtc_offset); 572 1.1 riastrad WREG32(RADEON_CRTC_PITCH + radeon_crtc->crtc_offset, crtc_pitch); 573 1.1 riastrad 574 1.1 riastrad if (!atomic && fb && fb != crtc->primary->fb) { 575 1.4 riastrad rbo = gem_to_radeon_bo(fb->obj[0]); 576 1.1 riastrad r = radeon_bo_reserve(rbo, false); 577 1.1 riastrad if (unlikely(r != 0)) 578 1.1 riastrad return r; 579 1.1 riastrad radeon_bo_unpin(rbo); 580 1.1 riastrad radeon_bo_unreserve(rbo); 581 1.1 riastrad } 582 1.1 riastrad 583 1.1 riastrad /* Bytes per pixel may have changed */ 584 1.1 riastrad radeon_bandwidth_update(rdev); 585 1.1 riastrad 586 1.1 riastrad return 0; 587 1.1 riastrad } 588 1.1 riastrad 589 1.1 riastrad static bool radeon_set_crtc_timing(struct drm_crtc *crtc, struct drm_display_mode *mode) 590 1.1 riastrad { 591 1.1 riastrad struct drm_device *dev = crtc->dev; 592 1.1 riastrad struct radeon_device *rdev = dev->dev_private; 593 1.1 riastrad struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); 594 1.4 riastrad const struct drm_framebuffer *fb = crtc->primary->fb; 595 1.1 riastrad struct drm_encoder *encoder; 596 1.1 riastrad int format; 597 1.1 riastrad int hsync_start; 598 1.1 riastrad int hsync_wid; 599 1.1 riastrad int vsync_wid; 600 1.1 riastrad uint32_t crtc_h_total_disp; 601 1.1 riastrad uint32_t crtc_h_sync_strt_wid; 602 1.1 riastrad uint32_t crtc_v_total_disp; 603 1.1 riastrad uint32_t crtc_v_sync_strt_wid; 604 1.1 riastrad bool is_tv = false; 605 1.1 riastrad 606 1.1 riastrad DRM_DEBUG_KMS("\n"); 607 1.1 riastrad list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { 608 1.1 riastrad if (encoder->crtc == crtc) { 609 1.1 riastrad struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 610 1.1 riastrad if (radeon_encoder->active_device & ATOM_DEVICE_TV_SUPPORT) { 611 1.1 riastrad is_tv = true; 612 1.1 riastrad DRM_INFO("crtc %d is connected to a TV\n", radeon_crtc->crtc_id); 613 1.1 riastrad break; 614 1.1 riastrad } 615 1.1 riastrad } 616 1.1 riastrad } 617 1.1 riastrad 618 1.4 riastrad switch (fb->format->cpp[0] * 8) { 619 1.1 riastrad case 8: 620 1.1 riastrad format = 2; 621 1.1 riastrad break; 622 1.1 riastrad case 15: /* 555 */ 623 1.1 riastrad format = 3; 624 1.1 riastrad break; 625 1.1 riastrad case 16: /* 565 */ 626 1.1 riastrad format = 4; 627 1.1 riastrad break; 628 1.1 riastrad case 24: /* RGB */ 629 1.1 riastrad format = 5; 630 1.1 riastrad break; 631 1.1 riastrad case 32: /* xRGB */ 632 1.1 riastrad format = 6; 633 1.1 riastrad break; 634 1.1 riastrad default: 635 1.1 riastrad return false; 636 1.1 riastrad } 637 1.1 riastrad 638 1.1 riastrad crtc_h_total_disp = ((((mode->crtc_htotal / 8) - 1) & 0x3ff) 639 1.1 riastrad | ((((mode->crtc_hdisplay / 8) - 1) & 0x1ff) << 16)); 640 1.1 riastrad 641 1.1 riastrad hsync_wid = (mode->crtc_hsync_end - mode->crtc_hsync_start) / 8; 642 1.1 riastrad if (!hsync_wid) 643 1.1 riastrad hsync_wid = 1; 644 1.1 riastrad hsync_start = mode->crtc_hsync_start - 8; 645 1.1 riastrad 646 1.1 riastrad crtc_h_sync_strt_wid = ((hsync_start & 0x1fff) 647 1.1 riastrad | ((hsync_wid & 0x3f) << 16) 648 1.1 riastrad | ((mode->flags & DRM_MODE_FLAG_NHSYNC) 649 1.1 riastrad ? RADEON_CRTC_H_SYNC_POL 650 1.1 riastrad : 0)); 651 1.1 riastrad 652 1.1 riastrad /* This works for double scan mode. */ 653 1.1 riastrad crtc_v_total_disp = (((mode->crtc_vtotal - 1) & 0xffff) 654 1.1 riastrad | ((mode->crtc_vdisplay - 1) << 16)); 655 1.1 riastrad 656 1.1 riastrad vsync_wid = mode->crtc_vsync_end - mode->crtc_vsync_start; 657 1.1 riastrad if (!vsync_wid) 658 1.1 riastrad vsync_wid = 1; 659 1.1 riastrad 660 1.1 riastrad crtc_v_sync_strt_wid = (((mode->crtc_vsync_start - 1) & 0xfff) 661 1.1 riastrad | ((vsync_wid & 0x1f) << 16) 662 1.1 riastrad | ((mode->flags & DRM_MODE_FLAG_NVSYNC) 663 1.1 riastrad ? RADEON_CRTC_V_SYNC_POL 664 1.1 riastrad : 0)); 665 1.1 riastrad 666 1.1 riastrad if (radeon_crtc->crtc_id) { 667 1.1 riastrad uint32_t crtc2_gen_cntl; 668 1.1 riastrad uint32_t disp2_merge_cntl; 669 1.1 riastrad 670 1.1 riastrad /* if TV DAC is enabled for another crtc and keep it enabled */ 671 1.1 riastrad crtc2_gen_cntl = RREG32(RADEON_CRTC2_GEN_CNTL) & 0x00718080; 672 1.1 riastrad crtc2_gen_cntl |= ((format << 8) 673 1.1 riastrad | RADEON_CRTC2_VSYNC_DIS 674 1.1 riastrad | RADEON_CRTC2_HSYNC_DIS 675 1.1 riastrad | RADEON_CRTC2_DISP_DIS 676 1.1 riastrad | RADEON_CRTC2_DISP_REQ_EN_B 677 1.1 riastrad | ((mode->flags & DRM_MODE_FLAG_DBLSCAN) 678 1.1 riastrad ? RADEON_CRTC2_DBL_SCAN_EN 679 1.1 riastrad : 0) 680 1.1 riastrad | ((mode->flags & DRM_MODE_FLAG_CSYNC) 681 1.1 riastrad ? RADEON_CRTC2_CSYNC_EN 682 1.1 riastrad : 0) 683 1.1 riastrad | ((mode->flags & DRM_MODE_FLAG_INTERLACE) 684 1.1 riastrad ? RADEON_CRTC2_INTERLACE_EN 685 1.1 riastrad : 0)); 686 1.1 riastrad 687 1.1 riastrad /* rs4xx chips seem to like to have the crtc enabled when the timing is set */ 688 1.1 riastrad if ((rdev->family == CHIP_RS400) || (rdev->family == CHIP_RS480)) 689 1.1 riastrad crtc2_gen_cntl |= RADEON_CRTC2_EN; 690 1.1 riastrad 691 1.1 riastrad disp2_merge_cntl = RREG32(RADEON_DISP2_MERGE_CNTL); 692 1.1 riastrad disp2_merge_cntl &= ~RADEON_DISP2_RGB_OFFSET_EN; 693 1.1 riastrad 694 1.1 riastrad WREG32(RADEON_DISP2_MERGE_CNTL, disp2_merge_cntl); 695 1.1 riastrad WREG32(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl); 696 1.1 riastrad 697 1.1 riastrad WREG32(RADEON_FP_H2_SYNC_STRT_WID, crtc_h_sync_strt_wid); 698 1.1 riastrad WREG32(RADEON_FP_V2_SYNC_STRT_WID, crtc_v_sync_strt_wid); 699 1.1 riastrad } else { 700 1.1 riastrad uint32_t crtc_gen_cntl; 701 1.1 riastrad uint32_t crtc_ext_cntl; 702 1.1 riastrad uint32_t disp_merge_cntl; 703 1.1 riastrad 704 1.1 riastrad crtc_gen_cntl = RREG32(RADEON_CRTC_GEN_CNTL) & 0x00718000; 705 1.1 riastrad crtc_gen_cntl |= (RADEON_CRTC_EXT_DISP_EN 706 1.1 riastrad | (format << 8) 707 1.1 riastrad | RADEON_CRTC_DISP_REQ_EN_B 708 1.1 riastrad | ((mode->flags & DRM_MODE_FLAG_DBLSCAN) 709 1.1 riastrad ? RADEON_CRTC_DBL_SCAN_EN 710 1.1 riastrad : 0) 711 1.1 riastrad | ((mode->flags & DRM_MODE_FLAG_CSYNC) 712 1.1 riastrad ? RADEON_CRTC_CSYNC_EN 713 1.1 riastrad : 0) 714 1.1 riastrad | ((mode->flags & DRM_MODE_FLAG_INTERLACE) 715 1.1 riastrad ? RADEON_CRTC_INTERLACE_EN 716 1.1 riastrad : 0)); 717 1.1 riastrad 718 1.1 riastrad /* rs4xx chips seem to like to have the crtc enabled when the timing is set */ 719 1.1 riastrad if ((rdev->family == CHIP_RS400) || (rdev->family == CHIP_RS480)) 720 1.1 riastrad crtc_gen_cntl |= RADEON_CRTC_EN; 721 1.1 riastrad 722 1.1 riastrad crtc_ext_cntl = RREG32(RADEON_CRTC_EXT_CNTL); 723 1.1 riastrad crtc_ext_cntl |= (RADEON_XCRT_CNT_EN | 724 1.1 riastrad RADEON_CRTC_VSYNC_DIS | 725 1.1 riastrad RADEON_CRTC_HSYNC_DIS | 726 1.1 riastrad RADEON_CRTC_DISPLAY_DIS); 727 1.1 riastrad 728 1.1 riastrad disp_merge_cntl = RREG32(RADEON_DISP_MERGE_CNTL); 729 1.1 riastrad disp_merge_cntl &= ~RADEON_DISP_RGB_OFFSET_EN; 730 1.1 riastrad 731 1.1 riastrad WREG32(RADEON_DISP_MERGE_CNTL, disp_merge_cntl); 732 1.1 riastrad WREG32(RADEON_CRTC_GEN_CNTL, crtc_gen_cntl); 733 1.1 riastrad WREG32(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl); 734 1.1 riastrad } 735 1.1 riastrad 736 1.1 riastrad if (is_tv) 737 1.1 riastrad radeon_legacy_tv_adjust_crtc_reg(encoder, &crtc_h_total_disp, 738 1.1 riastrad &crtc_h_sync_strt_wid, &crtc_v_total_disp, 739 1.1 riastrad &crtc_v_sync_strt_wid); 740 1.1 riastrad 741 1.1 riastrad WREG32(RADEON_CRTC_H_TOTAL_DISP + radeon_crtc->crtc_offset, crtc_h_total_disp); 742 1.1 riastrad WREG32(RADEON_CRTC_H_SYNC_STRT_WID + radeon_crtc->crtc_offset, crtc_h_sync_strt_wid); 743 1.1 riastrad WREG32(RADEON_CRTC_V_TOTAL_DISP + radeon_crtc->crtc_offset, crtc_v_total_disp); 744 1.1 riastrad WREG32(RADEON_CRTC_V_SYNC_STRT_WID + radeon_crtc->crtc_offset, crtc_v_sync_strt_wid); 745 1.1 riastrad 746 1.1 riastrad return true; 747 1.1 riastrad } 748 1.1 riastrad 749 1.1 riastrad static void radeon_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode) 750 1.1 riastrad { 751 1.1 riastrad struct drm_device *dev = crtc->dev; 752 1.1 riastrad struct radeon_device *rdev = dev->dev_private; 753 1.1 riastrad struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); 754 1.1 riastrad struct drm_encoder *encoder; 755 1.1 riastrad uint32_t feedback_div = 0; 756 1.1 riastrad uint32_t frac_fb_div = 0; 757 1.1 riastrad uint32_t reference_div = 0; 758 1.1 riastrad uint32_t post_divider = 0; 759 1.1 riastrad uint32_t freq = 0; 760 1.1 riastrad uint8_t pll_gain; 761 1.1 riastrad bool use_bios_divs = false; 762 1.1 riastrad /* PLL registers */ 763 1.1 riastrad uint32_t pll_ref_div = 0; 764 1.1 riastrad uint32_t pll_fb_post_div = 0; 765 1.1 riastrad uint32_t htotal_cntl = 0; 766 1.1 riastrad bool is_tv = false; 767 1.1 riastrad struct radeon_pll *pll; 768 1.1 riastrad 769 1.1 riastrad struct { 770 1.1 riastrad int divider; 771 1.1 riastrad int bitvalue; 772 1.1 riastrad } *post_div, post_divs[] = { 773 1.1 riastrad /* From RAGE 128 VR/RAGE 128 GL Register 774 1.1 riastrad * Reference Manual (Technical Reference 775 1.1 riastrad * Manual P/N RRG-G04100-C Rev. 0.04), page 776 1.1 riastrad * 3-17 (PLL_DIV_[3:0]). 777 1.1 riastrad */ 778 1.1 riastrad { 1, 0 }, /* VCLK_SRC */ 779 1.1 riastrad { 2, 1 }, /* VCLK_SRC/2 */ 780 1.1 riastrad { 4, 2 }, /* VCLK_SRC/4 */ 781 1.1 riastrad { 8, 3 }, /* VCLK_SRC/8 */ 782 1.1 riastrad { 3, 4 }, /* VCLK_SRC/3 */ 783 1.1 riastrad { 16, 5 }, /* VCLK_SRC/16 */ 784 1.1 riastrad { 6, 6 }, /* VCLK_SRC/6 */ 785 1.1 riastrad { 12, 7 }, /* VCLK_SRC/12 */ 786 1.1 riastrad { 0, 0 } 787 1.1 riastrad }; 788 1.1 riastrad 789 1.1 riastrad if (radeon_crtc->crtc_id) 790 1.1 riastrad pll = &rdev->clock.p2pll; 791 1.1 riastrad else 792 1.1 riastrad pll = &rdev->clock.p1pll; 793 1.1 riastrad 794 1.1 riastrad pll->flags = RADEON_PLL_LEGACY; 795 1.1 riastrad 796 1.1 riastrad if (mode->clock > 200000) /* range limits??? */ 797 1.1 riastrad pll->flags |= RADEON_PLL_PREFER_HIGH_FB_DIV; 798 1.1 riastrad else 799 1.1 riastrad pll->flags |= RADEON_PLL_PREFER_LOW_REF_DIV; 800 1.1 riastrad 801 1.1 riastrad list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { 802 1.1 riastrad if (encoder->crtc == crtc) { 803 1.1 riastrad struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 804 1.1 riastrad 805 1.1 riastrad if (radeon_encoder->active_device & ATOM_DEVICE_TV_SUPPORT) { 806 1.1 riastrad is_tv = true; 807 1.1 riastrad break; 808 1.1 riastrad } 809 1.1 riastrad 810 1.1 riastrad if (encoder->encoder_type != DRM_MODE_ENCODER_DAC) 811 1.1 riastrad pll->flags |= RADEON_PLL_NO_ODD_POST_DIV; 812 1.1 riastrad if (encoder->encoder_type == DRM_MODE_ENCODER_LVDS) { 813 1.1 riastrad if (!rdev->is_atom_bios) { 814 1.1 riastrad struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 815 1.1 riastrad struct radeon_encoder_lvds *lvds = (struct radeon_encoder_lvds *)radeon_encoder->enc_priv; 816 1.1 riastrad if (lvds) { 817 1.1 riastrad if (lvds->use_bios_dividers) { 818 1.1 riastrad pll_ref_div = lvds->panel_ref_divider; 819 1.1 riastrad pll_fb_post_div = (lvds->panel_fb_divider | 820 1.1 riastrad (lvds->panel_post_divider << 16)); 821 1.1 riastrad htotal_cntl = 0; 822 1.1 riastrad use_bios_divs = true; 823 1.1 riastrad } 824 1.1 riastrad } 825 1.1 riastrad } 826 1.1 riastrad pll->flags |= RADEON_PLL_USE_REF_DIV; 827 1.1 riastrad } 828 1.1 riastrad } 829 1.1 riastrad } 830 1.1 riastrad 831 1.1 riastrad DRM_DEBUG_KMS("\n"); 832 1.1 riastrad 833 1.1 riastrad if (!use_bios_divs) { 834 1.1 riastrad radeon_compute_pll_legacy(pll, mode->clock, 835 1.1 riastrad &freq, &feedback_div, &frac_fb_div, 836 1.1 riastrad &reference_div, &post_divider); 837 1.1 riastrad 838 1.1 riastrad for (post_div = &post_divs[0]; post_div->divider; ++post_div) { 839 1.1 riastrad if (post_div->divider == post_divider) 840 1.1 riastrad break; 841 1.1 riastrad } 842 1.1 riastrad 843 1.1 riastrad if (!post_div->divider) 844 1.1 riastrad post_div = &post_divs[0]; 845 1.1 riastrad 846 1.1 riastrad DRM_DEBUG_KMS("dc=%u, fd=%d, rd=%d, pd=%d\n", 847 1.1 riastrad (unsigned)freq, 848 1.1 riastrad feedback_div, 849 1.1 riastrad reference_div, 850 1.1 riastrad post_divider); 851 1.1 riastrad 852 1.1 riastrad pll_ref_div = reference_div; 853 1.1 riastrad #if defined(__powerpc__) && (0) /* TODO */ 854 1.1 riastrad /* apparently programming this otherwise causes a hang??? */ 855 1.1 riastrad if (info->MacModel == RADEON_MAC_IBOOK) 856 1.1 riastrad pll_fb_post_div = 0x000600ad; 857 1.1 riastrad else 858 1.1 riastrad #endif 859 1.1 riastrad pll_fb_post_div = (feedback_div | (post_div->bitvalue << 16)); 860 1.1 riastrad 861 1.1 riastrad htotal_cntl = mode->htotal & 0x7; 862 1.1 riastrad 863 1.1 riastrad } 864 1.1 riastrad 865 1.1 riastrad pll_gain = radeon_compute_pll_gain(pll->reference_freq, 866 1.1 riastrad pll_ref_div & 0x3ff, 867 1.1 riastrad pll_fb_post_div & 0x7ff); 868 1.1 riastrad 869 1.1 riastrad if (radeon_crtc->crtc_id) { 870 1.1 riastrad uint32_t pixclks_cntl = ((RREG32_PLL(RADEON_PIXCLKS_CNTL) & 871 1.1 riastrad ~(RADEON_PIX2CLK_SRC_SEL_MASK)) | 872 1.1 riastrad RADEON_PIX2CLK_SRC_SEL_P2PLLCLK); 873 1.1 riastrad 874 1.1 riastrad if (is_tv) { 875 1.1 riastrad radeon_legacy_tv_adjust_pll2(encoder, &htotal_cntl, 876 1.1 riastrad &pll_ref_div, &pll_fb_post_div, 877 1.1 riastrad &pixclks_cntl); 878 1.1 riastrad } 879 1.1 riastrad 880 1.1 riastrad WREG32_PLL_P(RADEON_PIXCLKS_CNTL, 881 1.1 riastrad RADEON_PIX2CLK_SRC_SEL_CPUCLK, 882 1.1 riastrad ~(RADEON_PIX2CLK_SRC_SEL_MASK)); 883 1.1 riastrad 884 1.1 riastrad WREG32_PLL_P(RADEON_P2PLL_CNTL, 885 1.1 riastrad RADEON_P2PLL_RESET 886 1.1 riastrad | RADEON_P2PLL_ATOMIC_UPDATE_EN 887 1.1 riastrad | ((uint32_t)pll_gain << RADEON_P2PLL_PVG_SHIFT), 888 1.1 riastrad ~(RADEON_P2PLL_RESET 889 1.1 riastrad | RADEON_P2PLL_ATOMIC_UPDATE_EN 890 1.1 riastrad | RADEON_P2PLL_PVG_MASK)); 891 1.1 riastrad 892 1.1 riastrad WREG32_PLL_P(RADEON_P2PLL_REF_DIV, 893 1.1 riastrad pll_ref_div, 894 1.1 riastrad ~RADEON_P2PLL_REF_DIV_MASK); 895 1.1 riastrad 896 1.1 riastrad WREG32_PLL_P(RADEON_P2PLL_DIV_0, 897 1.1 riastrad pll_fb_post_div, 898 1.1 riastrad ~RADEON_P2PLL_FB0_DIV_MASK); 899 1.1 riastrad 900 1.1 riastrad WREG32_PLL_P(RADEON_P2PLL_DIV_0, 901 1.1 riastrad pll_fb_post_div, 902 1.1 riastrad ~RADEON_P2PLL_POST0_DIV_MASK); 903 1.1 riastrad 904 1.1 riastrad radeon_pll2_write_update(dev); 905 1.1 riastrad radeon_pll2_wait_for_read_update_complete(dev); 906 1.1 riastrad 907 1.1 riastrad WREG32_PLL(RADEON_HTOTAL2_CNTL, htotal_cntl); 908 1.1 riastrad 909 1.1 riastrad WREG32_PLL_P(RADEON_P2PLL_CNTL, 910 1.1 riastrad 0, 911 1.1 riastrad ~(RADEON_P2PLL_RESET 912 1.1 riastrad | RADEON_P2PLL_SLEEP 913 1.1 riastrad | RADEON_P2PLL_ATOMIC_UPDATE_EN)); 914 1.1 riastrad 915 1.1 riastrad DRM_DEBUG_KMS("Wrote2: 0x%08x 0x%08x 0x%08x (0x%08x)\n", 916 1.1 riastrad (unsigned)pll_ref_div, 917 1.1 riastrad (unsigned)pll_fb_post_div, 918 1.1 riastrad (unsigned)htotal_cntl, 919 1.1 riastrad RREG32_PLL(RADEON_P2PLL_CNTL)); 920 1.1 riastrad DRM_DEBUG_KMS("Wrote2: rd=%u, fd=%u, pd=%u\n", 921 1.1 riastrad (unsigned)pll_ref_div & RADEON_P2PLL_REF_DIV_MASK, 922 1.1 riastrad (unsigned)pll_fb_post_div & RADEON_P2PLL_FB0_DIV_MASK, 923 1.1 riastrad (unsigned)((pll_fb_post_div & 924 1.1 riastrad RADEON_P2PLL_POST0_DIV_MASK) >> 16)); 925 1.1 riastrad 926 1.1 riastrad mdelay(50); /* Let the clock to lock */ 927 1.1 riastrad 928 1.1 riastrad WREG32_PLL_P(RADEON_PIXCLKS_CNTL, 929 1.1 riastrad RADEON_PIX2CLK_SRC_SEL_P2PLLCLK, 930 1.1 riastrad ~(RADEON_PIX2CLK_SRC_SEL_MASK)); 931 1.1 riastrad 932 1.1 riastrad WREG32_PLL(RADEON_PIXCLKS_CNTL, pixclks_cntl); 933 1.1 riastrad } else { 934 1.1 riastrad uint32_t pixclks_cntl; 935 1.1 riastrad 936 1.1 riastrad 937 1.1 riastrad if (is_tv) { 938 1.1 riastrad pixclks_cntl = RREG32_PLL(RADEON_PIXCLKS_CNTL); 939 1.1 riastrad radeon_legacy_tv_adjust_pll1(encoder, &htotal_cntl, &pll_ref_div, 940 1.1 riastrad &pll_fb_post_div, &pixclks_cntl); 941 1.1 riastrad } 942 1.1 riastrad 943 1.1 riastrad if (rdev->flags & RADEON_IS_MOBILITY) { 944 1.1 riastrad /* A temporal workaround for the occasional blanking on certain laptop panels. 945 1.1 riastrad This appears to related to the PLL divider registers (fail to lock?). 946 1.1 riastrad It occurs even when all dividers are the same with their old settings. 947 1.1 riastrad In this case we really don't need to fiddle with PLL registers. 948 1.1 riastrad By doing this we can avoid the blanking problem with some panels. 949 1.1 riastrad */ 950 1.1 riastrad if ((pll_ref_div == (RREG32_PLL(RADEON_PPLL_REF_DIV) & RADEON_PPLL_REF_DIV_MASK)) && 951 1.1 riastrad (pll_fb_post_div == (RREG32_PLL(RADEON_PPLL_DIV_3) & 952 1.1 riastrad (RADEON_PPLL_POST3_DIV_MASK | RADEON_PPLL_FB3_DIV_MASK)))) { 953 1.1 riastrad WREG32_P(RADEON_CLOCK_CNTL_INDEX, 954 1.1 riastrad RADEON_PLL_DIV_SEL, 955 1.1 riastrad ~(RADEON_PLL_DIV_SEL)); 956 1.1 riastrad r100_pll_errata_after_index(rdev); 957 1.1 riastrad return; 958 1.1 riastrad } 959 1.1 riastrad } 960 1.1 riastrad 961 1.1 riastrad WREG32_PLL_P(RADEON_VCLK_ECP_CNTL, 962 1.1 riastrad RADEON_VCLK_SRC_SEL_CPUCLK, 963 1.1 riastrad ~(RADEON_VCLK_SRC_SEL_MASK)); 964 1.1 riastrad WREG32_PLL_P(RADEON_PPLL_CNTL, 965 1.1 riastrad RADEON_PPLL_RESET 966 1.1 riastrad | RADEON_PPLL_ATOMIC_UPDATE_EN 967 1.1 riastrad | RADEON_PPLL_VGA_ATOMIC_UPDATE_EN 968 1.1 riastrad | ((uint32_t)pll_gain << RADEON_PPLL_PVG_SHIFT), 969 1.1 riastrad ~(RADEON_PPLL_RESET 970 1.1 riastrad | RADEON_PPLL_ATOMIC_UPDATE_EN 971 1.1 riastrad | RADEON_PPLL_VGA_ATOMIC_UPDATE_EN 972 1.1 riastrad | RADEON_PPLL_PVG_MASK)); 973 1.1 riastrad 974 1.1 riastrad WREG32_P(RADEON_CLOCK_CNTL_INDEX, 975 1.1 riastrad RADEON_PLL_DIV_SEL, 976 1.1 riastrad ~(RADEON_PLL_DIV_SEL)); 977 1.1 riastrad r100_pll_errata_after_index(rdev); 978 1.1 riastrad 979 1.1 riastrad if (ASIC_IS_R300(rdev) || 980 1.1 riastrad (rdev->family == CHIP_RS300) || 981 1.1 riastrad (rdev->family == CHIP_RS400) || 982 1.1 riastrad (rdev->family == CHIP_RS480)) { 983 1.1 riastrad if (pll_ref_div & R300_PPLL_REF_DIV_ACC_MASK) { 984 1.1 riastrad /* When restoring console mode, use saved PPLL_REF_DIV 985 1.1 riastrad * setting. 986 1.1 riastrad */ 987 1.1 riastrad WREG32_PLL_P(RADEON_PPLL_REF_DIV, 988 1.1 riastrad pll_ref_div, 989 1.1 riastrad 0); 990 1.1 riastrad } else { 991 1.1 riastrad /* R300 uses ref_div_acc field as real ref divider */ 992 1.1 riastrad WREG32_PLL_P(RADEON_PPLL_REF_DIV, 993 1.1 riastrad (pll_ref_div << R300_PPLL_REF_DIV_ACC_SHIFT), 994 1.1 riastrad ~R300_PPLL_REF_DIV_ACC_MASK); 995 1.1 riastrad } 996 1.1 riastrad } else 997 1.1 riastrad WREG32_PLL_P(RADEON_PPLL_REF_DIV, 998 1.1 riastrad pll_ref_div, 999 1.1 riastrad ~RADEON_PPLL_REF_DIV_MASK); 1000 1.1 riastrad 1001 1.1 riastrad WREG32_PLL_P(RADEON_PPLL_DIV_3, 1002 1.1 riastrad pll_fb_post_div, 1003 1.1 riastrad ~RADEON_PPLL_FB3_DIV_MASK); 1004 1.1 riastrad 1005 1.1 riastrad WREG32_PLL_P(RADEON_PPLL_DIV_3, 1006 1.1 riastrad pll_fb_post_div, 1007 1.1 riastrad ~RADEON_PPLL_POST3_DIV_MASK); 1008 1.1 riastrad 1009 1.1 riastrad radeon_pll_write_update(dev); 1010 1.1 riastrad radeon_pll_wait_for_read_update_complete(dev); 1011 1.1 riastrad 1012 1.1 riastrad WREG32_PLL(RADEON_HTOTAL_CNTL, htotal_cntl); 1013 1.1 riastrad 1014 1.1 riastrad WREG32_PLL_P(RADEON_PPLL_CNTL, 1015 1.1 riastrad 0, 1016 1.1 riastrad ~(RADEON_PPLL_RESET 1017 1.1 riastrad | RADEON_PPLL_SLEEP 1018 1.1 riastrad | RADEON_PPLL_ATOMIC_UPDATE_EN 1019 1.1 riastrad | RADEON_PPLL_VGA_ATOMIC_UPDATE_EN)); 1020 1.1 riastrad 1021 1.1 riastrad DRM_DEBUG_KMS("Wrote: 0x%08x 0x%08x 0x%08x (0x%08x)\n", 1022 1.1 riastrad pll_ref_div, 1023 1.1 riastrad pll_fb_post_div, 1024 1.1 riastrad (unsigned)htotal_cntl, 1025 1.1 riastrad RREG32_PLL(RADEON_PPLL_CNTL)); 1026 1.1 riastrad DRM_DEBUG_KMS("Wrote: rd=%d, fd=%d, pd=%d\n", 1027 1.1 riastrad pll_ref_div & RADEON_PPLL_REF_DIV_MASK, 1028 1.1 riastrad pll_fb_post_div & RADEON_PPLL_FB3_DIV_MASK, 1029 1.1 riastrad (pll_fb_post_div & RADEON_PPLL_POST3_DIV_MASK) >> 16); 1030 1.1 riastrad 1031 1.1 riastrad mdelay(50); /* Let the clock to lock */ 1032 1.1 riastrad 1033 1.1 riastrad WREG32_PLL_P(RADEON_VCLK_ECP_CNTL, 1034 1.1 riastrad RADEON_VCLK_SRC_SEL_PPLLCLK, 1035 1.1 riastrad ~(RADEON_VCLK_SRC_SEL_MASK)); 1036 1.1 riastrad 1037 1.1 riastrad if (is_tv) 1038 1.1 riastrad WREG32_PLL(RADEON_PIXCLKS_CNTL, pixclks_cntl); 1039 1.1 riastrad } 1040 1.1 riastrad } 1041 1.1 riastrad 1042 1.1 riastrad static bool radeon_crtc_mode_fixup(struct drm_crtc *crtc, 1043 1.1 riastrad const struct drm_display_mode *mode, 1044 1.1 riastrad struct drm_display_mode *adjusted_mode) 1045 1.1 riastrad { 1046 1.1 riastrad if (!radeon_crtc_scaling_mode_fixup(crtc, mode, adjusted_mode)) 1047 1.1 riastrad return false; 1048 1.1 riastrad return true; 1049 1.1 riastrad } 1050 1.1 riastrad 1051 1.1 riastrad static int radeon_crtc_mode_set(struct drm_crtc *crtc, 1052 1.1 riastrad struct drm_display_mode *mode, 1053 1.1 riastrad struct drm_display_mode *adjusted_mode, 1054 1.1 riastrad int x, int y, struct drm_framebuffer *old_fb) 1055 1.1 riastrad { 1056 1.1 riastrad struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); 1057 1.1 riastrad 1058 1.1 riastrad /* TODO TV */ 1059 1.1 riastrad radeon_crtc_set_base(crtc, x, y, old_fb); 1060 1.1 riastrad radeon_set_crtc_timing(crtc, adjusted_mode); 1061 1.1 riastrad radeon_set_pll(crtc, adjusted_mode); 1062 1.1 riastrad radeon_overscan_setup(crtc, adjusted_mode); 1063 1.1 riastrad if (radeon_crtc->crtc_id == 0) { 1064 1.1 riastrad radeon_legacy_rmx_mode_set(crtc, adjusted_mode); 1065 1.1 riastrad } else { 1066 1.1 riastrad if (radeon_crtc->rmx_type != RMX_OFF) { 1067 1.1 riastrad /* FIXME: only first crtc has rmx what should we 1068 1.1 riastrad * do ? 1069 1.1 riastrad */ 1070 1.1 riastrad DRM_ERROR("Mode need scaling but only first crtc can do that.\n"); 1071 1.1 riastrad } 1072 1.1 riastrad } 1073 1.3 riastrad radeon_cursor_reset(crtc); 1074 1.1 riastrad return 0; 1075 1.1 riastrad } 1076 1.1 riastrad 1077 1.1 riastrad static void radeon_crtc_prepare(struct drm_crtc *crtc) 1078 1.1 riastrad { 1079 1.1 riastrad struct drm_device *dev = crtc->dev; 1080 1.1 riastrad struct drm_crtc *crtci; 1081 1.1 riastrad 1082 1.1 riastrad /* 1083 1.1 riastrad * The hardware wedges sometimes if you reconfigure one CRTC 1084 1.1 riastrad * whilst another is running (see fdo bug #24611). 1085 1.1 riastrad */ 1086 1.1 riastrad list_for_each_entry(crtci, &dev->mode_config.crtc_list, head) 1087 1.1 riastrad radeon_crtc_dpms(crtci, DRM_MODE_DPMS_OFF); 1088 1.1 riastrad } 1089 1.1 riastrad 1090 1.1 riastrad static void radeon_crtc_commit(struct drm_crtc *crtc) 1091 1.1 riastrad { 1092 1.1 riastrad struct drm_device *dev = crtc->dev; 1093 1.1 riastrad struct drm_crtc *crtci; 1094 1.1 riastrad 1095 1.1 riastrad /* 1096 1.1 riastrad * Reenable the CRTCs that should be running. 1097 1.1 riastrad */ 1098 1.1 riastrad list_for_each_entry(crtci, &dev->mode_config.crtc_list, head) { 1099 1.1 riastrad if (crtci->enabled) 1100 1.1 riastrad radeon_crtc_dpms(crtci, DRM_MODE_DPMS_ON); 1101 1.1 riastrad } 1102 1.1 riastrad } 1103 1.1 riastrad 1104 1.1 riastrad static void radeon_crtc_disable(struct drm_crtc *crtc) 1105 1.1 riastrad { 1106 1.1 riastrad radeon_crtc_dpms(crtc, DRM_MODE_DPMS_OFF); 1107 1.1 riastrad if (crtc->primary->fb) { 1108 1.1 riastrad int r; 1109 1.1 riastrad struct radeon_bo *rbo; 1110 1.1 riastrad 1111 1.4 riastrad rbo = gem_to_radeon_bo(crtc->primary->fb->obj[0]); 1112 1.1 riastrad r = radeon_bo_reserve(rbo, false); 1113 1.1 riastrad if (unlikely(r)) 1114 1.1 riastrad DRM_ERROR("failed to reserve rbo before unpin\n"); 1115 1.1 riastrad else { 1116 1.1 riastrad radeon_bo_unpin(rbo); 1117 1.1 riastrad radeon_bo_unreserve(rbo); 1118 1.1 riastrad } 1119 1.1 riastrad } 1120 1.1 riastrad } 1121 1.1 riastrad 1122 1.1 riastrad static const struct drm_crtc_helper_funcs legacy_helper_funcs = { 1123 1.1 riastrad .dpms = radeon_crtc_dpms, 1124 1.1 riastrad .mode_fixup = radeon_crtc_mode_fixup, 1125 1.1 riastrad .mode_set = radeon_crtc_mode_set, 1126 1.1 riastrad .mode_set_base = radeon_crtc_set_base, 1127 1.1 riastrad .mode_set_base_atomic = radeon_crtc_set_base_atomic, 1128 1.1 riastrad .prepare = radeon_crtc_prepare, 1129 1.1 riastrad .commit = radeon_crtc_commit, 1130 1.1 riastrad .disable = radeon_crtc_disable 1131 1.1 riastrad }; 1132 1.1 riastrad 1133 1.1 riastrad 1134 1.1 riastrad void radeon_legacy_init_crtc(struct drm_device *dev, 1135 1.1 riastrad struct radeon_crtc *radeon_crtc) 1136 1.1 riastrad { 1137 1.1 riastrad if (radeon_crtc->crtc_id == 1) 1138 1.1 riastrad radeon_crtc->crtc_offset = RADEON_CRTC2_H_TOTAL_DISP - RADEON_CRTC_H_TOTAL_DISP; 1139 1.1 riastrad drm_crtc_helper_add(&radeon_crtc->base, &legacy_helper_funcs); 1140 1.1 riastrad } 1141