diff --git a/source/hal/source/components/display/CMakeLists.txt b/source/hal/source/components/display/CMakeLists.txt index 109bf4bbf4b3a14e7c42dfac28e89318906183c0..7cf1f12cadbc1b6648f2c6fbbb67e0b59af5f3f1 100644 --- a/source/hal/source/components/display/CMakeLists.txt +++ b/source/hal/source/components/display/CMakeLists.txt @@ -17,7 +17,7 @@ #---------------------------------------------------------------------------- ######################################################### -# LCD library # +# Display library # ######################################################### cmake_minimum_required(VERSION 3.21.0) @@ -31,33 +31,6 @@ set(DISPLAY_IFACE_TARGET hal_display_iface) add_library(${DISPLAY_IFACE_TARGET} INTERFACE) target_include_directories(${DISPLAY_IFACE_TARGET} INTERFACE include) -# Create static library for MPS3 LCD -set(DISPLAY_MPS3_TARGET hal_display_mps3) -add_library(${DISPLAY_MPS3_TARGET} STATIC) - -set(CLCD_CONFIG_BASE "0x4930A000" CACHE STRING "LCD configuration base address") -option(DISPLAY_TITLE_EN "Enables display of title string on LCD" ON) - -if (DISPLAY_TITLE_EN) - set(DISPLAY_TITLE_STRING "Arm ML Embedded Evaluation Kit" CACHE STRING "Title string") -endif() - -## Include directories - private -target_include_directories(${DISPLAY_MPS3_TARGET} PRIVATE - source - source/glcd_mps3) - -## Component sources -target_sources(${DISPLAY_MPS3_TARGET} PRIVATE - source/glcd_mps3/glcd_mps3.c - source/glcd_mps3/hal_display_mps3.c) - -# Compile definitions -target_compile_definitions(${DISPLAY_MPS3_TARGET} - PRIVATE - CLCD_CONFIG_BASE=${CLCD_CONFIG_BASE} - $<$:DISPLAY_TITLE_STRING=\"${DISPLAY_TITLE_STRING}\">) - ## Logging utilities: if (NOT TARGET mlek_log) if (NOT DEFINED LOG_PROJECT_DIR) @@ -66,17 +39,6 @@ if (NOT TARGET mlek_log) add_subdirectory(${LOG_PROJECT_DIR} ${CMAKE_BINARY_DIR}/log) endif() -## Add dependencies -target_link_libraries(${DISPLAY_MPS3_TARGET} PUBLIC - ${DISPLAY_IFACE_TARGET} - mlek_log) - -# Display status -message(STATUS "CMAKE_CURRENT_SOURCE_DIR: " ${CMAKE_CURRENT_SOURCE_DIR}) -message(STATUS "*******************************************************") -message(STATUS "Library: " ${DISPLAY_MPS3_TARGET}) -message(STATUS "*******************************************************") - # Create static library for LCD Stubs set(DISPLAY_STUBS_TARGET hal_display_stubs) add_library(${DISPLAY_STUBS_TARGET} STATIC) @@ -90,6 +52,10 @@ target_link_libraries(${DISPLAY_STUBS_TARGET} PUBLIC ${DISPLAY_IFACE_TARGET} mlek_log) +# Add sub projects +add_subdirectory(source/glcd_mps3 EXCLUDE_FROM_ALL) +add_subdirectory(source/hdlcd_mps4 EXCLUDE_FROM_ALL) + # Display status message(STATUS "CMAKE_CURRENT_SOURCE_DIR:" ${CMAKE_CURRENT_SOURCE_DIR}) message(STATUS "*******************************************************") diff --git a/source/hal/source/components/display/source/font_9x15_h.h b/source/hal/source/components/display/include/font_9x15_h.h similarity index 100% rename from source/hal/source/components/display/source/font_9x15_h.h rename to source/hal/source/components/display/include/font_9x15_h.h diff --git a/source/hal/source/components/display/source/glcd_mps3/CMakeLists.txt b/source/hal/source/components/display/source/glcd_mps3/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..fe45eff9bc8487afbd4686a622168804cfe33fd8 --- /dev/null +++ b/source/hal/source/components/display/source/glcd_mps3/CMakeLists.txt @@ -0,0 +1,60 @@ +#---------------------------------------------------------------------------- +# SPDX-FileCopyrightText: Copyright 2022, 2024-2025 Arm Limited and/or +# its affiliates +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +#---------------------------------------------------------------------------- + +######################################################### +# Display library for MPS3 # +######################################################### + +cmake_minimum_required(VERSION 3.21.0) + +project(display_component + DESCRIPTION "Display support library for MPS3" + LANGUAGES C CXX ASM) + +# Create static library for MPS3 LCD +set(DISPLAY_MPS3_TARGET hal_display_mps3) +add_library(${DISPLAY_MPS3_TARGET} STATIC) + +set(CLCD_CONFIG_BASE "0x4930A000" CACHE STRING "LCD configuration base address") +option(DISPLAY_TITLE_EN "Enables display of title string on LCD" ON) + +if (DISPLAY_TITLE_EN) + set(DISPLAY_TITLE_STRING "Arm ML Embedded Evaluation Kit" CACHE STRING "Title string") +endif() + +## Component sources +target_sources(${DISPLAY_MPS3_TARGET} PRIVATE + glcd_mps3.c + hal_display_mps3.c) + +# Compile definitions +target_compile_definitions(${DISPLAY_MPS3_TARGET} + PRIVATE + CLCD_CONFIG_BASE=${CLCD_CONFIG_BASE} + $<$:DISPLAY_TITLE_STRING=\"${DISPLAY_TITLE_STRING}\">) + +## Add dependencies +target_link_libraries(${DISPLAY_MPS3_TARGET} PUBLIC + hal_display_iface + mlek_log) + +# Display status +message(STATUS "CMAKE_CURRENT_SOURCE_DIR: " ${CMAKE_CURRENT_SOURCE_DIR}) +message(STATUS "*******************************************************") +message(STATUS "Library: " ${DISPLAY_MPS3_TARGET}) +message(STATUS "*******************************************************") diff --git a/source/hal/source/components/display/source/hdlcd_mps4/CMakeLists.txt b/source/hal/source/components/display/source/hdlcd_mps4/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..6fbcdc80dc716d660372d95a75cc622f1a07b481 --- /dev/null +++ b/source/hal/source/components/display/source/hdlcd_mps4/CMakeLists.txt @@ -0,0 +1,59 @@ +#---------------------------------------------------------------------------- +# SPDX-FileCopyrightText: Copyright 2025 Arm Limited and/or +# its affiliates +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +#---------------------------------------------------------------------------- + +######################################################### +# Display library for MPS4 # +######################################################### + +cmake_minimum_required(VERSION 3.21.0) + +project(display_component + DESCRIPTION "Display support library for MPS4" + LANGUAGES C CXX ASM) + +# Create static library for MPS4 HDLCD +set(DISPLAY_MPS4_TARGET hal_display_mps4) +add_library(${DISPLAY_MPS4_TARGET} STATIC) + +set(HDLCD_FRAME_BUFFER_BASE_ADDRESS "0x90000000" CACHE STRING "Framebuffer base address") +set(HDLCD_RES_WIDTH 320 CACHE STRING "Frame width - target HDLCD resolution") +set(HDLCD_RES_HEIGHT 240 CACHE STRING "Frame height - target HDLCD resolution") +set(HDLCD_BYTES_PER_PIXEL 3 CACHE STRING "Bytes per pixel for HDLCD") + +## Definitions - private +target_compile_definitions(${DISPLAY_MPS4_TARGET} PRIVATE + HDLCD_FRAME_BUFFER_BASE_ADDRESS=${HDLCD_FRAME_BUFFER_BASE_ADDRESS} + HDLCD_BYTES_PER_PIXEL=${HDLCD_BYTES_PER_PIXEL} + HDLCD_RES_WIDTH=${HDLCD_RES_WIDTH} + HDLCD_RES_HEIGHT=${HDLCD_RES_WIDTH} + $<$:DISPLAY_TITLE_STRING=\"${DISPLAY_TITLE_STRING}\">) + +## Component sources +target_sources(${DISPLAY_MPS4_TARGET} PRIVATE + hal_display_mps4.c) + +## Add dependencies +target_link_libraries(${DISPLAY_MPS4_TARGET} PUBLIC + hal_display_iface + mlek_log) + +# Display status +message(STATUS "CMAKE_CURRENT_SOURCE_DIR: " ${CMAKE_CURRENT_SOURCE_DIR}) +message(STATUS "*******************************************************") +message(STATUS "Library: " ${DISPLAY_MPS4_TARGET}) +message(STATUS "*******************************************************") diff --git a/source/hal/source/components/display/source/hdlcd_mps4/hal_display_mps4.c b/source/hal/source/components/display/source/hdlcd_mps4/hal_display_mps4.c new file mode 100644 index 0000000000000000000000000000000000000000..16b69f74b65d23ca683b403f75b979dbf6276918 --- /dev/null +++ b/source/hal/source/components/display/source/hdlcd_mps4/hal_display_mps4.c @@ -0,0 +1,379 @@ +/* + * SPDX-FileCopyrightText: Copyright 2025 Arm Limited and/or + * its affiliates + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "hal_display.h" +#include "font_9x15_h.h" + +#include "log_macros.h" + +#include +#include +#include + +#if !defined(__arm__) || (__ARM_ARCH_PROFILE != 77) +#error "This file writes to a fixed address (compile-time determined) meant for MCU targets." +#endif /* !defined(__arm__) || (__ARM_ARCH_PROFILE != 77) */ + +#if !defined(HDLCD_FRAME_BUFFER_BASE_ADDRESS) | \ + !defined(HDLCD_BYTES_PER_PIXEL) | \ + !defined(HDLCD_RES_WIDTH) | \ + !defined(HDLCD_RES_HEIGHT) +#error "Base address, pixel width, height and width should be defined." +#endif /* required definition check. */ + +#if (HDLCD_BYTES_PER_PIXEL == 4) || (HDLCD_BYTES_PER_PIXEL == 3) +struct pixel_value { + uint8_t red; + uint8_t green; + uint8_t blue; +#if HDLCD_BYTES_PER_PIXEL == 4 + uint8_t alpha; +#endif +} __attribute__((packed)); +#else /* (HDLCD_BYTES_PER_PIXEL == 4) || (HDLCD_BYTES_PER_PIXEL == 3) */ +#error "Only RGB24 and RGB32 are supported." +#endif + + +/** +* Text and background colour +*/ +#define BG_COLOUR 0 /* Background colour */ +#define TXT_COLOUR 1 /* Text colour */ + +static volatile struct pixel_value s_colour[] = { + { + .red = 0, + .green = 0, + .blue = 0, +#if HDLCD_BYTES_PER_PIXEL == 4 + .alpha = 0 +#endif + }, + { + .red = 0xff, + .green = 0xff, + .blue = 0xff, +#if HDLCD_BYTES_PER_PIXEL == 4 + .alpha = 0 +#endif + }, +}; + +static hal_display_dev dev = { + .name = "MPS4 HDLCD", + .hor_res = 0, + .ver_res = 0, + .bytes_per_pixel = 0, + .colour_format = HAL_DISPLAY_COLOUR_FORMAT_INVALID, + .initialized = false, +}; + +static hal_display_dev* get_display_device(void) +{ + return &dev; +} + +static int show_title(void) +{ + int ret = 0; +#if defined(DISPLAY_TITLE_STRING) + const char *title = DISPLAY_TITLE_STRING; + if (get_display_device()->initialized) { + hal_display_set_text_color(0xFFFF); + ret = hal_display_show_text(title, strlen(title), 10, 0, false); + } +#endif /* DISPLAY_TITLE_STRING */ + return ret; +} + +int hal_display_init(void) +{ + get_display_device()->initialized = true; +#if (4 == HDLCD_BYTES_PER_PIXEL) + const hal_display_clr_format fmt = HAL_DISPLAY_COLOUR_FORMAT_ARGB8888; +#elif (3 == HDLCD_BYTES_PER_PIXEL) + const hal_display_clr_format fmt = HAL_DISPLAY_COLOUR_FORMAT_RGB888; +#endif /* HDLCD_BYTES_PER_PIXEL */ + hal_display_configure(HDLCD_RES_WIDTH, HDLCD_RES_HEIGHT, fmt); + return show_title(); +} + +int hal_display_configure(uint32_t width, uint32_t height, hal_display_clr_format format) +{ + hal_display_dev* dev = get_display_device(); + if (!dev->initialized) { + return -1; + } + + dev->hor_res = width; + dev->ver_res = height; + + char fmt_str[16]; + memset(fmt_str, 0, sizeof(fmt_str)); + + switch (format) { + case HAL_DISPLAY_COLOUR_FORMAT_RGB565: + strncpy(fmt_str, "RGB565", sizeof(fmt_str) - 1); + dev->bytes_per_pixel = 2; + break; + case HAL_DISPLAY_COLOUR_FORMAT_RGB888: + strncpy(fmt_str, "RGB888", sizeof(fmt_str) - 1); + dev->bytes_per_pixel = 3; + break; + case HAL_DISPLAY_COLOUR_FORMAT_ARGB8888: + strncpy(fmt_str, "ARGB8888", sizeof(fmt_str) - 1); + dev->bytes_per_pixel = 4; + break; + default: + printf_err("Unsupported colour format\n"); + return -3; + } + + dev->colour_format = format; + dev->initialized = true; + + info("Device %s configured\n", dev->name); + info("Resolution: %" PRIu32 " x %" PRIu32 "\n", dev->hor_res, dev->ver_res); + info("Colour format: %s\n", fmt_str); + return 0; +} + +uint32_t hal_display_get_width(void) +{ + hal_display_dev* dev = get_display_device(); + if (dev->initialized) { + return dev->hor_res; + } + return 0; +} + +uint32_t hal_display_get_height(void) +{ + hal_display_dev* dev = get_display_device(); + if (dev->initialized) { + return dev->ver_res; + } + return 0; +} + +int hal_display_show_image(const uint8_t* data, const uint32_t width, + const uint32_t height, const uint32_t channels, + const uint32_t pos_x, const uint32_t pos_y, + const uint32_t downsample_factor) +{ + debug("image display: (x, y, w, h) = " + "(%" PRIu32 ", %" PRIu32 ", %" PRIu32 ", %" PRIu32 ")\n", + pos_x, pos_y, width, height); + debug("image display: channels = %" PRIu32 ", downsample factor = %" PRIu32 "\n", + channels, downsample_factor); + + const uint32_t line_stride = HDLCD_RES_WIDTH * HDLCD_BYTES_PER_PIXEL; + uint8_t* dst = (uint8_t*)(HDLCD_FRAME_BUFFER_BASE_ADDRESS); + uint8_t* src = (uint8_t*)data; + + if (channels <= HDLCD_BYTES_PER_PIXEL) { + for (uint32_t j = 0; j < height/downsample_factor; ++j) { + uint8_t* dst_row = dst + ((j + pos_y) * line_stride); + uint8_t* src_row = src + (j * width * channels * downsample_factor); + for (uint32_t i = 0; i < width/downsample_factor; ++i) { + memcpy(dst_row + ((pos_x + i) * HDLCD_BYTES_PER_PIXEL), + src_row + (i * channels * downsample_factor), + channels); + } + } + } else { + printf_err("Unsupported number of channels %" PRIu32 "\n", channels); + return -1; + } + return 0; +} + +/** + * @brief Gets the pixel values (RGB) from RGB16 value + * @param[in] color 16-bit value representing RGB656 + * @return colour expressed as `struct pixel_value`. + */ +static struct pixel_value get_color_from_rgb565(unsigned short color) +{ + struct pixel_value tmp = { + .red = ((color >> 11) & 0x1F) << 3, + .green = ((color >> 5) & 0x3F) << 2, + .blue = ((color >> 0) & 0x1F) << 3, +#if HDLCD_BYTES_PER_PIXEL == 4 + .alpha = 0 +#endif + }; + return tmp; +} + +/** + * @brief Draws a character to framebuffer. + * @param[in] x Horizontal position to draw from. + * @param[in] y Vertical position to draw from. + * @param[in] cw Character width (depends on the font). + * @param[in] ch Character width (depends on the font). + * @param[in] c Character to be drawn. + */ +static void draw_char( + unsigned int x, unsigned int y, + unsigned int cw, unsigned int ch, + unsigned char *c) +{ + unsigned int i, j, k, pixs; + + /* Health check: out of bounds? */ + if ((x + cw) > HDLCD_RES_WIDTH || (y + ch) > HDLCD_RES_HEIGHT) { + return; + } + + uint8_t* dst = (uint8_t*)(HDLCD_FRAME_BUFFER_BASE_ADDRESS) + + (y * HDLCD_RES_WIDTH * HDLCD_BYTES_PER_PIXEL) + + (x * HDLCD_BYTES_PER_PIXEL); + struct pixel_value* dst_pixel = (struct pixel_value*)dst; + + k = (cw + 7)/8; + + if (k == 1) { + for (j = 0; j < ch; ++j) { + pixs = *(unsigned char *)c; + c += 1; + for (i = 0; i < cw; ++i) { + dst_pixel[i] = s_colour[(pixs >> i) & 1]; + } + dst_pixel += HDLCD_RES_WIDTH; + } + } + else if (k == 2) { + for (j = 0; j < ch; ++j) { + pixs = *(unsigned short *)c; + c += 2; + for (i = 0; i < cw; ++i) { + dst_pixel[i] = s_colour[(pixs >> i) & 1]; + } + dst_pixel += HDLCD_RES_WIDTH; + } + } +} + +/** + * @brief Renders a character on framebuffer. + * @param[in] ln Line number (depends on the font). + * @param[in] col Horizontal position to draw from. + * @param[in] fi Font index to use. + * @param[in] c Character to be drawn. + */ +static void render_char( + unsigned int ln, unsigned int col, + unsigned char fi, unsigned char c) +{ + c -= 32; + switch (fi) { + case 0: /* Font 9 x 15. */ + draw_char(col * 9, ln * 15, 9, 15, (unsigned char *)&Font_9x15_h[c * 15]); + break; + } +} + +int hal_display_show_text(const char* str, const size_t str_sz, + const uint32_t pos_x, const uint32_t pos_y, + const bool allow_multiple_lines) +{ + hal_display_dev* dev = get_display_device(); + assert(dev->initialized); + + /* We use a font 0 which is 9x15. */ + const uint32_t x_span = 9; /* Each character is this 9 pixels "wide". */ + const uint32_t y_span = 15; /* Each character is this 15 pixels "high". */ + + if (str_sz == 0) { + return 1; + } + + /* If not within the LCD bounds, return error. */ + if (pos_x + x_span > dev->hor_res || pos_y + y_span > dev->ver_res) { + return 1; + } else { + const unsigned char font_idx = 0; /* We are using the custom font = 0 */ + + const uint32_t col = pos_x/x_span; + const uint32_t max_cols = dev->hor_res/x_span - 1; + const uint32_t max_lines = dev->ver_res/y_span - 1; + + uint32_t i = 0; + uint32_t current_line = pos_y/y_span; + uint32_t current_col = col; + + /* Display the string on the LCD. */ + for (i = 0; i < str_sz; ++i) { + + if (allow_multiple_lines) { + + /* If the next character won't fit. */ + if (current_col > max_cols) { + current_col = col; + + /* If the next line won't fit. */ + if (++current_line > max_lines) { + return 1; + } + } + } + + render_char(current_line, current_col++, font_idx, str[i]); + } + } + return 0; +} + +int hal_display_show_box(const uint32_t pos_x, const uint32_t pos_y, + const uint32_t width, const uint32_t height, const uint16_t color) +{ + hal_display_dev* dev = get_display_device(); + assert(dev->initialized); + + /* If not within the LCD bounds, return error. */ + if (pos_x > dev->hor_res || pos_y > dev->ver_res) { + return 1; + } + + /** TODO: Draw lines for a box */ + UNUSED(width); + UNUSED(height); + UNUSED(color); + return 0; +} + +int hal_display_clear(const uint16_t color) +{ + struct pixel_value c = get_color_from_rgb565(color); + s_colour[BG_COLOUR] = c; + + struct pixel_value * dst = (struct pixel_value *)(HDLCD_FRAME_BUFFER_BASE_ADDRESS); + for (uint32_t j = 0; j < HDLCD_RES_WIDTH * HDLCD_RES_HEIGHT; ++j) { + *dst++ = c; + } + + return show_title(); +} + +int hal_display_set_text_color(const uint16_t color) +{ + assert(get_display_device()->initialized); + s_colour[TXT_COLOUR] = get_color_from_rgb565(color); + return 0; +} diff --git a/source/hal/source/platform/mps4/CMakeLists.txt b/source/hal/source/platform/mps4/CMakeLists.txt index 6af95af5c72fe2b34e720d6050d288da79e36325..9448342edebceb4833f1b15732075f14d2234a4f 100644 --- a/source/hal/source/platform/mps4/CMakeLists.txt +++ b/source/hal/source/platform/mps4/CMakeLists.txt @@ -64,6 +64,15 @@ math(EXPR OFM_BASE "${DYNAMIC_IFM_BASE} + ${DYNAMIC_IFM_SIZE}" OUTPUT_FORMA set(DYNAMIC_OFM_BASE "${OFM_BASE}" CACHE STRING "Base address for OFMs to be dumped to") set(DYNAMIC_OFM_SIZE "0x01000000" CACHE STRING "Size of the space reserved for the OFM") +# HDLCD parameters +math(EXPR HDLCD_FRAME_BUFFER_BASE_ADDRESS "${DYNAMIC_OFM_BASE} + ${DYNAMIC_OFM_SIZE}" OUTPUT_FORMAT HEXADECIMAL) + +# Although the device is capable of better resolutions, +# we currently stick to the resolution that is supported +# for MPS3 based targets to keep parity. +set(HDLCD_RES_WIDTH 320) +set(HDLCD_RES_HEIGHT 240) +set(HDLCD_BYTES_PER_PIXEL 4) # 2. Create static library add_library(${PLATFORM_DRIVERS_TARGET} STATIC) @@ -79,10 +88,18 @@ target_include_directories(${PLATFORM_DRIVERS_TARGET} include include/${TARGET_SUBSYSTEM}) +## Compile definitions +target_compile_definitions(${PLATFORM_DRIVERS_TARGET} PRIVATE + HDLCD_FRAME_BUFFER_BASE_ADDRESS=${HDLCD_FRAME_BUFFER_BASE_ADDRESS} + HDLCD_BYTES_PER_PIXEL=${HDLCD_BYTES_PER_PIXEL} + HDLCD_RES_WIDTH=${HDLCD_RES_WIDTH} + HDLCD_RES_HEIGHT=${HDLCD_RES_HEIGHT}) + ## Platform sources target_sources(${PLATFORM_DRIVERS_TARGET} PRIVATE source/timer_mps4.c + source/hdlcd_drv.c source/platform_drivers.c) ## Directory for additional components required by MPS4: @@ -126,7 +143,7 @@ target_link_libraries(${PLATFORM_DRIVERS_TARGET} PUBLIC mlek_log cmsis_device platform_pmu - hal_display_stubs + hal_display_mps4 hal_audio_static_streams $,hal_camera_vsi,hal_camera_static_images> $<$>:stdout_retarget_cmsdk>) diff --git a/source/hal/source/platform/mps4/source/hdlcd_drv.c b/source/hal/source/platform/mps4/source/hdlcd_drv.c new file mode 100644 index 0000000000000000000000000000000000000000..0ec312629101a200000eed19ec5935bb78948edc --- /dev/null +++ b/source/hal/source/platform/mps4/source/hdlcd_drv.c @@ -0,0 +1,494 @@ +/* + * SPDX-FileCopyrightText: Copyright 2023, 2024-2025 Arm Limited and/or + * its affiliates + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * \file hdlcd_drv.c + * + * \brief Driver for HDLCD + */ + +#include "hdlcd_drv.h" +#include "hdlcd_reg_map.h" + +const struct hdlcd_resolution_cfg_t HDLCD_RES[HDLCD_RES_NUM] = { + [HDLCD_RES_VGA] = {.h_data = 640, .h_front_porch = 16, .h_sync = 64, .h_back_porch = 80, + .v_data = 480, .v_front_porch = 3, .v_sync = 4, .v_back_porch = 13}, + [HDLCD_RES_SVGA] = {.h_data = 800, .h_front_porch = 32, .h_sync = 80, .h_back_porch = 112, + .v_data = 600, .v_front_porch = 3, .v_sync = 4, .v_back_porch = 17}, + [HDLCD_RES_XGA] = {.h_data = 1024, .h_front_porch = 48, .h_sync = 104, .h_back_porch = 152, + .v_data = 768, .v_front_porch = 3, .v_sync = 4, .v_back_porch = 23}, + [HDLCD_RES_UXGA] = {.h_data = 1600, .h_front_porch = 112, .h_sync = 168, .h_back_porch = 280, + .v_data = 1200, .v_front_porch = 3, .v_sync = 4, .v_back_porch = 38}, + [HDLCD_RES_320x240] = {.h_data = 320, .h_front_porch = 8, .h_sync = 32, .h_back_porch = 40, + .v_data = 240, .v_front_porch = 3, .v_sync = 4, .v_back_porch = 6}, + [HDLCD_RES_SXGA] = {.h_data = 1280, .h_front_porch = 80, .h_sync = 136, .h_back_porch = 216, + .v_data = 1024, .v_front_porch = 3, .v_sync = 7, .v_back_porch = 29}, + [HDLCD_RES_HD720] = {.h_data = 1280, .h_front_porch = 64, .h_sync = 128, .h_back_porch = 192, + .v_data = 720, .v_front_porch = 3, .v_sync = 5, .v_back_porch = 20}, + [HDLCD_RES_HD768] = {.h_data = 1366, .h_front_porch = 72, .h_sync = 136, .h_back_porch = 208, + .v_data = 768, .v_front_porch = 3, .v_sync = 10, .v_back_porch = 17}, + [HDLCD_RES_HD1080] = {.h_data = 1920, .h_front_porch = 128, .h_sync = 200, .h_back_porch = 328, + .v_data = 1080, .v_front_porch = 3, .v_sync = 5, .v_back_porch = 32}, + [HDLCD_RES_640x360] = {.h_data = 640, .h_front_porch = 16, .h_sync = 64, .h_back_porch = 80, + .v_data = 360, .v_front_porch = 3, .v_sync = 5, .v_back_porch = 8} +}; + +enum hdlcd_error_t hdlcd_init(struct hdlcd_dev_t* dev) +{ + struct hdlcd_reg_map_t* p_hdlcd; + + if(!dev) { + return HDLCD_ERR; + } + + p_hdlcd = (struct hdlcd_reg_map_t*)dev->cfg->base; + + if((p_hdlcd->version & VERSION_PRODUCT_ID_Msk) != + (PRODUCT_ID << VERSION_PRODUCT_ID_Pos)) { + return HDLCD_ERR; + } + + if (dev->data->is_initialized == false) { + dev->data->is_initialized = true; + } + p_hdlcd->int_mask &= ~(INT_UNDERRUN_Msk | INT_VSYNC_Msk | INT_BUS_ERROR_Msk | INT_DMA_END_Msk); + p_hdlcd->command &= ~COMMAND_ENABLE_Msk; + + return HDLCD_ERR_NONE; +} + +enum hdlcd_error_t hdlcd_uninit(struct hdlcd_dev_t* dev) +{ + struct hdlcd_reg_map_t* p_hdlcd; + + if (dev->data->is_initialized == false) { + return HDLCD_ERR; + } + + p_hdlcd = (struct hdlcd_reg_map_t*)dev->cfg->base; + + if (dev->data->is_initialized == true) { + dev->data->is_initialized = false; + } + + p_hdlcd->int_mask &= ~(INT_UNDERRUN_Msk | INT_VSYNC_Msk | INT_BUS_ERROR_Msk | INT_DMA_END_Msk); + p_hdlcd->command &= ~COMMAND_ENABLE_Msk; + + return HDLCD_ERR_NONE; +} + +enum hdlcd_error_t hdlcd_static_config(struct hdlcd_dev_t* dev) +{ + struct hdlcd_reg_map_t* p_hdlcd; + const struct hdlcd_dev_cfg_t* p_cfg; + + if (dev->data->is_initialized == false) { + return HDLCD_ERR; + } + + p_hdlcd = (struct hdlcd_reg_map_t*)dev->cfg->base; + p_cfg = dev->cfg; + + p_hdlcd->polarities = p_cfg->polarities; + p_hdlcd->bus_options = p_cfg->bus_options; + + return HDLCD_ERR_NONE; +} + +enum hdlcd_error_t hdlcd_set_resolution(struct hdlcd_dev_t* dev, enum hdlcd_resolution_t resolution) +{ + if (dev->data->is_initialized == false) { + return HDLCD_ERR; + } + if (resolution >= HDLCD_RES_NUM) { + return HDLCD_ERR; + } + return hdlcd_set_custom_resolution(dev, &HDLCD_RES[resolution]); +} + +enum hdlcd_error_t hdlcd_set_custom_resolution(struct hdlcd_dev_t* dev, const struct hdlcd_resolution_cfg_t* resolution_cfg) +{ + struct hdlcd_reg_map_t* p_hdlcd; + + if (dev->data->is_initialized == false) { + return HDLCD_ERR; + } + + p_hdlcd = (struct hdlcd_reg_map_t*)dev->cfg->base; + + p_hdlcd->hsync_data_width = resolution_cfg->h_data - 1; + p_hdlcd->hsync_front_porch_width = resolution_cfg->h_front_porch - 1; + p_hdlcd->hsync_width = resolution_cfg->h_sync - 1; + p_hdlcd->hsync_back_porch_width = resolution_cfg->h_back_porch - 1; + + /* FIXME: Current FVP requires VSYNC_DATA to be 3 pixel greater */ + p_hdlcd->vsync_data_width = resolution_cfg->v_data - 1; + p_hdlcd->vsync_front_porch_width = resolution_cfg->v_front_porch - 1; + p_hdlcd->vsync_width = resolution_cfg->v_sync - 1; + p_hdlcd->vsync_back_porch_width = resolution_cfg->v_back_porch - 1; + + return HDLCD_ERR_NONE; +} + +enum hdlcd_error_t hdlcd_get_custom_resolution(struct hdlcd_dev_t* dev, struct hdlcd_resolution_cfg_t* resolution_cfg) +{ + struct hdlcd_reg_map_t* p_hdlcd; + + if (dev->data->is_initialized == false) { + return HDLCD_ERR; + } + + p_hdlcd = (struct hdlcd_reg_map_t*)dev->cfg->base; + + resolution_cfg->h_data = p_hdlcd->hsync_data_width + 1; + resolution_cfg->h_front_porch = p_hdlcd->hsync_front_porch_width + 1; + resolution_cfg->h_sync = p_hdlcd->hsync_width + 1; + resolution_cfg->h_back_porch = p_hdlcd->hsync_back_porch_width + 1; + + /* FIXME: Current FVP requires VSYNC_DATA to be 3 pixel greater */ + resolution_cfg->v_data = p_hdlcd->vsync_data_width + 1; + resolution_cfg->v_front_porch = p_hdlcd->vsync_front_porch_width + 1; + resolution_cfg->v_sync = p_hdlcd->vsync_width + 1; + resolution_cfg->v_back_porch = p_hdlcd->vsync_back_porch_width + 1; + + return HDLCD_ERR_NONE; +} + +enum hdlcd_error_t hdlcd_buffer_config(struct hdlcd_dev_t* dev, struct hdlcd_buffer_cfg_t* buff) +{ + struct hdlcd_reg_map_t* p_hdlcd; + + if (dev->data->is_initialized == false) { + return HDLCD_ERR; + } + if(!buff) { + return HDLCD_ERR; + } + + p_hdlcd = (struct hdlcd_reg_map_t*)dev->cfg->base; + + p_hdlcd->fb_base_addr = buff->base_address; + p_hdlcd->fb_line_length = buff->line_length; + p_hdlcd->fb_line_count = buff->line_count; + p_hdlcd->fb_line_pitch = buff->line_pitch; + + p_hdlcd->pixel_format = buff->pixel_format; + + return HDLCD_ERR_NONE; +} + +enum hdlcd_error_t hdlcd_pixel_config(struct hdlcd_dev_t* dev, const struct hdlcd_pixel_cfg_t* pixel) +{ + struct hdlcd_reg_map_t* p_hdlcd; + + if (dev->data->is_initialized == false) { + return HDLCD_ERR; + } + if(!pixel) { + return HDLCD_ERR; + } + + p_hdlcd = (struct hdlcd_reg_map_t*)dev->cfg->base; + + p_hdlcd->red_select = pixel->red.default_color << COLOR_SELECT_DEFAULT_Pos | + pixel->red.bit_size << COLOR_SELECT_SIZE_Pos | + pixel->red.offset << COLOR_SELECT_OFFSET_Pos; + + p_hdlcd->green_select = pixel->green.default_color << COLOR_SELECT_DEFAULT_Pos | + pixel->green.bit_size << COLOR_SELECT_SIZE_Pos | + pixel->green.offset << COLOR_SELECT_OFFSET_Pos; + + p_hdlcd->blue_select = pixel->blue.default_color << COLOR_SELECT_DEFAULT_Pos | + pixel->blue.bit_size << COLOR_SELECT_SIZE_Pos | + pixel->blue.offset << COLOR_SELECT_OFFSET_Pos; + + return HDLCD_ERR_NONE; +} + +enum hdlcd_error_t hdlcd_enable(struct hdlcd_dev_t* dev) +{ + struct hdlcd_reg_map_t* p_hdlcd; + + if (dev->data->is_initialized == false) { + return HDLCD_ERR; + } + + p_hdlcd = (struct hdlcd_reg_map_t*)dev->cfg->base; + + p_hdlcd->command |= COMMAND_ENABLE_Msk; + + return HDLCD_ERR_NONE; +} + +enum hdlcd_error_t hdlcd_disable(struct hdlcd_dev_t* dev) +{ + struct hdlcd_reg_map_t* p_hdlcd; + + if (dev->data->is_initialized == false) { + return HDLCD_ERR; + } + + p_hdlcd = (struct hdlcd_reg_map_t*)dev->cfg->base; + + p_hdlcd->command &= ~COMMAND_ENABLE_Msk; + + return HDLCD_ERR_NONE; +} + +enum hdlcd_error_t hdlcd_enable_irq(struct hdlcd_dev_t* dev, uint32_t mask) +{ + struct hdlcd_reg_map_t* p_hdlcd; + + if (dev->data->is_initialized == false) { + return HDLCD_ERR; + } + + p_hdlcd = (struct hdlcd_reg_map_t*)dev->cfg->base; + + p_hdlcd->int_mask |= mask; + + return HDLCD_ERR_NONE; +} + +enum hdlcd_error_t hdlcd_disable_irq(struct hdlcd_dev_t* dev, uint32_t mask) +{ + struct hdlcd_reg_map_t* p_hdlcd; + + if (dev->data->is_initialized == false) { + return HDLCD_ERR; + } + + p_hdlcd = (struct hdlcd_reg_map_t*)dev->cfg->base; + + p_hdlcd->int_mask &= ~mask; + + return HDLCD_ERR_NONE; +} + +enum hdlcd_error_t hdlcd_generate_irq(struct hdlcd_dev_t* dev, uint32_t mask) +{ + struct hdlcd_reg_map_t* p_hdlcd; + + if (dev->data->is_initialized == false) { + return HDLCD_ERR; + } + + p_hdlcd = (struct hdlcd_reg_map_t*)dev->cfg->base; + + p_hdlcd->raw_int_stat = mask; + + return HDLCD_ERR_NONE; +} + +enum hdlcd_error_t hdlcd_clear_irq(struct hdlcd_dev_t* dev, uint32_t mask) +{ + struct hdlcd_reg_map_t* p_hdlcd; + + if (dev->data->is_initialized == false) { + return HDLCD_ERR; + } + + p_hdlcd = (struct hdlcd_reg_map_t*)dev->cfg->base; + + p_hdlcd->int_clr = mask; + + return HDLCD_ERR_NONE; +} + +uint32_t hdlcd_get_irq_state(struct hdlcd_dev_t* dev) +{ + struct hdlcd_reg_map_t* p_hdlcd = (struct hdlcd_reg_map_t*)dev->cfg->base; + + return p_hdlcd->int_stat; +} + +enum hdlcd_error_t hdlcd_set_user_output(struct hdlcd_dev_t* dev, uint32_t value) +{ + struct hdlcd_reg_map_t* p_hdlcd; + + if (dev->data->is_initialized == false) { + return HDLCD_ERR; + } + + p_hdlcd = (struct hdlcd_reg_map_t*)dev->cfg->base; + + p_hdlcd->user_output = value; + + return HDLCD_ERR_NONE; +} + +uint32_t hdlcd_get_user_output(struct hdlcd_dev_t* dev) +{ + struct hdlcd_reg_map_t* p_hdlcd = (struct hdlcd_reg_map_t*)dev->cfg->base; + + return p_hdlcd->user_output; +} + +enum hdlcd_error_t hdlcd_set_frame_buffer_base_address(struct hdlcd_dev_t* dev, uint32_t value) +{ + struct hdlcd_reg_map_t* p_hdlcd; + + if (dev->data->is_initialized == false) { + return HDLCD_ERR; + } + + p_hdlcd = (struct hdlcd_reg_map_t*)dev->cfg->base; + + p_hdlcd->fb_base_addr = value; + + return HDLCD_ERR_NONE; +} + + uint32_t hdlcd_get_frame_buffer_base_address(struct hdlcd_dev_t* dev) +{ + struct hdlcd_reg_map_t* p_hdlcd = (struct hdlcd_reg_map_t*)dev->cfg->base; + + return p_hdlcd->fb_base_addr; +} + +enum hdlcd_error_t hdlcd_set_frame_buffer_line_length(struct hdlcd_dev_t* dev, uint32_t value) +{ + struct hdlcd_reg_map_t* p_hdlcd; + + if (dev->data->is_initialized == false) { + return HDLCD_ERR; + } + + p_hdlcd = (struct hdlcd_reg_map_t*)dev->cfg->base; + + p_hdlcd->fb_line_length = value; + + return HDLCD_ERR_NONE; +} + + uint32_t hdlcd_get_frame_buffer_line_length(struct hdlcd_dev_t* dev) +{ + struct hdlcd_reg_map_t* p_hdlcd = (struct hdlcd_reg_map_t*)dev->cfg->base; + + return p_hdlcd->fb_line_length; +} + +enum hdlcd_error_t hdlcd_set_frame_buffer_line_count(struct hdlcd_dev_t* dev, uint32_t value) +{ + struct hdlcd_reg_map_t* p_hdlcd; + + if (dev->data->is_initialized == false) { + return HDLCD_ERR; + } + + p_hdlcd = (struct hdlcd_reg_map_t*)dev->cfg->base; + + p_hdlcd->fb_line_count = value; + + return HDLCD_ERR_NONE; +} + + uint32_t hdlcd_get_frame_buffer_line_count(struct hdlcd_dev_t* dev) +{ + struct hdlcd_reg_map_t* p_hdlcd = (struct hdlcd_reg_map_t*)dev->cfg->base; + + return p_hdlcd->fb_line_count; +} + +enum hdlcd_error_t hdlcd_set_frame_buffer_line_pitch(struct hdlcd_dev_t* dev, uint32_t value) +{ + struct hdlcd_reg_map_t* p_hdlcd; + + if (dev->data->is_initialized == false) { + return HDLCD_ERR; + } + + p_hdlcd = (struct hdlcd_reg_map_t*)dev->cfg->base; + + p_hdlcd->fb_line_pitch = value; + + return HDLCD_ERR_NONE; +} + + uint32_t hdlcd_get_frame_buffer_line_pitch(struct hdlcd_dev_t* dev) +{ + struct hdlcd_reg_map_t* p_hdlcd = (struct hdlcd_reg_map_t*)dev->cfg->base; + + return p_hdlcd->fb_line_pitch; +} + +enum hdlcd_error_t set_select_register(struct hdlcd_dev_t* dev, + enum hdlcd_color_t color, struct hdlcd_color_cfg_t* color_cfg) +{ + + struct hdlcd_reg_map_t* p_hdlcd; + uint32_t reg_value = 0; + + if (dev->data->is_initialized == false) { + return HDLCD_ERR; + } + + p_hdlcd = (struct hdlcd_reg_map_t*)dev->cfg->base; + + reg_value = ((color_cfg->default_color << COLOR_SELECT_DEFAULT_Pos) & COLOR_SELECT_DEFAULT_Msk); + reg_value |= ((color_cfg->bit_size << COLOR_SELECT_SIZE_Pos) & COLOR_SELECT_SIZE_Msk); + reg_value |= ((color_cfg->offset << COLOR_SELECT_OFFSET_Pos) & COLOR_SELECT_OFFSET_Msk); + + switch(color) { + case HDLCD_COLOR_RED: + p_hdlcd->red_select = reg_value; + break; + case HDLCD_COLOR_GREEN: + p_hdlcd->green_select = reg_value; + break; + case HDLCD_COLOR_BLUE: + p_hdlcd->blue_select = reg_value; + break; + default: + return HDLCD_ERR; + } + + return HDLCD_ERR_NONE; +} + +enum hdlcd_error_t get_select_register(struct hdlcd_dev_t* dev, + enum hdlcd_color_t color, struct hdlcd_color_cfg_t* color_cfg) +{ + struct hdlcd_reg_map_t* p_hdlcd; + uint32_t reg_value = 0; + + if (dev->data->is_initialized == false) { + return HDLCD_ERR; + } + + p_hdlcd = (struct hdlcd_reg_map_t*)dev->cfg->base; + + switch(color) { + case HDLCD_COLOR_RED: + reg_value = p_hdlcd->red_select; + break; + case HDLCD_COLOR_GREEN: + reg_value = p_hdlcd->green_select; + break; + case HDLCD_COLOR_BLUE: + reg_value = p_hdlcd->blue_select; + break; + default: + return HDLCD_ERR; + } + + color_cfg->default_color = ((reg_value >> COLOR_SELECT_DEFAULT_Pos) & COLOR_SELECT_DEFAULT_Msk); + color_cfg->bit_size = ((reg_value >> COLOR_SELECT_SIZE_Pos) & COLOR_SELECT_SIZE_Msk); + color_cfg->offset = ((reg_value >> COLOR_SELECT_OFFSET_Pos) & COLOR_SELECT_OFFSET_Msk); + + return HDLCD_ERR_NONE; +} diff --git a/source/hal/source/platform/mps4/source/hdlcd_drv.h b/source/hal/source/platform/mps4/source/hdlcd_drv.h new file mode 100644 index 0000000000000000000000000000000000000000..0dd4f4d9888db4f8c66f842964b947812a387bbf --- /dev/null +++ b/source/hal/source/platform/mps4/source/hdlcd_drv.h @@ -0,0 +1,426 @@ +/* + * SPDX-FileCopyrightText: Copyright 2023, 2025 Arm Limited and/or + * its affiliates + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * \file hdlcd_drv.h + * + * \brief Driver for HDLCD + */ + +#ifndef __HDLCD_DRV_H__ +#define __HDLCD_DRV_H__ + +#include +#include +#include "hdlcd_reg_map.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define PRODUCT_ID 0x1CDC +#define BYTESPERPIXEL4 3 +#define BYTESPERPIXEL3 2 +#define BYTESPERPIXEL2 1 +#define BYTESPERPIXEL1 0 + +enum hdlcd_error_t { + HDLCD_ERR_NONE, /*!< No error */ + HDLCD_ERR /*!< Generic error */ +}; + +enum hdlcd_color_t { + HDLCD_COLOR_RED, + HDLCD_COLOR_GREEN, + HDLCD_COLOR_BLUE +}; + +/** + * \brief Supported HDLCD resolutions enum + */ +enum hdlcd_resolution_t { + /* 4:3 */ + HDLCD_RES_VGA = 0, + HDLCD_RES_SVGA, + HDLCD_RES_XGA, + HDLCD_RES_UXGA, + /* Non-standard */ + HDLCD_RES_320x240, + /* 5:4 */ + HDLCD_RES_SXGA, + /* 16:9 */ + HDLCD_RES_HD720, + HDLCD_RES_HD768, + HDLCD_RES_HD1080, + /* Non-standard */ + HDLCD_RES_640x360, + HDLCD_RES_NUM +}; + +/** + * \brief HDLCD device configuration structure + */ +struct hdlcd_resolution_cfg_t { + uint32_t h_data; + uint32_t h_front_porch; + uint32_t h_sync; + uint32_t h_back_porch; + uint32_t v_data; + uint32_t v_front_porch; + uint32_t v_sync; + uint32_t v_back_porch; +}; + +/** + * \brief Supported HDLCD resolutions config + */ +extern const struct hdlcd_resolution_cfg_t HDLCD_RES[HDLCD_RES_NUM]; + +/** + * \brief HDLCD device configuration structure + */ +struct hdlcd_dev_cfg_t { + /*!< HDLCD device base address */ + const uint32_t base; + /*!< Polarities of the sync signals for the LCD panel */ + const uint32_t polarities; + /*!< Aspects of how the LCD controller accesses the bus */ + const uint32_t bus_options; +}; + +/** + * \brief HDLCD device data structure + */ +struct hdlcd_dev_data_t { + bool is_initialized; +}; + +/** + * \brief HDLCD buffer structure + */ +struct hdlcd_buffer_cfg_t { + /*!< Address of the first pixel of the first line in the frame buffer */ + uint32_t base_address; + /*!< The length of each frame buffer line in bytes */ + uint32_t line_length; + /*!< The number of lines to read from the frame buffer */ + uint32_t line_count; + /*!< The number of bytes between the start of one line in the frame buffer and the start of the next line */ + uint32_t line_pitch; + /*!< Endianness and number of bytes per pixel */ + uint32_t pixel_format; +}; + +/** + * \brief HDLCD color structure + */ +struct hdlcd_color_cfg_t { + /*!< Defaulr color */ + uint32_t default_color; + /*!< Number of bits to exract */ + uint32_t bit_size; + /*!< Index of the lowest bit to extract */ + uint32_t offset; +}; + +/** + * \brief HDLCD pixel structure + */ +struct hdlcd_pixel_cfg_t { + struct hdlcd_color_cfg_t red; + struct hdlcd_color_cfg_t green; + struct hdlcd_color_cfg_t blue; +}; + +/** + * \brief HDLCD device structure + */ +struct hdlcd_dev_t { + /*!< HDLCD configuration structure */ + const struct hdlcd_dev_cfg_t* const cfg; + /*!< HDLCD data structure */ + struct hdlcd_dev_data_t* const data; +}; + +/** + * \brief Initializes HDLCD + * + * \param[in] dev HDLCD device struct \ref hdlcd_dev_t + * + * \return Returns error code as specified in \ref hdlcd_error_t + */ +enum hdlcd_error_t hdlcd_init(struct hdlcd_dev_t* dev); + +/** + * \brief Uninitializes HDLCD + * + * \param[in] dev HDLCD device struct \ref hdlcd_dev_t + * + * \return Returns error code as specified in \ref hdlcd_error_t + */ +enum hdlcd_error_t hdlcd_uninit(struct hdlcd_dev_t* dev); + +/** + * \brief Static configuration of HDLCD + * + * \param[in] dev HDLCD device struct \ref hdlcd_dev_t + * + * \return Returns error code as specified in \ref hdlcd_error_t + */ +enum hdlcd_error_t hdlcd_static_config(struct hdlcd_dev_t* dev); + +/** +* \brief Set resolution of HDLCD from pre-configured options + * + * \param[in] dev HDLCD device struct \ref hdlcd_dev_t + * \param[in] resolution HDLCD resolution to set \ref hdlcd_resolution_t + * + * \return Returns error code as specified in \ref hdlcd_error_t + */ +enum hdlcd_error_t hdlcd_set_resolution(struct hdlcd_dev_t* dev, enum hdlcd_resolution_t resolution); + +/** +* \brief Configure the resolution of HDLCD + * + * \param[in] dev HDLCD device struct \ref hdlcd_dev_t + * \param[in] resolution_cfg HDLCD resolution config to set \ref hdlcd_resolution_cfg_t + * + * \return Returns error code as specified in \ref hdlcd_error_t + */ +enum hdlcd_error_t hdlcd_set_custom_resolution(struct hdlcd_dev_t* dev, const struct hdlcd_resolution_cfg_t* resolution_cfg); + +/** + * \brief Get configured resolution of HDLCD + * + * \param[in] dev HDLCD device struct \ref hdlcd_dev_t + * \param[out] resolution_cfg configured HDLCD resolution \ref hdlcd_resolution_cfg_t + * + * \return Returns error code as specified in \ref hdlcd_error_t + */ +enum hdlcd_error_t hdlcd_get_custom_resolution(struct hdlcd_dev_t* dev, struct hdlcd_resolution_cfg_t* resolution_cfg); + +/** + * \brief Buffer configuration of HDLCD + * + * \param[in] dev HDLCD device struct \ref hdlcd_dev_t + * \param[in] buff HDLC buffer struct \ref hdlcd_buffer_cfg_t + * + * \return Returns error code as specified in \ref hdlcd_error_t + */ +enum hdlcd_error_t hdlcd_buffer_config(struct hdlcd_dev_t* dev, struct hdlcd_buffer_cfg_t* buff); + +/** + * \brief Pixel condfiguration of HDLCD + * + * \param[in] dev HDLCD device struct \ref hdlcd_dev_t + * \param[in] pixel HDLCD pixel struct \ref hdlcd_pixel_cfg_t + * + * \return Returns error code as specified in \ref hdlcd_error_t + */ +enum hdlcd_error_t hdlcd_pixel_config(struct hdlcd_dev_t* dev, const struct hdlcd_pixel_cfg_t* pixel); + +/** + * \brief Enable HDLCD + * + * \param[in] dev HDLCD device struct \ref hdlcd_dev_t + * + * \return Returns error code as specified in \ref hdlcd_error_t + */ +enum hdlcd_error_t hdlcd_enable(struct hdlcd_dev_t* dev); + +/** + * \brief Disable HDLCD + * + * \param[in] dev HDLCD device struct \ref hdlcd_dev_t + * + * \return Returns error code as specified in \ref hdlcd_error_t + */ +enum hdlcd_error_t hdlcd_disable(struct hdlcd_dev_t* dev); + +/** + * \brief Enable HDLCD IRQs + * + * \param[in] dev HDLCD device struct \ref hdlcd_dev_t + * \param[in] mask IRQ mask + * + * \return Returns error code as specified in \ref hdlcd_error_t + */ +enum hdlcd_error_t hdlcd_enable_irq(struct hdlcd_dev_t* dev, uint32_t mask); + +/** + * \brief Disable HDLCD IRQs + * + * \param[in] dev HDLCD device struct \ref hdlcd_dev_t + * \param[in] mask IRQ mask + * + * \return Returns error code as specified in \ref hdlcd_error_t + */ +enum hdlcd_error_t hdlcd_disable_irq(struct hdlcd_dev_t* dev, uint32_t mask); + +/** + * \brief Generate HDLCD IRQs + * + * \param[in] dev HDLCD device struct \ref hdlcd_dev_t + * \param[in] mask IRQ mask + * + * \return Returns error code as specified in \ref hdlcd_error_t + */ +enum hdlcd_error_t hdlcd_generate_irq(struct hdlcd_dev_t* dev, uint32_t mask); + +/** + * \brief Clear HDLCD IRQs + * + * \param[in] dev HDLCD device struct \ref hdlcd_dev_t + * \param[in] mask IRQ mask + * + * \return Returns error code as specified in \ref hdlcd_error_t + */ +enum hdlcd_error_t hdlcd_clear_irq(struct hdlcd_dev_t* dev, uint32_t mask); + +/** + * \brief Get HDLCD IRQ state + * + * \param[in] dev HDLCD device struct \ref hdlcd_dev_t + * + * \return Returns INT_STATE register content + */ +uint32_t hdlcd_get_irq_state(struct hdlcd_dev_t* dev); + +/** + * \brief Set user output register + * + * \param[in] dev HDLCD device struct \ref hdlcd_dev_t + * \param[in] value Desired user output value + * + * \return Returns error code as specified in \ref hdlcd_error_t + */ +enum hdlcd_error_t hdlcd_set_user_output(struct hdlcd_dev_t* dev, uint32_t value); + +/** + * \brief Get user output register content + * + * \param[in] dev HDLCD device struct \ref hdlcd_dev_t + * + * \return Returns user output register content + */ +uint32_t hdlcd_get_user_output(struct hdlcd_dev_t* dev); + +/** + * \brief Set frame buffer base address + * + * \param[in] dev HDLCD device struct \ref hdlcd_dev_t + * \param[in] value Frame buffer base address + * + * \return Returns error code as specified in \ref hdlcd_error_t + */ +enum hdlcd_error_t hdlcd_set_frame_buffer_base_address(struct hdlcd_dev_t* dev, uint32_t value); + +/** + * \brief Get frame bufer base address value + * + * \param[in] dev HDLCD device struct \ref hdlcd_dev_t + * + * \return Returns frame bufer base address register content + */ +uint32_t hdlcd_get_frame_buffer_base_address(struct hdlcd_dev_t* dev); + +/** + * \brief Set frame buffer line length + * + * \param[in] dev HDLCD device struct \ref hdlcd_dev_t + * \param[in] value Frame buffer line length + * + * \return Returns error code as specified in \ref hdlcd_error_t + */ +enum hdlcd_error_t hdlcd_set_frame_buffer_line_length(struct hdlcd_dev_t* dev, uint32_t value); + +/** + * \brief Get frame bufer line length value + * + * \param[in] dev HDLCD device struct \ref hdlcd_dev_t + * + * \return Returns frame bufer line length register content + */ +uint32_t hdlcd_get_frame_buffer_line_length(struct hdlcd_dev_t* dev); + +/** + * \brief Set frame buffer line count + * + * \param[in] dev HDLCD device struct \ref hdlcd_dev_t + * \param[in] value Frame buffer line count + * + * \return Returns error code as specified in \ref hdlcd_error_t + */ +enum hdlcd_error_t hdlcd_set_frame_buffer_line_count(struct hdlcd_dev_t* dev, uint32_t value); + +/** + * \brief Get frame bufer line count value + * + * \param[in] dev HDLCD device struct \ref hdlcd_dev_t + * + * \return Returns frame bufer line count register content + */ +uint32_t hdlcd_get_frame_buffer_line_count(struct hdlcd_dev_t* dev); + +/** + * \brief Set frame buffer line pitch + * + * \param[in] dev HDLCD device struct \ref hdlcd_dev_t + * \param[in] value Frame buffer line pitch + * + * \return Returns error code as specified in \ref hdlcd_error_t + */ +enum hdlcd_error_t hdlcd_set_frame_buffer_line_pitch(struct hdlcd_dev_t* dev, uint32_t value); + +/** + * \brief Get frame bufer line pitch value + * + * \param[in] dev HDLCD device struct \ref hdlcd_dev_t + * + * \return Returns frame bufer line pitch register content + */ +uint32_t hdlcd_get_frame_buffer_line_pitch(struct hdlcd_dev_t* dev); + +/** + * \brief Set color select register + * + * \param[in] dev HDLCD device struct \ref hdlcd_dev_t + * \param[in] color Selected color \ref hdlcd_color_t + * \param[in] color_cfg Color configuration \ref hdlcd_color_cfg_t + * + * \return Returns error code as specified in \ref hdlcd_error_t + */ +enum hdlcd_error_t set_select_register(struct hdlcd_dev_t* dev, + enum hdlcd_color_t color, struct hdlcd_color_cfg_t* color_cfg); + +/** + * \brief get color select register content + * + * \param[in] dev HDLCD device struct \ref hdlcd_dev_t + * \param[in] color Selected color \ref hdlcd_color_t + * \param[out] color_cfg Color configuration \ref hdlcd_color_cfg_t + * + * \return Returns error code as specified in \ref hdlcd_error_t + */ +enum hdlcd_error_t get_select_register(struct hdlcd_dev_t* dev, + enum hdlcd_color_t color, struct hdlcd_color_cfg_t* color_cfg); + +#ifdef __cplusplus +} +#endif +#endif /* __HDLCD_DRV_H__ */ diff --git a/source/hal/source/platform/mps4/source/hdlcd_reg_map.h b/source/hal/source/platform/mps4/source/hdlcd_reg_map.h new file mode 100644 index 0000000000000000000000000000000000000000..c63809dfe64dc67fc7467c9370972854b3590de1 --- /dev/null +++ b/source/hal/source/platform/mps4/source/hdlcd_reg_map.h @@ -0,0 +1,202 @@ +/* + * SPDX-FileCopyrightText: Copyright 2023, 2025 Arm Limited and/or + * its affiliates + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +/** + * \file hdlcd_reg_map.h + * + * \brief Register map for HDLCD + */ + +#ifndef __HDLCD_REG_MAP_H__ +#define __HDLCD_REG_MAP_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief HDLCD Register map structure + */ +struct hdlcd_reg_map_t { + volatile const uint32_t version; /*!< Offset: 0x000 (R/ ) Version Register */ + volatile const uint32_t reserved1[3]; /*!< Offset: 0x004-0x00C Reserved */ + volatile uint32_t raw_int_stat; /*!< Offset: 0x010 (R/W) Raw Interrupt Status Register */ + volatile uint32_t int_clr; /*!< Offset: 0x014 ( /W) Interrupt Clear Register */ + volatile uint32_t int_mask; /*!< Offset: 0x018 (R/W) Interrupt Clear Register */ + volatile uint32_t int_stat; /*!< Offset: 0x01C (R/W) Interrupt Status Register */ + volatile uint32_t user_output; /*!< Offset: 0x020 (R/W) User Output Register */ + volatile const uint32_t reserved2[55]; /*!< Offset: 0x024-0x0FC Reserved */ + volatile uint32_t fb_base_addr; /*!< Offset: 0x100 (R/W) Frame Buffer Base Address Register */ + volatile uint32_t fb_line_length; /*!< Offset: 0x104 (R/W) Frame Buffer Line Length Register */ + volatile uint32_t fb_line_count; /*!< Offset: 0x108 (R/W) Frame Buffer Line Count Register */ + volatile uint32_t fb_line_pitch; /*!< Offset: 0x10C (R/W) Frame Buffer Line Pitch Register */ + volatile uint32_t bus_options; /*!< Offset: 0x110 (R/W) Bus Options Register */ + volatile const uint32_t reserved3[59]; /*!< Offset: 0x114-0x1FC Reserved */ + volatile uint32_t vsync_width; /*!< Offset: 0x200 (R/W) Vertical Synch Register */ + volatile uint32_t vsync_back_porch_width; /*!< Offset: 0x204 (R/W) Vertical Back Porch Width Register */ + volatile uint32_t vsync_data_width; /*!< Offset: 0x208 (R/W) Vertical Data Width Register */ + volatile uint32_t vsync_front_porch_width; /*!< Offset: 0x20C (R/W) Vertical Front Porch Width Register */ + volatile uint32_t hsync_width; /*!< Offset: 0x210 (R/W) Horizontal Synch Register */ + volatile uint32_t hsync_back_porch_width; /*!< Offset: 0x214 (R/W) Horizontal Back Porch Width Register */ + volatile uint32_t hsync_data_width; /*!< Offset: 0x218 (R/W) Horizontal Data Width Register */ + volatile uint32_t hsync_front_porch_width; /*!< Offset: 0x21C (R/W) Horizontal Front Porch Width Register */ + volatile uint32_t polarities; /*!< Offset: 0x220 (R/W) Polarities Register */ + volatile const uint32_t reserved4[3]; /*!< Offset: 0x224-0x22C Reserved */ + volatile uint32_t command; /*!< Offset: 0x230 (R/W) Command Register */ + volatile const uint32_t reserved5[3]; /*!< Offset: 0x234-0x23C Reserved */ + volatile uint32_t pixel_format; /*!< Offset: 0x240 (R/W) Pixel Format Register */ + volatile uint32_t red_select; /*!< Offset: 0x244 (R/W) Red Select Register */ + volatile uint32_t green_select; /*!< Offset: 0x248 (R/W) Green Select Register */ + volatile uint32_t blue_select; /*!< Offset: 0x24C (R/W) Blue Select Register */ +}; + +/* Version Register Definitions */ +#define VERSION_PRODUCT_ID_Pos 16U /*!< VERSION: PRODUCT ID Position */ +#define VERSION_PRODUCT_ID_Msk (0xFFFFUL << VERSION_PRODUCT_ID_Pos) /*!< VERSION: PRODUCT ID Mask */ + +#define VERSION_VERSION_MAJOR_Pos 8U /*!< VERSION: VERSION MAJOR Position */ +#define VERSION_VERSION_MAJOR_Msk (0xFfUL << VERSION_VERSION_MAJOR_Pos) /*!< VERSION: VERSION MAJOR Mask */ + +#define VERSION_VERSION_MINOR_Pos 0U /*!< VERSION: VERSION MINOR Position */ +#define VERSION_VERSION_MINOR_Msk (0xFFUL /*<< VERSION_VERSION_MINOR_Pos*/) /*!< VERSION: VERSION MINOR Mask */ + +/* Interrupt Register Definitions */ +#define INT_UNDERRUN_Pos 3U /*!< INT: UNDERRUN Position */ +#define INT_UNDERRUN_Msk (0x1UL << INT_UNDERRUN_Pos) /*!< INT: UNDERRUN Mask */ + +#define INT_VSYNC_Pos 2U /*!< INT: VSYNC Position */ +#define INT_VSYNC_Msk (0x1UL << INT_VSYNC_Pos) /*!< INT: VSYNC Mask */ + +#define INT_BUS_ERROR_Pos 1U /*!< INT: BUS ERROR Position */ +#define INT_BUS_ERROR_Msk (0x1UL << INT_BUS_ERROR_Pos) /*!< INT: BUS ERROR Mask */ + +#define INT_DMA_END_Pos 0U /*!< INT: DMA END Position */ +#define INT_DMA_END_Msk (0x1UL /*<< INT_DMA_END_Pos*/) /*!< INT: DMA END Mask */ + +/* Frame Buffer Base Address Register Definitions */ +#define FB_BASE_ADDR_FB_BASE_ADDR_Pos 3U /*!< FB BASE ADDR: FB BASE ADDR Position */ +#define FB_BASE_ADDR_FB_BASE_ADDR_Msk (0x1FFFFFFFUL << FB_BASE_ADDR_FB_BASE_ADDR_Pos) /*!< FB BASE ADDR: FB BASE ADDR Mask */ + +/* Frame Buffer Line Length Register Definitions */ +#define FB_LINE_LENGTH_FB_LINE_LENGTH_Pos 3U /*!< FB LINE LENGTH: FB LINE LENGTH Position */ +#define FB_LINE_LENGTH_FB_LINE_LENGTH_Msk (0x1FFFFFFFUL << FB_LINE_LENGTH_FB_LINE_LENGTH_Pos) /*!< FB LINE LENGTH: FB LINE LENGTH Mask */ + +/* Frame Buffer Line Count Register Definitions */ +#define FB_LINE_PITCH_FB_LINE_PITCH_Pos 3U /*!< FB LINE PITCH: FB LINE PITCH Position */ +#define FB_LINE_PITCH_FB_LINE_PITCH_Msk (0x1FFFFFFFUL << FB_LINE_PITCH_FB_LINE_PITCH_Pos) /*!< FB LINE PITCH: FB LINE PITCH Mask */ + +/* Frame Buffer Line Count Register Definitions */ +#define FB_LINE_PITCH_FB_LINE_PITCH_Pos 3U /*!< FB LINE PITCH: FB LINE PITCH Position */ +#define FB_LINE_PITCH_FB_LINE_PITCH_Msk (0x1FFFFFFFUL << FB_LINE_PITCH_FB_LINE_PITCH_Pos) /*!< FB LINE PITCH: FB LINE PITCH Mask */ + +/* Bus Options Register Definitions */ +#define BUS_OPTIONS_MAX_OUTSTANDING_Pos 8U /*!< BUS OPTIONS: MAX OUTSTANDING Position */ +#define BUS_OPTIONS_MAX_OUTSTANDING_Msk (0xFUL << BUS_OPTIONS_MAX_OUTSTANDING_Pos) /*!< BUS OPTIONS: MAX OUTSTANDING Mask */ + +#define BUS_OPTIONS_BURST_16_Pos 4U /*!< BUS OPTIONS: BURST 16 Position */ +#define BUS_OPTIONS_BURST_16_Msk (0x1UL << BUS_OPTIONS_BURST_16_Pos) /*!< BUS OPTIONS: BURST 16 Mask */ + +#define BUS_OPTIONS_BURST_8_Pos 3U /*!< BUS OPTIONS: BURST 8 Position */ +#define BUS_OPTIONS_BURST_8_Msk (0x1UL << BUS_OPTIONS_BURST_8_Pos) /*!< BUS OPTIONS: BURST 8 Mask */ + +#define BUS_OPTIONS_BURST_4_Pos 2U /*!< BUS OPTIONS: BURST 4 Position */ +#define BUS_OPTIONS_BURST_4_Msk (0x1UL << BUS_OPTIONS_BURST_4_Pos) /*!< BUS OPTIONS: BURST 4 Mask */ + +#define BUS_OPTIONS_BURST_2_Pos 1U /*!< BUS OPTIONS: BURST 2 Position */ +#define BUS_OPTIONS_BURST_2_Msk (0x1UL << BUS_OPTIONS_BURST_2_Pos) /*!< BUS OPTIONS: BURST 2 Mask */ + +#define BUS_OPTIONS_BURST_1_Pos 0U /*!< BUS OPTIONS: BURST 1 Position */ +#define BUS_OPTIONS_BURST_1_Msk (0x1UL /*<< BUS_OPTIONS_BURST_1_Pos*/) /*!< BUS OPTIONS: BURST 1 Mask */ + +/* Vertical Sync Width Register Definitions */ +#define VSYNC_WIDTH_V_SYNC_Pos 0U /*!< VSYNC WIDTH: V SYNC Position */ +#define VSYNC_WIDTH_V_SYNC_Msk (0xFFFUL << /*VSYNC_WIDTH_V_SYNC_Pos*/) /*!< VSYNC WIDTH: V SYNC Mask */ + +/* Vertical Back Porch Register Definitions */ +#define VSYNC_BACK_PORCH_WIDTH_V_BACK_PORCH_Pos 0U /*!< VSYNC BACK PORCH WIDTH: V BACK PORCH Position */ +#define VSYNC_BACK_PORCH_WIDTH_V_BACK_PORCH_Msk (0xFFFUL << /*VSYNC_BACK_PORCH_WIDTH_V_BACK_PORCH_Pos*/) /*!< VSYNC BACK PORCH WIDTH: V BACK PORCH Mask */ + +/* Vertical Data Width Register Definitions */ +#define VSYNC_DATA_WIDTH_V_DATA_Pos 0U /*!< VSYNC DATA WIDTH: V DATA Position */ +#define VSYNC_DATA_WIDTH_V_DATA_Msk (0xFFFUL << /*VSYNC_DATA_WIDTH_V_DATA_Pos*/) /*!< VSYNC DATA WIDTH: V DATA Mask */ + +/* Vertical Front Porch Register Definitions */ +#define VSYNC_FRONT_PORCH_WIDTH_V_FRONT_PORCH_Pos 0U /*!< VSYNC FRONT PORCH WIDTH: V FRONT PORCH Position */ +#define VSYNC_FRONT_PORCH_WIDTH_V_FRONT_PORCH_Msk (0xFFFUL << /*VSYNC_FRONT_PORCH_WIDTH_V_FRONT_PORCH_Pos*/) /*!< VSYNC FRONT PORCH WIDTH: V FRONT PORCH Mask */ + +/* Horizontal Sync Width Register Definitions */ +#define HSYNC_WIDTH_H_SYNC_Pos 0U /*!< HSYNC WIDTH: H SYNC Position */ +#define HSYNC_WIDTH_H_SYNC_Msk (0xFFFUL << /*HSYNC_WIDTH_H_SYNC_Pos*/) /*!< HSYNC WIDTH: H SYNC Mask */ + +/* Horizontal Back Porch Register Definitions */ +#define HSYNC_BACK_PORCH_WIDTH_H_BACK_PORCH_Pos 0U /*!< HSYNC BACK PORCH WIDTH: H BACK PORCH Position */ +#define HSYNC_BACK_PORCH_WIDTH_H_BACK_PORCH_Msk (0xFFFUL << /*HSYNC_BACK_PORCH_WIDTH_H_BACK_PORCH_Pos*/) /*!< HSYNC BACK PORCH WIDTH: H BACK PORCH Mask */ + +/* Horizontal Data Width Register Definitions */ +#define HSYNC_DATA_WIDTH_H_DATA_Pos 0U /*!< HSYNC DATA WIDTH: H DATA Position */ +#define HSYNC_DATA_WIDTH_H_DATA_Msk (0xFFFUL << /*HSYNC_DATA_WIDTH_H_DATA_Pos*/) /*!< HSYNC DATA WIDTH: H DATA Mask */ + +/* Horizontal Front Porch Register Definitions */ +#define HSYNC_FRONT_PORCH_WIDTH_H_FRONT_PORCH_Pos 0U /*!< HSYNC FRONT PORCH WIDTH: H FRONT PORCH Position */ +#define HSYNC_FRONT_PORCH_WIDTH_H_FRONT_PORCH_Msk (0xFFFUL << /*HSYNC_FRONT_PORCH_WIDTH_H_FRONT_PORCH_Pos*/) /*!< HSYNC FRONT PORCH WIDTH: H FRONT PORCH Mask */ + +/* Polarities Register Definitions */ +#define POLARITIES_PXLCLK_POLARITY_Pos 4U /*!< POLARITIES: PXLCLK POLARITY Position */ +#define POLARITIES_PXLCLK_POLARITY_Msk (0x1UL << POLARITIES_PXLCLK_POLARITY_Pos) /*!< POLARITIES: PXLCLK POLARITY Mask */ + +#define POLARITIES_DATA_POLARITY_Pos 3U /*!< POLARITIES: DATA POLARITY Position */ +#define POLARITIES_DATA_POLARITY_Msk (0x1UL << POLARITIES_DATA_POLARITY_Pos) /*!< POLARITIES: DATA POLARITY Mask */ + +#define POLARITIES_DATAEN_POLARITY_Pos 2U /*!< POLARITIES: DATAEN POLARITY Position */ +#define POLARITIES_DATAEN_POLARITY_Msk (0x1UL << POLARITIES_DATAEN_POLARITY_Pos) /*!< POLARITIES: DATAEN POLARITY Mask */ + +#define POLARITIES_HSYNC_POLARITY_Pos 1U /*!< POLARITIES: HSYNC POLARITY Position */ +#define POLARITIES_HSYNC_POLARITY_Msk (0x1UL << POLARITIES_HSYNC_POLARITY_Pos) /*!< POLARITIES: HSYNC POLARITY Mask */ + +#define POLARITIES_VSYNC_POLARITY_Pos 0U /*!< POLARITIES: VSYNC POLARITY Position */ +#define POLARITIES_VSYNC_POLARITY_Msk (0x1UL /*<< POLARITIES_VSYNC_POLARITY_Pos*/) /*!< POLARITIES: VSYNC POLARITY Mask */ + +/* Command Register Definitions */ +#define COMMAND_ENABLE_Pos 0U /*!< COMMAND: ENABLE Position */ +#define COMMAND_ENABLE_Msk (0x1UL /*<< COMMAND_ENABLE_Pos*/) /*!< COMMAND: ENABLE Mask */ + +/* Pixel Format Register Definitions */ +#define PIXEL_FORMAT_BIG_ENDIAN_Pos 31U /*!< PIXEL FORMAT: BIG ENDIAN Position */ +#define PIXEL_FORMAT_BIG_ENDIAN_Msk (0x1UL << PIXEL_FORMAT_BIG_ENDIAN_Pos) /*!< PIXEL FORMAT: BIG ENDIAN Mask */ + +#define PIXEL_FORMAT_BYTES_PER_PIXEL_Pos 3U /*!< PIXEL FORMAT: BYTES PER PIXEL Position */ +#define PIXEL_FORMAT_BYTES_PER_PIXEL_Msk (0x3UL << PIXEL_FORMAT_BYTES_PER_PIXEL_Pos) /*!< PIXEL FORMAT: BYTES PER PIXEL Mask */ + +/* Red Select Register Definitions */ +#define COLOR_SELECT_DEFAULT_Pos 16U /*!< COLOR SELECT: DEFAULT Position */ +#define COLOR_SELECT_DEFAULT_Msk (0xFFUL << COLOR_SELECT_DEFAULT_Pos) /*!< COLOR SELECT: DEFAULT Mask */ + +#define COLOR_SELECT_SIZE_Pos 8U /*!< COLOR SELECT: SIZE Position */ +#define COLOR_SELECT_SIZE_Msk (0xFUL << COLOR_SELECT_SIZE_Pos) /*!< COLOR SELECT: SIZE Mask */ + +#define COLOR_SELECT_OFFSET_Pos 0U /*!< COLOR SELECT: OFFSET Position */ +#define COLOR_SELECT_OFFSET_Msk (0xFUL /*<< COLOR_SELECT_OFFSET_Pos*/) /*!< COLOR SELECT: OFFSET Mask */ + +#ifdef __cplusplus +} +#endif + +#endif /* __HDLCD_REG_MAP_H__ */ diff --git a/source/hal/source/platform/mps4/source/platform_drivers.c b/source/hal/source/platform/mps4/source/platform_drivers.c index 1924a385a35c0b41872ffb5d2f083c0488d1c54b..82447318a4ee557fa62bdda3ff98174445f2a000 100644 --- a/source/hal/source/platform/mps4/source/platform_drivers.c +++ b/source/hal/source/platform/mps4/source/platform_drivers.c @@ -20,6 +20,10 @@ #include "log_macros.h" /* Logging functions */ #include "smm_mps4.h" /* Memory map for MPS4. */ +#include "hdlcd_drv.h" /* HDLCD driver */ +#include "peripheral_irqs.h" /* Interrupt numbers */ + +#include #if defined(ARM_NPU) #include "ethosu_npu_init.h" @@ -42,6 +46,12 @@ */ static int verify_platform(void); +/** + * @brief Initialises the HDLCD for MPS4 platform + * @return 0 if successful, error code otherwise. + */ +static int platform_hdlcd_init(void); + /** Platform name */ static const char* s_platform_name = DESIGN_NAME; @@ -90,6 +100,11 @@ int platform_init(void) #endif /* ARM_NPU */ + /* Initialise HDLCD device. */ + if (0 != (state = platform_hdlcd_init())) { + return state; + } + /* Print target design info */ info("Target system design: %s\n", s_platform_name); return 0; @@ -183,3 +198,116 @@ static int verify_platform(void) printf_err("CPU mismatch!\n"); return 1; } + +static const struct hdlcd_dev_cfg_t HDLCD_DEV_CFG_S = { + .base = HDLCD_BASE_S, + .polarities = (POLARITIES_DATA_POLARITY_Msk | + POLARITIES_DATAEN_POLARITY_Msk | + POLARITIES_HSYNC_POLARITY_Pos), + .bus_options = ((4 << BUS_OPTIONS_MAX_OUTSTANDING_Pos) | + BUS_OPTIONS_BURST_16_Msk)}; + +static struct hdlcd_dev_data_t HDLCD_DEV_DATA_S = {.is_initialized = false}; + +static struct hdlcd_dev_t HDLCD_DEV_S = { + &(HDLCD_DEV_CFG_S), + &(HDLCD_DEV_DATA_S)}; + +static struct hdlcd_dev_t* platform_get_hdlcd_dev() +{ + return &HDLCD_DEV_S; +} + +static void HDLCD_Handler(void) +{ + /* Clear IRQ */ + hdlcd_clear_irq(platform_get_hdlcd_dev(), INT_DMA_END_Msk); + __NVIC_ClearPendingIRQ(HDLCD_IRQn); +} + +static void enable_hdlcd_irq(void) +{ + NVIC_ClearPendingIRQ(HDLCD_IRQn); + NVIC_SetVector(HDLCD_IRQn, (uint32_t)HDLCD_Handler); + NVIC_EnableIRQ(HDLCD_IRQn); + hdlcd_enable_irq(platform_get_hdlcd_dev(), INT_DMA_END_Msk); +} + +static int platform_hdlcd_init(void) +{ + /* Initialise HDLCD */ + struct hdlcd_dev_t* hdlcd_dev = platform_get_hdlcd_dev(); + enum hdlcd_error_t hdlcd_err = hdlcd_init(hdlcd_dev); + + if (hdlcd_err != HDLCD_ERR_NONE) { + printf_err("HDLCD initialization failed.\n"); + return hdlcd_err; + } + debug("HDLCD device init\n"); + + hdlcd_err = hdlcd_static_config(hdlcd_dev); + if (hdlcd_err != HDLCD_ERR_NONE) { + printf_err("Failed to set HDLCD resolution.\n"); + return hdlcd_err; + } + +#if (HDLCD_RES_HEIGHT == 240) && (HDLCD_RES_WIDTH == 320) + const enum hdlcd_resolution_t res = HDLCD_RES_320x240; + hdlcd_err = hdlcd_set_resolution(hdlcd_dev, res); +#elif (HDLCD_RES_HEIGHT == 480) && (HDLCD_RES_WIDTH == 640) + const enum hdlcd_resolution_t res = HDLCD_RES_VGA; + hdlcd_err = hdlcd_set_resolution(hdlcd_dev, res); +#else /* resolutions */ + #error "Resolution not supported!" +#endif /* resolutions */ + + if (hdlcd_err != HDLCD_ERR_NONE) { + printf_err("Failed to set HDLCD resolution.\n"); + return hdlcd_err; + } + info("HDLCD resolution id: %d\n", res); + enable_hdlcd_irq(); + + struct hdlcd_buffer_cfg_t cfg = { + .base_address = HDLCD_FRAME_BUFFER_BASE_ADDRESS, + .line_length = HDLCD_RES_WIDTH * HDLCD_BYTES_PER_PIXEL, + .line_count = HDLCD_RES_HEIGHT - 1, + .line_pitch = HDLCD_RES_WIDTH * HDLCD_BYTES_PER_PIXEL, + .pixel_format = ((HDLCD_BYTES_PER_PIXEL - 1) << PIXEL_FORMAT_BYTES_PER_PIXEL_Pos) + }; + + hdlcd_err = hdlcd_buffer_config(hdlcd_dev, &cfg); + if (hdlcd_err != HDLCD_ERR_NONE) { + printf_err("Failed to set HDLCD config.\n"); + return hdlcd_err; + } + trace("HDLCD base address set\n"); + + const struct hdlcd_pixel_cfg_t hdlcd_pixel_cfg_rgb888 = { + .red.default_color = 0x00, + .red.bit_size = 0x8, + .red.offset = 0x10, + .green.default_color = 0x00, + .green.bit_size = 0x8, + .green.offset = 0x8, + .blue.default_color = 0x00, + .blue.bit_size = 0x8, + .blue.offset = 0x0}; + + hdlcd_err = hdlcd_pixel_config(hdlcd_dev, &hdlcd_pixel_cfg_rgb888); + if (hdlcd_err != HDLCD_ERR_NONE) { + printf_err("Failed to set HDLCD pixel config.\n"); + return hdlcd_err; + } + + memset((uint8_t*)HDLCD_FRAME_BUFFER_BASE_ADDRESS, 0, cfg.line_pitch * cfg.line_count + 1); + + hdlcd_enable(hdlcd_dev); + hdlcd_err = hdlcd_enable(hdlcd_dev); + if (hdlcd_err != HDLCD_ERR_NONE) { + printf_err("Failed to enable HDLCD.\n"); + } + + debug("HDLCD device initialised.\n"); + return 0; +}