2012-08-15 13:59:49 +01:00
/*
* Copyright ( C ) 2012 Russell King
* Written from the i915 driver .
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation .
*/
# include <linux/errno.h>
# include <linux/kernel.h>
# include <linux/module.h>
# include <drm/drm_fb_helper.h>
# include "armada_crtc.h"
# include "armada_drm.h"
# include "armada_fb.h"
# include "armada_gem.h"
static /*const*/ struct fb_ops armada_fb_ops = {
. owner = THIS_MODULE ,
2016-11-14 00:03:14 +01:00
DRM_FB_HELPER_DEFAULT_OPS ,
2015-07-22 14:58:04 +05:30
. fb_fillrect = drm_fb_helper_cfb_fillrect ,
. fb_copyarea = drm_fb_helper_cfb_copyarea ,
. fb_imageblit = drm_fb_helper_cfb_imageblit ,
2012-08-15 13:59:49 +01:00
} ;
static int armada_fb_create ( struct drm_fb_helper * fbh ,
struct drm_fb_helper_surface_size * sizes )
{
struct drm_device * dev = fbh - > dev ;
struct drm_mode_fb_cmd2 mode ;
struct armada_framebuffer * dfb ;
struct armada_gem_object * obj ;
struct fb_info * info ;
int size , ret ;
void * ptr ;
memset ( & mode , 0 , sizeof ( mode ) ) ;
mode . width = sizes - > surface_width ;
mode . height = sizes - > surface_height ;
mode . pitches [ 0 ] = armada_pitch ( mode . width , sizes - > surface_bpp ) ;
mode . pixel_format = drm_mode_legacy_fb_format ( sizes - > surface_bpp ,
sizes - > surface_depth ) ;
size = mode . pitches [ 0 ] * mode . height ;
obj = armada_gem_alloc_private_object ( dev , size ) ;
if ( ! obj ) {
DRM_ERROR ( " failed to allocate fb memory \n " ) ;
return - ENOMEM ;
}
ret = armada_gem_linear_back ( dev , obj ) ;
if ( ret ) {
2017-09-20 12:54:48 -06:00
drm_gem_object_put_unlocked ( & obj - > obj ) ;
2012-08-15 13:59:49 +01:00
return ret ;
}
ptr = armada_gem_map_object ( dev , obj ) ;
if ( ! ptr ) {
2017-09-20 12:54:48 -06:00
drm_gem_object_put_unlocked ( & obj - > obj ) ;
2012-08-15 13:59:49 +01:00
return - ENOMEM ;
}
dfb = armada_framebuffer_create ( dev , & mode , obj ) ;
/*
* A reference is now held by the framebuffer object if
* successful , otherwise this drops the ref for the error path .
*/
2017-09-20 12:54:48 -06:00
drm_gem_object_put_unlocked ( & obj - > obj ) ;
2012-08-15 13:59:49 +01:00
if ( IS_ERR ( dfb ) )
return PTR_ERR ( dfb ) ;
2015-07-22 14:58:04 +05:30
info = drm_fb_helper_alloc_fbi ( fbh ) ;
if ( IS_ERR ( info ) ) {
ret = PTR_ERR ( info ) ;
2012-08-15 13:59:49 +01:00
goto err_fballoc ;
}
strlcpy ( info - > fix . id , " armada-drmfb " , sizeof ( info - > fix . id ) ) ;
info - > par = fbh ;
info - > fbops = & armada_fb_ops ;
info - > fix . smem_start = obj - > phys_addr ;
info - > fix . smem_len = obj - > obj . size ;
info - > screen_size = obj - > obj . size ;
info - > screen_base = ptr ;
fbh - > fb = & dfb - > fb ;
2015-07-22 14:58:04 +05:30
2016-12-14 23:31:35 +02:00
drm_fb_helper_fill_fix ( info , dfb - > fb . pitches [ 0 ] ,
dfb - > fb . format - > depth ) ;
2012-08-15 13:59:49 +01:00
drm_fb_helper_fill_var ( info , fbh , sizes - > fb_width , sizes - > fb_height ) ;
2013-11-27 15:46:55 +00:00
DRM_DEBUG_KMS ( " allocated %dx%d %dbpp fb: 0x%08llx \n " ,
2016-12-14 23:32:20 +02:00
dfb - > fb . width , dfb - > fb . height , dfb - > fb . format - > cpp [ 0 ] * 8 ,
2013-11-27 15:46:55 +00:00
( unsigned long long ) obj - > phys_addr ) ;
2012-08-15 13:59:49 +01:00
return 0 ;
err_fballoc :
dfb - > fb . funcs - > destroy ( & dfb - > fb ) ;
return ret ;
}
static int armada_fb_probe ( struct drm_fb_helper * fbh ,
struct drm_fb_helper_surface_size * sizes )
{
int ret = 0 ;
if ( ! fbh - > fb ) {
ret = armada_fb_create ( fbh , sizes ) ;
if ( ret = = 0 )
ret = 1 ;
}
return ret ;
}
2014-06-27 17:19:23 +02:00
static const struct drm_fb_helper_funcs armada_fb_helper_funcs = {
2012-08-15 13:59:49 +01:00
. fb_probe = armada_fb_probe ,
} ;
int armada_fbdev_init ( struct drm_device * dev )
{
struct armada_private * priv = dev - > dev_private ;
struct drm_fb_helper * fbh ;
int ret ;
fbh = devm_kzalloc ( dev - > dev , sizeof ( * fbh ) , GFP_KERNEL ) ;
if ( ! fbh )
return - ENOMEM ;
priv - > fbdev = fbh ;
2014-06-27 17:19:24 +02:00
drm_fb_helper_prepare ( dev , fbh , & armada_fb_helper_funcs ) ;
2012-08-15 13:59:49 +01:00
drm: Rely on mode_config data for fb_helper initialization
Instead of receiving the num_crts as a parameter, we can read it
directly from the mode_config structure. I audited the drivers that
invoke this helper and I believe all of them initialize the mode_config
struct accordingly, prior to calling the fb_helper.
I used the following coccinelle hack to make this transformation, except
for the function headers and comment updates. The first and second
rules are split because I couldn't find a way to remove the unused
temporary variables at the same time I removed the parameter.
// <smpl>
@r@
expression A,B,D,E;
identifier C;
@@
(
- drm_fb_helper_init(A,B,C,D)
+ drm_fb_helper_init(A,B,D)
|
- drm_fbdev_cma_init_with_funcs(A,B,C,D,E)
+ drm_fbdev_cma_init_with_funcs(A,B,D,E)
|
- drm_fbdev_cma_init(A,B,C,D)
+ drm_fbdev_cma_init(A,B,D)
)
@@
expression A,B,C,D,E;
@@
(
- drm_fb_helper_init(A,B,C,D)
+ drm_fb_helper_init(A,B,D)
|
- drm_fbdev_cma_init_with_funcs(A,B,C,D,E)
+ drm_fbdev_cma_init_with_funcs(A,B,D,E)
|
- drm_fbdev_cma_init(A,B,C,D)
+ drm_fbdev_cma_init(A,B,D)
)
@@
identifier r.C;
type T;
expression V;
@@
- T C;
<...
when != C
- C = V;
...>
// </smpl>
Changes since v1:
- Rebased on top of the tip of drm-misc-next.
- Remove mention to sti since a proper fix got merged.
Suggested-by: Daniel Vetter <daniel.vetter@intel.com>
Signed-off-by: Gabriel Krisman Bertazi <krisman@collabora.co.uk>
Reviewed-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Link: http://patchwork.freedesktop.org/patch/msgid/20170202162640.27261-1-krisman@collabora.co.uk
2017-02-02 14:26:40 -02:00
ret = drm_fb_helper_init ( dev , fbh , 1 ) ;
2012-08-15 13:59:49 +01:00
if ( ret ) {
DRM_ERROR ( " failed to initialize drm fb helper \n " ) ;
goto err_fb_helper ;
}
ret = drm_fb_helper_single_add_all_connectors ( fbh ) ;
if ( ret ) {
DRM_ERROR ( " failed to add fb connectors \n " ) ;
goto err_fb_setup ;
}
ret = drm_fb_helper_initial_config ( fbh , 32 ) ;
if ( ret ) {
DRM_ERROR ( " failed to set initial config \n " ) ;
goto err_fb_setup ;
}
return 0 ;
err_fb_setup :
drm_fb_helper_fini ( fbh ) ;
err_fb_helper :
priv - > fbdev = NULL ;
return ret ;
}
void armada_fbdev_fini ( struct drm_device * dev )
{
struct armada_private * priv = dev - > dev_private ;
struct drm_fb_helper * fbh = priv - > fbdev ;
if ( fbh ) {
2015-07-22 14:58:04 +05:30
drm_fb_helper_unregister_fbi ( fbh ) ;
2012-08-15 13:59:49 +01:00
2013-10-27 15:35:27 +00:00
drm_fb_helper_fini ( fbh ) ;
2012-08-15 13:59:49 +01:00
if ( fbh - > fb )
fbh - > fb - > funcs - > destroy ( fbh - > fb ) ;
priv - > fbdev = NULL ;
}
}