Display Protocol

Overview

The Display protocol provides an abstract interface for controlling one additional real-time display device streaming video data using 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 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.

​​​​​​./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 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-2


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_configoperation.
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.

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-81 3 1 66
80-81 3 2 100
81-82 3 0 33
81-82 3 1 67
81-82 3 2 101
82-83 3 1 68
82-83 3 2 102
83-84 3 2 103
84 3 0 34
84 3 1 69
84 3 2 104
84-85 3 2 105
85-86 3 1 70
85-86 3 2 106
86-87 3 0 35
86-87 3 1 71
86-87 3 2 107
87-88 3 1 72
87-88 3 2 108
88 3 2 109
88-89 3 0 36
88-89 3 1 73
88-89 3 2 110
89-90 3 2 111
90 3 1 74
90-91 3 2 112
91-92 3 0 37
91-92 3 1 75
91-92 3 2 113
92 3 2 114
92-93 3 1 76
92-93 3 2 115
93-94 3 0 38
93-94 3 1 77
93-94 3 2 116
94-95 3 1 78
94-95 3 2 117
95-96 3 2 118
96 3 0 39
96 3 1 79
96 3 2 119
96-97 3 2 120
97-98 3 1 80
97-98 3 2 121
98-99 3 0 40
98-99 3 1 81
98-99 3 2 122
99-100 3 1 82
99-100 3 2 123
100 3 2 124
100-101 3 0 41
100-101 3 1 83
100-101 3 2 125
101-102 3 2 126
102 3 1 84
102-103 3 2 127
103-104 3 0 42
103-104 3 1 85
104-105 3 1 86
105-106 3 0 43
105-106 3 1 87
106-107 3 1 88
108 3 0 44
108 3 1 89
109-110 3 1 90
110-111 3 0 45
110-111 3 1 91
111-112 3 1 92
112-113 3 0 46
112-113 3 1 93
114 3 1 94
115-116 3 0 47
115-116 3 1 95
116-117 3 1 96
117-118 3 0 48
117-118 3 1 97
118-119 3 1 98
120 3 0 49
120 3 1 99
121-122 3 1 100
122-123 3 0 50
122-123 3 1 101
123-124 3 1 102
124-125 3 0 51
124-125 3 1 103
126 2 3 104
126-127 2 2 78
127-128 2 1 52
127-128 2 3 105
128 2 2 79
128-129 2 3 106
129-130 2 0 26
129-130 2 1 53
129-130 2 2 80
129-130 2 3 107
130-131 2 3 108
131-132 2 2 81
132 2 1 54
132 2 3 109
132-133 2 2 82
133-134 2 3 110
134-135 2 0 27
134-135 2 1 55
134-135 2 2 83
134-135 2 3 111
135-136 2 3 112
136 2 2 84
136-137 2 1 56
136-137 2 3 113
137-138 2 2 85
138 2 3 114
139-140 2 0 28
139-140 2 1 57
139-140 2 2 86
139-140 2 3 115
140-141 2 2 87
140-141 2 3 116
141-142 2 1 58
141-142 2 3 117
142-143 2 2 88
142-143 2 3 118
144 2 0 29
144 2 1 59
144 2 2 89
144 2 3 119
145-146 2 2 90
145-146 2 3 120
146-147 2 1 60
146-147 2 3 121
147-148 2 2 91
147-148 2 3 122
148-149 2 0 30
148-149 2 1 61
148-149 2 2 92
148-149 2 3 123
150 2 3 124
150-151 2 2 93
151-152 2 1 62
151-152 2 3 125
152 2 2 94
152-153 2 3 126
153-154 2 0 31
153-154 2 1 63
153-154 2 2 95
153-154 2 3 127
155-156 2 2 96
156 2 1 64
156-157 2 2 97
158-159 2 0 32
158-159 2 1 65
158-159 2 2 98
160 2 2 99
160-161 2 1 66
161-162 2 2 100
163-164 2 0 33
163-164 2 1 67
163-164 2 2 101
164-165 2 2 102
165-166 2 1 68
166-167 2 2 103
168 2 0 34
168 2 1 69
168 2 2 104
169-170 2 2 105
170-171 2 1 70
171-172 2 2 106
172-173 2 0 35
172-173 2 1 71
172-173 2 2 107
174-175 2 2 108
175-176 2 1 72
176 2 2 109
177-178 2 0 36
177-178 2 1 73
177-178 2 2 110
179-180 2 2 111
180 2 1 74
180-181 2 2 112
182-183 2 0 37
182-183 2 1 75
182-183 2 2 113
184 2 2 114
184-185 2 1 76
185-186 2 2 115
187-188 2 0 38
187-188 2 1 77
187-188 2 2 116
188-189 2 2 117
189-190 2 1 78
190-191 2 2 118
192 2 0 39
192 2 1 79
192 2 2 119
193-194 2 2 120
194-195 2 1 80
195-196 2 2 121
196-197 2 0 40
196-197 2 1 81
196-197 2 2 122
198-199 2 2 123
199-200 2 1 82
200 2 2 124
201-202 2 0 41
201-202 2 1 83
201-202 2 2 125
203-204 2 2 126
204 2 1 84
204-205 2 2 127
206-207 2 0 42
206-207 2 1 85
208-209 2 1 86
211-212 2 0 43
211-212 2 1 87
213-214 2 1 88
216 2 0 44
216 2 1 89
218-219 2 1 90
220-221 2 0 45
220-221 2 1 91
223-224 2 1 92
225-226 2 0 46
225-226 2 1 93
228 2 1 94
230-231 2 0 47
230-231 2 1 95
232-233 2 1 96
235-236 2 0 48
235-236 2 1 97
237-238 2 1 98
240 2 0 49
240 2 1 99
242-243 2 1 100
244-245 2 0 50
244-245 2 1 101
247-248 2 1 102
249-250 2 0 51
249-250 2 1 103
252 1 3 104
252-253 1 2 78
254-255 1 1 52
254-255 1 3 105
256 1 2 79
256-257 1 3 106
259-260 1 0 26
259-260 1 1 53
259-260 1 2 80
259-260 1 3 107
261-262 1 3 108
262-263 1 2 81
264 1 1 54
264 1 3 109
265-266 1 2 82
266-267 1 3 110
268-269 1 0 27
268-269 1 1 55
268-269 1 2 83
268-269 1 3 111
271-272 1 3 112
272 1 2 84
273-274 1 1 56
273-274 1 3 113
275-276 1 2 85
276 1 3 114
278-279 1 0 28
278-279 1 1 57
278-279 1 2 86
278-279 1 3 115
280-281 1 3 116
281-282 1 2 87
283-284 1 1 58
283-284 1 3 117
284-285 1 2 88
285-286 1 3 118
288 1 0 29
288 1 1 59
288 1 2 89
288 1 3 119
290-291 1 3 120
291-292 1 2 90
292-293 1 1 60
292-293 1 3 121
294-295 1 2 91
295-296 1 3 122
297-298 1 0 30
297-298 1 1 61
297-298 1 2 92
297-298 1 3 123
300 1 3 124
300-301 1 2 93
302-303 1 1 62
302-303 1 3 125
304 1 2 94
304-305 1 3 126
307-308 1 0 31
307-308 1 1 63
307-308 1 2 95
307-308 1 3 127
310-311 1 2 96
312 1 1 64
313-314 1 2 97
316-317 1 0 32
316-317 1 1 65
316-317 1 2 98
320 1 2 99
321-322 1 1 66
323-324 1 2 100
326-327 1 0 33
326-327 1 1 67
326-327 1 2 101
329-330 1 2 102
331-332 1 1 68
332-333 1 2 103
336 1 0 34
336 1 1 69
336 1 2 104
339-340 1 2 105
340-341 1 1 70
342-343 1 2 106
345-346 1 0 35
345-346 1 1 71
345-346 1 2 107
348-349 1 2 108
350-351 1 1 72
352 1 2 109
355-356 1 0 36
355-356 1 1 73
355-356 1 2 110
358-359 1 2 111
360 1 1 74
361-362 1 2 112
364-365 1 0 37
364-365 1 1 75
364-365 1 2 113
368 1 2 114
369-370 1 1 76
371-372 1 2 115
374-375 1 0 38
374-375 1 1 77
374-375 1 2 116
377-378 1 2 117
379-380 1 1 78
380-381 1 2 118
384 1 0 39
384 1 1 79
384 1 2 119
387-388 1 2 120
388-389 1 1 80
390-391 1 2 121
393-394 1 0 40
393-394 1 1 81
393-394 1 2 122
396-397 1 2 123
398-399 1 1 82
400 1 2 124
403-404 1 0 41
403-404 1 1 83
403-404 1 2 125
406-407 1 2 126
408 1 1 84
409-410 1 2 127
412-413 1 0 42
412-413 1 1 85
417-418 1 1 86
422-423 1 0 43
422-423 1 1 87
427-428 1 1 88
432 1 0 44
432 1 1 89
436-437 1 1 90
441-442 1 0 45
441-442 1 1 91
446-447 1 1 92
451-452 1 0 46
451-452 1 1 93
456 1 1 94
460-461 1 0 47
460-461 1 1 95
465-466 1 1 96
470-471 1 0 48
470-471 1 1 97
475-476 1 1 98
480 1 0 49
480 1 1 99
484-485 1 1 100
489-490 1 0 50
489-490 1 1 101
494-495 1 1 102
499-500 1 0 51
499-500 1 1 103
504 0 3 104
505-506 0 2 78
508-509 0 1 52
508-509 0 3 105
512 0 2 79
513-514 0 3 106
518-519 0 0 26
518-519 0 1 53
518-519 0 2 80
518-519 0 3 107
523-524 0 3 108
524-525 0 2 81
528 0 1 54
528 0 3 109
531-532 0 2 82
532-533 0 3 110
537-538 0 0 27
537-538 0 1 55
537-538 0 2 83
537-538 0 3 111
542-543 0 3 112
544 0 2 84
547-548 0 1 56
547-548 0 3 113
550-551 0 2 85
552 0 3 114
556-557 0 0 28
556-557 0 1 57
556-557 0 2 86
556-557 0 3 115
561-562 0 3 116
563-564 0 2 87
566-567 0 1 58
566-567 0 3 117
569-570 0 2 88
571-572 0 3 118
576 0 0 29
576 0 1 59
576 0 2 89
576 0 3 119
580-581 0 3 120
582-583 0 2 90
585-586 0 1 60
585-586 0 3 121
588-589 0 2 91
590-591 0 3 122
595-596 0 0 30
595-596 0 1 61
595-596 0 2 92
595-596 0 3 123
600 0 3 124
601-602 0 2 93
604-605 0 1 62
604-605 0 3 125
608 0 2 94
609-610 0 3 126
614-615 0 0 31
614-615 0 1 63
614-615 0 2 95
614-615 0 3 127
620-621 0 2 96
624 0 1 64
627-628 0 2 97
633-634 0 0 32
633-634 0 1 65
633-634 0 2 98
640 0 2 99
643-644 0 1 66
646-647 0 2 100
652-653 0 0 33
652-653 0 1 67
652-653 0 2 101
659-660 0 2 102
662-663 0 1 68
665-666 0 2 103
672 0 0 34
672 0 1 69
672 0 2 104
678-679 0 2 105
681-682 0 1 70
684-685 0 2 106
691-692 0 0 35
691-692 0 1 71
691-692 0 2 107
697-698 0 2 108
700-701 0 1 72
704 0 2 109
710-711 0 0 36
710-711 0 1 73
710-711 0 2 110
716-717 0 2 111
720 0 1 74
723-724 0 2 112
729-730 0 0 37
729-730 0 1 75
729-730 0 2 113
736 0 2 114
739-740 0 1 76
742-743 0 2 115
748-749 0 0 38
748-749 0 1 77
748-749 0 2 116
755-756 0 2 117
758-759 0 1 78
761-762 0 2 118
768 0 0 39
768 0 1 79
768 0 2 119
774-775 0 2 120
777-778 0 1 80
780-781 0 2 121
787-788 0 0 40
787-788 0 1 81
787-788 0 2 122
793-794 0 2 123
796-797 0 1 82
800 0 2 124
806-807 0 0 41
806-807 0 1 83
806-807 0 2 125
812-813 0 2 126
816 0 1 84
819-820 0 2 127
825-826 0 0 42
825-826 0 1 85
835-836 0 1 86
844-845 0 0 43
844-845 0 1 87
854-855 0 1 88
864 0 0 44
864 0 1 89
873-874 0 1 90
883-884 0 0 45
883-884 0 1 91
892-893 0 1 92
902-903 0 0 46
902-903 0 1 93
912 0 1 94
921-922 0 0 47
921-922 0 1 95
931-932 0 1 96
940-941 0 0 48
940-941 0 1 97
950-951 0 1 98
960 0 0 49
960 0 1 99
969-970 0 1 100
979-980 0 0 50
979-980 0 1 101
988-989 0 1 102
998-999 0 0 51
998-999 0 1 103