Moto Mods Firmware: Display Protocol

Overview

The Display protocol provides an abstract interface for controlling one additional real-time display device streaming video data using either MIPI DSI or Mobility DisplayPort (MyDP).

The Display protocol interface concerns itself with the 'control' path of a display device.  The actual video data-stream, or 'data' path, is out-of-band and not included in this interface.  

  • The interface provides a number of functions:
  • Query and choose the configuration
  • Register for and receive display events
  • Query and set the current display state (e.g. on or off)

For DSI panels connected to the APBE using the Mods High-Speed Bridge (MHB) there is a default implementation, mhb_dsi_display, that implements the device-level interface and requires only a few helper functions to provide panel-specific configuration and commands.  The DSI display interface should be used for low-power mobile display functionality.

For DisplayPort devices, the implementation simply advertises the EDID configuration and sends display notification events.  The DisplayPort interface itself handles the rest.  The DisplayPort display interface should be used for DRM protected content and can support up to 4k30 resolution.


Files

Generic Files

nuttx/include/nuttx/device_display.h

This file defines the device_display_type_ops structure and provides a number of wrapper functions to safely call the operations in the structure.

DSI-specific Files

./nuttx/include/nuttx/mhb/mhb_dsi_display.h

This file defines the function prototypes of the DSI panel-specific functions that you need to implement for a DSI panel.

./nuttx/include/nuttx/mhb/mhb_protocol.h

This file defines the structures used in your implementation of the DSI panel-specific functions.

./nuttx/drivers/mhb/mhb_dsi_display.c

This file implements the Display class interface for a generic DSI panel connected to the APBE using the Mods High-Speed Bridge (MHB). It requires a number of panel-specific functions to be implemented and linked in.

DSI-specific Example Files

./nuttx/drivers/display/smd_470_720p.c
./nuttx/drivers/display/tdi_546_1080p.c

These files implement the panel-specific functions for a pair of example panels. For your specific panel, add nuttx/drivers/display/<NEW_PANEL>.c and update nuttx/drivers/display/Kconfig and nuttx/drivers/display/Make.defs.

./nuttx/configs/hdk/muc/src/stm32_boot.c

This file provides an example Display class registration including the necessary device resources. This file provides the starting point for your development. It should be copied into nuttx/configs/<NEW_PROJECT>/src for your specific Project and modified.

DisplayPort-specific Example Files

./nuttx/drivers/hdmi_display.c

This file is a 'skeleton' implementation of a DisplayPort driver that can be used to start your own DisplayPort device implementation.

Generic Example Files

./nuttx/drivers/null_display.c

The file is a blank 'skeleton' driver that can be used to start your own implementation.


Details

Display Notification Events

The Greybus display class driver is the client of the Display device driver. It automatically registers and unregisters a callback function for display notification events. Your implementation must support exactly one registration. It must also send the appropriate display notification events when appropriate.

Below are the definitions for display notification events, the callback function, and the register and unregister functions.

Host Ready

This operation is used by the client to notify implementations that it is ready to receive display notification events. This operation must be received before the your implementation can send any display notification events.

int (*host_ready)(struct device *dev);

Display Notification Events

enum display_notification_event {
    DISPLAY_NOTIFICATION_EVENT_INVALID     = 0x00,
    DISPLAY_NOTIFICATION_EVENT_FAILURE     = 0x01,
    DISPLAY_NOTIFICATION_EVENT_AVAILABLE   = 0x02,
    DISPLAY_NOTIFICATION_EVENT_UNAVAILABLE = 0x03,
    DISPLAY_NOTIFICATION_EVENT_CONNECT     = 0x04,
    DISPLAY_NOTIFICATION_EVENT_DISCONNECT  = 0x05,
};

The display notification events are defined as follows:

  • DISPLAY_NOTIFICATION_EVENT_INVALID: A reserved value, do not use.
  • DISPLAY_NOTIFICATION_EVENT_FAILURE: Send this event if the display device has encountered a catastrophic failure that it cannot recover from.
  • DISPLAY_NOTIFICATION_EVENT_AVAILABLE: Send this event when the display device software is available for operations from the phone. This is typically sent in response to the host_ready() call. The phone will not send operations before this event is received.
  • DISPLAY_NOTIFICATION_EVENT_UNAVAILABLE: Send this event if the display device software is no longer available to receive operations from the phone. The phone will not send operations after this event is received.
  • DISPLAY_NOTIFICATION_EVENT_CONNECT: Send this event when the display device hardware is ready to be used (e.g. turned on). For devices that are always connected (e.g. a DSI panel), this event can be sent immediately after the AVAILABLE event. For devices that are intermittently connected (e.g. an HDMI port), this event can be sent after an external device is plugged in.
  • DISPLAY_NOTIFICATION_EVENT_DISCONNECT: Send this event when the display device hardware is no longer ready to be used. For devices that are intermittently connected (e.g. an HDMI port), this event can be sent after an external device is unplugged. For other devices, this event is not typically used.

