2018-05-07 01:16:26 +02:00
// SPDX-License-Identifier: GPL-2.0 OR MIT
2009-12-10 00:19:58 +00:00
/**************************************************************************
*
2018-05-07 01:16:26 +02:00
* Copyright 2009 - 2015 VMware , Inc . , Palo Alto , CA . , USA
2009-12-10 00:19:58 +00:00
*
* 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 ;
2017-03-23 14:38:18 -07:00
fb = entry - > base . crtc . primary - > state - > 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 ) ;
2017-03-23 14:38:18 -07:00
fb = entry - > base . crtc . primary - > state - > 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 ) ;
2017-03-23 13:14:54 -07:00
vmw_svga_enable ( vmw_priv ) ;
2010-05-28 11:21:56 +02:00
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 ;
}
2017-03-23 13:14:54 -07:00
/**
* vmw_ldu_crtc_mode_set_nofb - Enable svga
*
* @ crtc : CRTC associated with the new screen
*
* For LDU , just enable the svga
*/
static void vmw_ldu_crtc_mode_set_nofb ( struct drm_crtc * crtc )
{
}
/**
2017-06-30 12:36:44 +03:00
* vmw_ldu_crtc_atomic_enable - Noop
2017-03-23 13:14:54 -07:00
*
* @ crtc : CRTC associated with the new screen
*
* This is called after a mode set has been completed . Here ' s
* usually a good place to call vmw_ldu_add_active / vmw_ldu_del_active
* but since for LDU the display plane is closely tied to the
* CRTC , it makes more sense to do those at plane update time .
*/
2017-06-30 12:36:44 +03:00
static void vmw_ldu_crtc_atomic_enable ( struct drm_crtc * crtc ,
struct drm_crtc_state * old_state )
2017-03-23 13:14:54 -07:00
{
}
/**
2017-06-30 12:36:45 +03:00
* vmw_ldu_crtc_atomic_disable - Turns off CRTC
2017-03-23 13:14:54 -07:00
*
* @ crtc : CRTC to be turned off
*/
2017-06-30 12:36:45 +03:00
static void vmw_ldu_crtc_atomic_disable ( struct drm_crtc * crtc ,
struct drm_crtc_state * old_state )
2017-03-23 13:14:54 -07: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 ,
2017-03-23 14:38:18 -07:00
. set_config = vmw_kms_set_config ,
2009-12-10 00:19:58 +00:00
} ;
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 ,
2018-01-17 10:16:20 -05:00
. atomic_duplicate_state = vmw_du_connector_duplicate_state ,
. atomic_destroy_state = vmw_du_connector_destroy_state ,
2017-03-23 11:48:44 -07:00
. 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 14:23:20 -07:00
static const struct
drm_connector_helper_funcs vmw_ldu_connector_helper_funcs = {
. best_encoder = drm_atomic_helper_best_encoder ,
} ;
2017-03-23 11:28:11 -07:00
/*
* Legacy Display Plane Functions
*/
2017-03-23 14:18:32 -07:00
static void
vmw_ldu_primary_plane_atomic_update ( struct drm_plane * plane ,
struct drm_plane_state * old_state )
{
2017-03-23 14:42:36 -07:00
struct vmw_private * dev_priv ;
struct vmw_legacy_display_unit * ldu ;
struct vmw_framebuffer * vfb ;
struct drm_framebuffer * fb ;
struct drm_crtc * crtc = plane - > state - > crtc ? : old_state - > crtc ;
ldu = vmw_crtc_to_ldu ( crtc ) ;
dev_priv = vmw_priv ( plane - > dev ) ;
fb = plane - > state - > fb ;
vfb = ( fb ) ? vmw_framebuffer_to_vfb ( fb ) : NULL ;
if ( vfb )
vmw_ldu_add_active ( dev_priv , ldu , vfb ) ;
else
vmw_ldu_del_active ( dev_priv , ldu ) ;
vmw_ldu_commit_list ( dev_priv ) ;
2017-03-23 14:18:32 -07:00
}
2017-03-23 11:28:11 -07:00
static const struct drm_plane_funcs vmw_ldu_plane_funcs = {
2017-03-23 14:38:18 -07:00
. update_plane = drm_atomic_helper_update_plane ,
. disable_plane = drm_atomic_helper_disable_plane ,
2017-03-23 11:28:11 -07:00
. 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 = {
2017-03-23 14:38:18 -07:00
. update_plane = drm_atomic_helper_update_plane ,
. disable_plane = drm_atomic_helper_disable_plane ,
2017-03-23 11:28:11 -07:00
. 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
} ;
2017-03-23 13:14:54 -07:00
/*
* Atomic Helpers
*/
2017-03-23 14:18:32 -07:00
static const struct
drm_plane_helper_funcs vmw_ldu_cursor_plane_helper_funcs = {
. atomic_check = vmw_du_cursor_plane_atomic_check ,
. atomic_update = vmw_du_cursor_plane_atomic_update ,
. prepare_fb = vmw_du_cursor_plane_prepare_fb ,
. cleanup_fb = vmw_du_plane_cleanup_fb ,
} ;
static const struct
drm_plane_helper_funcs vmw_ldu_primary_plane_helper_funcs = {
. atomic_check = vmw_du_primary_plane_atomic_check ,
. atomic_update = vmw_ldu_primary_plane_atomic_update ,
} ;
2017-03-23 13:14:54 -07:00
static const struct drm_crtc_helper_funcs vmw_ldu_crtc_helper_funcs = {
. mode_set_nofb = vmw_ldu_crtc_mode_set_nofb ,
. atomic_check = vmw_du_crtc_atomic_check ,
. atomic_begin = vmw_du_crtc_atomic_begin ,
. atomic_flush = vmw_du_crtc_atomic_flush ,
2017-06-30 12:36:44 +03:00
. atomic_enable = vmw_ldu_crtc_atomic_enable ,
2017-06-30 12:36:45 +03:00
. atomic_disable = vmw_ldu_crtc_atomic_disable ,
2017-03-23 13:14:54 -07:00
} ;
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 ) ,
2017-07-23 20:46:38 -07:00
NULL , DRM_PLANE_TYPE_PRIMARY , NULL ) ;
2017-03-23 11:28:11 -07:00
if ( ret ) {
DRM_ERROR ( " Failed to initialize primary plane " ) ;
goto err_free ;
}
2017-03-23 14:18:32 -07:00
drm_plane_helper_add ( primary , & vmw_ldu_primary_plane_helper_funcs ) ;
2017-03-23 11:28:11 -07:00
/* 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 ) ,
2017-07-23 20:46:38 -07:00
NULL , DRM_PLANE_TYPE_CURSOR , NULL ) ;
2017-03-23 11:28:11 -07:00
if ( ret ) {
DRM_ERROR ( " Failed to initialize cursor plane " ) ;
drm_plane_cleanup ( & ldu - > base . primary ) ;
goto err_free ;
}
2017-03-23 14:18:32 -07:00
drm_plane_helper_add ( cursor , & vmw_ldu_cursor_plane_helper_funcs ) ;
vmw_du_connector_reset ( connector ) ;
2017-03-23 11:28:11 -07:00
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 ;
}
2017-03-23 14:23:20 -07:00
drm_connector_helper_add ( connector , & vmw_ldu_connector_helper_funcs ) ;
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 ;
}
2018-07-09 10:40:07 +02:00
( void ) drm_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
2017-03-23 13:14:54 -07:00
drm_crtc_helper_add ( crtc , & vmw_ldu_crtc_helper_funcs ) ;
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
{
if ( ! dev_priv - > ldu_priv )
return - ENOSYS ;
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 ;
}