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
8struct 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
14void edp_bridge_destroy(struct drm_bridge *bridge)
15{
16}
17
18static 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
27static void edp_bridge_enable(struct drm_bridge *bridge)
28{
29	DBG("");
30}
31
32static void edp_bridge_disable(struct drm_bridge *bridge)
33{
34	DBG("");
35}
36
37static 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
46static 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		struct drm_encoder *encoder = connector->encoder;
59		struct drm_bridge *first_bridge;
60
61		if (!connector->encoder)
62			continue;
63
64		first_bridge = drm_bridge_chain_get_first_bridge(encoder);
65		if (bridge == first_bridge) {
66			msm_edp_ctrl_timing_cfg(edp->ctrl,
67				adjusted_mode, &connector->display_info);
68			break;
69		}
70	}
71}
72
73static const struct drm_bridge_funcs edp_bridge_funcs = {
74	.pre_enable = edp_bridge_pre_enable,
75	.enable = edp_bridge_enable,
76	.disable = edp_bridge_disable,
77	.post_disable = edp_bridge_post_disable,
78	.mode_set = edp_bridge_mode_set,
79};
80
81/* initialize bridge */
82struct drm_bridge *msm_edp_bridge_init(struct msm_edp *edp)
83{
84	struct drm_bridge *bridge = NULL;
85	struct edp_bridge *edp_bridge;
86	int ret;
87
88	edp_bridge = devm_kzalloc(edp->dev->dev,
89			sizeof(*edp_bridge), GFP_KERNEL);
90	if (!edp_bridge) {
91		ret = -ENOMEM;
92		goto fail;
93	}
94
95	edp_bridge->edp = edp;
96
97	bridge = &edp_bridge->base;
98	bridge->funcs = &edp_bridge_funcs;
99
100	ret = drm_bridge_attach(edp->encoder, bridge, NULL, 0);
101	if (ret)
102		goto fail;
103
104	return bridge;
105
106fail:
107	if (bridge)
108		edp_bridge_destroy(bridge);
109
110	return ERR_PTR(ret);
111}
112