Display Notification Callback

typedef int (*display_notification_cb)(struct device *dev,
    enum display_notification_event event);

The callback function receives a pointer to the device and the display notification event. Clients handle these events as they see fit and return an errno. Your implementation should ignore the errno.

Register Callback

int (*register_callback)(struct device *dev, display_notification_cb cb);

This operation is used by clients to register a callback handler for display notification events. Your implementation must support at exactly one callback.

Callers pass a pointer to the device and a pointer to the callback function.

If a callback is not already registered, your implementation saves the callback function and returns success. If a callback is already registered, then return an errno.

Unregister Callback

int (*unregister_callback)(struct device *dev);

This operation is used by clients to unregister a previously registered callback handler for display notification events. It is an error to unregister a callback function if one was not previously registered.

Callers pass a pointer to the device.

If a callback is not already registered, your implementation clears the callback function and returns success. If a callback was not already registered, then return an errno.

Configuration

Below are the configuration operations. Your driver must implement these operations and be prepared to handle them any time after sending a DISPLAY_NOTIFICATION_EVENT_AVAILALBE event and before sending a DISPLAY_NOTIFICATION_EVENT_UNAVAILALBE event.

Display Type

enum display_type {
    DISPLAY_TYPE_INVALID = 0x00,
    DISPLAY_TYPE_DSI     = 0x01,
    DISPLAY_TYPE_DP      = 0x02,
};

The display type describes the physical display interface:

  • DISPLAY_TYPE_INVALID: Reserved, do not use.
  • DISPLAY_TYPE_DSI: The Display device uses DSI.
  • DISPLAY_TYPE_DP: The Display device uses DisplayPort

Display Config Type

enum display_config_type {
    DISPLAY_CONFIG_TYPE_INVALID  = 0x00,
    DISPLAY_CONFIG_TYPE_EDID_1P3 = 0x01,
    DISPLAY_CONFIG_TYPE_DSI      = 0x02,
};

The display config type describes the binary format of the config data returned by get_config().

  • DISPLAY_CONFIG_TYPE_INVALID: Reserved, do not use.
  • DISPLAY_CONFIG_TYPE_EDID_1P3: An EDID binary block as defined by VESA EDID version 1.3.
  • DISPLAY_CONFIG_TYPE_DSI: A custom DSI-specific structure described in detail below.

DisplayPort implementations must use the EDID v1.3 format while DSI implementations must use the DSI format.

Get Config Size

int (*get_config_size)(struct device *dev, uint32_t *size);

This operation requests the size, in bytes, of the configuration data that would be returned by a subsequent get_config operation.

Callers pass a pointer to the device and a pointer to a variable to hold the size.

Your implementation fills in the size and returns an appropriate errno value.

Get Config

int (*get_config)(struct device *dev, uint8_t *display_type,
        uint8_t *config_type, uint32_t *size, uint8_t **config);

This operation requests the configuration or configurations supported by the display device.

Callers pass a pointer to the device and a pointers to a variable to the display type, display config type, config size, and config data.

Your implementation fills in the display type, config type, size, and config data and returns an appropriate errno value. If a config of size 0 is returned with an errno of 0, then the client will attempt to read the display configuration from another source (e.g. directly over DisplayPort). The exact format of the configuration data is discussed in more detail below.

Set Config

int (*set_config)(struct device *dev, uint8_t index);

The EDID v1.3 format has the ability to specify more than one supported configuration. If this is the case, clients may want to select a configuration other than the default. The set_config operation allows clients to select, by zero-based index, the desired configuration.

Callers pass a pointer to the device and the zero-based index of the desired configuration.

Your implementation verifies the index and, if valid selects, the configuration. Otherwise, returns an errno. All implementations must support at least one configuration (index of 0) even if they return an zero-length config data.

Configuration Data

For DSI Display devices, the config data is formatted as a custom binary structure. Some of these fields may not be important to the DSI panel itself, but are necessary for the phone.

DSI Mode

enum display_config_dsi_mode {
    DISPLAY_CONFIG_DSI_MODE_VIDEO   = 0x00,
    DISPLAY_CONFIG_DSI_MODE_COMMAND = 0x01,
};

Selects DSI Command or Video Mode.

DSI Swap

enum display_config_dsi_swap {
    DISPLAY_CONFIG_DSI_SWAP_RGB_TO_RGB = 0x00,
    DISPLAY_CONFIG_DSI_SWAP_RGB_TO_RBG = 0x01,
    DISPLAY_CONFIG_DSI_SWAP_RGB_TO_BGR = 0x02,
    DISPLAY_CONFIG_DSI_SWAP_RGB_TO_BRG = 0x03,
    DISPLAY_CONFIG_DSI_SWAP_RGB_TO_GRB = 0x04,
    DISPLAY_CONFIG_DSI_SWAP_RGB_TO_GBR = 0x05,
};

