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 */
28760285e7e7ab282c25b5e90816f7c47000557f4fDavid Howells#include <drm/drmP.h>
29760285e7e7ab282c25b5e90816f7c47000557f4fDavid Howells#include <drm/i915_drm.h>
3002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#include "i915_drv.h"
3102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#include "i915_reg.h"
3202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#include "intel_drv.h"
3302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
3402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter/* Limits for overlay size. According to intel doc, the real limits are:
3502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter * Y width: 4095, UV width (planar): 2047, Y height: 2047,
3602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter * UV width (planar): * 1023. But the xorg thinks 2048 for height and width. Use
3702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter * the mininum of both.  */
3802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define IMAGE_MAX_WIDTH		2048
3902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define IMAGE_MAX_HEIGHT	2046 /* 2 * 1023 */
4002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter/* on 830 and 845 these large limits result in the card hanging */
4102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define IMAGE_MAX_WIDTH_LEGACY	1024
4202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define IMAGE_MAX_HEIGHT_LEGACY	1088
4302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
4402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter/* overlay register definitions */
4502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter/* OCMD register */
4602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_TILED_SURFACE	(0x1<<19)
4702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_MIRROR_MASK	(0x3<<17)
4802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_MIRROR_MODE	(0x3<<17)
4902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_MIRROR_HORIZONTAL	(0x1<<17)
5002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_MIRROR_VERTICAL	(0x2<<17)
5102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_MIRROR_BOTH	(0x3<<17)
5202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_BYTEORDER_MASK	(0x3<<14) /* zero for YUYV or FOURCC YUY2 */
5302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_UV_SWAP		(0x1<<14) /* YVYU */
5402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_Y_SWAP		(0x2<<14) /* UYVY or FOURCC UYVY */
5502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_Y_AND_UV_SWAP	(0x3<<14) /* VYUY */
5602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_SOURCE_FORMAT_MASK (0xf<<10)
5702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_RGB_888		(0x1<<10) /* not in i965 Intel docs */
5802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_RGB_555		(0x2<<10) /* not in i965 Intel docs */
5902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_RGB_565		(0x3<<10) /* not in i965 Intel docs */
6002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_YUV_422_PACKED	(0x8<<10)
6102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_YUV_411_PACKED	(0x9<<10) /* not in i965 Intel docs */
6202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_YUV_420_PLANAR	(0xc<<10)
6302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_YUV_422_PLANAR	(0xd<<10)
6402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_YUV_410_PLANAR	(0xe<<10) /* also 411 */
6502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_TVSYNCFLIP_PARITY	(0x1<<9)
6602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_TVSYNCFLIP_ENABLE	(0x1<<7)
67d79613643b4512962b2be5262a09b6694dd96101Chris Wilson#define OCMD_BUF_TYPE_MASK	(0x1<<5)
6802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_BUF_TYPE_FRAME	(0x0<<5)
6902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_BUF_TYPE_FIELD	(0x1<<5)
7002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_TEST_MODE		(0x1<<4)
7102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_BUFFER_SELECT	(0x3<<2)
7202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_BUFFER0		(0x0<<2)
7302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_BUFFER1		(0x1<<2)
7402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_FIELD_SELECT	(0x1<<2)
7502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_FIELD0		(0x0<<1)
7602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_FIELD1		(0x1<<1)
7702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_ENABLE		(0x1<<0)
7802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
7902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter/* OCONFIG register */
8002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCONF_PIPE_MASK		(0x1<<18)
8102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCONF_PIPE_A		(0x0<<18)
8202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCONF_PIPE_B		(0x1<<18)
8302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCONF_GAMMA2_ENABLE	(0x1<<16)
8402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCONF_CSC_MODE_BT601	(0x0<<5)
8502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCONF_CSC_MODE_BT709	(0x1<<5)
8602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCONF_CSC_BYPASS	(0x1<<4)
8702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCONF_CC_OUT_8BIT	(0x1<<3)
8802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCONF_TEST_MODE		(0x1<<2)
8902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCONF_THREE_LINE_BUFFER	(0x1<<0)
9002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCONF_TWO_LINE_BUFFER	(0x0<<0)
9102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
9202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter/* DCLRKM (dst-key) register */
9302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define DST_KEY_ENABLE		(0x1<<31)
9402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define CLK_RGB24_MASK		0x0
9502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define CLK_RGB16_MASK		0x070307
9602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define CLK_RGB15_MASK		0x070707
9702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define CLK_RGB8I_MASK		0xffffff
9802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
9902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define RGB16_TO_COLORKEY(c) \
10002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	(((c & 0xF800) << 8) | ((c & 0x07E0) << 5) | ((c & 0x001F) << 3))
10102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define RGB15_TO_COLORKEY(c) \
10202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	(((c & 0x7c00) << 9) | ((c & 0x03E0) << 6) | ((c & 0x001F) << 3))
10302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
10402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter/* overlay flip addr flag */
10502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OFC_UPDATE		0x1
10602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
10702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter/* polyphase filter coefficients */
10802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define N_HORIZ_Y_TAPS          5
10902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define N_VERT_Y_TAPS           3
11002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define N_HORIZ_UV_TAPS         3
11102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define N_VERT_UV_TAPS          3
11202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define N_PHASES                17
11302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define MAX_TAPS                5
11402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
11502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter/* memory bufferd overlay registers */
11602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstruct overlay_registers {
1170206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	u32 OBUF_0Y;
1180206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	u32 OBUF_1Y;
1190206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	u32 OBUF_0U;
1200206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	u32 OBUF_0V;
1210206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	u32 OBUF_1U;
1220206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	u32 OBUF_1V;
1230206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	u32 OSTRIDE;
1240206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	u32 YRGB_VPH;
1250206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	u32 UV_VPH;
1260206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	u32 HORZ_PH;
1270206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	u32 INIT_PHS;
1280206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	u32 DWINPOS;
1290206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	u32 DWINSZ;
1300206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	u32 SWIDTH;
1310206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	u32 SWIDTHSW;
1320206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	u32 SHEIGHT;
1330206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	u32 YRGBSCALE;
1340206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	u32 UVSCALE;
1350206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	u32 OCLRC0;
1360206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	u32 OCLRC1;
1370206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	u32 DCLRKV;
1380206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	u32 DCLRKM;
1390206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	u32 SCLRKVH;
1400206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	u32 SCLRKVL;
1410206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	u32 SCLRKEN;
1420206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	u32 OCONFIG;
1430206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	u32 OCMD;
1440206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	u32 RESERVED1; /* 0x6C */
1450206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	u32 OSTART_0Y;
1460206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	u32 OSTART_1Y;
1470206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	u32 OSTART_0U;
1480206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	u32 OSTART_0V;
1490206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	u32 OSTART_1U;
1500206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	u32 OSTART_1V;
1510206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	u32 OTILEOFF_0Y;
1520206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	u32 OTILEOFF_1Y;
1530206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	u32 OTILEOFF_0U;
1540206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	u32 OTILEOFF_0V;
1550206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	u32 OTILEOFF_1U;
1560206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	u32 OTILEOFF_1V;
1570206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	u32 FASTHSCALE; /* 0xA0 */
1580206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	u32 UVSCALEV; /* 0xA4 */
1590206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	u32 RESERVEDC[(0x200 - 0xA8) / 4]; /* 0xA8 - 0x1FC */
1600206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	u16 Y_VCOEFS[N_VERT_Y_TAPS * N_PHASES]; /* 0x200 */
1610206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	u16 RESERVEDD[0x100 / 2 - N_VERT_Y_TAPS * N_PHASES];
1620206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	u16 Y_HCOEFS[N_HORIZ_Y_TAPS * N_PHASES]; /* 0x300 */
1630206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	u16 RESERVEDE[0x200 / 2 - N_HORIZ_Y_TAPS * N_PHASES];
1640206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	u16 UV_VCOEFS[N_VERT_UV_TAPS * N_PHASES]; /* 0x500 */
1650206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	u16 RESERVEDF[0x100 / 2 - N_VERT_UV_TAPS * N_PHASES];
1660206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	u16 UV_HCOEFS[N_HORIZ_UV_TAPS * N_PHASES]; /* 0x600 */
1670206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	u16 RESERVEDG[0x100 / 2 - N_HORIZ_UV_TAPS * N_PHASES];
16802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter};
16902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
17023f09ce31ca68af3728ac5eed3e3efb03c5f990aChris Wilsonstruct intel_overlay {
17123f09ce31ca68af3728ac5eed3e3efb03c5f990aChris Wilson	struct drm_device *dev;
17223f09ce31ca68af3728ac5eed3e3efb03c5f990aChris Wilson	struct intel_crtc *crtc;
17323f09ce31ca68af3728ac5eed3e3efb03c5f990aChris Wilson	struct drm_i915_gem_object *vid_bo;
17423f09ce31ca68af3728ac5eed3e3efb03c5f990aChris Wilson	struct drm_i915_gem_object *old_vid_bo;
17523f09ce31ca68af3728ac5eed3e3efb03c5f990aChris Wilson	int active;
17623f09ce31ca68af3728ac5eed3e3efb03c5f990aChris Wilson	int pfit_active;
17723f09ce31ca68af3728ac5eed3e3efb03c5f990aChris Wilson	u32 pfit_vscale_ratio; /* shifted-point number, (1<<12) == 1.0 */
17823f09ce31ca68af3728ac5eed3e3efb03c5f990aChris Wilson	u32 color_key;
17923f09ce31ca68af3728ac5eed3e3efb03c5f990aChris Wilson	u32 brightness, contrast, saturation;
18023f09ce31ca68af3728ac5eed3e3efb03c5f990aChris Wilson	u32 old_xscale, old_yscale;
18123f09ce31ca68af3728ac5eed3e3efb03c5f990aChris Wilson	/* register access */
18223f09ce31ca68af3728ac5eed3e3efb03c5f990aChris Wilson	u32 flip_addr;
18323f09ce31ca68af3728ac5eed3e3efb03c5f990aChris Wilson	struct drm_i915_gem_object *reg_bo;
18423f09ce31ca68af3728ac5eed3e3efb03c5f990aChris Wilson	/* flip handling */
18523f09ce31ca68af3728ac5eed3e3efb03c5f990aChris Wilson	uint32_t last_flip_req;
186b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson	void (*flip_tail)(struct intel_overlay *);
18723f09ce31ca68af3728ac5eed3e3efb03c5f990aChris Wilson};
18802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
18975020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawskystatic struct overlay_registers __iomem *
1908d74f656dd78ae1ba813389cd46197c6329696bcChris Wilsonintel_overlay_map_regs(struct intel_overlay *overlay)
19102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
192d5d45cc5fe02d158e4ca8fc5a45e0614873bfeb3Jani Nikula	struct drm_i915_private *dev_priv = overlay->dev->dev_private;
19375020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawsky	struct overlay_registers __iomem *regs;
19402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
1959bb2ff731b32c023e7a502efdc0dee46157290d5Chris Wilson	if (OVERLAY_NEEDS_PHYSICAL(overlay->dev))
19600731155a73020c8e3c215723be193f96b4fcb1fChris Wilson		regs = (struct overlay_registers __iomem *)overlay->reg_bo->phys_handle->vaddr;
1979bb2ff731b32c023e7a502efdc0dee46157290d5Chris Wilson	else
1985d4545aef561ad47f91bcf75814af20c104b5a9eBen Widawsky		regs = io_mapping_map_wc(dev_priv->gtt.mappable,
199f343c5f6477354967ee1e331a68a56b9fece2f36Ben Widawsky					 i915_gem_obj_ggtt_offset(overlay->reg_bo));
20002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
2019bb2ff731b32c023e7a502efdc0dee46157290d5Chris Wilson	return regs;
2028d74f656dd78ae1ba813389cd46197c6329696bcChris Wilson}
20302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
2049bb2ff731b32c023e7a502efdc0dee46157290d5Chris Wilsonstatic void intel_overlay_unmap_regs(struct intel_overlay *overlay,
20575020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawsky				     struct overlay_registers __iomem *regs)
2068d74f656dd78ae1ba813389cd46197c6329696bcChris Wilson{
2078d74f656dd78ae1ba813389cd46197c6329696bcChris Wilson	if (!OVERLAY_NEEDS_PHYSICAL(overlay->dev))
2089bb2ff731b32c023e7a502efdc0dee46157290d5Chris Wilson		io_mapping_unmap(regs);
20902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
21002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
211b6c028e00445de9dfde2cd0c26521ac53965320aChris Wilsonstatic int intel_overlay_do_wait_request(struct intel_overlay *overlay,
212b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson					 void (*tail)(struct intel_overlay *))
21302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
21402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct drm_device *dev = overlay->dev;
215d5d45cc5fe02d158e4ca8fc5a45e0614873bfeb3Jani Nikula	struct drm_i915_private *dev_priv = dev->dev_private;
216a4872ba6d01454dfeb251d96f623ab5d1b0666a4Oscar Mateo	struct intel_engine_cs *ring = &dev_priv->ring[RCS];
217b6c028e00445de9dfde2cd0c26521ac53965320aChris Wilson	int ret;
21802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
219b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson	BUG_ON(overlay->last_flip_req);
2200025c0772de7451c2302fa628f038b213a0783bfMika Kuoppala	ret = i915_add_request(ring, &overlay->last_flip_req);
221acb868d3d710b09a356d848e0cd44d9713a9e274Chris Wilson	if (ret)
222acb868d3d710b09a356d848e0cd44d9713a9e274Chris Wilson		return ret;
223acb868d3d710b09a356d848e0cd44d9713a9e274Chris Wilson
224b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson	overlay->flip_tail = tail;
225199b2bc25ba587f666a712e9d8475d691d9cec4cBen Widawsky	ret = i915_wait_seqno(ring, overlay->last_flip_req);
226b6c028e00445de9dfde2cd0c26521ac53965320aChris Wilson	if (ret)
22703f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter		return ret;
228b2da9fe5d5994a104bbae154590070d698279919Ben Widawsky	i915_gem_retire_requests(dev);
22902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
23003f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	overlay->last_flip_req = 0;
23102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return 0;
23202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
23302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
23402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter/* overlay needs to be disable in OCMD reg */
23502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic int intel_overlay_on(struct intel_overlay *overlay)
23602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
23702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct drm_device *dev = overlay->dev;
238e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson	struct drm_i915_private *dev_priv = dev->dev_private;
239a4872ba6d01454dfeb251d96f623ab5d1b0666a4Oscar Mateo	struct intel_engine_cs *ring = &dev_priv->ring[RCS];
24002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int ret;
24102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
24202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	BUG_ON(overlay->active);
24303f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	overlay->active = 1;
244b6c028e00445de9dfde2cd0c26521ac53965320aChris Wilson
2456306cb4f809ccf92c1b7bf446635c571e33f5151Daniel Vetter	WARN_ON(IS_I830(dev) && !(dev_priv->quirks & QUIRK_PIPEA_FORCE));
246106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson
2476d90c952cdd20158ec41a5c016c6fad73c9a8749Daniel Vetter	ret = intel_ring_begin(ring, 4);
248acb868d3d710b09a356d848e0cd44d9713a9e274Chris Wilson	if (ret)
249acb868d3d710b09a356d848e0cd44d9713a9e274Chris Wilson		return ret;
250e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson
2516d90c952cdd20158ec41a5c016c6fad73c9a8749Daniel Vetter	intel_ring_emit(ring, MI_OVERLAY_FLIP | MI_OVERLAY_ON);
2526d90c952cdd20158ec41a5c016c6fad73c9a8749Daniel Vetter	intel_ring_emit(ring, overlay->flip_addr | OFC_UPDATE);
2536d90c952cdd20158ec41a5c016c6fad73c9a8749Daniel Vetter	intel_ring_emit(ring, MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
2546d90c952cdd20158ec41a5c016c6fad73c9a8749Daniel Vetter	intel_ring_emit(ring, MI_NOOP);
2556d90c952cdd20158ec41a5c016c6fad73c9a8749Daniel Vetter	intel_ring_advance(ring);
25602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
257acb868d3d710b09a356d848e0cd44d9713a9e274Chris Wilson	return intel_overlay_do_wait_request(overlay, NULL);
25802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
25902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
26002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter/* overlay needs to be enabled in OCMD reg */
2618dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilsonstatic int intel_overlay_continue(struct intel_overlay *overlay,
2628dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson				  bool load_polyphase_filter)
26302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
26402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct drm_device *dev = overlay->dev;
265d5d45cc5fe02d158e4ca8fc5a45e0614873bfeb3Jani Nikula	struct drm_i915_private *dev_priv = dev->dev_private;
266a4872ba6d01454dfeb251d96f623ab5d1b0666a4Oscar Mateo	struct intel_engine_cs *ring = &dev_priv->ring[RCS];
26702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	u32 flip_addr = overlay->flip_addr;
26802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	u32 tmp;
269e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson	int ret;
27002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
27102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	BUG_ON(!overlay->active);
27202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
27302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (load_polyphase_filter)
27402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		flip_addr |= OFC_UPDATE;
27502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
27602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* check for underruns */
27702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	tmp = I915_READ(DOVSTA);
27802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (tmp & (1 << 17))
27902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		DRM_DEBUG("overlay underrun, DOVSTA: %x\n", tmp);
28002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
2816d90c952cdd20158ec41a5c016c6fad73c9a8749Daniel Vetter	ret = intel_ring_begin(ring, 2);
282acb868d3d710b09a356d848e0cd44d9713a9e274Chris Wilson	if (ret)
283e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson		return ret;
284acb868d3d710b09a356d848e0cd44d9713a9e274Chris Wilson
2856d90c952cdd20158ec41a5c016c6fad73c9a8749Daniel Vetter	intel_ring_emit(ring, MI_OVERLAY_FLIP | MI_OVERLAY_CONTINUE);
2866d90c952cdd20158ec41a5c016c6fad73c9a8749Daniel Vetter	intel_ring_emit(ring, flip_addr);
2876d90c952cdd20158ec41a5c016c6fad73c9a8749Daniel Vetter	intel_ring_advance(ring);
2885a5a0c64a99d7542c48c99d1a8bbb49e665842beDaniel Vetter
2890025c0772de7451c2302fa628f038b213a0783bfMika Kuoppala	return i915_add_request(ring, &overlay->last_flip_req);
2905a5a0c64a99d7542c48c99d1a8bbb49e665842beDaniel Vetter}
2915a5a0c64a99d7542c48c99d1a8bbb49e665842beDaniel Vetter
292b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilsonstatic void intel_overlay_release_old_vid_tail(struct intel_overlay *overlay)
2935a5a0c64a99d7542c48c99d1a8bbb49e665842beDaniel Vetter{
29405394f3975dceb107a5e1393e2244946e5b43660Chris Wilson	struct drm_i915_gem_object *obj = overlay->old_vid_bo;
2955a5a0c64a99d7542c48c99d1a8bbb49e665842beDaniel Vetter
296d7f46fc4e7323887494db13f063a8e59861fefb0Ben Widawsky	i915_gem_object_ggtt_unpin(obj);
29705394f3975dceb107a5e1393e2244946e5b43660Chris Wilson	drm_gem_object_unreference(&obj->base);
2985a5a0c64a99d7542c48c99d1a8bbb49e665842beDaniel Vetter
299b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson	overlay->old_vid_bo = NULL;
300b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson}
30103f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter
302b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilsonstatic void intel_overlay_off_tail(struct intel_overlay *overlay)
303b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson{
30405394f3975dceb107a5e1393e2244946e5b43660Chris Wilson	struct drm_i915_gem_object *obj = overlay->vid_bo;
30502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
306b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson	/* never have the overlay hw on without showing a frame */
307b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson	BUG_ON(!overlay->vid_bo);
30802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
309d7f46fc4e7323887494db13f063a8e59861fefb0Ben Widawsky	i915_gem_object_ggtt_unpin(obj);
31005394f3975dceb107a5e1393e2244946e5b43660Chris Wilson	drm_gem_object_unreference(&obj->base);
311b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson	overlay->vid_bo = NULL;
31203f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter
313b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson	overlay->crtc->overlay = NULL;
314b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson	overlay->crtc = NULL;
315b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson	overlay->active = 0;
31602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
31702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
31802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter/* overlay needs to be disabled in OCMD reg */
319ce453d81cb0397aa7d5148984f51907e14072d74Chris Wilsonstatic int intel_overlay_off(struct intel_overlay *overlay)
32002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
32102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct drm_device *dev = overlay->dev;
322e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson	struct drm_i915_private *dev_priv = dev->dev_private;
323a4872ba6d01454dfeb251d96f623ab5d1b0666a4Oscar Mateo	struct intel_engine_cs *ring = &dev_priv->ring[RCS];
3248dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson	u32 flip_addr = overlay->flip_addr;
325e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson	int ret;
32602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
32702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	BUG_ON(!overlay->active);
32802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
32902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* According to intel docs the overlay hw may hang (when switching
33002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	 * off) without loading the filter coeffs. It is however unclear whether
33102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	 * this applies to the disabling of the overlay or to the switching off
33202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	 * of the hw. Do it in both cases */
33302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	flip_addr |= OFC_UPDATE;
33402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
3356d90c952cdd20158ec41a5c016c6fad73c9a8749Daniel Vetter	ret = intel_ring_begin(ring, 6);
336acb868d3d710b09a356d848e0cd44d9713a9e274Chris Wilson	if (ret)
337e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson		return ret;
338acb868d3d710b09a356d848e0cd44d9713a9e274Chris Wilson
33902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* wait for overlay to go idle */
3406d90c952cdd20158ec41a5c016c6fad73c9a8749Daniel Vetter	intel_ring_emit(ring, MI_OVERLAY_FLIP | MI_OVERLAY_CONTINUE);
3416d90c952cdd20158ec41a5c016c6fad73c9a8749Daniel Vetter	intel_ring_emit(ring, flip_addr);
3426d90c952cdd20158ec41a5c016c6fad73c9a8749Daniel Vetter	intel_ring_emit(ring, MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
34302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* turn overlay off */
344a9193983f4f292a82a00c72971c17ec0ee8c6c15Daniel Vetter	if (IS_I830(dev)) {
345a9193983f4f292a82a00c72971c17ec0ee8c6c15Daniel Vetter		/* Workaround: Don't disable the overlay fully, since otherwise
346a9193983f4f292a82a00c72971c17ec0ee8c6c15Daniel Vetter		 * it dies on the next OVERLAY_ON cmd. */
347a9193983f4f292a82a00c72971c17ec0ee8c6c15Daniel Vetter		intel_ring_emit(ring, MI_NOOP);
348a9193983f4f292a82a00c72971c17ec0ee8c6c15Daniel Vetter		intel_ring_emit(ring, MI_NOOP);
349a9193983f4f292a82a00c72971c17ec0ee8c6c15Daniel Vetter		intel_ring_emit(ring, MI_NOOP);
350a9193983f4f292a82a00c72971c17ec0ee8c6c15Daniel Vetter	} else {
351a9193983f4f292a82a00c72971c17ec0ee8c6c15Daniel Vetter		intel_ring_emit(ring, MI_OVERLAY_FLIP | MI_OVERLAY_OFF);
352a9193983f4f292a82a00c72971c17ec0ee8c6c15Daniel Vetter		intel_ring_emit(ring, flip_addr);
353a9193983f4f292a82a00c72971c17ec0ee8c6c15Daniel Vetter		intel_ring_emit(ring, MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
354a9193983f4f292a82a00c72971c17ec0ee8c6c15Daniel Vetter	}
3556d90c952cdd20158ec41a5c016c6fad73c9a8749Daniel Vetter	intel_ring_advance(ring);
35602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
357acb868d3d710b09a356d848e0cd44d9713a9e274Chris Wilson	return intel_overlay_do_wait_request(overlay, intel_overlay_off_tail);
35812ca45fea91cfbb09df828bea958b47348caee6dDaniel Vetter}
35912ca45fea91cfbb09df828bea958b47348caee6dDaniel Vetter
36003f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter/* recover from an interruption due to a signal
36103f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter * We have to be careful not to repeat work forever an make forward progess. */
362ce453d81cb0397aa7d5148984f51907e14072d74Chris Wilsonstatic int intel_overlay_recover_from_interrupt(struct intel_overlay *overlay)
36303f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter{
36403f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	struct drm_device *dev = overlay->dev;
365d5d45cc5fe02d158e4ca8fc5a45e0614873bfeb3Jani Nikula	struct drm_i915_private *dev_priv = dev->dev_private;
366a4872ba6d01454dfeb251d96f623ab5d1b0666a4Oscar Mateo	struct intel_engine_cs *ring = &dev_priv->ring[RCS];
36703f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	int ret;
36803f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter
369b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson	if (overlay->last_flip_req == 0)
370b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson		return 0;
37103f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter
372199b2bc25ba587f666a712e9d8475d691d9cec4cBen Widawsky	ret = i915_wait_seqno(ring, overlay->last_flip_req);
373b6c028e00445de9dfde2cd0c26521ac53965320aChris Wilson	if (ret)
37403f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter		return ret;
375b2da9fe5d5994a104bbae154590070d698279919Ben Widawsky	i915_gem_retire_requests(dev);
37603f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter
377b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson	if (overlay->flip_tail)
378b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson		overlay->flip_tail(overlay);
37903f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter
38003f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	overlay->last_flip_req = 0;
38103f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	return 0;
38203f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter}
38303f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter
3845a5a0c64a99d7542c48c99d1a8bbb49e665842beDaniel Vetter/* Wait for pending overlay flip and release old frame.
3855a5a0c64a99d7542c48c99d1a8bbb49e665842beDaniel Vetter * Needs to be called before the overlay register are changed
3868d74f656dd78ae1ba813389cd46197c6329696bcChris Wilson * via intel_overlay_(un)map_regs
3878d74f656dd78ae1ba813389cd46197c6329696bcChris Wilson */
38802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic int intel_overlay_release_old_vid(struct intel_overlay *overlay)
38902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
3905cd68c9864d65e49c910c701716e4e94e09f7ce0Chris Wilson	struct drm_device *dev = overlay->dev;
391d5d45cc5fe02d158e4ca8fc5a45e0614873bfeb3Jani Nikula	struct drm_i915_private *dev_priv = dev->dev_private;
392a4872ba6d01454dfeb251d96f623ab5d1b0666a4Oscar Mateo	struct intel_engine_cs *ring = &dev_priv->ring[RCS];
39302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int ret;
39402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
3955cd68c9864d65e49c910c701716e4e94e09f7ce0Chris Wilson	/* Only wait if there is actually an old frame to release to
3965cd68c9864d65e49c910c701716e4e94e09f7ce0Chris Wilson	 * guarantee forward progress.
3975cd68c9864d65e49c910c701716e4e94e09f7ce0Chris Wilson	 */
39803f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	if (!overlay->old_vid_bo)
39903f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter		return 0;
40003f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter
4015cd68c9864d65e49c910c701716e4e94e09f7ce0Chris Wilson	if (I915_READ(ISR) & I915_OVERLAY_PLANE_FLIP_PENDING_INTERRUPT) {
4025cd68c9864d65e49c910c701716e4e94e09f7ce0Chris Wilson		/* synchronous slowpath */
4036d90c952cdd20158ec41a5c016c6fad73c9a8749Daniel Vetter		ret = intel_ring_begin(ring, 2);
404acb868d3d710b09a356d848e0cd44d9713a9e274Chris Wilson		if (ret)
405e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson			return ret;
406e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson
4076d90c952cdd20158ec41a5c016c6fad73c9a8749Daniel Vetter		intel_ring_emit(ring, MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
4086d90c952cdd20158ec41a5c016c6fad73c9a8749Daniel Vetter		intel_ring_emit(ring, MI_NOOP);
4096d90c952cdd20158ec41a5c016c6fad73c9a8749Daniel Vetter		intel_ring_advance(ring);
4105cd68c9864d65e49c910c701716e4e94e09f7ce0Chris Wilson
411acb868d3d710b09a356d848e0cd44d9713a9e274Chris Wilson		ret = intel_overlay_do_wait_request(overlay,
412b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson						    intel_overlay_release_old_vid_tail);
4135cd68c9864d65e49c910c701716e4e94e09f7ce0Chris Wilson		if (ret)
4145cd68c9864d65e49c910c701716e4e94e09f7ce0Chris Wilson			return ret;
4155cd68c9864d65e49c910c701716e4e94e09f7ce0Chris Wilson	}
41602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
4175cd68c9864d65e49c910c701716e4e94e09f7ce0Chris Wilson	intel_overlay_release_old_vid_tail(overlay);
418a071fa00647bc9a3c53f917b236fff9aea175e3aDaniel Vetter
419a071fa00647bc9a3c53f917b236fff9aea175e3aDaniel Vetter
420a071fa00647bc9a3c53f917b236fff9aea175e3aDaniel Vetter	i915_gem_track_fb(overlay->old_vid_bo, NULL,
421a071fa00647bc9a3c53f917b236fff9aea175e3aDaniel Vetter			  INTEL_FRONTBUFFER_OVERLAY(overlay->crtc->pipe));
42202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return 0;
42302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
42402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
42502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstruct put_image_params {
42602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int format;
42702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	short dst_x;
42802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	short dst_y;
42902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	short dst_w;
43002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	short dst_h;
43102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	short src_w;
43202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	short src_scan_h;
43302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	short src_scan_w;
43402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	short src_h;
43502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	short stride_Y;
43602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	short stride_UV;
43702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int offset_Y;
43802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int offset_U;
43902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int offset_V;
44002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter};
44102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
44202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic int packed_depth_bytes(u32 format)
44302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
44402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	switch (format & I915_OVERLAY_DEPTH_MASK) {
445722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case I915_OVERLAY_YUV422:
446722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		return 4;
447722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case I915_OVERLAY_YUV411:
448722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		/* return 6; not implemented */
449722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	default:
450722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		return -EINVAL;
45102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
45202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
45302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
45402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic int packed_width_bytes(u32 format, short width)
45502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
45602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	switch (format & I915_OVERLAY_DEPTH_MASK) {
457722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case I915_OVERLAY_YUV422:
458722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		return width << 1;
459722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	default:
460722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		return -EINVAL;
46102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
46202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
46302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
46402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic int uv_hsubsampling(u32 format)
46502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
46602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	switch (format & I915_OVERLAY_DEPTH_MASK) {
467722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case I915_OVERLAY_YUV422:
468722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case I915_OVERLAY_YUV420:
469722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		return 2;
470722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case I915_OVERLAY_YUV411:
471722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case I915_OVERLAY_YUV410:
472722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		return 4;
473722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	default:
474722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		return -EINVAL;
47502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
47602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
47702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
47802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic int uv_vsubsampling(u32 format)
47902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
48002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	switch (format & I915_OVERLAY_DEPTH_MASK) {
481722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case I915_OVERLAY_YUV420:
482722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case I915_OVERLAY_YUV410:
483722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		return 2;
484722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case I915_OVERLAY_YUV422:
485722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case I915_OVERLAY_YUV411:
486722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		return 1;
487722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	default:
488722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		return -EINVAL;
48902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
49002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
49102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
49202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic u32 calc_swidthsw(struct drm_device *dev, u32 offset, u32 width)
49302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
49402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	u32 mask, shift, ret;
495a6c45cf013a57e32ddae43dd4ac911eb4a3919fdChris Wilson	if (IS_GEN2(dev)) {
49602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		mask = 0x1f;
49702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		shift = 5;
498a6c45cf013a57e32ddae43dd4ac911eb4a3919fdChris Wilson	} else {
499a6c45cf013a57e32ddae43dd4ac911eb4a3919fdChris Wilson		mask = 0x3f;
500a6c45cf013a57e32ddae43dd4ac911eb4a3919fdChris Wilson		shift = 6;
50102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
50202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	ret = ((offset + width + mask) >> shift) - (offset >> shift);
503a6c45cf013a57e32ddae43dd4ac911eb4a3919fdChris Wilson	if (!IS_GEN2(dev))
50402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		ret <<= 1;
5050206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	ret -= 1;
50602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return ret << 2;
50702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
50802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
50902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic const u16 y_static_hcoeffs[N_HORIZ_Y_TAPS * N_PHASES] = {
51002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3000, 0xb4a0, 0x1930, 0x1920, 0xb4a0,
51102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3000, 0xb500, 0x19d0, 0x1880, 0xb440,
51202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3000, 0xb540, 0x1a88, 0x2f80, 0xb3e0,
51302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3000, 0xb580, 0x1b30, 0x2e20, 0xb380,
51402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3000, 0xb5c0, 0x1bd8, 0x2cc0, 0xb320,
51502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3020, 0xb5e0, 0x1c60, 0x2b80, 0xb2c0,
51602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3020, 0xb5e0, 0x1cf8, 0x2a20, 0xb260,
51702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3020, 0xb5e0, 0x1d80, 0x28e0, 0xb200,
51802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3020, 0xb5c0, 0x1e08, 0x3f40, 0xb1c0,
51902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3020, 0xb580, 0x1e78, 0x3ce0, 0xb160,
52002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3040, 0xb520, 0x1ed8, 0x3aa0, 0xb120,
52102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3040, 0xb4a0, 0x1f30, 0x3880, 0xb0e0,
52202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3040, 0xb400, 0x1f78, 0x3680, 0xb0a0,
52302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3020, 0xb340, 0x1fb8, 0x34a0, 0xb060,
52402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3020, 0xb240, 0x1fe0, 0x32e0, 0xb040,
52502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3020, 0xb140, 0x1ff8, 0x3160, 0xb020,
526722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	0xb000, 0x3000, 0x0800, 0x3000, 0xb000
527722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson};
528722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson
52902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic const u16 uv_static_hcoeffs[N_HORIZ_UV_TAPS * N_PHASES] = {
53002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3000, 0x1800, 0x1800, 0xb000, 0x18d0, 0x2e60,
53102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0xb000, 0x1990, 0x2ce0, 0xb020, 0x1a68, 0x2b40,
53202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0xb040, 0x1b20, 0x29e0, 0xb060, 0x1bd8, 0x2880,
53302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0xb080, 0x1c88, 0x3e60, 0xb0a0, 0x1d28, 0x3c00,
53402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0xb0c0, 0x1db8, 0x39e0, 0xb0e0, 0x1e40, 0x37e0,
53502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0xb100, 0x1eb8, 0x3620, 0xb100, 0x1f18, 0x34a0,
53602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0xb100, 0x1f68, 0x3360, 0xb0e0, 0x1fa8, 0x3240,
53702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0xb0c0, 0x1fe0, 0x3140, 0xb060, 0x1ff0, 0x30a0,
538722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	0x3000, 0x0800, 0x3000
539722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson};
54002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
54175020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawskystatic void update_polyphase_filter(struct overlay_registers __iomem *regs)
54202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
54375020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawsky	memcpy_toio(regs->Y_HCOEFS, y_static_hcoeffs, sizeof(y_static_hcoeffs));
54475020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawsky	memcpy_toio(regs->UV_HCOEFS, uv_static_hcoeffs,
54575020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawsky		    sizeof(uv_static_hcoeffs));
54602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
54702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
54802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic bool update_scaling_factors(struct intel_overlay *overlay,
54975020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawsky				   struct overlay_registers __iomem *regs,
55002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				   struct put_image_params *params)
55102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
55202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* fixed point with a 12 bit shift */
55302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	u32 xscale, yscale, xscale_UV, yscale_UV;
55402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define FP_SHIFT 12
55502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define FRACT_MASK 0xfff
55602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	bool scale_changed = false;
55702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int uv_hscale = uv_hsubsampling(params->format);
55802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int uv_vscale = uv_vsubsampling(params->format);
55902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
56002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (params->dst_w > 1)
56102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		xscale = ((params->src_scan_w - 1) << FP_SHIFT)
56202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			/(params->dst_w);
56302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	else
56402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		xscale = 1 << FP_SHIFT;
56502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
56602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (params->dst_h > 1)
56702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		yscale = ((params->src_scan_h - 1) << FP_SHIFT)
56802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			/(params->dst_h);
56902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	else
57002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		yscale = 1 << FP_SHIFT;
57102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
57202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/*if (params->format & I915_OVERLAY_YUV_PLANAR) {*/
573722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	xscale_UV = xscale/uv_hscale;
574722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	yscale_UV = yscale/uv_vscale;
575722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	/* make the Y scale to UV scale ratio an exact multiply */
576722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	xscale = xscale_UV * uv_hscale;
577722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	yscale = yscale_UV * uv_vscale;
57802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/*} else {
579722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	  xscale_UV = 0;
580722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	  yscale_UV = 0;
581722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	  }*/
58202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
58302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (xscale != overlay->old_xscale || yscale != overlay->old_yscale)
58402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		scale_changed = true;
58502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	overlay->old_xscale = xscale;
58602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	overlay->old_yscale = yscale;
58702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
58875020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawsky	iowrite32(((yscale & FRACT_MASK) << 20) |
58975020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawsky		  ((xscale >> FP_SHIFT)  << 16) |
59075020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawsky		  ((xscale & FRACT_MASK) << 3),
59175020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawsky		 &regs->YRGBSCALE);
592722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson
59375020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawsky	iowrite32(((yscale_UV & FRACT_MASK) << 20) |
59475020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawsky		  ((xscale_UV >> FP_SHIFT)  << 16) |
59575020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawsky		  ((xscale_UV & FRACT_MASK) << 3),
59675020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawsky		 &regs->UVSCALE);
597722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson
59875020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawsky	iowrite32((((yscale    >> FP_SHIFT) << 16) |
59975020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawsky		   ((yscale_UV >> FP_SHIFT) << 0)),
60075020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawsky		 &regs->UVSCALEV);
60102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
60202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (scale_changed)
60302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		update_polyphase_filter(regs);
60402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
60502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return scale_changed;
60602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
60702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
60802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic void update_colorkey(struct intel_overlay *overlay,
60975020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawsky			    struct overlay_registers __iomem *regs)
61002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
61102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	u32 key = overlay->color_key;
6126ba3ddd9838f5e4d6ac7c6dce95648d205e11bffChris Wilson
613f4510a2752b75ad5847b7935b68c233cab497f97Matt Roper	switch (overlay->crtc->base.primary->fb->bits_per_pixel) {
614722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case 8:
61575020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawsky		iowrite32(0, &regs->DCLRKV);
61675020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawsky		iowrite32(CLK_RGB8I_MASK | DST_KEY_ENABLE, &regs->DCLRKM);
6176ba3ddd9838f5e4d6ac7c6dce95648d205e11bffChris Wilson		break;
6186ba3ddd9838f5e4d6ac7c6dce95648d205e11bffChris Wilson
619722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case 16:
620f4510a2752b75ad5847b7935b68c233cab497f97Matt Roper		if (overlay->crtc->base.primary->fb->depth == 15) {
62175020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawsky			iowrite32(RGB15_TO_COLORKEY(key), &regs->DCLRKV);
62275020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawsky			iowrite32(CLK_RGB15_MASK | DST_KEY_ENABLE,
62375020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawsky				  &regs->DCLRKM);
624722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		} else {
62575020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawsky			iowrite32(RGB16_TO_COLORKEY(key), &regs->DCLRKV);
62675020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawsky			iowrite32(CLK_RGB16_MASK | DST_KEY_ENABLE,
62775020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawsky				  &regs->DCLRKM);
628722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		}
6296ba3ddd9838f5e4d6ac7c6dce95648d205e11bffChris Wilson		break;
6306ba3ddd9838f5e4d6ac7c6dce95648d205e11bffChris Wilson
631722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case 24:
632722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case 32:
63375020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawsky		iowrite32(key, &regs->DCLRKV);
63475020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawsky		iowrite32(CLK_RGB24_MASK | DST_KEY_ENABLE, &regs->DCLRKM);
6356ba3ddd9838f5e4d6ac7c6dce95648d205e11bffChris Wilson		break;
63602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
63702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
63802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
63902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic u32 overlay_cmd_reg(struct put_image_params *params)
64002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
64102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	u32 cmd = OCMD_ENABLE | OCMD_BUF_TYPE_FRAME | OCMD_BUFFER0;
64202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
64302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (params->format & I915_OVERLAY_YUV_PLANAR) {
64402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		switch (params->format & I915_OVERLAY_DEPTH_MASK) {
645722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		case I915_OVERLAY_YUV422:
646722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			cmd |= OCMD_YUV_422_PLANAR;
647722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			break;
648722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		case I915_OVERLAY_YUV420:
649722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			cmd |= OCMD_YUV_420_PLANAR;
650722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			break;
651722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		case I915_OVERLAY_YUV411:
652722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		case I915_OVERLAY_YUV410:
653722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			cmd |= OCMD_YUV_410_PLANAR;
654722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			break;
65502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		}
65602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	} else { /* YUV packed */
65702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		switch (params->format & I915_OVERLAY_DEPTH_MASK) {
658722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		case I915_OVERLAY_YUV422:
659722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			cmd |= OCMD_YUV_422_PACKED;
660722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			break;
661722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		case I915_OVERLAY_YUV411:
662722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			cmd |= OCMD_YUV_411_PACKED;
663722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			break;
66402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		}
66502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
66602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		switch (params->format & I915_OVERLAY_SWAP_MASK) {
667722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		case I915_OVERLAY_NO_SWAP:
668722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			break;
669722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		case I915_OVERLAY_UV_SWAP:
670722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			cmd |= OCMD_UV_SWAP;
671722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			break;
672722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		case I915_OVERLAY_Y_SWAP:
673722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			cmd |= OCMD_Y_SWAP;
674722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			break;
675722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		case I915_OVERLAY_Y_AND_UV_SWAP:
676722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			cmd |= OCMD_Y_AND_UV_SWAP;
677722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			break;
67802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		}
67902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
68002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
68102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return cmd;
68202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
68302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
6845fe82c5ee1ba2d04183c376038c5d233a0311ec9Chris Wilsonstatic int intel_overlay_do_put_image(struct intel_overlay *overlay,
68505394f3975dceb107a5e1393e2244946e5b43660Chris Wilson				      struct drm_i915_gem_object *new_bo,
6865fe82c5ee1ba2d04183c376038c5d233a0311ec9Chris Wilson				      struct put_image_params *params)
68702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
68802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int ret, tmp_width;
68975020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawsky	struct overlay_registers __iomem *regs;
69002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	bool scale_changed = false;
69102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct drm_device *dev = overlay->dev;
69275020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawsky	u32 swidth, swidthsw, sheight, ostride;
693a071fa00647bc9a3c53f917b236fff9aea175e3aDaniel Vetter	enum pipe pipe = overlay->crtc->pipe;
69402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
69502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	BUG_ON(!mutex_is_locked(&dev->struct_mutex));
69651fd371bbaf94018a1223b4e2cf20b9880fd92d4Rob Clark	BUG_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex));
69702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	BUG_ON(!overlay);
69802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
69902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	ret = intel_overlay_release_old_vid(overlay);
70002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (ret != 0)
70102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return ret;
70202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
7032da3b9b940e2a18147422c54ed8b29d01e1ade88Chris Wilson	ret = i915_gem_object_pin_to_display_plane(new_bo, 0, NULL);
70402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (ret != 0)
70502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return ret;
70602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
707d9e86c0ee60f323e890484628f351bf50fa9a15dChris Wilson	ret = i915_gem_object_put_fence(new_bo);
708d9e86c0ee60f323e890484628f351bf50fa9a15dChris Wilson	if (ret)
709d9e86c0ee60f323e890484628f351bf50fa9a15dChris Wilson		goto out_unpin;
710d9e86c0ee60f323e890484628f351bf50fa9a15dChris Wilson
71102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!overlay->active) {
71275020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawsky		u32 oconfig;
7138d74f656dd78ae1ba813389cd46197c6329696bcChris Wilson		regs = intel_overlay_map_regs(overlay);
71402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		if (!regs) {
71502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			ret = -ENOMEM;
71602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			goto out_unpin;
71702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		}
71875020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawsky		oconfig = OCONF_CC_OUT_8BIT;
719a6c45cf013a57e32ddae43dd4ac911eb4a3919fdChris Wilson		if (IS_GEN4(overlay->dev))
72075020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawsky			oconfig |= OCONF_CSC_MODE_BT709;
721a071fa00647bc9a3c53f917b236fff9aea175e3aDaniel Vetter		oconfig |= pipe == 0 ?
72202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			OCONF_PIPE_A : OCONF_PIPE_B;
72375020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawsky		iowrite32(oconfig, &regs->OCONFIG);
7249bb2ff731b32c023e7a502efdc0dee46157290d5Chris Wilson		intel_overlay_unmap_regs(overlay, regs);
72502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
72602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		ret = intel_overlay_on(overlay);
72702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		if (ret != 0)
72802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			goto out_unpin;
72902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
73002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
7318d74f656dd78ae1ba813389cd46197c6329696bcChris Wilson	regs = intel_overlay_map_regs(overlay);
73202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!regs) {
73302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		ret = -ENOMEM;
73402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		goto out_unpin;
73502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
73602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
73775020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawsky	iowrite32((params->dst_y << 16) | params->dst_x, &regs->DWINPOS);
73875020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawsky	iowrite32((params->dst_h << 16) | params->dst_w, &regs->DWINSZ);
73902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
74002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (params->format & I915_OVERLAY_YUV_PACKED)
74102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		tmp_width = packed_width_bytes(params->format, params->src_w);
74202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	else
74302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		tmp_width = params->src_w;
74402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
74575020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawsky	swidth = params->src_w;
74675020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawsky	swidthsw = calc_swidthsw(overlay->dev, params->offset_Y, tmp_width);
74775020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawsky	sheight = params->src_h;
748f343c5f6477354967ee1e331a68a56b9fece2f36Ben Widawsky	iowrite32(i915_gem_obj_ggtt_offset(new_bo) + params->offset_Y, &regs->OBUF_0Y);
74975020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawsky	ostride = params->stride_Y;
75002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
75102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (params->format & I915_OVERLAY_YUV_PLANAR) {
75202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		int uv_hscale = uv_hsubsampling(params->format);
75302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		int uv_vscale = uv_vsubsampling(params->format);
75402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		u32 tmp_U, tmp_V;
75575020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawsky		swidth |= (params->src_w/uv_hscale) << 16;
75602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		tmp_U = calc_swidthsw(overlay->dev, params->offset_U,
757722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson				      params->src_w/uv_hscale);
75802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		tmp_V = calc_swidthsw(overlay->dev, params->offset_V,
759722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson				      params->src_w/uv_hscale);
76075020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawsky		swidthsw |= max_t(u32, tmp_U, tmp_V) << 16;
76175020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawsky		sheight |= (params->src_h/uv_vscale) << 16;
762f343c5f6477354967ee1e331a68a56b9fece2f36Ben Widawsky		iowrite32(i915_gem_obj_ggtt_offset(new_bo) + params->offset_U, &regs->OBUF_0U);
763f343c5f6477354967ee1e331a68a56b9fece2f36Ben Widawsky		iowrite32(i915_gem_obj_ggtt_offset(new_bo) + params->offset_V, &regs->OBUF_0V);
76475020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawsky		ostride |= params->stride_UV << 16;
76502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
76602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
76775020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawsky	iowrite32(swidth, &regs->SWIDTH);
76875020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawsky	iowrite32(swidthsw, &regs->SWIDTHSW);
76975020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawsky	iowrite32(sheight, &regs->SHEIGHT);
77075020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawsky	iowrite32(ostride, &regs->OSTRIDE);
77175020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawsky
77202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	scale_changed = update_scaling_factors(overlay, regs, params);
77302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
77402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	update_colorkey(overlay, regs);
77502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
77675020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawsky	iowrite32(overlay_cmd_reg(params), &regs->OCMD);
77702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
7789bb2ff731b32c023e7a502efdc0dee46157290d5Chris Wilson	intel_overlay_unmap_regs(overlay, regs);
77902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
7808dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson	ret = intel_overlay_continue(overlay, scale_changed);
7818dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson	if (ret)
7828dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson		goto out_unpin;
78302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
784a071fa00647bc9a3c53f917b236fff9aea175e3aDaniel Vetter	i915_gem_track_fb(overlay->vid_bo, new_bo,
785a071fa00647bc9a3c53f917b236fff9aea175e3aDaniel Vetter			  INTEL_FRONTBUFFER_OVERLAY(pipe));
786a071fa00647bc9a3c53f917b236fff9aea175e3aDaniel Vetter
78702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	overlay->old_vid_bo = overlay->vid_bo;
78805394f3975dceb107a5e1393e2244946e5b43660Chris Wilson	overlay->vid_bo = new_bo;
78902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
790f99d70690e0755696e4e68404c8993431efda469Daniel Vetter	intel_frontbuffer_flip(dev,
791f99d70690e0755696e4e68404c8993431efda469Daniel Vetter			       INTEL_FRONTBUFFER_OVERLAY(pipe));
792f99d70690e0755696e4e68404c8993431efda469Daniel Vetter
79302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return 0;
79402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
79502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterout_unpin:
796d7f46fc4e7323887494db13f063a8e59861fefb0Ben Widawsky	i915_gem_object_ggtt_unpin(new_bo);
79702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return ret;
79802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
79902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
800ce453d81cb0397aa7d5148984f51907e14072d74Chris Wilsonint intel_overlay_switch_off(struct intel_overlay *overlay)
80102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
80275020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawsky	struct overlay_registers __iomem *regs;
80302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct drm_device *dev = overlay->dev;
8045dcdbcb06badbdf2faa698bf3198e421a1e12840Chris Wilson	int ret;
80502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
80602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	BUG_ON(!mutex_is_locked(&dev->struct_mutex));
80751fd371bbaf94018a1223b4e2cf20b9880fd92d4Rob Clark	BUG_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex));
80802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
809ce453d81cb0397aa7d5148984f51907e14072d74Chris Wilson	ret = intel_overlay_recover_from_interrupt(overlay);
810b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson	if (ret != 0)
811b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson		return ret;
8129bedb9743fd906e4160468663ee6e1bbdc4412b8Daniel Vetter
81302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!overlay->active)
81402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return 0;
81502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
81602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	ret = intel_overlay_release_old_vid(overlay);
81702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (ret != 0)
81802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return ret;
81902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
8208d74f656dd78ae1ba813389cd46197c6329696bcChris Wilson	regs = intel_overlay_map_regs(overlay);
82175020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawsky	iowrite32(0, &regs->OCMD);
8229bb2ff731b32c023e7a502efdc0dee46157290d5Chris Wilson	intel_overlay_unmap_regs(overlay, regs);
82302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
824ce453d81cb0397aa7d5148984f51907e14072d74Chris Wilson	ret = intel_overlay_off(overlay);
82503f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	if (ret != 0)
82603f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter		return ret;
82703f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter
82812ca45fea91cfbb09df828bea958b47348caee6dDaniel Vetter	intel_overlay_off_tail(overlay);
82902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return 0;
83002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
83102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
83202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic int check_overlay_possible_on_crtc(struct intel_overlay *overlay,
83302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter					  struct intel_crtc *crtc)
83402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
835f7abfe8b281991c66406c42c1a6c6c9ee0daa0ffChris Wilson	if (!crtc->active)
83602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EINVAL;
83702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
83802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* can't use the overlay with double wide pipe */
8394926cb76bd8c4fb18066862bf9e00c840db4b3d8Ville Syrjälä	if (crtc->config.double_wide)
84002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EINVAL;
84102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
84202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return 0;
84302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
84402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
84502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic void update_pfit_vscale_ratio(struct intel_overlay *overlay)
84602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
84702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct drm_device *dev = overlay->dev;
848d5d45cc5fe02d158e4ca8fc5a45e0614873bfeb3Jani Nikula	struct drm_i915_private *dev_priv = dev->dev_private;
84902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	u32 pfit_control = I915_READ(PFIT_CONTROL);
850446d2183af68c0fd2772f5ef97a033efe69904a5Chris Wilson	u32 ratio;
85102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
85202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* XXX: This is not the same logic as in the xorg driver, but more in
853446d2183af68c0fd2772f5ef97a033efe69904a5Chris Wilson	 * line with the intel documentation for the i965
854446d2183af68c0fd2772f5ef97a033efe69904a5Chris Wilson	 */
855a6c45cf013a57e32ddae43dd4ac911eb4a3919fdChris Wilson	if (INTEL_INFO(dev)->gen >= 4) {
8560206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi		/* on i965 use the PGM reg to read out the autoscaler values */
857a6c45cf013a57e32ddae43dd4ac911eb4a3919fdChris Wilson		ratio = I915_READ(PFIT_PGM_RATIOS) >> PFIT_VERT_SCALE_SHIFT_965;
858a6c45cf013a57e32ddae43dd4ac911eb4a3919fdChris Wilson	} else {
859446d2183af68c0fd2772f5ef97a033efe69904a5Chris Wilson		if (pfit_control & VERT_AUTO_SCALE)
860446d2183af68c0fd2772f5ef97a033efe69904a5Chris Wilson			ratio = I915_READ(PFIT_AUTO_RATIOS);
86102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		else
862446d2183af68c0fd2772f5ef97a033efe69904a5Chris Wilson			ratio = I915_READ(PFIT_PGM_RATIOS);
863446d2183af68c0fd2772f5ef97a033efe69904a5Chris Wilson		ratio >>= PFIT_VERT_SCALE_SHIFT;
86402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
86502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
86602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	overlay->pfit_vscale_ratio = ratio;
86702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
86802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
86902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic int check_overlay_dst(struct intel_overlay *overlay,
87002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			     struct drm_intel_overlay_put_image *rec)
87102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
87202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct drm_display_mode *mode = &overlay->crtc->base.mode;
87302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
87475c13993db592343bda1fd62f2555fea037d56bdDaniel Vetter	if (rec->dst_x < mode->hdisplay &&
87575c13993db592343bda1fd62f2555fea037d56bdDaniel Vetter	    rec->dst_x + rec->dst_width <= mode->hdisplay &&
87675c13993db592343bda1fd62f2555fea037d56bdDaniel Vetter	    rec->dst_y < mode->vdisplay &&
87775c13993db592343bda1fd62f2555fea037d56bdDaniel Vetter	    rec->dst_y + rec->dst_height <= mode->vdisplay)
87802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return 0;
87902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	else
88002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EINVAL;
88102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
88202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
88302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic int check_overlay_scaling(struct put_image_params *rec)
88402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
88502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	u32 tmp;
88602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
88702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* downscaling limit is 8.0 */
88802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	tmp = ((rec->src_scan_h << 16) / rec->dst_h) >> 16;
88902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (tmp > 7)
89002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EINVAL;
89102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	tmp = ((rec->src_scan_w << 16) / rec->dst_w) >> 16;
89202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (tmp > 7)
89302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EINVAL;
89402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
89502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return 0;
89602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
89702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
89802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic int check_overlay_src(struct drm_device *dev,
89902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			     struct drm_intel_overlay_put_image *rec,
90005394f3975dceb107a5e1393e2244946e5b43660Chris Wilson			     struct drm_i915_gem_object *new_bo)
90102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
90202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int uv_hscale = uv_hsubsampling(rec->flags);
90302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int uv_vscale = uv_vsubsampling(rec->flags);
9048f28f54aad8bcf52a47afb6447fac34f96597b6fDan Carpenter	u32 stride_mask;
9058f28f54aad8bcf52a47afb6447fac34f96597b6fDan Carpenter	int depth;
9068f28f54aad8bcf52a47afb6447fac34f96597b6fDan Carpenter	u32 tmp;
90702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
90802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* check src dimensions */
90902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (IS_845G(dev) || IS_I830(dev)) {
910722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		if (rec->src_height > IMAGE_MAX_HEIGHT_LEGACY ||
9119f7c3f442bb7c0d0a0ed25cc287932450a1f2babChris Wilson		    rec->src_width  > IMAGE_MAX_WIDTH_LEGACY)
91202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			return -EINVAL;
91302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	} else {
914722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		if (rec->src_height > IMAGE_MAX_HEIGHT ||
9159f7c3f442bb7c0d0a0ed25cc287932450a1f2babChris Wilson		    rec->src_width  > IMAGE_MAX_WIDTH)
91602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			return -EINVAL;
91702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
9189f7c3f442bb7c0d0a0ed25cc287932450a1f2babChris Wilson
91902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* better safe than sorry, use 4 as the maximal subsampling ratio */
920722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	if (rec->src_height < N_VERT_Y_TAPS*4 ||
9219f7c3f442bb7c0d0a0ed25cc287932450a1f2babChris Wilson	    rec->src_width  < N_HORIZ_Y_TAPS*4)
92202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EINVAL;
92302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
924a1efd14a99483a4fb9308902397ed86b69454c99Chris Wilson	/* check alignment constraints */
92502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	switch (rec->flags & I915_OVERLAY_TYPE_MASK) {
926722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case I915_OVERLAY_RGB:
927722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		/* not implemented */
928722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		return -EINVAL;
9299f7c3f442bb7c0d0a0ed25cc287932450a1f2babChris Wilson
930722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case I915_OVERLAY_YUV_PACKED:
931722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		if (uv_vscale != 1)
93202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			return -EINVAL;
9339f7c3f442bb7c0d0a0ed25cc287932450a1f2babChris Wilson
9349f7c3f442bb7c0d0a0ed25cc287932450a1f2babChris Wilson		depth = packed_depth_bytes(rec->flags);
935722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		if (depth < 0)
936722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			return depth;
9379f7c3f442bb7c0d0a0ed25cc287932450a1f2babChris Wilson
938722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		/* ignore UV planes */
939722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		rec->stride_UV = 0;
940722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		rec->offset_U = 0;
941722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		rec->offset_V = 0;
942722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		/* check pixel alignment */
943722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		if (rec->offset_Y % depth)
944722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			return -EINVAL;
945722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		break;
9469f7c3f442bb7c0d0a0ed25cc287932450a1f2babChris Wilson
947722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case I915_OVERLAY_YUV_PLANAR:
948722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		if (uv_vscale < 0 || uv_hscale < 0)
94902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			return -EINVAL;
950722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		/* no offset restrictions for planar formats */
951722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		break;
9529f7c3f442bb7c0d0a0ed25cc287932450a1f2babChris Wilson
953722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	default:
954722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		return -EINVAL;
95502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
95602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
95702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (rec->src_width % uv_hscale)
95802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EINVAL;
95902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
96002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* stride checking */
961a1efd14a99483a4fb9308902397ed86b69454c99Chris Wilson	if (IS_I830(dev) || IS_845G(dev))
962a1efd14a99483a4fb9308902397ed86b69454c99Chris Wilson		stride_mask = 255;
963a1efd14a99483a4fb9308902397ed86b69454c99Chris Wilson	else
964a1efd14a99483a4fb9308902397ed86b69454c99Chris Wilson		stride_mask = 63;
96502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
96602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (rec->stride_Y & stride_mask || rec->stride_UV & stride_mask)
96702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EINVAL;
968a6c45cf013a57e32ddae43dd4ac911eb4a3919fdChris Wilson	if (IS_GEN4(dev) && rec->stride_Y < 512)
96902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EINVAL;
97002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
97102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	tmp = (rec->flags & I915_OVERLAY_TYPE_MASK) == I915_OVERLAY_YUV_PLANAR ?
9729f7c3f442bb7c0d0a0ed25cc287932450a1f2babChris Wilson		4096 : 8192;
9739f7c3f442bb7c0d0a0ed25cc287932450a1f2babChris Wilson	if (rec->stride_Y > tmp || rec->stride_UV > 2*1024)
97402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EINVAL;
97502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
97602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* check buffer dimensions */
97702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	switch (rec->flags & I915_OVERLAY_TYPE_MASK) {
978722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case I915_OVERLAY_RGB:
979722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case I915_OVERLAY_YUV_PACKED:
980722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		/* always 4 Y values per depth pixels */
981722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		if (packed_width_bytes(rec->flags, rec->src_width) > rec->stride_Y)
982722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			return -EINVAL;
983722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson
984722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		tmp = rec->stride_Y*rec->src_height;
98505394f3975dceb107a5e1393e2244946e5b43660Chris Wilson		if (rec->offset_Y + tmp > new_bo->base.size)
986722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			return -EINVAL;
987722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		break;
988722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson
989722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case I915_OVERLAY_YUV_PLANAR:
990722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		if (rec->src_width > rec->stride_Y)
991722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			return -EINVAL;
992722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		if (rec->src_width/uv_hscale > rec->stride_UV)
993722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			return -EINVAL;
994722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson
9959f7c3f442bb7c0d0a0ed25cc287932450a1f2babChris Wilson		tmp = rec->stride_Y * rec->src_height;
99605394f3975dceb107a5e1393e2244946e5b43660Chris Wilson		if (rec->offset_Y + tmp > new_bo->base.size)
997722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			return -EINVAL;
9989f7c3f442bb7c0d0a0ed25cc287932450a1f2babChris Wilson
9999f7c3f442bb7c0d0a0ed25cc287932450a1f2babChris Wilson		tmp = rec->stride_UV * (rec->src_height / uv_vscale);
100005394f3975dceb107a5e1393e2244946e5b43660Chris Wilson		if (rec->offset_U + tmp > new_bo->base.size ||
100105394f3975dceb107a5e1393e2244946e5b43660Chris Wilson		    rec->offset_V + tmp > new_bo->base.size)
1002722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			return -EINVAL;
1003722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		break;
100402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
100502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
100602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return 0;
100702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
100802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
1009e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson/**
1010e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson * Return the pipe currently connected to the panel fitter,
1011e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson * or -1 if the panel fitter is not present or not in use
1012e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson */
1013e9e331a8abeece1565d383510ed985945132ffe3Chris Wilsonstatic int intel_panel_fitter_pipe(struct drm_device *dev)
1014e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson{
1015e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson	struct drm_i915_private *dev_priv = dev->dev_private;
1016e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson	u32  pfit_control;
1017e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson
1018e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson	/* i830 doesn't have a panel fitter */
1019dc9e7decf13d49ff80fa690455ad89379b6b01aaVille Syrjälä	if (INTEL_INFO(dev)->gen <= 3 && (IS_I830(dev) || !IS_MOBILE(dev)))
1020e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson		return -1;
1021e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson
1022e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson	pfit_control = I915_READ(PFIT_CONTROL);
1023e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson
1024e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson	/* See if the panel fitter is in use */
1025e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson	if ((pfit_control & PFIT_ENABLE) == 0)
1026e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson		return -1;
1027e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson
1028e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson	/* 965 can place panel fitter on either pipe */
1029a6c45cf013a57e32ddae43dd4ac911eb4a3919fdChris Wilson	if (IS_GEN4(dev))
1030e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson		return (pfit_control >> 29) & 0x3;
1031e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson
1032e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson	/* older chips can only use pipe 1 */
1033e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson	return 1;
1034e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson}
1035e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson
103602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterint intel_overlay_put_image(struct drm_device *dev, void *data,
10370206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi			    struct drm_file *file_priv)
103802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
103902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct drm_intel_overlay_put_image *put_image_rec = data;
1040d5d45cc5fe02d158e4ca8fc5a45e0614873bfeb3Jani Nikula	struct drm_i915_private *dev_priv = dev->dev_private;
104102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct intel_overlay *overlay;
10427707e6535f43328e05e4729ac96eee864b90e8a4Rob Clark	struct drm_crtc *drmmode_crtc;
104302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct intel_crtc *crtc;
104405394f3975dceb107a5e1393e2244946e5b43660Chris Wilson	struct drm_i915_gem_object *new_bo;
104502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct put_image_params *params;
104602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int ret;
104702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
10481cff8f6b4c668a060c7e3f82d3f1fb5aaa37edc4Daniel Vetter	/* No need to check for DRIVER_MODESET - we don't set it up then. */
104902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	overlay = dev_priv->overlay;
105002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!overlay) {
105102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		DRM_DEBUG("userspace bug: no overlay\n");
105202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -ENODEV;
105302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
105402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
105502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!(put_image_rec->flags & I915_OVERLAY_ENABLE)) {
1056a0e99e68c12ac6dc5d6b1da7942b5e05d5f848afDaniel Vetter		drm_modeset_lock_all(dev);
105702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		mutex_lock(&dev->struct_mutex);
105802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
1059ce453d81cb0397aa7d5148984f51907e14072d74Chris Wilson		ret = intel_overlay_switch_off(overlay);
106002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
106102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		mutex_unlock(&dev->struct_mutex);
1062a0e99e68c12ac6dc5d6b1da7942b5e05d5f848afDaniel Vetter		drm_modeset_unlock_all(dev);
106302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
106402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return ret;
106502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
106602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
1067b14c5679dd2c87b5bd14c49c5bdd1962be2ab209Daniel Vetter	params = kmalloc(sizeof(*params), GFP_KERNEL);
106802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!params)
106902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -ENOMEM;
107002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
10717707e6535f43328e05e4729ac96eee864b90e8a4Rob Clark	drmmode_crtc = drm_crtc_find(dev, put_image_rec->crtc_id);
10727707e6535f43328e05e4729ac96eee864b90e8a4Rob Clark	if (!drmmode_crtc) {
1073915a428e43acfd05e4ffeaf40549b0cf163eebe2Dan Carpenter		ret = -ENOENT;
1074915a428e43acfd05e4ffeaf40549b0cf163eebe2Dan Carpenter		goto out_free;
1075915a428e43acfd05e4ffeaf40549b0cf163eebe2Dan Carpenter	}
10767707e6535f43328e05e4729ac96eee864b90e8a4Rob Clark	crtc = to_intel_crtc(drmmode_crtc);
107702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
107805394f3975dceb107a5e1393e2244946e5b43660Chris Wilson	new_bo = to_intel_bo(drm_gem_object_lookup(dev, file_priv,
107905394f3975dceb107a5e1393e2244946e5b43660Chris Wilson						   put_image_rec->bo_handle));
1080c87252266352c5201e2925740018f52578fa92bbChris Wilson	if (&new_bo->base == NULL) {
1081915a428e43acfd05e4ffeaf40549b0cf163eebe2Dan Carpenter		ret = -ENOENT;
1082915a428e43acfd05e4ffeaf40549b0cf163eebe2Dan Carpenter		goto out_free;
1083915a428e43acfd05e4ffeaf40549b0cf163eebe2Dan Carpenter	}
108402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
1085a0e99e68c12ac6dc5d6b1da7942b5e05d5f848afDaniel Vetter	drm_modeset_lock_all(dev);
108602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	mutex_lock(&dev->struct_mutex);
108702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
1088d9e86c0ee60f323e890484628f351bf50fa9a15dChris Wilson	if (new_bo->tiling_mode) {
10893b25b31fd15ed5a25822b450757dc33bc2d6b63bDaniel Vetter		DRM_DEBUG_KMS("buffer used for overlay image can not be tiled\n");
1090d9e86c0ee60f323e890484628f351bf50fa9a15dChris Wilson		ret = -EINVAL;
1091d9e86c0ee60f323e890484628f351bf50fa9a15dChris Wilson		goto out_unlock;
1092d9e86c0ee60f323e890484628f351bf50fa9a15dChris Wilson	}
1093d9e86c0ee60f323e890484628f351bf50fa9a15dChris Wilson
1094ce453d81cb0397aa7d5148984f51907e14072d74Chris Wilson	ret = intel_overlay_recover_from_interrupt(overlay);
1095b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson	if (ret != 0)
1096b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson		goto out_unlock;
109703f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter
109802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (overlay->crtc != crtc) {
109902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		struct drm_display_mode *mode = &crtc->base.mode;
1100ce453d81cb0397aa7d5148984f51907e14072d74Chris Wilson		ret = intel_overlay_switch_off(overlay);
110102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		if (ret != 0)
110202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			goto out_unlock;
110302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
110402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		ret = check_overlay_possible_on_crtc(overlay, crtc);
110502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		if (ret != 0)
110602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			goto out_unlock;
110702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
110802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		overlay->crtc = crtc;
110902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		crtc->overlay = overlay;
111002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
1111e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson		/* line too wide, i.e. one-line-mode */
1112e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson		if (mode->hdisplay > 1024 &&
1113e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson		    intel_panel_fitter_pipe(dev) == crtc->pipe) {
111402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			overlay->pfit_active = 1;
111502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			update_pfit_vscale_ratio(overlay);
111602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		} else
111702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			overlay->pfit_active = 0;
111802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
111902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
112002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	ret = check_overlay_dst(overlay, put_image_rec);
112102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (ret != 0)
112202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		goto out_unlock;
112302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
112402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (overlay->pfit_active) {
112502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		params->dst_y = ((((u32)put_image_rec->dst_y) << 12) /
1126722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson				 overlay->pfit_vscale_ratio);
112702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		/* shifting right rounds downwards, so add 1 */
112802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		params->dst_h = ((((u32)put_image_rec->dst_height) << 12) /
1129722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson				 overlay->pfit_vscale_ratio) + 1;
113002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	} else {
113102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		params->dst_y = put_image_rec->dst_y;
113202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		params->dst_h = put_image_rec->dst_height;
113302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
113402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	params->dst_x = put_image_rec->dst_x;
113502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	params->dst_w = put_image_rec->dst_width;
113602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
113702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	params->src_w = put_image_rec->src_width;
113802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	params->src_h = put_image_rec->src_height;
113902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	params->src_scan_w = put_image_rec->src_scan_width;
114002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	params->src_scan_h = put_image_rec->src_scan_height;
1141722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	if (params->src_scan_h > params->src_h ||
1142722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	    params->src_scan_w > params->src_w) {
114302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		ret = -EINVAL;
114402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		goto out_unlock;
114502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
114602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
114702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	ret = check_overlay_src(dev, put_image_rec, new_bo);
114802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (ret != 0)
114902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		goto out_unlock;
115002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	params->format = put_image_rec->flags & ~I915_OVERLAY_FLAGS_MASK;
115102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	params->stride_Y = put_image_rec->stride_Y;
115202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	params->stride_UV = put_image_rec->stride_UV;
115302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	params->offset_Y = put_image_rec->offset_Y;
115402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	params->offset_U = put_image_rec->offset_U;
115502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	params->offset_V = put_image_rec->offset_V;
115602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
115702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* Check scaling after src size to prevent a divide-by-zero. */
115802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	ret = check_overlay_scaling(params);
115902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (ret != 0)
116002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		goto out_unlock;
116102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
116202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	ret = intel_overlay_do_put_image(overlay, new_bo, params);
116302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (ret != 0)
116402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		goto out_unlock;
116502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
116602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	mutex_unlock(&dev->struct_mutex);
1167a0e99e68c12ac6dc5d6b1da7942b5e05d5f848afDaniel Vetter	drm_modeset_unlock_all(dev);
116802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
116902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	kfree(params);
117002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
117102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return 0;
117202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
117302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterout_unlock:
117402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	mutex_unlock(&dev->struct_mutex);
1175a0e99e68c12ac6dc5d6b1da7942b5e05d5f848afDaniel Vetter	drm_modeset_unlock_all(dev);
117605394f3975dceb107a5e1393e2244946e5b43660Chris Wilson	drm_gem_object_unreference_unlocked(&new_bo->base);
1177915a428e43acfd05e4ffeaf40549b0cf163eebe2Dan Carpenterout_free:
117802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	kfree(params);
117902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
118002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return ret;
118102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
118202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
118302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic void update_reg_attrs(struct intel_overlay *overlay,
118475020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawsky			     struct overlay_registers __iomem *regs)
118502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
118675020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawsky	iowrite32((overlay->contrast << 18) | (overlay->brightness & 0xff),
118775020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawsky		  &regs->OCLRC0);
118875020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawsky	iowrite32(overlay->saturation, &regs->OCLRC1);
118902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
119002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
119102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic bool check_gamma_bounds(u32 gamma1, u32 gamma2)
119202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
119302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int i;
119402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
119502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (gamma1 & 0xff000000 || gamma2 & 0xff000000)
119602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return false;
119702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
119802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	for (i = 0; i < 3; i++) {
1199722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		if (((gamma1 >> i*8) & 0xff) >= ((gamma2 >> i*8) & 0xff))
120002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			return false;
120102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
120202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
120302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return true;
120402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
120502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
120602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic bool check_gamma5_errata(u32 gamma5)
120702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
120802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int i;
120902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
121002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	for (i = 0; i < 3; i++) {
121102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		if (((gamma5 >> i*8) & 0xff) == 0x80)
121202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			return false;
121302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
121402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
121502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return true;
121602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
121702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
121802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic int check_gamma(struct drm_intel_overlay_attrs *attrs)
121902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
1220722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	if (!check_gamma_bounds(0, attrs->gamma0) ||
1221722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	    !check_gamma_bounds(attrs->gamma0, attrs->gamma1) ||
1222722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	    !check_gamma_bounds(attrs->gamma1, attrs->gamma2) ||
1223722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	    !check_gamma_bounds(attrs->gamma2, attrs->gamma3) ||
1224722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	    !check_gamma_bounds(attrs->gamma3, attrs->gamma4) ||
1225722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	    !check_gamma_bounds(attrs->gamma4, attrs->gamma5) ||
1226722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	    !check_gamma_bounds(attrs->gamma5, 0x00ffffff))
122702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EINVAL;
1228722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson
122902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!check_gamma5_errata(attrs->gamma5))
123002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EINVAL;
1231722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson
123202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return 0;
123302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
123402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
123502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterint intel_overlay_attrs(struct drm_device *dev, void *data,
12360206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi			struct drm_file *file_priv)
123702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
123802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct drm_intel_overlay_attrs *attrs = data;
1239d5d45cc5fe02d158e4ca8fc5a45e0614873bfeb3Jani Nikula	struct drm_i915_private *dev_priv = dev->dev_private;
124002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct intel_overlay *overlay;
124175020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawsky	struct overlay_registers __iomem *regs;
124202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int ret;
124302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
12441cff8f6b4c668a060c7e3f82d3f1fb5aaa37edc4Daniel Vetter	/* No need to check for DRIVER_MODESET - we don't set it up then. */
124502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	overlay = dev_priv->overlay;
124602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!overlay) {
124702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		DRM_DEBUG("userspace bug: no overlay\n");
124802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -ENODEV;
124902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
125002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
1251a0e99e68c12ac6dc5d6b1da7942b5e05d5f848afDaniel Vetter	drm_modeset_lock_all(dev);
125202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	mutex_lock(&dev->struct_mutex);
125302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
125460fc332cb5ab19e5a86d696b210df65814b2ad8aChris Wilson	ret = -EINVAL;
125502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!(attrs->flags & I915_OVERLAY_UPDATE_ATTRS)) {
125660fc332cb5ab19e5a86d696b210df65814b2ad8aChris Wilson		attrs->color_key  = overlay->color_key;
125702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		attrs->brightness = overlay->brightness;
125860fc332cb5ab19e5a86d696b210df65814b2ad8aChris Wilson		attrs->contrast   = overlay->contrast;
125902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		attrs->saturation = overlay->saturation;
126002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
1261a6c45cf013a57e32ddae43dd4ac911eb4a3919fdChris Wilson		if (!IS_GEN2(dev)) {
126202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			attrs->gamma0 = I915_READ(OGAMC0);
126302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			attrs->gamma1 = I915_READ(OGAMC1);
126402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			attrs->gamma2 = I915_READ(OGAMC2);
126502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			attrs->gamma3 = I915_READ(OGAMC3);
126602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			attrs->gamma4 = I915_READ(OGAMC4);
126702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			attrs->gamma5 = I915_READ(OGAMC5);
126802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		}
126902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	} else {
127060fc332cb5ab19e5a86d696b210df65814b2ad8aChris Wilson		if (attrs->brightness < -128 || attrs->brightness > 127)
127102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			goto out_unlock;
127260fc332cb5ab19e5a86d696b210df65814b2ad8aChris Wilson		if (attrs->contrast > 255)
127302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			goto out_unlock;
127460fc332cb5ab19e5a86d696b210df65814b2ad8aChris Wilson		if (attrs->saturation > 1023)
127502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			goto out_unlock;
127602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
127760fc332cb5ab19e5a86d696b210df65814b2ad8aChris Wilson		overlay->color_key  = attrs->color_key;
127860fc332cb5ab19e5a86d696b210df65814b2ad8aChris Wilson		overlay->brightness = attrs->brightness;
127960fc332cb5ab19e5a86d696b210df65814b2ad8aChris Wilson		overlay->contrast   = attrs->contrast;
128060fc332cb5ab19e5a86d696b210df65814b2ad8aChris Wilson		overlay->saturation = attrs->saturation;
128102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
12828d74f656dd78ae1ba813389cd46197c6329696bcChris Wilson		regs = intel_overlay_map_regs(overlay);
128302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		if (!regs) {
128402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			ret = -ENOMEM;
128502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			goto out_unlock;
128602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		}
128702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
128802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		update_reg_attrs(overlay, regs);
128902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
12909bb2ff731b32c023e7a502efdc0dee46157290d5Chris Wilson		intel_overlay_unmap_regs(overlay, regs);
129102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
129202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		if (attrs->flags & I915_OVERLAY_UPDATE_GAMMA) {
1293a6c45cf013a57e32ddae43dd4ac911eb4a3919fdChris Wilson			if (IS_GEN2(dev))
129402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				goto out_unlock;
129502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
129602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			if (overlay->active) {
129702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				ret = -EBUSY;
129802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				goto out_unlock;
129902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			}
130002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
130102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			ret = check_gamma(attrs);
130260fc332cb5ab19e5a86d696b210df65814b2ad8aChris Wilson			if (ret)
130302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				goto out_unlock;
130402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
130502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			I915_WRITE(OGAMC0, attrs->gamma0);
130602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			I915_WRITE(OGAMC1, attrs->gamma1);
130702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			I915_WRITE(OGAMC2, attrs->gamma2);
130802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			I915_WRITE(OGAMC3, attrs->gamma3);
130902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			I915_WRITE(OGAMC4, attrs->gamma4);
131002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			I915_WRITE(OGAMC5, attrs->gamma5);
131102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		}
131202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
131302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
131460fc332cb5ab19e5a86d696b210df65814b2ad8aChris Wilson	ret = 0;
131502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterout_unlock:
131602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	mutex_unlock(&dev->struct_mutex);
1317a0e99e68c12ac6dc5d6b1da7942b5e05d5f848afDaniel Vetter	drm_modeset_unlock_all(dev);
131802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
131902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return ret;
132002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
132102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
132202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vettervoid intel_setup_overlay(struct drm_device *dev)
132302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
1324d5d45cc5fe02d158e4ca8fc5a45e0614873bfeb3Jani Nikula	struct drm_i915_private *dev_priv = dev->dev_private;
132502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct intel_overlay *overlay;
132605394f3975dceb107a5e1393e2244946e5b43660Chris Wilson	struct drm_i915_gem_object *reg_bo;
132775020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawsky	struct overlay_registers __iomem *regs;
132802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int ret;
132902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
133031578148b2c62612f9516fdcf5ebb64ab32ed12dChris Wilson	if (!HAS_OVERLAY(dev))
133102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return;
133202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
1333b14c5679dd2c87b5bd14c49c5bdd1962be2ab209Daniel Vetter	overlay = kzalloc(sizeof(*overlay), GFP_KERNEL);
133402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!overlay)
133502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return;
133679d2427338e8da362678de32a1c8af1dc8a9810aChris Wilson
133779d2427338e8da362678de32a1c8af1dc8a9810aChris Wilson	mutex_lock(&dev->struct_mutex);
133879d2427338e8da362678de32a1c8af1dc8a9810aChris Wilson	if (WARN_ON(dev_priv->overlay))
133979d2427338e8da362678de32a1c8af1dc8a9810aChris Wilson		goto out_free;
134079d2427338e8da362678de32a1c8af1dc8a9810aChris Wilson
134102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	overlay->dev = dev;
134202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
1343f63a484c2f606b8267eb4d1dbfce5d1d3416e0bbDaniel Vetter	reg_bo = NULL;
1344f63a484c2f606b8267eb4d1dbfce5d1d3416e0bbDaniel Vetter	if (!OVERLAY_NEEDS_PHYSICAL(dev))
1345f63a484c2f606b8267eb4d1dbfce5d1d3416e0bbDaniel Vetter		reg_bo = i915_gem_object_create_stolen(dev, PAGE_SIZE);
13468040513870399f1cb032cb8bc805df5042fedcdfChris Wilson	if (reg_bo == NULL)
13478040513870399f1cb032cb8bc805df5042fedcdfChris Wilson		reg_bo = i915_gem_alloc_object(dev, PAGE_SIZE);
13488040513870399f1cb032cb8bc805df5042fedcdfChris Wilson	if (reg_bo == NULL)
134902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		goto out_free;
135005394f3975dceb107a5e1393e2244946e5b43660Chris Wilson	overlay->reg_bo = reg_bo;
135102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
135231578148b2c62612f9516fdcf5ebb64ab32ed12dChris Wilson	if (OVERLAY_NEEDS_PHYSICAL(dev)) {
135300731155a73020c8e3c215723be193f96b4fcb1fChris Wilson		ret = i915_gem_object_attach_phys(reg_bo, PAGE_SIZE);
13540206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi		if (ret) {
13550206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi			DRM_ERROR("failed to attach phys overlay regs\n");
13560206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi			goto out_free_bo;
13570206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi		}
135800731155a73020c8e3c215723be193f96b4fcb1fChris Wilson		overlay->flip_addr = reg_bo->phys_handle->busaddr;
135931578148b2c62612f9516fdcf5ebb64ab32ed12dChris Wilson	} else {
13601ec9e26ddab06459e89a890431b2de064c5d1056Daniel Vetter		ret = i915_gem_obj_ggtt_pin(reg_bo, PAGE_SIZE, PIN_MAPPABLE);
136102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		if (ret) {
13620206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi			DRM_ERROR("failed to pin overlay register bo\n");
13630206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi			goto out_free_bo;
13640206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi		}
1365f343c5f6477354967ee1e331a68a56b9fece2f36Ben Widawsky		overlay->flip_addr = i915_gem_obj_ggtt_offset(reg_bo);
13660ddc1289f3ffd779779ddd3922f26ae7d0a21604Chris Wilson
13670ddc1289f3ffd779779ddd3922f26ae7d0a21604Chris Wilson		ret = i915_gem_object_set_to_gtt_domain(reg_bo, true);
13680ddc1289f3ffd779779ddd3922f26ae7d0a21604Chris Wilson		if (ret) {
13690206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi			DRM_ERROR("failed to move overlay register bo into the GTT\n");
13700206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi			goto out_unpin_bo;
13710206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi		}
137202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
137302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
137402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* init all values */
137502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	overlay->color_key = 0x0101fe;
137602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	overlay->brightness = -19;
137702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	overlay->contrast = 75;
137802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	overlay->saturation = 146;
137902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
13808d74f656dd78ae1ba813389cd46197c6329696bcChris Wilson	regs = intel_overlay_map_regs(overlay);
138102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!regs)
138279d2427338e8da362678de32a1c8af1dc8a9810aChris Wilson		goto out_unpin_bo;
138302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
138475020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawsky	memset_io(regs, 0, sizeof(struct overlay_registers));
138502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	update_polyphase_filter(regs);
138602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	update_reg_attrs(overlay, regs);
138702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
13889bb2ff731b32c023e7a502efdc0dee46157290d5Chris Wilson	intel_overlay_unmap_regs(overlay, regs);
138902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
139002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	dev_priv->overlay = overlay;
139179d2427338e8da362678de32a1c8af1dc8a9810aChris Wilson	mutex_unlock(&dev->struct_mutex);
139202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	DRM_INFO("initialized overlay support\n");
139302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return;
139402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
13950ddc1289f3ffd779779ddd3922f26ae7d0a21604Chris Wilsonout_unpin_bo:
139679d2427338e8da362678de32a1c8af1dc8a9810aChris Wilson	if (!OVERLAY_NEEDS_PHYSICAL(dev))
1397d7f46fc4e7323887494db13f063a8e59861fefb0Ben Widawsky		i915_gem_object_ggtt_unpin(reg_bo);
139802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterout_free_bo:
139905394f3975dceb107a5e1393e2244946e5b43660Chris Wilson	drm_gem_object_unreference(&reg_bo->base);
140002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterout_free:
140179d2427338e8da362678de32a1c8af1dc8a9810aChris Wilson	mutex_unlock(&dev->struct_mutex);
140202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	kfree(overlay);
140302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return;
140402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
140502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
140602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vettervoid intel_cleanup_overlay(struct drm_device *dev)
140702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
1408d5d45cc5fe02d158e4ca8fc5a45e0614873bfeb3Jani Nikula	struct drm_i915_private *dev_priv = dev->dev_private;
140902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
141062cf4e6fef35b4422e206b63b7f0ac90261d4ad9Chris Wilson	if (!dev_priv->overlay)
141162cf4e6fef35b4422e206b63b7f0ac90261d4ad9Chris Wilson		return;
141202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
141362cf4e6fef35b4422e206b63b7f0ac90261d4ad9Chris Wilson	/* The bo's should be free'd by the generic code already.
141462cf4e6fef35b4422e206b63b7f0ac90261d4ad9Chris Wilson	 * Furthermore modesetting teardown happens beforehand so the
141562cf4e6fef35b4422e206b63b7f0ac90261d4ad9Chris Wilson	 * hardware should be off already */
141662cf4e6fef35b4422e206b63b7f0ac90261d4ad9Chris Wilson	BUG_ON(dev_priv->overlay->active);
141762cf4e6fef35b4422e206b63b7f0ac90261d4ad9Chris Wilson
141862cf4e6fef35b4422e206b63b7f0ac90261d4ad9Chris Wilson	drm_gem_object_unreference_unlocked(&dev_priv->overlay->reg_bo->base);
141962cf4e6fef35b4422e206b63b7f0ac90261d4ad9Chris Wilson	kfree(dev_priv->overlay);
142002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
14216ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson
14226ef3d4278034982c13df87c4a51e0445f762d316Chris Wilsonstruct intel_overlay_error_state {
14236ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	struct overlay_registers regs;
14246ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	unsigned long base;
14256ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	u32 dovsta;
14266ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	u32 isr;
14276ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson};
14286ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson
142975020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawskystatic struct overlay_registers __iomem *
1430c48c43e422c1404fd72c57d1d21a6f6d01e18900Linus Torvaldsintel_overlay_map_regs_atomic(struct intel_overlay *overlay)
14313bd3c9329973a93fa3ef5e9840f2fd6fa2889e3fChris Wilson{
1432d5d45cc5fe02d158e4ca8fc5a45e0614873bfeb3Jani Nikula	struct drm_i915_private *dev_priv = overlay->dev->dev_private;
143375020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawsky	struct overlay_registers __iomem *regs;
14343bd3c9329973a93fa3ef5e9840f2fd6fa2889e3fChris Wilson
14353bd3c9329973a93fa3ef5e9840f2fd6fa2889e3fChris Wilson	if (OVERLAY_NEEDS_PHYSICAL(overlay->dev))
143675020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawsky		/* Cast to make sparse happy, but it's wc memory anyway, so
143775020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawsky		 * equivalent to the wc io mapping on X86. */
143875020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawsky		regs = (struct overlay_registers __iomem *)
143900731155a73020c8e3c215723be193f96b4fcb1fChris Wilson			overlay->reg_bo->phys_handle->vaddr;
14403bd3c9329973a93fa3ef5e9840f2fd6fa2889e3fChris Wilson	else
14415d4545aef561ad47f91bcf75814af20c104b5a9eBen Widawsky		regs = io_mapping_map_atomic_wc(dev_priv->gtt.mappable,
1442f343c5f6477354967ee1e331a68a56b9fece2f36Ben Widawsky						i915_gem_obj_ggtt_offset(overlay->reg_bo));
14433bd3c9329973a93fa3ef5e9840f2fd6fa2889e3fChris Wilson
14443bd3c9329973a93fa3ef5e9840f2fd6fa2889e3fChris Wilson	return regs;
14453bd3c9329973a93fa3ef5e9840f2fd6fa2889e3fChris Wilson}
14463bd3c9329973a93fa3ef5e9840f2fd6fa2889e3fChris Wilson
14473bd3c9329973a93fa3ef5e9840f2fd6fa2889e3fChris Wilsonstatic void intel_overlay_unmap_regs_atomic(struct intel_overlay *overlay,
144875020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawsky					struct overlay_registers __iomem *regs)
14493bd3c9329973a93fa3ef5e9840f2fd6fa2889e3fChris Wilson{
14503bd3c9329973a93fa3ef5e9840f2fd6fa2889e3fChris Wilson	if (!OVERLAY_NEEDS_PHYSICAL(overlay->dev))
1451c48c43e422c1404fd72c57d1d21a6f6d01e18900Linus Torvalds		io_mapping_unmap_atomic(regs);
14523bd3c9329973a93fa3ef5e9840f2fd6fa2889e3fChris Wilson}
14533bd3c9329973a93fa3ef5e9840f2fd6fa2889e3fChris Wilson
14543bd3c9329973a93fa3ef5e9840f2fd6fa2889e3fChris Wilson
14556ef3d4278034982c13df87c4a51e0445f762d316Chris Wilsonstruct intel_overlay_error_state *
14566ef3d4278034982c13df87c4a51e0445f762d316Chris Wilsonintel_overlay_capture_error_state(struct drm_device *dev)
14576ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson{
1458d5d45cc5fe02d158e4ca8fc5a45e0614873bfeb3Jani Nikula	struct drm_i915_private *dev_priv = dev->dev_private;
14596ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	struct intel_overlay *overlay = dev_priv->overlay;
14606ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	struct intel_overlay_error_state *error;
14616ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	struct overlay_registers __iomem *regs;
14626ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson
14636ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	if (!overlay || !overlay->active)
14646ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson		return NULL;
14656ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson
14666ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	error = kmalloc(sizeof(*error), GFP_ATOMIC);
14676ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	if (error == NULL)
14686ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson		return NULL;
14696ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson
14706ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	error->dovsta = I915_READ(DOVSTA);
14716ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	error->isr = I915_READ(ISR);
147231578148b2c62612f9516fdcf5ebb64ab32ed12dChris Wilson	if (OVERLAY_NEEDS_PHYSICAL(overlay->dev))
147300731155a73020c8e3c215723be193f96b4fcb1fChris Wilson		error->base = (__force long)overlay->reg_bo->phys_handle->vaddr;
147431578148b2c62612f9516fdcf5ebb64ab32ed12dChris Wilson	else
1475f343c5f6477354967ee1e331a68a56b9fece2f36Ben Widawsky		error->base = i915_gem_obj_ggtt_offset(overlay->reg_bo);
14766ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson
14776ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	regs = intel_overlay_map_regs_atomic(overlay);
14786ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	if (!regs)
14796ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson		goto err;
14806ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson
14816ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	memcpy_fromio(&error->regs, regs, sizeof(struct overlay_registers));
1482c48c43e422c1404fd72c57d1d21a6f6d01e18900Linus Torvalds	intel_overlay_unmap_regs_atomic(overlay, regs);
14836ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson
14846ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	return error;
14856ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson
14866ef3d4278034982c13df87c4a51e0445f762d316Chris Wilsonerr:
14876ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	kfree(error);
14886ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	return NULL;
14896ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson}
14906ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson
14916ef3d4278034982c13df87c4a51e0445f762d316Chris Wilsonvoid
1492edc3d8848dc9fe2a470316363dab8ef211d77e01Mika Kuoppalaintel_overlay_print_error_state(struct drm_i915_error_state_buf *m,
1493edc3d8848dc9fe2a470316363dab8ef211d77e01Mika Kuoppala				struct intel_overlay_error_state *error)
14946ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson{
1495edc3d8848dc9fe2a470316363dab8ef211d77e01Mika Kuoppala	i915_error_printf(m, "Overlay, status: 0x%08x, interrupt: 0x%08x\n",
1496edc3d8848dc9fe2a470316363dab8ef211d77e01Mika Kuoppala			  error->dovsta, error->isr);
1497edc3d8848dc9fe2a470316363dab8ef211d77e01Mika Kuoppala	i915_error_printf(m, "  Register file at 0x%08lx:\n",
1498edc3d8848dc9fe2a470316363dab8ef211d77e01Mika Kuoppala			  error->base);
14996ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson
1500edc3d8848dc9fe2a470316363dab8ef211d77e01Mika Kuoppala#define P(x) i915_error_printf(m, "    " #x ":	0x%08x\n", error->regs.x)
15016ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OBUF_0Y);
15026ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OBUF_1Y);
15036ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OBUF_0U);
15046ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OBUF_0V);
15056ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OBUF_1U);
15066ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OBUF_1V);
15076ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OSTRIDE);
15086ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(YRGB_VPH);
15096ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(UV_VPH);
15106ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(HORZ_PH);
15116ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(INIT_PHS);
15126ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(DWINPOS);
15136ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(DWINSZ);
15146ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(SWIDTH);
15156ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(SWIDTHSW);
15166ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(SHEIGHT);
15176ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(YRGBSCALE);
15186ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(UVSCALE);
15196ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OCLRC0);
15206ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OCLRC1);
15216ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(DCLRKV);
15226ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(DCLRKM);
15236ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(SCLRKVH);
15246ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(SCLRKVL);
15256ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(SCLRKEN);
15266ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OCONFIG);
15276ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OCMD);
15286ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OSTART_0Y);
15296ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OSTART_1Y);
15306ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OSTART_0U);
15316ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OSTART_0V);
15326ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OSTART_1U);
15336ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OSTART_1V);
15346ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OTILEOFF_0Y);
15356ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OTILEOFF_1Y);
15366ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OTILEOFF_0U);
15376ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OTILEOFF_0V);
15386ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OTILEOFF_1U);
15396ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OTILEOFF_1V);
15406ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(FASTHSCALE);
15416ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(UVSCALEV);
15426ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson#undef P
15436ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson}
1544