ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
ra8_mipi_dsi_cmd.c
Go to the documentation of this file.
1
34
35#include <stddef.h>
36#include <stdint.h>
37#include <string.h>
38
39#include "ra8_attributes.h"
40#include "ra8_check.h"
41#include "ra8_err.h"
42#include "ra8_log.h"
43#include "ra8_mipi_dsi.h"
45#include "ra8_mipi_dsi_regs.h"
46
56static const char* s_tag = "MIPI_DSI";
57
67typedef enum : uint32_t {
70
71/* =============================================================================
72 * Command-path helpers
73 * =============================================================================
74 */
75
92{
93 uint8_t data0 = 0U;
94 uint8_t data1 = 0U;
95 /* Long packets put the word count in DATA0/DATA1; short packets put
96 * the first two parameter bytes there. */
97 const uint8_t low_nibble = (uint8_t)((uint32_t)cmd->cmd_id & k_dsi_cmd_id_mask);
98 const bool is_long = low_nibble > 0x08U;
99 if (is_long) {
100 data0 = (uint8_t)(cmd->tx_len & k_ra8_mipi_dsi_byte_mask);
101 data1 = (uint8_t)((cmd->tx_len >> (uint32_t)k_shift_8) & k_ra8_mipi_dsi_byte_mask);
102 } else {
103 if ((cmd->p_tx_buffer != nullptr) && (cmd->tx_len > 0U)) {
104 data0 = cmd->p_tx_buffer[0];
105 }
106 if ((cmd->p_tx_buffer != nullptr) && (cmd->tx_len > 1U)) {
107 data1 = cmd->p_tx_buffer[1];
108 }
109 }
110
111 /* HUM Ch 65.2 "SQCH0DSC0AR : Sequence Channel 0 Descriptor 0 Setting A", p 3925 */
112 uint32_t v =
113 (((uint32_t)data0 & k_ra8_mipi_dsi_byte_mask) << (uint32_t)k_ra8_mipi_dsi_dsc0a_shift_data0) |
114 (((uint32_t)data1 & k_ra8_mipi_dsi_byte_mask) << (uint32_t)k_ra8_mipi_dsi_dsc0a_shift_data1) |
115 (((uint32_t)cmd->cmd_id & k_ra8_mipi_dsi_dt_mask) << (uint32_t)k_ra8_mipi_dsi_dsc0a_shift_dt) |
116 (((uint32_t)cmd->virtual_channel & k_ra8_mipi_dsi_vc_mask)
117 << (uint32_t)k_ra8_mipi_dsi_dsc0a_shift_vc);
118 if (is_long) {
119 v |= (1UL << (uint32_t)k_ra8_mipi_dsi_dsc0a_shift_fmt);
120 }
121 if (cmd->low_power) {
122 v |= (1UL << (uint32_t)k_ra8_mipi_dsi_dsc0a_shift_spd);
123 }
124 v |= (((uint32_t)cmd->bta & k_ra8_mipi_dsi_bta_mask) << (uint32_t)k_ra8_mipi_dsi_dsc0a_shift_bta);
125 return v;
126}
127
144{
145 uint32_t v = k_ra8_mipi_dsi_dsc0c_finact;
146 if (cmd->aux_operation) {
148 v |= (((uint32_t)cmd->action_code) << k_ra8_mipi_dsi_dsc0c_actcode_shift) &
150 }
151 return v;
152}
153
168RA8_INTERNAL static void internal_ra8_mipi_dsi_stage_payload(const uint8_t* data, uint16_t len)
169{
170 volatile r_mipi_dsi_regs_t* reg = ra8_mipi_dsi();
171 uint32_t words[4] = {0U, 0U, 0U, 0U};
172 const uint16_t cap = k_ra8_mipi_dsi_payload_max;
173 const uint16_t eff = (len < cap) ? len : cap;
174 for (uint16_t i = 0U; i < eff; ++i) {
175 const uint16_t word_idx = (uint16_t)(i / 4U);
176 const uint16_t byte_idx = (uint16_t)(i % 4U);
177 words[word_idx] |= ((uint32_t)data[i]) << (byte_idx * (uint32_t)k_shift_8);
178 }
179 /* HUM Ch 65.2 "TXPPD0R : Transmit Packet Payload Data 0", p 3849 */
180 reg->TXPPD0R = words[0];
181 /* HUM Ch 65.2 "TXPPD1R : Transmit Packet Payload Data 1", p 3850 */
182 reg->TXPPD1R = words[1];
183 /* HUM Ch 65.2 "TXPPD2R : Transmit Packet Payload Data 2", p 3850 */
184 reg->TXPPD2R = words[2];
185 /* HUM Ch 65.2 "TXPPD3R : Transmit Packet Payload Data 3", p 3851 */
186 reg->TXPPD3R = words[3];
187}
188
207{
208 volatile r_mipi_dsi_regs_t* reg = ra8_mipi_dsi();
209 const uint32_t ch0_word =
210 k_ra8_mipi_dsi_sqch_chsel | ((channel == 0U) ? k_ra8_mipi_dsi_sqch_start : 0U);
211 const uint32_t ch1_word =
212 k_ra8_mipi_dsi_sqch_chsel | ((channel == 1U) ? k_ra8_mipi_dsi_sqch_start : 0U);
213 /* HUM Ch 65.2 "SQCH0SET0R : Sequence Channel 0 Setting 0", p 3899 */
214 reg->SQCH0SET0R = ch0_word;
215 /* HUM Ch 65.2 "SQCH1SET0R : Sequence Channel 1 Setting 0", p 3905 */
216 reg->SQCH1SET0R = ch1_word;
217}
218
235{
236 if ((uint32_t)cmd->virtual_channel > (uint32_t)k_ra8_mipi_dsi_vc3) {
238 }
239 if ((cmd->tx_len > 0U) && (cmd->p_tx_buffer == nullptr)) {
240 return k_ra8_err_null_ptr;
241 }
242 if (cmd->low_power && (cmd->tx_len > (uint32_t)k_ra8_mipi_dsi_max_lp_bytes)) {
244 }
245 if ((!cmd->low_power) && (cmd->tx_len > (uint32_t)k_ra8_mipi_dsi_max_hs_bytes)) {
247 }
248 return k_ra8_ok;
249}
250
251/* =============================================================================
252 * Sequence-channel commands
253 * =============================================================================
254 */
255
280{
281 volatile const r_mipi_dsi_regs_t* reg = ra8_mipi_dsi();
282 const uint32_t link = reg->LINKSR;
283 if (cmd->low_power && ((link & k_ra8_mipi_dsi_link_vrun) != 0U)) {
284 ra8_log_error(s_tag, "send_command: LP not allowed during video mode");
286 }
288 ra8_log_error(s_tag, "send_command: sequence busy");
289 return k_ra8_err_busy;
290 }
291 if (cmd->aux_operation && ((link & k_ra8_mipi_dsi_link_vrun) != 0U)) {
293 }
294 return k_ra8_ok;
295}
296
317 const ra8_mipi_dsi_command_t* cmd)
318{
322 const uintptr_t buf_addr = (cmd->bta == k_ra8_mipi_dsi_bta_read) || (cmd->p_rx_buffer != nullptr)
323 ? (uintptr_t)cmd->p_rx_buffer
324 : (uintptr_t)cmd->p_tx_buffer;
325 dsc->D = (uint32_t)buf_addr;
326}
327
350{
351 volatile r_mipi_dsi_regs_t* reg = ra8_mipi_dsi();
352
353 uint8_t channel = 1U;
354 if (cmd->low_power) {
355 channel = 0U;
356 }
357 const uint8_t low_nibble = (uint8_t)((uint32_t)cmd->cmd_id & k_dsi_cmd_id_mask);
358 const bool is_long = low_nibble > 0x08U;
359
360 if (is_long && (cmd->tx_len > 0U)) {
362 }
363
364 volatile r_mipi_dsi_descriptor_t* dsc = (channel == 0U) ? &reg->SQCH0DSC[0] : &reg->SQCH1DSC[0];
366
368}
369
371{
372 RA8_CHECK_NULL_PTR(cmd, s_tag, "cmd must not be nullptr");
374 RA8_RETURN_ON_ERROR(v_err, s_tag, "send_command: validate");
375
376 const ra8_err_t link_err = internal_check_link_state(cmd);
377 RA8_RETURN_ON_ERROR(link_err, s_tag, "send_command: link state");
378
380
381 if (cmd->p_rx_buffer != nullptr) {
384 }
385
386 return k_ra8_ok;
387}
388
391 uint8_t param0,
392 uint8_t param1)
393{
394 uint8_t buf[2] = {param0, param1};
395 const ra8_mipi_dsi_command_t cmd = {
396 .cmd_id = cmd_id,
397 .virtual_channel = vc,
399 .low_power = true,
400 .ack_request = false,
401 .aux_operation = false,
402 .action_code = 0U,
403 .tx_len = 2U,
404 .p_tx_buffer = buf,
405 .p_rx_buffer = nullptr,
406 };
407 return ra8_mipi_dsi_send_command(&cmd);
408}
409
412 const uint8_t* data,
413 uint16_t tx_len,
414 bool low_power)
415{
416 if ((tx_len > 0U) && (data == nullptr)) {
417 return k_ra8_err_null_ptr;
418 }
419 const ra8_mipi_dsi_command_t cmd = {
420 .cmd_id = cmd_id,
421 .virtual_channel = vc,
423 .low_power = low_power,
424 .ack_request = false,
425 .aux_operation = false,
426 .action_code = 0U,
427 .tx_len = tx_len,
428 .p_tx_buffer = data,
429 .p_rx_buffer = nullptr,
430 };
431 return ra8_mipi_dsi_send_command(&cmd);
432}
433
436 uint8_t param0,
437 uint8_t param1,
438 uint8_t* p_rx_buffer,
439 uint16_t rx_len)
440{
441 RA8_CHECK_NULL_PTR(p_rx_buffer, s_tag, "p_rx_buffer must not be nullptr");
442 if (rx_len == 0U) {
444 }
445 uint8_t tx_buf[2] = {param0, param1};
446 const ra8_mipi_dsi_command_t cmd = {
447 .cmd_id = cmd_id,
448 .virtual_channel = vc,
450 .low_power = true,
451 .ack_request = true,
452 .aux_operation = false,
453 .action_code = 0U,
454 .tx_len = 2U,
455 .p_tx_buffer = tx_buf,
456 .p_rx_buffer = p_rx_buffer,
457 };
458 s_mipi_dsi_pending_rx_buffer = p_rx_buffer;
460 return ra8_mipi_dsi_send_command(&cmd);
461}
static const char * s_tag
Logging / check tag.
Definition ra8_app.c:17
Annotation-attribute framework macros for ra8-firmware.
#define RA8_INTERNAL
Marker that a function is intended to be static (file-local).
Validation and Error-Checking Macros for ra8-firmware.
#define RA8_RETURN_ON_ERROR(err, tag, message)
Early return on error, propagating the code upward.
Definition ra8_check.h:184
#define RA8_CHECK_NULL_PTR(ptr, tag, message)
Reject nullptr pointer, returning k_ra8_err_null_ptr.
Definition ra8_check.h:243
Error Code Definitions for ra8-firmware.
@ k_ra8_err_busy
Resource busy – blocking operation cannot proceed.
Definition ra8_err.h:195
@ k_ra8_err_invalid_arg
Invalid function argument.
Definition ra8_err.h:152
@ k_ra8_err_invalid_state
Module in wrong state for requested operation.
Definition ra8_err.h:161
@ k_ra8_ok
Success – operation completed with all postconditions satisfied.
Definition ra8_err.h:119
@ k_ra8_err_null_ptr
Pointer was NULL where a valid pointer was required.
Definition ra8_err.h:478
ra8_err_codes_t ra8_err_t
Canonical error-return type used by every ra8-firmware API.
Definition ra8_err.h:546
Lightweight Logging Interface for ra8-firmware.
#define ra8_log_error(tag, message)
RA8 log error.
Definition ra8_log.h:335
uint16_t s_mipi_dsi_pending_rx_len
Single definition of the shared pending receive capacity.
uint8_t * s_mipi_dsi_pending_rx_buffer
Single definition of the shared pending receive buffer.
MIPI DSI-2 host driver – public API (full HUM Ch 65 surface).
static uint32_t internal_ra8_mipi_dsi_make_dsc_a(const ra8_mipi_dsi_command_t *cmd)
Build descriptor word A from a fully-formed command struct.
static ra8_err_t internal_check_link_state(const ra8_mipi_dsi_command_t *cmd)
Run the LINKSR-based pre-condition checks for send_command.
static void internal_ra8_mipi_dsi_stage_payload(const uint8_t *data, uint16_t len)
Stage long-packet payload bytes into TXPPD0..3R.
ra8_err_t ra8_mipi_dsi_send_command(const ra8_mipi_dsi_command_t *cmd)
Send any sequence-channel command (full-feature path).
static void internal_ra8_mipi_dsi_pulse_start(uint8_t channel)
Write the START-bit pulse for the given sequence channel.
static void internal_send_stage_and_pulse(const ra8_mipi_dsi_command_t *cmd)
Stage payload + descriptor for ra8_mipi_dsi_send_command.
ra8_err_t ra8_mipi_dsi_send_short_packet(ra8_mipi_dsi_dt_t cmd_id, ra8_mipi_dsi_vc_t vc, uint8_t param0, uint8_t param1)
Send a DSI short packet on sequence channel 0 (LP escape).
dsi_cmd_mask_t
Low-nibble mask for the DCS command id.
@ k_dsi_cmd_id_mask
Low nibble of the DCS command id.
static void internal_program_descriptor(volatile r_mipi_dsi_descriptor_t *dsc, const ra8_mipi_dsi_command_t *cmd)
Fill the four descriptor words for a sequence-channel command.
ra8_err_t ra8_mipi_dsi_send_long_packet(ra8_mipi_dsi_dt_t cmd_id, ra8_mipi_dsi_vc_t vc, const uint8_t *data, uint16_t tx_len, bool low_power)
Send a DSI long-packet write (Generic Long / DCS Long).
static uint32_t internal_ra8_mipi_dsi_make_dsc_c(const ra8_mipi_dsi_command_t *cmd)
Build descriptor word C (FINACT / AUXOP / ACTCODE).
static ra8_err_t internal_ra8_mipi_dsi_validate_cmd(const ra8_mipi_dsi_command_t *cmd)
Common LP/HS bound-checking for command submission.
ra8_err_t ra8_mipi_dsi_read_packet(ra8_mipi_dsi_dt_t cmd_id, ra8_mipi_dsi_vc_t vc, uint8_t param0, uint8_t param1, uint8_t *p_rx_buffer, uint16_t rx_len)
Issue a BTA-then-read on sequence channel 0 and return the captured response payload.
Module-private link seam shared between the MIPI DSI-2 hostdriver translation units.
@ k_shift_8
Shift 8.
@ k_ra8_mipi_dsi_byte_mask
8-bit byte field.
@ k_ra8_mipi_dsi_bta_mask
2-bit BTA selector.
@ k_ra8_mipi_dsi_vc_mask
2-bit virtual-channel.
@ k_ra8_mipi_dsi_dt_mask
6-bit DSI Data Type.
MIPI DSI Host (DSI-2) register layout for the RA8D2.
@ k_ra8_mipi_dsi_bta_none
No bus-turnaround.
@ k_ra8_mipi_dsi_bta_read
BTA followed by read.
@ k_ra8_mipi_dsi_max_lp_bytes
LP (ch 0) max long-pkt size.
@ k_ra8_mipi_dsi_max_hs_bytes
HS (ch 1) max long-pkt size.
@ k_ra8_mipi_dsi_payload_max
TXPPD bytes (4 x 32-bit regs).
static volatile r_mipi_dsi_regs_t * ra8_mipi_dsi(void)
Pointer to the RA8D2 MIPI DSI host register block.
@ k_ra8_mipi_dsi_dsc0b_dtsel_seqrm
Use sequence RAM.
@ k_ra8_mipi_dsi_sqch_start
START: kick sequence.
@ k_ra8_mipi_dsi_sqch_chsel
Channel-select bit (FSP).
@ k_ra8_mipi_dsi_link_vrun
Video-mode operation running.
@ k_ra8_mipi_dsi_link_sq1run
Sequence ch 1 running.
@ k_ra8_mipi_dsi_link_sq0run
Sequence ch 0 running.
@ k_ra8_mipi_dsi_dsc0a_shift_bta
Bus Turn Around bits.
@ k_ra8_mipi_dsi_dsc0a_shift_spd
0 = HS, 1 = LP escape.
@ k_ra8_mipi_dsi_dsc0a_shift_data0
Byte 1 of short packet.
@ k_ra8_mipi_dsi_dsc0a_shift_fmt
0 = short packet, 1 = long.
@ k_ra8_mipi_dsi_dsc0a_shift_data1
Byte 2 of short packet.
@ k_ra8_mipi_dsi_dsc0a_shift_dt
DSI data type (cmd id).
@ k_ra8_mipi_dsi_dsc0a_shift_vc
Virtual channel.
@ k_ra8_mipi_dsi_dsc0c_actcode_shift
Action code shift.
@ k_ra8_mipi_dsi_dsc0c_auxop
Auxiliary op flag.
@ k_ra8_mipi_dsi_dsc0c_finact
Finish action flag.
@ k_ra8_mipi_dsi_dsc0c_actcode_mask
ACTCODE[31:24].
ra8_mipi_dsi_dt_t
Frequently used DSI Data Types (cmd id) for short and long packets.
ra8_mipi_dsi_vc_t
DSI virtual channel identifier (DT[7:6] in the packet header).
@ k_ra8_mipi_dsi_vc3
Virtual channel 3.
One sequence-channel descriptor slot (4 x 32-bit registers).
volatile uint32_t D
Descriptor word D: payload buffer address.
volatile uint32_t A
Descriptor word A: packet header.
volatile uint32_t C
Descriptor word C: action / finish.
volatile uint32_t B
Descriptor word B: payload select.
MIPI DSI host register block (full layout).
volatile uint32_t LINKSR
+0x010 Link status (RO).
volatile uint32_t SQCH1SET0R
+0x600 Sequence ch 1 START bit.
volatile uint32_t TXPPD0R
+0x160 Tx packet payload data 0.
volatile uint32_t SQCH0SET0R
+0x5C0 Sequence ch 0 START bit.
r_mipi_dsi_descriptor_t SQCH0DSC[8]
+0x780..0x7FC ch0 desc 0..7.
volatile uint32_t TXPPD3R
+0x16C Tx packet payload data 3.
volatile uint32_t TXPPD1R
+0x164 Tx packet payload data 1.
r_mipi_dsi_descriptor_t SQCH1DSC[8]
+0x800..0x87C ch1 desc 0..7.
volatile uint32_t TXPPD2R
+0x168 Tx packet payload data 2.
Generic DSI packet descriptor for ra8_mipi_dsi_send_command.
uint8_t action_code
ACTCODE (only when aux_op).
bool low_power
true = LP escape (ch 0).
const uint8_t * p_tx_buffer
Source bytes for long packet.
uint8_t * p_rx_buffer
Sink bytes for read responses.
ra8_mipi_dsi_bta_t bta
BTA selector (none/after/...).
ra8_mipi_dsi_dt_t cmd_id
Data Type / command opcode.
ra8_mipi_dsi_vc_t virtual_channel
VC[1:0] in the packet header.
uint16_t tx_len
Bytes in p_tx_buffer.
bool aux_operation
AUXOP descriptor word C.