1 // SPDX-License-Identifier: GPL-2.0-only 2 /************************************************************************** 3 * Copyright (c) 2011, Intel Corporation. 4 * All Rights Reserved. 5 * 6 **************************************************************************/ 7 8 #include <drm/drm.h> 9 10 #include "gma_device.h" 11 #include "intel_bios.h" 12 #include "psb_device.h" 13 #include "psb_drv.h" 14 #include "psb_intel_reg.h" 15 #include "psb_reg.h" 16 17 static int psb_output_init(struct drm_device *dev) 18 { 19 struct drm_psb_private *dev_priv = to_drm_psb_private(dev); 20 psb_intel_lvds_init(dev, &dev_priv->mode_dev); 21 psb_intel_sdvo_init(dev, SDVOB); 22 return 0; 23 } 24 25 /* 26 * Poulsbo Backlight Interfaces 27 */ 28 29 #define BLC_PWM_PRECISION_FACTOR 100 /* 10000000 */ 30 #define BLC_PWM_FREQ_CALC_CONSTANT 32 31 #define MHz 1000000 32 33 #define PSB_BLC_PWM_PRECISION_FACTOR 10 34 #define PSB_BLC_MAX_PWM_REG_FREQ 0xFFFE 35 #define PSB_BLC_MIN_PWM_REG_FREQ 0x2 36 37 #define PSB_BACKLIGHT_PWM_POLARITY_BIT_CLEAR (0xFFFE) 38 #define PSB_BACKLIGHT_PWM_CTL_SHIFT (16) 39 40 static int psb_backlight_setup(struct drm_device *dev) 41 { 42 struct drm_psb_private *dev_priv = to_drm_psb_private(dev); 43 unsigned long core_clock; 44 /* u32 bl_max_freq; */ 45 /* unsigned long value; */ 46 u16 bl_max_freq; 47 uint32_t value; 48 uint32_t blc_pwm_precision_factor; 49 50 /* get bl_max_freq and pol from dev_priv*/ 51 if (!dev_priv->lvds_bl) { 52 dev_err(dev->dev, "Has no valid LVDS backlight info\n"); 53 return -ENOENT; 54 } 55 bl_max_freq = dev_priv->lvds_bl->freq; 56 blc_pwm_precision_factor = PSB_BLC_PWM_PRECISION_FACTOR; 57 58 core_clock = dev_priv->core_freq; 59 60 value = (core_clock * MHz) / BLC_PWM_FREQ_CALC_CONSTANT; 61 value *= blc_pwm_precision_factor; 62 value /= bl_max_freq; 63 value /= blc_pwm_precision_factor; 64 65 if (value > (unsigned long long)PSB_BLC_MAX_PWM_REG_FREQ || 66 value < (unsigned long long)PSB_BLC_MIN_PWM_REG_FREQ) 67 return -ERANGE; 68 else { 69 value &= PSB_BACKLIGHT_PWM_POLARITY_BIT_CLEAR; 70 REG_WRITE(BLC_PWM_CTL, 71 (value << PSB_BACKLIGHT_PWM_CTL_SHIFT) | (value)); 72 } 73 74 psb_intel_lvds_set_brightness(dev, PSB_MAX_BRIGHTNESS); 75 /* This must occur after the backlight is properly initialised */ 76 psb_lid_timer_init(dev_priv); 77 return 0; 78 } 79 80 /* 81 * Provide the Poulsbo specific chip logic and low level methods 82 * for power management 83 */ 84 85 static void psb_init_pm(struct drm_device *dev) 86 { 87 struct drm_psb_private *dev_priv = to_drm_psb_private(dev); 88 89 u32 gating = PSB_RSGX32(PSB_CR_CLKGATECTL); 90 gating &= ~3; /* Disable 2D clock gating */ 91 gating |= 1; 92 PSB_WSGX32(gating, PSB_CR_CLKGATECTL); 93 PSB_RSGX32(PSB_CR_CLKGATECTL); 94 } 95 96 /** 97 * psb_save_display_registers - save registers lost on suspend 98 * @dev: our DRM device 99 * 100 * Save the state we need in order to be able to restore the interface 101 * upon resume from suspend 102 */ 103 static int psb_save_display_registers(struct drm_device *dev) 104 { 105 struct drm_psb_private *dev_priv = to_drm_psb_private(dev); 106 struct gma_connector *gma_connector; 107 struct drm_crtc *crtc; 108 struct drm_connector_list_iter conn_iter; 109 struct drm_connector *connector; 110 struct psb_state *regs = &dev_priv->regs.psb; 111 112 /* Display arbitration control + watermarks */ 113 regs->saveDSPARB = PSB_RVDC32(DSPARB); 114 regs->saveDSPFW1 = PSB_RVDC32(DSPFW1); 115 regs->saveDSPFW2 = PSB_RVDC32(DSPFW2); 116 regs->saveDSPFW3 = PSB_RVDC32(DSPFW3); 117 regs->saveDSPFW4 = PSB_RVDC32(DSPFW4); 118 regs->saveDSPFW5 = PSB_RVDC32(DSPFW5); 119 regs->saveDSPFW6 = PSB_RVDC32(DSPFW6); 120 regs->saveCHICKENBIT = PSB_RVDC32(DSPCHICKENBIT); 121 122 /* Save crtc and output state */ 123 drm_modeset_lock_all(dev); 124 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { 125 if (drm_helper_crtc_in_use(crtc)) 126 dev_priv->ops->save_crtc(crtc); 127 } 128 129 drm_connector_list_iter_begin(dev, &conn_iter); 130 drm_for_each_connector_iter(connector, &conn_iter) { 131 gma_connector = to_gma_connector(connector); 132 if (gma_connector->save) 133 gma_connector->save(connector); 134 } 135 drm_connector_list_iter_end(&conn_iter); 136 137 drm_modeset_unlock_all(dev); 138 return 0; 139 } 140 141 /** 142 * psb_restore_display_registers - restore lost register state 143 * @dev: our DRM device 144 * 145 * Restore register state that was lost during suspend and resume. 146 */ 147 static int psb_restore_display_registers(struct drm_device *dev) 148 { 149 struct drm_psb_private *dev_priv = to_drm_psb_private(dev); 150 struct gma_connector *gma_connector; 151 struct drm_crtc *crtc; 152 struct drm_connector_list_iter conn_iter; 153 struct drm_connector *connector; 154 struct psb_state *regs = &dev_priv->regs.psb; 155 156 /* Display arbitration + watermarks */ 157 PSB_WVDC32(regs->saveDSPARB, DSPARB); 158 PSB_WVDC32(regs->saveDSPFW1, DSPFW1); 159 PSB_WVDC32(regs->saveDSPFW2, DSPFW2); 160 PSB_WVDC32(regs->saveDSPFW3, DSPFW3); 161 PSB_WVDC32(regs->saveDSPFW4, DSPFW4); 162 PSB_WVDC32(regs->saveDSPFW5, DSPFW5); 163 PSB_WVDC32(regs->saveDSPFW6, DSPFW6); 164 PSB_WVDC32(regs->saveCHICKENBIT, DSPCHICKENBIT); 165 166 /*make sure VGA plane is off. it initializes to on after reset!*/ 167 PSB_WVDC32(0x80000000, VGACNTRL); 168 169 drm_modeset_lock_all(dev); 170 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) 171 if (drm_helper_crtc_in_use(crtc)) 172 dev_priv->ops->restore_crtc(crtc); 173 174 drm_connector_list_iter_begin(dev, &conn_iter); 175 drm_for_each_connector_iter(connector, &conn_iter) { 176 gma_connector = to_gma_connector(connector); 177 if (gma_connector->restore) 178 gma_connector->restore(connector); 179 } 180 drm_connector_list_iter_end(&conn_iter); 181 182 drm_modeset_unlock_all(dev); 183 return 0; 184 } 185 186 static int psb_power_down(struct drm_device *dev) 187 { 188 return 0; 189 } 190 191 static int psb_power_up(struct drm_device *dev) 192 { 193 return 0; 194 } 195 196 /* Poulsbo */ 197 static const struct psb_offset psb_regmap[2] = { 198 { 199 .fp0 = FPA0, 200 .fp1 = FPA1, 201 .cntr = DSPACNTR, 202 .conf = PIPEACONF, 203 .src = PIPEASRC, 204 .dpll = DPLL_A, 205 .htotal = HTOTAL_A, 206 .hblank = HBLANK_A, 207 .hsync = HSYNC_A, 208 .vtotal = VTOTAL_A, 209 .vblank = VBLANK_A, 210 .vsync = VSYNC_A, 211 .stride = DSPASTRIDE, 212 .size = DSPASIZE, 213 .pos = DSPAPOS, 214 .base = DSPABASE, 215 .surf = DSPASURF, 216 .addr = DSPABASE, 217 .status = PIPEASTAT, 218 .linoff = DSPALINOFF, 219 .tileoff = DSPATILEOFF, 220 .palette = PALETTE_A, 221 }, 222 { 223 .fp0 = FPB0, 224 .fp1 = FPB1, 225 .cntr = DSPBCNTR, 226 .conf = PIPEBCONF, 227 .src = PIPEBSRC, 228 .dpll = DPLL_B, 229 .htotal = HTOTAL_B, 230 .hblank = HBLANK_B, 231 .hsync = HSYNC_B, 232 .vtotal = VTOTAL_B, 233 .vblank = VBLANK_B, 234 .vsync = VSYNC_B, 235 .stride = DSPBSTRIDE, 236 .size = DSPBSIZE, 237 .pos = DSPBPOS, 238 .base = DSPBBASE, 239 .surf = DSPBSURF, 240 .addr = DSPBBASE, 241 .status = PIPEBSTAT, 242 .linoff = DSPBLINOFF, 243 .tileoff = DSPBTILEOFF, 244 .palette = PALETTE_B, 245 } 246 }; 247 248 static int psb_chip_setup(struct drm_device *dev) 249 { 250 struct drm_psb_private *dev_priv = to_drm_psb_private(dev); 251 dev_priv->regmap = psb_regmap; 252 gma_get_core_freq(dev); 253 gma_intel_setup_gmbus(dev); 254 psb_intel_opregion_init(dev); 255 psb_intel_init_bios(dev); 256 return 0; 257 } 258 259 static void psb_chip_teardown(struct drm_device *dev) 260 { 261 struct drm_psb_private *dev_priv = to_drm_psb_private(dev); 262 psb_lid_timer_takedown(dev_priv); 263 gma_intel_teardown_gmbus(dev); 264 } 265 266 const struct psb_ops psb_chip_ops = { 267 .name = "Poulsbo", 268 .pipes = 2, 269 .crtcs = 2, 270 .hdmi_mask = (1 << 0), 271 .lvds_mask = (1 << 1), 272 .sdvo_mask = (1 << 0), 273 .cursor_needs_phys = 1, 274 .sgx_offset = PSB_SGX_OFFSET, 275 .chip_setup = psb_chip_setup, 276 .chip_teardown = psb_chip_teardown, 277 278 .crtc_helper = &psb_intel_helper_funcs, 279 .clock_funcs = &psb_clock_funcs, 280 281 .output_init = psb_output_init, 282 283 .backlight_init = psb_backlight_setup, 284 .backlight_set = psb_intel_lvds_set_brightness, 285 .backlight_name = "psb-bl", 286 287 .init_pm = psb_init_pm, 288 .save_regs = psb_save_display_registers, 289 .restore_regs = psb_restore_display_registers, 290 .save_crtc = gma_crtc_save, 291 .restore_crtc = gma_crtc_restore, 292 .power_down = psb_power_down, 293 .power_up = psb_power_up, 294 }; 295 296