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