intel_overlay.c revision 6d90c952cdd20158ec41a5c016c6fad73c9a8749
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 */
2802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#include "drmP.h"
2902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#include "drm.h"
3002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#include "i915_drm.h"
3102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#include "i915_drv.h"
3202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#include "i915_reg.h"
3302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#include "intel_drv.h"
3402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
3502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter/* Limits for overlay size. According to intel doc, the real limits are:
3602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter * Y width: 4095, UV width (planar): 2047, Y height: 2047,
3702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter * UV width (planar): * 1023. But the xorg thinks 2048 for height and width. Use
3802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter * the mininum of both.  */
3902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define IMAGE_MAX_WIDTH		2048
4002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define IMAGE_MAX_HEIGHT	2046 /* 2 * 1023 */
4102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter/* on 830 and 845 these large limits result in the card hanging */
4202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define IMAGE_MAX_WIDTH_LEGACY	1024
4302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define IMAGE_MAX_HEIGHT_LEGACY	1088
4402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
4502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter/* overlay register definitions */
4602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter/* OCMD register */
4702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_TILED_SURFACE	(0x1<<19)
4802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_MIRROR_MASK	(0x3<<17)
4902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_MIRROR_MODE	(0x3<<17)
5002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_MIRROR_HORIZONTAL	(0x1<<17)
5102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_MIRROR_VERTICAL	(0x2<<17)
5202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_MIRROR_BOTH	(0x3<<17)
5302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_BYTEORDER_MASK	(0x3<<14) /* zero for YUYV or FOURCC YUY2 */
5402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_UV_SWAP		(0x1<<14) /* YVYU */
5502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_Y_SWAP		(0x2<<14) /* UYVY or FOURCC UYVY */
5602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_Y_AND_UV_SWAP	(0x3<<14) /* VYUY */
5702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_SOURCE_FORMAT_MASK (0xf<<10)
5802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_RGB_888		(0x1<<10) /* not in i965 Intel docs */
5902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_RGB_555		(0x2<<10) /* not in i965 Intel docs */
6002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_RGB_565		(0x3<<10) /* not in i965 Intel docs */
6102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_YUV_422_PACKED	(0x8<<10)
6202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_YUV_411_PACKED	(0x9<<10) /* not in i965 Intel docs */
6302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_YUV_420_PLANAR	(0xc<<10)
6402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_YUV_422_PLANAR	(0xd<<10)
6502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_YUV_410_PLANAR	(0xe<<10) /* also 411 */
6602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_TVSYNCFLIP_PARITY	(0x1<<9)
6702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_TVSYNCFLIP_ENABLE	(0x1<<7)
68d79613643b4512962b2be5262a09b6694dd96101Chris Wilson#define OCMD_BUF_TYPE_MASK	(0x1<<5)
6902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_BUF_TYPE_FRAME	(0x0<<5)
7002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_BUF_TYPE_FIELD	(0x1<<5)
7102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_TEST_MODE		(0x1<<4)
7202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_BUFFER_SELECT	(0x3<<2)
7302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_BUFFER0		(0x0<<2)
7402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_BUFFER1		(0x1<<2)
7502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_FIELD_SELECT	(0x1<<2)
7602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_FIELD0		(0x0<<1)
7702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_FIELD1		(0x1<<1)
7802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCMD_ENABLE		(0x1<<0)
7902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
8002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter/* OCONFIG register */
8102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCONF_PIPE_MASK		(0x1<<18)
8202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCONF_PIPE_A		(0x0<<18)
8302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCONF_PIPE_B		(0x1<<18)
8402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCONF_GAMMA2_ENABLE	(0x1<<16)
8502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCONF_CSC_MODE_BT601	(0x0<<5)
8602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCONF_CSC_MODE_BT709	(0x1<<5)
8702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCONF_CSC_BYPASS	(0x1<<4)
8802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCONF_CC_OUT_8BIT	(0x1<<3)
8902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCONF_TEST_MODE		(0x1<<2)
9002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCONF_THREE_LINE_BUFFER	(0x1<<0)
9102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OCONF_TWO_LINE_BUFFER	(0x0<<0)
9202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
9302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter/* DCLRKM (dst-key) register */
9402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define DST_KEY_ENABLE		(0x1<<31)
9502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define CLK_RGB24_MASK		0x0
9602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define CLK_RGB16_MASK		0x070307
9702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define CLK_RGB15_MASK		0x070707
9802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define CLK_RGB8I_MASK		0xffffff
9902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
10002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define RGB16_TO_COLORKEY(c) \
10102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	(((c & 0xF800) << 8) | ((c & 0x07E0) << 5) | ((c & 0x001F) << 3))
10202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define RGB15_TO_COLORKEY(c) \
10302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	(((c & 0x7c00) << 9) | ((c & 0x03E0) << 6) | ((c & 0x001F) << 3))
10402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
10502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter/* overlay flip addr flag */
10602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define OFC_UPDATE		0x1
10702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
10802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter/* polyphase filter coefficients */
10902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define N_HORIZ_Y_TAPS          5
11002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define N_VERT_Y_TAPS           3
11102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define N_HORIZ_UV_TAPS         3
11202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define N_VERT_UV_TAPS          3
11302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define N_PHASES                17
11402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define MAX_TAPS                5
11502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
11602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter/* memory bufferd overlay registers */
11702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstruct overlay_registers {
1180206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	u32 OBUF_0Y;
1190206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	u32 OBUF_1Y;
1200206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	u32 OBUF_0U;
1210206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	u32 OBUF_0V;
1220206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	u32 OBUF_1U;
1230206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	u32 OBUF_1V;
1240206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	u32 OSTRIDE;
1250206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	u32 YRGB_VPH;
1260206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	u32 UV_VPH;
1270206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	u32 HORZ_PH;
1280206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	u32 INIT_PHS;
1290206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	u32 DWINPOS;
1300206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	u32 DWINSZ;
1310206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	u32 SWIDTH;
1320206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	u32 SWIDTHSW;
1330206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	u32 SHEIGHT;
1340206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	u32 YRGBSCALE;
1350206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	u32 UVSCALE;
1360206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	u32 OCLRC0;
1370206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	u32 OCLRC1;
1380206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	u32 DCLRKV;
1390206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	u32 DCLRKM;
1400206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	u32 SCLRKVH;
1410206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	u32 SCLRKVL;
1420206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	u32 SCLRKEN;
1430206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	u32 OCONFIG;
1440206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	u32 OCMD;
1450206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	u32 RESERVED1; /* 0x6C */
1460206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	u32 OSTART_0Y;
1470206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	u32 OSTART_1Y;
1480206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	u32 OSTART_0U;
1490206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	u32 OSTART_0V;
1500206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	u32 OSTART_1U;
1510206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	u32 OSTART_1V;
1520206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	u32 OTILEOFF_0Y;
1530206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	u32 OTILEOFF_1Y;
1540206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	u32 OTILEOFF_0U;
1550206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	u32 OTILEOFF_0V;
1560206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	u32 OTILEOFF_1U;
1570206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	u32 OTILEOFF_1V;
1580206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	u32 FASTHSCALE; /* 0xA0 */
1590206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	u32 UVSCALEV; /* 0xA4 */
1600206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	u32 RESERVEDC[(0x200 - 0xA8) / 4]; /* 0xA8 - 0x1FC */
1610206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	u16 Y_VCOEFS[N_VERT_Y_TAPS * N_PHASES]; /* 0x200 */
1620206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	u16 RESERVEDD[0x100 / 2 - N_VERT_Y_TAPS * N_PHASES];
1630206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	u16 Y_HCOEFS[N_HORIZ_Y_TAPS * N_PHASES]; /* 0x300 */
1640206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	u16 RESERVEDE[0x200 / 2 - N_HORIZ_Y_TAPS * N_PHASES];
1650206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	u16 UV_VCOEFS[N_VERT_UV_TAPS * N_PHASES]; /* 0x500 */
1660206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	u16 RESERVEDF[0x100 / 2 - N_VERT_UV_TAPS * N_PHASES];
1670206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	u16 UV_HCOEFS[N_HORIZ_UV_TAPS * N_PHASES]; /* 0x600 */
1680206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	u16 RESERVEDG[0x100 / 2 - N_HORIZ_UV_TAPS * N_PHASES];
16902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter};
17002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
17123f09ce31ca68af3728ac5eed3e3efb03c5f990aChris Wilsonstruct intel_overlay {
17223f09ce31ca68af3728ac5eed3e3efb03c5f990aChris Wilson	struct drm_device *dev;
17323f09ce31ca68af3728ac5eed3e3efb03c5f990aChris Wilson	struct intel_crtc *crtc;
17423f09ce31ca68af3728ac5eed3e3efb03c5f990aChris Wilson	struct drm_i915_gem_object *vid_bo;
17523f09ce31ca68af3728ac5eed3e3efb03c5f990aChris Wilson	struct drm_i915_gem_object *old_vid_bo;
17623f09ce31ca68af3728ac5eed3e3efb03c5f990aChris Wilson	int active;
17723f09ce31ca68af3728ac5eed3e3efb03c5f990aChris Wilson	int pfit_active;
17823f09ce31ca68af3728ac5eed3e3efb03c5f990aChris Wilson	u32 pfit_vscale_ratio; /* shifted-point number, (1<<12) == 1.0 */
17923f09ce31ca68af3728ac5eed3e3efb03c5f990aChris Wilson	u32 color_key;
18023f09ce31ca68af3728ac5eed3e3efb03c5f990aChris Wilson	u32 brightness, contrast, saturation;
18123f09ce31ca68af3728ac5eed3e3efb03c5f990aChris Wilson	u32 old_xscale, old_yscale;
18223f09ce31ca68af3728ac5eed3e3efb03c5f990aChris Wilson	/* register access */
18323f09ce31ca68af3728ac5eed3e3efb03c5f990aChris Wilson	u32 flip_addr;
18423f09ce31ca68af3728ac5eed3e3efb03c5f990aChris Wilson	struct drm_i915_gem_object *reg_bo;
18523f09ce31ca68af3728ac5eed3e3efb03c5f990aChris Wilson	/* flip handling */
18623f09ce31ca68af3728ac5eed3e3efb03c5f990aChris Wilson	uint32_t last_flip_req;
187b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson	void (*flip_tail)(struct intel_overlay *);
18823f09ce31ca68af3728ac5eed3e3efb03c5f990aChris Wilson};
18902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
19075020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawskystatic struct overlay_registers __iomem *
1918d74f656dd78ae1ba813389cd46197c6329696bcChris Wilsonintel_overlay_map_regs(struct intel_overlay *overlay)
19202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
1930206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	drm_i915_private_t *dev_priv = overlay->dev->dev_private;
19475020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawsky	struct overlay_registers __iomem *regs;
19502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
1969bb2ff731b32c023e7a502efdc0dee46157290d5Chris Wilson	if (OVERLAY_NEEDS_PHYSICAL(overlay->dev))
19775020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawsky		regs = (struct overlay_registers __iomem *)overlay->reg_bo->phys_obj->handle->vaddr;
1989bb2ff731b32c023e7a502efdc0dee46157290d5Chris Wilson	else
1998d74f656dd78ae1ba813389cd46197c6329696bcChris Wilson		regs = io_mapping_map_wc(dev_priv->mm.gtt_mapping,
2008d74f656dd78ae1ba813389cd46197c6329696bcChris Wilson					 overlay->reg_bo->gtt_offset);
20102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
2029bb2ff731b32c023e7a502efdc0dee46157290d5Chris Wilson	return regs;
2038d74f656dd78ae1ba813389cd46197c6329696bcChris Wilson}
20402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
2059bb2ff731b32c023e7a502efdc0dee46157290d5Chris Wilsonstatic void intel_overlay_unmap_regs(struct intel_overlay *overlay,
20675020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawsky				     struct overlay_registers __iomem *regs)
2078d74f656dd78ae1ba813389cd46197c6329696bcChris Wilson{
2088d74f656dd78ae1ba813389cd46197c6329696bcChris Wilson	if (!OVERLAY_NEEDS_PHYSICAL(overlay->dev))
2099bb2ff731b32c023e7a502efdc0dee46157290d5Chris Wilson		io_mapping_unmap(regs);
21002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
21102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
212b6c028e00445de9dfde2cd0c26521ac53965320aChris Wilsonstatic int intel_overlay_do_wait_request(struct intel_overlay *overlay,
2138dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson					 struct drm_i915_gem_request *request,
214b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson					 void (*tail)(struct intel_overlay *))
21502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
21602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct drm_device *dev = overlay->dev;
217852835f343146a82a528c3b712b373661d4fa17aZou Nan hai	drm_i915_private_t *dev_priv = dev->dev_private;
2186d90c952cdd20158ec41a5c016c6fad73c9a8749Daniel Vetter	struct intel_ring_buffer *ring = &dev_priv->ring[RCS];
219b6c028e00445de9dfde2cd0c26521ac53965320aChris Wilson	int ret;
22002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
221b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson	BUG_ON(overlay->last_flip_req);
2226d90c952cdd20158ec41a5c016c6fad73c9a8749Daniel Vetter	ret = i915_add_request(ring, NULL, request);
2233cce469cab880ef8990d2d16d745bf85443fc998Chris Wilson	if (ret) {
2243cce469cab880ef8990d2d16d745bf85443fc998Chris Wilson	    kfree(request);
2253cce469cab880ef8990d2d16d745bf85443fc998Chris Wilson	    return ret;
2263cce469cab880ef8990d2d16d745bf85443fc998Chris Wilson	}
2273cce469cab880ef8990d2d16d745bf85443fc998Chris Wilson	overlay->last_flip_req = request->seqno;
228b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson	overlay->flip_tail = tail;
2296d90c952cdd20158ec41a5c016c6fad73c9a8749Daniel Vetter	ret = i915_wait_request(ring, overlay->last_flip_req);
230b6c028e00445de9dfde2cd0c26521ac53965320aChris Wilson	if (ret)
23103f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter		return ret;
232b2da9fe5d5994a104bbae154590070d698279919Ben Widawsky	i915_gem_retire_requests(dev);
23302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
23403f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	overlay->last_flip_req = 0;
23502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return 0;
23602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
23702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
238106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson/* Workaround for i830 bug where pipe a must be enable to change control regs */
239106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilsonstatic int
240106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilsoni830_activate_pipe_a(struct drm_device *dev)
24102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
242106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	drm_i915_private_t *dev_priv = dev->dev_private;
243106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	struct intel_crtc *crtc;
244106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	struct drm_crtc_helper_funcs *crtc_funcs;
245106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	struct drm_display_mode vesa_640x480 = {
246106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson		DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 25175, 640, 656,
247106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson			 752, 800, 0, 480, 489, 492, 525, 0,
248106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson			 DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC)
249106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	}, *mode;
250106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson
251106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	crtc = to_intel_crtc(dev_priv->pipe_to_crtc_mapping[0]);
252106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	if (crtc->dpms_mode == DRM_MODE_DPMS_ON)
253106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson		return 0;
25402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
255106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	/* most i8xx have pipe a forced on, so don't trust dpms mode */
2569db4a9c7b2a3bd5b4952846bc0c2f58daa80ddd7Jesse Barnes	if (I915_READ(_PIPEACONF) & PIPECONF_ENABLE)
257106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson		return 0;
25802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
259106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	crtc_funcs = crtc->base.helper_private;
260106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	if (crtc_funcs->dpms == NULL)
261106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson		return 0;
262106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson
263106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	DRM_DEBUG_DRIVER("Enabling pipe A in order to enable overlay\n");
264106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson
265106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	mode = drm_mode_duplicate(dev, &vesa_640x480);
266ca9bfa7eed20ea34e862804e62aae10eb159edbbDaniel Vetter	drm_mode_set_crtcinfo(mode, 0);
2670206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	if (!drm_crtc_helper_set_mode(&crtc->base, mode,
268106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson				       crtc->base.x, crtc->base.y,
269106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson				       crtc->base.fb))
270106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson		return 0;
271106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson
272106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	crtc_funcs->dpms(&crtc->base, DRM_MODE_DPMS_ON);
273106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	return 1;
274106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson}
275106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson
276106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilsonstatic void
277106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilsoni830_deactivate_pipe_a(struct drm_device *dev)
278106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson{
279106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	drm_i915_private_t *dev_priv = dev->dev_private;
280106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[0];
281106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
282106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson
283106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	crtc_funcs->dpms(crtc, DRM_MODE_DPMS_OFF);
28402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
28502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
28602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter/* overlay needs to be disable in OCMD reg */
28702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic int intel_overlay_on(struct intel_overlay *overlay)
28802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
28902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct drm_device *dev = overlay->dev;
290e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson	struct drm_i915_private *dev_priv = dev->dev_private;
2916d90c952cdd20158ec41a5c016c6fad73c9a8749Daniel Vetter	struct intel_ring_buffer *ring = &dev_priv->ring[RCS];
2928dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson	struct drm_i915_gem_request *request;
293106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	int pipe_a_quirk = 0;
29402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int ret;
29502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
29602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	BUG_ON(overlay->active);
29703f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	overlay->active = 1;
298b6c028e00445de9dfde2cd0c26521ac53965320aChris Wilson
299106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	if (IS_I830(dev)) {
300106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson		pipe_a_quirk = i830_activate_pipe_a(dev);
301106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson		if (pipe_a_quirk < 0)
302106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson			return pipe_a_quirk;
303106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	}
304106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson
3058dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson	request = kzalloc(sizeof(*request), GFP_KERNEL);
306106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	if (request == NULL) {
307106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson		ret = -ENOMEM;
308106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson		goto out;
309106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	}
31003f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter
3116d90c952cdd20158ec41a5c016c6fad73c9a8749Daniel Vetter	ret = intel_ring_begin(ring, 4);
312e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson	if (ret) {
313e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson		kfree(request);
314e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson		goto out;
315e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson	}
316e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson
3176d90c952cdd20158ec41a5c016c6fad73c9a8749Daniel Vetter	intel_ring_emit(ring, MI_OVERLAY_FLIP | MI_OVERLAY_ON);
3186d90c952cdd20158ec41a5c016c6fad73c9a8749Daniel Vetter	intel_ring_emit(ring, overlay->flip_addr | OFC_UPDATE);
3196d90c952cdd20158ec41a5c016c6fad73c9a8749Daniel Vetter	intel_ring_emit(ring, MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
3206d90c952cdd20158ec41a5c016c6fad73c9a8749Daniel Vetter	intel_ring_emit(ring, MI_NOOP);
3216d90c952cdd20158ec41a5c016c6fad73c9a8749Daniel Vetter	intel_ring_advance(ring);
32202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
323ce453d81cb0397aa7d5148984f51907e14072d74Chris Wilson	ret = intel_overlay_do_wait_request(overlay, request, NULL);
324106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilsonout:
325106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	if (pipe_a_quirk)
326106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson		i830_deactivate_pipe_a(dev);
32702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
328106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	return ret;
32902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
33002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
33102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter/* overlay needs to be enabled in OCMD reg */
3328dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilsonstatic int intel_overlay_continue(struct intel_overlay *overlay,
3338dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson				  bool load_polyphase_filter)
33402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
33502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct drm_device *dev = overlay->dev;
3360206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	drm_i915_private_t *dev_priv = dev->dev_private;
3376d90c952cdd20158ec41a5c016c6fad73c9a8749Daniel Vetter	struct intel_ring_buffer *ring = &dev_priv->ring[RCS];
3388dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson	struct drm_i915_gem_request *request;
33902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	u32 flip_addr = overlay->flip_addr;
34002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	u32 tmp;
341e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson	int ret;
34202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
34302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	BUG_ON(!overlay->active);
34402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
3458dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson	request = kzalloc(sizeof(*request), GFP_KERNEL);
3468dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson	if (request == NULL)
3478dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson		return -ENOMEM;
3488dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson
34902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (load_polyphase_filter)
35002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		flip_addr |= OFC_UPDATE;
35102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
35202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* check for underruns */
35302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	tmp = I915_READ(DOVSTA);
35402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (tmp & (1 << 17))
35502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		DRM_DEBUG("overlay underrun, DOVSTA: %x\n", tmp);
35602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
3576d90c952cdd20158ec41a5c016c6fad73c9a8749Daniel Vetter	ret = intel_ring_begin(ring, 2);
358e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson	if (ret) {
359e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson		kfree(request);
360e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson		return ret;
361e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson	}
3626d90c952cdd20158ec41a5c016c6fad73c9a8749Daniel Vetter	intel_ring_emit(ring, MI_OVERLAY_FLIP | MI_OVERLAY_CONTINUE);
3636d90c952cdd20158ec41a5c016c6fad73c9a8749Daniel Vetter	intel_ring_emit(ring, flip_addr);
3646d90c952cdd20158ec41a5c016c6fad73c9a8749Daniel Vetter	intel_ring_advance(ring);
3655a5a0c64a99d7542c48c99d1a8bbb49e665842beDaniel Vetter
3666d90c952cdd20158ec41a5c016c6fad73c9a8749Daniel Vetter	ret = i915_add_request(ring, NULL, request);
3673cce469cab880ef8990d2d16d745bf85443fc998Chris Wilson	if (ret) {
3683cce469cab880ef8990d2d16d745bf85443fc998Chris Wilson		kfree(request);
3693cce469cab880ef8990d2d16d745bf85443fc998Chris Wilson		return ret;
3703cce469cab880ef8990d2d16d745bf85443fc998Chris Wilson	}
3713cce469cab880ef8990d2d16d745bf85443fc998Chris Wilson
3723cce469cab880ef8990d2d16d745bf85443fc998Chris Wilson	overlay->last_flip_req = request->seqno;
3738dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson	return 0;
3745a5a0c64a99d7542c48c99d1a8bbb49e665842beDaniel Vetter}
3755a5a0c64a99d7542c48c99d1a8bbb49e665842beDaniel Vetter
376b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilsonstatic void intel_overlay_release_old_vid_tail(struct intel_overlay *overlay)
3775a5a0c64a99d7542c48c99d1a8bbb49e665842beDaniel Vetter{
37805394f3975dceb107a5e1393e2244946e5b43660Chris Wilson	struct drm_i915_gem_object *obj = overlay->old_vid_bo;
3795a5a0c64a99d7542c48c99d1a8bbb49e665842beDaniel Vetter
380b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson	i915_gem_object_unpin(obj);
38105394f3975dceb107a5e1393e2244946e5b43660Chris Wilson	drm_gem_object_unreference(&obj->base);
3825a5a0c64a99d7542c48c99d1a8bbb49e665842beDaniel Vetter
383b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson	overlay->old_vid_bo = NULL;
384b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson}
38503f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter
386b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilsonstatic void intel_overlay_off_tail(struct intel_overlay *overlay)
387b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson{
38805394f3975dceb107a5e1393e2244946e5b43660Chris Wilson	struct drm_i915_gem_object *obj = overlay->vid_bo;
38902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
390b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson	/* never have the overlay hw on without showing a frame */
391b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson	BUG_ON(!overlay->vid_bo);
39202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
393b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson	i915_gem_object_unpin(obj);
39405394f3975dceb107a5e1393e2244946e5b43660Chris Wilson	drm_gem_object_unreference(&obj->base);
395b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson	overlay->vid_bo = NULL;
39603f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter
397b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson	overlay->crtc->overlay = NULL;
398b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson	overlay->crtc = NULL;
399b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson	overlay->active = 0;
40002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
40102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
40202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter/* overlay needs to be disabled in OCMD reg */
403ce453d81cb0397aa7d5148984f51907e14072d74Chris Wilsonstatic int intel_overlay_off(struct intel_overlay *overlay)
40402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
40502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct drm_device *dev = overlay->dev;
406e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson	struct drm_i915_private *dev_priv = dev->dev_private;
4076d90c952cdd20158ec41a5c016c6fad73c9a8749Daniel Vetter	struct intel_ring_buffer *ring = &dev_priv->ring[RCS];
4088dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson	u32 flip_addr = overlay->flip_addr;
4098dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson	struct drm_i915_gem_request *request;
410e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson	int ret;
41102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
41202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	BUG_ON(!overlay->active);
41302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
4148dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson	request = kzalloc(sizeof(*request), GFP_KERNEL);
4158dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson	if (request == NULL)
4168dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson		return -ENOMEM;
4178dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson
41802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* According to intel docs the overlay hw may hang (when switching
41902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	 * off) without loading the filter coeffs. It is however unclear whether
42002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	 * this applies to the disabling of the overlay or to the switching off
42102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	 * of the hw. Do it in both cases */
42202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	flip_addr |= OFC_UPDATE;
42302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
4246d90c952cdd20158ec41a5c016c6fad73c9a8749Daniel Vetter	ret = intel_ring_begin(ring, 6);
425e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson	if (ret) {
426e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson		kfree(request);
427e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson		return ret;
428e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson	}
42902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* wait for overlay to go idle */
4306d90c952cdd20158ec41a5c016c6fad73c9a8749Daniel Vetter	intel_ring_emit(ring, MI_OVERLAY_FLIP | MI_OVERLAY_CONTINUE);
4316d90c952cdd20158ec41a5c016c6fad73c9a8749Daniel Vetter	intel_ring_emit(ring, flip_addr);
4326d90c952cdd20158ec41a5c016c6fad73c9a8749Daniel Vetter	intel_ring_emit(ring, MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
43302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* turn overlay off */
4346d90c952cdd20158ec41a5c016c6fad73c9a8749Daniel Vetter	intel_ring_emit(ring, MI_OVERLAY_FLIP | MI_OVERLAY_OFF);
4356d90c952cdd20158ec41a5c016c6fad73c9a8749Daniel Vetter	intel_ring_emit(ring, flip_addr);
4366d90c952cdd20158ec41a5c016c6fad73c9a8749Daniel Vetter	intel_ring_emit(ring, MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
4376d90c952cdd20158ec41a5c016c6fad73c9a8749Daniel Vetter	intel_ring_advance(ring);
43802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
439ce453d81cb0397aa7d5148984f51907e14072d74Chris Wilson	return intel_overlay_do_wait_request(overlay, request,
440b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson					     intel_overlay_off_tail);
44112ca45fea91cfbb09df828bea958b47348caee6dDaniel Vetter}
44212ca45fea91cfbb09df828bea958b47348caee6dDaniel Vetter
44303f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter/* recover from an interruption due to a signal
44403f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter * We have to be careful not to repeat work forever an make forward progess. */
445ce453d81cb0397aa7d5148984f51907e14072d74Chris Wilsonstatic int intel_overlay_recover_from_interrupt(struct intel_overlay *overlay)
44603f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter{
44703f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	struct drm_device *dev = overlay->dev;
448852835f343146a82a528c3b712b373661d4fa17aZou Nan hai	drm_i915_private_t *dev_priv = dev->dev_private;
4496d90c952cdd20158ec41a5c016c6fad73c9a8749Daniel Vetter	struct intel_ring_buffer *ring = &dev_priv->ring[RCS];
45003f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	int ret;
45103f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter
452b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson	if (overlay->last_flip_req == 0)
453b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson		return 0;
45403f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter
4556d90c952cdd20158ec41a5c016c6fad73c9a8749Daniel Vetter	ret = i915_wait_request(ring, overlay->last_flip_req);
456b6c028e00445de9dfde2cd0c26521ac53965320aChris Wilson	if (ret)
45703f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter		return ret;
458b2da9fe5d5994a104bbae154590070d698279919Ben Widawsky	i915_gem_retire_requests(dev);
45903f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter
460b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson	if (overlay->flip_tail)
461b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson		overlay->flip_tail(overlay);
46203f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter
46303f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	overlay->last_flip_req = 0;
46403f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	return 0;
46503f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter}
46603f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter
4675a5a0c64a99d7542c48c99d1a8bbb49e665842beDaniel Vetter/* Wait for pending overlay flip and release old frame.
4685a5a0c64a99d7542c48c99d1a8bbb49e665842beDaniel Vetter * Needs to be called before the overlay register are changed
4698d74f656dd78ae1ba813389cd46197c6329696bcChris Wilson * via intel_overlay_(un)map_regs
4708d74f656dd78ae1ba813389cd46197c6329696bcChris Wilson */
47102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic int intel_overlay_release_old_vid(struct intel_overlay *overlay)
47202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
4735cd68c9864d65e49c910c701716e4e94e09f7ce0Chris Wilson	struct drm_device *dev = overlay->dev;
4745cd68c9864d65e49c910c701716e4e94e09f7ce0Chris Wilson	drm_i915_private_t *dev_priv = dev->dev_private;
4756d90c952cdd20158ec41a5c016c6fad73c9a8749Daniel Vetter	struct intel_ring_buffer *ring = &dev_priv->ring[RCS];
47602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int ret;
47702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
4785cd68c9864d65e49c910c701716e4e94e09f7ce0Chris Wilson	/* Only wait if there is actually an old frame to release to
4795cd68c9864d65e49c910c701716e4e94e09f7ce0Chris Wilson	 * guarantee forward progress.
4805cd68c9864d65e49c910c701716e4e94e09f7ce0Chris Wilson	 */
48103f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	if (!overlay->old_vid_bo)
48203f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter		return 0;
48303f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter
4845cd68c9864d65e49c910c701716e4e94e09f7ce0Chris Wilson	if (I915_READ(ISR) & I915_OVERLAY_PLANE_FLIP_PENDING_INTERRUPT) {
4858dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson		struct drm_i915_gem_request *request;
48602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
4875cd68c9864d65e49c910c701716e4e94e09f7ce0Chris Wilson		/* synchronous slowpath */
4888dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson		request = kzalloc(sizeof(*request), GFP_KERNEL);
4898dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson		if (request == NULL)
4908dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson			return -ENOMEM;
49102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
4926d90c952cdd20158ec41a5c016c6fad73c9a8749Daniel Vetter		ret = intel_ring_begin(ring, 2);
493e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson		if (ret) {
494e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson			kfree(request);
495e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson			return ret;
496e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson		}
497e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson
4986d90c952cdd20158ec41a5c016c6fad73c9a8749Daniel Vetter		intel_ring_emit(ring, MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
4996d90c952cdd20158ec41a5c016c6fad73c9a8749Daniel Vetter		intel_ring_emit(ring, MI_NOOP);
5006d90c952cdd20158ec41a5c016c6fad73c9a8749Daniel Vetter		intel_ring_advance(ring);
5015cd68c9864d65e49c910c701716e4e94e09f7ce0Chris Wilson
502ce453d81cb0397aa7d5148984f51907e14072d74Chris Wilson		ret = intel_overlay_do_wait_request(overlay, request,
503b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson						    intel_overlay_release_old_vid_tail);
5045cd68c9864d65e49c910c701716e4e94e09f7ce0Chris Wilson		if (ret)
5055cd68c9864d65e49c910c701716e4e94e09f7ce0Chris Wilson			return ret;
5065cd68c9864d65e49c910c701716e4e94e09f7ce0Chris Wilson	}
50702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
5085cd68c9864d65e49c910c701716e4e94e09f7ce0Chris Wilson	intel_overlay_release_old_vid_tail(overlay);
50902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return 0;
51002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
51102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
51202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstruct put_image_params {
51302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int format;
51402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	short dst_x;
51502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	short dst_y;
51602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	short dst_w;
51702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	short dst_h;
51802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	short src_w;
51902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	short src_scan_h;
52002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	short src_scan_w;
52102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	short src_h;
52202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	short stride_Y;
52302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	short stride_UV;
52402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int offset_Y;
52502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int offset_U;
52602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int offset_V;
52702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter};
52802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
52902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic int packed_depth_bytes(u32 format)
53002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
53102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	switch (format & I915_OVERLAY_DEPTH_MASK) {
532722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case I915_OVERLAY_YUV422:
533722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		return 4;
534722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case I915_OVERLAY_YUV411:
535722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		/* return 6; not implemented */
536722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	default:
537722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		return -EINVAL;
53802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
53902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
54002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
54102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic int packed_width_bytes(u32 format, short width)
54202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
54302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	switch (format & I915_OVERLAY_DEPTH_MASK) {
544722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case I915_OVERLAY_YUV422:
545722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		return width << 1;
546722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	default:
547722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		return -EINVAL;
54802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
54902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
55002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
55102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic int uv_hsubsampling(u32 format)
55202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
55302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	switch (format & I915_OVERLAY_DEPTH_MASK) {
554722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case I915_OVERLAY_YUV422:
555722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case I915_OVERLAY_YUV420:
556722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		return 2;
557722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case I915_OVERLAY_YUV411:
558722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case I915_OVERLAY_YUV410:
559722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		return 4;
560722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	default:
561722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		return -EINVAL;
56202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
56302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
56402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
56502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic int uv_vsubsampling(u32 format)
56602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
56702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	switch (format & I915_OVERLAY_DEPTH_MASK) {
568722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case I915_OVERLAY_YUV420:
569722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case I915_OVERLAY_YUV410:
570722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		return 2;
571722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case I915_OVERLAY_YUV422:
572722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case I915_OVERLAY_YUV411:
573722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		return 1;
574722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	default:
575722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		return -EINVAL;
57602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
57702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
57802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
57902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic u32 calc_swidthsw(struct drm_device *dev, u32 offset, u32 width)
58002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
58102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	u32 mask, shift, ret;
582a6c45cf013a57e32ddae43dd4ac911eb4a3919fdChris Wilson	if (IS_GEN2(dev)) {
58302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		mask = 0x1f;
58402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		shift = 5;
585a6c45cf013a57e32ddae43dd4ac911eb4a3919fdChris Wilson	} else {
586a6c45cf013a57e32ddae43dd4ac911eb4a3919fdChris Wilson		mask = 0x3f;
587a6c45cf013a57e32ddae43dd4ac911eb4a3919fdChris Wilson		shift = 6;
58802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
58902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	ret = ((offset + width + mask) >> shift) - (offset >> shift);
590a6c45cf013a57e32ddae43dd4ac911eb4a3919fdChris Wilson	if (!IS_GEN2(dev))
59102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		ret <<= 1;
5920206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	ret -= 1;
59302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return ret << 2;
59402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
59502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
59602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic const u16 y_static_hcoeffs[N_HORIZ_Y_TAPS * N_PHASES] = {
59702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3000, 0xb4a0, 0x1930, 0x1920, 0xb4a0,
59802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3000, 0xb500, 0x19d0, 0x1880, 0xb440,
59902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3000, 0xb540, 0x1a88, 0x2f80, 0xb3e0,
60002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3000, 0xb580, 0x1b30, 0x2e20, 0xb380,
60102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3000, 0xb5c0, 0x1bd8, 0x2cc0, 0xb320,
60202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3020, 0xb5e0, 0x1c60, 0x2b80, 0xb2c0,
60302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3020, 0xb5e0, 0x1cf8, 0x2a20, 0xb260,
60402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3020, 0xb5e0, 0x1d80, 0x28e0, 0xb200,
60502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3020, 0xb5c0, 0x1e08, 0x3f40, 0xb1c0,
60602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3020, 0xb580, 0x1e78, 0x3ce0, 0xb160,
60702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3040, 0xb520, 0x1ed8, 0x3aa0, 0xb120,
60802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3040, 0xb4a0, 0x1f30, 0x3880, 0xb0e0,
60902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3040, 0xb400, 0x1f78, 0x3680, 0xb0a0,
61002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3020, 0xb340, 0x1fb8, 0x34a0, 0xb060,
61102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3020, 0xb240, 0x1fe0, 0x32e0, 0xb040,
61202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3020, 0xb140, 0x1ff8, 0x3160, 0xb020,
613722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	0xb000, 0x3000, 0x0800, 0x3000, 0xb000
614722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson};
615722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson
61602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic const u16 uv_static_hcoeffs[N_HORIZ_UV_TAPS * N_PHASES] = {
61702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3000, 0x1800, 0x1800, 0xb000, 0x18d0, 0x2e60,
61802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0xb000, 0x1990, 0x2ce0, 0xb020, 0x1a68, 0x2b40,
61902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0xb040, 0x1b20, 0x29e0, 0xb060, 0x1bd8, 0x2880,
62002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0xb080, 0x1c88, 0x3e60, 0xb0a0, 0x1d28, 0x3c00,
62102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0xb0c0, 0x1db8, 0x39e0, 0xb0e0, 0x1e40, 0x37e0,
62202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0xb100, 0x1eb8, 0x3620, 0xb100, 0x1f18, 0x34a0,
62302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0xb100, 0x1f68, 0x3360, 0xb0e0, 0x1fa8, 0x3240,
62402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0xb0c0, 0x1fe0, 0x3140, 0xb060, 0x1ff0, 0x30a0,
625722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	0x3000, 0x0800, 0x3000
626722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson};
62702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
62875020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawskystatic void update_polyphase_filter(struct overlay_registers __iomem *regs)
62902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
63075020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawsky	memcpy_toio(regs->Y_HCOEFS, y_static_hcoeffs, sizeof(y_static_hcoeffs));
63175020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawsky	memcpy_toio(regs->UV_HCOEFS, uv_static_hcoeffs,
63275020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawsky		    sizeof(uv_static_hcoeffs));
63302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
63402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
63502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic bool update_scaling_factors(struct intel_overlay *overlay,
63675020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawsky				   struct overlay_registers __iomem *regs,
63702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				   struct put_image_params *params)
63802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
63902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* fixed point with a 12 bit shift */
64002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	u32 xscale, yscale, xscale_UV, yscale_UV;
64102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define FP_SHIFT 12
64202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define FRACT_MASK 0xfff
64302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	bool scale_changed = false;
64402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int uv_hscale = uv_hsubsampling(params->format);
64502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int uv_vscale = uv_vsubsampling(params->format);
64602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
64702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (params->dst_w > 1)
64802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		xscale = ((params->src_scan_w - 1) << FP_SHIFT)
64902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			/(params->dst_w);
65002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	else
65102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		xscale = 1 << FP_SHIFT;
65202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
65302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (params->dst_h > 1)
65402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		yscale = ((params->src_scan_h - 1) << FP_SHIFT)
65502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			/(params->dst_h);
65602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	else
65702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		yscale = 1 << FP_SHIFT;
65802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
65902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/*if (params->format & I915_OVERLAY_YUV_PLANAR) {*/
660722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	xscale_UV = xscale/uv_hscale;
661722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	yscale_UV = yscale/uv_vscale;
662722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	/* make the Y scale to UV scale ratio an exact multiply */
663722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	xscale = xscale_UV * uv_hscale;
664722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	yscale = yscale_UV * uv_vscale;
66502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/*} else {
666722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	  xscale_UV = 0;
667722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	  yscale_UV = 0;
668722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	  }*/
66902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
67002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (xscale != overlay->old_xscale || yscale != overlay->old_yscale)
67102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		scale_changed = true;
67202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	overlay->old_xscale = xscale;
67302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	overlay->old_yscale = yscale;
67402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
67575020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawsky	iowrite32(((yscale & FRACT_MASK) << 20) |
67675020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawsky		  ((xscale >> FP_SHIFT)  << 16) |
67775020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawsky		  ((xscale & FRACT_MASK) << 3),
67875020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawsky		 &regs->YRGBSCALE);
679722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson
68075020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawsky	iowrite32(((yscale_UV & FRACT_MASK) << 20) |
68175020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawsky		  ((xscale_UV >> FP_SHIFT)  << 16) |
68275020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawsky		  ((xscale_UV & FRACT_MASK) << 3),
68375020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawsky		 &regs->UVSCALE);
684722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson
68575020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawsky	iowrite32((((yscale    >> FP_SHIFT) << 16) |
68675020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawsky		   ((yscale_UV >> FP_SHIFT) << 0)),
68775020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawsky		 &regs->UVSCALEV);
68802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
68902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (scale_changed)
69002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		update_polyphase_filter(regs);
69102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
69202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return scale_changed;
69302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
69402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
69502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic void update_colorkey(struct intel_overlay *overlay,
69675020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawsky			    struct overlay_registers __iomem *regs)
69702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
69802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	u32 key = overlay->color_key;
6996ba3ddd9838f5e4d6ac7c6dce95648d205e11bffChris Wilson
70002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	switch (overlay->crtc->base.fb->bits_per_pixel) {
701722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case 8:
70275020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawsky		iowrite32(0, &regs->DCLRKV);
70375020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawsky		iowrite32(CLK_RGB8I_MASK | DST_KEY_ENABLE, &regs->DCLRKM);
7046ba3ddd9838f5e4d6ac7c6dce95648d205e11bffChris Wilson		break;
7056ba3ddd9838f5e4d6ac7c6dce95648d205e11bffChris Wilson
706722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case 16:
707722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		if (overlay->crtc->base.fb->depth == 15) {
70875020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawsky			iowrite32(RGB15_TO_COLORKEY(key), &regs->DCLRKV);
70975020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawsky			iowrite32(CLK_RGB15_MASK | DST_KEY_ENABLE,
71075020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawsky				  &regs->DCLRKM);
711722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		} else {
71275020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawsky			iowrite32(RGB16_TO_COLORKEY(key), &regs->DCLRKV);
71375020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawsky			iowrite32(CLK_RGB16_MASK | DST_KEY_ENABLE,
71475020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawsky				  &regs->DCLRKM);
715722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		}
7166ba3ddd9838f5e4d6ac7c6dce95648d205e11bffChris Wilson		break;
7176ba3ddd9838f5e4d6ac7c6dce95648d205e11bffChris Wilson
718722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case 24:
719722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case 32:
72075020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawsky		iowrite32(key, &regs->DCLRKV);
72175020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawsky		iowrite32(CLK_RGB24_MASK | DST_KEY_ENABLE, &regs->DCLRKM);
7226ba3ddd9838f5e4d6ac7c6dce95648d205e11bffChris Wilson		break;
72302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
72402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
72502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
72602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic u32 overlay_cmd_reg(struct put_image_params *params)
72702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
72802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	u32 cmd = OCMD_ENABLE | OCMD_BUF_TYPE_FRAME | OCMD_BUFFER0;
72902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
73002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (params->format & I915_OVERLAY_YUV_PLANAR) {
73102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		switch (params->format & I915_OVERLAY_DEPTH_MASK) {
732722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		case I915_OVERLAY_YUV422:
733722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			cmd |= OCMD_YUV_422_PLANAR;
734722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			break;
735722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		case I915_OVERLAY_YUV420:
736722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			cmd |= OCMD_YUV_420_PLANAR;
737722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			break;
738722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		case I915_OVERLAY_YUV411:
739722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		case I915_OVERLAY_YUV410:
740722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			cmd |= OCMD_YUV_410_PLANAR;
741722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			break;
74202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		}
74302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	} else { /* YUV packed */
74402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		switch (params->format & I915_OVERLAY_DEPTH_MASK) {
745722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		case I915_OVERLAY_YUV422:
746722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			cmd |= OCMD_YUV_422_PACKED;
747722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			break;
748722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		case I915_OVERLAY_YUV411:
749722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			cmd |= OCMD_YUV_411_PACKED;
750722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			break;
75102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		}
75202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
75302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		switch (params->format & I915_OVERLAY_SWAP_MASK) {
754722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		case I915_OVERLAY_NO_SWAP:
755722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			break;
756722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		case I915_OVERLAY_UV_SWAP:
757722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			cmd |= OCMD_UV_SWAP;
758722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			break;
759722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		case I915_OVERLAY_Y_SWAP:
760722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			cmd |= OCMD_Y_SWAP;
761722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			break;
762722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		case I915_OVERLAY_Y_AND_UV_SWAP:
763722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			cmd |= OCMD_Y_AND_UV_SWAP;
764722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			break;
76502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		}
76602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
76702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
76802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return cmd;
76902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
77002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
7715fe82c5ee1ba2d04183c376038c5d233a0311ec9Chris Wilsonstatic int intel_overlay_do_put_image(struct intel_overlay *overlay,
77205394f3975dceb107a5e1393e2244946e5b43660Chris Wilson				      struct drm_i915_gem_object *new_bo,
7735fe82c5ee1ba2d04183c376038c5d233a0311ec9Chris Wilson				      struct put_image_params *params)
77402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
77502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int ret, tmp_width;
77675020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawsky	struct overlay_registers __iomem *regs;
77702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	bool scale_changed = false;
77802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct drm_device *dev = overlay->dev;
77975020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawsky	u32 swidth, swidthsw, sheight, ostride;
78002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
78102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	BUG_ON(!mutex_is_locked(&dev->struct_mutex));
78202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	BUG_ON(!mutex_is_locked(&dev->mode_config.mutex));
78302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	BUG_ON(!overlay);
78402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
78502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	ret = intel_overlay_release_old_vid(overlay);
78602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (ret != 0)
78702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return ret;
78802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
7892da3b9b940e2a18147422c54ed8b29d01e1ade88Chris Wilson	ret = i915_gem_object_pin_to_display_plane(new_bo, 0, NULL);
79002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (ret != 0)
79102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return ret;
79202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
793d9e86c0ee60f323e890484628f351bf50fa9a15dChris Wilson	ret = i915_gem_object_put_fence(new_bo);
794d9e86c0ee60f323e890484628f351bf50fa9a15dChris Wilson	if (ret)
795d9e86c0ee60f323e890484628f351bf50fa9a15dChris Wilson		goto out_unpin;
796d9e86c0ee60f323e890484628f351bf50fa9a15dChris Wilson
79702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!overlay->active) {
79875020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawsky		u32 oconfig;
7998d74f656dd78ae1ba813389cd46197c6329696bcChris Wilson		regs = intel_overlay_map_regs(overlay);
80002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		if (!regs) {
80102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			ret = -ENOMEM;
80202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			goto out_unpin;
80302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		}
80475020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawsky		oconfig = OCONF_CC_OUT_8BIT;
805a6c45cf013a57e32ddae43dd4ac911eb4a3919fdChris Wilson		if (IS_GEN4(overlay->dev))
80675020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawsky			oconfig |= OCONF_CSC_MODE_BT709;
80775020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawsky		oconfig |= overlay->crtc->pipe == 0 ?
80802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			OCONF_PIPE_A : OCONF_PIPE_B;
80975020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawsky		iowrite32(oconfig, &regs->OCONFIG);
8109bb2ff731b32c023e7a502efdc0dee46157290d5Chris Wilson		intel_overlay_unmap_regs(overlay, regs);
81102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
81202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		ret = intel_overlay_on(overlay);
81302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		if (ret != 0)
81402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			goto out_unpin;
81502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
81602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
8178d74f656dd78ae1ba813389cd46197c6329696bcChris Wilson	regs = intel_overlay_map_regs(overlay);
81802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!regs) {
81902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		ret = -ENOMEM;
82002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		goto out_unpin;
82102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
82202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
82375020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawsky	iowrite32((params->dst_y << 16) | params->dst_x, &regs->DWINPOS);
82475020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawsky	iowrite32((params->dst_h << 16) | params->dst_w, &regs->DWINSZ);
82502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
82602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (params->format & I915_OVERLAY_YUV_PACKED)
82702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		tmp_width = packed_width_bytes(params->format, params->src_w);
82802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	else
82902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		tmp_width = params->src_w;
83002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
83175020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawsky	swidth = params->src_w;
83275020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawsky	swidthsw = calc_swidthsw(overlay->dev, params->offset_Y, tmp_width);
83375020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawsky	sheight = params->src_h;
83475020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawsky	iowrite32(new_bo->gtt_offset + params->offset_Y, &regs->OBUF_0Y);
83575020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawsky	ostride = params->stride_Y;
83602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
83702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (params->format & I915_OVERLAY_YUV_PLANAR) {
83802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		int uv_hscale = uv_hsubsampling(params->format);
83902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		int uv_vscale = uv_vsubsampling(params->format);
84002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		u32 tmp_U, tmp_V;
84175020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawsky		swidth |= (params->src_w/uv_hscale) << 16;
84202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		tmp_U = calc_swidthsw(overlay->dev, params->offset_U,
843722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson				      params->src_w/uv_hscale);
84402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		tmp_V = calc_swidthsw(overlay->dev, params->offset_V,
845722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson				      params->src_w/uv_hscale);
84675020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawsky		swidthsw |= max_t(u32, tmp_U, tmp_V) << 16;
84775020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawsky		sheight |= (params->src_h/uv_vscale) << 16;
84875020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawsky		iowrite32(new_bo->gtt_offset + params->offset_U, &regs->OBUF_0U);
84975020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawsky		iowrite32(new_bo->gtt_offset + params->offset_V, &regs->OBUF_0V);
85075020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawsky		ostride |= params->stride_UV << 16;
85102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
85202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
85375020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawsky	iowrite32(swidth, &regs->SWIDTH);
85475020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawsky	iowrite32(swidthsw, &regs->SWIDTHSW);
85575020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawsky	iowrite32(sheight, &regs->SHEIGHT);
85675020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawsky	iowrite32(ostride, &regs->OSTRIDE);
85775020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawsky
85802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	scale_changed = update_scaling_factors(overlay, regs, params);
85902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
86002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	update_colorkey(overlay, regs);
86102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
86275020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawsky	iowrite32(overlay_cmd_reg(params), &regs->OCMD);
86302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
8649bb2ff731b32c023e7a502efdc0dee46157290d5Chris Wilson	intel_overlay_unmap_regs(overlay, regs);
86502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
8668dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson	ret = intel_overlay_continue(overlay, scale_changed);
8678dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson	if (ret)
8688dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson		goto out_unpin;
86902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
87002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	overlay->old_vid_bo = overlay->vid_bo;
87105394f3975dceb107a5e1393e2244946e5b43660Chris Wilson	overlay->vid_bo = new_bo;
87202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
87302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return 0;
87402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
87502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterout_unpin:
87602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	i915_gem_object_unpin(new_bo);
87702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return ret;
87802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
87902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
880ce453d81cb0397aa7d5148984f51907e14072d74Chris Wilsonint intel_overlay_switch_off(struct intel_overlay *overlay)
88102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
88275020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawsky	struct overlay_registers __iomem *regs;
88302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct drm_device *dev = overlay->dev;
8845dcdbcb06badbdf2faa698bf3198e421a1e12840Chris Wilson	int ret;
88502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
88602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	BUG_ON(!mutex_is_locked(&dev->struct_mutex));
88702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	BUG_ON(!mutex_is_locked(&dev->mode_config.mutex));
88802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
889ce453d81cb0397aa7d5148984f51907e14072d74Chris Wilson	ret = intel_overlay_recover_from_interrupt(overlay);
890b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson	if (ret != 0)
891b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson		return ret;
8929bedb9743fd906e4160468663ee6e1bbdc4412b8Daniel Vetter
89302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!overlay->active)
89402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return 0;
89502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
89602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	ret = intel_overlay_release_old_vid(overlay);
89702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (ret != 0)
89802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return ret;
89902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
9008d74f656dd78ae1ba813389cd46197c6329696bcChris Wilson	regs = intel_overlay_map_regs(overlay);
90175020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawsky	iowrite32(0, &regs->OCMD);
9029bb2ff731b32c023e7a502efdc0dee46157290d5Chris Wilson	intel_overlay_unmap_regs(overlay, regs);
90302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
904ce453d81cb0397aa7d5148984f51907e14072d74Chris Wilson	ret = intel_overlay_off(overlay);
90503f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	if (ret != 0)
90603f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter		return ret;
90703f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter
90812ca45fea91cfbb09df828bea958b47348caee6dDaniel Vetter	intel_overlay_off_tail(overlay);
90902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return 0;
91002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
91102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
91202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic int check_overlay_possible_on_crtc(struct intel_overlay *overlay,
91302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter					  struct intel_crtc *crtc)
91402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
915722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	drm_i915_private_t *dev_priv = overlay->dev->dev_private;
91602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
917f7abfe8b281991c66406c42c1a6c6c9ee0daa0ffChris Wilson	if (!crtc->active)
91802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EINVAL;
91902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
92002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* can't use the overlay with double wide pipe */
921a6c45cf013a57e32ddae43dd4ac911eb4a3919fdChris Wilson	if (INTEL_INFO(overlay->dev)->gen < 4 &&
922f7abfe8b281991c66406c42c1a6c6c9ee0daa0ffChris Wilson	    (I915_READ(PIPECONF(crtc->pipe)) & (PIPECONF_DOUBLE_WIDE | PIPECONF_ENABLE)) != PIPECONF_ENABLE)
92302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EINVAL;
92402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
92502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return 0;
92602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
92702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
92802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic void update_pfit_vscale_ratio(struct intel_overlay *overlay)
92902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
93002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct drm_device *dev = overlay->dev;
931722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	drm_i915_private_t *dev_priv = dev->dev_private;
93202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	u32 pfit_control = I915_READ(PFIT_CONTROL);
933446d2183af68c0fd2772f5ef97a033efe69904a5Chris Wilson	u32 ratio;
93402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
93502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* XXX: This is not the same logic as in the xorg driver, but more in
936446d2183af68c0fd2772f5ef97a033efe69904a5Chris Wilson	 * line with the intel documentation for the i965
937446d2183af68c0fd2772f5ef97a033efe69904a5Chris Wilson	 */
938a6c45cf013a57e32ddae43dd4ac911eb4a3919fdChris Wilson	if (INTEL_INFO(dev)->gen >= 4) {
9390206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi		/* on i965 use the PGM reg to read out the autoscaler values */
940a6c45cf013a57e32ddae43dd4ac911eb4a3919fdChris Wilson		ratio = I915_READ(PFIT_PGM_RATIOS) >> PFIT_VERT_SCALE_SHIFT_965;
941a6c45cf013a57e32ddae43dd4ac911eb4a3919fdChris Wilson	} else {
942446d2183af68c0fd2772f5ef97a033efe69904a5Chris Wilson		if (pfit_control & VERT_AUTO_SCALE)
943446d2183af68c0fd2772f5ef97a033efe69904a5Chris Wilson			ratio = I915_READ(PFIT_AUTO_RATIOS);
94402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		else
945446d2183af68c0fd2772f5ef97a033efe69904a5Chris Wilson			ratio = I915_READ(PFIT_PGM_RATIOS);
946446d2183af68c0fd2772f5ef97a033efe69904a5Chris Wilson		ratio >>= PFIT_VERT_SCALE_SHIFT;
94702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
94802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
94902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	overlay->pfit_vscale_ratio = ratio;
95002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
95102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
95202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic int check_overlay_dst(struct intel_overlay *overlay,
95302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			     struct drm_intel_overlay_put_image *rec)
95402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
95502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct drm_display_mode *mode = &overlay->crtc->base.mode;
95602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
95775c13993db592343bda1fd62f2555fea037d56bdDaniel Vetter	if (rec->dst_x < mode->hdisplay &&
95875c13993db592343bda1fd62f2555fea037d56bdDaniel Vetter	    rec->dst_x + rec->dst_width <= mode->hdisplay &&
95975c13993db592343bda1fd62f2555fea037d56bdDaniel Vetter	    rec->dst_y < mode->vdisplay &&
96075c13993db592343bda1fd62f2555fea037d56bdDaniel Vetter	    rec->dst_y + rec->dst_height <= mode->vdisplay)
96102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return 0;
96202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	else
96302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EINVAL;
96402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
96502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
96602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic int check_overlay_scaling(struct put_image_params *rec)
96702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
96802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	u32 tmp;
96902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
97002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* downscaling limit is 8.0 */
97102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	tmp = ((rec->src_scan_h << 16) / rec->dst_h) >> 16;
97202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (tmp > 7)
97302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EINVAL;
97402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	tmp = ((rec->src_scan_w << 16) / rec->dst_w) >> 16;
97502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (tmp > 7)
97602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EINVAL;
97702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
97802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return 0;
97902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
98002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
98102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic int check_overlay_src(struct drm_device *dev,
98202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			     struct drm_intel_overlay_put_image *rec,
98305394f3975dceb107a5e1393e2244946e5b43660Chris Wilson			     struct drm_i915_gem_object *new_bo)
98402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
98502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int uv_hscale = uv_hsubsampling(rec->flags);
98602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int uv_vscale = uv_vsubsampling(rec->flags);
9878f28f54aad8bcf52a47afb6447fac34f96597b6fDan Carpenter	u32 stride_mask;
9888f28f54aad8bcf52a47afb6447fac34f96597b6fDan Carpenter	int depth;
9898f28f54aad8bcf52a47afb6447fac34f96597b6fDan Carpenter	u32 tmp;
99002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
99102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* check src dimensions */
99202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (IS_845G(dev) || IS_I830(dev)) {
993722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		if (rec->src_height > IMAGE_MAX_HEIGHT_LEGACY ||
9949f7c3f442bb7c0d0a0ed25cc287932450a1f2babChris Wilson		    rec->src_width  > IMAGE_MAX_WIDTH_LEGACY)
99502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			return -EINVAL;
99602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	} else {
997722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		if (rec->src_height > IMAGE_MAX_HEIGHT ||
9989f7c3f442bb7c0d0a0ed25cc287932450a1f2babChris Wilson		    rec->src_width  > IMAGE_MAX_WIDTH)
99902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			return -EINVAL;
100002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
10019f7c3f442bb7c0d0a0ed25cc287932450a1f2babChris Wilson
100202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* better safe than sorry, use 4 as the maximal subsampling ratio */
1003722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	if (rec->src_height < N_VERT_Y_TAPS*4 ||
10049f7c3f442bb7c0d0a0ed25cc287932450a1f2babChris Wilson	    rec->src_width  < N_HORIZ_Y_TAPS*4)
100502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EINVAL;
100602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
1007a1efd14a99483a4fb9308902397ed86b69454c99Chris Wilson	/* check alignment constraints */
100802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	switch (rec->flags & I915_OVERLAY_TYPE_MASK) {
1009722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case I915_OVERLAY_RGB:
1010722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		/* not implemented */
1011722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		return -EINVAL;
10129f7c3f442bb7c0d0a0ed25cc287932450a1f2babChris Wilson
1013722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case I915_OVERLAY_YUV_PACKED:
1014722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		if (uv_vscale != 1)
101502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			return -EINVAL;
10169f7c3f442bb7c0d0a0ed25cc287932450a1f2babChris Wilson
10179f7c3f442bb7c0d0a0ed25cc287932450a1f2babChris Wilson		depth = packed_depth_bytes(rec->flags);
1018722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		if (depth < 0)
1019722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			return depth;
10209f7c3f442bb7c0d0a0ed25cc287932450a1f2babChris Wilson
1021722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		/* ignore UV planes */
1022722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		rec->stride_UV = 0;
1023722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		rec->offset_U = 0;
1024722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		rec->offset_V = 0;
1025722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		/* check pixel alignment */
1026722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		if (rec->offset_Y % depth)
1027722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			return -EINVAL;
1028722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		break;
10299f7c3f442bb7c0d0a0ed25cc287932450a1f2babChris Wilson
1030722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case I915_OVERLAY_YUV_PLANAR:
1031722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		if (uv_vscale < 0 || uv_hscale < 0)
103202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			return -EINVAL;
1033722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		/* no offset restrictions for planar formats */
1034722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		break;
10359f7c3f442bb7c0d0a0ed25cc287932450a1f2babChris Wilson
1036722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	default:
1037722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		return -EINVAL;
103802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
103902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
104002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (rec->src_width % uv_hscale)
104102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EINVAL;
104202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
104302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* stride checking */
1044a1efd14a99483a4fb9308902397ed86b69454c99Chris Wilson	if (IS_I830(dev) || IS_845G(dev))
1045a1efd14a99483a4fb9308902397ed86b69454c99Chris Wilson		stride_mask = 255;
1046a1efd14a99483a4fb9308902397ed86b69454c99Chris Wilson	else
1047a1efd14a99483a4fb9308902397ed86b69454c99Chris Wilson		stride_mask = 63;
104802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
104902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (rec->stride_Y & stride_mask || rec->stride_UV & stride_mask)
105002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EINVAL;
1051a6c45cf013a57e32ddae43dd4ac911eb4a3919fdChris Wilson	if (IS_GEN4(dev) && rec->stride_Y < 512)
105202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EINVAL;
105302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
105402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	tmp = (rec->flags & I915_OVERLAY_TYPE_MASK) == I915_OVERLAY_YUV_PLANAR ?
10559f7c3f442bb7c0d0a0ed25cc287932450a1f2babChris Wilson		4096 : 8192;
10569f7c3f442bb7c0d0a0ed25cc287932450a1f2babChris Wilson	if (rec->stride_Y > tmp || rec->stride_UV > 2*1024)
105702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EINVAL;
105802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
105902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* check buffer dimensions */
106002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	switch (rec->flags & I915_OVERLAY_TYPE_MASK) {
1061722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case I915_OVERLAY_RGB:
1062722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case I915_OVERLAY_YUV_PACKED:
1063722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		/* always 4 Y values per depth pixels */
1064722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		if (packed_width_bytes(rec->flags, rec->src_width) > rec->stride_Y)
1065722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			return -EINVAL;
1066722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson
1067722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		tmp = rec->stride_Y*rec->src_height;
106805394f3975dceb107a5e1393e2244946e5b43660Chris Wilson		if (rec->offset_Y + tmp > new_bo->base.size)
1069722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			return -EINVAL;
1070722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		break;
1071722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson
1072722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case I915_OVERLAY_YUV_PLANAR:
1073722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		if (rec->src_width > rec->stride_Y)
1074722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			return -EINVAL;
1075722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		if (rec->src_width/uv_hscale > rec->stride_UV)
1076722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			return -EINVAL;
1077722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson
10789f7c3f442bb7c0d0a0ed25cc287932450a1f2babChris Wilson		tmp = rec->stride_Y * rec->src_height;
107905394f3975dceb107a5e1393e2244946e5b43660Chris Wilson		if (rec->offset_Y + tmp > new_bo->base.size)
1080722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			return -EINVAL;
10819f7c3f442bb7c0d0a0ed25cc287932450a1f2babChris Wilson
10829f7c3f442bb7c0d0a0ed25cc287932450a1f2babChris Wilson		tmp = rec->stride_UV * (rec->src_height / uv_vscale);
108305394f3975dceb107a5e1393e2244946e5b43660Chris Wilson		if (rec->offset_U + tmp > new_bo->base.size ||
108405394f3975dceb107a5e1393e2244946e5b43660Chris Wilson		    rec->offset_V + tmp > new_bo->base.size)
1085722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			return -EINVAL;
1086722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		break;
108702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
108802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
108902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return 0;
109002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
109102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
1092e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson/**
1093e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson * Return the pipe currently connected to the panel fitter,
1094e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson * or -1 if the panel fitter is not present or not in use
1095e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson */
1096e9e331a8abeece1565d383510ed985945132ffe3Chris Wilsonstatic int intel_panel_fitter_pipe(struct drm_device *dev)
1097e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson{
1098e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson	struct drm_i915_private *dev_priv = dev->dev_private;
1099e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson	u32  pfit_control;
1100e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson
1101e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson	/* i830 doesn't have a panel fitter */
1102e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson	if (IS_I830(dev))
1103e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson		return -1;
1104e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson
1105e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson	pfit_control = I915_READ(PFIT_CONTROL);
1106e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson
1107e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson	/* See if the panel fitter is in use */
1108e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson	if ((pfit_control & PFIT_ENABLE) == 0)
1109e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson		return -1;
1110e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson
1111e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson	/* 965 can place panel fitter on either pipe */
1112a6c45cf013a57e32ddae43dd4ac911eb4a3919fdChris Wilson	if (IS_GEN4(dev))
1113e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson		return (pfit_control >> 29) & 0x3;
1114e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson
1115e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson	/* older chips can only use pipe 1 */
1116e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson	return 1;
1117e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson}
1118e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson
111902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterint intel_overlay_put_image(struct drm_device *dev, void *data,
11200206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi			    struct drm_file *file_priv)
112102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
112202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct drm_intel_overlay_put_image *put_image_rec = data;
112302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	drm_i915_private_t *dev_priv = dev->dev_private;
112402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct intel_overlay *overlay;
112502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct drm_mode_object *drmmode_obj;
112602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct intel_crtc *crtc;
112705394f3975dceb107a5e1393e2244946e5b43660Chris Wilson	struct drm_i915_gem_object *new_bo;
112802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct put_image_params *params;
112902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int ret;
113002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
11311cff8f6b4c668a060c7e3f82d3f1fb5aaa37edc4Daniel Vetter	/* No need to check for DRIVER_MODESET - we don't set it up then. */
113202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	overlay = dev_priv->overlay;
113302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!overlay) {
113402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		DRM_DEBUG("userspace bug: no overlay\n");
113502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -ENODEV;
113602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
113702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
113802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!(put_image_rec->flags & I915_OVERLAY_ENABLE)) {
113902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		mutex_lock(&dev->mode_config.mutex);
114002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		mutex_lock(&dev->struct_mutex);
114102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
1142ce453d81cb0397aa7d5148984f51907e14072d74Chris Wilson		ret = intel_overlay_switch_off(overlay);
114302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
114402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		mutex_unlock(&dev->struct_mutex);
114502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		mutex_unlock(&dev->mode_config.mutex);
114602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
114702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return ret;
114802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
114902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
115002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	params = kmalloc(sizeof(struct put_image_params), GFP_KERNEL);
115102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!params)
115202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -ENOMEM;
115302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
115402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	drmmode_obj = drm_mode_object_find(dev, put_image_rec->crtc_id,
1155722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson					   DRM_MODE_OBJECT_CRTC);
1156915a428e43acfd05e4ffeaf40549b0cf163eebe2Dan Carpenter	if (!drmmode_obj) {
1157915a428e43acfd05e4ffeaf40549b0cf163eebe2Dan Carpenter		ret = -ENOENT;
1158915a428e43acfd05e4ffeaf40549b0cf163eebe2Dan Carpenter		goto out_free;
1159915a428e43acfd05e4ffeaf40549b0cf163eebe2Dan Carpenter	}
116002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	crtc = to_intel_crtc(obj_to_crtc(drmmode_obj));
116102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
116205394f3975dceb107a5e1393e2244946e5b43660Chris Wilson	new_bo = to_intel_bo(drm_gem_object_lookup(dev, file_priv,
116305394f3975dceb107a5e1393e2244946e5b43660Chris Wilson						   put_image_rec->bo_handle));
1164c87252266352c5201e2925740018f52578fa92bbChris Wilson	if (&new_bo->base == NULL) {
1165915a428e43acfd05e4ffeaf40549b0cf163eebe2Dan Carpenter		ret = -ENOENT;
1166915a428e43acfd05e4ffeaf40549b0cf163eebe2Dan Carpenter		goto out_free;
1167915a428e43acfd05e4ffeaf40549b0cf163eebe2Dan Carpenter	}
116802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
116902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	mutex_lock(&dev->mode_config.mutex);
117002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	mutex_lock(&dev->struct_mutex);
117102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
1172d9e86c0ee60f323e890484628f351bf50fa9a15dChris Wilson	if (new_bo->tiling_mode) {
1173d9e86c0ee60f323e890484628f351bf50fa9a15dChris Wilson		DRM_ERROR("buffer used for overlay image can not be tiled\n");
1174d9e86c0ee60f323e890484628f351bf50fa9a15dChris Wilson		ret = -EINVAL;
1175d9e86c0ee60f323e890484628f351bf50fa9a15dChris Wilson		goto out_unlock;
1176d9e86c0ee60f323e890484628f351bf50fa9a15dChris Wilson	}
1177d9e86c0ee60f323e890484628f351bf50fa9a15dChris Wilson
1178ce453d81cb0397aa7d5148984f51907e14072d74Chris Wilson	ret = intel_overlay_recover_from_interrupt(overlay);
1179b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson	if (ret != 0)
1180b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson		goto out_unlock;
118103f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter
118202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (overlay->crtc != crtc) {
118302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		struct drm_display_mode *mode = &crtc->base.mode;
1184ce453d81cb0397aa7d5148984f51907e14072d74Chris Wilson		ret = intel_overlay_switch_off(overlay);
118502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		if (ret != 0)
118602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			goto out_unlock;
118702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
118802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		ret = check_overlay_possible_on_crtc(overlay, crtc);
118902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		if (ret != 0)
119002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			goto out_unlock;
119102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
119202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		overlay->crtc = crtc;
119302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		crtc->overlay = overlay;
119402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
1195e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson		/* line too wide, i.e. one-line-mode */
1196e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson		if (mode->hdisplay > 1024 &&
1197e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson		    intel_panel_fitter_pipe(dev) == crtc->pipe) {
119802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			overlay->pfit_active = 1;
119902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			update_pfit_vscale_ratio(overlay);
120002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		} else
120102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			overlay->pfit_active = 0;
120202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
120302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
120402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	ret = check_overlay_dst(overlay, put_image_rec);
120502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (ret != 0)
120602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		goto out_unlock;
120702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
120802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (overlay->pfit_active) {
120902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		params->dst_y = ((((u32)put_image_rec->dst_y) << 12) /
1210722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson				 overlay->pfit_vscale_ratio);
121102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		/* shifting right rounds downwards, so add 1 */
121202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		params->dst_h = ((((u32)put_image_rec->dst_height) << 12) /
1213722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson				 overlay->pfit_vscale_ratio) + 1;
121402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	} else {
121502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		params->dst_y = put_image_rec->dst_y;
121602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		params->dst_h = put_image_rec->dst_height;
121702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
121802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	params->dst_x = put_image_rec->dst_x;
121902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	params->dst_w = put_image_rec->dst_width;
122002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
122102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	params->src_w = put_image_rec->src_width;
122202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	params->src_h = put_image_rec->src_height;
122302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	params->src_scan_w = put_image_rec->src_scan_width;
122402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	params->src_scan_h = put_image_rec->src_scan_height;
1225722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	if (params->src_scan_h > params->src_h ||
1226722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	    params->src_scan_w > params->src_w) {
122702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		ret = -EINVAL;
122802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		goto out_unlock;
122902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
123002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
123102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	ret = check_overlay_src(dev, put_image_rec, new_bo);
123202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (ret != 0)
123302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		goto out_unlock;
123402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	params->format = put_image_rec->flags & ~I915_OVERLAY_FLAGS_MASK;
123502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	params->stride_Y = put_image_rec->stride_Y;
123602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	params->stride_UV = put_image_rec->stride_UV;
123702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	params->offset_Y = put_image_rec->offset_Y;
123802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	params->offset_U = put_image_rec->offset_U;
123902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	params->offset_V = put_image_rec->offset_V;
124002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
124102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* Check scaling after src size to prevent a divide-by-zero. */
124202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	ret = check_overlay_scaling(params);
124302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (ret != 0)
124402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		goto out_unlock;
124502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
124602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	ret = intel_overlay_do_put_image(overlay, new_bo, params);
124702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (ret != 0)
124802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		goto out_unlock;
124902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
125002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	mutex_unlock(&dev->struct_mutex);
125102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	mutex_unlock(&dev->mode_config.mutex);
125202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
125302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	kfree(params);
125402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
125502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return 0;
125602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
125702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterout_unlock:
125802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	mutex_unlock(&dev->struct_mutex);
125902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	mutex_unlock(&dev->mode_config.mutex);
126005394f3975dceb107a5e1393e2244946e5b43660Chris Wilson	drm_gem_object_unreference_unlocked(&new_bo->base);
1261915a428e43acfd05e4ffeaf40549b0cf163eebe2Dan Carpenterout_free:
126202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	kfree(params);
126302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
126402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return ret;
126502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
126602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
126702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic void update_reg_attrs(struct intel_overlay *overlay,
126875020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawsky			     struct overlay_registers __iomem *regs)
126902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
127075020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawsky	iowrite32((overlay->contrast << 18) | (overlay->brightness & 0xff),
127175020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawsky		  &regs->OCLRC0);
127275020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawsky	iowrite32(overlay->saturation, &regs->OCLRC1);
127302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
127402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
127502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic bool check_gamma_bounds(u32 gamma1, u32 gamma2)
127602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
127702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int i;
127802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
127902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (gamma1 & 0xff000000 || gamma2 & 0xff000000)
128002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return false;
128102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
128202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	for (i = 0; i < 3; i++) {
1283722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		if (((gamma1 >> i*8) & 0xff) >= ((gamma2 >> i*8) & 0xff))
128402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			return false;
128502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
128602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
128702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return true;
128802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
128902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
129002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic bool check_gamma5_errata(u32 gamma5)
129102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
129202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int i;
129302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
129402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	for (i = 0; i < 3; i++) {
129502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		if (((gamma5 >> i*8) & 0xff) == 0x80)
129602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			return false;
129702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
129802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
129902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return true;
130002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
130102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
130202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic int check_gamma(struct drm_intel_overlay_attrs *attrs)
130302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
1304722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	if (!check_gamma_bounds(0, attrs->gamma0) ||
1305722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	    !check_gamma_bounds(attrs->gamma0, attrs->gamma1) ||
1306722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	    !check_gamma_bounds(attrs->gamma1, attrs->gamma2) ||
1307722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	    !check_gamma_bounds(attrs->gamma2, attrs->gamma3) ||
1308722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	    !check_gamma_bounds(attrs->gamma3, attrs->gamma4) ||
1309722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	    !check_gamma_bounds(attrs->gamma4, attrs->gamma5) ||
1310722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	    !check_gamma_bounds(attrs->gamma5, 0x00ffffff))
131102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EINVAL;
1312722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson
131302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!check_gamma5_errata(attrs->gamma5))
131402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EINVAL;
1315722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson
131602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return 0;
131702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
131802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
131902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterint intel_overlay_attrs(struct drm_device *dev, void *data,
13200206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi			struct drm_file *file_priv)
132102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
132202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct drm_intel_overlay_attrs *attrs = data;
13230206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	drm_i915_private_t *dev_priv = dev->dev_private;
132402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct intel_overlay *overlay;
132575020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawsky	struct overlay_registers __iomem *regs;
132602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int ret;
132702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
13281cff8f6b4c668a060c7e3f82d3f1fb5aaa37edc4Daniel Vetter	/* No need to check for DRIVER_MODESET - we don't set it up then. */
132902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	overlay = dev_priv->overlay;
133002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!overlay) {
133102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		DRM_DEBUG("userspace bug: no overlay\n");
133202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -ENODEV;
133302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
133402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
133502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	mutex_lock(&dev->mode_config.mutex);
133602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	mutex_lock(&dev->struct_mutex);
133702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
133860fc332cb5ab19e5a86d696b210df65814b2ad8aChris Wilson	ret = -EINVAL;
133902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!(attrs->flags & I915_OVERLAY_UPDATE_ATTRS)) {
134060fc332cb5ab19e5a86d696b210df65814b2ad8aChris Wilson		attrs->color_key  = overlay->color_key;
134102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		attrs->brightness = overlay->brightness;
134260fc332cb5ab19e5a86d696b210df65814b2ad8aChris Wilson		attrs->contrast   = overlay->contrast;
134302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		attrs->saturation = overlay->saturation;
134402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
1345a6c45cf013a57e32ddae43dd4ac911eb4a3919fdChris Wilson		if (!IS_GEN2(dev)) {
134602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			attrs->gamma0 = I915_READ(OGAMC0);
134702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			attrs->gamma1 = I915_READ(OGAMC1);
134802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			attrs->gamma2 = I915_READ(OGAMC2);
134902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			attrs->gamma3 = I915_READ(OGAMC3);
135002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			attrs->gamma4 = I915_READ(OGAMC4);
135102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			attrs->gamma5 = I915_READ(OGAMC5);
135202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		}
135302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	} else {
135460fc332cb5ab19e5a86d696b210df65814b2ad8aChris Wilson		if (attrs->brightness < -128 || attrs->brightness > 127)
135502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			goto out_unlock;
135660fc332cb5ab19e5a86d696b210df65814b2ad8aChris Wilson		if (attrs->contrast > 255)
135702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			goto out_unlock;
135860fc332cb5ab19e5a86d696b210df65814b2ad8aChris Wilson		if (attrs->saturation > 1023)
135902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			goto out_unlock;
136002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
136160fc332cb5ab19e5a86d696b210df65814b2ad8aChris Wilson		overlay->color_key  = attrs->color_key;
136260fc332cb5ab19e5a86d696b210df65814b2ad8aChris Wilson		overlay->brightness = attrs->brightness;
136360fc332cb5ab19e5a86d696b210df65814b2ad8aChris Wilson		overlay->contrast   = attrs->contrast;
136460fc332cb5ab19e5a86d696b210df65814b2ad8aChris Wilson		overlay->saturation = attrs->saturation;
136502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
13668d74f656dd78ae1ba813389cd46197c6329696bcChris Wilson		regs = intel_overlay_map_regs(overlay);
136702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		if (!regs) {
136802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			ret = -ENOMEM;
136902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			goto out_unlock;
137002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		}
137102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
137202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		update_reg_attrs(overlay, regs);
137302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
13749bb2ff731b32c023e7a502efdc0dee46157290d5Chris Wilson		intel_overlay_unmap_regs(overlay, regs);
137502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
137602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		if (attrs->flags & I915_OVERLAY_UPDATE_GAMMA) {
1377a6c45cf013a57e32ddae43dd4ac911eb4a3919fdChris Wilson			if (IS_GEN2(dev))
137802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				goto out_unlock;
137902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
138002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			if (overlay->active) {
138102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				ret = -EBUSY;
138202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				goto out_unlock;
138302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			}
138402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
138502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			ret = check_gamma(attrs);
138660fc332cb5ab19e5a86d696b210df65814b2ad8aChris Wilson			if (ret)
138702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				goto out_unlock;
138802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
138902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			I915_WRITE(OGAMC0, attrs->gamma0);
139002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			I915_WRITE(OGAMC1, attrs->gamma1);
139102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			I915_WRITE(OGAMC2, attrs->gamma2);
139202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			I915_WRITE(OGAMC3, attrs->gamma3);
139302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			I915_WRITE(OGAMC4, attrs->gamma4);
139402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			I915_WRITE(OGAMC5, attrs->gamma5);
139502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		}
139602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
139702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
139860fc332cb5ab19e5a86d696b210df65814b2ad8aChris Wilson	ret = 0;
139902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterout_unlock:
140002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	mutex_unlock(&dev->struct_mutex);
140102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	mutex_unlock(&dev->mode_config.mutex);
140202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
140302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return ret;
140402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
140502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
140602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vettervoid intel_setup_overlay(struct drm_device *dev)
140702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
14080206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	drm_i915_private_t *dev_priv = dev->dev_private;
140902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct intel_overlay *overlay;
141005394f3975dceb107a5e1393e2244946e5b43660Chris Wilson	struct drm_i915_gem_object *reg_bo;
141175020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawsky	struct overlay_registers __iomem *regs;
141202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int ret;
141302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
141431578148b2c62612f9516fdcf5ebb64ab32ed12dChris Wilson	if (!HAS_OVERLAY(dev))
141502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return;
141602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
141702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	overlay = kzalloc(sizeof(struct intel_overlay), GFP_KERNEL);
141802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!overlay)
141902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return;
142079d2427338e8da362678de32a1c8af1dc8a9810aChris Wilson
142179d2427338e8da362678de32a1c8af1dc8a9810aChris Wilson	mutex_lock(&dev->struct_mutex);
142279d2427338e8da362678de32a1c8af1dc8a9810aChris Wilson	if (WARN_ON(dev_priv->overlay))
142379d2427338e8da362678de32a1c8af1dc8a9810aChris Wilson		goto out_free;
142479d2427338e8da362678de32a1c8af1dc8a9810aChris Wilson
142502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	overlay->dev = dev;
142602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
1427ac52bc56de25535a907ef07f8755f1387b89b0f5Daniel Vetter	reg_bo = i915_gem_alloc_object(dev, PAGE_SIZE);
142802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!reg_bo)
142902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		goto out_free;
143005394f3975dceb107a5e1393e2244946e5b43660Chris Wilson	overlay->reg_bo = reg_bo;
143102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
143231578148b2c62612f9516fdcf5ebb64ab32ed12dChris Wilson	if (OVERLAY_NEEDS_PHYSICAL(dev)) {
143302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		ret = i915_gem_attach_phys_object(dev, reg_bo,
14346eeefaf3c86b8937db8ad930c48bfb592fc5e32eChris Wilson						  I915_GEM_PHYS_OVERLAY_REGS,
1435a29301288f1840bdf9c5456da9cd7c944436edd5Chris Wilson						  PAGE_SIZE);
14360206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi		if (ret) {
14370206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi			DRM_ERROR("failed to attach phys overlay regs\n");
14380206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi			goto out_free_bo;
14390206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi		}
144005394f3975dceb107a5e1393e2244946e5b43660Chris Wilson		overlay->flip_addr = reg_bo->phys_obj->handle->busaddr;
144131578148b2c62612f9516fdcf5ebb64ab32ed12dChris Wilson	} else {
144275e9e9158f38e5cb21eff23b30bafa6f32e0a606Daniel Vetter		ret = i915_gem_object_pin(reg_bo, PAGE_SIZE, true);
144302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		if (ret) {
14440206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi			DRM_ERROR("failed to pin overlay register bo\n");
14450206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi			goto out_free_bo;
14460206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi		}
144705394f3975dceb107a5e1393e2244946e5b43660Chris Wilson		overlay->flip_addr = reg_bo->gtt_offset;
14480ddc1289f3ffd779779ddd3922f26ae7d0a21604Chris Wilson
14490ddc1289f3ffd779779ddd3922f26ae7d0a21604Chris Wilson		ret = i915_gem_object_set_to_gtt_domain(reg_bo, true);
14500ddc1289f3ffd779779ddd3922f26ae7d0a21604Chris Wilson		if (ret) {
14510206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi			DRM_ERROR("failed to move overlay register bo into the GTT\n");
14520206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi			goto out_unpin_bo;
14530206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi		}
145402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
145502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
145602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* init all values */
145702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	overlay->color_key = 0x0101fe;
145802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	overlay->brightness = -19;
145902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	overlay->contrast = 75;
146002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	overlay->saturation = 146;
146102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
14628d74f656dd78ae1ba813389cd46197c6329696bcChris Wilson	regs = intel_overlay_map_regs(overlay);
146302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!regs)
146479d2427338e8da362678de32a1c8af1dc8a9810aChris Wilson		goto out_unpin_bo;
146502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
146675020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawsky	memset_io(regs, 0, sizeof(struct overlay_registers));
146702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	update_polyphase_filter(regs);
146802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	update_reg_attrs(overlay, regs);
146902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
14709bb2ff731b32c023e7a502efdc0dee46157290d5Chris Wilson	intel_overlay_unmap_regs(overlay, regs);
147102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
147202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	dev_priv->overlay = overlay;
147379d2427338e8da362678de32a1c8af1dc8a9810aChris Wilson	mutex_unlock(&dev->struct_mutex);
147402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	DRM_INFO("initialized overlay support\n");
147502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return;
147602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
14770ddc1289f3ffd779779ddd3922f26ae7d0a21604Chris Wilsonout_unpin_bo:
147879d2427338e8da362678de32a1c8af1dc8a9810aChris Wilson	if (!OVERLAY_NEEDS_PHYSICAL(dev))
147979d2427338e8da362678de32a1c8af1dc8a9810aChris Wilson		i915_gem_object_unpin(reg_bo);
148002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterout_free_bo:
148105394f3975dceb107a5e1393e2244946e5b43660Chris Wilson	drm_gem_object_unreference(&reg_bo->base);
148202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterout_free:
148379d2427338e8da362678de32a1c8af1dc8a9810aChris Wilson	mutex_unlock(&dev->struct_mutex);
148402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	kfree(overlay);
148502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return;
148602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
148702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
148802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vettervoid intel_cleanup_overlay(struct drm_device *dev)
148902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
1490722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	drm_i915_private_t *dev_priv = dev->dev_private;
149102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
149262cf4e6fef35b4422e206b63b7f0ac90261d4ad9Chris Wilson	if (!dev_priv->overlay)
149362cf4e6fef35b4422e206b63b7f0ac90261d4ad9Chris Wilson		return;
149402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
149562cf4e6fef35b4422e206b63b7f0ac90261d4ad9Chris Wilson	/* The bo's should be free'd by the generic code already.
149662cf4e6fef35b4422e206b63b7f0ac90261d4ad9Chris Wilson	 * Furthermore modesetting teardown happens beforehand so the
149762cf4e6fef35b4422e206b63b7f0ac90261d4ad9Chris Wilson	 * hardware should be off already */
149862cf4e6fef35b4422e206b63b7f0ac90261d4ad9Chris Wilson	BUG_ON(dev_priv->overlay->active);
149962cf4e6fef35b4422e206b63b7f0ac90261d4ad9Chris Wilson
150062cf4e6fef35b4422e206b63b7f0ac90261d4ad9Chris Wilson	drm_gem_object_unreference_unlocked(&dev_priv->overlay->reg_bo->base);
150162cf4e6fef35b4422e206b63b7f0ac90261d4ad9Chris Wilson	kfree(dev_priv->overlay);
150202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
15036ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson
15043bd3c9329973a93fa3ef5e9840f2fd6fa2889e3fChris Wilson#ifdef CONFIG_DEBUG_FS
15053bd3c9329973a93fa3ef5e9840f2fd6fa2889e3fChris Wilson#include <linux/seq_file.h>
15063bd3c9329973a93fa3ef5e9840f2fd6fa2889e3fChris Wilson
15076ef3d4278034982c13df87c4a51e0445f762d316Chris Wilsonstruct intel_overlay_error_state {
15086ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	struct overlay_registers regs;
15096ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	unsigned long base;
15106ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	u32 dovsta;
15116ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	u32 isr;
15126ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson};
15136ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson
151475020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawskystatic struct overlay_registers __iomem *
1515c48c43e422c1404fd72c57d1d21a6f6d01e18900Linus Torvaldsintel_overlay_map_regs_atomic(struct intel_overlay *overlay)
15163bd3c9329973a93fa3ef5e9840f2fd6fa2889e3fChris Wilson{
1517c48c43e422c1404fd72c57d1d21a6f6d01e18900Linus Torvalds	drm_i915_private_t *dev_priv = overlay->dev->dev_private;
151875020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawsky	struct overlay_registers __iomem *regs;
15193bd3c9329973a93fa3ef5e9840f2fd6fa2889e3fChris Wilson
15203bd3c9329973a93fa3ef5e9840f2fd6fa2889e3fChris Wilson	if (OVERLAY_NEEDS_PHYSICAL(overlay->dev))
152175020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawsky		/* Cast to make sparse happy, but it's wc memory anyway, so
152275020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawsky		 * equivalent to the wc io mapping on X86. */
152375020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawsky		regs = (struct overlay_registers __iomem *)
152475020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawsky			overlay->reg_bo->phys_obj->handle->vaddr;
15253bd3c9329973a93fa3ef5e9840f2fd6fa2889e3fChris Wilson	else
15263bd3c9329973a93fa3ef5e9840f2fd6fa2889e3fChris Wilson		regs = io_mapping_map_atomic_wc(dev_priv->mm.gtt_mapping,
1527c48c43e422c1404fd72c57d1d21a6f6d01e18900Linus Torvalds						overlay->reg_bo->gtt_offset);
15283bd3c9329973a93fa3ef5e9840f2fd6fa2889e3fChris Wilson
15293bd3c9329973a93fa3ef5e9840f2fd6fa2889e3fChris Wilson	return regs;
15303bd3c9329973a93fa3ef5e9840f2fd6fa2889e3fChris Wilson}
15313bd3c9329973a93fa3ef5e9840f2fd6fa2889e3fChris Wilson
15323bd3c9329973a93fa3ef5e9840f2fd6fa2889e3fChris Wilsonstatic void intel_overlay_unmap_regs_atomic(struct intel_overlay *overlay,
153375020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawsky					struct overlay_registers __iomem *regs)
15343bd3c9329973a93fa3ef5e9840f2fd6fa2889e3fChris Wilson{
15353bd3c9329973a93fa3ef5e9840f2fd6fa2889e3fChris Wilson	if (!OVERLAY_NEEDS_PHYSICAL(overlay->dev))
1536c48c43e422c1404fd72c57d1d21a6f6d01e18900Linus Torvalds		io_mapping_unmap_atomic(regs);
15373bd3c9329973a93fa3ef5e9840f2fd6fa2889e3fChris Wilson}
15383bd3c9329973a93fa3ef5e9840f2fd6fa2889e3fChris Wilson
15393bd3c9329973a93fa3ef5e9840f2fd6fa2889e3fChris Wilson
15406ef3d4278034982c13df87c4a51e0445f762d316Chris Wilsonstruct intel_overlay_error_state *
15416ef3d4278034982c13df87c4a51e0445f762d316Chris Wilsonintel_overlay_capture_error_state(struct drm_device *dev)
15426ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson{
15430206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	drm_i915_private_t *dev_priv = dev->dev_private;
15446ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	struct intel_overlay *overlay = dev_priv->overlay;
15456ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	struct intel_overlay_error_state *error;
15466ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	struct overlay_registers __iomem *regs;
15476ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson
15486ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	if (!overlay || !overlay->active)
15496ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson		return NULL;
15506ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson
15516ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	error = kmalloc(sizeof(*error), GFP_ATOMIC);
15526ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	if (error == NULL)
15536ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson		return NULL;
15546ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson
15556ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	error->dovsta = I915_READ(DOVSTA);
15566ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	error->isr = I915_READ(ISR);
155731578148b2c62612f9516fdcf5ebb64ab32ed12dChris Wilson	if (OVERLAY_NEEDS_PHYSICAL(overlay->dev))
155875020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawsky		error->base = (__force long)overlay->reg_bo->phys_obj->handle->vaddr;
155931578148b2c62612f9516fdcf5ebb64ab32ed12dChris Wilson	else
156075020bc11c2fa4c060d45b8d0e3f6a37109725bcBen Widawsky		error->base = overlay->reg_bo->gtt_offset;
15616ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson
15626ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	regs = intel_overlay_map_regs_atomic(overlay);
15636ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	if (!regs)
15646ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson		goto err;
15656ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson
15666ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	memcpy_fromio(&error->regs, regs, sizeof(struct overlay_registers));
1567c48c43e422c1404fd72c57d1d21a6f6d01e18900Linus Torvalds	intel_overlay_unmap_regs_atomic(overlay, regs);
15686ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson
15696ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	return error;
15706ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson
15716ef3d4278034982c13df87c4a51e0445f762d316Chris Wilsonerr:
15726ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	kfree(error);
15736ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	return NULL;
15746ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson}
15756ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson
15766ef3d4278034982c13df87c4a51e0445f762d316Chris Wilsonvoid
15776ef3d4278034982c13df87c4a51e0445f762d316Chris Wilsonintel_overlay_print_error_state(struct seq_file *m, struct intel_overlay_error_state *error)
15786ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson{
15796ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	seq_printf(m, "Overlay, status: 0x%08x, interrupt: 0x%08x\n",
15806ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson		   error->dovsta, error->isr);
15816ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	seq_printf(m, "  Register file at 0x%08lx:\n",
15826ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson		   error->base);
15836ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson
15846ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson#define P(x) seq_printf(m, "    " #x ":	0x%08x\n", error->regs.x)
15856ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OBUF_0Y);
15866ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OBUF_1Y);
15876ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OBUF_0U);
15886ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OBUF_0V);
15896ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OBUF_1U);
15906ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OBUF_1V);
15916ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OSTRIDE);
15926ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(YRGB_VPH);
15936ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(UV_VPH);
15946ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(HORZ_PH);
15956ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(INIT_PHS);
15966ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(DWINPOS);
15976ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(DWINSZ);
15986ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(SWIDTH);
15996ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(SWIDTHSW);
16006ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(SHEIGHT);
16016ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(YRGBSCALE);
16026ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(UVSCALE);
16036ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OCLRC0);
16046ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OCLRC1);
16056ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(DCLRKV);
16066ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(DCLRKM);
16076ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(SCLRKVH);
16086ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(SCLRKVL);
16096ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(SCLRKEN);
16106ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OCONFIG);
16116ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OCMD);
16126ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OSTART_0Y);
16136ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OSTART_1Y);
16146ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OSTART_0U);
16156ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OSTART_0V);
16166ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OSTART_1U);
16176ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OSTART_1V);
16186ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OTILEOFF_0Y);
16196ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OTILEOFF_1Y);
16206ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OTILEOFF_0U);
16216ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OTILEOFF_0V);
16226ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OTILEOFF_1U);
16236ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OTILEOFF_1V);
16246ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(FASTHSCALE);
16256ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(UVSCALEV);
16266ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson#undef P
16276ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson}
16283bd3c9329973a93fa3ef5e9840f2fd6fa2889e3fChris Wilson#endif
1629