2 * Copyright (c) 2015, The Linux Foundation. All rights reserved.
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.
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.
16 struct drm_encoder
*msm_dsi_get_encoder(struct msm_dsi
*msm_dsi
)
18 if (!msm_dsi
|| !msm_dsi_device_connected(msm_dsi
))
21 return (msm_dsi
->device_flags
& MIPI_DSI_MODE_VIDEO
) ?
22 msm_dsi
->encoders
[MSM_DSI_VIDEO_ENCODER_ID
] :
23 msm_dsi
->encoders
[MSM_DSI_CMD_ENCODER_ID
];
26 static int dsi_get_phy(struct msm_dsi
*msm_dsi
)
28 struct platform_device
*pdev
= msm_dsi
->pdev
;
29 struct platform_device
*phy_pdev
;
30 struct device_node
*phy_node
;
32 phy_node
= of_parse_phandle(pdev
->dev
.of_node
, "qcom,dsi-phy", 0);
34 dev_err(&pdev
->dev
, "cannot find phy device\n");
38 phy_pdev
= of_find_device_by_node(phy_node
);
40 msm_dsi
->phy
= platform_get_drvdata(phy_pdev
);
42 of_node_put(phy_node
);
44 if (!phy_pdev
|| !msm_dsi
->phy
) {
45 dev_err(&pdev
->dev
, "%s: phy driver is not ready\n", __func__
);
49 msm_dsi
->phy_dev
= get_device(&phy_pdev
->dev
);
54 static void dsi_destroy(struct msm_dsi
*msm_dsi
)
59 msm_dsi_manager_unregister(msm_dsi
);
61 if (msm_dsi
->phy_dev
) {
62 put_device(msm_dsi
->phy_dev
);
64 msm_dsi
->phy_dev
= NULL
;
68 msm_dsi_host_destroy(msm_dsi
->host
);
72 platform_set_drvdata(msm_dsi
->pdev
, NULL
);
75 static struct msm_dsi
*dsi_init(struct platform_device
*pdev
)
77 struct msm_dsi
*msm_dsi
;
81 return ERR_PTR(-ENXIO
);
83 msm_dsi
= devm_kzalloc(&pdev
->dev
, sizeof(*msm_dsi
), GFP_KERNEL
);
85 return ERR_PTR(-ENOMEM
);
86 DBG("dsi probed=%p", msm_dsi
);
89 platform_set_drvdata(pdev
, msm_dsi
);
92 ret
= msm_dsi_host_init(msm_dsi
);
97 ret
= dsi_get_phy(msm_dsi
);
101 /* Register to dsi manager */
102 ret
= msm_dsi_manager_register(msm_dsi
);
109 dsi_destroy(msm_dsi
);
113 static int dsi_bind(struct device
*dev
, struct device
*master
, void *data
)
115 struct drm_device
*drm
= dev_get_drvdata(master
);
116 struct msm_drm_private
*priv
= drm
->dev_private
;
117 struct platform_device
*pdev
= to_platform_device(dev
);
118 struct msm_dsi
*msm_dsi
;
121 msm_dsi
= dsi_init(pdev
);
123 return PTR_ERR(msm_dsi
);
125 priv
->dsi
[msm_dsi
->id
] = msm_dsi
;
130 static void dsi_unbind(struct device
*dev
, struct device
*master
,
133 struct drm_device
*drm
= dev_get_drvdata(master
);
134 struct msm_drm_private
*priv
= drm
->dev_private
;
135 struct msm_dsi
*msm_dsi
= dev_get_drvdata(dev
);
136 int id
= msm_dsi
->id
;
139 dsi_destroy(msm_dsi
);
140 priv
->dsi
[id
] = NULL
;
144 static const struct component_ops dsi_ops
= {
146 .unbind
= dsi_unbind
,
149 static int dsi_dev_probe(struct platform_device
*pdev
)
151 return component_add(&pdev
->dev
, &dsi_ops
);
154 static int dsi_dev_remove(struct platform_device
*pdev
)
157 component_del(&pdev
->dev
, &dsi_ops
);
161 static const struct of_device_id dt_match
[] = {
162 { .compatible
= "qcom,mdss-dsi-ctrl" },
166 static struct platform_driver dsi_driver
= {
167 .probe
= dsi_dev_probe
,
168 .remove
= dsi_dev_remove
,
171 .of_match_table
= dt_match
,
175 void __init
msm_dsi_register(void)
178 msm_dsi_phy_driver_register();
179 platform_driver_register(&dsi_driver
);
182 void __exit
msm_dsi_unregister(void)
185 msm_dsi_phy_driver_unregister();
186 platform_driver_unregister(&dsi_driver
);
189 int msm_dsi_modeset_init(struct msm_dsi
*msm_dsi
, struct drm_device
*dev
,
190 struct drm_encoder
*encoders
[MSM_DSI_ENCODER_NUM
])
192 struct msm_drm_private
*priv
= dev
->dev_private
;
193 struct drm_bridge
*ext_bridge
;
196 if (WARN_ON(!encoders
[MSM_DSI_VIDEO_ENCODER_ID
] ||
197 !encoders
[MSM_DSI_CMD_ENCODER_ID
]))
202 ret
= msm_dsi_host_modeset_init(msm_dsi
->host
, dev
);
204 dev_err(dev
->dev
, "failed to modeset init host: %d\n", ret
);
208 msm_dsi
->bridge
= msm_dsi_manager_bridge_init(msm_dsi
->id
);
209 if (IS_ERR(msm_dsi
->bridge
)) {
210 ret
= PTR_ERR(msm_dsi
->bridge
);
211 dev_err(dev
->dev
, "failed to create dsi bridge: %d\n", ret
);
212 msm_dsi
->bridge
= NULL
;
216 for (i
= 0; i
< MSM_DSI_ENCODER_NUM
; i
++) {
217 encoders
[i
]->bridge
= msm_dsi
->bridge
;
218 msm_dsi
->encoders
[i
] = encoders
[i
];
222 * check if the dsi encoder output is connected to a panel or an
223 * external bridge. We create a connector only if we're connected to a
224 * drm_panel device. When we're connected to an external bridge, we
225 * assume that the drm_bridge driver will create the connector itself.
227 ext_bridge
= msm_dsi_host_get_bridge(msm_dsi
->host
);
231 msm_dsi_manager_ext_bridge_init(msm_dsi
->id
);
234 msm_dsi_manager_connector_init(msm_dsi
->id
);
236 if (IS_ERR(msm_dsi
->connector
)) {
237 ret
= PTR_ERR(msm_dsi
->connector
);
239 "failed to create dsi connector: %d\n", ret
);
240 msm_dsi
->connector
= NULL
;
244 priv
->bridges
[priv
->num_bridges
++] = msm_dsi
->bridge
;
245 priv
->connectors
[priv
->num_connectors
++] = msm_dsi
->connector
;
250 /* bridge/connector are normally destroyed by drm: */
251 if (msm_dsi
->bridge
) {
252 msm_dsi_manager_bridge_destroy(msm_dsi
->bridge
);
253 msm_dsi
->bridge
= NULL
;
256 /* don't destroy connector if we didn't make it */
257 if (msm_dsi
->connector
&& !msm_dsi
->external_bridge
)
258 msm_dsi
->connector
->funcs
->destroy(msm_dsi
->connector
);
260 msm_dsi
->connector
= NULL
;