1771fe6b9SJerome Glisse /* 2771fe6b9SJerome Glisse * Copyright 2007-8 Advanced Micro Devices, Inc. 3771fe6b9SJerome Glisse * Copyright 2008 Red Hat Inc. 4771fe6b9SJerome Glisse * 5771fe6b9SJerome Glisse * Permission is hereby granted, free of charge, to any person obtaining a 6771fe6b9SJerome Glisse * copy of this software and associated documentation files (the "Software"), 7771fe6b9SJerome Glisse * to deal in the Software without restriction, including without limitation 8771fe6b9SJerome Glisse * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9771fe6b9SJerome Glisse * and/or sell copies of the Software, and to permit persons to whom the 10771fe6b9SJerome Glisse * Software is furnished to do so, subject to the following conditions: 11771fe6b9SJerome Glisse * 12771fe6b9SJerome Glisse * The above copyright notice and this permission notice shall be included in 13771fe6b9SJerome Glisse * all copies or substantial portions of the Software. 14771fe6b9SJerome Glisse * 15771fe6b9SJerome Glisse * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16771fe6b9SJerome Glisse * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17771fe6b9SJerome Glisse * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18771fe6b9SJerome Glisse * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 19771fe6b9SJerome Glisse * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 20771fe6b9SJerome Glisse * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 21771fe6b9SJerome Glisse * OTHER DEALINGS IN THE SOFTWARE. 22771fe6b9SJerome Glisse * 23771fe6b9SJerome Glisse * Authors: Dave Airlie 24771fe6b9SJerome Glisse * Alex Deucher 25771fe6b9SJerome Glisse */ 26771fe6b9SJerome Glisse #include <drm/drmP.h> 27771fe6b9SJerome Glisse #include <drm/drm_crtc_helper.h> 28771fe6b9SJerome Glisse #include <drm/radeon_drm.h> 29771fe6b9SJerome Glisse #include "radeon_fixed.h" 30771fe6b9SJerome Glisse #include "radeon.h" 31771fe6b9SJerome Glisse #include "atom.h" 32771fe6b9SJerome Glisse #include "atom-bits.h" 33771fe6b9SJerome Glisse 34771fe6b9SJerome Glisse static void atombios_lock_crtc(struct drm_crtc *crtc, int lock) 35771fe6b9SJerome Glisse { 36771fe6b9SJerome Glisse struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); 37771fe6b9SJerome Glisse struct drm_device *dev = crtc->dev; 38771fe6b9SJerome Glisse struct radeon_device *rdev = dev->dev_private; 39771fe6b9SJerome Glisse int index = 40771fe6b9SJerome Glisse GetIndexIntoMasterTable(COMMAND, UpdateCRTC_DoubleBufferRegisters); 41771fe6b9SJerome Glisse ENABLE_CRTC_PS_ALLOCATION args; 42771fe6b9SJerome Glisse 43771fe6b9SJerome Glisse memset(&args, 0, sizeof(args)); 44771fe6b9SJerome Glisse 45771fe6b9SJerome Glisse args.ucCRTC = radeon_crtc->crtc_id; 46771fe6b9SJerome Glisse args.ucEnable = lock; 47771fe6b9SJerome Glisse 48771fe6b9SJerome Glisse atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); 49771fe6b9SJerome Glisse } 50771fe6b9SJerome Glisse 51771fe6b9SJerome Glisse static void atombios_enable_crtc(struct drm_crtc *crtc, int state) 52771fe6b9SJerome Glisse { 53771fe6b9SJerome Glisse struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); 54771fe6b9SJerome Glisse struct drm_device *dev = crtc->dev; 55771fe6b9SJerome Glisse struct radeon_device *rdev = dev->dev_private; 56771fe6b9SJerome Glisse int index = GetIndexIntoMasterTable(COMMAND, EnableCRTC); 57771fe6b9SJerome Glisse ENABLE_CRTC_PS_ALLOCATION args; 58771fe6b9SJerome Glisse 59771fe6b9SJerome Glisse memset(&args, 0, sizeof(args)); 60771fe6b9SJerome Glisse 61771fe6b9SJerome Glisse args.ucCRTC = radeon_crtc->crtc_id; 62771fe6b9SJerome Glisse args.ucEnable = state; 63771fe6b9SJerome Glisse 64771fe6b9SJerome Glisse atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); 65771fe6b9SJerome Glisse } 66771fe6b9SJerome Glisse 67771fe6b9SJerome Glisse static void atombios_enable_crtc_memreq(struct drm_crtc *crtc, int state) 68771fe6b9SJerome Glisse { 69771fe6b9SJerome Glisse struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); 70771fe6b9SJerome Glisse struct drm_device *dev = crtc->dev; 71771fe6b9SJerome Glisse struct radeon_device *rdev = dev->dev_private; 72771fe6b9SJerome Glisse int index = GetIndexIntoMasterTable(COMMAND, EnableCRTCMemReq); 73771fe6b9SJerome Glisse ENABLE_CRTC_PS_ALLOCATION args; 74771fe6b9SJerome Glisse 75771fe6b9SJerome Glisse memset(&args, 0, sizeof(args)); 76771fe6b9SJerome Glisse 77771fe6b9SJerome Glisse args.ucCRTC = radeon_crtc->crtc_id; 78771fe6b9SJerome Glisse args.ucEnable = state; 79771fe6b9SJerome Glisse 80771fe6b9SJerome Glisse atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); 81771fe6b9SJerome Glisse } 82771fe6b9SJerome Glisse 83771fe6b9SJerome Glisse static void atombios_blank_crtc(struct drm_crtc *crtc, int state) 84771fe6b9SJerome Glisse { 85771fe6b9SJerome Glisse struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); 86771fe6b9SJerome Glisse struct drm_device *dev = crtc->dev; 87771fe6b9SJerome Glisse struct radeon_device *rdev = dev->dev_private; 88771fe6b9SJerome Glisse int index = GetIndexIntoMasterTable(COMMAND, BlankCRTC); 89771fe6b9SJerome Glisse BLANK_CRTC_PS_ALLOCATION args; 90771fe6b9SJerome Glisse 91771fe6b9SJerome Glisse memset(&args, 0, sizeof(args)); 92771fe6b9SJerome Glisse 93771fe6b9SJerome Glisse args.ucCRTC = radeon_crtc->crtc_id; 94771fe6b9SJerome Glisse args.ucBlanking = state; 95771fe6b9SJerome Glisse 96771fe6b9SJerome Glisse atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); 97771fe6b9SJerome Glisse } 98771fe6b9SJerome Glisse 99771fe6b9SJerome Glisse void atombios_crtc_dpms(struct drm_crtc *crtc, int mode) 100771fe6b9SJerome Glisse { 101771fe6b9SJerome Glisse struct drm_device *dev = crtc->dev; 102771fe6b9SJerome Glisse struct radeon_device *rdev = dev->dev_private; 103771fe6b9SJerome Glisse 104771fe6b9SJerome Glisse switch (mode) { 105771fe6b9SJerome Glisse case DRM_MODE_DPMS_ON: 106771fe6b9SJerome Glisse if (ASIC_IS_DCE3(rdev)) 107771fe6b9SJerome Glisse atombios_enable_crtc_memreq(crtc, 1); 108771fe6b9SJerome Glisse atombios_enable_crtc(crtc, 1); 109771fe6b9SJerome Glisse atombios_blank_crtc(crtc, 0); 110771fe6b9SJerome Glisse break; 111771fe6b9SJerome Glisse case DRM_MODE_DPMS_STANDBY: 112771fe6b9SJerome Glisse case DRM_MODE_DPMS_SUSPEND: 113771fe6b9SJerome Glisse case DRM_MODE_DPMS_OFF: 114771fe6b9SJerome Glisse atombios_blank_crtc(crtc, 1); 115771fe6b9SJerome Glisse atombios_enable_crtc(crtc, 0); 116771fe6b9SJerome Glisse if (ASIC_IS_DCE3(rdev)) 117771fe6b9SJerome Glisse atombios_enable_crtc_memreq(crtc, 0); 118771fe6b9SJerome Glisse break; 119771fe6b9SJerome Glisse } 120771fe6b9SJerome Glisse 121771fe6b9SJerome Glisse if (mode != DRM_MODE_DPMS_OFF) { 122771fe6b9SJerome Glisse radeon_crtc_load_lut(crtc); 123771fe6b9SJerome Glisse } 124771fe6b9SJerome Glisse } 125771fe6b9SJerome Glisse 126771fe6b9SJerome Glisse static void 127771fe6b9SJerome Glisse atombios_set_crtc_dtd_timing(struct drm_crtc *crtc, 128771fe6b9SJerome Glisse SET_CRTC_USING_DTD_TIMING_PARAMETERS * crtc_param) 129771fe6b9SJerome Glisse { 130771fe6b9SJerome Glisse struct drm_device *dev = crtc->dev; 131771fe6b9SJerome Glisse struct radeon_device *rdev = dev->dev_private; 132771fe6b9SJerome Glisse SET_CRTC_USING_DTD_TIMING_PARAMETERS conv_param; 133771fe6b9SJerome Glisse int index = GetIndexIntoMasterTable(COMMAND, SetCRTC_UsingDTDTiming); 134771fe6b9SJerome Glisse 135771fe6b9SJerome Glisse conv_param.usH_Size = cpu_to_le16(crtc_param->usH_Size); 136771fe6b9SJerome Glisse conv_param.usH_Blanking_Time = 137771fe6b9SJerome Glisse cpu_to_le16(crtc_param->usH_Blanking_Time); 138771fe6b9SJerome Glisse conv_param.usV_Size = cpu_to_le16(crtc_param->usV_Size); 139771fe6b9SJerome Glisse conv_param.usV_Blanking_Time = 140771fe6b9SJerome Glisse cpu_to_le16(crtc_param->usV_Blanking_Time); 141771fe6b9SJerome Glisse conv_param.usH_SyncOffset = cpu_to_le16(crtc_param->usH_SyncOffset); 142771fe6b9SJerome Glisse conv_param.usH_SyncWidth = cpu_to_le16(crtc_param->usH_SyncWidth); 143771fe6b9SJerome Glisse conv_param.usV_SyncOffset = cpu_to_le16(crtc_param->usV_SyncOffset); 144771fe6b9SJerome Glisse conv_param.usV_SyncWidth = cpu_to_le16(crtc_param->usV_SyncWidth); 145771fe6b9SJerome Glisse conv_param.susModeMiscInfo.usAccess = 146771fe6b9SJerome Glisse cpu_to_le16(crtc_param->susModeMiscInfo.usAccess); 147771fe6b9SJerome Glisse conv_param.ucCRTC = crtc_param->ucCRTC; 148771fe6b9SJerome Glisse 149771fe6b9SJerome Glisse printk("executing set crtc dtd timing\n"); 150771fe6b9SJerome Glisse atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&conv_param); 151771fe6b9SJerome Glisse } 152771fe6b9SJerome Glisse 153771fe6b9SJerome Glisse void atombios_crtc_set_timing(struct drm_crtc *crtc, 154771fe6b9SJerome Glisse SET_CRTC_TIMING_PARAMETERS_PS_ALLOCATION * 155771fe6b9SJerome Glisse crtc_param) 156771fe6b9SJerome Glisse { 157771fe6b9SJerome Glisse struct drm_device *dev = crtc->dev; 158771fe6b9SJerome Glisse struct radeon_device *rdev = dev->dev_private; 159771fe6b9SJerome Glisse SET_CRTC_TIMING_PARAMETERS_PS_ALLOCATION conv_param; 160771fe6b9SJerome Glisse int index = GetIndexIntoMasterTable(COMMAND, SetCRTC_Timing); 161771fe6b9SJerome Glisse 162771fe6b9SJerome Glisse conv_param.usH_Total = cpu_to_le16(crtc_param->usH_Total); 163771fe6b9SJerome Glisse conv_param.usH_Disp = cpu_to_le16(crtc_param->usH_Disp); 164771fe6b9SJerome Glisse conv_param.usH_SyncStart = cpu_to_le16(crtc_param->usH_SyncStart); 165771fe6b9SJerome Glisse conv_param.usH_SyncWidth = cpu_to_le16(crtc_param->usH_SyncWidth); 166771fe6b9SJerome Glisse conv_param.usV_Total = cpu_to_le16(crtc_param->usV_Total); 167771fe6b9SJerome Glisse conv_param.usV_Disp = cpu_to_le16(crtc_param->usV_Disp); 168771fe6b9SJerome Glisse conv_param.usV_SyncStart = cpu_to_le16(crtc_param->usV_SyncStart); 169771fe6b9SJerome Glisse conv_param.usV_SyncWidth = cpu_to_le16(crtc_param->usV_SyncWidth); 170771fe6b9SJerome Glisse conv_param.susModeMiscInfo.usAccess = 171771fe6b9SJerome Glisse cpu_to_le16(crtc_param->susModeMiscInfo.usAccess); 172771fe6b9SJerome Glisse conv_param.ucCRTC = crtc_param->ucCRTC; 173771fe6b9SJerome Glisse conv_param.ucOverscanRight = crtc_param->ucOverscanRight; 174771fe6b9SJerome Glisse conv_param.ucOverscanLeft = crtc_param->ucOverscanLeft; 175771fe6b9SJerome Glisse conv_param.ucOverscanBottom = crtc_param->ucOverscanBottom; 176771fe6b9SJerome Glisse conv_param.ucOverscanTop = crtc_param->ucOverscanTop; 177771fe6b9SJerome Glisse conv_param.ucReserved = crtc_param->ucReserved; 178771fe6b9SJerome Glisse 179771fe6b9SJerome Glisse printk("executing set crtc timing\n"); 180771fe6b9SJerome Glisse atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&conv_param); 181771fe6b9SJerome Glisse } 182771fe6b9SJerome Glisse 183771fe6b9SJerome Glisse void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode) 184771fe6b9SJerome Glisse { 185771fe6b9SJerome Glisse struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); 186771fe6b9SJerome Glisse struct drm_device *dev = crtc->dev; 187771fe6b9SJerome Glisse struct radeon_device *rdev = dev->dev_private; 188771fe6b9SJerome Glisse struct drm_encoder *encoder = NULL; 189771fe6b9SJerome Glisse struct radeon_encoder *radeon_encoder = NULL; 190771fe6b9SJerome Glisse uint8_t frev, crev; 191771fe6b9SJerome Glisse int index = GetIndexIntoMasterTable(COMMAND, SetPixelClock); 192771fe6b9SJerome Glisse SET_PIXEL_CLOCK_PS_ALLOCATION args; 193771fe6b9SJerome Glisse PIXEL_CLOCK_PARAMETERS *spc1_ptr; 194771fe6b9SJerome Glisse PIXEL_CLOCK_PARAMETERS_V2 *spc2_ptr; 195771fe6b9SJerome Glisse PIXEL_CLOCK_PARAMETERS_V3 *spc3_ptr; 196771fe6b9SJerome Glisse uint32_t sclock = mode->clock; 197771fe6b9SJerome Glisse uint32_t ref_div = 0, fb_div = 0, frac_fb_div = 0, post_div = 0; 198771fe6b9SJerome Glisse struct radeon_pll *pll; 199771fe6b9SJerome Glisse int pll_flags = 0; 200771fe6b9SJerome Glisse 201771fe6b9SJerome Glisse memset(&args, 0, sizeof(args)); 202771fe6b9SJerome Glisse 203771fe6b9SJerome Glisse if (ASIC_IS_AVIVO(rdev)) { 204771fe6b9SJerome Glisse uint32_t ss_cntl; 205771fe6b9SJerome Glisse 206eb1300bcSAlex Deucher if ((rdev->family == CHIP_RS600) || 207eb1300bcSAlex Deucher (rdev->family == CHIP_RS690) || 208eb1300bcSAlex Deucher (rdev->family == CHIP_RS740)) 209eb1300bcSAlex Deucher pll_flags |= (RADEON_PLL_USE_FRAC_FB_DIV | 210eb1300bcSAlex Deucher RADEON_PLL_PREFER_CLOSEST_LOWER); 211eb1300bcSAlex Deucher 212771fe6b9SJerome Glisse if (ASIC_IS_DCE32(rdev) && mode->clock > 200000) /* range limits??? */ 213771fe6b9SJerome Glisse pll_flags |= RADEON_PLL_PREFER_HIGH_FB_DIV; 214771fe6b9SJerome Glisse else 215771fe6b9SJerome Glisse pll_flags |= RADEON_PLL_PREFER_LOW_REF_DIV; 216771fe6b9SJerome Glisse 217771fe6b9SJerome Glisse /* disable spread spectrum clocking for now -- thanks Hedy Lamarr */ 218771fe6b9SJerome Glisse if (radeon_crtc->crtc_id == 0) { 219771fe6b9SJerome Glisse ss_cntl = RREG32(AVIVO_P1PLL_INT_SS_CNTL); 220771fe6b9SJerome Glisse WREG32(AVIVO_P1PLL_INT_SS_CNTL, ss_cntl & ~1); 221771fe6b9SJerome Glisse } else { 222771fe6b9SJerome Glisse ss_cntl = RREG32(AVIVO_P2PLL_INT_SS_CNTL); 223771fe6b9SJerome Glisse WREG32(AVIVO_P2PLL_INT_SS_CNTL, ss_cntl & ~1); 224771fe6b9SJerome Glisse } 225771fe6b9SJerome Glisse } else { 226771fe6b9SJerome Glisse pll_flags |= RADEON_PLL_LEGACY; 227771fe6b9SJerome Glisse 228771fe6b9SJerome Glisse if (mode->clock > 200000) /* range limits??? */ 229771fe6b9SJerome Glisse pll_flags |= RADEON_PLL_PREFER_HIGH_FB_DIV; 230771fe6b9SJerome Glisse else 231771fe6b9SJerome Glisse pll_flags |= RADEON_PLL_PREFER_LOW_REF_DIV; 232771fe6b9SJerome Glisse 233771fe6b9SJerome Glisse } 234771fe6b9SJerome Glisse 235771fe6b9SJerome Glisse list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { 236771fe6b9SJerome Glisse if (encoder->crtc == crtc) { 237771fe6b9SJerome Glisse if (!ASIC_IS_AVIVO(rdev)) { 238771fe6b9SJerome Glisse if (encoder->encoder_type != 239771fe6b9SJerome Glisse DRM_MODE_ENCODER_DAC) 240771fe6b9SJerome Glisse pll_flags |= RADEON_PLL_NO_ODD_POST_DIV; 241771fe6b9SJerome Glisse if (!ASIC_IS_AVIVO(rdev) 242771fe6b9SJerome Glisse && (encoder->encoder_type == 243771fe6b9SJerome Glisse DRM_MODE_ENCODER_LVDS)) 244771fe6b9SJerome Glisse pll_flags |= RADEON_PLL_USE_REF_DIV; 245771fe6b9SJerome Glisse } 246771fe6b9SJerome Glisse radeon_encoder = to_radeon_encoder(encoder); 247771fe6b9SJerome Glisse } 248771fe6b9SJerome Glisse } 249771fe6b9SJerome Glisse 250771fe6b9SJerome Glisse if (radeon_crtc->crtc_id == 0) 251771fe6b9SJerome Glisse pll = &rdev->clock.p1pll; 252771fe6b9SJerome Glisse else 253771fe6b9SJerome Glisse pll = &rdev->clock.p2pll; 254771fe6b9SJerome Glisse 255771fe6b9SJerome Glisse radeon_compute_pll(pll, mode->clock, &sclock, &fb_div, &frac_fb_div, 256771fe6b9SJerome Glisse &ref_div, &post_div, pll_flags); 257771fe6b9SJerome Glisse 258771fe6b9SJerome Glisse atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, 259771fe6b9SJerome Glisse &crev); 260771fe6b9SJerome Glisse 261771fe6b9SJerome Glisse switch (frev) { 262771fe6b9SJerome Glisse case 1: 263771fe6b9SJerome Glisse switch (crev) { 264771fe6b9SJerome Glisse case 1: 265771fe6b9SJerome Glisse spc1_ptr = (PIXEL_CLOCK_PARAMETERS *) & args.sPCLKInput; 266771fe6b9SJerome Glisse spc1_ptr->usPixelClock = cpu_to_le16(sclock); 267771fe6b9SJerome Glisse spc1_ptr->usRefDiv = cpu_to_le16(ref_div); 268771fe6b9SJerome Glisse spc1_ptr->usFbDiv = cpu_to_le16(fb_div); 269771fe6b9SJerome Glisse spc1_ptr->ucFracFbDiv = frac_fb_div; 270771fe6b9SJerome Glisse spc1_ptr->ucPostDiv = post_div; 271771fe6b9SJerome Glisse spc1_ptr->ucPpll = 272771fe6b9SJerome Glisse radeon_crtc->crtc_id ? ATOM_PPLL2 : ATOM_PPLL1; 273771fe6b9SJerome Glisse spc1_ptr->ucCRTC = radeon_crtc->crtc_id; 274771fe6b9SJerome Glisse spc1_ptr->ucRefDivSrc = 1; 275771fe6b9SJerome Glisse break; 276771fe6b9SJerome Glisse case 2: 277771fe6b9SJerome Glisse spc2_ptr = 278771fe6b9SJerome Glisse (PIXEL_CLOCK_PARAMETERS_V2 *) & args.sPCLKInput; 279771fe6b9SJerome Glisse spc2_ptr->usPixelClock = cpu_to_le16(sclock); 280771fe6b9SJerome Glisse spc2_ptr->usRefDiv = cpu_to_le16(ref_div); 281771fe6b9SJerome Glisse spc2_ptr->usFbDiv = cpu_to_le16(fb_div); 282771fe6b9SJerome Glisse spc2_ptr->ucFracFbDiv = frac_fb_div; 283771fe6b9SJerome Glisse spc2_ptr->ucPostDiv = post_div; 284771fe6b9SJerome Glisse spc2_ptr->ucPpll = 285771fe6b9SJerome Glisse radeon_crtc->crtc_id ? ATOM_PPLL2 : ATOM_PPLL1; 286771fe6b9SJerome Glisse spc2_ptr->ucCRTC = radeon_crtc->crtc_id; 287771fe6b9SJerome Glisse spc2_ptr->ucRefDivSrc = 1; 288771fe6b9SJerome Glisse break; 289771fe6b9SJerome Glisse case 3: 290771fe6b9SJerome Glisse if (!encoder) 291771fe6b9SJerome Glisse return; 292771fe6b9SJerome Glisse spc3_ptr = 293771fe6b9SJerome Glisse (PIXEL_CLOCK_PARAMETERS_V3 *) & args.sPCLKInput; 294771fe6b9SJerome Glisse spc3_ptr->usPixelClock = cpu_to_le16(sclock); 295771fe6b9SJerome Glisse spc3_ptr->usRefDiv = cpu_to_le16(ref_div); 296771fe6b9SJerome Glisse spc3_ptr->usFbDiv = cpu_to_le16(fb_div); 297771fe6b9SJerome Glisse spc3_ptr->ucFracFbDiv = frac_fb_div; 298771fe6b9SJerome Glisse spc3_ptr->ucPostDiv = post_div; 299771fe6b9SJerome Glisse spc3_ptr->ucPpll = 300771fe6b9SJerome Glisse radeon_crtc->crtc_id ? ATOM_PPLL2 : ATOM_PPLL1; 301771fe6b9SJerome Glisse spc3_ptr->ucMiscInfo = (radeon_crtc->crtc_id << 2); 302771fe6b9SJerome Glisse spc3_ptr->ucTransmitterId = radeon_encoder->encoder_id; 303771fe6b9SJerome Glisse spc3_ptr->ucEncoderMode = 304771fe6b9SJerome Glisse atombios_get_encoder_mode(encoder); 305771fe6b9SJerome Glisse break; 306771fe6b9SJerome Glisse default: 307771fe6b9SJerome Glisse DRM_ERROR("Unknown table version %d %d\n", frev, crev); 308771fe6b9SJerome Glisse return; 309771fe6b9SJerome Glisse } 310771fe6b9SJerome Glisse break; 311771fe6b9SJerome Glisse default: 312771fe6b9SJerome Glisse DRM_ERROR("Unknown table version %d %d\n", frev, crev); 313771fe6b9SJerome Glisse return; 314771fe6b9SJerome Glisse } 315771fe6b9SJerome Glisse 316771fe6b9SJerome Glisse printk("executing set pll\n"); 317771fe6b9SJerome Glisse atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); 318771fe6b9SJerome Glisse } 319771fe6b9SJerome Glisse 320771fe6b9SJerome Glisse int atombios_crtc_set_base(struct drm_crtc *crtc, int x, int y, 321771fe6b9SJerome Glisse struct drm_framebuffer *old_fb) 322771fe6b9SJerome Glisse { 323771fe6b9SJerome Glisse struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); 324771fe6b9SJerome Glisse struct drm_device *dev = crtc->dev; 325771fe6b9SJerome Glisse struct radeon_device *rdev = dev->dev_private; 326771fe6b9SJerome Glisse struct radeon_framebuffer *radeon_fb; 327771fe6b9SJerome Glisse struct drm_gem_object *obj; 328771fe6b9SJerome Glisse struct drm_radeon_gem_object *obj_priv; 329771fe6b9SJerome Glisse uint64_t fb_location; 330e024e110SDave Airlie uint32_t fb_format, fb_pitch_pixels, tiling_flags; 331771fe6b9SJerome Glisse 332771fe6b9SJerome Glisse if (!crtc->fb) 333771fe6b9SJerome Glisse return -EINVAL; 334771fe6b9SJerome Glisse 335771fe6b9SJerome Glisse radeon_fb = to_radeon_framebuffer(crtc->fb); 336771fe6b9SJerome Glisse 337771fe6b9SJerome Glisse obj = radeon_fb->obj; 338771fe6b9SJerome Glisse obj_priv = obj->driver_private; 339771fe6b9SJerome Glisse 340771fe6b9SJerome Glisse if (radeon_gem_object_pin(obj, RADEON_GEM_DOMAIN_VRAM, &fb_location)) { 341771fe6b9SJerome Glisse return -EINVAL; 342771fe6b9SJerome Glisse } 343771fe6b9SJerome Glisse 344771fe6b9SJerome Glisse switch (crtc->fb->bits_per_pixel) { 345771fe6b9SJerome Glisse case 15: 346771fe6b9SJerome Glisse fb_format = 347771fe6b9SJerome Glisse AVIVO_D1GRPH_CONTROL_DEPTH_16BPP | 348771fe6b9SJerome Glisse AVIVO_D1GRPH_CONTROL_16BPP_ARGB1555; 349771fe6b9SJerome Glisse break; 350771fe6b9SJerome Glisse case 16: 351771fe6b9SJerome Glisse fb_format = 352771fe6b9SJerome Glisse AVIVO_D1GRPH_CONTROL_DEPTH_16BPP | 353771fe6b9SJerome Glisse AVIVO_D1GRPH_CONTROL_16BPP_RGB565; 354771fe6b9SJerome Glisse break; 355771fe6b9SJerome Glisse case 24: 356771fe6b9SJerome Glisse case 32: 357771fe6b9SJerome Glisse fb_format = 358771fe6b9SJerome Glisse AVIVO_D1GRPH_CONTROL_DEPTH_32BPP | 359771fe6b9SJerome Glisse AVIVO_D1GRPH_CONTROL_32BPP_ARGB8888; 360771fe6b9SJerome Glisse break; 361771fe6b9SJerome Glisse default: 362771fe6b9SJerome Glisse DRM_ERROR("Unsupported screen depth %d\n", 363771fe6b9SJerome Glisse crtc->fb->bits_per_pixel); 364771fe6b9SJerome Glisse return -EINVAL; 365771fe6b9SJerome Glisse } 366771fe6b9SJerome Glisse 367e024e110SDave Airlie radeon_object_get_tiling_flags(obj->driver_private, 368e024e110SDave Airlie &tiling_flags, NULL); 369e024e110SDave Airlie if (tiling_flags & RADEON_TILING_MACRO) 370e024e110SDave Airlie fb_format |= AVIVO_D1GRPH_MACRO_ADDRESS_MODE; 371e024e110SDave Airlie 372e024e110SDave Airlie if (tiling_flags & RADEON_TILING_MICRO) 373e024e110SDave Airlie fb_format |= AVIVO_D1GRPH_TILED; 374e024e110SDave Airlie 375771fe6b9SJerome Glisse if (radeon_crtc->crtc_id == 0) 376771fe6b9SJerome Glisse WREG32(AVIVO_D1VGA_CONTROL, 0); 377771fe6b9SJerome Glisse else 378771fe6b9SJerome Glisse WREG32(AVIVO_D2VGA_CONTROL, 0); 379771fe6b9SJerome Glisse WREG32(AVIVO_D1GRPH_PRIMARY_SURFACE_ADDRESS + radeon_crtc->crtc_offset, 380771fe6b9SJerome Glisse (u32) fb_location); 381771fe6b9SJerome Glisse WREG32(AVIVO_D1GRPH_SECONDARY_SURFACE_ADDRESS + 382771fe6b9SJerome Glisse radeon_crtc->crtc_offset, (u32) fb_location); 383771fe6b9SJerome Glisse WREG32(AVIVO_D1GRPH_CONTROL + radeon_crtc->crtc_offset, fb_format); 384771fe6b9SJerome Glisse 385771fe6b9SJerome Glisse WREG32(AVIVO_D1GRPH_SURFACE_OFFSET_X + radeon_crtc->crtc_offset, 0); 386771fe6b9SJerome Glisse WREG32(AVIVO_D1GRPH_SURFACE_OFFSET_Y + radeon_crtc->crtc_offset, 0); 387771fe6b9SJerome Glisse WREG32(AVIVO_D1GRPH_X_START + radeon_crtc->crtc_offset, 0); 388771fe6b9SJerome Glisse WREG32(AVIVO_D1GRPH_Y_START + radeon_crtc->crtc_offset, 0); 389771fe6b9SJerome Glisse WREG32(AVIVO_D1GRPH_X_END + radeon_crtc->crtc_offset, crtc->fb->width); 390771fe6b9SJerome Glisse WREG32(AVIVO_D1GRPH_Y_END + radeon_crtc->crtc_offset, crtc->fb->height); 391771fe6b9SJerome Glisse 392771fe6b9SJerome Glisse fb_pitch_pixels = crtc->fb->pitch / (crtc->fb->bits_per_pixel / 8); 393771fe6b9SJerome Glisse WREG32(AVIVO_D1GRPH_PITCH + radeon_crtc->crtc_offset, fb_pitch_pixels); 394771fe6b9SJerome Glisse WREG32(AVIVO_D1GRPH_ENABLE + radeon_crtc->crtc_offset, 1); 395771fe6b9SJerome Glisse 396771fe6b9SJerome Glisse WREG32(AVIVO_D1MODE_DESKTOP_HEIGHT + radeon_crtc->crtc_offset, 397771fe6b9SJerome Glisse crtc->mode.vdisplay); 398771fe6b9SJerome Glisse x &= ~3; 399771fe6b9SJerome Glisse y &= ~1; 400771fe6b9SJerome Glisse WREG32(AVIVO_D1MODE_VIEWPORT_START + radeon_crtc->crtc_offset, 401771fe6b9SJerome Glisse (x << 16) | y); 402771fe6b9SJerome Glisse WREG32(AVIVO_D1MODE_VIEWPORT_SIZE + radeon_crtc->crtc_offset, 403771fe6b9SJerome Glisse (crtc->mode.hdisplay << 16) | crtc->mode.vdisplay); 404771fe6b9SJerome Glisse 405771fe6b9SJerome Glisse if (crtc->mode.flags & DRM_MODE_FLAG_INTERLACE) 406771fe6b9SJerome Glisse WREG32(AVIVO_D1MODE_DATA_FORMAT + radeon_crtc->crtc_offset, 407771fe6b9SJerome Glisse AVIVO_D1MODE_INTERLEAVE_EN); 408771fe6b9SJerome Glisse else 409771fe6b9SJerome Glisse WREG32(AVIVO_D1MODE_DATA_FORMAT + radeon_crtc->crtc_offset, 0); 410771fe6b9SJerome Glisse 411771fe6b9SJerome Glisse if (old_fb && old_fb != crtc->fb) { 412771fe6b9SJerome Glisse radeon_fb = to_radeon_framebuffer(old_fb); 413771fe6b9SJerome Glisse radeon_gem_object_unpin(radeon_fb->obj); 414771fe6b9SJerome Glisse } 415771fe6b9SJerome Glisse return 0; 416771fe6b9SJerome Glisse } 417771fe6b9SJerome Glisse 418771fe6b9SJerome Glisse int atombios_crtc_mode_set(struct drm_crtc *crtc, 419771fe6b9SJerome Glisse struct drm_display_mode *mode, 420771fe6b9SJerome Glisse struct drm_display_mode *adjusted_mode, 421771fe6b9SJerome Glisse int x, int y, struct drm_framebuffer *old_fb) 422771fe6b9SJerome Glisse { 423771fe6b9SJerome Glisse struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); 424771fe6b9SJerome Glisse struct drm_device *dev = crtc->dev; 425771fe6b9SJerome Glisse struct radeon_device *rdev = dev->dev_private; 426771fe6b9SJerome Glisse struct drm_encoder *encoder; 427771fe6b9SJerome Glisse SET_CRTC_TIMING_PARAMETERS_PS_ALLOCATION crtc_timing; 428771fe6b9SJerome Glisse 429771fe6b9SJerome Glisse /* TODO color tiling */ 430771fe6b9SJerome Glisse memset(&crtc_timing, 0, sizeof(crtc_timing)); 431771fe6b9SJerome Glisse 432771fe6b9SJerome Glisse /* TODO tv */ 433771fe6b9SJerome Glisse list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { 434771fe6b9SJerome Glisse 435771fe6b9SJerome Glisse } 436771fe6b9SJerome Glisse 437771fe6b9SJerome Glisse crtc_timing.ucCRTC = radeon_crtc->crtc_id; 438771fe6b9SJerome Glisse crtc_timing.usH_Total = adjusted_mode->crtc_htotal; 439771fe6b9SJerome Glisse crtc_timing.usH_Disp = adjusted_mode->crtc_hdisplay; 440771fe6b9SJerome Glisse crtc_timing.usH_SyncStart = adjusted_mode->crtc_hsync_start; 441771fe6b9SJerome Glisse crtc_timing.usH_SyncWidth = 442771fe6b9SJerome Glisse adjusted_mode->crtc_hsync_end - adjusted_mode->crtc_hsync_start; 443771fe6b9SJerome Glisse 444771fe6b9SJerome Glisse crtc_timing.usV_Total = adjusted_mode->crtc_vtotal; 445771fe6b9SJerome Glisse crtc_timing.usV_Disp = adjusted_mode->crtc_vdisplay; 446771fe6b9SJerome Glisse crtc_timing.usV_SyncStart = adjusted_mode->crtc_vsync_start; 447771fe6b9SJerome Glisse crtc_timing.usV_SyncWidth = 448771fe6b9SJerome Glisse adjusted_mode->crtc_vsync_end - adjusted_mode->crtc_vsync_start; 449771fe6b9SJerome Glisse 450771fe6b9SJerome Glisse if (adjusted_mode->flags & DRM_MODE_FLAG_NVSYNC) 451771fe6b9SJerome Glisse crtc_timing.susModeMiscInfo.usAccess |= ATOM_VSYNC_POLARITY; 452771fe6b9SJerome Glisse 453771fe6b9SJerome Glisse if (adjusted_mode->flags & DRM_MODE_FLAG_NHSYNC) 454771fe6b9SJerome Glisse crtc_timing.susModeMiscInfo.usAccess |= ATOM_HSYNC_POLARITY; 455771fe6b9SJerome Glisse 456771fe6b9SJerome Glisse if (adjusted_mode->flags & DRM_MODE_FLAG_CSYNC) 457771fe6b9SJerome Glisse crtc_timing.susModeMiscInfo.usAccess |= ATOM_COMPOSITESYNC; 458771fe6b9SJerome Glisse 459771fe6b9SJerome Glisse if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) 460771fe6b9SJerome Glisse crtc_timing.susModeMiscInfo.usAccess |= ATOM_INTERLACE; 461771fe6b9SJerome Glisse 462771fe6b9SJerome Glisse if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN) 463771fe6b9SJerome Glisse crtc_timing.susModeMiscInfo.usAccess |= ATOM_DOUBLE_CLOCK_MODE; 464771fe6b9SJerome Glisse 465771fe6b9SJerome Glisse atombios_crtc_set_pll(crtc, adjusted_mode); 466771fe6b9SJerome Glisse atombios_crtc_set_timing(crtc, &crtc_timing); 467771fe6b9SJerome Glisse 468771fe6b9SJerome Glisse if (ASIC_IS_AVIVO(rdev)) 469771fe6b9SJerome Glisse atombios_crtc_set_base(crtc, x, y, old_fb); 470771fe6b9SJerome Glisse else { 471771fe6b9SJerome Glisse if (radeon_crtc->crtc_id == 0) { 472771fe6b9SJerome Glisse SET_CRTC_USING_DTD_TIMING_PARAMETERS crtc_dtd_timing; 473771fe6b9SJerome Glisse memset(&crtc_dtd_timing, 0, sizeof(crtc_dtd_timing)); 474771fe6b9SJerome Glisse 475771fe6b9SJerome Glisse /* setup FP shadow regs on R4xx */ 476771fe6b9SJerome Glisse crtc_dtd_timing.ucCRTC = radeon_crtc->crtc_id; 477771fe6b9SJerome Glisse crtc_dtd_timing.usH_Size = adjusted_mode->crtc_hdisplay; 478771fe6b9SJerome Glisse crtc_dtd_timing.usV_Size = adjusted_mode->crtc_vdisplay; 479771fe6b9SJerome Glisse crtc_dtd_timing.usH_Blanking_Time = 480771fe6b9SJerome Glisse adjusted_mode->crtc_hblank_end - 481771fe6b9SJerome Glisse adjusted_mode->crtc_hdisplay; 482771fe6b9SJerome Glisse crtc_dtd_timing.usV_Blanking_Time = 483771fe6b9SJerome Glisse adjusted_mode->crtc_vblank_end - 484771fe6b9SJerome Glisse adjusted_mode->crtc_vdisplay; 485771fe6b9SJerome Glisse crtc_dtd_timing.usH_SyncOffset = 486771fe6b9SJerome Glisse adjusted_mode->crtc_hsync_start - 487771fe6b9SJerome Glisse adjusted_mode->crtc_hdisplay; 488771fe6b9SJerome Glisse crtc_dtd_timing.usV_SyncOffset = 489771fe6b9SJerome Glisse adjusted_mode->crtc_vsync_start - 490771fe6b9SJerome Glisse adjusted_mode->crtc_vdisplay; 491771fe6b9SJerome Glisse crtc_dtd_timing.usH_SyncWidth = 492771fe6b9SJerome Glisse adjusted_mode->crtc_hsync_end - 493771fe6b9SJerome Glisse adjusted_mode->crtc_hsync_start; 494771fe6b9SJerome Glisse crtc_dtd_timing.usV_SyncWidth = 495771fe6b9SJerome Glisse adjusted_mode->crtc_vsync_end - 496771fe6b9SJerome Glisse adjusted_mode->crtc_vsync_start; 497771fe6b9SJerome Glisse /* crtc_dtd_timing.ucH_Border = adjusted_mode->crtc_hborder; */ 498771fe6b9SJerome Glisse /* crtc_dtd_timing.ucV_Border = adjusted_mode->crtc_vborder; */ 499771fe6b9SJerome Glisse 500771fe6b9SJerome Glisse if (adjusted_mode->flags & DRM_MODE_FLAG_NVSYNC) 501771fe6b9SJerome Glisse crtc_dtd_timing.susModeMiscInfo.usAccess |= 502771fe6b9SJerome Glisse ATOM_VSYNC_POLARITY; 503771fe6b9SJerome Glisse 504771fe6b9SJerome Glisse if (adjusted_mode->flags & DRM_MODE_FLAG_NHSYNC) 505771fe6b9SJerome Glisse crtc_dtd_timing.susModeMiscInfo.usAccess |= 506771fe6b9SJerome Glisse ATOM_HSYNC_POLARITY; 507771fe6b9SJerome Glisse 508771fe6b9SJerome Glisse if (adjusted_mode->flags & DRM_MODE_FLAG_CSYNC) 509771fe6b9SJerome Glisse crtc_dtd_timing.susModeMiscInfo.usAccess |= 510771fe6b9SJerome Glisse ATOM_COMPOSITESYNC; 511771fe6b9SJerome Glisse 512771fe6b9SJerome Glisse if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) 513771fe6b9SJerome Glisse crtc_dtd_timing.susModeMiscInfo.usAccess |= 514771fe6b9SJerome Glisse ATOM_INTERLACE; 515771fe6b9SJerome Glisse 516771fe6b9SJerome Glisse if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN) 517771fe6b9SJerome Glisse crtc_dtd_timing.susModeMiscInfo.usAccess |= 518771fe6b9SJerome Glisse ATOM_DOUBLE_CLOCK_MODE; 519771fe6b9SJerome Glisse 520771fe6b9SJerome Glisse atombios_set_crtc_dtd_timing(crtc, &crtc_dtd_timing); 521771fe6b9SJerome Glisse } 522771fe6b9SJerome Glisse radeon_crtc_set_base(crtc, x, y, old_fb); 523771fe6b9SJerome Glisse radeon_legacy_atom_set_surface(crtc); 524771fe6b9SJerome Glisse } 525771fe6b9SJerome Glisse return 0; 526771fe6b9SJerome Glisse } 527771fe6b9SJerome Glisse 528771fe6b9SJerome Glisse static bool atombios_crtc_mode_fixup(struct drm_crtc *crtc, 529771fe6b9SJerome Glisse struct drm_display_mode *mode, 530771fe6b9SJerome Glisse struct drm_display_mode *adjusted_mode) 531771fe6b9SJerome Glisse { 532771fe6b9SJerome Glisse return true; 533771fe6b9SJerome Glisse } 534771fe6b9SJerome Glisse 535771fe6b9SJerome Glisse static void atombios_crtc_prepare(struct drm_crtc *crtc) 536771fe6b9SJerome Glisse { 537771fe6b9SJerome Glisse atombios_crtc_dpms(crtc, DRM_MODE_DPMS_OFF); 538771fe6b9SJerome Glisse atombios_lock_crtc(crtc, 1); 539771fe6b9SJerome Glisse } 540771fe6b9SJerome Glisse 541771fe6b9SJerome Glisse static void atombios_crtc_commit(struct drm_crtc *crtc) 542771fe6b9SJerome Glisse { 543771fe6b9SJerome Glisse atombios_crtc_dpms(crtc, DRM_MODE_DPMS_ON); 544771fe6b9SJerome Glisse atombios_lock_crtc(crtc, 0); 545771fe6b9SJerome Glisse } 546771fe6b9SJerome Glisse 547771fe6b9SJerome Glisse static const struct drm_crtc_helper_funcs atombios_helper_funcs = { 548771fe6b9SJerome Glisse .dpms = atombios_crtc_dpms, 549771fe6b9SJerome Glisse .mode_fixup = atombios_crtc_mode_fixup, 550771fe6b9SJerome Glisse .mode_set = atombios_crtc_mode_set, 551771fe6b9SJerome Glisse .mode_set_base = atombios_crtc_set_base, 552771fe6b9SJerome Glisse .prepare = atombios_crtc_prepare, 553771fe6b9SJerome Glisse .commit = atombios_crtc_commit, 554771fe6b9SJerome Glisse }; 555771fe6b9SJerome Glisse 556771fe6b9SJerome Glisse void radeon_atombios_init_crtc(struct drm_device *dev, 557771fe6b9SJerome Glisse struct radeon_crtc *radeon_crtc) 558771fe6b9SJerome Glisse { 559771fe6b9SJerome Glisse if (radeon_crtc->crtc_id == 1) 560771fe6b9SJerome Glisse radeon_crtc->crtc_offset = 561771fe6b9SJerome Glisse AVIVO_D2CRTC_H_TOTAL - AVIVO_D1CRTC_H_TOTAL; 562771fe6b9SJerome Glisse drm_crtc_helper_add(&radeon_crtc->base, &atombios_helper_funcs); 563771fe6b9SJerome Glisse } 564771fe6b9SJerome Glisse 565771fe6b9SJerome Glisse void radeon_init_disp_bw_avivo(struct drm_device *dev, 566771fe6b9SJerome Glisse struct drm_display_mode *mode1, 567771fe6b9SJerome Glisse uint32_t pixel_bytes1, 568771fe6b9SJerome Glisse struct drm_display_mode *mode2, 569771fe6b9SJerome Glisse uint32_t pixel_bytes2) 570771fe6b9SJerome Glisse { 571771fe6b9SJerome Glisse struct radeon_device *rdev = dev->dev_private; 572771fe6b9SJerome Glisse fixed20_12 min_mem_eff; 573771fe6b9SJerome Glisse fixed20_12 peak_disp_bw, mem_bw, pix_clk, pix_clk2, temp_ff; 574771fe6b9SJerome Glisse fixed20_12 sclk_ff, mclk_ff; 575771fe6b9SJerome Glisse uint32_t dc_lb_memory_split, temp; 576771fe6b9SJerome Glisse 577771fe6b9SJerome Glisse min_mem_eff.full = rfixed_const_8(0); 578771fe6b9SJerome Glisse if (rdev->disp_priority == 2) { 579771fe6b9SJerome Glisse uint32_t mc_init_misc_lat_timer = 0; 580771fe6b9SJerome Glisse if (rdev->family == CHIP_RV515) 581771fe6b9SJerome Glisse mc_init_misc_lat_timer = 582771fe6b9SJerome Glisse RREG32_MC(RV515_MC_INIT_MISC_LAT_TIMER); 583771fe6b9SJerome Glisse else if (rdev->family == CHIP_RS690) 584771fe6b9SJerome Glisse mc_init_misc_lat_timer = 585771fe6b9SJerome Glisse RREG32_MC(RS690_MC_INIT_MISC_LAT_TIMER); 586771fe6b9SJerome Glisse 587771fe6b9SJerome Glisse mc_init_misc_lat_timer &= 588771fe6b9SJerome Glisse ~(R300_MC_DISP1R_INIT_LAT_MASK << 589771fe6b9SJerome Glisse R300_MC_DISP1R_INIT_LAT_SHIFT); 590771fe6b9SJerome Glisse mc_init_misc_lat_timer &= 591771fe6b9SJerome Glisse ~(R300_MC_DISP0R_INIT_LAT_MASK << 592771fe6b9SJerome Glisse R300_MC_DISP0R_INIT_LAT_SHIFT); 593771fe6b9SJerome Glisse 594771fe6b9SJerome Glisse if (mode2) 595771fe6b9SJerome Glisse mc_init_misc_lat_timer |= 596771fe6b9SJerome Glisse (1 << R300_MC_DISP1R_INIT_LAT_SHIFT); 597771fe6b9SJerome Glisse if (mode1) 598771fe6b9SJerome Glisse mc_init_misc_lat_timer |= 599771fe6b9SJerome Glisse (1 << R300_MC_DISP0R_INIT_LAT_SHIFT); 600771fe6b9SJerome Glisse 601771fe6b9SJerome Glisse if (rdev->family == CHIP_RV515) 602771fe6b9SJerome Glisse WREG32_MC(RV515_MC_INIT_MISC_LAT_TIMER, 603771fe6b9SJerome Glisse mc_init_misc_lat_timer); 604771fe6b9SJerome Glisse else if (rdev->family == CHIP_RS690) 605771fe6b9SJerome Glisse WREG32_MC(RS690_MC_INIT_MISC_LAT_TIMER, 606771fe6b9SJerome Glisse mc_init_misc_lat_timer); 607771fe6b9SJerome Glisse } 608771fe6b9SJerome Glisse 609771fe6b9SJerome Glisse /* 610771fe6b9SJerome Glisse * determine is there is enough bw for current mode 611771fe6b9SJerome Glisse */ 612771fe6b9SJerome Glisse temp_ff.full = rfixed_const(100); 613771fe6b9SJerome Glisse mclk_ff.full = rfixed_const(rdev->clock.default_mclk); 614771fe6b9SJerome Glisse mclk_ff.full = rfixed_div(mclk_ff, temp_ff); 615771fe6b9SJerome Glisse sclk_ff.full = rfixed_const(rdev->clock.default_sclk); 616771fe6b9SJerome Glisse sclk_ff.full = rfixed_div(sclk_ff, temp_ff); 617771fe6b9SJerome Glisse 618771fe6b9SJerome Glisse temp = (rdev->mc.vram_width / 8) * (rdev->mc.vram_is_ddr ? 2 : 1); 619771fe6b9SJerome Glisse temp_ff.full = rfixed_const(temp); 620771fe6b9SJerome Glisse mem_bw.full = rfixed_mul(mclk_ff, temp_ff); 621771fe6b9SJerome Glisse mem_bw.full = rfixed_mul(mem_bw, min_mem_eff); 622771fe6b9SJerome Glisse 623771fe6b9SJerome Glisse pix_clk.full = 0; 624771fe6b9SJerome Glisse pix_clk2.full = 0; 625771fe6b9SJerome Glisse peak_disp_bw.full = 0; 626771fe6b9SJerome Glisse if (mode1) { 627771fe6b9SJerome Glisse temp_ff.full = rfixed_const(1000); 628771fe6b9SJerome Glisse pix_clk.full = rfixed_const(mode1->clock); /* convert to fixed point */ 629771fe6b9SJerome Glisse pix_clk.full = rfixed_div(pix_clk, temp_ff); 630771fe6b9SJerome Glisse temp_ff.full = rfixed_const(pixel_bytes1); 631771fe6b9SJerome Glisse peak_disp_bw.full += rfixed_mul(pix_clk, temp_ff); 632771fe6b9SJerome Glisse } 633771fe6b9SJerome Glisse if (mode2) { 634771fe6b9SJerome Glisse temp_ff.full = rfixed_const(1000); 635771fe6b9SJerome Glisse pix_clk2.full = rfixed_const(mode2->clock); /* convert to fixed point */ 636771fe6b9SJerome Glisse pix_clk2.full = rfixed_div(pix_clk2, temp_ff); 637771fe6b9SJerome Glisse temp_ff.full = rfixed_const(pixel_bytes2); 638771fe6b9SJerome Glisse peak_disp_bw.full += rfixed_mul(pix_clk2, temp_ff); 639771fe6b9SJerome Glisse } 640771fe6b9SJerome Glisse 641771fe6b9SJerome Glisse if (peak_disp_bw.full >= mem_bw.full) { 642771fe6b9SJerome Glisse DRM_ERROR 643771fe6b9SJerome Glisse ("You may not have enough display bandwidth for current mode\n" 644771fe6b9SJerome Glisse "If you have flickering problem, try to lower resolution, refresh rate, or color depth\n"); 645771fe6b9SJerome Glisse printk("peak disp bw %d, mem_bw %d\n", 646771fe6b9SJerome Glisse rfixed_trunc(peak_disp_bw), rfixed_trunc(mem_bw)); 647771fe6b9SJerome Glisse } 648771fe6b9SJerome Glisse 649771fe6b9SJerome Glisse /* 650771fe6b9SJerome Glisse * Line Buffer Setup 651771fe6b9SJerome Glisse * There is a single line buffer shared by both display controllers. 652771fe6b9SJerome Glisse * DC_LB_MEMORY_SPLIT controls how that line buffer is shared between the display 653771fe6b9SJerome Glisse * controllers. The paritioning can either be done manually or via one of four 654771fe6b9SJerome Glisse * preset allocations specified in bits 1:0: 655771fe6b9SJerome Glisse * 0 - line buffer is divided in half and shared between each display controller 656771fe6b9SJerome Glisse * 1 - D1 gets 3/4 of the line buffer, D2 gets 1/4 657771fe6b9SJerome Glisse * 2 - D1 gets the whole buffer 658771fe6b9SJerome Glisse * 3 - D1 gets 1/4 of the line buffer, D2 gets 3/4 659771fe6b9SJerome Glisse * Setting bit 2 of DC_LB_MEMORY_SPLIT controls switches to manual allocation mode. 660771fe6b9SJerome Glisse * In manual allocation mode, D1 always starts at 0, D1 end/2 is specified in bits 661771fe6b9SJerome Glisse * 14:4; D2 allocation follows D1. 662771fe6b9SJerome Glisse */ 663771fe6b9SJerome Glisse 664771fe6b9SJerome Glisse /* is auto or manual better ? */ 665771fe6b9SJerome Glisse dc_lb_memory_split = 666771fe6b9SJerome Glisse RREG32(AVIVO_DC_LB_MEMORY_SPLIT) & ~AVIVO_DC_LB_MEMORY_SPLIT_MASK; 667771fe6b9SJerome Glisse dc_lb_memory_split &= ~AVIVO_DC_LB_MEMORY_SPLIT_SHIFT_MODE; 668771fe6b9SJerome Glisse #if 1 669771fe6b9SJerome Glisse /* auto */ 670771fe6b9SJerome Glisse if (mode1 && mode2) { 671771fe6b9SJerome Glisse if (mode1->hdisplay > mode2->hdisplay) { 672771fe6b9SJerome Glisse if (mode1->hdisplay > 2560) 673771fe6b9SJerome Glisse dc_lb_memory_split |= 674771fe6b9SJerome Glisse AVIVO_DC_LB_MEMORY_SPLIT_D1_3Q_D2_1Q; 675771fe6b9SJerome Glisse else 676771fe6b9SJerome Glisse dc_lb_memory_split |= 677771fe6b9SJerome Glisse AVIVO_DC_LB_MEMORY_SPLIT_D1HALF_D2HALF; 678771fe6b9SJerome Glisse } else if (mode2->hdisplay > mode1->hdisplay) { 679771fe6b9SJerome Glisse if (mode2->hdisplay > 2560) 680771fe6b9SJerome Glisse dc_lb_memory_split |= 681771fe6b9SJerome Glisse AVIVO_DC_LB_MEMORY_SPLIT_D1_1Q_D2_3Q; 682771fe6b9SJerome Glisse else 683771fe6b9SJerome Glisse dc_lb_memory_split |= 684771fe6b9SJerome Glisse AVIVO_DC_LB_MEMORY_SPLIT_D1HALF_D2HALF; 685771fe6b9SJerome Glisse } else 686771fe6b9SJerome Glisse dc_lb_memory_split |= 687771fe6b9SJerome Glisse AVIVO_DC_LB_MEMORY_SPLIT_D1HALF_D2HALF; 688771fe6b9SJerome Glisse } else if (mode1) { 689771fe6b9SJerome Glisse dc_lb_memory_split |= AVIVO_DC_LB_MEMORY_SPLIT_D1_ONLY; 690771fe6b9SJerome Glisse } else if (mode2) { 691771fe6b9SJerome Glisse dc_lb_memory_split |= AVIVO_DC_LB_MEMORY_SPLIT_D1_1Q_D2_3Q; 692771fe6b9SJerome Glisse } 693771fe6b9SJerome Glisse #else 694771fe6b9SJerome Glisse /* manual */ 695771fe6b9SJerome Glisse dc_lb_memory_split |= AVIVO_DC_LB_MEMORY_SPLIT_SHIFT_MODE; 696771fe6b9SJerome Glisse dc_lb_memory_split &= 697771fe6b9SJerome Glisse ~(AVIVO_DC_LB_DISP1_END_ADR_MASK << 698771fe6b9SJerome Glisse AVIVO_DC_LB_DISP1_END_ADR_SHIFT); 699771fe6b9SJerome Glisse if (mode1) { 700771fe6b9SJerome Glisse dc_lb_memory_split |= 701771fe6b9SJerome Glisse ((((mode1->hdisplay / 2) + 64) & AVIVO_DC_LB_DISP1_END_ADR_MASK) 702771fe6b9SJerome Glisse << AVIVO_DC_LB_DISP1_END_ADR_SHIFT); 703771fe6b9SJerome Glisse } else if (mode2) { 704771fe6b9SJerome Glisse dc_lb_memory_split |= (0 << AVIVO_DC_LB_DISP1_END_ADR_SHIFT); 705771fe6b9SJerome Glisse } 706771fe6b9SJerome Glisse #endif 707771fe6b9SJerome Glisse WREG32(AVIVO_DC_LB_MEMORY_SPLIT, dc_lb_memory_split); 708771fe6b9SJerome Glisse } 709