Subversion Repositories Kolibri OS

Rev

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

  1. /*
  2.  * Copyright © 2011 Intel Corporation
  3.  *
  4.  * Permission is hereby granted, free of charge, to any person obtaining a
  5.  * copy of this software and associated documentation files (the "Software"),
  6.  * to deal in the Software without restriction, including without limitation
  7.  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  8.  * and/or sell copies of the Software, and to permit persons to whom the
  9.  * Software is furnished to do so, subject to the following conditions:
  10.  *
  11.  * The above copyright notice and this permission notice (including the next
  12.  * paragraph) shall be included in all copies or substantial portions of the
  13.  * Software.
  14.  *
  15.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16.  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  18.  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19.  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  20.  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  21.  * SOFTWARE.
  22.  *
  23.  * Authors:
  24.  *   Jesse Barnes <jbarnes@virtuousgeek.org>
  25.  *
  26.  * New plane/sprite handling.
  27.  *
  28.  * The older chips had a separate interface for programming plane related
  29.  * registers; newer ones are much simpler and we can use the new DRM plane
  30.  * support.
  31.  */
  32. #include <drm/drmP.h>
  33. #include <drm/drm_crtc.h>
  34. #include <drm/drm_fourcc.h>
  35. #include "intel_drv.h"
  36. #include <drm/i915_drm.h>
  37. #include "i915_drv.h"
  38.  
  39. static void
  40. vlv_update_plane(struct drm_plane *dplane, struct drm_framebuffer *fb,
  41.                  struct drm_i915_gem_object *obj, int crtc_x, int crtc_y,
  42.                  unsigned int crtc_w, unsigned int crtc_h,
  43.                  uint32_t x, uint32_t y,
  44.                  uint32_t src_w, uint32_t src_h)
  45. {
  46.         struct drm_device *dev = dplane->dev;
  47.         struct drm_i915_private *dev_priv = dev->dev_private;
  48.         struct intel_plane *intel_plane = to_intel_plane(dplane);
  49.         int pipe = intel_plane->pipe;
  50.         int plane = intel_plane->plane;
  51.         u32 sprctl;
  52.         unsigned long sprsurf_offset, linear_offset;
  53.         int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
  54.  
  55.         sprctl = I915_READ(SPCNTR(pipe, plane));
  56.  
  57.         /* Mask out pixel format bits in case we change it */
  58.         sprctl &= ~SP_PIXFORMAT_MASK;
  59.         sprctl &= ~SP_YUV_BYTE_ORDER_MASK;
  60.         sprctl &= ~SP_TILED;
  61.  
  62.         switch (fb->pixel_format) {
  63.         case DRM_FORMAT_YUYV:
  64.                 sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_YUYV;
  65.                 break;
  66.         case DRM_FORMAT_YVYU:
  67.                 sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_YVYU;
  68.                 break;
  69.         case DRM_FORMAT_UYVY:
  70.                 sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_UYVY;
  71.                 break;
  72.         case DRM_FORMAT_VYUY:
  73.                 sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_VYUY;
  74.                 break;
  75.         case DRM_FORMAT_RGB565:
  76.                 sprctl |= SP_FORMAT_BGR565;
  77.                 break;
  78.         case DRM_FORMAT_XRGB8888:
  79.                 sprctl |= SP_FORMAT_BGRX8888;
  80.                 break;
  81.         case DRM_FORMAT_ARGB8888:
  82.                 sprctl |= SP_FORMAT_BGRA8888;
  83.                 break;
  84.         case DRM_FORMAT_XBGR2101010:
  85.                 sprctl |= SP_FORMAT_RGBX1010102;
  86.                 break;
  87.         case DRM_FORMAT_ABGR2101010:
  88.                 sprctl |= SP_FORMAT_RGBA1010102;
  89.                 break;
  90.         case DRM_FORMAT_XBGR8888:
  91.                 sprctl |= SP_FORMAT_RGBX8888;
  92.                 break;
  93.         case DRM_FORMAT_ABGR8888:
  94.                 sprctl |= SP_FORMAT_RGBA8888;
  95.                 break;
  96.         default:
  97.                 /*
  98.                  * If we get here one of the upper layers failed to filter
  99.                  * out the unsupported plane formats
  100.                  */
  101.                 BUG();
  102.                 break;
  103.         }
  104.  
  105.         if (obj->tiling_mode != I915_TILING_NONE)
  106.                 sprctl |= SP_TILED;
  107.  
  108.         sprctl |= SP_ENABLE;
  109.  
  110.         /* Sizes are 0 based */
  111.         src_w--;
  112.         src_h--;
  113.         crtc_w--;
  114.         crtc_h--;
  115.  
  116.         intel_update_sprite_watermarks(dev, pipe, crtc_w, pixel_size);
  117.  
  118.         I915_WRITE(SPSTRIDE(pipe, plane), fb->pitches[0]);
  119.         I915_WRITE(SPPOS(pipe, plane), (crtc_y << 16) | crtc_x);
  120.  
  121.         linear_offset = y * fb->pitches[0] + x * pixel_size;
  122.         sprsurf_offset = intel_gen4_compute_page_offset(&x, &y,
  123.                                                         obj->tiling_mode,
  124.                                                         pixel_size,
  125.                                                         fb->pitches[0]);
  126.         linear_offset -= sprsurf_offset;
  127.  
  128.         if (obj->tiling_mode != I915_TILING_NONE)
  129.                 I915_WRITE(SPTILEOFF(pipe, plane), (y << 16) | x);
  130.         else
  131.                 I915_WRITE(SPLINOFF(pipe, plane), linear_offset);
  132.  
  133.         I915_WRITE(SPSIZE(pipe, plane), (crtc_h << 16) | crtc_w);
  134.         I915_WRITE(SPCNTR(pipe, plane), sprctl);
  135.         I915_MODIFY_DISPBASE(SPSURF(pipe, plane), obj->gtt_offset +
  136.                              sprsurf_offset);
  137.         POSTING_READ(SPSURF(pipe, plane));
  138. }
  139.  
  140. static void
  141. vlv_disable_plane(struct drm_plane *dplane)
  142. {
  143.         struct drm_device *dev = dplane->dev;
  144.         struct drm_i915_private *dev_priv = dev->dev_private;
  145.         struct intel_plane *intel_plane = to_intel_plane(dplane);
  146.         int pipe = intel_plane->pipe;
  147.         int plane = intel_plane->plane;
  148.  
  149.         I915_WRITE(SPCNTR(pipe, plane), I915_READ(SPCNTR(pipe, plane)) &
  150.                    ~SP_ENABLE);
  151.         /* Activate double buffered register update */
  152.         I915_MODIFY_DISPBASE(SPSURF(pipe, plane), 0);
  153.         POSTING_READ(SPSURF(pipe, plane));
  154. }
  155.  
  156. static int
  157. vlv_update_colorkey(struct drm_plane *dplane,
  158.                     struct drm_intel_sprite_colorkey *key)
  159. {
  160.         struct drm_device *dev = dplane->dev;
  161.         struct drm_i915_private *dev_priv = dev->dev_private;
  162.         struct intel_plane *intel_plane = to_intel_plane(dplane);
  163.         int pipe = intel_plane->pipe;
  164.         int plane = intel_plane->plane;
  165.         u32 sprctl;
  166.  
  167.         if (key->flags & I915_SET_COLORKEY_DESTINATION)
  168.                 return -EINVAL;
  169.  
  170.         I915_WRITE(SPKEYMINVAL(pipe, plane), key->min_value);
  171.         I915_WRITE(SPKEYMAXVAL(pipe, plane), key->max_value);
  172.         I915_WRITE(SPKEYMSK(pipe, plane), key->channel_mask);
  173.  
  174.         sprctl = I915_READ(SPCNTR(pipe, plane));
  175.         sprctl &= ~SP_SOURCE_KEY;
  176.         if (key->flags & I915_SET_COLORKEY_SOURCE)
  177.                 sprctl |= SP_SOURCE_KEY;
  178.         I915_WRITE(SPCNTR(pipe, plane), sprctl);
  179.  
  180.         POSTING_READ(SPKEYMSK(pipe, plane));
  181.  
  182.         return 0;
  183. }
  184.  
  185. static void
  186. vlv_get_colorkey(struct drm_plane *dplane,
  187.                  struct drm_intel_sprite_colorkey *key)
  188. {
  189.         struct drm_device *dev = dplane->dev;
  190.         struct drm_i915_private *dev_priv = dev->dev_private;
  191.         struct intel_plane *intel_plane = to_intel_plane(dplane);
  192.         int pipe = intel_plane->pipe;
  193.         int plane = intel_plane->plane;
  194.         u32 sprctl;
  195.  
  196.         key->min_value = I915_READ(SPKEYMINVAL(pipe, plane));
  197.         key->max_value = I915_READ(SPKEYMAXVAL(pipe, plane));
  198.         key->channel_mask = I915_READ(SPKEYMSK(pipe, plane));
  199.  
  200.         sprctl = I915_READ(SPCNTR(pipe, plane));
  201.         if (sprctl & SP_SOURCE_KEY)
  202.                 key->flags = I915_SET_COLORKEY_SOURCE;
  203.         else
  204.                 key->flags = I915_SET_COLORKEY_NONE;
  205. }
  206.  
  207. static void
  208. ivb_update_plane(struct drm_plane *plane, struct drm_framebuffer *fb,
  209.                  struct drm_i915_gem_object *obj, int crtc_x, int crtc_y,
  210.                  unsigned int crtc_w, unsigned int crtc_h,
  211.                  uint32_t x, uint32_t y,
  212.                  uint32_t src_w, uint32_t src_h)
  213. {
  214.         struct drm_device *dev = plane->dev;
  215.         struct drm_i915_private *dev_priv = dev->dev_private;
  216.         struct intel_plane *intel_plane = to_intel_plane(plane);
  217.         int pipe = intel_plane->pipe;
  218.         u32 sprctl, sprscale = 0;
  219.         unsigned long sprsurf_offset, linear_offset;
  220.         int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
  221.         bool scaling_was_enabled = dev_priv->sprite_scaling_enabled;
  222.  
  223.         sprctl = I915_READ(SPRCTL(pipe));
  224.  
  225.         /* Mask out pixel format bits in case we change it */
  226.         sprctl &= ~SPRITE_PIXFORMAT_MASK;
  227.         sprctl &= ~SPRITE_RGB_ORDER_RGBX;
  228.         sprctl &= ~SPRITE_YUV_BYTE_ORDER_MASK;
  229.         sprctl &= ~SPRITE_TILED;
  230.  
  231.         switch (fb->pixel_format) {
  232.         case DRM_FORMAT_XBGR8888:
  233.                 sprctl |= SPRITE_FORMAT_RGBX888 | SPRITE_RGB_ORDER_RGBX;
  234.                 break;
  235.         case DRM_FORMAT_XRGB8888:
  236.                 sprctl |= SPRITE_FORMAT_RGBX888;
  237.                 break;
  238.         case DRM_FORMAT_YUYV:
  239.                 sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_YUYV;
  240.                 break;
  241.         case DRM_FORMAT_YVYU:
  242.                 sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_YVYU;
  243.                 break;
  244.         case DRM_FORMAT_UYVY:
  245.                 sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_UYVY;
  246.                 break;
  247.         case DRM_FORMAT_VYUY:
  248.                 sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_VYUY;
  249.                 break;
  250.         default:
  251.                 BUG();
  252.         }
  253.  
  254.         if (obj->tiling_mode != I915_TILING_NONE)
  255.                 sprctl |= SPRITE_TILED;
  256.  
  257.         /* must disable */
  258.         sprctl |= SPRITE_TRICKLE_FEED_DISABLE;
  259.         sprctl |= SPRITE_ENABLE;
  260.  
  261.         if (IS_HASWELL(dev))
  262.                 sprctl |= SPRITE_PIPE_CSC_ENABLE;
  263.  
  264.         /* Sizes are 0 based */
  265.         src_w--;
  266.         src_h--;
  267.         crtc_w--;
  268.         crtc_h--;
  269.  
  270.         intel_update_sprite_watermarks(dev, pipe, crtc_w, pixel_size);
  271.  
  272.         /*
  273.          * IVB workaround: must disable low power watermarks for at least
  274.          * one frame before enabling scaling.  LP watermarks can be re-enabled
  275.          * when scaling is disabled.
  276.          */
  277.         if (crtc_w != src_w || crtc_h != src_h) {
  278.                 dev_priv->sprite_scaling_enabled |= 1 << pipe;
  279.  
  280.                 if (!scaling_was_enabled) {
  281.                         intel_update_watermarks(dev);
  282.                 intel_wait_for_vblank(dev, pipe);
  283.                 }
  284.                 sprscale = SPRITE_SCALE_ENABLE | (src_w << 16) | src_h;
  285.         } else
  286.                 dev_priv->sprite_scaling_enabled &= ~(1 << pipe);
  287.  
  288.         I915_WRITE(SPRSTRIDE(pipe), fb->pitches[0]);
  289.         I915_WRITE(SPRPOS(pipe), (crtc_y << 16) | crtc_x);
  290.  
  291.         linear_offset = y * fb->pitches[0] + x * pixel_size;
  292.         sprsurf_offset =
  293.                 intel_gen4_compute_page_offset(&x, &y, obj->tiling_mode,
  294.                                                  pixel_size, fb->pitches[0]);
  295.         linear_offset -= sprsurf_offset;
  296.  
  297.         /* HSW consolidates SPRTILEOFF and SPRLINOFF into a single SPROFFSET
  298.          * register */
  299.         if (IS_HASWELL(dev))
  300.                 I915_WRITE(SPROFFSET(pipe), (y << 16) | x);
  301.         else if (obj->tiling_mode != I915_TILING_NONE)
  302.                 I915_WRITE(SPRTILEOFF(pipe), (y << 16) | x);
  303.         else
  304.                 I915_WRITE(SPRLINOFF(pipe), linear_offset);
  305.  
  306.         I915_WRITE(SPRSIZE(pipe), (crtc_h << 16) | crtc_w);
  307.         if (intel_plane->can_scale)
  308.         I915_WRITE(SPRSCALE(pipe), sprscale);
  309.         I915_WRITE(SPRCTL(pipe), sprctl);
  310.         I915_MODIFY_DISPBASE(SPRSURF(pipe), obj->gtt_offset + sprsurf_offset);
  311.         POSTING_READ(SPRSURF(pipe));
  312.  
  313.         /* potentially re-enable LP watermarks */
  314.         if (scaling_was_enabled && !dev_priv->sprite_scaling_enabled)
  315.                 intel_update_watermarks(dev);
  316. }
  317.  
  318. static void
  319. ivb_disable_plane(struct drm_plane *plane)
  320. {
  321.         struct drm_device *dev = plane->dev;
  322.         struct drm_i915_private *dev_priv = dev->dev_private;
  323.         struct intel_plane *intel_plane = to_intel_plane(plane);
  324.         int pipe = intel_plane->pipe;
  325.         bool scaling_was_enabled = dev_priv->sprite_scaling_enabled;
  326.  
  327.         I915_WRITE(SPRCTL(pipe), I915_READ(SPRCTL(pipe)) & ~SPRITE_ENABLE);
  328.         /* Can't leave the scaler enabled... */
  329.         if (intel_plane->can_scale)
  330.         I915_WRITE(SPRSCALE(pipe), 0);
  331.         /* Activate double buffered register update */
  332.         I915_MODIFY_DISPBASE(SPRSURF(pipe), 0);
  333.         POSTING_READ(SPRSURF(pipe));
  334.  
  335.         dev_priv->sprite_scaling_enabled &= ~(1 << pipe);
  336.  
  337.         /* potentially re-enable LP watermarks */
  338.         if (scaling_was_enabled && !dev_priv->sprite_scaling_enabled)
  339.         intel_update_watermarks(dev);
  340. }
  341.  
  342. static int
  343. ivb_update_colorkey(struct drm_plane *plane,
  344.                     struct drm_intel_sprite_colorkey *key)
  345. {
  346.         struct drm_device *dev = plane->dev;
  347.         struct drm_i915_private *dev_priv = dev->dev_private;
  348.         struct intel_plane *intel_plane;
  349.         u32 sprctl;
  350.         int ret = 0;
  351.  
  352.         intel_plane = to_intel_plane(plane);
  353.  
  354.         I915_WRITE(SPRKEYVAL(intel_plane->pipe), key->min_value);
  355.         I915_WRITE(SPRKEYMAX(intel_plane->pipe), key->max_value);
  356.         I915_WRITE(SPRKEYMSK(intel_plane->pipe), key->channel_mask);
  357.  
  358.         sprctl = I915_READ(SPRCTL(intel_plane->pipe));
  359.         sprctl &= ~(SPRITE_SOURCE_KEY | SPRITE_DEST_KEY);
  360.         if (key->flags & I915_SET_COLORKEY_DESTINATION)
  361.                 sprctl |= SPRITE_DEST_KEY;
  362.         else if (key->flags & I915_SET_COLORKEY_SOURCE)
  363.                 sprctl |= SPRITE_SOURCE_KEY;
  364.         I915_WRITE(SPRCTL(intel_plane->pipe), sprctl);
  365.  
  366.         POSTING_READ(SPRKEYMSK(intel_plane->pipe));
  367.  
  368.         return ret;
  369. }
  370.  
  371. static void
  372. ivb_get_colorkey(struct drm_plane *plane, struct drm_intel_sprite_colorkey *key)
  373. {
  374.         struct drm_device *dev = plane->dev;
  375.         struct drm_i915_private *dev_priv = dev->dev_private;
  376.         struct intel_plane *intel_plane;
  377.         u32 sprctl;
  378.  
  379.         intel_plane = to_intel_plane(plane);
  380.  
  381.         key->min_value = I915_READ(SPRKEYVAL(intel_plane->pipe));
  382.         key->max_value = I915_READ(SPRKEYMAX(intel_plane->pipe));
  383.         key->channel_mask = I915_READ(SPRKEYMSK(intel_plane->pipe));
  384.         key->flags = 0;
  385.  
  386.         sprctl = I915_READ(SPRCTL(intel_plane->pipe));
  387.  
  388.         if (sprctl & SPRITE_DEST_KEY)
  389.                 key->flags = I915_SET_COLORKEY_DESTINATION;
  390.         else if (sprctl & SPRITE_SOURCE_KEY)
  391.                 key->flags = I915_SET_COLORKEY_SOURCE;
  392.         else
  393.                 key->flags = I915_SET_COLORKEY_NONE;
  394. }
  395.  
  396. static void
  397. ilk_update_plane(struct drm_plane *plane, struct drm_framebuffer *fb,
  398.                  struct drm_i915_gem_object *obj, int crtc_x, int crtc_y,
  399.                  unsigned int crtc_w, unsigned int crtc_h,
  400.                  uint32_t x, uint32_t y,
  401.                  uint32_t src_w, uint32_t src_h)
  402. {
  403.         struct drm_device *dev = plane->dev;
  404.         struct drm_i915_private *dev_priv = dev->dev_private;
  405.         struct intel_plane *intel_plane = to_intel_plane(plane);
  406.         int pipe = intel_plane->pipe;
  407.         unsigned long dvssurf_offset, linear_offset;
  408.         u32 dvscntr, dvsscale;
  409.         int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
  410.  
  411.         dvscntr = I915_READ(DVSCNTR(pipe));
  412.  
  413.         /* Mask out pixel format bits in case we change it */
  414.         dvscntr &= ~DVS_PIXFORMAT_MASK;
  415.         dvscntr &= ~DVS_RGB_ORDER_XBGR;
  416.         dvscntr &= ~DVS_YUV_BYTE_ORDER_MASK;
  417.         dvscntr &= ~DVS_TILED;
  418.  
  419.         switch (fb->pixel_format) {
  420.         case DRM_FORMAT_XBGR8888:
  421.                 dvscntr |= DVS_FORMAT_RGBX888 | DVS_RGB_ORDER_XBGR;
  422.                 break;
  423.         case DRM_FORMAT_XRGB8888:
  424.                 dvscntr |= DVS_FORMAT_RGBX888;
  425.                 break;
  426.         case DRM_FORMAT_YUYV:
  427.                 dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_YUYV;
  428.                 break;
  429.         case DRM_FORMAT_YVYU:
  430.                 dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_YVYU;
  431.                 break;
  432.         case DRM_FORMAT_UYVY:
  433.                 dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_UYVY;
  434.                 break;
  435.         case DRM_FORMAT_VYUY:
  436.                 dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_VYUY;
  437.                 break;
  438.         default:
  439.                 BUG();
  440.         }
  441.  
  442.         if (obj->tiling_mode != I915_TILING_NONE)
  443.                 dvscntr |= DVS_TILED;
  444.  
  445.         if (IS_GEN6(dev))
  446.                 dvscntr |= DVS_TRICKLE_FEED_DISABLE; /* must disable */
  447.         dvscntr |= DVS_ENABLE;
  448.  
  449.         /* Sizes are 0 based */
  450.         src_w--;
  451.         src_h--;
  452.         crtc_w--;
  453.         crtc_h--;
  454.  
  455.         intel_update_sprite_watermarks(dev, pipe, crtc_w, pixel_size);
  456.  
  457.         dvsscale = 0;
  458.         if (IS_GEN5(dev) || crtc_w != src_w || crtc_h != src_h)
  459.                 dvsscale = DVS_SCALE_ENABLE | (src_w << 16) | src_h;
  460.  
  461.         I915_WRITE(DVSSTRIDE(pipe), fb->pitches[0]);
  462.         I915_WRITE(DVSPOS(pipe), (crtc_y << 16) | crtc_x);
  463.  
  464.         linear_offset = y * fb->pitches[0] + x * pixel_size;
  465.         dvssurf_offset =
  466.                 intel_gen4_compute_page_offset(&x, &y, obj->tiling_mode,
  467.                                                  pixel_size, fb->pitches[0]);
  468.         linear_offset -= dvssurf_offset;
  469.  
  470.         if (obj->tiling_mode != I915_TILING_NONE)
  471.                 I915_WRITE(DVSTILEOFF(pipe), (y << 16) | x);
  472.         else
  473.                 I915_WRITE(DVSLINOFF(pipe), linear_offset);
  474.  
  475.         I915_WRITE(DVSSIZE(pipe), (crtc_h << 16) | crtc_w);
  476.         I915_WRITE(DVSSCALE(pipe), dvsscale);
  477.         I915_WRITE(DVSCNTR(pipe), dvscntr);
  478.         I915_MODIFY_DISPBASE(DVSSURF(pipe), obj->gtt_offset + dvssurf_offset);
  479.         POSTING_READ(DVSSURF(pipe));
  480. }
  481.  
  482. static void
  483. ilk_disable_plane(struct drm_plane *plane)
  484. {
  485.         struct drm_device *dev = plane->dev;
  486.         struct drm_i915_private *dev_priv = dev->dev_private;
  487.         struct intel_plane *intel_plane = to_intel_plane(plane);
  488.         int pipe = intel_plane->pipe;
  489.  
  490.         I915_WRITE(DVSCNTR(pipe), I915_READ(DVSCNTR(pipe)) & ~DVS_ENABLE);
  491.         /* Disable the scaler */
  492.         I915_WRITE(DVSSCALE(pipe), 0);
  493.         /* Flush double buffered register updates */
  494.         I915_MODIFY_DISPBASE(DVSSURF(pipe), 0);
  495.         POSTING_READ(DVSSURF(pipe));
  496. }
  497.  
  498. static void
  499. intel_enable_primary(struct drm_crtc *crtc)
  500. {
  501.         struct drm_device *dev = crtc->dev;
  502.         struct drm_i915_private *dev_priv = dev->dev_private;
  503.         struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
  504.         int reg = DSPCNTR(intel_crtc->plane);
  505.  
  506.         if (!intel_crtc->primary_disabled)
  507.                 return;
  508.  
  509.         intel_crtc->primary_disabled = false;
  510.         intel_update_fbc(dev);
  511.  
  512.         I915_WRITE(reg, I915_READ(reg) | DISPLAY_PLANE_ENABLE);
  513. }
  514.  
  515. static void
  516. intel_disable_primary(struct drm_crtc *crtc)
  517. {
  518.         struct drm_device *dev = crtc->dev;
  519.         struct drm_i915_private *dev_priv = dev->dev_private;
  520.         struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
  521.         int reg = DSPCNTR(intel_crtc->plane);
  522.  
  523.         if (intel_crtc->primary_disabled)
  524.                 return;
  525.  
  526.         I915_WRITE(reg, I915_READ(reg) & ~DISPLAY_PLANE_ENABLE);
  527.  
  528.         intel_crtc->primary_disabled = true;
  529.         intel_update_fbc(dev);
  530. }
  531.  
  532. static int
  533. ilk_update_colorkey(struct drm_plane *plane,
  534.                     struct drm_intel_sprite_colorkey *key)
  535. {
  536.         struct drm_device *dev = plane->dev;
  537.         struct drm_i915_private *dev_priv = dev->dev_private;
  538.         struct intel_plane *intel_plane;
  539.         u32 dvscntr;
  540.         int ret = 0;
  541.  
  542.         intel_plane = to_intel_plane(plane);
  543.  
  544.         I915_WRITE(DVSKEYVAL(intel_plane->pipe), key->min_value);
  545.         I915_WRITE(DVSKEYMAX(intel_plane->pipe), key->max_value);
  546.         I915_WRITE(DVSKEYMSK(intel_plane->pipe), key->channel_mask);
  547.  
  548.         dvscntr = I915_READ(DVSCNTR(intel_plane->pipe));
  549.         dvscntr &= ~(DVS_SOURCE_KEY | DVS_DEST_KEY);
  550.         if (key->flags & I915_SET_COLORKEY_DESTINATION)
  551.                 dvscntr |= DVS_DEST_KEY;
  552.         else if (key->flags & I915_SET_COLORKEY_SOURCE)
  553.                 dvscntr |= DVS_SOURCE_KEY;
  554.         I915_WRITE(DVSCNTR(intel_plane->pipe), dvscntr);
  555.  
  556.         POSTING_READ(DVSKEYMSK(intel_plane->pipe));
  557.  
  558.         return ret;
  559. }
  560.  
  561. static void
  562. ilk_get_colorkey(struct drm_plane *plane, struct drm_intel_sprite_colorkey *key)
  563. {
  564.         struct drm_device *dev = plane->dev;
  565.         struct drm_i915_private *dev_priv = dev->dev_private;
  566.         struct intel_plane *intel_plane;
  567.         u32 dvscntr;
  568.  
  569.         intel_plane = to_intel_plane(plane);
  570.  
  571.         key->min_value = I915_READ(DVSKEYVAL(intel_plane->pipe));
  572.         key->max_value = I915_READ(DVSKEYMAX(intel_plane->pipe));
  573.         key->channel_mask = I915_READ(DVSKEYMSK(intel_plane->pipe));
  574.         key->flags = 0;
  575.  
  576.         dvscntr = I915_READ(DVSCNTR(intel_plane->pipe));
  577.  
  578.         if (dvscntr & DVS_DEST_KEY)
  579.                 key->flags = I915_SET_COLORKEY_DESTINATION;
  580.         else if (dvscntr & DVS_SOURCE_KEY)
  581.                 key->flags = I915_SET_COLORKEY_SOURCE;
  582.         else
  583.                 key->flags = I915_SET_COLORKEY_NONE;
  584. }
  585.  
  586. static int
  587. intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
  588.                    struct drm_framebuffer *fb, int crtc_x, int crtc_y,
  589.                    unsigned int crtc_w, unsigned int crtc_h,
  590.                    uint32_t src_x, uint32_t src_y,
  591.                    uint32_t src_w, uint32_t src_h)
  592. {
  593.         struct drm_device *dev = plane->dev;
  594.         struct drm_i915_private *dev_priv = dev->dev_private;
  595.         struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
  596.         struct intel_plane *intel_plane = to_intel_plane(plane);
  597.         struct intel_framebuffer *intel_fb;
  598.         struct drm_i915_gem_object *obj, *old_obj;
  599.         int pipe = intel_plane->pipe;
  600.         enum transcoder cpu_transcoder = intel_pipe_to_cpu_transcoder(dev_priv,
  601.                                                                       pipe);
  602.         int ret = 0;
  603.         int x = src_x >> 16, y = src_y >> 16;
  604.         int primary_w = crtc->mode.hdisplay, primary_h = crtc->mode.vdisplay;
  605.         bool disable_primary = false;
  606.  
  607.         intel_fb = to_intel_framebuffer(fb);
  608.         obj = intel_fb->obj;
  609.  
  610.         old_obj = intel_plane->obj;
  611.  
  612.         intel_plane->crtc_x = crtc_x;
  613.         intel_plane->crtc_y = crtc_y;
  614.         intel_plane->crtc_w = crtc_w;
  615.         intel_plane->crtc_h = crtc_h;
  616.         intel_plane->src_x = src_x;
  617.         intel_plane->src_y = src_y;
  618.         intel_plane->src_w = src_w;
  619.         intel_plane->src_h = src_h;
  620.  
  621.         src_w = src_w >> 16;
  622.         src_h = src_h >> 16;
  623.  
  624.         /* Pipe must be running... */
  625.         if (!(I915_READ(PIPECONF(cpu_transcoder)) & PIPECONF_ENABLE))
  626.                 return -EINVAL;
  627.  
  628.         if (crtc_x >= primary_w || crtc_y >= primary_h)
  629.                 return -EINVAL;
  630.  
  631.         /* Don't modify another pipe's plane */
  632.         if (intel_plane->pipe != intel_crtc->pipe)
  633.                 return -EINVAL;
  634.  
  635.         /* Sprite planes can be linear or x-tiled surfaces */
  636.         switch (obj->tiling_mode) {
  637.                 case I915_TILING_NONE:
  638.                 case I915_TILING_X:
  639.                         break;
  640.                 default:
  641.                         return -EINVAL;
  642.         }
  643.  
  644.         /*
  645.          * Clamp the width & height into the visible area.  Note we don't
  646.          * try to scale the source if part of the visible region is offscreen.
  647.          * The caller must handle that by adjusting source offset and size.
  648.          */
  649.         if ((crtc_x < 0) && ((crtc_x + crtc_w) > 0)) {
  650.                 crtc_w += crtc_x;
  651.                 crtc_x = 0;
  652.         }
  653.         if ((crtc_x + crtc_w) <= 0) /* Nothing to display */
  654.                 goto out;
  655.         if ((crtc_x + crtc_w) > primary_w)
  656.                 crtc_w = primary_w - crtc_x;
  657.  
  658.         if ((crtc_y < 0) && ((crtc_y + crtc_h) > 0)) {
  659.                 crtc_h += crtc_y;
  660.                 crtc_y = 0;
  661.         }
  662.         if ((crtc_y + crtc_h) <= 0) /* Nothing to display */
  663.                 goto out;
  664.         if (crtc_y + crtc_h > primary_h)
  665.                 crtc_h = primary_h - crtc_y;
  666.  
  667.         if (!crtc_w || !crtc_h) /* Again, nothing to display */
  668.                 goto out;
  669.  
  670.         /*
  671.          * We may not have a scaler, eg. HSW does not have it any more
  672.          */
  673.         if (!intel_plane->can_scale && (crtc_w != src_w || crtc_h != src_h))
  674.                 return -EINVAL;
  675.  
  676.         /*
  677.          * We can take a larger source and scale it down, but
  678.          * only so much...  16x is the max on SNB.
  679.          */
  680.         if (((src_w * src_h) / (crtc_w * crtc_h)) > intel_plane->max_downscale)
  681.                 return -EINVAL;
  682.  
  683.         /*
  684.          * If the sprite is completely covering the primary plane,
  685.          * we can disable the primary and save power.
  686.          */
  687.         if ((crtc_x == 0) && (crtc_y == 0) &&
  688.             (crtc_w == primary_w) && (crtc_h == primary_h))
  689.                 disable_primary = true;
  690.  
  691.         mutex_lock(&dev->struct_mutex);
  692.  
  693.         /* Note that this will apply the VT-d workaround for scanouts,
  694.          * which is more restrictive than required for sprites. (The
  695.          * primary plane requires 256KiB alignment with 64 PTE padding,
  696.          * the sprite planes only require 128KiB alignment and 32 PTE padding.
  697.          */
  698.         ret = intel_pin_and_fence_fb_obj(dev, obj, NULL);
  699.         if (ret)
  700.                 goto out_unlock;
  701.  
  702.         intel_plane->obj = obj;
  703.  
  704.         /*
  705.          * Be sure to re-enable the primary before the sprite is no longer
  706.          * covering it fully.
  707.          */
  708.         if (!disable_primary)
  709.                 intel_enable_primary(crtc);
  710.  
  711.         intel_plane->update_plane(plane, fb, obj, crtc_x, crtc_y,
  712.                                   crtc_w, crtc_h, x, y, src_w, src_h);
  713.  
  714.         if (disable_primary)
  715.                 intel_disable_primary(crtc);
  716.  
  717.         /* Unpin old obj after new one is active to avoid ugliness */
  718.         if (old_obj) {
  719.                 /*
  720.                  * It's fairly common to simply update the position of
  721.                  * an existing object.  In that case, we don't need to
  722.                  * wait for vblank to avoid ugliness, we only need to
  723.                  * do the pin & ref bookkeeping.
  724.                  */
  725.                 if (old_obj != obj) {
  726.                         mutex_unlock(&dev->struct_mutex);
  727.                         intel_wait_for_vblank(dev, to_intel_crtc(crtc)->pipe);
  728.                         mutex_lock(&dev->struct_mutex);
  729.                 }
  730.                 intel_unpin_fb_obj(old_obj);
  731.         }
  732.  
  733. out_unlock:
  734.         mutex_unlock(&dev->struct_mutex);
  735. out:
  736.         return ret;
  737. }
  738.  
  739. static int
  740. intel_disable_plane(struct drm_plane *plane)
  741. {
  742.         struct drm_device *dev = plane->dev;
  743.         struct intel_plane *intel_plane = to_intel_plane(plane);
  744.         int ret = 0;
  745.  
  746.         if (plane->crtc)
  747.                 intel_enable_primary(plane->crtc);
  748.         intel_plane->disable_plane(plane);
  749.  
  750.         if (!intel_plane->obj)
  751.                 goto out;
  752.  
  753.         intel_wait_for_vblank(dev, intel_plane->pipe);
  754.  
  755.         mutex_lock(&dev->struct_mutex);
  756.         intel_unpin_fb_obj(intel_plane->obj);
  757.         intel_plane->obj = NULL;
  758.         mutex_unlock(&dev->struct_mutex);
  759. out:
  760.  
  761.         return ret;
  762. }
  763.  
  764. static void intel_destroy_plane(struct drm_plane *plane)
  765. {
  766.         struct intel_plane *intel_plane = to_intel_plane(plane);
  767.         intel_disable_plane(plane);
  768.         drm_plane_cleanup(plane);
  769.         kfree(intel_plane);
  770. }
  771.  
  772. int intel_sprite_set_colorkey(struct drm_device *dev, void *data,
  773.                               struct drm_file *file_priv)
  774. {
  775.         struct drm_intel_sprite_colorkey *set = data;
  776.         struct drm_mode_object *obj;
  777.         struct drm_plane *plane;
  778.         struct intel_plane *intel_plane;
  779.         int ret = 0;
  780.  
  781.         if (!drm_core_check_feature(dev, DRIVER_MODESET))
  782.                 return -ENODEV;
  783.  
  784.         /* Make sure we don't try to enable both src & dest simultaneously */
  785.         if ((set->flags & (I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE)) == (I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE))
  786.                 return -EINVAL;
  787.  
  788.         drm_modeset_lock_all(dev);
  789.  
  790.         obj = drm_mode_object_find(dev, set->plane_id, DRM_MODE_OBJECT_PLANE);
  791.         if (!obj) {
  792.                 ret = -EINVAL;
  793.                 goto out_unlock;
  794.         }
  795.  
  796.         plane = obj_to_plane(obj);
  797.         intel_plane = to_intel_plane(plane);
  798.         ret = intel_plane->update_colorkey(plane, set);
  799.  
  800. out_unlock:
  801.         drm_modeset_unlock_all(dev);
  802.         return ret;
  803. }
  804.  
  805. int intel_sprite_get_colorkey(struct drm_device *dev, void *data,
  806.                               struct drm_file *file_priv)
  807. {
  808.         struct drm_intel_sprite_colorkey *get = data;
  809.         struct drm_mode_object *obj;
  810.         struct drm_plane *plane;
  811.         struct intel_plane *intel_plane;
  812.         int ret = 0;
  813.  
  814.         if (!drm_core_check_feature(dev, DRIVER_MODESET))
  815.                 return -ENODEV;
  816.  
  817.         drm_modeset_lock_all(dev);
  818.  
  819.         obj = drm_mode_object_find(dev, get->plane_id, DRM_MODE_OBJECT_PLANE);
  820.         if (!obj) {
  821.                 ret = -EINVAL;
  822.                 goto out_unlock;
  823.         }
  824.  
  825.         plane = obj_to_plane(obj);
  826.         intel_plane = to_intel_plane(plane);
  827.         intel_plane->get_colorkey(plane, get);
  828.  
  829. out_unlock:
  830.         drm_modeset_unlock_all(dev);
  831.         return ret;
  832. }
  833.  
  834. void intel_plane_restore(struct drm_plane *plane)
  835. {
  836.         struct intel_plane *intel_plane = to_intel_plane(plane);
  837.  
  838.         if (!plane->crtc || !plane->fb)
  839.                 return;
  840.  
  841.         intel_update_plane(plane, plane->crtc, plane->fb,
  842.                            intel_plane->crtc_x, intel_plane->crtc_y,
  843.                            intel_plane->crtc_w, intel_plane->crtc_h,
  844.                            intel_plane->src_x, intel_plane->src_y,
  845.                            intel_plane->src_w, intel_plane->src_h);
  846. }
  847.  
  848. static const struct drm_plane_funcs intel_plane_funcs = {
  849.         .update_plane = intel_update_plane,
  850.         .disable_plane = intel_disable_plane,
  851.         .destroy = intel_destroy_plane,
  852. };
  853.  
  854. static uint32_t ilk_plane_formats[] = {
  855.         DRM_FORMAT_XRGB8888,
  856.         DRM_FORMAT_YUYV,
  857.         DRM_FORMAT_YVYU,
  858.         DRM_FORMAT_UYVY,
  859.         DRM_FORMAT_VYUY,
  860. };
  861.  
  862. static uint32_t snb_plane_formats[] = {
  863.         DRM_FORMAT_XBGR8888,
  864.         DRM_FORMAT_XRGB8888,
  865.         DRM_FORMAT_YUYV,
  866.         DRM_FORMAT_YVYU,
  867.         DRM_FORMAT_UYVY,
  868.         DRM_FORMAT_VYUY,
  869. };
  870.  
  871. static uint32_t vlv_plane_formats[] = {
  872.         DRM_FORMAT_RGB565,
  873.         DRM_FORMAT_ABGR8888,
  874.         DRM_FORMAT_ARGB8888,
  875.         DRM_FORMAT_XBGR8888,
  876.         DRM_FORMAT_XRGB8888,
  877.         DRM_FORMAT_XBGR2101010,
  878.         DRM_FORMAT_ABGR2101010,
  879.         DRM_FORMAT_YUYV,
  880.         DRM_FORMAT_YVYU,
  881.         DRM_FORMAT_UYVY,
  882.         DRM_FORMAT_VYUY,
  883. };
  884.  
  885. int
  886. intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane)
  887. {
  888.         struct intel_plane *intel_plane;
  889.         unsigned long possible_crtcs;
  890.         const uint32_t *plane_formats;
  891.         int num_plane_formats;
  892.         int ret;
  893.  
  894.         if (INTEL_INFO(dev)->gen < 5)
  895.                 return -ENODEV;
  896.  
  897.         intel_plane = kzalloc(sizeof(struct intel_plane), GFP_KERNEL);
  898.         if (!intel_plane)
  899.                 return -ENOMEM;
  900.  
  901.         switch (INTEL_INFO(dev)->gen) {
  902.         case 5:
  903.         case 6:
  904.                 intel_plane->can_scale = true;
  905.                 intel_plane->max_downscale = 16;
  906.                 intel_plane->update_plane = ilk_update_plane;
  907.                 intel_plane->disable_plane = ilk_disable_plane;
  908.                 intel_plane->update_colorkey = ilk_update_colorkey;
  909.                 intel_plane->get_colorkey = ilk_get_colorkey;
  910.  
  911.         if (IS_GEN6(dev)) {
  912.                         plane_formats = snb_plane_formats;
  913.                         num_plane_formats = ARRAY_SIZE(snb_plane_formats);
  914.                 } else {
  915.                         plane_formats = ilk_plane_formats;
  916.                         num_plane_formats = ARRAY_SIZE(ilk_plane_formats);
  917.                 }
  918.                 break;
  919.  
  920.         case 7:
  921.                 if (IS_HASWELL(dev) || IS_VALLEYVIEW(dev))
  922.                         intel_plane->can_scale = false;
  923.                 else
  924.                         intel_plane->can_scale = true;
  925.  
  926.                 if (IS_VALLEYVIEW(dev)) {
  927.                         intel_plane->max_downscale = 1;
  928.                         intel_plane->update_plane = vlv_update_plane;
  929.                         intel_plane->disable_plane = vlv_disable_plane;
  930.                         intel_plane->update_colorkey = vlv_update_colorkey;
  931.                         intel_plane->get_colorkey = vlv_get_colorkey;
  932.  
  933.                         plane_formats = vlv_plane_formats;
  934.                         num_plane_formats = ARRAY_SIZE(vlv_plane_formats);
  935.                 } else {
  936.                 intel_plane->max_downscale = 2;
  937.                 intel_plane->update_plane = ivb_update_plane;
  938.                 intel_plane->disable_plane = ivb_disable_plane;
  939.                 intel_plane->update_colorkey = ivb_update_colorkey;
  940.                 intel_plane->get_colorkey = ivb_get_colorkey;
  941.  
  942.                 plane_formats = snb_plane_formats;
  943.                 num_plane_formats = ARRAY_SIZE(snb_plane_formats);
  944.                 }
  945.                 break;
  946.  
  947.         default:
  948.                 kfree(intel_plane);
  949.                 return -ENODEV;
  950.         }
  951.  
  952.         intel_plane->pipe = pipe;
  953.         intel_plane->plane = plane;
  954.         possible_crtcs = (1 << pipe);
  955.         ret = drm_plane_init(dev, &intel_plane->base, possible_crtcs,
  956.                              &intel_plane_funcs,
  957.                              plane_formats, num_plane_formats,
  958.                              false);
  959.         if (ret)
  960.                 kfree(intel_plane);
  961.  
  962.         return ret;
  963. }
  964.