1515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin/* 2515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin * Copyright 2013 Ilia Mirkin 3515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin * 4515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin * Permission is hereby granted, free of charge, to any person obtaining a 5515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin * copy of this software and associated documentation files (the "Software"), 6515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin * to deal in the Software without restriction, including without limitation 7515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin * and/or sell copies of the Software, and to permit persons to whom the 9515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin * Software is furnished to do so, subject to the following conditions: 10515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin * 11515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin * The above copyright notice and this permission notice shall be included in 12515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin * all copies or substantial portions of the Software. 13515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin * 14515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 18515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF 19515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin * SOFTWARE. 21515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin * 22515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin * Implementation based on the pre-KMS implementation in xf86-video-nouveau, 23515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin * written by Arthur Huillet. 24515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin */ 25515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin 26515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin#include <drm/drmP.h> 27515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin#include <drm/drm_crtc.h> 28515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin#include <drm/drm_fourcc.h> 29515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin 30515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin#include "nouveau_drm.h" 31515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin 32515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin#include "nouveau_bo.h" 33515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin#include "nouveau_connector.h" 34515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin#include "nouveau_display.h" 35515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin#include "nvreg.h" 36515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin 37515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin 38515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkinstruct nouveau_plane { 39515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin struct drm_plane base; 40515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin bool flip; 41515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin struct nouveau_bo *cur; 42515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin 43515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin struct { 44515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin struct drm_property *colorkey; 45515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin struct drm_property *contrast; 46515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin struct drm_property *brightness; 47515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin struct drm_property *hue; 48515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin struct drm_property *saturation; 49515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin struct drm_property *iturbt_709; 50515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin } props; 51515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin 52515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin int colorkey; 53515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin int contrast; 54515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin int brightness; 55515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin int hue; 56515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin int saturation; 57515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin int iturbt_709; 58ab9b18a6a13c438505d3419bd59dcd8e1856ceddIlia Mirkin 59ab9b18a6a13c438505d3419bd59dcd8e1856ceddIlia Mirkin void (*set_params)(struct nouveau_plane *); 60515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin}; 61515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin 62515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkinstatic uint32_t formats[] = { 637ffb078172d6906c4712914321c551d4f595875fIlia Mirkin DRM_FORMAT_YUYV, 64515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin DRM_FORMAT_UYVY, 65efffa9841cf42ae8350d421070cea962b063df8cIlia Mirkin DRM_FORMAT_NV12, 66515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin}; 67515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin 68515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin/* Sine can be approximated with 69515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin * http://en.wikipedia.org/wiki/Bhaskara_I's_sine_approximation_formula 70515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin * sin(x degrees) ~= 4 x (180 - x) / (40500 - x (180 - x) ) 71515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin * Note that this only works for the range [0, 180]. 72515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin * Also note that sin(x) == -sin(x - 180) 73515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin */ 74515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkinstatic inline int 75515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkinsin_mul(int degrees, int factor) 76515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin{ 77515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin if (degrees > 180) { 78515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin degrees -= 180; 79515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin factor *= -1; 80515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin } 81515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin return factor * 4 * degrees * (180 - degrees) / 82515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin (40500 - degrees * (180 - degrees)); 83515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin} 84515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin 85515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin/* cos(x) = sin(x + 90) */ 86515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkinstatic inline int 87515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkincos_mul(int degrees, int factor) 88515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin{ 89515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin return sin_mul((degrees + 90) % 360, factor); 90515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin} 91515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin 92515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkinstatic int 93515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkinnv10_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, 94515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin struct drm_framebuffer *fb, int crtc_x, int crtc_y, 95515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin unsigned int crtc_w, unsigned int crtc_h, 96515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin uint32_t src_x, uint32_t src_y, 97515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin uint32_t src_w, uint32_t src_h) 98515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin{ 99967e7bde8739fe3b215f7537e8f1f39c044902afBen Skeggs struct nvif_device *dev = &nouveau_drm(plane->dev)->device; 1005ee932d049a4e6e1e134f521dbb98fdd3993a8e9Fabian Frederick struct nouveau_plane *nv_plane = 1015ee932d049a4e6e1e134f521dbb98fdd3993a8e9Fabian Frederick container_of(plane, struct nouveau_plane, base); 102515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin struct nouveau_framebuffer *nv_fb = nouveau_framebuffer(fb); 103515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); 104515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin struct nouveau_bo *cur = nv_plane->cur; 105515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin bool flip = nv_plane->flip; 106515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin int soff = NV_PCRTC0_SIZE * nv_crtc->index; 107515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin int soff2 = NV_PCRTC0_SIZE * !nv_crtc->index; 10892e5b0a2b121c29eac31e6d8106ceefa31de46a9Ilia Mirkin int format, ret; 10992e5b0a2b121c29eac31e6d8106ceefa31de46a9Ilia Mirkin 11092e5b0a2b121c29eac31e6d8106ceefa31de46a9Ilia Mirkin /* Source parameters given in 16.16 fixed point, ignore fractional. */ 11192e5b0a2b121c29eac31e6d8106ceefa31de46a9Ilia Mirkin src_x >>= 16; 11292e5b0a2b121c29eac31e6d8106ceefa31de46a9Ilia Mirkin src_y >>= 16; 11392e5b0a2b121c29eac31e6d8106ceefa31de46a9Ilia Mirkin src_w >>= 16; 11492e5b0a2b121c29eac31e6d8106ceefa31de46a9Ilia Mirkin src_h >>= 16; 11592e5b0a2b121c29eac31e6d8106ceefa31de46a9Ilia Mirkin 11692e5b0a2b121c29eac31e6d8106ceefa31de46a9Ilia Mirkin format = ALIGN(src_w * 4, 0x100); 117515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin 118515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin if (format > 0xffff) 119050828e9563d03cbaab950c16ae4aebaa02ff0deIlia Mirkin return -ERANGE; 120050828e9563d03cbaab950c16ae4aebaa02ff0deIlia Mirkin 121967e7bde8739fe3b215f7537e8f1f39c044902afBen Skeggs if (dev->info.chipset >= 0x30) { 122050828e9563d03cbaab950c16ae4aebaa02ff0deIlia Mirkin if (crtc_w < (src_w >> 1) || crtc_h < (src_h >> 1)) 123050828e9563d03cbaab950c16ae4aebaa02ff0deIlia Mirkin return -ERANGE; 124050828e9563d03cbaab950c16ae4aebaa02ff0deIlia Mirkin } else { 125050828e9563d03cbaab950c16ae4aebaa02ff0deIlia Mirkin if (crtc_w < (src_w >> 3) || crtc_h < (src_h >> 3)) 126050828e9563d03cbaab950c16ae4aebaa02ff0deIlia Mirkin return -ERANGE; 127050828e9563d03cbaab950c16ae4aebaa02ff0deIlia Mirkin } 128515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin 129515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin ret = nouveau_bo_pin(nv_fb->nvbo, TTM_PL_FLAG_VRAM); 130515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin if (ret) 131515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin return ret; 132515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin 133515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin nv_plane->cur = nv_fb->nvbo; 134515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin 135db2bec187dd68e79d512112df1f6e7a849e7f0ceBen Skeggs nvif_mask(dev, NV_PCRTC_ENGINE_CTRL + soff, NV_CRTC_FSEL_OVERLAY, NV_CRTC_FSEL_OVERLAY); 136db2bec187dd68e79d512112df1f6e7a849e7f0ceBen Skeggs nvif_mask(dev, NV_PCRTC_ENGINE_CTRL + soff2, NV_CRTC_FSEL_OVERLAY, 0); 137515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin 138db2bec187dd68e79d512112df1f6e7a849e7f0ceBen Skeggs nvif_wr32(dev, NV_PVIDEO_BASE(flip), 0); 139db2bec187dd68e79d512112df1f6e7a849e7f0ceBen Skeggs nvif_wr32(dev, NV_PVIDEO_OFFSET_BUFF(flip), nv_fb->nvbo->bo.offset); 140db2bec187dd68e79d512112df1f6e7a849e7f0ceBen Skeggs nvif_wr32(dev, NV_PVIDEO_SIZE_IN(flip), src_h << 16 | src_w); 141db2bec187dd68e79d512112df1f6e7a849e7f0ceBen Skeggs nvif_wr32(dev, NV_PVIDEO_POINT_IN(flip), src_y << 16 | src_x); 142db2bec187dd68e79d512112df1f6e7a849e7f0ceBen Skeggs nvif_wr32(dev, NV_PVIDEO_DS_DX(flip), (src_w << 20) / crtc_w); 143db2bec187dd68e79d512112df1f6e7a849e7f0ceBen Skeggs nvif_wr32(dev, NV_PVIDEO_DT_DY(flip), (src_h << 20) / crtc_h); 144db2bec187dd68e79d512112df1f6e7a849e7f0ceBen Skeggs nvif_wr32(dev, NV_PVIDEO_POINT_OUT(flip), crtc_y << 16 | crtc_x); 145db2bec187dd68e79d512112df1f6e7a849e7f0ceBen Skeggs nvif_wr32(dev, NV_PVIDEO_SIZE_OUT(flip), crtc_h << 16 | crtc_w); 146515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin 1477ffb078172d6906c4712914321c551d4f595875fIlia Mirkin if (fb->pixel_format != DRM_FORMAT_UYVY) 148515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin format |= NV_PVIDEO_FORMAT_COLOR_LE_CR8YB8CB8YA8; 1497ffb078172d6906c4712914321c551d4f595875fIlia Mirkin if (fb->pixel_format == DRM_FORMAT_NV12) 150515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin format |= NV_PVIDEO_FORMAT_PLANAR; 151515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin if (nv_plane->iturbt_709) 152515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin format |= NV_PVIDEO_FORMAT_MATRIX_ITURBT709; 153515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin if (nv_plane->colorkey & (1 << 24)) 154515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin format |= NV_PVIDEO_FORMAT_DISPLAY_COLOR_KEY; 155515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin 156515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin if (fb->pixel_format == DRM_FORMAT_NV12) { 157db2bec187dd68e79d512112df1f6e7a849e7f0ceBen Skeggs nvif_wr32(dev, NV_PVIDEO_UVPLANE_BASE(flip), 0); 158db2bec187dd68e79d512112df1f6e7a849e7f0ceBen Skeggs nvif_wr32(dev, NV_PVIDEO_UVPLANE_OFFSET_BUFF(flip), 159515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin nv_fb->nvbo->bo.offset + fb->offsets[1]); 160515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin } 161db2bec187dd68e79d512112df1f6e7a849e7f0ceBen Skeggs nvif_wr32(dev, NV_PVIDEO_FORMAT(flip), format); 162db2bec187dd68e79d512112df1f6e7a849e7f0ceBen Skeggs nvif_wr32(dev, NV_PVIDEO_STOP, 0); 163515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin /* TODO: wait for vblank? */ 164db2bec187dd68e79d512112df1f6e7a849e7f0ceBen Skeggs nvif_wr32(dev, NV_PVIDEO_BUFFER, flip ? 0x10 : 0x1); 165515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin nv_plane->flip = !flip; 166515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin 167515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin if (cur) 168515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin nouveau_bo_unpin(cur); 169515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin 170515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin return 0; 171515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin} 172515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin 173515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkinstatic int 174515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkinnv10_disable_plane(struct drm_plane *plane) 175515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin{ 176967e7bde8739fe3b215f7537e8f1f39c044902afBen Skeggs struct nvif_device *dev = &nouveau_drm(plane->dev)->device; 1775ee932d049a4e6e1e134f521dbb98fdd3993a8e9Fabian Frederick struct nouveau_plane *nv_plane = 1785ee932d049a4e6e1e134f521dbb98fdd3993a8e9Fabian Frederick container_of(plane, struct nouveau_plane, base); 179515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin 180db2bec187dd68e79d512112df1f6e7a849e7f0ceBen Skeggs nvif_wr32(dev, NV_PVIDEO_STOP, 1); 181515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin if (nv_plane->cur) { 182515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin nouveau_bo_unpin(nv_plane->cur); 183515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin nv_plane->cur = NULL; 184515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin } 185515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin 186515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin return 0; 187515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin} 188515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin 189515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkinstatic void 190ab9b18a6a13c438505d3419bd59dcd8e1856ceddIlia Mirkinnv_destroy_plane(struct drm_plane *plane) 191515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin{ 192ab9b18a6a13c438505d3419bd59dcd8e1856ceddIlia Mirkin plane->funcs->disable_plane(plane); 193515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin drm_plane_cleanup(plane); 194515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin kfree(plane); 195515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin} 196515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin 197515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkinstatic void 198515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkinnv10_set_params(struct nouveau_plane *plane) 199515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin{ 200967e7bde8739fe3b215f7537e8f1f39c044902afBen Skeggs struct nvif_device *dev = &nouveau_drm(plane->base.dev)->device; 201515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin u32 luma = (plane->brightness - 512) << 16 | plane->contrast; 202515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin u32 chroma = ((sin_mul(plane->hue, plane->saturation) & 0xffff) << 16) | 203515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin (cos_mul(plane->hue, plane->saturation) & 0xffff); 204515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin u32 format = 0; 205515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin 206db2bec187dd68e79d512112df1f6e7a849e7f0ceBen Skeggs nvif_wr32(dev, NV_PVIDEO_LUMINANCE(0), luma); 207db2bec187dd68e79d512112df1f6e7a849e7f0ceBen Skeggs nvif_wr32(dev, NV_PVIDEO_LUMINANCE(1), luma); 208db2bec187dd68e79d512112df1f6e7a849e7f0ceBen Skeggs nvif_wr32(dev, NV_PVIDEO_CHROMINANCE(0), chroma); 209db2bec187dd68e79d512112df1f6e7a849e7f0ceBen Skeggs nvif_wr32(dev, NV_PVIDEO_CHROMINANCE(1), chroma); 210db2bec187dd68e79d512112df1f6e7a849e7f0ceBen Skeggs nvif_wr32(dev, NV_PVIDEO_COLOR_KEY, plane->colorkey & 0xffffff); 211515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin 212515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin if (plane->cur) { 213515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin if (plane->iturbt_709) 214515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin format |= NV_PVIDEO_FORMAT_MATRIX_ITURBT709; 215515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin if (plane->colorkey & (1 << 24)) 216515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin format |= NV_PVIDEO_FORMAT_DISPLAY_COLOR_KEY; 217db2bec187dd68e79d512112df1f6e7a849e7f0ceBen Skeggs nvif_mask(dev, NV_PVIDEO_FORMAT(plane->flip), 218515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin NV_PVIDEO_FORMAT_MATRIX_ITURBT709 | 219515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin NV_PVIDEO_FORMAT_DISPLAY_COLOR_KEY, 220515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin format); 221515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin } 222515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin} 223515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin 224515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkinstatic int 225ab9b18a6a13c438505d3419bd59dcd8e1856ceddIlia Mirkinnv_set_property(struct drm_plane *plane, 226ab9b18a6a13c438505d3419bd59dcd8e1856ceddIlia Mirkin struct drm_property *property, 227ab9b18a6a13c438505d3419bd59dcd8e1856ceddIlia Mirkin uint64_t value) 228515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin{ 2295ee932d049a4e6e1e134f521dbb98fdd3993a8e9Fabian Frederick struct nouveau_plane *nv_plane = 2305ee932d049a4e6e1e134f521dbb98fdd3993a8e9Fabian Frederick container_of(plane, struct nouveau_plane, base); 231515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin 232515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin if (property == nv_plane->props.colorkey) 233515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin nv_plane->colorkey = value; 234515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin else if (property == nv_plane->props.contrast) 235515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin nv_plane->contrast = value; 236515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin else if (property == nv_plane->props.brightness) 237515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin nv_plane->brightness = value; 238515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin else if (property == nv_plane->props.hue) 239515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin nv_plane->hue = value; 240515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin else if (property == nv_plane->props.saturation) 241515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin nv_plane->saturation = value; 242515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin else if (property == nv_plane->props.iturbt_709) 243515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin nv_plane->iturbt_709 = value; 244515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin else 245515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin return -EINVAL; 246515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin 247ab9b18a6a13c438505d3419bd59dcd8e1856ceddIlia Mirkin if (nv_plane->set_params) 248ab9b18a6a13c438505d3419bd59dcd8e1856ceddIlia Mirkin nv_plane->set_params(nv_plane); 249515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin return 0; 250515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin} 251515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin 252515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkinstatic const struct drm_plane_funcs nv10_plane_funcs = { 253515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin .update_plane = nv10_update_plane, 254515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin .disable_plane = nv10_disable_plane, 255ab9b18a6a13c438505d3419bd59dcd8e1856ceddIlia Mirkin .set_property = nv_set_property, 256ab9b18a6a13c438505d3419bd59dcd8e1856ceddIlia Mirkin .destroy = nv_destroy_plane, 257515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin}; 258515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin 259515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkinstatic void 260515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkinnv10_overlay_init(struct drm_device *device) 261515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin{ 262fa2bade99a6fb24c3847d48ba3cad9a70dbb5364Ben Skeggs struct nouveau_drm *drm = nouveau_drm(device); 263515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin struct nouveau_plane *plane = kzalloc(sizeof(struct nouveau_plane), GFP_KERNEL); 264efffa9841cf42ae8350d421070cea962b063df8cIlia Mirkin int num_formats = ARRAY_SIZE(formats); 265515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin int ret; 266515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin 267515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin if (!plane) 268515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin return; 269515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin 270967e7bde8739fe3b215f7537e8f1f39c044902afBen Skeggs switch (drm->device.info.chipset) { 271efffa9841cf42ae8350d421070cea962b063df8cIlia Mirkin case 0x10: 272efffa9841cf42ae8350d421070cea962b063df8cIlia Mirkin case 0x11: 273efffa9841cf42ae8350d421070cea962b063df8cIlia Mirkin case 0x15: 274efffa9841cf42ae8350d421070cea962b063df8cIlia Mirkin case 0x1a: 275efffa9841cf42ae8350d421070cea962b063df8cIlia Mirkin case 0x20: 2767ffb078172d6906c4712914321c551d4f595875fIlia Mirkin num_formats = 2; 277efffa9841cf42ae8350d421070cea962b063df8cIlia Mirkin break; 278efffa9841cf42ae8350d421070cea962b063df8cIlia Mirkin } 279efffa9841cf42ae8350d421070cea962b063df8cIlia Mirkin 280515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin ret = drm_plane_init(device, &plane->base, 3 /* both crtc's */, 281515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin &nv10_plane_funcs, 282efffa9841cf42ae8350d421070cea962b063df8cIlia Mirkin formats, num_formats, false); 283515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin if (ret) 284515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin goto err; 285515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin 286515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin /* Set up the plane properties */ 287515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin plane->props.colorkey = drm_property_create_range( 288515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin device, 0, "colorkey", 0, 0x01ffffff); 289515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin plane->props.contrast = drm_property_create_range( 290515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin device, 0, "contrast", 0, 8192 - 1); 291515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin plane->props.brightness = drm_property_create_range( 292515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin device, 0, "brightness", 0, 1024); 293515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin plane->props.hue = drm_property_create_range( 294515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin device, 0, "hue", 0, 359); 295515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin plane->props.saturation = drm_property_create_range( 296515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin device, 0, "saturation", 0, 8192 - 1); 297515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin plane->props.iturbt_709 = drm_property_create_range( 298515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin device, 0, "iturbt_709", 0, 1); 299515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin if (!plane->props.colorkey || 300515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin !plane->props.contrast || 301515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin !plane->props.brightness || 302515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin !plane->props.hue || 303515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin !plane->props.saturation || 304515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin !plane->props.iturbt_709) 305515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin goto cleanup; 306515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin 307515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin plane->colorkey = 0; 308515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin drm_object_attach_property(&plane->base.base, 309515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin plane->props.colorkey, plane->colorkey); 310515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin 311515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin plane->contrast = 0x1000; 312515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin drm_object_attach_property(&plane->base.base, 313515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin plane->props.contrast, plane->contrast); 314515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin 315515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin plane->brightness = 512; 316515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin drm_object_attach_property(&plane->base.base, 317515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin plane->props.brightness, plane->brightness); 318515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin 319515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin plane->hue = 0; 320515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin drm_object_attach_property(&plane->base.base, 321515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin plane->props.hue, plane->hue); 322515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin 323515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin plane->saturation = 0x1000; 324515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin drm_object_attach_property(&plane->base.base, 325515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin plane->props.saturation, plane->saturation); 326515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin 327515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin plane->iturbt_709 = 0; 328515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin drm_object_attach_property(&plane->base.base, 329515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin plane->props.iturbt_709, plane->iturbt_709); 330515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin 331ab9b18a6a13c438505d3419bd59dcd8e1856ceddIlia Mirkin plane->set_params = nv10_set_params; 332515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin nv10_set_params(plane); 333ab9b18a6a13c438505d3419bd59dcd8e1856ceddIlia Mirkin nv10_disable_plane(&plane->base); 334ab9b18a6a13c438505d3419bd59dcd8e1856ceddIlia Mirkin return; 335ab9b18a6a13c438505d3419bd59dcd8e1856ceddIlia Mirkincleanup: 336ab9b18a6a13c438505d3419bd59dcd8e1856ceddIlia Mirkin drm_plane_cleanup(&plane->base); 337ab9b18a6a13c438505d3419bd59dcd8e1856ceddIlia Mirkinerr: 338ab9b18a6a13c438505d3419bd59dcd8e1856ceddIlia Mirkin kfree(plane); 339fa2bade99a6fb24c3847d48ba3cad9a70dbb5364Ben Skeggs NV_ERROR(drm, "Failed to create plane\n"); 340ab9b18a6a13c438505d3419bd59dcd8e1856ceddIlia Mirkin} 341ab9b18a6a13c438505d3419bd59dcd8e1856ceddIlia Mirkin 342ab9b18a6a13c438505d3419bd59dcd8e1856ceddIlia Mirkinstatic int 343ab9b18a6a13c438505d3419bd59dcd8e1856ceddIlia Mirkinnv04_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, 344ab9b18a6a13c438505d3419bd59dcd8e1856ceddIlia Mirkin struct drm_framebuffer *fb, int crtc_x, int crtc_y, 345ab9b18a6a13c438505d3419bd59dcd8e1856ceddIlia Mirkin unsigned int crtc_w, unsigned int crtc_h, 346ab9b18a6a13c438505d3419bd59dcd8e1856ceddIlia Mirkin uint32_t src_x, uint32_t src_y, 347ab9b18a6a13c438505d3419bd59dcd8e1856ceddIlia Mirkin uint32_t src_w, uint32_t src_h) 348ab9b18a6a13c438505d3419bd59dcd8e1856ceddIlia Mirkin{ 349967e7bde8739fe3b215f7537e8f1f39c044902afBen Skeggs struct nvif_device *dev = &nouveau_drm(plane->dev)->device; 3505ee932d049a4e6e1e134f521dbb98fdd3993a8e9Fabian Frederick struct nouveau_plane *nv_plane = 3515ee932d049a4e6e1e134f521dbb98fdd3993a8e9Fabian Frederick container_of(plane, struct nouveau_plane, base); 352ab9b18a6a13c438505d3419bd59dcd8e1856ceddIlia Mirkin struct nouveau_framebuffer *nv_fb = nouveau_framebuffer(fb); 353ab9b18a6a13c438505d3419bd59dcd8e1856ceddIlia Mirkin struct nouveau_bo *cur = nv_plane->cur; 354ab9b18a6a13c438505d3419bd59dcd8e1856ceddIlia Mirkin uint32_t overlay = 1; 355ab9b18a6a13c438505d3419bd59dcd8e1856ceddIlia Mirkin int brightness = (nv_plane->brightness - 512) * 62 / 512; 356ab9b18a6a13c438505d3419bd59dcd8e1856ceddIlia Mirkin int pitch, ret, i; 357ab9b18a6a13c438505d3419bd59dcd8e1856ceddIlia Mirkin 358ab9b18a6a13c438505d3419bd59dcd8e1856ceddIlia Mirkin /* Source parameters given in 16.16 fixed point, ignore fractional. */ 359ab9b18a6a13c438505d3419bd59dcd8e1856ceddIlia Mirkin src_x >>= 16; 360ab9b18a6a13c438505d3419bd59dcd8e1856ceddIlia Mirkin src_y >>= 16; 361ab9b18a6a13c438505d3419bd59dcd8e1856ceddIlia Mirkin src_w >>= 16; 362ab9b18a6a13c438505d3419bd59dcd8e1856ceddIlia Mirkin src_h >>= 16; 363ab9b18a6a13c438505d3419bd59dcd8e1856ceddIlia Mirkin 364ab9b18a6a13c438505d3419bd59dcd8e1856ceddIlia Mirkin pitch = ALIGN(src_w * 4, 0x100); 365ab9b18a6a13c438505d3419bd59dcd8e1856ceddIlia Mirkin 366ab9b18a6a13c438505d3419bd59dcd8e1856ceddIlia Mirkin if (pitch > 0xffff) 367ab9b18a6a13c438505d3419bd59dcd8e1856ceddIlia Mirkin return -ERANGE; 368ab9b18a6a13c438505d3419bd59dcd8e1856ceddIlia Mirkin 369ab9b18a6a13c438505d3419bd59dcd8e1856ceddIlia Mirkin /* TODO: Compute an offset? Not sure how to do this for YUYV. */ 370ab9b18a6a13c438505d3419bd59dcd8e1856ceddIlia Mirkin if (src_x != 0 || src_y != 0) 371ab9b18a6a13c438505d3419bd59dcd8e1856ceddIlia Mirkin return -ERANGE; 372ab9b18a6a13c438505d3419bd59dcd8e1856ceddIlia Mirkin 373ab9b18a6a13c438505d3419bd59dcd8e1856ceddIlia Mirkin if (crtc_w < src_w || crtc_h < src_h) 374ab9b18a6a13c438505d3419bd59dcd8e1856ceddIlia Mirkin return -ERANGE; 375ab9b18a6a13c438505d3419bd59dcd8e1856ceddIlia Mirkin 376ab9b18a6a13c438505d3419bd59dcd8e1856ceddIlia Mirkin ret = nouveau_bo_pin(nv_fb->nvbo, TTM_PL_FLAG_VRAM); 377ab9b18a6a13c438505d3419bd59dcd8e1856ceddIlia Mirkin if (ret) 378ab9b18a6a13c438505d3419bd59dcd8e1856ceddIlia Mirkin return ret; 379ab9b18a6a13c438505d3419bd59dcd8e1856ceddIlia Mirkin 380ab9b18a6a13c438505d3419bd59dcd8e1856ceddIlia Mirkin nv_plane->cur = nv_fb->nvbo; 381ab9b18a6a13c438505d3419bd59dcd8e1856ceddIlia Mirkin 382db2bec187dd68e79d512112df1f6e7a849e7f0ceBen Skeggs nvif_wr32(dev, NV_PVIDEO_OE_STATE, 0); 383db2bec187dd68e79d512112df1f6e7a849e7f0ceBen Skeggs nvif_wr32(dev, NV_PVIDEO_SU_STATE, 0); 384db2bec187dd68e79d512112df1f6e7a849e7f0ceBen Skeggs nvif_wr32(dev, NV_PVIDEO_RM_STATE, 0); 385ab9b18a6a13c438505d3419bd59dcd8e1856ceddIlia Mirkin 386ab9b18a6a13c438505d3419bd59dcd8e1856ceddIlia Mirkin for (i = 0; i < 2; i++) { 387db2bec187dd68e79d512112df1f6e7a849e7f0ceBen Skeggs nvif_wr32(dev, NV_PVIDEO_BUFF0_START_ADDRESS + 4 * i, 388ab9b18a6a13c438505d3419bd59dcd8e1856ceddIlia Mirkin nv_fb->nvbo->bo.offset); 389db2bec187dd68e79d512112df1f6e7a849e7f0ceBen Skeggs nvif_wr32(dev, NV_PVIDEO_BUFF0_PITCH_LENGTH + 4 * i, pitch); 390db2bec187dd68e79d512112df1f6e7a849e7f0ceBen Skeggs nvif_wr32(dev, NV_PVIDEO_BUFF0_OFFSET + 4 * i, 0); 391ab9b18a6a13c438505d3419bd59dcd8e1856ceddIlia Mirkin } 392db2bec187dd68e79d512112df1f6e7a849e7f0ceBen Skeggs nvif_wr32(dev, NV_PVIDEO_WINDOW_START, crtc_y << 16 | crtc_x); 393db2bec187dd68e79d512112df1f6e7a849e7f0ceBen Skeggs nvif_wr32(dev, NV_PVIDEO_WINDOW_SIZE, crtc_h << 16 | crtc_w); 394db2bec187dd68e79d512112df1f6e7a849e7f0ceBen Skeggs nvif_wr32(dev, NV_PVIDEO_STEP_SIZE, 395ab9b18a6a13c438505d3419bd59dcd8e1856ceddIlia Mirkin (uint32_t)(((src_h - 1) << 11) / (crtc_h - 1)) << 16 | (uint32_t)(((src_w - 1) << 11) / (crtc_w - 1))); 396ab9b18a6a13c438505d3419bd59dcd8e1856ceddIlia Mirkin 397ab9b18a6a13c438505d3419bd59dcd8e1856ceddIlia Mirkin /* It should be possible to convert hue/contrast to this */ 398db2bec187dd68e79d512112df1f6e7a849e7f0ceBen Skeggs nvif_wr32(dev, NV_PVIDEO_RED_CSC_OFFSET, 0x69 - brightness); 399db2bec187dd68e79d512112df1f6e7a849e7f0ceBen Skeggs nvif_wr32(dev, NV_PVIDEO_GREEN_CSC_OFFSET, 0x3e + brightness); 400db2bec187dd68e79d512112df1f6e7a849e7f0ceBen Skeggs nvif_wr32(dev, NV_PVIDEO_BLUE_CSC_OFFSET, 0x89 - brightness); 401db2bec187dd68e79d512112df1f6e7a849e7f0ceBen Skeggs nvif_wr32(dev, NV_PVIDEO_CSC_ADJUST, 0); 402ab9b18a6a13c438505d3419bd59dcd8e1856ceddIlia Mirkin 403db2bec187dd68e79d512112df1f6e7a849e7f0ceBen Skeggs nvif_wr32(dev, NV_PVIDEO_CONTROL_Y, 0x001); /* (BLUR_ON, LINE_HALF) */ 404db2bec187dd68e79d512112df1f6e7a849e7f0ceBen Skeggs nvif_wr32(dev, NV_PVIDEO_CONTROL_X, 0x111); /* (WEIGHT_HEAVY, SHARPENING_ON, SMOOTHING_ON) */ 405ab9b18a6a13c438505d3419bd59dcd8e1856ceddIlia Mirkin 406db2bec187dd68e79d512112df1f6e7a849e7f0ceBen Skeggs nvif_wr32(dev, NV_PVIDEO_FIFO_BURST_LENGTH, 0x03); 407db2bec187dd68e79d512112df1f6e7a849e7f0ceBen Skeggs nvif_wr32(dev, NV_PVIDEO_FIFO_THRES_SIZE, 0x38); 408ab9b18a6a13c438505d3419bd59dcd8e1856ceddIlia Mirkin 409db2bec187dd68e79d512112df1f6e7a849e7f0ceBen Skeggs nvif_wr32(dev, NV_PVIDEO_KEY, nv_plane->colorkey); 410ab9b18a6a13c438505d3419bd59dcd8e1856ceddIlia Mirkin 411ab9b18a6a13c438505d3419bd59dcd8e1856ceddIlia Mirkin if (nv_plane->colorkey & (1 << 24)) 412ab9b18a6a13c438505d3419bd59dcd8e1856ceddIlia Mirkin overlay |= 0x10; 413ab9b18a6a13c438505d3419bd59dcd8e1856ceddIlia Mirkin if (fb->pixel_format == DRM_FORMAT_YUYV) 414ab9b18a6a13c438505d3419bd59dcd8e1856ceddIlia Mirkin overlay |= 0x100; 415ab9b18a6a13c438505d3419bd59dcd8e1856ceddIlia Mirkin 416db2bec187dd68e79d512112df1f6e7a849e7f0ceBen Skeggs nvif_wr32(dev, NV_PVIDEO_OVERLAY, overlay); 417ab9b18a6a13c438505d3419bd59dcd8e1856ceddIlia Mirkin 418db2bec187dd68e79d512112df1f6e7a849e7f0ceBen Skeggs nvif_wr32(dev, NV_PVIDEO_SU_STATE, nvif_rd32(dev, NV_PVIDEO_SU_STATE) ^ (1 << 16)); 419ab9b18a6a13c438505d3419bd59dcd8e1856ceddIlia Mirkin 420ab9b18a6a13c438505d3419bd59dcd8e1856ceddIlia Mirkin if (cur) 421ab9b18a6a13c438505d3419bd59dcd8e1856ceddIlia Mirkin nouveau_bo_unpin(cur); 422ab9b18a6a13c438505d3419bd59dcd8e1856ceddIlia Mirkin 423ab9b18a6a13c438505d3419bd59dcd8e1856ceddIlia Mirkin return 0; 424ab9b18a6a13c438505d3419bd59dcd8e1856ceddIlia Mirkin} 425ab9b18a6a13c438505d3419bd59dcd8e1856ceddIlia Mirkin 426ab9b18a6a13c438505d3419bd59dcd8e1856ceddIlia Mirkinstatic int 427ab9b18a6a13c438505d3419bd59dcd8e1856ceddIlia Mirkinnv04_disable_plane(struct drm_plane *plane) 428ab9b18a6a13c438505d3419bd59dcd8e1856ceddIlia Mirkin{ 429967e7bde8739fe3b215f7537e8f1f39c044902afBen Skeggs struct nvif_device *dev = &nouveau_drm(plane->dev)->device; 4305ee932d049a4e6e1e134f521dbb98fdd3993a8e9Fabian Frederick struct nouveau_plane *nv_plane = 4315ee932d049a4e6e1e134f521dbb98fdd3993a8e9Fabian Frederick container_of(plane, struct nouveau_plane, base); 432ab9b18a6a13c438505d3419bd59dcd8e1856ceddIlia Mirkin 433db2bec187dd68e79d512112df1f6e7a849e7f0ceBen Skeggs nvif_mask(dev, NV_PVIDEO_OVERLAY, 1, 0); 434db2bec187dd68e79d512112df1f6e7a849e7f0ceBen Skeggs nvif_wr32(dev, NV_PVIDEO_OE_STATE, 0); 435db2bec187dd68e79d512112df1f6e7a849e7f0ceBen Skeggs nvif_wr32(dev, NV_PVIDEO_SU_STATE, 0); 436db2bec187dd68e79d512112df1f6e7a849e7f0ceBen Skeggs nvif_wr32(dev, NV_PVIDEO_RM_STATE, 0); 437ab9b18a6a13c438505d3419bd59dcd8e1856ceddIlia Mirkin if (nv_plane->cur) { 438ab9b18a6a13c438505d3419bd59dcd8e1856ceddIlia Mirkin nouveau_bo_unpin(nv_plane->cur); 439ab9b18a6a13c438505d3419bd59dcd8e1856ceddIlia Mirkin nv_plane->cur = NULL; 440ab9b18a6a13c438505d3419bd59dcd8e1856ceddIlia Mirkin } 441ab9b18a6a13c438505d3419bd59dcd8e1856ceddIlia Mirkin 442ab9b18a6a13c438505d3419bd59dcd8e1856ceddIlia Mirkin return 0; 443ab9b18a6a13c438505d3419bd59dcd8e1856ceddIlia Mirkin} 444ab9b18a6a13c438505d3419bd59dcd8e1856ceddIlia Mirkin 445ab9b18a6a13c438505d3419bd59dcd8e1856ceddIlia Mirkinstatic const struct drm_plane_funcs nv04_plane_funcs = { 446ab9b18a6a13c438505d3419bd59dcd8e1856ceddIlia Mirkin .update_plane = nv04_update_plane, 447ab9b18a6a13c438505d3419bd59dcd8e1856ceddIlia Mirkin .disable_plane = nv04_disable_plane, 448ab9b18a6a13c438505d3419bd59dcd8e1856ceddIlia Mirkin .set_property = nv_set_property, 449ab9b18a6a13c438505d3419bd59dcd8e1856ceddIlia Mirkin .destroy = nv_destroy_plane, 450ab9b18a6a13c438505d3419bd59dcd8e1856ceddIlia Mirkin}; 451ab9b18a6a13c438505d3419bd59dcd8e1856ceddIlia Mirkin 452ab9b18a6a13c438505d3419bd59dcd8e1856ceddIlia Mirkinstatic void 453ab9b18a6a13c438505d3419bd59dcd8e1856ceddIlia Mirkinnv04_overlay_init(struct drm_device *device) 454ab9b18a6a13c438505d3419bd59dcd8e1856ceddIlia Mirkin{ 455fa2bade99a6fb24c3847d48ba3cad9a70dbb5364Ben Skeggs struct nouveau_drm *drm = nouveau_drm(device); 456ab9b18a6a13c438505d3419bd59dcd8e1856ceddIlia Mirkin struct nouveau_plane *plane = kzalloc(sizeof(struct nouveau_plane), GFP_KERNEL); 457ab9b18a6a13c438505d3419bd59dcd8e1856ceddIlia Mirkin int ret; 458ab9b18a6a13c438505d3419bd59dcd8e1856ceddIlia Mirkin 459ab9b18a6a13c438505d3419bd59dcd8e1856ceddIlia Mirkin if (!plane) 460ab9b18a6a13c438505d3419bd59dcd8e1856ceddIlia Mirkin return; 461ab9b18a6a13c438505d3419bd59dcd8e1856ceddIlia Mirkin 462ab9b18a6a13c438505d3419bd59dcd8e1856ceddIlia Mirkin ret = drm_plane_init(device, &plane->base, 1 /* single crtc */, 463ab9b18a6a13c438505d3419bd59dcd8e1856ceddIlia Mirkin &nv04_plane_funcs, 464ab9b18a6a13c438505d3419bd59dcd8e1856ceddIlia Mirkin formats, 2, false); 465ab9b18a6a13c438505d3419bd59dcd8e1856ceddIlia Mirkin if (ret) 466ab9b18a6a13c438505d3419bd59dcd8e1856ceddIlia Mirkin goto err; 467ab9b18a6a13c438505d3419bd59dcd8e1856ceddIlia Mirkin 468ab9b18a6a13c438505d3419bd59dcd8e1856ceddIlia Mirkin /* Set up the plane properties */ 469ab9b18a6a13c438505d3419bd59dcd8e1856ceddIlia Mirkin plane->props.colorkey = drm_property_create_range( 470ab9b18a6a13c438505d3419bd59dcd8e1856ceddIlia Mirkin device, 0, "colorkey", 0, 0x01ffffff); 471ab9b18a6a13c438505d3419bd59dcd8e1856ceddIlia Mirkin plane->props.brightness = drm_property_create_range( 472ab9b18a6a13c438505d3419bd59dcd8e1856ceddIlia Mirkin device, 0, "brightness", 0, 1024); 473ab9b18a6a13c438505d3419bd59dcd8e1856ceddIlia Mirkin if (!plane->props.colorkey || 474ab9b18a6a13c438505d3419bd59dcd8e1856ceddIlia Mirkin !plane->props.brightness) 475ab9b18a6a13c438505d3419bd59dcd8e1856ceddIlia Mirkin goto cleanup; 476ab9b18a6a13c438505d3419bd59dcd8e1856ceddIlia Mirkin 477ab9b18a6a13c438505d3419bd59dcd8e1856ceddIlia Mirkin plane->colorkey = 0; 478ab9b18a6a13c438505d3419bd59dcd8e1856ceddIlia Mirkin drm_object_attach_property(&plane->base.base, 479ab9b18a6a13c438505d3419bd59dcd8e1856ceddIlia Mirkin plane->props.colorkey, plane->colorkey); 480ab9b18a6a13c438505d3419bd59dcd8e1856ceddIlia Mirkin 481ab9b18a6a13c438505d3419bd59dcd8e1856ceddIlia Mirkin plane->brightness = 512; 482ab9b18a6a13c438505d3419bd59dcd8e1856ceddIlia Mirkin drm_object_attach_property(&plane->base.base, 483ab9b18a6a13c438505d3419bd59dcd8e1856ceddIlia Mirkin plane->props.brightness, plane->brightness); 484ab9b18a6a13c438505d3419bd59dcd8e1856ceddIlia Mirkin 485ab9b18a6a13c438505d3419bd59dcd8e1856ceddIlia Mirkin nv04_disable_plane(&plane->base); 486515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin return; 487515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkincleanup: 488515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin drm_plane_cleanup(&plane->base); 489515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkinerr: 490515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin kfree(plane); 491fa2bade99a6fb24c3847d48ba3cad9a70dbb5364Ben Skeggs NV_ERROR(drm, "Failed to create plane\n"); 492515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin} 493515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin 494515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkinvoid 495515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkinnouveau_overlay_init(struct drm_device *device) 496515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin{ 497967e7bde8739fe3b215f7537e8f1f39c044902afBen Skeggs struct nvif_device *dev = &nouveau_drm(device)->device; 498967e7bde8739fe3b215f7537e8f1f39c044902afBen Skeggs if (dev->info.chipset < 0x10) 499ab9b18a6a13c438505d3419bd59dcd8e1856ceddIlia Mirkin nv04_overlay_init(device); 500967e7bde8739fe3b215f7537e8f1f39c044902afBen Skeggs else if (dev->info.chipset <= 0x40) 501515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin nv10_overlay_init(device); 502515de6b27f96fb7ff58f34bda6e1be44a6f9e46dIlia Mirkin} 503