0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/backlight.h>
0009
0010 #include <drm/drm.h>
0011
0012 #include "gma_device.h"
0013 #include "intel_bios.h"
0014 #include "psb_device.h"
0015 #include "psb_drv.h"
0016 #include "psb_intel_reg.h"
0017 #include "psb_reg.h"
0018
0019 static int psb_output_init(struct drm_device *dev)
0020 {
0021 struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
0022 psb_intel_lvds_init(dev, &dev_priv->mode_dev);
0023 psb_intel_sdvo_init(dev, SDVOB);
0024 return 0;
0025 }
0026
0027 #ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
0028
0029
0030
0031
0032
0033 #define BLC_PWM_PRECISION_FACTOR 100
0034 #define BLC_PWM_FREQ_CALC_CONSTANT 32
0035 #define MHz 1000000
0036
0037 #define PSB_BLC_PWM_PRECISION_FACTOR 10
0038 #define PSB_BLC_MAX_PWM_REG_FREQ 0xFFFE
0039 #define PSB_BLC_MIN_PWM_REG_FREQ 0x2
0040
0041 #define PSB_BACKLIGHT_PWM_POLARITY_BIT_CLEAR (0xFFFE)
0042 #define PSB_BACKLIGHT_PWM_CTL_SHIFT (16)
0043
0044 static int psb_brightness;
0045 static struct backlight_device *psb_backlight_device;
0046
0047 static int psb_get_brightness(struct backlight_device *bd)
0048 {
0049
0050
0051
0052 return psb_brightness;
0053 }
0054
0055
0056 static int psb_backlight_setup(struct drm_device *dev)
0057 {
0058 struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
0059 unsigned long core_clock;
0060
0061
0062 u16 bl_max_freq;
0063 uint32_t value;
0064 uint32_t blc_pwm_precision_factor;
0065
0066
0067 if (!dev_priv->lvds_bl) {
0068 dev_err(dev->dev, "Has no valid LVDS backlight info\n");
0069 return -ENOENT;
0070 }
0071 bl_max_freq = dev_priv->lvds_bl->freq;
0072 blc_pwm_precision_factor = PSB_BLC_PWM_PRECISION_FACTOR;
0073
0074 core_clock = dev_priv->core_freq;
0075
0076 value = (core_clock * MHz) / BLC_PWM_FREQ_CALC_CONSTANT;
0077 value *= blc_pwm_precision_factor;
0078 value /= bl_max_freq;
0079 value /= blc_pwm_precision_factor;
0080
0081 if (value > (unsigned long long)PSB_BLC_MAX_PWM_REG_FREQ ||
0082 value < (unsigned long long)PSB_BLC_MIN_PWM_REG_FREQ)
0083 return -ERANGE;
0084 else {
0085 value &= PSB_BACKLIGHT_PWM_POLARITY_BIT_CLEAR;
0086 REG_WRITE(BLC_PWM_CTL,
0087 (value << PSB_BACKLIGHT_PWM_CTL_SHIFT) | (value));
0088 }
0089 return 0;
0090 }
0091
0092 static int psb_set_brightness(struct backlight_device *bd)
0093 {
0094 struct drm_device *dev = bl_get_data(psb_backlight_device);
0095 int level = bd->props.brightness;
0096
0097
0098 if (level < 1)
0099 level = 1;
0100
0101 psb_intel_lvds_set_brightness(dev, level);
0102 psb_brightness = level;
0103 return 0;
0104 }
0105
0106 static const struct backlight_ops psb_ops = {
0107 .get_brightness = psb_get_brightness,
0108 .update_status = psb_set_brightness,
0109 };
0110
0111 static int psb_backlight_init(struct drm_device *dev)
0112 {
0113 struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
0114 int ret;
0115 struct backlight_properties props;
0116
0117 memset(&props, 0, sizeof(struct backlight_properties));
0118 props.max_brightness = 100;
0119 props.type = BACKLIGHT_PLATFORM;
0120
0121 psb_backlight_device = backlight_device_register("psb-bl",
0122 NULL, (void *)dev, &psb_ops, &props);
0123 if (IS_ERR(psb_backlight_device))
0124 return PTR_ERR(psb_backlight_device);
0125
0126 ret = psb_backlight_setup(dev);
0127 if (ret < 0) {
0128 backlight_device_unregister(psb_backlight_device);
0129 psb_backlight_device = NULL;
0130 return ret;
0131 }
0132 psb_backlight_device->props.brightness = 100;
0133 psb_backlight_device->props.max_brightness = 100;
0134 backlight_update_status(psb_backlight_device);
0135 dev_priv->backlight_device = psb_backlight_device;
0136
0137
0138 psb_lid_timer_init(dev_priv);
0139
0140 return 0;
0141 }
0142
0143 #endif
0144
0145
0146
0147
0148
0149
0150 static void psb_init_pm(struct drm_device *dev)
0151 {
0152 struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
0153
0154 u32 gating = PSB_RSGX32(PSB_CR_CLKGATECTL);
0155 gating &= ~3;
0156 gating |= 1;
0157 PSB_WSGX32(gating, PSB_CR_CLKGATECTL);
0158 PSB_RSGX32(PSB_CR_CLKGATECTL);
0159 }
0160
0161
0162
0163
0164
0165
0166
0167
0168 static int psb_save_display_registers(struct drm_device *dev)
0169 {
0170 struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
0171 struct gma_connector *gma_connector;
0172 struct drm_crtc *crtc;
0173 struct drm_connector_list_iter conn_iter;
0174 struct drm_connector *connector;
0175 struct psb_state *regs = &dev_priv->regs.psb;
0176
0177
0178 regs->saveDSPARB = PSB_RVDC32(DSPARB);
0179 regs->saveDSPFW1 = PSB_RVDC32(DSPFW1);
0180 regs->saveDSPFW2 = PSB_RVDC32(DSPFW2);
0181 regs->saveDSPFW3 = PSB_RVDC32(DSPFW3);
0182 regs->saveDSPFW4 = PSB_RVDC32(DSPFW4);
0183 regs->saveDSPFW5 = PSB_RVDC32(DSPFW5);
0184 regs->saveDSPFW6 = PSB_RVDC32(DSPFW6);
0185 regs->saveCHICKENBIT = PSB_RVDC32(DSPCHICKENBIT);
0186
0187
0188 drm_modeset_lock_all(dev);
0189 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
0190 if (drm_helper_crtc_in_use(crtc))
0191 dev_priv->ops->save_crtc(crtc);
0192 }
0193
0194 drm_connector_list_iter_begin(dev, &conn_iter);
0195 drm_for_each_connector_iter(connector, &conn_iter) {
0196 gma_connector = to_gma_connector(connector);
0197 if (gma_connector->save)
0198 gma_connector->save(connector);
0199 }
0200 drm_connector_list_iter_end(&conn_iter);
0201
0202 drm_modeset_unlock_all(dev);
0203 return 0;
0204 }
0205
0206
0207
0208
0209
0210
0211
0212 static int psb_restore_display_registers(struct drm_device *dev)
0213 {
0214 struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
0215 struct gma_connector *gma_connector;
0216 struct drm_crtc *crtc;
0217 struct drm_connector_list_iter conn_iter;
0218 struct drm_connector *connector;
0219 struct psb_state *regs = &dev_priv->regs.psb;
0220
0221
0222 PSB_WVDC32(regs->saveDSPARB, DSPARB);
0223 PSB_WVDC32(regs->saveDSPFW1, DSPFW1);
0224 PSB_WVDC32(regs->saveDSPFW2, DSPFW2);
0225 PSB_WVDC32(regs->saveDSPFW3, DSPFW3);
0226 PSB_WVDC32(regs->saveDSPFW4, DSPFW4);
0227 PSB_WVDC32(regs->saveDSPFW5, DSPFW5);
0228 PSB_WVDC32(regs->saveDSPFW6, DSPFW6);
0229 PSB_WVDC32(regs->saveCHICKENBIT, DSPCHICKENBIT);
0230
0231
0232 PSB_WVDC32(0x80000000, VGACNTRL);
0233
0234 drm_modeset_lock_all(dev);
0235 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
0236 if (drm_helper_crtc_in_use(crtc))
0237 dev_priv->ops->restore_crtc(crtc);
0238
0239 drm_connector_list_iter_begin(dev, &conn_iter);
0240 drm_for_each_connector_iter(connector, &conn_iter) {
0241 gma_connector = to_gma_connector(connector);
0242 if (gma_connector->restore)
0243 gma_connector->restore(connector);
0244 }
0245 drm_connector_list_iter_end(&conn_iter);
0246
0247 drm_modeset_unlock_all(dev);
0248 return 0;
0249 }
0250
0251 static int psb_power_down(struct drm_device *dev)
0252 {
0253 return 0;
0254 }
0255
0256 static int psb_power_up(struct drm_device *dev)
0257 {
0258 return 0;
0259 }
0260
0261
0262 static const struct psb_offset psb_regmap[2] = {
0263 {
0264 .fp0 = FPA0,
0265 .fp1 = FPA1,
0266 .cntr = DSPACNTR,
0267 .conf = PIPEACONF,
0268 .src = PIPEASRC,
0269 .dpll = DPLL_A,
0270 .htotal = HTOTAL_A,
0271 .hblank = HBLANK_A,
0272 .hsync = HSYNC_A,
0273 .vtotal = VTOTAL_A,
0274 .vblank = VBLANK_A,
0275 .vsync = VSYNC_A,
0276 .stride = DSPASTRIDE,
0277 .size = DSPASIZE,
0278 .pos = DSPAPOS,
0279 .base = DSPABASE,
0280 .surf = DSPASURF,
0281 .addr = DSPABASE,
0282 .status = PIPEASTAT,
0283 .linoff = DSPALINOFF,
0284 .tileoff = DSPATILEOFF,
0285 .palette = PALETTE_A,
0286 },
0287 {
0288 .fp0 = FPB0,
0289 .fp1 = FPB1,
0290 .cntr = DSPBCNTR,
0291 .conf = PIPEBCONF,
0292 .src = PIPEBSRC,
0293 .dpll = DPLL_B,
0294 .htotal = HTOTAL_B,
0295 .hblank = HBLANK_B,
0296 .hsync = HSYNC_B,
0297 .vtotal = VTOTAL_B,
0298 .vblank = VBLANK_B,
0299 .vsync = VSYNC_B,
0300 .stride = DSPBSTRIDE,
0301 .size = DSPBSIZE,
0302 .pos = DSPBPOS,
0303 .base = DSPBBASE,
0304 .surf = DSPBSURF,
0305 .addr = DSPBBASE,
0306 .status = PIPEBSTAT,
0307 .linoff = DSPBLINOFF,
0308 .tileoff = DSPBTILEOFF,
0309 .palette = PALETTE_B,
0310 }
0311 };
0312
0313 static int psb_chip_setup(struct drm_device *dev)
0314 {
0315 struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
0316 dev_priv->regmap = psb_regmap;
0317 gma_get_core_freq(dev);
0318 gma_intel_setup_gmbus(dev);
0319 psb_intel_opregion_init(dev);
0320 psb_intel_init_bios(dev);
0321 return 0;
0322 }
0323
0324 static void psb_chip_teardown(struct drm_device *dev)
0325 {
0326 struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
0327 psb_lid_timer_takedown(dev_priv);
0328 gma_intel_teardown_gmbus(dev);
0329 }
0330
0331 const struct psb_ops psb_chip_ops = {
0332 .name = "Poulsbo",
0333 .pipes = 2,
0334 .crtcs = 2,
0335 .hdmi_mask = (1 << 0),
0336 .lvds_mask = (1 << 1),
0337 .sdvo_mask = (1 << 0),
0338 .cursor_needs_phys = 1,
0339 .sgx_offset = PSB_SGX_OFFSET,
0340 .chip_setup = psb_chip_setup,
0341 .chip_teardown = psb_chip_teardown,
0342
0343 .crtc_helper = &psb_intel_helper_funcs,
0344 .clock_funcs = &psb_clock_funcs,
0345
0346 .output_init = psb_output_init,
0347
0348 #ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
0349 .backlight_init = psb_backlight_init,
0350 #endif
0351
0352 .init_pm = psb_init_pm,
0353 .save_regs = psb_save_display_registers,
0354 .restore_regs = psb_restore_display_registers,
0355 .save_crtc = gma_crtc_save,
0356 .restore_crtc = gma_crtc_restore,
0357 .power_down = psb_power_down,
0358 .power_up = psb_power_up,
0359 };
0360