123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243 |
- /*
- * Copyright 2019-2021, 2023 NXP
- * All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
- #include "fsl_fbdev.h"
- /*******************************************************************************
- * Definitions
- ******************************************************************************/
- /*******************************************************************************
- * Prototypes
- ******************************************************************************/
- static void FBDEV_BufferSwitchOffCallback(void *param, void *switchOffBuffer);
- /*******************************************************************************
- * Variables
- ******************************************************************************/
- /*******************************************************************************
- * Code
- ******************************************************************************/
- status_t FBDEV_Open(fbdev_t *fbdev, const dc_fb_t *dc, uint8_t layer)
- {
- status_t status;
- assert(NULL != fbdev);
- (void)memset(fbdev, 0, sizeof(fbdev_t));
- fbdev->dc = dc;
- (void)VIDEO_STACK_Init(&fbdev->fbManager, fbdev->buffers, FBDEV_MAX_FRAME_BUFFER);
- /* Initialize the display controller. */
- status = dc->ops->init(dc);
- if (kStatus_Success != status)
- {
- return status;
- }
- fbdev->layer = layer;
- /* Initializes the dc_fb_info_t to the display controller default setting. */
- status = dc->ops->getLayerDefaultConfig(dc, layer, &fbdev->fbInfo.bufInfo);
- if (kStatus_Success != status)
- {
- return status;
- }
- fbdev->semaFramePending = rt_sem_create("fsfp", 0, RT_IPC_FLAG_PRIO);
- if (NULL == fbdev->semaFramePending)
- {
- return kStatus_Fail;
- }
- /* No frame pending. */
- (void)rt_sem_release(fbdev->semaFramePending);
- dc->ops->setCallback(dc, layer, FBDEV_BufferSwitchOffCallback, (void *)fbdev);
- return kStatus_Success;
- }
- status_t FBDEV_Close(fbdev_t *fbdev)
- {
- const dc_fb_t *dc = fbdev->dc;
- (void)dc->ops->deinit(dc);
- if (NULL != fbdev->semaFbManager)
- {
- rt_sem_delete(fbdev->semaFbManager);
- fbdev->semaFbManager = NULL;
- }
- if (NULL != fbdev->semaFramePending)
- {
- rt_sem_delete(fbdev->semaFramePending);
- fbdev->semaFramePending = NULL;
- }
- return kStatus_Success;
- }
- status_t FBDEV_Enable(fbdev_t *fbdev)
- {
- status_t status = kStatus_Success;
- const dc_fb_t *dc = fbdev->dc;
- if (!fbdev->enabled)
- {
- /* Wait for frame buffer sent to display controller video memory. */
- if ((dc->ops->getProperty(dc) & (uint32_t)kDC_FB_ReserveFrameBuffer) == 0U)
- {
- if (RT_EOK != rt_sem_take(fbdev->semaFramePending, RT_WAITING_FOREVER))
- {
- status = kStatus_Fail;
- }
- }
- if (kStatus_Success == status)
- {
- /* No frame is pending. */
- (void)rt_sem_release(fbdev->semaFramePending);
- status = dc->ops->enableLayer(dc, fbdev->layer);
- if (kStatus_Success == status)
- {
- fbdev->enabled = true;
- }
- }
- }
- return status;
- }
- status_t FBDEV_Disable(fbdev_t *fbdev)
- {
- status_t status = kStatus_Success;
- const dc_fb_t *dc = fbdev->dc;
- if (!fbdev->enabled)
- {
- /* Wait until no frame pending. */
- if (RT_EOK != rt_sem_take(fbdev->semaFramePending, RT_WAITING_FOREVER))
- {
- status = kStatus_Fail;
- }
- if (kStatus_Success == status)
- {
- (void)rt_sem_release(fbdev->semaFramePending);
- (void)dc->ops->disableLayer(dc, fbdev->layer);
- fbdev->enabled = false;
- }
- }
- return status;
- }
- void FBDEV_GetFrameBufferInfo(fbdev_t *fbdev, fbdev_fb_info_t *info)
- {
- *info = fbdev->fbInfo;
- }
- status_t FBDEV_SetFrameBufferInfo(fbdev_t *fbdev, fbdev_fb_info_t *info)
- {
- status_t status;
- const dc_fb_t *dc = fbdev->dc;
- /* Should only change the frame buffer setting before enabling the fbdev. */
- if (fbdev->enabled)
- {
- return kStatus_Fail;
- }
- fbdev->fbInfo = *info;
- status = dc->ops->setLayerConfig(dc, fbdev->layer, &fbdev->fbInfo.bufInfo);
- if (kStatus_Success != status)
- {
- return status;
- }
- fbdev->semaFbManager = rt_sem_create("fsfm", 0, RT_IPC_FLAG_PRIO);
- if (NULL == fbdev->semaFbManager)
- {
- return kStatus_Fail;
- }
- for (uint8_t i = 0; i < info->bufferCount; i++)
- {
- /* Don't need to disable interrupt for the FB stack operation, because
- the fbdev is not working, this is the only function to access FB stack.
- */
- (void)VIDEO_STACK_Push(&fbdev->fbManager, info->buffers[i]);
- (void)rt_sem_release(fbdev->semaFbManager);
- }
- return kStatus_Success;
- }
- void *FBDEV_GetFrameBuffer(fbdev_t *fbdev, uint32_t flags)
- {
- rt_uint32_t tick;
- void *fb;
- tick = ((flags & (uint32_t)kFBDEV_NoWait) != 0U) ? 0U : RT_WAITING_FOREVER;
- if (RT_EOK == rt_sem_take(fbdev->semaFbManager, tick))
- {
- /* Disable interrupt to protect the FB stack. */
- rt_enter_critical();
- (void)VIDEO_STACK_Pop(&fbdev->fbManager, &fb);
- rt_exit_critical();
- }
- else
- {
- fb = NULL;
- }
- return fb;
- }
- status_t FBDEV_SetFrameBuffer(fbdev_t *fbdev, void *frameBuffer, uint32_t flags)
- {
- rt_uint32_t tick;
- const dc_fb_t *dc = fbdev->dc;
- tick = ((flags & (uint32_t)kFBDEV_NoWait) != 0U) ? 0U : RT_WAITING_FOREVER;
- if (RT_EOK == rt_sem_take(fbdev->semaFramePending, tick))
- {
- return dc->ops->setFrameBuffer(dc, fbdev->layer, frameBuffer);
- }
- else
- {
- return kStatus_Fail;
- }
- }
- static void FBDEV_BufferSwitchOffCallback(void *param, void *switchOffBuffer)
- {
- fbdev_t *fbdev = (fbdev_t *)param;
- /* This function should only be called in ISR, so don't need to protect the FB stack */
- (void)VIDEO_STACK_Push(&fbdev->fbManager, switchOffBuffer);
- rt_sem_release(fbdev->semaFbManager);
- rt_sem_release(fbdev->semaFramePending);
- }
|