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