intel_overlay.c revision e1f99ce6cac3b6a95551642be5ddb5d9c46bea76
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 */
28e167976ee7f5fe4b80f7e8f55e087f6c67cf9562Andrew Morton
29e167976ee7f5fe4b80f7e8f55e087f6c67cf9562Andrew Morton#include <linux/seq_file.h>
3002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#include "drmP.h"
3102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#include "drm.h"
3202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#include "i915_drm.h"
3302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#include "i915_drv.h"
3402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#include "i915_reg.h"
3502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#include "intel_drv.h"
3602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
3702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter/* Limits for overlay size. According to intel doc, the real limits are:
3802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter * Y width: 4095, UV width (planar): 2047, Y height: 2047,
3902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter * UV width (planar): * 1023. But the xorg thinks 2048 for height and width. Use
4002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter * the mininum of both.  */
4102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define IMAGE_MAX_WIDTH		2048
4202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define IMAGE_MAX_HEIGHT	2046 /* 2 * 1023 */
4302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter/* on 830 and 845 these large limits result in the card hanging */
4402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define IMAGE_MAX_WIDTH_LEGACY	1024
4502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define IMAGE_MAX_HEIGHT_LEGACY	1088
4602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
4702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter/* overlay register definitions */
4802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter/* OCMD register */
4902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_TILED_SURFACE	(0x1<<19)
5002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_MIRROR_MASK	(0x3<<17)
5102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_MIRROR_MODE	(0x3<<17)
5202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_MIRROR_HORIZONTAL	(0x1<<17)
5302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_MIRROR_VERTICAL	(0x2<<17)
5402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_MIRROR_BOTH	(0x3<<17)
5502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_BYTEORDER_MASK	(0x3<<14) /* zero for YUYV or FOURCC YUY2 */
5602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_UV_SWAP		(0x1<<14) /* YVYU */
5702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_Y_SWAP		(0x2<<14) /* UYVY or FOURCC UYVY */
5802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_Y_AND_UV_SWAP	(0x3<<14) /* VYUY */
5902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_SOURCE_FORMAT_MASK (0xf<<10)
6002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_RGB_888		(0x1<<10) /* not in i965 Intel docs */
6102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_RGB_555		(0x2<<10) /* not in i965 Intel docs */
6202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_RGB_565		(0x3<<10) /* not in i965 Intel docs */
6302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_YUV_422_PACKED	(0x8<<10)
6402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_YUV_411_PACKED	(0x9<<10) /* not in i965 Intel docs */
6502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_YUV_420_PLANAR	(0xc<<10)
6602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_YUV_422_PLANAR	(0xd<<10)
6702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_YUV_410_PLANAR	(0xe<<10) /* also 411 */
6802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_TVSYNCFLIP_PARITY	(0x1<<9)
6902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_TVSYNCFLIP_ENABLE	(0x1<<7)
70d79613643b4512962b2be5262a09b6694dd96101Chris Wilson#define OCMD_BUF_TYPE_MASK	(0x1<<5)
7102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_BUF_TYPE_FRAME	(0x0<<5)
7202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_BUF_TYPE_FIELD	(0x1<<5)
7302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_TEST_MODE		(0x1<<4)
7402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_BUFFER_SELECT	(0x3<<2)
7502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_BUFFER0		(0x0<<2)
7602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_BUFFER1		(0x1<<2)
7702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_FIELD_SELECT	(0x1<<2)
7802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_FIELD0		(0x0<<1)
7902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_FIELD1		(0x1<<1)
8002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_ENABLE		(0x1<<0)
8102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
8202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter/* OCONFIG register */
8302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCONF_PIPE_MASK		(0x1<<18)
8402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCONF_PIPE_A		(0x0<<18)
8502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCONF_PIPE_B		(0x1<<18)
8602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCONF_GAMMA2_ENABLE	(0x1<<16)
8702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCONF_CSC_MODE_BT601	(0x0<<5)
8802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCONF_CSC_MODE_BT709	(0x1<<5)
8902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCONF_CSC_BYPASS	(0x1<<4)
9002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCONF_CC_OUT_8BIT	(0x1<<3)
9102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCONF_TEST_MODE		(0x1<<2)
9202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCONF_THREE_LINE_BUFFER	(0x1<<0)
9302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCONF_TWO_LINE_BUFFER	(0x0<<0)
9402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
9502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter/* DCLRKM (dst-key) register */
9602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define DST_KEY_ENABLE		(0x1<<31)
9702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define CLK_RGB24_MASK		0x0
9802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define CLK_RGB16_MASK		0x070307
9902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define CLK_RGB15_MASK		0x070707
10002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define CLK_RGB8I_MASK		0xffffff
10102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
10202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define RGB16_TO_COLORKEY(c) \
10302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	(((c & 0xF800) << 8) | ((c & 0x07E0) << 5) | ((c & 0x001F) << 3))
10402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define RGB15_TO_COLORKEY(c) \
10502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	(((c & 0x7c00) << 9) | ((c & 0x03E0) << 6) | ((c & 0x001F) << 3))
10602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
10702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter/* overlay flip addr flag */
10802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OFC_UPDATE		0x1
10902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
11002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter/* polyphase filter coefficients */
11102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define N_HORIZ_Y_TAPS          5
11202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define N_VERT_Y_TAPS           3
11302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define N_HORIZ_UV_TAPS         3
11402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define N_VERT_UV_TAPS          3
11502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define N_PHASES                17
11602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define MAX_TAPS                5
11702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
11802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter/* memory bufferd overlay registers */
11902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstruct overlay_registers {
12002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u32 OBUF_0Y;
12102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u32 OBUF_1Y;
12202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u32 OBUF_0U;
12302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u32 OBUF_0V;
12402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u32 OBUF_1U;
12502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u32 OBUF_1V;
12602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u32 OSTRIDE;
12702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u32 YRGB_VPH;
12802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u32 UV_VPH;
12902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u32 HORZ_PH;
13002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u32 INIT_PHS;
13102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u32 DWINPOS;
13202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u32 DWINSZ;
13302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u32 SWIDTH;
13402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u32 SWIDTHSW;
13502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u32 SHEIGHT;
13602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u32 YRGBSCALE;
13702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u32 UVSCALE;
13802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u32 OCLRC0;
13902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u32 OCLRC1;
14002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u32 DCLRKV;
14102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u32 DCLRKM;
14202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u32 SCLRKVH;
14302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u32 SCLRKVL;
14402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u32 SCLRKEN;
14502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u32 OCONFIG;
14602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u32 OCMD;
14702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u32 RESERVED1; /* 0x6C */
14802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u32 OSTART_0Y;
14902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u32 OSTART_1Y;
15002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u32 OSTART_0U;
15102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u32 OSTART_0V;
15202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u32 OSTART_1U;
15302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u32 OSTART_1V;
15402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u32 OTILEOFF_0Y;
15502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u32 OTILEOFF_1Y;
15602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u32 OTILEOFF_0U;
15702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u32 OTILEOFF_0V;
15802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u32 OTILEOFF_1U;
15902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u32 OTILEOFF_1V;
16002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u32 FASTHSCALE; /* 0xA0 */
16102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u32 UVSCALEV; /* 0xA4 */
16202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u32 RESERVEDC[(0x200 - 0xA8) / 4]; /* 0xA8 - 0x1FC */
16302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u16 Y_VCOEFS[N_VERT_Y_TAPS * N_PHASES]; /* 0x200 */
16402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u16 RESERVEDD[0x100 / 2 - N_VERT_Y_TAPS * N_PHASES];
16502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u16 Y_HCOEFS[N_HORIZ_Y_TAPS * N_PHASES]; /* 0x300 */
16602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u16 RESERVEDE[0x200 / 2 - N_HORIZ_Y_TAPS * N_PHASES];
16702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u16 UV_VCOEFS[N_VERT_UV_TAPS * N_PHASES]; /* 0x500 */
16802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u16 RESERVEDF[0x100 / 2 - N_VERT_UV_TAPS * N_PHASES];
16902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u16 UV_HCOEFS[N_HORIZ_UV_TAPS * N_PHASES]; /* 0x600 */
17002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter    u16 RESERVEDG[0x100 / 2 - N_HORIZ_UV_TAPS * N_PHASES];
17102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter};
17202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
17323f09ce31ca68af3728ac5eed3e3efb03c5f990aChris Wilsonstruct intel_overlay {
17423f09ce31ca68af3728ac5eed3e3efb03c5f990aChris Wilson	struct drm_device *dev;
17523f09ce31ca68af3728ac5eed3e3efb03c5f990aChris Wilson	struct intel_crtc *crtc;
17623f09ce31ca68af3728ac5eed3e3efb03c5f990aChris Wilson	struct drm_i915_gem_object *vid_bo;
17723f09ce31ca68af3728ac5eed3e3efb03c5f990aChris Wilson	struct drm_i915_gem_object *old_vid_bo;
17823f09ce31ca68af3728ac5eed3e3efb03c5f990aChris Wilson	int active;
17923f09ce31ca68af3728ac5eed3e3efb03c5f990aChris Wilson	int pfit_active;
18023f09ce31ca68af3728ac5eed3e3efb03c5f990aChris Wilson	u32 pfit_vscale_ratio; /* shifted-point number, (1<<12) == 1.0 */
18123f09ce31ca68af3728ac5eed3e3efb03c5f990aChris Wilson	u32 color_key;
18223f09ce31ca68af3728ac5eed3e3efb03c5f990aChris Wilson	u32 brightness, contrast, saturation;
18323f09ce31ca68af3728ac5eed3e3efb03c5f990aChris Wilson	u32 old_xscale, old_yscale;
18423f09ce31ca68af3728ac5eed3e3efb03c5f990aChris Wilson	/* register access */
18523f09ce31ca68af3728ac5eed3e3efb03c5f990aChris Wilson	u32 flip_addr;
18623f09ce31ca68af3728ac5eed3e3efb03c5f990aChris Wilson	struct drm_i915_gem_object *reg_bo;
18723f09ce31ca68af3728ac5eed3e3efb03c5f990aChris Wilson	/* flip handling */
18823f09ce31ca68af3728ac5eed3e3efb03c5f990aChris Wilson	uint32_t last_flip_req;
189b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson	void (*flip_tail)(struct intel_overlay *);
19023f09ce31ca68af3728ac5eed3e3efb03c5f990aChris Wilson};
19102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
1928d74f656dd78ae1ba813389cd46197c6329696bcChris Wilsonstatic struct overlay_registers *
1938d74f656dd78ae1ba813389cd46197c6329696bcChris Wilsonintel_overlay_map_regs(struct intel_overlay *overlay)
19402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
19502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter        drm_i915_private_t *dev_priv = overlay->dev->dev_private;
19602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct overlay_registers *regs;
19702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
1989bb2ff731b32c023e7a502efdc0dee46157290d5Chris Wilson	if (OVERLAY_NEEDS_PHYSICAL(overlay->dev))
1998d74f656dd78ae1ba813389cd46197c6329696bcChris Wilson		regs = overlay->reg_bo->phys_obj->handle->vaddr;
2009bb2ff731b32c023e7a502efdc0dee46157290d5Chris Wilson	else
2018d74f656dd78ae1ba813389cd46197c6329696bcChris Wilson		regs = io_mapping_map_wc(dev_priv->mm.gtt_mapping,
2028d74f656dd78ae1ba813389cd46197c6329696bcChris Wilson					 overlay->reg_bo->gtt_offset);
20302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
2049bb2ff731b32c023e7a502efdc0dee46157290d5Chris Wilson	return regs;
2058d74f656dd78ae1ba813389cd46197c6329696bcChris Wilson}
20602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
2079bb2ff731b32c023e7a502efdc0dee46157290d5Chris Wilsonstatic void intel_overlay_unmap_regs(struct intel_overlay *overlay,
2089bb2ff731b32c023e7a502efdc0dee46157290d5Chris Wilson				     struct overlay_registers *regs)
2098d74f656dd78ae1ba813389cd46197c6329696bcChris Wilson{
2108d74f656dd78ae1ba813389cd46197c6329696bcChris Wilson	if (!OVERLAY_NEEDS_PHYSICAL(overlay->dev))
2119bb2ff731b32c023e7a502efdc0dee46157290d5Chris Wilson		io_mapping_unmap(regs);
21202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
21302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
214b6c028e00445de9dfde2cd0c26521ac53965320aChris Wilsonstatic int intel_overlay_do_wait_request(struct intel_overlay *overlay,
2158dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson					 struct drm_i915_gem_request *request,
216b6c028e00445de9dfde2cd0c26521ac53965320aChris Wilson					 bool interruptible,
217b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson					 void (*tail)(struct intel_overlay *))
21802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
21902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct drm_device *dev = overlay->dev;
220852835f343146a82a528c3b712b373661d4fa17aZou Nan hai	drm_i915_private_t *dev_priv = dev->dev_private;
221b6c028e00445de9dfde2cd0c26521ac53965320aChris Wilson	int ret;
22202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
223b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson	BUG_ON(overlay->last_flip_req);
224852835f343146a82a528c3b712b373661d4fa17aZou Nan hai	overlay->last_flip_req =
2258dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson		i915_add_request(dev, NULL, request, &dev_priv->render_ring);
22603f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	if (overlay->last_flip_req == 0)
22703f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter		return -ENOMEM;
22802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
229b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson	overlay->flip_tail = tail;
230852835f343146a82a528c3b712b373661d4fa17aZou Nan hai	ret = i915_do_wait_request(dev,
231722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson				   overlay->last_flip_req, true,
232722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson				   &dev_priv->render_ring);
233b6c028e00445de9dfde2cd0c26521ac53965320aChris Wilson	if (ret)
23403f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter		return ret;
23502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
23603f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	overlay->last_flip_req = 0;
23702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return 0;
23802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
23902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
240106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson/* Workaround for i830 bug where pipe a must be enable to change control regs */
241106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilsonstatic int
242106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilsoni830_activate_pipe_a(struct drm_device *dev)
24302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
244106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	drm_i915_private_t *dev_priv = dev->dev_private;
245106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	struct intel_crtc *crtc;
246106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	struct drm_crtc_helper_funcs *crtc_funcs;
247106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	struct drm_display_mode vesa_640x480 = {
248106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson		DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 25175, 640, 656,
249106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson			 752, 800, 0, 480, 489, 492, 525, 0,
250106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson			 DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC)
251106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	}, *mode;
252106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson
253106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	crtc = to_intel_crtc(dev_priv->pipe_to_crtc_mapping[0]);
254106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	if (crtc->dpms_mode == DRM_MODE_DPMS_ON)
255106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson		return 0;
25602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
257106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	/* most i8xx have pipe a forced on, so don't trust dpms mode */
2585eddb70ba2b8cdbbdd563f5cb04e26fdc9b017f7Chris Wilson	if (I915_READ(PIPEACONF) & PIPECONF_ENABLE)
259106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson		return 0;
26002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
261106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	crtc_funcs = crtc->base.helper_private;
262106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	if (crtc_funcs->dpms == NULL)
263106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson		return 0;
264106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson
265106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	DRM_DEBUG_DRIVER("Enabling pipe A in order to enable overlay\n");
266106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson
267106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	mode = drm_mode_duplicate(dev, &vesa_640x480);
268106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V);
269106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	if(!drm_crtc_helper_set_mode(&crtc->base, mode,
270106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson				       crtc->base.x, crtc->base.y,
271106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson				       crtc->base.fb))
272106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson		return 0;
273106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson
274106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	crtc_funcs->dpms(&crtc->base, DRM_MODE_DPMS_ON);
275106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	return 1;
276106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson}
277106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson
278106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilsonstatic void
279106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilsoni830_deactivate_pipe_a(struct drm_device *dev)
280106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson{
281106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	drm_i915_private_t *dev_priv = dev->dev_private;
282106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[0];
283106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
284106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson
285106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	crtc_funcs->dpms(crtc, DRM_MODE_DPMS_OFF);
28602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
28702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
28802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter/* overlay needs to be disable in OCMD reg */
28902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic int intel_overlay_on(struct intel_overlay *overlay)
29002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
29102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct drm_device *dev = overlay->dev;
292e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson	struct drm_i915_private *dev_priv = dev->dev_private;
2938dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson	struct drm_i915_gem_request *request;
294106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	int pipe_a_quirk = 0;
29502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int ret;
29602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
29702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	BUG_ON(overlay->active);
29803f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	overlay->active = 1;
299b6c028e00445de9dfde2cd0c26521ac53965320aChris Wilson
300106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	if (IS_I830(dev)) {
301106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson		pipe_a_quirk = i830_activate_pipe_a(dev);
302106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson		if (pipe_a_quirk < 0)
303106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson			return pipe_a_quirk;
304106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	}
305106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson
3068dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson	request = kzalloc(sizeof(*request), GFP_KERNEL);
307106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	if (request == NULL) {
308106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson		ret = -ENOMEM;
309106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson		goto out;
310106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	}
31103f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter
312e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson	ret = BEGIN_LP_RING(4);
313e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson	if (ret) {
314e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson		kfree(request);
315e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson		goto out;
316e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson	}
317e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson
31802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_ON);
31902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	OUT_RING(overlay->flip_addr | OFC_UPDATE);
32002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
32102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	OUT_RING(MI_NOOP);
32202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	ADVANCE_LP_RING();
32302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
324b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson	ret = intel_overlay_do_wait_request(overlay, request, true, NULL);
325106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilsonout:
326106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	if (pipe_a_quirk)
327106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson		i830_deactivate_pipe_a(dev);
32802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
329106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	return ret;
33002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
33102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
33202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter/* overlay needs to be enabled in OCMD reg */
3338dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilsonstatic int intel_overlay_continue(struct intel_overlay *overlay,
3348dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson				  bool load_polyphase_filter)
33502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
33602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct drm_device *dev = overlay->dev;
33702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter        drm_i915_private_t *dev_priv = dev->dev_private;
3388dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson	struct drm_i915_gem_request *request;
33902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	u32 flip_addr = overlay->flip_addr;
34002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	u32 tmp;
341e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson	int ret;
34202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
34302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	BUG_ON(!overlay->active);
34402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
3458dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson	request = kzalloc(sizeof(*request), GFP_KERNEL);
3468dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson	if (request == NULL)
3478dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson		return -ENOMEM;
3488dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson
34902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (load_polyphase_filter)
35002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		flip_addr |= OFC_UPDATE;
35102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
35202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* check for underruns */
35302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	tmp = I915_READ(DOVSTA);
35402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (tmp & (1 << 17))
35502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		DRM_DEBUG("overlay underrun, DOVSTA: %x\n", tmp);
35602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
357e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson	ret = BEGIN_LP_RING(2);
358e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson	if (ret) {
359e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson		kfree(request);
360e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson		return ret;
361e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson	}
36202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_CONTINUE);
36302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	OUT_RING(flip_addr);
3645a5a0c64a99d7542c48c99d1a8bbb49e665842beDaniel Vetter        ADVANCE_LP_RING();
3655a5a0c64a99d7542c48c99d1a8bbb49e665842beDaniel Vetter
366852835f343146a82a528c3b712b373661d4fa17aZou Nan hai	overlay->last_flip_req =
3678dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson		i915_add_request(dev, NULL, request, &dev_priv->render_ring);
3688dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson	return 0;
3695a5a0c64a99d7542c48c99d1a8bbb49e665842beDaniel Vetter}
3705a5a0c64a99d7542c48c99d1a8bbb49e665842beDaniel Vetter
371b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilsonstatic void intel_overlay_release_old_vid_tail(struct intel_overlay *overlay)
3725a5a0c64a99d7542c48c99d1a8bbb49e665842beDaniel Vetter{
373b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson	struct drm_gem_object *obj = &overlay->old_vid_bo->base;
3745a5a0c64a99d7542c48c99d1a8bbb49e665842beDaniel Vetter
375b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson	i915_gem_object_unpin(obj);
376b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson	drm_gem_object_unreference(obj);
3775a5a0c64a99d7542c48c99d1a8bbb49e665842beDaniel Vetter
378b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson	overlay->old_vid_bo = NULL;
379b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson}
38003f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter
381b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilsonstatic void intel_overlay_off_tail(struct intel_overlay *overlay)
382b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson{
383b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson	struct drm_gem_object *obj;
38402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
385b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson	/* never have the overlay hw on without showing a frame */
386b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson	BUG_ON(!overlay->vid_bo);
387b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson	obj = &overlay->vid_bo->base;
38802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
389b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson	i915_gem_object_unpin(obj);
390b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson	drm_gem_object_unreference(obj);
391b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson	overlay->vid_bo = NULL;
39203f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter
393b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson	overlay->crtc->overlay = NULL;
394b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson	overlay->crtc = NULL;
395b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson	overlay->active = 0;
39602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
39702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
39802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter/* overlay needs to be disabled in OCMD reg */
3995dcdbcb06badbdf2faa698bf3198e421a1e12840Chris Wilsonstatic int intel_overlay_off(struct intel_overlay *overlay,
4005dcdbcb06badbdf2faa698bf3198e421a1e12840Chris Wilson			     bool interruptible)
40102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
40202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct drm_device *dev = overlay->dev;
403e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson	struct drm_i915_private *dev_priv = dev->dev_private;
4048dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson	u32 flip_addr = overlay->flip_addr;
4058dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson	struct drm_i915_gem_request *request;
406e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson	int ret;
40702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
40802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	BUG_ON(!overlay->active);
40902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
4108dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson	request = kzalloc(sizeof(*request), GFP_KERNEL);
4118dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson	if (request == NULL)
4128dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson		return -ENOMEM;
4138dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson
41402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* According to intel docs the overlay hw may hang (when switching
41502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	 * off) without loading the filter coeffs. It is however unclear whether
41602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	 * this applies to the disabling of the overlay or to the switching off
41702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	 * of the hw. Do it in both cases */
41802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	flip_addr |= OFC_UPDATE;
41902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
420e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson	ret = BEGIN_LP_RING(6);
421e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson	if (ret) {
422e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson		kfree(request);
423e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson		return ret;
424e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson	}
42502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* wait for overlay to go idle */
42602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_CONTINUE);
42702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	OUT_RING(flip_addr);
428722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
42902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* turn overlay off */
430722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_OFF);
43102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	OUT_RING(flip_addr);
432722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
43302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	ADVANCE_LP_RING();
43402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
4355dcdbcb06badbdf2faa698bf3198e421a1e12840Chris Wilson	return intel_overlay_do_wait_request(overlay, request, interruptible,
436b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson					     intel_overlay_off_tail);
43712ca45fea91cfbb09df828bea958b47348caee6dDaniel Vetter}
43812ca45fea91cfbb09df828bea958b47348caee6dDaniel Vetter
43903f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter/* recover from an interruption due to a signal
44003f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter * We have to be careful not to repeat work forever an make forward progess. */
4415dcdbcb06badbdf2faa698bf3198e421a1e12840Chris Wilsonstatic int intel_overlay_recover_from_interrupt(struct intel_overlay *overlay,
4425dcdbcb06badbdf2faa698bf3198e421a1e12840Chris Wilson						bool interruptible)
44303f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter{
44403f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	struct drm_device *dev = overlay->dev;
445852835f343146a82a528c3b712b373661d4fa17aZou Nan hai	drm_i915_private_t *dev_priv = dev->dev_private;
44603f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	int ret;
44703f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter
448b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson	if (overlay->last_flip_req == 0)
449b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson		return 0;
45003f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter
451852835f343146a82a528c3b712b373661d4fa17aZou Nan hai	ret = i915_do_wait_request(dev, overlay->last_flip_req,
452722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson				   interruptible, &dev_priv->render_ring);
453b6c028e00445de9dfde2cd0c26521ac53965320aChris Wilson	if (ret)
45403f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter		return ret;
45503f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter
456b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson	if (overlay->flip_tail)
457b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson		overlay->flip_tail(overlay);
45803f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter
45903f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	overlay->last_flip_req = 0;
46003f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	return 0;
46103f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter}
46203f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter
4635a5a0c64a99d7542c48c99d1a8bbb49e665842beDaniel Vetter/* Wait for pending overlay flip and release old frame.
4645a5a0c64a99d7542c48c99d1a8bbb49e665842beDaniel Vetter * Needs to be called before the overlay register are changed
4658d74f656dd78ae1ba813389cd46197c6329696bcChris Wilson * via intel_overlay_(un)map_regs
4668d74f656dd78ae1ba813389cd46197c6329696bcChris Wilson */
46702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic int intel_overlay_release_old_vid(struct intel_overlay *overlay)
46802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
4695cd68c9864d65e49c910c701716e4e94e09f7ce0Chris Wilson	struct drm_device *dev = overlay->dev;
4705cd68c9864d65e49c910c701716e4e94e09f7ce0Chris Wilson	drm_i915_private_t *dev_priv = dev->dev_private;
47102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int ret;
47202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
4735cd68c9864d65e49c910c701716e4e94e09f7ce0Chris Wilson	/* Only wait if there is actually an old frame to release to
4745cd68c9864d65e49c910c701716e4e94e09f7ce0Chris Wilson	 * guarantee forward progress.
4755cd68c9864d65e49c910c701716e4e94e09f7ce0Chris Wilson	 */
47603f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	if (!overlay->old_vid_bo)
47703f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter		return 0;
47803f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter
4795cd68c9864d65e49c910c701716e4e94e09f7ce0Chris Wilson	if (I915_READ(ISR) & I915_OVERLAY_PLANE_FLIP_PENDING_INTERRUPT) {
4808dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson		struct drm_i915_gem_request *request;
48102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
4825cd68c9864d65e49c910c701716e4e94e09f7ce0Chris Wilson		/* synchronous slowpath */
4838dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson		request = kzalloc(sizeof(*request), GFP_KERNEL);
4848dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson		if (request == NULL)
4858dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson			return -ENOMEM;
48602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
487e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson		ret = BEGIN_LP_RING(2);
488e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson		if (ret) {
489e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson			kfree(request);
490e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson			return ret;
491e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson		}
492e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson
4935cd68c9864d65e49c910c701716e4e94e09f7ce0Chris Wilson		OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
4945cd68c9864d65e49c910c701716e4e94e09f7ce0Chris Wilson		OUT_RING(MI_NOOP);
4955cd68c9864d65e49c910c701716e4e94e09f7ce0Chris Wilson		ADVANCE_LP_RING();
4965cd68c9864d65e49c910c701716e4e94e09f7ce0Chris Wilson
4978dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson		ret = intel_overlay_do_wait_request(overlay, request, true,
498b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson						    intel_overlay_release_old_vid_tail);
4995cd68c9864d65e49c910c701716e4e94e09f7ce0Chris Wilson		if (ret)
5005cd68c9864d65e49c910c701716e4e94e09f7ce0Chris Wilson			return ret;
5015cd68c9864d65e49c910c701716e4e94e09f7ce0Chris Wilson	}
50202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
5035cd68c9864d65e49c910c701716e4e94e09f7ce0Chris Wilson	intel_overlay_release_old_vid_tail(overlay);
50402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return 0;
50502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
50602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
50702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstruct put_image_params {
50802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int format;
50902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	short dst_x;
51002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	short dst_y;
51102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	short dst_w;
51202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	short dst_h;
51302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	short src_w;
51402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	short src_scan_h;
51502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	short src_scan_w;
51602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	short src_h;
51702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	short stride_Y;
51802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	short stride_UV;
51902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int offset_Y;
52002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int offset_U;
52102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int offset_V;
52202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter};
52302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
52402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic int packed_depth_bytes(u32 format)
52502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
52602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	switch (format & I915_OVERLAY_DEPTH_MASK) {
527722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case I915_OVERLAY_YUV422:
528722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		return 4;
529722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case I915_OVERLAY_YUV411:
530722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		/* return 6; not implemented */
531722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	default:
532722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		return -EINVAL;
53302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
53402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
53502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
53602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic int packed_width_bytes(u32 format, short width)
53702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
53802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	switch (format & I915_OVERLAY_DEPTH_MASK) {
539722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case I915_OVERLAY_YUV422:
540722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		return width << 1;
541722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	default:
542722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		return -EINVAL;
54302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
54402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
54502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
54602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic int uv_hsubsampling(u32 format)
54702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
54802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	switch (format & I915_OVERLAY_DEPTH_MASK) {
549722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case I915_OVERLAY_YUV422:
550722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case I915_OVERLAY_YUV420:
551722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		return 2;
552722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case I915_OVERLAY_YUV411:
553722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case I915_OVERLAY_YUV410:
554722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		return 4;
555722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	default:
556722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		return -EINVAL;
55702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
55802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
55902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
56002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic int uv_vsubsampling(u32 format)
56102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
56202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	switch (format & I915_OVERLAY_DEPTH_MASK) {
563722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case I915_OVERLAY_YUV420:
564722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case I915_OVERLAY_YUV410:
565722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		return 2;
566722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case I915_OVERLAY_YUV422:
567722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case I915_OVERLAY_YUV411:
568722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		return 1;
569722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	default:
570722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		return -EINVAL;
57102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
57202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
57302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
57402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic u32 calc_swidthsw(struct drm_device *dev, u32 offset, u32 width)
57502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
57602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	u32 mask, shift, ret;
577a6c45cf013a57e32ddae43dd4ac911eb4a3919fdChris Wilson	if (IS_GEN2(dev)) {
57802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		mask = 0x1f;
57902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		shift = 5;
580a6c45cf013a57e32ddae43dd4ac911eb4a3919fdChris Wilson	} else {
581a6c45cf013a57e32ddae43dd4ac911eb4a3919fdChris Wilson		mask = 0x3f;
582a6c45cf013a57e32ddae43dd4ac911eb4a3919fdChris Wilson		shift = 6;
58302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
58402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	ret = ((offset + width + mask) >> shift) - (offset >> shift);
585a6c45cf013a57e32ddae43dd4ac911eb4a3919fdChris Wilson	if (!IS_GEN2(dev))
58602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		ret <<= 1;
58702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	ret -=1;
58802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return ret << 2;
58902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
59002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
59102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic const u16 y_static_hcoeffs[N_HORIZ_Y_TAPS * N_PHASES] = {
59202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3000, 0xb4a0, 0x1930, 0x1920, 0xb4a0,
59302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3000, 0xb500, 0x19d0, 0x1880, 0xb440,
59402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3000, 0xb540, 0x1a88, 0x2f80, 0xb3e0,
59502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3000, 0xb580, 0x1b30, 0x2e20, 0xb380,
59602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3000, 0xb5c0, 0x1bd8, 0x2cc0, 0xb320,
59702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3020, 0xb5e0, 0x1c60, 0x2b80, 0xb2c0,
59802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3020, 0xb5e0, 0x1cf8, 0x2a20, 0xb260,
59902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3020, 0xb5e0, 0x1d80, 0x28e0, 0xb200,
60002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3020, 0xb5c0, 0x1e08, 0x3f40, 0xb1c0,
60102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3020, 0xb580, 0x1e78, 0x3ce0, 0xb160,
60202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3040, 0xb520, 0x1ed8, 0x3aa0, 0xb120,
60302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3040, 0xb4a0, 0x1f30, 0x3880, 0xb0e0,
60402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3040, 0xb400, 0x1f78, 0x3680, 0xb0a0,
60502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3020, 0xb340, 0x1fb8, 0x34a0, 0xb060,
60602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3020, 0xb240, 0x1fe0, 0x32e0, 0xb040,
60702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3020, 0xb140, 0x1ff8, 0x3160, 0xb020,
608722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	0xb000, 0x3000, 0x0800, 0x3000, 0xb000
609722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson};
610722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson
61102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic const u16 uv_static_hcoeffs[N_HORIZ_UV_TAPS * N_PHASES] = {
61202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3000, 0x1800, 0x1800, 0xb000, 0x18d0, 0x2e60,
61302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0xb000, 0x1990, 0x2ce0, 0xb020, 0x1a68, 0x2b40,
61402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0xb040, 0x1b20, 0x29e0, 0xb060, 0x1bd8, 0x2880,
61502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0xb080, 0x1c88, 0x3e60, 0xb0a0, 0x1d28, 0x3c00,
61602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0xb0c0, 0x1db8, 0x39e0, 0xb0e0, 0x1e40, 0x37e0,
61702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0xb100, 0x1eb8, 0x3620, 0xb100, 0x1f18, 0x34a0,
61802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0xb100, 0x1f68, 0x3360, 0xb0e0, 0x1fa8, 0x3240,
61902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0xb0c0, 0x1fe0, 0x3140, 0xb060, 0x1ff0, 0x30a0,
620722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	0x3000, 0x0800, 0x3000
621722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson};
62202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
62302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic void update_polyphase_filter(struct overlay_registers *regs)
62402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
62502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	memcpy(regs->Y_HCOEFS, y_static_hcoeffs, sizeof(y_static_hcoeffs));
62602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	memcpy(regs->UV_HCOEFS, uv_static_hcoeffs, sizeof(uv_static_hcoeffs));
62702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
62802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
62902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic bool update_scaling_factors(struct intel_overlay *overlay,
63002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				   struct overlay_registers *regs,
63102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				   struct put_image_params *params)
63202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
63302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* fixed point with a 12 bit shift */
63402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	u32 xscale, yscale, xscale_UV, yscale_UV;
63502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define FP_SHIFT 12
63602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define FRACT_MASK 0xfff
63702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	bool scale_changed = false;
63802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int uv_hscale = uv_hsubsampling(params->format);
63902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int uv_vscale = uv_vsubsampling(params->format);
64002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
64102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (params->dst_w > 1)
64202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		xscale = ((params->src_scan_w - 1) << FP_SHIFT)
64302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			/(params->dst_w);
64402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	else
64502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		xscale = 1 << FP_SHIFT;
64602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
64702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (params->dst_h > 1)
64802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		yscale = ((params->src_scan_h - 1) << FP_SHIFT)
64902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			/(params->dst_h);
65002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	else
65102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		yscale = 1 << FP_SHIFT;
65202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
65302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/*if (params->format & I915_OVERLAY_YUV_PLANAR) {*/
654722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	xscale_UV = xscale/uv_hscale;
655722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	yscale_UV = yscale/uv_vscale;
656722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	/* make the Y scale to UV scale ratio an exact multiply */
657722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	xscale = xscale_UV * uv_hscale;
658722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	yscale = yscale_UV * uv_vscale;
65902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/*} else {
660722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	  xscale_UV = 0;
661722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	  yscale_UV = 0;
662722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	  }*/
66302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
66402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (xscale != overlay->old_xscale || yscale != overlay->old_yscale)
66502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		scale_changed = true;
66602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	overlay->old_xscale = xscale;
66702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	overlay->old_yscale = yscale;
66802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
669722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	regs->YRGBSCALE = (((yscale & FRACT_MASK) << 20) |
670722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			   ((xscale >> FP_SHIFT)  << 16) |
671722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			   ((xscale & FRACT_MASK) << 3));
672722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson
673722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	regs->UVSCALE = (((yscale_UV & FRACT_MASK) << 20) |
674722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			 ((xscale_UV >> FP_SHIFT)  << 16) |
675722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			 ((xscale_UV & FRACT_MASK) << 3));
676722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson
677722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	regs->UVSCALEV = ((((yscale    >> FP_SHIFT) << 16) |
678722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			   ((yscale_UV >> FP_SHIFT) << 0)));
67902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
68002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (scale_changed)
68102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		update_polyphase_filter(regs);
68202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
68302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return scale_changed;
68402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
68502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
68602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic void update_colorkey(struct intel_overlay *overlay,
68702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			    struct overlay_registers *regs)
68802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
68902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	u32 key = overlay->color_key;
6906ba3ddd9838f5e4d6ac7c6dce95648d205e11bffChris Wilson
69102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	switch (overlay->crtc->base.fb->bits_per_pixel) {
692722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case 8:
693722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		regs->DCLRKV = 0;
694722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		regs->DCLRKM = CLK_RGB8I_MASK | DST_KEY_ENABLE;
6956ba3ddd9838f5e4d6ac7c6dce95648d205e11bffChris Wilson		break;
6966ba3ddd9838f5e4d6ac7c6dce95648d205e11bffChris Wilson
697722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case 16:
698722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		if (overlay->crtc->base.fb->depth == 15) {
699722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			regs->DCLRKV = RGB15_TO_COLORKEY(key);
700722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			regs->DCLRKM = CLK_RGB15_MASK | DST_KEY_ENABLE;
701722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		} else {
702722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			regs->DCLRKV = RGB16_TO_COLORKEY(key);
703722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			regs->DCLRKM = CLK_RGB16_MASK | DST_KEY_ENABLE;
704722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		}
7056ba3ddd9838f5e4d6ac7c6dce95648d205e11bffChris Wilson		break;
7066ba3ddd9838f5e4d6ac7c6dce95648d205e11bffChris Wilson
707722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case 24:
708722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case 32:
709722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		regs->DCLRKV = key;
710722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		regs->DCLRKM = CLK_RGB24_MASK | DST_KEY_ENABLE;
7116ba3ddd9838f5e4d6ac7c6dce95648d205e11bffChris Wilson		break;
71202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
71302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
71402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
71502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic u32 overlay_cmd_reg(struct put_image_params *params)
71602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
71702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	u32 cmd = OCMD_ENABLE | OCMD_BUF_TYPE_FRAME | OCMD_BUFFER0;
71802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
71902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (params->format & I915_OVERLAY_YUV_PLANAR) {
72002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		switch (params->format & I915_OVERLAY_DEPTH_MASK) {
721722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		case I915_OVERLAY_YUV422:
722722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			cmd |= OCMD_YUV_422_PLANAR;
723722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			break;
724722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		case I915_OVERLAY_YUV420:
725722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			cmd |= OCMD_YUV_420_PLANAR;
726722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			break;
727722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		case I915_OVERLAY_YUV411:
728722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		case I915_OVERLAY_YUV410:
729722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			cmd |= OCMD_YUV_410_PLANAR;
730722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			break;
73102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		}
73202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	} else { /* YUV packed */
73302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		switch (params->format & I915_OVERLAY_DEPTH_MASK) {
734722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		case I915_OVERLAY_YUV422:
735722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			cmd |= OCMD_YUV_422_PACKED;
736722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			break;
737722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		case I915_OVERLAY_YUV411:
738722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			cmd |= OCMD_YUV_411_PACKED;
739722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			break;
74002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		}
74102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
74202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		switch (params->format & I915_OVERLAY_SWAP_MASK) {
743722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		case I915_OVERLAY_NO_SWAP:
744722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			break;
745722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		case I915_OVERLAY_UV_SWAP:
746722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			cmd |= OCMD_UV_SWAP;
747722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			break;
748722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		case I915_OVERLAY_Y_SWAP:
749722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			cmd |= OCMD_Y_SWAP;
750722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			break;
751722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		case I915_OVERLAY_Y_AND_UV_SWAP:
752722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			cmd |= OCMD_Y_AND_UV_SWAP;
753722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			break;
75402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		}
75502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
75602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
75702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return cmd;
75802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
75902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
7605fe82c5ee1ba2d04183c376038c5d233a0311ec9Chris Wilsonstatic int intel_overlay_do_put_image(struct intel_overlay *overlay,
7615fe82c5ee1ba2d04183c376038c5d233a0311ec9Chris Wilson				      struct drm_gem_object *new_bo,
7625fe82c5ee1ba2d04183c376038c5d233a0311ec9Chris Wilson				      struct put_image_params *params)
76302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
76402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int ret, tmp_width;
76502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct overlay_registers *regs;
76602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	bool scale_changed = false;
76723010e43b353c2cdc9725cbedc7e364708039bf7Daniel Vetter	struct drm_i915_gem_object *bo_priv = to_intel_bo(new_bo);
76802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct drm_device *dev = overlay->dev;
76902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
77002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	BUG_ON(!mutex_is_locked(&dev->struct_mutex));
77102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	BUG_ON(!mutex_is_locked(&dev->mode_config.mutex));
77202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	BUG_ON(!overlay);
77302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
77402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	ret = intel_overlay_release_old_vid(overlay);
77502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (ret != 0)
77602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return ret;
77702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
77802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	ret = i915_gem_object_pin(new_bo, PAGE_SIZE);
77902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (ret != 0)
78002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return ret;
78102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
78202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	ret = i915_gem_object_set_to_gtt_domain(new_bo, 0);
78302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (ret != 0)
78402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		goto out_unpin;
78502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
78602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!overlay->active) {
7878d74f656dd78ae1ba813389cd46197c6329696bcChris Wilson		regs = intel_overlay_map_regs(overlay);
78802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		if (!regs) {
78902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			ret = -ENOMEM;
79002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			goto out_unpin;
79102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		}
79202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		regs->OCONFIG = OCONF_CC_OUT_8BIT;
793a6c45cf013a57e32ddae43dd4ac911eb4a3919fdChris Wilson		if (IS_GEN4(overlay->dev))
79402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			regs->OCONFIG |= OCONF_CSC_MODE_BT709;
79502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		regs->OCONFIG |= overlay->crtc->pipe == 0 ?
79602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			OCONF_PIPE_A : OCONF_PIPE_B;
7979bb2ff731b32c023e7a502efdc0dee46157290d5Chris Wilson		intel_overlay_unmap_regs(overlay, regs);
79802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
79902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		ret = intel_overlay_on(overlay);
80002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		if (ret != 0)
80102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			goto out_unpin;
80202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
80302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
8048d74f656dd78ae1ba813389cd46197c6329696bcChris Wilson	regs = intel_overlay_map_regs(overlay);
80502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!regs) {
80602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		ret = -ENOMEM;
80702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		goto out_unpin;
80802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
80902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
81002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	regs->DWINPOS = (params->dst_y << 16) | params->dst_x;
81102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	regs->DWINSZ = (params->dst_h << 16) | params->dst_w;
81202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
81302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (params->format & I915_OVERLAY_YUV_PACKED)
81402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		tmp_width = packed_width_bytes(params->format, params->src_w);
81502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	else
81602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		tmp_width = params->src_w;
81702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
81802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	regs->SWIDTH = params->src_w;
81902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	regs->SWIDTHSW = calc_swidthsw(overlay->dev,
820722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson				       params->offset_Y, tmp_width);
82102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	regs->SHEIGHT = params->src_h;
82202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	regs->OBUF_0Y = bo_priv->gtt_offset + params-> offset_Y;
82302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	regs->OSTRIDE = params->stride_Y;
82402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
82502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (params->format & I915_OVERLAY_YUV_PLANAR) {
82602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		int uv_hscale = uv_hsubsampling(params->format);
82702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		int uv_vscale = uv_vsubsampling(params->format);
82802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		u32 tmp_U, tmp_V;
82902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		regs->SWIDTH |= (params->src_w/uv_hscale) << 16;
83002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		tmp_U = calc_swidthsw(overlay->dev, params->offset_U,
831722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson				      params->src_w/uv_hscale);
83202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		tmp_V = calc_swidthsw(overlay->dev, params->offset_V,
833722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson				      params->src_w/uv_hscale);
83402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		regs->SWIDTHSW |= max_t(u32, tmp_U, tmp_V) << 16;
83502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		regs->SHEIGHT |= (params->src_h/uv_vscale) << 16;
83602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		regs->OBUF_0U = bo_priv->gtt_offset + params->offset_U;
83702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		regs->OBUF_0V = bo_priv->gtt_offset + params->offset_V;
83802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		regs->OSTRIDE |= params->stride_UV << 16;
83902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
84002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
84102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	scale_changed = update_scaling_factors(overlay, regs, params);
84202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
84302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	update_colorkey(overlay, regs);
84402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
84502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	regs->OCMD = overlay_cmd_reg(params);
84602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
8479bb2ff731b32c023e7a502efdc0dee46157290d5Chris Wilson	intel_overlay_unmap_regs(overlay, regs);
84802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
8498dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson	ret = intel_overlay_continue(overlay, scale_changed);
8508dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson	if (ret)
8518dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson		goto out_unpin;
85202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
85302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	overlay->old_vid_bo = overlay->vid_bo;
85423010e43b353c2cdc9725cbedc7e364708039bf7Daniel Vetter	overlay->vid_bo = to_intel_bo(new_bo);
85502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
85602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return 0;
85702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
85802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterout_unpin:
85902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	i915_gem_object_unpin(new_bo);
86002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return ret;
86102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
86202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
8635dcdbcb06badbdf2faa698bf3198e421a1e12840Chris Wilsonint intel_overlay_switch_off(struct intel_overlay *overlay,
8645dcdbcb06badbdf2faa698bf3198e421a1e12840Chris Wilson			     bool interruptible)
86502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
86602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct overlay_registers *regs;
86702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct drm_device *dev = overlay->dev;
8685dcdbcb06badbdf2faa698bf3198e421a1e12840Chris Wilson	int ret;
86902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
87002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	BUG_ON(!mutex_is_locked(&dev->struct_mutex));
87102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	BUG_ON(!mutex_is_locked(&dev->mode_config.mutex));
87202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
873b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson	ret = intel_overlay_recover_from_interrupt(overlay, interruptible);
874b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson	if (ret != 0)
875b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson		return ret;
8769bedb9743fd906e4160468663ee6e1bbdc4412b8Daniel Vetter
87702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!overlay->active)
87802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return 0;
87902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
88002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	ret = intel_overlay_release_old_vid(overlay);
88102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (ret != 0)
88202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return ret;
88302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
8848d74f656dd78ae1ba813389cd46197c6329696bcChris Wilson	regs = intel_overlay_map_regs(overlay);
88502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	regs->OCMD = 0;
8869bb2ff731b32c023e7a502efdc0dee46157290d5Chris Wilson	intel_overlay_unmap_regs(overlay, regs);
88702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
8885dcdbcb06badbdf2faa698bf3198e421a1e12840Chris Wilson	ret = intel_overlay_off(overlay, interruptible);
88903f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	if (ret != 0)
89003f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter		return ret;
89103f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter
89212ca45fea91cfbb09df828bea958b47348caee6dDaniel Vetter	intel_overlay_off_tail(overlay);
89302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return 0;
89402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
89502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
89602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic int check_overlay_possible_on_crtc(struct intel_overlay *overlay,
89702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter					  struct intel_crtc *crtc)
89802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
899722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	drm_i915_private_t *dev_priv = overlay->dev->dev_private;
90002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
901f7abfe8b281991c66406c42c1a6c6c9ee0daa0ffChris Wilson	if (!crtc->active)
90202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EINVAL;
90302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
90402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* can't use the overlay with double wide pipe */
905a6c45cf013a57e32ddae43dd4ac911eb4a3919fdChris Wilson	if (INTEL_INFO(overlay->dev)->gen < 4 &&
906f7abfe8b281991c66406c42c1a6c6c9ee0daa0ffChris Wilson	    (I915_READ(PIPECONF(crtc->pipe)) & (PIPECONF_DOUBLE_WIDE | PIPECONF_ENABLE)) != PIPECONF_ENABLE)
90702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EINVAL;
90802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
90902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return 0;
91002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
91102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
91202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic void update_pfit_vscale_ratio(struct intel_overlay *overlay)
91302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
91402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct drm_device *dev = overlay->dev;
915722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	drm_i915_private_t *dev_priv = dev->dev_private;
91602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	u32 pfit_control = I915_READ(PFIT_CONTROL);
917446d2183af68c0fd2772f5ef97a033efe69904a5Chris Wilson	u32 ratio;
91802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
91902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* XXX: This is not the same logic as in the xorg driver, but more in
920446d2183af68c0fd2772f5ef97a033efe69904a5Chris Wilson	 * line with the intel documentation for the i965
921446d2183af68c0fd2772f5ef97a033efe69904a5Chris Wilson	 */
922a6c45cf013a57e32ddae43dd4ac911eb4a3919fdChris Wilson	if (INTEL_INFO(dev)->gen >= 4) {
923a6c45cf013a57e32ddae43dd4ac911eb4a3919fdChris Wilson	       	/* on i965 use the PGM reg to read out the autoscaler values */
924a6c45cf013a57e32ddae43dd4ac911eb4a3919fdChris Wilson		ratio = I915_READ(PFIT_PGM_RATIOS) >> PFIT_VERT_SCALE_SHIFT_965;
925a6c45cf013a57e32ddae43dd4ac911eb4a3919fdChris Wilson	} else {
926446d2183af68c0fd2772f5ef97a033efe69904a5Chris Wilson		if (pfit_control & VERT_AUTO_SCALE)
927446d2183af68c0fd2772f5ef97a033efe69904a5Chris Wilson			ratio = I915_READ(PFIT_AUTO_RATIOS);
92802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		else
929446d2183af68c0fd2772f5ef97a033efe69904a5Chris Wilson			ratio = I915_READ(PFIT_PGM_RATIOS);
930446d2183af68c0fd2772f5ef97a033efe69904a5Chris Wilson		ratio >>= PFIT_VERT_SCALE_SHIFT;
93102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
93202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
93302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	overlay->pfit_vscale_ratio = ratio;
93402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
93502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
93602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic int check_overlay_dst(struct intel_overlay *overlay,
93702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			     struct drm_intel_overlay_put_image *rec)
93802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
93902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct drm_display_mode *mode = &overlay->crtc->base.mode;
94002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
941722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	if (rec->dst_x < mode->crtc_hdisplay &&
942722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	    rec->dst_x + rec->dst_width <= mode->crtc_hdisplay &&
943722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	    rec->dst_y < mode->crtc_vdisplay &&
944722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	    rec->dst_y + rec->dst_height <= mode->crtc_vdisplay)
94502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return 0;
94602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	else
94702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EINVAL;
94802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
94902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
95002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic int check_overlay_scaling(struct put_image_params *rec)
95102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
95202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	u32 tmp;
95302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
95402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* downscaling limit is 8.0 */
95502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	tmp = ((rec->src_scan_h << 16) / rec->dst_h) >> 16;
95602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (tmp > 7)
95702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EINVAL;
95802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	tmp = ((rec->src_scan_w << 16) / rec->dst_w) >> 16;
95902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (tmp > 7)
96002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EINVAL;
96102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
96202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return 0;
96302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
96402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
96502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic int check_overlay_src(struct drm_device *dev,
96602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			     struct drm_intel_overlay_put_image *rec,
96702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			     struct drm_gem_object *new_bo)
96802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
96902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int uv_hscale = uv_hsubsampling(rec->flags);
97002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int uv_vscale = uv_vsubsampling(rec->flags);
9719f7c3f442bb7c0d0a0ed25cc287932450a1f2babChris Wilson	u32 stride_mask, depth, tmp;
97202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
97302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* check src dimensions */
97402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (IS_845G(dev) || IS_I830(dev)) {
975722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		if (rec->src_height > IMAGE_MAX_HEIGHT_LEGACY ||
9769f7c3f442bb7c0d0a0ed25cc287932450a1f2babChris Wilson		    rec->src_width  > IMAGE_MAX_WIDTH_LEGACY)
97702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			return -EINVAL;
97802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	} else {
979722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		if (rec->src_height > IMAGE_MAX_HEIGHT ||
9809f7c3f442bb7c0d0a0ed25cc287932450a1f2babChris Wilson		    rec->src_width  > IMAGE_MAX_WIDTH)
98102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			return -EINVAL;
98202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
9839f7c3f442bb7c0d0a0ed25cc287932450a1f2babChris Wilson
98402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* better safe than sorry, use 4 as the maximal subsampling ratio */
985722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	if (rec->src_height < N_VERT_Y_TAPS*4 ||
9869f7c3f442bb7c0d0a0ed25cc287932450a1f2babChris Wilson	    rec->src_width  < N_HORIZ_Y_TAPS*4)
98702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EINVAL;
98802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
989a1efd14a99483a4fb9308902397ed86b69454c99Chris Wilson	/* check alignment constraints */
99002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	switch (rec->flags & I915_OVERLAY_TYPE_MASK) {
991722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case I915_OVERLAY_RGB:
992722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		/* not implemented */
993722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		return -EINVAL;
9949f7c3f442bb7c0d0a0ed25cc287932450a1f2babChris Wilson
995722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case I915_OVERLAY_YUV_PACKED:
996722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		if (uv_vscale != 1)
99702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			return -EINVAL;
9989f7c3f442bb7c0d0a0ed25cc287932450a1f2babChris Wilson
9999f7c3f442bb7c0d0a0ed25cc287932450a1f2babChris Wilson		depth = packed_depth_bytes(rec->flags);
1000722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		if (depth < 0)
1001722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			return depth;
10029f7c3f442bb7c0d0a0ed25cc287932450a1f2babChris Wilson
1003722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		/* ignore UV planes */
1004722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		rec->stride_UV = 0;
1005722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		rec->offset_U = 0;
1006722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		rec->offset_V = 0;
1007722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		/* check pixel alignment */
1008722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		if (rec->offset_Y % depth)
1009722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			return -EINVAL;
1010722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		break;
10119f7c3f442bb7c0d0a0ed25cc287932450a1f2babChris Wilson
1012722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case I915_OVERLAY_YUV_PLANAR:
1013722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		if (uv_vscale < 0 || uv_hscale < 0)
101402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			return -EINVAL;
1015722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		/* no offset restrictions for planar formats */
1016722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		break;
10179f7c3f442bb7c0d0a0ed25cc287932450a1f2babChris Wilson
1018722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	default:
1019722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		return -EINVAL;
102002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
102102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
102202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (rec->src_width % uv_hscale)
102302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EINVAL;
102402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
102502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* stride checking */
1026a1efd14a99483a4fb9308902397ed86b69454c99Chris Wilson	if (IS_I830(dev) || IS_845G(dev))
1027a1efd14a99483a4fb9308902397ed86b69454c99Chris Wilson		stride_mask = 255;
1028a1efd14a99483a4fb9308902397ed86b69454c99Chris Wilson	else
1029a1efd14a99483a4fb9308902397ed86b69454c99Chris Wilson		stride_mask = 63;
103002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
103102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (rec->stride_Y & stride_mask || rec->stride_UV & stride_mask)
103202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EINVAL;
1033a6c45cf013a57e32ddae43dd4ac911eb4a3919fdChris Wilson	if (IS_GEN4(dev) && rec->stride_Y < 512)
103402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EINVAL;
103502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
103602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	tmp = (rec->flags & I915_OVERLAY_TYPE_MASK) == I915_OVERLAY_YUV_PLANAR ?
10379f7c3f442bb7c0d0a0ed25cc287932450a1f2babChris Wilson		4096 : 8192;
10389f7c3f442bb7c0d0a0ed25cc287932450a1f2babChris Wilson	if (rec->stride_Y > tmp || rec->stride_UV > 2*1024)
103902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EINVAL;
104002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
104102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* check buffer dimensions */
104202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	switch (rec->flags & I915_OVERLAY_TYPE_MASK) {
1043722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case I915_OVERLAY_RGB:
1044722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case I915_OVERLAY_YUV_PACKED:
1045722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		/* always 4 Y values per depth pixels */
1046722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		if (packed_width_bytes(rec->flags, rec->src_width) > rec->stride_Y)
1047722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			return -EINVAL;
1048722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson
1049722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		tmp = rec->stride_Y*rec->src_height;
1050722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		if (rec->offset_Y + tmp > new_bo->size)
1051722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			return -EINVAL;
1052722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		break;
1053722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson
1054722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case I915_OVERLAY_YUV_PLANAR:
1055722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		if (rec->src_width > rec->stride_Y)
1056722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			return -EINVAL;
1057722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		if (rec->src_width/uv_hscale > rec->stride_UV)
1058722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			return -EINVAL;
1059722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson
10609f7c3f442bb7c0d0a0ed25cc287932450a1f2babChris Wilson		tmp = rec->stride_Y * rec->src_height;
1061722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		if (rec->offset_Y + tmp > new_bo->size)
1062722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			return -EINVAL;
10639f7c3f442bb7c0d0a0ed25cc287932450a1f2babChris Wilson
10649f7c3f442bb7c0d0a0ed25cc287932450a1f2babChris Wilson		tmp = rec->stride_UV * (rec->src_height / uv_vscale);
1065722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		if (rec->offset_U + tmp > new_bo->size ||
1066722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		    rec->offset_V + tmp > new_bo->size)
1067722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			return -EINVAL;
1068722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		break;
106902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
107002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
107102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return 0;
107202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
107302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
1074e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson/**
1075e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson * Return the pipe currently connected to the panel fitter,
1076e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson * or -1 if the panel fitter is not present or not in use
1077e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson */
1078e9e331a8abeece1565d383510ed985945132ffe3Chris Wilsonstatic int intel_panel_fitter_pipe(struct drm_device *dev)
1079e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson{
1080e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson	struct drm_i915_private *dev_priv = dev->dev_private;
1081e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson	u32  pfit_control;
1082e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson
1083e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson	/* i830 doesn't have a panel fitter */
1084e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson	if (IS_I830(dev))
1085e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson		return -1;
1086e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson
1087e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson	pfit_control = I915_READ(PFIT_CONTROL);
1088e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson
1089e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson	/* See if the panel fitter is in use */
1090e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson	if ((pfit_control & PFIT_ENABLE) == 0)
1091e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson		return -1;
1092e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson
1093e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson	/* 965 can place panel fitter on either pipe */
1094a6c45cf013a57e32ddae43dd4ac911eb4a3919fdChris Wilson	if (IS_GEN4(dev))
1095e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson		return (pfit_control >> 29) & 0x3;
1096e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson
1097e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson	/* older chips can only use pipe 1 */
1098e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson	return 1;
1099e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson}
1100e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson
110102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterint intel_overlay_put_image(struct drm_device *dev, void *data,
110202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter                            struct drm_file *file_priv)
110302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
110402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct drm_intel_overlay_put_image *put_image_rec = data;
110502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	drm_i915_private_t *dev_priv = dev->dev_private;
110602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct intel_overlay *overlay;
110702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct drm_mode_object *drmmode_obj;
110802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct intel_crtc *crtc;
110902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct drm_gem_object *new_bo;
111002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct put_image_params *params;
111102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int ret;
111202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
111302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!dev_priv) {
111402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		DRM_ERROR("called with no initialization\n");
111502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EINVAL;
111602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
111702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
111802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	overlay = dev_priv->overlay;
111902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!overlay) {
112002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		DRM_DEBUG("userspace bug: no overlay\n");
112102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -ENODEV;
112202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
112302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
112402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!(put_image_rec->flags & I915_OVERLAY_ENABLE)) {
112502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		mutex_lock(&dev->mode_config.mutex);
112602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		mutex_lock(&dev->struct_mutex);
112702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
11285dcdbcb06badbdf2faa698bf3198e421a1e12840Chris Wilson		ret = intel_overlay_switch_off(overlay, true);
112902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
113002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		mutex_unlock(&dev->struct_mutex);
113102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		mutex_unlock(&dev->mode_config.mutex);
113202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
113302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return ret;
113402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
113502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
113602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	params = kmalloc(sizeof(struct put_image_params), GFP_KERNEL);
113702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!params)
113802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -ENOMEM;
113902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
114002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	drmmode_obj = drm_mode_object_find(dev, put_image_rec->crtc_id,
1141722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson					   DRM_MODE_OBJECT_CRTC);
1142915a428e43acfd05e4ffeaf40549b0cf163eebe2Dan Carpenter	if (!drmmode_obj) {
1143915a428e43acfd05e4ffeaf40549b0cf163eebe2Dan Carpenter		ret = -ENOENT;
1144915a428e43acfd05e4ffeaf40549b0cf163eebe2Dan Carpenter		goto out_free;
1145915a428e43acfd05e4ffeaf40549b0cf163eebe2Dan Carpenter	}
114602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	crtc = to_intel_crtc(obj_to_crtc(drmmode_obj));
114702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
114802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	new_bo = drm_gem_object_lookup(dev, file_priv,
1149722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson				       put_image_rec->bo_handle);
1150915a428e43acfd05e4ffeaf40549b0cf163eebe2Dan Carpenter	if (!new_bo) {
1151915a428e43acfd05e4ffeaf40549b0cf163eebe2Dan Carpenter		ret = -ENOENT;
1152915a428e43acfd05e4ffeaf40549b0cf163eebe2Dan Carpenter		goto out_free;
1153915a428e43acfd05e4ffeaf40549b0cf163eebe2Dan Carpenter	}
115402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
115502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	mutex_lock(&dev->mode_config.mutex);
115602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	mutex_lock(&dev->struct_mutex);
115702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
1158b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson	ret = intel_overlay_recover_from_interrupt(overlay, true);
1159b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson	if (ret != 0)
1160b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson		goto out_unlock;
116103f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter
116202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (overlay->crtc != crtc) {
116302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		struct drm_display_mode *mode = &crtc->base.mode;
11645dcdbcb06badbdf2faa698bf3198e421a1e12840Chris Wilson		ret = intel_overlay_switch_off(overlay, true);
116502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		if (ret != 0)
116602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			goto out_unlock;
116702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
116802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		ret = check_overlay_possible_on_crtc(overlay, crtc);
116902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		if (ret != 0)
117002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			goto out_unlock;
117102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
117202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		overlay->crtc = crtc;
117302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		crtc->overlay = overlay;
117402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
1175e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson		/* line too wide, i.e. one-line-mode */
1176e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson		if (mode->hdisplay > 1024 &&
1177e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson		    intel_panel_fitter_pipe(dev) == crtc->pipe) {
117802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			overlay->pfit_active = 1;
117902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			update_pfit_vscale_ratio(overlay);
118002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		} else
118102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			overlay->pfit_active = 0;
118202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
118302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
118402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	ret = check_overlay_dst(overlay, put_image_rec);
118502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (ret != 0)
118602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		goto out_unlock;
118702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
118802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (overlay->pfit_active) {
118902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		params->dst_y = ((((u32)put_image_rec->dst_y) << 12) /
1190722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson				 overlay->pfit_vscale_ratio);
119102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		/* shifting right rounds downwards, so add 1 */
119202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		params->dst_h = ((((u32)put_image_rec->dst_height) << 12) /
1193722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson				 overlay->pfit_vscale_ratio) + 1;
119402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	} else {
119502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		params->dst_y = put_image_rec->dst_y;
119602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		params->dst_h = put_image_rec->dst_height;
119702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
119802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	params->dst_x = put_image_rec->dst_x;
119902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	params->dst_w = put_image_rec->dst_width;
120002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
120102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	params->src_w = put_image_rec->src_width;
120202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	params->src_h = put_image_rec->src_height;
120302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	params->src_scan_w = put_image_rec->src_scan_width;
120402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	params->src_scan_h = put_image_rec->src_scan_height;
1205722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	if (params->src_scan_h > params->src_h ||
1206722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	    params->src_scan_w > params->src_w) {
120702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		ret = -EINVAL;
120802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		goto out_unlock;
120902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
121002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
121102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	ret = check_overlay_src(dev, put_image_rec, new_bo);
121202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (ret != 0)
121302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		goto out_unlock;
121402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	params->format = put_image_rec->flags & ~I915_OVERLAY_FLAGS_MASK;
121502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	params->stride_Y = put_image_rec->stride_Y;
121602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	params->stride_UV = put_image_rec->stride_UV;
121702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	params->offset_Y = put_image_rec->offset_Y;
121802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	params->offset_U = put_image_rec->offset_U;
121902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	params->offset_V = put_image_rec->offset_V;
122002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
122102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* Check scaling after src size to prevent a divide-by-zero. */
122202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	ret = check_overlay_scaling(params);
122302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (ret != 0)
122402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		goto out_unlock;
122502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
122602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	ret = intel_overlay_do_put_image(overlay, new_bo, params);
122702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (ret != 0)
122802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		goto out_unlock;
122902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
123002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	mutex_unlock(&dev->struct_mutex);
123102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	mutex_unlock(&dev->mode_config.mutex);
123202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
123302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	kfree(params);
123402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
123502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return 0;
123602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
123702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterout_unlock:
123802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	mutex_unlock(&dev->struct_mutex);
123902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	mutex_unlock(&dev->mode_config.mutex);
1240bc9025bdc4e2b591734cca17697093845007b63dLuca Barbieri	drm_gem_object_unreference_unlocked(new_bo);
1241915a428e43acfd05e4ffeaf40549b0cf163eebe2Dan Carpenterout_free:
124202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	kfree(params);
124302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
124402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return ret;
124502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
124602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
124702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic void update_reg_attrs(struct intel_overlay *overlay,
124802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			     struct overlay_registers *regs)
124902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
125002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	regs->OCLRC0 = (overlay->contrast << 18) | (overlay->brightness & 0xff);
125102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	regs->OCLRC1 = overlay->saturation;
125202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
125302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
125402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic bool check_gamma_bounds(u32 gamma1, u32 gamma2)
125502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
125602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int i;
125702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
125802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (gamma1 & 0xff000000 || gamma2 & 0xff000000)
125902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return false;
126002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
126102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	for (i = 0; i < 3; i++) {
1262722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		if (((gamma1 >> i*8) & 0xff) >= ((gamma2 >> i*8) & 0xff))
126302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			return false;
126402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
126502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
126602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return true;
126702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
126802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
126902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic bool check_gamma5_errata(u32 gamma5)
127002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
127102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int i;
127202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
127302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	for (i = 0; i < 3; i++) {
127402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		if (((gamma5 >> i*8) & 0xff) == 0x80)
127502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			return false;
127602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
127702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
127802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return true;
127902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
128002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
128102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic int check_gamma(struct drm_intel_overlay_attrs *attrs)
128202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
1283722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	if (!check_gamma_bounds(0, attrs->gamma0) ||
1284722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	    !check_gamma_bounds(attrs->gamma0, attrs->gamma1) ||
1285722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	    !check_gamma_bounds(attrs->gamma1, attrs->gamma2) ||
1286722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	    !check_gamma_bounds(attrs->gamma2, attrs->gamma3) ||
1287722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	    !check_gamma_bounds(attrs->gamma3, attrs->gamma4) ||
1288722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	    !check_gamma_bounds(attrs->gamma4, attrs->gamma5) ||
1289722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	    !check_gamma_bounds(attrs->gamma5, 0x00ffffff))
129002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EINVAL;
1291722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson
129202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!check_gamma5_errata(attrs->gamma5))
129302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EINVAL;
1294722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson
129502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return 0;
129602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
129702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
129802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterint intel_overlay_attrs(struct drm_device *dev, void *data,
129902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter                        struct drm_file *file_priv)
130002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
130102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct drm_intel_overlay_attrs *attrs = data;
130202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter        drm_i915_private_t *dev_priv = dev->dev_private;
130302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct intel_overlay *overlay;
130402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct overlay_registers *regs;
130502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int ret;
130602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
130702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!dev_priv) {
130802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		DRM_ERROR("called with no initialization\n");
130902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EINVAL;
131002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
131102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
131202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	overlay = dev_priv->overlay;
131302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!overlay) {
131402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		DRM_DEBUG("userspace bug: no overlay\n");
131502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -ENODEV;
131602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
131702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
131802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	mutex_lock(&dev->mode_config.mutex);
131902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	mutex_lock(&dev->struct_mutex);
132002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
132160fc332cb5ab19e5a86d696b210df65814b2ad8aChris Wilson	ret = -EINVAL;
132202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!(attrs->flags & I915_OVERLAY_UPDATE_ATTRS)) {
132360fc332cb5ab19e5a86d696b210df65814b2ad8aChris Wilson		attrs->color_key  = overlay->color_key;
132402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		attrs->brightness = overlay->brightness;
132560fc332cb5ab19e5a86d696b210df65814b2ad8aChris Wilson		attrs->contrast   = overlay->contrast;
132602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		attrs->saturation = overlay->saturation;
132702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
1328a6c45cf013a57e32ddae43dd4ac911eb4a3919fdChris Wilson		if (!IS_GEN2(dev)) {
132902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			attrs->gamma0 = I915_READ(OGAMC0);
133002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			attrs->gamma1 = I915_READ(OGAMC1);
133102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			attrs->gamma2 = I915_READ(OGAMC2);
133202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			attrs->gamma3 = I915_READ(OGAMC3);
133302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			attrs->gamma4 = I915_READ(OGAMC4);
133402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			attrs->gamma5 = I915_READ(OGAMC5);
133502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		}
133602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	} else {
133760fc332cb5ab19e5a86d696b210df65814b2ad8aChris Wilson		if (attrs->brightness < -128 || attrs->brightness > 127)
133802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			goto out_unlock;
133960fc332cb5ab19e5a86d696b210df65814b2ad8aChris Wilson		if (attrs->contrast > 255)
134002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			goto out_unlock;
134160fc332cb5ab19e5a86d696b210df65814b2ad8aChris Wilson		if (attrs->saturation > 1023)
134202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			goto out_unlock;
134302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
134460fc332cb5ab19e5a86d696b210df65814b2ad8aChris Wilson		overlay->color_key  = attrs->color_key;
134560fc332cb5ab19e5a86d696b210df65814b2ad8aChris Wilson		overlay->brightness = attrs->brightness;
134660fc332cb5ab19e5a86d696b210df65814b2ad8aChris Wilson		overlay->contrast   = attrs->contrast;
134760fc332cb5ab19e5a86d696b210df65814b2ad8aChris Wilson		overlay->saturation = attrs->saturation;
134802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
13498d74f656dd78ae1ba813389cd46197c6329696bcChris Wilson		regs = intel_overlay_map_regs(overlay);
135002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		if (!regs) {
135102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			ret = -ENOMEM;
135202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			goto out_unlock;
135302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		}
135402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
135502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		update_reg_attrs(overlay, regs);
135602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
13579bb2ff731b32c023e7a502efdc0dee46157290d5Chris Wilson		intel_overlay_unmap_regs(overlay, regs);
135802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
135902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		if (attrs->flags & I915_OVERLAY_UPDATE_GAMMA) {
1360a6c45cf013a57e32ddae43dd4ac911eb4a3919fdChris Wilson			if (IS_GEN2(dev))
136102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				goto out_unlock;
136202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
136302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			if (overlay->active) {
136402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				ret = -EBUSY;
136502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				goto out_unlock;
136602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			}
136702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
136802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			ret = check_gamma(attrs);
136960fc332cb5ab19e5a86d696b210df65814b2ad8aChris Wilson			if (ret)
137002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				goto out_unlock;
137102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
137202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			I915_WRITE(OGAMC0, attrs->gamma0);
137302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			I915_WRITE(OGAMC1, attrs->gamma1);
137402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			I915_WRITE(OGAMC2, attrs->gamma2);
137502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			I915_WRITE(OGAMC3, attrs->gamma3);
137602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			I915_WRITE(OGAMC4, attrs->gamma4);
137702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			I915_WRITE(OGAMC5, attrs->gamma5);
137802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		}
137902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
138002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
138160fc332cb5ab19e5a86d696b210df65814b2ad8aChris Wilson	ret = 0;
138202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterout_unlock:
138302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	mutex_unlock(&dev->struct_mutex);
138402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	mutex_unlock(&dev->mode_config.mutex);
138502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
138602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return ret;
138702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
138802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
138902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vettervoid intel_setup_overlay(struct drm_device *dev)
139002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
139102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter        drm_i915_private_t *dev_priv = dev->dev_private;
139202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct intel_overlay *overlay;
139302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct drm_gem_object *reg_bo;
139402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct overlay_registers *regs;
139502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int ret;
139602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
139731578148b2c62612f9516fdcf5ebb64ab32ed12dChris Wilson	if (!HAS_OVERLAY(dev))
139802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return;
139902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
140002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	overlay = kzalloc(sizeof(struct intel_overlay), GFP_KERNEL);
140102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!overlay)
140202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return;
140302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	overlay->dev = dev;
140402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
1405ac52bc56de25535a907ef07f8755f1387b89b0f5Daniel Vetter	reg_bo = i915_gem_alloc_object(dev, PAGE_SIZE);
140602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!reg_bo)
140702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		goto out_free;
140823010e43b353c2cdc9725cbedc7e364708039bf7Daniel Vetter	overlay->reg_bo = to_intel_bo(reg_bo);
140902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
141031578148b2c62612f9516fdcf5ebb64ab32ed12dChris Wilson	if (OVERLAY_NEEDS_PHYSICAL(dev)) {
141102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		ret = i915_gem_attach_phys_object(dev, reg_bo,
14126eeefaf3c86b8937db8ad930c48bfb592fc5e32eChris Wilson						  I915_GEM_PHYS_OVERLAY_REGS,
1413a29301288f1840bdf9c5456da9cd7c944436edd5Chris Wilson						  PAGE_SIZE);
141402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter                if (ret) {
141502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter                        DRM_ERROR("failed to attach phys overlay regs\n");
141602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter                        goto out_free_bo;
141702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter                }
141802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		overlay->flip_addr = overlay->reg_bo->phys_obj->handle->busaddr;
141931578148b2c62612f9516fdcf5ebb64ab32ed12dChris Wilson	} else {
142002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		ret = i915_gem_object_pin(reg_bo, PAGE_SIZE);
142102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		if (ret) {
142202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter                        DRM_ERROR("failed to pin overlay register bo\n");
142302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter                        goto out_free_bo;
142402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter                }
142502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		overlay->flip_addr = overlay->reg_bo->gtt_offset;
14260ddc1289f3ffd779779ddd3922f26ae7d0a21604Chris Wilson
14270ddc1289f3ffd779779ddd3922f26ae7d0a21604Chris Wilson		ret = i915_gem_object_set_to_gtt_domain(reg_bo, true);
14280ddc1289f3ffd779779ddd3922f26ae7d0a21604Chris Wilson		if (ret) {
14290ddc1289f3ffd779779ddd3922f26ae7d0a21604Chris Wilson                        DRM_ERROR("failed to move overlay register bo into the GTT\n");
14300ddc1289f3ffd779779ddd3922f26ae7d0a21604Chris Wilson                        goto out_unpin_bo;
14310ddc1289f3ffd779779ddd3922f26ae7d0a21604Chris Wilson                }
143202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
143302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
143402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* init all values */
143502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	overlay->color_key = 0x0101fe;
143602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	overlay->brightness = -19;
143702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	overlay->contrast = 75;
143802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	overlay->saturation = 146;
143902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
14408d74f656dd78ae1ba813389cd46197c6329696bcChris Wilson	regs = intel_overlay_map_regs(overlay);
144102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!regs)
144202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		goto out_free_bo;
144302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
144402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	memset(regs, 0, sizeof(struct overlay_registers));
144502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	update_polyphase_filter(regs);
144602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	update_reg_attrs(overlay, regs);
144702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
14489bb2ff731b32c023e7a502efdc0dee46157290d5Chris Wilson	intel_overlay_unmap_regs(overlay, regs);
144902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
145002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	dev_priv->overlay = overlay;
145102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	DRM_INFO("initialized overlay support\n");
145202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return;
145302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
14540ddc1289f3ffd779779ddd3922f26ae7d0a21604Chris Wilsonout_unpin_bo:
14550ddc1289f3ffd779779ddd3922f26ae7d0a21604Chris Wilson	i915_gem_object_unpin(reg_bo);
145602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterout_free_bo:
145702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	drm_gem_object_unreference(reg_bo);
145802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterout_free:
145902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	kfree(overlay);
146002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return;
146102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
146202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
146302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vettervoid intel_cleanup_overlay(struct drm_device *dev)
146402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
1465722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	drm_i915_private_t *dev_priv = dev->dev_private;
146602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
146762cf4e6fef35b4422e206b63b7f0ac90261d4ad9Chris Wilson	if (!dev_priv->overlay)
146862cf4e6fef35b4422e206b63b7f0ac90261d4ad9Chris Wilson		return;
146902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
147062cf4e6fef35b4422e206b63b7f0ac90261d4ad9Chris Wilson	/* The bo's should be free'd by the generic code already.
147162cf4e6fef35b4422e206b63b7f0ac90261d4ad9Chris Wilson	 * Furthermore modesetting teardown happens beforehand so the
147262cf4e6fef35b4422e206b63b7f0ac90261d4ad9Chris Wilson	 * hardware should be off already */
147362cf4e6fef35b4422e206b63b7f0ac90261d4ad9Chris Wilson	BUG_ON(dev_priv->overlay->active);
147462cf4e6fef35b4422e206b63b7f0ac90261d4ad9Chris Wilson
147562cf4e6fef35b4422e206b63b7f0ac90261d4ad9Chris Wilson	drm_gem_object_unreference_unlocked(&dev_priv->overlay->reg_bo->base);
147662cf4e6fef35b4422e206b63b7f0ac90261d4ad9Chris Wilson	kfree(dev_priv->overlay);
147702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
14786ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson
14793bd3c9329973a93fa3ef5e9840f2fd6fa2889e3fChris Wilson#ifdef CONFIG_DEBUG_FS
14803bd3c9329973a93fa3ef5e9840f2fd6fa2889e3fChris Wilson#include <linux/seq_file.h>
14813bd3c9329973a93fa3ef5e9840f2fd6fa2889e3fChris Wilson
14826ef3d4278034982c13df87c4a51e0445f762d316Chris Wilsonstruct intel_overlay_error_state {
14836ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	struct overlay_registers regs;
14846ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	unsigned long base;
14856ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	u32 dovsta;
14866ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	u32 isr;
14876ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson};
14886ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson
14893bd3c9329973a93fa3ef5e9840f2fd6fa2889e3fChris Wilsonstatic struct overlay_registers *
1490c48c43e422c1404fd72c57d1d21a6f6d01e18900Linus Torvaldsintel_overlay_map_regs_atomic(struct intel_overlay *overlay)
14913bd3c9329973a93fa3ef5e9840f2fd6fa2889e3fChris Wilson{
1492c48c43e422c1404fd72c57d1d21a6f6d01e18900Linus Torvalds	drm_i915_private_t *dev_priv = overlay->dev->dev_private;
14933bd3c9329973a93fa3ef5e9840f2fd6fa2889e3fChris Wilson	struct overlay_registers *regs;
14943bd3c9329973a93fa3ef5e9840f2fd6fa2889e3fChris Wilson
14953bd3c9329973a93fa3ef5e9840f2fd6fa2889e3fChris Wilson	if (OVERLAY_NEEDS_PHYSICAL(overlay->dev))
14963bd3c9329973a93fa3ef5e9840f2fd6fa2889e3fChris Wilson		regs = overlay->reg_bo->phys_obj->handle->vaddr;
14973bd3c9329973a93fa3ef5e9840f2fd6fa2889e3fChris Wilson	else
14983bd3c9329973a93fa3ef5e9840f2fd6fa2889e3fChris Wilson		regs = io_mapping_map_atomic_wc(dev_priv->mm.gtt_mapping,
1499c48c43e422c1404fd72c57d1d21a6f6d01e18900Linus Torvalds						overlay->reg_bo->gtt_offset);
15003bd3c9329973a93fa3ef5e9840f2fd6fa2889e3fChris Wilson
15013bd3c9329973a93fa3ef5e9840f2fd6fa2889e3fChris Wilson	return regs;
15023bd3c9329973a93fa3ef5e9840f2fd6fa2889e3fChris Wilson}
15033bd3c9329973a93fa3ef5e9840f2fd6fa2889e3fChris Wilson
15043bd3c9329973a93fa3ef5e9840f2fd6fa2889e3fChris Wilsonstatic void intel_overlay_unmap_regs_atomic(struct intel_overlay *overlay,
15053bd3c9329973a93fa3ef5e9840f2fd6fa2889e3fChris Wilson					    struct overlay_registers *regs)
15063bd3c9329973a93fa3ef5e9840f2fd6fa2889e3fChris Wilson{
15073bd3c9329973a93fa3ef5e9840f2fd6fa2889e3fChris Wilson	if (!OVERLAY_NEEDS_PHYSICAL(overlay->dev))
1508c48c43e422c1404fd72c57d1d21a6f6d01e18900Linus Torvalds		io_mapping_unmap_atomic(regs);
15093bd3c9329973a93fa3ef5e9840f2fd6fa2889e3fChris Wilson}
15103bd3c9329973a93fa3ef5e9840f2fd6fa2889e3fChris Wilson
15113bd3c9329973a93fa3ef5e9840f2fd6fa2889e3fChris Wilson
15126ef3d4278034982c13df87c4a51e0445f762d316Chris Wilsonstruct intel_overlay_error_state *
15136ef3d4278034982c13df87c4a51e0445f762d316Chris Wilsonintel_overlay_capture_error_state(struct drm_device *dev)
15146ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson{
15156ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson        drm_i915_private_t *dev_priv = dev->dev_private;
15166ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	struct intel_overlay *overlay = dev_priv->overlay;
15176ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	struct intel_overlay_error_state *error;
15186ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	struct overlay_registers __iomem *regs;
15196ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson
15206ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	if (!overlay || !overlay->active)
15216ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson		return NULL;
15226ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson
15236ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	error = kmalloc(sizeof(*error), GFP_ATOMIC);
15246ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	if (error == NULL)
15256ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson		return NULL;
15266ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson
15276ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	error->dovsta = I915_READ(DOVSTA);
15286ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	error->isr = I915_READ(ISR);
152931578148b2c62612f9516fdcf5ebb64ab32ed12dChris Wilson	if (OVERLAY_NEEDS_PHYSICAL(overlay->dev))
15306ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson		error->base = (long) overlay->reg_bo->phys_obj->handle->vaddr;
153131578148b2c62612f9516fdcf5ebb64ab32ed12dChris Wilson	else
153231578148b2c62612f9516fdcf5ebb64ab32ed12dChris Wilson		error->base = (long) overlay->reg_bo->gtt_offset;
15336ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson
15346ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	regs = intel_overlay_map_regs_atomic(overlay);
15356ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	if (!regs)
15366ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson		goto err;
15376ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson
15386ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	memcpy_fromio(&error->regs, regs, sizeof(struct overlay_registers));
1539c48c43e422c1404fd72c57d1d21a6f6d01e18900Linus Torvalds	intel_overlay_unmap_regs_atomic(overlay, regs);
15406ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson
15416ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	return error;
15426ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson
15436ef3d4278034982c13df87c4a51e0445f762d316Chris Wilsonerr:
15446ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	kfree(error);
15456ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	return NULL;
15466ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson}
15476ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson
15486ef3d4278034982c13df87c4a51e0445f762d316Chris Wilsonvoid
15496ef3d4278034982c13df87c4a51e0445f762d316Chris Wilsonintel_overlay_print_error_state(struct seq_file *m, struct intel_overlay_error_state *error)
15506ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson{
15516ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	seq_printf(m, "Overlay, status: 0x%08x, interrupt: 0x%08x\n",
15526ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson		   error->dovsta, error->isr);
15536ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	seq_printf(m, "  Register file at 0x%08lx:\n",
15546ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson		   error->base);
15556ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson
15566ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson#define P(x) seq_printf(m, "    " #x ":	0x%08x\n", error->regs.x)
15576ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OBUF_0Y);
15586ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OBUF_1Y);
15596ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OBUF_0U);
15606ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OBUF_0V);
15616ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OBUF_1U);
15626ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OBUF_1V);
15636ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OSTRIDE);
15646ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(YRGB_VPH);
15656ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(UV_VPH);
15666ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(HORZ_PH);
15676ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(INIT_PHS);
15686ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(DWINPOS);
15696ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(DWINSZ);
15706ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(SWIDTH);
15716ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(SWIDTHSW);
15726ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(SHEIGHT);
15736ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(YRGBSCALE);
15746ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(UVSCALE);
15756ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OCLRC0);
15766ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OCLRC1);
15776ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(DCLRKV);
15786ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(DCLRKM);
15796ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(SCLRKVH);
15806ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(SCLRKVL);
15816ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(SCLRKEN);
15826ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OCONFIG);
15836ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OCMD);
15846ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OSTART_0Y);
15856ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OSTART_1Y);
15866ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OSTART_0U);
15876ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OSTART_0V);
15886ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OSTART_1U);
15896ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OSTART_1V);
15906ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OTILEOFF_0Y);
15916ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OTILEOFF_1Y);
15926ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OTILEOFF_0U);
15936ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OTILEOFF_0V);
15946ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OTILEOFF_1U);
15956ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OTILEOFF_1V);
15966ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(FASTHSCALE);
15976ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(UVSCALEV);
15986ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson#undef P
15996ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson}
16003bd3c9329973a93fa3ef5e9840f2fd6fa2889e3fChris Wilson#endif
1601