2016-04-07 14:52:02 +03:00
/*
* Copyright ( C ) 2015 Texas Instruments
* Author : Jyri Sarha < jsarha @ ti . com >
*
* 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 .
*
* This program is distributed in the hope that it will be useful , but WITHOUT
* ANY WARRANTY ; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE . See the GNU General Public License for
* more details .
*
* You should have received a copy of the GNU General Public License along with
* this program . If not , see < http : //www.gnu.org/licenses/>.
*/
# include <drm/drmP.h>
# include <drm/drm_atomic.h>
# include <drm/drm_plane_helper.h>
# include <drm/drm_atomic_helper.h>
# include <uapi/drm/drm_fourcc.h>
# include "tilcdc_drv.h"
static struct drm_plane_funcs tilcdc_plane_funcs = {
. update_plane = drm_atomic_helper_update_plane ,
. disable_plane = drm_atomic_helper_disable_plane ,
. destroy = drm_plane_cleanup ,
. reset = drm_atomic_helper_plane_reset ,
. atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state ,
. atomic_destroy_state = drm_atomic_helper_plane_destroy_state ,
} ;
static int tilcdc_plane_atomic_check ( struct drm_plane * plane ,
struct drm_plane_state * state )
{
struct drm_crtc_state * crtc_state ;
struct drm_plane_state * old_state = plane - > state ;
2016-10-18 01:41:14 +03:00
unsigned int pitch ;
2016-04-07 14:52:02 +03:00
if ( ! state - > crtc )
return 0 ;
if ( WARN_ON ( ! state - > fb ) )
return - EINVAL ;
if ( state - > crtc_x | | state - > crtc_y ) {
dev_err ( plane - > dev - > dev , " %s: crtc position must be zero. " ,
__func__ ) ;
return - EINVAL ;
}
crtc_state = drm_atomic_get_existing_crtc_state ( state - > state ,
state - > crtc ) ;
/* we should have a crtc state if the plane is attached to a crtc */
if ( WARN_ON ( ! crtc_state ) )
return 0 ;
if ( crtc_state - > mode . hdisplay ! = state - > crtc_w | |
crtc_state - > mode . vdisplay ! = state - > crtc_h ) {
dev_err ( plane - > dev - > dev ,
" %s: Size must match mode (%dx%d == %dx%d) " , __func__ ,
crtc_state - > mode . hdisplay , crtc_state - > mode . vdisplay ,
state - > crtc_w , state - > crtc_h ) ;
return - EINVAL ;
}
2016-10-18 01:41:14 +03:00
pitch = crtc_state - > mode . hdisplay *
2016-12-14 23:30:57 +02:00
state - > fb - > format - > cpp [ 0 ] ;
2016-10-18 01:41:14 +03:00
if ( state - > fb - > pitches [ 0 ] ! = pitch ) {
2016-04-07 14:52:02 +03:00
dev_err ( plane - > dev - > dev ,
" Invalid pitch: fb and crtc widths must be the same " ) ;
return - EINVAL ;
}
if ( state - > fb & & old_state - > fb & &
2016-11-18 21:53:10 +02:00
state - > fb - > format ! = old_state - > fb - > format ) {
2016-04-07 14:52:02 +03:00
dev_dbg ( plane - > dev - > dev ,
" %s(): pixel format change requires mode_change \n " ,
__func__ ) ;
crtc_state - > mode_changed = true ;
}
return 0 ;
}
static void tilcdc_plane_atomic_update ( struct drm_plane * plane ,
struct drm_plane_state * old_state )
{
struct drm_plane_state * state = plane - > state ;
if ( ! state - > crtc )
return ;
if ( WARN_ON ( ! state - > fb | | ! state - > crtc - > state ) )
return ;
2016-06-22 17:21:06 +03:00
tilcdc_crtc_update_fb ( state - > crtc ,
2016-04-07 14:52:02 +03:00
state - > fb ,
2016-06-22 17:21:06 +03:00
state - > crtc - > state - > event ) ;
2016-04-07 14:52:02 +03:00
}
static const struct drm_plane_helper_funcs plane_helper_funcs = {
. atomic_check = tilcdc_plane_atomic_check ,
. atomic_update = tilcdc_plane_atomic_update ,
} ;
int tilcdc_plane_init ( struct drm_device * dev ,
struct drm_plane * plane )
{
2016-08-11 19:09:43 +03:00
struct tilcdc_drm_private * priv = dev - > dev_private ;
2016-04-07 14:52:02 +03:00
int ret ;
ret = drm_plane_init ( dev , plane , 1 ,
& tilcdc_plane_funcs ,
2016-08-11 19:09:43 +03:00
priv - > pixelformats ,
priv - > num_pixelformats ,
2016-04-07 14:52:02 +03:00
true ) ;
if ( ret ) {
dev_err ( dev - > dev , " Failed to initialize plane: %d \n " , ret ) ;
return ret ;
}
drm_plane_helper_add ( plane , & plane_helper_funcs ) ;
return 0 ;
}