@@ -216,6 +216,7 @@ struct dw_hdmi {
216216 struct drm_connector connector ;
217217 struct drm_encoder * encoder ;
218218 struct drm_bridge bridge ;
219+ struct drm_bridge * next_bridge ;
219220 struct platform_device * hdcp_dev ;
220221 enum dw_hdmi_devtype dev_type ;
221222 unsigned int version ;
@@ -2522,6 +2523,27 @@ static void dw_hdmi_update_phy_mask(struct dw_hdmi *hdmi)
25222523 hdmi_writeb (hdmi , hdmi -> phy_mask , HDMI_PHY_MASK0 );
25232524}
25242525
2526+ static int dw_hdmi_bridge_attach (struct drm_bridge * bridge )
2527+ {
2528+ struct dw_hdmi * hdmi = bridge -> driver_private ;
2529+ int ret ;
2530+
2531+ if (!hdmi -> next_bridge )
2532+ return 0 ;
2533+
2534+ hdmi -> next_bridge -> encoder = bridge -> encoder ;
2535+
2536+ ret = drm_bridge_attach (bridge -> dev , hdmi -> next_bridge );
2537+ if (ret ) {
2538+ DRM_ERROR ("Failed to attach bridge with dw-hdmi\n" );
2539+ return - EINVAL ;
2540+ }
2541+
2542+ bridge -> next = hdmi -> next_bridge ;
2543+
2544+ return 0 ;
2545+ }
2546+
25252547static void dw_hdmi_bridge_mode_set (struct drm_bridge * bridge ,
25262548 struct drm_display_mode * orig_mode ,
25272549 struct drm_display_mode * mode )
@@ -2884,6 +2906,7 @@ static const struct drm_connector_helper_funcs dw_hdmi_connector_helper_funcs =
28842906};
28852907
28862908static const struct drm_bridge_funcs dw_hdmi_bridge_funcs = {
2909+ .attach = dw_hdmi_bridge_attach ,
28872910 .enable = dw_hdmi_bridge_enable ,
28882911 .disable = dw_hdmi_bridge_disable ,
28892912 .pre_enable = dw_hdmi_bridge_nop ,
@@ -2997,8 +3020,10 @@ static irqreturn_t dw_hdmi_irq(int irq, void *dev_id)
29973020 check_hdmi_irq (hdmi , intr_stat , phy_int_pol );
29983021
29993022 hdmi_writeb (hdmi , intr_stat , HDMI_IH_PHY_STAT0 );
3000- hdmi_writeb (hdmi , ~(HDMI_IH_PHY_STAT0_HPD | HDMI_IH_PHY_STAT0_RX_SENSE ),
3001- HDMI_IH_MUTE_PHY_STAT0 );
3023+ if (!hdmi -> next_bridge )
3024+ hdmi_writeb (hdmi , ~(HDMI_IH_PHY_STAT0_HPD |
3025+ HDMI_IH_PHY_STAT0_RX_SENSE ),
3026+ HDMI_IH_MUTE_PHY_STAT0 );
30023027
30033028 hdcp_stat = hdmi_readb (hdmi , HDMI_A_APIINTSTAT );
30043029 if (hdcp_stat ) {
@@ -3204,19 +3229,59 @@ static void dw_hdmi_destroy_properties(struct dw_hdmi *hdmi)
32043229
32053230static int dw_hdmi_register (struct drm_device * drm , struct dw_hdmi * hdmi )
32063231{
3232+ struct device * dev = hdmi -> dev ;
32073233 struct drm_encoder * encoder = hdmi -> encoder ;
32083234 struct drm_bridge * bridge = & hdmi -> bridge ;
3235+ struct device_node * endpoint ;
32093236 int ret ;
32103237
32113238 bridge -> driver_private = hdmi ;
32123239 bridge -> funcs = & dw_hdmi_bridge_funcs ;
3240+
3241+ encoder -> bridge = bridge ;
3242+
3243+ endpoint = of_graph_get_endpoint_by_regs (dev -> of_node , 1 , -1 );
3244+ if (endpoint && of_device_is_available (endpoint )) {
3245+ struct device_node * remote ;
3246+
3247+ remote = of_graph_get_remote_port_parent (endpoint );
3248+ of_node_put (endpoint );
3249+ if (!remote || !of_device_is_available (remote )) {
3250+ of_node_put (remote );
3251+ return - ENODEV ;
3252+ }
3253+
3254+ bridge -> encoder = encoder ;
3255+ ret = drm_bridge_add (bridge );
3256+ if (ret ) {
3257+ dev_err (hdmi -> dev , "failed to add bridge: %d\n" , ret );
3258+ of_node_put (remote );
3259+ return ret ;
3260+ }
3261+
3262+ hdmi -> next_bridge = of_drm_find_bridge (remote );
3263+ of_node_put (remote );
3264+ if (!hdmi -> next_bridge ) {
3265+ dev_err (hdmi -> dev , "can't find next bridge\n" );
3266+ drm_bridge_remove (bridge );
3267+ return - EPROBE_DEFER ;
3268+ }
3269+
3270+ ret = drm_bridge_attach (drm , bridge );
3271+ if (ret ) {
3272+ dev_err (hdmi -> dev , "can't attach bridge with drm\n" );
3273+ return ret ;
3274+ }
3275+
3276+ return 0 ;
3277+ }
3278+
32133279 ret = drm_bridge_attach (drm , bridge );
32143280 if (ret ) {
32153281 DRM_ERROR ("Failed to initialize bridge with drm\n" );
32163282 return - EINVAL ;
32173283 }
32183284
3219- encoder -> bridge = bridge ;
32203285 hdmi -> connector .polled = DRM_CONNECTOR_POLL_HPD ;
32213286 hdmi -> connector .port = hdmi -> dev -> of_node ;
32223287
@@ -3597,7 +3662,7 @@ int dw_hdmi_bind(struct device *dev, struct device *master,
35973662 hdmi -> encoder = encoder ;
35983663 hdmi -> disabled = true;
35993664 hdmi -> rxsense = true;
3600- hdmi -> phy_mask = ( u8 )~( HDMI_PHY_HPD | HDMI_PHY_RX_SENSE );
3665+
36013666 hdmi -> irq = irq ;
36023667 hdmi -> mc_clkdis = 0x7f ;
36033668
@@ -3768,9 +3833,6 @@ int dw_hdmi_bind(struct device *dev, struct device *master,
37683833 /* Re-init HPD polarity */
37693834 hdmi_writeb (hdmi , HDMI_PHY_HPD | HDMI_PHY_RX_SENSE , HDMI_PHY_POL0 );
37703835
3771- /* Unmask HPD, clear transitory interrupts, then unmute */
3772- hdmi_writeb (hdmi , hdmi -> phy_mask , HDMI_PHY_MASK0 );
3773-
37743836 if (hdmi -> dev_type == RK3288_HDMI && hdmi -> version == 0x200a )
37753837 hdmi -> connector .ycbcr_420_allowed = false;
37763838 else
@@ -3780,13 +3842,24 @@ int dw_hdmi_bind(struct device *dev, struct device *master,
37803842 if (ret )
37813843 goto err_iahb ;
37823844
3845+ if (!hdmi -> next_bridge ) {
3846+ hdmi -> phy_mask = (u8 )~(HDMI_PHY_HPD | HDMI_PHY_RX_SENSE );
37833847#ifdef CONFIG_SWITCH
3784- hdmi -> switchdev .name = "hdmi" ;
3785- switch_dev_register (& hdmi -> switchdev );
3848+ hdmi -> switchdev .name = "hdmi" ;
3849+ switch_dev_register (& hdmi -> switchdev );
3850+
37863851#endif
3852+ hdmi_writeb (hdmi , ~(HDMI_IH_PHY_STAT0_HPD |
3853+ HDMI_IH_PHY_STAT0_RX_SENSE ),
3854+ HDMI_IH_MUTE_PHY_STAT0 );
3855+ } else {
3856+ hdmi -> sink_is_hdmi = true;
3857+ hdmi -> sink_has_audio = true;
3858+ hdmi -> phy_mask = 0xff ;
3859+ }
37873860
3788- hdmi_writeb ( hdmi , ~( HDMI_IH_PHY_STAT0_HPD | HDMI_IH_PHY_STAT0_RX_SENSE ),
3789- HDMI_IH_MUTE_PHY_STAT0 );
3861+ /* Unmask HPD, clear transitory interrupts, then unmute */
3862+ hdmi_writeb ( hdmi , hdmi -> phy_mask , HDMI_PHY_MASK0 );
37903863
37913864 /* Unmute I2CM interrupts and reset HDMI DDC I2C master controller */
37923865 if (hdmi -> i2c )
@@ -3911,11 +3984,13 @@ void dw_hdmi_unbind(struct device *dev, struct device *master, void *data)
39113984 if (hdmi -> cec_notifier )
39123985 cec_notifier_put (hdmi -> cec_notifier );
39133986
3987+ if (!hdmi -> next_bridge ) {
39143988#ifdef CONFIG_SWITCH
3915- switch_dev_unregister (& hdmi -> switchdev );
3989+ switch_dev_unregister (& hdmi -> switchdev );
39163990#endif
3917- dw_hdmi_destroy_properties (hdmi );
3918- hdmi -> connector .funcs -> destroy (& hdmi -> connector );
3991+ dw_hdmi_destroy_properties (hdmi );
3992+ hdmi -> connector .funcs -> destroy (& hdmi -> connector );
3993+ }
39193994 hdmi -> encoder -> funcs -> destroy (hdmi -> encoder );
39203995
39213996 clk_disable_unprepare (hdmi -> iahb_clk );
@@ -3941,12 +4016,14 @@ static void dw_hdmi_reg_initial(struct dw_hdmi *hdmi)
39414016 HDMI_PHY_I2CM_CTLINT_ADDR_ARBITRATION_POL ,
39424017 HDMI_PHY_I2CM_CTLINT_ADDR );
39434018
3944- hdmi_writeb (hdmi , HDMI_PHY_HPD | HDMI_PHY_RX_SENSE ,
3945- HDMI_PHY_POL0 );
3946- hdmi_writeb (hdmi , hdmi -> phy_mask , HDMI_PHY_MASK0 );
3947- hdmi_writeb (hdmi , ~(HDMI_IH_PHY_STAT0_HPD |
3948- HDMI_IH_PHY_STAT0_RX_SENSE ),
3949- HDMI_IH_MUTE_PHY_STAT0 );
4019+ if (!hdmi -> next_bridge ) {
4020+ hdmi_writeb (hdmi , HDMI_PHY_HPD | HDMI_PHY_RX_SENSE ,
4021+ HDMI_PHY_POL0 );
4022+ hdmi_writeb (hdmi , hdmi -> phy_mask , HDMI_PHY_MASK0 );
4023+ hdmi_writeb (hdmi , ~(HDMI_IH_PHY_STAT0_HPD |
4024+ HDMI_IH_PHY_STAT0_RX_SENSE ),
4025+ HDMI_IH_MUTE_PHY_STAT0 );
4026+ }
39504027 }
39514028}
39524029
0 commit comments