Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:22:58

0001 /*
0002  * Copyright 2017-2022 NXP
0003  * All rights reserved.
0004  *
0005  *
0006  * SPDX-License-Identifier: BSD-3-Clause
0007  */
0008 
0009 #include "fsl_elcdif.h"
0010 
0011 /* Component ID definition, used by tools. */
0012 #ifndef FSL_COMPONENT_ID
0013 #define FSL_COMPONENT_ID "platform.drivers.elcdif"
0014 #endif
0015 
0016 /*******************************************************************************
0017  * Prototypes
0018  ******************************************************************************/
0019 
0020 /*!
0021  * @brief Get instance number for ELCDIF module.
0022  *
0023  * @param base ELCDIF peripheral base address
0024  */
0025 static uint32_t ELCDIF_GetInstance(const LCDIF_Type *base);
0026 
0027 /*******************************************************************************
0028  * Variables
0029  ******************************************************************************/
0030 
0031 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
0032 /*! @brief Pointers to eLCDIF apb_clk for each instance. */
0033 static const clock_ip_name_t s_elcdifApbClocks[] = LCDIF_CLOCKS;
0034 #if defined(LCDIF_PERIPH_CLOCKS)
0035 /*! @brief Pointers to eLCDIF pix_clk for each instance. */
0036 static const clock_ip_name_t s_elcdifPixClocks[] = LCDIF_PERIPH_CLOCKS;
0037 #endif
0038 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
0039 
0040 /*! @brief The control register value to select different pixel format. */
0041 static const elcdif_pixel_format_reg_t s_pixelFormatReg[] = {
0042     /* kELCDIF_PixelFormatRAW8 */
0043     {/* Register CTRL. */
0044      LCDIF_CTRL_WORD_LENGTH(1U),
0045      /* Register CTRL1. */
0046      LCDIF_CTRL1_BYTE_PACKING_FORMAT(0x0FU)},
0047     /* kELCDIF_PixelFormatRGB565 */
0048     {/* Register CTRL. */
0049      LCDIF_CTRL_WORD_LENGTH(0U),
0050      /* Register CTRL1. */
0051      LCDIF_CTRL1_BYTE_PACKING_FORMAT(0x0FU)},
0052     /* kELCDIF_PixelFormatRGB666 */
0053     {/* Register CTRL. */
0054      LCDIF_CTRL_WORD_LENGTH(3U) | LCDIF_CTRL_DATA_FORMAT_24_BIT(1U),
0055      /* Register CTRL1. */
0056      LCDIF_CTRL1_BYTE_PACKING_FORMAT(0x07U)},
0057     /* kELCDIF_PixelFormatXRGB8888 */
0058     {/* Register CTRL. 24-bit. */
0059      LCDIF_CTRL_WORD_LENGTH(3U),
0060      /* Register CTRL1. */
0061      LCDIF_CTRL1_BYTE_PACKING_FORMAT(0x07U)},
0062     /* kELCDIF_PixelFormatRGB888 */
0063     {/* Register CTRL. 24-bit. */
0064      LCDIF_CTRL_WORD_LENGTH(3U),
0065      /* Register CTRL1. */
0066      LCDIF_CTRL1_BYTE_PACKING_FORMAT(0x0FU)},
0067 };
0068 
0069 /*******************************************************************************
0070  * Codes
0071  ******************************************************************************/
0072 static uint32_t ELCDIF_GetInstance(const LCDIF_Type *base)
0073 {
0074     static LCDIF_Type *const s_elcdifBases[] = LCDIF_BASE_PTRS;
0075 
0076     uint32_t instance;
0077 
0078     /* Find the instance index from base address mappings. */
0079     for (instance = 0; instance < ARRAY_SIZE(s_elcdifBases); instance++)
0080     {
0081         if (s_elcdifBases[instance] == base)
0082         {
0083             break;
0084         }
0085     }
0086 
0087     assert(instance < ARRAY_SIZE(s_elcdifBases));
0088 
0089     return instance;
0090 }
0091 
0092 /*!
0093  * brief Initializes the eLCDIF to work in RGB mode (DOTCLK mode).
0094  *
0095  * This function ungates the eLCDIF clock and configures the eLCDIF peripheral according
0096  * to the configuration structure.
0097  *
0098  * param base eLCDIF peripheral base address.
0099  * param config Pointer to the configuration structure.
0100  */
0101 void ELCDIF_RgbModeInit(LCDIF_Type *base, const elcdif_rgb_mode_config_t *config)
0102 {
0103     assert(NULL != config);
0104     assert((uint32_t)config->pixelFormat < ARRAY_SIZE(s_pixelFormatReg));
0105 
0106 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && (0 != FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL))
0107     uint32_t instance = ELCDIF_GetInstance(base);
0108     /* Enable the clock. */
0109     (void)CLOCK_EnableClock(s_elcdifApbClocks[instance]);
0110 #if defined(LCDIF_PERIPH_CLOCKS)
0111     (void)CLOCK_EnableClock(s_elcdifPixClocks[instance]);
0112 #endif
0113 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
0114 
0115     /* Reset. */
0116     ELCDIF_Reset(base);
0117 
0118     base->CTRL = s_pixelFormatReg[(uint32_t)config->pixelFormat].regCtrl | (uint32_t)(config->dataBus) |
0119                  LCDIF_CTRL_DOTCLK_MODE_MASK |  /* RGB mode. */
0120                  LCDIF_CTRL_BYPASS_COUNT_MASK | /* Keep RUN bit set. */
0121                  LCDIF_CTRL_MASTER_MASK;
0122 
0123     base->CTRL1 = s_pixelFormatReg[(uint32_t)config->pixelFormat].regCtrl1;
0124 
0125     base->CTRL2 = (base->CTRL2 & ~LCDIF_CTRL2_OUTSTANDING_REQS_MASK) | (LCDIF_CTRL2_OUTSTANDING_REQS(4));
0126 
0127     base->TRANSFER_COUNT = ((uint32_t)config->panelHeight << LCDIF_TRANSFER_COUNT_V_COUNT_SHIFT) |
0128                            ((uint32_t)config->panelWidth << LCDIF_TRANSFER_COUNT_H_COUNT_SHIFT);
0129 
0130     base->VDCTRL0 = LCDIF_VDCTRL0_ENABLE_PRESENT_MASK |         /* Data enable signal. */
0131                     LCDIF_VDCTRL0_VSYNC_PERIOD_UNIT_MASK |      /* VSYNC period in the unit of display clock. */
0132                     LCDIF_VDCTRL0_VSYNC_PULSE_WIDTH_UNIT_MASK | /* VSYNC pulse width in the unit of display clock. */
0133                     (uint32_t)config->polarityFlags | (uint32_t)config->vsw;
0134 
0135     base->VDCTRL1 =
0136         (uint32_t)config->vsw + (uint32_t)config->panelHeight + (uint32_t)config->vfp + (uint32_t)config->vbp;
0137     base->VDCTRL2 =
0138         ((uint32_t)config->hsw << LCDIF_VDCTRL2_HSYNC_PULSE_WIDTH_SHIFT) |
0139         ((uint32_t)config->hfp + (uint32_t)config->hbp + (uint32_t)config->panelWidth + (uint32_t)config->hsw)
0140             << LCDIF_VDCTRL2_HSYNC_PERIOD_SHIFT;
0141 
0142     base->VDCTRL3 = (((uint32_t)config->hbp + config->hsw) << LCDIF_VDCTRL3_HORIZONTAL_WAIT_CNT_SHIFT) |
0143                     (((uint32_t)config->vbp + config->vsw) << LCDIF_VDCTRL3_VERTICAL_WAIT_CNT_SHIFT);
0144 
0145     base->VDCTRL4 = LCDIF_VDCTRL4_SYNC_SIGNALS_ON_MASK |
0146                     ((uint32_t)config->panelWidth << LCDIF_VDCTRL4_DOTCLK_H_VALID_DATA_CNT_SHIFT);
0147 
0148     base->CUR_BUF  = ELCDIF_ADDR_CPU_2_IP(config->bufferAddr);
0149     base->NEXT_BUF = ELCDIF_ADDR_CPU_2_IP(config->bufferAddr);
0150 }
0151 
0152 /*!
0153  * brief Gets the eLCDIF default configuration structure for RGB (DOTCLK) mode.
0154  *
0155  * This function sets the configuration structure to default values.
0156  * The default configuration is set to the following values.
0157  * code
0158     config->panelWidth = 480U;
0159     config->panelHeight = 272U;
0160     config->hsw = 41;
0161     config->hfp = 4;
0162     config->hbp = 8;
0163     config->vsw = 10;
0164     config->vfp = 4;
0165     config->vbp = 2;
0166     config->polarityFlags = kELCDIF_VsyncActiveLow |
0167                             kELCDIF_HsyncActiveLow |
0168                             kELCDIF_DataEnableActiveLow |
0169                             kELCDIF_DriveDataOnFallingClkEdge;
0170     config->bufferAddr = 0U;
0171     config->pixelFormat = kELCDIF_PixelFormatRGB888;
0172     config->dataBus = kELCDIF_DataBus24Bit;
0173     code
0174  *
0175  * param config Pointer to the eLCDIF configuration structure.
0176  */
0177 void ELCDIF_RgbModeGetDefaultConfig(elcdif_rgb_mode_config_t *config)
0178 {
0179     assert(NULL != config);
0180 
0181     /* Initializes the configure structure to zero. */
0182     (void)memset(config, 0, sizeof(*config));
0183 
0184     config->panelWidth    = 480U;
0185     config->panelHeight   = 272U;
0186     config->hsw           = 41;
0187     config->hfp           = 4;
0188     config->hbp           = 8;
0189     config->vsw           = 10;
0190     config->vfp           = 4;
0191     config->vbp           = 2;
0192     config->polarityFlags = (uint32_t)kELCDIF_VsyncActiveLow | (uint32_t)kELCDIF_HsyncActiveLow |
0193                             (uint32_t)kELCDIF_DataEnableActiveLow | (uint32_t)kELCDIF_DriveDataOnFallingClkEdge;
0194     config->bufferAddr  = 0U;
0195     config->pixelFormat = kELCDIF_PixelFormatRGB888;
0196     config->dataBus     = kELCDIF_DataBus24Bit;
0197 }
0198 
0199 /*!
0200  * brief Set the pixel format in RGB (DOTCLK) mode.
0201  *
0202  * param base eLCDIF peripheral base address.
0203  * param pixelFormat The pixel format.
0204  */
0205 void ELCDIF_RgbModeSetPixelFormat(LCDIF_Type *base, elcdif_pixel_format_t pixelFormat)
0206 {
0207     assert((uint32_t)pixelFormat < ARRAY_SIZE(s_pixelFormatReg));
0208 
0209     base->CTRL = (base->CTRL & ~(LCDIF_CTRL_WORD_LENGTH_MASK | LCDIF_CTRL_DATA_FORMAT_24_BIT_MASK |
0210                                  LCDIF_CTRL_DATA_FORMAT_18_BIT_MASK | LCDIF_CTRL_DATA_FORMAT_16_BIT_MASK)) |
0211                  s_pixelFormatReg[(uint32_t)pixelFormat].regCtrl;
0212 
0213     base->CTRL1 = s_pixelFormatReg[(uint32_t)pixelFormat].regCtrl1;
0214 }
0215 
0216 /*!
0217  * brief Deinitializes the eLCDIF peripheral.
0218  *
0219  * param base eLCDIF peripheral base address.
0220  */
0221 void ELCDIF_Deinit(LCDIF_Type *base)
0222 {
0223     ELCDIF_Reset(base);
0224 
0225 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && (0 != FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL))
0226     uint32_t instance = ELCDIF_GetInstance(base);
0227 /* Disable the clock. */
0228 #if defined(LCDIF_PERIPH_CLOCKS)
0229     (void)CLOCK_DisableClock(s_elcdifPixClocks[instance]);
0230 #endif
0231     (void)CLOCK_DisableClock(s_elcdifApbClocks[instance]);
0232 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
0233 }
0234 
0235 /*!
0236  * brief Stop display in RGB (DOTCLK) mode and wait until finished.
0237  *
0238  * param base eLCDIF peripheral base address.
0239  */
0240 void ELCDIF_RgbModeStop(LCDIF_Type *base)
0241 {
0242     base->CTRL_CLR = LCDIF_CTRL_DOTCLK_MODE_MASK;
0243 
0244     /* Wait for data transfer finished. */
0245     while (0U != (base->CTRL & LCDIF_CTRL_DOTCLK_MODE_MASK))
0246     {
0247     }
0248 }
0249 
0250 /*!
0251  * brief Reset the eLCDIF peripheral.
0252  *
0253  * param base eLCDIF peripheral base address.
0254  */
0255 void ELCDIF_Reset(LCDIF_Type *base)
0256 {
0257     /*
0258      * ELCDIF reset workflow:
0259      *
0260      * 1. Ungate clock.
0261      * 2. Trigger the software reset.
0262      * 3. The software reset finished when clk_gate bit is set.
0263      * 4. Ungate the clock.
0264      * 5. Release the reset.
0265      */
0266 
0267     /* Ungate clock. */
0268     base->CTRL_CLR = LCDIF_CTRL_CLKGATE_MASK;
0269 
0270     /*
0271      * If already in reset state, release the reset.
0272      * If not, trigger reset.
0273      */
0274     if (0U == (base->CTRL & LCDIF_CTRL_SFTRST_MASK))
0275     {
0276         /* Trigger reset. */
0277         base->CTRL_SET = LCDIF_CTRL_SFTRST_MASK;
0278 
0279         /* Reset is not finished until CLK_GATE is set. */
0280         while (0U == (base->CTRL & LCDIF_CTRL_CLKGATE_MASK))
0281         {
0282         }
0283 
0284         /* Ungate the clock. */
0285         base->CTRL_CLR = LCDIF_CTRL_CLKGATE_MASK;
0286     }
0287 
0288     /* Release the reset. */
0289     base->CTRL_CLR = LCDIF_CTRL_SFTRST_MASK;
0290 }
0291 
0292 #if !(defined(FSL_FEATURE_LCDIF_HAS_NO_AS) && (0 != FSL_FEATURE_LCDIF_HAS_NO_AS))
0293 /*!
0294  * brief Set the configuration for alpha surface buffer.
0295  *
0296  * param base eLCDIF peripheral base address.
0297  * param config Pointer to the configuration structure.
0298  */
0299 void ELCDIF_SetAlphaSurfaceBufferConfig(LCDIF_Type *base, const elcdif_as_buffer_config_t *config)
0300 {
0301     assert(NULL != config);
0302 
0303     base->AS_CTRL     = (base->AS_CTRL & ~LCDIF_AS_CTRL_FORMAT_MASK) | LCDIF_AS_CTRL_FORMAT(config->pixelFormat);
0304     base->AS_BUF      = ELCDIF_ADDR_CPU_2_IP(config->bufferAddr);
0305     base->AS_NEXT_BUF = ELCDIF_ADDR_CPU_2_IP(config->bufferAddr);
0306 }
0307 
0308 /*!
0309  * brief Set the alpha surface blending configuration.
0310  *
0311  * param base eLCDIF peripheral base address.
0312  * param config Pointer to the configuration structure.
0313  */
0314 void ELCDIF_SetAlphaSurfaceBlendConfig(LCDIF_Type *base, const elcdif_as_blend_config_t *config)
0315 {
0316     assert(NULL != config);
0317     uint32_t reg;
0318 
0319     reg = base->AS_CTRL;
0320     reg &= ~(LCDIF_AS_CTRL_ALPHA_INVERT_MASK | LCDIF_AS_CTRL_ROP_MASK | LCDIF_AS_CTRL_ALPHA_MASK |
0321              LCDIF_AS_CTRL_ALPHA_CTRL_MASK);
0322     reg |= (LCDIF_AS_CTRL_ROP(config->ropMode) | LCDIF_AS_CTRL_ALPHA(config->alpha) |
0323             LCDIF_AS_CTRL_ALPHA_CTRL(config->alphaMode));
0324 
0325     if (config->invertAlpha)
0326     {
0327         reg |= LCDIF_AS_CTRL_ALPHA_INVERT_MASK;
0328     }
0329 
0330     base->AS_CTRL = reg;
0331 }
0332 #endif /* FSL_FEATURE_LCDIF_HAS_NO_AS */
0333 
0334 #if (defined(FSL_FEATURE_LCDIF_HAS_LUT) && (0 != FSL_FEATURE_LCDIF_HAS_LUT))
0335 /*!
0336  * brief Load the LUT value.
0337  *
0338  * This function loads the LUT value to the specific LUT memory, user can
0339  * specify the start entry index.
0340  *
0341  * param base eLCDIF peripheral base address.
0342  * param lut Which LUT to load.
0343  * param startIndex The start index of the LUT entry to update.
0344  * param lutData The LUT data to load.
0345  * param count Count of p lutData.
0346  * retval kStatus_Success Initialization success.
0347  * retval kStatus_InvalidArgument Wrong argument.
0348  */
0349 status_t ELCDIF_UpdateLut(
0350     LCDIF_Type *base, elcdif_lut_t lut, uint16_t startIndex, const uint32_t *lutData, uint16_t count)
0351 {
0352     volatile uint32_t *regLutAddr;
0353     volatile uint32_t *regLutData;
0354     uint32_t i;
0355     status_t status;
0356 
0357     /* Only has 256 entries. */
0358     if ((startIndex + count) > ELCDIF_LUT_ENTRY_NUM)
0359     {
0360         status = kStatus_InvalidArgument;
0361     }
0362     else
0363     {
0364         if (kELCDIF_Lut0 == lut)
0365         {
0366             regLutAddr = &(base->LUT0_ADDR);
0367             regLutData = &(base->LUT0_DATA);
0368         }
0369         else
0370         {
0371             regLutAddr = &(base->LUT1_ADDR);
0372             regLutData = &(base->LUT1_DATA);
0373         }
0374 
0375         *regLutAddr = startIndex;
0376 
0377         for (i = 0; i < count; i++)
0378         {
0379             *regLutData = lutData[i];
0380         }
0381 
0382         status = kStatus_Success;
0383     }
0384 
0385     return status;
0386 }
0387 #endif /* FSL_FEATURE_LCDIF_HAS_LUT */