intel_overlay.c revision a1efd14a99483a4fb9308902397ed86b69454c99
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))
175bad720ff3e8e47a04bd88d9bbc8317e7d7e049d3Eric Anholt#define OVERLAY_EXISTS(dev) (!IS_G4X(dev) && !IS_IRONLAKE(dev) && !IS_GEN6(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	if (OVERLAY_NONPHYSICAL(overlay->dev))
20302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		io_mapping_unmap_atomic(overlay->virt_addr);
20402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
20502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	overlay->virt_addr = NULL;
20602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
20702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return;
20802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
20902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
21002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter/* overlay needs to be disable in OCMD reg */
21102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic int intel_overlay_on(struct intel_overlay *overlay)
21202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
21302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct drm_device *dev = overlay->dev;
21402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int ret;
215852835f343146a82a528c3b712b373661d4fa17aZou Nan hai	drm_i915_private_t *dev_priv = dev->dev_private;
21602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
21702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	BUG_ON(overlay->active);
21802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
21903f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	overlay->active = 1;
22003f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	overlay->hw_wedged = NEEDS_WAIT_FOR_FLIP;
22103f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter
2224f8a567c4666c73284832240db89fdadb2c50bd5Daniel Vetter	BEGIN_LP_RING(4);
22302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_ON);
22402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	OUT_RING(overlay->flip_addr | OFC_UPDATE);
22502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
22602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	OUT_RING(MI_NOOP);
22702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	ADVANCE_LP_RING();
22802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
229852835f343146a82a528c3b712b373661d4fa17aZou Nan hai	overlay->last_flip_req =
230852835f343146a82a528c3b712b373661d4fa17aZou Nan hai		i915_add_request(dev, NULL, 0, &dev_priv->render_ring);
23103f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	if (overlay->last_flip_req == 0)
23203f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter		return -ENOMEM;
23302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
234852835f343146a82a528c3b712b373661d4fa17aZou Nan hai	ret = i915_do_wait_request(dev,
235852835f343146a82a528c3b712b373661d4fa17aZou Nan hai			overlay->last_flip_req, 1, &dev_priv->render_ring);
23603f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	if (ret != 0)
23703f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter		return ret;
23802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
23903f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	overlay->hw_wedged = 0;
24003f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	overlay->last_flip_req = 0;
24102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return 0;
24202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
24302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
24402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter/* overlay needs to be enabled in OCMD reg */
24502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic void intel_overlay_continue(struct intel_overlay *overlay,
24602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			    bool load_polyphase_filter)
24702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
24802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct drm_device *dev = overlay->dev;
24902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter        drm_i915_private_t *dev_priv = dev->dev_private;
25002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	u32 flip_addr = overlay->flip_addr;
25102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	u32 tmp;
25202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
25302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	BUG_ON(!overlay->active);
25402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
25502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (load_polyphase_filter)
25602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		flip_addr |= OFC_UPDATE;
25702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
25802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* check for underruns */
25902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	tmp = I915_READ(DOVSTA);
26002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (tmp & (1 << 17))
26102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		DRM_DEBUG("overlay underrun, DOVSTA: %x\n", tmp);
26202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
2634f8a567c4666c73284832240db89fdadb2c50bd5Daniel Vetter	BEGIN_LP_RING(2);
26402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_CONTINUE);
26502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	OUT_RING(flip_addr);
2665a5a0c64a99d7542c48c99d1a8bbb49e665842beDaniel Vetter        ADVANCE_LP_RING();
2675a5a0c64a99d7542c48c99d1a8bbb49e665842beDaniel Vetter
268852835f343146a82a528c3b712b373661d4fa17aZou Nan hai	overlay->last_flip_req =
269852835f343146a82a528c3b712b373661d4fa17aZou Nan hai		i915_add_request(dev, NULL, 0, &dev_priv->render_ring);
2705a5a0c64a99d7542c48c99d1a8bbb49e665842beDaniel Vetter}
2715a5a0c64a99d7542c48c99d1a8bbb49e665842beDaniel Vetter
2725a5a0c64a99d7542c48c99d1a8bbb49e665842beDaniel Vetterstatic int intel_overlay_wait_flip(struct intel_overlay *overlay)
2735a5a0c64a99d7542c48c99d1a8bbb49e665842beDaniel Vetter{
2745a5a0c64a99d7542c48c99d1a8bbb49e665842beDaniel Vetter	struct drm_device *dev = overlay->dev;
2755a5a0c64a99d7542c48c99d1a8bbb49e665842beDaniel Vetter        drm_i915_private_t *dev_priv = dev->dev_private;
2765a5a0c64a99d7542c48c99d1a8bbb49e665842beDaniel Vetter	int ret;
2775a5a0c64a99d7542c48c99d1a8bbb49e665842beDaniel Vetter	u32 tmp;
2785a5a0c64a99d7542c48c99d1a8bbb49e665842beDaniel Vetter
2795a5a0c64a99d7542c48c99d1a8bbb49e665842beDaniel Vetter	if (overlay->last_flip_req != 0) {
280852835f343146a82a528c3b712b373661d4fa17aZou Nan hai		ret = i915_do_wait_request(dev, overlay->last_flip_req,
281852835f343146a82a528c3b712b373661d4fa17aZou Nan hai				1, &dev_priv->render_ring);
2825c5a4359fe392b52b444134877fc4002be542b42Daniel Vetter		if (ret == 0) {
2835c5a4359fe392b52b444134877fc4002be542b42Daniel Vetter			overlay->last_flip_req = 0;
2845a5a0c64a99d7542c48c99d1a8bbb49e665842beDaniel Vetter
2855c5a4359fe392b52b444134877fc4002be542b42Daniel Vetter			tmp = I915_READ(ISR);
2865a5a0c64a99d7542c48c99d1a8bbb49e665842beDaniel Vetter
2875c5a4359fe392b52b444134877fc4002be542b42Daniel Vetter			if (!(tmp & I915_OVERLAY_PLANE_FLIP_PENDING_INTERRUPT))
2885c5a4359fe392b52b444134877fc4002be542b42Daniel Vetter				return 0;
2895c5a4359fe392b52b444134877fc4002be542b42Daniel Vetter		}
2905a5a0c64a99d7542c48c99d1a8bbb49e665842beDaniel Vetter	}
2915a5a0c64a99d7542c48c99d1a8bbb49e665842beDaniel Vetter
2925a5a0c64a99d7542c48c99d1a8bbb49e665842beDaniel Vetter	/* synchronous slowpath */
29303f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	overlay->hw_wedged = RELEASE_OLD_VID;
29403f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter
2955a5a0c64a99d7542c48c99d1a8bbb49e665842beDaniel Vetter	BEGIN_LP_RING(2);
29602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter        OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
29702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter        OUT_RING(MI_NOOP);
29802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter        ADVANCE_LP_RING();
29902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
300852835f343146a82a528c3b712b373661d4fa17aZou Nan hai	overlay->last_flip_req =
301852835f343146a82a528c3b712b373661d4fa17aZou Nan hai		i915_add_request(dev, NULL, 0, &dev_priv->render_ring);
30203f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	if (overlay->last_flip_req == 0)
30303f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter		return -ENOMEM;
30402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
305852835f343146a82a528c3b712b373661d4fa17aZou Nan hai	ret = i915_do_wait_request(dev, overlay->last_flip_req,
306852835f343146a82a528c3b712b373661d4fa17aZou Nan hai			1, &dev_priv->render_ring);
30703f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	if (ret != 0)
30803f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter		return ret;
30903f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter
31003f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	overlay->hw_wedged = 0;
31103f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	overlay->last_flip_req = 0;
31203f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	return 0;
31302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
31402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
31502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter/* overlay needs to be disabled in OCMD reg */
31602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic int intel_overlay_off(struct intel_overlay *overlay)
31702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
31802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	u32 flip_addr = overlay->flip_addr;
31902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct drm_device *dev = overlay->dev;
320852835f343146a82a528c3b712b373661d4fa17aZou Nan hai	drm_i915_private_t *dev_priv = dev->dev_private;
32102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int ret;
32202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
32302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	BUG_ON(!overlay->active);
32402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
32502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* According to intel docs the overlay hw may hang (when switching
32602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	 * off) without loading the filter coeffs. It is however unclear whether
32702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	 * this applies to the disabling of the overlay or to the switching off
32802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	 * of the hw. Do it in both cases */
32902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	flip_addr |= OFC_UPDATE;
33002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
33102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* wait for overlay to go idle */
33203f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	overlay->hw_wedged = SWITCH_OFF_STAGE_1;
33303f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter
3344f8a567c4666c73284832240db89fdadb2c50bd5Daniel Vetter	BEGIN_LP_RING(4);
33502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_CONTINUE);
33602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	OUT_RING(flip_addr);
33702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter        OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
33802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter        OUT_RING(MI_NOOP);
33902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter        ADVANCE_LP_RING();
34002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
341852835f343146a82a528c3b712b373661d4fa17aZou Nan hai	overlay->last_flip_req =
342852835f343146a82a528c3b712b373661d4fa17aZou Nan hai		i915_add_request(dev, NULL, 0, &dev_priv->render_ring);
34303f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	if (overlay->last_flip_req == 0)
34403f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter		return -ENOMEM;
34503f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter
346852835f343146a82a528c3b712b373661d4fa17aZou Nan hai	ret = i915_do_wait_request(dev, overlay->last_flip_req,
347852835f343146a82a528c3b712b373661d4fa17aZou Nan hai			1, &dev_priv->render_ring);
34803f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	if (ret != 0)
34902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return ret;
35002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
35102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* turn overlay off */
35203f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	overlay->hw_wedged = SWITCH_OFF_STAGE_2;
35303f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter
3544f8a567c4666c73284832240db89fdadb2c50bd5Daniel Vetter	BEGIN_LP_RING(4);
35502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter        OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_OFF);
35602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	OUT_RING(flip_addr);
35702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter        OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
35802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter        OUT_RING(MI_NOOP);
35902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	ADVANCE_LP_RING();
36002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
361852835f343146a82a528c3b712b373661d4fa17aZou Nan hai	overlay->last_flip_req =
362852835f343146a82a528c3b712b373661d4fa17aZou Nan hai		i915_add_request(dev, NULL, 0, &dev_priv->render_ring);
36303f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	if (overlay->last_flip_req == 0)
36403f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter		return -ENOMEM;
36503f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter
366852835f343146a82a528c3b712b373661d4fa17aZou Nan hai	ret = i915_do_wait_request(dev, overlay->last_flip_req,
367852835f343146a82a528c3b712b373661d4fa17aZou Nan hai			1, &dev_priv->render_ring);
36803f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	if (ret != 0)
36902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return ret;
37002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
37103f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	overlay->hw_wedged = 0;
37203f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	overlay->last_flip_req = 0;
37302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return ret;
37402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
37502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
37612ca45fea91cfbb09df828bea958b47348caee6dDaniel Vetterstatic void intel_overlay_off_tail(struct intel_overlay *overlay)
37712ca45fea91cfbb09df828bea958b47348caee6dDaniel Vetter{
37812ca45fea91cfbb09df828bea958b47348caee6dDaniel Vetter	struct drm_gem_object *obj;
37912ca45fea91cfbb09df828bea958b47348caee6dDaniel Vetter
38012ca45fea91cfbb09df828bea958b47348caee6dDaniel Vetter	/* never have the overlay hw on without showing a frame */
38112ca45fea91cfbb09df828bea958b47348caee6dDaniel Vetter	BUG_ON(!overlay->vid_bo);
382a8089e849a32c5b6bfd6c88dbd09c0ea4a779b71Daniel Vetter	obj = &overlay->vid_bo->base;
38312ca45fea91cfbb09df828bea958b47348caee6dDaniel Vetter
38412ca45fea91cfbb09df828bea958b47348caee6dDaniel Vetter	i915_gem_object_unpin(obj);
38512ca45fea91cfbb09df828bea958b47348caee6dDaniel Vetter	drm_gem_object_unreference(obj);
38612ca45fea91cfbb09df828bea958b47348caee6dDaniel Vetter	overlay->vid_bo = NULL;
38712ca45fea91cfbb09df828bea958b47348caee6dDaniel Vetter
38812ca45fea91cfbb09df828bea958b47348caee6dDaniel Vetter	overlay->crtc->overlay = NULL;
38912ca45fea91cfbb09df828bea958b47348caee6dDaniel Vetter	overlay->crtc = NULL;
39012ca45fea91cfbb09df828bea958b47348caee6dDaniel Vetter	overlay->active = 0;
39112ca45fea91cfbb09df828bea958b47348caee6dDaniel Vetter}
39212ca45fea91cfbb09df828bea958b47348caee6dDaniel Vetter
39303f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter/* recover from an interruption due to a signal
39403f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter * We have to be careful not to repeat work forever an make forward progess. */
39503f77ea5972e6a2363152aec692744cac824dabaDaniel Vetterint intel_overlay_recover_from_interrupt(struct intel_overlay *overlay,
39603f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter					 int interruptible)
39703f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter{
39803f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	struct drm_device *dev = overlay->dev;
39903f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	struct drm_gem_object *obj;
400852835f343146a82a528c3b712b373661d4fa17aZou Nan hai	drm_i915_private_t *dev_priv = dev->dev_private;
40103f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	u32 flip_addr;
40203f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	int ret;
40303f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter
40403f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	if (overlay->hw_wedged == HW_WEDGED)
40503f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter		return -EIO;
40603f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter
40703f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	if (overlay->last_flip_req == 0) {
408852835f343146a82a528c3b712b373661d4fa17aZou Nan hai		overlay->last_flip_req =
409852835f343146a82a528c3b712b373661d4fa17aZou Nan hai			i915_add_request(dev, NULL, 0, &dev_priv->render_ring);
41003f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter		if (overlay->last_flip_req == 0)
41103f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter			return -ENOMEM;
41203f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	}
41303f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter
414852835f343146a82a528c3b712b373661d4fa17aZou Nan hai	ret = i915_do_wait_request(dev, overlay->last_flip_req,
415852835f343146a82a528c3b712b373661d4fa17aZou Nan hai			interruptible, &dev_priv->render_ring);
41603f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	if (ret != 0)
41703f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter		return ret;
41803f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter
41903f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	switch (overlay->hw_wedged) {
42003f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter		case RELEASE_OLD_VID:
421a8089e849a32c5b6bfd6c88dbd09c0ea4a779b71Daniel Vetter			obj = &overlay->old_vid_bo->base;
42203f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter			i915_gem_object_unpin(obj);
42303f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter			drm_gem_object_unreference(obj);
42403f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter			overlay->old_vid_bo = NULL;
42503f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter			break;
42603f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter		case SWITCH_OFF_STAGE_1:
42703f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter			flip_addr = overlay->flip_addr;
42803f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter			flip_addr |= OFC_UPDATE;
42903f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter
43003f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter			overlay->hw_wedged = SWITCH_OFF_STAGE_2;
43103f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter
4324f8a567c4666c73284832240db89fdadb2c50bd5Daniel Vetter			BEGIN_LP_RING(4);
43303f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter			OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_OFF);
43403f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter			OUT_RING(flip_addr);
43503f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter			OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
43603f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter			OUT_RING(MI_NOOP);
43703f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter			ADVANCE_LP_RING();
43803f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter
439852835f343146a82a528c3b712b373661d4fa17aZou Nan hai			overlay->last_flip_req = i915_add_request(dev, NULL,
440852835f343146a82a528c3b712b373661d4fa17aZou Nan hai					0, &dev_priv->render_ring);
44103f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter			if (overlay->last_flip_req == 0)
44203f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter				return -ENOMEM;
44303f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter
44403f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter			ret = i915_do_wait_request(dev, overlay->last_flip_req,
445852835f343146a82a528c3b712b373661d4fa17aZou Nan hai					interruptible, &dev_priv->render_ring);
44603f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter			if (ret != 0)
44703f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter				return ret;
44803f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter
44903f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter		case SWITCH_OFF_STAGE_2:
45012ca45fea91cfbb09df828bea958b47348caee6dDaniel Vetter			intel_overlay_off_tail(overlay);
45103f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter			break;
45203f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter		default:
45303f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter			BUG_ON(overlay->hw_wedged != NEEDS_WAIT_FOR_FLIP);
45403f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	}
45503f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter
45603f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	overlay->hw_wedged = 0;
45703f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	overlay->last_flip_req = 0;
45803f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	return 0;
45903f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter}
46003f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter
4615a5a0c64a99d7542c48c99d1a8bbb49e665842beDaniel Vetter/* Wait for pending overlay flip and release old frame.
4625a5a0c64a99d7542c48c99d1a8bbb49e665842beDaniel Vetter * Needs to be called before the overlay register are changed
4635a5a0c64a99d7542c48c99d1a8bbb49e665842beDaniel Vetter * via intel_overlay_(un)map_regs_atomic */
46402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic int intel_overlay_release_old_vid(struct intel_overlay *overlay)
46502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
46602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int ret;
46702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct drm_gem_object *obj;
46802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
46903f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	/* only wait if there is actually an old frame to release to
47003f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	 * guarantee forward progress */
47103f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	if (!overlay->old_vid_bo)
47203f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter		return 0;
47303f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter
47402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	ret = intel_overlay_wait_flip(overlay);
47502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (ret != 0)
47602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return ret;
47702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
478a8089e849a32c5b6bfd6c88dbd09c0ea4a779b71Daniel Vetter	obj = &overlay->old_vid_bo->base;
47902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	i915_gem_object_unpin(obj);
48002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	drm_gem_object_unreference(obj);
48102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	overlay->old_vid_bo = NULL;
48202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
48302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return 0;
48402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
48502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
48602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstruct put_image_params {
48702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int format;
48802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	short dst_x;
48902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	short dst_y;
49002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	short dst_w;
49102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	short dst_h;
49202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	short src_w;
49302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	short src_scan_h;
49402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	short src_scan_w;
49502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	short src_h;
49602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	short stride_Y;
49702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	short stride_UV;
49802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int offset_Y;
49902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int offset_U;
50002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int offset_V;
50102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter};
50202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
50302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic int packed_depth_bytes(u32 format)
50402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
50502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	switch (format & I915_OVERLAY_DEPTH_MASK) {
50602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		case I915_OVERLAY_YUV422:
50702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			return 4;
50802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		case I915_OVERLAY_YUV411:
50902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			/* return 6; not implemented */
51002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		default:
51102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			return -EINVAL;
51202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
51302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
51402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
51502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic int packed_width_bytes(u32 format, short width)
51602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
51702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	switch (format & I915_OVERLAY_DEPTH_MASK) {
51802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		case I915_OVERLAY_YUV422:
51902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			return width << 1;
52002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		default:
52102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			return -EINVAL;
52202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
52302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
52402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
52502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic int uv_hsubsampling(u32 format)
52602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
52702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	switch (format & I915_OVERLAY_DEPTH_MASK) {
52802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		case I915_OVERLAY_YUV422:
52902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		case I915_OVERLAY_YUV420:
53002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			return 2;
53102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		case I915_OVERLAY_YUV411:
53202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		case I915_OVERLAY_YUV410:
53302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			return 4;
53402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		default:
53502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			return -EINVAL;
53602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
53702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
53802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
53902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic int uv_vsubsampling(u32 format)
54002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
54102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	switch (format & I915_OVERLAY_DEPTH_MASK) {
54202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		case I915_OVERLAY_YUV420:
54302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		case I915_OVERLAY_YUV410:
54402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			return 2;
54502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		case I915_OVERLAY_YUV422:
54602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		case I915_OVERLAY_YUV411:
54702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			return 1;
54802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		default:
54902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			return -EINVAL;
55002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
55102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
55202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
55302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic u32 calc_swidthsw(struct drm_device *dev, u32 offset, u32 width)
55402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
55502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	u32 mask, shift, ret;
55602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (IS_I9XX(dev)) {
55702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		mask = 0x3f;
55802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		shift = 6;
55902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	} else {
56002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		mask = 0x1f;
56102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		shift = 5;
56202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
56302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	ret = ((offset + width + mask) >> shift) - (offset >> shift);
56402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (IS_I9XX(dev))
56502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		ret <<= 1;
56602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	ret -=1;
56702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return ret << 2;
56802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
56902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
57002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic const u16 y_static_hcoeffs[N_HORIZ_Y_TAPS * N_PHASES] = {
57102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3000, 0xb4a0, 0x1930, 0x1920, 0xb4a0,
57202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3000, 0xb500, 0x19d0, 0x1880, 0xb440,
57302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3000, 0xb540, 0x1a88, 0x2f80, 0xb3e0,
57402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3000, 0xb580, 0x1b30, 0x2e20, 0xb380,
57502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3000, 0xb5c0, 0x1bd8, 0x2cc0, 0xb320,
57602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3020, 0xb5e0, 0x1c60, 0x2b80, 0xb2c0,
57702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3020, 0xb5e0, 0x1cf8, 0x2a20, 0xb260,
57802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3020, 0xb5e0, 0x1d80, 0x28e0, 0xb200,
57902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3020, 0xb5c0, 0x1e08, 0x3f40, 0xb1c0,
58002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3020, 0xb580, 0x1e78, 0x3ce0, 0xb160,
58102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3040, 0xb520, 0x1ed8, 0x3aa0, 0xb120,
58202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3040, 0xb4a0, 0x1f30, 0x3880, 0xb0e0,
58302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3040, 0xb400, 0x1f78, 0x3680, 0xb0a0,
58402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3020, 0xb340, 0x1fb8, 0x34a0, 0xb060,
58502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3020, 0xb240, 0x1fe0, 0x32e0, 0xb040,
58602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3020, 0xb140, 0x1ff8, 0x3160, 0xb020,
58702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0xb000, 0x3000, 0x0800, 0x3000, 0xb000};
58802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic const u16 uv_static_hcoeffs[N_HORIZ_UV_TAPS * N_PHASES] = {
58902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3000, 0x1800, 0x1800, 0xb000, 0x18d0, 0x2e60,
59002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0xb000, 0x1990, 0x2ce0, 0xb020, 0x1a68, 0x2b40,
59102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0xb040, 0x1b20, 0x29e0, 0xb060, 0x1bd8, 0x2880,
59202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0xb080, 0x1c88, 0x3e60, 0xb0a0, 0x1d28, 0x3c00,
59302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0xb0c0, 0x1db8, 0x39e0, 0xb0e0, 0x1e40, 0x37e0,
59402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0xb100, 0x1eb8, 0x3620, 0xb100, 0x1f18, 0x34a0,
59502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0xb100, 0x1f68, 0x3360, 0xb0e0, 0x1fa8, 0x3240,
59602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0xb0c0, 0x1fe0, 0x3140, 0xb060, 0x1ff0, 0x30a0,
59702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3000, 0x0800, 0x3000};
59802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
59902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic void update_polyphase_filter(struct overlay_registers *regs)
60002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
60102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	memcpy(regs->Y_HCOEFS, y_static_hcoeffs, sizeof(y_static_hcoeffs));
60202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	memcpy(regs->UV_HCOEFS, uv_static_hcoeffs, sizeof(uv_static_hcoeffs));
60302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
60402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
60502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic bool update_scaling_factors(struct intel_overlay *overlay,
60602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				   struct overlay_registers *regs,
60702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				   struct put_image_params *params)
60802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
60902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* fixed point with a 12 bit shift */
61002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	u32 xscale, yscale, xscale_UV, yscale_UV;
61102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define FP_SHIFT 12
61202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define FRACT_MASK 0xfff
61302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	bool scale_changed = false;
61402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int uv_hscale = uv_hsubsampling(params->format);
61502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int uv_vscale = uv_vsubsampling(params->format);
61602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
61702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (params->dst_w > 1)
61802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		xscale = ((params->src_scan_w - 1) << FP_SHIFT)
61902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			/(params->dst_w);
62002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	else
62102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		xscale = 1 << FP_SHIFT;
62202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
62302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (params->dst_h > 1)
62402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		yscale = ((params->src_scan_h - 1) << FP_SHIFT)
62502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			/(params->dst_h);
62602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	else
62702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		yscale = 1 << FP_SHIFT;
62802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
62902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/*if (params->format & I915_OVERLAY_YUV_PLANAR) {*/
63002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		xscale_UV = xscale/uv_hscale;
63102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		yscale_UV = yscale/uv_vscale;
63202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		/* make the Y scale to UV scale ratio an exact multiply */
63302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		xscale = xscale_UV * uv_hscale;
63402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		yscale = yscale_UV * uv_vscale;
63502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/*} else {
63602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		xscale_UV = 0;
63702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		yscale_UV = 0;
63802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}*/
63902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
64002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (xscale != overlay->old_xscale || yscale != overlay->old_yscale)
64102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		scale_changed = true;
64202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	overlay->old_xscale = xscale;
64302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	overlay->old_yscale = yscale;
64402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
64502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	regs->YRGBSCALE = ((yscale & FRACT_MASK) << 20)
64602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		| ((xscale >> FP_SHIFT) << 16)
64702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		| ((xscale & FRACT_MASK) << 3);
64802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	regs->UVSCALE = ((yscale_UV & FRACT_MASK) << 20)
64902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		| ((xscale_UV >> FP_SHIFT) << 16)
65002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		| ((xscale_UV & FRACT_MASK) << 3);
65102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	regs->UVSCALEV = ((yscale >> FP_SHIFT) << 16)
65202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		| ((yscale_UV >> FP_SHIFT) << 0);
65302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
65402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (scale_changed)
65502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		update_polyphase_filter(regs);
65602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
65702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return scale_changed;
65802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
65902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
66002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic void update_colorkey(struct intel_overlay *overlay,
66102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			    struct overlay_registers *regs)
66202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
66302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	u32 key = overlay->color_key;
66402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	switch (overlay->crtc->base.fb->bits_per_pixel) {
66502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		case 8:
66602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			regs->DCLRKV = 0;
66702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			regs->DCLRKM = CLK_RGB8I_MASK | DST_KEY_ENABLE;
66802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		case 16:
66902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			if (overlay->crtc->base.fb->depth == 15) {
67002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				regs->DCLRKV = RGB15_TO_COLORKEY(key);
67102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				regs->DCLRKM = CLK_RGB15_MASK | DST_KEY_ENABLE;
67202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			} else {
67302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				regs->DCLRKV = RGB16_TO_COLORKEY(key);
67402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				regs->DCLRKM = CLK_RGB16_MASK | DST_KEY_ENABLE;
67502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			}
67602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		case 24:
67702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		case 32:
67802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			regs->DCLRKV = key;
67902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			regs->DCLRKM = CLK_RGB24_MASK | DST_KEY_ENABLE;
68002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
68102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
68202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
68302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic u32 overlay_cmd_reg(struct put_image_params *params)
68402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
68502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	u32 cmd = OCMD_ENABLE | OCMD_BUF_TYPE_FRAME | OCMD_BUFFER0;
68602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
68702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (params->format & I915_OVERLAY_YUV_PLANAR) {
68802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		switch (params->format & I915_OVERLAY_DEPTH_MASK) {
68902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			case I915_OVERLAY_YUV422:
69002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				cmd |= OCMD_YUV_422_PLANAR;
69102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				break;
69202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			case I915_OVERLAY_YUV420:
69302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				cmd |= OCMD_YUV_420_PLANAR;
69402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				break;
69502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			case I915_OVERLAY_YUV411:
69602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			case I915_OVERLAY_YUV410:
69702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				cmd |= OCMD_YUV_410_PLANAR;
69802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				break;
69902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		}
70002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	} else { /* YUV packed */
70102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		switch (params->format & I915_OVERLAY_DEPTH_MASK) {
70202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			case I915_OVERLAY_YUV422:
70302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				cmd |= OCMD_YUV_422_PACKED;
70402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				break;
70502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			case I915_OVERLAY_YUV411:
70602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				cmd |= OCMD_YUV_411_PACKED;
70702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				break;
70802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		}
70902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
71002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		switch (params->format & I915_OVERLAY_SWAP_MASK) {
71102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			case I915_OVERLAY_NO_SWAP:
71202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				break;
71302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			case I915_OVERLAY_UV_SWAP:
71402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				cmd |= OCMD_UV_SWAP;
71502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				break;
71602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			case I915_OVERLAY_Y_SWAP:
71702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				cmd |= OCMD_Y_SWAP;
71802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				break;
71902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			case I915_OVERLAY_Y_AND_UV_SWAP:
72002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				cmd |= OCMD_Y_AND_UV_SWAP;
72102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				break;
72202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		}
72302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
72402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
72502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return cmd;
72602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
72702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
72802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterint intel_overlay_do_put_image(struct intel_overlay *overlay,
72902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			       struct drm_gem_object *new_bo,
73002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			       struct put_image_params *params)
73102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
73202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int ret, tmp_width;
73302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct overlay_registers *regs;
73402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	bool scale_changed = false;
73523010e43b353c2cdc9725cbedc7e364708039bf7Daniel Vetter	struct drm_i915_gem_object *bo_priv = to_intel_bo(new_bo);
73602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct drm_device *dev = overlay->dev;
73702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
73802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	BUG_ON(!mutex_is_locked(&dev->struct_mutex));
73902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	BUG_ON(!mutex_is_locked(&dev->mode_config.mutex));
74002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	BUG_ON(!overlay);
74102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
74202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	ret = intel_overlay_release_old_vid(overlay);
74302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (ret != 0)
74402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return ret;
74502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
74602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	ret = i915_gem_object_pin(new_bo, PAGE_SIZE);
74702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (ret != 0)
74802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return ret;
74902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
75002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	ret = i915_gem_object_set_to_gtt_domain(new_bo, 0);
75102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (ret != 0)
75202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		goto out_unpin;
75302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
75402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!overlay->active) {
75502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		regs = intel_overlay_map_regs_atomic(overlay);
75602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		if (!regs) {
75702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			ret = -ENOMEM;
75802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			goto out_unpin;
75902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		}
76002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		regs->OCONFIG = OCONF_CC_OUT_8BIT;
76102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		if (IS_I965GM(overlay->dev))
76202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			regs->OCONFIG |= OCONF_CSC_MODE_BT709;
76302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		regs->OCONFIG |= overlay->crtc->pipe == 0 ?
76402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			OCONF_PIPE_A : OCONF_PIPE_B;
76502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		intel_overlay_unmap_regs_atomic(overlay);
76602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
76702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		ret = intel_overlay_on(overlay);
76802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		if (ret != 0)
76902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			goto out_unpin;
77002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
77102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
77202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	regs = intel_overlay_map_regs_atomic(overlay);
77302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!regs) {
77402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		ret = -ENOMEM;
77502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		goto out_unpin;
77602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
77702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
77802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	regs->DWINPOS = (params->dst_y << 16) | params->dst_x;
77902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	regs->DWINSZ = (params->dst_h << 16) | params->dst_w;
78002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
78102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (params->format & I915_OVERLAY_YUV_PACKED)
78202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		tmp_width = packed_width_bytes(params->format, params->src_w);
78302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	else
78402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		tmp_width = params->src_w;
78502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
78602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	regs->SWIDTH = params->src_w;
78702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	regs->SWIDTHSW = calc_swidthsw(overlay->dev,
78802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			params->offset_Y, tmp_width);
78902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	regs->SHEIGHT = params->src_h;
79002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	regs->OBUF_0Y = bo_priv->gtt_offset + params-> offset_Y;
79102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	regs->OSTRIDE = params->stride_Y;
79202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
79302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (params->format & I915_OVERLAY_YUV_PLANAR) {
79402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		int uv_hscale = uv_hsubsampling(params->format);
79502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		int uv_vscale = uv_vsubsampling(params->format);
79602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		u32 tmp_U, tmp_V;
79702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		regs->SWIDTH |= (params->src_w/uv_hscale) << 16;
79802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		tmp_U = calc_swidthsw(overlay->dev, params->offset_U,
79902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				params->src_w/uv_hscale);
80002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		tmp_V = calc_swidthsw(overlay->dev, params->offset_V,
80102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				params->src_w/uv_hscale);
80202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		regs->SWIDTHSW |= max_t(u32, tmp_U, tmp_V) << 16;
80302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		regs->SHEIGHT |= (params->src_h/uv_vscale) << 16;
80402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		regs->OBUF_0U = bo_priv->gtt_offset + params->offset_U;
80502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		regs->OBUF_0V = bo_priv->gtt_offset + params->offset_V;
80602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		regs->OSTRIDE |= params->stride_UV << 16;
80702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
80802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
80902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	scale_changed = update_scaling_factors(overlay, regs, params);
81002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
81102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	update_colorkey(overlay, regs);
81202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
81302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	regs->OCMD = overlay_cmd_reg(params);
81402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
81502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	intel_overlay_unmap_regs_atomic(overlay);
81602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
81702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	intel_overlay_continue(overlay, scale_changed);
81802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
81902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	overlay->old_vid_bo = overlay->vid_bo;
82023010e43b353c2cdc9725cbedc7e364708039bf7Daniel Vetter	overlay->vid_bo = to_intel_bo(new_bo);
82102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
82202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return 0;
82302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
82402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterout_unpin:
82502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	i915_gem_object_unpin(new_bo);
82602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return ret;
82702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
82802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
82902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterint intel_overlay_switch_off(struct intel_overlay *overlay)
83002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
83102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int ret;
83202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct overlay_registers *regs;
83302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct drm_device *dev = overlay->dev;
83402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
83502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	BUG_ON(!mutex_is_locked(&dev->struct_mutex));
83602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	BUG_ON(!mutex_is_locked(&dev->mode_config.mutex));
83702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
8389bedb9743fd906e4160468663ee6e1bbdc4412b8Daniel Vetter	if (overlay->hw_wedged) {
8399bedb9743fd906e4160468663ee6e1bbdc4412b8Daniel Vetter		ret = intel_overlay_recover_from_interrupt(overlay, 1);
8409bedb9743fd906e4160468663ee6e1bbdc4412b8Daniel Vetter		if (ret != 0)
8419bedb9743fd906e4160468663ee6e1bbdc4412b8Daniel Vetter			return ret;
8429bedb9743fd906e4160468663ee6e1bbdc4412b8Daniel Vetter	}
8439bedb9743fd906e4160468663ee6e1bbdc4412b8Daniel Vetter
84402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!overlay->active)
84502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return 0;
84602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
84702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	ret = intel_overlay_release_old_vid(overlay);
84802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (ret != 0)
84902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return ret;
85002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
85102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	regs = intel_overlay_map_regs_atomic(overlay);
85202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	regs->OCMD = 0;
85302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	intel_overlay_unmap_regs_atomic(overlay);
85402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
85502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	ret = intel_overlay_off(overlay);
85603f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	if (ret != 0)
85703f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter		return ret;
85803f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter
85912ca45fea91cfbb09df828bea958b47348caee6dDaniel Vetter	intel_overlay_off_tail(overlay);
86002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
86102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return 0;
86202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
86302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
86402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic int check_overlay_possible_on_crtc(struct intel_overlay *overlay,
86502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter					  struct intel_crtc *crtc)
86602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
86702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter        drm_i915_private_t *dev_priv = overlay->dev->dev_private;
86802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	u32 pipeconf;
86902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int pipeconf_reg = (crtc->pipe == 0) ? PIPEACONF : PIPEBCONF;
87002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
87102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!crtc->base.enabled || crtc->dpms_mode != DRM_MODE_DPMS_ON)
87202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EINVAL;
87302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
87402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	pipeconf = I915_READ(pipeconf_reg);
87502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
87602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* can't use the overlay with double wide pipe */
87702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!IS_I965G(overlay->dev) && pipeconf & PIPEACONF_DOUBLE_WIDE)
87802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EINVAL;
87902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
88002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return 0;
88102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
88202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
88302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic void update_pfit_vscale_ratio(struct intel_overlay *overlay)
88402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
88502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct drm_device *dev = overlay->dev;
88602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter        drm_i915_private_t *dev_priv = dev->dev_private;
88702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	u32 ratio;
88802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	u32 pfit_control = I915_READ(PFIT_CONTROL);
88902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
89002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* XXX: This is not the same logic as in the xorg driver, but more in
89102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	 * line with the intel documentation for the i965 */
89202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!IS_I965G(dev) && (pfit_control & VERT_AUTO_SCALE)) {
89302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		ratio = I915_READ(PFIT_AUTO_RATIOS) >> PFIT_VERT_SCALE_SHIFT;
89402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	} else { /* on i965 use the PGM reg to read out the autoscaler values */
89502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		ratio = I915_READ(PFIT_PGM_RATIOS);
89602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		if (IS_I965G(dev))
89702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			ratio >>= PFIT_VERT_SCALE_SHIFT_965;
89802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		else
89902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			ratio >>= PFIT_VERT_SCALE_SHIFT;
90002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
90102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
90202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	overlay->pfit_vscale_ratio = ratio;
90302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
90402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
90502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic int check_overlay_dst(struct intel_overlay *overlay,
90602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			     struct drm_intel_overlay_put_image *rec)
90702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
90802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct drm_display_mode *mode = &overlay->crtc->base.mode;
90902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
91002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if ((rec->dst_x < mode->crtc_hdisplay)
91102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	    && (rec->dst_x + rec->dst_width
91202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		    <= mode->crtc_hdisplay)
91302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	    && (rec->dst_y < mode->crtc_vdisplay)
91402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	    && (rec->dst_y + rec->dst_height
91502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		    <= mode->crtc_vdisplay))
91602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return 0;
91702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	else
91802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EINVAL;
91902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
92002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
92102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic int check_overlay_scaling(struct put_image_params *rec)
92202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
92302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	u32 tmp;
92402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
92502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* downscaling limit is 8.0 */
92602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	tmp = ((rec->src_scan_h << 16) / rec->dst_h) >> 16;
92702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (tmp > 7)
92802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EINVAL;
92902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	tmp = ((rec->src_scan_w << 16) / rec->dst_w) >> 16;
93002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (tmp > 7)
93102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EINVAL;
93202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
93302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return 0;
93402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
93502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
93602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic int check_overlay_src(struct drm_device *dev,
93702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			     struct drm_intel_overlay_put_image *rec,
93802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			     struct drm_gem_object *new_bo)
93902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
94002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	u32 stride_mask;
94102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int depth;
94202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int uv_hscale = uv_hsubsampling(rec->flags);
94302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int uv_vscale = uv_vsubsampling(rec->flags);
94402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	size_t tmp;
94502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
94602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* check src dimensions */
94702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (IS_845G(dev) || IS_I830(dev)) {
94802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		if (rec->src_height > IMAGE_MAX_HEIGHT_LEGACY
94902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		    || rec->src_width > IMAGE_MAX_WIDTH_LEGACY)
95002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			return -EINVAL;
95102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	} else {
95202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		if (rec->src_height > IMAGE_MAX_HEIGHT
95302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		    || rec->src_width > IMAGE_MAX_WIDTH)
95402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			return -EINVAL;
95502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
95602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* better safe than sorry, use 4 as the maximal subsampling ratio */
95702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (rec->src_height < N_VERT_Y_TAPS*4
95802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	    || rec->src_width < N_HORIZ_Y_TAPS*4)
95902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EINVAL;
96002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
961a1efd14a99483a4fb9308902397ed86b69454c99Chris Wilson	/* check alignment constraints */
96202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	switch (rec->flags & I915_OVERLAY_TYPE_MASK) {
96302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		case I915_OVERLAY_RGB:
96402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			/* not implemented */
96502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			return -EINVAL;
96602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		case I915_OVERLAY_YUV_PACKED:
96702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			depth = packed_depth_bytes(rec->flags);
96802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			if (uv_vscale != 1)
96902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				return -EINVAL;
97002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			if (depth < 0)
97102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				return depth;
97202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			/* ignore UV planes */
97302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			rec->stride_UV = 0;
97402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			rec->offset_U = 0;
97502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			rec->offset_V = 0;
97602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			/* check pixel alignment */
97702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			if (rec->offset_Y % depth)
97802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				return -EINVAL;
97902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			break;
98002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		case I915_OVERLAY_YUV_PLANAR:
98102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			if (uv_vscale < 0 || uv_hscale < 0)
98202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				return -EINVAL;
98302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			/* no offset restrictions for planar formats */
98402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			break;
98502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		default:
98602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			return -EINVAL;
98702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
98802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
98902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (rec->src_width % uv_hscale)
99002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EINVAL;
99102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
99202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* stride checking */
993a1efd14a99483a4fb9308902397ed86b69454c99Chris Wilson	if (IS_I830(dev) || IS_845G(dev))
994a1efd14a99483a4fb9308902397ed86b69454c99Chris Wilson		stride_mask = 255;
995a1efd14a99483a4fb9308902397ed86b69454c99Chris Wilson	else
996a1efd14a99483a4fb9308902397ed86b69454c99Chris Wilson		stride_mask = 63;
99702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
99802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (rec->stride_Y & stride_mask || rec->stride_UV & stride_mask)
99902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EINVAL;
100002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (IS_I965G(dev) && rec->stride_Y < 512)
100102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EINVAL;
100202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
100302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	tmp = (rec->flags & I915_OVERLAY_TYPE_MASK) == I915_OVERLAY_YUV_PLANAR ?
100402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		4 : 8;
100502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (rec->stride_Y > tmp*1024 || rec->stride_UV > 2*1024)
100602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EINVAL;
100702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
100802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* check buffer dimensions */
100902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	switch (rec->flags & I915_OVERLAY_TYPE_MASK) {
101002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		case I915_OVERLAY_RGB:
101102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		case I915_OVERLAY_YUV_PACKED:
101202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			/* always 4 Y values per depth pixels */
101302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			if (packed_width_bytes(rec->flags, rec->src_width)
101402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter					> rec->stride_Y)
101502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				return -EINVAL;
101602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
101702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			tmp = rec->stride_Y*rec->src_height;
101802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			if (rec->offset_Y + tmp > new_bo->size)
101902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				return -EINVAL;
102002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			break;
102102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		case I915_OVERLAY_YUV_PLANAR:
102202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			if (rec->src_width > rec->stride_Y)
102302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				return -EINVAL;
102402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			if (rec->src_width/uv_hscale > rec->stride_UV)
102502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				return -EINVAL;
102602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
102702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			tmp = rec->stride_Y*rec->src_height;
102802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			if (rec->offset_Y + tmp > new_bo->size)
102902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				return -EINVAL;
103002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			tmp = rec->stride_UV*rec->src_height;
103102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			tmp /= uv_vscale;
103202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			if (rec->offset_U + tmp > new_bo->size
103302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			    || rec->offset_V + tmp > new_bo->size)
103402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				return -EINVAL;
103502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			break;
103602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
103702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
103802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return 0;
103902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
104002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
104102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterint intel_overlay_put_image(struct drm_device *dev, void *data,
104202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter                            struct drm_file *file_priv)
104302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
104402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct drm_intel_overlay_put_image *put_image_rec = data;
104502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	drm_i915_private_t *dev_priv = dev->dev_private;
104602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct intel_overlay *overlay;
104702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct drm_mode_object *drmmode_obj;
104802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct intel_crtc *crtc;
104902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct drm_gem_object *new_bo;
105002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct put_image_params *params;
105102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int ret;
105202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
105302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!dev_priv) {
105402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		DRM_ERROR("called with no initialization\n");
105502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EINVAL;
105602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
105702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
105802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	overlay = dev_priv->overlay;
105902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!overlay) {
106002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		DRM_DEBUG("userspace bug: no overlay\n");
106102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -ENODEV;
106202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
106302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
106402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!(put_image_rec->flags & I915_OVERLAY_ENABLE)) {
106502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		mutex_lock(&dev->mode_config.mutex);
106602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		mutex_lock(&dev->struct_mutex);
106702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
106802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		ret = intel_overlay_switch_off(overlay);
106902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
107002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		mutex_unlock(&dev->struct_mutex);
107102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		mutex_unlock(&dev->mode_config.mutex);
107202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
107302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return ret;
107402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
107502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
107602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	params = kmalloc(sizeof(struct put_image_params), GFP_KERNEL);
107702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!params)
107802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -ENOMEM;
107902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
108002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	drmmode_obj = drm_mode_object_find(dev, put_image_rec->crtc_id,
108102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter                        DRM_MODE_OBJECT_CRTC);
1082915a428e43acfd05e4ffeaf40549b0cf163eebe2Dan Carpenter	if (!drmmode_obj) {
1083915a428e43acfd05e4ffeaf40549b0cf163eebe2Dan Carpenter		ret = -ENOENT;
1084915a428e43acfd05e4ffeaf40549b0cf163eebe2Dan Carpenter		goto out_free;
1085915a428e43acfd05e4ffeaf40549b0cf163eebe2Dan Carpenter	}
108602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	crtc = to_intel_crtc(obj_to_crtc(drmmode_obj));
108702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
108802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	new_bo = drm_gem_object_lookup(dev, file_priv,
108902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			put_image_rec->bo_handle);
1090915a428e43acfd05e4ffeaf40549b0cf163eebe2Dan Carpenter	if (!new_bo) {
1091915a428e43acfd05e4ffeaf40549b0cf163eebe2Dan Carpenter		ret = -ENOENT;
1092915a428e43acfd05e4ffeaf40549b0cf163eebe2Dan Carpenter		goto out_free;
1093915a428e43acfd05e4ffeaf40549b0cf163eebe2Dan Carpenter	}
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);
1182bc9025bdc4e2b591734cca17697093845007b63dLuca Barbieri	drm_gem_object_unreference_unlocked(new_bo);
1183915a428e43acfd05e4ffeaf40549b0cf163eebe2Dan Carpenterout_free:
118402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	kfree(params);
118502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
118602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return ret;
118702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
118802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
118902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic void update_reg_attrs(struct intel_overlay *overlay,
119002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			     struct overlay_registers *regs)
119102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
119202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	regs->OCLRC0 = (overlay->contrast << 18) | (overlay->brightness & 0xff);
119302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	regs->OCLRC1 = overlay->saturation;
119402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
119502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
119602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic bool check_gamma_bounds(u32 gamma1, u32 gamma2)
119702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
119802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int i;
119902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
120002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (gamma1 & 0xff000000 || gamma2 & 0xff000000)
120102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return false;
120202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
120302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	for (i = 0; i < 3; i++) {
120402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		if (((gamma1 >> i * 8) & 0xff) >= ((gamma2 >> i*8) & 0xff))
120502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			return false;
120602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
120702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
120802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return true;
120902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
121002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
121102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic bool check_gamma5_errata(u32 gamma5)
121202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
121302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int i;
121402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
121502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	for (i = 0; i < 3; i++) {
121602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		if (((gamma5 >> i*8) & 0xff) == 0x80)
121702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			return false;
121802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
121902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
122002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return true;
122102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
122202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
122302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic int check_gamma(struct drm_intel_overlay_attrs *attrs)
122402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
122502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!check_gamma_bounds(0, attrs->gamma0)
122602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	    || !check_gamma_bounds(attrs->gamma0, attrs->gamma1)
122702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	    || !check_gamma_bounds(attrs->gamma1, attrs->gamma2)
122802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	    || !check_gamma_bounds(attrs->gamma2, attrs->gamma3)
122902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	    || !check_gamma_bounds(attrs->gamma3, attrs->gamma4)
123002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	    || !check_gamma_bounds(attrs->gamma4, attrs->gamma5)
123102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	    || !check_gamma_bounds(attrs->gamma5, 0x00ffffff))
123202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EINVAL;
123302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!check_gamma5_errata(attrs->gamma5))
123402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EINVAL;
123502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return 0;
123602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
123702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
123802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterint intel_overlay_attrs(struct drm_device *dev, void *data,
123902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter                        struct drm_file *file_priv)
124002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
124102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct drm_intel_overlay_attrs *attrs = data;
124202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter        drm_i915_private_t *dev_priv = dev->dev_private;
124302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct intel_overlay *overlay;
124402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct overlay_registers *regs;
124502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int ret;
124602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
124702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!dev_priv) {
124802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		DRM_ERROR("called with no initialization\n");
124902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EINVAL;
125002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
125102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
125202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	overlay = dev_priv->overlay;
125302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!overlay) {
125402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		DRM_DEBUG("userspace bug: no overlay\n");
125502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -ENODEV;
125602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
125702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
125802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	mutex_lock(&dev->mode_config.mutex);
125902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	mutex_lock(&dev->struct_mutex);
126002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
126102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!(attrs->flags & I915_OVERLAY_UPDATE_ATTRS)) {
126202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		attrs->color_key = overlay->color_key;
126302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		attrs->brightness = overlay->brightness;
126402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		attrs->contrast = overlay->contrast;
126502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		attrs->saturation = overlay->saturation;
126602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
126702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		if (IS_I9XX(dev)) {
126802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			attrs->gamma0 = I915_READ(OGAMC0);
126902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			attrs->gamma1 = I915_READ(OGAMC1);
127002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			attrs->gamma2 = I915_READ(OGAMC2);
127102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			attrs->gamma3 = I915_READ(OGAMC3);
127202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			attrs->gamma4 = I915_READ(OGAMC4);
127302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			attrs->gamma5 = I915_READ(OGAMC5);
127402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		}
127502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		ret = 0;
127602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	} else {
127702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		overlay->color_key = attrs->color_key;
127802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		if (attrs->brightness >= -128 && attrs->brightness <= 127) {
127902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			overlay->brightness = attrs->brightness;
128002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		} else {
128102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			ret = -EINVAL;
128202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			goto out_unlock;
128302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		}
128402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		if (attrs->contrast <= 255) {
128502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			overlay->contrast = attrs->contrast;
128602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		} else {
128702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			ret = -EINVAL;
128802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			goto out_unlock;
128902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		}
129002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		if (attrs->saturation <= 1023) {
129102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			overlay->saturation = attrs->saturation;
129202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		} else {
129302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			ret = -EINVAL;
129402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			goto out_unlock;
129502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		}
129602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
129702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		regs = intel_overlay_map_regs_atomic(overlay);
129802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		if (!regs) {
129902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			ret = -ENOMEM;
130002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			goto out_unlock;
130102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		}
130202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
130302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		update_reg_attrs(overlay, regs);
130402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
130502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		intel_overlay_unmap_regs_atomic(overlay);
130602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
130702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		if (attrs->flags & I915_OVERLAY_UPDATE_GAMMA) {
130802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			if (!IS_I9XX(dev)) {
130902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				ret = -EINVAL;
131002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				goto out_unlock;
131102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			}
131202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
131302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			if (overlay->active) {
131402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				ret = -EBUSY;
131502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				goto out_unlock;
131602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			}
131702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
131802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			ret = check_gamma(attrs);
131902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			if (ret != 0)
132002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				goto out_unlock;
132102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
132202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			I915_WRITE(OGAMC0, attrs->gamma0);
132302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			I915_WRITE(OGAMC1, attrs->gamma1);
132402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			I915_WRITE(OGAMC2, attrs->gamma2);
132502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			I915_WRITE(OGAMC3, attrs->gamma3);
132602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			I915_WRITE(OGAMC4, attrs->gamma4);
132702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			I915_WRITE(OGAMC5, attrs->gamma5);
132802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		}
132902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		ret = 0;
133002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
133102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
133202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterout_unlock:
133302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	mutex_unlock(&dev->struct_mutex);
133402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	mutex_unlock(&dev->mode_config.mutex);
133502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
133602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return ret;
133702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
133802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
133902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vettervoid intel_setup_overlay(struct drm_device *dev)
134002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
134102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter        drm_i915_private_t *dev_priv = dev->dev_private;
134202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct intel_overlay *overlay;
134302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct drm_gem_object *reg_bo;
134402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct overlay_registers *regs;
134502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int ret;
134602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
134702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!OVERLAY_EXISTS(dev))
134802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return;
134902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
135002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	overlay = kzalloc(sizeof(struct intel_overlay), GFP_KERNEL);
135102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!overlay)
135202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return;
135302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	overlay->dev = dev;
135402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
1355ac52bc56de25535a907ef07f8755f1387b89b0f5Daniel Vetter	reg_bo = i915_gem_alloc_object(dev, PAGE_SIZE);
135602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!reg_bo)
135702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		goto out_free;
135823010e43b353c2cdc9725cbedc7e364708039bf7Daniel Vetter	overlay->reg_bo = to_intel_bo(reg_bo);
135902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
136002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (OVERLAY_NONPHYSICAL(dev)) {
136102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		ret = i915_gem_object_pin(reg_bo, PAGE_SIZE);
136202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		if (ret) {
136302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter                        DRM_ERROR("failed to pin overlay register bo\n");
136402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter                        goto out_free_bo;
136502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter                }
136602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		overlay->flip_addr = overlay->reg_bo->gtt_offset;
136702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	} else {
136802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		ret = i915_gem_attach_phys_object(dev, reg_bo,
136902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				I915_GEM_PHYS_OVERLAY_REGS);
137002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter                if (ret) {
137102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter                        DRM_ERROR("failed to attach phys overlay regs\n");
137202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter                        goto out_free_bo;
137302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter                }
137402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		overlay->flip_addr = overlay->reg_bo->phys_obj->handle->busaddr;
137502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
137602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
137702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* init all values */
137802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	overlay->color_key = 0x0101fe;
137902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	overlay->brightness = -19;
138002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	overlay->contrast = 75;
138102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	overlay->saturation = 146;
138202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
138302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	regs = intel_overlay_map_regs_atomic(overlay);
138402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!regs)
138502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		goto out_free_bo;
138602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
138702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	memset(regs, 0, sizeof(struct overlay_registers));
138802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	update_polyphase_filter(regs);
138902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
139002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	update_reg_attrs(overlay, regs);
139102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
139202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	intel_overlay_unmap_regs_atomic(overlay);
139302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
139402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	dev_priv->overlay = overlay;
139502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	DRM_INFO("initialized overlay support\n");
139602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return;
139702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
139802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterout_free_bo:
139902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	drm_gem_object_unreference(reg_bo);
140002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterout_free:
140102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	kfree(overlay);
140202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return;
140302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
140402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
140502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vettervoid intel_cleanup_overlay(struct drm_device *dev)
140602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
140702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter        drm_i915_private_t *dev_priv = dev->dev_private;
140802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
140902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (dev_priv->overlay) {
141002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		/* The bo's should be free'd by the generic code already.
141102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		 * Furthermore modesetting teardown happens beforehand so the
141202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		 * hardware should be off already */
141302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		BUG_ON(dev_priv->overlay->active);
141402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
141502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		kfree(dev_priv->overlay);
141602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
141702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
1418