intel_overlay.c revision 106dadacbeeea92f61a2c32f3651ee31c1b34e31
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
1738d74f656dd78ae1ba813389cd46197c6329696bcChris Wilsonstatic struct overlay_registers *
1748d74f656dd78ae1ba813389cd46197c6329696bcChris Wilsonintel_overlay_map_regs_atomic(struct intel_overlay *overlay,
1758d74f656dd78ae1ba813389cd46197c6329696bcChris Wilson			      int slot)
17602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
17702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter        drm_i915_private_t *dev_priv = overlay->dev->dev_private;
17802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct overlay_registers *regs;
17902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
1809bb2ff731b32c023e7a502efdc0dee46157290d5Chris Wilson	if (OVERLAY_NEEDS_PHYSICAL(overlay->dev))
18131578148b2c62612f9516fdcf5ebb64ab32ed12dChris Wilson		regs = overlay->reg_bo->phys_obj->handle->vaddr;
1829bb2ff731b32c023e7a502efdc0dee46157290d5Chris Wilson	else
18302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		regs = io_mapping_map_atomic_wc(dev_priv->mm.gtt_mapping,
184fca3ec01e0b40cab82cac7745e154b01969e6219Chris Wilson						overlay->reg_bo->gtt_offset,
1858d74f656dd78ae1ba813389cd46197c6329696bcChris Wilson						slot);
18602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
1879bb2ff731b32c023e7a502efdc0dee46157290d5Chris Wilson	return regs;
18802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
18902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
1908d74f656dd78ae1ba813389cd46197c6329696bcChris Wilsonstatic void intel_overlay_unmap_regs_atomic(struct intel_overlay *overlay,
1919bb2ff731b32c023e7a502efdc0dee46157290d5Chris Wilson					    int slot,
1929bb2ff731b32c023e7a502efdc0dee46157290d5Chris Wilson					    struct overlay_registers *regs)
19302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
19431578148b2c62612f9516fdcf5ebb64ab32ed12dChris Wilson	if (!OVERLAY_NEEDS_PHYSICAL(overlay->dev))
1959bb2ff731b32c023e7a502efdc0dee46157290d5Chris Wilson		io_mapping_unmap_atomic(regs, slot);
1968d74f656dd78ae1ba813389cd46197c6329696bcChris Wilson}
1978d74f656dd78ae1ba813389cd46197c6329696bcChris Wilson
1988d74f656dd78ae1ba813389cd46197c6329696bcChris Wilsonstatic struct overlay_registers *
1998d74f656dd78ae1ba813389cd46197c6329696bcChris Wilsonintel_overlay_map_regs(struct intel_overlay *overlay)
2008d74f656dd78ae1ba813389cd46197c6329696bcChris Wilson{
2018d74f656dd78ae1ba813389cd46197c6329696bcChris Wilson        drm_i915_private_t *dev_priv = overlay->dev->dev_private;
2028d74f656dd78ae1ba813389cd46197c6329696bcChris Wilson	struct overlay_registers *regs;
2038d74f656dd78ae1ba813389cd46197c6329696bcChris Wilson
2049bb2ff731b32c023e7a502efdc0dee46157290d5Chris Wilson	if (OVERLAY_NEEDS_PHYSICAL(overlay->dev))
2058d74f656dd78ae1ba813389cd46197c6329696bcChris Wilson		regs = overlay->reg_bo->phys_obj->handle->vaddr;
2069bb2ff731b32c023e7a502efdc0dee46157290d5Chris Wilson	else
2078d74f656dd78ae1ba813389cd46197c6329696bcChris Wilson		regs = io_mapping_map_wc(dev_priv->mm.gtt_mapping,
2088d74f656dd78ae1ba813389cd46197c6329696bcChris Wilson					 overlay->reg_bo->gtt_offset);
2098d74f656dd78ae1ba813389cd46197c6329696bcChris Wilson
2109bb2ff731b32c023e7a502efdc0dee46157290d5Chris Wilson	return regs;
2118d74f656dd78ae1ba813389cd46197c6329696bcChris Wilson}
2128d74f656dd78ae1ba813389cd46197c6329696bcChris Wilson
2139bb2ff731b32c023e7a502efdc0dee46157290d5Chris Wilsonstatic void intel_overlay_unmap_regs(struct intel_overlay *overlay,
2149bb2ff731b32c023e7a502efdc0dee46157290d5Chris Wilson				     struct overlay_registers *regs)
2158d74f656dd78ae1ba813389cd46197c6329696bcChris Wilson{
2168d74f656dd78ae1ba813389cd46197c6329696bcChris Wilson	if (!OVERLAY_NEEDS_PHYSICAL(overlay->dev))
2179bb2ff731b32c023e7a502efdc0dee46157290d5Chris Wilson		io_mapping_unmap(regs);
21802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
21902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
220b6c028e00445de9dfde2cd0c26521ac53965320aChris Wilsonstatic int intel_overlay_do_wait_request(struct intel_overlay *overlay,
2218dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson					 struct drm_i915_gem_request *request,
222b6c028e00445de9dfde2cd0c26521ac53965320aChris Wilson					 bool interruptible,
223b6c028e00445de9dfde2cd0c26521ac53965320aChris Wilson					 int stage)
22402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
22502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct drm_device *dev = overlay->dev;
226852835f343146a82a528c3b712b373661d4fa17aZou Nan hai	drm_i915_private_t *dev_priv = dev->dev_private;
227b6c028e00445de9dfde2cd0c26521ac53965320aChris Wilson	int ret;
22802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
229852835f343146a82a528c3b712b373661d4fa17aZou Nan hai	overlay->last_flip_req =
2308dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson		i915_add_request(dev, NULL, request, &dev_priv->render_ring);
23103f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	if (overlay->last_flip_req == 0)
23203f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter		return -ENOMEM;
23302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
234b6c028e00445de9dfde2cd0c26521ac53965320aChris Wilson	overlay->hw_wedged = stage;
235852835f343146a82a528c3b712b373661d4fa17aZou Nan hai	ret = i915_do_wait_request(dev,
236722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson				   overlay->last_flip_req, true,
237722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson				   &dev_priv->render_ring);
238b6c028e00445de9dfde2cd0c26521ac53965320aChris Wilson	if (ret)
23903f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter		return ret;
24002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
24103f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	overlay->hw_wedged = 0;
24203f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	overlay->last_flip_req = 0;
24302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return 0;
24402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
24502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
246106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson/* Workaround for i830 bug where pipe a must be enable to change control regs */
247106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilsonstatic int
248106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilsoni830_activate_pipe_a(struct drm_device *dev)
249106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson{
250106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	drm_i915_private_t *dev_priv = dev->dev_private;
251106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	struct intel_crtc *crtc;
252106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	struct drm_crtc_helper_funcs *crtc_funcs;
253106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	struct drm_display_mode vesa_640x480 = {
254106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson		DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 25175, 640, 656,
255106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson			 752, 800, 0, 480, 489, 492, 525, 0,
256106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson			 DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC)
257106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	}, *mode;
258106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson
259106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	crtc = to_intel_crtc(dev_priv->pipe_to_crtc_mapping[0]);
260106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	if (crtc->dpms_mode == DRM_MODE_DPMS_ON)
261106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson		return 0;
262106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson
263106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	/* most i8xx have pipe a forced on, so don't trust dpms mode */
264106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	if (I915_READ(PIPEACONF) & PIPEACONF_ENABLE)
265106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson		return 0;
266106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson
267106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	crtc_funcs = crtc->base.helper_private;
268106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	if (crtc_funcs->dpms == NULL)
269106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson		return 0;
270106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson
271106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	DRM_DEBUG_DRIVER("Enabling pipe A in order to enable overlay\n");
272106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson
273106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	mode = drm_mode_duplicate(dev, &vesa_640x480);
274106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V);
275106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	if(!drm_crtc_helper_set_mode(&crtc->base, mode,
276106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson				       crtc->base.x, crtc->base.y,
277106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson				       crtc->base.fb))
278106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson		return 0;
279106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson
280106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	crtc_funcs->dpms(&crtc->base, DRM_MODE_DPMS_ON);
281106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	return 1;
282106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson}
283106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson
284106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilsonstatic void
285106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilsoni830_deactivate_pipe_a(struct drm_device *dev)
286106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson{
287106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	drm_i915_private_t *dev_priv = dev->dev_private;
288106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[0];
289106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
290106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson
291106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	crtc_funcs->dpms(crtc, DRM_MODE_DPMS_OFF);
292106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson}
293106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson
294b6c028e00445de9dfde2cd0c26521ac53965320aChris Wilson/* overlay needs to be disable in OCMD reg */
295b6c028e00445de9dfde2cd0c26521ac53965320aChris Wilsonstatic int intel_overlay_on(struct intel_overlay *overlay)
296b6c028e00445de9dfde2cd0c26521ac53965320aChris Wilson{
297b6c028e00445de9dfde2cd0c26521ac53965320aChris Wilson	struct drm_device *dev = overlay->dev;
2988dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson	struct drm_i915_gem_request *request;
299106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	int pipe_a_quirk = 0;
300106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	int ret;
301b6c028e00445de9dfde2cd0c26521ac53965320aChris Wilson
302b6c028e00445de9dfde2cd0c26521ac53965320aChris Wilson	BUG_ON(overlay->active);
303b6c028e00445de9dfde2cd0c26521ac53965320aChris Wilson	overlay->active = 1;
304b6c028e00445de9dfde2cd0c26521ac53965320aChris Wilson
305106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	if (IS_I830(dev)) {
306106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson		pipe_a_quirk = i830_activate_pipe_a(dev);
307106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson		if (pipe_a_quirk < 0)
308106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson			return pipe_a_quirk;
309106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	}
310106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson
3118dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson	request = kzalloc(sizeof(*request), GFP_KERNEL);
312106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	if (request == NULL) {
313106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson		ret = -ENOMEM;
314106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson		goto out;
315106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	}
3168dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson
317b6c028e00445de9dfde2cd0c26521ac53965320aChris Wilson	BEGIN_LP_RING(4);
318b6c028e00445de9dfde2cd0c26521ac53965320aChris Wilson	OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_ON);
319b6c028e00445de9dfde2cd0c26521ac53965320aChris Wilson	OUT_RING(overlay->flip_addr | OFC_UPDATE);
320b6c028e00445de9dfde2cd0c26521ac53965320aChris Wilson	OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
321b6c028e00445de9dfde2cd0c26521ac53965320aChris Wilson	OUT_RING(MI_NOOP);
322b6c028e00445de9dfde2cd0c26521ac53965320aChris Wilson	ADVANCE_LP_RING();
323b6c028e00445de9dfde2cd0c26521ac53965320aChris Wilson
324106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	ret = intel_overlay_do_wait_request(overlay, request, true,
325106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson					    NEEDS_WAIT_FOR_FLIP);
326106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilsonout:
327106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	if (pipe_a_quirk)
328106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson		i830_deactivate_pipe_a(dev);
329106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson
330106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	return ret;
331b6c028e00445de9dfde2cd0c26521ac53965320aChris Wilson}
332b6c028e00445de9dfde2cd0c26521ac53965320aChris Wilson
33302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter/* overlay needs to be enabled in OCMD reg */
3348dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilsonstatic int intel_overlay_continue(struct intel_overlay *overlay,
3358dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson				  bool load_polyphase_filter)
33602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
33702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct drm_device *dev = overlay->dev;
33802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter        drm_i915_private_t *dev_priv = dev->dev_private;
3398dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson	struct drm_i915_gem_request *request;
34002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	u32 flip_addr = overlay->flip_addr;
34102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	u32 tmp;
34202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
34302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	BUG_ON(!overlay->active);
34402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
3458dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson	request = kzalloc(sizeof(*request), GFP_KERNEL);
3468dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson	if (request == NULL)
3478dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson		return -ENOMEM;
3488dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson
34902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (load_polyphase_filter)
35002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		flip_addr |= OFC_UPDATE;
35102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
35202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* check for underruns */
35302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	tmp = I915_READ(DOVSTA);
35402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (tmp & (1 << 17))
35502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		DRM_DEBUG("overlay underrun, DOVSTA: %x\n", tmp);
35602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
3574f8a567c4666c73284832240db89fdadb2c50bd5Daniel Vetter	BEGIN_LP_RING(2);
35802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_CONTINUE);
35902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	OUT_RING(flip_addr);
3605a5a0c64a99d7542c48c99d1a8bbb49e665842beDaniel Vetter        ADVANCE_LP_RING();
3615a5a0c64a99d7542c48c99d1a8bbb49e665842beDaniel Vetter
362852835f343146a82a528c3b712b373661d4fa17aZou Nan hai	overlay->last_flip_req =
3638dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson		i915_add_request(dev, NULL, request, &dev_priv->render_ring);
3648dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson	return 0;
3655a5a0c64a99d7542c48c99d1a8bbb49e665842beDaniel Vetter}
3665a5a0c64a99d7542c48c99d1a8bbb49e665842beDaniel Vetter
36702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter/* overlay needs to be disabled in OCMD reg */
36802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic int intel_overlay_off(struct intel_overlay *overlay)
36902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
37002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct drm_device *dev = overlay->dev;
3718dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson	u32 flip_addr = overlay->flip_addr;
3728dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson	struct drm_i915_gem_request *request;
37302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
37402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	BUG_ON(!overlay->active);
37502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
3768dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson	request = kzalloc(sizeof(*request), GFP_KERNEL);
3778dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson	if (request == NULL)
3788dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson		return -ENOMEM;
3798dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson
38002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* According to intel docs the overlay hw may hang (when switching
38102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	 * off) without loading the filter coeffs. It is however unclear whether
38202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	 * this applies to the disabling of the overlay or to the switching off
38302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	 * of the hw. Do it in both cases */
38402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	flip_addr |= OFC_UPDATE;
38502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
3868dfbc3403113bcc51f0350c3471fa1abf664305fChris Wilson	BEGIN_LP_RING(6);
38702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* wait for overlay to go idle */
38802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_CONTINUE);
38902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	OUT_RING(flip_addr);
390722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
39102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* turn overlay off */
392722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_OFF);
39302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	OUT_RING(flip_addr);
394722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
39502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	ADVANCE_LP_RING();
39602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
3978dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson	return intel_overlay_do_wait_request(overlay, request, true,
3988dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson					     SWITCH_OFF);
39902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
40002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
4015cd68c9864d65e49c910c701716e4e94e09f7ce0Chris Wilsonstatic void intel_overlay_release_old_vid_tail(struct intel_overlay *overlay)
4025cd68c9864d65e49c910c701716e4e94e09f7ce0Chris Wilson{
4035cd68c9864d65e49c910c701716e4e94e09f7ce0Chris Wilson	struct drm_gem_object *obj = &overlay->old_vid_bo->base;
4045cd68c9864d65e49c910c701716e4e94e09f7ce0Chris Wilson
4055cd68c9864d65e49c910c701716e4e94e09f7ce0Chris Wilson	i915_gem_object_unpin(obj);
4065cd68c9864d65e49c910c701716e4e94e09f7ce0Chris Wilson	drm_gem_object_unreference(obj);
4075cd68c9864d65e49c910c701716e4e94e09f7ce0Chris Wilson
4085cd68c9864d65e49c910c701716e4e94e09f7ce0Chris Wilson	overlay->old_vid_bo = NULL;
4095cd68c9864d65e49c910c701716e4e94e09f7ce0Chris Wilson}
4105cd68c9864d65e49c910c701716e4e94e09f7ce0Chris Wilson
41112ca45fea91cfbb09df828bea958b47348caee6dDaniel Vetterstatic void intel_overlay_off_tail(struct intel_overlay *overlay)
41212ca45fea91cfbb09df828bea958b47348caee6dDaniel Vetter{
41312ca45fea91cfbb09df828bea958b47348caee6dDaniel Vetter	struct drm_gem_object *obj;
41412ca45fea91cfbb09df828bea958b47348caee6dDaniel Vetter
41512ca45fea91cfbb09df828bea958b47348caee6dDaniel Vetter	/* never have the overlay hw on without showing a frame */
41612ca45fea91cfbb09df828bea958b47348caee6dDaniel Vetter	BUG_ON(!overlay->vid_bo);
417a8089e849a32c5b6bfd6c88dbd09c0ea4a779b71Daniel Vetter	obj = &overlay->vid_bo->base;
41812ca45fea91cfbb09df828bea958b47348caee6dDaniel Vetter
41912ca45fea91cfbb09df828bea958b47348caee6dDaniel Vetter	i915_gem_object_unpin(obj);
42012ca45fea91cfbb09df828bea958b47348caee6dDaniel Vetter	drm_gem_object_unreference(obj);
42112ca45fea91cfbb09df828bea958b47348caee6dDaniel Vetter	overlay->vid_bo = NULL;
42212ca45fea91cfbb09df828bea958b47348caee6dDaniel Vetter
42312ca45fea91cfbb09df828bea958b47348caee6dDaniel Vetter	overlay->crtc->overlay = NULL;
42412ca45fea91cfbb09df828bea958b47348caee6dDaniel Vetter	overlay->crtc = NULL;
42512ca45fea91cfbb09df828bea958b47348caee6dDaniel Vetter	overlay->active = 0;
42612ca45fea91cfbb09df828bea958b47348caee6dDaniel Vetter}
42712ca45fea91cfbb09df828bea958b47348caee6dDaniel Vetter
42803f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter/* recover from an interruption due to a signal
42903f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter * We have to be careful not to repeat work forever an make forward progess. */
43003f77ea5972e6a2363152aec692744cac824dabaDaniel Vetterint intel_overlay_recover_from_interrupt(struct intel_overlay *overlay,
431722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson					 bool interruptible)
43203f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter{
43303f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	struct drm_device *dev = overlay->dev;
434852835f343146a82a528c3b712b373661d4fa17aZou Nan hai	drm_i915_private_t *dev_priv = dev->dev_private;
43503f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	int ret;
43603f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter
43703f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	if (overlay->hw_wedged == HW_WEDGED)
43803f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter		return -EIO;
43903f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter
440852835f343146a82a528c3b712b373661d4fa17aZou Nan hai	ret = i915_do_wait_request(dev, overlay->last_flip_req,
441722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson				   interruptible, &dev_priv->render_ring);
442b6c028e00445de9dfde2cd0c26521ac53965320aChris Wilson	if (ret)
44303f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter		return ret;
44403f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter
44503f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	switch (overlay->hw_wedged) {
446722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case RELEASE_OLD_VID:
4475cd68c9864d65e49c910c701716e4e94e09f7ce0Chris Wilson		intel_overlay_release_old_vid_tail(overlay);
448722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		break;
449b6c028e00445de9dfde2cd0c26521ac53965320aChris Wilson
4508dfbc3403113bcc51f0350c3471fa1abf664305fChris Wilson	case SWITCH_OFF:
451722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		intel_overlay_off_tail(overlay);
452722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		break;
4538dfbc3403113bcc51f0350c3471fa1abf664305fChris Wilson
454722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	default:
455722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		BUG_ON(overlay->hw_wedged != NEEDS_WAIT_FOR_FLIP);
45603f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	}
45703f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter
45803f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	overlay->hw_wedged = 0;
45903f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	overlay->last_flip_req = 0;
46003f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	return 0;
46103f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter}
46203f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter
4635a5a0c64a99d7542c48c99d1a8bbb49e665842beDaniel Vetter/* Wait for pending overlay flip and release old frame.
4645a5a0c64a99d7542c48c99d1a8bbb49e665842beDaniel Vetter * Needs to be called before the overlay register are changed
4658d74f656dd78ae1ba813389cd46197c6329696bcChris Wilson * via intel_overlay_(un)map_regs
4668d74f656dd78ae1ba813389cd46197c6329696bcChris Wilson */
46702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic int intel_overlay_release_old_vid(struct intel_overlay *overlay)
46802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
4695cd68c9864d65e49c910c701716e4e94e09f7ce0Chris Wilson	struct drm_device *dev = overlay->dev;
4705cd68c9864d65e49c910c701716e4e94e09f7ce0Chris Wilson	drm_i915_private_t *dev_priv = dev->dev_private;
47102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int ret;
47202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
4735cd68c9864d65e49c910c701716e4e94e09f7ce0Chris Wilson	/* Only wait if there is actually an old frame to release to
4745cd68c9864d65e49c910c701716e4e94e09f7ce0Chris Wilson	 * guarantee forward progress.
4755cd68c9864d65e49c910c701716e4e94e09f7ce0Chris Wilson	 */
47603f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	if (!overlay->old_vid_bo)
47703f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter		return 0;
47803f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter
4795cd68c9864d65e49c910c701716e4e94e09f7ce0Chris Wilson	if (I915_READ(ISR) & I915_OVERLAY_PLANE_FLIP_PENDING_INTERRUPT) {
4808dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson		struct drm_i915_gem_request *request;
4818dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson
4825cd68c9864d65e49c910c701716e4e94e09f7ce0Chris Wilson		/* synchronous slowpath */
4838dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson		request = kzalloc(sizeof(*request), GFP_KERNEL);
4848dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson		if (request == NULL)
4858dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson			return -ENOMEM;
4868dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson
4875cd68c9864d65e49c910c701716e4e94e09f7ce0Chris Wilson		BEGIN_LP_RING(2);
4885cd68c9864d65e49c910c701716e4e94e09f7ce0Chris Wilson		OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
4895cd68c9864d65e49c910c701716e4e94e09f7ce0Chris Wilson		OUT_RING(MI_NOOP);
4905cd68c9864d65e49c910c701716e4e94e09f7ce0Chris Wilson		ADVANCE_LP_RING();
4915cd68c9864d65e49c910c701716e4e94e09f7ce0Chris Wilson
4928dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson		ret = intel_overlay_do_wait_request(overlay, request, true,
4935cd68c9864d65e49c910c701716e4e94e09f7ce0Chris Wilson						    RELEASE_OLD_VID);
4945cd68c9864d65e49c910c701716e4e94e09f7ce0Chris Wilson		if (ret)
4955cd68c9864d65e49c910c701716e4e94e09f7ce0Chris Wilson			return ret;
4965cd68c9864d65e49c910c701716e4e94e09f7ce0Chris Wilson	}
49702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
4985cd68c9864d65e49c910c701716e4e94e09f7ce0Chris Wilson	intel_overlay_release_old_vid_tail(overlay);
49902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return 0;
50002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
50102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
50202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstruct put_image_params {
50302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int format;
50402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	short dst_x;
50502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	short dst_y;
50602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	short dst_w;
50702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	short dst_h;
50802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	short src_w;
50902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	short src_scan_h;
51002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	short src_scan_w;
51102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	short src_h;
51202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	short stride_Y;
51302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	short stride_UV;
51402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int offset_Y;
51502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int offset_U;
51602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int offset_V;
51702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter};
51802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
51902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic int packed_depth_bytes(u32 format)
52002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
52102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	switch (format & I915_OVERLAY_DEPTH_MASK) {
522722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case I915_OVERLAY_YUV422:
523722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		return 4;
524722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case I915_OVERLAY_YUV411:
525722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		/* return 6; not implemented */
526722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	default:
527722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		return -EINVAL;
52802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
52902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
53002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
53102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic int packed_width_bytes(u32 format, short width)
53202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
53302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	switch (format & I915_OVERLAY_DEPTH_MASK) {
534722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case I915_OVERLAY_YUV422:
535722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		return width << 1;
536722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	default:
537722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		return -EINVAL;
53802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
53902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
54002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
54102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic int uv_hsubsampling(u32 format)
54202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
54302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	switch (format & I915_OVERLAY_DEPTH_MASK) {
544722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case I915_OVERLAY_YUV422:
545722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case I915_OVERLAY_YUV420:
546722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		return 2;
547722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case I915_OVERLAY_YUV411:
548722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case I915_OVERLAY_YUV410:
549722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		return 4;
550722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	default:
551722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		return -EINVAL;
55202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
55302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
55402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
55502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic int uv_vsubsampling(u32 format)
55602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
55702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	switch (format & I915_OVERLAY_DEPTH_MASK) {
558722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case I915_OVERLAY_YUV420:
559722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case I915_OVERLAY_YUV410:
560722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		return 2;
561722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case I915_OVERLAY_YUV422:
562722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case I915_OVERLAY_YUV411:
563722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		return 1;
564722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	default:
565722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		return -EINVAL;
56602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
56702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
56802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
56902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic u32 calc_swidthsw(struct drm_device *dev, u32 offset, u32 width)
57002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
57102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	u32 mask, shift, ret;
57202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (IS_I9XX(dev)) {
57302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		mask = 0x3f;
57402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		shift = 6;
57502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	} else {
57602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		mask = 0x1f;
57702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		shift = 5;
57802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
57902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	ret = ((offset + width + mask) >> shift) - (offset >> shift);
58002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (IS_I9XX(dev))
58102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		ret <<= 1;
58202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	ret -=1;
58302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return ret << 2;
58402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
58502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
58602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic const u16 y_static_hcoeffs[N_HORIZ_Y_TAPS * N_PHASES] = {
58702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3000, 0xb4a0, 0x1930, 0x1920, 0xb4a0,
58802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3000, 0xb500, 0x19d0, 0x1880, 0xb440,
58902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3000, 0xb540, 0x1a88, 0x2f80, 0xb3e0,
59002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3000, 0xb580, 0x1b30, 0x2e20, 0xb380,
59102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3000, 0xb5c0, 0x1bd8, 0x2cc0, 0xb320,
59202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3020, 0xb5e0, 0x1c60, 0x2b80, 0xb2c0,
59302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3020, 0xb5e0, 0x1cf8, 0x2a20, 0xb260,
59402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3020, 0xb5e0, 0x1d80, 0x28e0, 0xb200,
59502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3020, 0xb5c0, 0x1e08, 0x3f40, 0xb1c0,
59602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3020, 0xb580, 0x1e78, 0x3ce0, 0xb160,
59702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3040, 0xb520, 0x1ed8, 0x3aa0, 0xb120,
59802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3040, 0xb4a0, 0x1f30, 0x3880, 0xb0e0,
59902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3040, 0xb400, 0x1f78, 0x3680, 0xb0a0,
60002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3020, 0xb340, 0x1fb8, 0x34a0, 0xb060,
60102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3020, 0xb240, 0x1fe0, 0x32e0, 0xb040,
60202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3020, 0xb140, 0x1ff8, 0x3160, 0xb020,
603722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	0xb000, 0x3000, 0x0800, 0x3000, 0xb000
604722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson};
605722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson
60602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic const u16 uv_static_hcoeffs[N_HORIZ_UV_TAPS * N_PHASES] = {
60702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3000, 0x1800, 0x1800, 0xb000, 0x18d0, 0x2e60,
60802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0xb000, 0x1990, 0x2ce0, 0xb020, 0x1a68, 0x2b40,
60902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0xb040, 0x1b20, 0x29e0, 0xb060, 0x1bd8, 0x2880,
61002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0xb080, 0x1c88, 0x3e60, 0xb0a0, 0x1d28, 0x3c00,
61102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0xb0c0, 0x1db8, 0x39e0, 0xb0e0, 0x1e40, 0x37e0,
61202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0xb100, 0x1eb8, 0x3620, 0xb100, 0x1f18, 0x34a0,
61302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0xb100, 0x1f68, 0x3360, 0xb0e0, 0x1fa8, 0x3240,
61402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0xb0c0, 0x1fe0, 0x3140, 0xb060, 0x1ff0, 0x30a0,
615722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	0x3000, 0x0800, 0x3000
616722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson};
61702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
61802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic void update_polyphase_filter(struct overlay_registers *regs)
61902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
62002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	memcpy(regs->Y_HCOEFS, y_static_hcoeffs, sizeof(y_static_hcoeffs));
62102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	memcpy(regs->UV_HCOEFS, uv_static_hcoeffs, sizeof(uv_static_hcoeffs));
62202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
62302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
62402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic bool update_scaling_factors(struct intel_overlay *overlay,
62502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				   struct overlay_registers *regs,
62602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				   struct put_image_params *params)
62702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
62802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* fixed point with a 12 bit shift */
62902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	u32 xscale, yscale, xscale_UV, yscale_UV;
63002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define FP_SHIFT 12
63102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define FRACT_MASK 0xfff
63202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	bool scale_changed = false;
63302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int uv_hscale = uv_hsubsampling(params->format);
63402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int uv_vscale = uv_vsubsampling(params->format);
63502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
63602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (params->dst_w > 1)
63702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		xscale = ((params->src_scan_w - 1) << FP_SHIFT)
63802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			/(params->dst_w);
63902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	else
64002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		xscale = 1 << FP_SHIFT;
64102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
64202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (params->dst_h > 1)
64302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		yscale = ((params->src_scan_h - 1) << FP_SHIFT)
64402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			/(params->dst_h);
64502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	else
64602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		yscale = 1 << FP_SHIFT;
64702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
64802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/*if (params->format & I915_OVERLAY_YUV_PLANAR) {*/
649722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	xscale_UV = xscale/uv_hscale;
650722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	yscale_UV = yscale/uv_vscale;
651722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	/* make the Y scale to UV scale ratio an exact multiply */
652722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	xscale = xscale_UV * uv_hscale;
653722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	yscale = yscale_UV * uv_vscale;
65402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/*} else {
655722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	  xscale_UV = 0;
656722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	  yscale_UV = 0;
657722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	  }*/
65802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
65902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (xscale != overlay->old_xscale || yscale != overlay->old_yscale)
66002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		scale_changed = true;
66102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	overlay->old_xscale = xscale;
66202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	overlay->old_yscale = yscale;
66302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
664722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	regs->YRGBSCALE = (((yscale & FRACT_MASK) << 20) |
665722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			   ((xscale >> FP_SHIFT)  << 16) |
666722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			   ((xscale & FRACT_MASK) << 3));
667722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson
668722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	regs->UVSCALE = (((yscale_UV & FRACT_MASK) << 20) |
669722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			 ((xscale_UV >> FP_SHIFT)  << 16) |
670722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			 ((xscale_UV & FRACT_MASK) << 3));
671722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson
672722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	regs->UVSCALEV = ((((yscale    >> FP_SHIFT) << 16) |
673722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			   ((yscale_UV >> FP_SHIFT) << 0)));
67402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
67502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (scale_changed)
67602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		update_polyphase_filter(regs);
67702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
67802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return scale_changed;
67902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
68002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
68102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic void update_colorkey(struct intel_overlay *overlay,
68202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			    struct overlay_registers *regs)
68302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
68402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	u32 key = overlay->color_key;
6856ba3ddd9838f5e4d6ac7c6dce95648d205e11bffChris Wilson
68602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	switch (overlay->crtc->base.fb->bits_per_pixel) {
687722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case 8:
688722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		regs->DCLRKV = 0;
689722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		regs->DCLRKM = CLK_RGB8I_MASK | DST_KEY_ENABLE;
6906ba3ddd9838f5e4d6ac7c6dce95648d205e11bffChris Wilson		break;
6916ba3ddd9838f5e4d6ac7c6dce95648d205e11bffChris Wilson
692722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case 16:
693722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		if (overlay->crtc->base.fb->depth == 15) {
694722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			regs->DCLRKV = RGB15_TO_COLORKEY(key);
695722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			regs->DCLRKM = CLK_RGB15_MASK | DST_KEY_ENABLE;
696722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		} else {
697722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			regs->DCLRKV = RGB16_TO_COLORKEY(key);
698722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			regs->DCLRKM = CLK_RGB16_MASK | DST_KEY_ENABLE;
699722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		}
7006ba3ddd9838f5e4d6ac7c6dce95648d205e11bffChris Wilson		break;
7016ba3ddd9838f5e4d6ac7c6dce95648d205e11bffChris Wilson
702722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case 24:
703722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case 32:
704722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		regs->DCLRKV = key;
705722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		regs->DCLRKM = CLK_RGB24_MASK | DST_KEY_ENABLE;
7066ba3ddd9838f5e4d6ac7c6dce95648d205e11bffChris Wilson		break;
70702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
70802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
70902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
71002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic u32 overlay_cmd_reg(struct put_image_params *params)
71102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
71202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	u32 cmd = OCMD_ENABLE | OCMD_BUF_TYPE_FRAME | OCMD_BUFFER0;
71302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
71402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (params->format & I915_OVERLAY_YUV_PLANAR) {
71502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		switch (params->format & I915_OVERLAY_DEPTH_MASK) {
716722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		case I915_OVERLAY_YUV422:
717722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			cmd |= OCMD_YUV_422_PLANAR;
718722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			break;
719722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		case I915_OVERLAY_YUV420:
720722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			cmd |= OCMD_YUV_420_PLANAR;
721722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			break;
722722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		case I915_OVERLAY_YUV411:
723722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		case I915_OVERLAY_YUV410:
724722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			cmd |= OCMD_YUV_410_PLANAR;
725722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			break;
72602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		}
72702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	} else { /* YUV packed */
72802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		switch (params->format & I915_OVERLAY_DEPTH_MASK) {
729722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		case I915_OVERLAY_YUV422:
730722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			cmd |= OCMD_YUV_422_PACKED;
731722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			break;
732722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		case I915_OVERLAY_YUV411:
733722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			cmd |= OCMD_YUV_411_PACKED;
734722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			break;
73502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		}
73602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
73702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		switch (params->format & I915_OVERLAY_SWAP_MASK) {
738722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		case I915_OVERLAY_NO_SWAP:
739722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			break;
740722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		case I915_OVERLAY_UV_SWAP:
741722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			cmd |= OCMD_UV_SWAP;
742722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			break;
743722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		case I915_OVERLAY_Y_SWAP:
744722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			cmd |= OCMD_Y_SWAP;
745722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			break;
746722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		case I915_OVERLAY_Y_AND_UV_SWAP:
747722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			cmd |= OCMD_Y_AND_UV_SWAP;
748722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			break;
74902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		}
75002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
75102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
75202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return cmd;
75302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
75402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
7555fe82c5ee1ba2d04183c376038c5d233a0311ec9Chris Wilsonstatic int intel_overlay_do_put_image(struct intel_overlay *overlay,
7565fe82c5ee1ba2d04183c376038c5d233a0311ec9Chris Wilson				      struct drm_gem_object *new_bo,
7575fe82c5ee1ba2d04183c376038c5d233a0311ec9Chris Wilson				      struct put_image_params *params)
75802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
75902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int ret, tmp_width;
76002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct overlay_registers *regs;
76102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	bool scale_changed = false;
76223010e43b353c2cdc9725cbedc7e364708039bf7Daniel Vetter	struct drm_i915_gem_object *bo_priv = to_intel_bo(new_bo);
76302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct drm_device *dev = overlay->dev;
76402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
76502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	BUG_ON(!mutex_is_locked(&dev->struct_mutex));
76602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	BUG_ON(!mutex_is_locked(&dev->mode_config.mutex));
76702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	BUG_ON(!overlay);
76802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
76902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	ret = intel_overlay_release_old_vid(overlay);
77002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (ret != 0)
77102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return ret;
77202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
77302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	ret = i915_gem_object_pin(new_bo, PAGE_SIZE);
77402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (ret != 0)
77502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return ret;
77602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
77702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	ret = i915_gem_object_set_to_gtt_domain(new_bo, 0);
77802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (ret != 0)
77902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		goto out_unpin;
78002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
78102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!overlay->active) {
7828d74f656dd78ae1ba813389cd46197c6329696bcChris Wilson		regs = intel_overlay_map_regs(overlay);
78302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		if (!regs) {
78402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			ret = -ENOMEM;
78502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			goto out_unpin;
78602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		}
78702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		regs->OCONFIG = OCONF_CC_OUT_8BIT;
78802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		if (IS_I965GM(overlay->dev))
78902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			regs->OCONFIG |= OCONF_CSC_MODE_BT709;
79002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		regs->OCONFIG |= overlay->crtc->pipe == 0 ?
79102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			OCONF_PIPE_A : OCONF_PIPE_B;
7929bb2ff731b32c023e7a502efdc0dee46157290d5Chris Wilson		intel_overlay_unmap_regs(overlay, regs);
79302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
79402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		ret = intel_overlay_on(overlay);
79502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		if (ret != 0)
79602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			goto out_unpin;
79702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
79802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
7998d74f656dd78ae1ba813389cd46197c6329696bcChris Wilson	regs = intel_overlay_map_regs(overlay);
80002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!regs) {
80102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		ret = -ENOMEM;
80202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		goto out_unpin;
80302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
80402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
80502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	regs->DWINPOS = (params->dst_y << 16) | params->dst_x;
80602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	regs->DWINSZ = (params->dst_h << 16) | params->dst_w;
80702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
80802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (params->format & I915_OVERLAY_YUV_PACKED)
80902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		tmp_width = packed_width_bytes(params->format, params->src_w);
81002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	else
81102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		tmp_width = params->src_w;
81202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
81302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	regs->SWIDTH = params->src_w;
81402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	regs->SWIDTHSW = calc_swidthsw(overlay->dev,
815722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson				       params->offset_Y, tmp_width);
81602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	regs->SHEIGHT = params->src_h;
81702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	regs->OBUF_0Y = bo_priv->gtt_offset + params-> offset_Y;
81802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	regs->OSTRIDE = params->stride_Y;
81902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
82002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (params->format & I915_OVERLAY_YUV_PLANAR) {
82102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		int uv_hscale = uv_hsubsampling(params->format);
82202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		int uv_vscale = uv_vsubsampling(params->format);
82302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		u32 tmp_U, tmp_V;
82402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		regs->SWIDTH |= (params->src_w/uv_hscale) << 16;
82502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		tmp_U = calc_swidthsw(overlay->dev, params->offset_U,
826722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson				      params->src_w/uv_hscale);
82702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		tmp_V = calc_swidthsw(overlay->dev, params->offset_V,
828722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson				      params->src_w/uv_hscale);
82902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		regs->SWIDTHSW |= max_t(u32, tmp_U, tmp_V) << 16;
83002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		regs->SHEIGHT |= (params->src_h/uv_vscale) << 16;
83102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		regs->OBUF_0U = bo_priv->gtt_offset + params->offset_U;
83202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		regs->OBUF_0V = bo_priv->gtt_offset + params->offset_V;
83302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		regs->OSTRIDE |= params->stride_UV << 16;
83402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
83502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
83602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	scale_changed = update_scaling_factors(overlay, regs, params);
83702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
83802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	update_colorkey(overlay, regs);
83902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
84002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	regs->OCMD = overlay_cmd_reg(params);
84102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
8429bb2ff731b32c023e7a502efdc0dee46157290d5Chris Wilson	intel_overlay_unmap_regs(overlay, regs);
84302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
8448dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson	ret = intel_overlay_continue(overlay, scale_changed);
8458dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson	if (ret)
8468dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson		goto out_unpin;
84702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
84802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	overlay->old_vid_bo = overlay->vid_bo;
84923010e43b353c2cdc9725cbedc7e364708039bf7Daniel Vetter	overlay->vid_bo = to_intel_bo(new_bo);
85002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
85102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return 0;
85202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
85302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterout_unpin:
85402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	i915_gem_object_unpin(new_bo);
85502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return ret;
85602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
85702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
85802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterint intel_overlay_switch_off(struct intel_overlay *overlay)
85902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
86002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int ret;
86102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct overlay_registers *regs;
86202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct drm_device *dev = overlay->dev;
86302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
86402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	BUG_ON(!mutex_is_locked(&dev->struct_mutex));
86502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	BUG_ON(!mutex_is_locked(&dev->mode_config.mutex));
86602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
8679bedb9743fd906e4160468663ee6e1bbdc4412b8Daniel Vetter	if (overlay->hw_wedged) {
8689bedb9743fd906e4160468663ee6e1bbdc4412b8Daniel Vetter		ret = intel_overlay_recover_from_interrupt(overlay, 1);
8699bedb9743fd906e4160468663ee6e1bbdc4412b8Daniel Vetter		if (ret != 0)
8709bedb9743fd906e4160468663ee6e1bbdc4412b8Daniel Vetter			return ret;
8719bedb9743fd906e4160468663ee6e1bbdc4412b8Daniel Vetter	}
8729bedb9743fd906e4160468663ee6e1bbdc4412b8Daniel Vetter
87302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!overlay->active)
87402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return 0;
87502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
87602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	ret = intel_overlay_release_old_vid(overlay);
87702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (ret != 0)
87802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return ret;
87902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
8808d74f656dd78ae1ba813389cd46197c6329696bcChris Wilson	regs = intel_overlay_map_regs(overlay);
88102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	regs->OCMD = 0;
8829bb2ff731b32c023e7a502efdc0dee46157290d5Chris Wilson	intel_overlay_unmap_regs(overlay, regs);
88302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
88402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	ret = intel_overlay_off(overlay);
88503f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	if (ret != 0)
88603f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter		return ret;
88703f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter
88812ca45fea91cfbb09df828bea958b47348caee6dDaniel Vetter	intel_overlay_off_tail(overlay);
88902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
89002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return 0;
89102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
89202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
89302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic int check_overlay_possible_on_crtc(struct intel_overlay *overlay,
89402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter					  struct intel_crtc *crtc)
89502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
896722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	drm_i915_private_t *dev_priv = overlay->dev->dev_private;
89702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	u32 pipeconf;
89802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int pipeconf_reg = (crtc->pipe == 0) ? PIPEACONF : PIPEBCONF;
89902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
90002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!crtc->base.enabled || crtc->dpms_mode != DRM_MODE_DPMS_ON)
90102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EINVAL;
90202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
90302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	pipeconf = I915_READ(pipeconf_reg);
90402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
90502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* can't use the overlay with double wide pipe */
90602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!IS_I965G(overlay->dev) && pipeconf & PIPEACONF_DOUBLE_WIDE)
90702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EINVAL;
90802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
90902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return 0;
91002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
91102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
91202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic void update_pfit_vscale_ratio(struct intel_overlay *overlay)
91302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
91402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct drm_device *dev = overlay->dev;
915722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	drm_i915_private_t *dev_priv = dev->dev_private;
91602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	u32 pfit_control = I915_READ(PFIT_CONTROL);
917446d2183af68c0fd2772f5ef97a033efe69904a5Chris Wilson	u32 ratio;
91802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
91902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* XXX: This is not the same logic as in the xorg driver, but more in
920446d2183af68c0fd2772f5ef97a033efe69904a5Chris Wilson	 * line with the intel documentation for the i965
921446d2183af68c0fd2772f5ef97a033efe69904a5Chris Wilson	 */
922446d2183af68c0fd2772f5ef97a033efe69904a5Chris Wilson	if (!IS_I965G(dev)) {
923446d2183af68c0fd2772f5ef97a033efe69904a5Chris Wilson		if (pfit_control & VERT_AUTO_SCALE)
924446d2183af68c0fd2772f5ef97a033efe69904a5Chris Wilson			ratio = I915_READ(PFIT_AUTO_RATIOS);
92502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		else
926446d2183af68c0fd2772f5ef97a033efe69904a5Chris Wilson			ratio = I915_READ(PFIT_PGM_RATIOS);
927446d2183af68c0fd2772f5ef97a033efe69904a5Chris Wilson		ratio >>= PFIT_VERT_SCALE_SHIFT;
928446d2183af68c0fd2772f5ef97a033efe69904a5Chris Wilson	} else { /* on i965 use the PGM reg to read out the autoscaler values */
929446d2183af68c0fd2772f5ef97a033efe69904a5Chris Wilson		ratio = I915_READ(PFIT_PGM_RATIOS) >> PFIT_VERT_SCALE_SHIFT_965;
93002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
93102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
93202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	overlay->pfit_vscale_ratio = ratio;
93302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
93402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
93502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic int check_overlay_dst(struct intel_overlay *overlay,
93602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			     struct drm_intel_overlay_put_image *rec)
93702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
93802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct drm_display_mode *mode = &overlay->crtc->base.mode;
93902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
940722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	if (rec->dst_x < mode->crtc_hdisplay &&
941722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	    rec->dst_x + rec->dst_width <= mode->crtc_hdisplay &&
942722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	    rec->dst_y < mode->crtc_vdisplay &&
943722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	    rec->dst_y + rec->dst_height <= mode->crtc_vdisplay)
94402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return 0;
94502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	else
94602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EINVAL;
94702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
94802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
94902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic int check_overlay_scaling(struct put_image_params *rec)
95002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
95102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	u32 tmp;
95202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
95302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* downscaling limit is 8.0 */
95402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	tmp = ((rec->src_scan_h << 16) / rec->dst_h) >> 16;
95502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (tmp > 7)
95602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EINVAL;
95702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	tmp = ((rec->src_scan_w << 16) / rec->dst_w) >> 16;
95802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (tmp > 7)
95902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EINVAL;
96002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
96102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return 0;
96202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
96302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
96402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic int check_overlay_src(struct drm_device *dev,
96502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			     struct drm_intel_overlay_put_image *rec,
96602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			     struct drm_gem_object *new_bo)
96702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
96802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int uv_hscale = uv_hsubsampling(rec->flags);
96902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int uv_vscale = uv_vsubsampling(rec->flags);
9709f7c3f442bb7c0d0a0ed25cc287932450a1f2babChris Wilson	u32 stride_mask, depth, tmp;
97102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
97202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* check src dimensions */
97302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (IS_845G(dev) || IS_I830(dev)) {
974722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		if (rec->src_height > IMAGE_MAX_HEIGHT_LEGACY ||
9759f7c3f442bb7c0d0a0ed25cc287932450a1f2babChris Wilson		    rec->src_width  > IMAGE_MAX_WIDTH_LEGACY)
97602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			return -EINVAL;
97702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	} else {
978722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		if (rec->src_height > IMAGE_MAX_HEIGHT ||
9799f7c3f442bb7c0d0a0ed25cc287932450a1f2babChris Wilson		    rec->src_width  > IMAGE_MAX_WIDTH)
98002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			return -EINVAL;
98102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
9829f7c3f442bb7c0d0a0ed25cc287932450a1f2babChris Wilson
98302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* better safe than sorry, use 4 as the maximal subsampling ratio */
984722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	if (rec->src_height < N_VERT_Y_TAPS*4 ||
9859f7c3f442bb7c0d0a0ed25cc287932450a1f2babChris Wilson	    rec->src_width  < N_HORIZ_Y_TAPS*4)
98602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EINVAL;
98702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
988a1efd14a99483a4fb9308902397ed86b69454c99Chris Wilson	/* check alignment constraints */
98902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	switch (rec->flags & I915_OVERLAY_TYPE_MASK) {
990722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case I915_OVERLAY_RGB:
991722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		/* not implemented */
992722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		return -EINVAL;
9939f7c3f442bb7c0d0a0ed25cc287932450a1f2babChris Wilson
994722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case I915_OVERLAY_YUV_PACKED:
995722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		if (uv_vscale != 1)
99602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			return -EINVAL;
9979f7c3f442bb7c0d0a0ed25cc287932450a1f2babChris Wilson
9989f7c3f442bb7c0d0a0ed25cc287932450a1f2babChris Wilson		depth = packed_depth_bytes(rec->flags);
999722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		if (depth < 0)
1000722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			return depth;
10019f7c3f442bb7c0d0a0ed25cc287932450a1f2babChris Wilson
1002722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		/* ignore UV planes */
1003722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		rec->stride_UV = 0;
1004722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		rec->offset_U = 0;
1005722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		rec->offset_V = 0;
1006722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		/* check pixel alignment */
1007722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		if (rec->offset_Y % depth)
1008722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			return -EINVAL;
1009722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		break;
10109f7c3f442bb7c0d0a0ed25cc287932450a1f2babChris Wilson
1011722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case I915_OVERLAY_YUV_PLANAR:
1012722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		if (uv_vscale < 0 || uv_hscale < 0)
101302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			return -EINVAL;
1014722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		/* no offset restrictions for planar formats */
1015722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		break;
10169f7c3f442bb7c0d0a0ed25cc287932450a1f2babChris Wilson
1017722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	default:
1018722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		return -EINVAL;
101902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
102002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
102102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (rec->src_width % uv_hscale)
102202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EINVAL;
102302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
102402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* stride checking */
1025a1efd14a99483a4fb9308902397ed86b69454c99Chris Wilson	if (IS_I830(dev) || IS_845G(dev))
1026a1efd14a99483a4fb9308902397ed86b69454c99Chris Wilson		stride_mask = 255;
1027a1efd14a99483a4fb9308902397ed86b69454c99Chris Wilson	else
1028a1efd14a99483a4fb9308902397ed86b69454c99Chris Wilson		stride_mask = 63;
102902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
103002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (rec->stride_Y & stride_mask || rec->stride_UV & stride_mask)
103102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EINVAL;
103202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (IS_I965G(dev) && rec->stride_Y < 512)
103302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EINVAL;
103402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
103502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	tmp = (rec->flags & I915_OVERLAY_TYPE_MASK) == I915_OVERLAY_YUV_PLANAR ?
10369f7c3f442bb7c0d0a0ed25cc287932450a1f2babChris Wilson		4096 : 8192;
10379f7c3f442bb7c0d0a0ed25cc287932450a1f2babChris Wilson	if (rec->stride_Y > tmp || rec->stride_UV > 2*1024)
103802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EINVAL;
103902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
104002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* check buffer dimensions */
104102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	switch (rec->flags & I915_OVERLAY_TYPE_MASK) {
1042722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case I915_OVERLAY_RGB:
1043722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case I915_OVERLAY_YUV_PACKED:
1044722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		/* always 4 Y values per depth pixels */
1045722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		if (packed_width_bytes(rec->flags, rec->src_width) > rec->stride_Y)
1046722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			return -EINVAL;
1047722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson
1048722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		tmp = rec->stride_Y*rec->src_height;
1049722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		if (rec->offset_Y + tmp > new_bo->size)
1050722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			return -EINVAL;
1051722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		break;
1052722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson
1053722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case I915_OVERLAY_YUV_PLANAR:
1054722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		if (rec->src_width > rec->stride_Y)
1055722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			return -EINVAL;
1056722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		if (rec->src_width/uv_hscale > rec->stride_UV)
1057722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			return -EINVAL;
1058722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson
10599f7c3f442bb7c0d0a0ed25cc287932450a1f2babChris Wilson		tmp = rec->stride_Y * rec->src_height;
1060722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		if (rec->offset_Y + tmp > new_bo->size)
1061722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			return -EINVAL;
10629f7c3f442bb7c0d0a0ed25cc287932450a1f2babChris Wilson
10639f7c3f442bb7c0d0a0ed25cc287932450a1f2babChris Wilson		tmp = rec->stride_UV * (rec->src_height / uv_vscale);
1064722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		if (rec->offset_U + tmp > new_bo->size ||
1065722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		    rec->offset_V + tmp > new_bo->size)
1066722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			return -EINVAL;
1067722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		break;
106802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
106902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
107002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return 0;
107102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
107202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
107302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterint intel_overlay_put_image(struct drm_device *dev, void *data,
107402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter                            struct drm_file *file_priv)
107502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
107602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct drm_intel_overlay_put_image *put_image_rec = data;
107702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	drm_i915_private_t *dev_priv = dev->dev_private;
107802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct intel_overlay *overlay;
107902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct drm_mode_object *drmmode_obj;
108002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct intel_crtc *crtc;
108102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct drm_gem_object *new_bo;
108202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct put_image_params *params;
108302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int ret;
108402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
108502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!dev_priv) {
108602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		DRM_ERROR("called with no initialization\n");
108702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EINVAL;
108802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
108902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
109002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	overlay = dev_priv->overlay;
109102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!overlay) {
109202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		DRM_DEBUG("userspace bug: no overlay\n");
109302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -ENODEV;
109402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
109502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
109602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!(put_image_rec->flags & I915_OVERLAY_ENABLE)) {
109702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		mutex_lock(&dev->mode_config.mutex);
109802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		mutex_lock(&dev->struct_mutex);
109902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
110002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		ret = intel_overlay_switch_off(overlay);
110102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
110202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		mutex_unlock(&dev->struct_mutex);
110302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		mutex_unlock(&dev->mode_config.mutex);
110402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
110502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return ret;
110602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
110702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
110802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	params = kmalloc(sizeof(struct put_image_params), GFP_KERNEL);
110902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!params)
111002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -ENOMEM;
111102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
111202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	drmmode_obj = drm_mode_object_find(dev, put_image_rec->crtc_id,
1113722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson					   DRM_MODE_OBJECT_CRTC);
1114915a428e43acfd05e4ffeaf40549b0cf163eebe2Dan Carpenter	if (!drmmode_obj) {
1115915a428e43acfd05e4ffeaf40549b0cf163eebe2Dan Carpenter		ret = -ENOENT;
1116915a428e43acfd05e4ffeaf40549b0cf163eebe2Dan Carpenter		goto out_free;
1117915a428e43acfd05e4ffeaf40549b0cf163eebe2Dan Carpenter	}
111802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	crtc = to_intel_crtc(obj_to_crtc(drmmode_obj));
111902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
112002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	new_bo = drm_gem_object_lookup(dev, file_priv,
1121722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson				       put_image_rec->bo_handle);
1122915a428e43acfd05e4ffeaf40549b0cf163eebe2Dan Carpenter	if (!new_bo) {
1123915a428e43acfd05e4ffeaf40549b0cf163eebe2Dan Carpenter		ret = -ENOENT;
1124915a428e43acfd05e4ffeaf40549b0cf163eebe2Dan Carpenter		goto out_free;
1125915a428e43acfd05e4ffeaf40549b0cf163eebe2Dan Carpenter	}
112602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
112702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	mutex_lock(&dev->mode_config.mutex);
112802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	mutex_lock(&dev->struct_mutex);
112902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
113003f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	if (overlay->hw_wedged) {
113103f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter		ret = intel_overlay_recover_from_interrupt(overlay, 1);
113203f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter		if (ret != 0)
113303f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter			goto out_unlock;
113403f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	}
113503f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter
113602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (overlay->crtc != crtc) {
113702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		struct drm_display_mode *mode = &crtc->base.mode;
113802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		ret = intel_overlay_switch_off(overlay);
113902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		if (ret != 0)
114002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			goto out_unlock;
114102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
114202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		ret = check_overlay_possible_on_crtc(overlay, crtc);
114302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		if (ret != 0)
114402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			goto out_unlock;
114502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
114602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		overlay->crtc = crtc;
114702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		crtc->overlay = overlay;
114802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
114902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		if (intel_panel_fitter_pipe(dev) == crtc->pipe
115002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		    /* and line to wide, i.e. one-line-mode */
115102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		    && mode->hdisplay > 1024) {
115202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			overlay->pfit_active = 1;
115302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			update_pfit_vscale_ratio(overlay);
115402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		} else
115502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			overlay->pfit_active = 0;
115602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
115702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
115802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	ret = check_overlay_dst(overlay, put_image_rec);
115902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (ret != 0)
116002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		goto out_unlock;
116102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
116202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (overlay->pfit_active) {
116302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		params->dst_y = ((((u32)put_image_rec->dst_y) << 12) /
1164722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson				 overlay->pfit_vscale_ratio);
116502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		/* shifting right rounds downwards, so add 1 */
116602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		params->dst_h = ((((u32)put_image_rec->dst_height) << 12) /
1167722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson				 overlay->pfit_vscale_ratio) + 1;
116802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	} else {
116902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		params->dst_y = put_image_rec->dst_y;
117002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		params->dst_h = put_image_rec->dst_height;
117102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
117202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	params->dst_x = put_image_rec->dst_x;
117302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	params->dst_w = put_image_rec->dst_width;
117402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
117502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	params->src_w = put_image_rec->src_width;
117602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	params->src_h = put_image_rec->src_height;
117702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	params->src_scan_w = put_image_rec->src_scan_width;
117802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	params->src_scan_h = put_image_rec->src_scan_height;
1179722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	if (params->src_scan_h > params->src_h ||
1180722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	    params->src_scan_w > params->src_w) {
118102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		ret = -EINVAL;
118202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		goto out_unlock;
118302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
118402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
118502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	ret = check_overlay_src(dev, put_image_rec, new_bo);
118602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (ret != 0)
118702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		goto out_unlock;
118802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	params->format = put_image_rec->flags & ~I915_OVERLAY_FLAGS_MASK;
118902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	params->stride_Y = put_image_rec->stride_Y;
119002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	params->stride_UV = put_image_rec->stride_UV;
119102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	params->offset_Y = put_image_rec->offset_Y;
119202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	params->offset_U = put_image_rec->offset_U;
119302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	params->offset_V = put_image_rec->offset_V;
119402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
119502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* Check scaling after src size to prevent a divide-by-zero. */
119602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	ret = check_overlay_scaling(params);
119702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (ret != 0)
119802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		goto out_unlock;
119902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
120002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	ret = intel_overlay_do_put_image(overlay, new_bo, params);
120102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (ret != 0)
120202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		goto out_unlock;
120302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
120402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	mutex_unlock(&dev->struct_mutex);
120502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	mutex_unlock(&dev->mode_config.mutex);
120602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
120702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	kfree(params);
120802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
120902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return 0;
121002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
121102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterout_unlock:
121202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	mutex_unlock(&dev->struct_mutex);
121302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	mutex_unlock(&dev->mode_config.mutex);
1214bc9025bdc4e2b591734cca17697093845007b63dLuca Barbieri	drm_gem_object_unreference_unlocked(new_bo);
1215915a428e43acfd05e4ffeaf40549b0cf163eebe2Dan Carpenterout_free:
121602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	kfree(params);
121702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
121802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return ret;
121902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
122002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
122102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic void update_reg_attrs(struct intel_overlay *overlay,
122202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			     struct overlay_registers *regs)
122302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
122402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	regs->OCLRC0 = (overlay->contrast << 18) | (overlay->brightness & 0xff);
122502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	regs->OCLRC1 = overlay->saturation;
122602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
122702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
122802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic bool check_gamma_bounds(u32 gamma1, u32 gamma2)
122902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
123002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int i;
123102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
123202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (gamma1 & 0xff000000 || gamma2 & 0xff000000)
123302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return false;
123402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
123502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	for (i = 0; i < 3; i++) {
1236722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		if (((gamma1 >> i*8) & 0xff) >= ((gamma2 >> i*8) & 0xff))
123702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			return false;
123802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
123902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
124002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return true;
124102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
124202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
124302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic bool check_gamma5_errata(u32 gamma5)
124402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
124502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int i;
124602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
124702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	for (i = 0; i < 3; i++) {
124802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		if (((gamma5 >> i*8) & 0xff) == 0x80)
124902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			return false;
125002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
125102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
125202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return true;
125302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
125402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
125502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic int check_gamma(struct drm_intel_overlay_attrs *attrs)
125602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
1257722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	if (!check_gamma_bounds(0, attrs->gamma0) ||
1258722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	    !check_gamma_bounds(attrs->gamma0, attrs->gamma1) ||
1259722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	    !check_gamma_bounds(attrs->gamma1, attrs->gamma2) ||
1260722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	    !check_gamma_bounds(attrs->gamma2, attrs->gamma3) ||
1261722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	    !check_gamma_bounds(attrs->gamma3, attrs->gamma4) ||
1262722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	    !check_gamma_bounds(attrs->gamma4, attrs->gamma5) ||
1263722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	    !check_gamma_bounds(attrs->gamma5, 0x00ffffff))
126402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EINVAL;
1265722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson
126602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!check_gamma5_errata(attrs->gamma5))
126702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EINVAL;
1268722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson
126902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return 0;
127002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
127102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
127202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterint intel_overlay_attrs(struct drm_device *dev, void *data,
127302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter                        struct drm_file *file_priv)
127402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
127502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct drm_intel_overlay_attrs *attrs = data;
127602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter        drm_i915_private_t *dev_priv = dev->dev_private;
127702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct intel_overlay *overlay;
127802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct overlay_registers *regs;
127902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int ret;
128002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
128102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!dev_priv) {
128202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		DRM_ERROR("called with no initialization\n");
128302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EINVAL;
128402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
128502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
128602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	overlay = dev_priv->overlay;
128702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!overlay) {
128802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		DRM_DEBUG("userspace bug: no overlay\n");
128902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -ENODEV;
129002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
129102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
129202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	mutex_lock(&dev->mode_config.mutex);
129302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	mutex_lock(&dev->struct_mutex);
129402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
129560fc332cb5ab19e5a86d696b210df65814b2ad8aChris Wilson	ret = -EINVAL;
129602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!(attrs->flags & I915_OVERLAY_UPDATE_ATTRS)) {
129760fc332cb5ab19e5a86d696b210df65814b2ad8aChris Wilson		attrs->color_key  = overlay->color_key;
129802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		attrs->brightness = overlay->brightness;
129960fc332cb5ab19e5a86d696b210df65814b2ad8aChris Wilson		attrs->contrast   = overlay->contrast;
130002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		attrs->saturation = overlay->saturation;
130102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
130202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		if (IS_I9XX(dev)) {
130302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			attrs->gamma0 = I915_READ(OGAMC0);
130402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			attrs->gamma1 = I915_READ(OGAMC1);
130502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			attrs->gamma2 = I915_READ(OGAMC2);
130602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			attrs->gamma3 = I915_READ(OGAMC3);
130702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			attrs->gamma4 = I915_READ(OGAMC4);
130802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			attrs->gamma5 = I915_READ(OGAMC5);
130902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		}
131002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	} else {
131160fc332cb5ab19e5a86d696b210df65814b2ad8aChris Wilson		if (attrs->brightness < -128 || attrs->brightness > 127)
131202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			goto out_unlock;
131360fc332cb5ab19e5a86d696b210df65814b2ad8aChris Wilson		if (attrs->contrast > 255)
131402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			goto out_unlock;
131560fc332cb5ab19e5a86d696b210df65814b2ad8aChris Wilson		if (attrs->saturation > 1023)
131602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			goto out_unlock;
131760fc332cb5ab19e5a86d696b210df65814b2ad8aChris Wilson
131860fc332cb5ab19e5a86d696b210df65814b2ad8aChris Wilson		overlay->color_key  = attrs->color_key;
131960fc332cb5ab19e5a86d696b210df65814b2ad8aChris Wilson		overlay->brightness = attrs->brightness;
132060fc332cb5ab19e5a86d696b210df65814b2ad8aChris Wilson		overlay->contrast   = attrs->contrast;
132160fc332cb5ab19e5a86d696b210df65814b2ad8aChris Wilson		overlay->saturation = attrs->saturation;
132202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
13238d74f656dd78ae1ba813389cd46197c6329696bcChris Wilson		regs = intel_overlay_map_regs(overlay);
132402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		if (!regs) {
132502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			ret = -ENOMEM;
132602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			goto out_unlock;
132702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		}
132802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
132902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		update_reg_attrs(overlay, regs);
133002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
13319bb2ff731b32c023e7a502efdc0dee46157290d5Chris Wilson		intel_overlay_unmap_regs(overlay, regs);
133202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
133302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		if (attrs->flags & I915_OVERLAY_UPDATE_GAMMA) {
133460fc332cb5ab19e5a86d696b210df65814b2ad8aChris Wilson			if (!IS_I9XX(dev))
133502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				goto out_unlock;
133602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
133702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			if (overlay->active) {
133802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				ret = -EBUSY;
133902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				goto out_unlock;
134002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			}
134102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
134202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			ret = check_gamma(attrs);
134360fc332cb5ab19e5a86d696b210df65814b2ad8aChris Wilson			if (ret)
134402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				goto out_unlock;
134502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
134602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			I915_WRITE(OGAMC0, attrs->gamma0);
134702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			I915_WRITE(OGAMC1, attrs->gamma1);
134802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			I915_WRITE(OGAMC2, attrs->gamma2);
134902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			I915_WRITE(OGAMC3, attrs->gamma3);
135002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			I915_WRITE(OGAMC4, attrs->gamma4);
135102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			I915_WRITE(OGAMC5, attrs->gamma5);
135202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		}
135302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
135402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
135560fc332cb5ab19e5a86d696b210df65814b2ad8aChris Wilson	ret = 0;
135602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterout_unlock:
135702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	mutex_unlock(&dev->struct_mutex);
135802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	mutex_unlock(&dev->mode_config.mutex);
135902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
136002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return ret;
136102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
136202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
136302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vettervoid intel_setup_overlay(struct drm_device *dev)
136402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
136502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter        drm_i915_private_t *dev_priv = dev->dev_private;
136602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct intel_overlay *overlay;
136702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct drm_gem_object *reg_bo;
136802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct overlay_registers *regs;
136902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int ret;
137002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
137131578148b2c62612f9516fdcf5ebb64ab32ed12dChris Wilson	if (!HAS_OVERLAY(dev))
137202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return;
137302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
137402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	overlay = kzalloc(sizeof(struct intel_overlay), GFP_KERNEL);
137502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!overlay)
137602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return;
137702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	overlay->dev = dev;
137802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
1379ac52bc56de25535a907ef07f8755f1387b89b0f5Daniel Vetter	reg_bo = i915_gem_alloc_object(dev, PAGE_SIZE);
138002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!reg_bo)
138102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		goto out_free;
138223010e43b353c2cdc9725cbedc7e364708039bf7Daniel Vetter	overlay->reg_bo = to_intel_bo(reg_bo);
138302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
138431578148b2c62612f9516fdcf5ebb64ab32ed12dChris Wilson	if (OVERLAY_NEEDS_PHYSICAL(dev)) {
138531578148b2c62612f9516fdcf5ebb64ab32ed12dChris Wilson		ret = i915_gem_attach_phys_object(dev, reg_bo,
138631578148b2c62612f9516fdcf5ebb64ab32ed12dChris Wilson						  I915_GEM_PHYS_OVERLAY_REGS,
1387a29301288f1840bdf9c5456da9cd7c944436edd5Chris Wilson						  PAGE_SIZE);
138831578148b2c62612f9516fdcf5ebb64ab32ed12dChris Wilson                if (ret) {
138931578148b2c62612f9516fdcf5ebb64ab32ed12dChris Wilson                        DRM_ERROR("failed to attach phys overlay regs\n");
139031578148b2c62612f9516fdcf5ebb64ab32ed12dChris Wilson                        goto out_free_bo;
139131578148b2c62612f9516fdcf5ebb64ab32ed12dChris Wilson                }
139231578148b2c62612f9516fdcf5ebb64ab32ed12dChris Wilson		overlay->flip_addr = overlay->reg_bo->phys_obj->handle->busaddr;
139331578148b2c62612f9516fdcf5ebb64ab32ed12dChris Wilson	} else {
139402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		ret = i915_gem_object_pin(reg_bo, PAGE_SIZE);
139502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		if (ret) {
139602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter                        DRM_ERROR("failed to pin overlay register bo\n");
139702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter                        goto out_free_bo;
139802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter                }
139902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		overlay->flip_addr = overlay->reg_bo->gtt_offset;
14000ddc1289f3ffd779779ddd3922f26ae7d0a21604Chris Wilson
14010ddc1289f3ffd779779ddd3922f26ae7d0a21604Chris Wilson		ret = i915_gem_object_set_to_gtt_domain(reg_bo, true);
14020ddc1289f3ffd779779ddd3922f26ae7d0a21604Chris Wilson		if (ret) {
14030ddc1289f3ffd779779ddd3922f26ae7d0a21604Chris Wilson                        DRM_ERROR("failed to move overlay register bo into the GTT\n");
14040ddc1289f3ffd779779ddd3922f26ae7d0a21604Chris Wilson                        goto out_unpin_bo;
14050ddc1289f3ffd779779ddd3922f26ae7d0a21604Chris Wilson                }
140602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
140702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
140802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* init all values */
140902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	overlay->color_key = 0x0101fe;
141002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	overlay->brightness = -19;
141102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	overlay->contrast = 75;
141202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	overlay->saturation = 146;
141302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
14148d74f656dd78ae1ba813389cd46197c6329696bcChris Wilson	regs = intel_overlay_map_regs(overlay);
141502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!regs)
141602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		goto out_free_bo;
141702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
141802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	memset(regs, 0, sizeof(struct overlay_registers));
141902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	update_polyphase_filter(regs);
142002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	update_reg_attrs(overlay, regs);
142102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
14229bb2ff731b32c023e7a502efdc0dee46157290d5Chris Wilson	intel_overlay_unmap_regs(overlay, regs);
142302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
142402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	dev_priv->overlay = overlay;
142502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	DRM_INFO("initialized overlay support\n");
142602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return;
142702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
14280ddc1289f3ffd779779ddd3922f26ae7d0a21604Chris Wilsonout_unpin_bo:
14290ddc1289f3ffd779779ddd3922f26ae7d0a21604Chris Wilson	i915_gem_object_unpin(reg_bo);
143002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterout_free_bo:
143102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	drm_gem_object_unreference(reg_bo);
143202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterout_free:
143302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	kfree(overlay);
143402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return;
143502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
143602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
143702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vettervoid intel_cleanup_overlay(struct drm_device *dev)
143802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
1439722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	drm_i915_private_t *dev_priv = dev->dev_private;
144002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
144162cf4e6fef35b4422e206b63b7f0ac90261d4ad9Chris Wilson	if (!dev_priv->overlay)
144262cf4e6fef35b4422e206b63b7f0ac90261d4ad9Chris Wilson		return;
144302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
144462cf4e6fef35b4422e206b63b7f0ac90261d4ad9Chris Wilson	/* The bo's should be free'd by the generic code already.
144562cf4e6fef35b4422e206b63b7f0ac90261d4ad9Chris Wilson	 * Furthermore modesetting teardown happens beforehand so the
144662cf4e6fef35b4422e206b63b7f0ac90261d4ad9Chris Wilson	 * hardware should be off already */
144762cf4e6fef35b4422e206b63b7f0ac90261d4ad9Chris Wilson	BUG_ON(dev_priv->overlay->active);
144862cf4e6fef35b4422e206b63b7f0ac90261d4ad9Chris Wilson
144962cf4e6fef35b4422e206b63b7f0ac90261d4ad9Chris Wilson	drm_gem_object_unreference_unlocked(&dev_priv->overlay->reg_bo->base);
145062cf4e6fef35b4422e206b63b7f0ac90261d4ad9Chris Wilson	kfree(dev_priv->overlay);
145102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
14526ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson
14536ef3d4278034982c13df87c4a51e0445f762d316Chris Wilsonstruct intel_overlay_error_state {
14546ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	struct overlay_registers regs;
14556ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	unsigned long base;
14566ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	u32 dovsta;
14576ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	u32 isr;
14586ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson};
14596ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson
14606ef3d4278034982c13df87c4a51e0445f762d316Chris Wilsonstruct intel_overlay_error_state *
14616ef3d4278034982c13df87c4a51e0445f762d316Chris Wilsonintel_overlay_capture_error_state(struct drm_device *dev)
14626ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson{
14636ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson        drm_i915_private_t *dev_priv = dev->dev_private;
14646ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	struct intel_overlay *overlay = dev_priv->overlay;
14656ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	struct intel_overlay_error_state *error;
14666ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	struct overlay_registers __iomem *regs;
14676ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson
14686ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	if (!overlay || !overlay->active)
14696ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson		return NULL;
14706ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson
14716ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	error = kmalloc(sizeof(*error), GFP_ATOMIC);
14726ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	if (error == NULL)
14736ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson		return NULL;
14746ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson
14756ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	error->dovsta = I915_READ(DOVSTA);
14766ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	error->isr = I915_READ(ISR);
147731578148b2c62612f9516fdcf5ebb64ab32ed12dChris Wilson	if (OVERLAY_NEEDS_PHYSICAL(overlay->dev))
14786ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson		error->base = (long) overlay->reg_bo->phys_obj->handle->vaddr;
147931578148b2c62612f9516fdcf5ebb64ab32ed12dChris Wilson	else
148031578148b2c62612f9516fdcf5ebb64ab32ed12dChris Wilson		error->base = (long) overlay->reg_bo->gtt_offset;
14816ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson
14828d74f656dd78ae1ba813389cd46197c6329696bcChris Wilson	regs = intel_overlay_map_regs_atomic(overlay, KM_IRQ0);
14836ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	if (!regs)
14846ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson		goto err;
14856ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson
14866ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	memcpy_fromio(&error->regs, regs, sizeof(struct overlay_registers));
14879bb2ff731b32c023e7a502efdc0dee46157290d5Chris Wilson	intel_overlay_unmap_regs_atomic(overlay, KM_IRQ0, regs);
14886ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson
14896ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	return error;
14906ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson
14916ef3d4278034982c13df87c4a51e0445f762d316Chris Wilsonerr:
14926ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	kfree(error);
14936ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	return NULL;
14946ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson}
14956ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson
14966ef3d4278034982c13df87c4a51e0445f762d316Chris Wilsonvoid
14976ef3d4278034982c13df87c4a51e0445f762d316Chris Wilsonintel_overlay_print_error_state(struct seq_file *m, struct intel_overlay_error_state *error)
14986ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson{
14996ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	seq_printf(m, "Overlay, status: 0x%08x, interrupt: 0x%08x\n",
15006ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson		   error->dovsta, error->isr);
15016ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	seq_printf(m, "  Register file at 0x%08lx:\n",
15026ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson		   error->base);
15036ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson
15046ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson#define P(x) seq_printf(m, "    " #x ":	0x%08x\n", error->regs.x)
15056ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OBUF_0Y);
15066ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OBUF_1Y);
15076ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OBUF_0U);
15086ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OBUF_0V);
15096ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OBUF_1U);
15106ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OBUF_1V);
15116ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OSTRIDE);
15126ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(YRGB_VPH);
15136ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(UV_VPH);
15146ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(HORZ_PH);
15156ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(INIT_PHS);
15166ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(DWINPOS);
15176ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(DWINSZ);
15186ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(SWIDTH);
15196ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(SWIDTHSW);
15206ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(SHEIGHT);
15216ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(YRGBSCALE);
15226ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(UVSCALE);
15236ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OCLRC0);
15246ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OCLRC1);
15256ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(DCLRKV);
15266ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(DCLRKM);
15276ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(SCLRKVH);
15286ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(SCLRKVL);
15296ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(SCLRKEN);
15306ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OCONFIG);
15316ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OCMD);
15326ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OSTART_0Y);
15336ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OSTART_1Y);
15346ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OSTART_0U);
15356ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OSTART_0V);
15366ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OSTART_1U);
15376ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OSTART_1V);
15386ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OTILEOFF_0Y);
15396ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OTILEOFF_1Y);
15406ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OTILEOFF_0U);
15416ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OTILEOFF_0V);
15426ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OTILEOFF_1U);
15436ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OTILEOFF_1V);
15446ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(FASTHSCALE);
15456ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(UVSCALEV);
15466ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson#undef P
15476ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson}
1548