1 /*
2 * Copyright (c) 2020 - 2024 Renesas Electronics Corporation and/or its affiliates
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6 
7 /***********************************************************************************************************************
8  * Includes
9  **********************************************************************************************************************/
10 #include <string.h>
11 
12 #include "bsp_api.h"
13 
14 #include "r_glcdc.h"
15 #include "r_glcdc_cfg.h"
16 
17 #if defined(GLCDC_CFG_USING_DSI)
18  #include "r_mipi_dsi_api.h"
19 #endif
20 
21 /***********************************************************************************************************************
22  * Macro definitions
23  **********************************************************************************************************************/
24 
25 /* The macro to use for 64-byte alignment checking, calculation */
26 #define GLCDC_PRV_ADDRESS_ALIGNMENT_64B                (64U)
27 
28 /* This enables the GLCDC to locate the foreground/background layer image, at the physical start of the left side of
29  * the display, if the offset of layer start position is a negative value, compared to the active video area.
30  *  Shifting the base address of the layer image can be used in this operation, but it must be aligned to 64 byte
31  * boundary, so that the layer position adjustment can be made.
32  */
33 #define GLCDC_PRV_OFFSET_MARGIN_MINUS_64PIX            (64U)
34 
35 #define GLCDC_PRV_OUT_CLKPHASE_ALL_RISING              (0x00000000)
36 #define GLCDC_PRV_OUT_CLKPHASE_ALL_FALLING             (0x00000178)
37 
38 /* Color look up table entry size */
39 #define GLCDC_PRV_CLUT_ENTRY_SIZE                      (256U)
40 
41 /* Panel timing, Maximum threshold */
42 #define GLCDC_PRV_BG_PLANE_H_CYC_MAX                   (2047U)         ///< BG_PERI.FH
43 #define GLCDC_PRV_BG_PLANE_V_CYC_MAX                   (2047U)         ///< BG_PERI.FV
44 #define GLCDC_PRV_BG_PLANE_H_CYC_ACTIVE_SIZE_MAX       (2039U)         ///< BG_HSIZE.HW (Max=2039)
45 #define GLCDC_PRV_BG_PLANE_V_CYC_ACTIVE_SIZE_MAX       (2043U)         ///< BG_VSIZE.VW (Max=2043)
46 #define GLCDC_PRV_BG_PLANE_H_CYC_ACTIVE_POS_MAX        (2029U)         ///< BG_HSIZE.HP (Max=2029, note that this value is 1cycle larger than GRn_AB3.GRCHS)
47 #define GLCDC_PRV_BG_PLANE_V_CYC_ACTIVE_POS_MAX        (2030U)         ///< BG_VSIZE.VP (Max=2030, note that this value is 1cycle larger than GRn_AB3.GRCVS)
48 #define GLCDC_PRV_GR_PLANE_TOTAL_TRANSFER_TIMES_MAX    (65536U)        ///< GRn_FLM5.DATANUM (Max=65536)
49 #define GLCDC_PRV_GR_PLANE_V_CYC_ACTIVE_SIZE_MAX       (2043U)         ///< GRn_AB2.GRCVW (Max=2043) ; Image Area, GRn_AB4.ARCVW (Max=2043); Rectangular Area
50 #define GLCDC_PRV_GR_PLANE_H_CYC_ACTIVE_POS_MAX        (2028U)         ///< GRn_AB3.GRCHS (Max=2028) ; Image Area, GRn_AB5.ARCHS (Max=2028); Rectangular Area
51 #define GLCDC_PRV_GR_PLANE_V_CYC_ACTIVE_POS_MAX        (2029U)         ///< GRn_AB2.GRCVS (Max=2029) ; Image Area, GRn_AB4.ARCVS (Max=2029); Rectangular Area
52 #define GLCDC_PRV_TCON_SIGNAL_ASSERT_WIDTH_MAX         (2046U)
53 
54 /* Panel timing, Minimum threshold */
55 #define GLCDC_PRV_BG_PLANE_H_CYC_MIN                   ((uint16_t) 23) ///< BG_PERI.FH
56 #define GLCDC_PRV_BG_PLANE_V_CYC_MIN                   ((uint16_t) 19) ///< BG_PERI.FV
57 #define GLCDC_PRV_BG_PLANE_HSYNC_POS_MIN               ((uint16_t) 1)  ///< BG_HSYNC.HP (Min=1)
58 #define GLCDC_PRV_BG_PLANE_VSYNC_POS_MIN               ((uint16_t) 1)  ///< BG_HSYNC.VP (Min=1)
59 #define GLCDC_PRV_BG_PLANE_H_CYC_ACTIVE_SIZE_MIN       ((uint16_t) 16) ///< BG_HSIZE.HW (Min=16)
60 #define GLCDC_PRV_BG_PLANE_V_CYC_ACTIVE_SIZE_MIN       ((uint16_t) 16) ///< BG_VSIZE.VW (Min=16)
61 #define GLCDC_PRV_BG_PLANE_H_CYC_ACTIVE_POS_MIN        ((uint16_t) 6)  ///< BG_HSIZE.HP (Min= 6)
62 #define GLCDC_PRV_BG_PLANE_V_CYC_ACTIVE_POS_MIN        ((uint16_t) 3)  ///< BG_VSIZE.VP (Min= 3)
63 
64 /* This driver sets same value to GRn_AB2.GRCVW and GRn_AB4.ARCVW, so the value of this macro
65  * is defined as the number of GRn_AB2.GRCVW(larger value).
66  */
67 #define GLCDC_PRV_GR_PLANE_H_CYC_ACTIVE_POS_MIN        (5U)            ///< GRn_AB3.GRCHS (Min= 5) ; Image Area, GRn_AB5.ARCHS (Min= 5); Rectangular Area
68 #define GLCDC_PRV_GR_PLANE_V_CYC_ACTIVE_POS_MIN        (2U)            ///< GRn_AB2.GRCVS (Min= 2) ; Image Area, GRn_AB4.ARCVS (Min= 2); Rectangular Area
69 #define GLCDC_PRV_TCON_SIGNAL_ASSERT_WIDTH_MIN         (0U)
70 
71 /* Color correction setting threshold */
72 #define GLCDC_PRV_BRIGHTNESS_DEFAULT                   (512U)          ///< OUT_BRIGHT1.BRTG, OUT_BRIGHT2.BRTR and .BRTB (Mid=512)
73 #define GLCDC_PRV_BRIGHTNESS_MIN                       (0U)            ///< OUT_BRIGHT1.BRTG, OUT_BRIGHT2.BRTR and .BRTB (Min=0)
74 #define GLCDC_PRV_BRIGHTNESS_MAX                       (1023U)         ///< OUT_BRIGHT1.BRTG, OUT_BRIGHT2.BRTR and .BRTB (Max=1023)
75 #define GLCDC_PRV_CONTRAST_DEFAULT                     (128U)          ///< OUT_CONTRAST.CONTG and .CONTB and .CONTR (Mid=128)
76 #define GLCDC_PRV_CONTRAST_MIN                         (0U)            ///< OUT_CONTRAST.CONTG and .CONTB and .CONTR (Min=0)
77 #define GLCDC_PRV_CONTRAST_MAX                         (255U)          ///< OUT_CONTRAST.CONTG and .CONTB and .CONTR (Max=255)
78 #define GLCDC_PRV_GAMMA_GAIN_MAX                       (2047U)         ///< GAMx_LUTn.GAIN15 - GAIN0 (Max=2047)
79 #define GLCDC_PRV_GAMMA_THRESHOLD_MAX                  (1023U)         ///< GAMx_AREAn.TH15  - TH0   (Max=1023)
80 
81 /* Registers for Background Frame Control Block */
82 #define GLCDC_PRV_BG_PERI_FV_MASK                      (0x7FFU)
83 #define GLCDC_PRV_BG_PERI_FH_MASK                      (0x7FFU)
84 #define GLCDC_PRV_BG_SYNC_VP_MASK                      (0xFU)
85 #define GLCDC_PRV_BG_SYNC_HP_MASK                      (0xFU)
86 #define GLCDC_PRV_BG_VSIZE_VP_MASK                     (0x7FFU)
87 #define GLCDC_PRV_BG_VSIZE_VW_MASK                     (0x7FFU)
88 #define GLCDC_PRV_BG_HSIZE_HP_MASK                     (0x7FFU)
89 #define GLCDC_PRV_BG_HSIZE_HW_MASK                     (0x7FFU)
90 
91 /* Register bit definition for Graphics Frame Control Block */
92 #define GLCDC_PRV_GR_FLM3_LNOFF_MASK                   (0xFFFFU)
93 #define GLCDC_PRV_GR_FLM3_FLNUM_MASK                   (0x3FFU)
94 #define GLCDC_PRV_GR_FLM4_FLOFF_MASK                   (0xFFFFFFU)
95 #define GLCDC_PRV_GR_FLM5_LNNUM_MASK                   (0x7FFU)
96 #define GLCDC_PRV_GR_FLM5_DATANUM_MASK                 (0xFFFFU)
97 #define GLCDC_PRV_GR_FLM6_FORMAT_MASK                  (0x7U)
98 
99 #define GLCDC_PRV_GR_AB1_DISPSEL_MASK                  (0x3U)
100 #define GLCDC_PRV_GR_AB1_ARCON_SET                     (1 << 12)
101 #define GLCDC_PRV_GR_AB2_GRCVS_MASK                    (0x7FFU)
102 #define GLCDC_PRV_GR_AB2_GRCVW_MASK                    (0x7FFU)
103 #define GLCDC_PRV_GR_AB3_GRCHS_MASK                    (0x7FFU)
104 #define GLCDC_PRV_GR_AB3_GRCHW_MASK                    (0x7FFU)
105 #define GLCDC_PRV_GR_AB4_ARCVS_MASK                    (0x7FFU)
106 #define GLCDC_PRV_GR_AB4_ARCVW_MASK                    (0x7FFU)
107 #define GLCDC_PRV_GR_AB5_ARCHS_MASK                    (0x7FFU)
108 #define GLCDC_PRV_GR_AB5_ARCHW_MASK                    (0x7FFU)
109 #define GLCDC_PRV_GR_AB6_ARCCOEF_MASK                  (0x1FFU)
110 #define GLCDC_PRV_GR_AB6_ARCRATE_MASK                  (0xFFU)
111 #define GLCDC_PRV_GR_AB7_ARCDEF_MASK                   (0xFFU)
112 #define GLCDC_PRV_GR_CLUTINT_LINE_MASK                 (0x7FFU)
113 
114 /* Register bit definition for Output Control Block */
115 #define GLCDC_PRV_GAMX_LUTX_GAIN_MASK                  (0x7FFU)
116 #define GLCDC_PRV_GAMX_AREAX_MASK                      (0x3FFU)
117 
118 #define GLCDC_PRV_OUT_SET_FRQSEL_NO_DIVISION           (0U)
119 #define GLCDC_PRV_OUT_SET_FRQSEL_QUARTER_DIVISION      (2U)
120 #define GLCDC_PRV_OUT_SET_FORMAT_SHIFT                 (12U)
121 #define GLCDC_PRV_OUT_SET_ENDIANON_ENABLE              (1 << 28)
122 #define GLCDC_PRV_OUT_SET_SWAPON_ENABLE                (1 << 24)
123 
124 #define GLCDC_PRV_OUT_PDTHA_SEL_SHIFT                  (20U)
125 #define GLCDC_PRV_OUT_PDTHA_FORM_SHIFT                 (16U)
126 #define GLCDC_PRV_OUT_PDTHA_PA_SHIFT                   (12U)
127 #define GLCDC_PRV_OUT_PDTHA_PB_SHIFT                   (8U)
128 #define GLCDC_PRV_OUT_PDTHA_PC_SHIFT                   (4U)
129 
130 #define GLCDC_PRV_OUT_BRIGHT1_BRTG_MASK                (0x3FFU)
131 #define GLCDC_PRV_OUT_BRIGHT2_BRTB_MASK                (0x3FFU)
132 #define GLCDC_PRV_OUT_BRIGHT2_BRTR_MASK                (0x3FFU)
133 
134 #define GLCDC_PRV_OUT_CONTRAST_CONTG_MASK              (0xFFU)
135 #define GLCDC_PRV_OUT_CONTRAST_CONTB_MASK              (0xFFU)
136 #define GLCDC_PRV_OUT_CONTRAST_CONTR_MASK              (0xFFU)
137 
138 #define GLCDC_PRV_TCON_STHX1_HS_MASK                   (0x7FFU)
139 #define GLCDC_PRV_TCON_STHX1_HW_MASK                   (0x7FFU)
140 #define GLCDC_PRV_TCON_STVX1_VS_MASK                   (0x7FFU)
141 #define GLCDC_PRV_TCON_STVX1_VW_MASK                   (0x7FFU)
142 #define GLCDC_PRV_TCON_STXX2_INV_SET                   (1 << 4)
143 
144 #define GLCDC_PRV_SYSCNT_PANEL_CLK_PIXSEL_SERIALRGB    (1 << 12)
145 #define GLCDC_PRV_SYSCNT_PANEL_CLK_CLKSEL_PLL          (1 << 8)
146 #define GLCDC_PRV_SYSCNT_PANEL_CLK_CLKEN_ENABLE        (1 << 6)
147 #define GLCDC_PRV_SYSCNT_PANEL_CLK_DCDR_MASK           (0x3FU)
148 
149 #define GLCDC_PRV_SYSCNT_DTCTEN_INIT                   (6U)
150 #define GLCDC_PRV_SYSCNT_INTEN_INIT                    (7U)
151 
152 /***********************************************************************************************************************
153  * Typedef definitions
154  **********************************************************************************************************************/
155 
156 /* RGB color order select */
157 typedef enum e_glcdc_plane_blend
158 {
159     GLCDC_PLANE_BLEND_TRANSPARENT     = 1, ///< Current graphics layer is transparent and the lower layer is displayed
160     GLCDC_PLANE_BLEND_NON_TRANSPARENT = 2, ///< Current graphics layer is displayed
161     GLCDC_PLANE_BLEND_ON_LOWER_LAYER  = 3  ///< Current graphics layer is blended with the lower layer
162 } glcdc_plane_blend_t;
163 
164 /* RGB color order select */
165 typedef enum e_glcdc_fading_control_initial_alpha
166 {
167     GLCDC_FADING_CONTROL_INITIAL_ALPHA_MIN = 0,   ///< Initial alpha value setting for a graphics plane is zero
168     GLCDC_FADING_CONTROL_INITIAL_ALPHA_MAX = 0xff ///< Initial alpha value setting for a graphics plane is maximum
169 } glcdc_fading_control_initial_alpha_t;
170 
171 /* The structure for the layer parameter recalculation */
172 typedef struct st_recalculated_param
173 {
174     uint16_t hpix_size;
175     uint16_t vpix_size;
176     int16_t  hpix_offset;              /* Offset can be signed value */
177     int16_t  vpix_offset;
178     uint32_t hread_size;
179     uint32_t base_address;
180 } glcdc_recalculated_param_t;
181 
182 /***********************************************************************************************************************
183  * Private function prototypes
184  **********************************************************************************************************************/
185 static fsp_err_t r_glcdc_stop(glcdc_instance_ctrl_t * const p_ctrl);
186 static void      r_glcdc_sync_signal_set(display_cfg_t const * const p_cfg);
187 
188 static void r_glcdc_background_screen_set(display_cfg_t const * const p_cfg);
189 
190 static void r_glcdc_graphics_layer_set(display_input_cfg_t const * const p_input,
191                                        display_layer_t const * const     p_layer,
192                                        display_frame_layer_t const       layer);
193 
194 static void r_glcdc_output_block_set(display_cfg_t const * const p_cfg);
195 
196 static void r_glcdc_hsync_set(glcdc_tcon_pin_t tcon, display_timing_t const * timing);
197 
198 static void r_glcdc_vsync_set(glcdc_tcon_pin_t tcon, display_timing_t const * const timing);
199 
200 static void r_glcdc_data_enable_set(glcdc_tcon_pin_t const          tcon,
201                                     display_timing_t const * const  vtiming,
202                                     display_timing_t const * const  htiming,
203                                     display_signal_polarity_t const polarity);
204 
205 static void r_glcdc_clock_set(display_cfg_t const * const p_cfg);
206 
207 #if (GLCDC_CFG_PARAM_CHECKING_ENABLE)
208 
209 static fsp_err_t r_glcdc_open_param_check(display_cfg_t const * const p_cfg);
210 
211  #if GLCDC_CFG_COLOR_CORRECTION_ENABLE
212 
213 static fsp_err_t r_glcdc_param_check_brightness(display_brightness_t const * const p_brightness);
214 
215  #endif
216 
217 #endif
218 
219 static inline uint16_t r_glcdc_get_bit_size(display_in_format_t const format);
220 
221 static void r_glcdc_interrupt_enable(glcdc_instance_ctrl_t * p_instance_ctrl);
222 
223 static void r_glcdc_pixel_size_recalculate(display_input_cfg_t const * const p_input,
224                                            display_layer_t const * const     p_layer,
225                                            glcdc_recalculated_param_t      * p_recalculated,
226                                            uint16_t                          bit_size);
227 
228 #if GLCDC_CFG_COLOR_CORRECTION_ENABLE
229 
230 static void r_glcdc_brightness_correction(glcdc_instance_ctrl_t const * const p_ctrl,
231                                           display_brightness_t const * const  p_brightness);
232 
233 static void r_glcdc_contrast_correction(glcdc_instance_ctrl_t const * const p_ctrl,
234                                         display_contrast_t const * const    p_contrast);
235 
236 static void r_glcdc_color_correction_order(display_cfg_t const * const p_cfg);
237 
238 static void r_glcdc_gamma_correction(display_cfg_t const * const p_cfg);
239 
240 #endif
241 
242 /***********************************************************************************************************************
243  * Private global variables
244  **********************************************************************************************************************/
245 
246 /* GLCDC HAL module API function pointer list */
247 const display_api_t g_display_on_glcdc =
248 {
249     .open         = R_GLCDC_Open,
250     .close        = R_GLCDC_Close,
251     .start        = R_GLCDC_Start,
252     .stop         = R_GLCDC_Stop,
253     .layerChange  = R_GLCDC_LayerChange,
254     .bufferChange = R_GLCDC_BufferChange,
255     .clut         = R_GLCDC_ClutUpdate,
256     .clutEdit     = R_GLCDC_ClutEdit,
257     .correction   = R_GLCDC_ColorCorrection,
258     .colorKeySet  = R_GLCDC_ColorKeySet,
259     .statusGet    = R_GLCDC_StatusGet,
260 };
261 
262 /* GLCDC control block */
263 static glcdc_ctrl_t g_ctrl_blk =
264 {
265     .back_porch = {0U, 0U},
266     .hsize      = 0U,
267     .vsize      = 0U,
268     .p_context  = NULL
269 };
270 
271 void glcdc_line_detect_isr(void);
272 void glcdc_underflow_1_isr(void);
273 void glcdc_underflow_2_isr(void);
274 
275 /* Needed to track fade status */
276 static uint32_t          g_fade_pending[2] = {false, false};
277 static volatile uint32_t g_frame_ctr       = 0;
278 
279 /* Tracks when an edited CLUT has been latched in */
280 static volatile bool g_clut_data_latched[2] = {true, true};
281 
282 /* Look-up table for r_glcdc_tcon_set */
283 static uint32_t volatile * g_tcon_lut[] =
284 {
285     &(R_GLCDC->TCON.STVA2), &(R_GLCDC->TCON.STVB2), &(R_GLCDC->TCON.STHA2), &(R_GLCDC->TCON.STHB2),
286 };
287 
288 /* Look-up table for converting display_in_format_t to glcdc_input_interface_format_t */
289 static glcdc_input_interface_format_t g_format_lut[] =
290 {
291     GLCDC_INPUT_INTERFACE_FORMAT_ARGB8888,
292     GLCDC_INPUT_INTERFACE_FORMAT_RGB888,
293     GLCDC_INPUT_INTERFACE_FORMAT_RGB565,
294     GLCDC_INPUT_INTERFACE_FORMAT_ARGB1555,
295     GLCDC_INPUT_INTERFACE_FORMAT_ARGB4444,
296     GLCDC_INPUT_INTERFACE_FORMAT_CLUT8,
297     GLCDC_INPUT_INTERFACE_FORMAT_CLUT4,
298     GLCDC_INPUT_INTERFACE_FORMAT_CLUT1
299 };
300 
301 /* Look-up table for r_glcdc_get_bit_size */
302 static uint16_t g_pixsize_lut[] = {32, 32, 16, 16, 16, 8, 4, 1}; // NOLINT(readability-magic-numbers)
303 
304 /* Look-up tables for use in r_glcdc_output_block_set */
305 static glcdc_output_interface_format_t g_outset_lut[] =
306 {
307     GLCDC_OUTPUT_INTERFACE_FORMAT_RGB888,
308     GLCDC_OUTPUT_INTERFACE_FORMAT_RGB666,
309     GLCDC_OUTPUT_INTERFACE_FORMAT_RGB565,
310     GLCDC_OUTPUT_INTERFACE_FORMAT_SERIAL_RGB
311 };
312 static glcdc_dithering_output_format_t g_pdtha_lut[] =
313 {
314     GLCDC_DITHERING_OUTPUT_FORMAT_RGB888,
315     GLCDC_DITHERING_OUTPUT_FORMAT_RGB666,
316     GLCDC_DITHERING_OUTPUT_FORMAT_RGB565,
317     GLCDC_DITHERING_OUTPUT_FORMAT_RGB888
318 };
319 
320 /*******************************************************************************************************************//**
321  * @addtogroup GLCDC
322  * @{
323  **********************************************************************************************************************/
324 
325 /***********************************************************************************************************************
326  * Functions
327  **********************************************************************************************************************/
328 
329 /*******************************************************************************************************************//**
330  * Open GLCDC module. Implements @ref display_api_t::open.
331  *
332  * @retval  FSP_SUCCESS                        Device was opened successfully.
333  * @retval  FSP_ERR_ALREADY_OPEN               Device was already open.
334  * @retval  FSP_ERR_ASSERTION                  Pointer to the control block or the configuration structure is NULL.
335  * @retval  FSP_ERR_CLOCK_GENERATION           Dot clock cannot be generated from clock source.
336  * @retval  FSP_ERR_INVALID_TIMING_SETTING     Invalid panel timing parameter.
337  * @retval  FSP_ERR_INVALID_LAYER_SETTING      Invalid layer setting found.
338  * @retval  FSP_ERR_INVALID_ALIGNMENT          Input buffer alignment invalid.
339  * @retval  FSP_ERR_INVALID_GAMMA_SETTING      Invalid gamma correction setting found
340  * @retval  FSP_ERR_INVALID_BRIGHTNESS_SETTING Invalid brightness correction setting found
341  * @note    PCLKA  must be supplied to Graphics LCD Controller (GLCDC) and  GLCDC pins must be set in IOPORT before
342  *           calling this API.
343  **********************************************************************************************************************/
R_GLCDC_Open(display_ctrl_t * const p_api_ctrl,display_cfg_t const * const p_cfg)344 fsp_err_t R_GLCDC_Open (display_ctrl_t * const p_api_ctrl, display_cfg_t const * const p_cfg)
345 {
346     glcdc_instance_ctrl_t * p_ctrl = (glcdc_instance_ctrl_t *) p_api_ctrl;
347     fsp_err_t               err    = FSP_SUCCESS;
348 
349 #if (GLCDC_CFG_PARAM_CHECKING_ENABLE)
350 
351     /* Check parameters */
352     FSP_ASSERT(p_ctrl);
353     FSP_ERROR_RETURN(p_ctrl->state <= DISPLAY_STATE_CLOSED, FSP_ERR_ALREADY_OPEN);
354     err = r_glcdc_open_param_check(p_cfg);
355     if (FSP_SUCCESS != err)
356     {
357         return err;
358     }
359 #endif
360 
361     p_ctrl->state = DISPLAY_STATE_CLOSED;
362 
363     /* Supply the peripheral clock to the GLCDC module */
364     R_BSP_MODULE_START(FSP_IP_GLCDC, 0);
365 
366     /* Release GLCDC from a SW reset status. */
367     R_GLCDC->BG.EN_b.SWRST = 1U;
368 
369     /* Set the dot clock frequency */
370     r_glcdc_clock_set(p_cfg);
371 
372     /* Set the panel signal timing */
373     r_glcdc_sync_signal_set(p_cfg);
374 
375     /* Configure the background screen */
376     r_glcdc_background_screen_set(p_cfg);
377 
378     /* Store back porch position to the control block (needed to define the layer blending position later) */
379     g_ctrl_blk.back_porch.x = (int16_t) (p_cfg->output.htiming.back_porch);
380     g_ctrl_blk.back_porch.y = (int16_t) (p_cfg->output.vtiming.back_porch);
381     g_ctrl_blk.hsize        = p_cfg->output.htiming.display_cyc;
382     g_ctrl_blk.vsize        = p_cfg->output.vtiming.display_cyc;
383 
384     /* Configure the graphics plane layers */
385     for (uint32_t layer = 0U; layer <= DISPLAY_FRAME_LAYER_2; layer++)
386     {
387         r_glcdc_graphics_layer_set(&(p_cfg->input[layer]), &(p_cfg->layer[layer]), (display_frame_layer_t) layer);
388     }
389 
390     /* Configure the output control block */
391     r_glcdc_output_block_set(p_cfg);
392 
393 #if GLCDC_CFG_COLOR_CORRECTION_ENABLE
394 
395     /* Configure the color correction setting (brightness, brightness and gamma correction) */
396     r_glcdc_brightness_correction(p_ctrl, &p_cfg->output.brightness);
397     r_glcdc_contrast_correction(p_ctrl, &p_cfg->output.contrast);
398     if (p_cfg->output.p_gamma_correction)
399     {
400         r_glcdc_gamma_correction(p_cfg);
401     }
402 
403     /* Set the color correction order (brightness/contrast or gamma first) */
404     r_glcdc_color_correction_order(p_cfg);
405 #else
406 
407     /* Set default brightness and contrast */
408     R_GLCDC->OUT.BRIGHT1 = GLCDC_PRV_BRIGHTNESS_DEFAULT & GLCDC_PRV_OUT_BRIGHT1_BRTG_MASK;
409     R_GLCDC->OUT.BRIGHT2 = ((GLCDC_PRV_BRIGHTNESS_DEFAULT & GLCDC_PRV_OUT_BRIGHT2_BRTB_MASK) << 16) +
410                            (GLCDC_PRV_BRIGHTNESS_DEFAULT & GLCDC_PRV_OUT_BRIGHT2_BRTR_MASK);
411     R_GLCDC->OUT.CONTRAST = ((GLCDC_PRV_CONTRAST_DEFAULT & GLCDC_PRV_OUT_CONTRAST_CONTG_MASK) << 16) +
412                             ((GLCDC_PRV_CONTRAST_DEFAULT & GLCDC_PRV_OUT_CONTRAST_CONTB_MASK) << 8) +
413                             (GLCDC_PRV_CONTRAST_DEFAULT & GLCDC_PRV_OUT_CONTRAST_CONTR_MASK);
414 #endif
415 
416     p_ctrl->p_callback   = p_cfg->p_callback; /// Save callback function
417     p_ctrl->p_context    = p_cfg->p_context;  /// Save user defined context
418     p_ctrl->p_cfg        = p_cfg;             /// Save user configuration
419     g_ctrl_blk.p_context = p_ctrl;            /// Save the display interface context into GLCDC HAL control block
420 
421     /* Set the line number to trigger the line detect interrupt */
422     R_GLCDC->GR[1].CLUTINT_b.LINE = (uint16_t) (p_cfg->output.vtiming.back_porch +
423                                                 p_cfg->output.vtiming.display_cyc +
424                                                 GLCDC_PRV_BG_PLANE_HSYNC_POS_MIN) & GLCDC_PRV_GR_CLUTINT_LINE_MASK;
425 
426 #if defined(GLCDC_CFG_USING_DSI)
427 
428     /* DSI must be opened after GLCDC configuration. See RA8 UM R01UH0995EJ0050 Section 56.3.1 */
429     glcdc_extended_cfg_t * p_extend     = (glcdc_extended_cfg_t *) p_ctrl->p_cfg->p_extend;
430     mipi_dsi_instance_t  * dsi_instance = (mipi_dsi_instance_t *) p_extend->phy_layer;
431     err = dsi_instance->p_api->open(dsi_instance->p_ctrl, dsi_instance->p_cfg);
432 #endif
433 
434     if (FSP_SUCCESS == err)
435     {
436         /* Enable GLCDC interrupts */
437         r_glcdc_interrupt_enable(p_api_ctrl);
438         p_ctrl->state = DISPLAY_STATE_OPENED; /// Change GLCDC driver state
439     }
440     else
441     {
442         R_BSP_MODULE_STOP(FSP_IP_GLCDC, 0);
443     }
444 
445     return err;
446 }
447 
448 /*******************************************************************************************************************//**
449  * Close GLCDC module. Implements @ref display_api_t::close.
450  *
451  * @retval  FSP_SUCCESS                     Device was closed successfully.
452  * @retval  FSP_ERR_ASSERTION               Pointer to the control block is NULL.
453  * @retval  FSP_ERR_NOT_OPEN                The function call is performed when the driver state is not equal to
454  *                                           DISPLAY_STATE_CLOSED.
455  * @retval  FSP_ERR_INVALID_UPDATE_TIMING   A function call is performed when the GLCDC is updating register values
456  *                                           internally.
457  * @note    This API can be called when the driver is not in DISPLAY_STATE_CLOSED state. It returns an error
458  *           if the register update operation for the background screen generation block is being held.
459  **********************************************************************************************************************/
R_GLCDC_Close(display_ctrl_t * const p_api_ctrl)460 fsp_err_t R_GLCDC_Close (display_ctrl_t * const p_api_ctrl)
461 {
462     glcdc_instance_ctrl_t * p_ctrl = (glcdc_instance_ctrl_t *) p_api_ctrl;
463     fsp_err_t               err    = FSP_SUCCESS;
464 
465 #if (GLCDC_CFG_PARAM_CHECKING_ENABLE)
466     FSP_ASSERT(p_ctrl);
467     FSP_ERROR_RETURN(DISPLAY_STATE_CLOSED != p_ctrl->state, FSP_ERR_NOT_OPEN);
468 #endif
469 
470     /* Stop video if running */
471     if (R_GLCDC->BG.EN_b.EN)
472     {
473         r_glcdc_stop(p_api_ctrl);
474     }
475 
476 #if defined(GLCDC_CFG_USING_DSI)
477 
478     /* DSI must be closed before GLCDC. See RA8 UM R01UH0995EJ0050 Section 56.3.7.2 */
479     glcdc_extended_cfg_t * p_extend     = (glcdc_extended_cfg_t *) p_ctrl->p_cfg->p_extend;
480     mipi_dsi_instance_t  * dsi_instance = (mipi_dsi_instance_t *) p_extend->phy_layer;
481     err = dsi_instance->p_api->close(dsi_instance->p_ctrl);
482 #endif
483 
484     /* Return immediately if the background block register updating is performed. */
485     FSP_ERROR_RETURN(false == (bool) (R_GLCDC->BG.MON_b.VEN & 1U), FSP_ERR_INVALID_UPDATE_TIMING);
486 
487     /* Disable the GLCDC interrupts in the NVIC */
488     if (p_ctrl->p_cfg->line_detect_irq >= 0)
489     {
490         R_BSP_IrqDisable(p_ctrl->p_cfg->line_detect_irq);
491     }
492 
493     if (p_ctrl->p_cfg->underflow_1_irq >= 0)
494     {
495         R_BSP_IrqDisable(p_ctrl->p_cfg->underflow_1_irq);
496     }
497 
498     if (p_ctrl->p_cfg->underflow_2_irq >= 0)
499     {
500         R_BSP_IrqDisable(p_ctrl->p_cfg->underflow_2_irq);
501     }
502 
503     /* Disable the GLCDC interrupts */
504     R_GLCDC->SYSCNT.DTCTEN = 0U;
505     R_GLCDC->SYSCNT.INTEN  = 0U;
506 
507     /* Disable background plane operation */
508     R_GLCDC->BG.EN_b.EN = 0U;
509 
510     /* Reset the GLCDC hardware */
511     R_GLCDC->BG.EN_b.SWRST = 0U;
512 
513     /* Halt the peripheral clock to the GLCDC module */
514     R_BSP_MODULE_STOP(FSP_IP_GLCDC, 0);
515 
516     p_ctrl->state = DISPLAY_STATE_CLOSED;
517 
518     return err;
519 }
520 
521 /*******************************************************************************************************************//**
522  * Start GLCDC module. Implements @ref display_api_t::start.
523  *
524  * @retval  FSP_SUCCESS                  Device was started successfully.
525  * @retval  FSP_ERR_NOT_OPEN             GLCDC module has not been opened.
526  * @retval  FSP_ERR_ASSERTION            Pointer to the control block is NULL.
527  * @note    This API can be called when the driver is not in DISPLAY_STATE_OPENED status.
528  **********************************************************************************************************************/
R_GLCDC_Start(display_ctrl_t * const p_api_ctrl)529 fsp_err_t R_GLCDC_Start (display_ctrl_t * const p_api_ctrl)
530 {
531     glcdc_instance_ctrl_t * p_ctrl = (glcdc_instance_ctrl_t *) p_api_ctrl;
532     fsp_err_t               err    = FSP_SUCCESS;
533 
534 #if (GLCDC_CFG_PARAM_CHECKING_ENABLE)
535     FSP_ASSERT(p_ctrl);
536     FSP_ERROR_RETURN(DISPLAY_STATE_OPENED == p_ctrl->state, FSP_ERR_NOT_OPEN);
537 #endif
538 
539 #if defined(GLCDC_CFG_USING_DSI)
540 
541     /* DSI must be started before GLCDC. See RA8 UM R01UH0995EJ0050 Section 56.3.7.1 */
542     glcdc_extended_cfg_t * p_extend     = (glcdc_extended_cfg_t *) p_ctrl->p_cfg->p_extend;
543     mipi_dsi_instance_t  * dsi_instance = (mipi_dsi_instance_t *) p_extend->phy_layer;
544     err = dsi_instance->p_api->start(dsi_instance->p_ctrl);
545 #endif
546 
547     /* Start to output the vertical and horizontal synchronization signals and screen data. */
548 
549     /* enables background plane operation and internal register value reflection. */
550     R_GLCDC->BG.EN_b.VEN = 1U;
551     R_GLCDC->BG.EN_b.EN  = 1U;
552 
553     /* Enable Line detect function    */
554     R_GLCDC->SYSCNT.DTCTEN_b.VPOSDTC = 1U;
555 
556     p_ctrl->state = DISPLAY_STATE_DISPLAYING;
557 
558     return err;
559 }
560 
561 /*******************************************************************************************************************//**
562  * Stop GLCDC module. Implements @ref display_api_t::stop.
563  *
564  * @retval  FSP_SUCCESS                   Device was stopped successfully
565  * @retval  FSP_ERR_ASSERTION             Pointer to the control block is NULL
566  * @retval  FSP_ERR_INVALID_MODE          Function call is performed when the driver state is not
567  *                                        DISPLAY_STATE_DISPLAYING.
568  * @retval  FSP_ERR_INVALID_UPDATE_TIMING The function call is performed while the GLCDC is updating register values
569  *                                          internally.
570  * @note    This API can be called when the driver is in the DISPLAY_STATE_DISPLAYING state. It returns an
571  *          error if the register update operation for the background screen generation blocks, the graphics data I/F
572  *          blocks, or the output control block is being held.
573  **********************************************************************************************************************/
R_GLCDC_Stop(display_ctrl_t * const p_api_ctrl)574 fsp_err_t R_GLCDC_Stop (display_ctrl_t * const p_api_ctrl)
575 {
576     glcdc_instance_ctrl_t * p_ctrl = (glcdc_instance_ctrl_t *) p_api_ctrl;
577 
578 #if (GLCDC_CFG_PARAM_CHECKING_ENABLE)
579     FSP_ASSERT(p_ctrl);
580     FSP_ERROR_RETURN((DISPLAY_STATE_DISPLAYING == p_ctrl->state), FSP_ERR_INVALID_MODE);
581 #endif
582 
583     return r_glcdc_stop(p_ctrl);
584 }
585 
586 /*******************************************************************************************************************//**
587  * Change layer parameters of GLCDC module at runtime. Implements display_api_t::layerChange.
588  *
589  * @retval  FSP_SUCCESS                      Changed layer parameters of GLCDC module successfully.
590  * @retval  FSP_ERR_ASSERTION                Pointer to the control block or the configuration structure is NULL.
591  * @retval  FSP_ERR_INVALID_MODE             A function call is performed when the driver state is not
592  *                                            DISPLAY_STATE_DISPLAYING.
593  * @retval  FSP_ERR_INVALID_UPDATE_TIMING    A function call is performed while the GLCDC is updating register values
594  *                                            internally.
595  * @note    This API can be called when the driver is in DISPLAY_STATE_DISPLAYING state. It returns an error if
596  *           the register update operation for the background screen generation blocks or the graphics data I/F block
597  *           is being held.
598  **********************************************************************************************************************/
R_GLCDC_LayerChange(display_ctrl_t const * const p_api_ctrl,display_runtime_cfg_t const * const p_cfg,display_frame_layer_t layer)599 fsp_err_t R_GLCDC_LayerChange (display_ctrl_t const * const        p_api_ctrl,
600                                display_runtime_cfg_t const * const p_cfg,
601                                display_frame_layer_t               layer)
602 {
603     glcdc_instance_ctrl_t * p_ctrl = (glcdc_instance_ctrl_t *) p_api_ctrl;
604     FSP_PARAMETER_NOT_USED(p_ctrl);
605 
606 #if (GLCDC_CFG_PARAM_CHECKING_ENABLE)
607     FSP_ASSERT(p_ctrl);
608     FSP_ASSERT(p_cfg);
609     FSP_ERROR_RETURN((DISPLAY_STATE_DISPLAYING == p_ctrl->state), FSP_ERR_INVALID_MODE);
610 #endif
611 
612     /* Return immediately if the register updating is in progress */
613     FSP_ERROR_RETURN(false == (bool) (R_GLCDC->GR[layer].VEN_b.PVEN), FSP_ERR_INVALID_UPDATE_TIMING);
614     FSP_ERROR_RETURN(false == (bool) (R_GLCDC->BG.EN_b.VEN), FSP_ERR_INVALID_UPDATE_TIMING);
615 
616     /* Configure the graphics plane layers */
617     r_glcdc_graphics_layer_set(&p_cfg->input, &p_cfg->layer, layer);
618 
619     /* Reflect the graphics module register value to the GLCDC internal operations (at the timing of the next Vsync
620      * assertion) */
621     R_GLCDC->GR[layer].VEN_b.PVEN = 1U;
622 
623     return FSP_SUCCESS;
624 }
625 
626 /*******************************************************************************************************************//**
627  * Change the framebuffer pointer for a layer. Implements @ref display_api_t::bufferChange.
628  *
629  * @retval  FSP_SUCCESS                      Changed layer parameters of GLCDC module successfully.
630  * @retval  FSP_ERR_ASSERTION                Pointer to the control block is NULL.
631  * @retval  FSP_ERR_INVALID_MODE             A function call is performed when the driver state is not
632  *                                            DISPLAY_STATE_DISPLAYING.
633  * @retval  FSP_ERR_INVALID_ALIGNMENT        The framebuffer pointer is not 64-byte aligned.
634  * @retval  FSP_ERR_INVALID_UPDATE_TIMING    A function call is performed while the GLCDC is updating register values
635  *                                            internally.
636  * @note    This API can be called when the driver is in DISPLAY_STATE_OPENED state or higher. It returns an error if
637  *           the register update operation for the background screen generation blocks or the graphics data I/F block
638  *           is being held.
639  **********************************************************************************************************************/
R_GLCDC_BufferChange(display_ctrl_t const * const p_api_ctrl,uint8_t * const framebuffer,display_frame_layer_t layer)640 fsp_err_t R_GLCDC_BufferChange (display_ctrl_t const * const p_api_ctrl,
641                                 uint8_t * const              framebuffer,
642                                 display_frame_layer_t        layer)
643 {
644     glcdc_instance_ctrl_t * p_ctrl = (glcdc_instance_ctrl_t *) p_api_ctrl;
645     FSP_PARAMETER_NOT_USED(p_ctrl);
646 
647 #if (GLCDC_CFG_PARAM_CHECKING_ENABLE)
648     FSP_ASSERT(p_ctrl);
649     FSP_ERROR_RETURN((DISPLAY_STATE_DISPLAYING == p_ctrl->state), FSP_ERR_INVALID_MODE);
650 
651     /* Buffer address must be aligned to 64-byte boundary */
652     FSP_ERROR_RETURN(0U == (((uint32_t) framebuffer) % GLCDC_PRV_ADDRESS_ALIGNMENT_64B), FSP_ERR_INVALID_ALIGNMENT);
653 #endif
654 
655     /* Return immediately if the register updating is in progress */
656     FSP_ERROR_RETURN(false == (bool) (R_GLCDC->GR[layer].VEN_b.PVEN), FSP_ERR_INVALID_UPDATE_TIMING);
657     FSP_ERROR_RETURN(false == (bool) (R_GLCDC->BG.EN_b.VEN), FSP_ERR_INVALID_UPDATE_TIMING);
658 
659     uint32_t dispsel;
660     uint32_t flmrd;
661 
662     /* If the base address is NULL set the layer as transparent and disable read memory access */
663     if (framebuffer == NULL)
664     {
665         dispsel = GLCDC_PLANE_BLEND_TRANSPARENT;
666         flmrd   = 0U;
667     }
668     else
669     {
670         dispsel = GLCDC_PLANE_BLEND_ON_LOWER_LAYER;
671         flmrd   = 1U;
672     }
673 
674     /* Enable or disable the layer */
675     R_GLCDC->GR[layer].AB1_b.DISPSEL = dispsel & GLCDC_PRV_GR_AB1_DISPSEL_MASK; /* Set layer transparent */
676     R_GLCDC->GR[layer].FLMRD         = flmrd;
677 
678     /* Set the buffer address */
679     R_GLCDC->GR[layer].FLM2 = (uint32_t) framebuffer;
680 
681     /* Reflect the shadow registers on the next Vsync */
682     R_GLCDC->GR[layer].VEN_b.PVEN = 1U;
683 
684     return FSP_SUCCESS;
685 }
686 
687 /*******************************************************************************************************************//**
688  * Perform color correction through the GLCDC module. Implements display_api_t::correction.
689  *
690  * @retval  FSP_SUCCESS                        Color correction by GLCDC module was performed successfully.
691  * @retval  FSP_ERR_ASSERTION                  Pointer to the control block or the display correction structure is NULL.
692  * @retval  FSP_ERR_INVALID_MODE               Function call is performed when the driver state is not
693  *                                              DISPLAY_STATE_DISPLAYING.
694  * @retval  FSP_ERR_INVALID_UPDATE_TIMING      A function call is performed while the GLCDC is updating registers
695  *                                              internally.
696  * @retval  FSP_ERR_UNSUPPORTED                Feature not supported with the current configuration.
697  *
698  * @retval  FSP_ERR_INVALID_BRIGHTNESS_SETTING Invalid brightness correction setting found
699  * @note    This API can be called when the driver is in the DISPLAY_STATE_DISPLAYING state. It returns an error if
700  *           the register update operation for the background screen generation blocks or the output control block is
701  *           being held.
702  **********************************************************************************************************************/
R_GLCDC_ColorCorrection(display_ctrl_t const * const p_api_ctrl,display_correction_t const * const p_correction)703 fsp_err_t R_GLCDC_ColorCorrection (display_ctrl_t const * const       p_api_ctrl,
704                                    display_correction_t const * const p_correction)
705 {
706 #if GLCDC_CFG_COLOR_CORRECTION_ENABLE
707     glcdc_instance_ctrl_t * p_ctrl = (glcdc_instance_ctrl_t *) p_api_ctrl;
708 
709  #if (GLCDC_CFG_PARAM_CHECKING_ENABLE)
710     FSP_ASSERT(p_ctrl);
711     FSP_ASSERT(p_correction);
712     FSP_ERROR_RETURN((DISPLAY_STATE_DISPLAYING == p_ctrl->state), FSP_ERR_INVALID_MODE);
713 
714     if (p_correction->brightness.enable)
715     {
716         /* Ensure brightness settings are in range */
717         FSP_ERROR_RETURN((FSP_SUCCESS == r_glcdc_param_check_brightness(&(p_correction->brightness))),
718                          FSP_ERR_INVALID_BRIGHTNESS_SETTING);
719     }
720  #endif
721 
722     /* Return immediately if the register updatings are performed */
723     FSP_ERROR_RETURN(false == (bool) (R_GLCDC->OUT.VLATCH_b.VEN), FSP_ERR_INVALID_UPDATE_TIMING);
724     FSP_ERROR_RETURN(false == (bool) (R_GLCDC->BG.EN_b.VEN), FSP_ERR_INVALID_UPDATE_TIMING);
725 
726     /* Configure the brightness and contrast correction register setting. */
727     r_glcdc_brightness_correction(p_ctrl, &p_correction->brightness);
728     r_glcdc_contrast_correction(p_ctrl, &p_correction->contrast);
729 
730     /* Update the Output block register setting. */
731     R_GLCDC->OUT.VLATCH_b.VEN = 1U;
732 
733     return FSP_SUCCESS;
734 #else
735     FSP_PARAMETER_NOT_USED(p_api_ctrl);
736     FSP_PARAMETER_NOT_USED(p_correction);
737 
738     return FSP_ERR_UNSUPPORTED;
739 #endif
740 }
741 
742 /*******************************************************************************************************************//**
743  * Write an entire color look-up table (CLUT) in the GLCDC module. Implements display_api_t::clut.
744  *
745  * @retval  FSP_SUCCESS                    CLUT written successfully.
746  * @retval  FSP_ERR_ASSERTION              Pointer to the control block or CLUT source data is NULL.
747  * @retval  FSP_ERR_INVALID_UPDATE_TIMING  R_GLCDC_ClutEdit was already used to edit the specified CLUT this frame.
748  * @retval  FSP_ERR_INVALID_CLUT_ACCESS    Illegal CLUT entry or size is specified.
749  * @note    This API can be called any time. The written data will be used after the next vertical sync event.
750  **********************************************************************************************************************/
R_GLCDC_ClutUpdate(display_ctrl_t const * const p_api_ctrl,display_clut_cfg_t const * const p_clut_cfg,display_frame_layer_t layer)751 fsp_err_t R_GLCDC_ClutUpdate (display_ctrl_t const * const     p_api_ctrl,
752                               display_clut_cfg_t const * const p_clut_cfg,
753                               display_frame_layer_t            layer)
754 {
755     glcdc_instance_ctrl_t * p_ctrl = (glcdc_instance_ctrl_t *) p_api_ctrl;
756     FSP_PARAMETER_NOT_USED(p_ctrl);
757 
758 #if (GLCDC_CFG_PARAM_CHECKING_ENABLE)
759     FSP_ASSERT(p_ctrl);
760     FSP_ASSERT(p_clut_cfg);
761     FSP_ERROR_RETURN(g_clut_data_latched[layer], FSP_ERR_INVALID_UPDATE_TIMING);
762     FSP_ERROR_RETURN((GLCDC_PRV_CLUT_ENTRY_SIZE > p_clut_cfg->start), FSP_ERR_INVALID_CLUT_ACCESS);
763     FSP_ERROR_RETURN((GLCDC_PRV_CLUT_ENTRY_SIZE >= p_clut_cfg->size), FSP_ERR_INVALID_CLUT_ACCESS);
764 #endif
765 
766     /* Get the index of the CLUT not in use */
767     uint32_t target_plane = R_GLCDC->GR[layer].CLUTINT_b.SEL ? 0 : 1;
768 
769     /* Get the start address in the destination CLUT hardware array based on the currently selected table and layer */
770     uint32_t volatile * clut_hw = R_GLCDC->GR1_CLUT0 +
771                                   ((target_plane + (uint32_t) (layer << 1)) * GLCDC_PRV_CLUT_ENTRY_SIZE) +
772                                   p_clut_cfg->start;
773 
774     /* Copy the new CLUT data from the source memory to the CLUT SRAM in the GLCDC module */
775     memcpy((void *) clut_hw, p_clut_cfg->p_base, sizeof(uint32_t) * p_clut_cfg->size);
776 
777     /* Swap to the new CLUT table data on the next frame */
778     R_GLCDC->GR[layer].CLUTINT_b.SEL = target_plane & 1;
779 
780     return FSP_SUCCESS;
781 }
782 
783 /*******************************************************************************************************************//**
784  * Update an element of a color look-up table (CLUT) in the GLCDC module. Implements display_api_t::clutEdit.
785  *
786  * @retval  FSP_SUCCESS                  CLUT element updated successfully.
787  * @retval  FSP_ERR_ASSERTION            Pointer to the control block is NULL.
788  * @note    This API can be called any time. The written data will be used after the next vertical sync event.
789  **********************************************************************************************************************/
R_GLCDC_ClutEdit(display_ctrl_t const * const p_api_ctrl,display_frame_layer_t layer,uint8_t index,uint32_t color)790 fsp_err_t R_GLCDC_ClutEdit (display_ctrl_t const * const p_api_ctrl,
791                             display_frame_layer_t        layer,
792                             uint8_t                      index,
793                             uint32_t                     color)
794 {
795     glcdc_instance_ctrl_t * p_ctrl = (glcdc_instance_ctrl_t *) p_api_ctrl;
796     FSP_PARAMETER_NOT_USED(p_ctrl);
797 
798 #if (GLCDC_CFG_PARAM_CHECKING_ENABLE)
799     FSP_ASSERT(p_ctrl);
800 #endif
801 
802     static uint32_t volatile * clut_hw[2] = {R_GLCDC->GR1_CLUT0, R_GLCDC->GR2_CLUT0};
803 
804     /* If the previously written CLUT has been selected, switch to the unused one */
805     if (g_clut_data_latched[layer])
806     {
807         g_clut_data_latched[layer] = false;
808 
809         /* Get the index of the CLUT not in use */
810         uint32_t target_plane = R_GLCDC->GR[layer].CLUTINT_b.SEL ? 0 : 1;
811 
812         /* Get the start address of the destination CLUT hardware array */
813         uint32_t volatile * clut_hw_new = R_GLCDC->GR1_CLUT0 +
814                                           ((target_plane + (uint32_t) (layer << 1)) * GLCDC_PRV_CLUT_ENTRY_SIZE);
815 
816         /* Copy the old data to the new table then save the new table address */
817         memcpy((void *) clut_hw_new, (void *) clut_hw[layer], GLCDC_PRV_CLUT_ENTRY_SIZE * 4U);
818         clut_hw[layer] = clut_hw_new;
819 
820         /* Swap to the new CLUT table data on the next frame */
821         R_GLCDC->GR[layer].CLUTINT_b.SEL = target_plane & 1;
822     }
823 
824     /* Set the CLUT element */
825     clut_hw[layer][index] = color;
826 
827     return FSP_SUCCESS;
828 }
829 
830 /*******************************************************************************************************************//**
831  * Configuring color key is not supported for GLCDC.
832  *
833  * @retval FSP_ERR_UNSUPPORTED
834  **********************************************************************************************************************/
R_GLCDC_ColorKeySet(display_ctrl_t const * const p_api_ctrl,display_colorkeying_layer_t key_cfg,display_frame_layer_t layer)835 fsp_err_t R_GLCDC_ColorKeySet (display_ctrl_t const * const p_api_ctrl,
836                                display_colorkeying_layer_t  key_cfg,
837                                display_frame_layer_t        layer)
838 {
839     FSP_PARAMETER_NOT_USED(p_api_ctrl);
840     FSP_PARAMETER_NOT_USED(key_cfg);
841     FSP_PARAMETER_NOT_USED(layer);
842 
843     return FSP_ERR_UNSUPPORTED;
844 }
845 
846 /*******************************************************************************************************************//**
847  * Get status of GLCDC module. Implements display_api_t::statusGet.
848  *
849  * @retval  FSP_SUCCESS         Got status successfully.
850  * @retval  FSP_ERR_ASSERTION   Pointer to the control block or the status structure is NULL.
851  * @note    The GLCDC hardware starts the fading processing at the first Vsync after the previous LayerChange() call is
852  * held.
853  *      Due to this behavior of the hardware, this API may not return DISPLAY_FADE_STATUS_FADING_UNDERWAY as the fading
854  *       status, if it is called before the first Vsync after LayerChange() is called. In this case, the API returns
855  *       DISPLAY_FADE_STATUS_PENDING, instead of DISPLAY_FADE_STATUS_NOT_UNDERWAY.
856  **********************************************************************************************************************/
R_GLCDC_StatusGet(display_ctrl_t const * const p_api_ctrl,display_status_t * const p_status)857 fsp_err_t R_GLCDC_StatusGet (display_ctrl_t const * const p_api_ctrl, display_status_t * const p_status)
858 {
859     glcdc_instance_ctrl_t * p_ctrl = (glcdc_instance_ctrl_t *) p_api_ctrl;
860 
861 #if (GLCDC_CFG_PARAM_CHECKING_ENABLE)
862     FSP_ASSERT(p_ctrl);
863     FSP_ASSERT(p_status);
864 #endif
865 
866     /* Return the GLCDC HAL driver state */
867     p_status->state = p_ctrl->state;
868 
869     /* Return the fading status for the layers */
870     for (display_frame_layer_t layer = (display_frame_layer_t) 0; layer <= DISPLAY_FRAME_LAYER_2; layer++)
871     {
872         if ((bool) (R_GLCDC->GR[layer].VEN & 1U) || (g_fade_pending[layer] > g_frame_ctr))
873         {
874             /* Fading status is uncertain (the reason is described above). */
875             p_status->fade_status[layer] = DISPLAY_FADE_STATUS_PENDING;
876         }
877         else
878         {
879             if (R_GLCDC->GR[layer].MON & 1U)
880             {
881                 p_status->fade_status[layer] = DISPLAY_FADE_STATUS_FADING_UNDERWAY;
882             }
883             else
884             {
885                 p_status->fade_status[layer] = DISPLAY_FADE_STATUS_NOT_UNDERWAY;
886             }
887         }
888     }
889 
890     return FSP_SUCCESS;
891 }
892 
893 /* @} (end addtogroup GLCDC) */
894 
895 /***********************************************************************************************************************
896  * Private Functions
897  **********************************************************************************************************************/
898 
899 /*******************************************************************************************************************//**
900  * The GLCDC stop subroutine for R_GLCDC_Stop API.
901  * @param[in]     p_ctrl                       Pointer to the configuration structure for display interface
902  * @retval  FSP_SUCCESS                   Stoped successfully.
903  * @retval  FSP_ERR_INVALID_UPDATE_TIMING The function call is performed while the GLCDC is updating register values
904  *                                          internally.
905  **********************************************************************************************************************/
r_glcdc_stop(glcdc_instance_ctrl_t * const p_ctrl)906 static fsp_err_t r_glcdc_stop (glcdc_instance_ctrl_t * const p_ctrl)
907 {
908     fsp_err_t err = FSP_SUCCESS;
909 
910 #if defined(GLCDC_CFG_USING_DSI)
911 
912     /* DSI must be stopped before GLCDC. See RA8 UM R01UH0995EJ0050 Section 56.3.7.2 */
913     glcdc_extended_cfg_t * p_extend     = (glcdc_extended_cfg_t *) p_ctrl->p_cfg->p_extend;
914     mipi_dsi_instance_t  * dsi_instance = (mipi_dsi_instance_t *) p_extend->phy_layer;
915     err = dsi_instance->p_api->stop(dsi_instance->p_ctrl);
916     FSP_ERROR_RETURN(FSP_SUCCESS == err, err);
917 #endif
918 
919     /* Return immediately if the register is being updated */
920     FSP_ERROR_RETURN(false == (bool) (R_GLCDC->GR[DISPLAY_FRAME_LAYER_1].VEN_b.PVEN), FSP_ERR_INVALID_UPDATE_TIMING);
921     FSP_ERROR_RETURN(false == (bool) (R_GLCDC->GR[DISPLAY_FRAME_LAYER_2].VEN_b.PVEN), FSP_ERR_INVALID_UPDATE_TIMING);
922     FSP_ERROR_RETURN(false == (bool) (R_GLCDC->OUT.VLATCH_b.VEN), FSP_ERR_INVALID_UPDATE_TIMING);
923     FSP_ERROR_RETURN(false == (bool) (R_GLCDC->BG.EN_b.VEN), FSP_ERR_INVALID_UPDATE_TIMING);
924 
925     /* Disable background plane operation */
926     R_GLCDC->BG.EN_b.EN = 0U;
927 
928     p_ctrl->state = DISPLAY_STATE_OPENED;
929 
930     return err;
931 }
932 
933 #if (GLCDC_CFG_PARAM_CHECKING_ENABLE)
934  #if GLCDC_CFG_COLOR_CORRECTION_ENABLE
935 
936 /*******************************************************************************************************************//**
937  * The parameter checking subroutine for brightness correction.
938  * @param[in]     p_brightness   Pointer to a brightness setting struct
939  * @retval  FSP_SUCCESS                           No parameter error found
940  * @retval  FSP_ERR_INVALID_BRIGHTNESS_SETTING    Invalid brightness setting found
941  **********************************************************************************************************************/
r_glcdc_param_check_brightness(display_brightness_t const * const p_brightness)942 static fsp_err_t r_glcdc_param_check_brightness (display_brightness_t const * const p_brightness)
943 {
944     if ((p_brightness->r > GLCDC_PRV_BRIGHTNESS_MAX) ||
945         (p_brightness->g > GLCDC_PRV_BRIGHTNESS_MAX) ||
946         (p_brightness->b > GLCDC_PRV_BRIGHTNESS_MAX))
947     {
948         return FSP_ERR_INVALID_BRIGHTNESS_SETTING;
949     }
950 
951     return FSP_SUCCESS;
952 }
953 
954 /*******************************************************************************************************************//**
955  * The parameter checking subroutine for R_GLCDC_Open API.
956  * @param[in]     p_gamma_correction   Pointer to the gamma configuration struct
957  * @retval  FSP_SUCCESS                      No parameter error found
958  * @retval  FSP_ERR_ASSERTION                Gain or threshold table pointers are NULL
959  * @retval  FSP_ERR_INVALID_GAMMA_SETTING    Invalid gamma correction setting found
960  **********************************************************************************************************************/
r_glcdc_param_check_gamma_correction(gamma_correction_t const * const p_gamma_correction)961 static fsp_err_t r_glcdc_param_check_gamma_correction (gamma_correction_t const * const p_gamma_correction)
962 {
963     uint16_t previous_threshold = 0;
964 
965     /* Verify gain/threshold tables are not NULL */
966     FSP_ASSERT(p_gamma_correction->gain);
967     FSP_ASSERT(p_gamma_correction->threshold);
968 
969     for (int32_t i = 0; i < DISPLAY_GAMMA_CURVE_ELEMENT_NUM; i++)
970     {
971         /* Each of the gamma correction threshold values must be less than GLCDC_PRV_GAMMA_THRESHOLD_MAX */
972         FSP_ERROR_RETURN((GLCDC_PRV_GAMMA_THRESHOLD_MAX >= p_gamma_correction->threshold[i]),
973                          FSP_ERR_INVALID_GAMMA_SETTING);
974 
975         /* The Gamma correction threshold[N] must be less than threshold[N+1] */
976         FSP_ERROR_RETURN(previous_threshold <= p_gamma_correction->threshold[i], FSP_ERR_INVALID_GAMMA_SETTING);
977         previous_threshold = p_gamma_correction->threshold[i];
978 
979         /* Each of gamma correction gain values must be less than GLCDC_PRV_GAMMA_GAIN_MAX */
980         FSP_ERROR_RETURN((GLCDC_PRV_GAMMA_GAIN_MAX >= p_gamma_correction->gain[i]), FSP_ERR_INVALID_GAMMA_SETTING);
981     }
982 
983     return FSP_SUCCESS;
984 }
985 
986  #endif
987 
988 /*******************************************************************************************************************//**
989  * The parameter checking subroutine for the R_GLCDC_Open API.
990  * @param[in]     p_cfg   Pointer to the configuration structure for display interface
991  * @param[in]     layer   Layer number to check
992  * @retval  FSP_SUCCESS                      No parameter error found
993  * @retval  FSP_ERR_INVALID_ALIGNMENT        Invalid setting for base address and memory stride
994  **********************************************************************************************************************/
r_glcdc_param_check_layer_setting_alignment(display_cfg_t const * const p_cfg,display_frame_layer_t layer)995 static fsp_err_t r_glcdc_param_check_layer_setting_alignment (display_cfg_t const * const p_cfg,
996                                                               display_frame_layer_t       layer)
997 {
998     /* Base address and memory stride have to be aligned to 64-byte boundary */
999     FSP_ERROR_RETURN(0U == ((uint32_t) (p_cfg->input[layer].p_base) % GLCDC_PRV_ADDRESS_ALIGNMENT_64B),
1000                      FSP_ERR_INVALID_ALIGNMENT);
1001     FSP_ERROR_RETURN((uint16_t) 0 ==
1002                      (((p_cfg->input[layer].hstride *
1003                         r_glcdc_get_bit_size(p_cfg->input[layer].format)) >> 3) % GLCDC_PRV_ADDRESS_ALIGNMENT_64B),
1004                      FSP_ERR_INVALID_ALIGNMENT);
1005 
1006     return FSP_SUCCESS;
1007 }
1008 
1009 /*******************************************************************************************************************//**
1010  * This is the parameter checking subroutine for the R_GLCDC_Open API.
1011  * @param[in]     p_cfg   Pointer to the configuration structure for display interface
1012  * @retval  FSP_SUCCESS                      No parameter error found
1013  * @retval  FSP_ERR_INVALID_TIMING_SETTING   Invalid panel timing parameter
1014  **********************************************************************************************************************/
r_glcdc_param_check_display_cycle(display_cfg_t const * const p_cfg)1015 static fsp_err_t r_glcdc_param_check_display_cycle (display_cfg_t const * const p_cfg)
1016 {
1017     FSP_ERROR_RETURN((GLCDC_PRV_BG_PLANE_H_CYC_MIN <= p_cfg->output.htiming.total_cyc) &&
1018                      (GLCDC_PRV_BG_PLANE_H_CYC_MAX >= p_cfg->output.htiming.total_cyc),
1019                      FSP_ERR_INVALID_TIMING_SETTING);
1020     FSP_ERROR_RETURN((GLCDC_PRV_BG_PLANE_V_CYC_MIN <= p_cfg->output.vtiming.total_cyc) &&
1021                      (GLCDC_PRV_BG_PLANE_V_CYC_MAX >= p_cfg->output.vtiming.total_cyc),
1022                      FSP_ERR_INVALID_TIMING_SETTING);
1023     FSP_ERROR_RETURN((GLCDC_PRV_BG_PLANE_H_CYC_ACTIVE_SIZE_MIN <= p_cfg->output.htiming.display_cyc) &&
1024                      (GLCDC_PRV_BG_PLANE_H_CYC_ACTIVE_SIZE_MAX >= p_cfg->output.htiming.display_cyc),
1025                      FSP_ERR_INVALID_TIMING_SETTING);
1026     FSP_ERROR_RETURN((GLCDC_PRV_BG_PLANE_V_CYC_ACTIVE_SIZE_MIN <= p_cfg->output.vtiming.display_cyc) &&
1027                      (GLCDC_PRV_BG_PLANE_V_CYC_ACTIVE_SIZE_MAX >= p_cfg->output.vtiming.display_cyc),
1028                      FSP_ERR_INVALID_TIMING_SETTING);
1029 
1030     return FSP_SUCCESS;
1031 }
1032 
1033 /*******************************************************************************************************************//**
1034  * This is the parameter checking subroutine for the R_GLCDC_Open API.
1035  * @param[in]     p_cfg   Pointer to the configuration structure for display interface
1036  * @retval  FSP_SUCCESS                      No parameter error found
1037  * @retval  FSP_ERR_INVALID_TIMING_SETTING   Invalid panel timing parameter
1038  **********************************************************************************************************************/
r_glcdc_param_check_display_timing(display_cfg_t const * const p_cfg)1039 static fsp_err_t r_glcdc_param_check_display_timing (display_cfg_t const * const p_cfg)
1040 {
1041     /* p_cfg->output.htiming.back_porch / p_cfg->output.vtiming.back_porch
1042      * |_ <Sync> __________________________________
1043      * | |______|    |
1044      * |1|<---BP---->|
1045      *                ^GLCDC_PRV_BG_PLANE_X_CYC_ACTIVE_POS_xxx
1046      */
1047     FSP_ERROR_RETURN(((GLCDC_PRV_BG_PLANE_H_CYC_ACTIVE_POS_MIN - GLCDC_PRV_BG_PLANE_HSYNC_POS_MIN) <=
1048                       p_cfg->output.htiming.back_porch) &&
1049                      ((GLCDC_PRV_BG_PLANE_H_CYC_ACTIVE_POS_MAX - GLCDC_PRV_BG_PLANE_HSYNC_POS_MIN) >=
1050                       p_cfg->output.htiming.back_porch),
1051                      FSP_ERR_INVALID_TIMING_SETTING);
1052     FSP_ERROR_RETURN(((GLCDC_PRV_BG_PLANE_V_CYC_ACTIVE_POS_MIN - GLCDC_PRV_BG_PLANE_VSYNC_POS_MIN) <=
1053                       p_cfg->output.vtiming.back_porch) &&
1054                      ((GLCDC_PRV_BG_PLANE_V_CYC_ACTIVE_POS_MAX - GLCDC_PRV_BG_PLANE_VSYNC_POS_MIN) >=
1055                       p_cfg->output.vtiming.back_porch),
1056                      FSP_ERR_INVALID_TIMING_SETTING);
1057     FSP_ERROR_RETURN((GLCDC_PRV_TCON_SIGNAL_ASSERT_WIDTH_MAX >= p_cfg->output.htiming.sync_width),
1058                      FSP_ERR_INVALID_TIMING_SETTING);
1059     FSP_ERROR_RETURN((GLCDC_PRV_TCON_SIGNAL_ASSERT_WIDTH_MAX >= p_cfg->output.vtiming.sync_width),
1060                      FSP_ERR_INVALID_TIMING_SETTING);
1061 
1062     /* See S7G2 H/W manual figure 57.26 about 3cycles */
1063     FSP_ERROR_RETURN((p_cfg->output.htiming.total_cyc >=
1064                       (p_cfg->output.htiming.back_porch + p_cfg->output.htiming.display_cyc + 3)),
1065                      FSP_ERR_INVALID_TIMING_SETTING);
1066 
1067     return FSP_SUCCESS;
1068 }
1069 
1070 /*******************************************************************************************************************//**
1071  * This is the parameter checking subroutine for the R_GLCDC_Open API.
1072  * @param[in]     p_cfg   Pointer to the configuration structure for display interface
1073  * @retval  FSP_SUCCESS                      No parameter error found
1074  * @retval  FSP_ERR_INVALID_TIMING_SETTING   Invalid panel timing parameter
1075  **********************************************************************************************************************/
r_glcdc_open_param_check_sync_signal(display_cfg_t const * const p_cfg)1076 static fsp_err_t r_glcdc_open_param_check_sync_signal (display_cfg_t const * const p_cfg)
1077 {
1078     fsp_err_t error;
1079 
1080     error = r_glcdc_param_check_display_cycle(p_cfg);
1081     FSP_ERROR_RETURN(FSP_SUCCESS == error, error);
1082 
1083     error = r_glcdc_param_check_display_timing(p_cfg);
1084     FSP_ERROR_RETURN(FSP_SUCCESS == error, error);
1085 
1086     /* See RA6M3 User's Manual (R01UH0886EJ0100) Figure 58.26 "Definition of background screen" for explanation of +2 */
1087     FSP_ERROR_RETURN((p_cfg->output.vtiming.total_cyc >=
1088                       (p_cfg->output.vtiming.back_porch + p_cfg->output.vtiming.display_cyc + 2)),
1089                      FSP_ERR_INVALID_TIMING_SETTING);
1090 
1091     return FSP_SUCCESS;
1092 }
1093 
1094 /*******************************************************************************************************************//**
1095  * The parameter checking subroutine for the R_GLCDC_Open API.
1096  * @param[in]     p_cfg   Pointer to the configuration structure for display interface
1097  * @retval  FSP_SUCCESS                      No parameter error found
1098  * @retval  FSP_ERR_INVALID_LAYER_SETTING    Invalid layer setting found
1099  * @retval  FSP_ERR_INVALID_ALIGNMENT        Invalid setting for base address and memory stride
1100  **********************************************************************************************************************/
r_glcdc_open_param_check_layer_setting(display_cfg_t const * const p_cfg)1101 static fsp_err_t r_glcdc_open_param_check_layer_setting (display_cfg_t const * const p_cfg)
1102 {
1103     fsp_err_t error;
1104     for (uint32_t i = 0U; i <= DISPLAY_FRAME_LAYER_2; i++)
1105     {
1106         if (p_cfg->input[i].p_base)
1107         {
1108             error = r_glcdc_param_check_layer_setting_alignment(p_cfg, (display_frame_layer_t) i);
1109             FSP_ERROR_RETURN(FSP_SUCCESS == error, error);
1110 
1111             /* Check horizontal/vertical pixels is less than or equal to maximum value, also horizontal pixel
1112              * must not be an odd value. Horizontal check is intently not performed because of supporting line
1113              * repeating mode.*/
1114 
1115             uint16_t vline_size = p_cfg->input[i].vsize;
1116             if (p_cfg->input[i].lines_repeat_enable)
1117             {
1118                 vline_size = (uint16_t) (vline_size * p_cfg->input[i].lines_repeat_times);
1119             }
1120 
1121             FSP_ERROR_RETURN((GLCDC_PRV_GR_PLANE_V_CYC_ACTIVE_SIZE_MAX >= vline_size), FSP_ERR_INVALID_LAYER_SETTING);
1122 
1123             /* Check horizontal/vertical pixels is less than or equal to the maximum value, also horizontal pixel must
1124              * not be an odd value*/
1125             FSP_ERROR_RETURN((uint16_t) 0 == ((p_cfg->input[i].hsize) % (uint16_t) 2), FSP_ERR_INVALID_LAYER_SETTING);
1126 
1127             /* Check the number of data transfer times per a line (64bytes/transfer) */
1128             FSP_ERROR_RETURN((GLCDC_PRV_GR_PLANE_TOTAL_TRANSFER_TIMES_MAX >=
1129                               (((p_cfg->input[i].hstride *
1130                                  r_glcdc_get_bit_size(p_cfg->input[i].format)) / 8) /
1131                                GLCDC_PRV_ADDRESS_ALIGNMENT_64B)),
1132                              FSP_ERR_INVALID_LAYER_SETTING);
1133         }
1134     }
1135 
1136     return FSP_SUCCESS;
1137 }
1138 
1139  #if GLCDC_CFG_COLOR_CORRECTION_ENABLE
1140 
1141 /*******************************************************************************************************************//**
1142  * The parameter checking subroutine for R_GLCDC_Open API.
1143  * @param[in]     p_cfg   Pointer to the configuration structure for display interface
1144  * @retval  FSP_SUCCESS                        No parameter error found
1145  * @retval  FSP_ERR_ASSERTION                  Gain or threshold table pointers are NULL
1146  * @retval  FSP_ERR_INVALID_GAMMA_SETTING      Invalid gamma correction setting found
1147  * @retval  FSP_ERR_INVALID_BRIGHTNESS_SETTING Invalid brightness correction setting found
1148  **********************************************************************************************************************/
r_glcdc_open_param_check_correction_setting(display_cfg_t const * const p_cfg)1149 static fsp_err_t r_glcdc_open_param_check_correction_setting (display_cfg_t const * const p_cfg)
1150 {
1151     fsp_err_t error;
1152 
1153     if (p_cfg->output.brightness.enable)
1154     {
1155         error = r_glcdc_param_check_brightness(&(p_cfg->output.brightness));
1156         FSP_ERROR_RETURN(FSP_SUCCESS == error, error);
1157     }
1158 
1159     if (p_cfg->output.p_gamma_correction)
1160     {
1161         if (p_cfg->output.p_gamma_correction->b.enable)
1162         {
1163             error = r_glcdc_param_check_gamma_correction(&(p_cfg->output.p_gamma_correction->b));
1164             FSP_ERROR_RETURN(FSP_SUCCESS == error, error);
1165         }
1166 
1167         if (p_cfg->output.p_gamma_correction->g.enable)
1168         {
1169             error = r_glcdc_param_check_gamma_correction(&(p_cfg->output.p_gamma_correction->g));
1170             FSP_ERROR_RETURN(FSP_SUCCESS == error, error);
1171         }
1172 
1173         if (p_cfg->output.p_gamma_correction->r.enable)
1174         {
1175             error = r_glcdc_param_check_gamma_correction(&(p_cfg->output.p_gamma_correction->r));
1176             FSP_ERROR_RETURN(FSP_SUCCESS == error, error);
1177         }
1178     }
1179 
1180     return FSP_SUCCESS;
1181 }
1182 
1183  #endif
1184 
1185 /*******************************************************************************************************************//**
1186  * The parameter checking subroutine for R_GLCDC_Open API.
1187  * @param[in] p_cfg   Pointer to the configuration structure for display interface
1188  * @retval  FSP_SUCCESS                        No parameter error found
1189  * @retval  FSP_ERR_ASSERTION                  Pointer to the control block is NULL
1190  * @retval  FSP_ERR_CLOCK_GENERATION           Clock ratio setting is invalid
1191  * @retval  FSP_ERR_INVALID_TIMING_SETTING     Invalid panel timing parameter
1192  * @retval  FSP_ERR_INVALID_LAYER_SETTING      Invalid layer setting found
1193  * @retval  FSP_ERR_INVALID_ALIGNMENT          Input data alignment invalid
1194  * @retval  FSP_ERR_INVALID_GAMMA_SETTING      Invalid gamma correction setting found
1195  * @retval  FSP_ERR_INVALID_BRIGHTNESS_SETTING Invalid brightness correction setting found
1196  **********************************************************************************************************************/
r_glcdc_open_param_check(display_cfg_t const * const p_cfg)1197 static fsp_err_t r_glcdc_open_param_check (display_cfg_t const * const p_cfg)
1198 {
1199     fsp_err_t error;
1200 
1201     FSP_ASSERT(p_cfg);
1202     FSP_ASSERT(p_cfg->p_extend);
1203 
1204     glcdc_extended_cfg_t * pextend = (glcdc_extended_cfg_t *) p_cfg->p_extend;
1205 
1206     /* Sync signal parameter check */
1207     error = r_glcdc_open_param_check_sync_signal(p_cfg);
1208     FSP_ERROR_RETURN(FSP_SUCCESS == error, error);
1209 
1210     /* Layer setting parameter check */
1211     error = r_glcdc_open_param_check_layer_setting(p_cfg);
1212     FSP_ERROR_RETURN(FSP_SUCCESS == error, error);
1213 
1214  #if GLCDC_CFG_COLOR_CORRECTION_ENABLE
1215 
1216     /* Color correction setting parameter check */
1217     error = r_glcdc_open_param_check_correction_setting(p_cfg);
1218     FSP_ERROR_RETURN(FSP_SUCCESS == error, error);
1219  #endif
1220 
1221     /* Ensure clock division ratio is initialized */
1222     FSP_ERROR_RETURN(0 != pextend->clock_div_ratio, FSP_ERR_CLOCK_GENERATION);
1223 
1224     return FSP_SUCCESS;
1225 }
1226 
1227 #endif
1228 
1229 /*******************************************************************************************************************//**
1230  * Subroutine to configure dot clock setting
1231  * @param[in]     p_cfg        Pointer to the configuration structure for display interface
1232  * @retval        void
1233  **********************************************************************************************************************/
r_glcdc_clock_set(display_cfg_t const * const p_cfg)1234 static void r_glcdc_clock_set (display_cfg_t const * const p_cfg)
1235 {
1236     glcdc_extended_cfg_t * pextend = (glcdc_extended_cfg_t *) p_cfg->p_extend;
1237 
1238     /* Build PANEL_CLK bitfields */
1239     uint32_t pixsel =
1240         ((DISPLAY_OUT_FORMAT_8BITS_SERIAL !=
1241           p_cfg->output.format) ? 0 : GLCDC_PRV_SYSCNT_PANEL_CLK_PIXSEL_SERIALRGB);
1242     uint32_t clksel = ((GLCDC_CLK_SRC_INTERNAL == pextend->clksrc) ? GLCDC_PRV_SYSCNT_PANEL_CLK_CLKSEL_PLL : 0);
1243     uint32_t clken  = GLCDC_PRV_SYSCNT_PANEL_CLK_CLKEN_ENABLE;
1244     uint32_t dcdr   = (pextend->clock_div_ratio & GLCDC_PRV_SYSCNT_PANEL_CLK_DCDR_MASK);
1245 
1246     /* Set panel clock configuration */
1247     R_GLCDC->SYSCNT.PANEL_CLK = pixsel | clksel | clken | dcdr;
1248 }
1249 
1250 /*******************************************************************************************************************//**
1251  * Subroutine to configure the sync signal setting (TCON block setting)
1252  * @param[in]     p_cfg        Pointer to the configuration structure for display interface
1253  * @retval        void
1254  **********************************************************************************************************************/
r_glcdc_sync_signal_set(display_cfg_t const * const p_cfg)1255 static void r_glcdc_sync_signal_set (display_cfg_t const * const p_cfg)
1256 {
1257     glcdc_extended_cfg_t * pextend = (glcdc_extended_cfg_t *) p_cfg->p_extend;
1258     glcdc_tcon_pin_t       tcon_hsync;
1259     glcdc_tcon_pin_t       tcon_vsync;
1260     glcdc_tcon_pin_t       tcon_de;
1261 
1262     /* Because this function is called before gamma correction is enabled we can clobber the CLKPHASE register */
1263     if (DISPLAY_SIGNAL_SYNC_EDGE_RISING == p_cfg->output.sync_edge)
1264     {
1265         /* Set all phases to rising edge */
1266         R_GLCDC->OUT.CLKPHASE = GLCDC_PRV_OUT_CLKPHASE_ALL_RISING;
1267     }
1268     else
1269     {
1270         /* Set all phases to falling edge */
1271         R_GLCDC->OUT.CLKPHASE = GLCDC_PRV_OUT_CLKPHASE_ALL_FALLING;
1272     }
1273 
1274     /* Clear signal reference timing */
1275     R_GLCDC->TCON.TIM = 0;
1276 
1277     tcon_hsync = pextend->tcon_hsync;
1278     tcon_vsync = pextend->tcon_vsync;
1279     tcon_de    = pextend->tcon_de;
1280 
1281     if (GLCDC_TCON_PIN_NONE != tcon_hsync)
1282     {
1283         r_glcdc_hsync_set(tcon_hsync, &p_cfg->output.htiming);
1284     }
1285 
1286     if (GLCDC_TCON_PIN_NONE != tcon_vsync)
1287     {
1288         r_glcdc_vsync_set(tcon_vsync, &p_cfg->output.vtiming);
1289     }
1290 
1291     if (GLCDC_TCON_PIN_NONE != tcon_de)
1292     {
1293         r_glcdc_data_enable_set(tcon_de,
1294                                 &p_cfg->output.vtiming,
1295                                 &p_cfg->output.htiming,
1296                                 p_cfg->output.data_enable_polarity);
1297     }
1298 }
1299 
1300 /*******************************************************************************************************************//**
1301  * Subroutine to configure a TCON signal output
1302  * @param[in]     tcon         TCON pin select(GLCDC_TCON_PIN_0|GLCDC_TCON_PIN_1|GLCDC_TCON_PIN_2|GLCDC_TCON_PIN_3)
1303  * @param[in]     signal       Signal to output
1304  * @param[in]     polarity     Signal polarity
1305  * @retval        void
1306  **********************************************************************************************************************/
r_glcdc_tcon_set(glcdc_tcon_pin_t tcon,glcdc_tcon_signal_select_t signal,display_signal_polarity_t polarity)1307 static void r_glcdc_tcon_set (glcdc_tcon_pin_t           tcon,
1308                               glcdc_tcon_signal_select_t signal,
1309                               display_signal_polarity_t  polarity)
1310 {
1311     /* Set signal polarity */
1312     if (DISPLAY_SIGNAL_POLARITY_LOACTIVE == polarity)
1313     {
1314         /* Set INV bit depending on register */
1315         if (GLCDC_TCON_SIGNAL_SELECT_DE != signal)
1316         {
1317             *g_tcon_lut[signal] |= GLCDC_PRV_TCON_STXX2_INV_SET;
1318         }
1319         else
1320         {
1321             R_GLCDC->TCON.DE = 1;
1322         }
1323     }
1324 
1325     /* Set TCON signal */
1326     *g_tcon_lut[tcon] |= signal;
1327 }
1328 
1329 /*******************************************************************************************************************//**
1330  * Subroutine to configure the horizontal signal setting
1331  * @param[in]     tcon        TCON pin select(GLCDC_TCON_PIN_0|GLCDC_TCON_PIN_1|GLCDC_TCON_PIN_2|GLCDC_TCON_PIN_3)
1332  * @param[in]     timing      Hsync signal timing
1333  * @retval        void
1334  **********************************************************************************************************************/
r_glcdc_hsync_set(glcdc_tcon_pin_t tcon,display_timing_t const * timing)1335 static void r_glcdc_hsync_set (glcdc_tcon_pin_t tcon, display_timing_t const * timing)
1336 {
1337     r_glcdc_tcon_set(tcon, GLCDC_TCON_SIGNAL_SELECT_STHA_HS, timing->sync_polarity);
1338 
1339     R_GLCDC->TCON.STHA1 = timing->sync_width & GLCDC_PRV_TCON_STHX1_HW_MASK;
1340 }
1341 
1342 /*******************************************************************************************************************//**
1343  * Subroutine to configure the vertical signal setting
1344  * @param[in]     tcon        TCON pin select(GLCDC_TCON_PIN_0|GLCDC_TCON_PIN_1|GLCDC_TCON_PIN_2|GLCDC_TCON_PIN_3)
1345  * @param[in]     timing      Vsync signal timing
1346  * @retval        void
1347  **********************************************************************************************************************/
r_glcdc_vsync_set(glcdc_tcon_pin_t tcon,display_timing_t const * const timing)1348 static void r_glcdc_vsync_set (glcdc_tcon_pin_t tcon, display_timing_t const * const timing)
1349 {
1350     r_glcdc_tcon_set(tcon, GLCDC_TCON_SIGNAL_SELECT_STVA_VS, timing->sync_polarity);
1351 
1352     R_GLCDC->TCON.STVA1 = timing->sync_width & GLCDC_PRV_TCON_STVX1_VW_MASK;
1353 }
1354 
1355 /*******************************************************************************************************************//**
1356  * Subroutine to configure the data enable(DE) signal setting
1357  * @param[in]     tcon        TCON pin select(GLCDC_TCON_PIN_0|GLCDC_TCON_PIN_1|GLCDC_TCON_PIN_2|GLCDC_TCON_PIN_3)
1358  * @param[in]     vtiming     DE signal vertical timing
1359  * @param[in]     htiming     DE signal horizontal timing
1360  * @param[in]     polarity    DE signal porarity(DISPLAY_SIGNAL_POLARITY_LOACTIVE|DISPLAY_SIGNAL_POLARITY_HIACTIVE)
1361  * @retval        void
1362  **********************************************************************************************************************/
r_glcdc_data_enable_set(glcdc_tcon_pin_t const tcon,display_timing_t const * const vtiming,display_timing_t const * const htiming,display_signal_polarity_t const polarity)1363 static void r_glcdc_data_enable_set (glcdc_tcon_pin_t const          tcon,
1364                                      display_timing_t const * const  vtiming,
1365                                      display_timing_t const * const  htiming,
1366                                      display_signal_polarity_t const polarity)
1367 {
1368     r_glcdc_tcon_set(tcon, GLCDC_TCON_SIGNAL_SELECT_DE, polarity);
1369 
1370     R_GLCDC->TCON.STHB1 = ((htiming->back_porch & GLCDC_PRV_TCON_STHX1_HS_MASK) << 16) +
1371                           (htiming->display_cyc & GLCDC_PRV_TCON_STHX1_HW_MASK);
1372     R_GLCDC->TCON.STVB1 = ((vtiming->back_porch & GLCDC_PRV_TCON_STVX1_VS_MASK) << 16) +
1373                           (vtiming->display_cyc & GLCDC_PRV_TCON_STVX1_VW_MASK);
1374 }
1375 
1376 /*******************************************************************************************************************//**
1377  * Subroutine to configure the background screen setting
1378  *          - Panel timing setting
1379  *          - Color setting for the background screen
1380  * @param[in]     p_cfg      Pointer to the configuration structure for display interface
1381  * @retval        void
1382  **********************************************************************************************************************/
r_glcdc_background_screen_set(display_cfg_t const * const p_cfg)1383 static void r_glcdc_background_screen_set (display_cfg_t const * const p_cfg)
1384 {
1385     /* Set number of total cycles for a line including sync, back porch and Front porch */
1386     R_GLCDC->BG.PERI = ((p_cfg->output.vtiming.total_cyc & GLCDC_PRV_BG_PERI_FV_MASK) << 16) +
1387                        (p_cfg->output.htiming.total_cyc & GLCDC_PRV_BG_PERI_FH_MASK);
1388     R_GLCDC->BG.SYNC = ((GLCDC_PRV_BG_PLANE_VSYNC_POS_MIN & GLCDC_PRV_BG_SYNC_VP_MASK) << 16) +
1389                        (GLCDC_PRV_BG_PLANE_HSYNC_POS_MIN & GLCDC_PRV_BG_SYNC_HP_MASK);
1390 
1391     /* Set the start position and width of the background screen */
1392     R_GLCDC->BG.HSIZE = ((((uint32_t) (p_cfg->output.htiming.back_porch) + GLCDC_PRV_BG_PLANE_HSYNC_POS_MIN) &
1393                           GLCDC_PRV_BG_HSIZE_HP_MASK) << 16) +
1394                         (p_cfg->output.htiming.display_cyc & GLCDC_PRV_BG_HSIZE_HW_MASK);
1395     R_GLCDC->BG.VSIZE = ((((uint32_t) (p_cfg->output.vtiming.back_porch) + GLCDC_PRV_BG_PLANE_VSYNC_POS_MIN) &
1396                           GLCDC_PRV_BG_VSIZE_VP_MASK) << 16) +
1397                         (p_cfg->output.vtiming.display_cyc & GLCDC_PRV_BG_VSIZE_VW_MASK);
1398 
1399     /* Set the background color */
1400     R_GLCDC->BG.BGC = ((uint32_t) (p_cfg->output.bg_color.byte.r) << 16) +
1401                       ((uint32_t) (p_cfg->output.bg_color.byte.g) << 8) +
1402                       ((uint32_t) (p_cfg->output.bg_color.byte.b));
1403 }
1404 
1405 /*******************************************************************************************************************//**
1406  * Subroutine to configure the blending setting for the graphics planes
1407  * @param[in]     p_layer     The layer configuration
1408  * @param[in]     layer       Layer number
1409  * @retval        void
1410  * @note    This function does not perform parameter check and it would be expected to be done in the caller function.
1411  **********************************************************************************************************************/
r_glcdc_graphics_layer_blend_condition_set(display_layer_t const * const p_layer,display_frame_layer_t const layer)1412 static void r_glcdc_graphics_layer_blend_condition_set (display_layer_t const * const p_layer,
1413                                                         display_frame_layer_t const   layer)
1414 {
1415     uint32_t arcon_temp = 0;
1416     uint32_t ab6_temp;
1417     uint32_t ab7_temp;
1418 
1419     if (DISPLAY_FADE_CONTROL_NONE != p_layer->fade_control)
1420     {
1421         /* Enable alpha blending */
1422         arcon_temp = GLCDC_PRV_GR_AB1_ARCON_SET;
1423 
1424         /* Set AB6 and AB7 for fade in or fade out */
1425         if (DISPLAY_FADE_CONTROL_FADEIN == p_layer->fade_control)
1426         {
1427             ab7_temp = (GLCDC_FADING_CONTROL_INITIAL_ALPHA_MIN & GLCDC_PRV_GR_AB7_ARCDEF_MASK) << 16;
1428             ab6_temp = ((uint32_t) p_layer->fade_speed & GLCDC_PRV_GR_AB6_ARCCOEF_MASK) << 16;
1429         }
1430         else
1431         {
1432             ab7_temp = (GLCDC_FADING_CONTROL_INITIAL_ALPHA_MAX & GLCDC_PRV_GR_AB7_ARCDEF_MASK) << 16;
1433             ab6_temp = ((uint32_t) (p_layer->fade_speed | (1U << 8)) & GLCDC_PRV_GR_AB6_ARCCOEF_MASK) << 16;
1434         }
1435 
1436         R_GLCDC->GR[layer].AB6 = ab6_temp;
1437         R_GLCDC->GR[layer].AB7 = ab7_temp;
1438 
1439         /* Set g_fade_pending flag to inform R_GLCDC_StatusGet that a fade is scheduled */
1440         g_fade_pending[layer] = g_frame_ctr + 2;
1441     }
1442 
1443     /* Set blend mode and enable if configured */
1444     R_GLCDC->GR[layer].AB1 = (GLCDC_PLANE_BLEND_ON_LOWER_LAYER & GLCDC_PRV_GR_AB1_DISPSEL_MASK) + arcon_temp;
1445 
1446     /* Graphics data read enable */
1447     R_GLCDC->GR[layer].FLMRD = 1U;
1448 }
1449 
1450 /*******************************************************************************************************************//**
1451  * Subroutine to recalculate the configuration for the graphics planes. This routine recalculates the layer
1452  *           configuration if the layer is beyond the left/right/top/bottom end of the active video region.
1453  * @param[in]     p_input         The input frame buffer configuration
1454  * @param[in]     p_layer         The layer configuration
1455  * @param[in,out] p_recalculated  Pointer to store recalculated parameter
1456  * @retval        void
1457  **********************************************************************************************************************/
r_glcdc_graphics_layer_param_recalculation(display_input_cfg_t const * const p_input,display_layer_t const * const p_layer,glcdc_recalculated_param_t * p_recalculated)1458 static void r_glcdc_graphics_layer_param_recalculation (display_input_cfg_t const * const p_input,
1459                                                         display_layer_t const * const     p_layer,
1460                                                         glcdc_recalculated_param_t      * p_recalculated)
1461 {
1462     uint16_t bit_size    = r_glcdc_get_bit_size(p_input->format);
1463     int32_t  line_offset = (int32_t) ((p_input->hstride * bit_size) / 8);
1464 
1465     p_recalculated->hpix_size   = 0U;
1466     p_recalculated->vpix_size   = 0U;
1467     p_recalculated->hpix_offset = 0;
1468     p_recalculated->vpix_offset = 0;
1469 
1470     r_glcdc_pixel_size_recalculate(p_input, p_layer, p_recalculated, bit_size);
1471 
1472     int16_t coord_y = p_layer->coordinate.y;
1473 
1474     /* Get data size to be read in a line */
1475     p_recalculated->hread_size = ((uint32_t) p_recalculated->hpix_size * bit_size) / 8;
1476 
1477     /* If line repeat mode is enabled, data number to be read (in a line) is multiplied by line number of image */
1478     if (p_input->lines_repeat_enable)
1479     {
1480         p_recalculated->hread_size *= p_input->vsize;
1481     }
1482 
1483     /* Calculate data size to be aligned to a 64-byte boundary. This is required by hardware */
1484     if (p_recalculated->hread_size % GLCDC_PRV_ADDRESS_ALIGNMENT_64B)
1485     {
1486         p_recalculated->hread_size = (p_recalculated->hread_size & (uint32_t) (~0x3F)) + // NOLINT(readability-magic-numbers)
1487                                      GLCDC_PRV_ADDRESS_ALIGNMENT_64B;
1488     }
1489 
1490     if ((g_ctrl_blk.vsize >= coord_y) && (0 <= coord_y))
1491     {
1492         /* If graphics layer offset is less than or equal to display window size, calculate the actual pixel size to
1493          * display */
1494         if ((g_ctrl_blk.vsize - coord_y) < p_input->vsize)
1495         {
1496             /* Actual pixel size to display is less than display window size */
1497             p_recalculated->vpix_size = (uint16_t) (g_ctrl_blk.vsize - coord_y);
1498         }
1499         else
1500         {
1501             /* Actual pixel size to display is the same as display window size */
1502             p_recalculated->vpix_size = p_input->vsize;
1503         }
1504 
1505         p_recalculated->vpix_offset = coord_y;
1506     }
1507     else if ((0 > coord_y) && (p_input->vsize + coord_y > 0))
1508     {
1509         /* If the offset of the graphics layer is less than the top end of display window but some part of the layer
1510          * may still be visible, calculate actual pixel size to display */
1511 
1512         /* Calculate actual pixel size, the pixels to be displayed is less than the display window size */
1513         p_recalculated->vpix_size     = (uint16_t) (p_input->vsize + coord_y);
1514         p_recalculated->base_address += (uint32_t) (line_offset * ((coord_y) * (-1)));
1515     }
1516     else
1517     {
1518         p_recalculated->vpix_size = 0U;
1519     }
1520 }
1521 
1522 /*******************************************************************************************************************//**
1523  * Subroutine to configure the graphics layer register settings which includes...
1524  *          - Blend setting of foreground or background plane on background plane
1525  *          - Rectangle area blending settings
1526  * @param[in]     p_input         The input frame buffer configuration
1527  * @param[in]     p_layer         The layer configuration
1528  * @param[in]     layer           Layer number
1529  * @retval        void
1530  * @note    This function does not perform parameter check and it would be expected to be done in the caller function.
1531  **********************************************************************************************************************/
r_glcdc_graphics_layer_set(display_input_cfg_t const * const p_input,display_layer_t const * const p_layer,display_frame_layer_t const layer)1532 static void r_glcdc_graphics_layer_set (display_input_cfg_t const * const p_input,
1533                                         display_layer_t const * const     p_layer,
1534                                         display_frame_layer_t const       layer)
1535 {
1536     uint32_t bit_size    = r_glcdc_get_bit_size(p_input->format);
1537     int32_t  line_offset = (int32_t) ((p_input->hstride * bit_size) / 8);
1538     glcdc_recalculated_param_t recalculated;
1539     uint32_t lnnum_temp;
1540     uint32_t grcvw_temp;
1541     uint32_t arcvw_temp;
1542 
1543     /* If the base address is NULL, just set the layer transparent and disable read memory access */
1544     if (NULL == p_input->p_base)
1545     {
1546         R_GLCDC->GR[layer].AB1   = GLCDC_PLANE_BLEND_TRANSPARENT & GLCDC_PRV_GR_AB1_DISPSEL_MASK; /* Set layer transparent */
1547         R_GLCDC->GR[layer].FLMRD = 0U;
1548 
1549         return;
1550     }
1551 
1552     /* Set layer pixel color format */
1553     R_GLCDC->GR[layer].FLM6 = ((uint32_t) g_format_lut[p_input->format]) << 28;
1554 
1555     r_glcdc_graphics_layer_param_recalculation(p_input, p_layer, &recalculated);
1556 
1557     /* Set the base address of graphics plane */
1558     R_GLCDC->GR[layer].FLM2 = recalculated.base_address;
1559 
1560     /* If line number descending mode is enable, change its sign */
1561     if (p_input->line_descending_enable)
1562     {
1563         line_offset *= (-1);
1564     }
1565 
1566     /* In line repeat mode, the GLCDC is configured to treat the entire repeated region of the buffer as a single line.
1567      * The number of lines given in the configuration reflects how many times the pattern is repeated. */
1568     if (p_input->lines_repeat_enable)
1569     {
1570         /* Set the line offset address for accessing the graphics data on graphics plane */
1571         lnnum_temp = (uint32_t) (p_input->lines_repeat_times);
1572 
1573         /* When line repeating mode, always read data on same line(s) */
1574         R_GLCDC->GR[layer].FLM3 = 0;
1575 
1576         /* Set the total visible line count based on the size and number of the repeated region */
1577         grcvw_temp = (uint32_t) (recalculated.vpix_size * p_input->lines_repeat_times);
1578         arcvw_temp = grcvw_temp;
1579     }
1580     else
1581     {
1582         /* Set the line offset address for accessing the graphics data */
1583         lnnum_temp = (uint32_t) (recalculated.vpix_size);
1584 
1585         /* Set the line offset address for accessing the graphics data on graphics plane */
1586         R_GLCDC->GR[layer].FLM3 = ((uint32_t) line_offset & GLCDC_PRV_GR_FLM3_LNOFF_MASK) << 16;
1587 
1588         /* Set the total visible line count */
1589         grcvw_temp = recalculated.vpix_size;
1590         arcvw_temp = grcvw_temp;
1591     }
1592 
1593     /* Set the number of data transfer times per line, 64 bytes are transferred in each transfer */
1594     /* Set (actual transfer times - 1) */
1595     R_GLCDC->GR[layer].FLM5 = (((lnnum_temp - 1) & GLCDC_PRV_GR_FLM5_LNNUM_MASK) << 16) +
1596                               (((recalculated.hread_size >> 6) - 1) & GLCDC_PRV_GR_FLM5_DATANUM_MASK);
1597 
1598     /* Set the graphics area horizontal dimensions */
1599     R_GLCDC->GR[layer].AB3 =
1600         (((uint32_t) (g_ctrl_blk.back_porch.x + recalculated.hpix_offset) & GLCDC_PRV_GR_AB3_GRCHS_MASK) << 16) +
1601         (recalculated.hpix_size & GLCDC_PRV_GR_AB3_GRCHW_MASK);
1602 
1603     /* Set the alpha blending area horizontal dimensions */
1604     R_GLCDC->GR[layer].AB5 =
1605         (((uint32_t) (g_ctrl_blk.back_porch.x + recalculated.hpix_offset) & GLCDC_PRV_GR_AB5_ARCHS_MASK) << 16) +
1606         (recalculated.hpix_size & GLCDC_PRV_GR_AB5_ARCHW_MASK);
1607 
1608     /* Set the graphics area vertical dimensions */
1609     R_GLCDC->GR[layer].AB2 =
1610         (grcvw_temp & GLCDC_PRV_GR_AB2_GRCVW_MASK) +
1611         (((uint32_t) (g_ctrl_blk.back_porch.y + recalculated.vpix_offset) & GLCDC_PRV_GR_AB2_GRCVS_MASK) << 16);
1612 
1613     /* Set the alpha blending area vertical dimensions */
1614     R_GLCDC->GR[layer].AB4 =
1615         (arcvw_temp & GLCDC_PRV_GR_AB4_ARCVW_MASK) +
1616         (((uint32_t) (g_ctrl_blk.back_porch.y + recalculated.vpix_offset) & GLCDC_PRV_GR_AB4_ARCVS_MASK) << 16);
1617 
1618     /* Set the alpha blending condition */
1619     r_glcdc_graphics_layer_blend_condition_set(p_layer, layer);
1620 
1621     /* Reset CLUT table selection */
1622     R_GLCDC->GR[layer].CLUTINT = 0;
1623     g_clut_data_latched[0]     = true;
1624     g_clut_data_latched[1]     = true;
1625 }
1626 
1627 /*******************************************************************************************************************//**
1628  * Subroutine to configure the output control block register settings which includes...
1629  *          - Bit endian / color order setting
1630  *          - Output color setting
1631  *          - Color correction setting
1632  * @param[in]     p_cfg       Pointer to the configuration structure for display interface
1633  * @retval        void
1634  **********************************************************************************************************************/
r_glcdc_output_block_set(display_cfg_t const * const p_cfg)1635 static void r_glcdc_output_block_set (display_cfg_t const * const p_cfg)
1636 {
1637     glcdc_extended_cfg_t * pextend     = (glcdc_extended_cfg_t *) p_cfg->p_extend;
1638     uint32_t               outset_temp = 0;
1639     uint32_t               pdtha_temp  = 0;
1640 
1641     /* Select the output format */
1642     outset_temp = ((uint32_t) g_outset_lut[p_cfg->output.format]) << GLCDC_PRV_OUT_SET_FORMAT_SHIFT;
1643     pdtha_temp  = ((uint32_t) g_pdtha_lut[p_cfg->output.format]) << GLCDC_PRV_OUT_PDTHA_FORM_SHIFT;
1644 
1645     /* Selects big or little endian for output data */
1646     if (DISPLAY_ENDIAN_BIG == p_cfg->output.endian)
1647     {
1648         outset_temp |= GLCDC_PRV_OUT_SET_ENDIANON_ENABLE;
1649     }
1650 
1651     /* Selects the output byte order swapping */
1652     if (DISPLAY_COLOR_ORDER_BGR == p_cfg->output.color_order)
1653     {
1654         outset_temp |= GLCDC_PRV_OUT_SET_SWAPON_ENABLE;
1655     }
1656 
1657     /* Sets the pixel clock (the GLCDC internal signal) frequency in case that the output format is 8-bit serial RGB */
1658     if (DISPLAY_OUT_FORMAT_8BITS_SERIAL == p_cfg->output.format)
1659     {
1660         outset_temp |= GLCDC_PRV_OUT_SET_FRQSEL_QUARTER_DIVISION << 8;
1661     }
1662 
1663     /* Set the dithering mode */
1664     if (p_cfg->output.dithering_on)
1665     {
1666         if (GLCDC_DITHERING_MODE_2X2PATTERN == pextend->dithering_mode)
1667         {
1668             pdtha_temp |= (uint32_t) ((GLCDC_DITHERING_MODE_2X2PATTERN << GLCDC_PRV_OUT_PDTHA_SEL_SHIFT) |
1669                                       (pextend->dithering_pattern_A << GLCDC_PRV_OUT_PDTHA_PA_SHIFT) |
1670                                       (pextend->dithering_pattern_B << GLCDC_PRV_OUT_PDTHA_PB_SHIFT) |
1671                                       (pextend->dithering_pattern_C << GLCDC_PRV_OUT_PDTHA_PC_SHIFT) |
1672                                       (pextend->dithering_pattern_D));
1673         }
1674         else
1675         {
1676             pdtha_temp |= GLCDC_DITHERING_MODE_ROUND_OFF << GLCDC_PRV_OUT_PDTHA_SEL_SHIFT;
1677         }
1678     }
1679 
1680     /* Set registers */
1681     R_GLCDC->OUT.SET   = outset_temp;
1682     R_GLCDC->OUT.PDTHA = pdtha_temp;
1683 }
1684 
1685 #if GLCDC_CFG_COLOR_CORRECTION_ENABLE
1686 
1687 /*******************************************************************************************************************//**
1688  * Subroutine to configure the brightness register settings. Pixel color output comes to be the value
1689  *           shown below processed by the brightness control block.
1690  *          - Gout = Gin + p_cfg->output.brightness.g - 512 (output.brightness.g must be 10 bits value; up to 512)
1691  *          - Bout = Bin + p_cfg->output.brightness.b - 512 (output.brightness.b must be 10 bits value; up to 512)
1692  *          - Rout = Rin + p_cfg->output.brightness.r - 512 (output.brightness.r must be 10 bits value; up to 512)
1693  * @param[in]  p_ctrl       Pointer to the control block for Display Interface
1694  * @param[in]  p_brightness Pointer to brightness configuration structure
1695  * @retval     void
1696  **********************************************************************************************************************/
r_glcdc_brightness_correction(glcdc_instance_ctrl_t const * const p_ctrl,display_brightness_t const * const p_brightness)1697 static void r_glcdc_brightness_correction (glcdc_instance_ctrl_t const * const p_ctrl,
1698                                            display_brightness_t const * const  p_brightness)
1699 {
1700     uint32_t r;
1701     uint32_t g;
1702     uint32_t b;
1703 
1704     if (p_brightness->enable)
1705     {
1706         g = p_brightness->g;
1707         b = p_brightness->b;
1708         r = p_brightness->r;
1709     }
1710     else
1711     {
1712         if (DISPLAY_STATE_CLOSED == p_ctrl->state)
1713         {
1714             /* If brightness setting in configuration is 'off', apply default value */
1715             g = GLCDC_PRV_BRIGHTNESS_DEFAULT;
1716             b = GLCDC_PRV_BRIGHTNESS_DEFAULT;
1717             r = GLCDC_PRV_BRIGHTNESS_DEFAULT;
1718         }
1719         else
1720         {
1721             return;
1722         }
1723     }
1724 
1725     /* Sets brightness correction register for each color in a pixel. */
1726     R_GLCDC->OUT.BRIGHT1 = g & GLCDC_PRV_OUT_BRIGHT1_BRTG_MASK;
1727     R_GLCDC->OUT.BRIGHT2 = ((b & GLCDC_PRV_OUT_BRIGHT2_BRTB_MASK) << 16) + (r & GLCDC_PRV_OUT_BRIGHT2_BRTR_MASK);
1728 }
1729 
1730 /*******************************************************************************************************************//**
1731  * Subroutine to configure the contrast register settings. Pixel color output becomes the value
1732  *           shown below, processed by the contrast control block. Contrast can be changed between x0.000 to x1.992
1733  *           (0x0:x0.000 / 0x80:x1.000 / 0xFF:x1.992).
1734  *          - Gout = (Gin + p_contrast->g)/128
1735  *          - Bout = (Bin + p_contrast->b)/128
1736  *          - Rout = (Rin + p_contrast->r)/128
1737  * @param[in]  p_ctrl     Pointer to the control block for the Display Interface
1738  * @param[in]  p_contrast Pointer to the contrast configuration structure
1739  * @retval     void
1740  **********************************************************************************************************************/
r_glcdc_contrast_correction(glcdc_instance_ctrl_t const * const p_ctrl,display_contrast_t const * const p_contrast)1741 static void r_glcdc_contrast_correction (glcdc_instance_ctrl_t const * const p_ctrl,
1742                                          display_contrast_t const * const    p_contrast)
1743 {
1744     uint32_t r;
1745     uint32_t g;
1746     uint32_t b;
1747 
1748     if (p_contrast->enable)
1749     {
1750         g = p_contrast->g;
1751         b = p_contrast->b;
1752         r = p_contrast->r;
1753     }
1754     else
1755     {
1756         if (DISPLAY_STATE_CLOSED == p_ctrl->state)
1757         {
1758             /* If the contrast setting in the configuration is set to 'off', apply default value */
1759             g = GLCDC_PRV_CONTRAST_DEFAULT;
1760             b = GLCDC_PRV_CONTRAST_DEFAULT;
1761             r = GLCDC_PRV_CONTRAST_DEFAULT;
1762         }
1763         else
1764         {
1765             return;
1766         }
1767     }
1768 
1769     /* Sets the contrast correction register for each color in a pixel. */
1770     R_GLCDC->OUT.CONTRAST = ((g & GLCDC_PRV_OUT_CONTRAST_CONTG_MASK) << 16) +
1771                             ((b & GLCDC_PRV_OUT_CONTRAST_CONTB_MASK) << 8) +
1772                             (r & GLCDC_PRV_OUT_CONTRAST_CONTR_MASK);
1773 }
1774 
1775 /*******************************************************************************************************************//**
1776  * Subroutine to configure the color correction order.
1777  *
1778  * @param[in]  p_cfg      Pointer to the configuration structure for the display interface
1779  * @retval     void
1780  **********************************************************************************************************************/
r_glcdc_color_correction_order(display_cfg_t const * const p_cfg)1781 static void r_glcdc_color_correction_order (display_cfg_t const * const p_cfg)
1782 {
1783     glcdc_extended_cfg_t * pextend = (glcdc_extended_cfg_t *) p_cfg->p_extend;
1784 
1785     /* Sets the Brightness/contrast and Gamma Correction processing order */
1786     if (GLCDC_CORRECTION_PROC_ORDER_BRIGHTNESS_CONTRAST2GAMMA == pextend->correction_proc_order)
1787     {
1788         /* OUT_CLKPHASE (LCDC clock source is PLCKA)
1789          * b12   FRONTGAM  = 0(Brightness/contrast correction is followed by gamma correction.)
1790          */
1791         R_GLCDC->OUT.CLKPHASE_b.FRONTGAM = 0U;
1792     }
1793     else
1794     {
1795         /* OUT_CLKPHASE (LCDC clock source is PLCKA)
1796          * b12   FRONTGAM  = 1(Gamma correction is followed by Brightness/contrast correction)
1797          */
1798         R_GLCDC->OUT.CLKPHASE_b.FRONTGAM = 1U;
1799     }
1800 }
1801 
1802 /*******************************************************************************************************************//**
1803  * Subroutine to configure the gamma correction register setting.
1804  * @param[in]     p_cfg      Pointer to the configuration structure for the display interface
1805  * @retval        void
1806  **********************************************************************************************************************/
r_glcdc_gamma_correction(display_cfg_t const * const p_cfg)1807 static void r_glcdc_gamma_correction (display_cfg_t const * const p_cfg)
1808 {
1809     uint8_t i;
1810     uint8_t j;
1811 
1812     gamma_correction_t * LUT_ptr;
1813 
1814     /* Set gamma correction LUTs based on config struct */
1815     for (j = 0U; j < 3U; j++)
1816     {
1817         /* Get pointer to LUT */
1818         switch (j)
1819         {
1820             default:
1821             case 0:
1822             {
1823                 LUT_ptr = &(p_cfg->output.p_gamma_correction->g);
1824                 break;
1825             }
1826 
1827             case 1:
1828             {
1829                 LUT_ptr = &(p_cfg->output.p_gamma_correction->b);
1830                 break;
1831             }
1832 
1833             case 2:
1834             {
1835                 LUT_ptr = &(p_cfg->output.p_gamma_correction->r);
1836                 break;
1837             }
1838         }
1839 
1840         if (LUT_ptr->enable)
1841         {
1842             for (i = 0U; i < (uint8_t) (DISPLAY_GAMMA_CURVE_ELEMENT_NUM / 2); i++)
1843             {
1844                 R_GLCDC->GAM[j].LUT[i] = ((LUT_ptr->gain[i * 2U] & GLCDC_PRV_GAMX_LUTX_GAIN_MASK) << 16) +
1845                                          (LUT_ptr->gain[(i * 2U) + 1U] & GLCDC_PRV_GAMX_LUTX_GAIN_MASK);
1846             }
1847 
1848             for (i = 0U; i < (uint8_t) (DISPLAY_GAMMA_CURVE_ELEMENT_NUM / 3); i++)
1849             {
1850                 R_GLCDC->GAM[j].AREA[i] = ((LUT_ptr->threshold[(i * 3U) + 1U] & GLCDC_PRV_GAMX_AREAX_MASK) << 20) +
1851                                           ((LUT_ptr->threshold[(i * 3U) + 2U] & GLCDC_PRV_GAMX_AREAX_MASK) << 10) +
1852                                           (LUT_ptr->threshold[(i * 3U) + 3U] & GLCDC_PRV_GAMX_AREAX_MASK);
1853             }
1854 
1855             /* Enable LUT */
1856             R_GLCDC->GAM[j].GAM_SW = 1U;
1857         }
1858         else
1859         {
1860             R_GLCDC->GAM[j].GAM_SW = 0U;
1861         }
1862 
1863         R_GLCDC->GAM[j].LATCH = 1U;
1864     }
1865 }
1866 
1867 #endif
1868 
1869 /*******************************************************************************************************************//**
1870  * Subroutine to get the bit size of the specified format.
1871  * @param[in]     format   Color format (specify display_in_format_t type enumeration value)
1872  * @retval        Bit size
1873  **********************************************************************************************************************/
r_glcdc_get_bit_size(display_in_format_t const format)1874 static inline uint16_t r_glcdc_get_bit_size (display_in_format_t const format)
1875 {
1876     return g_pixsize_lut[format];
1877 }
1878 
1879 /*******************************************************************************************************************//**
1880  * The line detection interrupt service routine.
1881  *           This ISR is called when the number of the display line reaches the designated number of lines. If a
1882  *           callback function is registered in R_GLCDC_Open(), it is called from this ISR and the
1883  *           DISPLAY_EVENT_LINE_DETECTION event code is set as its argument.
1884  * @retval        none
1885  **********************************************************************************************************************/
glcdc_line_detect_isr(void)1886 void glcdc_line_detect_isr (void)
1887 {
1888     FSP_CONTEXT_SAVE
1889 
1890     display_callback_args_t args;
1891     glcdc_instance_ctrl_t * p_ctrl = (glcdc_instance_ctrl_t *) g_ctrl_blk.p_context;
1892 
1893     /* Increment frame counter */
1894     g_frame_ctr++;
1895 
1896     /* Handle overflow case for g_frame_ctr vs. g_fade_pending
1897      * (at 60FPS this should occur once every 2.25 years of uptime) */
1898     if (!g_frame_ctr)
1899     {
1900         g_fade_pending[0] = 0;
1901         g_fade_pending[1] = 0;
1902     }
1903 
1904     /* Set CLUT state to latched */
1905     g_clut_data_latched[0] = true;
1906     g_clut_data_latched[1] = true;
1907 
1908     /* Call back callback function if it is registered */
1909     if (NULL != p_ctrl->p_callback)
1910     {
1911         args.event     = DISPLAY_EVENT_LINE_DETECTION;
1912         args.p_context = p_ctrl->p_context;
1913         p_ctrl->p_callback(&args);
1914     }
1915 
1916     /* Clear interrupt flag in the register of the GLCDC module */
1917     R_GLCDC->SYSCNT.STCLR_b.VPOSCLR = 1U;
1918 
1919     /* Clear interrupt flag in the register of the NVIC module */
1920     R_BSP_IrqStatusClear(R_FSP_CurrentIrqGet());
1921 
1922     FSP_CONTEXT_RESTORE
1923 }
1924 
1925 /*******************************************************************************************************************//**
1926  * The graphics plane 1 underflow detection interrupt service routine.
1927  *           This ISR is called when the underflow occurs in the graphics plane 1 control block. If a callback function
1928  *           is registered in R_GLCDC_Open(), it is called back from this ISR and the DISPLAY_EVENT_GR1_UNDERFLOW event
1929  *           code is set as its argument.
1930  * @retval        none
1931  **********************************************************************************************************************/
glcdc_underflow_1_isr(void)1932 void glcdc_underflow_1_isr (void)
1933 {
1934     FSP_CONTEXT_SAVE
1935 
1936     display_callback_args_t args;
1937     glcdc_instance_ctrl_t * p_ctrl = (glcdc_instance_ctrl_t *) g_ctrl_blk.p_context;
1938 
1939     /* Call back callback function if it is registered */
1940     if (NULL != p_ctrl->p_callback)
1941     {
1942         args.event     = DISPLAY_EVENT_GR1_UNDERFLOW;
1943         args.p_context = p_ctrl->p_context;
1944         p_ctrl->p_callback(&args);
1945     }
1946 
1947     /* Clear interrupt flag in the register of the GLCDC module */
1948     R_GLCDC->SYSCNT.STCLR_b.L1UNDFCLR = 1U;
1949 
1950     /* Clear interrupt flag in the register of the NVIC module */
1951     R_BSP_IrqStatusClear(R_FSP_CurrentIrqGet());
1952 
1953     FSP_CONTEXT_RESTORE
1954 }
1955 
1956 /*******************************************************************************************************************//**
1957  * The graphics plane 2 underflow detection interrupt service routine.
1958  *           This ISR is called when the underflow occurs in the graphics plane 2 control block. If a callback function
1959  *           is registered in R_GLCDC_Open(), it is called from this ISR and the DISPLAY_EVENT_GR2_UNDERFLOW event
1960  *           code is set as its argument.
1961  * @retval        none
1962  **********************************************************************************************************************/
glcdc_underflow_2_isr(void)1963 void glcdc_underflow_2_isr (void)
1964 {
1965     FSP_CONTEXT_SAVE
1966 
1967     display_callback_args_t args;
1968     glcdc_instance_ctrl_t * p_ctrl = (glcdc_instance_ctrl_t *) g_ctrl_blk.p_context;
1969 
1970     /* Call the callback function if it is registered */
1971     if (NULL != p_ctrl->p_callback)
1972     {
1973         args.event     = DISPLAY_EVENT_GR2_UNDERFLOW;
1974         args.p_context = p_ctrl->p_context;
1975         p_ctrl->p_callback(&args);
1976     }
1977 
1978     /* Clear interrupt flag in the register of the GLCDC module */
1979     R_GLCDC->SYSCNT.STCLR_b.L2UNDFCLR = 1U;
1980 
1981     /* Clear interrupt flag in the register of the NVIC module */
1982     R_BSP_IrqStatusClear(R_FSP_CurrentIrqGet());
1983 
1984     FSP_CONTEXT_RESTORE
1985 }
1986 
1987 /*******************************************************************************************************************//**
1988  * Enable the glcdc interrupt.
1989  * @param[in]     p_instance_ctrl   Pointer to GLCDC instance struct
1990  * @retval        none
1991  **********************************************************************************************************************/
r_glcdc_interrupt_enable(glcdc_instance_ctrl_t * p_instance_ctrl)1992 static void r_glcdc_interrupt_enable (glcdc_instance_ctrl_t * p_instance_ctrl)
1993 {
1994     /* Enable the GLCDC interrupts */
1995     R_GLCDC->SYSCNT.DTCTEN = GLCDC_PRV_SYSCNT_DTCTEN_INIT; // VPOS interrupt is enabled in R_GLCDC_Start
1996     R_GLCDC->SYSCNT.INTEN  = GLCDC_PRV_SYSCNT_INTEN_INIT;
1997 
1998     if (p_instance_ctrl->p_cfg->line_detect_irq >= 0)
1999     {
2000         R_BSP_IrqCfgEnable(p_instance_ctrl->p_cfg->line_detect_irq,
2001                            p_instance_ctrl->p_cfg->line_detect_ipl,
2002                            p_instance_ctrl);
2003     }
2004 
2005     if (p_instance_ctrl->p_cfg->underflow_1_irq >= 0)
2006     {
2007         R_BSP_IrqCfgEnable(p_instance_ctrl->p_cfg->underflow_1_irq,
2008                            p_instance_ctrl->p_cfg->underflow_1_ipl,
2009                            p_instance_ctrl);
2010     }
2011 
2012     if (p_instance_ctrl->p_cfg->underflow_2_irq >= 0)
2013     {
2014         R_BSP_IrqCfgEnable(p_instance_ctrl->p_cfg->underflow_2_irq,
2015                            p_instance_ctrl->p_cfg->underflow_2_ipl,
2016                            p_instance_ctrl);
2017     }
2018 }
2019 
2020 /*******************************************************************************************************************//**
2021  * Calculate the pixels to be displayed on window based on the offset of the graphic layer.
2022  * @param[in]     p_input         The input frame buffer configuration
2023  * @param[in]     p_layer         The layer configuration
2024  * @param[in,out] p_recalculated  Pointer to store recalculated parameter
2025  * @param[in]     bit_size        Pointer to bit size of the color format
2026  * @retval        void
2027  **********************************************************************************************************************/
r_glcdc_pixel_size_recalculate(display_input_cfg_t const * const p_input,display_layer_t const * const p_layer,glcdc_recalculated_param_t * p_recalculated,uint16_t bit_size)2028 static void r_glcdc_pixel_size_recalculate (display_input_cfg_t const * const p_input,
2029                                             display_layer_t const * const     p_layer,
2030                                             glcdc_recalculated_param_t      * p_recalculated,
2031                                             uint16_t                          bit_size)
2032 {
2033     uint16_t hpix_size_temp;
2034     int16_t  hpix_offset_temp;         /* Offset can be signed value */
2035     uint32_t base_address_temp;
2036 
2037     int16_t coord_x = p_layer->coordinate.x;
2038 
2039     if ((g_ctrl_blk.hsize >= coord_x) && (0 <= coord_x))
2040     {
2041         /* If the offset of the graphics layer is greater than or equal to zero and it is less than or
2042          *  equal to the size of the display window, calculate actual pixel size to display.
2043          */
2044         if ((g_ctrl_blk.hsize - (uint16_t) coord_x) < p_input->hsize)
2045         {
2046             /* Calculate actual pixel size, the pixels to be displayed is less than the display window size */
2047             hpix_size_temp = (uint16_t) (g_ctrl_blk.hsize - (uint16_t) coord_x);
2048         }
2049         else
2050         {
2051             /* Actual pixel size to display is same as the display window size */
2052             hpix_size_temp = p_input->hsize;
2053         }
2054 
2055         p_recalculated->hpix_offset = coord_x;
2056         base_address_temp           = (uint32_t) p_input->p_base;
2057     }
2058     else if ((0 > coord_x) && (p_input->hsize + coord_x > 0))
2059     {
2060         /* If the offset of the graphics layer is less than zero but part of the layer would still be visible, calculate
2061          * the actual pixel size to display. */
2062 
2063         /* If coordinate.x is a minus value, the layer image position can be adjusted not only by adjusting
2064          *  the horizontal offset but also by changing the base address of layer image. Since the base address
2065          *  has to be aligned to 64 bytes, we need to adjust the horizontal offset, which is the cycles from
2066          *  the 'internal zero' to the start cycle of active video region to achieve 1 pixel unit offset.
2067          *  We need to adjust the size of image to display as well.
2068          */
2069         int16_t adj_cycles = 1;
2070         if (bit_size >= 8)
2071         {
2072             adj_cycles = (int16_t) (GLCDC_PRV_OFFSET_MARGIN_MINUS_64PIX / ((bit_size) / 8));
2073         }
2074 
2075         if (g_ctrl_blk.back_porch.x < adj_cycles)
2076         {
2077             /* If there is not enough cycles for the offset adjustment, simply do not adjust. */
2078             hpix_offset_temp = 0;
2079             hpix_size_temp   = (uint16_t) (p_input->hsize - (((coord_x * (-1)) / adj_cycles) * adj_cycles));
2080         }
2081         else
2082         {
2083             /* If there are cycles for the offset adjustment, adjust pixel offset and size */
2084             hpix_offset_temp = (int16_t) (((coord_x * (-1)) % adj_cycles) * (-1));
2085             hpix_size_temp   = (uint16_t) ((p_input->hsize + coord_x) + ((coord_x * (-1)) % adj_cycles));
2086         }
2087 
2088         p_recalculated->hpix_offset = hpix_offset_temp;
2089 
2090         /* Base address must be aligned to a 64-bit address */
2091         uint32_t offset_address = (uint32_t) (((coord_x * (-1)) * (bit_size)) / 8);
2092         base_address_temp = ((uint32_t) p_input->p_base + offset_address) & (uint32_t) (~0x3F); // NOLINT(readability-magic-numbers)
2093     }
2094     else
2095     {
2096         /* If graphics layer offset is beyond the display window size, set the pixel size to display to zero */
2097         hpix_size_temp    = 0U;
2098         base_address_temp = (uint32_t) p_input->p_base;
2099     }
2100 
2101     p_recalculated->hpix_size    = hpix_size_temp;
2102     p_recalculated->base_address = base_address_temp;
2103 }
2104