intel_overlay.c revision 9bedb9743fd906e4160468663ee6e1bbdc4412b8
102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter/*
202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter * Copyright © 2009
302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter *
402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter * Permission is hereby granted, free of charge, to any person obtaining a
502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter * copy of this software and associated documentation files (the "Software"),
602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter * to deal in the Software without restriction, including without limitation
702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter * the rights to use, copy, modify, merge, publish, distribute, sublicense,
802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter * and/or sell copies of the Software, and to permit persons to whom the
902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter * Software is furnished to do so, subject to the following conditions:
1002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter *
1102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter * The above copyright notice and this permission notice (including the next
1202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter * paragraph) shall be included in all copies or substantial portions of the
1302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter * Software.
1402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter *
1502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
1802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
2002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
2102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter * SOFTWARE.
2202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter *
2302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter * Authors:
2402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter *    Daniel Vetter <daniel@ffwll.ch>
2502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter *
2602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter * Derived from Xorg ddx, xf86-video-intel, src/i830_video.c
2702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter */
2802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#include "drmP.h"
2902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#include "drm.h"
3002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#include "i915_drm.h"
3102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#include "i915_drv.h"
3202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#include "i915_reg.h"
3302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#include "intel_drv.h"
3402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
3502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter/* Limits for overlay size. According to intel doc, the real limits are:
3602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter * Y width: 4095, UV width (planar): 2047, Y height: 2047,
3702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter * UV width (planar): * 1023. But the xorg thinks 2048 for height and width. Use
3802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter * the mininum of both.  */
3902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define IMAGE_MAX_WIDTH		2048
4002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define IMAGE_MAX_HEIGHT	2046 /* 2 * 1023 */
4102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter/* on 830 and 845 these large limits result in the card hanging */
4202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define IMAGE_MAX_WIDTH_LEGACY	1024
4302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define IMAGE_MAX_HEIGHT_LEGACY	1088
4402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
4502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter/* overlay register definitions */
4602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter/* OCMD register */
4702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_TILED_SURFACE	(0x1<<19)
4802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_MIRROR_MASK	(0x3<<17)
4902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_MIRROR_MODE	(0x3<<17)
5002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_MIRROR_HORIZONTAL	(0x1<<17)
5102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_MIRROR_VERTICAL	(0x2<<17)
5202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_MIRROR_BOTH	(0x3<<17)
5302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_BYTEORDER_MASK	(0x3<<14) /* zero for YUYV or FOURCC YUY2 */
5402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_UV_SWAP		(0x1<<14) /* YVYU */
5502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_Y_SWAP		(0x2<<14) /* UYVY or FOURCC UYVY */
5602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_Y_AND_UV_SWAP	(0x3<<14) /* VYUY */
5702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_SOURCE_FORMAT_MASK (0xf<<10)
5802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_RGB_888		(0x1<<10) /* not in i965 Intel docs */
5902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_RGB_555		(0x2<<10) /* not in i965 Intel docs */
6002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_RGB_565		(0x3<<10) /* not in i965 Intel docs */
6102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_YUV_422_PACKED	(0x8<<10)
6202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_YUV_411_PACKED	(0x9<<10) /* not in i965 Intel docs */
6302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_YUV_420_PLANAR	(0xc<<10)
6402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_YUV_422_PLANAR	(0xd<<10)
6502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_YUV_410_PLANAR	(0xe<<10) /* also 411 */
6602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_TVSYNCFLIP_PARITY	(0x1<<9)
6702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_TVSYNCFLIP_ENABLE	(0x1<<7)
6802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_BUF_TYPE_MASK	(Ox1<<5)
6902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_BUF_TYPE_FRAME	(0x0<<5)
7002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_BUF_TYPE_FIELD	(0x1<<5)
7102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_TEST_MODE		(0x1<<4)
7202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_BUFFER_SELECT	(0x3<<2)
7302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_BUFFER0		(0x0<<2)
7402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_BUFFER1		(0x1<<2)
7502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_FIELD_SELECT	(0x1<<2)
7602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_FIELD0		(0x0<<1)
7702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_FIELD1		(0x1<<1)
7802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_ENABLE		(0x1<<0)
7902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
8002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter/* OCONFIG register */
8102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCONF_PIPE_MASK		(0x1<<18)
8202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCONF_PIPE_A		(0x0<<18)
8302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCONF_PIPE_B		(0x1<<18)
8402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCONF_GAMMA2_ENABLE	(0x1<<16)
8502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCONF_CSC_MODE_BT601	(0x0<<5)
8602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCONF_CSC_MODE_BT709	(0x1<<5)
8702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCONF_CSC_BYPASS	(0x1<<4)
8802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCONF_CC_OUT_8BIT	(0x1<<3)
8902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCONF_TEST_MODE		(0x1<<2)
9002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCONF_THREE_LINE_BUFFER	(0x1<<0)
9102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCONF_TWO_LINE_BUFFER	(0x0<<0)
9202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
9302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter/* DCLRKM (dst-key) register */
9402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define DST_KEY_ENABLE		(0x1<<31)
9502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define CLK_RGB24_MASK		0x0
9602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define CLK_RGB16_MASK		0x070307
9702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define CLK_RGB15_MASK		0x070707
9802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define CLK_RGB8I_MASK		0xffffff
9902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
10002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define RGB16_TO_COLORKEY(c) \
10102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	(((c & 0xF800) << 8) | ((c & 0x07E0) << 5) | ((c & 0x001F) << 3))
10202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define RGB15_TO_COLORKEY(c) \
10302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	(((c & 0x7c00) << 9) | ((c & 0x03E0) << 6) | ((c & 0x001F) << 3))
10402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
10502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter/* overlay flip addr flag */
10602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OFC_UPDATE		0x1
10702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
10802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter/* polyphase filter coefficients */
10902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define N_HORIZ_Y_TAPS          5
11002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define N_VERT_Y_TAPS           3
11102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define N_HORIZ_UV_TAPS         3
11202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define N_VERT_UV_TAPS          3
11302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define N_PHASES                17
11402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define MAX_TAPS                5
11502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
11602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter/* memory bufferd overlay registers */
11702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstruct overlay_registers {
11802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u32 OBUF_0Y;
11902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u32 OBUF_1Y;
12002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u32 OBUF_0U;
12102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u32 OBUF_0V;
12202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u32 OBUF_1U;
12302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u32 OBUF_1V;
12402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u32 OSTRIDE;
12502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u32 YRGB_VPH;
12602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u32 UV_VPH;
12702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u32 HORZ_PH;
12802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u32 INIT_PHS;
12902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u32 DWINPOS;
13002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u32 DWINSZ;
13102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u32 SWIDTH;
13202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u32 SWIDTHSW;
13302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u32 SHEIGHT;
13402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u32 YRGBSCALE;
13502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u32 UVSCALE;
13602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u32 OCLRC0;
13702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u32 OCLRC1;
13802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u32 DCLRKV;
13902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u32 DCLRKM;
14002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u32 SCLRKVH;
14102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u32 SCLRKVL;
14202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u32 SCLRKEN;
14302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u32 OCONFIG;
14402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u32 OCMD;
14502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u32 RESERVED1; /* 0x6C */
14602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u32 OSTART_0Y;
14702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u32 OSTART_1Y;
14802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u32 OSTART_0U;
14902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u32 OSTART_0V;
15002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u32 OSTART_1U;
15102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u32 OSTART_1V;
15202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u32 OTILEOFF_0Y;
15302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u32 OTILEOFF_1Y;
15402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u32 OTILEOFF_0U;
15502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u32 OTILEOFF_0V;
15602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u32 OTILEOFF_1U;
15702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u32 OTILEOFF_1V;
15802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u32 FASTHSCALE; /* 0xA0 */
15902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u32 UVSCALEV; /* 0xA4 */
16002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u32 RESERVEDC[(0x200 - 0xA8) / 4]; /* 0xA8 - 0x1FC */
16102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u16 Y_VCOEFS[N_VERT_Y_TAPS * N_PHASES]; /* 0x200 */
16202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u16 RESERVEDD[0x100 / 2 - N_VERT_Y_TAPS * N_PHASES];
16302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u16 Y_HCOEFS[N_HORIZ_Y_TAPS * N_PHASES]; /* 0x300 */
16402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u16 RESERVEDE[0x200 / 2 - N_HORIZ_Y_TAPS * N_PHASES];
16502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u16 UV_VCOEFS[N_VERT_UV_TAPS * N_PHASES]; /* 0x500 */
16602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u16 RESERVEDF[0x100 / 2 - N_VERT_UV_TAPS * N_PHASES];
16702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u16 UV_HCOEFS[N_HORIZ_UV_TAPS * N_PHASES]; /* 0x600 */
16802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u16 RESERVEDG[0x100 / 2 - N_HORIZ_UV_TAPS * N_PHASES];
16902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter};
17002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
17102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter/* overlay flip addr flag */
17202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OFC_UPDATE		0x1
17302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
17402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OVERLAY_NONPHYSICAL(dev) (IS_G33(dev) || IS_I965G(dev))
17502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OVERLAY_EXISTS(dev) (!IS_G4X(dev) && !IS_IGDNG(dev))
17602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
17702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
17802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic struct overlay_registers *intel_overlay_map_regs_atomic(struct intel_overlay *overlay)
17902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
18002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter        drm_i915_private_t *dev_priv = overlay->dev->dev_private;
18102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct overlay_registers *regs;
18202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
18302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* no recursive mappings */
18402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	BUG_ON(overlay->virt_addr);
18502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
18602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (OVERLAY_NONPHYSICAL(overlay->dev)) {
18702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		regs = io_mapping_map_atomic_wc(dev_priv->mm.gtt_mapping,
18802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				overlay->reg_bo->gtt_offset);
18902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
19002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		if (!regs) {
19102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			DRM_ERROR("failed to map overlay regs in GTT\n");
19202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			return NULL;
19302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		}
19402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	} else
19502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		regs = overlay->reg_bo->phys_obj->handle->vaddr;
19602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
19702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return overlay->virt_addr = regs;
19802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
19902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
20002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic void intel_overlay_unmap_regs_atomic(struct intel_overlay *overlay)
20102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
20202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct drm_device *dev = overlay->dev;
20302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter        drm_i915_private_t *dev_priv = dev->dev_private;
20402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
20502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (OVERLAY_NONPHYSICAL(overlay->dev))
20602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		io_mapping_unmap_atomic(overlay->virt_addr);
20702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
20802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	overlay->virt_addr = NULL;
20902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
21002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	I915_READ(OVADD); /* flush wc cashes */
21102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
21202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return;
21302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
21402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
21502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter/* overlay needs to be disable in OCMD reg */
21602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic int intel_overlay_on(struct intel_overlay *overlay)
21702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
21802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct drm_device *dev = overlay->dev;
21902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter        drm_i915_private_t *dev_priv = dev->dev_private;
22002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int ret;
22102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	RING_LOCALS;
22202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
22302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	BUG_ON(overlay->active);
22402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
22503f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	overlay->active = 1;
22603f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	overlay->hw_wedged = NEEDS_WAIT_FOR_FLIP;
22703f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter
22802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	BEGIN_LP_RING(6);
22902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	OUT_RING(MI_FLUSH);
23002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	OUT_RING(MI_NOOP);
23102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_ON);
23202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	OUT_RING(overlay->flip_addr | OFC_UPDATE);
23302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
23402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	OUT_RING(MI_NOOP);
23502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	ADVANCE_LP_RING();
23602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
23703f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	overlay->last_flip_req = i915_add_request(dev, NULL, 0);
23803f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	if (overlay->last_flip_req == 0)
23903f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter		return -ENOMEM;
24002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
24103f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	ret = i915_do_wait_request(dev, overlay->last_flip_req, 1);
24203f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	if (ret != 0)
24303f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter		return ret;
24402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
24503f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	overlay->hw_wedged = 0;
24603f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	overlay->last_flip_req = 0;
24702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return 0;
24802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
24902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
25002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter/* overlay needs to be enabled in OCMD reg */
25102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic void intel_overlay_continue(struct intel_overlay *overlay,
25202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			    bool load_polyphase_filter)
25302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
25402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct drm_device *dev = overlay->dev;
25502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter        drm_i915_private_t *dev_priv = dev->dev_private;
25602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	u32 flip_addr = overlay->flip_addr;
25702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	u32 tmp;
25802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	RING_LOCALS;
25902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
26002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	BUG_ON(!overlay->active);
26102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
26202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (load_polyphase_filter)
26302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		flip_addr |= OFC_UPDATE;
26402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
26502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* check for underruns */
26602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	tmp = I915_READ(DOVSTA);
26702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (tmp & (1 << 17))
26802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		DRM_DEBUG("overlay underrun, DOVSTA: %x\n", tmp);
26902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
2705a5a0c64a99d7542c48c99d1a8bbb49e665842beDaniel Vetter	BEGIN_LP_RING(4);
27102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	OUT_RING(MI_FLUSH);
27202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	OUT_RING(MI_NOOP);
27302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_CONTINUE);
27402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	OUT_RING(flip_addr);
2755a5a0c64a99d7542c48c99d1a8bbb49e665842beDaniel Vetter        ADVANCE_LP_RING();
2765a5a0c64a99d7542c48c99d1a8bbb49e665842beDaniel Vetter
2775a5a0c64a99d7542c48c99d1a8bbb49e665842beDaniel Vetter	overlay->last_flip_req = i915_add_request(dev, NULL, 0);
2785a5a0c64a99d7542c48c99d1a8bbb49e665842beDaniel Vetter}
2795a5a0c64a99d7542c48c99d1a8bbb49e665842beDaniel Vetter
2805a5a0c64a99d7542c48c99d1a8bbb49e665842beDaniel Vetterstatic int intel_overlay_wait_flip(struct intel_overlay *overlay)
2815a5a0c64a99d7542c48c99d1a8bbb49e665842beDaniel Vetter{
2825a5a0c64a99d7542c48c99d1a8bbb49e665842beDaniel Vetter	struct drm_device *dev = overlay->dev;
2835a5a0c64a99d7542c48c99d1a8bbb49e665842beDaniel Vetter        drm_i915_private_t *dev_priv = dev->dev_private;
2845a5a0c64a99d7542c48c99d1a8bbb49e665842beDaniel Vetter	int ret;
2855a5a0c64a99d7542c48c99d1a8bbb49e665842beDaniel Vetter	u32 tmp;
2865a5a0c64a99d7542c48c99d1a8bbb49e665842beDaniel Vetter	RING_LOCALS;
2875a5a0c64a99d7542c48c99d1a8bbb49e665842beDaniel Vetter
2885a5a0c64a99d7542c48c99d1a8bbb49e665842beDaniel Vetter	if (overlay->last_flip_req != 0) {
2895c5a4359fe392b52b444134877fc4002be542b42Daniel Vetter		ret = i915_do_wait_request(dev, overlay->last_flip_req, 1);
2905c5a4359fe392b52b444134877fc4002be542b42Daniel Vetter		if (ret == 0) {
2915c5a4359fe392b52b444134877fc4002be542b42Daniel Vetter			overlay->last_flip_req = 0;
2925a5a0c64a99d7542c48c99d1a8bbb49e665842beDaniel Vetter
2935c5a4359fe392b52b444134877fc4002be542b42Daniel Vetter			tmp = I915_READ(ISR);
2945a5a0c64a99d7542c48c99d1a8bbb49e665842beDaniel Vetter
2955c5a4359fe392b52b444134877fc4002be542b42Daniel Vetter			if (!(tmp & I915_OVERLAY_PLANE_FLIP_PENDING_INTERRUPT))
2965c5a4359fe392b52b444134877fc4002be542b42Daniel Vetter				return 0;
2975c5a4359fe392b52b444134877fc4002be542b42Daniel Vetter		}
2985a5a0c64a99d7542c48c99d1a8bbb49e665842beDaniel Vetter	}
2995a5a0c64a99d7542c48c99d1a8bbb49e665842beDaniel Vetter
3005a5a0c64a99d7542c48c99d1a8bbb49e665842beDaniel Vetter	/* synchronous slowpath */
30103f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	overlay->hw_wedged = RELEASE_OLD_VID;
30203f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter
3035a5a0c64a99d7542c48c99d1a8bbb49e665842beDaniel Vetter	BEGIN_LP_RING(2);
30402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter        OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
30502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter        OUT_RING(MI_NOOP);
30602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter        ADVANCE_LP_RING();
30702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
30803f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	overlay->last_flip_req = i915_add_request(dev, NULL, 0);
30903f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	if (overlay->last_flip_req == 0)
31003f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter		return -ENOMEM;
31102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
31203f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	ret = i915_do_wait_request(dev, overlay->last_flip_req, 1);
31303f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	if (ret != 0)
31403f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter		return ret;
31503f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter
31603f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	overlay->hw_wedged = 0;
31703f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	overlay->last_flip_req = 0;
31803f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	return 0;
31902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
32002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
32102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter/* overlay needs to be disabled in OCMD reg */
32202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic int intel_overlay_off(struct intel_overlay *overlay)
32302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
32402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	u32 flip_addr = overlay->flip_addr;
32502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct drm_device *dev = overlay->dev;
32602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter        drm_i915_private_t *dev_priv = dev->dev_private;
32702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int ret;
32802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	RING_LOCALS;
32902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
33002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	BUG_ON(!overlay->active);
33102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
33202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* According to intel docs the overlay hw may hang (when switching
33302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	 * off) without loading the filter coeffs. It is however unclear whether
33402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	 * this applies to the disabling of the overlay or to the switching off
33502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	 * of the hw. Do it in both cases */
33602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	flip_addr |= OFC_UPDATE;
33702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
33802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* wait for overlay to go idle */
33903f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	overlay->hw_wedged = SWITCH_OFF_STAGE_1;
34003f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter
34102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	BEGIN_LP_RING(6);
34202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	OUT_RING(MI_FLUSH);
34302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	OUT_RING(MI_NOOP);
34402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_CONTINUE);
34502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	OUT_RING(flip_addr);
34602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter        OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
34702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter        OUT_RING(MI_NOOP);
34802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter        ADVANCE_LP_RING();
34902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
35003f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	overlay->last_flip_req = i915_add_request(dev, NULL, 0);
35103f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	if (overlay->last_flip_req == 0)
35203f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter		return -ENOMEM;
35303f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter
35403f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	ret = i915_do_wait_request(dev, overlay->last_flip_req, 1);
35503f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	if (ret != 0)
35602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return ret;
35702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
35802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* turn overlay off */
35903f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	overlay->hw_wedged = SWITCH_OFF_STAGE_2;
36003f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter
36102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	BEGIN_LP_RING(6);
36202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter        OUT_RING(MI_FLUSH);
36302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter        OUT_RING(MI_NOOP);
36402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter        OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_OFF);
36502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	OUT_RING(flip_addr);
36602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter        OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
36702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter        OUT_RING(MI_NOOP);
36802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	ADVANCE_LP_RING();
36902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
37003f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	overlay->last_flip_req = i915_add_request(dev, NULL, 0);
37103f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	if (overlay->last_flip_req == 0)
37203f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter		return -ENOMEM;
37303f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter
37403f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	ret = i915_do_wait_request(dev, overlay->last_flip_req, 1);
37503f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	if (ret != 0)
37602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return ret;
37702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
37803f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	overlay->hw_wedged = 0;
37903f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	overlay->last_flip_req = 0;
38002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return ret;
38102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
38202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
38312ca45fea91cfbb09df828bea958b47348caee6dDaniel Vetterstatic void intel_overlay_off_tail(struct intel_overlay *overlay)
38412ca45fea91cfbb09df828bea958b47348caee6dDaniel Vetter{
38512ca45fea91cfbb09df828bea958b47348caee6dDaniel Vetter	struct drm_gem_object *obj;
38612ca45fea91cfbb09df828bea958b47348caee6dDaniel Vetter
38712ca45fea91cfbb09df828bea958b47348caee6dDaniel Vetter	/* never have the overlay hw on without showing a frame */
38812ca45fea91cfbb09df828bea958b47348caee6dDaniel Vetter	BUG_ON(!overlay->vid_bo);
38912ca45fea91cfbb09df828bea958b47348caee6dDaniel Vetter	obj = overlay->vid_bo->obj;
39012ca45fea91cfbb09df828bea958b47348caee6dDaniel Vetter
39112ca45fea91cfbb09df828bea958b47348caee6dDaniel Vetter	i915_gem_object_unpin(obj);
39212ca45fea91cfbb09df828bea958b47348caee6dDaniel Vetter	drm_gem_object_unreference(obj);
39312ca45fea91cfbb09df828bea958b47348caee6dDaniel Vetter	overlay->vid_bo = NULL;
39412ca45fea91cfbb09df828bea958b47348caee6dDaniel Vetter
39512ca45fea91cfbb09df828bea958b47348caee6dDaniel Vetter	overlay->crtc->overlay = NULL;
39612ca45fea91cfbb09df828bea958b47348caee6dDaniel Vetter	overlay->crtc = NULL;
39712ca45fea91cfbb09df828bea958b47348caee6dDaniel Vetter	overlay->active = 0;
39812ca45fea91cfbb09df828bea958b47348caee6dDaniel Vetter}
39912ca45fea91cfbb09df828bea958b47348caee6dDaniel Vetter
40003f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter/* recover from an interruption due to a signal
40103f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter * We have to be careful not to repeat work forever an make forward progess. */
40203f77ea5972e6a2363152aec692744cac824dabaDaniel Vetterint intel_overlay_recover_from_interrupt(struct intel_overlay *overlay,
40303f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter					 int interruptible)
40403f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter{
40503f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	struct drm_device *dev = overlay->dev;
40603f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter        drm_i915_private_t *dev_priv = dev->dev_private;
40703f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	struct drm_gem_object *obj;
40803f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	u32 flip_addr;
40903f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	int ret;
41003f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	RING_LOCALS;
41103f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter
41203f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	if (overlay->hw_wedged == HW_WEDGED)
41303f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter		return -EIO;
41403f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter
41503f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	if (overlay->last_flip_req == 0) {
41603f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter		overlay->last_flip_req = i915_add_request(dev, NULL, 0);
41703f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter		if (overlay->last_flip_req == 0)
41803f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter			return -ENOMEM;
41903f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	}
42003f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter
42103f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	ret = i915_do_wait_request(dev, overlay->last_flip_req, interruptible);
42203f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	if (ret != 0)
42303f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter		return ret;
42403f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter
42503f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	switch (overlay->hw_wedged) {
42603f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter		case RELEASE_OLD_VID:
42703f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter			obj = overlay->old_vid_bo->obj;
42803f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter			i915_gem_object_unpin(obj);
42903f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter			drm_gem_object_unreference(obj);
43003f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter			overlay->old_vid_bo = NULL;
43103f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter			break;
43203f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter		case SWITCH_OFF_STAGE_1:
43303f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter			flip_addr = overlay->flip_addr;
43403f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter			flip_addr |= OFC_UPDATE;
43503f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter
43603f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter			overlay->hw_wedged = SWITCH_OFF_STAGE_2;
43703f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter
43803f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter			BEGIN_LP_RING(6);
43903f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter			OUT_RING(MI_FLUSH);
44003f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter			OUT_RING(MI_NOOP);
44103f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter			OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_OFF);
44203f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter			OUT_RING(flip_addr);
44303f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter			OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
44403f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter			OUT_RING(MI_NOOP);
44503f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter			ADVANCE_LP_RING();
44603f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter
44703f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter			overlay->last_flip_req = i915_add_request(dev, NULL, 0);
44803f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter			if (overlay->last_flip_req == 0)
44903f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter				return -ENOMEM;
45003f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter
45103f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter			ret = i915_do_wait_request(dev, overlay->last_flip_req,
45203f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter					interruptible);
45303f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter			if (ret != 0)
45403f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter				return ret;
45503f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter
45603f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter		case SWITCH_OFF_STAGE_2:
45712ca45fea91cfbb09df828bea958b47348caee6dDaniel Vetter			intel_overlay_off_tail(overlay);
45803f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter			break;
45903f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter		default:
46003f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter			BUG_ON(overlay->hw_wedged != NEEDS_WAIT_FOR_FLIP);
46103f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	}
46203f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter
46303f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	overlay->hw_wedged = 0;
46403f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	overlay->last_flip_req = 0;
46503f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	return 0;
46603f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter}
46703f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter
4685a5a0c64a99d7542c48c99d1a8bbb49e665842beDaniel Vetter/* Wait for pending overlay flip and release old frame.
4695a5a0c64a99d7542c48c99d1a8bbb49e665842beDaniel Vetter * Needs to be called before the overlay register are changed
4705a5a0c64a99d7542c48c99d1a8bbb49e665842beDaniel Vetter * via intel_overlay_(un)map_regs_atomic */
47102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic int intel_overlay_release_old_vid(struct intel_overlay *overlay)
47202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
47302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int ret;
47402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct drm_gem_object *obj;
47502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
47603f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	/* only wait if there is actually an old frame to release to
47703f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	 * guarantee forward progress */
47803f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	if (!overlay->old_vid_bo)
47903f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter		return 0;
48003f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter
48102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	ret = intel_overlay_wait_flip(overlay);
48202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (ret != 0)
48302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return ret;
48402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
48502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	obj = overlay->old_vid_bo->obj;
48602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	i915_gem_object_unpin(obj);
48702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	drm_gem_object_unreference(obj);
48802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	overlay->old_vid_bo = NULL;
48902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
49002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return 0;
49102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
49202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
49302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstruct put_image_params {
49402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int format;
49502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	short dst_x;
49602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	short dst_y;
49702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	short dst_w;
49802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	short dst_h;
49902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	short src_w;
50002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	short src_scan_h;
50102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	short src_scan_w;
50202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	short src_h;
50302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	short stride_Y;
50402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	short stride_UV;
50502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int offset_Y;
50602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int offset_U;
50702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int offset_V;
50802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter};
50902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
51002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic int packed_depth_bytes(u32 format)
51102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
51202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	switch (format & I915_OVERLAY_DEPTH_MASK) {
51302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		case I915_OVERLAY_YUV422:
51402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			return 4;
51502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		case I915_OVERLAY_YUV411:
51602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			/* return 6; not implemented */
51702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		default:
51802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			return -EINVAL;
51902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
52002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
52102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
52202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic int packed_width_bytes(u32 format, short width)
52302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
52402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	switch (format & I915_OVERLAY_DEPTH_MASK) {
52502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		case I915_OVERLAY_YUV422:
52602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			return width << 1;
52702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		default:
52802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			return -EINVAL;
52902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
53002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
53102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
53202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic int uv_hsubsampling(u32 format)
53302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
53402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	switch (format & I915_OVERLAY_DEPTH_MASK) {
53502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		case I915_OVERLAY_YUV422:
53602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		case I915_OVERLAY_YUV420:
53702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			return 2;
53802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		case I915_OVERLAY_YUV411:
53902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		case I915_OVERLAY_YUV410:
54002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			return 4;
54102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		default:
54202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			return -EINVAL;
54302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
54402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
54502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
54602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic int uv_vsubsampling(u32 format)
54702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
54802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	switch (format & I915_OVERLAY_DEPTH_MASK) {
54902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		case I915_OVERLAY_YUV420:
55002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		case I915_OVERLAY_YUV410:
55102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			return 2;
55202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		case I915_OVERLAY_YUV422:
55302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		case I915_OVERLAY_YUV411:
55402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			return 1;
55502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		default:
55602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			return -EINVAL;
55702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
55802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
55902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
56002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic u32 calc_swidthsw(struct drm_device *dev, u32 offset, u32 width)
56102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
56202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	u32 mask, shift, ret;
56302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (IS_I9XX(dev)) {
56402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		mask = 0x3f;
56502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		shift = 6;
56602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	} else {
56702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		mask = 0x1f;
56802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		shift = 5;
56902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
57002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	ret = ((offset + width + mask) >> shift) - (offset >> shift);
57102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (IS_I9XX(dev))
57202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		ret <<= 1;
57302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	ret -=1;
57402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return ret << 2;
57502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
57602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
57702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic const u16 y_static_hcoeffs[N_HORIZ_Y_TAPS * N_PHASES] = {
57802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3000, 0xb4a0, 0x1930, 0x1920, 0xb4a0,
57902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3000, 0xb500, 0x19d0, 0x1880, 0xb440,
58002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3000, 0xb540, 0x1a88, 0x2f80, 0xb3e0,
58102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3000, 0xb580, 0x1b30, 0x2e20, 0xb380,
58202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3000, 0xb5c0, 0x1bd8, 0x2cc0, 0xb320,
58302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3020, 0xb5e0, 0x1c60, 0x2b80, 0xb2c0,
58402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3020, 0xb5e0, 0x1cf8, 0x2a20, 0xb260,
58502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3020, 0xb5e0, 0x1d80, 0x28e0, 0xb200,
58602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3020, 0xb5c0, 0x1e08, 0x3f40, 0xb1c0,
58702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3020, 0xb580, 0x1e78, 0x3ce0, 0xb160,
58802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3040, 0xb520, 0x1ed8, 0x3aa0, 0xb120,
58902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3040, 0xb4a0, 0x1f30, 0x3880, 0xb0e0,
59002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3040, 0xb400, 0x1f78, 0x3680, 0xb0a0,
59102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3020, 0xb340, 0x1fb8, 0x34a0, 0xb060,
59202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3020, 0xb240, 0x1fe0, 0x32e0, 0xb040,
59302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3020, 0xb140, 0x1ff8, 0x3160, 0xb020,
59402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0xb000, 0x3000, 0x0800, 0x3000, 0xb000};
59502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic const u16 uv_static_hcoeffs[N_HORIZ_UV_TAPS * N_PHASES] = {
59602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3000, 0x1800, 0x1800, 0xb000, 0x18d0, 0x2e60,
59702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0xb000, 0x1990, 0x2ce0, 0xb020, 0x1a68, 0x2b40,
59802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0xb040, 0x1b20, 0x29e0, 0xb060, 0x1bd8, 0x2880,
59902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0xb080, 0x1c88, 0x3e60, 0xb0a0, 0x1d28, 0x3c00,
60002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0xb0c0, 0x1db8, 0x39e0, 0xb0e0, 0x1e40, 0x37e0,
60102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0xb100, 0x1eb8, 0x3620, 0xb100, 0x1f18, 0x34a0,
60202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0xb100, 0x1f68, 0x3360, 0xb0e0, 0x1fa8, 0x3240,
60302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0xb0c0, 0x1fe0, 0x3140, 0xb060, 0x1ff0, 0x30a0,
60402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3000, 0x0800, 0x3000};
60502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
60602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic void update_polyphase_filter(struct overlay_registers *regs)
60702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
60802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	memcpy(regs->Y_HCOEFS, y_static_hcoeffs, sizeof(y_static_hcoeffs));
60902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	memcpy(regs->UV_HCOEFS, uv_static_hcoeffs, sizeof(uv_static_hcoeffs));
61002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
61102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
61202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic bool update_scaling_factors(struct intel_overlay *overlay,
61302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				   struct overlay_registers *regs,
61402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				   struct put_image_params *params)
61502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
61602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* fixed point with a 12 bit shift */
61702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	u32 xscale, yscale, xscale_UV, yscale_UV;
61802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define FP_SHIFT 12
61902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define FRACT_MASK 0xfff
62002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	bool scale_changed = false;
62102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int uv_hscale = uv_hsubsampling(params->format);
62202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int uv_vscale = uv_vsubsampling(params->format);
62302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
62402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (params->dst_w > 1)
62502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		xscale = ((params->src_scan_w - 1) << FP_SHIFT)
62602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			/(params->dst_w);
62702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	else
62802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		xscale = 1 << FP_SHIFT;
62902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
63002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (params->dst_h > 1)
63102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		yscale = ((params->src_scan_h - 1) << FP_SHIFT)
63202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			/(params->dst_h);
63302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	else
63402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		yscale = 1 << FP_SHIFT;
63502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
63602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/*if (params->format & I915_OVERLAY_YUV_PLANAR) {*/
63702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		xscale_UV = xscale/uv_hscale;
63802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		yscale_UV = yscale/uv_vscale;
63902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		/* make the Y scale to UV scale ratio an exact multiply */
64002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		xscale = xscale_UV * uv_hscale;
64102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		yscale = yscale_UV * uv_vscale;
64202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/*} else {
64302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		xscale_UV = 0;
64402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		yscale_UV = 0;
64502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}*/
64602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
64702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (xscale != overlay->old_xscale || yscale != overlay->old_yscale)
64802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		scale_changed = true;
64902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	overlay->old_xscale = xscale;
65002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	overlay->old_yscale = yscale;
65102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
65202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	regs->YRGBSCALE = ((yscale & FRACT_MASK) << 20)
65302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		| ((xscale >> FP_SHIFT) << 16)
65402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		| ((xscale & FRACT_MASK) << 3);
65502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	regs->UVSCALE = ((yscale_UV & FRACT_MASK) << 20)
65602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		| ((xscale_UV >> FP_SHIFT) << 16)
65702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		| ((xscale_UV & FRACT_MASK) << 3);
65802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	regs->UVSCALEV = ((yscale >> FP_SHIFT) << 16)
65902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		| ((yscale_UV >> FP_SHIFT) << 0);
66002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
66102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (scale_changed)
66202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		update_polyphase_filter(regs);
66302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
66402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return scale_changed;
66502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
66602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
66702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic void update_colorkey(struct intel_overlay *overlay,
66802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			    struct overlay_registers *regs)
66902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
67002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	u32 key = overlay->color_key;
67102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	switch (overlay->crtc->base.fb->bits_per_pixel) {
67202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		case 8:
67302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			regs->DCLRKV = 0;
67402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			regs->DCLRKM = CLK_RGB8I_MASK | DST_KEY_ENABLE;
67502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		case 16:
67602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			if (overlay->crtc->base.fb->depth == 15) {
67702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				regs->DCLRKV = RGB15_TO_COLORKEY(key);
67802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				regs->DCLRKM = CLK_RGB15_MASK | DST_KEY_ENABLE;
67902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			} else {
68002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				regs->DCLRKV = RGB16_TO_COLORKEY(key);
68102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				regs->DCLRKM = CLK_RGB16_MASK | DST_KEY_ENABLE;
68202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			}
68302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		case 24:
68402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		case 32:
68502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			regs->DCLRKV = key;
68602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			regs->DCLRKM = CLK_RGB24_MASK | DST_KEY_ENABLE;
68702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
68802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
68902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
69002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic u32 overlay_cmd_reg(struct put_image_params *params)
69102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
69202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	u32 cmd = OCMD_ENABLE | OCMD_BUF_TYPE_FRAME | OCMD_BUFFER0;
69302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
69402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (params->format & I915_OVERLAY_YUV_PLANAR) {
69502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		switch (params->format & I915_OVERLAY_DEPTH_MASK) {
69602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			case I915_OVERLAY_YUV422:
69702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				cmd |= OCMD_YUV_422_PLANAR;
69802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				break;
69902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			case I915_OVERLAY_YUV420:
70002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				cmd |= OCMD_YUV_420_PLANAR;
70102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				break;
70202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			case I915_OVERLAY_YUV411:
70302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			case I915_OVERLAY_YUV410:
70402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				cmd |= OCMD_YUV_410_PLANAR;
70502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				break;
70602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		}
70702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	} else { /* YUV packed */
70802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		switch (params->format & I915_OVERLAY_DEPTH_MASK) {
70902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			case I915_OVERLAY_YUV422:
71002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				cmd |= OCMD_YUV_422_PACKED;
71102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				break;
71202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			case I915_OVERLAY_YUV411:
71302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				cmd |= OCMD_YUV_411_PACKED;
71402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				break;
71502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		}
71602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
71702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		switch (params->format & I915_OVERLAY_SWAP_MASK) {
71802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			case I915_OVERLAY_NO_SWAP:
71902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				break;
72002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			case I915_OVERLAY_UV_SWAP:
72102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				cmd |= OCMD_UV_SWAP;
72202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				break;
72302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			case I915_OVERLAY_Y_SWAP:
72402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				cmd |= OCMD_Y_SWAP;
72502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				break;
72602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			case I915_OVERLAY_Y_AND_UV_SWAP:
72702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				cmd |= OCMD_Y_AND_UV_SWAP;
72802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				break;
72902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		}
73002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
73102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
73202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return cmd;
73302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
73402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
73502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterint intel_overlay_do_put_image(struct intel_overlay *overlay,
73602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			       struct drm_gem_object *new_bo,
73702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			       struct put_image_params *params)
73802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
73902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int ret, tmp_width;
74002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct overlay_registers *regs;
74102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	bool scale_changed = false;
74202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct drm_i915_gem_object *bo_priv = new_bo->driver_private;
74302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct drm_device *dev = overlay->dev;
74402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
74502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	BUG_ON(!mutex_is_locked(&dev->struct_mutex));
74602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	BUG_ON(!mutex_is_locked(&dev->mode_config.mutex));
74702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	BUG_ON(!overlay);
74802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
74902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	ret = intel_overlay_release_old_vid(overlay);
75002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (ret != 0)
75102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return ret;
75202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
75302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	ret = i915_gem_object_pin(new_bo, PAGE_SIZE);
75402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (ret != 0)
75502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return ret;
75602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
75702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	ret = i915_gem_object_set_to_gtt_domain(new_bo, 0);
75802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (ret != 0)
75902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		goto out_unpin;
76002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
76102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!overlay->active) {
76202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		regs = intel_overlay_map_regs_atomic(overlay);
76302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		if (!regs) {
76402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			ret = -ENOMEM;
76502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			goto out_unpin;
76602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		}
76702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		regs->OCONFIG = OCONF_CC_OUT_8BIT;
76802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		if (IS_I965GM(overlay->dev))
76902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			regs->OCONFIG |= OCONF_CSC_MODE_BT709;
77002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		regs->OCONFIG |= overlay->crtc->pipe == 0 ?
77102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			OCONF_PIPE_A : OCONF_PIPE_B;
77202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		intel_overlay_unmap_regs_atomic(overlay);
77302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
77402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		ret = intel_overlay_on(overlay);
77502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		if (ret != 0)
77602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			goto out_unpin;
77702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
77802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
77902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	regs = intel_overlay_map_regs_atomic(overlay);
78002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!regs) {
78102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		ret = -ENOMEM;
78202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		goto out_unpin;
78302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
78402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
78502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	regs->DWINPOS = (params->dst_y << 16) | params->dst_x;
78602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	regs->DWINSZ = (params->dst_h << 16) | params->dst_w;
78702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
78802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (params->format & I915_OVERLAY_YUV_PACKED)
78902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		tmp_width = packed_width_bytes(params->format, params->src_w);
79002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	else
79102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		tmp_width = params->src_w;
79202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
79302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	regs->SWIDTH = params->src_w;
79402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	regs->SWIDTHSW = calc_swidthsw(overlay->dev,
79502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			params->offset_Y, tmp_width);
79602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	regs->SHEIGHT = params->src_h;
79702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	regs->OBUF_0Y = bo_priv->gtt_offset + params-> offset_Y;
79802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	regs->OSTRIDE = params->stride_Y;
79902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
80002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (params->format & I915_OVERLAY_YUV_PLANAR) {
80102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		int uv_hscale = uv_hsubsampling(params->format);
80202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		int uv_vscale = uv_vsubsampling(params->format);
80302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		u32 tmp_U, tmp_V;
80402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		regs->SWIDTH |= (params->src_w/uv_hscale) << 16;
80502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		tmp_U = calc_swidthsw(overlay->dev, params->offset_U,
80602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				params->src_w/uv_hscale);
80702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		tmp_V = calc_swidthsw(overlay->dev, params->offset_V,
80802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				params->src_w/uv_hscale);
80902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		regs->SWIDTHSW |= max_t(u32, tmp_U, tmp_V) << 16;
81002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		regs->SHEIGHT |= (params->src_h/uv_vscale) << 16;
81102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		regs->OBUF_0U = bo_priv->gtt_offset + params->offset_U;
81202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		regs->OBUF_0V = bo_priv->gtt_offset + params->offset_V;
81302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		regs->OSTRIDE |= params->stride_UV << 16;
81402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
81502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
81602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	scale_changed = update_scaling_factors(overlay, regs, params);
81702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
81802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	update_colorkey(overlay, regs);
81902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
82002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	regs->OCMD = overlay_cmd_reg(params);
82102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
82202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	intel_overlay_unmap_regs_atomic(overlay);
82302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
82402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	intel_overlay_continue(overlay, scale_changed);
82502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
82602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	overlay->old_vid_bo = overlay->vid_bo;
82702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	overlay->vid_bo = new_bo->driver_private;
82802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
82902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return 0;
83002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
83102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterout_unpin:
83202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	i915_gem_object_unpin(new_bo);
83302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return ret;
83402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
83502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
83602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterint intel_overlay_switch_off(struct intel_overlay *overlay)
83702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
83802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int ret;
83902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct overlay_registers *regs;
84002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct drm_device *dev = overlay->dev;
84102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
84202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	BUG_ON(!mutex_is_locked(&dev->struct_mutex));
84302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	BUG_ON(!mutex_is_locked(&dev->mode_config.mutex));
84402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
8459bedb9743fd906e4160468663ee6e1bbdc4412b8Daniel Vetter	if (overlay->hw_wedged) {
8469bedb9743fd906e4160468663ee6e1bbdc4412b8Daniel Vetter		ret = intel_overlay_recover_from_interrupt(overlay, 1);
8479bedb9743fd906e4160468663ee6e1bbdc4412b8Daniel Vetter		if (ret != 0)
8489bedb9743fd906e4160468663ee6e1bbdc4412b8Daniel Vetter			return ret;
8499bedb9743fd906e4160468663ee6e1bbdc4412b8Daniel Vetter	}
8509bedb9743fd906e4160468663ee6e1bbdc4412b8Daniel Vetter
85102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!overlay->active)
85202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return 0;
85302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
85402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	ret = intel_overlay_release_old_vid(overlay);
85502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (ret != 0)
85602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return ret;
85702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
85802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	regs = intel_overlay_map_regs_atomic(overlay);
85902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	regs->OCMD = 0;
86002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	intel_overlay_unmap_regs_atomic(overlay);
86102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
86202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	ret = intel_overlay_off(overlay);
86303f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	if (ret != 0)
86403f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter		return ret;
86503f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter
86612ca45fea91cfbb09df828bea958b47348caee6dDaniel Vetter	intel_overlay_off_tail(overlay);
86702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
86802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return 0;
86902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
87002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
87102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic int check_overlay_possible_on_crtc(struct intel_overlay *overlay,
87202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter					  struct intel_crtc *crtc)
87302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
87402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter        drm_i915_private_t *dev_priv = overlay->dev->dev_private;
87502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	u32 pipeconf;
87602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int pipeconf_reg = (crtc->pipe == 0) ? PIPEACONF : PIPEBCONF;
87702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
87802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!crtc->base.enabled || crtc->dpms_mode != DRM_MODE_DPMS_ON)
87902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EINVAL;
88002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
88102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	pipeconf = I915_READ(pipeconf_reg);
88202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
88302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* can't use the overlay with double wide pipe */
88402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!IS_I965G(overlay->dev) && pipeconf & PIPEACONF_DOUBLE_WIDE)
88502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EINVAL;
88602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
88702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return 0;
88802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
88902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
89002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic void update_pfit_vscale_ratio(struct intel_overlay *overlay)
89102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
89202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct drm_device *dev = overlay->dev;
89302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter        drm_i915_private_t *dev_priv = dev->dev_private;
89402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	u32 ratio;
89502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	u32 pfit_control = I915_READ(PFIT_CONTROL);
89602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
89702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* XXX: This is not the same logic as in the xorg driver, but more in
89802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	 * line with the intel documentation for the i965 */
89902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!IS_I965G(dev) && (pfit_control & VERT_AUTO_SCALE)) {
90002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		ratio = I915_READ(PFIT_AUTO_RATIOS) >> PFIT_VERT_SCALE_SHIFT;
90102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	} else { /* on i965 use the PGM reg to read out the autoscaler values */
90202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		ratio = I915_READ(PFIT_PGM_RATIOS);
90302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		if (IS_I965G(dev))
90402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			ratio >>= PFIT_VERT_SCALE_SHIFT_965;
90502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		else
90602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			ratio >>= PFIT_VERT_SCALE_SHIFT;
90702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
90802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
90902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	overlay->pfit_vscale_ratio = ratio;
91002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
91102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
91202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic int check_overlay_dst(struct intel_overlay *overlay,
91302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			     struct drm_intel_overlay_put_image *rec)
91402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
91502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct drm_display_mode *mode = &overlay->crtc->base.mode;
91602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
91702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if ((rec->dst_x < mode->crtc_hdisplay)
91802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	    && (rec->dst_x + rec->dst_width
91902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		    <= mode->crtc_hdisplay)
92002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	    && (rec->dst_y < mode->crtc_vdisplay)
92102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	    && (rec->dst_y + rec->dst_height
92202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		    <= mode->crtc_vdisplay))
92302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return 0;
92402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	else
92502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EINVAL;
92602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
92702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
92802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic int check_overlay_scaling(struct put_image_params *rec)
92902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
93002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	u32 tmp;
93102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
93202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* downscaling limit is 8.0 */
93302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	tmp = ((rec->src_scan_h << 16) / rec->dst_h) >> 16;
93402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (tmp > 7)
93502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EINVAL;
93602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	tmp = ((rec->src_scan_w << 16) / rec->dst_w) >> 16;
93702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (tmp > 7)
93802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EINVAL;
93902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
94002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return 0;
94102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
94202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
94302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic int check_overlay_src(struct drm_device *dev,
94402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			     struct drm_intel_overlay_put_image *rec,
94502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			     struct drm_gem_object *new_bo)
94602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
94702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	u32 stride_mask;
94802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int depth;
94902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int uv_hscale = uv_hsubsampling(rec->flags);
95002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int uv_vscale = uv_vsubsampling(rec->flags);
95102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	size_t tmp;
95202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
95302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* check src dimensions */
95402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (IS_845G(dev) || IS_I830(dev)) {
95502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		if (rec->src_height > IMAGE_MAX_HEIGHT_LEGACY
95602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		    || rec->src_width > IMAGE_MAX_WIDTH_LEGACY)
95702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			return -EINVAL;
95802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	} else {
95902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		if (rec->src_height > IMAGE_MAX_HEIGHT
96002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		    || rec->src_width > IMAGE_MAX_WIDTH)
96102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			return -EINVAL;
96202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
96302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* better safe than sorry, use 4 as the maximal subsampling ratio */
96402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (rec->src_height < N_VERT_Y_TAPS*4
96502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	    || rec->src_width < N_HORIZ_Y_TAPS*4)
96602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EINVAL;
96702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
96802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* check alingment constrains */
96902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	switch (rec->flags & I915_OVERLAY_TYPE_MASK) {
97002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		case I915_OVERLAY_RGB:
97102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			/* not implemented */
97202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			return -EINVAL;
97302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		case I915_OVERLAY_YUV_PACKED:
97402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			depth = packed_depth_bytes(rec->flags);
97502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			if (uv_vscale != 1)
97602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				return -EINVAL;
97702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			if (depth < 0)
97802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				return depth;
97902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			/* ignore UV planes */
98002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			rec->stride_UV = 0;
98102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			rec->offset_U = 0;
98202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			rec->offset_V = 0;
98302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			/* check pixel alignment */
98402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			if (rec->offset_Y % depth)
98502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				return -EINVAL;
98602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			break;
98702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		case I915_OVERLAY_YUV_PLANAR:
98802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			if (uv_vscale < 0 || uv_hscale < 0)
98902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				return -EINVAL;
99002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			/* no offset restrictions for planar formats */
99102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			break;
99202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		default:
99302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			return -EINVAL;
99402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
99502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
99602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (rec->src_width % uv_hscale)
99702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EINVAL;
99802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
99902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* stride checking */
100002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	stride_mask = 63;
100102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
100202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (rec->stride_Y & stride_mask || rec->stride_UV & stride_mask)
100302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EINVAL;
100402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (IS_I965G(dev) && rec->stride_Y < 512)
100502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EINVAL;
100602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
100702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	tmp = (rec->flags & I915_OVERLAY_TYPE_MASK) == I915_OVERLAY_YUV_PLANAR ?
100802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		4 : 8;
100902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (rec->stride_Y > tmp*1024 || rec->stride_UV > 2*1024)
101002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EINVAL;
101102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
101202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* check buffer dimensions */
101302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	switch (rec->flags & I915_OVERLAY_TYPE_MASK) {
101402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		case I915_OVERLAY_RGB:
101502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		case I915_OVERLAY_YUV_PACKED:
101602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			/* always 4 Y values per depth pixels */
101702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			if (packed_width_bytes(rec->flags, rec->src_width)
101802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter					> rec->stride_Y)
101902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				return -EINVAL;
102002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
102102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			tmp = rec->stride_Y*rec->src_height;
102202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			if (rec->offset_Y + tmp > new_bo->size)
102302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				return -EINVAL;
102402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			break;
102502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		case I915_OVERLAY_YUV_PLANAR:
102602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			if (rec->src_width > rec->stride_Y)
102702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				return -EINVAL;
102802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			if (rec->src_width/uv_hscale > rec->stride_UV)
102902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				return -EINVAL;
103002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
103102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			tmp = rec->stride_Y*rec->src_height;
103202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			if (rec->offset_Y + tmp > new_bo->size)
103302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				return -EINVAL;
103402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			tmp = rec->stride_UV*rec->src_height;
103502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			tmp /= uv_vscale;
103602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			if (rec->offset_U + tmp > new_bo->size
103702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			    || rec->offset_V + tmp > new_bo->size)
103802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				return -EINVAL;
103902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			break;
104002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
104102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
104202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return 0;
104302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
104402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
104502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterint intel_overlay_put_image(struct drm_device *dev, void *data,
104602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter                            struct drm_file *file_priv)
104702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
104802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct drm_intel_overlay_put_image *put_image_rec = data;
104902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	drm_i915_private_t *dev_priv = dev->dev_private;
105002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct intel_overlay *overlay;
105102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct drm_mode_object *drmmode_obj;
105202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct intel_crtc *crtc;
105302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct drm_gem_object *new_bo;
105402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct put_image_params *params;
105502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int ret;
105602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
105702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!dev_priv) {
105802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		DRM_ERROR("called with no initialization\n");
105902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EINVAL;
106002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
106102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
106202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	overlay = dev_priv->overlay;
106302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!overlay) {
106402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		DRM_DEBUG("userspace bug: no overlay\n");
106502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -ENODEV;
106602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
106702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
106802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!(put_image_rec->flags & I915_OVERLAY_ENABLE)) {
106902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		mutex_lock(&dev->mode_config.mutex);
107002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		mutex_lock(&dev->struct_mutex);
107102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
107202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		ret = intel_overlay_switch_off(overlay);
107302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
107402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		mutex_unlock(&dev->struct_mutex);
107502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		mutex_unlock(&dev->mode_config.mutex);
107602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
107702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return ret;
107802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
107902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
108002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	params = kmalloc(sizeof(struct put_image_params), GFP_KERNEL);
108102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!params)
108202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -ENOMEM;
108302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
108402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	drmmode_obj = drm_mode_object_find(dev, put_image_rec->crtc_id,
108502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter                        DRM_MODE_OBJECT_CRTC);
108602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!drmmode_obj)
108702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -ENOENT;
108802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	crtc = to_intel_crtc(obj_to_crtc(drmmode_obj));
108902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
109002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	new_bo = drm_gem_object_lookup(dev, file_priv,
109102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			put_image_rec->bo_handle);
109202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!new_bo)
109302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -ENOENT;
109402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
109502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	mutex_lock(&dev->mode_config.mutex);
109602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	mutex_lock(&dev->struct_mutex);
109702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
109803f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	if (overlay->hw_wedged) {
109903f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter		ret = intel_overlay_recover_from_interrupt(overlay, 1);
110003f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter		if (ret != 0)
110103f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter			goto out_unlock;
110203f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	}
110303f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter
110402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (overlay->crtc != crtc) {
110502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		struct drm_display_mode *mode = &crtc->base.mode;
110602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		ret = intel_overlay_switch_off(overlay);
110702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		if (ret != 0)
110802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			goto out_unlock;
110902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
111002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		ret = check_overlay_possible_on_crtc(overlay, crtc);
111102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		if (ret != 0)
111202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			goto out_unlock;
111302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
111402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		overlay->crtc = crtc;
111502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		crtc->overlay = overlay;
111602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
111702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		if (intel_panel_fitter_pipe(dev) == crtc->pipe
111802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		    /* and line to wide, i.e. one-line-mode */
111902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		    && mode->hdisplay > 1024) {
112002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			overlay->pfit_active = 1;
112102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			update_pfit_vscale_ratio(overlay);
112202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		} else
112302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			overlay->pfit_active = 0;
112402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
112502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
112602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	ret = check_overlay_dst(overlay, put_image_rec);
112702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (ret != 0)
112802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		goto out_unlock;
112902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
113002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (overlay->pfit_active) {
113102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		params->dst_y = ((((u32)put_image_rec->dst_y) << 12) /
113202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			overlay->pfit_vscale_ratio);
113302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		/* shifting right rounds downwards, so add 1 */
113402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		params->dst_h = ((((u32)put_image_rec->dst_height) << 12) /
113502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			overlay->pfit_vscale_ratio) + 1;
113602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	} else {
113702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		params->dst_y = put_image_rec->dst_y;
113802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		params->dst_h = put_image_rec->dst_height;
113902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
114002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	params->dst_x = put_image_rec->dst_x;
114102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	params->dst_w = put_image_rec->dst_width;
114202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
114302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	params->src_w = put_image_rec->src_width;
114402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	params->src_h = put_image_rec->src_height;
114502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	params->src_scan_w = put_image_rec->src_scan_width;
114602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	params->src_scan_h = put_image_rec->src_scan_height;
114702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (params->src_scan_h > params->src_h
114802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	    || params->src_scan_w > params->src_w) {
114902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		ret = -EINVAL;
115002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		goto out_unlock;
115102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
115202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
115302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	ret = check_overlay_src(dev, put_image_rec, new_bo);
115402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (ret != 0)
115502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		goto out_unlock;
115602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	params->format = put_image_rec->flags & ~I915_OVERLAY_FLAGS_MASK;
115702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	params->stride_Y = put_image_rec->stride_Y;
115802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	params->stride_UV = put_image_rec->stride_UV;
115902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	params->offset_Y = put_image_rec->offset_Y;
116002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	params->offset_U = put_image_rec->offset_U;
116102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	params->offset_V = put_image_rec->offset_V;
116202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
116302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* Check scaling after src size to prevent a divide-by-zero. */
116402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	ret = check_overlay_scaling(params);
116502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (ret != 0)
116602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		goto out_unlock;
116702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
116802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	ret = intel_overlay_do_put_image(overlay, new_bo, params);
116902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (ret != 0)
117002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		goto out_unlock;
117102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
117202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	mutex_unlock(&dev->struct_mutex);
117302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	mutex_unlock(&dev->mode_config.mutex);
117402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
117502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	kfree(params);
117602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
117702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return 0;
117802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
117902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterout_unlock:
118002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	mutex_unlock(&dev->struct_mutex);
118102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	mutex_unlock(&dev->mode_config.mutex);
118202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	drm_gem_object_unreference(new_bo);
118302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	kfree(params);
118402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
118502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return ret;
118602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
118702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
118802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic void update_reg_attrs(struct intel_overlay *overlay,
118902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			     struct overlay_registers *regs)
119002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
119102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	regs->OCLRC0 = (overlay->contrast << 18) | (overlay->brightness & 0xff);
119202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	regs->OCLRC1 = overlay->saturation;
119302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
119402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
119502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic bool check_gamma_bounds(u32 gamma1, u32 gamma2)
119602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
119702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int i;
119802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
119902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (gamma1 & 0xff000000 || gamma2 & 0xff000000)
120002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return false;
120102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
120202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	for (i = 0; i < 3; i++) {
120302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		if (((gamma1 >> i * 8) & 0xff) >= ((gamma2 >> i*8) & 0xff))
120402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			return false;
120502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
120602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
120702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return true;
120802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
120902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
121002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic bool check_gamma5_errata(u32 gamma5)
121102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
121202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int i;
121302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
121402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	for (i = 0; i < 3; i++) {
121502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		if (((gamma5 >> i*8) & 0xff) == 0x80)
121602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			return false;
121702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
121802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
121902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return true;
122002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
122102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
122202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic int check_gamma(struct drm_intel_overlay_attrs *attrs)
122302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
122402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!check_gamma_bounds(0, attrs->gamma0)
122502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	    || !check_gamma_bounds(attrs->gamma0, attrs->gamma1)
122602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	    || !check_gamma_bounds(attrs->gamma1, attrs->gamma2)
122702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	    || !check_gamma_bounds(attrs->gamma2, attrs->gamma3)
122802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	    || !check_gamma_bounds(attrs->gamma3, attrs->gamma4)
122902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	    || !check_gamma_bounds(attrs->gamma4, attrs->gamma5)
123002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	    || !check_gamma_bounds(attrs->gamma5, 0x00ffffff))
123102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EINVAL;
123202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!check_gamma5_errata(attrs->gamma5))
123302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EINVAL;
123402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return 0;
123502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
123602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
123702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterint intel_overlay_attrs(struct drm_device *dev, void *data,
123802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter                        struct drm_file *file_priv)
123902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
124002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct drm_intel_overlay_attrs *attrs = data;
124102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter        drm_i915_private_t *dev_priv = dev->dev_private;
124202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct intel_overlay *overlay;
124302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct overlay_registers *regs;
124402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int ret;
124502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
124602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!dev_priv) {
124702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		DRM_ERROR("called with no initialization\n");
124802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EINVAL;
124902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
125002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
125102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	overlay = dev_priv->overlay;
125202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!overlay) {
125302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		DRM_DEBUG("userspace bug: no overlay\n");
125402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -ENODEV;
125502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
125602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
125702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	mutex_lock(&dev->mode_config.mutex);
125802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	mutex_lock(&dev->struct_mutex);
125902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
126002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!(attrs->flags & I915_OVERLAY_UPDATE_ATTRS)) {
126102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		attrs->color_key = overlay->color_key;
126202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		attrs->brightness = overlay->brightness;
126302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		attrs->contrast = overlay->contrast;
126402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		attrs->saturation = overlay->saturation;
126502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
126602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		if (IS_I9XX(dev)) {
126702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			attrs->gamma0 = I915_READ(OGAMC0);
126802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			attrs->gamma1 = I915_READ(OGAMC1);
126902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			attrs->gamma2 = I915_READ(OGAMC2);
127002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			attrs->gamma3 = I915_READ(OGAMC3);
127102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			attrs->gamma4 = I915_READ(OGAMC4);
127202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			attrs->gamma5 = I915_READ(OGAMC5);
127302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		}
127402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		ret = 0;
127502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	} else {
127602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		overlay->color_key = attrs->color_key;
127702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		if (attrs->brightness >= -128 && attrs->brightness <= 127) {
127802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			overlay->brightness = attrs->brightness;
127902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		} else {
128002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			ret = -EINVAL;
128102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			goto out_unlock;
128202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		}
128302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		if (attrs->contrast <= 255) {
128402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			overlay->contrast = attrs->contrast;
128502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		} else {
128602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			ret = -EINVAL;
128702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			goto out_unlock;
128802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		}
128902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		if (attrs->saturation <= 1023) {
129002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			overlay->saturation = attrs->saturation;
129102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		} else {
129202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			ret = -EINVAL;
129302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			goto out_unlock;
129402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		}
129502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
129602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		regs = intel_overlay_map_regs_atomic(overlay);
129702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		if (!regs) {
129802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			ret = -ENOMEM;
129902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			goto out_unlock;
130002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		}
130102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
130202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		update_reg_attrs(overlay, regs);
130302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
130402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		intel_overlay_unmap_regs_atomic(overlay);
130502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
130602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		if (attrs->flags & I915_OVERLAY_UPDATE_GAMMA) {
130702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			if (!IS_I9XX(dev)) {
130802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				ret = -EINVAL;
130902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				goto out_unlock;
131002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			}
131102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
131202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			if (overlay->active) {
131302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				ret = -EBUSY;
131402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				goto out_unlock;
131502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			}
131602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
131702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			ret = check_gamma(attrs);
131802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			if (ret != 0)
131902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				goto out_unlock;
132002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
132102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			I915_WRITE(OGAMC0, attrs->gamma0);
132202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			I915_WRITE(OGAMC1, attrs->gamma1);
132302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			I915_WRITE(OGAMC2, attrs->gamma2);
132402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			I915_WRITE(OGAMC3, attrs->gamma3);
132502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			I915_WRITE(OGAMC4, attrs->gamma4);
132602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			I915_WRITE(OGAMC5, attrs->gamma5);
132702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		}
132802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		ret = 0;
132902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
133002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
133102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterout_unlock:
133202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	mutex_unlock(&dev->struct_mutex);
133302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	mutex_unlock(&dev->mode_config.mutex);
133402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
133502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return ret;
133602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
133702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
133802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vettervoid intel_setup_overlay(struct drm_device *dev)
133902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
134002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter        drm_i915_private_t *dev_priv = dev->dev_private;
134102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct intel_overlay *overlay;
134202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct drm_gem_object *reg_bo;
134302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct overlay_registers *regs;
134402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int ret;
134502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
134602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!OVERLAY_EXISTS(dev))
134702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return;
134802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
134902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	overlay = kzalloc(sizeof(struct intel_overlay), GFP_KERNEL);
135002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!overlay)
135102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return;
135202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	overlay->dev = dev;
135302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
135402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	reg_bo = drm_gem_object_alloc(dev, PAGE_SIZE);
135502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!reg_bo)
135602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		goto out_free;
135702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	overlay->reg_bo = reg_bo->driver_private;
135802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
135902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (OVERLAY_NONPHYSICAL(dev)) {
136002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		ret = i915_gem_object_pin(reg_bo, PAGE_SIZE);
136102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		if (ret) {
136202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter                        DRM_ERROR("failed to pin overlay register bo\n");
136302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter                        goto out_free_bo;
136402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter                }
136502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		overlay->flip_addr = overlay->reg_bo->gtt_offset;
136602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	} else {
136702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		ret = i915_gem_attach_phys_object(dev, reg_bo,
136802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				I915_GEM_PHYS_OVERLAY_REGS);
136902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter                if (ret) {
137002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter                        DRM_ERROR("failed to attach phys overlay regs\n");
137102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter                        goto out_free_bo;
137202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter                }
137302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		overlay->flip_addr = overlay->reg_bo->phys_obj->handle->busaddr;
137402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
137502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
137602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* init all values */
137702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	overlay->color_key = 0x0101fe;
137802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	overlay->brightness = -19;
137902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	overlay->contrast = 75;
138002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	overlay->saturation = 146;
138102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
138202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	regs = intel_overlay_map_regs_atomic(overlay);
138302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!regs)
138402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		goto out_free_bo;
138502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
138602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	memset(regs, 0, sizeof(struct overlay_registers));
138702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	update_polyphase_filter(regs);
138802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
138902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	update_reg_attrs(overlay, regs);
139002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
139102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	intel_overlay_unmap_regs_atomic(overlay);
139202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
139302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	dev_priv->overlay = overlay;
139402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	DRM_INFO("initialized overlay support\n");
139502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return;
139602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
139702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterout_free_bo:
139802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	drm_gem_object_unreference(reg_bo);
139902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterout_free:
140002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	kfree(overlay);
140102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return;
140202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
140302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
140402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vettervoid intel_cleanup_overlay(struct drm_device *dev)
140502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
140602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter        drm_i915_private_t *dev_priv = dev->dev_private;
140702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
140802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (dev_priv->overlay) {
140902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		/* The bo's should be free'd by the generic code already.
141002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		 * Furthermore modesetting teardown happens beforehand so the
141102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		 * hardware should be off already */
141202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		BUG_ON(dev_priv->overlay->active);
141302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
141402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		kfree(dev_priv->overlay);
141502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
141602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
1417