intel_overlay.c revision b303cf9542b016e2af3b9d17255a7f93cd790ef5
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_atomic(struct intel_overlay *overlay,
1948d74f656dd78ae1ba813389cd46197c6329696bcChris Wilson			      int slot)
19502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
19602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter        drm_i915_private_t *dev_priv = overlay->dev->dev_private;
19702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct overlay_registers *regs;
19802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
1999bb2ff731b32c023e7a502efdc0dee46157290d5Chris Wilson	if (OVERLAY_NEEDS_PHYSICAL(overlay->dev))
20031578148b2c62612f9516fdcf5ebb64ab32ed12dChris Wilson		regs = overlay->reg_bo->phys_obj->handle->vaddr;
2019bb2ff731b32c023e7a502efdc0dee46157290d5Chris Wilson	else
20202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		regs = io_mapping_map_atomic_wc(dev_priv->mm.gtt_mapping,
203fca3ec01e0b40cab82cac7745e154b01969e6219Chris Wilson						overlay->reg_bo->gtt_offset,
2048d74f656dd78ae1ba813389cd46197c6329696bcChris Wilson						slot);
20502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
2069bb2ff731b32c023e7a502efdc0dee46157290d5Chris Wilson	return regs;
20702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
20802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
2098d74f656dd78ae1ba813389cd46197c6329696bcChris Wilsonstatic void intel_overlay_unmap_regs_atomic(struct intel_overlay *overlay,
2109bb2ff731b32c023e7a502efdc0dee46157290d5Chris Wilson					    int slot,
2119bb2ff731b32c023e7a502efdc0dee46157290d5Chris Wilson					    struct overlay_registers *regs)
21202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
21331578148b2c62612f9516fdcf5ebb64ab32ed12dChris Wilson	if (!OVERLAY_NEEDS_PHYSICAL(overlay->dev))
2149bb2ff731b32c023e7a502efdc0dee46157290d5Chris Wilson		io_mapping_unmap_atomic(regs, slot);
2158d74f656dd78ae1ba813389cd46197c6329696bcChris Wilson}
2168d74f656dd78ae1ba813389cd46197c6329696bcChris Wilson
2178d74f656dd78ae1ba813389cd46197c6329696bcChris Wilsonstatic struct overlay_registers *
2188d74f656dd78ae1ba813389cd46197c6329696bcChris Wilsonintel_overlay_map_regs(struct intel_overlay *overlay)
2198d74f656dd78ae1ba813389cd46197c6329696bcChris Wilson{
2208d74f656dd78ae1ba813389cd46197c6329696bcChris Wilson        drm_i915_private_t *dev_priv = overlay->dev->dev_private;
2218d74f656dd78ae1ba813389cd46197c6329696bcChris Wilson	struct overlay_registers *regs;
2228d74f656dd78ae1ba813389cd46197c6329696bcChris Wilson
2239bb2ff731b32c023e7a502efdc0dee46157290d5Chris Wilson	if (OVERLAY_NEEDS_PHYSICAL(overlay->dev))
2248d74f656dd78ae1ba813389cd46197c6329696bcChris Wilson		regs = overlay->reg_bo->phys_obj->handle->vaddr;
2259bb2ff731b32c023e7a502efdc0dee46157290d5Chris Wilson	else
2268d74f656dd78ae1ba813389cd46197c6329696bcChris Wilson		regs = io_mapping_map_wc(dev_priv->mm.gtt_mapping,
2278d74f656dd78ae1ba813389cd46197c6329696bcChris Wilson					 overlay->reg_bo->gtt_offset);
2288d74f656dd78ae1ba813389cd46197c6329696bcChris Wilson
2299bb2ff731b32c023e7a502efdc0dee46157290d5Chris Wilson	return regs;
2308d74f656dd78ae1ba813389cd46197c6329696bcChris Wilson}
2318d74f656dd78ae1ba813389cd46197c6329696bcChris Wilson
2329bb2ff731b32c023e7a502efdc0dee46157290d5Chris Wilsonstatic void intel_overlay_unmap_regs(struct intel_overlay *overlay,
2339bb2ff731b32c023e7a502efdc0dee46157290d5Chris Wilson				     struct overlay_registers *regs)
2348d74f656dd78ae1ba813389cd46197c6329696bcChris Wilson{
2358d74f656dd78ae1ba813389cd46197c6329696bcChris Wilson	if (!OVERLAY_NEEDS_PHYSICAL(overlay->dev))
2369bb2ff731b32c023e7a502efdc0dee46157290d5Chris Wilson		io_mapping_unmap(regs);
23702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
23802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
239b6c028e00445de9dfde2cd0c26521ac53965320aChris Wilsonstatic int intel_overlay_do_wait_request(struct intel_overlay *overlay,
2408dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson					 struct drm_i915_gem_request *request,
241b6c028e00445de9dfde2cd0c26521ac53965320aChris Wilson					 bool interruptible,
242b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson					 void (*tail)(struct intel_overlay *))
24302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
24402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct drm_device *dev = overlay->dev;
245852835f343146a82a528c3b712b373661d4fa17aZou Nan hai	drm_i915_private_t *dev_priv = dev->dev_private;
246b6c028e00445de9dfde2cd0c26521ac53965320aChris Wilson	int ret;
24702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
248b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson	BUG_ON(overlay->last_flip_req);
249852835f343146a82a528c3b712b373661d4fa17aZou Nan hai	overlay->last_flip_req =
2508dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson		i915_add_request(dev, NULL, request, &dev_priv->render_ring);
25103f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	if (overlay->last_flip_req == 0)
25203f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter		return -ENOMEM;
25302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
254b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson	overlay->flip_tail = tail;
255852835f343146a82a528c3b712b373661d4fa17aZou Nan hai	ret = i915_do_wait_request(dev,
256722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson				   overlay->last_flip_req, true,
257722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson				   &dev_priv->render_ring);
258b6c028e00445de9dfde2cd0c26521ac53965320aChris Wilson	if (ret)
25903f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter		return ret;
26002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
26103f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	overlay->last_flip_req = 0;
26202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return 0;
26302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
26402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
265106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson/* Workaround for i830 bug where pipe a must be enable to change control regs */
266106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilsonstatic int
267106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilsoni830_activate_pipe_a(struct drm_device *dev)
268106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson{
269106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	drm_i915_private_t *dev_priv = dev->dev_private;
270106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	struct intel_crtc *crtc;
271106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	struct drm_crtc_helper_funcs *crtc_funcs;
272106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	struct drm_display_mode vesa_640x480 = {
273106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson		DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 25175, 640, 656,
274106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson			 752, 800, 0, 480, 489, 492, 525, 0,
275106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson			 DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC)
276106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	}, *mode;
277106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson
278106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	crtc = to_intel_crtc(dev_priv->pipe_to_crtc_mapping[0]);
279106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	if (crtc->dpms_mode == DRM_MODE_DPMS_ON)
280106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson		return 0;
281106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson
282106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	/* most i8xx have pipe a forced on, so don't trust dpms mode */
283106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	if (I915_READ(PIPEACONF) & PIPEACONF_ENABLE)
284106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson		return 0;
285106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson
286106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	crtc_funcs = crtc->base.helper_private;
287106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	if (crtc_funcs->dpms == NULL)
288106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson		return 0;
289106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson
290106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	DRM_DEBUG_DRIVER("Enabling pipe A in order to enable overlay\n");
291106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson
292106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	mode = drm_mode_duplicate(dev, &vesa_640x480);
293106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V);
294106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	if(!drm_crtc_helper_set_mode(&crtc->base, mode,
295106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson				       crtc->base.x, crtc->base.y,
296106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson				       crtc->base.fb))
297106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson		return 0;
298106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson
299106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	crtc_funcs->dpms(&crtc->base, DRM_MODE_DPMS_ON);
300106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	return 1;
301106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson}
302106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson
303106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilsonstatic void
304106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilsoni830_deactivate_pipe_a(struct drm_device *dev)
305106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson{
306106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	drm_i915_private_t *dev_priv = dev->dev_private;
307106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[0];
308106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
309106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson
310106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	crtc_funcs->dpms(crtc, DRM_MODE_DPMS_OFF);
311106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson}
312106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson
313b6c028e00445de9dfde2cd0c26521ac53965320aChris Wilson/* overlay needs to be disable in OCMD reg */
314b6c028e00445de9dfde2cd0c26521ac53965320aChris Wilsonstatic int intel_overlay_on(struct intel_overlay *overlay)
315b6c028e00445de9dfde2cd0c26521ac53965320aChris Wilson{
316b6c028e00445de9dfde2cd0c26521ac53965320aChris Wilson	struct drm_device *dev = overlay->dev;
3178dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson	struct drm_i915_gem_request *request;
318106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	int pipe_a_quirk = 0;
319106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	int ret;
320b6c028e00445de9dfde2cd0c26521ac53965320aChris Wilson
321b6c028e00445de9dfde2cd0c26521ac53965320aChris Wilson	BUG_ON(overlay->active);
322b6c028e00445de9dfde2cd0c26521ac53965320aChris Wilson	overlay->active = 1;
323b6c028e00445de9dfde2cd0c26521ac53965320aChris Wilson
324106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	if (IS_I830(dev)) {
325106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson		pipe_a_quirk = i830_activate_pipe_a(dev);
326106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson		if (pipe_a_quirk < 0)
327106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson			return pipe_a_quirk;
328106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	}
329106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson
3308dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson	request = kzalloc(sizeof(*request), GFP_KERNEL);
331106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	if (request == NULL) {
332106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson		ret = -ENOMEM;
333106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson		goto out;
334106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	}
3358dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson
336b6c028e00445de9dfde2cd0c26521ac53965320aChris Wilson	BEGIN_LP_RING(4);
337b6c028e00445de9dfde2cd0c26521ac53965320aChris Wilson	OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_ON);
338b6c028e00445de9dfde2cd0c26521ac53965320aChris Wilson	OUT_RING(overlay->flip_addr | OFC_UPDATE);
339b6c028e00445de9dfde2cd0c26521ac53965320aChris Wilson	OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
340b6c028e00445de9dfde2cd0c26521ac53965320aChris Wilson	OUT_RING(MI_NOOP);
341b6c028e00445de9dfde2cd0c26521ac53965320aChris Wilson	ADVANCE_LP_RING();
342b6c028e00445de9dfde2cd0c26521ac53965320aChris Wilson
343b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson	ret = intel_overlay_do_wait_request(overlay, request, true, NULL);
344106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilsonout:
345106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	if (pipe_a_quirk)
346106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson		i830_deactivate_pipe_a(dev);
347106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson
348106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	return ret;
349b6c028e00445de9dfde2cd0c26521ac53965320aChris Wilson}
350b6c028e00445de9dfde2cd0c26521ac53965320aChris Wilson
35102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter/* overlay needs to be enabled in OCMD reg */
3528dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilsonstatic int intel_overlay_continue(struct intel_overlay *overlay,
3538dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson				  bool load_polyphase_filter)
35402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
35502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct drm_device *dev = overlay->dev;
35602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter        drm_i915_private_t *dev_priv = dev->dev_private;
3578dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson	struct drm_i915_gem_request *request;
35802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	u32 flip_addr = overlay->flip_addr;
35902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	u32 tmp;
36002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
36102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	BUG_ON(!overlay->active);
36202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
3638dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson	request = kzalloc(sizeof(*request), GFP_KERNEL);
3648dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson	if (request == NULL)
3658dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson		return -ENOMEM;
3668dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson
36702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (load_polyphase_filter)
36802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		flip_addr |= OFC_UPDATE;
36902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
37002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* check for underruns */
37102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	tmp = I915_READ(DOVSTA);
37202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (tmp & (1 << 17))
37302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		DRM_DEBUG("overlay underrun, DOVSTA: %x\n", tmp);
37402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
3754f8a567c4666c73284832240db89fdadb2c50bd5Daniel Vetter	BEGIN_LP_RING(2);
37602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_CONTINUE);
37702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	OUT_RING(flip_addr);
3785a5a0c64a99d7542c48c99d1a8bbb49e665842beDaniel Vetter        ADVANCE_LP_RING();
3795a5a0c64a99d7542c48c99d1a8bbb49e665842beDaniel Vetter
380852835f343146a82a528c3b712b373661d4fa17aZou Nan hai	overlay->last_flip_req =
3818dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson		i915_add_request(dev, NULL, request, &dev_priv->render_ring);
3828dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson	return 0;
3835a5a0c64a99d7542c48c99d1a8bbb49e665842beDaniel Vetter}
3845a5a0c64a99d7542c48c99d1a8bbb49e665842beDaniel Vetter
385b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilsonstatic void intel_overlay_release_old_vid_tail(struct intel_overlay *overlay)
386b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson{
387b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson	struct drm_gem_object *obj = &overlay->old_vid_bo->base;
388b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson
389b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson	i915_gem_object_unpin(obj);
390b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson	drm_gem_object_unreference(obj);
391b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson
392b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson	overlay->old_vid_bo = NULL;
393b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson}
394b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson
395b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilsonstatic void intel_overlay_off_tail(struct intel_overlay *overlay)
396b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson{
397b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson	struct drm_gem_object *obj;
398b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson
399b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson	/* never have the overlay hw on without showing a frame */
400b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson	BUG_ON(!overlay->vid_bo);
401b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson	obj = &overlay->vid_bo->base;
402b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson
403b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson	i915_gem_object_unpin(obj);
404b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson	drm_gem_object_unreference(obj);
405b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson	overlay->vid_bo = NULL;
406b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson
407b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson	overlay->crtc->overlay = NULL;
408b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson	overlay->crtc = NULL;
409b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson	overlay->active = 0;
410b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson}
411b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson
41202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter/* overlay needs to be disabled in OCMD reg */
4135dcdbcb06badbdf2faa698bf3198e421a1e12840Chris Wilsonstatic int intel_overlay_off(struct intel_overlay *overlay,
4145dcdbcb06badbdf2faa698bf3198e421a1e12840Chris Wilson			     bool interruptible)
41502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
41602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct drm_device *dev = overlay->dev;
4178dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson	u32 flip_addr = overlay->flip_addr;
4188dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson	struct drm_i915_gem_request *request;
41902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
42002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	BUG_ON(!overlay->active);
42102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
4228dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson	request = kzalloc(sizeof(*request), GFP_KERNEL);
4238dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson	if (request == NULL)
4248dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson		return -ENOMEM;
4258dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson
42602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* According to intel docs the overlay hw may hang (when switching
42702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	 * off) without loading the filter coeffs. It is however unclear whether
42802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	 * this applies to the disabling of the overlay or to the switching off
42902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	 * of the hw. Do it in both cases */
43002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	flip_addr |= OFC_UPDATE;
43102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
4328dfbc3403113bcc51f0350c3471fa1abf664305fChris Wilson	BEGIN_LP_RING(6);
43302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* wait for overlay to go idle */
43402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_CONTINUE);
43502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	OUT_RING(flip_addr);
436722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
43702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* turn overlay off */
438722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_OFF);
43902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	OUT_RING(flip_addr);
440722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
44102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	ADVANCE_LP_RING();
44202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
4435dcdbcb06badbdf2faa698bf3198e421a1e12840Chris Wilson	return intel_overlay_do_wait_request(overlay, request, interruptible,
444b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson					     intel_overlay_off_tail);
44512ca45fea91cfbb09df828bea958b47348caee6dDaniel Vetter}
44612ca45fea91cfbb09df828bea958b47348caee6dDaniel Vetter
44703f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter/* recover from an interruption due to a signal
44803f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter * We have to be careful not to repeat work forever an make forward progess. */
4495dcdbcb06badbdf2faa698bf3198e421a1e12840Chris Wilsonstatic int intel_overlay_recover_from_interrupt(struct intel_overlay *overlay,
4505dcdbcb06badbdf2faa698bf3198e421a1e12840Chris Wilson						bool interruptible)
45103f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter{
45203f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	struct drm_device *dev = overlay->dev;
453852835f343146a82a528c3b712b373661d4fa17aZou Nan hai	drm_i915_private_t *dev_priv = dev->dev_private;
45403f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	int ret;
45503f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter
456b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson	if (overlay->last_flip_req == 0)
457b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson		return 0;
45803f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter
459852835f343146a82a528c3b712b373661d4fa17aZou Nan hai	ret = i915_do_wait_request(dev, overlay->last_flip_req,
460722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson				   interruptible, &dev_priv->render_ring);
461b6c028e00445de9dfde2cd0c26521ac53965320aChris Wilson	if (ret)
46203f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter		return ret;
46303f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter
464b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson	if (overlay->flip_tail)
465b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson		overlay->flip_tail(overlay);
466b6c028e00445de9dfde2cd0c26521ac53965320aChris Wilson
46703f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	overlay->last_flip_req = 0;
46803f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	return 0;
46903f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter}
47003f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter
4715a5a0c64a99d7542c48c99d1a8bbb49e665842beDaniel Vetter/* Wait for pending overlay flip and release old frame.
4725a5a0c64a99d7542c48c99d1a8bbb49e665842beDaniel Vetter * Needs to be called before the overlay register are changed
4738d74f656dd78ae1ba813389cd46197c6329696bcChris Wilson * via intel_overlay_(un)map_regs
4748d74f656dd78ae1ba813389cd46197c6329696bcChris Wilson */
47502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic int intel_overlay_release_old_vid(struct intel_overlay *overlay)
47602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
4775cd68c9864d65e49c910c701716e4e94e09f7ce0Chris Wilson	struct drm_device *dev = overlay->dev;
4785cd68c9864d65e49c910c701716e4e94e09f7ce0Chris Wilson	drm_i915_private_t *dev_priv = dev->dev_private;
47902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int ret;
48002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
4815cd68c9864d65e49c910c701716e4e94e09f7ce0Chris Wilson	/* Only wait if there is actually an old frame to release to
4825cd68c9864d65e49c910c701716e4e94e09f7ce0Chris Wilson	 * guarantee forward progress.
4835cd68c9864d65e49c910c701716e4e94e09f7ce0Chris Wilson	 */
48403f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	if (!overlay->old_vid_bo)
48503f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter		return 0;
48603f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter
4875cd68c9864d65e49c910c701716e4e94e09f7ce0Chris Wilson	if (I915_READ(ISR) & I915_OVERLAY_PLANE_FLIP_PENDING_INTERRUPT) {
4888dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson		struct drm_i915_gem_request *request;
4898dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson
4905cd68c9864d65e49c910c701716e4e94e09f7ce0Chris Wilson		/* synchronous slowpath */
4918dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson		request = kzalloc(sizeof(*request), GFP_KERNEL);
4928dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson		if (request == NULL)
4938dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson			return -ENOMEM;
4948dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson
4955cd68c9864d65e49c910c701716e4e94e09f7ce0Chris Wilson		BEGIN_LP_RING(2);
4965cd68c9864d65e49c910c701716e4e94e09f7ce0Chris Wilson		OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
4975cd68c9864d65e49c910c701716e4e94e09f7ce0Chris Wilson		OUT_RING(MI_NOOP);
4985cd68c9864d65e49c910c701716e4e94e09f7ce0Chris Wilson		ADVANCE_LP_RING();
4995cd68c9864d65e49c910c701716e4e94e09f7ce0Chris Wilson
5008dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson		ret = intel_overlay_do_wait_request(overlay, request, true,
501b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson						    intel_overlay_release_old_vid_tail);
5025cd68c9864d65e49c910c701716e4e94e09f7ce0Chris Wilson		if (ret)
5035cd68c9864d65e49c910c701716e4e94e09f7ce0Chris Wilson			return ret;
5045cd68c9864d65e49c910c701716e4e94e09f7ce0Chris Wilson	}
50502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
5065cd68c9864d65e49c910c701716e4e94e09f7ce0Chris Wilson	intel_overlay_release_old_vid_tail(overlay);
50702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return 0;
50802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
50902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
51002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstruct put_image_params {
51102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int format;
51202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	short dst_x;
51302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	short dst_y;
51402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	short dst_w;
51502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	short dst_h;
51602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	short src_w;
51702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	short src_scan_h;
51802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	short src_scan_w;
51902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	short src_h;
52002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	short stride_Y;
52102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	short stride_UV;
52202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int offset_Y;
52302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int offset_U;
52402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int offset_V;
52502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter};
52602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
52702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic int packed_depth_bytes(u32 format)
52802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
52902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	switch (format & I915_OVERLAY_DEPTH_MASK) {
530722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case I915_OVERLAY_YUV422:
531722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		return 4;
532722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case I915_OVERLAY_YUV411:
533722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		/* return 6; not implemented */
534722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	default:
535722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		return -EINVAL;
53602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
53702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
53802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
53902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic int packed_width_bytes(u32 format, short width)
54002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
54102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	switch (format & I915_OVERLAY_DEPTH_MASK) {
542722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case I915_OVERLAY_YUV422:
543722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		return width << 1;
544722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	default:
545722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		return -EINVAL;
54602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
54702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
54802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
54902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic int uv_hsubsampling(u32 format)
55002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
55102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	switch (format & I915_OVERLAY_DEPTH_MASK) {
552722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case I915_OVERLAY_YUV422:
553722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case I915_OVERLAY_YUV420:
554722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		return 2;
555722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case I915_OVERLAY_YUV411:
556722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case I915_OVERLAY_YUV410:
557722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		return 4;
558722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	default:
559722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		return -EINVAL;
56002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
56102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
56202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
56302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic int uv_vsubsampling(u32 format)
56402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
56502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	switch (format & I915_OVERLAY_DEPTH_MASK) {
566722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case I915_OVERLAY_YUV420:
567722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case I915_OVERLAY_YUV410:
568722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		return 2;
569722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case I915_OVERLAY_YUV422:
570722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case I915_OVERLAY_YUV411:
571722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		return 1;
572722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	default:
573722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		return -EINVAL;
57402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
57502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
57602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
57702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic u32 calc_swidthsw(struct drm_device *dev, u32 offset, u32 width)
57802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
57902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	u32 mask, shift, ret;
58002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (IS_I9XX(dev)) {
58102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		mask = 0x3f;
58202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		shift = 6;
58302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	} else {
58402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		mask = 0x1f;
58502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		shift = 5;
58602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
58702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	ret = ((offset + width + mask) >> shift) - (offset >> shift);
58802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (IS_I9XX(dev))
58902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		ret <<= 1;
59002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	ret -=1;
59102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return ret << 2;
59202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
59302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
59402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic const u16 y_static_hcoeffs[N_HORIZ_Y_TAPS * N_PHASES] = {
59502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3000, 0xb4a0, 0x1930, 0x1920, 0xb4a0,
59602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3000, 0xb500, 0x19d0, 0x1880, 0xb440,
59702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3000, 0xb540, 0x1a88, 0x2f80, 0xb3e0,
59802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3000, 0xb580, 0x1b30, 0x2e20, 0xb380,
59902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3000, 0xb5c0, 0x1bd8, 0x2cc0, 0xb320,
60002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3020, 0xb5e0, 0x1c60, 0x2b80, 0xb2c0,
60102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3020, 0xb5e0, 0x1cf8, 0x2a20, 0xb260,
60202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3020, 0xb5e0, 0x1d80, 0x28e0, 0xb200,
60302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3020, 0xb5c0, 0x1e08, 0x3f40, 0xb1c0,
60402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3020, 0xb580, 0x1e78, 0x3ce0, 0xb160,
60502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3040, 0xb520, 0x1ed8, 0x3aa0, 0xb120,
60602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3040, 0xb4a0, 0x1f30, 0x3880, 0xb0e0,
60702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3040, 0xb400, 0x1f78, 0x3680, 0xb0a0,
60802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3020, 0xb340, 0x1fb8, 0x34a0, 0xb060,
60902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3020, 0xb240, 0x1fe0, 0x32e0, 0xb040,
61002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3020, 0xb140, 0x1ff8, 0x3160, 0xb020,
611722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	0xb000, 0x3000, 0x0800, 0x3000, 0xb000
612722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson};
613722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson
61402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic const u16 uv_static_hcoeffs[N_HORIZ_UV_TAPS * N_PHASES] = {
61502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3000, 0x1800, 0x1800, 0xb000, 0x18d0, 0x2e60,
61602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0xb000, 0x1990, 0x2ce0, 0xb020, 0x1a68, 0x2b40,
61702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0xb040, 0x1b20, 0x29e0, 0xb060, 0x1bd8, 0x2880,
61802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0xb080, 0x1c88, 0x3e60, 0xb0a0, 0x1d28, 0x3c00,
61902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0xb0c0, 0x1db8, 0x39e0, 0xb0e0, 0x1e40, 0x37e0,
62002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0xb100, 0x1eb8, 0x3620, 0xb100, 0x1f18, 0x34a0,
62102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0xb100, 0x1f68, 0x3360, 0xb0e0, 0x1fa8, 0x3240,
62202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0xb0c0, 0x1fe0, 0x3140, 0xb060, 0x1ff0, 0x30a0,
623722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	0x3000, 0x0800, 0x3000
624722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson};
62502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
62602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic void update_polyphase_filter(struct overlay_registers *regs)
62702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
62802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	memcpy(regs->Y_HCOEFS, y_static_hcoeffs, sizeof(y_static_hcoeffs));
62902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	memcpy(regs->UV_HCOEFS, uv_static_hcoeffs, sizeof(uv_static_hcoeffs));
63002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
63102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
63202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic bool update_scaling_factors(struct intel_overlay *overlay,
63302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				   struct overlay_registers *regs,
63402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				   struct put_image_params *params)
63502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
63602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* fixed point with a 12 bit shift */
63702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	u32 xscale, yscale, xscale_UV, yscale_UV;
63802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define FP_SHIFT 12
63902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define FRACT_MASK 0xfff
64002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	bool scale_changed = false;
64102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int uv_hscale = uv_hsubsampling(params->format);
64202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int uv_vscale = uv_vsubsampling(params->format);
64302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
64402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (params->dst_w > 1)
64502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		xscale = ((params->src_scan_w - 1) << FP_SHIFT)
64602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			/(params->dst_w);
64702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	else
64802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		xscale = 1 << FP_SHIFT;
64902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
65002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (params->dst_h > 1)
65102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		yscale = ((params->src_scan_h - 1) << FP_SHIFT)
65202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			/(params->dst_h);
65302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	else
65402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		yscale = 1 << FP_SHIFT;
65502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
65602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/*if (params->format & I915_OVERLAY_YUV_PLANAR) {*/
657722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	xscale_UV = xscale/uv_hscale;
658722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	yscale_UV = yscale/uv_vscale;
659722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	/* make the Y scale to UV scale ratio an exact multiply */
660722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	xscale = xscale_UV * uv_hscale;
661722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	yscale = yscale_UV * uv_vscale;
66202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/*} else {
663722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	  xscale_UV = 0;
664722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	  yscale_UV = 0;
665722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	  }*/
66602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
66702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (xscale != overlay->old_xscale || yscale != overlay->old_yscale)
66802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		scale_changed = true;
66902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	overlay->old_xscale = xscale;
67002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	overlay->old_yscale = yscale;
67102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
672722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	regs->YRGBSCALE = (((yscale & FRACT_MASK) << 20) |
673722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			   ((xscale >> FP_SHIFT)  << 16) |
674722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			   ((xscale & FRACT_MASK) << 3));
675722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson
676722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	regs->UVSCALE = (((yscale_UV & FRACT_MASK) << 20) |
677722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			 ((xscale_UV >> FP_SHIFT)  << 16) |
678722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			 ((xscale_UV & FRACT_MASK) << 3));
679722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson
680722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	regs->UVSCALEV = ((((yscale    >> FP_SHIFT) << 16) |
681722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			   ((yscale_UV >> FP_SHIFT) << 0)));
68202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
68302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (scale_changed)
68402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		update_polyphase_filter(regs);
68502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
68602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return scale_changed;
68702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
68802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
68902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic void update_colorkey(struct intel_overlay *overlay,
69002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			    struct overlay_registers *regs)
69102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
69202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	u32 key = overlay->color_key;
6936ba3ddd9838f5e4d6ac7c6dce95648d205e11bffChris Wilson
69402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	switch (overlay->crtc->base.fb->bits_per_pixel) {
695722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case 8:
696722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		regs->DCLRKV = 0;
697722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		regs->DCLRKM = CLK_RGB8I_MASK | DST_KEY_ENABLE;
6986ba3ddd9838f5e4d6ac7c6dce95648d205e11bffChris Wilson		break;
6996ba3ddd9838f5e4d6ac7c6dce95648d205e11bffChris Wilson
700722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case 16:
701722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		if (overlay->crtc->base.fb->depth == 15) {
702722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			regs->DCLRKV = RGB15_TO_COLORKEY(key);
703722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			regs->DCLRKM = CLK_RGB15_MASK | DST_KEY_ENABLE;
704722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		} else {
705722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			regs->DCLRKV = RGB16_TO_COLORKEY(key);
706722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			regs->DCLRKM = CLK_RGB16_MASK | DST_KEY_ENABLE;
707722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		}
7086ba3ddd9838f5e4d6ac7c6dce95648d205e11bffChris Wilson		break;
7096ba3ddd9838f5e4d6ac7c6dce95648d205e11bffChris Wilson
710722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case 24:
711722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case 32:
712722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		regs->DCLRKV = key;
713722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		regs->DCLRKM = CLK_RGB24_MASK | DST_KEY_ENABLE;
7146ba3ddd9838f5e4d6ac7c6dce95648d205e11bffChris Wilson		break;
71502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
71602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
71702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
71802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic u32 overlay_cmd_reg(struct put_image_params *params)
71902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
72002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	u32 cmd = OCMD_ENABLE | OCMD_BUF_TYPE_FRAME | OCMD_BUFFER0;
72102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
72202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (params->format & I915_OVERLAY_YUV_PLANAR) {
72302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		switch (params->format & I915_OVERLAY_DEPTH_MASK) {
724722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		case I915_OVERLAY_YUV422:
725722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			cmd |= OCMD_YUV_422_PLANAR;
726722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			break;
727722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		case I915_OVERLAY_YUV420:
728722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			cmd |= OCMD_YUV_420_PLANAR;
729722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			break;
730722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		case I915_OVERLAY_YUV411:
731722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		case I915_OVERLAY_YUV410:
732722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			cmd |= OCMD_YUV_410_PLANAR;
733722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			break;
73402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		}
73502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	} else { /* YUV packed */
73602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		switch (params->format & I915_OVERLAY_DEPTH_MASK) {
737722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		case I915_OVERLAY_YUV422:
738722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			cmd |= OCMD_YUV_422_PACKED;
739722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			break;
740722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		case I915_OVERLAY_YUV411:
741722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			cmd |= OCMD_YUV_411_PACKED;
742722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			break;
74302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		}
74402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
74502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		switch (params->format & I915_OVERLAY_SWAP_MASK) {
746722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		case I915_OVERLAY_NO_SWAP:
747722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			break;
748722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		case I915_OVERLAY_UV_SWAP:
749722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			cmd |= OCMD_UV_SWAP;
750722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			break;
751722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		case I915_OVERLAY_Y_SWAP:
752722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			cmd |= OCMD_Y_SWAP;
753722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			break;
754722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		case I915_OVERLAY_Y_AND_UV_SWAP:
755722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			cmd |= OCMD_Y_AND_UV_SWAP;
756722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			break;
75702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		}
75802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
75902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
76002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return cmd;
76102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
76202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
7635fe82c5ee1ba2d04183c376038c5d233a0311ec9Chris Wilsonstatic int intel_overlay_do_put_image(struct intel_overlay *overlay,
7645fe82c5ee1ba2d04183c376038c5d233a0311ec9Chris Wilson				      struct drm_gem_object *new_bo,
7655fe82c5ee1ba2d04183c376038c5d233a0311ec9Chris Wilson				      struct put_image_params *params)
76602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
76702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int ret, tmp_width;
76802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct overlay_registers *regs;
76902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	bool scale_changed = false;
77023010e43b353c2cdc9725cbedc7e364708039bf7Daniel Vetter	struct drm_i915_gem_object *bo_priv = to_intel_bo(new_bo);
77102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct drm_device *dev = overlay->dev;
77202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
77302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	BUG_ON(!mutex_is_locked(&dev->struct_mutex));
77402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	BUG_ON(!mutex_is_locked(&dev->mode_config.mutex));
77502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	BUG_ON(!overlay);
77602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
77702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	ret = intel_overlay_release_old_vid(overlay);
77802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (ret != 0)
77902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return ret;
78002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
78102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	ret = i915_gem_object_pin(new_bo, PAGE_SIZE);
78202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (ret != 0)
78302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return ret;
78402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
78502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	ret = i915_gem_object_set_to_gtt_domain(new_bo, 0);
78602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (ret != 0)
78702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		goto out_unpin;
78802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
78902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!overlay->active) {
7908d74f656dd78ae1ba813389cd46197c6329696bcChris Wilson		regs = intel_overlay_map_regs(overlay);
79102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		if (!regs) {
79202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			ret = -ENOMEM;
79302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			goto out_unpin;
79402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		}
79502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		regs->OCONFIG = OCONF_CC_OUT_8BIT;
79602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		if (IS_I965GM(overlay->dev))
79702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			regs->OCONFIG |= OCONF_CSC_MODE_BT709;
79802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		regs->OCONFIG |= overlay->crtc->pipe == 0 ?
79902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			OCONF_PIPE_A : OCONF_PIPE_B;
8009bb2ff731b32c023e7a502efdc0dee46157290d5Chris Wilson		intel_overlay_unmap_regs(overlay, regs);
80102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
80202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		ret = intel_overlay_on(overlay);
80302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		if (ret != 0)
80402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			goto out_unpin;
80502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
80602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
8078d74f656dd78ae1ba813389cd46197c6329696bcChris Wilson	regs = intel_overlay_map_regs(overlay);
80802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!regs) {
80902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		ret = -ENOMEM;
81002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		goto out_unpin;
81102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
81202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
81302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	regs->DWINPOS = (params->dst_y << 16) | params->dst_x;
81402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	regs->DWINSZ = (params->dst_h << 16) | params->dst_w;
81502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
81602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (params->format & I915_OVERLAY_YUV_PACKED)
81702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		tmp_width = packed_width_bytes(params->format, params->src_w);
81802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	else
81902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		tmp_width = params->src_w;
82002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
82102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	regs->SWIDTH = params->src_w;
82202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	regs->SWIDTHSW = calc_swidthsw(overlay->dev,
823722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson				       params->offset_Y, tmp_width);
82402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	regs->SHEIGHT = params->src_h;
82502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	regs->OBUF_0Y = bo_priv->gtt_offset + params-> offset_Y;
82602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	regs->OSTRIDE = params->stride_Y;
82702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
82802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (params->format & I915_OVERLAY_YUV_PLANAR) {
82902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		int uv_hscale = uv_hsubsampling(params->format);
83002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		int uv_vscale = uv_vsubsampling(params->format);
83102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		u32 tmp_U, tmp_V;
83202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		regs->SWIDTH |= (params->src_w/uv_hscale) << 16;
83302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		tmp_U = calc_swidthsw(overlay->dev, params->offset_U,
834722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson				      params->src_w/uv_hscale);
83502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		tmp_V = calc_swidthsw(overlay->dev, params->offset_V,
836722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson				      params->src_w/uv_hscale);
83702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		regs->SWIDTHSW |= max_t(u32, tmp_U, tmp_V) << 16;
83802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		regs->SHEIGHT |= (params->src_h/uv_vscale) << 16;
83902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		regs->OBUF_0U = bo_priv->gtt_offset + params->offset_U;
84002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		regs->OBUF_0V = bo_priv->gtt_offset + params->offset_V;
84102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		regs->OSTRIDE |= params->stride_UV << 16;
84202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
84302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
84402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	scale_changed = update_scaling_factors(overlay, regs, params);
84502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
84602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	update_colorkey(overlay, regs);
84702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
84802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	regs->OCMD = overlay_cmd_reg(params);
84902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
8509bb2ff731b32c023e7a502efdc0dee46157290d5Chris Wilson	intel_overlay_unmap_regs(overlay, regs);
85102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
8528dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson	ret = intel_overlay_continue(overlay, scale_changed);
8538dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson	if (ret)
8548dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson		goto out_unpin;
85502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
85602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	overlay->old_vid_bo = overlay->vid_bo;
85723010e43b353c2cdc9725cbedc7e364708039bf7Daniel Vetter	overlay->vid_bo = to_intel_bo(new_bo);
85802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
85902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return 0;
86002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
86102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterout_unpin:
86202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	i915_gem_object_unpin(new_bo);
86302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return ret;
86402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
86502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
8665dcdbcb06badbdf2faa698bf3198e421a1e12840Chris Wilsonint intel_overlay_switch_off(struct intel_overlay *overlay,
8675dcdbcb06badbdf2faa698bf3198e421a1e12840Chris Wilson			     bool interruptible)
86802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
86902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct overlay_registers *regs;
87002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct drm_device *dev = overlay->dev;
8715dcdbcb06badbdf2faa698bf3198e421a1e12840Chris Wilson	int ret;
87202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
87302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	BUG_ON(!mutex_is_locked(&dev->struct_mutex));
87402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	BUG_ON(!mutex_is_locked(&dev->mode_config.mutex));
87502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
876b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson	ret = intel_overlay_recover_from_interrupt(overlay, interruptible);
877b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson	if (ret != 0)
878b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson		return ret;
8799bedb9743fd906e4160468663ee6e1bbdc4412b8Daniel Vetter
88002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!overlay->active)
88102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return 0;
88202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
88302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	ret = intel_overlay_release_old_vid(overlay);
88402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (ret != 0)
88502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return ret;
88602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
8878d74f656dd78ae1ba813389cd46197c6329696bcChris Wilson	regs = intel_overlay_map_regs(overlay);
88802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	regs->OCMD = 0;
8899bb2ff731b32c023e7a502efdc0dee46157290d5Chris Wilson	intel_overlay_unmap_regs(overlay, regs);
89002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
8915dcdbcb06badbdf2faa698bf3198e421a1e12840Chris Wilson	ret = intel_overlay_off(overlay, interruptible);
89203f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	if (ret != 0)
89303f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter		return ret;
89403f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter
89512ca45fea91cfbb09df828bea958b47348caee6dDaniel Vetter	intel_overlay_off_tail(overlay);
89602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return 0;
89702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
89802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
89902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic int check_overlay_possible_on_crtc(struct intel_overlay *overlay,
90002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter					  struct intel_crtc *crtc)
90102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
902722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	drm_i915_private_t *dev_priv = overlay->dev->dev_private;
90302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	u32 pipeconf;
90402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int pipeconf_reg = (crtc->pipe == 0) ? PIPEACONF : PIPEBCONF;
90502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
90602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!crtc->base.enabled || crtc->dpms_mode != DRM_MODE_DPMS_ON)
90702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EINVAL;
90802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
90902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	pipeconf = I915_READ(pipeconf_reg);
91002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
91102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* can't use the overlay with double wide pipe */
91202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!IS_I965G(overlay->dev) && pipeconf & PIPEACONF_DOUBLE_WIDE)
91302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EINVAL;
91402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
91502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return 0;
91602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
91702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
91802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic void update_pfit_vscale_ratio(struct intel_overlay *overlay)
91902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
92002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct drm_device *dev = overlay->dev;
921722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	drm_i915_private_t *dev_priv = dev->dev_private;
92202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	u32 pfit_control = I915_READ(PFIT_CONTROL);
923446d2183af68c0fd2772f5ef97a033efe69904a5Chris Wilson	u32 ratio;
92402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
92502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* XXX: This is not the same logic as in the xorg driver, but more in
926446d2183af68c0fd2772f5ef97a033efe69904a5Chris Wilson	 * line with the intel documentation for the i965
927446d2183af68c0fd2772f5ef97a033efe69904a5Chris Wilson	 */
928446d2183af68c0fd2772f5ef97a033efe69904a5Chris Wilson	if (!IS_I965G(dev)) {
929446d2183af68c0fd2772f5ef97a033efe69904a5Chris Wilson		if (pfit_control & VERT_AUTO_SCALE)
930446d2183af68c0fd2772f5ef97a033efe69904a5Chris Wilson			ratio = I915_READ(PFIT_AUTO_RATIOS);
93102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		else
932446d2183af68c0fd2772f5ef97a033efe69904a5Chris Wilson			ratio = I915_READ(PFIT_PGM_RATIOS);
933446d2183af68c0fd2772f5ef97a033efe69904a5Chris Wilson		ratio >>= PFIT_VERT_SCALE_SHIFT;
934446d2183af68c0fd2772f5ef97a033efe69904a5Chris Wilson	} else { /* on i965 use the PGM reg to read out the autoscaler values */
935446d2183af68c0fd2772f5ef97a033efe69904a5Chris Wilson		ratio = I915_READ(PFIT_PGM_RATIOS) >> PFIT_VERT_SCALE_SHIFT_965;
93602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
93702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
93802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	overlay->pfit_vscale_ratio = ratio;
93902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
94002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
94102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic int check_overlay_dst(struct intel_overlay *overlay,
94202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			     struct drm_intel_overlay_put_image *rec)
94302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
94402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct drm_display_mode *mode = &overlay->crtc->base.mode;
94502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
946722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	if (rec->dst_x < mode->crtc_hdisplay &&
947722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	    rec->dst_x + rec->dst_width <= mode->crtc_hdisplay &&
948722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	    rec->dst_y < mode->crtc_vdisplay &&
949722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	    rec->dst_y + rec->dst_height <= mode->crtc_vdisplay)
95002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return 0;
95102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	else
95202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EINVAL;
95302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
95402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
95502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic int check_overlay_scaling(struct put_image_params *rec)
95602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
95702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	u32 tmp;
95802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
95902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* downscaling limit is 8.0 */
96002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	tmp = ((rec->src_scan_h << 16) / rec->dst_h) >> 16;
96102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (tmp > 7)
96202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EINVAL;
96302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	tmp = ((rec->src_scan_w << 16) / rec->dst_w) >> 16;
96402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (tmp > 7)
96502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EINVAL;
96602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
96702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return 0;
96802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
96902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
97002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic int check_overlay_src(struct drm_device *dev,
97102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			     struct drm_intel_overlay_put_image *rec,
97202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			     struct drm_gem_object *new_bo)
97302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
97402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int uv_hscale = uv_hsubsampling(rec->flags);
97502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int uv_vscale = uv_vsubsampling(rec->flags);
9769f7c3f442bb7c0d0a0ed25cc287932450a1f2babChris Wilson	u32 stride_mask, depth, tmp;
97702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
97802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* check src dimensions */
97902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (IS_845G(dev) || IS_I830(dev)) {
980722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		if (rec->src_height > IMAGE_MAX_HEIGHT_LEGACY ||
9819f7c3f442bb7c0d0a0ed25cc287932450a1f2babChris Wilson		    rec->src_width  > IMAGE_MAX_WIDTH_LEGACY)
98202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			return -EINVAL;
98302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	} else {
984722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		if (rec->src_height > IMAGE_MAX_HEIGHT ||
9859f7c3f442bb7c0d0a0ed25cc287932450a1f2babChris Wilson		    rec->src_width  > IMAGE_MAX_WIDTH)
98602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			return -EINVAL;
98702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
9889f7c3f442bb7c0d0a0ed25cc287932450a1f2babChris Wilson
98902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* better safe than sorry, use 4 as the maximal subsampling ratio */
990722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	if (rec->src_height < N_VERT_Y_TAPS*4 ||
9919f7c3f442bb7c0d0a0ed25cc287932450a1f2babChris Wilson	    rec->src_width  < N_HORIZ_Y_TAPS*4)
99202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EINVAL;
99302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
994a1efd14a99483a4fb9308902397ed86b69454c99Chris Wilson	/* check alignment constraints */
99502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	switch (rec->flags & I915_OVERLAY_TYPE_MASK) {
996722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case I915_OVERLAY_RGB:
997722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		/* not implemented */
998722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		return -EINVAL;
9999f7c3f442bb7c0d0a0ed25cc287932450a1f2babChris Wilson
1000722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case I915_OVERLAY_YUV_PACKED:
1001722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		if (uv_vscale != 1)
100202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			return -EINVAL;
10039f7c3f442bb7c0d0a0ed25cc287932450a1f2babChris Wilson
10049f7c3f442bb7c0d0a0ed25cc287932450a1f2babChris Wilson		depth = packed_depth_bytes(rec->flags);
1005722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		if (depth < 0)
1006722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			return depth;
10079f7c3f442bb7c0d0a0ed25cc287932450a1f2babChris Wilson
1008722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		/* ignore UV planes */
1009722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		rec->stride_UV = 0;
1010722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		rec->offset_U = 0;
1011722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		rec->offset_V = 0;
1012722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		/* check pixel alignment */
1013722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		if (rec->offset_Y % depth)
1014722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			return -EINVAL;
1015722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		break;
10169f7c3f442bb7c0d0a0ed25cc287932450a1f2babChris Wilson
1017722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case I915_OVERLAY_YUV_PLANAR:
1018722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		if (uv_vscale < 0 || uv_hscale < 0)
101902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			return -EINVAL;
1020722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		/* no offset restrictions for planar formats */
1021722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		break;
10229f7c3f442bb7c0d0a0ed25cc287932450a1f2babChris Wilson
1023722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	default:
1024722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		return -EINVAL;
102502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
102602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
102702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (rec->src_width % uv_hscale)
102802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EINVAL;
102902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
103002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* stride checking */
1031a1efd14a99483a4fb9308902397ed86b69454c99Chris Wilson	if (IS_I830(dev) || IS_845G(dev))
1032a1efd14a99483a4fb9308902397ed86b69454c99Chris Wilson		stride_mask = 255;
1033a1efd14a99483a4fb9308902397ed86b69454c99Chris Wilson	else
1034a1efd14a99483a4fb9308902397ed86b69454c99Chris Wilson		stride_mask = 63;
103502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
103602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (rec->stride_Y & stride_mask || rec->stride_UV & stride_mask)
103702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EINVAL;
103802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (IS_I965G(dev) && rec->stride_Y < 512)
103902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EINVAL;
104002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
104102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	tmp = (rec->flags & I915_OVERLAY_TYPE_MASK) == I915_OVERLAY_YUV_PLANAR ?
10429f7c3f442bb7c0d0a0ed25cc287932450a1f2babChris Wilson		4096 : 8192;
10439f7c3f442bb7c0d0a0ed25cc287932450a1f2babChris Wilson	if (rec->stride_Y > tmp || rec->stride_UV > 2*1024)
104402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EINVAL;
104502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
104602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* check buffer dimensions */
104702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	switch (rec->flags & I915_OVERLAY_TYPE_MASK) {
1048722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case I915_OVERLAY_RGB:
1049722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case I915_OVERLAY_YUV_PACKED:
1050722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		/* always 4 Y values per depth pixels */
1051722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		if (packed_width_bytes(rec->flags, rec->src_width) > rec->stride_Y)
1052722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			return -EINVAL;
1053722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson
1054722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		tmp = rec->stride_Y*rec->src_height;
1055722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		if (rec->offset_Y + tmp > new_bo->size)
1056722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			return -EINVAL;
1057722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		break;
1058722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson
1059722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case I915_OVERLAY_YUV_PLANAR:
1060722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		if (rec->src_width > rec->stride_Y)
1061722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			return -EINVAL;
1062722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		if (rec->src_width/uv_hscale > rec->stride_UV)
1063722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			return -EINVAL;
1064722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson
10659f7c3f442bb7c0d0a0ed25cc287932450a1f2babChris Wilson		tmp = rec->stride_Y * rec->src_height;
1066722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		if (rec->offset_Y + tmp > new_bo->size)
1067722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			return -EINVAL;
10689f7c3f442bb7c0d0a0ed25cc287932450a1f2babChris Wilson
10699f7c3f442bb7c0d0a0ed25cc287932450a1f2babChris Wilson		tmp = rec->stride_UV * (rec->src_height / uv_vscale);
1070722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		if (rec->offset_U + tmp > new_bo->size ||
1071722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		    rec->offset_V + tmp > new_bo->size)
1072722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			return -EINVAL;
1073722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		break;
107402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
107502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
107602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return 0;
107702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
107802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
107902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterint intel_overlay_put_image(struct drm_device *dev, void *data,
108002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter                            struct drm_file *file_priv)
108102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
108202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct drm_intel_overlay_put_image *put_image_rec = data;
108302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	drm_i915_private_t *dev_priv = dev->dev_private;
108402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct intel_overlay *overlay;
108502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct drm_mode_object *drmmode_obj;
108602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct intel_crtc *crtc;
108702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct drm_gem_object *new_bo;
108802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct put_image_params *params;
108902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int ret;
109002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
109102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!dev_priv) {
109202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		DRM_ERROR("called with no initialization\n");
109302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EINVAL;
109402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
109502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
109602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	overlay = dev_priv->overlay;
109702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!overlay) {
109802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		DRM_DEBUG("userspace bug: no overlay\n");
109902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -ENODEV;
110002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
110102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
110202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!(put_image_rec->flags & I915_OVERLAY_ENABLE)) {
110302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		mutex_lock(&dev->mode_config.mutex);
110402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		mutex_lock(&dev->struct_mutex);
110502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
11065dcdbcb06badbdf2faa698bf3198e421a1e12840Chris Wilson		ret = intel_overlay_switch_off(overlay, true);
110702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
110802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		mutex_unlock(&dev->struct_mutex);
110902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		mutex_unlock(&dev->mode_config.mutex);
111002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
111102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return ret;
111202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
111302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
111402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	params = kmalloc(sizeof(struct put_image_params), GFP_KERNEL);
111502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!params)
111602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -ENOMEM;
111702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
111802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	drmmode_obj = drm_mode_object_find(dev, put_image_rec->crtc_id,
1119722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson					   DRM_MODE_OBJECT_CRTC);
1120915a428e43acfd05e4ffeaf40549b0cf163eebe2Dan Carpenter	if (!drmmode_obj) {
1121915a428e43acfd05e4ffeaf40549b0cf163eebe2Dan Carpenter		ret = -ENOENT;
1122915a428e43acfd05e4ffeaf40549b0cf163eebe2Dan Carpenter		goto out_free;
1123915a428e43acfd05e4ffeaf40549b0cf163eebe2Dan Carpenter	}
112402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	crtc = to_intel_crtc(obj_to_crtc(drmmode_obj));
112502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
112602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	new_bo = drm_gem_object_lookup(dev, file_priv,
1127722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson				       put_image_rec->bo_handle);
1128915a428e43acfd05e4ffeaf40549b0cf163eebe2Dan Carpenter	if (!new_bo) {
1129915a428e43acfd05e4ffeaf40549b0cf163eebe2Dan Carpenter		ret = -ENOENT;
1130915a428e43acfd05e4ffeaf40549b0cf163eebe2Dan Carpenter		goto out_free;
1131915a428e43acfd05e4ffeaf40549b0cf163eebe2Dan Carpenter	}
113202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
113302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	mutex_lock(&dev->mode_config.mutex);
113402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	mutex_lock(&dev->struct_mutex);
113502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
1136b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson	ret = intel_overlay_recover_from_interrupt(overlay, true);
1137b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson	if (ret != 0)
1138b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson		goto out_unlock;
113903f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter
114002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (overlay->crtc != crtc) {
114102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		struct drm_display_mode *mode = &crtc->base.mode;
11425dcdbcb06badbdf2faa698bf3198e421a1e12840Chris Wilson		ret = intel_overlay_switch_off(overlay, true);
114302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		if (ret != 0)
114402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			goto out_unlock;
114502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
114602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		ret = check_overlay_possible_on_crtc(overlay, crtc);
114702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		if (ret != 0)
114802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			goto out_unlock;
114902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
115002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		overlay->crtc = crtc;
115102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		crtc->overlay = overlay;
115202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
115302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		if (intel_panel_fitter_pipe(dev) == crtc->pipe
115402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		    /* and line to wide, i.e. one-line-mode */
115502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		    && mode->hdisplay > 1024) {
115602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			overlay->pfit_active = 1;
115702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			update_pfit_vscale_ratio(overlay);
115802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		} else
115902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			overlay->pfit_active = 0;
116002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
116102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
116202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	ret = check_overlay_dst(overlay, put_image_rec);
116302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (ret != 0)
116402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		goto out_unlock;
116502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
116602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (overlay->pfit_active) {
116702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		params->dst_y = ((((u32)put_image_rec->dst_y) << 12) /
1168722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson				 overlay->pfit_vscale_ratio);
116902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		/* shifting right rounds downwards, so add 1 */
117002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		params->dst_h = ((((u32)put_image_rec->dst_height) << 12) /
1171722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson				 overlay->pfit_vscale_ratio) + 1;
117202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	} else {
117302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		params->dst_y = put_image_rec->dst_y;
117402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		params->dst_h = put_image_rec->dst_height;
117502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
117602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	params->dst_x = put_image_rec->dst_x;
117702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	params->dst_w = put_image_rec->dst_width;
117802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
117902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	params->src_w = put_image_rec->src_width;
118002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	params->src_h = put_image_rec->src_height;
118102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	params->src_scan_w = put_image_rec->src_scan_width;
118202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	params->src_scan_h = put_image_rec->src_scan_height;
1183722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	if (params->src_scan_h > params->src_h ||
1184722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	    params->src_scan_w > params->src_w) {
118502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		ret = -EINVAL;
118602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		goto out_unlock;
118702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
118802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
118902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	ret = check_overlay_src(dev, put_image_rec, new_bo);
119002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (ret != 0)
119102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		goto out_unlock;
119202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	params->format = put_image_rec->flags & ~I915_OVERLAY_FLAGS_MASK;
119302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	params->stride_Y = put_image_rec->stride_Y;
119402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	params->stride_UV = put_image_rec->stride_UV;
119502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	params->offset_Y = put_image_rec->offset_Y;
119602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	params->offset_U = put_image_rec->offset_U;
119702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	params->offset_V = put_image_rec->offset_V;
119802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
119902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* Check scaling after src size to prevent a divide-by-zero. */
120002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	ret = check_overlay_scaling(params);
120102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (ret != 0)
120202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		goto out_unlock;
120302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
120402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	ret = intel_overlay_do_put_image(overlay, new_bo, params);
120502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (ret != 0)
120602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		goto out_unlock;
120702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
120802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	mutex_unlock(&dev->struct_mutex);
120902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	mutex_unlock(&dev->mode_config.mutex);
121002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
121102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	kfree(params);
121202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
121302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return 0;
121402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
121502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterout_unlock:
121602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	mutex_unlock(&dev->struct_mutex);
121702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	mutex_unlock(&dev->mode_config.mutex);
1218bc9025bdc4e2b591734cca17697093845007b63dLuca Barbieri	drm_gem_object_unreference_unlocked(new_bo);
1219915a428e43acfd05e4ffeaf40549b0cf163eebe2Dan Carpenterout_free:
122002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	kfree(params);
122102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
122202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return ret;
122302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
122402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
122502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic void update_reg_attrs(struct intel_overlay *overlay,
122602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			     struct overlay_registers *regs)
122702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
122802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	regs->OCLRC0 = (overlay->contrast << 18) | (overlay->brightness & 0xff);
122902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	regs->OCLRC1 = overlay->saturation;
123002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
123102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
123202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic bool check_gamma_bounds(u32 gamma1, u32 gamma2)
123302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
123402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int i;
123502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
123602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (gamma1 & 0xff000000 || gamma2 & 0xff000000)
123702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return false;
123802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
123902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	for (i = 0; i < 3; i++) {
1240722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		if (((gamma1 >> i*8) & 0xff) >= ((gamma2 >> i*8) & 0xff))
124102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			return false;
124202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
124302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
124402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return true;
124502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
124602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
124702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic bool check_gamma5_errata(u32 gamma5)
124802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
124902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int i;
125002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
125102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	for (i = 0; i < 3; i++) {
125202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		if (((gamma5 >> i*8) & 0xff) == 0x80)
125302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			return false;
125402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
125502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
125602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return true;
125702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
125802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
125902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic int check_gamma(struct drm_intel_overlay_attrs *attrs)
126002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
1261722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	if (!check_gamma_bounds(0, attrs->gamma0) ||
1262722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	    !check_gamma_bounds(attrs->gamma0, attrs->gamma1) ||
1263722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	    !check_gamma_bounds(attrs->gamma1, attrs->gamma2) ||
1264722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	    !check_gamma_bounds(attrs->gamma2, attrs->gamma3) ||
1265722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	    !check_gamma_bounds(attrs->gamma3, attrs->gamma4) ||
1266722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	    !check_gamma_bounds(attrs->gamma4, attrs->gamma5) ||
1267722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	    !check_gamma_bounds(attrs->gamma5, 0x00ffffff))
126802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EINVAL;
1269722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson
127002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!check_gamma5_errata(attrs->gamma5))
127102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EINVAL;
1272722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson
127302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return 0;
127402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
127502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
127602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterint intel_overlay_attrs(struct drm_device *dev, void *data,
127702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter                        struct drm_file *file_priv)
127802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
127902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct drm_intel_overlay_attrs *attrs = data;
128002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter        drm_i915_private_t *dev_priv = dev->dev_private;
128102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct intel_overlay *overlay;
128202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct overlay_registers *regs;
128302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int ret;
128402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
128502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!dev_priv) {
128602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		DRM_ERROR("called with no initialization\n");
128702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EINVAL;
128802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
128902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
129002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	overlay = dev_priv->overlay;
129102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!overlay) {
129202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		DRM_DEBUG("userspace bug: no overlay\n");
129302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -ENODEV;
129402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
129502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
129602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	mutex_lock(&dev->mode_config.mutex);
129702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	mutex_lock(&dev->struct_mutex);
129802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
129960fc332cb5ab19e5a86d696b210df65814b2ad8aChris Wilson	ret = -EINVAL;
130002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!(attrs->flags & I915_OVERLAY_UPDATE_ATTRS)) {
130160fc332cb5ab19e5a86d696b210df65814b2ad8aChris Wilson		attrs->color_key  = overlay->color_key;
130202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		attrs->brightness = overlay->brightness;
130360fc332cb5ab19e5a86d696b210df65814b2ad8aChris Wilson		attrs->contrast   = overlay->contrast;
130402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		attrs->saturation = overlay->saturation;
130502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
130602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		if (IS_I9XX(dev)) {
130702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			attrs->gamma0 = I915_READ(OGAMC0);
130802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			attrs->gamma1 = I915_READ(OGAMC1);
130902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			attrs->gamma2 = I915_READ(OGAMC2);
131002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			attrs->gamma3 = I915_READ(OGAMC3);
131102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			attrs->gamma4 = I915_READ(OGAMC4);
131202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			attrs->gamma5 = I915_READ(OGAMC5);
131302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		}
131402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	} else {
131560fc332cb5ab19e5a86d696b210df65814b2ad8aChris Wilson		if (attrs->brightness < -128 || attrs->brightness > 127)
131602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			goto out_unlock;
131760fc332cb5ab19e5a86d696b210df65814b2ad8aChris Wilson		if (attrs->contrast > 255)
131802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			goto out_unlock;
131960fc332cb5ab19e5a86d696b210df65814b2ad8aChris Wilson		if (attrs->saturation > 1023)
132002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			goto out_unlock;
132160fc332cb5ab19e5a86d696b210df65814b2ad8aChris Wilson
132260fc332cb5ab19e5a86d696b210df65814b2ad8aChris Wilson		overlay->color_key  = attrs->color_key;
132360fc332cb5ab19e5a86d696b210df65814b2ad8aChris Wilson		overlay->brightness = attrs->brightness;
132460fc332cb5ab19e5a86d696b210df65814b2ad8aChris Wilson		overlay->contrast   = attrs->contrast;
132560fc332cb5ab19e5a86d696b210df65814b2ad8aChris Wilson		overlay->saturation = attrs->saturation;
132602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
13278d74f656dd78ae1ba813389cd46197c6329696bcChris Wilson		regs = intel_overlay_map_regs(overlay);
132802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		if (!regs) {
132902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			ret = -ENOMEM;
133002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			goto out_unlock;
133102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		}
133202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
133302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		update_reg_attrs(overlay, regs);
133402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
13359bb2ff731b32c023e7a502efdc0dee46157290d5Chris Wilson		intel_overlay_unmap_regs(overlay, regs);
133602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
133702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		if (attrs->flags & I915_OVERLAY_UPDATE_GAMMA) {
133860fc332cb5ab19e5a86d696b210df65814b2ad8aChris Wilson			if (!IS_I9XX(dev))
133902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				goto out_unlock;
134002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
134102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			if (overlay->active) {
134202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				ret = -EBUSY;
134302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				goto out_unlock;
134402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			}
134502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
134602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			ret = check_gamma(attrs);
134760fc332cb5ab19e5a86d696b210df65814b2ad8aChris Wilson			if (ret)
134802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				goto out_unlock;
134902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
135002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			I915_WRITE(OGAMC0, attrs->gamma0);
135102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			I915_WRITE(OGAMC1, attrs->gamma1);
135202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			I915_WRITE(OGAMC2, attrs->gamma2);
135302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			I915_WRITE(OGAMC3, attrs->gamma3);
135402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			I915_WRITE(OGAMC4, attrs->gamma4);
135502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			I915_WRITE(OGAMC5, attrs->gamma5);
135602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		}
135702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
135802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
135960fc332cb5ab19e5a86d696b210df65814b2ad8aChris Wilson	ret = 0;
136002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterout_unlock:
136102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	mutex_unlock(&dev->struct_mutex);
136202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	mutex_unlock(&dev->mode_config.mutex);
136302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
136402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return ret;
136502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
136602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
136702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vettervoid intel_setup_overlay(struct drm_device *dev)
136802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
136902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter        drm_i915_private_t *dev_priv = dev->dev_private;
137002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct intel_overlay *overlay;
137102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct drm_gem_object *reg_bo;
137202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct overlay_registers *regs;
137302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int ret;
137402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
137531578148b2c62612f9516fdcf5ebb64ab32ed12dChris Wilson	if (!HAS_OVERLAY(dev))
137602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return;
137702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
137802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	overlay = kzalloc(sizeof(struct intel_overlay), GFP_KERNEL);
137902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!overlay)
138002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return;
138102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	overlay->dev = dev;
138202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
1383ac52bc56de25535a907ef07f8755f1387b89b0f5Daniel Vetter	reg_bo = i915_gem_alloc_object(dev, PAGE_SIZE);
138402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!reg_bo)
138502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		goto out_free;
138623010e43b353c2cdc9725cbedc7e364708039bf7Daniel Vetter	overlay->reg_bo = to_intel_bo(reg_bo);
138702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
138831578148b2c62612f9516fdcf5ebb64ab32ed12dChris Wilson	if (OVERLAY_NEEDS_PHYSICAL(dev)) {
138931578148b2c62612f9516fdcf5ebb64ab32ed12dChris Wilson		ret = i915_gem_attach_phys_object(dev, reg_bo,
139031578148b2c62612f9516fdcf5ebb64ab32ed12dChris Wilson						  I915_GEM_PHYS_OVERLAY_REGS,
1391a29301288f1840bdf9c5456da9cd7c944436edd5Chris Wilson						  PAGE_SIZE);
139231578148b2c62612f9516fdcf5ebb64ab32ed12dChris Wilson                if (ret) {
139331578148b2c62612f9516fdcf5ebb64ab32ed12dChris Wilson                        DRM_ERROR("failed to attach phys overlay regs\n");
139431578148b2c62612f9516fdcf5ebb64ab32ed12dChris Wilson                        goto out_free_bo;
139531578148b2c62612f9516fdcf5ebb64ab32ed12dChris Wilson                }
139631578148b2c62612f9516fdcf5ebb64ab32ed12dChris Wilson		overlay->flip_addr = overlay->reg_bo->phys_obj->handle->busaddr;
139731578148b2c62612f9516fdcf5ebb64ab32ed12dChris Wilson	} else {
139802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		ret = i915_gem_object_pin(reg_bo, PAGE_SIZE);
139902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		if (ret) {
140002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter                        DRM_ERROR("failed to pin overlay register bo\n");
140102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter                        goto out_free_bo;
140202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter                }
140302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		overlay->flip_addr = overlay->reg_bo->gtt_offset;
14040ddc1289f3ffd779779ddd3922f26ae7d0a21604Chris Wilson
14050ddc1289f3ffd779779ddd3922f26ae7d0a21604Chris Wilson		ret = i915_gem_object_set_to_gtt_domain(reg_bo, true);
14060ddc1289f3ffd779779ddd3922f26ae7d0a21604Chris Wilson		if (ret) {
14070ddc1289f3ffd779779ddd3922f26ae7d0a21604Chris Wilson                        DRM_ERROR("failed to move overlay register bo into the GTT\n");
14080ddc1289f3ffd779779ddd3922f26ae7d0a21604Chris Wilson                        goto out_unpin_bo;
14090ddc1289f3ffd779779ddd3922f26ae7d0a21604Chris Wilson                }
141002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
141102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
141202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* init all values */
141302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	overlay->color_key = 0x0101fe;
141402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	overlay->brightness = -19;
141502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	overlay->contrast = 75;
141602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	overlay->saturation = 146;
141702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
14188d74f656dd78ae1ba813389cd46197c6329696bcChris Wilson	regs = intel_overlay_map_regs(overlay);
141902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!regs)
142002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		goto out_free_bo;
142102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
142202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	memset(regs, 0, sizeof(struct overlay_registers));
142302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	update_polyphase_filter(regs);
142402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	update_reg_attrs(overlay, regs);
142502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
14269bb2ff731b32c023e7a502efdc0dee46157290d5Chris Wilson	intel_overlay_unmap_regs(overlay, regs);
142702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
142802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	dev_priv->overlay = overlay;
142902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	DRM_INFO("initialized overlay support\n");
143002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return;
143102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
14320ddc1289f3ffd779779ddd3922f26ae7d0a21604Chris Wilsonout_unpin_bo:
14330ddc1289f3ffd779779ddd3922f26ae7d0a21604Chris Wilson	i915_gem_object_unpin(reg_bo);
143402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterout_free_bo:
143502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	drm_gem_object_unreference(reg_bo);
143602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterout_free:
143702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	kfree(overlay);
143802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return;
143902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
144002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
144102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vettervoid intel_cleanup_overlay(struct drm_device *dev)
144202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
1443722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	drm_i915_private_t *dev_priv = dev->dev_private;
144402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
144562cf4e6fef35b4422e206b63b7f0ac90261d4ad9Chris Wilson	if (!dev_priv->overlay)
144662cf4e6fef35b4422e206b63b7f0ac90261d4ad9Chris Wilson		return;
144702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
144862cf4e6fef35b4422e206b63b7f0ac90261d4ad9Chris Wilson	/* The bo's should be free'd by the generic code already.
144962cf4e6fef35b4422e206b63b7f0ac90261d4ad9Chris Wilson	 * Furthermore modesetting teardown happens beforehand so the
145062cf4e6fef35b4422e206b63b7f0ac90261d4ad9Chris Wilson	 * hardware should be off already */
145162cf4e6fef35b4422e206b63b7f0ac90261d4ad9Chris Wilson	BUG_ON(dev_priv->overlay->active);
145262cf4e6fef35b4422e206b63b7f0ac90261d4ad9Chris Wilson
145362cf4e6fef35b4422e206b63b7f0ac90261d4ad9Chris Wilson	drm_gem_object_unreference_unlocked(&dev_priv->overlay->reg_bo->base);
145462cf4e6fef35b4422e206b63b7f0ac90261d4ad9Chris Wilson	kfree(dev_priv->overlay);
145502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
14566ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson
14576ef3d4278034982c13df87c4a51e0445f762d316Chris Wilsonstruct intel_overlay_error_state {
14586ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	struct overlay_registers regs;
14596ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	unsigned long base;
14606ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	u32 dovsta;
14616ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	u32 isr;
14626ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson};
14636ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson
14646ef3d4278034982c13df87c4a51e0445f762d316Chris Wilsonstruct intel_overlay_error_state *
14656ef3d4278034982c13df87c4a51e0445f762d316Chris Wilsonintel_overlay_capture_error_state(struct drm_device *dev)
14666ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson{
14676ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson        drm_i915_private_t *dev_priv = dev->dev_private;
14686ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	struct intel_overlay *overlay = dev_priv->overlay;
14696ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	struct intel_overlay_error_state *error;
14706ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	struct overlay_registers __iomem *regs;
14716ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson
14726ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	if (!overlay || !overlay->active)
14736ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson		return NULL;
14746ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson
14756ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	error = kmalloc(sizeof(*error), GFP_ATOMIC);
14766ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	if (error == NULL)
14776ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson		return NULL;
14786ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson
14796ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	error->dovsta = I915_READ(DOVSTA);
14806ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	error->isr = I915_READ(ISR);
148131578148b2c62612f9516fdcf5ebb64ab32ed12dChris Wilson	if (OVERLAY_NEEDS_PHYSICAL(overlay->dev))
14826ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson		error->base = (long) overlay->reg_bo->phys_obj->handle->vaddr;
148331578148b2c62612f9516fdcf5ebb64ab32ed12dChris Wilson	else
148431578148b2c62612f9516fdcf5ebb64ab32ed12dChris Wilson		error->base = (long) overlay->reg_bo->gtt_offset;
14856ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson
14868d74f656dd78ae1ba813389cd46197c6329696bcChris Wilson	regs = intel_overlay_map_regs_atomic(overlay, KM_IRQ0);
14876ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	if (!regs)
14886ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson		goto err;
14896ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson
14906ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	memcpy_fromio(&error->regs, regs, sizeof(struct overlay_registers));
14919bb2ff731b32c023e7a502efdc0dee46157290d5Chris Wilson	intel_overlay_unmap_regs_atomic(overlay, KM_IRQ0, regs);
14926ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson
14936ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	return error;
14946ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson
14956ef3d4278034982c13df87c4a51e0445f762d316Chris Wilsonerr:
14966ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	kfree(error);
14976ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	return NULL;
14986ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson}
14996ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson
15006ef3d4278034982c13df87c4a51e0445f762d316Chris Wilsonvoid
15016ef3d4278034982c13df87c4a51e0445f762d316Chris Wilsonintel_overlay_print_error_state(struct seq_file *m, struct intel_overlay_error_state *error)
15026ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson{
15036ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	seq_printf(m, "Overlay, status: 0x%08x, interrupt: 0x%08x\n",
15046ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson		   error->dovsta, error->isr);
15056ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	seq_printf(m, "  Register file at 0x%08lx:\n",
15066ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson		   error->base);
15076ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson
15086ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson#define P(x) seq_printf(m, "    " #x ":	0x%08x\n", error->regs.x)
15096ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OBUF_0Y);
15106ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OBUF_1Y);
15116ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OBUF_0U);
15126ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OBUF_0V);
15136ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OBUF_1U);
15146ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OBUF_1V);
15156ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OSTRIDE);
15166ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(YRGB_VPH);
15176ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(UV_VPH);
15186ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(HORZ_PH);
15196ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(INIT_PHS);
15206ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(DWINPOS);
15216ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(DWINSZ);
15226ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(SWIDTH);
15236ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(SWIDTHSW);
15246ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(SHEIGHT);
15256ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(YRGBSCALE);
15266ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(UVSCALE);
15276ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OCLRC0);
15286ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OCLRC1);
15296ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(DCLRKV);
15306ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(DCLRKM);
15316ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(SCLRKVH);
15326ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(SCLRKVL);
15336ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(SCLRKEN);
15346ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OCONFIG);
15356ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OCMD);
15366ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OSTART_0Y);
15376ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OSTART_1Y);
15386ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OSTART_0U);
15396ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OSTART_0V);
15406ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OSTART_1U);
15416ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OSTART_1V);
15426ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OTILEOFF_0Y);
15436ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OTILEOFF_1Y);
15446ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OTILEOFF_0U);
15456ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OTILEOFF_0V);
15466ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OTILEOFF_1U);
15476ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OTILEOFF_1V);
15486ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(FASTHSCALE);
15496ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(UVSCALEV);
15506ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson#undef P
15516ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson}
1552