blob: f2f5a6d3669af0625d21cd49e16ef1990e80c736 [file] [log] [blame]
Andrzej Hajda068a0022013-12-04 16:35:12 +01001/*
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 <drm/drm_mipi_dsi.h>
29
30#include <linux/device.h>
31#include <linux/module.h>
32#include <linux/of_device.h>
33#include <linux/pm_runtime.h>
34#include <linux/slab.h>
35
36#include <video/mipi_display.h>
37
Thierry Reding009081e2014-08-05 10:41:13 +020038/**
39 * DOC: dsi helpers
40 *
41 * These functions contain some common logic and helpers to deal with MIPI DSI
42 * peripherals.
43 *
44 * Helpers are provided for a number of standard MIPI DSI command as well as a
45 * subset of the MIPI DCS command set.
46 */
47
Andrzej Hajda068a0022013-12-04 16:35:12 +010048static int mipi_dsi_device_match(struct device *dev, struct device_driver *drv)
49{
Archit Tanejabf4363c2016-02-12 14:48:32 +053050 struct mipi_dsi_device *dsi = to_mipi_dsi_device(dev);
51
52 /* attempt OF style match */
53 if (of_driver_match_device(dev, drv))
54 return 1;
55
56 /* compare DSI device and driver names */
57 if (!strcmp(dsi->name, drv->name))
58 return 1;
59
60 return 0;
Andrzej Hajda068a0022013-12-04 16:35:12 +010061}
62
63static const struct dev_pm_ops mipi_dsi_device_pm_ops = {
64 .runtime_suspend = pm_generic_runtime_suspend,
65 .runtime_resume = pm_generic_runtime_resume,
66 .suspend = pm_generic_suspend,
67 .resume = pm_generic_resume,
68 .freeze = pm_generic_freeze,
69 .thaw = pm_generic_thaw,
70 .poweroff = pm_generic_poweroff,
71 .restore = pm_generic_restore,
72};
73
74static struct bus_type mipi_dsi_bus_type = {
75 .name = "mipi-dsi",
76 .match = mipi_dsi_device_match,
77 .pm = &mipi_dsi_device_pm_ops,
78};
79
Thierry Reding3ef05922014-08-06 08:53:39 +020080static int of_device_match(struct device *dev, void *data)
81{
82 return dev->of_node == data;
83}
84
85/**
86 * of_find_mipi_dsi_device_by_node() - find the MIPI DSI device matching a
87 * device tree node
88 * @np: device tree node
89 *
90 * Return: A pointer to the MIPI DSI device corresponding to @np or NULL if no
91 * such device exists (or has not been registered yet).
92 */
93struct mipi_dsi_device *of_find_mipi_dsi_device_by_node(struct device_node *np)
94{
95 struct device *dev;
96
97 dev = bus_find_device(&mipi_dsi_bus_type, NULL, np, of_device_match);
98
99 return dev ? to_mipi_dsi_device(dev) : NULL;
100}
101EXPORT_SYMBOL(of_find_mipi_dsi_device_by_node);
102
Andrzej Hajda068a0022013-12-04 16:35:12 +0100103static void mipi_dsi_dev_release(struct device *dev)
104{
105 struct mipi_dsi_device *dsi = to_mipi_dsi_device(dev);
106
107 of_node_put(dev->of_node);
108 kfree(dsi);
109}
110
111static const struct device_type mipi_dsi_device_type = {
112 .release = mipi_dsi_dev_release,
113};
114
115static struct mipi_dsi_device *mipi_dsi_device_alloc(struct mipi_dsi_host *host)
116{
117 struct mipi_dsi_device *dsi;
118
119 dsi = kzalloc(sizeof(*dsi), GFP_KERNEL);
120 if (!dsi)
121 return ERR_PTR(-ENOMEM);
122
123 dsi->host = host;
124 dsi->dev.bus = &mipi_dsi_bus_type;
125 dsi->dev.parent = host->dev;
126 dsi->dev.type = &mipi_dsi_device_type;
127
128 device_initialize(&dsi->dev);
129
130 return dsi;
131}
132
133static int mipi_dsi_device_add(struct mipi_dsi_device *dsi)
134{
135 struct mipi_dsi_host *host = dsi->host;
136
137 dev_set_name(&dsi->dev, "%s.%d", dev_name(host->dev), dsi->channel);
138
139 return device_add(&dsi->dev);
140}
141
Archit Tanejafc903eb2016-02-12 14:48:30 +0530142#if IS_ENABLED(CONFIG_OF)
Andrzej Hajda068a0022013-12-04 16:35:12 +0100143static struct mipi_dsi_device *
144of_mipi_dsi_device_add(struct mipi_dsi_host *host, struct device_node *node)
145{
Andrzej Hajda068a0022013-12-04 16:35:12 +0100146 struct device *dev = host->dev;
Archit Tanejac63ae8a2016-02-12 14:48:31 +0530147 struct mipi_dsi_device_info info = { };
Andrzej Hajda068a0022013-12-04 16:35:12 +0100148 int ret;
149 u32 reg;
150
Archit Tanejabf4363c2016-02-12 14:48:32 +0530151 if (of_modalias_node(node, info.type, sizeof(info.type)) < 0) {
152 dev_err(dev, "modalias failure on %s\n", node->full_name);
153 return ERR_PTR(-EINVAL);
154 }
155
Andrzej Hajda068a0022013-12-04 16:35:12 +0100156 ret = of_property_read_u32(node, "reg", &reg);
157 if (ret) {
158 dev_err(dev, "device node %s has no valid reg property: %d\n",
159 node->full_name, ret);
160 return ERR_PTR(-EINVAL);
161 }
162
Archit Tanejac63ae8a2016-02-12 14:48:31 +0530163 info.channel = reg;
164 info.node = of_node_get(node);
Andrzej Hajda068a0022013-12-04 16:35:12 +0100165
Archit Tanejac63ae8a2016-02-12 14:48:31 +0530166 return mipi_dsi_device_register_full(host, &info);
Andrzej Hajda068a0022013-12-04 16:35:12 +0100167}
Archit Tanejafc903eb2016-02-12 14:48:30 +0530168#else
169static struct mipi_dsi_device *
170of_mipi_dsi_device_add(struct mipi_dsi_host *host, struct device_node *node)
171{
172 return ERR_PTR(-ENODEV);
173}
174#endif
Andrzej Hajda068a0022013-12-04 16:35:12 +0100175
Archit Tanejac63ae8a2016-02-12 14:48:31 +0530176/**
177 * mipi_dsi_device_register_full - create a MIPI DSI device
178 * @host: DSI host to which this device is connected
179 * @info: pointer to template containing DSI device information
180 *
181 * Create a MIPI DSI device by using the device information provided by
182 * mipi_dsi_device_info template
183 *
184 * Returns:
185 * A pointer to the newly created MIPI DSI device, or, a pointer encoded
186 * with an error
187 */
188struct mipi_dsi_device *
189mipi_dsi_device_register_full(struct mipi_dsi_host *host,
190 const struct mipi_dsi_device_info *info)
191{
192 struct mipi_dsi_device *dsi;
193 struct device *dev = host->dev;
194 int ret;
195
196 if (!info) {
197 dev_err(dev, "invalid mipi_dsi_device_info pointer\n");
198 return ERR_PTR(-EINVAL);
199 }
200
201 if (info->channel > 3) {
202 dev_err(dev, "invalid virtual channel: %u\n", info->channel);
203 return ERR_PTR(-EINVAL);
204 }
205
206 dsi = mipi_dsi_device_alloc(host);
207 if (IS_ERR(dsi)) {
208 dev_err(dev, "failed to allocate DSI device %ld\n",
209 PTR_ERR(dsi));
210 return dsi;
211 }
212
213 dsi->dev.of_node = info->node;
214 dsi->channel = info->channel;
Archit Tanejabf4363c2016-02-12 14:48:32 +0530215 strlcpy(dsi->name, info->type, sizeof(dsi->name));
Archit Tanejac63ae8a2016-02-12 14:48:31 +0530216
217 ret = mipi_dsi_device_add(dsi);
218 if (ret) {
219 dev_err(dev, "failed to add DSI device %d\n", ret);
220 kfree(dsi);
221 return ERR_PTR(ret);
222 }
223
224 return dsi;
225}
226EXPORT_SYMBOL(mipi_dsi_device_register_full);
227
Archit Taneja509e42c2016-02-12 14:48:33 +0530228/**
229 * mipi_dsi_device_unregister - unregister MIPI DSI device
230 * @dsi: DSI peripheral device
231 */
232void mipi_dsi_device_unregister(struct mipi_dsi_device *dsi)
233{
234 device_unregister(&dsi->dev);
235}
236EXPORT_SYMBOL(mipi_dsi_device_unregister);
237
Andrzej Hajda068a0022013-12-04 16:35:12 +0100238int mipi_dsi_host_register(struct mipi_dsi_host *host)
239{
240 struct device_node *node;
241
Andrzej Hajdae49640d2014-03-28 12:52:37 +0100242 for_each_available_child_of_node(host->dev->of_node, node) {
243 /* skip nodes without reg property */
244 if (!of_find_property(node, "reg", NULL))
245 continue;
Andrzej Hajda068a0022013-12-04 16:35:12 +0100246 of_mipi_dsi_device_add(host, node);
Andrzej Hajdae49640d2014-03-28 12:52:37 +0100247 }
Andrzej Hajda068a0022013-12-04 16:35:12 +0100248
249 return 0;
250}
251EXPORT_SYMBOL(mipi_dsi_host_register);
252
253static int mipi_dsi_remove_device_fn(struct device *dev, void *priv)
254{
255 struct mipi_dsi_device *dsi = to_mipi_dsi_device(dev);
256
Archit Taneja509e42c2016-02-12 14:48:33 +0530257 mipi_dsi_device_unregister(dsi);
Andrzej Hajda068a0022013-12-04 16:35:12 +0100258
259 return 0;
260}
261
262void mipi_dsi_host_unregister(struct mipi_dsi_host *host)
263{
264 device_for_each_child(host->dev, NULL, mipi_dsi_remove_device_fn);
265}
266EXPORT_SYMBOL(mipi_dsi_host_unregister);
267
268/**
269 * mipi_dsi_attach - attach a DSI device to its DSI host
270 * @dsi: DSI peripheral
271 */
272int mipi_dsi_attach(struct mipi_dsi_device *dsi)
273{
274 const struct mipi_dsi_host_ops *ops = dsi->host->ops;
275
276 if (!ops || !ops->attach)
277 return -ENOSYS;
278
279 return ops->attach(dsi->host, dsi);
280}
281EXPORT_SYMBOL(mipi_dsi_attach);
282
283/**
284 * mipi_dsi_detach - detach a DSI device from its DSI host
285 * @dsi: DSI peripheral
286 */
287int mipi_dsi_detach(struct mipi_dsi_device *dsi)
288{
289 const struct mipi_dsi_host_ops *ops = dsi->host->ops;
290
291 if (!ops || !ops->detach)
292 return -ENOSYS;
293
294 return ops->detach(dsi->host, dsi);
295}
296EXPORT_SYMBOL(mipi_dsi_detach);
297
Thierry Reding9eb491f2014-10-14 11:12:32 +0200298static ssize_t mipi_dsi_device_transfer(struct mipi_dsi_device *dsi,
299 struct mipi_dsi_msg *msg)
300{
301 const struct mipi_dsi_host_ops *ops = dsi->host->ops;
302
303 if (!ops || !ops->transfer)
304 return -ENOSYS;
305
306 if (dsi->mode_flags & MIPI_DSI_MODE_LPM)
307 msg->flags |= MIPI_DSI_MSG_USE_LPM;
308
309 return ops->transfer(dsi->host, msg);
310}
311
Andrzej Hajda068a0022013-12-04 16:35:12 +0100312/**
Thierry Reding02acb762014-11-04 14:59:14 +0100313 * mipi_dsi_packet_format_is_short - check if a packet is of the short format
314 * @type: MIPI DSI data type of the packet
315 *
316 * Return: true if the packet for the given data type is a short packet, false
317 * otherwise.
318 */
319bool mipi_dsi_packet_format_is_short(u8 type)
320{
321 switch (type) {
322 case MIPI_DSI_V_SYNC_START:
323 case MIPI_DSI_V_SYNC_END:
324 case MIPI_DSI_H_SYNC_START:
325 case MIPI_DSI_H_SYNC_END:
326 case MIPI_DSI_END_OF_TRANSMISSION:
327 case MIPI_DSI_COLOR_MODE_OFF:
328 case MIPI_DSI_COLOR_MODE_ON:
329 case MIPI_DSI_SHUTDOWN_PERIPHERAL:
330 case MIPI_DSI_TURN_ON_PERIPHERAL:
331 case MIPI_DSI_GENERIC_SHORT_WRITE_0_PARAM:
332 case MIPI_DSI_GENERIC_SHORT_WRITE_1_PARAM:
333 case MIPI_DSI_GENERIC_SHORT_WRITE_2_PARAM:
334 case MIPI_DSI_GENERIC_READ_REQUEST_0_PARAM:
335 case MIPI_DSI_GENERIC_READ_REQUEST_1_PARAM:
336 case MIPI_DSI_GENERIC_READ_REQUEST_2_PARAM:
337 case MIPI_DSI_DCS_SHORT_WRITE:
338 case MIPI_DSI_DCS_SHORT_WRITE_PARAM:
339 case MIPI_DSI_DCS_READ:
340 case MIPI_DSI_SET_MAXIMUM_RETURN_PACKET_SIZE:
341 return true;
342 }
343
344 return false;
345}
346EXPORT_SYMBOL(mipi_dsi_packet_format_is_short);
347
348/**
349 * mipi_dsi_packet_format_is_long - check if a packet is of the long format
350 * @type: MIPI DSI data type of the packet
351 *
352 * Return: true if the packet for the given data type is a long packet, false
353 * otherwise.
354 */
355bool mipi_dsi_packet_format_is_long(u8 type)
356{
357 switch (type) {
358 case MIPI_DSI_NULL_PACKET:
359 case MIPI_DSI_BLANKING_PACKET:
360 case MIPI_DSI_GENERIC_LONG_WRITE:
361 case MIPI_DSI_DCS_LONG_WRITE:
362 case MIPI_DSI_LOOSELY_PACKED_PIXEL_STREAM_YCBCR20:
363 case MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR24:
364 case MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR16:
365 case MIPI_DSI_PACKED_PIXEL_STREAM_30:
366 case MIPI_DSI_PACKED_PIXEL_STREAM_36:
367 case MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR12:
368 case MIPI_DSI_PACKED_PIXEL_STREAM_16:
369 case MIPI_DSI_PACKED_PIXEL_STREAM_18:
370 case MIPI_DSI_PIXEL_STREAM_3BYTE_18:
371 case MIPI_DSI_PACKED_PIXEL_STREAM_24:
372 return true;
373 }
374
375 return false;
376}
377EXPORT_SYMBOL(mipi_dsi_packet_format_is_long);
378
379/**
Thierry Redinga52879e2014-10-16 13:44:02 +0200380 * mipi_dsi_create_packet - create a packet from a message according to the
381 * DSI protocol
382 * @packet: pointer to a DSI packet structure
383 * @msg: message to translate into a packet
384 *
385 * Return: 0 on success or a negative error code on failure.
386 */
387int mipi_dsi_create_packet(struct mipi_dsi_packet *packet,
388 const struct mipi_dsi_msg *msg)
389{
Thierry Redinga52879e2014-10-16 13:44:02 +0200390 if (!packet || !msg)
391 return -EINVAL;
392
393 /* do some minimum sanity checking */
394 if (!mipi_dsi_packet_format_is_short(msg->type) &&
395 !mipi_dsi_packet_format_is_long(msg->type))
396 return -EINVAL;
397
398 if (msg->channel > 3)
399 return -EINVAL;
400
401 memset(packet, 0, sizeof(*packet));
402 packet->header[0] = ((msg->channel & 0x3) << 6) | (msg->type & 0x3f);
403
404 /* TODO: compute ECC if hardware support is not available */
405
406 /*
407 * Long write packets contain the word count in header bytes 1 and 2.
408 * The payload follows the header and is word count bytes long.
409 *
410 * Short write packets encode up to two parameters in header bytes 1
411 * and 2.
412 */
413 if (mipi_dsi_packet_format_is_long(msg->type)) {
414 packet->header[1] = (msg->tx_len >> 0) & 0xff;
415 packet->header[2] = (msg->tx_len >> 8) & 0xff;
416
417 packet->payload_length = msg->tx_len;
Thierry Reding9b973832014-12-05 11:46:56 +0100418 packet->payload = msg->tx_buf;
Thierry Redinga52879e2014-10-16 13:44:02 +0200419 } else {
Thierry Reding9b973832014-12-05 11:46:56 +0100420 const u8 *tx = msg->tx_buf;
421
Thierry Redinga52879e2014-10-16 13:44:02 +0200422 packet->header[1] = (msg->tx_len > 0) ? tx[0] : 0;
423 packet->header[2] = (msg->tx_len > 1) ? tx[1] : 0;
424 }
425
426 packet->size = sizeof(packet->header) + packet->payload_length;
427
428 return 0;
429}
430EXPORT_SYMBOL(mipi_dsi_create_packet);
431
Werner Johansson6e8c9e32015-10-30 17:38:26 -0700432/**
433 * mipi_dsi_shutdown_peripheral() - sends a Shutdown Peripheral command
434 * @dsi: DSI peripheral device
435 *
436 * Return: 0 on success or a negative error code on failure.
437 */
438int mipi_dsi_shutdown_peripheral(struct mipi_dsi_device *dsi)
439{
440 struct mipi_dsi_msg msg = {
441 .channel = dsi->channel,
442 .type = MIPI_DSI_SHUTDOWN_PERIPHERAL,
443 .tx_buf = (u8 [2]) { 0, 0 },
444 .tx_len = 2,
445 };
446
447 return mipi_dsi_device_transfer(dsi, &msg);
448}
449EXPORT_SYMBOL(mipi_dsi_shutdown_peripheral);
450
451/**
452 * mipi_dsi_turn_on_peripheral() - sends a Turn On Peripheral command
453 * @dsi: DSI peripheral device
454 *
455 * Return: 0 on success or a negative error code on failure.
456 */
457int mipi_dsi_turn_on_peripheral(struct mipi_dsi_device *dsi)
458{
459 struct mipi_dsi_msg msg = {
460 .channel = dsi->channel,
461 .type = MIPI_DSI_TURN_ON_PERIPHERAL,
462 .tx_buf = (u8 [2]) { 0, 0 },
463 .tx_len = 2,
464 };
465
466 return mipi_dsi_device_transfer(dsi, &msg);
467}
468EXPORT_SYMBOL(mipi_dsi_turn_on_peripheral);
469
YoungJun Chodbf30b62014-08-05 09:27:15 +0200470/*
471 * mipi_dsi_set_maximum_return_packet_size() - specify the maximum size of the
472 * the payload in a long packet transmitted from the peripheral back to the
473 * host processor
474 * @dsi: DSI peripheral device
475 * @value: the maximum size of the payload
476 *
477 * Return: 0 on success or a negative error code on failure.
478 */
479int mipi_dsi_set_maximum_return_packet_size(struct mipi_dsi_device *dsi,
480 u16 value)
481{
482 u8 tx[2] = { value & 0xff, value >> 8 };
483 struct mipi_dsi_msg msg = {
484 .channel = dsi->channel,
485 .type = MIPI_DSI_SET_MAXIMUM_RETURN_PACKET_SIZE,
486 .tx_len = sizeof(tx),
487 .tx_buf = tx,
488 };
489
490 return mipi_dsi_device_transfer(dsi, &msg);
491}
492EXPORT_SYMBOL(mipi_dsi_set_maximum_return_packet_size);
493
Thierry Redinga52879e2014-10-16 13:44:02 +0200494/**
Thierry Reding550ab842014-08-05 10:36:21 +0200495 * mipi_dsi_generic_write() - transmit data using a generic write packet
496 * @dsi: DSI peripheral device
497 * @payload: buffer containing the payload
498 * @size: size of payload buffer
499 *
500 * This function will automatically choose the right data type depending on
501 * the payload length.
502 *
503 * Return: The number of bytes transmitted on success or a negative error code
504 * on failure.
505 */
506ssize_t mipi_dsi_generic_write(struct mipi_dsi_device *dsi, const void *payload,
507 size_t size)
508{
509 struct mipi_dsi_msg msg = {
510 .channel = dsi->channel,
511 .tx_buf = payload,
512 .tx_len = size
513 };
514
515 switch (size) {
516 case 0:
517 msg.type = MIPI_DSI_GENERIC_SHORT_WRITE_0_PARAM;
518 break;
519
520 case 1:
521 msg.type = MIPI_DSI_GENERIC_SHORT_WRITE_1_PARAM;
522 break;
523
524 case 2:
525 msg.type = MIPI_DSI_GENERIC_SHORT_WRITE_2_PARAM;
526 break;
527
528 default:
529 msg.type = MIPI_DSI_GENERIC_LONG_WRITE;
530 break;
531 }
532
533 return mipi_dsi_device_transfer(dsi, &msg);
534}
535EXPORT_SYMBOL(mipi_dsi_generic_write);
536
537/**
538 * mipi_dsi_generic_read() - receive data using a generic read packet
539 * @dsi: DSI peripheral device
540 * @params: buffer containing the request parameters
541 * @num_params: number of request parameters
542 * @data: buffer in which to return the received data
543 * @size: size of receive buffer
544 *
545 * This function will automatically choose the right data type depending on
546 * the number of parameters passed in.
547 *
548 * Return: The number of bytes successfully read or a negative error code on
549 * failure.
550 */
551ssize_t mipi_dsi_generic_read(struct mipi_dsi_device *dsi, const void *params,
552 size_t num_params, void *data, size_t size)
553{
554 struct mipi_dsi_msg msg = {
555 .channel = dsi->channel,
556 .tx_len = num_params,
557 .tx_buf = params,
558 .rx_len = size,
559 .rx_buf = data
560 };
561
562 switch (num_params) {
563 case 0:
564 msg.type = MIPI_DSI_GENERIC_READ_REQUEST_0_PARAM;
565 break;
566
567 case 1:
568 msg.type = MIPI_DSI_GENERIC_READ_REQUEST_1_PARAM;
569 break;
570
571 case 2:
572 msg.type = MIPI_DSI_GENERIC_READ_REQUEST_2_PARAM;
573 break;
574
575 default:
576 return -EINVAL;
577 }
578
579 return mipi_dsi_device_transfer(dsi, &msg);
580}
581EXPORT_SYMBOL(mipi_dsi_generic_read);
582
583/**
Thierry Reding960dd612014-07-21 15:47:10 +0200584 * mipi_dsi_dcs_write_buffer() - transmit a DCS command with payload
585 * @dsi: DSI peripheral device
586 * @data: buffer containing data to be transmitted
587 * @len: size of transmission buffer
588 *
589 * This function will automatically choose the right data type depending on
590 * the command payload length.
591 *
592 * Return: The number of bytes successfully transmitted or a negative error
593 * code on failure.
Andrzej Hajda068a0022013-12-04 16:35:12 +0100594 */
Thierry Reding960dd612014-07-21 15:47:10 +0200595ssize_t mipi_dsi_dcs_write_buffer(struct mipi_dsi_device *dsi,
596 const void *data, size_t len)
Andrzej Hajda068a0022013-12-04 16:35:12 +0100597{
Andrzej Hajda068a0022013-12-04 16:35:12 +0100598 struct mipi_dsi_msg msg = {
Thierry Reding3c523d72014-07-21 12:28:25 +0200599 .channel = dsi->channel,
Andrzej Hajda068a0022013-12-04 16:35:12 +0100600 .tx_buf = data,
601 .tx_len = len
602 };
603
Andrzej Hajda068a0022013-12-04 16:35:12 +0100604 switch (len) {
605 case 0:
606 return -EINVAL;
Thierry Reding960dd612014-07-21 15:47:10 +0200607
Andrzej Hajda068a0022013-12-04 16:35:12 +0100608 case 1:
609 msg.type = MIPI_DSI_DCS_SHORT_WRITE;
610 break;
Thierry Reding960dd612014-07-21 15:47:10 +0200611
Andrzej Hajda068a0022013-12-04 16:35:12 +0100612 case 2:
613 msg.type = MIPI_DSI_DCS_SHORT_WRITE_PARAM;
614 break;
Thierry Reding960dd612014-07-21 15:47:10 +0200615
Andrzej Hajda068a0022013-12-04 16:35:12 +0100616 default:
617 msg.type = MIPI_DSI_DCS_LONG_WRITE;
618 break;
619 }
620
Thierry Reding9eb491f2014-10-14 11:12:32 +0200621 return mipi_dsi_device_transfer(dsi, &msg);
Andrzej Hajda068a0022013-12-04 16:35:12 +0100622}
Thierry Reding960dd612014-07-21 15:47:10 +0200623EXPORT_SYMBOL(mipi_dsi_dcs_write_buffer);
624
625/**
626 * mipi_dsi_dcs_write() - send DCS write command
627 * @dsi: DSI peripheral device
628 * @cmd: DCS command
629 * @data: buffer containing the command payload
630 * @len: command payload length
631 *
632 * This function will automatically choose the right data type depending on
633 * the command payload length.
634 *
635 * Return: The number of bytes successfully transmitted or a negative error
636 * code on failure.
637 */
638ssize_t mipi_dsi_dcs_write(struct mipi_dsi_device *dsi, u8 cmd,
639 const void *data, size_t len)
640{
641 ssize_t err;
642 size_t size;
643 u8 *tx;
644
645 if (len > 0) {
646 size = 1 + len;
647
648 tx = kmalloc(size, GFP_KERNEL);
649 if (!tx)
650 return -ENOMEM;
651
652 /* concatenate the DCS command byte and the payload */
653 tx[0] = cmd;
654 memcpy(&tx[1], data, len);
655 } else {
656 tx = &cmd;
657 size = 1;
658 }
659
660 err = mipi_dsi_dcs_write_buffer(dsi, tx, size);
661
662 if (len > 0)
663 kfree(tx);
664
665 return err;
666}
Andrzej Hajda068a0022013-12-04 16:35:12 +0100667EXPORT_SYMBOL(mipi_dsi_dcs_write);
668
669/**
Thierry Reding960dd612014-07-21 15:47:10 +0200670 * mipi_dsi_dcs_read() - send DCS read request command
671 * @dsi: DSI peripheral device
672 * @cmd: DCS command
673 * @data: buffer in which to receive data
674 * @len: size of receive buffer
Andrzej Hajda068a0022013-12-04 16:35:12 +0100675 *
Thierry Reding960dd612014-07-21 15:47:10 +0200676 * Return: The number of bytes read or a negative error code on failure.
Andrzej Hajda068a0022013-12-04 16:35:12 +0100677 */
Thierry Reding3c523d72014-07-21 12:28:25 +0200678ssize_t mipi_dsi_dcs_read(struct mipi_dsi_device *dsi, u8 cmd, void *data,
679 size_t len)
Andrzej Hajda068a0022013-12-04 16:35:12 +0100680{
Andrzej Hajda068a0022013-12-04 16:35:12 +0100681 struct mipi_dsi_msg msg = {
Thierry Reding3c523d72014-07-21 12:28:25 +0200682 .channel = dsi->channel,
Andrzej Hajda068a0022013-12-04 16:35:12 +0100683 .type = MIPI_DSI_DCS_READ,
684 .tx_buf = &cmd,
685 .tx_len = 1,
686 .rx_buf = data,
687 .rx_len = len
688 };
689
Thierry Reding9eb491f2014-10-14 11:12:32 +0200690 return mipi_dsi_device_transfer(dsi, &msg);
Andrzej Hajda068a0022013-12-04 16:35:12 +0100691}
692EXPORT_SYMBOL(mipi_dsi_dcs_read);
693
YoungJun Cho42fe1e72014-08-05 10:38:31 +0200694/**
Thierry Reding083d5732014-08-05 11:14:02 +0200695 * mipi_dsi_dcs_nop() - send DCS nop packet
696 * @dsi: DSI peripheral device
697 *
698 * Return: 0 on success or a negative error code on failure.
699 */
700int mipi_dsi_dcs_nop(struct mipi_dsi_device *dsi)
701{
702 ssize_t err;
703
704 err = mipi_dsi_dcs_write(dsi, MIPI_DCS_NOP, NULL, 0);
705 if (err < 0)
706 return err;
707
708 return 0;
709}
710EXPORT_SYMBOL(mipi_dsi_dcs_nop);
711
712/**
Thierry Reding2f16b892014-08-05 11:15:15 +0200713 * mipi_dsi_dcs_soft_reset() - perform a software reset of the display module
714 * @dsi: DSI peripheral device
715 *
716 * Return: 0 on success or a negative error code on failure.
717 */
718int mipi_dsi_dcs_soft_reset(struct mipi_dsi_device *dsi)
719{
720 ssize_t err;
721
722 err = mipi_dsi_dcs_write(dsi, MIPI_DCS_SOFT_RESET, NULL, 0);
723 if (err < 0)
724 return err;
725
726 return 0;
727}
728EXPORT_SYMBOL(mipi_dsi_dcs_soft_reset);
729
730/**
Thierry Reding3d9a8fc2014-08-05 11:17:06 +0200731 * mipi_dsi_dcs_get_power_mode() - query the display module's current power
732 * mode
733 * @dsi: DSI peripheral device
734 * @mode: return location for the current power mode
735 *
736 * Return: 0 on success or a negative error code on failure.
737 */
738int mipi_dsi_dcs_get_power_mode(struct mipi_dsi_device *dsi, u8 *mode)
739{
740 ssize_t err;
741
742 err = mipi_dsi_dcs_read(dsi, MIPI_DCS_GET_POWER_MODE, mode,
743 sizeof(*mode));
744 if (err <= 0) {
745 if (err == 0)
746 err = -ENODATA;
747
748 return err;
749 }
750
751 return 0;
752}
753EXPORT_SYMBOL(mipi_dsi_dcs_get_power_mode);
754
755/**
Thierry Reding5cc0af12014-08-05 11:18:46 +0200756 * mipi_dsi_dcs_get_pixel_format() - gets the pixel format for the RGB image
757 * data used by the interface
758 * @dsi: DSI peripheral device
759 * @format: return location for the pixel format
760 *
761 * Return: 0 on success or a negative error code on failure.
762 */
763int mipi_dsi_dcs_get_pixel_format(struct mipi_dsi_device *dsi, u8 *format)
764{
765 ssize_t err;
766
767 err = mipi_dsi_dcs_read(dsi, MIPI_DCS_GET_PIXEL_FORMAT, format,
768 sizeof(*format));
769 if (err <= 0) {
770 if (err == 0)
771 err = -ENODATA;
772
773 return err;
774 }
775
776 return 0;
777}
778EXPORT_SYMBOL(mipi_dsi_dcs_get_pixel_format);
779
780/**
YoungJun Cho42fe1e72014-08-05 10:38:31 +0200781 * mipi_dsi_dcs_enter_sleep_mode() - disable all unnecessary blocks inside the
782 * display module except interface communication
783 * @dsi: DSI peripheral device
784 *
785 * Return: 0 on success or a negative error code on failure.
786 */
787int mipi_dsi_dcs_enter_sleep_mode(struct mipi_dsi_device *dsi)
788{
789 ssize_t err;
790
791 err = mipi_dsi_dcs_write(dsi, MIPI_DCS_ENTER_SLEEP_MODE, NULL, 0);
792 if (err < 0)
793 return err;
794
795 return 0;
796}
797EXPORT_SYMBOL(mipi_dsi_dcs_enter_sleep_mode);
798
799/**
800 * mipi_dsi_dcs_exit_sleep_mode() - enable all blocks inside the display
801 * module
802 * @dsi: DSI peripheral device
803 *
804 * Return: 0 on success or a negative error code on failure.
805 */
806int mipi_dsi_dcs_exit_sleep_mode(struct mipi_dsi_device *dsi)
807{
808 ssize_t err;
809
810 err = mipi_dsi_dcs_write(dsi, MIPI_DCS_EXIT_SLEEP_MODE, NULL, 0);
811 if (err < 0)
812 return err;
813
814 return 0;
815}
816EXPORT_SYMBOL(mipi_dsi_dcs_exit_sleep_mode);
817
818/**
819 * mipi_dsi_dcs_set_display_off() - stop displaying the image data on the
820 * display device
821 * @dsi: DSI peripheral device
822 *
823 * Return: 0 on success or a negative error code on failure.
824 */
825int mipi_dsi_dcs_set_display_off(struct mipi_dsi_device *dsi)
826{
827 ssize_t err;
828
829 err = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_DISPLAY_OFF, NULL, 0);
830 if (err < 0)
831 return err;
832
833 return 0;
834}
835EXPORT_SYMBOL(mipi_dsi_dcs_set_display_off);
836
837/**
838 * mipi_dsi_dcs_set_display_on() - start displaying the image data on the
839 * display device
840 * @dsi: DSI peripheral device
841 *
842 * Return: 0 on success or a negative error code on failure
843 */
844int mipi_dsi_dcs_set_display_on(struct mipi_dsi_device *dsi)
845{
846 ssize_t err;
847
848 err = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_DISPLAY_ON, NULL, 0);
849 if (err < 0)
850 return err;
851
852 return 0;
853}
854EXPORT_SYMBOL(mipi_dsi_dcs_set_display_on);
855
856/**
Thierry Reding3b46d4a2014-08-05 11:20:25 +0200857 * mipi_dsi_dcs_set_column_address() - define the column extent of the frame
858 * memory accessed by the host processor
859 * @dsi: DSI peripheral device
860 * @start: first column of frame memory
861 * @end: last column of frame memory
862 *
863 * Return: 0 on success or a negative error code on failure.
864 */
865int mipi_dsi_dcs_set_column_address(struct mipi_dsi_device *dsi, u16 start,
866 u16 end)
867{
868 u8 payload[4] = { start >> 8, start & 0xff, end >> 8, end & 0xff };
869 ssize_t err;
870
871 err = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_COLUMN_ADDRESS, payload,
872 sizeof(payload));
873 if (err < 0)
874 return err;
875
876 return 0;
877}
878EXPORT_SYMBOL(mipi_dsi_dcs_set_column_address);
879
880/**
881 * mipi_dsi_dcs_set_page_address() - define the page extent of the frame
882 * memory accessed by the host processor
883 * @dsi: DSI peripheral device
884 * @start: first page of frame memory
885 * @end: last page of frame memory
886 *
887 * Return: 0 on success or a negative error code on failure.
888 */
889int mipi_dsi_dcs_set_page_address(struct mipi_dsi_device *dsi, u16 start,
890 u16 end)
891{
892 u8 payload[4] = { start >> 8, start & 0xff, end >> 8, end & 0xff };
893 ssize_t err;
894
895 err = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_PAGE_ADDRESS, payload,
896 sizeof(payload));
897 if (err < 0)
898 return err;
899
900 return 0;
901}
902EXPORT_SYMBOL(mipi_dsi_dcs_set_page_address);
903
904/**
YoungJun Cho42fe1e72014-08-05 10:38:31 +0200905 * mipi_dsi_dcs_set_tear_off() - turn off the display module's Tearing Effect
906 * output signal on the TE signal line
907 * @dsi: DSI peripheral device
908 *
909 * Return: 0 on success or a negative error code on failure
910 */
911int mipi_dsi_dcs_set_tear_off(struct mipi_dsi_device *dsi)
912{
913 ssize_t err;
914
915 err = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_TEAR_OFF, NULL, 0);
916 if (err < 0)
917 return err;
918
919 return 0;
920}
921EXPORT_SYMBOL(mipi_dsi_dcs_set_tear_off);
922
923/**
924 * mipi_dsi_dcs_set_tear_on() - turn on the display module's Tearing Effect
925 * output signal on the TE signal line.
926 * @dsi: DSI peripheral device
927 * @mode: the Tearing Effect Output Line mode
928 *
929 * Return: 0 on success or a negative error code on failure
930 */
931int mipi_dsi_dcs_set_tear_on(struct mipi_dsi_device *dsi,
932 enum mipi_dsi_dcs_tear_mode mode)
933{
934 u8 value = mode;
935 ssize_t err;
936
937 err = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_TEAR_ON, &value,
938 sizeof(value));
939 if (err < 0)
940 return err;
941
942 return 0;
943}
944EXPORT_SYMBOL(mipi_dsi_dcs_set_tear_on);
945
Thierry Reding5cc0af12014-08-05 11:18:46 +0200946/**
947 * mipi_dsi_dcs_set_pixel_format() - sets the pixel format for the RGB image
948 * data used by the interface
949 * @dsi: DSI peripheral device
950 * @format: pixel format
951 *
952 * Return: 0 on success or a negative error code on failure.
953 */
954int mipi_dsi_dcs_set_pixel_format(struct mipi_dsi_device *dsi, u8 format)
955{
956 ssize_t err;
957
958 err = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_PIXEL_FORMAT, &format,
959 sizeof(format));
960 if (err < 0)
961 return err;
962
963 return 0;
964}
965EXPORT_SYMBOL(mipi_dsi_dcs_set_pixel_format);
966
Andrzej Hajda068a0022013-12-04 16:35:12 +0100967static int mipi_dsi_drv_probe(struct device *dev)
968{
969 struct mipi_dsi_driver *drv = to_mipi_dsi_driver(dev->driver);
970 struct mipi_dsi_device *dsi = to_mipi_dsi_device(dev);
971
972 return drv->probe(dsi);
973}
974
975static int mipi_dsi_drv_remove(struct device *dev)
976{
977 struct mipi_dsi_driver *drv = to_mipi_dsi_driver(dev->driver);
978 struct mipi_dsi_device *dsi = to_mipi_dsi_device(dev);
979
980 return drv->remove(dsi);
981}
982
Thierry Redingd1621802014-04-29 17:19:57 +0200983static void mipi_dsi_drv_shutdown(struct device *dev)
984{
985 struct mipi_dsi_driver *drv = to_mipi_dsi_driver(dev->driver);
986 struct mipi_dsi_device *dsi = to_mipi_dsi_device(dev);
987
988 drv->shutdown(dsi);
989}
990
Andrzej Hajda068a0022013-12-04 16:35:12 +0100991/**
Thierry Reding99035e92014-11-04 16:09:56 +0100992 * mipi_dsi_driver_register_full() - register a driver for DSI devices
Andrzej Hajda068a0022013-12-04 16:35:12 +0100993 * @drv: DSI driver structure
Thierry Reding99035e92014-11-04 16:09:56 +0100994 * @owner: owner module
Thierry Reding009081e2014-08-05 10:41:13 +0200995 *
996 * Return: 0 on success or a negative error code on failure.
Andrzej Hajda068a0022013-12-04 16:35:12 +0100997 */
Thierry Reding99035e92014-11-04 16:09:56 +0100998int mipi_dsi_driver_register_full(struct mipi_dsi_driver *drv,
999 struct module *owner)
Andrzej Hajda068a0022013-12-04 16:35:12 +01001000{
1001 drv->driver.bus = &mipi_dsi_bus_type;
Thierry Reding99035e92014-11-04 16:09:56 +01001002 drv->driver.owner = owner;
1003
Andrzej Hajda068a0022013-12-04 16:35:12 +01001004 if (drv->probe)
1005 drv->driver.probe = mipi_dsi_drv_probe;
1006 if (drv->remove)
1007 drv->driver.remove = mipi_dsi_drv_remove;
Thierry Redingd1621802014-04-29 17:19:57 +02001008 if (drv->shutdown)
1009 drv->driver.shutdown = mipi_dsi_drv_shutdown;
Andrzej Hajda068a0022013-12-04 16:35:12 +01001010
1011 return driver_register(&drv->driver);
1012}
Thierry Reding99035e92014-11-04 16:09:56 +01001013EXPORT_SYMBOL(mipi_dsi_driver_register_full);
Andrzej Hajda068a0022013-12-04 16:35:12 +01001014
1015/**
Thierry Reding009081e2014-08-05 10:41:13 +02001016 * mipi_dsi_driver_unregister() - unregister a driver for DSI devices
Andrzej Hajda068a0022013-12-04 16:35:12 +01001017 * @drv: DSI driver structure
Thierry Reding009081e2014-08-05 10:41:13 +02001018 *
1019 * Return: 0 on success or a negative error code on failure.
Andrzej Hajda068a0022013-12-04 16:35:12 +01001020 */
1021void mipi_dsi_driver_unregister(struct mipi_dsi_driver *drv)
1022{
1023 driver_unregister(&drv->driver);
1024}
1025EXPORT_SYMBOL(mipi_dsi_driver_unregister);
1026
1027static int __init mipi_dsi_bus_init(void)
1028{
1029 return bus_register(&mipi_dsi_bus_type);
1030}
1031postcore_initcall(mipi_dsi_bus_init);
1032
1033MODULE_AUTHOR("Andrzej Hajda <a.hajda@samsung.com>");
1034MODULE_DESCRIPTION("MIPI DSI Bus");
1035MODULE_LICENSE("GPL and additional rights");