/*
* Copyright (c) 2011, 2013 Intel Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Authors:
* Jesse Barnes <jbarnes@virtuousgeek.org>
*
*
* The older chips had a separate interface for programming plane related
* registers; newer ones are much simpler and we can use the new DRM plane
* support.
*/
#include "drmP.h"
#include "drm_crtc.h"
#include "drm_fourcc.h"
#include "drm_rect.h"
#include "intel_drv.h"
#include "i915_drm.h"
#include "i915_drv.h"
static void
int x, int y,
{
/* Mask out pixel format bits in case we change it */
sprctl &= ~SP_PIXFORMAT_MASK;
switch (fb->pixel_format) {
case DRM_FORMAT_YUYV:
break;
case DRM_FORMAT_YVYU:
break;
case DRM_FORMAT_UYVY:
break;
case DRM_FORMAT_VYUY:
break;
case DRM_FORMAT_RGB565:
break;
case DRM_FORMAT_XRGB8888:
break;
case DRM_FORMAT_ARGB8888:
break;
case DRM_FORMAT_XBGR2101010:
break;
case DRM_FORMAT_ABGR2101010:
break;
case DRM_FORMAT_XBGR8888:
break;
case DRM_FORMAT_ABGR8888:
break;
default:
/*
* If we get here one of the upper layers failed to filter
* out the unsupported plane formats
*/
BUG();
break;
}
/* Sizes are 0 based */
src_w--;
src_h--;
crtc_w--;
crtc_h--;
sprsurf_offset = intel_gen4_compute_page_offset(&x, &y,
else
}
static void
{
~SP_ENABLE);
/* Activate double buffered register update */
}
static int
struct drm_intel_sprite_colorkey *key)
{
return -EINVAL;
sprctl &= ~SP_SOURCE_KEY;
sprctl |= SP_SOURCE_KEY;
return 0;
}
static void
struct drm_intel_sprite_colorkey *key)
{
if (sprctl & SP_SOURCE_KEY)
else
}
static void
int x, int y,
{
/* Mask out pixel format bits in case we change it */
sprctl &= ~SPRITE_TILED;
switch (fb->pixel_format) {
case DRM_FORMAT_XBGR8888:
break;
case DRM_FORMAT_XRGB8888:
break;
case DRM_FORMAT_YUYV:
break;
case DRM_FORMAT_YVYU:
break;
case DRM_FORMAT_UYVY:
break;
case DRM_FORMAT_VYUY:
break;
default:
BUG();
}
sprctl |= SPRITE_TILED;
/* must disable */
sprctl |= SPRITE_ENABLE;
if (IS_HASWELL(dev))
/* Sizes are 0 based */
src_w--;
src_h--;
crtc_w--;
crtc_h--;
/*
* IVB workaround: must disable low power watermarks for at least
* one frame before enabling scaling. LP watermarks can be re-enabled
* when scaling is disabled.
*/
if (!scaling_was_enabled) {
}
} else
/* HSW consolidates SPRTILEOFF and SPRLINOFF into a single SPROFFSET
* register */
if (IS_HASWELL(dev))
else
if (intel_plane->can_scale)
/* potentially re-enable LP watermarks */
}
static void
{
/* Can't leave the scaler enabled... */
if (intel_plane->can_scale)
/* Activate double buffered register update */
/* potentially re-enable LP watermarks */
}
static int
struct drm_intel_sprite_colorkey *key)
{
int ret = 0;
return ret;
}
static void
{
if (sprctl & SPRITE_DEST_KEY)
else if (sprctl & SPRITE_SOURCE_KEY)
else
}
static void
int x, int y,
{
/* Mask out pixel format bits in case we change it */
switch (fb->pixel_format) {
case DRM_FORMAT_XBGR8888:
break;
case DRM_FORMAT_XRGB8888:
break;
case DRM_FORMAT_YUYV:
break;
case DRM_FORMAT_YVYU:
break;
case DRM_FORMAT_UYVY:
break;
case DRM_FORMAT_VYUY:
break;
default:
BUG();
}
dvscntr |= DVS_ENABLE;
/* Sizes are 0 based */
src_w--;
src_h--;
crtc_w--;
crtc_h--;
dvsscale = 0;
else
}
static void
{
/* Disable the scaler */
/* Flush double buffered register updates */
}
static void
{
if (!intel_crtc->primary_disabled)
return;
intel_crtc->primary_disabled = false;
}
static void
{
if (intel_crtc->primary_disabled)
return;
intel_crtc->primary_disabled = true;
}
static int
struct drm_intel_sprite_colorkey *key)
{
int ret = 0;
dvscntr |= DVS_DEST_KEY;
return ret;
}
static void
{
if (dvscntr & DVS_DEST_KEY)
else if (dvscntr & DVS_SOURCE_KEY)
else
}
static bool
{
switch (format) {
case DRM_FORMAT_YUYV:
case DRM_FORMAT_UYVY:
case DRM_FORMAT_VYUY:
case DRM_FORMAT_YVYU:
return true;
default:
return false;
}
}
static int
{
pipe);
int ret = 0;
bool disable_primary = false;
bool visible;
/* sample coordinates in 16.16 fixed point */
};
/* integer pixels */
};
};
/* Pipe must be running... */
DRM_DEBUG_KMS("Pipe disabled\n");
return -EINVAL;
}
/* Don't modify another pipe's plane */
DRM_DEBUG_KMS("Wrong plane <-> crtc mapping\n");
return -EINVAL;
}
/* FIXME check all gen limits */
DRM_DEBUG_KMS("Unsuitable framebuffer for plane\n");
return -EINVAL;
}
/* Sprite planes can be linear or x-tiled surfaces */
switch (obj->tiling_mode) {
case I915_TILING_NONE:
case I915_TILING_X:
break;
default:
DRM_DEBUG_KMS("Unsupported tiling mode\n");
return -EINVAL;
}
/*
* FIXME the following code does a bunch of fuzzy adjustments to the
* coordinates and sizes. We probably need some way to decide whether
* more strict checking should be done instead.
*/
if (visible) {
/* check again in case clipping clamped the results */
if (hscale < 0) {
DRM_DEBUG_KMS("Horizontal scaling factor out of limits\n");
drm_rect_debug_print(&src, true);
drm_rect_debug_print(&dst, false);
return hscale;
}
if (vscale < 0) {
DRM_DEBUG_KMS("Vertical scaling factor out of limits\n");
drm_rect_debug_print(&src, true);
drm_rect_debug_print(&dst, false);
return vscale;
}
/* Make the source viewport size an exact multiple of the scaling factors. */
/* sanity check to make sure the src viewport wasn't enlarged */
/*
* Hardware doesn't handle subpixel coordinates.
* Adjust to (macro)pixel boundary, but be careful not to
* increase the source viewport size, because that could
* push the downscaling factor out of bounds.
*/
src_x &= ~1;
src_w &= ~1;
/*
* Must keep src and dst the
* same if we can't scale.
*/
if (!intel_plane->can_scale)
crtc_w &= ~1;
if (crtc_w == 0)
visible = false;
}
}
/* Check size restrictions when scaling */
unsigned int width_bytes;
/* FIXME interlacing min height is 6 */
visible = false;
visible = false;
DRM_DEBUG_KMS("Source dimensions exceed hardware limits\n");
return -EINVAL;
}
}
/*
* If the sprite is completely covering the primary plane,
* we can disable the primary and save power.
*/
/* Note that this will apply the VT-d workaround for scanouts,
* which is more restrictive than required for sprites. (The
* primary plane requires 256KiB alignment with 64 PTE padding,
* the sprite planes only require 128KiB alignment and 32 PTE padding.
*/
if (ret)
goto out_unlock;
/*
* Be sure to re-enable the primary before the sprite is no longer
* covering it fully.
*/
if (!disable_primary)
if (visible)
else
if (disable_primary)
/* Unpin old obj after new one is active to avoid ugliness */
if (old_obj) {
/*
* It's fairly common to simply update the position of
* an existing object. In that case, we don't need to
* wait for vblank to avoid ugliness, we only need to
* do the pin & ref bookkeeping.
*/
}
}
return ret;
}
static int
{
int ret = 0;
if (!intel_plane->obj)
goto out;
out:
return ret;
}
{
}
{
int ret = 0;
return -ENODEV;
/* Make sure we don't try to enable both src & dest simultaneously */
if ((set->flags & (I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE)) == (I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE))
return -EINVAL;
if (!obj) {
goto out_unlock;
}
return ret;
}
{
int ret = 0;
return -ENODEV;
if (!obj) {
goto out_unlock;
}
return ret;
}
{
return;
}
{
return;
}
};
};
};
};
int
{
unsigned long possible_crtcs;
int num_plane_formats;
int ret;
return -ENODEV;
if (!intel_plane)
return -ENOMEM;
case 5:
case 6:
intel_plane->can_scale = true;
} else {
}
break;
case 7:
if (IS_IVYBRIDGE(dev)) {
intel_plane->can_scale = true;
} else {
intel_plane->can_scale = false;
}
if (IS_VALLEYVIEW(dev)) {
} else {
}
break;
default:
return -ENODEV;
}
false);
if (ret)
return ret;
}