1 /* $NetBSD: drm_mipi_dsi.c,v 1.3 2021/12/18 23:44:57 riastradh Exp $ */
2
3 /*
4 * MIPI DSI Bus
5 *
6 * Copyright (C) 2012-2013, Samsung Electronics, Co., Ltd.
7 * Andrzej Hajda <a.hajda@samsung.com>
8 *
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the
11 * "Software"), to deal in the Software without restriction, including
12 * without limitation the rights to use, copy, modify, merge, publish,
13 * distribute, sub license, and/or sell copies of the Software, and to
14 * permit persons to whom the Software is furnished to do so, subject to
15 * the following conditions:
16 *
17 * The above copyright notice and this permission notice (including the
18 * next paragraph) shall be included in all copies or substantial portions
19 * of the Software.
20 *
21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
24 * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
25 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
26 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
27 * USE OR OTHER DEALINGS IN THE SOFTWARE.
28 */
29
30 #include <sys/cdefs.h>
31 __KERNEL_RCSID(0, "$NetBSD: drm_mipi_dsi.c,v 1.3 2021/12/18 23:44:57 riastradh Exp $");
32
33 #include <drm/drm_mipi_dsi.h>
34
35 #include <linux/device.h>
36 #include <linux/module.h>
37 #include <linux/of_device.h>
38 #include <linux/pm_runtime.h>
39 #include <linux/slab.h>
40
41 #include <drm/drm_dsc.h>
42 #include <video/mipi_display.h>
43
44 /**
45 * DOC: dsi helpers
46 *
47 * These functions contain some common logic and helpers to deal with MIPI DSI
48 * peripherals.
49 *
50 * Helpers are provided for a number of standard MIPI DSI command as well as a
51 * subset of the MIPI DCS command set.
52 */
53
mipi_dsi_device_match(struct device * dev,struct device_driver * drv)54 static int mipi_dsi_device_match(struct device *dev, struct device_driver *drv)
55 {
56 struct mipi_dsi_device *dsi = to_mipi_dsi_device(dev);
57
58 /* attempt OF style match */
59 if (of_driver_match_device(dev, drv))
60 return 1;
61
62 /* compare DSI device and driver names */
63 if (!strcmp(dsi->name, drv->name))
64 return 1;
65
66 return 0;
67 }
68
mipi_dsi_uevent(struct device * dev,struct kobj_uevent_env * env)69 static int mipi_dsi_uevent(struct device *dev, struct kobj_uevent_env *env)
70 {
71 struct mipi_dsi_device *dsi = to_mipi_dsi_device(dev);
72 int err;
73
74 err = of_device_uevent_modalias(dev, env);
75 if (err != -ENODEV)
76 return err;
77
78 add_uevent_var(env, "MODALIAS=%s%s", MIPI_DSI_MODULE_PREFIX,
79 dsi->name);
80
81 return 0;
82 }
83
84 static const struct dev_pm_ops mipi_dsi_device_pm_ops = {
85 .runtime_suspend = pm_generic_runtime_suspend,
86 .runtime_resume = pm_generic_runtime_resume,
87 .suspend = pm_generic_suspend,
88 .resume = pm_generic_resume,
89 .freeze = pm_generic_freeze,
90 .thaw = pm_generic_thaw,
91 .poweroff = pm_generic_poweroff,
92 .restore = pm_generic_restore,
93 };
94
95 static struct bus_type mipi_dsi_bus_type = {
96 .name = "mipi-dsi",
97 .match = mipi_dsi_device_match,
98 .uevent = mipi_dsi_uevent,
99 .pm = &mipi_dsi_device_pm_ops,
100 };
101
102 /**
103 * of_find_mipi_dsi_device_by_node() - find the MIPI DSI device matching a
104 * device tree node
105 * @np: device tree node
106 *
107 * Return: A pointer to the MIPI DSI device corresponding to @np or NULL if no
108 * such device exists (or has not been registered yet).
109 */
of_find_mipi_dsi_device_by_node(struct device_node * np)110 struct mipi_dsi_device *of_find_mipi_dsi_device_by_node(struct device_node *np)
111 {
112 struct device *dev;
113
114 dev = bus_find_device_by_of_node(&mipi_dsi_bus_type, np);
115
116 return dev ? to_mipi_dsi_device(dev) : NULL;
117 }
118 EXPORT_SYMBOL(of_find_mipi_dsi_device_by_node);
119
mipi_dsi_dev_release(struct device * dev)120 static void mipi_dsi_dev_release(struct device *dev)
121 {
122 struct mipi_dsi_device *dsi = to_mipi_dsi_device(dev);
123
124 of_node_put(dev->of_node);
125 kfree(dsi);
126 }
127
128 static const struct device_type mipi_dsi_device_type = {
129 .release = mipi_dsi_dev_release,
130 };
131
mipi_dsi_device_alloc(struct mipi_dsi_host * host)132 static struct mipi_dsi_device *mipi_dsi_device_alloc(struct mipi_dsi_host *host)
133 {
134 struct mipi_dsi_device *dsi;
135
136 dsi = kzalloc(sizeof(*dsi), GFP_KERNEL);
137 if (!dsi)
138 return ERR_PTR(-ENOMEM);
139
140 dsi->host = host;
141 dsi->dev.bus = &mipi_dsi_bus_type;
142 dsi->dev.parent = host->dev;
143 dsi->dev.type = &mipi_dsi_device_type;
144
145 device_initialize(&dsi->dev);
146
147 return dsi;
148 }
149
mipi_dsi_device_add(struct mipi_dsi_device * dsi)150 static int mipi_dsi_device_add(struct mipi_dsi_device *dsi)
151 {
152 struct mipi_dsi_host *host = dsi->host;
153
154 dev_set_name(&dsi->dev, "%s.%d", dev_name(host->dev), dsi->channel);
155
156 return device_add(&dsi->dev);
157 }
158
159 #if IS_ENABLED(CONFIG_OF)
160 static struct mipi_dsi_device *
of_mipi_dsi_device_add(struct mipi_dsi_host * host,struct device_node * node)161 of_mipi_dsi_device_add(struct mipi_dsi_host *host, struct device_node *node)
162 {
163 struct device *dev = host->dev;
164 struct mipi_dsi_device_info info = { };
165 int ret;
166 u32 reg;
167
168 if (of_modalias_node(node, info.type, sizeof(info.type)) < 0) {
169 dev_err(dev, "modalias failure on %pOF\n", node);
170 return ERR_PTR(-EINVAL);
171 }
172
173 ret = of_property_read_u32(node, "reg", ®);
174 if (ret) {
175 dev_err(dev, "device node %pOF has no valid reg property: %d\n",
176 node, ret);
177 return ERR_PTR(-EINVAL);
178 }
179
180 info.channel = reg;
181 info.node = of_node_get(node);
182
183 return mipi_dsi_device_register_full(host, &info);
184 }
185 #else
186 static struct mipi_dsi_device *
of_mipi_dsi_device_add(struct mipi_dsi_host * host,struct device_node * node)187 of_mipi_dsi_device_add(struct mipi_dsi_host *host, struct device_node *node)
188 {
189 return ERR_PTR(-ENODEV);
190 }
191 #endif
192
193 /**
194 * mipi_dsi_device_register_full - create a MIPI DSI device
195 * @host: DSI host to which this device is connected
196 * @info: pointer to template containing DSI device information
197 *
198 * Create a MIPI DSI device by using the device information provided by
199 * mipi_dsi_device_info template
200 *
201 * Returns:
202 * A pointer to the newly created MIPI DSI device, or, a pointer encoded
203 * with an error
204 */
205 struct mipi_dsi_device *
mipi_dsi_device_register_full(struct mipi_dsi_host * host,const struct mipi_dsi_device_info * info)206 mipi_dsi_device_register_full(struct mipi_dsi_host *host,
207 const struct mipi_dsi_device_info *info)
208 {
209 struct mipi_dsi_device *dsi;
210 struct device *dev = host->dev;
211 int ret;
212
213 if (!info) {
214 dev_err(dev, "invalid mipi_dsi_device_info pointer\n");
215 return ERR_PTR(-EINVAL);
216 }
217
218 if (info->channel > 3) {
219 dev_err(dev, "invalid virtual channel: %u\n", info->channel);
220 return ERR_PTR(-EINVAL);
221 }
222
223 dsi = mipi_dsi_device_alloc(host);
224 if (IS_ERR(dsi)) {
225 dev_err(dev, "failed to allocate DSI device %ld\n",
226 PTR_ERR(dsi));
227 return dsi;
228 }
229
230 dsi->dev.of_node = info->node;
231 dsi->channel = info->channel;
232 strlcpy(dsi->name, info->type, sizeof(dsi->name));
233
234 ret = mipi_dsi_device_add(dsi);
235 if (ret) {
236 dev_err(dev, "failed to add DSI device %d\n", ret);
237 kfree(dsi);
238 return ERR_PTR(ret);
239 }
240
241 return dsi;
242 }
243 EXPORT_SYMBOL(mipi_dsi_device_register_full);
244
245 /**
246 * mipi_dsi_device_unregister - unregister MIPI DSI device
247 * @dsi: DSI peripheral device
248 */
mipi_dsi_device_unregister(struct mipi_dsi_device * dsi)249 void mipi_dsi_device_unregister(struct mipi_dsi_device *dsi)
250 {
251 device_unregister(&dsi->dev);
252 }
253 EXPORT_SYMBOL(mipi_dsi_device_unregister);
254
255 static DEFINE_MUTEX(host_lock);
256 static LIST_HEAD(host_list);
257
258 /**
259 * of_find_mipi_dsi_host_by_node() - find the MIPI DSI host matching a
260 * device tree node
261 * @node: device tree node
262 *
263 * Returns:
264 * A pointer to the MIPI DSI host corresponding to @node or NULL if no
265 * such device exists (or has not been registered yet).
266 */
of_find_mipi_dsi_host_by_node(struct device_node * node)267 struct mipi_dsi_host *of_find_mipi_dsi_host_by_node(struct device_node *node)
268 {
269 struct mipi_dsi_host *host;
270
271 mutex_lock(&host_lock);
272
273 list_for_each_entry(host, &host_list, list) {
274 if (host->dev->of_node == node) {
275 mutex_unlock(&host_lock);
276 return host;
277 }
278 }
279
280 mutex_unlock(&host_lock);
281
282 return NULL;
283 }
284 EXPORT_SYMBOL(of_find_mipi_dsi_host_by_node);
285
mipi_dsi_host_register(struct mipi_dsi_host * host)286 int mipi_dsi_host_register(struct mipi_dsi_host *host)
287 {
288 struct device_node *node;
289
290 for_each_available_child_of_node(host->dev->of_node, node) {
291 /* skip nodes without reg property */
292 if (!of_find_property(node, "reg", NULL))
293 continue;
294 of_mipi_dsi_device_add(host, node);
295 }
296
297 mutex_lock(&host_lock);
298 list_add_tail(&host->list, &host_list);
299 mutex_unlock(&host_lock);
300
301 return 0;
302 }
303 EXPORT_SYMBOL(mipi_dsi_host_register);
304
mipi_dsi_remove_device_fn(struct device * dev,void * priv)305 static int mipi_dsi_remove_device_fn(struct device *dev, void *priv)
306 {
307 struct mipi_dsi_device *dsi = to_mipi_dsi_device(dev);
308
309 mipi_dsi_device_unregister(dsi);
310
311 return 0;
312 }
313
mipi_dsi_host_unregister(struct mipi_dsi_host * host)314 void mipi_dsi_host_unregister(struct mipi_dsi_host *host)
315 {
316 device_for_each_child(host->dev, NULL, mipi_dsi_remove_device_fn);
317
318 mutex_lock(&host_lock);
319 list_del_init(&host->list);
320 mutex_unlock(&host_lock);
321 }
322 EXPORT_SYMBOL(mipi_dsi_host_unregister);
323
324 /**
325 * mipi_dsi_attach - attach a DSI device to its DSI host
326 * @dsi: DSI peripheral
327 */
mipi_dsi_attach(struct mipi_dsi_device * dsi)328 int mipi_dsi_attach(struct mipi_dsi_device *dsi)
329 {
330 const struct mipi_dsi_host_ops *ops = dsi->host->ops;
331
332 if (!ops || !ops->attach)
333 return -ENOSYS;
334
335 return ops->attach(dsi->host, dsi);
336 }
337 EXPORT_SYMBOL(mipi_dsi_attach);
338
339 /**
340 * mipi_dsi_detach - detach a DSI device from its DSI host
341 * @dsi: DSI peripheral
342 */
mipi_dsi_detach(struct mipi_dsi_device * dsi)343 int mipi_dsi_detach(struct mipi_dsi_device *dsi)
344 {
345 const struct mipi_dsi_host_ops *ops = dsi->host->ops;
346
347 if (!ops || !ops->detach)
348 return -ENOSYS;
349
350 return ops->detach(dsi->host, dsi);
351 }
352 EXPORT_SYMBOL(mipi_dsi_detach);
353
mipi_dsi_device_transfer(struct mipi_dsi_device * dsi,struct mipi_dsi_msg * msg)354 static ssize_t mipi_dsi_device_transfer(struct mipi_dsi_device *dsi,
355 struct mipi_dsi_msg *msg)
356 {
357 const struct mipi_dsi_host_ops *ops = dsi->host->ops;
358
359 if (!ops || !ops->transfer)
360 return -ENOSYS;
361
362 if (dsi->mode_flags & MIPI_DSI_MODE_LPM)
363 msg->flags |= MIPI_DSI_MSG_USE_LPM;
364
365 return ops->transfer(dsi->host, msg);
366 }
367
368 /**
369 * mipi_dsi_packet_format_is_short - check if a packet is of the short format
370 * @type: MIPI DSI data type of the packet
371 *
372 * Return: true if the packet for the given data type is a short packet, false
373 * otherwise.
374 */
mipi_dsi_packet_format_is_short(u8 type)375 bool mipi_dsi_packet_format_is_short(u8 type)
376 {
377 switch (type) {
378 case MIPI_DSI_V_SYNC_START:
379 case MIPI_DSI_V_SYNC_END:
380 case MIPI_DSI_H_SYNC_START:
381 case MIPI_DSI_H_SYNC_END:
382 case MIPI_DSI_COMPRESSION_MODE:
383 case MIPI_DSI_END_OF_TRANSMISSION:
384 case MIPI_DSI_COLOR_MODE_OFF:
385 case MIPI_DSI_COLOR_MODE_ON:
386 case MIPI_DSI_SHUTDOWN_PERIPHERAL:
387 case MIPI_DSI_TURN_ON_PERIPHERAL:
388 case MIPI_DSI_GENERIC_SHORT_WRITE_0_PARAM:
389 case MIPI_DSI_GENERIC_SHORT_WRITE_1_PARAM:
390 case MIPI_DSI_GENERIC_SHORT_WRITE_2_PARAM:
391 case MIPI_DSI_GENERIC_READ_REQUEST_0_PARAM:
392 case MIPI_DSI_GENERIC_READ_REQUEST_1_PARAM:
393 case MIPI_DSI_GENERIC_READ_REQUEST_2_PARAM:
394 case MIPI_DSI_DCS_SHORT_WRITE:
395 case MIPI_DSI_DCS_SHORT_WRITE_PARAM:
396 case MIPI_DSI_DCS_READ:
397 case MIPI_DSI_EXECUTE_QUEUE:
398 case MIPI_DSI_SET_MAXIMUM_RETURN_PACKET_SIZE:
399 return true;
400 }
401
402 return false;
403 }
404 EXPORT_SYMBOL(mipi_dsi_packet_format_is_short);
405
406 /**
407 * mipi_dsi_packet_format_is_long - check if a packet is of the long format
408 * @type: MIPI DSI data type of the packet
409 *
410 * Return: true if the packet for the given data type is a long packet, false
411 * otherwise.
412 */
mipi_dsi_packet_format_is_long(u8 type)413 bool mipi_dsi_packet_format_is_long(u8 type)
414 {
415 switch (type) {
416 case MIPI_DSI_NULL_PACKET:
417 case MIPI_DSI_BLANKING_PACKET:
418 case MIPI_DSI_GENERIC_LONG_WRITE:
419 case MIPI_DSI_DCS_LONG_WRITE:
420 case MIPI_DSI_PICTURE_PARAMETER_SET:
421 case MIPI_DSI_COMPRESSED_PIXEL_STREAM:
422 case MIPI_DSI_LOOSELY_PACKED_PIXEL_STREAM_YCBCR20:
423 case MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR24:
424 case MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR16:
425 case MIPI_DSI_PACKED_PIXEL_STREAM_30:
426 case MIPI_DSI_PACKED_PIXEL_STREAM_36:
427 case MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR12:
428 case MIPI_DSI_PACKED_PIXEL_STREAM_16:
429 case MIPI_DSI_PACKED_PIXEL_STREAM_18:
430 case MIPI_DSI_PIXEL_STREAM_3BYTE_18:
431 case MIPI_DSI_PACKED_PIXEL_STREAM_24:
432 return true;
433 }
434
435 return false;
436 }
437 EXPORT_SYMBOL(mipi_dsi_packet_format_is_long);
438
439 /**
440 * mipi_dsi_create_packet - create a packet from a message according to the
441 * DSI protocol
442 * @packet: pointer to a DSI packet structure
443 * @msg: message to translate into a packet
444 *
445 * Return: 0 on success or a negative error code on failure.
446 */
mipi_dsi_create_packet(struct mipi_dsi_packet * packet,const struct mipi_dsi_msg * msg)447 int mipi_dsi_create_packet(struct mipi_dsi_packet *packet,
448 const struct mipi_dsi_msg *msg)
449 {
450 if (!packet || !msg)
451 return -EINVAL;
452
453 /* do some minimum sanity checking */
454 if (!mipi_dsi_packet_format_is_short(msg->type) &&
455 !mipi_dsi_packet_format_is_long(msg->type))
456 return -EINVAL;
457
458 if (msg->channel > 3)
459 return -EINVAL;
460
461 memset(packet, 0, sizeof(*packet));
462 packet->header[0] = ((msg->channel & 0x3) << 6) | (msg->type & 0x3f);
463
464 /* TODO: compute ECC if hardware support is not available */
465
466 /*
467 * Long write packets contain the word count in header bytes 1 and 2.
468 * The payload follows the header and is word count bytes long.
469 *
470 * Short write packets encode up to two parameters in header bytes 1
471 * and 2.
472 */
473 if (mipi_dsi_packet_format_is_long(msg->type)) {
474 packet->header[1] = (msg->tx_len >> 0) & 0xff;
475 packet->header[2] = (msg->tx_len >> 8) & 0xff;
476
477 packet->payload_length = msg->tx_len;
478 packet->payload = msg->tx_buf;
479 } else {
480 const u8 *tx = msg->tx_buf;
481
482 packet->header[1] = (msg->tx_len > 0) ? tx[0] : 0;
483 packet->header[2] = (msg->tx_len > 1) ? tx[1] : 0;
484 }
485
486 packet->size = sizeof(packet->header) + packet->payload_length;
487
488 return 0;
489 }
490 EXPORT_SYMBOL(mipi_dsi_create_packet);
491
492 /**
493 * mipi_dsi_shutdown_peripheral() - sends a Shutdown Peripheral command
494 * @dsi: DSI peripheral device
495 *
496 * Return: 0 on success or a negative error code on failure.
497 */
mipi_dsi_shutdown_peripheral(struct mipi_dsi_device * dsi)498 int mipi_dsi_shutdown_peripheral(struct mipi_dsi_device *dsi)
499 {
500 struct mipi_dsi_msg msg = {
501 .channel = dsi->channel,
502 .type = MIPI_DSI_SHUTDOWN_PERIPHERAL,
503 .tx_buf = (u8 [2]) { 0, 0 },
504 .tx_len = 2,
505 };
506 int ret = mipi_dsi_device_transfer(dsi, &msg);
507
508 return (ret < 0) ? ret : 0;
509 }
510 EXPORT_SYMBOL(mipi_dsi_shutdown_peripheral);
511
512 /**
513 * mipi_dsi_turn_on_peripheral() - sends a Turn On Peripheral command
514 * @dsi: DSI peripheral device
515 *
516 * Return: 0 on success or a negative error code on failure.
517 */
mipi_dsi_turn_on_peripheral(struct mipi_dsi_device * dsi)518 int mipi_dsi_turn_on_peripheral(struct mipi_dsi_device *dsi)
519 {
520 struct mipi_dsi_msg msg = {
521 .channel = dsi->channel,
522 .type = MIPI_DSI_TURN_ON_PERIPHERAL,
523 .tx_buf = (u8 [2]) { 0, 0 },
524 .tx_len = 2,
525 };
526 int ret = mipi_dsi_device_transfer(dsi, &msg);
527
528 return (ret < 0) ? ret : 0;
529 }
530 EXPORT_SYMBOL(mipi_dsi_turn_on_peripheral);
531
532 /*
533 * mipi_dsi_set_maximum_return_packet_size() - specify the maximum size of the
534 * the payload in a long packet transmitted from the peripheral back to the
535 * host processor
536 * @dsi: DSI peripheral device
537 * @value: the maximum size of the payload
538 *
539 * Return: 0 on success or a negative error code on failure.
540 */
mipi_dsi_set_maximum_return_packet_size(struct mipi_dsi_device * dsi,u16 value)541 int mipi_dsi_set_maximum_return_packet_size(struct mipi_dsi_device *dsi,
542 u16 value)
543 {
544 u8 tx[2] = { value & 0xff, value >> 8 };
545 struct mipi_dsi_msg msg = {
546 .channel = dsi->channel,
547 .type = MIPI_DSI_SET_MAXIMUM_RETURN_PACKET_SIZE,
548 .tx_len = sizeof(tx),
549 .tx_buf = tx,
550 };
551 int ret = mipi_dsi_device_transfer(dsi, &msg);
552
553 return (ret < 0) ? ret : 0;
554 }
555 EXPORT_SYMBOL(mipi_dsi_set_maximum_return_packet_size);
556
557 /**
558 * mipi_dsi_compression_mode() - enable/disable DSC on the peripheral
559 * @dsi: DSI peripheral device
560 * @enable: Whether to enable or disable the DSC
561 *
562 * Enable or disable Display Stream Compression on the peripheral using the
563 * default Picture Parameter Set and VESA DSC 1.1 algorithm.
564 *
565 * Return: 0 on success or a negative error code on failure.
566 */
mipi_dsi_compression_mode(struct mipi_dsi_device * dsi,bool enable)567 ssize_t mipi_dsi_compression_mode(struct mipi_dsi_device *dsi, bool enable)
568 {
569 /* Note: Needs updating for non-default PPS or algorithm */
570 u8 tx[2] = { enable << 0, 0 };
571 struct mipi_dsi_msg msg = {
572 .channel = dsi->channel,
573 .type = MIPI_DSI_COMPRESSION_MODE,
574 .tx_len = sizeof(tx),
575 .tx_buf = tx,
576 };
577 int ret = mipi_dsi_device_transfer(dsi, &msg);
578
579 return (ret < 0) ? ret : 0;
580 }
581 EXPORT_SYMBOL(mipi_dsi_compression_mode);
582
583 /**
584 * mipi_dsi_picture_parameter_set() - transmit the DSC PPS to the peripheral
585 * @dsi: DSI peripheral device
586 * @pps: VESA DSC 1.1 Picture Parameter Set
587 *
588 * Transmit the VESA DSC 1.1 Picture Parameter Set to the peripheral.
589 *
590 * Return: 0 on success or a negative error code on failure.
591 */
mipi_dsi_picture_parameter_set(struct mipi_dsi_device * dsi,const struct drm_dsc_picture_parameter_set * pps)592 ssize_t mipi_dsi_picture_parameter_set(struct mipi_dsi_device *dsi,
593 const struct drm_dsc_picture_parameter_set *pps)
594 {
595 struct mipi_dsi_msg msg = {
596 .channel = dsi->channel,
597 .type = MIPI_DSI_PICTURE_PARAMETER_SET,
598 .tx_len = sizeof(*pps),
599 .tx_buf = pps,
600 };
601 int ret = mipi_dsi_device_transfer(dsi, &msg);
602
603 return (ret < 0) ? ret : 0;
604 }
605 EXPORT_SYMBOL(mipi_dsi_picture_parameter_set);
606
607 /**
608 * mipi_dsi_generic_write() - transmit data using a generic write packet
609 * @dsi: DSI peripheral device
610 * @payload: buffer containing the payload
611 * @size: size of payload buffer
612 *
613 * This function will automatically choose the right data type depending on
614 * the payload length.
615 *
616 * Return: The number of bytes transmitted on success or a negative error code
617 * on failure.
618 */
mipi_dsi_generic_write(struct mipi_dsi_device * dsi,const void * payload,size_t size)619 ssize_t mipi_dsi_generic_write(struct mipi_dsi_device *dsi, const void *payload,
620 size_t size)
621 {
622 struct mipi_dsi_msg msg = {
623 .channel = dsi->channel,
624 .tx_buf = payload,
625 .tx_len = size
626 };
627
628 switch (size) {
629 case 0:
630 msg.type = MIPI_DSI_GENERIC_SHORT_WRITE_0_PARAM;
631 break;
632
633 case 1:
634 msg.type = MIPI_DSI_GENERIC_SHORT_WRITE_1_PARAM;
635 break;
636
637 case 2:
638 msg.type = MIPI_DSI_GENERIC_SHORT_WRITE_2_PARAM;
639 break;
640
641 default:
642 msg.type = MIPI_DSI_GENERIC_LONG_WRITE;
643 break;
644 }
645
646 return mipi_dsi_device_transfer(dsi, &msg);
647 }
648 EXPORT_SYMBOL(mipi_dsi_generic_write);
649
650 /**
651 * mipi_dsi_generic_read() - receive data using a generic read packet
652 * @dsi: DSI peripheral device
653 * @params: buffer containing the request parameters
654 * @num_params: number of request parameters
655 * @data: buffer in which to return the received data
656 * @size: size of receive buffer
657 *
658 * This function will automatically choose the right data type depending on
659 * the number of parameters passed in.
660 *
661 * Return: The number of bytes successfully read or a negative error code on
662 * failure.
663 */
mipi_dsi_generic_read(struct mipi_dsi_device * dsi,const void * params,size_t num_params,void * data,size_t size)664 ssize_t mipi_dsi_generic_read(struct mipi_dsi_device *dsi, const void *params,
665 size_t num_params, void *data, size_t size)
666 {
667 struct mipi_dsi_msg msg = {
668 .channel = dsi->channel,
669 .tx_len = num_params,
670 .tx_buf = params,
671 .rx_len = size,
672 .rx_buf = data
673 };
674
675 switch (num_params) {
676 case 0:
677 msg.type = MIPI_DSI_GENERIC_READ_REQUEST_0_PARAM;
678 break;
679
680 case 1:
681 msg.type = MIPI_DSI_GENERIC_READ_REQUEST_1_PARAM;
682 break;
683
684 case 2:
685 msg.type = MIPI_DSI_GENERIC_READ_REQUEST_2_PARAM;
686 break;
687
688 default:
689 return -EINVAL;
690 }
691
692 return mipi_dsi_device_transfer(dsi, &msg);
693 }
694 EXPORT_SYMBOL(mipi_dsi_generic_read);
695
696 /**
697 * mipi_dsi_dcs_write_buffer() - transmit a DCS command with payload
698 * @dsi: DSI peripheral device
699 * @data: buffer containing data to be transmitted
700 * @len: size of transmission buffer
701 *
702 * This function will automatically choose the right data type depending on
703 * the command payload length.
704 *
705 * Return: The number of bytes successfully transmitted or a negative error
706 * code on failure.
707 */
mipi_dsi_dcs_write_buffer(struct mipi_dsi_device * dsi,const void * data,size_t len)708 ssize_t mipi_dsi_dcs_write_buffer(struct mipi_dsi_device *dsi,
709 const void *data, size_t len)
710 {
711 struct mipi_dsi_msg msg = {
712 .channel = dsi->channel,
713 .tx_buf = data,
714 .tx_len = len
715 };
716
717 switch (len) {
718 case 0:
719 return -EINVAL;
720
721 case 1:
722 msg.type = MIPI_DSI_DCS_SHORT_WRITE;
723 break;
724
725 case 2:
726 msg.type = MIPI_DSI_DCS_SHORT_WRITE_PARAM;
727 break;
728
729 default:
730 msg.type = MIPI_DSI_DCS_LONG_WRITE;
731 break;
732 }
733
734 return mipi_dsi_device_transfer(dsi, &msg);
735 }
736 EXPORT_SYMBOL(mipi_dsi_dcs_write_buffer);
737
738 /**
739 * mipi_dsi_dcs_write() - send DCS write command
740 * @dsi: DSI peripheral device
741 * @cmd: DCS command
742 * @data: buffer containing the command payload
743 * @len: command payload length
744 *
745 * This function will automatically choose the right data type depending on
746 * the command payload length.
747 *
748 * Return: The number of bytes successfully transmitted or a negative error
749 * code on failure.
750 */
mipi_dsi_dcs_write(struct mipi_dsi_device * dsi,u8 cmd,const void * data,size_t len)751 ssize_t mipi_dsi_dcs_write(struct mipi_dsi_device *dsi, u8 cmd,
752 const void *data, size_t len)
753 {
754 ssize_t err;
755 size_t size;
756 u8 *tx;
757
758 if (len > 0) {
759 size = 1 + len;
760
761 tx = kmalloc(size, GFP_KERNEL);
762 if (!tx)
763 return -ENOMEM;
764
765 /* concatenate the DCS command byte and the payload */
766 tx[0] = cmd;
767 memcpy(&tx[1], data, len);
768 } else {
769 tx = &cmd;
770 size = 1;
771 }
772
773 err = mipi_dsi_dcs_write_buffer(dsi, tx, size);
774
775 if (len > 0)
776 kfree(tx);
777
778 return err;
779 }
780 EXPORT_SYMBOL(mipi_dsi_dcs_write);
781
782 /**
783 * mipi_dsi_dcs_read() - send DCS read request command
784 * @dsi: DSI peripheral device
785 * @cmd: DCS command
786 * @data: buffer in which to receive data
787 * @len: size of receive buffer
788 *
789 * Return: The number of bytes read or a negative error code on failure.
790 */
mipi_dsi_dcs_read(struct mipi_dsi_device * dsi,u8 cmd,void * data,size_t len)791 ssize_t mipi_dsi_dcs_read(struct mipi_dsi_device *dsi, u8 cmd, void *data,
792 size_t len)
793 {
794 struct mipi_dsi_msg msg = {
795 .channel = dsi->channel,
796 .type = MIPI_DSI_DCS_READ,
797 .tx_buf = &cmd,
798 .tx_len = 1,
799 .rx_buf = data,
800 .rx_len = len
801 };
802
803 return mipi_dsi_device_transfer(dsi, &msg);
804 }
805 EXPORT_SYMBOL(mipi_dsi_dcs_read);
806
807 /**
808 * mipi_dsi_dcs_nop() - send DCS nop packet
809 * @dsi: DSI peripheral device
810 *
811 * Return: 0 on success or a negative error code on failure.
812 */
mipi_dsi_dcs_nop(struct mipi_dsi_device * dsi)813 int mipi_dsi_dcs_nop(struct mipi_dsi_device *dsi)
814 {
815 ssize_t err;
816
817 err = mipi_dsi_dcs_write(dsi, MIPI_DCS_NOP, NULL, 0);
818 if (err < 0)
819 return err;
820
821 return 0;
822 }
823 EXPORT_SYMBOL(mipi_dsi_dcs_nop);
824
825 /**
826 * mipi_dsi_dcs_soft_reset() - perform a software reset of the display module
827 * @dsi: DSI peripheral device
828 *
829 * Return: 0 on success or a negative error code on failure.
830 */
mipi_dsi_dcs_soft_reset(struct mipi_dsi_device * dsi)831 int mipi_dsi_dcs_soft_reset(struct mipi_dsi_device *dsi)
832 {
833 ssize_t err;
834
835 err = mipi_dsi_dcs_write(dsi, MIPI_DCS_SOFT_RESET, NULL, 0);
836 if (err < 0)
837 return err;
838
839 return 0;
840 }
841 EXPORT_SYMBOL(mipi_dsi_dcs_soft_reset);
842
843 /**
844 * mipi_dsi_dcs_get_power_mode() - query the display module's current power
845 * mode
846 * @dsi: DSI peripheral device
847 * @mode: return location for the current power mode
848 *
849 * Return: 0 on success or a negative error code on failure.
850 */
mipi_dsi_dcs_get_power_mode(struct mipi_dsi_device * dsi,u8 * mode)851 int mipi_dsi_dcs_get_power_mode(struct mipi_dsi_device *dsi, u8 *mode)
852 {
853 ssize_t err;
854
855 err = mipi_dsi_dcs_read(dsi, MIPI_DCS_GET_POWER_MODE, mode,
856 sizeof(*mode));
857 if (err <= 0) {
858 if (err == 0)
859 err = -ENODATA;
860
861 return err;
862 }
863
864 return 0;
865 }
866 EXPORT_SYMBOL(mipi_dsi_dcs_get_power_mode);
867
868 /**
869 * mipi_dsi_dcs_get_pixel_format() - gets the pixel format for the RGB image
870 * data used by the interface
871 * @dsi: DSI peripheral device
872 * @format: return location for the pixel format
873 *
874 * Return: 0 on success or a negative error code on failure.
875 */
mipi_dsi_dcs_get_pixel_format(struct mipi_dsi_device * dsi,u8 * format)876 int mipi_dsi_dcs_get_pixel_format(struct mipi_dsi_device *dsi, u8 *format)
877 {
878 ssize_t err;
879
880 err = mipi_dsi_dcs_read(dsi, MIPI_DCS_GET_PIXEL_FORMAT, format,
881 sizeof(*format));
882 if (err <= 0) {
883 if (err == 0)
884 err = -ENODATA;
885
886 return err;
887 }
888
889 return 0;
890 }
891 EXPORT_SYMBOL(mipi_dsi_dcs_get_pixel_format);
892
893 /**
894 * mipi_dsi_dcs_enter_sleep_mode() - disable all unnecessary blocks inside the
895 * display module except interface communication
896 * @dsi: DSI peripheral device
897 *
898 * Return: 0 on success or a negative error code on failure.
899 */
mipi_dsi_dcs_enter_sleep_mode(struct mipi_dsi_device * dsi)900 int mipi_dsi_dcs_enter_sleep_mode(struct mipi_dsi_device *dsi)
901 {
902 ssize_t err;
903
904 err = mipi_dsi_dcs_write(dsi, MIPI_DCS_ENTER_SLEEP_MODE, NULL, 0);
905 if (err < 0)
906 return err;
907
908 return 0;
909 }
910 EXPORT_SYMBOL(mipi_dsi_dcs_enter_sleep_mode);
911
912 /**
913 * mipi_dsi_dcs_exit_sleep_mode() - enable all blocks inside the display
914 * module
915 * @dsi: DSI peripheral device
916 *
917 * Return: 0 on success or a negative error code on failure.
918 */
mipi_dsi_dcs_exit_sleep_mode(struct mipi_dsi_device * dsi)919 int mipi_dsi_dcs_exit_sleep_mode(struct mipi_dsi_device *dsi)
920 {
921 ssize_t err;
922
923 err = mipi_dsi_dcs_write(dsi, MIPI_DCS_EXIT_SLEEP_MODE, NULL, 0);
924 if (err < 0)
925 return err;
926
927 return 0;
928 }
929 EXPORT_SYMBOL(mipi_dsi_dcs_exit_sleep_mode);
930
931 /**
932 * mipi_dsi_dcs_set_display_off() - stop displaying the image data on the
933 * display device
934 * @dsi: DSI peripheral device
935 *
936 * Return: 0 on success or a negative error code on failure.
937 */
mipi_dsi_dcs_set_display_off(struct mipi_dsi_device * dsi)938 int mipi_dsi_dcs_set_display_off(struct mipi_dsi_device *dsi)
939 {
940 ssize_t err;
941
942 err = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_DISPLAY_OFF, NULL, 0);
943 if (err < 0)
944 return err;
945
946 return 0;
947 }
948 EXPORT_SYMBOL(mipi_dsi_dcs_set_display_off);
949
950 /**
951 * mipi_dsi_dcs_set_display_on() - start displaying the image data on the
952 * display device
953 * @dsi: DSI peripheral device
954 *
955 * Return: 0 on success or a negative error code on failure
956 */
mipi_dsi_dcs_set_display_on(struct mipi_dsi_device * dsi)957 int mipi_dsi_dcs_set_display_on(struct mipi_dsi_device *dsi)
958 {
959 ssize_t err;
960
961 err = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_DISPLAY_ON, NULL, 0);
962 if (err < 0)
963 return err;
964
965 return 0;
966 }
967 EXPORT_SYMBOL(mipi_dsi_dcs_set_display_on);
968
969 /**
970 * mipi_dsi_dcs_set_column_address() - define the column extent of the frame
971 * memory accessed by the host processor
972 * @dsi: DSI peripheral device
973 * @start: first column of frame memory
974 * @end: last column of frame memory
975 *
976 * Return: 0 on success or a negative error code on failure.
977 */
mipi_dsi_dcs_set_column_address(struct mipi_dsi_device * dsi,u16 start,u16 end)978 int mipi_dsi_dcs_set_column_address(struct mipi_dsi_device *dsi, u16 start,
979 u16 end)
980 {
981 u8 payload[4] = { start >> 8, start & 0xff, end >> 8, end & 0xff };
982 ssize_t err;
983
984 err = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_COLUMN_ADDRESS, payload,
985 sizeof(payload));
986 if (err < 0)
987 return err;
988
989 return 0;
990 }
991 EXPORT_SYMBOL(mipi_dsi_dcs_set_column_address);
992
993 /**
994 * mipi_dsi_dcs_set_page_address() - define the page extent of the frame
995 * memory accessed by the host processor
996 * @dsi: DSI peripheral device
997 * @start: first page of frame memory
998 * @end: last page of frame memory
999 *
1000 * Return: 0 on success or a negative error code on failure.
1001 */
mipi_dsi_dcs_set_page_address(struct mipi_dsi_device * dsi,u16 start,u16 end)1002 int mipi_dsi_dcs_set_page_address(struct mipi_dsi_device *dsi, u16 start,
1003 u16 end)
1004 {
1005 u8 payload[4] = { start >> 8, start & 0xff, end >> 8, end & 0xff };
1006 ssize_t err;
1007
1008 err = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_PAGE_ADDRESS, payload,
1009 sizeof(payload));
1010 if (err < 0)
1011 return err;
1012
1013 return 0;
1014 }
1015 EXPORT_SYMBOL(mipi_dsi_dcs_set_page_address);
1016
1017 /**
1018 * mipi_dsi_dcs_set_tear_off() - turn off the display module's Tearing Effect
1019 * output signal on the TE signal line
1020 * @dsi: DSI peripheral device
1021 *
1022 * Return: 0 on success or a negative error code on failure
1023 */
mipi_dsi_dcs_set_tear_off(struct mipi_dsi_device * dsi)1024 int mipi_dsi_dcs_set_tear_off(struct mipi_dsi_device *dsi)
1025 {
1026 ssize_t err;
1027
1028 err = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_TEAR_OFF, NULL, 0);
1029 if (err < 0)
1030 return err;
1031
1032 return 0;
1033 }
1034 EXPORT_SYMBOL(mipi_dsi_dcs_set_tear_off);
1035
1036 /**
1037 * mipi_dsi_dcs_set_tear_on() - turn on the display module's Tearing Effect
1038 * output signal on the TE signal line.
1039 * @dsi: DSI peripheral device
1040 * @mode: the Tearing Effect Output Line mode
1041 *
1042 * Return: 0 on success or a negative error code on failure
1043 */
mipi_dsi_dcs_set_tear_on(struct mipi_dsi_device * dsi,enum mipi_dsi_dcs_tear_mode mode)1044 int mipi_dsi_dcs_set_tear_on(struct mipi_dsi_device *dsi,
1045 enum mipi_dsi_dcs_tear_mode mode)
1046 {
1047 u8 value = mode;
1048 ssize_t err;
1049
1050 err = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_TEAR_ON, &value,
1051 sizeof(value));
1052 if (err < 0)
1053 return err;
1054
1055 return 0;
1056 }
1057 EXPORT_SYMBOL(mipi_dsi_dcs_set_tear_on);
1058
1059 /**
1060 * mipi_dsi_dcs_set_pixel_format() - sets the pixel format for the RGB image
1061 * data used by the interface
1062 * @dsi: DSI peripheral device
1063 * @format: pixel format
1064 *
1065 * Return: 0 on success or a negative error code on failure.
1066 */
mipi_dsi_dcs_set_pixel_format(struct mipi_dsi_device * dsi,u8 format)1067 int mipi_dsi_dcs_set_pixel_format(struct mipi_dsi_device *dsi, u8 format)
1068 {
1069 ssize_t err;
1070
1071 err = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_PIXEL_FORMAT, &format,
1072 sizeof(format));
1073 if (err < 0)
1074 return err;
1075
1076 return 0;
1077 }
1078 EXPORT_SYMBOL(mipi_dsi_dcs_set_pixel_format);
1079
1080 /**
1081 * mipi_dsi_dcs_set_tear_scanline() - set the scanline to use as trigger for
1082 * the Tearing Effect output signal of the display module
1083 * @dsi: DSI peripheral device
1084 * @scanline: scanline to use as trigger
1085 *
1086 * Return: 0 on success or a negative error code on failure
1087 */
mipi_dsi_dcs_set_tear_scanline(struct mipi_dsi_device * dsi,u16 scanline)1088 int mipi_dsi_dcs_set_tear_scanline(struct mipi_dsi_device *dsi, u16 scanline)
1089 {
1090 u8 payload[3] = { MIPI_DCS_SET_TEAR_SCANLINE, scanline >> 8,
1091 scanline & 0xff };
1092 ssize_t err;
1093
1094 err = mipi_dsi_generic_write(dsi, payload, sizeof(payload));
1095 if (err < 0)
1096 return err;
1097
1098 return 0;
1099 }
1100 EXPORT_SYMBOL(mipi_dsi_dcs_set_tear_scanline);
1101
1102 /**
1103 * mipi_dsi_dcs_set_display_brightness() - sets the brightness value of the
1104 * display
1105 * @dsi: DSI peripheral device
1106 * @brightness: brightness value
1107 *
1108 * Return: 0 on success or a negative error code on failure.
1109 */
mipi_dsi_dcs_set_display_brightness(struct mipi_dsi_device * dsi,u16 brightness)1110 int mipi_dsi_dcs_set_display_brightness(struct mipi_dsi_device *dsi,
1111 u16 brightness)
1112 {
1113 u8 payload[2] = { brightness & 0xff, brightness >> 8 };
1114 ssize_t err;
1115
1116 err = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_DISPLAY_BRIGHTNESS,
1117 payload, sizeof(payload));
1118 if (err < 0)
1119 return err;
1120
1121 return 0;
1122 }
1123 EXPORT_SYMBOL(mipi_dsi_dcs_set_display_brightness);
1124
1125 /**
1126 * mipi_dsi_dcs_get_display_brightness() - gets the current brightness value
1127 * of the display
1128 * @dsi: DSI peripheral device
1129 * @brightness: brightness value
1130 *
1131 * Return: 0 on success or a negative error code on failure.
1132 */
mipi_dsi_dcs_get_display_brightness(struct mipi_dsi_device * dsi,u16 * brightness)1133 int mipi_dsi_dcs_get_display_brightness(struct mipi_dsi_device *dsi,
1134 u16 *brightness)
1135 {
1136 ssize_t err;
1137
1138 err = mipi_dsi_dcs_read(dsi, MIPI_DCS_GET_DISPLAY_BRIGHTNESS,
1139 brightness, sizeof(*brightness));
1140 if (err <= 0) {
1141 if (err == 0)
1142 err = -ENODATA;
1143
1144 return err;
1145 }
1146
1147 return 0;
1148 }
1149 EXPORT_SYMBOL(mipi_dsi_dcs_get_display_brightness);
1150
mipi_dsi_drv_probe(struct device * dev)1151 static int mipi_dsi_drv_probe(struct device *dev)
1152 {
1153 struct mipi_dsi_driver *drv = to_mipi_dsi_driver(dev->driver);
1154 struct mipi_dsi_device *dsi = to_mipi_dsi_device(dev);
1155
1156 return drv->probe(dsi);
1157 }
1158
mipi_dsi_drv_remove(struct device * dev)1159 static int mipi_dsi_drv_remove(struct device *dev)
1160 {
1161 struct mipi_dsi_driver *drv = to_mipi_dsi_driver(dev->driver);
1162 struct mipi_dsi_device *dsi = to_mipi_dsi_device(dev);
1163
1164 return drv->remove(dsi);
1165 }
1166
mipi_dsi_drv_shutdown(struct device * dev)1167 static void mipi_dsi_drv_shutdown(struct device *dev)
1168 {
1169 struct mipi_dsi_driver *drv = to_mipi_dsi_driver(dev->driver);
1170 struct mipi_dsi_device *dsi = to_mipi_dsi_device(dev);
1171
1172 drv->shutdown(dsi);
1173 }
1174
1175 /**
1176 * mipi_dsi_driver_register_full() - register a driver for DSI devices
1177 * @drv: DSI driver structure
1178 * @owner: owner module
1179 *
1180 * Return: 0 on success or a negative error code on failure.
1181 */
mipi_dsi_driver_register_full(struct mipi_dsi_driver * drv,struct module * owner)1182 int mipi_dsi_driver_register_full(struct mipi_dsi_driver *drv,
1183 struct module *owner)
1184 {
1185 drv->driver.bus = &mipi_dsi_bus_type;
1186 drv->driver.owner = owner;
1187
1188 if (drv->probe)
1189 drv->driver.probe = mipi_dsi_drv_probe;
1190 if (drv->remove)
1191 drv->driver.remove = mipi_dsi_drv_remove;
1192 if (drv->shutdown)
1193 drv->driver.shutdown = mipi_dsi_drv_shutdown;
1194
1195 return driver_register(&drv->driver);
1196 }
1197 EXPORT_SYMBOL(mipi_dsi_driver_register_full);
1198
1199 /**
1200 * mipi_dsi_driver_unregister() - unregister a driver for DSI devices
1201 * @drv: DSI driver structure
1202 *
1203 * Return: 0 on success or a negative error code on failure.
1204 */
mipi_dsi_driver_unregister(struct mipi_dsi_driver * drv)1205 void mipi_dsi_driver_unregister(struct mipi_dsi_driver *drv)
1206 {
1207 driver_unregister(&drv->driver);
1208 }
1209 EXPORT_SYMBOL(mipi_dsi_driver_unregister);
1210
mipi_dsi_bus_init(void)1211 static int __init mipi_dsi_bus_init(void)
1212 {
1213 return bus_register(&mipi_dsi_bus_type);
1214 }
1215 postcore_initcall(mipi_dsi_bus_init);
1216
1217 MODULE_AUTHOR("Andrzej Hajda <a.hajda@samsung.com>");
1218 MODULE_DESCRIPTION("MIPI DSI Bus");
1219 MODULE_LICENSE("GPL and additional rights");
1220