intel_overlay.c revision 02e792fbaadb75dec8e476a05b610e49908fc6a4
102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter/*
202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter * Copyright © 2009
302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter *
402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter * Permission is hereby granted, free of charge, to any person obtaining a
502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter * copy of this software and associated documentation files (the "Software"),
602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter * to deal in the Software without restriction, including without limitation
702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter * the rights to use, copy, modify, merge, publish, distribute, sublicense,
802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter * and/or sell copies of the Software, and to permit persons to whom the
902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter * Software is furnished to do so, subject to the following conditions:
1002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter *
1102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter * The above copyright notice and this permission notice (including the next
1202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter * paragraph) shall be included in all copies or substantial portions of the
1302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter * Software.
1402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter *
1502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
1802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
2002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
2102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter * SOFTWARE.
2202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter *
2302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter * Authors:
2402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter *    Daniel Vetter <daniel@ffwll.ch>
2502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter *
2602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter * Derived from Xorg ddx, xf86-video-intel, src/i830_video.c
2702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter */
2802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#include "drmP.h"
2902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#include "drm.h"
3002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#include "i915_drm.h"
3102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#include "i915_drv.h"
3202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#include "i915_reg.h"
3302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#include "intel_drv.h"
3402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
3502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter/* Limits for overlay size. According to intel doc, the real limits are:
3602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter * Y width: 4095, UV width (planar): 2047, Y height: 2047,
3702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter * UV width (planar): * 1023. But the xorg thinks 2048 for height and width. Use
3802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter * the mininum of both.  */
3902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define IMAGE_MAX_WIDTH		2048
4002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define IMAGE_MAX_HEIGHT	2046 /* 2 * 1023 */
4102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter/* on 830 and 845 these large limits result in the card hanging */
4202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define IMAGE_MAX_WIDTH_LEGACY	1024
4302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define IMAGE_MAX_HEIGHT_LEGACY	1088
4402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
4502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter/* overlay register definitions */
4602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter/* OCMD register */
4702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_TILED_SURFACE	(0x1<<19)
4802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_MIRROR_MASK	(0x3<<17)
4902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_MIRROR_MODE	(0x3<<17)
5002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_MIRROR_HORIZONTAL	(0x1<<17)
5102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_MIRROR_VERTICAL	(0x2<<17)
5202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_MIRROR_BOTH	(0x3<<17)
5302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_BYTEORDER_MASK	(0x3<<14) /* zero for YUYV or FOURCC YUY2 */
5402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_UV_SWAP		(0x1<<14) /* YVYU */
5502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_Y_SWAP		(0x2<<14) /* UYVY or FOURCC UYVY */
5602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_Y_AND_UV_SWAP	(0x3<<14) /* VYUY */
5702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_SOURCE_FORMAT_MASK (0xf<<10)
5802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_RGB_888		(0x1<<10) /* not in i965 Intel docs */
5902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_RGB_555		(0x2<<10) /* not in i965 Intel docs */
6002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_RGB_565		(0x3<<10) /* not in i965 Intel docs */
6102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_YUV_422_PACKED	(0x8<<10)
6202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_YUV_411_PACKED	(0x9<<10) /* not in i965 Intel docs */
6302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_YUV_420_PLANAR	(0xc<<10)
6402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_YUV_422_PLANAR	(0xd<<10)
6502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_YUV_410_PLANAR	(0xe<<10) /* also 411 */
6602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_TVSYNCFLIP_PARITY	(0x1<<9)
6702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_TVSYNCFLIP_ENABLE	(0x1<<7)
6802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_BUF_TYPE_MASK	(Ox1<<5)
6902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_BUF_TYPE_FRAME	(0x0<<5)
7002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_BUF_TYPE_FIELD	(0x1<<5)
7102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_TEST_MODE		(0x1<<4)
7202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_BUFFER_SELECT	(0x3<<2)
7302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_BUFFER0		(0x0<<2)
7402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_BUFFER1		(0x1<<2)
7502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_FIELD_SELECT	(0x1<<2)
7602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_FIELD0		(0x0<<1)
7702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_FIELD1		(0x1<<1)
7802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_ENABLE		(0x1<<0)
7902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
8002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter/* OCONFIG register */
8102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCONF_PIPE_MASK		(0x1<<18)
8202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCONF_PIPE_A		(0x0<<18)
8302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCONF_PIPE_B		(0x1<<18)
8402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCONF_GAMMA2_ENABLE	(0x1<<16)
8502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCONF_CSC_MODE_BT601	(0x0<<5)
8602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCONF_CSC_MODE_BT709	(0x1<<5)
8702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCONF_CSC_BYPASS	(0x1<<4)
8802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCONF_CC_OUT_8BIT	(0x1<<3)
8902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCONF_TEST_MODE		(0x1<<2)
9002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCONF_THREE_LINE_BUFFER	(0x1<<0)
9102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCONF_TWO_LINE_BUFFER	(0x0<<0)
9202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
9302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter/* DCLRKM (dst-key) register */
9402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define DST_KEY_ENABLE		(0x1<<31)
9502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define CLK_RGB24_MASK		0x0
9602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define CLK_RGB16_MASK		0x070307
9702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define CLK_RGB15_MASK		0x070707
9802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define CLK_RGB8I_MASK		0xffffff
9902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
10002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define RGB16_TO_COLORKEY(c) \
10102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	(((c & 0xF800) << 8) | ((c & 0x07E0) << 5) | ((c & 0x001F) << 3))
10202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define RGB15_TO_COLORKEY(c) \
10302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	(((c & 0x7c00) << 9) | ((c & 0x03E0) << 6) | ((c & 0x001F) << 3))
10402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
10502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter/* overlay flip addr flag */
10602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OFC_UPDATE		0x1
10702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
10802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter/* polyphase filter coefficients */
10902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define N_HORIZ_Y_TAPS          5
11002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define N_VERT_Y_TAPS           3
11102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define N_HORIZ_UV_TAPS         3
11202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define N_VERT_UV_TAPS          3
11302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define N_PHASES                17
11402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define MAX_TAPS                5
11502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
11602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter/* memory bufferd overlay registers */
11702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstruct overlay_registers {
11802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u32 OBUF_0Y;
11902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u32 OBUF_1Y;
12002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u32 OBUF_0U;
12102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u32 OBUF_0V;
12202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u32 OBUF_1U;
12302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u32 OBUF_1V;
12402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u32 OSTRIDE;
12502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u32 YRGB_VPH;
12602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u32 UV_VPH;
12702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u32 HORZ_PH;
12802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u32 INIT_PHS;
12902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u32 DWINPOS;
13002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u32 DWINSZ;
13102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u32 SWIDTH;
13202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u32 SWIDTHSW;
13302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u32 SHEIGHT;
13402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u32 YRGBSCALE;
13502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u32 UVSCALE;
13602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u32 OCLRC0;
13702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u32 OCLRC1;
13802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u32 DCLRKV;
13902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u32 DCLRKM;
14002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u32 SCLRKVH;
14102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u32 SCLRKVL;
14202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u32 SCLRKEN;
14302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u32 OCONFIG;
14402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u32 OCMD;
14502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u32 RESERVED1; /* 0x6C */
14602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u32 OSTART_0Y;
14702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u32 OSTART_1Y;
14802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u32 OSTART_0U;
14902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u32 OSTART_0V;
15002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u32 OSTART_1U;
15102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u32 OSTART_1V;
15202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u32 OTILEOFF_0Y;
15302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u32 OTILEOFF_1Y;
15402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u32 OTILEOFF_0U;
15502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u32 OTILEOFF_0V;
15602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u32 OTILEOFF_1U;
15702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u32 OTILEOFF_1V;
15802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u32 FASTHSCALE; /* 0xA0 */
15902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u32 UVSCALEV; /* 0xA4 */
16002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u32 RESERVEDC[(0x200 - 0xA8) / 4]; /* 0xA8 - 0x1FC */
16102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u16 Y_VCOEFS[N_VERT_Y_TAPS * N_PHASES]; /* 0x200 */
16202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u16 RESERVEDD[0x100 / 2 - N_VERT_Y_TAPS * N_PHASES];
16302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u16 Y_HCOEFS[N_HORIZ_Y_TAPS * N_PHASES]; /* 0x300 */
16402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u16 RESERVEDE[0x200 / 2 - N_HORIZ_Y_TAPS * N_PHASES];
16502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u16 UV_VCOEFS[N_VERT_UV_TAPS * N_PHASES]; /* 0x500 */
16602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u16 RESERVEDF[0x100 / 2 - N_VERT_UV_TAPS * N_PHASES];
16702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u16 UV_HCOEFS[N_HORIZ_UV_TAPS * N_PHASES]; /* 0x600 */
16802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u16 RESERVEDG[0x100 / 2 - N_HORIZ_UV_TAPS * N_PHASES];
16902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter};
17002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
17102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter/* overlay flip addr flag */
17202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OFC_UPDATE		0x1
17302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
17402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OVERLAY_NONPHYSICAL(dev) (IS_G33(dev) || IS_I965G(dev))
17502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OVERLAY_EXISTS(dev) (!IS_G4X(dev) && !IS_IGDNG(dev))
17602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
17702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
17802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic struct overlay_registers *intel_overlay_map_regs_atomic(struct intel_overlay *overlay)
17902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
18002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter        drm_i915_private_t *dev_priv = overlay->dev->dev_private;
18102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct overlay_registers *regs;
18202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
18302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* no recursive mappings */
18402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	BUG_ON(overlay->virt_addr);
18502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
18602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (OVERLAY_NONPHYSICAL(overlay->dev)) {
18702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		regs = io_mapping_map_atomic_wc(dev_priv->mm.gtt_mapping,
18802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				overlay->reg_bo->gtt_offset);
18902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
19002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		if (!regs) {
19102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			DRM_ERROR("failed to map overlay regs in GTT\n");
19202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			return NULL;
19302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		}
19402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	} else
19502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		regs = overlay->reg_bo->phys_obj->handle->vaddr;
19602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
19702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return overlay->virt_addr = regs;
19802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
19902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
20002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic void intel_overlay_unmap_regs_atomic(struct intel_overlay *overlay)
20102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
20202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct drm_device *dev = overlay->dev;
20302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter        drm_i915_private_t *dev_priv = dev->dev_private;
20402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
20502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (OVERLAY_NONPHYSICAL(overlay->dev))
20602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		io_mapping_unmap_atomic(overlay->virt_addr);
20702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
20802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	overlay->virt_addr = NULL;
20902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
21002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	I915_READ(OVADD); /* flush wc cashes */
21102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
21202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return;
21302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
21402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
21502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter/* overlay needs to be disable in OCMD reg */
21602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic int intel_overlay_on(struct intel_overlay *overlay)
21702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
21802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct drm_device *dev = overlay->dev;
21902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter        drm_i915_private_t *dev_priv = dev->dev_private;
22002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int ret;
22102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	RING_LOCALS;
22202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
22302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	BUG_ON(overlay->active);
22402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
22502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	BEGIN_LP_RING(6);
22602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	OUT_RING(MI_FLUSH);
22702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	OUT_RING(MI_NOOP);
22802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_ON);
22902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	OUT_RING(overlay->flip_addr | OFC_UPDATE);
23002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
23102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	OUT_RING(MI_NOOP);
23202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	ADVANCE_LP_RING();
23302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
23402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	ret = i915_lp_ring_sync(dev);
23502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (ret != 0) {
23602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		DRM_ERROR("intel overlay: ring sync failed, hw likely wedged\n");
23702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		overlay->hw_wedged = 1;
23802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return 0;
23902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
24002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
24102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	overlay->active = 1;
24202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
24302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return 0;
24402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
24502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
24602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter/* overlay needs to be enabled in OCMD reg */
24702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic void intel_overlay_continue(struct intel_overlay *overlay,
24802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			    bool load_polyphase_filter)
24902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
25002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct drm_device *dev = overlay->dev;
25102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter        drm_i915_private_t *dev_priv = dev->dev_private;
25202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	u32 flip_addr = overlay->flip_addr;
25302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	u32 tmp;
25402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int ret;
25502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	RING_LOCALS;
25602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
25702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	BUG_ON(!overlay->active);
25802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
25902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (load_polyphase_filter)
26002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		flip_addr |= OFC_UPDATE;
26102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
26202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* check for underruns */
26302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	tmp = I915_READ(DOVSTA);
26402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (tmp & (1 << 17))
26502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		DRM_DEBUG("overlay underrun, DOVSTA: %x\n", tmp);
26602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
26702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	BEGIN_LP_RING(6);
26802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	OUT_RING(MI_FLUSH);
26902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	OUT_RING(MI_NOOP);
27002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_CONTINUE);
27102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	OUT_RING(flip_addr);
27202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter        OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
27302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter        OUT_RING(MI_NOOP);
27402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter        ADVANCE_LP_RING();
27502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
27602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* run in lockstep with the hw for easier testing */
27702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	ret = i915_lp_ring_sync(dev);
27802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (ret != 0) {
27902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		DRM_ERROR("intel overlay: ring sync failed, hw likely wedged\n");
28002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		overlay->hw_wedged = 1;
28102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
28202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
28302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
28402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic int intel_overlay_wait_flip(struct intel_overlay *overlay)
28502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
28602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* don't overcomplicate things for now with asynchronous operations
28702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	 * see comment above */
28802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return 0;
28902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
29002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
29102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter/* overlay needs to be disabled in OCMD reg */
29202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic int intel_overlay_off(struct intel_overlay *overlay)
29302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
29402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	u32 flip_addr = overlay->flip_addr;
29502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct drm_device *dev = overlay->dev;
29602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter        drm_i915_private_t *dev_priv = dev->dev_private;
29702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int ret;
29802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	RING_LOCALS;
29902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
30002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	BUG_ON(!overlay->active);
30102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
30202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* According to intel docs the overlay hw may hang (when switching
30302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	 * off) without loading the filter coeffs. It is however unclear whether
30402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	 * this applies to the disabling of the overlay or to the switching off
30502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	 * of the hw. Do it in both cases */
30602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	flip_addr |= OFC_UPDATE;
30702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
30802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* wait for overlay to go idle */
30902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	BEGIN_LP_RING(6);
31002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	OUT_RING(MI_FLUSH);
31102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	OUT_RING(MI_NOOP);
31202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_CONTINUE);
31302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	OUT_RING(flip_addr);
31402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter        OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
31502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter        OUT_RING(MI_NOOP);
31602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter        ADVANCE_LP_RING();
31702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
31802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	ret = i915_lp_ring_sync(dev);
31902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (ret != 0) {
32002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		DRM_ERROR("intel overlay: ring sync failed, hw likely wedged\n");
32102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		overlay->hw_wedged = 1;
32202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return ret;
32302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
32402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
32502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* turn overlay off */
32602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* this is not done in userspace!
32702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	BEGIN_LP_RING(6);
32802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter        OUT_RING(MI_FLUSH);
32902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter        OUT_RING(MI_NOOP);
33002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter        OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_OFF);
33102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	OUT_RING(flip_addr);
33202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter        OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
33302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter        OUT_RING(MI_NOOP);
33402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	ADVANCE_LP_RING();
33502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
33602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	ret = i915_lp_ring_sync(dev);
33702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (ret != 0) {
33802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		DRM_ERROR("intel overlay: ring sync failed, hw likely wedged\n");
33902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		overlay->hw_wedged = 1;
34002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return ret;
34102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}*/
34202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
34302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	overlay->active = 0;
34402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
34502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return ret;
34602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
34702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
34802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter/* wait for pending overlay flip and release old frame */
34902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic int intel_overlay_release_old_vid(struct intel_overlay *overlay)
35002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
35102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int ret;
35202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct drm_gem_object *obj;
35302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
35402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	ret = intel_overlay_wait_flip(overlay);
35502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (ret != 0)
35602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return ret;
35702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
35802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!overlay->old_vid_bo)
35902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return 0;
36002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
36102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	obj = overlay->old_vid_bo->obj;
36202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	i915_gem_object_unpin(obj);
36302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	drm_gem_object_unreference(obj);
36402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	overlay->old_vid_bo = NULL;
36502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
36602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return 0;
36702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
36802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
36902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstruct put_image_params {
37002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int format;
37102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	short dst_x;
37202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	short dst_y;
37302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	short dst_w;
37402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	short dst_h;
37502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	short src_w;
37602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	short src_scan_h;
37702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	short src_scan_w;
37802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	short src_h;
37902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	short stride_Y;
38002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	short stride_UV;
38102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int offset_Y;
38202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int offset_U;
38302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int offset_V;
38402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter};
38502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
38602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic int packed_depth_bytes(u32 format)
38702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
38802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	switch (format & I915_OVERLAY_DEPTH_MASK) {
38902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		case I915_OVERLAY_YUV422:
39002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			return 4;
39102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		case I915_OVERLAY_YUV411:
39202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			/* return 6; not implemented */
39302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		default:
39402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			return -EINVAL;
39502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
39602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
39702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
39802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic int packed_width_bytes(u32 format, short width)
39902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
40002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	switch (format & I915_OVERLAY_DEPTH_MASK) {
40102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		case I915_OVERLAY_YUV422:
40202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			return width << 1;
40302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		default:
40402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			return -EINVAL;
40502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
40602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
40702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
40802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic int uv_hsubsampling(u32 format)
40902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
41002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	switch (format & I915_OVERLAY_DEPTH_MASK) {
41102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		case I915_OVERLAY_YUV422:
41202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		case I915_OVERLAY_YUV420:
41302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			return 2;
41402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		case I915_OVERLAY_YUV411:
41502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		case I915_OVERLAY_YUV410:
41602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			return 4;
41702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		default:
41802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			return -EINVAL;
41902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
42002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
42102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
42202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic int uv_vsubsampling(u32 format)
42302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
42402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	switch (format & I915_OVERLAY_DEPTH_MASK) {
42502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		case I915_OVERLAY_YUV420:
42602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		case I915_OVERLAY_YUV410:
42702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			return 2;
42802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		case I915_OVERLAY_YUV422:
42902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		case I915_OVERLAY_YUV411:
43002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			return 1;
43102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		default:
43202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			return -EINVAL;
43302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
43402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
43502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
43602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic u32 calc_swidthsw(struct drm_device *dev, u32 offset, u32 width)
43702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
43802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	u32 mask, shift, ret;
43902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (IS_I9XX(dev)) {
44002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		mask = 0x3f;
44102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		shift = 6;
44202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	} else {
44302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		mask = 0x1f;
44402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		shift = 5;
44502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
44602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	ret = ((offset + width + mask) >> shift) - (offset >> shift);
44702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (IS_I9XX(dev))
44802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		ret <<= 1;
44902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	ret -=1;
45002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return ret << 2;
45102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
45202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
45302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic const u16 y_static_hcoeffs[N_HORIZ_Y_TAPS * N_PHASES] = {
45402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3000, 0xb4a0, 0x1930, 0x1920, 0xb4a0,
45502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3000, 0xb500, 0x19d0, 0x1880, 0xb440,
45602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3000, 0xb540, 0x1a88, 0x2f80, 0xb3e0,
45702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3000, 0xb580, 0x1b30, 0x2e20, 0xb380,
45802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3000, 0xb5c0, 0x1bd8, 0x2cc0, 0xb320,
45902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3020, 0xb5e0, 0x1c60, 0x2b80, 0xb2c0,
46002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3020, 0xb5e0, 0x1cf8, 0x2a20, 0xb260,
46102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3020, 0xb5e0, 0x1d80, 0x28e0, 0xb200,
46202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3020, 0xb5c0, 0x1e08, 0x3f40, 0xb1c0,
46302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3020, 0xb580, 0x1e78, 0x3ce0, 0xb160,
46402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3040, 0xb520, 0x1ed8, 0x3aa0, 0xb120,
46502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3040, 0xb4a0, 0x1f30, 0x3880, 0xb0e0,
46602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3040, 0xb400, 0x1f78, 0x3680, 0xb0a0,
46702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3020, 0xb340, 0x1fb8, 0x34a0, 0xb060,
46802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3020, 0xb240, 0x1fe0, 0x32e0, 0xb040,
46902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3020, 0xb140, 0x1ff8, 0x3160, 0xb020,
47002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0xb000, 0x3000, 0x0800, 0x3000, 0xb000};
47102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic const u16 uv_static_hcoeffs[N_HORIZ_UV_TAPS * N_PHASES] = {
47202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3000, 0x1800, 0x1800, 0xb000, 0x18d0, 0x2e60,
47302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0xb000, 0x1990, 0x2ce0, 0xb020, 0x1a68, 0x2b40,
47402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0xb040, 0x1b20, 0x29e0, 0xb060, 0x1bd8, 0x2880,
47502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0xb080, 0x1c88, 0x3e60, 0xb0a0, 0x1d28, 0x3c00,
47602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0xb0c0, 0x1db8, 0x39e0, 0xb0e0, 0x1e40, 0x37e0,
47702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0xb100, 0x1eb8, 0x3620, 0xb100, 0x1f18, 0x34a0,
47802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0xb100, 0x1f68, 0x3360, 0xb0e0, 0x1fa8, 0x3240,
47902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0xb0c0, 0x1fe0, 0x3140, 0xb060, 0x1ff0, 0x30a0,
48002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3000, 0x0800, 0x3000};
48102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
48202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic void update_polyphase_filter(struct overlay_registers *regs)
48302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
48402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	memcpy(regs->Y_HCOEFS, y_static_hcoeffs, sizeof(y_static_hcoeffs));
48502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	memcpy(regs->UV_HCOEFS, uv_static_hcoeffs, sizeof(uv_static_hcoeffs));
48602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
48702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
48802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic bool update_scaling_factors(struct intel_overlay *overlay,
48902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				   struct overlay_registers *regs,
49002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				   struct put_image_params *params)
49102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
49202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* fixed point with a 12 bit shift */
49302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	u32 xscale, yscale, xscale_UV, yscale_UV;
49402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define FP_SHIFT 12
49502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define FRACT_MASK 0xfff
49602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	bool scale_changed = false;
49702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int uv_hscale = uv_hsubsampling(params->format);
49802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int uv_vscale = uv_vsubsampling(params->format);
49902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
50002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (params->dst_w > 1)
50102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		xscale = ((params->src_scan_w - 1) << FP_SHIFT)
50202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			/(params->dst_w);
50302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	else
50402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		xscale = 1 << FP_SHIFT;
50502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
50602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (params->dst_h > 1)
50702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		yscale = ((params->src_scan_h - 1) << FP_SHIFT)
50802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			/(params->dst_h);
50902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	else
51002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		yscale = 1 << FP_SHIFT;
51102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
51202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/*if (params->format & I915_OVERLAY_YUV_PLANAR) {*/
51302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		xscale_UV = xscale/uv_hscale;
51402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		yscale_UV = yscale/uv_vscale;
51502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		/* make the Y scale to UV scale ratio an exact multiply */
51602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		xscale = xscale_UV * uv_hscale;
51702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		yscale = yscale_UV * uv_vscale;
51802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/*} else {
51902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		xscale_UV = 0;
52002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		yscale_UV = 0;
52102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}*/
52202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
52302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (xscale != overlay->old_xscale || yscale != overlay->old_yscale)
52402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		scale_changed = true;
52502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	overlay->old_xscale = xscale;
52602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	overlay->old_yscale = yscale;
52702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
52802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	regs->YRGBSCALE = ((yscale & FRACT_MASK) << 20)
52902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		| ((xscale >> FP_SHIFT) << 16)
53002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		| ((xscale & FRACT_MASK) << 3);
53102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	regs->UVSCALE = ((yscale_UV & FRACT_MASK) << 20)
53202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		| ((xscale_UV >> FP_SHIFT) << 16)
53302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		| ((xscale_UV & FRACT_MASK) << 3);
53402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	regs->UVSCALEV = ((yscale >> FP_SHIFT) << 16)
53502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		| ((yscale_UV >> FP_SHIFT) << 0);
53602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
53702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (scale_changed)
53802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		update_polyphase_filter(regs);
53902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
54002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return scale_changed;
54102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
54202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
54302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic void update_colorkey(struct intel_overlay *overlay,
54402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			    struct overlay_registers *regs)
54502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
54602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	u32 key = overlay->color_key;
54702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	switch (overlay->crtc->base.fb->bits_per_pixel) {
54802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		case 8:
54902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			regs->DCLRKV = 0;
55002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			regs->DCLRKM = CLK_RGB8I_MASK | DST_KEY_ENABLE;
55102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		case 16:
55202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			if (overlay->crtc->base.fb->depth == 15) {
55302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				regs->DCLRKV = RGB15_TO_COLORKEY(key);
55402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				regs->DCLRKM = CLK_RGB15_MASK | DST_KEY_ENABLE;
55502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			} else {
55602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				regs->DCLRKV = RGB16_TO_COLORKEY(key);
55702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				regs->DCLRKM = CLK_RGB16_MASK | DST_KEY_ENABLE;
55802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			}
55902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		case 24:
56002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		case 32:
56102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			regs->DCLRKV = key;
56202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			regs->DCLRKM = CLK_RGB24_MASK | DST_KEY_ENABLE;
56302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
56402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
56502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
56602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic u32 overlay_cmd_reg(struct put_image_params *params)
56702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
56802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	u32 cmd = OCMD_ENABLE | OCMD_BUF_TYPE_FRAME | OCMD_BUFFER0;
56902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
57002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (params->format & I915_OVERLAY_YUV_PLANAR) {
57102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		switch (params->format & I915_OVERLAY_DEPTH_MASK) {
57202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			case I915_OVERLAY_YUV422:
57302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				cmd |= OCMD_YUV_422_PLANAR;
57402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				break;
57502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			case I915_OVERLAY_YUV420:
57602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				cmd |= OCMD_YUV_420_PLANAR;
57702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				break;
57802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			case I915_OVERLAY_YUV411:
57902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			case I915_OVERLAY_YUV410:
58002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				cmd |= OCMD_YUV_410_PLANAR;
58102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				break;
58202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		}
58302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	} else { /* YUV packed */
58402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		switch (params->format & I915_OVERLAY_DEPTH_MASK) {
58502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			case I915_OVERLAY_YUV422:
58602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				cmd |= OCMD_YUV_422_PACKED;
58702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				break;
58802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			case I915_OVERLAY_YUV411:
58902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				cmd |= OCMD_YUV_411_PACKED;
59002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				break;
59102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		}
59202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
59302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		switch (params->format & I915_OVERLAY_SWAP_MASK) {
59402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			case I915_OVERLAY_NO_SWAP:
59502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				break;
59602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			case I915_OVERLAY_UV_SWAP:
59702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				cmd |= OCMD_UV_SWAP;
59802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				break;
59902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			case I915_OVERLAY_Y_SWAP:
60002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				cmd |= OCMD_Y_SWAP;
60102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				break;
60202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			case I915_OVERLAY_Y_AND_UV_SWAP:
60302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				cmd |= OCMD_Y_AND_UV_SWAP;
60402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				break;
60502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		}
60602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
60702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
60802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return cmd;
60902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
61002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
61102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterint intel_overlay_do_put_image(struct intel_overlay *overlay,
61202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			       struct drm_gem_object *new_bo,
61302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			       struct put_image_params *params)
61402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
61502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int ret, tmp_width;
61602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct overlay_registers *regs;
61702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	bool scale_changed = false;
61802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct drm_i915_gem_object *bo_priv = new_bo->driver_private;
61902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct drm_device *dev = overlay->dev;
62002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
62102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	BUG_ON(!mutex_is_locked(&dev->struct_mutex));
62202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	BUG_ON(!mutex_is_locked(&dev->mode_config.mutex));
62302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	BUG_ON(!overlay);
62402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
62502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (overlay->hw_wedged)
62602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EBUSY;
62702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
62802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	ret = intel_overlay_release_old_vid(overlay);
62902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (ret != 0)
63002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return ret;
63102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
63202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	ret = i915_gem_object_pin(new_bo, PAGE_SIZE);
63302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (ret != 0)
63402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return ret;
63502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
63602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	ret = i915_gem_object_set_to_gtt_domain(new_bo, 0);
63702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (ret != 0)
63802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		goto out_unpin;
63902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
64002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!overlay->active) {
64102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		regs = intel_overlay_map_regs_atomic(overlay);
64202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		if (!regs) {
64302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			ret = -ENOMEM;
64402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			goto out_unpin;
64502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		}
64602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		regs->OCONFIG = OCONF_CC_OUT_8BIT;
64702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		if (IS_I965GM(overlay->dev))
64802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			regs->OCONFIG |= OCONF_CSC_MODE_BT709;
64902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		regs->OCONFIG |= overlay->crtc->pipe == 0 ?
65002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			OCONF_PIPE_A : OCONF_PIPE_B;
65102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		intel_overlay_unmap_regs_atomic(overlay);
65202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
65302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		ret = intel_overlay_on(overlay);
65402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		if (ret != 0)
65502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			goto out_unpin;
65602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
65702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
65802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	regs = intel_overlay_map_regs_atomic(overlay);
65902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!regs) {
66002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		ret = -ENOMEM;
66102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		goto out_unpin;
66202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
66302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
66402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	regs->DWINPOS = (params->dst_y << 16) | params->dst_x;
66502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	regs->DWINSZ = (params->dst_h << 16) | params->dst_w;
66602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
66702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (params->format & I915_OVERLAY_YUV_PACKED)
66802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		tmp_width = packed_width_bytes(params->format, params->src_w);
66902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	else
67002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		tmp_width = params->src_w;
67102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
67202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	regs->SWIDTH = params->src_w;
67302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	regs->SWIDTHSW = calc_swidthsw(overlay->dev,
67402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			params->offset_Y, tmp_width);
67502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	regs->SHEIGHT = params->src_h;
67602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	regs->OBUF_0Y = bo_priv->gtt_offset + params-> offset_Y;
67702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	regs->OSTRIDE = params->stride_Y;
67802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
67902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (params->format & I915_OVERLAY_YUV_PLANAR) {
68002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		int uv_hscale = uv_hsubsampling(params->format);
68102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		int uv_vscale = uv_vsubsampling(params->format);
68202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		u32 tmp_U, tmp_V;
68302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		regs->SWIDTH |= (params->src_w/uv_hscale) << 16;
68402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		tmp_U = calc_swidthsw(overlay->dev, params->offset_U,
68502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				params->src_w/uv_hscale);
68602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		tmp_V = calc_swidthsw(overlay->dev, params->offset_V,
68702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				params->src_w/uv_hscale);
68802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		regs->SWIDTHSW |= max_t(u32, tmp_U, tmp_V) << 16;
68902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		regs->SHEIGHT |= (params->src_h/uv_vscale) << 16;
69002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		regs->OBUF_0U = bo_priv->gtt_offset + params->offset_U;
69102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		regs->OBUF_0V = bo_priv->gtt_offset + params->offset_V;
69202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		regs->OSTRIDE |= params->stride_UV << 16;
69302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
69402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
69502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	scale_changed = update_scaling_factors(overlay, regs, params);
69602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
69702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	update_colorkey(overlay, regs);
69802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
69902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	regs->OCMD = overlay_cmd_reg(params);
70002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
70102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	intel_overlay_unmap_regs_atomic(overlay);
70202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
70302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	intel_overlay_continue(overlay, scale_changed);
70402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
70502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	overlay->old_vid_bo = overlay->vid_bo;
70602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	overlay->vid_bo = new_bo->driver_private;
70702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
70802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return 0;
70902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
71002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterout_unpin:
71102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	i915_gem_object_unpin(new_bo);
71202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return ret;
71302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
71402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
71502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterint intel_overlay_switch_off(struct intel_overlay *overlay)
71602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
71702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int ret;
71802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct overlay_registers *regs;
71902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct drm_gem_object *obj;
72002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct drm_device *dev = overlay->dev;
72102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
72202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	BUG_ON(!mutex_is_locked(&dev->struct_mutex));
72302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	BUG_ON(!mutex_is_locked(&dev->mode_config.mutex));
72402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
72502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!overlay->active)
72602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return 0;
72702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
72802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (overlay->hw_wedged)
72902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EBUSY;
73002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
73102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	ret = intel_overlay_release_old_vid(overlay);
73202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (ret != 0)
73302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return ret;
73402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
73502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	regs = intel_overlay_map_regs_atomic(overlay);
73602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	regs->OCMD = 0;
73702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	intel_overlay_unmap_regs_atomic(overlay);
73802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
73902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	ret = intel_overlay_off(overlay);
74002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* never have the overlay hw on without showing a frame */
74102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	BUG_ON(!overlay->vid_bo);
74202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	obj = overlay->vid_bo->obj;
74302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
74402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	i915_gem_object_unpin(obj);
74502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	drm_gem_object_unreference(obj);
74602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	overlay->vid_bo = NULL;
74702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
74802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	overlay->crtc->overlay = NULL;
74902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	overlay->crtc = NULL;
75002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
75102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return 0;
75202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
75302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
75402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic int check_overlay_possible_on_crtc(struct intel_overlay *overlay,
75502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter					  struct intel_crtc *crtc)
75602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
75702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter        drm_i915_private_t *dev_priv = overlay->dev->dev_private;
75802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	u32 pipeconf;
75902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int pipeconf_reg = (crtc->pipe == 0) ? PIPEACONF : PIPEBCONF;
76002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
76102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!crtc->base.enabled || crtc->dpms_mode != DRM_MODE_DPMS_ON)
76202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EINVAL;
76302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
76402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	pipeconf = I915_READ(pipeconf_reg);
76502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
76602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* can't use the overlay with double wide pipe */
76702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!IS_I965G(overlay->dev) && pipeconf & PIPEACONF_DOUBLE_WIDE)
76802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EINVAL;
76902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
77002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return 0;
77102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
77202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
77302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic void update_pfit_vscale_ratio(struct intel_overlay *overlay)
77402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
77502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct drm_device *dev = overlay->dev;
77602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter        drm_i915_private_t *dev_priv = dev->dev_private;
77702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	u32 ratio;
77802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	u32 pfit_control = I915_READ(PFIT_CONTROL);
77902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
78002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* XXX: This is not the same logic as in the xorg driver, but more in
78102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	 * line with the intel documentation for the i965 */
78202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!IS_I965G(dev) && (pfit_control & VERT_AUTO_SCALE)) {
78302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		ratio = I915_READ(PFIT_AUTO_RATIOS) >> PFIT_VERT_SCALE_SHIFT;
78402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	} else { /* on i965 use the PGM reg to read out the autoscaler values */
78502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		ratio = I915_READ(PFIT_PGM_RATIOS);
78602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		if (IS_I965G(dev))
78702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			ratio >>= PFIT_VERT_SCALE_SHIFT_965;
78802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		else
78902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			ratio >>= PFIT_VERT_SCALE_SHIFT;
79002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
79102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
79202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	overlay->pfit_vscale_ratio = ratio;
79302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
79402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
79502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic int check_overlay_dst(struct intel_overlay *overlay,
79602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			     struct drm_intel_overlay_put_image *rec)
79702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
79802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct drm_display_mode *mode = &overlay->crtc->base.mode;
79902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
80002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if ((rec->dst_x < mode->crtc_hdisplay)
80102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	    && (rec->dst_x + rec->dst_width
80202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		    <= mode->crtc_hdisplay)
80302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	    && (rec->dst_y < mode->crtc_vdisplay)
80402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	    && (rec->dst_y + rec->dst_height
80502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		    <= mode->crtc_vdisplay))
80602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return 0;
80702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	else
80802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EINVAL;
80902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
81002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
81102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic int check_overlay_scaling(struct put_image_params *rec)
81202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
81302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	u32 tmp;
81402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
81502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* downscaling limit is 8.0 */
81602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	tmp = ((rec->src_scan_h << 16) / rec->dst_h) >> 16;
81702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (tmp > 7)
81802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EINVAL;
81902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	tmp = ((rec->src_scan_w << 16) / rec->dst_w) >> 16;
82002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (tmp > 7)
82102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EINVAL;
82202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
82302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return 0;
82402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
82502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
82602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic int check_overlay_src(struct drm_device *dev,
82702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			     struct drm_intel_overlay_put_image *rec,
82802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			     struct drm_gem_object *new_bo)
82902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
83002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	u32 stride_mask;
83102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int depth;
83202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int uv_hscale = uv_hsubsampling(rec->flags);
83302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int uv_vscale = uv_vsubsampling(rec->flags);
83402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	size_t tmp;
83502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
83602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* check src dimensions */
83702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (IS_845G(dev) || IS_I830(dev)) {
83802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		if (rec->src_height > IMAGE_MAX_HEIGHT_LEGACY
83902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		    || rec->src_width > IMAGE_MAX_WIDTH_LEGACY)
84002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			return -EINVAL;
84102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	} else {
84202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		if (rec->src_height > IMAGE_MAX_HEIGHT
84302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		    || rec->src_width > IMAGE_MAX_WIDTH)
84402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			return -EINVAL;
84502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
84602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* better safe than sorry, use 4 as the maximal subsampling ratio */
84702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (rec->src_height < N_VERT_Y_TAPS*4
84802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	    || rec->src_width < N_HORIZ_Y_TAPS*4)
84902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EINVAL;
85002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
85102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* check alingment constrains */
85202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	switch (rec->flags & I915_OVERLAY_TYPE_MASK) {
85302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		case I915_OVERLAY_RGB:
85402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			/* not implemented */
85502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			return -EINVAL;
85602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		case I915_OVERLAY_YUV_PACKED:
85702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			depth = packed_depth_bytes(rec->flags);
85802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			if (uv_vscale != 1)
85902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				return -EINVAL;
86002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			if (depth < 0)
86102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				return depth;
86202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			/* ignore UV planes */
86302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			rec->stride_UV = 0;
86402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			rec->offset_U = 0;
86502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			rec->offset_V = 0;
86602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			/* check pixel alignment */
86702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			if (rec->offset_Y % depth)
86802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				return -EINVAL;
86902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			break;
87002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		case I915_OVERLAY_YUV_PLANAR:
87102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			if (uv_vscale < 0 || uv_hscale < 0)
87202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				return -EINVAL;
87302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			/* no offset restrictions for planar formats */
87402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			break;
87502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		default:
87602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			return -EINVAL;
87702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
87802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
87902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (rec->src_width % uv_hscale)
88002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EINVAL;
88102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
88202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* stride checking */
88302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	stride_mask = 63;
88402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
88502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (rec->stride_Y & stride_mask || rec->stride_UV & stride_mask)
88602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EINVAL;
88702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (IS_I965G(dev) && rec->stride_Y < 512)
88802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EINVAL;
88902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
89002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	tmp = (rec->flags & I915_OVERLAY_TYPE_MASK) == I915_OVERLAY_YUV_PLANAR ?
89102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		4 : 8;
89202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (rec->stride_Y > tmp*1024 || rec->stride_UV > 2*1024)
89302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EINVAL;
89402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
89502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* check buffer dimensions */
89602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	switch (rec->flags & I915_OVERLAY_TYPE_MASK) {
89702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		case I915_OVERLAY_RGB:
89802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		case I915_OVERLAY_YUV_PACKED:
89902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			/* always 4 Y values per depth pixels */
90002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			if (packed_width_bytes(rec->flags, rec->src_width)
90102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter					> rec->stride_Y)
90202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				return -EINVAL;
90302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
90402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			tmp = rec->stride_Y*rec->src_height;
90502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			if (rec->offset_Y + tmp > new_bo->size)
90602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				return -EINVAL;
90702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			break;
90802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		case I915_OVERLAY_YUV_PLANAR:
90902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			if (rec->src_width > rec->stride_Y)
91002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				return -EINVAL;
91102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			if (rec->src_width/uv_hscale > rec->stride_UV)
91202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				return -EINVAL;
91302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
91402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			tmp = rec->stride_Y*rec->src_height;
91502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			if (rec->offset_Y + tmp > new_bo->size)
91602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				return -EINVAL;
91702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			tmp = rec->stride_UV*rec->src_height;
91802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			tmp /= uv_vscale;
91902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			if (rec->offset_U + tmp > new_bo->size
92002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			    || rec->offset_V + tmp > new_bo->size)
92102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				return -EINVAL;
92202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			break;
92302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
92402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
92502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return 0;
92602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
92702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
92802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterint intel_overlay_put_image(struct drm_device *dev, void *data,
92902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter                            struct drm_file *file_priv)
93002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
93102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct drm_intel_overlay_put_image *put_image_rec = data;
93202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	drm_i915_private_t *dev_priv = dev->dev_private;
93302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct intel_overlay *overlay;
93402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct drm_mode_object *drmmode_obj;
93502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct intel_crtc *crtc;
93602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct drm_gem_object *new_bo;
93702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct put_image_params *params;
93802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int ret;
93902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
94002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!dev_priv) {
94102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		DRM_ERROR("called with no initialization\n");
94202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EINVAL;
94302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
94402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
94502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	overlay = dev_priv->overlay;
94602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!overlay) {
94702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		DRM_DEBUG("userspace bug: no overlay\n");
94802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -ENODEV;
94902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
95002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
95102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!(put_image_rec->flags & I915_OVERLAY_ENABLE)) {
95202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		mutex_lock(&dev->mode_config.mutex);
95302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		mutex_lock(&dev->struct_mutex);
95402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
95502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		ret = intel_overlay_switch_off(overlay);
95602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
95702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		mutex_unlock(&dev->struct_mutex);
95802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		mutex_unlock(&dev->mode_config.mutex);
95902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
96002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return ret;
96102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
96202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
96302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	params = kmalloc(sizeof(struct put_image_params), GFP_KERNEL);
96402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!params)
96502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -ENOMEM;
96602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
96702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	drmmode_obj = drm_mode_object_find(dev, put_image_rec->crtc_id,
96802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter                        DRM_MODE_OBJECT_CRTC);
96902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!drmmode_obj)
97002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -ENOENT;
97102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	crtc = to_intel_crtc(obj_to_crtc(drmmode_obj));
97202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
97302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	new_bo = drm_gem_object_lookup(dev, file_priv,
97402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			put_image_rec->bo_handle);
97502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!new_bo)
97602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -ENOENT;
97702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
97802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	mutex_lock(&dev->mode_config.mutex);
97902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	mutex_lock(&dev->struct_mutex);
98002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
98102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (overlay->crtc != crtc) {
98202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		struct drm_display_mode *mode = &crtc->base.mode;
98302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		ret = intel_overlay_switch_off(overlay);
98402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		if (ret != 0)
98502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			goto out_unlock;
98602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
98702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		ret = check_overlay_possible_on_crtc(overlay, crtc);
98802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		if (ret != 0)
98902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			goto out_unlock;
99002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
99102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		overlay->crtc = crtc;
99202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		crtc->overlay = overlay;
99302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
99402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		if (intel_panel_fitter_pipe(dev) == crtc->pipe
99502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		    /* and line to wide, i.e. one-line-mode */
99602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		    && mode->hdisplay > 1024) {
99702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			overlay->pfit_active = 1;
99802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			update_pfit_vscale_ratio(overlay);
99902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		} else
100002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			overlay->pfit_active = 0;
100102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
100202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
100302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	ret = check_overlay_dst(overlay, put_image_rec);
100402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (ret != 0)
100502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		goto out_unlock;
100602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
100702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (overlay->pfit_active) {
100802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		params->dst_y = ((((u32)put_image_rec->dst_y) << 12) /
100902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			overlay->pfit_vscale_ratio);
101002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		/* shifting right rounds downwards, so add 1 */
101102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		params->dst_h = ((((u32)put_image_rec->dst_height) << 12) /
101202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			overlay->pfit_vscale_ratio) + 1;
101302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	} else {
101402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		params->dst_y = put_image_rec->dst_y;
101502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		params->dst_h = put_image_rec->dst_height;
101602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
101702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	params->dst_x = put_image_rec->dst_x;
101802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	params->dst_w = put_image_rec->dst_width;
101902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
102002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	params->src_w = put_image_rec->src_width;
102102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	params->src_h = put_image_rec->src_height;
102202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	params->src_scan_w = put_image_rec->src_scan_width;
102302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	params->src_scan_h = put_image_rec->src_scan_height;
102402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (params->src_scan_h > params->src_h
102502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	    || params->src_scan_w > params->src_w) {
102602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		ret = -EINVAL;
102702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		goto out_unlock;
102802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
102902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
103002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	ret = check_overlay_src(dev, put_image_rec, new_bo);
103102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (ret != 0)
103202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		goto out_unlock;
103302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	params->format = put_image_rec->flags & ~I915_OVERLAY_FLAGS_MASK;
103402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	params->stride_Y = put_image_rec->stride_Y;
103502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	params->stride_UV = put_image_rec->stride_UV;
103602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	params->offset_Y = put_image_rec->offset_Y;
103702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	params->offset_U = put_image_rec->offset_U;
103802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	params->offset_V = put_image_rec->offset_V;
103902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
104002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* Check scaling after src size to prevent a divide-by-zero. */
104102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	ret = check_overlay_scaling(params);
104202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (ret != 0)
104302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		goto out_unlock;
104402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
104502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	ret = intel_overlay_do_put_image(overlay, new_bo, params);
104602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (ret != 0)
104702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		goto out_unlock;
104802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
104902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	mutex_unlock(&dev->struct_mutex);
105002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	mutex_unlock(&dev->mode_config.mutex);
105102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
105202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	kfree(params);
105302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
105402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return 0;
105502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
105602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterout_unlock:
105702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	mutex_unlock(&dev->struct_mutex);
105802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	mutex_unlock(&dev->mode_config.mutex);
105902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	drm_gem_object_unreference(new_bo);
106002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	kfree(params);
106102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
106202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return ret;
106302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
106402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
106502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic void update_reg_attrs(struct intel_overlay *overlay,
106602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			     struct overlay_registers *regs)
106702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
106802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	regs->OCLRC0 = (overlay->contrast << 18) | (overlay->brightness & 0xff);
106902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	regs->OCLRC1 = overlay->saturation;
107002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
107102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
107202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic bool check_gamma_bounds(u32 gamma1, u32 gamma2)
107302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
107402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int i;
107502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
107602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (gamma1 & 0xff000000 || gamma2 & 0xff000000)
107702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return false;
107802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
107902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	for (i = 0; i < 3; i++) {
108002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		if (((gamma1 >> i * 8) & 0xff) >= ((gamma2 >> i*8) & 0xff))
108102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			return false;
108202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
108302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
108402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return true;
108502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
108602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
108702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic bool check_gamma5_errata(u32 gamma5)
108802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
108902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int i;
109002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
109102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	for (i = 0; i < 3; i++) {
109202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		if (((gamma5 >> i*8) & 0xff) == 0x80)
109302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			return false;
109402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
109502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
109602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return true;
109702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
109802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
109902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic int check_gamma(struct drm_intel_overlay_attrs *attrs)
110002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
110102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!check_gamma_bounds(0, attrs->gamma0)
110202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	    || !check_gamma_bounds(attrs->gamma0, attrs->gamma1)
110302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	    || !check_gamma_bounds(attrs->gamma1, attrs->gamma2)
110402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	    || !check_gamma_bounds(attrs->gamma2, attrs->gamma3)
110502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	    || !check_gamma_bounds(attrs->gamma3, attrs->gamma4)
110602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	    || !check_gamma_bounds(attrs->gamma4, attrs->gamma5)
110702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	    || !check_gamma_bounds(attrs->gamma5, 0x00ffffff))
110802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EINVAL;
110902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!check_gamma5_errata(attrs->gamma5))
111002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EINVAL;
111102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return 0;
111202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
111302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
111402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterint intel_overlay_attrs(struct drm_device *dev, void *data,
111502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter                        struct drm_file *file_priv)
111602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
111702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct drm_intel_overlay_attrs *attrs = data;
111802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter        drm_i915_private_t *dev_priv = dev->dev_private;
111902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct intel_overlay *overlay;
112002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct overlay_registers *regs;
112102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int ret;
112202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
112302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!dev_priv) {
112402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		DRM_ERROR("called with no initialization\n");
112502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EINVAL;
112602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
112702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
112802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	overlay = dev_priv->overlay;
112902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!overlay) {
113002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		DRM_DEBUG("userspace bug: no overlay\n");
113102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -ENODEV;
113202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
113302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
113402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	mutex_lock(&dev->mode_config.mutex);
113502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	mutex_lock(&dev->struct_mutex);
113602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
113702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!(attrs->flags & I915_OVERLAY_UPDATE_ATTRS)) {
113802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		attrs->color_key = overlay->color_key;
113902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		attrs->brightness = overlay->brightness;
114002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		attrs->contrast = overlay->contrast;
114102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		attrs->saturation = overlay->saturation;
114202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
114302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		if (IS_I9XX(dev)) {
114402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			attrs->gamma0 = I915_READ(OGAMC0);
114502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			attrs->gamma1 = I915_READ(OGAMC1);
114602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			attrs->gamma2 = I915_READ(OGAMC2);
114702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			attrs->gamma3 = I915_READ(OGAMC3);
114802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			attrs->gamma4 = I915_READ(OGAMC4);
114902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			attrs->gamma5 = I915_READ(OGAMC5);
115002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		}
115102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		ret = 0;
115202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	} else {
115302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		overlay->color_key = attrs->color_key;
115402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		if (attrs->brightness >= -128 && attrs->brightness <= 127) {
115502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			overlay->brightness = attrs->brightness;
115602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		} else {
115702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			ret = -EINVAL;
115802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			goto out_unlock;
115902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		}
116002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		if (attrs->contrast <= 255) {
116102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			overlay->contrast = attrs->contrast;
116202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		} else {
116302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			ret = -EINVAL;
116402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			goto out_unlock;
116502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		}
116602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		if (attrs->saturation <= 1023) {
116702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			overlay->saturation = attrs->saturation;
116802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		} else {
116902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			ret = -EINVAL;
117002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			goto out_unlock;
117102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		}
117202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
117302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		regs = intel_overlay_map_regs_atomic(overlay);
117402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		if (!regs) {
117502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			ret = -ENOMEM;
117602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			goto out_unlock;
117702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		}
117802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
117902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		update_reg_attrs(overlay, regs);
118002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
118102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		intel_overlay_unmap_regs_atomic(overlay);
118202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
118302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		if (attrs->flags & I915_OVERLAY_UPDATE_GAMMA) {
118402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			if (!IS_I9XX(dev)) {
118502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				ret = -EINVAL;
118602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				goto out_unlock;
118702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			}
118802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
118902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			if (overlay->active) {
119002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				ret = -EBUSY;
119102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				goto out_unlock;
119202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			}
119302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
119402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			ret = check_gamma(attrs);
119502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			if (ret != 0)
119602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				goto out_unlock;
119702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
119802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			I915_WRITE(OGAMC0, attrs->gamma0);
119902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			I915_WRITE(OGAMC1, attrs->gamma1);
120002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			I915_WRITE(OGAMC2, attrs->gamma2);
120102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			I915_WRITE(OGAMC3, attrs->gamma3);
120202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			I915_WRITE(OGAMC4, attrs->gamma4);
120302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			I915_WRITE(OGAMC5, attrs->gamma5);
120402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		}
120502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		ret = 0;
120602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
120702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
120802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterout_unlock:
120902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	mutex_unlock(&dev->struct_mutex);
121002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	mutex_unlock(&dev->mode_config.mutex);
121102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
121202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return ret;
121302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
121402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
121502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vettervoid intel_setup_overlay(struct drm_device *dev)
121602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
121702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter        drm_i915_private_t *dev_priv = dev->dev_private;
121802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct intel_overlay *overlay;
121902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct drm_gem_object *reg_bo;
122002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct overlay_registers *regs;
122102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int ret;
122202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
122302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!OVERLAY_EXISTS(dev))
122402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return;
122502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
122602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	overlay = kzalloc(sizeof(struct intel_overlay), GFP_KERNEL);
122702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!overlay)
122802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return;
122902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	overlay->dev = dev;
123002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
123102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	reg_bo = drm_gem_object_alloc(dev, PAGE_SIZE);
123202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!reg_bo)
123302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		goto out_free;
123402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	overlay->reg_bo = reg_bo->driver_private;
123502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
123602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (OVERLAY_NONPHYSICAL(dev)) {
123702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		ret = i915_gem_object_pin(reg_bo, PAGE_SIZE);
123802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		if (ret) {
123902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter                        DRM_ERROR("failed to pin overlay register bo\n");
124002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter                        goto out_free_bo;
124102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter                }
124202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		overlay->flip_addr = overlay->reg_bo->gtt_offset;
124302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	} else {
124402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		ret = i915_gem_attach_phys_object(dev, reg_bo,
124502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				I915_GEM_PHYS_OVERLAY_REGS);
124602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter                if (ret) {
124702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter                        DRM_ERROR("failed to attach phys overlay regs\n");
124802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter                        goto out_free_bo;
124902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter                }
125002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		overlay->flip_addr = overlay->reg_bo->phys_obj->handle->busaddr;
125102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
125202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
125302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* init all values */
125402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	overlay->color_key = 0x0101fe;
125502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	overlay->brightness = -19;
125602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	overlay->contrast = 75;
125702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	overlay->saturation = 146;
125802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
125902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	regs = intel_overlay_map_regs_atomic(overlay);
126002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!regs)
126102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		goto out_free_bo;
126202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
126302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	memset(regs, 0, sizeof(struct overlay_registers));
126402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	update_polyphase_filter(regs);
126502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
126602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	update_reg_attrs(overlay, regs);
126702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
126802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	intel_overlay_unmap_regs_atomic(overlay);
126902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
127002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	dev_priv->overlay = overlay;
127102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	DRM_INFO("initialized overlay support\n");
127202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return;
127302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
127402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterout_free_bo:
127502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	drm_gem_object_unreference(reg_bo);
127602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterout_free:
127702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	kfree(overlay);
127802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return;
127902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
128002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
128102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vettervoid intel_cleanup_overlay(struct drm_device *dev)
128202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
128302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter        drm_i915_private_t *dev_priv = dev->dev_private;
128402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
128502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (dev_priv->overlay) {
128602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		/* The bo's should be free'd by the generic code already.
128702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		 * Furthermore modesetting teardown happens beforehand so the
128802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		 * hardware should be off already */
128902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		BUG_ON(dev_priv->overlay->active);
129002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
129102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		kfree(dev_priv->overlay);
129202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
129302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
1294