2018-04-23 00:33:20 +03:00
// SPDX-License-Identifier: GPL-2.0+
2013-07-10 19:03:30 +04:00
/*
* vsp1_lut . c - - R - Car VSP1 Look - Up Table
*
* Copyright ( C ) 2013 Renesas Corporation
*
* 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-23 01:29:25 +03:00
# include "vsp1_dl.h"
2013-07-10 19:03:30 +04:00
# include "vsp1_lut.h"
# define LUT_MIN_SIZE 4U
# define LUT_MAX_SIZE 8190U
/* -----------------------------------------------------------------------------
* Device Access
*/
2015-11-23 01:29:25 +03:00
static inline void vsp1_lut_write ( struct vsp1_lut * lut , struct vsp1_dl_list * dl ,
u32 reg , u32 data )
2013-07-10 19:03:30 +04:00
{
2015-11-23 01:29:25 +03:00
vsp1_dl_list_write ( dl , reg , data ) ;
2013-07-10 19:03:30 +04:00
}
/* -----------------------------------------------------------------------------
2016-05-13 19:52:11 +03:00
* Controls
2013-07-10 19:03:30 +04:00
*/
2016-05-13 19:52:11 +03:00
# define V4L2_CID_VSP1_LUT_TABLE (V4L2_CID_USER_BASE | 0x1001)
static int lut_set_table ( struct vsp1_lut * lut , struct v4l2_ctrl * ctrl )
2013-07-10 19:03:30 +04:00
{
2016-03-03 20:17:11 +03:00
struct vsp1_dl_body * dlb ;
unsigned int i ;
2018-05-18 23:41:56 +03:00
dlb = vsp1_dl_body_alloc ( lut - > entity . vsp1 , 256 ) ;
2016-03-03 20:17:11 +03:00
if ( ! dlb )
return - ENOMEM ;
2016-05-13 19:52:11 +03:00
for ( i = 0 ; i < 256 ; + + i )
2018-05-18 23:41:56 +03:00
vsp1_dl_body_write ( dlb , VI6_LUT_TABLE + 4 * i ,
2016-05-13 19:52:11 +03:00
ctrl - > p_new . p_u32 [ i ] ) ;
2016-03-03 20:17:11 +03:00
2016-06-11 10:11:27 +03:00
spin_lock_irq ( & lut - > lock ) ;
2016-03-03 20:17:11 +03:00
swap ( lut - > lut , dlb ) ;
2016-06-11 10:11:27 +03:00
spin_unlock_irq ( & lut - > lock ) ;
2016-03-03 20:17:11 +03:00
2018-05-18 23:41:56 +03:00
vsp1_dl_body_free ( dlb ) ;
2016-03-03 20:17:11 +03:00
return 0 ;
2013-07-10 19:03:30 +04:00
}
2016-05-13 19:52:11 +03:00
static int lut_s_ctrl ( struct v4l2_ctrl * ctrl )
2013-07-10 19:03:30 +04:00
{
2016-05-13 19:52:11 +03:00
struct vsp1_lut * lut =
container_of ( ctrl - > handler , struct vsp1_lut , ctrls ) ;
2013-07-10 19:03:30 +04:00
2016-05-13 19:52:11 +03:00
switch ( ctrl - > id ) {
case V4L2_CID_VSP1_LUT_TABLE :
lut_set_table ( lut , ctrl ) ;
break ;
2013-07-10 19:03:30 +04:00
}
2016-05-13 19:52:11 +03:00
return 0 ;
2013-07-10 19:03:30 +04:00
}
2016-05-13 19:52:11 +03:00
static const struct v4l2_ctrl_ops lut_ctrl_ops = {
. s_ctrl = lut_s_ctrl ,
} ;
static const struct v4l2_ctrl_config lut_table_control = {
. ops = & lut_ctrl_ops ,
. id = V4L2_CID_VSP1_LUT_TABLE ,
. name = " Look-Up Table " ,
. type = V4L2_CTRL_TYPE_U32 ,
. min = 0x00000000 ,
. max = 0x00ffffff ,
. step = 1 ,
. def = 0 ,
. dims = { 256 } ,
} ;
2013-07-10 19:03:30 +04:00
/* -----------------------------------------------------------------------------
* V4L2 Subdevice Pad Operations
*/
2017-11-27 22:59:45 +03:00
static const unsigned int lut_codes [ ] = {
MEDIA_BUS_FMT_ARGB8888_1X32 ,
MEDIA_BUS_FMT_AHSV8888_1X32 ,
MEDIA_BUS_FMT_AYUV8_1X32 ,
} ;
2013-07-10 19:03:30 +04:00
static int lut_enum_mbus_code ( struct v4l2_subdev * subdev ,
2015-03-04 12:47:54 +03:00
struct v4l2_subdev_pad_config * cfg ,
2013-07-10 19:03:30 +04:00
struct v4l2_subdev_mbus_code_enum * code )
{
2017-11-27 22:59:45 +03:00
return vsp1_subdev_enum_mbus_code ( subdev , cfg , code , lut_codes ,
ARRAY_SIZE ( lut_codes ) ) ;
2013-07-10 19:03:30 +04:00
}
static int lut_enum_frame_size ( struct v4l2_subdev * subdev ,
2015-03-04 12:47:54 +03:00
struct v4l2_subdev_pad_config * cfg ,
2013-07-10 19:03:30 +04:00
struct v4l2_subdev_frame_size_enum * fse )
{
2016-02-25 02:25:42 +03:00
return vsp1_subdev_enum_frame_size ( subdev , cfg , fse , LUT_MIN_SIZE ,
LUT_MIN_SIZE , LUT_MAX_SIZE ,
LUT_MAX_SIZE ) ;
2013-07-10 19:03:30 +04:00
}
2015-11-01 20:18:32 +03:00
static int lut_set_format ( struct v4l2_subdev * subdev ,
struct v4l2_subdev_pad_config * cfg ,
2013-07-10 19:03:30 +04:00
struct v4l2_subdev_format * fmt )
{
2017-11-27 22:59:45 +03:00
return vsp1_subdev_set_pad_format ( subdev , cfg , fmt , lut_codes ,
ARRAY_SIZE ( lut_codes ) ,
LUT_MIN_SIZE , LUT_MIN_SIZE ,
LUT_MAX_SIZE , LUT_MAX_SIZE ) ;
2013-07-10 19:03:30 +04:00
}
/* -----------------------------------------------------------------------------
* V4L2 Subdevice Operations
*/
2016-06-18 03:11:26 +03:00
static const struct v4l2_subdev_pad_ops lut_pad_ops = {
2015-11-16 01:09:08 +03:00
. init_cfg = vsp1_entity_init_cfg ,
2013-07-10 19:03:30 +04:00
. enum_mbus_code = lut_enum_mbus_code ,
. enum_frame_size = lut_enum_frame_size ,
2016-02-25 03:10:13 +03:00
. get_fmt = vsp1_subdev_get_pad_format ,
2013-07-10 19:03:30 +04:00
. set_fmt = lut_set_format ,
} ;
2016-06-18 03:11:26 +03:00
static const struct v4l2_subdev_ops lut_ops = {
2013-07-10 19:03:30 +04:00
. pad = & lut_pad_ops ,
} ;
2015-11-17 18:10:26 +03:00
/* -----------------------------------------------------------------------------
* VSP1 Entity Operations
*/
2016-01-14 19:17:32 +03:00
static void lut_configure ( struct vsp1_entity * entity ,
struct vsp1_pipeline * pipe ,
2016-09-12 01:39:30 +03:00
struct vsp1_dl_list * dl ,
enum vsp1_entity_params params )
2015-11-17 18:10:26 +03:00
{
struct vsp1_lut * lut = to_lut ( & entity - > subdev ) ;
2016-06-11 10:11:27 +03:00
struct vsp1_dl_body * dlb ;
unsigned long flags ;
2015-11-17 18:10:26 +03:00
2016-09-12 01:39:30 +03:00
switch ( params ) {
case VSP1_ENTITY_PARAMS_INIT :
2016-06-11 10:11:27 +03:00
vsp1_lut_write ( lut , dl , VI6_LUT_CTRL , VI6_LUT_CTRL_EN ) ;
2016-09-12 01:39:30 +03:00
break ;
2016-05-13 19:52:11 +03:00
2016-09-12 15:50:13 +03:00
case VSP1_ENTITY_PARAMS_PARTITION :
break ;
2016-09-12 01:39:30 +03:00
case VSP1_ENTITY_PARAMS_RUNTIME :
spin_lock_irqsave ( & lut - > lock , flags ) ;
dlb = lut - > lut ;
lut - > lut = NULL ;
spin_unlock_irqrestore ( & lut - > lock , flags ) ;
2016-06-11 10:11:27 +03:00
2016-09-12 01:39:30 +03:00
if ( dlb )
2018-05-18 23:41:56 +03:00
vsp1_dl_list_add_body ( dl , dlb ) ;
2016-09-12 01:39:30 +03:00
break ;
}
2015-11-17 18:10:26 +03:00
}
static const struct vsp1_entity_operations lut_entity_ops = {
. configure = lut_configure ,
} ;
2013-07-10 19:03:30 +04:00
/* -----------------------------------------------------------------------------
* Initialization and Cleanup
*/
struct vsp1_lut * vsp1_lut_create ( struct vsp1_device * vsp1 )
{
struct vsp1_lut * lut ;
int ret ;
lut = devm_kzalloc ( vsp1 - > dev , sizeof ( * lut ) , GFP_KERNEL ) ;
if ( lut = = NULL )
return ERR_PTR ( - ENOMEM ) ;
2016-06-11 10:11:27 +03:00
spin_lock_init ( & lut - > lock ) ;
2015-11-17 18:10:26 +03:00
lut - > entity . ops = & lut_entity_ops ;
2013-07-10 19:03:30 +04:00
lut - > entity . type = VSP1_ENTITY_LUT ;
2016-02-16 03:10:26 +03:00
ret = vsp1_entity_init ( vsp1 , & lut - > entity , " lut " , 2 , & lut_ops ,
MEDIA_ENT_F_PROC_VIDEO_LUT ) ;
2013-07-10 19:03:30 +04:00
if ( ret < 0 )
return ERR_PTR ( ret ) ;
2016-05-13 19:52:11 +03:00
/* Initialize the control handler. */
v4l2_ctrl_handler_init ( & lut - > ctrls , 1 ) ;
v4l2_ctrl_new_custom ( & lut - > ctrls , & lut_table_control , NULL ) ;
lut - > entity . subdev . ctrl_handler = & lut - > ctrls ;
if ( lut - > ctrls . error ) {
dev_err ( vsp1 - > dev , " lut: failed to initialize controls \n " ) ;
ret = lut - > ctrls . error ;
vsp1_entity_destroy ( & lut - > entity ) ;
return ERR_PTR ( ret ) ;
}
v4l2_ctrl_handler_setup ( & lut - > ctrls ) ;
2013-07-10 19:03:30 +04:00
return lut ;
}