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