xref: /linux/drivers/gpu/drm/adp/adp-mipi.c (revision 3a2c4d55e32ad65efebdb6de44eef3bfa08bb49d)
1 // SPDX-License-Identifier: GPL-2.0-only
2 
3 #include <linux/component.h>
4 #include <linux/iopoll.h>
5 #include <linux/of.h>
6 #include <linux/platform_device.h>
7 
8 #include <drm/drm_atomic_state_helper.h>
9 #include <drm/drm_bridge.h>
10 #include <drm/drm_mipi_dsi.h>
11 
12 #define DSI_GEN_HDR 0x6c
13 #define DSI_GEN_PLD_DATA 0x70
14 
15 #define DSI_CMD_PKT_STATUS 0x74
16 
17 #define GEN_PLD_R_EMPTY BIT(4)
18 #define GEN_PLD_W_FULL BIT(3)
19 #define GEN_PLD_W_EMPTY BIT(2)
20 #define GEN_CMD_FULL BIT(1)
21 #define GEN_CMD_EMPTY BIT(0)
22 #define GEN_RD_CMD_BUSY BIT(6)
23 #define CMD_PKT_STATUS_TIMEOUT_US 20000
24 
25 struct adp_mipi_drv_private {
26 	struct mipi_dsi_host dsi;
27 	struct drm_bridge bridge;
28 	struct drm_bridge *next_bridge;
29 	void __iomem *mipi;
30 };
31 
32 #define mipi_to_adp(x) container_of(x, struct adp_mipi_drv_private, dsi)
33 
34 static int adp_dsi_gen_pkt_hdr_write(struct adp_mipi_drv_private *adp, u32 hdr_val)
35 {
36 	int ret;
37 	u32 val, mask;
38 
39 	ret = readl_poll_timeout(adp->mipi + DSI_CMD_PKT_STATUS,
40 				 val, !(val & GEN_CMD_FULL), 1000,
41 				 CMD_PKT_STATUS_TIMEOUT_US);
42 	if (ret) {
43 		dev_err(adp->dsi.dev, "failed to get available command FIFO\n");
44 		return ret;
45 	}
46 
47 	writel(hdr_val, adp->mipi + DSI_GEN_HDR);
48 
49 	mask = GEN_CMD_EMPTY | GEN_PLD_W_EMPTY;
50 	ret = readl_poll_timeout(adp->mipi + DSI_CMD_PKT_STATUS,
51 				 val, (val & mask) == mask,
52 				 1000, CMD_PKT_STATUS_TIMEOUT_US);
53 	if (ret) {
54 		dev_err(adp->dsi.dev, "failed to write command FIFO\n");
55 		return ret;
56 	}
57 
58 	return 0;
59 }
60 
61 static int adp_dsi_write(struct adp_mipi_drv_private *adp,
62 			 const struct mipi_dsi_packet *packet)
63 {
64 	const u8 *tx_buf = packet->payload;
65 	int len = packet->payload_length, pld_data_bytes = sizeof(u32), ret;
66 	__le32 word;
67 	u32 val;
68 
69 	while (len) {
70 		if (len < pld_data_bytes) {
71 			word = 0;
72 			memcpy(&word, tx_buf, len);
73 			writel(le32_to_cpu(word), adp->mipi + DSI_GEN_PLD_DATA);
74 			len = 0;
75 		} else {
76 			memcpy(&word, tx_buf, pld_data_bytes);
77 			writel(le32_to_cpu(word), adp->mipi + DSI_GEN_PLD_DATA);
78 			tx_buf += pld_data_bytes;
79 			len -= pld_data_bytes;
80 		}
81 
82 		ret = readl_poll_timeout(adp->mipi + DSI_CMD_PKT_STATUS,
83 					 val, !(val & GEN_PLD_W_FULL), 1000,
84 					 CMD_PKT_STATUS_TIMEOUT_US);
85 		if (ret) {
86 			dev_err(adp->dsi.dev,
87 				"failed to get available write payload FIFO\n");
88 			return ret;
89 		}
90 	}
91 
92 	word = 0;
93 	memcpy(&word, packet->header, sizeof(packet->header));
94 	return adp_dsi_gen_pkt_hdr_write(adp, le32_to_cpu(word));
95 }
96 
97 static int adp_dsi_read(struct adp_mipi_drv_private *adp,
98 			const struct mipi_dsi_msg *msg)
99 {
100 	int i, j, ret, len = msg->rx_len;
101 	u8 *buf = msg->rx_buf;
102 	u32 val;
103 
104 	/* Wait end of the read operation */
105 	ret = readl_poll_timeout(adp->mipi + DSI_CMD_PKT_STATUS,
106 				 val, !(val & GEN_RD_CMD_BUSY),
107 				 1000, CMD_PKT_STATUS_TIMEOUT_US);
108 	if (ret) {
109 		dev_err(adp->dsi.dev, "Timeout during read operation\n");
110 		return ret;
111 	}
112 
113 	for (i = 0; i < len; i += 4) {
114 		/* Read fifo must not be empty before all bytes are read */
115 		ret = readl_poll_timeout(adp->mipi + DSI_CMD_PKT_STATUS,
116 					 val, !(val & GEN_PLD_R_EMPTY),
117 					 1000, CMD_PKT_STATUS_TIMEOUT_US);
118 		if (ret) {
119 			dev_err(adp->dsi.dev, "Read payload FIFO is empty\n");
120 			return ret;
121 		}
122 
123 		val = readl(adp->mipi + DSI_GEN_PLD_DATA);
124 		for (j = 0; j < 4 && j + i < len; j++)
125 			buf[i + j] = val >> (8 * j);
126 	}
127 
128 	return ret;
129 }
130 
131 static ssize_t adp_dsi_host_transfer(struct mipi_dsi_host *host,
132 				     const struct mipi_dsi_msg *msg)
133 {
134 	struct adp_mipi_drv_private *adp = mipi_to_adp(host);
135 	struct mipi_dsi_packet packet;
136 	int ret, nb_bytes;
137 
138 	ret = mipi_dsi_create_packet(&packet, msg);
139 	if (ret) {
140 		dev_err(adp->dsi.dev, "failed to create packet: %d\n", ret);
141 		return ret;
142 	}
143 
144 	ret = adp_dsi_write(adp, &packet);
145 	if (ret)
146 		return ret;
147 
148 	if (msg->rx_buf && msg->rx_len) {
149 		ret = adp_dsi_read(adp, msg);
150 		if (ret)
151 			return ret;
152 		nb_bytes = msg->rx_len;
153 	} else {
154 		nb_bytes = packet.size;
155 	}
156 
157 	return nb_bytes;
158 }
159 
160 static int adp_dsi_bind(struct device *dev, struct device *master, void *data)
161 {
162 	return 0;
163 }
164 
165 static void adp_dsi_unbind(struct device *dev, struct device *master, void *data)
166 {
167 }
168 
169 static const struct component_ops adp_dsi_component_ops = {
170 	.bind	= adp_dsi_bind,
171 	.unbind	= adp_dsi_unbind,
172 };
173 
174 static int adp_dsi_host_attach(struct mipi_dsi_host *host,
175 			       struct mipi_dsi_device *dev)
176 {
177 	struct adp_mipi_drv_private *adp = mipi_to_adp(host);
178 	struct drm_bridge *next;
179 	int ret;
180 
181 	next = devm_drm_of_get_bridge(adp->dsi.dev, adp->dsi.dev->of_node, 1, 0);
182 	if (IS_ERR(next))
183 		return PTR_ERR(next);
184 
185 	adp->next_bridge = next;
186 
187 	drm_bridge_add(&adp->bridge);
188 
189 	ret = component_add(host->dev, &adp_dsi_component_ops);
190 	if (ret) {
191 		pr_err("failed to add dsi_host component: %d\n", ret);
192 		drm_bridge_remove(&adp->bridge);
193 		return ret;
194 	}
195 
196 	return 0;
197 }
198 
199 static int adp_dsi_host_detach(struct mipi_dsi_host *host,
200 			       struct mipi_dsi_device *dev)
201 {
202 	struct adp_mipi_drv_private *adp = mipi_to_adp(host);
203 
204 	component_del(host->dev, &adp_dsi_component_ops);
205 	drm_bridge_remove(&adp->bridge);
206 	return 0;
207 }
208 
209 static const struct mipi_dsi_host_ops adp_dsi_host_ops = {
210 	.transfer = adp_dsi_host_transfer,
211 	.attach = adp_dsi_host_attach,
212 	.detach = adp_dsi_host_detach,
213 };
214 
215 static int adp_dsi_bridge_attach(struct drm_bridge *bridge,
216 				 struct drm_encoder *encoder,
217 				 enum drm_bridge_attach_flags flags)
218 {
219 	struct adp_mipi_drv_private *adp =
220 		container_of(bridge, struct adp_mipi_drv_private, bridge);
221 
222 	return drm_bridge_attach(encoder, adp->next_bridge, bridge, flags);
223 }
224 
225 static const struct drm_bridge_funcs adp_dsi_bridge_funcs = {
226 	.atomic_create_state = drm_atomic_helper_bridge_create_state,
227 	.atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
228 	.atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
229 	.attach	= adp_dsi_bridge_attach,
230 };
231 
232 static int adp_mipi_probe(struct platform_device *pdev)
233 {
234 	struct adp_mipi_drv_private *adp;
235 
236 	adp = devm_drm_bridge_alloc(&pdev->dev, struct adp_mipi_drv_private,
237 				    bridge, &adp_dsi_bridge_funcs);
238 	if (IS_ERR(adp))
239 		return PTR_ERR(adp);
240 
241 	adp->mipi = devm_platform_ioremap_resource(pdev, 0);
242 	if (IS_ERR(adp->mipi)) {
243 		dev_err(&pdev->dev, "failed to map mipi mmio");
244 		return PTR_ERR(adp->mipi);
245 	}
246 
247 	adp->dsi.dev = &pdev->dev;
248 	adp->dsi.ops = &adp_dsi_host_ops;
249 	adp->bridge.of_node = pdev->dev.of_node;
250 	adp->bridge.type = DRM_MODE_CONNECTOR_DSI;
251 	dev_set_drvdata(&pdev->dev, adp);
252 	return mipi_dsi_host_register(&adp->dsi);
253 }
254 
255 static void adp_mipi_remove(struct platform_device *pdev)
256 {
257 	struct device *dev = &pdev->dev;
258 	struct adp_mipi_drv_private *adp = dev_get_drvdata(dev);
259 
260 	mipi_dsi_host_unregister(&adp->dsi);
261 }
262 
263 static const struct of_device_id adp_mipi_of_match[] = {
264 	{ .compatible = "apple,h7-display-pipe-mipi", },
265 	{ },
266 };
267 MODULE_DEVICE_TABLE(of, adp_mipi_of_match);
268 
269 static struct platform_driver adp_mipi_platform_driver = {
270 	.driver = {
271 		.name = "adp-mipi",
272 		.of_match_table = adp_mipi_of_match,
273 	},
274 	.probe = adp_mipi_probe,
275 	.remove = adp_mipi_remove,
276 };
277 
278 module_platform_driver(adp_mipi_platform_driver);
279 
280 MODULE_DESCRIPTION("Apple Display Pipe MIPI driver");
281 MODULE_LICENSE("GPL");
282