Hi TI engineer,
How to bing the display frame buffer with the dss pipeline?
This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
Hi TI engineer,
How to bing the display frame buffer with the dss pipeline?
Hi xie jc,
From the HW perspective, it is possible, but as discussed on the other ticket, it is not supported in the SDK.
Regards,
Brijesh
Hi,Brijesh
Thanks for replying.
The previous way was to control DSS through A72, but I didn't see the code in the latest Linux SDK.
But now it is controlled with R5 cores, and the current SDK does not support it?
If the SDK not support now,we want to try,need you help.
Hi xie jc,
But SDK does not support this feature, so wondering how i can help here.
Regards,
Brijesh
Hi Brijesh,
I want to a test.
1.Read two different pic and write to the dss pipeline DMA buff
2.After Overlay Manager blending, routing blended image to the writeback pipe
How to write display data to the dss pipeline DMA buff?
Hi xie jc,
But this is not supported/ validated in the SDK, so i really don't think this can be done..
Regards,
Brijesh
Hi xie jc,
This isn't related to HW design. There is no SW component, which supports currently overlaying of images.. You would probably have to write own kernel on DSP to do this overlaying..
Regards,
Brijesh
ok, lets work together to enable this path. I will point you to the changes to enable this path, would you please try it out?
There could be multiple iterations before we can get it working..
Regards,
Brijesh
ok, lets work together to enable this path. I will point you to the changes to enable this path, would you please try it out?
There could be multiple iterations before we can get it working..
Regards,
Brijesh
Hi, Brijesh:
I do below modifications:
and try to set pipe num to 2 before init M2M display node.
file: dss_m2m.h: dss_m2m.h
file: dss_soc.h: dss_soc.h
file: m2m_target.c:
/* * * Copyright (c) 2021 Texas Instruments Incorporated * * All rights reserved not granted herein. * * Limited License. * * Texas Instruments Incorporated grants a world-wide, royalty-free, non-exclusive * license under copyrights and patents it now or hereafter owns or controls to make, * have made, use, import, offer to sell and sell ("Utilize") this software subject to the * terms herein. With respect to the foregoing patent license, such license is granted * solely to the extent that any such patent is necessary to Utilize the software alone. * The patent license shall not apply to any combinations which include this software, * other than combinations with devices manufactured by or for TI ("TI Devices"). * No hardware patent is licensed hereunder. * * Redistributions must preserve existing copyright notices and reproduce this license * (including the above copyright notice and the disclaimer and (if applicable) source * code license limitations below) in the documentation and/or other materials provided * with the distribution * * Redistribution and use in binary form, without modification, are permitted provided * that the following conditions are met: * * * No reverse engineering, decompilation, or disassembly of this software is * permitted with respect to any software provided in binary form. * * * any redistribution and use are licensed by TI for use only with TI Devices. * * * Nothing shall obligate TI to provide you with source code for the software * licensed and provided to you in object code. * * If software source code is provided to you, modification and redistribution of the * source code are permitted provided that the following conditions are met: * * * any redistribution and use of the source code, including any resulting derivative * works, are licensed by TI for use only with TI Devices. * * * any redistribution and use of any object code compiled from the source code * and any resulting derivative works, are licensed by TI for use only with TI Devices. * * Neither the name of Texas Instruments Incorporated nor the names of its suppliers * * may be used to endorse or promote products derived from this software without * specific prior written permission. * * DISCLAIMER. * * THIS SOFTWARE IS PROVIDED BY TI AND TI'S LICENSORS "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 TI AND TI'S LICENSORS 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. * */ #include <stdio.h> #include "TI/tivx.h" #include "VX/vx.h" #include "TI/tivx_event.h" #include "tivx_hwa_kernels.h" #include "tivx_kernel_display_m2m.h" #include "TI/tivx_target_kernel.h" #include "tivx_kernels_target_utils.h" #include "tivx_hwa_display_m2m_priv.h" #include <TI/tivx_queue.h> #include <ti/drv/fvid2/fvid2.h> #include <ti/drv/dss/dss.h> #include <tivx_obj_desc_priv.h> #include <vx_reference.h> #define DISPLAY_MAX_VALID_PLANES 2U #define DISPLAY_M2M_MAX_HANDLES (10) typedef struct { /*! IDs=> 0: Write-back pipe-line1 */ uint32_t instId; /*! Number of pipe-lines used, should be set to '1' as blending is not supported currently */ uint32_t numPipe; /*! IDs=> 0:VID1, 1:VIDL1, 2:VID2 and 3:VIDL2 */ uint32_t pipeId[TIVX_DISPLAY_M2M_MAX_PIPE]; /*! IDs=> 0:Overlay1, 1:Overlay2, 2:Overlay3 and 3:Overlay4 */ uint32_t overlayId; /*! FVID2 display driver handle */ Fvid2_Handle drvHandle; /*! WB pipe create parameters */ Dss_WbCreateParams createParams; /*! WB pipe create status */ Dss_WbCreateStatus createStatus; /*! Callback parameters */ Fvid2_CbParams cbParams; /*! WB pipe status */ Dss_WbStatus wbStatus; /*! WB pipe configuration */ Dss_WbPipeCfgParams wbCfg; /*! WB pipe DMA configuration */ CSL_DssWbPipeDmaCfg wbDmaCfg; /*! WB pipe MFlag configuration */ Dss_WbPipeMflagParams wbMflagCfg; /*! WB pipe CSC configuration */ CSL_DssCscCoeff wbCscCfg; /*! Display pipe configuration */ Dss_PipeCfgParams pipeCfg[TIVX_DISPLAY_M2M_MAX_PIPE]; /*! Display pipe MFlag configuration */ Dss_PipeMflagParams mFlagCfg[TIVX_DISPLAY_M2M_MAX_PIPE]; /*! Display pipe CSC configuration */ Dss_PipeCscParams cscCfg[TIVX_DISPLAY_M2M_MAX_PIPE]; /*! Display Overlay configuration */ Dss_DctrlOverlayParams ovrCfg; /*! Display Layer configuration */ Dss_DctrlOverlayLayerParams layerCfg; /*! Display Global configuration */ Dss_DctrlGlobalDssParams globalParams; /*! Mutex used for waiting for process completion */ tivx_event waitForProcessCmpl; /*! Display M2M Driver Input Frame List, used for providing * an array of input frames */ Fvid2_FrameList inFrmList; /*! Display M2M Driver Output Frame List, used for providing * an array of output frames */ Fvid2_FrameList outFrmList; /*! Display M2M Driver Input Frames */ Fvid2_Frame inFrm[TIVX_DISPLAY_M2M_MAX_PIPE]; /*! Display M2M Driver Output Frames */ Fvid2_Frame outFrm[1U]; } tivxDisplayM2MDrvObj; typedef struct { /*! IDs=> 0: Object free, 1: allocated */ uint32_t isAlloc; /*! Display M2M driver object */ tivxDisplayM2MDrvObj drvObj; /*! Display M2M Node create parameters provided by application */ tivx_display_m2m_params_t createParams; } tivxDisplayM2MParams; typedef struct { tivx_mutex lock; tivxDisplayM2MParams m2mObj[DISPLAY_M2M_MAX_HANDLES]; } tivxDisplayM2MInstObj; static tivx_target_kernel vx_display_m2m_target_kernel1 = NULL; static tivx_target_kernel vx_display_m2m_target_kernel2 = NULL; static tivx_target_kernel vx_display_m2m_target_kernel3 = NULL; static tivx_target_kernel vx_display_m2m_target_kernel4 = NULL; tivxDisplayM2MInstObj gTivxDispM2mInstObj; static vx_status VX_CALLBACK tivxDisplayM2MProcess( tivx_target_kernel_instance kernel, tivx_obj_desc_t *obj_desc[], uint16_t num_params, void *priv_arg); static vx_status VX_CALLBACK tivxDisplayM2MCreate( tivx_target_kernel_instance kernel, tivx_obj_desc_t *obj_desc[], uint16_t num_params, void *priv_arg); static vx_status VX_CALLBACK tivxDisplayM2MDelete( tivx_target_kernel_instance kernel, tivx_obj_desc_t *obj_desc[], uint16_t num_params, void *priv_arg); static vx_status VX_CALLBACK tivxDisplayM2MControl( tivx_target_kernel_instance kernel, uint32_t node_cmd_id, tivx_obj_desc_t *obj_desc[], uint16_t num_params, void *priv_arg); static vx_status tivxDisplayM2MSetCreateParams( tivxDisplayM2MParams *prms, const tivx_obj_desc_user_data_object_t *obj_desc, const tivx_obj_desc_image_t *obj_desc_imageIn, const tivx_obj_desc_image_t *obj_desc_imageOut); static vx_status tivxDisplayM2MDrvStructsInit(tivxDisplayM2MDrvObj *drvObj); static vx_status tivxDisplayM2MDrvCfg(tivxDisplayM2MDrvObj *drvObj); static int32_t tivxDisplayM2MCallback(Fvid2_Handle handle, void *appData); static vx_status tivxDisplayExtractFvid2Format( const tivx_obj_desc_image_t *obj_desc_img, Fvid2_Format *format); static tivxDisplayM2MParams *tivxDispM2mAllocObject(tivxDisplayM2MInstObj *instObj); static void tivxDispM2mFreeObject(tivxDisplayM2MInstObj *instObj, tivxDisplayM2MParams *m2mObj); static vx_status VX_CALLBACK tivxDisplayM2MProcess( tivx_target_kernel_instance kernel, tivx_obj_desc_t *obj_desc[], uint16_t num_params, void *priv_arg) { vx_status status = (vx_status)VX_SUCCESS; tivxDisplayM2MParams *prms = NULL; tivxDisplayM2MDrvObj *drvObj; tivx_obj_desc_image_t *input_desc; tivx_obj_desc_image_t *output_desc; void *input_target_ptr, *input_target_ptr2 = NULL; void *output_target_ptr, *output_target_ptr2 = NULL; Fvid2_Frame *frm; int32_t fvid2_status = FVID2_SOK; uint32_t pipeIdx; VX_PRINT(VX_ZONE_ERROR, "cyhdebug11: M2M: %s:%d--------------------------------------!!!\n", __func__, __LINE__); if ( (num_params != TIVX_KERNEL_DISPLAY_M2M_MAX_PARAMS) || (NULL == obj_desc[TIVX_KERNEL_DISPLAY_M2M_CONFIGURATION_IDX]) || (NULL == obj_desc[TIVX_KERNEL_DISPLAY_M2M_INPUT_IDX]) || (NULL == obj_desc[TIVX_KERNEL_DISPLAY_M2M_OUTPUT_IDX]) ) { status = (vx_status)VX_FAILURE; } if((vx_status)VX_SUCCESS == status) { uint32_t size; input_desc = (tivx_obj_desc_image_t *)obj_desc[TIVX_KERNEL_DISPLAY_M2M_INPUT_IDX]; output_desc = (tivx_obj_desc_image_t *)obj_desc[TIVX_KERNEL_DISPLAY_M2M_OUTPUT_IDX]; status = tivxGetTargetKernelInstanceContext(kernel, (void **)&prms, &size); if (((vx_status)VX_SUCCESS != status) || (NULL == prms) || (sizeof(tivxDisplayM2MParams) != size)) { status = (vx_status)VX_FAILURE; VX_PRINT(VX_ZONE_ERROR, "DISPLAY M2M: ERROR: Instance context is NULL!\r\n"); } } if((vx_status)VX_SUCCESS == status) { /* Update 'input_desc' to array from only single image input to support blending i.e. more than 1 number of pipes. */ input_target_ptr = tivxMemShared2TargetPtr(&input_desc->mem_ptr[0]); if((vx_df_image)VX_DF_IMAGE_NV12 == input_desc->format) { input_target_ptr2 = tivxMemShared2TargetPtr(&input_desc->mem_ptr[1]); } output_target_ptr = tivxMemShared2TargetPtr(&output_desc->mem_ptr[0]); if((vx_df_image)VX_DF_IMAGE_NV12 == output_desc->format) { output_target_ptr2 = tivxMemShared2TargetPtr(&output_desc->mem_ptr[1]); } /* call kernel processing function */ drvObj = &prms->drvObj; /* Assign input buffer addresses */ for (pipeIdx = 0U ; pipeIdx < drvObj->numPipe ; pipeIdx++) { frm = &drvObj->inFrm[pipeIdx]; frm->addr[0U] = (uint64_t)input_target_ptr; if((vx_df_image)VX_DF_IMAGE_NV12 == input_desc->format) { frm->addr[1U] = (uint64_t)input_target_ptr2; } } /* Assign output buffer addresses */ frm = drvObj->outFrm; frm->addr[0U] = (uint64_t)output_target_ptr; if((vx_df_image)VX_DF_IMAGE_NV12 == output_desc->format) { frm->addr[1U] = (uint64_t)output_target_ptr2; } /* Submit the request to the driver */ fvid2_status = Fvid2_processRequest(drvObj->drvHandle, &drvObj->inFrmList, &drvObj->outFrmList, FVID2_TIMEOUT_FOREVER); if (FVID2_SOK != fvid2_status) { VX_PRINT(VX_ZONE_ERROR, "Failed to Submit Request\n"); status = (vx_status)VX_FAILURE; } else { /* Wait for Frame Completion */ tivxEventWait(drvObj->waitForProcessCmpl, TIVX_EVENT_TIMEOUT_WAIT_FOREVER); fvid2_status = Fvid2_getProcessedRequest(drvObj->drvHandle, &drvObj->inFrmList, &drvObj->outFrmList, 0); if (FVID2_SOK != fvid2_status) { VX_PRINT(VX_ZONE_ERROR, "Failed to Get Processed Request\n"); status = (vx_status)VX_FAILURE; } } /* kernel processing function complete */ } return status; } static vx_status VX_CALLBACK tivxDisplayM2MCreate( tivx_target_kernel_instance kernel, tivx_obj_desc_t *obj_desc[], uint16_t num_params, void *priv_arg) { VX_PRINT(VX_ZONE_ERROR, "cyhdebug7: M2M: %s:%d--------------------------------------!!!\n", __func__, __LINE__); vx_status status = (vx_status)VX_SUCCESS; tivxDisplayM2MParams *prms = NULL; tivx_obj_desc_user_data_object_t *configuration_desc; tivx_obj_desc_image_t *obj_desc_imageIn, *obj_desc_imageOut; if ( (num_params != TIVX_KERNEL_DISPLAY_M2M_MAX_PARAMS) || (NULL == obj_desc[TIVX_KERNEL_DISPLAY_M2M_CONFIGURATION_IDX]) || (NULL == obj_desc[TIVX_KERNEL_DISPLAY_M2M_INPUT_IDX]) || (NULL == obj_desc[TIVX_KERNEL_DISPLAY_M2M_OUTPUT_IDX]) ) { status = (vx_status)VX_FAILURE; } else { configuration_desc = (tivx_obj_desc_user_data_object_t *)obj_desc[TIVX_KERNEL_DISPLAY_M2M_CONFIGURATION_IDX]; obj_desc_imageIn = (tivx_obj_desc_image_t *)obj_desc[TIVX_KERNEL_DISPLAY_M2M_INPUT_IDX]; obj_desc_imageOut = (tivx_obj_desc_image_t *)obj_desc[TIVX_KERNEL_DISPLAY_M2M_OUTPUT_IDX]; if (configuration_desc->mem_size != sizeof(tivx_display_m2m_params_t)) { VX_PRINT(VX_ZONE_ERROR, "User data object size on target does not match the size on host, possibly due to misalignment in data structure\n"); status = (vx_status)VX_FAILURE; } prms = tivxDispM2mAllocObject(&gTivxDispM2mInstObj); if (NULL == prms) { status = (vx_status)VX_ERROR_NO_MEMORY; VX_PRINT(VX_ZONE_ERROR, "Unable to allocate local memory\n"); } /* Create Node object elements */ if ((vx_status)VX_SUCCESS == status) { status = tivxDisplayM2MSetCreateParams(prms, configuration_desc, obj_desc_imageIn, obj_desc_imageOut); } /* Create sync events */ if (status == (vx_status)VX_SUCCESS) { status = tivxEventCreate(&prms->drvObj.waitForProcessCmpl); if ((vx_status)VX_SUCCESS != status) { VX_PRINT(VX_ZONE_ERROR, "Failed to allocate Event\n"); } } /* DSS M2M Driver create and configuration */ if (status == (vx_status)VX_SUCCESS) { status = tivxDisplayM2MDrvCfg(&prms->drvObj); } if ((vx_status)VX_SUCCESS == status) { tivxSetTargetKernelInstanceContext(kernel, prms, sizeof(tivxDisplayM2MParams)); } else { status = (vx_status)VX_ERROR_NO_MEMORY; VX_PRINT(VX_ZONE_ERROR, "Unable to allocate local memory\n"); } } return status; } static vx_status VX_CALLBACK tivxDisplayM2MDelete( tivx_target_kernel_instance kernel, tivx_obj_desc_t *obj_desc[], uint16_t num_params, void *priv_arg) { vx_status status = (vx_status)VX_SUCCESS; tivxDisplayM2MParams *prms = NULL; uint32_t size; int32_t fvid2_status = FVID2_SOK; VX_PRINT(VX_ZONE_ERROR, "cyhdebug8: M2M: %s:%d--------------------------------------!!!\n", __func__, __LINE__); if ( (num_params != TIVX_KERNEL_DISPLAY_M2M_MAX_PARAMS) || (NULL == obj_desc[TIVX_KERNEL_DISPLAY_M2M_CONFIGURATION_IDX]) || (NULL == obj_desc[TIVX_KERNEL_DISPLAY_M2M_INPUT_IDX]) || (NULL == obj_desc[TIVX_KERNEL_DISPLAY_M2M_OUTPUT_IDX]) ) { status = (vx_status)VX_FAILURE; } else { status = tivxGetTargetKernelInstanceContext(kernel, (void **)&prms, &size); if ((vx_status)VX_SUCCESS != status) { VX_PRINT(VX_ZONE_ERROR, " DSS M2M: ERROR: Could not obtain kernel instance context !!!\n"); } if(NULL == prms) { VX_PRINT(VX_ZONE_ERROR, "Kernel instance context is NULL!!!\n"); status = (vx_status)VX_FAILURE; } if ((vx_status)VX_SUCCESS == status) { /* Stop Display M2M Driver */ fvid2_status = Fvid2_stop(prms->drvObj.drvHandle, NULL); if (FVID2_SOK != fvid2_status) { status = (vx_status)VX_FAILURE; VX_PRINT(VX_ZONE_ERROR, " DSS M2M: ERROR: FVID2 DSS M2M not stopped !!!\n"); } } if ((vx_status)VX_SUCCESS == status) { /* Dequeue all the request from the driver */ while ((vx_status)VX_SUCCESS == status) { fvid2_status = Fvid2_getProcessedRequest(prms->drvObj.drvHandle, &prms->drvObj.inFrmList, &prms->drvObj.outFrmList, 0); if (FVID2_SOK != fvid2_status) { if (fvid2_status != FVID2_ENO_MORE_BUFFERS) { VX_PRINT(VX_ZONE_ERROR, "Failed to Get Processed Request\n"); } status = (vx_status)VX_FAILURE; } } if (fvid2_status == FVID2_ENO_MORE_BUFFERS) { status = (vx_status)VX_SUCCESS; } } if ((vx_status)VX_SUCCESS == status) { /* print status */ fvid2_status = Fvid2_control(prms->drvObj.drvHandle, IOCTL_DSS_M2M_GET_CURRENT_STATUS, &prms->drvObj.wbStatus, NULL); if (FVID2_SOK != fvid2_status) { VX_PRINT(VX_ZONE_ERROR, "Get status returned failure\n"); status = (vx_status)VX_FAILURE; } else { printf( "==========================================================\r\n"); printf( " Display M2M Status: Instance|%d\r\n", prms->drvObj.instId); printf( "==========================================================\r\n"); printf( " Queue Count: %d\r\n", prms->drvObj.wbStatus.queueCount); printf( " De-queue Count: %d\r\n", prms->drvObj.wbStatus.dequeueCount); printf( " Write-back Frames Count: %d\r\n", prms->drvObj.wbStatus.wbFrmCount); printf( " Underflow Count: %d\r\n", prms->drvObj.wbStatus.underflowCount); } } if ((vx_status)VX_SUCCESS == status) { /* Delete FVID2 handle */ fvid2_status = Fvid2_delete(prms->drvObj.drvHandle, NULL); if (FVID2_SOK != fvid2_status) { status = (vx_status)VX_FAILURE; VX_PRINT(VX_ZONE_ERROR, " DSS M2M: ERROR: FVID2 Delete Failed !!!\n"); } else { prms->drvObj.drvHandle = NULL; } } if ((vx_status)VX_SUCCESS == status) { /* Delete event */ tivxEventDelete(&prms->drvObj.waitForProcessCmpl); } if ((NULL != prms) && (sizeof(tivxDisplayM2MParams) == size)) { tivxDispM2mFreeObject(&gTivxDispM2mInstObj, prms); //tivxMemFree(prms, size, (vx_enum)TIVX_MEM_EXTERNAL); } } return status; } static vx_status VX_CALLBACK tivxDisplayM2MControl( tivx_target_kernel_instance kernel, uint32_t node_cmd_id, tivx_obj_desc_t *obj_desc[], uint16_t num_params, void *priv_arg) { vx_status status = (vx_status)VX_SUCCESS; int32_t fvid2_status = FVID2_SOK; uint32_t size; tivxDisplayM2MParams *prms = NULL; tivxDisplayM2MDrvObj *drvObj; tivx_display_m2m_statistics_t *m2m_status_prms = NULL; void *target_ptr; tivx_obj_desc_user_data_object_t *usr_data_obj; VX_PRINT(VX_ZONE_ERROR, "cyhdebug6: M2M: %s:%d--------------------------------------!!!\n", __func__, __LINE__); status = tivxGetTargetKernelInstanceContext(kernel, (void **)&prms, &size); if (((vx_status)VX_SUCCESS != status) || (NULL == prms) || (sizeof(tivxDisplayM2MParams) != size)) { status = (vx_status)VX_FAILURE; } if (status == (vx_status)VX_SUCCESS) { switch (node_cmd_id) { case TIVX_DISPLAY_M2M_GET_STATISTICS: { if (NULL != obj_desc[0]) { drvObj = &prms->drvObj; fvid2_status = Fvid2_control(drvObj->drvHandle, IOCTL_DSS_M2M_GET_CURRENT_STATUS, &drvObj->wbStatus, NULL); if (FVID2_SOK != fvid2_status) { VX_PRINT(VX_ZONE_ERROR, "Get status returned failure\n"); status = (vx_status)VX_FAILURE; } else { /* Update return status object */ usr_data_obj = (tivx_obj_desc_user_data_object_t *)obj_desc[0U]; target_ptr = tivxMemShared2TargetPtr(&usr_data_obj->mem_ptr); tivxCheckStatus(&status, tivxMemBufferMap(target_ptr, usr_data_obj->mem_size, (vx_enum)VX_MEMORY_TYPE_HOST, (vx_enum)VX_WRITE_ONLY)); if (sizeof(tivx_display_m2m_statistics_t) == usr_data_obj->mem_size) { m2m_status_prms = (tivx_display_m2m_statistics_t *)target_ptr; m2m_status_prms->queueCount = drvObj->wbStatus.queueCount; m2m_status_prms->dequeueCount = drvObj->wbStatus.dequeueCount; m2m_status_prms->wbFrmCount = drvObj->wbStatus.wbFrmCount; m2m_status_prms->underflowCount = drvObj->wbStatus.underflowCount; } else { VX_PRINT(VX_ZONE_ERROR, "Invalid Size \n"); status = (vx_status)VX_ERROR_INVALID_PARAMETERS; } tivxCheckStatus(&status, tivxMemBufferUnmap(target_ptr, usr_data_obj->mem_size, (vx_enum)VX_MEMORY_TYPE_HOST, (vx_enum)VX_WRITE_ONLY)); } } else { VX_PRINT(VX_ZONE_ERROR, "User data object was NULL\n"); status = (vx_status)VX_FAILURE; } break; } default: { VX_PRINT(VX_ZONE_ERROR, "Invalid Command Id\n"); status = (vx_status)VX_FAILURE; break; } } } return status; } void tivxAddTargetKernelDisplayM2M(void) { vx_status status = (vx_status)VX_FAILURE; char target_name[TIVX_TARGET_MAX_NAME]; vx_enum self_cpu; VX_PRINT(VX_ZONE_ERROR, "cyhdebug1: M2M: %s:%d--------------------------------------!!!\n", __func__, __LINE__); self_cpu = tivxGetSelfCpuId(); if ( self_cpu == (vx_enum)TIVX_CPU_ID_MCU2_0 ) { strncpy(target_name, TIVX_TARGET_DISPLAY_M2M1, TIVX_TARGET_MAX_NAME); vx_display_m2m_target_kernel1 = tivxAddTargetKernelByName( TIVX_KERNEL_DISPLAY_M2M_NAME, target_name, tivxDisplayM2MProcess, tivxDisplayM2MCreate, tivxDisplayM2MDelete, tivxDisplayM2MControl, NULL); strncpy(target_name, TIVX_TARGET_DISPLAY_M2M2, TIVX_TARGET_MAX_NAME); vx_display_m2m_target_kernel2 = tivxAddTargetKernelByName( TIVX_KERNEL_DISPLAY_M2M_NAME, target_name, tivxDisplayM2MProcess, tivxDisplayM2MCreate, tivxDisplayM2MDelete, tivxDisplayM2MControl, NULL); strncpy(target_name, TIVX_TARGET_DISPLAY_M2M3, TIVX_TARGET_MAX_NAME); vx_display_m2m_target_kernel3 = tivxAddTargetKernelByName( TIVX_KERNEL_DISPLAY_M2M_NAME, target_name, tivxDisplayM2MProcess, tivxDisplayM2MCreate, tivxDisplayM2MDelete, tivxDisplayM2MControl, NULL); strncpy(target_name, TIVX_TARGET_DISPLAY_M2M4, TIVX_TARGET_MAX_NAME); vx_display_m2m_target_kernel4 = tivxAddTargetKernelByName( TIVX_KERNEL_DISPLAY_M2M_NAME, target_name, tivxDisplayM2MProcess, tivxDisplayM2MCreate, tivxDisplayM2MDelete, tivxDisplayM2MControl, NULL); status = tivxMutexCreate(&gTivxDispM2mInstObj.lock); if ((vx_status)VX_SUCCESS != status) { VX_PRINT(VX_ZONE_ERROR, "Failed to create Mutex\n"); } else { memset(&gTivxDispM2mInstObj.m2mObj, 0x0, sizeof(tivxDisplayM2MParams) * DISPLAY_M2M_MAX_HANDLES); } } } void tivxRemoveTargetKernelDisplayM2M(void) { vx_status status = (vx_status)VX_SUCCESS; VX_PRINT(VX_ZONE_ERROR, "cyhdebug13: M2M: %s:%d--------------------------------------!!!\n", __func__, __LINE__); status = tivxRemoveTargetKernel(vx_display_m2m_target_kernel1); if (status == (vx_status)VX_SUCCESS) { vx_display_m2m_target_kernel1 = NULL; } status = tivxRemoveTargetKernel(vx_display_m2m_target_kernel2); if (status == (vx_status)VX_SUCCESS) { vx_display_m2m_target_kernel2 = NULL; } status = tivxRemoveTargetKernel(vx_display_m2m_target_kernel3); if (status == (vx_status)VX_SUCCESS) { vx_display_m2m_target_kernel3 = NULL; } status = tivxRemoveTargetKernel(vx_display_m2m_target_kernel4); if (status == (vx_status)VX_SUCCESS) { vx_display_m2m_target_kernel4 = NULL; } if (NULL != gTivxDispM2mInstObj.lock) { tivxMutexDelete(&gTivxDispM2mInstObj.lock); } } static vx_status tivxDisplayM2MSetCreateParams( tivxDisplayM2MParams *prms, const tivx_obj_desc_user_data_object_t *obj_desc, const tivx_obj_desc_image_t *obj_desc_imageIn, const tivx_obj_desc_image_t *obj_desc_imageOut) { vx_status status = (vx_status)VX_SUCCESS; void *cfgPtr; tivx_display_m2m_params_t *createParams; tivxDisplayM2MDrvObj *drvObj; uint32_t pipeIdx, layerIdx; Dss_DispParams *dispParams; CSL_DssWbPipeCfg *wbPipeCfg; Dss_DctrlOverlayParams *ovrParams; Dss_DctrlOverlayLayerParams *layerParams; Fvid2_Frame *frm; VX_PRINT(VX_ZONE_ERROR, "cyhdebug12: M2M: %s:%d--------------------------------------!!!\n", __func__, __LINE__); cfgPtr = tivxMemShared2TargetPtr(&obj_desc->mem_ptr); tivxCheckStatus(&status, tivxMemBufferMap(cfgPtr, obj_desc->mem_size, (vx_enum)VX_MEMORY_TYPE_HOST, (vx_enum)VX_READ_ONLY)); if (status == (vx_status)VX_SUCCESS) { VX_PRINT(VX_ZONE_ERROR, "M2M: createParams->instId: %d, numpipe: %d, overlayId: %d----------!!!\n", createParams->instId, createParams->numPipe, createParams->overlayId); createParams = (tivx_display_m2m_params_t *)cfgPtr; memcpy(&prms->createParams, createParams, sizeof(tivx_display_m2m_params_t)); drvObj = &prms->drvObj; /* Set Driver object */ drvObj->instId = createParams->instId; drvObj->numPipe = createParams->numPipe; drvObj->overlayId = createParams->overlayId; memcpy(&drvObj->pipeId[0U], &createParams->pipeId[0U], sizeof(createParams->pipeId)); } /* Initialize driver object */ if (status == (vx_status)VX_SUCCESS) { status = tivxDisplayM2MDrvStructsInit(drvObj); } /* set driver object parameters */ if (status == (vx_status)VX_SUCCESS) { /* Callback parameters */ drvObj->cbParams.cbFxn = (Fvid2_CbFxn) (&tivxDisplayM2MCallback); drvObj->cbParams.appData = drvObj; drvObj->createParams.numPipe = drvObj->numPipe; drvObj->createParams.overlayId = drvObj->overlayId; /* Set Display pipeline parameters */ for (pipeIdx = 0U ; pipeIdx < drvObj->numPipe ; pipeIdx++) { dispParams = &drvObj->pipeCfg[pipeIdx].cfgParams; drvObj->createParams.pipeId[pipeIdx] = drvObj->pipeId[pipeIdx]; drvObj->pipeCfg[pipeIdx].pipeId = drvObj->pipeId[pipeIdx]; drvObj->mFlagCfg[pipeIdx].pipeId = drvObj->pipeId[pipeIdx]; drvObj->cscCfg[pipeIdx].pipeId = drvObj->pipeId[pipeIdx]; dispParams->pipeCfg.pipeType = CSL_DSS_VID_PIPE_TYPE_VID; dispParams->layerPos.startX = 0U; dispParams->layerPos.startY = 0U; dispParams->pipeCfg.scEnable = FALSE; dispParams->alphaCfg.globalAlpha = 0xFFU; dispParams->alphaCfg.preMultiplyAlpha = FALSE; status = tivxDisplayExtractFvid2Format( obj_desc_imageIn, &dispParams->pipeCfg.inFmt); if (status == (vx_status)VX_SUCCESS) { /* Set video pipe output frame dimensions same as input as no scaling is done in video pipe-line */ dispParams->pipeCfg.outWidth = dispParams->pipeCfg.inFmt.width; dispParams->pipeCfg.outHeight = dispParams->pipeCfg.inFmt.height; } else { status = (vx_status)VX_FAILURE; VX_PRINT(VX_ZONE_ERROR, "Invalid Input Image\n"); break; } } /* Set Display WB pipeline parameters */ if (((vx_status)VX_SUCCESS == status) && (pipeIdx > 0)) { wbPipeCfg = &drvObj->wbCfg.pipeCfg; /* Set WB pipe input frame dimensions same as video pipe input/output frame, no scaling is done in video pipe, it will be done in WB pipe-line */ wbPipeCfg->inFmt.width = dispParams->pipeCfg.outWidth; wbPipeCfg->inFmt.height = dispParams->pipeCfg.outHeight; wbPipeCfg->inPos.startX = 0U; wbPipeCfg->inPos.startY = 0U; status = tivxDisplayExtractFvid2Format(obj_desc_imageOut, &wbPipeCfg->outFmt); if (status != (vx_status)VX_SUCCESS) { VX_PRINT(VX_ZONE_ERROR, "Invalid Input Image\n"); status = (vx_status)VX_FAILURE; } else { if ((wbPipeCfg->inFmt.width != wbPipeCfg->outFmt.width) || (wbPipeCfg->inFmt.height != wbPipeCfg->outFmt.height)) { wbPipeCfg->scEnable = TRUE; } } } /* Set Display WB pipeline parameters */ if ((vx_status)VX_SUCCESS == status) { ovrParams = &drvObj->ovrCfg; ovrParams->overlayId = drvObj->overlayId; ovrParams->colorbarEnable = FALSE; ovrParams->overlayCfg.colorKeyEnable = FALSE; ovrParams->overlayCfg.colorKeySel = CSL_DSS_OVERLAY_TRANS_COLOR_DEST; ovrParams->overlayCfg.backGroundColor = 0xc8c800U; layerParams = &drvObj->layerCfg; layerParams->overlayId = drvObj->overlayId; /* Set all layer to invalid first and then update only used ones */ for(layerIdx = 0U ; layerIdx < CSL_DSS_VID_PIPE_ID_MAX ; layerIdx++) { layerParams->pipeLayerNum[layerIdx] = CSL_DSS_OVERLAY_LAYER_INVALID; } /* Currently blending is not supported so only one layer is used. This code needs to updated when blending is supported. */ layerParams->pipeLayerNum[drvObj->createParams.pipeId[0U]] = CSL_DSS_OVERLAY_LAYER_NUM_0; layerParams->pipeLayerNum[drvObj->createParams.pipeId[1U]] = CSL_DSS_OVERLAY_LAYER_NUM_1; } /* Update frame-lists */ if ((vx_status)VX_SUCCESS == status) { drvObj->inFrmList.numFrames = drvObj->numPipe; for (pipeIdx = 0U ; pipeIdx < drvObj->numPipe ; pipeIdx++) { frm = (Fvid2_Frame *) &drvObj->inFrm[pipeIdx]; frm->chNum = drvObj->createParams.pipeId[pipeIdx]; drvObj->inFrmList.frames[pipeIdx] = frm; } frm = (Fvid2_Frame *) &drvObj->outFrm[0U]; drvObj->outFrmList.frames[0U] = frm; drvObj->outFrmList.numFrames = 1U; } } return status; } static vx_status tivxDisplayM2MDrvStructsInit(tivxDisplayM2MDrvObj *drvObj) { vx_status status = (vx_status)VX_SUCCESS; uint32_t loopCnt; VX_PRINT(VX_ZONE_ERROR, "cyhdebug10: M2M: %s:%d--------------------------------------!!!\n", __func__, __LINE__); /* Initialize driver create parameters */ Dss_m2mCreateParamsInit(&drvObj->createParams); /* Initialize driver call-back parameters */ Fvid2CbParams_init(&drvObj->cbParams); /* Initialize driver pipe configuration parameters */ for (loopCnt = 0U ; loopCnt < drvObj->numPipe ; loopCnt++) { Dss_dispParamsInit(&drvObj->pipeCfg[loopCnt].cfgParams); Dss_dispPipeMflagParamsInit(&drvObj->mFlagCfg[loopCnt].mFlagCfg); CSL_dssCscCoeffInit(&drvObj->cscCfg[loopCnt].csc); } /* Initialize WB pipeline parameters */ Dss_m2mPipeCfgParamsInit(&drvObj->wbCfg); CSL_dssWbPipeDmaCfgInit(&drvObj->wbDmaCfg); Dss_m2mMFlagParamsInit(&drvObj->wbMflagCfg); CSL_dssCscCoeffInit(&drvObj->wbCscCfg); Dss_m2mStatusInit(&drvObj->wbStatus); /* Initialize Display overlay parameters */ Dss_dctrlOverlayParamsInit(&drvObj->ovrCfg); Dss_dctrlOverlayLayerParamsInit(&drvObj->layerCfg); /* Initialize Display global parameters */ Dss_dctrlGlobalDssParamsInit(&drvObj->globalParams); /* Initialize input and output frame lists */ Fvid2FrameList_init(&drvObj->inFrmList); Fvid2FrameList_init(&drvObj->outFrmList); return status; } static vx_status tivxDisplayM2MDrvCfg(tivxDisplayM2MDrvObj *drvObj) { vx_status status = (vx_status)VX_SUCCESS; uint32_t loopCnt; int32_t fvid2_status = FVID2_SOK; VX_PRINT(VX_ZONE_ERROR, "cyhdebug9: M2M: %s:%d--------------------------------------!!!\n", __func__, __LINE__); /* Display M2M Driver create */ drvObj->drvHandle = Fvid2_create(DSS_M2M_DRV_ID, drvObj->instId, &drvObj->createParams, &drvObj->createStatus, &drvObj->cbParams); if((NULL == drvObj->drvHandle) || (drvObj->createStatus.retVal != FVID2_SOK)) { VX_PRINT(VX_ZONE_ERROR, ": Display M2M Create Failed!!!\r\n"); status = (vx_status)VX_FAILURE; } /* Display M2M pipe configuration */ if ((vx_status)VX_SUCCESS == status) { for (loopCnt = 0U ; loopCnt < drvObj->numPipe ; loopCnt++) { fvid2_status += Fvid2_control(drvObj->drvHandle, IOCTL_DSS_M2M_SET_PIPE_PARAMS, &drvObj->pipeCfg[loopCnt], NULL); fvid2_status += Fvid2_control(drvObj->drvHandle, IOCTL_DSS_M2M_SET_PIPE_MFLAG_PARAMS, &drvObj->mFlagCfg[loopCnt], NULL); if (FVID2_SOK != fvid2_status) { VX_PRINT(VX_ZONE_ERROR, ": Display M2M DISP IOCTL Failed!!!\r\n"); status = (vx_status)VX_FAILURE; break; } } } /* Display M2M overlay configuration */ if ((vx_status)VX_SUCCESS == status) { fvid2_status += Fvid2_control(drvObj->drvHandle, IOCTL_DSS_DCTRL_SET_OVERLAY_PARAMS, &drvObj->ovrCfg, NULL); fvid2_status += Fvid2_control(drvObj->drvHandle, IOCTL_DSS_DCTRL_SET_LAYER_PARAMS, &drvObj->layerCfg, NULL); if (FVID2_SOK != fvid2_status) { VX_PRINT(VX_ZONE_ERROR, ": Display M2M Overlay IOCTL Failed!!!\r\n"); status = (vx_status)VX_FAILURE; } } /* Display M2M global configuration */ if ((vx_status)VX_SUCCESS == status) { fvid2_status += Fvid2_control(drvObj->drvHandle, IOCTL_DSS_DCTRL_SET_GLOBAL_DSS_PARAMS, &drvObj->globalParams, NULL); if (FVID2_SOK != fvid2_status) { VX_PRINT(VX_ZONE_ERROR, ": Display M2M Global IOCTL Failed!!!\r\n"); status = (vx_status)VX_FAILURE; } } /* Display M2M write-back pipe configuration */ if ((vx_status)VX_SUCCESS == status) { fvid2_status += Fvid2_control(drvObj->drvHandle, IOCTL_DSS_M2M_SET_WB_PIPE_PARAMS, &drvObj->wbCfg, NULL); fvid2_status += Fvid2_control(drvObj->drvHandle, IOCTL_DSS_M2M_SET_WB_PIPE_MFLAG_PARAMS, &drvObj->wbMflagCfg, NULL); fvid2_status += Fvid2_control(drvObj->drvHandle, IOCTL_DSS_M2M_SET_WB_PIPE_DMA_CFG, &drvObj->wbDmaCfg, NULL); if (FVID2_SOK != fvid2_status) { VX_PRINT(VX_ZONE_ERROR, ": Display M2M WB IOCTL Failed!!!\r\n"); status = (vx_status)VX_FAILURE; } } /* Start Display M2M Driver */ if ((vx_status)VX_SUCCESS == status) { fvid2_status = Fvid2_start(drvObj->drvHandle, NULL); if (FVID2_SOK != fvid2_status) { VX_PRINT(VX_ZONE_ERROR, ": Display M2M Driver Start Failed!!!\r\n"); status = (vx_status)VX_FAILURE; } } return status; } static int32_t tivxDisplayM2MCallback(Fvid2_Handle handle, void *appData) { tivxDisplayM2MDrvObj *drvObj = (tivxDisplayM2MDrvObj *)(appData); VX_PRINT(VX_ZONE_ERROR, "cyhdebug5: M2M: %s:%d--------------------------------------!!!\n", __func__, __LINE__); if ((NULL != drvObj) && (drvObj->waitForProcessCmpl != NULL)) { tivxEventPost(drvObj->waitForProcessCmpl); } return (vx_status)VX_SUCCESS; } static vx_status tivxDisplayExtractFvid2Format( const tivx_obj_desc_image_t *obj_desc_img, Fvid2_Format *format) { vx_status status = (vx_status)VX_SUCCESS; Fvid2Format_init(format); format->width = obj_desc_img->imagepatch_addr[0].dim_x; format->height = obj_desc_img->imagepatch_addr[0].dim_y; format->ccsFormat = FVID2_CCSF_BITS8_PACKED; format->scanFormat = FVID2_SF_PROGRESSIVE; VX_PRINT(VX_ZONE_ERROR, "cyhdebug4: M2M: %s:%d--------------------------------------!!!\n", __func__, __LINE__); switch (obj_desc_img->format) { case (vx_df_image)TIVX_DF_IMAGE_RGB565: format->dataFormat = FVID2_DF_BGR16_565; format->pitch[FVID2_RGB_ADDR_IDX] = (uint32_t)obj_desc_img->imagepatch_addr[0].stride_y; break; case (vx_df_image)VX_DF_IMAGE_RGB: format->dataFormat = FVID2_DF_RGB24_888; format->pitch[FVID2_RGB_ADDR_IDX] = (uint32_t)obj_desc_img->imagepatch_addr[0].stride_y; break; case (vx_df_image)VX_DF_IMAGE_RGBX: VX_PRINT(VX_ZONE_ERROR, "debug: -----------------------------choose VX_DF_IMAGE_RGBX"); format->dataFormat = FVID2_DF_BGRX24_8888; format->pitch[FVID2_RGB_ADDR_IDX] = (uint32_t)obj_desc_img->imagepatch_addr[0].stride_y; break; case (vx_df_image)TIVX_DF_IMAGE_BGRX: format->dataFormat = FVID2_DF_BGRX24_8888; format->pitch[FVID2_RGB_ADDR_IDX] = (uint32_t)obj_desc_img->imagepatch_addr[0].stride_y; break; case (vx_df_image)VX_DF_IMAGE_UYVY: format->dataFormat = FVID2_DF_YUV422I_UYVY; format->pitch[FVID2_YUV_INT_ADDR_IDX] = (uint32_t)obj_desc_img->imagepatch_addr[0].stride_y; break; case (vx_df_image)VX_DF_IMAGE_YUYV: format->dataFormat = FVID2_DF_YUV422I_YUYV; format->pitch[FVID2_YUV_INT_ADDR_IDX] = (uint32_t)obj_desc_img->imagepatch_addr[0].stride_y; break; case (vx_df_image)VX_DF_IMAGE_NV12: format->dataFormat = FVID2_DF_YUV420SP_UV; format->pitch[FVID2_YUV_SP_Y_ADDR_IDX] = (uint32_t)obj_desc_img->imagepatch_addr[0].stride_y; format->pitch[FVID2_YUV_SP_CBCR_ADDR_IDX] = (uint32_t)obj_desc_img->imagepatch_addr[1].stride_y; break; case (vx_df_image)VX_DF_IMAGE_U16: format->ccsFormat = FVID2_CCSF_BITS12_UNPACKED16; format->dataFormat = FVID2_DF_YUV420SP_UV; format->pitch[FVID2_YUV_SP_Y_ADDR_IDX] = (uint32_t)obj_desc_img->imagepatch_addr[0].stride_y; format->pitch[FVID2_YUV_SP_CBCR_ADDR_IDX] = (uint32_t)obj_desc_img->imagepatch_addr[0].stride_y; break; case (vx_df_image)VX_DF_IMAGE_U8: format->ccsFormat = FVID2_CCSF_BITS8_PACKED; format->dataFormat = FVID2_DF_YUV420SP_UV; format->pitch[FVID2_YUV_SP_Y_ADDR_IDX] = (uint32_t)obj_desc_img->imagepatch_addr[0].stride_y; format->pitch[FVID2_YUV_SP_CBCR_ADDR_IDX] = (uint32_t)obj_desc_img->imagepatch_addr[0].stride_y; break; default: status = (vx_status)VX_FAILURE; break; } return status; } static tivxDisplayM2MParams *tivxDispM2mAllocObject(tivxDisplayM2MInstObj *instObj) { uint32_t cnt; tivxDisplayM2MParams *m2mObj = NULL; VX_PRINT(VX_ZONE_ERROR, "cyhdebug2: M2M: %s:%d--------------------------------------!!!\n", __func__, __LINE__); /* Lock instance mutex */ tivxMutexLock(instObj->lock); for (cnt = 0U; cnt < DISPLAY_M2M_MAX_HANDLES; cnt ++) { if (0U == instObj->m2mObj[cnt].isAlloc) { m2mObj = &instObj->m2mObj[cnt]; memset(m2mObj, 0x0, sizeof(tivxDisplayM2MParams)); instObj->m2mObj[cnt].isAlloc = 1U; break; } } /* Release instance mutex */ tivxMutexUnlock(instObj->lock); return (m2mObj); } static void tivxDispM2mFreeObject(tivxDisplayM2MInstObj *instObj, tivxDisplayM2MParams *m2mObj) { uint32_t cnt; VX_PRINT(VX_ZONE_ERROR, "cyhdebug3: M2M: %s:%d--------------------------------------!!!\n", __func__, __LINE__); /* Lock instance mutex */ tivxMutexLock(instObj->lock); for (cnt = 0U; cnt < DISPLAY_M2M_MAX_HANDLES; cnt ++) { if (m2mObj == &instObj->m2mObj[cnt]) { m2mObj->isAlloc = 0U; break; } } /* Release instance mutex */ tivxMutexUnlock(instObj->lock); }
below error was occured:
log file:
MobaXterm_COM3ProlificUSB-to-SerialCommPortCOM3_20230328_163601.txt
Regards.
Hi, Brijesh,
I mask the judge of pipe num vx_display_m2m_host.c
the error becomes as follows:
from the output of app vx_app_arm_remote_log.out:
it seems that the error occurred while allocating memory:
log file: MobaXterm_COM3ProlificUSB-to-SerialCommPortCOM3_20230328_173623.txt
Regards.
Hi xie jc,
The above driver changes look to be fine. But before trying it out in OpenVX node, can we please first check it in the driver example? We need to make sure that driver is working fine before checking it on OpenVX.
Regarding above error, there are two types of errors,
1, "Unable to allocate local memory": this error comes when we are trying to allocate more than 10 handles, are you trying to use this node for multiple instances?
2, also it looks like you are trying to enable scaling on the video lite pipeline, this pipeline does not support scaling. So please make sure to set input and output resolution same, thus disabling scalar.
Regards,
Brijesh
Hi, Brijesh,
The above driver changes look to be fine. But before trying it out in OpenVX node, can we please first check it in the driver example? We need to make sure that driver is working fine before checking it on OpenVX.
OK. Which driver sample should we use to check first?
1, "Unable to allocate local memory": this error comes when we are trying to allocate more than 10 handles, are you trying to use this node for multiple instances?
No. our data flow: uyvy picture -> M2M -> csitx.
also it looks like you are trying to enable scaling on the video lite pipeline, this pipeline does not support scaling. So please make sure to set input and output resolution same, thus disabling scalar.
function tivxDisplayM2MDrvCfg() in vx_display_m2m_target.c will call function Fvid2_control(), and Dss_m2mControl() will call by Fvid2_control, and error
occur in Dss_m2mDrvValidataDispParams()
Regards.
/* * * Copyright (c) 2021 Texas Instruments Incorporated * * All rights reserved not granted herein. * * Limited License. * * Texas Instruments Incorporated grants a world-wide, royalty-free, non-exclusive * license under copyrights and patents it now or hereafter owns or controls to make, * have made, use, import, offer to sell and sell ("Utilize") this software subject to the * terms herein. With respect to the foregoing patent license, such license is granted * solely to the extent that any such patent is necessary to Utilize the software alone. * The patent license shall not apply to any combinations which include this software, * other than combinations with devices manufactured by or for TI ("TI Devices"). * No hardware patent is licensed hereunder. * * Redistributions must preserve existing copyright notices and reproduce this license * (including the above copyright notice and the disclaimer and (if applicable) source * code license limitations below) in the documentation and/or other materials provided * with the distribution * * Redistribution and use in binary form, without modification, are permitted provided * that the following conditions are met: * * * No reverse engineering, decompilation, or disassembly of this software is * permitted with respect to any software provided in binary form. * * * any redistribution and use are licensed by TI for use only with TI Devices. * * * Nothing shall obligate TI to provide you with source code for the software * licensed and provided to you in object code. * * If software source code is provided to you, modification and redistribution of the * source code are permitted provided that the following conditions are met: * * * any redistribution and use of the source code, including any resulting derivative * works, are licensed by TI for use only with TI Devices. * * * any redistribution and use of any object code compiled from the source code * and any resulting derivative works, are licensed by TI for use only with TI Devices. * * Neither the name of Texas Instruments Incorporated nor the names of its suppliers * * may be used to endorse or promote products derived from this software without * specific prior written permission. * * DISCLAIMER. * * THIS SOFTWARE IS PROVIDED BY TI AND TI'S LICENSORS "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 TI AND TI'S LICENSORS 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. * */ #include <stdio.h> #include "TI/tivx.h" #include "VX/vx.h" #include "TI/tivx_event.h" #include "tivx_hwa_kernels.h" #include "tivx_kernel_display_m2m.h" #include "TI/tivx_target_kernel.h" #include "tivx_kernels_target_utils.h" #include "tivx_hwa_display_m2m_priv.h" #include <TI/tivx_queue.h> #include <ti/drv/fvid2/fvid2.h> #include <ti/drv/dss/dss.h> #include <tivx_obj_desc_priv.h> #include <vx_reference.h> #define DISPLAY_MAX_VALID_PLANES 2U #define DISPLAY_M2M_MAX_HANDLES (10) typedef struct { /*! IDs=> 0: Write-back pipe-line1 */ uint32_t instId; /*! Number of pipe-lines used, should be set to '1' as blending is not supported currently */ uint32_t numPipe; /*! IDs=> 0:VID1, 1:VIDL1, 2:VID2 and 3:VIDL2 */ uint32_t pipeId[TIVX_DISPLAY_M2M_MAX_PIPE]; /*! IDs=> 0:Overlay1, 1:Overlay2, 2:Overlay3 and 3:Overlay4 */ uint32_t overlayId; /*! FVID2 display driver handle */ Fvid2_Handle drvHandle; /*! WB pipe create parameters */ Dss_WbCreateParams createParams; /*! WB pipe create status */ Dss_WbCreateStatus createStatus; /*! Callback parameters */ Fvid2_CbParams cbParams; /*! WB pipe status */ Dss_WbStatus wbStatus; /*! WB pipe configuration */ Dss_WbPipeCfgParams wbCfg; /*! WB pipe DMA configuration */ CSL_DssWbPipeDmaCfg wbDmaCfg; /*! WB pipe MFlag configuration */ Dss_WbPipeMflagParams wbMflagCfg; /*! WB pipe CSC configuration */ CSL_DssCscCoeff wbCscCfg; /*! Display pipe configuration */ Dss_PipeCfgParams pipeCfg[TIVX_DISPLAY_M2M_MAX_PIPE]; /*! Display pipe MFlag configuration */ Dss_PipeMflagParams mFlagCfg[TIVX_DISPLAY_M2M_MAX_PIPE]; /*! Display pipe CSC configuration */ Dss_PipeCscParams cscCfg[TIVX_DISPLAY_M2M_MAX_PIPE]; /*! Display Overlay configuration */ Dss_DctrlOverlayParams ovrCfg; /*! Display Layer configuration */ Dss_DctrlOverlayLayerParams layerCfg; /*! Display Global configuration */ Dss_DctrlGlobalDssParams globalParams; /*! Mutex used for waiting for process completion */ tivx_event waitForProcessCmpl; /*! Display M2M Driver Input Frame List, used for providing * an array of input frames */ Fvid2_FrameList inFrmList; /*! Display M2M Driver Output Frame List, used for providing * an array of output frames */ Fvid2_FrameList outFrmList; /*! Display M2M Driver Input Frames */ Fvid2_Frame inFrm[TIVX_DISPLAY_M2M_MAX_PIPE]; /*! Display M2M Driver Output Frames */ Fvid2_Frame outFrm[1U]; } tivxDisplayM2MDrvObj; typedef struct { /*! IDs=> 0: Object free, 1: allocated */ uint32_t isAlloc; /*! Display M2M driver object */ tivxDisplayM2MDrvObj drvObj; /*! Display M2M Node create parameters provided by application */ tivx_display_m2m_params_t createParams; } tivxDisplayM2MParams; typedef struct { tivx_mutex lock; tivxDisplayM2MParams m2mObj[DISPLAY_M2M_MAX_HANDLES]; } tivxDisplayM2MInstObj; static tivx_target_kernel vx_display_m2m_target_kernel1 = NULL; static tivx_target_kernel vx_display_m2m_target_kernel2 = NULL; static tivx_target_kernel vx_display_m2m_target_kernel3 = NULL; static tivx_target_kernel vx_display_m2m_target_kernel4 = NULL; tivxDisplayM2MInstObj gTivxDispM2mInstObj; static vx_status VX_CALLBACK tivxDisplayM2MProcess( tivx_target_kernel_instance kernel, tivx_obj_desc_t *obj_desc[], uint16_t num_params, void *priv_arg); static vx_status VX_CALLBACK tivxDisplayM2MCreate( tivx_target_kernel_instance kernel, tivx_obj_desc_t *obj_desc[], uint16_t num_params, void *priv_arg); static vx_status VX_CALLBACK tivxDisplayM2MDelete( tivx_target_kernel_instance kernel, tivx_obj_desc_t *obj_desc[], uint16_t num_params, void *priv_arg); static vx_status VX_CALLBACK tivxDisplayM2MControl( tivx_target_kernel_instance kernel, uint32_t node_cmd_id, tivx_obj_desc_t *obj_desc[], uint16_t num_params, void *priv_arg); static vx_status tivxDisplayM2MSetCreateParams( tivxDisplayM2MParams *prms, const tivx_obj_desc_user_data_object_t *obj_desc, const tivx_obj_desc_image_t *obj_desc_imageIn, const tivx_obj_desc_image_t *obj_desc_imageOut); static vx_status tivxDisplayM2MDrvStructsInit(tivxDisplayM2MDrvObj *drvObj); static vx_status tivxDisplayM2MDrvCfg(tivxDisplayM2MDrvObj *drvObj); static int32_t tivxDisplayM2MCallback(Fvid2_Handle handle, void *appData); static vx_status tivxDisplayExtractFvid2Format( const tivx_obj_desc_image_t *obj_desc_img, Fvid2_Format *format); static tivxDisplayM2MParams *tivxDispM2mAllocObject(tivxDisplayM2MInstObj *instObj); static void tivxDispM2mFreeObject(tivxDisplayM2MInstObj *instObj, tivxDisplayM2MParams *m2mObj); static vx_status VX_CALLBACK tivxDisplayM2MProcess( tivx_target_kernel_instance kernel, tivx_obj_desc_t *obj_desc[], uint16_t num_params, void *priv_arg) { vx_status status = (vx_status)VX_SUCCESS; tivxDisplayM2MParams *prms = NULL; tivxDisplayM2MDrvObj *drvObj; tivx_obj_desc_image_t *input_desc; tivx_obj_desc_image_t *output_desc; void *input_target_ptr, *input_target_ptr2 = NULL; void *output_target_ptr, *output_target_ptr2 = NULL; Fvid2_Frame *frm; int32_t fvid2_status = FVID2_SOK; uint32_t pipeIdx; VX_PRINT(VX_ZONE_ERROR, "cyhdebug11: M2M: %s:%d--------------------------------------!!!\n", __func__, __LINE__); if ( (num_params != TIVX_KERNEL_DISPLAY_M2M_MAX_PARAMS) || (NULL == obj_desc[TIVX_KERNEL_DISPLAY_M2M_CONFIGURATION_IDX]) || (NULL == obj_desc[TIVX_KERNEL_DISPLAY_M2M_INPUT_IDX]) || (NULL == obj_desc[TIVX_KERNEL_DISPLAY_M2M_OUTPUT_IDX]) ) { status = (vx_status)VX_FAILURE; } if((vx_status)VX_SUCCESS == status) { uint32_t size; input_desc = (tivx_obj_desc_image_t *)obj_desc[TIVX_KERNEL_DISPLAY_M2M_INPUT_IDX]; output_desc = (tivx_obj_desc_image_t *)obj_desc[TIVX_KERNEL_DISPLAY_M2M_OUTPUT_IDX]; status = tivxGetTargetKernelInstanceContext(kernel, (void **)&prms, &size); if (((vx_status)VX_SUCCESS != status) || (NULL == prms) || (sizeof(tivxDisplayM2MParams) != size)) { status = (vx_status)VX_FAILURE; VX_PRINT(VX_ZONE_ERROR, "DISPLAY M2M: ERROR: Instance context is NULL!\r\n"); } } if((vx_status)VX_SUCCESS == status) { /* Update 'input_desc' to array from only single image input to support blending i.e. more than 1 number of pipes. */ input_target_ptr = tivxMemShared2TargetPtr(&input_desc->mem_ptr[0]); if((vx_df_image)VX_DF_IMAGE_NV12 == input_desc->format) { input_target_ptr2 = tivxMemShared2TargetPtr(&input_desc->mem_ptr[1]); } output_target_ptr = tivxMemShared2TargetPtr(&output_desc->mem_ptr[0]); if((vx_df_image)VX_DF_IMAGE_NV12 == output_desc->format) { output_target_ptr2 = tivxMemShared2TargetPtr(&output_desc->mem_ptr[1]); } /* call kernel processing function */ drvObj = &prms->drvObj; /* Assign input buffer addresses */ for (pipeIdx = 0U ; pipeIdx < drvObj->numPipe ; pipeIdx++) { frm = &drvObj->inFrm[pipeIdx]; frm->addr[0U] = (uint64_t)input_target_ptr; if((vx_df_image)VX_DF_IMAGE_NV12 == input_desc->format) { frm->addr[1U] = (uint64_t)input_target_ptr2; } } /* Assign output buffer addresses */ frm = drvObj->outFrm; frm->addr[0U] = (uint64_t)output_target_ptr; if((vx_df_image)VX_DF_IMAGE_NV12 == output_desc->format) { frm->addr[1U] = (uint64_t)output_target_ptr2; } /* Submit the request to the driver */ fvid2_status = Fvid2_processRequest(drvObj->drvHandle, &drvObj->inFrmList, &drvObj->outFrmList, FVID2_TIMEOUT_FOREVER); if (FVID2_SOK != fvid2_status) { VX_PRINT(VX_ZONE_ERROR, "Failed to Submit Request\n"); status = (vx_status)VX_FAILURE; } else { /* Wait for Frame Completion */ tivxEventWait(drvObj->waitForProcessCmpl, TIVX_EVENT_TIMEOUT_WAIT_FOREVER); fvid2_status = Fvid2_getProcessedRequest(drvObj->drvHandle, &drvObj->inFrmList, &drvObj->outFrmList, 0); if (FVID2_SOK != fvid2_status) { VX_PRINT(VX_ZONE_ERROR, "Failed to Get Processed Request\n"); status = (vx_status)VX_FAILURE; } } /* kernel processing function complete */ } return status; } static vx_status VX_CALLBACK tivxDisplayM2MCreate( tivx_target_kernel_instance kernel, tivx_obj_desc_t *obj_desc[], uint16_t num_params, void *priv_arg) { VX_PRINT(VX_ZONE_ERROR, "cyhdebug7: M2M: %s:%d--------------------------------------!!!\n", __func__, __LINE__); vx_status status = (vx_status)VX_SUCCESS; tivxDisplayM2MParams *prms = NULL; tivx_obj_desc_user_data_object_t *configuration_desc; tivx_obj_desc_image_t *obj_desc_imageIn, *obj_desc_imageOut; if ( (num_params != TIVX_KERNEL_DISPLAY_M2M_MAX_PARAMS) || (NULL == obj_desc[TIVX_KERNEL_DISPLAY_M2M_CONFIGURATION_IDX]) || (NULL == obj_desc[TIVX_KERNEL_DISPLAY_M2M_INPUT_IDX]) || (NULL == obj_desc[TIVX_KERNEL_DISPLAY_M2M_OUTPUT_IDX]) ) { status = (vx_status)VX_FAILURE; } else { configuration_desc = (tivx_obj_desc_user_data_object_t *)obj_desc[TIVX_KERNEL_DISPLAY_M2M_CONFIGURATION_IDX]; obj_desc_imageIn = (tivx_obj_desc_image_t *)obj_desc[TIVX_KERNEL_DISPLAY_M2M_INPUT_IDX]; obj_desc_imageOut = (tivx_obj_desc_image_t *)obj_desc[TIVX_KERNEL_DISPLAY_M2M_OUTPUT_IDX]; if (configuration_desc->mem_size != sizeof(tivx_display_m2m_params_t)) { VX_PRINT(VX_ZONE_ERROR, "User data object size on target does not match the size on host, possibly due to misalignment in data structure\n"); status = (vx_status)VX_FAILURE; } prms = tivxDispM2mAllocObject(&gTivxDispM2mInstObj); if (NULL == prms) { status = (vx_status)VX_ERROR_NO_MEMORY; VX_PRINT(VX_ZONE_ERROR, "Unable to allocate local memory\n"); } /* Create Node object elements */ if ((vx_status)VX_SUCCESS == status) { status = tivxDisplayM2MSetCreateParams(prms, configuration_desc, obj_desc_imageIn, obj_desc_imageOut); } /* Create sync events */ if (status == (vx_status)VX_SUCCESS) { status = tivxEventCreate(&prms->drvObj.waitForProcessCmpl); if ((vx_status)VX_SUCCESS != status) { VX_PRINT(VX_ZONE_ERROR, "Failed to allocate Event\n"); } } /* DSS M2M Driver create and configuration */ if (status == (vx_status)VX_SUCCESS) { status = tivxDisplayM2MDrvCfg(&prms->drvObj); } if ((vx_status)VX_SUCCESS == status) { tivxSetTargetKernelInstanceContext(kernel, prms, sizeof(tivxDisplayM2MParams)); } else { status = (vx_status)VX_ERROR_NO_MEMORY; VX_PRINT(VX_ZONE_ERROR, "Unable to allocate local memory\n"); } } return status; } static vx_status VX_CALLBACK tivxDisplayM2MDelete( tivx_target_kernel_instance kernel, tivx_obj_desc_t *obj_desc[], uint16_t num_params, void *priv_arg) { vx_status status = (vx_status)VX_SUCCESS; tivxDisplayM2MParams *prms = NULL; uint32_t size; int32_t fvid2_status = FVID2_SOK; VX_PRINT(VX_ZONE_ERROR, "cyhdebug8: M2M: %s:%d--------------------------------------!!!\n", __func__, __LINE__); if ( (num_params != TIVX_KERNEL_DISPLAY_M2M_MAX_PARAMS) || (NULL == obj_desc[TIVX_KERNEL_DISPLAY_M2M_CONFIGURATION_IDX]) || (NULL == obj_desc[TIVX_KERNEL_DISPLAY_M2M_INPUT_IDX]) || (NULL == obj_desc[TIVX_KERNEL_DISPLAY_M2M_OUTPUT_IDX]) ) { status = (vx_status)VX_FAILURE; } else { status = tivxGetTargetKernelInstanceContext(kernel, (void **)&prms, &size); if ((vx_status)VX_SUCCESS != status) { VX_PRINT(VX_ZONE_ERROR, " DSS M2M: ERROR: Could not obtain kernel instance context !!!\n"); } if(NULL == prms) { VX_PRINT(VX_ZONE_ERROR, "Kernel instance context is NULL!!!\n"); status = (vx_status)VX_FAILURE; } if ((vx_status)VX_SUCCESS == status) { /* Stop Display M2M Driver */ fvid2_status = Fvid2_stop(prms->drvObj.drvHandle, NULL); if (FVID2_SOK != fvid2_status) { status = (vx_status)VX_FAILURE; VX_PRINT(VX_ZONE_ERROR, " DSS M2M: ERROR: FVID2 DSS M2M not stopped !!!\n"); } } if ((vx_status)VX_SUCCESS == status) { /* Dequeue all the request from the driver */ while ((vx_status)VX_SUCCESS == status) { fvid2_status = Fvid2_getProcessedRequest(prms->drvObj.drvHandle, &prms->drvObj.inFrmList, &prms->drvObj.outFrmList, 0); if (FVID2_SOK != fvid2_status) { if (fvid2_status != FVID2_ENO_MORE_BUFFERS) { VX_PRINT(VX_ZONE_ERROR, "Failed to Get Processed Request\n"); } status = (vx_status)VX_FAILURE; } } if (fvid2_status == FVID2_ENO_MORE_BUFFERS) { status = (vx_status)VX_SUCCESS; } } if ((vx_status)VX_SUCCESS == status) { /* print status */ fvid2_status = Fvid2_control(prms->drvObj.drvHandle, IOCTL_DSS_M2M_GET_CURRENT_STATUS, &prms->drvObj.wbStatus, NULL); if (FVID2_SOK != fvid2_status) { VX_PRINT(VX_ZONE_ERROR, "Get status returned failure\n"); status = (vx_status)VX_FAILURE; } else { printf( "==========================================================\r\n"); printf( " Display M2M Status: Instance|%d\r\n", prms->drvObj.instId); printf( "==========================================================\r\n"); printf( " Queue Count: %d\r\n", prms->drvObj.wbStatus.queueCount); printf( " De-queue Count: %d\r\n", prms->drvObj.wbStatus.dequeueCount); printf( " Write-back Frames Count: %d\r\n", prms->drvObj.wbStatus.wbFrmCount); printf( " Underflow Count: %d\r\n", prms->drvObj.wbStatus.underflowCount); } } if ((vx_status)VX_SUCCESS == status) { /* Delete FVID2 handle */ fvid2_status = Fvid2_delete(prms->drvObj.drvHandle, NULL); if (FVID2_SOK != fvid2_status) { status = (vx_status)VX_FAILURE; VX_PRINT(VX_ZONE_ERROR, " DSS M2M: ERROR: FVID2 Delete Failed !!!\n"); } else { prms->drvObj.drvHandle = NULL; } } if ((vx_status)VX_SUCCESS == status) { /* Delete event */ tivxEventDelete(&prms->drvObj.waitForProcessCmpl); } if ((NULL != prms) && (sizeof(tivxDisplayM2MParams) == size)) { tivxDispM2mFreeObject(&gTivxDispM2mInstObj, prms); //tivxMemFree(prms, size, (vx_enum)TIVX_MEM_EXTERNAL); } } return status; } static vx_status VX_CALLBACK tivxDisplayM2MControl( tivx_target_kernel_instance kernel, uint32_t node_cmd_id, tivx_obj_desc_t *obj_desc[], uint16_t num_params, void *priv_arg) { vx_status status = (vx_status)VX_SUCCESS; int32_t fvid2_status = FVID2_SOK; uint32_t size; tivxDisplayM2MParams *prms = NULL; tivxDisplayM2MDrvObj *drvObj; tivx_display_m2m_statistics_t *m2m_status_prms = NULL; void *target_ptr; tivx_obj_desc_user_data_object_t *usr_data_obj; VX_PRINT(VX_ZONE_ERROR, "cyhdebug6: M2M: %s:%d--------------------------------------!!!\n", __func__, __LINE__); status = tivxGetTargetKernelInstanceContext(kernel, (void **)&prms, &size); if (((vx_status)VX_SUCCESS != status) || (NULL == prms) || (sizeof(tivxDisplayM2MParams) != size)) { status = (vx_status)VX_FAILURE; } if (status == (vx_status)VX_SUCCESS) { switch (node_cmd_id) { case TIVX_DISPLAY_M2M_GET_STATISTICS: { if (NULL != obj_desc[0]) { drvObj = &prms->drvObj; fvid2_status = Fvid2_control(drvObj->drvHandle, IOCTL_DSS_M2M_GET_CURRENT_STATUS, &drvObj->wbStatus, NULL); if (FVID2_SOK != fvid2_status) { VX_PRINT(VX_ZONE_ERROR, "Get status returned failure\n"); status = (vx_status)VX_FAILURE; } else { /* Update return status object */ usr_data_obj = (tivx_obj_desc_user_data_object_t *)obj_desc[0U]; target_ptr = tivxMemShared2TargetPtr(&usr_data_obj->mem_ptr); tivxCheckStatus(&status, tivxMemBufferMap(target_ptr, usr_data_obj->mem_size, (vx_enum)VX_MEMORY_TYPE_HOST, (vx_enum)VX_WRITE_ONLY)); if (sizeof(tivx_display_m2m_statistics_t) == usr_data_obj->mem_size) { m2m_status_prms = (tivx_display_m2m_statistics_t *)target_ptr; m2m_status_prms->queueCount = drvObj->wbStatus.queueCount; m2m_status_prms->dequeueCount = drvObj->wbStatus.dequeueCount; m2m_status_prms->wbFrmCount = drvObj->wbStatus.wbFrmCount; m2m_status_prms->underflowCount = drvObj->wbStatus.underflowCount; } else { VX_PRINT(VX_ZONE_ERROR, "Invalid Size \n"); status = (vx_status)VX_ERROR_INVALID_PARAMETERS; } tivxCheckStatus(&status, tivxMemBufferUnmap(target_ptr, usr_data_obj->mem_size, (vx_enum)VX_MEMORY_TYPE_HOST, (vx_enum)VX_WRITE_ONLY)); } } else { VX_PRINT(VX_ZONE_ERROR, "User data object was NULL\n"); status = (vx_status)VX_FAILURE; } break; } default: { VX_PRINT(VX_ZONE_ERROR, "Invalid Command Id\n"); status = (vx_status)VX_FAILURE; break; } } } return status; } void tivxAddTargetKernelDisplayM2M(void) { vx_status status = (vx_status)VX_FAILURE; char target_name[TIVX_TARGET_MAX_NAME]; vx_enum self_cpu; VX_PRINT(VX_ZONE_ERROR, "cyhdebug1: M2M: %s:%d--------------------------------------!!!\n", __func__, __LINE__); self_cpu = tivxGetSelfCpuId(); if ( self_cpu == (vx_enum)TIVX_CPU_ID_MCU2_0 ) { strncpy(target_name, TIVX_TARGET_DISPLAY_M2M1, TIVX_TARGET_MAX_NAME); vx_display_m2m_target_kernel1 = tivxAddTargetKernelByName( TIVX_KERNEL_DISPLAY_M2M_NAME, target_name, tivxDisplayM2MProcess, tivxDisplayM2MCreate, tivxDisplayM2MDelete, tivxDisplayM2MControl, NULL); strncpy(target_name, TIVX_TARGET_DISPLAY_M2M2, TIVX_TARGET_MAX_NAME); vx_display_m2m_target_kernel2 = tivxAddTargetKernelByName( TIVX_KERNEL_DISPLAY_M2M_NAME, target_name, tivxDisplayM2MProcess, tivxDisplayM2MCreate, tivxDisplayM2MDelete, tivxDisplayM2MControl, NULL); strncpy(target_name, TIVX_TARGET_DISPLAY_M2M3, TIVX_TARGET_MAX_NAME); vx_display_m2m_target_kernel3 = tivxAddTargetKernelByName( TIVX_KERNEL_DISPLAY_M2M_NAME, target_name, tivxDisplayM2MProcess, tivxDisplayM2MCreate, tivxDisplayM2MDelete, tivxDisplayM2MControl, NULL); strncpy(target_name, TIVX_TARGET_DISPLAY_M2M4, TIVX_TARGET_MAX_NAME); vx_display_m2m_target_kernel4 = tivxAddTargetKernelByName( TIVX_KERNEL_DISPLAY_M2M_NAME, target_name, tivxDisplayM2MProcess, tivxDisplayM2MCreate, tivxDisplayM2MDelete, tivxDisplayM2MControl, NULL); status = tivxMutexCreate(&gTivxDispM2mInstObj.lock); if ((vx_status)VX_SUCCESS != status) { VX_PRINT(VX_ZONE_ERROR, "Failed to create Mutex\n"); } else { memset(&gTivxDispM2mInstObj.m2mObj, 0x0, sizeof(tivxDisplayM2MParams) * DISPLAY_M2M_MAX_HANDLES); } } } void tivxRemoveTargetKernelDisplayM2M(void) { vx_status status = (vx_status)VX_SUCCESS; VX_PRINT(VX_ZONE_ERROR, "cyhdebug13: M2M: %s:%d--------------------------------------!!!\n", __func__, __LINE__); status = tivxRemoveTargetKernel(vx_display_m2m_target_kernel1); if (status == (vx_status)VX_SUCCESS) { vx_display_m2m_target_kernel1 = NULL; } status = tivxRemoveTargetKernel(vx_display_m2m_target_kernel2); if (status == (vx_status)VX_SUCCESS) { vx_display_m2m_target_kernel2 = NULL; } status = tivxRemoveTargetKernel(vx_display_m2m_target_kernel3); if (status == (vx_status)VX_SUCCESS) { vx_display_m2m_target_kernel3 = NULL; } status = tivxRemoveTargetKernel(vx_display_m2m_target_kernel4); if (status == (vx_status)VX_SUCCESS) { vx_display_m2m_target_kernel4 = NULL; } if (NULL != gTivxDispM2mInstObj.lock) { tivxMutexDelete(&gTivxDispM2mInstObj.lock); } } static vx_status tivxDisplayM2MSetCreateParams( tivxDisplayM2MParams *prms, const tivx_obj_desc_user_data_object_t *obj_desc, const tivx_obj_desc_image_t *obj_desc_imageIn, const tivx_obj_desc_image_t *obj_desc_imageOut) { vx_status status = (vx_status)VX_SUCCESS; void *cfgPtr; tivx_display_m2m_params_t *createParams; tivxDisplayM2MDrvObj *drvObj; uint32_t pipeIdx, layerIdx; Dss_DispParams *dispParams; CSL_DssWbPipeCfg *wbPipeCfg; Dss_DctrlOverlayParams *ovrParams; Dss_DctrlOverlayLayerParams *layerParams; Fvid2_Frame *frm; VX_PRINT(VX_ZONE_ERROR, "cyhdebug12: M2M: %s:%d--------------------------------------!!!\n", __func__, __LINE__); cfgPtr = tivxMemShared2TargetPtr(&obj_desc->mem_ptr); tivxCheckStatus(&status, tivxMemBufferMap(cfgPtr, obj_desc->mem_size, (vx_enum)VX_MEMORY_TYPE_HOST, (vx_enum)VX_READ_ONLY)); if (status == (vx_status)VX_SUCCESS) { createParams = (tivx_display_m2m_params_t *)cfgPtr; VX_PRINT(VX_ZONE_ERROR, "M2M: createParams->instId: %d, numpipe: %d, overlayId: %d----------!!!\n", createParams->instId, createParams->numPipe, createParams->overlayId); memcpy(&prms->createParams, createParams, sizeof(tivx_display_m2m_params_t)); drvObj = &prms->drvObj; /* Set Driver object */ drvObj->instId = createParams->instId; drvObj->numPipe = createParams->numPipe; drvObj->overlayId = createParams->overlayId; memcpy(&drvObj->pipeId[0U], &createParams->pipeId[0U], sizeof(createParams->pipeId)); memcpy(&drvObj->pipeId[1U], &createParams->pipeId[1U], sizeof(createParams->pipeId)); } /* Initialize driver object */ if (status == (vx_status)VX_SUCCESS) { status = tivxDisplayM2MDrvStructsInit(drvObj); } /* set driver object parameters */ if (status == (vx_status)VX_SUCCESS) { /* Callback parameters */ drvObj->cbParams.cbFxn = (Fvid2_CbFxn) (&tivxDisplayM2MCallback); drvObj->cbParams.appData = drvObj; drvObj->createParams.numPipe = drvObj->numPipe; drvObj->createParams.overlayId = drvObj->overlayId; /* Set Display pipeline parameters */ for (pipeIdx = 0U ; pipeIdx < drvObj->numPipe ; pipeIdx++) { dispParams = &drvObj->pipeCfg[pipeIdx].cfgParams; drvObj->createParams.pipeId[pipeIdx] = drvObj->pipeId[pipeIdx]; drvObj->pipeCfg[pipeIdx].pipeId = drvObj->pipeId[pipeIdx]; drvObj->mFlagCfg[pipeIdx].pipeId = drvObj->pipeId[pipeIdx]; drvObj->cscCfg[pipeIdx].pipeId = drvObj->pipeId[pipeIdx]; dispParams->pipeCfg.pipeType = CSL_DSS_VID_PIPE_TYPE_VID; dispParams->layerPos.startX = 0U; dispParams->layerPos.startY = 0U; dispParams->pipeCfg.scEnable = FALSE; dispParams->alphaCfg.globalAlpha = 0xFFU; dispParams->alphaCfg.preMultiplyAlpha = FALSE; status = tivxDisplayExtractFvid2Format( obj_desc_imageIn, &dispParams->pipeCfg.inFmt); if (status == (vx_status)VX_SUCCESS) { /* Set video pipe output frame dimensions same as input as no scaling is done in video pipe-line */ dispParams->pipeCfg.outWidth = dispParams->pipeCfg.inFmt.width; dispParams->pipeCfg.outHeight = dispParams->pipeCfg.inFmt.height; } else { status = (vx_status)VX_FAILURE; VX_PRINT(VX_ZONE_ERROR, "Invalid Input Image\n"); break; } } /* Set Display WB pipeline parameters */ if (((vx_status)VX_SUCCESS == status) && (pipeIdx > 0)) { wbPipeCfg = &drvObj->wbCfg.pipeCfg; /* Set WB pipe input frame dimensions same as video pipe input/output frame, no scaling is done in video pipe, it will be done in WB pipe-line */ wbPipeCfg->inFmt.width = dispParams->pipeCfg.outWidth; wbPipeCfg->inFmt.height = dispParams->pipeCfg.outHeight; wbPipeCfg->inPos.startX = 0U; wbPipeCfg->inPos.startY = 0U; status = tivxDisplayExtractFvid2Format(obj_desc_imageOut, &wbPipeCfg->outFmt); if (status != (vx_status)VX_SUCCESS) { VX_PRINT(VX_ZONE_ERROR, "Invalid Input Image\n"); status = (vx_status)VX_FAILURE; } else { if ((wbPipeCfg->inFmt.width != wbPipeCfg->outFmt.width) || (wbPipeCfg->inFmt.height != wbPipeCfg->outFmt.height)) { wbPipeCfg->scEnable = TRUE; } } } /* Set Display WB pipeline parameters */ if ((vx_status)VX_SUCCESS == status) { ovrParams = &drvObj->ovrCfg; ovrParams->overlayId = drvObj->overlayId; ovrParams->colorbarEnable = FALSE; ovrParams->overlayCfg.colorKeyEnable = FALSE; ovrParams->overlayCfg.colorKeySel = CSL_DSS_OVERLAY_TRANS_COLOR_DEST; ovrParams->overlayCfg.backGroundColor = 0xc8c800U; layerParams = &drvObj->layerCfg; layerParams->overlayId = drvObj->overlayId; /* Set all layer to invalid first and then update only used ones */ for(layerIdx = 0U ; layerIdx < CSL_DSS_VID_PIPE_ID_MAX ; layerIdx++) { layerParams->pipeLayerNum[layerIdx] = CSL_DSS_OVERLAY_LAYER_INVALID; } /* Currently blending is not supported so only one layer is used. This code needs to updated when blending is supported. */ layerParams->pipeLayerNum[drvObj->createParams.pipeId[0U]] = CSL_DSS_OVERLAY_LAYER_NUM_0; layerParams->pipeLayerNum[drvObj->createParams.pipeId[1U]] = CSL_DSS_OVERLAY_LAYER_NUM_1; } /* Update frame-lists */ if ((vx_status)VX_SUCCESS == status) { drvObj->inFrmList.numFrames = drvObj->numPipe; for (pipeIdx = 0U ; pipeIdx < drvObj->numPipe ; pipeIdx++) { frm = (Fvid2_Frame *) &drvObj->inFrm[pipeIdx]; frm->chNum = drvObj->createParams.pipeId[pipeIdx]; drvObj->inFrmList.frames[pipeIdx] = frm; } frm = (Fvid2_Frame *) &drvObj->outFrm[0U]; drvObj->outFrmList.frames[0U] = frm; drvObj->outFrmList.numFrames = 1U; } } return status; } static vx_status tivxDisplayM2MDrvStructsInit(tivxDisplayM2MDrvObj *drvObj) { vx_status status = (vx_status)VX_SUCCESS; uint32_t loopCnt; VX_PRINT(VX_ZONE_ERROR, "cyhdebug10: M2M: %s:%d--------------------------------------!!!\n", __func__, __LINE__); /* Initialize driver create parameters */ Dss_m2mCreateParamsInit(&drvObj->createParams); /* Initialize driver call-back parameters */ Fvid2CbParams_init(&drvObj->cbParams); /* Initialize driver pipe configuration parameters */ for (loopCnt = 0U ; loopCnt < drvObj->numPipe ; loopCnt++) { Dss_dispParamsInit(&drvObj->pipeCfg[loopCnt].cfgParams); Dss_dispPipeMflagParamsInit(&drvObj->mFlagCfg[loopCnt].mFlagCfg); CSL_dssCscCoeffInit(&drvObj->cscCfg[loopCnt].csc); } /* Initialize WB pipeline parameters */ Dss_m2mPipeCfgParamsInit(&drvObj->wbCfg); CSL_dssWbPipeDmaCfgInit(&drvObj->wbDmaCfg); Dss_m2mMFlagParamsInit(&drvObj->wbMflagCfg); CSL_dssCscCoeffInit(&drvObj->wbCscCfg); Dss_m2mStatusInit(&drvObj->wbStatus); /* Initialize Display overlay parameters */ Dss_dctrlOverlayParamsInit(&drvObj->ovrCfg); Dss_dctrlOverlayLayerParamsInit(&drvObj->layerCfg); /* Initialize Display global parameters */ Dss_dctrlGlobalDssParamsInit(&drvObj->globalParams); /* Initialize input and output frame lists */ Fvid2FrameList_init(&drvObj->inFrmList); Fvid2FrameList_init(&drvObj->outFrmList); return status; } static vx_status tivxDisplayM2MDrvCfg(tivxDisplayM2MDrvObj *drvObj) { vx_status status = (vx_status)VX_SUCCESS; uint32_t loopCnt; int32_t fvid2_status = FVID2_SOK; VX_PRINT(VX_ZONE_ERROR, "cyhdebug9: M2M: %s:%d--------------------------------------!!!\n", __func__, __LINE__); /* Display M2M Driver create */ drvObj->drvHandle = Fvid2_create(DSS_M2M_DRV_ID, drvObj->instId, &drvObj->createParams, &drvObj->createStatus, &drvObj->cbParams); if((NULL == drvObj->drvHandle) || (drvObj->createStatus.retVal != FVID2_SOK)) { VX_PRINT(VX_ZONE_ERROR, ": Display M2M Create Failed!!!\r\n"); status = (vx_status)VX_FAILURE; } /* Display M2M pipe configuration */ if ((vx_status)VX_SUCCESS == status) { for (loopCnt = 0U ; loopCnt < drvObj->numPipe ; loopCnt++) { fvid2_status += Fvid2_control(drvObj->drvHandle, IOCTL_DSS_M2M_SET_PIPE_PARAMS, &drvObj->pipeCfg[loopCnt], NULL); VX_PRINT(VX_ZONE_ERROR, ": Display M2M DISP IOCTL: loopCnt1: %d, status = %d\r\n", loopCnt, fvid2_status); fvid2_status += Fvid2_control(drvObj->drvHandle, IOCTL_DSS_M2M_SET_PIPE_MFLAG_PARAMS, &drvObj->mFlagCfg[loopCnt], NULL); VX_PRINT(VX_ZONE_ERROR, ": Display M2M DISP IOCTL: loopCnt1: %d, status = %d\r\n", loopCnt, fvid2_status); if (FVID2_SOK != fvid2_status) { VX_PRINT(VX_ZONE_ERROR, ": Display M2M DISP IOCTL Failed!!! loopCnt1: %d\r\n", loopCnt); status = (vx_status)VX_FAILURE; break; } } } /* Display M2M overlay configuration */ if ((vx_status)VX_SUCCESS == status) { fvid2_status += Fvid2_control(drvObj->drvHandle, IOCTL_DSS_DCTRL_SET_OVERLAY_PARAMS, &drvObj->ovrCfg, NULL); fvid2_status += Fvid2_control(drvObj->drvHandle, IOCTL_DSS_DCTRL_SET_LAYER_PARAMS, &drvObj->layerCfg, NULL); if (FVID2_SOK != fvid2_status) { VX_PRINT(VX_ZONE_ERROR, ": Display M2M Overlay IOCTL Failed!!!\r\n"); status = (vx_status)VX_FAILURE; } } /* Display M2M global configuration */ if ((vx_status)VX_SUCCESS == status) { fvid2_status += Fvid2_control(drvObj->drvHandle, IOCTL_DSS_DCTRL_SET_GLOBAL_DSS_PARAMS, &drvObj->globalParams, NULL); if (FVID2_SOK != fvid2_status) { VX_PRINT(VX_ZONE_ERROR, ": Display M2M Global IOCTL Failed!!!\r\n"); status = (vx_status)VX_FAILURE; } } /* Display M2M write-back pipe configuration */ if ((vx_status)VX_SUCCESS == status) { fvid2_status += Fvid2_control(drvObj->drvHandle, IOCTL_DSS_M2M_SET_WB_PIPE_PARAMS, &drvObj->wbCfg, NULL); fvid2_status += Fvid2_control(drvObj->drvHandle, IOCTL_DSS_M2M_SET_WB_PIPE_MFLAG_PARAMS, &drvObj->wbMflagCfg, NULL); fvid2_status += Fvid2_control(drvObj->drvHandle, IOCTL_DSS_M2M_SET_WB_PIPE_DMA_CFG, &drvObj->wbDmaCfg, NULL); if (FVID2_SOK != fvid2_status) { VX_PRINT(VX_ZONE_ERROR, ": Display M2M WB IOCTL Failed!!!\r\n"); status = (vx_status)VX_FAILURE; } } /* Start Display M2M Driver */ if ((vx_status)VX_SUCCESS == status) { fvid2_status = Fvid2_start(drvObj->drvHandle, NULL); if (FVID2_SOK != fvid2_status) { VX_PRINT(VX_ZONE_ERROR, ": Display M2M Driver Start Failed!!!\r\n"); status = (vx_status)VX_FAILURE; } } return status; } static int32_t tivxDisplayM2MCallback(Fvid2_Handle handle, void *appData) { tivxDisplayM2MDrvObj *drvObj = (tivxDisplayM2MDrvObj *)(appData); VX_PRINT(VX_ZONE_ERROR, "cyhdebug5: M2M: %s:%d--------------------------------------!!!\n", __func__, __LINE__); if ((NULL != drvObj) && (drvObj->waitForProcessCmpl != NULL)) { tivxEventPost(drvObj->waitForProcessCmpl); } return (vx_status)VX_SUCCESS; } static vx_status tivxDisplayExtractFvid2Format( const tivx_obj_desc_image_t *obj_desc_img, Fvid2_Format *format) { vx_status status = (vx_status)VX_SUCCESS; Fvid2Format_init(format); format->width = obj_desc_img->imagepatch_addr[0].dim_x; format->height = obj_desc_img->imagepatch_addr[0].dim_y; format->ccsFormat = FVID2_CCSF_BITS8_PACKED; format->scanFormat = FVID2_SF_PROGRESSIVE; VX_PRINT(VX_ZONE_ERROR, "cyhdebug4: M2M: %s:%d--------------------------------------!!!\n", __func__, __LINE__); switch (obj_desc_img->format) { case (vx_df_image)TIVX_DF_IMAGE_RGB565: format->dataFormat = FVID2_DF_BGR16_565; format->pitch[FVID2_RGB_ADDR_IDX] = (uint32_t)obj_desc_img->imagepatch_addr[0].stride_y; break; case (vx_df_image)VX_DF_IMAGE_RGB: format->dataFormat = FVID2_DF_RGB24_888; format->pitch[FVID2_RGB_ADDR_IDX] = (uint32_t)obj_desc_img->imagepatch_addr[0].stride_y; break; case (vx_df_image)VX_DF_IMAGE_RGBX: VX_PRINT(VX_ZONE_ERROR, "debug: -----------------------------choose VX_DF_IMAGE_RGBX"); format->dataFormat = FVID2_DF_BGRX24_8888; format->pitch[FVID2_RGB_ADDR_IDX] = (uint32_t)obj_desc_img->imagepatch_addr[0].stride_y; break; case (vx_df_image)TIVX_DF_IMAGE_BGRX: format->dataFormat = FVID2_DF_BGRX24_8888; format->pitch[FVID2_RGB_ADDR_IDX] = (uint32_t)obj_desc_img->imagepatch_addr[0].stride_y; break; case (vx_df_image)VX_DF_IMAGE_UYVY: format->dataFormat = FVID2_DF_YUV422I_UYVY; format->pitch[FVID2_YUV_INT_ADDR_IDX] = (uint32_t)obj_desc_img->imagepatch_addr[0].stride_y; break; case (vx_df_image)VX_DF_IMAGE_YUYV: format->dataFormat = FVID2_DF_YUV422I_YUYV; format->pitch[FVID2_YUV_INT_ADDR_IDX] = (uint32_t)obj_desc_img->imagepatch_addr[0].stride_y; break; case (vx_df_image)VX_DF_IMAGE_NV12: format->dataFormat = FVID2_DF_YUV420SP_UV; format->pitch[FVID2_YUV_SP_Y_ADDR_IDX] = (uint32_t)obj_desc_img->imagepatch_addr[0].stride_y; format->pitch[FVID2_YUV_SP_CBCR_ADDR_IDX] = (uint32_t)obj_desc_img->imagepatch_addr[1].stride_y; break; case (vx_df_image)VX_DF_IMAGE_U16: format->ccsFormat = FVID2_CCSF_BITS12_UNPACKED16; format->dataFormat = FVID2_DF_YUV420SP_UV; format->pitch[FVID2_YUV_SP_Y_ADDR_IDX] = (uint32_t)obj_desc_img->imagepatch_addr[0].stride_y; format->pitch[FVID2_YUV_SP_CBCR_ADDR_IDX] = (uint32_t)obj_desc_img->imagepatch_addr[0].stride_y; break; case (vx_df_image)VX_DF_IMAGE_U8: format->ccsFormat = FVID2_CCSF_BITS8_PACKED; format->dataFormat = FVID2_DF_YUV420SP_UV; format->pitch[FVID2_YUV_SP_Y_ADDR_IDX] = (uint32_t)obj_desc_img->imagepatch_addr[0].stride_y; format->pitch[FVID2_YUV_SP_CBCR_ADDR_IDX] = (uint32_t)obj_desc_img->imagepatch_addr[0].stride_y; break; default: status = (vx_status)VX_FAILURE; break; } return status; } static tivxDisplayM2MParams *tivxDispM2mAllocObject(tivxDisplayM2MInstObj *instObj) { uint32_t cnt; tivxDisplayM2MParams *m2mObj = NULL; VX_PRINT(VX_ZONE_ERROR, "cyhdebug2: M2M: %s:%d--------------------------------------!!!\n", __func__, __LINE__); /* Lock instance mutex */ tivxMutexLock(instObj->lock); for (cnt = 0U; cnt < DISPLAY_M2M_MAX_HANDLES; cnt ++) { if (0U == instObj->m2mObj[cnt].isAlloc) { m2mObj = &instObj->m2mObj[cnt]; memset(m2mObj, 0x0, sizeof(tivxDisplayM2MParams)); instObj->m2mObj[cnt].isAlloc = 1U; break; } } /* Release instance mutex */ tivxMutexUnlock(instObj->lock); return (m2mObj); } static void tivxDispM2mFreeObject(tivxDisplayM2MInstObj *instObj, tivxDisplayM2MParams *m2mObj) { uint32_t cnt; VX_PRINT(VX_ZONE_ERROR, "cyhdebug3: M2M: %s:%d--------------------------------------!!!\n", __func__, __LINE__); /* Lock instance mutex */ tivxMutexLock(instObj->lock); for (cnt = 0U; cnt < DISPLAY_M2M_MAX_HANDLES; cnt ++) { if (m2mObj == &instObj->m2mObj[cnt]) { m2mObj->isAlloc = 0U; break; } } /* Release instance mutex */ tivxMutexUnlock(instObj->lock); }
/* * Copyright (c) Texas Instruments Incorporated 2022 * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 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. * * Neither the name of Texas Instruments Incorporated 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. */ /** * \file dss_m2mDisp.c * * \brief File containing the DSS M2M driver DSS_DISP APIs. * */ /* ========================================================================== */ /* Include Files */ /* ========================================================================== */ #include <ti/drv/dss/dss.h> #include <ti/drv/dss/src/drv/common/dss_evtMgr.h> #include <ti/drv/dss/src/drv/disp/dss_dispDrv.h> #include <ti/drv/dss/src/drv/disp/dss_dispPriv.h> #include <ti/drv/dss/src/drv/dctrl/dss_dctrlDrv.h> #include <ti/drv/dss/src/drv/dctrl/dss_dctrlPriv.h> #include <ti/drv/dss/src/drv/m2m/dss_m2mDrv.h> #include <dss_soc_priv.h> /* ========================================================================== */ /* Macros & Typedefs */ /* ========================================================================== */ /* None */ /* ========================================================================== */ /* Structure Declarations */ /* ========================================================================== */ /* None */ /* ========================================================================== */ /* Function Declarations */ /* ========================================================================== */ /* Returns TRUE if instance and channel/context configurations matches, returns FALSE otherwise */ uint32_t Dss_m2mDrvDispPipeCfgChk(const Dss_DispParams *instCfg, const Dss_DispParams *progCfg); /* Returns TRUE if instance and channel/context configurations matches, returns FALSE otherwise */ uint32_t Dss_m2mDrvDispMFlagCfgChk(const Dss_DispPipeMflagParams *instCfg, const Dss_DispPipeMflagParams *progCfg); /* Returns TRUE if instance and channel/context configurations matches, returns FALSE otherwise */ uint32_t Dss_m2mDrvDispCscCfgChk(const CSL_DssCscCoeff *instCfg, const CSL_DssCscCoeff *progCfg); int32_t Dss_m2mDrvPrgramDisp(DssM2MDrv_VirtContext *context); /* * Display IOCTLs */ static int32_t Dss_m2mDrvValidateDispParams(DssM2MDrv_InstObj *instObj, const Dss_PipeCfgParams *pipeCfg); int32_t Dss_m2mDrvIoctlSetDssPipeParams(DssM2MDrv_VirtContext *context, const Dss_PipeCfgParams *pipeCfg); int32_t Dss_m2mDrvIoctlSetPipeMflagParams(DssM2MDrv_VirtContext *context, const Dss_PipeMflagParams *mFlagParams); int32_t Dss_m2mDrvIoctlSetPipeCsc(DssM2MDrv_VirtContext *context, const Dss_PipeCscParams *csc); /* ========================================================================== */ /* Global Variables */ /* ========================================================================== */ /* ========================================================================== */ /* Function Definitions */ /* ========================================================================== */ uint32_t Dss_m2mDrvDispPipeCfgChk(const Dss_DispParams *instCfg, const Dss_DispParams *progCfg) { uint32_t retVal = (uint32_t) TRUE; uint32_t loopCnt = 0U; /* check for Pipe configurations */ if ((instCfg->pipeCfg.pipeType != progCfg->pipeCfg.pipeType) || (instCfg->pipeCfg.pixelInc != progCfg->pipeCfg.pixelInc) || (instCfg->pipeCfg.yuvAlign != progCfg->pipeCfg.yuvAlign) || (instCfg->pipeCfg.outWidth != progCfg->pipeCfg.outWidth) || (instCfg->pipeCfg.outHeight != progCfg->pipeCfg.outHeight) || (instCfg->pipeCfg.scEnable != progCfg->pipeCfg.scEnable) || (instCfg->pipeCfg.cscRange != progCfg->pipeCfg.cscRange) || (instCfg->pipeCfg.flipType != progCfg->pipeCfg.flipType) || (instCfg->pipeCfg.nibbleModeEnable != progCfg->pipeCfg.nibbleModeEnable) || (instCfg->pipeCfg.gammaEnable != progCfg->pipeCfg.gammaEnable) || (instCfg->pipeCfg.inFmt.width != progCfg->pipeCfg.inFmt.width) || (instCfg->pipeCfg.inFmt.height != progCfg->pipeCfg.inFmt.height) || (instCfg->pipeCfg.inFmt.pitch != progCfg->pipeCfg.inFmt.pitch) || (instCfg->pipeCfg.inFmt.dataFormat != progCfg->pipeCfg.inFmt.dataFormat) || (instCfg->pipeCfg.inFmt.scanFormat != progCfg->pipeCfg.inFmt.scanFormat) || (instCfg->pipeCfg.inFmt.ccsFormat != progCfg->pipeCfg.inFmt.ccsFormat) || (instCfg->pipeCfg.inFmt.fieldMerged != progCfg->pipeCfg.inFmt.fieldMerged)) { retVal = (uint32_t) FALSE; } else { for (loopCnt = 0U ; loopCnt < CSL_DSS_NUM_LUT_ENTRIES ; loopCnt++) { if (instCfg->pipeCfg.clutData[loopCnt] != progCfg->pipeCfg.clutData[loopCnt]) { break; } } if (loopCnt < CSL_DSS_NUM_LUT_ENTRIES) { retVal = (uint32_t) FALSE; } } /* check for DMA configurations */ if (retVal == ((uint32_t) TRUE)) { if ((instCfg->dmaCfg.bufPreloadControl != progCfg->dmaCfg.bufPreloadControl) || (instCfg->dmaCfg.preloadVal != progCfg->dmaCfg.preloadVal) || (instCfg->dmaCfg.bufLowThreshold != progCfg->dmaCfg.bufLowThreshold) || (instCfg->dmaCfg.bufHighThreshold != progCfg->dmaCfg.bufHighThreshold) || (instCfg->dmaCfg.selfRefreshControl != progCfg->dmaCfg.selfRefreshControl) || (instCfg->dmaCfg.selfRefreshEnable != progCfg->dmaCfg.selfRefreshEnable) || (instCfg->dmaCfg.arbitration != progCfg->dmaCfg.arbitration)) { retVal = (uint32_t) FALSE; } } /* check for Alpha configurations */ if (retVal == ((uint32_t) TRUE)) { if ((instCfg->alphaCfg.globalAlpha != progCfg->alphaCfg.globalAlpha) || (instCfg->alphaCfg.preMultiplyAlpha != progCfg->alphaCfg.preMultiplyAlpha)) { retVal = (uint32_t) FALSE; } } /* check for VC1 configurations */ if (retVal == ((uint32_t) TRUE)) { if ((instCfg->vc1Cfg.vc1Enable != progCfg->vc1Cfg.vc1Enable) || (instCfg->vc1Cfg.rangeY != progCfg->vc1Cfg.rangeY) || (instCfg->vc1Cfg.rangeUV != progCfg->vc1Cfg.rangeUV)) { retVal = (uint32_t) FALSE; } } /* check for Crop configurations */ if (retVal == ((uint32_t) TRUE)) { if ((instCfg->cropParams.cropEnable != progCfg->cropParams.cropEnable) || (instCfg->cropParams.cropCfg.cropTop != progCfg->cropParams.cropCfg.cropTop) || (instCfg->cropParams.cropCfg.cropBottom != progCfg->cropParams.cropCfg.cropBottom) || (instCfg->cropParams.cropCfg.cropLeft != progCfg->cropParams.cropCfg.cropLeft) || (instCfg->cropParams.cropCfg.cropRight != progCfg->cropParams.cropCfg.cropRight)) { retVal = (uint32_t) FALSE; } } /* check for Layer configurations */ if (retVal == ((uint32_t) TRUE)) { if ((instCfg->layerPos.startX != progCfg->layerPos.startX) || (instCfg->layerPos.startY != progCfg->layerPos.startY)) { retVal = (uint32_t) FALSE; } } return retVal; } uint32_t Dss_m2mDrvDispMFlagCfgChk(const Dss_DispPipeMflagParams *instCfg, const Dss_DispPipeMflagParams *progCfg) { uint32_t retVal = (uint32_t) TRUE; if ((instCfg->mflagCfg.thresholdLow != progCfg->mflagCfg.thresholdLow) || (instCfg->mflagCfg.thresholdHigh != progCfg->mflagCfg.thresholdHigh)) { retVal = (uint32_t) FALSE; } return retVal; } uint32_t Dss_m2mDrvDispCscCfgChk(const CSL_DssCscCoeff *instCfg, const CSL_DssCscCoeff *progCfg) { uint32_t retVal = (uint32_t) TRUE; if ((instCfg->cscRange != progCfg->cscRange) || (instCfg->c00 != progCfg->c00) || (instCfg->c01 != progCfg->c01) || (instCfg->c02 != progCfg->c02) || (instCfg->c10 != progCfg->c10) || (instCfg->c11 != progCfg->c11) || (instCfg->c12 != progCfg->c12) || (instCfg->c20 != progCfg->c20) || (instCfg->c21 != progCfg->c21) || (instCfg->c22 != progCfg->c22) || (instCfg->preOffset1 != progCfg->preOffset1) || (instCfg->preOffset2 != progCfg->preOffset2) || (instCfg->preOffset3 != progCfg->preOffset3) || (instCfg->postOffset1 != progCfg->postOffset1) || (instCfg->postOffset2 != progCfg->postOffset2) || (instCfg->postOffset3 != progCfg->postOffset3)) { retVal = (uint32_t) FALSE; } return retVal; } int32_t Dss_m2mDrvPrgramDisp(DssM2MDrv_VirtContext *context) { int32_t retVal = FVID2_SOK; uint32_t copyCfg = (uint32_t) FALSE; uint32_t layerNum, pipeIdx; DssM2MDrv_InstObj *instObj; DssM2MDrv_DispPipeCfg *instCfg, *progCfg; CSL_DssOverlayPipePosCfg overlayPosCfg; instObj = context->instObj; for (pipeIdx = 0U ; pipeIdx < context->numPipe ; pipeIdx++) { instCfg = &context->instCfg.pipeCfg[context->pipeId[pipeIdx]]; progCfg = &instObj->progCfg.pipeCfg[context->pipeId[pipeIdx]]; /* Re-program DSS pipe only if channel/instance configurations are different than programmed */ if (FVID2_SOK == retVal) { /* Check DSS Pipeline configuration */ if (((uint32_t) FALSE) == Dss_m2mDrvDispPipeCfgChk(&instCfg->cfgParams, &progCfg->cfgParams)) { if (FVID2_SOK == retVal) { /* Program: DSS Pipeline */ retVal = CSL_dssVidPipeSetConfig(instObj->pipeRegs[context->pipeId[pipeIdx]], (const CSL_DssVidPipeCfg *)(&instCfg->cfgParams.pipeCfg), (const CSL_DssVidPipeVC1Cfg *)(&instCfg->cfgParams.vc1Cfg)); } if (FVID2_SOK == retVal) { /* Program: DMA, Alpha, Crop, Layer configurations */ CSL_dssVidPipeSetDmaConfig(instObj->pipeRegs[context->pipeId[pipeIdx]], (const CSL_DssVidPipeDmaCfg *)(&instCfg->cfgParams.dmaCfg)); CSL_dssVidPipeSetAlphaConfig(instObj->pipeRegs[context->pipeId[pipeIdx]], (const CSL_DssVidPipeAlphaCfg *)(&instCfg->cfgParams.alphaCfg)); #if defined (SOC_J721E) || defined (SOC_J721S2) CSL_dssVidPipeSetCropConfig(instObj->pipeRegs[context->pipeId[pipeIdx]], (const Fvid2_EdgeCropConfig *)(&instCfg->cfgParams.cropParams.cropCfg), instCfg->cfgParams.cropParams.cropEnable); #endif layerNum = CSL_dssOverlayGetEnabledPipeLayerNum(instObj->ovrRegs, context->pipeId[pipeIdx]); GT_assert(DssTrace, (layerNum < CSL_DSS_OVERLAY_LAYER_MAX)); overlayPosCfg.layerPos.startX = instCfg->cfgParams.layerPos.startX; overlayPosCfg.layerPos.startY = instCfg->cfgParams.layerPos.startY; CSL_dssOverlaySetPipePosConfig(instObj->ovrRegs, (const CSL_DssOverlayPipePosCfg *)(&overlayPosCfg), layerNum); } if (FVID2_SOK == retVal) { copyCfg = (uint32_t) TRUE; } } } if (FVID2_SOK == retVal) { /* Check DSS Pipeline MFlag configuration */ if (((uint32_t) FALSE) == Dss_m2mDrvDispMFlagCfgChk(&instCfg->mFlagParams, &progCfg->mFlagParams)) { if (FVID2_SOK == retVal) { /* Program: DSS Pipeline MFlag */ CSL_dssVidPipeSetMflagConfig(instObj->pipeRegs[context->pipeId[pipeIdx]], (const CSL_DssVidPipeMFlagCfg *)(&instCfg->mFlagParams.mflagCfg)); copyCfg = (uint32_t) TRUE; } } } if (FVID2_SOK == retVal) { /* Check DSS Pipeline Csc configuration */ if (((uint32_t) FALSE) == Dss_m2mDrvDispCscCfgChk(&instCfg->cscCoeff, &progCfg->cscCoeff)) { if (FVID2_SOK == retVal) { /* Program: DSS Pipeline Csc */ CSL_dssVidPipeSetCSCCoeff(instObj->pipeRegs[context->pipeId[pipeIdx]], (const CSL_DssCscCoeff *)(&instCfg->cscCoeff)); copyCfg = (uint32_t) TRUE; } } } if ((FVID2_SOK == retVal) && (((uint32_t) TRUE) == copyCfg)) { /* Update instance configurations */ Fvid2Utils_memcpy(progCfg, instCfg, sizeof(DssM2MDrv_DispPipeCfg)); } } return retVal; } static int32_t Dss_m2mDrvValidateDispParams(DssM2MDrv_InstObj *instObj, const Dss_PipeCfgParams *pipeCfg) { int32_t retVal = FVID2_SOK; const Dss_DispParams *dispParams; dispParams = &pipeCfg->cfgParams; /* Not Checked: Interlaced to progressive or vice versa, not supported in M2M */ /* Scaling ratio check */ if(((dispParams->pipeCfg.inFmt.height * 16U) < (dispParams->pipeCfg.outHeight)) || ((dispParams->pipeCfg.inFmt.width * 16U) < (dispParams->pipeCfg.outWidth))) { GT_0trace(DssTrace, GT_ERR, "M2M: Upscaling ratio is more than 16x \r\n"); retVal = FVID2_EINVALID_PARAMS; } if(((dispParams->pipeCfg.inFmt.height) > (dispParams->pipeCfg.outHeight * 4U)) || ((dispParams->pipeCfg.inFmt.width) > (dispParams->pipeCfg.outWidth * 4U))) { GT_0trace(DssTrace, GT_ERR, "M2M: Downscaling ratio is more than 0.25x \r\n"); retVal = FVID2_EINVALID_PARAMS; } GT_2trace(DssTrace, GT_ERR, "cyhdebug: M2M: in_h:%d, in_w:%d\r\n", dispParams->pipeCfg.inFmt.height, dispParams->pipeCfg.inFmt.width); GT_2trace(DssTrace, GT_ERR, "cyhdebug: M2M: out_h:%d, out_w:%d\r\n", dispParams->pipeCfg.outHeight, dispParams->pipeCfg.outWidth); if((dispParams->pipeCfg.inFmt.height != dispParams->pipeCfg.outHeight) || (dispParams->pipeCfg.inFmt.width != dispParams->pipeCfg.outWidth)) { if(TRUE == Dss_dispIsVidLInst(pipeCfg->pipeId)) { GT_0trace(DssTrace, GT_ERR, "M2M: Scaling cant be enabled for video lite pipe \r\n"); retVal = FVID2_EINVALID_PARAMS; } if(FALSE == dispParams->pipeCfg.scEnable) { GT_0trace(DssTrace, GT_ERR, "M2M: Scaling should be enabled \r\n"); retVal = FVID2_EINVALID_PARAMS; } } if((dispParams->cropParams.cropCfg.cropTop >= 32U) || (dispParams->cropParams.cropCfg.cropBottom >= 32U) || (dispParams->cropParams.cropCfg.cropLeft >= 32U) || (dispParams->cropParams.cropCfg.cropRight >= 32U)) { GT_0trace(DssTrace, GT_ERR, "M2M: Crop Parameter(s) should be less than 32 \r\n"); retVal = FVID2_EINVALID_PARAMS; } if(((dispParams->pipeCfg.flipType == FVID2_FLIP_TYPE_V) || (dispParams->pipeCfg.flipType == FVID2_FLIP_TYPE_H)) && ((dispParams->pipeCfg.inFmt.dataFormat == FVID2_DF_RGB24_888) || (dispParams->pipeCfg.inFmt.dataFormat == FVID2_DF_BGR24_888))) { GT_0trace(DssTrace, GT_ERR, "M2M: Flip Parameter(s) should not be used for 24-bit RGB/BGR formats \r\n"); retVal = FVID2_EINVALID_PARAMS; } /* There is a limitation with scaling in DSS, where maximum scaling ratio * supported is the ratio of the DSS functional clock and Pixel Clock. * Driver can't check this condition as it is unaware of Pixel Clock. * So it should be checked by the application. */ return retVal; } int32_t Dss_m2mDrvIoctlSetDssPipeParams(DssM2MDrv_VirtContext *context, const Dss_PipeCfgParams *pipeCfg) { int32_t retVal = FVID2_SOK; /* check for parameters */ if (NULL == pipeCfg) { retVal = FVID2_EBADARGS; } else if (pipeCfg->pipeId >= CSL_DSS_VID_PIPE_ID_MAX) { retVal = FVID2_EBADARGS; } else { retVal = Dss_m2mDrvValidateDispParams(context->instObj, pipeCfg); if (retVal == FVID2_SOK) { /* upgrade configurations into context object and re-program HW module on buffer submission */ Fvid2Utils_memcpy(&context->instCfg.pipeCfg[pipeCfg->pipeId].cfgParams, &pipeCfg->cfgParams, sizeof(Dss_DispParams)); } } return retVal; } int32_t Dss_m2mDrvIoctlSetPipeMflagParams(DssM2MDrv_VirtContext *context, const Dss_PipeMflagParams *mFlagParams) { int32_t retVal = FVID2_SOK; /* check for parameters */ if (NULL == mFlagParams) { retVal = FVID2_EBADARGS; } else if (mFlagParams->pipeId >= CSL_DSS_VID_PIPE_ID_MAX) { retVal = FVID2_EBADARGS; } else { /* upgrade configurations into context object and re-program HW module on buffer submission */ Fvid2Utils_memcpy(&context->instCfg.pipeCfg[mFlagParams->pipeId].mFlagParams, &mFlagParams->mFlagCfg, sizeof(Dss_DispPipeMflagParams)); } return retVal; } int32_t Dss_m2mDrvIoctlSetPipeCsc(DssM2MDrv_VirtContext *context, const Dss_PipeCscParams *csc) { int32_t retVal = FVID2_SOK; /* check for parameters */ if (NULL == csc) { retVal = FVID2_EBADARGS; } else if (csc->pipeId >= CSL_DSS_VID_PIPE_ID_MAX) { retVal = FVID2_EBADARGS; } else { /* upgrade configurations into context object and re-program HW module on buffer submission */ Fvid2Utils_memcpy(&context->instCfg.pipeCfg[csc->pipeId].cscCoeff, &csc->csc, sizeof(CSL_DssCscCoeff)); } return retVal; }
log file: MobaXterm_COM3ProlificUSB-to-SerialCommPortCOM3_20230329_153625.txt
I think I have forgot to initialize somewhere.
Regards.
Hi xie jc,
Can you please wait for a week? Let me first check it on EVM and then share you the exact changes.
Regards,
Brijesh
Hi xie jc,
Please find attached list of patches, which allows to use two video pipelines in the DSS M2M node.
1, PDK_DSS_M2M.patch: This patch needs to be applied on top of ti-processor-sdk-rtos-j721e-evm-08_06_00_12\pdk_jacinto_08_06_00_31 folder. This contains simple change in the DSS M2M driver to allow at max two input video pipelines. I also have updated PDK DSS M2M example to use two video pipelines.
/cfs-file/__key/communityserver-discussions-components-files/791/PDK_5F00_DSS_5F00_M2M.patch
2, TIOVX_DSS_M2M.patch: This patch needs to be applied on ti-processor-sdk-rtos-j721e-evm-08_06_00_12\tiovx folder. This patch modifies DSS M2M node and it can now accept two input images for the two input video pipelines..
/cfs-file/__key/communityserver-discussions-components-files/791/TIOVX_5F00_DSS_5F00_M2M.patch
3, VAPPS_DSS_M2M.patch: This patch needs to be applied on ti-processor-sdk-rtos-j721e-evm-08_06_00_12\vision_apps. This contains simple change of connecting two VIDL pipelines to the overlay which is used for DSS M2M path.
/cfs-file/__key/communityserver-discussions-components-files/791/VAPPS_5F00_DSS_5F00_M2M.patch
Can you please try with these changes?
Regards,
Brijesh