Subversion Repositories Kolibri OS

Rev

Rev 4293 | Rev 5060 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * Copyright © 2006-2010 Intel Corporation
  3.  * Copyright (c) 2006 Dave Airlie <airlied@linux.ie>
  4.  *
  5.  * Permission is hereby granted, free of charge, to any person obtaining a
  6.  * copy of this software and associated documentation files (the "Software"),
  7.  * to deal in the Software without restriction, including without limitation
  8.  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  9.  * and/or sell copies of the Software, and to permit persons to whom the
  10.  * Software is furnished to do so, subject to the following conditions:
  11.  *
  12.  * The above copyright notice and this permission notice (including the next
  13.  * paragraph) shall be included in all copies or substantial portions of the
  14.  * Software.
  15.  *
  16.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17.  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  19.  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20.  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  21.  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  22.  * DEALINGS IN THE SOFTWARE.
  23.  *
  24.  * Authors:
  25.  *      Eric Anholt <eric@anholt.net>
  26.  *      Dave Airlie <airlied@linux.ie>
  27.  *      Jesse Barnes <jesse.barnes@intel.com>
  28.  *      Chris Wilson <chris@chris-wilson.co.uk>
  29.  */
  30.  
  31. #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  32.  
  33. #include <linux/moduleparam.h>
  34. #include "intel_drv.h"
  35.  
  36. #define PCI_LBPC 0xf4 /* legacy/combination backlight modes */
  37.  
  38. void
  39. intel_fixed_panel_mode(const struct drm_display_mode *fixed_mode,
  40.                        struct drm_display_mode *adjusted_mode)
  41. {
  42.         drm_mode_copy(adjusted_mode, fixed_mode);
  43.  
  44.         drm_mode_set_crtcinfo(adjusted_mode, 0);
  45. }
  46.  
  47. /* adjusted_mode has been preset to be the panel's fixed mode */
  48. void
  49. intel_pch_panel_fitting(struct intel_crtc *intel_crtc,
  50.                         struct intel_crtc_config *pipe_config,
  51.                         int fitting_mode)
  52. {
  53.         struct drm_display_mode *adjusted_mode;
  54.         int x, y, width, height;
  55.  
  56.         adjusted_mode = &pipe_config->adjusted_mode;
  57.  
  58.         x = y = width = height = 0;
  59.  
  60.         /* Native modes don't need fitting */
  61.         if (adjusted_mode->hdisplay == pipe_config->pipe_src_w &&
  62.             adjusted_mode->vdisplay == pipe_config->pipe_src_h)
  63.                 goto done;
  64.  
  65.         switch (fitting_mode) {
  66.         case DRM_MODE_SCALE_CENTER:
  67.                 width = pipe_config->pipe_src_w;
  68.                 height = pipe_config->pipe_src_h;
  69.                 x = (adjusted_mode->hdisplay - width + 1)/2;
  70.                 y = (adjusted_mode->vdisplay - height + 1)/2;
  71.                 break;
  72.  
  73.         case DRM_MODE_SCALE_ASPECT:
  74.                 /* Scale but preserve the aspect ratio */
  75.                 {
  76.                         u32 scaled_width = adjusted_mode->hdisplay
  77.                                 * pipe_config->pipe_src_h;
  78.                         u32 scaled_height = pipe_config->pipe_src_w
  79.                                 * adjusted_mode->vdisplay;
  80.                         if (scaled_width > scaled_height) { /* pillar */
  81.                                 width = scaled_height / pipe_config->pipe_src_h;
  82.                                 if (width & 1)
  83.                                         width++;
  84.                                 x = (adjusted_mode->hdisplay - width + 1) / 2;
  85.                                 y = 0;
  86.                                 height = adjusted_mode->vdisplay;
  87.                         } else if (scaled_width < scaled_height) { /* letter */
  88.                                 height = scaled_width / pipe_config->pipe_src_w;
  89.                                 if (height & 1)
  90.                                     height++;
  91.                                 y = (adjusted_mode->vdisplay - height + 1) / 2;
  92.                                 x = 0;
  93.                                 width = adjusted_mode->hdisplay;
  94.                         } else {
  95.                                 x = y = 0;
  96.                                 width = adjusted_mode->hdisplay;
  97.                                 height = adjusted_mode->vdisplay;
  98.                         }
  99.                 }
  100.                 break;
  101.  
  102.         case DRM_MODE_SCALE_FULLSCREEN:
  103.                 x = y = 0;
  104.                 width = adjusted_mode->hdisplay;
  105.                 height = adjusted_mode->vdisplay;
  106.                 break;
  107.  
  108.         default:
  109.                 WARN(1, "bad panel fit mode: %d\n", fitting_mode);
  110.                 return;
  111.         }
  112.  
  113. done:
  114.         pipe_config->pch_pfit.pos = (x << 16) | y;
  115.         pipe_config->pch_pfit.size = (width << 16) | height;
  116.         pipe_config->pch_pfit.enabled = pipe_config->pch_pfit.size != 0;
  117. }
  118.  
  119. static void
  120. centre_horizontally(struct drm_display_mode *mode,
  121.                     int width)
  122. {
  123.         u32 border, sync_pos, blank_width, sync_width;
  124.  
  125.         /* keep the hsync and hblank widths constant */
  126.         sync_width = mode->crtc_hsync_end - mode->crtc_hsync_start;
  127.         blank_width = mode->crtc_hblank_end - mode->crtc_hblank_start;
  128.         sync_pos = (blank_width - sync_width + 1) / 2;
  129.  
  130.         border = (mode->hdisplay - width + 1) / 2;
  131.         border += border & 1; /* make the border even */
  132.  
  133.         mode->crtc_hdisplay = width;
  134.         mode->crtc_hblank_start = width + border;
  135.         mode->crtc_hblank_end = mode->crtc_hblank_start + blank_width;
  136.  
  137.         mode->crtc_hsync_start = mode->crtc_hblank_start + sync_pos;
  138.         mode->crtc_hsync_end = mode->crtc_hsync_start + sync_width;
  139. }
  140.  
  141. static void
  142. centre_vertically(struct drm_display_mode *mode,
  143.                   int height)
  144. {
  145.         u32 border, sync_pos, blank_width, sync_width;
  146.  
  147.         /* keep the vsync and vblank widths constant */
  148.         sync_width = mode->crtc_vsync_end - mode->crtc_vsync_start;
  149.         blank_width = mode->crtc_vblank_end - mode->crtc_vblank_start;
  150.         sync_pos = (blank_width - sync_width + 1) / 2;
  151.  
  152.         border = (mode->vdisplay - height + 1) / 2;
  153.  
  154.         mode->crtc_vdisplay = height;
  155.         mode->crtc_vblank_start = height + border;
  156.         mode->crtc_vblank_end = mode->crtc_vblank_start + blank_width;
  157.  
  158.         mode->crtc_vsync_start = mode->crtc_vblank_start + sync_pos;
  159.         mode->crtc_vsync_end = mode->crtc_vsync_start + sync_width;
  160. }
  161.  
  162. static inline u32 panel_fitter_scaling(u32 source, u32 target)
  163. {
  164.         /*
  165.          * Floating point operation is not supported. So the FACTOR
  166.          * is defined, which can avoid the floating point computation
  167.          * when calculating the panel ratio.
  168.          */
  169. #define ACCURACY 12
  170. #define FACTOR (1 << ACCURACY)
  171.         u32 ratio = source * FACTOR / target;
  172.         return (FACTOR * ratio + FACTOR/2) / FACTOR;
  173. }
  174.  
  175. static void i965_scale_aspect(struct intel_crtc_config *pipe_config,
  176.                               u32 *pfit_control)
  177. {
  178.         struct drm_display_mode *adjusted_mode = &pipe_config->adjusted_mode;
  179.                         u32 scaled_width = adjusted_mode->hdisplay *
  180.                 pipe_config->pipe_src_h;
  181.         u32 scaled_height = pipe_config->pipe_src_w *
  182.                                 adjusted_mode->vdisplay;
  183.  
  184.                         /* 965+ is easy, it does everything in hw */
  185.                         if (scaled_width > scaled_height)
  186.                 *pfit_control |= PFIT_ENABLE |
  187.                                         PFIT_SCALING_PILLAR;
  188.                         else if (scaled_width < scaled_height)
  189.                 *pfit_control |= PFIT_ENABLE |
  190.                                         PFIT_SCALING_LETTER;
  191.         else if (adjusted_mode->hdisplay != pipe_config->pipe_src_w)
  192.                 *pfit_control |= PFIT_ENABLE | PFIT_SCALING_AUTO;
  193. }
  194.  
  195. static void i9xx_scale_aspect(struct intel_crtc_config *pipe_config,
  196.                               u32 *pfit_control, u32 *pfit_pgm_ratios,
  197.                               u32 *border)
  198. {
  199.         struct drm_display_mode *adjusted_mode = &pipe_config->adjusted_mode;
  200.                         u32 scaled_width = adjusted_mode->hdisplay *
  201.                 pipe_config->pipe_src_h;
  202.         u32 scaled_height = pipe_config->pipe_src_w *
  203.                                 adjusted_mode->vdisplay;
  204.         u32 bits;
  205.  
  206.                         /*
  207.                          * For earlier chips we have to calculate the scaling
  208.                          * ratio by hand and program it into the
  209.                          * PFIT_PGM_RATIO register
  210.                          */
  211.                         if (scaled_width > scaled_height) { /* pillar */
  212.                                 centre_horizontally(adjusted_mode,
  213.                                                     scaled_height /
  214.                                     pipe_config->pipe_src_h);
  215.  
  216.                 *border = LVDS_BORDER_ENABLE;
  217.                 if (pipe_config->pipe_src_h != adjusted_mode->vdisplay) {
  218.                         bits = panel_fitter_scaling(pipe_config->pipe_src_h,
  219.                                                     adjusted_mode->vdisplay);
  220.  
  221.                         *pfit_pgm_ratios |= (bits << PFIT_HORIZ_SCALE_SHIFT |
  222.                                                             bits << PFIT_VERT_SCALE_SHIFT);
  223.                         *pfit_control |= (PFIT_ENABLE |
  224.                                                          VERT_INTERP_BILINEAR |
  225.                                                          HORIZ_INTERP_BILINEAR);
  226.                                 }
  227.                         } else if (scaled_width < scaled_height) { /* letter */
  228.                                 centre_vertically(adjusted_mode,
  229.                                                   scaled_width /
  230.                                   pipe_config->pipe_src_w);
  231.  
  232.                 *border = LVDS_BORDER_ENABLE;
  233.                 if (pipe_config->pipe_src_w != adjusted_mode->hdisplay) {
  234.                         bits = panel_fitter_scaling(pipe_config->pipe_src_w,
  235.                                                     adjusted_mode->hdisplay);
  236.  
  237.                         *pfit_pgm_ratios |= (bits << PFIT_HORIZ_SCALE_SHIFT |
  238.                                                             bits << PFIT_VERT_SCALE_SHIFT);
  239.                         *pfit_control |= (PFIT_ENABLE |
  240.                                                          VERT_INTERP_BILINEAR |
  241.                                                          HORIZ_INTERP_BILINEAR);
  242.                                 }
  243.                         } else {
  244.                                 /* Aspects match, Let hw scale both directions */
  245.                 *pfit_control |= (PFIT_ENABLE |
  246.                                                  VERT_AUTO_SCALE | HORIZ_AUTO_SCALE |
  247.                                                  VERT_INTERP_BILINEAR |
  248.                                                  HORIZ_INTERP_BILINEAR);
  249.                         }
  250. }
  251.  
  252. void intel_gmch_panel_fitting(struct intel_crtc *intel_crtc,
  253.                               struct intel_crtc_config *pipe_config,
  254.                               int fitting_mode)
  255. {
  256.         struct drm_device *dev = intel_crtc->base.dev;
  257.         u32 pfit_control = 0, pfit_pgm_ratios = 0, border = 0;
  258.         struct drm_display_mode *adjusted_mode;
  259.  
  260.         adjusted_mode = &pipe_config->adjusted_mode;
  261.  
  262.         /* Native modes don't need fitting */
  263.         if (adjusted_mode->hdisplay == pipe_config->pipe_src_w &&
  264.             adjusted_mode->vdisplay == pipe_config->pipe_src_h)
  265.                 goto out;
  266.  
  267.         switch (fitting_mode) {
  268.         case DRM_MODE_SCALE_CENTER:
  269.                 /*
  270.                  * For centered modes, we have to calculate border widths &
  271.                  * heights and modify the values programmed into the CRTC.
  272.                  */
  273.                 centre_horizontally(adjusted_mode, pipe_config->pipe_src_w);
  274.                 centre_vertically(adjusted_mode, pipe_config->pipe_src_h);
  275.                 border = LVDS_BORDER_ENABLE;
  276.                 break;
  277.         case DRM_MODE_SCALE_ASPECT:
  278.                 /* Scale but preserve the aspect ratio */
  279.                 if (INTEL_INFO(dev)->gen >= 4)
  280.                         i965_scale_aspect(pipe_config, &pfit_control);
  281.                 else
  282.                         i9xx_scale_aspect(pipe_config, &pfit_control,
  283.                                           &pfit_pgm_ratios, &border);
  284.                 break;
  285.         case DRM_MODE_SCALE_FULLSCREEN:
  286.                 /*
  287.                  * Full scaling, even if it changes the aspect ratio.
  288.                  * Fortunately this is all done for us in hw.
  289.                  */
  290.                 if (pipe_config->pipe_src_h != adjusted_mode->vdisplay ||
  291.                     pipe_config->pipe_src_w != adjusted_mode->hdisplay) {
  292.                         pfit_control |= PFIT_ENABLE;
  293.                         if (INTEL_INFO(dev)->gen >= 4)
  294.                                 pfit_control |= PFIT_SCALING_AUTO;
  295.                         else
  296.                                 pfit_control |= (VERT_AUTO_SCALE |
  297.                                                  VERT_INTERP_BILINEAR |
  298.                                                  HORIZ_AUTO_SCALE |
  299.                                                  HORIZ_INTERP_BILINEAR);
  300.                 }
  301.                 break;
  302.         default:
  303.                 WARN(1, "bad panel fit mode: %d\n", fitting_mode);
  304.                 return;
  305.         }
  306.  
  307.         /* 965+ wants fuzzy fitting */
  308.         /* FIXME: handle multiple panels by failing gracefully */
  309.         if (INTEL_INFO(dev)->gen >= 4)
  310.                 pfit_control |= ((intel_crtc->pipe << PFIT_PIPE_SHIFT) |
  311.                                  PFIT_FILTER_FUZZY);
  312.  
  313. out:
  314.         if ((pfit_control & PFIT_ENABLE) == 0) {
  315.                 pfit_control = 0;
  316.                 pfit_pgm_ratios = 0;
  317.         }
  318.  
  319.         /* Make sure pre-965 set dither correctly for 18bpp panels. */
  320.         if (INTEL_INFO(dev)->gen < 4 && pipe_config->pipe_bpp == 18)
  321.                 pfit_control |= PANEL_8TO6_DITHER_ENABLE;
  322.  
  323.         pipe_config->gmch_pfit.control = pfit_control;
  324.         pipe_config->gmch_pfit.pgm_ratios = pfit_pgm_ratios;
  325.         pipe_config->gmch_pfit.lvds_border_bits = border;
  326. }
  327.  
  328. static int i915_panel_invert_brightness;
  329. MODULE_PARM_DESC(invert_brightness, "Invert backlight brightness "
  330.         "(-1 force normal, 0 machine defaults, 1 force inversion), please "
  331.         "report PCI device ID, subsystem vendor and subsystem device ID "
  332.         "to dri-devel@lists.freedesktop.org, if your machine needs it. "
  333.         "It will then be included in an upcoming module version.");
  334. module_param_named(invert_brightness, i915_panel_invert_brightness, int, 0600);
  335. static u32 intel_panel_compute_brightness(struct intel_connector *connector,
  336.                                           u32 val)
  337. {
  338.         struct drm_device *dev = connector->base.dev;
  339.         struct drm_i915_private *dev_priv = dev->dev_private;
  340.         struct intel_panel *panel = &connector->panel;
  341.  
  342.         WARN_ON(panel->backlight.max == 0);
  343.  
  344.         if (i915_panel_invert_brightness < 0)
  345.                 return val;
  346.  
  347.         if (i915_panel_invert_brightness > 0 ||
  348.             dev_priv->quirks & QUIRK_INVERT_BRIGHTNESS) {
  349.                 return panel->backlight.max - val;
  350.         }
  351.  
  352.         return val;
  353. }
  354.  
  355. static u32 bdw_get_backlight(struct intel_connector *connector)
  356. {
  357.         struct drm_device *dev = connector->base.dev;
  358.         struct drm_i915_private *dev_priv = dev->dev_private;
  359.  
  360.         return I915_READ(BLC_PWM_PCH_CTL2) & BACKLIGHT_DUTY_CYCLE_MASK;
  361. }
  362.  
  363. static u32 pch_get_backlight(struct intel_connector *connector)
  364. {
  365.         struct drm_device *dev = connector->base.dev;
  366.         struct drm_i915_private *dev_priv = dev->dev_private;
  367.  
  368.         return I915_READ(BLC_PWM_CPU_CTL) & BACKLIGHT_DUTY_CYCLE_MASK;
  369. }
  370.  
  371. static u32 i9xx_get_backlight(struct intel_connector *connector)
  372. {
  373.         struct drm_device *dev = connector->base.dev;
  374.         struct drm_i915_private *dev_priv = dev->dev_private;
  375.         struct intel_panel *panel = &connector->panel;
  376.         u32 val;
  377.  
  378.         val = I915_READ(BLC_PWM_CTL) & BACKLIGHT_DUTY_CYCLE_MASK;
  379.         if (INTEL_INFO(dev)->gen < 4)
  380.                 val >>= 1;
  381.  
  382.         if (panel->backlight.combination_mode) {
  383.                 u8 lbpc;
  384.  
  385.                 pci_read_config_byte(dev->pdev, PCI_LBPC, &lbpc);
  386.                 val *= lbpc;
  387.         }
  388.  
  389.         return val;
  390. }
  391.  
  392. static u32 _vlv_get_backlight(struct drm_device *dev, enum pipe pipe)
  393. {
  394.         struct drm_i915_private *dev_priv = dev->dev_private;
  395.  
  396.         return I915_READ(VLV_BLC_PWM_CTL(pipe)) & BACKLIGHT_DUTY_CYCLE_MASK;
  397. }
  398.  
  399. static u32 vlv_get_backlight(struct intel_connector *connector)
  400. {
  401.         struct drm_device *dev = connector->base.dev;
  402.         enum pipe pipe = intel_get_pipe_from_connector(connector);
  403.  
  404.         return _vlv_get_backlight(dev, pipe);
  405. }
  406.  
  407. static u32 intel_panel_get_backlight(struct intel_connector *connector)
  408. {
  409.         struct drm_device *dev = connector->base.dev;
  410.         struct drm_i915_private *dev_priv = dev->dev_private;
  411.         u32 val;
  412.         unsigned long flags;
  413.  
  414.         spin_lock_irqsave(&dev_priv->backlight_lock, flags);
  415.  
  416.         val = dev_priv->display.get_backlight(connector);
  417.         val = intel_panel_compute_brightness(connector, val);
  418.  
  419.         spin_unlock_irqrestore(&dev_priv->backlight_lock, flags);
  420.  
  421.         DRM_DEBUG_DRIVER("get backlight PWM = %d\n", val);
  422.         return val;
  423. }
  424.  
  425. static void bdw_set_backlight(struct intel_connector *connector, u32 level)
  426. {
  427.         struct drm_device *dev = connector->base.dev;
  428.         struct drm_i915_private *dev_priv = dev->dev_private;
  429.         u32 val = I915_READ(BLC_PWM_PCH_CTL2) & ~BACKLIGHT_DUTY_CYCLE_MASK;
  430.         I915_WRITE(BLC_PWM_PCH_CTL2, val | level);
  431. }
  432.  
  433. static void pch_set_backlight(struct intel_connector *connector, u32 level)
  434. {
  435.         struct drm_device *dev = connector->base.dev;
  436.         struct drm_i915_private *dev_priv = dev->dev_private;
  437.         u32 tmp;
  438.  
  439.         tmp = I915_READ(BLC_PWM_CPU_CTL) & ~BACKLIGHT_DUTY_CYCLE_MASK;
  440.         I915_WRITE(BLC_PWM_CPU_CTL, tmp | level);
  441. }
  442.  
  443. static void i9xx_set_backlight(struct intel_connector *connector, u32 level)
  444. {
  445.         struct drm_device *dev = connector->base.dev;
  446.         struct drm_i915_private *dev_priv = dev->dev_private;
  447.         struct intel_panel *panel = &connector->panel;
  448.         u32 tmp, mask;
  449.  
  450.         WARN_ON(panel->backlight.max == 0);
  451.  
  452.         if (panel->backlight.combination_mode) {
  453.                 u8 lbpc;
  454.  
  455.                 lbpc = level * 0xfe / panel->backlight.max + 1;
  456.                 level /= lbpc;
  457.                 pci_write_config_byte(dev->pdev, PCI_LBPC, lbpc);
  458.         }
  459.  
  460.         if (IS_GEN4(dev)) {
  461.                 mask = BACKLIGHT_DUTY_CYCLE_MASK;
  462.         } else {
  463.                 level <<= 1;
  464.                 mask = BACKLIGHT_DUTY_CYCLE_MASK_PNV;
  465.         }
  466.  
  467.         tmp = I915_READ(BLC_PWM_CTL) & ~mask;
  468.         I915_WRITE(BLC_PWM_CTL, tmp | level);
  469. }
  470.  
  471. static void vlv_set_backlight(struct intel_connector *connector, u32 level)
  472. {
  473.         struct drm_device *dev = connector->base.dev;
  474.         struct drm_i915_private *dev_priv = dev->dev_private;
  475.         enum pipe pipe = intel_get_pipe_from_connector(connector);
  476.         u32 tmp;
  477.  
  478.         tmp = I915_READ(VLV_BLC_PWM_CTL(pipe)) & ~BACKLIGHT_DUTY_CYCLE_MASK;
  479.         I915_WRITE(VLV_BLC_PWM_CTL(pipe), tmp | level);
  480. }
  481.  
  482. static void
  483. intel_panel_actually_set_backlight(struct intel_connector *connector, u32 level)
  484. {
  485.         struct drm_device *dev = connector->base.dev;
  486.         struct drm_i915_private *dev_priv = dev->dev_private;
  487.  
  488.         DRM_DEBUG_DRIVER("set backlight PWM = %d\n", level);
  489.  
  490.         level = intel_panel_compute_brightness(connector, level);
  491.         dev_priv->display.set_backlight(connector, level);
  492. }
  493.  
  494. /* set backlight brightness to level in range [0..max] */
  495. void intel_panel_set_backlight(struct intel_connector *connector, u32 level,
  496.                                u32 max)
  497. {
  498.         struct drm_device *dev = connector->base.dev;
  499.         struct drm_i915_private *dev_priv = dev->dev_private;
  500.         struct intel_panel *panel = &connector->panel;
  501.         enum pipe pipe = intel_get_pipe_from_connector(connector);
  502.         u32 freq;
  503.         unsigned long flags;
  504.  
  505.         if (!panel->backlight.present || pipe == INVALID_PIPE)
  506.                 return;
  507.  
  508.         spin_lock_irqsave(&dev_priv->backlight_lock, flags);
  509.  
  510.         WARN_ON(panel->backlight.max == 0);
  511.  
  512.         /* scale to hardware max, but be careful to not overflow */
  513.         freq = panel->backlight.max;
  514.         if (freq < max)
  515.                 level = level * freq / max;
  516.         else
  517.                 level = freq / max * level;
  518.  
  519.         panel->backlight.level = level;
  520. //      if (panel->backlight.device)
  521. //              panel->backlight.device->props.brightness = level;
  522.  
  523.         if (panel->backlight.enabled)
  524.                 intel_panel_actually_set_backlight(connector, level);
  525.  
  526.         spin_unlock_irqrestore(&dev_priv->backlight_lock, flags);
  527. }
  528.  
  529. static void pch_disable_backlight(struct intel_connector *connector)
  530. {
  531.         struct drm_device *dev = connector->base.dev;
  532.         struct drm_i915_private *dev_priv = dev->dev_private;
  533.         u32 tmp;
  534.  
  535.         intel_panel_actually_set_backlight(connector, 0);
  536.  
  537.         tmp = I915_READ(BLC_PWM_CPU_CTL2);
  538.         I915_WRITE(BLC_PWM_CPU_CTL2, tmp & ~BLM_PWM_ENABLE);
  539.  
  540.         tmp = I915_READ(BLC_PWM_PCH_CTL1);
  541.         I915_WRITE(BLC_PWM_PCH_CTL1, tmp & ~BLM_PCH_PWM_ENABLE);
  542. }
  543.  
  544. static void i9xx_disable_backlight(struct intel_connector *connector)
  545. {
  546.         intel_panel_actually_set_backlight(connector, 0);
  547. }
  548.  
  549. static void i965_disable_backlight(struct intel_connector *connector)
  550. {
  551.         struct drm_device *dev = connector->base.dev;
  552.         struct drm_i915_private *dev_priv = dev->dev_private;
  553.         u32 tmp;
  554.  
  555.         intel_panel_actually_set_backlight(connector, 0);
  556.  
  557.         tmp = I915_READ(BLC_PWM_CTL2);
  558.         I915_WRITE(BLC_PWM_CTL2, tmp & ~BLM_PWM_ENABLE);
  559. }
  560.  
  561. static void vlv_disable_backlight(struct intel_connector *connector)
  562. {
  563.         struct drm_device *dev = connector->base.dev;
  564.         struct drm_i915_private *dev_priv = dev->dev_private;
  565.         enum pipe pipe = intel_get_pipe_from_connector(connector);
  566.         u32 tmp;
  567.  
  568.         intel_panel_actually_set_backlight(connector, 0);
  569.  
  570.         tmp = I915_READ(VLV_BLC_PWM_CTL2(pipe));
  571.         I915_WRITE(VLV_BLC_PWM_CTL2(pipe), tmp & ~BLM_PWM_ENABLE);
  572. }
  573.  
  574. void intel_panel_disable_backlight(struct intel_connector *connector)
  575. {
  576.         struct drm_device *dev = connector->base.dev;
  577.         struct drm_i915_private *dev_priv = dev->dev_private;
  578.         struct intel_panel *panel = &connector->panel;
  579.         enum pipe pipe = intel_get_pipe_from_connector(connector);
  580.         unsigned long flags;
  581.  
  582.         if (!panel->backlight.present || pipe == INVALID_PIPE)
  583.                 return;
  584.  
  585.         /*
  586.          * Do not disable backlight on the vgaswitcheroo path. When switching
  587.          * away from i915, the other client may depend on i915 to handle the
  588.          * backlight. This will leave the backlight on unnecessarily when
  589.          * another client is not activated.
  590.          */
  591.         if (dev->switch_power_state == DRM_SWITCH_POWER_CHANGING) {
  592.                 DRM_DEBUG_DRIVER("Skipping backlight disable on vga switch\n");
  593.                 return;
  594.         }
  595.  
  596.         spin_lock_irqsave(&dev_priv->backlight_lock, flags);
  597.  
  598.         panel->backlight.enabled = false;
  599.         dev_priv->display.disable_backlight(connector);
  600.  
  601.         spin_unlock_irqrestore(&dev_priv->backlight_lock, flags);
  602. }
  603.  
  604. static void bdw_enable_backlight(struct intel_connector *connector)
  605. {
  606.         struct drm_device *dev = connector->base.dev;
  607.         struct drm_i915_private *dev_priv = dev->dev_private;
  608.         struct intel_panel *panel = &connector->panel;
  609.         u32 pch_ctl1, pch_ctl2;
  610.  
  611.         pch_ctl1 = I915_READ(BLC_PWM_PCH_CTL1);
  612.         if (pch_ctl1 & BLM_PCH_PWM_ENABLE) {
  613.                 DRM_DEBUG_KMS("pch backlight already enabled\n");
  614.                 pch_ctl1 &= ~BLM_PCH_PWM_ENABLE;
  615.                 I915_WRITE(BLC_PWM_PCH_CTL1, pch_ctl1);
  616.         }
  617.  
  618.         pch_ctl2 = panel->backlight.max << 16;
  619.         I915_WRITE(BLC_PWM_PCH_CTL2, pch_ctl2);
  620.  
  621.         pch_ctl1 = 0;
  622.         if (panel->backlight.active_low_pwm)
  623.                 pch_ctl1 |= BLM_PCH_POLARITY;
  624.  
  625.         /* BDW always uses the pch pwm controls. */
  626.         pch_ctl1 |= BLM_PCH_OVERRIDE_ENABLE;
  627.  
  628.         I915_WRITE(BLC_PWM_PCH_CTL1, pch_ctl1);
  629.         POSTING_READ(BLC_PWM_PCH_CTL1);
  630.         I915_WRITE(BLC_PWM_PCH_CTL1, pch_ctl1 | BLM_PCH_PWM_ENABLE);
  631.  
  632.         /* This won't stick until the above enable. */
  633.         intel_panel_actually_set_backlight(connector, panel->backlight.level);
  634. }
  635.  
  636. static void pch_enable_backlight(struct intel_connector *connector)
  637. {
  638.         struct drm_device *dev = connector->base.dev;
  639.         struct drm_i915_private *dev_priv = dev->dev_private;
  640.         struct intel_panel *panel = &connector->panel;
  641.         enum pipe pipe = intel_get_pipe_from_connector(connector);
  642.         enum transcoder cpu_transcoder =
  643.                 intel_pipe_to_cpu_transcoder(dev_priv, pipe);
  644.         u32 cpu_ctl2, pch_ctl1, pch_ctl2;
  645.  
  646.         cpu_ctl2 = I915_READ(BLC_PWM_CPU_CTL2);
  647.         if (cpu_ctl2 & BLM_PWM_ENABLE) {
  648.                 WARN(1, "cpu backlight already enabled\n");
  649.                 cpu_ctl2 &= ~BLM_PWM_ENABLE;
  650.                 I915_WRITE(BLC_PWM_CPU_CTL2, cpu_ctl2);
  651.         }
  652.  
  653.         pch_ctl1 = I915_READ(BLC_PWM_PCH_CTL1);
  654.         if (pch_ctl1 & BLM_PCH_PWM_ENABLE) {
  655.                 DRM_DEBUG_KMS("pch backlight already enabled\n");
  656.                 pch_ctl1 &= ~BLM_PCH_PWM_ENABLE;
  657.                 I915_WRITE(BLC_PWM_PCH_CTL1, pch_ctl1);
  658.         }
  659.  
  660.         if (cpu_transcoder == TRANSCODER_EDP)
  661.                 cpu_ctl2 = BLM_TRANSCODER_EDP;
  662.         else
  663.                 cpu_ctl2 = BLM_PIPE(cpu_transcoder);
  664.         I915_WRITE(BLC_PWM_CPU_CTL2, cpu_ctl2);
  665.         POSTING_READ(BLC_PWM_CPU_CTL2);
  666.         I915_WRITE(BLC_PWM_CPU_CTL2, cpu_ctl2 | BLM_PWM_ENABLE);
  667.  
  668.         /* This won't stick until the above enable. */
  669.         intel_panel_actually_set_backlight(connector, panel->backlight.level);
  670.  
  671.         pch_ctl2 = panel->backlight.max << 16;
  672.         I915_WRITE(BLC_PWM_PCH_CTL2, pch_ctl2);
  673.  
  674.         pch_ctl1 = 0;
  675.         if (panel->backlight.active_low_pwm)
  676.                 pch_ctl1 |= BLM_PCH_POLARITY;
  677.  
  678.         I915_WRITE(BLC_PWM_PCH_CTL1, pch_ctl1);
  679.         POSTING_READ(BLC_PWM_PCH_CTL1);
  680.         I915_WRITE(BLC_PWM_PCH_CTL1, pch_ctl1 | BLM_PCH_PWM_ENABLE);
  681. }
  682.  
  683. static void i9xx_enable_backlight(struct intel_connector *connector)
  684. {
  685.         struct drm_device *dev = connector->base.dev;
  686.         struct drm_i915_private *dev_priv = dev->dev_private;
  687.         struct intel_panel *panel = &connector->panel;
  688.         u32 ctl, freq;
  689.  
  690.         ctl = I915_READ(BLC_PWM_CTL);
  691.         if (ctl & BACKLIGHT_DUTY_CYCLE_MASK_PNV) {
  692.                 WARN(1, "backlight already enabled\n");
  693.                 I915_WRITE(BLC_PWM_CTL, 0);
  694.         }
  695.  
  696.         freq = panel->backlight.max;
  697.         if (panel->backlight.combination_mode)
  698.                 freq /= 0xff;
  699.  
  700.         ctl = freq << 17;
  701.         if (IS_GEN2(dev) && panel->backlight.combination_mode)
  702.                 ctl |= BLM_LEGACY_MODE;
  703.         if (IS_PINEVIEW(dev) && panel->backlight.active_low_pwm)
  704.                 ctl |= BLM_POLARITY_PNV;
  705.  
  706.         I915_WRITE(BLC_PWM_CTL, ctl);
  707.         POSTING_READ(BLC_PWM_CTL);
  708.  
  709.         /* XXX: combine this into above write? */
  710.         intel_panel_actually_set_backlight(connector, panel->backlight.level);
  711. }
  712.  
  713. static void i965_enable_backlight(struct intel_connector *connector)
  714. {
  715.         struct drm_device *dev = connector->base.dev;
  716.         struct drm_i915_private *dev_priv = dev->dev_private;
  717.         struct intel_panel *panel = &connector->panel;
  718.         enum pipe pipe = intel_get_pipe_from_connector(connector);
  719.         u32 ctl, ctl2, freq;
  720.  
  721.         ctl2 = I915_READ(BLC_PWM_CTL2);
  722.         if (ctl2 & BLM_PWM_ENABLE) {
  723.                 WARN(1, "backlight already enabled\n");
  724.                 ctl2 &= ~BLM_PWM_ENABLE;
  725.                 I915_WRITE(BLC_PWM_CTL2, ctl2);
  726.                 }
  727.  
  728.         freq = panel->backlight.max;
  729.         if (panel->backlight.combination_mode)
  730.                 freq /= 0xff;
  731.  
  732.         ctl = freq << 16;
  733.         I915_WRITE(BLC_PWM_CTL, ctl);
  734.  
  735.         /* XXX: combine this into above write? */
  736.         intel_panel_actually_set_backlight(connector, panel->backlight.level);
  737.  
  738.         ctl2 = BLM_PIPE(pipe);
  739.         if (panel->backlight.combination_mode)
  740.                 ctl2 |= BLM_COMBINATION_MODE;
  741.         if (panel->backlight.active_low_pwm)
  742.                 ctl2 |= BLM_POLARITY_I965;
  743.         I915_WRITE(BLC_PWM_CTL2, ctl2);
  744.         POSTING_READ(BLC_PWM_CTL2);
  745.         I915_WRITE(BLC_PWM_CTL2, ctl2 | BLM_PWM_ENABLE);
  746. }
  747.  
  748. static void vlv_enable_backlight(struct intel_connector *connector)
  749. {
  750.         struct drm_device *dev = connector->base.dev;
  751.         struct drm_i915_private *dev_priv = dev->dev_private;
  752.         struct intel_panel *panel = &connector->panel;
  753.         enum pipe pipe = intel_get_pipe_from_connector(connector);
  754.         u32 ctl, ctl2;
  755.  
  756.         ctl2 = I915_READ(VLV_BLC_PWM_CTL2(pipe));
  757.         if (ctl2 & BLM_PWM_ENABLE) {
  758.                 WARN(1, "backlight already enabled\n");
  759.                 ctl2 &= ~BLM_PWM_ENABLE;
  760.                 I915_WRITE(VLV_BLC_PWM_CTL2(pipe), ctl2);
  761.         }
  762.  
  763.         ctl = panel->backlight.max << 16;
  764.         I915_WRITE(VLV_BLC_PWM_CTL(pipe), ctl);
  765.  
  766.         /* XXX: combine this into above write? */
  767.         intel_panel_actually_set_backlight(connector, panel->backlight.level);
  768.  
  769.         ctl2 = 0;
  770.         if (panel->backlight.active_low_pwm)
  771.                 ctl2 |= BLM_POLARITY_I965;
  772.         I915_WRITE(VLV_BLC_PWM_CTL2(pipe), ctl2);
  773.         POSTING_READ(VLV_BLC_PWM_CTL2(pipe));
  774.         I915_WRITE(VLV_BLC_PWM_CTL2(pipe), ctl2 | BLM_PWM_ENABLE);
  775. }
  776.  
  777. void intel_panel_enable_backlight(struct intel_connector *connector)
  778. {
  779.         struct drm_device *dev = connector->base.dev;
  780.         struct drm_i915_private *dev_priv = dev->dev_private;
  781.         struct intel_panel *panel = &connector->panel;
  782.         enum pipe pipe = intel_get_pipe_from_connector(connector);
  783.         unsigned long flags;
  784.  
  785.         if (!panel->backlight.present || pipe == INVALID_PIPE)
  786.                 return;
  787.  
  788.         DRM_DEBUG_KMS("pipe %c\n", pipe_name(pipe));
  789.  
  790.         spin_lock_irqsave(&dev_priv->backlight_lock, flags);
  791.  
  792.         WARN_ON(panel->backlight.max == 0);
  793.  
  794.         if (panel->backlight.level == 0) {
  795.                 panel->backlight.level = panel->backlight.max;
  796. //              if (panel->backlight.device)
  797. //                      panel->backlight.device->props.brightness =
  798. //                              panel->backlight.level;
  799.         }
  800.  
  801.         dev_priv->display.enable_backlight(connector);
  802.         panel->backlight.enabled = true;
  803.  
  804.         spin_unlock_irqrestore(&dev_priv->backlight_lock, flags);
  805. }
  806.  
  807. enum drm_connector_status
  808. intel_panel_detect(struct drm_device *dev)
  809. {
  810.         struct drm_i915_private *dev_priv = dev->dev_private;
  811.  
  812.         /* Assume that the BIOS does not lie through the OpRegion... */
  813.         if (!i915_panel_ignore_lid && dev_priv->opregion.lid_state) {
  814.                 return ioread32(dev_priv->opregion.lid_state) & 0x1 ?
  815.                         connector_status_connected :
  816.                         connector_status_disconnected;
  817.         }
  818.  
  819.         switch (i915_panel_ignore_lid) {
  820.         case -2:
  821.                 return connector_status_connected;
  822.         case -1:
  823.                 return connector_status_disconnected;
  824.         default:
  825.         return connector_status_unknown;
  826.         }
  827. }
  828.  
  829. #if IS_ENABLED(CONFIG_BACKLIGHT_CLASS_DEVICE)
  830. static int intel_backlight_device_update_status(struct backlight_device *bd)
  831. {
  832.         struct intel_connector *connector = bl_get_data(bd);
  833.         struct drm_device *dev = connector->base.dev;
  834.  
  835.         mutex_lock(&dev->mode_config.mutex);
  836.         DRM_DEBUG_KMS("updating intel_backlight, brightness=%d/%d\n",
  837.                       bd->props.brightness, bd->props.max_brightness);
  838.         intel_panel_set_backlight(connector, bd->props.brightness,
  839.                                   bd->props.max_brightness);
  840.         mutex_unlock(&dev->mode_config.mutex);
  841.         return 0;
  842. }
  843.  
  844. static int intel_backlight_device_get_brightness(struct backlight_device *bd)
  845. {
  846.         struct intel_connector *connector = bl_get_data(bd);
  847.         struct drm_device *dev = connector->base.dev;
  848.         struct drm_i915_private *dev_priv = dev->dev_private;
  849.         int ret;
  850.  
  851.         intel_runtime_pm_get(dev_priv);
  852.         mutex_lock(&dev->mode_config.mutex);
  853.         ret = intel_panel_get_backlight(connector);
  854.         mutex_unlock(&dev->mode_config.mutex);
  855.         intel_runtime_pm_put(dev_priv);
  856.  
  857.         return ret;
  858. }
  859.  
  860. static const struct backlight_ops intel_backlight_device_ops = {
  861.         .update_status = intel_backlight_device_update_status,
  862.         .get_brightness = intel_backlight_device_get_brightness,
  863. };
  864.  
  865. static int intel_backlight_device_register(struct intel_connector *connector)
  866. {
  867.         struct intel_panel *panel = &connector->panel;
  868.         struct backlight_properties props;
  869.  
  870.         if (WARN_ON(panel->backlight.device))
  871.                 return -ENODEV;
  872.  
  873.         BUG_ON(panel->backlight.max == 0);
  874.  
  875.         memset(&props, 0, sizeof(props));
  876.         props.type = BACKLIGHT_RAW;
  877.         props.brightness = panel->backlight.level;
  878.         props.max_brightness = panel->backlight.max;
  879.  
  880.         /*
  881.          * Note: using the same name independent of the connector prevents
  882.          * registration of multiple backlight devices in the driver.
  883.          */
  884.         panel->backlight.device =
  885.                 backlight_device_register("intel_backlight",
  886.                                           connector->base.kdev,
  887.                                           connector,
  888.                                           &intel_backlight_device_ops, &props);
  889.  
  890.         if (IS_ERR(panel->backlight.device)) {
  891.                 DRM_ERROR("Failed to register backlight: %ld\n",
  892.                           PTR_ERR(panel->backlight.device));
  893.                 panel->backlight.device = NULL;
  894.                 return -ENODEV;
  895.         }
  896.         return 0;
  897. }
  898.  
  899. static void intel_backlight_device_unregister(struct intel_connector *connector)
  900. {
  901.         struct intel_panel *panel = &connector->panel;
  902.  
  903.         if (panel->backlight.device) {
  904.                 backlight_device_unregister(panel->backlight.device);
  905.                 panel->backlight.device = NULL;
  906.         }
  907. }
  908. #else /* CONFIG_BACKLIGHT_CLASS_DEVICE */
  909. static int intel_backlight_device_register(struct intel_connector *connector)
  910. {
  911.         return 0;
  912. }
  913. static void intel_backlight_device_unregister(struct intel_connector *connector)
  914. {
  915. }
  916. #endif /* CONFIG_BACKLIGHT_CLASS_DEVICE */
  917.  
  918. /*
  919.  * Note: The setup hooks can't assume pipe is set!
  920.  *
  921.  * XXX: Query mode clock or hardware clock and program PWM modulation frequency
  922.  * appropriately when it's 0. Use VBT and/or sane defaults.
  923.  */
  924. static int bdw_setup_backlight(struct intel_connector *connector)
  925. {
  926.         struct drm_device *dev = connector->base.dev;
  927.         struct drm_i915_private *dev_priv = dev->dev_private;
  928.         struct intel_panel *panel = &connector->panel;
  929.         u32 pch_ctl1, pch_ctl2, val;
  930.  
  931.         pch_ctl1 = I915_READ(BLC_PWM_PCH_CTL1);
  932.         panel->backlight.active_low_pwm = pch_ctl1 & BLM_PCH_POLARITY;
  933.  
  934.         pch_ctl2 = I915_READ(BLC_PWM_PCH_CTL2);
  935.         panel->backlight.max = pch_ctl2 >> 16;
  936.         if (!panel->backlight.max)
  937.                 return -ENODEV;
  938.  
  939.         val = bdw_get_backlight(connector);
  940.         panel->backlight.level = intel_panel_compute_brightness(connector, val);
  941.  
  942.         panel->backlight.enabled = (pch_ctl1 & BLM_PCH_PWM_ENABLE) &&
  943.                 panel->backlight.level != 0;
  944.  
  945.         return 0;
  946. }
  947.  
  948. static int pch_setup_backlight(struct intel_connector *connector)
  949. {
  950.         struct drm_device *dev = connector->base.dev;
  951.         struct drm_i915_private *dev_priv = dev->dev_private;
  952.         struct intel_panel *panel = &connector->panel;
  953.         u32 cpu_ctl2, pch_ctl1, pch_ctl2, val;
  954.  
  955.         pch_ctl1 = I915_READ(BLC_PWM_PCH_CTL1);
  956.         panel->backlight.active_low_pwm = pch_ctl1 & BLM_PCH_POLARITY;
  957.  
  958.         pch_ctl2 = I915_READ(BLC_PWM_PCH_CTL2);
  959.         panel->backlight.max = pch_ctl2 >> 16;
  960.         if (!panel->backlight.max)
  961.                 return -ENODEV;
  962.  
  963.         val = pch_get_backlight(connector);
  964.         panel->backlight.level = intel_panel_compute_brightness(connector, val);
  965.  
  966.         cpu_ctl2 = I915_READ(BLC_PWM_CPU_CTL2);
  967.         panel->backlight.enabled = (cpu_ctl2 & BLM_PWM_ENABLE) &&
  968.                 (pch_ctl1 & BLM_PCH_PWM_ENABLE) && panel->backlight.level != 0;
  969.  
  970.         return 0;
  971. }
  972.  
  973. static int i9xx_setup_backlight(struct intel_connector *connector)
  974. {
  975.         struct drm_device *dev = connector->base.dev;
  976.         struct drm_i915_private *dev_priv = dev->dev_private;
  977.         struct intel_panel *panel = &connector->panel;
  978.         u32 ctl, val;
  979.  
  980.         ctl = I915_READ(BLC_PWM_CTL);
  981.  
  982.         if (IS_GEN2(dev))
  983.                 panel->backlight.combination_mode = ctl & BLM_LEGACY_MODE;
  984.  
  985.         if (IS_PINEVIEW(dev))
  986.                 panel->backlight.active_low_pwm = ctl & BLM_POLARITY_PNV;
  987.  
  988.         panel->backlight.max = ctl >> 17;
  989.         if (panel->backlight.combination_mode)
  990.                 panel->backlight.max *= 0xff;
  991.  
  992.         if (!panel->backlight.max)
  993.                 return -ENODEV;
  994.  
  995.         val = i9xx_get_backlight(connector);
  996.         panel->backlight.level = intel_panel_compute_brightness(connector, val);
  997.  
  998.         panel->backlight.enabled = panel->backlight.level != 0;
  999.  
  1000.         return 0;
  1001. }
  1002.  
  1003. static int i965_setup_backlight(struct intel_connector *connector)
  1004. {
  1005.         struct drm_device *dev = connector->base.dev;
  1006.         struct drm_i915_private *dev_priv = dev->dev_private;
  1007.         struct intel_panel *panel = &connector->panel;
  1008.         u32 ctl, ctl2, val;
  1009.  
  1010.         ctl2 = I915_READ(BLC_PWM_CTL2);
  1011.         panel->backlight.combination_mode = ctl2 & BLM_COMBINATION_MODE;
  1012.         panel->backlight.active_low_pwm = ctl2 & BLM_POLARITY_I965;
  1013.  
  1014.         ctl = I915_READ(BLC_PWM_CTL);
  1015.         panel->backlight.max = ctl >> 16;
  1016.         if (panel->backlight.combination_mode)
  1017.                 panel->backlight.max *= 0xff;
  1018.  
  1019.         if (!panel->backlight.max)
  1020.                 return -ENODEV;
  1021.  
  1022.         val = i9xx_get_backlight(connector);
  1023.         panel->backlight.level = intel_panel_compute_brightness(connector, val);
  1024.  
  1025.         panel->backlight.enabled = (ctl2 & BLM_PWM_ENABLE) &&
  1026.                 panel->backlight.level != 0;
  1027.  
  1028.         return 0;
  1029. }
  1030.  
  1031. static int vlv_setup_backlight(struct intel_connector *connector)
  1032. {
  1033.         struct drm_device *dev = connector->base.dev;
  1034.         struct drm_i915_private *dev_priv = dev->dev_private;
  1035.         struct intel_panel *panel = &connector->panel;
  1036.         enum pipe pipe;
  1037.         u32 ctl, ctl2, val;
  1038.  
  1039.         for_each_pipe(pipe) {
  1040.                 u32 cur_val = I915_READ(VLV_BLC_PWM_CTL(pipe));
  1041.  
  1042.                 /* Skip if the modulation freq is already set */
  1043.                 if (cur_val & ~BACKLIGHT_DUTY_CYCLE_MASK)
  1044.                         continue;
  1045.  
  1046.                 cur_val &= BACKLIGHT_DUTY_CYCLE_MASK;
  1047.                 I915_WRITE(VLV_BLC_PWM_CTL(pipe), (0xf42 << 16) |
  1048.                            cur_val);
  1049.         }
  1050.  
  1051.         ctl2 = I915_READ(VLV_BLC_PWM_CTL2(PIPE_A));
  1052.         panel->backlight.active_low_pwm = ctl2 & BLM_POLARITY_I965;
  1053.  
  1054.         ctl = I915_READ(VLV_BLC_PWM_CTL(PIPE_A));
  1055.         panel->backlight.max = ctl >> 16;
  1056.         if (!panel->backlight.max)
  1057.                 return -ENODEV;
  1058.  
  1059.         val = _vlv_get_backlight(dev, PIPE_A);
  1060.         panel->backlight.level = intel_panel_compute_brightness(connector, val);
  1061.  
  1062.         panel->backlight.enabled = (ctl2 & BLM_PWM_ENABLE) &&
  1063.                 panel->backlight.level != 0;
  1064.  
  1065.         return 0;
  1066. }
  1067.  
  1068. int intel_panel_setup_backlight(struct drm_connector *connector)
  1069. {
  1070.         struct drm_device *dev = connector->dev;
  1071.         struct drm_i915_private *dev_priv = dev->dev_private;
  1072.         struct intel_connector *intel_connector = to_intel_connector(connector);
  1073.         struct intel_panel *panel = &intel_connector->panel;
  1074.         unsigned long flags;
  1075.         int ret;
  1076.  
  1077.         /* set level and max in panel struct */
  1078.         spin_lock_irqsave(&dev_priv->backlight_lock, flags);
  1079.         ret = dev_priv->display.setup_backlight(intel_connector);
  1080.         spin_unlock_irqrestore(&dev_priv->backlight_lock, flags);
  1081.  
  1082.         if (ret) {
  1083.                 DRM_DEBUG_KMS("failed to setup backlight for connector %s\n",
  1084.                               drm_get_connector_name(connector));
  1085.                 return ret;
  1086.         }
  1087.  
  1088.         intel_backlight_device_register(intel_connector);
  1089.  
  1090.         panel->backlight.present = true;
  1091.  
  1092.         DRM_DEBUG_KMS("backlight initialized, %s, brightness %u/%u, "
  1093.                       "sysfs interface %sregistered\n",
  1094.                       panel->backlight.enabled ? "enabled" : "disabled",
  1095.                       panel->backlight.level, panel->backlight.max,
  1096.                       panel->backlight.device ? "" : "not ");
  1097.  
  1098.         return 0;
  1099. }
  1100.  
  1101. void intel_panel_destroy_backlight(struct drm_connector *connector)
  1102. {
  1103.         struct intel_connector *intel_connector = to_intel_connector(connector);
  1104.         struct intel_panel *panel = &intel_connector->panel;
  1105.  
  1106.         panel->backlight.present = false;
  1107.         intel_backlight_device_unregister(intel_connector);
  1108. }
  1109.  
  1110. /**
  1111.  * intel_find_panel_downclock - find the reduced downclock for LVDS in EDID
  1112.  * @dev: drm device
  1113.  * @fixed_mode : panel native mode
  1114.  * @connector: LVDS/eDP connector
  1115.  *
  1116.  * Return downclock_avail
  1117.  * Find the reduced downclock for LVDS/eDP in EDID.
  1118.  */
  1119. struct drm_display_mode *
  1120. intel_find_panel_downclock(struct drm_device *dev,
  1121.                         struct drm_display_mode *fixed_mode,
  1122.                         struct drm_connector *connector)
  1123. {
  1124.         struct drm_display_mode *scan, *tmp_mode;
  1125.         int temp_downclock;
  1126.  
  1127.         temp_downclock = fixed_mode->clock;
  1128.         tmp_mode = NULL;
  1129.  
  1130.         list_for_each_entry(scan, &connector->probed_modes, head) {
  1131.                 /*
  1132.                  * If one mode has the same resolution with the fixed_panel
  1133.                  * mode while they have the different refresh rate, it means
  1134.                  * that the reduced downclock is found. In such
  1135.                  * case we can set the different FPx0/1 to dynamically select
  1136.                  * between low and high frequency.
  1137.                  */
  1138.                 if (scan->hdisplay == fixed_mode->hdisplay &&
  1139.                     scan->hsync_start == fixed_mode->hsync_start &&
  1140.                     scan->hsync_end == fixed_mode->hsync_end &&
  1141.                     scan->htotal == fixed_mode->htotal &&
  1142.                     scan->vdisplay == fixed_mode->vdisplay &&
  1143.                     scan->vsync_start == fixed_mode->vsync_start &&
  1144.                     scan->vsync_end == fixed_mode->vsync_end &&
  1145.                     scan->vtotal == fixed_mode->vtotal) {
  1146.                         if (scan->clock < temp_downclock) {
  1147.                                 /*
  1148.                                  * The downclock is already found. But we
  1149.                                  * expect to find the lower downclock.
  1150.                                  */
  1151.                                 temp_downclock = scan->clock;
  1152.                                 tmp_mode = scan;
  1153.                         }
  1154.                 }
  1155.         }
  1156.  
  1157.         if (temp_downclock < fixed_mode->clock)
  1158.                 return drm_mode_duplicate(dev, tmp_mode);
  1159.         else
  1160.                 return NULL;
  1161. }
  1162.  
  1163. /* Set up chip specific backlight functions */
  1164. void intel_panel_init_backlight_funcs(struct drm_device *dev)
  1165. {
  1166.         struct drm_i915_private *dev_priv = dev->dev_private;
  1167.  
  1168.         if (IS_BROADWELL(dev)) {
  1169.                 dev_priv->display.setup_backlight = bdw_setup_backlight;
  1170.                 dev_priv->display.enable_backlight = bdw_enable_backlight;
  1171.                 dev_priv->display.disable_backlight = pch_disable_backlight;
  1172.                 dev_priv->display.set_backlight = bdw_set_backlight;
  1173.                 dev_priv->display.get_backlight = bdw_get_backlight;
  1174.         } else if (HAS_PCH_SPLIT(dev)) {
  1175.                 dev_priv->display.setup_backlight = pch_setup_backlight;
  1176.                 dev_priv->display.enable_backlight = pch_enable_backlight;
  1177.                 dev_priv->display.disable_backlight = pch_disable_backlight;
  1178.                 dev_priv->display.set_backlight = pch_set_backlight;
  1179.                 dev_priv->display.get_backlight = pch_get_backlight;
  1180.         } else if (IS_VALLEYVIEW(dev)) {
  1181.                 dev_priv->display.setup_backlight = vlv_setup_backlight;
  1182.                 dev_priv->display.enable_backlight = vlv_enable_backlight;
  1183.                 dev_priv->display.disable_backlight = vlv_disable_backlight;
  1184.                 dev_priv->display.set_backlight = vlv_set_backlight;
  1185.                 dev_priv->display.get_backlight = vlv_get_backlight;
  1186.         } else if (IS_GEN4(dev)) {
  1187.                 dev_priv->display.setup_backlight = i965_setup_backlight;
  1188.                 dev_priv->display.enable_backlight = i965_enable_backlight;
  1189.                 dev_priv->display.disable_backlight = i965_disable_backlight;
  1190.                 dev_priv->display.set_backlight = i9xx_set_backlight;
  1191.                 dev_priv->display.get_backlight = i9xx_get_backlight;
  1192.         } else {
  1193.                 dev_priv->display.setup_backlight = i9xx_setup_backlight;
  1194.                 dev_priv->display.enable_backlight = i9xx_enable_backlight;
  1195.                 dev_priv->display.disable_backlight = i9xx_disable_backlight;
  1196.                 dev_priv->display.set_backlight = i9xx_set_backlight;
  1197.                 dev_priv->display.get_backlight = i9xx_get_backlight;
  1198.         }
  1199. }
  1200.  
  1201. int intel_panel_init(struct intel_panel *panel,
  1202.                      struct drm_display_mode *fixed_mode)
  1203. {
  1204.         panel->fixed_mode = fixed_mode;
  1205.  
  1206.         return 0;
  1207. }
  1208.  
  1209. void intel_panel_fini(struct intel_panel *panel)
  1210. {
  1211.         struct intel_connector *intel_connector =
  1212.                 container_of(panel, struct intel_connector, panel);
  1213.  
  1214.         if (panel->fixed_mode)
  1215.                 drm_mode_destroy(intel_connector->base.dev, panel->fixed_mode);
  1216.  
  1217.         if (panel->downclock_mode)
  1218.                 drm_mode_destroy(intel_connector->base.dev,
  1219.                                 panel->downclock_mode);
  1220. }
  1221.