1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright (c) 2014-2015, The Linux Foundation. All rights reserved.
4  */
5 
6 #include "edp.h"
7 
8 struct edp_bridge {
9 	struct drm_bridge base;
10 	struct msm_edp *edp;
11 };
12 #define to_edp_bridge(x) container_of(x, struct edp_bridge, base)
13 
edp_bridge_destroy(struct drm_bridge * bridge)14 void edp_bridge_destroy(struct drm_bridge *bridge)
15 {
16 }
17 
edp_bridge_pre_enable(struct drm_bridge * bridge)18 static void edp_bridge_pre_enable(struct drm_bridge *bridge)
19 {
20 	struct edp_bridge *edp_bridge = to_edp_bridge(bridge);
21 	struct msm_edp *edp = edp_bridge->edp;
22 
23 	DBG("");
24 	msm_edp_ctrl_power(edp->ctrl, true);
25 }
26 
edp_bridge_enable(struct drm_bridge * bridge)27 static void edp_bridge_enable(struct drm_bridge *bridge)
28 {
29 	DBG("");
30 }
31 
edp_bridge_disable(struct drm_bridge * bridge)32 static void edp_bridge_disable(struct drm_bridge *bridge)
33 {
34 	DBG("");
35 }
36 
edp_bridge_post_disable(struct drm_bridge * bridge)37 static void edp_bridge_post_disable(struct drm_bridge *bridge)
38 {
39 	struct edp_bridge *edp_bridge = to_edp_bridge(bridge);
40 	struct msm_edp *edp = edp_bridge->edp;
41 
42 	DBG("");
43 	msm_edp_ctrl_power(edp->ctrl, false);
44 }
45 
edp_bridge_mode_set(struct drm_bridge * bridge,const struct drm_display_mode * mode,const struct drm_display_mode * adjusted_mode)46 static void edp_bridge_mode_set(struct drm_bridge *bridge,
47 		const struct drm_display_mode *mode,
48 		const struct drm_display_mode *adjusted_mode)
49 {
50 	struct drm_device *dev = bridge->dev;
51 	struct drm_connector *connector;
52 	struct edp_bridge *edp_bridge = to_edp_bridge(bridge);
53 	struct msm_edp *edp = edp_bridge->edp;
54 
55 	DBG("set mode: " DRM_MODE_FMT, DRM_MODE_ARG(mode));
56 
57 	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
58 		if ((connector->encoder != NULL) &&
59 			(connector->encoder->bridge == bridge)) {
60 			msm_edp_ctrl_timing_cfg(edp->ctrl,
61 				adjusted_mode, &connector->display_info);
62 			break;
63 		}
64 	}
65 }
66 
67 static const struct drm_bridge_funcs edp_bridge_funcs = {
68 	.pre_enable = edp_bridge_pre_enable,
69 	.enable = edp_bridge_enable,
70 	.disable = edp_bridge_disable,
71 	.post_disable = edp_bridge_post_disable,
72 	.mode_set = edp_bridge_mode_set,
73 };
74 
75 /* initialize bridge */
msm_edp_bridge_init(struct msm_edp * edp)76 struct drm_bridge *msm_edp_bridge_init(struct msm_edp *edp)
77 {
78 	struct drm_bridge *bridge = NULL;
79 	struct edp_bridge *edp_bridge;
80 	int ret;
81 
82 	edp_bridge = devm_kzalloc(edp->dev->dev,
83 			sizeof(*edp_bridge), GFP_KERNEL);
84 	if (!edp_bridge) {
85 		ret = -ENOMEM;
86 		goto fail;
87 	}
88 
89 	edp_bridge->edp = edp;
90 
91 	bridge = &edp_bridge->base;
92 	bridge->funcs = &edp_bridge_funcs;
93 
94 	ret = drm_bridge_attach(edp->encoder, bridge, NULL);
95 	if (ret)
96 		goto fail;
97 
98 	return bridge;
99 
100 fail:
101 	if (bridge)
102 		edp_bridge_destroy(bridge);
103 
104 	return ERR_PTR(ret);
105 }
106