Subversion Repositories Kolibri OS

Rev

Rev 2344 | 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 "drmP.h"
  33. #include "drm_crtc.h"
  34. #include "drm_fourcc.h"
  35. #include "intel_drv.h"
  36. #include "i915_drm.h"
  37. #include "i915_drv.h"
  38.  
  39. static void
  40. ivb_update_plane(struct drm_plane *plane, 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 = plane->dev;
  47.         struct drm_i915_private *dev_priv = dev->dev_private;
  48.         struct intel_plane *intel_plane = to_intel_plane(plane);
  49.         int pipe = intel_plane->pipe;
  50.         u32 sprctl, sprscale = 0;
  51.         int pixel_size;
  52.  
  53.         sprctl = I915_READ(SPRCTL(pipe));
  54.  
  55.         /* Mask out pixel format bits in case we change it */
  56.         sprctl &= ~SPRITE_PIXFORMAT_MASK;
  57.         sprctl &= ~SPRITE_RGB_ORDER_RGBX;
  58.         sprctl &= ~SPRITE_YUV_BYTE_ORDER_MASK;
  59.  
  60.         switch (fb->pixel_format) {
  61.         case DRM_FORMAT_XBGR8888:
  62.                 sprctl |= SPRITE_FORMAT_RGBX888;
  63.                 pixel_size = 4;
  64.                 break;
  65.         case DRM_FORMAT_XRGB8888:
  66.                 sprctl |= SPRITE_FORMAT_RGBX888 | SPRITE_RGB_ORDER_RGBX;
  67.                 pixel_size = 4;
  68.                 break;
  69.         case DRM_FORMAT_YUYV:
  70.                 sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_YUYV;
  71.                 pixel_size = 2;
  72.                 break;
  73.         case DRM_FORMAT_YVYU:
  74.                 sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_YVYU;
  75.                 pixel_size = 2;
  76.                 break;
  77.         case DRM_FORMAT_UYVY:
  78.                 sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_UYVY;
  79.                 pixel_size = 2;
  80.                 break;
  81.         case DRM_FORMAT_VYUY:
  82.                 sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_VYUY;
  83.                 pixel_size = 2;
  84.                 break;
  85.         default:
  86.                 DRM_DEBUG_DRIVER("bad pixel format, assuming RGBX888\n");
  87.                 sprctl |= DVS_FORMAT_RGBX888;
  88.                 pixel_size = 4;
  89.                 break;
  90.         }
  91.  
  92.         if (obj->tiling_mode != I915_TILING_NONE)
  93.                 sprctl |= SPRITE_TILED;
  94.  
  95.         /* must disable */
  96.         sprctl |= SPRITE_TRICKLE_FEED_DISABLE;
  97.         sprctl |= SPRITE_ENABLE;
  98.         sprctl |= SPRITE_DEST_KEY;
  99.  
  100.         /* Sizes are 0 based */
  101.         src_w--;
  102.         src_h--;
  103.         crtc_w--;
  104.         crtc_h--;
  105.  
  106.         intel_update_sprite_watermarks(dev, pipe, crtc_w, pixel_size);
  107.  
  108.         /*
  109.          * IVB workaround: must disable low power watermarks for at least
  110.          * one frame before enabling scaling.  LP watermarks can be re-enabled
  111.          * when scaling is disabled.
  112.          */
  113.         if (crtc_w != src_w || crtc_h != src_h) {
  114.                 dev_priv->sprite_scaling_enabled = true;
  115.                 sandybridge_update_wm(dev);
  116.                 intel_wait_for_vblank(dev, pipe);
  117.                 sprscale = SPRITE_SCALE_ENABLE | (src_w << 16) | src_h;
  118.         } else {
  119.                 dev_priv->sprite_scaling_enabled = false;
  120.                 /* potentially re-enable LP watermarks */
  121.                 sandybridge_update_wm(dev);
  122.         }
  123.  
  124.         I915_WRITE(SPRSTRIDE(pipe), fb->pitches[0]);
  125.         I915_WRITE(SPRPOS(pipe), (crtc_y << 16) | crtc_x);
  126.         if (obj->tiling_mode != I915_TILING_NONE) {
  127.                 I915_WRITE(SPRTILEOFF(pipe), (y << 16) | x);
  128.         } else {
  129.                 unsigned long offset;
  130.  
  131.                 offset = y * fb->pitches[0] + x * (fb->bits_per_pixel / 8);
  132.                 I915_WRITE(SPRLINOFF(pipe), offset);
  133.         }
  134.         I915_WRITE(SPRSIZE(pipe), (crtc_h << 16) | crtc_w);
  135.         I915_WRITE(SPRSCALE(pipe), sprscale);
  136.         I915_WRITE(SPRCTL(pipe), sprctl);
  137.         I915_WRITE(SPRSURF(pipe), obj->gtt_offset);
  138.         POSTING_READ(SPRSURF(pipe));
  139. }
  140.  
  141. static void
  142. ivb_disable_plane(struct drm_plane *plane)
  143. {
  144.         struct drm_device *dev = plane->dev;
  145.         struct drm_i915_private *dev_priv = dev->dev_private;
  146.         struct intel_plane *intel_plane = to_intel_plane(plane);
  147.         int pipe = intel_plane->pipe;
  148.  
  149.         I915_WRITE(SPRCTL(pipe), I915_READ(SPRCTL(pipe)) & ~SPRITE_ENABLE);
  150.         /* Can't leave the scaler enabled... */
  151.         I915_WRITE(SPRSCALE(pipe), 0);
  152.         /* Activate double buffered register update */
  153.         I915_WRITE(SPRSURF(pipe), 0);
  154.         POSTING_READ(SPRSURF(pipe));
  155. }
  156.  
  157. static int
  158. ivb_update_colorkey(struct drm_plane *plane,
  159.                     struct drm_intel_sprite_colorkey *key)
  160. {
  161.         struct drm_device *dev = plane->dev;
  162.         struct drm_i915_private *dev_priv = dev->dev_private;
  163.         struct intel_plane *intel_plane;
  164.         u32 sprctl;
  165.         int ret = 0;
  166.  
  167.         intel_plane = to_intel_plane(plane);
  168.  
  169.         I915_WRITE(SPRKEYVAL(intel_plane->pipe), key->min_value);
  170.         I915_WRITE(SPRKEYMAX(intel_plane->pipe), key->max_value);
  171.         I915_WRITE(SPRKEYMSK(intel_plane->pipe), key->channel_mask);
  172.  
  173.         sprctl = I915_READ(SPRCTL(intel_plane->pipe));
  174.         sprctl &= ~(SPRITE_SOURCE_KEY | SPRITE_DEST_KEY);
  175.         if (key->flags & I915_SET_COLORKEY_DESTINATION)
  176.                 sprctl |= SPRITE_DEST_KEY;
  177.         else if (key->flags & I915_SET_COLORKEY_SOURCE)
  178.                 sprctl |= SPRITE_SOURCE_KEY;
  179.         I915_WRITE(SPRCTL(intel_plane->pipe), sprctl);
  180.  
  181.         POSTING_READ(SPRKEYMSK(intel_plane->pipe));
  182.  
  183.         return ret;
  184. }
  185.  
  186. static void
  187. ivb_get_colorkey(struct drm_plane *plane, struct drm_intel_sprite_colorkey *key)
  188. {
  189.         struct drm_device *dev = plane->dev;
  190.         struct drm_i915_private *dev_priv = dev->dev_private;
  191.         struct intel_plane *intel_plane;
  192.         u32 sprctl;
  193.  
  194.         intel_plane = to_intel_plane(plane);
  195.  
  196.         key->min_value = I915_READ(SPRKEYVAL(intel_plane->pipe));
  197.         key->max_value = I915_READ(SPRKEYMAX(intel_plane->pipe));
  198.         key->channel_mask = I915_READ(SPRKEYMSK(intel_plane->pipe));
  199.         key->flags = 0;
  200.  
  201.         sprctl = I915_READ(SPRCTL(intel_plane->pipe));
  202.  
  203.         if (sprctl & SPRITE_DEST_KEY)
  204.                 key->flags = I915_SET_COLORKEY_DESTINATION;
  205.         else if (sprctl & SPRITE_SOURCE_KEY)
  206.                 key->flags = I915_SET_COLORKEY_SOURCE;
  207.         else
  208.                 key->flags = I915_SET_COLORKEY_NONE;
  209. }
  210.  
  211. static void
  212. snb_update_plane(struct drm_plane *plane, struct drm_framebuffer *fb,
  213.                  struct drm_i915_gem_object *obj, int crtc_x, int crtc_y,
  214.                  unsigned int crtc_w, unsigned int crtc_h,
  215.                  uint32_t x, uint32_t y,
  216.                  uint32_t src_w, uint32_t src_h)
  217. {
  218.         struct drm_device *dev = plane->dev;
  219.         struct drm_i915_private *dev_priv = dev->dev_private;
  220.         struct intel_plane *intel_plane = to_intel_plane(plane);
  221.         int pipe = intel_plane->pipe, pixel_size;
  222.         u32 dvscntr, dvsscale = 0;
  223.  
  224.         dvscntr = I915_READ(DVSCNTR(pipe));
  225.  
  226.         /* Mask out pixel format bits in case we change it */
  227.         dvscntr &= ~DVS_PIXFORMAT_MASK;
  228.         dvscntr &= ~DVS_RGB_ORDER_RGBX;
  229.         dvscntr &= ~DVS_YUV_BYTE_ORDER_MASK;
  230.  
  231.         switch (fb->pixel_format) {
  232.         case DRM_FORMAT_XBGR8888:
  233.                 dvscntr |= DVS_FORMAT_RGBX888;
  234.                 pixel_size = 4;
  235.                 break;
  236.         case DRM_FORMAT_XRGB8888:
  237.                 dvscntr |= DVS_FORMAT_RGBX888 | DVS_RGB_ORDER_RGBX;
  238.                 pixel_size = 4;
  239.                 break;
  240.         case DRM_FORMAT_YUYV:
  241.                 dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_YUYV;
  242.                 pixel_size = 2;
  243.                 break;
  244.         case DRM_FORMAT_YVYU:
  245.                 dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_YVYU;
  246.                 pixel_size = 2;
  247.                 break;
  248.         case DRM_FORMAT_UYVY:
  249.                 dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_UYVY;
  250.                 pixel_size = 2;
  251.                 break;
  252.         case DRM_FORMAT_VYUY:
  253.                 dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_VYUY;
  254.                 pixel_size = 2;
  255.                 break;
  256.         default:
  257.                 DRM_DEBUG_DRIVER("bad pixel format, assuming RGBX888\n");
  258.                 dvscntr |= DVS_FORMAT_RGBX888;
  259.                 pixel_size = 4;
  260.                 break;
  261.         }
  262.  
  263.         if (obj->tiling_mode != I915_TILING_NONE)
  264.                 dvscntr |= DVS_TILED;
  265.  
  266.         /* must disable */
  267.         dvscntr |= DVS_TRICKLE_FEED_DISABLE;
  268.         dvscntr |= DVS_ENABLE;
  269.  
  270.         /* Sizes are 0 based */
  271.         src_w--;
  272.         src_h--;
  273.         crtc_w--;
  274.         crtc_h--;
  275.  
  276.         intel_update_sprite_watermarks(dev, pipe, crtc_w, pixel_size);
  277.  
  278.         if (crtc_w != src_w || crtc_h != src_h)
  279.                 dvsscale = DVS_SCALE_ENABLE | (src_w << 16) | src_h;
  280.  
  281.         I915_WRITE(DVSSTRIDE(pipe), fb->pitches[0]);
  282.         I915_WRITE(DVSPOS(pipe), (crtc_y << 16) | crtc_x);
  283.         if (obj->tiling_mode != I915_TILING_NONE) {
  284.                 I915_WRITE(DVSTILEOFF(pipe), (y << 16) | x);
  285.         } else {
  286.                 unsigned long offset;
  287.  
  288.                 offset = y * fb->pitches[0] + x * (fb->bits_per_pixel / 8);
  289.                 I915_WRITE(DVSLINOFF(pipe), offset);
  290.         }
  291.         I915_WRITE(DVSSIZE(pipe), (crtc_h << 16) | crtc_w);
  292.         I915_WRITE(DVSSCALE(pipe), dvsscale);
  293.         I915_WRITE(DVSCNTR(pipe), dvscntr);
  294.         I915_WRITE(DVSSURF(pipe), obj->gtt_offset);
  295.         POSTING_READ(DVSSURF(pipe));
  296. }
  297.  
  298. static void
  299. snb_disable_plane(struct drm_plane *plane)
  300. {
  301.         struct drm_device *dev = plane->dev;
  302.         struct drm_i915_private *dev_priv = dev->dev_private;
  303.         struct intel_plane *intel_plane = to_intel_plane(plane);
  304.         int pipe = intel_plane->pipe;
  305.  
  306.         I915_WRITE(DVSCNTR(pipe), I915_READ(DVSCNTR(pipe)) & ~DVS_ENABLE);
  307.         /* Disable the scaler */
  308.         I915_WRITE(DVSSCALE(pipe), 0);
  309.         /* Flush double buffered register updates */
  310.         I915_WRITE(DVSSURF(pipe), 0);
  311.         POSTING_READ(DVSSURF(pipe));
  312. }
  313.  
  314. static void
  315. intel_enable_primary(struct drm_crtc *crtc)
  316. {
  317.         struct drm_device *dev = crtc->dev;
  318.         struct drm_i915_private *dev_priv = dev->dev_private;
  319.         struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
  320.         int reg = DSPCNTR(intel_crtc->plane);
  321.  
  322.         I915_WRITE(reg, I915_READ(reg) | DISPLAY_PLANE_ENABLE);
  323. }
  324.  
  325. static void
  326. intel_disable_primary(struct drm_crtc *crtc)
  327. {
  328.         struct drm_device *dev = crtc->dev;
  329.         struct drm_i915_private *dev_priv = dev->dev_private;
  330.         struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
  331.         int reg = DSPCNTR(intel_crtc->plane);
  332.  
  333.         I915_WRITE(reg, I915_READ(reg) & ~DISPLAY_PLANE_ENABLE);
  334. }
  335.  
  336. static int
  337. snb_update_colorkey(struct drm_plane *plane,
  338.                     struct drm_intel_sprite_colorkey *key)
  339. {
  340.         struct drm_device *dev = plane->dev;
  341.         struct drm_i915_private *dev_priv = dev->dev_private;
  342.         struct intel_plane *intel_plane;
  343.         u32 dvscntr;
  344.         int ret = 0;
  345.  
  346.         intel_plane = to_intel_plane(plane);
  347.  
  348.         I915_WRITE(DVSKEYVAL(intel_plane->pipe), key->min_value);
  349.         I915_WRITE(DVSKEYMAX(intel_plane->pipe), key->max_value);
  350.         I915_WRITE(DVSKEYMSK(intel_plane->pipe), key->channel_mask);
  351.  
  352.         dvscntr = I915_READ(DVSCNTR(intel_plane->pipe));
  353.         dvscntr &= ~(DVS_SOURCE_KEY | DVS_DEST_KEY);
  354.         if (key->flags & I915_SET_COLORKEY_DESTINATION)
  355.                 dvscntr |= DVS_DEST_KEY;
  356.         else if (key->flags & I915_SET_COLORKEY_SOURCE)
  357.                 dvscntr |= DVS_SOURCE_KEY;
  358.         I915_WRITE(DVSCNTR(intel_plane->pipe), dvscntr);
  359.  
  360.         POSTING_READ(DVSKEYMSK(intel_plane->pipe));
  361.  
  362.         return ret;
  363. }
  364.  
  365. static void
  366. snb_get_colorkey(struct drm_plane *plane, struct drm_intel_sprite_colorkey *key)
  367. {
  368.         struct drm_device *dev = plane->dev;
  369.         struct drm_i915_private *dev_priv = dev->dev_private;
  370.         struct intel_plane *intel_plane;
  371.         u32 dvscntr;
  372.  
  373.         intel_plane = to_intel_plane(plane);
  374.  
  375.         key->min_value = I915_READ(DVSKEYVAL(intel_plane->pipe));
  376.         key->max_value = I915_READ(DVSKEYMAX(intel_plane->pipe));
  377.         key->channel_mask = I915_READ(DVSKEYMSK(intel_plane->pipe));
  378.         key->flags = 0;
  379.  
  380.         dvscntr = I915_READ(DVSCNTR(intel_plane->pipe));
  381.  
  382.         if (dvscntr & DVS_DEST_KEY)
  383.                 key->flags = I915_SET_COLORKEY_DESTINATION;
  384.         else if (dvscntr & DVS_SOURCE_KEY)
  385.                 key->flags = I915_SET_COLORKEY_SOURCE;
  386.         else
  387.                 key->flags = I915_SET_COLORKEY_NONE;
  388. }
  389.  
  390. static int
  391. intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
  392.                    struct drm_framebuffer *fb, int crtc_x, int crtc_y,
  393.                    unsigned int crtc_w, unsigned int crtc_h,
  394.                    uint32_t src_x, uint32_t src_y,
  395.                    uint32_t src_w, uint32_t src_h)
  396. {
  397.         struct drm_device *dev = plane->dev;
  398.         struct drm_i915_private *dev_priv = dev->dev_private;
  399.         struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
  400.         struct intel_plane *intel_plane = to_intel_plane(plane);
  401.         struct intel_framebuffer *intel_fb;
  402.         struct drm_i915_gem_object *obj, *old_obj;
  403.         int pipe = intel_plane->pipe;
  404.         int ret = 0;
  405.         int x = src_x >> 16, y = src_y >> 16;
  406.         int primary_w = crtc->mode.hdisplay, primary_h = crtc->mode.vdisplay;
  407.         bool disable_primary = false;
  408.  
  409.         intel_fb = to_intel_framebuffer(fb);
  410.         obj = intel_fb->obj;
  411.  
  412.         old_obj = intel_plane->obj;
  413.  
  414.         /* Pipe must be running... */
  415.         if (!(I915_READ(PIPECONF(pipe)) & PIPECONF_ENABLE))
  416.                 return -EINVAL;
  417.  
  418.         if (crtc_x >= primary_w || crtc_y >= primary_h)
  419.                 return -EINVAL;
  420.  
  421.         /* Don't modify another pipe's plane */
  422.         if (intel_plane->pipe != intel_crtc->pipe)
  423.                 return -EINVAL;
  424.  
  425.         /*
  426.          * Clamp the width & height into the visible area.  Note we don't
  427.          * try to scale the source if part of the visible region is offscreen.
  428.          * The caller must handle that by adjusting source offset and size.
  429.          */
  430.         if ((crtc_x < 0) && ((crtc_x + crtc_w) > 0)) {
  431.                 crtc_w += crtc_x;
  432.                 crtc_x = 0;
  433.         }
  434.         if ((crtc_x + crtc_w) <= 0) /* Nothing to display */
  435.                 goto out;
  436.         if ((crtc_x + crtc_w) > primary_w)
  437.                 crtc_w = primary_w - crtc_x;
  438.  
  439.         if ((crtc_y < 0) && ((crtc_y + crtc_h) > 0)) {
  440.                 crtc_h += crtc_y;
  441.                 crtc_y = 0;
  442.         }
  443.         if ((crtc_y + crtc_h) <= 0) /* Nothing to display */
  444.                 goto out;
  445.         if (crtc_y + crtc_h > primary_h)
  446.                 crtc_h = primary_h - crtc_y;
  447.  
  448.         if (!crtc_w || !crtc_h) /* Again, nothing to display */
  449.                 goto out;
  450.  
  451.         /*
  452.          * We can take a larger source and scale it down, but
  453.          * only so much...  16x is the max on SNB.
  454.          */
  455.         if (((src_w * src_h) / (crtc_w * crtc_h)) > intel_plane->max_downscale)
  456.                 return -EINVAL;
  457.  
  458.         /*
  459.          * If the sprite is completely covering the primary plane,
  460.          * we can disable the primary and save power.
  461.          */
  462.         if ((crtc_x == 0) && (crtc_y == 0) &&
  463.             (crtc_w == primary_w) && (crtc_h == primary_h))
  464.                 disable_primary = true;
  465.  
  466.         mutex_lock(&dev->struct_mutex);
  467.  
  468.         ret = intel_pin_and_fence_fb_obj(dev, obj, NULL);
  469.         if (ret)
  470.                 goto out_unlock;
  471.  
  472.         intel_plane->obj = obj;
  473.  
  474.         /*
  475.          * Be sure to re-enable the primary before the sprite is no longer
  476.          * covering it fully.
  477.          */
  478.         if (!disable_primary && intel_plane->primary_disabled) {
  479.                 intel_enable_primary(crtc);
  480.                 intel_plane->primary_disabled = false;
  481.         }
  482.  
  483.         intel_plane->update_plane(plane, fb, obj, crtc_x, crtc_y,
  484.                                   crtc_w, crtc_h, x, y, src_w, src_h);
  485.  
  486.         if (disable_primary) {
  487.                 intel_disable_primary(crtc);
  488.                 intel_plane->primary_disabled = true;
  489.         }
  490.  
  491.         /* Unpin old obj after new one is active to avoid ugliness */
  492.         if (old_obj) {
  493.                 /*
  494.                  * It's fairly common to simply update the position of
  495.                  * an existing object.  In that case, we don't need to
  496.                  * wait for vblank to avoid ugliness, we only need to
  497.                  * do the pin & ref bookkeeping.
  498.                  */
  499.                 if (old_obj != obj) {
  500.                         mutex_unlock(&dev->struct_mutex);
  501.                         intel_wait_for_vblank(dev, to_intel_crtc(crtc)->pipe);
  502.                         mutex_lock(&dev->struct_mutex);
  503.                 }
  504. //       i915_gem_object_unpin(old_obj);
  505.         }
  506.  
  507. out_unlock:
  508.         mutex_unlock(&dev->struct_mutex);
  509. out:
  510.         return ret;
  511. }
  512.  
  513. static int
  514. intel_disable_plane(struct drm_plane *plane)
  515. {
  516.         struct drm_device *dev = plane->dev;
  517.         struct intel_plane *intel_plane = to_intel_plane(plane);
  518.         int ret = 0;
  519.  
  520.         if (intel_plane->primary_disabled) {
  521.                 intel_enable_primary(plane->crtc);
  522.                 intel_plane->primary_disabled = false;
  523.         }
  524.  
  525.         intel_plane->disable_plane(plane);
  526.  
  527.         if (!intel_plane->obj)
  528.                 goto out;
  529.  
  530.         mutex_lock(&dev->struct_mutex);
  531. //   i915_gem_object_unpin(intel_plane->obj);
  532.         intel_plane->obj = NULL;
  533.         mutex_unlock(&dev->struct_mutex);
  534. out:
  535.  
  536.         return ret;
  537. }
  538.  
  539. static void intel_destroy_plane(struct drm_plane *plane)
  540. {
  541.         struct intel_plane *intel_plane = to_intel_plane(plane);
  542.         intel_disable_plane(plane);
  543.         drm_plane_cleanup(plane);
  544.         kfree(intel_plane);
  545. }
  546.  
  547. int intel_sprite_set_colorkey(struct drm_device *dev, void *data,
  548.                               struct drm_file *file_priv)
  549. {
  550.         struct drm_intel_sprite_colorkey *set = data;
  551.         struct drm_i915_private *dev_priv = dev->dev_private;
  552.         struct drm_mode_object *obj;
  553.         struct drm_plane *plane;
  554.         struct intel_plane *intel_plane;
  555.         int ret = 0;
  556.  
  557.         if (!dev_priv)
  558.                 return -EINVAL;
  559.  
  560.         /* Make sure we don't try to enable both src & dest simultaneously */
  561.         if ((set->flags & (I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE)) == (I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE))
  562.                 return -EINVAL;
  563.  
  564.         mutex_lock(&dev->mode_config.mutex);
  565.  
  566.         obj = drm_mode_object_find(dev, set->plane_id, DRM_MODE_OBJECT_PLANE);
  567.         if (!obj) {
  568.                 ret = -EINVAL;
  569.                 goto out_unlock;
  570.         }
  571.  
  572.         plane = obj_to_plane(obj);
  573.         intel_plane = to_intel_plane(plane);
  574.         ret = intel_plane->update_colorkey(plane, set);
  575.  
  576. out_unlock:
  577.         mutex_unlock(&dev->mode_config.mutex);
  578.         return ret;
  579. }
  580.  
  581. int intel_sprite_get_colorkey(struct drm_device *dev, void *data,
  582.                               struct drm_file *file_priv)
  583. {
  584.         struct drm_intel_sprite_colorkey *get = data;
  585.         struct drm_i915_private *dev_priv = dev->dev_private;
  586.         struct drm_mode_object *obj;
  587.         struct drm_plane *plane;
  588.         struct intel_plane *intel_plane;
  589.         int ret = 0;
  590.  
  591.         if (!dev_priv)
  592.                 return -EINVAL;
  593.  
  594.         mutex_lock(&dev->mode_config.mutex);
  595.  
  596.         obj = drm_mode_object_find(dev, get->plane_id, DRM_MODE_OBJECT_PLANE);
  597.         if (!obj) {
  598.                 ret = -EINVAL;
  599.                 goto out_unlock;
  600.         }
  601.  
  602.         plane = obj_to_plane(obj);
  603.         intel_plane = to_intel_plane(plane);
  604.         intel_plane->get_colorkey(plane, get);
  605.  
  606. out_unlock:
  607.         mutex_unlock(&dev->mode_config.mutex);
  608.         return ret;
  609. }
  610.  
  611. static const struct drm_plane_funcs intel_plane_funcs = {
  612.         .update_plane = intel_update_plane,
  613.         .disable_plane = intel_disable_plane,
  614.         .destroy = intel_destroy_plane,
  615. };
  616.  
  617. static uint32_t snb_plane_formats[] = {
  618.         DRM_FORMAT_XBGR8888,
  619.         DRM_FORMAT_XRGB8888,
  620.         DRM_FORMAT_YUYV,
  621.         DRM_FORMAT_YVYU,
  622.         DRM_FORMAT_UYVY,
  623.         DRM_FORMAT_VYUY,
  624. };
  625.  
  626. int
  627. intel_plane_init(struct drm_device *dev, enum pipe pipe)
  628. {
  629.         struct intel_plane *intel_plane;
  630.         unsigned long possible_crtcs;
  631.         int ret;
  632.  
  633.         if (!(IS_GEN6(dev) || IS_GEN7(dev)))
  634.                 return -ENODEV;
  635.  
  636.         intel_plane = kzalloc(sizeof(struct intel_plane), GFP_KERNEL);
  637.         if (!intel_plane)
  638.                 return -ENOMEM;
  639.  
  640.         if (IS_GEN6(dev)) {
  641.                 intel_plane->max_downscale = 16;
  642.                 intel_plane->update_plane = snb_update_plane;
  643.                 intel_plane->disable_plane = snb_disable_plane;
  644.                 intel_plane->update_colorkey = snb_update_colorkey;
  645.                 intel_plane->get_colorkey = snb_get_colorkey;
  646.         } else if (IS_GEN7(dev)) {
  647.                 intel_plane->max_downscale = 2;
  648.                 intel_plane->update_plane = ivb_update_plane;
  649.                 intel_plane->disable_plane = ivb_disable_plane;
  650.                 intel_plane->update_colorkey = ivb_update_colorkey;
  651.                 intel_plane->get_colorkey = ivb_get_colorkey;
  652.         }
  653.  
  654.         intel_plane->pipe = pipe;
  655.         possible_crtcs = (1 << pipe);
  656.         ret = drm_plane_init(dev, &intel_plane->base, possible_crtcs,
  657.                              &intel_plane_funcs, snb_plane_formats,
  658.                              ARRAY_SIZE(snb_plane_formats), false);
  659.         if (ret)
  660.                 kfree(intel_plane);
  661.  
  662.         return ret;
  663. }
  664.  
  665.