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
1908d74f656dd78ae1ba813389cd46197c6329696bcChris Wilsonstatic struct overlay_registers *
1918d74f656dd78ae1ba813389cd46197c6329696bcChris Wilsonintel_overlay_map_regs(struct intel_overlay *overlay)
19202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
1930206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	drm_i915_private_t *dev_priv = overlay->dev->dev_private;
19402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct overlay_registers *regs;
19502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
1969bb2ff731b32c023e7a502efdc0dee46157290d5Chris Wilson	if (OVERLAY_NEEDS_PHYSICAL(overlay->dev))
1978d74f656dd78ae1ba813389cd46197c6329696bcChris Wilson		regs = 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,
2069bb2ff731b32c023e7a502efdc0dee46157290d5Chris Wilson				     struct overlay_registers *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;
218b6c028e00445de9dfde2cd0c26521ac53965320aChris Wilson	int ret;
21902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
220b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson	BUG_ON(overlay->last_flip_req);
221db53a302611c06bde01851f61fa0675a84ca018cChris Wilson	ret = i915_add_request(LP_RING(dev_priv), NULL, request);
2223cce469cab880ef8990d2d16d745bf85443fc998Chris Wilson	if (ret) {
2233cce469cab880ef8990d2d16d745bf85443fc998Chris Wilson	    kfree(request);
2243cce469cab880ef8990d2d16d745bf85443fc998Chris Wilson	    return ret;
2253cce469cab880ef8990d2d16d745bf85443fc998Chris Wilson	}
2263cce469cab880ef8990d2d16d745bf85443fc998Chris Wilson	overlay->last_flip_req = request->seqno;
227b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson	overlay->flip_tail = tail;
228b93f9cf14e714c20ce9a544ed1a6070ee7604588Ben Widawsky	ret = i915_wait_request(LP_RING(dev_priv), overlay->last_flip_req,
229b93f9cf14e714c20ce9a544ed1a6070ee7604588Ben Widawsky				true);
230b6c028e00445de9dfde2cd0c26521ac53965320aChris Wilson	if (ret)
23103f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter		return ret;
23202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
23303f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	overlay->last_flip_req = 0;
23402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return 0;
23502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
23602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
237106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson/* Workaround for i830 bug where pipe a must be enable to change control regs */
238106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilsonstatic int
239106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilsoni830_activate_pipe_a(struct drm_device *dev)
24002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
241106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	drm_i915_private_t *dev_priv = dev->dev_private;
242106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	struct intel_crtc *crtc;
243106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	struct drm_crtc_helper_funcs *crtc_funcs;
244106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	struct drm_display_mode vesa_640x480 = {
245106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson		DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 25175, 640, 656,
246106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson			 752, 800, 0, 480, 489, 492, 525, 0,
247106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson			 DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC)
248106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	}, *mode;
249106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson
250106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	crtc = to_intel_crtc(dev_priv->pipe_to_crtc_mapping[0]);
251106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	if (crtc->dpms_mode == DRM_MODE_DPMS_ON)
252106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson		return 0;
25302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
254106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	/* most i8xx have pipe a forced on, so don't trust dpms mode */
2559db4a9c7b2a3bd5b4952846bc0c2f58daa80ddd7Jesse Barnes	if (I915_READ(_PIPEACONF) & PIPECONF_ENABLE)
256106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson		return 0;
25702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
258106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	crtc_funcs = crtc->base.helper_private;
259106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	if (crtc_funcs->dpms == NULL)
260106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson		return 0;
261106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson
262106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	DRM_DEBUG_DRIVER("Enabling pipe A in order to enable overlay\n");
263106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson
264106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	mode = drm_mode_duplicate(dev, &vesa_640x480);
265ca9bfa7eed20ea34e862804e62aae10eb159edbbDaniel Vetter	drm_mode_set_crtcinfo(mode, 0);
2660206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	if (!drm_crtc_helper_set_mode(&crtc->base, mode,
267106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson				       crtc->base.x, crtc->base.y,
268106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson				       crtc->base.fb))
269106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson		return 0;
270106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson
271106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	crtc_funcs->dpms(&crtc->base, DRM_MODE_DPMS_ON);
272106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	return 1;
273106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson}
274106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson
275106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilsonstatic void
276106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilsoni830_deactivate_pipe_a(struct drm_device *dev)
277106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson{
278106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	drm_i915_private_t *dev_priv = dev->dev_private;
279106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[0];
280106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
281106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson
282106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	crtc_funcs->dpms(crtc, DRM_MODE_DPMS_OFF);
28302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
28402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
28502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter/* overlay needs to be disable in OCMD reg */
28602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic int intel_overlay_on(struct intel_overlay *overlay)
28702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
28802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct drm_device *dev = overlay->dev;
289e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson	struct drm_i915_private *dev_priv = dev->dev_private;
2908dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson	struct drm_i915_gem_request *request;
291106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	int pipe_a_quirk = 0;
29202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int ret;
29302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
29402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	BUG_ON(overlay->active);
29503f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	overlay->active = 1;
296b6c028e00445de9dfde2cd0c26521ac53965320aChris Wilson
297106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	if (IS_I830(dev)) {
298106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson		pipe_a_quirk = i830_activate_pipe_a(dev);
299106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson		if (pipe_a_quirk < 0)
300106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson			return pipe_a_quirk;
301106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	}
302106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson
3038dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson	request = kzalloc(sizeof(*request), GFP_KERNEL);
304106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	if (request == NULL) {
305106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson		ret = -ENOMEM;
306106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson		goto out;
307106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	}
30803f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter
309e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson	ret = BEGIN_LP_RING(4);
310e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson	if (ret) {
311e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson		kfree(request);
312e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson		goto out;
313e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson	}
314e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson
31502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_ON);
31602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	OUT_RING(overlay->flip_addr | OFC_UPDATE);
31702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
31802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	OUT_RING(MI_NOOP);
31902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	ADVANCE_LP_RING();
32002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
321ce453d81cb0397aa7d5148984f51907e14072d74Chris Wilson	ret = intel_overlay_do_wait_request(overlay, request, NULL);
322106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilsonout:
323106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	if (pipe_a_quirk)
324106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson		i830_deactivate_pipe_a(dev);
32502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
326106dadacbeeea92f61a2c32f3651ee31c1b34e31Chris Wilson	return ret;
32702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
32802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
32902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter/* overlay needs to be enabled in OCMD reg */
3308dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilsonstatic int intel_overlay_continue(struct intel_overlay *overlay,
3318dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson				  bool load_polyphase_filter)
33202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
33302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct drm_device *dev = overlay->dev;
3340206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	drm_i915_private_t *dev_priv = dev->dev_private;
3358dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson	struct drm_i915_gem_request *request;
33602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	u32 flip_addr = overlay->flip_addr;
33702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	u32 tmp;
338e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson	int ret;
33902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
34002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	BUG_ON(!overlay->active);
34102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
3428dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson	request = kzalloc(sizeof(*request), GFP_KERNEL);
3438dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson	if (request == NULL)
3448dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson		return -ENOMEM;
3458dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson
34602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (load_polyphase_filter)
34702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		flip_addr |= OFC_UPDATE;
34802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
34902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* check for underruns */
35002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	tmp = I915_READ(DOVSTA);
35102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (tmp & (1 << 17))
35202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		DRM_DEBUG("overlay underrun, DOVSTA: %x\n", tmp);
35302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
354e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson	ret = BEGIN_LP_RING(2);
355e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson	if (ret) {
356e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson		kfree(request);
357e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson		return ret;
358e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson	}
35902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_CONTINUE);
36002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	OUT_RING(flip_addr);
3610206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	ADVANCE_LP_RING();
3625a5a0c64a99d7542c48c99d1a8bbb49e665842beDaniel Vetter
363db53a302611c06bde01851f61fa0675a84ca018cChris Wilson	ret = i915_add_request(LP_RING(dev_priv), NULL, request);
3643cce469cab880ef8990d2d16d745bf85443fc998Chris Wilson	if (ret) {
3653cce469cab880ef8990d2d16d745bf85443fc998Chris Wilson		kfree(request);
3663cce469cab880ef8990d2d16d745bf85443fc998Chris Wilson		return ret;
3673cce469cab880ef8990d2d16d745bf85443fc998Chris Wilson	}
3683cce469cab880ef8990d2d16d745bf85443fc998Chris Wilson
3693cce469cab880ef8990d2d16d745bf85443fc998Chris Wilson	overlay->last_flip_req = request->seqno;
3708dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson	return 0;
3715a5a0c64a99d7542c48c99d1a8bbb49e665842beDaniel Vetter}
3725a5a0c64a99d7542c48c99d1a8bbb49e665842beDaniel Vetter
373b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilsonstatic void intel_overlay_release_old_vid_tail(struct intel_overlay *overlay)
3745a5a0c64a99d7542c48c99d1a8bbb49e665842beDaniel Vetter{
37505394f3975dceb107a5e1393e2244946e5b43660Chris Wilson	struct drm_i915_gem_object *obj = overlay->old_vid_bo;
3765a5a0c64a99d7542c48c99d1a8bbb49e665842beDaniel Vetter
377b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson	i915_gem_object_unpin(obj);
37805394f3975dceb107a5e1393e2244946e5b43660Chris Wilson	drm_gem_object_unreference(&obj->base);
3795a5a0c64a99d7542c48c99d1a8bbb49e665842beDaniel Vetter
380b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson	overlay->old_vid_bo = NULL;
381b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson}
38203f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter
383b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilsonstatic void intel_overlay_off_tail(struct intel_overlay *overlay)
384b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson{
38505394f3975dceb107a5e1393e2244946e5b43660Chris Wilson	struct drm_i915_gem_object *obj = overlay->vid_bo;
38602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
387b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson	/* never have the overlay hw on without showing a frame */
388b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson	BUG_ON(!overlay->vid_bo);
38902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
390b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson	i915_gem_object_unpin(obj);
39105394f3975dceb107a5e1393e2244946e5b43660Chris Wilson	drm_gem_object_unreference(&obj->base);
392b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson	overlay->vid_bo = NULL;
39303f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter
394b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson	overlay->crtc->overlay = NULL;
395b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson	overlay->crtc = NULL;
396b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson	overlay->active = 0;
39702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
39802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
39902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter/* overlay needs to be disabled in OCMD reg */
400ce453d81cb0397aa7d5148984f51907e14072d74Chris Wilsonstatic int intel_overlay_off(struct intel_overlay *overlay)
40102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
40202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct drm_device *dev = overlay->dev;
403e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson	struct drm_i915_private *dev_priv = dev->dev_private;
4048dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson	u32 flip_addr = overlay->flip_addr;
4058dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson	struct drm_i915_gem_request *request;
406e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson	int ret;
40702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
40802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	BUG_ON(!overlay->active);
40902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
4108dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson	request = kzalloc(sizeof(*request), GFP_KERNEL);
4118dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson	if (request == NULL)
4128dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson		return -ENOMEM;
4138dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson
41402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* According to intel docs the overlay hw may hang (when switching
41502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	 * off) without loading the filter coeffs. It is however unclear whether
41602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	 * this applies to the disabling of the overlay or to the switching off
41702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	 * of the hw. Do it in both cases */
41802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	flip_addr |= OFC_UPDATE;
41902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
420e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson	ret = BEGIN_LP_RING(6);
421e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson	if (ret) {
422e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson		kfree(request);
423e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson		return ret;
424e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson	}
42502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* wait for overlay to go idle */
42602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_CONTINUE);
42702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	OUT_RING(flip_addr);
428722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
42902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* turn overlay off */
430722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_OFF);
43102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	OUT_RING(flip_addr);
432722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
43302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	ADVANCE_LP_RING();
43402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
435ce453d81cb0397aa7d5148984f51907e14072d74Chris Wilson	return intel_overlay_do_wait_request(overlay, request,
436b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson					     intel_overlay_off_tail);
43712ca45fea91cfbb09df828bea958b47348caee6dDaniel Vetter}
43812ca45fea91cfbb09df828bea958b47348caee6dDaniel Vetter
43903f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter/* recover from an interruption due to a signal
44003f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter * We have to be careful not to repeat work forever an make forward progess. */
441ce453d81cb0397aa7d5148984f51907e14072d74Chris Wilsonstatic int intel_overlay_recover_from_interrupt(struct intel_overlay *overlay)
44203f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter{
44303f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	struct drm_device *dev = overlay->dev;
444852835f343146a82a528c3b712b373661d4fa17aZou Nan hai	drm_i915_private_t *dev_priv = dev->dev_private;
44503f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	int ret;
44603f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter
447b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson	if (overlay->last_flip_req == 0)
448b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson		return 0;
44903f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter
450b93f9cf14e714c20ce9a544ed1a6070ee7604588Ben Widawsky	ret = i915_wait_request(LP_RING(dev_priv), overlay->last_flip_req,
451b93f9cf14e714c20ce9a544ed1a6070ee7604588Ben Widawsky				true);
452b6c028e00445de9dfde2cd0c26521ac53965320aChris Wilson	if (ret)
45303f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter		return ret;
45403f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter
455b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson	if (overlay->flip_tail)
456b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson		overlay->flip_tail(overlay);
45703f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter
45803f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	overlay->last_flip_req = 0;
45903f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	return 0;
46003f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter}
46103f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter
4625a5a0c64a99d7542c48c99d1a8bbb49e665842beDaniel Vetter/* Wait for pending overlay flip and release old frame.
4635a5a0c64a99d7542c48c99d1a8bbb49e665842beDaniel Vetter * Needs to be called before the overlay register are changed
4648d74f656dd78ae1ba813389cd46197c6329696bcChris Wilson * via intel_overlay_(un)map_regs
4658d74f656dd78ae1ba813389cd46197c6329696bcChris Wilson */
46602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic int intel_overlay_release_old_vid(struct intel_overlay *overlay)
46702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
4685cd68c9864d65e49c910c701716e4e94e09f7ce0Chris Wilson	struct drm_device *dev = overlay->dev;
4695cd68c9864d65e49c910c701716e4e94e09f7ce0Chris Wilson	drm_i915_private_t *dev_priv = dev->dev_private;
47002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int ret;
47102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
4725cd68c9864d65e49c910c701716e4e94e09f7ce0Chris Wilson	/* Only wait if there is actually an old frame to release to
4735cd68c9864d65e49c910c701716e4e94e09f7ce0Chris Wilson	 * guarantee forward progress.
4745cd68c9864d65e49c910c701716e4e94e09f7ce0Chris Wilson	 */
47503f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	if (!overlay->old_vid_bo)
47603f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter		return 0;
47703f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter
4785cd68c9864d65e49c910c701716e4e94e09f7ce0Chris Wilson	if (I915_READ(ISR) & I915_OVERLAY_PLANE_FLIP_PENDING_INTERRUPT) {
4798dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson		struct drm_i915_gem_request *request;
48002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
4815cd68c9864d65e49c910c701716e4e94e09f7ce0Chris Wilson		/* synchronous slowpath */
4828dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson		request = kzalloc(sizeof(*request), GFP_KERNEL);
4838dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson		if (request == NULL)
4848dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson			return -ENOMEM;
48502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
486e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson		ret = BEGIN_LP_RING(2);
487e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson		if (ret) {
488e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson			kfree(request);
489e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson			return ret;
490e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson		}
491e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson
4925cd68c9864d65e49c910c701716e4e94e09f7ce0Chris Wilson		OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
4935cd68c9864d65e49c910c701716e4e94e09f7ce0Chris Wilson		OUT_RING(MI_NOOP);
4945cd68c9864d65e49c910c701716e4e94e09f7ce0Chris Wilson		ADVANCE_LP_RING();
4955cd68c9864d65e49c910c701716e4e94e09f7ce0Chris Wilson
496ce453d81cb0397aa7d5148984f51907e14072d74Chris Wilson		ret = intel_overlay_do_wait_request(overlay, request,
497b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson						    intel_overlay_release_old_vid_tail);
4985cd68c9864d65e49c910c701716e4e94e09f7ce0Chris Wilson		if (ret)
4995cd68c9864d65e49c910c701716e4e94e09f7ce0Chris Wilson			return ret;
5005cd68c9864d65e49c910c701716e4e94e09f7ce0Chris Wilson	}
50102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
5025cd68c9864d65e49c910c701716e4e94e09f7ce0Chris Wilson	intel_overlay_release_old_vid_tail(overlay);
50302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return 0;
50402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
50502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
50602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstruct put_image_params {
50702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int format;
50802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	short dst_x;
50902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	short dst_y;
51002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	short dst_w;
51102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	short dst_h;
51202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	short src_w;
51302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	short src_scan_h;
51402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	short src_scan_w;
51502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	short src_h;
51602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	short stride_Y;
51702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	short stride_UV;
51802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int offset_Y;
51902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int offset_U;
52002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int offset_V;
52102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter};
52202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
52302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic int packed_depth_bytes(u32 format)
52402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
52502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	switch (format & I915_OVERLAY_DEPTH_MASK) {
526722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case I915_OVERLAY_YUV422:
527722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		return 4;
528722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case I915_OVERLAY_YUV411:
529722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		/* return 6; not implemented */
530722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	default:
531722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		return -EINVAL;
53202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
53302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
53402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
53502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic int packed_width_bytes(u32 format, short width)
53602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
53702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	switch (format & I915_OVERLAY_DEPTH_MASK) {
538722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case I915_OVERLAY_YUV422:
539722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		return width << 1;
540722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	default:
541722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		return -EINVAL;
54202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
54302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
54402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
54502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic int uv_hsubsampling(u32 format)
54602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
54702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	switch (format & I915_OVERLAY_DEPTH_MASK) {
548722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case I915_OVERLAY_YUV422:
549722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case I915_OVERLAY_YUV420:
550722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		return 2;
551722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case I915_OVERLAY_YUV411:
552722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case I915_OVERLAY_YUV410:
553722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		return 4;
554722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	default:
555722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		return -EINVAL;
55602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
55702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
55802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
55902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic int uv_vsubsampling(u32 format)
56002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
56102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	switch (format & I915_OVERLAY_DEPTH_MASK) {
562722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case I915_OVERLAY_YUV420:
563722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case I915_OVERLAY_YUV410:
564722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		return 2;
565722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case I915_OVERLAY_YUV422:
566722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case I915_OVERLAY_YUV411:
567722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		return 1;
568722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	default:
569722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		return -EINVAL;
57002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
57102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
57202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
57302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic u32 calc_swidthsw(struct drm_device *dev, u32 offset, u32 width)
57402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
57502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	u32 mask, shift, ret;
576a6c45cf013a57e32ddae43dd4ac911eb4a3919fdChris Wilson	if (IS_GEN2(dev)) {
57702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		mask = 0x1f;
57802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		shift = 5;
579a6c45cf013a57e32ddae43dd4ac911eb4a3919fdChris Wilson	} else {
580a6c45cf013a57e32ddae43dd4ac911eb4a3919fdChris Wilson		mask = 0x3f;
581a6c45cf013a57e32ddae43dd4ac911eb4a3919fdChris Wilson		shift = 6;
58202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
58302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	ret = ((offset + width + mask) >> shift) - (offset >> shift);
584a6c45cf013a57e32ddae43dd4ac911eb4a3919fdChris Wilson	if (!IS_GEN2(dev))
58502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		ret <<= 1;
5860206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	ret -= 1;
58702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return ret << 2;
58802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
58902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
59002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic const u16 y_static_hcoeffs[N_HORIZ_Y_TAPS * N_PHASES] = {
59102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3000, 0xb4a0, 0x1930, 0x1920, 0xb4a0,
59202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3000, 0xb500, 0x19d0, 0x1880, 0xb440,
59302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3000, 0xb540, 0x1a88, 0x2f80, 0xb3e0,
59402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3000, 0xb580, 0x1b30, 0x2e20, 0xb380,
59502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3000, 0xb5c0, 0x1bd8, 0x2cc0, 0xb320,
59602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3020, 0xb5e0, 0x1c60, 0x2b80, 0xb2c0,
59702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3020, 0xb5e0, 0x1cf8, 0x2a20, 0xb260,
59802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3020, 0xb5e0, 0x1d80, 0x28e0, 0xb200,
59902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3020, 0xb5c0, 0x1e08, 0x3f40, 0xb1c0,
60002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3020, 0xb580, 0x1e78, 0x3ce0, 0xb160,
60102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3040, 0xb520, 0x1ed8, 0x3aa0, 0xb120,
60202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3040, 0xb4a0, 0x1f30, 0x3880, 0xb0e0,
60302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3040, 0xb400, 0x1f78, 0x3680, 0xb0a0,
60402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3020, 0xb340, 0x1fb8, 0x34a0, 0xb060,
60502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3020, 0xb240, 0x1fe0, 0x32e0, 0xb040,
60602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3020, 0xb140, 0x1ff8, 0x3160, 0xb020,
607722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	0xb000, 0x3000, 0x0800, 0x3000, 0xb000
608722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson};
609722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson
61002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic const u16 uv_static_hcoeffs[N_HORIZ_UV_TAPS * N_PHASES] = {
61102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0x3000, 0x1800, 0x1800, 0xb000, 0x18d0, 0x2e60,
61202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0xb000, 0x1990, 0x2ce0, 0xb020, 0x1a68, 0x2b40,
61302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0xb040, 0x1b20, 0x29e0, 0xb060, 0x1bd8, 0x2880,
61402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0xb080, 0x1c88, 0x3e60, 0xb0a0, 0x1d28, 0x3c00,
61502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0xb0c0, 0x1db8, 0x39e0, 0xb0e0, 0x1e40, 0x37e0,
61602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0xb100, 0x1eb8, 0x3620, 0xb100, 0x1f18, 0x34a0,
61702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0xb100, 0x1f68, 0x3360, 0xb0e0, 0x1fa8, 0x3240,
61802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	0xb0c0, 0x1fe0, 0x3140, 0xb060, 0x1ff0, 0x30a0,
619722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	0x3000, 0x0800, 0x3000
620722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson};
62102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
62202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic void update_polyphase_filter(struct overlay_registers *regs)
62302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
62402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	memcpy(regs->Y_HCOEFS, y_static_hcoeffs, sizeof(y_static_hcoeffs));
62502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	memcpy(regs->UV_HCOEFS, uv_static_hcoeffs, sizeof(uv_static_hcoeffs));
62602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
62702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
62802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic bool update_scaling_factors(struct intel_overlay *overlay,
62902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				   struct overlay_registers *regs,
63002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				   struct put_image_params *params)
63102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
63202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* fixed point with a 12 bit shift */
63302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	u32 xscale, yscale, xscale_UV, yscale_UV;
63402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define FP_SHIFT 12
63502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter#define FRACT_MASK 0xfff
63602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	bool scale_changed = false;
63702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int uv_hscale = uv_hsubsampling(params->format);
63802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int uv_vscale = uv_vsubsampling(params->format);
63902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
64002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (params->dst_w > 1)
64102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		xscale = ((params->src_scan_w - 1) << FP_SHIFT)
64202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			/(params->dst_w);
64302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	else
64402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		xscale = 1 << FP_SHIFT;
64502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
64602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (params->dst_h > 1)
64702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		yscale = ((params->src_scan_h - 1) << FP_SHIFT)
64802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			/(params->dst_h);
64902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	else
65002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		yscale = 1 << FP_SHIFT;
65102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
65202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/*if (params->format & I915_OVERLAY_YUV_PLANAR) {*/
653722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	xscale_UV = xscale/uv_hscale;
654722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	yscale_UV = yscale/uv_vscale;
655722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	/* make the Y scale to UV scale ratio an exact multiply */
656722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	xscale = xscale_UV * uv_hscale;
657722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	yscale = yscale_UV * uv_vscale;
65802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/*} else {
659722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	  xscale_UV = 0;
660722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	  yscale_UV = 0;
661722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	  }*/
66202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
66302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (xscale != overlay->old_xscale || yscale != overlay->old_yscale)
66402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		scale_changed = true;
66502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	overlay->old_xscale = xscale;
66602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	overlay->old_yscale = yscale;
66702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
668722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	regs->YRGBSCALE = (((yscale & FRACT_MASK) << 20) |
669722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			   ((xscale >> FP_SHIFT)  << 16) |
670722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			   ((xscale & FRACT_MASK) << 3));
671722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson
672722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	regs->UVSCALE = (((yscale_UV & FRACT_MASK) << 20) |
673722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			 ((xscale_UV >> FP_SHIFT)  << 16) |
674722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			 ((xscale_UV & FRACT_MASK) << 3));
675722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson
676722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	regs->UVSCALEV = ((((yscale    >> FP_SHIFT) << 16) |
677722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			   ((yscale_UV >> FP_SHIFT) << 0)));
67802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
67902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (scale_changed)
68002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		update_polyphase_filter(regs);
68102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
68202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return scale_changed;
68302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
68402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
68502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic void update_colorkey(struct intel_overlay *overlay,
68602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			    struct overlay_registers *regs)
68702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
68802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	u32 key = overlay->color_key;
6896ba3ddd9838f5e4d6ac7c6dce95648d205e11bffChris Wilson
69002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	switch (overlay->crtc->base.fb->bits_per_pixel) {
691722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case 8:
692722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		regs->DCLRKV = 0;
693722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		regs->DCLRKM = CLK_RGB8I_MASK | DST_KEY_ENABLE;
6946ba3ddd9838f5e4d6ac7c6dce95648d205e11bffChris Wilson		break;
6956ba3ddd9838f5e4d6ac7c6dce95648d205e11bffChris Wilson
696722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case 16:
697722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		if (overlay->crtc->base.fb->depth == 15) {
698722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			regs->DCLRKV = RGB15_TO_COLORKEY(key);
699722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			regs->DCLRKM = CLK_RGB15_MASK | DST_KEY_ENABLE;
700722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		} else {
701722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			regs->DCLRKV = RGB16_TO_COLORKEY(key);
702722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			regs->DCLRKM = CLK_RGB16_MASK | DST_KEY_ENABLE;
703722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		}
7046ba3ddd9838f5e4d6ac7c6dce95648d205e11bffChris Wilson		break;
7056ba3ddd9838f5e4d6ac7c6dce95648d205e11bffChris Wilson
706722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case 24:
707722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case 32:
708722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		regs->DCLRKV = key;
709722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		regs->DCLRKM = CLK_RGB24_MASK | DST_KEY_ENABLE;
7106ba3ddd9838f5e4d6ac7c6dce95648d205e11bffChris Wilson		break;
71102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
71202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
71302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
71402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic u32 overlay_cmd_reg(struct put_image_params *params)
71502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
71602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	u32 cmd = OCMD_ENABLE | OCMD_BUF_TYPE_FRAME | OCMD_BUFFER0;
71702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
71802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (params->format & I915_OVERLAY_YUV_PLANAR) {
71902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		switch (params->format & I915_OVERLAY_DEPTH_MASK) {
720722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		case I915_OVERLAY_YUV422:
721722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			cmd |= OCMD_YUV_422_PLANAR;
722722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			break;
723722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		case I915_OVERLAY_YUV420:
724722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			cmd |= OCMD_YUV_420_PLANAR;
725722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			break;
726722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		case I915_OVERLAY_YUV411:
727722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		case I915_OVERLAY_YUV410:
728722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			cmd |= OCMD_YUV_410_PLANAR;
729722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			break;
73002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		}
73102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	} else { /* YUV packed */
73202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		switch (params->format & I915_OVERLAY_DEPTH_MASK) {
733722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		case I915_OVERLAY_YUV422:
734722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			cmd |= OCMD_YUV_422_PACKED;
735722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			break;
736722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		case I915_OVERLAY_YUV411:
737722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			cmd |= OCMD_YUV_411_PACKED;
738722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			break;
73902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		}
74002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
74102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		switch (params->format & I915_OVERLAY_SWAP_MASK) {
742722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		case I915_OVERLAY_NO_SWAP:
743722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			break;
744722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		case I915_OVERLAY_UV_SWAP:
745722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			cmd |= OCMD_UV_SWAP;
746722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			break;
747722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		case I915_OVERLAY_Y_SWAP:
748722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			cmd |= OCMD_Y_SWAP;
749722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			break;
750722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		case I915_OVERLAY_Y_AND_UV_SWAP:
751722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			cmd |= OCMD_Y_AND_UV_SWAP;
752722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			break;
75302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		}
75402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
75502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
75602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return cmd;
75702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
75802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
7595fe82c5ee1ba2d04183c376038c5d233a0311ec9Chris Wilsonstatic int intel_overlay_do_put_image(struct intel_overlay *overlay,
76005394f3975dceb107a5e1393e2244946e5b43660Chris Wilson				      struct drm_i915_gem_object *new_bo,
7615fe82c5ee1ba2d04183c376038c5d233a0311ec9Chris Wilson				      struct put_image_params *params)
76202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
76302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int ret, tmp_width;
76402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct overlay_registers *regs;
76502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	bool scale_changed = false;
76602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct drm_device *dev = overlay->dev;
76702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
76802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	BUG_ON(!mutex_is_locked(&dev->struct_mutex));
76902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	BUG_ON(!mutex_is_locked(&dev->mode_config.mutex));
77002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	BUG_ON(!overlay);
77102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
77202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	ret = intel_overlay_release_old_vid(overlay);
77302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (ret != 0)
77402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return ret;
77502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
7762da3b9b940e2a18147422c54ed8b29d01e1ade88Chris Wilson	ret = i915_gem_object_pin_to_display_plane(new_bo, 0, NULL);
77702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (ret != 0)
77802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return ret;
77902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
780d9e86c0ee60f323e890484628f351bf50fa9a15dChris Wilson	ret = i915_gem_object_put_fence(new_bo);
781d9e86c0ee60f323e890484628f351bf50fa9a15dChris Wilson	if (ret)
782d9e86c0ee60f323e890484628f351bf50fa9a15dChris Wilson		goto out_unpin;
783d9e86c0ee60f323e890484628f351bf50fa9a15dChris Wilson
78402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!overlay->active) {
7858d74f656dd78ae1ba813389cd46197c6329696bcChris Wilson		regs = intel_overlay_map_regs(overlay);
78602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		if (!regs) {
78702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			ret = -ENOMEM;
78802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			goto out_unpin;
78902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		}
79002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		regs->OCONFIG = OCONF_CC_OUT_8BIT;
791a6c45cf013a57e32ddae43dd4ac911eb4a3919fdChris Wilson		if (IS_GEN4(overlay->dev))
79202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			regs->OCONFIG |= OCONF_CSC_MODE_BT709;
79302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		regs->OCONFIG |= overlay->crtc->pipe == 0 ?
79402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			OCONF_PIPE_A : OCONF_PIPE_B;
7959bb2ff731b32c023e7a502efdc0dee46157290d5Chris Wilson		intel_overlay_unmap_regs(overlay, regs);
79602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
79702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		ret = intel_overlay_on(overlay);
79802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		if (ret != 0)
79902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			goto out_unpin;
80002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
80102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
8028d74f656dd78ae1ba813389cd46197c6329696bcChris Wilson	regs = intel_overlay_map_regs(overlay);
80302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!regs) {
80402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		ret = -ENOMEM;
80502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		goto out_unpin;
80602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
80702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
80802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	regs->DWINPOS = (params->dst_y << 16) | params->dst_x;
80902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	regs->DWINSZ = (params->dst_h << 16) | params->dst_w;
81002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
81102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (params->format & I915_OVERLAY_YUV_PACKED)
81202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		tmp_width = packed_width_bytes(params->format, params->src_w);
81302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	else
81402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		tmp_width = params->src_w;
81502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
81602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	regs->SWIDTH = params->src_w;
81702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	regs->SWIDTHSW = calc_swidthsw(overlay->dev,
818722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson				       params->offset_Y, tmp_width);
81902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	regs->SHEIGHT = params->src_h;
8200206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	regs->OBUF_0Y = new_bo->gtt_offset + params->offset_Y;
82102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	regs->OSTRIDE = params->stride_Y;
82202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
82302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (params->format & I915_OVERLAY_YUV_PLANAR) {
82402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		int uv_hscale = uv_hsubsampling(params->format);
82502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		int uv_vscale = uv_vsubsampling(params->format);
82602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		u32 tmp_U, tmp_V;
82702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		regs->SWIDTH |= (params->src_w/uv_hscale) << 16;
82802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		tmp_U = calc_swidthsw(overlay->dev, params->offset_U,
829722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson				      params->src_w/uv_hscale);
83002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		tmp_V = calc_swidthsw(overlay->dev, params->offset_V,
831722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson				      params->src_w/uv_hscale);
83202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		regs->SWIDTHSW |= max_t(u32, tmp_U, tmp_V) << 16;
83302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		regs->SHEIGHT |= (params->src_h/uv_vscale) << 16;
83405394f3975dceb107a5e1393e2244946e5b43660Chris Wilson		regs->OBUF_0U = new_bo->gtt_offset + params->offset_U;
83505394f3975dceb107a5e1393e2244946e5b43660Chris Wilson		regs->OBUF_0V = new_bo->gtt_offset + params->offset_V;
83602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		regs->OSTRIDE |= params->stride_UV << 16;
83702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
83802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
83902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	scale_changed = update_scaling_factors(overlay, regs, params);
84002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
84102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	update_colorkey(overlay, regs);
84202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
84302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	regs->OCMD = overlay_cmd_reg(params);
84402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
8459bb2ff731b32c023e7a502efdc0dee46157290d5Chris Wilson	intel_overlay_unmap_regs(overlay, regs);
84602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
8478dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson	ret = intel_overlay_continue(overlay, scale_changed);
8488dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson	if (ret)
8498dc5d14741dc1ee0074a14b360993a10c2c02d24Chris Wilson		goto out_unpin;
85002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
85102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	overlay->old_vid_bo = overlay->vid_bo;
85205394f3975dceb107a5e1393e2244946e5b43660Chris Wilson	overlay->vid_bo = new_bo;
85302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
85402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return 0;
85502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
85602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterout_unpin:
85702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	i915_gem_object_unpin(new_bo);
85802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return ret;
85902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
86002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
861ce453d81cb0397aa7d5148984f51907e14072d74Chris Wilsonint intel_overlay_switch_off(struct intel_overlay *overlay)
86202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
86302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct overlay_registers *regs;
86402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct drm_device *dev = overlay->dev;
8655dcdbcb06badbdf2faa698bf3198e421a1e12840Chris Wilson	int ret;
86602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
86702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	BUG_ON(!mutex_is_locked(&dev->struct_mutex));
86802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	BUG_ON(!mutex_is_locked(&dev->mode_config.mutex));
86902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
870ce453d81cb0397aa7d5148984f51907e14072d74Chris Wilson	ret = intel_overlay_recover_from_interrupt(overlay);
871b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson	if (ret != 0)
872b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson		return ret;
8739bedb9743fd906e4160468663ee6e1bbdc4412b8Daniel Vetter
87402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!overlay->active)
87502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return 0;
87602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
87702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	ret = intel_overlay_release_old_vid(overlay);
87802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (ret != 0)
87902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return ret;
88002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
8818d74f656dd78ae1ba813389cd46197c6329696bcChris Wilson	regs = intel_overlay_map_regs(overlay);
88202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	regs->OCMD = 0;
8839bb2ff731b32c023e7a502efdc0dee46157290d5Chris Wilson	intel_overlay_unmap_regs(overlay, regs);
88402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
885ce453d81cb0397aa7d5148984f51907e14072d74Chris Wilson	ret = intel_overlay_off(overlay);
88603f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter	if (ret != 0)
88703f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter		return ret;
88803f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter
88912ca45fea91cfbb09df828bea958b47348caee6dDaniel Vetter	intel_overlay_off_tail(overlay);
89002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return 0;
89102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
89202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
89302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic int check_overlay_possible_on_crtc(struct intel_overlay *overlay,
89402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter					  struct intel_crtc *crtc)
89502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
896722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	drm_i915_private_t *dev_priv = overlay->dev->dev_private;
89702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
898f7abfe8b281991c66406c42c1a6c6c9ee0daa0ffChris Wilson	if (!crtc->active)
89902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EINVAL;
90002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
90102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* can't use the overlay with double wide pipe */
902a6c45cf013a57e32ddae43dd4ac911eb4a3919fdChris Wilson	if (INTEL_INFO(overlay->dev)->gen < 4 &&
903f7abfe8b281991c66406c42c1a6c6c9ee0daa0ffChris Wilson	    (I915_READ(PIPECONF(crtc->pipe)) & (PIPECONF_DOUBLE_WIDE | PIPECONF_ENABLE)) != PIPECONF_ENABLE)
90402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EINVAL;
90502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
90602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return 0;
90702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
90802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
90902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic void update_pfit_vscale_ratio(struct intel_overlay *overlay)
91002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
91102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct drm_device *dev = overlay->dev;
912722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	drm_i915_private_t *dev_priv = dev->dev_private;
91302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	u32 pfit_control = I915_READ(PFIT_CONTROL);
914446d2183af68c0fd2772f5ef97a033efe69904a5Chris Wilson	u32 ratio;
91502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
91602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* XXX: This is not the same logic as in the xorg driver, but more in
917446d2183af68c0fd2772f5ef97a033efe69904a5Chris Wilson	 * line with the intel documentation for the i965
918446d2183af68c0fd2772f5ef97a033efe69904a5Chris Wilson	 */
919a6c45cf013a57e32ddae43dd4ac911eb4a3919fdChris Wilson	if (INTEL_INFO(dev)->gen >= 4) {
9200206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi		/* on i965 use the PGM reg to read out the autoscaler values */
921a6c45cf013a57e32ddae43dd4ac911eb4a3919fdChris Wilson		ratio = I915_READ(PFIT_PGM_RATIOS) >> PFIT_VERT_SCALE_SHIFT_965;
922a6c45cf013a57e32ddae43dd4ac911eb4a3919fdChris Wilson	} else {
923446d2183af68c0fd2772f5ef97a033efe69904a5Chris Wilson		if (pfit_control & VERT_AUTO_SCALE)
924446d2183af68c0fd2772f5ef97a033efe69904a5Chris Wilson			ratio = I915_READ(PFIT_AUTO_RATIOS);
92502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		else
926446d2183af68c0fd2772f5ef97a033efe69904a5Chris Wilson			ratio = I915_READ(PFIT_PGM_RATIOS);
927446d2183af68c0fd2772f5ef97a033efe69904a5Chris Wilson		ratio >>= PFIT_VERT_SCALE_SHIFT;
92802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
92902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
93002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	overlay->pfit_vscale_ratio = ratio;
93102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
93202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
93302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic int check_overlay_dst(struct intel_overlay *overlay,
93402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			     struct drm_intel_overlay_put_image *rec)
93502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
93602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct drm_display_mode *mode = &overlay->crtc->base.mode;
93702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
93875c13993db592343bda1fd62f2555fea037d56bdDaniel Vetter	if (rec->dst_x < mode->hdisplay &&
93975c13993db592343bda1fd62f2555fea037d56bdDaniel Vetter	    rec->dst_x + rec->dst_width <= mode->hdisplay &&
94075c13993db592343bda1fd62f2555fea037d56bdDaniel Vetter	    rec->dst_y < mode->vdisplay &&
94175c13993db592343bda1fd62f2555fea037d56bdDaniel Vetter	    rec->dst_y + rec->dst_height <= mode->vdisplay)
94202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return 0;
94302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	else
94402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EINVAL;
94502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
94602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
94702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic int check_overlay_scaling(struct put_image_params *rec)
94802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
94902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	u32 tmp;
95002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
95102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* downscaling limit is 8.0 */
95202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	tmp = ((rec->src_scan_h << 16) / rec->dst_h) >> 16;
95302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (tmp > 7)
95402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EINVAL;
95502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	tmp = ((rec->src_scan_w << 16) / rec->dst_w) >> 16;
95602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (tmp > 7)
95702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EINVAL;
95802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
95902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return 0;
96002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
96102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
96202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic int check_overlay_src(struct drm_device *dev,
96302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			     struct drm_intel_overlay_put_image *rec,
96405394f3975dceb107a5e1393e2244946e5b43660Chris Wilson			     struct drm_i915_gem_object *new_bo)
96502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
96602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int uv_hscale = uv_hsubsampling(rec->flags);
96702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int uv_vscale = uv_vsubsampling(rec->flags);
9688f28f54aad8bcf52a47afb6447fac34f96597b6fDan Carpenter	u32 stride_mask;
9698f28f54aad8bcf52a47afb6447fac34f96597b6fDan Carpenter	int depth;
9708f28f54aad8bcf52a47afb6447fac34f96597b6fDan Carpenter	u32 tmp;
97102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
97202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* check src dimensions */
97302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (IS_845G(dev) || IS_I830(dev)) {
974722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		if (rec->src_height > IMAGE_MAX_HEIGHT_LEGACY ||
9759f7c3f442bb7c0d0a0ed25cc287932450a1f2babChris Wilson		    rec->src_width  > IMAGE_MAX_WIDTH_LEGACY)
97602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			return -EINVAL;
97702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	} else {
978722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		if (rec->src_height > IMAGE_MAX_HEIGHT ||
9799f7c3f442bb7c0d0a0ed25cc287932450a1f2babChris Wilson		    rec->src_width  > IMAGE_MAX_WIDTH)
98002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			return -EINVAL;
98102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
9829f7c3f442bb7c0d0a0ed25cc287932450a1f2babChris Wilson
98302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* better safe than sorry, use 4 as the maximal subsampling ratio */
984722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	if (rec->src_height < N_VERT_Y_TAPS*4 ||
9859f7c3f442bb7c0d0a0ed25cc287932450a1f2babChris Wilson	    rec->src_width  < N_HORIZ_Y_TAPS*4)
98602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EINVAL;
98702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
988a1efd14a99483a4fb9308902397ed86b69454c99Chris Wilson	/* check alignment constraints */
98902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	switch (rec->flags & I915_OVERLAY_TYPE_MASK) {
990722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case I915_OVERLAY_RGB:
991722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		/* not implemented */
992722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		return -EINVAL;
9939f7c3f442bb7c0d0a0ed25cc287932450a1f2babChris Wilson
994722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case I915_OVERLAY_YUV_PACKED:
995722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		if (uv_vscale != 1)
99602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			return -EINVAL;
9979f7c3f442bb7c0d0a0ed25cc287932450a1f2babChris Wilson
9989f7c3f442bb7c0d0a0ed25cc287932450a1f2babChris Wilson		depth = packed_depth_bytes(rec->flags);
999722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		if (depth < 0)
1000722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			return depth;
10019f7c3f442bb7c0d0a0ed25cc287932450a1f2babChris Wilson
1002722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		/* ignore UV planes */
1003722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		rec->stride_UV = 0;
1004722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		rec->offset_U = 0;
1005722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		rec->offset_V = 0;
1006722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		/* check pixel alignment */
1007722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		if (rec->offset_Y % depth)
1008722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			return -EINVAL;
1009722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		break;
10109f7c3f442bb7c0d0a0ed25cc287932450a1f2babChris Wilson
1011722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case I915_OVERLAY_YUV_PLANAR:
1012722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		if (uv_vscale < 0 || uv_hscale < 0)
101302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			return -EINVAL;
1014722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		/* no offset restrictions for planar formats */
1015722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		break;
10169f7c3f442bb7c0d0a0ed25cc287932450a1f2babChris Wilson
1017722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	default:
1018722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		return -EINVAL;
101902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
102002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
102102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (rec->src_width % uv_hscale)
102202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EINVAL;
102302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
102402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* stride checking */
1025a1efd14a99483a4fb9308902397ed86b69454c99Chris Wilson	if (IS_I830(dev) || IS_845G(dev))
1026a1efd14a99483a4fb9308902397ed86b69454c99Chris Wilson		stride_mask = 255;
1027a1efd14a99483a4fb9308902397ed86b69454c99Chris Wilson	else
1028a1efd14a99483a4fb9308902397ed86b69454c99Chris Wilson		stride_mask = 63;
102902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
103002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (rec->stride_Y & stride_mask || rec->stride_UV & stride_mask)
103102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EINVAL;
1032a6c45cf013a57e32ddae43dd4ac911eb4a3919fdChris Wilson	if (IS_GEN4(dev) && rec->stride_Y < 512)
103302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EINVAL;
103402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
103502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	tmp = (rec->flags & I915_OVERLAY_TYPE_MASK) == I915_OVERLAY_YUV_PLANAR ?
10369f7c3f442bb7c0d0a0ed25cc287932450a1f2babChris Wilson		4096 : 8192;
10379f7c3f442bb7c0d0a0ed25cc287932450a1f2babChris Wilson	if (rec->stride_Y > tmp || rec->stride_UV > 2*1024)
103802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EINVAL;
103902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
104002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* check buffer dimensions */
104102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	switch (rec->flags & I915_OVERLAY_TYPE_MASK) {
1042722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case I915_OVERLAY_RGB:
1043722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case I915_OVERLAY_YUV_PACKED:
1044722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		/* always 4 Y values per depth pixels */
1045722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		if (packed_width_bytes(rec->flags, rec->src_width) > rec->stride_Y)
1046722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			return -EINVAL;
1047722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson
1048722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		tmp = rec->stride_Y*rec->src_height;
104905394f3975dceb107a5e1393e2244946e5b43660Chris Wilson		if (rec->offset_Y + tmp > new_bo->base.size)
1050722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			return -EINVAL;
1051722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		break;
1052722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson
1053722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	case I915_OVERLAY_YUV_PLANAR:
1054722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		if (rec->src_width > rec->stride_Y)
1055722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			return -EINVAL;
1056722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		if (rec->src_width/uv_hscale > rec->stride_UV)
1057722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			return -EINVAL;
1058722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson
10599f7c3f442bb7c0d0a0ed25cc287932450a1f2babChris Wilson		tmp = rec->stride_Y * rec->src_height;
106005394f3975dceb107a5e1393e2244946e5b43660Chris Wilson		if (rec->offset_Y + tmp > new_bo->base.size)
1061722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			return -EINVAL;
10629f7c3f442bb7c0d0a0ed25cc287932450a1f2babChris Wilson
10639f7c3f442bb7c0d0a0ed25cc287932450a1f2babChris Wilson		tmp = rec->stride_UV * (rec->src_height / uv_vscale);
106405394f3975dceb107a5e1393e2244946e5b43660Chris Wilson		if (rec->offset_U + tmp > new_bo->base.size ||
106505394f3975dceb107a5e1393e2244946e5b43660Chris Wilson		    rec->offset_V + tmp > new_bo->base.size)
1066722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson			return -EINVAL;
1067722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		break;
106802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
106902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
107002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return 0;
107102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
107202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
1073e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson/**
1074e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson * Return the pipe currently connected to the panel fitter,
1075e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson * or -1 if the panel fitter is not present or not in use
1076e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson */
1077e9e331a8abeece1565d383510ed985945132ffe3Chris Wilsonstatic int intel_panel_fitter_pipe(struct drm_device *dev)
1078e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson{
1079e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson	struct drm_i915_private *dev_priv = dev->dev_private;
1080e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson	u32  pfit_control;
1081e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson
1082e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson	/* i830 doesn't have a panel fitter */
1083e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson	if (IS_I830(dev))
1084e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson		return -1;
1085e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson
1086e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson	pfit_control = I915_READ(PFIT_CONTROL);
1087e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson
1088e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson	/* See if the panel fitter is in use */
1089e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson	if ((pfit_control & PFIT_ENABLE) == 0)
1090e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson		return -1;
1091e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson
1092e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson	/* 965 can place panel fitter on either pipe */
1093a6c45cf013a57e32ddae43dd4ac911eb4a3919fdChris Wilson	if (IS_GEN4(dev))
1094e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson		return (pfit_control >> 29) & 0x3;
1095e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson
1096e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson	/* older chips can only use pipe 1 */
1097e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson	return 1;
1098e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson}
1099e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson
110002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterint intel_overlay_put_image(struct drm_device *dev, void *data,
11010206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi			    struct drm_file *file_priv)
110202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
110302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct drm_intel_overlay_put_image *put_image_rec = data;
110402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	drm_i915_private_t *dev_priv = dev->dev_private;
110502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct intel_overlay *overlay;
110602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct drm_mode_object *drmmode_obj;
110702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct intel_crtc *crtc;
110805394f3975dceb107a5e1393e2244946e5b43660Chris Wilson	struct drm_i915_gem_object *new_bo;
110902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct put_image_params *params;
111002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int ret;
111102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
111202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!dev_priv) {
111302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		DRM_ERROR("called with no initialization\n");
111402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EINVAL;
111502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
111602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
111702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	overlay = dev_priv->overlay;
111802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!overlay) {
111902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		DRM_DEBUG("userspace bug: no overlay\n");
112002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -ENODEV;
112102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
112202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
112302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!(put_image_rec->flags & I915_OVERLAY_ENABLE)) {
112402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		mutex_lock(&dev->mode_config.mutex);
112502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		mutex_lock(&dev->struct_mutex);
112602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
1127ce453d81cb0397aa7d5148984f51907e14072d74Chris Wilson		ret = intel_overlay_switch_off(overlay);
112802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
112902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		mutex_unlock(&dev->struct_mutex);
113002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		mutex_unlock(&dev->mode_config.mutex);
113102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
113202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return ret;
113302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
113402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
113502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	params = kmalloc(sizeof(struct put_image_params), GFP_KERNEL);
113602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!params)
113702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -ENOMEM;
113802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
113902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	drmmode_obj = drm_mode_object_find(dev, put_image_rec->crtc_id,
1140722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson					   DRM_MODE_OBJECT_CRTC);
1141915a428e43acfd05e4ffeaf40549b0cf163eebe2Dan Carpenter	if (!drmmode_obj) {
1142915a428e43acfd05e4ffeaf40549b0cf163eebe2Dan Carpenter		ret = -ENOENT;
1143915a428e43acfd05e4ffeaf40549b0cf163eebe2Dan Carpenter		goto out_free;
1144915a428e43acfd05e4ffeaf40549b0cf163eebe2Dan Carpenter	}
114502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	crtc = to_intel_crtc(obj_to_crtc(drmmode_obj));
114602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
114705394f3975dceb107a5e1393e2244946e5b43660Chris Wilson	new_bo = to_intel_bo(drm_gem_object_lookup(dev, file_priv,
114805394f3975dceb107a5e1393e2244946e5b43660Chris Wilson						   put_image_rec->bo_handle));
1149c87252266352c5201e2925740018f52578fa92bbChris Wilson	if (&new_bo->base == NULL) {
1150915a428e43acfd05e4ffeaf40549b0cf163eebe2Dan Carpenter		ret = -ENOENT;
1151915a428e43acfd05e4ffeaf40549b0cf163eebe2Dan Carpenter		goto out_free;
1152915a428e43acfd05e4ffeaf40549b0cf163eebe2Dan Carpenter	}
115302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
115402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	mutex_lock(&dev->mode_config.mutex);
115502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	mutex_lock(&dev->struct_mutex);
115602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
1157d9e86c0ee60f323e890484628f351bf50fa9a15dChris Wilson	if (new_bo->tiling_mode) {
1158d9e86c0ee60f323e890484628f351bf50fa9a15dChris Wilson		DRM_ERROR("buffer used for overlay image can not be tiled\n");
1159d9e86c0ee60f323e890484628f351bf50fa9a15dChris Wilson		ret = -EINVAL;
1160d9e86c0ee60f323e890484628f351bf50fa9a15dChris Wilson		goto out_unlock;
1161d9e86c0ee60f323e890484628f351bf50fa9a15dChris Wilson	}
1162d9e86c0ee60f323e890484628f351bf50fa9a15dChris Wilson
1163ce453d81cb0397aa7d5148984f51907e14072d74Chris Wilson	ret = intel_overlay_recover_from_interrupt(overlay);
1164b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson	if (ret != 0)
1165b303cf9542b016e2af3b9d17255a7f93cd790ef5Chris Wilson		goto out_unlock;
116603f77ea5972e6a2363152aec692744cac824dabaDaniel Vetter
116702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (overlay->crtc != crtc) {
116802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		struct drm_display_mode *mode = &crtc->base.mode;
1169ce453d81cb0397aa7d5148984f51907e14072d74Chris Wilson		ret = intel_overlay_switch_off(overlay);
117002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		if (ret != 0)
117102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			goto out_unlock;
117202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
117302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		ret = check_overlay_possible_on_crtc(overlay, crtc);
117402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		if (ret != 0)
117502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			goto out_unlock;
117602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
117702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		overlay->crtc = crtc;
117802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		crtc->overlay = overlay;
117902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
1180e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson		/* line too wide, i.e. one-line-mode */
1181e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson		if (mode->hdisplay > 1024 &&
1182e9e331a8abeece1565d383510ed985945132ffe3Chris Wilson		    intel_panel_fitter_pipe(dev) == crtc->pipe) {
118302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			overlay->pfit_active = 1;
118402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			update_pfit_vscale_ratio(overlay);
118502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		} else
118602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			overlay->pfit_active = 0;
118702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
118802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
118902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	ret = check_overlay_dst(overlay, put_image_rec);
119002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (ret != 0)
119102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		goto out_unlock;
119202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
119302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (overlay->pfit_active) {
119402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		params->dst_y = ((((u32)put_image_rec->dst_y) << 12) /
1195722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson				 overlay->pfit_vscale_ratio);
119602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		/* shifting right rounds downwards, so add 1 */
119702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		params->dst_h = ((((u32)put_image_rec->dst_height) << 12) /
1198722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson				 overlay->pfit_vscale_ratio) + 1;
119902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	} else {
120002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		params->dst_y = put_image_rec->dst_y;
120102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		params->dst_h = put_image_rec->dst_height;
120202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
120302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	params->dst_x = put_image_rec->dst_x;
120402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	params->dst_w = put_image_rec->dst_width;
120502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
120602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	params->src_w = put_image_rec->src_width;
120702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	params->src_h = put_image_rec->src_height;
120802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	params->src_scan_w = put_image_rec->src_scan_width;
120902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	params->src_scan_h = put_image_rec->src_scan_height;
1210722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	if (params->src_scan_h > params->src_h ||
1211722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	    params->src_scan_w > params->src_w) {
121202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		ret = -EINVAL;
121302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		goto out_unlock;
121402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
121502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
121602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	ret = check_overlay_src(dev, put_image_rec, new_bo);
121702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (ret != 0)
121802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		goto out_unlock;
121902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	params->format = put_image_rec->flags & ~I915_OVERLAY_FLAGS_MASK;
122002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	params->stride_Y = put_image_rec->stride_Y;
122102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	params->stride_UV = put_image_rec->stride_UV;
122202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	params->offset_Y = put_image_rec->offset_Y;
122302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	params->offset_U = put_image_rec->offset_U;
122402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	params->offset_V = put_image_rec->offset_V;
122502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
122602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* Check scaling after src size to prevent a divide-by-zero. */
122702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	ret = check_overlay_scaling(params);
122802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (ret != 0)
122902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		goto out_unlock;
123002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
123102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	ret = intel_overlay_do_put_image(overlay, new_bo, params);
123202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (ret != 0)
123302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		goto out_unlock;
123402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
123502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	mutex_unlock(&dev->struct_mutex);
123602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	mutex_unlock(&dev->mode_config.mutex);
123702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
123802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	kfree(params);
123902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
124002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return 0;
124102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
124202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterout_unlock:
124302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	mutex_unlock(&dev->struct_mutex);
124402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	mutex_unlock(&dev->mode_config.mutex);
124505394f3975dceb107a5e1393e2244946e5b43660Chris Wilson	drm_gem_object_unreference_unlocked(&new_bo->base);
1246915a428e43acfd05e4ffeaf40549b0cf163eebe2Dan Carpenterout_free:
124702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	kfree(params);
124802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
124902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return ret;
125002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
125102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
125202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic void update_reg_attrs(struct intel_overlay *overlay,
125302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			     struct overlay_registers *regs)
125402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
125502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	regs->OCLRC0 = (overlay->contrast << 18) | (overlay->brightness & 0xff);
125602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	regs->OCLRC1 = overlay->saturation;
125702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
125802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
125902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic bool check_gamma_bounds(u32 gamma1, u32 gamma2)
126002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
126102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int i;
126202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
126302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (gamma1 & 0xff000000 || gamma2 & 0xff000000)
126402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return false;
126502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
126602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	for (i = 0; i < 3; i++) {
1267722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson		if (((gamma1 >> i*8) & 0xff) >= ((gamma2 >> i*8) & 0xff))
126802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			return false;
126902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
127002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
127102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return true;
127202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
127302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
127402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic bool check_gamma5_errata(u32 gamma5)
127502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
127602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int i;
127702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
127802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	for (i = 0; i < 3; i++) {
127902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		if (((gamma5 >> i*8) & 0xff) == 0x80)
128002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			return false;
128102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
128202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
128302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return true;
128402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
128502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
128602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterstatic int check_gamma(struct drm_intel_overlay_attrs *attrs)
128702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
1288722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	if (!check_gamma_bounds(0, attrs->gamma0) ||
1289722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	    !check_gamma_bounds(attrs->gamma0, attrs->gamma1) ||
1290722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	    !check_gamma_bounds(attrs->gamma1, attrs->gamma2) ||
1291722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	    !check_gamma_bounds(attrs->gamma2, attrs->gamma3) ||
1292722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	    !check_gamma_bounds(attrs->gamma3, attrs->gamma4) ||
1293722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	    !check_gamma_bounds(attrs->gamma4, attrs->gamma5) ||
1294722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	    !check_gamma_bounds(attrs->gamma5, 0x00ffffff))
129502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EINVAL;
1296722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson
129702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!check_gamma5_errata(attrs->gamma5))
129802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EINVAL;
1299722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson
130002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return 0;
130102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
130202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
130302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterint intel_overlay_attrs(struct drm_device *dev, void *data,
13040206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi			struct drm_file *file_priv)
130502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
130602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct drm_intel_overlay_attrs *attrs = data;
13070206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	drm_i915_private_t *dev_priv = dev->dev_private;
130802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct intel_overlay *overlay;
130902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct overlay_registers *regs;
131002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int ret;
131102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
131202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!dev_priv) {
131302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		DRM_ERROR("called with no initialization\n");
131402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -EINVAL;
131502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
131602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
131702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	overlay = dev_priv->overlay;
131802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!overlay) {
131902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		DRM_DEBUG("userspace bug: no overlay\n");
132002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return -ENODEV;
132102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
132202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
132302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	mutex_lock(&dev->mode_config.mutex);
132402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	mutex_lock(&dev->struct_mutex);
132502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
132660fc332cb5ab19e5a86d696b210df65814b2ad8aChris Wilson	ret = -EINVAL;
132702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!(attrs->flags & I915_OVERLAY_UPDATE_ATTRS)) {
132860fc332cb5ab19e5a86d696b210df65814b2ad8aChris Wilson		attrs->color_key  = overlay->color_key;
132902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		attrs->brightness = overlay->brightness;
133060fc332cb5ab19e5a86d696b210df65814b2ad8aChris Wilson		attrs->contrast   = overlay->contrast;
133102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		attrs->saturation = overlay->saturation;
133202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
1333a6c45cf013a57e32ddae43dd4ac911eb4a3919fdChris Wilson		if (!IS_GEN2(dev)) {
133402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			attrs->gamma0 = I915_READ(OGAMC0);
133502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			attrs->gamma1 = I915_READ(OGAMC1);
133602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			attrs->gamma2 = I915_READ(OGAMC2);
133702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			attrs->gamma3 = I915_READ(OGAMC3);
133802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			attrs->gamma4 = I915_READ(OGAMC4);
133902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			attrs->gamma5 = I915_READ(OGAMC5);
134002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		}
134102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	} else {
134260fc332cb5ab19e5a86d696b210df65814b2ad8aChris Wilson		if (attrs->brightness < -128 || attrs->brightness > 127)
134302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			goto out_unlock;
134460fc332cb5ab19e5a86d696b210df65814b2ad8aChris Wilson		if (attrs->contrast > 255)
134502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			goto out_unlock;
134660fc332cb5ab19e5a86d696b210df65814b2ad8aChris Wilson		if (attrs->saturation > 1023)
134702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			goto out_unlock;
134802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
134960fc332cb5ab19e5a86d696b210df65814b2ad8aChris Wilson		overlay->color_key  = attrs->color_key;
135060fc332cb5ab19e5a86d696b210df65814b2ad8aChris Wilson		overlay->brightness = attrs->brightness;
135160fc332cb5ab19e5a86d696b210df65814b2ad8aChris Wilson		overlay->contrast   = attrs->contrast;
135260fc332cb5ab19e5a86d696b210df65814b2ad8aChris Wilson		overlay->saturation = attrs->saturation;
135302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
13548d74f656dd78ae1ba813389cd46197c6329696bcChris Wilson		regs = intel_overlay_map_regs(overlay);
135502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		if (!regs) {
135602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			ret = -ENOMEM;
135702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			goto out_unlock;
135802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		}
135902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
136002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		update_reg_attrs(overlay, regs);
136102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
13629bb2ff731b32c023e7a502efdc0dee46157290d5Chris Wilson		intel_overlay_unmap_regs(overlay, regs);
136302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
136402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		if (attrs->flags & I915_OVERLAY_UPDATE_GAMMA) {
1365a6c45cf013a57e32ddae43dd4ac911eb4a3919fdChris Wilson			if (IS_GEN2(dev))
136602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				goto out_unlock;
136702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
136802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			if (overlay->active) {
136902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				ret = -EBUSY;
137002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				goto out_unlock;
137102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			}
137202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
137302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			ret = check_gamma(attrs);
137460fc332cb5ab19e5a86d696b210df65814b2ad8aChris Wilson			if (ret)
137502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter				goto out_unlock;
137602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
137702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			I915_WRITE(OGAMC0, attrs->gamma0);
137802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			I915_WRITE(OGAMC1, attrs->gamma1);
137902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			I915_WRITE(OGAMC2, attrs->gamma2);
138002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			I915_WRITE(OGAMC3, attrs->gamma3);
138102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			I915_WRITE(OGAMC4, attrs->gamma4);
138202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter			I915_WRITE(OGAMC5, attrs->gamma5);
138302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		}
138402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
138502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
138660fc332cb5ab19e5a86d696b210df65814b2ad8aChris Wilson	ret = 0;
138702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterout_unlock:
138802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	mutex_unlock(&dev->struct_mutex);
138902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	mutex_unlock(&dev->mode_config.mutex);
139002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
139102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return ret;
139202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
139302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
139402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vettervoid intel_setup_overlay(struct drm_device *dev)
139502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
13960206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	drm_i915_private_t *dev_priv = dev->dev_private;
139702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct intel_overlay *overlay;
139805394f3975dceb107a5e1393e2244946e5b43660Chris Wilson	struct drm_i915_gem_object *reg_bo;
139902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	struct overlay_registers *regs;
140002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	int ret;
140102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
140231578148b2c62612f9516fdcf5ebb64ab32ed12dChris Wilson	if (!HAS_OVERLAY(dev))
140302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return;
140402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
140502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	overlay = kzalloc(sizeof(struct intel_overlay), GFP_KERNEL);
140602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!overlay)
140702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		return;
140879d2427338e8da362678de32a1c8af1dc8a9810aChris Wilson
140979d2427338e8da362678de32a1c8af1dc8a9810aChris Wilson	mutex_lock(&dev->struct_mutex);
141079d2427338e8da362678de32a1c8af1dc8a9810aChris Wilson	if (WARN_ON(dev_priv->overlay))
141179d2427338e8da362678de32a1c8af1dc8a9810aChris Wilson		goto out_free;
141279d2427338e8da362678de32a1c8af1dc8a9810aChris Wilson
141302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	overlay->dev = dev;
141402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
1415ac52bc56de25535a907ef07f8755f1387b89b0f5Daniel Vetter	reg_bo = i915_gem_alloc_object(dev, PAGE_SIZE);
141602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!reg_bo)
141702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		goto out_free;
141805394f3975dceb107a5e1393e2244946e5b43660Chris Wilson	overlay->reg_bo = reg_bo;
141902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
142031578148b2c62612f9516fdcf5ebb64ab32ed12dChris Wilson	if (OVERLAY_NEEDS_PHYSICAL(dev)) {
142102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		ret = i915_gem_attach_phys_object(dev, reg_bo,
14226eeefaf3c86b8937db8ad930c48bfb592fc5e32eChris Wilson						  I915_GEM_PHYS_OVERLAY_REGS,
1423a29301288f1840bdf9c5456da9cd7c944436edd5Chris Wilson						  PAGE_SIZE);
14240206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi		if (ret) {
14250206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi			DRM_ERROR("failed to attach phys overlay regs\n");
14260206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi			goto out_free_bo;
14270206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi		}
142805394f3975dceb107a5e1393e2244946e5b43660Chris Wilson		overlay->flip_addr = reg_bo->phys_obj->handle->busaddr;
142931578148b2c62612f9516fdcf5ebb64ab32ed12dChris Wilson	} else {
143075e9e9158f38e5cb21eff23b30bafa6f32e0a606Daniel Vetter		ret = i915_gem_object_pin(reg_bo, PAGE_SIZE, true);
143102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		if (ret) {
14320206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi			DRM_ERROR("failed to pin overlay register bo\n");
14330206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi			goto out_free_bo;
14340206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi		}
143505394f3975dceb107a5e1393e2244946e5b43660Chris Wilson		overlay->flip_addr = reg_bo->gtt_offset;
14360ddc1289f3ffd779779ddd3922f26ae7d0a21604Chris Wilson
14370ddc1289f3ffd779779ddd3922f26ae7d0a21604Chris Wilson		ret = i915_gem_object_set_to_gtt_domain(reg_bo, true);
14380ddc1289f3ffd779779ddd3922f26ae7d0a21604Chris Wilson		if (ret) {
14390206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi			DRM_ERROR("failed to move overlay register bo into the GTT\n");
14400206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi			goto out_unpin_bo;
14410206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi		}
144202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	}
144302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
144402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	/* init all values */
144502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	overlay->color_key = 0x0101fe;
144602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	overlay->brightness = -19;
144702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	overlay->contrast = 75;
144802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	overlay->saturation = 146;
144902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
14508d74f656dd78ae1ba813389cd46197c6329696bcChris Wilson	regs = intel_overlay_map_regs(overlay);
145102e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	if (!regs)
145279d2427338e8da362678de32a1c8af1dc8a9810aChris Wilson		goto out_unpin_bo;
145302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
145402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	memset(regs, 0, sizeof(struct overlay_registers));
145502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	update_polyphase_filter(regs);
145602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	update_reg_attrs(overlay, regs);
145702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
14589bb2ff731b32c023e7a502efdc0dee46157290d5Chris Wilson	intel_overlay_unmap_regs(overlay, regs);
145902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
146002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	dev_priv->overlay = overlay;
146179d2427338e8da362678de32a1c8af1dc8a9810aChris Wilson	mutex_unlock(&dev->struct_mutex);
146202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	DRM_INFO("initialized overlay support\n");
146302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return;
146402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
14650ddc1289f3ffd779779ddd3922f26ae7d0a21604Chris Wilsonout_unpin_bo:
146679d2427338e8da362678de32a1c8af1dc8a9810aChris Wilson	if (!OVERLAY_NEEDS_PHYSICAL(dev))
146779d2427338e8da362678de32a1c8af1dc8a9810aChris Wilson		i915_gem_object_unpin(reg_bo);
146802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterout_free_bo:
146905394f3975dceb107a5e1393e2244946e5b43660Chris Wilson	drm_gem_object_unreference(&reg_bo->base);
147002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetterout_free:
147179d2427338e8da362678de32a1c8af1dc8a9810aChris Wilson	mutex_unlock(&dev->struct_mutex);
147202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	kfree(overlay);
147302e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	return;
147402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
147502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
147602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vettervoid intel_cleanup_overlay(struct drm_device *dev)
147702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter{
1478722506f04dae7c88193dab2fc836ff15070190f0Chris Wilson	drm_i915_private_t *dev_priv = dev->dev_private;
147902e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
148062cf4e6fef35b4422e206b63b7f0ac90261d4ad9Chris Wilson	if (!dev_priv->overlay)
148162cf4e6fef35b4422e206b63b7f0ac90261d4ad9Chris Wilson		return;
148202e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
148362cf4e6fef35b4422e206b63b7f0ac90261d4ad9Chris Wilson	/* The bo's should be free'd by the generic code already.
148462cf4e6fef35b4422e206b63b7f0ac90261d4ad9Chris Wilson	 * Furthermore modesetting teardown happens beforehand so the
148562cf4e6fef35b4422e206b63b7f0ac90261d4ad9Chris Wilson	 * hardware should be off already */
148662cf4e6fef35b4422e206b63b7f0ac90261d4ad9Chris Wilson	BUG_ON(dev_priv->overlay->active);
148762cf4e6fef35b4422e206b63b7f0ac90261d4ad9Chris Wilson
148862cf4e6fef35b4422e206b63b7f0ac90261d4ad9Chris Wilson	drm_gem_object_unreference_unlocked(&dev_priv->overlay->reg_bo->base);
148962cf4e6fef35b4422e206b63b7f0ac90261d4ad9Chris Wilson	kfree(dev_priv->overlay);
149002e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter}
14916ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson
14923bd3c9329973a93fa3ef5e9840f2fd6fa2889e3fChris Wilson#ifdef CONFIG_DEBUG_FS
14933bd3c9329973a93fa3ef5e9840f2fd6fa2889e3fChris Wilson#include <linux/seq_file.h>
14943bd3c9329973a93fa3ef5e9840f2fd6fa2889e3fChris Wilson
14956ef3d4278034982c13df87c4a51e0445f762d316Chris Wilsonstruct intel_overlay_error_state {
14966ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	struct overlay_registers regs;
14976ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	unsigned long base;
14986ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	u32 dovsta;
14996ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	u32 isr;
15006ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson};
15016ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson
15023bd3c9329973a93fa3ef5e9840f2fd6fa2889e3fChris Wilsonstatic struct overlay_registers *
1503c48c43e422c1404fd72c57d1d21a6f6d01e18900Linus Torvaldsintel_overlay_map_regs_atomic(struct intel_overlay *overlay)
15043bd3c9329973a93fa3ef5e9840f2fd6fa2889e3fChris Wilson{
1505c48c43e422c1404fd72c57d1d21a6f6d01e18900Linus Torvalds	drm_i915_private_t *dev_priv = overlay->dev->dev_private;
15063bd3c9329973a93fa3ef5e9840f2fd6fa2889e3fChris Wilson	struct overlay_registers *regs;
15073bd3c9329973a93fa3ef5e9840f2fd6fa2889e3fChris Wilson
15083bd3c9329973a93fa3ef5e9840f2fd6fa2889e3fChris Wilson	if (OVERLAY_NEEDS_PHYSICAL(overlay->dev))
15093bd3c9329973a93fa3ef5e9840f2fd6fa2889e3fChris Wilson		regs = overlay->reg_bo->phys_obj->handle->vaddr;
15103bd3c9329973a93fa3ef5e9840f2fd6fa2889e3fChris Wilson	else
15113bd3c9329973a93fa3ef5e9840f2fd6fa2889e3fChris Wilson		regs = io_mapping_map_atomic_wc(dev_priv->mm.gtt_mapping,
1512c48c43e422c1404fd72c57d1d21a6f6d01e18900Linus Torvalds						overlay->reg_bo->gtt_offset);
15133bd3c9329973a93fa3ef5e9840f2fd6fa2889e3fChris Wilson
15143bd3c9329973a93fa3ef5e9840f2fd6fa2889e3fChris Wilson	return regs;
15153bd3c9329973a93fa3ef5e9840f2fd6fa2889e3fChris Wilson}
15163bd3c9329973a93fa3ef5e9840f2fd6fa2889e3fChris Wilson
15173bd3c9329973a93fa3ef5e9840f2fd6fa2889e3fChris Wilsonstatic void intel_overlay_unmap_regs_atomic(struct intel_overlay *overlay,
15183bd3c9329973a93fa3ef5e9840f2fd6fa2889e3fChris Wilson					    struct overlay_registers *regs)
15193bd3c9329973a93fa3ef5e9840f2fd6fa2889e3fChris Wilson{
15203bd3c9329973a93fa3ef5e9840f2fd6fa2889e3fChris Wilson	if (!OVERLAY_NEEDS_PHYSICAL(overlay->dev))
1521c48c43e422c1404fd72c57d1d21a6f6d01e18900Linus Torvalds		io_mapping_unmap_atomic(regs);
15223bd3c9329973a93fa3ef5e9840f2fd6fa2889e3fChris Wilson}
15233bd3c9329973a93fa3ef5e9840f2fd6fa2889e3fChris Wilson
15243bd3c9329973a93fa3ef5e9840f2fd6fa2889e3fChris Wilson
15256ef3d4278034982c13df87c4a51e0445f762d316Chris Wilsonstruct intel_overlay_error_state *
15266ef3d4278034982c13df87c4a51e0445f762d316Chris Wilsonintel_overlay_capture_error_state(struct drm_device *dev)
15276ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson{
15280206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	drm_i915_private_t *dev_priv = dev->dev_private;
15296ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	struct intel_overlay *overlay = dev_priv->overlay;
15306ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	struct intel_overlay_error_state *error;
15316ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	struct overlay_registers __iomem *regs;
15326ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson
15336ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	if (!overlay || !overlay->active)
15346ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson		return NULL;
15356ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson
15366ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	error = kmalloc(sizeof(*error), GFP_ATOMIC);
15376ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	if (error == NULL)
15386ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson		return NULL;
15396ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson
15406ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	error->dovsta = I915_READ(DOVSTA);
15416ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	error->isr = I915_READ(ISR);
154231578148b2c62612f9516fdcf5ebb64ab32ed12dChris Wilson	if (OVERLAY_NEEDS_PHYSICAL(overlay->dev))
15436ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson		error->base = (long) overlay->reg_bo->phys_obj->handle->vaddr;
154431578148b2c62612f9516fdcf5ebb64ab32ed12dChris Wilson	else
154531578148b2c62612f9516fdcf5ebb64ab32ed12dChris Wilson		error->base = (long) overlay->reg_bo->gtt_offset;
15466ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson
15476ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	regs = intel_overlay_map_regs_atomic(overlay);
15486ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	if (!regs)
15496ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson		goto err;
15506ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson
15516ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	memcpy_fromio(&error->regs, regs, sizeof(struct overlay_registers));
1552c48c43e422c1404fd72c57d1d21a6f6d01e18900Linus Torvalds	intel_overlay_unmap_regs_atomic(overlay, regs);
15536ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson
15546ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	return error;
15556ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson
15566ef3d4278034982c13df87c4a51e0445f762d316Chris Wilsonerr:
15576ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	kfree(error);
15586ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	return NULL;
15596ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson}
15606ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson
15616ef3d4278034982c13df87c4a51e0445f762d316Chris Wilsonvoid
15626ef3d4278034982c13df87c4a51e0445f762d316Chris Wilsonintel_overlay_print_error_state(struct seq_file *m, struct intel_overlay_error_state *error)
15636ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson{
15646ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	seq_printf(m, "Overlay, status: 0x%08x, interrupt: 0x%08x\n",
15656ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson		   error->dovsta, error->isr);
15666ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	seq_printf(m, "  Register file at 0x%08lx:\n",
15676ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson		   error->base);
15686ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson
15696ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson#define P(x) seq_printf(m, "    " #x ":	0x%08x\n", error->regs.x)
15706ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OBUF_0Y);
15716ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OBUF_1Y);
15726ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OBUF_0U);
15736ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OBUF_0V);
15746ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OBUF_1U);
15756ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OBUF_1V);
15766ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OSTRIDE);
15776ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(YRGB_VPH);
15786ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(UV_VPH);
15796ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(HORZ_PH);
15806ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(INIT_PHS);
15816ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(DWINPOS);
15826ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(DWINSZ);
15836ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(SWIDTH);
15846ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(SWIDTHSW);
15856ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(SHEIGHT);
15866ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(YRGBSCALE);
15876ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(UVSCALE);
15886ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OCLRC0);
15896ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OCLRC1);
15906ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(DCLRKV);
15916ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(DCLRKM);
15926ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(SCLRKVH);
15936ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(SCLRKVL);
15946ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(SCLRKEN);
15956ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OCONFIG);
15966ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OCMD);
15976ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OSTART_0Y);
15986ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OSTART_1Y);
15996ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OSTART_0U);
16006ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OSTART_0V);
16016ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OSTART_1U);
16026ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OSTART_1V);
16036ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OTILEOFF_0Y);
16046ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OTILEOFF_1Y);
16056ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OTILEOFF_0U);
16066ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OTILEOFF_0V);
16076ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OTILEOFF_1U);
16086ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(OTILEOFF_1V);
16096ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(FASTHSCALE);
16106ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson	P(UVSCALEV);
16116ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson#undef P
16126ef3d4278034982c13df87c4a51e0445f762d316Chris Wilson}
16133bd3c9329973a93fa3ef5e9840f2fd6fa2889e3fChris Wilson#endif
1614