Selects the pixel color swapping. The default is no swapping (DISPLAY_CONFIG_DSI_SWAP_RGB_TO_RGB).

Continuous Clock

enum display_config_dsi_continuous_clock {
    DISPLAY_CONFIG_DSI_CONTINUOUS_CLOCK_DISABLED = 0x00,
    DISPLAY_CONFIG_DSI_CONTINUOUS_CLOCK_ENABLED  = 0x01,
};

Selects if the DSI clock pair should be run continuously or just during transfers.

EOT Mode

enum display_config_dsi_eot_mode {
    DISPLAY_CONFIG_DSI_EOT_MODE_NONE   = 0x00,
    DISPLAY_CONFIG_DSI_EOT_MODE_APPEND = 0x01,
};

Selects if EOT should be append during DSI transmission.

VSync Mode

enum display_config_dsi_vsync_mode {
    DISPLAY_CONFIG_DSI_VSYNC_MODE_NONE = 0x00,
    DISPLAY_CONFIG_DSI_VSYNC_MODE_GPIO = 0x01,
    DISPLAY_CONFIG_DSI_VSYNC_MODE_DCS  = 0x02,
};

Selects the vertical sync (vsync) mode:

  • DISPLAY_CONFIG_DSI_VSYNC_MODE_NONE: No vsync
  • DISPLAY_CONFIG_DSI_VSYNC_MODE_GPIO: Use GPIO for vsync
  • DISPLAY_CONFIG_DSI_VSYNC_MODE_DCS: Use a DCS command for vsync

DSI Traffic Mode

enum display_config_dsi_traffic_mode {
    DISPLAY_CONFIG_DSI_TRAFFIC_MODE_NON_BURST_SYNC_PULSE = 0x00,
    DISPLAY_CONFIG_DSI_TRAFFIC_MODE_NON_BURST_SYNC_EVENT = 0x01,
    DISPLAY_CONFIG_DSI_TRAFFIC_MODE_BURST                = 0x02,
};

Selects the DSI traffic mode.

Selects the vertical sync (vsync) mode:

  • DISPLAY_CONFIG_DSI_TRAFFIC_MODE_NON_BURST_SYNC_PULSE: Sync pulse
  • DISPLAY_CONFIG_DSI_TRAFFIC_MODE_NON_BURST_SYNC_EVENT: Sync event
  • DISPLAY_CONFIG_DSI_TRAFFIC_MODE_BURST: Burst

DSI Pixel Packing

enum display_config_dsi_pixel_packing {
    DISPLAY_CONFIG_DSI_PIXEL_PACKING_UNPACKED = 0x00,
};

Selects the pixel packing mode. Only unpacked is currently supported.

DSI Config

struct display_dsi_config {
    /* MIPI manufacturer ID (http://mid.mipi.org) */
    uint16_t manufacturer_id;
    /* display_config_dsi_mode */
    uint8_t mode;
    /* 1-4 lanes */
    uint8_t num_lanes;

    /* pixels */
    uint16_t width;
    /* pixels */
    uint16_t height;

    /* millimeters */
    uint16_t physical_width_dim;
    /* millimeters */
    uint16_t physical_length_dim;

    /* frames-per-second */
    uint8_t framerate;
    /* bits-per-pixel */
    uint8_t bpp;
    /* must be zero */
    uint16_t reserved0;

    /* Hz */
    uint64_t clockrate;

    /* nanoseconds */
    uint16_t t_clk_pre;
    /* nanoseconds */
    uint16_t t_clk_post;

    /* display_config_dsi_continuous_clock */
    uint8_t continuous_clock;
    /* display_config_dsi_eot_mode */
    uint8_t eot_mode;
    /* display_config_dsi_vsync_mode */
    uint8_t vsync_mode;
    /* display_config_dsi_traffic_mode */
    uint8_t traffic_mode;

    /* DSI virtual channel (VC) ID */
    uint8_t virtual_channel_id;
    /* display_config_dsi_swap */
    uint8_t color_order;
    /* display_config_dsi_pixel_packing* */
    uint8_t pixel_packing;
    /* must be zero */
    uint8_t reserved1;

    /* pixels */
    uint16_t horizontal_front_porch;
    uint16_t horizontal_sync_pulse_width;
    uint16_t horizontal_sync_skew;
    uint16_t horizontal_back_porch;
    uint16_t horizontal_left_border;
    uint16_t horizontal_right_border;

    /* lines */
    uint16_t vertical_front_porch;
    uint16_t vertical_sync_pulse_width;
    uint16_t vertical_back_porch;
    uint16_t vertical_top_border;
    uint16_t vertical_bottom_border;
    uint16_t reserved2;
};

