2013-12-17 18:04:46 +01:00
/*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 2 of the License , or
* ( at your option ) any later version .
*/
# include "bochs.h"
2014-10-29 10:03:57 +01:00
# include <drm/drm_plane_helper.h>
2013-12-17 18:04:46 +01:00
static int defx = 1024 ;
static int defy = 768 ;
module_param ( defx , int , 0444 ) ;
module_param ( defy , int , 0444 ) ;
MODULE_PARM_DESC ( defx , " default x resolution " ) ;
MODULE_PARM_DESC ( defy , " default y resolution " ) ;
/* ---------------------------------------------------------------------- */
static void bochs_crtc_dpms ( struct drm_crtc * crtc , int mode )
{
switch ( mode ) {
case DRM_MODE_DPMS_ON :
case DRM_MODE_DPMS_STANDBY :
case DRM_MODE_DPMS_SUSPEND :
case DRM_MODE_DPMS_OFF :
default :
return ;
}
}
static int bochs_crtc_mode_set_base ( struct drm_crtc * crtc , int x , int y ,
struct drm_framebuffer * old_fb )
{
struct bochs_device * bochs =
container_of ( crtc , struct bochs_device , crtc ) ;
struct bochs_bo * bo ;
u64 gpu_addr = 0 ;
int ret ;
if ( old_fb ) {
2018-09-07 00:18:08 +02:00
bo = gem_to_bochs_bo ( old_fb - > obj [ 0 ] ) ;
2016-04-06 11:12:03 +02:00
ret = ttm_bo_reserve ( & bo - > bo , true , false , NULL ) ;
2013-12-17 18:04:46 +01:00
if ( ret ) {
DRM_ERROR ( " failed to reserve old_fb bo \n " ) ;
} else {
bochs_bo_unpin ( bo ) ;
ttm_bo_unreserve ( & bo - > bo ) ;
}
}
2014-04-01 15:22:40 -07:00
if ( WARN_ON ( crtc - > primary - > fb = = NULL ) )
2013-12-17 18:04:46 +01:00
return - EINVAL ;
2018-09-07 00:18:08 +02:00
bo = gem_to_bochs_bo ( crtc - > primary - > fb - > obj [ 0 ] ) ;
2016-04-06 11:12:03 +02:00
ret = ttm_bo_reserve ( & bo - > bo , true , false , NULL ) ;
2013-12-17 18:04:46 +01:00
if ( ret )
return ret ;
ret = bochs_bo_pin ( bo , TTM_PL_FLAG_VRAM , & gpu_addr ) ;
if ( ret ) {
ttm_bo_unreserve ( & bo - > bo ) ;
return ret ;
}
ttm_bo_unreserve ( & bo - > bo ) ;
bochs_hw_setbase ( bochs , x , y , gpu_addr ) ;
return 0 ;
}
static int bochs_crtc_mode_set ( struct drm_crtc * crtc ,
struct drm_display_mode * mode ,
struct drm_display_mode * adjusted_mode ,
int x , int y , struct drm_framebuffer * old_fb )
{
struct bochs_device * bochs =
container_of ( crtc , struct bochs_device , crtc ) ;
2018-09-21 15:47:02 +02:00
if ( WARN_ON ( crtc - > primary - > fb = = NULL ) )
return - EINVAL ;
bochs_hw_setmode ( bochs , mode , crtc - > primary - > fb - > format ) ;
2013-12-17 18:04:46 +01:00
bochs_crtc_mode_set_base ( crtc , x , y , old_fb ) ;
return 0 ;
}
static void bochs_crtc_prepare ( struct drm_crtc * crtc )
{
}
static void bochs_crtc_commit ( struct drm_crtc * crtc )
{
}
2014-11-19 12:28:12 +01:00
static int bochs_crtc_page_flip ( struct drm_crtc * crtc ,
struct drm_framebuffer * fb ,
struct drm_pending_vblank_event * event ,
2017-03-22 22:50:50 +01:00
uint32_t page_flip_flags ,
struct drm_modeset_acquire_ctx * ctx )
2014-11-19 12:28:12 +01:00
{
struct bochs_device * bochs =
container_of ( crtc , struct bochs_device , crtc ) ;
struct drm_framebuffer * old_fb = crtc - > primary - > fb ;
unsigned long irqflags ;
crtc - > primary - > fb = fb ;
bochs_crtc_mode_set_base ( crtc , 0 , 0 , old_fb ) ;
if ( event ) {
spin_lock_irqsave ( & bochs - > dev - > event_lock , irqflags ) ;
2015-12-15 12:20:50 +01:00
drm_crtc_send_vblank_event ( crtc , event ) ;
2014-11-19 12:28:12 +01:00
spin_unlock_irqrestore ( & bochs - > dev - > event_lock , irqflags ) ;
}
return 0 ;
}
2013-12-17 18:04:46 +01:00
/* These provide the minimum set of functions required to handle a CRTC */
static const struct drm_crtc_funcs bochs_crtc_funcs = {
. set_config = drm_crtc_helper_set_config ,
. destroy = drm_crtc_cleanup ,
2014-11-19 12:28:12 +01:00
. page_flip = bochs_crtc_page_flip ,
2013-12-17 18:04:46 +01:00
} ;
static const struct drm_crtc_helper_funcs bochs_helper_funcs = {
. dpms = bochs_crtc_dpms ,
. mode_set = bochs_crtc_mode_set ,
. mode_set_base = bochs_crtc_mode_set_base ,
. prepare = bochs_crtc_prepare ,
. commit = bochs_crtc_commit ,
} ;
2018-09-21 15:47:01 +02:00
static const uint32_t bochs_formats [ ] = {
2018-09-21 15:47:02 +02:00
DRM_FORMAT_XRGB8888 ,
DRM_FORMAT_BGRX8888 ,
2018-09-21 15:47:01 +02:00
} ;
static struct drm_plane * bochs_primary_plane ( struct drm_device * dev )
{
struct drm_plane * primary ;
int ret ;
primary = kzalloc ( sizeof ( * primary ) , GFP_KERNEL ) ;
if ( primary = = NULL ) {
DRM_DEBUG_KMS ( " Failed to allocate primary plane \n " ) ;
return NULL ;
}
ret = drm_universal_plane_init ( dev , primary , 0 ,
& drm_primary_helper_funcs ,
bochs_formats ,
ARRAY_SIZE ( bochs_formats ) ,
NULL ,
DRM_PLANE_TYPE_PRIMARY , NULL ) ;
if ( ret ) {
kfree ( primary ) ;
primary = NULL ;
}
return primary ;
}
2013-12-17 18:04:46 +01:00
static void bochs_crtc_init ( struct drm_device * dev )
{
struct bochs_device * bochs = dev - > dev_private ;
struct drm_crtc * crtc = & bochs - > crtc ;
2018-09-21 15:47:01 +02:00
struct drm_plane * primary = bochs_primary_plane ( dev ) ;
2013-12-17 18:04:46 +01:00
2018-09-21 15:47:01 +02:00
drm_crtc_init_with_planes ( dev , crtc , primary , NULL ,
& bochs_crtc_funcs , NULL ) ;
2013-12-17 18:04:46 +01:00
drm_crtc_helper_add ( crtc , & bochs_helper_funcs ) ;
}
static void bochs_encoder_mode_set ( struct drm_encoder * encoder ,
struct drm_display_mode * mode ,
struct drm_display_mode * adjusted_mode )
{
}
static void bochs_encoder_dpms ( struct drm_encoder * encoder , int state )
{
}
static void bochs_encoder_prepare ( struct drm_encoder * encoder )
{
}
static void bochs_encoder_commit ( struct drm_encoder * encoder )
{
}
static const struct drm_encoder_helper_funcs bochs_encoder_helper_funcs = {
. dpms = bochs_encoder_dpms ,
. mode_set = bochs_encoder_mode_set ,
. prepare = bochs_encoder_prepare ,
. commit = bochs_encoder_commit ,
} ;
static const struct drm_encoder_funcs bochs_encoder_encoder_funcs = {
. destroy = drm_encoder_cleanup ,
} ;
static void bochs_encoder_init ( struct drm_device * dev )
{
struct bochs_device * bochs = dev - > dev_private ;
struct drm_encoder * encoder = & bochs - > encoder ;
encoder - > possible_crtcs = 0x1 ;
drm_encoder_init ( dev , encoder , & bochs_encoder_encoder_funcs ,
drm: Pass 'name' to drm_encoder_init()
Done with coccinelle for the most part. However, it thinks '...' is
part of the semantic patch, so I put an 'int DOTDOTDOT' placeholder
in its place and got rid of it with sed afterwards.
@@
identifier dev, encoder, funcs;
@@
int drm_encoder_init(struct drm_device *dev,
struct drm_encoder *encoder,
const struct drm_encoder_funcs *funcs,
int encoder_type
+ ,const char *name, int DOTDOTDOT
)
{ ... }
@@
identifier dev, encoder, funcs;
@@
int drm_encoder_init(struct drm_device *dev,
struct drm_encoder *encoder,
const struct drm_encoder_funcs *funcs,
int encoder_type
+ ,const char *name, int DOTDOTDOT
);
@@
expression E1, E2, E3, E4;
@@
drm_encoder_init(E1, E2, E3, E4
+ ,NULL
)
v2: Add ', or NULL...' to @name kernel doc (Jani)
Annotate the function with __printf() attribute (Jani)
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Link: http://patchwork.freedesktop.org/patch/msgid/1449670818-2966-1-git-send-email-ville.syrjala@linux.intel.com
2015-12-09 16:20:18 +02:00
DRM_MODE_ENCODER_DAC , NULL ) ;
2013-12-17 18:04:46 +01:00
drm_encoder_helper_add ( encoder , & bochs_encoder_helper_funcs ) ;
}
2016-09-25 15:25:34 +08:00
static int bochs_connector_get_modes ( struct drm_connector * connector )
2013-12-17 18:04:46 +01:00
{
int count ;
count = drm_add_modes_noedid ( connector , 8192 , 8192 ) ;
drm_set_preferred_mode ( connector , defx , defy ) ;
return count ;
}
2018-04-24 15:14:45 +02:00
static enum drm_mode_status bochs_connector_mode_valid ( struct drm_connector * connector ,
2013-12-17 18:04:46 +01:00
struct drm_display_mode * mode )
{
struct bochs_device * bochs =
container_of ( connector , struct bochs_device , connector ) ;
unsigned long size = mode - > hdisplay * mode - > vdisplay * 4 ;
/*
* Make sure we can fit two framebuffers into video memory .
* This allows up to 1600 x1200 with 16 MB ( default size ) .
* If you want more try this :
* ' qemu - vga std - global VGA . vgamem_mb = 32 $ otherargs '
*/
if ( size * 2 > bochs - > fb_size )
return MODE_BAD ;
return MODE_OK ;
}
static struct drm_encoder *
bochs_connector_best_encoder ( struct drm_connector * connector )
{
int enc_id = connector - > encoder_ids [ 0 ] ;
/* pick the encoder ids */
2014-07-17 23:29:57 -04:00
if ( enc_id )
2017-03-14 23:25:07 -07:00
return drm_encoder_find ( connector - > dev , NULL , enc_id ) ;
2013-12-17 18:04:46 +01:00
return NULL ;
}
2015-12-15 12:21:01 +01:00
static const struct drm_connector_helper_funcs bochs_connector_connector_helper_funcs = {
2013-12-17 18:04:46 +01:00
. get_modes = bochs_connector_get_modes ,
. mode_valid = bochs_connector_mode_valid ,
. best_encoder = bochs_connector_best_encoder ,
} ;
2015-12-15 12:21:01 +01:00
static const struct drm_connector_funcs bochs_connector_connector_funcs = {
2013-12-17 18:04:46 +01:00
. dpms = drm_helper_connector_dpms ,
. fill_modes = drm_helper_probe_single_connector_modes ,
. destroy = drm_connector_cleanup ,
} ;
static void bochs_connector_init ( struct drm_device * dev )
{
struct bochs_device * bochs = dev - > dev_private ;
struct drm_connector * connector = & bochs - > connector ;
drm_connector_init ( dev , connector , & bochs_connector_connector_funcs ,
DRM_MODE_CONNECTOR_VIRTUAL ) ;
drm_connector_helper_add ( connector ,
& bochs_connector_connector_helper_funcs ) ;
2014-09-19 10:11:37 +02:00
drm_connector_register ( connector ) ;
2013-12-17 18:04:46 +01:00
}
int bochs_kms_init ( struct bochs_device * bochs )
{
drm_mode_config_init ( bochs - > dev ) ;
bochs - > mode_config_initialized = true ;
bochs - > dev - > mode_config . max_width = 8192 ;
bochs - > dev - > mode_config . max_height = 8192 ;
bochs - > dev - > mode_config . fb_base = bochs - > fb_base ;
bochs - > dev - > mode_config . preferred_depth = 24 ;
bochs - > dev - > mode_config . prefer_shadow = 0 ;
2018-09-21 15:47:01 +02:00
bochs - > dev - > mode_config . quirk_addfb_prefer_host_byte_order = true ;
2013-12-17 18:04:46 +01:00
2015-12-15 12:21:01 +01:00
bochs - > dev - > mode_config . funcs = & bochs_mode_funcs ;
2013-12-17 18:04:46 +01:00
bochs_crtc_init ( bochs - > dev ) ;
bochs_encoder_init ( bochs - > dev ) ;
bochs_connector_init ( bochs - > dev ) ;
2018-07-09 10:40:07 +02:00
drm_connector_attach_encoder ( & bochs - > connector ,
2013-12-17 18:04:46 +01:00
& bochs - > encoder ) ;
return 0 ;
}
void bochs_kms_fini ( struct bochs_device * bochs )
{
if ( bochs - > mode_config_initialized ) {
drm_mode_config_cleanup ( bochs - > dev ) ;
bochs - > mode_config_initialized = false ;
}
}