2011-12-13 13:19:38 -08:00
/*
* Copyright © 2011 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 ,
* and / or sell copies of the Software , and to permit persons to whom the
* 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 >
*
* New plane / sprite handling .
*
* 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 "intel_drv.h"
# include "i915_drm.h"
# include "i915_drv.h"
static void
ivb_update_plane ( struct drm_plane * plane , struct drm_framebuffer * fb ,
struct drm_i915_gem_object * obj , int crtc_x , int crtc_y ,
unsigned int crtc_w , unsigned int crtc_h ,
uint32_t x , uint32_t y ,
uint32_t src_w , uint32_t src_h )
{
struct drm_device * dev = plane - > dev ;
struct drm_i915_private * dev_priv = dev - > dev_private ;
struct intel_plane * intel_plane = to_intel_plane ( plane ) ;
int pipe = intel_plane - > pipe ;
u32 sprctl , sprscale = 0 ;
int pixel_size ;
sprctl = I915_READ ( SPRCTL ( pipe ) ) ;
/* Mask out pixel format bits in case we change it */
sprctl & = ~ SPRITE_PIXFORMAT_MASK ;
sprctl & = ~ SPRITE_RGB_ORDER_RGBX ;
sprctl & = ~ SPRITE_YUV_BYTE_ORDER_MASK ;
switch ( fb - > pixel_format ) {
case DRM_FORMAT_XBGR8888 :
sprctl | = SPRITE_FORMAT_RGBX888 ;
pixel_size = 4 ;
break ;
case DRM_FORMAT_XRGB8888 :
sprctl | = SPRITE_FORMAT_RGBX888 | SPRITE_RGB_ORDER_RGBX ;
pixel_size = 4 ;
break ;
case DRM_FORMAT_YUYV :
sprctl | = SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_YUYV ;
pixel_size = 2 ;
break ;
case DRM_FORMAT_YVYU :
sprctl | = SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_YVYU ;
pixel_size = 2 ;
break ;
case DRM_FORMAT_UYVY :
sprctl | = SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_UYVY ;
pixel_size = 2 ;
break ;
case DRM_FORMAT_VYUY :
sprctl | = SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_VYUY ;
pixel_size = 2 ;
break ;
default :
DRM_DEBUG_DRIVER ( " bad pixel format, assuming RGBX888 \n " ) ;
sprctl | = DVS_FORMAT_RGBX888 ;
pixel_size = 4 ;
break ;
}
if ( obj - > tiling_mode ! = I915_TILING_NONE )
sprctl | = SPRITE_TILED ;
/* must disable */
sprctl | = SPRITE_TRICKLE_FEED_DISABLE ;
sprctl | = SPRITE_ENABLE ;
2012-01-03 08:05:39 -08:00
sprctl | = SPRITE_DEST_KEY ;
2011-12-13 13:19:38 -08:00
/* Sizes are 0 based */
src_w - - ;
src_h - - ;
crtc_w - - ;
crtc_h - - ;
intel_update_sprite_watermarks ( dev , pipe , crtc_w , pixel_size ) ;
/*
* 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 ( crtc_w ! = src_w | | crtc_h ! = src_h ) {
dev_priv - > sprite_scaling_enabled = true ;
sandybridge_update_wm ( dev ) ;
intel_wait_for_vblank ( dev , pipe ) ;
sprscale = SPRITE_SCALE_ENABLE | ( src_w < < 16 ) | src_h ;
} else {
dev_priv - > sprite_scaling_enabled = false ;
/* potentially re-enable LP watermarks */
sandybridge_update_wm ( dev ) ;
}
I915_WRITE ( SPRSTRIDE ( pipe ) , fb - > pitches [ 0 ] ) ;
I915_WRITE ( SPRPOS ( pipe ) , ( crtc_y < < 16 ) | crtc_x ) ;
if ( obj - > tiling_mode ! = I915_TILING_NONE ) {
I915_WRITE ( SPRTILEOFF ( pipe ) , ( y < < 16 ) | x ) ;
} else {
unsigned long offset ;
offset = y * fb - > pitches [ 0 ] + x * ( fb - > bits_per_pixel / 8 ) ;
I915_WRITE ( SPRLINOFF ( pipe ) , offset ) ;
}
I915_WRITE ( SPRSIZE ( pipe ) , ( crtc_h < < 16 ) | crtc_w ) ;
I915_WRITE ( SPRSCALE ( pipe ) , sprscale ) ;
I915_WRITE ( SPRCTL ( pipe ) , sprctl ) ;
I915_WRITE ( SPRSURF ( pipe ) , obj - > gtt_offset ) ;
POSTING_READ ( SPRSURF ( pipe ) ) ;
}
static void
ivb_disable_plane ( struct drm_plane * plane )
{
struct drm_device * dev = plane - > dev ;
struct drm_i915_private * dev_priv = dev - > dev_private ;
struct intel_plane * intel_plane = to_intel_plane ( plane ) ;
int pipe = intel_plane - > pipe ;
I915_WRITE ( SPRCTL ( pipe ) , I915_READ ( SPRCTL ( pipe ) ) & ~ SPRITE_ENABLE ) ;
/* Can't leave the scaler enabled... */
I915_WRITE ( SPRSCALE ( pipe ) , 0 ) ;
/* Activate double buffered register update */
I915_WRITE ( SPRSURF ( pipe ) , 0 ) ;
POSTING_READ ( SPRSURF ( pipe ) ) ;
}
2012-01-03 08:05:39 -08:00
static int
ivb_update_colorkey ( struct drm_plane * plane ,
struct drm_intel_sprite_colorkey * key )
{
struct drm_device * dev = plane - > dev ;
struct drm_i915_private * dev_priv = dev - > dev_private ;
struct intel_plane * intel_plane ;
u32 sprctl ;
int ret = 0 ;
intel_plane = to_intel_plane ( plane ) ;
I915_WRITE ( SPRKEYVAL ( intel_plane - > pipe ) , key - > min_value ) ;
I915_WRITE ( SPRKEYMAX ( intel_plane - > pipe ) , key - > max_value ) ;
I915_WRITE ( SPRKEYMSK ( intel_plane - > pipe ) , key - > channel_mask ) ;
sprctl = I915_READ ( SPRCTL ( intel_plane - > pipe ) ) ;
sprctl & = ~ ( SPRITE_SOURCE_KEY | SPRITE_DEST_KEY ) ;
if ( key - > flags & I915_SET_COLORKEY_DESTINATION )
sprctl | = SPRITE_DEST_KEY ;
else if ( key - > flags & I915_SET_COLORKEY_SOURCE )
sprctl | = SPRITE_SOURCE_KEY ;
I915_WRITE ( SPRCTL ( intel_plane - > pipe ) , sprctl ) ;
POSTING_READ ( SPRKEYMSK ( intel_plane - > pipe ) ) ;
return ret ;
}
static void
ivb_get_colorkey ( struct drm_plane * plane , struct drm_intel_sprite_colorkey * key )
{
struct drm_device * dev = plane - > dev ;
struct drm_i915_private * dev_priv = dev - > dev_private ;
struct intel_plane * intel_plane ;
u32 sprctl ;
intel_plane = to_intel_plane ( plane ) ;
key - > min_value = I915_READ ( SPRKEYVAL ( intel_plane - > pipe ) ) ;
key - > max_value = I915_READ ( SPRKEYMAX ( intel_plane - > pipe ) ) ;
key - > channel_mask = I915_READ ( SPRKEYMSK ( intel_plane - > pipe ) ) ;
key - > flags = 0 ;
sprctl = I915_READ ( SPRCTL ( intel_plane - > pipe ) ) ;
if ( sprctl & SPRITE_DEST_KEY )
key - > flags = I915_SET_COLORKEY_DESTINATION ;
else if ( sprctl & SPRITE_SOURCE_KEY )
key - > flags = I915_SET_COLORKEY_SOURCE ;
else
key - > flags = I915_SET_COLORKEY_NONE ;
}
2011-12-13 13:19:38 -08:00
static void
snb_update_plane ( struct drm_plane * plane , struct drm_framebuffer * fb ,
struct drm_i915_gem_object * obj , int crtc_x , int crtc_y ,
unsigned int crtc_w , unsigned int crtc_h ,
uint32_t x , uint32_t y ,
uint32_t src_w , uint32_t src_h )
{
struct drm_device * dev = plane - > dev ;
struct drm_i915_private * dev_priv = dev - > dev_private ;
struct intel_plane * intel_plane = to_intel_plane ( plane ) ;
int pipe = intel_plane - > pipe , pixel_size ;
u32 dvscntr , dvsscale = 0 ;
dvscntr = I915_READ ( DVSCNTR ( pipe ) ) ;
/* Mask out pixel format bits in case we change it */
dvscntr & = ~ DVS_PIXFORMAT_MASK ;
dvscntr & = ~ DVS_RGB_ORDER_RGBX ;
dvscntr & = ~ DVS_YUV_BYTE_ORDER_MASK ;
switch ( fb - > pixel_format ) {
case DRM_FORMAT_XBGR8888 :
dvscntr | = DVS_FORMAT_RGBX888 ;
pixel_size = 4 ;
break ;
case DRM_FORMAT_XRGB8888 :
dvscntr | = DVS_FORMAT_RGBX888 | DVS_RGB_ORDER_RGBX ;
pixel_size = 4 ;
break ;
case DRM_FORMAT_YUYV :
dvscntr | = DVS_FORMAT_YUV422 | DVS_YUV_ORDER_YUYV ;
pixel_size = 2 ;
break ;
case DRM_FORMAT_YVYU :
dvscntr | = DVS_FORMAT_YUV422 | DVS_YUV_ORDER_YVYU ;
pixel_size = 2 ;
break ;
case DRM_FORMAT_UYVY :
dvscntr | = DVS_FORMAT_YUV422 | DVS_YUV_ORDER_UYVY ;
pixel_size = 2 ;
break ;
case DRM_FORMAT_VYUY :
dvscntr | = DVS_FORMAT_YUV422 | DVS_YUV_ORDER_VYUY ;
pixel_size = 2 ;
break ;
default :
DRM_DEBUG_DRIVER ( " bad pixel format, assuming RGBX888 \n " ) ;
dvscntr | = DVS_FORMAT_RGBX888 ;
pixel_size = 4 ;
break ;
}
if ( obj - > tiling_mode ! = I915_TILING_NONE )
dvscntr | = DVS_TILED ;
/* must disable */
dvscntr | = DVS_TRICKLE_FEED_DISABLE ;
dvscntr | = DVS_ENABLE ;
/* Sizes are 0 based */
src_w - - ;
src_h - - ;
crtc_w - - ;
crtc_h - - ;
intel_update_sprite_watermarks ( dev , pipe , crtc_w , pixel_size ) ;
if ( crtc_w ! = src_w | | crtc_h ! = src_h )
dvsscale = DVS_SCALE_ENABLE | ( src_w < < 16 ) | src_h ;
I915_WRITE ( DVSSTRIDE ( pipe ) , fb - > pitches [ 0 ] ) ;
I915_WRITE ( DVSPOS ( pipe ) , ( crtc_y < < 16 ) | crtc_x ) ;
if ( obj - > tiling_mode ! = I915_TILING_NONE ) {
I915_WRITE ( DVSTILEOFF ( pipe ) , ( y < < 16 ) | x ) ;
} else {
unsigned long offset ;
offset = y * fb - > pitches [ 0 ] + x * ( fb - > bits_per_pixel / 8 ) ;
I915_WRITE ( DVSLINOFF ( pipe ) , offset ) ;
}
I915_WRITE ( DVSSIZE ( pipe ) , ( crtc_h < < 16 ) | crtc_w ) ;
I915_WRITE ( DVSSCALE ( pipe ) , dvsscale ) ;
I915_WRITE ( DVSCNTR ( pipe ) , dvscntr ) ;
I915_WRITE ( DVSSURF ( pipe ) , obj - > gtt_offset ) ;
POSTING_READ ( DVSSURF ( pipe ) ) ;
}
static void
snb_disable_plane ( struct drm_plane * plane )
{
struct drm_device * dev = plane - > dev ;
struct drm_i915_private * dev_priv = dev - > dev_private ;
struct intel_plane * intel_plane = to_intel_plane ( plane ) ;
int pipe = intel_plane - > pipe ;
I915_WRITE ( DVSCNTR ( pipe ) , I915_READ ( DVSCNTR ( pipe ) ) & ~ DVS_ENABLE ) ;
/* Disable the scaler */
I915_WRITE ( DVSSCALE ( pipe ) , 0 ) ;
/* Flush double buffered register updates */
I915_WRITE ( DVSSURF ( pipe ) , 0 ) ;
POSTING_READ ( DVSSURF ( pipe ) ) ;
}
2011-12-13 13:19:39 -08:00
static void
intel_enable_primary ( struct drm_crtc * crtc )
{
struct drm_device * dev = crtc - > dev ;
struct drm_i915_private * dev_priv = dev - > dev_private ;
struct intel_crtc * intel_crtc = to_intel_crtc ( crtc ) ;
int reg = DSPCNTR ( intel_crtc - > plane ) ;
I915_WRITE ( reg , I915_READ ( reg ) | DISPLAY_PLANE_ENABLE ) ;
}
static void
intel_disable_primary ( struct drm_crtc * crtc )
{
struct drm_device * dev = crtc - > dev ;
struct drm_i915_private * dev_priv = dev - > dev_private ;
struct intel_crtc * intel_crtc = to_intel_crtc ( crtc ) ;
int reg = DSPCNTR ( intel_crtc - > plane ) ;
I915_WRITE ( reg , I915_READ ( reg ) & ~ DISPLAY_PLANE_ENABLE ) ;
}
2012-01-03 08:05:39 -08:00
static int
snb_update_colorkey ( struct drm_plane * plane ,
struct drm_intel_sprite_colorkey * key )
{
struct drm_device * dev = plane - > dev ;
struct drm_i915_private * dev_priv = dev - > dev_private ;
struct intel_plane * intel_plane ;
u32 dvscntr ;
int ret = 0 ;
intel_plane = to_intel_plane ( plane ) ;
I915_WRITE ( DVSKEYVAL ( intel_plane - > pipe ) , key - > min_value ) ;
I915_WRITE ( DVSKEYMAX ( intel_plane - > pipe ) , key - > max_value ) ;
I915_WRITE ( DVSKEYMSK ( intel_plane - > pipe ) , key - > channel_mask ) ;
dvscntr = I915_READ ( DVSCNTR ( intel_plane - > pipe ) ) ;
dvscntr & = ~ ( DVS_SOURCE_KEY | DVS_DEST_KEY ) ;
if ( key - > flags & I915_SET_COLORKEY_DESTINATION )
dvscntr | = DVS_DEST_KEY ;
else if ( key - > flags & I915_SET_COLORKEY_SOURCE )
dvscntr | = DVS_SOURCE_KEY ;
I915_WRITE ( DVSCNTR ( intel_plane - > pipe ) , dvscntr ) ;
POSTING_READ ( DVSKEYMSK ( intel_plane - > pipe ) ) ;
return ret ;
}
static void
snb_get_colorkey ( struct drm_plane * plane , struct drm_intel_sprite_colorkey * key )
{
struct drm_device * dev = plane - > dev ;
struct drm_i915_private * dev_priv = dev - > dev_private ;
struct intel_plane * intel_plane ;
u32 dvscntr ;
intel_plane = to_intel_plane ( plane ) ;
key - > min_value = I915_READ ( DVSKEYVAL ( intel_plane - > pipe ) ) ;
key - > max_value = I915_READ ( DVSKEYMAX ( intel_plane - > pipe ) ) ;
key - > channel_mask = I915_READ ( DVSKEYMSK ( intel_plane - > pipe ) ) ;
key - > flags = 0 ;
dvscntr = I915_READ ( DVSCNTR ( intel_plane - > pipe ) ) ;
if ( dvscntr & DVS_DEST_KEY )
key - > flags = I915_SET_COLORKEY_DESTINATION ;
else if ( dvscntr & DVS_SOURCE_KEY )
key - > flags = I915_SET_COLORKEY_SOURCE ;
else
key - > flags = I915_SET_COLORKEY_NONE ;
}
2011-12-13 13:19:38 -08:00
static int
intel_update_plane ( struct drm_plane * plane , struct drm_crtc * crtc ,
struct drm_framebuffer * fb , int crtc_x , int crtc_y ,
unsigned int crtc_w , unsigned int crtc_h ,
uint32_t src_x , uint32_t src_y ,
uint32_t src_w , uint32_t src_h )
{
struct drm_device * dev = plane - > dev ;
struct drm_i915_private * dev_priv = dev - > dev_private ;
struct intel_crtc * intel_crtc = to_intel_crtc ( crtc ) ;
struct intel_plane * intel_plane = to_intel_plane ( plane ) ;
struct intel_framebuffer * intel_fb ;
struct drm_i915_gem_object * obj , * old_obj ;
int pipe = intel_plane - > pipe ;
int ret = 0 ;
int x = src_x > > 16 , y = src_y > > 16 ;
int primary_w = crtc - > mode . hdisplay , primary_h = crtc - > mode . vdisplay ;
bool disable_primary = false ;
intel_fb = to_intel_framebuffer ( fb ) ;
obj = intel_fb - > obj ;
old_obj = intel_plane - > obj ;
/* Pipe must be running... */
if ( ! ( I915_READ ( PIPECONF ( pipe ) ) & PIPECONF_ENABLE ) )
return - EINVAL ;
if ( crtc_x > = primary_w | | crtc_y > = primary_h )
return - EINVAL ;
/* Don't modify another pipe's plane */
if ( intel_plane - > pipe ! = intel_crtc - > pipe )
return - EINVAL ;
/*
* Clamp the width & height into the visible area . Note we don ' t
* try to scale the source if part of the visible region is offscreen .
* The caller must handle that by adjusting source offset and size .
*/
if ( ( crtc_x < 0 ) & & ( ( crtc_x + crtc_w ) > 0 ) ) {
crtc_w + = crtc_x ;
crtc_x = 0 ;
}
if ( ( crtc_x + crtc_w ) < = 0 ) /* Nothing to display */
goto out ;
if ( ( crtc_x + crtc_w ) > primary_w )
crtc_w = primary_w - crtc_x ;
if ( ( crtc_y < 0 ) & & ( ( crtc_y + crtc_h ) > 0 ) ) {
crtc_h + = crtc_y ;
crtc_y = 0 ;
}
if ( ( crtc_y + crtc_h ) < = 0 ) /* Nothing to display */
goto out ;
if ( crtc_y + crtc_h > primary_h )
crtc_h = primary_h - crtc_y ;
if ( ! crtc_w | | ! crtc_h ) /* Again, nothing to display */
goto out ;
/*
* We can take a larger source and scale it down , but
* only so much . . . 16 x is the max on SNB .
*/
if ( ( ( src_w * src_h ) / ( crtc_w * crtc_h ) ) > intel_plane - > max_downscale )
return - EINVAL ;
/*
* If the sprite is completely covering the primary plane ,
* we can disable the primary and save power .
*/
if ( ( crtc_x = = 0 ) & & ( crtc_y = = 0 ) & &
( crtc_w = = primary_w ) & & ( crtc_h = = primary_h ) )
disable_primary = true ;
mutex_lock ( & dev - > struct_mutex ) ;
ret = intel_pin_and_fence_fb_obj ( dev , obj , NULL ) ;
2012-01-13 15:48:39 -08:00
if ( ret )
2011-12-13 13:19:38 -08:00
goto out_unlock ;
intel_plane - > obj = obj ;
2011-12-13 13:19:39 -08:00
/*
* Be sure to re - enable the primary before the sprite is no longer
* covering it fully .
*/
if ( ! disable_primary & & intel_plane - > primary_disabled ) {
intel_enable_primary ( crtc ) ;
intel_plane - > primary_disabled = false ;
}
2011-12-13 13:19:38 -08:00
intel_plane - > update_plane ( plane , fb , obj , crtc_x , crtc_y ,
crtc_w , crtc_h , x , y , src_w , src_h ) ;
2011-12-13 13:19:39 -08:00
if ( disable_primary ) {
intel_disable_primary ( crtc ) ;
intel_plane - > primary_disabled = true ;
}
2011-12-13 13:19:38 -08:00
/* 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 .
*/
if ( old_obj ! = obj ) {
mutex_unlock ( & dev - > struct_mutex ) ;
intel_wait_for_vblank ( dev , to_intel_crtc ( crtc ) - > pipe ) ;
mutex_lock ( & dev - > struct_mutex ) ;
}
i915_gem_object_unpin ( old_obj ) ;
}
out_unlock :
mutex_unlock ( & dev - > struct_mutex ) ;
out :
return ret ;
}
static int
intel_disable_plane ( struct drm_plane * plane )
{
struct drm_device * dev = plane - > dev ;
struct intel_plane * intel_plane = to_intel_plane ( plane ) ;
int ret = 0 ;
2011-12-13 13:19:39 -08:00
if ( intel_plane - > primary_disabled ) {
intel_enable_primary ( plane - > crtc ) ;
intel_plane - > primary_disabled = false ;
}
2011-12-13 13:19:38 -08:00
intel_plane - > disable_plane ( plane ) ;
if ( ! intel_plane - > obj )
goto out ;
mutex_lock ( & dev - > struct_mutex ) ;
i915_gem_object_unpin ( intel_plane - > obj ) ;
intel_plane - > obj = NULL ;
mutex_unlock ( & dev - > struct_mutex ) ;
out :
return ret ;
}
static void intel_destroy_plane ( struct drm_plane * plane )
{
struct intel_plane * intel_plane = to_intel_plane ( plane ) ;
intel_disable_plane ( plane ) ;
drm_plane_cleanup ( plane ) ;
kfree ( intel_plane ) ;
}
2012-01-03 08:05:39 -08:00
int intel_sprite_set_colorkey ( struct drm_device * dev , void * data ,
struct drm_file * file_priv )
{
struct drm_intel_sprite_colorkey * set = data ;
struct drm_i915_private * dev_priv = dev - > dev_private ;
struct drm_mode_object * obj ;
struct drm_plane * plane ;
struct intel_plane * intel_plane ;
int ret = 0 ;
if ( ! dev_priv )
return - EINVAL ;
/* 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 ;
mutex_lock ( & dev - > mode_config . mutex ) ;
obj = drm_mode_object_find ( dev , set - > plane_id , DRM_MODE_OBJECT_PLANE ) ;
if ( ! obj ) {
ret = - EINVAL ;
goto out_unlock ;
}
plane = obj_to_plane ( obj ) ;
intel_plane = to_intel_plane ( plane ) ;
ret = intel_plane - > update_colorkey ( plane , set ) ;
out_unlock :
mutex_unlock ( & dev - > mode_config . mutex ) ;
return ret ;
}
int intel_sprite_get_colorkey ( struct drm_device * dev , void * data ,
struct drm_file * file_priv )
{
struct drm_intel_sprite_colorkey * get = data ;
struct drm_i915_private * dev_priv = dev - > dev_private ;
struct drm_mode_object * obj ;
struct drm_plane * plane ;
struct intel_plane * intel_plane ;
int ret = 0 ;
if ( ! dev_priv )
return - EINVAL ;
mutex_lock ( & dev - > mode_config . mutex ) ;
obj = drm_mode_object_find ( dev , get - > plane_id , DRM_MODE_OBJECT_PLANE ) ;
if ( ! obj ) {
ret = - EINVAL ;
goto out_unlock ;
}
plane = obj_to_plane ( obj ) ;
intel_plane = to_intel_plane ( plane ) ;
intel_plane - > get_colorkey ( plane , get ) ;
out_unlock :
mutex_unlock ( & dev - > mode_config . mutex ) ;
return ret ;
}
2011-12-13 13:19:38 -08:00
static const struct drm_plane_funcs intel_plane_funcs = {
. update_plane = intel_update_plane ,
. disable_plane = intel_disable_plane ,
. destroy = intel_destroy_plane ,
} ;
static uint32_t snb_plane_formats [ ] = {
DRM_FORMAT_XBGR8888 ,
DRM_FORMAT_XRGB8888 ,
DRM_FORMAT_YUYV ,
DRM_FORMAT_YVYU ,
DRM_FORMAT_UYVY ,
DRM_FORMAT_VYUY ,
} ;
int
intel_plane_init ( struct drm_device * dev , enum pipe pipe )
{
struct intel_plane * intel_plane ;
unsigned long possible_crtcs ;
int ret ;
2012-01-13 15:48:39 -08:00
if ( ! ( IS_GEN6 ( dev ) | | IS_GEN7 ( dev ) ) )
2011-12-13 13:19:38 -08:00
return - ENODEV ;
intel_plane = kzalloc ( sizeof ( struct intel_plane ) , GFP_KERNEL ) ;
if ( ! intel_plane )
return - ENOMEM ;
if ( IS_GEN6 ( dev ) ) {
intel_plane - > max_downscale = 16 ;
intel_plane - > update_plane = snb_update_plane ;
intel_plane - > disable_plane = snb_disable_plane ;
2012-01-03 08:05:39 -08:00
intel_plane - > update_colorkey = snb_update_colorkey ;
intel_plane - > get_colorkey = snb_get_colorkey ;
2011-12-13 13:19:38 -08:00
} else if ( IS_GEN7 ( dev ) ) {
intel_plane - > max_downscale = 2 ;
intel_plane - > update_plane = ivb_update_plane ;
intel_plane - > disable_plane = ivb_disable_plane ;
2012-01-03 08:05:39 -08:00
intel_plane - > update_colorkey = ivb_update_colorkey ;
intel_plane - > get_colorkey = ivb_get_colorkey ;
2011-12-13 13:19:38 -08:00
}
intel_plane - > pipe = pipe ;
possible_crtcs = ( 1 < < pipe ) ;
ret = drm_plane_init ( dev , & intel_plane - > base , possible_crtcs ,
& intel_plane_funcs , snb_plane_formats ,
2011-12-13 20:19:36 -06:00
ARRAY_SIZE ( snb_plane_formats ) , false ) ;
2011-12-13 13:19:38 -08:00
if ( ret )
kfree ( intel_plane ) ;
return ret ;
}