The DSI config structure includes all of the necessary parameters for configuring both RX and TX DSI interfaces on the phone, APBA, and APBE.

DSI Config
DSI Interface
  • mode: Video or command DSI mode (display_config_dsi_mode).
  • num_lanes: Number of DSI lanes. Only 1 through 4 are supported.
Format
  • width: Display width in pixels.
  • height: Display height in pixels.
  • physical_width_dim: Display width in millimeters.
  • physical_length_dim: Display height in millimeters.
  • framerate: Display frame rate in frames-per-second.
  • bpp: Bits per pixel (e.g. 24-bits, 8-bits for red, green, and blue).
Timing
  • clockrate: Desired clock-rate in Hz. This rate is not guaranteed. It may need to be adjusted based on specific hardware.
  • t_clk_pre: T_CLK_PRE in nanoseconds.
  • t_clk_post: T_CLK_POST in nanoseconds.
Options
  • continuous_clock: Clock mode (display_config_dsi_continuous_clock)
  • eot_mode: EOT mode: (display_config_dsi_eot_mode)
  • vsync_mode: Vsync mode (display_config_dsi_vsync_mode)
  • traffic_mode: Traffic mode (display_config_dsi_traffic_mode)
  • virtual_channel_id: DSI virtual channel (VC) ID
  • color_order: Color order (display_config_dsi_swap)
  • pixel_packing: Pixel packing mode (display_config_dsi_pixel_packing)
Horizontal

All vertical parameters are measured in pixels.

  • horizontal_front_porch
  • horizontal_sync_pulse_width
  • horizontal_sync_skew
  • horizontal_back_porch
  • horizontal_left_border
  • horizontal_right_border
Vertical

All vertical parameters are measured in lines.

  • vertical_front_porch
  • vertical_sync_pulse_width
  • vertical_back_porch
  • vertical_top_border
  • vertical_bottom_border
Reserved
  • reserved0: Reserved, must be zero.
  • reserved1: Reserved, must be zero.
  • reserved2: Reserved, must be zero.

State

Display State

enum display_state {
    DISPLAY_STATE_OFF = 0x00,
    DISPLAY_STATE_ON  = 0x01,
};

The display state describes whether the Display device is on or off.

  • DISPLAY_STATE_OFF: Off
  • DISPLAY_STATE_ON: On

Get State

int (*get_state)(struct device *dev, uint8_t *state);

This operation requests the current state of the Display device.

Callers pass a pointer to the device and a pointer to a variable to the state.

Your implementation fills in the current state and returns an appropriate errno value.

Set State

int (*set_state)(struct device *dev, uint8_t state);

This operation sets the current state of the Display device.

Callers pass a pointer to the device and a the new state.

Your implementation changes state (if appropriate) and returns an appropriate errno value.


Motorola High-Speed Bridge DSI Display

Introduction

Instead of writing a Display device driver, many DSI panels can make use of the generic MHB DSI Display driver. In these cases, your code just needs to implement the three panel-specific functions to configure the MHB DSI Display driver.

The steps are:

  • Enable the CONFIG_MHB_DSI_DISPLAY configuration in your target's defconfig.
  • Copy the example driver at ./nuttx/drivers/display/tdi_546_1080p.c into your own file.
  • Add config entries in ./nuttx/drivers/display/Kconfig
  • Add your new config to your target's defconfig.
  • Add makefile entries in ./nuttx/drivers/display/Make.defs.
  • Implement the functions in your target .c file.

Details

MHB DSI Config

struct mhb_cdsi_config {
    /* Common */
    uint8_t direction; /* RX: 0 (CDSI -> UniPro), TX: 1 (UniPro -> CDSI) */
    uint8_t mode;                    /* DSI: 0, CSI: 1 */
    uint8_t rx_num_lanes;            /* 1 to 4 */
    uint8_t tx_num_lanes;            /* 1 to 4 */
    uint32_t rx_bits_per_lane;       /* bits-per-lane */
    uint32_t tx_bits_per_lane;       /* bits-per-lane */
    /* RX only */
    uint32_t hs_rx_timeout;
    /* TX only */
    uint32_t pll_frs;
    uint32_t pll_prd;
    uint32_t pll_fbd;
    uint32_t framerate;              /* frames-per-second */
    uint32_t width;                  /* pixels */
    uint32_t height;                 /* pixels */
    uint32_t physical_width;         /* millimeters */
    uint32_t physical_height;        /* millimeters */
    uint32_t bpp;                    /* bits-per-pixel */
    uint32_t vss_control_payload;
    uint8_t bta_enabled;             /* 0: disabled, 1: enabled */
    uint8_t continuous_clock;        /* 0: off, 1: on */
    uint8_t blank_packet_enabled;
    uint8_t video_mode;              /* 0: video, 1: command */
    uint8_t color_bar_enabled;       /* 0: disabled */
    uint8_t keep_alive;              /* 0: disabled */
    uint8_t t_clk_pre;               /* nanoseconds */
    uint8_t t_clk_post;              /* nanoseconds */
    /* CSI only */
    /* DSI only */
    uint8_t horizontal_front_porch;  /* pixels */
    uint8_t horizontal_back_porch;   /* pixels */
    uint8_t horizontal_pulse_width;  /* pixels */
    uint8_t horizontal_sync_skew;    /* pixels */
    uint8_t horizontal_left_border;  /* pixels */
    uint8_t horizontal_right_border; /* pixels */
    uint8_t vertical_front_porch;    /* lines */
    uint8_t vertical_back_porch;     /* lines */
    uint8_t vertical_pulse_width;    /* lines */
    uint8_t vertical_top_border;     /* lines */
    uint8_t vertical_bottom_border;  /* lines */
    uint8_t vsync_mode;              /* 0: none, 1: gpio, 2: dcs */
} __attribute__((packed));

