Line data Source code
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 <dev/pci/drm/drm_linux.h>
29 : #include <dev/pci/drm/drm_mipi_dsi.h>
30 :
31 : #ifdef __linux__
32 : #include <linux/device.h>
33 : #include <linux/module.h>
34 : #include <linux/of_device.h>
35 : #include <linux/pm_runtime.h>
36 : #include <linux/slab.h>
37 :
38 : #include <video/mipi_display.h>
39 : #endif
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 :
51 : #ifdef notyet
52 :
53 : static int mipi_dsi_device_match(struct device *dev, struct device_driver *drv)
54 : {
55 : return of_driver_match_device(dev, drv);
56 : }
57 :
58 : static const struct dev_pm_ops mipi_dsi_device_pm_ops = {
59 : .runtime_suspend = pm_generic_runtime_suspend,
60 : .runtime_resume = pm_generic_runtime_resume,
61 : .suspend = pm_generic_suspend,
62 : .resume = pm_generic_resume,
63 : .freeze = pm_generic_freeze,
64 : .thaw = pm_generic_thaw,
65 : .poweroff = pm_generic_poweroff,
66 : .restore = pm_generic_restore,
67 : };
68 :
69 : static struct bus_type mipi_dsi_bus_type = {
70 : .name = "mipi-dsi",
71 : .match = mipi_dsi_device_match,
72 : .pm = &mipi_dsi_device_pm_ops,
73 : };
74 :
75 : static int of_device_match(struct device *dev, void *data)
76 : {
77 : return dev->of_node == data;
78 : }
79 :
80 : /**
81 : * of_find_mipi_dsi_device_by_node() - find the MIPI DSI device matching a
82 : * device tree node
83 : * @np: device tree node
84 : *
85 : * Return: A pointer to the MIPI DSI device corresponding to @np or NULL if no
86 : * such device exists (or has not been registered yet).
87 : */
88 : struct mipi_dsi_device *of_find_mipi_dsi_device_by_node(struct device_node *np)
89 : {
90 : struct device *dev;
91 :
92 : dev = bus_find_device(&mipi_dsi_bus_type, NULL, np, of_device_match);
93 :
94 : return dev ? to_mipi_dsi_device(dev) : NULL;
95 : }
96 : EXPORT_SYMBOL(of_find_mipi_dsi_device_by_node);
97 :
98 : static void mipi_dsi_dev_release(struct device *dev)
99 : {
100 : struct mipi_dsi_device *dsi = to_mipi_dsi_device(dev);
101 :
102 : of_node_put(dev->of_node);
103 : kfree(dsi);
104 : }
105 :
106 : static const struct device_type mipi_dsi_device_type = {
107 : .release = mipi_dsi_dev_release,
108 : };
109 :
110 : static struct mipi_dsi_device *mipi_dsi_device_alloc(struct mipi_dsi_host *host)
111 : {
112 : struct mipi_dsi_device *dsi;
113 :
114 : dsi = kzalloc(sizeof(*dsi), GFP_KERNEL);
115 : if (!dsi)
116 : return ERR_PTR(-ENOMEM);
117 :
118 : dsi->host = host;
119 : dsi->dev.bus = &mipi_dsi_bus_type;
120 : dsi->dev.parent = host->dev;
121 : dsi->dev.type = &mipi_dsi_device_type;
122 :
123 : device_initialize(&dsi->dev);
124 :
125 : return dsi;
126 : }
127 :
128 : static int mipi_dsi_device_add(struct mipi_dsi_device *dsi)
129 : {
130 : struct mipi_dsi_host *host = dsi->host;
131 :
132 : dev_set_name(&dsi->dev, "%s.%d", dev_name(host->dev), dsi->channel);
133 :
134 : return device_add(&dsi->dev);
135 : }
136 :
137 : static struct mipi_dsi_device *
138 : of_mipi_dsi_device_add(struct mipi_dsi_host *host, struct device_node *node)
139 : {
140 : struct mipi_dsi_device *dsi;
141 : struct device *dev = host->dev;
142 : int ret;
143 : u32 reg;
144 :
145 : ret = of_property_read_u32(node, "reg", ®);
146 : if (ret) {
147 : dev_err(dev, "device node %s has no valid reg property: %d\n",
148 : node->full_name, ret);
149 : return ERR_PTR(-EINVAL);
150 : }
151 :
152 : if (reg > 3) {
153 : dev_err(dev, "device node %s has invalid reg property: %u\n",
154 : node->full_name, reg);
155 : return ERR_PTR(-EINVAL);
156 : }
157 :
158 : dsi = mipi_dsi_device_alloc(host);
159 : if (IS_ERR(dsi)) {
160 : dev_err(dev, "failed to allocate DSI device %s: %ld\n",
161 : node->full_name, PTR_ERR(dsi));
162 : return dsi;
163 : }
164 :
165 : dsi->dev.of_node = of_node_get(node);
166 : dsi->channel = reg;
167 :
168 : ret = mipi_dsi_device_add(dsi);
169 : if (ret) {
170 : dev_err(dev, "failed to add DSI device %s: %d\n",
171 : node->full_name, ret);
172 : kfree(dsi);
173 : return ERR_PTR(ret);
174 : }
175 :
176 : return dsi;
177 : }
178 :
179 : int mipi_dsi_host_register(struct mipi_dsi_host *host)
180 : {
181 : struct device_node *node;
182 :
183 : for_each_available_child_of_node(host->dev->of_node, node) {
184 : /* skip nodes without reg property */
185 : if (!of_find_property(node, "reg", NULL))
186 : continue;
187 : of_mipi_dsi_device_add(host, node);
188 : }
189 :
190 : return 0;
191 : }
192 : EXPORT_SYMBOL(mipi_dsi_host_register);
193 :
194 : static int mipi_dsi_remove_device_fn(struct device *dev, void *priv)
195 : {
196 : struct mipi_dsi_device *dsi = to_mipi_dsi_device(dev);
197 :
198 : device_unregister(&dsi->dev);
199 :
200 : return 0;
201 : }
202 :
203 : void mipi_dsi_host_unregister(struct mipi_dsi_host *host)
204 : {
205 : device_for_each_child(host->dev, NULL, mipi_dsi_remove_device_fn);
206 : }
207 : EXPORT_SYMBOL(mipi_dsi_host_unregister);
208 :
209 : #endif
210 :
211 : /**
212 : * mipi_dsi_attach - attach a DSI device to its DSI host
213 : * @dsi: DSI peripheral
214 : */
215 0 : int mipi_dsi_attach(struct mipi_dsi_device *dsi)
216 : {
217 0 : const struct mipi_dsi_host_ops *ops = dsi->host->ops;
218 :
219 0 : if (!ops || !ops->attach)
220 0 : return -ENOSYS;
221 :
222 0 : return ops->attach(dsi->host, dsi);
223 0 : }
224 : EXPORT_SYMBOL(mipi_dsi_attach);
225 :
226 : /**
227 : * mipi_dsi_detach - detach a DSI device from its DSI host
228 : * @dsi: DSI peripheral
229 : */
230 0 : int mipi_dsi_detach(struct mipi_dsi_device *dsi)
231 : {
232 0 : const struct mipi_dsi_host_ops *ops = dsi->host->ops;
233 :
234 0 : if (!ops || !ops->detach)
235 0 : return -ENOSYS;
236 :
237 0 : return ops->detach(dsi->host, dsi);
238 0 : }
239 : EXPORT_SYMBOL(mipi_dsi_detach);
240 :
241 0 : static ssize_t mipi_dsi_device_transfer(struct mipi_dsi_device *dsi,
242 : struct mipi_dsi_msg *msg)
243 : {
244 0 : const struct mipi_dsi_host_ops *ops = dsi->host->ops;
245 :
246 0 : if (!ops || !ops->transfer)
247 0 : return -ENOSYS;
248 :
249 0 : if (dsi->mode_flags & MIPI_DSI_MODE_LPM)
250 0 : msg->flags |= MIPI_DSI_MSG_USE_LPM;
251 :
252 0 : return ops->transfer(dsi->host, msg);
253 0 : }
254 :
255 : /**
256 : * mipi_dsi_packet_format_is_short - check if a packet is of the short format
257 : * @type: MIPI DSI data type of the packet
258 : *
259 : * Return: true if the packet for the given data type is a short packet, false
260 : * otherwise.
261 : */
262 0 : bool mipi_dsi_packet_format_is_short(u8 type)
263 : {
264 0 : switch (type) {
265 : case MIPI_DSI_V_SYNC_START:
266 : case MIPI_DSI_V_SYNC_END:
267 : case MIPI_DSI_H_SYNC_START:
268 : case MIPI_DSI_H_SYNC_END:
269 : case MIPI_DSI_END_OF_TRANSMISSION:
270 : case MIPI_DSI_COLOR_MODE_OFF:
271 : case MIPI_DSI_COLOR_MODE_ON:
272 : case MIPI_DSI_SHUTDOWN_PERIPHERAL:
273 : case MIPI_DSI_TURN_ON_PERIPHERAL:
274 : case MIPI_DSI_GENERIC_SHORT_WRITE_0_PARAM:
275 : case MIPI_DSI_GENERIC_SHORT_WRITE_1_PARAM:
276 : case MIPI_DSI_GENERIC_SHORT_WRITE_2_PARAM:
277 : case MIPI_DSI_GENERIC_READ_REQUEST_0_PARAM:
278 : case MIPI_DSI_GENERIC_READ_REQUEST_1_PARAM:
279 : case MIPI_DSI_GENERIC_READ_REQUEST_2_PARAM:
280 : case MIPI_DSI_DCS_SHORT_WRITE:
281 : case MIPI_DSI_DCS_SHORT_WRITE_PARAM:
282 : case MIPI_DSI_DCS_READ:
283 : case MIPI_DSI_SET_MAXIMUM_RETURN_PACKET_SIZE:
284 0 : return true;
285 : }
286 :
287 0 : return false;
288 0 : }
289 : EXPORT_SYMBOL(mipi_dsi_packet_format_is_short);
290 :
291 : /**
292 : * mipi_dsi_packet_format_is_long - check if a packet is of the long format
293 : * @type: MIPI DSI data type of the packet
294 : *
295 : * Return: true if the packet for the given data type is a long packet, false
296 : * otherwise.
297 : */
298 0 : bool mipi_dsi_packet_format_is_long(u8 type)
299 : {
300 0 : switch (type) {
301 : case MIPI_DSI_NULL_PACKET:
302 : case MIPI_DSI_BLANKING_PACKET:
303 : case MIPI_DSI_GENERIC_LONG_WRITE:
304 : case MIPI_DSI_DCS_LONG_WRITE:
305 : case MIPI_DSI_LOOSELY_PACKED_PIXEL_STREAM_YCBCR20:
306 : case MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR24:
307 : case MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR16:
308 : case MIPI_DSI_PACKED_PIXEL_STREAM_30:
309 : case MIPI_DSI_PACKED_PIXEL_STREAM_36:
310 : case MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR12:
311 : case MIPI_DSI_PACKED_PIXEL_STREAM_16:
312 : case MIPI_DSI_PACKED_PIXEL_STREAM_18:
313 : case MIPI_DSI_PIXEL_STREAM_3BYTE_18:
314 : case MIPI_DSI_PACKED_PIXEL_STREAM_24:
315 0 : return true;
316 : }
317 :
318 0 : return false;
319 0 : }
320 : EXPORT_SYMBOL(mipi_dsi_packet_format_is_long);
321 :
322 : /**
323 : * mipi_dsi_create_packet - create a packet from a message according to the
324 : * DSI protocol
325 : * @packet: pointer to a DSI packet structure
326 : * @msg: message to translate into a packet
327 : *
328 : * Return: 0 on success or a negative error code on failure.
329 : */
330 0 : int mipi_dsi_create_packet(struct mipi_dsi_packet *packet,
331 : const struct mipi_dsi_msg *msg)
332 : {
333 0 : if (!packet || !msg)
334 0 : return -EINVAL;
335 :
336 : /* do some minimum sanity checking */
337 0 : if (!mipi_dsi_packet_format_is_short(msg->type) &&
338 0 : !mipi_dsi_packet_format_is_long(msg->type))
339 0 : return -EINVAL;
340 :
341 0 : if (msg->channel > 3)
342 0 : return -EINVAL;
343 :
344 0 : memset(packet, 0, sizeof(*packet));
345 0 : packet->header[0] = ((msg->channel & 0x3) << 6) | (msg->type & 0x3f);
346 :
347 : /* TODO: compute ECC if hardware support is not available */
348 :
349 : /*
350 : * Long write packets contain the word count in header bytes 1 and 2.
351 : * The payload follows the header and is word count bytes long.
352 : *
353 : * Short write packets encode up to two parameters in header bytes 1
354 : * and 2.
355 : */
356 0 : if (mipi_dsi_packet_format_is_long(msg->type)) {
357 0 : packet->header[1] = (msg->tx_len >> 0) & 0xff;
358 0 : packet->header[2] = (msg->tx_len >> 8) & 0xff;
359 :
360 0 : packet->payload_length = msg->tx_len;
361 0 : packet->payload = msg->tx_buf;
362 0 : } else {
363 0 : const u8 *tx = msg->tx_buf;
364 :
365 0 : packet->header[1] = (msg->tx_len > 0) ? tx[0] : 0;
366 0 : packet->header[2] = (msg->tx_len > 1) ? tx[1] : 0;
367 : }
368 :
369 0 : packet->size = sizeof(packet->header) + packet->payload_length;
370 :
371 0 : return 0;
372 0 : }
373 : EXPORT_SYMBOL(mipi_dsi_create_packet);
374 :
375 : /*
376 : * mipi_dsi_set_maximum_return_packet_size() - specify the maximum size of the
377 : * the payload in a long packet transmitted from the peripheral back to the
378 : * host processor
379 : * @dsi: DSI peripheral device
380 : * @value: the maximum size of the payload
381 : *
382 : * Return: 0 on success or a negative error code on failure.
383 : */
384 0 : int mipi_dsi_set_maximum_return_packet_size(struct mipi_dsi_device *dsi,
385 : u16 value)
386 : {
387 0 : u8 tx[2] = { value & 0xff, value >> 8 };
388 0 : struct mipi_dsi_msg msg = {
389 0 : .channel = dsi->channel,
390 : .type = MIPI_DSI_SET_MAXIMUM_RETURN_PACKET_SIZE,
391 : .tx_len = sizeof(tx),
392 0 : .tx_buf = tx,
393 : };
394 :
395 0 : return mipi_dsi_device_transfer(dsi, &msg);
396 0 : }
397 : EXPORT_SYMBOL(mipi_dsi_set_maximum_return_packet_size);
398 :
399 : /**
400 : * mipi_dsi_generic_write() - transmit data using a generic write packet
401 : * @dsi: DSI peripheral device
402 : * @payload: buffer containing the payload
403 : * @size: size of payload buffer
404 : *
405 : * This function will automatically choose the right data type depending on
406 : * the payload length.
407 : *
408 : * Return: The number of bytes transmitted on success or a negative error code
409 : * on failure.
410 : */
411 0 : ssize_t mipi_dsi_generic_write(struct mipi_dsi_device *dsi, const void *payload,
412 : size_t size)
413 : {
414 0 : struct mipi_dsi_msg msg = {
415 0 : .channel = dsi->channel,
416 : .tx_buf = payload,
417 : .tx_len = size
418 : };
419 :
420 0 : switch (size) {
421 : case 0:
422 0 : msg.type = MIPI_DSI_GENERIC_SHORT_WRITE_0_PARAM;
423 0 : break;
424 :
425 : case 1:
426 0 : msg.type = MIPI_DSI_GENERIC_SHORT_WRITE_1_PARAM;
427 0 : break;
428 :
429 : case 2:
430 0 : msg.type = MIPI_DSI_GENERIC_SHORT_WRITE_2_PARAM;
431 0 : break;
432 :
433 : default:
434 0 : msg.type = MIPI_DSI_GENERIC_LONG_WRITE;
435 0 : break;
436 : }
437 :
438 0 : return mipi_dsi_device_transfer(dsi, &msg);
439 0 : }
440 : EXPORT_SYMBOL(mipi_dsi_generic_write);
441 :
442 : /**
443 : * mipi_dsi_generic_read() - receive data using a generic read packet
444 : * @dsi: DSI peripheral device
445 : * @params: buffer containing the request parameters
446 : * @num_params: number of request parameters
447 : * @data: buffer in which to return the received data
448 : * @size: size of receive buffer
449 : *
450 : * This function will automatically choose the right data type depending on
451 : * the number of parameters passed in.
452 : *
453 : * Return: The number of bytes successfully read or a negative error code on
454 : * failure.
455 : */
456 0 : ssize_t mipi_dsi_generic_read(struct mipi_dsi_device *dsi, const void *params,
457 : size_t num_params, void *data, size_t size)
458 : {
459 0 : struct mipi_dsi_msg msg = {
460 0 : .channel = dsi->channel,
461 : .tx_len = num_params,
462 : .tx_buf = params,
463 : .rx_len = size,
464 : .rx_buf = data
465 : };
466 :
467 0 : switch (num_params) {
468 : case 0:
469 0 : msg.type = MIPI_DSI_GENERIC_READ_REQUEST_0_PARAM;
470 0 : break;
471 :
472 : case 1:
473 0 : msg.type = MIPI_DSI_GENERIC_READ_REQUEST_1_PARAM;
474 0 : break;
475 :
476 : case 2:
477 0 : msg.type = MIPI_DSI_GENERIC_READ_REQUEST_2_PARAM;
478 0 : break;
479 :
480 : default:
481 0 : return -EINVAL;
482 : }
483 :
484 0 : return mipi_dsi_device_transfer(dsi, &msg);
485 0 : }
486 : EXPORT_SYMBOL(mipi_dsi_generic_read);
487 :
488 : /**
489 : * mipi_dsi_dcs_write_buffer() - transmit a DCS command with payload
490 : * @dsi: DSI peripheral device
491 : * @data: buffer containing data to be transmitted
492 : * @len: size of transmission buffer
493 : *
494 : * This function will automatically choose the right data type depending on
495 : * the command payload length.
496 : *
497 : * Return: The number of bytes successfully transmitted or a negative error
498 : * code on failure.
499 : */
500 0 : ssize_t mipi_dsi_dcs_write_buffer(struct mipi_dsi_device *dsi,
501 : const void *data, size_t len)
502 : {
503 0 : struct mipi_dsi_msg msg = {
504 0 : .channel = dsi->channel,
505 : .tx_buf = data,
506 : .tx_len = len
507 : };
508 :
509 0 : switch (len) {
510 : case 0:
511 0 : return -EINVAL;
512 :
513 : case 1:
514 0 : msg.type = MIPI_DSI_DCS_SHORT_WRITE;
515 0 : break;
516 :
517 : case 2:
518 0 : msg.type = MIPI_DSI_DCS_SHORT_WRITE_PARAM;
519 0 : break;
520 :
521 : default:
522 0 : msg.type = MIPI_DSI_DCS_LONG_WRITE;
523 0 : break;
524 : }
525 :
526 0 : return mipi_dsi_device_transfer(dsi, &msg);
527 0 : }
528 : EXPORT_SYMBOL(mipi_dsi_dcs_write_buffer);
529 :
530 : /**
531 : * mipi_dsi_dcs_write() - send DCS write command
532 : * @dsi: DSI peripheral device
533 : * @cmd: DCS command
534 : * @data: buffer containing the command payload
535 : * @len: command payload length
536 : *
537 : * This function will automatically choose the right data type depending on
538 : * the command payload length.
539 : *
540 : * Return: The number of bytes successfully transmitted or a negative error
541 : * code on failure.
542 : */
543 0 : ssize_t mipi_dsi_dcs_write(struct mipi_dsi_device *dsi, u8 cmd,
544 : const void *data, size_t len)
545 : {
546 : ssize_t err;
547 : size_t size;
548 : u8 *tx;
549 :
550 0 : if (len > 0) {
551 0 : size = 1 + len;
552 :
553 0 : tx = kmalloc(size, GFP_KERNEL);
554 0 : if (!tx)
555 0 : return -ENOMEM;
556 :
557 : /* concatenate the DCS command byte and the payload */
558 0 : tx[0] = cmd;
559 0 : memcpy(&tx[1], data, len);
560 0 : } else {
561 : tx = &cmd;
562 : size = 1;
563 : }
564 :
565 0 : err = mipi_dsi_dcs_write_buffer(dsi, tx, size);
566 :
567 0 : if (len > 0)
568 0 : kfree(tx);
569 :
570 0 : return err;
571 0 : }
572 : EXPORT_SYMBOL(mipi_dsi_dcs_write);
573 :
574 : /**
575 : * mipi_dsi_dcs_read() - send DCS read request command
576 : * @dsi: DSI peripheral device
577 : * @cmd: DCS command
578 : * @data: buffer in which to receive data
579 : * @len: size of receive buffer
580 : *
581 : * Return: The number of bytes read or a negative error code on failure.
582 : */
583 0 : ssize_t mipi_dsi_dcs_read(struct mipi_dsi_device *dsi, u8 cmd, void *data,
584 : size_t len)
585 : {
586 0 : struct mipi_dsi_msg msg = {
587 0 : .channel = dsi->channel,
588 : .type = MIPI_DSI_DCS_READ,
589 : .tx_buf = &cmd,
590 : .tx_len = 1,
591 : .rx_buf = data,
592 : .rx_len = len
593 : };
594 :
595 0 : return mipi_dsi_device_transfer(dsi, &msg);
596 0 : }
597 : EXPORT_SYMBOL(mipi_dsi_dcs_read);
598 :
599 : /**
600 : * mipi_dsi_dcs_nop() - send DCS nop packet
601 : * @dsi: DSI peripheral device
602 : *
603 : * Return: 0 on success or a negative error code on failure.
604 : */
605 0 : int mipi_dsi_dcs_nop(struct mipi_dsi_device *dsi)
606 : {
607 : ssize_t err;
608 :
609 0 : err = mipi_dsi_dcs_write(dsi, MIPI_DCS_NOP, NULL, 0);
610 0 : if (err < 0)
611 0 : return err;
612 :
613 0 : return 0;
614 0 : }
615 : EXPORT_SYMBOL(mipi_dsi_dcs_nop);
616 :
617 : /**
618 : * mipi_dsi_dcs_soft_reset() - perform a software reset of the display module
619 : * @dsi: DSI peripheral device
620 : *
621 : * Return: 0 on success or a negative error code on failure.
622 : */
623 0 : int mipi_dsi_dcs_soft_reset(struct mipi_dsi_device *dsi)
624 : {
625 : ssize_t err;
626 :
627 0 : err = mipi_dsi_dcs_write(dsi, MIPI_DCS_SOFT_RESET, NULL, 0);
628 0 : if (err < 0)
629 0 : return err;
630 :
631 0 : return 0;
632 0 : }
633 : EXPORT_SYMBOL(mipi_dsi_dcs_soft_reset);
634 :
635 : /**
636 : * mipi_dsi_dcs_get_power_mode() - query the display module's current power
637 : * mode
638 : * @dsi: DSI peripheral device
639 : * @mode: return location for the current power mode
640 : *
641 : * Return: 0 on success or a negative error code on failure.
642 : */
643 0 : int mipi_dsi_dcs_get_power_mode(struct mipi_dsi_device *dsi, u8 *mode)
644 : {
645 : ssize_t err;
646 :
647 0 : err = mipi_dsi_dcs_read(dsi, MIPI_DCS_GET_POWER_MODE, mode,
648 : sizeof(*mode));
649 0 : if (err <= 0) {
650 0 : if (err == 0)
651 0 : err = -ENODATA;
652 :
653 0 : return err;
654 : }
655 :
656 0 : return 0;
657 0 : }
658 : EXPORT_SYMBOL(mipi_dsi_dcs_get_power_mode);
659 :
660 : /**
661 : * mipi_dsi_dcs_get_pixel_format() - gets the pixel format for the RGB image
662 : * data used by the interface
663 : * @dsi: DSI peripheral device
664 : * @format: return location for the pixel format
665 : *
666 : * Return: 0 on success or a negative error code on failure.
667 : */
668 0 : int mipi_dsi_dcs_get_pixel_format(struct mipi_dsi_device *dsi, u8 *format)
669 : {
670 : ssize_t err;
671 :
672 0 : err = mipi_dsi_dcs_read(dsi, MIPI_DCS_GET_PIXEL_FORMAT, format,
673 : sizeof(*format));
674 0 : if (err <= 0) {
675 0 : if (err == 0)
676 0 : err = -ENODATA;
677 :
678 0 : return err;
679 : }
680 :
681 0 : return 0;
682 0 : }
683 : EXPORT_SYMBOL(mipi_dsi_dcs_get_pixel_format);
684 :
685 : /**
686 : * mipi_dsi_dcs_enter_sleep_mode() - disable all unnecessary blocks inside the
687 : * display module except interface communication
688 : * @dsi: DSI peripheral device
689 : *
690 : * Return: 0 on success or a negative error code on failure.
691 : */
692 0 : int mipi_dsi_dcs_enter_sleep_mode(struct mipi_dsi_device *dsi)
693 : {
694 : ssize_t err;
695 :
696 0 : err = mipi_dsi_dcs_write(dsi, MIPI_DCS_ENTER_SLEEP_MODE, NULL, 0);
697 0 : if (err < 0)
698 0 : return err;
699 :
700 0 : return 0;
701 0 : }
702 : EXPORT_SYMBOL(mipi_dsi_dcs_enter_sleep_mode);
703 :
704 : /**
705 : * mipi_dsi_dcs_exit_sleep_mode() - enable all blocks inside the display
706 : * module
707 : * @dsi: DSI peripheral device
708 : *
709 : * Return: 0 on success or a negative error code on failure.
710 : */
711 0 : int mipi_dsi_dcs_exit_sleep_mode(struct mipi_dsi_device *dsi)
712 : {
713 : ssize_t err;
714 :
715 0 : err = mipi_dsi_dcs_write(dsi, MIPI_DCS_EXIT_SLEEP_MODE, NULL, 0);
716 0 : if (err < 0)
717 0 : return err;
718 :
719 0 : return 0;
720 0 : }
721 : EXPORT_SYMBOL(mipi_dsi_dcs_exit_sleep_mode);
722 :
723 : /**
724 : * mipi_dsi_dcs_set_display_off() - stop displaying the image data on the
725 : * display device
726 : * @dsi: DSI peripheral device
727 : *
728 : * Return: 0 on success or a negative error code on failure.
729 : */
730 0 : int mipi_dsi_dcs_set_display_off(struct mipi_dsi_device *dsi)
731 : {
732 : ssize_t err;
733 :
734 0 : err = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_DISPLAY_OFF, NULL, 0);
735 0 : if (err < 0)
736 0 : return err;
737 :
738 0 : return 0;
739 0 : }
740 : EXPORT_SYMBOL(mipi_dsi_dcs_set_display_off);
741 :
742 : /**
743 : * mipi_dsi_dcs_set_display_on() - start displaying the image data on the
744 : * display device
745 : * @dsi: DSI peripheral device
746 : *
747 : * Return: 0 on success or a negative error code on failure
748 : */
749 0 : int mipi_dsi_dcs_set_display_on(struct mipi_dsi_device *dsi)
750 : {
751 : ssize_t err;
752 :
753 0 : err = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_DISPLAY_ON, NULL, 0);
754 0 : if (err < 0)
755 0 : return err;
756 :
757 0 : return 0;
758 0 : }
759 : EXPORT_SYMBOL(mipi_dsi_dcs_set_display_on);
760 :
761 : /**
762 : * mipi_dsi_dcs_set_column_address() - define the column extent of the frame
763 : * memory accessed by the host processor
764 : * @dsi: DSI peripheral device
765 : * @start: first column of frame memory
766 : * @end: last column of frame memory
767 : *
768 : * Return: 0 on success or a negative error code on failure.
769 : */
770 0 : int mipi_dsi_dcs_set_column_address(struct mipi_dsi_device *dsi, u16 start,
771 : u16 end)
772 : {
773 0 : u8 payload[4] = { start >> 8, start & 0xff, end >> 8, end & 0xff };
774 : ssize_t err;
775 :
776 0 : err = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_COLUMN_ADDRESS, payload,
777 : sizeof(payload));
778 0 : if (err < 0)
779 0 : return err;
780 :
781 0 : return 0;
782 0 : }
783 : EXPORT_SYMBOL(mipi_dsi_dcs_set_column_address);
784 :
785 : /**
786 : * mipi_dsi_dcs_set_page_address() - define the page extent of the frame
787 : * memory accessed by the host processor
788 : * @dsi: DSI peripheral device
789 : * @start: first page of frame memory
790 : * @end: last page of frame memory
791 : *
792 : * Return: 0 on success or a negative error code on failure.
793 : */
794 0 : int mipi_dsi_dcs_set_page_address(struct mipi_dsi_device *dsi, u16 start,
795 : u16 end)
796 : {
797 0 : u8 payload[4] = { start >> 8, start & 0xff, end >> 8, end & 0xff };
798 : ssize_t err;
799 :
800 0 : err = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_PAGE_ADDRESS, payload,
801 : sizeof(payload));
802 0 : if (err < 0)
803 0 : return err;
804 :
805 0 : return 0;
806 0 : }
807 : EXPORT_SYMBOL(mipi_dsi_dcs_set_page_address);
808 :
809 : /**
810 : * mipi_dsi_dcs_set_tear_off() - turn off the display module's Tearing Effect
811 : * output signal on the TE signal line
812 : * @dsi: DSI peripheral device
813 : *
814 : * Return: 0 on success or a negative error code on failure
815 : */
816 0 : int mipi_dsi_dcs_set_tear_off(struct mipi_dsi_device *dsi)
817 : {
818 : ssize_t err;
819 :
820 0 : err = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_TEAR_OFF, NULL, 0);
821 0 : if (err < 0)
822 0 : return err;
823 :
824 0 : return 0;
825 0 : }
826 : EXPORT_SYMBOL(mipi_dsi_dcs_set_tear_off);
827 :
828 : /**
829 : * mipi_dsi_dcs_set_tear_on() - turn on the display module's Tearing Effect
830 : * output signal on the TE signal line.
831 : * @dsi: DSI peripheral device
832 : * @mode: the Tearing Effect Output Line mode
833 : *
834 : * Return: 0 on success or a negative error code on failure
835 : */
836 0 : int mipi_dsi_dcs_set_tear_on(struct mipi_dsi_device *dsi,
837 : enum mipi_dsi_dcs_tear_mode mode)
838 : {
839 0 : u8 value = mode;
840 : ssize_t err;
841 :
842 0 : err = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_TEAR_ON, &value,
843 : sizeof(value));
844 0 : if (err < 0)
845 0 : return err;
846 :
847 0 : return 0;
848 0 : }
849 : EXPORT_SYMBOL(mipi_dsi_dcs_set_tear_on);
850 :
851 : /**
852 : * mipi_dsi_dcs_set_pixel_format() - sets the pixel format for the RGB image
853 : * data used by the interface
854 : * @dsi: DSI peripheral device
855 : * @format: pixel format
856 : *
857 : * Return: 0 on success or a negative error code on failure.
858 : */
859 0 : int mipi_dsi_dcs_set_pixel_format(struct mipi_dsi_device *dsi, u8 format)
860 : {
861 : ssize_t err;
862 :
863 0 : err = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_PIXEL_FORMAT, &format,
864 : sizeof(format));
865 0 : if (err < 0)
866 0 : return err;
867 :
868 0 : return 0;
869 0 : }
870 : EXPORT_SYMBOL(mipi_dsi_dcs_set_pixel_format);
871 :
872 : #ifdef notyet
873 :
874 : static int mipi_dsi_drv_probe(struct device *dev)
875 : {
876 : struct mipi_dsi_driver *drv = to_mipi_dsi_driver(dev->driver);
877 : struct mipi_dsi_device *dsi = to_mipi_dsi_device(dev);
878 :
879 : return drv->probe(dsi);
880 : }
881 :
882 : static int mipi_dsi_drv_remove(struct device *dev)
883 : {
884 : struct mipi_dsi_driver *drv = to_mipi_dsi_driver(dev->driver);
885 : struct mipi_dsi_device *dsi = to_mipi_dsi_device(dev);
886 :
887 : return drv->remove(dsi);
888 : }
889 :
890 : static void mipi_dsi_drv_shutdown(struct device *dev)
891 : {
892 : struct mipi_dsi_driver *drv = to_mipi_dsi_driver(dev->driver);
893 : struct mipi_dsi_device *dsi = to_mipi_dsi_device(dev);
894 :
895 : drv->shutdown(dsi);
896 : }
897 :
898 : /**
899 : * mipi_dsi_driver_register_full() - register a driver for DSI devices
900 : * @drv: DSI driver structure
901 : * @owner: owner module
902 : *
903 : * Return: 0 on success or a negative error code on failure.
904 : */
905 : int mipi_dsi_driver_register_full(struct mipi_dsi_driver *drv,
906 : struct module *owner)
907 : {
908 : drv->driver.bus = &mipi_dsi_bus_type;
909 : drv->driver.owner = owner;
910 :
911 : if (drv->probe)
912 : drv->driver.probe = mipi_dsi_drv_probe;
913 : if (drv->remove)
914 : drv->driver.remove = mipi_dsi_drv_remove;
915 : if (drv->shutdown)
916 : drv->driver.shutdown = mipi_dsi_drv_shutdown;
917 :
918 : return driver_register(&drv->driver);
919 : }
920 : EXPORT_SYMBOL(mipi_dsi_driver_register_full);
921 :
922 : /**
923 : * mipi_dsi_driver_unregister() - unregister a driver for DSI devices
924 : * @drv: DSI driver structure
925 : *
926 : * Return: 0 on success or a negative error code on failure.
927 : */
928 : void mipi_dsi_driver_unregister(struct mipi_dsi_driver *drv)
929 : {
930 : driver_unregister(&drv->driver);
931 : }
932 : EXPORT_SYMBOL(mipi_dsi_driver_unregister);
933 :
934 : static int __init mipi_dsi_bus_init(void)
935 : {
936 : return bus_register(&mipi_dsi_bus_type);
937 : }
938 : postcore_initcall(mipi_dsi_bus_init);
939 :
940 : MODULE_AUTHOR("Andrzej Hajda <a.hajda@samsung.com>");
941 : MODULE_DESCRIPTION("MIPI DSI Bus");
942 : MODULE_LICENSE("GPL and additional rights");
943 :
944 : #endif
|