xref: /netbsd-src/sys/external/bsd/drm2/dist/drm/drm_mipi_dsi.c (revision 41ec02673d281bbb3d38e6c78504ce6e30c228c1)
1 /*	$NetBSD: drm_mipi_dsi.c,v 1.3 2021/12/18 23:44:57 riastradh Exp $	*/
2 
3 /*
4  * MIPI DSI Bus
5  *
6  * Copyright (C) 2012-2013, Samsung Electronics, Co., Ltd.
7  * Andrzej Hajda <a.hajda@samsung.com>
8  *
9  * Permission is hereby granted, free of charge, to any person obtaining a
10  * copy of this software and associated documentation files (the
11  * "Software"), to deal in the Software without restriction, including
12  * without limitation the rights to use, copy, modify, merge, publish,
13  * distribute, sub license, and/or sell copies of the Software, and to
14  * permit persons to whom the Software is furnished to do so, subject to
15  * the following conditions:
16  *
17  * The above copyright notice and this permission notice (including the
18  * next paragraph) shall be included in all copies or substantial portions
19  * of the Software.
20  *
21  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
24  * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
25  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
26  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
27  * USE OR OTHER DEALINGS IN THE SOFTWARE.
28  */
29 
30 #include <sys/cdefs.h>
31 __KERNEL_RCSID(0, "$NetBSD: drm_mipi_dsi.c,v 1.3 2021/12/18 23:44:57 riastradh Exp $");
32 
33 #include <drm/drm_mipi_dsi.h>
34 
35 #include <linux/device.h>
36 #include <linux/module.h>
37 #include <linux/of_device.h>
38 #include <linux/pm_runtime.h>
39 #include <linux/slab.h>
40 
41 #include <drm/drm_dsc.h>
42 #include <video/mipi_display.h>
43 
44 /**
45  * DOC: dsi helpers
46  *
47  * These functions contain some common logic and helpers to deal with MIPI DSI
48  * peripherals.
49  *
50  * Helpers are provided for a number of standard MIPI DSI command as well as a
51  * subset of the MIPI DCS command set.
52  */
53 
mipi_dsi_device_match(struct device * dev,struct device_driver * drv)54 static int mipi_dsi_device_match(struct device *dev, struct device_driver *drv)
55 {
56 	struct mipi_dsi_device *dsi = to_mipi_dsi_device(dev);
57 
58 	/* attempt OF style match */
59 	if (of_driver_match_device(dev, drv))
60 		return 1;
61 
62 	/* compare DSI device and driver names */
63 	if (!strcmp(dsi->name, drv->name))
64 		return 1;
65 
66 	return 0;
67 }
68 
mipi_dsi_uevent(struct device * dev,struct kobj_uevent_env * env)69 static int mipi_dsi_uevent(struct device *dev, struct kobj_uevent_env *env)
70 {
71 	struct mipi_dsi_device *dsi = to_mipi_dsi_device(dev);
72 	int err;
73 
74 	err = of_device_uevent_modalias(dev, env);
75 	if (err != -ENODEV)
76 		return err;
77 
78 	add_uevent_var(env, "MODALIAS=%s%s", MIPI_DSI_MODULE_PREFIX,
79 		       dsi->name);
80 
81 	return 0;
82 }
83 
84 static const struct dev_pm_ops mipi_dsi_device_pm_ops = {
85 	.runtime_suspend = pm_generic_runtime_suspend,
86 	.runtime_resume = pm_generic_runtime_resume,
87 	.suspend = pm_generic_suspend,
88 	.resume = pm_generic_resume,
89 	.freeze = pm_generic_freeze,
90 	.thaw = pm_generic_thaw,
91 	.poweroff = pm_generic_poweroff,
92 	.restore = pm_generic_restore,
93 };
94 
95 static struct bus_type mipi_dsi_bus_type = {
96 	.name = "mipi-dsi",
97 	.match = mipi_dsi_device_match,
98 	.uevent = mipi_dsi_uevent,
99 	.pm = &mipi_dsi_device_pm_ops,
100 };
101 
102 /**
103  * of_find_mipi_dsi_device_by_node() - find the MIPI DSI device matching a
104  *    device tree node
105  * @np: device tree node
106  *
107  * Return: A pointer to the MIPI DSI device corresponding to @np or NULL if no
108  *    such device exists (or has not been registered yet).
109  */
of_find_mipi_dsi_device_by_node(struct device_node * np)110 struct mipi_dsi_device *of_find_mipi_dsi_device_by_node(struct device_node *np)
111 {
112 	struct device *dev;
113 
114 	dev = bus_find_device_by_of_node(&mipi_dsi_bus_type, np);
115 
116 	return dev ? to_mipi_dsi_device(dev) : NULL;
117 }
118 EXPORT_SYMBOL(of_find_mipi_dsi_device_by_node);
119 
mipi_dsi_dev_release(struct device * dev)120 static void mipi_dsi_dev_release(struct device *dev)
121 {
122 	struct mipi_dsi_device *dsi = to_mipi_dsi_device(dev);
123 
124 	of_node_put(dev->of_node);
125 	kfree(dsi);
126 }
127 
128 static const struct device_type mipi_dsi_device_type = {
129 	.release = mipi_dsi_dev_release,
130 };
131 
mipi_dsi_device_alloc(struct mipi_dsi_host * host)132 static struct mipi_dsi_device *mipi_dsi_device_alloc(struct mipi_dsi_host *host)
133 {
134 	struct mipi_dsi_device *dsi;
135 
136 	dsi = kzalloc(sizeof(*dsi), GFP_KERNEL);
137 	if (!dsi)
138 		return ERR_PTR(-ENOMEM);
139 
140 	dsi->host = host;
141 	dsi->dev.bus = &mipi_dsi_bus_type;
142 	dsi->dev.parent = host->dev;
143 	dsi->dev.type = &mipi_dsi_device_type;
144 
145 	device_initialize(&dsi->dev);
146 
147 	return dsi;
148 }
149 
mipi_dsi_device_add(struct mipi_dsi_device * dsi)150 static int mipi_dsi_device_add(struct mipi_dsi_device *dsi)
151 {
152 	struct mipi_dsi_host *host = dsi->host;
153 
154 	dev_set_name(&dsi->dev, "%s.%d", dev_name(host->dev),  dsi->channel);
155 
156 	return device_add(&dsi->dev);
157 }
158 
159 #if IS_ENABLED(CONFIG_OF)
160 static struct mipi_dsi_device *
of_mipi_dsi_device_add(struct mipi_dsi_host * host,struct device_node * node)161 of_mipi_dsi_device_add(struct mipi_dsi_host *host, struct device_node *node)
162 {
163 	struct device *dev = host->dev;
164 	struct mipi_dsi_device_info info = { };
165 	int ret;
166 	u32 reg;
167 
168 	if (of_modalias_node(node, info.type, sizeof(info.type)) < 0) {
169 		dev_err(dev, "modalias failure on %pOF\n", node);
170 		return ERR_PTR(-EINVAL);
171 	}
172 
173 	ret = of_property_read_u32(node, "reg", &reg);
174 	if (ret) {
175 		dev_err(dev, "device node %pOF has no valid reg property: %d\n",
176 			node, ret);
177 		return ERR_PTR(-EINVAL);
178 	}
179 
180 	info.channel = reg;
181 	info.node = of_node_get(node);
182 
183 	return mipi_dsi_device_register_full(host, &info);
184 }
185 #else
186 static struct mipi_dsi_device *
of_mipi_dsi_device_add(struct mipi_dsi_host * host,struct device_node * node)187 of_mipi_dsi_device_add(struct mipi_dsi_host *host, struct device_node *node)
188 {
189 	return ERR_PTR(-ENODEV);
190 }
191 #endif
192 
193 /**
194  * mipi_dsi_device_register_full - create a MIPI DSI device
195  * @host: DSI host to which this device is connected
196  * @info: pointer to template containing DSI device information
197  *
198  * Create a MIPI DSI device by using the device information provided by
199  * mipi_dsi_device_info template
200  *
201  * Returns:
202  * A pointer to the newly created MIPI DSI device, or, a pointer encoded
203  * with an error
204  */
205 struct mipi_dsi_device *
mipi_dsi_device_register_full(struct mipi_dsi_host * host,const struct mipi_dsi_device_info * info)206 mipi_dsi_device_register_full(struct mipi_dsi_host *host,
207 			      const struct mipi_dsi_device_info *info)
208 {
209 	struct mipi_dsi_device *dsi;
210 	struct device *dev = host->dev;
211 	int ret;
212 
213 	if (!info) {
214 		dev_err(dev, "invalid mipi_dsi_device_info pointer\n");
215 		return ERR_PTR(-EINVAL);
216 	}
217 
218 	if (info->channel > 3) {
219 		dev_err(dev, "invalid virtual channel: %u\n", info->channel);
220 		return ERR_PTR(-EINVAL);
221 	}
222 
223 	dsi = mipi_dsi_device_alloc(host);
224 	if (IS_ERR(dsi)) {
225 		dev_err(dev, "failed to allocate DSI device %ld\n",
226 			PTR_ERR(dsi));
227 		return dsi;
228 	}
229 
230 	dsi->dev.of_node = info->node;
231 	dsi->channel = info->channel;
232 	strlcpy(dsi->name, info->type, sizeof(dsi->name));
233 
234 	ret = mipi_dsi_device_add(dsi);
235 	if (ret) {
236 		dev_err(dev, "failed to add DSI device %d\n", ret);
237 		kfree(dsi);
238 		return ERR_PTR(ret);
239 	}
240 
241 	return dsi;
242 }
243 EXPORT_SYMBOL(mipi_dsi_device_register_full);
244 
245 /**
246  * mipi_dsi_device_unregister - unregister MIPI DSI device
247  * @dsi: DSI peripheral device
248  */
mipi_dsi_device_unregister(struct mipi_dsi_device * dsi)249 void mipi_dsi_device_unregister(struct mipi_dsi_device *dsi)
250 {
251 	device_unregister(&dsi->dev);
252 }
253 EXPORT_SYMBOL(mipi_dsi_device_unregister);
254 
255 static DEFINE_MUTEX(host_lock);
256 static LIST_HEAD(host_list);
257 
258 /**
259  * of_find_mipi_dsi_host_by_node() - find the MIPI DSI host matching a
260  *				     device tree node
261  * @node: device tree node
262  *
263  * Returns:
264  * A pointer to the MIPI DSI host corresponding to @node or NULL if no
265  * such device exists (or has not been registered yet).
266  */
of_find_mipi_dsi_host_by_node(struct device_node * node)267 struct mipi_dsi_host *of_find_mipi_dsi_host_by_node(struct device_node *node)
268 {
269 	struct mipi_dsi_host *host;
270 
271 	mutex_lock(&host_lock);
272 
273 	list_for_each_entry(host, &host_list, list) {
274 		if (host->dev->of_node == node) {
275 			mutex_unlock(&host_lock);
276 			return host;
277 		}
278 	}
279 
280 	mutex_unlock(&host_lock);
281 
282 	return NULL;
283 }
284 EXPORT_SYMBOL(of_find_mipi_dsi_host_by_node);
285 
mipi_dsi_host_register(struct mipi_dsi_host * host)286 int mipi_dsi_host_register(struct mipi_dsi_host *host)
287 {
288 	struct device_node *node;
289 
290 	for_each_available_child_of_node(host->dev->of_node, node) {
291 		/* skip nodes without reg property */
292 		if (!of_find_property(node, "reg", NULL))
293 			continue;
294 		of_mipi_dsi_device_add(host, node);
295 	}
296 
297 	mutex_lock(&host_lock);
298 	list_add_tail(&host->list, &host_list);
299 	mutex_unlock(&host_lock);
300 
301 	return 0;
302 }
303 EXPORT_SYMBOL(mipi_dsi_host_register);
304 
mipi_dsi_remove_device_fn(struct device * dev,void * priv)305 static int mipi_dsi_remove_device_fn(struct device *dev, void *priv)
306 {
307 	struct mipi_dsi_device *dsi = to_mipi_dsi_device(dev);
308 
309 	mipi_dsi_device_unregister(dsi);
310 
311 	return 0;
312 }
313 
mipi_dsi_host_unregister(struct mipi_dsi_host * host)314 void mipi_dsi_host_unregister(struct mipi_dsi_host *host)
315 {
316 	device_for_each_child(host->dev, NULL, mipi_dsi_remove_device_fn);
317 
318 	mutex_lock(&host_lock);
319 	list_del_init(&host->list);
320 	mutex_unlock(&host_lock);
321 }
322 EXPORT_SYMBOL(mipi_dsi_host_unregister);
323 
324 /**
325  * mipi_dsi_attach - attach a DSI device to its DSI host
326  * @dsi: DSI peripheral
327  */
mipi_dsi_attach(struct mipi_dsi_device * dsi)328 int mipi_dsi_attach(struct mipi_dsi_device *dsi)
329 {
330 	const struct mipi_dsi_host_ops *ops = dsi->host->ops;
331 
332 	if (!ops || !ops->attach)
333 		return -ENOSYS;
334 
335 	return ops->attach(dsi->host, dsi);
336 }
337 EXPORT_SYMBOL(mipi_dsi_attach);
338 
339 /**
340  * mipi_dsi_detach - detach a DSI device from its DSI host
341  * @dsi: DSI peripheral
342  */
mipi_dsi_detach(struct mipi_dsi_device * dsi)343 int mipi_dsi_detach(struct mipi_dsi_device *dsi)
344 {
345 	const struct mipi_dsi_host_ops *ops = dsi->host->ops;
346 
347 	if (!ops || !ops->detach)
348 		return -ENOSYS;
349 
350 	return ops->detach(dsi->host, dsi);
351 }
352 EXPORT_SYMBOL(mipi_dsi_detach);
353 
mipi_dsi_device_transfer(struct mipi_dsi_device * dsi,struct mipi_dsi_msg * msg)354 static ssize_t mipi_dsi_device_transfer(struct mipi_dsi_device *dsi,
355 					struct mipi_dsi_msg *msg)
356 {
357 	const struct mipi_dsi_host_ops *ops = dsi->host->ops;
358 
359 	if (!ops || !ops->transfer)
360 		return -ENOSYS;
361 
362 	if (dsi->mode_flags & MIPI_DSI_MODE_LPM)
363 		msg->flags |= MIPI_DSI_MSG_USE_LPM;
364 
365 	return ops->transfer(dsi->host, msg);
366 }
367 
368 /**
369  * mipi_dsi_packet_format_is_short - check if a packet is of the short format
370  * @type: MIPI DSI data type of the packet
371  *
372  * Return: true if the packet for the given data type is a short packet, false
373  * otherwise.
374  */
mipi_dsi_packet_format_is_short(u8 type)375 bool mipi_dsi_packet_format_is_short(u8 type)
376 {
377 	switch (type) {
378 	case MIPI_DSI_V_SYNC_START:
379 	case MIPI_DSI_V_SYNC_END:
380 	case MIPI_DSI_H_SYNC_START:
381 	case MIPI_DSI_H_SYNC_END:
382 	case MIPI_DSI_COMPRESSION_MODE:
383 	case MIPI_DSI_END_OF_TRANSMISSION:
384 	case MIPI_DSI_COLOR_MODE_OFF:
385 	case MIPI_DSI_COLOR_MODE_ON:
386 	case MIPI_DSI_SHUTDOWN_PERIPHERAL:
387 	case MIPI_DSI_TURN_ON_PERIPHERAL:
388 	case MIPI_DSI_GENERIC_SHORT_WRITE_0_PARAM:
389 	case MIPI_DSI_GENERIC_SHORT_WRITE_1_PARAM:
390 	case MIPI_DSI_GENERIC_SHORT_WRITE_2_PARAM:
391 	case MIPI_DSI_GENERIC_READ_REQUEST_0_PARAM:
392 	case MIPI_DSI_GENERIC_READ_REQUEST_1_PARAM:
393 	case MIPI_DSI_GENERIC_READ_REQUEST_2_PARAM:
394 	case MIPI_DSI_DCS_SHORT_WRITE:
395 	case MIPI_DSI_DCS_SHORT_WRITE_PARAM:
396 	case MIPI_DSI_DCS_READ:
397 	case MIPI_DSI_EXECUTE_QUEUE:
398 	case MIPI_DSI_SET_MAXIMUM_RETURN_PACKET_SIZE:
399 		return true;
400 	}
401 
402 	return false;
403 }
404 EXPORT_SYMBOL(mipi_dsi_packet_format_is_short);
405 
406 /**
407  * mipi_dsi_packet_format_is_long - check if a packet is of the long format
408  * @type: MIPI DSI data type of the packet
409  *
410  * Return: true if the packet for the given data type is a long packet, false
411  * otherwise.
412  */
mipi_dsi_packet_format_is_long(u8 type)413 bool mipi_dsi_packet_format_is_long(u8 type)
414 {
415 	switch (type) {
416 	case MIPI_DSI_NULL_PACKET:
417 	case MIPI_DSI_BLANKING_PACKET:
418 	case MIPI_DSI_GENERIC_LONG_WRITE:
419 	case MIPI_DSI_DCS_LONG_WRITE:
420 	case MIPI_DSI_PICTURE_PARAMETER_SET:
421 	case MIPI_DSI_COMPRESSED_PIXEL_STREAM:
422 	case MIPI_DSI_LOOSELY_PACKED_PIXEL_STREAM_YCBCR20:
423 	case MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR24:
424 	case MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR16:
425 	case MIPI_DSI_PACKED_PIXEL_STREAM_30:
426 	case MIPI_DSI_PACKED_PIXEL_STREAM_36:
427 	case MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR12:
428 	case MIPI_DSI_PACKED_PIXEL_STREAM_16:
429 	case MIPI_DSI_PACKED_PIXEL_STREAM_18:
430 	case MIPI_DSI_PIXEL_STREAM_3BYTE_18:
431 	case MIPI_DSI_PACKED_PIXEL_STREAM_24:
432 		return true;
433 	}
434 
435 	return false;
436 }
437 EXPORT_SYMBOL(mipi_dsi_packet_format_is_long);
438 
439 /**
440  * mipi_dsi_create_packet - create a packet from a message according to the
441  *     DSI protocol
442  * @packet: pointer to a DSI packet structure
443  * @msg: message to translate into a packet
444  *
445  * Return: 0 on success or a negative error code on failure.
446  */
mipi_dsi_create_packet(struct mipi_dsi_packet * packet,const struct mipi_dsi_msg * msg)447 int mipi_dsi_create_packet(struct mipi_dsi_packet *packet,
448 			   const struct mipi_dsi_msg *msg)
449 {
450 	if (!packet || !msg)
451 		return -EINVAL;
452 
453 	/* do some minimum sanity checking */
454 	if (!mipi_dsi_packet_format_is_short(msg->type) &&
455 	    !mipi_dsi_packet_format_is_long(msg->type))
456 		return -EINVAL;
457 
458 	if (msg->channel > 3)
459 		return -EINVAL;
460 
461 	memset(packet, 0, sizeof(*packet));
462 	packet->header[0] = ((msg->channel & 0x3) << 6) | (msg->type & 0x3f);
463 
464 	/* TODO: compute ECC if hardware support is not available */
465 
466 	/*
467 	 * Long write packets contain the word count in header bytes 1 and 2.
468 	 * The payload follows the header and is word count bytes long.
469 	 *
470 	 * Short write packets encode up to two parameters in header bytes 1
471 	 * and 2.
472 	 */
473 	if (mipi_dsi_packet_format_is_long(msg->type)) {
474 		packet->header[1] = (msg->tx_len >> 0) & 0xff;
475 		packet->header[2] = (msg->tx_len >> 8) & 0xff;
476 
477 		packet->payload_length = msg->tx_len;
478 		packet->payload = msg->tx_buf;
479 	} else {
480 		const u8 *tx = msg->tx_buf;
481 
482 		packet->header[1] = (msg->tx_len > 0) ? tx[0] : 0;
483 		packet->header[2] = (msg->tx_len > 1) ? tx[1] : 0;
484 	}
485 
486 	packet->size = sizeof(packet->header) + packet->payload_length;
487 
488 	return 0;
489 }
490 EXPORT_SYMBOL(mipi_dsi_create_packet);
491 
492 /**
493  * mipi_dsi_shutdown_peripheral() - sends a Shutdown Peripheral command
494  * @dsi: DSI peripheral device
495  *
496  * Return: 0 on success or a negative error code on failure.
497  */
mipi_dsi_shutdown_peripheral(struct mipi_dsi_device * dsi)498 int mipi_dsi_shutdown_peripheral(struct mipi_dsi_device *dsi)
499 {
500 	struct mipi_dsi_msg msg = {
501 		.channel = dsi->channel,
502 		.type = MIPI_DSI_SHUTDOWN_PERIPHERAL,
503 		.tx_buf = (u8 [2]) { 0, 0 },
504 		.tx_len = 2,
505 	};
506 	int ret = mipi_dsi_device_transfer(dsi, &msg);
507 
508 	return (ret < 0) ? ret : 0;
509 }
510 EXPORT_SYMBOL(mipi_dsi_shutdown_peripheral);
511 
512 /**
513  * mipi_dsi_turn_on_peripheral() - sends a Turn On Peripheral command
514  * @dsi: DSI peripheral device
515  *
516  * Return: 0 on success or a negative error code on failure.
517  */
mipi_dsi_turn_on_peripheral(struct mipi_dsi_device * dsi)518 int mipi_dsi_turn_on_peripheral(struct mipi_dsi_device *dsi)
519 {
520 	struct mipi_dsi_msg msg = {
521 		.channel = dsi->channel,
522 		.type = MIPI_DSI_TURN_ON_PERIPHERAL,
523 		.tx_buf = (u8 [2]) { 0, 0 },
524 		.tx_len = 2,
525 	};
526 	int ret = mipi_dsi_device_transfer(dsi, &msg);
527 
528 	return (ret < 0) ? ret : 0;
529 }
530 EXPORT_SYMBOL(mipi_dsi_turn_on_peripheral);
531 
532 /*
533  * mipi_dsi_set_maximum_return_packet_size() - specify the maximum size of the
534  *    the payload in a long packet transmitted from the peripheral back to the
535  *    host processor
536  * @dsi: DSI peripheral device
537  * @value: the maximum size of the payload
538  *
539  * Return: 0 on success or a negative error code on failure.
540  */
mipi_dsi_set_maximum_return_packet_size(struct mipi_dsi_device * dsi,u16 value)541 int mipi_dsi_set_maximum_return_packet_size(struct mipi_dsi_device *dsi,
542 					    u16 value)
543 {
544 	u8 tx[2] = { value & 0xff, value >> 8 };
545 	struct mipi_dsi_msg msg = {
546 		.channel = dsi->channel,
547 		.type = MIPI_DSI_SET_MAXIMUM_RETURN_PACKET_SIZE,
548 		.tx_len = sizeof(tx),
549 		.tx_buf = tx,
550 	};
551 	int ret = mipi_dsi_device_transfer(dsi, &msg);
552 
553 	return (ret < 0) ? ret : 0;
554 }
555 EXPORT_SYMBOL(mipi_dsi_set_maximum_return_packet_size);
556 
557 /**
558  * mipi_dsi_compression_mode() - enable/disable DSC on the peripheral
559  * @dsi: DSI peripheral device
560  * @enable: Whether to enable or disable the DSC
561  *
562  * Enable or disable Display Stream Compression on the peripheral using the
563  * default Picture Parameter Set and VESA DSC 1.1 algorithm.
564  *
565  * Return: 0 on success or a negative error code on failure.
566  */
mipi_dsi_compression_mode(struct mipi_dsi_device * dsi,bool enable)567 ssize_t mipi_dsi_compression_mode(struct mipi_dsi_device *dsi, bool enable)
568 {
569 	/* Note: Needs updating for non-default PPS or algorithm */
570 	u8 tx[2] = { enable << 0, 0 };
571 	struct mipi_dsi_msg msg = {
572 		.channel = dsi->channel,
573 		.type = MIPI_DSI_COMPRESSION_MODE,
574 		.tx_len = sizeof(tx),
575 		.tx_buf = tx,
576 	};
577 	int ret = mipi_dsi_device_transfer(dsi, &msg);
578 
579 	return (ret < 0) ? ret : 0;
580 }
581 EXPORT_SYMBOL(mipi_dsi_compression_mode);
582 
583 /**
584  * mipi_dsi_picture_parameter_set() - transmit the DSC PPS to the peripheral
585  * @dsi: DSI peripheral device
586  * @pps: VESA DSC 1.1 Picture Parameter Set
587  *
588  * Transmit the VESA DSC 1.1 Picture Parameter Set to the peripheral.
589  *
590  * Return: 0 on success or a negative error code on failure.
591  */
mipi_dsi_picture_parameter_set(struct mipi_dsi_device * dsi,const struct drm_dsc_picture_parameter_set * pps)592 ssize_t mipi_dsi_picture_parameter_set(struct mipi_dsi_device *dsi,
593 				       const struct drm_dsc_picture_parameter_set *pps)
594 {
595 	struct mipi_dsi_msg msg = {
596 		.channel = dsi->channel,
597 		.type = MIPI_DSI_PICTURE_PARAMETER_SET,
598 		.tx_len = sizeof(*pps),
599 		.tx_buf = pps,
600 	};
601 	int ret = mipi_dsi_device_transfer(dsi, &msg);
602 
603 	return (ret < 0) ? ret : 0;
604 }
605 EXPORT_SYMBOL(mipi_dsi_picture_parameter_set);
606 
607 /**
608  * mipi_dsi_generic_write() - transmit data using a generic write packet
609  * @dsi: DSI peripheral device
610  * @payload: buffer containing the payload
611  * @size: size of payload buffer
612  *
613  * This function will automatically choose the right data type depending on
614  * the payload length.
615  *
616  * Return: The number of bytes transmitted on success or a negative error code
617  * on failure.
618  */
mipi_dsi_generic_write(struct mipi_dsi_device * dsi,const void * payload,size_t size)619 ssize_t mipi_dsi_generic_write(struct mipi_dsi_device *dsi, const void *payload,
620 			       size_t size)
621 {
622 	struct mipi_dsi_msg msg = {
623 		.channel = dsi->channel,
624 		.tx_buf = payload,
625 		.tx_len = size
626 	};
627 
628 	switch (size) {
629 	case 0:
630 		msg.type = MIPI_DSI_GENERIC_SHORT_WRITE_0_PARAM;
631 		break;
632 
633 	case 1:
634 		msg.type = MIPI_DSI_GENERIC_SHORT_WRITE_1_PARAM;
635 		break;
636 
637 	case 2:
638 		msg.type = MIPI_DSI_GENERIC_SHORT_WRITE_2_PARAM;
639 		break;
640 
641 	default:
642 		msg.type = MIPI_DSI_GENERIC_LONG_WRITE;
643 		break;
644 	}
645 
646 	return mipi_dsi_device_transfer(dsi, &msg);
647 }
648 EXPORT_SYMBOL(mipi_dsi_generic_write);
649 
650 /**
651  * mipi_dsi_generic_read() - receive data using a generic read packet
652  * @dsi: DSI peripheral device
653  * @params: buffer containing the request parameters
654  * @num_params: number of request parameters
655  * @data: buffer in which to return the received data
656  * @size: size of receive buffer
657  *
658  * This function will automatically choose the right data type depending on
659  * the number of parameters passed in.
660  *
661  * Return: The number of bytes successfully read or a negative error code on
662  * failure.
663  */
mipi_dsi_generic_read(struct mipi_dsi_device * dsi,const void * params,size_t num_params,void * data,size_t size)664 ssize_t mipi_dsi_generic_read(struct mipi_dsi_device *dsi, const void *params,
665 			      size_t num_params, void *data, size_t size)
666 {
667 	struct mipi_dsi_msg msg = {
668 		.channel = dsi->channel,
669 		.tx_len = num_params,
670 		.tx_buf = params,
671 		.rx_len = size,
672 		.rx_buf = data
673 	};
674 
675 	switch (num_params) {
676 	case 0:
677 		msg.type = MIPI_DSI_GENERIC_READ_REQUEST_0_PARAM;
678 		break;
679 
680 	case 1:
681 		msg.type = MIPI_DSI_GENERIC_READ_REQUEST_1_PARAM;
682 		break;
683 
684 	case 2:
685 		msg.type = MIPI_DSI_GENERIC_READ_REQUEST_2_PARAM;
686 		break;
687 
688 	default:
689 		return -EINVAL;
690 	}
691 
692 	return mipi_dsi_device_transfer(dsi, &msg);
693 }
694 EXPORT_SYMBOL(mipi_dsi_generic_read);
695 
696 /**
697  * mipi_dsi_dcs_write_buffer() - transmit a DCS command with payload
698  * @dsi: DSI peripheral device
699  * @data: buffer containing data to be transmitted
700  * @len: size of transmission buffer
701  *
702  * This function will automatically choose the right data type depending on
703  * the command payload length.
704  *
705  * Return: The number of bytes successfully transmitted or a negative error
706  * code on failure.
707  */
mipi_dsi_dcs_write_buffer(struct mipi_dsi_device * dsi,const void * data,size_t len)708 ssize_t mipi_dsi_dcs_write_buffer(struct mipi_dsi_device *dsi,
709 				  const void *data, size_t len)
710 {
711 	struct mipi_dsi_msg msg = {
712 		.channel = dsi->channel,
713 		.tx_buf = data,
714 		.tx_len = len
715 	};
716 
717 	switch (len) {
718 	case 0:
719 		return -EINVAL;
720 
721 	case 1:
722 		msg.type = MIPI_DSI_DCS_SHORT_WRITE;
723 		break;
724 
725 	case 2:
726 		msg.type = MIPI_DSI_DCS_SHORT_WRITE_PARAM;
727 		break;
728 
729 	default:
730 		msg.type = MIPI_DSI_DCS_LONG_WRITE;
731 		break;
732 	}
733 
734 	return mipi_dsi_device_transfer(dsi, &msg);
735 }
736 EXPORT_SYMBOL(mipi_dsi_dcs_write_buffer);
737 
738 /**
739  * mipi_dsi_dcs_write() - send DCS write command
740  * @dsi: DSI peripheral device
741  * @cmd: DCS command
742  * @data: buffer containing the command payload
743  * @len: command payload length
744  *
745  * This function will automatically choose the right data type depending on
746  * the command payload length.
747  *
748  * Return: The number of bytes successfully transmitted or a negative error
749  * code on failure.
750  */
mipi_dsi_dcs_write(struct mipi_dsi_device * dsi,u8 cmd,const void * data,size_t len)751 ssize_t mipi_dsi_dcs_write(struct mipi_dsi_device *dsi, u8 cmd,
752 			   const void *data, size_t len)
753 {
754 	ssize_t err;
755 	size_t size;
756 	u8 *tx;
757 
758 	if (len > 0) {
759 		size = 1 + len;
760 
761 		tx = kmalloc(size, GFP_KERNEL);
762 		if (!tx)
763 			return -ENOMEM;
764 
765 		/* concatenate the DCS command byte and the payload */
766 		tx[0] = cmd;
767 		memcpy(&tx[1], data, len);
768 	} else {
769 		tx = &cmd;
770 		size = 1;
771 	}
772 
773 	err = mipi_dsi_dcs_write_buffer(dsi, tx, size);
774 
775 	if (len > 0)
776 		kfree(tx);
777 
778 	return err;
779 }
780 EXPORT_SYMBOL(mipi_dsi_dcs_write);
781 
782 /**
783  * mipi_dsi_dcs_read() - send DCS read request command
784  * @dsi: DSI peripheral device
785  * @cmd: DCS command
786  * @data: buffer in which to receive data
787  * @len: size of receive buffer
788  *
789  * Return: The number of bytes read or a negative error code on failure.
790  */
mipi_dsi_dcs_read(struct mipi_dsi_device * dsi,u8 cmd,void * data,size_t len)791 ssize_t mipi_dsi_dcs_read(struct mipi_dsi_device *dsi, u8 cmd, void *data,
792 			  size_t len)
793 {
794 	struct mipi_dsi_msg msg = {
795 		.channel = dsi->channel,
796 		.type = MIPI_DSI_DCS_READ,
797 		.tx_buf = &cmd,
798 		.tx_len = 1,
799 		.rx_buf = data,
800 		.rx_len = len
801 	};
802 
803 	return mipi_dsi_device_transfer(dsi, &msg);
804 }
805 EXPORT_SYMBOL(mipi_dsi_dcs_read);
806 
807 /**
808  * mipi_dsi_dcs_nop() - send DCS nop packet
809  * @dsi: DSI peripheral device
810  *
811  * Return: 0 on success or a negative error code on failure.
812  */
mipi_dsi_dcs_nop(struct mipi_dsi_device * dsi)813 int mipi_dsi_dcs_nop(struct mipi_dsi_device *dsi)
814 {
815 	ssize_t err;
816 
817 	err = mipi_dsi_dcs_write(dsi, MIPI_DCS_NOP, NULL, 0);
818 	if (err < 0)
819 		return err;
820 
821 	return 0;
822 }
823 EXPORT_SYMBOL(mipi_dsi_dcs_nop);
824 
825 /**
826  * mipi_dsi_dcs_soft_reset() - perform a software reset of the display module
827  * @dsi: DSI peripheral device
828  *
829  * Return: 0 on success or a negative error code on failure.
830  */
mipi_dsi_dcs_soft_reset(struct mipi_dsi_device * dsi)831 int mipi_dsi_dcs_soft_reset(struct mipi_dsi_device *dsi)
832 {
833 	ssize_t err;
834 
835 	err = mipi_dsi_dcs_write(dsi, MIPI_DCS_SOFT_RESET, NULL, 0);
836 	if (err < 0)
837 		return err;
838 
839 	return 0;
840 }
841 EXPORT_SYMBOL(mipi_dsi_dcs_soft_reset);
842 
843 /**
844  * mipi_dsi_dcs_get_power_mode() - query the display module's current power
845  *    mode
846  * @dsi: DSI peripheral device
847  * @mode: return location for the current power mode
848  *
849  * Return: 0 on success or a negative error code on failure.
850  */
mipi_dsi_dcs_get_power_mode(struct mipi_dsi_device * dsi,u8 * mode)851 int mipi_dsi_dcs_get_power_mode(struct mipi_dsi_device *dsi, u8 *mode)
852 {
853 	ssize_t err;
854 
855 	err = mipi_dsi_dcs_read(dsi, MIPI_DCS_GET_POWER_MODE, mode,
856 				sizeof(*mode));
857 	if (err <= 0) {
858 		if (err == 0)
859 			err = -ENODATA;
860 
861 		return err;
862 	}
863 
864 	return 0;
865 }
866 EXPORT_SYMBOL(mipi_dsi_dcs_get_power_mode);
867 
868 /**
869  * mipi_dsi_dcs_get_pixel_format() - gets the pixel format for the RGB image
870  *    data used by the interface
871  * @dsi: DSI peripheral device
872  * @format: return location for the pixel format
873  *
874  * Return: 0 on success or a negative error code on failure.
875  */
mipi_dsi_dcs_get_pixel_format(struct mipi_dsi_device * dsi,u8 * format)876 int mipi_dsi_dcs_get_pixel_format(struct mipi_dsi_device *dsi, u8 *format)
877 {
878 	ssize_t err;
879 
880 	err = mipi_dsi_dcs_read(dsi, MIPI_DCS_GET_PIXEL_FORMAT, format,
881 				sizeof(*format));
882 	if (err <= 0) {
883 		if (err == 0)
884 			err = -ENODATA;
885 
886 		return err;
887 	}
888 
889 	return 0;
890 }
891 EXPORT_SYMBOL(mipi_dsi_dcs_get_pixel_format);
892 
893 /**
894  * mipi_dsi_dcs_enter_sleep_mode() - disable all unnecessary blocks inside the
895  *    display module except interface communication
896  * @dsi: DSI peripheral device
897  *
898  * Return: 0 on success or a negative error code on failure.
899  */
mipi_dsi_dcs_enter_sleep_mode(struct mipi_dsi_device * dsi)900 int mipi_dsi_dcs_enter_sleep_mode(struct mipi_dsi_device *dsi)
901 {
902 	ssize_t err;
903 
904 	err = mipi_dsi_dcs_write(dsi, MIPI_DCS_ENTER_SLEEP_MODE, NULL, 0);
905 	if (err < 0)
906 		return err;
907 
908 	return 0;
909 }
910 EXPORT_SYMBOL(mipi_dsi_dcs_enter_sleep_mode);
911 
912 /**
913  * mipi_dsi_dcs_exit_sleep_mode() - enable all blocks inside the display
914  *    module
915  * @dsi: DSI peripheral device
916  *
917  * Return: 0 on success or a negative error code on failure.
918  */
mipi_dsi_dcs_exit_sleep_mode(struct mipi_dsi_device * dsi)919 int mipi_dsi_dcs_exit_sleep_mode(struct mipi_dsi_device *dsi)
920 {
921 	ssize_t err;
922 
923 	err = mipi_dsi_dcs_write(dsi, MIPI_DCS_EXIT_SLEEP_MODE, NULL, 0);
924 	if (err < 0)
925 		return err;
926 
927 	return 0;
928 }
929 EXPORT_SYMBOL(mipi_dsi_dcs_exit_sleep_mode);
930 
931 /**
932  * mipi_dsi_dcs_set_display_off() - stop displaying the image data on the
933  *    display device
934  * @dsi: DSI peripheral device
935  *
936  * Return: 0 on success or a negative error code on failure.
937  */
mipi_dsi_dcs_set_display_off(struct mipi_dsi_device * dsi)938 int mipi_dsi_dcs_set_display_off(struct mipi_dsi_device *dsi)
939 {
940 	ssize_t err;
941 
942 	err = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_DISPLAY_OFF, NULL, 0);
943 	if (err < 0)
944 		return err;
945 
946 	return 0;
947 }
948 EXPORT_SYMBOL(mipi_dsi_dcs_set_display_off);
949 
950 /**
951  * mipi_dsi_dcs_set_display_on() - start displaying the image data on the
952  *    display device
953  * @dsi: DSI peripheral device
954  *
955  * Return: 0 on success or a negative error code on failure
956  */
mipi_dsi_dcs_set_display_on(struct mipi_dsi_device * dsi)957 int mipi_dsi_dcs_set_display_on(struct mipi_dsi_device *dsi)
958 {
959 	ssize_t err;
960 
961 	err = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_DISPLAY_ON, NULL, 0);
962 	if (err < 0)
963 		return err;
964 
965 	return 0;
966 }
967 EXPORT_SYMBOL(mipi_dsi_dcs_set_display_on);
968 
969 /**
970  * mipi_dsi_dcs_set_column_address() - define the column extent of the frame
971  *    memory accessed by the host processor
972  * @dsi: DSI peripheral device
973  * @start: first column of frame memory
974  * @end: last column of frame memory
975  *
976  * Return: 0 on success or a negative error code on failure.
977  */
mipi_dsi_dcs_set_column_address(struct mipi_dsi_device * dsi,u16 start,u16 end)978 int mipi_dsi_dcs_set_column_address(struct mipi_dsi_device *dsi, u16 start,
979 				    u16 end)
980 {
981 	u8 payload[4] = { start >> 8, start & 0xff, end >> 8, end & 0xff };
982 	ssize_t err;
983 
984 	err = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_COLUMN_ADDRESS, payload,
985 				 sizeof(payload));
986 	if (err < 0)
987 		return err;
988 
989 	return 0;
990 }
991 EXPORT_SYMBOL(mipi_dsi_dcs_set_column_address);
992 
993 /**
994  * mipi_dsi_dcs_set_page_address() - define the page extent of the frame
995  *    memory accessed by the host processor
996  * @dsi: DSI peripheral device
997  * @start: first page of frame memory
998  * @end: last page of frame memory
999  *
1000  * Return: 0 on success or a negative error code on failure.
1001  */
mipi_dsi_dcs_set_page_address(struct mipi_dsi_device * dsi,u16 start,u16 end)1002 int mipi_dsi_dcs_set_page_address(struct mipi_dsi_device *dsi, u16 start,
1003 				  u16 end)
1004 {
1005 	u8 payload[4] = { start >> 8, start & 0xff, end >> 8, end & 0xff };
1006 	ssize_t err;
1007 
1008 	err = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_PAGE_ADDRESS, payload,
1009 				 sizeof(payload));
1010 	if (err < 0)
1011 		return err;
1012 
1013 	return 0;
1014 }
1015 EXPORT_SYMBOL(mipi_dsi_dcs_set_page_address);
1016 
1017 /**
1018  * mipi_dsi_dcs_set_tear_off() - turn off the display module's Tearing Effect
1019  *    output signal on the TE signal line
1020  * @dsi: DSI peripheral device
1021  *
1022  * Return: 0 on success or a negative error code on failure
1023  */
mipi_dsi_dcs_set_tear_off(struct mipi_dsi_device * dsi)1024 int mipi_dsi_dcs_set_tear_off(struct mipi_dsi_device *dsi)
1025 {
1026 	ssize_t err;
1027 
1028 	err = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_TEAR_OFF, NULL, 0);
1029 	if (err < 0)
1030 		return err;
1031 
1032 	return 0;
1033 }
1034 EXPORT_SYMBOL(mipi_dsi_dcs_set_tear_off);
1035 
1036 /**
1037  * mipi_dsi_dcs_set_tear_on() - turn on the display module's Tearing Effect
1038  *    output signal on the TE signal line.
1039  * @dsi: DSI peripheral device
1040  * @mode: the Tearing Effect Output Line mode
1041  *
1042  * Return: 0 on success or a negative error code on failure
1043  */
mipi_dsi_dcs_set_tear_on(struct mipi_dsi_device * dsi,enum mipi_dsi_dcs_tear_mode mode)1044 int mipi_dsi_dcs_set_tear_on(struct mipi_dsi_device *dsi,
1045 			     enum mipi_dsi_dcs_tear_mode mode)
1046 {
1047 	u8 value = mode;
1048 	ssize_t err;
1049 
1050 	err = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_TEAR_ON, &value,
1051 				 sizeof(value));
1052 	if (err < 0)
1053 		return err;
1054 
1055 	return 0;
1056 }
1057 EXPORT_SYMBOL(mipi_dsi_dcs_set_tear_on);
1058 
1059 /**
1060  * mipi_dsi_dcs_set_pixel_format() - sets the pixel format for the RGB image
1061  *    data used by the interface
1062  * @dsi: DSI peripheral device
1063  * @format: pixel format
1064  *
1065  * Return: 0 on success or a negative error code on failure.
1066  */
mipi_dsi_dcs_set_pixel_format(struct mipi_dsi_device * dsi,u8 format)1067 int mipi_dsi_dcs_set_pixel_format(struct mipi_dsi_device *dsi, u8 format)
1068 {
1069 	ssize_t err;
1070 
1071 	err = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_PIXEL_FORMAT, &format,
1072 				 sizeof(format));
1073 	if (err < 0)
1074 		return err;
1075 
1076 	return 0;
1077 }
1078 EXPORT_SYMBOL(mipi_dsi_dcs_set_pixel_format);
1079 
1080 /**
1081  * mipi_dsi_dcs_set_tear_scanline() - set the scanline to use as trigger for
1082  *    the Tearing Effect output signal of the display module
1083  * @dsi: DSI peripheral device
1084  * @scanline: scanline to use as trigger
1085  *
1086  * Return: 0 on success or a negative error code on failure
1087  */
mipi_dsi_dcs_set_tear_scanline(struct mipi_dsi_device * dsi,u16 scanline)1088 int mipi_dsi_dcs_set_tear_scanline(struct mipi_dsi_device *dsi, u16 scanline)
1089 {
1090 	u8 payload[3] = { MIPI_DCS_SET_TEAR_SCANLINE, scanline >> 8,
1091 			  scanline & 0xff };
1092 	ssize_t err;
1093 
1094 	err = mipi_dsi_generic_write(dsi, payload, sizeof(payload));
1095 	if (err < 0)
1096 		return err;
1097 
1098 	return 0;
1099 }
1100 EXPORT_SYMBOL(mipi_dsi_dcs_set_tear_scanline);
1101 
1102 /**
1103  * mipi_dsi_dcs_set_display_brightness() - sets the brightness value of the
1104  *    display
1105  * @dsi: DSI peripheral device
1106  * @brightness: brightness value
1107  *
1108  * Return: 0 on success or a negative error code on failure.
1109  */
mipi_dsi_dcs_set_display_brightness(struct mipi_dsi_device * dsi,u16 brightness)1110 int mipi_dsi_dcs_set_display_brightness(struct mipi_dsi_device *dsi,
1111 					u16 brightness)
1112 {
1113 	u8 payload[2] = { brightness & 0xff, brightness >> 8 };
1114 	ssize_t err;
1115 
1116 	err = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_DISPLAY_BRIGHTNESS,
1117 				 payload, sizeof(payload));
1118 	if (err < 0)
1119 		return err;
1120 
1121 	return 0;
1122 }
1123 EXPORT_SYMBOL(mipi_dsi_dcs_set_display_brightness);
1124 
1125 /**
1126  * mipi_dsi_dcs_get_display_brightness() - gets the current brightness value
1127  *    of the display
1128  * @dsi: DSI peripheral device
1129  * @brightness: brightness value
1130  *
1131  * Return: 0 on success or a negative error code on failure.
1132  */
mipi_dsi_dcs_get_display_brightness(struct mipi_dsi_device * dsi,u16 * brightness)1133 int mipi_dsi_dcs_get_display_brightness(struct mipi_dsi_device *dsi,
1134 					u16 *brightness)
1135 {
1136 	ssize_t err;
1137 
1138 	err = mipi_dsi_dcs_read(dsi, MIPI_DCS_GET_DISPLAY_BRIGHTNESS,
1139 				brightness, sizeof(*brightness));
1140 	if (err <= 0) {
1141 		if (err == 0)
1142 			err = -ENODATA;
1143 
1144 		return err;
1145 	}
1146 
1147 	return 0;
1148 }
1149 EXPORT_SYMBOL(mipi_dsi_dcs_get_display_brightness);
1150 
mipi_dsi_drv_probe(struct device * dev)1151 static int mipi_dsi_drv_probe(struct device *dev)
1152 {
1153 	struct mipi_dsi_driver *drv = to_mipi_dsi_driver(dev->driver);
1154 	struct mipi_dsi_device *dsi = to_mipi_dsi_device(dev);
1155 
1156 	return drv->probe(dsi);
1157 }
1158 
mipi_dsi_drv_remove(struct device * dev)1159 static int mipi_dsi_drv_remove(struct device *dev)
1160 {
1161 	struct mipi_dsi_driver *drv = to_mipi_dsi_driver(dev->driver);
1162 	struct mipi_dsi_device *dsi = to_mipi_dsi_device(dev);
1163 
1164 	return drv->remove(dsi);
1165 }
1166 
mipi_dsi_drv_shutdown(struct device * dev)1167 static void mipi_dsi_drv_shutdown(struct device *dev)
1168 {
1169 	struct mipi_dsi_driver *drv = to_mipi_dsi_driver(dev->driver);
1170 	struct mipi_dsi_device *dsi = to_mipi_dsi_device(dev);
1171 
1172 	drv->shutdown(dsi);
1173 }
1174 
1175 /**
1176  * mipi_dsi_driver_register_full() - register a driver for DSI devices
1177  * @drv: DSI driver structure
1178  * @owner: owner module
1179  *
1180  * Return: 0 on success or a negative error code on failure.
1181  */
mipi_dsi_driver_register_full(struct mipi_dsi_driver * drv,struct module * owner)1182 int mipi_dsi_driver_register_full(struct mipi_dsi_driver *drv,
1183 				  struct module *owner)
1184 {
1185 	drv->driver.bus = &mipi_dsi_bus_type;
1186 	drv->driver.owner = owner;
1187 
1188 	if (drv->probe)
1189 		drv->driver.probe = mipi_dsi_drv_probe;
1190 	if (drv->remove)
1191 		drv->driver.remove = mipi_dsi_drv_remove;
1192 	if (drv->shutdown)
1193 		drv->driver.shutdown = mipi_dsi_drv_shutdown;
1194 
1195 	return driver_register(&drv->driver);
1196 }
1197 EXPORT_SYMBOL(mipi_dsi_driver_register_full);
1198 
1199 /**
1200  * mipi_dsi_driver_unregister() - unregister a driver for DSI devices
1201  * @drv: DSI driver structure
1202  *
1203  * Return: 0 on success or a negative error code on failure.
1204  */
mipi_dsi_driver_unregister(struct mipi_dsi_driver * drv)1205 void mipi_dsi_driver_unregister(struct mipi_dsi_driver *drv)
1206 {
1207 	driver_unregister(&drv->driver);
1208 }
1209 EXPORT_SYMBOL(mipi_dsi_driver_unregister);
1210 
mipi_dsi_bus_init(void)1211 static int __init mipi_dsi_bus_init(void)
1212 {
1213 	return bus_register(&mipi_dsi_bus_type);
1214 }
1215 postcore_initcall(mipi_dsi_bus_init);
1216 
1217 MODULE_AUTHOR("Andrzej Hajda <a.hajda@samsung.com>");
1218 MODULE_DESCRIPTION("MIPI DSI Bus");
1219 MODULE_LICENSE("GPL and additional rights");
1220