2015-08-20 05:19:49 +03:00
/*
* Copyright 2015 Freescale Semiconductor , Inc .
*
* Freescale DCU drm device driver
*
* 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 <linux/regmap.h>
# include <drm/drmP.h>
# include <drm/drm_atomic_helper.h>
# include <drm/drm_crtc.h>
# include <drm/drm_crtc_helper.h>
# include <drm/drm_fb_cma_helper.h>
# include <drm/drm_gem_cma_helper.h>
# include <drm/drm_plane_helper.h>
# include "fsl_dcu_drm_drv.h"
# include "fsl_dcu_drm_plane.h"
static int fsl_dcu_drm_plane_index ( struct drm_plane * plane )
{
struct fsl_dcu_drm_device * fsl_dev = plane - > dev - > dev_private ;
unsigned int total_layer = fsl_dev - > soc - > total_layer ;
unsigned int index ;
index = drm_plane_index ( plane ) ;
if ( index < total_layer )
return total_layer - index - 1 ;
dev_err ( fsl_dev - > dev , " No more layer left \n " ) ;
return - EINVAL ;
}
static int fsl_dcu_drm_plane_atomic_check ( struct drm_plane * plane ,
struct drm_plane_state * state )
{
struct drm_framebuffer * fb = state - > fb ;
2016-01-06 07:12:05 +03:00
if ( ! state - > fb | | ! state - > crtc )
return 0 ;
2015-08-20 05:19:49 +03:00
switch ( fb - > pixel_format ) {
case DRM_FORMAT_RGB565 :
case DRM_FORMAT_RGB888 :
case DRM_FORMAT_ARGB8888 :
case DRM_FORMAT_BGRA4444 :
case DRM_FORMAT_ARGB1555 :
case DRM_FORMAT_YUV422 :
return 0 ;
default :
return - EINVAL ;
}
}
static void fsl_dcu_drm_plane_atomic_disable ( struct drm_plane * plane ,
struct drm_plane_state * old_state )
{
struct fsl_dcu_drm_device * fsl_dev = plane - > dev - > dev_private ;
2015-09-21 16:33:47 +03:00
unsigned int value ;
2015-11-19 03:50:55 +03:00
int index ;
2015-08-20 05:19:49 +03:00
index = fsl_dcu_drm_plane_index ( plane ) ;
if ( index < 0 )
return ;
2015-11-19 03:50:55 +03:00
regmap_read ( fsl_dev - > regmap , DCU_CTRLDESCLN ( index , 4 ) , & value ) ;
2015-08-20 05:19:49 +03:00
value & = ~ DCU_LAYER_EN ;
2015-11-19 03:50:55 +03:00
regmap_write ( fsl_dev - > regmap , DCU_CTRLDESCLN ( index , 4 ) , value ) ;
2015-08-20 05:19:49 +03:00
}
static void fsl_dcu_drm_plane_atomic_update ( struct drm_plane * plane ,
struct drm_plane_state * old_state )
{
struct fsl_dcu_drm_device * fsl_dev = plane - > dev - > dev_private ;
struct drm_plane_state * state = plane - > state ;
struct drm_framebuffer * fb = plane - > state - > fb ;
struct drm_gem_cma_object * gem ;
unsigned int alpha , bpp ;
2015-11-19 03:50:55 +03:00
int index ;
2015-08-20 05:19:49 +03:00
if ( ! fb )
return ;
index = fsl_dcu_drm_plane_index ( plane ) ;
if ( index < 0 )
return ;
gem = drm_fb_cma_get_gem_obj ( fb , 0 ) ;
switch ( fb - > pixel_format ) {
case DRM_FORMAT_RGB565 :
bpp = FSL_DCU_RGB565 ;
alpha = 0xff ;
break ;
case DRM_FORMAT_RGB888 :
bpp = FSL_DCU_RGB888 ;
alpha = 0xff ;
break ;
case DRM_FORMAT_ARGB8888 :
bpp = FSL_DCU_ARGB8888 ;
alpha = 0xff ;
break ;
case DRM_FORMAT_BGRA4444 :
bpp = FSL_DCU_ARGB4444 ;
alpha = 0xff ;
break ;
case DRM_FORMAT_ARGB1555 :
bpp = FSL_DCU_ARGB1555 ;
alpha = 0xff ;
break ;
case DRM_FORMAT_YUV422 :
bpp = FSL_DCU_YUV422 ;
alpha = 0xff ;
break ;
default :
return ;
}
2015-11-19 03:50:55 +03:00
regmap_write ( fsl_dev - > regmap , DCU_CTRLDESCLN ( index , 1 ) ,
DCU_LAYER_HEIGHT ( state - > crtc_h ) |
DCU_LAYER_WIDTH ( state - > crtc_w ) ) ;
regmap_write ( fsl_dev - > regmap , DCU_CTRLDESCLN ( index , 2 ) ,
DCU_LAYER_POSY ( state - > crtc_y ) |
DCU_LAYER_POSX ( state - > crtc_x ) ) ;
regmap_write ( fsl_dev - > regmap ,
DCU_CTRLDESCLN ( index , 3 ) , gem - > paddr ) ;
regmap_write ( fsl_dev - > regmap , DCU_CTRLDESCLN ( index , 4 ) ,
DCU_LAYER_EN |
DCU_LAYER_TRANS ( alpha ) |
DCU_LAYER_BPP ( bpp ) |
DCU_LAYER_AB ( 0 ) ) ;
regmap_write ( fsl_dev - > regmap , DCU_CTRLDESCLN ( index , 5 ) ,
DCU_LAYER_CKMAX_R ( 0xFF ) |
DCU_LAYER_CKMAX_G ( 0xFF ) |
DCU_LAYER_CKMAX_B ( 0xFF ) ) ;
regmap_write ( fsl_dev - > regmap , DCU_CTRLDESCLN ( index , 6 ) ,
DCU_LAYER_CKMIN_R ( 0 ) |
DCU_LAYER_CKMIN_G ( 0 ) |
DCU_LAYER_CKMIN_B ( 0 ) ) ;
regmap_write ( fsl_dev - > regmap , DCU_CTRLDESCLN ( index , 7 ) , 0 ) ;
regmap_write ( fsl_dev - > regmap , DCU_CTRLDESCLN ( index , 8 ) ,
DCU_LAYER_FG_FCOLOR ( 0 ) ) ;
regmap_write ( fsl_dev - > regmap , DCU_CTRLDESCLN ( index , 9 ) ,
DCU_LAYER_BG_BCOLOR ( 0 ) ) ;
2015-08-20 05:19:49 +03:00
if ( ! strcmp ( fsl_dev - > soc - > name , " ls1021a " ) ) {
2015-11-19 03:50:55 +03:00
regmap_write ( fsl_dev - > regmap , DCU_CTRLDESCLN ( index , 10 ) ,
DCU_LAYER_POST_SKIP ( 0 ) |
DCU_LAYER_PRE_SKIP ( 0 ) ) ;
2015-08-20 05:19:49 +03:00
}
2015-11-19 03:50:55 +03:00
regmap_update_bits ( fsl_dev - > regmap , DCU_DCU_MODE ,
DCU_MODE_DCU_MODE_MASK ,
DCU_MODE_DCU_MODE ( DCU_MODE_NORMAL ) ) ;
regmap_write ( fsl_dev - > regmap ,
DCU_UPDATE_MODE , DCU_UPDATE_MODE_READREG ) ;
2015-08-20 05:19:49 +03:00
2015-11-19 03:50:55 +03:00
return ;
2015-08-20 05:19:49 +03:00
}
static void
fsl_dcu_drm_plane_cleanup_fb ( struct drm_plane * plane ,
const struct drm_plane_state * new_state )
{
}
static int
fsl_dcu_drm_plane_prepare_fb ( struct drm_plane * plane ,
const struct drm_plane_state * new_state )
{
return 0 ;
}
static const struct drm_plane_helper_funcs fsl_dcu_drm_plane_helper_funcs = {
. atomic_check = fsl_dcu_drm_plane_atomic_check ,
. atomic_disable = fsl_dcu_drm_plane_atomic_disable ,
. atomic_update = fsl_dcu_drm_plane_atomic_update ,
. cleanup_fb = fsl_dcu_drm_plane_cleanup_fb ,
. prepare_fb = fsl_dcu_drm_plane_prepare_fb ,
} ;
static void fsl_dcu_drm_plane_destroy ( struct drm_plane * plane )
{
drm_plane_cleanup ( plane ) ;
}
static const struct drm_plane_funcs fsl_dcu_drm_plane_funcs = {
. atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state ,
. atomic_destroy_state = drm_atomic_helper_plane_destroy_state ,
. destroy = fsl_dcu_drm_plane_destroy ,
. disable_plane = drm_atomic_helper_disable_plane ,
. reset = drm_atomic_helper_plane_reset ,
. update_plane = drm_atomic_helper_update_plane ,
} ;
static const u32 fsl_dcu_drm_plane_formats [ ] = {
DRM_FORMAT_RGB565 ,
DRM_FORMAT_RGB888 ,
DRM_FORMAT_ARGB8888 ,
DRM_FORMAT_ARGB4444 ,
DRM_FORMAT_ARGB1555 ,
DRM_FORMAT_YUV422 ,
} ;
struct drm_plane * fsl_dcu_drm_primary_create_plane ( struct drm_device * dev )
{
struct drm_plane * primary ;
int ret ;
primary = kzalloc ( sizeof ( * primary ) , GFP_KERNEL ) ;
if ( ! primary ) {
DRM_DEBUG_KMS ( " Failed to allocate primary plane \n " ) ;
return NULL ;
}
/* possible_crtc's will be filled in later by crtc_init */
ret = drm_universal_plane_init ( dev , primary , 0 ,
& fsl_dcu_drm_plane_funcs ,
fsl_dcu_drm_plane_formats ,
ARRAY_SIZE ( fsl_dcu_drm_plane_formats ) ,
drm: Pass 'name' to drm_universal_plane_init()
Done with coccinelle for the most part. It choked on
msm/mdp/mdp5/mdp5_plane.c like so:
"BAD:!!!!! enum drm_plane_type type;"
No idea how to deal with that, so I just fixed that up
by hand.
Also 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.
I didn't convert drm_plane_init() since passing the varargs through
would mean either cpp macros or va_list, and I figured we don't
care about these legacy functions enough to warrant the extra pain.
@@
typedef uint32_t;
identifier dev, plane, possible_crtcs, funcs, formats, format_count, type;
@@
int drm_universal_plane_init(struct drm_device *dev,
struct drm_plane *plane,
unsigned long possible_crtcs,
const struct drm_plane_funcs *funcs,
const uint32_t *formats,
unsigned int format_count,
enum drm_plane_type type
+ ,const char *name, int DOTDOTDOT
)
{ ... }
@@
identifier dev, plane, possible_crtcs, funcs, formats, format_count, type;
@@
int drm_universal_plane_init(struct drm_device *dev,
struct drm_plane *plane,
unsigned long possible_crtcs,
const struct drm_plane_funcs *funcs,
const uint32_t *formats,
unsigned int format_count,
enum drm_plane_type type
+ ,const char *name, int DOTDOTDOT
);
@@
expression E1, E2, E3, E4, E5, E6, E7;
@@
drm_universal_plane_init(E1, E2, E3, E4, E5, E6, E7
+ ,NULL
)
v2: Split crtc and plane changes apart
Pass NUL for no-name instead of ""
Leave drm_plane_init() alone
v3: 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/1449670795-2853-1-git-send-email-ville.syrjala@linux.intel.com
2015-12-09 17:19:55 +03:00
DRM_PLANE_TYPE_PRIMARY , NULL ) ;
2015-08-20 05:19:49 +03:00
if ( ret ) {
kfree ( primary ) ;
primary = NULL ;
}
drm_plane_helper_add ( primary , & fsl_dcu_drm_plane_helper_funcs ) ;
return primary ;
}