intel_overlay.c revision f7abfe8b281991c66406c42c1a6c6c9ee0daa0ff
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};
19123f09ce31ca68af3728ac5eed3e3efb03c5f990aChris Wilson
1928d74f656dd78ae1ba813389cd46197c6329696bcChris Wilsonstatic struct overlay_registers *
1938d74f656dd78ae1ba813389cd46197c6329696bcChris Wilsonintel_overlay_map_regs(struct intel_overlay *overlay)
1948d74f656dd78ae1ba813389cd46197c6329696bcChris Wilson{
1958d74f656dd78ae1ba813389cd46197c6329696bcChris Wilson        drm_i915_private_t *dev_priv = overlay->dev->dev_private;
1968d74f656dd78ae1ba813389cd46197c6329696bcChris Wilson	struct overlay_registers *regs;
1978d74f656dd78ae1ba813389cd46197c6329696bcChris Wilson
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);
2038d74f656dd78ae1ba813389cd46197c6329696bcChris Wilson
2049bb2ff731b32c023e7a502efdc0dee46157290d5Chris Wilson	return regs;
2058d74f656dd78ae1ba813389cd46197c6329696bcChris Wilson}
2068d74f656dd78ae1ba813389cd46197c6329696bcChris Wilson
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)
243106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson{
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;
256106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson
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;
260106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson
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);
286106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson}
287106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson
288b6c028e00445de9dfde2cd0c26521ac53965320aChris Wilson/* overlay needs to be disable in OCMD reg */
289b6c028e00445de9dfde2cd0c26521ac53965320aChris Wilsonstatic int intel_overlay_on(struct intel_overlay *overlay)
290b6c028e00445de9dfde2cd0c26521ac53965320aChris Wilson{
291b6c028e00445de9dfde2cd0c26521ac53965320aChris Wilson	struct drm_device *dev = overlay->dev;
2928dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson	struct drm_i915_gem_request *request;
293106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	int pipe_a_quirk = 0;
294106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	int ret;
295b6c028e00445de9dfde2cd0c26521ac53965320aChris Wilson
296b6c028e00445de9dfde2cd0c26521ac53965320aChris Wilson	BUG_ON(overlay->active);
297b6c028e00445de9dfde2cd0c26521ac53965320aChris Wilson	overlay->active = 1;
298b6c028e00445de9dfde2cd0c26521ac53965320aChris Wilson
299106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	if (IS_I830(dev)) {
300106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson		pipe_a_quirk = i830_activate_pipe_a(dev);
301106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson		if (pipe_a_quirk < 0)
302106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson			return pipe_a_quirk;
303106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	}
304106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson
3058dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson	request = kzalloc(sizeof(*request), GFP_KERNEL);
306106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	if (request == NULL) {
307106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson		ret = -ENOMEM;
308106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson		goto out;
309106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	}
3108dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson
311b6c028e00445de9dfde2cd0c26521ac53965320aChris Wilson	BEGIN_LP_RING(4);
312b6c028e00445de9dfde2cd0c26521ac53965320aChris Wilson	OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_ON);
313b6c028e00445de9dfde2cd0c26521ac53965320aChris Wilson	OUT_RING(overlay->flip_addr | OFC_UPDATE);
314b6c028e00445de9dfde2cd0c26521ac53965320aChris Wilson	OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
315b6c028e00445de9dfde2cd0c26521ac53965320aChris Wilson	OUT_RING(MI_NOOP);
316b6c028e00445de9dfde2cd0c26521ac53965320aChris Wilson	ADVANCE_LP_RING();
317b6c028e00445de9dfde2cd0c26521ac53965320aChris Wilson
318b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson	ret = intel_overlay_do_wait_request(overlay, request, true, NULL);
319106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilsonout:
320106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	if (pipe_a_quirk)
321106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson		i830_deactivate_pipe_a(dev);
322106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson
323106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	return ret;
324b6c028e00445de9dfde2cd0c26521ac53965320aChris Wilson}
325b6c028e00445de9dfde2cd0c26521ac53965320aChris Wilson
32602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter/* overlay needs to be enabled in OCMD reg */
3278dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilsonstatic int intel_overlay_continue(struct intel_overlay *overlay,
3288dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson				  bool load_polyphase_filter)
32902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
33002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct drm_device *dev = overlay->dev;
33102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter        drm_i915_private_t *dev_priv = dev->dev_private;
3328dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson	struct drm_i915_gem_request *request;
33302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	u32 flip_addr = overlay->flip_addr;
33402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	u32 tmp;
33502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
33602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	BUG_ON(!overlay->active);
33702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
3388dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson	request = kzalloc(sizeof(*request), GFP_KERNEL);
3398dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson	if (request == NULL)
3408dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson		return -ENOMEM;
3418dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson
34202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (load_polyphase_filter)
34302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		flip_addr |= OFC_UPDATE;
34402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
34502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* check for underruns */
34602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	tmp = I915_READ(DOVSTA);
34702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (tmp & (1 << 17))
34802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		DRM_DEBUG("overlay underrun, DOVSTA: %x\n", tmp);
34902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
3504f8a567c4666c73284832240db89fdadb2c50bd5Daniel Vetter	BEGIN_LP_RING(2);
35102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_CONTINUE);
35202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	OUT_RING(flip_addr);
3535a5a0c64a99d7542c48c99d1a8bbb49e665842beDaniel Vetter        ADVANCE_LP_RING();
3545a5a0c64a99d7542c48c99d1a8bbb49e665842beDaniel Vetter
355852835f343146a82a528c3b712b373661d4fa17aZou Nan hai	overlay->last_flip_req =
3568dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson		i915_add_request(dev, NULL, request, &dev_priv->render_ring);
3578dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson	return 0;
3585a5a0c64a99d7542c48c99d1a8bbb49e665842beDaniel Vetter}
3595a5a0c64a99d7542c48c99d1a8bbb49e665842beDaniel Vetter
360b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilsonstatic void intel_overlay_release_old_vid_tail(struct intel_overlay *overlay)
361b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson{
362b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson	struct drm_gem_object *obj = &overlay->old_vid_bo->base;
363b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson
364b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson	i915_gem_object_unpin(obj);
365b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson	drm_gem_object_unreference(obj);
366b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson
367b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson	overlay->old_vid_bo = NULL;
368b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson}
369b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson
370b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilsonstatic void intel_overlay_off_tail(struct intel_overlay *overlay)
371b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson{
372b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson	struct drm_gem_object *obj;
373b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson
374b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson	/* never have the overlay hw on without showing a frame */
375b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson	BUG_ON(!overlay->vid_bo);
376b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson	obj = &overlay->vid_bo->base;
377b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson
378b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson	i915_gem_object_unpin(obj);
379b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson	drm_gem_object_unreference(obj);
380b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson	overlay->vid_bo = NULL;
381b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson
382b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson	overlay->crtc->overlay = NULL;
383b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson	overlay->crtc = NULL;
384b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson	overlay->active = 0;
385b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson}
386b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson
38702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter/* overlay needs to be disabled in OCMD reg */
3885dcdbcb06badbdf2faa698bf3198e421a1e12840Chris Wilsonstatic int intel_overlay_off(struct intel_overlay *overlay,
3895dcdbcb06badbdf2faa698bf3198e421a1e12840Chris Wilson			     bool interruptible)
39002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
39102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct drm_device *dev = overlay->dev;
3928dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson	u32 flip_addr = overlay->flip_addr;
3938dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson	struct drm_i915_gem_request *request;
39402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
39502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	BUG_ON(!overlay->active);
39602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
3978dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson	request = kzalloc(sizeof(*request), GFP_KERNEL);
3988dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson	if (request == NULL)
3998dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson		return -ENOMEM;
4008dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson
40102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* According to intel docs the overlay hw may hang (when switching
40202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	 * off) without loading the filter coeffs. It is however unclear whether
40302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	 * this applies to the disabling of the overlay or to the switching off
40402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	 * of the hw. Do it in both cases */
40502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	flip_addr |= OFC_UPDATE;
40602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
4078dfbc3403113bcc51f0350c3471fa1abf664305fChris Wilson	BEGIN_LP_RING(6);
40802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* wait for overlay to go idle */
40902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_CONTINUE);
41002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	OUT_RING(flip_addr);
411722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
41202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* turn overlay off */
413722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_OFF);
41402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	OUT_RING(flip_addr);
415722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
41602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	ADVANCE_LP_RING();
41702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
4185dcdbcb06badbdf2faa698bf3198e421a1e12840Chris Wilson	return intel_overlay_do_wait_request(overlay, request, interruptible,
419b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson					     intel_overlay_off_tail);
42012ca45fea91cfbb09df828bea958b47348caee6dDaniel Vetter}
42112ca45fea91cfbb09df828bea958b47348caee6dDaniel Vetter
42203f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter/* recover from an interruption due to a signal
42303f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter * We have to be careful not to repeat work forever an make forward progess. */
4245dcdbcb06badbdf2faa698bf3198e421a1e12840Chris Wilsonstatic int intel_overlay_recover_from_interrupt(struct intel_overlay *overlay,
4255dcdbcb06badbdf2faa698bf3198e421a1e12840Chris Wilson						bool interruptible)
42603f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter{
42703f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	struct drm_device *dev = overlay->dev;
428852835f343146a82a528c3b712b373661d4fa17aZou Nan hai	drm_i915_private_t *dev_priv = dev->dev_private;
42903f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	int ret;
43003f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter
431b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson	if (overlay->last_flip_req == 0)
432b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson		return 0;
43303f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter
434852835f343146a82a528c3b712b373661d4fa17aZou Nan hai	ret = i915_do_wait_request(dev, overlay->last_flip_req,
435722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson				   interruptible, &dev_priv->render_ring);
436b6c028e00445de9dfde2cd0c26521ac53965320aChris Wilson	if (ret)
43703f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter		return ret;
43803f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter
439b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson	if (overlay->flip_tail)
440b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson		overlay->flip_tail(overlay);
441b6c028e00445de9dfde2cd0c26521ac53965320aChris Wilson
44203f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	overlay->last_flip_req = 0;
44303f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	return 0;
44403f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter}
44503f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter
4465a5a0c64a99d7542c48c99d1a8bbb49e665842beDaniel Vetter/* Wait for pending overlay flip and release old frame.
4475a5a0c64a99d7542c48c99d1a8bbb49e665842beDaniel Vetter * Needs to be called before the overlay register are changed
4488d74f656dd78ae1ba813389cd46197c6329696bcChris Wilson * via intel_overlay_(un)map_regs
4498d74f656dd78ae1ba813389cd46197c6329696bcChris Wilson */
45002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic int intel_overlay_release_old_vid(struct intel_overlay *overlay)
45102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
4525cd68c9864d65e49c910c701716e4e94e09f7ce0Chris Wilson	struct drm_device *dev = overlay->dev;
4535cd68c9864d65e49c910c701716e4e94e09f7ce0Chris Wilson	drm_i915_private_t *dev_priv = dev->dev_private;
45402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int ret;
45502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
4565cd68c9864d65e49c910c701716e4e94e09f7ce0Chris Wilson	/* Only wait if there is actually an old frame to release to
4575cd68c9864d65e49c910c701716e4e94e09f7ce0Chris Wilson	 * guarantee forward progress.
4585cd68c9864d65e49c910c701716e4e94e09f7ce0Chris Wilson	 */
45903f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	if (!overlay->old_vid_bo)
46003f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter		return 0;
46103f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter
4625cd68c9864d65e49c910c701716e4e94e09f7ce0Chris Wilson	if (I915_READ(ISR) & I915_OVERLAY_PLANE_FLIP_PENDING_INTERRUPT) {
4638dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson		struct drm_i915_gem_request *request;
4648dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson
4655cd68c9864d65e49c910c701716e4e94e09f7ce0Chris Wilson		/* synchronous slowpath */
4668dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson		request = kzalloc(sizeof(*request), GFP_KERNEL);
4678dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson		if (request == NULL)
4688dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson			return -ENOMEM;
4698dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson
4705cd68c9864d65e49c910c701716e4e94e09f7ce0Chris Wilson		BEGIN_LP_RING(2);
4715cd68c9864d65e49c910c701716e4e94e09f7ce0Chris Wilson		OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
4725cd68c9864d65e49c910c701716e4e94e09f7ce0Chris Wilson		OUT_RING(MI_NOOP);
4735cd68c9864d65e49c910c701716e4e94e09f7ce0Chris Wilson		ADVANCE_LP_RING();
4745cd68c9864d65e49c910c701716e4e94e09f7ce0Chris Wilson
4758dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson		ret = intel_overlay_do_wait_request(overlay, request, true,
476b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson						    intel_overlay_release_old_vid_tail);
4775cd68c9864d65e49c910c701716e4e94e09f7ce0Chris Wilson		if (ret)
4785cd68c9864d65e49c910c701716e4e94e09f7ce0Chris Wilson			return ret;
4795cd68c9864d65e49c910c701716e4e94e09f7ce0Chris Wilson	}
48002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
4815cd68c9864d65e49c910c701716e4e94e09f7ce0Chris Wilson	intel_overlay_release_old_vid_tail(overlay);
48202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return 0;
48302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
48402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
48502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstruct put_image_params {
48602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int format;
48702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	short dst_x;
48802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	short dst_y;
48902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	short dst_w;
49002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	short dst_h;
49102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	short src_w;
49202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	short src_scan_h;
49302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	short src_scan_w;
49402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	short src_h;
49502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	short stride_Y;
49602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	short stride_UV;
49702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int offset_Y;
49802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int offset_U;
49902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int offset_V;
50002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter};
50102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
50202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic int packed_depth_bytes(u32 format)
50302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
50402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	switch (format & I915_OVERLAY_DEPTH_MASK) {
505722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case I915_OVERLAY_YUV422:
506722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		return 4;
507722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case I915_OVERLAY_YUV411:
508722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		/* return 6; not implemented */
509722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	default:
510722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		return -EINVAL;
51102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
51202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
51302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
51402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic int packed_width_bytes(u32 format, short width)
51502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
51602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	switch (format & I915_OVERLAY_DEPTH_MASK) {
517722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case I915_OVERLAY_YUV422:
518722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		return width << 1;
519722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	default:
520722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		return -EINVAL;
52102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
52202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
52302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
52402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic int uv_hsubsampling(u32 format)
52502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
52602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	switch (format & I915_OVERLAY_DEPTH_MASK) {
527722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case I915_OVERLAY_YUV422:
528722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case I915_OVERLAY_YUV420:
529722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		return 2;
530722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case I915_OVERLAY_YUV411:
531722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case I915_OVERLAY_YUV410:
532722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		return 4;
533722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	default:
534722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		return -EINVAL;
53502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
53602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
53702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
53802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic int uv_vsubsampling(u32 format)
53902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
54002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	switch (format & I915_OVERLAY_DEPTH_MASK) {
541722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case I915_OVERLAY_YUV420:
542722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case I915_OVERLAY_YUV410:
543722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		return 2;
544722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case I915_OVERLAY_YUV422:
545722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case I915_OVERLAY_YUV411:
546722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		return 1;
547722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	default:
548722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		return -EINVAL;
54902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
55002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
55102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
55202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic u32 calc_swidthsw(struct drm_device *dev, u32 offset, u32 width)
55302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
55402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	u32 mask, shift, ret;
55502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (IS_I9XX(dev)) {
55602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		mask = 0x3f;
55702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		shift = 6;
55802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	} else {
55902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		mask = 0x1f;
56002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		shift = 5;
56102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
56202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	ret = ((offset + width + mask) >> shift) - (offset >> shift);
56302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (IS_I9XX(dev))
56402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		ret <<= 1;
56502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	ret -=1;
56602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return ret << 2;
56702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
56802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
56902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic const u16 y_static_hcoeffs[N_HORIZ_Y_TAPS * N_PHASES] = {
57002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3000, 0xb4a0, 0x1930, 0x1920, 0xb4a0,
57102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3000, 0xb500, 0x19d0, 0x1880, 0xb440,
57202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3000, 0xb540, 0x1a88, 0x2f80, 0xb3e0,
57302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3000, 0xb580, 0x1b30, 0x2e20, 0xb380,
57402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3000, 0xb5c0, 0x1bd8, 0x2cc0, 0xb320,
57502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3020, 0xb5e0, 0x1c60, 0x2b80, 0xb2c0,
57602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3020, 0xb5e0, 0x1cf8, 0x2a20, 0xb260,
57702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3020, 0xb5e0, 0x1d80, 0x28e0, 0xb200,
57802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3020, 0xb5c0, 0x1e08, 0x3f40, 0xb1c0,
57902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3020, 0xb580, 0x1e78, 0x3ce0, 0xb160,
58002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3040, 0xb520, 0x1ed8, 0x3aa0, 0xb120,
58102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3040, 0xb4a0, 0x1f30, 0x3880, 0xb0e0,
58202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3040, 0xb400, 0x1f78, 0x3680, 0xb0a0,
58302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3020, 0xb340, 0x1fb8, 0x34a0, 0xb060,
58402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3020, 0xb240, 0x1fe0, 0x32e0, 0xb040,
58502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3020, 0xb140, 0x1ff8, 0x3160, 0xb020,
586722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	0xb000, 0x3000, 0x0800, 0x3000, 0xb000
587722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson};
588722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson
58902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic const u16 uv_static_hcoeffs[N_HORIZ_UV_TAPS * N_PHASES] = {
59002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3000, 0x1800, 0x1800, 0xb000, 0x18d0, 0x2e60,
59102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0xb000, 0x1990, 0x2ce0, 0xb020, 0x1a68, 0x2b40,
59202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0xb040, 0x1b20, 0x29e0, 0xb060, 0x1bd8, 0x2880,
59302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0xb080, 0x1c88, 0x3e60, 0xb0a0, 0x1d28, 0x3c00,
59402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0xb0c0, 0x1db8, 0x39e0, 0xb0e0, 0x1e40, 0x37e0,
59502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0xb100, 0x1eb8, 0x3620, 0xb100, 0x1f18, 0x34a0,
59602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0xb100, 0x1f68, 0x3360, 0xb0e0, 0x1fa8, 0x3240,
59702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0xb0c0, 0x1fe0, 0x3140, 0xb060, 0x1ff0, 0x30a0,
598722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	0x3000, 0x0800, 0x3000
599722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson};
60002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
60102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic void update_polyphase_filter(struct overlay_registers *regs)
60202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
60302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	memcpy(regs->Y_HCOEFS, y_static_hcoeffs, sizeof(y_static_hcoeffs));
60402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	memcpy(regs->UV_HCOEFS, uv_static_hcoeffs, sizeof(uv_static_hcoeffs));
60502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
60602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
60702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic bool update_scaling_factors(struct intel_overlay *overlay,
60802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				   struct overlay_registers *regs,
60902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				   struct put_image_params *params)
61002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
61102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* fixed point with a 12 bit shift */
61202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	u32 xscale, yscale, xscale_UV, yscale_UV;
61302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define FP_SHIFT 12
61402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define FRACT_MASK 0xfff
61502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	bool scale_changed = false;
61602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int uv_hscale = uv_hsubsampling(params->format);
61702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int uv_vscale = uv_vsubsampling(params->format);
61802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
61902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (params->dst_w > 1)
62002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		xscale = ((params->src_scan_w - 1) << FP_SHIFT)
62102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			/(params->dst_w);
62202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	else
62302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		xscale = 1 << FP_SHIFT;
62402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
62502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (params->dst_h > 1)
62602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		yscale = ((params->src_scan_h - 1) << FP_SHIFT)
62702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			/(params->dst_h);
62802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	else
62902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		yscale = 1 << FP_SHIFT;
63002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
63102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/*if (params->format & I915_OVERLAY_YUV_PLANAR) {*/
632722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	xscale_UV = xscale/uv_hscale;
633722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	yscale_UV = yscale/uv_vscale;
634722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	/* make the Y scale to UV scale ratio an exact multiply */
635722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	xscale = xscale_UV * uv_hscale;
636722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	yscale = yscale_UV * uv_vscale;
63702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/*} else {
638722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	  xscale_UV = 0;
639722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	  yscale_UV = 0;
640722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	  }*/
64102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
64202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (xscale != overlay->old_xscale || yscale != overlay->old_yscale)
64302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		scale_changed = true;
64402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	overlay->old_xscale = xscale;
64502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	overlay->old_yscale = yscale;
64602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
647722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	regs->YRGBSCALE = (((yscale & FRACT_MASK) << 20) |
648722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			   ((xscale >> FP_SHIFT)  << 16) |
649722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			   ((xscale & FRACT_MASK) << 3));
650722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson
651722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	regs->UVSCALE = (((yscale_UV & FRACT_MASK) << 20) |
652722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			 ((xscale_UV >> FP_SHIFT)  << 16) |
653722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			 ((xscale_UV & FRACT_MASK) << 3));
654722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson
655722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	regs->UVSCALEV = ((((yscale    >> FP_SHIFT) << 16) |
656722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			   ((yscale_UV >> FP_SHIFT) << 0)));
65702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
65802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (scale_changed)
65902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		update_polyphase_filter(regs);
66002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
66102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return scale_changed;
66202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
66302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
66402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic void update_colorkey(struct intel_overlay *overlay,
66502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			    struct overlay_registers *regs)
66602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
66702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	u32 key = overlay->color_key;
6686ba3ddd9838f5e4d6ac7c6dce95648d205e11bffChris Wilson
66902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	switch (overlay->crtc->base.fb->bits_per_pixel) {
670722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case 8:
671722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		regs->DCLRKV = 0;
672722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		regs->DCLRKM = CLK_RGB8I_MASK | DST_KEY_ENABLE;
6736ba3ddd9838f5e4d6ac7c6dce95648d205e11bffChris Wilson		break;
6746ba3ddd9838f5e4d6ac7c6dce95648d205e11bffChris Wilson
675722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case 16:
676722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		if (overlay->crtc->base.fb->depth == 15) {
677722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			regs->DCLRKV = RGB15_TO_COLORKEY(key);
678722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			regs->DCLRKM = CLK_RGB15_MASK | DST_KEY_ENABLE;
679722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		} else {
680722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			regs->DCLRKV = RGB16_TO_COLORKEY(key);
681722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			regs->DCLRKM = CLK_RGB16_MASK | DST_KEY_ENABLE;
682722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		}
6836ba3ddd9838f5e4d6ac7c6dce95648d205e11bffChris Wilson		break;
6846ba3ddd9838f5e4d6ac7c6dce95648d205e11bffChris Wilson
685722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case 24:
686722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case 32:
687722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		regs->DCLRKV = key;
688722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		regs->DCLRKM = CLK_RGB24_MASK | DST_KEY_ENABLE;
6896ba3ddd9838f5e4d6ac7c6dce95648d205e11bffChris Wilson		break;
69002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
69102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
69202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
69302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic u32 overlay_cmd_reg(struct put_image_params *params)
69402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
69502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	u32 cmd = OCMD_ENABLE | OCMD_BUF_TYPE_FRAME | OCMD_BUFFER0;
69602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
69702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (params->format & I915_OVERLAY_YUV_PLANAR) {
69802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		switch (params->format & I915_OVERLAY_DEPTH_MASK) {
699722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		case I915_OVERLAY_YUV422:
700722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			cmd |= OCMD_YUV_422_PLANAR;
701722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			break;
702722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		case I915_OVERLAY_YUV420:
703722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			cmd |= OCMD_YUV_420_PLANAR;
704722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			break;
705722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		case I915_OVERLAY_YUV411:
706722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		case I915_OVERLAY_YUV410:
707722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			cmd |= OCMD_YUV_410_PLANAR;
708722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			break;
70902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		}
71002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	} else { /* YUV packed */
71102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		switch (params->format & I915_OVERLAY_DEPTH_MASK) {
712722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		case I915_OVERLAY_YUV422:
713722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			cmd |= OCMD_YUV_422_PACKED;
714722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			break;
715722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		case I915_OVERLAY_YUV411:
716722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			cmd |= OCMD_YUV_411_PACKED;
717722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			break;
71802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		}
71902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
72002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		switch (params->format & I915_OVERLAY_SWAP_MASK) {
721722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		case I915_OVERLAY_NO_SWAP:
722722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			break;
723722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		case I915_OVERLAY_UV_SWAP:
724722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			cmd |= OCMD_UV_SWAP;
725722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			break;
726722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		case I915_OVERLAY_Y_SWAP:
727722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			cmd |= OCMD_Y_SWAP;
728722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			break;
729722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		case I915_OVERLAY_Y_AND_UV_SWAP:
730722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			cmd |= OCMD_Y_AND_UV_SWAP;
731722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			break;
73202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		}
73302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
73402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
73502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return cmd;
73602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
73702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
7385fe82c5ee1ba2d04183c376038c5d233a0311ec9Chris Wilsonstatic int intel_overlay_do_put_image(struct intel_overlay *overlay,
7395fe82c5ee1ba2d04183c376038c5d233a0311ec9Chris Wilson				      struct drm_gem_object *new_bo,
7405fe82c5ee1ba2d04183c376038c5d233a0311ec9Chris Wilson				      struct put_image_params *params)
74102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
74202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int ret, tmp_width;
74302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct overlay_registers *regs;
74402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	bool scale_changed = false;
74523010e43b353c2cdc9725cbedc7e364708039bf7Daniel Vetter	struct drm_i915_gem_object *bo_priv = to_intel_bo(new_bo);
74602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct drm_device *dev = overlay->dev;
74702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
74802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	BUG_ON(!mutex_is_locked(&dev->struct_mutex));
74902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	BUG_ON(!mutex_is_locked(&dev->mode_config.mutex));
75002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	BUG_ON(!overlay);
75102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
75202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	ret = intel_overlay_release_old_vid(overlay);
75302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (ret != 0)
75402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return ret;
75502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
75602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	ret = i915_gem_object_pin(new_bo, PAGE_SIZE);
75702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (ret != 0)
75802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return ret;
75902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
76002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	ret = i915_gem_object_set_to_gtt_domain(new_bo, 0);
76102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (ret != 0)
76202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		goto out_unpin;
76302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
76402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!overlay->active) {
7658d74f656dd78ae1ba813389cd46197c6329696bcChris Wilson		regs = intel_overlay_map_regs(overlay);
76602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		if (!regs) {
76702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			ret = -ENOMEM;
76802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			goto out_unpin;
76902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		}
77002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		regs->OCONFIG = OCONF_CC_OUT_8BIT;
77102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		if (IS_I965GM(overlay->dev))
77202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			regs->OCONFIG |= OCONF_CSC_MODE_BT709;
77302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		regs->OCONFIG |= overlay->crtc->pipe == 0 ?
77402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			OCONF_PIPE_A : OCONF_PIPE_B;
7759bb2ff731b32c023e7a502efdc0dee46157290d5Chris Wilson		intel_overlay_unmap_regs(overlay, regs);
77602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
77702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		ret = intel_overlay_on(overlay);
77802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		if (ret != 0)
77902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			goto out_unpin;
78002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
78102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
7828d74f656dd78ae1ba813389cd46197c6329696bcChris Wilson	regs = intel_overlay_map_regs(overlay);
78302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!regs) {
78402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		ret = -ENOMEM;
78502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		goto out_unpin;
78602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
78702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
78802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	regs->DWINPOS = (params->dst_y << 16) | params->dst_x;
78902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	regs->DWINSZ = (params->dst_h << 16) | params->dst_w;
79002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
79102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (params->format & I915_OVERLAY_YUV_PACKED)
79202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		tmp_width = packed_width_bytes(params->format, params->src_w);
79302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	else
79402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		tmp_width = params->src_w;
79502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
79602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	regs->SWIDTH = params->src_w;
79702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	regs->SWIDTHSW = calc_swidthsw(overlay->dev,
798722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson				       params->offset_Y, tmp_width);
79902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	regs->SHEIGHT = params->src_h;
80002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	regs->OBUF_0Y = bo_priv->gtt_offset + params-> offset_Y;
80102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	regs->OSTRIDE = params->stride_Y;
80202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
80302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (params->format & I915_OVERLAY_YUV_PLANAR) {
80402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		int uv_hscale = uv_hsubsampling(params->format);
80502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		int uv_vscale = uv_vsubsampling(params->format);
80602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		u32 tmp_U, tmp_V;
80702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		regs->SWIDTH |= (params->src_w/uv_hscale) << 16;
80802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		tmp_U = calc_swidthsw(overlay->dev, params->offset_U,
809722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson				      params->src_w/uv_hscale);
81002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		tmp_V = calc_swidthsw(overlay->dev, params->offset_V,
811722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson				      params->src_w/uv_hscale);
81202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		regs->SWIDTHSW |= max_t(u32, tmp_U, tmp_V) << 16;
81302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		regs->SHEIGHT |= (params->src_h/uv_vscale) << 16;
81402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		regs->OBUF_0U = bo_priv->gtt_offset + params->offset_U;
81502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		regs->OBUF_0V = bo_priv->gtt_offset + params->offset_V;
81602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		regs->OSTRIDE |= params->stride_UV << 16;
81702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
81802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
81902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	scale_changed = update_scaling_factors(overlay, regs, params);
82002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
82102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	update_colorkey(overlay, regs);
82202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
82302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	regs->OCMD = overlay_cmd_reg(params);
82402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
8259bb2ff731b32c023e7a502efdc0dee46157290d5Chris Wilson	intel_overlay_unmap_regs(overlay, regs);
82602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
8278dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson	ret = intel_overlay_continue(overlay, scale_changed);
8288dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson	if (ret)
8298dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson		goto out_unpin;
83002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
83102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	overlay->old_vid_bo = overlay->vid_bo;
83223010e43b353c2cdc9725cbedc7e364708039bf7Daniel Vetter	overlay->vid_bo = to_intel_bo(new_bo);
83302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
83402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return 0;
83502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
83602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterout_unpin:
83702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	i915_gem_object_unpin(new_bo);
83802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return ret;
83902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
84002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
8415dcdbcb06badbdf2faa698bf3198e421a1e12840Chris Wilsonint intel_overlay_switch_off(struct intel_overlay *overlay,
8425dcdbcb06badbdf2faa698bf3198e421a1e12840Chris Wilson			     bool interruptible)
84302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
84402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct overlay_registers *regs;
84502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct drm_device *dev = overlay->dev;
8465dcdbcb06badbdf2faa698bf3198e421a1e12840Chris Wilson	int ret;
84702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
84802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	BUG_ON(!mutex_is_locked(&dev->struct_mutex));
84902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	BUG_ON(!mutex_is_locked(&dev->mode_config.mutex));
85002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
851b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson	ret = intel_overlay_recover_from_interrupt(overlay, interruptible);
852b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson	if (ret != 0)
853b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson		return ret;
8549bedb9743fd906e4160468663ee6e1bbdc4412b8Daniel Vetter
85502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!overlay->active)
85602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return 0;
85702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
85802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	ret = intel_overlay_release_old_vid(overlay);
85902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (ret != 0)
86002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return ret;
86102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
8628d74f656dd78ae1ba813389cd46197c6329696bcChris Wilson	regs = intel_overlay_map_regs(overlay);
86302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	regs->OCMD = 0;
8649bb2ff731b32c023e7a502efdc0dee46157290d5Chris Wilson	intel_overlay_unmap_regs(overlay, regs);
86502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
8665dcdbcb06badbdf2faa698bf3198e421a1e12840Chris Wilson	ret = intel_overlay_off(overlay, interruptible);
86703f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	if (ret != 0)
86803f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter		return ret;
86903f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter
87012ca45fea91cfbb09df828bea958b47348caee6dDaniel Vetter	intel_overlay_off_tail(overlay);
87102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return 0;
87202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
87302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
87402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic int check_overlay_possible_on_crtc(struct intel_overlay *overlay,
87502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter					  struct intel_crtc *crtc)
87602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
877722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	drm_i915_private_t *dev_priv = overlay->dev->dev_private;
87802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
879f7abfe8b281991c66406c42c1a6c6c9ee0daa0ffChris Wilson	if (!crtc->active)
88002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EINVAL;
88102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
88202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* can't use the overlay with double wide pipe */
883f7abfe8b281991c66406c42c1a6c6c9ee0daa0ffChris Wilson	if (!IS_I965G(overlay->dev) &&
884f7abfe8b281991c66406c42c1a6c6c9ee0daa0ffChris Wilson	    (I915_READ(PIPECONF(crtc->pipe)) & (PIPECONF_DOUBLE_WIDE | PIPECONF_ENABLE)) != PIPECONF_ENABLE)
88502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EINVAL;
88602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
88702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return 0;
88802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
88902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
89002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic void update_pfit_vscale_ratio(struct intel_overlay *overlay)
89102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
89202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct drm_device *dev = overlay->dev;
893722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	drm_i915_private_t *dev_priv = dev->dev_private;
89402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	u32 pfit_control = I915_READ(PFIT_CONTROL);
895446d2183af68c0fd2772f5ef97a033efe69904a5Chris Wilson	u32 ratio;
89602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
89702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* XXX: This is not the same logic as in the xorg driver, but more in
898446d2183af68c0fd2772f5ef97a033efe69904a5Chris Wilson	 * line with the intel documentation for the i965
899446d2183af68c0fd2772f5ef97a033efe69904a5Chris Wilson	 */
900446d2183af68c0fd2772f5ef97a033efe69904a5Chris Wilson	if (!IS_I965G(dev)) {
901446d2183af68c0fd2772f5ef97a033efe69904a5Chris Wilson		if (pfit_control & VERT_AUTO_SCALE)
902446d2183af68c0fd2772f5ef97a033efe69904a5Chris Wilson			ratio = I915_READ(PFIT_AUTO_RATIOS);
90302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		else
904446d2183af68c0fd2772f5ef97a033efe69904a5Chris Wilson			ratio = I915_READ(PFIT_PGM_RATIOS);
905446d2183af68c0fd2772f5ef97a033efe69904a5Chris Wilson		ratio >>= PFIT_VERT_SCALE_SHIFT;
906446d2183af68c0fd2772f5ef97a033efe69904a5Chris Wilson	} else { /* on i965 use the PGM reg to read out the autoscaler values */
907446d2183af68c0fd2772f5ef97a033efe69904a5Chris Wilson		ratio = I915_READ(PFIT_PGM_RATIOS) >> PFIT_VERT_SCALE_SHIFT_965;
90802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
90902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
91002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	overlay->pfit_vscale_ratio = ratio;
91102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
91202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
91302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic int check_overlay_dst(struct intel_overlay *overlay,
91402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			     struct drm_intel_overlay_put_image *rec)
91502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
91602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct drm_display_mode *mode = &overlay->crtc->base.mode;
91702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
918722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	if (rec->dst_x < mode->crtc_hdisplay &&
919722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	    rec->dst_x + rec->dst_width <= mode->crtc_hdisplay &&
920722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	    rec->dst_y < mode->crtc_vdisplay &&
921722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	    rec->dst_y + rec->dst_height <= mode->crtc_vdisplay)
92202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return 0;
92302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	else
92402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EINVAL;
92502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
92602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
92702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic int check_overlay_scaling(struct put_image_params *rec)
92802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
92902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	u32 tmp;
93002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
93102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* downscaling limit is 8.0 */
93202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	tmp = ((rec->src_scan_h << 16) / rec->dst_h) >> 16;
93302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (tmp > 7)
93402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EINVAL;
93502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	tmp = ((rec->src_scan_w << 16) / rec->dst_w) >> 16;
93602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (tmp > 7)
93702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EINVAL;
93802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
93902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return 0;
94002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
94102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
94202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic int check_overlay_src(struct drm_device *dev,
94302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			     struct drm_intel_overlay_put_image *rec,
94402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			     struct drm_gem_object *new_bo)
94502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
94602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int uv_hscale = uv_hsubsampling(rec->flags);
94702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int uv_vscale = uv_vsubsampling(rec->flags);
9489f7c3f442bb7c0d0a0ed25cc287932450a1f2babChris Wilson	u32 stride_mask, depth, tmp;
94902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
95002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* check src dimensions */
95102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (IS_845G(dev) || IS_I830(dev)) {
952722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		if (rec->src_height > IMAGE_MAX_HEIGHT_LEGACY ||
9539f7c3f442bb7c0d0a0ed25cc287932450a1f2babChris Wilson		    rec->src_width  > IMAGE_MAX_WIDTH_LEGACY)
95402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			return -EINVAL;
95502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	} else {
956722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		if (rec->src_height > IMAGE_MAX_HEIGHT ||
9579f7c3f442bb7c0d0a0ed25cc287932450a1f2babChris Wilson		    rec->src_width  > IMAGE_MAX_WIDTH)
95802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			return -EINVAL;
95902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
9609f7c3f442bb7c0d0a0ed25cc287932450a1f2babChris Wilson
96102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* better safe than sorry, use 4 as the maximal subsampling ratio */
962722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	if (rec->src_height < N_VERT_Y_TAPS*4 ||
9639f7c3f442bb7c0d0a0ed25cc287932450a1f2babChris Wilson	    rec->src_width  < N_HORIZ_Y_TAPS*4)
96402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EINVAL;
96502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
966a1efd14a99483a4fb9308902397ed86b69454c99Chris Wilson	/* check alignment constraints */
96702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	switch (rec->flags & I915_OVERLAY_TYPE_MASK) {
968722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case I915_OVERLAY_RGB:
969722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		/* not implemented */
970722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		return -EINVAL;
9719f7c3f442bb7c0d0a0ed25cc287932450a1f2babChris Wilson
972722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case I915_OVERLAY_YUV_PACKED:
973722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		if (uv_vscale != 1)
97402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			return -EINVAL;
9759f7c3f442bb7c0d0a0ed25cc287932450a1f2babChris Wilson
9769f7c3f442bb7c0d0a0ed25cc287932450a1f2babChris Wilson		depth = packed_depth_bytes(rec->flags);
977722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		if (depth < 0)
978722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			return depth;
9799f7c3f442bb7c0d0a0ed25cc287932450a1f2babChris Wilson
980722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		/* ignore UV planes */
981722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		rec->stride_UV = 0;
982722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		rec->offset_U = 0;
983722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		rec->offset_V = 0;
984722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		/* check pixel alignment */
985722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		if (rec->offset_Y % depth)
986722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			return -EINVAL;
987722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		break;
9889f7c3f442bb7c0d0a0ed25cc287932450a1f2babChris Wilson
989722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case I915_OVERLAY_YUV_PLANAR:
990722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		if (uv_vscale < 0 || uv_hscale < 0)
99102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			return -EINVAL;
992722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		/* no offset restrictions for planar formats */
993722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		break;
9949f7c3f442bb7c0d0a0ed25cc287932450a1f2babChris Wilson
995722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	default:
996722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		return -EINVAL;
99702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
99802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
99902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (rec->src_width % uv_hscale)
100002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EINVAL;
100102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
100202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* stride checking */
1003a1efd14a99483a4fb9308902397ed86b69454c99Chris Wilson	if (IS_I830(dev) || IS_845G(dev))
1004a1efd14a99483a4fb9308902397ed86b69454c99Chris Wilson		stride_mask = 255;
1005a1efd14a99483a4fb9308902397ed86b69454c99Chris Wilson	else
1006a1efd14a99483a4fb9308902397ed86b69454c99Chris Wilson		stride_mask = 63;
100702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
100802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (rec->stride_Y & stride_mask || rec->stride_UV & stride_mask)
100902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EINVAL;
101002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (IS_I965G(dev) && rec->stride_Y < 512)
101102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EINVAL;
101202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
101302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	tmp = (rec->flags & I915_OVERLAY_TYPE_MASK) == I915_OVERLAY_YUV_PLANAR ?
10149f7c3f442bb7c0d0a0ed25cc287932450a1f2babChris Wilson		4096 : 8192;
10159f7c3f442bb7c0d0a0ed25cc287932450a1f2babChris Wilson	if (rec->stride_Y > tmp || rec->stride_UV > 2*1024)
101602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EINVAL;
101702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
101802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* check buffer dimensions */
101902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	switch (rec->flags & I915_OVERLAY_TYPE_MASK) {
1020722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case I915_OVERLAY_RGB:
1021722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case I915_OVERLAY_YUV_PACKED:
1022722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		/* always 4 Y values per depth pixels */
1023722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		if (packed_width_bytes(rec->flags, rec->src_width) > rec->stride_Y)
1024722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			return -EINVAL;
1025722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson
1026722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		tmp = rec->stride_Y*rec->src_height;
1027722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		if (rec->offset_Y + tmp > new_bo->size)
1028722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			return -EINVAL;
1029722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		break;
1030722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson
1031722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case I915_OVERLAY_YUV_PLANAR:
1032722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		if (rec->src_width > rec->stride_Y)
1033722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			return -EINVAL;
1034722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		if (rec->src_width/uv_hscale > rec->stride_UV)
1035722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			return -EINVAL;
1036722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson
10379f7c3f442bb7c0d0a0ed25cc287932450a1f2babChris Wilson		tmp = rec->stride_Y * rec->src_height;
1038722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		if (rec->offset_Y + tmp > new_bo->size)
1039722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			return -EINVAL;
10409f7c3f442bb7c0d0a0ed25cc287932450a1f2babChris Wilson
10419f7c3f442bb7c0d0a0ed25cc287932450a1f2babChris Wilson		tmp = rec->stride_UV * (rec->src_height / uv_vscale);
1042722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		if (rec->offset_U + tmp > new_bo->size ||
1043722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		    rec->offset_V + tmp > new_bo->size)
1044722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			return -EINVAL;
1045722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		break;
104602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
104702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
104802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return 0;
104902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
105002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
1051e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson/**
1052e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson * Return the pipe currently connected to the panel fitter,
1053e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson * or -1 if the panel fitter is not present or not in use
1054e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson */
1055e9e331a8abeece1565d383510ed985945132ffe3Chris Wilsonstatic int intel_panel_fitter_pipe(struct drm_device *dev)
1056e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson{
1057e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson	struct drm_i915_private *dev_priv = dev->dev_private;
1058e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson	u32  pfit_control;
1059e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson
1060e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson	/* i830 doesn't have a panel fitter */
1061e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson	if (IS_I830(dev))
1062e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson		return -1;
1063e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson
1064e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson	pfit_control = I915_READ(PFIT_CONTROL);
1065e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson
1066e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson	/* See if the panel fitter is in use */
1067e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson	if ((pfit_control & PFIT_ENABLE) == 0)
1068e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson		return -1;
1069e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson
1070e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson	/* 965 can place panel fitter on either pipe */
1071e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson	if (IS_I965G(dev))
1072e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson		return (pfit_control >> 29) & 0x3;
1073e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson
1074e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson	/* older chips can only use pipe 1 */
1075e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson	return 1;
1076e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson}
1077e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson
107802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterint intel_overlay_put_image(struct drm_device *dev, void *data,
107902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter                            struct drm_file *file_priv)
108002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
108102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct drm_intel_overlay_put_image *put_image_rec = data;
108202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	drm_i915_private_t *dev_priv = dev->dev_private;
108302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct intel_overlay *overlay;
108402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct drm_mode_object *drmmode_obj;
108502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct intel_crtc *crtc;
108602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct drm_gem_object *new_bo;
108702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct put_image_params *params;
108802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int ret;
108902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
109002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!dev_priv) {
109102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		DRM_ERROR("called with no initialization\n");
109202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EINVAL;
109302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
109402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
109502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	overlay = dev_priv->overlay;
109602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!overlay) {
109702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		DRM_DEBUG("userspace bug: no overlay\n");
109802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -ENODEV;
109902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
110002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
110102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!(put_image_rec->flags & I915_OVERLAY_ENABLE)) {
110202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		mutex_lock(&dev->mode_config.mutex);
110302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		mutex_lock(&dev->struct_mutex);
110402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
11055dcdbcb06badbdf2faa698bf3198e421a1e12840Chris Wilson		ret = intel_overlay_switch_off(overlay, true);
110602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
110702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		mutex_unlock(&dev->struct_mutex);
110802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		mutex_unlock(&dev->mode_config.mutex);
110902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
111002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return ret;
111102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
111202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
111302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	params = kmalloc(sizeof(struct put_image_params), GFP_KERNEL);
111402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!params)
111502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -ENOMEM;
111602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
111702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	drmmode_obj = drm_mode_object_find(dev, put_image_rec->crtc_id,
1118722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson					   DRM_MODE_OBJECT_CRTC);
1119915a428e43acfd05e4ffeaf40549b0cf163eebe2Dan Carpenter	if (!drmmode_obj) {
1120915a428e43acfd05e4ffeaf40549b0cf163eebe2Dan Carpenter		ret = -ENOENT;
1121915a428e43acfd05e4ffeaf40549b0cf163eebe2Dan Carpenter		goto out_free;
1122915a428e43acfd05e4ffeaf40549b0cf163eebe2Dan Carpenter	}
112302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	crtc = to_intel_crtc(obj_to_crtc(drmmode_obj));
112402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
112502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	new_bo = drm_gem_object_lookup(dev, file_priv,
1126722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson				       put_image_rec->bo_handle);
1127915a428e43acfd05e4ffeaf40549b0cf163eebe2Dan Carpenter	if (!new_bo) {
1128915a428e43acfd05e4ffeaf40549b0cf163eebe2Dan Carpenter		ret = -ENOENT;
1129915a428e43acfd05e4ffeaf40549b0cf163eebe2Dan Carpenter		goto out_free;
1130915a428e43acfd05e4ffeaf40549b0cf163eebe2Dan Carpenter	}
113102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
113202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	mutex_lock(&dev->mode_config.mutex);
113302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	mutex_lock(&dev->struct_mutex);
113402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
1135b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson	ret = intel_overlay_recover_from_interrupt(overlay, true);
1136b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson	if (ret != 0)
1137b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson		goto out_unlock;
113803f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter
113902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (overlay->crtc != crtc) {
114002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		struct drm_display_mode *mode = &crtc->base.mode;
11415dcdbcb06badbdf2faa698bf3198e421a1e12840Chris Wilson		ret = intel_overlay_switch_off(overlay, true);
114202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		if (ret != 0)
114302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			goto out_unlock;
114402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
114502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		ret = check_overlay_possible_on_crtc(overlay, crtc);
114602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		if (ret != 0)
114702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			goto out_unlock;
114802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
114902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		overlay->crtc = crtc;
115002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		crtc->overlay = overlay;
115102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
1152e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson		/* line too wide, i.e. one-line-mode */
1153e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson		if (mode->hdisplay > 1024 &&
1154e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson		    intel_panel_fitter_pipe(dev) == crtc->pipe) {
115502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			overlay->pfit_active = 1;
115602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			update_pfit_vscale_ratio(overlay);
115702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		} else
115802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			overlay->pfit_active = 0;
115902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
116002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
116102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	ret = check_overlay_dst(overlay, put_image_rec);
116202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (ret != 0)
116302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		goto out_unlock;
116402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
116502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (overlay->pfit_active) {
116602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		params->dst_y = ((((u32)put_image_rec->dst_y) << 12) /
1167722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson				 overlay->pfit_vscale_ratio);
116802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		/* shifting right rounds downwards, so add 1 */
116902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		params->dst_h = ((((u32)put_image_rec->dst_height) << 12) /
1170722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson				 overlay->pfit_vscale_ratio) + 1;
117102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	} else {
117202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		params->dst_y = put_image_rec->dst_y;
117302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		params->dst_h = put_image_rec->dst_height;
117402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
117502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	params->dst_x = put_image_rec->dst_x;
117602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	params->dst_w = put_image_rec->dst_width;
117702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
117802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	params->src_w = put_image_rec->src_width;
117902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	params->src_h = put_image_rec->src_height;
118002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	params->src_scan_w = put_image_rec->src_scan_width;
118102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	params->src_scan_h = put_image_rec->src_scan_height;
1182722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	if (params->src_scan_h > params->src_h ||
1183722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	    params->src_scan_w > params->src_w) {
118402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		ret = -EINVAL;
118502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		goto out_unlock;
118602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
118702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
118802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	ret = check_overlay_src(dev, put_image_rec, new_bo);
118902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (ret != 0)
119002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		goto out_unlock;
119102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	params->format = put_image_rec->flags & ~I915_OVERLAY_FLAGS_MASK;
119202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	params->stride_Y = put_image_rec->stride_Y;
119302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	params->stride_UV = put_image_rec->stride_UV;
119402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	params->offset_Y = put_image_rec->offset_Y;
119502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	params->offset_U = put_image_rec->offset_U;
119602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	params->offset_V = put_image_rec->offset_V;
119702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
119802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* Check scaling after src size to prevent a divide-by-zero. */
119902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	ret = check_overlay_scaling(params);
120002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (ret != 0)
120102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		goto out_unlock;
120202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
120302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	ret = intel_overlay_do_put_image(overlay, new_bo, params);
120402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (ret != 0)
120502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		goto out_unlock;
120602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
120702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	mutex_unlock(&dev->struct_mutex);
120802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	mutex_unlock(&dev->mode_config.mutex);
120902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
121002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	kfree(params);
121102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
121202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return 0;
121302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
121402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterout_unlock:
121502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	mutex_unlock(&dev->struct_mutex);
121602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	mutex_unlock(&dev->mode_config.mutex);
1217bc9025bdc4e2b591734cca17697093845007b63dLuca Barbieri	drm_gem_object_unreference_unlocked(new_bo);
1218915a428e43acfd05e4ffeaf40549b0cf163eebe2Dan Carpenterout_free:
121902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	kfree(params);
122002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
122102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return ret;
122202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
122302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
122402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic void update_reg_attrs(struct intel_overlay *overlay,
122502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			     struct overlay_registers *regs)
122602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
122702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	regs->OCLRC0 = (overlay->contrast << 18) | (overlay->brightness & 0xff);
122802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	regs->OCLRC1 = overlay->saturation;
122902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
123002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
123102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic bool check_gamma_bounds(u32 gamma1, u32 gamma2)
123202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
123302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int i;
123402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
123502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (gamma1 & 0xff000000 || gamma2 & 0xff000000)
123602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return false;
123702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
123802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	for (i = 0; i < 3; i++) {
1239722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		if (((gamma1 >> i*8) & 0xff) >= ((gamma2 >> i*8) & 0xff))
124002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			return false;
124102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
124202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
124302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return true;
124402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
124502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
124602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic bool check_gamma5_errata(u32 gamma5)
124702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
124802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int i;
124902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
125002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	for (i = 0; i < 3; i++) {
125102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		if (((gamma5 >> i*8) & 0xff) == 0x80)
125202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			return false;
125302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
125402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
125502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return true;
125602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
125702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
125802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic int check_gamma(struct drm_intel_overlay_attrs *attrs)
125902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
1260722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	if (!check_gamma_bounds(0, attrs->gamma0) ||
1261722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	    !check_gamma_bounds(attrs->gamma0, attrs->gamma1) ||
1262722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	    !check_gamma_bounds(attrs->gamma1, attrs->gamma2) ||
1263722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	    !check_gamma_bounds(attrs->gamma2, attrs->gamma3) ||
1264722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	    !check_gamma_bounds(attrs->gamma3, attrs->gamma4) ||
1265722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	    !check_gamma_bounds(attrs->gamma4, attrs->gamma5) ||
1266722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	    !check_gamma_bounds(attrs->gamma5, 0x00ffffff))
126702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EINVAL;
1268722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson
126902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!check_gamma5_errata(attrs->gamma5))
127002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EINVAL;
1271722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson
127202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return 0;
127302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
127402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
127502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterint intel_overlay_attrs(struct drm_device *dev, void *data,
127602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter                        struct drm_file *file_priv)
127702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
127802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct drm_intel_overlay_attrs *attrs = data;
127902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter        drm_i915_private_t *dev_priv = dev->dev_private;
128002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct intel_overlay *overlay;
128102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct overlay_registers *regs;
128202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int ret;
128302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
128402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!dev_priv) {
128502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		DRM_ERROR("called with no initialization\n");
128602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EINVAL;
128702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
128802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
128902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	overlay = dev_priv->overlay;
129002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!overlay) {
129102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		DRM_DEBUG("userspace bug: no overlay\n");
129202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -ENODEV;
129302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
129402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
129502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	mutex_lock(&dev->mode_config.mutex);
129602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	mutex_lock(&dev->struct_mutex);
129702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
129860fc332cb5ab19e5a86d696b210df65814b2ad8aChris Wilson	ret = -EINVAL;
129902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!(attrs->flags & I915_OVERLAY_UPDATE_ATTRS)) {
130060fc332cb5ab19e5a86d696b210df65814b2ad8aChris Wilson		attrs->color_key  = overlay->color_key;
130102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		attrs->brightness = overlay->brightness;
130260fc332cb5ab19e5a86d696b210df65814b2ad8aChris Wilson		attrs->contrast   = overlay->contrast;
130302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		attrs->saturation = overlay->saturation;
130402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
130502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		if (IS_I9XX(dev)) {
130602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			attrs->gamma0 = I915_READ(OGAMC0);
130702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			attrs->gamma1 = I915_READ(OGAMC1);
130802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			attrs->gamma2 = I915_READ(OGAMC2);
130902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			attrs->gamma3 = I915_READ(OGAMC3);
131002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			attrs->gamma4 = I915_READ(OGAMC4);
131102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			attrs->gamma5 = I915_READ(OGAMC5);
131202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		}
131302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	} else {
131460fc332cb5ab19e5a86d696b210df65814b2ad8aChris Wilson		if (attrs->brightness < -128 || attrs->brightness > 127)
131502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			goto out_unlock;
131660fc332cb5ab19e5a86d696b210df65814b2ad8aChris Wilson		if (attrs->contrast > 255)
131702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			goto out_unlock;
131860fc332cb5ab19e5a86d696b210df65814b2ad8aChris Wilson		if (attrs->saturation > 1023)
131902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			goto out_unlock;
132060fc332cb5ab19e5a86d696b210df65814b2ad8aChris Wilson
132160fc332cb5ab19e5a86d696b210df65814b2ad8aChris Wilson		overlay->color_key  = attrs->color_key;
132260fc332cb5ab19e5a86d696b210df65814b2ad8aChris Wilson		overlay->brightness = attrs->brightness;
132360fc332cb5ab19e5a86d696b210df65814b2ad8aChris Wilson		overlay->contrast   = attrs->contrast;
132460fc332cb5ab19e5a86d696b210df65814b2ad8aChris Wilson		overlay->saturation = attrs->saturation;
132502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
13268d74f656dd78ae1ba813389cd46197c6329696bcChris Wilson		regs = intel_overlay_map_regs(overlay);
132702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		if (!regs) {
132802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			ret = -ENOMEM;
132902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			goto out_unlock;
133002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		}
133102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
133202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		update_reg_attrs(overlay, regs);
133302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
13349bb2ff731b32c023e7a502efdc0dee46157290d5Chris Wilson		intel_overlay_unmap_regs(overlay, regs);
133502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
133602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		if (attrs->flags & I915_OVERLAY_UPDATE_GAMMA) {
133760fc332cb5ab19e5a86d696b210df65814b2ad8aChris Wilson			if (!IS_I9XX(dev))
133802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				goto out_unlock;
133902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
134002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			if (overlay->active) {
134102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				ret = -EBUSY;
134202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				goto out_unlock;
134302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			}
134402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
134502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			ret = check_gamma(attrs);
134660fc332cb5ab19e5a86d696b210df65814b2ad8aChris Wilson			if (ret)
134702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				goto out_unlock;
134802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
134902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			I915_WRITE(OGAMC0, attrs->gamma0);
135002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			I915_WRITE(OGAMC1, attrs->gamma1);
135102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			I915_WRITE(OGAMC2, attrs->gamma2);
135202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			I915_WRITE(OGAMC3, attrs->gamma3);
135302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			I915_WRITE(OGAMC4, attrs->gamma4);
135402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			I915_WRITE(OGAMC5, attrs->gamma5);
135502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		}
135602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
135702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
135860fc332cb5ab19e5a86d696b210df65814b2ad8aChris Wilson	ret = 0;
135902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterout_unlock:
136002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	mutex_unlock(&dev->struct_mutex);
136102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	mutex_unlock(&dev->mode_config.mutex);
136202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
136302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return ret;
136402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
136502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
136602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vettervoid intel_setup_overlay(struct drm_device *dev)
136702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
136802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter        drm_i915_private_t *dev_priv = dev->dev_private;
136902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct intel_overlay *overlay;
137002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct drm_gem_object *reg_bo;
137102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct overlay_registers *regs;
137202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int ret;
137302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
137431578148b2c62612f9516fdcf5ebb64ab32ed12dChris Wilson	if (!HAS_OVERLAY(dev))
137502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return;
137602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
137702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	overlay = kzalloc(sizeof(struct intel_overlay), GFP_KERNEL);
137802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!overlay)
137902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return;
138002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	overlay->dev = dev;
138102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
1382ac52bc56de25535a907ef07f8755f1387b89b0f5Daniel Vetter	reg_bo = i915_gem_alloc_object(dev, PAGE_SIZE);
138302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!reg_bo)
138402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		goto out_free;
138523010e43b353c2cdc9725cbedc7e364708039bf7Daniel Vetter	overlay->reg_bo = to_intel_bo(reg_bo);
138602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
138731578148b2c62612f9516fdcf5ebb64ab32ed12dChris Wilson	if (OVERLAY_NEEDS_PHYSICAL(dev)) {
138831578148b2c62612f9516fdcf5ebb64ab32ed12dChris Wilson		ret = i915_gem_attach_phys_object(dev, reg_bo,
138931578148b2c62612f9516fdcf5ebb64ab32ed12dChris Wilson						  I915_GEM_PHYS_OVERLAY_REGS,
1390a29301288f1840bdf9c5456da9cd7c944436edd5Chris Wilson						  PAGE_SIZE);
139131578148b2c62612f9516fdcf5ebb64ab32ed12dChris Wilson                if (ret) {
139231578148b2c62612f9516fdcf5ebb64ab32ed12dChris Wilson                        DRM_ERROR("failed to attach phys overlay regs\n");
139331578148b2c62612f9516fdcf5ebb64ab32ed12dChris Wilson                        goto out_free_bo;
139431578148b2c62612f9516fdcf5ebb64ab32ed12dChris Wilson                }
139531578148b2c62612f9516fdcf5ebb64ab32ed12dChris Wilson		overlay->flip_addr = overlay->reg_bo->phys_obj->handle->busaddr;
139631578148b2c62612f9516fdcf5ebb64ab32ed12dChris Wilson	} else {
139702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		ret = i915_gem_object_pin(reg_bo, PAGE_SIZE);
139802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		if (ret) {
139902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter                        DRM_ERROR("failed to pin overlay register bo\n");
140002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter                        goto out_free_bo;
140102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter                }
140202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		overlay->flip_addr = overlay->reg_bo->gtt_offset;
14030ddc1289f3ffd779779ddd3922f26ae7d0a21604Chris Wilson
14040ddc1289f3ffd779779ddd3922f26ae7d0a21604Chris Wilson		ret = i915_gem_object_set_to_gtt_domain(reg_bo, true);
14050ddc1289f3ffd779779ddd3922f26ae7d0a21604Chris Wilson		if (ret) {
14060ddc1289f3ffd779779ddd3922f26ae7d0a21604Chris Wilson                        DRM_ERROR("failed to move overlay register bo into the GTT\n");
14070ddc1289f3ffd779779ddd3922f26ae7d0a21604Chris Wilson                        goto out_unpin_bo;
14080ddc1289f3ffd779779ddd3922f26ae7d0a21604Chris Wilson                }
140902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
141002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
141102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* init all values */
141202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	overlay->color_key = 0x0101fe;
141302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	overlay->brightness = -19;
141402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	overlay->contrast = 75;
141502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	overlay->saturation = 146;
141602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
14178d74f656dd78ae1ba813389cd46197c6329696bcChris Wilson	regs = intel_overlay_map_regs(overlay);
141802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!regs)
141902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		goto out_free_bo;
142002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
142102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	memset(regs, 0, sizeof(struct overlay_registers));
142202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	update_polyphase_filter(regs);
142302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	update_reg_attrs(overlay, regs);
142402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
14259bb2ff731b32c023e7a502efdc0dee46157290d5Chris Wilson	intel_overlay_unmap_regs(overlay, regs);
142602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
142702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	dev_priv->overlay = overlay;
142802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	DRM_INFO("initialized overlay support\n");
142902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return;
143002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
14310ddc1289f3ffd779779ddd3922f26ae7d0a21604Chris Wilsonout_unpin_bo:
14320ddc1289f3ffd779779ddd3922f26ae7d0a21604Chris Wilson	i915_gem_object_unpin(reg_bo);
143302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterout_free_bo:
143402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	drm_gem_object_unreference(reg_bo);
143502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterout_free:
143602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	kfree(overlay);
143702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return;
143802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
143902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
144002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vettervoid intel_cleanup_overlay(struct drm_device *dev)
144102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
1442722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	drm_i915_private_t *dev_priv = dev->dev_private;
144302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
144462cf4e6fef35b4422e206b63b7f0ac90261d4ad9Chris Wilson	if (!dev_priv->overlay)
144562cf4e6fef35b4422e206b63b7f0ac90261d4ad9Chris Wilson		return;
144602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
144762cf4e6fef35b4422e206b63b7f0ac90261d4ad9Chris Wilson	/* The bo's should be free'd by the generic code already.
144862cf4e6fef35b4422e206b63b7f0ac90261d4ad9Chris Wilson	 * Furthermore modesetting teardown happens beforehand so the
144962cf4e6fef35b4422e206b63b7f0ac90261d4ad9Chris Wilson	 * hardware should be off already */
145062cf4e6fef35b4422e206b63b7f0ac90261d4ad9Chris Wilson	BUG_ON(dev_priv->overlay->active);
145162cf4e6fef35b4422e206b63b7f0ac90261d4ad9Chris Wilson
145262cf4e6fef35b4422e206b63b7f0ac90261d4ad9Chris Wilson	drm_gem_object_unreference_unlocked(&dev_priv->overlay->reg_bo->base);
145362cf4e6fef35b4422e206b63b7f0ac90261d4ad9Chris Wilson	kfree(dev_priv->overlay);
145402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
14556ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson
14563bd3c9329973a93fa3ef5e9840f2fd6fa2889e3fChris Wilson#ifdef CONFIG_DEBUG_FS
14573bd3c9329973a93fa3ef5e9840f2fd6fa2889e3fChris Wilson#include <linux/seq_file.h>
14583bd3c9329973a93fa3ef5e9840f2fd6fa2889e3fChris Wilson
14596ef3d4278034982c13df87c4a51e0445f762d316Chris Wilsonstruct intel_overlay_error_state {
14606ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	struct overlay_registers regs;
14616ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	unsigned long base;
14626ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	u32 dovsta;
14636ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	u32 isr;
14646ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson};
14656ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson
14663bd3c9329973a93fa3ef5e9840f2fd6fa2889e3fChris Wilsonstatic struct overlay_registers *
14673bd3c9329973a93fa3ef5e9840f2fd6fa2889e3fChris Wilsonintel_overlay_map_regs_atomic(struct intel_overlay *overlay,
14683bd3c9329973a93fa3ef5e9840f2fd6fa2889e3fChris Wilson			      int slot)
14693bd3c9329973a93fa3ef5e9840f2fd6fa2889e3fChris Wilson{
14703bd3c9329973a93fa3ef5e9840f2fd6fa2889e3fChris Wilson        drm_i915_private_t *dev_priv = overlay->dev->dev_private;
14713bd3c9329973a93fa3ef5e9840f2fd6fa2889e3fChris Wilson	struct overlay_registers *regs;
14723bd3c9329973a93fa3ef5e9840f2fd6fa2889e3fChris Wilson
14733bd3c9329973a93fa3ef5e9840f2fd6fa2889e3fChris Wilson	if (OVERLAY_NEEDS_PHYSICAL(overlay->dev))
14743bd3c9329973a93fa3ef5e9840f2fd6fa2889e3fChris Wilson		regs = overlay->reg_bo->phys_obj->handle->vaddr;
14753bd3c9329973a93fa3ef5e9840f2fd6fa2889e3fChris Wilson	else
14763bd3c9329973a93fa3ef5e9840f2fd6fa2889e3fChris Wilson		regs = io_mapping_map_atomic_wc(dev_priv->mm.gtt_mapping,
14773bd3c9329973a93fa3ef5e9840f2fd6fa2889e3fChris Wilson						overlay->reg_bo->gtt_offset,
14783bd3c9329973a93fa3ef5e9840f2fd6fa2889e3fChris Wilson						slot);
14793bd3c9329973a93fa3ef5e9840f2fd6fa2889e3fChris Wilson
14803bd3c9329973a93fa3ef5e9840f2fd6fa2889e3fChris Wilson	return regs;
14813bd3c9329973a93fa3ef5e9840f2fd6fa2889e3fChris Wilson}
14823bd3c9329973a93fa3ef5e9840f2fd6fa2889e3fChris Wilson
14833bd3c9329973a93fa3ef5e9840f2fd6fa2889e3fChris Wilsonstatic void intel_overlay_unmap_regs_atomic(struct intel_overlay *overlay,
14843bd3c9329973a93fa3ef5e9840f2fd6fa2889e3fChris Wilson					    int slot,
14853bd3c9329973a93fa3ef5e9840f2fd6fa2889e3fChris Wilson					    struct overlay_registers *regs)
14863bd3c9329973a93fa3ef5e9840f2fd6fa2889e3fChris Wilson{
14873bd3c9329973a93fa3ef5e9840f2fd6fa2889e3fChris Wilson	if (!OVERLAY_NEEDS_PHYSICAL(overlay->dev))
14883bd3c9329973a93fa3ef5e9840f2fd6fa2889e3fChris Wilson		io_mapping_unmap_atomic(regs, slot);
14893bd3c9329973a93fa3ef5e9840f2fd6fa2889e3fChris Wilson}
14903bd3c9329973a93fa3ef5e9840f2fd6fa2889e3fChris Wilson
14913bd3c9329973a93fa3ef5e9840f2fd6fa2889e3fChris Wilson
14926ef3d4278034982c13df87c4a51e0445f762d316Chris Wilsonstruct intel_overlay_error_state *
14936ef3d4278034982c13df87c4a51e0445f762d316Chris Wilsonintel_overlay_capture_error_state(struct drm_device *dev)
14946ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson{
14956ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson        drm_i915_private_t *dev_priv = dev->dev_private;
14966ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	struct intel_overlay *overlay = dev_priv->overlay;
14976ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	struct intel_overlay_error_state *error;
14986ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	struct overlay_registers __iomem *regs;
14996ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson
15006ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	if (!overlay || !overlay->active)
15016ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson		return NULL;
15026ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson
15036ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	error = kmalloc(sizeof(*error), GFP_ATOMIC);
15046ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	if (error == NULL)
15056ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson		return NULL;
15066ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson
15076ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	error->dovsta = I915_READ(DOVSTA);
15086ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	error->isr = I915_READ(ISR);
150931578148b2c62612f9516fdcf5ebb64ab32ed12dChris Wilson	if (OVERLAY_NEEDS_PHYSICAL(overlay->dev))
15106ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson		error->base = (long) overlay->reg_bo->phys_obj->handle->vaddr;
151131578148b2c62612f9516fdcf5ebb64ab32ed12dChris Wilson	else
151231578148b2c62612f9516fdcf5ebb64ab32ed12dChris Wilson		error->base = (long) overlay->reg_bo->gtt_offset;
15136ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson
15148d74f656dd78ae1ba813389cd46197c6329696bcChris Wilson	regs = intel_overlay_map_regs_atomic(overlay, KM_IRQ0);
15156ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	if (!regs)
15166ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson		goto err;
15176ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson
15186ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	memcpy_fromio(&error->regs, regs, sizeof(struct overlay_registers));
15199bb2ff731b32c023e7a502efdc0dee46157290d5Chris Wilson	intel_overlay_unmap_regs_atomic(overlay, KM_IRQ0, regs);
15206ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson
15216ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	return error;
15226ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson
15236ef3d4278034982c13df87c4a51e0445f762d316Chris Wilsonerr:
15246ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	kfree(error);
15256ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	return NULL;
15266ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson}
15276ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson
15286ef3d4278034982c13df87c4a51e0445f762d316Chris Wilsonvoid
15296ef3d4278034982c13df87c4a51e0445f762d316Chris Wilsonintel_overlay_print_error_state(struct seq_file *m, struct intel_overlay_error_state *error)
15306ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson{
15316ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	seq_printf(m, "Overlay, status: 0x%08x, interrupt: 0x%08x\n",
15326ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson		   error->dovsta, error->isr);
15336ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	seq_printf(m, "  Register file at 0x%08lx:\n",
15346ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson		   error->base);
15356ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson
15366ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson#define P(x) seq_printf(m, "    " #x ":	0x%08x\n", error->regs.x)
15376ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OBUF_0Y);
15386ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OBUF_1Y);
15396ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OBUF_0U);
15406ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OBUF_0V);
15416ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OBUF_1U);
15426ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OBUF_1V);
15436ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OSTRIDE);
15446ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(YRGB_VPH);
15456ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(UV_VPH);
15466ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(HORZ_PH);
15476ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(INIT_PHS);
15486ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(DWINPOS);
15496ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(DWINSZ);
15506ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(SWIDTH);
15516ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(SWIDTHSW);
15526ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(SHEIGHT);
15536ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(YRGBSCALE);
15546ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(UVSCALE);
15556ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OCLRC0);
15566ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OCLRC1);
15576ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(DCLRKV);
15586ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(DCLRKM);
15596ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(SCLRKVH);
15606ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(SCLRKVL);
15616ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(SCLRKEN);
15626ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OCONFIG);
15636ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OCMD);
15646ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OSTART_0Y);
15656ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OSTART_1Y);
15666ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OSTART_0U);
15676ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OSTART_0V);
15686ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OSTART_1U);
15696ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OSTART_1V);
15706ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OTILEOFF_0Y);
15716ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OTILEOFF_1Y);
15726ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OTILEOFF_0U);
15736ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OTILEOFF_0V);
15746ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OTILEOFF_1U);
15756ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OTILEOFF_1V);
15766ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(FASTHSCALE);
15776ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(UVSCALEV);
15786ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson#undef P
15796ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson}
15803bd3c9329973a93fa3ef5e9840f2fd6fa2889e3fChris Wilson#endif
1581