blob: 42a7aacf7a2fb5d4d824643967e2e9c9c2ce8a1c [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
Andrzej Hajda068a0022013-12-04 16:35:12 +0100228int mipi_dsi_host_register(struct mipi_dsi_host *host)
229{
230 struct device_node *node;
231
Andrzej Hajdae49640d2014-03-28 12:52:37 +0100232 for_each_available_child_of_node(host->dev->of_node, node) {
233 /* skip nodes without reg property */
234 if (!of_find_property(node, "reg", NULL))
235 continue;
Andrzej Hajda068a0022013-12-04 16:35:12 +0100236 of_mipi_dsi_device_add(host, node);
Andrzej Hajdae49640d2014-03-28 12:52:37 +0100237 }
Andrzej Hajda068a0022013-12-04 16:35:12 +0100238
239 return 0;
240}
241EXPORT_SYMBOL(mipi_dsi_host_register);
242
243static int mipi_dsi_remove_device_fn(struct device *dev, void *priv)
244{
245 struct mipi_dsi_device *dsi = to_mipi_dsi_device(dev);
246
247 device_unregister(&dsi->dev);
248
249 return 0;
250}
251
252void mipi_dsi_host_unregister(struct mipi_dsi_host *host)
253{
254 device_for_each_child(host->dev, NULL, mipi_dsi_remove_device_fn);
255}
256EXPORT_SYMBOL(mipi_dsi_host_unregister);
257
258/**
259 * mipi_dsi_attach - attach a DSI device to its DSI host
260 * @dsi: DSI peripheral
261 */
262int mipi_dsi_attach(struct mipi_dsi_device *dsi)
263{
264 const struct mipi_dsi_host_ops *ops = dsi->host->ops;
265
266 if (!ops || !ops->attach)
267 return -ENOSYS;
268
269 return ops->attach(dsi->host, dsi);
270}
271EXPORT_SYMBOL(mipi_dsi_attach);
272
273/**
274 * mipi_dsi_detach - detach a DSI device from its DSI host
275 * @dsi: DSI peripheral
276 */
277int mipi_dsi_detach(struct mipi_dsi_device *dsi)
278{
279 const struct mipi_dsi_host_ops *ops = dsi->host->ops;
280
281 if (!ops || !ops->detach)
282 return -ENOSYS;
283
284 return ops->detach(dsi->host, dsi);
285}
286EXPORT_SYMBOL(mipi_dsi_detach);
287
Thierry Reding9eb491f2014-10-14 11:12:32 +0200288static ssize_t mipi_dsi_device_transfer(struct mipi_dsi_device *dsi,
289 struct mipi_dsi_msg *msg)
290{
291 const struct mipi_dsi_host_ops *ops = dsi->host->ops;
292
293 if (!ops || !ops->transfer)
294 return -ENOSYS;
295
296 if (dsi->mode_flags & MIPI_DSI_MODE_LPM)
297 msg->flags |= MIPI_DSI_MSG_USE_LPM;
298
299 return ops->transfer(dsi->host, msg);
300}
301
Andrzej Hajda068a0022013-12-04 16:35:12 +0100302/**
Thierry Reding02acb762014-11-04 14:59:14 +0100303 * mipi_dsi_packet_format_is_short - check if a packet is of the short format
304 * @type: MIPI DSI data type of the packet
305 *
306 * Return: true if the packet for the given data type is a short packet, false
307 * otherwise.
308 */
309bool mipi_dsi_packet_format_is_short(u8 type)
310{
311 switch (type) {
312 case MIPI_DSI_V_SYNC_START:
313 case MIPI_DSI_V_SYNC_END:
314 case MIPI_DSI_H_SYNC_START:
315 case MIPI_DSI_H_SYNC_END:
316 case MIPI_DSI_END_OF_TRANSMISSION:
317 case MIPI_DSI_COLOR_MODE_OFF:
318 case MIPI_DSI_COLOR_MODE_ON:
319 case MIPI_DSI_SHUTDOWN_PERIPHERAL:
320 case MIPI_DSI_TURN_ON_PERIPHERAL:
321 case MIPI_DSI_GENERIC_SHORT_WRITE_0_PARAM:
322 case MIPI_DSI_GENERIC_SHORT_WRITE_1_PARAM:
323 case MIPI_DSI_GENERIC_SHORT_WRITE_2_PARAM:
324 case MIPI_DSI_GENERIC_READ_REQUEST_0_PARAM:
325 case MIPI_DSI_GENERIC_READ_REQUEST_1_PARAM:
326 case MIPI_DSI_GENERIC_READ_REQUEST_2_PARAM:
327 case MIPI_DSI_DCS_SHORT_WRITE:
328 case MIPI_DSI_DCS_SHORT_WRITE_PARAM:
329 case MIPI_DSI_DCS_READ:
330 case MIPI_DSI_SET_MAXIMUM_RETURN_PACKET_SIZE:
331 return true;
332 }
333
334 return false;
335}
336EXPORT_SYMBOL(mipi_dsi_packet_format_is_short);
337
338/**
339 * mipi_dsi_packet_format_is_long - check if a packet is of the long format
340 * @type: MIPI DSI data type of the packet
341 *
342 * Return: true if the packet for the given data type is a long packet, false
343 * otherwise.
344 */
345bool mipi_dsi_packet_format_is_long(u8 type)
346{
347 switch (type) {
348 case MIPI_DSI_NULL_PACKET:
349 case MIPI_DSI_BLANKING_PACKET:
350 case MIPI_DSI_GENERIC_LONG_WRITE:
351 case MIPI_DSI_DCS_LONG_WRITE:
352 case MIPI_DSI_LOOSELY_PACKED_PIXEL_STREAM_YCBCR20:
353 case MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR24:
354 case MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR16:
355 case MIPI_DSI_PACKED_PIXEL_STREAM_30:
356 case MIPI_DSI_PACKED_PIXEL_STREAM_36:
357 case MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR12:
358 case MIPI_DSI_PACKED_PIXEL_STREAM_16:
359 case MIPI_DSI_PACKED_PIXEL_STREAM_18:
360 case MIPI_DSI_PIXEL_STREAM_3BYTE_18:
361 case MIPI_DSI_PACKED_PIXEL_STREAM_24:
362 return true;
363 }
364
365 return false;
366}
367EXPORT_SYMBOL(mipi_dsi_packet_format_is_long);
368
369/**
Thierry Redinga52879e2014-10-16 13:44:02 +0200370 * mipi_dsi_create_packet - create a packet from a message according to the
371 * DSI protocol
372 * @packet: pointer to a DSI packet structure
373 * @msg: message to translate into a packet
374 *
375 * Return: 0 on success or a negative error code on failure.
376 */
377int mipi_dsi_create_packet(struct mipi_dsi_packet *packet,
378 const struct mipi_dsi_msg *msg)
379{
Thierry Redinga52879e2014-10-16 13:44:02 +0200380 if (!packet || !msg)
381 return -EINVAL;
382
383 /* do some minimum sanity checking */
384 if (!mipi_dsi_packet_format_is_short(msg->type) &&
385 !mipi_dsi_packet_format_is_long(msg->type))
386 return -EINVAL;
387
388 if (msg->channel > 3)
389 return -EINVAL;
390
391 memset(packet, 0, sizeof(*packet));
392 packet->header[0] = ((msg->channel & 0x3) << 6) | (msg->type & 0x3f);
393
394 /* TODO: compute ECC if hardware support is not available */
395
396 /*
397 * Long write packets contain the word count in header bytes 1 and 2.
398 * The payload follows the header and is word count bytes long.
399 *
400 * Short write packets encode up to two parameters in header bytes 1
401 * and 2.
402 */
403 if (mipi_dsi_packet_format_is_long(msg->type)) {
404 packet->header[1] = (msg->tx_len >> 0) & 0xff;
405 packet->header[2] = (msg->tx_len >> 8) & 0xff;
406
407 packet->payload_length = msg->tx_len;
Thierry Reding9b973832014-12-05 11:46:56 +0100408 packet->payload = msg->tx_buf;
Thierry Redinga52879e2014-10-16 13:44:02 +0200409 } else {
Thierry Reding9b973832014-12-05 11:46:56 +0100410 const u8 *tx = msg->tx_buf;
411
Thierry Redinga52879e2014-10-16 13:44:02 +0200412 packet->header[1] = (msg->tx_len > 0) ? tx[0] : 0;
413 packet->header[2] = (msg->tx_len > 1) ? tx[1] : 0;
414 }
415
416 packet->size = sizeof(packet->header) + packet->payload_length;
417
418 return 0;
419}
420EXPORT_SYMBOL(mipi_dsi_create_packet);
421
Werner Johansson6e8c9e32015-10-30 17:38:26 -0700422/**
423 * mipi_dsi_shutdown_peripheral() - sends a Shutdown Peripheral command
424 * @dsi: DSI peripheral device
425 *
426 * Return: 0 on success or a negative error code on failure.
427 */
428int mipi_dsi_shutdown_peripheral(struct mipi_dsi_device *dsi)
429{
430 struct mipi_dsi_msg msg = {
431 .channel = dsi->channel,
432 .type = MIPI_DSI_SHUTDOWN_PERIPHERAL,
433 .tx_buf = (u8 [2]) { 0, 0 },
434 .tx_len = 2,
435 };
436
437 return mipi_dsi_device_transfer(dsi, &msg);
438}
439EXPORT_SYMBOL(mipi_dsi_shutdown_peripheral);
440
441/**
442 * mipi_dsi_turn_on_peripheral() - sends a Turn On Peripheral command
443 * @dsi: DSI peripheral device
444 *
445 * Return: 0 on success or a negative error code on failure.
446 */
447int mipi_dsi_turn_on_peripheral(struct mipi_dsi_device *dsi)
448{
449 struct mipi_dsi_msg msg = {
450 .channel = dsi->channel,
451 .type = MIPI_DSI_TURN_ON_PERIPHERAL,
452 .tx_buf = (u8 [2]) { 0, 0 },
453 .tx_len = 2,
454 };
455
456 return mipi_dsi_device_transfer(dsi, &msg);
457}
458EXPORT_SYMBOL(mipi_dsi_turn_on_peripheral);
459
YoungJun Chodbf30b62014-08-05 09:27:15 +0200460/*
461 * mipi_dsi_set_maximum_return_packet_size() - specify the maximum size of the
462 * the payload in a long packet transmitted from the peripheral back to the
463 * host processor
464 * @dsi: DSI peripheral device
465 * @value: the maximum size of the payload
466 *
467 * Return: 0 on success or a negative error code on failure.
468 */
469int mipi_dsi_set_maximum_return_packet_size(struct mipi_dsi_device *dsi,
470 u16 value)
471{
472 u8 tx[2] = { value & 0xff, value >> 8 };
473 struct mipi_dsi_msg msg = {
474 .channel = dsi->channel,
475 .type = MIPI_DSI_SET_MAXIMUM_RETURN_PACKET_SIZE,
476 .tx_len = sizeof(tx),
477 .tx_buf = tx,
478 };
479
480 return mipi_dsi_device_transfer(dsi, &msg);
481}
482EXPORT_SYMBOL(mipi_dsi_set_maximum_return_packet_size);
483
Thierry Redinga52879e2014-10-16 13:44:02 +0200484/**
Thierry Reding550ab842014-08-05 10:36:21 +0200485 * mipi_dsi_generic_write() - transmit data using a generic write packet
486 * @dsi: DSI peripheral device
487 * @payload: buffer containing the payload
488 * @size: size of payload buffer
489 *
490 * This function will automatically choose the right data type depending on
491 * the payload length.
492 *
493 * Return: The number of bytes transmitted on success or a negative error code
494 * on failure.
495 */
496ssize_t mipi_dsi_generic_write(struct mipi_dsi_device *dsi, const void *payload,
497 size_t size)
498{
499 struct mipi_dsi_msg msg = {
500 .channel = dsi->channel,
501 .tx_buf = payload,
502 .tx_len = size
503 };
504
505 switch (size) {
506 case 0:
507 msg.type = MIPI_DSI_GENERIC_SHORT_WRITE_0_PARAM;
508 break;
509
510 case 1:
511 msg.type = MIPI_DSI_GENERIC_SHORT_WRITE_1_PARAM;
512 break;
513
514 case 2:
515 msg.type = MIPI_DSI_GENERIC_SHORT_WRITE_2_PARAM;
516 break;
517
518 default:
519 msg.type = MIPI_DSI_GENERIC_LONG_WRITE;
520 break;
521 }
522
523 return mipi_dsi_device_transfer(dsi, &msg);
524}
525EXPORT_SYMBOL(mipi_dsi_generic_write);
526
527/**
528 * mipi_dsi_generic_read() - receive data using a generic read packet
529 * @dsi: DSI peripheral device
530 * @params: buffer containing the request parameters
531 * @num_params: number of request parameters
532 * @data: buffer in which to return the received data
533 * @size: size of receive buffer
534 *
535 * This function will automatically choose the right data type depending on
536 * the number of parameters passed in.
537 *
538 * Return: The number of bytes successfully read or a negative error code on
539 * failure.
540 */
541ssize_t mipi_dsi_generic_read(struct mipi_dsi_device *dsi, const void *params,
542 size_t num_params, void *data, size_t size)
543{
544 struct mipi_dsi_msg msg = {
545 .channel = dsi->channel,
546 .tx_len = num_params,
547 .tx_buf = params,
548 .rx_len = size,
549 .rx_buf = data
550 };
551
552 switch (num_params) {
553 case 0:
554 msg.type = MIPI_DSI_GENERIC_READ_REQUEST_0_PARAM;
555 break;
556
557 case 1:
558 msg.type = MIPI_DSI_GENERIC_READ_REQUEST_1_PARAM;
559 break;
560
561 case 2:
562 msg.type = MIPI_DSI_GENERIC_READ_REQUEST_2_PARAM;
563 break;
564
565 default:
566 return -EINVAL;
567 }
568
569 return mipi_dsi_device_transfer(dsi, &msg);
570}
571EXPORT_SYMBOL(mipi_dsi_generic_read);
572
573/**
Thierry Reding960dd612014-07-21 15:47:10 +0200574 * mipi_dsi_dcs_write_buffer() - transmit a DCS command with payload
575 * @dsi: DSI peripheral device
576 * @data: buffer containing data to be transmitted
577 * @len: size of transmission buffer
578 *
579 * This function will automatically choose the right data type depending on
580 * the command payload length.
581 *
582 * Return: The number of bytes successfully transmitted or a negative error
583 * code on failure.
Andrzej Hajda068a0022013-12-04 16:35:12 +0100584 */
Thierry Reding960dd612014-07-21 15:47:10 +0200585ssize_t mipi_dsi_dcs_write_buffer(struct mipi_dsi_device *dsi,
586 const void *data, size_t len)
Andrzej Hajda068a0022013-12-04 16:35:12 +0100587{
Andrzej Hajda068a0022013-12-04 16:35:12 +0100588 struct mipi_dsi_msg msg = {
Thierry Reding3c523d72014-07-21 12:28:25 +0200589 .channel = dsi->channel,
Andrzej Hajda068a0022013-12-04 16:35:12 +0100590 .tx_buf = data,
591 .tx_len = len
592 };
593
Andrzej Hajda068a0022013-12-04 16:35:12 +0100594 switch (len) {
595 case 0:
596 return -EINVAL;
Thierry Reding960dd612014-07-21 15:47:10 +0200597
Andrzej Hajda068a0022013-12-04 16:35:12 +0100598 case 1:
599 msg.type = MIPI_DSI_DCS_SHORT_WRITE;
600 break;
Thierry Reding960dd612014-07-21 15:47:10 +0200601
Andrzej Hajda068a0022013-12-04 16:35:12 +0100602 case 2:
603 msg.type = MIPI_DSI_DCS_SHORT_WRITE_PARAM;
604 break;
Thierry Reding960dd612014-07-21 15:47:10 +0200605
Andrzej Hajda068a0022013-12-04 16:35:12 +0100606 default:
607 msg.type = MIPI_DSI_DCS_LONG_WRITE;
608 break;
609 }
610
Thierry Reding9eb491f2014-10-14 11:12:32 +0200611 return mipi_dsi_device_transfer(dsi, &msg);
Andrzej Hajda068a0022013-12-04 16:35:12 +0100612}
Thierry Reding960dd612014-07-21 15:47:10 +0200613EXPORT_SYMBOL(mipi_dsi_dcs_write_buffer);
614
615/**
616 * mipi_dsi_dcs_write() - send DCS write command
617 * @dsi: DSI peripheral device
618 * @cmd: DCS command
619 * @data: buffer containing the command payload
620 * @len: command payload length
621 *
622 * This function will automatically choose the right data type depending on
623 * the command payload length.
624 *
625 * Return: The number of bytes successfully transmitted or a negative error
626 * code on failure.
627 */
628ssize_t mipi_dsi_dcs_write(struct mipi_dsi_device *dsi, u8 cmd,
629 const void *data, size_t len)
630{
631 ssize_t err;
632 size_t size;
633 u8 *tx;
634
635 if (len > 0) {
636 size = 1 + len;
637
638 tx = kmalloc(size, GFP_KERNEL);
639 if (!tx)
640 return -ENOMEM;
641
642 /* concatenate the DCS command byte and the payload */
643 tx[0] = cmd;
644 memcpy(&tx[1], data, len);
645 } else {
646 tx = &cmd;
647 size = 1;
648 }
649
650 err = mipi_dsi_dcs_write_buffer(dsi, tx, size);
651
652 if (len > 0)
653 kfree(tx);
654
655 return err;
656}
Andrzej Hajda068a0022013-12-04 16:35:12 +0100657EXPORT_SYMBOL(mipi_dsi_dcs_write);
658
659/**
Thierry Reding960dd612014-07-21 15:47:10 +0200660 * mipi_dsi_dcs_read() - send DCS read request command
661 * @dsi: DSI peripheral device
662 * @cmd: DCS command
663 * @data: buffer in which to receive data
664 * @len: size of receive buffer
Andrzej Hajda068a0022013-12-04 16:35:12 +0100665 *
Thierry Reding960dd612014-07-21 15:47:10 +0200666 * Return: The number of bytes read or a negative error code on failure.
Andrzej Hajda068a0022013-12-04 16:35:12 +0100667 */
Thierry Reding3c523d72014-07-21 12:28:25 +0200668ssize_t mipi_dsi_dcs_read(struct mipi_dsi_device *dsi, u8 cmd, void *data,
669 size_t len)
Andrzej Hajda068a0022013-12-04 16:35:12 +0100670{
Andrzej Hajda068a0022013-12-04 16:35:12 +0100671 struct mipi_dsi_msg msg = {
Thierry Reding3c523d72014-07-21 12:28:25 +0200672 .channel = dsi->channel,
Andrzej Hajda068a0022013-12-04 16:35:12 +0100673 .type = MIPI_DSI_DCS_READ,
674 .tx_buf = &cmd,
675 .tx_len = 1,
676 .rx_buf = data,
677 .rx_len = len
678 };
679
Thierry Reding9eb491f2014-10-14 11:12:32 +0200680 return mipi_dsi_device_transfer(dsi, &msg);
Andrzej Hajda068a0022013-12-04 16:35:12 +0100681}
682EXPORT_SYMBOL(mipi_dsi_dcs_read);
683
YoungJun Cho42fe1e72014-08-05 10:38:31 +0200684/**
Thierry Reding083d5732014-08-05 11:14:02 +0200685 * mipi_dsi_dcs_nop() - send DCS nop packet
686 * @dsi: DSI peripheral device
687 *
688 * Return: 0 on success or a negative error code on failure.
689 */
690int mipi_dsi_dcs_nop(struct mipi_dsi_device *dsi)
691{
692 ssize_t err;
693
694 err = mipi_dsi_dcs_write(dsi, MIPI_DCS_NOP, NULL, 0);
695 if (err < 0)
696 return err;
697
698 return 0;
699}
700EXPORT_SYMBOL(mipi_dsi_dcs_nop);
701
702/**
Thierry Reding2f16b892014-08-05 11:15:15 +0200703 * mipi_dsi_dcs_soft_reset() - perform a software reset of the display module
704 * @dsi: DSI peripheral device
705 *
706 * Return: 0 on success or a negative error code on failure.
707 */
708int mipi_dsi_dcs_soft_reset(struct mipi_dsi_device *dsi)
709{
710 ssize_t err;
711
712 err = mipi_dsi_dcs_write(dsi, MIPI_DCS_SOFT_RESET, NULL, 0);
713 if (err < 0)
714 return err;
715
716 return 0;
717}
718EXPORT_SYMBOL(mipi_dsi_dcs_soft_reset);
719
720/**
Thierry Reding3d9a8fc2014-08-05 11:17:06 +0200721 * mipi_dsi_dcs_get_power_mode() - query the display module's current power
722 * mode
723 * @dsi: DSI peripheral device
724 * @mode: return location for the current power mode
725 *
726 * Return: 0 on success or a negative error code on failure.
727 */
728int mipi_dsi_dcs_get_power_mode(struct mipi_dsi_device *dsi, u8 *mode)
729{
730 ssize_t err;
731
732 err = mipi_dsi_dcs_read(dsi, MIPI_DCS_GET_POWER_MODE, mode,
733 sizeof(*mode));
734 if (err <= 0) {
735 if (err == 0)
736 err = -ENODATA;
737
738 return err;
739 }
740
741 return 0;
742}
743EXPORT_SYMBOL(mipi_dsi_dcs_get_power_mode);
744
745/**
Thierry Reding5cc0af12014-08-05 11:18:46 +0200746 * mipi_dsi_dcs_get_pixel_format() - gets the pixel format for the RGB image
747 * data used by the interface
748 * @dsi: DSI peripheral device
749 * @format: return location for the pixel format
750 *
751 * Return: 0 on success or a negative error code on failure.
752 */
753int mipi_dsi_dcs_get_pixel_format(struct mipi_dsi_device *dsi, u8 *format)
754{
755 ssize_t err;
756
757 err = mipi_dsi_dcs_read(dsi, MIPI_DCS_GET_PIXEL_FORMAT, format,
758 sizeof(*format));
759 if (err <= 0) {
760 if (err == 0)
761 err = -ENODATA;
762
763 return err;
764 }
765
766 return 0;
767}
768EXPORT_SYMBOL(mipi_dsi_dcs_get_pixel_format);
769
770/**
YoungJun Cho42fe1e72014-08-05 10:38:31 +0200771 * mipi_dsi_dcs_enter_sleep_mode() - disable all unnecessary blocks inside the
772 * display module except interface communication
773 * @dsi: DSI peripheral device
774 *
775 * Return: 0 on success or a negative error code on failure.
776 */
777int mipi_dsi_dcs_enter_sleep_mode(struct mipi_dsi_device *dsi)
778{
779 ssize_t err;
780
781 err = mipi_dsi_dcs_write(dsi, MIPI_DCS_ENTER_SLEEP_MODE, NULL, 0);
782 if (err < 0)
783 return err;
784
785 return 0;
786}
787EXPORT_SYMBOL(mipi_dsi_dcs_enter_sleep_mode);
788
789/**
790 * mipi_dsi_dcs_exit_sleep_mode() - enable all blocks inside the display
791 * module
792 * @dsi: DSI peripheral device
793 *
794 * Return: 0 on success or a negative error code on failure.
795 */
796int mipi_dsi_dcs_exit_sleep_mode(struct mipi_dsi_device *dsi)
797{
798 ssize_t err;
799
800 err = mipi_dsi_dcs_write(dsi, MIPI_DCS_EXIT_SLEEP_MODE, NULL, 0);
801 if (err < 0)
802 return err;
803
804 return 0;
805}
806EXPORT_SYMBOL(mipi_dsi_dcs_exit_sleep_mode);
807
808/**
809 * mipi_dsi_dcs_set_display_off() - stop displaying the image data on the
810 * display device
811 * @dsi: DSI peripheral device
812 *
813 * Return: 0 on success or a negative error code on failure.
814 */
815int mipi_dsi_dcs_set_display_off(struct mipi_dsi_device *dsi)
816{
817 ssize_t err;
818
819 err = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_DISPLAY_OFF, NULL, 0);
820 if (err < 0)
821 return err;
822
823 return 0;
824}
825EXPORT_SYMBOL(mipi_dsi_dcs_set_display_off);
826
827/**
828 * mipi_dsi_dcs_set_display_on() - start displaying the image data on the
829 * display device
830 * @dsi: DSI peripheral device
831 *
832 * Return: 0 on success or a negative error code on failure
833 */
834int mipi_dsi_dcs_set_display_on(struct mipi_dsi_device *dsi)
835{
836 ssize_t err;
837
838 err = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_DISPLAY_ON, NULL, 0);
839 if (err < 0)
840 return err;
841
842 return 0;
843}
844EXPORT_SYMBOL(mipi_dsi_dcs_set_display_on);
845
846/**
Thierry Reding3b46d4a2014-08-05 11:20:25 +0200847 * mipi_dsi_dcs_set_column_address() - define the column extent of the frame
848 * memory accessed by the host processor
849 * @dsi: DSI peripheral device
850 * @start: first column of frame memory
851 * @end: last column of frame memory
852 *
853 * Return: 0 on success or a negative error code on failure.
854 */
855int mipi_dsi_dcs_set_column_address(struct mipi_dsi_device *dsi, u16 start,
856 u16 end)
857{
858 u8 payload[4] = { start >> 8, start & 0xff, end >> 8, end & 0xff };
859 ssize_t err;
860
861 err = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_COLUMN_ADDRESS, payload,
862 sizeof(payload));
863 if (err < 0)
864 return err;
865
866 return 0;
867}
868EXPORT_SYMBOL(mipi_dsi_dcs_set_column_address);
869
870/**
871 * mipi_dsi_dcs_set_page_address() - define the page extent of the frame
872 * memory accessed by the host processor
873 * @dsi: DSI peripheral device
874 * @start: first page of frame memory
875 * @end: last page of frame memory
876 *
877 * Return: 0 on success or a negative error code on failure.
878 */
879int mipi_dsi_dcs_set_page_address(struct mipi_dsi_device *dsi, u16 start,
880 u16 end)
881{
882 u8 payload[4] = { start >> 8, start & 0xff, end >> 8, end & 0xff };
883 ssize_t err;
884
885 err = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_PAGE_ADDRESS, payload,
886 sizeof(payload));
887 if (err < 0)
888 return err;
889
890 return 0;
891}
892EXPORT_SYMBOL(mipi_dsi_dcs_set_page_address);
893
894/**
YoungJun Cho42fe1e72014-08-05 10:38:31 +0200895 * mipi_dsi_dcs_set_tear_off() - turn off the display module's Tearing Effect
896 * output signal on the TE signal line
897 * @dsi: DSI peripheral device
898 *
899 * Return: 0 on success or a negative error code on failure
900 */
901int mipi_dsi_dcs_set_tear_off(struct mipi_dsi_device *dsi)
902{
903 ssize_t err;
904
905 err = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_TEAR_OFF, NULL, 0);
906 if (err < 0)
907 return err;
908
909 return 0;
910}
911EXPORT_SYMBOL(mipi_dsi_dcs_set_tear_off);
912
913/**
914 * mipi_dsi_dcs_set_tear_on() - turn on the display module's Tearing Effect
915 * output signal on the TE signal line.
916 * @dsi: DSI peripheral device
917 * @mode: the Tearing Effect Output Line mode
918 *
919 * Return: 0 on success or a negative error code on failure
920 */
921int mipi_dsi_dcs_set_tear_on(struct mipi_dsi_device *dsi,
922 enum mipi_dsi_dcs_tear_mode mode)
923{
924 u8 value = mode;
925 ssize_t err;
926
927 err = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_TEAR_ON, &value,
928 sizeof(value));
929 if (err < 0)
930 return err;
931
932 return 0;
933}
934EXPORT_SYMBOL(mipi_dsi_dcs_set_tear_on);
935
Thierry Reding5cc0af12014-08-05 11:18:46 +0200936/**
937 * mipi_dsi_dcs_set_pixel_format() - sets the pixel format for the RGB image
938 * data used by the interface
939 * @dsi: DSI peripheral device
940 * @format: pixel format
941 *
942 * Return: 0 on success or a negative error code on failure.
943 */
944int mipi_dsi_dcs_set_pixel_format(struct mipi_dsi_device *dsi, u8 format)
945{
946 ssize_t err;
947
948 err = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_PIXEL_FORMAT, &format,
949 sizeof(format));
950 if (err < 0)
951 return err;
952
953 return 0;
954}
955EXPORT_SYMBOL(mipi_dsi_dcs_set_pixel_format);
956
Andrzej Hajda068a0022013-12-04 16:35:12 +0100957static int mipi_dsi_drv_probe(struct device *dev)
958{
959 struct mipi_dsi_driver *drv = to_mipi_dsi_driver(dev->driver);
960 struct mipi_dsi_device *dsi = to_mipi_dsi_device(dev);
961
962 return drv->probe(dsi);
963}
964
965static int mipi_dsi_drv_remove(struct device *dev)
966{
967 struct mipi_dsi_driver *drv = to_mipi_dsi_driver(dev->driver);
968 struct mipi_dsi_device *dsi = to_mipi_dsi_device(dev);
969
970 return drv->remove(dsi);
971}
972
Thierry Redingd1621802014-04-29 17:19:57 +0200973static void mipi_dsi_drv_shutdown(struct device *dev)
974{
975 struct mipi_dsi_driver *drv = to_mipi_dsi_driver(dev->driver);
976 struct mipi_dsi_device *dsi = to_mipi_dsi_device(dev);
977
978 drv->shutdown(dsi);
979}
980
Andrzej Hajda068a0022013-12-04 16:35:12 +0100981/**
Thierry Reding99035e92014-11-04 16:09:56 +0100982 * mipi_dsi_driver_register_full() - register a driver for DSI devices
Andrzej Hajda068a0022013-12-04 16:35:12 +0100983 * @drv: DSI driver structure
Thierry Reding99035e92014-11-04 16:09:56 +0100984 * @owner: owner module
Thierry Reding009081e2014-08-05 10:41:13 +0200985 *
986 * Return: 0 on success or a negative error code on failure.
Andrzej Hajda068a0022013-12-04 16:35:12 +0100987 */
Thierry Reding99035e92014-11-04 16:09:56 +0100988int mipi_dsi_driver_register_full(struct mipi_dsi_driver *drv,
989 struct module *owner)
Andrzej Hajda068a0022013-12-04 16:35:12 +0100990{
991 drv->driver.bus = &mipi_dsi_bus_type;
Thierry Reding99035e92014-11-04 16:09:56 +0100992 drv->driver.owner = owner;
993
Andrzej Hajda068a0022013-12-04 16:35:12 +0100994 if (drv->probe)
995 drv->driver.probe = mipi_dsi_drv_probe;
996 if (drv->remove)
997 drv->driver.remove = mipi_dsi_drv_remove;
Thierry Redingd1621802014-04-29 17:19:57 +0200998 if (drv->shutdown)
999 drv->driver.shutdown = mipi_dsi_drv_shutdown;
Andrzej Hajda068a0022013-12-04 16:35:12 +01001000
1001 return driver_register(&drv->driver);
1002}
Thierry Reding99035e92014-11-04 16:09:56 +01001003EXPORT_SYMBOL(mipi_dsi_driver_register_full);
Andrzej Hajda068a0022013-12-04 16:35:12 +01001004
1005/**
Thierry Reding009081e2014-08-05 10:41:13 +02001006 * mipi_dsi_driver_unregister() - unregister a driver for DSI devices
Andrzej Hajda068a0022013-12-04 16:35:12 +01001007 * @drv: DSI driver structure
Thierry Reding009081e2014-08-05 10:41:13 +02001008 *
1009 * Return: 0 on success or a negative error code on failure.
Andrzej Hajda068a0022013-12-04 16:35:12 +01001010 */
1011void mipi_dsi_driver_unregister(struct mipi_dsi_driver *drv)
1012{
1013 driver_unregister(&drv->driver);
1014}
1015EXPORT_SYMBOL(mipi_dsi_driver_unregister);
1016
1017static int __init mipi_dsi_bus_init(void)
1018{
1019 return bus_register(&mipi_dsi_bus_type);
1020}
1021postcore_initcall(mipi_dsi_bus_init);
1022
1023MODULE_AUTHOR("Andrzej Hajda <a.hajda@samsung.com>");
1024MODULE_DESCRIPTION("MIPI DSI Bus");
1025MODULE_LICENSE("GPL and additional rights");