@ -151,26 +151,48 @@ static int fimc_pipeline_s_power(struct fimc_pipeline *p, bool state)
* __fimc_pipeline_open - update the pipeline information , enable power
* of all pipeline subdevs and the sensor clock
* @ me : media entity to start graph walk with
* @ prep : true to acquire sensor ( and csis ) subdevs
* @ prepare : true to walk the current pipeline and acquire all subdevs
*
* Called with the graph mutex held .
*/
static int __fimc_pipeline_open ( struct fimc_pipeline * p ,
struct media_entity * me , bool prep )
struct media_entity * me , bool prepare )
{
struct fimc_md * fmd = entity_to_fimc_mdev ( me ) ;
struct v4l2_subdev * sd ;
int ret ;
if ( prep )
if ( WARN_ON ( p = = NULL | | me = = NULL ) )
return - EINVAL ;
if ( prepare )
fimc_pipeline_prepare ( p , me ) ;
if ( p - > subdevs [ IDX_SENSOR ] = = NULL )
sd = p - > subdevs [ IDX_SENSOR ] ;
if ( sd = = NULL )
return - EINVAL ;
ret = fimc_md_set_camclk ( p - > subdevs [ IDX_SENSOR ] , true ) ;
if ( ret )
return ret ;
/* Disable PXLASYNC clock if this pipeline includes FIMC-IS */
if ( ! IS_ERR ( fmd - > wbclk [ CLK_IDX_WB_B ] ) & & p - > subdevs [ IDX_IS_ISP ] ) {
ret = clk_prepare_enable ( fmd - > wbclk [ CLK_IDX_WB_B ] ) ;
if ( ret < 0 )
return ret ;
}
ret = fimc_md_set_camclk ( sd , true ) ;
if ( ret < 0 )
goto err_wbclk ;
ret = fimc_pipeline_s_power ( p , 1 ) ;
if ( ! ret )
return 0 ;
fimc_md_set_camclk ( sd , false ) ;
return fimc_pipeline_s_power ( p , 1 ) ;
err_wbclk :
if ( ! IS_ERR ( fmd - > wbclk [ CLK_IDX_WB_B ] ) & & p - > subdevs [ IDX_IS_ISP ] )
clk_disable_unprepare ( fmd - > wbclk [ CLK_IDX_WB_B ] ) ;
return ret ;
}
/**
@ -181,15 +203,24 @@ static int __fimc_pipeline_open(struct fimc_pipeline *p,
*/
static int __fimc_pipeline_close ( struct fimc_pipeline * p )
{
struct v4l2_subdev * sd = p ? p - > subdevs [ IDX_SENSOR ] : NULL ;
struct fimc_md * fmd ;
int ret = 0 ;
if ( ! p | | ! p - > subdevs [ IDX_SENSOR ] )
if ( WARN_ON ( sd = = NULL ) )
return - EINVAL ;
if ( p - > subdevs [ IDX_SENSOR ] ) {
ret = fimc_pipeline_s_power ( p , 0 ) ;
fimc_md_set_camclk ( p - > sub devs [ IDX_SENSOR ] , false ) ;
fimc_md_set_camclk ( s d, false ) ;
}
fmd = entity_to_fimc_mdev ( & sd - > entity ) ;
/* Disable PXLASYNC clock if this pipeline includes FIMC-IS */
if ( ! IS_ERR ( fmd - > wbclk [ CLK_IDX_WB_B ] ) & & p - > subdevs [ IDX_IS_ISP ] )
clk_disable_unprepare ( fmd - > wbclk [ CLK_IDX_WB_B ] ) ;
return ret = = - ENXIO ? 0 : ret ;
}
@ -959,7 +990,7 @@ static int fimc_md_create_links(struct fimc_md *fmd)
}
/*
* The peripheral sensor clock management .
* The peripheral sensor and CAM_BLK ( PIXELASYNCMx ) clocks management .
*/
static void fimc_md_put_clocks ( struct fimc_md * fmd )
{
@ -972,6 +1003,14 @@ static void fimc_md_put_clocks(struct fimc_md *fmd)
clk_put ( fmd - > camclk [ i ] . clock ) ;
fmd - > camclk [ i ] . clock = ERR_PTR ( - EINVAL ) ;
}
/* Writeback (PIXELASYNCMx) clocks */
for ( i = 0 ; i < FIMC_MAX_WBCLKS ; i + + ) {
if ( IS_ERR ( fmd - > wbclk [ i ] ) )
continue ;
clk_put ( fmd - > wbclk [ i ] ) ;
fmd - > wbclk [ i ] = ERR_PTR ( - EINVAL ) ;
}
}
static int fimc_md_get_clocks ( struct fimc_md * fmd )
@ -1008,6 +1047,28 @@ static int fimc_md_get_clocks(struct fimc_md *fmd)
if ( ret )
fimc_md_put_clocks ( fmd ) ;
if ( ! fmd - > use_isp )
return 0 ;
/*
* For now get only PIXELASYNCM1 clock ( Writeback B / ISP ) ,
* leave PIXELASYNCM0 out for the LCD Writeback driver .
*/
fmd - > wbclk [ CLK_IDX_WB_A ] = ERR_PTR ( - EINVAL ) ;
for ( i = CLK_IDX_WB_B ; i < FIMC_MAX_WBCLKS ; i + + ) {
snprintf ( clk_name , sizeof ( clk_name ) , " pxl_async%u " , i ) ;
clock = clk_get ( dev , clk_name ) ;
if ( IS_ERR ( clock ) ) {
v4l2_err ( & fmd - > v4l2_dev , " Failed to get clock: %s \n " ,
clk_name ) ;
ret = PTR_ERR ( clock ) ;
break ;
}
fmd - > wbclk [ i ] = clock ;
}
if ( ret )
fimc_md_put_clocks ( fmd ) ;
return ret ;
}