2019-06-03 07:44:50 +02:00
// SPDX-License-Identifier: GPL-2.0-only
2015-01-06 11:13:28 +01:00
/*
* Copyright ( C ) 2014 Free Electrons
* Copyright ( C ) 2014 Atmel
*
* Author : Boris BREZILLON < boris . brezillon @ free - electrons . com >
*/
2019-06-30 08:19:03 +02:00
# include <linux/dmapool.h>
# include <linux/mfd/atmel-hlcdc.h>
# include <drm/drm_atomic.h>
# include <drm/drm_atomic_helper.h>
2022-06-13 23:03:12 +03:00
# include <drm/drm_blend.h>
2022-08-02 02:04:02 +02:00
# include <drm/drm_fb_dma_helper.h>
2019-06-30 08:19:03 +02:00
# include <drm/drm_fourcc.h>
2022-06-14 12:54:49 +03:00
# include <drm/drm_framebuffer.h>
2022-08-02 02:04:03 +02:00
# include <drm/drm_gem_dma_helper.h>
2019-06-30 08:19:03 +02:00
2015-01-06 11:13:28 +01:00
# include "atmel_hlcdc_dc.h"
2015-02-05 16:32:33 +01:00
/**
2020-11-12 19:00:26 +00:00
* struct atmel_hlcdc_plane_state - Atmel HLCDC Plane state structure .
2015-02-05 16:32:33 +01:00
*
* @ base : DRM plane state
* @ crtc_x : x position of the plane relative to the CRTC
* @ crtc_y : y position of the plane relative to the CRTC
* @ crtc_w : visible width of the plane
* @ crtc_h : visible height of the plane
* @ src_x : x buffer position
* @ src_y : y buffer position
* @ src_w : buffer width
* @ src_h : buffer height
2017-02-06 18:57:19 +01:00
* @ disc_x : x discard position
* @ disc_y : y discard position
* @ disc_w : discard width
* @ disc_h : discard height
2020-11-12 19:00:26 +00:00
* @ ahb_id : AHB identification number
2015-02-05 16:32:33 +01:00
* @ bpp : bytes per pixel deduced from pixel_format
* @ offsets : offsets to apply to the GEM buffers
* @ xstride : value to add to the pixel pointer between each line
* @ pstride : value to add to the pixel pointer between each pixel
* @ nplanes : number of planes ( deduced from pixel_format )
2017-02-06 18:57:19 +01:00
* @ dscrs : DMA descriptors
2015-02-05 16:32:33 +01:00
*/
struct atmel_hlcdc_plane_state {
struct drm_plane_state base ;
int crtc_x ;
int crtc_y ;
unsigned int crtc_w ;
unsigned int crtc_h ;
uint32_t src_x ;
uint32_t src_y ;
uint32_t src_w ;
uint32_t src_h ;
2015-02-06 16:25:06 +01:00
int disc_x ;
int disc_y ;
int disc_w ;
int disc_h ;
2016-03-15 18:01:08 +01:00
int ahb_id ;
2015-02-05 16:32:33 +01:00
/* These fields are private and should not be touched */
2017-02-06 18:57:19 +01:00
int bpp [ ATMEL_HLCDC_LAYER_MAX_PLANES ] ;
unsigned int offsets [ ATMEL_HLCDC_LAYER_MAX_PLANES ] ;
int xstride [ ATMEL_HLCDC_LAYER_MAX_PLANES ] ;
int pstride [ ATMEL_HLCDC_LAYER_MAX_PLANES ] ;
2015-02-05 16:32:33 +01:00
int nplanes ;
2017-02-06 18:57:19 +01:00
/* DMA descriptors. */
struct atmel_hlcdc_dma_channel_dscr * dscrs [ ATMEL_HLCDC_LAYER_MAX_PLANES ] ;
2015-02-05 16:32:33 +01:00
} ;
static inline struct atmel_hlcdc_plane_state *
drm_plane_state_to_atmel_hlcdc_plane_state ( struct drm_plane_state * s )
{
return container_of ( s , struct atmel_hlcdc_plane_state , base ) ;
}
2015-01-06 11:13:28 +01:00
# define SUBPIXEL_MASK 0xffff
static uint32_t rgb_formats [ ] = {
2017-06-22 07:03:11 +02:00
DRM_FORMAT_C8 ,
2015-01-06 11:13:28 +01:00
DRM_FORMAT_XRGB4444 ,
DRM_FORMAT_ARGB4444 ,
DRM_FORMAT_RGBA4444 ,
DRM_FORMAT_ARGB1555 ,
DRM_FORMAT_RGB565 ,
DRM_FORMAT_RGB888 ,
DRM_FORMAT_XRGB8888 ,
DRM_FORMAT_ARGB8888 ,
DRM_FORMAT_RGBA8888 ,
} ;
struct atmel_hlcdc_formats atmel_hlcdc_plane_rgb_formats = {
. formats = rgb_formats ,
. nformats = ARRAY_SIZE ( rgb_formats ) ,
} ;
static uint32_t rgb_and_yuv_formats [ ] = {
2017-06-22 07:03:11 +02:00
DRM_FORMAT_C8 ,
2015-01-06 11:13:28 +01:00
DRM_FORMAT_XRGB4444 ,
DRM_FORMAT_ARGB4444 ,
DRM_FORMAT_RGBA4444 ,
DRM_FORMAT_ARGB1555 ,
DRM_FORMAT_RGB565 ,
DRM_FORMAT_RGB888 ,
DRM_FORMAT_XRGB8888 ,
DRM_FORMAT_ARGB8888 ,
DRM_FORMAT_RGBA8888 ,
DRM_FORMAT_AYUV ,
DRM_FORMAT_YUYV ,
DRM_FORMAT_UYVY ,
DRM_FORMAT_YVYU ,
DRM_FORMAT_VYUY ,
DRM_FORMAT_NV21 ,
DRM_FORMAT_NV61 ,
DRM_FORMAT_YUV422 ,
DRM_FORMAT_YUV420 ,
} ;
struct atmel_hlcdc_formats atmel_hlcdc_plane_rgb_and_yuv_formats = {
. formats = rgb_and_yuv_formats ,
. nformats = ARRAY_SIZE ( rgb_and_yuv_formats ) ,
} ;
static int atmel_hlcdc_format_to_plane_mode ( u32 format , u32 * mode )
{
switch ( format ) {
2017-06-22 07:03:11 +02:00
case DRM_FORMAT_C8 :
* mode = ATMEL_HLCDC_C8_MODE ;
break ;
2015-01-06 11:13:28 +01:00
case DRM_FORMAT_XRGB4444 :
* mode = ATMEL_HLCDC_XRGB4444_MODE ;
break ;
case DRM_FORMAT_ARGB4444 :
* mode = ATMEL_HLCDC_ARGB4444_MODE ;
break ;
case DRM_FORMAT_RGBA4444 :
* mode = ATMEL_HLCDC_RGBA4444_MODE ;
break ;
case DRM_FORMAT_RGB565 :
* mode = ATMEL_HLCDC_RGB565_MODE ;
break ;
case DRM_FORMAT_RGB888 :
* mode = ATMEL_HLCDC_RGB888_MODE ;
break ;
case DRM_FORMAT_ARGB1555 :
* mode = ATMEL_HLCDC_ARGB1555_MODE ;
break ;
case DRM_FORMAT_XRGB8888 :
* mode = ATMEL_HLCDC_XRGB8888_MODE ;
break ;
case DRM_FORMAT_ARGB8888 :
* mode = ATMEL_HLCDC_ARGB8888_MODE ;
break ;
case DRM_FORMAT_RGBA8888 :
* mode = ATMEL_HLCDC_RGBA8888_MODE ;
break ;
case DRM_FORMAT_AYUV :
* mode = ATMEL_HLCDC_AYUV_MODE ;
break ;
case DRM_FORMAT_YUYV :
* mode = ATMEL_HLCDC_YUYV_MODE ;
break ;
case DRM_FORMAT_UYVY :
* mode = ATMEL_HLCDC_UYVY_MODE ;
break ;
case DRM_FORMAT_YVYU :
* mode = ATMEL_HLCDC_YVYU_MODE ;
break ;
case DRM_FORMAT_VYUY :
* mode = ATMEL_HLCDC_VYUY_MODE ;
break ;
case DRM_FORMAT_NV21 :
* mode = ATMEL_HLCDC_NV21_MODE ;
break ;
case DRM_FORMAT_NV61 :
* mode = ATMEL_HLCDC_NV61_MODE ;
break ;
case DRM_FORMAT_YUV420 :
* mode = ATMEL_HLCDC_YUV420_MODE ;
break ;
case DRM_FORMAT_YUV422 :
* mode = ATMEL_HLCDC_YUV422_MODE ;
break ;
default :
return - ENOTSUPP ;
}
return 0 ;
}
static u32 heo_downscaling_xcoef [ ] = {
0x11343311 ,
0x000000f7 ,
0x1635300c ,
0x000000f9 ,
0x1b362c08 ,
0x000000fb ,
0x1f372804 ,
0x000000fe ,
0x24382400 ,
0x00000000 ,
0x28371ffe ,
0x00000004 ,
0x2c361bfb ,
0x00000008 ,
0x303516f9 ,
0x0000000c ,
} ;
static u32 heo_downscaling_ycoef [ ] = {
0x00123737 ,
0x00173732 ,
0x001b382d ,
0x001f3928 ,
0x00243824 ,
0x0028391f ,
0x002d381b ,
0x00323717 ,
} ;
static u32 heo_upscaling_xcoef [ ] = {
0xf74949f7 ,
0x00000000 ,
0xf55f33fb ,
0x000000fe ,
0xf5701efe ,
0x000000ff ,
0xf87c0dff ,
0x00000000 ,
0x00800000 ,
0x00000000 ,
0x0d7cf800 ,
0x000000ff ,
0x1e70f5ff ,
0x000000fe ,
0x335ff5fe ,
0x000000fb ,
} ;
static u32 heo_upscaling_ycoef [ ] = {
0x00004040 ,
0x00075920 ,
0x00056f0c ,
0x00027b03 ,
0x00008000 ,
0x00037b02 ,
0x000c6f05 ,
0x00205907 ,
} ;
2017-02-06 18:57:19 +01:00
# define ATMEL_HLCDC_XPHIDEF 4
# define ATMEL_HLCDC_YPHIDEF 4
static u32 atmel_hlcdc_plane_phiscaler_get_factor ( u32 srcsize ,
u32 dstsize ,
u32 phidef )
{
u32 factor , max_memsize ;
factor = ( 256 * ( ( 8 * ( srcsize - 1 ) ) - phidef ) ) / ( dstsize - 1 ) ;
max_memsize = ( ( factor * ( dstsize - 1 ) ) + ( 256 * phidef ) ) / 2048 ;
if ( max_memsize > srcsize - 1 )
factor - - ;
return factor ;
}
2015-01-06 11:13:28 +01:00
static void
2017-02-06 18:57:19 +01:00
atmel_hlcdc_plane_scaler_set_phicoeff ( struct atmel_hlcdc_plane * plane ,
const u32 * coeff_tab , int size ,
unsigned int cfg_offs )
2015-01-06 11:13:28 +01:00
{
2017-02-06 18:57:19 +01:00
int i ;
2015-01-06 11:13:28 +01:00
2017-02-06 18:57:19 +01:00
for ( i = 0 ; i < size ; i + + )
atmel_hlcdc_layer_write_cfg ( & plane - > layer , cfg_offs + i ,
coeff_tab [ i ] ) ;
}
2020-11-12 19:00:25 +00:00
static void atmel_hlcdc_plane_setup_scaler ( struct atmel_hlcdc_plane * plane ,
struct atmel_hlcdc_plane_state * state )
2017-02-06 18:57:19 +01:00
{
const struct atmel_hlcdc_layer_desc * desc = plane - > layer . desc ;
u32 xfactor , yfactor ;
if ( ! desc - > layout . scaler_config )
return ;
2015-01-06 11:13:28 +01:00
2017-02-06 18:57:19 +01:00
if ( state - > crtc_w = = state - > src_w & & state - > crtc_h = = state - > src_h ) {
atmel_hlcdc_layer_write_cfg ( & plane - > layer ,
desc - > layout . scaler_config , 0 ) ;
return ;
}
if ( desc - > layout . phicoeffs . x ) {
xfactor = atmel_hlcdc_plane_phiscaler_get_factor ( state - > src_w ,
state - > crtc_w ,
ATMEL_HLCDC_XPHIDEF ) ;
yfactor = atmel_hlcdc_plane_phiscaler_get_factor ( state - > src_h ,
state - > crtc_h ,
ATMEL_HLCDC_YPHIDEF ) ;
atmel_hlcdc_plane_scaler_set_phicoeff ( plane ,
state - > crtc_w < state - > src_w ?
heo_downscaling_xcoef :
heo_upscaling_xcoef ,
ARRAY_SIZE ( heo_upscaling_xcoef ) ,
desc - > layout . phicoeffs . x ) ;
atmel_hlcdc_plane_scaler_set_phicoeff ( plane ,
state - > crtc_h < state - > src_h ?
heo_downscaling_ycoef :
heo_upscaling_ycoef ,
ARRAY_SIZE ( heo_upscaling_ycoef ) ,
desc - > layout . phicoeffs . y ) ;
2016-05-27 16:09:25 +02:00
} else {
2017-02-06 18:57:19 +01:00
xfactor = ( 1024 * state - > src_w ) / state - > crtc_w ;
yfactor = ( 1024 * state - > src_h ) / state - > crtc_h ;
2015-01-06 11:13:28 +01:00
}
2017-02-06 18:57:19 +01:00
atmel_hlcdc_layer_write_cfg ( & plane - > layer , desc - > layout . scaler_config ,
ATMEL_HLCDC_LAYER_SCALER_ENABLE |
ATMEL_HLCDC_LAYER_SCALER_FACTORS ( xfactor ,
yfactor ) ) ;
}
static void
atmel_hlcdc_plane_update_pos_and_size ( struct atmel_hlcdc_plane * plane ,
struct atmel_hlcdc_plane_state * state )
{
const struct atmel_hlcdc_layer_desc * desc = plane - > layer . desc ;
if ( desc - > layout . size )
atmel_hlcdc_layer_write_cfg ( & plane - > layer , desc - > layout . size ,
ATMEL_HLCDC_LAYER_SIZE ( state - > crtc_w ,
state - > crtc_h ) ) ;
if ( desc - > layout . memsize )
atmel_hlcdc_layer_write_cfg ( & plane - > layer ,
desc - > layout . memsize ,
ATMEL_HLCDC_LAYER_SIZE ( state - > src_w ,
state - > src_h ) ) ;
if ( desc - > layout . pos )
atmel_hlcdc_layer_write_cfg ( & plane - > layer , desc - > layout . pos ,
ATMEL_HLCDC_LAYER_POS ( state - > crtc_x ,
state - > crtc_y ) ) ;
atmel_hlcdc_plane_setup_scaler ( plane , state ) ;
2015-01-06 11:13:28 +01:00
}
static void
atmel_hlcdc_plane_update_general_settings ( struct atmel_hlcdc_plane * plane ,
2015-02-05 16:32:33 +01:00
struct atmel_hlcdc_plane_state * state )
2015-01-06 11:13:28 +01:00
{
2017-02-06 18:57:19 +01:00
unsigned int cfg = ATMEL_HLCDC_LAYER_DMA_BLEN_INCR16 | state - > ahb_id ;
const struct atmel_hlcdc_layer_desc * desc = plane - > layer . desc ;
2017-12-22 15:31:27 +01:00
const struct drm_format_info * format = state - > base . fb - > format ;
2017-02-06 18:57:19 +01:00
/*
* Rotation optimization is not working on RGB888 ( rotation is still
* working but without any optimization ) .
*/
2017-12-22 15:31:27 +01:00
if ( format - > format = = DRM_FORMAT_RGB888 )
2017-02-06 18:57:19 +01:00
cfg | = ATMEL_HLCDC_LAYER_DMA_ROTDIS ;
atmel_hlcdc_layer_write_cfg ( & plane - > layer , ATMEL_HLCDC_LAYER_DMA_CFG ,
cfg ) ;
2019-07-09 15:35:12 +00:00
cfg = ATMEL_HLCDC_LAYER_DMA | ATMEL_HLCDC_LAYER_REP ;
2015-01-06 11:13:28 +01:00
if ( plane - > base . type ! = DRM_PLANE_TYPE_PRIMARY ) {
cfg | = ATMEL_HLCDC_LAYER_OVR | ATMEL_HLCDC_LAYER_ITER2BL |
ATMEL_HLCDC_LAYER_ITER ;
2017-12-22 15:31:27 +01:00
if ( format - > has_alpha )
2015-01-06 11:13:28 +01:00
cfg | = ATMEL_HLCDC_LAYER_LAEN ;
else
2015-02-05 16:32:33 +01:00
cfg | = ATMEL_HLCDC_LAYER_GAEN |
2019-04-25 12:36:39 +00:00
ATMEL_HLCDC_LAYER_GA ( state - > base . alpha ) ;
2015-01-06 11:13:28 +01:00
}
2017-02-06 18:57:19 +01:00
if ( state - > disc_h & & state - > disc_w )
cfg | = ATMEL_HLCDC_LAYER_DISCEN ;
atmel_hlcdc_layer_write_cfg ( & plane - > layer , desc - > layout . general_config ,
cfg ) ;
2015-01-06 11:13:28 +01:00
}
static void atmel_hlcdc_plane_update_format ( struct atmel_hlcdc_plane * plane ,
2015-02-05 16:32:33 +01:00
struct atmel_hlcdc_plane_state * state )
2015-01-06 11:13:28 +01:00
{
u32 cfg ;
int ret ;
2016-12-14 23:32:55 +02:00
ret = atmel_hlcdc_format_to_plane_mode ( state - > base . fb - > format - > format ,
2015-02-05 16:32:33 +01:00
& cfg ) ;
2015-01-06 11:13:28 +01:00
if ( ret )
return ;
2016-12-14 23:32:55 +02:00
if ( ( state - > base . fb - > format - > format = = DRM_FORMAT_YUV422 | |
state - > base . fb - > format - > format = = DRM_FORMAT_NV61 ) & &
2016-09-26 19:30:46 +03:00
drm_rotation_90_or_270 ( state - > base . rotation ) )
2015-01-06 11:13:28 +01:00
cfg | = ATMEL_HLCDC_YUV422ROT ;
2017-02-06 18:57:19 +01:00
atmel_hlcdc_layer_write_cfg ( & plane - > layer ,
ATMEL_HLCDC_LAYER_FORMAT_CFG , cfg ) ;
2015-01-06 11:13:28 +01:00
}
2018-04-05 18:13:50 +03:00
static void atmel_hlcdc_plane_update_clut ( struct atmel_hlcdc_plane * plane ,
struct atmel_hlcdc_plane_state * state )
2017-06-22 07:03:11 +02:00
{
2018-04-05 18:13:50 +03:00
struct drm_crtc * crtc = state - > base . crtc ;
2017-06-22 07:03:11 +02:00
struct drm_color_lut * lut ;
int idx ;
if ( ! crtc | | ! crtc - > state )
return ;
if ( ! crtc - > state - > color_mgmt_changed | | ! crtc - > state - > gamma_lut )
return ;
lut = ( struct drm_color_lut * ) crtc - > state - > gamma_lut - > data ;
for ( idx = 0 ; idx < ATMEL_HLCDC_CLUT_SIZE ; idx + + , lut + + ) {
u32 val = ( ( lut - > red < < 8 ) & 0xff0000 ) |
( lut - > green & 0xff00 ) |
( lut - > blue > > 8 ) ;
atmel_hlcdc_layer_write_clut ( & plane - > layer , idx , val ) ;
}
}
2015-01-06 11:13:28 +01:00
static void atmel_hlcdc_plane_update_buffers ( struct atmel_hlcdc_plane * plane ,
2015-02-05 16:32:33 +01:00
struct atmel_hlcdc_plane_state * state )
2015-01-06 11:13:28 +01:00
{
2017-02-06 18:57:19 +01:00
const struct atmel_hlcdc_layer_desc * desc = plane - > layer . desc ;
struct drm_framebuffer * fb = state - > base . fb ;
u32 sr ;
2015-01-06 11:13:28 +01:00
int i ;
2017-02-06 18:57:19 +01:00
sr = atmel_hlcdc_layer_read_reg ( & plane - > layer , ATMEL_HLCDC_LAYER_CHSR ) ;
2015-01-06 11:13:28 +01:00
2015-02-05 16:32:33 +01:00
for ( i = 0 ; i < state - > nplanes ; i + + ) {
2022-08-02 02:04:03 +02:00
struct drm_gem_dma_object * gem = drm_fb_dma_get_gem_obj ( fb , i ) ;
2017-02-06 18:57:19 +01:00
2022-08-02 02:04:04 +02:00
state - > dscrs [ i ] - > addr = gem - > dma_addr + state - > offsets [ i ] ;
2017-02-06 18:57:19 +01:00
atmel_hlcdc_layer_write_reg ( & plane - > layer ,
ATMEL_HLCDC_LAYER_PLANE_HEAD ( i ) ,
state - > dscrs [ i ] - > self ) ;
if ( ! ( sr & ATMEL_HLCDC_LAYER_EN ) ) {
atmel_hlcdc_layer_write_reg ( & plane - > layer ,
ATMEL_HLCDC_LAYER_PLANE_ADDR ( i ) ,
state - > dscrs [ i ] - > addr ) ;
atmel_hlcdc_layer_write_reg ( & plane - > layer ,
ATMEL_HLCDC_LAYER_PLANE_CTRL ( i ) ,
state - > dscrs [ i ] - > ctrl ) ;
atmel_hlcdc_layer_write_reg ( & plane - > layer ,
ATMEL_HLCDC_LAYER_PLANE_NEXT ( i ) ,
state - > dscrs [ i ] - > self ) ;
2015-01-06 11:13:28 +01:00
}
2017-02-06 18:57:19 +01:00
if ( desc - > layout . xstride [ i ] )
atmel_hlcdc_layer_write_cfg ( & plane - > layer ,
desc - > layout . xstride [ i ] ,
state - > xstride [ i ] ) ;
if ( desc - > layout . pstride [ i ] )
atmel_hlcdc_layer_write_cfg ( & plane - > layer ,
desc - > layout . pstride [ i ] ,
state - > pstride [ i ] ) ;
2015-01-06 11:13:28 +01:00
}
}
2016-03-15 18:01:08 +01:00
int atmel_hlcdc_plane_prepare_ahb_routing ( struct drm_crtc_state * c_state )
{
unsigned int ahb_load [ 2 ] = { } ;
struct drm_plane * plane ;
drm_atomic_crtc_state_for_each_plane ( plane , c_state ) {
struct atmel_hlcdc_plane_state * plane_state ;
struct drm_plane_state * plane_s ;
unsigned int pixels , load = 0 ;
int i ;
plane_s = drm_atomic_get_plane_state ( c_state - > state , plane ) ;
if ( IS_ERR ( plane_s ) )
return PTR_ERR ( plane_s ) ;
plane_state =
drm_plane_state_to_atmel_hlcdc_plane_state ( plane_s ) ;
pixels = ( plane_state - > src_w * plane_state - > src_h ) -
( plane_state - > disc_w * plane_state - > disc_h ) ;
for ( i = 0 ; i < plane_state - > nplanes ; i + + )
load + = pixels * plane_state - > bpp [ i ] ;
if ( ahb_load [ 0 ] < = ahb_load [ 1 ] )
plane_state - > ahb_id = 0 ;
else
plane_state - > ahb_id = 1 ;
ahb_load [ plane_state - > ahb_id ] + = load ;
}
return 0 ;
}
2015-02-06 16:25:06 +01:00
int
atmel_hlcdc_plane_prepare_disc_area ( struct drm_crtc_state * c_state )
{
int disc_x = 0 , disc_y = 0 , disc_w = 0 , disc_h = 0 ;
const struct atmel_hlcdc_layer_cfg_layout * layout ;
struct atmel_hlcdc_plane_state * primary_state ;
struct drm_plane_state * primary_s ;
struct atmel_hlcdc_plane * primary ;
struct drm_plane * ovl ;
primary = drm_plane_to_atmel_hlcdc_plane ( c_state - > crtc - > primary ) ;
layout = & primary - > layer . desc - > layout ;
if ( ! layout - > disc_pos | | ! layout - > disc_size )
return 0 ;
primary_s = drm_atomic_get_plane_state ( c_state - > state ,
& primary - > base ) ;
if ( IS_ERR ( primary_s ) )
return PTR_ERR ( primary_s ) ;
primary_state = drm_plane_state_to_atmel_hlcdc_plane_state ( primary_s ) ;
drm_atomic_crtc_state_for_each_plane ( ovl , c_state ) {
struct atmel_hlcdc_plane_state * ovl_state ;
struct drm_plane_state * ovl_s ;
if ( ovl = = c_state - > crtc - > primary )
continue ;
ovl_s = drm_atomic_get_plane_state ( c_state - > state , ovl ) ;
if ( IS_ERR ( ovl_s ) )
return PTR_ERR ( ovl_s ) ;
ovl_state = drm_plane_state_to_atmel_hlcdc_plane_state ( ovl_s ) ;
2019-01-10 15:10:44 +00:00
if ( ! ovl_s - > visible | |
! ovl_s - > fb | |
2017-12-22 15:31:27 +01:00
ovl_s - > fb - > format - > has_alpha | |
2018-04-11 09:39:26 +02:00
ovl_s - > alpha ! = DRM_BLEND_ALPHA_OPAQUE )
2015-02-06 16:25:06 +01:00
continue ;
/* TODO: implement a smarter hidden area detection */
if ( ovl_state - > crtc_h * ovl_state - > crtc_w < disc_h * disc_w )
continue ;
disc_x = ovl_state - > crtc_x ;
disc_y = ovl_state - > crtc_y ;
disc_h = ovl_state - > crtc_h ;
disc_w = ovl_state - > crtc_w ;
}
primary_state - > disc_x = disc_x ;
primary_state - > disc_y = disc_y ;
primary_state - > disc_w = disc_w ;
primary_state - > disc_h = disc_h ;
return 0 ;
}
static void
atmel_hlcdc_plane_update_disc_area ( struct atmel_hlcdc_plane * plane ,
struct atmel_hlcdc_plane_state * state )
{
2017-02-06 18:57:19 +01:00
const struct atmel_hlcdc_layer_cfg_layout * layout ;
2015-02-06 16:25:06 +01:00
2017-02-06 18:57:19 +01:00
layout = & plane - > layer . desc - > layout ;
if ( ! layout - > disc_pos | | ! layout - > disc_size )
2015-02-06 16:25:06 +01:00
return ;
2017-02-06 18:57:19 +01:00
atmel_hlcdc_layer_write_cfg ( & plane - > layer , layout - > disc_pos ,
ATMEL_HLCDC_LAYER_DISC_POS ( state - > disc_x ,
state - > disc_y ) ) ;
2015-02-06 16:25:06 +01:00
2017-02-06 18:57:19 +01:00
atmel_hlcdc_layer_write_cfg ( & plane - > layer , layout - > disc_size ,
ATMEL_HLCDC_LAYER_DISC_SIZE ( state - > disc_w ,
state - > disc_h ) ) ;
2015-02-06 16:25:06 +01:00
}
2015-02-05 16:32:33 +01:00
static int atmel_hlcdc_plane_atomic_check ( struct drm_plane * p ,
drm/atomic: Pass the full state to planes atomic_check
The current atomic helpers have either their object state being passed as
an argument or the full atomic state.
The former is the pattern that was done at first, before switching to the
latter for new hooks or when it was needed.
Let's convert all the remaining helpers to provide a consistent
interface, starting with the planes atomic_check.
The conversion was done using the coccinelle script below plus some
manual changes for vmwgfx, built tested on all the drivers.
@@
identifier plane, plane_state;
symbol state;
@@
struct drm_plane_helper_funcs {
...
int (*atomic_check)(struct drm_plane *plane,
- struct drm_plane_state *plane_state);
+ struct drm_atomic_state *state);
...
}
@ plane_atomic_func @
identifier helpers;
identifier func;
@@
static const struct drm_plane_helper_funcs helpers = {
...,
.atomic_check = func,
...,
};
@@
struct drm_plane_helper_funcs *FUNCS;
identifier f;
identifier dev;
identifier plane, plane_state, state;
@@
f(struct drm_device *dev, struct drm_atomic_state *state)
{
<+...
- FUNCS->atomic_check(plane, plane_state)
+ FUNCS->atomic_check(plane, state)
...+>
}
@ ignores_new_state @
identifier plane_atomic_func.func;
identifier plane, new_plane_state;
@@
func(struct drm_plane *plane, struct drm_plane_state *new_plane_state)
{
... when != new_plane_state
}
@ adds_new_state depends on plane_atomic_func && !ignores_new_state @
identifier plane_atomic_func.func;
identifier plane, new_plane_state;
@@
func(struct drm_plane *plane, struct drm_plane_state *new_plane_state)
{
+ struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state, plane);
...
}
@ depends on plane_atomic_func @
identifier plane_atomic_func.func;
identifier plane, new_plane_state;
@@
func(struct drm_plane *plane,
- struct drm_plane_state *new_plane_state
+ struct drm_atomic_state *state
)
{ ... }
@ include depends on adds_new_state @
@@
#include <drm/drm_atomic.h>
@ no_include depends on !include && adds_new_state @
@@
+ #include <drm/drm_atomic.h>
#include <drm/...>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
Acked-by: Thomas Zimmermann <tzimmermann@suse.de>
Link: https://patchwork.freedesktop.org/patch/msgid/20210219120032.260676-4-maxime@cerno.tech
2021-02-19 13:00:24 +01:00
struct drm_atomic_state * state )
2015-01-06 11:13:28 +01:00
{
drm/atomic: Pass the full state to planes atomic_check
The current atomic helpers have either their object state being passed as
an argument or the full atomic state.
The former is the pattern that was done at first, before switching to the
latter for new hooks or when it was needed.
Let's convert all the remaining helpers to provide a consistent
interface, starting with the planes atomic_check.
The conversion was done using the coccinelle script below plus some
manual changes for vmwgfx, built tested on all the drivers.
@@
identifier plane, plane_state;
symbol state;
@@
struct drm_plane_helper_funcs {
...
int (*atomic_check)(struct drm_plane *plane,
- struct drm_plane_state *plane_state);
+ struct drm_atomic_state *state);
...
}
@ plane_atomic_func @
identifier helpers;
identifier func;
@@
static const struct drm_plane_helper_funcs helpers = {
...,
.atomic_check = func,
...,
};
@@
struct drm_plane_helper_funcs *FUNCS;
identifier f;
identifier dev;
identifier plane, plane_state, state;
@@
f(struct drm_device *dev, struct drm_atomic_state *state)
{
<+...
- FUNCS->atomic_check(plane, plane_state)
+ FUNCS->atomic_check(plane, state)
...+>
}
@ ignores_new_state @
identifier plane_atomic_func.func;
identifier plane, new_plane_state;
@@
func(struct drm_plane *plane, struct drm_plane_state *new_plane_state)
{
... when != new_plane_state
}
@ adds_new_state depends on plane_atomic_func && !ignores_new_state @
identifier plane_atomic_func.func;
identifier plane, new_plane_state;
@@
func(struct drm_plane *plane, struct drm_plane_state *new_plane_state)
{
+ struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state, plane);
...
}
@ depends on plane_atomic_func @
identifier plane_atomic_func.func;
identifier plane, new_plane_state;
@@
func(struct drm_plane *plane,
- struct drm_plane_state *new_plane_state
+ struct drm_atomic_state *state
)
{ ... }
@ include depends on adds_new_state @
@@
#include <drm/drm_atomic.h>
@ no_include depends on !include && adds_new_state @
@@
+ #include <drm/drm_atomic.h>
#include <drm/...>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
Acked-by: Thomas Zimmermann <tzimmermann@suse.de>
Link: https://patchwork.freedesktop.org/patch/msgid/20210219120032.260676-4-maxime@cerno.tech
2021-02-19 13:00:24 +01:00
struct drm_plane_state * s = drm_atomic_get_new_plane_state ( state , p ) ;
2015-01-06 11:13:28 +01:00
struct atmel_hlcdc_plane * plane = drm_plane_to_atmel_hlcdc_plane ( p ) ;
2021-02-19 13:00:23 +01:00
struct atmel_hlcdc_plane_state * hstate =
2015-02-05 16:32:33 +01:00
drm_plane_state_to_atmel_hlcdc_plane_state ( s ) ;
2017-02-06 18:57:19 +01:00
const struct atmel_hlcdc_layer_desc * desc = plane - > layer . desc ;
2021-02-19 13:00:23 +01:00
struct drm_framebuffer * fb = hstate - > base . fb ;
2015-02-05 16:32:33 +01:00
const struct drm_display_mode * mode ;
struct drm_crtc_state * crtc_state ;
2019-01-10 15:10:44 +00:00
int ret ;
2015-01-06 11:13:28 +01:00
int i ;
2021-02-19 13:00:23 +01:00
if ( ! hstate - > base . crtc | | WARN_ON ( ! fb ) )
2015-02-05 16:32:33 +01:00
return 0 ;
drm: Use the state pointer directly in planes atomic_check
Now that atomic_check takes the global atomic state as a parameter, we
don't need to go through the pointer in the plane state.
This was done using the following coccinelle script:
@ plane_atomic_func @
identifier helpers;
identifier func;
@@
static struct drm_plane_helper_funcs helpers = {
...,
.atomic_check = func,
...,
};
@@
identifier plane_atomic_func.func;
identifier plane, state;
identifier plane_state;
@@
func(struct drm_plane *plane, struct drm_atomic_state *state) {
...
- struct drm_plane_state *plane_state = drm_atomic_get_new_plane_state(state, plane);
<... when != plane_state
- plane_state->state
+ state
...>
}
@@
identifier plane_atomic_func.func;
identifier plane, state;
identifier plane_state;
@@
func(struct drm_plane *plane, struct drm_atomic_state *state) {
...
struct drm_plane_state *plane_state = drm_atomic_get_new_plane_state(state, plane);
<...
- plane_state->state
+ state
...>
}
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
Acked-by: Thomas Zimmermann <tzimmermann@suse.de>
Link: https://patchwork.freedesktop.org/patch/msgid/20210219120032.260676-5-maxime@cerno.tech
2021-02-19 13:00:25 +01:00
crtc_state = drm_atomic_get_existing_crtc_state ( state , s - > crtc ) ;
2015-02-05 16:32:33 +01:00
mode = & crtc_state - > adjusted_mode ;
2019-01-10 15:10:44 +00:00
ret = drm_atomic_helper_check_plane_state ( s , crtc_state ,
( 1 < < 16 ) / 2048 ,
INT_MAX , true , true ) ;
if ( ret | | ! s - > visible )
return ret ;
2021-02-19 13:00:23 +01:00
hstate - > src_x = s - > src . x1 ;
hstate - > src_y = s - > src . y1 ;
hstate - > src_w = drm_rect_width ( & s - > src ) ;
hstate - > src_h = drm_rect_height ( & s - > src ) ;
hstate - > crtc_x = s - > dst . x1 ;
hstate - > crtc_y = s - > dst . y1 ;
hstate - > crtc_w = drm_rect_width ( & s - > dst ) ;
hstate - > crtc_h = drm_rect_height ( & s - > dst ) ;
2019-01-10 15:10:44 +00:00
2021-02-19 13:00:23 +01:00
if ( ( hstate - > src_x | hstate - > src_y | hstate - > src_w | hstate - > src_h ) &
2015-01-06 11:13:28 +01:00
SUBPIXEL_MASK )
return - EINVAL ;
2021-02-19 13:00:23 +01:00
hstate - > src_x > > = 16 ;
hstate - > src_y > > = 16 ;
hstate - > src_w > > = 16 ;
hstate - > src_h > > = 16 ;
2015-01-06 11:13:28 +01:00
2021-02-19 13:00:23 +01:00
hstate - > nplanes = fb - > format - > num_planes ;
if ( hstate - > nplanes > ATMEL_HLCDC_LAYER_MAX_PLANES )
2015-01-06 11:13:28 +01:00
return - EINVAL ;
2021-02-19 13:00:23 +01:00
for ( i = 0 ; i < hstate - > nplanes ; i + + ) {
2015-01-06 11:13:28 +01:00
unsigned int offset = 0 ;
2019-05-16 12:31:48 +02:00
int xdiv = i ? fb - > format - > hsub : 1 ;
int ydiv = i ? fb - > format - > vsub : 1 ;
2015-01-06 11:13:28 +01:00
2021-02-19 13:00:23 +01:00
hstate - > bpp [ i ] = fb - > format - > cpp [ i ] ;
if ( ! hstate - > bpp [ i ] )
2015-01-06 11:13:28 +01:00
return - EINVAL ;
2021-02-19 13:00:23 +01:00
switch ( hstate - > base . rotation & DRM_MODE_ROTATE_MASK ) {
2017-05-19 16:50:17 -04:00
case DRM_MODE_ROTATE_90 :
2021-02-19 13:00:23 +01:00
offset = ( hstate - > src_y / ydiv ) *
2019-01-10 15:10:34 +00:00
fb - > pitches [ i ] ;
2021-02-19 13:00:23 +01:00
offset + = ( ( hstate - > src_x + hstate - > src_w - 1 ) /
xdiv ) * hstate - > bpp [ i ] ;
hstate - > xstride [ i ] = - ( ( ( hstate - > src_h - 1 ) / ydiv ) *
2019-01-10 15:10:34 +00:00
fb - > pitches [ i ] ) -
2021-02-19 13:00:23 +01:00
( 2 * hstate - > bpp [ i ] ) ;
hstate - > pstride [ i ] = fb - > pitches [ i ] - hstate - > bpp [ i ] ;
2015-01-06 11:13:28 +01:00
break ;
2017-05-19 16:50:17 -04:00
case DRM_MODE_ROTATE_180 :
2021-02-19 13:00:23 +01:00
offset = ( ( hstate - > src_y + hstate - > src_h - 1 ) /
2015-02-05 16:32:33 +01:00
ydiv ) * fb - > pitches [ i ] ;
2021-02-19 13:00:23 +01:00
offset + = ( ( hstate - > src_x + hstate - > src_w - 1 ) /
xdiv ) * hstate - > bpp [ i ] ;
hstate - > xstride [ i ] = ( ( ( ( hstate - > src_w - 1 ) / xdiv ) - 1 ) *
hstate - > bpp [ i ] ) - fb - > pitches [ i ] ;
hstate - > pstride [ i ] = - 2 * hstate - > bpp [ i ] ;
2015-01-06 11:13:28 +01:00
break ;
2017-05-19 16:50:17 -04:00
case DRM_MODE_ROTATE_270 :
2021-02-19 13:00:23 +01:00
offset = ( ( hstate - > src_y + hstate - > src_h - 1 ) /
2019-01-10 15:10:34 +00:00
ydiv ) * fb - > pitches [ i ] ;
2021-02-19 13:00:23 +01:00
offset + = ( hstate - > src_x / xdiv ) * hstate - > bpp [ i ] ;
hstate - > xstride [ i ] = ( ( hstate - > src_h - 1 ) / ydiv ) *
2019-01-10 15:10:34 +00:00
fb - > pitches [ i ] ;
2021-02-19 13:00:23 +01:00
hstate - > pstride [ i ] = - fb - > pitches [ i ] - hstate - > bpp [ i ] ;
2015-01-06 11:13:28 +01:00
break ;
2017-05-19 16:50:17 -04:00
case DRM_MODE_ROTATE_0 :
2015-01-06 11:13:28 +01:00
default :
2021-02-19 13:00:23 +01:00
offset = ( hstate - > src_y / ydiv ) * fb - > pitches [ i ] ;
offset + = ( hstate - > src_x / xdiv ) * hstate - > bpp [ i ] ;
hstate - > xstride [ i ] = fb - > pitches [ i ] -
( ( hstate - > src_w / xdiv ) *
hstate - > bpp [ i ] ) ;
hstate - > pstride [ i ] = 0 ;
2015-01-06 11:13:28 +01:00
break ;
}
2021-02-19 13:00:23 +01:00
hstate - > offsets [ i ] = offset + fb - > offsets [ i ] ;
2015-01-06 11:13:28 +01:00
}
2019-01-10 15:10:44 +00:00
/*
* Swap width and size in case of 90 or 270 degrees rotation
*/
2021-02-19 13:00:23 +01:00
if ( drm_rotation_90_or_270 ( hstate - > base . rotation ) ) {
swap ( hstate - > src_w , hstate - > src_h ) ;
2019-01-10 15:10:44 +00:00
}
2015-01-06 11:13:28 +01:00
2017-02-06 18:57:19 +01:00
if ( ! desc - > layout . size & &
2021-02-19 13:00:23 +01:00
( mode - > hdisplay ! = hstate - > crtc_w | |
mode - > vdisplay ! = hstate - > crtc_h ) )
2015-02-05 16:32:33 +01:00
return - EINVAL ;
2015-01-06 11:13:28 +01:00
2021-02-19 13:00:23 +01:00
if ( ( hstate - > crtc_h ! = hstate - > src_h | | hstate - > crtc_w ! = hstate - > src_w ) & &
2017-02-06 18:57:19 +01:00
( ! desc - > layout . memsize | |
2021-02-19 13:00:23 +01:00
hstate - > base . fb - > format - > has_alpha ) )
2015-02-05 16:32:33 +01:00
return - EINVAL ;
2015-01-06 11:13:28 +01:00
2019-01-10 15:10:44 +00:00
return 0 ;
}
2015-02-05 16:32:33 +01:00
2019-01-10 15:10:44 +00:00
static void atmel_hlcdc_plane_atomic_disable ( struct drm_plane * p ,
drm/atomic: Pass the full state to planes atomic disable and update
The current atomic helpers have either their object state being passed as
an argument or the full atomic state.
The former is the pattern that was done at first, before switching to the
latter for new hooks or when it was needed.
Let's convert the remaining helpers to provide a consistent interface,
this time with the planes atomic_update and atomic_disable.
The conversion was done using the coccinelle script below, built tested on
all the drivers.
@@
identifier plane, plane_state;
symbol state;
@@
struct drm_plane_helper_funcs {
...
void (*atomic_update)(struct drm_plane *plane,
- struct drm_plane_state *plane_state);
+ struct drm_atomic_state *state);
...
}
@@
identifier plane, plane_state;
symbol state;
@@
struct drm_plane_helper_funcs {
...
void (*atomic_disable)(struct drm_plane *plane,
- struct drm_plane_state *plane_state);
+ struct drm_atomic_state *state);
...
}
@ plane_atomic_func @
identifier helpers;
identifier func;
@@
(
static const struct drm_plane_helper_funcs helpers = {
...,
.atomic_update = func,
...,
};
|
static const struct drm_plane_helper_funcs helpers = {
...,
.atomic_disable = func,
...,
};
)
@@
struct drm_plane_helper_funcs *FUNCS;
identifier f;
identifier crtc_state;
identifier plane, plane_state, state;
expression e;
@@
f(struct drm_crtc_state *crtc_state)
{
...
struct drm_atomic_state *state = e;
<+...
(
- FUNCS->atomic_disable(plane, plane_state)
+ FUNCS->atomic_disable(plane, state)
|
- FUNCS->atomic_update(plane, plane_state)
+ FUNCS->atomic_update(plane, state)
)
...+>
}
@@
identifier plane_atomic_func.func;
identifier plane;
symbol state;
@@
func(struct drm_plane *plane,
- struct drm_plane_state *state)
+ struct drm_plane_state *old_plane_state)
{
<...
- state
+ old_plane_state
...>
}
@ ignores_old_state @
identifier plane_atomic_func.func;
identifier plane, old_state;
@@
func(struct drm_plane *plane, struct drm_plane_state *old_state)
{
... when != old_state
}
@ adds_old_state depends on plane_atomic_func && !ignores_old_state @
identifier plane_atomic_func.func;
identifier plane, plane_state;
@@
func(struct drm_plane *plane, struct drm_plane_state *plane_state)
{
+ struct drm_plane_state *plane_state = drm_atomic_get_old_plane_state(state, plane);
...
}
@ depends on plane_atomic_func @
identifier plane_atomic_func.func;
identifier plane, plane_state;
@@
func(struct drm_plane *plane,
- struct drm_plane_state *plane_state
+ struct drm_atomic_state *state
)
{ ... }
@ include depends on adds_old_state @
@@
#include <drm/drm_atomic.h>
@ no_include depends on !include && adds_old_state @
@@
+ #include <drm/drm_atomic.h>
#include <drm/...>
@@
identifier plane_atomic_func.func;
identifier plane, state;
identifier plane_state;
@@
func(struct drm_plane *plane, struct drm_atomic_state *state) {
...
struct drm_plane_state *plane_state = drm_atomic_get_old_plane_state(state, plane);
<+...
- plane_state->state
+ state
...+>
}
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
Acked-by: Thomas Zimmermann <tzimmermann@suse.de>
Link: https://patchwork.freedesktop.org/patch/msgid/20210219120032.260676-9-maxime@cerno.tech
2021-02-19 13:00:29 +01:00
struct drm_atomic_state * state )
2019-01-10 15:10:44 +00:00
{
struct atmel_hlcdc_plane * plane = drm_plane_to_atmel_hlcdc_plane ( p ) ;
2015-01-06 11:13:28 +01:00
2019-01-10 15:10:44 +00:00
/* Disable interrupts */
atmel_hlcdc_layer_write_reg ( & plane - > layer , ATMEL_HLCDC_LAYER_IDR ,
0xffffffff ) ;
/* Disable the layer */
atmel_hlcdc_layer_write_reg ( & plane - > layer , ATMEL_HLCDC_LAYER_CHDR ,
ATMEL_HLCDC_LAYER_RST |
ATMEL_HLCDC_LAYER_A2Q |
ATMEL_HLCDC_LAYER_UPDATE ) ;
/* Clear all pending interrupts */
atmel_hlcdc_layer_read_reg ( & plane - > layer , ATMEL_HLCDC_LAYER_ISR ) ;
2015-01-06 11:13:28 +01:00
}
2015-02-05 16:32:33 +01:00
static void atmel_hlcdc_plane_atomic_update ( struct drm_plane * p ,
drm/atomic: Pass the full state to planes atomic disable and update
The current atomic helpers have either their object state being passed as
an argument or the full atomic state.
The former is the pattern that was done at first, before switching to the
latter for new hooks or when it was needed.
Let's convert the remaining helpers to provide a consistent interface,
this time with the planes atomic_update and atomic_disable.
The conversion was done using the coccinelle script below, built tested on
all the drivers.
@@
identifier plane, plane_state;
symbol state;
@@
struct drm_plane_helper_funcs {
...
void (*atomic_update)(struct drm_plane *plane,
- struct drm_plane_state *plane_state);
+ struct drm_atomic_state *state);
...
}
@@
identifier plane, plane_state;
symbol state;
@@
struct drm_plane_helper_funcs {
...
void (*atomic_disable)(struct drm_plane *plane,
- struct drm_plane_state *plane_state);
+ struct drm_atomic_state *state);
...
}
@ plane_atomic_func @
identifier helpers;
identifier func;
@@
(
static const struct drm_plane_helper_funcs helpers = {
...,
.atomic_update = func,
...,
};
|
static const struct drm_plane_helper_funcs helpers = {
...,
.atomic_disable = func,
...,
};
)
@@
struct drm_plane_helper_funcs *FUNCS;
identifier f;
identifier crtc_state;
identifier plane, plane_state, state;
expression e;
@@
f(struct drm_crtc_state *crtc_state)
{
...
struct drm_atomic_state *state = e;
<+...
(
- FUNCS->atomic_disable(plane, plane_state)
+ FUNCS->atomic_disable(plane, state)
|
- FUNCS->atomic_update(plane, plane_state)
+ FUNCS->atomic_update(plane, state)
)
...+>
}
@@
identifier plane_atomic_func.func;
identifier plane;
symbol state;
@@
func(struct drm_plane *plane,
- struct drm_plane_state *state)
+ struct drm_plane_state *old_plane_state)
{
<...
- state
+ old_plane_state
...>
}
@ ignores_old_state @
identifier plane_atomic_func.func;
identifier plane, old_state;
@@
func(struct drm_plane *plane, struct drm_plane_state *old_state)
{
... when != old_state
}
@ adds_old_state depends on plane_atomic_func && !ignores_old_state @
identifier plane_atomic_func.func;
identifier plane, plane_state;
@@
func(struct drm_plane *plane, struct drm_plane_state *plane_state)
{
+ struct drm_plane_state *plane_state = drm_atomic_get_old_plane_state(state, plane);
...
}
@ depends on plane_atomic_func @
identifier plane_atomic_func.func;
identifier plane, plane_state;
@@
func(struct drm_plane *plane,
- struct drm_plane_state *plane_state
+ struct drm_atomic_state *state
)
{ ... }
@ include depends on adds_old_state @
@@
#include <drm/drm_atomic.h>
@ no_include depends on !include && adds_old_state @
@@
+ #include <drm/drm_atomic.h>
#include <drm/...>
@@
identifier plane_atomic_func.func;
identifier plane, state;
identifier plane_state;
@@
func(struct drm_plane *plane, struct drm_atomic_state *state) {
...
struct drm_plane_state *plane_state = drm_atomic_get_old_plane_state(state, plane);
<+...
- plane_state->state
+ state
...+>
}
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
Acked-by: Thomas Zimmermann <tzimmermann@suse.de>
Link: https://patchwork.freedesktop.org/patch/msgid/20210219120032.260676-9-maxime@cerno.tech
2021-02-19 13:00:29 +01:00
struct drm_atomic_state * state )
2015-01-06 11:13:28 +01:00
{
drm: Use state helper instead of the plane state pointer
Many drivers reference the plane->state pointer in order to get the
current plane state in their atomic_update or atomic_disable hooks,
which would be the new plane state in the global atomic state since
_swap_state happened when those hooks are run.
Use the drm_atomic_get_new_plane_state helper to get that state to make it
more obvious.
This was made using the coccinelle script below:
@ plane_atomic_func @
identifier helpers;
identifier func;
@@
(
static const struct drm_plane_helper_funcs helpers = {
...,
.atomic_disable = func,
...,
};
|
static const struct drm_plane_helper_funcs helpers = {
...,
.atomic_update = func,
...,
};
)
@ adds_new_state @
identifier plane_atomic_func.func;
identifier plane, state;
identifier new_state;
@@
func(struct drm_plane *plane, struct drm_atomic_state *state)
{
...
- struct drm_plane_state *new_state = plane->state;
+ struct drm_plane_state *new_state = drm_atomic_get_new_plane_state(state, plane);
...
}
@ include depends on adds_new_state @
@@
#include <drm/drm_atomic.h>
@ no_include depends on !include && adds_new_state @
@@
+ #include <drm/drm_atomic.h>
#include <drm/...>
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
Acked-by: Thomas Zimmermann <tzimmermann@suse.de>
Link: https://lore.kernel.org/r/20210219120032.260676-1-maxime@cerno.tech
2021-02-19 13:00:30 +01:00
struct drm_plane_state * new_s = drm_atomic_get_new_plane_state ( state ,
p ) ;
2015-02-05 16:32:33 +01:00
struct atmel_hlcdc_plane * plane = drm_plane_to_atmel_hlcdc_plane ( p ) ;
2021-02-19 13:00:23 +01:00
struct atmel_hlcdc_plane_state * hstate =
drm: Store new plane state in a variable for atomic_update and disable
In order to store the new plane state in a subsequent helper, let's move
the plane->state dereferences into a variable.
This was done using the following coccinelle script, plus some hand
changes for vmwgfx:
@ plane_atomic_func @
identifier helpers;
identifier func;
@@
(
static const struct drm_plane_helper_funcs helpers = {
...,
.atomic_disable = func,
...,
};
|
static const struct drm_plane_helper_funcs helpers = {
...,
.atomic_update = func,
...,
};
)
@ has_new_state_old_state @
identifier plane_atomic_func.func;
identifier plane;
identifier new_state;
symbol old_state;
@@
func(struct drm_plane *plane, struct drm_plane_state *old_state)
{
...
struct drm_plane_state *new_state = plane->state;
...
}
@ depends on !has_new_state_old_state @
identifier plane_atomic_func.func;
identifier plane;
symbol old_state;
@@
func(struct drm_plane *plane, struct drm_plane_state *old_state)
{
+ struct drm_plane_state *new_state = plane->state;
<+...
- plane->state
+ new_state
...+>
}
@ has_new_state_state @
identifier plane_atomic_func.func;
identifier plane;
identifier new_state;
symbol state;
@@
func(struct drm_plane *plane, struct drm_plane_state *state)
{
...
struct drm_plane_state *new_state = plane->state;
...
}
@ depends on !has_new_state_state @
identifier plane_atomic_func.func;
identifier plane;
symbol state;
@@
func(struct drm_plane *plane, struct drm_plane_state *state)
{
+ struct drm_plane_state *new_plane_state = plane->state;
<+...
- plane->state
+ new_plane_state
...+>
}
@ has_new_state_old_s @
identifier plane_atomic_func.func;
identifier plane;
identifier new_state;
symbol old_s;
@@
func(struct drm_plane *plane, struct drm_plane_state *old_s)
{
...
struct drm_plane_state *new_state = plane->state;
...
}
@ depends on !has_new_state_old_s @
identifier plane_atomic_func.func;
identifier plane;
symbol old_s;
@@
func(struct drm_plane *plane, struct drm_plane_state *old_s)
{
+ struct drm_plane_state *new_s = plane->state;
<+...
- plane->state
+ new_s
...+>
}
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
Acked-by: Thomas Zimmermann <tzimmermann@suse.de>
Link: https://lore.kernel.org/r/20210219120032.260676-1-maxime@cerno.tech
2021-02-19 13:00:27 +01:00
drm_plane_state_to_atmel_hlcdc_plane_state ( new_s ) ;
2017-02-06 18:57:19 +01:00
u32 sr ;
2015-02-05 16:32:33 +01:00
drm: Store new plane state in a variable for atomic_update and disable
In order to store the new plane state in a subsequent helper, let's move
the plane->state dereferences into a variable.
This was done using the following coccinelle script, plus some hand
changes for vmwgfx:
@ plane_atomic_func @
identifier helpers;
identifier func;
@@
(
static const struct drm_plane_helper_funcs helpers = {
...,
.atomic_disable = func,
...,
};
|
static const struct drm_plane_helper_funcs helpers = {
...,
.atomic_update = func,
...,
};
)
@ has_new_state_old_state @
identifier plane_atomic_func.func;
identifier plane;
identifier new_state;
symbol old_state;
@@
func(struct drm_plane *plane, struct drm_plane_state *old_state)
{
...
struct drm_plane_state *new_state = plane->state;
...
}
@ depends on !has_new_state_old_state @
identifier plane_atomic_func.func;
identifier plane;
symbol old_state;
@@
func(struct drm_plane *plane, struct drm_plane_state *old_state)
{
+ struct drm_plane_state *new_state = plane->state;
<+...
- plane->state
+ new_state
...+>
}
@ has_new_state_state @
identifier plane_atomic_func.func;
identifier plane;
identifier new_state;
symbol state;
@@
func(struct drm_plane *plane, struct drm_plane_state *state)
{
...
struct drm_plane_state *new_state = plane->state;
...
}
@ depends on !has_new_state_state @
identifier plane_atomic_func.func;
identifier plane;
symbol state;
@@
func(struct drm_plane *plane, struct drm_plane_state *state)
{
+ struct drm_plane_state *new_plane_state = plane->state;
<+...
- plane->state
+ new_plane_state
...+>
}
@ has_new_state_old_s @
identifier plane_atomic_func.func;
identifier plane;
identifier new_state;
symbol old_s;
@@
func(struct drm_plane *plane, struct drm_plane_state *old_s)
{
...
struct drm_plane_state *new_state = plane->state;
...
}
@ depends on !has_new_state_old_s @
identifier plane_atomic_func.func;
identifier plane;
symbol old_s;
@@
func(struct drm_plane *plane, struct drm_plane_state *old_s)
{
+ struct drm_plane_state *new_s = plane->state;
<+...
- plane->state
+ new_s
...+>
}
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
Acked-by: Thomas Zimmermann <tzimmermann@suse.de>
Link: https://lore.kernel.org/r/20210219120032.260676-1-maxime@cerno.tech
2021-02-19 13:00:27 +01:00
if ( ! new_s - > crtc | | ! new_s - > fb )
2015-02-05 16:32:33 +01:00
return ;
2021-02-19 13:00:23 +01:00
if ( ! hstate - > base . visible ) {
drm/atomic: Pass the full state to planes atomic disable and update
The current atomic helpers have either their object state being passed as
an argument or the full atomic state.
The former is the pattern that was done at first, before switching to the
latter for new hooks or when it was needed.
Let's convert the remaining helpers to provide a consistent interface,
this time with the planes atomic_update and atomic_disable.
The conversion was done using the coccinelle script below, built tested on
all the drivers.
@@
identifier plane, plane_state;
symbol state;
@@
struct drm_plane_helper_funcs {
...
void (*atomic_update)(struct drm_plane *plane,
- struct drm_plane_state *plane_state);
+ struct drm_atomic_state *state);
...
}
@@
identifier plane, plane_state;
symbol state;
@@
struct drm_plane_helper_funcs {
...
void (*atomic_disable)(struct drm_plane *plane,
- struct drm_plane_state *plane_state);
+ struct drm_atomic_state *state);
...
}
@ plane_atomic_func @
identifier helpers;
identifier func;
@@
(
static const struct drm_plane_helper_funcs helpers = {
...,
.atomic_update = func,
...,
};
|
static const struct drm_plane_helper_funcs helpers = {
...,
.atomic_disable = func,
...,
};
)
@@
struct drm_plane_helper_funcs *FUNCS;
identifier f;
identifier crtc_state;
identifier plane, plane_state, state;
expression e;
@@
f(struct drm_crtc_state *crtc_state)
{
...
struct drm_atomic_state *state = e;
<+...
(
- FUNCS->atomic_disable(plane, plane_state)
+ FUNCS->atomic_disable(plane, state)
|
- FUNCS->atomic_update(plane, plane_state)
+ FUNCS->atomic_update(plane, state)
)
...+>
}
@@
identifier plane_atomic_func.func;
identifier plane;
symbol state;
@@
func(struct drm_plane *plane,
- struct drm_plane_state *state)
+ struct drm_plane_state *old_plane_state)
{
<...
- state
+ old_plane_state
...>
}
@ ignores_old_state @
identifier plane_atomic_func.func;
identifier plane, old_state;
@@
func(struct drm_plane *plane, struct drm_plane_state *old_state)
{
... when != old_state
}
@ adds_old_state depends on plane_atomic_func && !ignores_old_state @
identifier plane_atomic_func.func;
identifier plane, plane_state;
@@
func(struct drm_plane *plane, struct drm_plane_state *plane_state)
{
+ struct drm_plane_state *plane_state = drm_atomic_get_old_plane_state(state, plane);
...
}
@ depends on plane_atomic_func @
identifier plane_atomic_func.func;
identifier plane, plane_state;
@@
func(struct drm_plane *plane,
- struct drm_plane_state *plane_state
+ struct drm_atomic_state *state
)
{ ... }
@ include depends on adds_old_state @
@@
#include <drm/drm_atomic.h>
@ no_include depends on !include && adds_old_state @
@@
+ #include <drm/drm_atomic.h>
#include <drm/...>
@@
identifier plane_atomic_func.func;
identifier plane, state;
identifier plane_state;
@@
func(struct drm_plane *plane, struct drm_atomic_state *state) {
...
struct drm_plane_state *plane_state = drm_atomic_get_old_plane_state(state, plane);
<+...
- plane_state->state
+ state
...+>
}
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
Acked-by: Thomas Zimmermann <tzimmermann@suse.de>
Link: https://patchwork.freedesktop.org/patch/msgid/20210219120032.260676-9-maxime@cerno.tech
2021-02-19 13:00:29 +01:00
atmel_hlcdc_plane_atomic_disable ( p , state ) ;
2019-01-10 15:10:44 +00:00
return ;
}
2021-02-19 13:00:23 +01:00
atmel_hlcdc_plane_update_pos_and_size ( plane , hstate ) ;
atmel_hlcdc_plane_update_general_settings ( plane , hstate ) ;
atmel_hlcdc_plane_update_format ( plane , hstate ) ;
atmel_hlcdc_plane_update_clut ( plane , hstate ) ;
atmel_hlcdc_plane_update_buffers ( plane , hstate ) ;
atmel_hlcdc_plane_update_disc_area ( plane , hstate ) ;
2015-02-05 16:32:33 +01:00
2017-02-06 18:57:19 +01:00
/* Enable the overrun interrupts. */
atmel_hlcdc_layer_write_reg ( & plane - > layer , ATMEL_HLCDC_LAYER_IER ,
ATMEL_HLCDC_LAYER_OVR_IRQ ( 0 ) |
ATMEL_HLCDC_LAYER_OVR_IRQ ( 1 ) |
ATMEL_HLCDC_LAYER_OVR_IRQ ( 2 ) ) ;
/* Apply the new config at the next SOF event. */
sr = atmel_hlcdc_layer_read_reg ( & plane - > layer , ATMEL_HLCDC_LAYER_CHSR ) ;
atmel_hlcdc_layer_write_reg ( & plane - > layer , ATMEL_HLCDC_LAYER_CHER ,
ATMEL_HLCDC_LAYER_UPDATE |
( sr & ATMEL_HLCDC_LAYER_EN ?
ATMEL_HLCDC_LAYER_A2Q : ATMEL_HLCDC_LAYER_EN ) ) ;
2015-01-06 11:13:28 +01:00
}
2018-04-11 09:39:26 +02:00
static int atmel_hlcdc_plane_init_properties ( struct atmel_hlcdc_plane * plane )
2015-01-06 11:13:28 +01:00
{
2017-02-06 18:57:19 +01:00
const struct atmel_hlcdc_layer_desc * desc = plane - > layer . desc ;
2015-01-06 11:13:28 +01:00
if ( desc - > type = = ATMEL_HLCDC_OVERLAY_LAYER | |
2018-04-11 09:39:26 +02:00
desc - > type = = ATMEL_HLCDC_CURSOR_LAYER ) {
int ret ;
ret = drm_plane_create_alpha_property ( & plane - > base ) ;
if ( ret )
return ret ;
}
2015-01-06 11:13:28 +01:00
2018-06-17 10:48:22 +02:00
if ( desc - > layout . xstride [ 0 ] & & desc - > layout . pstride [ 0 ] ) {
2016-09-26 19:30:50 +03:00
int ret ;
ret = drm_plane_create_rotation_property ( & plane - > base ,
2017-05-19 16:50:17 -04:00
DRM_MODE_ROTATE_0 ,
DRM_MODE_ROTATE_0 |
DRM_MODE_ROTATE_90 |
DRM_MODE_ROTATE_180 |
DRM_MODE_ROTATE_270 ) ;
2016-09-26 19:30:50 +03:00
if ( ret )
return ret ;
}
2015-01-06 11:13:28 +01:00
if ( desc - > layout . csc ) {
/*
* TODO : decare a " yuv-to-rgb-conv-factors " property to let
* userspace modify these factors ( using a BLOB property ? ) .
*/
2017-02-06 18:57:19 +01:00
atmel_hlcdc_layer_write_cfg ( & plane - > layer ,
desc - > layout . csc ,
0x4c900091 ) ;
atmel_hlcdc_layer_write_cfg ( & plane - > layer ,
desc - > layout . csc + 1 ,
0x7a5f5090 ) ;
atmel_hlcdc_layer_write_cfg ( & plane - > layer ,
desc - > layout . csc + 2 ,
0x40040890 ) ;
2015-01-06 11:13:28 +01:00
}
2016-09-26 19:30:50 +03:00
return 0 ;
2015-01-06 11:13:28 +01:00
}
2017-02-06 18:57:19 +01:00
void atmel_hlcdc_plane_irq ( struct atmel_hlcdc_plane * plane )
{
const struct atmel_hlcdc_layer_desc * desc = plane - > layer . desc ;
u32 isr ;
isr = atmel_hlcdc_layer_read_reg ( & plane - > layer , ATMEL_HLCDC_LAYER_ISR ) ;
/*
* There ' s not much we can do in case of overrun except informing
* the user . However , we are in interrupt context here , hence the
* use of dev_dbg ( ) .
*/
if ( isr &
( ATMEL_HLCDC_LAYER_OVR_IRQ ( 0 ) | ATMEL_HLCDC_LAYER_OVR_IRQ ( 1 ) |
ATMEL_HLCDC_LAYER_OVR_IRQ ( 2 ) ) )
dev_dbg ( plane - > base . dev - > dev , " overrun on plane %s \n " ,
desc - > name ) ;
}
2017-07-03 21:53:54 +05:30
static const struct drm_plane_helper_funcs atmel_hlcdc_layer_plane_helper_funcs = {
2015-02-05 16:32:33 +01:00
. atomic_check = atmel_hlcdc_plane_atomic_check ,
. atomic_update = atmel_hlcdc_plane_atomic_update ,
. atomic_disable = atmel_hlcdc_plane_atomic_disable ,
} ;
2017-02-06 18:57:19 +01:00
static int atmel_hlcdc_plane_alloc_dscrs ( struct drm_plane * p ,
struct atmel_hlcdc_plane_state * state )
{
struct atmel_hlcdc_dc * dc = p - > dev - > dev_private ;
int i ;
for ( i = 0 ; i < ARRAY_SIZE ( state - > dscrs ) ; i + + ) {
struct atmel_hlcdc_dma_channel_dscr * dscr ;
dma_addr_t dscr_dma ;
dscr = dma_pool_alloc ( dc - > dscrpool , GFP_KERNEL , & dscr_dma ) ;
if ( ! dscr )
goto err ;
dscr - > addr = 0 ;
dscr - > next = dscr_dma ;
dscr - > self = dscr_dma ;
dscr - > ctrl = ATMEL_HLCDC_LAYER_DFETCH ;
state - > dscrs [ i ] = dscr ;
}
return 0 ;
err :
for ( i - - ; i > = 0 ; i - - ) {
dma_pool_free ( dc - > dscrpool , state - > dscrs [ i ] ,
state - > dscrs [ i ] - > self ) ;
}
return - ENOMEM ;
}
2015-02-05 16:32:33 +01:00
static void atmel_hlcdc_plane_reset ( struct drm_plane * p )
{
struct atmel_hlcdc_plane_state * state ;
if ( p - > state ) {
state = drm_plane_state_to_atmel_hlcdc_plane_state ( p - > state ) ;
if ( state - > base . fb )
2017-08-03 14:58:20 +03:00
drm_framebuffer_put ( state - > base . fb ) ;
2015-02-05 16:32:33 +01:00
kfree ( state ) ;
p - > state = NULL ;
}
state = kzalloc ( sizeof ( * state ) , GFP_KERNEL ) ;
if ( state ) {
2017-02-06 18:57:19 +01:00
if ( atmel_hlcdc_plane_alloc_dscrs ( p , state ) ) {
kfree ( state ) ;
dev_err ( p - > dev - > dev ,
" Failed to allocate initial plane state \n " ) ;
return ;
}
2018-08-04 17:15:24 +01:00
__drm_atomic_helper_plane_reset ( p , & state - > base ) ;
2015-02-05 16:32:33 +01:00
}
}
static struct drm_plane_state *
atmel_hlcdc_plane_atomic_duplicate_state ( struct drm_plane * p )
{
struct atmel_hlcdc_plane_state * state =
drm_plane_state_to_atmel_hlcdc_plane_state ( p - > state ) ;
struct atmel_hlcdc_plane_state * copy ;
copy = kmemdup ( state , sizeof ( * state ) , GFP_KERNEL ) ;
if ( ! copy )
return NULL ;
2017-02-06 18:57:19 +01:00
if ( atmel_hlcdc_plane_alloc_dscrs ( p , copy ) ) {
kfree ( copy ) ;
return NULL ;
}
2015-02-06 16:25:06 +01:00
2015-02-05 16:32:33 +01:00
if ( copy - > base . fb )
2017-08-03 14:58:20 +03:00
drm_framebuffer_get ( copy - > base . fb ) ;
2015-02-05 16:32:33 +01:00
return & copy - > base ;
}
2017-02-06 18:57:19 +01:00
static void atmel_hlcdc_plane_atomic_destroy_state ( struct drm_plane * p ,
2015-02-05 16:32:33 +01:00
struct drm_plane_state * s )
{
struct atmel_hlcdc_plane_state * state =
drm_plane_state_to_atmel_hlcdc_plane_state ( s ) ;
2017-02-06 18:57:19 +01:00
struct atmel_hlcdc_dc * dc = p - > dev - > dev_private ;
int i ;
for ( i = 0 ; i < ARRAY_SIZE ( state - > dscrs ) ; i + + ) {
dma_pool_free ( dc - > dscrpool , state - > dscrs [ i ] ,
state - > dscrs [ i ] - > self ) ;
}
2015-02-05 16:32:33 +01:00
if ( s - > fb )
2017-08-03 14:58:20 +03:00
drm_framebuffer_put ( s - > fb ) ;
2015-02-05 16:32:33 +01:00
kfree ( state ) ;
}
2017-07-03 21:53:54 +05:30
static const struct drm_plane_funcs layer_plane_funcs = {
2015-02-05 16:32:33 +01:00
. update_plane = drm_atomic_helper_update_plane ,
. disable_plane = drm_atomic_helper_disable_plane ,
2018-04-05 18:13:57 +03:00
. destroy = drm_plane_cleanup ,
2015-02-05 16:32:33 +01:00
. reset = atmel_hlcdc_plane_reset ,
. atomic_duplicate_state = atmel_hlcdc_plane_atomic_duplicate_state ,
. atomic_destroy_state = atmel_hlcdc_plane_atomic_destroy_state ,
2015-01-06 11:13:28 +01:00
} ;
2017-02-06 18:57:19 +01:00
static int atmel_hlcdc_plane_create ( struct drm_device * dev ,
2018-04-11 09:39:26 +02:00
const struct atmel_hlcdc_layer_desc * desc )
2015-01-06 11:13:28 +01:00
{
2017-02-06 18:57:19 +01:00
struct atmel_hlcdc_dc * dc = dev - > dev_private ;
2015-01-06 11:13:28 +01:00
struct atmel_hlcdc_plane * plane ;
enum drm_plane_type type ;
int ret ;
plane = devm_kzalloc ( dev - > dev , sizeof ( * plane ) , GFP_KERNEL ) ;
if ( ! plane )
2017-02-06 18:57:19 +01:00
return - ENOMEM ;
2015-01-06 11:13:28 +01:00
2017-02-06 18:57:19 +01:00
atmel_hlcdc_layer_init ( & plane - > layer , desc , dc - > hlcdc - > regmap ) ;
2015-01-06 11:13:28 +01:00
if ( desc - > type = = ATMEL_HLCDC_BASE_LAYER )
type = DRM_PLANE_TYPE_PRIMARY ;
else if ( desc - > type = = ATMEL_HLCDC_CURSOR_LAYER )
type = DRM_PLANE_TYPE_CURSOR ;
else
type = DRM_PLANE_TYPE_OVERLAY ;
ret = drm_universal_plane_init ( dev , & plane - > base , 0 ,
& layer_plane_funcs ,
desc - > formats - > formats ,
2017-07-23 20:46:38 -07:00
desc - > formats - > nformats ,
NULL , type , NULL ) ;
2015-01-06 11:13:28 +01:00
if ( ret )
2017-02-06 18:57:19 +01:00
return ret ;
2015-01-06 11:13:28 +01:00
2015-02-05 16:32:33 +01:00
drm_plane_helper_add ( & plane - > base ,
& atmel_hlcdc_layer_plane_helper_funcs ) ;
2015-01-06 11:13:28 +01:00
/* Set default property values*/
2018-04-11 09:39:26 +02:00
ret = atmel_hlcdc_plane_init_properties ( plane ) ;
2016-09-26 19:30:50 +03:00
if ( ret )
2017-02-06 18:57:19 +01:00
return ret ;
dc - > layers [ desc - > id ] = & plane - > layer ;
2015-01-06 11:13:28 +01:00
2017-02-06 18:57:19 +01:00
return 0 ;
2015-01-06 11:13:28 +01:00
}
2017-02-06 18:57:19 +01:00
int atmel_hlcdc_create_planes ( struct drm_device * dev )
2015-01-06 11:13:28 +01:00
{
struct atmel_hlcdc_dc * dc = dev - > dev_private ;
const struct atmel_hlcdc_layer_desc * descs = dc - > desc - > layers ;
int nlayers = dc - > desc - > nlayers ;
2017-02-06 18:57:19 +01:00
int i , ret ;
2015-01-06 11:13:28 +01:00
2017-02-06 18:57:19 +01:00
dc - > dscrpool = dmam_pool_create ( " atmel-hlcdc-dscr " , dev - > dev ,
sizeof ( struct atmel_hlcdc_dma_channel_dscr ) ,
sizeof ( u64 ) , 0 ) ;
if ( ! dc - > dscrpool )
return - ENOMEM ;
2015-01-06 11:13:28 +01:00
2017-02-06 18:57:19 +01:00
for ( i = 0 ; i < nlayers ; i + + ) {
if ( descs [ i ] . type ! = ATMEL_HLCDC_BASE_LAYER & &
descs [ i ] . type ! = ATMEL_HLCDC_OVERLAY_LAYER & &
descs [ i ] . type ! = ATMEL_HLCDC_CURSOR_LAYER )
2015-01-06 11:13:28 +01:00
continue ;
2018-04-11 09:39:26 +02:00
ret = atmel_hlcdc_plane_create ( dev , & descs [ i ] ) ;
2017-02-06 18:57:19 +01:00
if ( ret )
return ret ;
2015-01-06 11:13:28 +01:00
}
2017-02-06 18:57:19 +01:00
return 0 ;
2015-01-06 11:13:28 +01:00
}