2018-04-22 17:33:20 -04:00
// SPDX-License-Identifier: GPL-2.0+
2013-06-04 11:22:30 -03:00
/*
* vsp1_lif . c - - R - Car VSP1 LCD Controller Interface
*
2014-02-06 14:42:31 -03:00
* Copyright ( C ) 2013 - 2014 Renesas Electronics Corporation
2013-06-04 11:22:30 -03:00
*
* Contact : Laurent Pinchart ( laurent . pinchart @ ideasonboard . com )
*/
# include <linux/device.h>
# include <linux/gfp.h>
# include <media/v4l2-subdev.h>
# include "vsp1.h"
2015-11-22 20:29:25 -02:00
# include "vsp1_dl.h"
2013-06-04 11:22:30 -03:00
# include "vsp1_lif.h"
# define LIF_MIN_SIZE 2U
2016-03-25 06:51:06 -03:00
# define LIF_MAX_SIZE 8190U
2013-06-04 11:22:30 -03:00
/* -----------------------------------------------------------------------------
* Device Access
*/
2018-05-18 16:42:02 -04:00
static inline void vsp1_lif_write ( struct vsp1_lif * lif ,
struct vsp1_dl_body * dlb , u32 reg , u32 data )
2013-06-04 11:22:30 -03:00
{
2018-05-18 16:42:02 -04:00
vsp1_dl_body_write ( dlb , reg + lif - > entity . index * VI6_LIF_OFFSET ,
data ) ;
2013-06-04 11:22:30 -03:00
}
/* -----------------------------------------------------------------------------
2015-11-17 13:10:26 -02:00
* V4L2 Subdevice Operations
2013-06-04 11:22:30 -03:00
*/
2017-11-27 14:59:45 -05:00
static const unsigned int lif_codes [ ] = {
MEDIA_BUS_FMT_ARGB8888_1X32 ,
MEDIA_BUS_FMT_AYUV8_1X32 ,
} ;
2013-06-04 11:22:30 -03:00
static int lif_enum_mbus_code ( struct v4l2_subdev * subdev ,
2015-03-04 01:47:54 -08:00
struct v4l2_subdev_pad_config * cfg ,
2013-06-04 11:22:30 -03:00
struct v4l2_subdev_mbus_code_enum * code )
{
2017-11-27 14:59:45 -05:00
return vsp1_subdev_enum_mbus_code ( subdev , cfg , code , lif_codes ,
ARRAY_SIZE ( lif_codes ) ) ;
2013-06-04 11:22:30 -03:00
}
static int lif_enum_frame_size ( struct v4l2_subdev * subdev ,
2015-03-04 01:47:54 -08:00
struct v4l2_subdev_pad_config * cfg ,
2013-06-04 11:22:30 -03:00
struct v4l2_subdev_frame_size_enum * fse )
{
2016-02-24 20:25:42 -03:00
return vsp1_subdev_enum_frame_size ( subdev , cfg , fse , LIF_MIN_SIZE ,
LIF_MIN_SIZE , LIF_MAX_SIZE ,
LIF_MAX_SIZE ) ;
2013-06-04 11:22:30 -03:00
}
2015-11-01 15:18:32 -02:00
static int lif_set_format ( struct v4l2_subdev * subdev ,
struct v4l2_subdev_pad_config * cfg ,
2013-06-04 11:22:30 -03:00
struct v4l2_subdev_format * fmt )
{
2017-11-27 14:59:45 -05:00
return vsp1_subdev_set_pad_format ( subdev , cfg , fmt , lif_codes ,
ARRAY_SIZE ( lif_codes ) ,
LIF_MIN_SIZE , LIF_MIN_SIZE ,
LIF_MAX_SIZE , LIF_MAX_SIZE ) ;
2013-06-04 11:22:30 -03:00
}
2016-06-17 21:11:26 -03:00
static const struct v4l2_subdev_pad_ops lif_pad_ops = {
2015-11-15 20:09:08 -02:00
. init_cfg = vsp1_entity_init_cfg ,
2013-06-04 11:22:30 -03:00
. enum_mbus_code = lif_enum_mbus_code ,
. enum_frame_size = lif_enum_frame_size ,
2016-02-24 21:10:13 -03:00
. get_fmt = vsp1_subdev_get_pad_format ,
2013-06-04 11:22:30 -03:00
. set_fmt = lif_set_format ,
} ;
2016-06-17 21:11:26 -03:00
static const struct v4l2_subdev_ops lif_ops = {
2013-06-04 11:22:30 -03:00
. pad = & lif_pad_ops ,
} ;
2015-11-17 13:10:26 -02:00
/* -----------------------------------------------------------------------------
* VSP1 Entity Operations
*/
2018-05-18 16:42:01 -04:00
static void lif_configure_stream ( struct vsp1_entity * entity ,
struct vsp1_pipeline * pipe ,
2019-03-11 20:13:43 +02:00
struct vsp1_dl_list * dl ,
2018-05-18 16:42:02 -04:00
struct vsp1_dl_body * dlb )
2015-11-17 13:10:26 -02:00
{
const struct v4l2_mbus_framefmt * format ;
struct vsp1_lif * lif = to_lif ( & entity - > subdev ) ;
2017-10-26 02:27:51 -04:00
unsigned int hbth ;
unsigned int obth ;
unsigned int lbth ;
2015-11-17 13:10:26 -02:00
format = vsp1_entity_get_pad_format ( & lif - > entity , lif - > entity . config ,
LIF_PAD_SOURCE ) ;
2018-11-21 22:38:07 -05:00
switch ( entity - > vsp1 - > version & VI6_IP_VERSION_MODEL_MASK ) {
2017-10-26 02:27:51 -04:00
case VI6_IP_VERSION_MODEL_VSPD_GEN2 :
case VI6_IP_VERSION_MODEL_VSPD_V2H :
hbth = 1536 ;
obth = min ( 128U , ( format - > width + 1 ) / 2 * format - > height - 4 ) ;
lbth = 1520 ;
break ;
case VI6_IP_VERSION_MODEL_VSPDL_GEN3 :
case VI6_IP_VERSION_MODEL_VSPD_V3 :
hbth = 0 ;
obth = 1500 ;
lbth = 0 ;
break ;
case VI6_IP_VERSION_MODEL_VSPD_GEN3 :
default :
hbth = 0 ;
obth = 3000 ;
lbth = 0 ;
break ;
}
2015-11-17 13:10:26 -02:00
2018-05-18 16:42:02 -04:00
vsp1_lif_write ( lif , dlb , VI6_LIF_CSBTH ,
2015-11-17 13:10:26 -02:00
( hbth < < VI6_LIF_CSBTH_HBTH_SHIFT ) |
( lbth < < VI6_LIF_CSBTH_LBTH_SHIFT ) ) ;
2018-05-18 16:42:02 -04:00
vsp1_lif_write ( lif , dlb , VI6_LIF_CTRL ,
2015-11-17 13:10:26 -02:00
( obth < < VI6_LIF_CTRL_OBTH_SHIFT ) |
( format - > code = = 0 ? VI6_LIF_CTRL_CFMT : 0 ) |
VI6_LIF_CTRL_REQSEL | VI6_LIF_CTRL_LIF_EN ) ;
2018-01-18 09:05:51 -05:00
/*
* On R - Car V3M the LIF0 buffer attribute register has to be set to a
* non - default value to guarantee proper operation ( otherwise artifacts
* may appear on the output ) . The value required by the manual is not
* explained but is likely a buffer size or threshold .
*/
if ( ( entity - > vsp1 - > version & VI6_IP_VERSION_MASK ) = =
( VI6_IP_VERSION_MODEL_VSPD_V3 | VI6_IP_VERSION_SOC_V3M ) )
2018-05-18 16:42:02 -04:00
vsp1_lif_write ( lif , dlb , VI6_LIF_LBA ,
2018-01-18 09:05:51 -05:00
VI6_LIF_LBA_LBA0 |
( 1536 < < VI6_LIF_LBA_LBA1_SHIFT ) ) ;
2015-11-17 13:10:26 -02:00
}
static const struct vsp1_entity_operations lif_entity_ops = {
2018-05-18 16:42:01 -04:00
. configure_stream = lif_configure_stream ,
2015-11-17 13:10:26 -02:00
} ;
2013-06-04 11:22:30 -03:00
/* -----------------------------------------------------------------------------
* Initialization and Cleanup
*/
2017-06-21 16:10:18 +03:00
struct vsp1_lif * vsp1_lif_create ( struct vsp1_device * vsp1 , unsigned int index )
2013-06-04 11:22:30 -03:00
{
struct vsp1_lif * lif ;
int ret ;
lif = devm_kzalloc ( vsp1 - > dev , sizeof ( * lif ) , GFP_KERNEL ) ;
if ( lif = = NULL )
return ERR_PTR ( - ENOMEM ) ;
2015-11-17 13:10:26 -02:00
lif - > entity . ops = & lif_entity_ops ;
2013-06-04 11:22:30 -03:00
lif - > entity . type = VSP1_ENTITY_LIF ;
2017-06-21 16:10:18 +03:00
lif - > entity . index = index ;
2013-06-04 11:22:30 -03:00
2017-02-26 10:29:50 -03:00
/*
* The LIF is never exposed to userspace , but media entity registration
2016-02-15 22:10:26 -02:00
* requires a function to be set . Use PROC_VIDEO_PIXEL_FORMATTER just to
* avoid triggering a WARN_ON ( ) , the value won ' t be seen anywhere .
*/
ret = vsp1_entity_init ( vsp1 , & lif - > entity , " lif " , 2 , & lif_ops ,
MEDIA_ENT_F_PROC_VIDEO_PIXEL_FORMATTER ) ;
2013-06-04 11:22:30 -03:00
if ( ret < 0 )
return ERR_PTR ( ret ) ;
return lif ;
}