2009-12-10 00:19:58 +00:00
/**************************************************************************
*
2015-07-29 12:38:02 -07:00
* Copyright © 2009 - 2015 VMware , Inc . , Palo Alto , CA . , USA
2009-12-10 00:19:58 +00:00
* All Rights Reserved .
*
* 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 , sub license , 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 NON - INFRINGEMENT . IN NO EVENT SHALL
* THE COPYRIGHT HOLDERS , AUTHORS AND / OR ITS SUPPLIERS 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 .
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# include "vmwgfx_kms.h"
2014-10-29 10:03:57 +01:00
# include <drm/drm_plane_helper.h>
2017-03-23 11:48:44 -07:00
# include <drm/drm_atomic.h>
# include <drm/drm_atomic_helper.h>
2009-12-10 00:19:58 +00:00
2010-10-01 10:21:49 +02:00
2009-12-10 00:19:58 +00:00
# define vmw_crtc_to_ldu(x) \
container_of ( x , struct vmw_legacy_display_unit , base . crtc )
# define vmw_encoder_to_ldu(x) \
container_of ( x , struct vmw_legacy_display_unit , base . encoder )
# define vmw_connector_to_ldu(x) \
container_of ( x , struct vmw_legacy_display_unit , base . connector )
struct vmw_legacy_display {
struct list_head active ;
unsigned num_active ;
2010-05-28 11:21:59 +02:00
unsigned last_num_active ;
2009-12-10 00:19:58 +00:00
struct vmw_framebuffer * fb ;
} ;
/**
* Display unit using the legacy register interface .
*/
struct vmw_legacy_display_unit {
struct vmw_display_unit base ;
struct list_head active ;
} ;
static void vmw_ldu_destroy ( struct vmw_legacy_display_unit * ldu )
{
list_del_init ( & ldu - > active ) ;
2015-06-26 01:23:42 -07:00
vmw_du_cleanup ( & ldu - > base ) ;
2009-12-10 00:19:58 +00:00
kfree ( ldu ) ;
}
/*
* Legacy Display Unit CRTC functions
*/
static void vmw_ldu_crtc_destroy ( struct drm_crtc * crtc )
{
vmw_ldu_destroy ( vmw_crtc_to_ldu ( crtc ) ) ;
}
static int vmw_ldu_commit_list ( struct vmw_private * dev_priv )
{
struct vmw_legacy_display * lds = dev_priv - > ldu_priv ;
struct vmw_legacy_display_unit * entry ;
2010-05-28 11:21:59 +02:00
struct drm_framebuffer * fb = NULL ;
struct drm_crtc * crtc = NULL ;
2017-03-23 11:28:11 -07:00
int i = 0 ;
2009-12-10 00:19:58 +00:00
2010-05-28 11:21:59 +02:00
/* If there is no display topology the host just assumes
* that the guest will set the same layout as the host .
*/
if ( ! ( dev_priv - > capabilities & SVGA_CAP_DISPLAY_TOPOLOGY ) ) {
int w = 0 , h = 0 ;
list_for_each_entry ( entry , & lds - > active , active ) {
crtc = & entry - > base . crtc ;
w = max ( w , crtc - > x + crtc - > mode . hdisplay ) ;
h = max ( h , crtc - > y + crtc - > mode . vdisplay ) ;
i + + ;
}
if ( crtc = = NULL )
return 0 ;
2014-04-01 15:22:40 -07:00
fb = entry - > base . crtc . primary - > fb ;
2010-05-28 11:21:59 +02:00
2011-12-20 00:06:49 +02:00
return vmw_kms_write_svga ( dev_priv , w , h , fb - > pitches [ 0 ] ,
2016-12-14 23:32:20 +02:00
fb - > format - > cpp [ 0 ] * 8 ,
2016-12-14 23:31:35 +02:00
fb - > format - > depth ) ;
2010-05-28 11:21:59 +02:00
}
if ( ! list_empty ( & lds - > active ) ) {
entry = list_entry ( lds - > active . next , typeof ( * entry ) , active ) ;
2014-04-01 15:22:40 -07:00
fb = entry - > base . crtc . primary - > fb ;
2010-05-28 11:21:59 +02:00
2011-12-20 00:06:49 +02:00
vmw_kms_write_svga ( dev_priv , fb - > width , fb - > height , fb - > pitches [ 0 ] ,
2016-12-14 23:32:20 +02:00
fb - > format - > cpp [ 0 ] * 8 , fb - > format - > depth ) ;
2010-05-28 11:21:59 +02:00
}
2010-05-28 11:22:03 +02:00
/* Make sure we always show something. */
vmw_write ( dev_priv , SVGA_REG_NUM_GUEST_DISPLAYS ,
lds - > num_active ? lds - > num_active : 1 ) ;
2009-12-10 00:19:58 +00:00
i = 0 ;
list_for_each_entry ( entry , & lds - > active , active ) {
crtc = & entry - > base . crtc ;
vmw_write ( dev_priv , SVGA_REG_DISPLAY_ID , i ) ;
vmw_write ( dev_priv , SVGA_REG_DISPLAY_IS_PRIMARY , ! i ) ;
vmw_write ( dev_priv , SVGA_REG_DISPLAY_POSITION_X , crtc - > x ) ;
vmw_write ( dev_priv , SVGA_REG_DISPLAY_POSITION_Y , crtc - > y ) ;
vmw_write ( dev_priv , SVGA_REG_DISPLAY_WIDTH , crtc - > mode . hdisplay ) ;
vmw_write ( dev_priv , SVGA_REG_DISPLAY_HEIGHT , crtc - > mode . vdisplay ) ;
vmw_write ( dev_priv , SVGA_REG_DISPLAY_ID , SVGA_ID_INVALID ) ;
i + + ;
}
2010-05-28 11:21:59 +02:00
BUG_ON ( i ! = lds - > num_active ) ;
lds - > last_num_active = lds - > num_active ;
2009-12-10 00:19:58 +00:00
return 0 ;
}
static int vmw_ldu_del_active ( struct vmw_private * vmw_priv ,
struct vmw_legacy_display_unit * ldu )
{
struct vmw_legacy_display * ld = vmw_priv - > ldu_priv ;
if ( list_empty ( & ldu - > active ) )
return 0 ;
2010-05-28 11:21:55 +02:00
/* Must init otherwise list_empty(&ldu->active) will not work. */
2009-12-10 00:19:58 +00:00
list_del_init ( & ldu - > active ) ;
if ( - - ( ld - > num_active ) = = 0 ) {
BUG_ON ( ! ld - > fb ) ;
if ( ld - > fb - > unpin )
ld - > fb - > unpin ( ld - > fb ) ;
ld - > fb = NULL ;
}
return 0 ;
}
static int vmw_ldu_add_active ( struct vmw_private * vmw_priv ,
struct vmw_legacy_display_unit * ldu ,
struct vmw_framebuffer * vfb )
{
struct vmw_legacy_display * ld = vmw_priv - > ldu_priv ;
struct vmw_legacy_display_unit * entry ;
struct list_head * at ;
2010-05-28 11:21:56 +02:00
BUG_ON ( ! ld - > num_active & & ld - > fb ) ;
if ( vfb ! = ld - > fb ) {
if ( ld - > fb & & ld - > fb - > unpin )
ld - > fb - > unpin ( ld - > fb ) ;
if ( vfb - > pin )
vfb - > pin ( vfb ) ;
ld - > fb = vfb ;
}
2009-12-10 00:19:58 +00:00
if ( ! list_empty ( & ldu - > active ) )
return 0 ;
at = & ld - > active ;
list_for_each_entry ( entry , & ld - > active , active ) {
2010-05-28 11:22:01 +02:00
if ( entry - > base . unit > ldu - > base . unit )
2009-12-10 00:19:58 +00:00
break ;
at = & entry - > active ;
}
list_add ( & ldu - > active , at ) ;
2010-05-28 11:21:56 +02:00
ld - > num_active + + ;
2009-12-10 00:19:58 +00:00
return 0 ;
}
static int vmw_ldu_crtc_set_config ( struct drm_mode_set * set )
{
struct vmw_private * dev_priv ;
struct vmw_legacy_display_unit * ldu ;
struct drm_connector * connector ;
struct drm_display_mode * mode ;
struct drm_encoder * encoder ;
struct vmw_framebuffer * vfb ;
struct drm_framebuffer * fb ;
struct drm_crtc * crtc ;
if ( ! set )
return - EINVAL ;
if ( ! set - > crtc )
return - EINVAL ;
/* get the ldu */
crtc = set - > crtc ;
ldu = vmw_crtc_to_ldu ( crtc ) ;
vfb = set - > fb ? vmw_framebuffer_to_vfb ( set - > fb ) : NULL ;
dev_priv = vmw_priv ( crtc - > dev ) ;
if ( set - > num_connectors > 1 ) {
DRM_ERROR ( " to many connectors \n " ) ;
return - EINVAL ;
}
if ( set - > num_connectors = = 1 & &
set - > connectors [ 0 ] ! = & ldu - > base . connector ) {
DRM_ERROR ( " connector doesn't match %p %p \n " ,
set - > connectors [ 0 ] , & ldu - > base . connector ) ;
return - EINVAL ;
}
/* ldu only supports one fb active at the time */
if ( dev_priv - > ldu_priv - > fb & & vfb & &
2010-05-28 11:21:55 +02:00
! ( dev_priv - > ldu_priv - > num_active = = 1 & &
! list_empty ( & ldu - > active ) ) & &
2009-12-10 00:19:58 +00:00
dev_priv - > ldu_priv - > fb ! = vfb ) {
DRM_ERROR ( " Multiple framebuffers not supported \n " ) ;
return - EINVAL ;
}
/* since they always map one to one these are safe */
connector = & ldu - > base . connector ;
encoder = & ldu - > base . encoder ;
/* should we turn the crtc off? */
if ( set - > num_connectors = = 0 | | ! set - > mode | | ! set - > fb ) {
connector - > encoder = NULL ;
encoder - > crtc = NULL ;
2014-04-01 15:22:40 -07:00
crtc - > primary - > fb = NULL ;
2013-11-14 03:11:10 -08:00
crtc - > enabled = false ;
2009-12-10 00:19:58 +00:00
vmw_ldu_del_active ( dev_priv , ldu ) ;
2011-08-31 07:42:50 +00:00
return vmw_ldu_commit_list ( dev_priv ) ;
2009-12-10 00:19:58 +00:00
}
/* we now know we want to set a mode */
mode = set - > mode ;
fb = set - > fb ;
if ( set - > x + mode - > hdisplay > fb - > width | |
set - > y + mode - > vdisplay > fb - > height ) {
DRM_ERROR ( " set outside of framebuffer \n " ) ;
return - EINVAL ;
}
2015-06-25 10:47:43 -07:00
vmw_svga_enable ( dev_priv ) ;
2009-12-10 00:19:58 +00:00
2014-04-01 15:22:40 -07:00
crtc - > primary - > fb = fb ;
2009-12-10 00:19:58 +00:00
encoder - > crtc = crtc ;
connector - > encoder = encoder ;
crtc - > x = set - > x ;
crtc - > y = set - > y ;
crtc - > mode = * mode ;
2013-11-14 03:11:10 -08:00
crtc - > enabled = true ;
2016-02-12 09:57:15 +01:00
ldu - > base . set_gui_x = set - > x ;
ldu - > base . set_gui_y = set - > y ;
2009-12-10 00:19:58 +00:00
vmw_ldu_add_active ( dev_priv , ldu , vfb ) ;
2011-08-31 07:42:50 +00:00
return vmw_ldu_commit_list ( dev_priv ) ;
2009-12-10 00:19:58 +00:00
}
2015-12-15 12:21:15 +01:00
static const struct drm_crtc_funcs vmw_legacy_crtc_funcs = {
2011-10-04 20:13:20 +02:00
. gamma_set = vmw_du_crtc_gamma_set ,
2009-12-10 00:19:58 +00:00
. destroy = vmw_ldu_crtc_destroy ,
2017-03-23 11:33:39 -07:00
. reset = vmw_du_crtc_reset ,
. atomic_duplicate_state = vmw_du_crtc_duplicate_state ,
. atomic_destroy_state = vmw_du_crtc_destroy_state ,
2009-12-10 00:19:58 +00:00
. set_config = vmw_ldu_crtc_set_config ,
} ;
2011-10-04 20:13:20 +02:00
2009-12-10 00:19:58 +00:00
/*
* Legacy Display Unit encoder functions
*/
static void vmw_ldu_encoder_destroy ( struct drm_encoder * encoder )
{
vmw_ldu_destroy ( vmw_encoder_to_ldu ( encoder ) ) ;
}
2015-12-15 12:21:15 +01:00
static const struct drm_encoder_funcs vmw_legacy_encoder_funcs = {
2009-12-10 00:19:58 +00:00
. destroy = vmw_ldu_encoder_destroy ,
} ;
/*
* Legacy Display Unit connector functions
*/
static void vmw_ldu_connector_destroy ( struct drm_connector * connector )
{
vmw_ldu_destroy ( vmw_connector_to_ldu ( connector ) ) ;
}
2015-12-15 12:21:15 +01:00
static const struct drm_connector_funcs vmw_legacy_connector_funcs = {
2011-10-04 20:13:20 +02:00
. dpms = vmw_du_connector_dpms ,
. detect = vmw_du_connector_detect ,
. fill_modes = vmw_du_connector_fill_modes ,
. set_property = vmw_du_connector_set_property ,
2009-12-10 00:19:58 +00:00
. destroy = vmw_ldu_connector_destroy ,
2017-03-23 11:48:44 -07:00
. reset = vmw_du_connector_reset ,
. atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state ,
. atomic_destroy_state = drm_atomic_helper_connector_destroy_state ,
. atomic_set_property = vmw_du_connector_atomic_set_property ,
. atomic_get_property = vmw_du_connector_atomic_get_property ,
2009-12-10 00:19:58 +00:00
} ;
2017-03-23 11:28:11 -07:00
/*
* Legacy Display Plane Functions
*/
static const struct drm_plane_funcs vmw_ldu_plane_funcs = {
. update_plane = drm_primary_helper_update ,
. disable_plane = drm_primary_helper_disable ,
. destroy = vmw_du_primary_plane_destroy ,
2017-03-23 11:36:05 -07:00
. reset = vmw_du_plane_reset ,
. atomic_duplicate_state = vmw_du_plane_duplicate_state ,
. atomic_destroy_state = vmw_du_plane_destroy_state ,
2017-03-23 11:28:11 -07:00
} ;
static const struct drm_plane_funcs vmw_ldu_cursor_funcs = {
. update_plane = vmw_du_cursor_plane_update ,
. disable_plane = vmw_du_cursor_plane_disable ,
. destroy = vmw_du_cursor_plane_destroy ,
2017-03-23 11:36:05 -07:00
. reset = vmw_du_plane_reset ,
. atomic_duplicate_state = vmw_du_plane_duplicate_state ,
. atomic_destroy_state = vmw_du_plane_destroy_state ,
2017-03-23 11:28:11 -07:00
} ;
2009-12-10 00:19:58 +00:00
static int vmw_ldu_init ( struct vmw_private * dev_priv , unsigned unit )
{
struct vmw_legacy_display_unit * ldu ;
struct drm_device * dev = dev_priv - > dev ;
struct drm_connector * connector ;
struct drm_encoder * encoder ;
2017-03-23 11:36:05 -07:00
struct drm_plane * primary , * cursor ;
2009-12-10 00:19:58 +00:00
struct drm_crtc * crtc ;
2017-03-23 11:28:11 -07:00
int ret ;
2009-12-10 00:19:58 +00:00
ldu = kzalloc ( sizeof ( * ldu ) , GFP_KERNEL ) ;
if ( ! ldu )
return - ENOMEM ;
2010-05-28 11:22:01 +02:00
ldu - > base . unit = unit ;
2009-12-10 00:19:58 +00:00
crtc = & ldu - > base . crtc ;
encoder = & ldu - > base . encoder ;
connector = & ldu - > base . connector ;
2017-03-23 11:36:05 -07:00
primary = & ldu - > base . primary ;
cursor = & ldu - > base . cursor ;
2009-12-10 00:19:58 +00:00
2010-05-28 11:21:58 +02:00
INIT_LIST_HEAD ( & ldu - > active ) ;
2011-10-04 20:13:20 +02:00
ldu - > base . pref_active = ( unit = = 0 ) ;
2012-02-09 16:56:46 +01:00
ldu - > base . pref_width = dev_priv - > initial_width ;
ldu - > base . pref_height = dev_priv - > initial_height ;
2011-10-04 20:13:20 +02:00
ldu - > base . pref_mode = NULL ;
2017-03-23 11:33:39 -07:00
/*
* Remove this after enabling atomic because property values can
* only exist in a state object
*/
2011-11-02 09:43:11 +01:00
ldu - > base . is_implicit = true ;
2010-06-01 11:54:20 +02:00
2017-03-23 11:28:11 -07:00
/* Initialize primary plane */
2017-03-23 11:36:05 -07:00
vmw_du_plane_reset ( primary ) ;
2017-03-23 11:28:11 -07:00
ret = drm_universal_plane_init ( dev , & ldu - > base . primary ,
0 , & vmw_ldu_plane_funcs ,
vmw_primary_plane_formats ,
ARRAY_SIZE ( vmw_primary_plane_formats ) ,
DRM_PLANE_TYPE_PRIMARY , NULL ) ;
if ( ret ) {
DRM_ERROR ( " Failed to initialize primary plane " ) ;
goto err_free ;
}
/* Initialize cursor plane */
2017-03-23 11:36:05 -07:00
vmw_du_plane_reset ( cursor ) ;
2017-03-23 11:28:11 -07:00
ret = drm_universal_plane_init ( dev , & ldu - > base . cursor ,
0 , & vmw_ldu_cursor_funcs ,
vmw_cursor_plane_formats ,
ARRAY_SIZE ( vmw_cursor_plane_formats ) ,
DRM_PLANE_TYPE_CURSOR , NULL ) ;
if ( ret ) {
DRM_ERROR ( " Failed to initialize cursor plane " ) ;
drm_plane_cleanup ( & ldu - > base . primary ) ;
goto err_free ;
}
ret = drm_connector_init ( dev , connector , & vmw_legacy_connector_funcs ,
DRM_MODE_CONNECTOR_VIRTUAL ) ;
if ( ret ) {
DRM_ERROR ( " Failed to initialize connector \n " ) ;
goto err_free ;
}
2011-10-04 20:13:20 +02:00
connector - > status = vmw_du_connector_detect ( connector , true ) ;
2017-03-23 11:48:44 -07:00
vmw_connector_state_to_vcs ( connector - > state ) - > is_implicit = true ;
2009-12-10 00:19:58 +00:00
2017-03-23 11:28:11 -07:00
ret = drm_encoder_init ( dev , encoder , & vmw_legacy_encoder_funcs ,
DRM_MODE_ENCODER_VIRTUAL , NULL ) ;
if ( ret ) {
DRM_ERROR ( " Failed to initialize encoder \n " ) ;
goto err_free_connector ;
}
( void ) drm_mode_connector_attach_encoder ( connector , encoder ) ;
2009-12-10 00:19:58 +00:00
encoder - > possible_crtcs = ( 1 < < unit ) ;
encoder - > possible_clones = 0 ;
2017-03-23 11:28:11 -07:00
ret = drm_connector_register ( connector ) ;
if ( ret ) {
DRM_ERROR ( " Failed to register connector \n " ) ;
goto err_free_encoder ;
}
2013-12-02 06:04:38 -08:00
2017-03-23 11:48:44 -07:00
vmw_du_crtc_reset ( crtc ) ;
2017-03-23 11:28:11 -07:00
ret = drm_crtc_init_with_planes ( dev , crtc , & ldu - > base . primary ,
& ldu - > base . cursor ,
& vmw_legacy_crtc_funcs , NULL ) ;
if ( ret ) {
DRM_ERROR ( " Failed to initialize CRTC \n " ) ;
goto err_free_unregister ;
}
2009-12-10 00:19:58 +00:00
2011-08-31 07:42:47 +00:00
drm_mode_crtc_set_gamma_size ( crtc , 256 ) ;
2016-02-12 09:45:42 +01:00
drm_object_attach_property ( & connector - > base ,
dev_priv - > hotplug_mode_update_property , 1 ) ;
drm_object_attach_property ( & connector - > base ,
dev - > mode_config . suggested_x_property , 0 ) ;
drm_object_attach_property ( & connector - > base ,
dev - > mode_config . suggested_y_property , 0 ) ;
2016-02-12 09:55:45 +01:00
if ( dev_priv - > implicit_placement_property )
drm_object_attach_property
( & connector - > base ,
dev_priv - > implicit_placement_property ,
1 ) ;
2009-12-10 00:19:58 +00:00
return 0 ;
2017-03-23 11:28:11 -07:00
err_free_unregister :
drm_connector_unregister ( connector ) ;
err_free_encoder :
drm_encoder_cleanup ( encoder ) ;
err_free_connector :
drm_connector_cleanup ( connector ) ;
err_free :
kfree ( ldu ) ;
return ret ;
2009-12-10 00:19:58 +00:00
}
2015-06-26 01:23:42 -07:00
int vmw_kms_ldu_init_display ( struct vmw_private * dev_priv )
2009-12-10 00:19:58 +00:00
{
2010-10-01 10:21:49 +02:00
struct drm_device * dev = dev_priv - > dev ;
2011-10-17 11:59:44 +02:00
int i , ret ;
2010-10-01 10:21:49 +02:00
2009-12-10 00:19:58 +00:00
if ( dev_priv - > ldu_priv ) {
DRM_INFO ( " ldu system already on \n " ) ;
return - EINVAL ;
}
2010-10-31 22:33:53 +00:00
dev_priv - > ldu_priv = kmalloc ( sizeof ( * dev_priv - > ldu_priv ) , GFP_KERNEL ) ;
2009-12-10 00:19:58 +00:00
if ( ! dev_priv - > ldu_priv )
return - ENOMEM ;
INIT_LIST_HEAD ( & dev_priv - > ldu_priv - > active ) ;
dev_priv - > ldu_priv - > num_active = 0 ;
2010-05-28 11:21:59 +02:00
dev_priv - > ldu_priv - > last_num_active = 0 ;
2009-12-10 00:19:58 +00:00
dev_priv - > ldu_priv - > fb = NULL ;
2011-10-17 11:59:43 +02:00
/* for old hardware without multimon only enable one display */
if ( dev_priv - > capabilities & SVGA_CAP_MULTIMON )
ret = drm_vblank_init ( dev , VMWGFX_NUM_DISPLAY_UNITS ) ;
else
ret = drm_vblank_init ( dev , 1 ) ;
if ( ret ! = 0 )
goto err_free ;
2009-12-10 00:19:58 +00:00
2016-02-12 09:55:45 +01:00
vmw_kms_create_implicit_placement_property ( dev_priv , true ) ;
2011-10-17 11:59:43 +02:00
if ( dev_priv - > capabilities & SVGA_CAP_MULTIMON )
2011-10-04 20:13:22 +02:00
for ( i = 0 ; i < VMWGFX_NUM_DISPLAY_UNITS ; + + i )
2010-10-01 10:21:49 +02:00
vmw_ldu_init ( dev_priv , i ) ;
2011-10-17 11:59:43 +02:00
else
2010-10-01 10:21:49 +02:00
vmw_ldu_init ( dev_priv , 0 ) ;
2009-12-10 00:19:58 +00:00
2015-06-26 01:23:42 -07:00
dev_priv - > active_display_unit = vmw_du_legacy ;
DRM_INFO ( " Legacy Display Unit initialized \n " ) ;
2011-10-17 11:59:43 +02:00
return 0 ;
err_free :
kfree ( dev_priv - > ldu_priv ) ;
dev_priv - > ldu_priv = NULL ;
2010-10-01 10:21:49 +02:00
return ret ;
2009-12-10 00:19:58 +00:00
}
2015-06-26 01:23:42 -07:00
int vmw_kms_ldu_close_display ( struct vmw_private * dev_priv )
2009-12-10 00:19:58 +00:00
{
2010-10-01 10:21:49 +02:00
struct drm_device * dev = dev_priv - > dev ;
2009-12-10 00:19:58 +00:00
if ( ! dev_priv - > ldu_priv )
return - ENOSYS ;
2011-10-17 11:59:43 +02:00
drm_vblank_cleanup ( dev ) ;
2009-12-10 00:19:58 +00:00
BUG_ON ( ! list_empty ( & dev_priv - > ldu_priv - > active ) ) ;
kfree ( dev_priv - > ldu_priv ) ;
return 0 ;
}
2015-06-26 01:23:42 -07:00
int vmw_kms_ldu_do_dmabuf_dirty ( struct vmw_private * dev_priv ,
struct vmw_framebuffer * framebuffer ,
unsigned flags , unsigned color ,
struct drm_clip_rect * clips ,
unsigned num_clips , int increment )
{
size_t fifo_size ;
int i ;
struct {
uint32_t header ;
SVGAFifoCmdUpdate body ;
} * cmd ;
fifo_size = sizeof ( * cmd ) * num_clips ;
cmd = vmw_fifo_reserve ( dev_priv , fifo_size ) ;
if ( unlikely ( cmd = = NULL ) ) {
DRM_ERROR ( " Fifo reserve failed. \n " ) ;
return - ENOMEM ;
}
memset ( cmd , 0 , fifo_size ) ;
for ( i = 0 ; i < num_clips ; i + + , clips + = increment ) {
2015-04-02 02:39:45 -07:00
cmd [ i ] . header = SVGA_CMD_UPDATE ;
cmd [ i ] . body . x = clips - > x1 ;
cmd [ i ] . body . y = clips - > y1 ;
cmd [ i ] . body . width = clips - > x2 - clips - > x1 ;
cmd [ i ] . body . height = clips - > y2 - clips - > y1 ;
2015-06-26 01:23:42 -07:00
}
vmw_fifo_commit ( dev_priv , fifo_size ) ;
return 0 ;
}