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