xref: /linux/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c (revision 220994d61cebfc04f071d69049127657c7e8191b)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright (C) 2013 Red Hat
4  * Author: Rob Clark <robdclark@gmail.com>
5  */
6 
7 #include <linux/delay.h>
8 #include <drm/drm_bridge_connector.h>
9 #include <drm/drm_edid.h>
10 #include <drm/display/drm_hdmi_helper.h>
11 #include <drm/display/drm_hdmi_state_helper.h>
12 
13 #include "msm_kms.h"
14 #include "hdmi.h"
15 
msm_hdmi_power_on(struct drm_bridge * bridge)16 static void msm_hdmi_power_on(struct drm_bridge *bridge)
17 {
18 	struct drm_device *dev = bridge->dev;
19 	struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);
20 	struct hdmi *hdmi = hdmi_bridge->hdmi;
21 	int ret;
22 
23 	pm_runtime_resume_and_get(&hdmi->pdev->dev);
24 
25 	if (hdmi->extp_clk) {
26 		DBG("pixclock: %lu", hdmi->pixclock);
27 		ret = clk_set_rate(hdmi->extp_clk, hdmi->pixclock);
28 		if (ret)
29 			DRM_DEV_ERROR(dev->dev, "failed to set extp clk rate: %d\n", ret);
30 
31 		ret = clk_prepare_enable(hdmi->extp_clk);
32 		if (ret)
33 			DRM_DEV_ERROR(dev->dev, "failed to enable extp clk: %d\n", ret);
34 	}
35 }
36 
power_off(struct drm_bridge * bridge)37 static void power_off(struct drm_bridge *bridge)
38 {
39 	struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);
40 	struct hdmi *hdmi = hdmi_bridge->hdmi;
41 
42 	/* TODO do we need to wait for final vblank somewhere before
43 	 * cutting the clocks?
44 	 */
45 	mdelay(16 + 4);
46 
47 	if (hdmi->extp_clk)
48 		clk_disable_unprepare(hdmi->extp_clk);
49 
50 	pm_runtime_put(&hdmi->pdev->dev);
51 }
52 
53 #define AVI_IFRAME_LINE_NUMBER 1
54 #define SPD_IFRAME_LINE_NUMBER 1
55 #define VENSPEC_IFRAME_LINE_NUMBER 3
56 
msm_hdmi_config_avi_infoframe(struct hdmi * hdmi,const u8 * buffer,size_t len)57 static int msm_hdmi_config_avi_infoframe(struct hdmi *hdmi,
58 					 const u8 *buffer, size_t len)
59 {
60 	u32 buf[4] = {};
61 	u32 val;
62 	int i;
63 
64 	if (len != HDMI_INFOFRAME_SIZE(AVI) || len - 3 > sizeof(buf)) {
65 		DRM_DEV_ERROR(&hdmi->pdev->dev,
66 			"failed to configure avi infoframe\n");
67 		return -EINVAL;
68 	}
69 
70 	/*
71 	 * the AVI_INFOx registers don't map exactly to how the AVI infoframes
72 	 * are packed according to the spec. The checksum from the header is
73 	 * written to the LSB byte of AVI_INFO0 and the version is written to
74 	 * the third byte from the LSB of AVI_INFO3
75 	 */
76 	memcpy(buf, &buffer[3], len - 3);
77 
78 	buf[3] |= buffer[1] << 24;
79 
80 	for (i = 0; i < ARRAY_SIZE(buf); i++)
81 		hdmi_write(hdmi, REG_HDMI_AVI_INFO(i), buf[i]);
82 
83 	val = hdmi_read(hdmi, REG_HDMI_INFOFRAME_CTRL1);
84 	val |= HDMI_INFOFRAME_CTRL0_AVI_SEND |
85 		HDMI_INFOFRAME_CTRL0_AVI_CONT;
86 	hdmi_write(hdmi, REG_HDMI_INFOFRAME_CTRL0, val);
87 
88 	val = hdmi_read(hdmi, REG_HDMI_INFOFRAME_CTRL1);
89 	val &= ~HDMI_INFOFRAME_CTRL1_AVI_INFO_LINE__MASK;
90 	val |= HDMI_INFOFRAME_CTRL1_AVI_INFO_LINE(AVI_IFRAME_LINE_NUMBER);
91 	hdmi_write(hdmi, REG_HDMI_INFOFRAME_CTRL1, val);
92 
93 	return 0;
94 }
95 
msm_hdmi_config_audio_infoframe(struct hdmi * hdmi,const u8 * buffer,size_t len)96 static int msm_hdmi_config_audio_infoframe(struct hdmi *hdmi,
97 					   const u8 *buffer, size_t len)
98 {
99 	u32 val;
100 
101 	if (len != HDMI_INFOFRAME_SIZE(AUDIO)) {
102 		DRM_DEV_ERROR(&hdmi->pdev->dev,
103 			"failed to configure audio infoframe\n");
104 		return -EINVAL;
105 	}
106 
107 	hdmi_write(hdmi, REG_HDMI_AUDIO_INFO0,
108 		   buffer[3] |
109 		   buffer[4] << 8 |
110 		   buffer[5] << 16 |
111 		   buffer[6] << 24);
112 
113 	hdmi_write(hdmi, REG_HDMI_AUDIO_INFO1,
114 		   buffer[7] |
115 		   buffer[8] << 8 |
116 		   buffer[9] << 16 |
117 		   buffer[10] << 24);
118 
119 	val = hdmi_read(hdmi, REG_HDMI_INFOFRAME_CTRL1);
120 	val |= HDMI_INFOFRAME_CTRL0_AUDIO_INFO_SEND |
121 		HDMI_INFOFRAME_CTRL0_AUDIO_INFO_CONT |
122 		HDMI_INFOFRAME_CTRL0_AUDIO_INFO_SOURCE |
123 		HDMI_INFOFRAME_CTRL0_AUDIO_INFO_UPDATE;
124 	hdmi_write(hdmi, REG_HDMI_INFOFRAME_CTRL0, val);
125 
126 	return 0;
127 }
128 
msm_hdmi_config_spd_infoframe(struct hdmi * hdmi,const u8 * buffer,size_t len)129 static int msm_hdmi_config_spd_infoframe(struct hdmi *hdmi,
130 					 const u8 *buffer, size_t len)
131 {
132 	u32 buf[7] = {};
133 	u32 val;
134 	int i;
135 
136 	if (len != HDMI_INFOFRAME_SIZE(SPD) || len - 3 > sizeof(buf)) {
137 		DRM_DEV_ERROR(&hdmi->pdev->dev,
138 			"failed to configure SPD infoframe\n");
139 		return -EINVAL;
140 	}
141 
142 	/* checksum gets written together with the body of the frame */
143 	hdmi_write(hdmi, REG_HDMI_GENERIC1_HDR,
144 		   buffer[0] |
145 		   buffer[1] << 8 |
146 		   buffer[2] << 16);
147 
148 	memcpy(buf, &buffer[3], len - 3);
149 
150 	for (i = 0; i < ARRAY_SIZE(buf); i++)
151 		hdmi_write(hdmi, REG_HDMI_GENERIC1(i), buf[i]);
152 
153 	val = hdmi_read(hdmi, REG_HDMI_GEN_PKT_CTRL);
154 	val |= HDMI_GEN_PKT_CTRL_GENERIC1_SEND |
155 		 HDMI_GEN_PKT_CTRL_GENERIC1_CONT |
156 		 HDMI_GEN_PKT_CTRL_GENERIC1_LINE(SPD_IFRAME_LINE_NUMBER);
157 	hdmi_write(hdmi, REG_HDMI_GEN_PKT_CTRL, val);
158 
159 	return 0;
160 }
161 
msm_hdmi_config_hdmi_infoframe(struct hdmi * hdmi,const u8 * buffer,size_t len)162 static int msm_hdmi_config_hdmi_infoframe(struct hdmi *hdmi,
163 					  const u8 *buffer, size_t len)
164 {
165 	u32 buf[7] = {};
166 	u32 val;
167 	int i;
168 
169 	if (len < HDMI_INFOFRAME_HEADER_SIZE + HDMI_VENDOR_INFOFRAME_SIZE ||
170 	    len - 3 > sizeof(buf)) {
171 		DRM_DEV_ERROR(&hdmi->pdev->dev,
172 			"failed to configure HDMI infoframe\n");
173 		return -EINVAL;
174 	}
175 
176 	/* checksum gets written together with the body of the frame */
177 	hdmi_write(hdmi, REG_HDMI_GENERIC0_HDR,
178 		   buffer[0] |
179 		   buffer[1] << 8 |
180 		   buffer[2] << 16);
181 
182 	memcpy(buf, &buffer[3], len - 3);
183 
184 	for (i = 0; i < ARRAY_SIZE(buf); i++)
185 		hdmi_write(hdmi, REG_HDMI_GENERIC0(i), buf[i]);
186 
187 	val = hdmi_read(hdmi, REG_HDMI_GEN_PKT_CTRL);
188 	val |= HDMI_GEN_PKT_CTRL_GENERIC0_SEND |
189 		 HDMI_GEN_PKT_CTRL_GENERIC0_CONT |
190 		 HDMI_GEN_PKT_CTRL_GENERIC0_UPDATE |
191 		 HDMI_GEN_PKT_CTRL_GENERIC0_LINE(VENSPEC_IFRAME_LINE_NUMBER);
192 	hdmi_write(hdmi, REG_HDMI_GEN_PKT_CTRL, val);
193 
194 	return 0;
195 }
196 
msm_hdmi_bridge_clear_infoframe(struct drm_bridge * bridge,enum hdmi_infoframe_type type)197 static int msm_hdmi_bridge_clear_infoframe(struct drm_bridge *bridge,
198 					   enum hdmi_infoframe_type type)
199 {
200 	struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);
201 	struct hdmi *hdmi = hdmi_bridge->hdmi;
202 	u32 val;
203 
204 	switch (type) {
205 	case HDMI_INFOFRAME_TYPE_AVI:
206 		val = hdmi_read(hdmi, REG_HDMI_INFOFRAME_CTRL0);
207 		val &= ~(HDMI_INFOFRAME_CTRL0_AVI_SEND |
208 			 HDMI_INFOFRAME_CTRL0_AVI_CONT);
209 		hdmi_write(hdmi, REG_HDMI_INFOFRAME_CTRL0, val);
210 
211 		val = hdmi_read(hdmi, REG_HDMI_INFOFRAME_CTRL1);
212 		val &= ~HDMI_INFOFRAME_CTRL1_AVI_INFO_LINE__MASK;
213 		hdmi_write(hdmi, REG_HDMI_INFOFRAME_CTRL1, val);
214 
215 		break;
216 
217 	case HDMI_INFOFRAME_TYPE_AUDIO:
218 		val = hdmi_read(hdmi, REG_HDMI_INFOFRAME_CTRL0);
219 		val &= ~(HDMI_INFOFRAME_CTRL0_AUDIO_INFO_SEND |
220 			 HDMI_INFOFRAME_CTRL0_AUDIO_INFO_CONT |
221 			 HDMI_INFOFRAME_CTRL0_AUDIO_INFO_SOURCE |
222 			 HDMI_INFOFRAME_CTRL0_AUDIO_INFO_UPDATE);
223 		hdmi_write(hdmi, REG_HDMI_INFOFRAME_CTRL0, val);
224 
225 		val = hdmi_read(hdmi, REG_HDMI_INFOFRAME_CTRL1);
226 		val &= ~HDMI_INFOFRAME_CTRL1_AUDIO_INFO_LINE__MASK;
227 		hdmi_write(hdmi, REG_HDMI_INFOFRAME_CTRL1, val);
228 
229 		break;
230 
231 	case HDMI_INFOFRAME_TYPE_SPD:
232 		val = hdmi_read(hdmi, REG_HDMI_GEN_PKT_CTRL);
233 		val &= ~(HDMI_GEN_PKT_CTRL_GENERIC1_SEND |
234 			 HDMI_GEN_PKT_CTRL_GENERIC1_CONT |
235 			 HDMI_GEN_PKT_CTRL_GENERIC1_LINE__MASK);
236 		hdmi_write(hdmi, REG_HDMI_GEN_PKT_CTRL, val);
237 
238 		break;
239 
240 	case HDMI_INFOFRAME_TYPE_VENDOR:
241 		val = hdmi_read(hdmi, REG_HDMI_GEN_PKT_CTRL);
242 		val &= ~(HDMI_GEN_PKT_CTRL_GENERIC0_SEND |
243 			 HDMI_GEN_PKT_CTRL_GENERIC0_CONT |
244 			 HDMI_GEN_PKT_CTRL_GENERIC0_UPDATE |
245 			 HDMI_GEN_PKT_CTRL_GENERIC0_LINE__MASK);
246 		hdmi_write(hdmi, REG_HDMI_GEN_PKT_CTRL, val);
247 
248 		break;
249 
250 	default:
251 		drm_dbg_driver(hdmi_bridge->base.dev, "Unsupported infoframe type %x\n", type);
252 	}
253 
254 	return 0;
255 }
256 
msm_hdmi_bridge_write_infoframe(struct drm_bridge * bridge,enum hdmi_infoframe_type type,const u8 * buffer,size_t len)257 static int msm_hdmi_bridge_write_infoframe(struct drm_bridge *bridge,
258 					   enum hdmi_infoframe_type type,
259 					   const u8 *buffer, size_t len)
260 {
261 	struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);
262 	struct hdmi *hdmi = hdmi_bridge->hdmi;
263 
264 	msm_hdmi_bridge_clear_infoframe(bridge, type);
265 
266 	switch (type) {
267 	case HDMI_INFOFRAME_TYPE_AVI:
268 		return msm_hdmi_config_avi_infoframe(hdmi, buffer, len);
269 	case HDMI_INFOFRAME_TYPE_AUDIO:
270 		return msm_hdmi_config_audio_infoframe(hdmi, buffer, len);
271 	case HDMI_INFOFRAME_TYPE_SPD:
272 		return msm_hdmi_config_spd_infoframe(hdmi, buffer, len);
273 	case HDMI_INFOFRAME_TYPE_VENDOR:
274 		return msm_hdmi_config_hdmi_infoframe(hdmi, buffer, len);
275 	default:
276 		drm_dbg_driver(hdmi_bridge->base.dev, "Unsupported infoframe type %x\n", type);
277 		return 0;
278 	}
279 }
280 
281 static void msm_hdmi_set_timings(struct hdmi *hdmi,
282 				 const struct drm_display_mode *mode);
283 
msm_hdmi_bridge_atomic_pre_enable(struct drm_bridge * bridge,struct drm_atomic_state * state)284 static void msm_hdmi_bridge_atomic_pre_enable(struct drm_bridge *bridge,
285 					      struct drm_atomic_state *state)
286 {
287 	struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);
288 	struct hdmi *hdmi = hdmi_bridge->hdmi;
289 	struct hdmi_phy *phy = hdmi->phy;
290 	struct drm_encoder *encoder = bridge->encoder;
291 	struct drm_connector *connector;
292 	struct drm_connector_state *conn_state;
293 	struct drm_crtc_state *crtc_state;
294 
295 	DBG("power up");
296 
297 	connector = drm_atomic_get_new_connector_for_encoder(state, encoder);
298 	conn_state = drm_atomic_get_new_connector_state(state, connector);
299 	crtc_state = drm_atomic_get_new_crtc_state(state, conn_state->crtc);
300 
301 	hdmi->pixclock = conn_state->hdmi.tmds_char_rate;
302 
303 	msm_hdmi_set_timings(hdmi, &crtc_state->adjusted_mode);
304 
305 	mutex_lock(&hdmi->state_mutex);
306 	if (!hdmi->power_on) {
307 		msm_hdmi_phy_resource_enable(phy);
308 		msm_hdmi_power_on(bridge);
309 		hdmi->power_on = true;
310 	}
311 	mutex_unlock(&hdmi->state_mutex);
312 
313 	if (connector->display_info.is_hdmi)
314 		msm_hdmi_audio_update(hdmi);
315 
316 	drm_atomic_helper_connector_hdmi_update_infoframes(connector, state);
317 
318 	msm_hdmi_phy_powerup(phy, hdmi->pixclock);
319 
320 	msm_hdmi_set_mode(hdmi, true);
321 
322 	if (hdmi->hdcp_ctrl)
323 		msm_hdmi_hdcp_on(hdmi->hdcp_ctrl);
324 }
325 
msm_hdmi_bridge_atomic_post_disable(struct drm_bridge * bridge,struct drm_atomic_state * state)326 static void msm_hdmi_bridge_atomic_post_disable(struct drm_bridge *bridge,
327 						struct drm_atomic_state *state)
328 {
329 	struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);
330 	struct hdmi *hdmi = hdmi_bridge->hdmi;
331 	struct hdmi_phy *phy = hdmi->phy;
332 
333 	if (hdmi->hdcp_ctrl)
334 		msm_hdmi_hdcp_off(hdmi->hdcp_ctrl);
335 
336 	DBG("power down");
337 
338 	/* Keep the HDMI enabled if the HPD is enabled */
339 	mutex_lock(&hdmi->state_mutex);
340 	msm_hdmi_set_mode(hdmi, hdmi->hpd_enabled);
341 
342 	msm_hdmi_phy_powerdown(phy);
343 
344 	if (hdmi->power_on) {
345 		power_off(bridge);
346 		hdmi->power_on = false;
347 		if (hdmi->connector->display_info.is_hdmi)
348 			msm_hdmi_audio_update(hdmi);
349 		msm_hdmi_phy_resource_disable(phy);
350 	}
351 	mutex_unlock(&hdmi->state_mutex);
352 }
353 
msm_hdmi_set_timings(struct hdmi * hdmi,const struct drm_display_mode * mode)354 static void msm_hdmi_set_timings(struct hdmi *hdmi,
355 				 const struct drm_display_mode *mode)
356 {
357 	int hstart, hend, vstart, vend;
358 	uint32_t frame_ctrl;
359 
360 	hstart = mode->htotal - mode->hsync_start;
361 	hend   = mode->htotal - mode->hsync_start + mode->hdisplay;
362 
363 	vstart = mode->vtotal - mode->vsync_start - 1;
364 	vend   = mode->vtotal - mode->vsync_start + mode->vdisplay - 1;
365 
366 	DBG("htotal=%d, vtotal=%d, hstart=%d, hend=%d, vstart=%d, vend=%d",
367 			mode->htotal, mode->vtotal, hstart, hend, vstart, vend);
368 
369 	hdmi_write(hdmi, REG_HDMI_TOTAL,
370 			HDMI_TOTAL_H_TOTAL(mode->htotal - 1) |
371 			HDMI_TOTAL_V_TOTAL(mode->vtotal - 1));
372 
373 	hdmi_write(hdmi, REG_HDMI_ACTIVE_HSYNC,
374 			HDMI_ACTIVE_HSYNC_START(hstart) |
375 			HDMI_ACTIVE_HSYNC_END(hend));
376 	hdmi_write(hdmi, REG_HDMI_ACTIVE_VSYNC,
377 			HDMI_ACTIVE_VSYNC_START(vstart) |
378 			HDMI_ACTIVE_VSYNC_END(vend));
379 
380 	if (mode->flags & DRM_MODE_FLAG_INTERLACE) {
381 		hdmi_write(hdmi, REG_HDMI_VSYNC_TOTAL_F2,
382 				HDMI_VSYNC_TOTAL_F2_V_TOTAL(mode->vtotal));
383 		hdmi_write(hdmi, REG_HDMI_VSYNC_ACTIVE_F2,
384 				HDMI_VSYNC_ACTIVE_F2_START(vstart + 1) |
385 				HDMI_VSYNC_ACTIVE_F2_END(vend + 1));
386 	} else {
387 		hdmi_write(hdmi, REG_HDMI_VSYNC_TOTAL_F2,
388 				HDMI_VSYNC_TOTAL_F2_V_TOTAL(0));
389 		hdmi_write(hdmi, REG_HDMI_VSYNC_ACTIVE_F2,
390 				HDMI_VSYNC_ACTIVE_F2_START(0) |
391 				HDMI_VSYNC_ACTIVE_F2_END(0));
392 	}
393 
394 	frame_ctrl = 0;
395 	if (mode->flags & DRM_MODE_FLAG_NHSYNC)
396 		frame_ctrl |= HDMI_FRAME_CTRL_HSYNC_LOW;
397 	if (mode->flags & DRM_MODE_FLAG_NVSYNC)
398 		frame_ctrl |= HDMI_FRAME_CTRL_VSYNC_LOW;
399 	if (mode->flags & DRM_MODE_FLAG_INTERLACE)
400 		frame_ctrl |= HDMI_FRAME_CTRL_INTERLACED_EN;
401 	DBG("frame_ctrl=%08x", frame_ctrl);
402 	hdmi_write(hdmi, REG_HDMI_FRAME_CTRL, frame_ctrl);
403 }
404 
msm_hdmi_bridge_edid_read(struct drm_bridge * bridge,struct drm_connector * connector)405 static const struct drm_edid *msm_hdmi_bridge_edid_read(struct drm_bridge *bridge,
406 							struct drm_connector *connector)
407 {
408 	struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);
409 	struct hdmi *hdmi = hdmi_bridge->hdmi;
410 	const struct drm_edid *drm_edid;
411 	uint32_t hdmi_ctrl;
412 
413 	hdmi_ctrl = hdmi_read(hdmi, REG_HDMI_CTRL);
414 	hdmi_write(hdmi, REG_HDMI_CTRL, hdmi_ctrl | HDMI_CTRL_ENABLE);
415 
416 	drm_edid = drm_edid_read_ddc(connector, hdmi->i2c);
417 
418 	hdmi_write(hdmi, REG_HDMI_CTRL, hdmi_ctrl);
419 
420 	return drm_edid;
421 }
422 
msm_hdmi_bridge_tmds_char_rate_valid(const struct drm_bridge * bridge,const struct drm_display_mode * mode,unsigned long long tmds_rate)423 static enum drm_mode_status msm_hdmi_bridge_tmds_char_rate_valid(const struct drm_bridge *bridge,
424 								 const struct drm_display_mode *mode,
425 								 unsigned long long tmds_rate)
426 {
427 	struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);
428 	struct hdmi *hdmi = hdmi_bridge->hdmi;
429 	struct msm_drm_private *priv = bridge->dev->dev_private;
430 	struct msm_kms *kms = priv->kms;
431 	long actual;
432 
433 	/* for mdp5/apq8074, we manage our own pixel clk (as opposed to
434 	 * mdp4/dtv stuff where pixel clk is assigned to mdp/encoder
435 	 * instead):
436 	 */
437 	if (kms->funcs->round_pixclk)
438 		actual = kms->funcs->round_pixclk(kms,
439 						  tmds_rate,
440 						  hdmi_bridge->hdmi->encoder);
441 	else if (hdmi->extp_clk)
442 		actual = clk_round_rate(hdmi->extp_clk, tmds_rate);
443 	else
444 		actual = tmds_rate;
445 
446 	DBG("requested=%lld, actual=%ld", tmds_rate, actual);
447 
448 	if (actual != tmds_rate)
449 		return MODE_CLOCK_RANGE;
450 
451 	return 0;
452 }
453 
454 static const struct drm_bridge_funcs msm_hdmi_bridge_funcs = {
455 	.atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
456 	.atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
457 	.atomic_reset = drm_atomic_helper_bridge_reset,
458 	.atomic_pre_enable = msm_hdmi_bridge_atomic_pre_enable,
459 	.atomic_post_disable = msm_hdmi_bridge_atomic_post_disable,
460 	.edid_read = msm_hdmi_bridge_edid_read,
461 	.detect = msm_hdmi_bridge_detect,
462 	.hpd_enable = msm_hdmi_hpd_enable,
463 	.hpd_disable = msm_hdmi_hpd_disable,
464 	.hdmi_tmds_char_rate_valid = msm_hdmi_bridge_tmds_char_rate_valid,
465 	.hdmi_clear_infoframe = msm_hdmi_bridge_clear_infoframe,
466 	.hdmi_write_infoframe = msm_hdmi_bridge_write_infoframe,
467 	.hdmi_audio_prepare = msm_hdmi_bridge_audio_prepare,
468 	.hdmi_audio_shutdown = msm_hdmi_bridge_audio_shutdown,
469 };
470 
471 static void
msm_hdmi_hotplug_work(struct work_struct * work)472 msm_hdmi_hotplug_work(struct work_struct *work)
473 {
474 	struct hdmi_bridge *hdmi_bridge =
475 		container_of(work, struct hdmi_bridge, hpd_work);
476 	struct drm_bridge *bridge = &hdmi_bridge->base;
477 
478 	drm_bridge_hpd_notify(bridge, drm_bridge_detect(bridge, hdmi_bridge->hdmi->connector));
479 }
480 
481 /* initialize bridge */
msm_hdmi_bridge_init(struct hdmi * hdmi)482 int msm_hdmi_bridge_init(struct hdmi *hdmi)
483 {
484 	struct drm_bridge *bridge = NULL;
485 	struct hdmi_bridge *hdmi_bridge;
486 	int ret;
487 
488 	hdmi_bridge = devm_drm_bridge_alloc(hdmi->dev->dev, struct hdmi_bridge, base,
489 					    &msm_hdmi_bridge_funcs);
490 	if (IS_ERR(hdmi_bridge))
491 		return PTR_ERR(hdmi_bridge);
492 
493 	hdmi_bridge->hdmi = hdmi;
494 	INIT_WORK(&hdmi_bridge->hpd_work, msm_hdmi_hotplug_work);
495 
496 	bridge = &hdmi_bridge->base;
497 	bridge->ddc = hdmi->i2c;
498 	bridge->type = DRM_MODE_CONNECTOR_HDMIA;
499 	bridge->vendor = "Qualcomm";
500 	bridge->product = "Snapdragon";
501 	bridge->ops = DRM_BRIDGE_OP_HPD |
502 		DRM_BRIDGE_OP_DETECT |
503 		DRM_BRIDGE_OP_HDMI |
504 		DRM_BRIDGE_OP_HDMI_AUDIO |
505 		DRM_BRIDGE_OP_EDID;
506 	bridge->hdmi_audio_max_i2s_playback_channels = 8;
507 	bridge->hdmi_audio_dev = &hdmi->pdev->dev;
508 	bridge->hdmi_audio_dai_port = -1;
509 
510 	ret = devm_drm_bridge_add(hdmi->dev->dev, bridge);
511 	if (ret)
512 		return ret;
513 
514 	ret = drm_bridge_attach(hdmi->encoder, bridge, NULL, DRM_BRIDGE_ATTACH_NO_CONNECTOR);
515 	if (ret)
516 		return ret;
517 
518 	hdmi->bridge = bridge;
519 
520 	return 0;
521 }
522