The MHB DSI Display driver uses a DSI config structure similar to that of the Display device interface. However, there are a few additional fields that are needed specifically for the APBE implementation.

The additional fields include:

  • pll_frs: PLL FRS
  • pll_prd: PLL PRD
  • pll_fbd: PLL FBD

You can set these values to override the default PLL settings used to configure the APBE to achieve the corresponding bits-per-lane. See the Appendix for a table of valid PLL settings.

DSI Panel Info

struct mhb_dsi_panel_info {
    uint16_t supplier_id;
    uint8_t id0; /* optional */
    uint8_t id1; /* optional */
    uint8_t id2; /* optional */
} __attribute__((packed));

The DSI panel information structure includes the MIPI supplier ID and optionally up to three additional identifiers.

These values correspond to the respective DCS read results of:

  • read_DDB_start (0xa1)
  • 0xda
  • 0xdb
  • 0xdc

C-Types

/* DSI and DCS */
#define MHB_CTYPE_HS_FLAG    (0x0)
#define MHB_CTYPE_LP_FLAG    (0x8)
#define MHB_CTYPE_SHORT_FLAG (0x0)
#define MHB_CTYPE_LONG_FLAG  (0x4)

#define MHB_CTYPE_HS_SHORT (MHB_CTYPE_HS_FLAG|MHB_CTYPE_SHORT_FLAG)
#define MHB_CTYPE_HS_LONG  (MHB_CTYPE_HS_FLAG|MHB_CTYPE_LONG_FLAG)
#define MHB_CTYPE_LP_SHORT (MHB_CTYPE_LP_FLAG|MHB_CTYPE_SHORT_FLAG)
#define MHB_CTYPE_LP_LONG  (MHB_CTYPE_LP_FLAG|MHB_CTYPE_LONG_FLAG)

These are the definitions for the C-Types. These correspond directly to the MIPI D-Phy specification.

D-Types

/* Data Types for Processor-sourced Packets */
#define MHB_DTYPE_GEN_SHORT_WRITE0 0x03
#define MHB_DTYPE_GEN_SHORT_WRITE1 0x13
#define MHB_DTYPE_GEN_SHORT_WRITE2 0x23
#define MHB_DTYPE_GEN_READ0        0x04
#define MHB_DTYPE_GEN_READ1        0x14
#define MHB_DTYPE_GEN_READ2        0x24
#define MHB_DTYPE_DCS_WRITE0       0x05
#define MHB_DTYPE_DCS_WRITE1       0x15
#define MHB_DTYPE_DCS_READ0        0x06
#define MHB_DTYPE_MAX_RET_PKT      0x37
#define MHB_DTYPE_GEN_LONG_WRITE   0x29
#define MHB_DTYPE_DCS_LONG_WRITE   0x39

These are the definitions for the D-Types. These correspond directly to the MIPI D-Phy and DCS specifications.

DSI Command

struct mhb_cdsi_cmd {
    uint8_t ctype;  /* MHB_CTYPE_* */
    uint8_t dtype;  /* MHB_DTYPE_* */
    uint16_t length;
    uint32_t delay; /* minimum microseconds to wait after command */
    union {
        uint16_t spdata;
        uint32_t lpdata[2];
    } u;
} __attribute__((packed));

This structure is used to specify a single DCS command to be written either during the panel on or off sequence.

Specify the appropriate C-Types and D-Types from the MHB_CTYPE_* and MHB_DTYPE_* definitions. Set the length of the data for both short and long packets.

Optionally set a delay, in microseconds, to wait after this command is written.

Set the data field depending on the packet type. For short packets, use spdata and for long packets, use lpdata. Data must be stored in the least-significant bytes.

Short Packet Example
{ .ctype = MHB_CTYPE_LP_SHORT, .dtype = MHB_DTYPE_DCS_WRITE0, .length = 2, .u = { .spdata = 0x0011 }, .delay = 120000 }, /* exit_sleep_mode */

