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