1/*
2 * MIPI DSI Bus
3 *
4 * Copyright (C) 2012-2013, Samsung Electronics, Co., Ltd.
5 * Andrzej Hajda <a.hajda@samsung.com>
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the
9 * "Software"), to deal in the Software without restriction, including
10 * without limitation the rights to use, copy, modify, merge, publish,
11 * distribute, sub license, and/or sell copies of the Software, and to
12 * permit persons to whom the Software is furnished to do so, subject to
13 * the following conditions:
14 *
15 * The above copyright notice and this permission notice (including the
16 * next paragraph) shall be included in all copies or substantial portions
17 * of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
22 * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
23 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
24 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
25 * USE OR OTHER DEALINGS IN THE SOFTWARE.
26 */
27
28#include <linux/device.h>
29#include <linux/module.h>
30#include <linux/of.h>
31#include <linux/of_device.h>
32#include <linux/pm_runtime.h>
33#include <linux/slab.h>
34
35#include <drm/display/drm_dsc.h>
36#include <drm/drm_mipi_dsi.h>
37#include <drm/drm_print.h>
38
39#include <linux/media-bus-format.h>
40
41#include <video/mipi_display.h>
42
43/**
44 * DOC: dsi helpers
45 *
46 * These functions contain some common logic and helpers to deal with MIPI DSI
47 * peripherals.
48 *
49 * Helpers are provided for a number of standard MIPI DSI command as well as a
50 * subset of the MIPI DCS command set.
51 */
52
53static int mipi_dsi_device_match(struct device *dev, const struct device_driver *drv)
54{
55 struct mipi_dsi_device *dsi = to_mipi_dsi_device(dev);
56
57 /* attempt OF style match */
58 if (of_driver_match_device(dev, drv))
59 return 1;
60
61 /* compare DSI device and driver names */
62 if (!strcmp(dsi->name, drv->name))
63 return 1;
64
65 return 0;
66}
67
68static int mipi_dsi_uevent(const struct device *dev, struct kobj_uevent_env *env)
69{
70 const struct mipi_dsi_device *dsi = to_mipi_dsi_device(dev);
71 int err;
72
73 err = of_device_uevent_modalias(dev, env);
74 if (err != -ENODEV)
75 return err;
76
77 add_uevent_var(env, format: "MODALIAS=%s%s", MIPI_DSI_MODULE_PREFIX,
78 dsi->name);
79
80 return 0;
81}
82
83static const struct dev_pm_ops mipi_dsi_device_pm_ops = {
84 .runtime_suspend = pm_generic_runtime_suspend,
85 .runtime_resume = pm_generic_runtime_resume,
86 .suspend = pm_generic_suspend,
87 .resume = pm_generic_resume,
88 .freeze = pm_generic_freeze,
89 .thaw = pm_generic_thaw,
90 .poweroff = pm_generic_poweroff,
91 .restore = pm_generic_restore,
92};
93
94static const struct bus_type mipi_dsi_bus_type = {
95 .name = "mipi-dsi",
96 .match = mipi_dsi_device_match,
97 .uevent = mipi_dsi_uevent,
98 .pm = &mipi_dsi_device_pm_ops,
99};
100
101/**
102 * of_find_mipi_dsi_device_by_node() - find the MIPI DSI device matching a
103 * device tree node
104 * @np: device tree node
105 *
106 * Return: A pointer to the MIPI DSI device corresponding to @np or NULL if no
107 * such device exists (or has not been registered yet).
108 */
109struct mipi_dsi_device *of_find_mipi_dsi_device_by_node(struct device_node *np)
110{
111 struct device *dev;
112
113 dev = bus_find_device_by_of_node(bus: &mipi_dsi_bus_type, np);
114
115 return dev ? to_mipi_dsi_device(dev) : NULL;
116}
117EXPORT_SYMBOL(of_find_mipi_dsi_device_by_node);
118
119static void mipi_dsi_dev_release(struct device *dev)
120{
121 struct mipi_dsi_device *dsi = to_mipi_dsi_device(dev);
122
123 of_node_put(node: dev->of_node);
124 kfree(objp: dsi);
125}
126
127static const struct device_type mipi_dsi_device_type = {
128 .release = mipi_dsi_dev_release,
129};
130
131static struct mipi_dsi_device *mipi_dsi_device_alloc(struct mipi_dsi_host *host)
132{
133 struct mipi_dsi_device *dsi;
134
135 dsi = kzalloc(sizeof(*dsi), GFP_KERNEL);
136 if (!dsi)
137 return ERR_PTR(error: -ENOMEM);
138
139 dsi->host = host;
140 dsi->dev.bus = &mipi_dsi_bus_type;
141 dsi->dev.parent = host->dev;
142 dsi->dev.type = &mipi_dsi_device_type;
143
144 device_initialize(dev: &dsi->dev);
145
146 return dsi;
147}
148
149static int mipi_dsi_device_add(struct mipi_dsi_device *dsi)
150{
151 struct mipi_dsi_host *host = dsi->host;
152
153 dev_set_name(dev: &dsi->dev, name: "%s.%d", dev_name(dev: host->dev), dsi->channel);
154
155 return device_add(dev: &dsi->dev);
156}
157
158#if IS_ENABLED(CONFIG_OF)
159static struct mipi_dsi_device *
160of_mipi_dsi_device_add(struct mipi_dsi_host *host, struct device_node *node)
161{
162 struct mipi_dsi_device_info info = { };
163 int ret;
164 u32 reg;
165
166 if (of_alias_from_compatible(node, alias: info.type, len: sizeof(info.type)) < 0) {
167 dev_err(host->dev, "modalias failure on %pOF\n", node);
168 return ERR_PTR(error: -EINVAL);
169 }
170
171 ret = of_property_read_u32(np: node, propname: "reg", out_value: &reg);
172 if (ret) {
173 dev_err(host->dev, "device node %pOF has no valid reg property: %d\n",
174 node, ret);
175 return ERR_PTR(error: -EINVAL);
176 }
177
178 info.channel = reg;
179 info.node = of_node_get(node);
180
181 return mipi_dsi_device_register_full(host, info: &info);
182}
183#else
184static struct mipi_dsi_device *
185of_mipi_dsi_device_add(struct mipi_dsi_host *host, struct device_node *node)
186{
187 return ERR_PTR(-ENODEV);
188}
189#endif
190
191/**
192 * mipi_dsi_device_register_full - create a MIPI DSI device
193 * @host: DSI host to which this device is connected
194 * @info: pointer to template containing DSI device information
195 *
196 * Create a MIPI DSI device by using the device information provided by
197 * mipi_dsi_device_info template
198 *
199 * Returns:
200 * A pointer to the newly created MIPI DSI device, or, a pointer encoded
201 * with an error
202 */
203struct mipi_dsi_device *
204mipi_dsi_device_register_full(struct mipi_dsi_host *host,
205 const struct mipi_dsi_device_info *info)
206{
207 struct mipi_dsi_device *dsi;
208 int ret;
209
210 if (!info) {
211 dev_err(host->dev, "invalid mipi_dsi_device_info pointer\n");
212 return ERR_PTR(error: -EINVAL);
213 }
214
215 if (info->channel > 3) {
216 dev_err(host->dev, "invalid virtual channel: %u\n", info->channel);
217 return ERR_PTR(error: -EINVAL);
218 }
219
220 dsi = mipi_dsi_device_alloc(host);
221 if (IS_ERR(ptr: dsi)) {
222 dev_err(host->dev, "failed to allocate DSI device %ld\n",
223 PTR_ERR(dsi));
224 return dsi;
225 }
226
227 device_set_node(dev: &dsi->dev, of_fwnode_handle(info->node));
228 dsi->channel = info->channel;
229 strscpy(dsi->name, info->type, sizeof(dsi->name));
230
231 ret = mipi_dsi_device_add(dsi);
232 if (ret) {
233 dev_err(host->dev, "failed to add DSI device %d\n", ret);
234 kfree(objp: dsi);
235 return ERR_PTR(error: ret);
236 }
237
238 return dsi;
239}
240EXPORT_SYMBOL(mipi_dsi_device_register_full);
241
242/**
243 * mipi_dsi_device_unregister - unregister MIPI DSI device
244 * @dsi: DSI peripheral device
245 */
246void mipi_dsi_device_unregister(struct mipi_dsi_device *dsi)
247{
248 device_unregister(dev: &dsi->dev);
249}
250EXPORT_SYMBOL(mipi_dsi_device_unregister);
251
252static void devm_mipi_dsi_device_unregister(void *arg)
253{
254 struct mipi_dsi_device *dsi = arg;
255
256 mipi_dsi_device_unregister(dsi);
257}
258
259/**
260 * devm_mipi_dsi_device_register_full - create a managed MIPI DSI device
261 * @dev: device to tie the MIPI-DSI device lifetime to
262 * @host: DSI host to which this device is connected
263 * @info: pointer to template containing DSI device information
264 *
265 * Create a MIPI DSI device by using the device information provided by
266 * mipi_dsi_device_info template
267 *
268 * This is the managed version of mipi_dsi_device_register_full() which
269 * automatically calls mipi_dsi_device_unregister() when @dev is
270 * unbound.
271 *
272 * Returns:
273 * A pointer to the newly created MIPI DSI device, or, a pointer encoded
274 * with an error
275 */
276struct mipi_dsi_device *
277devm_mipi_dsi_device_register_full(struct device *dev,
278 struct mipi_dsi_host *host,
279 const struct mipi_dsi_device_info *info)
280{
281 struct mipi_dsi_device *dsi;
282 int ret;
283
284 dsi = mipi_dsi_device_register_full(host, info);
285 if (IS_ERR(ptr: dsi))
286 return dsi;
287
288 ret = devm_add_action_or_reset(dev,
289 devm_mipi_dsi_device_unregister,
290 dsi);
291 if (ret)
292 return ERR_PTR(error: ret);
293
294 return dsi;
295}
296EXPORT_SYMBOL_GPL(devm_mipi_dsi_device_register_full);
297
298static DEFINE_MUTEX(host_lock);
299static LIST_HEAD(host_list);
300
301/**
302 * of_find_mipi_dsi_host_by_node() - find the MIPI DSI host matching a
303 * device tree node
304 * @node: device tree node
305 *
306 * Returns:
307 * A pointer to the MIPI DSI host corresponding to @node or NULL if no
308 * such device exists (or has not been registered yet).
309 */
310struct mipi_dsi_host *of_find_mipi_dsi_host_by_node(struct device_node *node)
311{
312 struct mipi_dsi_host *host;
313
314 mutex_lock(&host_lock);
315
316 list_for_each_entry(host, &host_list, list) {
317 if (host->dev->of_node == node) {
318 mutex_unlock(lock: &host_lock);
319 return host;
320 }
321 }
322
323 mutex_unlock(lock: &host_lock);
324
325 return NULL;
326}
327EXPORT_SYMBOL(of_find_mipi_dsi_host_by_node);
328
329int mipi_dsi_host_register(struct mipi_dsi_host *host)
330{
331 struct device_node *node;
332
333 for_each_available_child_of_node(host->dev->of_node, node) {
334 /* skip nodes without reg property */
335 if (!of_property_present(np: node, propname: "reg"))
336 continue;
337 of_mipi_dsi_device_add(host, node);
338 }
339
340 mutex_lock(&host_lock);
341 list_add_tail(new: &host->list, head: &host_list);
342 mutex_unlock(lock: &host_lock);
343
344 return 0;
345}
346EXPORT_SYMBOL(mipi_dsi_host_register);
347
348static int mipi_dsi_remove_device_fn(struct device *dev, void *priv)
349{
350 struct mipi_dsi_device *dsi = to_mipi_dsi_device(dev);
351
352 if (dsi->attached)
353 mipi_dsi_detach(dsi);
354 mipi_dsi_device_unregister(dsi);
355
356 return 0;
357}
358
359void mipi_dsi_host_unregister(struct mipi_dsi_host *host)
360{
361 device_for_each_child(parent: host->dev, NULL, fn: mipi_dsi_remove_device_fn);
362
363 mutex_lock(&host_lock);
364 list_del_init(entry: &host->list);
365 mutex_unlock(lock: &host_lock);
366}
367EXPORT_SYMBOL(mipi_dsi_host_unregister);
368
369/**
370 * mipi_dsi_attach - attach a DSI device to its DSI host
371 * @dsi: DSI peripheral
372 */
373int mipi_dsi_attach(struct mipi_dsi_device *dsi)
374{
375 const struct mipi_dsi_host_ops *ops = dsi->host->ops;
376 int ret;
377
378 if (!ops || !ops->attach)
379 return -ENOSYS;
380
381 ret = ops->attach(dsi->host, dsi);
382 if (ret)
383 return ret;
384
385 dsi->attached = true;
386
387 return 0;
388}
389EXPORT_SYMBOL(mipi_dsi_attach);
390
391/**
392 * mipi_dsi_detach - detach a DSI device from its DSI host
393 * @dsi: DSI peripheral
394 */
395int mipi_dsi_detach(struct mipi_dsi_device *dsi)
396{
397 const struct mipi_dsi_host_ops *ops = dsi->host->ops;
398
399 if (WARN_ON(!dsi->attached))
400 return -EINVAL;
401
402 if (!ops || !ops->detach)
403 return -ENOSYS;
404
405 dsi->attached = false;
406
407 return ops->detach(dsi->host, dsi);
408}
409EXPORT_SYMBOL(mipi_dsi_detach);
410
411static void devm_mipi_dsi_detach(void *arg)
412{
413 struct mipi_dsi_device *dsi = arg;
414
415 mipi_dsi_detach(dsi);
416}
417
418/**
419 * devm_mipi_dsi_attach - Attach a MIPI-DSI device to its DSI Host
420 * @dev: device to tie the MIPI-DSI device attachment lifetime to
421 * @dsi: DSI peripheral
422 *
423 * This is the managed version of mipi_dsi_attach() which automatically
424 * calls mipi_dsi_detach() when @dev is unbound.
425 *
426 * Returns:
427 * 0 on success, a negative error code on failure.
428 */
429int devm_mipi_dsi_attach(struct device *dev,
430 struct mipi_dsi_device *dsi)
431{
432 int ret;
433
434 ret = mipi_dsi_attach(dsi);
435 if (ret)
436 return ret;
437
438 ret = devm_add_action_or_reset(dev, devm_mipi_dsi_detach, dsi);
439 if (ret)
440 return ret;
441
442 return 0;
443}
444EXPORT_SYMBOL_GPL(devm_mipi_dsi_attach);
445
446static ssize_t mipi_dsi_device_transfer(struct mipi_dsi_device *dsi,
447 struct mipi_dsi_msg *msg)
448{
449 const struct mipi_dsi_host_ops *ops = dsi->host->ops;
450
451 if (!ops || !ops->transfer)
452 return -ENOSYS;
453
454 if (dsi->mode_flags & MIPI_DSI_MODE_LPM)
455 msg->flags |= MIPI_DSI_MSG_USE_LPM;
456
457 return ops->transfer(dsi->host, msg);
458}
459
460/**
461 * mipi_dsi_packet_format_is_short - check if a packet is of the short format
462 * @type: MIPI DSI data type of the packet
463 *
464 * Return: true if the packet for the given data type is a short packet, false
465 * otherwise.
466 */
467bool mipi_dsi_packet_format_is_short(u8 type)
468{
469 switch (type) {
470 case MIPI_DSI_V_SYNC_START:
471 case MIPI_DSI_V_SYNC_END:
472 case MIPI_DSI_H_SYNC_START:
473 case MIPI_DSI_H_SYNC_END:
474 case MIPI_DSI_COMPRESSION_MODE:
475 case MIPI_DSI_END_OF_TRANSMISSION:
476 case MIPI_DSI_COLOR_MODE_OFF:
477 case MIPI_DSI_COLOR_MODE_ON:
478 case MIPI_DSI_SHUTDOWN_PERIPHERAL:
479 case MIPI_DSI_TURN_ON_PERIPHERAL:
480 case MIPI_DSI_GENERIC_SHORT_WRITE_0_PARAM:
481 case MIPI_DSI_GENERIC_SHORT_WRITE_1_PARAM:
482 case MIPI_DSI_GENERIC_SHORT_WRITE_2_PARAM:
483 case MIPI_DSI_GENERIC_READ_REQUEST_0_PARAM:
484 case MIPI_DSI_GENERIC_READ_REQUEST_1_PARAM:
485 case MIPI_DSI_GENERIC_READ_REQUEST_2_PARAM:
486 case MIPI_DSI_DCS_SHORT_WRITE:
487 case MIPI_DSI_DCS_SHORT_WRITE_PARAM:
488 case MIPI_DSI_DCS_READ:
489 case MIPI_DSI_EXECUTE_QUEUE:
490 case MIPI_DSI_SET_MAXIMUM_RETURN_PACKET_SIZE:
491 return true;
492 }
493
494 return false;
495}
496EXPORT_SYMBOL(mipi_dsi_packet_format_is_short);
497
498/**
499 * mipi_dsi_packet_format_is_long - check if a packet is of the long format
500 * @type: MIPI DSI data type of the packet
501 *
502 * Return: true if the packet for the given data type is a long packet, false
503 * otherwise.
504 */
505bool mipi_dsi_packet_format_is_long(u8 type)
506{
507 switch (type) {
508 case MIPI_DSI_NULL_PACKET:
509 case MIPI_DSI_BLANKING_PACKET:
510 case MIPI_DSI_GENERIC_LONG_WRITE:
511 case MIPI_DSI_DCS_LONG_WRITE:
512 case MIPI_DSI_PICTURE_PARAMETER_SET:
513 case MIPI_DSI_COMPRESSED_PIXEL_STREAM:
514 case MIPI_DSI_LOOSELY_PACKED_PIXEL_STREAM_YCBCR20:
515 case MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR24:
516 case MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR16:
517 case MIPI_DSI_PACKED_PIXEL_STREAM_30:
518 case MIPI_DSI_PACKED_PIXEL_STREAM_36:
519 case MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR12:
520 case MIPI_DSI_PACKED_PIXEL_STREAM_16:
521 case MIPI_DSI_PACKED_PIXEL_STREAM_18:
522 case MIPI_DSI_PIXEL_STREAM_3BYTE_18:
523 case MIPI_DSI_PACKED_PIXEL_STREAM_24:
524 return true;
525 }
526
527 return false;
528}
529EXPORT_SYMBOL(mipi_dsi_packet_format_is_long);
530
531/**
532 * mipi_dsi_create_packet - create a packet from a message according to the
533 * DSI protocol
534 * @packet: pointer to a DSI packet structure
535 * @msg: message to translate into a packet
536 *
537 * Return: 0 on success or a negative error code on failure.
538 */
539int mipi_dsi_create_packet(struct mipi_dsi_packet *packet,
540 const struct mipi_dsi_msg *msg)
541{
542 if (!packet || !msg)
543 return -EINVAL;
544
545 /* do some minimum sanity checking */
546 if (!mipi_dsi_packet_format_is_short(msg->type) &&
547 !mipi_dsi_packet_format_is_long(msg->type))
548 return -EINVAL;
549
550 if (msg->channel > 3)
551 return -EINVAL;
552
553 memset(packet, 0, sizeof(*packet));
554 packet->header[0] = ((msg->channel & 0x3) << 6) | (msg->type & 0x3f);
555
556 /* TODO: compute ECC if hardware support is not available */
557
558 /*
559 * Long write packets contain the word count in header bytes 1 and 2.
560 * The payload follows the header and is word count bytes long.
561 *
562 * Short write packets encode up to two parameters in header bytes 1
563 * and 2.
564 */
565 if (mipi_dsi_packet_format_is_long(msg->type)) {
566 packet->header[1] = (msg->tx_len >> 0) & 0xff;
567 packet->header[2] = (msg->tx_len >> 8) & 0xff;
568
569 packet->payload_length = msg->tx_len;
570 packet->payload = msg->tx_buf;
571 } else {
572 const u8 *tx = msg->tx_buf;
573
574 packet->header[1] = (msg->tx_len > 0) ? tx[0] : 0;
575 packet->header[2] = (msg->tx_len > 1) ? tx[1] : 0;
576 }
577
578 packet->size = sizeof(packet->header) + packet->payload_length;
579
580 return 0;
581}
582EXPORT_SYMBOL(mipi_dsi_create_packet);
583
584/**
585 * mipi_dsi_shutdown_peripheral() - sends a Shutdown Peripheral command
586 * @dsi: DSI peripheral device
587 *
588 * Return: 0 on success or a negative error code on failure.
589 */
590int mipi_dsi_shutdown_peripheral(struct mipi_dsi_device *dsi)
591{
592 struct mipi_dsi_msg msg = {
593 .channel = dsi->channel,
594 .type = MIPI_DSI_SHUTDOWN_PERIPHERAL,
595 .tx_buf = (u8 [2]) { 0, 0 },
596 .tx_len = 2,
597 };
598 int ret = mipi_dsi_device_transfer(dsi, msg: &msg);
599
600 return (ret < 0) ? ret : 0;
601}
602EXPORT_SYMBOL(mipi_dsi_shutdown_peripheral);
603
604/**
605 * mipi_dsi_turn_on_peripheral() - sends a Turn On Peripheral command
606 * @dsi: DSI peripheral device
607 *
608 * This function is deprecated. Use mipi_dsi_turn_on_peripheral_multi() instead.
609 *
610 * Return: 0 on success or a negative error code on failure.
611 */
612int mipi_dsi_turn_on_peripheral(struct mipi_dsi_device *dsi)
613{
614 struct mipi_dsi_msg msg = {
615 .channel = dsi->channel,
616 .type = MIPI_DSI_TURN_ON_PERIPHERAL,
617 .tx_buf = (u8 [2]) { 0, 0 },
618 .tx_len = 2,
619 };
620 int ret = mipi_dsi_device_transfer(dsi, msg: &msg);
621
622 return (ret < 0) ? ret : 0;
623}
624EXPORT_SYMBOL(mipi_dsi_turn_on_peripheral);
625
626/*
627 * mipi_dsi_set_maximum_return_packet_size() - specify the maximum size of
628 * the payload in a long packet transmitted from the peripheral back to the
629 * host processor
630 * @dsi: DSI peripheral device
631 * @value: the maximum size of the payload
632 *
633 * Return: 0 on success or a negative error code on failure.
634 */
635int mipi_dsi_set_maximum_return_packet_size(struct mipi_dsi_device *dsi,
636 u16 value)
637{
638 u8 tx[2] = { value & 0xff, value >> 8 };
639 struct mipi_dsi_msg msg = {
640 .channel = dsi->channel,
641 .type = MIPI_DSI_SET_MAXIMUM_RETURN_PACKET_SIZE,
642 .tx_len = sizeof(tx),
643 .tx_buf = tx,
644 };
645 int ret = mipi_dsi_device_transfer(dsi, msg: &msg);
646
647 return (ret < 0) ? ret : 0;
648}
649EXPORT_SYMBOL(mipi_dsi_set_maximum_return_packet_size);
650
651/**
652 * mipi_dsi_compression_mode_ext() - enable/disable DSC on the peripheral
653 * @dsi: DSI peripheral device
654 * @enable: Whether to enable or disable the DSC
655 * @algo: Selected compression algorithm
656 * @pps_selector: Select PPS from the table of pre-stored or uploaded PPS entries
657 *
658 * Enable or disable Display Stream Compression on the peripheral.
659 * This function is deprecated. Use mipi_dsi_compression_mode_ext_multi() instead.
660 *
661 * Return: 0 on success or a negative error code on failure.
662 */
663int mipi_dsi_compression_mode_ext(struct mipi_dsi_device *dsi, bool enable,
664 enum mipi_dsi_compression_algo algo,
665 unsigned int pps_selector)
666{
667 u8 tx[2] = { };
668 struct mipi_dsi_msg msg = {
669 .channel = dsi->channel,
670 .type = MIPI_DSI_COMPRESSION_MODE,
671 .tx_len = sizeof(tx),
672 .tx_buf = tx,
673 };
674 int ret;
675
676 if (algo > 3 || pps_selector > 3)
677 return -EINVAL;
678
679 tx[0] = (enable << 0) |
680 (algo << 1) |
681 (pps_selector << 4);
682
683 ret = mipi_dsi_device_transfer(dsi, msg: &msg);
684
685 return (ret < 0) ? ret : 0;
686}
687EXPORT_SYMBOL(mipi_dsi_compression_mode_ext);
688
689/**
690 * mipi_dsi_compression_mode() - enable/disable DSC on the peripheral
691 * @dsi: DSI peripheral device
692 * @enable: Whether to enable or disable the DSC
693 *
694 * Enable or disable Display Stream Compression on the peripheral using the
695 * default Picture Parameter Set and VESA DSC 1.1 algorithm.
696 *
697 * Return: 0 on success or a negative error code on failure.
698 */
699int mipi_dsi_compression_mode(struct mipi_dsi_device *dsi, bool enable)
700{
701 return mipi_dsi_compression_mode_ext(dsi, enable, MIPI_DSI_COMPRESSION_DSC, 0);
702}
703EXPORT_SYMBOL(mipi_dsi_compression_mode);
704
705/**
706 * mipi_dsi_picture_parameter_set() - transmit the DSC PPS to the peripheral
707 * @dsi: DSI peripheral device
708 * @pps: VESA DSC 1.1 Picture Parameter Set
709 *
710 * Transmit the VESA DSC 1.1 Picture Parameter Set to the peripheral.
711 * This function is deprecated. Use mipi_dsi_picture_parameter_set_multi() instead.
712 *
713 * Return: 0 on success or a negative error code on failure.
714 */
715int mipi_dsi_picture_parameter_set(struct mipi_dsi_device *dsi,
716 const struct drm_dsc_picture_parameter_set *pps)
717{
718 struct mipi_dsi_msg msg = {
719 .channel = dsi->channel,
720 .type = MIPI_DSI_PICTURE_PARAMETER_SET,
721 .tx_len = sizeof(*pps),
722 .tx_buf = pps,
723 };
724 int ret = mipi_dsi_device_transfer(dsi, msg: &msg);
725
726 return (ret < 0) ? ret : 0;
727}
728EXPORT_SYMBOL(mipi_dsi_picture_parameter_set);
729
730/**
731 * mipi_dsi_generic_write() - transmit data using a generic write packet
732 * @dsi: DSI peripheral device
733 * @payload: buffer containing the payload
734 * @size: size of payload buffer
735 *
736 * This function will automatically choose the right data type depending on
737 * the payload length.
738 *
739 * Return: The number of bytes transmitted on success or a negative error code
740 * on failure.
741 */
742ssize_t mipi_dsi_generic_write(struct mipi_dsi_device *dsi, const void *payload,
743 size_t size)
744{
745 struct mipi_dsi_msg msg = {
746 .channel = dsi->channel,
747 .tx_buf = payload,
748 .tx_len = size
749 };
750
751 switch (size) {
752 case 0:
753 msg.type = MIPI_DSI_GENERIC_SHORT_WRITE_0_PARAM;
754 break;
755
756 case 1:
757 msg.type = MIPI_DSI_GENERIC_SHORT_WRITE_1_PARAM;
758 break;
759
760 case 2:
761 msg.type = MIPI_DSI_GENERIC_SHORT_WRITE_2_PARAM;
762 break;
763
764 default:
765 msg.type = MIPI_DSI_GENERIC_LONG_WRITE;
766 break;
767 }
768
769 return mipi_dsi_device_transfer(dsi, msg: &msg);
770}
771EXPORT_SYMBOL(mipi_dsi_generic_write);
772
773/**
774 * mipi_dsi_generic_write_chatty() - mipi_dsi_generic_write() w/ an error log
775 * @dsi: DSI peripheral device
776 * @payload: buffer containing the payload
777 * @size: size of payload buffer
778 *
779 * Like mipi_dsi_generic_write() but includes a dev_err()
780 * call for you and returns 0 upon success, not the number of bytes sent.
781 *
782 * Return: 0 on success or a negative error code on failure.
783 */
784int mipi_dsi_generic_write_chatty(struct mipi_dsi_device *dsi,
785 const void *payload, size_t size)
786{
787 struct device *dev = &dsi->dev;
788 ssize_t ret;
789
790 ret = mipi_dsi_generic_write(dsi, payload, size);
791 if (ret < 0) {
792 dev_err(dev, "sending generic data %*ph failed: %zd\n",
793 (int)size, payload, ret);
794 return ret;
795 }
796
797 return 0;
798}
799EXPORT_SYMBOL(mipi_dsi_generic_write_chatty);
800
801/**
802 * mipi_dsi_generic_write_multi() - mipi_dsi_generic_write_chatty() w/ accum_err
803 * @ctx: Context for multiple DSI transactions
804 * @payload: buffer containing the payload
805 * @size: size of payload buffer
806 *
807 * Like mipi_dsi_generic_write_chatty() but deals with errors in a way that
808 * makes it convenient to make several calls in a row.
809 */
810void mipi_dsi_generic_write_multi(struct mipi_dsi_multi_context *ctx,
811 const void *payload, size_t size)
812{
813 struct mipi_dsi_device *dsi = ctx->dsi;
814 struct device *dev = &dsi->dev;
815 ssize_t ret;
816
817 if (ctx->accum_err)
818 return;
819
820 ret = mipi_dsi_generic_write(dsi, payload, size);
821 if (ret < 0) {
822 ctx->accum_err = ret;
823 dev_err(dev, "sending generic data %*ph failed: %d\n",
824 (int)size, payload, ctx->accum_err);
825 }
826}
827EXPORT_SYMBOL(mipi_dsi_generic_write_multi);
828
829/**
830 * mipi_dsi_generic_read() - receive data using a generic read packet
831 * @dsi: DSI peripheral device
832 * @params: buffer containing the request parameters
833 * @num_params: number of request parameters
834 * @data: buffer in which to return the received data
835 * @size: size of receive buffer
836 *
837 * This function will automatically choose the right data type depending on
838 * the number of parameters passed in.
839 *
840 * Return: The number of bytes successfully read or a negative error code on
841 * failure.
842 */
843ssize_t mipi_dsi_generic_read(struct mipi_dsi_device *dsi, const void *params,
844 size_t num_params, void *data, size_t size)
845{
846 struct mipi_dsi_msg msg = {
847 .channel = dsi->channel,
848 .tx_len = num_params,
849 .tx_buf = params,
850 .rx_len = size,
851 .rx_buf = data
852 };
853
854 switch (num_params) {
855 case 0:
856 msg.type = MIPI_DSI_GENERIC_READ_REQUEST_0_PARAM;
857 break;
858
859 case 1:
860 msg.type = MIPI_DSI_GENERIC_READ_REQUEST_1_PARAM;
861 break;
862
863 case 2:
864 msg.type = MIPI_DSI_GENERIC_READ_REQUEST_2_PARAM;
865 break;
866
867 default:
868 return -EINVAL;
869 }
870
871 return mipi_dsi_device_transfer(dsi, msg: &msg);
872}
873EXPORT_SYMBOL(mipi_dsi_generic_read);
874
875/**
876 * drm_mipi_dsi_get_input_bus_fmt() - Get the required MEDIA_BUS_FMT_* based
877 * input pixel format for a given DSI output
878 * pixel format
879 * @dsi_format: pixel format that a DSI host needs to output
880 *
881 * Various DSI hosts can use this function during their
882 * &drm_bridge_funcs.atomic_get_input_bus_fmts operation to ascertain
883 * the MEDIA_BUS_FMT_* pixel format required as input.
884 *
885 * RETURNS:
886 * a 32-bit MEDIA_BUS_FMT_* value on success or 0 in case of failure.
887 */
888u32 drm_mipi_dsi_get_input_bus_fmt(enum mipi_dsi_pixel_format dsi_format)
889{
890 switch (dsi_format) {
891 case MIPI_DSI_FMT_RGB888:
892 return MEDIA_BUS_FMT_RGB888_1X24;
893
894 case MIPI_DSI_FMT_RGB666:
895 return MEDIA_BUS_FMT_RGB666_1X24_CPADHI;
896
897 case MIPI_DSI_FMT_RGB666_PACKED:
898 return MEDIA_BUS_FMT_RGB666_1X18;
899
900 case MIPI_DSI_FMT_RGB565:
901 return MEDIA_BUS_FMT_RGB565_1X16;
902
903 default:
904 /* Unsupported DSI Format */
905 return 0;
906 }
907}
908EXPORT_SYMBOL(drm_mipi_dsi_get_input_bus_fmt);
909
910/**
911 * mipi_dsi_dcs_write_buffer() - transmit a DCS command with payload
912 * @dsi: DSI peripheral device
913 * @data: buffer containing data to be transmitted
914 * @len: size of transmission buffer
915 *
916 * This function will automatically choose the right data type depending on
917 * the command payload length.
918 *
919 * Return: The number of bytes successfully transmitted or a negative error
920 * code on failure.
921 */
922ssize_t mipi_dsi_dcs_write_buffer(struct mipi_dsi_device *dsi,
923 const void *data, size_t len)
924{
925 struct mipi_dsi_msg msg = {
926 .channel = dsi->channel,
927 .tx_buf = data,
928 .tx_len = len
929 };
930
931 switch (len) {
932 case 0:
933 return -EINVAL;
934
935 case 1:
936 msg.type = MIPI_DSI_DCS_SHORT_WRITE;
937 break;
938
939 case 2:
940 msg.type = MIPI_DSI_DCS_SHORT_WRITE_PARAM;
941 break;
942
943 default:
944 msg.type = MIPI_DSI_DCS_LONG_WRITE;
945 break;
946 }
947
948 return mipi_dsi_device_transfer(dsi, msg: &msg);
949}
950EXPORT_SYMBOL(mipi_dsi_dcs_write_buffer);
951
952/**
953 * mipi_dsi_dcs_write_buffer_chatty - mipi_dsi_dcs_write_buffer() w/ an error log
954 * @dsi: DSI peripheral device
955 * @data: buffer containing data to be transmitted
956 * @len: size of transmission buffer
957 *
958 * Like mipi_dsi_dcs_write_buffer() but includes a dev_err()
959 * call for you and returns 0 upon success, not the number of bytes sent.
960 *
961 * Return: 0 on success or a negative error code on failure.
962 */
963int mipi_dsi_dcs_write_buffer_chatty(struct mipi_dsi_device *dsi,
964 const void *data, size_t len)
965{
966 struct device *dev = &dsi->dev;
967 ssize_t ret;
968
969 ret = mipi_dsi_dcs_write_buffer(dsi, data, len);
970 if (ret < 0) {
971 dev_err(dev, "sending dcs data %*ph failed: %zd\n",
972 (int)len, data, ret);
973 return ret;
974 }
975
976 return 0;
977}
978EXPORT_SYMBOL(mipi_dsi_dcs_write_buffer_chatty);
979
980/**
981 * mipi_dsi_dcs_write_buffer_multi - mipi_dsi_dcs_write_buffer_chatty() w/ accum_err
982 * @ctx: Context for multiple DSI transactions
983 * @data: buffer containing data to be transmitted
984 * @len: size of transmission buffer
985 *
986 * Like mipi_dsi_dcs_write_buffer_chatty() but deals with errors in a way that
987 * makes it convenient to make several calls in a row.
988 */
989void mipi_dsi_dcs_write_buffer_multi(struct mipi_dsi_multi_context *ctx,
990 const void *data, size_t len)
991{
992 struct mipi_dsi_device *dsi = ctx->dsi;
993 struct device *dev = &dsi->dev;
994 ssize_t ret;
995
996 if (ctx->accum_err)
997 return;
998
999 ret = mipi_dsi_dcs_write_buffer(dsi, data, len);
1000 if (ret < 0) {
1001 ctx->accum_err = ret;
1002 dev_err(dev, "sending dcs data %*ph failed: %d\n",
1003 (int)len, data, ctx->accum_err);
1004 }
1005}
1006EXPORT_SYMBOL(mipi_dsi_dcs_write_buffer_multi);
1007
1008/**
1009 * mipi_dsi_dcs_write() - send DCS write command
1010 * @dsi: DSI peripheral device
1011 * @cmd: DCS command
1012 * @data: buffer containing the command payload
1013 * @len: command payload length
1014 *
1015 * This function will automatically choose the right data type depending on
1016 * the command payload length.
1017 *
1018 * Return: The number of bytes successfully transmitted or a negative error
1019 * code on failure.
1020 */
1021ssize_t mipi_dsi_dcs_write(struct mipi_dsi_device *dsi, u8 cmd,
1022 const void *data, size_t len)
1023{
1024 ssize_t err;
1025 size_t size;
1026 u8 stack_tx[8];
1027 u8 *tx;
1028
1029 size = 1 + len;
1030 if (len > ARRAY_SIZE(stack_tx) - 1) {
1031 tx = kmalloc(size, GFP_KERNEL);
1032 if (!tx)
1033 return -ENOMEM;
1034 } else {
1035 tx = stack_tx;
1036 }
1037
1038 /* concatenate the DCS command byte and the payload */
1039 tx[0] = cmd;
1040 if (data)
1041 memcpy(&tx[1], data, len);
1042
1043 err = mipi_dsi_dcs_write_buffer(dsi, tx, size);
1044
1045 if (tx != stack_tx)
1046 kfree(objp: tx);
1047
1048 return err;
1049}
1050EXPORT_SYMBOL(mipi_dsi_dcs_write);
1051
1052/**
1053 * mipi_dsi_dcs_read() - send DCS read request command
1054 * @dsi: DSI peripheral device
1055 * @cmd: DCS command
1056 * @data: buffer in which to receive data
1057 * @len: size of receive buffer
1058 *
1059 * Return: The number of bytes read or a negative error code on failure.
1060 */
1061ssize_t mipi_dsi_dcs_read(struct mipi_dsi_device *dsi, u8 cmd, void *data,
1062 size_t len)
1063{
1064 struct mipi_dsi_msg msg = {
1065 .channel = dsi->channel,
1066 .type = MIPI_DSI_DCS_READ,
1067 .tx_buf = &cmd,
1068 .tx_len = 1,
1069 .rx_buf = data,
1070 .rx_len = len
1071 };
1072
1073 return mipi_dsi_device_transfer(dsi, msg: &msg);
1074}
1075EXPORT_SYMBOL(mipi_dsi_dcs_read);
1076
1077/**
1078 * mipi_dsi_dcs_nop() - send DCS nop packet
1079 * @dsi: DSI peripheral device
1080 *
1081 * This function is deprecated. Use mipi_dsi_dcs_nop_multi() instead.
1082 *
1083 * Return: 0 on success or a negative error code on failure.
1084 */
1085int mipi_dsi_dcs_nop(struct mipi_dsi_device *dsi)
1086{
1087 ssize_t err;
1088
1089 err = mipi_dsi_dcs_write(dsi, MIPI_DCS_NOP, NULL, 0);
1090 if (err < 0)
1091 return err;
1092
1093 return 0;
1094}
1095EXPORT_SYMBOL(mipi_dsi_dcs_nop);
1096
1097/**
1098 * mipi_dsi_dcs_soft_reset() - perform a software reset of the display module
1099 * @dsi: DSI peripheral device
1100 *
1101 * This function is deprecated. Use mipi_dsi_dcs_soft_reset_multi() instead.
1102 *
1103 * Return: 0 on success or a negative error code on failure.
1104 */
1105int mipi_dsi_dcs_soft_reset(struct mipi_dsi_device *dsi)
1106{
1107 ssize_t err;
1108
1109 err = mipi_dsi_dcs_write(dsi, MIPI_DCS_SOFT_RESET, NULL, 0);
1110 if (err < 0)
1111 return err;
1112
1113 return 0;
1114}
1115EXPORT_SYMBOL(mipi_dsi_dcs_soft_reset);
1116
1117/**
1118 * mipi_dsi_dcs_get_power_mode() - query the display module's current power
1119 * mode
1120 * @dsi: DSI peripheral device
1121 * @mode: return location for the current power mode
1122 *
1123 * Return: 0 on success or a negative error code on failure.
1124 */
1125int mipi_dsi_dcs_get_power_mode(struct mipi_dsi_device *dsi, u8 *mode)
1126{
1127 ssize_t err;
1128
1129 err = mipi_dsi_dcs_read(dsi, MIPI_DCS_GET_POWER_MODE, mode,
1130 sizeof(*mode));
1131 if (err <= 0) {
1132 if (err == 0)
1133 err = -ENODATA;
1134
1135 return err;
1136 }
1137
1138 return 0;
1139}
1140EXPORT_SYMBOL(mipi_dsi_dcs_get_power_mode);
1141
1142/**
1143 * mipi_dsi_dcs_get_pixel_format() - gets the pixel format for the RGB image
1144 * data used by the interface
1145 * @dsi: DSI peripheral device
1146 * @format: return location for the pixel format
1147 *
1148 * Return: 0 on success or a negative error code on failure.
1149 */
1150int mipi_dsi_dcs_get_pixel_format(struct mipi_dsi_device *dsi, u8 *format)
1151{
1152 ssize_t err;
1153
1154 err = mipi_dsi_dcs_read(dsi, MIPI_DCS_GET_PIXEL_FORMAT, format,
1155 sizeof(*format));
1156 if (err <= 0) {
1157 if (err == 0)
1158 err = -ENODATA;
1159
1160 return err;
1161 }
1162
1163 return 0;
1164}
1165EXPORT_SYMBOL(mipi_dsi_dcs_get_pixel_format);
1166
1167/**
1168 * mipi_dsi_dcs_enter_sleep_mode() - disable all unnecessary blocks inside the
1169 * display module except interface communication
1170 * @dsi: DSI peripheral device
1171 *
1172 * This function is deprecated. Use mipi_dsi_dcs_enter_sleep_mode_multi() instead.
1173 *
1174 * Return: 0 on success or a negative error code on failure.
1175 */
1176int mipi_dsi_dcs_enter_sleep_mode(struct mipi_dsi_device *dsi)
1177{
1178 ssize_t err;
1179
1180 err = mipi_dsi_dcs_write(dsi, MIPI_DCS_ENTER_SLEEP_MODE, NULL, 0);
1181 if (err < 0)
1182 return err;
1183
1184 return 0;
1185}
1186EXPORT_SYMBOL(mipi_dsi_dcs_enter_sleep_mode);
1187
1188/**
1189 * mipi_dsi_dcs_exit_sleep_mode() - enable all blocks inside the display
1190 * module
1191 * @dsi: DSI peripheral device
1192 *
1193 * This function is deprecated. Use mipi_dsi_dcs_exit_sleep_mode_multi() instead.
1194 *
1195 * Return: 0 on success or a negative error code on failure.
1196 */
1197int mipi_dsi_dcs_exit_sleep_mode(struct mipi_dsi_device *dsi)
1198{
1199 ssize_t err;
1200
1201 err = mipi_dsi_dcs_write(dsi, MIPI_DCS_EXIT_SLEEP_MODE, NULL, 0);
1202 if (err < 0)
1203 return err;
1204
1205 return 0;
1206}
1207EXPORT_SYMBOL(mipi_dsi_dcs_exit_sleep_mode);
1208
1209/**
1210 * mipi_dsi_dcs_set_display_off() - stop displaying the image data on the
1211 * display device
1212 * @dsi: DSI peripheral device
1213 *
1214 * This function is deprecated. Use mipi_dsi_dcs_set_display_off_multi() instead.
1215 *
1216 * Return: 0 on success or a negative error code on failure.
1217 */
1218int mipi_dsi_dcs_set_display_off(struct mipi_dsi_device *dsi)
1219{
1220 ssize_t err;
1221
1222 err = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_DISPLAY_OFF, NULL, 0);
1223 if (err < 0)
1224 return err;
1225
1226 return 0;
1227}
1228EXPORT_SYMBOL(mipi_dsi_dcs_set_display_off);
1229
1230/**
1231 * mipi_dsi_dcs_set_display_on() - start displaying the image data on the
1232 * display device
1233 * @dsi: DSI peripheral device
1234 *
1235 * This function is deprecated. Use mipi_dsi_dcs_set_display_on_multi() instead.
1236 *
1237 * Return: 0 on success or a negative error code on failure
1238 */
1239int mipi_dsi_dcs_set_display_on(struct mipi_dsi_device *dsi)
1240{
1241 ssize_t err;
1242
1243 err = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_DISPLAY_ON, NULL, 0);
1244 if (err < 0)
1245 return err;
1246
1247 return 0;
1248}
1249EXPORT_SYMBOL(mipi_dsi_dcs_set_display_on);
1250
1251/**
1252 * mipi_dsi_dcs_set_column_address() - define the column extent of the frame
1253 * memory accessed by the host processor
1254 * @dsi: DSI peripheral device
1255 * @start: first column of frame memory
1256 * @end: last column of frame memory
1257 *
1258 * This function is deprecated. Use mipi_dsi_dcs_set_column_address_multi()
1259 * instead.
1260 *
1261 * Return: 0 on success or a negative error code on failure.
1262 */
1263int mipi_dsi_dcs_set_column_address(struct mipi_dsi_device *dsi, u16 start,
1264 u16 end)
1265{
1266 u8 payload[4] = { start >> 8, start & 0xff, end >> 8, end & 0xff };
1267 ssize_t err;
1268
1269 err = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_COLUMN_ADDRESS, payload,
1270 sizeof(payload));
1271 if (err < 0)
1272 return err;
1273
1274 return 0;
1275}
1276EXPORT_SYMBOL(mipi_dsi_dcs_set_column_address);
1277
1278/**
1279 * mipi_dsi_dcs_set_page_address() - define the page extent of the frame
1280 * memory accessed by the host processor
1281 * @dsi: DSI peripheral device
1282 * @start: first page of frame memory
1283 * @end: last page of frame memory
1284 *
1285 * This function is deprecated. Use mipi_dsi_dcs_set_page_address_multi()
1286 * instead.
1287 *
1288 * Return: 0 on success or a negative error code on failure.
1289 */
1290int mipi_dsi_dcs_set_page_address(struct mipi_dsi_device *dsi, u16 start,
1291 u16 end)
1292{
1293 u8 payload[4] = { start >> 8, start & 0xff, end >> 8, end & 0xff };
1294 ssize_t err;
1295
1296 err = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_PAGE_ADDRESS, payload,
1297 sizeof(payload));
1298 if (err < 0)
1299 return err;
1300
1301 return 0;
1302}
1303EXPORT_SYMBOL(mipi_dsi_dcs_set_page_address);
1304
1305/**
1306 * mipi_dsi_dcs_set_tear_on() - turn on the display module's Tearing Effect
1307 * output signal on the TE signal line.
1308 * @dsi: DSI peripheral device
1309 * @mode: the Tearing Effect Output Line mode
1310 *
1311 * This function is deprecated. Use mipi_dsi_dcs_set_tear_on_multi() instead.
1312 *
1313 * Return: 0 on success or a negative error code on failure
1314 */
1315int mipi_dsi_dcs_set_tear_on(struct mipi_dsi_device *dsi,
1316 enum mipi_dsi_dcs_tear_mode mode)
1317{
1318 u8 value = mode;
1319 ssize_t err;
1320
1321 err = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_TEAR_ON, &value,
1322 sizeof(value));
1323 if (err < 0)
1324 return err;
1325
1326 return 0;
1327}
1328EXPORT_SYMBOL(mipi_dsi_dcs_set_tear_on);
1329
1330/**
1331 * mipi_dsi_dcs_set_pixel_format() - sets the pixel format for the RGB image
1332 * data used by the interface
1333 * @dsi: DSI peripheral device
1334 * @format: pixel format
1335 *
1336 * This function is deprecated. Use mipi_dsi_dcs_set_pixel_format_multi()
1337 * instead.
1338 *
1339 * Return: 0 on success or a negative error code on failure.
1340 */
1341int mipi_dsi_dcs_set_pixel_format(struct mipi_dsi_device *dsi, u8 format)
1342{
1343 ssize_t err;
1344
1345 err = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_PIXEL_FORMAT, &format,
1346 sizeof(format));
1347 if (err < 0)
1348 return err;
1349
1350 return 0;
1351}
1352EXPORT_SYMBOL(mipi_dsi_dcs_set_pixel_format);
1353
1354/**
1355 * mipi_dsi_dcs_set_tear_scanline() - set the scanline to use as trigger for
1356 * the Tearing Effect output signal of the display module
1357 * @dsi: DSI peripheral device
1358 * @scanline: scanline to use as trigger
1359 *
1360 * This function is deprecated. Use mipi_dsi_dcs_set_tear_scanline_multi()
1361 * instead.
1362 *
1363 * Return: 0 on success or a negative error code on failure
1364 */
1365int mipi_dsi_dcs_set_tear_scanline(struct mipi_dsi_device *dsi, u16 scanline)
1366{
1367 u8 payload[2] = { scanline >> 8, scanline & 0xff };
1368 ssize_t err;
1369
1370 err = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_TEAR_SCANLINE, payload,
1371 sizeof(payload));
1372 if (err < 0)
1373 return err;
1374
1375 return 0;
1376}
1377EXPORT_SYMBOL(mipi_dsi_dcs_set_tear_scanline);
1378
1379/**
1380 * mipi_dsi_dcs_set_display_brightness() - sets the brightness value of the
1381 * display
1382 * @dsi: DSI peripheral device
1383 * @brightness: brightness value
1384 *
1385 * This function is deprecated. Use mipi_dsi_dcs_set_display_brightness_multi()
1386 * instead.
1387 *
1388 * Return: 0 on success or a negative error code on failure.
1389 */
1390int mipi_dsi_dcs_set_display_brightness(struct mipi_dsi_device *dsi,
1391 u16 brightness)
1392{
1393 u8 payload[2] = { brightness & 0xff, brightness >> 8 };
1394 ssize_t err;
1395
1396 err = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_DISPLAY_BRIGHTNESS,
1397 payload, sizeof(payload));
1398 if (err < 0)
1399 return err;
1400
1401 return 0;
1402}
1403EXPORT_SYMBOL(mipi_dsi_dcs_set_display_brightness);
1404
1405/**
1406 * mipi_dsi_dcs_get_display_brightness() - gets the current brightness value
1407 * of the display
1408 * @dsi: DSI peripheral device
1409 * @brightness: brightness value
1410 *
1411 * Return: 0 on success or a negative error code on failure.
1412 */
1413int mipi_dsi_dcs_get_display_brightness(struct mipi_dsi_device *dsi,
1414 u16 *brightness)
1415{
1416 ssize_t err;
1417
1418 err = mipi_dsi_dcs_read(dsi, MIPI_DCS_GET_DISPLAY_BRIGHTNESS,
1419 brightness, sizeof(*brightness));
1420 if (err <= 0) {
1421 if (err == 0)
1422 err = -ENODATA;
1423
1424 return err;
1425 }
1426
1427 return 0;
1428}
1429EXPORT_SYMBOL(mipi_dsi_dcs_get_display_brightness);
1430
1431/**
1432 * mipi_dsi_dcs_set_display_brightness_large() - sets the 16-bit brightness value
1433 * of the display
1434 * @dsi: DSI peripheral device
1435 * @brightness: brightness value
1436 *
1437 * Return: 0 on success or a negative error code on failure.
1438 */
1439int mipi_dsi_dcs_set_display_brightness_large(struct mipi_dsi_device *dsi,
1440 u16 brightness)
1441{
1442 u8 payload[2] = { brightness >> 8, brightness & 0xff };
1443 ssize_t err;
1444
1445 err = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_DISPLAY_BRIGHTNESS,
1446 payload, sizeof(payload));
1447 if (err < 0)
1448 return err;
1449
1450 return 0;
1451}
1452EXPORT_SYMBOL(mipi_dsi_dcs_set_display_brightness_large);
1453
1454/**
1455 * mipi_dsi_dcs_get_display_brightness_large() - gets the current 16-bit
1456 * brightness value of the display
1457 * @dsi: DSI peripheral device
1458 * @brightness: brightness value
1459 *
1460 * Return: 0 on success or a negative error code on failure.
1461 */
1462int mipi_dsi_dcs_get_display_brightness_large(struct mipi_dsi_device *dsi,
1463 u16 *brightness)
1464{
1465 u8 brightness_be[2];
1466 ssize_t err;
1467
1468 err = mipi_dsi_dcs_read(dsi, MIPI_DCS_GET_DISPLAY_BRIGHTNESS,
1469 brightness_be, sizeof(brightness_be));
1470 if (err <= 0) {
1471 if (err == 0)
1472 err = -ENODATA;
1473
1474 return err;
1475 }
1476
1477 *brightness = (brightness_be[0] << 8) | brightness_be[1];
1478
1479 return 0;
1480}
1481EXPORT_SYMBOL(mipi_dsi_dcs_get_display_brightness_large);
1482
1483/**
1484 * mipi_dsi_picture_parameter_set_multi() - transmit the DSC PPS to the peripheral
1485 * @ctx: Context for multiple DSI transactions
1486 * @pps: VESA DSC 1.1 Picture Parameter Set
1487 *
1488 * Like mipi_dsi_picture_parameter_set() but deals with errors in a way that
1489 * makes it convenient to make several calls in a row.
1490 */
1491void mipi_dsi_picture_parameter_set_multi(struct mipi_dsi_multi_context *ctx,
1492 const struct drm_dsc_picture_parameter_set *pps)
1493{
1494 struct mipi_dsi_device *dsi = ctx->dsi;
1495 struct device *dev = &dsi->dev;
1496 ssize_t ret;
1497
1498 if (ctx->accum_err)
1499 return;
1500
1501 ret = mipi_dsi_picture_parameter_set(dsi, pps);
1502 if (ret < 0) {
1503 ctx->accum_err = ret;
1504 dev_err(dev, "sending PPS failed: %d\n",
1505 ctx->accum_err);
1506 }
1507}
1508EXPORT_SYMBOL(mipi_dsi_picture_parameter_set_multi);
1509
1510/**
1511 * mipi_dsi_compression_mode_ext_multi() - enable/disable DSC on the peripheral
1512 * @ctx: Context for multiple DSI transactions
1513 * @enable: Whether to enable or disable the DSC
1514 * @algo: Selected compression algorithm
1515 * @pps_selector: Select PPS from the table of pre-stored or uploaded PPS entries
1516 *
1517 * Like mipi_dsi_compression_mode_ext() but deals with errors in a way that
1518 * makes it convenient to make several calls in a row.
1519 */
1520void mipi_dsi_compression_mode_ext_multi(struct mipi_dsi_multi_context *ctx,
1521 bool enable,
1522 enum mipi_dsi_compression_algo algo,
1523 unsigned int pps_selector)
1524{
1525 struct mipi_dsi_device *dsi = ctx->dsi;
1526 struct device *dev = &dsi->dev;
1527 ssize_t ret;
1528
1529 if (ctx->accum_err)
1530 return;
1531
1532 ret = mipi_dsi_compression_mode_ext(dsi, enable, algo, pps_selector);
1533 if (ret < 0) {
1534 ctx->accum_err = ret;
1535 dev_err(dev, "sending COMPRESSION_MODE failed: %d\n",
1536 ctx->accum_err);
1537 }
1538}
1539EXPORT_SYMBOL(mipi_dsi_compression_mode_ext_multi);
1540
1541/**
1542 * mipi_dsi_compression_mode_multi() - enable/disable DSC on the peripheral
1543 * @ctx: Context for multiple DSI transactions
1544 * @enable: Whether to enable or disable the DSC
1545 *
1546 * Enable or disable Display Stream Compression on the peripheral using the
1547 * default Picture Parameter Set and VESA DSC 1.1 algorithm.
1548 */
1549void mipi_dsi_compression_mode_multi(struct mipi_dsi_multi_context *ctx,
1550 bool enable)
1551{
1552 return mipi_dsi_compression_mode_ext_multi(ctx, enable,
1553 MIPI_DSI_COMPRESSION_DSC, 0);
1554}
1555EXPORT_SYMBOL(mipi_dsi_compression_mode_multi);
1556
1557/**
1558 * mipi_dsi_dcs_nop_multi() - send DCS NOP packet
1559 * @ctx: Context for multiple DSI transactions
1560 *
1561 * Like mipi_dsi_dcs_nop() but deals with errors in a way that
1562 * makes it convenient to make several calls in a row.
1563 */
1564void mipi_dsi_dcs_nop_multi(struct mipi_dsi_multi_context *ctx)
1565{
1566 struct mipi_dsi_device *dsi = ctx->dsi;
1567 struct device *dev = &dsi->dev;
1568 ssize_t ret;
1569
1570 if (ctx->accum_err)
1571 return;
1572
1573 ret = mipi_dsi_dcs_nop(dsi);
1574 if (ret < 0) {
1575 ctx->accum_err = ret;
1576 dev_err(dev, "sending DCS NOP failed: %d\n",
1577 ctx->accum_err);
1578 }
1579}
1580EXPORT_SYMBOL(mipi_dsi_dcs_nop_multi);
1581
1582/**
1583 * mipi_dsi_dcs_enter_sleep_mode_multi() - send DCS ENTER_SLEEP_MODE packet
1584 * @ctx: Context for multiple DSI transactions
1585 *
1586 * Like mipi_dsi_dcs_enter_sleep_mode() but deals with errors in a way that
1587 * makes it convenient to make several calls in a row.
1588 */
1589void mipi_dsi_dcs_enter_sleep_mode_multi(struct mipi_dsi_multi_context *ctx)
1590{
1591 struct mipi_dsi_device *dsi = ctx->dsi;
1592 struct device *dev = &dsi->dev;
1593 ssize_t ret;
1594
1595 if (ctx->accum_err)
1596 return;
1597
1598 ret = mipi_dsi_dcs_enter_sleep_mode(dsi);
1599 if (ret < 0) {
1600 ctx->accum_err = ret;
1601 dev_err(dev, "sending DCS ENTER_SLEEP_MODE failed: %d\n",
1602 ctx->accum_err);
1603 }
1604}
1605EXPORT_SYMBOL(mipi_dsi_dcs_enter_sleep_mode_multi);
1606
1607/**
1608 * mipi_dsi_dcs_exit_sleep_mode_multi() - send DCS EXIT_SLEEP_MODE packet
1609 * @ctx: Context for multiple DSI transactions
1610 *
1611 * Like mipi_dsi_dcs_exit_sleep_mode() but deals with errors in a way that
1612 * makes it convenient to make several calls in a row.
1613 */
1614void mipi_dsi_dcs_exit_sleep_mode_multi(struct mipi_dsi_multi_context *ctx)
1615{
1616 struct mipi_dsi_device *dsi = ctx->dsi;
1617 struct device *dev = &dsi->dev;
1618 ssize_t ret;
1619
1620 if (ctx->accum_err)
1621 return;
1622
1623 ret = mipi_dsi_dcs_exit_sleep_mode(dsi);
1624 if (ret < 0) {
1625 ctx->accum_err = ret;
1626 dev_err(dev, "sending DCS EXIT_SLEEP_MODE failed: %d\n",
1627 ctx->accum_err);
1628 }
1629}
1630EXPORT_SYMBOL(mipi_dsi_dcs_exit_sleep_mode_multi);
1631
1632/**
1633 * mipi_dsi_dcs_set_display_off_multi() - send DCS SET_DISPLAY_OFF packet
1634 * @ctx: Context for multiple DSI transactions
1635 *
1636 * Like mipi_dsi_dcs_set_display_off() but deals with errors in a way that
1637 * makes it convenient to make several calls in a row.
1638 */
1639void mipi_dsi_dcs_set_display_off_multi(struct mipi_dsi_multi_context *ctx)
1640{
1641 struct mipi_dsi_device *dsi = ctx->dsi;
1642 struct device *dev = &dsi->dev;
1643 ssize_t ret;
1644
1645 if (ctx->accum_err)
1646 return;
1647
1648 ret = mipi_dsi_dcs_set_display_off(dsi);
1649 if (ret < 0) {
1650 ctx->accum_err = ret;
1651 dev_err(dev, "sending DCS SET_DISPLAY_OFF failed: %d\n",
1652 ctx->accum_err);
1653 }
1654}
1655EXPORT_SYMBOL(mipi_dsi_dcs_set_display_off_multi);
1656
1657/**
1658 * mipi_dsi_dcs_set_display_on_multi() - send DCS SET_DISPLAY_ON packet
1659 * @ctx: Context for multiple DSI transactions
1660 *
1661 * Like mipi_dsi_dcs_set_display_on() but deals with errors in a way that
1662 * makes it convenient to make several calls in a row.
1663 */
1664void mipi_dsi_dcs_set_display_on_multi(struct mipi_dsi_multi_context *ctx)
1665{
1666 struct mipi_dsi_device *dsi = ctx->dsi;
1667 struct device *dev = &dsi->dev;
1668 ssize_t ret;
1669
1670 if (ctx->accum_err)
1671 return;
1672
1673 ret = mipi_dsi_dcs_set_display_on(dsi);
1674 if (ret < 0) {
1675 ctx->accum_err = ret;
1676 dev_err(dev, "sending DCS SET_DISPLAY_ON failed: %d\n",
1677 ctx->accum_err);
1678 }
1679}
1680EXPORT_SYMBOL(mipi_dsi_dcs_set_display_on_multi);
1681
1682/**
1683 * mipi_dsi_dcs_set_tear_on_multi() - send DCS SET_TEAR_ON packet
1684 * @ctx: Context for multiple DSI transactions
1685 * @mode: the Tearing Effect Output Line mode
1686 *
1687 * Like mipi_dsi_dcs_set_tear_on() but deals with errors in a way that
1688 * makes it convenient to make several calls in a row.
1689 */
1690void mipi_dsi_dcs_set_tear_on_multi(struct mipi_dsi_multi_context *ctx,
1691 enum mipi_dsi_dcs_tear_mode mode)
1692{
1693 struct mipi_dsi_device *dsi = ctx->dsi;
1694 struct device *dev = &dsi->dev;
1695 ssize_t ret;
1696
1697 if (ctx->accum_err)
1698 return;
1699
1700 ret = mipi_dsi_dcs_set_tear_on(dsi, mode);
1701 if (ret < 0) {
1702 ctx->accum_err = ret;
1703 dev_err(dev, "sending DCS SET_TEAR_ON failed: %d\n",
1704 ctx->accum_err);
1705 }
1706}
1707EXPORT_SYMBOL(mipi_dsi_dcs_set_tear_on_multi);
1708
1709/**
1710 * mipi_dsi_turn_on_peripheral_multi() - sends a Turn On Peripheral command
1711 * @ctx: Context for multiple DSI transactions
1712 *
1713 * Like mipi_dsi_turn_on_peripheral() but deals with errors in a way that
1714 * makes it convenient to make several calls in a row.
1715 */
1716void mipi_dsi_turn_on_peripheral_multi(struct mipi_dsi_multi_context *ctx)
1717{
1718 struct mipi_dsi_device *dsi = ctx->dsi;
1719 struct device *dev = &dsi->dev;
1720 int ret;
1721
1722 if (ctx->accum_err)
1723 return;
1724
1725 ret = mipi_dsi_turn_on_peripheral(dsi);
1726 if (ret < 0) {
1727 ctx->accum_err = ret;
1728 dev_err(dev, "Failed to turn on peripheral: %d\n",
1729 ctx->accum_err);
1730 }
1731}
1732EXPORT_SYMBOL(mipi_dsi_turn_on_peripheral_multi);
1733
1734/**
1735 * mipi_dsi_dcs_set_tear_off_multi() - turn off the display module's Tearing Effect
1736 * output signal on the TE signal line
1737 * @ctx: Context for multiple DSI transactions
1738 */
1739void mipi_dsi_dcs_set_tear_off_multi(struct mipi_dsi_multi_context *ctx)
1740{
1741 struct mipi_dsi_device *dsi = ctx->dsi;
1742 struct device *dev = &dsi->dev;
1743 ssize_t err;
1744
1745 if (ctx->accum_err)
1746 return;
1747
1748 err = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_TEAR_OFF, NULL, 0);
1749 if (err < 0) {
1750 ctx->accum_err = err;
1751 dev_err(dev, "Failed to set tear off: %d\n",
1752 ctx->accum_err);
1753 }
1754}
1755EXPORT_SYMBOL(mipi_dsi_dcs_set_tear_off_multi);
1756
1757/**
1758 * mipi_dsi_dcs_soft_reset_multi() - perform a software reset of the display module
1759 * @ctx: Context for multiple DSI transactions
1760 *
1761 * Like mipi_dsi_dcs_soft_reset() but deals with errors in a way that
1762 * makes it convenient to make several calls in a row.
1763 */
1764void mipi_dsi_dcs_soft_reset_multi(struct mipi_dsi_multi_context *ctx)
1765{
1766 struct mipi_dsi_device *dsi = ctx->dsi;
1767 struct device *dev = &dsi->dev;
1768 int ret;
1769
1770 if (ctx->accum_err)
1771 return;
1772
1773 ret = mipi_dsi_dcs_soft_reset(dsi);
1774 if (ret < 0) {
1775 ctx->accum_err = ret;
1776 dev_err(dev, "Failed to mipi_dsi_dcs_soft_reset: %d\n",
1777 ctx->accum_err);
1778 }
1779}
1780EXPORT_SYMBOL(mipi_dsi_dcs_soft_reset_multi);
1781
1782/**
1783 * mipi_dsi_dcs_set_display_brightness_multi() - sets the brightness value of
1784 * the display
1785 * @ctx: Context for multiple DSI transactions
1786 * @brightness: brightness value
1787 *
1788 * Like mipi_dsi_dcs_set_display_brightness() but deals with errors in a way that
1789 * makes it convenient to make several calls in a row.
1790 */
1791void mipi_dsi_dcs_set_display_brightness_multi(struct mipi_dsi_multi_context *ctx,
1792 u16 brightness)
1793{
1794 struct mipi_dsi_device *dsi = ctx->dsi;
1795 struct device *dev = &dsi->dev;
1796 int ret;
1797
1798 if (ctx->accum_err)
1799 return;
1800
1801 ret = mipi_dsi_dcs_set_display_brightness(dsi, brightness);
1802 if (ret < 0) {
1803 ctx->accum_err = ret;
1804 dev_err(dev, "Failed to write display brightness: %d\n",
1805 ctx->accum_err);
1806 }
1807}
1808EXPORT_SYMBOL(mipi_dsi_dcs_set_display_brightness_multi);
1809
1810/**
1811 * mipi_dsi_dcs_set_pixel_format_multi() - sets the pixel format for the RGB image
1812 * data used by the interface
1813 * @ctx: Context for multiple DSI transactions
1814 * @format: pixel format
1815 *
1816 * Like mipi_dsi_dcs_set_pixel_format() but deals with errors in a way that
1817 * makes it convenient to make several calls in a row.
1818 */
1819void mipi_dsi_dcs_set_pixel_format_multi(struct mipi_dsi_multi_context *ctx,
1820 u8 format)
1821{
1822 struct mipi_dsi_device *dsi = ctx->dsi;
1823 struct device *dev = &dsi->dev;
1824 int ret;
1825
1826 if (ctx->accum_err)
1827 return;
1828
1829 ret = mipi_dsi_dcs_set_pixel_format(dsi, format);
1830 if (ret < 0) {
1831 ctx->accum_err = ret;
1832 dev_err(dev, "Failed to set pixel format: %d\n",
1833 ctx->accum_err);
1834 }
1835}
1836EXPORT_SYMBOL(mipi_dsi_dcs_set_pixel_format_multi);
1837
1838/**
1839 * mipi_dsi_dcs_set_column_address_multi() - define the column extent of the
1840 * frame memory accessed by the host processor
1841 * @ctx: Context for multiple DSI transactions
1842 * @start: first column of frame memory
1843 * @end: last column of frame memory
1844 *
1845 * Like mipi_dsi_dcs_set_column_address() but deals with errors in a way that
1846 * makes it convenient to make several calls in a row.
1847 */
1848void mipi_dsi_dcs_set_column_address_multi(struct mipi_dsi_multi_context *ctx,
1849 u16 start, u16 end)
1850{
1851 struct mipi_dsi_device *dsi = ctx->dsi;
1852 struct device *dev = &dsi->dev;
1853 int ret;
1854
1855 if (ctx->accum_err)
1856 return;
1857
1858 ret = mipi_dsi_dcs_set_column_address(dsi, start, end);
1859 if (ret < 0) {
1860 ctx->accum_err = ret;
1861 dev_err(dev, "Failed to set column address: %d\n",
1862 ctx->accum_err);
1863 }
1864}
1865EXPORT_SYMBOL(mipi_dsi_dcs_set_column_address_multi);
1866
1867/**
1868 * mipi_dsi_dcs_set_page_address_multi() - define the page extent of the
1869 * frame memory accessed by the host processor
1870 * @ctx: Context for multiple DSI transactions
1871 * @start: first page of frame memory
1872 * @end: last page of frame memory
1873 *
1874 * Like mipi_dsi_dcs_set_page_address() but deals with errors in a way that
1875 * makes it convenient to make several calls in a row.
1876 */
1877void mipi_dsi_dcs_set_page_address_multi(struct mipi_dsi_multi_context *ctx,
1878 u16 start, u16 end)
1879{
1880 struct mipi_dsi_device *dsi = ctx->dsi;
1881 struct device *dev = &dsi->dev;
1882 int ret;
1883
1884 if (ctx->accum_err)
1885 return;
1886
1887 ret = mipi_dsi_dcs_set_page_address(dsi, start, end);
1888 if (ret < 0) {
1889 ctx->accum_err = ret;
1890 dev_err(dev, "Failed to set page address: %d\n",
1891 ctx->accum_err);
1892 }
1893}
1894EXPORT_SYMBOL(mipi_dsi_dcs_set_page_address_multi);
1895
1896/**
1897 * mipi_dsi_dcs_set_tear_scanline_multi() - set the scanline to use as trigger for
1898 * the Tearing Effect output signal of the display module
1899 * @ctx: Context for multiple DSI transactions
1900 * @scanline: scanline to use as trigger
1901 *
1902 * Like mipi_dsi_dcs_set_tear_scanline() but deals with errors in a way that
1903 * makes it convenient to make several calls in a row.
1904 */
1905void mipi_dsi_dcs_set_tear_scanline_multi(struct mipi_dsi_multi_context *ctx,
1906 u16 scanline)
1907{
1908 struct mipi_dsi_device *dsi = ctx->dsi;
1909 struct device *dev = &dsi->dev;
1910 int ret;
1911
1912 if (ctx->accum_err)
1913 return;
1914
1915 ret = mipi_dsi_dcs_set_tear_scanline(dsi, scanline);
1916 if (ret < 0) {
1917 ctx->accum_err = ret;
1918 dev_err(dev, "Failed to set tear scanline: %d\n",
1919 ctx->accum_err);
1920 }
1921}
1922EXPORT_SYMBOL(mipi_dsi_dcs_set_tear_scanline_multi);
1923
1924static int mipi_dsi_drv_probe(struct device *dev)
1925{
1926 struct mipi_dsi_driver *drv = to_mipi_dsi_driver(driver: dev->driver);
1927 struct mipi_dsi_device *dsi = to_mipi_dsi_device(dev);
1928
1929 return drv->probe(dsi);
1930}
1931
1932static int mipi_dsi_drv_remove(struct device *dev)
1933{
1934 struct mipi_dsi_driver *drv = to_mipi_dsi_driver(driver: dev->driver);
1935 struct mipi_dsi_device *dsi = to_mipi_dsi_device(dev);
1936
1937 drv->remove(dsi);
1938
1939 return 0;
1940}
1941
1942static void mipi_dsi_drv_shutdown(struct device *dev)
1943{
1944 struct mipi_dsi_driver *drv = to_mipi_dsi_driver(driver: dev->driver);
1945 struct mipi_dsi_device *dsi = to_mipi_dsi_device(dev);
1946
1947 drv->shutdown(dsi);
1948}
1949
1950/**
1951 * mipi_dsi_driver_register_full() - register a driver for DSI devices
1952 * @drv: DSI driver structure
1953 * @owner: owner module
1954 *
1955 * Return: 0 on success or a negative error code on failure.
1956 */
1957int mipi_dsi_driver_register_full(struct mipi_dsi_driver *drv,
1958 struct module *owner)
1959{
1960 drv->driver.bus = &mipi_dsi_bus_type;
1961 drv->driver.owner = owner;
1962
1963 if (drv->probe)
1964 drv->driver.probe = mipi_dsi_drv_probe;
1965 if (drv->remove)
1966 drv->driver.remove = mipi_dsi_drv_remove;
1967 if (drv->shutdown)
1968 drv->driver.shutdown = mipi_dsi_drv_shutdown;
1969
1970 return driver_register(drv: &drv->driver);
1971}
1972EXPORT_SYMBOL(mipi_dsi_driver_register_full);
1973
1974/**
1975 * mipi_dsi_driver_unregister() - unregister a driver for DSI devices
1976 * @drv: DSI driver structure
1977 *
1978 * Return: 0 on success or a negative error code on failure.
1979 */
1980void mipi_dsi_driver_unregister(struct mipi_dsi_driver *drv)
1981{
1982 driver_unregister(drv: &drv->driver);
1983}
1984EXPORT_SYMBOL(mipi_dsi_driver_unregister);
1985
1986static int __init mipi_dsi_bus_init(void)
1987{
1988 return bus_register(bus: &mipi_dsi_bus_type);
1989}
1990postcore_initcall(mipi_dsi_bus_init);
1991
1992MODULE_AUTHOR("Andrzej Hajda <a.hajda@samsung.com>");
1993MODULE_DESCRIPTION("MIPI DSI Bus");
1994MODULE_LICENSE("GPL and additional rights");
1995

Provided by KDAB

Privacy Policy
Improve your Profiling and Debugging skills
Find out more

source code of linux/drivers/gpu/drm/drm_mipi_dsi.c