This sends a command with the following details:

  • A short packet.
  • A DCS write with 0 additional parameters, one parameter is automatically included.
  • The automatic parameter is 0x11 which is the exit sleep mode command.
  • The length of the data is 2 bytes (one byte for the D-Type and one byte for the parameter).
  • Wait 120 milliseconds after sending.
Long Packet Example

{ .ctype = MHB_CTYPE_LP_LONG, .dtype = MHB_DTYPE_DCS_LONG_WRITE, .length = 5, .u = { .lpdata = { 0x0002cf2a, 0x00000000 } }, .delay = 0 }, / set_column_address /

This sends a command with the following details:

  • A long packet.
  • A DCS long write.
  • The data is 0x2a 0xcf 0x02 0x00 0x00. The 0x2a is the set_column_address command, 0xcf 0x02 0x00 0x00 byte-reversed is 0x000002cf which corresponds to 719. This is the max column for a 720p panel. Note that only the least-significant byte of lpdata[1] is used. The other bytes are ignored.
  • The length is 5 bytes (one byte for the command and four bytes for the value).
  • Do not wait after sending.

Get Config

int _mhb_dsi_display_get_config(uint8_t instance,
    const struct mhb_dsi_panel_info *panel_info,
    const struct mhb_cdsi_config **cfg,
    size_t *size);

This function is used to specify the panel-specific configuration.

Callers pass a pointer to the panel info (if available) and pointers to variables to receive the configuration and configuration size.

Your implementation fills in the configuration and the size, in bytes, of the configuration. Your implementation may use the panel information to choose the appropriate configuration. However, the panel information may not always be available.

Get On-Commands

int _mhb_dsi_display_get_on_commands(uint8_t instance,
    const struct mhb_dsi_panel_info *panel_info,
    const struct mhb_cdsi_cmd **cmds,
    size_t *size);

This function is used to specify the panel-specific DCS commands to send before a panel is turned on.

Callers pass a pointer to the panel info (if available) and pointers to variables to receive the commands and command size.

Your implementation fills in the array of commands and the size, in bytes, of the array of commands. Your implementation may use the panel information to choose the appropriate commands. However, the panel information may not always be available.

Get Off-Commands

int _mhb_dsi_display_get_off_commands(uint8_t instance,
    const struct mhb_dsi_panel_info *panel_info,
    const struct mhb_cdsi_cmd **cmds,
    size_t *size);

This function is used to specify the panel-specific DCS commands to send before a panel is turned off.

Callers pass a pointer to the panel info (if available) and pointers to variables to receive the commands and command size.

Your implementation fills in the array of commands and the size, in bytes, of the array of commands. Your implementation may use the panel information to choose the appropriate commands. However, the panel information may not always be available.


Greybus Manifest

The Greybus Manifest requires at least two entries for a Display class:

  • The Display class
  • A Bundle

If your Display device requires additional hardware to function, include those device classes in the same bundle. If your Display device has optional hardware that is useful, but not required to function, you may want to include it in its own bundle.

Simple Display

[cport-descriptor 2]
bundle = 2
protocol = 0xee        ; Display-Ext

[bundle-descriptor 2]
class = 0x0c           ; Display (bundle)

Display and Backlight

[cport-descriptor 2]
bundle = 2
protocol = 0xee        ; Display-Ext

[cport-descriptor 3]
bundle = 2
protocol = 0x0f        ; Lights

[bundle-descriptor 2]
class = 0x0c           ; Display (bundle)

Display, Backlight, and Buttons

[cport-descriptor 2]
bundle = 2
protocol = 0xee        ; Display-Ext

[cport-descriptor 3]
bundle = 2
protocol = 0x0f        ; Lights

[bundle-descriptor 2]
class = 0x0c           ; Display (bundle)

[cport-descriptor 5]
bundle = 3
protocol = 0x05        ; HID

[bundle-descriptor 3]
class = 0x05           ; HID (bundle)

Appendix: PLL Script

The following is a Python 3 script to determine the appropriate PLL settings. It accepts the desired Mbps/lane as the argument.

#!/usr/bin/env python3
import sys

def measure(hz, pll_frs, pll_prd, pll_fbd):
    pll_vco = 2.0 * 19.2 * (float(pll_fbd) + 1.0) / (float(pll_prd) + 1.0)
    pll_vco_valid = (pll_vco > 1000.0 and pll_vco < 2000.0)

    hsck = pll_vco / (2.0 ** (float(pll_frs) + 1.0))
    hsck_valid = (hsck > 80.0 and hsck < 1000.0)

    valid = pll_vco_valid and hsck_valid
    if not valid:
        return

    delta = abs(hz - hsck)
    error = delta / hz * 100

    return (hz, hsck, delta, error, pll_frs, pll_prd, pll_fbd, pll_vco)

