root/drivers/gpu/drm/gma500/psb_device.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. psb_output_init
  2. psb_get_brightness
  3. psb_backlight_setup
  4. psb_set_brightness
  5. psb_backlight_init
  6. psb_init_pm
  7. psb_save_display_registers
  8. psb_restore_display_registers
  9. psb_power_down
  10. psb_power_up
  11. psb_chip_setup
  12. psb_chip_teardown

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

/* [<][>][^][v][top][bottom][index][help] */