Merge tag 'drm-misc-next-2019-10-09-2' of git://anongit.freedesktop.org/drm/drm-misc...
[linux-2.6-microblaze.git] / drivers / gpu / drm / msm / edp / edp.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright (c) 2014-2015, The Linux Foundation. All rights reserved.
4  */
5
6 #include <linux/of_irq.h>
7 #include "edp.h"
8
9 static irqreturn_t edp_irq(int irq, void *dev_id)
10 {
11         struct msm_edp *edp = dev_id;
12
13         /* Process eDP irq */
14         return msm_edp_ctrl_irq(edp->ctrl);
15 }
16
17 static void edp_destroy(struct platform_device *pdev)
18 {
19         struct msm_edp *edp = platform_get_drvdata(pdev);
20
21         if (!edp)
22                 return;
23
24         if (edp->ctrl) {
25                 msm_edp_ctrl_destroy(edp->ctrl);
26                 edp->ctrl = NULL;
27         }
28
29         platform_set_drvdata(pdev, NULL);
30 }
31
32 /* construct eDP at bind/probe time, grab all the resources. */
33 static struct msm_edp *edp_init(struct platform_device *pdev)
34 {
35         struct msm_edp *edp = NULL;
36         int ret;
37
38         if (!pdev) {
39                 pr_err("no eDP device\n");
40                 ret = -ENXIO;
41                 goto fail;
42         }
43
44         edp = devm_kzalloc(&pdev->dev, sizeof(*edp), GFP_KERNEL);
45         if (!edp) {
46                 ret = -ENOMEM;
47                 goto fail;
48         }
49         DBG("eDP probed=%p", edp);
50
51         edp->pdev = pdev;
52         platform_set_drvdata(pdev, edp);
53
54         ret = msm_edp_ctrl_init(edp);
55         if (ret)
56                 goto fail;
57
58         return edp;
59
60 fail:
61         if (edp)
62                 edp_destroy(pdev);
63
64         return ERR_PTR(ret);
65 }
66
67 static int edp_bind(struct device *dev, struct device *master, void *data)
68 {
69         struct drm_device *drm = dev_get_drvdata(master);
70         struct msm_drm_private *priv = drm->dev_private;
71         struct msm_edp *edp;
72
73         DBG("");
74         edp = edp_init(to_platform_device(dev));
75         if (IS_ERR(edp))
76                 return PTR_ERR(edp);
77         priv->edp = edp;
78
79         return 0;
80 }
81
82 static void edp_unbind(struct device *dev, struct device *master, void *data)
83 {
84         struct drm_device *drm = dev_get_drvdata(master);
85         struct msm_drm_private *priv = drm->dev_private;
86
87         DBG("");
88         if (priv->edp) {
89                 edp_destroy(to_platform_device(dev));
90                 priv->edp = NULL;
91         }
92 }
93
94 static const struct component_ops edp_ops = {
95                 .bind   = edp_bind,
96                 .unbind = edp_unbind,
97 };
98
99 static int edp_dev_probe(struct platform_device *pdev)
100 {
101         DBG("");
102         return component_add(&pdev->dev, &edp_ops);
103 }
104
105 static int edp_dev_remove(struct platform_device *pdev)
106 {
107         DBG("");
108         component_del(&pdev->dev, &edp_ops);
109         return 0;
110 }
111
112 static const struct of_device_id dt_match[] = {
113         { .compatible = "qcom,mdss-edp" },
114         {}
115 };
116
117 static struct platform_driver edp_driver = {
118         .probe = edp_dev_probe,
119         .remove = edp_dev_remove,
120         .driver = {
121                 .name = "msm_edp",
122                 .of_match_table = dt_match,
123         },
124 };
125
126 void __init msm_edp_register(void)
127 {
128         DBG("");
129         platform_driver_register(&edp_driver);
130 }
131
132 void __exit msm_edp_unregister(void)
133 {
134         DBG("");
135         platform_driver_unregister(&edp_driver);
136 }
137
138 /* Second part of initialization, the drm/kms level modeset_init */
139 int msm_edp_modeset_init(struct msm_edp *edp, struct drm_device *dev,
140                                 struct drm_encoder *encoder)
141 {
142         struct platform_device *pdev = edp->pdev;
143         struct msm_drm_private *priv = dev->dev_private;
144         int ret;
145
146         edp->encoder = encoder;
147         edp->dev = dev;
148
149         edp->bridge = msm_edp_bridge_init(edp);
150         if (IS_ERR(edp->bridge)) {
151                 ret = PTR_ERR(edp->bridge);
152                 DRM_DEV_ERROR(dev->dev, "failed to create eDP bridge: %d\n", ret);
153                 edp->bridge = NULL;
154                 goto fail;
155         }
156
157         edp->connector = msm_edp_connector_init(edp);
158         if (IS_ERR(edp->connector)) {
159                 ret = PTR_ERR(edp->connector);
160                 DRM_DEV_ERROR(dev->dev, "failed to create eDP connector: %d\n", ret);
161                 edp->connector = NULL;
162                 goto fail;
163         }
164
165         edp->irq = irq_of_parse_and_map(pdev->dev.of_node, 0);
166         if (edp->irq < 0) {
167                 ret = edp->irq;
168                 DRM_DEV_ERROR(dev->dev, "failed to get IRQ: %d\n", ret);
169                 goto fail;
170         }
171
172         ret = devm_request_irq(&pdev->dev, edp->irq,
173                         edp_irq, IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
174                         "edp_isr", edp);
175         if (ret < 0) {
176                 DRM_DEV_ERROR(dev->dev, "failed to request IRQ%u: %d\n",
177                                 edp->irq, ret);
178                 goto fail;
179         }
180
181         ret = drm_bridge_attach(encoder, edp->bridge, NULL);
182         if (ret)
183                 goto fail;
184
185         priv->bridges[priv->num_bridges++]       = edp->bridge;
186         priv->connectors[priv->num_connectors++] = edp->connector;
187
188         return 0;
189
190 fail:
191         /* bridge/connector are normally destroyed by drm */
192         if (edp->bridge) {
193                 edp_bridge_destroy(edp->bridge);
194                 edp->bridge = NULL;
195         }
196         if (edp->connector) {
197                 edp->connector->funcs->destroy(edp->connector);
198                 edp->connector = NULL;
199         }
200
201         return ret;
202 }