def find_valid(hz, pll_frs_width=2, pll_prd_width=4, pll_fbd_width=7, num_results=5):
    results = []

    for pll_frs in range(0, 2**pll_frs_width):
        for pll_prd in range(0, 2**pll_prd_width):
            for pll_fbd in range(0, 2**pll_fbd_width):
                result = measure(hz, pll_frs, pll_prd, pll_fbd)
                if result:
                    results.append(result)

    return sorted(results, key=lambda r: r[2])

def display_results(results):
    fmt = '{:^12}{:^12}{:^12}{:^7}{:^9}{:^9}{:^9}'
    print(fmt.format('Target', 'Actual', 'delta', 'error', 'pll_frs', 'pll_prd', 'pll_fbd'))
    print(fmt.format('(Mbps/lane)', '(Mbps/lane)', '(Mbps/lane)', '(%)', '', '', ''))
    print('-' * 70)

    for result in results:
        print('{:^12}{:^12.1f}{:^12.1f}{:^7.2}{:^9}{:^9}{:^9}'.format(*result))

    print()

if __name__ == '__main__':

    for arg in sys.argv[1:]:
        results = find_valid(hz=float(arg))
        display_results(results[0:5])

A sample session for an input of 807 Mbps/lane are as follows:

$ ./pll.py 807
   Target      Actual      delta     error  pll_frs  pll_prd  pll_fbd 
(Mbps/lane) (Mbps/lane) (Mbps/lane)   (%)                              
----------------------------------------------------------------------
    807        806.4        0.6      0.074     0        0       41    
    807        806.4        0.6      0.074     0        1       83    
    807        806.4        0.6      0.074     0        2       125   
    807        812.8        5.8      0.72      0        2       126   
    807        800.0        7.0      0.87      0        2       124

The results from the script show the top five valid combinations of PLL settings that achieve an actual 806.4 Mbps/lanel. Any one of the top three results has an error of 0.074%.


Appendix: PLL Table

