xref: /linux/drivers/gpu/drm/msm/dsi/dsi.c (revision ec31abf6684ebe1134eb3320c96fb92e566eff74)
1 /*
2  * Copyright (c) 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 "dsi.h"
15 
16 struct drm_encoder *msm_dsi_get_encoder(struct msm_dsi *msm_dsi)
17 {
18 	if (!msm_dsi || !msm_dsi->panel)
19 		return NULL;
20 
21 	return (msm_dsi->panel_flags & MIPI_DSI_MODE_VIDEO) ?
22 		msm_dsi->encoders[MSM_DSI_VIDEO_ENCODER_ID] :
23 		msm_dsi->encoders[MSM_DSI_CMD_ENCODER_ID];
24 }
25 
26 static int dsi_get_phy(struct msm_dsi *msm_dsi)
27 {
28 	struct platform_device *pdev = msm_dsi->pdev;
29 	struct platform_device *phy_pdev;
30 	struct device_node *phy_node;
31 
32 	phy_node = of_parse_phandle(pdev->dev.of_node, "qcom,dsi-phy", 0);
33 	if (!phy_node) {
34 		dev_err(&pdev->dev, "cannot find phy device\n");
35 		return -ENXIO;
36 	}
37 
38 	phy_pdev = of_find_device_by_node(phy_node);
39 	if (phy_pdev)
40 		msm_dsi->phy = platform_get_drvdata(phy_pdev);
41 
42 	of_node_put(phy_node);
43 
44 	if (!phy_pdev || !msm_dsi->phy) {
45 		dev_err(&pdev->dev, "%s: phy driver is not ready\n", __func__);
46 		return -EPROBE_DEFER;
47 	}
48 
49 	msm_dsi->phy_dev = get_device(&phy_pdev->dev);
50 
51 	return 0;
52 }
53 
54 static void dsi_destroy(struct msm_dsi *msm_dsi)
55 {
56 	if (!msm_dsi)
57 		return;
58 
59 	msm_dsi_manager_unregister(msm_dsi);
60 
61 	if (msm_dsi->phy_dev) {
62 		put_device(msm_dsi->phy_dev);
63 		msm_dsi->phy = NULL;
64 		msm_dsi->phy_dev = NULL;
65 	}
66 
67 	if (msm_dsi->host) {
68 		msm_dsi_host_destroy(msm_dsi->host);
69 		msm_dsi->host = NULL;
70 	}
71 
72 	platform_set_drvdata(msm_dsi->pdev, NULL);
73 }
74 
75 static struct msm_dsi *dsi_init(struct platform_device *pdev)
76 {
77 	struct msm_dsi *msm_dsi = NULL;
78 	int ret;
79 
80 	if (!pdev) {
81 		ret = -ENXIO;
82 		goto fail;
83 	}
84 
85 	msm_dsi = devm_kzalloc(&pdev->dev, sizeof(*msm_dsi), GFP_KERNEL);
86 	if (!msm_dsi) {
87 		ret = -ENOMEM;
88 		goto fail;
89 	}
90 	DBG("dsi probed=%p", msm_dsi);
91 
92 	msm_dsi->pdev = pdev;
93 	platform_set_drvdata(pdev, msm_dsi);
94 
95 	/* Init dsi host */
96 	ret = msm_dsi_host_init(msm_dsi);
97 	if (ret)
98 		goto fail;
99 
100 	/* GET dsi PHY */
101 	ret = dsi_get_phy(msm_dsi);
102 	if (ret)
103 		goto fail;
104 
105 	/* Register to dsi manager */
106 	ret = msm_dsi_manager_register(msm_dsi);
107 	if (ret)
108 		goto fail;
109 
110 	return msm_dsi;
111 
112 fail:
113 	if (msm_dsi)
114 		dsi_destroy(msm_dsi);
115 
116 	return ERR_PTR(ret);
117 }
118 
119 static int dsi_bind(struct device *dev, struct device *master, void *data)
120 {
121 	struct drm_device *drm = dev_get_drvdata(master);
122 	struct msm_drm_private *priv = drm->dev_private;
123 	struct platform_device *pdev = to_platform_device(dev);
124 	struct msm_dsi *msm_dsi;
125 
126 	DBG("");
127 	msm_dsi = dsi_init(pdev);
128 	if (IS_ERR(msm_dsi))
129 		return PTR_ERR(msm_dsi);
130 
131 	priv->dsi[msm_dsi->id] = msm_dsi;
132 
133 	return 0;
134 }
135 
136 static void dsi_unbind(struct device *dev, struct device *master,
137 		void *data)
138 {
139 	struct drm_device *drm = dev_get_drvdata(master);
140 	struct msm_drm_private *priv = drm->dev_private;
141 	struct msm_dsi *msm_dsi = dev_get_drvdata(dev);
142 	int id = msm_dsi->id;
143 
144 	if (priv->dsi[id]) {
145 		dsi_destroy(msm_dsi);
146 		priv->dsi[id] = NULL;
147 	}
148 }
149 
150 static const struct component_ops dsi_ops = {
151 	.bind   = dsi_bind,
152 	.unbind = dsi_unbind,
153 };
154 
155 static int dsi_dev_probe(struct platform_device *pdev)
156 {
157 	return component_add(&pdev->dev, &dsi_ops);
158 }
159 
160 static int dsi_dev_remove(struct platform_device *pdev)
161 {
162 	DBG("");
163 	component_del(&pdev->dev, &dsi_ops);
164 	return 0;
165 }
166 
167 static const struct of_device_id dt_match[] = {
168 	{ .compatible = "qcom,mdss-dsi-ctrl" },
169 	{}
170 };
171 
172 static struct platform_driver dsi_driver = {
173 	.probe = dsi_dev_probe,
174 	.remove = dsi_dev_remove,
175 	.driver = {
176 		.name = "msm_dsi",
177 		.of_match_table = dt_match,
178 	},
179 };
180 
181 void __init msm_dsi_register(void)
182 {
183 	DBG("");
184 	msm_dsi_phy_driver_register();
185 	platform_driver_register(&dsi_driver);
186 }
187 
188 void __exit msm_dsi_unregister(void)
189 {
190 	DBG("");
191 	msm_dsi_phy_driver_unregister();
192 	platform_driver_unregister(&dsi_driver);
193 }
194 
195 int msm_dsi_modeset_init(struct msm_dsi *msm_dsi, struct drm_device *dev,
196 		struct drm_encoder *encoders[MSM_DSI_ENCODER_NUM])
197 {
198 	struct msm_drm_private *priv = dev->dev_private;
199 	int ret, i;
200 
201 	if (WARN_ON(!encoders[MSM_DSI_VIDEO_ENCODER_ID] ||
202 		!encoders[MSM_DSI_CMD_ENCODER_ID]))
203 		return -EINVAL;
204 
205 	msm_dsi->dev = dev;
206 
207 	ret = msm_dsi_host_modeset_init(msm_dsi->host, dev);
208 	if (ret) {
209 		dev_err(dev->dev, "failed to modeset init host: %d\n", ret);
210 		goto fail;
211 	}
212 
213 	msm_dsi->bridge = msm_dsi_manager_bridge_init(msm_dsi->id);
214 	if (IS_ERR(msm_dsi->bridge)) {
215 		ret = PTR_ERR(msm_dsi->bridge);
216 		dev_err(dev->dev, "failed to create dsi bridge: %d\n", ret);
217 		msm_dsi->bridge = NULL;
218 		goto fail;
219 	}
220 
221 	for (i = 0; i < MSM_DSI_ENCODER_NUM; i++) {
222 		encoders[i]->bridge = msm_dsi->bridge;
223 		msm_dsi->encoders[i] = encoders[i];
224 	}
225 
226 	msm_dsi->connector = msm_dsi_manager_connector_init(msm_dsi->id);
227 	if (IS_ERR(msm_dsi->connector)) {
228 		ret = PTR_ERR(msm_dsi->connector);
229 		dev_err(dev->dev, "failed to create dsi connector: %d\n", ret);
230 		msm_dsi->connector = NULL;
231 		goto fail;
232 	}
233 
234 	priv->bridges[priv->num_bridges++]       = msm_dsi->bridge;
235 	priv->connectors[priv->num_connectors++] = msm_dsi->connector;
236 
237 	return 0;
238 fail:
239 	if (msm_dsi) {
240 		/* bridge/connector are normally destroyed by drm: */
241 		if (msm_dsi->bridge) {
242 			msm_dsi_manager_bridge_destroy(msm_dsi->bridge);
243 			msm_dsi->bridge = NULL;
244 		}
245 		if (msm_dsi->connector) {
246 			msm_dsi->connector->funcs->destroy(msm_dsi->connector);
247 			msm_dsi->connector = NULL;
248 		}
249 	}
250 
251 	return ret;
252 }
253 
254