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