55 */
66
77#include <linux/delay.h>
8+ #include <drm/drm_bridge_connector.h>
89
10+ #include "msm_kms.h"
911#include "hdmi.h"
1012
11- struct hdmi_bridge {
12- struct drm_bridge base ;
13- struct hdmi * hdmi ;
14- };
15- #define to_hdmi_bridge (x ) container_of(x, struct hdmi_bridge, base)
16-
1713void msm_hdmi_bridge_destroy (struct drm_bridge * bridge )
1814{
15+ struct hdmi_bridge * hdmi_bridge = to_hdmi_bridge (bridge );
16+
17+ msm_hdmi_hpd_disable (hdmi_bridge );
1918}
2019
2120static void msm_hdmi_power_on (struct drm_bridge * bridge )
@@ -251,14 +250,76 @@ static void msm_hdmi_bridge_mode_set(struct drm_bridge *bridge,
251250 msm_hdmi_audio_update (hdmi );
252251}
253252
253+ static struct edid * msm_hdmi_bridge_get_edid (struct drm_bridge * bridge ,
254+ struct drm_connector * connector )
255+ {
256+ struct hdmi_bridge * hdmi_bridge = to_hdmi_bridge (bridge );
257+ struct hdmi * hdmi = hdmi_bridge -> hdmi ;
258+ struct edid * edid ;
259+ uint32_t hdmi_ctrl ;
260+
261+ hdmi_ctrl = hdmi_read (hdmi , REG_HDMI_CTRL );
262+ hdmi_write (hdmi , REG_HDMI_CTRL , hdmi_ctrl | HDMI_CTRL_ENABLE );
263+
264+ edid = drm_get_edid (connector , hdmi -> i2c );
265+
266+ hdmi_write (hdmi , REG_HDMI_CTRL , hdmi_ctrl );
267+
268+ hdmi -> hdmi_mode = drm_detect_hdmi_monitor (edid );
269+
270+ return edid ;
271+ }
272+
273+ static enum drm_mode_status msm_hdmi_bridge_mode_valid (struct drm_bridge * bridge ,
274+ const struct drm_display_info * info ,
275+ const struct drm_display_mode * mode )
276+ {
277+ struct hdmi_bridge * hdmi_bridge = to_hdmi_bridge (bridge );
278+ struct hdmi * hdmi = hdmi_bridge -> hdmi ;
279+ const struct hdmi_platform_config * config = hdmi -> config ;
280+ struct msm_drm_private * priv = bridge -> dev -> dev_private ;
281+ struct msm_kms * kms = priv -> kms ;
282+ long actual , requested ;
283+
284+ requested = 1000 * mode -> clock ;
285+ actual = kms -> funcs -> round_pixclk (kms ,
286+ requested , hdmi_bridge -> hdmi -> encoder );
287+
288+ /* for mdp5/apq8074, we manage our own pixel clk (as opposed to
289+ * mdp4/dtv stuff where pixel clk is assigned to mdp/encoder
290+ * instead):
291+ */
292+ if (config -> pwr_clk_cnt > 0 )
293+ actual = clk_round_rate (hdmi -> pwr_clks [0 ], actual );
294+
295+ DBG ("requested=%ld, actual=%ld" , requested , actual );
296+
297+ if (actual != requested )
298+ return MODE_CLOCK_RANGE ;
299+
300+ return 0 ;
301+ }
302+
254303static const struct drm_bridge_funcs msm_hdmi_bridge_funcs = {
255304 .pre_enable = msm_hdmi_bridge_pre_enable ,
256305 .enable = msm_hdmi_bridge_enable ,
257306 .disable = msm_hdmi_bridge_disable ,
258307 .post_disable = msm_hdmi_bridge_post_disable ,
259308 .mode_set = msm_hdmi_bridge_mode_set ,
309+ .mode_valid = msm_hdmi_bridge_mode_valid ,
310+ .get_edid = msm_hdmi_bridge_get_edid ,
311+ .detect = msm_hdmi_bridge_detect ,
260312};
261313
314+ static void
315+ msm_hdmi_hotplug_work (struct work_struct * work )
316+ {
317+ struct hdmi_bridge * hdmi_bridge =
318+ container_of (work , struct hdmi_bridge , hpd_work );
319+ struct drm_bridge * bridge = & hdmi_bridge -> base ;
320+
321+ drm_bridge_hpd_notify (bridge , drm_bridge_detect (bridge ));
322+ }
262323
263324/* initialize bridge */
264325struct drm_bridge * msm_hdmi_bridge_init (struct hdmi * hdmi )
@@ -275,11 +336,17 @@ struct drm_bridge *msm_hdmi_bridge_init(struct hdmi *hdmi)
275336 }
276337
277338 hdmi_bridge -> hdmi = hdmi ;
339+ INIT_WORK (& hdmi_bridge -> hpd_work , msm_hdmi_hotplug_work );
278340
279341 bridge = & hdmi_bridge -> base ;
280342 bridge -> funcs = & msm_hdmi_bridge_funcs ;
343+ bridge -> ddc = hdmi -> i2c ;
344+ bridge -> type = DRM_MODE_CONNECTOR_HDMIA ;
345+ bridge -> ops = DRM_BRIDGE_OP_HPD |
346+ DRM_BRIDGE_OP_DETECT |
347+ DRM_BRIDGE_OP_EDID ;
281348
282- ret = drm_bridge_attach (hdmi -> encoder , bridge , NULL , 0 );
349+ ret = drm_bridge_attach (hdmi -> encoder , bridge , NULL , DRM_BRIDGE_ATTACH_NO_CONNECTOR );
283350 if (ret )
284351 goto fail ;
285352
0 commit comments