@ -304,34 +304,37 @@ static const struct dev_pm_ops rockchip_drm_pm_ops = {
rockchip_drm_sys_resume )
} ;
static int compare_of ( struct device * dev , void * data )
{
struct device_node * np = data ;
# define MAX_ROCKCHIP_SUB_DRIVERS 16
static struct platform_driver * rockchip_sub_drivers [ MAX_ROCKCHIP_SUB_DRIVERS ] ;
static int num_rockchip_sub_drivers ;
return dev - > of_node = = np ;
static int compare_dev ( struct device * dev , void * data )
{
return dev = = ( struct device * ) data ;
}
static void rockchip_add_endpoints ( struct device * dev ,
struct component_match * * match ,
struct device_node * port )
static struct component_match * rockchip_drm_match_add ( struct device * dev )
{
struct device_node * ep , * remote ;
struct component_match * match = NULL ;
int i ;
for_each_child_of_node ( port , ep ) {
remote = of_graph_get_remote_port_parent ( ep ) ;
if ( ! remote | | ! of_device_is_available ( remote ) ) {
of_node_put ( remote ) ;
continue ;
} else if ( ! of_device_is_available ( remote - > parent ) ) {
dev_warn ( dev , " parent device of %s is not available \n " ,
remote - > full_name ) ;
of_node_put ( remote ) ;
continue ;
}
for ( i = 0 ; i < num_rockchip_sub_drivers ; i + + ) {
struct platform_driver * drv = rockchip_sub_drivers [ i ] ;
struct device * p = NULL , * d ;
do {
d = bus_find_device ( & platform_bus_type , p , & drv - > driver ,
( void * ) platform_bus_type . match ) ;
put_device ( p ) ;
p = d ;
drm_of_component_match_add ( dev , match , compare_of , remote ) ;
of_node_put ( remote ) ;
if ( ! d )
break ;
component_match_add ( dev , & match , compare_dev , d ) ;
} while ( true ) ;
}
return match ? : ERR_PTR ( - ENODEV ) ;
}
static const struct component_master_ops rockchip_drm_ops = {
@ -339,21 +342,16 @@ static const struct component_master_ops rockchip_drm_ops = {
. unbind = rockchip_drm_unbind ,
} ;
static int rockchip_drm_platform_probe ( struct platform_ device * p dev)
static int rockchip_drm_platform_of_ probe ( struct device * dev )
{
struct device * dev = & pdev - > dev ;
struct component_match * match = NULL ;
struct device_node * np = dev - > of_node ;
struct device_node * port ;
bool found = false ;
int i ;
if ( ! np )
return - ENODEV ;
/*
* Bind the crtc ports first , so that
* drm_of_find_possible_crtcs called from encoder . bind callbacks
* works as expected .
*/
for ( i = 0 ; ; i + + ) {
struct device_node * iommu ;
@ -377,9 +375,9 @@ static int rockchip_drm_platform_probe(struct platform_device *pdev)
is_support_iommu = false ;
}
found = true ;
of_node_put ( iommu ) ;
drm_of_component_match_add ( dev , & match , compare_of ,
port - > parent ) ;
of_node_put ( port ) ;
}
@ -388,27 +386,27 @@ static int rockchip_drm_platform_probe(struct platform_device *pdev)
return - ENODEV ;
}
if ( ! match ) {
if ( ! found ) {
dev_err ( dev , " No available vop found for display-subsystem. \n " ) ;
return - ENODEV ;
}
/*
* For each bound crtc , bind the encoders attached to its
* remote endpoint .
*/
for ( i = 0 ; ; i + + ) {
port = of_parse_phandle ( np , " ports " , i ) ;
if ( ! port )
break ;
if ( ! of_device_is_available ( port - > parent ) ) {
of_node_put ( port ) ;
continue ;
}
return 0 ;
}
rockchip_add_endpoints ( dev , & match , port ) ;
of_node_put ( port ) ;
}
static int rockchip_drm_platform_probe ( struct platform_device * pdev )
{
struct device * dev = & pdev - > dev ;
struct component_match * match = NULL ;
int ret ;
ret = rockchip_drm_platform_of_probe ( dev ) ;
if ( ret )
return ret ;
match = rockchip_drm_match_add ( dev ) ;
if ( IS_ERR ( match ) )
return PTR_ERR ( match ) ;
return component_master_add_with_match ( dev , & rockchip_drm_ops , match ) ;
}
@ -436,7 +434,54 @@ static struct platform_driver rockchip_drm_platform_driver = {
} ,
} ;
module_platform_driver ( rockchip_drm_platform_driver ) ;
# define ADD_ROCKCHIP_SUB_DRIVER(drv, cond) { \
if ( IS_ENABLED ( cond ) & & \
! WARN_ON ( num_rockchip_sub_drivers > = MAX_ROCKCHIP_SUB_DRIVERS ) ) \
rockchip_sub_drivers [ num_rockchip_sub_drivers + + ] = & drv ; \
}
static int __init rockchip_drm_init ( void )
{
int ret ;
num_rockchip_sub_drivers = 0 ;
ADD_ROCKCHIP_SUB_DRIVER ( vop_platform_driver , CONFIG_DRM_ROCKCHIP ) ;
ADD_ROCKCHIP_SUB_DRIVER ( rockchip_dp_driver ,
CONFIG_ROCKCHIP_ANALOGIX_DP ) ;
ADD_ROCKCHIP_SUB_DRIVER ( cdn_dp_driver , CONFIG_ROCKCHIP_CDN_DP ) ;
ADD_ROCKCHIP_SUB_DRIVER ( dw_hdmi_rockchip_pltfm_driver ,
CONFIG_ROCKCHIP_DW_HDMI ) ;
ADD_ROCKCHIP_SUB_DRIVER ( dw_mipi_dsi_driver ,
CONFIG_ROCKCHIP_DW_MIPI_DSI ) ;
ADD_ROCKCHIP_SUB_DRIVER ( inno_hdmi_driver , CONFIG_ROCKCHIP_INNO_HDMI ) ;
ret = platform_register_drivers ( rockchip_sub_drivers ,
num_rockchip_sub_drivers ) ;
if ( ret )
return ret ;
ret = platform_driver_register ( & rockchip_drm_platform_driver ) ;
if ( ret )
goto err_unreg_drivers ;
return 0 ;
err_unreg_drivers :
platform_unregister_drivers ( rockchip_sub_drivers ,
num_rockchip_sub_drivers ) ;
return ret ;
}
static void __exit rockchip_drm_fini ( void )
{
platform_driver_unregister ( & rockchip_drm_platform_driver ) ;
platform_unregister_drivers ( rockchip_sub_drivers ,
num_rockchip_sub_drivers ) ;
}
module_init ( rockchip_drm_init ) ;
module_exit ( rockchip_drm_fini ) ;
MODULE_AUTHOR ( " Mark Yao <mark.yao@rock-chips.com> " ) ;
MODULE_DESCRIPTION ( " ROCKCHIP DRM Driver " ) ;