/**************************************************************************** * arch/arm/src/imxrt/imxrt_lcd.c * * Copyright (C) 2019 Gregory Nutt. All rights reserved. * Copyright (C) 2017, NXP Semiconductors, Inc. * Author: Johannes Schock (Port) * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * 3. Neither the name NuttX nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * ****************************************************************************/ /**************************************************************************** * Included Files ****************************************************************************/ #include #include "imxrt_lcd.h" #include "imxrt_periphclks.h" #include #include #include #include #include #include "up_arch.h" #include #include "imxrt_gpio.h" #include "imxrt_iomuxc.h" #include "hardware/imxrt_pinmux.h" #include /**************************************************************************** * Pre-processor Definitions ****************************************************************************/ #define IMXRT_LCD_CLK_PER_LINE \ (CONFIG_IMXRT_LCD_HWIDTH + CONFIG_IMXRT_LCD_HPULSE + \ CONFIG_IMXRT_LCD_HFRONTPORCH + CONFIG_IMXRT_LCD_HBACKPORCH) #define IMXRT_LCD_LINES_PER_FRAME \ (CONFIG_IMXRT_LCD_VHEIGHT + CONFIG_IMXRT_LCD_VPULSE + \ CONFIG_IMXRT_LCD_VFRONTPORCH + CONFIG_IMXRT_LCD_VBACKPORCH) #define IMXRT_LCD_PIXEL_CLOCK \ (IMXRT_LCD_CLK_PER_LINE * IMXRT_LCD_LINES_PER_FRAME * \ CONFIG_IMXRT_LCD_REFRESH_FREQ) /* Framebuffer characteristics in bytes */ #define IMXRT_STRIDE ((CONFIG_IMXRT_LCD_HWIDTH * IMXRT_BPP + 7) / 8) #define IMXRT_FBSIZE (IMXRT_STRIDE * CONFIG_IMXRT_LCD_VHEIGHT) /* Delays */ #define IMXRT_LCD_RESET_DELAY (0x100) /**************************************************************************** * Private Function Prototypes ****************************************************************************/ /* Get information about the video controller configuration and the * configuration of each color plane. */ static int imxrt_getvideoinfo(FAR struct fb_vtable_s *vtable, FAR struct fb_videoinfo_s *vinfo); static int imxrt_getplaneinfo(FAR struct fb_vtable_s *vtable, int planeno, FAR struct fb_planeinfo_s *pinfo); /* The following is provided only if the video hardware supports RGB color * mapping */ #ifdef CONFIG_FB_CMAP static int imxrt_getcmap(FAR struct fb_vtable_s *vtable, FAR struct fb_cmap_s *cmap); static int imxrt_putcmap(FAR struct fb_vtable_s *vtable, FAR const struct fb_cmap_s *cmap); #endif #ifdef CONFIG_FB_HWCURSOR # error "Cursor control not supported by this driver" #endif /**************************************************************************** * Private Data ****************************************************************************/ /* This structure describes the video controller */ static const struct fb_videoinfo_s g_videoinfo = { .fmt = IMXRT_COLOR_FMT, .xres = CONFIG_IMXRT_LCD_HWIDTH, .yres = CONFIG_IMXRT_LCD_VHEIGHT, .nplanes = 1, }; /* This structure describes the single color plane */ static const struct fb_planeinfo_s g_planeinfo = { .fbmem = (FAR void *)CONFIG_IMXRT_LCD_VRAMBASE, .fblen = IMXRT_FBSIZE, .stride = IMXRT_STRIDE, .display = 0, .bpp = IMXRT_BPP, }; struct pixel_format_reg { uint32_t regCtrl; /* Value of register CTRL. */ uint32_t regCtrl1; /* Value of register CTRL1. */ }; #if defined (CONFIG_IMXRT_LCD_INPUT_BPP8) || defined (CONFIG_IMXRT_LCD_INPUT_BPP8_LUT) static const struct pixel_format_reg pixelFormat = { /* Register CTRL. */ LCDIF_CTRL_WORD_LENGTH(1U), /* Register CTRL1. */ LCDIF_CTRL1_BYTE_PACKING_FORMAT(0x0fU) }; const uint32_t dataBus = LCDIF_CTRL_LCD_DATABUS_WIDTH(1); #else # if defined (CONFIG_IMXRT_LCD_INPUT_BPP15) static const struct pixel_format_reg pixelFormat = { /* Register CTRL. */ LCDIF_CTRL_WORD_LENGTH(0U) | LCDIF_CTRL_SET_DATA_FORMAT_16_BIT_MASK, /* Register CTRL1. */ LCDIF_CTRL1_BYTE_PACKING_FORMAT(0x0fU) }; # elif defined (CONFIG_IMXRT_LCD_INPUT_BPP16) static const struct pixel_format_reg pixelFormat = { /* Register CTRL. */ LCDIF_CTRL_WORD_LENGTH(0U), /* Register CTRL1. */ LCDIF_CTRL1_BYTE_PACKING_FORMAT(0x0fU) }; # elif defined (CONFIG_IMXRT_LCD_INPUT_BPP24) static const struct pixel_format_reg pixelFormat = { /* Register CTRL. 24-bit. */ LCDIF_CTRL_WORD_LENGTH(3U), /* Register CTRL1. */ LCDIF_CTRL1_BYTE_PACKING_FORMAT(0x0fU) }; # elif defined (CONFIG_IMXRT_LCD_INPUT_BPP32) static const struct pixel_format_reg pixelFormat = { /* Register CTRL. 24-bit. */ LCDIF_CTRL_WORD_LENGTH(3U), /* Register CTRL1. */ LCDIF_CTRL1_BYTE_PACKING_FORMAT(0x07U) }; # endif # if defined (CONFIG_IMXRT_LCD_OUTPUT_8) const uint32_t dataBus = LCDIF_CTRL_LCD_DATABUS_WIDTH(1); # elif defined (CONFIG_IMXRT_LCD_OUTPUT_16) const uint32_t dataBus = LCDIF_CTRL_LCD_DATABUS_WIDTH(0); # elif defined (CONFIG_IMXRT_LCD_OUTPUT_18) const uint32_t dataBus = LCDIF_CTRL_LCD_DATABUS_WIDTH(2); # elif defined (CONFIG_IMXRT_LCD_OUTPUT_24) const uint32_t dataBus = LCDIF_CTRL_LCD_DATABUS_WIDTH(3); # endif #endif /* The framebuffer object -- There is no private state information in this * framebuffer driver. */ struct fb_vtable_s g_fbobject = { .getvideoinfo = imxrt_getvideoinfo, .getplaneinfo = imxrt_getplaneinfo, #ifdef CONFIG_FB_CMAP .getcmap = imxrt_getcmap, .putcmap = imxrt_putcmap, #endif }; /**************************************************************************** * Private Functions ****************************************************************************/ /**************************************************************************** * Name: imxrt_getvideoinfo ****************************************************************************/ static int imxrt_getvideoinfo(FAR struct fb_vtable_s *vtable, FAR struct fb_videoinfo_s *vinfo) { lcdinfo("vtable=%p vinfo=%p\n", vtable, vinfo); if (vtable && vinfo) { memcpy(vinfo, &g_videoinfo, sizeof(struct fb_videoinfo_s)); return OK; } lcderr("ERROR: Returning EINVAL\n"); return -EINVAL; } /**************************************************************************** * Name: imxrt_getplaneinfo ****************************************************************************/ static int imxrt_getplaneinfo(FAR struct fb_vtable_s *vtable, int planeno, FAR struct fb_planeinfo_s *pinfo) { lcdinfo("vtable=%p planeno=%d pinfo=%p\n", vtable, planeno, pinfo); if (vtable && planeno == 0 && pinfo) { memcpy(pinfo, &g_planeinfo, sizeof(struct fb_planeinfo_s)); return OK; } lcderr("ERROR: Returning EINVAL\n"); return -EINVAL; } /**************************************************************************** * Name: imxrt_getcmap ****************************************************************************/ #ifdef CONFIG_FB_CMAP static int imxrt_getcmap(FAR struct fb_vtable_s *vtable, FAR struct fb_cmap_s *cmap) { uint32_t n; uint32_t reg; lcdinfo("vtable=%p cmap=%p first=%d len=%d\n", vtable, cmap, cmap->first, cmap->len); DEBUGASSERT(vtable && cmap); /* Only has 256 entries. */ if (cmap->first + cmap->len > IMXRT_LCDIF_LUT_ENTRY_NUM) { return ERROR; } putreg32(cmap->first, IMXRT_LCDIF_LUT0_ADDR); for (n = 0; n < cmap->len; n++) { reg = getreg32(IMXRT_LCDIF_LUT0_DATA); #if defined (CONFIG_IMXRT_LCD_OUTPUT_24) cmap->red[n] = (reg >> 16) & 0xff; cmap->green[n] = (reg >> 8) & 0xff; cmap->blue[n] = (reg >> 0) & 0xff; #elif defined (CONFIG_IMXRT_LCD_OUTPUT_18) cmap->red[n] = (reg >> 10) & 0xfc; cmap->green[n] = (reg >> 4) & 0xfc; cmap->blue[n] = (reg << 2) & 0xfc; #elif defined (CONFIG_IMXRT_LCD_OUTPUT_16) cmap->red[n] = (reg >> 8) & 0xf8; cmap->green[n] = (reg >> 3) & 0xfc; cmap->blue[n] = (reg << 3) & 0xf8; #endif } return OK; } #endif /**************************************************************************** * Name: imxrt_putcmap ****************************************************************************/ #ifdef CONFIG_FB_CMAP static int imxrt_putcmap(FAR struct fb_vtable_s *vtable, FAR const struct fb_cmap_s *cmap) { uint32_t n; lcdinfo("vtable=%p cmap=%p first=%d len=%d\n", vtable, cmap, cmap->first, cmap->len); DEBUGASSERT(vtable && cmap); /* Only has 256 entries. */ if (cmap->first + cmap->len > IMXRT_LCDIF_LUT_ENTRY_NUM) { return ERROR; } putreg32(cmap->first, IMXRT_LCDIF_LUT0_ADDR); for (n = 0; n < cmap->len; n++) { #if defined (CONFIG_IMXRT_LCD_OUTPUT_24) putreg32((uint32_t)0xff000000 | ((uint32_t)cmap->red[n] << 16) | ((uint32_t)cmap->green[n] << 8) | ((uint32_t)cmap->blue[n] << 0), IMXRT_LCDIF_LUT0_DATA); #elif defined (CONFIG_IMXRT_LCD_OUTPUT_18) putreg32((uint32_t)0xfffc0000 | (((uint32_t)cmap->red[n] & 0xfc) << 10) | (((uint32_t)cmap->green[n] & 0xfc) << 4) | (((uint32_t)cmap->blue[n] & 0xfc) >> 2), IMXRT_LCDIF_LUT0_DATA); #elif defined (CONFIG_IMXRT_LCD_OUTPUT_16) putreg32((uint32_t)0xffff0000 | (((uint32_t)cmap->red[n] & 0xf8) << 8) | (((uint32_t)cmap->green[n] & 0xfc) << 3) | (((uint32_t)cmap->blue[n] & 0xf8) >> 3), IMXRT_LCDIF_LUT0_DATA); #endif } return OK; } #endif /**************************************************************************** * Name: imxrt_lcd_reset ****************************************************************************/ static void imxrt_lcdreset(void) { volatile uint32_t i = IMXRT_LCD_RESET_DELAY; /* Disable the clock gate. */ putreg32(LCDIF_CTRL_CLKGATE_MASK, IMXRT_LCDIF_CTRL_CLR); /* Confirm the clock gate is disabled. */ while ((getreg32(IMXRT_LCDIF_CTRL) & LCDIF_CTRL_CLKGATE_MASK) != 0) { } /* Reset the block. */ putreg32(LCDIF_CTRL_SFTRST_MASK, IMXRT_LCDIF_CTRL_SET); /* Confirm the reset bit is set. */ while ((getreg32(IMXRT_LCDIF_CTRL) & LCDIF_CTRL_SFTRST_MASK) == 0) { } /* Delay for the reset. */ while (i--) { } /* Bring the module out of reset. */ putreg32(LCDIF_CTRL_SFTRST_MASK, IMXRT_LCDIF_CTRL_CLR); /* Disable the clock gate. */ putreg32(LCDIF_CTRL_CLKGATE_MASK, IMXRT_LCDIF_CTRL_CLR); } /**************************************************************************** * Public Functions ****************************************************************************/ /**************************************************************************** * Name: up_fbinitialize * * Description: * Initialize the framebuffer video hardware associated with the display. * * Input Parameters: * display - In the case of hardware with multiple displays, this * specifies the display. Normally this is zero. * * Returned Value: * Zero is returned on success; a negated errno value is returned on any * failure. * ****************************************************************************/ int up_fbinitialize(int display) { #if defined (CONFIG_IMXRT_LCD_INPUT_BPP8_LUT) || defined (CONFIG_IMXRT_LCD_INPUT_BPP8) uint32_t n; #endif /* Configure pins * * LCD panel data. Pins used depend on the panel configuration: */ lcdinfo("Configuring pins\n"); #if defined(CONFIG_IMXRT_LCD_OUTPUT_24) imxrt_config_gpio(GPIO_LCD_DATA23); imxrt_config_gpio(GPIO_LCD_DATA22); imxrt_config_gpio(GPIO_LCD_DATA21); imxrt_config_gpio(GPIO_LCD_DATA20); imxrt_config_gpio(GPIO_LCD_DATA19); imxrt_config_gpio(GPIO_LCD_DATA18); #endif #if defined(CONFIG_IMXRT_LCD_OUTPUT_24) || \ defined(CONFIG_IMXRT_LCD_OUTPUT_18) imxrt_config_gpio(GPIO_LCD_DATA17); imxrt_config_gpio(GPIO_LCD_DATA16); #endif #if defined(CONFIG_IMXRT_LCD_OUTPUT_24) || \ defined(CONFIG_IMXRT_LCD_OUTPUT_18) || \ defined(CONFIG_IMXRT_LCD_OUTPUT_16) imxrt_config_gpio(GPIO_LCD_DATA15); imxrt_config_gpio(GPIO_LCD_DATA14); imxrt_config_gpio(GPIO_LCD_DATA13); imxrt_config_gpio(GPIO_LCD_DATA12); imxrt_config_gpio(GPIO_LCD_DATA11); imxrt_config_gpio(GPIO_LCD_DATA10); imxrt_config_gpio(GPIO_LCD_DATA09); imxrt_config_gpio(GPIO_LCD_DATA08); #endif imxrt_config_gpio(GPIO_LCD_DATA07); imxrt_config_gpio(GPIO_LCD_DATA06); imxrt_config_gpio(GPIO_LCD_DATA05); imxrt_config_gpio(GPIO_LCD_DATA04); imxrt_config_gpio(GPIO_LCD_DATA03); imxrt_config_gpio(GPIO_LCD_DATA02); imxrt_config_gpio(GPIO_LCD_DATA01); imxrt_config_gpio(GPIO_LCD_DATA00); /* Other pins */ imxrt_config_gpio(GPIO_LCD_ENABLE); imxrt_config_gpio(GPIO_LCD_HSYNC); imxrt_config_gpio(GPIO_LCD_VSYNC); imxrt_config_gpio(GPIO_LCD_CLK); lcdinfo("Enable clocking to the LCD controller\n"); /* Enable clocking to the LCD peripheral */ imxrt_clockall_pxp(); imxrt_clockall_lcd(); imxrt_clockall_lcdif_pix(); /* Reset the LCD */ imxrt_lcd_initialize(); imxrt_lcdreset(); lcdinfo("Configuring the LCD controller\n"); putreg32(pixelFormat.regCtrl | dataBus | LCDIF_CTRL_DOTCLK_MODE_MASK | LCDIF_CTRL_BYPASS_COUNT_MASK | LCDIF_CTRL_MASTER_MASK, IMXRT_LCDIF_CTRL); putreg32(pixelFormat.regCtrl1, IMXRT_LCDIF_CTRL1); putreg32((CONFIG_IMXRT_LCD_VHEIGHT << LCDIF_TRANSFER_COUNT_V_COUNT_SHIFT) | (CONFIG_IMXRT_LCD_HWIDTH << LCDIF_TRANSFER_COUNT_H_COUNT_SHIFT), IMXRT_LCDIF_TRANSFER_COUNT); putreg32(LCDIF_VDCTRL0_ENABLE_PRESENT_MASK | LCDIF_VDCTRL0_VSYNC_PERIOD_UNIT_MASK | LCDIF_VDCTRL0_VSYNC_PULSE_WIDTH_UNIT_MASK | VSYNC_POL | HSYNC_POL | DATAEN_POL | DATA_EDGE | CONFIG_IMXRT_LCD_VPULSE, IMXRT_LCDIF_VDCTRL0); putreg32(CONFIG_IMXRT_LCD_VPULSE + CONFIG_IMXRT_LCD_VHEIGHT + CONFIG_IMXRT_LCD_VFRONTPORCH + CONFIG_IMXRT_LCD_VBACKPORCH, IMXRT_LCDIF_VDCTRL1); putreg32((CONFIG_IMXRT_LCD_HPULSE << LCDIF_VDCTRL2_HSYNC_PULSE_WIDTH_SHIFT) | ((CONFIG_IMXRT_LCD_HFRONTPORCH + CONFIG_IMXRT_LCD_HBACKPORCH + CONFIG_IMXRT_LCD_HWIDTH + CONFIG_IMXRT_LCD_HPULSE) << LCDIF_VDCTRL2_HSYNC_PERIOD_SHIFT), IMXRT_LCDIF_VDCTRL2); putreg32(((CONFIG_IMXRT_LCD_HBACKPORCH + CONFIG_IMXRT_LCD_HPULSE) << LCDIF_VDCTRL3_HORIZONTAL_WAIT_CNT_SHIFT) | ((CONFIG_IMXRT_LCD_VBACKPORCH + CONFIG_IMXRT_LCD_VPULSE) << LCDIF_VDCTRL3_VERTICAL_WAIT_CNT_SHIFT), IMXRT_LCDIF_VDCTRL3); putreg32(LCDIF_VDCTRL4_SYNC_SIGNALS_ON_MASK | (CONFIG_IMXRT_LCD_HWIDTH << LCDIF_VDCTRL4_DOTCLK_H_VALID_DATA_CNT_SHIFT), IMXRT_LCDIF_VDCTRL4); #ifdef CONFIG_IMXRT_LCD_BGR /* Swap red and blue. The colors will be 0x00RRGGBB, not 0x00bbGGRR. */ /* TODO */ #endif #if defined (CONFIG_IMXRT_LCD_INPUT_BPP8_LUT) || defined (CONFIG_IMXRT_LCD_INPUT_BPP8) putreg32(0, IMXRT_LCDIF_LUT0_ADDR); for (n = 0; n < IMXRT_LCDIF_LUT_ENTRY_NUM; n++) { uint8_t red; uint8_t green; uint8_t blue; red = (n << 0) & 0xe0; green = (n << 3) & 0xe0; blue = (n << 6) & 0xc0; #if defined (CONFIG_IMXRT_LCD_OUTPUT_24) putreg32((uint32_t)0xff000000 | ((uint32_t)red << 16) | ((uint32_t)green << 8) | ((uint32_t)blue << 0), IMXRT_LCDIF_LUT0_DATA); #elif defined (CONFIG_IMXRT_LCD_OUTPUT_18) putreg32((uint32_t)0xfffc0000 | (((uint32_t)red & 0xfc) << 10) | (((uint32_t)green & 0xfc) << 4) | (((uint32_t)blue & 0xfc) >> 2), IMXRT_LCDIF_LUT0_DATA); #elif defined (CONFIG_IMXRT_LCD_OUTPUT_16) putreg32((uint32_t)0xffff0000 | (((uint32_t)red & 0xf8) << 8) | (((uint32_t)green & 0xfc) << 3) | (((uint32_t)blue & 0xf8) >> 3), IMXRT_LCDIF_LUT0_DATA); #endif } putreg32(0, IMXRT_LCDIF_LUT_CTRL); #endif putreg32(CONFIG_IMXRT_LCD_VRAMBASE, IMXRT_LCDIF_CUR_BUF); putreg32(CONFIG_IMXRT_LCD_VRAMBASE, IMXRT_LCDIF_NEXT_BUF); /* Clear the display */ imxrt_lcdclear(CONFIG_IMXRT_LCD_BACKCOLOR); #ifdef CONFIG_IMXRT_LCD_BACKLIGHT /* Turn on the back light */ imxrt_backlight(true); #endif putreg32(LCDIF_CTRL_RUN_MASK | LCDIF_CTRL_DOTCLK_MODE_MASK, IMXRT_LCDIF_CTRL_SET); return OK; } /**************************************************************************** * Name: up_fbgetvplane * * Description: * Return a a reference to the framebuffer object for the specified video * plane of the specified plane. Many OSDs support multiple planes of * video. * * Input Parameters: * display - In the case of hardware with multiple displays, this * specifies the display. Normally this is zero. * vplane - Identifies the plane being queried. * * Returned Value: * A non-NULL pointer to the frame buffer access structure is returned on * success; NULL is returned on any failure. * ****************************************************************************/ FAR struct fb_vtable_s *up_fbgetvplane(int display, int vplane) { lcdinfo("vplane: %d\n", vplane); if (vplane == 0) { return &g_fbobject; } else { return NULL; } } /**************************************************************************** * Name: up_fbuninitialize * * Description: * Uninitialize the framebuffer support for the specified display. * * Input Parameters: * display - In the case of hardware with multiple displays, this * specifies the display. Normally this is zero. * * Returned Value: * None * ****************************************************************************/ void up_fbuninitialize(int display) { /* We assume there is only one use of the LCD and so we do not need to * worry about mutually exclusive access to the LCD hardware. */ #ifdef CONFIG_IMXRT_LCD_BACKLIGHT /* Turn off the back light */ imxrt_backlight(false); #endif /* Disable the clock gate. */ putreg32(LCDIF_CTRL_CLKGATE_MASK, IMXRT_LCDIF_CTRL_CLR); /* Disable clocking to the LCD peripheral */ imxrt_clockoff_lcdif_pix(); imxrt_clockoff_lcd(); } /**************************************************************************** * Name: imxrt_lcdclear * * Description: * This is a non-standard LCD interface just for the IMXRT. Clearing * the display in the normal way by writing a sequences of runs that * covers the entire display can be slow. Here the display is cleared by * simply setting all VRAM memory to the specified color. * ****************************************************************************/ void imxrt_lcdclear(nxgl_mxpixel_t color) { int i; int size; size = CONFIG_IMXRT_LCD_HWIDTH * CONFIG_IMXRT_LCD_VHEIGHT; #if IMXRT_BPP > 24 uint32_t *dest = (uint32_t *)CONFIG_IMXRT_LCD_VRAMBASE; lcdinfo("Clearing display: color=%08x VRAM=%08x size=%d\n", color, CONFIG_IMXRT_LCD_VRAMBASE, size * sizeof(uint32_t)); #elif IMXRT_BPP > 16 uint32_t *dest = (uint32_t *)CONFIG_IMXRT_LCD_VRAMBASE; size = (size * 3) >> 2; lcdinfo("Clearing display: color=%06x VRAM=%08x size=%d\n", color, CONFIG_IMXRT_LCD_VRAMBASE, size * sizeof(uint32_t)); #elif IMXRT_BPP > 8 uint16_t *dest = (uint16_t *)CONFIG_IMXRT_LCD_VRAMBASE; lcdinfo("Clearing display: color=%04x VRAM=%08x size=%d\n", color, CONFIG_IMXRT_LCD_VRAMBASE, size * sizeof(uint16_t)); #else uint8_t *dest = (uint8_t *)CONFIG_IMXRT_LCD_VRAMBASE; lcdinfo("Clearing display: color=%02x VRAM=%08x size=%d\n", color, CONFIG_IMXRT_LCD_VRAMBASE, size * sizeof(uint8_t)); #endif for (i = 0; i < size; i++) { *dest++ = color; } }