LCOV - code coverage report
Current view: top level - drivers/gpu/drm/i915/display - intel_overlay.c (source / functions) Hit Total Coverage
Test: combined.info Lines: 0 578 0.0 %
Date: 2022-04-01 13:59:58 Functions: 0 25 0.0 %
Branches: 0 280 0.0 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * Copyright © 2009
       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                 :            :  *    Daniel Vetter <daniel@ffwll.ch>
      25                 :            :  *
      26                 :            :  * Derived from Xorg ddx, xf86-video-intel, src/i830_video.c
      27                 :            :  */
      28                 :            : 
      29                 :            : #include <drm/drm_fourcc.h>
      30                 :            : #include <drm/i915_drm.h>
      31                 :            : 
      32                 :            : #include "gem/i915_gem_pm.h"
      33                 :            : #include "gt/intel_ring.h"
      34                 :            : 
      35                 :            : #include "i915_drv.h"
      36                 :            : #include "i915_reg.h"
      37                 :            : #include "intel_display_types.h"
      38                 :            : #include "intel_frontbuffer.h"
      39                 :            : #include "intel_overlay.h"
      40                 :            : 
      41                 :            : /* Limits for overlay size. According to intel doc, the real limits are:
      42                 :            :  * Y width: 4095, UV width (planar): 2047, Y height: 2047,
      43                 :            :  * UV width (planar): * 1023. But the xorg thinks 2048 for height and width. Use
      44                 :            :  * the mininum of both.  */
      45                 :            : #define IMAGE_MAX_WIDTH         2048
      46                 :            : #define IMAGE_MAX_HEIGHT        2046 /* 2 * 1023 */
      47                 :            : /* on 830 and 845 these large limits result in the card hanging */
      48                 :            : #define IMAGE_MAX_WIDTH_LEGACY  1024
      49                 :            : #define IMAGE_MAX_HEIGHT_LEGACY 1088
      50                 :            : 
      51                 :            : /* overlay register definitions */
      52                 :            : /* OCMD register */
      53                 :            : #define OCMD_TILED_SURFACE      (0x1<<19)
      54                 :            : #define OCMD_MIRROR_MASK        (0x3<<17)
      55                 :            : #define OCMD_MIRROR_MODE        (0x3<<17)
      56                 :            : #define OCMD_MIRROR_HORIZONTAL  (0x1<<17)
      57                 :            : #define OCMD_MIRROR_VERTICAL    (0x2<<17)
      58                 :            : #define OCMD_MIRROR_BOTH        (0x3<<17)
      59                 :            : #define OCMD_BYTEORDER_MASK     (0x3<<14) /* zero for YUYV or FOURCC YUY2 */
      60                 :            : #define OCMD_UV_SWAP            (0x1<<14) /* YVYU */
      61                 :            : #define OCMD_Y_SWAP             (0x2<<14) /* UYVY or FOURCC UYVY */
      62                 :            : #define OCMD_Y_AND_UV_SWAP      (0x3<<14) /* VYUY */
      63                 :            : #define OCMD_SOURCE_FORMAT_MASK (0xf<<10)
      64                 :            : #define OCMD_RGB_888            (0x1<<10) /* not in i965 Intel docs */
      65                 :            : #define OCMD_RGB_555            (0x2<<10) /* not in i965 Intel docs */
      66                 :            : #define OCMD_RGB_565            (0x3<<10) /* not in i965 Intel docs */
      67                 :            : #define OCMD_YUV_422_PACKED     (0x8<<10)
      68                 :            : #define OCMD_YUV_411_PACKED     (0x9<<10) /* not in i965 Intel docs */
      69                 :            : #define OCMD_YUV_420_PLANAR     (0xc<<10)
      70                 :            : #define OCMD_YUV_422_PLANAR     (0xd<<10)
      71                 :            : #define OCMD_YUV_410_PLANAR     (0xe<<10) /* also 411 */
      72                 :            : #define OCMD_TVSYNCFLIP_PARITY  (0x1<<9)
      73                 :            : #define OCMD_TVSYNCFLIP_ENABLE  (0x1<<7)
      74                 :            : #define OCMD_BUF_TYPE_MASK      (0x1<<5)
      75                 :            : #define OCMD_BUF_TYPE_FRAME     (0x0<<5)
      76                 :            : #define OCMD_BUF_TYPE_FIELD     (0x1<<5)
      77                 :            : #define OCMD_TEST_MODE          (0x1<<4)
      78                 :            : #define OCMD_BUFFER_SELECT      (0x3<<2)
      79                 :            : #define OCMD_BUFFER0            (0x0<<2)
      80                 :            : #define OCMD_BUFFER1            (0x1<<2)
      81                 :            : #define OCMD_FIELD_SELECT       (0x1<<2)
      82                 :            : #define OCMD_FIELD0             (0x0<<1)
      83                 :            : #define OCMD_FIELD1             (0x1<<1)
      84                 :            : #define OCMD_ENABLE             (0x1<<0)
      85                 :            : 
      86                 :            : /* OCONFIG register */
      87                 :            : #define OCONF_PIPE_MASK         (0x1<<18)
      88                 :            : #define OCONF_PIPE_A            (0x0<<18)
      89                 :            : #define OCONF_PIPE_B            (0x1<<18)
      90                 :            : #define OCONF_GAMMA2_ENABLE     (0x1<<16)
      91                 :            : #define OCONF_CSC_MODE_BT601    (0x0<<5)
      92                 :            : #define OCONF_CSC_MODE_BT709    (0x1<<5)
      93                 :            : #define OCONF_CSC_BYPASS        (0x1<<4)
      94                 :            : #define OCONF_CC_OUT_8BIT       (0x1<<3)
      95                 :            : #define OCONF_TEST_MODE         (0x1<<2)
      96                 :            : #define OCONF_THREE_LINE_BUFFER (0x1<<0)
      97                 :            : #define OCONF_TWO_LINE_BUFFER   (0x0<<0)
      98                 :            : 
      99                 :            : /* DCLRKM (dst-key) register */
     100                 :            : #define DST_KEY_ENABLE          (0x1<<31)
     101                 :            : #define CLK_RGB24_MASK          0x0
     102                 :            : #define CLK_RGB16_MASK          0x070307
     103                 :            : #define CLK_RGB15_MASK          0x070707
     104                 :            : #define CLK_RGB8I_MASK          0xffffff
     105                 :            : 
     106                 :            : #define RGB16_TO_COLORKEY(c) \
     107                 :            :         (((c & 0xF800) << 8) | ((c & 0x07E0) << 5) | ((c & 0x001F) << 3))
     108                 :            : #define RGB15_TO_COLORKEY(c) \
     109                 :            :         (((c & 0x7c00) << 9) | ((c & 0x03E0) << 6) | ((c & 0x001F) << 3))
     110                 :            : 
     111                 :            : /* overlay flip addr flag */
     112                 :            : #define OFC_UPDATE              0x1
     113                 :            : 
     114                 :            : /* polyphase filter coefficients */
     115                 :            : #define N_HORIZ_Y_TAPS          5
     116                 :            : #define N_VERT_Y_TAPS           3
     117                 :            : #define N_HORIZ_UV_TAPS         3
     118                 :            : #define N_VERT_UV_TAPS          3
     119                 :            : #define N_PHASES                17
     120                 :            : #define MAX_TAPS                5
     121                 :            : 
     122                 :            : /* memory bufferd overlay registers */
     123                 :            : struct overlay_registers {
     124                 :            :         u32 OBUF_0Y;
     125                 :            :         u32 OBUF_1Y;
     126                 :            :         u32 OBUF_0U;
     127                 :            :         u32 OBUF_0V;
     128                 :            :         u32 OBUF_1U;
     129                 :            :         u32 OBUF_1V;
     130                 :            :         u32 OSTRIDE;
     131                 :            :         u32 YRGB_VPH;
     132                 :            :         u32 UV_VPH;
     133                 :            :         u32 HORZ_PH;
     134                 :            :         u32 INIT_PHS;
     135                 :            :         u32 DWINPOS;
     136                 :            :         u32 DWINSZ;
     137                 :            :         u32 SWIDTH;
     138                 :            :         u32 SWIDTHSW;
     139                 :            :         u32 SHEIGHT;
     140                 :            :         u32 YRGBSCALE;
     141                 :            :         u32 UVSCALE;
     142                 :            :         u32 OCLRC0;
     143                 :            :         u32 OCLRC1;
     144                 :            :         u32 DCLRKV;
     145                 :            :         u32 DCLRKM;
     146                 :            :         u32 SCLRKVH;
     147                 :            :         u32 SCLRKVL;
     148                 :            :         u32 SCLRKEN;
     149                 :            :         u32 OCONFIG;
     150                 :            :         u32 OCMD;
     151                 :            :         u32 RESERVED1; /* 0x6C */
     152                 :            :         u32 OSTART_0Y;
     153                 :            :         u32 OSTART_1Y;
     154                 :            :         u32 OSTART_0U;
     155                 :            :         u32 OSTART_0V;
     156                 :            :         u32 OSTART_1U;
     157                 :            :         u32 OSTART_1V;
     158                 :            :         u32 OTILEOFF_0Y;
     159                 :            :         u32 OTILEOFF_1Y;
     160                 :            :         u32 OTILEOFF_0U;
     161                 :            :         u32 OTILEOFF_0V;
     162                 :            :         u32 OTILEOFF_1U;
     163                 :            :         u32 OTILEOFF_1V;
     164                 :            :         u32 FASTHSCALE; /* 0xA0 */
     165                 :            :         u32 UVSCALEV; /* 0xA4 */
     166                 :            :         u32 RESERVEDC[(0x200 - 0xA8) / 4]; /* 0xA8 - 0x1FC */
     167                 :            :         u16 Y_VCOEFS[N_VERT_Y_TAPS * N_PHASES]; /* 0x200 */
     168                 :            :         u16 RESERVEDD[0x100 / 2 - N_VERT_Y_TAPS * N_PHASES];
     169                 :            :         u16 Y_HCOEFS[N_HORIZ_Y_TAPS * N_PHASES]; /* 0x300 */
     170                 :            :         u16 RESERVEDE[0x200 / 2 - N_HORIZ_Y_TAPS * N_PHASES];
     171                 :            :         u16 UV_VCOEFS[N_VERT_UV_TAPS * N_PHASES]; /* 0x500 */
     172                 :            :         u16 RESERVEDF[0x100 / 2 - N_VERT_UV_TAPS * N_PHASES];
     173                 :            :         u16 UV_HCOEFS[N_HORIZ_UV_TAPS * N_PHASES]; /* 0x600 */
     174                 :            :         u16 RESERVEDG[0x100 / 2 - N_HORIZ_UV_TAPS * N_PHASES];
     175                 :            : };
     176                 :            : 
     177                 :            : struct intel_overlay {
     178                 :            :         struct drm_i915_private *i915;
     179                 :            :         struct intel_context *context;
     180                 :            :         struct intel_crtc *crtc;
     181                 :            :         struct i915_vma *vma;
     182                 :            :         struct i915_vma *old_vma;
     183                 :            :         bool active;
     184                 :            :         bool pfit_active;
     185                 :            :         u32 pfit_vscale_ratio; /* shifted-point number, (1<<12) == 1.0 */
     186                 :            :         u32 color_key:24;
     187                 :            :         u32 color_key_enabled:1;
     188                 :            :         u32 brightness, contrast, saturation;
     189                 :            :         u32 old_xscale, old_yscale;
     190                 :            :         /* register access */
     191                 :            :         struct drm_i915_gem_object *reg_bo;
     192                 :            :         struct overlay_registers __iomem *regs;
     193                 :            :         u32 flip_addr;
     194                 :            :         /* flip handling */
     195                 :            :         struct i915_active last_flip;
     196                 :            :         void (*flip_complete)(struct intel_overlay *ovl);
     197                 :            : };
     198                 :            : 
     199                 :          0 : static void i830_overlay_clock_gating(struct drm_i915_private *dev_priv,
     200                 :            :                                       bool enable)
     201                 :            : {
     202                 :          0 :         struct pci_dev *pdev = dev_priv->drm.pdev;
     203                 :          0 :         u8 val;
     204                 :            : 
     205                 :            :         /* WA_OVERLAY_CLKGATE:alm */
     206         [ #  # ]:          0 :         if (enable)
     207                 :          0 :                 I915_WRITE(DSPCLK_GATE_D, 0);
     208                 :            :         else
     209                 :          0 :                 I915_WRITE(DSPCLK_GATE_D, OVRUNIT_CLOCK_GATE_DISABLE);
     210                 :            : 
     211                 :            :         /* WA_DISABLE_L2CACHE_CLOCK_GATING:alm */
     212                 :          0 :         pci_bus_read_config_byte(pdev->bus,
     213                 :            :                                  PCI_DEVFN(0, 0), I830_CLOCK_GATE, &val);
     214         [ #  # ]:          0 :         if (enable)
     215                 :          0 :                 val &= ~I830_L2_CACHE_CLOCK_GATE_DISABLE;
     216                 :            :         else
     217                 :          0 :                 val |= I830_L2_CACHE_CLOCK_GATE_DISABLE;
     218                 :          0 :         pci_bus_write_config_byte(pdev->bus,
     219                 :            :                                   PCI_DEVFN(0, 0), I830_CLOCK_GATE, val);
     220                 :          0 : }
     221                 :            : 
     222                 :            : static struct i915_request *
     223                 :          0 : alloc_request(struct intel_overlay *overlay, void (*fn)(struct intel_overlay *))
     224                 :            : {
     225                 :          0 :         struct i915_request *rq;
     226                 :          0 :         int err;
     227                 :            : 
     228                 :          0 :         overlay->flip_complete = fn;
     229                 :            : 
     230                 :          0 :         rq = i915_request_create(overlay->context);
     231         [ #  # ]:          0 :         if (IS_ERR(rq))
     232                 :            :                 return rq;
     233                 :            : 
     234                 :          0 :         err = i915_active_add_request(&overlay->last_flip, rq);
     235         [ #  # ]:          0 :         if (err) {
     236                 :          0 :                 i915_request_add(rq);
     237                 :          0 :                 return ERR_PTR(err);
     238                 :            :         }
     239                 :            : 
     240                 :            :         return rq;
     241                 :            : }
     242                 :            : 
     243                 :            : /* overlay needs to be disable in OCMD reg */
     244                 :          0 : static int intel_overlay_on(struct intel_overlay *overlay)
     245                 :            : {
     246                 :          0 :         struct drm_i915_private *dev_priv = overlay->i915;
     247                 :          0 :         struct i915_request *rq;
     248                 :          0 :         u32 *cs;
     249                 :            : 
     250         [ #  # ]:          0 :         WARN_ON(overlay->active);
     251                 :            : 
     252                 :          0 :         rq = alloc_request(overlay, NULL);
     253         [ #  # ]:          0 :         if (IS_ERR(rq))
     254                 :          0 :                 return PTR_ERR(rq);
     255                 :            : 
     256                 :          0 :         cs = intel_ring_begin(rq, 4);
     257         [ #  # ]:          0 :         if (IS_ERR(cs)) {
     258                 :          0 :                 i915_request_add(rq);
     259                 :          0 :                 return PTR_ERR(cs);
     260                 :            :         }
     261                 :            : 
     262                 :          0 :         overlay->active = true;
     263                 :            : 
     264         [ #  # ]:          0 :         if (IS_I830(dev_priv))
     265                 :          0 :                 i830_overlay_clock_gating(dev_priv, false);
     266                 :            : 
     267                 :          0 :         *cs++ = MI_OVERLAY_FLIP | MI_OVERLAY_ON;
     268                 :          0 :         *cs++ = overlay->flip_addr | OFC_UPDATE;
     269                 :          0 :         *cs++ = MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP;
     270                 :          0 :         *cs++ = MI_NOOP;
     271                 :          0 :         intel_ring_advance(rq, cs);
     272                 :            : 
     273                 :          0 :         i915_request_add(rq);
     274                 :            : 
     275                 :          0 :         return i915_active_wait(&overlay->last_flip);
     276                 :            : }
     277                 :            : 
     278                 :          0 : static void intel_overlay_flip_prepare(struct intel_overlay *overlay,
     279                 :            :                                        struct i915_vma *vma)
     280                 :            : {
     281                 :          0 :         enum pipe pipe = overlay->crtc->pipe;
     282                 :          0 :         struct intel_frontbuffer *from = NULL, *to = NULL;
     283                 :            : 
     284         [ #  # ]:          0 :         WARN_ON(overlay->old_vma);
     285                 :            : 
     286         [ #  # ]:          0 :         if (overlay->vma)
     287                 :          0 :                 from = intel_frontbuffer_get(overlay->vma->obj);
     288         [ #  # ]:          0 :         if (vma)
     289                 :          0 :                 to = intel_frontbuffer_get(vma->obj);
     290                 :            : 
     291                 :          0 :         intel_frontbuffer_track(from, to, INTEL_FRONTBUFFER_OVERLAY(pipe));
     292                 :            : 
     293         [ #  # ]:          0 :         if (to)
     294                 :          0 :                 intel_frontbuffer_put(to);
     295         [ #  # ]:          0 :         if (from)
     296                 :          0 :                 intel_frontbuffer_put(from);
     297                 :            : 
     298                 :          0 :         intel_frontbuffer_flip_prepare(overlay->i915,
     299                 :            :                                        INTEL_FRONTBUFFER_OVERLAY(pipe));
     300                 :            : 
     301                 :          0 :         overlay->old_vma = overlay->vma;
     302         [ #  # ]:          0 :         if (vma)
     303                 :          0 :                 overlay->vma = i915_vma_get(vma);
     304                 :            :         else
     305                 :          0 :                 overlay->vma = NULL;
     306                 :          0 : }
     307                 :            : 
     308                 :            : /* overlay needs to be enabled in OCMD reg */
     309                 :          0 : static int intel_overlay_continue(struct intel_overlay *overlay,
     310                 :            :                                   struct i915_vma *vma,
     311                 :            :                                   bool load_polyphase_filter)
     312                 :            : {
     313                 :          0 :         struct drm_i915_private *dev_priv = overlay->i915;
     314                 :          0 :         struct i915_request *rq;
     315                 :          0 :         u32 flip_addr = overlay->flip_addr;
     316                 :          0 :         u32 tmp, *cs;
     317                 :            : 
     318         [ #  # ]:          0 :         WARN_ON(!overlay->active);
     319                 :            : 
     320         [ #  # ]:          0 :         if (load_polyphase_filter)
     321                 :          0 :                 flip_addr |= OFC_UPDATE;
     322                 :            : 
     323                 :            :         /* check for underruns */
     324                 :          0 :         tmp = I915_READ(DOVSTA);
     325         [ #  # ]:          0 :         if (tmp & (1 << 17))
     326                 :          0 :                 DRM_DEBUG("overlay underrun, DOVSTA: %x\n", tmp);
     327                 :            : 
     328                 :          0 :         rq = alloc_request(overlay, NULL);
     329         [ #  # ]:          0 :         if (IS_ERR(rq))
     330                 :          0 :                 return PTR_ERR(rq);
     331                 :            : 
     332                 :          0 :         cs = intel_ring_begin(rq, 2);
     333         [ #  # ]:          0 :         if (IS_ERR(cs)) {
     334                 :          0 :                 i915_request_add(rq);
     335                 :          0 :                 return PTR_ERR(cs);
     336                 :            :         }
     337                 :            : 
     338                 :          0 :         *cs++ = MI_OVERLAY_FLIP | MI_OVERLAY_CONTINUE;
     339                 :          0 :         *cs++ = flip_addr;
     340                 :          0 :         intel_ring_advance(rq, cs);
     341                 :            : 
     342                 :          0 :         intel_overlay_flip_prepare(overlay, vma);
     343                 :          0 :         i915_request_add(rq);
     344                 :            : 
     345                 :          0 :         return 0;
     346                 :            : }
     347                 :            : 
     348                 :          0 : static void intel_overlay_release_old_vma(struct intel_overlay *overlay)
     349                 :            : {
     350                 :          0 :         struct i915_vma *vma;
     351                 :            : 
     352                 :          0 :         vma = fetch_and_zero(&overlay->old_vma);
     353   [ #  #  #  # ]:          0 :         if (WARN_ON(!vma))
     354                 :            :                 return;
     355                 :            : 
     356                 :          0 :         intel_frontbuffer_flip_complete(overlay->i915,
     357                 :          0 :                                         INTEL_FRONTBUFFER_OVERLAY(overlay->crtc->pipe));
     358                 :            : 
     359                 :          0 :         i915_gem_object_unpin_from_display_plane(vma);
     360                 :          0 :         i915_vma_put(vma);
     361                 :            : }
     362                 :            : 
     363                 :            : static void
     364                 :          0 : intel_overlay_release_old_vid_tail(struct intel_overlay *overlay)
     365                 :            : {
     366                 :          0 :         intel_overlay_release_old_vma(overlay);
     367                 :          0 : }
     368                 :            : 
     369                 :          0 : static void intel_overlay_off_tail(struct intel_overlay *overlay)
     370                 :            : {
     371                 :          0 :         struct drm_i915_private *dev_priv = overlay->i915;
     372                 :            : 
     373                 :          0 :         intel_overlay_release_old_vma(overlay);
     374                 :            : 
     375                 :          0 :         overlay->crtc->overlay = NULL;
     376                 :          0 :         overlay->crtc = NULL;
     377                 :          0 :         overlay->active = false;
     378                 :            : 
     379         [ #  # ]:          0 :         if (IS_I830(dev_priv))
     380                 :          0 :                 i830_overlay_clock_gating(dev_priv, true);
     381                 :          0 : }
     382                 :            : 
     383                 :            : static void
     384                 :          0 : intel_overlay_last_flip_retire(struct i915_active *active)
     385                 :            : {
     386                 :          0 :         struct intel_overlay *overlay =
     387                 :          0 :                 container_of(active, typeof(*overlay), last_flip);
     388                 :            : 
     389         [ #  # ]:          0 :         if (overlay->flip_complete)
     390                 :          0 :                 overlay->flip_complete(overlay);
     391                 :          0 : }
     392                 :            : 
     393                 :            : /* overlay needs to be disabled in OCMD reg */
     394                 :          0 : static int intel_overlay_off(struct intel_overlay *overlay)
     395                 :            : {
     396                 :          0 :         struct i915_request *rq;
     397                 :          0 :         u32 *cs, flip_addr = overlay->flip_addr;
     398                 :            : 
     399         [ #  # ]:          0 :         WARN_ON(!overlay->active);
     400                 :            : 
     401                 :            :         /* According to intel docs the overlay hw may hang (when switching
     402                 :            :          * off) without loading the filter coeffs. It is however unclear whether
     403                 :            :          * this applies to the disabling of the overlay or to the switching off
     404                 :            :          * of the hw. Do it in both cases */
     405                 :          0 :         flip_addr |= OFC_UPDATE;
     406                 :            : 
     407                 :          0 :         rq = alloc_request(overlay, intel_overlay_off_tail);
     408         [ #  # ]:          0 :         if (IS_ERR(rq))
     409                 :          0 :                 return PTR_ERR(rq);
     410                 :            : 
     411                 :          0 :         cs = intel_ring_begin(rq, 6);
     412         [ #  # ]:          0 :         if (IS_ERR(cs)) {
     413                 :          0 :                 i915_request_add(rq);
     414                 :          0 :                 return PTR_ERR(cs);
     415                 :            :         }
     416                 :            : 
     417                 :            :         /* wait for overlay to go idle */
     418                 :          0 :         *cs++ = MI_OVERLAY_FLIP | MI_OVERLAY_CONTINUE;
     419                 :          0 :         *cs++ = flip_addr;
     420                 :          0 :         *cs++ = MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP;
     421                 :            : 
     422                 :            :         /* turn overlay off */
     423                 :          0 :         *cs++ = MI_OVERLAY_FLIP | MI_OVERLAY_OFF;
     424                 :          0 :         *cs++ = flip_addr;
     425                 :          0 :         *cs++ = MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP;
     426                 :            : 
     427                 :          0 :         intel_ring_advance(rq, cs);
     428                 :            : 
     429                 :          0 :         intel_overlay_flip_prepare(overlay, NULL);
     430                 :          0 :         i915_request_add(rq);
     431                 :            : 
     432                 :          0 :         return i915_active_wait(&overlay->last_flip);
     433                 :            : }
     434                 :            : 
     435                 :            : /* recover from an interruption due to a signal
     436                 :            :  * We have to be careful not to repeat work forever an make forward progess. */
     437                 :          0 : static int intel_overlay_recover_from_interrupt(struct intel_overlay *overlay)
     438                 :            : {
     439                 :          0 :         return i915_active_wait(&overlay->last_flip);
     440                 :            : }
     441                 :            : 
     442                 :            : /* Wait for pending overlay flip and release old frame.
     443                 :            :  * Needs to be called before the overlay register are changed
     444                 :            :  * via intel_overlay_(un)map_regs
     445                 :            :  */
     446                 :          0 : static int intel_overlay_release_old_vid(struct intel_overlay *overlay)
     447                 :            : {
     448                 :          0 :         struct drm_i915_private *dev_priv = overlay->i915;
     449                 :          0 :         struct i915_request *rq;
     450                 :          0 :         u32 *cs;
     451                 :            : 
     452                 :            :         /*
     453                 :            :          * Only wait if there is actually an old frame to release to
     454                 :            :          * guarantee forward progress.
     455                 :            :          */
     456         [ #  # ]:          0 :         if (!overlay->old_vma)
     457                 :            :                 return 0;
     458                 :            : 
     459         [ #  # ]:          0 :         if (!(I915_READ(GEN2_ISR) & I915_OVERLAY_PLANE_FLIP_PENDING_INTERRUPT)) {
     460                 :          0 :                 intel_overlay_release_old_vid_tail(overlay);
     461                 :          0 :                 return 0;
     462                 :            :         }
     463                 :            : 
     464                 :          0 :         rq = alloc_request(overlay, intel_overlay_release_old_vid_tail);
     465         [ #  # ]:          0 :         if (IS_ERR(rq))
     466                 :          0 :                 return PTR_ERR(rq);
     467                 :            : 
     468                 :          0 :         cs = intel_ring_begin(rq, 2);
     469         [ #  # ]:          0 :         if (IS_ERR(cs)) {
     470                 :          0 :                 i915_request_add(rq);
     471                 :          0 :                 return PTR_ERR(cs);
     472                 :            :         }
     473                 :            : 
     474                 :          0 :         *cs++ = MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP;
     475                 :          0 :         *cs++ = MI_NOOP;
     476                 :          0 :         intel_ring_advance(rq, cs);
     477                 :            : 
     478                 :          0 :         i915_request_add(rq);
     479                 :            : 
     480                 :          0 :         return i915_active_wait(&overlay->last_flip);
     481                 :            : }
     482                 :            : 
     483                 :          0 : void intel_overlay_reset(struct drm_i915_private *dev_priv)
     484                 :            : {
     485                 :          0 :         struct intel_overlay *overlay = dev_priv->overlay;
     486                 :            : 
     487         [ #  # ]:          0 :         if (!overlay)
     488                 :            :                 return;
     489                 :            : 
     490                 :          0 :         overlay->old_xscale = 0;
     491                 :          0 :         overlay->old_yscale = 0;
     492                 :          0 :         overlay->crtc = NULL;
     493                 :          0 :         overlay->active = false;
     494                 :            : }
     495                 :            : 
     496                 :            : static int packed_depth_bytes(u32 format)
     497                 :            : {
     498                 :            :         switch (format & I915_OVERLAY_DEPTH_MASK) {
     499                 :            :         case I915_OVERLAY_YUV422:
     500                 :            :                 return 4;
     501                 :            :         case I915_OVERLAY_YUV411:
     502                 :            :                 /* return 6; not implemented */
     503                 :            :         default:
     504                 :            :                 return -EINVAL;
     505                 :            :         }
     506                 :            : }
     507                 :            : 
     508                 :          0 : static int packed_width_bytes(u32 format, short width)
     509                 :            : {
     510                 :          0 :         switch (format & I915_OVERLAY_DEPTH_MASK) {
     511                 :          0 :         case I915_OVERLAY_YUV422:
     512                 :          0 :                 return width << 1;
     513                 :            :         default:
     514                 :            :                 return -EINVAL;
     515                 :            :         }
     516                 :            : }
     517                 :            : 
     518                 :          0 : static int uv_hsubsampling(u32 format)
     519                 :            : {
     520                 :          0 :         switch (format & I915_OVERLAY_DEPTH_MASK) {
     521                 :            :         case I915_OVERLAY_YUV422:
     522                 :            :         case I915_OVERLAY_YUV420:
     523                 :            :                 return 2;
     524                 :          0 :         case I915_OVERLAY_YUV411:
     525                 :            :         case I915_OVERLAY_YUV410:
     526                 :          0 :                 return 4;
     527                 :          0 :         default:
     528                 :          0 :                 return -EINVAL;
     529                 :            :         }
     530                 :            : }
     531                 :            : 
     532                 :          0 : static int uv_vsubsampling(u32 format)
     533                 :            : {
     534                 :          0 :         switch (format & I915_OVERLAY_DEPTH_MASK) {
     535                 :            :         case I915_OVERLAY_YUV420:
     536                 :            :         case I915_OVERLAY_YUV410:
     537                 :            :                 return 2;
     538                 :          0 :         case I915_OVERLAY_YUV422:
     539                 :            :         case I915_OVERLAY_YUV411:
     540                 :          0 :                 return 1;
     541                 :          0 :         default:
     542                 :          0 :                 return -EINVAL;
     543                 :            :         }
     544                 :            : }
     545                 :            : 
     546                 :          0 : static u32 calc_swidthsw(struct drm_i915_private *dev_priv, u32 offset, u32 width)
     547                 :            : {
     548                 :          0 :         u32 sw;
     549                 :            : 
     550                 :          0 :         if (IS_GEN(dev_priv, 2))
     551                 :          0 :                 sw = ALIGN((offset & 31) + width, 32);
     552                 :            :         else
     553                 :          0 :                 sw = ALIGN((offset & 63) + width, 64);
     554                 :            : 
     555   [ #  #  #  #  :          0 :         if (sw == 0)
                   #  # ]
     556                 :            :                 return 0;
     557                 :            : 
     558                 :          0 :         return (sw - 32) >> 3;
     559                 :            : }
     560                 :            : 
     561                 :            : static const u16 y_static_hcoeffs[N_PHASES][N_HORIZ_Y_TAPS] = {
     562                 :            :         [ 0] = { 0x3000, 0xb4a0, 0x1930, 0x1920, 0xb4a0, },
     563                 :            :         [ 1] = { 0x3000, 0xb500, 0x19d0, 0x1880, 0xb440, },
     564                 :            :         [ 2] = { 0x3000, 0xb540, 0x1a88, 0x2f80, 0xb3e0, },
     565                 :            :         [ 3] = { 0x3000, 0xb580, 0x1b30, 0x2e20, 0xb380, },
     566                 :            :         [ 4] = { 0x3000, 0xb5c0, 0x1bd8, 0x2cc0, 0xb320, },
     567                 :            :         [ 5] = { 0x3020, 0xb5e0, 0x1c60, 0x2b80, 0xb2c0, },
     568                 :            :         [ 6] = { 0x3020, 0xb5e0, 0x1cf8, 0x2a20, 0xb260, },
     569                 :            :         [ 7] = { 0x3020, 0xb5e0, 0x1d80, 0x28e0, 0xb200, },
     570                 :            :         [ 8] = { 0x3020, 0xb5c0, 0x1e08, 0x3f40, 0xb1c0, },
     571                 :            :         [ 9] = { 0x3020, 0xb580, 0x1e78, 0x3ce0, 0xb160, },
     572                 :            :         [10] = { 0x3040, 0xb520, 0x1ed8, 0x3aa0, 0xb120, },
     573                 :            :         [11] = { 0x3040, 0xb4a0, 0x1f30, 0x3880, 0xb0e0, },
     574                 :            :         [12] = { 0x3040, 0xb400, 0x1f78, 0x3680, 0xb0a0, },
     575                 :            :         [13] = { 0x3020, 0xb340, 0x1fb8, 0x34a0, 0xb060, },
     576                 :            :         [14] = { 0x3020, 0xb240, 0x1fe0, 0x32e0, 0xb040, },
     577                 :            :         [15] = { 0x3020, 0xb140, 0x1ff8, 0x3160, 0xb020, },
     578                 :            :         [16] = { 0xb000, 0x3000, 0x0800, 0x3000, 0xb000, },
     579                 :            : };
     580                 :            : 
     581                 :            : static const u16 uv_static_hcoeffs[N_PHASES][N_HORIZ_UV_TAPS] = {
     582                 :            :         [ 0] = { 0x3000, 0x1800, 0x1800, },
     583                 :            :         [ 1] = { 0xb000, 0x18d0, 0x2e60, },
     584                 :            :         [ 2] = { 0xb000, 0x1990, 0x2ce0, },
     585                 :            :         [ 3] = { 0xb020, 0x1a68, 0x2b40, },
     586                 :            :         [ 4] = { 0xb040, 0x1b20, 0x29e0, },
     587                 :            :         [ 5] = { 0xb060, 0x1bd8, 0x2880, },
     588                 :            :         [ 6] = { 0xb080, 0x1c88, 0x3e60, },
     589                 :            :         [ 7] = { 0xb0a0, 0x1d28, 0x3c00, },
     590                 :            :         [ 8] = { 0xb0c0, 0x1db8, 0x39e0, },
     591                 :            :         [ 9] = { 0xb0e0, 0x1e40, 0x37e0, },
     592                 :            :         [10] = { 0xb100, 0x1eb8, 0x3620, },
     593                 :            :         [11] = { 0xb100, 0x1f18, 0x34a0, },
     594                 :            :         [12] = { 0xb100, 0x1f68, 0x3360, },
     595                 :            :         [13] = { 0xb0e0, 0x1fa8, 0x3240, },
     596                 :            :         [14] = { 0xb0c0, 0x1fe0, 0x3140, },
     597                 :            :         [15] = { 0xb060, 0x1ff0, 0x30a0, },
     598                 :            :         [16] = { 0x3000, 0x0800, 0x3000, },
     599                 :            : };
     600                 :            : 
     601                 :          0 : static void update_polyphase_filter(struct overlay_registers __iomem *regs)
     602                 :            : {
     603                 :          0 :         memcpy_toio(regs->Y_HCOEFS, y_static_hcoeffs, sizeof(y_static_hcoeffs));
     604                 :          0 :         memcpy_toio(regs->UV_HCOEFS, uv_static_hcoeffs,
     605                 :            :                     sizeof(uv_static_hcoeffs));
     606                 :          0 : }
     607                 :            : 
     608                 :            : static bool update_scaling_factors(struct intel_overlay *overlay,
     609                 :            :                                    struct overlay_registers __iomem *regs,
     610                 :            :                                    struct drm_intel_overlay_put_image *params)
     611                 :            : {
     612                 :            :         /* fixed point with a 12 bit shift */
     613                 :            :         u32 xscale, yscale, xscale_UV, yscale_UV;
     614                 :            : #define FP_SHIFT 12
     615                 :            : #define FRACT_MASK 0xfff
     616                 :            :         bool scale_changed = false;
     617                 :            :         int uv_hscale = uv_hsubsampling(params->flags);
     618                 :            :         int uv_vscale = uv_vsubsampling(params->flags);
     619                 :            : 
     620                 :            :         if (params->dst_width > 1)
     621                 :            :                 xscale = ((params->src_scan_width - 1) << FP_SHIFT) /
     622                 :            :                         params->dst_width;
     623                 :            :         else
     624                 :            :                 xscale = 1 << FP_SHIFT;
     625                 :            : 
     626                 :            :         if (params->dst_height > 1)
     627                 :            :                 yscale = ((params->src_scan_height - 1) << FP_SHIFT) /
     628                 :            :                         params->dst_height;
     629                 :            :         else
     630                 :            :                 yscale = 1 << FP_SHIFT;
     631                 :            : 
     632                 :            :         /*if (params->format & I915_OVERLAY_YUV_PLANAR) {*/
     633                 :            :         xscale_UV = xscale/uv_hscale;
     634                 :            :         yscale_UV = yscale/uv_vscale;
     635                 :            :         /* make the Y scale to UV scale ratio an exact multiply */
     636                 :            :         xscale = xscale_UV * uv_hscale;
     637                 :            :         yscale = yscale_UV * uv_vscale;
     638                 :            :         /*} else {
     639                 :            :           xscale_UV = 0;
     640                 :            :           yscale_UV = 0;
     641                 :            :           }*/
     642                 :            : 
     643                 :            :         if (xscale != overlay->old_xscale || yscale != overlay->old_yscale)
     644                 :            :                 scale_changed = true;
     645                 :            :         overlay->old_xscale = xscale;
     646                 :            :         overlay->old_yscale = yscale;
     647                 :            : 
     648                 :            :         iowrite32(((yscale & FRACT_MASK) << 20) |
     649                 :            :                   ((xscale >> FP_SHIFT)  << 16) |
     650                 :            :                   ((xscale & FRACT_MASK) << 3),
     651                 :            :                  &regs->YRGBSCALE);
     652                 :            : 
     653                 :            :         iowrite32(((yscale_UV & FRACT_MASK) << 20) |
     654                 :            :                   ((xscale_UV >> FP_SHIFT)  << 16) |
     655                 :            :                   ((xscale_UV & FRACT_MASK) << 3),
     656                 :            :                  &regs->UVSCALE);
     657                 :            : 
     658                 :            :         iowrite32((((yscale    >> FP_SHIFT) << 16) |
     659                 :            :                    ((yscale_UV >> FP_SHIFT) << 0)),
     660                 :            :                  &regs->UVSCALEV);
     661                 :            : 
     662                 :            :         if (scale_changed)
     663                 :            :                 update_polyphase_filter(regs);
     664                 :            : 
     665                 :            :         return scale_changed;
     666                 :            : }
     667                 :            : 
     668                 :          0 : static void update_colorkey(struct intel_overlay *overlay,
     669                 :            :                             struct overlay_registers __iomem *regs)
     670                 :            : {
     671                 :          0 :         const struct intel_plane_state *state =
     672                 :          0 :                 to_intel_plane_state(overlay->crtc->base.primary->state);
     673                 :          0 :         u32 key = overlay->color_key;
     674                 :          0 :         u32 format = 0;
     675                 :          0 :         u32 flags = 0;
     676                 :            : 
     677         [ #  # ]:          0 :         if (overlay->color_key_enabled)
     678                 :          0 :                 flags |= DST_KEY_ENABLE;
     679                 :            : 
     680         [ #  # ]:          0 :         if (state->uapi.visible)
     681                 :          0 :                 format = state->hw.fb->format->format;
     682                 :            : 
     683   [ #  #  #  # ]:          0 :         switch (format) {
     684                 :          0 :         case DRM_FORMAT_C8:
     685                 :          0 :                 key = 0;
     686                 :          0 :                 flags |= CLK_RGB8I_MASK;
     687                 :          0 :                 break;
     688                 :          0 :         case DRM_FORMAT_XRGB1555:
     689                 :          0 :                 key = RGB15_TO_COLORKEY(key);
     690                 :          0 :                 flags |= CLK_RGB15_MASK;
     691                 :          0 :                 break;
     692                 :          0 :         case DRM_FORMAT_RGB565:
     693                 :          0 :                 key = RGB16_TO_COLORKEY(key);
     694                 :          0 :                 flags |= CLK_RGB16_MASK;
     695                 :          0 :                 break;
     696                 :            :         default:
     697                 :            :                 flags |= CLK_RGB24_MASK;
     698                 :            :                 break;
     699                 :            :         }
     700                 :            : 
     701                 :          0 :         iowrite32(key, &regs->DCLRKV);
     702                 :          0 :         iowrite32(flags, &regs->DCLRKM);
     703                 :          0 : }
     704                 :            : 
     705                 :            : static u32 overlay_cmd_reg(struct drm_intel_overlay_put_image *params)
     706                 :            : {
     707                 :            :         u32 cmd = OCMD_ENABLE | OCMD_BUF_TYPE_FRAME | OCMD_BUFFER0;
     708                 :            : 
     709                 :            :         if (params->flags & I915_OVERLAY_YUV_PLANAR) {
     710                 :            :                 switch (params->flags & I915_OVERLAY_DEPTH_MASK) {
     711                 :            :                 case I915_OVERLAY_YUV422:
     712                 :            :                         cmd |= OCMD_YUV_422_PLANAR;
     713                 :            :                         break;
     714                 :            :                 case I915_OVERLAY_YUV420:
     715                 :            :                         cmd |= OCMD_YUV_420_PLANAR;
     716                 :            :                         break;
     717                 :            :                 case I915_OVERLAY_YUV411:
     718                 :            :                 case I915_OVERLAY_YUV410:
     719                 :            :                         cmd |= OCMD_YUV_410_PLANAR;
     720                 :            :                         break;
     721                 :            :                 }
     722                 :            :         } else { /* YUV packed */
     723                 :            :                 switch (params->flags & I915_OVERLAY_DEPTH_MASK) {
     724                 :            :                 case I915_OVERLAY_YUV422:
     725                 :            :                         cmd |= OCMD_YUV_422_PACKED;
     726                 :            :                         break;
     727                 :            :                 case I915_OVERLAY_YUV411:
     728                 :            :                         cmd |= OCMD_YUV_411_PACKED;
     729                 :            :                         break;
     730                 :            :                 }
     731                 :            : 
     732                 :            :                 switch (params->flags & I915_OVERLAY_SWAP_MASK) {
     733                 :            :                 case I915_OVERLAY_NO_SWAP:
     734                 :            :                         break;
     735                 :            :                 case I915_OVERLAY_UV_SWAP:
     736                 :            :                         cmd |= OCMD_UV_SWAP;
     737                 :            :                         break;
     738                 :            :                 case I915_OVERLAY_Y_SWAP:
     739                 :            :                         cmd |= OCMD_Y_SWAP;
     740                 :            :                         break;
     741                 :            :                 case I915_OVERLAY_Y_AND_UV_SWAP:
     742                 :            :                         cmd |= OCMD_Y_AND_UV_SWAP;
     743                 :            :                         break;
     744                 :            :                 }
     745                 :            :         }
     746                 :            : 
     747                 :            :         return cmd;
     748                 :            : }
     749                 :            : 
     750                 :          0 : static int intel_overlay_do_put_image(struct intel_overlay *overlay,
     751                 :            :                                       struct drm_i915_gem_object *new_bo,
     752                 :            :                                       struct drm_intel_overlay_put_image *params)
     753                 :            : {
     754                 :          0 :         struct overlay_registers __iomem *regs = overlay->regs;
     755                 :          0 :         struct drm_i915_private *dev_priv = overlay->i915;
     756                 :          0 :         u32 swidth, swidthsw, sheight, ostride;
     757                 :          0 :         enum pipe pipe = overlay->crtc->pipe;
     758                 :          0 :         bool scale_changed = false;
     759                 :          0 :         struct i915_vma *vma;
     760                 :          0 :         int ret, tmp_width;
     761                 :            : 
     762         [ #  # ]:          0 :         WARN_ON(!drm_modeset_is_locked(&dev_priv->drm.mode_config.connection_mutex));
     763                 :            : 
     764                 :          0 :         ret = intel_overlay_release_old_vid(overlay);
     765         [ #  # ]:          0 :         if (ret != 0)
     766                 :            :                 return ret;
     767                 :            : 
     768                 :          0 :         atomic_inc(&dev_priv->gpu_error.pending_fb_pin);
     769                 :            : 
     770                 :          0 :         vma = i915_gem_object_pin_to_display_plane(new_bo,
     771                 :            :                                                    0, NULL, PIN_MAPPABLE);
     772         [ #  # ]:          0 :         if (IS_ERR(vma)) {
     773                 :          0 :                 ret = PTR_ERR(vma);
     774                 :          0 :                 goto out_pin_section;
     775                 :            :         }
     776         [ #  # ]:          0 :         i915_gem_object_flush_frontbuffer(new_bo, ORIGIN_DIRTYFB);
     777                 :            : 
     778         [ #  # ]:          0 :         if (!overlay->active) {
     779                 :          0 :                 u32 oconfig;
     780                 :            : 
     781                 :          0 :                 oconfig = OCONF_CC_OUT_8BIT;
     782         [ #  # ]:          0 :                 if (IS_GEN(dev_priv, 4))
     783                 :          0 :                         oconfig |= OCONF_CSC_MODE_BT709;
     784                 :          0 :                 oconfig |= pipe == 0 ?
     785         [ #  # ]:          0 :                         OCONF_PIPE_A : OCONF_PIPE_B;
     786                 :          0 :                 iowrite32(oconfig, &regs->OCONFIG);
     787                 :            : 
     788                 :          0 :                 ret = intel_overlay_on(overlay);
     789         [ #  # ]:          0 :                 if (ret != 0)
     790                 :          0 :                         goto out_unpin;
     791                 :            :         }
     792                 :            : 
     793                 :          0 :         iowrite32(params->dst_y << 16 | params->dst_x, &regs->DWINPOS);
     794                 :          0 :         iowrite32(params->dst_height << 16 | params->dst_width, &regs->DWINSZ);
     795                 :            : 
     796         [ #  # ]:          0 :         if (params->flags & I915_OVERLAY_YUV_PACKED)
     797                 :          0 :                 tmp_width = packed_width_bytes(params->flags,
     798         [ #  # ]:          0 :                                                params->src_width);
     799                 :            :         else
     800                 :          0 :                 tmp_width = params->src_width;
     801                 :            : 
     802                 :          0 :         swidth = params->src_width;
     803         [ #  # ]:          0 :         swidthsw = calc_swidthsw(dev_priv, params->offset_Y, tmp_width);
     804                 :          0 :         sheight = params->src_height;
     805                 :          0 :         iowrite32(i915_ggtt_offset(vma) + params->offset_Y, &regs->OBUF_0Y);
     806                 :          0 :         ostride = params->stride_Y;
     807                 :            : 
     808         [ #  # ]:          0 :         if (params->flags & I915_OVERLAY_YUV_PLANAR) {
     809      [ #  #  # ]:          0 :                 int uv_hscale = uv_hsubsampling(params->flags);
     810      [ #  #  # ]:          0 :                 int uv_vscale = uv_vsubsampling(params->flags);
     811                 :          0 :                 u32 tmp_U, tmp_V;
     812                 :            : 
     813                 :          0 :                 swidth |= (params->src_width / uv_hscale) << 16;
     814                 :          0 :                 sheight |= (params->src_height / uv_vscale) << 16;
     815                 :            : 
     816         [ #  # ]:          0 :                 tmp_U = calc_swidthsw(dev_priv, params->offset_U,
     817                 :            :                                       params->src_width / uv_hscale);
     818         [ #  # ]:          0 :                 tmp_V = calc_swidthsw(dev_priv, params->offset_V,
     819                 :            :                                       params->src_width / uv_hscale);
     820                 :          0 :                 swidthsw |= max(tmp_U, tmp_V) << 16;
     821                 :            : 
     822                 :          0 :                 iowrite32(i915_ggtt_offset(vma) + params->offset_U,
     823                 :          0 :                           &regs->OBUF_0U);
     824                 :          0 :                 iowrite32(i915_ggtt_offset(vma) + params->offset_V,
     825                 :          0 :                           &regs->OBUF_0V);
     826                 :            : 
     827                 :          0 :                 ostride |= params->stride_UV << 16;
     828                 :            :         }
     829                 :            : 
     830                 :          0 :         iowrite32(swidth, &regs->SWIDTH);
     831                 :          0 :         iowrite32(swidthsw, &regs->SWIDTHSW);
     832                 :          0 :         iowrite32(sheight, &regs->SHEIGHT);
     833                 :          0 :         iowrite32(ostride, &regs->OSTRIDE);
     834                 :            : 
     835                 :          0 :         scale_changed = update_scaling_factors(overlay, regs, params);
     836                 :            : 
     837                 :          0 :         update_colorkey(overlay, regs);
     838                 :            : 
     839                 :          0 :         iowrite32(overlay_cmd_reg(params), &regs->OCMD);
     840                 :            : 
     841                 :          0 :         ret = intel_overlay_continue(overlay, vma, scale_changed);
     842         [ #  # ]:          0 :         if (ret)
     843                 :          0 :                 goto out_unpin;
     844                 :            : 
     845                 :            :         return 0;
     846                 :            : 
     847                 :          0 : out_unpin:
     848                 :          0 :         i915_gem_object_unpin_from_display_plane(vma);
     849                 :          0 : out_pin_section:
     850                 :          0 :         atomic_dec(&dev_priv->gpu_error.pending_fb_pin);
     851                 :            : 
     852                 :          0 :         return ret;
     853                 :            : }
     854                 :            : 
     855                 :          0 : int intel_overlay_switch_off(struct intel_overlay *overlay)
     856                 :            : {
     857                 :          0 :         struct drm_i915_private *dev_priv = overlay->i915;
     858                 :          0 :         int ret;
     859                 :            : 
     860         [ #  # ]:          0 :         WARN_ON(!drm_modeset_is_locked(&dev_priv->drm.mode_config.connection_mutex));
     861                 :            : 
     862                 :          0 :         ret = intel_overlay_recover_from_interrupt(overlay);
     863         [ #  # ]:          0 :         if (ret != 0)
     864                 :            :                 return ret;
     865                 :            : 
     866         [ #  # ]:          0 :         if (!overlay->active)
     867                 :            :                 return 0;
     868                 :            : 
     869                 :          0 :         ret = intel_overlay_release_old_vid(overlay);
     870         [ #  # ]:          0 :         if (ret != 0)
     871                 :            :                 return ret;
     872                 :            : 
     873                 :          0 :         iowrite32(0, &overlay->regs->OCMD);
     874                 :            : 
     875                 :          0 :         return intel_overlay_off(overlay);
     876                 :            : }
     877                 :            : 
     878                 :          0 : static int check_overlay_possible_on_crtc(struct intel_overlay *overlay,
     879                 :            :                                           struct intel_crtc *crtc)
     880                 :            : {
     881                 :          0 :         if (!crtc->active)
     882                 :            :                 return -EINVAL;
     883                 :            : 
     884                 :            :         /* can't use the overlay with double wide pipe */
     885         [ #  # ]:          0 :         if (crtc->config->double_wide)
     886                 :            :                 return -EINVAL;
     887                 :            : 
     888                 :            :         return 0;
     889                 :            : }
     890                 :            : 
     891                 :            : static void update_pfit_vscale_ratio(struct intel_overlay *overlay)
     892                 :            : {
     893                 :            :         struct drm_i915_private *dev_priv = overlay->i915;
     894                 :            :         u32 pfit_control = I915_READ(PFIT_CONTROL);
     895                 :            :         u32 ratio;
     896                 :            : 
     897                 :            :         /* XXX: This is not the same logic as in the xorg driver, but more in
     898                 :            :          * line with the intel documentation for the i965
     899                 :            :          */
     900                 :            :         if (INTEL_GEN(dev_priv) >= 4) {
     901                 :            :                 /* on i965 use the PGM reg to read out the autoscaler values */
     902                 :            :                 ratio = I915_READ(PFIT_PGM_RATIOS) >> PFIT_VERT_SCALE_SHIFT_965;
     903                 :            :         } else {
     904                 :            :                 if (pfit_control & VERT_AUTO_SCALE)
     905                 :            :                         ratio = I915_READ(PFIT_AUTO_RATIOS);
     906                 :            :                 else
     907                 :            :                         ratio = I915_READ(PFIT_PGM_RATIOS);
     908                 :            :                 ratio >>= PFIT_VERT_SCALE_SHIFT;
     909                 :            :         }
     910                 :            : 
     911                 :            :         overlay->pfit_vscale_ratio = ratio;
     912                 :            : }
     913                 :            : 
     914                 :          0 : static int check_overlay_dst(struct intel_overlay *overlay,
     915                 :            :                              struct drm_intel_overlay_put_image *rec)
     916                 :            : {
     917                 :          0 :         const struct intel_crtc_state *pipe_config =
     918                 :            :                 overlay->crtc->config;
     919                 :            : 
     920                 :          0 :         if (rec->dst_x < pipe_config->pipe_src_w &&
     921         [ #  # ]:          0 :             rec->dst_x + rec->dst_width <= pipe_config->pipe_src_w &&
     922         [ #  # ]:          0 :             rec->dst_y < pipe_config->pipe_src_h &&
     923         [ #  # ]:          0 :             rec->dst_y + rec->dst_height <= pipe_config->pipe_src_h)
     924                 :            :                 return 0;
     925                 :            :         else
     926                 :          0 :                 return -EINVAL;
     927                 :            : }
     928                 :            : 
     929                 :          0 : static int check_overlay_scaling(struct drm_intel_overlay_put_image *rec)
     930                 :            : {
     931                 :          0 :         u32 tmp;
     932                 :            : 
     933                 :            :         /* downscaling limit is 8.0 */
     934                 :          0 :         tmp = ((rec->src_scan_height << 16) / rec->dst_height) >> 16;
     935                 :          0 :         if (tmp > 7)
     936                 :            :                 return -EINVAL;
     937                 :            : 
     938                 :          0 :         tmp = ((rec->src_scan_width << 16) / rec->dst_width) >> 16;
     939         [ #  # ]:          0 :         if (tmp > 7)
     940                 :            :                 return -EINVAL;
     941                 :            : 
     942                 :            :         return 0;
     943                 :            : }
     944                 :            : 
     945                 :            : static int check_overlay_src(struct drm_i915_private *dev_priv,
     946                 :            :                              struct drm_intel_overlay_put_image *rec,
     947                 :            :                              struct drm_i915_gem_object *new_bo)
     948                 :            : {
     949                 :            :         int uv_hscale = uv_hsubsampling(rec->flags);
     950                 :            :         int uv_vscale = uv_vsubsampling(rec->flags);
     951                 :            :         u32 stride_mask;
     952                 :            :         int depth;
     953                 :            :         u32 tmp;
     954                 :            : 
     955                 :            :         /* check src dimensions */
     956                 :            :         if (IS_I845G(dev_priv) || IS_I830(dev_priv)) {
     957                 :            :                 if (rec->src_height > IMAGE_MAX_HEIGHT_LEGACY ||
     958                 :            :                     rec->src_width  > IMAGE_MAX_WIDTH_LEGACY)
     959                 :            :                         return -EINVAL;
     960                 :            :         } else {
     961                 :            :                 if (rec->src_height > IMAGE_MAX_HEIGHT ||
     962                 :            :                     rec->src_width  > IMAGE_MAX_WIDTH)
     963                 :            :                         return -EINVAL;
     964                 :            :         }
     965                 :            : 
     966                 :            :         /* better safe than sorry, use 4 as the maximal subsampling ratio */
     967                 :            :         if (rec->src_height < N_VERT_Y_TAPS*4 ||
     968                 :            :             rec->src_width  < N_HORIZ_Y_TAPS*4)
     969                 :            :                 return -EINVAL;
     970                 :            : 
     971                 :            :         /* check alignment constraints */
     972                 :            :         switch (rec->flags & I915_OVERLAY_TYPE_MASK) {
     973                 :            :         case I915_OVERLAY_RGB:
     974                 :            :                 /* not implemented */
     975                 :            :                 return -EINVAL;
     976                 :            : 
     977                 :            :         case I915_OVERLAY_YUV_PACKED:
     978                 :            :                 if (uv_vscale != 1)
     979                 :            :                         return -EINVAL;
     980                 :            : 
     981                 :            :                 depth = packed_depth_bytes(rec->flags);
     982                 :            :                 if (depth < 0)
     983                 :            :                         return depth;
     984                 :            : 
     985                 :            :                 /* ignore UV planes */
     986                 :            :                 rec->stride_UV = 0;
     987                 :            :                 rec->offset_U = 0;
     988                 :            :                 rec->offset_V = 0;
     989                 :            :                 /* check pixel alignment */
     990                 :            :                 if (rec->offset_Y % depth)
     991                 :            :                         return -EINVAL;
     992                 :            :                 break;
     993                 :            : 
     994                 :            :         case I915_OVERLAY_YUV_PLANAR:
     995                 :            :                 if (uv_vscale < 0 || uv_hscale < 0)
     996                 :            :                         return -EINVAL;
     997                 :            :                 /* no offset restrictions for planar formats */
     998                 :            :                 break;
     999                 :            : 
    1000                 :            :         default:
    1001                 :            :                 return -EINVAL;
    1002                 :            :         }
    1003                 :            : 
    1004                 :            :         if (rec->src_width % uv_hscale)
    1005                 :            :                 return -EINVAL;
    1006                 :            : 
    1007                 :            :         /* stride checking */
    1008                 :            :         if (IS_I830(dev_priv) || IS_I845G(dev_priv))
    1009                 :            :                 stride_mask = 255;
    1010                 :            :         else
    1011                 :            :                 stride_mask = 63;
    1012                 :            : 
    1013                 :            :         if (rec->stride_Y & stride_mask || rec->stride_UV & stride_mask)
    1014                 :            :                 return -EINVAL;
    1015                 :            :         if (IS_GEN(dev_priv, 4) && rec->stride_Y < 512)
    1016                 :            :                 return -EINVAL;
    1017                 :            : 
    1018                 :            :         tmp = (rec->flags & I915_OVERLAY_TYPE_MASK) == I915_OVERLAY_YUV_PLANAR ?
    1019                 :            :                 4096 : 8192;
    1020                 :            :         if (rec->stride_Y > tmp || rec->stride_UV > 2*1024)
    1021                 :            :                 return -EINVAL;
    1022                 :            : 
    1023                 :            :         /* check buffer dimensions */
    1024                 :            :         switch (rec->flags & I915_OVERLAY_TYPE_MASK) {
    1025                 :            :         case I915_OVERLAY_RGB:
    1026                 :            :         case I915_OVERLAY_YUV_PACKED:
    1027                 :            :                 /* always 4 Y values per depth pixels */
    1028                 :            :                 if (packed_width_bytes(rec->flags, rec->src_width) > rec->stride_Y)
    1029                 :            :                         return -EINVAL;
    1030                 :            : 
    1031                 :            :                 tmp = rec->stride_Y*rec->src_height;
    1032                 :            :                 if (rec->offset_Y + tmp > new_bo->base.size)
    1033                 :            :                         return -EINVAL;
    1034                 :            :                 break;
    1035                 :            : 
    1036                 :            :         case I915_OVERLAY_YUV_PLANAR:
    1037                 :            :                 if (rec->src_width > rec->stride_Y)
    1038                 :            :                         return -EINVAL;
    1039                 :            :                 if (rec->src_width/uv_hscale > rec->stride_UV)
    1040                 :            :                         return -EINVAL;
    1041                 :            : 
    1042                 :            :                 tmp = rec->stride_Y * rec->src_height;
    1043                 :            :                 if (rec->offset_Y + tmp > new_bo->base.size)
    1044                 :            :                         return -EINVAL;
    1045                 :            : 
    1046                 :            :                 tmp = rec->stride_UV * (rec->src_height / uv_vscale);
    1047                 :            :                 if (rec->offset_U + tmp > new_bo->base.size ||
    1048                 :            :                     rec->offset_V + tmp > new_bo->base.size)
    1049                 :            :                         return -EINVAL;
    1050                 :            :                 break;
    1051                 :            :         }
    1052                 :            : 
    1053                 :            :         return 0;
    1054                 :            : }
    1055                 :            : 
    1056                 :          0 : int intel_overlay_put_image_ioctl(struct drm_device *dev, void *data,
    1057                 :            :                                   struct drm_file *file_priv)
    1058                 :            : {
    1059                 :          0 :         struct drm_intel_overlay_put_image *params = data;
    1060         [ #  # ]:          0 :         struct drm_i915_private *dev_priv = to_i915(dev);
    1061                 :          0 :         struct intel_overlay *overlay;
    1062                 :          0 :         struct drm_crtc *drmmode_crtc;
    1063                 :          0 :         struct intel_crtc *crtc;
    1064                 :          0 :         struct drm_i915_gem_object *new_bo;
    1065                 :          0 :         int ret;
    1066                 :            : 
    1067                 :          0 :         overlay = dev_priv->overlay;
    1068         [ #  # ]:          0 :         if (!overlay) {
    1069                 :          0 :                 DRM_DEBUG("userspace bug: no overlay\n");
    1070                 :          0 :                 return -ENODEV;
    1071                 :            :         }
    1072                 :            : 
    1073         [ #  # ]:          0 :         if (!(params->flags & I915_OVERLAY_ENABLE)) {
    1074                 :          0 :                 drm_modeset_lock_all(dev);
    1075                 :          0 :                 ret = intel_overlay_switch_off(overlay);
    1076                 :          0 :                 drm_modeset_unlock_all(dev);
    1077                 :            : 
    1078                 :          0 :                 return ret;
    1079                 :            :         }
    1080                 :            : 
    1081                 :          0 :         drmmode_crtc = drm_crtc_find(dev, file_priv, params->crtc_id);
    1082         [ #  # ]:          0 :         if (!drmmode_crtc)
    1083                 :            :                 return -ENOENT;
    1084                 :          0 :         crtc = to_intel_crtc(drmmode_crtc);
    1085                 :            : 
    1086                 :          0 :         new_bo = i915_gem_object_lookup(file_priv, params->bo_handle);
    1087         [ #  # ]:          0 :         if (!new_bo)
    1088                 :            :                 return -ENOENT;
    1089                 :            : 
    1090                 :          0 :         drm_modeset_lock_all(dev);
    1091                 :            : 
    1092         [ #  # ]:          0 :         if (i915_gem_object_is_tiled(new_bo)) {
    1093                 :          0 :                 DRM_DEBUG_KMS("buffer used for overlay image can not be tiled\n");
    1094                 :          0 :                 ret = -EINVAL;
    1095                 :          0 :                 goto out_unlock;
    1096                 :            :         }
    1097                 :            : 
    1098                 :          0 :         ret = intel_overlay_recover_from_interrupt(overlay);
    1099         [ #  # ]:          0 :         if (ret != 0)
    1100                 :          0 :                 goto out_unlock;
    1101                 :            : 
    1102         [ #  # ]:          0 :         if (overlay->crtc != crtc) {
    1103                 :          0 :                 ret = intel_overlay_switch_off(overlay);
    1104         [ #  # ]:          0 :                 if (ret != 0)
    1105                 :          0 :                         goto out_unlock;
    1106                 :            : 
    1107         [ #  # ]:          0 :                 ret = check_overlay_possible_on_crtc(overlay, crtc);
    1108                 :          0 :                 if (ret != 0)
    1109                 :          0 :                         goto out_unlock;
    1110                 :            : 
    1111                 :          0 :                 overlay->crtc = crtc;
    1112                 :          0 :                 crtc->overlay = overlay;
    1113                 :            : 
    1114                 :            :                 /* line too wide, i.e. one-line-mode */
    1115         [ #  # ]:          0 :                 if (crtc->config->pipe_src_w > 1024 &&
    1116         [ #  # ]:          0 :                     crtc->config->gmch_pfit.control & PFIT_ENABLE) {
    1117                 :          0 :                         overlay->pfit_active = true;
    1118                 :          0 :                         update_pfit_vscale_ratio(overlay);
    1119                 :            :                 } else
    1120                 :          0 :                         overlay->pfit_active = false;
    1121                 :            :         }
    1122                 :            : 
    1123         [ #  # ]:          0 :         ret = check_overlay_dst(overlay, params);
    1124                 :          0 :         if (ret != 0)
    1125                 :          0 :                 goto out_unlock;
    1126                 :            : 
    1127         [ #  # ]:          0 :         if (overlay->pfit_active) {
    1128                 :          0 :                 params->dst_y = (((u32)params->dst_y << 12) /
    1129                 :          0 :                                  overlay->pfit_vscale_ratio);
    1130                 :            :                 /* shifting right rounds downwards, so add 1 */
    1131                 :          0 :                 params->dst_height = (((u32)params->dst_height << 12) /
    1132                 :          0 :                                  overlay->pfit_vscale_ratio) + 1;
    1133                 :            :         }
    1134                 :            : 
    1135         [ #  # ]:          0 :         if (params->src_scan_height > params->src_height ||
    1136         [ #  # ]:          0 :             params->src_scan_width > params->src_width) {
    1137                 :          0 :                 ret = -EINVAL;
    1138                 :          0 :                 goto out_unlock;
    1139                 :            :         }
    1140                 :            : 
    1141                 :          0 :         ret = check_overlay_src(dev_priv, params, new_bo);
    1142         [ #  # ]:          0 :         if (ret != 0)
    1143                 :          0 :                 goto out_unlock;
    1144                 :            : 
    1145                 :            :         /* Check scaling after src size to prevent a divide-by-zero. */
    1146         [ #  # ]:          0 :         ret = check_overlay_scaling(params);
    1147                 :          0 :         if (ret != 0)
    1148                 :          0 :                 goto out_unlock;
    1149                 :            : 
    1150                 :          0 :         ret = intel_overlay_do_put_image(overlay, new_bo, params);
    1151         [ #  # ]:          0 :         if (ret != 0)
    1152                 :          0 :                 goto out_unlock;
    1153                 :            : 
    1154                 :          0 :         drm_modeset_unlock_all(dev);
    1155                 :          0 :         i915_gem_object_put(new_bo);
    1156                 :            : 
    1157                 :          0 :         return 0;
    1158                 :            : 
    1159                 :          0 : out_unlock:
    1160                 :          0 :         drm_modeset_unlock_all(dev);
    1161                 :          0 :         i915_gem_object_put(new_bo);
    1162                 :            : 
    1163                 :          0 :         return ret;
    1164                 :            : }
    1165                 :            : 
    1166                 :          0 : static void update_reg_attrs(struct intel_overlay *overlay,
    1167                 :            :                              struct overlay_registers __iomem *regs)
    1168                 :            : {
    1169                 :          0 :         iowrite32((overlay->contrast << 18) | (overlay->brightness & 0xff),
    1170                 :          0 :                   &regs->OCLRC0);
    1171                 :          0 :         iowrite32(overlay->saturation, &regs->OCLRC1);
    1172                 :          0 : }
    1173                 :            : 
    1174                 :          0 : static bool check_gamma_bounds(u32 gamma1, u32 gamma2)
    1175                 :            : {
    1176                 :          0 :         int i;
    1177                 :            : 
    1178                 :          0 :         if (gamma1 & 0xff000000 || gamma2 & 0xff000000)
    1179                 :            :                 return false;
    1180                 :            : 
    1181   [ #  #  #  #  :          0 :         for (i = 0; i < 3; i++) {
          #  #  #  #  #  
             #  #  #  #  
                      # ]
    1182   [ #  #  #  #  :          0 :                 if (((gamma1 >> i*8) & 0xff) >= ((gamma2 >> i*8) & 0xff))
          #  #  #  #  #  
             #  #  #  #  
                      # ]
    1183                 :            :                         return false;
    1184                 :            :         }
    1185                 :            : 
    1186                 :            :         return true;
    1187                 :            : }
    1188                 :            : 
    1189                 :            : static bool check_gamma5_errata(u32 gamma5)
    1190                 :            : {
    1191                 :            :         int i;
    1192                 :            : 
    1193         [ #  # ]:          0 :         for (i = 0; i < 3; i++) {
    1194         [ #  # ]:          0 :                 if (((gamma5 >> i*8) & 0xff) == 0x80)
    1195                 :            :                         return false;
    1196                 :            :         }
    1197                 :            : 
    1198                 :            :         return true;
    1199                 :            : }
    1200                 :            : 
    1201                 :          0 : static int check_gamma(struct drm_intel_overlay_attrs *attrs)
    1202                 :            : {
    1203   [ #  #  #  #  :          0 :         if (!check_gamma_bounds(0, attrs->gamma0) ||
                   #  # ]
    1204   [ #  #  #  # ]:          0 :             !check_gamma_bounds(attrs->gamma0, attrs->gamma1) ||
    1205   [ #  #  #  # ]:          0 :             !check_gamma_bounds(attrs->gamma1, attrs->gamma2) ||
    1206   [ #  #  #  # ]:          0 :             !check_gamma_bounds(attrs->gamma2, attrs->gamma3) ||
    1207   [ #  #  #  # ]:          0 :             !check_gamma_bounds(attrs->gamma3, attrs->gamma4) ||
    1208   [ #  #  #  # ]:          0 :             !check_gamma_bounds(attrs->gamma4, attrs->gamma5) ||
    1209                 :            :             !check_gamma_bounds(attrs->gamma5, 0x00ffffff))
    1210                 :            :                 return -EINVAL;
    1211                 :            : 
    1212         [ #  # ]:          0 :         if (!check_gamma5_errata(attrs->gamma5))
    1213                 :          0 :                 return -EINVAL;
    1214                 :            : 
    1215                 :            :         return 0;
    1216                 :            : }
    1217                 :            : 
    1218                 :          0 : int intel_overlay_attrs_ioctl(struct drm_device *dev, void *data,
    1219                 :            :                               struct drm_file *file_priv)
    1220                 :            : {
    1221                 :          0 :         struct drm_intel_overlay_attrs *attrs = data;
    1222         [ #  # ]:          0 :         struct drm_i915_private *dev_priv = to_i915(dev);
    1223                 :          0 :         struct intel_overlay *overlay;
    1224                 :          0 :         int ret;
    1225                 :            : 
    1226                 :          0 :         overlay = dev_priv->overlay;
    1227         [ #  # ]:          0 :         if (!overlay) {
    1228                 :          0 :                 DRM_DEBUG("userspace bug: no overlay\n");
    1229                 :          0 :                 return -ENODEV;
    1230                 :            :         }
    1231                 :            : 
    1232                 :          0 :         drm_modeset_lock_all(dev);
    1233                 :            : 
    1234                 :          0 :         ret = -EINVAL;
    1235         [ #  # ]:          0 :         if (!(attrs->flags & I915_OVERLAY_UPDATE_ATTRS)) {
    1236                 :          0 :                 attrs->color_key  = overlay->color_key;
    1237                 :          0 :                 attrs->brightness = overlay->brightness;
    1238                 :          0 :                 attrs->contrast   = overlay->contrast;
    1239                 :          0 :                 attrs->saturation = overlay->saturation;
    1240                 :            : 
    1241         [ #  # ]:          0 :                 if (!IS_GEN(dev_priv, 2)) {
    1242                 :          0 :                         attrs->gamma0 = I915_READ(OGAMC0);
    1243                 :          0 :                         attrs->gamma1 = I915_READ(OGAMC1);
    1244                 :          0 :                         attrs->gamma2 = I915_READ(OGAMC2);
    1245                 :          0 :                         attrs->gamma3 = I915_READ(OGAMC3);
    1246                 :          0 :                         attrs->gamma4 = I915_READ(OGAMC4);
    1247                 :          0 :                         attrs->gamma5 = I915_READ(OGAMC5);
    1248                 :            :                 }
    1249                 :            :         } else {
    1250         [ #  # ]:          0 :                 if (attrs->brightness < -128 || attrs->brightness > 127)
    1251                 :          0 :                         goto out_unlock;
    1252         [ #  # ]:          0 :                 if (attrs->contrast > 255)
    1253                 :          0 :                         goto out_unlock;
    1254         [ #  # ]:          0 :                 if (attrs->saturation > 1023)
    1255                 :          0 :                         goto out_unlock;
    1256                 :            : 
    1257                 :          0 :                 overlay->color_key  = attrs->color_key;
    1258                 :          0 :                 overlay->brightness = attrs->brightness;
    1259                 :          0 :                 overlay->contrast   = attrs->contrast;
    1260                 :          0 :                 overlay->saturation = attrs->saturation;
    1261                 :            : 
    1262                 :          0 :                 update_reg_attrs(overlay, overlay->regs);
    1263                 :            : 
    1264         [ #  # ]:          0 :                 if (attrs->flags & I915_OVERLAY_UPDATE_GAMMA) {
    1265         [ #  # ]:          0 :                         if (IS_GEN(dev_priv, 2))
    1266                 :          0 :                                 goto out_unlock;
    1267                 :            : 
    1268         [ #  # ]:          0 :                         if (overlay->active) {
    1269                 :          0 :                                 ret = -EBUSY;
    1270                 :          0 :                                 goto out_unlock;
    1271                 :            :                         }
    1272                 :            : 
    1273                 :          0 :                         ret = check_gamma(attrs);
    1274         [ #  # ]:          0 :                         if (ret)
    1275                 :          0 :                                 goto out_unlock;
    1276                 :            : 
    1277                 :          0 :                         I915_WRITE(OGAMC0, attrs->gamma0);
    1278                 :          0 :                         I915_WRITE(OGAMC1, attrs->gamma1);
    1279                 :          0 :                         I915_WRITE(OGAMC2, attrs->gamma2);
    1280                 :          0 :                         I915_WRITE(OGAMC3, attrs->gamma3);
    1281                 :          0 :                         I915_WRITE(OGAMC4, attrs->gamma4);
    1282                 :          0 :                         I915_WRITE(OGAMC5, attrs->gamma5);
    1283                 :            :                 }
    1284                 :            :         }
    1285                 :          0 :         overlay->color_key_enabled = (attrs->flags & I915_OVERLAY_DISABLE_DEST_COLORKEY) == 0;
    1286                 :            : 
    1287                 :          0 :         ret = 0;
    1288                 :          0 : out_unlock:
    1289                 :          0 :         drm_modeset_unlock_all(dev);
    1290                 :            : 
    1291                 :          0 :         return ret;
    1292                 :            : }
    1293                 :            : 
    1294                 :          0 : static int get_registers(struct intel_overlay *overlay, bool use_phys)
    1295                 :            : {
    1296                 :          0 :         struct drm_i915_private *i915 = overlay->i915;
    1297                 :          0 :         struct drm_i915_gem_object *obj;
    1298                 :          0 :         struct i915_vma *vma;
    1299                 :          0 :         int err;
    1300                 :            : 
    1301                 :          0 :         obj = i915_gem_object_create_stolen(i915, PAGE_SIZE);
    1302         [ #  # ]:          0 :         if (IS_ERR(obj))
    1303                 :          0 :                 obj = i915_gem_object_create_internal(i915, PAGE_SIZE);
    1304         [ #  # ]:          0 :         if (IS_ERR(obj))
    1305                 :          0 :                 return PTR_ERR(obj);
    1306                 :            : 
    1307                 :          0 :         vma = i915_gem_object_ggtt_pin(obj, NULL, 0, 0, PIN_MAPPABLE);
    1308         [ #  # ]:          0 :         if (IS_ERR(vma)) {
    1309                 :          0 :                 err = PTR_ERR(vma);
    1310                 :          0 :                 goto err_put_bo;
    1311                 :            :         }
    1312                 :            : 
    1313         [ #  # ]:          0 :         if (use_phys)
    1314                 :          0 :                 overlay->flip_addr = sg_dma_address(obj->mm.pages->sgl);
    1315                 :            :         else
    1316                 :          0 :                 overlay->flip_addr = i915_ggtt_offset(vma);
    1317                 :          0 :         overlay->regs = i915_vma_pin_iomap(vma);
    1318                 :          0 :         i915_vma_unpin(vma);
    1319                 :            : 
    1320         [ #  # ]:          0 :         if (IS_ERR(overlay->regs)) {
    1321                 :          0 :                 err = PTR_ERR(overlay->regs);
    1322                 :          0 :                 goto err_put_bo;
    1323                 :            :         }
    1324                 :            : 
    1325                 :          0 :         overlay->reg_bo = obj;
    1326                 :          0 :         return 0;
    1327                 :            : 
    1328                 :          0 : err_put_bo:
    1329                 :          0 :         i915_gem_object_put(obj);
    1330                 :          0 :         return err;
    1331                 :            : }
    1332                 :            : 
    1333                 :          0 : void intel_overlay_setup(struct drm_i915_private *dev_priv)
    1334                 :            : {
    1335                 :          0 :         struct intel_overlay *overlay;
    1336                 :          0 :         struct intel_engine_cs *engine;
    1337                 :          0 :         int ret;
    1338                 :            : 
    1339         [ #  # ]:          0 :         if (!HAS_OVERLAY(dev_priv))
    1340                 :            :                 return;
    1341                 :            : 
    1342                 :          0 :         engine = dev_priv->engine[RCS0];
    1343   [ #  #  #  # ]:          0 :         if (!engine || !engine->kernel_context)
    1344                 :            :                 return;
    1345                 :            : 
    1346                 :          0 :         overlay = kzalloc(sizeof(*overlay), GFP_KERNEL);
    1347         [ #  # ]:          0 :         if (!overlay)
    1348                 :            :                 return;
    1349                 :            : 
    1350                 :          0 :         overlay->i915 = dev_priv;
    1351                 :          0 :         overlay->context = engine->kernel_context;
    1352                 :          0 :         GEM_BUG_ON(!overlay->context);
    1353                 :            : 
    1354                 :          0 :         overlay->color_key = 0x0101fe;
    1355                 :          0 :         overlay->color_key_enabled = true;
    1356                 :          0 :         overlay->brightness = -19;
    1357                 :          0 :         overlay->contrast = 75;
    1358                 :          0 :         overlay->saturation = 146;
    1359                 :            : 
    1360                 :          0 :         i915_active_init(&overlay->last_flip,
    1361                 :            :                          NULL, intel_overlay_last_flip_retire);
    1362                 :            : 
    1363                 :          0 :         ret = get_registers(overlay, OVERLAY_NEEDS_PHYSICAL(dev_priv));
    1364         [ #  # ]:          0 :         if (ret)
    1365                 :          0 :                 goto out_free;
    1366                 :            : 
    1367                 :          0 :         memset_io(overlay->regs, 0, sizeof(struct overlay_registers));
    1368                 :          0 :         update_polyphase_filter(overlay->regs);
    1369                 :          0 :         update_reg_attrs(overlay, overlay->regs);
    1370                 :            : 
    1371                 :          0 :         dev_priv->overlay = overlay;
    1372                 :          0 :         DRM_INFO("Initialized overlay support.\n");
    1373                 :          0 :         return;
    1374                 :            : 
    1375                 :            : out_free:
    1376                 :          0 :         kfree(overlay);
    1377                 :            : }
    1378                 :            : 
    1379                 :          0 : void intel_overlay_cleanup(struct drm_i915_private *dev_priv)
    1380                 :            : {
    1381                 :          0 :         struct intel_overlay *overlay;
    1382                 :            : 
    1383                 :          0 :         overlay = fetch_and_zero(&dev_priv->overlay);
    1384         [ #  # ]:          0 :         if (!overlay)
    1385                 :            :                 return;
    1386                 :            : 
    1387                 :            :         /*
    1388                 :            :          * The bo's should be free'd by the generic code already.
    1389                 :            :          * Furthermore modesetting teardown happens beforehand so the
    1390                 :            :          * hardware should be off already.
    1391                 :            :          */
    1392         [ #  # ]:          0 :         WARN_ON(overlay->active);
    1393                 :            : 
    1394                 :          0 :         i915_gem_object_put(overlay->reg_bo);
    1395                 :          0 :         i915_active_fini(&overlay->last_flip);
    1396                 :            : 
    1397                 :          0 :         kfree(overlay);
    1398                 :            : }
    1399                 :            : 
    1400                 :            : #if IS_ENABLED(CONFIG_DRM_I915_CAPTURE_ERROR)
    1401                 :            : 
    1402                 :            : struct intel_overlay_error_state {
    1403                 :            :         struct overlay_registers regs;
    1404                 :            :         unsigned long base;
    1405                 :            :         u32 dovsta;
    1406                 :            :         u32 isr;
    1407                 :            : };
    1408                 :            : 
    1409                 :            : struct intel_overlay_error_state *
    1410                 :          0 : intel_overlay_capture_error_state(struct drm_i915_private *dev_priv)
    1411                 :            : {
    1412                 :          0 :         struct intel_overlay *overlay = dev_priv->overlay;
    1413                 :          0 :         struct intel_overlay_error_state *error;
    1414                 :            : 
    1415   [ #  #  #  # ]:          0 :         if (!overlay || !overlay->active)
    1416                 :            :                 return NULL;
    1417                 :            : 
    1418                 :          0 :         error = kmalloc(sizeof(*error), GFP_ATOMIC);
    1419         [ #  # ]:          0 :         if (error == NULL)
    1420                 :            :                 return NULL;
    1421                 :            : 
    1422                 :          0 :         error->dovsta = I915_READ(DOVSTA);
    1423                 :          0 :         error->isr = I915_READ(GEN2_ISR);
    1424                 :          0 :         error->base = overlay->flip_addr;
    1425                 :            : 
    1426                 :          0 :         memcpy_fromio(&error->regs, overlay->regs, sizeof(error->regs));
    1427                 :            : 
    1428                 :          0 :         return error;
    1429                 :            : }
    1430                 :            : 
    1431                 :            : void
    1432                 :          0 : intel_overlay_print_error_state(struct drm_i915_error_state_buf *m,
    1433                 :            :                                 struct intel_overlay_error_state *error)
    1434                 :            : {
    1435                 :          0 :         i915_error_printf(m, "Overlay, status: 0x%08x, interrupt: 0x%08x\n",
    1436                 :            :                           error->dovsta, error->isr);
    1437                 :          0 :         i915_error_printf(m, "  Register file at 0x%08lx:\n",
    1438                 :            :                           error->base);
    1439                 :            : 
    1440                 :            : #define P(x) i915_error_printf(m, "    " #x ":   0x%08x\n", error->regs.x)
    1441                 :          0 :         P(OBUF_0Y);
    1442                 :          0 :         P(OBUF_1Y);
    1443                 :          0 :         P(OBUF_0U);
    1444                 :          0 :         P(OBUF_0V);
    1445                 :          0 :         P(OBUF_1U);
    1446                 :          0 :         P(OBUF_1V);
    1447                 :          0 :         P(OSTRIDE);
    1448                 :          0 :         P(YRGB_VPH);
    1449                 :          0 :         P(UV_VPH);
    1450                 :          0 :         P(HORZ_PH);
    1451                 :          0 :         P(INIT_PHS);
    1452                 :          0 :         P(DWINPOS);
    1453                 :          0 :         P(DWINSZ);
    1454                 :          0 :         P(SWIDTH);
    1455                 :          0 :         P(SWIDTHSW);
    1456                 :          0 :         P(SHEIGHT);
    1457                 :          0 :         P(YRGBSCALE);
    1458                 :          0 :         P(UVSCALE);
    1459                 :          0 :         P(OCLRC0);
    1460                 :          0 :         P(OCLRC1);
    1461                 :          0 :         P(DCLRKV);
    1462                 :          0 :         P(DCLRKM);
    1463                 :          0 :         P(SCLRKVH);
    1464                 :          0 :         P(SCLRKVL);
    1465                 :          0 :         P(SCLRKEN);
    1466                 :          0 :         P(OCONFIG);
    1467                 :          0 :         P(OCMD);
    1468                 :          0 :         P(OSTART_0Y);
    1469                 :          0 :         P(OSTART_1Y);
    1470                 :          0 :         P(OSTART_0U);
    1471                 :          0 :         P(OSTART_0V);
    1472                 :          0 :         P(OSTART_1U);
    1473                 :          0 :         P(OSTART_1V);
    1474                 :          0 :         P(OTILEOFF_0Y);
    1475                 :          0 :         P(OTILEOFF_1Y);
    1476                 :          0 :         P(OTILEOFF_0U);
    1477                 :          0 :         P(OTILEOFF_0V);
    1478                 :          0 :         P(OTILEOFF_1U);
    1479                 :          0 :         P(OTILEOFF_1V);
    1480                 :          0 :         P(FASTHSCALE);
    1481                 :          0 :         P(UVSCALEV);
    1482                 :            : #undef P
    1483                 :          0 : }
    1484                 :            : 
    1485                 :            : #endif

Generated by: LCOV version 1.14