1 /*
2  * Copyright (c) 2014-2015, The Linux Foundation. All rights reserved.
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License version 2 and
6  * only version 2 as published by the Free Software Foundation.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11  * GNU General Public License for more details.
12  */
13 
14 #include "edp.h"
15 
16 struct edp_bridge {
17 	struct drm_bridge base;
18 	struct msm_edp *edp;
19 };
20 #define to_edp_bridge(x) container_of(x, struct edp_bridge, base)
21 
edp_bridge_destroy(struct drm_bridge * bridge)22 void edp_bridge_destroy(struct drm_bridge *bridge)
23 {
24 }
25 
edp_bridge_pre_enable(struct drm_bridge * bridge)26 static void edp_bridge_pre_enable(struct drm_bridge *bridge)
27 {
28 	struct edp_bridge *edp_bridge = to_edp_bridge(bridge);
29 	struct msm_edp *edp = edp_bridge->edp;
30 
31 	DBG("");
32 	msm_edp_ctrl_power(edp->ctrl, true);
33 }
34 
edp_bridge_enable(struct drm_bridge * bridge)35 static void edp_bridge_enable(struct drm_bridge *bridge)
36 {
37 	DBG("");
38 }
39 
edp_bridge_disable(struct drm_bridge * bridge)40 static void edp_bridge_disable(struct drm_bridge *bridge)
41 {
42 	DBG("");
43 }
44 
edp_bridge_post_disable(struct drm_bridge * bridge)45 static void edp_bridge_post_disable(struct drm_bridge *bridge)
46 {
47 	struct edp_bridge *edp_bridge = to_edp_bridge(bridge);
48 	struct msm_edp *edp = edp_bridge->edp;
49 
50 	DBG("");
51 	msm_edp_ctrl_power(edp->ctrl, false);
52 }
53 
edp_bridge_mode_set(struct drm_bridge * bridge,struct drm_display_mode * mode,struct drm_display_mode * adjusted_mode)54 static void edp_bridge_mode_set(struct drm_bridge *bridge,
55 		struct drm_display_mode *mode,
56 		struct drm_display_mode *adjusted_mode)
57 {
58 	struct drm_device *dev = bridge->dev;
59 	struct drm_connector *connector;
60 	struct edp_bridge *edp_bridge = to_edp_bridge(bridge);
61 	struct msm_edp *edp = edp_bridge->edp;
62 
63 	DBG("set mode: %d:\"%s\" %d %d %d %d %d %d %d %d %d %d 0x%x 0x%x",
64 			mode->base.id, mode->name,
65 			mode->vrefresh, mode->clock,
66 			mode->hdisplay, mode->hsync_start,
67 			mode->hsync_end, mode->htotal,
68 			mode->vdisplay, mode->vsync_start,
69 			mode->vsync_end, mode->vtotal,
70 			mode->type, mode->flags);
71 
72 	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
73 		if ((connector->encoder != NULL) &&
74 			(connector->encoder->bridge == bridge)) {
75 			msm_edp_ctrl_timing_cfg(edp->ctrl,
76 				adjusted_mode, &connector->display_info);
77 			break;
78 		}
79 	}
80 }
81 
82 static const struct drm_bridge_funcs edp_bridge_funcs = {
83 	.pre_enable = edp_bridge_pre_enable,
84 	.enable = edp_bridge_enable,
85 	.disable = edp_bridge_disable,
86 	.post_disable = edp_bridge_post_disable,
87 	.mode_set = edp_bridge_mode_set,
88 };
89 
90 /* initialize bridge */
msm_edp_bridge_init(struct msm_edp * edp)91 struct drm_bridge *msm_edp_bridge_init(struct msm_edp *edp)
92 {
93 	struct drm_bridge *bridge = NULL;
94 	struct edp_bridge *edp_bridge;
95 	int ret;
96 
97 	edp_bridge = devm_kzalloc(edp->dev->dev,
98 			sizeof(*edp_bridge), GFP_KERNEL);
99 	if (!edp_bridge) {
100 		ret = -ENOMEM;
101 		goto fail;
102 	}
103 
104 	edp_bridge->edp = edp;
105 
106 	bridge = &edp_bridge->base;
107 	bridge->funcs = &edp_bridge_funcs;
108 
109 	ret = drm_bridge_attach(edp->encoder, bridge, NULL);
110 	if (ret)
111 		goto fail;
112 
113 	return bridge;
114 
115 fail:
116 	if (bridge)
117 		edp_bridge_destroy(bridge);
118 
119 	return ERR_PTR(ret);
120 }
121