diff --git a/drivers/ra/CMakeLists.txt b/drivers/ra/CMakeLists.txt index 3a2bd87..5116887 100644 --- a/drivers/ra/CMakeLists.txt +++ b/drivers/ra/CMakeLists.txt @@ -61,6 +61,9 @@ zephyr_library_sources_ifdef(CONFIG_USE_RA_FSP_SDRAM fsp/src/bsp/mcu/all/bsp_sdram.c) zephyr_library_sources_ifdef(CONFIG_USE_RA_FSP_DISPLAY fsp/src/r_glcdc/r_glcdc.c) +zephyr_library_sources_ifdef(CONFIG_USE_RA_FSP_MIPI_DSI + fsp/src/r_mipi_dsi/r_mipi_dsi.c + fsp/src/r_mipi_phy/r_mipi_phy.c) if(CONFIG_USE_RA_FSP_SCE) zephyr_include_directories( diff --git a/drivers/ra/fsp/inc/api/r_mipi_dsi_api.h b/drivers/ra/fsp/inc/api/r_mipi_dsi_api.h new file mode 100644 index 0000000..6875916 --- /dev/null +++ b/drivers/ra/fsp/inc/api/r_mipi_dsi_api.h @@ -0,0 +1,541 @@ +/* +* Copyright (c) 2020 - 2024 Renesas Electronics Corporation and/or its affiliates +* +* SPDX-License-Identifier: BSD-3-Clause +*/ + +/*******************************************************************************************************************//** + * @ingroup RENESAS_GRAPHICS_INTERFACES + * @defgroup MIPI_DSI_API MIPI DSI Interface + * @brief Interface for MIPI DSI communications. + * + * @section MIPI_DSI_API_SUMMARY Summary + * The MIPI DSI interface provides functionality involved with driving display panels over MIPI. + * + * @{ + **********************************************************************************************************************/ + +#ifndef R_MIPI_DSI_API_H +#define R_MIPI_DSI_API_H + +/*********************************************************************************************************************** + * Includes + **********************************************************************************************************************/ + +/* Includes board and MCU related header files. */ +#include "bsp_api.h" +#include "r_mipi_dsi_cfg.h" + +#include "r_mipi_phy.h" + +/* Common macro for FSP header files. There is also a corresponding FSP_FOOTER macro at the end of this file. */ +FSP_HEADER + +/********************************************************************************************************************** + * Macro definitions + **********************************************************************************************************************/ + +/********************************************************************************************************************** + * Typedef definitions + **********************************************************************************************************************/ + +/** MIPI DSI packet Data Type (commands) - See MIPI specification for additional information */ +typedef enum e_mipi_dsi_cmd_id +{ + MIPI_DSI_CMD_ID_V_SYNC_START = 0x01, ///< (Short) Sync Event, V Sync Start + MIPI_DSI_CMD_ID_V_SYNC_END = 0x11, ///< (Short) Sync Event, V Sync End + MIPI_DSI_CMD_ID_H_SYNC_START = 0x21, ///< (Short) Sync Event, H Sync Start + MIPI_DSI_CMD_ID_H_SYNC_END = 0x31, ///< (Short) Sync Event, H Sync End + + MIPI_DSI_CMD_ID_COMPRESSION_MODE = 0x07, ///< (Short) Compression Mode Command + MIPI_DSI_CMD_ID_END_OF_TRANSMISSION = 0x08, ///< (Short) End of Transmission packet (EoTp) + + MIPI_DSI_CMD_ID_COLOR_MODE_OFF = 0x02, ///< (Short) Color Mode (CM) Off Command + MIPI_DSI_CMD_ID_COLOR_MODE_ON = 0x12, ///< (Short) Color Mode (CM) On Command + MIPI_DSI_CMD_ID_SHUTDOWN_PERIPHERAL = 0x22, ///< (Short) Shut Down Peripheral Command + MIPI_DSI_CMD_ID_TURN_ON_PERIPHERAL = 0x32, ///< (Short) Turn On Peripheral Command + + MIPI_DSI_CMD_ID_GENERIC_SHORT_WRITE_0_PARAM = 0x03, ///< (Short) Generic Short WRITE, no parameters + MIPI_DSI_CMD_ID_GENERIC_SHORT_WRITE_1_PARAM = 0x13, ///< (Short) Generic Short WRITE, 1 parameter + MIPI_DSI_CMD_ID_GENERIC_SHORT_WRITE_2_PARAM = 0x23, ///< (Short) Generic Short WRITE, 2 parameters + + MIPI_DSI_CMD_ID_GENERIC_READ_REQUEST_0_PARAM = 0x04, ///< (Short) Generic READ, no parameters + MIPI_DSI_CMD_ID_GENERIC_READ_REQUEST_1_PARAM = 0x14, ///< (Short) Generic READ, 1 parameter + MIPI_DSI_CMD_ID_GENERIC_READ_REQUEST_2_PARAM = 0x24, ///< (Short) Generic READ, 2 parameters + + MIPI_DSI_CMD_ID_DCS_SHORT_WRITE_0_PARAM = 0x05, ///< (Short) DCS Short WRITE, no parameters + MIPI_DSI_CMD_ID_DCS_SHORT_WRITE_1_PARAM = 0x15, ///< (Short) DCS Short WRITE, 1 parameter + + MIPI_DSI_CMD_ID_DCS_READ = 0x06, ///< (Short) DCS READ, no parameters + MIPI_DSI_CMD_ID_EXECUTE_QUEUE = 0x16, ///< (Short) Execute Queue + + MIPI_DSI_CMD_ID_SET_MAXIMUM_RETURN_PACKET_SIZE = 0x37, ///< (Short) Set Maximum Return Packet Size + + MIPI_DSI_CMD_ID_NULL_PACKET = 0x09, ///< (Long) Null Packet, no data + MIPI_DSI_CMD_ID_BLANKING_PACKET = 0x19, ///< (Long) Blanking Packet, no data + MIPI_DSI_CMD_ID_GENERIC_LONG_WRITE = 0x29, ///< (Long) Generic Long Write + MIPI_DSI_CMD_ID_DCS_LONG_WRITE = 0x39, ///< (Long) DCS Long Write/write_LUT Command Packet + + MIPI_DSI_CMD_ID_PICTURE_PARAMETER_SET = 0x0A, ///< (Long) Picture Parameter Set + MIPI_DSI_CMD_ID_COMPRESSED_PIXEL_STREAM = 0x0B, ///< (Long) Compressed Pixel Stream + + MIPI_DSI_CMD_ID_LOOSELY_PACKED_PIXEL_STREAM_YCBCR20 = 0x0C, ///< (Long) Loosely Packed Pixel Stream, 20-bit YCbCr, 4:2:2 Format + MIPI_DSI_CMD_ID_PACKED_PIXEL_STREAM_YCBCR24 = 0x1C, ///< (Long) Packed Pixel Stream, 24-bit YCbCr, 4:2:2 Format + MIPI_DSI_CMD_ID_PACKED_PIXEL_STREAM_YCBCR16 = 0x2C, ///< (Long) Packed Pixel Stream, 16-bit YCbCr, 4:2:2 Format + + MIPI_DSI_CMD_ID_PACKED_PIXEL_STREAM_30 = 0x0D, ///< (Long) Packed Pixel Stream, 30-bit RGB, 10-10-10 Format + MIPI_DSI_CMD_ID_PACKED_PIXEL_STREAM_36 = 0x1D, ///< (Long) Packed Pixel Stream, 36-bit RGB, 12-12-12 Format + MIPI_DSI_CMD_ID_PACKED_PIXEL_STREAM_YCBCR12 = 0x3D, ///< (Long) Packed Pixel Stream, 12-bit YCbCr, 4:2:0 Format + + MIPI_DSI_CMD_ID_PACKED_PIXEL_STREAM_16 = 0x0E, ///< (Long) Packed Pixel Stream, 16-bit RGB, 5-6-5 Format + MIPI_DSI_CMD_ID_PACKED_PIXEL_STREAM_18 = 0x1E, ///< (Long) Packed Pixel Stream, 18-bit RGB, 6-6-6 Format + MIPI_DSI_CMD_ID_LOOSELY_PACKED_PIXEL_STREAM_18 = 0x2E, ///< (Long) Loosely Packed Pixel Stream, 18-bit RGB, 6-6-6 Format + MIPI_DSI_CMD_ID_PACKED_PIXEL_STREAM_24 = 0x3E, ///< (Long) Packed Pixel Stream, 24-bit RGB, 8-8-8 Format +} mipi_dsi_cmd_id_t; + +/** MIPI DCS ID types - See MIPI DCS specification for additional information */ +typedef enum e_mipi_dsi_dcs_id +{ + MIPI_DSI_DCS_ID_ENTER_IDLE_MODE = 0x39, ///< Enter idle mode + MIPI_DSI_DCS_ID_ENTER_INVERT_MODE = 0x21, ///< Displayed image colors inverted + MIPI_DSI_DCS_ID_ENTER_NORMAL_MODE = 0x13, ///< Whole display area used for image + MIPI_DSI_DCS_ID_ENTER_PARTIAL_MODE = 0x12, ///< Part of display area used for image + MIPI_DSI_DCS_ID_ENTER_SLEEP_MODE = 0x10, ///< Power off the display panel + MIPI_DSI_DCS_ID_EXIT_IDLE_MODE = 0x38, ///< Full color depth used + MIPI_DSI_DCS_ID_EXIT_INVERT_MODE = 0x20, ///< Displayed image colors not inverted + MIPI_DSI_DCS_ID_EXIT_SLEEP_MODE = 0x11, ///< Power on the display panel + MIPI_DSI_DCS_ID_GET_3D_CONTROL = 0x3F, ///< Get display module 3D mode + MIPI_DSI_DCS_ID_GET_ADDRESS_MODE = 0x0B, ///< Get data order for transfers from host to the display device + MIPI_DSI_DCS_ID_GET_BLUE_CHANNEL = 0x08, ///< Get blue component of pixel at 0,0 + MIPI_DSI_DCS_ID_GET_CABC_MIN_BRIGHTNESS = 0x5F, ///< Get current minimum brightness level of the active CABC mode + MIPI_DSI_DCS_ID_GET_COMPRESSION_MODE = 0x03, ///< Get current compression mode + MIPI_DSI_DCS_ID_GET_CONTROL_DISPLAY = 0x54, ///< Get control display mode + MIPI_DSI_DCS_ID_GET_DIAGNOSTIC_RESULT = 0x0F, ///< Get peripheral self-diagnostic result + MIPI_DSI_DCS_ID_GET_DISPLAY_BRIGHTNESS = 0x52, ///< Get current display brightness level + MIPI_DSI_DCS_ID_GET_DISPLAY_MODE = 0x0D, ///< Get current display mode from the peripheral + MIPI_DSI_DCS_ID_GET_DSI_MODE = 0x70, ///< Get DSI operation mode + MIPI_DSI_DCS_ID_GET_ERROR_COUNT_ON_DSI = 0x05, ///< Get number of corrupted packets on DSI + MIPI_DSI_DCS_ID_GET_GREEN_CHANNEL = 0x07, ///< Get green component of pixel at 0,0 + MIPI_DSI_DCS_ID_GET_IMAGE_CHECKSUM_CT = 0x15, ///< Returns checksum of frame of color-transformed pixel data + MIPI_DSI_DCS_ID_GET_IMAGE_CHECKSUM_RGB = 0x14, ///< Returns checksum of frame of RGB pixel data + MIPI_DSI_DCS_ID_GET_PIXEL_FORMAT = 0x0C, ///< Get current pixel format + MIPI_DSI_DCS_ID_GET_POWER_MODE = 0x0A, ///< Get current power mode + MIPI_DSI_DCS_ID_GET_POWER_SAVE = 0x56, ///< Get current power-save mode + MIPI_DSI_DCS_ID_GET_RED_CHANNEL = 0x06, ///< Get red component of pixel at 0,0 + MIPI_DSI_DCS_ID_GET_SCANLINE = 0x45, ///< Get current scanline + MIPI_DSI_DCS_ID_GET_SIGNAL_MODE = 0x0E, ///< Get display module signaling mode + MIPI_DSI_DCS_ID_NOP = 0x00, ///< No operation + MIPI_DSI_DCS_ID_READ_ACMD = 0x62, ///< Perform read access to the ACMD registers + MIPI_DSI_DCS_ID_READ_DDB_CONTINUE = 0xA8, ///< Continue reading the DDB from the last read location + MIPI_DSI_DCS_ID_READ_DDB_START = 0xA1, ///< Read the DDB from the provided location + MIPI_DSI_DCS_ID_READ_DSE_MAILBOX = 0x57, ///< Read access to the registers of the DSE read or write control mailbox + MIPI_DSI_DCS_ID_READ_MEMORY_CONTINUE = 0x3E, ///< Read image data from peripheral, continuing after last read + MIPI_DSI_DCS_ID_READ_MEMORY_START = 0x2E, ///< Read image data from the peripheral to the host + MIPI_DSI_DCS_ID_READ_PPS_CONTINUE = 0xA9, ///< Continue reading the specified length of PPS data + MIPI_DSI_DCS_ID_READ_PPS_START = 0xA2, ///< Read PPS data + MIPI_DSI_DCS_ID_SET_3D_CONTROL = 0x3D, ///< 3D is used on the display panel + MIPI_DSI_DCS_ID_SET_ADDRESS_MODE = 0x36, ///< Set data order for transfers from host to peripheral + MIPI_DSI_DCS_ID_SET_ARP_OFF = 0x60, ///< Disable ARP + MIPI_DSI_DCS_ID_SET_ARP_ON = 0x61, ///< Enable ARP and set T2 timer + MIPI_DSI_DCS_ID_SET_CABC_MIN_BRIGHTNESS = 0x5E, ///< Set minimum brightness level for CABC mode + MIPI_DSI_DCS_ID_SET_COLUMN_ADDRESS = 0x2A, ///< Set column extent + MIPI_DSI_DCS_ID_SET_DISPLAY_BRIGHTNESS = 0x51, ///< Set display brightness level + MIPI_DSI_DCS_ID_SET_DISPLAY_OFF = 0x28, ///< Blank the display device + MIPI_DSI_DCS_ID_SET_DISPLAY_ON = 0x29, ///< Show image on display device + MIPI_DSI_DCS_ID_SET_DSI_MODE = 0x71, ///< Set DSI operation mode + MIPI_DSI_DCS_ID_SET_GAMMA_CURVE = 0x26, ///< Select gamma curve used by display + MIPI_DSI_DCS_ID_SET_PAGE_ADDRESS = 0x2B, ///< Set page extent + MIPI_DSI_DCS_ID_SET_PARTIAL_COLUMNS = 0x31, ///< Define the number of columns in the partial display area + MIPI_DSI_DCS_ID_SET_PARTIAL_ROWS = 0x30, ///< Define the number of rows in the partial display area + MIPI_DSI_DCS_ID_SET_PIXEL_FORMAT = 0x3A, ///< Define how many bits per pixel are used + MIPI_DSI_DCS_ID_SET_SCROLL_AREA = 0x33, ///< Define vertical scrolling and fixed area + MIPI_DSI_DCS_ID_SET_SCROLL_START = 0x37, ///< Define vertical scrolling starting point + MIPI_DSI_DCS_ID_SET_TEAR_OFF = 0x34, ///< Sync information not sent from the display module to the host + MIPI_DSI_DCS_ID_SET_TEAR_ON = 0x35, ///< Sync information is sent from the display module to the host + MIPI_DSI_DCS_ID_SET_TEAR_SCANLINE = 0x44, ///< Sync information is sent from display to the host when display refresh reaches profivided scan line + MIPI_DSI_DCS_ID_SET_VSYNC_TIMING = 0x40, ///< Set VSYNC timing to the specified length of PPS data + MIPI_DSI_DCS_ID_SOFT_RESET = 0x01, ///< Software reset + MIPI_DSI_DCS_ID_WRITE_ACMD = 0x63, ///< Write access to ACMD registers + MIPI_DSI_DCS_ID_WRITE_CONTROL_DISPLAY = 0x53, ///< Write control mode of display brightness + MIPI_DSI_DCS_ID_WRITE_DSE_MAILBOX = 0x58, ///< Write registers of DSE read or write control mailbox + MIPI_DSI_DCS_ID_WRITE_LUT = 0x2D, ///< Fill peripheral look-up table with provided data + MIPI_DSI_DCS_ID_WRITE_MEMORY_CONTINUE = 0x3C, ///< Continue image information transfer from last address + MIPI_DSI_DCS_ID_WRITE_MEMORY_START = 0x2C, ///< Transfer image information from host to peripheral + MIPI_DSI_DCS_ID_WRITE_POWER_SAVE = 0x55, ///< Writes power save mode +} mipi_dsi_dcs_id_t; + +/** MIPI DSI Video Data type */ +typedef enum e_mipi_dsi_video_data +{ + MIPI_DSI_VIDEO_DATA_16RGB_PIXEL_STREAM = 0x0E, ///< 16-bit RGB Packed Pixel Stream + MIPI_DSI_VIDEO_DATA_18RGB_PIXEL_STREAM = 0x1E, ///< 18-bit RGB Packed Pixel Stream + MIPI_DSI_VIDEO_DATA_24RGB_PIXEL_STREAM = 0x3E, ///< 24-bit RGB Packed Pixel Stream +} mipi_dsi_video_data_t; + +/** MIPI DSI Acknowledge and Error type */ +typedef enum e_mipi_dsi_ack_err +{ + MIPI_DSI_ACK_ERR_NONE = 0x0000, ///< No Errors + MIPI_DSI_ACK_ERR_SOT_ERROR = 0x0001, ///< SoT Error + MIPI_DSI_ACK_ERR_SOT_SYNC_ERROR = 0x0002, ///< SoT Sync Error + MIPI_DSI_ACK_ERR_EOT_SYNC_ERROR = 0x0004, ///< EoT Sync Error + MIPI_DSI_ACK_ERR_ESCAPE_ENTRY_ERROR = 0x0008, ///< Escape Mode Entry Error + MIPI_DSI_ACK_ERR_LOW_POWER_SYNC_ERROR = 0x0010, ///< Low-Power Transmit Sync Error + MIPI_DSI_ACK_ERR_PERIPHERAL_TIMEOUT_ERROR = 0x0020, ///< Peripheral Timeout Error + MIPI_DSI_ACK_ERR_FALSE_CONTROL_ERROR = 0x0040, ///< False Control Error + MIPI_DSI_ACK_ERR_CONTENTION_DETECTED = 0x0080, ///< Contention Detected Error + MIPI_DSI_ACK_ERR_ECC_SINGLE = 0x0100, ///< ECC Error, single-bit + MIPI_DSI_ACK_ERR_ECC_MULTI = 0x0200, ///< ECC Error, multi-bit + MIPI_DSI_ACK_ERR_CKSM_ERROR = 0x0400, ///< Checksum Error (Long packet only) + MIPI_DSI_ACK_ERR_DSI_DATA_ERROR = 0x0800, ///< DSI Data Type Not Recognized + MIPI_DSI_ACK_ERR_DSI_VC_ID_ERROR = 0x1000, ///< DSI VC ID Invalid + MIPI_DSI_ACK_ERR_INVALID_TX_LEN = 0x2000, ///< Invalid Transmission Length + MIPI_DSI_ACK_ERR_DSI_PROTOCOL_VIOLATION = 0x8000, ///< DSI Protocol Violation +} mipi_dsi_ack_err_t; + +/* MIPI DSI Virtual Channel ID Type*/ +typedef enum e_mipi_dsi_vc +{ + MIPI_DSI_VC_NONE = 0x0, ///< No channels selected + MIPI_DSI_VC_0 = 0x1, ///< Virtual channel 0 + MIPI_DSI_VC_1 = 0x2, ///< Virtual channel 1 + MIPI_DSI_VC_2 = 0x4, ///< Virtual channel 2 + MIPI_DSI_VC_3 = 0x8, ///< Virtual channel 3 +} mipi_dsi_vc_t; + +/** MIPI DSI Message Flags */ +typedef enum e_mipi_dsi_cmd_flag +{ + MIPI_DSI_CMD_FLAG_NONE = 0x00, ///< No flags + MIPI_DSI_CMD_FLAG_BTA = 0x01, ///< Assert bus turnaround at end of transfer + MIPI_DSI_CMD_FLAG_BTA_READ = 0x02, ///< Assert bus turnaround followed by read request (No WRITE request before BTA) + MIPI_DSI_CMD_FLAG_BTA_NO_WRITE = 0x03, ///< Immediately assert bus turnaround (No WRITE request before BTA) + MIPI_DSI_CMD_FLAG_AUX_OPERATION = 0x20, ///< Execute auxiliary operation command + MIPI_DSI_CMD_FLAG_ACT_CODE_RESET_TRIGGER = 0x20, ///< Send action code reset trigger message. + MIPI_DSI_CMD_FLAG_ACT_CODE_INITIAL_SKEW_CAL = 0x24, ///< Send action code initial skew calibration message. + MIPI_DSI_CMD_FLAG_ACT_CODE_PERIODIC_SKEW_CAL = 0x25, ///< Send action code periodic skew message. + MIPI_DSI_CMD_FLAG_ACT_CODE_NO_OPERATION = 0x28, ///< Send action code NOOP message. + MIPI_DSI_CMD_FLAG_LOW_POWER = 0x40, ///< Transmit in low-power mode +} mipi_dsi_cmd_flag_t; + +/** MIPI DSI event codes */ +typedef enum e_mipi_dsi_event +{ + MIPI_DSI_EVENT_SEQUENCE_0, ///< Sequence 0 event (Low-Power) + MIPI_DSI_EVENT_SEQUENCE_1, ///< Sequence 1 event (High-Speed) + MIPI_DSI_EVENT_VIDEO, ///< Video event + MIPI_DSI_EVENT_RECEIVE, ///< Receive event + MIPI_DSI_EVENT_FATAL, ///< Fatal event + MIPI_DSI_EVENT_PHY, ///< Physical layer event + + /* Software triggered events - To allow application specific processing */ + MIPI_DSI_EVENT_POST_OPEN, ///< Interface has been opened. Perform post-open application processing + MIPI_DSI_EVENT_PRE_START, ///< Video is about to start. Perform pre-video application processing +} mipi_dsi_event_t; + +/** MIPI DSI Sequence status */ +typedef enum e_mipi_dsi_sequence_status +{ + MIPI_DSI_SEQUENCE_STATUS_NONE = 0X00000000, ///< Sequence status not set + MIPI_DSI_SEQUENCE_STATUS_RUNNING = 0x00000004, ///< Sequence operation in progress + MIPI_DSI_SEQUENCE_STATUS_ACTIONS_FINISHED = 0x00000010, ///< All descriptor actions finished + MIPI_DSI_SEQUENCE_STATUS_DESCRIPTORS_FINISHED = 0x00000100, ///< All descriptors finished + MIPI_DSI_SEQUENCE_STATUS_DESCRIPTOR_ABORT = 0x00010000, ///< Descriptor abort interrupt + MIPI_DSI_SEQUENCE_STATUS_SIZE_ERROR = 0x00080000, ///< Packet size error + MIPI_DSI_SEQUENCE_STATUS_TX_INTERNAL_BUS_ERROR = 0x01000000, ///< Tx internal bus error + MIPI_DSI_SEQUENCE_STATUS_RX_FATAL_ERROR = 0x04800000, ///< Receive fatal error + MIPI_DSI_SEQUENCE_STATUS_RX_FAIL = 0x08000000, ///< Receive fail + MIPI_DSI_SEQUENCE_STATUS_RX_PACKET_DATA_FAIL = 0x10000000, ///< Receive packet data fail + MIPI_DSI_SEQUENCE_STATUS_RX_CORRECTABLE_ERROR = 0x20000000, ///< Receive correctable error + MIPI_DSI_SEQUENCE_STATUS_RX_ACK_AND_ERROR = 0x40000000, ///< Receive acknowledge and error report +} mipi_dsi_sequence_status_t; + +/** MIPI DSI video status errors */ +typedef enum e_mipi_dsi_video_status +{ + MIPI_DSI_VIDEO_STATUS_NONE = 0x00000000, ///< Video status not set + MIPI_DSI_VIDEO_STATUS_START = 0x00000001, ///< Video started event + MIPI_DSI_VIDEO_STATUS_STOP = 0x00000002, ///< Video stopped event + MIPI_DSI_VIDEO_STATUS_RUNNING = 0x00000004, ///< Video running status + MIPI_DSI_VIDEO_STATUS_READY = 0x00000008, ///< Video ready event + MIPI_DSI_VIDEO_STATUS_TIMING_ERROR = 0x00100000, ///< Video timing error event + MIPI_DSI_VIDEO_STATUS_UNDERFLOW = 0x00400000, ///< Video buffer underflow event + MIPI_DSI_VIDEO_STATUS_OVERFLOW = 0x00800000, ///< Video buffer overflow event +} mipi_dsi_video_status_t; + +/** MIPI DSI receive status errors */ +typedef enum e_mipi_dsi_receive_status +{ + MIPI_DSI_RECEIVE_STATUS_NONE = 0x00000000, ///< Receive status not set + MIPI_DSI_RECEIVE_STATUS_BTA_REQUEST_END = 0x00000001, ///< Receive BTA request end + MIPI_DSI_RECEIVE_STATUS_LP_RX_HOST_TIMEOUT = 0x00000002, ///< Receive low power receive timeout + MIPI_DSI_RECEIVE_STATUS_BTA_ACK_TIMEOUT = 0x00000004, ///< Receive BTA ack timeout + MIPI_DSI_RECEIVE_STATUS_RESPONSE_PACKET = 0x00000100, ///< Receive response + MIPI_DSI_RECEIVE_STATUS_EOTP = 0x00000400, ///< Receive end of transmission packet + MIPI_DSI_RECEIVE_STATUS_TEARING_TRIGGER = 0x00002000, ///< Receive tearing trigger + MIPI_DSI_RECEIVE_STATUS_ACK_TRIGGER = 0x00004000, ///< Receive ack trigger + MIPI_DSI_RECEIVE_STATUS_TEARING_DETECT = 0x00008000, ///< Receive tearing detect + MIPI_DSI_RECEIVE_STATUS_MALFORM_ERROR = 0x00010000, ///< Receive malform error + MIPI_DSI_RECEIVE_STATUS_ECC_MULTI = 0x00020000, ///< Receive ecc multi-bit error + MIPI_DSI_RECEIVE_STATUS_UNEXPECTED_PACKET = 0x00040000, ///< Receive unexpected packet + MIPI_DSI_RECEIVE_STATUS_WORD_COUNT = 0x00100000, ///< Receive word count + MIPI_DSI_RECEIVE_STATUS_CRC = 0x00200000, ///< Receive crc error + MIPI_DSI_RECEIVE_STATUS_INTERNAL_BUS = 0x00400000, ///< Receive internal bus error + MIPI_DSI_RECEIVE_STATUS_BUFFER_OVERFLOW = 0x00800000, ///< Receive buffer overflow + MIPI_DSI_RECEIVE_STATUS_TIMEOUT = 0x01000000, ///< Receive timeout + MIPI_DSI_RECEIVE_STATUS_NO_RESPONSE = 0x02000000, ///< Receive no response + MIPI_DSI_RECEIVE_STATUS_PACKET_SIZE = 0x04000000, ///< Receive packet size error + MIPI_DSI_RECEIVE_STATUS_ECC_SINGLE = 0x10000000, ///< Receive ecc single bit error + MIPI_DSI_RECEIVE_STATUS_ACK_AND_ERROR = 0x40000000, ///< Receive ack and error +} mipi_dsi_receive_status_t; + +/** MIPI DSI fatal status errors */ +typedef enum e_mipi_dsi_fatal_status +{ + MIPI_DSI_FATAL_STATUS_NONE = 0x00000000, ///< Fatal status not set + MIPI_DSI_FATAL_STATUS_HS_TX_TIMEOUT = 0x00000001, ///< Fatal high speed transmit timeout + MIPI_DSI_FATAL_STATUS_LP_RX_TIMEOUT = 0x00000002, ///< Fatal low power receive timeout + MIPI_DSI_FATAL_STATUS_BTA_ACK_TIMEOUT = 0x00000004, ///< Fatal BTA ack timeout + MIPI_DSI_FATAL_STATUS_ESCAPE_ENTRY_ERROR = 0x00010000, ///< Fatal escape mode entry error + MIPI_DSI_FATAL_STATUS_LPDT_SYNC_ERROR = 0x00020000, ///< Fatal low power data transmission synchronization error + MIPI_DSI_FATAL_STATUS_CTRL_ERROR = 0x00040000, ///< Fatal control error + MIPI_DSI_FATAL_STATUS_LP0_CONTENTION_DETECT = 0x00080000, ///< Fatal lane 0 low power contention detect + MIPI_DSI_FATAL_STATUS_LP1_CONTENTION_DETECT = 0x00100000, ///< Fatal lane 1 low power contention detect + MIPI_DSI_FATAL_STATUS_LP0_CONTENTION = 0x80000000, ///< Fatal lane 0 low power contention status + MIPI_DSI_FATAL_STATUS_LP1_CONTENTION = 0x10000000, ///< Fatal lane 1 low power contention status +} mipi_dsi_fatal_status_t; + +/** MIPI DSI physical lane status */ +typedef enum e_mipi_dsi_phy_status +{ + MIPI_DSI_PHY_STATUS_NONE = 0x00000000, ///< Physical lane status not set + MIPI_DSI_PHY_STATUS_ULP_NOT_ACTIVE = 0x00000001, ///< Physical lane ULP not active + MIPI_DSI_PHY_STATUS_CLOCK_LANE_STOP = 0x00000002, ///< Clock lane in stopped state + MIPI_DSI_PHY_STATUS_DATA_LANE0_LP_RX = 0x00000004, ///< Data lane low power receive mode + MIPI_DSI_PHY_STATUS_DATA_LANE0_ULP_RX = 0x00000008, ///< Data lane ultra low power receive mode + MIPI_DSI_PHY_STATUS_DATA_LANE0_NOT_ULP = 0x00000010, ///< Data lane 0 not in ULP mode + MIPI_DSI_PHY_STATUS_DATA_LANE1_NOT_ULP = 0x00000020, ///< Data lane 1 not in ULP mode + MIPI_DSI_PHY_STATUS_DATA_LANE0_STOP = 0x00000100, ///< Data lane 0 stop state + MIPI_DSI_PHY_STATUS_DATA_LANE1_STOP = 0x00000200, ///< Data lane 1 stop state + MIPI_DSI_PHY_STATUS_DATA_LANE0_RX_TO_TX = 0x00001000, ///< Data lane Rx to Tx transition event + MIPI_DSI_PHY_STATUS_DATA_LANE0_TX_TO_RX = 0x00002000, ///< Data lane Tx to Rx transition event + MIPI_DSI_PHY_STATUS_DATA_LANE0_RX_STATE = 0x00008000, ///< Data lane Rx active state + MIPI_DSI_PHY_STATUS_CLOCK_ULPS_ENTER = 0x01000000, ///< Clock lane ULPS enter event + MIPI_DSI_PHY_STATUS_CLOCK_ULPS_EXIT = 0x02000000, ///< Clock lane ULPS exit event + MIPI_DSI_PHY_STATUS_CLOCK_LP_TO_HS = 0x04000000, ///< Clock lane LP to HS transition event + MIPI_DSI_PHY_STATUS_CLOCK_HS_TO_LP = 0x08000000, ///< Clock lane HS to LP transition event + MIPI_DSI_PHY_STATUS_DATA_LANE_ULPS_ENTER = 0x10000000, ///< Data lane ULPS enter event + MIPI_DSI_PHY_STATUS_DATA_LANE_ULPS_EXIT = 0x20000000, ///< Data lane ULPS exit event +} mipi_dsi_phy_status_t; + +/** MIPI DSI link status bits */ +typedef enum e_mipi_dsi_link_status +{ + MIPI_DSI_LINK_STATUS_IDLE = 0x0000, ///< Link idle or uninitialized + MIPI_DSI_LINK_STATUS_CH0_RUNNING = 0x0001, ///< Channel 0 running + MIPI_DSI_LINK_STATUS_CH1_RUNNING = 0x0010, ///< Channel 1 running + MIPI_DSI_LINK_STATUS_VIDEO_RUNNING = 0x0100, ///< Video output running + MIPI_DSI_LINK_STATUS_HP_MODE_BUSY = 0x1000, ///< HP operation busy + MIPI_DSI_LINK_STATUS_LP_MODE_BUSY = 0x2000, ///< LP operation busy +} mipi_dsi_link_status_t; + +/** MIPI DSI Lane Type */ +typedef enum e_mipi_dsi_lane +{ + MIPI_DSI_LANE_CLOCK = 0x01, ///< Clock Lanes + MIPI_DSI_LANE_DATA_ALL = 0x02, ///< All Data Lanes +} mipi_dsi_lane_t; + +/** MIPI DSI Command */ +typedef struct st_mipi_dsi_cmd +{ + uint8_t channel; ///< Virtual Channel ID + mipi_dsi_cmd_id_t cmd_id; ///< Message ID + mipi_dsi_cmd_flag_t flags; ///< Flags controlling this message transition + uint16_t tx_len; ///< Transmit buffer size + const uint8_t * p_tx_buffer; ///< Transmit buffer pointer + const uint8_t * p_rx_buffer; ///< Receive buffer pointer +} mipi_dsi_cmd_t; + +/** MIPI DSI Acknowledge and Error status type */ +typedef union st_mipi_dsi_ack_err_status_t +{ + __PACKED_STRUCT + { + mipi_dsi_ack_err_t error_report : 16; ///< Error report bits + mipi_dsi_vc_t virtual_channel : 4; ///< Virtual Channel ID + uint32_t : 12; // Padding + }; + uint32_t bits; +} mipi_dsi_ack_err_status_t; + +/** MIPI DSI status type */ +typedef struct st_mipi_dsi_status_t +{ + mipi_dsi_link_status_t link_status; ///< Link status + mipi_dsi_ack_err_status_t ack_err_latest; ///< Latest Acknowledge and Error Report Packet Latest Info + mipi_dsi_ack_err_status_t ack_err_accumulated; ///< Accumulated Acknowledge and Error Report Packet Latest Info +} mipi_dsi_status_t; + +/** MIPI DSI Result */ +typedef __PACKED_STRUCT st_mipi_dsi_result +{ + uint8_t data[2]; ///< Data of received packet header + mipi_dsi_cmd_id_t cmd_id : 6; ///< Data type + uint8_t virtual_channel_id : 2; ///< Virtual channel ID + uint8_t long_packet : 1; ///< Sort packet (0) or Long packet (1) + uint8_t rx_success : 1; ///< Response packet or ack trigger received + uint8_t timeout : 1; ///< Fatal timeout error + uint8_t rx_fail : 1; ///< Expected receive not done + uint8_t rx_data_fail : 1; ///< Receive packet data fail + uint8_t rx_correctable_error : 1; ///< Correctable error detected + uint8_t rx_ack_err : 1; ///< Rx acknowledge and error report packet received + uint8_t info_overwrite : 1; ///< This information was overwritten +} mipi_dsi_receive_result_t; + +/** MIPI DSI callback parameter definition */ +typedef struct st_mipi_dsi_callback_args +{ + mipi_dsi_event_t event; ///< Event code + union + { + mipi_dsi_sequence_status_t tx_status; ///< Sequence status + mipi_dsi_receive_status_t rx_status; ///< Receive status + mipi_dsi_fatal_status_t fatal_status; ///< Fatal status + mipi_dsi_video_status_t video_status; ///< Video status + mipi_dsi_phy_status_t phy_status; ///< Phy Status + }; + mipi_dsi_receive_result_t * p_result; ///< Receive result pointer + void const * p_context; ///< Context provided to user during callback +} mipi_dsi_callback_args_t; + +/** MIPI DSI transition timing */ +typedef struct st_mipi_dsi_timing +{ + uint32_t clock_stop_time; ///< Clock stop time + uint32_t clock_beforehand_time; ///< Clock beforehand time + uint32_t clock_keep_time; ///< Clock Keep time + uint32_t go_lp_and_back; ///< Go LP and Back time +} mipi_dsi_timing_t; + +/** MIPI DSI main configuration structure */ +typedef struct st_mipi_dsi_cfg +{ + mipi_phy_instance_t const * p_mipi_phy_instance; ///< Pointer to mipi physical layer instance + + mipi_dsi_timing_t const * p_timing; ///< Pointer to MIPI DSI timing configuration + + bool hsa_no_lp; ///< Suppress the transition to LP during HSA period and keep HS + bool hbp_no_lp; ///< Suppress the transition to LP during HBP period and keep HS + bool hfp_no_lp; ///< Suppress the transition to LP during HFP period and keep HS + uint8_t num_lanes; ///< Number of MIPI lanes to use. + uint8_t ulps_wakeup_period; ///< ULPS wakeup period + uint8_t continuous_clock; ///< Always run HS clock on/off + uint32_t hs_tx_timeout; ///< HS-Tx Timeout value + uint32_t lp_rx_timeout; ///< LP-Rx host processor timeout + uint32_t turnaround_timeout; ///< Turnaround Acknowledge Timeout + uint32_t bta_timeout; ///< Peripheral Response Timeout + uint32_t lprw_timeout; ///< LP Read and Write Timeouts + uint32_t hsrw_timeout; ///< HS Read and Write Timeouts + uint32_t max_return_packet_size; ///< Maximum return packet size + bool ecc_enable; ///< ECC Check enable + mipi_dsi_vc_t crc_check_mask; ///< Virtual channel CRC check enable + bool scramble_enable; ///< Scramble on/off + bool tearing_detect; ///< External tearing effect detection mode (0:rising, 1:falling edge) + bool eotp_enable; ///< End of Transmit Packet (EoTP) on/off + bool sync_pulse; ///< Enable for Non-Burst Mode with Sync Pulse sequence + mipi_dsi_video_data_t data_type; ///< Video mode data type: 16-bit RGB, 18-bit RGB, 24-bit RGB + uint8_t virtual_channel_id; ///< Video mode virtual channel to use (from 0x0 to 0x3) + uint32_t vertical_sync_lines; ///< Number of vertical sync active lines + bool vertical_sync_polarity; ///< V-Sync Polarity + uint32_t vertical_active_lines; ///< Number of vertical active lines + uint32_t vertical_back_porch; ///< Vertical back porch + uint32_t vertical_front_porch; ///< Vertical front porch + uint32_t horizontal_sync_lines; ///< Number of horizontal sync active lines + bool horizontal_sync_polarity; ///< H-Sync Polarity + uint32_t horizontal_active_lines; ///< Number of horizontal active lines + uint32_t horizontal_back_porch; ///< Horizontal back porch + uint32_t horizontal_front_porch; ///< Horizontal front porch + uint32_t video_mode_delay; + + /** Callback configuration */ + void (* p_callback)(mipi_dsi_callback_args_t * p_args); ///< Pointer to callback function + void const * p_context; ///< User defined context passed into callback function + + /** Pointer to display peripheral specific configuration */ + void const * p_extend; ///< MIPI hardware dependent configuration +} mipi_dsi_cfg_t; + +/** MIPI DSI control block. Allocate an instance specific control block to pass into the MIPI DSI API calls. */ +typedef void mipi_dsi_ctrl_t; + +/** Shared Interface definition for MIPI DSI peripheral */ +typedef struct st_mipi_dsi_api +{ + /** Open MIPI DSI device. + * + * @param[in,out] p_ctrl Pointer to MIPI DSI interface control block. Must be declared by user. Value set here. + * @param[in] p_cfg Pointer to MIPI DSI configuration structure. All elements of this structure must be set by user. + */ + fsp_err_t (* open)(mipi_dsi_ctrl_t * const p_ctrl, mipi_dsi_cfg_t const * const p_cfg); + + /** Close MIPI DSI device. + * + * @param[in] p_ctrl Pointer to MIPI DSI interface control block. + */ + fsp_err_t (* close)(mipi_dsi_ctrl_t * const p_ctrl); + + /** Start pixel data output. + * + * @param[in] p_ctrl Pointer to MIPI DSI interface control block. + */ + fsp_err_t (* start)(mipi_dsi_ctrl_t * const p_ctrl); + + /** Stop pixel data output. + * + * @param[in] p_ctrl Pointer to MIPI DSI interface control block. + */ + fsp_err_t (* stop)(mipi_dsi_ctrl_t * const p_ctrl); + + /** Enter Ultra-low Power State (ULPS). + * + * @param[in] p_ctrl Pointer to MIPI DSI interface control block. + * @param[in] lane Physical lane(s) to transition into ULPS + */ + fsp_err_t (* ulpsEnter)(mipi_dsi_ctrl_t * const p_ctrl, mipi_dsi_lane_t lane); + + /** Exit Ultra-low Power State (ULPS). + * + * @param[in] p_ctrl Pointer to MIPI DSI interface control block. + * @param[in] lane Physical lane(s) to transition from ULPS + */ + fsp_err_t (* ulpsExit)(mipi_dsi_ctrl_t * const p_ctrl, mipi_dsi_lane_t lane); + + /** Send a command to the display. + * + * @param[in] p_ctrl Pointer to MIPI DSI interface control block. + * @param[in] p_cmd Pointer to a command structure + */ + fsp_err_t (* command)(mipi_dsi_ctrl_t * const p_api_ctrl, mipi_dsi_cmd_t * p_cmd); + + /** Get status of MIPI link. + * + * @param[in] p_ctrl Pointer to MIPI DSI interface control block. + * @param[in] p_status Pointer to MIPI DSI interface status structure. + */ + fsp_err_t (* statusGet)(mipi_dsi_ctrl_t * const p_ctrl, mipi_dsi_status_t * p_status); +} mipi_dsi_api_t; + +/** This structure encompasses everything that is needed to use an instance of this interface. */ +typedef struct st_mipi_dsi_instance +{ + mipi_dsi_ctrl_t * p_ctrl; ///< Pointer to the control structure for this instance + mipi_dsi_cfg_t const * p_cfg; ///< Pointer to the configuration structure for this instance + mipi_dsi_api_t const * p_api; ///< Pointer to the API structure for this instance +} mipi_dsi_instance_t; + +/* @} (end defgroup MIPI_DSI_API) */ + +/* Common macro for FSP header files. There is also a corresponding FSP_HEADER macro at the top of this file. */ +FSP_FOOTER +#endif diff --git a/drivers/ra/fsp/inc/instances/r_mipi_dsi.h b/drivers/ra/fsp/inc/instances/r_mipi_dsi.h new file mode 100644 index 0000000..42c5c22 --- /dev/null +++ b/drivers/ra/fsp/inc/instances/r_mipi_dsi.h @@ -0,0 +1,106 @@ +/* +* Copyright (c) 2020 - 2024 Renesas Electronics Corporation and/or its affiliates +* +* SPDX-License-Identifier: BSD-3-Clause +*/ + +#ifndef R_MIPI_DSI_H +#define R_MIPI_DSI_H + +/*********************************************************************************************************************** + * Includes + **********************************************************************************************************************/ + +#include "bsp_api.h" +#include "r_mipi_dsi_cfg.h" +#include "r_mipi_dsi_api.h" + +/* Common macro for FSP header files. There is also a corresponding FSP_FOOTER macro at the end of this file. */ +FSP_HEADER + +/*******************************************************************************************************************//** + * @addtogroup MIPI_DSI + * @{ + **********************************************************************************************************************/ + +/*********************************************************************************************************************** + * Macro definitions + **********************************************************************************************************************/ + +/*********************************************************************************************************************** + * Typedef definitions + **********************************************************************************************************************/ + +/** MIPI DSI interrupt configuration */ +typedef struct st_mipi_dsi_irq_cfg +{ + uint8_t ipl; ///< Interrupt priority + IRQn_Type irq; ///< Interrupt vector number +} mipi_dsi_irq_cfg_t; + +/** Extended configuration structure for MIPI DSI. */ +typedef struct st_mipi_dsi_extended_cfg +{ + /* Interrupt configuration */ + mipi_dsi_irq_cfg_t dsi_seq0; ///< Sequence 0 interrupt + mipi_dsi_irq_cfg_t dsi_seq1; ///< Sequence 1 interrupt + mipi_dsi_irq_cfg_t dsi_ferr; ///< DSI Fatal Error interrupt + mipi_dsi_irq_cfg_t dsi_ppi; ///< D-PHY PPI interrupt + mipi_dsi_irq_cfg_t dsi_rcv; ///< Receive interrupt + mipi_dsi_irq_cfg_t dsi_vin1; ///< Video Input Operation interrupt + + uint32_t dsi_rxie; ///< Receive interrupt enable configuration + uint32_t dsi_ferrie; ///< Fatal error interrupt enable configuration + uint32_t dsi_plie; ///< Physical lane interrupt enable configuration + uint32_t dsi_vmie; ///< Video mode interrupt enable configuration + uint32_t dsi_sqch0ie; ///< Sequence Channel 0 interrupt enable configuration + uint32_t dsi_sqch1ie; ///< Sequence Channel 1 interrupt enable configuration +} mipi_dsi_extended_cfg_t; + +/** MIPI DSI instance control block. */ +typedef struct st_mipi_dsi_instance_ctrl +{ + uint32_t open; ///< Interface is open + bool data_ulps_active; ///< Data lane ULPS status + bool clock_ulps_active; ///< Data lane ULPS status + mipi_dsi_lane_t ulps_status; ///< Ultra-low Power State active status + mipi_dsi_cfg_t const * p_cfg; ///< Pointer to configuration structure used to open the interface + void (* p_callback)(mipi_dsi_callback_args_t *); ///< Pointer to callback that is called when an adc_event_t occurs. + void const * p_context; ///< Pointer to context to be passed into callback function + mipi_dsi_callback_args_t * p_callback_memory; ///< Pointer to non-secure memory that can be used to pass arguments to a callback in non-secure memory. +} mipi_dsi_instance_ctrl_t; + +/********************************************************************************************************************** + * Exported global variables + **********************************************************************************************************************/ + +/** @cond INC_HEADER_DEFS_SEC */ +/** Filled in Interface API structure for this Instance. */ +extern const mipi_dsi_api_t g_mipi_dsi; + +/** @endcond */ + +/*********************************************************************************************************************** + * Exported global functions (to be accessed by other files) + **********************************************************************************************************************/ + +/*********************************************************************************************************************** + * Public APIs + **********************************************************************************************************************/ +fsp_err_t R_MIPI_DSI_Open(mipi_dsi_ctrl_t * const p_api_ctrl, mipi_dsi_cfg_t const * const p_cfg); +fsp_err_t R_MIPI_DSI_Close(mipi_dsi_ctrl_t * const p_api_ctrl); +fsp_err_t R_MIPI_DSI_Start(mipi_dsi_ctrl_t * const p_api_ctrl); +fsp_err_t R_MIPI_DSI_UlpsEnter(mipi_dsi_ctrl_t * const p_api_ctrl, mipi_dsi_lane_t lane); +fsp_err_t R_MIPI_DSI_UlpsExit(mipi_dsi_ctrl_t * const p_api_ctrl, mipi_dsi_lane_t lane); +fsp_err_t R_MIPI_DSI_Stop(mipi_dsi_ctrl_t * const p_api_ctrl); +fsp_err_t R_MIPI_DSI_Command(mipi_dsi_ctrl_t * const p_api_ctrl, mipi_dsi_cmd_t * p_cmd); +fsp_err_t R_MIPI_DSI_StatusGet(mipi_dsi_ctrl_t * const p_api_ctrl, mipi_dsi_status_t * p_status); + +/*******************************************************************************************************************//** + * @} (end defgroup MIPI_DSI) + **********************************************************************************************************************/ + +/* Common macro for FSP header files. There is also a corresponding FSP_HEADER macro at the top of this file. */ +FSP_FOOTER + +#endif // R_MIPI_DSI_H diff --git a/drivers/ra/fsp/inc/instances/r_mipi_phy.h b/drivers/ra/fsp/inc/instances/r_mipi_phy.h new file mode 100644 index 0000000..594b1bd --- /dev/null +++ b/drivers/ra/fsp/inc/instances/r_mipi_phy.h @@ -0,0 +1,141 @@ +/* +* Copyright (c) 2020 - 2024 Renesas Electronics Corporation and/or its affiliates +* +* SPDX-License-Identifier: BSD-3-Clause +*/ + +#ifndef R_MIPI_PHY_H +#define R_MIPI_PHY_H + +/*********************************************************************************************************************** + * Includes + **********************************************************************************************************************/ + +#include "bsp_api.h" + +/* Common macro for FSP header files. There is also a corresponding FSP_FOOTER macro at the end of this file. */ +FSP_HEADER + +/*******************************************************************************************************************//** + * @addtogroup MIPI_PHY + * @{ + **********************************************************************************************************************/ + +/*********************************************************************************************************************** + * Macro definitions + **********************************************************************************************************************/ + +/*********************************************************************************************************************** + * Typedef definitions + **********************************************************************************************************************/ + +/* MIPI_PHY PLL speed configuration */ +typedef union +{ + __PACKED_STRUCT + { + uint8_t div; ///< PHY PLL divisor + uint8_t mul_frac; ///< PHY PLL fractional multiplier (0, 1/3, 2/3, or 1/2) + uint16_t mul_int; ///< PHY PLL integer multiplier (1-based) + }; + uint32_t raw; +} mipi_phy_pll_cfg_t; + +/** MIPI PHY D-PHY power mode transition timing */ +typedef struct st_mipi_phy_timing +{ + uint32_t t_init : 19; ///< Minimum duration of the TINIT state (Units: PCLKA cycles) + uint32_t : 13; // Padding + uint8_t t_clk_prep; ///< Duration of the clock lane LP-00 state (immediately before entry to the HS-0 state) + uint8_t t_hs_prep; ///< Duration of the data lane LP-00 state (immediately before entry to the HS-0 state) + union + { + __PACKED_STRUCT + { + uint8_t t_clk_zero; ///< TCLKZERO setting. See Figure 57.1 in User Manual (R01UH0995EJ0060) for more information + uint8_t t_clk_pre; ///< TCLKPRE setting. See Figure 57.1 in User Manual (R01UH0995EJ0060) for more information + uint8_t t_clk_post; ///< TCLKPOST setting. See Figure 57.1 in User Manual (R01UH0995EJ0060) for more information + uint8_t t_clk_trail; ///< TCLKTRAIL setting. See Figure 57.1 in User Manual (R01UH0995EJ0060) for more information + } dphytim4_b; + uint32_t dphytim4; ///< Clock lane pre and post data timing settings + }; + union + { + __PACKED_STRUCT + { + uint8_t t_hs_zero; ///< THSZERO setting. See Figure 57.1 in User Maual (R01UH0995EJ0060) for more information + uint8_t t_hs_trail; ///< THSTRAIL setting. See Figure 57.1 in User Maual (R01UH0995EJ0060) for more information + uint8_t t_hs_exit; ///< THSEXIT setting. See Figure 57.1 in User Maual (R01UH0995EJ0060) for more information + uint8_t : 8; + } dphytim5_b; + uint32_t dphytim5; ///< High-Speed data lane timing settings + }; + uint8_t t_lp_exit; ///< Low-power transition time to High-Speed mode +} mipi_phy_timing_t; + +/** MIPI_PHY configuration structure. */ +typedef struct st_mipi_phy_cfg +{ + mipi_phy_pll_cfg_t pll_settings; ///< PHY PLL configuration (DPHYPLFCR) + uint8_t lp_divisor : 5; ///< PHY PLL LP speed divisor setting (DPHYESCCR) + mipi_phy_timing_t const * p_timing; ///< Pointer to D-PHY HS/LP transition timing values +} mipi_phy_cfg_t; + +/** MIPI_PHY instance control block. */ +typedef struct st_mipi_phy_ctrl +{ + uint32_t open; + mipi_phy_cfg_t const * p_cfg; +} mipi_phy_ctrl_t; + +/** Private Interface definition for MIPI PHY peripheral */ +typedef struct st_mipi_phy_api +{ + /** Open MIPI PHY device. + * @param[in,out] p_ctrl Pointer to MIPI PHY interface control block. + * @param[in] p_cfg Pointer to MIPI PHY configuration structure. + */ + fsp_err_t (* open)(mipi_phy_ctrl_t * const p_ctrl, mipi_phy_cfg_t const * const p_cfg); + + /** Close MIPI PHY device. + * @param[in] p_ctrl Pointer to MIPI PHY interface control block. + */ + fsp_err_t (* close)(mipi_phy_ctrl_t * const p_ctrl); +} mipi_phy_api_t; + +/** This structure encompasses everything that is needed to use an instance of this interface. */ +typedef struct st_mipi_phy_instance +{ + mipi_phy_ctrl_t * p_ctrl; ///< Pointer to the control structure for this instance + mipi_phy_cfg_t const * p_cfg; ///< Pointer to the configuration structure for this instance + mipi_phy_api_t const * p_api; ///< Pointer to the API structure for this instance +} mipi_phy_instance_t; + +/********************************************************************************************************************** + * Exported global variables + **********************************************************************************************************************/ + +/** @cond INC_HEADER_DEFS_SEC */ +/** Filled in Interface API structure for this Instance. */ +extern const mipi_phy_api_t g_mipi_phy; + +/** @endcond */ + +/*********************************************************************************************************************** + * Exported global functions (to be accessed by other files) + **********************************************************************************************************************/ + +/*********************************************************************************************************************** + * Instance Functions (Note: This is not a public API and should not be called directly) + **********************************************************************************************************************/ +fsp_err_t r_mipi_phy_open(mipi_phy_ctrl_t * const p_api_ctrl, mipi_phy_cfg_t const * const p_cfg); +fsp_err_t r_mipi_phy_close(mipi_phy_ctrl_t * const p_api_ctrl); + +/*******************************************************************************************************************//** + * @} (end defgroup MIPI_PHY) + **********************************************************************************************************************/ + +/* Common macro for FSP header files. There is also a corresponding FSP_HEADER macro at the top of this file. */ +FSP_FOOTER + +#endif // R_MIPI_PHY_H diff --git a/drivers/ra/fsp/src/r_mipi_dsi/r_mipi_dsi.c b/drivers/ra/fsp/src/r_mipi_dsi/r_mipi_dsi.c new file mode 100644 index 0000000..b3aa267 --- /dev/null +++ b/drivers/ra/fsp/src/r_mipi_dsi/r_mipi_dsi.c @@ -0,0 +1,1082 @@ +/* +* Copyright (c) 2020 - 2024 Renesas Electronics Corporation and/or its affiliates +* +* SPDX-License-Identifier: BSD-3-Clause +*/ + +/*********************************************************************************************************************** + * Includes + **********************************************************************************************************************/ +#include +#include "r_mipi_dsi.h" + +/*********************************************************************************************************************** + * Macro definitions + **********************************************************************************************************************/ +#define MIPI_DSI_OPEN (0x4D504944) +#define MIPI_MAX_CH0_CMD (128) +#define MIPI_MAX_CH1_CMD (1024) +#define MIPI_DSI_RSRST_RESET_BITS (R_DSILINK_RSTSR_RSTHS_Msk | \ + R_DSILINK_RSTSR_RSTLP_Msk | \ + R_DSILINK_RSTSR_RSTAPB_Msk | \ + R_DSILINK_RSTSR_RSTAXI_Msk | \ + R_DSILINK_RSTSR_RSTV_Msk) + +#define DSI_PACKET_FORMAT_IS_SHORT(cmd_id) ((cmd_id & 0x0F) <= 0x08) +#define DSI_PACKET_FORMAT_IS_LONG(cmd_id) ((cmd_id & 0x0F) > 0x08) + +/*********************************************************************************************************************** + * Typedef definitions + **********************************************************************************************************************/ + +#if defined(__ARMCC_VERSION) || defined(__ICCARM__) +typedef void (BSP_CMSE_NONSECURE_CALL * mipi_dsi_prv_ns_callback)(mipi_dsi_callback_args_t * p_args); +#elif defined(__GNUC__) +typedef BSP_CMSE_NONSECURE_CALL void (*volatile mipi_dsi_prv_ns_callback)(mipi_dsi_callback_args_t * p_args); +#endif + +typedef enum e_mipi_dsi_clock_state +{ + MIPI_DSI_CLOCK_STATE_IDLE, ///< MIPI DSI Clock is off + MIPI_DSI_CLOCK_STATE_STARTING, ///< MIPI DSI Clock starting + MIPI_DSI_CLOCK_STATE_STARTED, ///< MIPI DSI Clock is started + MIPI_DSI_CLOCK_STATE_STOPPING, ///< MIPI DSI Clock is stopping +} mipi_dsi_clock_state_t; + +/*********************************************************************************************************************** + * Global variables + **********************************************************************************************************************/ +static volatile mipi_dsi_clock_state_t g_clock_state; +static volatile bool g_video_started; + +const mipi_dsi_api_t g_mipi_dsi = +{ + .open = R_MIPI_DSI_Open, + .close = R_MIPI_DSI_Close, + .start = R_MIPI_DSI_Start, + .stop = R_MIPI_DSI_Stop, + .ulpsEnter = R_MIPI_DSI_UlpsEnter, + .ulpsExit = R_MIPI_DSI_UlpsExit, + .command = R_MIPI_DSI_Command, + .statusGet = R_MIPI_DSI_StatusGet, +}; + +/*********************************************************************************************************************** + * Private function prototypes + **********************************************************************************************************************/ +void mipi_dsi_seq0(void); +void mipi_dsi_seq1(void); +void mipi_dsi_vin1(void); +void mipi_dsi_rcv(void); +void mipi_dsi_ferr(void); +void mipi_dsi_ppi(void); + +static void dsi_isr_enable(mipi_dsi_irq_cfg_t const * irq_cfg, mipi_dsi_instance_ctrl_t * p_ctrl); +static void dsi_isr_disable(mipi_dsi_irq_cfg_t const * irq_cfg); + +static void dsi_enter_reset(void); +static void dsi_init_timing(mipi_dsi_cfg_t const * const p_cfg); +static void dsi_exit_reset(mipi_dsi_cfg_t const * const p_cfg); +static void dsi_hs_clock_start(mipi_dsi_instance_ctrl_t * p_ctrl); +static void dsi_hs_clock_stop(mipi_dsi_instance_ctrl_t * p_ctrl); + +static void dsi_init_video(mipi_dsi_cfg_t const * p_cfg); + +static void dsi_call_callback(mipi_dsi_instance_ctrl_t * p_ctrl, mipi_dsi_callback_args_t * p_args); + +static fsp_err_t dsi_stop(mipi_dsi_instance_ctrl_t * p_ctrl); +static uint32_t dsi_cmd_sequence_register_a(mipi_dsi_cmd_t * p_cmd); +static uint32_t dsi_cmd_sequence_register_b(mipi_dsi_cmd_t * p_cmd); +static uint32_t dsi_cmd_sequence_register_c(mipi_dsi_cmd_t * p_cmd); +static uint32_t dsi_cmd_sequence_register_d(mipi_dsi_cmd_t * p_cmd); + +/*******************************************************************************************************************//** + * @addtogroup MIPI_DSI + * @{ + **********************************************************************************************************************/ + +/*********************************************************************************************************************** + * Functions + **********************************************************************************************************************/ + +/******************************************************************************************************************//** + * Initialize the MIPI DSI peripheral. + * + * @retval FSP_SUCCESS The channel was successfully opened. + * @retval FSP_ERR_ASSERTION One or both of the parameters was NULL. + * @retval FSP_ERR_ALREADY_OPEN The instance is already opened. + * @retval FSP_ERR_INVALID_STATE Display module must be opened before DSI. + **********************************************************************************************************************/ +fsp_err_t R_MIPI_DSI_Open (mipi_dsi_ctrl_t * const p_api_ctrl, mipi_dsi_cfg_t const * const p_cfg) +{ + fsp_err_t err; + mipi_dsi_instance_ctrl_t * p_ctrl = (mipi_dsi_instance_ctrl_t *) p_api_ctrl; + +#if MIPI_DSI_CFG_PARAM_CHECKING_ENABLE + FSP_ASSERT(NULL != p_cfg); + FSP_ASSERT(NULL != p_ctrl); + FSP_ERROR_RETURN(MIPI_DSI_OPEN != p_ctrl->open, FSP_ERR_ALREADY_OPEN); +#endif + + FSP_ERROR_RETURN(R_GLCDC->SYSCNT.PANEL_CLK_b.CLKEN, FSP_ERR_INVALID_STATE); + + /* Initialize internal state */ + g_clock_state = MIPI_DSI_CLOCK_STATE_IDLE; + g_video_started = false; + p_ctrl->p_cfg = p_cfg; + + /* Start clocks to the MIPI DSI peripheral */ + R_BSP_MODULE_START(FSP_IP_MIPI_DSI, 0); + + err = r_mipi_phy_open(p_cfg->p_mipi_phy_instance->p_ctrl, p_cfg->p_mipi_phy_instance->p_cfg); + FSP_ERROR_RETURN(FSP_SUCCESS == err, err); + + /* Perform sequence steps 5 to 9 from section 58.3.2 in RA8D1 hardware manual R01UH0995EJ0060. */ + dsi_enter_reset(); + dsi_init_timing(p_cfg); + dsi_exit_reset(p_cfg); + + /* Configure interrupt sources */ + mipi_dsi_extended_cfg_t * p_extend = (mipi_dsi_extended_cfg_t *) p_cfg->p_extend; + R_DSILINK->RXIER = p_extend->dsi_rxie; + R_DSILINK->FERRIER = p_extend->dsi_ferrie; + R_DSILINK->PLIER = p_extend->dsi_plie; + R_DSILINK->VMIER = p_extend->dsi_vmie; + R_DSILINK->SQCH0IER = p_extend->dsi_sqch0ie; + R_DSILINK->SQCH1IER = p_extend->dsi_sqch1ie; + + /* Clear any active status bits */ + R_DSILINK->SQCH0SCR = R_DSILINK_SQCH0SCR_AACTFIN_Msk | + R_DSILINK_SQCH0SCR_ADESFIN_Msk | + R_DSILINK_SQCH0SCR_DABORT_Msk | + R_DSILINK_SQCH0SCR_SIZEERR_Msk | + R_DSILINK_SQCH0SCR_TXIBERR_Msk | + R_DSILINK_SQCH0SCR_RXFERR_Msk | + R_DSILINK_SQCH0SCR_RXFAIL_Msk | + R_DSILINK_SQCH0SCR_RXPFAIL_Msk | + R_DSILINK_SQCH0SCR_RXCORERR_Msk | + R_DSILINK_SQCH0SCR_RXAKE_Msk; + R_DSILINK->SQCH1SCR = R_DSILINK_SQCH1SCR_AACTFIN_Msk | + R_DSILINK_SQCH1SCR_ADESFIN_Msk | + R_DSILINK_SQCH1SCR_DABORT_Msk | + R_DSILINK_SQCH1SCR_SIZEERR_Msk | + R_DSILINK_SQCH1SCR_TXIBERR_Msk | + R_DSILINK_SQCH1SCR_RXFERR_Msk | + R_DSILINK_SQCH1SCR_RXFAIL_Msk | + R_DSILINK_SQCH1SCR_RXPFAIL_Msk | + R_DSILINK_SQCH1SCR_RXCORERR_Msk | + R_DSILINK_SQCH1SCR_RXAKE_Msk; + R_DSILINK->VMSCR = R_DSILINK_VMSCR_START_Msk | + R_DSILINK_VMSCR_STOP_Msk | + R_DSILINK_VMSCR_VIRDY_Msk | + R_DSILINK_VMSCR_TIMERR_Msk | + R_DSILINK_VMSCR_VBUFUDF_Msk | + R_DSILINK_VMSCR_VBUFOVF_Msk; + R_DSILINK->RXSCR = R_DSILINK_RXSCR_BTAREND_Msk | + R_DSILINK_RXSCR_LRXHTO_Msk | + R_DSILINK_RXSCR_TATO_Msk | + R_DSILINK_RXSCR_RXRESP_Msk | + R_DSILINK_RXSCR_RXEOTP_Msk | + R_DSILINK_RXSCR_RXTE_Msk | + R_DSILINK_RXSCR_RXACK_Msk | + R_DSILINK_RXSCR_EXTEDET_Msk | + R_DSILINK_RXSCR_MLFERR_Msk | + R_DSILINK_RXSCR_ECCERRM_Msk | + R_DSILINK_RXSCR_UNEXERR_Msk | + R_DSILINK_RXSCR_WCERR_Msk | + R_DSILINK_RXSCR_CRCERR_Msk | + R_DSILINK_RXSCR_IBERR_Msk | + R_DSILINK_RXSCR_RXOVFERR_Msk | + R_DSILINK_RXSCR_PRTOERR_Msk | + R_DSILINK_RXSCR_NORESERR_Msk | + R_DSILINK_RXSCR_RSIZEERR_Msk | + R_DSILINK_RXSCR_ECCERRS_Msk | + R_DSILINK_RXSCR_RXAKE_Msk; + + p_ctrl->p_callback_memory = NULL; + p_ctrl->p_callback = p_cfg->p_callback; + + /* Enable interrupts */ + p_ctrl->p_context = p_cfg->p_context; + dsi_isr_enable(&p_extend->dsi_seq0, p_ctrl); + dsi_isr_enable(&p_extend->dsi_seq1, p_ctrl); + dsi_isr_enable(&p_extend->dsi_ferr, p_ctrl); + dsi_isr_enable(&p_extend->dsi_ppi, p_ctrl); + dsi_isr_enable(&p_extend->dsi_rcv, p_ctrl); + dsi_isr_enable(&p_extend->dsi_vin1, p_ctrl); + + /* Mark control block as opened */ + p_ctrl->open = MIPI_DSI_OPEN; + + /* Start high-speed clock and init video */ + dsi_hs_clock_start(p_ctrl); + dsi_init_video(p_cfg); + + /* Notify application that DSI is now open */ + mipi_dsi_callback_args_t callback_args; + callback_args.event = MIPI_DSI_EVENT_POST_OPEN; + callback_args.p_context = p_ctrl->p_context; + dsi_call_callback(p_ctrl, &callback_args); + + return FSP_SUCCESS; +} + +/******************************************************************************************************************//** + * Close MIPI DSI and display data instances, disable interrupts, and power-off the module. + * + * @retval FSP_SUCCESS The channel is successfully closed. + * @retval FSP_ERR_ASSERTION p_api_ctrl is NULL. + * @retval FSP_ERR_NOT_OPEN Instance is not open. + * @retval FSP_ERR_IN_USE Operation in progress and must be stopped before closing. + **********************************************************************************************************************/ +fsp_err_t R_MIPI_DSI_Close (mipi_dsi_ctrl_t * const p_api_ctrl) +{ + mipi_dsi_instance_ctrl_t * p_ctrl = (mipi_dsi_instance_ctrl_t *) p_api_ctrl; + +#if MIPI_DSI_CFG_PARAM_CHECKING_ENABLE + FSP_ASSERT(NULL != p_ctrl); + FSP_ERROR_RETURN(MIPI_DSI_OPEN == p_ctrl->open, FSP_ERR_NOT_OPEN); +#endif + + /* Ensure video has stopped first */ + fsp_err_t err = dsi_stop(p_ctrl); + FSP_ERROR_RETURN(FSP_SUCCESS == err, err); + + dsi_hs_clock_stop(p_ctrl); + + mipi_dsi_cfg_t const * p_cfg = p_ctrl->p_cfg; + mipi_dsi_extended_cfg_t * p_extend = (mipi_dsi_extended_cfg_t *) p_cfg->p_extend; + dsi_isr_disable(&p_extend->dsi_seq0); + dsi_isr_disable(&p_extend->dsi_seq1); + dsi_isr_disable(&p_extend->dsi_ferr); + dsi_isr_disable(&p_extend->dsi_ppi); + dsi_isr_disable(&p_extend->dsi_rcv); + dsi_isr_disable(&p_extend->dsi_vin1); + + /* Close MIPI PHY */ + r_mipi_phy_close(p_cfg->p_mipi_phy_instance->p_ctrl); + + /* Set control block to closed */ + p_ctrl->open = 0U; + + /* Stop clocks to the MIPI DSI peripheral */ + R_BSP_MODULE_STOP(FSP_IP_MIPI_DSI, 0); + + return err; +} + +/******************************************************************************************************************//** + * Start video output. + * Initialize Video Output Registers + * Perform sequence steps 3 to 5 from section 58.3.6.1 in RA8D1 hardware manual R01UH0995EJ0060. + * + * @retval FSP_SUCCESS Data is successfully written to the D/A Converter. + * @retval FSP_ERR_ASSERTION p_api_ctrl is NULL. + * @retval FSP_ERR_NOT_OPEN Instance is not open. + * @retval FSP_ERR_IN_USE The physical interface is currently in use. + * @retval FSP_ERR_INVALID_STATE DSI is already in video mode. + **********************************************************************************************************************/ +fsp_err_t R_MIPI_DSI_Start (mipi_dsi_ctrl_t * const p_api_ctrl) +{ + mipi_dsi_instance_ctrl_t * p_ctrl = (mipi_dsi_instance_ctrl_t *) p_api_ctrl; + +#if MIPI_DSI_CFG_PARAM_CHECKING_ENABLE + FSP_ASSERT(p_ctrl); + FSP_ERROR_RETURN(MIPI_DSI_OPEN == p_ctrl->open, FSP_ERR_NOT_OPEN); + FSP_ERROR_RETURN(!g_video_started, FSP_ERR_INVALID_STATE); +#endif + + /* Notify application that DSI is now open */ + mipi_dsi_callback_args_t callback_args; + callback_args.event = MIPI_DSI_EVENT_PRE_START; + callback_args.p_context = p_ctrl->p_context; + dsi_call_callback(p_ctrl, &callback_args); + + /* Do not start video if sequence operation is in progress */ + FSP_ERROR_RETURN(!(R_DSILINK->LINKSR_b.SQ0RUN) && !(R_DSILINK->LINKSR_b.SQ1RUN), FSP_ERR_IN_USE); + + mipi_dsi_cfg_t const * p_cfg = p_ctrl->p_cfg; + R_DSILINK->VMSET0R = + (((uint32_t) p_cfg->hsa_no_lp << R_DSILINK_VMSET0R_HSANOLP_Pos) & R_DSILINK_VMSET0R_HSANOLP_Msk) | + (((uint32_t) p_cfg->hbp_no_lp << R_DSILINK_VMSET0R_HBPNOLP_Pos) & R_DSILINK_VMSET0R_HBPNOLP_Msk) | + (((uint32_t) p_cfg->hfp_no_lp << R_DSILINK_VMSET0R_HFPNOLP_Pos) & R_DSILINK_VMSET0R_HFPNOLP_Msk) | + R_DSILINK_VMSET0R_VSTART_Msk; + + while ((R_DSILINK->VMSR_b.VIRDY != 1) && !g_video_started) + { + /* Wait for video mode ready status + * NOTE: VMSR may be modified in isr */ + } + + g_video_started = true; + + return FSP_SUCCESS; +} + +/******************************************************************************************************************//** + * Stop video output. + * + * @retval FSP_SUCCESS Data is successfully written to the D/A Converter. + * @retval FSP_ERR_ASSERTION p_api_ctrl is NULL. + * @retval FSP_ERR_NOT_OPEN Instance is not open. + * @retval FSP_ERR_IN_USE DSI cannot be closed while ULPS is active. + **********************************************************************************************************************/ +fsp_err_t R_MIPI_DSI_Stop (mipi_dsi_ctrl_t * const p_api_ctrl) +{ + mipi_dsi_instance_ctrl_t * p_ctrl = (mipi_dsi_instance_ctrl_t *) p_api_ctrl; + +#if MIPI_DSI_CFG_PARAM_CHECKING_ENABLE + FSP_ASSERT(p_ctrl); + FSP_ERROR_RETURN(MIPI_DSI_OPEN == p_ctrl->open, FSP_ERR_NOT_OPEN); +#endif + + return dsi_stop(p_ctrl); +} + +/******************************************************************************************************************//** + * Enter Ultra-low Power State (ULPS). + * + * @retval FSP_SUCCESS Information read successfully. + * @retval FSP_ERR_ASSERTION p_api_ctrl is NULL. + * @retval FSP_ERR_NOT_OPEN Instance is not open. + * @retval FSP_ERR_INVALID_MODE Invalid mode for transition. + * + **********************************************************************************************************************/ +fsp_err_t R_MIPI_DSI_UlpsEnter (mipi_dsi_ctrl_t * const p_api_ctrl, mipi_dsi_lane_t lane) +{ + mipi_dsi_instance_ctrl_t * p_ctrl = (mipi_dsi_instance_ctrl_t *) p_api_ctrl; + +#if MIPI_DSI_CFG_PARAM_CHECKING_ENABLE + FSP_ASSERT(NULL != p_ctrl); + FSP_ERROR_RETURN(MIPI_DSI_OPEN == p_ctrl->open, FSP_ERR_NOT_OPEN); + + /* Clock lane cannot enter ULPS when Continuous CLock mode is active */ + FSP_ERROR_RETURN(!((MIPI_DSI_LANE_CLOCK & lane) && R_DSILINK->HSCLKSETR_b.HSCLMD), FSP_ERR_INVALID_MODE); +#endif + + /* Do not set 'enter ULPS' bit if lane is already in ULPS */ + uint32_t ulpscr = ((MIPI_DSI_LANE_DATA_ALL & lane) && !p_ctrl->data_ulps_active) ? R_DSILINK_ULPSCR_DLENT_Msk : 0; + ulpscr |= + ((MIPI_DSI_LANE_CLOCK & lane) && !p_ctrl->clock_ulps_active) ? R_DSILINK_ULPSCR_CLENT_Msk : 0; + p_ctrl->ulps_status |= lane; + + p_ctrl->clock_ulps_active = p_ctrl->clock_ulps_active || (MIPI_DSI_LANE_CLOCK & lane); + p_ctrl->data_ulps_active = p_ctrl->data_ulps_active || (MIPI_DSI_LANE_DATA_ALL & lane); + + R_DSILINK->ULPSCR = ulpscr; + + return FSP_SUCCESS; +} + +/******************************************************************************************************************//** + * Exit Ultra-low Power State (ULPS). + * + * @retval FSP_SUCCESS Information read successfully. + * @retval FSP_ERR_ASSERTION p_api_ctrl is NULL. + * @retval FSP_ERR_NOT_OPEN Instance is not open. + * + **********************************************************************************************************************/ +fsp_err_t R_MIPI_DSI_UlpsExit (mipi_dsi_ctrl_t * const p_api_ctrl, mipi_dsi_lane_t lane) +{ + mipi_dsi_instance_ctrl_t * p_ctrl = (mipi_dsi_instance_ctrl_t *) p_api_ctrl; +#if MIPI_DSI_CFG_PARAM_CHECKING_ENABLE + FSP_ASSERT(NULL != p_ctrl); + FSP_ERROR_RETURN(MIPI_DSI_OPEN == p_ctrl->open, FSP_ERR_NOT_OPEN); +#endif + + /* Do not set 'exit ULPS' bit if lane is not in ULPS */ + uint32_t ulpscr = ((MIPI_DSI_LANE_DATA_ALL & lane) && p_ctrl->data_ulps_active) ? R_DSILINK_ULPSCR_DLEXIT_Msk : 0; + ulpscr |= + ((MIPI_DSI_LANE_CLOCK & lane) && p_ctrl->clock_ulps_active) ? R_DSILINK_ULPSCR_CLEXIT_Msk : 0; + + p_ctrl->clock_ulps_active = p_ctrl->clock_ulps_active && !(MIPI_DSI_LANE_CLOCK & lane); + p_ctrl->data_ulps_active = p_ctrl->data_ulps_active && !(MIPI_DSI_LANE_DATA_ALL & lane); + + R_DSILINK->ULPSCR = ulpscr; + p_ctrl->ulps_status &= ~lane; + + return FSP_SUCCESS; +} + +/******************************************************************************************************************//** + * Send a command to the peripheral device. + * + * @note p_data will be used as either write data or a read buffer depending on the data id. + * @note p_data memory must not be updated until sequence operation is complete if byte_count is greater than 16. + * + * @retval FSP_SUCCESS Command(s) queued successfully. + * @retval FSP_ERR_ASSERTION p_api_ctrl is NULL. + * cmd_id specifies a long packet but p_data is NULL. + * @retval FSP_ERR_NOT_OPEN Instance is not open. + * @retval FSP_ERR_IN_USE The physical interface is currently in use or video mode is in operation. + * @retval FSP_ERR_INVALID_POINTER Invalid pointer provided + * @retval FSP_ERR_INVALID_ARGUMENT Invalid message configuration + * @retval FSP_ERR_INVALID_CHANNEL Invalid channel for provided message configuration + **********************************************************************************************************************/ +fsp_err_t R_MIPI_DSI_Command (mipi_dsi_ctrl_t * const p_api_ctrl, mipi_dsi_cmd_t * p_cmd) +{ +#if MIPI_DSI_CFG_PARAM_CHECKING_ENABLE + mipi_dsi_instance_ctrl_t * p_ctrl = (mipi_dsi_instance_ctrl_t *) p_api_ctrl; + + FSP_ASSERT(NULL != p_ctrl); + FSP_ERROR_RETURN(p_cmd, FSP_ERR_INVALID_POINTER); + FSP_ERROR_RETURN(MIPI_DSI_OPEN == p_ctrl->open, FSP_ERR_NOT_OPEN); + FSP_ERROR_RETURN(p_cmd->p_tx_buffer || (p_cmd->tx_len == 0), FSP_ERR_INVALID_ARGUMENT); // Tx buffer must be supplied for non-zero Tx length + + FSP_ERROR_RETURN(!((p_cmd->channel == 0) && (p_cmd->tx_len > MIPI_MAX_CH0_CMD)), FSP_ERR_INVALID_ARGUMENT); // Max Tx size is 128 for channel 0 + FSP_ERROR_RETURN(!((p_cmd->channel == 1) && (p_cmd->tx_len > MIPI_MAX_CH1_CMD)), FSP_ERR_INVALID_ARGUMENT); // Max Tx size is 1k for channel 1 + + /* AUX Operation */ + bool aux = (p_cmd->flags & MIPI_DSI_CMD_FLAG_AUX_OPERATION); + if (aux) + { + bool bta = p_cmd->flags & + (MIPI_DSI_CMD_FLAG_BTA | MIPI_DSI_CMD_FLAG_BTA_READ | MIPI_DSI_CMD_FLAG_BTA_NO_WRITE); + bool initial_skew = (p_cmd->flags & MIPI_DSI_CMD_FLAG_ACT_CODE_INITIAL_SKEW_CAL); + bool periodic_skew = (p_cmd->flags & MIPI_DSI_CMD_FLAG_ACT_CODE_PERIODIC_SKEW_CAL); + FSP_ERROR_RETURN(!bta && !p_cmd->tx_len, FSP_ERR_INVALID_ARGUMENT); + FSP_ERROR_RETURN(!R_DSILINK->LINKSR_b.VRUN, FSP_ERR_INVALID_ARGUMENT); // Aux operation is prohibited when video mode is running + FSP_ERROR_RETURN(!(initial_skew || periodic_skew) || (p_cmd->channel != 0), FSP_ERR_INVALID_ARGUMENT); // Periodic and Initial skew must be HS + } + + uint8_t lp = (0 != (p_cmd->flags & MIPI_DSI_CMD_FLAG_LOW_POWER)); + + FSP_ERROR_RETURN(!(lp && R_DSILINK->LINKSR_b.VRUN), FSP_ERR_IN_USE); // LP not allowed during video mode operation. See RA8D1 UM 58.2.61 (R01UH0995EJ0060) + FSP_ERROR_RETURN(!(lp && (p_cmd->channel != 0)), FSP_ERR_INVALID_CHANNEL); // LP only allowed on channel 0 +#else + FSP_PARAMETER_NOT_USED(p_api_ctrl); +#endif + + /* Do not modify registers if sequence operation is currently in progress */ + FSP_ERROR_RETURN(!(R_DSILINK->LINKSR_b.SQ0RUN) && !(R_DSILINK->LINKSR_b.SQ1RUN), FSP_ERR_IN_USE); + + uint32_t * p_sequence_reg = (uint32_t *) (&R_DSILINK->SQCH0DSC0AR); + p_sequence_reg += (p_cmd->channel * 0x80) / 4; // NOLINT(readability-magic-numbers) + *p_sequence_reg++ = dsi_cmd_sequence_register_a(p_cmd); + *p_sequence_reg++ = dsi_cmd_sequence_register_b(p_cmd); + *p_sequence_reg++ = dsi_cmd_sequence_register_c(p_cmd); + *p_sequence_reg++ = dsi_cmd_sequence_register_d(p_cmd); + + /* Start sequence operation */ + R_DSILINK->SQCH0SET0R = (bool) (0 == p_cmd->channel); + R_DSILINK->SQCH1SET0R = (bool) (1 == p_cmd->channel); + + return FSP_SUCCESS; +} + +/******************************************************************************************************************//** + * Provide information about current MIPI DSI status. + * + * Note: Acknowledge and Error Status is only cleared when read by calling this function. + * + * @retval FSP_SUCCESS Information read successfully. + * @retval FSP_ERR_ASSERTION p_api_ctrl is NULL. + * @retval FSP_ERR_NOT_OPEN Instance is not open. + * + **********************************************************************************************************************/ +fsp_err_t R_MIPI_DSI_StatusGet (mipi_dsi_ctrl_t * const p_api_ctrl, mipi_dsi_status_t * p_status) +{ +#if MIPI_DSI_CFG_PARAM_CHECKING_ENABLE + mipi_dsi_instance_ctrl_t * p_ctrl = (mipi_dsi_instance_ctrl_t *) p_api_ctrl; + FSP_ASSERT(NULL != p_ctrl); + FSP_ASSERT(NULL != p_status); + FSP_ERROR_RETURN(MIPI_DSI_OPEN == p_ctrl->open, FSP_ERR_NOT_OPEN); +#else + FSP_PARAMETER_NOT_USED(p_api_ctrl); +#endif + + p_status->link_status = (mipi_dsi_link_status_t) R_DSILINK->LINKSR; + p_status->ack_err_latest.bits = R_DSILINK->AKEPLATIR; + p_status->ack_err_accumulated.bits = R_DSILINK->AKEPACMSR; + + /* Clear accumulated error bits after reading */ + R_DSILINK->AKEPSCR = p_status->ack_err_accumulated.bits; + + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * @} (end addtogroup MIPI_DSI) + **********************************************************************************************************************/ + +/*******************************************************************************************************************//** + * Stop DSI operation. Basic parameter checking to be performed by caller. + * + * @param[in] p_ctrl Pointer to instance control structure + * + * @retval FSP_SUCCESS DSI stopped successfully. + * @retval FSP_ERR_IN_USE DSI cannot be stopped in ULPS. + **********************************************************************************************************************/ +static fsp_err_t dsi_stop (mipi_dsi_instance_ctrl_t * p_ctrl) +{ +#if MIPI_DSI_CFG_PARAM_CHECKING_ENABLE + FSP_ERROR_RETURN(!p_ctrl->ulps_status, FSP_ERR_IN_USE); +#else + FSP_PARAMETER_NOT_USED(p_ctrl); +#endif + + /* Check if running first else the stop operation may stall indefinitely */ + if (R_DSILINK->VMSR_b.RUNNING) + { + /* Initiate stop video output and wait */ + R_DSILINK->VMSET0R_b.VSTOP = 1U; + + while ((R_DSILINK->VMSR_b.STOP != 1) && g_video_started) + { + /* Wait for video mode stop + * - VMSR.STOP must be zero before proceeding to stop GLCDC + * NOTE: VMSR may be modified in isr */ + } + + g_video_started = false; + + /* Clear any stale VMSR status */ + R_DSILINK->VMSCR = R_DSILINK->VMSR; + } + + return FSP_SUCCESS; +} + +/*********************************************************************************************************************** + * Returns configuration values for Sequence Register A + * + * @param[in] p_cmd Pointer to formatted message structure + **********************************************************************************************************************/ +static uint32_t dsi_cmd_sequence_register_a (mipi_dsi_cmd_t * p_cmd) +{ + /* + * Long write packets contain the word count in header bytes 1 and 2. + * The payload follows the header and is word count bytes long. + * + * Short write packets encode up to two parameters in header bytes 1 + * and 2. + */ + uint8_t short_data[2]; + bool long_packet = DSI_PACKET_FORMAT_IS_LONG(p_cmd->cmd_id); + if (long_packet) + { + short_data[0] = (p_cmd->tx_len >> 0) & 0xFFU; // NOLINT(readability-magic-numbers) + short_data[1] = (p_cmd->tx_len >> 8) & 0xFFU; // NOLINT(readability-magic-numbers) + } + else + { + short_data[0] = (p_cmd->tx_len > 0) ? p_cmd->p_tx_buffer[0] : 0U; + short_data[1] = (p_cmd->tx_len > 1) ? p_cmd->p_tx_buffer[1] : 0U; + } + + uint8_t bta = + (p_cmd->flags & (MIPI_DSI_CMD_FLAG_BTA | MIPI_DSI_CMD_FLAG_BTA_READ | MIPI_DSI_CMD_FLAG_BTA_NO_WRITE)); + + uint8_t lp = (0 != (p_cmd->flags & MIPI_DSI_CMD_FLAG_LOW_POWER)); + uint32_t sequence_register_a = + (((uint32_t) short_data[0] << R_DSILINK_SQCH0DSC0AR_DATA0_Pos) & R_DSILINK_SQCH0DSC0AR_DATA0_Msk) | + (((uint32_t) short_data[1] << R_DSILINK_SQCH0DSC0AR_DATA1_Pos) & R_DSILINK_SQCH0DSC0AR_DATA1_Msk) | + (((uint32_t) p_cmd->cmd_id << R_DSILINK_SQCH0DSC0AR_DT_Pos) & R_DSILINK_SQCH0DSC0AR_DT_Msk) | + (((uint32_t) p_cmd->channel << R_DSILINK_SQCH0DSC0AR_VC_Pos) & R_DSILINK_SQCH0DSC0AR_VC_Msk) | + (((uint32_t) long_packet << R_DSILINK_SQCH0DSC0AR_FMT_Pos) & R_DSILINK_SQCH0DSC0AR_FMT_Msk) | + (((uint32_t) lp << R_DSILINK_SQCH0DSC0AR_SPD_Pos) & R_DSILINK_SQCH0DSC0AR_SPD_Msk) | + (((uint32_t) bta << R_DSILINK_SQCH0DSC0AR_BTA_Pos) & R_DSILINK_SQCH0DSC0AR_BTA_Msk) | + (((uint32_t) 0 << R_DSILINK_SQCH0DSC0AR_NXACT_Pos) & R_DSILINK_SQCH0DSC0AR_NXACT_Msk); + + return sequence_register_a; +} + +/*********************************************************************************************************************** + * Returns configuration values for Sequence Register B + * + * @param[in] p_cmd Pointer to formatted message structure + **********************************************************************************************************************/ +static uint32_t dsi_cmd_sequence_register_b (mipi_dsi_cmd_t * p_cmd) +{ + FSP_PARAMETER_NOT_USED(p_cmd); + + /* Use sequence RAM */ + return (1 << R_DSILINK_SQCH0DSC0BR_DTSEL_Pos) & R_DSILINK_SQCH0DSC0BR_DTSEL_Msk; +} + +/*********************************************************************************************************************** + * Returns configuration values for Sequence Register C + * + * @param[in] p_cmd Pointer to formatted message structure + **********************************************************************************************************************/ +static uint32_t dsi_cmd_sequence_register_c (mipi_dsi_cmd_t * p_cmd) +{ + bool aux_operation = (p_cmd->flags & MIPI_DSI_CMD_FLAG_AUX_OPERATION); + bool actcode = aux_operation ? (p_cmd->flags & 0xF) : 0; // Always store Rx result in slot 0 + uint32_t sequence_register_c = + (((uint32_t) 0 << R_DSILINK_SQCH0DSC0CR_FINACT_Pos) & R_DSILINK_SQCH0DSC0CR_FINACT_Msk) | + (((uint32_t) aux_operation << R_DSILINK_SQCH0DSC0CR_AUXOP_Pos) & R_DSILINK_SQCH0DSC0CR_AUXOP_Msk) | + (((uint32_t) actcode << R_DSILINK_SQCH0DSC0CR_ACTCODE_Pos) & R_DSILINK_SQCH0DSC0CR_ACTCODE_Msk); + + return sequence_register_c; +} + +/*********************************************************************************************************************** + * Returns configuration values for Sequence Register D + * + * @param[in] p_cmd Pointer to formatted message structure + **********************************************************************************************************************/ +uint32_t dsi_cmd_sequence_register_d (mipi_dsi_cmd_t * p_cmd) +{ + uint8_t bta = + (p_cmd->flags & (MIPI_DSI_CMD_FLAG_BTA | MIPI_DSI_CMD_FLAG_BTA_READ | MIPI_DSI_CMD_FLAG_BTA_NO_WRITE)); + + return (uint32_t) (bta ? p_cmd->p_rx_buffer : p_cmd->p_tx_buffer); // This buffer address is used for both Tx and Rx. +} + +/*******************************************************************************************************************//** + * Calls user callback + * + * @param[in] p_ctrl Pointer to MIPI DSI instance control block + * @param[in] p_args Pointer to arguments on stack + **********************************************************************************************************************/ +static void dsi_call_callback (mipi_dsi_instance_ctrl_t * p_ctrl, mipi_dsi_callback_args_t * p_args) +{ + mipi_dsi_callback_args_t args; + + /* Store callback arguments in memory provided by user if available. This allows callback arguments to be + * stored in non-secure memory so they can be accessed by a non-secure callback function. */ + mipi_dsi_callback_args_t * p_args_memory = p_ctrl->p_callback_memory; + if (NULL == p_args_memory) + { + /* Use provided args struct on stack */ + p_args_memory = p_args; + } + else + { + /* Save current arguments on the stack in case this is a nested interrupt. */ + args = *p_args_memory; + + /* Copy the stacked args to callback memory */ + *p_args_memory = *p_args; + } + +#if BSP_TZ_SECURE_BUILD + + /* p_callback can point to a secure function or a non-secure function. */ + if (!cmse_is_nsfptr(p_ctrl->p_callback)) + { + /* If p_callback is secure, then the project does not need to change security state. */ + p_ctrl->p_callback(p_args_memory); + } + else + { + /* If p_callback is Non-secure, then the project must change to Non-secure state in order to call the callback. */ + mipi_dsi_prv_ns_callback p_callback = (mipi_dsi_prv_ns_callback) (p_ctrl->p_callback); + p_callback(p_args_memory); + } +#else + + /* If the project is not Trustzone Secure, then it will never need to change security state in order to call the callback. */ + p_ctrl->p_callback(p_args_memory); +#endif + + if (NULL != p_ctrl->p_callback_memory) + { + /* Restore callback memory in case this is a nested interrupt. */ + *p_ctrl->p_callback_memory = args; + } +} + +/*******************************************************************************************************************//** + * Private helper functions + **********************************************************************************************************************/ + +/*******************************************************************************************************************//** + * Enter Reset + * Perform sequence steps 1 to 3 from section 58.3.2 in RA8D1 hardware manual R01UH0995EJ0060. + **********************************************************************************************************************/ +static void dsi_enter_reset () +{ + /* Enable clock lane */ + R_DSILINK->TXSETR_b.CLEN = 1U; + + /* Enter the DSI Host software reset state */ + R_DSILINK->RSTCR_b.SWRST = 1; + + /* Wait for reset process to start - Polling RSTSR is okay since it's not updated in interrupt.*/ + FSP_HARDWARE_REGISTER_WAIT((R_DSILINK->RSTSR & MIPI_DSI_RSRST_RESET_BITS), MIPI_DSI_RSRST_RESET_BITS); +} + +/*******************************************************************************************************************//** + * Initialize timing registers from configuration data + * - Perform sequence step 4 from section 58.3.2 in RA8D1 hardware manual R01UH0995EJ0060. + * + * @param[in] p_cfg Pointer to MIPI DSI configuration structure + **********************************************************************************************************************/ +static void dsi_init_timing (mipi_dsi_cfg_t const * const p_cfg) +{ + /* Enable clock and data lanes and set number of lanes to use */ + R_DSILINK->TXSETR = R_DSILINK_TXSETR_DLEN_Msk | R_DSILINK_TXSETR_CLEN_Msk | (p_cfg->num_lanes - 1); + + /* Set ULPS wakeup period */ + R_DSILINK->ULPSSETR_b.WKUP = p_cfg->ulps_wakeup_period; + + /* Set data scrambling and/or EoTp transmission */ +#define DSILINK_DSISETR_VCCRCEN_Msk (R_DSILINK_DSISETR_VC0CRCEN_Msk | \ + R_DSILINK_DSISETR_VC1CRCEN_Msk | \ + R_DSILINK_DSISETR_VC2CRCEN_Msk | \ + R_DSILINK_DSISETR_VC3CRCEN_Msk) + R_DSILINK->DSISETR = + ((p_cfg->max_return_packet_size << R_DSILINK_DSISETR_MRPSZ_Pos) & R_DSILINK_DSISETR_MRPSZ_Msk) | + (((uint32_t) p_cfg->ecc_enable << R_DSILINK_DSISETR_ECCEN_Pos) & R_DSILINK_DSISETR_ECCEN_Msk) | + (((uint32_t) p_cfg->crc_check_mask << R_DSILINK_DSISETR_VC0CRCEN_Pos) & DSILINK_DSISETR_VCCRCEN_Msk) | + (((uint32_t) p_cfg->scramble_enable << R_DSILINK_DSISETR_SCREN_Pos) & R_DSILINK_DSISETR_SCREN_Msk) | + (((uint32_t) p_cfg->tearing_detect << R_DSILINK_DSISETR_EXTEMD_Pos) & R_DSILINK_DSISETR_EXTEMD_Msk) | + (((uint32_t) p_cfg->eotp_enable << R_DSILINK_DSISETR_EOTPEN_Pos) & R_DSILINK_DSISETR_EOTPEN_Msk); + + /* Set LP lane transition timing */ + R_DSILINK->CLSTPTSETR = + ((p_cfg->p_timing->clock_stop_time << R_DSILINK_CLSTPTSETR_CLKSTPT_Pos) & + R_DSILINK_CLSTPTSETR_CLKSTPT_Msk) | + ((p_cfg->p_timing->clock_beforehand_time << R_DSILINK_CLSTPTSETR_CLKBFHT_Pos) & + R_DSILINK_CLSTPTSETR_CLKBFHT_Msk) | + ((p_cfg->p_timing->clock_keep_time << R_DSILINK_CLSTPTSETR_CLKKPT_Pos) & + R_DSILINK_CLSTPTSETR_CLKKPT_Msk); + R_DSILINK->LPTRNSTSETR = p_cfg->p_timing->go_lp_and_back & R_DSILINK_LPTRNSTSETR_GOLPBKT_Msk; + + /* Set timeout values */ + R_DSILINK->PRESPTOBTASETR = p_cfg->bta_timeout; + R_DSILINK->PRESPTOLPSETR = p_cfg->lprw_timeout; + R_DSILINK->PRESPTOHSSETR = p_cfg->hsrw_timeout; + R_DSILINK->HSTXTOSETR = p_cfg->hs_tx_timeout; + R_DSILINK->LRXHTOSETR = p_cfg->lp_rx_timeout; + R_DSILINK->TATOSETR = p_cfg->turnaround_timeout; +} + +/*******************************************************************************************************************//** + * Exit Reset + * Perform sequence steps 5 to 9 from section 58.3.2 in RA8D1 hardware manual R01UH0995EJ0060. + * + * NOTE: Calling this function is prohibited without first calling dsi_enter_reset(), which sets RSTCR.SWRST to 1 + * + * @param[in] p_cfg Pointer to MIPI DSI configuration structure + **********************************************************************************************************************/ +static void dsi_exit_reset (mipi_dsi_cfg_t const * const p_cfg) +{ + /* Transition data lanes to stop state */ + R_DSILINK->RSTCR_b.FTXSTP = 1U; + + /* Wait for data lanes transition to stop state */ + FSP_HARDWARE_REGISTER_WAIT((R_DSILINK->RSTSR & + (R_DSILINK_RSTSR_DL0DIR_Msk | R_DSILINK_RSTSR_DL0STP_Msk | R_DSILINK_RSTSR_DL1STP_Msk)), + (((p_cfg->num_lanes * 2U) - 1U) << R_DSILINK_RSTSR_DL0STP_Pos)); + + /* Clear the Force Tx Stop and Software Reset bits */ + R_DSILINK->RSTCR_b.FTXSTP = 0U; + R_DSILINK->RSTCR_b.SWRST = 0U; + + /* Wait for software reset to complete */ + FSP_HARDWARE_REGISTER_WAIT((R_DSILINK->RSTSR & MIPI_DSI_RSRST_RESET_BITS), 0); +} + +/*******************************************************************************************************************//** + * Initialize High Speed Clock + * Perform sequence steps from section 58.3.3 in RA8D1 hardware manual R01UH0995EJ0060. + * + * @param[in] p_ctrl Pointer to MIPI DSI instance control block + **********************************************************************************************************************/ +static void dsi_hs_clock_start (mipi_dsi_instance_ctrl_t * p_ctrl) +{ + mipi_dsi_cfg_t const * p_cfg = p_ctrl->p_cfg; + + /* Enable clock lane */ + R_DSILINK->TXSETR_b.CLEN = 1U; + g_clock_state = MIPI_DSI_CLOCK_STATE_STARTING; + + /* Enable HS clock and set running mode */ + R_DSILINK->HSCLKSETR = R_DSILINK_HSCLKSETR_HSCLST_Msk | + (p_cfg->continuous_clock ? R_DSILINK_HSCLKSETR_HSCLMD_Msk : 0U); + + while ((R_DSILINK->PLSR_b.CLLP2HS != p_cfg->continuous_clock) && + (g_clock_state != MIPI_DSI_CLOCK_STATE_STARTED)) + { + /* Wait for HS clock notification bit set to 1. (only in the continuous clock mode) + * NOTE: PLSR may be modified in ISR */ + } + + g_clock_state = MIPI_DSI_CLOCK_STATE_STARTED; +} + +/*********************************************************************************************************************** + * De-initialize High Speed Clock + * Perform sequence steps from section 56.3.4 in RA8D1 hardware manual R01UH0995EJ0060. + * + * @param[in] p_ctrl Pointer to MIPI DSI instance control block + **********************************************************************************************************************/ +static void dsi_hs_clock_stop (mipi_dsi_instance_ctrl_t * p_ctrl) +{ + mipi_dsi_cfg_t const * p_cfg = p_ctrl->p_cfg; + + R_DSILINK->HSCLKSETR_b.HSCLST = 0; + g_clock_state = MIPI_DSI_CLOCK_STATE_STOPPING; + + while ((R_DSILINK->PLSR_b.CLHS2LP != p_cfg->continuous_clock) && (g_clock_state != MIPI_DSI_CLOCK_STATE_IDLE)) + { + /* Wait for clock lane transition LP state. + * NOTE: PLSR may be modified in ISR */ + } + + g_clock_state = MIPI_DSI_CLOCK_STATE_IDLE; +} + +/*********************************************************************************************************************** + * Initialize Video Output Registers + * Perform sequence steps 1 and 2 from section 58.3.6.1 in RA8D1 hardware manual R01UH0995EJ0060. + * + * @param[in] p_cfg Pointer to MIPI DSI configuration structure + **********************************************************************************************************************/ +static void dsi_init_video (mipi_dsi_cfg_t const * p_cfg) +{ + R_DSILINK->VMPPSETR = + (((uint32_t) p_cfg->sync_pulse << R_DSILINK_VMPPSETR_TXESYNC_Pos) & R_DSILINK_VMPPSETR_TXESYNC_Msk) | + (((uint32_t) p_cfg->data_type << R_DSILINK_VMPPSETR_DT_Pos) & R_DSILINK_VMPPSETR_DT_Msk) | + (((uint32_t) p_cfg->virtual_channel_id << R_DSILINK_VMPPSETR_VC_Pos) & + R_DSILINK_VMPPSETR_VC_Msk); + R_DSILINK->VMVSSETR = + ((p_cfg->vertical_sync_lines << R_DSILINK_VMVSSETR_VSA_Pos) & R_DSILINK_VMVSSETR_VSA_Msk) | + (((uint32_t) p_cfg->vertical_sync_polarity << R_DSILINK_VMVSSETR_VSPOL_Pos) & + R_DSILINK_VMVSSETR_VSPOL_Msk) | + ((p_cfg->vertical_active_lines << R_DSILINK_VMVSSETR_VACT_Pos) & + R_DSILINK_VMVSSETR_VACT_Msk); + R_DSILINK->VMVPSETR = + ((p_cfg->vertical_back_porch << R_DSILINK_VMVPSETR_VBP_Pos) & R_DSILINK_VMVPSETR_VBP_Msk) | + ((p_cfg->vertical_front_porch << R_DSILINK_VMVPSETR_VFP_Pos) & + R_DSILINK_VMVPSETR_VFP_Msk); + R_DSILINK->VMHSSETR = + ((p_cfg->horizontal_sync_lines << R_DSILINK_VMHSSETR_HSA_Pos) & R_DSILINK_VMHSSETR_HSA_Msk) | + (((uint32_t) p_cfg->horizontal_sync_polarity << R_DSILINK_VMHSSETR_HSPOL_Pos) & + R_DSILINK_VMHSSETR_HSPOL_Msk) | + ((p_cfg->horizontal_active_lines << R_DSILINK_VMHSSETR_HACT_Pos) & + R_DSILINK_VMHSSETR_HACT_Msk); + R_DSILINK->VMHPSETR = + ((p_cfg->horizontal_back_porch << R_DSILINK_VMHPSETR_HBP_Pos) & R_DSILINK_VMHPSETR_HBP_Msk) | + ((p_cfg->horizontal_front_porch << R_DSILINK_VMHPSETR_HFP_Pos) & + R_DSILINK_VMHPSETR_HFP_Msk); + R_DSILINK->VMSET1R = + ((p_cfg->video_mode_delay << R_DSILINK_VMSET1R_DLY_Pos) & R_DSILINK_VMSET1R_DLY_Msk); +} + +/*********************************************************************************************************************** + * Enable the specified ISR and add the control structure to the ISR context lookup table. + * + * @param[in] irq_cfg Pointer to interrupt configuration structure + * @param[in] p_ctrl Pointer to MIPI DSI instance control block + **********************************************************************************************************************/ +static void dsi_isr_enable (mipi_dsi_irq_cfg_t const * irq_cfg, mipi_dsi_instance_ctrl_t * p_ctrl) +{ + R_BSP_IrqCfgEnable(irq_cfg->irq, irq_cfg->ipl, p_ctrl); +} + +/*********************************************************************************************************************** + * Disable the specified ISR + * + * @param[in] irq_cfg Pointer to interrupt configuration structure + **********************************************************************************************************************/ +static void dsi_isr_disable (mipi_dsi_irq_cfg_t const * irq_cfg) +{ + R_BSP_IrqDisable(irq_cfg->irq); + R_FSP_IsrContextSet(irq_cfg->irq, NULL); +} + +/*********************************************************************************************************************** + * Interrupt Service Routines + **********************************************************************************************************************/ + +/*********************************************************************************************************************** + * Sequence 0 ISR + * - Process LP sequence command events and forward them to the user callback + **********************************************************************************************************************/ +void mipi_dsi_seq0 (void) { + /* Save context if RTOS is used */ + FSP_CONTEXT_SAVE; + + /* Clear sequence channel 0 status register bits */ + uint32_t sqch0sr_bits = R_DSILINK->SQCH0SR; + R_DSILINK->SQCH0SCR = sqch0sr_bits; // SIZEERR is reserved for SQCH0SCR and should be read and written as zero + + IRQn_Type irq = R_FSP_CurrentIrqGet(); + R_BSP_IrqStatusClear(irq); + + mipi_dsi_instance_ctrl_t * p_ctrl = (mipi_dsi_instance_ctrl_t *) R_FSP_IsrContextGet(irq); + mipi_dsi_callback_args_t args; + args.event = MIPI_DSI_EVENT_SEQUENCE_0; + args.tx_status = (mipi_dsi_sequence_status_t) sqch0sr_bits; + args.p_context = p_ctrl->p_context; + dsi_call_callback(p_ctrl, &args); + + /* Restore context if RTOS is used */ + FSP_CONTEXT_RESTORE; +} + +/*********************************************************************************************************************** + * Sequence 1 ISR + * - Process HS sequence command events and forward them to the user callback + **********************************************************************************************************************/ +void mipi_dsi_seq1 (void) { + /* Save context if RTOS is used */ + FSP_CONTEXT_SAVE; + + /* Clear sequence channel 1 status register bits */ + uint32_t sqch1sr_bits = R_DSILINK->SQCH1SR; + R_DSILINK->SQCH1SCR = sqch1sr_bits; + + IRQn_Type irq = R_FSP_CurrentIrqGet(); + R_BSP_IrqStatusClear(irq); + + mipi_dsi_instance_ctrl_t * p_ctrl = (mipi_dsi_instance_ctrl_t *) R_FSP_IsrContextGet(irq); + mipi_dsi_callback_args_t args; + args.event = MIPI_DSI_EVENT_SEQUENCE_1; + args.tx_status = (mipi_dsi_sequence_status_t) sqch1sr_bits; + args.p_context = p_ctrl->p_context; + dsi_call_callback(p_ctrl, &args); + + /* Restore context if RTOS is used */ + FSP_CONTEXT_RESTORE; +} + +/*********************************************************************************************************************** + * Video Input ISR + * - Process DSI Video Input Events and forward them to the user callback + **********************************************************************************************************************/ +void mipi_dsi_vin1 (void) { + /* Save context if RTOS is used */ + FSP_CONTEXT_SAVE; + + /* Clear video mode status register bits */ + uint32_t vmsr_bits = R_DSILINK->VMSR; + R_DSILINK->VMSCR = vmsr_bits; + + IRQn_Type irq = R_FSP_CurrentIrqGet(); + R_BSP_IrqStatusClear(irq); + + /* Update internal state */ + mipi_dsi_instance_ctrl_t * p_ctrl = (mipi_dsi_instance_ctrl_t *) R_FSP_IsrContextGet(irq); + if (vmsr_bits & R_DSILINK_VMSR_VIRDY_Msk) + { + g_video_started = true; + } + else if (vmsr_bits & R_DSILINK_VMSR_STOP_Msk) + { + g_video_started = false; + } + else + { + // Nothing + } + + /* Pass data to user */ + mipi_dsi_callback_args_t args; + args.event = MIPI_DSI_EVENT_VIDEO; + args.video_status = (mipi_dsi_video_status_t) vmsr_bits; + args.p_context = p_ctrl->p_context; + dsi_call_callback(p_ctrl, &args); + + /* Perform reset according to RA8D1 UM 58.3.8.6 (R01UH0995EJ0060) */ + if (vmsr_bits & (R_DSILINK_VMSR_VBUFUDF_Msk | R_DSILINK_VMSR_VBUFOVF_Msk)) + { + dsi_enter_reset(); + dsi_exit_reset(p_ctrl->p_cfg); + } + + /* Restore context if RTOS is used */ + FSP_CONTEXT_RESTORE; +} + +/*********************************************************************************************************************** + * Receive ISR + * - Process Receive Events and forward them to the user callback + **********************************************************************************************************************/ +void mipi_dsi_rcv (void) { + /* Save context if RTOS is used */ + FSP_CONTEXT_SAVE; + + /* Clear recieve status register bits */ + uint32_t rxsr_bits = R_DSILINK->RXSR; + R_DSILINK->RXSCR = rxsr_bits; + + IRQn_Type irq = R_FSP_CurrentIrqGet(); + R_BSP_IrqStatusClear(irq); + + mipi_dsi_instance_ctrl_t * p_ctrl = (mipi_dsi_instance_ctrl_t *) R_FSP_IsrContextGet(irq); + mipi_dsi_callback_args_t args; + args.event = MIPI_DSI_EVENT_RECEIVE; + args.rx_status = (mipi_dsi_receive_status_t) rxsr_bits; + args.p_result = (mipi_dsi_receive_result_t *) &R_DSILINK->RXRSS0R; + args.p_context = p_ctrl->p_context; + dsi_call_callback(p_ctrl, &args); + + R_DSILINK->RXRINFOOWSCR = R_DSILINK_RXRINFOOWSCR_SL0OW_Msk; // Clear slot 0 after reading + + /* Restore context if RTOS is used */ + FSP_CONTEXT_RESTORE; +} + +/*********************************************************************************************************************** + * Fatal Error ISR + * - Process Fatal Error Events and forward them to the user callback + **********************************************************************************************************************/ +void mipi_dsi_ferr (void) { + /* Save context if RTOS is used */ + FSP_CONTEXT_SAVE; + + /* Clear recieve status register bits */ + uint32_t ferrsr_bits = R_DSILINK->FERRSR; + R_DSILINK->FERRSCR = ferrsr_bits; + + IRQn_Type irq = R_FSP_CurrentIrqGet(); + R_BSP_IrqStatusClear(irq); + + mipi_dsi_instance_ctrl_t * p_ctrl = (mipi_dsi_instance_ctrl_t *) R_FSP_IsrContextGet(irq); + mipi_dsi_callback_args_t args; + args.event = MIPI_DSI_EVENT_FATAL; + args.fatal_status = (mipi_dsi_fatal_status_t) ferrsr_bits; + args.p_context = p_ctrl->p_context; + dsi_call_callback(p_ctrl, &args); + + /* Restore context if RTOS is used */ + FSP_CONTEXT_RESTORE; +} + +/*********************************************************************************************************************** + * PHY-Protocol Interface ISR + * - Process Phy-Protocol Events and forward them to the user callback + **********************************************************************************************************************/ +void mipi_dsi_ppi (void) { + /* Save context if RTOS is used */ + FSP_CONTEXT_SAVE; + + /* Clear PLSR */ + uint32_t plsr_bits = R_DSILINK->PLSR; + R_DSILINK->PLSCR = plsr_bits; + + IRQn_Type irq = R_FSP_CurrentIrqGet(); + R_BSP_IrqStatusClear(irq); + + /* Update internal state */ + mipi_dsi_instance_ctrl_t * p_ctrl = (mipi_dsi_instance_ctrl_t *) R_FSP_IsrContextGet(irq); + if ((g_clock_state == MIPI_DSI_CLOCK_STATE_STARTING) && + (plsr_bits & R_DSILINK_PLSR_CLLP2HS_Msk)) + { + g_clock_state = MIPI_DSI_CLOCK_STATE_STARTED; + } + else if ((g_clock_state == MIPI_DSI_CLOCK_STATE_STOPPING) && + (plsr_bits & R_DSILINK_PLSR_CLHS2LP_Msk)) + { + g_clock_state = MIPI_DSI_CLOCK_STATE_IDLE; + } + else + { + // Nothing + } + + /* Pass data to user */ + mipi_dsi_callback_args_t args; + args.event = MIPI_DSI_EVENT_PHY; + args.phy_status = (mipi_dsi_phy_status_t) plsr_bits; + args.p_context = p_ctrl->p_context; + dsi_call_callback(p_ctrl, &args); + + /* Restore context if RTOS is used */ + FSP_CONTEXT_RESTORE; +} diff --git a/drivers/ra/fsp/src/r_mipi_phy/r_mipi_phy.c b/drivers/ra/fsp/src/r_mipi_phy/r_mipi_phy.c new file mode 100644 index 0000000..568ca93 --- /dev/null +++ b/drivers/ra/fsp/src/r_mipi_phy/r_mipi_phy.c @@ -0,0 +1,125 @@ +/* +* Copyright (c) 2020 - 2024 Renesas Electronics Corporation and/or its affiliates +* +* SPDX-License-Identifier: BSD-3-Clause +*/ + +/*********************************************************************************************************************** + * Includes + **********************************************************************************************************************/ +#include "r_mipi_phy.h" + +/*********************************************************************************************************************** + * Macro definitions + **********************************************************************************************************************/ +#define MIPI_PHY_OPEN (0x4D504950) + +#define MIPI_DSI_PRV_1MHZ (1000000) + +/*********************************************************************************************************************** + * Typedef definitions + **********************************************************************************************************************/ + +/*********************************************************************************************************************** + * Global variables + **********************************************************************************************************************/ + +const mipi_phy_api_t g_mipi_phy = +{ + .open = r_mipi_phy_open, + .close = r_mipi_phy_close, +}; + +/*********************************************************************************************************************** + * Private function prototypes + **********************************************************************************************************************/ + +/*******************************************************************************************************************//** + * @addtogroup MIPI_PHY + * @{ + **********************************************************************************************************************/ + +/*********************************************************************************************************************** + * Functions + **********************************************************************************************************************/ + +/********************************************************************************************************************** + * Initialize the MIPI DSI peripheral according to section 57.3.1 D-PHY Start-up Procedure, R01UH0995EJ0060 + * + * @retval FSP_SUCCESS The channel was successfully opened. + * @retval FSP_ERR_ASSERTION One or both of the parameters was NULL. + * @retval FSP_ERR_ALREADY_OPEN The instance is already opened. + * @retval FSP_ERR_INVALID_MODE Power control mode must be high-speed-mode. + **********************************************************************************************************************/ +fsp_err_t r_mipi_phy_open (mipi_phy_ctrl_t * const p_api_ctrl, mipi_phy_cfg_t const * const p_cfg) +{ + mipi_phy_ctrl_t * p_ctrl = p_api_ctrl; + + /* Set DPHYREFCR to match PCLKA */ + uint32_t pclka_hz = R_FSP_SystemClockHzGet(FSP_PRIV_CLOCK_PCLKA); + R_DPHYCNT->DPHYREFCR_b.RFREQ = (uint8_t) ((pclka_hz / MIPI_DSI_PRV_1MHZ) - 1); + + /* Start D-PHY LDO and wait for startup */ + R_DPHYCNT->DPHYPWRCR_b.PWRSEN = 1; + FSP_HARDWARE_REGISTER_WAIT((R_DPHYCNT->DPHYSFR & R_DPHYCNT_DPHYSFR_PWRSF_Msk), R_DPHYCNT_DPHYSFR_PWRSF_Msk); + + /* Configure D-PHY PLL and LP frequency divider */ + R_DPHYCNT->DPHYPLFCR = p_cfg->pll_settings.raw; + R_DPHYCNT->DPHYESCCR_b.ESCDIV = p_cfg->lp_divisor; + + /* Start D-PHY PLL and wait for startup */ + R_DPHYCNT->DPHYPLOCR_b.PLLSTP = 0; + FSP_HARDWARE_REGISTER_WAIT((R_DPHYCNT->DPHYSFR & R_DPHYCNT_DPHYSFR_PLLSF_Msk), R_DPHYCNT_DPHYSFR_PLLSF_Msk); + + /* Set D-PHY timing parameters */ + mipi_phy_timing_t const * p_timing = p_cfg->p_timing; + R_DPHYCNT->DPHYTIM1 = p_timing->t_init; + R_DPHYCNT->DPHYTIM2 = p_timing->t_clk_prep; + R_DPHYCNT->DPHYTIM3 = p_timing->t_hs_prep; + R_DPHYCNT->DPHYTIM4 = p_timing->dphytim4; + R_DPHYCNT->DPHYTIM5 = p_timing->dphytim5; + R_DPHYCNT->DPHYTIM6 = p_timing->t_lp_exit; + + /* Enable D-PHY */ + R_DPHYCNT->DPHYOCR_b.DPHYEN = 1U; + + /* Keep track of p_cfg struct */ + p_ctrl->p_cfg = p_cfg; + + /* Mark control block as opened */ + p_ctrl->open = MIPI_PHY_OPEN; + + return FSP_SUCCESS; +} + +/********************************************************************************************************************** + * Stop filter operations and close the channel instance. + * + * NOTE: D_PHY must be stopped and LDO disabled before entering standby mode. See 56.3.2 D-PHY Stop Procedure, R01UH0995EJ0060 + * + * @retval FSP_SUCCESS The channel is successfully closed. + * @retval FSP_ERR_ASSERTION p_api_ctrl is NULL. + * @retval FSP_ERR_NOT_OPEN Instance is not open. + **********************************************************************************************************************/ +fsp_err_t r_mipi_phy_close (mipi_phy_ctrl_t * const p_api_ctrl) +{ + mipi_phy_ctrl_t * p_ctrl = p_api_ctrl; + + /* Disable D-PHY */ + R_DPHYCNT->DPHYOCR_b.DPHYEN = 0; + + /* Disable D-PHY PLL */ + R_DPHYCNT->DPHYPLOCR_b.PLLSTP = 1; + + /* Disable MIPI LDO */ + R_DPHYCNT->DPHYPWRCR_b.PWRSEN = 0; + + /* Set control block to closed */ + p_ctrl->open = 0U; + + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * @} (end addtogroup MIPI_PHY) + **********************************************************************************************************************/ diff --git a/zephyr/ra/ra_cfg/fsp_cfg/r_mipi_dsi_cfg.h b/zephyr/ra/ra_cfg/fsp_cfg/r_mipi_dsi_cfg.h new file mode 100644 index 0000000..2b59f44 --- /dev/null +++ b/zephyr/ra/ra_cfg/fsp_cfg/r_mipi_dsi_cfg.h @@ -0,0 +1,18 @@ +/* +* Copyright (c) 2020 - 2024 Renesas Electronics Corporation and/or its affiliates +* +* SPDX-License-Identifier: BSD-3-Clause +*/ + +#ifndef R_MIPI_DSI_CFG_H_ +#define R_MIPI_DSI_CFG_H_ +#ifdef __cplusplus +extern "C" { +#endif + +#define MIPI_DSI_CFG_PARAM_CHECKING_ENABLE ((BSP_CFG_PARAM_CHECKING_ENABLE)) + +#ifdef __cplusplus +} +#endif +#endif /* R_MIPI_DSI_CFG_H_ */