Frequency(MHz) PLL_FRS PLL_PRD PLL_FBD
80-813166
80-8132100
81-823033
81-823167
81-8232101
82-833168
82-8332102
83-8432103
843034
843169
8432104
84-8532105
85-863170
85-8632106
86-873035
86-873171
86-8732107
87-883172
87-8832108
8832109
88-893036
88-893173
88-8932110
89-9032111
903174
90-9132112
91-923037
91-923175
91-9232113
9232114
92-933176
92-9332115
93-943038
93-943177
93-9432116
94-953178
94-9532117
95-9632118
963039
963179
9632119
96-9732120
97-983180
97-9832121
98-993040
98-993181
98-9932122
99-1003182
99-10032123
10032124
100-1013041
100-1013183
100-10132125
101-10232126
1023184
102-10332127
103-1043042
103-1043185
104-1053186
105-1063043
105-1063187
106-1073188
1083044
1083189
109-1103190
110-1113045
110-1113191
111-1123192
112-1133046
112-1133193
1143194
115-1163047
115-1163195
116-1173196
117-1183048
117-1183197
118-1193198
1203049
1203199
121-12231100
122-1233050
122-12331101
123-12431102
124-1253051
124-12531103
12623104
126-1272278
127-1282152
127-12823105
1282279
128-12923106
129-1302026
129-1302153
129-1302280
129-13023107
130-13123108
131-1322281
1322154
13223109
132-1332282
133-13423110
134-1352027
134-1352155
134-1352283
134-13523111
135-13623112
1362284
136-1372156
136-13723113
137-1382285
13823114
139-1402028
139-1402157
139-1402286
139-14023115
140-1412287
140-14123116
141-1422158
141-14223117
142-1432288
142-14323118
1442029
1442159
1442289
14423119
145-1462290
145-14623120
146-1472160
146-14723121
147-1482291
147-14823122
148-1492030
148-1492161
148-1492292
148-14923123
15023124
150-1512293
151-1522162
151-15223125
1522294
152-15323126
153-1542031
153-1542163
153-1542295
153-15423127
155-1562296
1562164
156-1572297
158-1592032
158-1592165
158-1592298
1602299
160-1612166
161-16222100
163-1642033
163-1642167
163-16422101
164-16522102
165-1662168
166-16722103
1682034
1682169
16822104
169-17022105
170-1712170
171-17222106
172-1732035
172-1732171
172-17322107
174-17522108
175-1762172
17622109
177-1782036
177-1782173
177-17822110
179-18022111
1802174
180-18122112
182-1832037
182-1832175
182-18322113
18422114
184-1852176
185-18622115
187-1882038
187-1882177
187-18822116
188-18922117
189-1902178
190-19122118
1922039
1922179
19222119
193-19422120
194-1952180
195-19622121
196-1972040
196-1972181
196-19722122
198-19922123
199-2002182
20022124
201-2022041
201-2022183
201-20222125
203-20422126
2042184
204-20522127
206-2072042
206-2072185
208-2092186
211-2122043
211-2122187
213-2142188
2162044
2162189
218-2192190
220-2212045
220-2212191
223-2242192
225-2262046
225-2262193
2282194
230-2312047
230-2312195
232-2332196
235-2362048
235-2362197
237-2382198
2402049
2402199
242-24321100
244-2452050
244-24521101
247-24821102
249-2502051
249-25021103
25213104
252-2531278
254-2551152
254-25513105
2561279
256-25713106
259-2601026
259-2601153
259-2601280
259-26013107
261-26213108
262-2631281
2641154
26413109
265-2661282
266-26713110
268-2691027
268-2691155
268-2691283
268-26913111
271-27213112
2721284
273-2741156
273-27413113
275-2761285
27613114
278-2791028
278-2791157
278-2791286
278-27913115
280-28113116
281-2821287
283-2841158
283-28413117
284-2851288
285-28613118
2881029
2881159
2881289
28813119
290-29113120
291-2921290
292-2931160
292-29313121
294-2951291
295-29613122
297-2981030
297-2981161
297-2981292
297-29813123
30013124
300-3011293
302-3031162
302-30313125
3041294
304-30513126
307-3081031
307-3081163
307-3081295
307-30813127
310-3111296
3121164
313-3141297
316-3171032
316-3171165
316-3171298
3201299
321-3221166
323-32412100
326-3271033
326-3271167
326-32712101
329-33012102
331-3321168
332-33312103
3361034
3361169
33612104
339-34012105
340-3411170
342-34312106
345-3461035
345-3461171
345-34612107
348-34912108
350-3511172
35212109
355-3561036
355-3561173
355-35612110
358-35912111
3601174
361-36212112
364-3651037
364-3651175
364-36512113
36812114
369-3701176
371-37212115
374-3751038
374-3751177
374-37512116
377-37812117
379-3801178
380-38112118
3841039
3841179
38412119
387-38812120
388-3891180
390-39112121
393-3941040
393-3941181
393-39412122
396-39712123
398-3991182
40012124
403-4041041
403-4041183
403-40412125
406-40712126
4081184
409-41012127
412-4131042
412-4131185
417-4181186
422-4231043
422-4231187
427-4281188
4321044
4321189
436-4371190
441-4421045
441-4421191
446-4471192
451-4521046
451-4521193
4561194
460-4611047
460-4611195
465-4661196
470-4711048
470-4711197
475-4761198
4801049
4801199
484-48511100
489-4901050
489-49011101
494-49511102
499-5001051
499-50011103
50403104
505-5060278
508-5090152
508-50903105
5120279
513-51403106
518-5190026
518-5190153
518-5190280
518-51903107
523-52403108
524-5250281
5280154
52803109
531-5320282
532-53303110
537-5380027
537-5380155
537-5380283
537-53803111
542-54303112
5440284
547-5480156
547-54803113
550-5510285
55203114
556-5570028
556-5570157
556-5570286
556-55703115
561-56203116
563-5640287
566-5670158
566-56703117
569-5700288
571-57203118
5760029
5760159
5760289
57603119
580-58103120
582-5830290
585-5860160
585-58603121
588-5890291
590-59103122
595-5960030
595-5960161
595-5960292
595-59603123
60003124
601-6020293
604-6050162
604-60503125
6080294
609-61003126
614-6150031
614-6150163
614-6150295
614-61503127
620-6210296
6240164
627-6280297
633-6340032
633-6340165
633-6340298
6400299
643-6440166
646-64702100
652-6530033
652-6530167
652-65302101
659-66002102
662-6630168
665-66602103
6720034
6720169
67202104
678-67902105
681-6820170
684-68502106
691-6920035
691-6920171
691-69202107
697-69802108
700-7010172
70402109
710-7110036
710-7110173
710-71102110
716-71702111
7200174
723-72402112
729-7300037
729-7300175
729-73002113
73602114
739-7400176
742-74302115
748-7490038
748-7490177
748-74902116
755-75602117
758-7590178
761-76202118
7680039
7680179
76802119
774-77502120
777-7780180
780-78102121
787-7880040
787-7880181
787-78802122
793-79402123
796-7970182
80002124
806-8070041
806-8070183
806-80702125
812-81302126
8160184
819-82002127
825-8260042
825-8260185
835-8360186
844-8450043
844-8450187
854-8550188
8640044
8640189
873-8740190
883-8840045
883-8840191
892-8930192
902-9030046
902-9030193
9120194
921-9220047
921-9220195
931-9320196
940-9410048
940-9410197
950-9510198
9600049
9600199
969-97001100
979-9800050
979-98001101
988-98901102
998-9990051
998-99901103