2018-04-23 00:33:20 +03:00
// SPDX-License-Identifier: GPL-2.0+
2013-06-04 18:22:30 +04:00
/*
* vsp1_wpf . c - - R - Car VSP1 Write Pixel Formatter
*
2014-02-06 21:42:31 +04:00
* Copyright ( C ) 2013 - 2014 Renesas Electronics Corporation
2013-06-04 18:22:30 +04:00
*
* Contact : Laurent Pinchart ( laurent . pinchart @ ideasonboard . com )
*/
# include <linux/device.h>
# include <media/v4l2-subdev.h>
# include "vsp1.h"
2015-11-15 03:27:52 +03:00
# include "vsp1_dl.h"
2016-01-18 00:53:56 +03:00
# include "vsp1_pipe.h"
2013-06-04 18:22:30 +04:00
# include "vsp1_rwpf.h"
# include "vsp1_video.h"
2016-03-25 12:51:06 +03:00
# define WPF_GEN2_MAX_WIDTH 2048U
# define WPF_GEN2_MAX_HEIGHT 2048U
# define WPF_GEN3_MAX_WIDTH 8190U
# define WPF_GEN3_MAX_HEIGHT 8190U
2013-06-04 18:22:30 +04:00
/* -----------------------------------------------------------------------------
* Device Access
*/
2015-11-23 01:29:25 +03:00
static inline void vsp1_wpf_write ( struct vsp1_rwpf * wpf ,
2018-05-18 23:42:02 +03:00
struct vsp1_dl_body * dlb , u32 reg , u32 data )
2013-06-04 18:22:30 +04:00
{
2018-05-18 23:42:02 +03:00
vsp1_dl_body_write ( dlb , reg + wpf - > entity . index * VI6_WPF_OFFSET , data ) ;
2013-06-04 18:22:30 +04:00
}
2016-05-26 11:14:22 +03:00
/* -----------------------------------------------------------------------------
* Controls
*/
enum wpf_flip_ctrl {
WPF_CTRL_VFLIP = 0 ,
WPF_CTRL_HFLIP = 1 ,
} ;
2016-06-20 12:07:08 +03:00
static int vsp1_wpf_set_rotation ( struct vsp1_rwpf * wpf , unsigned int rotation )
{
struct vsp1_video * video = wpf - > video ;
struct v4l2_mbus_framefmt * sink_format ;
struct v4l2_mbus_framefmt * source_format ;
bool rotate ;
int ret = 0 ;
/*
* Only consider the 0 ° / 180 ° from / to 90 ° / 270 ° modifications , the rest
* is taken care of by the flipping configuration .
*/
rotate = rotation = = 90 | | rotation = = 270 ;
if ( rotate = = wpf - > flip . rotate )
return 0 ;
/* Changing rotation isn't allowed when buffers are allocated. */
mutex_lock ( & video - > lock ) ;
if ( vb2_is_busy ( & video - > queue ) ) {
ret = - EBUSY ;
goto done ;
}
sink_format = vsp1_entity_get_pad_format ( & wpf - > entity ,
wpf - > entity . config ,
RWPF_PAD_SINK ) ;
source_format = vsp1_entity_get_pad_format ( & wpf - > entity ,
wpf - > entity . config ,
RWPF_PAD_SOURCE ) ;
mutex_lock ( & wpf - > entity . lock ) ;
if ( rotate ) {
source_format - > width = sink_format - > height ;
source_format - > height = sink_format - > width ;
} else {
source_format - > width = sink_format - > width ;
source_format - > height = sink_format - > height ;
}
wpf - > flip . rotate = rotate ;
mutex_unlock ( & wpf - > entity . lock ) ;
done :
mutex_unlock ( & video - > lock ) ;
return ret ;
}
2016-05-26 11:14:22 +03:00
static int vsp1_wpf_s_ctrl ( struct v4l2_ctrl * ctrl )
{
struct vsp1_rwpf * wpf =
container_of ( ctrl - > handler , struct vsp1_rwpf , ctrls ) ;
2016-06-20 12:07:08 +03:00
unsigned int rotation ;
2016-05-26 11:14:22 +03:00
u32 flip = 0 ;
2016-06-20 12:07:08 +03:00
int ret ;
2016-05-26 11:14:22 +03:00
2016-06-20 12:07:08 +03:00
/* Update the rotation. */
rotation = wpf - > flip . ctrls . rotate ? wpf - > flip . ctrls . rotate - > val : 0 ;
ret = vsp1_wpf_set_rotation ( wpf , rotation ) ;
if ( ret < 0 )
return ret ;
/*
* Compute the flip value resulting from all three controls , with
* rotation by 180 ° flipping the image in both directions . Store the
* result in the pending flip field for the next frame that will be
* processed .
*/
if ( wpf - > flip . ctrls . vflip - > val )
flip | = BIT ( WPF_CTRL_VFLIP ) ;
2016-05-26 11:14:22 +03:00
2016-06-20 12:07:08 +03:00
if ( wpf - > flip . ctrls . hflip & & wpf - > flip . ctrls . hflip - > val )
flip | = BIT ( WPF_CTRL_HFLIP ) ;
2016-05-26 11:14:22 +03:00
2016-06-20 12:07:08 +03:00
if ( rotation = = 180 | | rotation = = 270 )
flip ^ = BIT ( WPF_CTRL_VFLIP ) | BIT ( WPF_CTRL_HFLIP ) ;
spin_lock_irq ( & wpf - > flip . lock ) ;
wpf - > flip . pending = flip ;
spin_unlock_irq ( & wpf - > flip . lock ) ;
2016-05-26 11:14:22 +03:00
return 0 ;
}
static const struct v4l2_ctrl_ops vsp1_wpf_ctrl_ops = {
. s_ctrl = vsp1_wpf_s_ctrl ,
} ;
static int wpf_init_controls ( struct vsp1_rwpf * wpf )
{
struct vsp1_device * vsp1 = wpf - > entity . vsp1 ;
unsigned int num_flip_ctrls ;
spin_lock_init ( & wpf - > flip . lock ) ;
if ( wpf - > entity . index ! = 0 ) {
/* Only WPF0 supports flipping. */
num_flip_ctrls = 0 ;
} else if ( vsp1 - > info - > features & VSP1_HAS_WPF_HFLIP ) {
2017-02-26 16:29:50 +03:00
/*
2016-06-20 12:07:08 +03:00
* When horizontal flip is supported the WPF implements three
* controls ( horizontal flip , vertical flip and rotation ) .
2016-05-26 11:14:22 +03:00
*/
2016-06-20 12:07:08 +03:00
num_flip_ctrls = 3 ;
2016-05-26 11:14:22 +03:00
} else if ( vsp1 - > info - > features & VSP1_HAS_WPF_VFLIP ) {
2017-02-26 16:29:50 +03:00
/*
* When only vertical flip is supported the WPF implements a
2016-05-26 11:14:22 +03:00
* single control ( vertical flip ) .
*/
num_flip_ctrls = 1 ;
} else {
/* Otherwise flipping is not supported. */
num_flip_ctrls = 0 ;
}
vsp1_rwpf_init_ctrls ( wpf , num_flip_ctrls ) ;
if ( num_flip_ctrls > = 1 ) {
2016-06-20 12:07:08 +03:00
wpf - > flip . ctrls . vflip =
2016-05-26 11:14:22 +03:00
v4l2_ctrl_new_std ( & wpf - > ctrls , & vsp1_wpf_ctrl_ops ,
V4L2_CID_VFLIP , 0 , 1 , 1 , 0 ) ;
}
2016-06-20 12:07:08 +03:00
if ( num_flip_ctrls = = 3 ) {
wpf - > flip . ctrls . hflip =
2016-05-26 11:14:22 +03:00
v4l2_ctrl_new_std ( & wpf - > ctrls , & vsp1_wpf_ctrl_ops ,
V4L2_CID_HFLIP , 0 , 1 , 1 , 0 ) ;
2016-06-20 12:07:08 +03:00
wpf - > flip . ctrls . rotate =
v4l2_ctrl_new_std ( & wpf - > ctrls , & vsp1_wpf_ctrl_ops ,
V4L2_CID_ROTATE , 0 , 270 , 90 , 0 ) ;
v4l2_ctrl_cluster ( 3 , & wpf - > flip . ctrls . vflip ) ;
2016-05-26 11:14:22 +03:00
}
if ( wpf - > ctrls . error ) {
dev_err ( vsp1 - > dev , " wpf%u: failed to initialize controls \n " ,
wpf - > entity . index ) ;
return wpf - > ctrls . error ;
}
return 0 ;
}
2013-06-04 18:22:30 +04:00
/* -----------------------------------------------------------------------------
* V4L2 Subdevice Core Operations
*/
static int wpf_s_stream ( struct v4l2_subdev * subdev , int enable )
{
struct vsp1_rwpf * wpf = to_rwpf ( subdev ) ;
struct vsp1_device * vsp1 = wpf - > entity . vsp1 ;
2014-05-22 02:00:05 +04:00
2015-11-17 18:10:26 +03:00
if ( enable )
2013-06-04 18:22:30 +04:00
return 0 ;
2017-02-26 16:29:50 +03:00
/*
* Write to registers directly when stopping the stream as there will be
2015-11-17 18:10:26 +03:00
* no pipeline run to apply the display list .
2013-07-11 01:03:46 +04:00
*/
2015-11-17 18:10:26 +03:00
vsp1_write ( vsp1 , VI6_WPF_IRQ_ENB ( wpf - > entity . index ) , 0 ) ;
vsp1_write ( vsp1 , wpf - > entity . index * VI6_WPF_OFFSET +
VI6_WPF_SRCRPF , 0 ) ;
2013-06-04 18:22:30 +04:00
2015-11-17 18:10:26 +03:00
return 0 ;
}
2015-08-05 22:40:31 +03:00
2015-11-17 18:10:26 +03:00
/* -----------------------------------------------------------------------------
* V4L2 Subdevice Operations
*/
2013-06-04 18:22:30 +04:00
2016-06-18 03:11:26 +03:00
static const struct v4l2_subdev_video_ops wpf_video_ops = {
2015-11-17 18:10:26 +03:00
. s_stream = wpf_s_stream ,
} ;
2013-07-11 01:03:46 +04:00
2016-06-18 03:11:26 +03:00
static const struct v4l2_subdev_ops wpf_ops = {
2015-11-17 18:10:26 +03:00
. video = & wpf_video_ops ,
2015-11-22 18:37:45 +03:00
. pad = & vsp1_rwpf_pad_ops ,
2015-11-17 18:10:26 +03:00
} ;
2013-06-04 18:22:30 +04:00
2015-11-17 18:10:26 +03:00
/* -----------------------------------------------------------------------------
* VSP1 Entity Operations
*/
static void vsp1_wpf_destroy ( struct vsp1_entity * entity )
{
struct vsp1_rwpf * wpf = entity_to_rwpf ( entity ) ;
vsp1_dlm_destroy ( wpf - > dlm ) ;
}
2018-05-18 23:42:01 +03:00
static void wpf_configure_stream ( struct vsp1_entity * entity ,
struct vsp1_pipeline * pipe ,
2018-05-18 23:42:02 +03:00
struct vsp1_dl_body * dlb )
2015-11-17 18:10:26 +03:00
{
struct vsp1_rwpf * wpf = to_rwpf ( & entity - > subdev ) ;
struct vsp1_device * vsp1 = wpf - > entity . vsp1 ;
const struct v4l2_mbus_framefmt * source_format ;
const struct v4l2_mbus_framefmt * sink_format ;
unsigned int i ;
u32 outfmt = 0 ;
u32 srcrpf = 0 ;
2013-06-04 18:22:30 +04:00
2015-11-16 00:14:22 +03:00
sink_format = vsp1_entity_get_pad_format ( & wpf - > entity ,
wpf - > entity . config ,
RWPF_PAD_SINK ) ;
source_format = vsp1_entity_get_pad_format ( & wpf - > entity ,
wpf - > entity . config ,
RWPF_PAD_SOURCE ) ;
2016-09-12 15:50:13 +03:00
/* Format */
2013-06-04 18:22:30 +04:00
if ( ! pipe - > lif ) {
2015-11-17 18:10:26 +03:00
const struct v4l2_pix_format_mplane * format = & wpf - > format ;
2015-07-28 20:00:43 +03:00
const struct vsp1_format_info * fmtinfo = wpf - > fmtinfo ;
2013-06-04 18:22:30 +04:00
outfmt = fmtinfo - > hwfmt < < VI6_WPF_OUTFMT_WRFMT_SHIFT ;
2016-06-20 12:07:08 +03:00
if ( wpf - > flip . rotate )
outfmt | = VI6_WPF_OUTFMT_ROT ;
2014-05-27 03:12:53 +04:00
if ( fmtinfo - > alpha )
outfmt | = VI6_WPF_OUTFMT_PXA ;
2013-06-04 18:22:30 +04:00
if ( fmtinfo - > swap_yc )
outfmt | = VI6_WPF_OUTFMT_SPYCS ;
if ( fmtinfo - > swap_uv )
outfmt | = VI6_WPF_OUTFMT_SPUVS ;
2015-11-17 18:10:26 +03:00
/* Destination stride and byte swapping. */
2018-05-18 23:42:02 +03:00
vsp1_wpf_write ( wpf , dlb , VI6_WPF_DSTM_STRIDE_Y ,
2015-11-17 18:10:26 +03:00
format - > plane_fmt [ 0 ] . bytesperline ) ;
if ( format - > num_planes > 1 )
2018-05-18 23:42:02 +03:00
vsp1_wpf_write ( wpf , dlb , VI6_WPF_DSTM_STRIDE_C ,
2015-11-17 18:10:26 +03:00
format - > plane_fmt [ 1 ] . bytesperline ) ;
2018-05-18 23:42:02 +03:00
vsp1_wpf_write ( wpf , dlb , VI6_WPF_DSWAP , fmtinfo - > swap ) ;
2016-05-26 11:14:22 +03:00
if ( vsp1 - > info - > features & VSP1_HAS_WPF_HFLIP & &
wpf - > entity . index = = 0 )
2018-05-18 23:42:02 +03:00
vsp1_wpf_write ( wpf , dlb , VI6_WPF_ROT_CTRL ,
2016-05-26 11:14:22 +03:00
VI6_WPF_ROT_CTRL_LN16 |
( 256 < < VI6_WPF_ROT_CTRL_LMEM_WD_SHIFT ) ) ;
2013-06-04 18:22:30 +04:00
}
2015-11-16 00:14:22 +03:00
if ( sink_format - > code ! = source_format - > code )
2013-06-04 18:22:30 +04:00
outfmt | = VI6_WPF_OUTFMT_CSC ;
2016-06-20 11:04:38 +03:00
wpf - > outfmt = outfmt ;
2013-06-04 18:22:30 +04:00
2018-05-18 23:42:02 +03:00
vsp1_dl_body_write ( dlb , VI6_DPR_WPF_FPORCH ( wpf - > entity . index ) ,
2015-11-23 01:29:25 +03:00
VI6_DPR_WPF_FPORCH_FP_WPFN ) ;
2013-06-04 18:22:30 +04:00
2018-05-18 23:42:02 +03:00
vsp1_dl_body_write ( dlb , VI6_WPF_WRBCK_CTRL , 0 ) ;
2013-06-04 18:22:30 +04:00
2017-02-26 16:29:50 +03:00
/*
2018-02-26 19:06:21 +03:00
* Sources . If the pipeline has a single input and BRx is not used ,
2015-11-17 18:10:26 +03:00
* configure it as the master layer . Otherwise configure all
* inputs as sub - layers and select the virtual RPF as the master
* layer .
*/
for ( i = 0 ; i < vsp1 - > info - > rpf_count ; + + i ) {
struct vsp1_rwpf * input = pipe - > inputs [ i ] ;
2013-06-04 18:22:30 +04:00
2015-11-17 18:10:26 +03:00
if ( ! input )
continue ;
2013-06-04 18:22:30 +04:00
2018-02-26 19:06:21 +03:00
srcrpf | = ( ! pipe - > brx & & pipe - > num_inputs = = 1 )
2015-11-17 18:10:26 +03:00
? VI6_WPF_SRCRPF_RPF_ACT_MST ( input - > entity . index )
: VI6_WPF_SRCRPF_RPF_ACT_SUB ( input - > entity . index ) ;
}
2015-11-17 17:23:23 +03:00
2018-02-26 19:06:21 +03:00
if ( pipe - > brx )
srcrpf | = pipe - > brx - > type = = VSP1_ENTITY_BRU
2017-05-25 00:16:57 +03:00
? VI6_WPF_SRCRPF_VIRACT_MST
: VI6_WPF_SRCRPF_VIRACT2_MST ;
2015-11-17 17:23:23 +03:00
2018-05-18 23:42:02 +03:00
vsp1_wpf_write ( wpf , dlb , VI6_WPF_SRCRPF , srcrpf ) ;
2015-11-17 17:23:23 +03:00
2015-11-17 18:10:26 +03:00
/* Enable interrupts */
2018-05-18 23:42:02 +03:00
vsp1_dl_body_write ( dlb , VI6_WPF_IRQ_STA ( wpf - > entity . index ) , 0 ) ;
vsp1_dl_body_write ( dlb , VI6_WPF_IRQ_ENB ( wpf - > entity . index ) ,
2016-09-06 12:55:02 +03:00
VI6_WFP_IRQ_ENB_DFEE ) ;
2013-06-04 18:22:30 +04:00
}
2018-05-18 23:42:01 +03:00
static void wpf_configure_frame ( struct vsp1_entity * entity ,
struct vsp1_pipeline * pipe ,
2018-05-18 23:42:02 +03:00
struct vsp1_dl_list * dl ,
struct vsp1_dl_body * dlb )
2018-05-18 23:42:01 +03:00
{
const unsigned int mask = BIT ( WPF_CTRL_VFLIP )
| BIT ( WPF_CTRL_HFLIP ) ;
struct vsp1_rwpf * wpf = to_rwpf ( & entity - > subdev ) ;
unsigned long flags ;
u32 outfmt ;
spin_lock_irqsave ( & wpf - > flip . lock , flags ) ;
wpf - > flip . active = ( wpf - > flip . active & ~ mask )
| ( wpf - > flip . pending & mask ) ;
spin_unlock_irqrestore ( & wpf - > flip . lock , flags ) ;
outfmt = ( wpf - > alpha < < VI6_WPF_OUTFMT_PDV_SHIFT ) | wpf - > outfmt ;
if ( wpf - > flip . active & BIT ( WPF_CTRL_VFLIP ) )
outfmt | = VI6_WPF_OUTFMT_FLP ;
if ( wpf - > flip . active & BIT ( WPF_CTRL_HFLIP ) )
outfmt | = VI6_WPF_OUTFMT_HFLP ;
2018-05-18 23:42:02 +03:00
vsp1_wpf_write ( wpf , dlb , VI6_WPF_OUTFMT , outfmt ) ;
2018-05-18 23:42:01 +03:00
}
static void wpf_configure_partition ( struct vsp1_entity * entity ,
struct vsp1_pipeline * pipe ,
2018-05-18 23:42:02 +03:00
struct vsp1_dl_list * dl ,
struct vsp1_dl_body * dlb )
2018-05-18 23:42:01 +03:00
{
struct vsp1_rwpf * wpf = to_rwpf ( & entity - > subdev ) ;
struct vsp1_device * vsp1 = wpf - > entity . vsp1 ;
struct vsp1_rwpf_memory mem = wpf - > mem ;
const struct v4l2_mbus_framefmt * sink_format ;
const struct v4l2_pix_format_mplane * format = & wpf - > format ;
const struct vsp1_format_info * fmtinfo = wpf - > fmtinfo ;
unsigned int width ;
unsigned int height ;
unsigned int offset ;
unsigned int flip ;
unsigned int i ;
sink_format = vsp1_entity_get_pad_format ( & wpf - > entity ,
wpf - > entity . config ,
RWPF_PAD_SINK ) ;
width = sink_format - > width ;
height = sink_format - > height ;
/*
* Cropping . The partition algorithm can split the image into
* multiple slices .
*/
if ( pipe - > partitions > 1 )
width = pipe - > partition - > wpf . width ;
2018-05-18 23:42:02 +03:00
vsp1_wpf_write ( wpf , dlb , VI6_WPF_HSZCLIP , VI6_WPF_SZCLIP_EN |
2018-05-18 23:42:01 +03:00
( 0 < < VI6_WPF_SZCLIP_OFST_SHIFT ) |
( width < < VI6_WPF_SZCLIP_SIZE_SHIFT ) ) ;
2018-05-18 23:42:02 +03:00
vsp1_wpf_write ( wpf , dlb , VI6_WPF_VSZCLIP , VI6_WPF_SZCLIP_EN |
2018-05-18 23:42:01 +03:00
( 0 < < VI6_WPF_SZCLIP_OFST_SHIFT ) |
( height < < VI6_WPF_SZCLIP_SIZE_SHIFT ) ) ;
if ( pipe - > lif )
return ;
/*
* Update the memory offsets based on flipping configuration .
* The destination addresses point to the locations where the
* VSP starts writing to memory , which can be any corner of the
* image depending on the combination of flipping and rotation .
*/
/*
* First take the partition left coordinate into account .
* Compute the offset to order the partitions correctly on the
* output based on whether flipping is enabled . Consider
* horizontal flipping when rotation is disabled but vertical
* flipping when rotation is enabled , as rotating the image
* switches the horizontal and vertical directions . The offset
* is applied horizontally or vertically accordingly .
*/
flip = wpf - > flip . active ;
if ( flip & BIT ( WPF_CTRL_HFLIP ) & & ! wpf - > flip . rotate )
offset = format - > width - pipe - > partition - > wpf . left
- pipe - > partition - > wpf . width ;
else if ( flip & BIT ( WPF_CTRL_VFLIP ) & & wpf - > flip . rotate )
offset = format - > height - pipe - > partition - > wpf . left
- pipe - > partition - > wpf . width ;
else
offset = pipe - > partition - > wpf . left ;
for ( i = 0 ; i < format - > num_planes ; + + i ) {
unsigned int hsub = i > 0 ? fmtinfo - > hsub : 1 ;
unsigned int vsub = i > 0 ? fmtinfo - > vsub : 1 ;
if ( wpf - > flip . rotate )
mem . addr [ i ] + = offset / vsub
* format - > plane_fmt [ i ] . bytesperline ;
else
mem . addr [ i ] + = offset / hsub
* fmtinfo - > bpp [ i ] / 8 ;
}
if ( flip & BIT ( WPF_CTRL_VFLIP ) ) {
/*
* When rotating the output ( after rotation ) image
* height is equal to the partition width ( before
* rotation ) . Otherwise it is equal to the output
* image height .
*/
if ( wpf - > flip . rotate )
height = pipe - > partition - > wpf . width ;
else
height = format - > height ;
mem . addr [ 0 ] + = ( height - 1 )
* format - > plane_fmt [ 0 ] . bytesperline ;
if ( format - > num_planes > 1 ) {
offset = ( height / fmtinfo - > vsub - 1 )
* format - > plane_fmt [ 1 ] . bytesperline ;
mem . addr [ 1 ] + = offset ;
mem . addr [ 2 ] + = offset ;
}
}
if ( wpf - > flip . rotate & & ! ( flip & BIT ( WPF_CTRL_HFLIP ) ) ) {
unsigned int hoffset = max ( 0 , ( int ) format - > width - 16 ) ;
/*
* Compute the output coordinate . The partition
* horizontal ( left ) offset becomes a vertical offset .
*/
for ( i = 0 ; i < format - > num_planes ; + + i ) {
unsigned int hsub = i > 0 ? fmtinfo - > hsub : 1 ;
mem . addr [ i ] + = hoffset / hsub
* fmtinfo - > bpp [ i ] / 8 ;
}
}
/*
* On Gen3 hardware the SPUVS bit has no effect on 3 - planar
* formats . Swap the U and V planes manually in that case .
*/
if ( vsp1 - > info - > gen = = 3 & & format - > num_planes = = 3 & &
fmtinfo - > swap_uv )
swap ( mem . addr [ 1 ] , mem . addr [ 2 ] ) ;
2018-05-18 23:42:02 +03:00
vsp1_wpf_write ( wpf , dlb , VI6_WPF_DSTM_ADDR_Y , mem . addr [ 0 ] ) ;
vsp1_wpf_write ( wpf , dlb , VI6_WPF_DSTM_ADDR_C0 , mem . addr [ 1 ] ) ;
vsp1_wpf_write ( wpf , dlb , VI6_WPF_DSTM_ADDR_C1 , mem . addr [ 2 ] ) ;
2018-05-18 23:42:01 +03:00
}
2016-06-20 12:07:08 +03:00
static unsigned int wpf_max_width ( struct vsp1_entity * entity ,
struct vsp1_pipeline * pipe )
{
struct vsp1_rwpf * wpf = to_rwpf ( & entity - > subdev ) ;
return wpf - > flip . rotate ? 256 : wpf - > max_width ;
}
2017-08-04 19:32:44 +03:00
static void wpf_partition ( struct vsp1_entity * entity ,
struct vsp1_pipeline * pipe ,
struct vsp1_partition * partition ,
unsigned int partition_idx ,
struct vsp1_partition_window * window )
{
partition - > wpf = * window ;
}
2015-11-17 17:23:23 +03:00
static const struct vsp1_entity_operations wpf_entity_ops = {
. destroy = vsp1_wpf_destroy ,
2018-05-18 23:42:01 +03:00
. configure_stream = wpf_configure_stream ,
. configure_frame = wpf_configure_frame ,
. configure_partition = wpf_configure_partition ,
2016-06-20 12:07:08 +03:00
. max_width = wpf_max_width ,
2017-08-04 19:32:44 +03:00
. partition = wpf_partition ,
2013-06-04 18:22:30 +04:00
} ;
/* -----------------------------------------------------------------------------
* Initialization and Cleanup
*/
struct vsp1_rwpf * vsp1_wpf_create ( struct vsp1_device * vsp1 , unsigned int index )
{
struct vsp1_rwpf * wpf ;
2015-11-16 00:42:01 +03:00
char name [ 6 ] ;
2013-06-04 18:22:30 +04:00
int ret ;
wpf = devm_kzalloc ( vsp1 - > dev , sizeof ( * wpf ) , GFP_KERNEL ) ;
if ( wpf = = NULL )
return ERR_PTR ( - ENOMEM ) ;
2016-03-25 12:51:06 +03:00
if ( vsp1 - > info - > gen = = 2 ) {
wpf - > max_width = WPF_GEN2_MAX_WIDTH ;
wpf - > max_height = WPF_GEN2_MAX_HEIGHT ;
} else {
wpf - > max_width = WPF_GEN3_MAX_WIDTH ;
wpf - > max_height = WPF_GEN3_MAX_HEIGHT ;
}
2013-06-04 18:22:30 +04:00
2015-11-17 17:23:23 +03:00
wpf - > entity . ops = & wpf_entity_ops ;
2013-06-04 18:22:30 +04:00
wpf - > entity . type = VSP1_ENTITY_WPF ;
wpf - > entity . index = index ;
2015-11-16 00:42:01 +03:00
sprintf ( name , " wpf.%u " , index ) ;
2016-02-16 03:10:26 +03:00
ret = vsp1_entity_init ( vsp1 , & wpf - > entity , name , 2 , & wpf_ops ,
MEDIA_ENT_F_PROC_VIDEO_PIXEL_FORMATTER ) ;
2013-06-04 18:22:30 +04:00
if ( ret < 0 )
return ERR_PTR ( ret ) ;
2015-11-01 20:18:56 +03:00
/* Initialize the display list manager. */
2016-07-12 19:49:46 +03:00
wpf - > dlm = vsp1_dlm_create ( vsp1 , index , 64 ) ;
2015-11-01 20:18:56 +03:00
if ( ! wpf - > dlm ) {
ret = - ENOMEM ;
goto error ;
2015-11-15 03:27:52 +03:00
}
2014-05-22 02:00:05 +04:00
/* Initialize the control handler. */
2016-05-26 11:14:22 +03:00
ret = wpf_init_controls ( wpf ) ;
2015-11-01 17:19:42 +03:00
if ( ret < 0 ) {
2014-05-22 02:00:05 +04:00
dev_err ( vsp1 - > dev , " wpf%u: failed to initialize controls \n " ,
index ) ;
goto error ;
}
2016-06-20 11:04:38 +03:00
v4l2_ctrl_handler_setup ( & wpf - > ctrls ) ;
2013-06-04 18:22:30 +04:00
return wpf ;
2014-05-28 19:49:13 +04:00
error :
vsp1_entity_destroy ( & wpf - > entity ) ;
2013-06-04 18:22:30 +04:00
return ERR_PTR ( ret ) ;
}