diff --git a/exynos4/multimedia/Android.mk b/exynos/multimedia/Android.mk similarity index 100% rename from exynos4/multimedia/Android.mk rename to exynos/multimedia/Android.mk diff --git a/exynos4/multimedia/codecs/Android.mk b/exynos/multimedia/codecs/Android.mk similarity index 100% rename from exynos4/multimedia/codecs/Android.mk rename to exynos/multimedia/codecs/Android.mk diff --git a/exynos4/multimedia/codecs/sec_codecs/audio/Android.mk b/exynos/multimedia/codecs/audio/Android.mk similarity index 100% rename from exynos4/multimedia/codecs/sec_codecs/audio/Android.mk rename to exynos/multimedia/codecs/audio/Android.mk diff --git a/exynos4/multimedia/codecs/sec_codecs/audio/exynos4/Android.mk b/exynos/multimedia/codecs/audio/exynos4/Android.mk similarity index 100% rename from exynos4/multimedia/codecs/sec_codecs/audio/exynos4/Android.mk rename to exynos/multimedia/codecs/audio/exynos4/Android.mk diff --git a/exynos4/multimedia/codecs/sec_codecs/audio/exynos4/srp/alp/Android.mk b/exynos/multimedia/codecs/audio/exynos4/srp/alp/Android.mk similarity index 100% rename from exynos4/multimedia/codecs/sec_codecs/audio/exynos4/srp/alp/Android.mk rename to exynos/multimedia/codecs/audio/exynos4/srp/alp/Android.mk diff --git a/exynos4/multimedia/codecs/sec_codecs/audio/exynos4/srp/alp/include/srp_api.h b/exynos/multimedia/codecs/audio/exynos4/srp/alp/include/srp_api.h similarity index 100% rename from exynos4/multimedia/codecs/sec_codecs/audio/exynos4/srp/alp/include/srp_api.h rename to exynos/multimedia/codecs/audio/exynos4/srp/alp/include/srp_api.h diff --git a/exynos4/multimedia/codecs/sec_codecs/audio/exynos4/srp/alp/include/srp_error.h b/exynos/multimedia/codecs/audio/exynos4/srp/alp/include/srp_error.h similarity index 100% rename from exynos4/multimedia/codecs/sec_codecs/audio/exynos4/srp/alp/include/srp_error.h rename to exynos/multimedia/codecs/audio/exynos4/srp/alp/include/srp_error.h diff --git a/exynos4/multimedia/codecs/sec_codecs/audio/exynos4/srp/alp/include/srp_ioctl.h b/exynos/multimedia/codecs/audio/exynos4/srp/alp/include/srp_ioctl.h similarity index 100% rename from exynos4/multimedia/codecs/sec_codecs/audio/exynos4/srp/alp/include/srp_ioctl.h rename to exynos/multimedia/codecs/audio/exynos4/srp/alp/include/srp_ioctl.h diff --git a/exynos4/multimedia/codecs/sec_codecs/audio/exynos4/srp/alp/src/srp_api.c b/exynos/multimedia/codecs/audio/exynos4/srp/alp/src/srp_api.c similarity index 100% rename from exynos4/multimedia/codecs/sec_codecs/audio/exynos4/srp/alp/src/srp_api.c rename to exynos/multimedia/codecs/audio/exynos4/srp/alp/src/srp_api.c diff --git a/exynos4/multimedia/codecs/sec_codecs/audio/exynos4/srp/libsa_jni/Android.mk b/exynos/multimedia/codecs/audio/exynos4/srp/libsa_jni/Android.mk similarity index 100% rename from exynos4/multimedia/codecs/sec_codecs/audio/exynos4/srp/libsa_jni/Android.mk rename to exynos/multimedia/codecs/audio/exynos4/srp/libsa_jni/Android.mk diff --git a/exynos4/multimedia/codecs/sec_codecs/audio/exynos4/srp/libsa_jni/SACtrl.c b/exynos/multimedia/codecs/audio/exynos4/srp/libsa_jni/SACtrl.c similarity index 100% rename from exynos4/multimedia/codecs/sec_codecs/audio/exynos4/srp/libsa_jni/SACtrl.c rename to exynos/multimedia/codecs/audio/exynos4/srp/libsa_jni/SACtrl.c diff --git a/exynos4/multimedia/codecs/sec_codecs/audio/exynos4/srp/ulp/Android.mk b/exynos/multimedia/codecs/audio/exynos4/srp/ulp/Android.mk similarity index 100% rename from exynos4/multimedia/codecs/sec_codecs/audio/exynos4/srp/ulp/Android.mk rename to exynos/multimedia/codecs/audio/exynos4/srp/ulp/Android.mk diff --git a/exynos4/multimedia/codecs/sec_codecs/audio/exynos4/srp/ulp/include/srp_api.h b/exynos/multimedia/codecs/audio/exynos4/srp/ulp/include/srp_api.h similarity index 100% rename from exynos4/multimedia/codecs/sec_codecs/audio/exynos4/srp/ulp/include/srp_api.h rename to exynos/multimedia/codecs/audio/exynos4/srp/ulp/include/srp_api.h diff --git a/exynos4/multimedia/codecs/sec_codecs/audio/exynos4/srp/ulp/include/srp_api_ctrl.h b/exynos/multimedia/codecs/audio/exynos4/srp/ulp/include/srp_api_ctrl.h similarity index 100% rename from exynos4/multimedia/codecs/sec_codecs/audio/exynos4/srp/ulp/include/srp_api_ctrl.h rename to exynos/multimedia/codecs/audio/exynos4/srp/ulp/include/srp_api_ctrl.h diff --git a/exynos4/multimedia/codecs/sec_codecs/audio/exynos4/srp/ulp/include/srp_ioctl.h b/exynos/multimedia/codecs/audio/exynos4/srp/ulp/include/srp_ioctl.h similarity index 100% rename from exynos4/multimedia/codecs/sec_codecs/audio/exynos4/srp/ulp/include/srp_ioctl.h rename to exynos/multimedia/codecs/audio/exynos4/srp/ulp/include/srp_ioctl.h diff --git a/exynos4/multimedia/codecs/sec_codecs/audio/exynos4/srp/ulp/src/srp_api.c b/exynos/multimedia/codecs/audio/exynos4/srp/ulp/src/srp_api.c similarity index 100% rename from exynos4/multimedia/codecs/sec_codecs/audio/exynos4/srp/ulp/src/srp_api.c rename to exynos/multimedia/codecs/audio/exynos4/srp/ulp/src/srp_api.c diff --git a/exynos4/multimedia/codecs/sec_codecs/audio/exynos4/srp/ulp/src/srp_api_ctrl.c b/exynos/multimedia/codecs/audio/exynos4/srp/ulp/src/srp_api_ctrl.c similarity index 100% rename from exynos4/multimedia/codecs/sec_codecs/audio/exynos4/srp/ulp/src/srp_api_ctrl.c rename to exynos/multimedia/codecs/audio/exynos4/srp/ulp/src/srp_api_ctrl.c diff --git a/exynos4/multimedia/codecs/sec_codecs/audio/exynos5/Android.mk b/exynos/multimedia/codecs/audio/exynos5/Android.mk similarity index 100% rename from exynos4/multimedia/codecs/sec_codecs/audio/exynos5/Android.mk rename to exynos/multimedia/codecs/audio/exynos5/Android.mk diff --git a/exynos4/multimedia/codecs/sec_codecs/audio/exynos5/srp/alp/Android.mk b/exynos/multimedia/codecs/audio/exynos5/srp/alp/Android.mk similarity index 100% rename from exynos4/multimedia/codecs/sec_codecs/audio/exynos5/srp/alp/Android.mk rename to exynos/multimedia/codecs/audio/exynos5/srp/alp/Android.mk diff --git a/exynos4/multimedia/codecs/sec_codecs/audio/exynos5/srp/alp/include/srp_api.h b/exynos/multimedia/codecs/audio/exynos5/srp/alp/include/srp_api.h similarity index 100% rename from exynos4/multimedia/codecs/sec_codecs/audio/exynos5/srp/alp/include/srp_api.h rename to exynos/multimedia/codecs/audio/exynos5/srp/alp/include/srp_api.h diff --git a/exynos4/multimedia/codecs/sec_codecs/audio/exynos5/srp/alp/include/srp_error.h b/exynos/multimedia/codecs/audio/exynos5/srp/alp/include/srp_error.h similarity index 100% rename from exynos4/multimedia/codecs/sec_codecs/audio/exynos5/srp/alp/include/srp_error.h rename to exynos/multimedia/codecs/audio/exynos5/srp/alp/include/srp_error.h diff --git a/exynos4/multimedia/codecs/sec_codecs/audio/exynos5/srp/alp/include/srp_ioctl.h b/exynos/multimedia/codecs/audio/exynos5/srp/alp/include/srp_ioctl.h similarity index 100% rename from exynos4/multimedia/codecs/sec_codecs/audio/exynos5/srp/alp/include/srp_ioctl.h rename to exynos/multimedia/codecs/audio/exynos5/srp/alp/include/srp_ioctl.h diff --git a/exynos4/multimedia/codecs/sec_codecs/audio/exynos5/srp/alp/src/srp_api.c b/exynos/multimedia/codecs/audio/exynos5/srp/alp/src/srp_api.c similarity index 100% rename from exynos4/multimedia/codecs/sec_codecs/audio/exynos5/srp/alp/src/srp_api.c rename to exynos/multimedia/codecs/audio/exynos5/srp/alp/src/srp_api.c diff --git a/exynos4/multimedia/codecs/sec_codecs/video/Android.mk b/exynos/multimedia/codecs/video/Android.mk similarity index 100% rename from exynos4/multimedia/codecs/sec_codecs/video/Android.mk rename to exynos/multimedia/codecs/video/Android.mk diff --git a/exynos4/multimedia/codecs/sec_codecs/video/exynos4/Android.mk b/exynos/multimedia/codecs/video/exynos4/Android.mk similarity index 100% rename from exynos4/multimedia/codecs/sec_codecs/video/exynos4/Android.mk rename to exynos/multimedia/codecs/video/exynos4/Android.mk diff --git a/exynos4/multimedia/codecs/sec_codecs/video/exynos4/mfc/Android.mk b/exynos/multimedia/codecs/video/exynos4/mfc/Android.mk similarity index 100% rename from exynos4/multimedia/codecs/sec_codecs/video/exynos4/mfc/Android.mk rename to exynos/multimedia/codecs/video/exynos4/mfc/Android.mk diff --git a/exynos4/multimedia/codecs/sec_codecs/video/exynos4/mfc/dec/src/SsbSipMfcDecAPI.c b/exynos/multimedia/codecs/video/exynos4/mfc/dec/src/SsbSipMfcDecAPI.c similarity index 94% rename from exynos4/multimedia/codecs/sec_codecs/video/exynos4/mfc/dec/src/SsbSipMfcDecAPI.c rename to exynos/multimedia/codecs/video/exynos4/mfc/dec/src/SsbSipMfcDecAPI.c index 5cc7c88..92a8ca6 100644 --- a/exynos4/multimedia/codecs/sec_codecs/video/exynos4/mfc/dec/src/SsbSipMfcDecAPI.c +++ b/exynos/multimedia/codecs/video/exynos4/mfc/dec/src/SsbSipMfcDecAPI.c @@ -808,71 +808,6 @@ SSBSIP_MFC_ERROR_CODE SsbSipMfcDecGetConfig(void *openHandle, SSBSIP_MFC_DEC_CON return MFC_RET_OK; } -void *SsbSipMfcDecAllocInputBuffer(void *openHandle, void **phyInBuf, int inputBufferSize) -{ - int ret_code; - _MFCLIB *pCTX; - struct mfc_common_args user_addr_arg, phys_addr_arg; - - if (inputBufferSize < 0) { - LOGE("SsbSipMfcDecAllocInputBuffer] inputBufferSize = %d is invalid\n", inputBufferSize); - return NULL; - } - - if (openHandle == NULL) { - LOGE("SsbSipMfcDecAllocInputBuffer] openHandle is NULL\n"); - return NULL; - } - - pCTX = (_MFCLIB *)openHandle; - - user_addr_arg.args.mem_alloc.type = DECODER; - user_addr_arg.args.mem_alloc.buff_size = inputBufferSize; - user_addr_arg.args.mem_alloc.mapped_addr = pCTX->mapped_addr; - ret_code = ioctl(pCTX->hMFC, IOCTL_MFC_GET_IN_BUF, &user_addr_arg); - if (ret_code < 0) { - LOGE("SsbSipMfcDecAllocInputBuffer] IOCTL_MFC_GET_IN_BUF failed"); - return NULL; - } - - phys_addr_arg.args.real_addr.key = user_addr_arg.args.mem_alloc.offset; - ret_code = ioctl(pCTX->hMFC, IOCTL_MFC_GET_REAL_ADDR, &phys_addr_arg); - if (ret_code < 0) { - LOGE("SsbSipMfcDecGetInBuf] IOCTL_MFC_GET_PHYS_ADDR failed"); - return NULL; - } - - pCTX->virStrmBuf = pCTX->mapped_addr + user_addr_arg.args.mem_alloc.offset; - pCTX->phyStrmBuf = phys_addr_arg.args.real_addr.addr; - pCTX->sizeStrmBuf = inputBufferSize; - pCTX->inter_buff_status |= MFC_USE_STRM_BUFF; - - *phyInBuf = (void *)pCTX->phyStrmBuf; - - return (void *)pCTX->virStrmBuf; -} - -void SsbSipMfcDecFreeInputBuffer(void *openHandle, void *phyInBuf) -{ - int ret; - _MFCLIB *pCTX; - struct mfc_common_args free_arg; - - if (openHandle == NULL) { - LOGE("SsbSipMfcDecFreeInputBuffer] openHandle is NULL"); - return MFC_RET_INVALID_PARAM; - } - - pCTX = (_MFCLIB *)openHandle; - - if (pCTX->inter_buff_status & MFC_USE_STRM_BUFF) { - free_arg.args.mem_free.key = pCTX->virStrmBuf; - ret = ioctl(pCTX->hMFC, IOCTL_MFC_FREE_BUF, &free_arg); - } - pCTX->inter_buff_status = MFC_USE_NONE; - return MFC_RET_OK; -} - /* CRESPO */ #if 1 int tile_4x2_read(int x_size, int y_size, int x_pos, int y_pos) diff --git a/exynos4/multimedia/codecs/sec_codecs/video/exynos4/mfc/enc/src/SsbSipMfcEncAPI.c b/exynos/multimedia/codecs/video/exynos4/mfc/enc/src/SsbSipMfcEncAPI.c similarity index 100% rename from exynos4/multimedia/codecs/sec_codecs/video/exynos4/mfc/enc/src/SsbSipMfcEncAPI.c rename to exynos/multimedia/codecs/video/exynos4/mfc/enc/src/SsbSipMfcEncAPI.c diff --git a/exynos4/multimedia/codecs/sec_codecs/video/exynos4/mfc/include/SsbSipMfcApi.h b/exynos/multimedia/codecs/video/exynos4/mfc/include/SsbSipMfcApi.h similarity index 73% rename from exynos4/multimedia/codecs/sec_codecs/video/exynos4/mfc/include/SsbSipMfcApi.h rename to exynos/multimedia/codecs/video/exynos4/mfc/include/SsbSipMfcApi.h index fed3e34..462c45d 100644 --- a/exynos4/multimedia/codecs/sec_codecs/video/exynos4/mfc/include/SsbSipMfcApi.h +++ b/exynos/multimedia/codecs/video/exynos4/mfc/include/SsbSipMfcApi.h @@ -71,15 +71,9 @@ typedef enum { typedef enum { NV12_LINEAR = 0, - NV12_TILE, - NV21_LINEAR + NV12_TILE } SSBSIP_MFC_INSTRM_MODE_TYPE; -typedef enum { - FRAME = 0, - SLICE, -} SSBSIP_MFC_OUTSTRM_MODE_TYPE; - typedef enum { NO_CACHE = 0, CACHE = 1 @@ -233,25 +227,24 @@ typedef struct { typedef struct { /* common parameters */ - SSBSIP_MFC_CODEC_TYPE codecType; /* [IN] codec type */ - int SourceWidth; /* [IN] width of video to be encoded */ - int SourceHeight; /* [IN] height of video to be encoded */ - int IDRPeriod; /* [IN] GOP number(interval of I-frame) */ - int SliceMode; /* [IN] Multi slice mode */ - int RandomIntraMBRefresh; /* [IN] cyclic intra refresh */ - int EnableFRMRateControl; /* [IN] frame based rate control enable */ - int Bitrate; /* [IN] rate control parameter(bit rate) */ - int FrameQp; /* [IN] The quantization parameter of the frame */ - int FrameQp_P; /* [IN] The quantization parameter of the P frame */ - int QSCodeMax; /* [IN] Maximum Quantization value */ - int QSCodeMin; /* [IN] Minimum Quantization value */ - int CBRPeriodRf; /* [IN] Reaction coefficient parameter for rate control */ - int PadControlOn; /* [IN] Enable padding control */ - int LumaPadVal; /* [IN] Luma pel value used to fill padding area */ - int CbPadVal; /* [IN] CB pel value used to fill padding area */ - int CrPadVal; /* [IN] CR pel value used to fill padding area */ - int FrameMap; /* [IN] Encoding input mode(tile mode or linear mode) */ - SSBSIP_MFC_OUTSTRM_MODE_TYPE OutputMode; /* [IN] Output mode: Frame/Slice */ + SSBSIP_MFC_CODEC_TYPE codecType; /* [IN] codec type */ + int SourceWidth; /* [IN] width of video to be encoded */ + int SourceHeight; /* [IN] height of video to be encoded */ + int IDRPeriod; /* [IN] GOP number(interval of I-frame) */ + int SliceMode; /* [IN] Multi slice mode */ + int RandomIntraMBRefresh; /* [IN] cyclic intra refresh */ + int EnableFRMRateControl; /* [IN] frame based rate control enable */ + int Bitrate; /* [IN] rate control parameter(bit rate) */ + int FrameQp; /* [IN] The quantization parameter of the frame */ + int FrameQp_P; /* [IN] The quantization parameter of the P frame */ + int QSCodeMax; /* [IN] Maximum Quantization value */ + int QSCodeMin; /* [IN] Minimum Quantization value */ + int CBRPeriodRf; /* [IN] Reaction coefficient parameter for rate control */ + int PadControlOn; /* [IN] Enable padding control */ + int LumaPadVal; /* [IN] Luma pel value used to fill padding area */ + int CbPadVal; /* [IN] CB pel value used to fill padding area */ + int CrPadVal; /* [IN] CR pel value used to fill padding area */ + int FrameMap; /* [IN] Encoding input mode(tile mode or linear mode) */ /* H.264 specific parameters */ int ProfileIDC; /* [IN] profile */ @@ -277,25 +270,24 @@ typedef struct { typedef struct { /* common parameters */ - SSBSIP_MFC_CODEC_TYPE codecType; /* [IN] codec type */ - int SourceWidth; /* [IN] width of video to be encoded */ - int SourceHeight; /* [IN] height of video to be encoded */ - int IDRPeriod; /* [IN] GOP number(interval of I-frame) */ - int SliceMode; /* [IN] Multi slice mode */ - int RandomIntraMBRefresh; /* [IN] cyclic intra refresh */ - int EnableFRMRateControl; /* [IN] frame based rate control enable */ - int Bitrate; /* [IN] rate control parameter(bit rate) */ - int FrameQp; /* [IN] The quantization parameter of the frame */ - int FrameQp_P; /* [IN] The quantization parameter of the P frame */ - int QSCodeMax; /* [IN] Maximum Quantization value */ - int QSCodeMin; /* [IN] Minimum Quantization value */ - int CBRPeriodRf; /* [IN] Reaction coefficient parameter for rate control */ - int PadControlOn; /* [IN] Enable padding control */ - int LumaPadVal; /* [IN] Luma pel value used to fill padding area */ - int CbPadVal; /* [IN] CB pel value used to fill padding area */ - int CrPadVal; /* [IN] CR pel value used to fill padding area */ - int FrameMap; /* [IN] Encoding input mode(tile mode or linear mode) */ - SSBSIP_MFC_OUTSTRM_MODE_TYPE OutputMode; /* [IN] Output mode: Frame/Slice */ + SSBSIP_MFC_CODEC_TYPE codecType; /* [IN] codec type */ + int SourceWidth; /* [IN] width of video to be encoded */ + int SourceHeight; /* [IN] height of video to be encoded */ + int IDRPeriod; /* [IN] GOP number(interval of I-frame) */ + int SliceMode; /* [IN] Multi slice mode */ + int RandomIntraMBRefresh; /* [IN] cyclic intra refresh */ + int EnableFRMRateControl; /* [IN] frame based rate control enable */ + int Bitrate; /* [IN] rate control parameter(bit rate) */ + int FrameQp; /* [IN] The quantization parameter of the frame */ + int FrameQp_P; /* [IN] The quantization parameter of the P frame */ + int QSCodeMax; /* [IN] Maximum Quantization value */ + int QSCodeMin; /* [IN] Minimum Quantization value */ + int CBRPeriodRf; /* [IN] Reaction coefficient parameter for rate control */ + int PadControlOn; /* [IN] Enable padding control */ + int LumaPadVal; /* [IN] Luma pel value used to fill padding area */ + int CbPadVal; /* [IN] CB pel value used to fill padding area */ + int CrPadVal; /* [IN] CR pel value used to fill padding area */ + int FrameMap; /* [IN] Encoding input mode(tile mode or linear mode) */ /* MPEG4 specific parameters */ int ProfileIDC; /* [IN] profile */ @@ -310,24 +302,24 @@ typedef struct { typedef struct { /* common parameters */ - SSBSIP_MFC_CODEC_TYPE codecType; /* [IN] codec type */ - int SourceWidth; /* [IN] width of video to be encoded */ - int SourceHeight; /* [IN] height of video to be encoded */ - int IDRPeriod; /* [IN] GOP number(interval of I-frame) */ - int SliceMode; /* [IN] Multi slice mode */ - int RandomIntraMBRefresh; /* [IN] cyclic intra refresh */ - int EnableFRMRateControl; /* [IN] frame based rate control enable */ - int Bitrate; /* [IN] rate control parameter(bit rate) */ - int FrameQp; /* [IN] The quantization parameter of the frame */ - int FrameQp_P; /* [IN] The quantization parameter of the P frame */ - int QSCodeMax; /* [IN] Maximum Quantization value */ - int QSCodeMin; /* [IN] Minimum Quantization value */ - int CBRPeriodRf; /* [IN] Reaction coefficient parameter for rate control */ - int PadControlOn; /* [IN] Enable padding control */ - int LumaPadVal; /* [IN] Luma pel value used to fill padding area */ - int CbPadVal; /* [IN] CB pel value used to fill padding area */ - int CrPadVal; /* [IN] CR pel value used to fill padding area */ - int FrameMap; /* [IN] Encoding input mode(tile mode or linear mode) */ + SSBSIP_MFC_CODEC_TYPE codecType; /* [IN] codec type */ + int SourceWidth; /* [IN] width of video to be encoded */ + int SourceHeight; /* [IN] height of video to be encoded */ + int IDRPeriod; /* [IN] GOP number(interval of I-frame) */ + int SliceMode; /* [IN] Multi slice mode */ + int RandomIntraMBRefresh; /* [IN] cyclic intra refresh */ + int EnableFRMRateControl; /* [IN] frame based rate control enable */ + int Bitrate; /* [IN] rate control parameter(bit rate) */ + int FrameQp; /* [IN] The quantization parameter of the frame */ + int FrameQp_P; /* [IN] The quantization parameter of the P frame */ + int QSCodeMax; /* [IN] Maximum Quantization value */ + int QSCodeMin; /* [IN] Minimum Quantization value */ + int CBRPeriodRf; /* [IN] Reaction coefficient parameter for rate control */ + int PadControlOn; /* [IN] Enable padding control */ + int LumaPadVal; /* [IN] Luma pel value used to fill padding area */ + int CbPadVal; /* [IN] CB pel value used to fill padding area */ + int CrPadVal; /* [IN] CR pel value used to fill padding area */ + int FrameMap; /* [IN] Encoding input mode(tile mode or linear mode) */ /* H.263 specific parameters */ int FrameRate; /* [IN] rate control parameter(frame rate) */ @@ -392,9 +384,6 @@ SSBSIP_MFC_DEC_OUTBUF_STATUS SsbSipMfcDecGetOutBuf(void *openHandle, SSBSIP_MFC_ SSBSIP_MFC_ERROR_CODE SsbSipMfcDecSetConfig(void *openHandle, SSBSIP_MFC_DEC_CONF conf_type, void *value); SSBSIP_MFC_ERROR_CODE SsbSipMfcDecGetConfig(void *openHandle, SSBSIP_MFC_DEC_CONF conf_type, void *value); -void *SsbSipMfcDecAllocInputBuffer(void *openHandle, void **phyInBuf, int inputBufferSize); -void SsbSipMfcDecFreeInputBuffer(void *openHandle, void *phyInBuf); - /*--------------------------------------------------------------------------------*/ /* Encoding APIs */ /*--------------------------------------------------------------------------------*/ diff --git a/exynos4/multimedia/codecs/sec_codecs/video/exynos4/mfc/include/mfc_errno.h b/exynos/multimedia/codecs/video/exynos4/mfc/include/mfc_errno.h similarity index 100% rename from exynos4/multimedia/codecs/sec_codecs/video/exynos4/mfc/include/mfc_errno.h rename to exynos/multimedia/codecs/video/exynos4/mfc/include/mfc_errno.h diff --git a/exynos4/multimedia/codecs/sec_codecs/video/exynos4/mfc/include/mfc_interface.h b/exynos/multimedia/codecs/video/exynos4/mfc/include/mfc_interface.h similarity index 99% rename from exynos4/multimedia/codecs/sec_codecs/video/exynos4/mfc/include/mfc_interface.h rename to exynos/multimedia/codecs/video/exynos4/mfc/include/mfc_interface.h index 968da44..7fa6b94 100644 --- a/exynos4/multimedia/codecs/sec_codecs/video/exynos4/mfc/include/mfc_interface.h +++ b/exynos/multimedia/codecs/video/exynos4/mfc/include/mfc_interface.h @@ -129,7 +129,6 @@ struct mfc_enc_init_common_arg { unsigned int in_pixelcache; - unsigned int in_mapped_addr; struct mfc_strm_ref_buf_arg out_u_addr; struct mfc_strm_ref_buf_arg out_p_addr; diff --git a/exynos4/multimedia/codecs/sec_codecs/video/exynos4/mfc_v4l2/Android.mk b/exynos/multimedia/codecs/video/exynos4/mfc_v4l2/Android.mk similarity index 92% rename from exynos4/multimedia/codecs/sec_codecs/video/exynos4/mfc_v4l2/Android.mk rename to exynos/multimedia/codecs/video/exynos4/mfc_v4l2/Android.mk index f135163..6025b43 100644 --- a/exynos4/multimedia/codecs/sec_codecs/video/exynos4/mfc_v4l2/Android.mk +++ b/exynos/multimedia/codecs/video/exynos4/mfc_v4l2/Android.mk @@ -16,7 +16,7 @@ LOCAL_SRC_FILES := \ LOCAL_C_INCLUDES := \ $(LOCAL_PATH)/include \ - $(BOARD_HAL_PATH)/include + device/samsung/$(TARGET_BOARD_PLATFORM)/include LOCAL_MODULE := libsecmfcapi diff --git a/exynos4/multimedia/codecs/sec_codecs/video/exynos4/mfc_v4l2/dec/src/SsbSipMfcDecAPI.c b/exynos/multimedia/codecs/video/exynos4/mfc_v4l2/dec/src/SsbSipMfcDecAPI.c similarity index 100% rename from exynos4/multimedia/codecs/sec_codecs/video/exynos4/mfc_v4l2/dec/src/SsbSipMfcDecAPI.c rename to exynos/multimedia/codecs/video/exynos4/mfc_v4l2/dec/src/SsbSipMfcDecAPI.c diff --git a/exynos4/multimedia/codecs/sec_codecs/video/exynos4/mfc_v4l2/enc/src/SsbSipMfcEncAPI.c b/exynos/multimedia/codecs/video/exynos4/mfc_v4l2/enc/src/SsbSipMfcEncAPI.c similarity index 100% rename from exynos4/multimedia/codecs/sec_codecs/video/exynos4/mfc_v4l2/enc/src/SsbSipMfcEncAPI.c rename to exynos/multimedia/codecs/video/exynos4/mfc_v4l2/enc/src/SsbSipMfcEncAPI.c diff --git a/exynos4/multimedia/codecs/sec_codecs/video/exynos4/mfc_v4l2/include/SsbSipMfcApi.h b/exynos/multimedia/codecs/video/exynos4/mfc_v4l2/include/SsbSipMfcApi.h similarity index 99% rename from exynos4/multimedia/codecs/sec_codecs/video/exynos4/mfc_v4l2/include/SsbSipMfcApi.h rename to exynos/multimedia/codecs/video/exynos4/mfc_v4l2/include/SsbSipMfcApi.h index b85256b..43e4ba0 100644 --- a/exynos4/multimedia/codecs/sec_codecs/video/exynos4/mfc_v4l2/include/SsbSipMfcApi.h +++ b/exynos/multimedia/codecs/video/exynos4/mfc_v4l2/include/SsbSipMfcApi.h @@ -73,8 +73,7 @@ typedef enum { typedef enum { NV12_LINEAR = 0, - NV12_TILE, - NV21_LINEAR + NV12_TILE } SSBSIP_MFC_INSTRM_MODE_TYPE; typedef enum { diff --git a/exynos4/multimedia/codecs/sec_codecs/video/exynos4/mfc_v4l2/include/mfc_errno.h b/exynos/multimedia/codecs/video/exynos4/mfc_v4l2/include/mfc_errno.h similarity index 100% rename from exynos4/multimedia/codecs/sec_codecs/video/exynos4/mfc_v4l2/include/mfc_errno.h rename to exynos/multimedia/codecs/video/exynos4/mfc_v4l2/include/mfc_errno.h diff --git a/exynos4/multimedia/codecs/sec_codecs/video/exynos4/mfc_v4l2/include/mfc_interface.h b/exynos/multimedia/codecs/video/exynos4/mfc_v4l2/include/mfc_interface.h similarity index 100% rename from exynos4/multimedia/codecs/sec_codecs/video/exynos4/mfc_v4l2/include/mfc_interface.h rename to exynos/multimedia/codecs/video/exynos4/mfc_v4l2/include/mfc_interface.h diff --git a/exynos4/multimedia/codecs/sec_codecs/video/exynos5/Android.mk b/exynos/multimedia/codecs/video/exynos5/Android.mk similarity index 100% rename from exynos4/multimedia/codecs/sec_codecs/video/exynos5/Android.mk rename to exynos/multimedia/codecs/video/exynos5/Android.mk diff --git a/exynos4/multimedia/codecs/sec_codecs/video/exynos5/mfc_v4l2/Android.mk b/exynos/multimedia/codecs/video/exynos5/mfc_v4l2/Android.mk similarity index 84% rename from exynos4/multimedia/codecs/sec_codecs/video/exynos5/mfc_v4l2/Android.mk rename to exynos/multimedia/codecs/video/exynos5/mfc_v4l2/Android.mk index 89f3e84..f7ae2ec 100644 --- a/exynos4/multimedia/codecs/sec_codecs/video/exynos5/mfc_v4l2/Android.mk +++ b/exynos/multimedia/codecs/video/exynos5/mfc_v4l2/Android.mk @@ -16,14 +16,14 @@ LOCAL_SRC_FILES := \ LOCAL_C_INCLUDES := \ $(LOCAL_PATH)/include \ - $(BOARD_HAL_PATH)/include + device/samsung/$(TARGET_BOARD_PLATFORM)/include LOCAL_MODULE := libsecmfcapi LOCAL_PRELINK_MODULE := false -ifeq ($(BOARD_USE_S3D_SUPPORT), true) -LOCAL_CFLAGS += -DS3D_SUPPORT +ifeq ($(BOARD_USES_MFC_FPS),true) +LOCAL_CFLAGS := -DCONFIG_MFC_FPS endif LOCAL_ARM_MODE := arm diff --git a/exynos4/multimedia/codecs/sec_codecs/video/exynos5/mfc_v4l2/dec/src/SsbSipMfcDecAPI.c b/exynos/multimedia/codecs/video/exynos5/mfc_v4l2/dec/src/SsbSipMfcDecAPI.c similarity index 87% rename from exynos4/multimedia/codecs/sec_codecs/video/exynos5/mfc_v4l2/dec/src/SsbSipMfcDecAPI.c rename to exynos/multimedia/codecs/video/exynos5/mfc_v4l2/dec/src/SsbSipMfcDecAPI.c index fb04587..cfb5dcc 100644 --- a/exynos4/multimedia/codecs/sec_codecs/video/exynos5/mfc_v4l2/dec/src/SsbSipMfcDecAPI.c +++ b/exynos/multimedia/codecs/video/exynos5/mfc_v4l2/dec/src/SsbSipMfcDecAPI.c @@ -43,6 +43,10 @@ #define LOG_TAG "MFC_DEC_APP" #include +#ifdef CONFIG_MFC_FPS +#include +#endif + /*#define CRC_ENABLE #define SLICE_MODE_ENABLE */ #define POLL_DEC_WAIT_TIMEOUT 25 @@ -51,12 +55,13 @@ #define VOP_START_CODE (0x000001B6) #define MP4_START_CODE (0x000001) +#ifdef CONFIG_MFC_FPS +unsigned int framecount, over30ms; +struct timeval mTS1, mTS2, mDec1, mDec2; +#endif + #define DEFAULT_NUMBER_OF_EXTRA_DPB 5 #define CLEAR(x) memset (&(x), 0, sizeof(x)) -#ifdef S3D_SUPPORT -#define OPERATE_BIT(x, mask, shift) ((x & (mask << shift)) >> shift) -#define FRAME_PACK_SEI_INFO_NUM 4 -#endif enum { NV12MT_FMT = 0, @@ -149,11 +154,9 @@ int v4l2_mfc_s_fmt(int fd, enum v4l2_buf_type type, case VC1RCV_DEC: fmt.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_VC1_RCV; break; -#if defined (MFC6x_VERSION) case VP8_DEC: fmt.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_VP8; break; -#endif default: LOGE("[%s] Does NOT support the codec type (%d)", __func__, pixelformat); return -1; @@ -162,11 +165,7 @@ int v4l2_mfc_s_fmt(int fd, enum v4l2_buf_type type, } else if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { switch (pixelformat) { case NV12MT_FMT: -#if defined (MFC6x_VERSION) fmt.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_NV12MT_16X16; -#else - fmt.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_NV12MT; -#endif break; case NV12M_FMT: fmt.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_NV12M; @@ -273,42 +272,6 @@ int v4l2_mfc_g_ctrl(int fd, int id, int *value) return ret; } -#ifdef S3D_SUPPORT -int v4l2_mfc_ext_g_ctrl(int fd, SSBSIP_MFC_DEC_CONF conf_type, void *value) -{ - struct v4l2_ext_control ext_ctrl[FRAME_PACK_SEI_INFO_NUM]; - struct v4l2_ext_controls ext_ctrls; - struct mfc_frame_pack_sei_info *sei_info; - int ret, i; - - ext_ctrls.ctrl_class = V4L2_CTRL_CLASS_CODEC; - - switch (conf_type) { - case MFC_DEC_GETCONF_FRAME_PACKING: - sei_info = (struct mfc_frame_pack_sei_info *)value; - for (i=0; isei_avail = ext_ctrl[0].value; - sei_info->arrgment_id = ext_ctrl[1].value; - sei_info->sei_info = ext_ctrl[2].value; - sei_info->grid_pos = ext_ctrl[3].value; - break; - } - - return ret; -} -#endif - int v4l2_mfc_qbuf(int fd, struct v4l2_buffer *qbuf, enum v4l2_buf_type type, enum v4l2_memory memory, int index, struct v4l2_plane *planes, int frame_length) @@ -473,6 +436,12 @@ void *SsbSipMfcDecOpen(void) LOGI("[%s] MFC Library Ver %d.%02d",__func__, MFC_LIB_VER_MAJOR, MFC_LIB_VER_MINOR); +#ifdef CONFIG_MFC_FPS + framecount = 0; + over30ms = 0; + gettimeofday(&mTS1, NULL); +#endif + pCTX = (_MFCLIB *)malloc(sizeof(_MFCLIB)); if (pCTX == NULL) { LOGE("[%s] malloc failed.",__func__); @@ -591,6 +560,14 @@ SSBSIP_MFC_ERROR_CODE SsbSipMfcDecClose(void *openHandle) int ret, i; _MFCLIB *pCTX; +#ifdef CONFIG_MFC_FPS + LOGI(">>> MFC"); + gettimeofday(&mTS2, NULL); + LOGI(">>> time=%d", mTS2.tv_sec-mTS1.tv_sec); + LOGI(">>> framecount=%d", framecount); + LOGI(">>> 30ms over=%d", over30ms); +#endif + if (openHandle == NULL) { LOGE("[%s] openHandle is NULL",__func__); return MFC_RET_INVALID_PARAM; @@ -929,7 +906,7 @@ int resolution_change(void *openHandle) _MFCLIB *pCTX; pCTX = (_MFCLIB *) openHandle; - ret = v4l2_mfc_streamoff(pCTX->hMFC, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); + ret = v4l2_mfc_streamoff(pCTX->hMFC, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); if (ret != 0) goto error_case; @@ -973,6 +950,9 @@ SSBSIP_MFC_ERROR_CODE SsbSipMfcDecExe(void *openHandle, int lengthBufFill) int poll_state; int poll_revents; +#ifdef CONFIG_MFC_FPS + framecount++; +#endif if (openHandle == NULL) { LOGE("[%s] openHandle is NULL",__func__); return MFC_RET_INVALID_PARAM; @@ -983,52 +963,53 @@ SSBSIP_MFC_ERROR_CODE SsbSipMfcDecExe(void *openHandle, int lengthBufFill) return MFC_RET_INVALID_PARAM; } +#ifdef CONFIG_MFC_FPS + gettimeofday(&mDec1, NULL); +#endif pCTX = (_MFCLIB *) openHandle; if ((lengthBufFill > 0) && (SSBSIP_MFC_LAST_FRAME_PROCESSED != pCTX->lastframe)) { - if (pCTX->displayStatus != MFC_GETOUTBUF_DISPLAY_ONLY) { - /* Queue the stream frame */ - ret = v4l2_mfc_qbuf(pCTX->hMFC, &buf, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, - V4L2_MEMORY_MMAP, pCTX->v4l2_dec.beingUsedIndex, planes, lengthBufFill); - if (ret != 0) { - LOGE("[%s] VIDIOC_QBUF failed, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE",__func__); + /* Queue the stream frame */ + ret = v4l2_mfc_qbuf(pCTX->hMFC, &buf, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, + V4L2_MEMORY_MMAP, pCTX->v4l2_dec.beingUsedIndex, planes, lengthBufFill); + if (ret != 0) { + LOGE("[%s] VIDIOC_QBUF failed, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE",__func__); + return MFC_RET_DEC_EXE_ERR; + } + + memset(&buf, 0, sizeof(buf)); + buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; + buf.memory = V4L2_MEMORY_MMAP; + buf.m.planes = planes; + buf.length = 1; + + /* wait for decoding */ + do { + poll_state = v4l2_mfc_poll(pCTX->hMFC, &poll_revents, POLL_DEC_WAIT_TIMEOUT); + if (poll_state > 0) { + if (poll_revents & POLLOUT) { + ret = v4l2_mfc_dqbuf(pCTX->hMFC, &buf, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, V4L2_MEMORY_MMAP); + if (ret == 0) { + if (buf.flags & V4L2_BUF_FLAG_ERROR) + return MFC_RET_DEC_EXE_ERR; + pCTX->v4l2_dec.mfc_src_buf_flags[buf.index] = BUF_DEQUEUED; + break; + } + } else if (poll_revents & POLLERR) { + LOGE("[%s] POLLERR\n",__func__); + return MFC_RET_DEC_EXE_ERR; + } else { + LOGE("[%s] poll() returns 0x%x\n", __func__, poll_revents); + return MFC_RET_DEC_EXE_ERR; + } + } else if (poll_state < 0) { return MFC_RET_DEC_EXE_ERR; } - memset(&buf, 0, sizeof(buf)); - buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; - buf.memory = V4L2_MEMORY_MMAP; - buf.m.planes = planes; - buf.length = 1; + if (isBreak_loop(pCTX)) + break; - /* wait for decoding */ - do { - poll_state = v4l2_mfc_poll(pCTX->hMFC, &poll_revents, POLL_DEC_WAIT_TIMEOUT); - if (poll_state > 0) { - if (poll_revents & POLLOUT) { - ret = v4l2_mfc_dqbuf(pCTX->hMFC, &buf, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, V4L2_MEMORY_MMAP); - if (ret == 0) { - if (buf.flags & V4L2_BUF_FLAG_ERROR) - return MFC_RET_DEC_EXE_ERR; - pCTX->v4l2_dec.mfc_src_buf_flags[buf.index] = BUF_DEQUEUED; - break; - } - } else if (poll_revents & POLLERR) { - LOGE("[%s] POLLERR\n",__func__); - return MFC_RET_DEC_EXE_ERR; - } else { - LOGE("[%s] poll() returns 0x%x\n", __func__, poll_revents); - return MFC_RET_DEC_EXE_ERR; - } - } else if (poll_state < 0) { - return MFC_RET_DEC_EXE_ERR; - } - - if (isBreak_loop(pCTX)) - break; - - } while(0 == poll_state); - } + } while(0 == poll_state); ret = v4l2_mfc_dqbuf(pCTX->hMFC, &buf, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, V4L2_MEMORY_MMAP); if (ret != 0) { @@ -1096,17 +1077,6 @@ SSBSIP_MFC_ERROR_CODE SsbSipMfcDecExe(void *openHandle, int lengthBufFill) } } while (ret != 0); - ret = v4l2_mfc_g_ctrl(pCTX->hMFC, V4L2_CID_CODEC_DISPLAY_STATUS, &ctrl_value); - if (ret != 0) { - LOGE("[%s] VIDIOC_G_CTRL failed", __func__); - return MFC_RET_DEC_EXE_ERR; - } - if (ctrl_value == 3) { - pCTX->displayStatus = MFC_GETOUTBUF_DISPLAY_END; - pCTX->decOutInfo.disp_pic_frame_type = -1; - return MFC_RET_OK; - } - pCTX->displayStatus = MFC_GETOUTBUF_DISPLAY_ONLY; pCTX->decOutInfo.YVirAddr = pCTX->v4l2_dec.mfc_dst_bufs[buf.index][0]; @@ -1162,6 +1132,10 @@ SSBSIP_MFC_ERROR_CODE SsbSipMfcDecExe(void *openHandle, int lengthBufFill) ret = v4l2_mfc_qbuf(pCTX->hMFC, &buf, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, V4L2_MEMORY_MMAP, buf.index, planes, 0); +#ifdef CONFIG_MFC_FPS + gettimeofday(&mDec2, NULL); + if (mDec2.tv_usec-mDec1.tv_usec > 30000) over30ms++; +#endif return MFC_RET_OK; } @@ -1173,6 +1147,9 @@ SSBSIP_MFC_ERROR_CODE SsbSipMfcDecExeNb(void *openHandle, int lengthBufFill) struct v4l2_buffer buf; struct v4l2_plane planes[MFC_DEC_NUM_PLANES]; +#ifdef CONFIG_MFC_FPS + framecount++; +#endif if (openHandle == NULL) { LOGE("[%s] openHandle is NULL",__func__); return MFC_RET_INVALID_PARAM; @@ -1185,8 +1162,7 @@ SSBSIP_MFC_ERROR_CODE SsbSipMfcDecExeNb(void *openHandle, int lengthBufFill) pCTX = (_MFCLIB *) openHandle; - if ((lengthBufFill > 0) && (SSBSIP_MFC_LAST_FRAME_PROCESSED != pCTX->lastframe) - && (pCTX->displayStatus != MFC_GETOUTBUF_DISPLAY_ONLY)) { + if ((lengthBufFill > 0) && (SSBSIP_MFC_LAST_FRAME_PROCESSED != pCTX->lastframe)) { /* Queue the stream frame */ ret = v4l2_mfc_qbuf(pCTX->hMFC, &buf, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, V4L2_MEMORY_MMAP, pCTX->v4l2_dec.beingUsedIndex, planes, lengthBufFill); @@ -1252,37 +1228,35 @@ SSBSIP_MFC_DEC_OUTBUF_STATUS SsbSipMfcDecWaitForOutBuf(void *openHandle, SSBSIP_ pCTX = (_MFCLIB *) openHandle; if (SSBSIP_MFC_LAST_FRAME_PROCESSED != pCTX->lastframe) { - if (pCTX->displayStatus != MFC_GETOUTBUF_DISPLAY_ONLY) { - /* wait for decoding */ - do { - poll_state = v4l2_mfc_poll(pCTX->hMFC, &poll_revents, POLL_DEC_WAIT_TIMEOUT); - if (poll_state > 0) { - if (poll_revents & POLLOUT) { - buf.m.planes = planes; - buf.length = 1; - ret = v4l2_mfc_dqbuf(pCTX->hMFC, &buf, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, V4L2_MEMORY_MMAP); - if (ret == 0) { - if (buf.flags & V4L2_BUF_FLAG_ERROR) - return MFC_GETOUTBUF_STATUS_NULL; - pCTX->v4l2_dec.mfc_src_buf_flags[buf.index] = BUF_DEQUEUED; - break; - } - } else if (poll_revents & POLLERR) { - LOGE("[%s] POLLERR\n",__func__); - return MFC_GETOUTBUF_STATUS_NULL; - } else { - LOGE("[%s] poll() returns 0x%x\n", __func__, poll_revents); - return MFC_GETOUTBUF_STATUS_NULL; + /* wait for decoding */ + do { + poll_state = v4l2_mfc_poll(pCTX->hMFC, &poll_revents, POLL_DEC_WAIT_TIMEOUT); + if (poll_state > 0) { + if (poll_revents & POLLOUT) { + buf.m.planes = planes; + buf.length = 1; + ret = v4l2_mfc_dqbuf(pCTX->hMFC, &buf, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, V4L2_MEMORY_MMAP); + if (ret == 0) { + if (buf.flags & V4L2_BUF_FLAG_ERROR) + return MFC_GETOUTBUF_STATUS_NULL; + pCTX->v4l2_dec.mfc_src_buf_flags[buf.index] = BUF_DEQUEUED; + break; } - } else if (poll_state < 0) { + } else if (poll_revents & POLLERR) { + LOGE("[%s] POLLERR\n",__func__); + return MFC_GETOUTBUF_STATUS_NULL; + } else { + LOGE("[%s] poll() returns 0x%x\n", __func__, poll_revents); return MFC_GETOUTBUF_STATUS_NULL; } + } else if (poll_state < 0) { + return MFC_GETOUTBUF_STATUS_NULL; + } - if (isBreak_loop(pCTX)) - break; + if (isBreak_loop(pCTX)) + break; - } while (0 == poll_state); - } + } while (poll_state == 0); ret = v4l2_mfc_dqbuf(pCTX->hMFC, &buf, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, V4L2_MEMORY_MMAP); if (ret != 0) { @@ -1341,17 +1315,6 @@ SSBSIP_MFC_DEC_OUTBUF_STATUS SsbSipMfcDecWaitForOutBuf(void *openHandle, SSBSIP_ } } while (ret != 0); - ret = v4l2_mfc_g_ctrl(pCTX->hMFC, V4L2_CID_CODEC_DISPLAY_STATUS, &ctrl_value); - if (ret != 0) { - LOGE("[%s] VIDIOC_G_CTRL failed", __func__); - return MFC_RET_DEC_GET_CONF_FAIL; - } - if (ctrl_value == 3) { - pCTX->displayStatus = MFC_GETOUTBUF_DISPLAY_END; - pCTX->decOutInfo.disp_pic_frame_type = -1; - return SsbSipMfcDecGetOutBuf(pCTX, output_info);; - } - pCTX->displayStatus = MFC_GETOUTBUF_DISPLAY_ONLY; pCTX->decOutInfo.YVirAddr = pCTX->v4l2_dec.mfc_dst_bufs[buf.index][0]; @@ -1620,12 +1583,7 @@ SSBSIP_MFC_ERROR_CODE SsbSipMfcDecSetConfig(void *openHandle, SSBSIP_MFC_DEC_CON id = V4L2_CID_CODEC_LOOP_FILTER_MPEG4_ENABLE; ctrl_value = *((unsigned int*)value); break; -#ifdef S3D_SUPPORT - case MFC_DEC_SETCONF_SEI_PARSE: - id = V4L2_CID_CODEC_FRAME_PACK_SEI_PARSE; - ctrl_value = 1; - break; -#endif + default: LOGE("[%s] conf_type(%d) is NOT supported",__func__, conf_type); return MFC_RET_INVALID_PARAM; @@ -1647,10 +1605,6 @@ SSBSIP_MFC_ERROR_CODE SsbSipMfcDecGetConfig(void *openHandle, SSBSIP_MFC_DEC_CON SSBSIP_MFC_IMG_RESOLUTION *img_resolution; int ret; SSBSIP_MFC_CRC_DATA *crc_data; -#ifdef S3D_SUPPORT - SSBSIP_MFC_FRAME_PACKING *frame_packing; - struct mfc_frame_pack_sei_info sei_info; -#endif SSBSIP_MFC_CROP_INFORMATION *crop_information; if (openHandle == NULL) { @@ -1697,32 +1651,7 @@ SSBSIP_MFC_ERROR_CODE SsbSipMfcDecGetConfig(void *openHandle, SSBSIP_MFC_DEC_CON LOGI("[%s] crc_data->luma0=0x%x\n", __func__, crc_data->luma0); LOGI("[%s] crc_data->chroma0=0x%x\n", __func__, crc_data->chroma0); break; -#ifdef S3D_SUPPORT - case MFC_DEC_GETCONF_FRAME_PACKING: - frame_packing = (SSBSIP_MFC_FRAME_PACKING *)value; - ret = v4l2_mfc_ext_g_ctrl(pCTX->hMFC, conf_type, &sei_info); - if (ret != 0) { - printf("Error to do ext_g_ctrl.\n"); - } - frame_packing->available = sei_info.sei_avail; - frame_packing->arrangement_id = sei_info.arrgment_id; - - frame_packing->arrangement_cancel_flag = OPERATE_BIT(sei_info.sei_info, 0x1, 0); - frame_packing->arrangement_type = OPERATE_BIT(sei_info.sei_info, 0x3f, 1); - frame_packing->quincunx_sampling_flag = OPERATE_BIT(sei_info.sei_info, 0x1, 8); - frame_packing->content_interpretation_type = OPERATE_BIT(sei_info.sei_info, 0x3f, 9); - frame_packing->spatial_flipping_flag = OPERATE_BIT(sei_info.sei_info, 0x1, 15); - frame_packing->frame0_flipped_flag = OPERATE_BIT(sei_info.sei_info, 0x1, 16); - frame_packing->field_views_flag = OPERATE_BIT(sei_info.sei_info, 0x1, 17); - frame_packing->current_frame_is_frame0_flag = OPERATE_BIT(sei_info.sei_info, 0x1, 18); - - frame_packing->frame0_grid_pos_x = OPERATE_BIT(sei_info.sei_info, 0xf, 0); - frame_packing->frame0_grid_pos_y = OPERATE_BIT(sei_info.sei_info, 0xf, 4); - frame_packing->frame1_grid_pos_x = OPERATE_BIT(sei_info.sei_info, 0xf, 8); - frame_packing->frame1_grid_pos_y = OPERATE_BIT(sei_info.sei_info, 0xf, 12); - break; -#endif case MFC_DEC_GETCONF_CROP_INFO: crop_information = (SSBSIP_MFC_CROP_INFORMATION *)value; crop_information->crop_top_offset = pCTX->decOutInfo.crop_top_offset; diff --git a/exynos4/multimedia/codecs/sec_codecs/video/exynos5/mfc_v4l2/enc/src/SsbSipMfcEncAPI.c b/exynos/multimedia/codecs/video/exynos5/mfc_v4l2/enc/src/SsbSipMfcEncAPI.c similarity index 80% rename from exynos4/multimedia/codecs/sec_codecs/video/exynos5/mfc_v4l2/enc/src/SsbSipMfcEncAPI.c rename to exynos/multimedia/codecs/video/exynos5/mfc_v4l2/enc/src/SsbSipMfcEncAPI.c index 2333b6c..a4a841f 100644 --- a/exynos4/multimedia/codecs/sec_codecs/video/exynos5/mfc_v4l2/enc/src/SsbSipMfcEncAPI.c +++ b/exynos/multimedia/codecs/video/exynos5/mfc_v4l2/enc/src/SsbSipMfcEncAPI.c @@ -50,17 +50,6 @@ static char *mfc_dev_name = SAMSUNG_MFC_DEV_NAME; static int mfc_dev_node = 7; -#if defined (MFC5x_VERSION) -#define H263_CTRL_NUM 19 -#define MPEG4_CTRL_NUM 27 -#define H264_CTRL_NUM 50 -#elif defined (MFC6x_VERSION) -#define H263_CTRL_NUM 20 -#define MPEG4_CTRL_NUM 28 -#define H264_CTRL_NUM 67 -#endif - - static void getMFCName(char *devicename, int size) { snprintf(devicename, size, "%s%d", SAMSUNG_MFC_DEV_NAME, mfc_dev_node); @@ -238,17 +227,18 @@ SSBSIP_MFC_ERROR_CODE SsbSipMfcEncInit(void *openHandle, void *param) struct pollfd poll_events; int poll_state; - struct v4l2_ext_control ext_ctrl_mpeg4[MPEG4_CTRL_NUM]; - struct v4l2_ext_control ext_ctrl_h263[H263_CTRL_NUM]; - struct v4l2_ext_control ext_ctrl[H264_CTRL_NUM]; + struct v4l2_ext_control ext_ctrl_mpeg4[28]; + struct v4l2_ext_control ext_ctrl_h263[20]; + struct v4l2_ext_control ext_ctrl[48]; struct v4l2_ext_controls ext_ctrls; SSBSIP_MFC_ENC_H264_PARAM *h264_arg; SSBSIP_MFC_ENC_MPEG4_PARAM *mpeg4_arg; SSBSIP_MFC_ENC_H263_PARAM *h263_arg; - if (openHandle == NULL) + if (openHandle == NULL) { return MFC_RET_INVALID_PARAM; + } pCTX = (_MFCLIB *) openHandle; @@ -296,23 +286,13 @@ SSBSIP_MFC_ERROR_CODE SsbSipMfcEncInit(void *openHandle, void *param) if (mpeg4_arg->SliceMode == 0) { ext_ctrl_mpeg4[5].id = V4L2_CID_CODEC_MFC5X_ENC_MULTI_SLICE_MB; ext_ctrl_mpeg4[5].value = 1; /* default */ -#if defined (MFC5x_VERSION) - ext_ctrl_mpeg4[6].id = V4L2_CID_CODEC_MFC5X_ENC_MULTI_SLICE_BIT; - ext_ctrl_mpeg4[6].value = 1900; /* default */ -#elif defined (MFC6x_VERSION) ext_ctrl_mpeg4[6].id = V4L2_CID_CODEC_MFC5X_ENC_MULTI_SLICE_BIT; ext_ctrl_mpeg4[6].value = 2800; /* based on MFC6.x */ -#endif } else if (mpeg4_arg->SliceMode == 1) { ext_ctrl_mpeg4[5].id = V4L2_CID_CODEC_MFC5X_ENC_MULTI_SLICE_MB; ext_ctrl_mpeg4[5].value = mpeg4_arg->SliceArgument; -#if defined (MFC5x_VERSION) - ext_ctrl_mpeg4[6].id = V4L2_CID_CODEC_MFC5X_ENC_MULTI_SLICE_BIT; - ext_ctrl_mpeg4[6].value = 1900; /* default */ -#elif defined (MFC6x_VERSION) ext_ctrl_mpeg4[6].id = V4L2_CID_CODEC_MFC5X_ENC_MULTI_SLICE_BIT; ext_ctrl_mpeg4[6].value = 2800; /* based on MFC6.x */ -#endif } else if (mpeg4_arg->SliceMode == 3) { ext_ctrl_mpeg4[5].id = V4L2_CID_CODEC_MFC5X_ENC_MULTI_SLICE_MB; ext_ctrl_mpeg4[5].value = 1; /* default */ @@ -320,7 +300,7 @@ SSBSIP_MFC_ERROR_CODE SsbSipMfcEncInit(void *openHandle, void *param) ext_ctrl_mpeg4[6].value = mpeg4_arg->SliceArgument; } /* - * It should be set using mpeg4_arg->NumberBFrames after being handled by appl. + It should be set using mpeg4_arg->NumberBFrames after being handled by appl. */ ext_ctrl_mpeg4[7].id = V4L2_CID_CODEC_MFC5X_ENC_MPEG4_B_FRAMES; ext_ctrl_mpeg4[7].value = mpeg4_arg->NumberBFrames; @@ -379,10 +359,8 @@ SSBSIP_MFC_ERROR_CODE SsbSipMfcEncInit(void *openHandle, void *param) ext_ctrl_mpeg4[26].id = V4L2_CID_CODEC_MFC5X_ENC_RC_FIXED_TARGET_BIT; ext_ctrl_mpeg4[26].value = V4L2_CODEC_MFC5X_ENC_SW_ENABLE; -#if defined (MFC6x_VERSION) ext_ctrl_mpeg4[27].id = V4L2_CID_CODEC_MFC5X_ENC_MPEG4_RC_MB_ENABLE; /* MFC 6.x Only */ ext_ctrl_mpeg4[27].value = mpeg4_arg->EnableMBRateControl; -#endif break; case H263_ENC: @@ -445,10 +423,8 @@ SSBSIP_MFC_ERROR_CODE SsbSipMfcEncInit(void *openHandle, void *param) ext_ctrl_h263[18].id = V4L2_CID_CODEC_MFC5X_ENC_RC_FIXED_TARGET_BIT; ext_ctrl_h263[18].value = V4L2_CODEC_MFC5X_ENC_SW_ENABLE; -#if defined (MFC6x_VERSION) ext_ctrl_h263[19].id = V4L2_CID_CODEC_MFC5X_ENC_H263_RC_MB_ENABLE; /* MFC 6.x Only */ ext_ctrl_h263[19].value = h263_arg->EnableMBRateControl; -#endif break; case H264_ENC: @@ -467,23 +443,13 @@ SSBSIP_MFC_ERROR_CODE SsbSipMfcEncInit(void *openHandle, void *param) if (h264_arg->SliceMode == 0) { ext_ctrl[6].id = V4L2_CID_CODEC_MFC5X_ENC_MULTI_SLICE_MB; ext_ctrl[6].value = 1; /* default */ -#if defined (MFC5x_VERSION) - ext_ctrl[7].id = V4L2_CID_CODEC_MFC5X_ENC_MULTI_SLICE_BIT; - ext_ctrl[7].value = 1900; /* default */ -#elif defined (MFC6x_VERSION) ext_ctrl[7].id = V4L2_CID_CODEC_MFC5X_ENC_MULTI_SLICE_BIT; ext_ctrl[7].value = 2800; /* based on MFC6.x */ -#endif } else if (h264_arg->SliceMode == 1) { ext_ctrl[6].id = V4L2_CID_CODEC_MFC5X_ENC_MULTI_SLICE_MB; ext_ctrl[6].value = h264_arg->SliceArgument; -#if defined (MFC5x_VERSION) - ext_ctrl[7].id = V4L2_CID_CODEC_MFC5X_ENC_MULTI_SLICE_BIT; - ext_ctrl[7].value = 1900; /* default */ -#elif defined (MFC6x_VERSION) ext_ctrl[7].id = V4L2_CID_CODEC_MFC5X_ENC_MULTI_SLICE_BIT; ext_ctrl[7].value = 2800; /* based on MFC6.x */ -#endif } else if (h264_arg->SliceMode == 3) { ext_ctrl[6].id = V4L2_CID_CODEC_MFC5X_ENC_MULTI_SLICE_MB; ext_ctrl[6].value = 1; /* default */ @@ -491,7 +457,7 @@ SSBSIP_MFC_ERROR_CODE SsbSipMfcEncInit(void *openHandle, void *param) ext_ctrl[7].value = h264_arg->SliceArgument; } /* - * It should be set using h264_arg->NumberBFrames after being handled by appl. + It should be set using h264_arg->NumberBFrames after being handled by appl. */ ext_ctrl[8].id = V4L2_CID_CODEC_MFC5X_ENC_H264_B_FRAMES; ext_ctrl[8].value = h264_arg->NumberBFrames; @@ -571,155 +537,40 @@ SSBSIP_MFC_ERROR_CODE SsbSipMfcEncInit(void *openHandle, void *param) ext_ctrl[37].value = 0; ext_ctrl[38].id = V4L2_CID_CODEC_MFC5X_ENC_SEQ_HDR_MODE; - ext_ctrl[38].value = 0; /* 0: seperated header, 1: header + first frame */ + ext_ctrl[38].value = 0; /* 0: seperated header + 1: header + first frame */ - ext_ctrl[39].id = V4L2_CID_CODEC_MFC5X_ENC_H264_AR_VUI_ENABLE; - ext_ctrl[39].value = V4L2_CODEC_MFC5X_ENC_SW_DISABLE; - ext_ctrl[40].id = V4L2_CID_CODEC_MFC5X_ENC_H264_AR_VUI_IDC; - ext_ctrl[40].value = 0; - ext_ctrl[41].id = V4L2_CID_CODEC_MFC5X_ENC_H264_EXT_SAR_WIDTH; + ext_ctrl[39].id = V4L2_CID_CODEC_MFC5X_ENC_RC_FIXED_TARGET_BIT; /* MFC5.x Only */ + ext_ctrl[39].value = V4L2_CODEC_MFC5X_ENC_SW_ENABLE; + + ext_ctrl[40].id = V4L2_CID_CODEC_MFC5X_ENC_H264_AR_VUI_ENABLE; + ext_ctrl[40].value = V4L2_CODEC_MFC5X_ENC_SW_DISABLE; + ext_ctrl[41].id = V4L2_CID_CODEC_MFC5X_ENC_H264_AR_VUI_IDC; ext_ctrl[41].value = 0; - ext_ctrl[42].id = V4L2_CID_CODEC_MFC5X_ENC_H264_EXT_SAR_HEIGHT; + ext_ctrl[42].id = V4L2_CID_CODEC_MFC5X_ENC_H264_EXT_SAR_WIDTH; ext_ctrl[42].value = 0; + ext_ctrl[43].id = V4L2_CID_CODEC_MFC5X_ENC_H264_EXT_SAR_HEIGHT; + ext_ctrl[43].value = 0; if (pCTX->hier_p_enable) { - ext_ctrl[43].id = V4L2_CID_CODEC_MFC5X_ENC_H264_HIER_P_ENABLE; - ext_ctrl[43].value = V4L2_CODEC_MFC5X_ENC_SW_ENABLE; - ext_ctrl[44].id = V4L2_CID_CODEC_MFC5X_ENC_H264_LAYER0_QP; - ext_ctrl[44].value = pCTX->hier_qp_value.t0_frame_qp; - ext_ctrl[45].id = V4L2_CID_CODEC_MFC5X_ENC_H264_LAYER1_QP; - ext_ctrl[45].value = pCTX->hier_qp_value.t2_frame_qp; - ext_ctrl[46].id = V4L2_CID_CODEC_MFC5X_ENC_H264_LAYER2_QP; - ext_ctrl[46].value = pCTX->hier_qp_value.t3_frame_qp; + ext_ctrl[44].id = V4L2_CID_CODEC_MFC5X_ENC_H264_HIER_P_ENABLE; + ext_ctrl[44].value = V4L2_CODEC_MFC5X_ENC_SW_ENABLE; + ext_ctrl[45].id = V4L2_CID_CODEC_MFC5X_ENC_H264_LAYER0_QP; + ext_ctrl[45].value = pCTX->hier_qp_value.t0_frame_qp; + ext_ctrl[46].id = V4L2_CID_CODEC_MFC5X_ENC_H264_LAYER1_QP; + ext_ctrl[46].value = pCTX->hier_qp_value.t2_frame_qp; + ext_ctrl[47].id = V4L2_CID_CODEC_MFC5X_ENC_H264_LAYER2_QP; + ext_ctrl[47].value = pCTX->hier_qp_value.t3_frame_qp; } else { - ext_ctrl[43].id = V4L2_CID_CODEC_MFC5X_ENC_H264_HIER_P_ENABLE; - ext_ctrl[43].value = V4L2_CODEC_MFC5X_ENC_SW_DISABLE; - ext_ctrl[44].id = V4L2_CID_CODEC_MFC5X_ENC_H264_LAYER0_QP; - ext_ctrl[44].value = 0; - ext_ctrl[45].id = V4L2_CID_CODEC_MFC5X_ENC_H264_LAYER1_QP; + ext_ctrl[44].id = V4L2_CID_CODEC_MFC5X_ENC_H264_HIER_P_ENABLE; + ext_ctrl[44].value = V4L2_CODEC_MFC5X_ENC_SW_DISABLE; + ext_ctrl[45].id = V4L2_CID_CODEC_MFC5X_ENC_H264_LAYER0_QP; ext_ctrl[45].value = 0; - ext_ctrl[46].id = V4L2_CID_CODEC_MFC5X_ENC_H264_LAYER2_QP; + ext_ctrl[46].id = V4L2_CID_CODEC_MFC5X_ENC_H264_LAYER1_QP; ext_ctrl[46].value = 0; - } -#ifdef S3D_SUPPORT - if (pCTX->sei_info.sei_gen_enable) { - ext_ctrl[47].id = V4L2_CID_CODEC_FRAME_PACK_FRM0_FLAG; - ext_ctrl[47].value = pCTX->sei_info.curr_frame_frm0_flag; - ext_ctrl[48].id = V4L2_CID_CODEC_FRAME_PACK_ARRGMENT_TYPE; - ext_ctrl[48].value = pCTX->sei_info.frame_pack_arrgment_type; - } else { - ext_ctrl[47].id = V4L2_CID_CODEC_FRAME_PACK_FRM0_FLAG; + ext_ctrl[47].id = V4L2_CID_CODEC_MFC5X_ENC_H264_LAYER2_QP; ext_ctrl[47].value = 0; - ext_ctrl[48].id = V4L2_CID_CODEC_FRAME_PACK_ARRGMENT_TYPE; - ext_ctrl[48].value = 3; } -#else - ext_ctrl[47].id = V4L2_CID_CODEC_FRAME_PACK_FRM0_FLAG; - ext_ctrl[47].value = 0; - ext_ctrl[48].id = V4L2_CID_CODEC_FRAME_PACK_ARRGMENT_TYPE; - ext_ctrl[48].value = 3; -#endif -#if defined (MFC5x_VERSION) - ext_ctrl[49].id = V4L2_CID_CODEC_MFC5X_ENC_RC_FIXED_TARGET_BIT; /* MFC5.x Only */ - ext_ctrl[49].value = V4L2_CODEC_MFC5X_ENC_SW_ENABLE; -#elif defined (MFC6x_VERSION) - if (pCTX->fmo_enable) { - ext_ctrl[49].id = V4L2_CID_CODEC_MFC5X_ENC_H264_FMO_ENABLE; - ext_ctrl[49].value = V4L2_CODEC_MFC5X_ENC_SW_ENABLE; - ext_ctrl[50].id = V4L2_CID_CODEC_MFC5X_ENC_H264_FMO_MAP_TYPE; - ext_ctrl[50].value = pCTX->fmo_value.slice_map_type; - ext_ctrl[51].id = V4L2_CID_CODEC_MFC5X_ENC_H264_FMO_SLICE_NUM; - ext_ctrl[51].value = pCTX->fmo_value.slice_num_grp; - if (pCTX->fmo_value.slice_map_type == 0) { - ext_ctrl[52].id = V4L2_CID_CODEC_MFC5X_ENC_H264_FMO_RUN_LEN1; - ext_ctrl[53].id = V4L2_CID_CODEC_MFC5X_ENC_H264_FMO_RUN_LEN2; - ext_ctrl[54].id = V4L2_CID_CODEC_MFC5X_ENC_H264_FMO_RUN_LEN3; - ext_ctrl[55].id = V4L2_CID_CODEC_MFC5X_ENC_H264_FMO_RUN_LEN4; - for (i = 0; i < pCTX->fmo_value.slice_num_grp; i++) - ext_ctrl[52+i].value = pCTX->fmo_value.run_length[i]; - for (i = pCTX->fmo_value.slice_num_grp; i < 4; i++); - ext_ctrl[52+i].value = 1; - } else { - ext_ctrl[52].id = V4L2_CID_CODEC_MFC5X_ENC_H264_FMO_RUN_LEN1; - ext_ctrl[52].value = 1; - ext_ctrl[53].id = V4L2_CID_CODEC_MFC5X_ENC_H264_FMO_RUN_LEN2; - ext_ctrl[53].value = 1; - ext_ctrl[54].id = V4L2_CID_CODEC_MFC5X_ENC_H264_FMO_RUN_LEN3; - ext_ctrl[54].value = 1; - ext_ctrl[55].id = V4L2_CID_CODEC_MFC5X_ENC_H264_FMO_RUN_LEN4; - ext_ctrl[55].value = 1; - } - if (pCTX->fmo_value.slice_map_type == 4 || pCTX->fmo_value.slice_map_type == 5) { - ext_ctrl[56].id = V4L2_CID_CODEC_MFC5X_ENC_H264_FMO_SG_DIR; - ext_ctrl[56].value = pCTX->fmo_value.sg_dir; - ext_ctrl[57].id = V4L2_CID_CODEC_MFC5X_ENC_H264_FMO_SG_RATE; - ext_ctrl[57].value = pCTX->fmo_value.sg_rate; - } else { - ext_ctrl[56].id = V4L2_CID_CODEC_MFC5X_ENC_H264_FMO_SG_DIR; - ext_ctrl[56].value = 0; - ext_ctrl[57].id = V4L2_CID_CODEC_MFC5X_ENC_H264_FMO_SG_RATE; - ext_ctrl[57].value = 1; - } - } else { - ext_ctrl[49].id = V4L2_CID_CODEC_MFC5X_ENC_H264_FMO_ENABLE; - ext_ctrl[49].value = V4L2_CODEC_MFC5X_ENC_SW_DISABLE; - ext_ctrl[50].id = V4L2_CID_CODEC_MFC5X_ENC_H264_FMO_MAP_TYPE; - ext_ctrl[50].value = 0; - ext_ctrl[51].id = V4L2_CID_CODEC_MFC5X_ENC_H264_FMO_SLICE_NUM; - ext_ctrl[51].value = 1; - ext_ctrl[52].id = V4L2_CID_CODEC_MFC5X_ENC_H264_FMO_RUN_LEN1; - ext_ctrl[52].value = 1; - ext_ctrl[53].id = V4L2_CID_CODEC_MFC5X_ENC_H264_FMO_RUN_LEN2; - ext_ctrl[53].value = 1; - ext_ctrl[54].id = V4L2_CID_CODEC_MFC5X_ENC_H264_FMO_RUN_LEN3; - ext_ctrl[54].value = 1; - ext_ctrl[55].id = V4L2_CID_CODEC_MFC5X_ENC_H264_FMO_RUN_LEN4; - ext_ctrl[55].value = 1; - ext_ctrl[56].id = V4L2_CID_CODEC_MFC5X_ENC_H264_FMO_SG_DIR; - ext_ctrl[56].value = 0; - ext_ctrl[57].id = V4L2_CID_CODEC_MFC5X_ENC_H264_FMO_SG_RATE; - ext_ctrl[57].value = 1; - } - if (pCTX->aso_enable) { - ext_ctrl[58].id = V4L2_CID_CODEC_MFC5X_ENC_H264_ASO_ENABLE; - ext_ctrl[58].value = V4L2_CODEC_MFC5X_ENC_SW_ENABLE; - ext_ctrl[59].id = V4L2_CID_CODEC_MFC5X_ENC_H264_ASO_SL_ORDER_0; - ext_ctrl[59].value = pCTX->aso_sl_order[0]; - ext_ctrl[60].id = V4L2_CID_CODEC_MFC5X_ENC_H264_ASO_SL_ORDER_1; - ext_ctrl[60].value = pCTX->aso_sl_order[1]; - ext_ctrl[61].id = V4L2_CID_CODEC_MFC5X_ENC_H264_ASO_SL_ORDER_2; - ext_ctrl[61].value = pCTX->aso_sl_order[2]; - ext_ctrl[62].id = V4L2_CID_CODEC_MFC5X_ENC_H264_ASO_SL_ORDER_3; - ext_ctrl[62].value = pCTX->aso_sl_order[3]; - ext_ctrl[63].id = V4L2_CID_CODEC_MFC5X_ENC_H264_ASO_SL_ORDER_4; - ext_ctrl[63].value = pCTX->aso_sl_order[4]; - ext_ctrl[64].id = V4L2_CID_CODEC_MFC5X_ENC_H264_ASO_SL_ORDER_5; - ext_ctrl[64].value = pCTX->aso_sl_order[5]; - ext_ctrl[65].id = V4L2_CID_CODEC_MFC5X_ENC_H264_ASO_SL_ORDER_6; - ext_ctrl[65].value = pCTX->aso_sl_order[6]; - ext_ctrl[66].id = V4L2_CID_CODEC_MFC5X_ENC_H264_ASO_SL_ORDER_7; - ext_ctrl[66].value = pCTX->aso_sl_order[7]; - } else { - ext_ctrl[58].id = V4L2_CID_CODEC_MFC5X_ENC_H264_ASO_ENABLE; - ext_ctrl[58].value = V4L2_CODEC_MFC5X_ENC_SW_DISABLE; - ext_ctrl[59].id = V4L2_CID_CODEC_MFC5X_ENC_H264_ASO_SL_ORDER_0; - ext_ctrl[59].value = 0; - ext_ctrl[60].id = V4L2_CID_CODEC_MFC5X_ENC_H264_ASO_SL_ORDER_1; - ext_ctrl[60].value = 0; - ext_ctrl[61].id = V4L2_CID_CODEC_MFC5X_ENC_H264_ASO_SL_ORDER_2; - ext_ctrl[61].value = 0; - ext_ctrl[62].id = V4L2_CID_CODEC_MFC5X_ENC_H264_ASO_SL_ORDER_3; - ext_ctrl[62].value = 0; - ext_ctrl[63].id = V4L2_CID_CODEC_MFC5X_ENC_H264_ASO_SL_ORDER_4; - ext_ctrl[63].value = 0; - ext_ctrl[64].id = V4L2_CID_CODEC_MFC5X_ENC_H264_ASO_SL_ORDER_5; - ext_ctrl[64].value = 0; - ext_ctrl[65].id = V4L2_CID_CODEC_MFC5X_ENC_H264_ASO_SL_ORDER_6; - ext_ctrl[65].value = 0; - ext_ctrl[66].id = V4L2_CID_CODEC_MFC5X_ENC_H264_ASO_SL_ORDER_7; - ext_ctrl[66].value = 0; - } -#endif break; default: @@ -730,13 +581,13 @@ SSBSIP_MFC_ERROR_CODE SsbSipMfcEncInit(void *openHandle, void *param) ext_ctrls.ctrl_class = V4L2_CTRL_CLASS_CODEC; if (pCTX->codecType == MPEG4_ENC) { - ext_ctrls.count = MPEG4_CTRL_NUM; + ext_ctrls.count = 28; ext_ctrls.controls = ext_ctrl_mpeg4; } else if (pCTX->codecType == H264_ENC) { - ext_ctrls.count = H264_CTRL_NUM; + ext_ctrls.count = 48; ext_ctrls.controls = ext_ctrl; } else if (pCTX->codecType == H263_ENC) { - ext_ctrls.count = H263_CTRL_NUM; + ext_ctrls.count = 20; ext_ctrls.controls = ext_ctrl_h263; } @@ -772,12 +623,11 @@ SSBSIP_MFC_ERROR_CODE SsbSipMfcEncInit(void *openHandle, void *param) } #else /* FIXME: */ if (NV12_TILE == pCTX->framemap) { - fmt.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_NV12MT_16X16; /* 4:2:0, 2 Planes, 16x16 Tiles */ + fmt.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_NV12MT; /* 4:2:0, 2 Planes, 16x16 Tiles */ } else { /* NV12_LINEAR (default) */ fmt.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_NV12M; /* 4:2:0, 2 Planes, linear */ } #endif - ret = ioctl(pCTX->hMFC, VIDIOC_S_FMT, &fmt); if (ret != 0) { LOGE("[%s] S_FMT failed on MFC output stream",__func__); @@ -995,7 +845,7 @@ SSBSIP_MFC_ERROR_CODE SsbSipMfcEncInit(void *openHandle, void *param) } while (1 == poll_state); pCTX->v4l2_enc.mfc_dst_bufs_bytes_used_len = buf.m.planes[0].bytesused; - pCTX->virStrmBuf = (unsigned int)pCTX->v4l2_enc.mfc_dst_bufs[buf.index]; + pCTX->virStrmBuf = pCTX->v4l2_enc.mfc_dst_bufs[buf.index]; /* stream dequeued index */ index = buf.index; @@ -1015,7 +865,6 @@ SSBSIP_MFC_ERROR_CODE SsbSipMfcEncInit(void *openHandle, void *param) LOGV("[%s] Strm out idx %d",__func__,index); return MFC_RET_OK; - error_case3: for (j = 0; j < i; j++) munmap(pCTX->v4l2_enc.mfc_dst_bufs[j], pCTX->v4l2_enc.mfc_dst_bufs_len); @@ -1058,8 +907,8 @@ SSBSIP_MFC_ERROR_CODE SsbSipMfcEncGetInBuf(void *openHandle, SSBSIP_MFC_ENC_INPU input_info->CSize = Align(Align(pCTX->width, 128) * Align(pCTX->height >> 1, 32), 8192); /* tiled mode */ } else { /* NV12_LINEAR (default) */ /* 4:2:0, 2 Planes, linear */ - input_info->YSize = Align(Align(pCTX->width, 16) * Align(pCTX->height, 16), 2048); /* width = 16B, height = 16B align */ - input_info->CSize = Align(Align(pCTX->width, 16) * Align(pCTX->height >> 1, 8), 2048); /* width = 16B, height = 8B align */ + input_info->YSize = Align((pCTX->width * pCTX->height), 2048); /* linear mode, 2K align */ + input_info->CSize = Align((pCTX->width * (pCTX->height >> 1)), 2048); /* linear mode, 2K align */ } } else { for (i = 0; i < pCTX->v4l2_enc.mfc_num_src_bufs; i++) @@ -1356,7 +1205,7 @@ SSBSIP_MFC_ERROR_CODE SsbSipMfcEncExe(void *openHandle) pCTX->v4l2_enc.mfc_src_buf_flags[qbuf.index] = BUF_DEQUEUED; /* Update context stream buffer address */ - pCTX->virStrmBuf = (unsigned int)pCTX->v4l2_enc.mfc_dst_bufs[dequeued_index]; + pCTX->virStrmBuf = pCTX->v4l2_enc.mfc_dst_bufs[dequeued_index]; LOGV("[%s] Strm out idx %d",__func__,dequeued_index); return MFC_RET_OK; @@ -1367,12 +1216,7 @@ SSBSIP_MFC_ERROR_CODE SsbSipMfcEncSetConfig(void *openHandle, SSBSIP_MFC_ENC_CON _MFCLIB *pCTX; struct v4l2_control ctrl; struct mfc_enc_hier_p_qp hier_p_qp; -#ifdef S3D_SUPPORT - SSBSIP_MFC_FRAME_PACKING *frame_packing; -#endif - struct mfc_enc_fmo fmo_param; - int *aso_param; - int ret, i; + int ret; if (openHandle == NULL) { LOGE("[%s] openHandle is NULL\n",__func__); @@ -1410,13 +1254,7 @@ SSBSIP_MFC_ERROR_CODE SsbSipMfcEncSetConfig(void *openHandle, SSBSIP_MFC_ENC_CON ctrl.id = V4L2_CID_CODEC_ENCODED_BIT_RATE_CH; ctrl.value = *((unsigned int*)value); break; -#ifdef S3D_SUPPORT - case MFC_ENC_SETCONF_SEI_GEN: - ctrl.id = V4L2_CID_CODEC_FRAME_PACK_SEI_GEN; - ctrl.value = *((unsigned int*)value); - pCTX->sei_info.sei_gen_enable = 1; - break; -#endif + case MFC_ENC_SETCONF_ALLOW_FRAME_SKIP: pCTX->enc_frameskip = *((int *)value); return MFC_RET_OK; @@ -1434,32 +1272,6 @@ SSBSIP_MFC_ERROR_CODE SsbSipMfcEncSetConfig(void *openHandle, SSBSIP_MFC_ENC_CON pCTX->hier_qp_value.t2_frame_qp = (int)(hier_p_qp.t2_frame_qp); pCTX->hier_qp_value.t3_frame_qp = (int)(hier_p_qp.t3_frame_qp); return MFC_RET_OK; -#ifdef S3D_SUPPORT - case MFC_ENC_SETCONF_FRAME_PACKING: - frame_packing = (SSBSIP_MFC_FRAME_PACKING *)value; - pCTX->sei_info.curr_frame_frm0_flag = (int)(frame_packing->current_frame_is_frame0_flag); - pCTX->sei_info.frame_pack_arrgment_type = (int)(frame_packing->arrangement_type); - return MFC_RET_OK; -#endif - case MFC_ENC_SETCONF_FMO: - fmo_param = *((struct mfc_enc_fmo *) value); - pCTX->fmo_enable = 1; - pCTX->fmo_value.slice_map_type = (int)(fmo_param.slice_map_type); - pCTX->fmo_value.slice_num_grp = (int)(fmo_param.slice_num_grp); - pCTX->fmo_value.run_length[0] = (int)(fmo_param.run_length[0]); - pCTX->fmo_value.run_length[1] = (int)(fmo_param.run_length[1]); - pCTX->fmo_value.run_length[2] = (int)(fmo_param.run_length[2]); - pCTX->fmo_value.run_length[3] = (int)(fmo_param.run_length[3]); - pCTX->fmo_value.sg_dir = (int)(fmo_param.sg_dir); - pCTX->fmo_value.sg_rate = (int)(fmo_param.sg_rate); - return MFC_RET_OK; - - case MFC_ENC_SETCONF_ASO: - aso_param = (int *) value; - pCTX->aso_enable = 1; - for (i = 0; i < 8; i++) - pCTX->aso_sl_order[i] = (int)aso_param[i]; - return MFC_RET_OK; default: LOGE("[%s] conf_type(%d) is NOT supported\n",__func__, conf_type); diff --git a/exynos4/multimedia/codecs/sec_codecs/video/exynos5/mfc_v4l2/include/SsbSipMfcApi.h b/exynos/multimedia/codecs/video/exynos5/mfc_v4l2/include/SsbSipMfcApi.h similarity index 68% rename from exynos4/multimedia/codecs/sec_codecs/video/exynos5/mfc_v4l2/include/SsbSipMfcApi.h rename to exynos/multimedia/codecs/video/exynos5/mfc_v4l2/include/SsbSipMfcApi.h index b386c72..28b2d8a 100644 --- a/exynos4/multimedia/codecs/sec_codecs/video/exynos5/mfc_v4l2/include/SsbSipMfcApi.h +++ b/exynos/multimedia/codecs/video/exynos5/mfc_v4l2/include/SsbSipMfcApi.h @@ -30,8 +30,6 @@ #define MAX_DECODER_INPUT_BUFFER_SIZE (1024 * 3072) #define MAX_ENCODER_OUTPUT_BUFFER_SIZE (1024 * 3072) -#define MFC6x_VERSION - #define SUPPORT_1080P 1 #if SUPPORT_1080P @@ -61,9 +59,7 @@ typedef enum { FIMV2_DEC, FIMV3_DEC, FIMV4_DEC, -#if defined (MFC6x_VERSION) VP8_DEC, -#endif H264_ENC, MPEG4_ENC, H263_ENC, @@ -78,15 +74,9 @@ typedef enum { typedef enum { NV12_LINEAR = 0, - NV12_TILE, - NV21_LINEAR + NV12_TILE } SSBSIP_MFC_INSTRM_MODE_TYPE; -typedef enum { - FRAME = 0, - SLICE, -} SSBSIP_MFC_OUTSTRM_MODE_TYPE; - typedef enum { NO_CACHE = 0, CACHE = 1 @@ -110,12 +100,7 @@ typedef enum { MFC_DEC_SETCONF_IMMEDIATELY_DISPLAY, MFC_DEC_SETCONF_DPB_FLUSH, MFC_DEC_SETCONF_PIXEL_CACHE, - MFC_DEC_GETCONF_WIDTH_HEIGHT, -#ifdef S3D_SUPPORT - /* S3D specific feature */ - MFC_DEC_SETCONF_SEI_PARSE, - MFC_DEC_GETCONF_FRAME_PACKING -#endif + MFC_DEC_GETCONF_WIDTH_HEIGHT } SSBSIP_MFC_DEC_CONF; typedef enum { @@ -129,14 +114,7 @@ typedef enum { /* C210 specific feature */ MFC_ENC_SETCONF_VUI_INFO, MFC_ENC_SETCONF_I_PERIOD, - MFC_ENC_SETCONF_HIER_P, -#ifdef S3D_SUPPORT - /* S3D Specific feature */ - MFC_ENC_SETCONF_SEI_GEN, - MFC_ENC_SETCONF_FRAME_PACKING, -#endif - MFC_ENC_SETCONF_FMO, - MFC_ENC_SETCONF_ASO, + MFC_ENC_SETCONF_HIER_P } SSBSIP_MFC_ENC_CONF; typedef enum { @@ -240,25 +218,24 @@ typedef struct { typedef struct { /* common parameters */ - SSBSIP_MFC_CODEC_TYPE codecType; /* [IN] codec type */ - int SourceWidth; /* [IN] width of video to be encoded */ - int SourceHeight; /* [IN] height of video to be encoded */ - int IDRPeriod; /* [IN] GOP number(interval of I-frame) */ - int SliceMode; /* [IN] Multi slice mode */ - int RandomIntraMBRefresh; /* [IN] cyclic intra refresh */ - int EnableFRMRateControl; /* [IN] frame based rate control enable */ - int Bitrate; /* [IN] rate control parameter(bit rate) */ - int FrameQp; /* [IN] The quantization parameter of the frame */ - int FrameQp_P; /* [IN] The quantization parameter of the P frame */ - int QSCodeMax; /* [IN] Maximum Quantization value */ - int QSCodeMin; /* [IN] Minimum Quantization value */ - int CBRPeriodRf; /* [IN] Reaction coefficient parameter for rate control */ - int PadControlOn; /* [IN] Enable padding control */ - int LumaPadVal; /* [IN] Luma pel value used to fill padding area */ - int CbPadVal; /* [IN] CB pel value used to fill padding area */ - int CrPadVal; /* [IN] CR pel value used to fill padding area */ - int FrameMap; /* [IN] Encoding input mode(tile mode or linear mode) */ - SSBSIP_MFC_OUTSTRM_MODE_TYPE OutputMode; /* [IN] Output mode: Frame/Slice */ + SSBSIP_MFC_CODEC_TYPE codecType; /* [IN] codec type */ + int SourceWidth; /* [IN] width of video to be encoded */ + int SourceHeight; /* [IN] height of video to be encoded */ + int IDRPeriod; /* [IN] GOP number(interval of I-frame) */ + int SliceMode; /* [IN] Multi slice mode */ + int RandomIntraMBRefresh; /* [IN] cyclic intra refresh */ + int EnableFRMRateControl; /* [IN] frame based rate control enable */ + int Bitrate; /* [IN] rate control parameter(bit rate) */ + int FrameQp; /* [IN] The quantization parameter of the frame */ + int FrameQp_P; /* [IN] The quantization parameter of the P frame */ + int QSCodeMax; /* [IN] Maximum Quantization value */ + int QSCodeMin; /* [IN] Minimum Quantization value */ + int CBRPeriodRf; /* [IN] Reaction coefficient parameter for rate control */ + int PadControlOn; /* [IN] Enable padding control */ + int LumaPadVal; /* [IN] Luma pel value used to fill padding area */ + int CbPadVal; /* [IN] CB pel value used to fill padding area */ + int CrPadVal; /* [IN] CR pel value used to fill padding area */ + int FrameMap; /* [IN] Encoding input mode(tile mode or linear mode) */ /* H.264 specific parameters */ int ProfileIDC; /* [IN] profile */ @@ -284,28 +261,25 @@ typedef struct { typedef struct { /* common parameters */ - SSBSIP_MFC_CODEC_TYPE codecType; /* [IN] codec type */ - int SourceWidth; /* [IN] width of video to be encoded */ - int SourceHeight; /* [IN] height of video to be encoded */ - int IDRPeriod; /* [IN] GOP number(interval of I-frame) */ - int SliceMode; /* [IN] Multi slice mode */ - int RandomIntraMBRefresh; /* [IN] cyclic intra refresh */ - int EnableFRMRateControl; /* [IN] frame based rate control enable */ - int Bitrate; /* [IN] rate control parameter(bit rate) */ - int FrameQp; /* [IN] The quantization parameter of the frame */ - int FrameQp_P; /* [IN] The quantization parameter of the P frame */ - int QSCodeMax; /* [IN] Maximum Quantization value */ - int QSCodeMin; /* [IN] Minimum Quantization value */ - int CBRPeriodRf; /* [IN] Reaction coefficient parameter for rate control */ - int PadControlOn; /* [IN] Enable padding control */ - int LumaPadVal; /* [IN] Luma pel value used to fill padding area */ - int CbPadVal; /* [IN] CB pel value used to fill padding area */ - int CrPadVal; /* [IN] CR pel value used to fill padding area */ - int FrameMap; /* [IN] Encoding input mode(tile mode or linear mode) */ - SSBSIP_MFC_OUTSTRM_MODE_TYPE OutputMode; /* [IN] Output mode: Frame/Slice */ -#if defined (MFC6x_VERSION) - int EnableMBRateControl; /* [IN] Enable macroblock-level rate control, MFC6.x Only */ -#endif + SSBSIP_MFC_CODEC_TYPE codecType; /* [IN] codec type */ + int SourceWidth; /* [IN] width of video to be encoded */ + int SourceHeight; /* [IN] height of video to be encoded */ + int IDRPeriod; /* [IN] GOP number(interval of I-frame) */ + int SliceMode; /* [IN] Multi slice mode */ + int RandomIntraMBRefresh; /* [IN] cyclic intra refresh */ + int EnableFRMRateControl; /* [IN] frame based rate control enable */ + int Bitrate; /* [IN] rate control parameter(bit rate) */ + int FrameQp; /* [IN] The quantization parameter of the frame */ + int FrameQp_P; /* [IN] The quantization parameter of the P frame */ + int QSCodeMax; /* [IN] Maximum Quantization value */ + int QSCodeMin; /* [IN] Minimum Quantization value */ + int CBRPeriodRf; /* [IN] Reaction coefficient parameter for rate control */ + int PadControlOn; /* [IN] Enable padding control */ + int LumaPadVal; /* [IN] Luma pel value used to fill padding area */ + int CbPadVal; /* [IN] CB pel value used to fill padding area */ + int CrPadVal; /* [IN] CR pel value used to fill padding area */ + int FrameMap; /* [IN] Encoding input mode(tile mode or linear mode) */ + int EnableMBRateControl; /* [IN] Enable macroblock-level rate control, MFC6.x Only */ /* MPEG4 specific parameters */ int ProfileIDC; /* [IN] profile */ @@ -320,27 +294,25 @@ typedef struct { typedef struct { /* common parameters */ - SSBSIP_MFC_CODEC_TYPE codecType; /* [IN] codec type */ - int SourceWidth; /* [IN] width of video to be encoded */ - int SourceHeight; /* [IN] height of video to be encoded */ - int IDRPeriod; /* [IN] GOP number(interval of I-frame) */ - int SliceMode; /* [IN] Multi slice mode */ - int RandomIntraMBRefresh; /* [IN] cyclic intra refresh */ - int EnableFRMRateControl; /* [IN] frame based rate control enable */ - int Bitrate; /* [IN] rate control parameter(bit rate) */ - int FrameQp; /* [IN] The quantization parameter of the frame */ - int FrameQp_P; /* [IN] The quantization parameter of the P frame */ - int QSCodeMax; /* [IN] Maximum Quantization value */ - int QSCodeMin; /* [IN] Minimum Quantization value */ - int CBRPeriodRf; /* [IN] Reaction coefficient parameter for rate control */ - int PadControlOn; /* [IN] Enable padding control */ - int LumaPadVal; /* [IN] Luma pel value used to fill padding area */ - int CbPadVal; /* [IN] CB pel value used to fill padding area */ - int CrPadVal; /* [IN] CR pel value used to fill padding area */ - int FrameMap; /* [IN] Encoding input mode(tile mode or linear mode) */ -#if defined (MFC6x_VERSION) - int EnableMBRateControl; /* [IN] Enable macroblock-level rate control, MFC6.x Only */ -#endif + SSBSIP_MFC_CODEC_TYPE codecType; /* [IN] codec type */ + int SourceWidth; /* [IN] width of video to be encoded */ + int SourceHeight; /* [IN] height of video to be encoded */ + int IDRPeriod; /* [IN] GOP number(interval of I-frame) */ + int SliceMode; /* [IN] Multi slice mode */ + int RandomIntraMBRefresh; /* [IN] cyclic intra refresh */ + int EnableFRMRateControl; /* [IN] frame based rate control enable */ + int Bitrate; /* [IN] rate control parameter(bit rate) */ + int FrameQp; /* [IN] The quantization parameter of the frame */ + int FrameQp_P; /* [IN] The quantization parameter of the P frame */ + int QSCodeMax; /* [IN] Maximum Quantization value */ + int QSCodeMin; /* [IN] Minimum Quantization value */ + int CBRPeriodRf; /* [IN] Reaction coefficient parameter for rate control */ + int PadControlOn; /* [IN] Enable padding control */ + int LumaPadVal; /* [IN] Luma pel value used to fill padding area */ + int CbPadVal; /* [IN] CB pel value used to fill padding area */ + int CrPadVal; /* [IN] CR pel value used to fill padding area */ + int FrameMap; /* [IN] Encoding input mode(tile mode or linear mode) */ + int EnableMBRateControl; /* [IN] Enable macroblock-level rate control, MFC6.x Only */ /* H.263 specific parameters */ int FrameRate; /* [IN] rate control parameter(frame rate) */ @@ -360,25 +332,6 @@ typedef struct { int crop_right_offset; } SSBSIP_MFC_CROP_INFORMATION; -#ifdef S3D_SUPPORT -typedef struct { - int available; - unsigned int arrangement_id; - int arrangement_cancel_flag; - unsigned char arrangement_type; - int quincunx_sampling_flag; - unsigned char content_interpretation_type; - int spatial_flipping_flag; - int frame0_flipped_flag; - int field_views_flag; - int current_frame_is_frame0_flag; - unsigned char frame0_grid_pos_x; - unsigned char frame0_grid_pos_y; - unsigned char frame1_grid_pos_x; - unsigned char frame1_grid_pos_y; -} SSBSIP_MFC_FRAME_PACKING; -#endif - #ifdef __cplusplus extern "C" { #endif diff --git a/exynos4/multimedia/codecs/sec_codecs/video/exynos5/mfc_v4l2/include/mfc_errno.h b/exynos/multimedia/codecs/video/exynos5/mfc_v4l2/include/mfc_errno.h similarity index 100% rename from exynos4/multimedia/codecs/sec_codecs/video/exynos5/mfc_v4l2/include/mfc_errno.h rename to exynos/multimedia/codecs/video/exynos5/mfc_v4l2/include/mfc_errno.h diff --git a/exynos4/multimedia/codecs/sec_codecs/video/exynos5/mfc_v4l2/include/mfc_interface.h b/exynos/multimedia/codecs/video/exynos5/mfc_v4l2/include/mfc_interface.h similarity index 96% rename from exynos4/multimedia/codecs/sec_codecs/video/exynos5/mfc_v4l2/include/mfc_interface.h rename to exynos/multimedia/codecs/video/exynos5/mfc_v4l2/include/mfc_interface.h index 9bcee9d..2200e10 100644 --- a/exynos4/multimedia/codecs/sec_codecs/video/exynos5/mfc_v4l2/include/mfc_interface.h +++ b/exynos/multimedia/codecs/video/exynos5/mfc_v4l2/include/mfc_interface.h @@ -99,15 +99,6 @@ typedef struct { int chroma1; /* per frame (or bottom field) */ } SSBSIP_MFC_CRC_DATA; -#ifdef S3D_SUPPORT -struct mfc_frame_pack_sei_info { - int sei_avail; - unsigned int arrgment_id; - int sei_info; - int grid_pos; -}; -#endif - struct mfc_strm_ref_buf_arg { unsigned int strm_ref_y; unsigned int mv_ref_yc; @@ -457,22 +448,6 @@ struct mfc_enc_hier_p_qp { int t3_frame_qp; }; -#ifdef S3D_SUPPORT -struct mfc_enc_sei_info { - int sei_gen_enable; - int curr_frame_frm0_flag; - int frame_pack_arrgment_type; -}; -#endif - -struct mfc_enc_fmo { - unsigned int slice_map_type; - unsigned int slice_num_grp; - unsigned int run_length[4]; - unsigned int sg_dir; - unsigned int sg_rate; -}; - enum BUF_STATUS { BUF_ENQUEUED, BUF_DEQUEUED @@ -566,14 +541,6 @@ typedef struct { int hier_p_enable; struct mfc_enc_hier_p_qp hier_qp_value; -#ifdef S3D_SUPPORT - struct mfc_enc_sei_info sei_info; -#endif - int fmo_enable; - struct mfc_enc_fmo fmo_value; - int aso_enable; - int aso_sl_order[8]; - /*ION related*/ int ion_fd; diff --git a/exynos4/multimedia/libstagefrighthw/Android.mk b/exynos/multimedia/libstagefrighthw/Android.mk similarity index 100% rename from exynos4/multimedia/libstagefrighthw/Android.mk rename to exynos/multimedia/libstagefrighthw/Android.mk diff --git a/exynos4/multimedia/libstagefrighthw/SEC_OMX_Plugin.cpp b/exynos/multimedia/libstagefrighthw/SEC_OMX_Plugin.cpp similarity index 100% rename from exynos4/multimedia/libstagefrighthw/SEC_OMX_Plugin.cpp rename to exynos/multimedia/libstagefrighthw/SEC_OMX_Plugin.cpp diff --git a/exynos4/multimedia/libstagefrighthw/SEC_OMX_Plugin.h b/exynos/multimedia/libstagefrighthw/SEC_OMX_Plugin.h similarity index 100% rename from exynos4/multimedia/libstagefrighthw/SEC_OMX_Plugin.h rename to exynos/multimedia/libstagefrighthw/SEC_OMX_Plugin.h diff --git a/exynos4/multimedia/openmax/sec_omx/Android.mk b/exynos/multimedia/openmax/Android.mk similarity index 94% rename from exynos4/multimedia/openmax/sec_omx/Android.mk rename to exynos/multimedia/openmax/Android.mk index a15f70d..61bdff7 100644 --- a/exynos4/multimedia/openmax/sec_omx/Android.mk +++ b/exynos/multimedia/openmax/Android.mk @@ -1,3 +1,7 @@ +WITH_SEC_OMX := true + +ifeq ($(WITH_SEC_OMX), true) + LOCAL_PATH := $(call my-dir) BOARD_USE_ANB := true @@ -30,3 +34,5 @@ ifeq ($(BOARD_USE_ALP_AUDIO), true) include $(SEC_OMX_COMPONENT)/audio/dec/Android.mk include $(SEC_OMX_COMPONENT)/audio/dec/mp3/Android.mk endif + +endif diff --git a/exynos4/multimedia/openmax/sec_omx/component/audio/dec/Android.mk b/exynos/multimedia/openmax/component/audio/dec/Android.mk similarity index 100% rename from exynos4/multimedia/openmax/sec_omx/component/audio/dec/Android.mk rename to exynos/multimedia/openmax/component/audio/dec/Android.mk diff --git a/exynos4/multimedia/openmax/sec_omx/component/audio/dec/SEC_OMX_Adec.c b/exynos/multimedia/openmax/component/audio/dec/SEC_OMX_Adec.c similarity index 100% rename from exynos4/multimedia/openmax/sec_omx/component/audio/dec/SEC_OMX_Adec.c rename to exynos/multimedia/openmax/component/audio/dec/SEC_OMX_Adec.c diff --git a/exynos4/multimedia/openmax/sec_omx/component/audio/dec/SEC_OMX_Adec.h b/exynos/multimedia/openmax/component/audio/dec/SEC_OMX_Adec.h similarity index 100% rename from exynos4/multimedia/openmax/sec_omx/component/audio/dec/SEC_OMX_Adec.h rename to exynos/multimedia/openmax/component/audio/dec/SEC_OMX_Adec.h diff --git a/exynos4/multimedia/openmax/sec_omx/component/audio/dec/mp3/Android.mk b/exynos/multimedia/openmax/component/audio/dec/mp3/Android.mk similarity index 100% rename from exynos4/multimedia/openmax/sec_omx/component/audio/dec/mp3/Android.mk rename to exynos/multimedia/openmax/component/audio/dec/mp3/Android.mk diff --git a/exynos4/multimedia/openmax/sec_omx/component/audio/dec/mp3/SEC_OMX_Mp3dec.c b/exynos/multimedia/openmax/component/audio/dec/mp3/SEC_OMX_Mp3dec.c similarity index 100% rename from exynos4/multimedia/openmax/sec_omx/component/audio/dec/mp3/SEC_OMX_Mp3dec.c rename to exynos/multimedia/openmax/component/audio/dec/mp3/SEC_OMX_Mp3dec.c diff --git a/exynos4/multimedia/openmax/sec_omx/component/audio/dec/mp3/SEC_OMX_Mp3dec.h b/exynos/multimedia/openmax/component/audio/dec/mp3/SEC_OMX_Mp3dec.h similarity index 100% rename from exynos4/multimedia/openmax/sec_omx/component/audio/dec/mp3/SEC_OMX_Mp3dec.h rename to exynos/multimedia/openmax/component/audio/dec/mp3/SEC_OMX_Mp3dec.h diff --git a/exynos4/multimedia/openmax/sec_omx/component/audio/dec/mp3/library_register.c b/exynos/multimedia/openmax/component/audio/dec/mp3/library_register.c similarity index 100% rename from exynos4/multimedia/openmax/sec_omx/component/audio/dec/mp3/library_register.c rename to exynos/multimedia/openmax/component/audio/dec/mp3/library_register.c diff --git a/exynos4/multimedia/openmax/sec_omx/component/audio/dec/mp3/library_register.h b/exynos/multimedia/openmax/component/audio/dec/mp3/library_register.h similarity index 100% rename from exynos4/multimedia/openmax/sec_omx/component/audio/dec/mp3/library_register.h rename to exynos/multimedia/openmax/component/audio/dec/mp3/library_register.h diff --git a/exynos4/multimedia/openmax/sec_omx/component/common/Android.mk b/exynos/multimedia/openmax/component/common/Android.mk similarity index 100% rename from exynos4/multimedia/openmax/sec_omx/component/common/Android.mk rename to exynos/multimedia/openmax/component/common/Android.mk diff --git a/exynos4/multimedia/openmax/sec_omx/component/common/SEC_OMX_Basecomponent.c b/exynos/multimedia/openmax/component/common/SEC_OMX_Basecomponent.c similarity index 100% rename from exynos4/multimedia/openmax/sec_omx/component/common/SEC_OMX_Basecomponent.c rename to exynos/multimedia/openmax/component/common/SEC_OMX_Basecomponent.c diff --git a/exynos4/multimedia/openmax/sec_omx/component/common/SEC_OMX_Basecomponent.h b/exynos/multimedia/openmax/component/common/SEC_OMX_Basecomponent.h similarity index 93% rename from exynos4/multimedia/openmax/sec_omx/component/common/SEC_OMX_Basecomponent.h rename to exynos/multimedia/openmax/component/common/SEC_OMX_Basecomponent.h index 47c6771..5cedc4d 100644 --- a/exynos4/multimedia/openmax/sec_omx/component/common/SEC_OMX_Basecomponent.h +++ b/exynos/multimedia/openmax/component/common/SEC_OMX_Basecomponent.h @@ -145,13 +145,8 @@ typedef struct _SEC_OMX_BASECOMPONENT OMX_ERRORTYPE (*sec_InputBufferReturn)(OMX_COMPONENTTYPE *pOMXComponent); OMX_ERRORTYPE (*sec_OutputBufferReturn)(OMX_COMPONENTTYPE *pOMXComponent); - OMX_ERRORTYPE (*sec_allocSecureInputBuffer)(OMX_IN OMX_HANDLETYPE hComponent, - OMX_IN OMX_U32 nBufferSize, - OMX_INOUT OMX_PTR *pInputBuffer_physicalAddress); - OMX_ERRORTYPE (*sec_freeSecureInputBuffer)(OMX_IN OMX_HANDLETYPE hComponent, - OMX_INOUT OMX_PTR pInputBuffer_physicalAddress); - int (*sec_checkInputFrame)(OMX_U8 *pInputStream, OMX_U32 buffSize, OMX_U32 flag, OMX_BOOL bPreviousFrameEOF, OMX_BOOL *pbEndOfFrame); + } SEC_OMX_BASECOMPONENT; OMX_ERRORTYPE SEC_OMX_GetParameter( diff --git a/exynos4/multimedia/openmax/sec_omx/component/common/SEC_OMX_Baseport.c b/exynos/multimedia/openmax/component/common/SEC_OMX_Baseport.c similarity index 100% rename from exynos4/multimedia/openmax/sec_omx/component/common/SEC_OMX_Baseport.c rename to exynos/multimedia/openmax/component/common/SEC_OMX_Baseport.c diff --git a/exynos4/multimedia/openmax/sec_omx/component/common/SEC_OMX_Baseport.h b/exynos/multimedia/openmax/component/common/SEC_OMX_Baseport.h similarity index 100% rename from exynos4/multimedia/openmax/sec_omx/component/common/SEC_OMX_Baseport.h rename to exynos/multimedia/openmax/component/common/SEC_OMX_Baseport.h diff --git a/exynos4/multimedia/openmax/sec_omx/component/common/SEC_OMX_Resourcemanager.c b/exynos/multimedia/openmax/component/common/SEC_OMX_Resourcemanager.c similarity index 100% rename from exynos4/multimedia/openmax/sec_omx/component/common/SEC_OMX_Resourcemanager.c rename to exynos/multimedia/openmax/component/common/SEC_OMX_Resourcemanager.c diff --git a/exynos4/multimedia/openmax/sec_omx/component/common/SEC_OMX_Resourcemanager.h b/exynos/multimedia/openmax/component/common/SEC_OMX_Resourcemanager.h similarity index 100% rename from exynos4/multimedia/openmax/sec_omx/component/common/SEC_OMX_Resourcemanager.h rename to exynos/multimedia/openmax/component/common/SEC_OMX_Resourcemanager.h diff --git a/exynos4/multimedia/openmax/sec_omx/component/video/dec/Android.mk b/exynos/multimedia/openmax/component/video/dec/Android.mk similarity index 100% rename from exynos4/multimedia/openmax/sec_omx/component/video/dec/Android.mk rename to exynos/multimedia/openmax/component/video/dec/Android.mk diff --git a/exynos4/multimedia/openmax/sec_omx/component/video/dec/SEC_OMX_Vdec.c b/exynos/multimedia/openmax/component/video/dec/SEC_OMX_Vdec.c similarity index 95% rename from exynos4/multimedia/openmax/sec_omx/component/video/dec/SEC_OMX_Vdec.c rename to exynos/multimedia/openmax/component/video/dec/SEC_OMX_Vdec.c index 042dd25..80d2a50 100644 --- a/exynos4/multimedia/openmax/sec_omx/component/video/dec/SEC_OMX_Vdec.c +++ b/exynos/multimedia/openmax/component/video/dec/SEC_OMX_Vdec.c @@ -196,7 +196,6 @@ OMX_ERRORTYPE SEC_OMX_AllocateBuffer( OMX_ERRORTYPE ret = OMX_ErrorNone; OMX_COMPONENTTYPE *pOMXComponent = NULL; SEC_OMX_BASECOMPONENT *pSECComponent = NULL; - SEC_OMX_VIDEODEC_COMPONENT *pVideoDec = NULL; SEC_OMX_BASEPORT *pSECPort = NULL; OMX_BUFFERHEADERTYPE *temp_bufferHeader = NULL; OMX_U8 *temp_buffer = NULL; @@ -219,7 +218,6 @@ OMX_ERRORTYPE SEC_OMX_AllocateBuffer( goto EXIT; } pSECComponent = (SEC_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; - pVideoDec = (SEC_OMX_VIDEODEC_COMPONENT *)pSECComponent->hComponentHandle; pSECPort = &pSECComponent->pSECPort[nPortIndex]; if (nPortIndex >= pSECComponent->portParam.nPorts) { @@ -237,25 +235,15 @@ OMX_ERRORTYPE SEC_OMX_AllocateBuffer( goto EXIT; } - if ((pVideoDec->bDRMPlayerMode == OMX_TRUE) && (nPortIndex == INPUT_PORT_INDEX)) { - ret = pSECComponent->sec_allocSecureInputBuffer(hComponent, sizeof(OMX_U8) * nSizeBytes, &temp_buffer); - if (ret != OMX_ErrorNone) - goto EXIT; - } else { - temp_buffer = SEC_OSAL_Malloc(sizeof(OMX_U8) * nSizeBytes); - if (temp_buffer == NULL) { - ret = OMX_ErrorInsufficientResources; - goto EXIT; - } + temp_buffer = SEC_OSAL_Malloc(sizeof(OMX_U8) * nSizeBytes); + if (temp_buffer == NULL) { + ret = OMX_ErrorInsufficientResources; + goto EXIT; } temp_bufferHeader = (OMX_BUFFERHEADERTYPE *)SEC_OSAL_Malloc(sizeof(OMX_BUFFERHEADERTYPE)); if (temp_bufferHeader == NULL) { - if ((pVideoDec->bDRMPlayerMode == OMX_TRUE) && (nPortIndex == INPUT_PORT_INDEX)) - pSECComponent->sec_freeSecureInputBuffer(hComponent, temp_buffer); - else - SEC_OSAL_Free(temp_buffer); - + SEC_OSAL_Free(temp_buffer); temp_buffer = NULL; ret = OMX_ErrorInsufficientResources; goto EXIT; @@ -288,11 +276,7 @@ OMX_ERRORTYPE SEC_OMX_AllocateBuffer( } SEC_OSAL_Free(temp_bufferHeader); - if ((pVideoDec->bDRMPlayerMode == OMX_TRUE) && (nPortIndex == INPUT_PORT_INDEX)) - pSECComponent->sec_freeSecureInputBuffer(hComponent, temp_buffer); - else - SEC_OSAL_Free(temp_buffer); - + SEC_OSAL_Free(temp_buffer); ret = OMX_ErrorInsufficientResources; EXIT: @@ -309,7 +293,6 @@ OMX_ERRORTYPE SEC_OMX_FreeBuffer( OMX_ERRORTYPE ret = OMX_ErrorNone; OMX_COMPONENTTYPE *pOMXComponent = NULL; SEC_OMX_BASECOMPONENT *pSECComponent = NULL; - SEC_OMX_VIDEODEC_COMPONENT *pVideoDec = NULL; SEC_OMX_BASEPORT *pSECPort = NULL; OMX_BUFFERHEADERTYPE *temp_bufferHeader = NULL; OMX_U8 *temp_buffer = NULL; @@ -332,7 +315,6 @@ OMX_ERRORTYPE SEC_OMX_FreeBuffer( goto EXIT; } pSECComponent = (SEC_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; - pVideoDec = (SEC_OMX_VIDEODEC_COMPONENT *)pSECComponent->hComponentHandle; pSECPort = &pSECComponent->pSECPort[nPortIndex]; if (CHECK_PORT_TUNNELED(pSECPort) && CHECK_PORT_BUFFER_SUPPLIER(pSECPort)) { @@ -352,10 +334,7 @@ OMX_ERRORTYPE SEC_OMX_FreeBuffer( if (((pSECPort->bufferStateAllocate[i] | BUFFER_STATE_FREE) != 0) && (pSECPort->bufferHeader[i] != NULL)) { if (pSECPort->bufferHeader[i]->pBuffer == pBufferHdr->pBuffer) { if (pSECPort->bufferStateAllocate[i] & BUFFER_STATE_ALLOCATED) { - if ((pVideoDec->bDRMPlayerMode == OMX_TRUE) && (nPortIndex == INPUT_PORT_INDEX)) - pSECComponent->sec_freeSecureInputBuffer(hComponent, pSECPort->bufferHeader[i]->pBuffer); - else - SEC_OSAL_Free(pSECPort->bufferHeader[i]->pBuffer); + SEC_OSAL_Free(pSECPort->bufferHeader[i]->pBuffer); pSECPort->bufferHeader[i]->pBuffer = NULL; pBufferHdr->pBuffer = NULL; } else if (pSECPort->bufferStateAllocate[i] & BUFFER_STATE_ASSIGNED) { @@ -704,7 +683,6 @@ OMX_BOOL SEC_Preprocessor_InputData(OMX_COMPONENTTYPE *pOMXComponent) { OMX_BOOL ret = OMX_FALSE; SEC_OMX_BASECOMPONENT *pSECComponent = (SEC_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; - SEC_OMX_VIDEODEC_COMPONENT *pVideoDec = (SEC_OMX_VIDEODEC_COMPONENT *)pSECComponent->hComponentHandle; SEC_OMX_DATABUFFER *inputUseBuffer = &pSECComponent->secDataBuffer[INPUT_PORT_INDEX]; SEC_OMX_DATA *inputData = &pSECComponent->processData[INPUT_PORT_INDEX]; OMX_U32 copySize = 0; @@ -725,10 +703,7 @@ OMX_BOOL SEC_Preprocessor_InputData(OMX_COMPONENTTYPE *pOMXComponent) } else { previousFrameEOF = OMX_FALSE; } - if (pVideoDec->bDRMPlayerMode == OMX_TRUE) { - flagEOF = OMX_TRUE; - checkedSize = checkInputStreamLen; - } else if ((pSECComponent->bUseFlagEOF == OMX_TRUE) && + if ((pSECComponent->bUseFlagEOF == OMX_TRUE) && !(inputUseBuffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG)) { flagEOF = OMX_TRUE; checkedSize = checkInputStreamLen; @@ -748,13 +723,9 @@ OMX_BOOL SEC_Preprocessor_InputData(OMX_COMPONENTTYPE *pOMXComponent) if (inputUseBuffer->nFlags & OMX_BUFFERFLAG_EOS) pSECComponent->bSaveFlagEOS = OMX_TRUE; - if ((((inputData->allocSize) - (inputData->dataLen)) >= copySize) || (pVideoDec->bDRMPlayerMode == OMX_TRUE)) { - if (pVideoDec->bDRMPlayerMode == OMX_TRUE) { - inputData->dataBuffer = checkInputStream; - } else { - if (copySize > 0) - SEC_OSAL_Memcpy(inputData->dataBuffer + inputData->dataLen, checkInputStream, copySize); - } + if (((inputData->allocSize) - (inputData->dataLen)) >= copySize) { + if (copySize > 0) + SEC_OSAL_Memcpy(inputData->dataBuffer + inputData->dataLen, checkInputStream, copySize); inputUseBuffer->dataLen -= copySize; inputUseBuffer->remainDataLen -= copySize; @@ -807,12 +778,10 @@ OMX_BOOL SEC_Preprocessor_InputData(OMX_COMPONENTTYPE *pOMXComponent) flagEOF = OMX_FALSE; } - if (inputUseBuffer->remainDataLen == 0) { - if (pVideoDec->bDRMPlayerMode != OMX_TRUE) - SEC_InputBufferReturn(pOMXComponent); - } else { + if (inputUseBuffer->remainDataLen == 0) + SEC_InputBufferReturn(pOMXComponent); + else inputUseBuffer->dataValid = OMX_TRUE; - } } if (flagEOF == OMX_TRUE) { @@ -964,14 +933,6 @@ OMX_ERRORTYPE SEC_OMX_BufferProcess(OMX_HANDLETYPE hComponent) SEC_OSAL_MutexLock(inputUseBuffer->bufferMutex); SEC_OSAL_MutexLock(outputUseBuffer->bufferMutex); ret = pSECComponent->sec_mfc_bufferProcess(pOMXComponent, inputData, outputData); - - if (pVideoDec->bDRMPlayerMode == OMX_TRUE) { - if ((inputUseBuffer->remainDataLen == 0) && - (ret != OMX_ErrorInputDataDecodeYet)) - SEC_InputBufferReturn(pOMXComponent); - else - inputUseBuffer->dataValid = OMX_TRUE; - } SEC_OSAL_MutexUnlock(outputUseBuffer->bufferMutex); SEC_OSAL_MutexUnlock(inputUseBuffer->bufferMutex); diff --git a/exynos4/multimedia/openmax/sec_omx/component/video/dec/SEC_OMX_Vdec.h b/exynos/multimedia/openmax/component/video/dec/SEC_OMX_Vdec.h similarity index 97% rename from exynos4/multimedia/openmax/sec_omx/component/video/dec/SEC_OMX_Vdec.h rename to exynos/multimedia/openmax/component/video/dec/SEC_OMX_Vdec.h index d3bbdf4..806ad44 100644 --- a/exynos4/multimedia/openmax/sec_omx/component/video/dec/SEC_OMX_Vdec.h +++ b/exynos/multimedia/openmax/component/video/dec/SEC_OMX_Vdec.h @@ -84,13 +84,6 @@ typedef struct _SEC_OMX_VIDEODEC_COMPONENT OMX_BOOL bFirstFrame; MFC_DEC_INPUT_BUFFER MFCDecInputBuffer[MFC_INPUT_BUFFER_NUM_MAX]; OMX_U32 indexInputBuffer; - - /* CSC handle */ - OMX_PTR csc_handle; - OMX_U32 csc_set_format; - - /* For DRM Play */ - OMX_BOOL bDRMPlayerMode; } SEC_OMX_VIDEODEC_COMPONENT; diff --git a/exynos4/multimedia/openmax/sec_omx/component/video/dec/vp8/Android.mk b/exynos/multimedia/openmax/component/video/dec/h264/Android.mk similarity index 67% rename from exynos4/multimedia/openmax/sec_omx/component/video/dec/vp8/Android.mk rename to exynos/multimedia/openmax/component/video/dec/h264/Android.mk index 1ced382..5ac0170 100644 --- a/exynos4/multimedia/openmax/sec_omx/component/video/dec/vp8/Android.mk +++ b/exynos/multimedia/openmax/component/video/dec/h264/Android.mk @@ -4,11 +4,11 @@ include $(CLEAR_VARS) LOCAL_MODULE_TAGS := optional LOCAL_SRC_FILES := \ - SEC_OMX_Vp8dec.c \ + SEC_OMX_H264dec.c \ library_register.c LOCAL_PRELINK_MODULE := false -LOCAL_MODULE := libOMX.SEC.VP8.Decoder +LOCAL_MODULE := libOMX.SEC.AVC.Decoder LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/omx LOCAL_CFLAGS := @@ -24,42 +24,35 @@ ifeq ($(BOARD_USE_V4L2_ION), false) LOCAL_CFLAGS += -DUSE_CSC_FIMC endif endif +endif -ifeq ($(BOARD_USE_CSC_GSCALER), true) -LOCAL_CFLAGS += -DUSE_CSC_GSCALER +ifeq ($(BOARD_USE_V4L2), false) +ifeq ($(BOARD_USE_S3D_SUPPORT), true) +LOCAL_CFLAGS += -DS3D_SUPPORT endif endif LOCAL_ARM_MODE := arm LOCAL_STATIC_LIBRARIES := libSEC_OMX_Vdec libsecosal libsecbasecomponent \ - libswconverter libsecmfcapi + libseccscapi libsecmfcapi LOCAL_SHARED_LIBRARIES := libc libdl libcutils libutils libui \ - libSEC_OMX_Resourcemanager libcsc + libSEC_OMX_Resourcemanager ifeq ($(filter-out exynos4,$(TARGET_BOARD_PLATFORM)),) -LOCAL_SHARED_LIBRARIES += libfimc libhwconverter -endif - -ifeq ($(filter-out exynos5,$(TARGET_BOARD_PLATFORM)),) -LOCAL_SHARED_LIBRARIES += libexynosgscaler +LOCAL_SHARED_LIBRARIES += libhwconverter endif #ifeq ($(BOARD_USE_V4L2_ION),true) #LOCAL_SHARED_LIBRARIES += libion #endif -ifeq ($(BOARD_USES_MFC_FPS),true) -LOCAL_CFLAGS += -DCONFIG_MFC_FPS -endif - LOCAL_C_INCLUDES := $(SEC_OMX_INC)/khronos \ $(SEC_OMX_INC)/sec \ $(SEC_OMX_TOP)/osal \ $(SEC_OMX_TOP)/core \ $(SEC_OMX_COMPONENT)/common \ $(SEC_OMX_COMPONENT)/video/dec \ - $(TARGET_OUT_HEADERS)/$(SEC_COPY_HEADERS_TO) \ - $(BOARD_HAL_PATH)/include + $(TARGET_OUT_HEADERS)/$(SEC_COPY_HEADERS_TO) include $(BUILD_SHARED_LIBRARY) diff --git a/exynos4/multimedia/openmax/sec_omx/component/video/dec/h264/SEC_OMX_H264dec.c b/exynos/multimedia/openmax/component/video/dec/h264/SEC_OMX_H264dec.c similarity index 69% rename from exynos4/multimedia/openmax/sec_omx/component/video/dec/h264/SEC_OMX_H264dec.c rename to exynos/multimedia/openmax/component/video/dec/h264/SEC_OMX_H264dec.c index 2ad34d8..5efa041 100644 --- a/exynos4/multimedia/openmax/sec_omx/component/video/dec/h264/SEC_OMX_H264dec.c +++ b/exynos/multimedia/openmax/component/video/dec/h264/SEC_OMX_H264dec.c @@ -38,14 +38,17 @@ #include "library_register.h" #include "SEC_OMX_H264dec.h" #include "SsbSipMfcApi.h" +#include "color_space_convertor.h" #ifdef USE_ANB #include "SEC_OSAL_Android.h" #endif -/* To use CSC_METHOD_PREFER_HW or CSC_METHOD_HW in SEC OMX, gralloc should allocate physical memory using FIMC */ +/* To use CSC FIMC in SEC OMX, gralloc should allocate physical memory using FIMC */ /* It means GRALLOC_USAGE_HW_FIMC1 should be set on Native Window usage */ -#include "csc.h" +#ifdef USE_CSC_FIMC +#include "csc_fimc.h" +#endif #undef SEC_LOG_TAG #define SEC_LOG_TAG "SEC_H264_DEC" @@ -197,74 +200,6 @@ OMX_BOOL Check_H264_StartCode(OMX_U8 *pInputStream, OMX_U32 streamSize) } } -OMX_ERRORTYPE SEC_MFC_H264Dec_Alloc_SecureInputBuffer(OMX_IN OMX_HANDLETYPE hComponent, - OMX_IN OMX_U32 nBufferSize, - OMX_INOUT OMX_PTR *pInputBuffer_physicalAddress) -{ - FunctionIn(); - - OMX_ERRORTYPE ret = OMX_ErrorNone; - OMX_COMPONENTTYPE *pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; - SEC_OMX_BASECOMPONENT *pSECComponent = (SEC_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; - SEC_OMX_VIDEODEC_COMPONENT *pVideoDec = (SEC_OMX_VIDEODEC_COMPONENT *)pSECComponent->hComponentHandle; - SEC_H264DEC_HANDLE *pH264Dec = NULL; - OMX_PTR pStreamBuffer = NULL; - OMX_PTR pStreamPhyBuffer = NULL; - -#ifdef USE_DRM - pH264Dec = (SEC_H264DEC_HANDLE *)((SEC_OMX_VIDEODEC_COMPONENT *)pSECComponent->hComponentHandle)->hCodecHandle; - if (pH264Dec == NULL) { - ret = OMX_ErrorInvalidState; - goto EXIT; - } - - pStreamBuffer = SsbSipMfcDecAllocInputBuffer(pH264Dec->hMFCH264Handle.hMFCHandle, &pStreamPhyBuffer, nBufferSize); - if (pStreamBuffer == NULL) { - ret = OMX_ErrorIncorrectStateOperation; - goto EXIT; - } - - pSECComponent->processData[INPUT_PORT_INDEX].dataBuffer = pStreamPhyBuffer; - pSECComponent->processData[INPUT_PORT_INDEX].allocSize = nBufferSize; - - *pInputBuffer_physicalAddress = pStreamPhyBuffer; -#endif - -EXIT: - FunctionOut(); - - return ret; -} - -OMX_ERRORTYPE SEC_MFC_H264Dec_Free_SecureInputBuffer(OMX_IN OMX_HANDLETYPE hComponent, - OMX_INOUT OMX_PTR pInputBuffer_physicalAddress) -{ - FunctionIn(); - - OMX_ERRORTYPE ret = OMX_ErrorNone; - OMX_COMPONENTTYPE *pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; - SEC_OMX_BASECOMPONENT *pSECComponent = (SEC_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; - SEC_OMX_VIDEODEC_COMPONENT *pVideoDec = (SEC_OMX_VIDEODEC_COMPONENT *)pSECComponent->hComponentHandle; - SEC_H264DEC_HANDLE *pH264Dec = NULL; - OMX_PTR pStreamPhyBuffer = NULL; - -#ifdef USE_DRM - pH264Dec = (SEC_H264DEC_HANDLE *)((SEC_OMX_VIDEODEC_COMPONENT *)pSECComponent->hComponentHandle)->hCodecHandle; - if (pH264Dec == NULL) { - ret = OMX_ErrorInvalidState; - goto EXIT; - } - - pStreamPhyBuffer = pInputBuffer_physicalAddress; - SsbSipMfcDecFreeInputBuffer(pH264Dec->hMFCH264Handle.hMFCHandle, pStreamPhyBuffer); -#endif - -EXIT: - FunctionOut(); - - return ret; -} - OMX_ERRORTYPE SEC_MFC_H264Dec_GetParameter( OMX_IN OMX_HANDLETYPE hComponent, OMX_IN OMX_INDEXTYPE nParamIndex, @@ -842,13 +777,7 @@ OMX_ERRORTYPE SEC_MFC_DecodeThread(OMX_HANDLETYPE hComponent) SEC_OSAL_SemaphoreWait(pVideoDec->NBDecThread.hDecFrameStart); if (pVideoDec->NBDecThread.bExitDecodeThread == OMX_FALSE) { -#ifdef CONFIG_MFC_FPS - SEC_OSAL_PerfStart(PERF_ID_DEC); -#endif pH264Dec->hMFCH264Handle.returnCodec = SsbSipMfcDecExe(pH264Dec->hMFCH264Handle.hMFCHandle, pVideoDec->NBDecThread.oneFrameSize); -#ifdef CONFIG_MFC_FPS - SEC_OSAL_PerfStop(PERF_ID_DEC); -#endif SEC_OSAL_SemaphorePost(pVideoDec->NBDecThread.hDecFrameEnd); } } @@ -868,19 +797,12 @@ OMX_ERRORTYPE SEC_MFC_H264Dec_Init(OMX_COMPONENTTYPE *pOMXComponent) SEC_OMX_VIDEODEC_COMPONENT *pVideoDec = (SEC_OMX_VIDEODEC_COMPONENT *)pSECComponent->hComponentHandle; SEC_OMX_BASEPORT *pSECOutputPort = &pSECComponent->pSECPort[OUTPUT_PORT_INDEX]; SEC_H264DEC_HANDLE *pH264Dec = NULL; + OMX_PTR hMFCHandle = NULL; OMX_PTR pStreamBuffer = NULL; OMX_PTR pStreamPhyBuffer = NULL; - OMX_PTR hMFCHandle; - #ifdef S3D_SUPPORT OMX_S32 setConfVal = 0; #endif - CSC_METHOD csc_method = CSC_METHOD_SW; - -#ifdef CONFIG_MFC_FPS - SEC_OSAL_PerfInit(PERF_ID_DEC); - SEC_OSAL_PerfInit(PERF_ID_CSC); -#endif pH264Dec = (SEC_H264DEC_HANDLE *)((SEC_OMX_VIDEODEC_COMPONENT *)pSECComponent->hComponentHandle)->hCodecHandle; pH264Dec->hMFCH264Handle.bConfiguredMFC = OMX_FALSE; @@ -888,26 +810,19 @@ OMX_ERRORTYPE SEC_MFC_H264Dec_Init(OMX_COMPONENTTYPE *pOMXComponent) pSECComponent->bSaveFlagEOS = OMX_FALSE; /* MFC(Multi Function Codec) decoder and CMM(Codec Memory Management) driver open */ - if (pVideoDec->bDRMPlayerMode == OMX_FALSE) { - hMFCHandle = NULL; - - if (pSECOutputPort->portDefinition.format.video.eColorFormat == OMX_SEC_COLOR_FormatNV12TPhysicalAddress) { - hMFCHandle = (OMX_PTR)SsbSipMfcDecOpen(); - } else { - SSBIP_MFC_BUFFER_TYPE buf_type = CACHE; - hMFCHandle = (OMX_PTR)SsbSipMfcDecOpenExt(&buf_type); - } - - if (hMFCHandle == NULL) { - ret = OMX_ErrorInsufficientResources; - goto EXIT; - } - pH264Dec->hMFCH264Handle.hMFCHandle = hMFCHandle; + if (pSECOutputPort->portDefinition.format.video.eColorFormat == OMX_SEC_COLOR_FormatNV12TPhysicalAddress) { + hMFCHandle = (OMX_PTR)SsbSipMfcDecOpen(); } else { - hMFCHandle = pH264Dec->hMFCH264Handle.hMFCHandle; - pSECComponent->bUseFlagEOF = OMX_TRUE; + SSBIP_MFC_BUFFER_TYPE buf_type = CACHE; + hMFCHandle = (OMX_PTR)SsbSipMfcDecOpenExt(&buf_type); } + if (hMFCHandle == NULL) { + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + pH264Dec->hMFCH264Handle.hMFCHandle = hMFCHandle; + #ifdef S3D_SUPPORT /*Enable SEI parsing for checking frame_packing S3D*/ setConfVal = 1; @@ -916,50 +831,48 @@ OMX_ERRORTYPE SEC_MFC_H264Dec_Init(OMX_COMPONENTTYPE *pOMXComponent) /* Allocate decoder's input buffer */ /* Get first input buffer */ - if (pVideoDec->bDRMPlayerMode == OMX_FALSE) { - pStreamBuffer = SsbSipMfcDecGetInBuf(hMFCHandle, &pStreamPhyBuffer, DEFAULT_MFC_INPUT_BUFFER_SIZE / 2); - if (pStreamBuffer == NULL) { - ret = OMX_ErrorInsufficientResources; - goto EXIT; - } - pVideoDec->MFCDecInputBuffer[0].VirAddr = pStreamBuffer; - pVideoDec->MFCDecInputBuffer[0].PhyAddr = pStreamPhyBuffer; - pVideoDec->MFCDecInputBuffer[0].bufferSize = DEFAULT_MFC_INPUT_BUFFER_SIZE / 2; - pVideoDec->MFCDecInputBuffer[0].dataSize = 0; + pStreamBuffer = SsbSipMfcDecGetInBuf(hMFCHandle, &pStreamPhyBuffer, DEFAULT_MFC_INPUT_BUFFER_SIZE / 2); + if (pStreamBuffer == NULL) { + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + pVideoDec->MFCDecInputBuffer[0].VirAddr = pStreamBuffer; + pVideoDec->MFCDecInputBuffer[0].PhyAddr = pStreamPhyBuffer; + pVideoDec->MFCDecInputBuffer[0].bufferSize = DEFAULT_MFC_INPUT_BUFFER_SIZE / 2; + pVideoDec->MFCDecInputBuffer[0].dataSize = 0; #ifdef NONBLOCK_MODE_PROCESS - /* Get second input buffer */ - pStreamBuffer = NULL; - pStreamBuffer = SsbSipMfcDecGetInBuf(hMFCHandle, &pStreamPhyBuffer, DEFAULT_MFC_INPUT_BUFFER_SIZE / 2); - if (pStreamBuffer == NULL) { - ret = OMX_ErrorInsufficientResources; - goto EXIT; - } - pVideoDec->MFCDecInputBuffer[1].VirAddr = pStreamBuffer; - pVideoDec->MFCDecInputBuffer[1].PhyAddr = pStreamPhyBuffer; - pVideoDec->MFCDecInputBuffer[1].bufferSize = DEFAULT_MFC_INPUT_BUFFER_SIZE / 2; - pVideoDec->MFCDecInputBuffer[1].dataSize = 0; - pVideoDec->indexInputBuffer = 0; + /* Get second input buffer */ + pStreamBuffer = NULL; + pStreamBuffer = SsbSipMfcDecGetInBuf(hMFCHandle, &pStreamPhyBuffer, DEFAULT_MFC_INPUT_BUFFER_SIZE / 2); + if (pStreamBuffer == NULL) { + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + pVideoDec->MFCDecInputBuffer[1].VirAddr = pStreamBuffer; + pVideoDec->MFCDecInputBuffer[1].PhyAddr = pStreamPhyBuffer; + pVideoDec->MFCDecInputBuffer[1].bufferSize = DEFAULT_MFC_INPUT_BUFFER_SIZE / 2; + pVideoDec->MFCDecInputBuffer[1].dataSize = 0; + pVideoDec->indexInputBuffer = 0; - pVideoDec->bFirstFrame = OMX_TRUE; + pVideoDec->bFirstFrame = OMX_TRUE; - pVideoDec->NBDecThread.bExitDecodeThread = OMX_FALSE; - pVideoDec->NBDecThread.bDecoderRun = OMX_FALSE; - pVideoDec->NBDecThread.oneFrameSize = 0; - SEC_OSAL_SemaphoreCreate(&(pVideoDec->NBDecThread.hDecFrameStart)); - SEC_OSAL_SemaphoreCreate(&(pVideoDec->NBDecThread.hDecFrameEnd)); - if (OMX_ErrorNone == SEC_OSAL_ThreadCreate(&pVideoDec->NBDecThread.hNBDecodeThread, - SEC_MFC_DecodeThread, - pOMXComponent)) { - pH264Dec->hMFCH264Handle.returnCodec = MFC_RET_OK; - } + pVideoDec->NBDecThread.bExitDecodeThread = OMX_FALSE; + pVideoDec->NBDecThread.bDecoderRun = OMX_FALSE; + pVideoDec->NBDecThread.oneFrameSize = 0; + SEC_OSAL_SemaphoreCreate(&(pVideoDec->NBDecThread.hDecFrameStart)); + SEC_OSAL_SemaphoreCreate(&(pVideoDec->NBDecThread.hDecFrameEnd)); + if (OMX_ErrorNone == SEC_OSAL_ThreadCreate(&pVideoDec->NBDecThread.hNBDecodeThread, + SEC_MFC_DecodeThread, + pOMXComponent)) { + pH264Dec->hMFCH264Handle.returnCodec = MFC_RET_OK; + } #endif - pH264Dec->hMFCH264Handle.pMFCStreamBuffer = pVideoDec->MFCDecInputBuffer[0].VirAddr; - pH264Dec->hMFCH264Handle.pMFCStreamPhyBuffer = pVideoDec->MFCDecInputBuffer[0].PhyAddr; - pSECComponent->processData[INPUT_PORT_INDEX].dataBuffer = pVideoDec->MFCDecInputBuffer[0].VirAddr; - pSECComponent->processData[INPUT_PORT_INDEX].allocSize = pVideoDec->MFCDecInputBuffer[0].bufferSize; - } + pH264Dec->hMFCH264Handle.pMFCStreamBuffer = pVideoDec->MFCDecInputBuffer[0].VirAddr; + pH264Dec->hMFCH264Handle.pMFCStreamPhyBuffer = pVideoDec->MFCDecInputBuffer[0].PhyAddr; + pSECComponent->processData[INPUT_PORT_INDEX].dataBuffer = pVideoDec->MFCDecInputBuffer[0].VirAddr; + pSECComponent->processData[INPUT_PORT_INDEX].allocSize = pVideoDec->MFCDecInputBuffer[0].bufferSize; SEC_OSAL_Memset(pSECComponent->timeStamp, -19771003, sizeof(OMX_TICKS) * MAX_TIMESTAMP); SEC_OSAL_Memset(pSECComponent->nFlags, 0, sizeof(OMX_U32) * MAX_FLAGS); @@ -968,19 +881,9 @@ OMX_ERRORTYPE SEC_MFC_H264Dec_Init(OMX_COMPONENTTYPE *pOMXComponent) pSECComponent->getAllDelayBuffer = OMX_FALSE; -#ifdef USE_ANB -#if defined(USE_CSC_FIMC) || defined(USE_CSC_GSCALER) - if (pSECOutputPort->bIsANBEnabled == OMX_TRUE) - csc_method = CSC_METHOD_PREFER_HW; +#ifdef USE_CSC_FIMC + pH264Dec->hFIMCHandle = csc_fimc_open(); #endif - if (pVideoDec->bDRMPlayerMode == OMX_TRUE) { - csc_method = CSC_METHOD_HW; - } -#endif - pVideoDec->csc_handle = csc_init(&csc_method); - pVideoDec->csc_set_format = OMX_FALSE; - - SEC_OSAL_Log(SEC_LOG_ERROR, "%s::csc_method=%d", __func__, csc_method); EXIT: FunctionOut(); @@ -999,11 +902,6 @@ OMX_ERRORTYPE SEC_MFC_H264Dec_Terminate(OMX_COMPONENTTYPE *pOMXComponent) FunctionIn(); -#ifdef CONFIG_MFC_FPS - SEC_OSAL_PerfPrint("[DEC]", PERF_ID_DEC); - SEC_OSAL_PerfPrint("[CSC]", PERF_ID_CSC); -#endif - pH264Dec = (SEC_H264DEC_HANDLE *)((SEC_OMX_VIDEODEC_COMPONENT *)pSECComponent->hComponentHandle)->hCodecHandle; hMFCHandle = pH264Dec->hMFCH264Handle.hMFCHandle; @@ -1012,38 +910,36 @@ OMX_ERRORTYPE SEC_MFC_H264Dec_Terminate(OMX_COMPONENTTYPE *pOMXComponent) pSECComponent->processData[INPUT_PORT_INDEX].dataBuffer = NULL; pSECComponent->processData[INPUT_PORT_INDEX].allocSize = 0; - if (pVideoDec->bDRMPlayerMode == OMX_FALSE) { #ifdef NONBLOCK_MODE_PROCESS - if (pVideoDec->NBDecThread.hNBDecodeThread != NULL) { - pVideoDec->NBDecThread.bExitDecodeThread = OMX_TRUE; - SEC_OSAL_SemaphorePost(pVideoDec->NBDecThread.hDecFrameStart); - SEC_OSAL_ThreadTerminate(pVideoDec->NBDecThread.hNBDecodeThread); - pVideoDec->NBDecThread.hNBDecodeThread = NULL; - } + if (pVideoDec->NBDecThread.hNBDecodeThread != NULL) { + pVideoDec->NBDecThread.bExitDecodeThread = OMX_TRUE; + SEC_OSAL_SemaphorePost(pVideoDec->NBDecThread.hDecFrameStart); + SEC_OSAL_ThreadTerminate(pVideoDec->NBDecThread.hNBDecodeThread); + pVideoDec->NBDecThread.hNBDecodeThread = NULL; + } - if(pVideoDec->NBDecThread.hDecFrameEnd != NULL) { - SEC_OSAL_SemaphoreTerminate(pVideoDec->NBDecThread.hDecFrameEnd); - pVideoDec->NBDecThread.hDecFrameEnd = NULL; - } + if(pVideoDec->NBDecThread.hDecFrameEnd != NULL) { + SEC_OSAL_SemaphoreTerminate(pVideoDec->NBDecThread.hDecFrameEnd); + pVideoDec->NBDecThread.hDecFrameEnd = NULL; + } - if(pVideoDec->NBDecThread.hDecFrameStart != NULL) { - SEC_OSAL_SemaphoreTerminate(pVideoDec->NBDecThread.hDecFrameStart); - pVideoDec->NBDecThread.hDecFrameStart = NULL; - } + if(pVideoDec->NBDecThread.hDecFrameStart != NULL) { + SEC_OSAL_SemaphoreTerminate(pVideoDec->NBDecThread.hDecFrameStart); + pVideoDec->NBDecThread.hDecFrameStart = NULL; + } #endif + + if (hMFCHandle != NULL) { + SsbSipMfcDecClose(hMFCHandle); + hMFCHandle = pH264Dec->hMFCH264Handle.hMFCHandle = NULL; } - if (pVideoDec->bDRMPlayerMode == OMX_FALSE) { - if (hMFCHandle != NULL) { - SsbSipMfcDecClose(hMFCHandle); - hMFCHandle = pH264Dec->hMFCH264Handle.hMFCHandle = NULL; - } - } - - if (pVideoDec->csc_handle != NULL) { - csc_deinit(pVideoDec->csc_handle); - pVideoDec->csc_handle = NULL; +#ifdef USE_CSC_FIMC + if (pH264Dec->hFIMCHandle != NULL) { + csc_fimc_close(pH264Dec->hFIMCHandle); + pH264Dec->hFIMCHandle = NULL; } +#endif EXIT: FunctionOut(); @@ -1459,20 +1355,13 @@ OMX_ERRORTYPE SEC_MFC_H264_Decode_Nonblock(OMX_COMPONENTTYPE *pOMXComponent, SEC /** Fill Output Buffer **/ if (outputDataValid == OMX_TRUE) { void *pOutputBuf = (void *)pOutputData->dataBuffer; - void *pSrcBuf[3] = {NULL, }; - void *pYUVBuf[3] = {NULL, }; - unsigned int csc_src_color_format, csc_dst_color_format; - CSC_METHOD csc_method = CSC_METHOD_SW; - unsigned int cacheable = 1; + void *pYUVBuf[3]; int frameSize = bufWidth * bufHeight; int actualWidth = outputInfo.img_width; int actualHeight = outputInfo.img_height; int actualImageSize = actualWidth * actualHeight; - pSrcBuf[0] = outputInfo.YVirAddr; - pSrcBuf[1] = outputInfo.CVirAddr; - pYUVBuf[0] = (unsigned char *)pOutputBuf; pYUVBuf[1] = (unsigned char *)pOutputBuf + actualImageSize; pYUVBuf[2] = (unsigned char *)pOutputBuf + actualImageSize + actualImageSize / 4; @@ -1486,20 +1375,16 @@ OMX_ERRORTYPE SEC_MFC_H264_Decode_Nonblock(OMX_COMPONENTTYPE *pOMXComponent, SEC pOutputData->dataLen = sizeof(void *); } #endif - if ((pVideoDec->bThumbnailMode == OMX_FALSE) && (pSECOutputPort->portDefinition.format.video.eColorFormat == OMX_SEC_COLOR_FormatNV12TPhysicalAddress)) { /* if use Post copy address structure */ - SEC_OSAL_Memcpy(pYUVBuf[0], &(outputInfo.YPhyAddr), sizeof(outputInfo.YPhyAddr)); - SEC_OSAL_Memcpy((unsigned char *)pYUVBuf[0] + (sizeof(void *) * 1), &(outputInfo.CPhyAddr), sizeof(outputInfo.CPhyAddr)); - SEC_OSAL_Memcpy((unsigned char *)pYUVBuf[0] + (sizeof(void *) * 2), &(outputInfo.YVirAddr), sizeof(outputInfo.YVirAddr)); - SEC_OSAL_Memcpy((unsigned char *)pYUVBuf[0] + (sizeof(void *) * 3), &(outputInfo.CVirAddr), sizeof(outputInfo.CVirAddr)); + SEC_OSAL_Memcpy(pOutputBuf, &(outputInfo.YPhyAddr), sizeof(outputInfo.YPhyAddr)); + SEC_OSAL_Memcpy((unsigned char *)pOutputBuf + (sizeof(void *) * 1), &(outputInfo.CPhyAddr), sizeof(outputInfo.CPhyAddr)); + SEC_OSAL_Memcpy((unsigned char *)pOutputBuf + (sizeof(void *) * 2), &(outputInfo.YVirAddr), sizeof(outputInfo.YVirAddr)); + SEC_OSAL_Memcpy((unsigned char *)pOutputBuf + (sizeof(void *) * 3), &(outputInfo.CVirAddr), sizeof(outputInfo.CVirAddr)); pOutputData->dataLen = (actualWidth * actualHeight * 3) / 2; } else { SEC_OSAL_Log(SEC_LOG_TRACE, "YUV420p out for ThumbnailMode/Flash player mode"); -#ifdef CONFIG_MFC_FPS - SEC_OSAL_PerfStart(PERF_ID_CSC); -#endif switch (pSECComponent->pSECPort[OUTPUT_PORT_INDEX].portDefinition.format.video.eColorFormat) { case OMX_SEC_COLOR_FormatNV12Tiled: #ifdef S3D_SUPPORT @@ -1520,8 +1405,28 @@ OMX_ERRORTYPE SEC_MFC_H264_Decode_Nonblock(OMX_COMPONENTTYPE *pOMXComponent, SEC case OMX_SEC_COLOR_FormatYUV420SemiPlanar_TB_RL: #endif case OMX_SEC_COLOR_FormatANBYUV420SemiPlanar: - csc_src_color_format = omx_2_hal_pixel_format((unsigned int)OMX_SEC_COLOR_FormatNV12Tiled); - csc_dst_color_format = omx_2_hal_pixel_format((unsigned int)OMX_COLOR_FormatYUV420SemiPlanar); +#ifdef USE_CSC_FIMC + if ((pSECOutputPort->bIsANBEnabled == OMX_TRUE) && (pH264Dec->hFIMCHandle != NULL)) { + void *pPhys[3]; + SEC_OSAL_GetPhysANB(pOutputData->dataBuffer, pPhys); + pYUVBuf[0] = outputInfo.YPhyAddr; + pYUVBuf[1] = outputInfo.CPhyAddr; + csc_fimc_convert_nv12t(pH264Dec->hFIMCHandle, pPhys, + pYUVBuf, actualWidth, actualHeight, + OMX_COLOR_FormatYUV420SemiPlanar); + break; + } +#endif + csc_tiled_to_linear_y_neon( + (unsigned char *)pYUVBuf[0], + (unsigned char *)outputInfo.YVirAddr, + actualWidth, + actualHeight); + csc_tiled_to_linear_uv_neon( + (unsigned char *)pYUVBuf[1], + (unsigned char *)outputInfo.CVirAddr, + actualWidth, + actualHeight / 2); break; case OMX_COLOR_FormatYUV420Planar: #ifdef S3D_SUPPORT @@ -1531,59 +1436,31 @@ OMX_ERRORTYPE SEC_MFC_H264_Decode_Nonblock(OMX_COMPONENTTYPE *pOMXComponent, SEC case OMX_SEC_COLOR_FormatYUV420Planar_TB_RL: #endif default: - csc_src_color_format = omx_2_hal_pixel_format((unsigned int)OMX_SEC_COLOR_FormatNV12Tiled); - csc_dst_color_format = omx_2_hal_pixel_format((unsigned int)OMX_COLOR_FormatYUV420Planar); +#ifdef USE_CSC_FIMC + if ((pSECOutputPort->bIsANBEnabled == OMX_TRUE) && (pH264Dec->hFIMCHandle != NULL)) { + void *pPhys[3]; + SEC_OSAL_GetPhysANB(pOutputData->dataBuffer, pPhys); + pYUVBuf[0] = outputInfo.YPhyAddr; + pYUVBuf[1] = outputInfo.CPhyAddr; + csc_fimc_convert_nv12t(pH264Dec->hFIMCHandle, pPhys, + pYUVBuf, actualWidth, actualHeight, + OMX_COLOR_FormatYUV420Planar); + break; + } +#endif + csc_tiled_to_linear_y_neon( + (unsigned char *)pYUVBuf[0], + (unsigned char *)outputInfo.YVirAddr, + actualWidth, + actualHeight); + csc_tiled_to_linear_uv_deinterleave_neon( + (unsigned char *)pYUVBuf[1], + (unsigned char *)pYUVBuf[2], + (unsigned char *)outputInfo.CVirAddr, + actualWidth, + actualHeight / 2); break; } - - csc_get_method(pVideoDec->csc_handle, &csc_method); -#ifdef USE_CSC_FIMC - if ((pSECOutputPort->bIsANBEnabled == OMX_TRUE) && (csc_method == CSC_METHOD_HW)) { - SEC_OSAL_GetPhysANB(pOutputData->dataBuffer, pYUVBuf); - pSrcBuf[0] = outputInfo.YPhyAddr; - pSrcBuf[1] = outputInfo.CPhyAddr; - } -#endif - if (pVideoDec->csc_set_format == OMX_FALSE) { - csc_set_src_format( - pVideoDec->csc_handle, /* handle */ - actualWidth, /* width */ - actualHeight, /* height */ - 0, /* crop_left */ - 0, /* crop_right */ - actualWidth, /* crop_width */ - actualHeight, /* crop_height */ - csc_src_color_format, /* color_format */ - cacheable); /* cacheable */ - csc_set_dst_format( - pVideoDec->csc_handle, /* handle */ - actualWidth, /* width */ - actualHeight, /* height */ - 0, /* crop_left */ - 0, /* crop_right */ - actualWidth, /* crop_width */ - actualHeight, /* crop_height */ - csc_dst_color_format, /* color_format */ - cacheable); /* cacheable */ - pVideoDec->csc_set_format = OMX_TRUE; - } - csc_set_src_buffer( - pVideoDec->csc_handle, /* handle */ - pSrcBuf[0], /* y addr */ - pSrcBuf[1], /* u addr or uv addr */ - pSrcBuf[2], /* v addr or none */ - 0); /* ion fd */ - csc_set_dst_buffer( - pVideoDec->csc_handle, /* handle */ - pYUVBuf[0], /* y addr */ - pYUVBuf[1], /* u addr or uv addr */ - pYUVBuf[2], /* v addr or none */ - 0); /* ion fd */ - csc_convert(pVideoDec->csc_handle); - -#ifdef CONFIG_MFC_FPS - SEC_OSAL_PerfStop(PERF_ID_CSC); -#endif } #ifdef USE_ANB if (pSECOutputPort->bIsANBEnabled == OMX_TRUE) { @@ -1786,20 +1663,13 @@ OMX_ERRORTYPE SEC_MFC_H264_Decode_Block(OMX_COMPONENTTYPE *pOMXComponent, SEC_OM (status == MFC_GETOUTBUF_DISPLAY_ONLY)) { /** Fill Output Buffer **/ void *pOutputBuf = (void *)pOutputData->dataBuffer; - void *pSrcBuf[3] = {NULL, }; - void *pYUVBuf[3] = {NULL, }; - unsigned int csc_src_color_format, csc_dst_color_format; - CSC_METHOD csc_method = CSC_METHOD_SW; - unsigned int cacheable = 1; + void *pYUVBuf[3]; int frameSize = bufWidth * bufHeight; int actualWidth = outputInfo.img_width; int actualHeight = outputInfo.img_height; int actualImageSize = actualWidth * actualHeight; - pSrcBuf[0] = outputInfo.YVirAddr; - pSrcBuf[1] = outputInfo.CVirAddr; - pYUVBuf[0] = (unsigned char *)pOutputBuf; pYUVBuf[1] = (unsigned char *)pOutputBuf + actualImageSize; pYUVBuf[2] = (unsigned char *)pOutputBuf + actualImageSize + actualImageSize / 4; @@ -1816,16 +1686,13 @@ OMX_ERRORTYPE SEC_MFC_H264_Decode_Block(OMX_COMPONENTTYPE *pOMXComponent, SEC_OM if ((pVideoDec->bThumbnailMode == OMX_FALSE) && (pSECOutputPort->portDefinition.format.video.eColorFormat == OMX_SEC_COLOR_FormatNV12TPhysicalAddress)) { /* if use Post copy address structure */ - SEC_OSAL_Memcpy(pYUVBuf[0], &(outputInfo.YPhyAddr), sizeof(outputInfo.YPhyAddr)); - SEC_OSAL_Memcpy((unsigned char *)pYUVBuf[0] + (sizeof(void *) * 1), &(outputInfo.CPhyAddr), sizeof(outputInfo.CPhyAddr)); - SEC_OSAL_Memcpy((unsigned char *)pYUVBuf[0] + (sizeof(void *) * 2), &(outputInfo.YVirAddr), sizeof(outputInfo.YVirAddr)); - SEC_OSAL_Memcpy((unsigned char *)pYUVBuf[0] + (sizeof(void *) * 3), &(outputInfo.CVirAddr), sizeof(outputInfo.CVirAddr)); + SEC_OSAL_Memcpy(pOutputBuf, &(outputInfo.YPhyAddr), sizeof(outputInfo.YPhyAddr)); + SEC_OSAL_Memcpy((unsigned char *)pOutputBuf + (sizeof(void *) * 1), &(outputInfo.CPhyAddr), sizeof(outputInfo.CPhyAddr)); + SEC_OSAL_Memcpy((unsigned char *)pOutputBuf + (sizeof(void *) * 2), &(outputInfo.YVirAddr), sizeof(outputInfo.YVirAddr)); + SEC_OSAL_Memcpy((unsigned char *)pOutputBuf + (sizeof(void *) * 3), &(outputInfo.CVirAddr), sizeof(outputInfo.CVirAddr)); pOutputData->dataLen = (actualWidth * actualHeight * 3) / 2; } else { SEC_OSAL_Log(SEC_LOG_TRACE, "YUV420p out for ThumbnailMode/Flash player mode"); -#ifdef CONFIG_MFC_FPS - SEC_OSAL_PerfStart(PERF_ID_CSC); -#endif switch (pSECComponent->pSECPort[OUTPUT_PORT_INDEX].portDefinition.format.video.eColorFormat) { case OMX_SEC_COLOR_FormatNV12Tiled: SEC_OSAL_Memcpy(pOutputBuf, outputInfo.YVirAddr, FrameBufferYSize); @@ -1834,64 +1701,56 @@ OMX_ERRORTYPE SEC_MFC_H264_Decode_Block(OMX_COMPONENTTYPE *pOMXComponent, SEC_OM break; case OMX_COLOR_FormatYUV420SemiPlanar: case OMX_SEC_COLOR_FormatANBYUV420SemiPlanar: - csc_src_color_format = omx_2_hal_pixel_format((unsigned int)OMX_SEC_COLOR_FormatNV12Tiled); - csc_dst_color_format = omx_2_hal_pixel_format((unsigned int)OMX_COLOR_FormatYUV420SemiPlanar); +#ifdef USE_CSC_FIMC + if ((pSECOutputPort->bIsANBEnabled == OMX_TRUE) && (pH264Dec->hFIMCHandle != NULL)) { + void *pPhys[3]; + SEC_OSAL_GetPhysANB(pOutputData->dataBuffer, pPhys); + pYUVBuf[0] = outputInfo.YPhyAddr; + pYUVBuf[1] = outputInfo.CPhyAddr; + csc_fimc_convert_nv12t(pH264Dec->hFIMCHandle, pPhys, + pYUVBuf, actualWidth, actualHeight, + OMX_SEC_COLOR_FormatANBYUV420SemiPlanar); + break; + } +#endif + csc_tiled_to_linear_y_neon( + (unsigned char *)pYUVBuf[0], + (unsigned char *)outputInfo.YVirAddr, + actualWidth, + actualHeight); + csc_tiled_to_linear_uv_neon( + (unsigned char *)pYUVBuf[1], + (unsigned char *)outputInfo.CVirAddr, + actualWidth, + actualHeight / 2); break; case OMX_COLOR_FormatYUV420Planar: default: - csc_src_color_format = omx_2_hal_pixel_format((unsigned int)OMX_SEC_COLOR_FormatNV12Tiled); - csc_dst_color_format = omx_2_hal_pixel_format((unsigned int)OMX_COLOR_FormatYUV420Planar); +#ifdef USE_CSC_FIMC + if ((pSECOutputPort->bIsANBEnabled == OMX_TRUE) && (pH264Dec->hFIMCHandle != NULL)) { + void *pPhys[3]; + SEC_OSAL_GetPhysANB(pOutputData->dataBuffer, pPhys); + pYUVBuf[0] = outputInfo.YPhyAddr; + pYUVBuf[1] = outputInfo.CPhyAddr; + csc_fimc_convert_nv12t(pH264Dec->hFIMCHandle, pPhys, + pYUVBuf, actualWidth, actualHeight, + OMX_COLOR_FormatYUV420Planar); + break; + } +#endif + csc_tiled_to_linear_y_neon( + (unsigned char *)pYUVBuf[0], + (unsigned char *)outputInfo.YVirAddr, + actualWidth, + actualHeight); + csc_tiled_to_linear_uv_deinterleave_neon( + (unsigned char *)pYUVBuf[1], + (unsigned char *)pYUVBuf[2], + (unsigned char *)outputInfo.CVirAddr, + actualWidth, + actualHeight / 2); break; } - - csc_get_method(pVideoDec->csc_handle, &csc_method); -#ifdef USE_CSC_FIMC - if ((pSECOutputPort->bIsANBEnabled == OMX_TRUE) && (csc_method == CSC_METHOD_HW)) { - SEC_OSAL_GetPhysANB(pOutputData->dataBuffer, pYUVBuf); - pSrcBuf[0] = outputInfo.YPhyAddr; - pSrcBuf[1] = outputInfo.CPhyAddr; - } -#endif - if (pVideoDec->csc_set_format == OMX_FALSE) { - csc_set_src_format( - pVideoDec->csc_handle, /* handle */ - actualWidth, /* width */ - actualHeight, /* height */ - 0, /* crop_left */ - 0, /* crop_right */ - actualWidth, /* crop_width */ - actualHeight, /* crop_height */ - csc_src_color_format, /* color_format */ - cacheable); /* cacheable */ - csc_set_dst_format( - pVideoDec->csc_handle, /* handle */ - actualWidth, /* width */ - actualHeight, /* height */ - 0, /* crop_left */ - 0, /* crop_right */ - actualWidth, /* crop_width */ - actualHeight, /* crop_height */ - csc_dst_color_format, /* color_format */ - cacheable); /* cacheable */ - pVideoDec->csc_set_format = OMX_TRUE; - } - csc_set_src_buffer( - pVideoDec->csc_handle, /* handle */ - pSrcBuf[0], /* y addr */ - pSrcBuf[1], /* u addr or uv addr */ - pSrcBuf[2], /* v addr or none */ - 0); /* ion fd */ - csc_set_dst_buffer( - pVideoDec->csc_handle, /* handle */ - pYUVBuf[0], /* y addr */ - pYUVBuf[1], /* u addr or uv addr */ - pYUVBuf[2], /* v addr or none */ - 0); /* ion fd */ - csc_convert(pVideoDec->csc_handle); - -#ifdef CONFIG_MFC_FPS - SEC_OSAL_PerfStop(PERF_ID_CSC); -#endif } #ifdef USE_ANB @@ -1960,377 +1819,11 @@ EXIT: return ret; } -OMX_ERRORTYPE SEC_MFC_H264_Decode_DRM(OMX_COMPONENTTYPE *pOMXComponent, SEC_OMX_DATA *pInputData, SEC_OMX_DATA *pOutputData) -{ - OMX_ERRORTYPE ret = OMX_ErrorNone; - SEC_OMX_BASECOMPONENT *pSECComponent = (SEC_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; - SEC_OMX_VIDEODEC_COMPONENT *pVideoDec = (SEC_OMX_VIDEODEC_COMPONENT *)pSECComponent->hComponentHandle; - SEC_OMX_BASEPORT *pSECInputPort = &pSECComponent->pSECPort[INPUT_PORT_INDEX]; - SEC_OMX_BASEPORT *pSECOutputPort = &pSECComponent->pSECPort[OUTPUT_PORT_INDEX]; - SEC_H264DEC_HANDLE *pH264Dec = (SEC_H264DEC_HANDLE *)((SEC_OMX_VIDEODEC_COMPONENT *)pSECComponent->hComponentHandle)->hCodecHandle; - OMX_U32 oneFrameSize = pInputData->dataLen; - SSBSIP_MFC_DEC_OUTPUT_INFO outputInfo; - OMX_S32 setConfVal = 0; - OMX_S32 returnCodec = 0; - int bufWidth = 0; - int bufHeight = 0; - OMX_U32 FrameBufferYSize; - OMX_U32 FrameBufferUVSize; - // DRM - OMX_PTR pInputPhysBuffer; - OMX_PTR pInputVirtBuffer; - - FunctionIn(); - - if (pH264Dec->hMFCH264Handle.bConfiguredMFC == OMX_FALSE) { - SSBSIP_MFC_CODEC_TYPE eCodecType = H264_DEC; - - if ((oneFrameSize <= 0) && (pInputData->nFlags & OMX_BUFFERFLAG_EOS)) { - pOutputData->timeStamp = pInputData->timeStamp; - pOutputData->nFlags = pInputData->nFlags; - ret = OMX_ErrorNone; - goto EXIT; - } - - /* Set the number of extra buffer to prevent tearing */ - /* DRM Play mode is returned only PhysicalAddress */ - setConfVal = H264_DEC_NUM_OF_EXTRA_BUFFERS; - SsbSipMfcDecSetConfig(pH264Dec->hMFCH264Handle.hMFCHandle, MFC_DEC_SETCONF_EXTRA_BUFFER_NUM, &setConfVal); - - /* Default number in the driver is optimized */ - if (pVideoDec->bThumbnailMode == OMX_TRUE) { - setConfVal = 0; - SsbSipMfcDecSetConfig(pH264Dec->hMFCH264Handle.hMFCHandle, MFC_DEC_SETCONF_DISPLAY_DELAY, &setConfVal); - } else { - setConfVal = 8; - SsbSipMfcDecSetConfig(pH264Dec->hMFCH264Handle.hMFCHandle, MFC_DEC_SETCONF_DISPLAY_DELAY, &setConfVal); - } - - pInputPhysBuffer = pSECComponent->processData[INPUT_PORT_INDEX].dataBuffer; - pInputVirtBuffer = NULL; /* ??????????? */ - - SEC_OSAL_Log(SEC_LOG_ERROR, "pInputPhysBuffer = 0x%x, allocSize = 0x%0x", pInputPhysBuffer, pSECComponent->processData[INPUT_PORT_INDEX].allocSize); - - SsbSipMfcDecSetInBuf(pH264Dec->hMFCH264Handle.hMFCHandle, - pInputPhysBuffer, pInputVirtBuffer, - pSECComponent->processData[INPUT_PORT_INDEX].allocSize); - - returnCodec = SsbSipMfcDecInit(pH264Dec->hMFCH264Handle.hMFCHandle, eCodecType, oneFrameSize); - if (returnCodec == MFC_RET_OK) { - SSBSIP_MFC_IMG_RESOLUTION imgResol; - SSBSIP_MFC_CROP_INFORMATION cropInfo; - - SsbSipMfcDecGetConfig(pH264Dec->hMFCH264Handle.hMFCHandle, MFC_DEC_GETCONF_BUF_WIDTH_HEIGHT, &imgResol); - SEC_OSAL_Log(SEC_LOG_TRACE, "set width height information : %d, %d", - pSECInputPort->portDefinition.format.video.nFrameWidth, - pSECInputPort->portDefinition.format.video.nFrameHeight); - SEC_OSAL_Log(SEC_LOG_TRACE, "mfc width height information : %d, %d", - imgResol.width, imgResol.height); - - SsbSipMfcDecGetConfig(pH264Dec->hMFCH264Handle.hMFCHandle, MFC_DEC_GETCONF_CROP_INFO, &cropInfo); - SEC_OSAL_Log(SEC_LOG_TRACE, "mfc crop_top crop_bottom crop_left crop_right : %d, %d, %d, %d", - cropInfo.crop_top_offset , cropInfo.crop_bottom_offset , - cropInfo.crop_left_offset , cropInfo.crop_right_offset); - - pSECOutputPort->cropRectangle.nTop = cropInfo.crop_top_offset; - pSECOutputPort->cropRectangle.nLeft = cropInfo.crop_left_offset; - pSECOutputPort->cropRectangle.nWidth = imgResol.width - cropInfo.crop_left_offset - cropInfo.crop_right_offset; - pSECOutputPort->cropRectangle.nHeight = imgResol.height - cropInfo.crop_top_offset - cropInfo.crop_bottom_offset; - - pH264Dec->hMFCH264Handle.bConfiguredMFC = OMX_TRUE; - - /** Update Frame Size **/ - if ((cropInfo.crop_left_offset != 0) || (cropInfo.crop_right_offset != 0) || - (cropInfo.crop_top_offset != 0) || (cropInfo.crop_bottom_offset != 0)) { - /* change width and height information */ - pSECInputPort->portDefinition.format.video.nFrameWidth = imgResol.width; - pSECInputPort->portDefinition.format.video.nFrameHeight = imgResol.height; - pSECInputPort->portDefinition.format.video.nStride = ((imgResol.width + 15) & (~15)); - pSECInputPort->portDefinition.format.video.nSliceHeight = ((imgResol.height + 15) & (~15)); - - SEC_UpdateFrameSize(pOMXComponent); - - /** Send crop info call back **/ - (*(pSECComponent->pCallbacks->EventHandler)) - (pOMXComponent, - pSECComponent->callbackData, - OMX_EventPortSettingsChanged, /* The command was completed */ - OMX_DirOutput, /* This is the port index */ - OMX_IndexConfigCommonOutputCrop, - NULL); - } - if ((pSECInputPort->portDefinition.format.video.nFrameWidth != (unsigned int)imgResol.width) || - (pSECInputPort->portDefinition.format.video.nFrameHeight != (unsigned int)imgResol.height)) { - SEC_OSAL_Log(SEC_LOG_TRACE, "change width height information : OMX_EventPortSettingsChanged"); - /* change width and height information */ - pSECInputPort->portDefinition.format.video.nFrameWidth = imgResol.width; - pSECInputPort->portDefinition.format.video.nFrameHeight = imgResol.height; - pSECInputPort->portDefinition.format.video.nStride = ((imgResol.width + 15) & (~15)); - pSECInputPort->portDefinition.format.video.nSliceHeight = ((imgResol.height + 15) & (~15)); - - SEC_UpdateFrameSize(pOMXComponent); - - /** Send Port Settings changed call back **/ - (*(pSECComponent->pCallbacks->EventHandler)) - (pOMXComponent, - pSECComponent->callbackData, - OMX_EventPortSettingsChanged, /* The command was completed */ - OMX_DirOutput, /* This is the port index */ - 0, - NULL); - } - -#ifdef ADD_SPS_PPS_I_FRAME - ret = OMX_ErrorInputDataDecodeYet; -#else - pOutputData->timeStamp = pInputData->timeStamp; - pOutputData->nFlags = pInputData->nFlags; - - ret = OMX_ErrorNone; -#endif - goto EXIT; - } else { - ret = OMX_ErrorMFCInit; - goto EXIT; - } - } - - if ((pInputData->dataBuffer != NULL) && (pInputData->dataLen != 0)) { - pSECComponent->timeStamp[pH264Dec->hMFCH264Handle.indexTimestamp] = pInputData->timeStamp; - pSECComponent->nFlags[pH264Dec->hMFCH264Handle.indexTimestamp] = pInputData->nFlags; - SsbSipMfcDecSetConfig(pH264Dec->hMFCH264Handle.hMFCHandle, MFC_DEC_SETCONF_FRAME_TAG, &(pH264Dec->hMFCH264Handle.indexTimestamp)); - if (pVideoDec->bDRMPlayerMode == OMX_TRUE) { - pInputPhysBuffer = pSECComponent->processData[INPUT_PORT_INDEX].dataBuffer; - pInputVirtBuffer = NULL; /* ??????????? */ - - SsbSipMfcDecSetInBuf(pH264Dec->hMFCH264Handle.hMFCHandle, - pInputPhysBuffer, pInputVirtBuffer, - pSECComponent->processData[INPUT_PORT_INDEX].allocSize); - } - returnCodec = SsbSipMfcDecExe(pH264Dec->hMFCH264Handle.hMFCHandle, oneFrameSize); - } else { - if (pSECComponent->checkTimeStamp.needCheckStartTimeStamp == OMX_TRUE) - pSECComponent->checkTimeStamp.needSetStartTimeStamp = OMX_TRUE; - - pOutputData->timeStamp = pInputData->timeStamp; - pOutputData->nFlags = pInputData->nFlags; - returnCodec = MFC_RET_OK; - goto EXIT; - } - - if (returnCodec == MFC_RET_OK) { - SSBSIP_MFC_DEC_OUTBUF_STATUS status; - OMX_S32 indexTimestamp = 0; - - status = SsbSipMfcDecGetOutBuf(pH264Dec->hMFCH264Handle.hMFCHandle, &outputInfo); - bufWidth = (outputInfo.img_width + 15) & (~15); - bufHeight = (outputInfo.img_height + 15) & (~15); - FrameBufferYSize = ALIGN_TO_8KB(ALIGN_TO_128B(outputInfo.img_width) * ALIGN_TO_32B(outputInfo.img_height)); - FrameBufferUVSize = ALIGN_TO_8KB(ALIGN_TO_128B(outputInfo.img_width) * ALIGN_TO_32B(outputInfo.img_height/2)); - - if (status != MFC_GETOUTBUF_DISPLAY_ONLY) { - pH264Dec->hMFCH264Handle.indexTimestamp++; - pH264Dec->hMFCH264Handle.indexTimestamp %= MAX_TIMESTAMP; - } - - if ((SsbSipMfcDecGetConfig(pH264Dec->hMFCH264Handle.hMFCHandle, MFC_DEC_GETCONF_FRAME_TAG, &indexTimestamp) != MFC_RET_OK) || - (((indexTimestamp < 0) || (indexTimestamp >= MAX_TIMESTAMP)))) { - pOutputData->timeStamp = pInputData->timeStamp; - pOutputData->nFlags = pInputData->nFlags; - } else { - /* For timestamp correction. if mfc support frametype detect */ - SEC_OSAL_Log(SEC_LOG_TRACE, "disp_pic_frame_type: %d", outputInfo.disp_pic_frame_type); -#ifdef NEED_TIMESTAMP_REORDER - if ((outputInfo.disp_pic_frame_type == MFC_FRAME_TYPE_I_FRAME) || - (pH264Dec->hMFCH264Handle.bFlashPlayerMode != OMX_FALSE)) { - pOutputData->timeStamp = pSECComponent->timeStamp[indexTimestamp]; - pOutputData->nFlags = pSECComponent->nFlags[indexTimestamp]; - pH264Dec->hMFCH264Handle.outputIndexTimestamp = indexTimestamp; - } else { - pOutputData->timeStamp = pSECComponent->timeStamp[pH264Dec->hMFCH264Handle.outputIndexTimestamp]; - pOutputData->nFlags = pSECComponent->nFlags[pH264Dec->hMFCH264Handle.outputIndexTimestamp]; - } -#else - pOutputData->timeStamp = pSECComponent->timeStamp[indexTimestamp]; - pOutputData->nFlags = pSECComponent->nFlags[indexTimestamp]; -#endif - SEC_OSAL_Log(SEC_LOG_TRACE, "timestamp %lld us (%.2f secs)", pOutputData->timeStamp, pOutputData->timeStamp / 1E6); - } - - if ((status == MFC_GETOUTBUF_DISPLAY_DECODING) || - (status == MFC_GETOUTBUF_DISPLAY_ONLY)) { - /** Fill Output Buffer **/ - void *pOutputBuf = (void *)pOutputData->dataBuffer; - void *pSrcBuf[3] = {NULL, }; - void *pYUVBuf[3] = {NULL, }; - unsigned int csc_src_color_format, csc_dst_color_format; - CSC_METHOD csc_method = CSC_METHOD_SW; - unsigned int cacheable = 1; - - int frameSize = bufWidth * bufHeight; - int actualWidth = outputInfo.img_width; - int actualHeight = outputInfo.img_height; - int actualImageSize = actualWidth * actualHeight; - - pSrcBuf[0] = outputInfo.YVirAddr; - pSrcBuf[1] = outputInfo.CVirAddr; - - pYUVBuf[0] = (unsigned char *)pOutputBuf; - pYUVBuf[1] = (unsigned char *)pOutputBuf + actualImageSize; - pYUVBuf[2] = (unsigned char *)pOutputBuf + actualImageSize + actualImageSize / 4; - pOutputData->dataLen = (actualImageSize * 3) / 2; - -#ifdef USE_ANB - if (pSECOutputPort->bIsANBEnabled == OMX_TRUE) { - OMX_U32 stride; - SEC_OSAL_LockANB(pOutputData->dataBuffer, actualWidth, actualHeight, pSECComponent->pSECPort[OUTPUT_PORT_INDEX].portDefinition.format.video.eColorFormat, &stride, pYUVBuf); - actualWidth = stride; - pOutputData->dataLen = sizeof(void *); - } -#endif - if (pSECOutputPort->portDefinition.format.video.eColorFormat == OMX_SEC_COLOR_FormatNV12TPhysicalAddress) { - /* if use Post copy address structure */ - SEC_OSAL_Log(SEC_LOG_TRACE, "DRM] physical address data mode"); - SEC_OSAL_Memcpy(pYUVBuf[0], &(outputInfo.YPhyAddr), sizeof(outputInfo.YPhyAddr)); - SEC_OSAL_Memcpy((unsigned char *)pYUVBuf[0] + (sizeof(void *) * 1), &(outputInfo.CPhyAddr), sizeof(outputInfo.CPhyAddr)); - SEC_OSAL_Memcpy((unsigned char *)pYUVBuf[0] + (sizeof(void *) * 2), &(outputInfo.YVirAddr), sizeof(outputInfo.YVirAddr)); - SEC_OSAL_Memcpy((unsigned char *)pYUVBuf[0] + (sizeof(void *) * 3), &(outputInfo.CVirAddr), sizeof(outputInfo.CVirAddr)); - pOutputData->dataLen = (actualWidth * actualHeight * 3) / 2; - } else { - SEC_OSAL_Log(SEC_LOG_TRACE, "DRM] Real data method"); -#ifdef CONFIG_MFC_FPS - SEC_OSAL_PerfStart(PERF_ID_CSC); -#endif - switch (pSECComponent->pSECPort[OUTPUT_PORT_INDEX].portDefinition.format.video.eColorFormat) { - case OMX_SEC_COLOR_FormatNV12Tiled: - SEC_OSAL_Memcpy(pOutputBuf, outputInfo.YVirAddr, FrameBufferYSize); - SEC_OSAL_Memcpy((unsigned char *)pOutputBuf + FrameBufferYSize, outputInfo.CVirAddr, FrameBufferUVSize); - pOutputData->dataLen = FrameBufferYSize + FrameBufferUVSize; - break; - case OMX_COLOR_FormatYUV420SemiPlanar: - case OMX_SEC_COLOR_FormatANBYUV420SemiPlanar: - csc_src_color_format = omx_2_hal_pixel_format((unsigned int)OMX_SEC_COLOR_FormatNV12Tiled); - csc_dst_color_format = omx_2_hal_pixel_format((unsigned int)OMX_COLOR_FormatYUV420SemiPlanar); - break; - case OMX_COLOR_FormatYUV420Planar: - default: - csc_src_color_format = omx_2_hal_pixel_format((unsigned int)OMX_SEC_COLOR_FormatNV12Tiled); - csc_dst_color_format = omx_2_hal_pixel_format((unsigned int)OMX_COLOR_FormatYUV420Planar); - break; - } - - csc_get_method(pVideoDec->csc_handle, &csc_method); -#ifdef USE_CSC_FIMC - if ((pSECOutputPort->bIsANBEnabled == OMX_TRUE) && (csc_method == CSC_METHOD_HW)) { - SEC_OSAL_GetPhysANB(pOutputData->dataBuffer, pYUVBuf); - pSrcBuf[0] = outputInfo.YPhyAddr; - pSrcBuf[1] = outputInfo.CPhyAddr; - } -#endif - if (pVideoDec->csc_set_format == OMX_FALSE) { - csc_set_src_format( - pVideoDec->csc_handle, /* handle */ - actualWidth, /* width */ - actualHeight, /* height */ - 0, /* crop_left */ - 0, /* crop_right */ - actualWidth, /* crop_width */ - actualHeight, /* crop_height */ - csc_src_color_format, /* color_format */ - cacheable); /* cacheable */ - csc_set_dst_format( - pVideoDec->csc_handle, /* handle */ - actualWidth, /* width */ - actualHeight, /* height */ - 0, /* crop_left */ - 0, /* crop_right */ - actualWidth, /* crop_width */ - actualHeight, /* crop_height */ - csc_dst_color_format, /* color_format */ - cacheable); /* cacheable */ - pVideoDec->csc_set_format = OMX_TRUE; - } - csc_set_src_buffer( - pVideoDec->csc_handle, /* handle */ - pSrcBuf[0], /* y addr */ - pSrcBuf[1], /* u addr or uv addr */ - pSrcBuf[2], /* v addr or none */ - 0); /* ion fd */ - csc_set_dst_buffer( - pVideoDec->csc_handle, /* handle */ - pYUVBuf[0], /* y addr */ - pYUVBuf[1], /* u addr or uv addr */ - pYUVBuf[2], /* v addr or none */ - 0); /* ion fd */ - csc_convert(pVideoDec->csc_handle); -#ifdef CONFIG_MFC_FPS - SEC_OSAL_PerfStop(PERF_ID_CSC); -#endif - } - -#ifdef USE_ANB - if (pSECOutputPort->bIsANBEnabled == OMX_TRUE) - SEC_OSAL_UnlockANB(pOutputData->dataBuffer); -#endif - pH264Dec->hMFCH264Handle.outputIndexTimestamp++; - pH264Dec->hMFCH264Handle.outputIndexTimestamp %= MAX_TIMESTAMP; - } - if (pOutputData->nFlags & OMX_BUFFERFLAG_EOS) - pOutputData->dataLen = 0; - - if ((status == MFC_GETOUTBUF_DISPLAY_ONLY) || - (pSECComponent->getAllDelayBuffer == OMX_TRUE)) - ret = OMX_ErrorInputDataDecodeYet; - - if (status == MFC_GETOUTBUF_DECODING_ONLY) { - if (((pInputData->nFlags & OMX_BUFFERFLAG_EOS) != OMX_BUFFERFLAG_EOS) && - ((pSECComponent->bSaveFlagEOS == OMX_TRUE) || (pSECComponent->getAllDelayBuffer == OMX_TRUE))) { - pInputData->nFlags |= OMX_BUFFERFLAG_EOS; - pSECComponent->getAllDelayBuffer = OMX_TRUE; - ret = OMX_ErrorInputDataDecodeYet; - } else { - ret = OMX_ErrorNone; - } - goto EXIT; - } - - if ((pInputData->nFlags & OMX_BUFFERFLAG_EOS) == OMX_BUFFERFLAG_EOS) { - pInputData->nFlags = (pOutputData->nFlags & (~OMX_BUFFERFLAG_EOS)); - pSECComponent->getAllDelayBuffer = OMX_TRUE; - ret = OMX_ErrorInputDataDecodeYet; - } else if ((pOutputData->nFlags & OMX_BUFFERFLAG_EOS) == OMX_BUFFERFLAG_EOS) { - pSECComponent->getAllDelayBuffer = OMX_FALSE; - ret = OMX_ErrorNone; - } - } else { - pOutputData->timeStamp = pInputData->timeStamp; - pOutputData->nFlags = pInputData->nFlags; - - if ((pSECComponent->bSaveFlagEOS == OMX_TRUE) || - (pSECComponent->getAllDelayBuffer == OMX_TRUE) || - (pInputData->nFlags & OMX_BUFFERFLAG_EOS)) { - pOutputData->nFlags |= OMX_BUFFERFLAG_EOS; - pSECComponent->getAllDelayBuffer = OMX_FALSE; - } - pOutputData->dataLen = 0; - - /* ret = OMX_ErrorUndefined; */ - ret = OMX_ErrorNone; - goto EXIT; - } - -EXIT: - FunctionOut(); - - return ret; -} - /* MFC Decode */ OMX_ERRORTYPE SEC_MFC_H264Dec_bufferProcess(OMX_COMPONENTTYPE *pOMXComponent, SEC_OMX_DATA *pInputData, SEC_OMX_DATA *pOutputData) { OMX_ERRORTYPE ret = OMX_ErrorNone; SEC_OMX_BASECOMPONENT *pSECComponent = (SEC_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; - SEC_OMX_VIDEODEC_COMPONENT *pVideoDec = (SEC_OMX_VIDEODEC_COMPONENT *)pSECComponent->hComponentHandle; SEC_H264DEC_HANDLE *pH264Dec = (SEC_H264DEC_HANDLE *)((SEC_OMX_VIDEODEC_COMPONENT *)pSECComponent->hComponentHandle)->hCodecHandle; SEC_OMX_BASEPORT *pSECInputPort = &pSECComponent->pSECPort[INPUT_PORT_INDEX]; SEC_OMX_BASEPORT *pSECOutputPort = &pSECComponent->pSECPort[OUTPUT_PORT_INDEX]; @@ -2348,16 +1841,11 @@ OMX_ERRORTYPE SEC_MFC_H264Dec_bufferProcess(OMX_COMPONENTTYPE *pOMXComponent, SE goto EXIT; } - if (pVideoDec->bDRMPlayerMode == OMX_FALSE) { #ifdef NONBLOCK_MODE_PROCESS - ret = SEC_MFC_H264_Decode_Nonblock(pOMXComponent, pInputData, pOutputData); + ret = SEC_MFC_H264_Decode_Nonblock(pOMXComponent, pInputData, pOutputData); #else - ret = SEC_MFC_H264_Decode_Block(pOMXComponent, pInputData, pOutputData); + ret = SEC_MFC_H264_Decode_Block(pOMXComponent, pInputData, pOutputData); #endif - } else { - ret = SEC_MFC_H264_Decode_DRM(pOMXComponent, pInputData, pOutputData); - } - if (ret != OMX_ErrorNone) { if (ret == OMX_ErrorInputDataDecodeYet) { pOutputData->usedDataLen = 0; @@ -2392,7 +1880,6 @@ OSCL_EXPORT_REF OMX_ERRORTYPE SEC_OMX_ComponentInit(OMX_HANDLETYPE hComponent, O SEC_OMX_BASEPORT *pSECPort = NULL; SEC_OMX_VIDEODEC_COMPONENT *pVideoDec = NULL; SEC_H264DEC_HANDLE *pH264Dec = NULL; - OMX_BOOL bDRMPlayerMode = OMX_FALSE; OMX_BOOL bFlashPlayerMode = OMX_FALSE; int i = 0; @@ -2404,13 +1891,8 @@ OSCL_EXPORT_REF OMX_ERRORTYPE SEC_OMX_ComponentInit(OMX_HANDLETYPE hComponent, O goto EXIT; } if (SEC_OSAL_Strcmp(SEC_OMX_COMPONENT_H264_DEC, componentName) == 0) { - bDRMPlayerMode = OMX_FALSE; - bFlashPlayerMode = OMX_FALSE; - } else if (SEC_OSAL_Strcmp(SEC_OMX_COMPONENT_H264_DRM_DEC, componentName) == 0) { - bDRMPlayerMode = OMX_TRUE; bFlashPlayerMode = OMX_FALSE; } else if (SEC_OSAL_Strcmp(SEC_OMX_COMPONENT_H264_FP_DEC, componentName) == 0) { - bDRMPlayerMode = OMX_FALSE; bFlashPlayerMode = OMX_TRUE; } else { ret = OMX_ErrorBadParameter; @@ -2447,14 +1929,11 @@ OSCL_EXPORT_REF OMX_ERRORTYPE SEC_OMX_ComponentInit(OMX_HANDLETYPE hComponent, O pVideoDec = (SEC_OMX_VIDEODEC_COMPONENT *)pSECComponent->hComponentHandle; pVideoDec->hCodecHandle = (OMX_HANDLETYPE)pH264Dec; - if (bDRMPlayerMode == OMX_TRUE) - SEC_OSAL_Strcpy(pSECComponent->componentName, SEC_OMX_COMPONENT_H264_DRM_DEC); - else if (bFlashPlayerMode == OMX_TRUE) - SEC_OSAL_Strcpy(pSECComponent->componentName, SEC_OMX_COMPONENT_H264_FP_DEC); - else + if (bFlashPlayerMode == OMX_FALSE) SEC_OSAL_Strcpy(pSECComponent->componentName, SEC_OMX_COMPONENT_H264_DEC); + else + SEC_OSAL_Strcpy(pSECComponent->componentName, SEC_OMX_COMPONENT_H264_FP_DEC); - pVideoDec->bDRMPlayerMode = bDRMPlayerMode; pH264Dec->hMFCH264Handle.bFlashPlayerMode = bFlashPlayerMode; #ifdef S3D_SUPPORT pH264Dec->hMFCH264Handle.bS3DMode = OMX_FALSE; @@ -2539,20 +2018,6 @@ OSCL_EXPORT_REF OMX_ERRORTYPE SEC_OMX_ComponentInit(OMX_HANDLETYPE hComponent, O pSECComponent->sec_mfc_bufferProcess = &SEC_MFC_H264Dec_bufferProcess; pSECComponent->sec_checkInputFrame = &Check_H264_Frame; - pSECComponent->sec_allocSecureInputBuffer = &SEC_MFC_H264Dec_Alloc_SecureInputBuffer; - pSECComponent->sec_freeSecureInputBuffer = &SEC_MFC_H264Dec_Free_SecureInputBuffer; - - if (bDRMPlayerMode == OMX_TRUE) { - OMX_PTR hMFCHandle = NULL; - SEC_OSAL_Log(SEC_LOG_ERROR, "DRM--SsbSipMfcDecOpen, Line:%d", __LINE__); - hMFCHandle = (OMX_PTR)SsbSipMfcDecOpen(); - if (hMFCHandle == NULL) { - ret = OMX_ErrorInsufficientResources; - goto EXIT; - } - pH264Dec->hMFCH264Handle.hMFCHandle = hMFCHandle; - } - pSECComponent->currentState = OMX_StateLoaded; ret = OMX_ErrorNone; @@ -2568,7 +2033,6 @@ OMX_ERRORTYPE SEC_OMX_ComponentDeinit(OMX_HANDLETYPE hComponent) OMX_ERRORTYPE ret = OMX_ErrorNone; OMX_COMPONENTTYPE *pOMXComponent = NULL; SEC_OMX_BASECOMPONENT *pSECComponent = NULL; - SEC_OMX_VIDEODEC_COMPONENT *pVideoDec = NULL; SEC_H264DEC_HANDLE *pH264Dec = NULL; FunctionIn(); @@ -2579,20 +2043,12 @@ OMX_ERRORTYPE SEC_OMX_ComponentDeinit(OMX_HANDLETYPE hComponent) } pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; pSECComponent = (SEC_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; - pVideoDec = (SEC_OMX_VIDEODEC_COMPONENT *)pSECComponent->hComponentHandle; SEC_OSAL_Free(pSECComponent->componentName); pSECComponent->componentName = NULL; pH264Dec = (SEC_H264DEC_HANDLE *)((SEC_OMX_VIDEODEC_COMPONENT *)pSECComponent->hComponentHandle)->hCodecHandle; if (pH264Dec != NULL) { - OMX_PTR hMFCHandle = NULL; - hMFCHandle = pH264Dec->hMFCH264Handle.hMFCHandle; - if ((hMFCHandle != NULL) && (pVideoDec->bDRMPlayerMode == OMX_TRUE)) { - SEC_OSAL_Log(SEC_LOG_ERROR, "DRM--SsbSipMfcDecClose, Line:%d", __LINE__); - SsbSipMfcDecClose(hMFCHandle); - hMFCHandle = pH264Dec->hMFCH264Handle.hMFCHandle = NULL; - } SEC_OSAL_Free(pH264Dec); pH264Dec = ((SEC_OMX_VIDEODEC_COMPONENT *)pSECComponent->hComponentHandle)->hCodecHandle = NULL; } diff --git a/exynos4/multimedia/openmax/sec_omx/component/video/dec/h264/SEC_OMX_H264dec.h b/exynos/multimedia/openmax/component/video/dec/h264/SEC_OMX_H264dec.h similarity index 96% rename from exynos4/multimedia/openmax/sec_omx/component/video/dec/h264/SEC_OMX_H264dec.h rename to exynos/multimedia/openmax/component/video/dec/h264/SEC_OMX_H264dec.h index 370a15f..06e3116 100644 --- a/exynos4/multimedia/openmax/sec_omx/component/video/dec/h264/SEC_OMX_H264dec.h +++ b/exynos/multimedia/openmax/component/video/dec/h264/SEC_OMX_H264dec.h @@ -58,6 +58,11 @@ typedef struct _SEC_H264DEC_HANDLE /* SEC MFC Codec specific */ SEC_MFC_H264DEC_HANDLE hMFCH264Handle; + + /* CSC FIMC handle */ +#ifdef USE_CSC_FIMC + OMX_PTR hFIMCHandle; +#endif } SEC_H264DEC_HANDLE; #ifdef __cplusplus diff --git a/exynos4/multimedia/openmax/sec_omx/component/video/dec/h264/library_register.c b/exynos/multimedia/openmax/component/video/dec/h264/library_register.c similarity index 86% rename from exynos4/multimedia/openmax/sec_omx/component/video/dec/h264/library_register.c rename to exynos/multimedia/openmax/component/video/dec/h264/library_register.c index aa63c6c..579a071 100644 --- a/exynos4/multimedia/openmax/sec_omx/component/video/dec/h264/library_register.c +++ b/exynos/multimedia/openmax/component/video/dec/h264/library_register.c @@ -52,11 +52,6 @@ OSCL_EXPORT_REF int SEC_OMX_COMPONENT_Library_Register(SECRegisterComponentType SEC_OSAL_Strcpy(secComponents[1]->roles[0], SEC_OMX_COMPONENT_H264_DEC_ROLE); secComponents[1]->totalRoleNum = MAX_COMPONENT_ROLE_NUM; - /* component 3 - video decoder H.264 for DRM */ - SEC_OSAL_Strcpy(secComponents[2]->componentName, SEC_OMX_COMPONENT_H264_DRM_DEC); - SEC_OSAL_Strcpy(secComponents[2]->roles[0], SEC_OMX_COMPONENT_H264_DEC_ROLE); - secComponents[2]->totalRoleNum = MAX_COMPONENT_ROLE_NUM; - EXIT: FunctionOut(); diff --git a/exynos4/multimedia/openmax/sec_omx/component/video/dec/h264/library_register.h b/exynos/multimedia/openmax/component/video/dec/h264/library_register.h similarity index 93% rename from exynos4/multimedia/openmax/sec_omx/component/video/dec/h264/library_register.h rename to exynos/multimedia/openmax/component/video/dec/h264/library_register.h index 8c03cbe..be7384b 100644 --- a/exynos4/multimedia/openmax/sec_omx/component/video/dec/h264/library_register.h +++ b/exynos/multimedia/openmax/component/video/dec/h264/library_register.h @@ -33,13 +33,12 @@ #define OSCL_EXPORT_REF __attribute__((visibility("default"))) -#define MAX_COMPONENT_NUM 3 +#define MAX_COMPONENT_NUM 2 #define MAX_COMPONENT_ROLE_NUM 1 /* H.264 */ #define SEC_OMX_COMPONENT_H264_DEC "OMX.SEC.AVC.Decoder" #define SEC_OMX_COMPONENT_H264_FP_DEC "OMX.SEC.FP.AVC.Decoder" -#define SEC_OMX_COMPONENT_H264_DRM_DEC "OMX.SEC.AVC.Decoder.secure" #define SEC_OMX_COMPONENT_H264_DEC_ROLE "video_decoder.avc" diff --git a/exynos4/multimedia/openmax/sec_omx/component/video/dec/mpeg4/Android.mk b/exynos/multimedia/openmax/component/video/dec/mpeg4/Android.mk similarity index 70% rename from exynos4/multimedia/openmax/sec_omx/component/video/dec/mpeg4/Android.mk rename to exynos/multimedia/openmax/component/video/dec/mpeg4/Android.mk index d353180..d45c727 100644 --- a/exynos4/multimedia/openmax/sec_omx/component/video/dec/mpeg4/Android.mk +++ b/exynos/multimedia/openmax/component/video/dec/mpeg4/Android.mk @@ -24,42 +24,29 @@ ifeq ($(BOARD_USE_V4L2_ION), false) LOCAL_CFLAGS += -DUSE_CSC_FIMC endif endif - -ifeq ($(BOARD_USE_CSC_GSCALER), true) -LOCAL_CFLAGS += -DUSE_CSC_GSCALER -endif endif LOCAL_ARM_MODE := arm LOCAL_STATIC_LIBRARIES := libSEC_OMX_Vdec libsecosal libsecbasecomponent \ - libswconverter libsecmfcapi + libseccscapi libsecmfcapi LOCAL_SHARED_LIBRARIES := libc libdl libcutils libutils libui \ - libSEC_OMX_Resourcemanager libcsc + libSEC_OMX_Resourcemanager ifeq ($(filter-out exynos4,$(TARGET_BOARD_PLATFORM)),) -LOCAL_SHARED_LIBRARIES += libfimc libhwconverter -endif - -ifeq ($(filter-out exynos5,$(TARGET_BOARD_PLATFORM)),) -LOCAL_SHARED_LIBRARIES += libexynosgscaler +LOCAL_SHARED_LIBRARIES += libhwconverter endif #ifeq ($(BOARD_USE_V4L2_ION),true) #LOCAL_SHARED_LIBRARIES += libion #endif -ifeq ($(BOARD_USES_MFC_FPS),true) -LOCAL_CFLAGS += -DCONFIG_MFC_FPS -endif - LOCAL_C_INCLUDES := $(SEC_OMX_INC)/khronos \ $(SEC_OMX_INC)/sec \ $(SEC_OMX_TOP)/osal \ $(SEC_OMX_TOP)/core \ $(SEC_OMX_COMPONENT)/common \ $(SEC_OMX_COMPONENT)/video/dec \ - $(TARGET_OUT_HEADERS)/$(SEC_COPY_HEADERS_TO) \ - $(BOARD_HAL_PATH)/include + $(TARGET_OUT_HEADERS)/$(SEC_COPY_HEADERS_TO) include $(BUILD_SHARED_LIBRARY) diff --git a/exynos4/multimedia/openmax/sec_omx/component/video/dec/mpeg4/SEC_OMX_Mpeg4dec.c b/exynos/multimedia/openmax/component/video/dec/mpeg4/SEC_OMX_Mpeg4dec.c similarity index 91% rename from exynos4/multimedia/openmax/sec_omx/component/video/dec/mpeg4/SEC_OMX_Mpeg4dec.c rename to exynos/multimedia/openmax/component/video/dec/mpeg4/SEC_OMX_Mpeg4dec.c index e820503..5969c71 100644 --- a/exynos4/multimedia/openmax/sec_omx/component/video/dec/mpeg4/SEC_OMX_Mpeg4dec.c +++ b/exynos/multimedia/openmax/component/video/dec/mpeg4/SEC_OMX_Mpeg4dec.c @@ -38,14 +38,17 @@ #include "library_register.h" #include "SEC_OMX_Mpeg4dec.h" #include "SsbSipMfcApi.h" +#include "color_space_convertor.h" #ifdef USE_ANB #include "SEC_OSAL_Android.h" #endif -/* To use CSC_METHOD_PREFER_HW or CSC_METHOD_HW in SEC OMX, gralloc should allocate physical memory using FIMC */ +/* To use CSC FIMC in SEC OMX, gralloc should allocate physical memory using FIMC */ /* It means GRALLOC_USAGE_HW_FIMC1 should be set on Native Window usage */ -#include "csc.h" +#ifdef USE_CSC_FIMC +#include "csc_fimc.h" +#endif #undef SEC_LOG_TAG #define SEC_LOG_TAG "SEC_MPEG4_DEC" @@ -923,13 +926,7 @@ OMX_ERRORTYPE SEC_MFC_DecodeThread(OMX_HANDLETYPE hComponent) SEC_OSAL_SemaphoreWait(pVideoDec->NBDecThread.hDecFrameStart); if (pVideoDec->NBDecThread.bExitDecodeThread == OMX_FALSE) { -#ifdef CONFIG_MFC_FPS - SEC_OSAL_PerfStart(PERF_ID_DEC); -#endif pMpeg4Dec->hMFCMpeg4Handle.returnCodec = SsbSipMfcDecExe(pMpeg4Dec->hMFCMpeg4Handle.hMFCHandle, pVideoDec->NBDecThread.oneFrameSize); -#ifdef CONFIG_MFC_FPS - SEC_OSAL_PerfStop(PERF_ID_DEC); -#endif SEC_OSAL_SemaphorePost(pVideoDec->NBDecThread.hDecFrameEnd); } } @@ -952,11 +949,6 @@ OMX_ERRORTYPE SEC_MFC_Mpeg4Dec_Init(OMX_COMPONENTTYPE *pOMXComponent) OMX_HANDLETYPE hMFCHandle = NULL; OMX_PTR pStreamBuffer = NULL; OMX_PTR pStreamPhyBuffer = NULL; -#ifdef CONFIG_MFC_FPS - SEC_OSAL_PerfInit(PERF_ID_DEC); - SEC_OSAL_PerfInit(PERF_ID_CSC); -#endif - CSC_METHOD csc_method = CSC_METHOD_SW; FunctionIn(); @@ -1031,15 +1023,9 @@ OMX_ERRORTYPE SEC_MFC_Mpeg4Dec_Init(OMX_COMPONENTTYPE *pOMXComponent) pSECComponent->getAllDelayBuffer = OMX_FALSE; -#ifdef USE_ANB -#if defined(USE_CSC_FIMC) || defined(USE_CSC_GSCALER) - if (pSECOutputPort->bIsANBEnabled == OMX_TRUE) { - csc_method = CSC_METHOD_PREFER_HW; - } +#ifdef USE_CSC_FIMC + pMpeg4Dec->hFIMCHandle = csc_fimc_open(); #endif -#endif - pVideoDec->csc_handle = csc_init(&csc_method); - pVideoDec->csc_set_format = OMX_FALSE; EXIT: FunctionOut(); @@ -1058,11 +1044,6 @@ OMX_ERRORTYPE SEC_MFC_Mpeg4Dec_Terminate(OMX_COMPONENTTYPE *pOMXComponent) FunctionIn(); -#ifdef CONFIG_MFC_FPS - SEC_OSAL_PerfPrint("[DEC]", PERF_ID_DEC); - SEC_OSAL_PerfPrint("[CSC]", PERF_ID_CSC); -#endif - pMpeg4Dec = (SEC_MPEG4_HANDLE *)((SEC_OMX_VIDEODEC_COMPONENT *)pSECComponent->hComponentHandle)->hCodecHandle; hMFCHandle = pMpeg4Dec->hMFCMpeg4Handle.hMFCHandle; @@ -1096,10 +1077,12 @@ OMX_ERRORTYPE SEC_MFC_Mpeg4Dec_Terminate(OMX_COMPONENTTYPE *pOMXComponent) pMpeg4Dec->hMFCMpeg4Handle.hMFCHandle = NULL; } - if (pVideoDec->csc_handle != NULL) { - csc_deinit(pVideoDec->csc_handle); - pVideoDec->csc_handle = NULL; +#ifdef USE_CSC_FIMC + if (pMpeg4Dec->hFIMCHandle != NULL) { + csc_fimc_close(pMpeg4Dec->hFIMCHandle); + pMpeg4Dec->hFIMCHandle = NULL; } +#endif EXIT: FunctionOut(); @@ -1385,20 +1368,13 @@ OMX_ERRORTYPE SEC_MFC_Mpeg4_Decode_Nonblock(OMX_COMPONENTTYPE *pOMXComponent, SE /** Fill Output Buffer **/ if (outputDataValid == OMX_TRUE) { void *pOutputBuf = (void *)pOutputData->dataBuffer; - void *pSrcBuf[3] = {NULL, }; - void *pYUVBuf[3] = {NULL, }; - unsigned int csc_src_color_format, csc_dst_color_format; - CSC_METHOD csc_method = CSC_METHOD_SW; - unsigned int cacheable = 1; + void *pYUVBuf[3]; int frameSize = bufWidth * bufHeight; int width = outputInfo.img_width; int height = outputInfo.img_height; int imageSize = outputInfo.img_width * outputInfo.img_height; - pSrcBuf[0] = outputInfo.YVirAddr; - pSrcBuf[1] = outputInfo.CVirAddr; - pYUVBuf[0] = (unsigned char *)pOutputBuf; pYUVBuf[1] = (unsigned char *)pOutputBuf + imageSize; pYUVBuf[2] = (unsigned char *)pOutputBuf + imageSize + imageSize / 4; @@ -1415,16 +1391,13 @@ OMX_ERRORTYPE SEC_MFC_Mpeg4_Decode_Nonblock(OMX_COMPONENTTYPE *pOMXComponent, SE if ((pVideoDec->bThumbnailMode == OMX_FALSE) && (pSECOutputPort->portDefinition.format.video.eColorFormat == OMX_SEC_COLOR_FormatNV12TPhysicalAddress)) { /* if use Post copy address structure */ - SEC_OSAL_Memcpy(pYUVBuf[0], &(outputInfo.YPhyAddr), sizeof(outputInfo.YPhyAddr)); - SEC_OSAL_Memcpy((unsigned char *)pYUVBuf[0] + (sizeof(void *) * 1), &(outputInfo.CPhyAddr), sizeof(outputInfo.CPhyAddr)); - SEC_OSAL_Memcpy((unsigned char *)pYUVBuf[0] + (sizeof(void *) * 2), &(outputInfo.YVirAddr), sizeof(outputInfo.YVirAddr)); - SEC_OSAL_Memcpy((unsigned char *)pYUVBuf[0] + (sizeof(void *) * 3), &(outputInfo.CVirAddr), sizeof(outputInfo.CVirAddr)); + SEC_OSAL_Memcpy(pOutputBuf, &(outputInfo.YPhyAddr), sizeof(outputInfo.YPhyAddr)); + SEC_OSAL_Memcpy((unsigned char *)pOutputBuf + (sizeof(void *) * 1), &(outputInfo.CPhyAddr), sizeof(outputInfo.CPhyAddr)); + SEC_OSAL_Memcpy((unsigned char *)pOutputBuf + (sizeof(void *) * 2), &(outputInfo.YVirAddr), sizeof(outputInfo.YVirAddr)); + SEC_OSAL_Memcpy((unsigned char *)pOutputBuf + (sizeof(void *) * 3), &(outputInfo.CVirAddr), sizeof(outputInfo.CVirAddr)); pOutputData->dataLen = (outputInfo.img_width * outputInfo.img_height * 3) / 2; } else { SEC_OSAL_Log(SEC_LOG_TRACE, "YUV420 out for ThumbnailMode"); -#ifdef CONFIG_MFC_FPS - SEC_OSAL_PerfStart(PERF_ID_CSC); -#endif switch (pSECComponent->pSECPort[OUTPUT_PORT_INDEX].portDefinition.format.video.eColorFormat) { case OMX_SEC_COLOR_FormatNV12Tiled: SEC_OSAL_Memcpy(pOutputBuf, outputInfo.YVirAddr, FrameBufferYSize); @@ -1433,65 +1406,56 @@ OMX_ERRORTYPE SEC_MFC_Mpeg4_Decode_Nonblock(OMX_COMPONENTTYPE *pOMXComponent, SE break; case OMX_COLOR_FormatYUV420SemiPlanar: case OMX_SEC_COLOR_FormatANBYUV420SemiPlanar: - csc_src_color_format = omx_2_hal_pixel_format((unsigned int)OMX_SEC_COLOR_FormatNV12Tiled); - csc_dst_color_format = omx_2_hal_pixel_format((unsigned int)OMX_COLOR_FormatYUV420SemiPlanar); +#ifdef USE_CSC_FIMC + if ((pSECOutputPort->bIsANBEnabled == OMX_TRUE) && (pMpeg4Dec->hFIMCHandle != NULL)) { + void *pPhys[3]; + SEC_OSAL_GetPhysANB(pOutputData->dataBuffer, pPhys); + pYUVBuf[0] = outputInfo.YPhyAddr; + pYUVBuf[1] = outputInfo.CPhyAddr; + csc_fimc_convert_nv12t(pMpeg4Dec->hFIMCHandle, pPhys, + pYUVBuf, width, height, + OMX_COLOR_FormatYUV420SemiPlanar); + break; + } +#endif + csc_tiled_to_linear_y_neon( + (unsigned char *)pYUVBuf[0], + (unsigned char *)outputInfo.YVirAddr, + width, + height); + csc_tiled_to_linear_uv_neon( + (unsigned char *)pYUVBuf[1], + (unsigned char *)outputInfo.CVirAddr, + width, + height / 2); break; case OMX_COLOR_FormatYUV420Planar: default: - csc_src_color_format = omx_2_hal_pixel_format((unsigned int)OMX_SEC_COLOR_FormatNV12Tiled); - csc_dst_color_format = omx_2_hal_pixel_format((unsigned int)OMX_COLOR_FormatYUV420Planar); +#ifdef USE_CSC_FIMC + if ((pSECOutputPort->bIsANBEnabled == OMX_TRUE) && (pMpeg4Dec->hFIMCHandle != NULL)) { + void *pPhys[3]; + SEC_OSAL_GetPhysANB(pOutputData->dataBuffer, pPhys); + pYUVBuf[0] = outputInfo.YPhyAddr; + pYUVBuf[1] = outputInfo.CPhyAddr; + csc_fimc_convert_nv12t(pMpeg4Dec->hFIMCHandle, pPhys, + pYUVBuf, width, height, + OMX_COLOR_FormatYUV420Planar); + break; + } +#endif + csc_tiled_to_linear_y_neon( + (unsigned char *)pYUVBuf[0], + (unsigned char *)outputInfo.YVirAddr, + width, + height); + csc_tiled_to_linear_uv_deinterleave_neon( + (unsigned char *)pYUVBuf[1], + (unsigned char *)pYUVBuf[2], + (unsigned char *)outputInfo.CVirAddr, + width, + height / 2); break; } - - csc_get_method(pVideoDec->csc_handle, &csc_method); -#ifdef USE_CSC_FIMC - if ((pSECOutputPort->bIsANBEnabled == OMX_TRUE) && (csc_method == CSC_METHOD_HW)) { - SEC_OSAL_GetPhysANB(pOutputData->dataBuffer, pYUVBuf); - pSrcBuf[0] = outputInfo.YPhyAddr; - pSrcBuf[1] = outputInfo.CPhyAddr; - } -#endif - if (pVideoDec->csc_set_format == OMX_FALSE) { - csc_set_src_format( - pVideoDec->csc_handle, /* handle */ - width, /* width */ - height, /* height */ - 0, /* crop_left */ - 0, /* crop_right */ - width, /* crop_width */ - height, /* crop_height */ - csc_src_color_format, /* color_format */ - cacheable); /* cacheable */ - csc_set_dst_format( - pVideoDec->csc_handle, /* handle */ - width, /* width */ - height, /* height */ - 0, /* crop_left */ - 0, /* crop_right */ - width, /* crop_width */ - height, /* crop_height */ - csc_dst_color_format, /* color_format */ - cacheable); /* cacheable */ - pVideoDec->csc_set_format = OMX_TRUE; - } - - csc_set_src_buffer( - pVideoDec->csc_handle, /* handle */ - pSrcBuf[0], /* y addr */ - pSrcBuf[1], /* u addr or uv addr */ - pSrcBuf[2], /* v addr or none */ - 0); /* ion fd */ - csc_set_dst_buffer( - pVideoDec->csc_handle, /* handle */ - pYUVBuf[0], /* y addr */ - pYUVBuf[1], /* u addr or uv addr */ - pYUVBuf[2], /* v addr or none */ - 0); /* ion fd */ - csc_convert(pVideoDec->csc_handle); - -#ifdef CONFIG_MFC_FPS - SEC_OSAL_PerfStop(PERF_ID_CSC); -#endif } #ifdef USE_ANB if (pSECOutputPort->bIsANBEnabled == OMX_TRUE) { @@ -1673,20 +1637,13 @@ OMX_ERRORTYPE SEC_MFC_Mpeg4_Decode_Block(OMX_COMPONENTTYPE *pOMXComponent, SEC_O (status == MFC_GETOUTBUF_DISPLAY_ONLY)) { /** Fill Output Buffer **/ void *pOutputBuf = (void *)pOutputData->dataBuffer; - void *pSrcBuf[3] = {NULL, }; - void *pYUVBuf[3] = {NULL, }; - unsigned int csc_src_color_format, csc_dst_color_format; - CSC_METHOD csc_method = CSC_METHOD_SW; - unsigned int cacheable = 1; + void *pYUVBuf[3]; int frameSize = bufWidth * bufHeight; int width = outputInfo.img_width; int height = outputInfo.img_height; int imageSize = outputInfo.img_width * outputInfo.img_height; - pSrcBuf[0] = outputInfo.YVirAddr; - pSrcBuf[1] = outputInfo.CVirAddr; - pYUVBuf[0] = (unsigned char *)pOutputBuf; pYUVBuf[1] = (unsigned char *)pOutputBuf + imageSize; pYUVBuf[2] = (unsigned char *)pOutputBuf + imageSize + imageSize / 4; @@ -1703,16 +1660,13 @@ OMX_ERRORTYPE SEC_MFC_Mpeg4_Decode_Block(OMX_COMPONENTTYPE *pOMXComponent, SEC_O if ((pVideoDec->bThumbnailMode == OMX_FALSE) && (pSECOutputPort->portDefinition.format.video.eColorFormat == OMX_SEC_COLOR_FormatNV12TPhysicalAddress)) { /* if use Post copy address structure */ - SEC_OSAL_Memcpy(pYUVBuf[0], &(outputInfo.YPhyAddr), sizeof(outputInfo.YPhyAddr)); - SEC_OSAL_Memcpy((unsigned char *)pYUVBuf[0] + (sizeof(void *) * 1), &(outputInfo.CPhyAddr), sizeof(outputInfo.CPhyAddr)); - SEC_OSAL_Memcpy((unsigned char *)pYUVBuf[0] + (sizeof(void *) * 2), &(outputInfo.YVirAddr), sizeof(outputInfo.YVirAddr)); - SEC_OSAL_Memcpy((unsigned char *)pYUVBuf[0] + (sizeof(void *) * 3), &(outputInfo.CVirAddr), sizeof(outputInfo.CVirAddr)); + SEC_OSAL_Memcpy(pOutputBuf, &(outputInfo.YPhyAddr), sizeof(outputInfo.YPhyAddr)); + SEC_OSAL_Memcpy((unsigned char *)pOutputBuf + (sizeof(void *) * 1), &(outputInfo.CPhyAddr), sizeof(outputInfo.CPhyAddr)); + SEC_OSAL_Memcpy((unsigned char *)pOutputBuf + (sizeof(void *) * 2), &(outputInfo.YVirAddr), sizeof(outputInfo.YVirAddr)); + SEC_OSAL_Memcpy((unsigned char *)pOutputBuf + (sizeof(void *) * 3), &(outputInfo.CVirAddr), sizeof(outputInfo.CVirAddr)); pOutputData->dataLen = (outputInfo.img_width * outputInfo.img_height * 3) / 2; } else { SEC_OSAL_Log(SEC_LOG_TRACE, "YUV420 out for ThumbnailMode"); -#ifdef CONFIG_MFC_FPS - SEC_OSAL_PerfStart(PERF_ID_CSC); -#endif switch (pSECComponent->pSECPort[OUTPUT_PORT_INDEX].portDefinition.format.video.eColorFormat) { case OMX_SEC_COLOR_FormatNV12Tiled: SEC_OSAL_Memcpy(pOutputBuf, outputInfo.YVirAddr, FrameBufferYSize); @@ -1721,65 +1675,56 @@ OMX_ERRORTYPE SEC_MFC_Mpeg4_Decode_Block(OMX_COMPONENTTYPE *pOMXComponent, SEC_O break; case OMX_COLOR_FormatYUV420SemiPlanar: case OMX_SEC_COLOR_FormatANBYUV420SemiPlanar: - csc_src_color_format = omx_2_hal_pixel_format((unsigned int)OMX_SEC_COLOR_FormatNV12Tiled); - csc_dst_color_format = omx_2_hal_pixel_format((unsigned int)OMX_COLOR_FormatYUV420SemiPlanar); +#ifdef USE_CSC_FIMC + if ((pSECOutputPort->bIsANBEnabled == OMX_TRUE) && (pMpeg4Dec->hFIMCHandle != NULL)) { + void *pPhys[3]; + SEC_OSAL_GetPhysANB(pOutputData->dataBuffer, pPhys); + pYUVBuf[0] = outputInfo.YPhyAddr; + pYUVBuf[1] = outputInfo.CPhyAddr; + csc_fimc_convert_nv12t(pMpeg4Dec->hFIMCHandle, pPhys, + pYUVBuf, width, height, + OMX_SEC_COLOR_FormatANBYUV420SemiPlanar); + break; + } +#endif + csc_tiled_to_linear_y_neon( + (unsigned char *)pYUVBuf[0], + (unsigned char *)outputInfo.YVirAddr, + width, + height); + csc_tiled_to_linear_uv_neon( + (unsigned char *)pYUVBuf[1], + (unsigned char *)outputInfo.CVirAddr, + width, + height / 2); break; case OMX_COLOR_FormatYUV420Planar: default: - csc_src_color_format = omx_2_hal_pixel_format((unsigned int)OMX_SEC_COLOR_FormatNV12Tiled); - csc_dst_color_format = omx_2_hal_pixel_format((unsigned int)OMX_COLOR_FormatYUV420Planar); +#ifdef USE_CSC_FIMC + if ((pSECOutputPort->bIsANBEnabled == OMX_TRUE) && (pMpeg4Dec->hFIMCHandle != NULL)) { + void *pPhys[3]; + SEC_OSAL_GetPhysANB(pOutputData->dataBuffer, pPhys); + pYUVBuf[0] = outputInfo.YPhyAddr; + pYUVBuf[1] = outputInfo.CPhyAddr; + csc_fimc_convert_nv12t(pMpeg4Dec->hFIMCHandle, pPhys, + pYUVBuf, width, height, + OMX_COLOR_FormatYUV420Planar); + break; + } +#endif + csc_tiled_to_linear_y_neon( + (unsigned char *)pYUVBuf[0], + (unsigned char *)outputInfo.YVirAddr, + width, + height); + csc_tiled_to_linear_uv_deinterleave_neon( + (unsigned char *)pYUVBuf[1], + (unsigned char *)pYUVBuf[2], + (unsigned char *)outputInfo.CVirAddr, + width, + height / 2); break; } - - csc_get_method(pVideoDec->csc_handle, &csc_method); -#ifdef USE_CSC_FIMC - if ((pSECOutputPort->bIsANBEnabled == OMX_TRUE) && (csc_method == CSC_METHOD_HW)) { - SEC_OSAL_GetPhysANB(pOutputData->dataBuffer, pYUVBuf); - pSrcBuf[0] = outputInfo.YPhyAddr; - pSrcBuf[1] = outputInfo.CPhyAddr; - } -#endif - if (pVideoDec->csc_set_format == OMX_FALSE) { - csc_set_src_format( - pVideoDec->csc_handle, /* handle */ - width, /* width */ - height, /* height */ - 0, /* crop_left */ - 0, /* crop_right */ - width, /* crop_width */ - height, /* crop_height */ - csc_src_color_format, /* color_format */ - cacheable); /* cacheable */ - csc_set_dst_format( - pVideoDec->csc_handle, /* handle */ - width, /* width */ - height, /* height */ - 0, /* crop_left */ - 0, /* crop_right */ - width, /* crop_width */ - height, /* crop_height */ - csc_dst_color_format, /* color_format */ - cacheable); /* cacheable */ - pVideoDec->csc_set_format = OMX_TRUE; - } - - csc_set_src_buffer( - pVideoDec->csc_handle, /* handle */ - pSrcBuf[0], /* y addr */ - pSrcBuf[1], /* u addr or uv addr */ - pSrcBuf[2], /* v addr or none */ - 0); /* ion fd */ - csc_set_dst_buffer( - pVideoDec->csc_handle, /* handle */ - pYUVBuf[0], /* y addr */ - pYUVBuf[1], /* u addr or uv addr */ - pYUVBuf[2], /* v addr or none */ - 0); /* ion fd */ - csc_convert(pVideoDec->csc_handle); - -#ifdef CONFIG_MFC_FPS - SEC_OSAL_PerfStop(PERF_ID_CSC); -#endif } #ifdef USE_ANB diff --git a/exynos4/multimedia/openmax/sec_omx/component/video/dec/mpeg4/SEC_OMX_Mpeg4dec.h b/exynos/multimedia/openmax/component/video/dec/mpeg4/SEC_OMX_Mpeg4dec.h similarity index 96% rename from exynos4/multimedia/openmax/sec_omx/component/video/dec/mpeg4/SEC_OMX_Mpeg4dec.h rename to exynos/multimedia/openmax/component/video/dec/mpeg4/SEC_OMX_Mpeg4dec.h index 256cb66..c844ff9 100644 --- a/exynos4/multimedia/openmax/sec_omx/component/video/dec/mpeg4/SEC_OMX_Mpeg4dec.h +++ b/exynos/multimedia/openmax/component/video/dec/mpeg4/SEC_OMX_Mpeg4dec.h @@ -76,6 +76,11 @@ typedef struct _SEC_MPEG4_HANDLE /* SEC MFC Codec specific */ SEC_MFC_MPEG4_HANDLE hMFCMpeg4Handle; + + /* CSC FIMC handle */ +#ifdef USE_CSC_FIMC + OMX_PTR hFIMCHandle; +#endif } SEC_MPEG4_HANDLE; #ifdef __cplusplus diff --git a/exynos4/multimedia/openmax/sec_omx/component/video/dec/mpeg4/library_register.c b/exynos/multimedia/openmax/component/video/dec/mpeg4/library_register.c similarity index 100% rename from exynos4/multimedia/openmax/sec_omx/component/video/dec/mpeg4/library_register.c rename to exynos/multimedia/openmax/component/video/dec/mpeg4/library_register.c diff --git a/exynos4/multimedia/openmax/sec_omx/component/video/dec/mpeg4/library_register.h b/exynos/multimedia/openmax/component/video/dec/mpeg4/library_register.h similarity index 100% rename from exynos4/multimedia/openmax/sec_omx/component/video/dec/mpeg4/library_register.h rename to exynos/multimedia/openmax/component/video/dec/mpeg4/library_register.h diff --git a/exynos4/multimedia/openmax/sec_omx/component/video/dec/vc1/Android.mk b/exynos/multimedia/openmax/component/video/dec/vc1/Android.mk similarity index 70% rename from exynos4/multimedia/openmax/sec_omx/component/video/dec/vc1/Android.mk rename to exynos/multimedia/openmax/component/video/dec/vc1/Android.mk index 8be63e1..9412233 100644 --- a/exynos4/multimedia/openmax/sec_omx/component/video/dec/vc1/Android.mk +++ b/exynos/multimedia/openmax/component/video/dec/vc1/Android.mk @@ -24,42 +24,29 @@ ifeq ($(BOARD_USE_V4L2_ION), false) LOCAL_CFLAGS += -DUSE_CSC_FIMC endif endif - -ifeq ($(BOARD_USE_CSC_GSCALER), true) -LOCAL_CFLAGS += -DUSE_CSC_GSCALER -endif endif LOCAL_ARM_MODE := arm LOCAL_STATIC_LIBRARIES := libSEC_OMX_Vdec libsecosal libsecbasecomponent \ - libswconverter libsecmfcapi + libseccscapi libsecmfcapi LOCAL_SHARED_LIBRARIES := libc libdl libcutils libutils libui \ - libSEC_OMX_Resourcemanager libcsc + libSEC_OMX_Resourcemanager ifeq ($(filter-out exynos4,$(TARGET_BOARD_PLATFORM)),) -LOCAL_SHARED_LIBRARIES += libfimc libhwconverter -endif - -ifeq ($(filter-out exynos5,$(TARGET_BOARD_PLATFORM)),) -LOCAL_SHARED_LIBRARIES += libexynosgscaler +LOCAL_SHARED_LIBRARIES += libhwconverter endif #ifeq ($(BOARD_USE_V4L2_ION),true) #LOCAL_SHARED_LIBRARIES += libion #endif -ifeq ($(BOARD_USES_MFC_FPS),true) -LOCAL_CFLAGS += -DCONFIG_MFC_FPS -endif - LOCAL_C_INCLUDES := $(SEC_OMX_INC)/khronos \ $(SEC_OMX_INC)/sec \ $(SEC_OMX_TOP)/osal \ $(SEC_OMX_TOP)/core \ $(SEC_OMX_COMPONENT)/common \ $(SEC_OMX_COMPONENT)/video/dec \ - $(TARGET_OUT_HEADERS)/$(SEC_COPY_HEADERS_TO) \ - $(BOARD_HAL_PATH)/include + $(TARGET_OUT_HEADERS)/$(SEC_COPY_HEADERS_TO) include $(BUILD_SHARED_LIBRARY) diff --git a/exynos4/multimedia/openmax/sec_omx/component/video/dec/vc1/SEC_OMX_Wmvdec.c b/exynos/multimedia/openmax/component/video/dec/vc1/SEC_OMX_Wmvdec.c similarity index 90% rename from exynos4/multimedia/openmax/sec_omx/component/video/dec/vc1/SEC_OMX_Wmvdec.c rename to exynos/multimedia/openmax/component/video/dec/vc1/SEC_OMX_Wmvdec.c index 7e9194b..ebc2a0f 100644 --- a/exynos4/multimedia/openmax/sec_omx/component/video/dec/vc1/SEC_OMX_Wmvdec.c +++ b/exynos/multimedia/openmax/component/video/dec/vc1/SEC_OMX_Wmvdec.c @@ -42,14 +42,17 @@ #include "SEC_OMX_Wmvdec.h" #include "SsbSipMfcApi.h" #include "SEC_OSAL_Event.h" +#include "color_space_convertor.h" #ifdef USE_ANB #include "SEC_OSAL_Android.h" #endif -/* To use CSC_METHOD_PREFER_HW or CSC_METHOD_HW in SEC OMX, gralloc should allocate physical memory using FIMC */ +/* To use CSC FIMC in SEC OMX, gralloc should allocate physical memory using FIMC */ /* It means GRALLOC_USAGE_HW_FIMC1 should be set on Native Window usage */ -#include "csc.h" +#ifdef USE_CSC_FIMC +#include "csc_fimc.h" +#endif #undef SEC_LOG_TAG #define SEC_LOG_TAG "SEC_WMV_DEC" @@ -783,13 +786,7 @@ OMX_ERRORTYPE SEC_MFC_DecodeThread(OMX_HANDLETYPE hComponent) SEC_OSAL_SemaphoreWait(pVideoDec->NBDecThread.hDecFrameStart); if (pVideoDec->NBDecThread.bExitDecodeThread == OMX_FALSE) { -#ifdef CONFIG_MFC_FPS - SEC_OSAL_PerfStart(PERF_ID_DEC); -#endif pWmvDec->hMFCWmvHandle.returnCodec = SsbSipMfcDecExe(pWmvDec->hMFCWmvHandle.hMFCHandle, pVideoDec->NBDecThread.oneFrameSize); -#ifdef CONFIG_MFC_FPS - SEC_OSAL_PerfStop(PERF_ID_DEC); -#endif SEC_OSAL_SemaphorePost(pVideoDec->NBDecThread.hDecFrameEnd); } } @@ -812,15 +809,9 @@ OMX_ERRORTYPE SEC_MFC_WmvDec_Init(OMX_COMPONENTTYPE *pOMXComponent) OMX_HANDLETYPE hMFCHandle = NULL; OMX_PTR pStreamBuffer = NULL; OMX_PTR pStreamPhyBuffer = NULL; - CSC_METHOD csc_method = CSC_METHOD_SW; FunctionIn(); -#ifdef CONFIG_MFC_FPS - SEC_OSAL_PerfInit(PERF_ID_DEC); - SEC_OSAL_PerfInit(PERF_ID_CSC); -#endif - pWmvDec = (SEC_WMV_HANDLE *)((SEC_OMX_VIDEODEC_COMPONENT *)pSECComponent->hComponentHandle)->hCodecHandle; pWmvDec->hMFCWmvHandle.bConfiguredMFC = OMX_FALSE; pSECComponent->bUseFlagEOF = OMX_FALSE; @@ -891,15 +882,9 @@ OMX_ERRORTYPE SEC_MFC_WmvDec_Init(OMX_COMPONENTTYPE *pOMXComponent) pWmvDec->hMFCWmvHandle.outputIndexTimestamp = 0; pSECComponent->getAllDelayBuffer = OMX_FALSE; -#ifdef USE_ANB -#if defined(USE_CSC_FIMC) || defined(USE_CSC_GSCALER) - if (pSECOutputPort->bIsANBEnabled == OMX_TRUE) { - csc_method = CSC_METHOD_PREFER_HW; - } +#ifdef USE_CSC_FIMC + pWmvDec->hFIMCHandle = csc_fimc_open(); #endif -#endif - pVideoDec->csc_handle = csc_init(&csc_method); - pVideoDec->csc_set_format = OMX_FALSE; EXIT: FunctionOut(); @@ -918,11 +903,6 @@ OMX_ERRORTYPE SEC_MFC_WmvDec_Terminate(OMX_COMPONENTTYPE *pOMXComponent) FunctionIn(); -#ifdef CONFIG_MFC_FPS - SEC_OSAL_PerfPrint("[DEC]", PERF_ID_DEC); - SEC_OSAL_PerfPrint("[CSC]", PERF_ID_CSC); -#endif - pWmvDec = (SEC_WMV_HANDLE *)((SEC_OMX_VIDEODEC_COMPONENT *)pSECComponent->hComponentHandle)->hCodecHandle; hMFCHandle = pWmvDec->hMFCWmvHandle.hMFCHandle; @@ -955,10 +935,12 @@ OMX_ERRORTYPE SEC_MFC_WmvDec_Terminate(OMX_COMPONENTTYPE *pOMXComponent) pWmvDec->hMFCWmvHandle.hMFCHandle = NULL; } - if (pVideoDec->csc_handle != NULL) { - csc_deinit(pVideoDec->csc_handle); - pVideoDec->csc_handle = NULL; +#ifdef USE_CSC_FIMC + if (pWmvDec->hFIMCHandle != NULL) { + csc_fimc_close(pWmvDec->hFIMCHandle); + pWmvDec->hFIMCHandle = NULL; } +#endif EXIT: FunctionOut(); @@ -1284,20 +1266,13 @@ OMX_ERRORTYPE SEC_MFC_Wmv_Decode_Nonblock(OMX_COMPONENTTYPE *pOMXComponent, SEC_ SEC_OMX_BASEPORT *pSECInputPort = &pSECComponent->pSECPort[INPUT_PORT_INDEX]; SEC_OMX_BASEPORT *pSECOutputPort = &pSECComponent->pSECPort[OUTPUT_PORT_INDEX]; void *pOutputBuf = (void *)pOutputData->dataBuffer; - void *pSrcBuf[3] = {NULL, }; - void *pYUVBuf[3] = {NULL, }; - unsigned int csc_src_color_format, csc_dst_color_format; - CSC_METHOD csc_method = CSC_METHOD_SW; - unsigned int cacheable = 1; + void *pYUVBuf[3]; int frameSize = bufWidth * bufHeight; int width = outputInfo.img_width; int height = outputInfo.img_height; int imageSize = outputInfo.img_width * outputInfo.img_height; - pSrcBuf[0] = outputInfo.YVirAddr; - pSrcBuf[1] = outputInfo.CVirAddr; - pYUVBuf[0] = (unsigned char *)pOutputBuf; pYUVBuf[1] = (unsigned char *)pOutputBuf + imageSize; pYUVBuf[2] = (unsigned char *)pOutputBuf + imageSize + imageSize / 4; @@ -1314,16 +1289,13 @@ OMX_ERRORTYPE SEC_MFC_Wmv_Decode_Nonblock(OMX_COMPONENTTYPE *pOMXComponent, SEC_ if ((pVideoDec->bThumbnailMode == OMX_FALSE) && (pSECOutputPort->portDefinition.format.video.eColorFormat == OMX_SEC_COLOR_FormatNV12TPhysicalAddress)) { /* if use Post copy address structure */ - SEC_OSAL_Memcpy(pYUVBuf[0], &(outputInfo.YPhyAddr), sizeof(outputInfo.YPhyAddr)); - SEC_OSAL_Memcpy((unsigned char *)pYUVBuf[0] + (sizeof(void *) * 1), &(outputInfo.CPhyAddr), sizeof(outputInfo.CPhyAddr)); - SEC_OSAL_Memcpy((unsigned char *)pYUVBuf[0] + (sizeof(void *) * 2), &(outputInfo.YVirAddr), sizeof(outputInfo.YVirAddr)); - SEC_OSAL_Memcpy((unsigned char *)pYUVBuf[0] + (sizeof(void *) * 3), &(outputInfo.CVirAddr), sizeof(outputInfo.CVirAddr)); + SEC_OSAL_Memcpy(pOutputBuf, &(outputInfo.YPhyAddr), sizeof(outputInfo.YPhyAddr)); + SEC_OSAL_Memcpy((unsigned char *)pOutputBuf + (sizeof(void *) * 1), &(outputInfo.CPhyAddr), sizeof(outputInfo.CPhyAddr)); + SEC_OSAL_Memcpy((unsigned char *)pOutputBuf + (sizeof(void *) * 2), &(outputInfo.YVirAddr), sizeof(outputInfo.YVirAddr)); + SEC_OSAL_Memcpy((unsigned char *)pOutputBuf + (sizeof(void *) * 3), &(outputInfo.CVirAddr), sizeof(outputInfo.CVirAddr)); pOutputData->dataLen = (outputInfo.img_width * outputInfo.img_height * 3) / 2; } else { SEC_OSAL_Log(SEC_LOG_TRACE, "YUV420 out for ThumbnailMode"); -#ifdef CONFIG_MFC_FPS - SEC_OSAL_PerfStart(PERF_ID_CSC); -#endif switch (pSECComponent->pSECPort[OUTPUT_PORT_INDEX].portDefinition.format.video.eColorFormat) { case OMX_SEC_COLOR_FormatNV12Tiled: SEC_OSAL_Memcpy(pOutputBuf, outputInfo.YVirAddr, FrameBufferYSize); @@ -1332,64 +1304,56 @@ OMX_ERRORTYPE SEC_MFC_Wmv_Decode_Nonblock(OMX_COMPONENTTYPE *pOMXComponent, SEC_ break; case OMX_COLOR_FormatYUV420SemiPlanar: case OMX_SEC_COLOR_FormatANBYUV420SemiPlanar: - csc_src_color_format = omx_2_hal_pixel_format((unsigned int)OMX_SEC_COLOR_FormatNV12Tiled); - csc_dst_color_format = omx_2_hal_pixel_format((unsigned int)OMX_COLOR_FormatYUV420SemiPlanar); +#ifdef USE_CSC_FIMC + if ((pSECOutputPort->bIsANBEnabled == OMX_TRUE) && (pWmvDec->hFIMCHandle != NULL)) { + void *pPhys[3]; + SEC_OSAL_GetPhysANB(pOutputData->dataBuffer, pPhys); + pYUVBuf[0] = outputInfo.YPhyAddr; + pYUVBuf[1] = outputInfo.CPhyAddr; + csc_fimc_convert_nv12t(pWmvDec->hFIMCHandle, pPhys, + pYUVBuf, width, height, + OMX_SEC_COLOR_FormatANBYUV420SemiPlanar); + break; + } +#endif + csc_tiled_to_linear_y_neon( + (unsigned char *)pYUVBuf[0], + (unsigned char *)outputInfo.YVirAddr, + width, + height); + csc_tiled_to_linear_uv_neon( + (unsigned char *)pYUVBuf[1], + (unsigned char *)outputInfo.CVirAddr, + width, + height / 2); break; case OMX_COLOR_FormatYUV420Planar: default: - csc_src_color_format = omx_2_hal_pixel_format((unsigned int)OMX_SEC_COLOR_FormatNV12Tiled); - csc_dst_color_format = omx_2_hal_pixel_format((unsigned int)OMX_COLOR_FormatYUV420Planar); +#ifdef USE_CSC_FIMC + if ((pSECOutputPort->bIsANBEnabled == OMX_TRUE) && (pWmvDec->hFIMCHandle != NULL)) { + void *pPhys[3]; + SEC_OSAL_GetPhysANB(pOutputData->dataBuffer, pPhys); + pYUVBuf[0] = outputInfo.YPhyAddr; + pYUVBuf[1] = outputInfo.CPhyAddr; + csc_fimc_convert_nv12t(pWmvDec->hFIMCHandle, pPhys, + pYUVBuf, width, height, + OMX_COLOR_FormatYUV420Planar); + break; + } +#endif + csc_tiled_to_linear_y_neon( + (unsigned char *)pYUVBuf[0], + (unsigned char *)outputInfo.YVirAddr, + width, + height); + csc_tiled_to_linear_uv_deinterleave_neon( + (unsigned char *)pYUVBuf[1], + (unsigned char *)pYUVBuf[2], + (unsigned char *)outputInfo.CVirAddr, + width, + height / 2); break; } - - csc_get_method(pVideoDec->csc_handle, &csc_method); -#ifdef USE_CSC_FIMC - if ((pSECOutputPort->bIsANBEnabled == OMX_TRUE) && (csc_method == CSC_METHOD_HW)) { - SEC_OSAL_GetPhysANB(pOutputData->dataBuffer, pYUVBuf); - pSrcBuf[0] = outputInfo.YPhyAddr; - pSrcBuf[1] = outputInfo.CPhyAddr; - } -#endif - if (pVideoDec->csc_set_format == OMX_FALSE) { - csc_set_src_format( - pVideoDec->csc_handle, /* handle */ - width, /* width */ - height, /* height */ - 0, /* crop_left */ - 0, /* crop_right */ - width, /* crop_width */ - height, /* crop_height */ - csc_src_color_format, /* color_format */ - cacheable); /* cacheable */ - csc_set_dst_format( - pVideoDec->csc_handle, /* handle */ - width, /* width */ - height, /* height */ - 0, /* crop_left */ - 0, /* crop_right */ - width, /* crop_width */ - height, /* crop_height */ - csc_dst_color_format, /* color_format */ - cacheable); /* cacheable */ - pVideoDec->csc_set_format = OMX_TRUE; - } - csc_set_src_buffer( - pVideoDec->csc_handle, /* handle */ - pSrcBuf[0], /* y addr */ - pSrcBuf[1], /* u addr or uv addr */ - pSrcBuf[2], /* v addr or none */ - 0); /* ion fd */ - csc_set_dst_buffer( - pVideoDec->csc_handle, - pYUVBuf[0], /* y addr */ - pYUVBuf[1], /* u addr or uv addr */ - pYUVBuf[2], /* v addr or none */ - 0); /* ion fd */ - csc_convert(pVideoDec->csc_handle); - -#ifdef CONFIG_MFC_FPS - SEC_OSAL_PerfStop(PERF_ID_CSC); -#endif } #ifdef USE_ANB if (pSECOutputPort->bIsANBEnabled == OMX_TRUE) { @@ -1611,20 +1575,13 @@ OMX_ERRORTYPE SEC_MFC_Wmv_Decode_Block(OMX_COMPONENTTYPE *pOMXComponent, SEC_OMX (status == MFC_GETOUTBUF_DISPLAY_ONLY)) { /** Fill Output Buffer **/ void *pOutputBuf = (void *)pOutputData->dataBuffer; - void *pSrcBuf[3] = {NULL, }; - void *pYUVBuf[3] = {NULL, }; - unsigned int csc_src_color_format, csc_dst_color_format; - CSC_METHOD csc_method = CSC_METHOD_SW; - unsigned int cacheable = 1; + void *pYUVBuf[3]; int frameSize = bufWidth * bufHeight; int width = outputInfo.img_width; int height = outputInfo.img_height; int imageSize = outputInfo.img_width * outputInfo.img_height; - pSrcBuf[0] = outputInfo.YVirAddr; - pSrcBuf[1] = outputInfo.CVirAddr; - pYUVBuf[0] = (unsigned char *)pOutputBuf; pYUVBuf[1] = (unsigned char *)pOutputBuf + imageSize; pYUVBuf[2] = (unsigned char *)pOutputBuf + imageSize + imageSize / 4; @@ -1640,16 +1597,13 @@ OMX_ERRORTYPE SEC_MFC_Wmv_Decode_Block(OMX_COMPONENTTYPE *pOMXComponent, SEC_OMX #endif if ((pVideoDec->bThumbnailMode == OMX_FALSE) && (pSECOutputPort->portDefinition.format.video.eColorFormat == OMX_SEC_COLOR_FormatNV12TPhysicalAddress)) { - SEC_OSAL_Memcpy(pYUVBuf[0], &(outputInfo.YPhyAddr), sizeof(outputInfo.YPhyAddr)); - SEC_OSAL_Memcpy((unsigned char *)pYUVBuf[0] + (sizeof(void *) * 1), &(outputInfo.CPhyAddr), sizeof(outputInfo.CPhyAddr)); - SEC_OSAL_Memcpy((unsigned char *)pYUVBuf[0] + (sizeof(void *) * 2), &(outputInfo.YVirAddr), sizeof(outputInfo.YVirAddr)); - SEC_OSAL_Memcpy((unsigned char *)pYUVBuf[0] + (sizeof(void *) * 3), &(outputInfo.CVirAddr), sizeof(outputInfo.CVirAddr)); + SEC_OSAL_Memcpy(pOutputBuf, &(outputInfo.YPhyAddr), sizeof(outputInfo.YPhyAddr)); + SEC_OSAL_Memcpy((unsigned char *)pOutputBuf + (sizeof(void *) * 1), &(outputInfo.CPhyAddr), sizeof(outputInfo.CPhyAddr)); + SEC_OSAL_Memcpy((unsigned char *)pOutputBuf + (sizeof(void *) * 2), &(outputInfo.YVirAddr), sizeof(outputInfo.YVirAddr)); + SEC_OSAL_Memcpy((unsigned char *)pOutputBuf + (sizeof(void *) * 3), &(outputInfo.CVirAddr), sizeof(outputInfo.CVirAddr)); pOutputData->dataLen = (outputInfo.img_width * outputInfo.img_height * 3) / 2; } else { SEC_OSAL_Log(SEC_LOG_TRACE, "YUV420 out for ThumbnailMode"); -#ifdef CONFIG_MFC_FPS - SEC_OSAL_PerfStart(PERF_ID_CSC); -#endif switch (pSECComponent->pSECPort[OUTPUT_PORT_INDEX].portDefinition.format.video.eColorFormat) { case OMX_SEC_COLOR_FormatNV12Tiled: SEC_OSAL_Memcpy(pOutputBuf, outputInfo.YVirAddr, FrameBufferYSize); @@ -1658,64 +1612,56 @@ OMX_ERRORTYPE SEC_MFC_Wmv_Decode_Block(OMX_COMPONENTTYPE *pOMXComponent, SEC_OMX break; case OMX_COLOR_FormatYUV420SemiPlanar: case OMX_SEC_COLOR_FormatANBYUV420SemiPlanar: - csc_src_color_format = omx_2_hal_pixel_format((unsigned int)OMX_SEC_COLOR_FormatNV12Tiled); - csc_dst_color_format = omx_2_hal_pixel_format((unsigned int)OMX_COLOR_FormatYUV420SemiPlanar); +#ifdef USE_CSC_FIMC + if ((pSECOutputPort->bIsANBEnabled == OMX_TRUE) && (pWmvDec->hFIMCHandle != NULL)) { + void *pPhys[3]; + SEC_OSAL_GetPhysANB(pOutputData->dataBuffer, pPhys); + pYUVBuf[0] = outputInfo.YPhyAddr; + pYUVBuf[1] = outputInfo.CPhyAddr; + csc_fimc_convert_nv12t(pWmvDec->hFIMCHandle, pPhys, + pYUVBuf, width, height, + OMX_SEC_COLOR_FormatANBYUV420SemiPlanar); + break; + } +#endif + csc_tiled_to_linear_y_neon( + (unsigned char *)pYUVBuf[0], + (unsigned char *)outputInfo.YVirAddr, + width, + height); + csc_tiled_to_linear_uv_neon( + (unsigned char *)pYUVBuf[1], + (unsigned char *)outputInfo.CVirAddr, + width, + height / 2); break; case OMX_COLOR_FormatYUV420Planar: default: - csc_src_color_format = omx_2_hal_pixel_format((unsigned int)OMX_SEC_COLOR_FormatNV12Tiled); - csc_dst_color_format = omx_2_hal_pixel_format((unsigned int)OMX_COLOR_FormatYUV420Planar); +#ifdef USE_CSC_FIMC + if ((pSECOutputPort->bIsANBEnabled == OMX_TRUE) && (pWmvDec->hFIMCHandle != NULL)) { + void *pPhys[3]; + SEC_OSAL_GetPhysANB(pOutputData->dataBuffer, pPhys); + pYUVBuf[0] = outputInfo.YPhyAddr; + pYUVBuf[1] = outputInfo.CPhyAddr; + csc_fimc_convert_nv12t(pWmvDec->hFIMCHandle, pPhys, + pYUVBuf, width, height, + OMX_COLOR_FormatYUV420Planar); + break; + } +#endif + csc_tiled_to_linear_y_neon( + (unsigned char *)pYUVBuf[0], + (unsigned char *)outputInfo.YVirAddr, + width, + height); + csc_tiled_to_linear_uv_deinterleave_neon( + (unsigned char *)pYUVBuf[1], + (unsigned char *)pYUVBuf[2], + (unsigned char *)outputInfo.CVirAddr, + width, + height / 2); break; } - - csc_get_method(pVideoDec->csc_handle, &csc_method); -#ifdef USE_CSC_FIMC - if ((pSECOutputPort->bIsANBEnabled == OMX_TRUE) && (csc_method == CSC_METHOD_HW)) { - SEC_OSAL_GetPhysANB(pOutputData->dataBuffer, pYUVBuf); - pSrcBuf[0] = outputInfo.YPhyAddr; - pSrcBuf[1] = outputInfo.CPhyAddr; - } -#endif - if (pVideoDec->csc_set_format == OMX_FALSE) { - csc_set_src_format( - pVideoDec->csc_handle, /* handle */ - width, /* width */ - height, /* height */ - 0, /* crop_left */ - 0, /* crop_right */ - width, /* crop_width */ - height, /* crop_height */ - csc_src_color_format, /* color_format */ - cacheable); /* cacheable */ - csc_set_dst_format( - pVideoDec->csc_handle, /* handle */ - width, /* width */ - height, /* height */ - 0, /* crop_left */ - 0, /* crop_right */ - width, /* crop_width */ - height, /* crop_height */ - csc_dst_color_format, /* color_format */ - cacheable); /* cacheable */ - pVideoDec->csc_set_format = OMX_TRUE; - } - csc_set_src_buffer( - pVideoDec->csc_handle, /* handle */ - pSrcBuf[0], /* y addr */ - pSrcBuf[1], /* u addr or uv addr */ - pSrcBuf[2], /* v addr or none */ - 0); /* ion fd */ - csc_set_dst_buffer( - pVideoDec->csc_handle, - pYUVBuf[0], /* y addr */ - pYUVBuf[1], /* u addr or uv addr */ - pYUVBuf[2], /* v addr or none */ - 0); /* ion fd */ - csc_convert(pVideoDec->csc_handle); - -#ifdef CONFIG_MFC_FPS - SEC_OSAL_PerfStop(PERF_ID_CSC); -#endif } #ifdef USE_ANB diff --git a/exynos4/multimedia/openmax/sec_omx/component/video/dec/vc1/SEC_OMX_Wmvdec.h b/exynos/multimedia/openmax/component/video/dec/vc1/SEC_OMX_Wmvdec.h similarity index 96% rename from exynos4/multimedia/openmax/sec_omx/component/video/dec/vc1/SEC_OMX_Wmvdec.h rename to exynos/multimedia/openmax/component/video/dec/vc1/SEC_OMX_Wmvdec.h index 0634465..c68b644 100644 --- a/exynos4/multimedia/openmax/sec_omx/component/video/dec/vc1/SEC_OMX_Wmvdec.h +++ b/exynos/multimedia/openmax/component/video/dec/vc1/SEC_OMX_Wmvdec.h @@ -78,6 +78,11 @@ typedef struct _SEC_WMV_HANDLE /* SEC MFC Codec specific */ SEC_MFC_WMV_HANDLE hMFCWmvHandle; + + /* CSC FIMC handle */ +#ifdef USE_CSC_FIMC + OMX_PTR hFIMCHandle; +#endif } SEC_WMV_HANDLE; #ifdef __cplusplus diff --git a/exynos4/multimedia/openmax/sec_omx/component/video/dec/vc1/library_register.c b/exynos/multimedia/openmax/component/video/dec/vc1/library_register.c similarity index 100% rename from exynos4/multimedia/openmax/sec_omx/component/video/dec/vc1/library_register.c rename to exynos/multimedia/openmax/component/video/dec/vc1/library_register.c diff --git a/exynos4/multimedia/openmax/sec_omx/component/video/dec/vc1/library_register.h b/exynos/multimedia/openmax/component/video/dec/vc1/library_register.h similarity index 100% rename from exynos4/multimedia/openmax/sec_omx/component/video/dec/vc1/library_register.h rename to exynos/multimedia/openmax/component/video/dec/vc1/library_register.h diff --git a/exynos/multimedia/openmax/component/video/dec/vp8/Android.mk b/exynos/multimedia/openmax/component/video/dec/vp8/Android.mk new file mode 100644 index 0000000..e4629a6 --- /dev/null +++ b/exynos/multimedia/openmax/component/video/dec/vp8/Android.mk @@ -0,0 +1,47 @@ +LOCAL_PATH := $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_MODULE_TAGS := optional + +LOCAL_SRC_FILES := \ + SEC_OMX_Vp8dec.c \ + library_register.c + +LOCAL_PRELINK_MODULE := false +LOCAL_MODULE := libOMX.SEC.VP8.Decoder +LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/omx + +LOCAL_CFLAGS := + +ifeq ($(BOARD_NONBLOCK_MODE_PROCESS), true) +LOCAL_CFLAGS += -DNONBLOCK_MODE_PROCESS +endif + +ifeq ($(BOARD_USE_ANB), true) +LOCAL_CFLAGS += -DUSE_ANB +endif + +LOCAL_ARM_MODE := arm + +LOCAL_STATIC_LIBRARIES := libSEC_OMX_Vdec libsecosal libsecbasecomponent \ + libseccscapi libsecmfcapi +LOCAL_SHARED_LIBRARIES := libc libdl libcutils libutils libui \ + libSEC_OMX_Resourcemanager + +ifeq ($(filter-out exynos4,$(TARGET_BOARD_PLATFORM)),) +LOCAL_SHARED_LIBRARIES += libhwconverter +endif + +#ifeq ($(BOARD_USE_V4L2_ION),true) +#LOCAL_SHARED_LIBRARIES += libion +#endif + +LOCAL_C_INCLUDES := $(SEC_OMX_INC)/khronos \ + $(SEC_OMX_INC)/sec \ + $(SEC_OMX_TOP)/osal \ + $(SEC_OMX_TOP)/core \ + $(SEC_OMX_COMPONENT)/common \ + $(SEC_OMX_COMPONENT)/video/dec \ + $(TARGET_OUT_HEADERS)/$(SEC_COPY_HEADERS_TO) + +include $(BUILD_SHARED_LIBRARY) diff --git a/exynos4/multimedia/openmax/sec_omx/component/video/dec/vp8/SEC_OMX_Vp8dec.c b/exynos/multimedia/openmax/component/video/dec/vp8/SEC_OMX_Vp8dec.c similarity index 88% rename from exynos4/multimedia/openmax/sec_omx/component/video/dec/vp8/SEC_OMX_Vp8dec.c rename to exynos/multimedia/openmax/component/video/dec/vp8/SEC_OMX_Vp8dec.c index 5ac91d5..1642ac2 100644 --- a/exynos4/multimedia/openmax/sec_omx/component/video/dec/vp8/SEC_OMX_Vp8dec.c +++ b/exynos/multimedia/openmax/component/video/dec/vp8/SEC_OMX_Vp8dec.c @@ -38,15 +38,12 @@ #include "library_register.h" #include "SEC_OMX_Vp8dec.h" #include "SsbSipMfcApi.h" +#include "color_space_convertor.h" #ifdef USE_ANB #include "SEC_OSAL_Android.h" #endif -/* To use CSC_METHOD_PREFER_HW or CSC_METHOD_HW in SEC OMX, gralloc should allocate physical memory using FIMC */ -/* It means GRALLOC_USAGE_HW_FIMC1 should be set on Native Window usage */ -#include "csc.h" - #undef SEC_LOG_TAG #define SEC_LOG_TAG "SEC_VP8_DEC" #define SEC_LOG_OFF @@ -549,13 +546,7 @@ OMX_ERRORTYPE SEC_MFC_DecodeThread(OMX_HANDLETYPE hComponent) SEC_OSAL_SemaphoreWait(pVideoDec->NBDecThread.hDecFrameStart); if (pVideoDec->NBDecThread.bExitDecodeThread == OMX_FALSE) { -#ifdef CONFIG_MFC_FPS - SEC_OSAL_PerfStart(PERF_ID_DEC); -#endif pVp8Dec->hMFCVp8Handle.returnCodec = SsbSipMfcDecExe(pVp8Dec->hMFCVp8Handle.hMFCHandle, pVideoDec->NBDecThread.oneFrameSize); -#ifdef CONFIG_MFC_FPS - SEC_OSAL_PerfStop(PERF_ID_DEC); -#endif SEC_OSAL_SemaphorePost(pVideoDec->NBDecThread.hDecFrameEnd); } } @@ -578,12 +569,6 @@ OMX_ERRORTYPE SEC_MFC_VP8Dec_Init(OMX_COMPONENTTYPE *pOMXComponent) OMX_PTR hMFCHandle = NULL; OMX_PTR pStreamBuffer = NULL; OMX_PTR pStreamPhyBuffer = NULL; - CSC_METHOD csc_method = CSC_METHOD_SW; - -#ifdef CONFIG_MFC_FPS - SEC_OSAL_PerfInit(PERF_ID_DEC); - SEC_OSAL_PerfInit(PERF_ID_CSC); -#endif pVp8Dec = (SEC_VP8DEC_HANDLE *)((SEC_OMX_VIDEODEC_COMPONENT *)pSECComponent->hComponentHandle)->hCodecHandle; pVp8Dec->hMFCVp8Handle.bConfiguredMFC = OMX_FALSE; @@ -656,16 +641,6 @@ OMX_ERRORTYPE SEC_MFC_VP8Dec_Init(OMX_COMPONENTTYPE *pOMXComponent) pSECComponent->getAllDelayBuffer = OMX_FALSE; -#ifdef USE_ANB -#if defined(USE_CSC_FIMC) || defined(USE_CSC_GSCALER) - if (pSECOutputPort->bIsANBEnabled == OMX_TRUE) { - csc_method = CSC_METHOD_PREFER_HW; - } -#endif -#endif - pVideoDec->csc_handle = csc_init(&csc_method); - pVideoDec->csc_set_format = OMX_FALSE; - EXIT: FunctionOut(); @@ -683,11 +658,6 @@ OMX_ERRORTYPE SEC_MFC_VP8Dec_Terminate(OMX_COMPONENTTYPE *pOMXComponent) FunctionIn(); -#ifdef CONFIG_MFC_FPS - SEC_OSAL_PerfPrint("[DEC]", PERF_ID_DEC); - SEC_OSAL_PerfPrint("[CSC]", PERF_ID_CSC); -#endif - pVp8Dec = (SEC_VP8DEC_HANDLE *)((SEC_OMX_VIDEODEC_COMPONENT *)pSECComponent->hComponentHandle)->hCodecHandle; hMFCHandle = pVp8Dec->hMFCVp8Handle.hMFCHandle; @@ -720,11 +690,6 @@ OMX_ERRORTYPE SEC_MFC_VP8Dec_Terminate(OMX_COMPONENTTYPE *pOMXComponent) hMFCHandle = pVp8Dec->hMFCVp8Handle.hMFCHandle = NULL; } - if (pVideoDec->csc_handle != NULL) { - csc_deinit(pVideoDec->csc_handle); - pVideoDec->csc_handle = NULL; - } - EXIT: FunctionOut(); @@ -994,20 +959,13 @@ OMX_ERRORTYPE SEC_MFC_VP8_Decode_Nonblock(OMX_COMPONENTTYPE *pOMXComponent, SEC_ /** Fill Output Buffer **/ if (outputDataValid == OMX_TRUE) { void *pOutputBuf = (void *)pOutputData->dataBuffer; - void *pSrcBuf[3] = {NULL, }; - void *pYUVBuf[3] = {NULL, }; - unsigned int csc_src_color_format, csc_dst_color_format; - CSC_METHOD csc_method = CSC_METHOD_SW; - unsigned int cacheable = 1; + void *pYUVBuf[3]; int frameSize = bufWidth * bufHeight; int width = outputInfo.img_width; int height = outputInfo.img_height; int imageSize = outputInfo.img_width * outputInfo.img_height; - pSrcBuf[0] = outputInfo.YVirAddr; - pSrcBuf[1] = outputInfo.CVirAddr; - pYUVBuf[0] = (unsigned char *)pOutputBuf; pYUVBuf[1] = (unsigned char *)pOutputBuf + imageSize; pYUVBuf[2] = (unsigned char *)pOutputBuf + imageSize + imageSize / 4; @@ -1024,16 +982,13 @@ OMX_ERRORTYPE SEC_MFC_VP8_Decode_Nonblock(OMX_COMPONENTTYPE *pOMXComponent, SEC_ if ((pVideoDec->bThumbnailMode == OMX_FALSE) && (pSECOutputPort->portDefinition.format.video.eColorFormat == OMX_SEC_COLOR_FormatNV12TPhysicalAddress)) { /* if use Post copy address structure */ - SEC_OSAL_Memcpy(pYUVBuf[0], &(outputInfo.YPhyAddr), sizeof(outputInfo.YPhyAddr)); - SEC_OSAL_Memcpy((unsigned char *)pYUVBuf[0] + (sizeof(void *) * 1), &(outputInfo.CPhyAddr), sizeof(outputInfo.CPhyAddr)); - SEC_OSAL_Memcpy((unsigned char *)pYUVBuf[0] + (sizeof(void *) * 2), &(outputInfo.YVirAddr), sizeof(outputInfo.YVirAddr)); - SEC_OSAL_Memcpy((unsigned char *)pYUVBuf[0] + (sizeof(void *) * 3), &(outputInfo.CVirAddr), sizeof(outputInfo.CVirAddr)); + SEC_OSAL_Memcpy(pOutputBuf, &(outputInfo.YPhyAddr), sizeof(outputInfo.YPhyAddr)); + SEC_OSAL_Memcpy((unsigned char *)pOutputBuf + (sizeof(void *) * 1), &(outputInfo.CPhyAddr), sizeof(outputInfo.CPhyAddr)); + SEC_OSAL_Memcpy((unsigned char *)pOutputBuf + (sizeof(void *) * 2), &(outputInfo.YVirAddr), sizeof(outputInfo.YVirAddr)); + SEC_OSAL_Memcpy((unsigned char *)pOutputBuf + (sizeof(void *) * 3), &(outputInfo.CVirAddr), sizeof(outputInfo.CVirAddr)); pOutputData->dataLen = (width * height * 3) / 2; } else { SEC_OSAL_Log(SEC_LOG_TRACE, "YUV420 SP/P Output mode"); -#ifdef CONFIG_MFC_FPS - SEC_OSAL_PerfStart(PERF_ID_CSC); -#endif switch (pSECComponent->pSECPort[OUTPUT_PORT_INDEX].portDefinition.format.video.eColorFormat) { case OMX_SEC_COLOR_FormatNV12Tiled: SEC_OSAL_Memcpy(pOutputBuf, outputInfo.YVirAddr, FrameBufferYSize); @@ -1042,64 +997,33 @@ OMX_ERRORTYPE SEC_MFC_VP8_Decode_Nonblock(OMX_COMPONENTTYPE *pOMXComponent, SEC_ break; case OMX_COLOR_FormatYUV420SemiPlanar: case OMX_SEC_COLOR_FormatANBYUV420SemiPlanar: - csc_src_color_format = omx_2_hal_pixel_format((unsigned int)OMX_SEC_COLOR_FormatNV12Tiled); - csc_dst_color_format = omx_2_hal_pixel_format((unsigned int)OMX_COLOR_FormatYUV420SemiPlanar); + csc_tiled_to_linear_y_neon( + (unsigned char *)pYUVBuf[0], + (unsigned char *)outputInfo.YVirAddr, + width, + height); + csc_tiled_to_linear_uv_neon( + (unsigned char *)pYUVBuf[1], + (unsigned char *)outputInfo.CVirAddr, + width, + height / 2); + break; break; case OMX_COLOR_FormatYUV420Planar: default: - csc_src_color_format = omx_2_hal_pixel_format((unsigned int)OMX_SEC_COLOR_FormatNV12Tiled); - csc_dst_color_format = omx_2_hal_pixel_format((unsigned int)OMX_COLOR_FormatYUV420Planar); + csc_tiled_to_linear_y_neon( + (unsigned char *)pYUVBuf[0], + (unsigned char *)outputInfo.YVirAddr, + width, + height); + csc_tiled_to_linear_uv_deinterleave_neon( + (unsigned char *)pYUVBuf[1], + (unsigned char *)pYUVBuf[2], + (unsigned char *)outputInfo.CVirAddr, + width, + height / 2); break; } - - csc_get_method(pVideoDec->csc_handle, &csc_method); -#ifdef USE_CSC_FIMC - if ((pSECOutputPort->bIsANBEnabled == OMX_TRUE) && (csc_method == CSC_METHOD_HW)) { - SEC_OSAL_GetPhysANB(pOutputData->dataBuffer, pYUVBuf); - pSrcBuf[0] = outputInfo.YPhyAddr; - pSrcBuf[1] = outputInfo.CPhyAddr; - } -#endif - if (pVideoDec->csc_set_format == OMX_FALSE) { - csc_set_src_format( - pVideoDec->csc_handle, /* handle */ - width, /* width */ - height, /* height */ - 0, /* crop_left */ - 0, /* crop_right */ - width, /* crop_width */ - height, /* crop_height */ - csc_src_color_format, /* color_format */ - cacheable); /* cacheable */ - csc_set_dst_format( - pVideoDec->csc_handle, /* handle */ - width, /* width */ - height, /* height */ - 0, /* crop_left */ - 0, /* crop_right */ - width, /* crop_width */ - height, /* crop_height */ - csc_dst_color_format, /* color_format */ - cacheable); /* cacheable */ - pVideoDec->csc_set_format = OMX_TRUE; - } - csc_set_src_buffer( - pVideoDec->csc_handle, /* handle */ - pSrcBuf[0], /* y addr */ - pSrcBuf[1], /* u addr or uv addr */ - pSrcBuf[2], /* v addr or none */ - 0); /* ion fd */ - csc_set_dst_buffer( - pVideoDec->csc_handle, - pYUVBuf[0], /* y addr */ - pYUVBuf[1], /* u addr or uv addr */ - pYUVBuf[2], /* v addr or none */ - 0); /* ion fd */ - csc_convert(pVideoDec->csc_handle); - -#ifdef CONFIG_MFC_FPS - SEC_OSAL_PerfStop(PERF_ID_CSC); -#endif } #ifdef USE_ANB if (pSECOutputPort->bIsANBEnabled == OMX_TRUE) { @@ -1263,20 +1187,13 @@ OMX_ERRORTYPE SEC_MFC_VP8_Decode_Block(OMX_COMPONENTTYPE *pOMXComponent, SEC_OMX (status == MFC_GETOUTBUF_DISPLAY_ONLY)) { /** Fill Output Buffer **/ void *pOutputBuf = (void *)pOutputData->dataBuffer; - void *pSrcBuf[3] = {NULL, }; - void *pYUVBuf[3] = {NULL, }; - unsigned int csc_src_color_format, csc_dst_color_format; - CSC_METHOD csc_method = CSC_METHOD_SW; - unsigned int cacheable = 1; + void *pYUVBuf[3]; int frameSize = bufWidth * bufHeight; int width = outputInfo.img_width; int height = outputInfo.img_height; int imageSize = outputInfo.img_width * outputInfo.img_height; - pSrcBuf[0] = outputInfo.YVirAddr; - pSrcBuf[1] = outputInfo.CVirAddr; - pYUVBuf[0] = (unsigned char *)pOutputBuf; pYUVBuf[1] = (unsigned char *)pOutputBuf + imageSize; pYUVBuf[2] = (unsigned char *)pOutputBuf + imageSize + imageSize / 4; @@ -1293,16 +1210,13 @@ OMX_ERRORTYPE SEC_MFC_VP8_Decode_Block(OMX_COMPONENTTYPE *pOMXComponent, SEC_OMX if ((pVideoDec->bThumbnailMode == OMX_FALSE) && (pSECOutputPort->portDefinition.format.video.eColorFormat == OMX_SEC_COLOR_FormatNV12TPhysicalAddress)) { /* if use Post copy address structure */ - SEC_OSAL_Memcpy(pYUVBuf[0], &(outputInfo.YPhyAddr), sizeof(outputInfo.YPhyAddr)); - SEC_OSAL_Memcpy((unsigned char *)pYUVBuf[0] + (sizeof(void *) * 1), &(outputInfo.CPhyAddr), sizeof(outputInfo.CPhyAddr)); - SEC_OSAL_Memcpy((unsigned char *)pYUVBuf[0] + (sizeof(void *) * 2), &(outputInfo.YVirAddr), sizeof(outputInfo.YVirAddr)); - SEC_OSAL_Memcpy((unsigned char *)pYUVBuf[0] + (sizeof(void *) * 3), &(outputInfo.CVirAddr), sizeof(outputInfo.CVirAddr)); + SEC_OSAL_Memcpy(pOutputBuf, &(outputInfo.YPhyAddr), sizeof(outputInfo.YPhyAddr)); + SEC_OSAL_Memcpy((unsigned char *)pOutputBuf + (sizeof(void *) * 1), &(outputInfo.CPhyAddr), sizeof(outputInfo.CPhyAddr)); + SEC_OSAL_Memcpy((unsigned char *)pOutputBuf + (sizeof(void *) * 2), &(outputInfo.YVirAddr), sizeof(outputInfo.YVirAddr)); + SEC_OSAL_Memcpy((unsigned char *)pOutputBuf + (sizeof(void *) * 3), &(outputInfo.CVirAddr), sizeof(outputInfo.CVirAddr)); pOutputData->dataLen = (width * height * 3) / 2; } else { SEC_OSAL_Log(SEC_LOG_TRACE, "YUV420 SP/P Output mode"); -#ifdef CONFIG_MFC_FPS - SEC_OSAL_PerfStart(PERF_ID_CSC); -#endif switch (pSECComponent->pSECPort[OUTPUT_PORT_INDEX].portDefinition.format.video.eColorFormat) { case OMX_SEC_COLOR_FormatNV12Tiled: SEC_OSAL_Memcpy(pOutputBuf, outputInfo.YVirAddr, FrameBufferYSize); @@ -1311,64 +1225,32 @@ OMX_ERRORTYPE SEC_MFC_VP8_Decode_Block(OMX_COMPONENTTYPE *pOMXComponent, SEC_OMX break; case OMX_COLOR_FormatYUV420SemiPlanar: case OMX_SEC_COLOR_FormatANBYUV420SemiPlanar: - csc_src_color_format = omx_2_hal_pixel_format((unsigned int)OMX_SEC_COLOR_FormatNV12Tiled); - csc_dst_color_format = omx_2_hal_pixel_format((unsigned int)OMX_COLOR_FormatYUV420SemiPlanar); + csc_tiled_to_linear_y_neon( + (unsigned char *)pYUVBuf[0], + (unsigned char *)outputInfo.YVirAddr, + width, + height); + csc_tiled_to_linear_uv_neon( + (unsigned char *)pYUVBuf[1], + (unsigned char *)outputInfo.CVirAddr, + width, + height / 2); break; case OMX_COLOR_FormatYUV420Planar: default: - csc_src_color_format = omx_2_hal_pixel_format((unsigned int)OMX_SEC_COLOR_FormatNV12Tiled); - csc_dst_color_format = omx_2_hal_pixel_format((unsigned int)OMX_COLOR_FormatYUV420Planar); + csc_tiled_to_linear_y_neon( + (unsigned char *)pYUVBuf[0], + (unsigned char *)outputInfo.YVirAddr, + width, + height); + csc_tiled_to_linear_uv_deinterleave_neon( + (unsigned char *)pYUVBuf[1], + (unsigned char *)pYUVBuf[2], + (unsigned char *)outputInfo.CVirAddr, + width, + height / 2); break; } - - csc_get_method(pVideoDec->csc_handle, &csc_method); -#ifdef USE_CSC_FIMC - if ((pSECOutputPort->bIsANBEnabled == OMX_TRUE) && (csc_method == CSC_METHOD_HW)) { - SEC_OSAL_GetPhysANB(pOutputData->dataBuffer, pYUVBuf); - pSrcBuf[0] = outputInfo.YPhyAddr; - pSrcBuf[1] = outputInfo.CPhyAddr; - } -#endif - if (pVideoDec->csc_set_format == OMX_FALSE) { - csc_set_src_format( - pVideoDec->csc_handle, /* handle */ - width, /* width */ - height, /* height */ - 0, /* crop_left */ - 0, /* crop_right */ - width, /* crop_width */ - height, /* crop_height */ - csc_src_color_format, /* color_format */ - cacheable); /* cacheable */ - csc_set_dst_format( - pVideoDec->csc_handle, /* handle */ - width, /* width */ - height, /* height */ - 0, /* crop_left */ - 0, /* crop_right */ - width, /* crop_width */ - height, /* crop_height */ - csc_dst_color_format, /* color_format */ - cacheable); /* cacheable */ - pVideoDec->csc_set_format = OMX_TRUE; - } - csc_set_src_buffer( - pVideoDec->csc_handle, /* handle */ - pSrcBuf[0], /* y addr */ - pSrcBuf[1], /* u addr or uv addr */ - pSrcBuf[2], /* v addr or none */ - 0); /* ion fd */ - csc_set_dst_buffer( - pVideoDec->csc_handle, - pYUVBuf[0], /* y addr */ - pYUVBuf[1], /* u addr or uv addr */ - pYUVBuf[2], /* v addr or none */ - 0); /* ion fd */ - csc_convert(pVideoDec->csc_handle); - -#ifdef CONFIG_MFC_FPS - SEC_OSAL_PerfStop(PERF_ID_CSC); -#endif } #ifdef USE_ANB diff --git a/exynos4/multimedia/openmax/sec_omx/component/video/dec/vp8/SEC_OMX_Vp8dec.h b/exynos/multimedia/openmax/component/video/dec/vp8/SEC_OMX_Vp8dec.h similarity index 100% rename from exynos4/multimedia/openmax/sec_omx/component/video/dec/vp8/SEC_OMX_Vp8dec.h rename to exynos/multimedia/openmax/component/video/dec/vp8/SEC_OMX_Vp8dec.h diff --git a/exynos4/multimedia/openmax/sec_omx/component/video/dec/vp8/library_register.c b/exynos/multimedia/openmax/component/video/dec/vp8/library_register.c similarity index 100% rename from exynos4/multimedia/openmax/sec_omx/component/video/dec/vp8/library_register.c rename to exynos/multimedia/openmax/component/video/dec/vp8/library_register.c diff --git a/exynos4/multimedia/openmax/sec_omx/component/video/dec/vp8/library_register.h b/exynos/multimedia/openmax/component/video/dec/vp8/library_register.h similarity index 100% rename from exynos4/multimedia/openmax/sec_omx/component/video/dec/vp8/library_register.h rename to exynos/multimedia/openmax/component/video/dec/vp8/library_register.h diff --git a/exynos4/multimedia/openmax/sec_omx/component/video/enc/Android.mk b/exynos/multimedia/openmax/component/video/enc/Android.mk similarity index 75% rename from exynos4/multimedia/openmax/sec_omx/component/video/enc/Android.mk rename to exynos/multimedia/openmax/component/video/enc/Android.mk index 1c842f2..e13d54d 100644 --- a/exynos4/multimedia/openmax/sec_omx/component/video/enc/Android.mk +++ b/exynos/multimedia/openmax/component/video/enc/Android.mk @@ -24,14 +24,4 @@ ifeq ($(BOARD_USE_STOREMETADATA), true) LOCAL_CFLAGS += -DUSE_STOREMETADATA endif -ifeq ($(BOARD_USE_V4L2), true) -ifeq ($(TARGET_SOC), exynos5250) -LOCAL_CFLAGS += -DUSE_SLICE_OUTPUT_MODE -endif -else -LOCAL_CFLAGS += -DUSE_SLICE_OUTPUT_MODE -endif - -LOCAL_SHARED_LIBRARIES := libcsc - include $(BUILD_STATIC_LIBRARY) diff --git a/exynos4/multimedia/openmax/sec_omx/component/video/enc/SEC_OMX_Venc.c b/exynos/multimedia/openmax/component/video/enc/SEC_OMX_Venc.c similarity index 93% rename from exynos4/multimedia/openmax/sec_omx/component/video/enc/SEC_OMX_Venc.c rename to exynos/multimedia/openmax/component/video/enc/SEC_OMX_Venc.c index e4b6cc2..d3f16b9 100644 --- a/exynos4/multimedia/openmax/sec_omx/component/video/enc/SEC_OMX_Venc.c +++ b/exynos/multimedia/openmax/component/video/enc/SEC_OMX_Venc.c @@ -36,7 +36,7 @@ #include "SEC_OSAL_Mutex.h" #include "SEC_OSAL_Semaphore.h" #include "SEC_OSAL_ETC.h" -#include "csc.h" +#include "color_space_convertor.h" #ifdef USE_STOREMETADATA #include "SEC_OSAL_Android.h" @@ -708,9 +708,6 @@ OMX_BOOL SEC_Preprocessor_InputData(OMX_COMPONENTTYPE *pOMXComponent) case OMX_COLOR_FormatYUV420Planar: case OMX_SEC_COLOR_FormatNV12TPhysicalAddress: case OMX_SEC_COLOR_FormatNV12LPhysicalAddress: - case OMX_SEC_COLOR_FormatNV21LPhysicalAddress: - case OMX_SEC_COLOR_FormatNV12Tiled: - case OMX_SEC_COLOR_FormatNV21Linear: oneFrameSize = (width * height * 3) / 2; break; case OMX_SEC_COLOR_FormatNV12LVirtualAddress: @@ -758,22 +755,13 @@ OMX_BOOL SEC_Preprocessor_InputData(OMX_COMPONENTTYPE *pOMXComponent) SEC_OMX_BASEPORT *pSECPort = &pSECComponent->pSECPort[INPUT_PORT_INDEX]; if ((pSECPort->portDefinition.format.video.eColorFormat != OMX_SEC_COLOR_FormatNV12TPhysicalAddress) && (pSECPort->portDefinition.format.video.eColorFormat != OMX_SEC_COLOR_FormatNV12LPhysicalAddress) && - (pSECPort->portDefinition.format.video.eColorFormat != OMX_SEC_COLOR_FormatNV12LVirtualAddress) && - (pSECPort->portDefinition.format.video.eColorFormat != OMX_SEC_COLOR_FormatNV21LPhysicalAddress)) { + (pSECPort->portDefinition.format.video.eColorFormat != OMX_SEC_COLOR_FormatNV12LVirtualAddress)) { if (flagEOF == OMX_TRUE) { OMX_U32 width, height; - unsigned int csc_src_color_format, csc_dst_color_format; - unsigned int cacheable = 1; - unsigned char *pSrcBuf[3] = {NULL, }; - unsigned char *pDstBuf[3] = {NULL, }; - OMX_PTR ppBuf[3]; width = pSECPort->portDefinition.format.video.nFrameWidth; height = pSECPort->portDefinition.format.video.nFrameHeight; - pDstBuf[0] = (unsigned char *)pVideoEnc->MFCEncInputBuffer[pVideoEnc->indexInputBuffer].YVirAddr; - pDstBuf[1] = (unsigned char *)pVideoEnc->MFCEncInputBuffer[pVideoEnc->indexInputBuffer].CVirAddr; - SEC_OSAL_Log(SEC_LOG_TRACE, "pVideoEnc->MFCEncInputBuffer[%d].YVirAddr : 0x%x", pVideoEnc->indexInputBuffer, pVideoEnc->MFCEncInputBuffer[pVideoEnc->indexInputBuffer].YVirAddr); SEC_OSAL_Log(SEC_LOG_TRACE, "pVideoEnc->MFCEncInputBuffer[%d].CVirAddr : 0x%x", pVideoEnc->indexInputBuffer, pVideoEnc->MFCEncInputBuffer[pVideoEnc->indexInputBuffer].CVirAddr); @@ -781,21 +769,28 @@ OMX_BOOL SEC_Preprocessor_InputData(OMX_COMPONENTTYPE *pOMXComponent) SEC_OSAL_Log(SEC_LOG_TRACE, "width:%d, height:%d, Csize:%d", width, height, ALIGN_TO_8KB(ALIGN_TO_128B(width) * ALIGN_TO_32B(height / 2))); if (pSECPort->bStoreMetaData == OMX_FALSE) { - pSrcBuf[0] = checkInputStream; - pSrcBuf[1] = checkInputStream + (width * height); - pSrcBuf[2] = checkInputStream + (((width * height) * 5) / 4); - switch (pSECPort->portDefinition.format.video.eColorFormat) { case OMX_COLOR_FormatYUV420Planar: /* YUV420Planar case it needed changed interleave UV plane (MFC spec.)*/ - csc_src_color_format = omx_2_hal_pixel_format((unsigned int)OMX_COLOR_FormatYUV420Planar); - csc_dst_color_format = omx_2_hal_pixel_format((unsigned int)OMX_COLOR_FormatYUV420SemiPlanar); + SEC_OSAL_Memcpy(pVideoEnc->MFCEncInputBuffer[pVideoEnc->indexInputBuffer].YVirAddr, + checkInputStream, (width * height)); + csc_interleave_memcpy_neon(pVideoEnc->MFCEncInputBuffer[pVideoEnc->indexInputBuffer].CVirAddr, + checkInputStream + (width * height), + checkInputStream + (((width * height) * 5) / 4), + width * height >> 2); break; case OMX_COLOR_FormatYUV420SemiPlanar: + SEC_OSAL_Memcpy(pVideoEnc->MFCEncInputBuffer[pVideoEnc->indexInputBuffer].YVirAddr, + checkInputStream, (width * height)); + SEC_OSAL_Memcpy(pVideoEnc->MFCEncInputBuffer[pVideoEnc->indexInputBuffer].CVirAddr, + checkInputStream + (width * height), (width * height / 2)); + break; case OMX_SEC_COLOR_FormatNV12Tiled: - case OMX_SEC_COLOR_FormatNV21Linear: - csc_src_color_format = omx_2_hal_pixel_format((unsigned int)OMX_COLOR_FormatYUV420SemiPlanar); - csc_dst_color_format = omx_2_hal_pixel_format((unsigned int)OMX_COLOR_FormatYUV420SemiPlanar); + SEC_OSAL_Memcpy(pVideoEnc->MFCEncInputBuffer[pVideoEnc->indexInputBuffer].YVirAddr, + checkInputStream, ALIGN_TO_8KB(ALIGN_TO_128B(width) * ALIGN_TO_32B(height))); + SEC_OSAL_Memcpy(pVideoEnc->MFCEncInputBuffer[pVideoEnc->indexInputBuffer].CVirAddr, + checkInputStream + ALIGN_TO_8KB(ALIGN_TO_128B(width) * ALIGN_TO_32B(height)), + ALIGN_TO_8KB(ALIGN_TO_128B(width) * ALIGN_TO_32B(height / 2))); break; default: break; @@ -804,58 +799,20 @@ OMX_BOOL SEC_Preprocessor_InputData(OMX_COMPONENTTYPE *pOMXComponent) #ifdef USE_METADATABUFFERTYPE else { if (pSECPort->portDefinition.format.video.eColorFormat == OMX_COLOR_FormatAndroidOpaque) { - OMX_PTR pOutBuffer; - csc_src_color_format = omx_2_hal_pixel_format((unsigned int)OMX_COLOR_Format32bitARGB8888); - csc_dst_color_format = omx_2_hal_pixel_format((unsigned int)OMX_COLOR_FormatYUV420SemiPlanar); + OMX_PTR ppBuf[3]; + OMX_PTR pOutBuffer; - SEC_OSAL_GetInfoFromMetaData(inputData, ppBuf); - SEC_OSAL_LockANBHandle((OMX_U32)ppBuf[0], width, height, OMX_COLOR_FormatAndroidOpaque, &pOutBuffer); - pSrcBuf[0] = (unsigned char *)pOutBuffer; - pSrcBuf[1] = NULL; - pSrcBuf[2] = NULL; + SEC_OSAL_GetInfoFromMetaData(inputData, ppBuf); + SEC_OSAL_LockANBHandle((OMX_U32)ppBuf[0], width, height, OMX_COLOR_FormatAndroidOpaque, &pOutBuffer); + + csc_ARGB8888_to_YUV420SP(pVideoEnc->MFCEncInputBuffer[pVideoEnc->indexInputBuffer].YVirAddr, + pVideoEnc->MFCEncInputBuffer[pVideoEnc->indexInputBuffer].CVirAddr, + pOutBuffer, width, height); + + SEC_OSAL_UnlockANBHandle((OMX_U32)ppBuf[0]); } } #endif - - csc_set_src_format( - pVideoEnc->csc_handle, /* handle */ - width, /* width */ - height, /* height */ - 0, /* crop_left */ - 0, /* crop_right */ - width, /* crop_width */ - height, /* crop_height */ - csc_src_color_format, /* color_format */ - cacheable); /* cacheable */ - csc_set_dst_format( - pVideoEnc->csc_handle, /* handle */ - width, /* width */ - height, /* height */ - 0, /* crop_left */ - 0, /* crop_right */ - width, /* crop_width */ - height, /* crop_height */ - csc_dst_color_format, /* color_format */ - cacheable); /* cacheable */ - csc_set_src_buffer( - pVideoEnc->csc_handle, /* handle */ - pSrcBuf[0], /* y addr */ - pSrcBuf[1], /* u addr or uv addr */ - pSrcBuf[2], /* v addr or none */ - 0); /* ion fd */ - csc_set_dst_buffer( - pVideoEnc->csc_handle, /* handle */ - pDstBuf[0], /* y addr */ - pDstBuf[1], /* u addr or uv addr */ - pDstBuf[2], /* v addr or none */ - 0); /* ion fd */ - csc_convert(pVideoEnc->csc_handle); - -#ifdef USE_METADATABUFFERTYPE - if (pSECPort->bStoreMetaData == OMX_TRUE) { - SEC_OSAL_UnlockANBHandle((OMX_U32)ppBuf[0]); - } -#endif } } @@ -1189,20 +1146,9 @@ OMX_ERRORTYPE SEC_OMX_VideoEncodeGetParameter( portFormat->xFramerate = portDefinition->format.video.xFramerate; break; case supportFormat_6: - portFormat->eCompressionFormat = OMX_VIDEO_CodingUnused; - portFormat->eColorFormat = OMX_SEC_COLOR_FormatNV21LPhysicalAddress; - portFormat->xFramerate = portDefinition->format.video.xFramerate; - break; - case supportFormat_7: - portFormat->eCompressionFormat = OMX_VIDEO_CodingUnused; - portFormat->eColorFormat = OMX_SEC_COLOR_FormatNV21Linear; - portFormat->xFramerate = portDefinition->format.video.xFramerate; - break; - case supportFormat_8: portFormat->eCompressionFormat = OMX_VIDEO_CodingUnused; portFormat->eColorFormat = OMX_COLOR_FormatAndroidOpaque; portFormat->xFramerate = portDefinition->format.video.xFramerate; - break; } } else if (portIndex == OUTPUT_PORT_INDEX) { supportFormatNum = OUTPUT_PORT_SUPPORTFORMAT_NUM_MAX - 1; diff --git a/exynos4/multimedia/openmax/sec_omx/component/video/enc/SEC_OMX_Venc.h b/exynos/multimedia/openmax/component/video/enc/SEC_OMX_Venc.h similarity index 98% rename from exynos4/multimedia/openmax/sec_omx/component/video/enc/SEC_OMX_Venc.h rename to exynos/multimedia/openmax/component/video/enc/SEC_OMX_Venc.h index 6225fd3..b16b372 100644 --- a/exynos4/multimedia/openmax/sec_omx/component/video/enc/SEC_OMX_Venc.h +++ b/exynos/multimedia/openmax/component/video/enc/SEC_OMX_Venc.h @@ -47,7 +47,7 @@ #define MFC_INPUT_BUFFER_NUM_MAX 2 -#define INPUT_PORT_SUPPORTFORMAT_NUM_MAX 9 +#define INPUT_PORT_SUPPORTFORMAT_NUM_MAX 7 #define OUTPUT_PORT_SUPPORTFORMAT_NUM_MAX 1 #ifdef USE_STOREMETADATA @@ -95,9 +95,6 @@ typedef struct _SEC_OMX_VIDEOENC_COMPONENT OMX_BOOL bFirstFrame; MFC_ENC_INPUT_BUFFER MFCEncInputBuffer[MFC_INPUT_BUFFER_NUM_MAX]; OMX_U32 indexInputBuffer; - - /* CSC handle */ - OMX_PTR csc_handle; } SEC_OMX_VIDEOENC_COMPONENT; #ifdef __cplusplus diff --git a/exynos4/multimedia/openmax/sec_omx/component/video/enc/h264/Android.mk b/exynos/multimedia/openmax/component/video/enc/h264/Android.mk similarity index 93% rename from exynos4/multimedia/openmax/sec_omx/component/video/enc/h264/Android.mk rename to exynos/multimedia/openmax/component/video/enc/h264/Android.mk index d8c7b06..435fbf7 100644 --- a/exynos4/multimedia/openmax/sec_omx/component/video/enc/h264/Android.mk +++ b/exynos/multimedia/openmax/component/video/enc/h264/Android.mk @@ -24,9 +24,9 @@ endif LOCAL_ARM_MODE := arm LOCAL_STATIC_LIBRARIES := libSEC_OMX_Venc libsecosal libsecbasecomponent \ - libswconverter libsecmfcapi + libseccscapi libsecmfcapi LOCAL_SHARED_LIBRARIES := libc libdl libcutils libutils libui \ - libSEC_OMX_Resourcemanager libcsc + libSEC_OMX_Resourcemanager LOCAL_C_INCLUDES := $(SEC_OMX_INC)/khronos \ $(SEC_OMX_INC)/sec \ diff --git a/exynos4/multimedia/openmax/sec_omx/component/video/enc/h264/SEC_OMX_H264enc.c b/exynos/multimedia/openmax/component/video/enc/h264/SEC_OMX_H264enc.c similarity index 98% rename from exynos4/multimedia/openmax/sec_omx/component/video/enc/h264/SEC_OMX_H264enc.c rename to exynos/multimedia/openmax/component/video/enc/h264/SEC_OMX_H264enc.c index df4241b..dfba49d 100644 --- a/exynos4/multimedia/openmax/sec_omx/component/video/enc/h264/SEC_OMX_H264enc.c +++ b/exynos/multimedia/openmax/component/video/enc/h264/SEC_OMX_H264enc.c @@ -39,7 +39,7 @@ #include "library_register.h" #include "SEC_OMX_H264enc.h" #include "SsbSipMfcApi.h" -#include "csc.h" +#include "color_space_convertor.h" #undef SEC_LOG_TAG #define SEC_LOG_TAG "SEC_H264_ENC" @@ -161,9 +161,6 @@ void H264PrintParams(SSBSIP_MFC_ENC_H264_PARAM *h264Arg) SEC_OSAL_Log(SEC_LOG_TRACE, "NumberRefForPframes : %d\n", h264Arg->NumberRefForPframes); SEC_OSAL_Log(SEC_LOG_TRACE, "SliceMode : %d\n", h264Arg->SliceMode); SEC_OSAL_Log(SEC_LOG_TRACE, "SliceArgument : %d\n", h264Arg->SliceArgument); -#ifdef USE_SLICE_OUTPUT_MODE - SEC_OSAL_Log(SEC_LOG_TRACE, "OutputMode : %d\n", h264Arg->OutputMode); -#endif SEC_OSAL_Log(SEC_LOG_TRACE, "NumberBFrames : %d\n", h264Arg->NumberBFrames); SEC_OSAL_Log(SEC_LOG_TRACE, "LoopFilterDisable : %d\n", h264Arg->LoopFilterDisable); SEC_OSAL_Log(SEC_LOG_TRACE, "LoopFilterAlphaC0Offset : %d\n", h264Arg->LoopFilterAlphaC0Offset); @@ -208,9 +205,6 @@ void Set_H264Enc_Param(SSBSIP_MFC_ENC_H264_PARAM *pH264Arg, SEC_OMX_BASECOMPONEN pH264Arg->SourceHeight = pSECOutputPort->portDefinition.format.video.nFrameHeight; pH264Arg->IDRPeriod = pH264Enc->AVCComponent[OUTPUT_PORT_INDEX].nPFrames + 1; pH264Arg->SliceMode = 0; -#ifdef USE_SLICE_OUTPUT_MODE - pH264Arg->OutputMode = FRAME; -#endif pH264Arg->RandomIntraMBRefresh = 0; pH264Arg->Bitrate = pSECOutputPort->portDefinition.format.video.nBitrate; pH264Arg->QSCodeMax = 51; @@ -230,9 +224,9 @@ void Set_H264Enc_Param(SSBSIP_MFC_ENC_H264_PARAM *pH264Arg, SEC_OMX_BASECOMPONEN pH264Arg->LoopFilterDisable = 1; // 1: Loop Filter Disable, 0: Filter Enable pH264Arg->LoopFilterAlphaC0Offset = 0; pH264Arg->LoopFilterBetaOffset = 0; - pH264Arg->SymbolMode = 1; // 0: CAVLC, 1: CABAC + pH264Arg->SymbolMode = 0; // 0: CAVLC, 1: CABAC pH264Arg->PictureInterlace = 0; - pH264Arg->Transform8x8Mode = 1; // 0: 4x4, 1: allow 8x8 + pH264Arg->Transform8x8Mode = 0; // 0: 4x4, 1: allow 8x8 pH264Arg->DarkDisable = 1; pH264Arg->SmoothDisable = 1; pH264Arg->StaticDisable = 1; @@ -277,12 +271,6 @@ void Set_H264Enc_Param(SSBSIP_MFC_ENC_H264_PARAM *pH264Arg, SEC_OMX_BASECOMPONEN break; case OMX_SEC_COLOR_FormatNV12TPhysicalAddress: case OMX_SEC_COLOR_FormatNV12Tiled: - pH264Arg->FrameMap = NV12_TILE; - break; - case OMX_SEC_COLOR_FormatNV21LPhysicalAddress: - case OMX_SEC_COLOR_FormatNV21Linear: - pH264Arg->FrameMap = NV21_LINEAR; - break; default: pH264Arg->FrameMap = NV12_TILE; break; @@ -873,7 +861,6 @@ OMX_ERRORTYPE SEC_MFC_H264Enc_Init(OMX_COMPONENTTYPE *pOMXComponent) SEC_H264ENC_HANDLE *pH264Enc = NULL; OMX_PTR hMFCHandle = NULL; OMX_S32 returnCodec = 0; - CSC_METHOD csc_method = CSC_METHOD_SW; FunctionIn(); @@ -887,7 +874,6 @@ OMX_ERRORTYPE SEC_MFC_H264Enc_Init(OMX_COMPONENTTYPE *pOMXComponent) case OMX_SEC_COLOR_FormatNV12TPhysicalAddress: case OMX_SEC_COLOR_FormatNV12LPhysicalAddress: case OMX_SEC_COLOR_FormatNV12LVirtualAddress: - case OMX_SEC_COLOR_FormatNV21LPhysicalAddress: hMFCHandle = (OMX_PTR)SsbSipMfcEncOpen(); break; default: { @@ -963,8 +949,6 @@ OMX_ERRORTYPE SEC_MFC_H264Enc_Init(OMX_COMPONENTTYPE *pOMXComponent) SEC_OSAL_Memset(pSECComponent->nFlags, 0, sizeof(OMX_U32) * MAX_FLAGS); pH264Enc->hMFCH264Handle.indexTimestamp = 0; - pVideoEnc->csc_handle = csc_init(&csc_method); - EXIT: FunctionOut(); @@ -1008,11 +992,6 @@ OMX_ERRORTYPE SEC_MFC_H264Enc_Terminate(OMX_COMPONENTTYPE *pOMXComponent) hMFCHandle = pH264Enc->hMFCH264Handle.hMFCHandle = NULL; } - if (pVideoEnc->csc_handle != NULL) { - csc_deinit(pVideoEnc->csc_handle); - pVideoEnc->csc_handle = NULL; - } - EXIT: FunctionOut(); @@ -1091,8 +1070,7 @@ OMX_ERRORTYPE SEC_MFC_H264_Encode_Nonblock(OMX_COMPONENTTYPE *pOMXComponent, SEC } else { switch (pSECPort->portDefinition.format.video.eColorFormat) { case OMX_SEC_COLOR_FormatNV12TPhysicalAddress: - case OMX_SEC_COLOR_FormatNV12LPhysicalAddress: - case OMX_SEC_COLOR_FormatNV21LPhysicalAddress: { + case OMX_SEC_COLOR_FormatNV12LPhysicalAddress: { #ifndef USE_METADATABUFFERTYPE /* USE_FIMC_FRAME_BUFFER */ SEC_OSAL_Memcpy(&addrInfo.pAddrY, pInputData->dataBuffer, sizeof(addrInfo.pAddrY)); @@ -1287,8 +1265,7 @@ OMX_ERRORTYPE SEC_MFC_H264_Encode_Block(OMX_COMPONENTTYPE *pOMXComponent, SEC_OM pSECPort = &pSECComponent->pSECPort[INPUT_PORT_INDEX]; switch (pSECPort->portDefinition.format.video.eColorFormat) { case OMX_SEC_COLOR_FormatNV12TPhysicalAddress: - case OMX_SEC_COLOR_FormatNV12LPhysicalAddress: - case OMX_SEC_COLOR_FormatNV21LPhysicalAddress: { + case OMX_SEC_COLOR_FormatNV12LPhysicalAddress: { #ifndef USE_METADATABUFFERTYPE /* USE_FIMC_FRAME_BUFFER */ SEC_OSAL_Memcpy(&addrInfo.pAddrY, pInputData->dataBuffer, sizeof(addrInfo.pAddrY)); @@ -1537,8 +1514,8 @@ OSCL_EXPORT_REF OMX_ERRORTYPE SEC_OMX_ComponentInit(OMX_HANDLETYPE hComponent, O for(i = 0; i < ALL_PORT_NUM; i++) { INIT_SET_SIZE_VERSION(&pH264Enc->AVCComponent[i], OMX_VIDEO_PARAM_AVCTYPE); pH264Enc->AVCComponent[i].nPortIndex = i; - pH264Enc->AVCComponent[i].eProfile = OMX_VIDEO_AVCProfileHigh; - pH264Enc->AVCComponent[i].eLevel = OMX_VIDEO_AVCLevel4; + pH264Enc->AVCComponent[i].eProfile = OMX_VIDEO_AVCProfileBaseline; + pH264Enc->AVCComponent[i].eLevel = OMX_VIDEO_AVCLevel31; pH264Enc->AVCComponent[i].nPFrames = 20; } diff --git a/exynos4/multimedia/openmax/sec_omx/component/video/enc/h264/SEC_OMX_H264enc.h b/exynos/multimedia/openmax/component/video/enc/h264/SEC_OMX_H264enc.h similarity index 100% rename from exynos4/multimedia/openmax/sec_omx/component/video/enc/h264/SEC_OMX_H264enc.h rename to exynos/multimedia/openmax/component/video/enc/h264/SEC_OMX_H264enc.h diff --git a/exynos4/multimedia/openmax/sec_omx/component/video/enc/h264/library_register.c b/exynos/multimedia/openmax/component/video/enc/h264/library_register.c similarity index 100% rename from exynos4/multimedia/openmax/sec_omx/component/video/enc/h264/library_register.c rename to exynos/multimedia/openmax/component/video/enc/h264/library_register.c diff --git a/exynos4/multimedia/openmax/sec_omx/component/video/enc/h264/library_register.h b/exynos/multimedia/openmax/component/video/enc/h264/library_register.h similarity index 100% rename from exynos4/multimedia/openmax/sec_omx/component/video/enc/h264/library_register.h rename to exynos/multimedia/openmax/component/video/enc/h264/library_register.h diff --git a/exynos4/multimedia/openmax/sec_omx/component/video/enc/mpeg4/Android.mk b/exynos/multimedia/openmax/component/video/enc/mpeg4/Android.mk similarity index 93% rename from exynos4/multimedia/openmax/sec_omx/component/video/enc/mpeg4/Android.mk rename to exynos/multimedia/openmax/component/video/enc/mpeg4/Android.mk index 441f5fb..ad6a604 100644 --- a/exynos4/multimedia/openmax/sec_omx/component/video/enc/mpeg4/Android.mk +++ b/exynos/multimedia/openmax/component/video/enc/mpeg4/Android.mk @@ -24,9 +24,9 @@ endif LOCAL_ARM_MODE := arm LOCAL_STATIC_LIBRARIES := libSEC_OMX_Venc libsecosal libsecbasecomponent \ - libswconverter libsecmfcapi + libseccscapi libsecmfcapi LOCAL_SHARED_LIBRARIES := libc libdl libcutils libutils libui \ - libSEC_OMX_Resourcemanager libcsc + libSEC_OMX_Resourcemanager LOCAL_C_INCLUDES := $(SEC_OMX_INC)/khronos \ $(SEC_OMX_INC)/sec \ diff --git a/exynos4/multimedia/openmax/sec_omx/component/video/enc/mpeg4/SEC_OMX_Mpeg4enc.c b/exynos/multimedia/openmax/component/video/enc/mpeg4/SEC_OMX_Mpeg4enc.c similarity index 98% rename from exynos4/multimedia/openmax/sec_omx/component/video/enc/mpeg4/SEC_OMX_Mpeg4enc.c rename to exynos/multimedia/openmax/component/video/enc/mpeg4/SEC_OMX_Mpeg4enc.c index 1fcc90e..ebfbe6e 100644 --- a/exynos4/multimedia/openmax/sec_omx/component/video/enc/mpeg4/SEC_OMX_Mpeg4enc.c +++ b/exynos/multimedia/openmax/component/video/enc/mpeg4/SEC_OMX_Mpeg4enc.c @@ -40,7 +40,7 @@ #include "library_register.h" #include "SEC_OMX_Mpeg4enc.h" #include "SsbSipMfcApi.h" -#include "csc.h" +#include "color_space_convertor.h" #undef SEC_LOG_TAG #define SEC_LOG_TAG "SEC_MPEG4_ENC" @@ -135,9 +135,6 @@ void Mpeg4PrintParams(SSBSIP_MFC_ENC_MPEG4_PARAM *pMpeg4Param) SEC_OSAL_Log(SEC_LOG_TRACE, "SourceHeight : %d\n", pMpeg4Param->SourceHeight); SEC_OSAL_Log(SEC_LOG_TRACE, "IDRPeriod : %d\n", pMpeg4Param->IDRPeriod); SEC_OSAL_Log(SEC_LOG_TRACE, "SliceMode : %d\n", pMpeg4Param->SliceMode); -#ifdef USE_SLICE_OUTPUT_MODE - SEC_OSAL_Log(SEC_LOG_TRACE, "OutputMode : %d\n", pMpeg4Param->OutputMode); -#endif SEC_OSAL_Log(SEC_LOG_TRACE, "RandomIntraMBRefresh : %d\n", pMpeg4Param->RandomIntraMBRefresh); SEC_OSAL_Log(SEC_LOG_TRACE, "EnableFRMRateControl : %d\n", pMpeg4Param->EnableFRMRateControl); SEC_OSAL_Log(SEC_LOG_TRACE, "Bitrate : %d\n", pMpeg4Param->Bitrate); @@ -204,9 +201,6 @@ void Set_Mpeg4Enc_Param(SSBSIP_MFC_ENC_MPEG4_PARAM *pMpeg4Param, SEC_OMX_BASECOM pMpeg4Param->SourceHeight = pSECOutputPort->portDefinition.format.video.nFrameHeight; pMpeg4Param->IDRPeriod = pMpeg4Enc->mpeg4Component[OUTPUT_PORT_INDEX].nPFrames + 1; pMpeg4Param->SliceMode = 0; -#ifdef USE_SLICE_OUTPUT_MODE - pMpeg4Param->OutputMode = FRAME; -#endif pMpeg4Param->RandomIntraMBRefresh = 0; pMpeg4Param->Bitrate = pSECOutputPort->portDefinition.format.video.nBitrate; pMpeg4Param->QSCodeMax = 30; @@ -260,12 +254,6 @@ void Set_Mpeg4Enc_Param(SSBSIP_MFC_ENC_MPEG4_PARAM *pMpeg4Param, SEC_OMX_BASECOM break; case OMX_SEC_COLOR_FormatNV12TPhysicalAddress: case OMX_SEC_COLOR_FormatNV12Tiled: - pMpeg4Param->FrameMap = NV12_TILE; - break; - case OMX_SEC_COLOR_FormatNV21LPhysicalAddress: - case OMX_SEC_COLOR_FormatNV21Linear: - pMpeg4Param->FrameMap = NV21_LINEAR; - break; default: pMpeg4Param->FrameMap = NV12_TILE; break; @@ -376,12 +364,6 @@ void Set_H263Enc_Param(SSBSIP_MFC_ENC_H263_PARAM *pH263Param, SEC_OMX_BASECOMPON break; case OMX_SEC_COLOR_FormatNV12TPhysicalAddress: case OMX_SEC_COLOR_FormatNV12Tiled: - pH263Param->FrameMap = NV12_TILE; - break; - case OMX_SEC_COLOR_FormatNV21LPhysicalAddress: - case OMX_SEC_COLOR_FormatNV21Linear: - pH263Param->FrameMap = NV21_LINEAR; - break; default: pH263Param->FrameMap = NV12_TILE; break; @@ -1048,7 +1030,6 @@ OMX_ERRORTYPE SEC_MFC_Mpeg4Enc_Init(OMX_COMPONENTTYPE *pOMXComponent) SEC_MPEG4ENC_HANDLE *pMpeg4Enc = NULL; OMX_HANDLETYPE hMFCHandle = NULL; OMX_S32 returnCodec = 0; - CSC_METHOD csc_method = CSC_METHOD_SW; FunctionIn(); @@ -1062,7 +1043,6 @@ OMX_ERRORTYPE SEC_MFC_Mpeg4Enc_Init(OMX_COMPONENTTYPE *pOMXComponent) case OMX_SEC_COLOR_FormatNV12TPhysicalAddress: case OMX_SEC_COLOR_FormatNV12LPhysicalAddress: case OMX_SEC_COLOR_FormatNV12LVirtualAddress: - case OMX_SEC_COLOR_FormatNV21LPhysicalAddress: hMFCHandle = (OMX_PTR)SsbSipMfcEncOpen(); break; default: { @@ -1143,8 +1123,6 @@ OMX_ERRORTYPE SEC_MFC_Mpeg4Enc_Init(OMX_COMPONENTTYPE *pOMXComponent) SEC_OSAL_Memset(pSECComponent->nFlags, 0, sizeof(OMX_U32) * MAX_FLAGS); pMpeg4Enc->hMFCMpeg4Handle.indexTimestamp = 0; - pVideoEnc->csc_handle = csc_init(&csc_method); - EXIT: FunctionOut(); @@ -1188,11 +1166,6 @@ OMX_ERRORTYPE SEC_MFC_Mpeg4Enc_Terminate(OMX_COMPONENTTYPE *pOMXComponent) hMFCHandle = pMpeg4Enc->hMFCMpeg4Handle.hMFCHandle = NULL; } - if (pVideoEnc->csc_handle != NULL) { - csc_deinit(pVideoEnc->csc_handle); - pVideoEnc->csc_handle = NULL; - } - EXIT: FunctionOut(); @@ -1259,8 +1232,7 @@ OMX_ERRORTYPE SEC_MFC_Mpeg4_Encode_Nonblock(OMX_COMPONENTTYPE *pOMXComponent, SE } else { switch (pSECPort->portDefinition.format.video.eColorFormat) { case OMX_SEC_COLOR_FormatNV12TPhysicalAddress: - case OMX_SEC_COLOR_FormatNV12LPhysicalAddress: - case OMX_SEC_COLOR_FormatNV21LPhysicalAddress: { + case OMX_SEC_COLOR_FormatNV12LPhysicalAddress: { #ifndef USE_METADATABUFFERTYPE /* USE_FIMC_FRAME_BUFFER */ SEC_OSAL_Memcpy(&addrInfo.pAddrY, pInputData->dataBuffer, sizeof(addrInfo.pAddrY)); @@ -1445,8 +1417,7 @@ OMX_ERRORTYPE SEC_MFC_Mpeg4_Encode_Block(OMX_COMPONENTTYPE *pOMXComponent, SEC_O pSECPort = &pSECComponent->pSECPort[INPUT_PORT_INDEX]; switch (pSECPort->portDefinition.format.video.eColorFormat) { case OMX_SEC_COLOR_FormatNV12TPhysicalAddress: - case OMX_SEC_COLOR_FormatNV12LPhysicalAddress: - case OMX_SEC_COLOR_FormatNV21LPhysicalAddress: { + case OMX_SEC_COLOR_FormatNV12LPhysicalAddress: { #ifndef USE_METADATABUFFERTYPE /* USE_FIMC_FRAME_BUFFER */ SEC_OSAL_Memcpy(&addrInfo.pAddrY, pInputData->dataBuffer, sizeof(addrInfo.pAddrY)); diff --git a/exynos4/multimedia/openmax/sec_omx/component/video/enc/mpeg4/SEC_OMX_Mpeg4enc.h b/exynos/multimedia/openmax/component/video/enc/mpeg4/SEC_OMX_Mpeg4enc.h similarity index 100% rename from exynos4/multimedia/openmax/sec_omx/component/video/enc/mpeg4/SEC_OMX_Mpeg4enc.h rename to exynos/multimedia/openmax/component/video/enc/mpeg4/SEC_OMX_Mpeg4enc.h diff --git a/exynos4/multimedia/openmax/sec_omx/component/video/enc/mpeg4/library_register.c b/exynos/multimedia/openmax/component/video/enc/mpeg4/library_register.c similarity index 100% rename from exynos4/multimedia/openmax/sec_omx/component/video/enc/mpeg4/library_register.c rename to exynos/multimedia/openmax/component/video/enc/mpeg4/library_register.c diff --git a/exynos4/multimedia/openmax/sec_omx/component/video/enc/mpeg4/library_register.h b/exynos/multimedia/openmax/component/video/enc/mpeg4/library_register.h similarity index 100% rename from exynos4/multimedia/openmax/sec_omx/component/video/enc/mpeg4/library_register.h rename to exynos/multimedia/openmax/component/video/enc/mpeg4/library_register.h diff --git a/exynos4/multimedia/openmax/sec_omx/core/Android.mk b/exynos/multimedia/openmax/core/Android.mk similarity index 100% rename from exynos4/multimedia/openmax/sec_omx/core/Android.mk rename to exynos/multimedia/openmax/core/Android.mk diff --git a/exynos4/multimedia/openmax/sec_omx/core/SEC_OMX_Component_Register.c b/exynos/multimedia/openmax/core/SEC_OMX_Component_Register.c similarity index 100% rename from exynos4/multimedia/openmax/sec_omx/core/SEC_OMX_Component_Register.c rename to exynos/multimedia/openmax/core/SEC_OMX_Component_Register.c diff --git a/exynos4/multimedia/openmax/sec_omx/core/SEC_OMX_Component_Register.h b/exynos/multimedia/openmax/core/SEC_OMX_Component_Register.h similarity index 100% rename from exynos4/multimedia/openmax/sec_omx/core/SEC_OMX_Component_Register.h rename to exynos/multimedia/openmax/core/SEC_OMX_Component_Register.h diff --git a/exynos4/multimedia/openmax/sec_omx/core/SEC_OMX_Core.c b/exynos/multimedia/openmax/core/SEC_OMX_Core.c similarity index 100% rename from exynos4/multimedia/openmax/sec_omx/core/SEC_OMX_Core.c rename to exynos/multimedia/openmax/core/SEC_OMX_Core.c diff --git a/exynos4/multimedia/openmax/sec_omx/core/SEC_OMX_Core.h b/exynos/multimedia/openmax/core/SEC_OMX_Core.h similarity index 100% rename from exynos4/multimedia/openmax/sec_omx/core/SEC_OMX_Core.h rename to exynos/multimedia/openmax/core/SEC_OMX_Core.h diff --git a/exynos4/multimedia/openmax/sec_omx/include/khronos/OMX_Audio.h b/exynos/multimedia/openmax/include/khronos/OMX_Audio.h similarity index 100% rename from exynos4/multimedia/openmax/sec_omx/include/khronos/OMX_Audio.h rename to exynos/multimedia/openmax/include/khronos/OMX_Audio.h diff --git a/exynos4/multimedia/openmax/sec_omx/include/khronos/OMX_Component.h b/exynos/multimedia/openmax/include/khronos/OMX_Component.h similarity index 100% rename from exynos4/multimedia/openmax/sec_omx/include/khronos/OMX_Component.h rename to exynos/multimedia/openmax/include/khronos/OMX_Component.h diff --git a/exynos4/multimedia/openmax/sec_omx/include/khronos/OMX_ContentPipe.h b/exynos/multimedia/openmax/include/khronos/OMX_ContentPipe.h similarity index 100% rename from exynos4/multimedia/openmax/sec_omx/include/khronos/OMX_ContentPipe.h rename to exynos/multimedia/openmax/include/khronos/OMX_ContentPipe.h diff --git a/exynos4/multimedia/openmax/sec_omx/include/khronos/OMX_Core.h b/exynos/multimedia/openmax/include/khronos/OMX_Core.h similarity index 100% rename from exynos4/multimedia/openmax/sec_omx/include/khronos/OMX_Core.h rename to exynos/multimedia/openmax/include/khronos/OMX_Core.h diff --git a/exynos4/multimedia/openmax/sec_omx/include/khronos/OMX_IVCommon.h b/exynos/multimedia/openmax/include/khronos/OMX_IVCommon.h similarity index 100% rename from exynos4/multimedia/openmax/sec_omx/include/khronos/OMX_IVCommon.h rename to exynos/multimedia/openmax/include/khronos/OMX_IVCommon.h diff --git a/exynos4/multimedia/openmax/sec_omx/include/khronos/OMX_Image.h b/exynos/multimedia/openmax/include/khronos/OMX_Image.h similarity index 100% rename from exynos4/multimedia/openmax/sec_omx/include/khronos/OMX_Image.h rename to exynos/multimedia/openmax/include/khronos/OMX_Image.h diff --git a/exynos4/multimedia/openmax/sec_omx/include/khronos/OMX_Index.h b/exynos/multimedia/openmax/include/khronos/OMX_Index.h similarity index 100% rename from exynos4/multimedia/openmax/sec_omx/include/khronos/OMX_Index.h rename to exynos/multimedia/openmax/include/khronos/OMX_Index.h diff --git a/exynos4/multimedia/openmax/sec_omx/include/khronos/OMX_Other.h b/exynos/multimedia/openmax/include/khronos/OMX_Other.h similarity index 100% rename from exynos4/multimedia/openmax/sec_omx/include/khronos/OMX_Other.h rename to exynos/multimedia/openmax/include/khronos/OMX_Other.h diff --git a/exynos4/multimedia/openmax/sec_omx/include/khronos/OMX_Types.h b/exynos/multimedia/openmax/include/khronos/OMX_Types.h similarity index 100% rename from exynos4/multimedia/openmax/sec_omx/include/khronos/OMX_Types.h rename to exynos/multimedia/openmax/include/khronos/OMX_Types.h diff --git a/exynos4/multimedia/openmax/sec_omx/include/khronos/OMX_Video.h b/exynos/multimedia/openmax/include/khronos/OMX_Video.h similarity index 100% rename from exynos4/multimedia/openmax/sec_omx/include/khronos/OMX_Video.h rename to exynos/multimedia/openmax/include/khronos/OMX_Video.h diff --git a/exynos4/multimedia/openmax/sec_omx/include/sec/SEC_OMX_Def.h b/exynos/multimedia/openmax/include/sec/SEC_OMX_Def.h similarity index 97% rename from exynos4/multimedia/openmax/sec_omx/include/sec/SEC_OMX_Def.h rename to exynos/multimedia/openmax/include/sec/SEC_OMX_Def.h index 2b4df69..bf5fe52 100644 --- a/exynos4/multimedia/openmax/sec_omx/include/sec/SEC_OMX_Def.h +++ b/exynos/multimedia/openmax/include/sec/SEC_OMX_Def.h @@ -129,9 +129,6 @@ typedef enum _SEC_OMX_COLOR_FORMATTYPE { OMX_SEC_COLOR_FormatYUV420Planar_TB_LR = 0x7FC0000D, /* 0x7FC0000D */ OMX_SEC_COLOR_FormatYUV420Planar_TB_RL = 0x7FC0000E, /* 0x7FC0000E */ #endif - OMX_SEC_COLOR_FormatNV21LPhysicalAddress = 0x7F000010, - OMX_SEC_COLOR_FormatNV21Linear = 0x7F000011, - /* for Android Native Window */ OMX_SEC_COLOR_FormatANBYUV420SemiPlanar = 0x100, /* for Android SurfaceMediaSource*/ @@ -147,8 +144,6 @@ typedef enum _SEC_OMX_SUPPORTFORMAT_TYPE supportFormat_4, supportFormat_5, supportFormat_6, - supportFormat_7, - supportFormat_8 } SEC_OMX_SUPPORTFORMAT_TYPE; /* for Android PV OpenCore*/ diff --git a/exynos4/multimedia/openmax/sec_omx/include/sec/SEC_OMX_Macros.h b/exynos/multimedia/openmax/include/sec/SEC_OMX_Macros.h similarity index 100% rename from exynos4/multimedia/openmax/sec_omx/include/sec/SEC_OMX_Macros.h rename to exynos/multimedia/openmax/include/sec/SEC_OMX_Macros.h diff --git a/exynos4/multimedia/openmax/sec_omx/osal/Android.mk b/exynos/multimedia/openmax/osal/Android.mk similarity index 83% rename from exynos4/multimedia/openmax/sec_omx/osal/Android.mk rename to exynos/multimedia/openmax/osal/Android.mk index 5dcbeee..e4ceba0 100644 --- a/exynos4/multimedia/openmax/sec_omx/osal/Android.mk +++ b/exynos/multimedia/openmax/osal/Android.mk @@ -20,9 +20,11 @@ LOCAL_MODULE := libsecosal LOCAL_CFLAGS := +ifeq ($(BOARD_USE_V4L2), false) ifeq ($(BOARD_USE_S3D_SUPPORT), true) LOCAL_CFLAGS += -DS3D_SUPPORT endif +endif LOCAL_STATIC_LIBRARIES := LOCAL_SHARED_LIBRARIES := libcutils libutils \ @@ -33,13 +35,10 @@ LOCAL_SHARED_LIBRARIES := libcutils libutils \ libbinder \ libmedia -LOCAL_C_INCLUDES := \ - $(SEC_OMX_INC)/khronos \ +LOCAL_C_INCLUDES := $(SEC_OMX_INC)/khronos \ $(SEC_OMX_INC)/sec \ $(SEC_OMX_TOP)/osal \ $(SEC_OMX_COMPONENT)/common \ - $(SEC_OMX_COMPONENT)/video/dec \ - $(BOARD_HAL_PATH)/include \ - $(BOARD_HAL_PATH)/libump/include + $(SEC_OMX_COMPONENT)/video/dec include $(BUILD_STATIC_LIBRARY) diff --git a/exynos4/multimedia/openmax/sec_omx/osal/SEC_OSAL_Android.cpp b/exynos/multimedia/openmax/osal/SEC_OSAL_Android.cpp similarity index 99% rename from exynos4/multimedia/openmax/sec_omx/osal/SEC_OSAL_Android.cpp rename to exynos/multimedia/openmax/osal/SEC_OSAL_Android.cpp index 2a51de9..bb41720 100644 --- a/exynos4/multimedia/openmax/sec_omx/osal/SEC_OSAL_Android.cpp +++ b/exynos/multimedia/openmax/osal/SEC_OSAL_Android.cpp @@ -37,8 +37,6 @@ #include #include -#include "gralloc_priv.h" - #include "SEC_OSAL_Semaphore.h" #include "SEC_OMX_Baseport.h" #include "SEC_OMX_Basecomponent.h" diff --git a/exynos4/multimedia/openmax/sec_omx/osal/SEC_OSAL_Android.h b/exynos/multimedia/openmax/osal/SEC_OSAL_Android.h similarity index 100% rename from exynos4/multimedia/openmax/sec_omx/osal/SEC_OSAL_Android.h rename to exynos/multimedia/openmax/osal/SEC_OSAL_Android.h diff --git a/exynos4/multimedia/openmax/sec_omx/osal/SEC_OSAL_ETC.c b/exynos/multimedia/openmax/osal/SEC_OSAL_ETC.c similarity index 64% rename from exynos4/multimedia/openmax/sec_omx/osal/SEC_OSAL_ETC.c rename to exynos/multimedia/openmax/osal/SEC_OSAL_ETC.c index 2082368..1bce154 100644 --- a/exynos4/multimedia/openmax/sec_omx/osal/SEC_OSAL_ETC.c +++ b/exynos/multimedia/openmax/osal/SEC_OSAL_ETC.c @@ -27,15 +27,10 @@ #include #include #include -#include #include "SEC_OSAL_Memory.h" #include "SEC_OSAL_ETC.h" -#include "SEC_OSAL_Log.h" -static struct timeval perfStart[PERF_ID_MAX+1], perfStop[PERF_ID_MAX+1]; -static unsigned long perfTime[PERF_ID_MAX+1], totalPerfTime[PERF_ID_MAX+1]; -static unsigned int perfFrameCount[PERF_ID_MAX+1], perfOver30ms[PERF_ID_MAX+1]; #ifndef HAVE_GETLINE ssize_t getline(char **ppLine, size_t *pLen, FILE *pStream) @@ -157,81 +152,3 @@ size_t SEC_OSAL_Strlen(const char *str) { return strlen(str); } - -static OMX_U32 MeasureTime(struct timeval *start, struct timeval *stop) -{ - unsigned long sec, usec, time; - - sec = stop->tv_sec - start->tv_sec; - if (stop->tv_usec >= start->tv_usec) { - usec = stop->tv_usec - start->tv_usec; - } else { - usec = stop->tv_usec + 1000000 - start->tv_usec; - sec--; - } - - time = sec * 1000000 + (usec); - - return time; -} - -void SEC_OSAL_PerfInit(PERF_ID_TYPE id) -{ - memset(&perfStart[id], 0, sizeof(perfStart[id])); - memset(&perfStop[id], 0, sizeof(perfStop[id])); - perfTime[id] = 0; - totalPerfTime[id] = 0; - perfFrameCount[id] = 0; - perfOver30ms[id] = 0; -} - -void SEC_OSAL_PerfStart(PERF_ID_TYPE id) -{ - gettimeofday(&perfStart[id], NULL); -} - -void SEC_OSAL_PerfStop(PERF_ID_TYPE id) -{ - gettimeofday(&perfStop[id], NULL); - - perfTime[id] = MeasureTime(&perfStart[id], &perfStop[id]); - totalPerfTime[id] += perfTime[id]; - perfFrameCount[id]++; - - if (perfTime[id] > 30000) - perfOver30ms[id]++; -} - -OMX_U32 SEC_OSAL_PerfFrame(PERF_ID_TYPE id) -{ - return perfTime[id]; -} - -OMX_U32 SEC_OSAL_PerfTotal(PERF_ID_TYPE id) -{ - return totalPerfTime[id]; -} - -OMX_U32 SEC_OSAL_PerfFrameCount(PERF_ID_TYPE id) -{ - return perfFrameCount[id]; -} - -int SEC_OSAL_PerfOver30ms(PERF_ID_TYPE id) -{ - return perfOver30ms[id]; -} - -void SEC_OSAL_PerfPrint(OMX_STRING prefix, PERF_ID_TYPE id) -{ - OMX_U32 perfTotal; - int frameCount; - - frameCount = SEC_OSAL_PerfFrameCount(id); - perfTotal = SEC_OSAL_PerfTotal(id); - - SEC_OSAL_Log(SEC_LOG_INFO, "%s Frame Count: %d", prefix, frameCount); - SEC_OSAL_Log(SEC_LOG_INFO, "%s Avg Time: %.2f ms, Over 30ms: %d", - prefix, (float)perfTotal / (float)(frameCount * 1000), - SEC_OSAL_PerfOver30ms(id)); -} diff --git a/exynos4/multimedia/openmax/sec_omx/osal/SEC_OSAL_ETC.h b/exynos/multimedia/openmax/osal/SEC_OSAL_ETC.h similarity index 70% rename from exynos4/multimedia/openmax/sec_omx/osal/SEC_OSAL_ETC.h rename to exynos/multimedia/openmax/osal/SEC_OSAL_ETC.h index 2275abb..f311f26 100644 --- a/exynos4/multimedia/openmax/sec_omx/osal/SEC_OSAL_ETC.h +++ b/exynos/multimedia/openmax/osal/SEC_OSAL_ETC.h @@ -41,24 +41,6 @@ OMX_PTR SEC_OSAL_Strcat(OMX_PTR dest, OMX_PTR src); size_t SEC_OSAL_Strlen(const char *str); ssize_t getline(char **ppLine, size_t *len, FILE *stream); -/* perf */ -typedef enum _PERF_ID_TYPE { - PERF_ID_CSC = 0, - PERF_ID_DEC, - PERF_ID_ENC, - PERF_ID_USER, - PERF_ID_MAX, -} PERF_ID_TYPE; - -void SEC_OSAL_PerfInit(PERF_ID_TYPE id); -void SEC_OSAL_PerfStart(PERF_ID_TYPE id); -void SEC_OSAL_PerfStop(PERF_ID_TYPE id); -OMX_U32 SEC_OSAL_PerfFrame(PERF_ID_TYPE id); -OMX_U32 SEC_OSAL_PerfTotal(PERF_ID_TYPE id); -OMX_U32 SEC_OSAL_PerfFrameCount(PERF_ID_TYPE id); -int SEC_OSAL_PerfOver30ms(PERF_ID_TYPE id); -void SEC_OSAL_PerfPrint(OMX_STRING prefix, PERF_ID_TYPE id); - #ifdef __cplusplus } #endif diff --git a/exynos4/multimedia/openmax/sec_omx/osal/SEC_OSAL_Event.c b/exynos/multimedia/openmax/osal/SEC_OSAL_Event.c similarity index 100% rename from exynos4/multimedia/openmax/sec_omx/osal/SEC_OSAL_Event.c rename to exynos/multimedia/openmax/osal/SEC_OSAL_Event.c diff --git a/exynos4/multimedia/openmax/sec_omx/osal/SEC_OSAL_Event.h b/exynos/multimedia/openmax/osal/SEC_OSAL_Event.h similarity index 100% rename from exynos4/multimedia/openmax/sec_omx/osal/SEC_OSAL_Event.h rename to exynos/multimedia/openmax/osal/SEC_OSAL_Event.h diff --git a/exynos4/multimedia/openmax/sec_omx/osal/SEC_OSAL_Library.c b/exynos/multimedia/openmax/osal/SEC_OSAL_Library.c similarity index 100% rename from exynos4/multimedia/openmax/sec_omx/osal/SEC_OSAL_Library.c rename to exynos/multimedia/openmax/osal/SEC_OSAL_Library.c diff --git a/exynos4/multimedia/openmax/sec_omx/osal/SEC_OSAL_Library.h b/exynos/multimedia/openmax/osal/SEC_OSAL_Library.h similarity index 100% rename from exynos4/multimedia/openmax/sec_omx/osal/SEC_OSAL_Library.h rename to exynos/multimedia/openmax/osal/SEC_OSAL_Library.h diff --git a/exynos4/multimedia/openmax/sec_omx/osal/SEC_OSAL_Log.c b/exynos/multimedia/openmax/osal/SEC_OSAL_Log.c similarity index 93% rename from exynos4/multimedia/openmax/sec_omx/osal/SEC_OSAL_Log.c rename to exynos/multimedia/openmax/osal/SEC_OSAL_Log.c index 0aa956a..ea95174 100644 --- a/exynos4/multimedia/openmax/sec_omx/osal/SEC_OSAL_Log.c +++ b/exynos/multimedia/openmax/osal/SEC_OSAL_Log.c @@ -39,9 +39,6 @@ void _SEC_OSAL_Log(SEC_LOG_LEVEL logLevel, const char *tag, const char *msg, ... case SEC_LOG_TRACE: __android_log_vprint(ANDROID_LOG_DEBUG, tag, msg, argptr); break; - case SEC_LOG_INFO: - __android_log_vprint(ANDROID_LOG_INFO, tag, msg, argptr); - break; case SEC_LOG_WARNING: __android_log_vprint(ANDROID_LOG_WARN, tag, msg, argptr); break; diff --git a/exynos4/multimedia/openmax/sec_omx/osal/SEC_OSAL_Log.h b/exynos/multimedia/openmax/osal/SEC_OSAL_Log.h similarity index 99% rename from exynos4/multimedia/openmax/sec_omx/osal/SEC_OSAL_Log.h rename to exynos/multimedia/openmax/osal/SEC_OSAL_Log.h index d4f2617..b993b90 100644 --- a/exynos4/multimedia/openmax/sec_omx/osal/SEC_OSAL_Log.h +++ b/exynos/multimedia/openmax/osal/SEC_OSAL_Log.h @@ -47,7 +47,6 @@ extern "C" { typedef enum _LOG_LEVEL { SEC_LOG_TRACE, - SEC_LOG_INFO, SEC_LOG_WARNING, SEC_LOG_ERROR } SEC_LOG_LEVEL; diff --git a/exynos4/multimedia/openmax/sec_omx/osal/SEC_OSAL_Memory.c b/exynos/multimedia/openmax/osal/SEC_OSAL_Memory.c similarity index 100% rename from exynos4/multimedia/openmax/sec_omx/osal/SEC_OSAL_Memory.c rename to exynos/multimedia/openmax/osal/SEC_OSAL_Memory.c diff --git a/exynos4/multimedia/openmax/sec_omx/osal/SEC_OSAL_Memory.h b/exynos/multimedia/openmax/osal/SEC_OSAL_Memory.h similarity index 100% rename from exynos4/multimedia/openmax/sec_omx/osal/SEC_OSAL_Memory.h rename to exynos/multimedia/openmax/osal/SEC_OSAL_Memory.h diff --git a/exynos4/multimedia/openmax/sec_omx/osal/SEC_OSAL_Mutex.c b/exynos/multimedia/openmax/osal/SEC_OSAL_Mutex.c similarity index 100% rename from exynos4/multimedia/openmax/sec_omx/osal/SEC_OSAL_Mutex.c rename to exynos/multimedia/openmax/osal/SEC_OSAL_Mutex.c diff --git a/exynos4/multimedia/openmax/sec_omx/osal/SEC_OSAL_Mutex.h b/exynos/multimedia/openmax/osal/SEC_OSAL_Mutex.h similarity index 100% rename from exynos4/multimedia/openmax/sec_omx/osal/SEC_OSAL_Mutex.h rename to exynos/multimedia/openmax/osal/SEC_OSAL_Mutex.h diff --git a/exynos4/multimedia/openmax/sec_omx/osal/SEC_OSAL_Queue.c b/exynos/multimedia/openmax/osal/SEC_OSAL_Queue.c similarity index 100% rename from exynos4/multimedia/openmax/sec_omx/osal/SEC_OSAL_Queue.c rename to exynos/multimedia/openmax/osal/SEC_OSAL_Queue.c diff --git a/exynos4/multimedia/openmax/sec_omx/osal/SEC_OSAL_Queue.h b/exynos/multimedia/openmax/osal/SEC_OSAL_Queue.h similarity index 100% rename from exynos4/multimedia/openmax/sec_omx/osal/SEC_OSAL_Queue.h rename to exynos/multimedia/openmax/osal/SEC_OSAL_Queue.h diff --git a/exynos4/multimedia/openmax/sec_omx/osal/SEC_OSAL_Semaphore.c b/exynos/multimedia/openmax/osal/SEC_OSAL_Semaphore.c similarity index 100% rename from exynos4/multimedia/openmax/sec_omx/osal/SEC_OSAL_Semaphore.c rename to exynos/multimedia/openmax/osal/SEC_OSAL_Semaphore.c diff --git a/exynos4/multimedia/openmax/sec_omx/osal/SEC_OSAL_Semaphore.h b/exynos/multimedia/openmax/osal/SEC_OSAL_Semaphore.h similarity index 100% rename from exynos4/multimedia/openmax/sec_omx/osal/SEC_OSAL_Semaphore.h rename to exynos/multimedia/openmax/osal/SEC_OSAL_Semaphore.h diff --git a/exynos4/multimedia/openmax/sec_omx/osal/SEC_OSAL_Thread.c b/exynos/multimedia/openmax/osal/SEC_OSAL_Thread.c similarity index 100% rename from exynos4/multimedia/openmax/sec_omx/osal/SEC_OSAL_Thread.c rename to exynos/multimedia/openmax/osal/SEC_OSAL_Thread.c diff --git a/exynos4/multimedia/openmax/sec_omx/osal/SEC_OSAL_Thread.h b/exynos/multimedia/openmax/osal/SEC_OSAL_Thread.h similarity index 100% rename from exynos4/multimedia/openmax/sec_omx/osal/SEC_OSAL_Thread.h rename to exynos/multimedia/openmax/osal/SEC_OSAL_Thread.h diff --git a/exynos4/multimedia/codecs/sec_codecs/Android.mk b/exynos/multimedia/utils/Android.mk similarity index 100% rename from exynos4/multimedia/codecs/sec_codecs/Android.mk rename to exynos/multimedia/utils/Android.mk diff --git a/exynos/multimedia/utils/csc/Android.mk b/exynos/multimedia/utils/csc/Android.mk new file mode 100644 index 0000000..3bc3577 --- /dev/null +++ b/exynos/multimedia/utils/csc/Android.mk @@ -0,0 +1,11 @@ +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) + +ifeq ($(filter-out exynos4,$(TARGET_BOARD_PLATFORM)),) +include $(LOCAL_PATH)/exynos4/Android.mk +endif + +ifeq ($(filter-out exynos5,$(TARGET_BOARD_PLATFORM)),) +include $(LOCAL_PATH)/exynos5/Android.mk +endif diff --git a/exynos/multimedia/utils/csc/exynos4/Android.mk b/exynos/multimedia/utils/csc/exynos4/Android.mk new file mode 100644 index 0000000..e7ed4e2 --- /dev/null +++ b/exynos/multimedia/utils/csc/exynos4/Android.mk @@ -0,0 +1,42 @@ +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_COPY_HEADERS_TO := libsecmm +LOCAL_COPY_HEADERS := \ + color_space_convertor.h \ + csc_fimc.h + +LOCAL_MODULE_TAGS := optional + +LOCAL_SRC_FILES := \ + color_space_convertor.c \ + csc_linear_to_tiled_crop_neon.s \ + csc_linear_to_tiled_interleave_crop_neon.s \ + csc_tiled_to_linear_crop_neon.s \ + csc_tiled_to_linear_deinterleave_crop_neon.s \ + csc_interleave_memcpy_neon.s \ + csc_fimc.cpp + +LOCAL_C_INCLUDES := \ + $(TOP)/$(TARGET_OMX_PATH)/include/khronos \ + $(TOP)/$(TARGET_OMX_PATH)/include/sec \ + $(TOP)/$(TARGET_HAL_PATH)/include \ + $(TOP)/$(TARGET_HAL_PATH)/libhwconverter + +ifeq ($(BOARD_USE_SAMSUNG_COLORFORMAT), true) +LOCAL_CFLAGS += -DUSE_SAMSUNG_COLORFORMAT +endif + +LOCAL_MODULE := libseccscapi + +LOCAL_PRELINK_MODULE := false + +LOCAL_CFLAGS := + +LOCAL_ARM_MODE := arm + +LOCAL_STATIC_LIBRARIES := +LOCAL_SHARED_LIBRARIES := liblog libfimc libhwconverter + +include $(BUILD_STATIC_LIBRARY) diff --git a/exynos/multimedia/utils/csc/exynos4/color_space_convertor.c b/exynos/multimedia/utils/csc/exynos4/color_space_convertor.c new file mode 100644 index 0000000..7a4c559 --- /dev/null +++ b/exynos/multimedia/utils/csc/exynos4/color_space_convertor.c @@ -0,0 +1,1732 @@ +/* + * + * Copyright 2010 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file color_space_convertor.c + * + * @brief SEC_OMX specific define + * + * @author ShinWon Lee (shinwon.lee@samsung.com) + * + * @version 1.0 + * + * @history + * 2011.7.01 : Create + */ + +#include "stdio.h" +#include "stdlib.h" +#include "color_space_convertor.h" + +/* + * Get tiled address of position(x,y) + * + * @param x_size + * width of tiled[in] + * + * @param y_size + * height of tiled[in] + * + * @param x_pos + * x position of tield[in] + * + * @param src_size + * y position of tield[in] + * + * @return + * address of tiled data + */ +static int tile_4x2_read(int x_size, int y_size, int x_pos, int y_pos) +{ + int pixel_x_m1, pixel_y_m1; + int roundup_x, roundup_y; + int linear_addr0, linear_addr1, bank_addr ; + int x_addr; + int trans_addr; + + pixel_x_m1 = x_size -1; + pixel_y_m1 = y_size -1; + + roundup_x = ((pixel_x_m1 >> 7) + 1); + roundup_y = ((pixel_x_m1 >> 6) + 1); + + x_addr = x_pos >> 2; + + if ((y_size <= y_pos+32) && ( y_pos < y_size) && + (((pixel_y_m1 >> 5) & 0x1) == 0) && (((y_pos >> 5) & 0x1) == 0)) { + linear_addr0 = (((y_pos & 0x1f) <<4) | (x_addr & 0xf)); + linear_addr1 = (((y_pos >> 6) & 0xff) * roundup_x + ((x_addr >> 6) & 0x3f)); + + if (((x_addr >> 5) & 0x1) == ((y_pos >> 5) & 0x1)) + bank_addr = ((x_addr >> 4) & 0x1); + else + bank_addr = 0x2 | ((x_addr >> 4) & 0x1); + } else { + linear_addr0 = (((y_pos & 0x1f) << 4) | (x_addr & 0xf)); + linear_addr1 = (((y_pos >> 6) & 0xff) * roundup_x + ((x_addr >> 5) & 0x7f)); + + if (((x_addr >> 5) & 0x1) == ((y_pos >> 5) & 0x1)) + bank_addr = ((x_addr >> 4) & 0x1); + else + bank_addr = 0x2 | ((x_addr >> 4) & 0x1); + } + + linear_addr0 = linear_addr0 << 2; + trans_addr = (linear_addr1 <<13) | (bank_addr << 11) | linear_addr0; + + return trans_addr; +} + +/* + * De-interleaves src to dest1, dest2 + * + * @param dest1 + * Address of de-interleaved data[out] + * + * @param dest2 + * Address of de-interleaved data[out] + * + * @param src + * Address of interleaved data[in] + * + * @param src_size + * Size of interleaved data[in] + */ +static void csc_deinterleave_memcpy( + unsigned char *dest1, + unsigned char *dest2, + unsigned char *src, + unsigned int src_size) +{ + unsigned int i = 0; + for(i=0; i= 256) { + for (i=top; i>8)<<8; + temp3 = temp3>>6; + temp4 = i>>5; + if (temp4 & 0x1) { + /* odd fomula: 2+x+(x>>2)<<2+x_block_num*(y-1) */ + tiled_offset = temp4-1; + temp1 = ((yuv420_width+127)>>7)<<7; + tiled_offset = tiled_offset*(temp1>>6); + tiled_offset = tiled_offset+temp3; + tiled_offset = tiled_offset+2; + temp1 = (temp3>>2)<<2; + tiled_offset = tiled_offset+temp1; + tiled_offset = tiled_offset<<11; + tiled_offset1 = tiled_offset+2048*2; + temp4 = 8; + } else { + temp2 = ((yuv420_height+31)>>5)<<5; + if ((i+32)>2)<<2+x_block_num*y */ + temp1 = temp3+2; + temp1 = (temp1>>2)<<2; + tiled_offset = temp3+temp1; + temp1 = ((yuv420_width+127)>>7)<<7; + tiled_offset = tiled_offset+temp4*(temp1>>6); + tiled_offset = tiled_offset<<11; + tiled_offset1 = tiled_offset+2048*6; + temp4 = 8; + } else { + /* even2 fomula: x+x_block_num*y */ + temp1 = ((yuv420_width+127)>>7)<<7; + tiled_offset = temp4*(temp1>>6); + tiled_offset = tiled_offset+temp3; + tiled_offset = tiled_offset<<11; + tiled_offset1 = tiled_offset+2048*2; + temp4 = 4; + } + } + + temp1 = i&0x1F; + tiled_offset = tiled_offset+64*(temp1); + tiled_offset1 = tiled_offset1+64*(temp1); + temp2 = yuv420_width-left-right; + linear_offset = temp2*(i-top); + temp3 = ((j+256)>>8)<<8; + temp3 = temp3-j; + temp1 = left&0x3F; + if (temp3 > 192) { + memcpy(yuv420_dest+linear_offset, nv12t_src+tiled_offset+temp1, 64-temp1); + temp2 = ((left+63)>>6)<<6; + temp3 = ((yuv420_width-right)>>6)<<6; + if (temp2 == temp3) { + temp2 = yuv420_width-right-(64-temp1); + } + memcpy(yuv420_dest+linear_offset+64-temp1, nv12t_src+tiled_offset+2048, 64); + memcpy(yuv420_dest+linear_offset+128-temp1, nv12t_src+tiled_offset1, 64); + memcpy(yuv420_dest+linear_offset+192-temp1, nv12t_src+tiled_offset1+2048, 64); + linear_offset = linear_offset+256-temp1; + } else if (temp3 > 128) { + memcpy(yuv420_dest+linear_offset, nv12t_src+tiled_offset+2048+temp1, 64-temp1); + memcpy(yuv420_dest+linear_offset+64-temp1, nv12t_src+tiled_offset1, 64); + memcpy(yuv420_dest+linear_offset+128-temp1, nv12t_src+tiled_offset1+2048, 64); + linear_offset = linear_offset+192-temp1; + } else if (temp3 > 64) { + memcpy(yuv420_dest+linear_offset, nv12t_src+tiled_offset1+temp1, 64-temp1); + memcpy(yuv420_dest+linear_offset+64-temp1, nv12t_src+tiled_offset1+2048, 64); + linear_offset = linear_offset+128-temp1; + } else if (temp3 > 0) { + memcpy(yuv420_dest+linear_offset, nv12t_src+tiled_offset1+2048+temp1, 64-temp1); + linear_offset = linear_offset+64-temp1; + } + + tiled_offset = tiled_offset+temp4*2048; + j = (left>>8)<<8; + j = j + 256; + temp2 = yuv420_width-right-256; + for (; j<=temp2; j=j+256) { + memcpy(yuv420_dest+linear_offset, nv12t_src+tiled_offset, 64); + tiled_offset1 = tiled_offset1+temp4*2048; + memcpy(yuv420_dest+linear_offset+64, nv12t_src+tiled_offset+2048, 64); + memcpy(yuv420_dest+linear_offset+128, nv12t_src+tiled_offset1, 64); + tiled_offset = tiled_offset+temp4*2048; + memcpy(yuv420_dest+linear_offset+192, nv12t_src+tiled_offset1+2048, 64); + linear_offset = linear_offset+256; + } + + tiled_offset1 = tiled_offset1+temp4*2048; + temp2 = yuv420_width-right-j; + if (temp2 > 192) { + memcpy(yuv420_dest+linear_offset, nv12t_src+tiled_offset, 64); + memcpy(yuv420_dest+linear_offset+64, nv12t_src+tiled_offset+2048, 64); + memcpy(yuv420_dest+linear_offset+128, nv12t_src+tiled_offset1, 64); + memcpy(yuv420_dest+linear_offset+192, nv12t_src+tiled_offset1+2048, temp2-192); + } else if (temp2 > 128) { + memcpy(yuv420_dest+linear_offset, nv12t_src+tiled_offset, 64); + memcpy(yuv420_dest+linear_offset+64, nv12t_src+tiled_offset+2048, 64); + memcpy(yuv420_dest+linear_offset+128, nv12t_src+tiled_offset1, temp2-128); + } else if (temp2 > 64) { + memcpy(yuv420_dest+linear_offset, nv12t_src+tiled_offset, 64); + memcpy(yuv420_dest+linear_offset+64, nv12t_src+tiled_offset+2048, temp2-64); + } else { + memcpy(yuv420_dest+linear_offset, nv12t_src+tiled_offset, temp2); + } + } + } else if (temp1 >= 64) { + for (i=top; i<(yuv420_height-buttom); i=i+1) { + j = left; + tiled_offset = tile_4x2_read(yuv420_width, yuv420_height, j, i); + temp2 = ((j+64)>>6)<<6; + temp2 = temp2-j; + linear_offset = temp1*(i-top); + temp4 = j&0x3; + tiled_offset = tiled_offset+temp4; + memcpy(yuv420_dest+linear_offset, nv12t_src+tiled_offset, temp2); + linear_offset = linear_offset+temp2; + j = j+temp2; + if ((j+64) <= temp3) { + tiled_offset = tile_4x2_read(yuv420_width, yuv420_height, j, i); + memcpy(yuv420_dest+linear_offset, nv12t_src+tiled_offset, 64); + linear_offset = linear_offset+64; + j = j+64; + } + if ((j+64) <= temp3) { + tiled_offset = tile_4x2_read(yuv420_width, yuv420_height, j, i); + memcpy(yuv420_dest+linear_offset, nv12t_src+tiled_offset, 64); + linear_offset = linear_offset+64; + j = j+64; + } + if (j < temp3) { + tiled_offset = tile_4x2_read(yuv420_width, yuv420_height, j, i); + temp2 = temp3-j; + memcpy(yuv420_dest+linear_offset, nv12t_src+tiled_offset, temp2); + } + } + } else { + for (i=top; i<(yuv420_height-buttom); i=i+1) { + linear_offset = temp1*(i-top); + for (j=left; j<(yuv420_width-right); j=j+2) { + tiled_offset = tile_4x2_read(yuv420_width, yuv420_height, j, i); + temp4 = j&0x3; + tiled_offset = tiled_offset+temp4; + memcpy(yuv420_dest+linear_offset, nv12t_src+tiled_offset, 2); + linear_offset = linear_offset+2; + } + } + } +} + +/* + * Converts and Deinterleaves tiled data to linear + * Crops left, top, right, buttom + * 1. UV of NV12T to UV of YUV420P + * + * @param yuv420_u_dest + * U plane address of YUV420P[out] + * + * @param yuv420_v_dest + * V plane address of YUV420P[out] + * + * @param nv12t_src + * UV plane address of NV12T[in] + * + * @param yuv420_width + * Width of YUV420[in] + * + * @param yuv420_uv_height + * Height/2 of YUV420[in] + * + * @param left + * Crop size of left + * + * @param top + * Crop size of top + * + * @param right + * Crop size of right + * + * @param buttom + * Crop size of buttom + */ +static void csc_tiled_to_linear_deinterleave_crop( + unsigned char *yuv420_u_dest, + unsigned char *yuv420_v_dest, + unsigned char *nv12t_uv_src, + unsigned int yuv420_width, + unsigned int yuv420_uv_height, + unsigned int left, + unsigned int top, + unsigned int right, + unsigned int buttom) +{ + unsigned int i, j; + unsigned int tiled_offset = 0, tiled_offset1 = 0; + unsigned int linear_offset = 0; + unsigned int temp1 = 0, temp2 = 0, temp3 = 0, temp4 = 0; + + temp3 = yuv420_width-right; + temp1 = temp3-left; + /* real width is greater than or equal 256 */ + if (temp1 >= 256) { + for (i=top; i>8)<<8; + temp3 = temp3>>6; + temp4 = i>>5; + if (temp4 & 0x1) { + /* odd fomula: 2+x+(x>>2)<<2+x_block_num*(y-1) */ + tiled_offset = temp4-1; + temp1 = ((yuv420_width+127)>>7)<<7; + tiled_offset = tiled_offset*(temp1>>6); + tiled_offset = tiled_offset+temp3; + tiled_offset = tiled_offset+2; + temp1 = (temp3>>2)<<2; + tiled_offset = tiled_offset+temp1; + tiled_offset = tiled_offset<<11; + tiled_offset1 = tiled_offset+2048*2; + temp4 = 8; + } else { + temp2 = ((yuv420_uv_height+31)>>5)<<5; + if ((i+32)>2)<<2+x_block_num*y */ + temp1 = temp3+2; + temp1 = (temp1>>2)<<2; + tiled_offset = temp3+temp1; + temp1 = ((yuv420_width+127)>>7)<<7; + tiled_offset = tiled_offset+temp4*(temp1>>6); + tiled_offset = tiled_offset<<11; + tiled_offset1 = tiled_offset+2048*6; + temp4 = 8; + } else { + /* even2 fomula: x+x_block_num*y */ + temp1 = ((yuv420_width+127)>>7)<<7; + tiled_offset = temp4*(temp1>>6); + tiled_offset = tiled_offset+temp3; + tiled_offset = tiled_offset<<11; + tiled_offset1 = tiled_offset+2048*2; + temp4 = 4; + } + } + + temp1 = i&0x1F; + tiled_offset = tiled_offset+64*(temp1); + tiled_offset1 = tiled_offset1+64*(temp1); + temp2 = yuv420_width-left-right; + linear_offset = temp2*(i-top)/2; + temp3 = ((j+256)>>8)<<8; + temp3 = temp3-j; + temp1 = left&0x3F; + if (temp3 > 192) { + csc_deinterleave_memcpy(yuv420_u_dest+linear_offset, yuv420_v_dest+linear_offset, nv12t_uv_src+tiled_offset+temp1, 64-temp1); + csc_deinterleave_memcpy(yuv420_u_dest+linear_offset+(32-temp1/2), + yuv420_v_dest+linear_offset+(32-temp1/2), + nv12t_uv_src+tiled_offset+2048, 64); + csc_deinterleave_memcpy(yuv420_u_dest+linear_offset+(64-temp1/2), + yuv420_v_dest+linear_offset+(64-temp1/2), + nv12t_uv_src+tiled_offset1, 64); + csc_deinterleave_memcpy(yuv420_u_dest+linear_offset+(96-temp1/2), + yuv420_v_dest+linear_offset+(96-temp1/2), + nv12t_uv_src+tiled_offset1+2048, 64); + linear_offset = linear_offset+128-temp1/2; + } else if (temp3 > 128) { + csc_deinterleave_memcpy(yuv420_u_dest+linear_offset, + yuv420_v_dest+linear_offset, + nv12t_uv_src+tiled_offset+2048+temp1, 64-temp1); + csc_deinterleave_memcpy(yuv420_u_dest+linear_offset+(32-temp1/2), + yuv420_v_dest+linear_offset+(32-temp1/2), + nv12t_uv_src+tiled_offset1, 64); + csc_deinterleave_memcpy(yuv420_u_dest+linear_offset+(64-temp1/2), + yuv420_v_dest+linear_offset+(64-temp1/2), + nv12t_uv_src+tiled_offset1+2048, 64); + linear_offset = linear_offset+96-temp1/2; + } else if (temp3 > 64) { + csc_deinterleave_memcpy(yuv420_u_dest+linear_offset, + yuv420_v_dest+linear_offset, + nv12t_uv_src+tiled_offset1+temp1, 64-temp1); + csc_deinterleave_memcpy(yuv420_u_dest+linear_offset+(32-temp1/2), + yuv420_v_dest+linear_offset+(32-temp1/2), + nv12t_uv_src+tiled_offset1+2048, 64); + linear_offset = linear_offset+64-temp1/2; + } else if (temp3 > 0) { + csc_deinterleave_memcpy(yuv420_u_dest+linear_offset, + yuv420_v_dest+linear_offset, + nv12t_uv_src+tiled_offset1+2048+temp1, 64-temp1); + linear_offset = linear_offset+32-temp1/2; + } + + tiled_offset = tiled_offset+temp4*2048; + j = (left>>8)<<8; + j = j + 256; + temp2 = yuv420_width-right-256; + for (; j<=temp2; j=j+256) { + csc_deinterleave_memcpy(yuv420_u_dest+linear_offset, + yuv420_v_dest+linear_offset, + nv12t_uv_src+tiled_offset, 64); + tiled_offset1 = tiled_offset1+temp4*2048; + csc_deinterleave_memcpy(yuv420_u_dest+linear_offset+32, + yuv420_v_dest+linear_offset+32, + nv12t_uv_src+tiled_offset+2048, 64); + csc_deinterleave_memcpy(yuv420_u_dest+linear_offset+64, + yuv420_v_dest+linear_offset+64, + nv12t_uv_src+tiled_offset1, 64); + tiled_offset = tiled_offset+temp4*2048; + csc_deinterleave_memcpy(yuv420_u_dest+linear_offset+96, + yuv420_v_dest+linear_offset+96, + nv12t_uv_src+tiled_offset1+2048, 64); + linear_offset = linear_offset+128; + } + + tiled_offset1 = tiled_offset1+temp4*2048; + temp2 = yuv420_width-right-j; + if (temp2 > 192) { + csc_deinterleave_memcpy(yuv420_u_dest+linear_offset, + yuv420_v_dest+linear_offset, + nv12t_uv_src+tiled_offset, 64); + csc_deinterleave_memcpy(yuv420_u_dest+linear_offset+32, + yuv420_v_dest+linear_offset+32, + nv12t_uv_src+tiled_offset+2048, 64); + csc_deinterleave_memcpy(yuv420_u_dest+linear_offset+64, + yuv420_v_dest+linear_offset+64, + nv12t_uv_src+tiled_offset1, 64); + csc_deinterleave_memcpy(yuv420_u_dest+linear_offset+96, + yuv420_v_dest+linear_offset+96, + nv12t_uv_src+tiled_offset1+2048, temp2-192); + } else if (temp2 > 128) { + csc_deinterleave_memcpy(yuv420_u_dest+linear_offset, + yuv420_v_dest+linear_offset, + nv12t_uv_src+tiled_offset, 64); + csc_deinterleave_memcpy(yuv420_u_dest+linear_offset+32, + yuv420_v_dest+linear_offset+32, + nv12t_uv_src+tiled_offset+2048, 64); + csc_deinterleave_memcpy(yuv420_u_dest+linear_offset+64, + yuv420_v_dest+linear_offset+64, + nv12t_uv_src+tiled_offset1, temp2-128); + } else if (temp2 > 64) { + csc_deinterleave_memcpy(yuv420_u_dest+linear_offset, + yuv420_v_dest+linear_offset, + nv12t_uv_src+tiled_offset, 64); + csc_deinterleave_memcpy(yuv420_u_dest+linear_offset+32, + yuv420_v_dest+linear_offset+32, + nv12t_uv_src+tiled_offset+2048, temp2-64); + } else { + csc_deinterleave_memcpy(yuv420_u_dest+linear_offset, + yuv420_v_dest+linear_offset, + nv12t_uv_src+tiled_offset, temp2); + } + } + } else if (temp1 >= 64) { + for (i=top; i<(yuv420_uv_height-buttom); i=i+1) { + j = left; + tiled_offset = tile_4x2_read(yuv420_width, yuv420_uv_height, j, i); + temp2 = ((j+64)>>6)<<6; + temp2 = temp2-j; + temp3 = yuv420_width-right; + temp4 = temp3-left; + linear_offset = temp4*(i-top)/2; + temp4 = j&0x3; + tiled_offset = tiled_offset+temp4; + csc_deinterleave_memcpy(yuv420_u_dest+linear_offset, + yuv420_v_dest+linear_offset, + nv12t_uv_src+tiled_offset, temp2); + linear_offset = linear_offset+temp2/2; + j = j+temp2; + if ((j+64) <= temp3) { + tiled_offset = tile_4x2_read(yuv420_width, yuv420_uv_height, j, i); + csc_deinterleave_memcpy(yuv420_u_dest+linear_offset, + yuv420_v_dest+linear_offset, + nv12t_uv_src+tiled_offset, 64); + linear_offset = linear_offset+32; + j = j+64; + } + if ((j+64) <= temp3) { + tiled_offset = tile_4x2_read(yuv420_width, yuv420_uv_height, j, i); + csc_deinterleave_memcpy(yuv420_u_dest+linear_offset, + yuv420_v_dest+linear_offset, + nv12t_uv_src+tiled_offset, 64); + linear_offset = linear_offset+32; + j = j+64; + } + if (j < temp3) { + tiled_offset = tile_4x2_read(yuv420_width, yuv420_uv_height, j, i); + temp1 = temp3-j; + csc_deinterleave_memcpy(yuv420_u_dest+linear_offset, + yuv420_v_dest+linear_offset, + nv12t_uv_src+tiled_offset, temp1); + } + } + } else { + for (i=top; i<(yuv420_uv_height-buttom); i=i+1) { + temp3 = yuv420_width-right; + temp4 = temp3-left; + linear_offset = temp4*(i-top)/2; + for (j=left; j<(yuv420_width-right); j=j+2) { + tiled_offset = tile_4x2_read(yuv420_width, yuv420_uv_height, j, i); + temp3 = j&0x3; + tiled_offset = tiled_offset+temp3; + csc_deinterleave_memcpy(yuv420_u_dest+linear_offset, + yuv420_v_dest+linear_offset, + nv12t_uv_src+tiled_offset, 2); + linear_offset = linear_offset+1; + } + } + } +} + +/* + * Converts linear data to tiled + * Crops left, top, right, buttom + * 1. Y of YUV420P to Y of NV12T + * 2. Y of YUV420S to Y of NV12T + * 3. UV of YUV420S to UV of NV12T + * + * @param nv12t_dest + * Y or UV plane address of NV12T[out] + * + * @param yuv420_src + * Y or UV plane address of YUV420P(S)[in] + * + * @param yuv420_width + * Width of YUV420[in] + * + * @param yuv420_height + * Y: Height of YUV420, UV: Height/2 of YUV420[in] + * + * @param left + * Crop size of left + * + * @param top + * Crop size of top + * + * @param right + * Crop size of right + * + * @param buttom + * Crop size of buttom + */ +static void csc_linear_to_tiled_crop( + unsigned char *nv12t_dest, + unsigned char *yuv420_src, + unsigned int yuv420_width, + unsigned int yuv420_height, + unsigned int left, + unsigned int top, + unsigned int right, + unsigned int buttom) +{ + unsigned int i, j; + unsigned int tiled_x_index = 0, tiled_y_index = 0; + unsigned int aligned_x_size = 0, aligned_y_size = 0; + unsigned int tiled_offset = 0; + unsigned int temp1 = 0, temp2 = 0; + + aligned_y_size = ((yuv420_height-top-buttom)>>5)<<5; + aligned_x_size = ((yuv420_width-left-right)>>6)<<6; + + for (i=0; i>6; + tiled_y_index = i>>5; + if (tiled_y_index & 0x1) { + /* odd fomula: 2+x+(x>>2)<<2+x_block_num*(y-1) */ + tiled_offset = tiled_y_index-1; + temp1 = (((yuv420_width-left-right)+127)>>7)<<7; + tiled_offset = tiled_offset*(temp1>>6); + tiled_offset = tiled_offset+tiled_x_index; + tiled_offset = tiled_offset+2; + temp1 = (tiled_x_index>>2)<<2; + tiled_offset = tiled_offset+temp1; + tiled_offset = tiled_offset<<11; + } else { + temp2 = (((yuv420_height-top-buttom)+31)>>5)<<5; + if ((i+32)>2)<<2+x_block_num*y */ + temp1 = tiled_x_index+2; + temp1 = (temp1>>2)<<2; + tiled_offset = tiled_x_index+temp1; + temp1 = (((yuv420_width-left-right)+127)>>7)<<7; + tiled_offset = tiled_offset+tiled_y_index*(temp1>>6); + tiled_offset = tiled_offset<<11; + } else { + /* even2 fomula: x+x_block_num*y */ + temp1 = (((yuv420_width-left-right)+127)>>7)<<7; + tiled_offset = tiled_y_index*(temp1>>6); + tiled_offset = tiled_offset+tiled_x_index; + tiled_offset = tiled_offset<<11; + } + } + + memcpy(nv12t_dest+tiled_offset, yuv420_src+left+j+yuv420_width*(i+top), 64); + memcpy(nv12t_dest+tiled_offset+64*1, yuv420_src+left+j+yuv420_width*(i+top+1), 64); + memcpy(nv12t_dest+tiled_offset+64*2, yuv420_src+left+j+yuv420_width*(i+top+2), 64); + memcpy(nv12t_dest+tiled_offset+64*3, yuv420_src+left+j+yuv420_width*(i+top+3), 64); + memcpy(nv12t_dest+tiled_offset+64*4, yuv420_src+left+j+yuv420_width*(i+top+4), 64); + memcpy(nv12t_dest+tiled_offset+64*5, yuv420_src+left+j+yuv420_width*(i+top+5), 64); + memcpy(nv12t_dest+tiled_offset+64*6, yuv420_src+left+j+yuv420_width*(i+top+6), 64); + memcpy(nv12t_dest+tiled_offset+64*7, yuv420_src+left+j+yuv420_width*(i+top+7), 64); + memcpy(nv12t_dest+tiled_offset+64*8, yuv420_src+left+j+yuv420_width*(i+top+8), 64); + memcpy(nv12t_dest+tiled_offset+64*9, yuv420_src+left+j+yuv420_width*(i+top+9), 64); + memcpy(nv12t_dest+tiled_offset+64*10, yuv420_src+left+j+yuv420_width*(i+top+10), 64); + memcpy(nv12t_dest+tiled_offset+64*11, yuv420_src+left+j+yuv420_width*(i+top+11), 64); + memcpy(nv12t_dest+tiled_offset+64*12, yuv420_src+left+j+yuv420_width*(i+top+12), 64); + memcpy(nv12t_dest+tiled_offset+64*13, yuv420_src+left+j+yuv420_width*(i+top+13), 64); + memcpy(nv12t_dest+tiled_offset+64*14, yuv420_src+left+j+yuv420_width*(i+top+14), 64); + memcpy(nv12t_dest+tiled_offset+64*15, yuv420_src+left+j+yuv420_width*(i+top+15), 64); + memcpy(nv12t_dest+tiled_offset+64*16, yuv420_src+left+j+yuv420_width*(i+top+16), 64); + memcpy(nv12t_dest+tiled_offset+64*17, yuv420_src+left+j+yuv420_width*(i+top+17), 64); + memcpy(nv12t_dest+tiled_offset+64*18, yuv420_src+left+j+yuv420_width*(i+top+18), 64); + memcpy(nv12t_dest+tiled_offset+64*19, yuv420_src+left+j+yuv420_width*(i+top+19), 64); + memcpy(nv12t_dest+tiled_offset+64*20, yuv420_src+left+j+yuv420_width*(i+top+20), 64); + memcpy(nv12t_dest+tiled_offset+64*21, yuv420_src+left+j+yuv420_width*(i+top+21), 64); + memcpy(nv12t_dest+tiled_offset+64*22, yuv420_src+left+j+yuv420_width*(i+top+22), 64); + memcpy(nv12t_dest+tiled_offset+64*23, yuv420_src+left+j+yuv420_width*(i+top+23), 64); + memcpy(nv12t_dest+tiled_offset+64*24, yuv420_src+left+j+yuv420_width*(i+top+24), 64); + memcpy(nv12t_dest+tiled_offset+64*25, yuv420_src+left+j+yuv420_width*(i+top+25), 64); + memcpy(nv12t_dest+tiled_offset+64*26, yuv420_src+left+j+yuv420_width*(i+top+26), 64); + memcpy(nv12t_dest+tiled_offset+64*27, yuv420_src+left+j+yuv420_width*(i+top+27), 64); + memcpy(nv12t_dest+tiled_offset+64*28, yuv420_src+left+j+yuv420_width*(i+top+28), 64); + memcpy(nv12t_dest+tiled_offset+64*29, yuv420_src+left+j+yuv420_width*(i+top+29), 64); + memcpy(nv12t_dest+tiled_offset+64*30, yuv420_src+left+j+yuv420_width*(i+top+30), 64); + memcpy(nv12t_dest+tiled_offset+64*31, yuv420_src+left+j+yuv420_width*(i+top+31), 64); + } + } + + for (i=aligned_y_size; i<(yuv420_height-top-buttom); i=i+2) { + for (j=0; j>6; + tiled_y_index = i>>5; + if (tiled_y_index & 0x1) { + /* odd fomula: 2+x+(x>>2)<<2+x_block_num*(y-1) */ + tiled_offset = tiled_y_index-1; + temp1 = (((yuv420_width-left-right)+127)>>7)<<7; + tiled_offset = tiled_offset*(temp1>>6); + tiled_offset = tiled_offset+tiled_x_index; + tiled_offset = tiled_offset+2; + temp1 = (tiled_x_index>>2)<<2; + tiled_offset = tiled_offset+temp1; + tiled_offset = tiled_offset<<11; + } else { + temp2 = (((yuv420_height-top-buttom)+31)>>5)<<5; + if ((i+32)>2)<<2+x_block_num*y */ + temp1 = tiled_x_index+2; + temp1 = (temp1>>2)<<2; + tiled_offset = tiled_x_index+temp1; + temp1 = (((yuv420_width-left-right)+127)>>7)<<7; + tiled_offset = tiled_offset+tiled_y_index*(temp1>>6); + tiled_offset = tiled_offset<<11; + } else { + /* even2 fomula: x+x_block_num*y */ + temp1 = (((yuv420_width-left-right)+127)>>7)<<7; + tiled_offset = tiled_y_index*(temp1>>6); + tiled_offset = tiled_offset+tiled_x_index; + tiled_offset = tiled_offset<<11; + } + } + + temp1 = i&0x1F; + memcpy(nv12t_dest+tiled_offset+64*(temp1), yuv420_src+left+j+yuv420_width*(i+top), 64); + memcpy(nv12t_dest+tiled_offset+64*(temp1+1), yuv420_src+left+j+yuv420_width*(i+top+1), 64); + } + } + + for (i=0; i<(yuv420_height-top-buttom); i=i+2) { + for (j=aligned_x_size; j<(yuv420_width-left-right); j=j+2) { + tiled_offset = 0; + tiled_x_index = j>>6; + tiled_y_index = i>>5; + if (tiled_y_index & 0x1) { + /* odd fomula: 2+x+(x>>2)<<2+x_block_num*(y-1) */ + tiled_offset = tiled_y_index-1; + temp1 = (((yuv420_width-left-right)+127)>>7)<<7; + tiled_offset = tiled_offset*(temp1>>6); + tiled_offset = tiled_offset+tiled_x_index; + tiled_offset = tiled_offset+2; + temp1 = (tiled_x_index>>2)<<2; + tiled_offset = tiled_offset+temp1; + tiled_offset = tiled_offset<<11; + } else { + temp2 = (((yuv420_height-top-buttom)+31)>>5)<<5; + if ((i+32)>2)<<2+x_block_num*y */ + temp1 = tiled_x_index+2; + temp1 = (temp1>>2)<<2; + tiled_offset = tiled_x_index+temp1; + temp1 = (((yuv420_width-left-right)+127)>>7)<<7; + tiled_offset = tiled_offset+tiled_y_index*(temp1>>6); + tiled_offset = tiled_offset<<11; + } else { + /* even2 fomula: x+x_block_num*y */ + temp1 = (((yuv420_width-left-right)+127)>>7)<<7; + tiled_offset = tiled_y_index*(temp1>>6); + tiled_offset = tiled_offset+tiled_x_index; + tiled_offset = tiled_offset<<11; + } + } + + temp1 = i&0x1F; + temp2 = j&0x3F; + memcpy(nv12t_dest+tiled_offset+temp2+64*(temp1), yuv420_src+left+j+yuv420_width*(i+top), 2); + memcpy(nv12t_dest+tiled_offset+temp2+64*(temp1+1), yuv420_src+left+j+yuv420_width*(i+top+1), 2); + } + } + +} + +/* + * Converts and Interleaves linear to tiled + * Crops left, top, right, buttom + * 1. UV of YUV420P to UV of NV12T + * + * @param nv12t_uv_dest + * UV plane address of NV12T[out] + * + * @param yuv420p_u_src + * U plane address of YUV420P[in] + * + * @param yuv420p_v_src + * V plane address of YUV420P[in] + * + * @param yuv420_width + * Width of YUV420[in] + * + * @param yuv420_uv_height + * Height/2 of YUV420[in] + * + * @param left + * Crop size of left + * + * @param top + * Crop size of top + * + * @param right + * Crop size of right + * + * @param buttom + * Crop size of buttom + */ +static void csc_linear_to_tiled_interleave_crop( + unsigned char *nv12t_uv_dest, + unsigned char *yuv420_u_src, + unsigned char *yuv420_v_src, + unsigned int yuv420_width, + unsigned int yuv420_height, + unsigned int left, + unsigned int top, + unsigned int right, + unsigned int buttom) +{ + unsigned int i, j; + unsigned int tiled_x_index = 0, tiled_y_index = 0; + unsigned int aligned_x_size = 0, aligned_y_size = 0; + unsigned int tiled_offset = 0; + unsigned int temp1 = 0, temp2 = 0; + + aligned_y_size = ((yuv420_height-top-buttom)>>5)<<5; + aligned_x_size = ((yuv420_width-left-right)>>6)<<6; + + for (i=0; i>6; + tiled_y_index = i>>5; + if (tiled_y_index & 0x1) { + /* odd fomula: 2+x+(x>>2)<<2+x_block_num*(y-1) */ + tiled_offset = tiled_y_index-1; + temp1 = (((yuv420_width-left-right)+127)>>7)<<7; + tiled_offset = tiled_offset*(temp1>>6); + tiled_offset = tiled_offset+tiled_x_index; + tiled_offset = tiled_offset+2; + temp1 = (tiled_x_index>>2)<<2; + tiled_offset = tiled_offset+temp1; + tiled_offset = tiled_offset<<11; + } else { + temp2 = (((yuv420_height-top-buttom)+31)>>5)<<5; + if ((i+32)>2)<<2+x_block_num*y */ + temp1 = tiled_x_index+2; + temp1 = (temp1>>2)<<2; + tiled_offset = tiled_x_index+temp1; + temp1 = (((yuv420_width-left-right)+127)>>7)<<7; + tiled_offset = tiled_offset+tiled_y_index*(temp1>>6); + tiled_offset = tiled_offset<<11; + } else { + /* even2 fomula: x+x_block_num*y */ + temp1 = (((yuv420_width-left-right)+127)>>7)<<7; + tiled_offset = tiled_y_index*(temp1>>6); + tiled_offset = tiled_offset+tiled_x_index; + tiled_offset = tiled_offset<<11; + } + } + + csc_interleave_memcpy(nv12t_uv_dest+tiled_offset, + yuv420_u_src+left/2+j/2+yuv420_width/2*(i+top), + yuv420_v_src+left/2+j/2+yuv420_width/2*(i+top), 32); + csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*1, + yuv420_u_src+left/2+j/2+yuv420_width/2*(i+top+1), + yuv420_v_src+left/2+j/2+yuv420_width/2*(i+top+1), 32); + csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*2, + yuv420_u_src+left/2+j/2+yuv420_width/2*(i+top+2), + yuv420_v_src+left/2+j/2+yuv420_width/2*(i+top+2), 32); + csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*3, + yuv420_u_src+left/2+j/2+yuv420_width/2*(i+top+3), + yuv420_v_src+left/2+j/2+yuv420_width/2*(i+top+3), 32); + csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*4, + yuv420_u_src+left/2+j/2+yuv420_width/2*(i+top+4), + yuv420_v_src+left/2+j/2+yuv420_width/2*(i+top+4), 32); + csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*5, + yuv420_u_src+left/2+j/2+yuv420_width/2*(i+top+5), + yuv420_v_src+left/2+j/2+yuv420_width/2*(i+top+5), 32); + csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*6, + yuv420_u_src+left/2+j/2+yuv420_width/2*(i+top+6), + yuv420_v_src+left/2+j/2+yuv420_width/2*(i+top+6), 32); + csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*7, + yuv420_u_src+left/2+j/2+yuv420_width/2*(i+top+7), + yuv420_v_src+left/2+j/2+yuv420_width/2*(i+top+7), 32); + csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*8, + yuv420_u_src+left/2+j/2+yuv420_width/2*(i+top+8), + yuv420_v_src+left/2+j/2+yuv420_width/2*(i+top+8), 32); + csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*9, + yuv420_u_src+left/2+j/2+yuv420_width/2*(i+top+9), + yuv420_v_src+left/2+j/2+yuv420_width/2*(i+top+9), 32); + csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*10, + yuv420_u_src+left/2+j/2+yuv420_width/2*(i+top+10), + yuv420_v_src+left/2+j/2+yuv420_width/2*(i+top+10), 32); + csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*11, + yuv420_u_src+left/2+j/2+yuv420_width/2*(i+top+11), + yuv420_v_src+left/2+j/2+yuv420_width/2*(i+top+11), 32); + csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*12, + yuv420_u_src+left/2+j/2+yuv420_width/2*(i+top+12), + yuv420_v_src+left/2+j/2+yuv420_width/2*(i+top+12), 32); + csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*13, + yuv420_u_src+left/2+j/2+yuv420_width/2*(i+top+13), + yuv420_v_src+left/2+j/2+yuv420_width/2*(i+top+13), 32); + csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*14, + yuv420_u_src+left/2+j/2+yuv420_width/2*(i+top+14), + yuv420_v_src+left/2+j/2+yuv420_width/2*(i+top+14), 32); + csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*15, + yuv420_u_src+left/2+j/2+yuv420_width/2*(i+top+15), + yuv420_v_src+left/2+j/2+yuv420_width/2*(i+top+15), 32); + csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*16, + yuv420_u_src+left/2+j/2+yuv420_width/2*(i+top+16), + yuv420_v_src+left/2+j/2+yuv420_width/2*(i+top+16), 32); + csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*17, + yuv420_u_src+left/2+j/2+yuv420_width/2*(i+top+17), + yuv420_v_src+left/2+j/2+yuv420_width/2*(i+top+17), 32); + csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*18, + yuv420_u_src+left/2+j/2+yuv420_width/2*(i+top+18), + yuv420_v_src+left/2+j/2+yuv420_width/2*(i+top+18), 32); + csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*19, + yuv420_u_src+left/2+j/2+yuv420_width/2*(i+top+19), + yuv420_v_src+left/2+j/2+yuv420_width/2*(i+top+19), 32); + csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*20, + yuv420_u_src+left/2+j/2+yuv420_width/2*(i+top+20), + yuv420_v_src+left/2+j/2+yuv420_width/2*(i+top+20), 32); + csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*21, + yuv420_u_src+left/2+j/2+yuv420_width/2*(i+top+21), + yuv420_v_src+left/2+j/2+yuv420_width/2*(i+top+21), 32); + csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*22, + yuv420_u_src+left/2+j/2+yuv420_width/2*(i+top+22), + yuv420_v_src+left/2+j/2+yuv420_width/2*(i+top+22), 32); + csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*23, + yuv420_u_src+left/2+j/2+yuv420_width/2*(i+top+23), + yuv420_v_src+left/2+j/2+yuv420_width/2*(i+top+23), 32); + csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*24, + yuv420_u_src+left/2+j/2+yuv420_width/2*(i+top+24), + yuv420_v_src+left/2+j/2+yuv420_width/2*(i+top+24), 32); + csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*25, + yuv420_u_src+left/2+j/2+yuv420_width/2*(i+top+25), + yuv420_v_src+left/2+j/2+yuv420_width/2*(i+top+25), 32); + csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*26, + yuv420_u_src+left/2+j/2+yuv420_width/2*(i+top+26), + yuv420_v_src+left/2+j/2+yuv420_width/2*(i+top+26), 32); + csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*27, + yuv420_u_src+left/2+j/2+yuv420_width/2*(i+top+27), + yuv420_v_src+left/2+j/2+yuv420_width/2*(i+top+27), 32); + csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*28, + yuv420_u_src+left/2+j/2+yuv420_width/2*(i+top+28), + yuv420_v_src+left/2+j/2+yuv420_width/2*(i+top+28), 32); + csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*29, + yuv420_u_src+left/2+j/2+yuv420_width/2*(i+top+29), + yuv420_v_src+left/2+j/2+yuv420_width/2*(i+top+29), 32); + csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*30, + yuv420_u_src+left/2+j/2+yuv420_width/2*(i+top+30), + yuv420_v_src+left/2+j/2+yuv420_width/2*(i+top+30), 32); + csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*31, + yuv420_u_src+left/2+j/2+yuv420_width/2*(i+top+31), + yuv420_v_src+left/2+j/2+yuv420_width/2*(i+top+31), 32); + + } + } + + for (i=aligned_y_size; i<(yuv420_height-top-buttom); i=i+1) { + for (j=0; j>6; + tiled_y_index = i>>5; + if (tiled_y_index & 0x1) { + /* odd fomula: 2+x+(x>>2)<<2+x_block_num*(y-1) */ + tiled_offset = tiled_y_index-1; + temp1 = (((yuv420_width-left-right)+127)>>7)<<7; + tiled_offset = tiled_offset*(temp1>>6); + tiled_offset = tiled_offset+tiled_x_index; + tiled_offset = tiled_offset+2; + temp1 = (tiled_x_index>>2)<<2; + tiled_offset = tiled_offset+temp1; + tiled_offset = tiled_offset<<11; + } else { + temp2 = (((yuv420_height-top-buttom)+31)>>5)<<5; + if ((i+32)>2)<<2+x_block_num*y */ + temp1 = tiled_x_index+2; + temp1 = (temp1>>2)<<2; + tiled_offset = tiled_x_index+temp1; + temp1 = (((yuv420_width-left-right)+127)>>7)<<7; + tiled_offset = tiled_offset+tiled_y_index*(temp1>>6); + tiled_offset = tiled_offset<<11; + } else { + /* even2 fomula: x+x_block_num*y */ + temp1 = (((yuv420_width-left-right)+127)>>7)<<7; + tiled_offset = tiled_y_index*(temp1>>6); + tiled_offset = tiled_offset+tiled_x_index; + tiled_offset = tiled_offset<<11; + } + } + temp1 = i&0x1F; + csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*(temp1), + yuv420_u_src+left/2+j/2+yuv420_width/2*(i+top), + yuv420_v_src+left/2+j/2+yuv420_width/2*(i+top), 32); + } + } + + for (i=0; i<(yuv420_height-top-buttom); i=i+1) { + for (j=aligned_x_size; j<(yuv420_width-left-right); j=j+2) { + tiled_offset = 0; + tiled_x_index = j>>6; + tiled_y_index = i>>5; + if (tiled_y_index & 0x1) { + /* odd fomula: 2+x+(x>>2)<<2+x_block_num*(y-1) */ + tiled_offset = tiled_y_index-1; + temp1 = (((yuv420_width-left-right)+127)>>7)<<7; + tiled_offset = tiled_offset*(temp1>>6); + tiled_offset = tiled_offset+tiled_x_index; + tiled_offset = tiled_offset+2; + temp1 = (tiled_x_index>>2)<<2; + tiled_offset = tiled_offset+temp1; + tiled_offset = tiled_offset<<11; + } else { + temp2 = (((yuv420_height-top-buttom)+31)>>5)<<5; + if ((i+32)>2)<<2+x_block_num*y */ + temp1 = tiled_x_index+2; + temp1 = (temp1>>2)<<2; + tiled_offset = tiled_x_index+temp1; + temp1 = (((yuv420_width-left-right)+127)>>7)<<7; + tiled_offset = tiled_offset+tiled_y_index*(temp1>>6); + tiled_offset = tiled_offset<<11; + } else { + /* even2 fomula: x+x_block_num*y */ + temp1 = (((yuv420_width-left-right)+127)>>7)<<7; + tiled_offset = tiled_y_index*(temp1>>6); + tiled_offset = tiled_offset+tiled_x_index; + tiled_offset = tiled_offset<<11; + } + } + temp1 = i&0x1F; + temp2 = j&0x3F; + csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+temp2+64*(temp1), + yuv420_u_src+left/2+j/2+yuv420_width/2*(i+top), + yuv420_v_src+left/2+j/2+yuv420_width/2*(i+top), 1); + } + } + +} + + +/* + * Converts tiled data to linear + * Crops left, top, right, buttom + * 1. Y of NV12T to Y of YUV420P + * 2. Y of NV12T to Y of YUV420S + * 3. UV of NV12T to UV of YUV420S + * + * @param yuv420_dest + * Y or UV plane address of YUV420[out] + * + * @param nv12t_src + * Y or UV plane address of NV12T[in] + * + * @param yuv420_width + * Width of YUV420[in] + * + * @param yuv420_height + * Y: Height of YUV420, UV: Height/2 of YUV420[in] + * + * @param left + * Crop size of left + * + * @param top + * Crop size of top + * + * @param right + * Crop size of right + * + * @param buttom + * Crop size of buttom + */ +void csc_tiled_to_linear_crop_neon( + unsigned char *yuv420_dest, + unsigned char *nv12t_src, + unsigned int yuv420_width, + unsigned int yuv420_height, + unsigned int left, + unsigned int top, + unsigned int right, + unsigned int buttom); + +/* + * Converts and Deinterleaves tiled data to linear + * Crops left, top, right, buttom + * 1. UV of NV12T to UV of YUV420P + * + * @param yuv420_u_dest + * U plane address of YUV420P[out] + * + * @param yuv420_v_dest + * V plane address of YUV420P[out] + * + * @param nv12t_src + * UV plane address of NV12T[in] + * + * @param yuv420_width + * Width of YUV420[in] + * + * @param yuv420_uv_height + * Height/2 of YUV420[in] + * + * @param left + * Crop size of left + * + * @param top + * Crop size of top + * + * @param right + * Crop size of right + * + * @param buttom + * Crop size of buttom + */ +void csc_tiled_to_linear_deinterleave_crop_neon( + unsigned char *yuv420_u_dest, + unsigned char *yuv420_v_dest, + unsigned char *nv12t_uv_src, + unsigned int yuv420_width, + unsigned int yuv420_uv_height, + unsigned int left, + unsigned int top, + unsigned int right, + unsigned int buttom); + +/* + * Converts linear data to tiled + * Crops left, top, right, buttom + * 1. Y of YUV420P to Y of NV12T + * 2. Y of YUV420S to Y of NV12T + * 3. UV of YUV420S to UV of NV12T + * + * @param nv12t_dest + * Y or UV plane address of NV12T[out] + * + * @param yuv420_src + * Y or UV plane address of YUV420P(S)[in] + * + * @param yuv420_width + * Width of YUV420[in] + * + * @param yuv420_height + * Y: Height of YUV420, UV: Height/2 of YUV420[in] + * + * @param left + * Crop size of left + * + * @param top + * Crop size of top + * + * @param right + * Crop size of right + * + * @param buttom + * Crop size of buttom + */ +void csc_linear_to_tiled_crop_neon( + unsigned char *nv12t_dest, + unsigned char *yuv420_src, + unsigned int yuv420_width, + unsigned int yuv420_height, + unsigned int left, + unsigned int top, + unsigned int right, + unsigned int buttom); + +/* + * Converts and Interleaves linear to tiled + * Crops left, top, right, buttom + * 1. UV of YUV420P to UV of NV12T + * + * @param nv12t_uv_dest + * UV plane address of NV12T[out] + * + * @param yuv420p_u_src + * U plane address of YUV420P[in] + * + * @param yuv420p_v_src + * V plane address of YUV420P[in] + * + * @param yuv420_width + * Width of YUV420[in] + * + * @param yuv420_uv_height + * Height/2 of YUV420[in] + * + * @param left + * Crop size of left + * + * @param top + * Crop size of top + * + * @param right + * Crop size of right + * + * @param buttom + * Crop size of buttom + */ +void csc_linear_to_tiled_interleave_crop_neon( + unsigned char *nv12t_uv_dest, + unsigned char *yuv420_u_src, + unsigned char *yuv420_v_src, + unsigned int yuv420_width, + unsigned int yuv420_height, + unsigned int left, + unsigned int top, + unsigned int right, + unsigned int buttom); + +/* + * Converts tiled data to linear. + * 1. y of nv12t to y of yuv420p + * 2. y of nv12t to y of yuv420s + * + * @param dst + * y address of yuv420[out] + * + * @param src + * y address of nv12t[in] + * + * @param yuv420_width + * real width of yuv420[in] + * it should be even + * + * @param yuv420_height + * real height of yuv420[in] + * it should be even. + * + */ +void csc_tiled_to_linear_y( + unsigned char *y_dst, + unsigned char *y_src, + unsigned int width, + unsigned int height) +{ + csc_tiled_to_linear_crop(y_dst, y_src, width, height, 0, 0, 0, 0); +} + +/* + * Converts tiled data to linear + * 1. uv of nv12t to y of yuv420s + * + * @param dst + * uv address of yuv420s[out] + * + * @param src + * uv address of nv12t[in] + * + * @param yuv420_width + * real width of yuv420s[in] + * + * @param yuv420_height + * real height of yuv420s[in] + * + */ +void csc_tiled_to_linear_uv( + unsigned char *uv_dst, + unsigned char *uv_src, + unsigned int width, + unsigned int height) +{ + csc_tiled_to_linear_crop(uv_dst, uv_src, width, height, 0, 0, 0, 0); +} + +/* + * Converts tiled data to linear + * 1. uv of nt12t to uv of yuv420p + * + * @param u_dst + * u address of yuv420p[out] + * + * @param v_dst + * v address of yuv420p[out] + * + * @param uv_src + * uv address of nt12t[in] + * + * @param yuv420_width + * real width of yuv420p[in] + * + * @param yuv420_height + * real height of yuv420p[in] + */ +void csc_tiled_to_linear_uv_deinterleave( + unsigned char *u_dst, + unsigned char *v_dst, + unsigned char *uv_src, + unsigned int width, + unsigned int height) +{ + csc_tiled_to_linear_deinterleave_crop(u_dst, v_dst, uv_src, width, height, + 0, 0, 0, 0); +} + +/* + * Converts linear data to tiled + * 1. y of yuv420 to y of nv12t + * + * @param dst + * y address of nv12t[out] + * + * @param src + * y address of yuv420[in] + * + * @param yuv420_width + * real width of yuv420[in] + * it should be even + * + * @param yuv420_height + * real height of yuv420[in] + * it should be even. + * + */ +void csc_linear_to_tiled_y( + unsigned char *y_dst, + unsigned char *y_src, + unsigned int width, + unsigned int height) +{ + csc_linear_to_tiled_crop(y_dst, y_src, width, height, 0, 0, 0, 0); +} + +/* + * Converts and interleaves linear data to tiled + * 1. uv of nv12t to uv of yuv420 + * + * @param dst + * uv address of nv12t[out] + * + * @param src + * u address of yuv420[in] + * + * @param src + * v address of yuv420[in] + * + * @param yuv420_width + * real width of yuv420[in] + * + * @param yuv420_height + * real height of yuv420[in] + * + */ +void csc_linear_to_tiled_uv( + unsigned char *uv_dst, + unsigned char *u_src, + unsigned char *v_src, + unsigned int width, + unsigned int height) +{ + csc_linear_to_tiled_interleave_crop(uv_dst, u_src, v_src, width, height, + 0, 0, 0, 0); +} + +/* + * Converts tiled data to linear for mfc 6.x + * 1. Y of NV12T to Y of YUV420P + * 2. Y of NV12T to Y of YUV420S + * + * @param dst + * Y address of YUV420[out] + * + * @param src + * Y address of NV12T[in] + * + * @param yuv420_width + * real width of YUV420[in] + * + * @param yuv420_height + * Y: real height of YUV420[in] + * + */ +void csc_tiled_to_linear_y_neon( + unsigned char *y_dst, + unsigned char *y_src, + unsigned int width, + unsigned int height) +{ + csc_tiled_to_linear_crop_neon(y_dst, y_src, width, height, 0, 0, 0, 0); +} + +/* + * Converts tiled data to linear for mfc 6.x + * 1. UV of NV12T to Y of YUV420S + * + * @param u_dst + * UV plane address of YUV420P[out] + * + * @param nv12t_src + * Y or UV plane address of NV12T[in] + * + * @param yuv420_width + * real width of YUV420[in] + * + * @param yuv420_height + * (real height)/2 of YUV420[in] + */ +void csc_tiled_to_linear_uv_neon( + unsigned char *uv_dst, + unsigned char *uv_src, + unsigned int width, + unsigned int height) +{ + csc_tiled_to_linear_crop_neon(uv_dst, uv_src, width, height, 0, 0, 0, 0); +} + +/* + * Converts tiled data to linear for mfc 6.x + * Deinterleave src to u_dst, v_dst + * 1. UV of NV12T to Y of YUV420P + * + * @param u_dst + * U plane address of YUV420P[out] + * + * @param v_dst + * V plane address of YUV420P[out] + * + * @param nv12t_src + * Y or UV plane address of NV12T[in] + * + * @param yuv420_width + * real width of YUV420[in] + * + * @param yuv420_height + * (real height)/2 of YUV420[in] + */ +void csc_tiled_to_linear_uv_deinterleave_neon( + unsigned char *u_dst, + unsigned char *v_dst, + unsigned char *uv_src, + unsigned int width, + unsigned int height) +{ + csc_tiled_to_linear_deinterleave_crop_neon(u_dst, v_dst, uv_src, width, height, + 0, 0, 0, 0); +} + +/* + * Converts linear data to tiled + * 1. y of yuv420 to y of nv12t + * + * @param dst + * y address of nv12t[out] + * + * @param src + * y address of yuv420[in] + * + * @param yuv420_width + * real width of yuv420[in] + * it should be even + * + * @param yuv420_height + * real height of yuv420[in] + * it should be even. + * + */ +void csc_linear_to_tiled_y_neon( + unsigned char *y_dst, + unsigned char *y_src, + unsigned int width, + unsigned int height) +{ + csc_linear_to_tiled_crop_neon(y_dst, y_src, width, height, 0, 0, 0, 0); +} + +/* + * Converts and interleaves linear data to tiled + * 1. uv of nv12t to uv of yuv420 + * + * @param dst + * uv address of nv12t[out] + * + * @param src + * u address of yuv420[in] + * + * @param src + * v address of yuv420[in] + * + * @param yuv420_width + * real width of yuv420[in] + * + * @param yuv420_height + * real height of yuv420[in] + * + */ +void csc_linear_to_tiled_uv_neon( + unsigned char *uv_dst, + unsigned char *u_src, + unsigned char *v_src, + unsigned int width, + unsigned int height) +{ + csc_linear_to_tiled_interleave_crop_neon(uv_dst, u_src, v_src, + width, height, 0, 0, 0, 0); +} + +/* + * Converts RGB565 to YUV420P + * + * @param y_dst + * Y plane address of YUV420P[out] + * + * @param u_dst + * U plane address of YUV420P[out] + * + * @param v_dst + * V plane address of YUV420P[out] + * + * @param rgb_src + * Address of RGB565[in] + * + * @param width + * Width of RGB565[in] + * + * @param height + * Height of RGB565[in] + */ +void csc_RGB565_to_YUV420P( + unsigned char *y_dst, + unsigned char *u_dst, + unsigned char *v_dst, + unsigned char *rgb_src, + unsigned int width, + unsigned int height) +{ + unsigned int i, j; + unsigned int tmp; + + unsigned int R, G, B; + unsigned int Y, U, V; + + unsigned int offset1 = width * height; + unsigned int offset2 = width/2 * height/2; + + unsigned short int *pSrc = (unsigned short int *)rgb_src; + + unsigned char *pDstY = (unsigned char *)y_dst; + unsigned char *pDstU = (unsigned char *)u_dst; + unsigned char *pDstV = (unsigned char *)v_dst; + + unsigned int yIndex = 0; + unsigned int uIndex = 0; + unsigned int vIndex = 0; + + for (j = 0; j < height; j++) { + for (i = 0; i < width; i++) { + tmp = pSrc[j * width + i]; + + R = (tmp & 0x0000F800) >> 8; + G = (tmp & 0x000007E0) >> 3; + B = (tmp & 0x0000001F); + B = B << 3; + + Y = ((66 * R) + (129 * G) + (25 * B) + 128); + Y = Y >> 8; + Y += 16; + + pDstY[yIndex++] = (unsigned char)Y; + + if ((j % 2) == 0 && (i % 2) == 0) { + U = ((-38 * R) - (74 * G) + (112 * B) + 128); + U = U >> 8; + U += 128; + V = ((112 * R) - (94 * G) - (18 * B) + 128); + V = V >> 8; + V += 128; + + pDstU[uIndex++] = (unsigned char)U; + pDstV[vIndex++] = (unsigned char)V; + } + } + } +} + +/* + * Converts RGB565 to YUV420SP + * + * @param y_dst + * Y plane address of YUV420SP[out] + * + * @param uv_dst + * UV plane address of YUV420SP[out] + * + * @param rgb_src + * Address of RGB565[in] + * + * @param width + * Width of RGB565[in] + * + * @param height + * Height of RGB565[in] + */ +void csc_RGB565_to_YUV420SP( + unsigned char *y_dst, + unsigned char *uv_dst, + unsigned char *rgb_src, + unsigned int width, + unsigned int height) +{ + unsigned int i, j; + unsigned int tmp; + + unsigned int R, G, B; + unsigned int Y, U, V; + + unsigned int offset = width * height; + + unsigned short int *pSrc = (unsigned short int *)rgb_src; + + unsigned char *pDstY = (unsigned char *)y_dst; + unsigned char *pDstUV = (unsigned char *)uv_dst; + + unsigned int yIndex = 0; + unsigned int uvIndex = 0; + + for (j = 0; j < height; j++) { + for (i = 0; i < width; i++) { + tmp = pSrc[j * width + i]; + + R = (tmp & 0x0000F800) >> 11; + R = R * 8; + G = (tmp & 0x000007E0) >> 5; + G = G * 4; + B = (tmp & 0x0000001F); + B = B * 8; + + Y = ((66 * R) + (129 * G) + (25 * B) + 128); + Y = Y >> 8; + Y += 16; + + pDstY[yIndex++] = (unsigned char)Y; + + if ((j % 2) == 0 && (i % 2) == 0) { + U = ((-38 * R) - (74 * G) + (112 * B) + 128); + U = U >> 8; + U += 128; + V = ((112 * R) - (94 * G) - (18 * B) + 128); + V = V >> 8; + V += 128; + + pDstUV[uvIndex++] = (unsigned char)U; + pDstUV[uvIndex++] = (unsigned char)V; + } + } + } +} + +void csc_ARGB8888_to_YUV420SP( + unsigned char *y_dst, + unsigned char *uv_dst, + unsigned char *rgb_src, + unsigned int width, + unsigned int height) +{ + unsigned int i, j; + unsigned int tmp; + + unsigned int R, G, B; + unsigned int Y, U, V; + + unsigned int offset = width * height; + + unsigned int *pSrc = (unsigned int *)rgb_src; + + unsigned char *pDstY = (unsigned char *)y_dst; + unsigned char *pDstUV = (unsigned char *)uv_dst; + + unsigned int yIndex = 0; + unsigned int uvIndex = 0; + + for (j = 0; j < height; j++) { + for (i = 0; i < width; i++) { + tmp = pSrc[j * width + i]; + + R = (tmp & 0x00FF0000) >> 16; + G = (tmp & 0x0000FF00) >> 8; + B = (tmp & 0x000000FF); + + Y = ((66 * R) + (129 * G) + (25 * B) + 128); + Y = Y >> 8; + Y += 16; + + pDstY[yIndex++] = (unsigned char)Y; + + if ((j % 2) == 0 && (i % 2) == 0) { + U = ((-38 * R) - (74 * G) + (112 * B) + 128); + U = U >> 8; + U += 128; + V = ((112 * R) - (94 * G) - (18 * B) + 128); + V = V >> 8; + V += 128; + + pDstUV[uvIndex++] = (unsigned char)U; + pDstUV[uvIndex++] = (unsigned char)V; + } + } + } +} \ No newline at end of file diff --git a/exynos4/hal/include/swconverter.h b/exynos/multimedia/utils/csc/exynos4/color_space_convertor.h similarity index 88% rename from exynos4/hal/include/swconverter.h rename to exynos/multimedia/utils/csc/exynos4/color_space_convertor.h index eb2eae3..92c0a6d 100644 --- a/exynos4/hal/include/swconverter.h +++ b/exynos/multimedia/utils/csc/exynos4/color_space_convertor.h @@ -1,6 +1,6 @@ /* * - * Copyright 2012 Samsung Electronics S.LSI Co. LTD + * Copyright 2010 Samsung Electronics S.LSI Co. LTD * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,7 +16,7 @@ */ /* - * @file swconverter.h + * @file color_space_convertor.h * @brief SEC_OMX specific define. It support MFC 5.x tiled. * NV12T(tiled) layout: * Each element is not pixel. It is 64x32 pixel block. @@ -47,36 +47,16 @@ * @author ShinWon Lee (shinwon.lee@samsung.com) * @version 1.0 * @history - * 2012.02.01 : Create + * 2011.07.01 : Create + * 2011.12.01 : Added csc functions */ -#ifndef SW_CONVERTOR_H_ -#define SW_CONVERTOR_H_ +#ifndef COLOR_SPACE_CONVERTOR_H_ +#define COLOR_SPACE_CONVERTOR_H_ /*--------------------------------------------------------------------------------*/ /* Format Conversion API */ /*--------------------------------------------------------------------------------*/ -/* - * De-interleaves src to dest1, dest2 - * - * @param dest1 - * Address of de-interleaved data[out] - * - * @param dest2 - * Address of de-interleaved data[out] - * - * @param src - * Address of interleaved data[in] - * - * @param src_size - * Size of interleaved data[in] - */ -void csc_deinterleave_memcpy( - unsigned char *dest1, - unsigned char *dest2, - unsigned char *src, - unsigned int src_size); - /* * Interleaves src1, src2 to dest * @@ -92,12 +72,13 @@ void csc_deinterleave_memcpy( * @param src_size * Size of de-interleaved data[in] */ +/* void csc_interleave_memcpy( unsigned char *dest, unsigned char *src1, unsigned char *src2, unsigned int src_size); - +*/ /* C Code */ /* * Converts tiled data to linear @@ -405,35 +386,6 @@ void csc_RGB565_to_YUV420SP( unsigned int width, unsigned int height); -/* - * Converts ARGB8888 to YUV420P - * - * @param y_dst - * Y plane address of YUV420P[out] - * - * @param u_dst - * U plane address of YUV420P[out] - * - * @param v_dst - * V plane address of YUV420P[out] - * - * @param rgb_src - * Address of ARGB8888[in] - * - * @param width - * Width of ARGB8888[in] - * - * @param height - * Height of ARGB8888[in] - */ -void csc_ARGB8888_to_YUV420P( - unsigned char *y_dst, - unsigned char *u_dst, - unsigned char *v_dst, - unsigned char *rgb_src, - unsigned int width, - unsigned int height); - /* * Converts ARGB888 to YUV420SP * @@ -444,13 +396,13 @@ void csc_ARGB8888_to_YUV420P( * UV plane address of YUV420SP[out] * * @param rgb_src - * Address of ARGB8888[in] + * Address of ARGB888[in] * * @param width - * Width of ARGB8888[in] + * Width of ARGB888[in] * * @param height - * Height of ARGB8888[in] + * Height of ARGB888[in] */ void csc_ARGB8888_to_YUV420SP( unsigned char *y_dst, diff --git a/exynos4/multimedia/libs/libcsc/hwconverter_wrapper.cpp b/exynos/multimedia/utils/csc/exynos4/csc_fimc.cpp similarity index 78% rename from exynos4/multimedia/libs/libcsc/hwconverter_wrapper.cpp rename to exynos/multimedia/utils/csc/exynos4/csc_fimc.cpp index 9f6cd07..7c458b2 100644 --- a/exynos4/multimedia/libs/libcsc/hwconverter_wrapper.cpp +++ b/exynos/multimedia/utils/csc/exynos4/csc_fimc.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 The Android Open Source Project + * Copyright (C) 2009 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,23 +15,23 @@ */ /* - * @file hwconverter_wrapper.cpp + * @file csc_fimc.cpp * - * @brief hwconverter_wrapper abstract libhwconverter and support c functions + * @brief csc_fimc use fimc1 to color space convertion * * @author ShinWon Lee (shinwon.lee@samsung.com) * * @version 1.0 * * @history - * 2012.02.01 : Create + * 2011.11.01 : Create */ #include #include #include "SEC_OMX_Def.h" -#include "hwconverter_wrapper.h" +#include "csc_fimc.h" #include "HardwareConverter.h" #ifdef __cplusplus @@ -39,12 +39,12 @@ extern "C" { #endif /* - * create hwconverter handle + * create and open fimc handle * * @return * fimc handle */ -void *csc_hwconverter_open() +void *csc_fimc_open() { HardwareConverter *hw_converter = NULL; @@ -59,7 +59,7 @@ void *csc_hwconverter_open() } /* - * destroy hwconverter handle + * close and destroy fimc handle * * @param handle * fimc handle[in] @@ -67,22 +67,21 @@ void *csc_hwconverter_open() * @return * pass or fail */ -HWCONVERTER_ERROR_CODE csc_hwconverter_close( - void *handle) +CSC_FIMC_ERROR_CODE csc_fimc_close(void *handle) { HardwareConverter *hw_converter = (HardwareConverter *)handle; if (hw_converter != NULL) delete hw_converter; - return HWCONVERTER_RET_OK; + return CSC_FIMC_RET_OK; } /* * convert color space nv12t to omxformat * * @param handle - * hwconverter handle[in] + * fimc handle[in] * * @param dst_addr * y,u,v address of dst_addr[out] @@ -102,7 +101,7 @@ HWCONVERTER_ERROR_CODE csc_hwconverter_close( * @return * pass or fail */ -HWCONVERTER_ERROR_CODE csc_hwconverter_convert_nv12t( +CSC_FIMC_ERROR_CODE csc_fimc_convert_nv12t( void *handle, void **dst_addr, void **src_addr, @@ -110,11 +109,11 @@ HWCONVERTER_ERROR_CODE csc_hwconverter_convert_nv12t( unsigned int height, OMX_COLOR_FORMATTYPE omxformat) { - HWCONVERTER_ERROR_CODE ret = HWCONVERTER_RET_OK; + CSC_FIMC_ERROR_CODE ret = CSC_FIMC_RET_OK; HardwareConverter *hw_converter = (HardwareConverter *)handle; if (hw_converter == NULL) { - ret = HWCONVERTER_RET_FAIL; + ret = CSC_FIMC_RET_FAIL; goto EXIT; } @@ -123,7 +122,7 @@ HWCONVERTER_ERROR_CODE csc_hwconverter_convert_nv12t( (OMX_COLOR_FORMATTYPE)OMX_SEC_COLOR_FormatNV12TPhysicalAddress, width, height, omxformat); - ret = HWCONVERTER_RET_OK; + ret = CSC_FIMC_RET_OK; EXIT: diff --git a/exynos4/multimedia/libs/libcsc/hwconverter_wrapper.h b/exynos/multimedia/utils/csc/exynos4/csc_fimc.h similarity index 75% rename from exynos4/multimedia/libs/libcsc/hwconverter_wrapper.h rename to exynos/multimedia/utils/csc/exynos4/csc_fimc.h index 292a680..3ae24ac 100644 --- a/exynos4/multimedia/libs/libcsc/hwconverter_wrapper.h +++ b/exynos/multimedia/utils/csc/exynos4/csc_fimc.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 The Android Open Source Project + * Copyright (C) 2009 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,21 +15,21 @@ */ /* - * @file hwconverter_wrapper.h + * @file csc_fimc.h * - * @brief hwconverter_wrapper abstract libhwconverter and support c functions + * @brief csc_fimc use fimc1 to color space convertion * * @author ShinWon Lee (shinwon.lee@samsung.com) * * @version 1.0 * * @history - * 2012.02.01 : Create + * 2011.11.01 : Create */ -#ifndef HWCONVERTER_WRAPPER_H +#ifndef CSC_FIMC_H -#define HWCONVERTER_WRAPPER_H +#define CSC_FIMC_H #ifdef __cplusplus extern "C" { @@ -41,38 +41,37 @@ extern "C" { /* Structure and Type */ /*--------------------------------------------------------------------------------*/ typedef enum { - HWCONVERTER_RET_OK = 0, - HWCONVERTER_RET_FAIL = -1 -} HWCONVERTER_ERROR_CODE; + CSC_FIMC_RET_OK = 0, + CSC_FIMC_RET_FAIL = -1 +} CSC_FIMC_ERROR_CODE; /*--------------------------------------------------------------------------------*/ /* CSC FIMC APIs */ /*--------------------------------------------------------------------------------*/ /* - * create hwconverter handle + * create and open fimc handle * * @return - * hwconverter handle + * fimc handle */ void *csc_fimc_open(); /* - * destroy hwconverter handle + * close and destroy fimc handle * * @param handle - * hwconverter handle[in] + * fimc handle[in] * * @return * error code */ -HWCONVERTER_ERROR_CODE csc_fimc_close( - void *handle); +CSC_FIMC_ERROR_CODE csc_fimc_close(void *handle); /* * convert color space nv12t to omxformat * * @param handle - * hwconverter handle[in] + * fimc handle[in] * * @param dst_addr * y,u,v address of dst_addr[out] @@ -92,7 +91,7 @@ HWCONVERTER_ERROR_CODE csc_fimc_close( * @return * error code */ -HWCONVERTER_ERROR_CODE csc_fimc_convert_nv12t( +CSC_FIMC_ERROR_CODE csc_fimc_convert_nv12t( void *handle, void **dst_addr, void **src_addr, diff --git a/exynos/multimedia/utils/csc/exynos4/csc_interleave_memcpy_neon.s b/exynos/multimedia/utils/csc/exynos4/csc_interleave_memcpy_neon.s new file mode 100644 index 0000000..3d2b41f --- /dev/null +++ b/exynos/multimedia/utils/csc/exynos4/csc_interleave_memcpy_neon.s @@ -0,0 +1,120 @@ +/* + * + * Copyright 2012 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License") + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file csc_linear_to_tiled_crop_neon.s + * @brief SEC_OMX specific define + * @author ShinWon Lee (shinwon.lee@samsung.com) + * @version 1.0 + * @history + * 2012.01.04 : Create + */ + +/* + * Interleave src1, src2 to dst + * + * @param dest + * dst address[out] + * + * @param src1 + * src1 address[in] + * + * @param src2 + * src2 address[in] + * + * @param src_size + * src_size or src1 + */ + + .arch armv7-a + .text + .global csc_interleave_memcpy_neon + .type csc_interleave_memcpy_neon, %function +csc_interleave_memcpy_neon: + .fnstart + + @r0 dest + @r1 src1 + @r2 src2 + @r3 src_size + @r4 + @r5 + @r6 + @r7 + @r8 temp1 + @r9 temp2 + @r10 dest_addr + @r11 src1_addr + @r12 src2_addr + @r14 i + + stmfd sp!, {r8-r12,r14} @ backup registers + + mov r10, r0 + mov r11, r1 + mov r12, r2 + mov r14, r3 + + cmp r14, #128 + blt LESS_THAN_128 + +LOOP_128: + vld1.8 {q0}, [r11]! + vld1.8 {q2}, [r11]! + vld1.8 {q4}, [r11]! + vld1.8 {q6}, [r11]! + vld1.8 {q8}, [r11]! + vld1.8 {q10}, [r11]! + vld1.8 {q12}, [r11]! + vld1.8 {q14}, [r11]! + vld1.8 {q1}, [r12]! + vld1.8 {q3}, [r12]! + vld1.8 {q5}, [r12]! + vld1.8 {q7}, [r12]! + vld1.8 {q9}, [r12]! + vld1.8 {q11}, [r12]! + vld1.8 {q13}, [r12]! + vld1.8 {q15}, [r12]! + + vst2.8 {q0, q1}, [r10]! + vst2.8 {q2, q3}, [r10]! + vst2.8 {q4, q5}, [r10]! + vst2.8 {q6, q7}, [r10]! + vst2.8 {q8, q9}, [r10]! + vst2.8 {q10, q11}, [r10]! + vst2.8 {q12, q13}, [r10]! + vst2.8 {q14, q15}, [r10]! + + sub r14, #128 + cmp r14, #128 + bgt LOOP_128 + +LESS_THAN_128: + cmp r14, #0 + beq RESTORE_REG + +LOOP_1: + ldrb r8, [r11], #1 + ldrb r9, [r12], #1 + strb r8, [r10], #1 + strb r9, [r10], #1 + subs r14, #1 + bne LOOP_1 + +RESTORE_REG: + ldmfd sp!, {r8-r12,r15} @ restore registers + .fnend diff --git a/exynos/multimedia/utils/csc/exynos4/csc_linear_to_tiled_crop_neon.s b/exynos/multimedia/utils/csc/exynos4/csc_linear_to_tiled_crop_neon.s new file mode 100644 index 0000000..745d495 --- /dev/null +++ b/exynos/multimedia/utils/csc/exynos4/csc_linear_to_tiled_crop_neon.s @@ -0,0 +1,492 @@ +/* + * + * Copyright 2010 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License") + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file csc_linear_to_tiled_crop_neon.s + * @brief SEC_OMX specific define + * @author ShinWon Lee (shinwon.lee@samsung.com) + * @version 1.0 + * @history + * 2011.8.04 : Create + */ + +/* + * Converts linear data to tiled + * Crops left, top, right, buttom + * 1. Y of YUV420P to Y of NV12T + * 2. Y of YUV420S to Y of NV12T + * 3. UV of YUV420S to UV of NV12T + * + * @param nv12t_dest + * Y or UV plane address of NV12T[out] + * + * @param yuv420_src + * Y or UV plane address of YUV420P(S)[in] + * + * @param yuv420_width + * Width of YUV420[in] + * + * @param yuv420_height + * Y: Height of YUV420, UV: Height/2 of YUV420[in] + * + * @param left + * Crop size of left. It should be even. + * + * @param top + * Crop size of top. It should be even. + * + * @param right + * Crop size of right. It should be even. + * + * @param buttom + * Crop size of buttom. It should be even. + */ + + .arch armv7-a + .text + .global csc_linear_to_tiled_crop_neon + .type csc_linear_to_tiled_crop_neon, %function +csc_linear_to_tiled_crop_neon: + .fnstart + + @r0 tiled_dest + @r1 linear_src + @r2 yuv420_width + @r3 yuv420_height + @r4 j + @r5 i + @r6 nn(tiled_addr) + @r7 mm(linear_addr) + @r8 aligned_x_size + @r9 aligned_y_size + @r10 temp1 + @r11 temp2 + @r12 temp3 + @r14 temp4 + + stmfd sp!, {r4-r12,r14} @ backup registers + + ldr r11, [sp, #44] @ top + ldr r14, [sp, #52] @ buttom + ldr r10, [sp, #40] @ left + ldr r12, [sp, #48] @ right + + sub r9, r3, r11 @ aligned_y_size = ((yuv420_height-top-buttom)>>5)<<5 + sub r9, r9, r14 + bic r9, r9, #0x1F + + sub r8, r2, r10 @ aligned_x_size = ((yuv420_width-left-right)>>6)<<6 + sub r8, r8, r12 + bic r8, r8, #0x3F + + mov r5, #0 @ i = 0 +LOOP_ALIGNED_Y_SIZE: + + mov r4, #0 @ j = 0 +LOOP_ALIGNED_X_SIZE: + + bl GET_TILED_OFFSET + + ldr r10, [sp, #44] @ r10 = top + ldr r14, [sp, #40] @ r14 = left + add r10, r5, r10 @ temp1 = linear_x_size*(i+top) + mul r10, r2, r10 + add r7, r1, r4 @ linear_addr = linear_src+j + add r7, r7, r10 @ linear_addr = linear_addr+temp1 + add r7, r7, r14 @ linear_addr = linear_addr+left + sub r10, r2, #32 + + pld [r7, r2] + vld1.8 {q0, q1}, [r7]! @ load {linear_src, 64} + pld [r7, r2] + vld1.8 {q2, q3}, [r7], r10 + pld [r7, r2] + vld1.8 {q4, q5}, [r7]! @ load {linear_src+linear_x_size*1, 64} + pld [r7, r2] + vld1.8 {q6, q7}, [r7], r10 + pld [r7, r2] + vld1.8 {q8, q9}, [r7]! @ load {linear_src+linear_x_size*2, 64} + pld [r7, r2] + vld1.8 {q10, q11}, [r7], r10 + pld [r7, r2] + vld1.8 {q12, q13}, [r7]! @ load {linear_src+linear_x_size*3, 64} + pld [r7, r2] + vld1.8 {q14, q15}, [r7], r10 + add r6, r0, r6 @ tiled_addr = tiled_dest+tiled_addr + vst1.8 {q0, q1}, [r6]! @ store {tiled_addr} + vst1.8 {q2, q3}, [r6]! + vst1.8 {q4, q5}, [r6]! @ store {tiled_addr+64*1} + vst1.8 {q6, q7}, [r6]! + vst1.8 {q8, q9}, [r6]! @ store {tiled_addr+64*2} + vst1.8 {q10, q11}, [r6]! + vst1.8 {q12, q13}, [r6]! @ store {tiled_addr+64*3} + vst1.8 {q14, q15}, [r6]! + + pld [r7, r2] + vld1.8 {q0, q1}, [r7]! @ load {linear_src+linear_x_size*4, 64} + pld [r7, r2] + vld1.8 {q2, q3}, [r7], r10 + pld [r7, r2] + vld1.8 {q4, q5}, [r7]! @ load {linear_src+linear_x_size*5, 64} + pld [r7, r2] + vld1.8 {q6, q7}, [r7], r10 + pld [r7, r2] + vld1.8 {q8, q9}, [r7]! @ load {linear_src+linear_x_size*6, 64} + pld [r7, r2] + vld1.8 {q10, q11}, [r7], r10 + pld [r7, r2] + vld1.8 {q12, q13}, [r7]! @ load {linear_src+linear_x_size*7, 64} + pld [r7, r2] + vld1.8 {q14, q15}, [r7], r10 + vst1.8 {q0, q1}, [r6]! @ store {tiled_addr+64*4} + vst1.8 {q2, q3}, [r6]! + vst1.8 {q4, q5}, [r6]! @ store {tiled_addr+64*5} + vst1.8 {q6, q7}, [r6]! + vst1.8 {q8, q9}, [r6]! @ store {tiled_addr+64*6} + vst1.8 {q10, q11}, [r6]! + vst1.8 {q12, q13}, [r6]! @ store {tiled_addr+64*7} + vst1.8 {q14, q15}, [r6]! + + pld [r7, r2] + vld1.8 {q0, q1}, [r7]! @ load {linear_src+linear_x_size*8, 64} + pld [r7, r2] + vld1.8 {q2, q3}, [r7], r10 + pld [r7, r2] + vld1.8 {q4, q5}, [r7]! @ load {linear_src+linear_x_size*9, 64} + pld [r7, r2] + vld1.8 {q6, q7}, [r7], r10 + pld [r7, r2] + vld1.8 {q8, q9}, [r7]! @ load {linear_src+linear_x_size*10, 64} + pld [r7, r2] + vld1.8 {q10, q11}, [r7], r10 + pld [r7, r2] + vld1.8 {q12, q13}, [r7]! @ load {linear_src+linear_x_size*11, 64} + pld [r7, r2] + vld1.8 {q14, q15}, [r7], r10 + vst1.8 {q0, q1}, [r6]! @ store {tiled_addr+64*8} + vst1.8 {q2, q3}, [r6]! + vst1.8 {q4, q5}, [r6]! @ store {tiled_addr+64*9} + vst1.8 {q6, q7}, [r6]! + vst1.8 {q8, q9}, [r6]! @ store {tiled_addr+64*10} + vst1.8 {q10, q11}, [r6]! + vst1.8 {q12, q13}, [r6]! @ store {tiled_addr+64*11} + vst1.8 {q14, q15}, [r6]! + + pld [r7, r2] + vld1.8 {q0, q1}, [r7]! @ load {linear_src+linear_x_size*12, 64} + pld [r7, r2] + vld1.8 {q2, q3}, [r7], r10 + pld [r7, r2] + vld1.8 {q4, q5}, [r7]! @ load {linear_src+linear_x_size*13, 64} + pld [r7, r2] + vld1.8 {q6, q7}, [r7], r10 + pld [r7, r2] + vld1.8 {q8, q9}, [r7]! @ load {linear_src+linear_x_size*14, 64} + pld [r7, r2] + vld1.8 {q10, q11}, [r7], r10 + pld [r7, r2] + vld1.8 {q12, q13}, [r7]! @ load {linear_src+linear_x_size*15, 64} + pld [r7, r2] + vld1.8 {q14, q15}, [r7], r10 + vst1.8 {q0, q1}, [r6]! @ store {tiled_addr+64*12} + vst1.8 {q2, q3}, [r6]! + vst1.8 {q4, q5}, [r6]! @ store {tiled_addr+64*13} + vst1.8 {q6, q7}, [r6]! + vst1.8 {q8, q9}, [r6]! @ store {tiled_addr+64*14} + vst1.8 {q10, q11}, [r6]! + vst1.8 {q12, q13}, [r6]! @ store {tiled_addr+64*15} + vst1.8 {q14, q15}, [r6]! + + pld [r7, r2] + vld1.8 {q0, q1}, [r7]! @ load {linear_src+linear_x_size*16, 64} + pld [r7, r2] + vld1.8 {q2, q3}, [r7], r10 + pld [r7, r2] + vld1.8 {q4, q5}, [r7]! @ load {linear_src+linear_x_size*17, 64} + pld [r7, r2] + vld1.8 {q6, q7}, [r7], r10 + pld [r7, r2] + vld1.8 {q8, q9}, [r7]! @ load {linear_src+linear_x_size*18, 64} + pld [r7, r2] + vld1.8 {q10, q11}, [r7], r10 + pld [r7, r2] + vld1.8 {q12, q13}, [r7]! @ load {linear_src+linear_x_size*19, 64} + pld [r7, r2] + vld1.8 {q14, q15}, [r7], r10 + vst1.8 {q0, q1}, [r6]! @ store {tiled_addr+64*16} + vst1.8 {q2, q3}, [r6]! + vst1.8 {q4, q5}, [r6]! @ store {tiled_addr+64*17} + vst1.8 {q6, q7}, [r6]! + vst1.8 {q8, q9}, [r6]! @ store {tiled_addr+64*18} + vst1.8 {q10, q11}, [r6]! + vst1.8 {q12, q13}, [r6]! @ store {tiled_addr+64*19} + vst1.8 {q14, q15}, [r6]! + + pld [r7, r2] + vld1.8 {q0, q1}, [r7]! @ load {linear_src+linear_x_size*20, 64} + pld [r7, r2] + vld1.8 {q2, q3}, [r7], r10 + pld [r7, r2] + vld1.8 {q4, q5}, [r7]! @ load {linear_src+linear_x_size*21, 64} + pld [r7, r2] + vld1.8 {q6, q7}, [r7], r10 + pld [r7, r2] + vld1.8 {q8, q9}, [r7]! @ load {linear_src+linear_x_size*22, 64} + pld [r7, r2] + vld1.8 {q10, q11}, [r7], r10 + pld [r7, r2] + vld1.8 {q12, q13}, [r7]! @ load {linear_src+linear_x_size*23, 64} + pld [r7, r2] + vld1.8 {q14, q15}, [r7], r10 + vst1.8 {q0, q1}, [r6]! @ store {tiled_addr+64*20} + vst1.8 {q2, q3}, [r6]! + vst1.8 {q4, q5}, [r6]! @ store {tiled_addr+64*21} + vst1.8 {q6, q7}, [r6]! + vst1.8 {q8, q9}, [r6]! @ store {tiled_addr+64*22} + vst1.8 {q10, q11}, [r6]! + vst1.8 {q12, q13}, [r6]! @ store {tiled_addr+64*23} + vst1.8 {q14, q15}, [r6]! + + pld [r7, r2] + vld1.8 {q0, q1}, [r7]! @ load {linear_src+linear_x_size*24, 64} + pld [r7, r2] + vld1.8 {q2, q3}, [r7], r10 + pld [r7, r2] + vld1.8 {q4, q5}, [r7]! @ load {linear_src+linear_x_size*25, 64} + pld [r7, r2] + vld1.8 {q6, q7}, [r7], r10 + pld [r7, r2] + vld1.8 {q8, q9}, [r7]! @ load {linear_src+linear_x_size*26, 64} + pld [r7, r2] + vld1.8 {q10, q11}, [r7], r10 + pld [r7, r2] + vld1.8 {q12, q13}, [r7]! @ load {linear_src+linear_x_size*27, 64} + pld [r7, r2] + vld1.8 {q14, q15}, [r7], r10 + vst1.8 {q0, q1}, [r6]! @ store {tiled_addr+64*24} + vst1.8 {q2, q3}, [r6]! + vst1.8 {q4, q5}, [r6]! @ store {tiled_addr+64*25} + vst1.8 {q6, q7}, [r6]! + vst1.8 {q8, q9}, [r6]! @ store {tiled_addr+64*26} + vst1.8 {q10, q11}, [r6]! + vst1.8 {q12, q13}, [r6]! @ store {tiled_addr+64*27} + vst1.8 {q14, q15}, [r6]! + + pld [r7, r2] + vld1.8 {q0, q1}, [r7]! @ load {linear_src+linear_x_size*28, 64} + pld [r7, r2] + vld1.8 {q2, q3}, [r7], r10 + pld [r7, r2] + vld1.8 {q4, q5}, [r7]! @ load {linear_src+linear_x_size*29, 64} + pld [r7, r2] + vld1.8 {q6, q7}, [r7], r10 + pld [r7, r2] + vld1.8 {q8, q9}, [r7]! @ load {linear_src+linear_x_size*30, 64} + pld [r7, r2] + vld1.8 {q10, q11}, [r7], r10 + vld1.8 {q12, q13}, [r7]! @ load {linear_src+linear_x_size*31, 64} + vld1.8 {q14, q15}, [r7], r10 + vst1.8 {q0, q1}, [r6]! @ store {tiled_addr+64*28} + vst1.8 {q2, q3}, [r6]! + vst1.8 {q4, q5}, [r6]! @ store {tiled_addr+64*29} + vst1.8 {q6, q7}, [r6]! + vst1.8 {q8, q9}, [r6]! @ store {tiled_addr+64*30} + vst1.8 {q10, q11}, [r6]! + vst1.8 {q12, q13}, [r6]! @ store {tiled_addr+64*31} + vst1.8 {q14, q15}, [r6]! + + add r4, r4, #64 @ j = j+64 + cmp r4, r8 @ j>5 + mov r10, r4, asr #6 @ temp1 = j>>6 + + and r12, r11, #0x1 @ if (temp2 & 0x1) + cmp r12, #0x1 + bne GET_TILED_OFFSET_EVEN_FORMULA_1 + +GET_TILED_OFFSET_ODD_FORMULA: + sub r6, r11, #1 @ tiled_addr = temp2-1 + + ldr r7, [sp, #40] @ left + add r12, r2, #127 @ temp3 = linear_x_size+127 + sub r12, r12, r7 + ldr r7, [sp, #48] @ right + sub r12, r12, r7 + bic r12, r12, #0x7F @ temp3 = (temp3 >>7)<<7 + mov r12, r12, asr #6 @ temp3 = temp3>>6 + mul r6, r6, r12 @ tiled_addr = tiled_addr*temp3 + add r6, r6, r10 @ tiled_addr = tiled_addr+temp1 + add r6, r6, #2 @ tiled_addr = tiled_addr+2 + bic r12, r10, #0x3 @ temp3 = (temp1>>2)<<2 + add r6, r6, r12 @ tiled_addr = tiled_addr+temp3 + mov r6, r6, lsl #11 @ tiled_addr = tiled_addr<<11 + b GET_TILED_OFFSET_RETURN + +GET_TILED_OFFSET_EVEN_FORMULA_1: + ldr r7, [sp, #44] @ top + add r12, r3, #31 @ temp3 = linear_y_size+31 + sub r12, r12, r7 + ldr r7, [sp, #52] @ buttom + sub r12, r12, r7 + bic r12, r12, #0x1F @ temp3 = (temp3>>5)<<5 + sub r12, r12, #32 @ temp3 = temp3 - 32 + cmp r5, r12 @ if (i<(temp3-32)) { + bge GET_TILED_OFFSET_EVEN_FORMULA_2 + add r12, r10, #2 @ temp3 = temp1+2 + bic r12, r12, #3 @ temp3 = (temp3>>2)<<2 + add r6, r10, r12 @ tiled_addr = temp1+temp3 + ldr r7, [sp, #40] @ left + add r12, r2, #127 @ temp3 = linear_x_size+127 + sub r12, r12, r7 + ldr r7, [sp, #48] @ right + sub r12, r12, r7 + bic r12, r12, #0x7F @ temp3 = (temp3>>7)<<7 + mov r12, r12, asr #6 @ temp3 = temp3>>6 + mul r11, r11, r12 @ tiled_y_index = tiled_y_index*temp3 + add r6, r6, r11 @ tiled_addr = tiled_addr+tiled_y_index + mov r6, r6, lsl #11 @ + b GET_TILED_OFFSET_RETURN + +GET_TILED_OFFSET_EVEN_FORMULA_2: + ldr r7, [sp, #40] @ left + add r12, r2, #127 @ temp3 = linear_x_size+127 + sub r12, r12, r7 + ldr r7, [sp, #48] @ right + sub r12, r12, r7 + bic r12, r12, #0x7F @ temp3 = (temp3>>7)<<7 + mov r12, r12, asr #6 @ temp3 = temp3>>6 + mul r6, r11, r12 @ tiled_addr = temp2*temp3 + add r6, r6, r10 @ tiled_addr = tiled_addr+temp3 + mov r6, r6, lsl #11 @ tiled_addr = tiled_addr<<11@ + +GET_TILED_OFFSET_RETURN: + mov pc, lr + + .fnend diff --git a/exynos/multimedia/utils/csc/exynos4/csc_linear_to_tiled_interleave_crop_neon.s b/exynos/multimedia/utils/csc/exynos4/csc_linear_to_tiled_interleave_crop_neon.s new file mode 100644 index 0000000..6a054fa --- /dev/null +++ b/exynos/multimedia/utils/csc/exynos4/csc_linear_to_tiled_interleave_crop_neon.s @@ -0,0 +1,563 @@ +/* + * + * Copyright 2010 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License") + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file csc_linear_to_tiled_interleave_crop_neon.s + * @brief SEC_OMX specific define + * @author ShinWon Lee (shinwon.lee@samsung.com) + * @version 1.0 + * @history + * 2011.8.04 : Create + */ + +/* + * Converts tiled data to linear + * Crops left, top, right, buttom + * 1. Y of NV12T to Y of YUV420P + * 2. Y of NV12T to Y of YUV420S + * 3. UV of NV12T to UV of YUV420S + * + * @param yuv420_dest + * Y or UV plane address of YUV420[out] + * + * @param nv12t_src + * Y or UV plane address of NV12T[in] + * + * @param yuv420_width + * Width of YUV420[in] + * + * @param yuv420_height + * Y: Height of YUV420, UV: Height/2 of YUV420[in] + * + * @param left + * Crop size of left. It should be even. + * + * @param top + * Crop size of top. It should be even. + * + * @param right + * Crop size of right. It should be even. + * + * @param buttom + * Crop size of buttom. It should be even. + */ + + .arch armv7-a + .text + .global csc_linear_to_tiled_interleave_crop_neon + .type csc_linear_to_tiled_interleave_crop_neon, %function +csc_linear_to_tiled_interleave_crop_neon: + .fnstart + + @r0 tiled_dest + @r1 linear_src_u + @r2 linear_src_v + @r3 yuv420_width + @r4 yuv420_height + @r5 j + @r6 i + @r7 tiled_addr + @r8 linear_addr + @r9 aligned_x_size + @r10 aligned_y_size + @r11 temp1 + @r12 temp2 + @r14 temp3 + + stmfd sp!, {r4-r12,r14} @ backup registers + + ldr r4, [sp, #40] @ load linear_y_size to r4 + + ldr r10, [sp, #48] @ r10 = top + ldr r14, [sp, #56] @ r14 = buttom + ldr r11, [sp, #44] @ r11 = left + ldr r12, [sp, #52] @ r12 = right + + sub r10, r4, r10 @ aligned_y_size = ((yuv420_height-top-buttom)>>5)<<5 + sub r10, r10, r14 + bic r10, r10, #0x1F + sub r11, r3, r11 @ aligned_x_size = ((yuv420_width-left-right)>>6)<<6 + sub r11, r11, r12 + bic r9, r11, #0x3F + + mov r6, #0 @ i = 0 +LOOP_ALIGNED_Y_SIZE: + + mov r5, #0 @ j = 0 +LOOP_ALIGNED_X_SIZE: + + bl GET_TILED_OFFSET + + ldr r12, [sp, #48] @ r12 = top + ldr r8, [sp, #44] @ r8 = left + + mov r11, r3, asr #1 @ temp1 = (yuv420_width/2)*(i+top) + add r12, r6, r12 + mul r11, r11, r12 + add r11, r11, r5, asr #1 @ temp1 = temp1+j/2 + add r11, r11, r8, asr #1 @ temp1 = temp1+left/2 + + mov r12, r3, asr #1 @ temp2 = yuv420_width/2 + sub r12, r12, #16 @ temp2 = yuv420_width-16 + + add r8, r1, r11 @ linear_addr = linear_src_u+temp1 + add r11, r2, r11 @ temp1 = linear_src_v+temp1 + add r7, r0, r7 @ tiled_addr = tiled_dest+tiled_addr + + pld [r8, r3] + vld1.8 {q0}, [r8]! @ load {linear_src_u, 32} + vld1.8 {q2}, [r8], r12 + pld [r8, r3] + vld1.8 {q4}, [r8]! @ load {linear_src_u+(linear_x_size/2)*1, 32} + vld1.8 {q6}, [r8], r12 + pld [r11] + vld1.8 {q8}, [r8]! @ load {linear_src_u+(linear_x_size/2)*2, 32} + vld1.8 {q10}, [r8], r12 + pld [r11, r3, asr #1] + vld1.8 {q12}, [r8]! @ load {linear_src_u+(linear_x_size/2)*3, 32} + vld1.8 {q14}, [r8], r12 + pld [r11, r3] + vld1.8 {q1}, [r11]! @ load {linear_src_v, 32} + vld1.8 {q3}, [r11], r12 + pld [r11, r3] + vld1.8 {q5}, [r11]! @ load {linear_src_v+(linear_x_size/2)*1, 32} + vld1.8 {q7}, [r11], r12 + pld [r8] + vld1.8 {q9}, [r11]! @ load {linear_src_v+(linear_x_size/2)*2, 32} + vld1.8 {q11}, [r11], r12 + pld [r8, r3, asr #1] + vld1.8 {q13}, [r11]! @ load {linear_src_v+(linear_x_size/2)*3, 32} + vld1.8 {q15}, [r11], r12 + vst2.8 {q0, q1}, [r7]! @ store {tiled_addr} + vst2.8 {q2, q3}, [r7]! + vst2.8 {q4, q5}, [r7]! @ store {tiled_addr+64*1} + vst2.8 {q6, q7}, [r7]! + vst2.8 {q8, q9}, [r7]! @ store {tiled_addr+64*2} + vst2.8 {q10, q11}, [r7]! + vst2.8 {q12, q13}, [r7]! @ store {tiled_addr+64*3} + vst2.8 {q14, q15}, [r7]! + + pld [r8, r3] + vld1.8 {q0}, [r8]! @ load {linear_src_u+(linear_x_size/2)*4, 32} + vld1.8 {q2}, [r8], r12 + pld [r8, r3] + vld1.8 {q4}, [r8]! @ load {linear_src_u+(linear_x_size/2)*5, 32} + vld1.8 {q6}, [r8], r12 + pld [r11] + vld1.8 {q8}, [r8]! @ load {linear_src_u+(linear_x_size/2)*6, 32} + vld1.8 {q10}, [r8], r12 + pld [r11, r3, asr #1] + vld1.8 {q12}, [r8]! @ load {linear_src_u+(linear_x_size/2)*7, 32} + vld1.8 {q14}, [r8], r12 + pld [r11, r3] + vld1.8 {q1}, [r11]! @ load {linear_src_v+(linear_x_size/2)*4, 32} + vld1.8 {q3}, [r11], r12 + pld [r11, r3] + vld1.8 {q5}, [r11]! @ load {linear_src_v+(linear_x_size/2)*5, 32} + vld1.8 {q7}, [r11], r12 + pld [r8] + vld1.8 {q9}, [r11]! @ load {linear_src_v+(linear_x_size/2)*6, 32} + vld1.8 {q11}, [r11], r12 + pld [r8, r3, asr #1] + vld1.8 {q13}, [r11]! @ load {linear_src_v+(linear_x_size/2)*7, 32} + vld1.8 {q15}, [r11], r12 + vst2.8 {q0, q1}, [r7]! @ store {tiled_addr+64*4} + vst2.8 {q2, q3}, [r7]! + vst2.8 {q4, q5}, [r7]! @ store {tiled_addr+64*5} + vst2.8 {q6, q7}, [r7]! + vst2.8 {q8, q9}, [r7]! @ store {tiled_addr+64*6} + vst2.8 {q10, q11}, [r7]! + vst2.8 {q12, q13}, [r7]! @ store {tiled_addr+64*7} + vst2.8 {q14, q15}, [r7]! + + pld [r8, r3] + vld1.8 {q0}, [r8]! @ load {linear_src_u+(linear_x_size/2)*8, 32} + vld1.8 {q2}, [r8], r12 + pld [r8, r3] + vld1.8 {q4}, [r8]! @ load {linear_src_u+(linear_x_size/2)*9, 32} + vld1.8 {q6}, [r8], r12 + pld [r11] + vld1.8 {q8}, [r8]! @ load {linear_src_u+(linear_x_size/2)*10, 32} + vld1.8 {q10}, [r8], r12 + pld [r11, r3, asr #1] + vld1.8 {q12}, [r8]! @ load {linear_src_u+(linear_x_size/2)*11, 32} + vld1.8 {q14}, [r8], r12 + pld [r11, r3] + vld1.8 {q1}, [r11]! @ load {linear_src_v+(linear_x_size/2)*8, 32} + vld1.8 {q3}, [r11], r12 + pld [r11, r3] + vld1.8 {q5}, [r11]! @ load {linear_src_v+(linear_x_size/2)*9, 32} + vld1.8 {q7}, [r11], r12 + pld [r8] + vld1.8 {q9}, [r11]! @ load {linear_src_v+(linear_x_size/2)*10, 32} + vld1.8 {q11}, [r11], r12 + pld [r8, r3, asr #1] + vld1.8 {q13}, [r11]! @ load {linear_src_v+(linear_x_size/2)*11, 32} + vld1.8 {q15}, [r11], r12 + vst2.8 {q0, q1}, [r7]! @ store {tiled_addr+64*8} + vst2.8 {q2, q3}, [r7]! + vst2.8 {q4, q5}, [r7]! @ store {tiled_addr+64*9} + vst2.8 {q6, q7}, [r7]! + vst2.8 {q8, q9}, [r7]! @ store {tiled_addr+64*10} + vst2.8 {q10, q11}, [r7]! + vst2.8 {q12, q13}, [r7]! @ store {tiled_addr+64*11} + vst2.8 {q14, q15}, [r7]! + + pld [r8, r3] + vld1.8 {q0}, [r8]! @ load {linear_src_u+(linear_x_size/2)*12, 32} + vld1.8 {q2}, [r8], r12 + pld [r8, r3] + vld1.8 {q4}, [r8]! @ load {linear_src_u+(linear_x_size/2)*13, 32} + vld1.8 {q6}, [r8], r12 + pld [r11] + vld1.8 {q8}, [r8]! @ load {linear_src_u+(linear_x_size/2)*14, 32} + vld1.8 {q10}, [r8], r12 + pld [r11, r3, asr #1] + vld1.8 {q12}, [r8]! @ load {linear_src_u+(linear_x_size/2)*15, 32} + vld1.8 {q14}, [r8], r12 + pld [r11, r3] + vld1.8 {q1}, [r11]! @ load {linear_src_v+(linear_x_size/2)*12, 32} + vld1.8 {q3}, [r11], r12 + pld [r11, r3] + vld1.8 {q5}, [r11]! @ load {linear_src_v+(linear_x_size/2)*13, 32} + vld1.8 {q7}, [r11], r12 + pld [r8] + vld1.8 {q9}, [r11]! @ load {linear_src_v+(linear_x_size/2)*14, 32} + vld1.8 {q11}, [r11], r12 + pld [r8, r3, asr #1] + vld1.8 {q13}, [r11]! @ load {linear_src_v+(linear_x_size/2)*15, 32} + vld1.8 {q15}, [r11], r12 + vst2.8 {q0, q1}, [r7]! @ store {tiled_addr+64*12} + vst2.8 {q2, q3}, [r7]! + vst2.8 {q4, q5}, [r7]! @ store {tiled_addr+64*13} + vst2.8 {q6, q7}, [r7]! + vst2.8 {q8, q9}, [r7]! @ store {tiled_addr+64*14} + vst2.8 {q10, q11}, [r7]! + vst2.8 {q12, q13}, [r7]! @ store {tiled_addr+64*15} + vst2.8 {q14, q15}, [r7]! + + pld [r8, r3] + vld1.8 {q0}, [r8]! @ load {linear_src_u+(linear_x_size/2)*16, 32} + vld1.8 {q2}, [r8], r12 + pld [r8, r3] + vld1.8 {q4}, [r8]! @ load {linear_src_u+(linear_x_size/2)*17, 32} + vld1.8 {q6}, [r8], r12 + pld [r11] + vld1.8 {q8}, [r8]! @ load {linear_src_u+(linear_x_size/2)*18, 32} + vld1.8 {q10}, [r8], r12 + pld [r11, r3, asr #1] + vld1.8 {q12}, [r8]! @ load {linear_src_u+(linear_x_size/2)*19, 32} + vld1.8 {q14}, [r8], r12 + pld [r11, r3] + vld1.8 {q1}, [r11]! @ load {linear_src_v+(linear_x_size/2)*16, 32} + vld1.8 {q3}, [r11], r12 + pld [r11, r3] + vld1.8 {q5}, [r11]! @ load {linear_src_v+(linear_x_size/2)*17, 32} + vld1.8 {q7}, [r11], r12 + pld [r8] + vld1.8 {q9}, [r11]! @ load {linear_src_v+(linear_x_size/2)*18, 32} + vld1.8 {q11}, [r11], r12 + pld [r8, r3, asr #1] + vld1.8 {q13}, [r11]! @ load {linear_src_v+(linear_x_size/2)*19, 32} + vld1.8 {q15}, [r11], r12 + vst2.8 {q0, q1}, [r7]! @ store {tiled_addr+64*16} + vst2.8 {q2, q3}, [r7]! + vst2.8 {q4, q5}, [r7]! @ store {tiled_addr+64*17} + vst2.8 {q6, q7}, [r7]! + vst2.8 {q8, q9}, [r7]! @ store {tiled_addr+64*18} + vst2.8 {q10, q11}, [r7]! + vst2.8 {q12, q13}, [r7]! @ store {tiled_addr+64*19} + vst2.8 {q14, q15}, [r7]! + + pld [r8, r3] + vld1.8 {q0}, [r8]! @ load {linear_src_u+(linear_x_size/2)*20, 32} + vld1.8 {q2}, [r8], r12 + pld [r8, r3] + vld1.8 {q4}, [r8]! @ load {linear_src_u+(linear_x_size/2)*21, 32} + vld1.8 {q6}, [r8], r12 + pld [r11] + vld1.8 {q8}, [r8]! @ load {linear_src_u+(linear_x_size/2)*22, 32} + vld1.8 {q10}, [r8], r12 + pld [r11, r3, asr #1] + vld1.8 {q12}, [r8]! @ load {linear_src_u+(linear_x_size/2)*23, 32} + vld1.8 {q14}, [r8], r12 + pld [r11, r3] + vld1.8 {q1}, [r11]! @ load {linear_src_v+(linear_x_size/2)*20, 32} + vld1.8 {q3}, [r11], r12 + pld [r11, r3] + vld1.8 {q5}, [r11]! @ load {linear_src_v+(linear_x_size/2)*21, 32} + vld1.8 {q7}, [r11], r12 + pld [r8] + vld1.8 {q9}, [r11]! @ load {linear_src_v+(linear_x_size/2)*22, 32} + vld1.8 {q11}, [r11], r12 + pld [r8, r3, asr #1] + vld1.8 {q13}, [r11]! @ load {linear_src_v+(linear_x_size/2)*23, 32} + vld1.8 {q15}, [r11], r12 + vst2.8 {q0, q1}, [r7]! @ store {tiled_addr+64*20} + vst2.8 {q2, q3}, [r7]! + vst2.8 {q4, q5}, [r7]! @ store {tiled_addr+64*21} + vst2.8 {q6, q7}, [r7]! + vst2.8 {q8, q9}, [r7]! @ store {tiled_addr+64*22} + vst2.8 {q10, q11}, [r7]! + vst2.8 {q12, q13}, [r7]! @ store {tiled_addr+64*23} + vst2.8 {q14, q15}, [r7]! + + pld [r8, r3] + vld1.8 {q0}, [r8]! @ load {linear_src_u+(linear_x_size/2)*24, 32} + vld1.8 {q2}, [r8], r12 + pld [r8, r3] + vld1.8 {q4}, [r8]! @ load {linear_src_u+(linear_x_size/2)*25, 32} + vld1.8 {q6}, [r8], r12 + pld [r11] + vld1.8 {q8}, [r8]! @ load {linear_src_u+(linear_x_size/2)*26, 32} + vld1.8 {q10}, [r8], r12 + pld [r11, r3, asr #1] + vld1.8 {q12}, [r8]! @ load {linear_src_u+(linear_x_size/2)*27, 32} + vld1.8 {q14}, [r8], r12 + pld [r11, r3] + vld1.8 {q1}, [r11]! @ load {linear_src_v+(linear_x_size/2)*24, 32} + vld1.8 {q3}, [r11], r12 + pld [r11, r3] + vld1.8 {q5}, [r11]! @ load {linear_src_v+(linear_x_size/2)*25, 32} + vld1.8 {q7}, [r11], r12 + pld [r8] + vld1.8 {q9}, [r11]! @ load {linear_src_v+(linear_x_size/2)*26, 32} + vld1.8 {q11}, [r11], r12 + pld [r8, r3, asr #1] + vld1.8 {q13}, [r11]! @ load {linear_src_v+(linear_x_size/2)*27, 32} + vld1.8 {q15}, [r11], r12 + vst2.8 {q0, q1}, [r7]! @ store {tiled_addr+64*24} + vst2.8 {q2, q3}, [r7]! + vst2.8 {q4, q5}, [r7]! @ store {tiled_addr+64*25} + vst2.8 {q6, q7}, [r7]! + vst2.8 {q8, q9}, [r7]! @ store {tiled_addr+64*26} + vst2.8 {q10, q11}, [r7]! + vst2.8 {q12, q13}, [r7]! @ store {tiled_addr+64*27} + vst2.8 {q14, q15}, [r7]! + + pld [r8, r3] + vld1.8 {q0}, [r8]! @ load {linear_src_u+(linear_x_size/2)*28, 32} + vld1.8 {q2}, [r8], r12 + pld [r8, r3] + vld1.8 {q4}, [r8]! @ load {linear_src_u+(linear_x_size/2)*29, 32} + vld1.8 {q6}, [r8], r12 + pld [r11] + vld1.8 {q8}, [r8]! @ load {linear_src_u+(linear_x_size/2)*30, 32} + vld1.8 {q10}, [r8], r12 + pld [r11, r3, asr #1] + vld1.8 {q12}, [r8]! @ load {linear_src_u+(linear_x_size/2)*31, 32} + vld1.8 {q14}, [r8], r12 + pld [r11, r3] + vld1.8 {q1}, [r11]! @ load {linear_src_v+(linear_x_size/2)*28, 32} + vld1.8 {q3}, [r11], r12 + pld [r11, r3] + vld1.8 {q5}, [r11]! @ load {linear_src_v+(linear_x_size/2)*29, 32} + vld1.8 {q7}, [r11], r12 + vld1.8 {q9}, [r11]! @ load {linear_src_v+(linear_x_size/2)*30, 32} + vld1.8 {q11}, [r11], r12 + vld1.8 {q13}, [r11]! @ load {linear_src_v+(linear_x_size/2)*31, 32} + vld1.8 {q15}, [r11], r12 + vst2.8 {q0, q1}, [r7]! @ store {tiled_addr+64*28} + vst2.8 {q2, q3}, [r7]! + vst2.8 {q4, q5}, [r7]! @ store {tiled_addr+64*29} + vst2.8 {q6, q7}, [r7]! + vst2.8 {q8, q9}, [r7]! @ store {tiled_addr+64*30} + vst2.8 {q10, q11}, [r7]! + vst2.8 {q12, q13}, [r7]! @ store {tiled_addr+64*31} + vst2.8 {q14, q15}, [r7]! + + add r5, r5, #64 @ j = j+64 + cmp r5, r9 @ j>5 + mov r11, r5, asr #6 @ temp1 = j>>6 + + and r14, r12, #0x1 @ if (temp2 & 0x1) + cmp r14, #0x1 + bne GET_TILED_OFFSET_EVEN_FORMULA_1 + +GET_TILED_OFFSET_ODD_FORMULA: + + ldr r7, [sp, #48] @ r7 = left , (r14 was pushed to stack) + ldr r8, [sp, #56] @ r8 = right , (r14 was pushed to stack) + sub r14, r3, r7 + sub r14, r14, r8 + add r14, r14, #127 @ temp3 = (((yuv420_width-left-right)+127)>>7)<<7 + bic r14, r14, #0x7F @ temp3 = (temp3 >>7)<<7 + mov r14, r14, asr #6 @ temp3 = temp3>>6 + sub r7, r12, #1 @ tiled_addr = temp2-1 + mul r7, r7, r14 @ tiled_addr = tiled_addr*temp3 + add r7, r7, r11 @ tiled_addr = tiled_addr+temp1 + add r7, r7, #2 @ tiled_addr = tiled_addr+2 + bic r14, r11, #0x3 @ temp3 = (temp1>>2)<<2 + add r7, r7, r14 @ tiled_addr = tiled_addr+temp3 + mov r7, r7, lsl #11 @ tiled_addr = tiled_addr<<11 + b GET_TILED_OFFSET_RETURN + +GET_TILED_OFFSET_EVEN_FORMULA_1: + ldr r7, [sp, #52] @ r7 = top, (r14 was pushed to stack) + ldr r8, [sp, #60] @ r8 = buttom, (r14 was pushed to stack) + sub r14, r4, r7 + sub r14, r14, r8 + add r14, r14, #31 @ temp3 = (((yuv420_height-top-buttom)+31)>>5)<<5 + bic r14, r14, #0x1F @ temp3 = (temp3>>5)<<5 + sub r14, r14, #32 @ temp3 = temp3 - 32 + cmp r6, r14 @ if (i<(temp3-32)) { + bge GET_TILED_OFFSET_EVEN_FORMULA_2 + add r14, r11, #2 @ temp3 = temp1+2 + bic r14, r14, #3 @ temp3 = (temp3>>2)<<2 + add r7, r11, r14 @ tiled_addr = temp1+temp3 + ldr r8, [sp, #48] @ r8 = left, (r14 was pushed to stack) + sub r14, r3, r8 + ldr r8, [sp, #56] @ r8 = right, (r14 was pushed to stack) + sub r14, r14, r8 + add r14, r14, #127 @ temp3 = (((yuv420_width-left-right)+127)>>7)<<7 + bic r14, r14, #0x7F @ temp3 = (temp3>>7)<<7 + mov r14, r14, asr #6 @ temp3 = temp3>>6 + mul r12, r12, r14 @ tiled_y_index = tiled_y_index*temp3 + add r7, r7, r12 @ tiled_addr = tiled_addr+tiled_y_index + mov r7, r7, lsl #11 @ + b GET_TILED_OFFSET_RETURN + +GET_TILED_OFFSET_EVEN_FORMULA_2: + ldr r8, [sp, #48] @ r8 = left, (r14 was pushed to stack) + sub r14, r3, r8 + ldr r8, [sp, #56] @ r8 = right, (r14 was pushed to stack) + sub r14, r14, r8 + add r14, r14, #127 @ temp3 = (((yuv420_width-left-right)+127)>>7)<<7 + bic r14, r14, #0x7F @ temp3 = (temp3>>7)<<7 + mov r14, r14, asr #6 @ temp3 = temp3>>6 + mul r7, r12, r14 @ tiled_addr = temp2*temp3 + add r7, r7, r11 @ tiled_addr = tiled_addr+temp3 + mov r7, r7, lsl #11 @ tiled_addr = tiled_addr<<11@ + +GET_TILED_OFFSET_RETURN: + ldmfd sp!, {r15} @ restore registers + + .fnend + diff --git a/exynos/multimedia/utils/csc/exynos4/csc_tiled_to_linear_crop_neon.s b/exynos/multimedia/utils/csc/exynos4/csc_tiled_to_linear_crop_neon.s new file mode 100644 index 0000000..da86ac6 --- /dev/null +++ b/exynos/multimedia/utils/csc/exynos4/csc_tiled_to_linear_crop_neon.s @@ -0,0 +1,701 @@ +/* + * + * Copyright 2010 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License") + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file csc_tiled_to_linear_crop_neon.s + * @brief SEC_OMX specific define + * @author ShinWon Lee (shinwon.lee@samsung.com) + * @version 1.0 + * @history + * 2011.8.04 : Create + */ + +/* + * Converts tiled data to linear + * Crops left, top, right, buttom + * 1. Y of NV12T to Y of YUV420P + * 2. Y of NV12T to Y of YUV420S + * 3. UV of NV12T to UV of YUV420S + * + * @param yuv420_dest + * Y or UV plane address of YUV420[out] + * + * @param nv12t_src + * Y or UV plane address of NV12T[in] + * + * @param yuv420_width + * Width of YUV420[in] + * + * @param yuv420_height + * Y: Height of YUV420, UV: Height/2 of YUV420[in] + * + * @param left + * Crop size of left. It should be even. + * + * @param top + * Crop size of top. It should be even. + * + * @param right + * Crop size of right. It should be even. + * + * @param buttom + * Crop size of buttom. It should be even. + */ + + .arch armv7-a + .text + .global csc_tiled_to_linear_crop_neon + .type csc_tiled_to_linear_crop_neon, %function +csc_tiled_to_linear_crop_neon: + .fnstart + + @r0 yuv420_dest + @r1 nv12t_src + @r2 yuv420_width + @r3 yuv420_height + @r4 + @r5 i + @r6 j + @r7 tiled_offset + @r8 tiled_offset1 + @r9 linear_offset + @r10 temp1 + @r11 temp2 + @r12 temp3 + @r14 temp4 + + stmfd sp!, {r4-r12,r14} @ backup registers + + ldr r12, [sp, #48] @ r12 = right + ldr r10, [sp, #40] @ r10 = left + sub r12, r2, r12 @ temp3 = yuv420_width-right@ + sub r10, r12, r10 @ temp1 = temp3-left@ + cmp r10, #256 @ if (temp1 >= 256) + blt LOOP_HEIGHT_64_START + + ldr r5, [sp, #44] @ i = top +LOOP_HEIGHT_256: + ldr r6, [sp, #40] @ j = left + mov r14, r5, asr #5 @ temp4 = i>>5 + bic r12, r6, #0xFF @ temp3 = (j>>8)<<8 + mov r12, r12, asr #6 @ temp3 = temp3>>6 + and r11, r14, #0x1 @ if (temp4 & 0x1) + cmp r11, #0x1 + bne LOOP_HEIGHT_256_GET_TILED_EVEN +LOOP_HEIGHT_256_GET_TILED_ODD: + sub r7, r14, #1 @ tiled_offset = temp4-1 + add r10, r2, #127 @ temp1 = ((yuv420_width+127)>>7)<<7 + bic r10, r10, #0x7F + mov r10, r10, asr #6 @ tiled_offset = tiled_offset*(temp1>>6) + mul r7, r7, r10 + add r7, r7, r12 @ tiled_offset = tiled_offset+temp3 + add r7, r7, #2 @ tiled_offset = tiled_offset+2 + bic r10, r12, #0x3 @ temp1 = (temp3>>2)<<2 + add r7, r7, r10 @ tiled_offset = tiled_offset+temp1 + mov r7, r7, lsl #11 @ tiled_offset = tiled_offset<<11 + add r8, r7, #4096 @ tiled_offset1 = tiled_offset+2048*2 + mov r14, #8 + b LOOP_HEIGHT_256_GET_TILED_END + +LOOP_HEIGHT_256_GET_TILED_EVEN: + add r11, r3, #31 @ temp2 = ((yuv420_height+31)>>5)<<5 + bic r11, r11, #0x1F + add r10, r5, #32 @ if ((i+32)>2)<<2 + add r7, r12, r10 @ tiled_offset = temp3+temp1@ + add r10, r2, #127 @ temp1 = ((yuv420_width+127)>>7)<<7 + bic r10, r10, #0x7F + mov r10, r10, asr #6 @ tiled_offset = tiled_offset+temp4*(temp1>>6) + mla r7, r14, r10, r7 + mov r7, r7, lsl #11 @ tiled_offset = tiled_offset<<11 + add r8, r7, #12288 @ tiled_offset1 = tiled_offset+2048*6 + mov r14, #8 + b LOOP_HEIGHT_256_GET_TILED_END + +LOOP_HEIGHT_256_GET_TILED_EVEN1: + add r10, r2, #127 @ temp1 = ((yuv420_width+127)>>7)<<7 + bic r10, r10, #0x7F + mov r10, r10, asr #6 @ tiled_offset = temp4*(temp1>>6) + mul r7, r14, r10 + add r7, r7, r12 @ tiled_offset = tiled_offset+temp3 + mov r7, r7, lsl #11 @ tiled_offset = tiled_offset<<11 + add r8, r7, #4096 @ tiled_offset1 = tiled_offset+2048*2 + mov r14, #4 + +LOOP_HEIGHT_256_GET_TILED_END: + + ldr r12, [sp, #48] @ right + ldr r9, [sp, #44] @ top + and r10, r5, #0x1F @ temp1 = i&0x1F + add r7, r7, r10, lsl #6 @ tiled_offset = tiled_offset+64*(temp1) + add r8, r8, r10, lsl #6 @ tiled_offset1 = tiled_offset1+64*(temp1) + sub r11, r2, r6 @ temp2 = yuv420_width-left(==j)-right + sub r11, r11, r12 + sub r9, r5, r9 @ linear_offset = temp2*(i-top)@ + mul r9, r11, r9 + add r12, r6, #256 @ temp3 = ((j+256)>>8)<<8@ + bic r12, r12, #0xFF + sub r12, r12, r6 @ temp3 = temp3-j@ + and r10, r6, #0x3F @ temp1 = left(==j)&0x3F + + cmp r12, #192 @ if (temp3 > 192) + ble LOOP_HEIGHT_256_LEFT_192 + add r11, r1, r7 @ r11 = nv12t_src+tiled_offset+temp1 + add r11, r11, r10 + pld [r11] + add r12, r1, r7 @ r12 = nv12t_src+tiled_offset+2048 + pld [r11, #32] + add r12, r12, #2048 + pld [r12] + cmp r10, #0 + pld [r12, #32] + stmnefd sp!, {r9-r12, r14} @ backup registers + rsbne r10, r10, #64 + blne MEMCOPY_UNDER_64 + ldmnefd sp!, {r9-r12, r14} @ restore registers + bne LOOP_HEIGHT_256_LEFT_256_64 + vld1.8 {q0, q1}, [r11]! @ load {nv12t_src+tiled_offset+temp1, 64} + vld1.8 {q2, q3}, [r11] + add r11, r0, r9 @ r11 = yuv420_dest+linear_offset + vst1.8 {q0, q1}, [r11]! @ store {yuv420_dest+linear_offset, 64} + vst1.8 {q2, q3}, [r11]! +LOOP_HEIGHT_256_LEFT_256_64: + add r11, r1, r8 @ r11 = nv12t_src+tiled_offset1 + pld [r11] + vld1.8 {q4, q5}, [r12]! @ load {nv12t_src+tiled_offset+2048, 64} + pld [r11, #32] + vld1.8 {q6, q7}, [r12] + add r12, r11, #2048 @ r12 = nv12t_src+tiled_offset1+2048 + pld [r12] + vld1.8 {q8, q9}, [r11]! @ load {nv12t_src+tiled_offset1, 64} + pld [r12, #32] + vld1.8 {q10, q11}, [r11] + vld1.8 {q12, q13}, [r12]! @ load {nv12t_src+tiled_offset1+2048, 64} + vld1.8 {q14, q15}, [r12] + + sub r11, r0, r10 @ r11 = yuv420_dest+linear_offset+64-temp1 + add r12, r9, #64 + add r11, r11, r12 + + vst1.8 {q4, q5}, [r11]! @ store {yuv420_dest+linear_offset+64-temp1, 64} + vst1.8 {q6, q7}, [r11]! + vst1.8 {q8, q9}, [r11]! @ store {yuv420_dest+linear_offset+128-temp1, 64} + vst1.8 {q10, q11}, [r11]! + vst1.8 {q12, q13}, [r11]! @ store {yuv420_dest+linear_offset+192-temp1, 64} + vst1.8 {q14, q15}, [r11]! + + add r9, r9, #256 + sub r9, r9, r10 + b LOOP_HEIGHT_256_LEFT_END + +LOOP_HEIGHT_256_LEFT_192: + cmp r12, #128 @ if (temp3 > 128) + ble LOOP_HEIGHT_256_LEFT_128 + add r11, r1, r7 @ r11 = nv12t_src+tiled_offset+2048+temp1 + add r11, r11, r10 + add r11, r11, #2048 + pld [r11] + add r12, r1, r8 @ r12 = nv12t_src+tiled_offset1 + pld [r11, #32] + cmp r10, #0 + pld [r12] + stmnefd sp!, {r9-r12, r14} @ backup registers + pld [r12, #32] + rsbne r10, r10, #64 + blne MEMCOPY_UNDER_64 + ldmnefd sp!, {r9-r12, r14} @ restore registers + bne LOOP_HEIGHT_256_LEFT_192_64 + vld1.8 {q0, q1}, [r11]! @ load {nv12t_src+tiled_offset+2048+temp1, 64} + vld1.8 {q2, q3}, [r11] + add r11, r0, r9 @ r11 = yuv420_dest+linear_offset + vst1.8 {q0, q1}, [r11]! @ store {yuv420_dest+linear_offset, 64} + vst1.8 {q2, q3}, [r11]! +LOOP_HEIGHT_256_LEFT_192_64: + add r11, r1, r8 @ r11 = nv12t_src+tiled_offset1+2048 + add r11, r11, #2048 + pld [r11] + vld1.8 {q4, q5}, [r12]! @ load {nv12t_src+tiled_offset1, 64} + pld [r11, #32] + vld1.8 {q6, q7}, [r12] + vld1.8 {q8, q9}, [r11]! @ load {nv12t_src+tiled_offset1+2048, 64} + vld1.8 {q10, q11}, [r11] + + sub r11, r0, r10 @ r11 = yuv420_dest+linear_offset+64-temp1 + add r12, r9, #64 + add r11, r11, r12 + + vst1.8 {q4, q5}, [r11]! @ store {yuv420_dest+linear_offset+64-temp1, 64} + vst1.8 {q6, q7}, [r11]! + vst1.8 {q8, q9}, [r11]! @ store {yuv420_dest+linear_offset+128-temp1, 64} + vst1.8 {q10, q11}, [r11]! + + add r9, r9, #192 + sub r9, r9, r10 + b LOOP_HEIGHT_256_LEFT_END + +LOOP_HEIGHT_256_LEFT_128: + cmp r12, #64 @ if (temp3 > 64) + ble LOOP_HEIGHT_256_LEFT_64 + add r11, r1, r8 @ r11 = nv12t_src+tiled_offset1+temp1 + add r11, r11, r10 + pld [r11] + add r12, r1, r8 @ r12 = nv12t_src+tiled_offset1 + add r12, r12, #2048 + pld [r11, #32] + cmp r10, #0 + pld [r12] + stmnefd sp!, {r9-r12, r14} @ backup registers + pld [r12, #32] + rsbne r10, r10, #64 + blne MEMCOPY_UNDER_64 + ldmnefd sp!, {r9-r12, r14} @ restore registers + bne LOOP_HEIGHT_256_LEFT_128_64 + vld1.8 {q0, q1}, [r11]! @ load {nv12t_src+tiled_offset1+temp1, 64} + vld1.8 {q2, q3}, [r11] + add r11, r0, r9 @ r11 = yuv420_dest+linear_offset + vst1.8 {q0, q1}, [r11]! @ store {yuv420_dest+linear_offset, 64} + vst1.8 {q2, q3}, [r11]! +LOOP_HEIGHT_256_LEFT_128_64: + vld1.8 {q4, q5}, [r12]! @ load {nv12t_src+tiled_offset1, 64} + vld1.8 {q6, q7}, [r12] + + sub r11, r0, r10 @ r11 = yuv420_dest+linear_offset+64-temp1 + add r12, r9, #64 + add r11, r11, r12 + + vst1.8 {q4, q5}, [r11]! @ store {yuv420_dest+linear_offset+64-temp1, 64} + vst1.8 {q6, q7}, [r11]! + + add r9, r9, #128 + sub r9, r9, r10 + b LOOP_HEIGHT_256_LEFT_END + +LOOP_HEIGHT_256_LEFT_64: + add r11, r1, r8 @ r11 = nv12t_src+tiled_offset1+2048+temp1 + add r11, r11, #2048 + add r11, r11, r10 + cmp r10, #0 + pld [r11] + stmnefd sp!, {r9-r12, r14} @ backup registers + pld [r11, #32] + rsbne r10, r10, #64 + blne MEMCOPY_UNDER_64 + ldmnefd sp!, {r9-r12, r14} @ restore registers + bne LOOP_HEIGHT_256_LEFT_64_64 + vld1.8 {q0, q1}, [r11]! @ load {nv12t_src+tiled_offset1+temp1, 64} + vld1.8 {q2, q3}, [r11] + add r11, r0, r9 @ r11 = yuv420_dest+linear_offset + vst1.8 {q0, q1}, [r11]! @ store {yuv420_dest+linear_offset, 64} + vst1.8 {q2, q3}, [r11]! +LOOP_HEIGHT_256_LEFT_64_64: + add r9, r9, #64 + sub r9, r9, r10 + +LOOP_HEIGHT_256_LEFT_END: + + ldr r12, [sp, #48] @ right + add r7, r7, r14, lsl #11 @ tiled_offset = tiled_offset+temp4*2048 + add r10, r1, r7 @ r10 = nv12t_src+tiled_offset + pld [r10] + bic r6, r6, #0xFF @ j = (left>>8)<<8 + pld [r10, #32] + add r6, r6, #256 @ j = j + 256 + sub r11, r2, r12 @ temp2 = yuv420_width-right-256 + sub r11, r11, #256 + cmp r6, r11 + bgt LOOP_HEIGHT_256_WIDTH_END + +LOOP_HEIGHT_256_WIDTH: + add r12, r10, #2048 @ r12 = nv12t_src+tiled_offset+2048 + pld [r12] + vld1.8 {q0, q1}, [r10]! @ load {nv12t_src+tiled_offset, 64} + pld [r12, #32] + vld1.8 {q2, q3}, [r10] + + add r8, r8, r14, lsl #11 @ tiled_offset1 = tiled_offset1+temp4*2048 + add r10, r1, r8 @ r10 = nv12t_src+tiled_offset1 + pld [r10] + vld1.8 {q4, q5}, [r12]! @ load {nv12t_src+tiled_offset+2048, 64} + pld [r10, #32] + vld1.8 {q6, q7}, [r12] + + add r12, r10, #2048 @ r12 = nv12t_src+tiled_offset+2048 + pld [r12] + vld1.8 {q8, q9}, [r10]! @ load {nv12t_src+tiled_offset+2048, 64} + pld [r12, #32] + vld1.8 {q10, q11}, [r10] + + add r7, r7, r14, lsl #11 @ tiled_offset = tiled_offset+temp4*2048 + add r10, r1, r7 + pld [r10] + vld1.8 {q12, q13}, [r12]! @ load {nv12t_src+tiled_offset+2048, 64} + pld [r10, #32] + vld1.8 {q14, q15}, [r12] + + add r12, r0, r9 @ r12 = yuv420_dest+linear_offset + vst1.8 {q0, q1}, [r12]! + vst1.8 {q2, q3}, [r12]! + vst1.8 {q4, q5}, [r12]! + vst1.8 {q6, q7}, [r12]! + vst1.8 {q8, q9}, [r12]! + vst1.8 {q10, q11}, [r12]! + vst1.8 {q12, q13}, [r12]! + vst1.8 {q14, q15}, [r12]! + add r9, r9, #256 @ linear_offset = linear_offset+256 + + add r12, r10, #2048 @ r12 = nv12t_src+tiled_offset+2048 + + add r6, r6, #256 @ j=j+256 + cmp r6, r11 @ j<=temp2 + ble LOOP_HEIGHT_256_WIDTH + +LOOP_HEIGHT_256_WIDTH_END: + + add r8, r8, r14, lsl #11 @ tiled_offset1 = tiled_offset1+temp4*2048 + ldr r14, [sp, #48] @ right + sub r11, r2, r6 @ temp2 = yuv420_width-right-j + sub r11, r11, r14 + cmp r11, #0 + beq LOOP_HEIGHT_256_RIGHT_END + cmp r11, #192 + ble LOOP_HEIGHT_256_RIGHT_192 + add r12, r10, #2048 + pld [r12] + vld1.8 {q0, q1}, [r10]! @ load {nv12t_src+tiled_offset} + pld [r12, #32] + vld1.8 {q2, q3}, [r10] + + add r10, r1, r8 @ r10 = nv12t_src+tiled_offset1 + pld [r10] + vld1.8 {q4, q5}, [r12]! @ load {nv12t_src+tiled_offset+2048} + pld [r10, #32] + vld1.8 {q6, q7}, [r12] + + add r14, r10, #2048 @ r10 = nv12t_src+tiled_offset1+2048 + pld [r14] + vld1.8 {q8, q9}, [r10]! @ load {nv12t_src+tiled_offset1} + pld [r14, #32] + vld1.8 {q10, q11}, [r10] + + add r12, r0, r9 @ r12 = yuv420_dest+linear_offset + vst1.8 {q0, q1}, [r12]! + vst1.8 {q2, q3}, [r12]! + vst1.8 {q4, q5}, [r12]! + vst1.8 {q6, q7}, [r12]! + vst1.8 {q8, q9}, [r12]! + vst1.8 {q10, q11}, [r12]! + add r9, r9, #192 @ linear_offset = linear_offset+192 + + stmfd sp!, {r9-r12, r14} @ backup registers + sub r10, r11, #192 + mov r11, r14 + bl MEMCOPY_UNDER_64 + ldmfd sp!, {r9-r12, r14} @ restore registers + b LOOP_HEIGHT_256_RIGHT_END + +LOOP_HEIGHT_256_RIGHT_192: + cmp r11, #128 + ble LOOP_HEIGHT_256_RIGHT_128 + add r12, r10, #2048 + pld [r12] + vld1.8 {q0, q1}, [r10]! @ load {nv12t_src+tiled_offset} + pld [r12, #32] + vld1.8 {q2, q3}, [r10] + + add r14, r1, r8 @ r10 = nv12t_src+tiled_offset1 + pld [r14] + vld1.8 {q4, q5}, [r12]! @ load {nv12t_src+tiled_offset+2048} + pld [r14, #32] + vld1.8 {q6, q7}, [r12] + + add r12, r0, r9 @ r12 = yuv420_dest+linear_offset + vst1.8 {q0, q1}, [r12]! + vst1.8 {q2, q3}, [r12]! + vst1.8 {q4, q5}, [r12]! + vst1.8 {q6, q7}, [r12]! + add r9, r9, #128 @ linear_offset = linear_offset+128 + + stmfd sp!, {r9-r12, r14} @ backup registers + sub r10, r11, #128 + mov r11, r14 + bl MEMCOPY_UNDER_64 + ldmfd sp!, {r9-r12, r14} @ restore registers + b LOOP_HEIGHT_256_RIGHT_END + +LOOP_HEIGHT_256_RIGHT_128: + cmp r11, #64 + ble LOOP_HEIGHT_256_RIGHT_64 + add r14, r10, #2048 + pld [r14] + vld1.8 {q0, q1}, [r10]! @ load {nv12t_src+tiled_offset} + pld [r14, #32] + vld1.8 {q2, q3}, [r10] + + add r12, r0, r9 @ r12 = yuv420_dest+linear_offset + vst1.8 {q0, q1}, [r12]! + vst1.8 {q2, q3}, [r12]! + add r9, r9, #64 @ linear_offset = linear_offset+64 + + stmfd sp!, {r9-r12, r14} @ backup registers + sub r10, r11, #64 + mov r11, r14 + bl MEMCOPY_UNDER_64 + ldmfd sp!, {r9-r12, r14} @ restore registers + b LOOP_HEIGHT_256_RIGHT_END + +LOOP_HEIGHT_256_RIGHT_64: + stmfd sp!, {r9-r12, r14} @ backup registers + mov r14, r11 + mov r11, r10 + mov r10, r14 + bl MEMCOPY_UNDER_64 + ldmfd sp!, {r9-r12, r14} @ restore registers + +LOOP_HEIGHT_256_RIGHT_END: + + ldr r14, [sp, #52] @ buttom + add r5, r5, #1 @ i=i+1 + sub r14, r3, r14 @ i= 64) + blt LOOP_HEIGHT_2_START + + ldr r5, [sp, #44] @ i = top +LOOP_HEIGHT_64: + ldr r6, [sp, #40] @ j = left + stmfd sp!, {r0-r3, r12} @ backup parameters + mov r0, r2 + mov r1, r3 + mov r2, r6 + mov r3, r5 + bl tile_4x2_read_asm + mov r7, r0 + ldmfd sp!, {r0-r3, r12} @ restore parameters + ldr r9, [sp, #44] @ linear_offset = top + add r11, r6, #64 @ temp2 = ((j+64)>>6)<<6 + bic r11, r11, #0x3F + sub r11, r11, r6 @ temp2 = temp2-j + sub r9, r5, r9 @ linear_offset = temp1*(i-top) + mul r9, r9, r10 + and r14, r6, #0x3 @ temp4 = j&0x3 + add r7, r7, r14 @ tiled_offset = tiled_offset+temp4 + stmfd sp!, {r9-r12} @ backup parameters + mov r10, r11 + add r11, r1, r7 + bl MEMCOPY_UNDER_64 + ldmfd sp!, {r9-r12} @ restore parameters + add r9, r9, r11 @ linear_offset = linear_offset+temp2 + add r6, r6, r11 @ j = j+temp2@ + + add r14, r6, #64 + cmp r14, r12 + bgt LOOP_HEIGHT_64_1 + stmfd sp!, {r0-r3, r12} @ backup parameters + mov r0, r2 + mov r1, r3 + mov r2, r6 + mov r3, r5 + bl tile_4x2_read_asm + mov r7, r0 + ldmfd sp!, {r0-r3, r12} @ restore parameters + add r7, r1, r7 + vld1.8 {q0, q1}, [r7]! + vld1.8 {q2, q3}, [r7] + add r7, r0, r9 + vst1.8 {q0, q1}, [r7]! + vst1.8 {q2, q3}, [r7] + add r9, r9, #64 + add r6, r6, #64 + +LOOP_HEIGHT_64_1: + add r14, r6, #64 + cmp r14, r12 + bgt LOOP_HEIGHT_64_2 + stmfd sp!, {r0-r3, r12} @ backup parameters + mov r0, r2 + mov r1, r3 + mov r2, r6 + mov r3, r5 + bl tile_4x2_read_asm + mov r7, r0 + ldmfd sp!, {r0-r3, r12} @ restore parameters + add r7, r1, r7 + vld1.8 {q0, q1}, [r7]! + vld1.8 {q2, q3}, [r7] + add r7, r0, r9 + vst1.8 {q0, q1}, [r7]! + vst1.8 {q2, q3}, [r7] + add r9, r9, #64 + add r6, r6, #64 + +LOOP_HEIGHT_64_2: + cmp r6, r12 + bge LOOP_HEIGHT_64_3 + stmfd sp!, {r0-r3, r12} @ backup parameters + mov r0, r2 + mov r1, r3 + mov r2, r6 + mov r3, r5 + bl tile_4x2_read_asm + mov r7, r0 + ldmfd sp!, {r0-r3, r12} @ restore parameters + sub r11, r12, r6 + stmfd sp!, {r9-r12} @ backup parameters + mov r10, r11 + add r11, r1, r7 + bl MEMCOPY_UNDER_64 + ldmfd sp!, {r9-r12} @ restore parameters + +LOOP_HEIGHT_64_3: + + ldr r14, [sp, #52] @ buttom + add r5, r5, #1 @ i=i+1 + sub r14, r3, r14 @ i>6)<<6 + bic r11, r11, #0x3F + sub r11, r11, r6 @ temp2 = temp2-j + sub r9, r5, r9 @ linear_offset = temp1*(i-top) + mul r9, r10, r9 + add r9, r0, r9 @ linear_offset = linear_dst+linear_offset +LOOP_HEIGHT_2_WIDTH: + stmfd sp!, {r0-r3, r12} @ backup parameters + mov r0, r2 + mov r1, r3 + mov r2, r6 + mov r3, r5 + bl tile_4x2_read_asm + mov r7, r0 + ldmfd sp!, {r0-r3, r12} @ restore parameters + + and r14, r6, #0x3 @ temp4 = j&0x3@ + add r7, r7, r14 @ tiled_offset = tiled_offset+temp4@ + add r7, r1, r7 + + ldrh r14, [r7] + strh r14, [r9], #2 + + ldr r14, [sp, #48] @ right + add r6, r6, #2 @ j=j+2 + sub r14, r2, r14 @ j= 256) + blt LOOP_HEIGHT_64_START + + ldr r5, [sp, #48] @ top +LOOP_HEIGHT_256: + ldr r6, [sp, #44] @ j = left + mov r14, r5, asr #5 @ temp4 = i>>5 + bic r12, r6, #0xFF @ temp3 = (j>>8)<<8 + mov r12, r12, asr #6 @ temp3 = temp3>>6 + and r11, r14, #0x1 @ if (temp4 & 0x1) + cmp r11, #0x1 + bne LOOP_HEIGHT_256_GET_TILED_EVEN +LOOP_HEIGHT_256_GET_TILED_ODD: + sub r7, r14, #1 @ tiled_offset = temp4-1 + add r10, r3, #127 @ temp1 = ((yuv420_width+127)>>7)<<7 + bic r10, r10, #0x7F + mov r10, r10, asr #6 @ tiled_offset = tiled_offset*(temp1>>6) + mul r7, r7, r10 + add r7, r7, r12 @ tiled_offset = tiled_offset+temp3 + add r7, r7, #2 @ tiled_offset = tiled_offset+2 + bic r10, r12, #0x3 @ temp1 = (temp3>>2)<<2 + add r7, r7, r10 @ tiled_offset = tiled_offset+temp1 + mov r7, r7, lsl #11 @ tiled_offset = tiled_offset<<11 + add r8, r7, #4096 @ tiled_offset1 = tiled_offset+2048*2 + mov r14, #8 + b LOOP_HEIGHT_256_GET_TILED_END + +LOOP_HEIGHT_256_GET_TILED_EVEN: + add r11, r4, #31 @ temp2 = ((yuv420_height+31)>>5)<<5 + bic r11, r11, #0x1F + add r10, r5, #32 @ if ((i+32)>2)<<2 + add r7, r12, r10 @ tiled_offset = temp3+temp1@ + add r10, r3, #127 @ temp1 = ((yuv420_width+127)>>7)<<7 + bic r10, r10, #0x7F + mov r10, r10, asr #6 @ tiled_offset = tiled_offset+temp4*(temp1>>6) + mla r7, r14, r10, r7 + mov r7, r7, lsl #11 @ tiled_offset = tiled_offset<<11 + add r8, r7, #12288 @ tiled_offset1 = tiled_offset+2048*6 + mov r14, #8 + b LOOP_HEIGHT_256_GET_TILED_END + +LOOP_HEIGHT_256_GET_TILED_EVEN1: + add r10, r3, #127 @ temp1 = ((yuv420_width+127)>>7)<<7 + bic r10, r10, #0x7F + mov r10, r10, asr #6 @ tiled_offset = temp4*(temp1>>6) + mul r7, r14, r10 + add r7, r7, r12 @ tiled_offset = tiled_offset+temp3 + mov r7, r7, lsl #11 @ tiled_offset = tiled_offset<<11 + add r8, r7, #4096 @ tiled_offset1 = tiled_offset+2048*2 + mov r14, #4 + +LOOP_HEIGHT_256_GET_TILED_END: + + ldr r12, [sp, #52] @ right + ldr r9, [sp, #48] @ top + and r10, r5, #0x1F @ temp1 = i&0x1F + add r7, r7, r10, lsl #6 @ tiled_offset = tiled_offset+64*(temp1) + add r8, r8, r10, lsl #6 @ tiled_offset1 = tiled_offset1+64*(temp1) + sub r11, r3, r6 @ temp2 = yuv420_width-left(==j)-right + sub r11, r11, r12 + sub r9, r5, r9 @ linear_offset = temp2*(i-top)/2@ + mul r9, r11, r9 + mov r9, r9, asr #1 + add r12, r6, #256 @ temp3 = ((j+256)>>8)<<8@ + bic r12, r12, #0xFF + sub r12, r12, r6 @ temp3 = temp3-j@ + and r10, r6, #0x3F @ temp1 = left(==j)&0x3F + + cmp r12, #192 @ if (temp3 > 192) + ble LOOP_HEIGHT_256_LEFT_192 + add r11, r2, r7 @ r11 = nv12t_src+tiled_offset+temp1 + add r11, r11, r10 + pld [r11] + add r12, r2, r7 @ r12 = nv12t_src+tiled_offset+2048 + pld [r11, #32] + add r12, r12, #2048 + pld [r12] + cmp r10, #0 + pld [r12, #32] + stmnefd sp!, {r8-r12, r14} @ backup registers + rsbne r10, r10, #64 + blne INTERLEAVED_MEMCOPY_UNDER_64 + ldmnefd sp!, {r8-r12, r14} @ restore registers + bne LOOP_HEIGHT_256_LEFT_256_64 + vld2.8 {q0, q1}, [r11]! @ load {nv12t_src+tiled_offset+temp1, 64} + vld2.8 {q2, q3}, [r11] + add r11, r0, r9 @ r11 = yuv420_u_dest+linear_offset + vst1.8 {q0}, [r11]! + vst1.8 {q2}, [r11]! + add r11, r1, r9 @ r11 = yuv420_v_dest+linear_offset + vst1.8 {q1}, [r11]! + vst1.8 {q3}, [r11]! +LOOP_HEIGHT_256_LEFT_256_64: + add r11, r2, r8 @ r11 = nv12t_src+tiled_offset1 + pld [r11] + vld2.8 {q4, q5}, [r12]! @ load {nv12t_src+tiled_offset+2048, 64} + pld [r11, #32] + vld2.8 {q6, q7}, [r12] + add r12, r11, #2048 @ r12 = nv12t_src+tiled_offset1+2048 + pld [r12] + vld2.8 {q8, q9}, [r11]! @ load {nv12t_src+tiled_offset1, 64} + pld [r12, #32] + vld2.8 {q10, q11}, [r11] + vld2.8 {q12, q13}, [r12]! @ load {nv12t_src+tiled_offset1+2048, 64} + vld2.8 {q14, q15}, [r12] + + add r11, r0, r9 @ r11 = yuv420_u_dest+linear_offset+32-temp1/2 + add r11, r11, #32 + sub r11, r11, r10, asr #1 + vst1.8 {q4}, [r11]! + vst1.8 {q6}, [r11]! + vst1.8 {q8}, [r11]! + vst1.8 {q10}, [r11]! + vst1.8 {q12}, [r11]! + vst1.8 {q14}, [r11]! + + add r11, r1, r9 @ r11 = yuv420_v_dest+linear_offset+32-temp1/2 + add r11, r11, #32 + sub r11, r11, r10, asr #1 + vst1.8 {q5}, [r11]! + vst1.8 {q7}, [r11]! + vst1.8 {q9}, [r11]! + vst1.8 {q11}, [r11]! + vst1.8 {q13}, [r11]! + vst1.8 {q15}, [r11]! + + add r9, r9, #128 + sub r9, r9, r10, asr #1 + b LOOP_HEIGHT_256_LEFT_END + +LOOP_HEIGHT_256_LEFT_192: + cmp r12, #128 @ if (temp3 > 128) + ble LOOP_HEIGHT_256_LEFT_128 + add r11, r2, r7 @ r11 = nv12t_src+tiled_offset+2048+temp1 + add r11, r11, r10 + add r11, r11, #2048 + pld [r11] + add r12, r2, r8 @ r12 = nv12t_src+tiled_offset1 + pld [r11, #32] + cmp r10, #0 + pld [r12] + stmnefd sp!, {r8-r12, r14} @ backup registers + pld [r12, #32] + rsbne r10, r10, #64 + blne INTERLEAVED_MEMCOPY_UNDER_64 + ldmnefd sp!, {r8-r12, r14} @ restore registers + bne LOOP_HEIGHT_256_LEFT_192_64 + vld2.8 {q0, q1}, [r11]! @ load {nv12t_src+tiled_offset+2048+temp1, 64} + vld2.8 {q2, q3}, [r11] + add r11, r0, r9 @ r11 = yuv420_u_dest+linear_offset + vst1.8 {q0}, [r11]! + vst1.8 {q2}, [r11]! + add r11, r1, r9 @ r11 = yuv420_v_dest+linear_offset + vst1.8 {q1}, [r11]! + vst1.8 {q3}, [r11]! +LOOP_HEIGHT_256_LEFT_192_64: + add r11, r2, r8 @ r11 = nv12t_src+tiled_offset1+2048 + add r11, r11, #2048 + pld [r11] + vld2.8 {q4, q5}, [r12]! @ load {nv12t_src+tiled_offset1, 64} + pld [r11, #32] + vld2.8 {q6, q7}, [r12] + vld2.8 {q8, q9}, [r11]! @ load {nv12t_src+tiled_offset1+2048, 64} + vld2.8 {q10, q11}, [r11] + + add r11, r0, r9 @ r11 = yuv420_u_dest+linear_offset+32-temp1/2 + add r11, r11, #32 + sub r11, r11, r10, asr #1 + vst1.8 {q4}, [r11]! + vst1.8 {q6}, [r11]! + vst1.8 {q8}, [r11]! + vst1.8 {q10}, [r11]! + + add r11, r1, r9 @ r11 = yuv420_v_dest+linear_offset+32-temp1/2 + add r11, r11, #32 + sub r11, r11, r10, asr #1 + vst1.8 {q5}, [r11]! + vst1.8 {q7}, [r11]! + vst1.8 {q9}, [r11]! + vst1.8 {q11}, [r11]! + + add r9, r9, #96 + sub r9, r9, r10, asr #1 + b LOOP_HEIGHT_256_LEFT_END + +LOOP_HEIGHT_256_LEFT_128: + cmp r12, #64 @ if (temp3 > 64) + ble LOOP_HEIGHT_256_LEFT_64 + add r11, r2, r8 @ r11 = nv12t_src+tiled_offset1+temp1 + add r11, r11, r10 + pld [r11] + add r12, r2, r8 @ r12 = nv12t_src+tiled_offset1 + add r12, r12, #2048 + pld [r11, #32] + cmp r10, #0 + pld [r12] + stmnefd sp!, {r8-r12, r14} @ backup registers + pld [r12, #32] + rsbne r10, r10, #64 + blne INTERLEAVED_MEMCOPY_UNDER_64 + ldmnefd sp!, {r8-r12, r14} @ restore registers + bne LOOP_HEIGHT_256_LEFT_128_64 + vld2.8 {q0, q1}, [r11]! @ load {nv12t_src+tiled_offset1+temp1, 64} + vld2.8 {q2, q3}, [r11] + add r11, r0, r9 @ r11 = yuv420_u_dest+linear_offset + vst1.8 {q0}, [r11]! + vst1.8 {q2}, [r11]! + add r11, r1, r9 @ r11 = yuv420_v_dest+linear_offset + vst1.8 {q1}, [r11]! + vst1.8 {q3}, [r11]! +LOOP_HEIGHT_256_LEFT_128_64: + vld2.8 {q4, q5}, [r12]! @ load {nv12t_src+tiled_offset1, 64} + vld2.8 {q6, q7}, [r12] + + add r11, r0, r9 @ r11 = yuv420_u_dest+linear_offset+32-temp1/2 + add r11, r11, #32 + sub r11, r11, r10, asr #1 + vst1.8 {q4}, [r11]! + vst1.8 {q6}, [r11]! + + add r11, r1, r9 @ r11 = yuv420_v_dest+linear_offset+32-temp1/2 + add r11, r11, #32 + sub r11, r11, r10, asr #1 + vst1.8 {q5}, [r11]! + vst1.8 {q7}, [r11]! + + add r9, r9, #64 + sub r9, r9, r10, asr #1 + b LOOP_HEIGHT_256_LEFT_END + +LOOP_HEIGHT_256_LEFT_64: + add r11, r2, r8 @ r11 = nv12t_src+tiled_offset1+2048+temp1 + add r11, r11, #2048 + add r11, r11, r10 + cmp r10, #0 + pld [r11] + stmnefd sp!, {r8-r12, r14} @ backup registers + pld [r11, #32] + rsbne r10, r10, #64 + blne INTERLEAVED_MEMCOPY_UNDER_64 + ldmnefd sp!, {r8-r12, r14} @ restore registers + bne LOOP_HEIGHT_256_LEFT_64_64 + vld2.8 {q0, q1}, [r11]! @ load {nv12t_src+tiled_offset1+temp1, 64} + vld2.8 {q2, q3}, [r11] + add r11, r0, r9 @ r11 = yuv420_dest+linear_offset + vst1.8 {q0, q1}, [r11]! @ store {yuv420_dest+linear_offset, 64} + vst1.8 {q2, q3}, [r11]! +LOOP_HEIGHT_256_LEFT_64_64: + add r9, r9, #32 + sub r9, r9, r10, asr #1 + +LOOP_HEIGHT_256_LEFT_END: + + ldr r12, [sp, #52] @ right + add r7, r7, r14, lsl #11 @ tiled_offset = tiled_offset+temp4*2048 + add r10, r2, r7 @ r10 = nv12t_src+tiled_offset + pld [r10] + bic r6, r6, #0xFF @ j = (left>>8)<<8 + pld [r10, #32] + add r6, r6, #256 @ j = j + 256 + sub r11, r3, r12 @ temp2 = yuv420_width-right-256 + sub r11, r11, #256 + cmp r6, r11 + bgt LOOP_HEIGHT_256_WIDTH_END + +LOOP_HEIGHT_256_WIDTH: + add r12, r10, #2048 @ r12 = nv12t_src+tiled_offset+2048 + pld [r12] + vld2.8 {q0, q1}, [r10]! @ load {nv12t_src+tiled_offset, 64} + pld [r12, #32] + vld2.8 {q2, q3}, [r10] + + add r8, r8, r14, lsl #11 @ tiled_offset1 = tiled_offset1+temp4*2048 + add r10, r2, r8 @ r10 = nv12t_src+tiled_offset1 + pld [r10] + vld2.8 {q4, q5}, [r12]! @ load {nv12t_src+tiled_offset+2048, 64} + pld [r10, #32] + vld2.8 {q6, q7}, [r12] + + add r12, r10, #2048 @ r12 = nv12t_src+tiled_offset+2048 + pld [r12] + vld2.8 {q8, q9}, [r10]! @ load {nv12t_src+tiled_offset+2048, 64} + pld [r12, #32] + vld2.8 {q10, q11}, [r10] + + add r7, r7, r14, lsl #11 @ tiled_offset = tiled_offset+temp4*2048 + add r10, r2, r7 + pld [r10] + vld2.8 {q12, q13}, [r12]! @ load {nv12t_src+tiled_offset+2048, 64} + pld [r10, #32] + vld2.8 {q14, q15}, [r12] + + add r12, r0, r9 @ r12 = yuv420_u_dest+linear_offset + vst1.8 {q0}, [r12]! + vst1.8 {q2}, [r12]! + vst1.8 {q4}, [r12]! + vst1.8 {q6}, [r12]! + vst1.8 {q8}, [r12]! + vst1.8 {q10}, [r12]! + vst1.8 {q12}, [r12]! + vst1.8 {q14}, [r12]! + add r12, r1, r9 @ r12 = yuv420_v_dest+linear_offset + vst1.8 {q1}, [r12]! + vst1.8 {q3}, [r12]! + vst1.8 {q5}, [r12]! + vst1.8 {q7}, [r12]! + vst1.8 {q9}, [r12]! + vst1.8 {q11}, [r12]! + vst1.8 {q13}, [r12]! + vst1.8 {q15}, [r12]! + add r9, r9, #128 @ linear_offset = linear_offset+128 + + add r12, r10, #2048 @ r12 = nv12t_src+tiled_offset+2048 + + add r6, r6, #256 @ j=j+256 + cmp r6, r11 @ j<=temp2 + ble LOOP_HEIGHT_256_WIDTH + +LOOP_HEIGHT_256_WIDTH_END: + + add r8, r8, r14, lsl #11 @ tiled_offset1 = tiled_offset1+temp4*2048 + ldr r14, [sp, #52] @ right + sub r11, r3, r6 @ temp2 = yuv420_width-right-j + sub r11, r11, r14 + cmp r11, #0 + beq LOOP_HEIGHT_256_RIGHT_END + cmp r11, #192 + ble LOOP_HEIGHT_256_RIGHT_192 + add r12, r10, #2048 + pld [r12] + vld2.8 {q0, q1}, [r10]! @ load {nv12t_src+tiled_offset} + pld [r12, #32] + vld2.8 {q2, q3}, [r10] + + add r10, r2, r8 @ r10 = nv12t_src+tiled_offset1 + pld [r10] + vld2.8 {q4, q5}, [r12]! @ load {nv12t_src+tiled_offset+2048} + pld [r10, #32] + vld2.8 {q6, q7}, [r12] + + add r14, r10, #2048 @ r10 = nv12t_src+tiled_offset1+2048 + pld [r14] + vld2.8 {q8, q9}, [r10]! @ load {nv12t_src+tiled_offset1} + pld [r14, #32] + vld2.8 {q10, q11}, [r10] + + add r12, r0, r9 @ r12 = yuv420_u_dest+linear_offset + vst1.8 {q0}, [r12]! + vst1.8 {q2}, [r12]! + vst1.8 {q4}, [r12]! + vst1.8 {q6}, [r12]! + vst1.8 {q8}, [r12]! + vst1.8 {q10}, [r12]! + add r12, r1, r9 @ r12 = yuv420_v_dest+linear_offset + vst1.8 {q1}, [r12]! + vst1.8 {q3}, [r12]! + vst1.8 {q5}, [r12]! + vst1.8 {q7}, [r12]! + vst1.8 {q9}, [r12]! + vst1.8 {q11}, [r12]! + add r9, r9, #96 @ linear_offset = linear_offset+96 + + stmfd sp!, {r8-r12, r14} @ backup registers + sub r10, r11, #192 + mov r11, r14 + bl INTERLEAVED_MEMCOPY_UNDER_64 + ldmfd sp!, {r8-r12, r14} @ restore registers + b LOOP_HEIGHT_256_RIGHT_END + +LOOP_HEIGHT_256_RIGHT_192: + cmp r11, #128 + ble LOOP_HEIGHT_256_RIGHT_128 + add r12, r10, #2048 + pld [r12] + vld2.8 {q0, q1}, [r10]! @ load {nv12t_src+tiled_offset} + pld [r12, #32] + vld2.8 {q2, q3}, [r10] + + add r14, r2, r8 @ r10 = nv12t_src+tiled_offset1 + pld [r14] + vld2.8 {q4, q5}, [r12]! @ load {nv12t_src+tiled_offset+2048} + pld [r14, #32] + vld2.8 {q6, q7}, [r12] + + add r12, r0, r9 @ r12 = yuv420_u_dest+linear_offset + vst1.8 {q0}, [r12]! + vst1.8 {q2}, [r12]! + vst1.8 {q4}, [r12]! + vst1.8 {q6}, [r12]! + add r12, r1, r9 @ r12 = yuv420_v_dest+linear_offset + vst1.8 {q1}, [r12]! + vst1.8 {q3}, [r12]! + vst1.8 {q5}, [r12]! + vst1.8 {q7}, [r12]! + add r9, r9, #64 @ linear_offset = linear_offset+64 + + stmfd sp!, {r8-r12, r14} @ backup registers + sub r10, r11, #128 + mov r11, r14 + bl INTERLEAVED_MEMCOPY_UNDER_64 + ldmfd sp!, {r8-r12, r14} @ restore registers + b LOOP_HEIGHT_256_RIGHT_END + +LOOP_HEIGHT_256_RIGHT_128: + cmp r11, #64 + ble LOOP_HEIGHT_256_RIGHT_64 + add r14, r10, #2048 + pld [r14] + vld2.8 {q0, q1}, [r10]! @ load {nv12t_src+tiled_offset} + pld [r14, #32] + vld2.8 {q2, q3}, [r10] + + add r12, r0, r9 @ r12 = yuv420_u_dest+linear_offset + vst1.8 {q0}, [r12]! + vst1.8 {q2}, [r12]! + add r12, r1, r9 @ r12 = yuv420_v_dest+linear_offset + vst1.8 {q1}, [r12]! + vst1.8 {q3}, [r12]! + add r9, r9, #32 @ linear_offset = linear_offset+32 + + stmfd sp!, {r8-r12, r14} @ backup registers + sub r10, r11, #64 + mov r11, r14 + bl INTERLEAVED_MEMCOPY_UNDER_64 + ldmfd sp!, {r8-r12, r14} @ restore registers + b LOOP_HEIGHT_256_RIGHT_END + +LOOP_HEIGHT_256_RIGHT_64: + stmfd sp!, {r8-r12, r14} @ backup registers + mov r14, r11 + mov r11, r10 + mov r10, r14 + bl INTERLEAVED_MEMCOPY_UNDER_64 + ldmfd sp!, {r8-r12, r14} @ restore registers + +LOOP_HEIGHT_256_RIGHT_END: + + ldr r14, [sp, #56] @ buttom + add r5, r5, #1 @ i=i+1 + sub r14, r4, r14 @ i= 64) + blt LOOP_HEIGHT_2_START + + ldr r5, [sp, #48] @ i = top +LOOP_HEIGHT_64: + ldr r6, [sp, #44] @ j = left + stmfd sp!, {r0-r3, r12} @ backup parameters + mov r0, r3 + mov r1, r4 + mov r2, r6 + mov r3, r5 + bl tile_4x2_read_asm + mov r7, r0 + ldmfd sp!, {r0-r3, r12} @ restore parameters + ldr r9, [sp, #48] @ linear_offset = top + ldr r12, [sp, #52] @ r12 = right + add r11, r6, #64 @ temp2 = ((j+64)>>6)<<6 + bic r11, r11, #0x3F + sub r11, r11, r6 @ temp2 = temp2-j + sub r12, r3, r12 @ temp3 = yuv420_width-right + sub r14, r12, r6 @ temp4 = temp3-left + sub r9, r5, r9 @ linear_offset = temp4*(i-top)/2 + mul r9, r9, r14 + mov r9, r9, asr #1 + and r14, r6, #0x3 @ temp4 = j&0x3 + add r7, r7, r14 @ tiled_offset = tiled_offset+temp4 + stmfd sp!, {r9-r12} @ backup parameters + mov r10, r11 + add r11, r2, r7 + bl INTERLEAVED_MEMCOPY_UNDER_64 + ldmfd sp!, {r9-r12} @ restore parameters + add r9, r9, r11, asr #1 @ linear_offset = linear_offset+temp2/2 + add r6, r6, r11 @ j = j+temp2@ + + add r14, r6, #64 + cmp r14, r12 + bgt LOOP_HEIGHT_64_1 + stmfd sp!, {r0-r3, r12} @ backup parameters + mov r0, r3 + mov r1, r4 + mov r2, r6 + mov r3, r5 + bl tile_4x2_read_asm + mov r7, r0 + ldmfd sp!, {r0-r3, r12} @ restore parameters + add r7, r2, r7 + vld2.8 {q0, q1}, [r7]! + vld2.8 {q2, q3}, [r7] + add r7, r0, r9 + vst1.8 {q0}, [r7]! + vst1.8 {q2}, [r7] + add r7, r1, r9 + vst1.8 {q1}, [r7]! + vst1.8 {q3}, [r7] + add r9, r9, #32 + add r6, r6, #64 + +LOOP_HEIGHT_64_1: + add r14, r6, #64 + cmp r14, r12 + bgt LOOP_HEIGHT_64_2 + stmfd sp!, {r0-r3, r12} @ backup parameters + mov r0, r3 + mov r1, r4 + mov r2, r6 + mov r3, r5 + bl tile_4x2_read_asm + mov r7, r0 + ldmfd sp!, {r0-r3, r12} @ restore parameters + add r7, r2, r7 + vld2.8 {q0, q1}, [r7]! + vld2.8 {q2, q3}, [r7] + add r7, r0, r9 + vst1.8 {q0}, [r7]! + vst1.8 {q2}, [r7] + add r7, r1, r9 + vst1.8 {q1}, [r7]! + vst1.8 {q3}, [r7] + add r9, r9, #32 + add r6, r6, #64 + +LOOP_HEIGHT_64_2: + cmp r6, r12 + bge LOOP_HEIGHT_64_3 + stmfd sp!, {r0-r3, r12} @ backup parameters + mov r0, r3 + mov r1, r4 + mov r2, r6 + mov r3, r5 + bl tile_4x2_read_asm + mov r7, r0 + ldmfd sp!, {r0-r3, r12} @ restore parameters + sub r11, r12, r6 + stmfd sp!, {r9-r12} @ backup parameters + mov r10, r11 + add r11, r2, r7 + bl INTERLEAVED_MEMCOPY_UNDER_64 + ldmfd sp!, {r9-r12} @ restore parameters + +LOOP_HEIGHT_64_3: + + ldr r14, [sp, #56] @ buttom + add r5, r5, #1 @ i=i+1 + sub r14, r4, r14 @ i> 4) << 4; + + for (i = 0; i < aligned_height; i = i + 16) { + for (j = 0; j> 4) << 4; + + for (i = 0; i < aligned_height; i = i + 8) { + for (j = 0; j> 4) << 4; + + for (i = 0; i < aligned_height; i = i + 8) { + for (j = 0; j> 1) * i + (j >> 1); + for (k = 0; k < 4; k++) { + csc_deinterleave_memcpy(u_dst + dst_offset, v_dst + dst_offset, + uv_src + src_offset, 16); + src_offset += 16; + dst_offset += width >> 1; + csc_deinterleave_memcpy(u_dst + dst_offset, v_dst + dst_offset, + uv_src + src_offset, 16); + src_offset += 16; + dst_offset += width >> 1; + } + } + if (aligned_width != width) { + src_offset = (tiled_width * i) + (j << 3); + dst_offset = (width >> 1) * i + (j >> 1); + for (k = 0; k < 4; k++) { + csc_deinterleave_memcpy(u_dst + dst_offset, v_dst + dst_offset, + uv_src + src_offset, width - j); + src_offset += 16; + dst_offset += width >> 1; + csc_deinterleave_memcpy(u_dst + dst_offset, v_dst + dst_offset, + uv_src + src_offset, width - j); + src_offset += 16; + dst_offset += width >> 1; + } + } + } + if (aligned_height != height) { + for (j = 0; j> 1) * i + (j >> 1); + for (k = 0; k < height - aligned_height; k = k + 1) { + csc_deinterleave_memcpy(u_dst + dst_offset, v_dst + dst_offset, + uv_src + src_offset, 16); + src_offset += 16; + dst_offset += width >> 1; + } + } + if (aligned_width != width) { + src_offset = (tiled_width * i) + (j << 3); + dst_offset = (width >> 1) * i + (j >> 1); + for (k = 0; k < height - aligned_height; k = k + 1) { + csc_deinterleave_memcpy(u_dst + dst_offset, v_dst + dst_offset, + uv_src + src_offset, width - j); + src_offset += 16; + dst_offset += width >> 1; + } + } + } +} + +/* + * Converts linear data to tiled + * It supports mfc 6.x tiled + * 1. y of yuv420 to y of nv12t + * + * @param dst + * y address of nv12t[out] + * + * @param src + * y address of yuv420[in] + * + * @param yuv420_width + * real width of yuv420[in] + * it should be even + * + * @param yuv420_height + * real height of yuv420[in] + * it should be even. + * + */ +void csc_linear_to_tiled_y( + unsigned char *y_dst, + unsigned char *y_src, + unsigned int width, + unsigned int height) +{ + +} + +/* + * Converts and interleaves linear data to tiled + * It supports mfc 6.x tiled + * 1. uv of nv12t to uv of yuv420 + * + * @param dst + * uv address of nv12t[out] + * + * @param src + * u address of yuv420[in] + * + * @param src + * v address of yuv420[in] + * + * @param yuv420_width + * real width of yuv420[in] + * + * @param yuv420_height + * real height of yuv420[in] + * + */ +void csc_linear_to_tiled_uv( + unsigned char *uv_dst, + unsigned char *u_src, + unsigned char *v_src, + unsigned int width, + unsigned int height) +{ + +} + +void Tile2D_To_YUV420(unsigned char *Y_plane, unsigned char *Cb_plane, unsigned char *Cr_plane, + unsigned int y_addr, unsigned int c_addr, unsigned int width, unsigned int height) +{ + int x, y, j, k, l; + int out_of_width, actual_width; + unsigned int base_addr, data; + + // y: 0, 16, 32, ... + for (y = 0; y < height; y += 16) { + // x: 0, 16, 32, ... + for (x = 0; x < width; x += 16) { + out_of_width = (x + 16) > width ? 1 : 0; + base_addr = y_addr + Tile2D_To_Linear(width, height, x, y, 0); + + for (k = 0; (k < 16) && ((y + k) < height); k++) { + actual_width = out_of_width ? ((width%4)?((width%16) / 4 + 1) : ((width%16) / 4)) : 4; + for (l = 0; l < actual_width; l++) { + data = *((unsigned int*)(base_addr + 16*k + l*4)); + for (j = 0; (j < 4) && (x + l*4 + j) < width; j++) { + Y_plane[(y+k)*width + x + l*4 +j] = (data>>(8*j))&0xff; + } + } + } + } + } + + for (y = 0; y < height/2; y += 8) { + for (x = 0; x < width; x += 16) { + out_of_width = (x + 16) > width ? 1 : 0; + base_addr = c_addr + Tile2D_To_Linear(width, height/2, x, y, 1); + for (k = 0; (k < 8) && ((y+k) < height/2); k++) { + actual_width = out_of_width ? ((width%4) ? ((width%16) / 4 + 1) : ((width%16) / 4)) : 4; + for (l = 0; l < actual_width; l++) { + data = *((unsigned int*)(base_addr + 16*k + l*4)); + for (j = 0; (j < 2) && (x/2 + l*2 +j) < width/2; j++) { + Cb_plane[(y+k)*width/2 + x/2 + l*2 +j] = (data>> (8*2*j))&0xff; + Cr_plane[(y+k)*width/2 + x/2 + l*2 +j] = (data>>(8*2*j+8))&0xff; + } + } + } + } + } +} + +/* + * Converts RGB565 to YUV420P + * + * @param y_dst + * Y plane address of YUV420P[out] + * + * @param u_dst + * U plane address of YUV420P[out] + * + * @param v_dst + * V plane address of YUV420P[out] + * + * @param rgb_src + * Address of RGB565[in] + * + * @param width + * Width of RGB565[in] + * + * @param height + * Height of RGB565[in] + */ +void csc_RGB565_to_YUV420P( + unsigned char *y_dst, + unsigned char *u_dst, + unsigned char *v_dst, + unsigned char *rgb_src, + int width, + int height) +{ + unsigned int i, j; + unsigned int tmp; + + unsigned int R, G, B; + unsigned int Y, U, V; + + unsigned int offset1 = width * height; + unsigned int offset2 = width/2 * height/2; + + unsigned short int *pSrc = (unsigned short int *)rgb_src; + + unsigned char *pDstY = (unsigned char *)y_dst; + unsigned char *pDstU = (unsigned char *)u_dst; + unsigned char *pDstV = (unsigned char *)v_dst; + + unsigned int yIndex = 0; + unsigned int uIndex = 0; + unsigned int vIndex = 0; + + for (j = 0; j < height; j++) { + for (i = 0; i < width; i++) { + tmp = pSrc[j * width + i]; + + R = (tmp & 0x0000F800) >> 8; + G = (tmp & 0x000007E0) >> 3; + B = (tmp & 0x0000001F); + B = B << 3; + + Y = ((66 * R) + (129 * G) + (25 * B) + 128); + Y = Y >> 8; + Y += 16; + + pDstY[yIndex++] = (unsigned char)Y; + + if ((j % 2) == 0 && (i % 2) == 0) { + U = ((-38 * R) - (74 * G) + (112 * B) + 128); + U = U >> 8; + U += 128; + V = ((112 * R) - (94 * G) - (18 * B) + 128); + V = V >> 8; + V += 128; + + pDstU[uIndex++] = (unsigned char)U; + pDstV[vIndex++] = (unsigned char)V; + } + } + } +} + +/* + * Converts RGB565 to YUV420SP + * + * @param y_dst + * Y plane address of YUV420SP[out] + * + * @param uv_dst + * UV plane address of YUV420SP[out] + * + * @param rgb_src + * Address of RGB565[in] + * + * @param width + * Width of RGB565[in] + * + * @param height + * Height of RGB565[in] + */ +void csc_RGB565_to_YUV420SP( + unsigned char *y_dst, + unsigned char *uv_dst, + unsigned char *rgb_src, + int width, + int height) +{ + unsigned int i, j; + unsigned int tmp; + + unsigned int R, G, B; + unsigned int Y, U, V; + + unsigned int offset = width * height; + + unsigned short int *pSrc = (unsigned short int *)rgb_src; + + unsigned char *pDstY = (unsigned char *)y_dst; + unsigned char *pDstUV = (unsigned char *)uv_dst; + + unsigned int yIndex = 0; + unsigned int uvIndex = 0; + + for (j = 0; j < height; j++) { + for (i = 0; i < width; i++) { + tmp = pSrc[j * width + i]; + + R = (tmp & 0x0000F800) >> 11; + R = R * 8; + G = (tmp & 0x000007E0) >> 5; + G = G * 4; + B = (tmp & 0x0000001F); + B = B * 8; + + Y = ((66 * R) + (129 * G) + (25 * B) + 128); + Y = Y >> 8; + Y += 16; + + pDstY[yIndex++] = (unsigned char)Y; + + if ((j % 2) == 0 && (i % 2) == 0) { + U = ((-38 * R) - (74 * G) + (112 * B) + 128); + U = U >> 8; + U += 128; + V = ((112 * R) - (94 * G) - (18 * B) + 128); + V = V >> 8; + V += 128; + + pDstUV[uvIndex++] = (unsigned char)U; + pDstUV[uvIndex++] = (unsigned char)V; + } + } + } +} diff --git a/exynos/multimedia/utils/csc/exynos5/color_space_convertor.h b/exynos/multimedia/utils/csc/exynos5/color_space_convertor.h new file mode 100644 index 0000000..202011e --- /dev/null +++ b/exynos/multimedia/utils/csc/exynos5/color_space_convertor.h @@ -0,0 +1,411 @@ +/* + * + * Copyright 2010 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file color_space_convertor.h + * @brief SEC_OMX specific define. It support MFC 6.x tiled. + * NV12T(tiled) layout: + * Each element is not pixel. It is 64x32 pixel block. + * uv pixel block is interleaved as u v u v u v ... + * y1 y2 y7 y8 y9 y10 y15 y16 + * y3 y4 y5 y6 y11 y12 y13 y14 + * y17 y18 y23 y24 y25 y26 y31 y32 + * y19 y20 y21 y22 y27 y28 y29 y30 + * uv1 uv2 uv7 uv8 uv9 uv10 uv15 uv16 + * uv3 uv4 uv5 uv6 uv11 uv12 uv13 uv14 + * YUV420Planar(linear) layout: + * Each element is not pixel. It is 64x32 pixel block. + * y1 y2 y3 y4 y5 y6 y7 y8 + * y9 y10 y11 y12 y13 y14 y15 y16 + * y17 y18 y19 y20 y21 y22 y23 y24 + * y25 y26 y27 y28 y29 y30 y31 y32 + * u1 u2 u3 u4 u5 u6 u7 u8 + * v1 v2 v3 v4 v5 v6 v7 v8 + * YUV420Semiplanar(linear) layout: + * Each element is not pixel. It is 64x32 pixel block. + * uv pixel block is interleaved as u v u v u v ... + * y1 y2 y3 y4 y5 y6 y7 y8 + * y9 y10 y11 y12 y13 y14 y15 y16 + * y17 y18 y19 y20 y21 y22 y23 y24 + * y25 y26 y27 y28 y29 y30 y31 y32 + * uv1 uv2 uv3 uv4 uv5 uv6 uv7 uv8 + * uv9 uv10 uv11 uv12 uv13 uv14 uv15 uv16 + * @author ShinWon Lee (shinwon.lee@samsung.com) + * @version 1.0 + * @history + * 2011.12.01 : Create + */ + +#ifndef COLOR_SPACE_CONVERTOR_H_ +#define COLOR_SPACE_CONVERTOR_H_ + +/*--------------------------------------------------------------------------------*/ +/* Format Conversion API */ +/*--------------------------------------------------------------------------------*/ +/* C Code */ +/* + * De-interleaves src to dest1, dest2 + * + * @param dest1 + * Address of de-interleaved data[out] + * + * @param dest2 + * Address of de-interleaved data[out] + * + * @param src + * Address of interleaved data[in] + * + * @param src_size + * Size of interleaved data[in] + */ +void csc_deinterleave_memcpy( + unsigned char *dest1, + unsigned char *dest2, + unsigned char *src, + unsigned int src_size); + +/* + * Interleaves src1, src2 to dest + * + * @param dest + * Address of interleaved data[out] + * + * @param src1 + * Address of de-interleaved data[in] + * + * @param src2 + * Address of de-interleaved data[in] + * + * @param src_size + * Size of de-interleaved data[in] + */ +void csc_interleave_memcpy( + unsigned char *dest, + unsigned char *src1, + unsigned char *src2, + unsigned int src_size); + +/* + * Converts tiled data to linear + * It supports mfc 6.x tiled + * 1. y of nv12t to y of yuv420p + * 2. y of nv12t to y of yuv420s + * + * @param dst + * y address of yuv420[out] + * + * @param src + * y address of nv12t[in] + * + * @param yuv420_width + * real width of yuv420[in] + * it should be even + * + * @param yuv420_height + * real height of yuv420[in] + * it should be even. + * + */ +void csc_tiled_to_linear_y( + unsigned char *y_dst, + unsigned char *y_src, + unsigned int width, + unsigned int height); + +/* + * Converts tiled data to linear + * It supports mfc 6.x tiled + * 1. uv of nv12t to y of yuv420s + * + * @param dst + * uv address of yuv420s[out] + * + * @param src + * uv address of nv12t[in] + * + * @param yuv420_width + * real width of yuv420s[in] + * + * @param yuv420_height + * real height of yuv420s[in] + * + */ +void csc_tiled_to_linear_uv( + unsigned char *uv_dst, + unsigned char *uv_src, + unsigned int width, + unsigned int height); + +/* + * Converts tiled data to linear + * It supports mfc 6.x tiled + * 1. uv of nt12t to uv of yuv420p + * + * @param u_dst + * u address of yuv420p[out] + * + * @param v_dst + * v address of yuv420p[out] + * + * @param uv_src + * uv address of nt12t[in] + * + * @param yuv420_width + * real width of yuv420p[in] + * + * @param yuv420_height + * real height of yuv420p[in] + */ +void csc_tiled_to_linear_uv_deinterleave( + unsigned char *u_dst, + unsigned char *v_dst, + unsigned char *uv_src, + unsigned int width, + unsigned int height); + +/* + * Converts linear data to tiled + * It supports mfc 6.x tiled + * 1. y of yuv420 to y of nv12t + * + * @param dst + * y address of nv12t[out] + * + * @param src + * y address of yuv420[in] + * + * @param yuv420_width + * real width of yuv420[in] + * it should be even + * + * @param yuv420_height + * real height of yuv420[in] + * it should be even. + * + */ +void csc_linear_to_tiled_y( + unsigned char *y_dst, + unsigned char *y_src, + unsigned int width, + unsigned int height); + +/* + * Converts and interleaves linear data to tiled + * It supports mfc 6.x tiled + * 1. uv of nv12t to uv of yuv420 + * + * @param dst + * uv address of nv12t[out] + * + * @param src + * u address of yuv420[in] + * + * @param src + * v address of yuv420[in] + * + * @param yuv420_width + * real width of yuv420[in] + * + * @param yuv420_height + * real height of yuv420[in] + * + */ +void csc_linear_to_tiled_uv( + unsigned char *uv_dst, + unsigned char *u_src, + unsigned char *v_src, + unsigned int width, + unsigned int height); + +/* + * Converts RGB565 to YUV420P + * + * @param y_dst + * Y plane address of YUV420P[out] + * + * @param u_dst + * U plane address of YUV420P[out] + * + * @param v_dst + * V plane address of YUV420P[out] + * + * @param rgb_src + * Address of RGB565[in] + * + * @param width + * Width of RGB565[in] + * + * @param height + * Height of RGB565[in] + */ +void csc_RGB565_to_YUV420P( + unsigned char *y_dst, + unsigned char *u_dst, + unsigned char *v_dst, + unsigned char *rgb_src, + int width, + int height); + +/* + * Converts RGB565 to YUV420S + * + * @param y_dst + * Y plane address of YUV420S[out] + * + * @param uv_dst + * UV plane address of YUV420S[out] + * + * @param rgb_src + * Address of RGB565[in] + * + * @param width + * Width of RGB565[in] + * + * @param height + * Height of RGB565[in] + */ +void csc_RGB565_to_YUV420SP( + unsigned char *y_dst, + unsigned char *uv_dst, + unsigned char *rgb_src, + int width, + int height); + +/* + * Converts tiled data to linear for mfc 6.x + * 1. Y of NV12T to Y of YUV420P + * 2. Y of NV12T to Y of YUV420S + * + * @param dst + * Y address of YUV420[out] + * + * @param src + * Y address of NV12T[in] + * + * @param yuv420_width + * real width of YUV420[in] + * + * @param yuv420_height + * Y: real height of YUV420[in] + * + */ +void csc_tiled_to_linear_y_neon( + unsigned char *y_dst, + unsigned char *y_src, + unsigned int width, + unsigned int height); + +/* + * Converts tiled data to linear for mfc 6.x + * 1. UV of NV12T to Y of YUV420S + * + * @param u_dst + * UV plane address of YUV420P[out] + * + * @param nv12t_src + * Y or UV plane address of NV12T[in] + * + * @param yuv420_width + * real width of YUV420[in] + * + * @param yuv420_height + * (real height)/2 of YUV420[in] + */ +void csc_tiled_to_linear_uv_neon( + unsigned char *uv_dst, + unsigned char *uv_src, + unsigned int width, + unsigned int height); + +/* + * Converts tiled data to linear for mfc 6.x + * Deinterleave src to u_dst, v_dst + * 1. UV of NV12T to Y of YUV420P + * + * @param u_dst + * U plane address of YUV420P[out] + * + * @param v_dst + * V plane address of YUV420P[out] + * + * @param nv12t_src + * Y or UV plane address of NV12T[in] + * + * @param yuv420_width + * real width of YUV420[in] + * + * @param yuv420_height + * (real height)/2 of YUV420[in] + */ +void csc_tiled_to_linear_uv_deinterleave_neon( + unsigned char *u_dst, + unsigned char *v_dst, + unsigned char *uv_src, + unsigned int width, + unsigned int height); + +/* + * Converts linear data to tiled + * It supports mfc 6.x tiled + * 1. y of yuv420 to y of nv12t + * + * @param dst + * y address of nv12t[out] + * + * @param src + * y address of yuv420[in] + * + * @param yuv420_width + * real width of yuv420[in] + * it should be even + * + * @param yuv420_height + * real height of yuv420[in] + * it should be even. + * + */ +void csc_linear_to_tiled_y_neon( + unsigned char *y_dst, + unsigned char *y_src, + unsigned int width, + unsigned int height); + +/* + * Converts and interleave linear data to tiled + * It supports mfc 6.x tiled + * 1. uv of nv12t to uv of yuv420 + * + * @param dst + * uv address of yuv420[out] + * + * @param src + * uv address of nv12t[in] + * + * @param yuv420_width + * real width of yuv420[in] + * + * @param yuv420_height + * real height of yuv420[in] + * + */ +void csc_linear_to_tiled_uv_neon( + unsigned char *uv_dst, + unsigned char *uv_src, + unsigned int width, + unsigned int height); + +#endif /*COLOR_SPACE_CONVERTOR_H_*/ diff --git a/exynos/multimedia/utils/csc/exynos5/csc_fimc.cpp b/exynos/multimedia/utils/csc/exynos5/csc_fimc.cpp new file mode 100644 index 0000000..89d0f97 --- /dev/null +++ b/exynos/multimedia/utils/csc/exynos5/csc_fimc.cpp @@ -0,0 +1,225 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file csc_fimc.cpp + * + * @brief csc_fimc use fimc1 to color space convertion + * + * @author ShinWon Lee (shinwon.lee@samsung.com) + * + * @version 1.0 + * + * @history + * 2011.11.01 : Create + */ + +#include +#include + +#include "SecFimc.h" +#include "csc_fimc.h" + +#define ALIGN(value, base) (((value) + (base) - 1) & ~((base) - 1)) + +unsigned int OMXtoHarPixelFomrat(OMX_COLOR_FORMATTYPE ColorFormat) +{ + unsigned int v4l2_format = 0; + switch (ColorFormat) { + case OMX_COLOR_FormatYUV420Planar: + v4l2_format = HAL_PIXEL_FORMAT_YCbCr_420_P; + break; + case OMX_COLOR_FormatYUV420SemiPlanar: + v4l2_format = HAL_PIXEL_FORMAT_YCbCr_420_SP; + break; + default: + v4l2_format = HAL_PIXEL_FORMAT_YCbCr_420_P; + break; + } + return v4l2_format; +} + +/* + * create and open fimc handle + * + * @return + * fimc handle + */ +void *csc_fimc_open() +{ + SecFimc *(*create_instance)(); + void (*destroy_instance)(void *); + SecFimc *handle_fimc = NULL; + void* hdl = NULL; + + hdl = dlopen("libfimc.so", RTLD_NOW); + if (hdl == NULL) { + LOGE("%s:: load libfimc.so failed", __func__); + return NULL; + } + + create_instance = (SecFimc *(*)())dlsym(hdl, "create_instance"); + handle_fimc = (SecFimc *)create_instance(); + if (handle_fimc == NULL) { + LOGE("%s:: create handle_fimc failed", __func__); + return NULL; + } + + if (!handle_fimc->create(SecFimc::DEV_1, SecFimc::MODE_MULTI_BUF, 1)) { + destroy_instance = (void (*)(void *))dlsym(hdl, "destroy_instance"); + destroy_instance(handle_fimc); + LOGE("%s:: create() failed", __func__); + return NULL; + } + return (void *)handle_fimc; +} + +/* + * close and destroy fimc handle + * + * @param handle + * fimc handle[in] + * + * @return + * pass or fail + */ +CSC_FIMC_ERROR_CODE csc_fimc_close(void *handle) +{ + void (*destroy_instance)(void *); + SecFimc *handle_fimc = (SecFimc *)handle; + void* hdl = NULL; + + if (!handle_fimc->destroy()) { + LOGE("%s:: destroy() failed", __func__); + return CSC_FIMC_RET_FAIL; + } + + hdl = dlopen("libfimc.so", RTLD_NOW); + if (hdl == NULL) { + LOGE("%s:: load libfimc.so failed", __func__); + return CSC_FIMC_RET_FAIL; + } + + destroy_instance = (void (*)(void *))dlsym(hdl, "destroy_instance"); + destroy_instance(handle); + + return CSC_FIMC_RET_OK; +} + +/* + * convert color space nv12t to omxformat + * + * @param handle + * fimc handle[in] + * + * @param dst_addr + * y,u,v address of dst_addr[out] + * + * @param src_addr + * y,uv address of src_addr.Format is nv12t[in] + * + * @param width + * width of dst image[in] + * + * @param height + * height of dst image[in] + * + * @param omxformat + * omxformat of dst image[in] + * + * @return + * pass or fail + */ +CSC_FIMC_ERROR_CODE csc_fimc_convert_nv12t( + void *handle, + void **dst_addr, + void **src_addr, + unsigned int width, + unsigned int height, + OMX_COLOR_FORMATTYPE omxformat) +{ + int rotate_value = 0; + + SecFimc *handle_fimc = (SecFimc *)handle; + + unsigned int src_crop_x = 0; + unsigned int src_crop_y = 0; + unsigned int src_crop_width = width; + unsigned int src_crop_height = height; + + unsigned int dst_crop_x = 0; + unsigned int dst_crop_y = 0; + unsigned int dst_crop_width = width; + unsigned int dst_crop_height = height; + + unsigned int HarPixelformat = 0; + HarPixelformat = OMXtoHarPixelFomrat(omxformat); + + // set post processor configuration + if (!handle_fimc->setSrcParams(width, height, src_crop_x, src_crop_y, + &src_crop_width, &src_crop_height, + HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_SP_TILED)) { + LOGE("%s:: setSrcParms() failed", __func__); + return CSC_FIMC_RET_FAIL; + } + + if (!handle_fimc->setSrcAddr((unsigned int)src_addr[0], + (unsigned int)src_addr[1], + (unsigned int)src_addr[1], + HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_SP_TILED)) { + LOGE("%s:: setSrcPhyAddr() failed", __func__); + return CSC_FIMC_RET_FAIL; + } + + if (!handle_fimc->setRotVal(rotate_value)) { + LOGE("%s:: setRotVal() failed", __func__); + return CSC_FIMC_RET_FAIL; + } + + if (!handle_fimc->setDstParams(width, height, dst_crop_x, dst_crop_y, + &dst_crop_width, &dst_crop_height, + HarPixelformat)) { + LOGE("%s:: setDstParams() failed", __func__); + return CSC_FIMC_RET_FAIL; + } + + switch (omxformat) { + case OMX_COLOR_FormatYUV420SemiPlanar: + if (!handle_fimc->setDstAddr((unsigned int)(dst_addr[0]), + (unsigned int)(dst_addr[1]), + (unsigned int)(dst_addr[1]))) { + LOGE("%s:: setDstPhyAddr() failed", __func__); + return CSC_FIMC_RET_FAIL; + } + break; + case OMX_COLOR_FormatYUV420Planar: + default: + if (!handle_fimc->setDstAddr((unsigned int)(dst_addr[0]), + (unsigned int)(dst_addr[1]), + (unsigned int)(dst_addr[2]))) { + LOGE("%s:: setDstPhyAddr() failed", __func__); + return CSC_FIMC_RET_FAIL; + } + break; + } + + if (!handle_fimc->draw(0, 0)) { + LOGE("%s:: handleOneShot() failed", __func__); + return CSC_FIMC_RET_FAIL; + } + + return CSC_FIMC_RET_OK; +} diff --git a/exynos/multimedia/utils/csc/exynos5/csc_fimc.h b/exynos/multimedia/utils/csc/exynos5/csc_fimc.h new file mode 100644 index 0000000..3ae24ac --- /dev/null +++ b/exynos/multimedia/utils/csc/exynos5/csc_fimc.h @@ -0,0 +1,106 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file csc_fimc.h + * + * @brief csc_fimc use fimc1 to color space convertion + * + * @author ShinWon Lee (shinwon.lee@samsung.com) + * + * @version 1.0 + * + * @history + * 2011.11.01 : Create + */ + +#ifndef CSC_FIMC_H + +#define CSC_FIMC_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +/*--------------------------------------------------------------------------------*/ +/* Structure and Type */ +/*--------------------------------------------------------------------------------*/ +typedef enum { + CSC_FIMC_RET_OK = 0, + CSC_FIMC_RET_FAIL = -1 +} CSC_FIMC_ERROR_CODE; + +/*--------------------------------------------------------------------------------*/ +/* CSC FIMC APIs */ +/*--------------------------------------------------------------------------------*/ +/* + * create and open fimc handle + * + * @return + * fimc handle + */ +void *csc_fimc_open(); + +/* + * close and destroy fimc handle + * + * @param handle + * fimc handle[in] + * + * @return + * error code + */ +CSC_FIMC_ERROR_CODE csc_fimc_close(void *handle); + +/* + * convert color space nv12t to omxformat + * + * @param handle + * fimc handle[in] + * + * @param dst_addr + * y,u,v address of dst_addr[out] + * + * @param src_addr + * y,uv address of src_addr.Format is nv12t[in] + * + * @param width + * width of dst image[in] + * + * @param height + * height of dst image[in] + * + * @param omxformat + * omxformat of dst image[in] + * + * @return + * error code + */ +CSC_FIMC_ERROR_CODE csc_fimc_convert_nv12t( + void *handle, + void **dst_addr, + void **src_addr, + unsigned int width, + unsigned int height, + OMX_COLOR_FORMATTYPE omxformat); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/exynos/multimedia/utils/csc/exynos5/csc_interleave_memcpy_neon.s b/exynos/multimedia/utils/csc/exynos5/csc_interleave_memcpy_neon.s new file mode 100644 index 0000000..3d2b41f --- /dev/null +++ b/exynos/multimedia/utils/csc/exynos5/csc_interleave_memcpy_neon.s @@ -0,0 +1,120 @@ +/* + * + * Copyright 2012 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License") + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file csc_linear_to_tiled_crop_neon.s + * @brief SEC_OMX specific define + * @author ShinWon Lee (shinwon.lee@samsung.com) + * @version 1.0 + * @history + * 2012.01.04 : Create + */ + +/* + * Interleave src1, src2 to dst + * + * @param dest + * dst address[out] + * + * @param src1 + * src1 address[in] + * + * @param src2 + * src2 address[in] + * + * @param src_size + * src_size or src1 + */ + + .arch armv7-a + .text + .global csc_interleave_memcpy_neon + .type csc_interleave_memcpy_neon, %function +csc_interleave_memcpy_neon: + .fnstart + + @r0 dest + @r1 src1 + @r2 src2 + @r3 src_size + @r4 + @r5 + @r6 + @r7 + @r8 temp1 + @r9 temp2 + @r10 dest_addr + @r11 src1_addr + @r12 src2_addr + @r14 i + + stmfd sp!, {r8-r12,r14} @ backup registers + + mov r10, r0 + mov r11, r1 + mov r12, r2 + mov r14, r3 + + cmp r14, #128 + blt LESS_THAN_128 + +LOOP_128: + vld1.8 {q0}, [r11]! + vld1.8 {q2}, [r11]! + vld1.8 {q4}, [r11]! + vld1.8 {q6}, [r11]! + vld1.8 {q8}, [r11]! + vld1.8 {q10}, [r11]! + vld1.8 {q12}, [r11]! + vld1.8 {q14}, [r11]! + vld1.8 {q1}, [r12]! + vld1.8 {q3}, [r12]! + vld1.8 {q5}, [r12]! + vld1.8 {q7}, [r12]! + vld1.8 {q9}, [r12]! + vld1.8 {q11}, [r12]! + vld1.8 {q13}, [r12]! + vld1.8 {q15}, [r12]! + + vst2.8 {q0, q1}, [r10]! + vst2.8 {q2, q3}, [r10]! + vst2.8 {q4, q5}, [r10]! + vst2.8 {q6, q7}, [r10]! + vst2.8 {q8, q9}, [r10]! + vst2.8 {q10, q11}, [r10]! + vst2.8 {q12, q13}, [r10]! + vst2.8 {q14, q15}, [r10]! + + sub r14, #128 + cmp r14, #128 + bgt LOOP_128 + +LESS_THAN_128: + cmp r14, #0 + beq RESTORE_REG + +LOOP_1: + ldrb r8, [r11], #1 + ldrb r9, [r12], #1 + strb r8, [r10], #1 + strb r9, [r10], #1 + subs r14, #1 + bne LOOP_1 + +RESTORE_REG: + ldmfd sp!, {r8-r12,r15} @ restore registers + .fnend diff --git a/exynos/multimedia/utils/csc/exynos5/csc_tiled_to_linear_uv_deinterleave_neon.s b/exynos/multimedia/utils/csc/exynos5/csc_tiled_to_linear_uv_deinterleave_neon.s new file mode 100644 index 0000000..1e76a2e --- /dev/null +++ b/exynos/multimedia/utils/csc/exynos5/csc_tiled_to_linear_uv_deinterleave_neon.s @@ -0,0 +1,249 @@ +/* + * + * Copyright 2010 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License") + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file csc_tiled_to_linear_uv_deinterleave_neon.s + * @brief SEC_OMX specific define. It support MFC 6.x tiled. + * @author ShinWon Lee (shinwon.lee@samsung.com) + * @version 1.0 + * @history + * 2011.12.01 : Create + */ + +/* + * Converts and Deinterleave tiled data to linear for mfc 6.x + * 1. UV of NV12T to Y of YUV420P + * + * @param u_dst + * U address of YUV420[out] + * + * @param v_dst + * V address of YUV420[out] + * + * @param uv_src + * UV address of NV12T[in] + * + * @param yuv420_width + * real width of YUV420[in]. It should be even. + * + * @param yuv420_height + * real height of YUV420[in] It should be even. + */ + + .arch armv7-a + .text + .global csc_tiled_to_linear_uv_deinterleave_neon + .type csc_tiled_to_linear_uv_deinterleave_neon, %function +csc_tiled_to_linear_uv_deinterleave_neon: + .fnstart + + .equ CACHE_LINE_SIZE, 64 + + @r0 u_dst + @r1 v_dst + @r2 uv_src + @r3 width + @r4 height + @r5 i + @r6 j + @r7 dst_offset + @r8 src_offset + @r9 aligned_height + @r10 aligned_width + @r11 tiled_width + @r12 temp1 + @r14 temp2 + + stmfd sp!, {r4-r12,r14} @ backup registers + ldr r4, [sp, #40] @ r4 = height + + bic r9, r4, #0x7 @ aligned_height = height & (~0x7) + bic r10, r3, #0xF @ aligned_width = width & (~0xF) + add r11, r3, #15 @ tiled_width = ((width + 15) >> 4) << 4 + mov r11, r11, asr #4 + mov r11, r11, lsl #4 + + mov r5, #0 +LOOP_MAIN_ALIGNED_HEIGHT: + mul r8, r11, r5 @ src_offset = tiled_width * i + mov r6, #0 + add r8, r2, r8 @ src_offset = uv_src + src_offset +LOOP_MAIN_ALIGNED_WIDTH: + mov r12, r3, asr #1 @ temp1 = (width >> 1) * i + (j >> 1) + mul r12, r12, r5 + + pld [r8, #CACHE_LINE_SIZE] + vld2.8 {q0, q1}, [r8]! + add r12, r12, r6, asr #1 + vld2.8 {q2, q3}, [r8]! + add r7, r0, r12 @ dst_offset = u_dst + temp1 + pld [r8, #CACHE_LINE_SIZE] + vld2.8 {q4, q5}, [r8]! + mov r14, r3, asr #1 @ temp2 = width / 2 + vld2.8 {q6, q7}, [r8]! + + vst1.8 {d0}, [r7], r14 + vst1.8 {d1}, [r7], r14 + vst1.8 {d4}, [r7], r14 + vst1.8 {d5}, [r7], r14 + vst1.8 {d8}, [r7], r14 + vst1.8 {d9}, [r7], r14 + vst1.8 {d12}, [r7], r14 + vst1.8 {d13}, [r7], r14 + + add r7, r1, r12 @ dst_offset = v_dst + temp1 + + vst1.8 {d2}, [r7], r14 + vst1.8 {d3}, [r7], r14 + vst1.8 {d6}, [r7], r14 + vst1.8 {d7}, [r7], r14 + vst1.8 {d10}, [r7], r14 + vst1.8 {d11}, [r7], r14 + add r6, r6, #16 + vst1.8 {d14}, [r7], r14 + cmp r6, r10 + vst1.8 {d15}, [r7], r14 + blt LOOP_MAIN_ALIGNED_WIDTH + +MAIN_REMAIN_WIDTH_START: + cmp r10, r3 @ if (aligned_width != width) { + beq MAIN_REMAIN_WIDTH_END + stmfd sp!, {r0-r2,r4} @ backup registers + mul r8, r11, r5 @ src_offset = (tiled_width * i) + (j << 3) + add r8, r8, r6, lsl #3 + add r8, r2, r8 @ r8 = uv_src + src_offset + mov r12, r3, asr #1 @ temp1 = (width >> 1) * i + (j >> 1) + mul r12, r12, r5 + add r12, r12, r6, asr #1 + add r7, r0, r12 @ r7 = u_dst + temp1 + add r12, r1, r12 @ r12 = v_dst + temp1 + sub r14, r3, r6 @ r14 = (width - j) / 2 + mov r14, r14, asr #1 + + mov r4, #0 +LOOP_MAIN_REMAIN_HEIGHT: + mov r0, #0 @ r0 is index in de-interleave +LOOP_MAIN_REMAIN_WIDTH: + ldrb r1, [r8], #1 + ldrb r2, [r8], #1 + strb r1, [r7], #1 + strb r2, [r12], #1 + add r0, #1 + cmp r0, r14 + blt LOOP_MAIN_REMAIN_WIDTH + + sub r8, r8, r14, lsl #1 + sub r7, r7, r14 + sub r12, r12, r14 + add r8, r8, #16 + add r7, r7, r3, asr #1 + add r12, r12, r3, asr #1 + + add r4, #1 + cmp r4, #8 + blt LOOP_MAIN_REMAIN_HEIGHT + ldmfd sp!, {r0-r2,r4} @ restore registers +MAIN_REMAIN_WIDTH_END: + + add r5, r5, #8 + cmp r5, r9 + blt LOOP_MAIN_ALIGNED_HEIGHT + +REMAIN_HEIGHT_START: + cmp r9, r4 @ if (aligned_height != height) { + beq REMAIN_HEIGHT_END + + mov r6, #0 +LOOP_REMAIN_HEIGHT_WIDTH16: + mul r8, r11, r5 @ src_offset = (tiled_width * i) + (j << 3) + add r8, r8, r6, lsl #3 + add r8, r2, r8 @ src_offset = uv_src + src_offset + + mov r12, r3, asr #1 @ temp1 = (width >> 1) * i + (j >> 1) + mul r12, r12, r5 + add r12, r12, r6, asr #1 + add r7, r0, r12 @ r7 = u_dst + temp1 + add r12, r1, r12 @ r12 = v_dst + temp1 + mov r14, r3, asr #1 @ temp2 = width / 2 + + stmfd sp!, {r0-r1} @ backup registers + mov r0, #0 + sub r1, r4, r9 +LOOP_REMAIN_HEIGHT_WIDTH16_HEIGHT1: + vld2.8 {d0, d1}, [r8]! + vst1.8 {d0}, [r7], r14 + vst1.8 {d1}, [r12], r14 + + add r0, r0, #1 + cmp r0, r1 + blt LOOP_REMAIN_HEIGHT_WIDTH16_HEIGHT1 + ldmfd sp!, {r0-r1} @ restore registers + + add r6, r6, #16 + cmp r6, r10 + blt LOOP_REMAIN_HEIGHT_WIDTH16 + +REMAIN_HEIGHT_REMAIN_WIDTH_START: + cmp r10, r3 + beq REMAIN_HEIGHT_REMAIN_WIDTH_END + mul r8, r11, r5 @ src_offset = (tiled_width * i) + (j << 3) + add r8, r8, r6, lsl #3 + add r8, r2, r8 @ src_offset = uv_src + src_offset + + mov r12, r3, asr #1 @ temp1 = (width >> 1) * i + (j >> 1) + mul r12, r12, r5 + add r12, r12, r6, asr #1 + add r7, r0, r12 @ r7 = u_dst + temp1 + add r12, r1, r12 @ r12 = v_dst + temp1 + sub r14, r3, r6 @ r14 = (width - j) /2 + mov r14, r14, asr #1 + + stmfd sp!, {r0-r2,r4-r5} @ backup registers + mov r0, #0 + sub r1, r4, r9 +LOOP_REMAIN_HEIGHT_REMAIN_WIDTH_HEIGHT1: + + mov r4, #0 +LOOP_REMAIN_HEIGHT_REMAIN_WIDTH_HEIGHT1_WIDTHx: + ldrb r2, [r8], #1 + ldrb r5, [r8], #1 + strb r2, [r7], #1 + strb r5, [r12], #1 + add r4, #1 + cmp r4, r14 + blt LOOP_REMAIN_HEIGHT_REMAIN_WIDTH_HEIGHT1_WIDTHx + + sub r8, r8, r14, lsl #1 + sub r7, r7, r14 + sub r12, r12, r14 + add r8, r8, #16 + add r7, r7, r3, asr #1 + add r12, r12, r3, asr #1 + + add r0, r0, #1 + cmp r0, r1 + blt LOOP_REMAIN_HEIGHT_REMAIN_WIDTH_HEIGHT1 + ldmfd sp!, {r0-r2,r4-r5} @ restore registers + +REMAIN_HEIGHT_REMAIN_WIDTH_END: + +REMAIN_HEIGHT_END: + +RESTORE_REG: + ldmfd sp!, {r4-r12,r15} @ restore registers + + .fnend diff --git a/exynos/multimedia/utils/csc/exynos5/csc_tiled_to_linear_uv_neon.s b/exynos/multimedia/utils/csc/exynos5/csc_tiled_to_linear_uv_neon.s new file mode 100644 index 0000000..ad58419 --- /dev/null +++ b/exynos/multimedia/utils/csc/exynos5/csc_tiled_to_linear_uv_neon.s @@ -0,0 +1,216 @@ +/* + * + * Copyright 2010 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License") + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file csc_tiled_to_linear_uv.s + * @brief SEC_OMX specific define. It support MFC 6.x tiled. + * @author ShinWon Lee (shinwon.lee@samsung.com) + * @version 1.0 + * @history + * 2011.12.01 : Create + */ + +/* + * Converts tiled data to linear for mfc 6.x tiled + * 1. uv of nv12t to y of yuv420s + * + * @param dst + * uv address of yuv420s[out] + * + * @param src + * uv address of nv12t[in] + * + * @param yuv420_width + * real width of yuv420s[in] + * + * @param yuv420_height + * real height of yuv420s[in] + * + */ + .arch armv7-a + .text + .global csc_tiled_to_linear_uv_neon + .type csc_tiled_to_linear_uv_neon, %function +csc_tiled_to_linear_uv_neon: + .fnstart + + .equ CACHE_LINE_SIZE, 64 + + @r0 y_dst + @r1 y_src + @r2 width + @r3 height + @r4 temp3 + @r5 i + @r6 j + @r7 dst_offset + @r8 src_offset + @r9 aligned_height + @r10 aligned_width + @r11 tiled_width + @r12 temp1 + @r14 temp2 + + stmfd sp!, {r4-r12,r14} @ backup registers + ldr r4, [sp, #40] @ r4 = height + + bic r9, r3, #0x7 @ aligned_height = height & (~0xF) + bic r10, r2, #0xF @ aligned_width = width & (~0xF) + add r11, r2, #15 @ tiled_width = ((width + 15) >> 4) << 4 + mov r11, r11, asr #4 + mov r11, r11, lsl #4 + + mov r5, #0 +LOOP_MAIN_ALIGNED_HEIGHT: + mul r8, r11, r5 @ src_offset = tiled_width * i + mov r6, #0 + add r8, r1, r8 @ src_offset = y_src + src_offset +LOOP_MAIN_ALIGNED_WIDTH: + pld [r8, #CACHE_LINE_SIZE] + vld1.8 {q0, q1}, [r8]! + mul r12, r2, r5 @ temp1 = width * i + j; + vld1.8 {q2, q3}, [r8]! + add r12, r12, r6 + pld [r8, #CACHE_LINE_SIZE] + vld1.8 {q4, q5}, [r8]! + add r7, r0, r12 @ dst_offset = y_dst + temp1 + vld1.8 {q6, q7}, [r8]! + + vst1.8 {q0}, [r7], r2 + vst1.8 {q1}, [r7], r2 + vst1.8 {q2}, [r7], r2 + vst1.8 {q3}, [r7], r2 + vst1.8 {q4}, [r7], r2 + vst1.8 {q5}, [r7], r2 + vst1.8 {q6}, [r7], r2 + vst1.8 {q7}, [r7], r2 + add r6, r6, #16 + cmp r6, r10 + blt LOOP_MAIN_ALIGNED_WIDTH + +MAIN_REMAIN_WIDTH_START: + cmp r10, r2 @ if (aligned_width != width) { + beq MAIN_REMAIN_WIDTH_END + + mul r8, r11, r5 @ src_offset = (tiled_width * i) + (j << 3); + add r8, r8, r6, lsl #3 + add r8, r1, r8 @ r8 = y_src + src_offset + + mul r12, r2, r5 @ temp1 = width * i + j; + add r12, r12, r6 + add r7, r0, r12 @ r7 = y_dst + temp1 + sub r14, r2, r6 @ r14 = width - j + + stmfd sp!, {r0-r1} @ backup registers + mov r1, #0 +LOOP_MAIN_REMAIN_HEIGHT: + mov r0, #0 @ r0 is index in memcpy +LOOP_MAIN_REMAIN_WIDTH: + ldrh r4, [r8], #2 + strh r4, [r7], #2 + add r0, #2 + cmp r0, r14 + blt LOOP_MAIN_REMAIN_WIDTH + + sub r8, r8, r14 + sub r7, r7, r14 + add r8, r8, #16 + add r7, r7, r2 + + add r1, #1 + cmp r1, #8 + blt LOOP_MAIN_REMAIN_HEIGHT + ldmfd sp!, {r0-r1} @ restore registers +MAIN_REMAIN_WIDTH_END: + + add r5, r5, #8 + cmp r5, r9 + blt LOOP_MAIN_ALIGNED_HEIGHT + +REMAIN_HEIGHT_START: + cmp r9, r3 @ if (aligned_height != height) { + beq REMAIN_HEIGHT_END + + mov r6, #0 +LOOP_REMAIN_HEIGHT_WIDTH16: + mul r8, r11, r5 @ src_offset = (tiled_width * i) + (j << 3) + add r8, r8, r6, lsl #3 + add r8, r1, r8 @ src_offset = y_src + src_offset + + mul r12, r2, r5 @ temp1 = width * i + j; + add r12, r12, r6 + add r7, r0, r12 @ r7 = y_dst + temp1 + + sub r12, r3, r9 + mov r14, #0 +LOOP_REMAIN_HEIGHT_WIDTH16_HEIGHT1: + vld1.8 {q0}, [r8]! + vld1.8 {q1}, [r8]! + vst1.8 {q0}, [r7], r2 + vst1.8 {q1}, [r7], r2 + + add r14, r14, #2 + cmp r14, r12 + blt LOOP_REMAIN_HEIGHT_WIDTH16_HEIGHT1 + + add r6, r6, #16 + cmp r6, r10 + blt LOOP_REMAIN_HEIGHT_WIDTH16 + +REMAIN_HEIGHT_REMAIN_WIDTH_START: + cmp r10, r2 + beq REMAIN_HEIGHT_REMAIN_WIDTH_END + mul r8, r11, r5 @ src_offset = (tiled_width * i) + (j << 3) + add r8, r8, r6, lsl #3 + add r8, r1, r8 @ src_offset = y_src + src_offset + + mul r12, r2, r5 @ temp1 = width * i + j; + add r12, r12, r6 + add r7, r0, r12 @ r7 = y_dst + temp1 + + stmfd sp!, {r0-r1,r3} @ backup registers + mov r0, #0 + sub r1, r3, r9 +LOOP_REMAIN_HEIGHT_REMAIN_WIDTH_HEIGHT1: + + sub r14, r2, r6 + mov r4, #0 +LOOP_REMAIN_HEIGHT_REMAIN_WIDTH_HEIGHT1_WIDTHx: + ldrh r3, [r8], #2 + strh r3, [r7], #2 + add r4, #2 + cmp r4, r14 + blt LOOP_REMAIN_HEIGHT_REMAIN_WIDTH_HEIGHT1_WIDTHx + + sub r8, r8, r14 + sub r7, r7, r14 + add r8, r8, #16 + add r7, r7, r2 + + add r0, r0, #1 + cmp r0, r1 + blt LOOP_REMAIN_HEIGHT_REMAIN_WIDTH_HEIGHT1 + ldmfd sp!, {r0-r1,r3} @ restore registers + +REMAIN_HEIGHT_REMAIN_WIDTH_END: + +REMAIN_HEIGHT_END: + +RESTORE_REG: + ldmfd sp!, {r4-r12,r15} @ restore registers + + .fnend diff --git a/exynos/multimedia/utils/csc/exynos5/csc_tiled_to_linear_y_neon.s b/exynos/multimedia/utils/csc/exynos5/csc_tiled_to_linear_y_neon.s new file mode 100644 index 0000000..1aa3b13 --- /dev/null +++ b/exynos/multimedia/utils/csc/exynos5/csc_tiled_to_linear_y_neon.s @@ -0,0 +1,231 @@ +/* + * + * Copyright 2010 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License") + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file csc_tiled_to_linear_y.s + * @brief SEC_OMX specific define. It support MFC 6.x tiled. + * @author ShinWon Lee (shinwon.lee@samsung.com) + * @version 1.0 + * @history + * 2011.12.01 : Create + */ + +/* + * Converts tiled data to linear for mfc 6.x + * 1. Y of NV12T to Y of YUV420P + * 2. Y of NV12T to Y of YUV420S + * + * @param dst + * Y address of YUV420[out] + * + * @param src + * Y address of NV12T[in] + * + * @param yuv420_width + * real width of YUV420[in]. It should be even. + * + * @param yuv420_height + * real height of YUV420[in] It should be even. + * + */ + .arch armv7-a + .text + .global csc_tiled_to_linear_y_neon + .type csc_tiled_to_linear_y_neon, %function +csc_tiled_to_linear_y_neon: + .fnstart + + .equ CACHE_LINE_SIZE, 64 + + @r0 y_dst + @r1 y_src + @r2 width + @r3 height + @r4 temp3 + @r5 i + @r6 j + @r7 dst_offset + @r8 src_offset + @r9 aligned_height + @r10 aligned_width + @r11 tiled_width + @r12 temp1 + @r14 temp2 + + stmfd sp!, {r4-r12,r14} @ backup registers + ldr r4, [sp, #40] @ r4 = height + + bic r9, r3, #0xF @ aligned_height = height & (~0xF) + bic r10, r2, #0xF @ aligned_width = width & (~0xF) + add r11, r2, #15 @ tiled_width = ((width + 15) >> 4) << 4 + mov r11, r11, asr #4 + mov r11, r11, lsl #4 + + mov r5, #0 +LOOP_MAIN_ALIGNED_HEIGHT: + mul r8, r11, r5 @ src_offset = tiled_width * i + mov r6, #0 + add r8, r1, r8 @ src_offset = y_src + src_offset +LOOP_MAIN_ALIGNED_WIDTH: + pld [r8, #CACHE_LINE_SIZE] + vld1.8 {q0, q1}, [r8]! + vld1.8 {q2, q3}, [r8]! + pld [r8, #CACHE_LINE_SIZE] + vld1.8 {q4, q5}, [r8]! + vld1.8 {q6, q7}, [r8]! + mul r12, r2, r5 @ temp1 = width * i + j; + pld [r8, #CACHE_LINE_SIZE] + vld1.8 {q8, q9}, [r8]! + add r12, r12, r6 + vld1.8 {q10, q11}, [r8]! + add r7, r0, r12 @ dst_offset = y_dst + temp1 + pld [r8, #CACHE_LINE_SIZE] + vld1.8 {q12, q13}, [r8]! + vld1.8 {q14, q15}, [r8]! + + vst1.8 {q0}, [r7], r2 + vst1.8 {q1}, [r7], r2 + vst1.8 {q2}, [r7], r2 + vst1.8 {q3}, [r7], r2 + vst1.8 {q4}, [r7], r2 + vst1.8 {q5}, [r7], r2 + vst1.8 {q6}, [r7], r2 + vst1.8 {q7}, [r7], r2 + vst1.8 {q8}, [r7], r2 + vst1.8 {q9}, [r7], r2 + vst1.8 {q10}, [r7], r2 + vst1.8 {q11}, [r7], r2 + vst1.8 {q12}, [r7], r2 + vst1.8 {q13}, [r7], r2 + add r6, r6, #16 + vst1.8 {q14}, [r7], r2 + cmp r6, r10 + vst1.8 {q15}, [r7], r2 + blt LOOP_MAIN_ALIGNED_WIDTH + +MAIN_REMAIN_WIDTH_START: + cmp r10, r2 @ if (aligned_width != width) { + beq MAIN_REMAIN_WIDTH_END + + mul r8, r11, r5 @ src_offset = (tiled_width * i) + (j << 4); + add r8, r8, r6, lsl #4 + add r8, r1, r8 @ r8 = y_src + src_offset + + mul r12, r2, r5 @ temp1 = width * i + j; + add r12, r12, r6 + add r7, r0, r12 @ r7 = y_dst + temp1 + sub r14, r2, r6 @ r14 = width - j + + stmfd sp!, {r0-r1} @ backup registers + mov r1, #0 +LOOP_MAIN_REMAIN_HEIGHT: + mov r0, #0 @ r0 is index in memcpy +LOOP_MAIN_REMAIN_WIDTH: + ldrh r4, [r8], #2 + strh r4, [r7], #2 + add r0, #2 + cmp r0, r14 + blt LOOP_MAIN_REMAIN_WIDTH + + sub r8, r8, r14 + sub r7, r7, r14 + add r8, r8, #16 + add r7, r7, r2 + + add r1, #1 + cmp r1, #16 + blt LOOP_MAIN_REMAIN_HEIGHT + ldmfd sp!, {r0-r1} @ restore registers +MAIN_REMAIN_WIDTH_END: + + add r5, r5, #16 + cmp r5, r9 + blt LOOP_MAIN_ALIGNED_HEIGHT + +REMAIN_HEIGHT_START: + cmp r9, r3 @ if (aligned_height != height) { + beq REMAIN_HEIGHT_END + + mov r6, #0 +LOOP_REMAIN_HEIGHT_WIDTH16: + mul r8, r11, r5 @ src_offset = (tiled_width * i) + (j << 4) + add r8, r8, r6, lsl #4 + add r8, r1, r8 @ src_offset = y_src + src_offset + + mul r12, r2, r5 @ temp1 = width * i + j; + add r12, r12, r6 + add r7, r0, r12 @ r7 = y_dst + temp1 + + sub r12, r3, r9 + mov r14, #0 +LOOP_REMAIN_HEIGHT_WIDTH16_HEIGHT1: + vld1.8 {q0}, [r8]! + vld1.8 {q1}, [r8]! + vst1.8 {q0}, [r7], r2 + vst1.8 {q1}, [r7], r2 + + add r14, r14, #2 + cmp r14, r12 + blt LOOP_REMAIN_HEIGHT_WIDTH16_HEIGHT1 + + add r6, r6, #16 + cmp r6, r10 + blt LOOP_REMAIN_HEIGHT_WIDTH16 + +REMAIN_HEIGHT_REMAIN_WIDTH_START: + cmp r10, r2 + beq REMAIN_HEIGHT_REMAIN_WIDTH_END + mul r8, r11, r5 @ src_offset = (tiled_width * i) + (j << 4) + add r8, r8, r6, lsl #4 + add r8, r1, r8 @ src_offset = y_src + src_offset + + mul r12, r2, r5 @ temp1 = width * i + j; + add r12, r12, r6 + add r7, r0, r12 @ r7 = y_dst + temp1 + + stmfd sp!, {r0-r1,r3} @ backup registers + mov r0, #0 + sub r1, r3, r9 +LOOP_REMAIN_HEIGHT_REMAIN_WIDTH_HEIGHT1: + + sub r14, r2, r6 + mov r4, #0 +LOOP_REMAIN_HEIGHT_REMAIN_WIDTH_HEIGHT1_WIDTHx: + ldrh r3, [r8], #2 + strh r3, [r7], #2 + add r4, #2 + cmp r4, r14 + blt LOOP_REMAIN_HEIGHT_REMAIN_WIDTH_HEIGHT1_WIDTHx + + sub r8, r8, r14 + sub r7, r7, r14 + add r8, r8, #16 + add r7, r7, r2 + + add r0, r0, #1 + cmp r0, r1 + blt LOOP_REMAIN_HEIGHT_REMAIN_WIDTH_HEIGHT1 + ldmfd sp!, {r0-r1,r3} @ restore registers + +REMAIN_HEIGHT_REMAIN_WIDTH_END: + +REMAIN_HEIGHT_END: + +RESTORE_REG: + ldmfd sp!, {r4-r12,r15} @ restore registers + + .fnend diff --git a/exynos4/Android.mk b/exynos4/exynos4210/Android.mk similarity index 78% rename from exynos4/Android.mk rename to exynos4/exynos4210/Android.mk index 3c99f1a..89f6189 100644 --- a/exynos4/Android.mk +++ b/exynos4/exynos4210/Android.mk @@ -1,3 +1,4 @@ +# # Copyright (C) 2012 The Android Open Source Project # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -11,13 +12,11 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. +# ifeq ($(TARGET_BOARD_PLATFORM),exynos4) +exynos4210_dirs := liblights libsensors -BOARD_HAL_PATH := hardware/samsung/exynos4/hal -BOARD_HMM_PATH := hardware/samsung/exynos4/multimedia - -include $(BOARD_HAL_PATH)/Android.mk -include $(BOARD_HMM_PATH)/Android.mk +include $(call all-named-subdir-makefiles,$(exynos4210_dirs)) endif diff --git a/exynos4/hal/liblights/Android.mk b/exynos4/exynos4210/liblights/Android.mk similarity index 100% rename from exynos4/hal/liblights/Android.mk rename to exynos4/exynos4210/liblights/Android.mk diff --git a/exynos4/hal/liblights/NOTICE b/exynos4/exynos4210/liblights/NOTICE similarity index 100% rename from exynos4/hal/liblights/NOTICE rename to exynos4/exynos4210/liblights/NOTICE diff --git a/exynos4/hal/liblights/lights.c b/exynos4/exynos4210/liblights/lights.c similarity index 100% rename from exynos4/hal/liblights/lights.c rename to exynos4/exynos4210/liblights/lights.c diff --git a/exynos4/hal/libsensors/AkmSensor.cpp b/exynos4/exynos4210/libsensors/AkmSensor.cpp similarity index 100% rename from exynos4/hal/libsensors/AkmSensor.cpp rename to exynos4/exynos4210/libsensors/AkmSensor.cpp diff --git a/exynos4/hal/libsensors/AkmSensor.h b/exynos4/exynos4210/libsensors/AkmSensor.h similarity index 100% rename from exynos4/hal/libsensors/AkmSensor.h rename to exynos4/exynos4210/libsensors/AkmSensor.h diff --git a/exynos4/hal/libsensors/Android.mk b/exynos4/exynos4210/libsensors/Android.mk similarity index 100% rename from exynos4/hal/libsensors/Android.mk rename to exynos4/exynos4210/libsensors/Android.mk diff --git a/exynos4/hal/libsensors/GyroSensor.cpp b/exynos4/exynos4210/libsensors/GyroSensor.cpp similarity index 100% rename from exynos4/hal/libsensors/GyroSensor.cpp rename to exynos4/exynos4210/libsensors/GyroSensor.cpp diff --git a/exynos4/hal/libsensors/GyroSensor.h b/exynos4/exynos4210/libsensors/GyroSensor.h similarity index 100% rename from exynos4/hal/libsensors/GyroSensor.h rename to exynos4/exynos4210/libsensors/GyroSensor.h diff --git a/exynos4/hal/libsensors/InputEventReader.cpp b/exynos4/exynos4210/libsensors/InputEventReader.cpp similarity index 100% rename from exynos4/hal/libsensors/InputEventReader.cpp rename to exynos4/exynos4210/libsensors/InputEventReader.cpp diff --git a/exynos4/hal/libsensors/InputEventReader.h b/exynos4/exynos4210/libsensors/InputEventReader.h similarity index 100% rename from exynos4/hal/libsensors/InputEventReader.h rename to exynos4/exynos4210/libsensors/InputEventReader.h diff --git a/exynos4/hal/libsensors/LightSensor.cpp b/exynos4/exynos4210/libsensors/LightSensor.cpp similarity index 100% rename from exynos4/hal/libsensors/LightSensor.cpp rename to exynos4/exynos4210/libsensors/LightSensor.cpp diff --git a/exynos4/hal/libsensors/LightSensor.h b/exynos4/exynos4210/libsensors/LightSensor.h similarity index 100% rename from exynos4/hal/libsensors/LightSensor.h rename to exynos4/exynos4210/libsensors/LightSensor.h diff --git a/exynos4/hal/libsensors/MODULE_LICENSE_APACHE2 b/exynos4/exynos4210/libsensors/MODULE_LICENSE_APACHE2 similarity index 100% rename from exynos4/hal/libsensors/MODULE_LICENSE_APACHE2 rename to exynos4/exynos4210/libsensors/MODULE_LICENSE_APACHE2 diff --git a/exynos4/hal/libsensors/ProximitySensor.cpp b/exynos4/exynos4210/libsensors/ProximitySensor.cpp similarity index 100% rename from exynos4/hal/libsensors/ProximitySensor.cpp rename to exynos4/exynos4210/libsensors/ProximitySensor.cpp diff --git a/exynos4/hal/libsensors/ProximitySensor.h b/exynos4/exynos4210/libsensors/ProximitySensor.h similarity index 100% rename from exynos4/hal/libsensors/ProximitySensor.h rename to exynos4/exynos4210/libsensors/ProximitySensor.h diff --git a/exynos4/hal/libsensors/SensorBase.cpp b/exynos4/exynos4210/libsensors/SensorBase.cpp similarity index 100% rename from exynos4/hal/libsensors/SensorBase.cpp rename to exynos4/exynos4210/libsensors/SensorBase.cpp diff --git a/exynos4/hal/libsensors/SensorBase.h b/exynos4/exynos4210/libsensors/SensorBase.h similarity index 100% rename from exynos4/hal/libsensors/SensorBase.h rename to exynos4/exynos4210/libsensors/SensorBase.h diff --git a/exynos4/hal/libsensors/ak8973b.h b/exynos4/exynos4210/libsensors/ak8973b.h similarity index 100% rename from exynos4/hal/libsensors/ak8973b.h rename to exynos4/exynos4210/libsensors/ak8973b.h diff --git a/exynos4/hal/libsensors/sensors.cpp b/exynos4/exynos4210/libsensors/sensors.cpp similarity index 100% rename from exynos4/hal/libsensors/sensors.cpp rename to exynos4/exynos4210/libsensors/sensors.cpp diff --git a/exynos4/hal/libsensors/sensors.h b/exynos4/exynos4210/libsensors/sensors.h similarity index 100% rename from exynos4/hal/libsensors/sensors.h rename to exynos4/exynos4210/libsensors/sensors.h diff --git a/exynos4/hal/Android.mk b/exynos4/hal/Android.mk index c1c40da..5765418 100644 --- a/exynos4/hal/Android.mk +++ b/exynos4/hal/Android.mk @@ -1,2 +1,29 @@ -exynos4_dirs := libfimg libhwconverter liblights libs5pjpeg libsensors libswconverter libump -include $(call all-named-subdir-makefiles,$(exynos4_dirs)) +# +# Copyright (C) 2012 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +ifeq ($(TARGET_BOARD_PLATFORM),exynos4) +#common_exynos4_dirs := libgralloc_ump libhdmi libfimc libhwcomposer libcamera libhwconverter +common_exynos4_dirs := libgralloc_ump libhdmi libfimc libhwcomposer libhwconverter +exynos4210_dirs := $(common_exynos4_dirs) libs5pjpeg libfimg3x + +exynos4x12_dirs := $(common_exynos4_dirs) libhwjpeg libfimg4x + +ifeq ($(TARGET_SOC),exynos4210) + include $(call all-named-subdir-makefiles,$(exynos4210_dirs)) +else + include $(call all-named-subdir-makefiles,$(exynos4x12_dirs)) +endif +endif diff --git a/exynos4/hal/include/SecHdmi.h b/exynos4/hal/include/SecHdmi.h index 67c3378..08bee20 100644 --- a/exynos4/hal/include/SecHdmi.h +++ b/exynos4/hal/include/SecHdmi.h @@ -159,6 +159,7 @@ private : void *mFBaddr; unsigned int mFBsize; int mFBionfd; + unsigned int mFBIndex; int mHdmiFd[HDMI_LAYER_MAX]; int mDstWidth[HDMI_LAYER_MAX]; diff --git a/exynos4/hal/include/gralloc_priv.h b/exynos4/hal/include/gralloc_priv.h index 9f3346a..8ffd161 100644 --- a/exynos4/hal/include/gralloc_priv.h +++ b/exynos4/hal/include/gralloc_priv.h @@ -1,6 +1,14 @@ /* * Copyright (C) 2010 ARM Limited. All rights reserved. * + * Portions of this code have been modified from the original. + * These modifications are: + * * includes + * * struct private_handle_t + * * usesPhysicallyContiguousMemory() + * * validate() + * * dynamicCast() + * * Copyright (C) 2008 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -27,145 +35,200 @@ #include #include -#include +/*#include */ +#include "ump.h" + +/* + * HWC_HWOVERLAY is flag for location of glReadPixels(). + * Enable this define if you want that glReadPixesl() is in HWComposer. + * If you disable this define, glReadPixesl() is called in threadloop(). + */ +#define HWC_HWOVERLAY 1 #define GRALLOC_ARM_UMP_MODULE 1 struct private_handle_t; -struct private_module_t -{ - gralloc_module_t base; +struct private_module_t { + gralloc_module_t base; - private_handle_t* framebuffer; - uint32_t flags; - uint32_t numBuffers; - uint32_t bufferMask; - pthread_mutex_t lock; - buffer_handle_t currentBuffer; + private_handle_t* framebuffer; + uint32_t flags; + uint32_t numBuffers; + uint32_t bufferMask; + pthread_mutex_t lock; + buffer_handle_t currentBuffer; + int ion_client; - struct fb_var_screeninfo info; - struct fb_fix_screeninfo finfo; - float xdpi; - float ydpi; - float fps; + struct fb_var_screeninfo info; + struct fb_fix_screeninfo finfo; + float xdpi; + float ydpi; + float fps; + int enableVSync; - enum - { - // flag to indicate we'll post this buffer - PRIV_USAGE_LOCKED_FOR_POST = 0x80000000 - }; + enum { + PRIV_USAGE_LOCKED_FOR_POST = 0x80000000 + }; }; +#ifdef USE_PARTIAL_FLUSH +struct private_handle_rect { + int handle; + int stride; + int l; + int t; + int w; + int h; + int locked; + struct private_handle_rect *next; +}; +#endif + #ifdef __cplusplus struct private_handle_t : public native_handle { #else -struct private_handle_t -{ - struct native_handle nativeHandle; +struct private_handle_t { + struct native_handle nativeHandle; #endif + enum { + PRIV_FLAGS_FRAMEBUFFER = 0x00000001, + PRIV_FLAGS_USES_UMP = 0x00000002, + PRIV_FLAGS_USES_PMEM = 0x00000004, + PRIV_FLAGS_USES_IOCTL = 0x00000008, + PRIV_FLAGS_USES_HDMI = 0x00000010, + PRIV_FLAGS_USES_ION = 0x00000020, + PRIV_FLAGS_NONE_CACHED = 0x00000040, + }; - enum - { - PRIV_FLAGS_FRAMEBUFFER = 0x00000001, - PRIV_FLAGS_USES_UMP = 0x00000002, - }; + enum { + LOCK_STATE_WRITE = 1<<31, + LOCK_STATE_MAPPED = 1<<30, + LOCK_STATE_READ_MASK = 0x3FFFFFFF + }; - enum - { - LOCK_STATE_WRITE = 1<<31, - LOCK_STATE_MAPPED = 1<<30, - LOCK_STATE_READ_MASK = 0x3FFFFFFF - }; + int fd; - // ints - int magic; - int flags; - int size; - int base; - int lockState; - int writeOwner; - int pid; + int magic; + int flags; + int size; + int base; + int lockState; + int writeOwner; + int pid; - // Following members are for UMP memory only - int ump_id; - int ump_mem_handle; + /* Following members are for UMP memory only */ + int ump_id; + int ump_mem_handle; + int offset; + int paddr; - // Following members is for framebuffer only - int fd; - int offset; + int format; + int usage; + int width; + int height; + int bpp; + int stride; + /* Following members are for ION memory only */ + int ion_client; + + /* Following members ard for YUV information */ + unsigned int yaddr; + unsigned int uoffset; + unsigned int voffset; #ifdef __cplusplus - static const int sNumInts = 11; - static const int sNumFds = 0; - static const int sMagic = 0x3141592; + static const int sNumInts = 21; + static const int sNumFds = 1; + static const int sMagic = 0x3141592; - private_handle_t(int flags, int size, int base, int lock_state, ump_secure_id secure_id, ump_handle handle): - magic(sMagic), - flags(flags), - size(size), - base(base), - lockState(lock_state), - writeOwner(0), - pid(getpid()), - ump_id((int)secure_id), - ump_mem_handle((int)handle), - fd(0), - offset(0) - { - version = sizeof(native_handle); - numFds = sNumFds; - numInts = sNumInts; - } + private_handle_t(int flags, int size, int base, int lock_state, ump_secure_id secure_id, ump_handle handle,int fd_val, int offset_val, int paddr_val): + fd(fd_val), + magic(sMagic), + flags(flags), + size(size), + base(base), + lockState(lock_state), + writeOwner(0), + pid(getpid()), + ump_id((int)secure_id), + ump_mem_handle((int)handle), + offset(offset_val), + paddr(paddr_val), + format(0), + usage(0), + width(0), + height(0), + bpp(0), + stride(0), + ion_client(0), + yaddr(0), + uoffset(0), + voffset(0) + { + version = sizeof(native_handle); + numFds = sNumFds; + numInts = sNumInts; + } - private_handle_t(int flags, int size, int base, int lock_state, int fb_file, int fb_offset): - magic(sMagic), - flags(flags), - size(size), - base(base), - lockState(lock_state), - writeOwner(0), - pid(getpid()), - ump_id((int)UMP_INVALID_SECURE_ID), - ump_mem_handle((int)UMP_INVALID_MEMORY_HANDLE), - fd(fb_file), - offset(fb_offset) - { - version = sizeof(native_handle); - numFds = sNumFds; - numInts = sNumInts; - } + private_handle_t(int flags, int size, int base, int lock_state, int fb_file, int fb_offset): + fd(fb_file), + magic(sMagic), + flags(flags), + size(size), + base(base), + lockState(lock_state), + writeOwner(0), + pid(getpid()), + ump_id((int)UMP_INVALID_SECURE_ID), + ump_mem_handle((int)UMP_INVALID_MEMORY_HANDLE), + offset(fb_offset), + paddr(0), + format(0), + usage(0), + width(0), + height(0), + bpp(0), + stride(0), + ion_client(0), + yaddr(0), + uoffset(0), + voffset(0) + { + version = sizeof(native_handle); + numFds = sNumFds; + numInts = sNumInts; + } - ~private_handle_t() - { - magic = 0; - } + ~private_handle_t() + { + magic = 0; + } - bool usesPhysicallyContiguousMemory() - { - return (flags & PRIV_FLAGS_FRAMEBUFFER) ? true : false; - } + bool usesPhysicallyContiguousMemory() + { + return (flags & PRIV_FLAGS_FRAMEBUFFER) ? true : false; + } - static int validate(const native_handle* h) - { - const private_handle_t* hnd = (const private_handle_t*)h; - if (!h || h->version != sizeof(native_handle) || h->numInts != sNumInts || h->numFds != sNumFds || hnd->magic != sMagic) - { - return -EINVAL; - } - return 0; - } + static int validate(const native_handle* h) + { + const private_handle_t* hnd = (const private_handle_t*)h; + if (!h || h->version != sizeof(native_handle) || + h->numInts != sNumInts || + h->numFds != sNumFds || + hnd->magic != sMagic) + return -EINVAL; + return 0; + } - static private_handle_t* dynamicCast(const native_handle* in) - { - if (validate(in) == 0) - { - return (private_handle_t*) in; - } - return NULL; - } + static private_handle_t* dynamicCast(const native_handle* in) + { + if (validate(in) == 0) + return (private_handle_t*) in; + return NULL; + } #endif }; diff --git a/exynos4/hal/include/s3c_lcd.h b/exynos4/hal/include/s3c_lcd.h index 7f2dec7..2782542 100644 --- a/exynos4/hal/include/s3c_lcd.h +++ b/exynos4/hal/include/s3c_lcd.h @@ -55,7 +55,6 @@ typedef struct { #ifdef BOARD_USE_V4L2_ION struct s3c_fb_user_ion_client { int fd; - int offset; }; #endif diff --git a/exynos4/hal/include/sec_format.h b/exynos4/hal/include/sec_format.h index 8722b45..23534c5 100644 --- a/exynos4/hal/include/sec_format.h +++ b/exynos4/hal/include/sec_format.h @@ -27,8 +27,6 @@ enum { HAL_PIXEL_FORMAT_CbYCrY_420_I = 0x104, HAL_PIXEL_FORMAT_YCbCr_420_SP = 0x105, HAL_PIXEL_FORMAT_YCrCb_422_SP = 0x106, - HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED = 0x107, - HAL_PIXEL_FORMAT_ARGB888 = 0x108, // support custom format for zero copy HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_SP = 0x110, HAL_PIXEL_FORMAT_CUSTOM_YCrCb_420_SP = 0x111, diff --git a/exynos4/hal/libump/include/ump/ump.h b/exynos4/hal/include/ump.h similarity index 91% rename from exynos4/hal/libump/include/ump/ump.h rename to exynos4/hal/include/ump.h index 2829113..fd01c44 100644 --- a/exynos4/hal/libump/include/ump/ump.h +++ b/exynos4/hal/include/ump.h @@ -1,17 +1,11 @@ /* - * Copyright (C) 2010-2011 ARM Limited. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * This confidential and proprietary software may be used only as + * authorised by a licensing agreement from ARM Limited + * (C) COPYRIGHT 2008-2010 ARM Limited + * ALL RIGHTS RESERVED + * The entire notice above must be reproduced on all authorised + * copies and copies may only be made to the extent permitted + * by a licensing agreement from ARM Limited. */ /** @@ -31,6 +25,7 @@ #include "ump_platform.h" +#include "ion.h" #ifdef __cplusplus extern "C" { #endif @@ -61,8 +56,8 @@ typedef unsigned int ump_secure_id; */ typedef enum { - UMP_OK = 0, /**< indicates success */ - UMP_ERROR, /**< indicates failure */ + UMP_OK, /**< indicates success */ + UMP_ERROR, /**< indicates failure */ } ump_result; diff --git a/exynos4/hal/include/ump_platform.h b/exynos4/hal/include/ump_platform.h new file mode 100644 index 0000000..9285aef --- /dev/null +++ b/exynos4/hal/include/ump_platform.h @@ -0,0 +1,46 @@ +/* + * This confidential and proprietary software may be used only as + * authorised by a licensing agreement from ARM Limited + * (C) COPYRIGHT 2008-2010 ARM Limited + * ALL RIGHTS RESERVED + * The entire notice above must be reproduced on all authorised + * copies and copies may only be made to the extent permitted + * by a licensing agreement from ARM Limited. + */ + +/** + * @file ump_platform.h + * + * This file should define UMP_API_EXPORT, + * which dictates how the UMP user space API should be exported/imported. + * Modify this file, if needed, to match your platform setup. + */ + +#ifndef __UMP_PLATFORM_H__ +#define __UMP_PLATFORM_H__ + +/** @addtogroup ump_user_space_api + * @{ */ + +/** + * A define which controls how UMP user space API functions are imported and exported. + * This define should be set by the implementor of the UMP API. + */ +#if defined(_WIN32) + +#define UMP_API_EXPORT + +#elif defined(__SYMBIAN32__) + +#define UMP_API_EXPORT IMPORT_C + +#else + +#define UMP_API_EXPORT + +#endif + +/** @} */ /* end group ump_user_space_api */ + + +#endif /* __UMP_PLATFORM_H__ */ diff --git a/exynos4/hal/libump/include/ump/ump_ref_drv.h b/exynos4/hal/include/ump_ref_drv.h similarity index 63% rename from exynos4/hal/libump/include/ump/ump_ref_drv.h rename to exynos4/hal/include/ump_ref_drv.h index 19fb28d..6320f1d 100644 --- a/exynos4/hal/libump/include/ump/ump_ref_drv.h +++ b/exynos4/hal/include/ump_ref_drv.h @@ -1,17 +1,11 @@ /* - * Copyright (C) 2010 ARM Limited. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * This confidential and proprietary software may be used only as + * authorised by a licensing agreement from ARM Limited + * (C) COPYRIGHT 2009-2010 ARM Limited + * ALL RIGHTS RESERVED + * The entire notice above must be reproduced on all authorised + * copies and copies may only be made to the extent permitted + * by a licensing agreement from ARM Limited. */ /** @@ -29,12 +23,12 @@ extern "C" { #endif -typedef enum -{ - /* This enum must match with the IOCTL enum in ump_ioctl.h */ - UMP_REF_DRV_CONSTRAINT_NONE = 0, - UMP_REF_DRV_CONSTRAINT_PHYSICALLY_LINEAR = 1, - UMP_REF_DRV_CONSTRAINT_USE_CACHE = 4, +typedef enum { + /* This enum must match with the IOCTL enum in ump_ioctl.h */ + UMP_REF_DRV_CONSTRAINT_NONE = 0, + UMP_REF_DRV_CONSTRAINT_PHYSICALLY_LINEAR = 1, + /* This enum is included by samsung */ + UMP_REF_DRV_CONSTRAINT_USE_CACHE = 128, } ump_alloc_constraints; /** Allocate an UMP handle containing a memory buffer. @@ -44,8 +38,8 @@ typedef enum * The flag UMP_REF_DRV_CONSTRAINT_PHYSICALLY_LINEAR is not supported.*/ UMP_API_EXPORT ump_handle ump_ref_drv_allocate(unsigned long size, ump_alloc_constraints usage); -typedef enum -{ +UMP_API_EXPORT ump_handle ump_ref_drv_ion_import(int ion_fd, ump_alloc_constraints constraints); +typedef enum { UMP_MSYNC_CLEAN = 0 , UMP_MSYNC_CLEAN_AND_INVALIDATE = 1, UMP_MSYNC_READOUT_CACHE_ENABLED = 128, @@ -58,7 +52,6 @@ typedef enum * Return value is 1 if cache is enabled, and 0 if it is disabled for the given allocation.*/ UMP_API_EXPORT int ump_cpu_msync_now(ump_handle mem, ump_cpu_msync_op op, void* address, int size); - #ifdef __cplusplus } #endif diff --git a/exynos4/hal/libcamera/Android.mk b/exynos4/hal/libcamera/Android.mk new file mode 100644 index 0000000..9523db9 --- /dev/null +++ b/exynos4/hal/libcamera/Android.mk @@ -0,0 +1,38 @@ +LOCAL_PATH:= $(call my-dir) +include $(CLEAR_VARS) + +# HAL module implemenation stored in +# hw/..so +LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw + +LOCAL_C_INCLUDES += $(LOCAL_PATH)/../include + +LOCAL_SRC_FILES:= \ + SecCamera.cpp SecCameraHWInterface.cpp + +LOCAL_SHARED_LIBRARIES:= libutils libcutils libbinder liblog libcamera_client libhardware + +ifeq ($(TARGET_SOC), exynos4210) +LOCAL_SHARED_LIBRARIES += libs5pjpeg +LOCAL_CFLAGS += -DSAMSUNG_EXYNOS4210 +endif + +ifeq ($(TARGET_SOC), exynos4x12) +LOCAL_SHARED_LIBRARIES += libhwjpeg +LOCAL_CFLAGS += -DSAMSUNG_EXYNOS4x12 +endif + +ifeq ($(BOARD_USE_V4L2), true) +LOCAL_CFLAGS += -DBOARD_USE_V4L2 +endif + +ifeq ($(BOARD_USE_V4L2_ION), true) +LOCAL_CFLAGS += -DBOARD_USE_V4L2 +LOCAL_CFLAGS += -DBOARD_USE_V4L2_ION +endif + +LOCAL_MODULE := camera.$(TARGET_BOARD_PLATFORM) + +LOCAL_MODULE_TAGS := optional + +include $(BUILD_SHARED_LIBRARY) diff --git a/exynos4/hal/libcamera/NOTICE b/exynos4/hal/libcamera/NOTICE new file mode 100644 index 0000000..f921593 --- /dev/null +++ b/exynos4/hal/libcamera/NOTICE @@ -0,0 +1,190 @@ + + Copyright (C) 2008 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + diff --git a/exynos4/hal/libcamera/SecCamera.cpp b/exynos4/hal/libcamera/SecCamera.cpp new file mode 100644 index 0000000..9c7bf94 --- /dev/null +++ b/exynos4/hal/libcamera/SecCamera.cpp @@ -0,0 +1,4360 @@ +/* + * Copyright 2008, The Android Open Source Project + * Copyright 2010, Samsung Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* +************************************ +* Filename: SecCamera.cpp +* Author: Sachin P. Kamat +* Purpose: This file interacts with the Camera and JPEG drivers. +************************************* +*/ + +//#define LOG_NDEBUG 0 +#define LOG_TAG "SecCamera" + +#include +#include +#include +#include +#include "SecCamera.h" +#include "cutils/properties.h" + +using namespace android; + +#define CHECK(return_value) \ + if (return_value < 0) { \ + LOGE("%s::%d fail. errno: %s, m_camera_id = %d", \ + __func__, __LINE__, strerror(errno), m_camera_id); \ + return -1; \ + } + +#define CHECK_PTR(return_value) \ + if (return_value < 0) { \ + LOGE("%s::%d fail, errno: %s, m_camera_id = %d", \ + __func__,__LINE__, strerror(errno), m_camera_id); \ + return NULL; \ + } + +namespace android { + +static struct timeval time_start; +static struct timeval time_stop; + +#if defined(LOG_NDEBUG) && LOG_NDEBUG == 0 +unsigned long measure_time_camera(struct timeval *start, struct timeval *stop) +{ + unsigned long sec, usec, time; + + sec = stop->tv_sec - start->tv_sec; + + if (stop->tv_usec >= start->tv_usec) { + usec = stop->tv_usec - start->tv_usec; + } else { + usec = stop->tv_usec + 1000000 - start->tv_usec; + sec--; + } + + time = (sec * 1000000) + usec; + + return time; +} +#endif + +static int close_buffers(struct SecBuffer *buffers, int num_of_buf) +{ + int ret; + + for (int i = 0; i < num_of_buf; i++) { + for(int j = 0; j < MAX_PLANES; j++) { + if (buffers[i].virt.extP[j]) { +#ifndef BOARD_USE_V4L2_ION + ret = munmap(buffers[i].virt.extP[j], buffers[i].size.extS[j]); + LOGV("munmap():buffers[%d].virt.extP[%d]: 0x%x size = %d", + i, j, (unsigned int) buffers[i].virt.extP[j], + buffers[i].size.extS[j]); +#endif + buffers[i].virt.extP[j] = NULL; + } + } + } + + return 0; +} + +static int get_pixel_depth(unsigned int fmt) +{ + int depth = 0; + + switch (fmt) { + case V4L2_PIX_FMT_NV12: + case V4L2_PIX_FMT_NV12T: + case V4L2_PIX_FMT_NV21: + case V4L2_PIX_FMT_YUV420: + case V4L2_PIX_FMT_YVU420: + case V4L2_PIX_FMT_YVU420M: + depth = 12; + break; + + case V4L2_PIX_FMT_RGB565: + case V4L2_PIX_FMT_YUYV: + case V4L2_PIX_FMT_YVYU: + case V4L2_PIX_FMT_UYVY: + case V4L2_PIX_FMT_VYUY: + case V4L2_PIX_FMT_NV16: + case V4L2_PIX_FMT_NV61: + case V4L2_PIX_FMT_YUV422P: + depth = 16; + break; + + case V4L2_PIX_FMT_RGB32: + depth = 32; + break; + } + + return depth; +} + +static int fimc_poll(struct pollfd *events) +{ + int ret; + + /* 10 second delay is because sensor can take a long time + * to do auto focus and capture in dark settings + */ + ret = poll(events, 1, 10000); + if (ret < 0) { + LOGE("ERR(%s):poll error", __func__); + return ret; + } + + if (ret == 0) { + LOGE("ERR(%s):No data in 10 secs..", __func__); + return ret; + } + + return ret; +} + +static int fimc_v4l2_querycap(int fp) +{ + struct v4l2_capability cap; + + if (ioctl(fp, VIDIOC_QUERYCAP, &cap) < 0) { + LOGE("ERR(%s):VIDIOC_QUERYCAP failed", __func__); + return -1; + } + + if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) { + LOGE("ERR(%s):no capture devices", __func__); + return -1; + } + + return 0; +} + +static const __u8* fimc_v4l2_enuminput(int fp, int index) +{ + static struct v4l2_input input; + + input.index = index; + if (ioctl(fp, VIDIOC_ENUMINPUT, &input) != 0) { + LOGE("ERR(%s):No matching index found", __func__); + return NULL; + } + LOGI("Name of input channel[%d] is %s", input.index, input.name); + + return input.name; +} + +static int fimc_v4l2_s_input(int fp, int index) +{ + struct v4l2_input input; + + input.index = index; + + if (ioctl(fp, VIDIOC_S_INPUT, &input) < 0) { + LOGE("ERR(%s):VIDIOC_S_INPUT failed", __func__); + return -1; + } + + return 0; +} + +static int fimc_v4l2_s_fmt(int fp, int width, int height, unsigned int fmt, enum v4l2_field field, unsigned int num_plane) +{ + struct v4l2_format v4l2_fmt; + struct v4l2_pix_format pixfmt; + unsigned int framesize; + + memset(&v4l2_fmt, 0, sizeof(struct v4l2_format)); + v4l2_fmt.type = V4L2_BUF_TYPE; + +#ifdef BOARD_USE_V4L2 + framesize = (width * height * get_pixel_depth(fmt)) / 8; + + v4l2_fmt.fmt.pix_mp.width = width; + v4l2_fmt.fmt.pix_mp.height = height; + v4l2_fmt.fmt.pix_mp.pixelformat = fmt; + v4l2_fmt.fmt.pix_mp.field = field; + if (num_plane == 1) { + v4l2_fmt.fmt.pix_mp.plane_fmt[0].sizeimage = framesize; + } else if (num_plane == 2) { + v4l2_fmt.fmt.pix_mp.plane_fmt[0].sizeimage = ALIGN(width * height, 2048); + v4l2_fmt.fmt.pix_mp.plane_fmt[1].sizeimage = ALIGN(width/2, 16) * ALIGN(height/2, 16) * 2; + } else if (num_plane == 3) { + v4l2_fmt.fmt.pix_mp.plane_fmt[0].sizeimage = ALIGN(width, 16) * ALIGN(height, 16); + v4l2_fmt.fmt.pix_mp.plane_fmt[1].sizeimage = ALIGN(width/2, 16) * ALIGN(height/2, 16); + v4l2_fmt.fmt.pix_mp.plane_fmt[2].sizeimage = ALIGN(width/2, 16) * ALIGN(height/2, 16); + } else { + LOGE("ERR(%s): Invalid plane number", __func__); + return -1; + } + v4l2_fmt.fmt.pix_mp.num_planes = num_plane; +#else + memset(&pixfmt, 0, sizeof(pixfmt)); + + pixfmt.width = width; + pixfmt.height = height; + pixfmt.pixelformat = fmt; + pixfmt.field = V4L2_FIELD_NONE; + + v4l2_fmt.fmt.pix = pixfmt; + LOGV("fimc_v4l2_s_fmt : width(%d) height(%d)", width, height); +#endif + + /* Set up for capture */ + if (ioctl(fp, VIDIOC_S_FMT, &v4l2_fmt) < 0) { + LOGE("ERR(%s):VIDIOC_S_FMT failed", __func__); + return -1; + } + + return 0; +} + +static int fimc_v4l2_s_fmt_cap(int fp, int width, int height, unsigned int fmt) +{ + struct v4l2_format v4l2_fmt; + struct v4l2_pix_format pixfmt; + + memset(&pixfmt, 0, sizeof(pixfmt)); + + v4l2_fmt.type = V4L2_BUF_TYPE; + + pixfmt.width = width; + pixfmt.height = height; + pixfmt.pixelformat = fmt; + if (fmt == V4L2_PIX_FMT_JPEG) + pixfmt.colorspace = V4L2_COLORSPACE_JPEG; + + v4l2_fmt.fmt.pix = pixfmt; + LOGV("fimc_v4l2_s_fmt_cap : width(%d) height(%d)", width, height); + + /* Set up for capture */ + if (ioctl(fp, VIDIOC_S_FMT, &v4l2_fmt) < 0) { + LOGE("ERR(%s):VIDIOC_S_FMT failed", __func__); + return -1; + } + + return 0; +} + +int fimc_v4l2_s_fmt_is(int fp, int width, int height, unsigned int fmt, enum v4l2_field field) +{ + struct v4l2_format v4l2_fmt; + struct v4l2_pix_format pixfmt; + + memset(&pixfmt, 0, sizeof(pixfmt)); + + v4l2_fmt.type = V4L2_BUF_TYPE_PRIVATE; + + pixfmt.width = width; + pixfmt.height = height; + pixfmt.pixelformat = fmt; + pixfmt.field = field; + + v4l2_fmt.fmt.pix = pixfmt; + LOGV("fimc_v4l2_s_fmt_is : width(%d) height(%d)", width, height); + + /* Set up for capture */ + if (ioctl(fp, VIDIOC_S_FMT, &v4l2_fmt) < 0) { + LOGE("ERR(%s):VIDIOC_S_FMT failed", __func__); + return -1; + } + + return 0; +} + +static int fimc_v4l2_enum_fmt(int fp, unsigned int fmt) +{ + struct v4l2_fmtdesc fmtdesc; + int found = 0; + + fmtdesc.type = V4L2_BUF_TYPE; + fmtdesc.index = 0; + + while (ioctl(fp, VIDIOC_ENUM_FMT, &fmtdesc) == 0) { + if (fmtdesc.pixelformat == fmt) { + LOGV("passed fmt = %#x found pixel format[%d]: %s", fmt, fmtdesc.index, fmtdesc.description); + found = 1; + break; + } + + fmtdesc.index++; + } + + if (!found) { + LOGE("unsupported pixel format"); + return -1; + } + + return 0; +} + +static int fimc_v4l2_reqbufs(int fp, enum v4l2_buf_type type, int nr_bufs) +{ + struct v4l2_requestbuffers req; + + req.count = nr_bufs; + req.type = type; + req.memory = V4L2_MEMORY_TYPE; + + if (ioctl(fp, VIDIOC_REQBUFS, &req) < 0) { + LOGE("ERR(%s):VIDIOC_REQBUFS failed", __func__); + return -1; + } + + return req.count; +} + +static int fimc_v4l2_querybuf(int fp, struct SecBuffer *buffers, enum v4l2_buf_type type, int nr_frames, int num_plane) +{ + struct v4l2_buffer v4l2_buf; +#ifdef BOARD_USE_V4L2 + struct v4l2_plane planes[VIDEO_MAX_PLANES]; +#endif + int i, ret, plane_index; + + for (i = 0; i < nr_frames; i++) { + v4l2_buf.type = type; + v4l2_buf.memory = V4L2_MEMORY_TYPE; + v4l2_buf.index = i; +#ifdef BOARD_USE_V4L2 + v4l2_buf.m.planes = planes; + v4l2_buf.length = num_plane; // this is for multi-planar + LOGV("QUERYBUF(index=%d)", i); + LOGV("memory plane is %d", v4l2_buf.length); +#endif + + ret = ioctl(fp, VIDIOC_QUERYBUF, &v4l2_buf); + if (ret < 0) { + LOGE("ERR(%s):VIDIOC_QUERYBUF failed", __func__); + return -1; + } + +#ifdef BOARD_USE_V4L2 + for (plane_index = 0; plane_index < num_plane; plane_index++) { + LOGV("Offset : 0x%x", v4l2_buf.m.planes[plane_index].m.mem_offset); + LOGV("Plane Length : 0x%x", v4l2_buf.m.planes[plane_index].length); + + buffers[i].phys.extP[plane_index] = (unsigned int)v4l2_buf.m.planes[plane_index].cookie; + + buffers[i].size.extS[plane_index] = v4l2_buf.m.planes[plane_index].length; + LOGV("length[%d] : 0x%x", i, buffers[i].size.extS[plane_index]); + if ((buffers[i].virt.extP[plane_index] = (char *)mmap(0, v4l2_buf.m.planes[plane_index].length, + PROT_READ | PROT_WRITE, MAP_SHARED, fp, v4l2_buf.m.planes[plane_index].m.mem_offset)) < 0) { + LOGE("mmap failed"); + return -1; + } + LOGV("vaddr[%d][%d] : 0x%x", i, plane_index, (__u32) buffers[i].virt.extP[plane_index]); + } +#else + buffers[i].size.s = v4l2_buf.length; + + if ((buffers[i].virt.p = (char *)mmap(0, v4l2_buf.length, PROT_READ | PROT_WRITE, MAP_SHARED, + fp, v4l2_buf.m.offset)) < 0) { + LOGE("%s %d] mmap() failed",__func__, __LINE__); + return -1; + } + LOGV("buffers[%d].virt.p = %p v4l2_buf.length = %d", i, buffers[i].virt.p, v4l2_buf.length); +#endif + } + return 0; +} + +static int fimc_v4l2_streamon(int fp) +{ + enum v4l2_buf_type type = V4L2_BUF_TYPE; + int ret; + + ret = ioctl(fp, VIDIOC_STREAMON, &type); + if (ret < 0) { + LOGE("ERR(%s):VIDIOC_STREAMON failed", __func__); + return ret; + } + + return ret; +} + +static int fimc_v4l2_streamoff(int fp) +{ + enum v4l2_buf_type type = V4L2_BUF_TYPE; + int ret; + + LOGV("%s :", __func__); + ret = ioctl(fp, VIDIOC_STREAMOFF, &type); + if (ret < 0) { + LOGE("ERR(%s):VIDIOC_STREAMOFF failed", __func__); + return ret; + } + + return ret; +} + +static int fimc_v4l2_qbuf(int fp, int width, int height, struct SecBuffer *vaddr, int index, int num_plane, int mode) +{ + struct v4l2_buffer v4l2_buf; + int ret; + +#ifdef BOARD_USE_V4L2 + struct v4l2_plane planes[VIDEO_MAX_PLANES]; + + v4l2_buf.m.planes = planes; + v4l2_buf.length = num_plane; +#endif + + v4l2_buf.type = V4L2_BUF_TYPE; + v4l2_buf.memory = V4L2_MEMORY_TYPE; + v4l2_buf.index = index; + +#ifdef BOARD_USE_V4L2_ION + if (mode == PREVIEW_MODE) { + if (num_plane == 1) { + v4l2_buf.m.planes[0].m.userptr = (long unsigned int)vaddr[index].virt.extP[0]; + v4l2_buf.m.planes[0].length = width * height * 2; + } else if (num_plane == 2) { + v4l2_buf.m.planes[0].m.userptr = (long unsigned int)vaddr[index].virt.extP[0]; + v4l2_buf.m.planes[0].length = ALIGN(width, 16) * ALIGN(height, 16); + v4l2_buf.m.planes[1].m.userptr = (long unsigned int)vaddr[index].virt.extP[1]; + v4l2_buf.m.planes[1].length = ALIGN(width/2, 16) * ALIGN(height/2, 16); + } else if (num_plane == 3) { + v4l2_buf.m.planes[0].m.userptr = (long unsigned int)vaddr[index].virt.extP[0]; + v4l2_buf.m.planes[0].length = ALIGN(width, 16) * ALIGN(height, 16); + v4l2_buf.m.planes[1].m.userptr = (long unsigned int)vaddr[index].virt.extP[1]; + v4l2_buf.m.planes[1].length = ALIGN(width/2, 16) * ALIGN(height/2, 16); + v4l2_buf.m.planes[2].m.userptr = (long unsigned int)vaddr[index].virt.extP[2]; + v4l2_buf.m.planes[2].length = ALIGN(width/2, 16) * ALIGN(height/2, 16); + } else { + LOGE("ERR(%s): Invalid plane number", __func__); + return -1; + } + } else if (mode == CAPTURE_MODE) { + v4l2_buf.m.planes[0].m.userptr = (long unsigned int)vaddr[index].virt.extP[0]; + v4l2_buf.m.planes[0].length = width * height * 2; + } else if (mode == RECORD_MODE) { + v4l2_buf.m.planes[0].m.userptr = (long unsigned int)vaddr[index].virt.extP[0]; + v4l2_buf.m.planes[0].length = ALIGN(ALIGN(width, 16) * ALIGN(height, 16), 2048); + v4l2_buf.m.planes[1].m.userptr = (long unsigned int)vaddr[index].virt.extP[1]; + v4l2_buf.m.planes[1].length = ALIGN(ALIGN(width, 16) * ALIGN(height >> 1, 8), 2048); + } else { + LOGE("ERR(%s): Invalid mode", __func__); + return -1; + } +#endif + + ret = ioctl(fp, VIDIOC_QBUF, &v4l2_buf); + if (ret < 0) { + LOGE("ERR(%s):VIDIOC_QBUF failed", __func__); + return ret; + } + + return 0; +} + +static int fimc_v4l2_dqbuf(int fp, int num_plane) +{ + struct v4l2_buffer v4l2_buf; + int ret; + +#ifdef BOARD_USE_V4L2 + struct v4l2_plane planes[VIDEO_MAX_PLANES]; + + v4l2_buf.m.planes = planes; + v4l2_buf.length = num_plane; +#endif + + v4l2_buf.type = V4L2_BUF_TYPE; + v4l2_buf.memory = V4L2_MEMORY_TYPE; + + ret = ioctl(fp, VIDIOC_DQBUF, &v4l2_buf); + if (ret < 0) { + LOGE("ERR(%s):VIDIOC_DQBUF failed, dropped frame", __func__); + return ret; + } + + return v4l2_buf.index; +} + +static int fimc_v4l2_g_ctrl(int fp, unsigned int id) +{ + struct v4l2_control ctrl; + int ret; + + ctrl.id = id; + + ret = ioctl(fp, VIDIOC_G_CTRL, &ctrl); + if (ret < 0) { + LOGE("ERR(%s): VIDIOC_G_CTRL(id = 0x%x (%d)) failed, ret = %d", + __func__, id, id-V4L2_CID_PRIVATE_BASE, ret); + return ret; + } + + return ctrl.value; +} + +static int fimc_v4l2_s_ctrl(int fp, unsigned int id, unsigned int value) +{ + struct v4l2_control ctrl; + int ret; + + ctrl.id = id; + ctrl.value = value; + + ret = ioctl(fp, VIDIOC_S_CTRL, &ctrl); + if (ret < 0) { + LOGE("ERR(%s):VIDIOC_S_CTRL(id = %#x (%d), value = %d) failed ret = %d", + __func__, id, id-V4L2_CID_PRIVATE_BASE, value, ret); + + return ret; + } + + return ctrl.value; +} + +static int fimc_v4l2_s_ext_ctrl(int fp, unsigned int id, void *value) +{ + struct v4l2_ext_controls ctrls; + struct v4l2_ext_control ctrl; + int ret; + + ctrl.id = id; + + ctrls.ctrl_class = V4L2_CTRL_CLASS_CAMERA; + ctrls.count = 1; + ctrls.controls = &ctrl; + + ret = ioctl(fp, VIDIOC_S_EXT_CTRLS, &ctrls); + if (ret < 0) + LOGE("ERR(%s):VIDIOC_S_EXT_CTRLS failed", __func__); + + return ret; +} + +static int fimc_v4l2_s_ext_ctrl_face_detection(int fp, unsigned int id, void *value) +{ + struct v4l2_ext_control ext_ctrl_fd[111]; + struct v4l2_ext_controls ext_ctrls_fd; + struct v4l2_ext_controls *ctrls; + camera_frame_metadata_t *facedata = (camera_frame_metadata_t *)value; + int i, ret; + + ext_ctrl_fd[0].id = V4L2_CID_IS_FD_GET_FACE_COUNT; + for (i = 0; i < 5; i++) { + ext_ctrl_fd[22*i+1].id = V4L2_CID_IS_FD_GET_FACE_FRAME_NUMBER; + ext_ctrl_fd[22*i+2].id = V4L2_CID_IS_FD_GET_FACE_CONFIDENCE; + ext_ctrl_fd[22*i+3].id = V4L2_CID_IS_FD_GET_FACE_SMILE_LEVEL; + ext_ctrl_fd[22*i+4].id = V4L2_CID_IS_FD_GET_FACE_BLINK_LEVEL; + ext_ctrl_fd[22*i+5].id = V4L2_CID_IS_FD_GET_FACE_TOPLEFT_X; + ext_ctrl_fd[22*i+6].id = V4L2_CID_IS_FD_GET_FACE_TOPLEFT_Y; + ext_ctrl_fd[22*i+7].id = V4L2_CID_IS_FD_GET_FACE_BOTTOMRIGHT_X; + ext_ctrl_fd[22*i+8].id = V4L2_CID_IS_FD_GET_FACE_BOTTOMRIGHT_Y; + ext_ctrl_fd[22*i+9].id = V4L2_CID_IS_FD_GET_LEFT_EYE_TOPLEFT_X; + ext_ctrl_fd[22*i+10].id = V4L2_CID_IS_FD_GET_LEFT_EYE_TOPLEFT_Y; + ext_ctrl_fd[22*i+11].id = V4L2_CID_IS_FD_GET_LEFT_EYE_BOTTOMRIGHT_X; + ext_ctrl_fd[22*i+12].id = V4L2_CID_IS_FD_GET_LEFT_EYE_BOTTOMRIGHT_Y; + ext_ctrl_fd[22*i+13].id = V4L2_CID_IS_FD_GET_RIGHT_EYE_TOPLEFT_X; + ext_ctrl_fd[22*i+14].id = V4L2_CID_IS_FD_GET_RIGHT_EYE_TOPLEFT_Y; + ext_ctrl_fd[22*i+15].id = V4L2_CID_IS_FD_GET_RIGHT_EYE_BOTTOMRIGHT_X; + ext_ctrl_fd[22*i+16].id = V4L2_CID_IS_FD_GET_RIGHT_EYE_BOTTOMRIGHT_Y; + ext_ctrl_fd[22*i+17].id = V4L2_CID_IS_FD_GET_MOUTH_TOPLEFT_X; + ext_ctrl_fd[22*i+18].id = V4L2_CID_IS_FD_GET_MOUTH_TOPLEFT_Y; + ext_ctrl_fd[22*i+19].id = V4L2_CID_IS_FD_GET_MOUTH_BOTTOMRIGHT_X; + ext_ctrl_fd[22*i+20].id = V4L2_CID_IS_FD_GET_MOUTH_BOTTOMRIGHT_Y; + ext_ctrl_fd[22*i+21].id = V4L2_CID_IS_FD_GET_ANGLE; + ext_ctrl_fd[22*i+22].id = V4L2_CID_IS_FD_GET_NEXT; + } + + ext_ctrls_fd.ctrl_class = V4L2_CTRL_CLASS_CAMERA; + ext_ctrls_fd.count = 111; + ext_ctrls_fd.controls = ext_ctrl_fd; + ctrls = &ext_ctrls_fd; + + ret = ioctl(fp, VIDIOC_G_EXT_CTRLS, &ext_ctrls_fd); + + facedata->number_of_faces = ext_ctrls_fd.controls[0].value; + + for(i = 0; i < facedata->number_of_faces; i++) { + facedata->faces[i].rect[0] = ext_ctrl_fd[22*i+5].value; + facedata->faces[i].rect[1] = ext_ctrl_fd[22*i+6].value; + facedata->faces[i].rect[2] = ext_ctrl_fd[22*i+7].value; + facedata->faces[i].rect[3] = ext_ctrl_fd[22*i+8].value; + facedata->faces[i].score = ext_ctrl_fd[22*i+2].value; +/* TODO : id is unique value for each face. We need to suppot this. */ + facedata->faces[i].id = 0; + facedata->faces[i].left_eye[0] = (ext_ctrl_fd[22*i+9].value + ext_ctrl_fd[22*i+11].value) / 2; + facedata->faces[i].left_eye[1] = (ext_ctrl_fd[22*i+10].value + ext_ctrl_fd[22*i+12].value) / 2; + facedata->faces[i].right_eye[0] = (ext_ctrl_fd[22*i+13].value + ext_ctrl_fd[22*i+15].value) / 2; + facedata->faces[i].right_eye[1] = (ext_ctrl_fd[22*i+14].value + ext_ctrl_fd[22*i+16].value) / 2; + facedata->faces[i].mouth[0] = (ext_ctrl_fd[22*i+17].value + ext_ctrl_fd[22*i+19].value) / 2; + facedata->faces[i].mouth[1] = (ext_ctrl_fd[22*i+18].value + ext_ctrl_fd[22*i+20].value) / 2; + } + + return ret; +} + +static int fimc_v4l2_g_parm(int fp, struct v4l2_streamparm *streamparm) +{ + int ret; + + streamparm->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + + ret = ioctl(fp, VIDIOC_G_PARM, streamparm); + if (ret < 0) { + LOGE("ERR(%s):VIDIOC_G_PARM failed", __func__); + return -1; + } + + LOGV("%s : timeperframe: numerator %d, denominator %d", __func__, + streamparm->parm.capture.timeperframe.numerator, + streamparm->parm.capture.timeperframe.denominator); + + return 0; +} + +static int fimc_v4l2_s_parm(int fp, struct v4l2_streamparm *streamparm) +{ + int ret; + + streamparm->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + + ret = ioctl(fp, VIDIOC_S_PARM, streamparm); + if (ret < 0) { + LOGE("ERR(%s):VIDIOC_S_PARM failed", __func__); + return ret; + } + + return 0; +} + +SecCamera::SecCamera() : + m_flagCreate(0), + m_preview_state(0), + m_snapshot_state(0), + m_camera_id(CAMERA_ID_BACK), + m_camera_use_ISP(0), + m_cam_fd(-1), + m_cam_fd2(-1), + m_cam_fd3(-1), + m_cap_fd(-1), + m_rec_fd(-1), + m_jpeg_fd(-1), + m_flag_record_start(0), + m_preview_v4lformat(V4L2_PIX_FMT_YVU420), + m_preview_width (0), + m_preview_height (0), + m_preview_max_width (MAX_BACK_CAMERA_PREVIEW_WIDTH), + m_preview_max_height (MAX_BACK_CAMERA_PREVIEW_HEIGHT), + m_snapshot_v4lformat(V4L2_PIX_FMT_YUYV), + m_snapshot_width (0), + m_snapshot_height (0), + m_num_capbuf (0), + m_videosnapshot_width (0), + m_videosnapshot_height(0), + m_snapshot_max_width (MAX_BACK_CAMERA_SNAPSHOT_WIDTH), + m_snapshot_max_height (MAX_BACK_CAMERA_SNAPSHOT_HEIGHT), + m_recording_en (0), + m_record_hint (0), + m_recording_width (0), + m_recording_height (0), + m_angle(-1), + m_anti_banding(0), + m_wdr(0), + m_anti_shake(0), + m_zoom_level(-1), + m_object_tracking(-1), + m_smart_auto(-1), + m_beauty_shot(-1), + m_vintage_mode(-1), + m_face_detect(0), + m_object_tracking_start_stop(-1), + m_gps_latitude(-1), + m_gps_longitude(-1), + m_gps_altitude(-1), + m_gps_timestamp(-1), + m_sensor_mode(-1), + m_shot_mode(-1), + m_exif_orientation(-1), + m_chk_dataline(-1), + m_video_gamma(0), + m_slow_ae(0), + m_camera_af_flag(-1), + m_flag_camera_create(0), + m_flag_camera_start(0), + m_jpeg_thumbnail_width (0), + m_jpeg_thumbnail_height(0), + m_jpeg_thumbnail_quality(100), + m_jpeg_quality(100), + m_touch_af_start_stop(-1), + m_postview_offset(0), + m_auto_focus_state(0) +#ifdef ENABLE_ESD_PREVIEW_CHECK + , + m_esd_check_count(0) +#endif // ENABLE_ESD_PREVIEW_CHECK +{ + initParameters(0); + memset(&mExifInfo, 0, sizeof(mExifInfo)); + + memset(&m_events_c, 0, sizeof(m_events_c)); + memset(&m_events_c2, 0, sizeof(m_events_c2)); + memset(&m_events_c3, 0, sizeof(m_events_c3)); +} + +SecCamera::~SecCamera() +{ + LOGV("%s :", __func__); + DestroyCamera(); +} + +bool SecCamera::CreateCamera(int index) +{ + LOGV("%s :", __func__); + int ret = 0; + + switch (index) { + case CAMERA_ID_FRONT: + m_preview_max_width = MAX_FRONT_CAMERA_PREVIEW_WIDTH; + m_preview_max_height = MAX_FRONT_CAMERA_PREVIEW_HEIGHT; + m_snapshot_max_width = MAX_FRONT_CAMERA_SNAPSHOT_WIDTH; + m_snapshot_max_height = MAX_FRONT_CAMERA_SNAPSHOT_HEIGHT; + break; + + case CAMERA_ID_BACK: + default: + m_preview_max_width = MAX_BACK_CAMERA_PREVIEW_WIDTH; + m_preview_max_height = MAX_BACK_CAMERA_PREVIEW_HEIGHT; + m_snapshot_max_width = MAX_BACK_CAMERA_SNAPSHOT_WIDTH; + m_snapshot_max_height = MAX_BACK_CAMERA_SNAPSHOT_HEIGHT; + break; + } + + if (!m_flagCreate) { + /* Arun C + * Reset the lense position only during camera starts; don't do + * reset between shot to shot + */ + m_flagCreate = 1; + m_snapshot_state = 0; + m_camera_af_flag = -1; + m_camera_id = index; + m_recording_en = 0; + + m_cam_fd = open(CAMERA_DEV_NAME, O_RDWR); + if (m_cam_fd < 0) { + LOGE("ERR(%s):Cannot open %s (error : %s)", __func__, CAMERA_DEV_NAME, strerror(errno)); + return -1; + } + LOGV("%s: open(%s) --> m_cam_fd %d", __func__, CAMERA_DEV_NAME, m_cam_fd); + + ret = fimc_v4l2_querycap(m_cam_fd); + CHECK(ret); + if (!fimc_v4l2_enuminput(m_cam_fd, index)) { + LOGE("m_cam_fd(%d) fimc_v4l2_enuminput fail", m_cam_fd); + return -1; + } + ret = fimc_v4l2_s_input(m_cam_fd, index); + CHECK(ret); + + m_camera_use_ISP = getUseInternalISP(); + + if (m_camera_use_ISP) { + if (!m_recording_en) + fimc_v4l2_s_fmt_is(m_cam_fd, m_preview_max_width, m_preview_max_height, + m_preview_v4lformat, (enum v4l2_field) IS_MODE_PREVIEW_STILL); + else + fimc_v4l2_s_fmt_is(m_cam_fd, m_preview_max_width, m_preview_max_height, + m_preview_v4lformat, (enum v4l2_field) IS_MODE_PREVIEW_VIDEO); + } + + ret = fimc_v4l2_s_fmt(m_cam_fd, m_preview_max_width, m_preview_max_height, + m_preview_v4lformat, V4L2_FIELD_ANY, PREVIEW_NUM_PLANE); + CHECK(ret); + + initParameters(m_camera_use_ISP); + +#ifdef SAMSUNG_EXYNOS4x12 +#ifdef ZERO_SHUTTER_LAG + if (m_camera_use_ISP) { + m_cam_fd2 = open(CAMERA_DEV_NAME2, O_RDWR); + LOGV("%s: open(%s) --> m_cam_fd2 = %d", __func__, CAMERA_DEV_NAME2, m_cam_fd2); + if (m_cam_fd2 < 0) { + LOGE("ERR(%s):Cannot open %s (error : %s)", __func__, CAMERA_DEV_NAME2, strerror(errno)); + return -1; + } + + ret = fimc_v4l2_querycap(m_cam_fd2); + CHECK(ret); + if (!fimc_v4l2_enuminput(m_cam_fd2, index)) { + LOGE("m_cam_fd2(%d) fimc_v4l2_enuminput fail", m_cam_fd2); + return -1; + } + ret = fimc_v4l2_s_input(m_cam_fd2, index); + CHECK(ret); + } +#endif +#endif + + m_cam_fd3 = open(CAMERA_DEV_NAME3, O_RDWR); + LOGV("%s: open(%s) --> m_cam_fd3 = %d", __func__, CAMERA_DEV_NAME3, m_cam_fd3); + if (m_cam_fd3 < 0) { + LOGE("ERR(%s):Cannot open %s (error : %s)", __func__, CAMERA_DEV_NAME3, strerror(errno)); + return -1; + } + + ret = fimc_v4l2_querycap(m_cam_fd3); + CHECK(ret); + if (!fimc_v4l2_enuminput(m_cam_fd3, index)) { + LOGE("m_cam_fd3(%d) fimc_v4l2_enuminput fail", m_cam_fd3); + return -1; + } + ret = fimc_v4l2_s_input(m_cam_fd3, index); + CHECK(ret); + + setExifFixedAttribute(); + } + +#ifdef ZERO_SHUTTER_LAG + if (m_camera_use_ISP) + m_cap_fd = m_cam_fd2; + else + m_cap_fd = m_cam_fd; +#else + m_cap_fd = m_cam_fd; +#endif + + m_rec_fd = m_cam_fd3; + + if (m_camera_use_ISP) + m_num_capbuf = CAP_BUFFERS; + else + m_num_capbuf = 1; + + m_flag_camera_create = 1; + + return 0; +} + +void SecCamera::resetCamera() +{ + LOGV("%s :", __func__); + DestroyCamera(); + CreateCamera(m_camera_id); +} + +bool SecCamera::DestroyCamera() +{ + LOGV("%s :", __func__); + + if (m_flagCreate) { + + stopRecord(); + + /* close m_cam_fd after stopRecord() because stopRecord() + * uses m_cam_fd to change frame rate + */ + LOGI("DestroyCamera: m_cam_fd(%d)", m_cam_fd); + if (m_cam_fd > -1) { + close(m_cam_fd); + m_cam_fd = -1; + } + +#ifdef ZERO_SHUTTER_LAG + if (m_camera_use_ISP) { + LOGI("DestroyCamera: m_cam_fd2(%d)", m_cam_fd2); + if (m_cam_fd2 > -1) { + close(m_cam_fd2); + m_cam_fd2 = -1; + } + } +#endif + + LOGI("DestroyCamera: m_cam_fd3(%d)", m_cam_fd3); + if (m_cam_fd3 > -1) { + close(m_cam_fd3); + m_cam_fd3 = -1; + } + + m_flagCreate = 0; + } else + LOGI("%s : already deinitialized", __func__); + + return 0; +} + +void SecCamera::initParameters(int internalISP) +{ + memset(&m_streamparm, 0, sizeof(m_streamparm)); + m_params = (struct sec_cam_parm*)&m_streamparm.parm.raw_data; + struct v4l2_captureparm capture; + + m_params->capture.timeperframe.numerator = 1; + m_params->capture.timeperframe.denominator = FRAME_RATE_AUTO; + m_params->flash_mode = FLASH_MODE_AUTO; + m_params->iso = ISO_AUTO; + m_params->metering = METERING_CENTER; + m_params->saturation = SATURATION_DEFAULT; + m_params->scene_mode = SCENE_MODE_NONE; + m_params->sharpness = SHARPNESS_DEFAULT; + m_params->white_balance = WHITE_BALANCE_AUTO; + m_params->anti_banding = ANTI_BANDING_OFF; + m_params->effects = IMAGE_EFFECT_NONE; + m_params->focus_mode = FOCUS_MODE_AUTO; + + if (internalISP) { + m_params->contrast = IS_CONTRAST_DEFAULT; + m_params->brightness = IS_BRIGHTNESS_DEFAULT; + m_params->exposure = IS_EXPOSURE_DEFAULT; + m_params->hue = IS_HUE_DEFAULT; + m_params->aeawb_mode = AE_UNLOCK_AWB_UNLOCK; + } else { + m_params->contrast = CONTRAST_DEFAULT; + m_params->brightness = EV_DEFAULT; + m_params->exposure = EV_DEFAULT; + m_params->hue = -1; + m_params->aeawb_mode = -1; + } +} + +int SecCamera::setMode(int recording_en) +{ + LOGV("%s :", __func__); + int mode; + + m_recording_en = recording_en; + + if (m_camera_use_ISP) { + if (!recording_en) + mode = IS_MODE_PREVIEW_STILL; + else + mode = IS_MODE_PREVIEW_VIDEO; + + if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_IS_S_FORMAT_SCENARIO, mode) < 0) { + LOGE("ERR(%s):Fail on V4L2_CID_IS_S_FORMAT_SCENARIO", __func__); + return -1; + } + } + + return 0; +} + +int SecCamera::getCameraFd(enum CAM_MODE mode) +{ + int ret = -1; + + switch (mode) { + case PREVIEW: + ret = m_cam_fd; + break; + case PICTURE: + ret = m_cap_fd; + break; + default: + ret = m_cam_fd; + break; + } + + return ret; +} + +int SecCamera::startPreview(void) +{ + v4l2_streamparm streamparm; + struct sec_cam_parm *parms; + parms = (struct sec_cam_parm*)&streamparm.parm.raw_data; + LOGV("%s :", __func__); + + // aleady started + if (m_flag_camera_start > 0) { + LOGE("ERR(%s):Preview was already started", __func__); + return 0; + } + + if (m_cam_fd <= 0) { + LOGE("ERR(%s):Camera was closed", __func__); + return -1; + } + + memset(&m_events_c, 0, sizeof(m_events_c)); + m_events_c.fd = m_cam_fd; + m_events_c.events = POLLIN | POLLERR; + + /* enum_fmt, s_fmt sample */ + int ret = fimc_v4l2_enum_fmt(m_cam_fd,m_preview_v4lformat); + CHECK(ret); + + LOGV("m_camera_use_ISP(%d), %s", m_camera_use_ISP, (const char*)getCameraSensorName()); + + if (m_camera_use_ISP) { + if (!m_recording_en) + fimc_v4l2_s_fmt_is(m_cam_fd, m_videosnapshot_width, m_videosnapshot_height, + m_preview_v4lformat, (enum v4l2_field) IS_MODE_PREVIEW_STILL); + else + fimc_v4l2_s_fmt_is(m_cam_fd, m_videosnapshot_width, m_videosnapshot_height, + m_preview_v4lformat, (enum v4l2_field) IS_MODE_PREVIEW_VIDEO); + } + + ret = fimc_v4l2_s_fmt(m_cam_fd, m_preview_width, m_preview_height, m_preview_v4lformat, V4L2_FIELD_ANY, PREVIEW_NUM_PLANE); + CHECK(ret); + +#ifndef BOARD_USE_V4L2_ION + if (!m_camera_use_ISP) { + fimc_v4l2_s_fmt_is(m_cam_fd, m_preview_width, m_preview_height, + m_preview_v4lformat, (enum v4l2_field) IS_MODE_PREVIEW_STILL); + } +#endif + + if (m_camera_use_ISP) { + if (!m_recording_en) + ret = fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_IS_S_SCENARIO_MODE, IS_MODE_PREVIEW_STILL); + else + ret = fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_IS_S_SCENARIO_MODE, IS_MODE_PREVIEW_VIDEO); + } + CHECK(ret); + +#ifndef BOARD_USE_V4L2_ION + ret = fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CACHEABLE, 1); + CHECK(ret); +#endif + + ret = fimc_v4l2_reqbufs(m_cam_fd, V4L2_BUF_TYPE, MAX_BUFFERS); + CHECK(ret); + +#ifndef BOARD_USE_V4L2_ION + ret = fimc_v4l2_querybuf(m_cam_fd, m_buffers_preview, V4L2_BUF_TYPE, MAX_BUFFERS, PREVIEW_NUM_PLANE); + CHECK(ret); +#endif + + LOGV("%s : m_preview_width: %d m_preview_height: %d m_angle: %d", + __func__, m_preview_width, m_preview_height, m_angle); + + LOGV("m_camera_id : %d", m_camera_id); + + /* start with all buffers in queue */ + for (int i = 0; i < MAX_BUFFERS; i++) { + ret = fimc_v4l2_qbuf(m_cam_fd, m_preview_width, m_preview_height, m_buffers_preview, i, PREVIEW_NUM_PLANE, PREVIEW_MODE); + CHECK(ret); + } + + ret = fimc_v4l2_streamon(m_cam_fd); + CHECK(ret); + +#ifdef USE_FACE_DETECTION + if (m_camera_use_ISP) { + ret = fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_IS_CMD_FD, IS_FD_COMMAND_START); + CHECK(ret); + } +#endif + +#ifdef ZERO_SHUTTER_LAG + if (m_camera_use_ISP && !m_recording_en) { + stopSnapshot(); + startSnapshot(NULL); + } +#endif + + m_flag_camera_start = 1; + + LOGV("%s: got the first frame of the preview", __func__); + + return 0; +} + +int SecCamera::stopPreview(void) +{ + int ret; + + LOGV("%s :", __func__); + + if (m_flag_camera_start == 0) { + LOGW("%s: doing nothing because m_flag_camera_start is zero", __func__); + return 0; + } + +#ifdef ZERO_SHUTTER_LAG + if (m_camera_use_ISP && !m_recording_en) + stopSnapshot(); +#endif + + if (m_params->flash_mode == FLASH_MODE_TORCH) + setFlashMode(FLASH_MODE_OFF); + + if (m_cam_fd <= 0) { + LOGE("ERR(%s):Camera was closed", __func__); + return -1; + } +#ifdef USE_FACE_DETECTION + if (m_camera_use_ISP) { + ret = fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_IS_CMD_FD, IS_FD_COMMAND_STOP); + CHECK(ret); + } +#endif + /* TODO : This code is temporary implementation. */ + /* Because streamoff is failed when ae lock or awb lock state */ + if (m_camera_use_ISP && m_params->aeawb_mode) { + if (m_params->aeawb_mode & 0x1) { + if (setAutoExposureLock(0) < 0) { + LOGE("ERR(%s): Fail on setAutoExposureLock()"); + return -1; + } + } + if (m_params->aeawb_mode & (0x1 << 1)) { + if (setAutoWhiteBalanceLock(0) < 0) { + LOGE("ERR(%s): Fail on setAutoWhiteBalnaceLock()"); + return -1; + } + } + m_params->aeawb_mode = 0; + } + + ret = fimc_v4l2_streamoff(m_cam_fd); + CHECK(ret); + + close_buffers(m_buffers_preview, MAX_BUFFERS); + + fimc_v4l2_reqbufs(m_cam_fd, V4L2_BUF_TYPE, 0); + + m_flag_camera_start = 0; + + return ret; +} + +int SecCamera::startSnapshot(SecBuffer *yuv_buf) +{ + LOGV("%s :", __func__); + + // already started + if (m_snapshot_state) { + LOGI("%s: Doing nothing because snapshot is already started!", __func__); + return 0; + } + + if (m_cap_fd <= 0) { + LOGE("ERR(%s):Camera was closed", __func__); + return -1; + } + + m_snapshot_state = 1; + + memset(&m_events_c2, 0, sizeof(m_events_c2)); + m_events_c2.fd = m_cap_fd; + m_events_c2.events = POLLIN | POLLERR; + +#if defined(LOG_NDEBUG) && LOG_NDEBUG == 0 + if (m_snapshot_v4lformat == V4L2_PIX_FMT_YUV420) + LOGV("SnapshotFormat:V4L2_PIX_FMT_YUV420"); + else if (m_snapshot_v4lformat == V4L2_PIX_FMT_NV12) + LOGV("SnapshotFormat:V4L2_PIX_FMT_NV12"); + else if (m_snapshot_v4lformat == V4L2_PIX_FMT_NV12T) + LOGV("SnapshotFormat:V4L2_PIX_FMT_NV12T"); + else if (m_snapshot_v4lformat == V4L2_PIX_FMT_NV21) + LOGV("SnapshotFormat:V4L2_PIX_FMT_NV21"); + else if (m_snapshot_v4lformat == V4L2_PIX_FMT_YUV422P) + LOGV("SnapshotFormat:V4L2_PIX_FMT_YUV422P"); + else if (m_snapshot_v4lformat == V4L2_PIX_FMT_YUYV) + LOGV("SnapshotFormat:V4L2_PIX_FMT_YUYV"); + else if (m_snapshot_v4lformat == V4L2_PIX_FMT_UYVY) + LOGV("SnapshotFormat:V4L2_PIX_FMT_UYVY"); + else if (m_snapshot_v4lformat == V4L2_PIX_FMT_RGB565) + LOGV("SnapshotFormat:V4L2_PIX_FMT_RGB565"); + else + LOGV("SnapshotFormat:UnknownFormat"); +#endif + + int ret = fimc_v4l2_enum_fmt(m_cap_fd, m_snapshot_v4lformat); + CHECK(ret); + + if (m_camera_use_ISP) { + fimc_v4l2_s_fmt_is(m_cap_fd, m_videosnapshot_width, m_videosnapshot_height, + m_preview_v4lformat, (enum v4l2_field) IS_MODE_PREVIEW_STILL); + } + + if (!m_recording_en) + ret = fimc_v4l2_s_fmt_cap(m_cap_fd, m_snapshot_width, m_snapshot_height, m_snapshot_v4lformat); + else + ret = fimc_v4l2_s_fmt_cap(m_cap_fd, m_videosnapshot_width, m_videosnapshot_height, m_snapshot_v4lformat); + CHECK(ret); + +#ifndef BOARD_USE_V4L2_ION + if (!m_camera_use_ISP) + if (!m_recording_en) + fimc_v4l2_s_fmt_is(m_cap_fd, m_snapshot_width, m_snapshot_height, + m_preview_v4lformat, (enum v4l2_field) IS_MODE_PREVIEW_STILL); + else + fimc_v4l2_s_fmt_is(m_cap_fd, m_videosnapshot_width, m_videosnapshot_height, + m_preview_v4lformat, (enum v4l2_field) IS_MODE_PREVIEW_VIDEO); +#endif + +#ifndef ZERO_SHUTTER_LAG + if (m_camera_use_ISP) + ret = fimc_v4l2_s_ctrl(m_cap_fd, V4L2_CID_IS_S_SCENARIO_MODE, IS_MODE_PREVIEW_STILL); + CHECK(ret); +#endif + +#ifndef BOARD_USE_V4L2_ION + ret = fimc_v4l2_s_ctrl(m_cap_fd, V4L2_CID_CACHEABLE, 1); + CHECK(ret); +#endif + + ret = fimc_v4l2_reqbufs(m_cap_fd, V4L2_BUF_TYPE, m_num_capbuf); + CHECK(ret); + +#ifdef BOARD_USE_V4L2_ION +#ifndef ZERO_SHUTTER_LAG + m_capture_buf[0].virt.p = (char *)yuv_buf->virt.p; +#endif +#else + ret = fimc_v4l2_querybuf(m_cap_fd, m_capture_buf, V4L2_BUF_TYPE, m_num_capbuf, 1); + CHECK(ret); +#endif + + /* start with all buffers in queue */ + for (int i = 0; i < m_num_capbuf; i++) { + ret = fimc_v4l2_qbuf(m_cap_fd, m_snapshot_width, m_snapshot_height, m_capture_buf, i, 1, CAPTURE_MODE); + CHECK(ret); + } + + ret = fimc_v4l2_streamon(m_cap_fd); + CHECK(ret); + + return 0; +} + +int SecCamera::stopSnapshot(void) +{ + int ret; + + LOGV("%s :", __func__); + + if (!m_snapshot_state) { + LOGI("%s: Doing nothing because snapshot is not started!", __func__); + return 0; + } + + if (m_cap_fd <= 0) { + LOGE("ERR(%s):Camera was closed", __func__); + return -1; + } + + ret = fimc_v4l2_streamoff(m_cap_fd); + CHECK(ret); + + endSnapshot(); + + m_snapshot_state = 0; + + return ret; +} + +//Recording +int SecCamera::startRecord(bool recordHint) +{ + int ret, i; + + LOGV("%s :", __func__); + + // aleady started + if (m_flag_record_start > 0) { + LOGE("ERR(%s):Preview was already started", __func__); + return 0; + } + + if (m_rec_fd <= 0) { + LOGE("ERR(%s):Camera was closed", __func__); + return -1; + } + + /* enum_fmt, s_fmt sample */ + ret = fimc_v4l2_enum_fmt(m_rec_fd, RECORD_PIX_FMT); + CHECK(ret); + + LOGI("%s: m_recording_width = %d, m_recording_height = %d", + __func__, m_recording_width, m_recording_height); + + LOGV("m_camera_use_ISP(%d), %s", m_camera_use_ISP, (const char*)getCameraSensorName()); + + if (m_camera_use_ISP) { + fimc_v4l2_s_fmt_is(m_rec_fd, m_videosnapshot_width, m_videosnapshot_height, + m_preview_v4lformat, (enum v4l2_field) IS_MODE_CAPTURE_VIDEO); + + ret = fimc_v4l2_s_fmt(m_rec_fd, m_recording_width, + m_recording_height, RECORD_PIX_FMT, V4L2_FIELD_ANY, RECORD_NUM_PLANE); + CHECK(ret); + } else { + ret = fimc_v4l2_s_fmt(m_rec_fd, m_preview_width, + m_preview_height, RECORD_PIX_FMT, V4L2_FIELD_ANY, RECORD_NUM_PLANE); + CHECK(ret); +#ifndef BOARD_USE_V4L2_ION + fimc_v4l2_s_fmt_is(m_rec_fd, m_preview_width, m_preview_height, + m_preview_v4lformat, (enum v4l2_field) IS_MODE_CAPTURE_VIDEO); +#endif + } + + if (!m_camera_use_ISP) { + ret = fimc_v4l2_s_ctrl(m_rec_fd, V4L2_CID_CAMERA_BUSFREQ_LOCK, 267160); + CHECK(ret); + } + + ret = fimc_v4l2_reqbufs(m_rec_fd, V4L2_BUF_TYPE, MAX_BUFFERS); + CHECK(ret); + +#ifndef BOARD_USE_V4L2_ION + ret = fimc_v4l2_querybuf(m_rec_fd, m_buffers_record, V4L2_BUF_TYPE, MAX_BUFFERS, RECORD_NUM_PLANE); + CHECK(ret); +#endif + + /* start with all buffers in queue */ + for (i = 0; i < MAX_BUFFERS; i++) { + ret = fimc_v4l2_qbuf(m_rec_fd, m_recording_width, m_recording_height, m_buffers_record, i, RECORD_NUM_PLANE, RECORD_MODE); + CHECK(ret); + } + + // Get and throw away the first frame since it is often garbled. + memset(&m_events_c3, 0, sizeof(m_events_c3)); + m_events_c3.fd = m_rec_fd; + m_events_c3.events = POLLIN | POLLERR; + + m_record_hint = recordHint; +#ifdef VIDEO_SNAPSHOT + if (m_camera_use_ISP && m_record_hint) { + stopSnapshot(); + startSnapshot(NULL); + } +#endif + + ret = fimc_v4l2_streamon(m_rec_fd); + CHECK(ret); + + m_flag_record_start = 1; + + return 0; +} + +int SecCamera::stopRecord(void) +{ + int ret; + + LOGV("%s :", __func__); + + if (m_flag_record_start == 0) { + LOGW("%s: doing nothing because m_flag_record_start is zero", __func__); + return 0; + } + +#ifdef VIDEO_SNAPSHOT + if (m_camera_use_ISP && m_record_hint) + stopSnapshot(); +#endif + + if (m_rec_fd <= 0) { + LOGE("ERR(%s):Camera was closed", __func__); + return -1; + } + + m_flag_record_start = 0; + + if (!m_camera_use_ISP) { + ret = fimc_v4l2_s_ctrl(m_rec_fd, V4L2_CID_CAMERA_BUSFREQ_UNLOCK, 0); + CHECK(ret); + } + + ret = fimc_v4l2_streamoff(m_rec_fd); + CHECK(ret); + + close_buffers(m_buffers_record, MAX_BUFFERS); + + fimc_v4l2_reqbufs(m_rec_fd, V4L2_BUF_TYPE, 0); + + return 0; +} + +int SecCamera::getRecordAddr(int index, SecBuffer *buffer) +{ +#ifdef BOARD_USE_V4L2 + buffer->phys.extP[0] = (unsigned int)m_buffers_record[index].phys.extP[0]; + buffer->phys.extP[1] = (unsigned int)(m_buffers_record[index].phys.extP[0] + (m_recording_width * m_recording_height)); +#else + buffer->phys.extP[0] = fimc_v4l2_s_ctrl(m_rec_fd, V4L2_CID_PADDR_Y, index); + CHECK((int)buffer->phys.extP[0]); + buffer->phys.extP[1] = fimc_v4l2_s_ctrl(m_rec_fd, V4L2_CID_PADDR_CBCR, index); + CHECK((int)buffer->phys.extP[1]); +#endif + return 0; +} + +int SecCamera::getPreviewAddr(int index, SecBuffer *buffer) +{ +#ifdef BOARD_USE_V4L2 + buffer->phys.extP[0] = (unsigned int)m_buffers_preview[index].phys.extP[0]; + buffer->phys.extP[1] = (unsigned int)m_buffers_preview[index].phys.extP[1]; + buffer->virt.extP[0] = m_buffers_preview[index].virt.extP[0]; +#else + buffer->phys.extP[0] = fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_PADDR_Y, index); + CHECK((int)buffer->phys.extP[0]); + buffer->phys.extP[1] = fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_PADDR_CBCR, index); + CHECK((int)buffer->phys.extP[1]); +#endif + return 0; +} + +int SecCamera::getCaptureAddr(int index, SecBuffer *buffer) +{ + buffer->virt.extP[0] = m_capture_buf[index].virt.extP[0]; + CHECK((int)buffer->virt.extP[0]); + return 0; +} + +#ifdef BOARD_USE_V4L2_ION +void SecCamera::setUserBufferAddr(void *ptr, int index, int mode) +{ + if (mode == PREVIEW_MODE) { + m_buffers_preview[index].virt.extP[0] = (char *)((unsigned int *)ptr)[0]; + m_buffers_preview[index].virt.extP[1] = (char *)((unsigned int *)ptr)[1]; + m_buffers_preview[index].virt.extP[2] = (char *)((unsigned int *)ptr)[2]; + } else if (mode == CAPTURE_MODE) { + m_capture_buf[index].virt.extP[0] = (char *)ptr; + } else if (mode == RECORD_MODE) { + m_buffers_record[index].virt.extP[0] = (char *)ptr; + m_buffers_record[index].virt.extP[1] = (char *)ptr + (ALIGN((ALIGN(m_recording_width, 16) * ALIGN(m_recording_height, 16)), 2048)); + } else + LOGE("%s: Invalid fd!!!", __func__); +} +#endif + +int SecCamera::getPreview(camera_frame_metadata_t *facedata) +{ + int index; + int ret; + + if (m_flag_camera_start == 0 || fimc_poll(&m_events_c) == 0) { + LOGE("ERR(%s):Start Camera Device Reset", __func__); + /* + * When there is no data for more than 1 second from the camera we inform + * the FIMC driver by calling fimc_v4l2_s_input() with a special value = 1000 + * FIMC driver identify that there is something wrong with the camera + * and it restarts the sensor. + */ + stopPreview(); + /* Reset Only Camera Device */ + ret = fimc_v4l2_querycap(m_cam_fd); + CHECK(ret); + if (fimc_v4l2_enuminput(m_cam_fd, m_camera_id)) + return -1; + ret = fimc_v4l2_s_input(m_cam_fd, 1000); + CHECK(ret); +#ifdef BOARD_USE_V4L2_ION + m_preview_state = 0; + return -1; +#endif + ret = startPreview(); + if (ret < 0) { + LOGE("ERR(%s): startPreview() return %d", __func__, ret); + return 0; + } + } + + index = fimc_v4l2_dqbuf(m_cam_fd, PREVIEW_NUM_PLANE); + if (!(0 <= index && index < MAX_BUFFERS)) { + LOGE("ERR(%s):wrong index = %d", __func__, index); + return -1; + } + +#ifdef USE_FACE_DETECTION + if (m_camera_use_ISP) { + fimc_v4l2_s_ext_ctrl_face_detection(m_cam_fd, 0, facedata); + } +#endif + + return index; +} + +int SecCamera::setPreviewFrame(int index) +{ + int ret; + ret = fimc_v4l2_qbuf(m_cam_fd, m_preview_width, m_preview_height, m_buffers_preview, index, PREVIEW_NUM_PLANE, PREVIEW_MODE); + CHECK(ret); + + return ret; +} + +int SecCamera::getSnapshot() +{ + int index; + int ret; + + if (m_snapshot_state) { + fimc_poll(&m_events_c2); + + index = fimc_v4l2_dqbuf(m_cap_fd, 1); + if (!(0 <= index && index < m_num_capbuf)) { + LOGE("ERR(%s):wrong index = %d", __func__, index); + return -1; + } + return index; + } + + return -1; +} + +int SecCamera::setSnapshotFrame(int index) +{ + int ret; + ret = fimc_v4l2_qbuf(m_cap_fd, m_snapshot_width, m_snapshot_height, m_capture_buf, index, PREVIEW_NUM_PLANE, CAPTURE_MODE); + CHECK(ret); + + return ret; +} + +int SecCamera::getRecordFrame() +{ + if (m_flag_record_start == 0) { + LOGE("%s: m_flag_record_start is 0", __func__); + return -1; + } + + fimc_poll(&m_events_c3); + int index = fimc_v4l2_dqbuf(m_rec_fd, RECORD_NUM_PLANE); + if (!(0 <= index && index < MAX_BUFFERS)) { + LOGE("ERR(%s):wrong index = %d", __func__, index); + return -1; + } + + return index; +} + +int SecCamera::releaseRecordFrame(int index) +{ + if (!m_flag_record_start) { + /* this can happen when recording frames are returned after + * the recording is stopped at the driver level. we don't + * need to return the buffers in this case and we've seen + * cases where fimc could crash if we called qbuf and it + * wasn't expecting it. + */ + LOGI("%s: recording not in progress, ignoring", __func__); + return 0; + } + + return fimc_v4l2_qbuf(m_rec_fd, m_recording_width, m_recording_height, m_buffers_record, index, RECORD_NUM_PLANE, RECORD_MODE); +} + +int SecCamera::setPreviewSize(int width, int height, int pixel_format) +{ + LOGV("%s(width(%d), height(%d), format(%d))", __func__, width, height, pixel_format); + + int v4lpixelformat = pixel_format; + +#if defined(LOG_NDEBUG) && LOG_NDEBUG == 0 + if (v4lpixelformat == V4L2_PIX_FMT_YUV420) + LOGV("PreviewFormat:V4L2_PIX_FMT_YUV420"); + else if (v4lpixelformat == V4L2_PIX_FMT_YVU420) + LOGV("PreviewFormat:V4L2_PIX_FMT_YVU420"); + else if (v4lpixelformat == V4L2_PIX_FMT_YVU420M) + LOGV("PreviewFormat:V4L2_PIX_FMT_YVU420M"); + else if (v4lpixelformat == V4L2_PIX_FMT_NV12) + LOGV("PreviewFormat:V4L2_PIX_FMT_NV12"); + else if (v4lpixelformat == V4L2_PIX_FMT_NV12T) + LOGV("PreviewFormat:V4L2_PIX_FMT_NV12T"); + else if (v4lpixelformat == V4L2_PIX_FMT_NV21) + LOGV("PreviewFormat:V4L2_PIX_FMT_NV21"); + else if (v4lpixelformat == V4L2_PIX_FMT_YUV422P) + LOGV("PreviewFormat:V4L2_PIX_FMT_YUV422P"); + else if (v4lpixelformat == V4L2_PIX_FMT_YUYV) + LOGV("PreviewFormat:V4L2_PIX_FMT_YUYV"); + else if (v4lpixelformat == V4L2_PIX_FMT_RGB565) + LOGV("PreviewFormat:V4L2_PIX_FMT_RGB565"); + else + LOGV("PreviewFormat:UnknownFormat"); +#endif + m_preview_width = width; + m_preview_height = height; + m_preview_v4lformat = v4lpixelformat; + + return 0; +} + +int SecCamera::getPreviewSize(int *width, int *height, int *frame_size) +{ + *width = m_preview_width; + *height = m_preview_height; + *frame_size = FRAME_SIZE(V4L2_PIX_2_HAL_PIXEL_FORMAT(m_preview_v4lformat), *width, *height); + return 0; +} + +int SecCamera::getPreviewMaxSize(int *width, int *height) +{ + *width = m_preview_max_width; + *height = m_preview_max_height; + + return 0; +} + +int SecCamera::getPreviewPixelFormat(void) +{ + return m_preview_v4lformat; +} + +/* + * Devide getJpeg() as two funcs, setSnapshotCmd() & getJpeg() because of the shutter sound timing. + * Here, just send the capture cmd to camera ISP to start JPEG capture. + */ +int SecCamera::setSnapshotCmd(void) +{ + LOGV("%s :", __func__); + + int ret = 0; + + if (m_cam_fd <= 0) { + LOGE("ERR(%s):Camera was closed", __func__); + return 0; + } + + if (m_flag_camera_start > 0) { + LOGW("WARN(%s):Camera was in preview, should have been stopped", __func__); + stopPreview(); + } + + memset(&m_events_c, 0, sizeof(m_events_c)); + m_events_c.fd = m_cam_fd; + m_events_c.events = POLLIN | POLLERR; + + int nframe = 1; + + ret = fimc_v4l2_enum_fmt(m_cam_fd,m_snapshot_v4lformat); + CHECK(ret); + ret = fimc_v4l2_s_fmt_cap(m_cam_fd, m_snapshot_width, m_snapshot_height, V4L2_PIX_FMT_JPEG); + CHECK(ret); + +#ifndef BOARD_USE_V4L2_ION + if (!m_camera_use_ISP) + if (!m_recording_en) + fimc_v4l2_s_fmt_is(m_cap_fd, m_snapshot_width, m_snapshot_height, + V4L2_PIX_FMT_JPEG, (enum v4l2_field) IS_MODE_PREVIEW_STILL); + else + fimc_v4l2_s_fmt_is(m_cap_fd, m_videosnapshot_width, m_videosnapshot_height, + V4L2_PIX_FMT_JPEG, (enum v4l2_field) IS_MODE_PREVIEW_VIDEO); +#endif + + ret = fimc_v4l2_reqbufs(m_cam_fd, V4L2_BUF_TYPE, nframe); + CHECK(ret); + +#ifndef BOARD_USE_V4L2_ION + ret = fimc_v4l2_querybuf(m_cam_fd, m_capture_buf, V4L2_BUF_TYPE, 1, 1); + CHECK(ret); +#endif + + ret = fimc_v4l2_qbuf(m_cam_fd, m_snapshot_width, m_snapshot_height, m_capture_buf, 0, 1, CAPTURE_MODE); + CHECK(ret); + + ret = fimc_v4l2_streamon(m_cam_fd); + CHECK(ret); + + return 0; +} + +int SecCamera::endSnapshot(void) +{ + close_buffers(m_capture_buf, m_num_capbuf); + + fimc_v4l2_reqbufs(m_cap_fd, V4L2_BUF_TYPE, 0); + + return 0; +} + +/* + * Set Jpeg quality & exif info and get JPEG data from camera ISP + */ +unsigned char* SecCamera::getJpeg(int *jpeg_size, + int *thumb_size, + unsigned int *thumb_addr, + unsigned int *phyaddr) +{ + int index, ret = 0; + unsigned char *addr; + SecBuffer jpegAddr; + + // capture + ret = fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_CAPTURE, 0); + CHECK_PTR(ret); + ret = fimc_poll(&m_events_c); + CHECK_PTR(ret); + index = fimc_v4l2_dqbuf(m_cam_fd, 1); + + if (index != 0) { + LOGE("ERR(%s):wrong index = %d", __func__, index); + return NULL; + } + + *jpeg_size = fimc_v4l2_g_ctrl(m_cam_fd, V4L2_CID_CAM_JPEG_MAIN_SIZE); + CHECK_PTR(*jpeg_size); + + int main_offset = fimc_v4l2_g_ctrl(m_cam_fd, V4L2_CID_CAM_JPEG_MAIN_OFFSET); + CHECK_PTR(main_offset); + + *thumb_size = fimc_v4l2_g_ctrl(m_cam_fd, V4L2_CID_CAM_JPEG_THUMB_SIZE); + CHECK_PTR(*thumb_size); + + int thumb_offset = fimc_v4l2_g_ctrl(m_cam_fd, V4L2_CID_CAM_JPEG_THUMB_OFFSET); + CHECK_PTR(thumb_offset); + + m_postview_offset = fimc_v4l2_g_ctrl(m_cam_fd, V4L2_CID_CAM_JPEG_POSTVIEW_OFFSET); + CHECK_PTR(m_postview_offset); + + ret = fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_STREAM_PAUSE, 0); + CHECK_PTR(ret); + + LOGV("\nsnapshot dqueued buffer = %d snapshot_width = %d snapshot_height = %d, size = %d", + index, m_snapshot_width, m_snapshot_height, *jpeg_size); + + addr = (unsigned char*)(m_capture_buf[0].virt.extP[0]) + main_offset; + + *thumb_addr = (unsigned int)(addr + thumb_offset); + + getPreviewAddr(index, &jpegAddr); + *phyaddr = jpegAddr.phys.extP[0] + m_postview_offset; + + ret = fimc_v4l2_streamoff(m_cam_fd); + CHECK_PTR(ret); + + return addr; +} + +int SecCamera::getExif(unsigned char *pExifDst, unsigned char *pThumbSrc, int thumbSize) +{ +#ifdef SAMSUNG_EXYNOS4210 + /* JPEG encode for smdkv310 */ + if (m_jpeg_fd > 0) { + if (api_jpeg_encode_deinit(m_jpeg_fd) != JPEG_OK) + LOGE("ERR(%s):Fail on api_jpeg_encode_deinit", __func__); + m_jpeg_fd = 0; + } + + m_jpeg_fd = api_jpeg_encode_init(); + LOGV("(%s):JPEG device open ID = %d", __func__, m_jpeg_fd); + + if (m_jpeg_fd <= 0) { + if (m_jpeg_fd < 0) { + m_jpeg_fd = 0; + LOGE("ERR(%s):Cannot open a jpeg device file", __func__); + return -1; + } + LOGE("ERR(%s):JPEG device was closed", __func__); + return -1; + } + + if (m_snapshot_v4lformat == V4L2_PIX_FMT_RGB565) { + LOGE("ERR(%s):It doesn't support V4L2_PIX_FMT_RGB565", __func__); + return -1; + } + + struct jpeg_enc_param enc_param; + enum jpeg_frame_format inFormat = YUV_422; + enum jpeg_stream_format outFormat = JPEG_422; + + switch (m_snapshot_v4lformat) { + case V4L2_PIX_FMT_NV12: + case V4L2_PIX_FMT_NV21: + case V4L2_PIX_FMT_NV12T: + case V4L2_PIX_FMT_YUV420: + inFormat = YUV_420; + outFormat = JPEG_420; + break; + case V4L2_PIX_FMT_YUYV: + case V4L2_PIX_FMT_UYVY: + case V4L2_PIX_FMT_YUV422P: + default: + inFormat = YUV_422; + outFormat = JPEG_422; + break; + } + + // set encode parameters // + enc_param.width = m_jpeg_thumbnail_width; + enc_param.height = m_jpeg_thumbnail_width; + enc_param.in_fmt = inFormat; // YCBCR Only + enc_param.out_fmt = outFormat; + + if (m_jpeg_thumbnail_quality >= 90) + enc_param.quality = QUALITY_LEVEL_1; + else if (m_jpeg_thumbnail_quality >= 80) + enc_param.quality = QUALITY_LEVEL_2; + else if (m_jpeg_thumbnail_quality >= 70) + enc_param.quality = QUALITY_LEVEL_3; + else + enc_param.quality = QUALITY_LEVEL_4; + + api_jpeg_set_encode_param(&enc_param); + + unsigned int thumbnail_size = m_jpeg_thumbnail_width * m_jpeg_thumbnail_height * 2; + unsigned char *pInBuf = (unsigned char *)api_jpeg_get_encode_in_buf(m_jpeg_fd, thumbnail_size); + if (pInBuf == NULL) { + LOGE("ERR(%s):JPEG input buffer is NULL!!", __func__); + return -1; + } + + unsigned char *pOutBuf = (unsigned char *)api_jpeg_get_encode_out_buf(m_jpeg_fd); + if (pOutBuf == NULL) { + LOGE("ERR(%s):JPEG output buffer is NULL!!", __func__); + return -1; + } + + memcpy(pInBuf, pThumbSrc, thumbnail_size); + + enum jpeg_ret_type result = api_jpeg_encode_exe(m_jpeg_fd, &enc_param); + if (result != JPEG_ENCODE_OK) { + LOGE("ERR(%s):encode failed", __func__); + return -1; + } + + unsigned int outbuf_size = enc_param.size; + unsigned int exifSize; + + setExifChangedAttribute(); + + LOGV("%s: calling jpgEnc.makeExif, mExifInfo.width set to %d, height to %d", + __func__, mExifInfo.width, mExifInfo.height); + + LOGV("%s : enableThumb set to true", __func__); + mExifInfo.enableThumb = true; + + makeExif(pExifDst, pOutBuf, outbuf_size, &mExifInfo, &exifSize, true); +#endif + +#ifdef SAMSUNG_EXYNOS4x12 + /* JPEG encode for smdk4x12 */ + unsigned int exifSize; + + if (m_camera_use_ISP) { + LOGV("%s : m_jpeg_thumbnail_width = %d, height = %d", + __func__, m_jpeg_thumbnail_width, m_jpeg_thumbnail_height); + m_jpeg_fd = jpeghal_enc_init(); + LOGV("(%s):JPEG device open ID = %d", __func__, m_jpeg_fd); + + if (m_jpeg_fd <= 0) { + if (m_jpeg_fd < 0) { + m_jpeg_fd = 0; + LOGE("ERR(%s):Cannot open a jpeg device file", __func__); + return -1; + } + LOGE("ERR(%s):JPEG device was closed", __func__); + return -1; + } + + if (m_snapshot_v4lformat == V4L2_PIX_FMT_RGB565) { + LOGE("ERR(%s):It doesn't support V4L2_PIX_FMT_RGB565", __func__); + return -1; + } + + struct jpeg_config enc_config; + int outFormat; + + switch (m_snapshot_v4lformat) { + case V4L2_PIX_FMT_NV12: + case V4L2_PIX_FMT_NV21: + case V4L2_PIX_FMT_NV12T: + case V4L2_PIX_FMT_YUV420: + outFormat = V4L2_PIX_FMT_JPEG_420; + break; + case V4L2_PIX_FMT_YUYV: + case V4L2_PIX_FMT_UYVY: + case V4L2_PIX_FMT_YUV422P: + default: + outFormat = V4L2_PIX_FMT_JPEG_422; + break; + } + + // set encode parameters // + enc_config.mode = JPEG_ENCODE; + + if (m_jpeg_thumbnail_quality >= 90) + enc_config.enc_qual = QUALITY_LEVEL_1; + else if (m_jpeg_thumbnail_quality >= 80) + enc_config.enc_qual = QUALITY_LEVEL_2; + else if (m_jpeg_thumbnail_quality >= 70) + enc_config.enc_qual = QUALITY_LEVEL_3; + else + enc_config.enc_qual = QUALITY_LEVEL_4; + + enc_config.width = m_jpeg_thumbnail_width; + enc_config.height = m_jpeg_thumbnail_height; + enc_config.pix.enc_fmt.in_fmt = m_snapshot_v4lformat; + enc_config.pix.enc_fmt.out_fmt = outFormat; + + jpeghal_enc_setconfig(m_jpeg_fd, &enc_config); + + jpeghal_s_ctrl(m_jpeg_fd, V4L2_CID_CACHEABLE, 1); + + struct jpeg_buf m_jpeg_inbuf; + m_jpeg_inbuf.memory = V4L2_MEMORY_MMAP; + m_jpeg_inbuf.num_planes = 1; + + if (jpeghal_set_inbuf(m_jpeg_fd, &m_jpeg_inbuf) < 0) { + LOGE("ERR(%s):Fail to JPEG input buffer!!", __func__); + return -1; + } + + struct jpeg_buf m_jpeg_outbuf; + m_jpeg_outbuf.memory = V4L2_MEMORY_MMAP; + m_jpeg_outbuf.num_planes = 1; + + if (jpeghal_set_outbuf(m_jpeg_fd, &m_jpeg_outbuf) < 0) { + LOGE("ERR(%s):Fail to JPEG output buffer!!", __func__); + return -1; + } + + memcpy(m_jpeg_inbuf.start[0], pThumbSrc, m_jpeg_inbuf.length[0]); + + if (jpeghal_enc_exe(m_jpeg_fd, &m_jpeg_inbuf, &m_jpeg_outbuf) < 0) { + LOGE("ERR(%s):encode failed", __func__); + return -1; + } + + int outbuf_size = jpeghal_g_ctrl(m_jpeg_fd, V4L2_CID_CAM_JPEG_ENCODEDSIZE); + if (outbuf_size < 0) { + LOGE("ERR(%s): jpeghal_g_ctrl fail on V4L2_CID_CAM_JPEG_ENCODEDSIZE", __func__); + return -1; + } + + setExifChangedAttribute(); + + LOGV("%s: calling jpgEnc.makeExif, mExifInfo.width set to %d, height to %d", + __func__, mExifInfo.width, mExifInfo.height); + + LOGV("%s : enableThumb set to true", __func__); + mExifInfo.enableThumb = true; + + makeExif(pExifDst, (unsigned char *)m_jpeg_outbuf.start[0], (unsigned int)outbuf_size, &mExifInfo, &exifSize, true); + + if (m_jpeg_fd > 0) { + if (jpeghal_deinit(m_jpeg_fd, &m_jpeg_inbuf, &m_jpeg_outbuf) < 0) + LOGE("ERR(%s):Fail on api_jpeg_encode_deinit", __func__); + m_jpeg_fd = 0; + } + } else { + setExifChangedAttribute(); + mExifInfo.enableThumb = true; + makeExif(pExifDst, pThumbSrc, (unsigned int)thumbSize, &mExifInfo, &exifSize, true); + } +#endif + + return exifSize; +} + +void SecCamera::getPostViewConfig(int *width, int *height, int *size) +{ + *width = m_snapshot_width; + *height = m_snapshot_height; + *size = FRAME_SIZE(V4L2_PIX_2_HAL_PIXEL_FORMAT(m_snapshot_v4lformat), *width, *height); + LOGV("[5B] m_preview_width : %d, mPostViewWidth = %d mPostViewHeight = %d mPostViewSize = %d", + m_preview_width, *width, *height, *size); +} + +void SecCamera::getThumbnailConfig(int *width, int *height, int *size) +{ + *width = m_jpeg_thumbnail_width; + *height = m_jpeg_thumbnail_height; + *size = FRAME_SIZE(V4L2_PIX_2_HAL_PIXEL_FORMAT(m_snapshot_v4lformat), *width, *height); +} + +int SecCamera::getPostViewOffset(void) +{ + return m_postview_offset; +} + +int SecCamera::getSnapshotAndJpeg(SecBuffer *yuv_buf, int index, unsigned char *jpeg_buf, + int *output_size) +{ + LOGV("%s :", __func__); + + int ret = 0; + int i; + +#ifdef ZERO_SHUTTER_LAG + if (!m_camera_use_ISP){ + startSnapshot(yuv_buf); + + index = getSnapshot(); + if (index < 0) { + LOGE("ERR(%s): Invalid index!", __func__); + return -1; + } + +#ifndef BOARD_USE_V4L2_ION + ret = fimc_v4l2_s_ctrl(m_cap_fd, V4L2_CID_STREAM_PAUSE, 0); + CHECK_PTR(ret); + LOGV("snapshot dequeued buffer = %d snapshot_width = %d snapshot_height = %d", + index, m_snapshot_width, m_snapshot_height); + + getCaptureAddr(index, yuv_buf); +#endif + + if (yuv_buf->virt.extP[0] == NULL) { + LOGE("ERR(%s):Fail on SecCamera getCaptureAddr = %0x ", + __func__, yuv_buf->virt.extP[0]); + return UNKNOWN_ERROR; + } + } +#else + startSnapshot(yuv_buf); + + index = getSnapshot(); + if (index < 0) { + LOGE("ERR(%s): Invalid index!", __func__); + return -1; + } + +#ifndef BOARD_USE_V4L2_ION + ret = fimc_v4l2_s_ctrl(m_cap_fd, V4L2_CID_STREAM_PAUSE, 0); + CHECK_PTR(ret); + LOGV("snapshot dequeued buffer = %d snapshot_width = %d snapshot_height = %d", + index, m_snapshot_width, m_snapshot_height); + + getCaptureAddr(index, yuv_buf); +#endif + + if (yuv_buf->virt.extP[0] == NULL) { + LOGE("ERR(%s):Fail on SecCamera getCaptureAddr = %0x ", + __func__, yuv_buf->virt.extP[0]); + return UNKNOWN_ERROR; + } +#endif + +#ifdef SAMSUNG_EXYNOS4210 + /* JPEG encode for smdkv310 */ + if (m_jpeg_fd > 0) { + if (api_jpeg_encode_deinit(m_jpeg_fd) != JPEG_OK) + LOGE("ERR(%s):Fail on api_jpeg_encode_deinit", __func__); + m_jpeg_fd = 0; + } + + m_jpeg_fd = api_jpeg_encode_init(); + LOGV("(%s):JPEG device open ID = %d", __func__, m_jpeg_fd); + + if (m_jpeg_fd <= 0) { + if (m_jpeg_fd < 0) { + m_jpeg_fd = 0; + LOGE("ERR(%s):Cannot open a jpeg device file", __func__); + return -1; + } + LOGE("ERR(%s):JPEG device was closed", __func__); + return -1; + } + + if (m_snapshot_v4lformat == V4L2_PIX_FMT_RGB565) { + LOGE("ERR(%s):It doesn't support V4L2_PIX_FMT_RGB565", __func__); + return -1; + } + + struct jpeg_enc_param enc_param; + enum jpeg_frame_format inFormat = YUV_422; + enum jpeg_stream_format outFormat = JPEG_422; + + switch (m_snapshot_v4lformat) { + case V4L2_PIX_FMT_NV12: + case V4L2_PIX_FMT_NV21: + case V4L2_PIX_FMT_NV12T: + case V4L2_PIX_FMT_YUV420: + inFormat = YUV_420; + outFormat = JPEG_420; + break; + case V4L2_PIX_FMT_YUYV: + case V4L2_PIX_FMT_UYVY: + case V4L2_PIX_FMT_YUV422P: + default: + inFormat = YUV_422; + outFormat = JPEG_422; + break; + } + + // set encode parameters // + enc_param.width = m_snapshot_width; + enc_param.height = m_snapshot_height; + enc_param.in_fmt = inFormat; // YCBCR Only + enc_param.out_fmt = outFormat; + + if (m_jpeg_quality >= 90) + enc_param.quality = QUALITY_LEVEL_1; + else if (m_jpeg_quality >= 80) + enc_param.quality = QUALITY_LEVEL_2; + else if (m_jpeg_quality >= 70) + enc_param.quality = QUALITY_LEVEL_3; + else + enc_param.quality = QUALITY_LEVEL_4; + + api_jpeg_set_encode_param(&enc_param); + + unsigned int snapshot_size = m_snapshot_width * m_snapshot_height * 2; + unsigned char *pInBuf = (unsigned char *)api_jpeg_get_encode_in_buf(m_jpeg_fd, snapshot_size); + if (pInBuf == NULL) { + LOGE("ERR(%s):JPEG input buffer is NULL!!", __func__); + return -1; + } + + unsigned char *pOutBuf = (unsigned char *)api_jpeg_get_encode_out_buf(m_jpeg_fd); + if (pOutBuf == NULL) { + LOGE("ERR(%s):JPEG output buffer is NULL!!", __func__); + return -1; + } + + memcpy(pInBuf, yuv_buf->virt.extP[0], snapshot_size); + + enum jpeg_ret_type result = api_jpeg_encode_exe(m_jpeg_fd, &enc_param); + if (result != JPEG_ENCODE_OK) { + LOGE("ERR(%s):encode failed", __func__); + return -1; + } + + *output_size = enc_param.size; + memcpy(jpeg_buf, pOutBuf, *output_size); +#endif + +#ifdef SAMSUNG_EXYNOS4x12 + /* JPEG encode for smdk4x12 */ + m_jpeg_fd = jpeghal_enc_init(); + LOGV("(%s):JPEG device open ID = %d", __func__, m_jpeg_fd); + + if (m_jpeg_fd <= 0) { + if (m_jpeg_fd < 0) { + m_jpeg_fd = 0; + LOGE("ERR(%s):Cannot open a jpeg device file", __func__); + return -1; + } + LOGE("ERR(%s):JPEG device was closed", __func__); + return -1; + } + + if (m_snapshot_v4lformat == V4L2_PIX_FMT_RGB565) { + LOGE("ERR(%s):It doesn't support V4L2_PIX_FMT_RGB565", __func__); + return -1; + } + + struct jpeg_config enc_config; + int outFormat; + + switch (m_snapshot_v4lformat) { + case V4L2_PIX_FMT_NV12: + case V4L2_PIX_FMT_NV21: + case V4L2_PIX_FMT_NV12T: + case V4L2_PIX_FMT_YUV420: + outFormat = V4L2_PIX_FMT_JPEG_420; + break; + case V4L2_PIX_FMT_YUYV: + case V4L2_PIX_FMT_UYVY: + case V4L2_PIX_FMT_YUV422P: + default: + outFormat = V4L2_PIX_FMT_JPEG_422; + break; + } + + // set encode parameters // + enc_config.mode = JPEG_ENCODE; + + if (m_jpeg_quality >= 90) + enc_config.enc_qual = QUALITY_LEVEL_1; + else if (m_jpeg_quality >= 80) + enc_config.enc_qual = QUALITY_LEVEL_2; + else if (m_jpeg_quality >= 70) + enc_config.enc_qual = QUALITY_LEVEL_3; + else + enc_config.enc_qual = QUALITY_LEVEL_4; + + if (!m_recording_en) { + enc_config.width = m_snapshot_width; + enc_config.height = m_snapshot_height; + } else { + enc_config.width = m_videosnapshot_width; + enc_config.height = m_videosnapshot_height; + } + enc_config.pix.enc_fmt.in_fmt = m_snapshot_v4lformat; + enc_config.pix.enc_fmt.out_fmt = outFormat; + + jpeghal_enc_setconfig(m_jpeg_fd, &enc_config); + + ret = jpeghal_s_ctrl(m_jpeg_fd, V4L2_CID_CACHEABLE, 3); + CHECK(ret); + + struct jpeg_buf m_jpeg_inbuf; +#ifdef BOARD_USE_V4L2_ION + m_jpeg_inbuf.memory = V4L2_MEMORY_MMAP; + m_jpeg_inbuf.num_planes = 1; +#else + m_jpeg_inbuf.start[0] = (void *)fimc_v4l2_s_ctrl(m_cap_fd, V4L2_CID_PADDR_Y, index); + m_jpeg_inbuf.length[0] = m_capture_buf[index].size.extS[0]; + m_jpeg_inbuf.memory = V4L2_MEMORY_USERPTR; + m_jpeg_inbuf.num_planes = 1; +#endif + + if (jpeghal_set_inbuf(m_jpeg_fd, &m_jpeg_inbuf) < 0) { + LOGE("ERR(%s):Fail to JPEG input buffer!!", __func__); + return -1; + } + + for (i = 0; i < m_jpeg_inbuf.num_planes; i++) { + if ((unsigned int)m_jpeg_inbuf.start[i] & (SIZE_4K - 1)) { + LOGE("ERR(%s): JPEG start address should be aligned to 4 Kbytes", __func__); + return -1; + } else if ((unsigned int)enc_config.width & (16 - 1)) { + LOGE("ERR(%s): Image width should be multiple of 16", __func__); + return -1; + } + } + + struct jpeg_buf m_jpeg_outbuf; + m_jpeg_outbuf.memory = V4L2_MEMORY_MMAP; + m_jpeg_outbuf.num_planes = 1; + + if (jpeghal_set_outbuf(m_jpeg_fd, &m_jpeg_outbuf) < 0) { + LOGE("ERR(%s):Fail to JPEG output buffer!!", __func__); + return -1; + } + +#ifdef BOARD_USE_V4L2_ION + memcpy(m_jpeg_inbuf.start[0], yuv_buf->virt.extP[0], m_jpeg_inbuf.length[0]); +#endif + + if (jpeghal_enc_exe(m_jpeg_fd, &m_jpeg_inbuf, &m_jpeg_outbuf) < 0) { + LOGE("ERR(%s):encode failed", __func__); + return -1; + } + + ret = jpeghal_g_ctrl(m_jpeg_fd, V4L2_CID_CAM_JPEG_ENCODEDSIZE); + if (ret < 0) { + LOGE("ERR(%s): jpeghal_g_ctrl fail on V4L2_CID_CAM_JPEG_ENCODEDSIZE", __func__); + return -1; + } else { + *output_size = (unsigned int)ret; + } + + memcpy(jpeg_buf, m_jpeg_outbuf.start[0], *output_size); + + if (m_jpeg_fd > 0) { + if (jpeghal_deinit(m_jpeg_fd, &m_jpeg_inbuf, &m_jpeg_outbuf) < 0) + LOGE("ERR(%s):Fail on api_jpeg_encode_deinit", __func__); + m_jpeg_fd = 0; + } +#endif + + return 0; +} + +int SecCamera::setVideosnapshotSize(int width, int height) +{ + LOGV("%s(width(%d), height(%d))", __func__, width, height); + + m_videosnapshot_width = width; + m_videosnapshot_height = height; + + return 0; +} + +int SecCamera::getVideosnapshotSize(int *width, int *height, int *frame_size) +{ + *width = m_videosnapshot_width; + *height = m_videosnapshot_height; + + int frame = 0; + + frame = FRAME_SIZE(V4L2_PIX_2_HAL_PIXEL_FORMAT(m_snapshot_v4lformat), *width, *height); + + // set it big. + if (frame == 0) + frame = m_videosnapshot_width * m_videosnapshot_height * BPP; + + *frame_size = frame; + + return 0; +} + +int SecCamera::setSnapshotSize(int width, int height) +{ + LOGV("%s(width(%d), height(%d))", __func__, width, height); + + m_snapshot_width = width; + m_snapshot_height = height; + + return 0; +} + +int SecCamera::getSnapshotSize(int *width, int *height, int *frame_size) +{ + *width = m_snapshot_width; + *height = m_snapshot_height; + + int frame = 0; + + frame = FRAME_SIZE(V4L2_PIX_2_HAL_PIXEL_FORMAT(m_snapshot_v4lformat), *width, *height); + + // set it big. + if (frame == 0) + frame = m_snapshot_width * m_snapshot_height * BPP; + + *frame_size = frame; + + return 0; +} + +int SecCamera::getSnapshotMaxSize(int *width, int *height) +{ + *width = m_snapshot_max_width; + *height = m_snapshot_max_height; + + return 0; +} + +int SecCamera::setSnapshotPixelFormat(int pixel_format) +{ + int v4lpixelformat = pixel_format; + + if (m_snapshot_v4lformat != v4lpixelformat) { + m_snapshot_v4lformat = v4lpixelformat; + } + +#if defined(LOG_NDEBUG) && LOG_NDEBUG == 0 + if (m_snapshot_v4lformat == V4L2_PIX_FMT_YUV420) + LOGE("%s : SnapshotFormat:V4L2_PIX_FMT_YUV420", __func__); + else if (m_snapshot_v4lformat == V4L2_PIX_FMT_NV12) + LOGD("%s : SnapshotFormat:V4L2_PIX_FMT_NV12", __func__); + else if (m_snapshot_v4lformat == V4L2_PIX_FMT_NV12T) + LOGD("%s : SnapshotFormat:V4L2_PIX_FMT_NV12T", __func__); + else if (m_snapshot_v4lformat == V4L2_PIX_FMT_NV21) + LOGD("%s : SnapshotFormat:V4L2_PIX_FMT_NV21", __func__); + else if (m_snapshot_v4lformat == V4L2_PIX_FMT_YUV422P) + LOGD("%s : SnapshotFormat:V4L2_PIX_FMT_YUV422P", __func__); + else if (m_snapshot_v4lformat == V4L2_PIX_FMT_YUYV) + LOGD("%s : SnapshotFormat:V4L2_PIX_FMT_YUYV", __func__); + else if (m_snapshot_v4lformat == V4L2_PIX_FMT_UYVY) + LOGD("%s : SnapshotFormat:V4L2_PIX_FMT_UYVY", __func__); + else if (m_snapshot_v4lformat == V4L2_PIX_FMT_RGB565) + LOGD("%s : SnapshotFormat:V4L2_PIX_FMT_RGB565", __func__); + else + LOGD("SnapshotFormat:UnknownFormat"); +#endif + return 0; +} + +int SecCamera::getSnapshotPixelFormat(void) +{ + return m_snapshot_v4lformat; +} + +int SecCamera::getCameraId(void) +{ + return m_camera_id; +} + +int SecCamera::initSetParams(void) +{ + LOGV("%s :", __func__); + + if (m_cam_fd <= 0) { + LOGE("ERR(%s):Camera was closed", __func__); + return -1; + } + + if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_ISO, ISO_AUTO) < 0) { + LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_ISO", __func__); + return -1; + } + if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_METERING, METERING_CENTER) < 0) { + LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_METERING", __func__); + return -1; + } + if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_SATURATION, SATURATION_DEFAULT) < 0) { + LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_SATURATION", __func__); + return -1; + } + if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_SCENE_MODE, SCENE_MODE_NONE) < 0) { + LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_SCENE_MODE", __func__); + return -1; + } + if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_SHARPNESS, SHARPNESS_DEFAULT) < 0) { + LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_SHARPNESS", __func__); + return -1; + } + if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_WHITE_BALANCE, WHITE_BALANCE_AUTO) < 0) { + LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_WHITE_BALANCE", __func__); + return -1; + } + if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_ANTI_BANDING, ANTI_BANDING_OFF) < 0) { + LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_ANTI_BANDING", __func__); + return -1; + } + if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_IS_CAMERA_CONTRAST, IS_CONTRAST_DEFAULT) < 0) { + LOGE("ERR(%s):Fail on V4L2_CID_IS_CAMERA_CONTRAST", __func__); + return -1; + } + if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_EFFECT, IMAGE_EFFECT_NONE) < 0) { + LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_EFFECT", __func__); + return -1; + } + if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_IS_CAMERA_BRIGHTNESS, IS_BRIGHTNESS_DEFAULT) < 0) { + LOGE("ERR(%s):Fail on V4L2_CID_IS_CAMERA_BRIGHTNESS", __func__); + return -1; + } + if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_IS_CAMERA_EXPOSURE, IS_EXPOSURE_DEFAULT) < 0) { + LOGE("ERR(%s):Fail on V4L2_CID_IS_CAMERA_EXPOSURE", __func__); + return -1; + } +/* TODO */ +/* This code is temporary implementation because * + * hue value tuning was not complete */ +#ifdef USE_HUE + if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_IS_CAMERA_HUE, IS_HUE_DEFAULT) < 0) { + LOGE("ERR(%s):Fail on V4L2_CID_IS_CAMERA_HUE", __func__); + return -1; + } +#endif + + initParameters(m_camera_use_ISP); + + return 0; +} + +int SecCamera::setAutofocus(void) +{ + LOGV("%s :", __func__); + + if (m_cam_fd <= 0) { + LOGE("ERR(%s):Camera was closed", __func__); + return -1; + } + + if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_SET_AUTO_FOCUS, AUTO_FOCUS_ON) < 0) { + LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_SET_AUTO_FOCUS", __func__); + return -1; + } + + m_auto_focus_state = 1; + + return 0; +} + +int SecCamera::setTouchAF(void) +{ + LOGV("%s :", __func__); + + if (m_cam_fd <= 0) { + LOGE("ERR(%s):Camera was closed", __func__); + return -1; + } + + if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_FOCUS_MODE, FOCUS_MODE_TOUCH) < 0) { + LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_FOCUS_MODE", __func__); + return -1; + } + + return 0; +} + +int SecCamera::getAutoFocusResult(void) +{ + int af_result; + + af_result = fimc_v4l2_g_ctrl(m_cam_fd, V4L2_CID_CAMERA_AUTO_FOCUS_RESULT); + + LOGV("%s : returning %d", __func__, af_result); + + return af_result; +} + +int SecCamera::cancelAutofocus(void) +{ + LOGV("%s :", __func__); + + if (m_cam_fd <= 0) { + LOGE("ERR(%s):Camera was closed", __func__); + return -1; + } + +#ifndef BOARD_USE_V4L2 + if (m_flag_camera_start && m_auto_focus_state) { + if (m_params->focus_mode == FOCUS_MODE_AUTO || m_params->focus_mode == FOCUS_MODE_MACRO) { + if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_SET_AUTO_FOCUS, AUTO_FOCUS_OFF) < 0) { + LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_SET_AUTO_FOCUS", __func__); + return -1; + } + } + m_auto_focus_state = 0; + } +#endif + + return 0; +} + +int SecCamera::SetRotate(int angle) +{ + LOGE("%s(angle(%d))", __func__, angle); + + if (m_angle != angle) { + switch (angle) { + case -360: + case 0: + case 360: + m_angle = 0; + break; + + case -270: + case 90: + m_angle = 90; + break; + + case -180: + case 180: + m_angle = 180; + break; + + case -90: + case 270: + m_angle = 270; + break; + + default: + LOGE("ERR(%s):Invalid angle(%d)", __func__, angle); + return -1; + } + + if (m_flag_camera_create) { + if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_ROTATION, angle) < 0) { + LOGE("ERR(%s):Fail on V4L2_CID_ROTATION", __func__); + return -1; + } + m_angle = angle; + } + } + + return 0; +} + +int SecCamera::getRotate(void) +{ + LOGV("%s : angle(%d)", __func__, m_angle); + return m_angle; +} + +int SecCamera::setFrameRate(int frame_rate) +{ + LOGV("%s(FrameRate(%d))", __func__, frame_rate); + + if (frame_rate < FRAME_RATE_AUTO || FRAME_RATE_MAX < frame_rate ) { + LOGE("ERR(%s):Invalid frame_rate(%d)", __func__, frame_rate); + return -1; + } + + if (m_params->capture.timeperframe.denominator != frame_rate) { + if (m_flag_camera_create) { + if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_FRAME_RATE, frame_rate) < 0) { + LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_FRAME_RATE", __func__); + return -1; + } + m_params->capture.timeperframe.denominator = frame_rate; + } + } + + return 0; +} + +int SecCamera::setVerticalMirror(void) +{ + LOGV("%s :", __func__); + + if (m_cam_fd <= 0) { + LOGE("ERR(%s):Camera was closed", __func__); + return -1; + } + + if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_VFLIP, 0) < 0) { + LOGE("ERR(%s):Fail on V4L2_CID_VFLIP", __func__); + return -1; + } + + return 0; +} + +int SecCamera::setHorizontalMirror(void) +{ + LOGV("%s :", __func__); + + if (m_cam_fd <= 0) { + LOGE("ERR(%s):Camera was closed", __func__); + return -1; + } + + if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_HFLIP, 0) < 0) { + LOGE("ERR(%s):Fail on V4L2_CID_HFLIP", __func__); + return -1; + } + + return 0; +} + +int SecCamera::setWhiteBalance(int white_balance) +{ + LOGV("%s(white_balance(%d))", __func__, white_balance); + + if (white_balance <= WHITE_BALANCE_BASE || WHITE_BALANCE_MAX <= white_balance) { + LOGE("ERR(%s):Invalid white_balance(%d)", __func__, white_balance); + return -1; + } + + if (m_params->white_balance != white_balance) { + if (m_flag_camera_create) { + LOGE("%s(white_balance(%d))", __func__, white_balance); + if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_WHITE_BALANCE, white_balance) < 0) { + LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_WHITE_BALANCE", __func__); + return -1; + } + m_params->white_balance = white_balance; + } + } + + return 0; +} + +int SecCamera::getWhiteBalance(void) +{ + LOGV("%s : white_balance(%d)", __func__, m_params->white_balance); + return m_params->white_balance; +} + +int SecCamera::setBrightness(int brightness) +{ + LOGV("%s(brightness(%d))", __func__, brightness); + + if (m_camera_use_ISP) { + brightness += IS_BRIGHTNESS_DEFAULT; + if (brightness < IS_BRIGHTNESS_MINUS_2 || IS_BRIGHTNESS_PLUS_2 < brightness) { + LOGE("ERR(%s):Invalid brightness(%d)", __func__, brightness); + return -1; + } + } else { + LOGW("WARN(%s):Not supported brightness setting", __func__); + return 0; + } + + if (m_params->brightness != brightness) { + if (m_flag_camera_create) { + if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_IS_CAMERA_BRIGHTNESS, brightness) < EV_MINUS_4) { + LOGE("ERR(%s):Fail on V4L2_CID_IS_CAMERA_BRIGHTNESS", __func__); + return -1; + } + m_params->brightness = brightness; + } + } + + return 0; +} + +int SecCamera::getBrightness(void) +{ + LOGV("%s : brightness(%d)", __func__, m_params->brightness); + return m_params->brightness; +} + +int SecCamera::setExposure(int exposure) +{ + LOGV("%s(exposure(%d))", __func__, exposure); + + if (m_camera_use_ISP) { + exposure += IS_EXPOSURE_DEFAULT; + if (exposure < IS_EXPOSURE_MINUS_4 || IS_EXPOSURE_PLUS_4 < exposure) { + LOGE("ERR(%s):Invalid exposure(%d)", __func__, exposure); + return -1; + } + } else { + exposure += EV_DEFAULT; + if (exposure < EV_MINUS_4 || EV_PLUS_4 < exposure) { + LOGE("ERR(%s):Invalid exposure(%d)", __func__, exposure); + return -1; + } + } + + if (m_params->exposure != exposure) { + if (m_flag_camera_create) { + if (m_camera_use_ISP) { + if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_IS_CAMERA_EXPOSURE, exposure) < 0) { + LOGE("ERR(%s):Fail on V4L2_CID_IS_CAMERA_EXPOSURE", __func__); + return -1; + } + } else { + if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_BRIGHTNESS, exposure) < EV_MINUS_4) { + LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_BRIGHTNESS", __func__); + return -1; + } + } + m_params->exposure = exposure; + } + } + + return 0; +} + +int SecCamera::getExposure(void) +{ + LOGV("%s : exposure(%d)", __func__, m_params->exposure); + return m_params->exposure; +} + +int SecCamera::setImageEffect(int image_effect) +{ + LOGV("%s(image_effect(%d))", __func__, image_effect); + + if (image_effect <= IMAGE_EFFECT_BASE || IMAGE_EFFECT_MAX <= image_effect) { + LOGE("ERR(%s):Invalid image_effect(%d)", __func__, image_effect); + return -1; + } + + if (m_params->effects != image_effect) { + if (m_flag_camera_create) { + if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_EFFECT, image_effect) < 0) { + LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_EFFECT", __func__); + return -1; + } + m_params->effects = image_effect; + } + } + + return 0; +} + +int SecCamera::getImageEffect(void) +{ + LOGV("%s : image_effect(%d)", __func__, m_params->effects); + return m_params->effects; +} + +int SecCamera::setAntiBanding(int anti_banding) +{ + LOGV("%s(anti_banding(%d))", __func__, anti_banding); + + if (anti_banding < ANTI_BANDING_AUTO || ANTI_BANDING_OFF < anti_banding) { + LOGE("ERR(%s):Invalid anti_banding (%d)", __func__, anti_banding); + return -1; + } + + if (m_params->anti_banding != anti_banding) { + if (m_flag_camera_create) { + if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_ANTI_BANDING, anti_banding) < 0) { + LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_ANTI_BANDING", __func__); + return -1; + } + m_params->anti_banding = anti_banding; + } + } + + return 0; +} + +int SecCamera::setSceneMode(int scene_mode) +{ + LOGV("%s(scene_mode(%d))", __func__, scene_mode); + + if (scene_mode <= SCENE_MODE_BASE || SCENE_MODE_MAX <= scene_mode) { + LOGE("ERR(%s):Invalid scene_mode (%d)", __func__, scene_mode); + return -1; + } + + if (m_params->scene_mode != scene_mode) { + if (m_flag_camera_create) { + LOGE("%s(scene_mode(%d))", __func__, scene_mode); + if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_SCENE_MODE, scene_mode) < 0) { + LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_SCENE_MODE", __func__); + return -1; + } + m_params->scene_mode = scene_mode; + } + } + + return 0; +} + +int SecCamera::getSceneMode(void) +{ + return m_params->scene_mode; +} + +int SecCamera::setFlashMode(int flash_mode) +{ + LOGV("%s(flash_mode(%d))", __func__, flash_mode); + + if (flash_mode <= FLASH_MODE_BASE || FLASH_MODE_MAX <= flash_mode) { + LOGE("ERR(%s):Invalid flash_mode (%d)", __func__, flash_mode); + return -1; + } + + if (m_params->flash_mode != flash_mode) { + if (m_flag_camera_create) { + if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_FLASH_MODE, flash_mode) < 0) { + LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_FLASH_MODE", __func__); + return -1; + } + m_params->flash_mode = flash_mode; + } + } + + return 0; +} + +int SecCamera::getFlashMode(void) +{ + return m_params->flash_mode; +} + +int SecCamera::setAutoExposureLock(int toggle) +{ + LOGV("%s(toggle value(%d))", __func__, toggle); + + int aeawb_mode = m_params->aeawb_mode; + + if (m_flag_camera_create) { + if (toggle ^ aeawb_mode) { + aeawb_mode = aeawb_mode ^ 0x1; + m_params->aeawb_mode = aeawb_mode; + if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_AEAWB_LOCK_UNLOCK, aeawb_mode) < 0) { + LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_AEAWB_LOCK_UNLOCK", __func__); + return -1; + } + } + } + return 0; +} + +int SecCamera::setAutoWhiteBalanceLock(int toggle) +{ + LOGV("%s(toggle value(%d))", __func__, toggle); + + int aeawb_mode = m_params->aeawb_mode; + + if (m_flag_camera_create) { + if (toggle ^ (aeawb_mode >> 1)) { + aeawb_mode = aeawb_mode ^ (0x1 << 1); + m_params->aeawb_mode = aeawb_mode; + if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_AEAWB_LOCK_UNLOCK, aeawb_mode) < 0) { + LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_AEAWB_LOCK_UNLOCK", __func__); + return -1; + } + } + } + return 0; +} + +int SecCamera::setISO(int iso_value) +{ + LOGV("%s(iso_value(%d))", __func__, iso_value); + + if (iso_value < ISO_AUTO || ISO_MAX <= iso_value) { + LOGE("ERR(%s):Invalid iso_value (%d)", __func__, iso_value); + return -1; + } + + if (m_params->iso != iso_value) { + if (m_flag_camera_create) { + if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_ISO, iso_value) < 0) { + LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_ISO", __func__); + return -1; + } + m_params->iso = iso_value; + } + } + + return 0; +} + +int SecCamera::getISO(void) +{ + return m_params->iso; +} + +int SecCamera::setContrast(int contrast_value) +{ + LOGV("%s(contrast_value(%d))", __func__, contrast_value); + + if (m_camera_use_ISP) { + if (contrast_value < IS_CONTRAST_AUTO || IS_CONTRAST_MAX <= contrast_value) { + LOGE("ERR(%s):Invalid contrast_value (%d)", __func__, contrast_value); + return -1; + } + } else { + if (contrast_value < CONTRAST_MINUS_2 || CONTRAST_MAX <= contrast_value) { + LOGE("ERR(%s):Invalid contrast_value (%d)", __func__, contrast_value); + return -1; + } + } + + if (m_params->contrast != contrast_value) { + if (m_flag_camera_create) { + if (m_camera_use_ISP) { + if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_IS_CAMERA_CONTRAST, contrast_value) < 0) { + LOGE("ERR(%s):Fail on V4L2_CID_IS_CAMERA_CONTRAST", __func__); + return -1; + } + } else { + if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_CONTRAST, contrast_value) < 0) { + LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_CONTRAST", __func__); + return -1; + } + } + m_params->contrast = contrast_value; + } + } + + return 0; +} + +int SecCamera::getContrast(void) +{ + return m_params->contrast; +} + +int SecCamera::setSaturation(int saturation_value) +{ + LOGV("%s(saturation_value(%d))", __func__, saturation_value); + + saturation_value += SATURATION_DEFAULT; + if (saturation_value < SATURATION_MINUS_2 || SATURATION_MAX <= saturation_value) { + LOGE("ERR(%s):Invalid saturation_value (%d)", __func__, saturation_value); + return -1; + } + + if (m_params->saturation != saturation_value) { + if (m_flag_camera_create) { + if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_SATURATION, saturation_value) < 0) { + LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_SATURATION", __func__); + return -1; + } + m_params->saturation = saturation_value; + } + } + + return 0; +} + +int SecCamera::getSaturation(void) +{ + return m_params->saturation; +} + +int SecCamera::setSharpness(int sharpness_value) +{ + LOGV("%s(sharpness_value(%d))", __func__, sharpness_value); + + sharpness_value += SHARPNESS_DEFAULT; + if (sharpness_value < SHARPNESS_MINUS_2 || SHARPNESS_MAX <= sharpness_value) { + LOGE("ERR(%s):Invalid sharpness_value (%d)", __func__, sharpness_value); + return -1; + } + + if (m_params->sharpness != sharpness_value) { + if (m_flag_camera_create) { + if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_SHARPNESS, sharpness_value) < 0) { + LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_SHARPNESS", __func__); + return -1; + } + m_params->sharpness = sharpness_value; + } + } + + return 0; +} + +int SecCamera::getSharpness(void) +{ + return m_params->sharpness; +} + +int SecCamera::setHue(int hue_value) +{ + LOGV("%s(hue_value(%d))", __func__, hue_value); + +/* TODO */ +/* This code is temporary implementation because * + * hue value tuning was not complete */ +#ifdef USE_HUE + if (m_camera_use_ISP) { + hue_value += IS_HUE_DEFAULT; + if (hue_value < IS_HUE_MINUS_2 || IS_HUE_MAX <= hue_value) { + LOGE("ERR(%s):Invalid hue_value (%d)", __func__, hue_value); + return -1; + } + } else { + LOGW("WARN(%s):Not supported hue setting", __func__); + return 0; + } + + if (m_params->hue != hue_value) { + if (m_flag_camera_create) { + if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_IS_CAMERA_HUE, hue_value) < 0) { + LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_HUE", __func__); + return -1; + } + m_params->hue = hue_value; + } + } +#endif + + return 0; +} + +int SecCamera::getHue(void) +{ + return m_params->hue; +} + +int SecCamera::setWDR(int wdr_value) +{ + LOGV("%s(wdr_value(%d))", __func__, wdr_value); + + if (m_camera_use_ISP) { + if (wdr_value < IS_DRC_BYPASS_DISABLE || IS_DRC_BYPASS_MAX <= wdr_value) { + LOGE("ERR(%s):Invalid drc_value (%d)", __func__, wdr_value); + return -1; + } + } else { + if (wdr_value < WDR_OFF || WDR_MAX <= wdr_value) { + LOGE("ERR(%s):Invalid wdr_value (%d)", __func__, wdr_value); + return -1; + } + } + + if (m_wdr != wdr_value) { + if (m_flag_camera_create) { + if (m_camera_use_ISP) { + if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_IS_SET_DRC, wdr_value) < 0) { + LOGE("ERR(%s):Fail on V4L2_CID_IS_SET_DRC", __func__); + return -1; + } + } else { + if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_WDR, wdr_value) < 0) { + LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_WDR", __func__); + return -1; + } + } + m_wdr = wdr_value; + } + } + + return 0; +} + +int SecCamera::getWDR(void) +{ + return m_wdr; +} + +int SecCamera::setAntiShake(int anti_shake) +{ + LOGV("%s(anti_shake(%d))", __func__, anti_shake); + + if (anti_shake < ANTI_SHAKE_OFF || ANTI_SHAKE_MAX <= anti_shake) { + LOGE("ERR(%s):Invalid anti_shake (%d)", __func__, anti_shake); + return -1; + } + + if (m_anti_shake != anti_shake) { + if (m_flag_camera_create) { + if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_ANTI_SHAKE, anti_shake) < 0) { + LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_ANTI_SHAKE", __func__); + return -1; + } + m_anti_shake = anti_shake; + } + } + + return 0; +} + +int SecCamera::getAntiShake(void) +{ + return m_anti_shake; +} + +int SecCamera::setMetering(int metering_value) +{ + LOGV("%s(metering (%d))", __func__, metering_value); + + if (metering_value <= METERING_BASE || METERING_MAX <= metering_value) { + LOGE("ERR(%s):Invalid metering_value (%d)", __func__, metering_value); + return -1; + } + + if (m_params->metering != metering_value) { + if (m_flag_camera_create) { + if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_METERING, metering_value) < 0) { + LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_METERING", __func__); + return -1; + } + m_params->metering = metering_value; + } + } + + return 0; +} + +int SecCamera::getMetering(void) +{ + return m_params->metering; +} + +int SecCamera::setJpegQuality(int jpeg_quality) +{ + LOGV("%s(jpeg_quality (%d))", __func__, jpeg_quality); + + if (jpeg_quality < JPEG_QUALITY_ECONOMY || JPEG_QUALITY_MAX <= jpeg_quality) { + LOGE("ERR(%s):Invalid jpeg_quality (%d)", __func__, jpeg_quality); + return -1; + } + + if (m_jpeg_quality != jpeg_quality) { + m_jpeg_quality = jpeg_quality; + if (m_flag_camera_create && !m_camera_use_ISP) { + jpeg_quality -= 5; + if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAM_JPEG_QUALITY, jpeg_quality) < 0) { + LOGE("ERR(%s):Fail on V4L2_CID_CAM_JPEG_QUALITY", __func__); + return -1; + } + } + } + + return 0; +} + +int SecCamera::getJpegQuality(void) +{ + return m_jpeg_quality; +} + +int SecCamera::setZoom(int zoom_level) +{ + LOGV("%s(zoom_level (%d))", __func__, zoom_level); + + if (zoom_level < ZOOM_LEVEL_0 || ZOOM_LEVEL_MAX <= zoom_level) { + LOGE("ERR(%s):Invalid zoom_level (%d)", __func__, zoom_level); + return -1; + } + + if (m_zoom_level != zoom_level) { + if (m_flag_camera_create) { + if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_ZOOM, zoom_level) < 0) { + LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_ZOOM", __func__); + return -1; + } + m_zoom_level = zoom_level; + } + } + + return 0; +} + +int SecCamera::getZoom(void) +{ + return m_zoom_level; +} + +int SecCamera::setObjectTracking(int object_tracking) +{ + LOGV("%s(object_tracking (%d))", __func__, object_tracking); + + if (object_tracking < OBJECT_TRACKING_OFF || OBJECT_TRACKING_MAX <= object_tracking) { + LOGE("ERR(%s):Invalid object_tracking (%d)", __func__, object_tracking); + return -1; + } + + if (m_object_tracking != object_tracking) + m_object_tracking = object_tracking; + + return 0; +} + +int SecCamera::getObjectTracking(void) +{ + return m_object_tracking; +} + +int SecCamera::getObjectTrackingStatus(void) +{ + int obj_status = 0; + obj_status = fimc_v4l2_g_ctrl(m_cam_fd, V4L2_CID_CAMERA_OBJ_TRACKING_STATUS); + return obj_status; +} + +int SecCamera::setObjectTrackingStartStop(int start_stop) +{ + LOGV("%s(object_tracking_start_stop (%d))", __func__, start_stop); + + if (m_object_tracking_start_stop != start_stop) { + m_object_tracking_start_stop = start_stop; + if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_OBJ_TRACKING_START_STOP, start_stop) < 0) { + LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_OBJ_TRACKING_START_STOP", __func__); + return -1; + } + } + + return 0; +} + +int SecCamera::setTouchAFStartStop(int start_stop) +{ + LOGV("%s(touch_af_start_stop (%d))", __func__, start_stop); + + if (m_touch_af_start_stop != start_stop) { + m_touch_af_start_stop = start_stop; + if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_TOUCH_AF_START_STOP, start_stop) < 0) { + LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_TOUCH_AF_START_STOP", __func__); + return -1; + } + } + + return 0; +} + +int SecCamera::setSmartAuto(int smart_auto) +{ + LOGV("%s(smart_auto (%d))", __func__, smart_auto); + + if (smart_auto < SMART_AUTO_OFF || SMART_AUTO_MAX <= smart_auto) { + LOGE("ERR(%s):Invalid smart_auto (%d)", __func__, smart_auto); + return -1; + } + + if (m_smart_auto != smart_auto) { + if (m_flag_camera_create) { + if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_SMART_AUTO, smart_auto) < 0) { + LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_SMART_AUTO", __func__); + return -1; + } + m_smart_auto = smart_auto; + } + } + + return 0; +} + +int SecCamera::getSmartAuto(void) +{ + return m_smart_auto; +} + +int SecCamera::getAutosceneStatus(void) +{ + int autoscene_status = -1; + + if (getSmartAuto() == SMART_AUTO_ON) { + autoscene_status = fimc_v4l2_g_ctrl(m_cam_fd, V4L2_CID_CAMERA_SMART_AUTO_STATUS); + + if ((autoscene_status < SMART_AUTO_STATUS_AUTO) || (autoscene_status > SMART_AUTO_STATUS_MAX)) { + LOGE("ERR(%s):Invalid getAutosceneStatus (%d)", __func__, autoscene_status); + return -1; + } + } + return autoscene_status; +} + +int SecCamera::setBeautyShot(int beauty_shot) +{ + LOGV("%s(beauty_shot (%d))", __func__, beauty_shot); + + if (beauty_shot < BEAUTY_SHOT_OFF || BEAUTY_SHOT_MAX <= beauty_shot) { + LOGE("ERR(%s):Invalid beauty_shot (%d)", __func__, beauty_shot); + return -1; + } + + if (m_beauty_shot != beauty_shot) { + if (m_flag_camera_create) { + if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_BEAUTY_SHOT, beauty_shot) < 0) { + LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_BEAUTY_SHOT", __func__); + return -1; + } + m_beauty_shot = beauty_shot; + } + + setFaceDetect(FACE_DETECTION_ON_BEAUTY); + } + + return 0; +} + +int SecCamera::getBeautyShot(void) +{ + return m_beauty_shot; +} + +int SecCamera::setVintageMode(int vintage_mode) +{ + LOGV("%s(vintage_mode(%d))", __func__, vintage_mode); + + if (vintage_mode <= VINTAGE_MODE_BASE || VINTAGE_MODE_MAX <= vintage_mode) { + LOGE("ERR(%s):Invalid vintage_mode (%d)", __func__, vintage_mode); + return -1; + } + + if (m_vintage_mode != vintage_mode) { + if (m_flag_camera_create) { + if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_VINTAGE_MODE, vintage_mode) < 0) { + LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_VINTAGE_MODE", __func__); + return -1; + } + m_vintage_mode = vintage_mode; + } + } + + return 0; +} + +int SecCamera::getVintageMode(void) +{ + return m_vintage_mode; +} + +int SecCamera::setFocusMode(int focus_mode) +{ + LOGV("%s(focus_mode(%d))", __func__, focus_mode); + + if (FOCUS_MODE_MAX <= focus_mode) { + LOGE("ERR(%s):Invalid focus_mode (%d)", __func__, focus_mode); + return -1; + } + + if (m_params->focus_mode != focus_mode) { + if (m_flag_camera_create) { + if (m_params->focus_mode == FOCUS_MODE_AUTO || m_params->focus_mode == FOCUS_MODE_MACRO) { + if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_SET_AUTO_FOCUS, AUTO_FOCUS_OFF) < 0) { + LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_SET_AUTO_FOCUS", __func__); + return -1; + } + } + if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_FOCUS_MODE, focus_mode) < 0) { + LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_FOCUS_MODE", __func__); + return -1; + } + if (!m_camera_use_ISP) { + if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_SET_AUTO_FOCUS, AUTO_FOCUS_ON) < 0) { + LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_SET_AUTO_FOCUS", __func__); + return -1; + } + } + m_params->focus_mode = focus_mode; + } + } + + return 0; +} + +int SecCamera::getFocusMode(void) +{ + return m_params->focus_mode; +} + +int SecCamera::setFaceDetect(int face_detect) +{ + LOGV("%s(face_detect(%d))", __func__, face_detect); + if (m_camera_use_ISP) { + if (face_detect < IS_FD_COMMAND_STOP || IS_FD_COMMAND_MAX <= face_detect) { + LOGE("ERR(%s):Invalid face_detect value (%d)", __func__, face_detect); + return -1; + } + } else { + if (face_detect < FACE_DETECTION_OFF || FACE_DETECTION_MAX <= face_detect) { + LOGE("ERR(%s):Invalid face_detect value (%d)", __func__, face_detect); + return -1; + } + } + + if (m_face_detect != face_detect) { + if (m_flag_camera_create) { + if (m_camera_use_ISP) { + if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_IS_CMD_FD, face_detect) < 0) { + LOGE("ERR(%s):Fail on V4L2_CID_IS_CMD_FD", __func__); + return -1; + } + } else { + if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_FACE_DETECTION, face_detect) < 0) { + LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_FACE_DETECTION", __func__); + return -1; + } + } + m_face_detect = face_detect; + } + } + + return 0; +} + +int SecCamera::getFaceDetect(void) +{ + return m_face_detect; +} + +int SecCamera::setGPSLatitude(const char *gps_latitude) +{ + double conveted_latitude = 0; + LOGV("%s(gps_latitude(%s))", __func__, gps_latitude); + if (gps_latitude == NULL) + m_gps_latitude = 0; + else { + conveted_latitude = atof(gps_latitude); + m_gps_latitude = (long)(conveted_latitude * 10000 / 1); + } + + LOGV("%s(m_gps_latitude(%ld))", __func__, m_gps_latitude); + return 0; +} + +int SecCamera::setGPSLongitude(const char *gps_longitude) +{ + double conveted_longitude = 0; + LOGV("%s(gps_longitude(%s))", __func__, gps_longitude); + if (gps_longitude == NULL) + m_gps_longitude = 0; + else { + conveted_longitude = atof(gps_longitude); + m_gps_longitude = (long)(conveted_longitude * 10000 / 1); + } + + LOGV("%s(m_gps_longitude(%ld))", __func__, m_gps_longitude); + return 0; +} + +int SecCamera::setGPSAltitude(const char *gps_altitude) +{ + double conveted_altitude = 0; + LOGV("%s(gps_altitude(%s))", __func__, gps_altitude); + if (gps_altitude == NULL) + m_gps_altitude = 0; + else { + conveted_altitude = atof(gps_altitude); + m_gps_altitude = (long)(conveted_altitude * 100 / 1); + } + + LOGV("%s(m_gps_altitude(%ld))", __func__, m_gps_altitude); + return 0; +} + +int SecCamera::setGPSTimeStamp(const char *gps_timestamp) +{ + LOGV("%s(gps_timestamp(%s))", __func__, gps_timestamp); + if (gps_timestamp == NULL) + m_gps_timestamp = 0; + else + m_gps_timestamp = atol(gps_timestamp); + + LOGV("%s(m_gps_timestamp(%ld))", __func__, m_gps_timestamp); + return 0; +} + +int SecCamera::setGPSProcessingMethod(const char *gps_processing_method) +{ + LOGV("%s(gps_processing_method(%s))", __func__, gps_processing_method); + memset(mExifInfo.gps_processing_method, 0, sizeof(mExifInfo.gps_processing_method)); + if (gps_processing_method != NULL) { + size_t len = strlen(gps_processing_method); + if (len > sizeof(mExifInfo.gps_processing_method)) { + len = sizeof(mExifInfo.gps_processing_method); + } + memcpy(mExifInfo.gps_processing_method, gps_processing_method, len); + } + return 0; +} + +int SecCamera::setFaceDetectLockUnlock(int facedetect_lockunlock) +{ + LOGV("%s(facedetect_lockunlock(%d))", __func__, facedetect_lockunlock); + + if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_FACEDETECT_LOCKUNLOCK, facedetect_lockunlock) < 0) { + LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_FACEDETECT_LOCKUNLOCK", __func__); + return -1; + } + + return 0; +} + +int SecCamera::setObjectPosition(int x, int y) +{ + LOGV("%s(setObjectPosition(x=%d, y=%d))", __func__, x, y); + + if (m_flag_camera_start) { + if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_OBJECT_POSITION_X, x) < 0) { + LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_OBJECT_POSITION_X", __func__); + return -1; + } + if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_OBJECT_POSITION_Y, y) < 0) { + LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_OBJECT_POSITION_Y", __func__); + return -1; + } + } + + return 0; +} + +int SecCamera::setGamma(int gamma) +{ + LOGV("%s(gamma(%d))", __func__, gamma); + + if (gamma < GAMMA_OFF || GAMMA_MAX <= gamma) { + LOGE("ERR(%s):Invalid gamma (%d)", __func__, gamma); + return -1; + } + + if (m_video_gamma != gamma) { + if (m_flag_camera_create) { + if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_SET_GAMMA, gamma) < 0) { + LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_SET_GAMMA", __func__); + return -1; + } + m_video_gamma = gamma; + } + } + + return 0; +} + +int SecCamera::setSlowAE(int slow_ae) +{ + LOGV("%s(slow_ae(%d))", __func__, slow_ae); + + if (slow_ae < GAMMA_OFF || GAMMA_MAX <= slow_ae) { + LOGE("ERR(%s):Invalid slow_ae (%d)", __func__, slow_ae); + return -1; + } + + if (m_slow_ae!= slow_ae) { + if (m_flag_camera_create) { + if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_SET_SLOW_AE, slow_ae) < 0) { + LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_SET_SLOW_AE", __func__); + return -1; + } + m_slow_ae = slow_ae; + } + } + + return 0; +} + +int SecCamera::setRecordingSize(int width, int height) +{ + LOGV("%s(width(%d), height(%d))", __func__, width, height); + + m_recording_width = width; + m_recording_height = height; + + return 0; +} + +int SecCamera::getRecordingSize(int *width, int *height) +{ + *width = m_recording_width; + *height = m_recording_height; + + return 0; +} + +int SecCamera::setExifOrientationInfo(int orientationInfo) +{ + LOGV("%s(orientationInfo(%d))", __func__, orientationInfo); + + if (orientationInfo < 0) { + LOGE("ERR(%s):Invalid orientationInfo (%d)", __func__, orientationInfo); + return -1; + } + m_exif_orientation = orientationInfo; + + return 0; +} + +int SecCamera::setBatchReflection() +{ + if (m_flag_camera_create) { + if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_BATCH_REFLECTION, 1) < 0) { + LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_BATCH_REFLECTION", __func__); + return -1; + } + } + + return 0; +} + +/* Camcorder fix fps */ +int SecCamera::setSensorMode(int sensor_mode) +{ + LOGV("%s(sensor_mode (%d))", __func__, sensor_mode); + + if (sensor_mode < SENSOR_MODE_CAMERA || SENSOR_MODE_MOVIE < sensor_mode) { + LOGE("ERR(%s):Invalid sensor mode (%d)", __func__, sensor_mode); + return -1; + } + + if (m_sensor_mode != sensor_mode) + m_sensor_mode = sensor_mode; + + return 0; +} + +/* Shot mode */ +/* SINGLE = 0 +* CONTINUOUS = 1 +* PANORAMA = 2 +* SMILE = 3 +* SELF = 6 +*/ +int SecCamera::setShotMode(int shot_mode) +{ + LOGV("%s(shot_mode (%d))", __func__, shot_mode); + if (shot_mode < SHOT_MODE_SINGLE || SHOT_MODE_SELF < shot_mode) { + LOGE("ERR(%s):Invalid shot_mode (%d)", __func__, shot_mode); + return -1; + } + m_shot_mode = shot_mode; + + return 0; +} + +int SecCamera::setDataLineCheck(int chk_dataline) +{ + LOGV("%s(chk_dataline (%d))", __func__, chk_dataline); + + if (chk_dataline < CHK_DATALINE_OFF || CHK_DATALINE_MAX <= chk_dataline) { + LOGE("ERR(%s):Invalid chk_dataline (%d)", __func__, chk_dataline); + return -1; + } + + m_chk_dataline = chk_dataline; + + return 0; +} + +int SecCamera::getDataLineCheck(void) +{ + return m_chk_dataline; +} + +int SecCamera::setDataLineCheckStop(void) +{ + LOGV("%s", __func__); + + if (m_flag_camera_create) { + if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_CHECK_DATALINE_STOP, 1) < 0) { + LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_CHECK_DATALINE_STOP", __func__); + return -1; + } + } + return 0; +} + +const __u8* SecCamera::getCameraSensorName(void) +{ + LOGV("%s", __func__); + + return fimc_v4l2_enuminput(m_cam_fd, getCameraId()); +} + +bool SecCamera::getUseInternalISP(void) +{ + LOGV("%s", __func__); + int ret = 0; + +/*TODO*/ + if (!strncmp((const char*)getCameraSensorName(), "ISP Camera", 10)) + return true; + else if(!strncmp((const char*)getCameraSensorName(), "S5K3H2", 10)) + return true; + else if(!strncmp((const char*)getCameraSensorName(), "S5K3H7", 10)) + return true; + else if(!strncmp((const char*)getCameraSensorName(), "S5K4E5", 10)) + return true; + else if(!strncmp((const char*)getCameraSensorName(), "S5K6A3", 10)) + return true; + else + return false; +} + +#ifdef ENABLE_ESD_PREVIEW_CHECK +int SecCamera::getCameraSensorESDStatus(void) +{ + LOGV("%s", __func__); + + // 0 : normal operation, 1 : abnormal operation + int status = fimc_v4l2_g_ctrl(m_cam_fd, V4L2_CID_ESD_INT); + + return status; +} +#endif // ENABLE_ESD_PREVIEW_CHECK + +int SecCamera::setJpegThumbnailSize(int width, int height) +{ + LOGV("%s(width(%d), height(%d))", __func__, width, height); + + m_jpeg_thumbnail_width = width; + m_jpeg_thumbnail_height = height; + + return 0; +} + +int SecCamera::getJpegThumbnailSize(int *width, int *height) +{ + if (width) + *width = m_jpeg_thumbnail_width; + if (height) + *height = m_jpeg_thumbnail_height; + + return 0; +} + +int SecCamera::setJpegThumbnailQuality(int jpeg_thumbnail_quality) +{ + LOGV("%s(jpeg_thumbnail_quality (%d))", __func__, jpeg_thumbnail_quality); + + if (jpeg_thumbnail_quality < JPEG_QUALITY_ECONOMY || JPEG_QUALITY_MAX <= jpeg_thumbnail_quality) { + LOGE("ERR(%s):Invalid jpeg_thumbnail_quality (%d)", __func__, jpeg_thumbnail_quality); + return -1; + } + + if (m_jpeg_thumbnail_quality != jpeg_thumbnail_quality) { + m_jpeg_thumbnail_quality = jpeg_thumbnail_quality; + } + + return 0; +} + +int SecCamera::getJpegThumbnailQuality(void) +{ + return m_jpeg_thumbnail_quality; +} + +void SecCamera::setExifFixedAttribute() +{ + char property[PROPERTY_VALUE_MAX]; + + //2 0th IFD TIFF Tags + //3 Maker + property_get("ro.product.brand", property, EXIF_DEF_MAKER); + strncpy((char *)mExifInfo.maker, property, + sizeof(mExifInfo.maker) - 1); + mExifInfo.maker[sizeof(mExifInfo.maker) - 1] = '\0'; + //3 Model + property_get("ro.product.model", property, EXIF_DEF_MODEL); + strncpy((char *)mExifInfo.model, property, + sizeof(mExifInfo.model) - 1); + mExifInfo.model[sizeof(mExifInfo.model) - 1] = '\0'; + //3 Software + property_get("ro.build.id", property, EXIF_DEF_SOFTWARE); + strncpy((char *)mExifInfo.software, property, + sizeof(mExifInfo.software) - 1); + mExifInfo.software[sizeof(mExifInfo.software) - 1] = '\0'; + + //3 YCbCr Positioning + mExifInfo.ycbcr_positioning = EXIF_DEF_YCBCR_POSITIONING; + + //2 0th IFD Exif Private Tags + //3 F Number + mExifInfo.fnumber.num = EXIF_DEF_FNUMBER_NUM; + mExifInfo.fnumber.den = EXIF_DEF_FNUMBER_DEN; + //3 Exposure Program + mExifInfo.exposure_program = EXIF_DEF_EXPOSURE_PROGRAM; + //3 Exif Version + memcpy(mExifInfo.exif_version, EXIF_DEF_EXIF_VERSION, sizeof(mExifInfo.exif_version)); + //3 Aperture + uint32_t av = APEX_FNUM_TO_APERTURE((double)mExifInfo.fnumber.num/mExifInfo.fnumber.den); + mExifInfo.aperture.num = av*EXIF_DEF_APEX_DEN; + mExifInfo.aperture.den = EXIF_DEF_APEX_DEN; + //3 Maximum lens aperture + mExifInfo.max_aperture.num = mExifInfo.aperture.num; + mExifInfo.max_aperture.den = mExifInfo.aperture.den; + //3 Lens Focal Length + if (m_camera_id == CAMERA_ID_BACK) + mExifInfo.focal_length.num = BACK_CAMERA_FOCAL_LENGTH; + else + mExifInfo.focal_length.num = FRONT_CAMERA_FOCAL_LENGTH; + + mExifInfo.focal_length.den = EXIF_DEF_FOCAL_LEN_DEN; + //3 User Comments + strcpy((char *)mExifInfo.user_comment, EXIF_DEF_USERCOMMENTS); + //3 Color Space information + mExifInfo.color_space = EXIF_DEF_COLOR_SPACE; + //3 Exposure Mode + mExifInfo.exposure_mode = EXIF_DEF_EXPOSURE_MODE; + + //2 0th IFD GPS Info Tags + unsigned char gps_version[4] = { 0x02, 0x02, 0x00, 0x00 }; + memcpy(mExifInfo.gps_version_id, gps_version, sizeof(gps_version)); + + //2 1th IFD TIFF Tags + mExifInfo.compression_scheme = EXIF_DEF_COMPRESSION; + mExifInfo.x_resolution.num = EXIF_DEF_RESOLUTION_NUM; + mExifInfo.x_resolution.den = EXIF_DEF_RESOLUTION_DEN; + mExifInfo.y_resolution.num = EXIF_DEF_RESOLUTION_NUM; + mExifInfo.y_resolution.den = EXIF_DEF_RESOLUTION_DEN; + mExifInfo.resolution_unit = EXIF_DEF_RESOLUTION_UNIT; +} + +void SecCamera::setExifChangedAttribute() +{ + //2 0th IFD TIFF Tags + //3 Width + mExifInfo.width = m_snapshot_width; + //3 Height + mExifInfo.height = m_snapshot_height; + //3 Orientation + switch (m_exif_orientation) { + case 90: + mExifInfo.orientation = EXIF_ORIENTATION_90; + break; + case 180: + mExifInfo.orientation = EXIF_ORIENTATION_180; + break; + case 270: + mExifInfo.orientation = EXIF_ORIENTATION_270; + break; + case 0: + default: + mExifInfo.orientation = EXIF_ORIENTATION_UP; + break; + } + //3 Date time + time_t rawtime; + struct tm *timeinfo; + time(&rawtime); + timeinfo = localtime(&rawtime); + strftime((char *)mExifInfo.date_time, 20, "%Y:%m:%d %H:%M:%S", timeinfo); + + //2 0th IFD Exif Private Tags + //3 Exposure Time + int shutterSpeed = 100; + if (m_camera_use_ISP) { + shutterSpeed = fimc_v4l2_g_ctrl(m_cam_fd, V4L2_CID_IS_CAMERA_EXIF_SHUTTERSPEED); + if (shutterSpeed <= 0) { + LOGE("%s: error %d getting shutterSpeed, camera_id = %d, using 100", + __func__, shutterSpeed, m_camera_id); + shutterSpeed = 100; + } + } else { + shutterSpeed = fimc_v4l2_g_ctrl(m_cam_fd, V4L2_CID_CAMERA_EXIF_TV); + if (shutterSpeed <= 0) { + LOGE("%s: error %d getting shutterSpeed, camera_id = %d, using 100", + __func__, shutterSpeed, m_camera_id); + shutterSpeed = 100; + } + } + + /* TODO : external isp is not shuppoting exptime now. */ + int exptime = 100; + if (m_camera_use_ISP) { + exptime = fimc_v4l2_g_ctrl(m_cam_fd, V4L2_CID_CAMERA_EXIF_EXPTIME); + if (exptime <= 0) { + LOGE("%s: error %d getting exposure time, camera_id = %d, using 100", + __func__, exptime, m_camera_id); + exptime = 100; + } + } + mExifInfo.exposure_time.num = 1; + mExifInfo.exposure_time.den = (uint32_t)exptime; + + /* TODO : Normaly exposure time and shutter speed is same. But we need to */ + /* calculate exactly value. */ + shutterSpeed = exptime; + + //3 ISO Speed Rating + int iso; + if (m_camera_use_ISP) + iso = fimc_v4l2_g_ctrl(m_cam_fd, V4L2_CID_IS_CAMERA_EXIF_ISO); + else + iso = fimc_v4l2_g_ctrl(m_cam_fd, V4L2_CID_CAMERA_EXIF_ISO); + if (iso < 0) { + LOGE("%s: error %d getting iso, camera_id = %d, using 100", + __func__, iso, m_camera_id); + iso = 0; + } + mExifInfo.iso_speed_rating = iso; + + uint32_t av, tv, bv, sv, ev; + if (m_camera_use_ISP) { + av = APEX_FNUM_TO_APERTURE((double)mExifInfo.fnumber.num / mExifInfo.fnumber.den); + tv = APEX_EXPOSURE_TO_SHUTTER((double)mExifInfo.exposure_time.num / mExifInfo.exposure_time.den); + sv = APEX_ISO_TO_FILMSENSITIVITY(mExifInfo.iso_speed_rating); + bv = av + tv - sv; + ev = m_params->exposure - IS_EXPOSURE_DEFAULT; + } else { + av = APEX_FNUM_TO_APERTURE((double)mExifInfo.fnumber.num / mExifInfo.fnumber.den); + tv = shutterSpeed; + sv = APEX_ISO_TO_FILMSENSITIVITY(mExifInfo.iso_speed_rating); + bv = fimc_v4l2_g_ctrl(m_cam_fd, V4L2_CID_CAMERA_EXIF_BV); + ev = fimc_v4l2_g_ctrl(m_cam_fd, V4L2_CID_CAMERA_EXIF_EBV); + } + LOGD("Shutter speed=1/%d s, iso=%d", shutterSpeed, mExifInfo.iso_speed_rating); + LOGD("AV=%d, TV=%d, SV=%d, BV=%d, EV=%d", av, tv, sv, bv, ev); + + //3 Shutter Speed + mExifInfo.shutter_speed.num = 1; + mExifInfo.shutter_speed.den = shutterSpeed; + //3 Brightness + mExifInfo.brightness.num = bv*EXIF_DEF_APEX_DEN; + mExifInfo.brightness.den = EXIF_DEF_APEX_DEN; + //3 Exposure Bias + if (m_params->scene_mode == SCENE_MODE_BEACH_SNOW) { + mExifInfo.exposure_bias.num = EXIF_DEF_APEX_DEN; + mExifInfo.exposure_bias.den = EXIF_DEF_APEX_DEN; + } else { + mExifInfo.exposure_bias.num = ev*EXIF_DEF_APEX_DEN; + mExifInfo.exposure_bias.den = EXIF_DEF_APEX_DEN; + } + //3 Metering Mode + switch (m_params->metering) { + case METERING_SPOT: + mExifInfo.metering_mode = EXIF_METERING_SPOT; + break; + case METERING_MATRIX: + mExifInfo.metering_mode = EXIF_METERING_AVERAGE; + break; + case METERING_CENTER: + mExifInfo.metering_mode = EXIF_METERING_CENTER; + break; + default : + mExifInfo.metering_mode = EXIF_METERING_AVERAGE; + break; + } + + //3 Flash + int flash = m_params->flash_mode; + //int flash = fimc_v4l2_g_ctrl(m_cam_fd, V4L2_CID_CAMERA_GET_FLASH_ONOFF); + if (flash < 0) + mExifInfo.flash = EXIF_DEF_FLASH; + else + mExifInfo.flash = flash; + + //3 White Balance + if (m_params->white_balance == WHITE_BALANCE_AUTO || m_params->white_balance == IS_AWB_AUTO) + mExifInfo.white_balance = EXIF_WB_AUTO; + else + mExifInfo.white_balance = EXIF_WB_MANUAL; + //3 Scene Capture Type + switch (m_params->scene_mode) { + case SCENE_MODE_PORTRAIT: + mExifInfo.scene_capture_type = EXIF_SCENE_PORTRAIT; + break; + case SCENE_MODE_LANDSCAPE: + mExifInfo.scene_capture_type = EXIF_SCENE_LANDSCAPE; + break; + case SCENE_MODE_NIGHTSHOT: + mExifInfo.scene_capture_type = EXIF_SCENE_NIGHT; + break; + default: + mExifInfo.scene_capture_type = EXIF_SCENE_STANDARD; + break; + } + + //2 0th IFD GPS Info Tags + if (m_gps_latitude != 0 && m_gps_longitude != 0) { + if (m_gps_latitude > 0) + strcpy((char *)mExifInfo.gps_latitude_ref, "N"); + else + strcpy((char *)mExifInfo.gps_latitude_ref, "S"); + + if (m_gps_longitude > 0) + strcpy((char *)mExifInfo.gps_longitude_ref, "E"); + else + strcpy((char *)mExifInfo.gps_longitude_ref, "W"); + + if (m_gps_altitude > 0) + mExifInfo.gps_altitude_ref = 0; + else + mExifInfo.gps_altitude_ref = 1; + + double latitude = fabs(m_gps_latitude / 10000.0); + double longitude = fabs(m_gps_longitude / 10000.0); + double altitude = fabs(m_gps_altitude / 100.0); + + mExifInfo.gps_latitude[0].num = (uint32_t)latitude; + mExifInfo.gps_latitude[0].den = 1; + mExifInfo.gps_latitude[1].num = (uint32_t)((latitude - mExifInfo.gps_latitude[0].num) * 60); + mExifInfo.gps_latitude[1].den = 1; + mExifInfo.gps_latitude[2].num = (uint32_t)((((latitude - mExifInfo.gps_latitude[0].num) * 60) + - mExifInfo.gps_latitude[1].num) * 60); + mExifInfo.gps_latitude[2].den = 1; + + mExifInfo.gps_longitude[0].num = (uint32_t)longitude; + mExifInfo.gps_longitude[0].den = 1; + mExifInfo.gps_longitude[1].num = (uint32_t)((longitude - mExifInfo.gps_longitude[0].num) * 60); + mExifInfo.gps_longitude[1].den = 1; + mExifInfo.gps_longitude[2].num = (uint32_t)((((longitude - mExifInfo.gps_longitude[0].num) * 60) + - mExifInfo.gps_longitude[1].num) * 60); + mExifInfo.gps_longitude[2].den = 1; + + mExifInfo.gps_altitude.num = (uint32_t)altitude; + mExifInfo.gps_altitude.den = 1; + + struct tm tm_data; + gmtime_r(&m_gps_timestamp, &tm_data); + mExifInfo.gps_timestamp[0].num = tm_data.tm_hour; + mExifInfo.gps_timestamp[0].den = 1; + mExifInfo.gps_timestamp[1].num = tm_data.tm_min; + mExifInfo.gps_timestamp[1].den = 1; + mExifInfo.gps_timestamp[2].num = tm_data.tm_sec; + mExifInfo.gps_timestamp[2].den = 1; + snprintf((char*)mExifInfo.gps_datestamp, sizeof(mExifInfo.gps_datestamp), + "%04d:%02d:%02d", tm_data.tm_year + 1900, tm_data.tm_mon + 1, tm_data.tm_mday); + + mExifInfo.enableGps = true; + } else { + mExifInfo.enableGps = false; + } + + //2 1th IFD TIFF Tags + mExifInfo.widthThumb = m_jpeg_thumbnail_width; + mExifInfo.heightThumb = m_jpeg_thumbnail_height; +} + +int SecCamera::makeExif (unsigned char *exifOut, + unsigned char *thumb_buf, + unsigned int thumb_size, + exif_attribute_t *exifInfo, + unsigned int *size, + bool useMainbufForThumb) +{ + unsigned char *pCur, *pApp1Start, *pIfdStart, *pGpsIfdPtr, *pNextIfdOffset; + unsigned int tmp, LongerTagOffest = 0; + pApp1Start = pCur = exifOut; + + //2 Exif Identifier Code & TIFF Header + pCur += 4; // Skip 4 Byte for APP1 marker and length + unsigned char ExifIdentifierCode[6] = { 0x45, 0x78, 0x69, 0x66, 0x00, 0x00 }; + memcpy(pCur, ExifIdentifierCode, 6); + pCur += 6; + + /* Byte Order - little endian, Offset of IFD - 0x00000008.H */ + unsigned char TiffHeader[8] = { 0x49, 0x49, 0x2A, 0x00, 0x08, 0x00, 0x00, 0x00 }; + memcpy(pCur, TiffHeader, 8); + pIfdStart = pCur; + pCur += 8; + + //2 0th IFD TIFF Tags + if (exifInfo->enableGps) + tmp = NUM_0TH_IFD_TIFF; + else + tmp = NUM_0TH_IFD_TIFF - 1; + + memcpy(pCur, &tmp, NUM_SIZE); + pCur += NUM_SIZE; + + LongerTagOffest += 8 + NUM_SIZE + tmp*IFD_SIZE + OFFSET_SIZE; + + writeExifIfd(&pCur, EXIF_TAG_IMAGE_WIDTH, EXIF_TYPE_LONG, + 1, exifInfo->width); + writeExifIfd(&pCur, EXIF_TAG_IMAGE_HEIGHT, EXIF_TYPE_LONG, + 1, exifInfo->height); + writeExifIfd(&pCur, EXIF_TAG_MAKE, EXIF_TYPE_ASCII, + strlen((char *)exifInfo->maker) + 1, exifInfo->maker, &LongerTagOffest, pIfdStart); + writeExifIfd(&pCur, EXIF_TAG_MODEL, EXIF_TYPE_ASCII, + strlen((char *)exifInfo->model) + 1, exifInfo->model, &LongerTagOffest, pIfdStart); + writeExifIfd(&pCur, EXIF_TAG_ORIENTATION, EXIF_TYPE_SHORT, + 1, exifInfo->orientation); + writeExifIfd(&pCur, EXIF_TAG_SOFTWARE, EXIF_TYPE_ASCII, + strlen((char *)exifInfo->software) + 1, exifInfo->software, &LongerTagOffest, pIfdStart); + writeExifIfd(&pCur, EXIF_TAG_DATE_TIME, EXIF_TYPE_ASCII, + 20, exifInfo->date_time, &LongerTagOffest, pIfdStart); + writeExifIfd(&pCur, EXIF_TAG_YCBCR_POSITIONING, EXIF_TYPE_SHORT, + 1, exifInfo->ycbcr_positioning); + writeExifIfd(&pCur, EXIF_TAG_EXIF_IFD_POINTER, EXIF_TYPE_LONG, + 1, LongerTagOffest); + if (exifInfo->enableGps) { + pGpsIfdPtr = pCur; + pCur += IFD_SIZE; // Skip a ifd size for gps IFD pointer + } + + pNextIfdOffset = pCur; // Skip a offset size for next IFD offset + pCur += OFFSET_SIZE; + + //2 0th IFD Exif Private Tags + pCur = pIfdStart + LongerTagOffest; + + tmp = NUM_0TH_IFD_EXIF; + memcpy(pCur, &tmp , NUM_SIZE); + pCur += NUM_SIZE; + + LongerTagOffest += NUM_SIZE + NUM_0TH_IFD_EXIF*IFD_SIZE + OFFSET_SIZE; + + writeExifIfd(&pCur, EXIF_TAG_EXPOSURE_TIME, EXIF_TYPE_RATIONAL, + 1, &exifInfo->exposure_time, &LongerTagOffest, pIfdStart); + writeExifIfd(&pCur, EXIF_TAG_FNUMBER, EXIF_TYPE_RATIONAL, + 1, &exifInfo->fnumber, &LongerTagOffest, pIfdStart); + writeExifIfd(&pCur, EXIF_TAG_EXPOSURE_PROGRAM, EXIF_TYPE_SHORT, + 1, exifInfo->exposure_program); + writeExifIfd(&pCur, EXIF_TAG_ISO_SPEED_RATING, EXIF_TYPE_SHORT, + 1, exifInfo->iso_speed_rating); + writeExifIfd(&pCur, EXIF_TAG_EXIF_VERSION, EXIF_TYPE_UNDEFINED, + 4, exifInfo->exif_version); + writeExifIfd(&pCur, EXIF_TAG_DATE_TIME_ORG, EXIF_TYPE_ASCII, + 20, exifInfo->date_time, &LongerTagOffest, pIfdStart); + writeExifIfd(&pCur, EXIF_TAG_DATE_TIME_DIGITIZE, EXIF_TYPE_ASCII, + 20, exifInfo->date_time, &LongerTagOffest, pIfdStart); + writeExifIfd(&pCur, EXIF_TAG_SHUTTER_SPEED, EXIF_TYPE_SRATIONAL, + 1, (rational_t *)&exifInfo->shutter_speed, &LongerTagOffest, pIfdStart); + writeExifIfd(&pCur, EXIF_TAG_APERTURE, EXIF_TYPE_RATIONAL, + 1, &exifInfo->aperture, &LongerTagOffest, pIfdStart); + writeExifIfd(&pCur, EXIF_TAG_BRIGHTNESS, EXIF_TYPE_SRATIONAL, + 1, (rational_t *)&exifInfo->brightness, &LongerTagOffest, pIfdStart); + writeExifIfd(&pCur, EXIF_TAG_EXPOSURE_BIAS, EXIF_TYPE_SRATIONAL, + 1, (rational_t *)&exifInfo->exposure_bias, &LongerTagOffest, pIfdStart); + writeExifIfd(&pCur, EXIF_TAG_MAX_APERTURE, EXIF_TYPE_RATIONAL, + 1, &exifInfo->max_aperture, &LongerTagOffest, pIfdStart); + writeExifIfd(&pCur, EXIF_TAG_METERING_MODE, EXIF_TYPE_SHORT, + 1, exifInfo->metering_mode); + writeExifIfd(&pCur, EXIF_TAG_FLASH, EXIF_TYPE_SHORT, + 1, exifInfo->flash); + writeExifIfd(&pCur, EXIF_TAG_FOCAL_LENGTH, EXIF_TYPE_RATIONAL, + 1, &exifInfo->focal_length, &LongerTagOffest, pIfdStart); + char code[8] = { 0x00, 0x00, 0x00, 0x49, 0x49, 0x43, 0x53, 0x41 }; + int commentsLen = strlen((char *)exifInfo->user_comment) + 1; + memmove(exifInfo->user_comment + sizeof(code), exifInfo->user_comment, commentsLen); + memcpy(exifInfo->user_comment, code, sizeof(code)); + writeExifIfd(&pCur, EXIF_TAG_USER_COMMENT, EXIF_TYPE_UNDEFINED, + commentsLen + sizeof(code), exifInfo->user_comment, &LongerTagOffest, pIfdStart); + writeExifIfd(&pCur, EXIF_TAG_COLOR_SPACE, EXIF_TYPE_SHORT, + 1, exifInfo->color_space); + writeExifIfd(&pCur, EXIF_TAG_PIXEL_X_DIMENSION, EXIF_TYPE_LONG, + 1, exifInfo->width); + writeExifIfd(&pCur, EXIF_TAG_PIXEL_Y_DIMENSION, EXIF_TYPE_LONG, + 1, exifInfo->height); + writeExifIfd(&pCur, EXIF_TAG_EXPOSURE_MODE, EXIF_TYPE_LONG, + 1, exifInfo->exposure_mode); + writeExifIfd(&pCur, EXIF_TAG_WHITE_BALANCE, EXIF_TYPE_LONG, + 1, exifInfo->white_balance); + writeExifIfd(&pCur, EXIF_TAG_SCENCE_CAPTURE_TYPE, EXIF_TYPE_LONG, + 1, exifInfo->scene_capture_type); + tmp = 0; + memcpy(pCur, &tmp, OFFSET_SIZE); // next IFD offset + pCur += OFFSET_SIZE; + + //2 0th IFD GPS Info Tags + if (exifInfo->enableGps) { + writeExifIfd(&pGpsIfdPtr, EXIF_TAG_GPS_IFD_POINTER, EXIF_TYPE_LONG, + 1, LongerTagOffest); // GPS IFD pointer skipped on 0th IFD + + pCur = pIfdStart + LongerTagOffest; + + if (exifInfo->gps_processing_method[0] == 0) { + // don't create GPS_PROCESSING_METHOD tag if there isn't any + tmp = NUM_0TH_IFD_GPS - 1; + } else { + tmp = NUM_0TH_IFD_GPS; + } + memcpy(pCur, &tmp, NUM_SIZE); + pCur += NUM_SIZE; + + LongerTagOffest += NUM_SIZE + tmp*IFD_SIZE + OFFSET_SIZE; + + writeExifIfd(&pCur, EXIF_TAG_GPS_VERSION_ID, EXIF_TYPE_BYTE, + 4, exifInfo->gps_version_id); + writeExifIfd(&pCur, EXIF_TAG_GPS_LATITUDE_REF, EXIF_TYPE_ASCII, + 2, exifInfo->gps_latitude_ref); + writeExifIfd(&pCur, EXIF_TAG_GPS_LATITUDE, EXIF_TYPE_RATIONAL, + 3, exifInfo->gps_latitude, &LongerTagOffest, pIfdStart); + writeExifIfd(&pCur, EXIF_TAG_GPS_LONGITUDE_REF, EXIF_TYPE_ASCII, + 2, exifInfo->gps_longitude_ref); + writeExifIfd(&pCur, EXIF_TAG_GPS_LONGITUDE, EXIF_TYPE_RATIONAL, + 3, exifInfo->gps_longitude, &LongerTagOffest, pIfdStart); + writeExifIfd(&pCur, EXIF_TAG_GPS_ALTITUDE_REF, EXIF_TYPE_BYTE, + 1, exifInfo->gps_altitude_ref); + writeExifIfd(&pCur, EXIF_TAG_GPS_ALTITUDE, EXIF_TYPE_RATIONAL, + 1, &exifInfo->gps_altitude, &LongerTagOffest, pIfdStart); + writeExifIfd(&pCur, EXIF_TAG_GPS_TIMESTAMP, EXIF_TYPE_RATIONAL, + 3, exifInfo->gps_timestamp, &LongerTagOffest, pIfdStart); + tmp = strlen((char*)exifInfo->gps_processing_method); + if (tmp > 0) { + if (tmp > 100) { + tmp = 100; + } + static const char ExifAsciiPrefix[] = { 0x41, 0x53, 0x43, 0x49, 0x49, 0x0, 0x0, 0x0 }; + unsigned char tmp_buf[100+sizeof(ExifAsciiPrefix)]; + memcpy(tmp_buf, ExifAsciiPrefix, sizeof(ExifAsciiPrefix)); + memcpy(&tmp_buf[sizeof(ExifAsciiPrefix)], exifInfo->gps_processing_method, tmp); + writeExifIfd(&pCur, EXIF_TAG_GPS_PROCESSING_METHOD, EXIF_TYPE_UNDEFINED, + tmp+sizeof(ExifAsciiPrefix), tmp_buf, &LongerTagOffest, pIfdStart); + } + writeExifIfd(&pCur, EXIF_TAG_GPS_DATESTAMP, EXIF_TYPE_ASCII, + 11, exifInfo->gps_datestamp, &LongerTagOffest, pIfdStart); + tmp = 0; + memcpy(pCur, &tmp, OFFSET_SIZE); // next IFD offset + pCur += OFFSET_SIZE; + } + + //2 1th IFD TIFF Tags + + unsigned char *thumbBuf = thumb_buf; + unsigned int thumbSize = thumb_size; + + if (exifInfo->enableThumb && (thumbBuf != NULL) && (thumbSize > 0)) { + tmp = LongerTagOffest; + memcpy(pNextIfdOffset, &tmp, OFFSET_SIZE); // NEXT IFD offset skipped on 0th IFD + + pCur = pIfdStart + LongerTagOffest; + + tmp = NUM_1TH_IFD_TIFF; + memcpy(pCur, &tmp, NUM_SIZE); + pCur += NUM_SIZE; + + LongerTagOffest += NUM_SIZE + NUM_1TH_IFD_TIFF*IFD_SIZE + OFFSET_SIZE; + + writeExifIfd(&pCur, EXIF_TAG_IMAGE_WIDTH, EXIF_TYPE_LONG, + 1, exifInfo->widthThumb); + writeExifIfd(&pCur, EXIF_TAG_IMAGE_HEIGHT, EXIF_TYPE_LONG, + 1, exifInfo->heightThumb); + writeExifIfd(&pCur, EXIF_TAG_COMPRESSION_SCHEME, EXIF_TYPE_SHORT, + 1, exifInfo->compression_scheme); + writeExifIfd(&pCur, EXIF_TAG_ORIENTATION, EXIF_TYPE_SHORT, + 1, exifInfo->orientation); + writeExifIfd(&pCur, EXIF_TAG_X_RESOLUTION, EXIF_TYPE_RATIONAL, + 1, &exifInfo->x_resolution, &LongerTagOffest, pIfdStart); + writeExifIfd(&pCur, EXIF_TAG_Y_RESOLUTION, EXIF_TYPE_RATIONAL, + 1, &exifInfo->y_resolution, &LongerTagOffest, pIfdStart); + writeExifIfd(&pCur, EXIF_TAG_RESOLUTION_UNIT, EXIF_TYPE_SHORT, + 1, exifInfo->resolution_unit); + writeExifIfd(&pCur, EXIF_TAG_JPEG_INTERCHANGE_FORMAT, EXIF_TYPE_LONG, + 1, LongerTagOffest); + writeExifIfd(&pCur, EXIF_TAG_JPEG_INTERCHANGE_FORMAT_LEN, EXIF_TYPE_LONG, + 1, thumbSize); + + tmp = 0; + memcpy(pCur, &tmp, OFFSET_SIZE); // next IFD offset + pCur += OFFSET_SIZE; + + memcpy(pIfdStart + LongerTagOffest, thumbBuf, thumbSize); + LongerTagOffest += thumbSize; + } else { + tmp = 0; + memcpy(pNextIfdOffset, &tmp, OFFSET_SIZE); // NEXT IFD offset skipped on 0th IFD + } + + unsigned char App1Marker[2] = { 0xff, 0xe1 }; + memcpy(pApp1Start, App1Marker, 2); + pApp1Start += 2; + + *size = 10 + LongerTagOffest; + tmp = *size - 2; // APP1 Maker isn't counted + unsigned char size_mm[2] = {(tmp >> 8) & 0xFF, tmp & 0xFF}; + memcpy(pApp1Start, size_mm, 2); + + LOGD("makeExif X"); + + return 0; +} + +inline void SecCamera::writeExifIfd(unsigned char **pCur, + unsigned short tag, + unsigned short type, + unsigned int count, + uint32_t value) +{ + memcpy(*pCur, &tag, 2); + *pCur += 2; + memcpy(*pCur, &type, 2); + *pCur += 2; + memcpy(*pCur, &count, 4); + *pCur += 4; + memcpy(*pCur, &value, 4); + *pCur += 4; +} + +inline void SecCamera::writeExifIfd(unsigned char **pCur, + unsigned short tag, + unsigned short type, + unsigned int count, + unsigned char *pValue) +{ + char buf[4] = { 0,}; + + memcpy(buf, pValue, count); + memcpy(*pCur, &tag, 2); + *pCur += 2; + memcpy(*pCur, &type, 2); + *pCur += 2; + memcpy(*pCur, &count, 4); + *pCur += 4; + memcpy(*pCur, buf, 4); + *pCur += 4; +} + +inline void SecCamera::writeExifIfd(unsigned char **pCur, + unsigned short tag, + unsigned short type, + unsigned int count, + unsigned char *pValue, + unsigned int *offset, + unsigned char *start) +{ + memcpy(*pCur, &tag, 2); + *pCur += 2; + memcpy(*pCur, &type, 2); + *pCur += 2; + memcpy(*pCur, &count, 4); + *pCur += 4; + memcpy(*pCur, offset, 4); + *pCur += 4; + memcpy(start + *offset, pValue, count); + *offset += count; +} + +inline void SecCamera::writeExifIfd(unsigned char **pCur, + unsigned short tag, + unsigned short type, + unsigned int count, + rational_t *pValue, + unsigned int *offset, + unsigned char *start) +{ + memcpy(*pCur, &tag, 2); + *pCur += 2; + memcpy(*pCur, &type, 2); + *pCur += 2; + memcpy(*pCur, &count, 4); + *pCur += 4; + memcpy(*pCur, offset, 4); + *pCur += 4; + memcpy(start + *offset, pValue, 8 * count); + *offset += 8 * count; +} + +status_t SecCamera::dump(int fd) +{ + const size_t SIZE = 256; + char buffer[SIZE]; + String8 result; + snprintf(buffer, 255, "dump(%d)\n", fd); + result.append(buffer); + ::write(fd, result.string(), result.size()); + return NO_ERROR; +} + +double SecCamera::jpeg_ratio = 0.7; +int SecCamera::interleaveDataSize = 5242880; +int SecCamera::jpegLineLength = 636; + +}; // namespace android diff --git a/exynos4/hal/libcamera/SecCamera.h b/exynos4/hal/libcamera/SecCamera.h new file mode 100644 index 0000000..fc30fc4 --- /dev/null +++ b/exynos4/hal/libcamera/SecCamera.h @@ -0,0 +1,695 @@ +/* +** +** Copyright 2008, The Android Open Source Project +** Copyright 2010, Samsung Electronics Co. LTD +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + +#ifndef ANDROID_HARDWARE_CAMERA_SEC_H +#define ANDROID_HARDWARE_CAMERA_SEC_H + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include "sec_utils_v4l2.h" + +#include "SecBuffer.h" + +#include + +#ifdef SAMSUNG_EXYNOS4210 +#include "jpeg_api.h" +#endif + +#ifdef SAMSUNG_EXYNOS4x12 +#include "jpeg_hal.h" +#endif + +#include "Exif.h" +namespace android { + +//#define ENABLE_ESD_PREVIEW_CHECK +//#define ZERO_SHUTTER_LAG +#define VIDEO_SNAPSHOT + +#if defined VIDEO_SNAPSHOT +#define ZERO_SHUTTER_LAG +#endif + +#define USE_FACE_DETECTION +//#define USE_TOUCH_AF + +#if defined(LOG_NDEBUG) && (LOG_NDEBUG == 0) +#define LOG_CAMERA LOGD +#define LOG_CAMERA_PREVIEW LOGD + +#define LOG_TIME_DEFINE(n) \ + struct timeval time_start_##n, time_stop_##n; unsigned long log_time_##n = 0; + +#define LOG_TIME_START(n) \ + gettimeofday(&time_start_##n, NULL); + +#define LOG_TIME_END(n) \ + gettimeofday(&time_stop_##n, NULL); log_time_##n = measure_time_camera(&time_start_##n, &time_stop_##n); + +#define LOG_TIME(n) \ + log_time_##n + +#else +#define LOG_CAMERA(...) +#define LOG_CAMERA_PREVIEW(...) +#define LOG_TIME_DEFINE(n) +#define LOG_TIME_START(n) +#define LOG_TIME_END(n) +#define LOG_TIME(n) +#endif + +#define FRM_RATIO(w, h) ((w)*10/(h)) +#define SIZE_4K (1 << 12) + +#define JOIN(x, y) JOIN_AGAIN(x, y) +#define JOIN_AGAIN(x, y) x ## y + +#define FRONT_CAM S5K6A3 +#define BACK_CAM M5MO + +#if !defined (FRONT_CAM) || !defined(BACK_CAM) +#error "Please define the Camera module" +#endif + +#define M5MO_PREVIEW_WIDTH 640 +#define M5MO_PREVIEW_HEIGHT 480 +#define M5MO_SNAPSHOT_WIDTH 3264 +#define M5MO_SNAPSHOT_HEIGHT 2448 + +#define M5MO_THUMBNAIL_WIDTH 320 +#define M5MO_THUMBNAIL_HEIGHT 240 +#define M5MO_THUMBNAIL_BPP 16 + +#define M5MO_FPS 30 + +/* focal length of 3.43mm */ +#define M5MO_FOCAL_LENGTH 343 + +#define S5K6A3_PREVIEW_WIDTH 480 +#define S5K6A3_PREVIEW_HEIGHT 480 +#define S5K6A3_SNAPSHOT_WIDTH 1392 +#define S5K6A3_SNAPSHOT_HEIGHT 1392 + +#define S5K6A3_THUMBNAIL_WIDTH 160 +#define S5K6A3_THUMBNAIL_HEIGHT 120 +#define S5K6A3_THUMBNAIL_BPP 16 + +#define S5K6A3_FPS 30 + +/* focal length of 0.9mm */ +#define S5K6A3_FOCAL_LENGTH 90 + +#define MAX_BACK_CAMERA_PREVIEW_WIDTH JOIN(BACK_CAM,_PREVIEW_WIDTH) +#define MAX_BACK_CAMERA_PREVIEW_HEIGHT JOIN(BACK_CAM,_PREVIEW_HEIGHT) +#define MAX_BACK_CAMERA_SNAPSHOT_WIDTH JOIN(BACK_CAM,_SNAPSHOT_WIDTH) +#define MAX_BACK_CAMERA_SNAPSHOT_HEIGHT JOIN(BACK_CAM,_SNAPSHOT_HEIGHT) + +#define BACK_CAMERA_THUMBNAIL_WIDTH JOIN(BACK_CAM,_THUMBNAIL_WIDTH) +#define BACK_CAMERA_THUMBNAIL_HEIGHT JOIN(BACK_CAM,_THUMBNAIL_HEIGHT) +#define BACK_CAMERA_THUMBNAIL_BPP JOIN(BACK_CAM,_THUMBNAIL_BPP) + +#define BACK_CAMERA_FPS JOIN(BACK_CAM,_FPS) + +#define BACK_CAMERA_FOCAL_LENGTH JOIN(BACK_CAM,_FOCAL_LENGTH) + +#define MAX_FRONT_CAMERA_PREVIEW_WIDTH JOIN(FRONT_CAM,_PREVIEW_WIDTH) +#define MAX_FRONT_CAMERA_PREVIEW_HEIGHT JOIN(FRONT_CAM,_PREVIEW_HEIGHT) +#define MAX_FRONT_CAMERA_SNAPSHOT_WIDTH JOIN(FRONT_CAM,_SNAPSHOT_WIDTH) +#define MAX_FRONT_CAMERA_SNAPSHOT_HEIGHT JOIN(FRONT_CAM,_SNAPSHOT_HEIGHT) + +#define FRONT_CAMERA_THUMBNAIL_WIDTH JOIN(FRONT_CAM,_THUMBNAIL_WIDTH) +#define FRONT_CAMERA_THUMBNAIL_HEIGHT JOIN(FRONT_CAM,_THUMBNAIL_HEIGHT) +#define FRONT_CAMERA_THUMBNAIL_BPP JOIN(FRONT_CAM,_THUMBNAIL_BPP) + +#define FRONT_CAMERA_FPS JOIN(FRONT_CAM,_FPS) + +#define FRONT_CAMERA_FOCAL_LENGTH JOIN(FRONT_CAM,_FOCAL_LENGTH) + +#define DEFAULT_JPEG_THUMBNAIL_WIDTH 256 +#define DEFAULT_JPEG_THUMBNAIL_HEIGHT 192 + +#ifdef BOARD_USE_V4L2 +#define CAMERA_DEV_NAME "/dev/video1" +#else +#define CAMERA_DEV_NAME "/dev/video0" +#endif + +#ifdef SAMSUNG_EXYNOS4210 +#define CAMERA_DEV_NAME3 "/dev/video2" +#endif + +#ifdef SAMSUNG_EXYNOS4x12 +#ifdef BOARD_USE_V4L2 +#define CAMERA_DEV_NAME3 "/dev/video3" +#else +#define CAMERA_DEV_NAME3 "/dev/video1" +#endif +#ifdef ZERO_SHUTTER_LAG +#define CAMERA_DEV_NAME2 "/dev/video2" +#endif +#endif + +#define CAMERA_DEV_NAME_TEMP "/data/videotmp_000" +#define CAMERA_DEV_NAME2_TEMP "/data/videotemp_002" + + +#define BPP 2 +#define MIN(x, y) (((x) < (y)) ? (x) : (y)) +#define MAX_BUFFERS 8 + +#ifdef ZERO_SHUTTER_LAG +#define CAP_BUFFERS 8 +#else +#define CAP_BUFFERS 1 +#endif + +#ifdef BOARD_USE_V4L2 +#define MAX_PLANES (3) +#define V4L2_BUF_TYPE V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE +#else +#define MAX_PLANES (1) +#define V4L2_BUF_TYPE V4L2_BUF_TYPE_VIDEO_CAPTURE +#endif + +#ifdef BOARD_USE_V4L2_ION +#define V4L2_MEMORY_TYPE V4L2_MEMORY_USERPTR +#define RECORD_PIX_FMT V4L2_PIX_FMT_NV12M +#define PREVIEW_NUM_PLANE (3) +#define RECORD_NUM_PLANE (2) +#else +#define V4L2_MEMORY_TYPE V4L2_MEMORY_MMAP +#define RECORD_PIX_FMT V4L2_PIX_FMT_NV12 +#define PREVIEW_NUM_PLANE (1) +#define RECORD_NUM_PLANE (1) +#endif + +/* + * V 4 L 2 F I M C E X T E N S I O N S + * + */ +#define V4L2_CID_ROTATION (V4L2_CID_PRIVATE_BASE + 0) +#define V4L2_CID_PADDR_Y (V4L2_CID_PRIVATE_BASE + 1) +#define V4L2_CID_PADDR_CB (V4L2_CID_PRIVATE_BASE + 2) +#define V4L2_CID_PADDR_CR (V4L2_CID_PRIVATE_BASE + 3) +#define V4L2_CID_PADDR_CBCR (V4L2_CID_PRIVATE_BASE + 4) +#define V4L2_CID_STREAM_PAUSE (V4L2_CID_PRIVATE_BASE + 53) + +#define V4L2_CID_CAM_JPEG_MAIN_SIZE (V4L2_CID_PRIVATE_BASE + 32) +#define V4L2_CID_CAM_JPEG_MAIN_OFFSET (V4L2_CID_PRIVATE_BASE + 33) +#define V4L2_CID_CAM_JPEG_THUMB_SIZE (V4L2_CID_PRIVATE_BASE + 34) +#define V4L2_CID_CAM_JPEG_THUMB_OFFSET (V4L2_CID_PRIVATE_BASE + 35) +#define V4L2_CID_CAM_JPEG_POSTVIEW_OFFSET (V4L2_CID_PRIVATE_BASE + 36) +#define V4L2_CID_CAM_JPEG_QUALITY (V4L2_CID_PRIVATE_BASE + 37) + +#define TPATTERN_COLORBAR 1 +#define TPATTERN_HORIZONTAL 2 +#define TPATTERN_VERTICAL 3 + +#define V4L2_PIX_FMT_YVYU v4l2_fourcc('Y', 'V', 'Y', 'U') + +/* FOURCC for FIMC specific */ +#define V4L2_PIX_FMT_VYUY v4l2_fourcc('V', 'Y', 'U', 'Y') +#define V4L2_PIX_FMT_NV16 v4l2_fourcc('N', 'V', '1', '6') +#define V4L2_PIX_FMT_NV61 v4l2_fourcc('N', 'V', '6', '1') +#define V4L2_PIX_FMT_NV12T v4l2_fourcc('T', 'V', '1', '2') +/* + * U S E R D E F I N E D T Y P E S + * + */ +#define PREVIEW_MODE 1 +#define CAPTURE_MODE 2 +#define RECORD_MODE 3 + +struct yuv_fmt_list { + const char *name; + const char *desc; + unsigned int fmt; + int depth; + int planes; +}; + +struct camsensor_date_info { + unsigned int year; + unsigned int month; + unsigned int date; +}; + +class SecCamera : public virtual RefBase { +public: + + enum CAMERA_ID { + CAMERA_ID_BACK = 0, + CAMERA_ID_FRONT = 1, + }; + + enum JPEG_QUALITY { + JPEG_QUALITY_ECONOMY = 0, + JPEG_QUALITY_NORMAL = 50, + JPEG_QUALITY_SUPERFINE = 100, + JPEG_QUALITY_MAX, + }; + + enum OBJECT_TRACKING { + OBJECT_TRACKING_OFF, + OBJECT_TRACKING_ON, + OBJECT_TRACKING_MAX, + }; + + /*VT call*/ + enum VT_MODE { + VT_MODE_OFF, + VT_MODE_ON, + VT_MODE_MAX, + }; + + /*Camera sensor mode - Camcorder fix fps*/ + enum SENSOR_MODE { + SENSOR_MODE_CAMERA, + SENSOR_MODE_MOVIE, + }; + + /*Camera Shot mode*/ + enum SHOT_MODE { + SHOT_MODE_SINGLE = 0, + SHOT_MODE_CONTINUOUS = 1, + SHOT_MODE_PANORAMA = 2, + SHOT_MODE_SMILE = 3, + SHOT_MODE_SELF = 6, + }; + + enum CHK_DATALINE { + CHK_DATALINE_OFF, + CHK_DATALINE_ON, + CHK_DATALINE_MAX, + }; + + enum CAM_MODE { + PREVIEW = 0, + PICTURE = 1, + RECORDING = 2, + }; + + int m_touch_af_start_stop; + + SecCamera(); + virtual ~SecCamera(); + + static SecCamera* createInstance(void) + { + static SecCamera singleton; + return &singleton; + } + status_t dump(int fd); + + bool CreateCamera(int index); + bool DestroyCamera(void); + int getCameraId(void); + void initParameters(int index); + int setMode(int recording_en); + + int startPreview(void); + int stopPreview(void); + int getPreviewState(void) + { + return m_preview_state; + } + void clearPreviewState(void) + { + m_preview_state = 0; + } + + int startSnapshot(SecBuffer *yuv_buf); + int stopSnapshot(void); + int getSnapshot(void); + int setSnapshotFrame(int index); + + int startRecord(bool recordHint); + int stopRecord(void); + int setPreviewFrame(int index); + int getRecordFrame(void); + int releaseRecordFrame(int index); + int getRecordAddr(int index, SecBuffer *buffer); + + int getPreview(camera_frame_metadata_t *facedata); + int setPreviewSize(int width, int height, int pixel_format); + int getPreviewSize(int *width, int *height, int *frame_size); + int getPreviewMaxSize(int *width, int *height); + int getPreviewPixelFormat(void); + int setPreviewImage(int index, unsigned char *buffer, int size); + + int setVideosnapshotSize(int width, int height); + int getVideosnapshotSize(int *width, int *height, int *frame_size); + int setSnapshotSize(int width, int height); + int getSnapshotSize(int *width, int *height, int *frame_size); + int getSnapshotMaxSize(int *width, int *height); + int setSnapshotPixelFormat(int pixel_format); + int getSnapshotPixelFormat(void); + + unsigned char* getJpeg(unsigned char *snapshot_data, int snapshot_size, int *size); + unsigned char* yuv2Jpeg(unsigned char *raw_data, int raw_size, + int *jpeg_size, + int width, int height, int pixel_format); + + int setJpegThumbnailSize(int width, int height); + int getJpegThumbnailSize(int *width, int *height); + + int setJpegThumbnailQuality(int jpeg_thumbnail_quality); + int getJpegThumbnailQuality(void); + + int initSetParams(void); + + int setAutofocus(void); + int setTouchAF(void); + + int SetRotate(int angle); + int getRotate(void); + + int setVerticalMirror(void); + int setHorizontalMirror(void); + + int setWhiteBalance(int white_balance); + int getWhiteBalance(void); + + int setBrightness(int brightness); + int getBrightness(void); + + int setExposure(int exposure); + int getExposure(void); + + int setImageEffect(int image_effect); + int getImageEffect(void); + + int setSceneMode(int scene_mode); + int getSceneMode(void); + + int setFlashMode(int flash_mode); + int getFlashMode(void); + + int setMetering(int metering_value); + int getMetering(void); + + int setAutoExposureLock(int toggle); + int setAutoWhiteBalanceLock(int toggle); + + int setISO(int iso_value); + int getISO(void); + + int setContrast(int contrast_value); + int getContrast(void); + + int setSaturation(int saturation_value); + int getSaturation(void); + + int setSharpness(int sharpness_value); + int getSharpness(void); + + int setHue(int hue_value); + int getHue(void); + + int setWDR(int wdr_value); + int getWDR(void); + + int setAntiShake(int anti_shake); + int getAntiShake(void); + + int setJpegQuality(int jpeg_qality); + int getJpegQuality(void); + + int setZoom(int zoom_level); + int getZoom(void); + + int setObjectTracking(int object_tracking); + int getObjectTracking(void); + int getObjectTrackingStatus(void); + + int setSmartAuto(int smart_auto); + int getSmartAuto(void); + int getAutosceneStatus(void); + + int setBeautyShot(int beauty_shot); + int getBeautyShot(void); + + int setVintageMode(int vintage_mode); + int getVintageMode(void); + + int setFocusMode(int focus_mode); + int getFocusMode(void); + + int setFaceDetect(int face_detect); + int getFaceDetect(void); + + int setGPSLatitude(const char *gps_latitude); + int setGPSLongitude(const char *gps_longitude); + int setGPSAltitude(const char *gps_altitude); + int setGPSTimeStamp(const char *gps_timestamp); + int setGPSProcessingMethod(const char *gps_timestamp); + int cancelAutofocus(void); + int setFaceDetectLockUnlock(int facedetect_lockunlock); + int setObjectPosition(int x, int y); + int setObjectTrackingStartStop(int start_stop); + int setTouchAFStartStop(int start_stop); + int setCAFStatus(int on_off); + int getAutoFocusResult(void); + int setAntiBanding(int anti_banding); + int getPostview(void); + int setRecordingSize(int width, int height); + int getRecordingSize(int *width, int *height); + int setGamma(int gamma); + int setSlowAE(int slow_ae); + int setExifOrientationInfo(int orientationInfo); + int setBatchReflection(void); + int setSnapshotCmd(void); + int endSnapshot(void); + int setCameraSensorReset(void); + int setSensorMode(int sensor_mode); /* Camcorder fix fps */ + int setShotMode(int shot_mode); /* Shot mode */ + int setDataLineCheck(int chk_dataline); + int getDataLineCheck(void); + int setDataLineCheckStop(void); + int setDefultIMEI(int imei); + int getDefultIMEI(void); + const __u8* getCameraSensorName(void); + bool getUseInternalISP(void); +#ifdef ENABLE_ESD_PREVIEW_CHECK + int getCameraSensorESDStatus(void); +#endif // ENABLE_ESD_PREVIEW_CHECK + + int setFrameRate(int frame_rate); + unsigned char* getJpeg(int *jpeg_size, + int *thumb_size, + unsigned int *thumb_addr, + unsigned int *phyaddr); + int getSnapshotAndJpeg(SecBuffer *yuv_buf, + int index, + unsigned char *jpeg_buf, + int *output_size); + int getExif(unsigned char *pExifDst, unsigned char *pThumbSrc, int thumbSize); + + void getPostViewConfig(int*, int*, int*); + void getThumbnailConfig(int *width, int *height, int *size); + + int getPostViewOffset(void); + int getCameraFd(enum CAM_MODE); + int getJpegFd(void); + void SetJpgAddr(unsigned char *addr); + int getPreviewAddr(int index, SecBuffer *buffer); + int getCaptureAddr(int index, SecBuffer *buffer); +#ifdef BOARD_USE_V4L2_ION + void setUserBufferAddr(void *ptr, int index, int mode); +#endif + static void setJpegRatio(double ratio) + { + if((ratio < 0) || (ratio > 1)) + return; + + jpeg_ratio = ratio; + } + + static double getJpegRatio() + { + return jpeg_ratio; + } + + static void setInterleaveDataSize(int x) + { + interleaveDataSize = x; + } + + static int getInterleaveDataSize() + { + return interleaveDataSize; + } + + static void setJpegLineLength(int x) + { + jpegLineLength = x; + } + + static int getJpegLineLength() + { + return jpegLineLength; + } + +private: + v4l2_streamparm m_streamparm; + struct sec_cam_parm *m_params; + int m_flagCreate; + int m_preview_state; + int m_snapshot_state; + int m_camera_id; + bool m_camera_use_ISP; + + int m_cam_fd; + struct pollfd m_events_c; + + int m_cam_fd2; + int m_cap_fd; + struct pollfd m_events_c2; + + int m_cam_fd3; + int m_rec_fd; + struct pollfd m_events_c3; + int m_flag_record_start; + + int m_preview_v4lformat; + int m_preview_width; + int m_preview_height; + int m_preview_max_width; + int m_preview_max_height; + + int m_snapshot_v4lformat; + int m_snapshot_width; + int m_snapshot_height; + int m_snapshot_max_width; + int m_snapshot_max_height; + + int m_num_capbuf; + int m_videosnapshot_width; + int m_videosnapshot_height; + + int m_angle; + int m_anti_banding; + int m_wdr; + int m_anti_shake; + int m_zoom_level; + int m_object_tracking; + int m_smart_auto; + int m_beauty_shot; + int m_vintage_mode; + int m_face_detect; + int m_object_tracking_start_stop; + int m_recording_en; + bool m_record_hint; + int m_recording_width; + int m_recording_height; + long m_gps_latitude; + long m_gps_longitude; + long m_gps_altitude; + long m_gps_timestamp; + int m_sensor_mode; /*Camcorder fix fps */ + int m_shot_mode; /* Shot mode */ + int m_exif_orientation; + int m_chk_dataline; + int m_video_gamma; + int m_slow_ae; + int m_camera_af_flag; + int m_auto_focus_state; + + int m_flag_camera_create; + int m_flag_camera_start; + + int m_jpeg_fd; + int m_jpeg_thumbnail_width; + int m_jpeg_thumbnail_height; + int m_jpeg_thumbnail_quality; + int m_jpeg_quality; + + int m_postview_offset; + +#ifdef ENABLE_ESD_PREVIEW_CHECK + int m_esd_check_count; +#endif // ENABLE_ESD_PREVIEW_CHECK + + exif_attribute_t mExifInfo; + + struct SecBuffer m_capture_buf[CAP_BUFFERS]; + struct SecBuffer m_buffers_preview[MAX_BUFFERS]; + struct SecBuffer m_buffers_record[MAX_BUFFERS]; + + inline void writeExifIfd(unsigned char **pCur, + unsigned short tag, + unsigned short type, + unsigned int count, + uint32_t value); + inline void writeExifIfd(unsigned char **pCur, + unsigned short tag, + unsigned short type, + unsigned int count, + unsigned char *pValue); + inline void writeExifIfd(unsigned char **pCur, + unsigned short tag, + unsigned short type, + unsigned int count, + rational_t *pValue, + unsigned int *offset, + unsigned char *start); + inline void writeExifIfd(unsigned char **pCur, + unsigned short tag, + unsigned short type, + unsigned int count, + unsigned char *pValue, + unsigned int *offset, + unsigned char *start); + + void setExifChangedAttribute(); + void setExifFixedAttribute(); + int makeExif (unsigned char *exifOut, + unsigned char *thumb_buf, + unsigned int thumb_size, + exif_attribute_t *exifInfo, + unsigned int *size, + bool useMainbufForThumb); + void resetCamera(); + + static double jpeg_ratio; + static int interleaveDataSize; + static int jpegLineLength; +}; + +extern unsigned long measure_time_camera(struct timeval *start, struct timeval *stop); + +}; // namespace android + +#endif // ANDROID_HARDWARE_CAMERA_SEC_H diff --git a/exynos4/hal/libcamera/SecCameraHWInterface.cpp b/exynos4/hal/libcamera/SecCameraHWInterface.cpp new file mode 100644 index 0000000..c50ec8d --- /dev/null +++ b/exynos4/hal/libcamera/SecCameraHWInterface.cpp @@ -0,0 +1,3410 @@ +/* +** +** Copyright 2008, The Android Open Source Project +** Copyright 2010, Samsung Electronics Co. LTD +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +//#define LOG_NDEBUG 0 +#define LOG_TAG "CameraHardwareSec" +#include + +#include "SecCameraHWInterface.h" +#include +#include +#include +#include +#include + +#define VIDEO_COMMENT_MARKER_H 0xFFBE +#define VIDEO_COMMENT_MARKER_L 0xFFBF +#define VIDEO_COMMENT_MARKER_LENGTH 4 +#define JPEG_EOI_MARKER 0xFFD9 +#define HIBYTE(x) (((x) >> 8) & 0xFF) +#define LOBYTE(x) ((x) & 0xFF) + +#define BACK_CAMERA_AUTO_FOCUS_DISTANCES_STR "0.10,1.20,Infinity" +#define BACK_CAMERA_MACRO_FOCUS_DISTANCES_STR "0.10,0.20,Infinity" +#define BACK_CAMERA_INFINITY_FOCUS_DISTANCES_STR "0.10,1.20,Infinity" +#define FRONT_CAMERA_FOCUS_DISTANCES_STR "0.20,0.25,Infinity" +#define USE_EGL + +// This hack does two things: +// -- it sets preview to NV21 (YUV420SP) +// -- it sets gralloc to YV12 +// +// The reason being: the samsung encoder understands only yuv420sp, and gralloc +// does yv12 and rgb565. So what we do is we break up the interleaved UV in +// separate V and U planes, which makes preview look good, and enabled the +// encoder as well. +// +// FIXME: Samsung needs to enable support for proper yv12 coming out of the +// camera, and to fix their video encoder to work with yv12. +// FIXME: It also seems like either Samsung's YUV420SP (NV21) or img's YV12 has +// the color planes switched. We need to figure which side is doing it +// wrong and have the respective party fix it. + +namespace android { + +struct addrs { + uint32_t type; // make sure that this is 4 byte. + unsigned int addr_y; + unsigned int addr_cbcr; + unsigned int buf_index; + unsigned int reserved; +}; + +struct addrs_cap { + unsigned int addr_y; + unsigned int width; + unsigned int height; +}; + +static const int INITIAL_SKIP_FRAME = 3; +static const int EFFECT_SKIP_FRAME = 1; + +gralloc_module_t const* CameraHardwareSec::mGrallocHal; + +CameraHardwareSec::CameraHardwareSec(int cameraId, camera_device_t *dev) + : + mCaptureInProgress(false), + mParameters(), + mFrameSizeDelta(0), + mCameraSensorName(NULL), + mUseInternalISP(false), + mSkipFrame(0), + mNotifyCb(0), + mDataCb(0), + mDataCbTimestamp(0), + mCallbackCookie(0), + mMsgEnabled(CAMERA_MSG_RAW_IMAGE), + mRecordRunning(false), + mPostViewWidth(0), + mPostViewHeight(0), + mPostViewSize(0), + mCapIndex(0), + mRecordHint(false), + mTouched(0), + mHalDevice(dev) +{ + LOGV("%s :", __func__); + memset(&mCapBuffer, 0, sizeof(struct SecBuffer)); + int ret = 0; + + mPreviewWindow = NULL; + mSecCamera = SecCamera::createInstance(); + + mRawHeap = NULL; + mPreviewHeap = NULL; + for(int i = 0; i < BUFFER_COUNT_FOR_ARRAY; i++) + mRecordHeap[i] = NULL; + + if (!mGrallocHal) { + ret = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, (const hw_module_t **)&mGrallocHal); + if (ret) + LOGE("ERR(%s):Fail on loading gralloc HAL", __func__); + } + + ret = mSecCamera->CreateCamera(cameraId); + if (ret < 0) { + LOGE("ERR(%s):Fail on mSecCamera init", __func__); + mSecCamera->DestroyCamera(); + } + + initDefaultParameters(cameraId); + + mExitAutoFocusThread = false; + mExitPreviewThread = false; + /* whether the PreviewThread is active in preview or stopped. we + * create the thread but it is initially in stopped state. + */ + mPreviewRunning = false; + mPreviewStartDeferred = false; + mPreviewThread = new PreviewThread(this); + mAutoFocusThread = new AutoFocusThread(this); + mPictureThread = new PictureThread(this); +} + +int CameraHardwareSec::getCameraId() const +{ + return mSecCamera->getCameraId(); +} + +void CameraHardwareSec::initDefaultParameters(int cameraId) +{ + if (mSecCamera == NULL) { + LOGE("ERR(%s):mSecCamera object is NULL", __func__); + return; + } + + CameraParameters p; + CameraParameters ip; + + mCameraSensorName = mSecCamera->getCameraSensorName(); + if (mCameraSensorName == NULL) { + LOGE("ERR(%s):mCameraSensorName is NULL", __func__); + return; + } + LOGV("CameraSensorName: %s", mCameraSensorName); + + int preview_max_width = 0; + int preview_max_height = 0; + int snapshot_max_width = 0; + int snapshot_max_height = 0; + + mCameraID = cameraId; + mUseInternalISP = mSecCamera->getUseInternalISP(); + + if (cameraId == SecCamera::CAMERA_ID_BACK) { + if (mUseInternalISP) { + //3H2 + p.set(CameraParameters::KEY_SUPPORTED_PREVIEW_SIZES, + "720x480,640x384,640x360,640x480,320x240,528x432,176x144"); + p.set(CameraParameters::KEY_SUPPORTED_PICTURE_SIZES, + "3248x2436,3216x2144,3200x1920,3072x1728,2592x1944,1920x1080,1440x1080,1280x720,1232x1008,800x480,720x480,640x480"); + p.set(CameraParameters::KEY_SUPPORTED_VIDEO_SIZES, + "1920x1080,1280x720,640x480,176x144"); + } else { + //M5MO + p.set(CameraParameters::KEY_SUPPORTED_PREVIEW_SIZES, + "3264x2448,1920x1080,1280x720,800x480,720x480,640x480,320x240,528x432,176x144"); + p.set(CameraParameters::KEY_SUPPORTED_PICTURE_SIZES, + "3264x2448,3264x1968,2048x1536,2048x1232,800x480,640x480"); + } + } else { + if (mUseInternalISP) { + //6A3 + p.set(CameraParameters::KEY_SUPPORTED_PREVIEW_SIZES, + "640x480,640x360,480x480,352x288,320x240,176x144"); + p.set(CameraParameters::KEY_SUPPORTED_PICTURE_SIZES, + "1392x1392,1280x960,1280x720,880x720,640x480"); + p.set(CameraParameters::KEY_SUPPORTED_VIDEO_SIZES, + "1280x720,640x480,176x144"); + } + } + + p.getSupportedPreviewSizes(mSupportedPreviewSizes); + + String8 parameterString; + + // If these fail, then we are using an invalid cameraId and we'll leave the + // sizes at zero to catch the error. + if (mSecCamera->getPreviewMaxSize(&preview_max_width, + &preview_max_height) < 0) + LOGE("getPreviewMaxSize fail (%d / %d)", + preview_max_width, preview_max_height); + if (mSecCamera->getSnapshotMaxSize(&snapshot_max_width, + &snapshot_max_height) < 0) + LOGE("getSnapshotMaxSize fail (%d / %d)", + snapshot_max_width, snapshot_max_height); + + parameterString = CameraParameters::PIXEL_FORMAT_YUV420P; + parameterString.append(","); + parameterString.append(CameraParameters::PIXEL_FORMAT_YUV420SP); + p.set(CameraParameters::KEY_SUPPORTED_PREVIEW_FORMATS, parameterString); + p.setPreviewFormat(CameraParameters::PIXEL_FORMAT_YUV420P); + mFrameSizeDelta = 16; + p.set(CameraParameters::KEY_VIDEO_FRAME_FORMAT, CameraParameters::PIXEL_FORMAT_YUV420SP); + p.setPreviewSize(preview_max_width, preview_max_height); + + p.setPictureFormat(CameraParameters::PIXEL_FORMAT_JPEG); + p.setPictureSize(snapshot_max_width, snapshot_max_height); + p.set(CameraParameters::KEY_JPEG_QUALITY, "100"); // maximum quality + p.set(CameraParameters::KEY_SUPPORTED_PICTURE_FORMATS, + CameraParameters::PIXEL_FORMAT_JPEG); + + p.set(CameraParameters::KEY_PREFERRED_PREVIEW_SIZE_FOR_VIDEO, "1280x720"); + +#ifdef USE_FACE_DETECTION + if (mUseInternalISP) { + p.set(CameraParameters::KEY_MAX_NUM_DETECTED_FACES_HW, "5"); + } else { + p.set(CameraParameters::KEY_MAX_NUM_DETECTED_FACES_HW, "0"); + } +#endif + + if (cameraId == SecCamera::CAMERA_ID_BACK) { + parameterString = CameraParameters::FOCUS_MODE_AUTO; + /* TODO : sensor will be support this mode */ + //parameterString.append(","); + //parameterString.append(CameraParameters::FOCUS_MODE_CONTINUOUS_VIDEO); + if (mUseInternalISP) { + parameterString.append(","); + parameterString.append(CameraParameters::FOCUS_MODE_INFINITY); + parameterString.append(","); + parameterString.append(CameraParameters::FOCUS_MODE_MACRO); + parameterString.append(","); + parameterString.append(CameraParameters::FOCUS_MODE_CONTINUOUS_PICTURE); + } + p.set(CameraParameters::KEY_SUPPORTED_FOCUS_MODES, + parameterString.string()); + p.set(CameraParameters::KEY_FOCUS_MODE, + CameraParameters::FOCUS_MODE_AUTO); + p.set(CameraParameters::KEY_FOCUS_DISTANCES, + BACK_CAMERA_AUTO_FOCUS_DISTANCES_STR); +#ifdef USE_TOUCH_AF + if (mUseInternalISP) + p.set(CameraParameters::KEY_MAX_NUM_FOCUS_AREAS, "1"); +#endif + p.set(CameraParameters::KEY_SUPPORTED_JPEG_THUMBNAIL_SIZES, + "320x240,0x0"); + p.set(CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH, "320"); + p.set(CameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT, "240"); + p.set(CameraParameters::KEY_SUPPORTED_PREVIEW_FRAME_RATES, "7,15,30"); + p.setPreviewFrameRate(30); + } else { + p.set(CameraParameters::KEY_FOCUS_MODE, NULL); + p.set(CameraParameters::KEY_SUPPORTED_JPEG_THUMBNAIL_SIZES, + "160x120,0x0"); + p.set(CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH, "160"); + p.set(CameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT, "120"); + p.set(CameraParameters::KEY_SUPPORTED_PREVIEW_FRAME_RATES, + "7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,50,60"); + p.setPreviewFrameRate(30); + } + + parameterString = CameraParameters::EFFECT_NONE; + parameterString.append(","); + parameterString.append(CameraParameters::EFFECT_MONO); + parameterString.append(","); + parameterString.append(CameraParameters::EFFECT_NEGATIVE); + parameterString.append(","); + parameterString.append(CameraParameters::EFFECT_SEPIA); + p.set(CameraParameters::KEY_SUPPORTED_EFFECTS, parameterString.string()); + + if (cameraId == SecCamera::CAMERA_ID_BACK) { + parameterString = CameraParameters::FLASH_MODE_ON; + parameterString.append(","); + parameterString.append(CameraParameters::FLASH_MODE_OFF); + parameterString.append(","); + parameterString.append(CameraParameters::FLASH_MODE_AUTO); + parameterString.append(","); + parameterString.append(CameraParameters::FLASH_MODE_TORCH); + p.set(CameraParameters::KEY_SUPPORTED_FLASH_MODES, + parameterString.string()); + p.set(CameraParameters::KEY_FLASH_MODE, + CameraParameters::FLASH_MODE_OFF); + + /* we have two ranges, 4-30fps for night mode and + * 15-30fps for all others + */ + p.set(CameraParameters::KEY_SUPPORTED_PREVIEW_FPS_RANGE, "(15000,30000)"); + p.set(CameraParameters::KEY_PREVIEW_FPS_RANGE, "15000,30000"); + + p.set(CameraParameters::KEY_FOCAL_LENGTH, "3.43"); + } else { + p.set(CameraParameters::KEY_SUPPORTED_PREVIEW_FPS_RANGE, "(7500,30000)"); + p.set(CameraParameters::KEY_PREVIEW_FPS_RANGE, "7500,30000"); + + p.set(CameraParameters::KEY_FOCAL_LENGTH, "0.9"); + } + parameterString = CameraParameters::SCENE_MODE_AUTO; + parameterString.append(","); + parameterString.append(CameraParameters::SCENE_MODE_PORTRAIT); + parameterString.append(","); + parameterString.append(CameraParameters::SCENE_MODE_LANDSCAPE); + parameterString.append(","); + parameterString.append(CameraParameters::SCENE_MODE_BEACH); + parameterString.append(","); + parameterString.append(CameraParameters::SCENE_MODE_SNOW); + parameterString.append(","); + parameterString.append(CameraParameters::SCENE_MODE_FIREWORKS); + parameterString.append(","); + parameterString.append(CameraParameters::SCENE_MODE_SPORTS); + parameterString.append(","); + parameterString.append(CameraParameters::SCENE_MODE_PARTY); + parameterString.append(","); + parameterString.append(CameraParameters::SCENE_MODE_CANDLELIGHT); + parameterString.append(","); + parameterString.append(CameraParameters::SCENE_MODE_NIGHT); + parameterString.append(","); + parameterString.append(CameraParameters::SCENE_MODE_SUNSET); + p.set(CameraParameters::KEY_SUPPORTED_SCENE_MODES, + parameterString.string()); + p.set(CameraParameters::KEY_SCENE_MODE, + CameraParameters::SCENE_MODE_AUTO); + + parameterString = CameraParameters::WHITE_BALANCE_AUTO; + parameterString.append(","); + parameterString.append(CameraParameters::WHITE_BALANCE_INCANDESCENT); + parameterString.append(","); + parameterString.append(CameraParameters::WHITE_BALANCE_FLUORESCENT); + parameterString.append(","); + parameterString.append(CameraParameters::WHITE_BALANCE_DAYLIGHT); + parameterString.append(","); + parameterString.append(CameraParameters::WHITE_BALANCE_CLOUDY_DAYLIGHT); + p.set(CameraParameters::KEY_SUPPORTED_WHITE_BALANCE, + parameterString.string()); + + p.set(CameraParameters::KEY_JPEG_THUMBNAIL_QUALITY, "100"); + + p.set(CameraParameters::KEY_ROTATION, 0); + p.set(CameraParameters::KEY_WHITE_BALANCE, CameraParameters::WHITE_BALANCE_AUTO); + + p.set(CameraParameters::KEY_EFFECT, CameraParameters::EFFECT_NONE); + + p.set("contrast", 0); + p.set("iso", "auto"); + p.set("metering", "center"); + p.set("wdr", 0); + + ip.set("chk_dataline", 0); + if (cameraId == SecCamera::CAMERA_ID_FRONT) { + ip.set("vtmode", 0); + ip.set("blur", 0); + } + + p.set(CameraParameters::KEY_HORIZONTAL_VIEW_ANGLE, "51.2"); + p.set(CameraParameters::KEY_VERTICAL_VIEW_ANGLE, "39.4"); + + p.set(CameraParameters::KEY_EXPOSURE_COMPENSATION, "0"); + p.set(CameraParameters::KEY_MAX_EXPOSURE_COMPENSATION, "4"); + p.set(CameraParameters::KEY_MIN_EXPOSURE_COMPENSATION, "-4"); + p.set(CameraParameters::KEY_EXPOSURE_COMPENSATION_STEP, "1"); + + p.set("brightness", 0); + p.set("brightness-max", 2); + p.set("brightness-min", -2); + + p.set("saturation", 0); + p.set("saturation-max", 2); + p.set("saturation-min", -2); + + p.set("sharpness", 0); + p.set("sharpness-max", 2); + p.set("sharpness-min", -2); + + p.set("hue", 0); + p.set("hue-max", 2); + p.set("hue-min", -2); + + parameterString = CameraParameters::ANTIBANDING_AUTO; + parameterString.append(","); + parameterString.append(CameraParameters::ANTIBANDING_50HZ); + parameterString.append(","); + parameterString.append(CameraParameters::ANTIBANDING_60HZ); + parameterString.append(","); + parameterString.append(CameraParameters::ANTIBANDING_OFF); + p.set(CameraParameters::KEY_SUPPORTED_ANTIBANDING, + parameterString.string()); + + p.set(CameraParameters::KEY_ANTIBANDING, CameraParameters::ANTIBANDING_OFF); + + if (mUseInternalISP) { + p.set(CameraParameters::KEY_AUTO_EXPOSURE_LOCK_SUPPORTED, "true"); + p.set(CameraParameters::KEY_AUTO_EXPOSURE_LOCK, "false"); + } + + if (mUseInternalISP) { + p.set(CameraParameters::KEY_AUTO_WHITEBALANCE_LOCK_SUPPORTED, "true"); + p.set(CameraParameters::KEY_AUTO_WHITEBALANCE_LOCK, "false"); + } + + p.set(CameraParameters::KEY_RECORDING_HINT, "false"); + +#ifdef VIDEO_SNAPSHOT + if (mUseInternalISP) + p.set(CameraParameters::KEY_VIDEO_SNAPSHOT_SUPPORTED, "true"); +#endif + + if (!mUseInternalISP) { + p.set(CameraParameters::KEY_ZOOM_SUPPORTED, "true"); + p.set(CameraParameters::KEY_MAX_ZOOM, ZOOM_LEVEL_MAX - 1); + p.set(CameraParameters::KEY_ZOOM_RATIOS, "31,4.0"); + } + + mPreviewRunning = false; + mParameters = p; + mInternalParameters = ip; + + /* make sure mSecCamera has all the settings we do. applications + * aren't required to call setParameters themselves (only if they + * want to change something. + */ + setParameters(p); +} + +CameraHardwareSec::~CameraHardwareSec() +{ + LOGV("%s", __func__); + mSecCamera->DestroyCamera(); +} + +status_t CameraHardwareSec::setPreviewWindow(preview_stream_ops *w) +{ + int min_bufs; + + mPreviewWindow = w; + LOGV("%s: mPreviewWindow %p", __func__, mPreviewWindow); + + if (!w) { + LOGE("preview window is NULL!"); + return OK; + } + + mPreviewLock.lock(); + + if (mPreviewRunning && !mPreviewStartDeferred) { + LOGI("stop preview (window change)"); + stopPreviewInternal(); + } + + if (w->get_min_undequeued_buffer_count(w, &min_bufs)) { + LOGE("%s: could not retrieve min undequeued buffer count", __func__); + return INVALID_OPERATION; + } + + if (min_bufs >= BUFFER_COUNT_FOR_GRALLOC) { + LOGE("%s: min undequeued buffer count %d is too high (expecting at most %d)", __func__, + min_bufs, BUFFER_COUNT_FOR_GRALLOC - 1); + } + + LOGV("%s: setting buffer count to %d", __func__, BUFFER_COUNT_FOR_GRALLOC); + if (w->set_buffer_count(w, BUFFER_COUNT_FOR_GRALLOC)) { + LOGE("%s: could not set buffer count", __func__); + return INVALID_OPERATION; + } + + int preview_width; + int preview_height; + mParameters.getPreviewSize(&preview_width, &preview_height); + + int hal_pixel_format; + + const char *str_preview_format = mParameters.getPreviewFormat(); + LOGV("%s: preview format %s", __func__, str_preview_format); + mFrameSizeDelta = 16; + + hal_pixel_format = HAL_PIXEL_FORMAT_YV12; // default + + if (!strcmp(str_preview_format, + CameraParameters::PIXEL_FORMAT_RGB565)) { + hal_pixel_format = HAL_PIXEL_FORMAT_RGB_565; + mFrameSizeDelta = 0; + } else if (!strcmp(str_preview_format, + CameraParameters::PIXEL_FORMAT_RGBA8888)) { + hal_pixel_format = HAL_PIXEL_FORMAT_RGBA_8888; + mFrameSizeDelta = 0; + } else if (!strcmp(str_preview_format, + CameraParameters::PIXEL_FORMAT_YUV420SP)) { + hal_pixel_format = HAL_PIXEL_FORMAT_YCrCb_420_SP; + } else if (!strcmp(str_preview_format, + CameraParameters::PIXEL_FORMAT_YUV420P)) + hal_pixel_format = HAL_PIXEL_FORMAT_YV12; // HACK + +#ifdef USE_EGL +#ifdef BOARD_USE_V4L2_ION + if (w->set_usage(w, GRALLOC_USAGE_SW_WRITE_OFTEN | GRALLOC_USAGE_HW_ION)) { +#else + if (w->set_usage(w, GRALLOC_USAGE_SW_WRITE_OFTEN)) { +#endif + LOGE("%s: could not set usage on gralloc buffer", __func__); + return INVALID_OPERATION; + } +#else +#ifdef BOARD_USE_V4L2_ION + if (w->set_usage(w, GRALLOC_USAGE_SW_WRITE_OFTEN + | GRALLOC_USAGE_HWC_HWOVERLAY | GRALLOC_USAGE_HW_ION)) { +#else + if (w->set_usage(w, GRALLOC_USAGE_SW_WRITE_OFTEN + | GRALLOC_USAGE_HW_FIMC1 | GRALLOC_USAGE_HWC_HWOVERLAY)) { +#endif + LOGE("%s: could not set usage on gralloc buffer", __func__); + return INVALID_OPERATION; + } +#endif + + if (w->set_buffers_geometry(w, + preview_width, preview_height, + hal_pixel_format)) { + LOGE("%s: could not set buffers geometry to %s", + __func__, str_preview_format); + return INVALID_OPERATION; + } + +#ifdef BOARD_USE_V4L2_ION + for(int i = 0; i < BUFFER_COUNT_FOR_ARRAY; i++) + if (0 != mPreviewWindow->dequeue_buffer(mPreviewWindow, &mBufferHandle[i], &mStride[i])) { + LOGE("%s: Could not dequeue gralloc buffer[%d]!!", __func__, i); + return INVALID_OPERATION; + } +#endif + + if (mPreviewRunning && mPreviewStartDeferred) { + LOGV("start/resume preview"); + status_t ret = startPreviewInternal(); + if (ret == OK) { + mPreviewStartDeferred = false; + mPreviewCondition.signal(); + } + } + mPreviewLock.unlock(); + + return OK; +} + +void CameraHardwareSec::setCallbacks(camera_notify_callback notify_cb, + camera_data_callback data_cb, + camera_data_timestamp_callback data_cb_timestamp, + camera_request_memory get_memory, + void *user) +{ + mNotifyCb = notify_cb; + mDataCb = data_cb; + mDataCbTimestamp = data_cb_timestamp; + mGetMemoryCb = get_memory; + mCallbackCookie = user; +} + +void CameraHardwareSec::enableMsgType(int32_t msgType) +{ + LOGV("%s : msgType = 0x%x, mMsgEnabled before = 0x%x", + __func__, msgType, mMsgEnabled); + mMsgEnabled |= msgType; + + mPreviewLock.lock(); + if ((msgType & (CAMERA_MSG_PREVIEW_FRAME | CAMERA_MSG_VIDEO_FRAME)) && + mPreviewRunning && mPreviewStartDeferred) { + LOGV("%s: starting deferred preview", __func__); + if (startPreviewInternal() == OK) { + mPreviewStartDeferred = false; + mPreviewCondition.signal(); + } + } + mPreviewLock.unlock(); + + LOGV("%s : mMsgEnabled = 0x%x", __func__, mMsgEnabled); +} + +void CameraHardwareSec::disableMsgType(int32_t msgType) +{ + LOGV("%s : msgType = 0x%x, mMsgEnabled before = 0x%x", + __func__, msgType, mMsgEnabled); + mMsgEnabled &= ~msgType; + LOGV("%s : mMsgEnabled = 0x%x", __func__, mMsgEnabled); +} + +bool CameraHardwareSec::msgTypeEnabled(int32_t msgType) +{ + return (mMsgEnabled & msgType); +} + +void CameraHardwareSec::setSkipFrame(int frame) +{ + Mutex::Autolock lock(mSkipFrameLock); + if (frame < mSkipFrame) + return; + + mSkipFrame = frame; +} + +int CameraHardwareSec::previewThreadWrapper() +{ + LOGI("%s: starting", __func__); + while (1) { + mPreviewLock.lock(); + while (!mPreviewRunning) { + LOGI("%s: calling mSecCamera->stopPreview() and waiting", __func__); + mSecCamera->stopPreview(); + /* signal that we're stopping */ + mPreviewStoppedCondition.signal(); + mPreviewCondition.wait(mPreviewLock); + LOGI("%s: return from wait", __func__); + } + mPreviewLock.unlock(); + + if (mExitPreviewThread) { + LOGI("%s: exiting", __func__); + mSecCamera->stopPreview(); + return 0; + } + + previewThread(); + } +} + +int CameraHardwareSec::previewThread() +{ + int index; + nsecs_t timestamp; + SecBuffer previewAddr, recordAddr; + static int numArray = 0; + void *virAddr[3]; + camera_frame_metadata_t fdmeta; + camera_face_t caface[5]; + +#ifdef BOARD_USE_V4L2_ION + private_handle_t *hnd = NULL; +#else + struct addrs *addrs; +#endif + + fdmeta.faces = caface; + index = mSecCamera->getPreview(&fdmeta); + + mFaceData = &fdmeta; + + if (index < 0) { + LOGE("ERR(%s):Fail on SecCamera->getPreview()", __func__); +#ifdef BOARD_USE_V4L2_ION + if (mSecCamera->getPreviewState()) { + stopPreview(); + startPreview(); + mSecCamera->clearPreviewState(); + } +#endif + return UNKNOWN_ERROR; + } + +#ifdef ZERO_SHUTTER_LAG + if (mUseInternalISP && !mRecordHint) { + mCapIndex = mSecCamera->getSnapshot(); + + if (mCapIndex >= 0) { + if (mSecCamera->setSnapshotFrame(mCapIndex) < 0) { + LOGE("%s: Fail qbuf, index(%d)", __func__, mCapIndex); + return INVALID_OPERATION; + } + } + } +#endif + + mSkipFrameLock.lock(); + if (mSkipFrame > 0) { + mSkipFrame--; + mSkipFrameLock.unlock(); + LOGV("%s: index %d skipping frame", __func__, index); + if (mSecCamera->setPreviewFrame(index) < 0) { + LOGE("%s: Could not qbuff[%d]!!", __func__, index); + return UNKNOWN_ERROR; + } + return NO_ERROR; + } + mSkipFrameLock.unlock(); + + timestamp = systemTime(SYSTEM_TIME_MONOTONIC); + + int width, height, frame_size, offset; + + mSecCamera->getPreviewSize(&width, &height, &frame_size); + + offset = frame_size * index; + + if (mPreviewWindow && mGrallocHal && mPreviewRunning) { +#ifdef BOARD_USE_V4L2_ION + hnd = (private_handle_t*)*mBufferHandle[index]; + + if (mPreviewHeap) { + mPreviewHeap->release(mPreviewHeap); + mPreviewHeap = 0; + } + + mPreviewHeap = mGetMemoryCb(hnd->fd, frame_size, 1, 0); + + hnd = NULL; + + mGrallocHal->unlock(mGrallocHal, *mBufferHandle[index]); + if (0 != mPreviewWindow->enqueue_buffer(mPreviewWindow, mBufferHandle[index])) { + LOGE("%s: Could not enqueue gralloc buffer[%d]!!", __func__, index); + goto callbacks; + } else { + mBufferHandle[index] = NULL; + mStride[index] = NULL; + } + + numArray = index; +#endif + + if (0 != mPreviewWindow->dequeue_buffer(mPreviewWindow, &mBufferHandle[numArray], &mStride[numArray])) { + LOGE("%s: Could not dequeue gralloc buffer[%d]!!", __func__, numArray); + goto callbacks; + } + + if (!mGrallocHal->lock(mGrallocHal, + *mBufferHandle[numArray], + GRALLOC_USAGE_SW_WRITE_OFTEN | GRALLOC_USAGE_YUV_ADDR, + 0, 0, width, height, virAddr)) { +#ifdef BOARD_USE_V4L2 + mSecCamera->getPreviewAddr(index, &previewAddr); + char *frame = (char *)previewAddr.virt.extP[0]; +#else + char *frame = ((char *)mPreviewHeap->data) + offset; +#endif + +#ifdef BOARD_USE_V4L2_ION + mSecCamera->setUserBufferAddr(virAddr, index, PREVIEW_MODE); +#else + int total = frame_size + mFrameSizeDelta; + int h = 0; + char *src = frame; + + /* TODO : Need to fix size of planes for supported color fmt. + Currnetly we support only YV12(3 plane) and NV21(2 plane)*/ + // Y + memcpy(virAddr[0],src, width * height); + src += width * height; + + if (mPreviewFmtPlane == PREVIEW_FMT_2_PLANE) { + memcpy(virAddr[1], src, width * height / 2); + } else if (mPreviewFmtPlane == PREVIEW_FMT_3_PLANE) { + // U + memcpy(virAddr[1], src, width * height / 4); + src += width * height / 4; + + // V + memcpy(virAddr[2], src, width * height / 4); + } + + mGrallocHal->unlock(mGrallocHal, **mBufferHandle); +#endif + } + else + LOGE("%s: could not obtain gralloc buffer", __func__); + + if (mSecCamera->setPreviewFrame(index) < 0) { + LOGE("%s: Fail qbuf, index(%d)", __func__, index); + goto callbacks; + } + + index = 0; +#ifndef BOARD_USE_V4L2_ION + if (0 != mPreviewWindow->enqueue_buffer(mPreviewWindow, *mBufferHandle)) { + LOGE("Could not enqueue gralloc buffer!"); + goto callbacks; + } +#endif + } + +callbacks: + // Notify the client of a new frame. + if (mMsgEnabled & CAMERA_MSG_PREVIEW_FRAME && mPreviewRunning) + mDataCb(CAMERA_MSG_PREVIEW_FRAME, mPreviewHeap, index, NULL, mCallbackCookie); + +#ifdef USE_FACE_DETECTION + if (mUseInternalISP && (mMsgEnabled & CAMERA_MSG_PREVIEW_METADATA) && mPreviewRunning) + mDataCb(CAMERA_MSG_PREVIEW_METADATA, mFaceDataHeap, 0, mFaceData, mCallbackCookie); +#endif + + Mutex::Autolock lock(mRecordLock); + if (mRecordRunning == true) { + int recordingIndex = 0; + + index = mSecCamera->getRecordFrame(); + if (index < 0) { + LOGE("ERR(%s):Fail on SecCamera->getRecordFrame()", __func__); + return UNKNOWN_ERROR; + } + +#ifdef VIDEO_SNAPSHOT + if (mUseInternalISP && mRecordHint) { + mCapIndex = mSecCamera->getSnapshot(); + + if (mSecCamera->setSnapshotFrame(mCapIndex) < 0) { + LOGE("%s: Fail qbuf, index(%d)", __func__, mCapIndex); + return INVALID_OPERATION; + } + } +#endif + +#ifdef BOARD_USE_V4L2_ION + numArray = index; +#else + recordingIndex = index; + mSecCamera->getRecordAddr(index, &recordAddr); + + LOGV("record PhyY(0x%08x) phyC(0x%08x) ", recordAddr.phys.extP[0], recordAddr.phys.extP[1]); + + if (recordAddr.phys.extP[0] == 0xffffffff || recordAddr.phys.extP[1] == 0xffffffff) { + LOGE("ERR(%s):Fail on SecCamera getRectPhyAddr Y addr = %0x C addr = %0x", __func__, + recordAddr.phys.extP[0], recordAddr.phys.extP[1]); + return UNKNOWN_ERROR; + } + + addrs = (struct addrs *)(*mRecordHeap)->data; + + addrs[index].type = kMetadataBufferTypeCameraSource; + addrs[index].addr_y = recordAddr.phys.extP[0]; + addrs[index].addr_cbcr = recordAddr.phys.extP[1]; + addrs[index].buf_index = index; +#endif + + // Notify the client of a new frame. + if (mMsgEnabled & CAMERA_MSG_VIDEO_FRAME) + mDataCbTimestamp(timestamp, CAMERA_MSG_VIDEO_FRAME, + mRecordHeap[numArray], recordingIndex, mCallbackCookie); + else + mSecCamera->releaseRecordFrame(index); + } + + return NO_ERROR; +} + +status_t CameraHardwareSec::startPreview() +{ + int ret = 0; + + LOGV("%s :", __func__); + + Mutex::Autolock lock(mStateLock); + if (mCaptureInProgress) { + LOGE("%s : capture in progress, not allowed", __func__); + return INVALID_OPERATION; + } + + mPreviewLock.lock(); + if (mPreviewRunning) { + // already running + LOGE("%s : preview thread already running", __func__); + mPreviewLock.unlock(); + return INVALID_OPERATION; + } + + mPreviewRunning = true; + mPreviewStartDeferred = false; + + if (!mPreviewWindow && + !(mMsgEnabled & CAMERA_MSG_PREVIEW_FRAME) && + !(mMsgEnabled & CAMERA_MSG_VIDEO_FRAME)) { + LOGI("%s : deferring", __func__); + mPreviewStartDeferred = true; + mPreviewLock.unlock(); + return NO_ERROR; + } + + ret = startPreviewInternal(); + if (ret == OK) + mPreviewCondition.signal(); + + mPreviewLock.unlock(); + return ret; +} + +status_t CameraHardwareSec::startPreviewInternal() +{ + LOGV("%s", __func__); + int width, height, frame_size; + + mSecCamera->getPreviewSize(&width, &height, &frame_size); + LOGD("mPreviewHeap(fd(%d), size(%d), width(%d), height(%d))", + mSecCamera->getCameraFd(SecCamera::PREVIEW), frame_size + mFrameSizeDelta, width, height); + +#ifdef BOARD_USE_V4L2_ION +#ifdef ZERO_SHUTTER_LAG +/*TODO*/ + int mPostViewWidth, mPostViewHeight, mPostViewSize; + mSecCamera->getPostViewConfig(&mPostViewWidth, &mPostViewHeight, &mPostViewSize); + for(int i = 0; i < CAP_BUFFERS; i++) { + mPostviewHeap[i] = new MemoryHeapBaseIon(mPostViewSize); + mSecCamera->setUserBufferAddr(mPostviewHeap[i]->base(), i, CAPTURE_MODE); + } +#endif + void *vaddr[3]; + + for (int i = 0; i < MAX_BUFFERS; i++) { + if (mBufferHandle[i] == NULL) { + if (0 != mPreviewWindow->dequeue_buffer(mPreviewWindow, &mBufferHandle[i], &mStride[i])) { + LOGE("%s: Could not dequeue gralloc buffer[%d]!!", __func__, i); + return INVALID_OPERATION; + } + } + if (mGrallocHal->lock(mGrallocHal, + *mBufferHandle[i], + GRALLOC_USAGE_SW_WRITE_OFTEN | GRALLOC_USAGE_YUV_ADDR, + 0, 0, width, height, vaddr)) { + LOGE("ERR(%s): Could not get virtual address!!, index = %d", __func__, i); + return UNKNOWN_ERROR; + } + mSecCamera->setUserBufferAddr(vaddr, i, PREVIEW_MODE); + } +#endif + + int ret = mSecCamera->startPreview(); + LOGV("%s : mSecCamera->startPreview() returned %d", __func__, ret); + + if (ret < 0) { + LOGE("ERR(%s):Fail on mSecCamera->startPreview()", __func__); + return UNKNOWN_ERROR; + } + + setSkipFrame(INITIAL_SKIP_FRAME); + + if (mPreviewHeap) { + mPreviewHeap->release(mPreviewHeap); + mPreviewHeap = 0; + } + + for(int i=0; irelease(mRecordHeap[i]); + mRecordHeap[i] = 0; + } + } + +#ifndef BOARD_USE_V4L2 + mPreviewHeap = mGetMemoryCb((int)mSecCamera->getCameraFd(SecCamera::PREVIEW), + frame_size + mFrameSizeDelta, + MAX_BUFFERS, + 0); // no cookie +#endif + + mFaceDataHeap = mGetMemoryCb(-1, 1, 1, 0); + + mSecCamera->getPostViewConfig(&mPostViewWidth, &mPostViewHeight, &mPostViewSize); + LOGV("CameraHardwareSec: mPostViewWidth = %d mPostViewHeight = %d mPostViewSize = %d", + mPostViewWidth,mPostViewHeight,mPostViewSize); + + return NO_ERROR; +} + +void CameraHardwareSec::stopPreviewInternal() +{ + LOGV("%s :", __func__); + + /* request that the preview thread stop. */ + if (mPreviewRunning) { + mPreviewRunning = false; + if (!mPreviewStartDeferred) { + mPreviewCondition.signal(); + /* wait until preview thread is stopped */ + mPreviewStoppedCondition.wait(mPreviewLock); + +#ifdef BOARD_USE_V4L2_ION + for (int i = 0; i < MAX_BUFFERS; i++) { + if (mBufferHandle[i] != NULL) { + if (0 != mPreviewWindow->cancel_buffer(mPreviewWindow, mBufferHandle[i])) { + LOGE("%s: Fail to cancel buffer[%d]", __func__, i); + } else { + mBufferHandle[i] = NULL; + mStride[i] = NULL; + } + } + } +#endif + } + else + LOGV("%s : preview running but deferred, doing nothing", __func__); + } else + LOGI("%s : preview not running, doing nothing", __func__); +} + +void CameraHardwareSec::stopPreview() +{ + LOGV("%s :", __func__); + + /* request that the preview thread stop. */ + mPreviewLock.lock(); + stopPreviewInternal(); + mPreviewLock.unlock(); +} + +bool CameraHardwareSec::previewEnabled() +{ + Mutex::Autolock lock(mPreviewLock); + LOGV("%s : %d", __func__, mPreviewRunning); + return mPreviewRunning; +} + +status_t CameraHardwareSec::startRecording() +{ + LOGV("%s :", __func__); + + Mutex::Autolock lock(mRecordLock); + + for(int i = 0; irelease(mRecordHeap[i]); + mRecordHeap[i] = 0; + } + +#ifdef BOARD_USE_V4L2_ION + int width, height; + + mSecCamera->getRecordingSize(&width, &height); + + mRecordHeap[i] = mGetMemoryCb(-1, (ALIGN((ALIGN(width, 16) * ALIGN(height, 16)), 2048) + ALIGN((ALIGN(width, 16) * ALIGN(height >> 1, 8)), 2048)), 1, NULL); + + mSecCamera->setUserBufferAddr((void *)(mRecordHeap[i]->data), i, RECORD_MODE); +#else + mRecordHeap[i] = mGetMemoryCb(-1, sizeof(struct addrs), MAX_BUFFERS, NULL); +#endif + if (!mRecordHeap[i]) { + LOGE("ERR(%s): Record heap[%d] creation fail", __func__, i); + return UNKNOWN_ERROR; + } + } + + LOGV("mRecordHeaps alloc done"); + + if (mRecordRunning == false) { + if (mSecCamera->startRecord(mRecordHint) < 0) { + LOGE("ERR(%s):Fail on mSecCamera->startRecord()", __func__); + return UNKNOWN_ERROR; + } + mRecordRunning = true; + } + return NO_ERROR; +} + +void CameraHardwareSec::stopRecording() +{ + LOGV("%s :", __func__); + + Mutex::Autolock lock(mRecordLock); + + if (mRecordRunning == true) { + if (mSecCamera->stopRecord() < 0) { + LOGE("ERR(%s):Fail on mSecCamera->stopRecord()", __func__); + return; + } + mRecordRunning = false; + } +} + +bool CameraHardwareSec::recordingEnabled() +{ + LOGV("%s :", __func__); + LOGV("%s : %d", __func__, mPreviewRunning); + + return mRecordRunning; +} + +void CameraHardwareSec::releaseRecordingFrame(const void *opaque) +{ +#ifdef BOARD_USE_V4L2_ION + int i; + for (i = 0; i < MAX_BUFFERS; i++) + if ((char *)mRecordHeap[i]->data == (char *)opaque) + break; + + mSecCamera->releaseRecordFrame(i); +#else + struct addrs *addrs = (struct addrs *)opaque; + mSecCamera->releaseRecordFrame(addrs->buf_index); +#endif +} + +int CameraHardwareSec::autoFocusThread() +{ + int count =0; + int af_status =0 ; + + LOGV("%s : starting", __func__); + + /* block until we're told to start. we don't want to use + * a restartable thread and requestExitAndWait() in cancelAutoFocus() + * because it would cause deadlock between our callbacks and the + * caller of cancelAutoFocus() which both want to grab the same lock + * in CameraServices layer. + */ + mFocusLock.lock(); + /* check early exit request */ + if (mExitAutoFocusThread) { + mFocusLock.unlock(); + LOGV("%s : exiting on request0", __func__); + return NO_ERROR; + } + mFocusCondition.wait(mFocusLock); + /* check early exit request */ + if (mExitAutoFocusThread) { + mFocusLock.unlock(); + LOGV("%s : exiting on request1", __func__); + return NO_ERROR; + } + mFocusLock.unlock(); + + /* TODO : Currently only possible auto focus at BACK caemra + We need to modify to check that sensor can support auto focus */ + if (mCameraID == SecCamera::CAMERA_ID_BACK) { + LOGV("%s : calling setAutoFocus", __func__); + if (mTouched == 0) { + if (mSecCamera->setAutofocus() < 0) { + LOGE("ERR(%s):Fail on mSecCamera->setAutofocus()", __func__); + return UNKNOWN_ERROR; + } + } else { + if (mSecCamera->setTouchAF() < 0) { + LOGE("ERR(%s):Fail on mSecCamera->setAutofocus()", __func__); + return UNKNOWN_ERROR; + } + } + } + + /* TODO */ + /* This is temperary implementation. + When camera support AF blocking mode, this code will be removed + Continous AutoFocus is not need to success */ + const char *focusModeStr = mParameters.get(CameraParameters::KEY_FOCUS_MODE); + int isContinousAF = !strncmp(focusModeStr, CameraParameters::FOCUS_MODE_CONTINUOUS_VIDEO, 7); + if (mUseInternalISP && !isContinousAF) { + int i, err = -1; + for (i = 0; i < 400; i++) { + usleep(10000); + + af_status = mSecCamera->getAutoFocusResult(); + + if ((af_status & 0x2)) { + err = 0; + break; + } + } + } else { + af_status = mSecCamera->getAutoFocusResult(); + } + + if (af_status == 0x01) { + LOGV("%s : AF Cancelled !!", __func__); + if (mMsgEnabled & CAMERA_MSG_FOCUS) + mNotifyCb(CAMERA_MSG_FOCUS, true, 0, mCallbackCookie); + } else if (af_status == 0x02) { + LOGV("%s : AF Success !!", __func__); + if (mMsgEnabled & CAMERA_MSG_FOCUS) { + /* CAMERA_MSG_FOCUS only takes a bool. true for + * finished and false for failure. cancel is still + * considered a true result. + */ + mNotifyCb(CAMERA_MSG_FOCUS, true, 0, mCallbackCookie); + } + } else { + LOGV("%s : AF Fail !!", __func__); + LOGV("%s : mMsgEnabled = 0x%x", __func__, mMsgEnabled); + if (mMsgEnabled & CAMERA_MSG_FOCUS) + mNotifyCb(CAMERA_MSG_FOCUS, false, 0, mCallbackCookie); + } + + LOGV("%s : exiting with no error", __func__); + return NO_ERROR; +} + +status_t CameraHardwareSec::autoFocus() +{ + LOGV("%s :", __func__); + /* signal autoFocusThread to run once */ + mFocusCondition.signal(); + return NO_ERROR; +} + +status_t CameraHardwareSec::cancelAutoFocus() +{ + LOGV("%s :", __func__); + + if (mSecCamera->cancelAutofocus() < 0) { + LOGE("ERR(%s):Fail on mSecCamera->cancelAutofocus()", __func__); + return UNKNOWN_ERROR; + } + + return NO_ERROR; +} + +int CameraHardwareSec::save_jpeg( unsigned char *real_jpeg, int jpeg_size) +{ + FILE *yuv_fp = NULL; + char filename[100], *buffer = NULL; + + /* file create/open, note to "wb" */ + yuv_fp = fopen("/data/camera_dump.jpeg", "wb"); + if (yuv_fp == NULL) { + LOGE("Save jpeg file open error"); + return -1; + } + + LOGV("[BestIQ] real_jpeg size ========> %d", jpeg_size); + buffer = (char *) malloc(jpeg_size); + if (buffer == NULL) { + LOGE("Save YUV] buffer alloc failed"); + if (yuv_fp) + fclose(yuv_fp); + + return -1; + } + + memcpy(buffer, real_jpeg, jpeg_size); + + fflush(stdout); + + fwrite(buffer, 1, jpeg_size, yuv_fp); + + fflush(yuv_fp); + + if (yuv_fp) + fclose(yuv_fp); + if (buffer) + free(buffer); + + return 0; +} + +void CameraHardwareSec::save_postview(const char *fname, uint8_t *buf, uint32_t size) +{ + int nw; + int cnt = 0; + uint32_t written = 0; + + LOGD("opening file [%s]", fname); + int fd = open(fname, O_RDWR | O_CREAT); + if (fd < 0) { + LOGE("failed to create file [%s]: %s", fname, strerror(errno)); + return; + } + + LOGD("writing %d bytes to file [%s]", size, fname); + while (written < size) { + nw = ::write(fd, buf + written, size - written); + if (nw < 0) { + LOGE("failed to write to file %d [%s]: %s",written,fname, strerror(errno)); + break; + } + written += nw; + cnt++; + } + LOGD("done writing %d bytes to file [%s] in %d passes",size, fname, cnt); + ::close(fd); +} + +bool CameraHardwareSec::scaleDownYuv422(char *srcBuf, uint32_t srcWidth, uint32_t srcHeight, + char *dstBuf, uint32_t dstWidth, uint32_t dstHeight) +{ + int32_t step_x, step_y; + int32_t iXsrc, iXdst; + int32_t x, y, src_y_start_pos, dst_pos, src_pos; + + if (dstWidth % 2 != 0 || dstHeight % 2 != 0) { + LOGE("scale_down_yuv422: invalid width, height for scaling"); + return false; + } + + step_x = srcWidth / dstWidth; + step_y = srcHeight / dstHeight; + + dst_pos = 0; + for (uint32_t y = 0; y < dstHeight; y++) { + src_y_start_pos = (y * step_y * (srcWidth * 2)); + + for (uint32_t x = 0; x < dstWidth; x += 2) { + src_pos = src_y_start_pos + (x * (step_x * 2)); + + dstBuf[dst_pos++] = srcBuf[src_pos ]; + dstBuf[dst_pos++] = srcBuf[src_pos + 1]; + dstBuf[dst_pos++] = srcBuf[src_pos + 2]; + dstBuf[dst_pos++] = srcBuf[src_pos + 3]; + } + } + + return true; +} + +bool CameraHardwareSec::YUY2toNV21(void *srcBuf, void *dstBuf, uint32_t srcWidth, uint32_t srcHeight) +{ + int32_t x, y, src_y_start_pos, dst_cbcr_pos, dst_pos, src_pos; + unsigned char *srcBufPointer = (unsigned char *)srcBuf; + unsigned char *dstBufPointer = (unsigned char *)dstBuf; + + dst_pos = 0; + dst_cbcr_pos = srcWidth*srcHeight; + for (uint32_t y = 0; y < srcHeight; y++) { + src_y_start_pos = (y * (srcWidth * 2)); + + for (uint32_t x = 0; x < (srcWidth * 2); x += 2) { + src_pos = src_y_start_pos + x; + + dstBufPointer[dst_pos++] = srcBufPointer[src_pos]; + } + } + for (uint32_t y = 0; y < srcHeight; y += 2) { + src_y_start_pos = (y * (srcWidth * 2)); + + for (uint32_t x = 0; x < (srcWidth * 2); x += 4) { + src_pos = src_y_start_pos + x; + + dstBufPointer[dst_cbcr_pos++] = srcBufPointer[src_pos + 3]; + dstBufPointer[dst_cbcr_pos++] = srcBufPointer[src_pos + 1]; + } + } + + return true; +} + +int CameraHardwareSec::pictureThread() +{ + LOGV("%s :", __func__); + + int jpeg_size = 0; + int ret = NO_ERROR; + unsigned char *jpeg_data = NULL; + int postview_offset = 0; + unsigned char *postview_data = NULL; + + unsigned char *addr = NULL; + int mPostViewWidth, mPostViewHeight, mPostViewSize; + int mThumbWidth, mThumbHeight, mThumbSize; + int cap_width, cap_height, cap_frame_size; + + int JpegImageSize = 0; + + mSecCamera->getPostViewConfig(&mPostViewWidth, &mPostViewHeight, &mPostViewSize); + mSecCamera->getThumbnailConfig(&mThumbWidth, &mThumbHeight, &mThumbSize); + int postviewHeapSize = mPostViewSize; + if (!mRecordRunning) + mSecCamera->getSnapshotSize(&cap_width, &cap_height, &cap_frame_size); + else + mSecCamera->getVideosnapshotSize(&cap_width, &cap_height, &cap_frame_size); + int mJpegHeapSize; + if (!mUseInternalISP) + mJpegHeapSize = cap_frame_size * SecCamera::getJpegRatio(); + else + mJpegHeapSize = cap_frame_size; + + LOGV("[5B] mPostViewWidth = %d mPostViewHeight = %d\n",mPostViewWidth,mPostViewHeight); + + camera_memory_t *JpegHeap = mGetMemoryCb(-1, mJpegHeapSize, 1, 0); +#ifdef BOARD_USE_V4L2_ION +#ifdef ZERO_SHUTTER_LAG + mThumbnailHeap = new MemoryHeapBaseIon(mThumbSize); +#else + mPostviewHeap[mCapIndex] = new MemoryHeapBaseIon(mPostViewSize); + mThumbnailHeap = new MemoryHeapBaseIon(mThumbSize); +#endif +#else + mThumbnailHeap = new MemoryHeapBase(mThumbSize); +#endif + + if (mMsgEnabled & CAMERA_MSG_RAW_IMAGE) { + int picture_size, picture_width, picture_height; + mSecCamera->getSnapshotSize(&picture_width, &picture_height, &picture_size); + int picture_format = mSecCamera->getSnapshotPixelFormat(); + + unsigned int thumb_addr, phyAddr; + + // Modified the shutter sound timing for Jpeg capture + if (!mUseInternalISP) { + mSecCamera->setSnapshotCmd(); + + if (mMsgEnabled & CAMERA_MSG_SHUTTER) + mNotifyCb(CAMERA_MSG_SHUTTER, 0, 0, mCallbackCookie); + + jpeg_data = mSecCamera->getJpeg(&JpegImageSize, &mThumbSize, &thumb_addr, &phyAddr); + if (jpeg_data == NULL) { + LOGE("ERR(%s):Fail on SecCamera->getJpeg()", __func__); + ret = UNKNOWN_ERROR; + } + + memcpy((unsigned char *)mThumbnailHeap->base(), (unsigned char *)thumb_addr, mThumbSize); + memcpy(JpegHeap->data, jpeg_data, JpegImageSize); + } else { + if (mMsgEnabled & CAMERA_MSG_SHUTTER) + mNotifyCb(CAMERA_MSG_SHUTTER, 0, 0, mCallbackCookie); + +#ifdef ZERO_SHUTTER_LAG + mSecCamera->getCaptureAddr(mCapIndex, &mCapBuffer); + + if (mCapBuffer.virt.extP[0] == NULL) { + LOGE("ERR(%s):Fail on SecCamera getCaptureAddr = %0x ", + __func__, mCapBuffer.virt.extP[0]); + return UNKNOWN_ERROR; + } + + scaleDownYuv422((char *)mCapBuffer.virt.extP[0], cap_width, cap_height, + (char *)mThumbnailHeap->base(), mThumbWidth, mThumbHeight); +#else +#ifdef BOARD_USE_V4L2_ION + mCapBuffer.virt.extP[0] = (char *)mPostviewHeap[mCapIndex]->base(); +#endif +#endif + + if (mSecCamera->getSnapshotAndJpeg(&mCapBuffer, mCapIndex, + (unsigned char*)JpegHeap->data, &JpegImageSize) < 0) { + mStateLock.lock(); + mCaptureInProgress = false; + mStateLock.unlock(); + JpegHeap->release(JpegHeap); + return UNKNOWN_ERROR; + } + LOGI("snapshotandjpeg done"); + +#ifdef ZERO_SHUTTER_LAG + if (!mRecordRunning) + stopPreview(); + memset(&mCapBuffer, 0, sizeof(struct SecBuffer)); +#else + scaleDownYuv422((char *)mCapBuffer.virt.extP[0], cap_width, cap_height, + (char *)mThumbnailHeap->base(), mThumbWidth, mThumbHeight); +#endif + } + } + +#ifndef BOARD_USE_V4L2_ION + int rawHeapSize = cap_frame_size; + LOGV("mRawHeap : MemoryHeapBase(previewHeapSize(%d))", rawHeapSize); +#ifdef BOARD_USE_V4L2_ION + mRawHeap = mGetMemoryCb(mPostviewHeap[mCapIndex]->getHeapID(), rawHeapSize, 1, 0); +#else + mRawHeap = mGetMemoryCb((int)mSecCamera->getCameraFd(SecCamera::PICTURE), rawHeapSize, 1, 0); +#endif + if (!mRawHeap) + LOGE("ERR(%s): Raw heap creation fail", __func__); + + if (mMsgEnabled & CAMERA_MSG_RAW_IMAGE) + mDataCb(CAMERA_MSG_RAW_IMAGE, mRawHeap, 0, NULL, mCallbackCookie); +#endif + mStateLock.lock(); + mCaptureInProgress = false; + mStateLock.unlock(); + + if (mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE) { + camera_memory_t *ExifHeap = + mGetMemoryCb(-1, EXIF_FILE_SIZE + mThumbSize, 1, 0); + + int JpegExifSize = mSecCamera->getExif((unsigned char *)ExifHeap->data, + (unsigned char *)mThumbnailHeap->base(), + mThumbSize); + LOGV("JpegExifSize=%d", JpegExifSize); + + if (JpegExifSize < 0) { + ret = UNKNOWN_ERROR; + goto out; + } + + int mJpegHeapSize_out = JpegImageSize + JpegExifSize; + camera_memory_t *JpegHeap_out = mGetMemoryCb(-1, mJpegHeapSize_out, 1, 0); + + unsigned char *ExifStart = (unsigned char *)JpegHeap_out->data + 2; + unsigned char *ImageStart = ExifStart + JpegExifSize; + + memcpy(JpegHeap_out->data, JpegHeap->data, 2); + memcpy(ExifStart, ExifHeap->data, JpegExifSize); + memcpy(ImageStart, JpegHeap->data + 2, JpegImageSize - 2); + + mDataCb(CAMERA_MSG_COMPRESSED_IMAGE, JpegHeap_out, 0, NULL, mCallbackCookie); + + if (ExifHeap) { + ExifHeap->release(ExifHeap); + ExifHeap = 0; + } + + if (JpegHeap_out) { + JpegHeap_out->release(JpegHeap_out); + JpegHeap_out = 0; + } + } + + LOGV("%s : pictureThread end", __func__); + +out: + if (JpegHeap) { + JpegHeap->release(JpegHeap); + JpegHeap = 0; + } + + if (mRawHeap) { + mRawHeap->release(mRawHeap); + mRawHeap = 0; + } + + if (!mUseInternalISP && !mRecordRunning) + mSecCamera->endSnapshot(); + + return ret; +} + +status_t CameraHardwareSec::takePicture() +{ + LOGV("%s :", __func__); + +#ifdef ZERO_SHUTTER_LAG + if (!mUseInternalISP) { + stopPreview(); + } +#else + stopPreview(); +#endif + + Mutex::Autolock lock(mStateLock); + if (mCaptureInProgress) { + LOGE("%s : capture already in progress", __func__); + return INVALID_OPERATION; + } + + if (mPictureThread->run("CameraPictureThread", PRIORITY_DEFAULT) != NO_ERROR) { + LOGE("%s : couldn't run picture thread", __func__); + return INVALID_OPERATION; + } + mCaptureInProgress = true; + + return NO_ERROR; +} + +status_t CameraHardwareSec::cancelPicture() +{ + LOGV("%s", __func__); + + if (mPictureThread.get()) { + LOGV("%s: waiting for picture thread to exit", __func__); + mPictureThread->requestExitAndWait(); + LOGV("%s: picture thread has exited", __func__); + } + + return NO_ERROR; +} + +bool CameraHardwareSec::CheckVideoStartMarker(unsigned char *pBuf) +{ + if (!pBuf) { + LOGE("CheckVideoStartMarker() => pBuf is NULL"); + return false; + } + + if (HIBYTE(VIDEO_COMMENT_MARKER_H) == * pBuf && LOBYTE(VIDEO_COMMENT_MARKER_H) == *(pBuf + 1) && + HIBYTE(VIDEO_COMMENT_MARKER_L) == *(pBuf + 2) && LOBYTE(VIDEO_COMMENT_MARKER_L) == *(pBuf + 3)) + return true; + + return false; +} + +bool CameraHardwareSec::CheckEOIMarker(unsigned char *pBuf) +{ + if (!pBuf) { + LOGE("CheckEOIMarker() => pBuf is NULL"); + return false; + } + + // EOI marker [FF D9] + if (HIBYTE(JPEG_EOI_MARKER) == *pBuf && LOBYTE(JPEG_EOI_MARKER) == *(pBuf + 1)) + return true; + + return false; +} + +bool CameraHardwareSec::FindEOIMarkerInJPEG(unsigned char *pBuf, int dwBufSize, int *pnJPEGsize) +{ + if (NULL == pBuf || 0 >= dwBufSize) { + LOGE("FindEOIMarkerInJPEG() => There is no contents."); + return false; + } + + unsigned char *pBufEnd = pBuf + dwBufSize; + + while (pBuf < pBufEnd) { + if (CheckEOIMarker(pBuf++)) + return true; + + (*pnJPEGsize)++; + } + + return false; +} + +bool CameraHardwareSec::SplitFrame(unsigned char *pFrame, int dwSize, + int dwJPEGLineLength, int dwVideoLineLength, int dwVideoHeight, + void *pJPEG, int *pdwJPEGSize, + void *pVideo, int *pdwVideoSize) +{ + LOGV("===========SplitFrame Start=============="); + + if (NULL == pFrame || 0 >= dwSize) { + LOGE("There is no contents (pFrame=%p, dwSize=%d", pFrame, dwSize); + return false; + } + + if (0 == dwJPEGLineLength || 0 == dwVideoLineLength) { + LOGE("There in no input information for decoding interleaved jpeg"); + return false; + } + + unsigned char *pSrc = pFrame; + unsigned char *pSrcEnd = pFrame + dwSize; + + unsigned char *pJ = (unsigned char *)pJPEG; + int dwJSize = 0; + unsigned char *pV = (unsigned char *)pVideo; + int dwVSize = 0; + + bool bRet = false; + bool isFinishJpeg = false; + + while (pSrc < pSrcEnd) { + // Check video start marker + if (CheckVideoStartMarker(pSrc)) { + int copyLength; + + if (pSrc + dwVideoLineLength <= pSrcEnd) + copyLength = dwVideoLineLength; + else + copyLength = pSrcEnd - pSrc - VIDEO_COMMENT_MARKER_LENGTH; + + // Copy video data + if (pV) { + memcpy(pV, pSrc + VIDEO_COMMENT_MARKER_LENGTH, copyLength); + pV += copyLength; + dwVSize += copyLength; + } + + pSrc += copyLength + VIDEO_COMMENT_MARKER_LENGTH; + } else { + // Copy pure JPEG data + int size = 0; + int dwCopyBufLen = dwJPEGLineLength <= pSrcEnd-pSrc ? dwJPEGLineLength : pSrcEnd - pSrc; + + if (FindEOIMarkerInJPEG((unsigned char *)pSrc, dwCopyBufLen, &size)) { + isFinishJpeg = true; + size += 2; // to count EOF marker size + } else { + if ((dwCopyBufLen == 1) && (pJPEG < pJ)) { + unsigned char checkBuf[2] = { *(pJ - 1), *pSrc }; + + if (CheckEOIMarker(checkBuf)) + isFinishJpeg = true; + } + size = dwCopyBufLen; + } + + memcpy(pJ, pSrc, size); + + dwJSize += size; + + pJ += dwCopyBufLen; + pSrc += dwCopyBufLen; + } + if (isFinishJpeg) + break; + } + + if (isFinishJpeg) { + bRet = true; + if (pdwJPEGSize) + *pdwJPEGSize = dwJSize; + if (pdwVideoSize) + *pdwVideoSize = dwVSize; + } else { + LOGE("DecodeInterleaveJPEG_WithOutDT() => Can not find EOI"); + bRet = false; + if (pdwJPEGSize) + *pdwJPEGSize = 0; + if (pdwVideoSize) + *pdwVideoSize = 0; + } + LOGV("===========SplitFrame end=============="); + + return bRet; +} + +int CameraHardwareSec::decodeInterleaveData(unsigned char *pInterleaveData, + int interleaveDataSize, + int yuvWidth, + int yuvHeight, + int *pJpegSize, + void *pJpegData, + void *pYuvData) +{ + if (pInterleaveData == NULL) + return false; + + bool ret = true; + unsigned int *interleave_ptr = (unsigned int *)pInterleaveData; + unsigned char *jpeg_ptr = (unsigned char *)pJpegData; + unsigned char *yuv_ptr = (unsigned char *)pYuvData; + unsigned char *p; + int jpeg_size = 0; + int yuv_size = 0; + + int i = 0; + + LOGV("decodeInterleaveData Start~~~"); + while (i < interleaveDataSize) { + if ((*interleave_ptr == 0xFFFFFFFF) || (*interleave_ptr == 0x02FFFFFF) || + (*interleave_ptr == 0xFF02FFFF)) { + // Padding Data + interleave_ptr++; + i += 4; + } else if ((*interleave_ptr & 0xFFFF) == 0x05FF) { + // Start-code of YUV Data + p = (unsigned char *)interleave_ptr; + p += 2; + i += 2; + + // Extract YUV Data + if (pYuvData != NULL) { + memcpy(yuv_ptr, p, yuvWidth * 2); + yuv_ptr += yuvWidth * 2; + yuv_size += yuvWidth * 2; + } + p += yuvWidth * 2; + i += yuvWidth * 2; + + // Check End-code of YUV Data + if ((*p == 0xFF) && (*(p + 1) == 0x06)) { + interleave_ptr = (unsigned int *)(p + 2); + i += 2; + } else { + ret = false; + break; + } + } else { + // Extract JPEG Data + if (pJpegData != NULL) { + memcpy(jpeg_ptr, interleave_ptr, 4); + jpeg_ptr += 4; + jpeg_size += 4; + } + interleave_ptr++; + i += 4; + } + } + if (ret) { + if (pJpegData != NULL) { + // Remove Padding after EOI + for (i = 0; i < 3; i++) { + if (*(--jpeg_ptr) != 0xFF) { + break; + } + jpeg_size--; + } + *pJpegSize = jpeg_size; + + } + // Check YUV Data Size + if (pYuvData != NULL) { + if (yuv_size != (yuvWidth * yuvHeight * 2)) { + ret = false; + } + } + } + LOGV("decodeInterleaveData End~~~"); + return ret; +} + +status_t CameraHardwareSec::dump(int fd) const +{ + const size_t SIZE = 256; + char buffer[SIZE]; + String8 result; + const Vector args; + + if (mSecCamera != 0) { + mSecCamera->dump(fd); + mParameters.dump(fd, args); + mInternalParameters.dump(fd, args); + snprintf(buffer, 255, " preview running(%s)\n", mPreviewRunning?"true": "false"); + result.append(buffer); + } else + result.append("No camera client yet.\n"); + write(fd, result.string(), result.size()); + return NO_ERROR; +} + +bool CameraHardwareSec::isSupportedPreviewSize(const int width, + const int height) const +{ + unsigned int i; + + for (i = 0; i < mSupportedPreviewSizes.size(); i++) { + if (mSupportedPreviewSizes[i].width == width && + mSupportedPreviewSizes[i].height == height) + return true; + } + + return false; +} + +bool CameraHardwareSec::getVideosnapshotSize(int *width, int *height) +{ + unsigned int i; + Vector pictureSizes, videoSizes; + int ratio = FRM_RATIO(*width, *height); + + mParameters.getSupportedPictureSizes(pictureSizes); + mParameters.getSupportedVideoSizes(videoSizes); + + for (i = 0; i < pictureSizes.size(); i++) { + if (FRM_RATIO(pictureSizes[i].width, pictureSizes[i].height) == ratio) { + if (mRecordHint) { + if (pictureSizes[i].width <= videoSizes[0].width) { + *width = pictureSizes[i].width; + *height = pictureSizes[i].height; + LOGV("%s(width(%d), height(%d))", __func__, *width, *height); + return true; + } + } else { + *width = pictureSizes[i].width; + *height = pictureSizes[i].height; + LOGV("%s(width(%d), height(%d))", __func__, *width, *height); + return true; + } + } + } + + return false; +} + +status_t CameraHardwareSec::setParameters(const CameraParameters& params) +{ + LOGV("%s :", __func__); + + status_t ret = NO_ERROR; + + const char *new_record_hint_str = params.get(CameraParameters::KEY_RECORDING_HINT); + const char *curr_record_hint_str = mParameters.get(CameraParameters::KEY_RECORDING_HINT); + LOGV("new_record_hint_str: %s", new_record_hint_str); + + if (new_record_hint_str) { + if (strncmp(new_record_hint_str, curr_record_hint_str, 5)) { + mRecordHint = !strncmp(new_record_hint_str, "true", 4); + if (mSecCamera->setMode(mRecordHint) < 0) { + LOGE("ERR(%s):fail on mSecCamera->setMode(%d)", __func__, mRecordHint); + ret = UNKNOWN_ERROR; + } else { + mParameters.set(CameraParameters::KEY_RECORDING_HINT, new_record_hint_str); + } + + if (mUseInternalISP) { + if (mSecCamera->initSetParams() < 0) { + LOGE("ERR(%s):fail on mSecCamera->initSetParams()", __func__); + ret = UNKNOWN_ERROR; + } + } + } + } + + /* if someone calls us while picture thread is running, it could screw + * up the sensor quite a bit so return error. we can't wait because + * that would cause deadlock with the callbacks + */ + mStateLock.lock(); + if (mCaptureInProgress) { + mStateLock.unlock(); + LOGE("%s : capture in progress, not allowed", __func__); + return UNKNOWN_ERROR; + } + mStateLock.unlock(); + + // preview size + int new_preview_width = 0; + int new_preview_height = 0; + int new_preview_format = 0; + + params.getPreviewSize(&new_preview_width, &new_preview_height); + + if (mUseInternalISP) { + int videosnapshot_width = new_preview_width; + int videosnapshot_height = new_preview_height; + + if (!getVideosnapshotSize(&videosnapshot_width, &videosnapshot_height)) { + LOGE("ERR(%s):fail on getVideosnapshotSize(width(%d), height(%d))", + __func__, videosnapshot_width, videosnapshot_height); + ret = UNKNOWN_ERROR; + } + + if (mSecCamera->setVideosnapshotSize(videosnapshot_width, videosnapshot_height) < 0) { + LOGE("ERR(%s):fail on mSecCamera->setVideosnapshotSize(width(%d), height(%d))", + __func__, videosnapshot_width, videosnapshot_height); + ret = UNKNOWN_ERROR; + } + } + + const char *new_str_preview_format = params.getPreviewFormat(); + LOGV("%s : new_preview_width x new_preview_height = %dx%d, format = %s", + __func__, new_preview_width, new_preview_height, new_str_preview_format); + + if (0 < new_preview_width && 0 < new_preview_height && + new_str_preview_format != NULL && + isSupportedPreviewSize(new_preview_width, new_preview_height)) { + + mFrameSizeDelta = 16; + if (!strcmp(new_str_preview_format, + CameraParameters::PIXEL_FORMAT_RGB565)) { + new_preview_format = V4L2_PIX_FMT_RGB565; + mFrameSizeDelta = 0; + } + else if (!strcmp(new_str_preview_format, + CameraParameters::PIXEL_FORMAT_RGBA8888)) { + new_preview_format = V4L2_PIX_FMT_RGB32; + mFrameSizeDelta = 0; + } + else if (!strcmp(new_str_preview_format, + CameraParameters::PIXEL_FORMAT_YUV420SP)) { + new_preview_format = V4L2_PIX_FMT_NV21; + mPreviewFmtPlane = PREVIEW_FMT_2_PLANE; + } + else if (!strcmp(new_str_preview_format, + CameraParameters::PIXEL_FORMAT_YUV420P)) { +#ifdef BOARD_USE_V4L2_ION + new_preview_format = V4L2_PIX_FMT_YVU420M; +#else + new_preview_format = V4L2_PIX_FMT_YVU420; +#endif + mPreviewFmtPlane = PREVIEW_FMT_3_PLANE; + } + else if (!strcmp(new_str_preview_format, "yuv420sp_custom")) + new_preview_format = V4L2_PIX_FMT_NV12T; + else if (!strcmp(new_str_preview_format, "yuv422i")) + new_preview_format = V4L2_PIX_FMT_YUYV; + else if (!strcmp(new_str_preview_format, "yuv422p")) + new_preview_format = V4L2_PIX_FMT_YUV422P; + else + new_preview_format = V4L2_PIX_FMT_NV21; //for 3rd party + + int current_preview_width, current_preview_height, current_frame_size; + mSecCamera->getPreviewSize(¤t_preview_width, + ¤t_preview_height, + ¤t_frame_size); + int current_pixel_format = mSecCamera->getPreviewPixelFormat(); + + if (current_preview_width != new_preview_width || + current_preview_height != new_preview_height || + current_pixel_format != new_preview_format) { + if (mSecCamera->setPreviewSize(new_preview_width, new_preview_height, + new_preview_format) < 0) { + LOGE("ERR(%s):Fail on mSecCamera->setPreviewSize(width(%d), height(%d), format(%d))", + __func__, new_preview_width, new_preview_height, new_preview_format); + ret = UNKNOWN_ERROR; + } else { + if (mPreviewWindow) { + if (mPreviewRunning && !mPreviewStartDeferred) { + LOGE("ERR(%s): preview is running, cannot change size and format!", __func__); + ret = INVALID_OPERATION; + } + LOGV("%s: mPreviewWindow (%p) set_buffers_geometry", __func__, mPreviewWindow); + LOGV("%s: mPreviewWindow->set_buffers_geometry (%p)", __func__, + mPreviewWindow->set_buffers_geometry); + mPreviewWindow->set_buffers_geometry(mPreviewWindow, + new_preview_width, new_preview_height, + V4L2_PIX_2_HAL_PIXEL_FORMAT(new_preview_format)); + LOGV("%s: DONE mPreviewWindow (%p) set_buffers_geometry", __func__, mPreviewWindow); + } + mParameters.setPreviewSize(new_preview_width, new_preview_height); + mParameters.setPreviewFormat(new_str_preview_format); + } + } + } else { + LOGE("%s: Invalid preview size(%dx%d)", + __func__, new_preview_width, new_preview_height); + + ret = INVALID_OPERATION; + } + + // picture size + int new_picture_width = 0; + int new_picture_height = 0; + + params.getPictureSize(&new_picture_width, &new_picture_height); + LOGV("%s : new_picture_width x new_picture_height = %dx%d", __func__, new_picture_width, new_picture_height); + + int current_picture_width, current_picture_height, current_picture_size; + mSecCamera->getSnapshotSize(¤t_picture_width, ¤t_picture_height, ¤t_picture_size); + + if (new_picture_width != current_picture_width || + new_picture_height != current_picture_height) { + if (mSecCamera->setSnapshotSize(new_picture_width, new_picture_height) < 0) { + LOGE("ERR(%s):fail on mSecCamera->setSnapshotSize(width(%d), height(%d))", + __func__, new_picture_width, new_picture_height); + ret = UNKNOWN_ERROR; + } else { +#ifdef ZERO_SHUTTER_LAG + mSecCamera->stopSnapshot(); + if (mUseInternalISP && !mRecordHint && mPreviewRunning){ + mSecCamera->startSnapshot(NULL); + } +#endif + mParameters.setPictureSize(new_picture_width, new_picture_height); + } + } + + // picture format + const char *new_str_picture_format = params.getPictureFormat(); + LOGV("%s : new_str_picture_format %s", __func__, new_str_picture_format); + if (new_str_picture_format != NULL) { + int new_picture_format = 0; + + if (!strcmp(new_str_picture_format, CameraParameters::PIXEL_FORMAT_RGB565)) + new_picture_format = V4L2_PIX_FMT_RGB565; + else if (!strcmp(new_str_picture_format, CameraParameters::PIXEL_FORMAT_RGBA8888)) + new_picture_format = V4L2_PIX_FMT_RGB32; + else if (!strcmp(new_str_picture_format, CameraParameters::PIXEL_FORMAT_YUV420SP)) + new_picture_format = V4L2_PIX_FMT_NV21; + else if (!strcmp(new_str_picture_format, "yuv420sp_custom")) + new_picture_format = V4L2_PIX_FMT_NV12T; + else if (!strcmp(new_str_picture_format, "yuv420p")) + new_picture_format = V4L2_PIX_FMT_YUV420; + else if (!strcmp(new_str_picture_format, "yuv422i")) + new_picture_format = V4L2_PIX_FMT_YUYV; + else if (!strcmp(new_str_picture_format, "uyv422i_custom")) //Zero copy UYVY format + new_picture_format = V4L2_PIX_FMT_UYVY; + else if (!strcmp(new_str_picture_format, "uyv422i")) //Non-zero copy UYVY format + new_picture_format = V4L2_PIX_FMT_UYVY; + else if (!strcmp(new_str_picture_format, CameraParameters::PIXEL_FORMAT_JPEG)) + new_picture_format = V4L2_PIX_FMT_YUYV; + else if (!strcmp(new_str_picture_format, "yuv422p")) + new_picture_format = V4L2_PIX_FMT_YUV422P; + else + new_picture_format = V4L2_PIX_FMT_NV21; //for 3rd party + + if (mSecCamera->setSnapshotPixelFormat(new_picture_format) < 0) { + LOGE("ERR(%s):Fail on mSecCamera->setSnapshotPixelFormat(format(%d))", __func__, new_picture_format); + ret = UNKNOWN_ERROR; + } else + mParameters.setPictureFormat(new_str_picture_format); + } + + // JPEG image quality + int new_jpeg_quality = params.getInt(CameraParameters::KEY_JPEG_QUALITY); + LOGV("%s : new_jpeg_quality %d", __func__, new_jpeg_quality); + /* we ignore bad values */ + if (new_jpeg_quality >=1 && new_jpeg_quality <= 100) { + if (mSecCamera->setJpegQuality(new_jpeg_quality) < 0) { + LOGE("ERR(%s):Fail on mSecCamera->setJpegQuality(quality(%d))", __func__, new_jpeg_quality); + ret = UNKNOWN_ERROR; + } else + mParameters.set(CameraParameters::KEY_JPEG_QUALITY, new_jpeg_quality); + } + + // JPEG thumbnail size + int new_jpeg_thumbnail_width = params.getInt(CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH); + int new_jpeg_thumbnail_height= params.getInt(CameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT); + if (0 <= new_jpeg_thumbnail_width && 0 <= new_jpeg_thumbnail_height) { + if (mSecCamera->setJpegThumbnailSize(new_jpeg_thumbnail_width, new_jpeg_thumbnail_height) < 0) { + LOGE("ERR(%s):Fail on mSecCamera->setJpegThumbnailSize(width(%d), height(%d))", __func__, new_jpeg_thumbnail_width, new_jpeg_thumbnail_height); + ret = UNKNOWN_ERROR; + } else { + mParameters.set(CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH, new_jpeg_thumbnail_width); + mParameters.set(CameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT, new_jpeg_thumbnail_height); + } + } + + // JPEG thumbnail quality + int new_jpeg_thumbnail_quality = params.getInt(CameraParameters::KEY_JPEG_THUMBNAIL_QUALITY); + LOGV("%s : new_jpeg_thumbnail_quality %d", __func__, new_jpeg_thumbnail_quality); + /* we ignore bad values */ + if (new_jpeg_thumbnail_quality >=1 && new_jpeg_thumbnail_quality <= 100) { + if (mSecCamera->setJpegThumbnailQuality(new_jpeg_thumbnail_quality) < 0) { + LOGE("ERR(%s):Fail on mSecCamera->setJpegThumbnailQuality(quality(%d))", + __func__, new_jpeg_thumbnail_quality); + ret = UNKNOWN_ERROR; + } else + mParameters.set(CameraParameters::KEY_JPEG_THUMBNAIL_QUALITY, new_jpeg_thumbnail_quality); + } + + // frame rate + int new_frame_rate = params.getPreviewFrameRate(); + /* ignore any fps request, we're determine fps automatically based + * on scene mode. don't return an error because it causes CTS failure. + */ + if (mRecordHint) { + if (new_frame_rate) { + if (mUseInternalISP && (mSecCamera->setFrameRate(new_frame_rate) < 0)){ + LOGE("ERR(%s):Fail on mSecCamera->setFrameRate(%d)", __func__, new_frame_rate); + ret = UNKNOWN_ERROR; + } else { + mParameters.setPreviewFrameRate(new_frame_rate); + } + } + } + + // rotation + int new_rotation = params.getInt(CameraParameters::KEY_ROTATION); + LOGV("%s : new_rotation %d", __func__, new_rotation); + if (0 <= new_rotation) { + LOGV("%s : set orientation:%d", __func__, new_rotation); + if (mSecCamera->setExifOrientationInfo(new_rotation) < 0) { + LOGE("ERR(%s):Fail on mSecCamera->setExifOrientationInfo(%d)", __func__, new_rotation); + ret = UNKNOWN_ERROR; + } else + mParameters.set(CameraParameters::KEY_ROTATION, new_rotation); + } + + // zoom + int new_zoom = params.getInt(CameraParameters::KEY_ZOOM); + int current_zoom = mParameters.getInt(CameraParameters::KEY_ZOOM); + LOGV("%s : new_zoom %d", __func__, new_zoom); + if (0 <= new_zoom) { + if (new_zoom != current_zoom) { + if (mSecCamera->setZoom(new_zoom) < 0) { + LOGE("ERR(%s):Fail on mSecCamera->setZoom(zoom(%d))", __func__, new_zoom); + ret = UNKNOWN_ERROR; + } else { + mParameters.set(CameraParameters::KEY_ZOOM, new_zoom); + } + } + } + + // brightness + int new_brightness = params.getInt("brightness"); + int max_brightness = params.getInt("brightness-max"); + int min_brightness = params.getInt("brightness-min"); + LOGV("%s : new_brightness %d", __func__, new_brightness); + if ((min_brightness <= new_brightness) && + (max_brightness >= new_brightness)) { + if (mSecCamera->setBrightness(new_brightness) < 0) { + LOGE("ERR(%s):Fail on mSecCamera->setBrightness(brightness(%d))", __func__, new_brightness); + ret = UNKNOWN_ERROR; + } else { + mParameters.set("brightness", new_brightness); + } + } + + // saturation + int new_saturation = params.getInt("saturation"); + int max_saturation = params.getInt("saturation-max"); + int min_saturation = params.getInt("saturation-min"); + LOGV("%s : new_saturation %d", __func__, new_saturation); + if ((min_saturation <= new_saturation) && + (max_saturation >= new_saturation)) { + if (mSecCamera->setSaturation(new_saturation) < 0) { + LOGE("ERR(%s):Fail on mSecCamera->setSaturation(saturation(%d))", __func__, new_saturation); + ret = UNKNOWN_ERROR; + } else { + mParameters.set("saturation", new_saturation); + } + } + + // sharpness + int new_sharpness = params.getInt("sharpness"); + int max_sharpness = params.getInt("sharpness-max"); + int min_sharpness = params.getInt("sharpness-min"); + LOGV("%s : new_sharpness %d", __func__, new_sharpness); + if ((min_sharpness <= new_sharpness) && + (max_sharpness >= new_sharpness)) { + if (mSecCamera->setSharpness(new_sharpness) < 0) { + LOGE("ERR(%s):Fail on mSecCamera->setSharpness(sharpness(%d))", __func__, new_sharpness); + ret = UNKNOWN_ERROR; + } else { + mParameters.set("sharpness", new_sharpness); + } + } + + // hue + int new_hue = params.getInt("hue"); + int max_hue = params.getInt("hue-max"); + int min_hue = params.getInt("hue-min"); + LOGV("%s : new_hue %d", __func__, new_hue); + if ((min_hue <= new_hue) && + (max_hue >= new_hue)) { + if (mSecCamera->setHue(new_hue) < 0) { + LOGE("ERR(%s):Fail on mSecCamera->setHue(hue(%d))", __func__, new_hue); + ret = UNKNOWN_ERROR; + } else { + mParameters.set("hue", new_hue); + } + } + + // exposure + int new_exposure_compensation = params.getInt(CameraParameters::KEY_EXPOSURE_COMPENSATION); + int max_exposure_compensation = params.getInt(CameraParameters::KEY_MAX_EXPOSURE_COMPENSATION); + int min_exposure_compensation = params.getInt(CameraParameters::KEY_MIN_EXPOSURE_COMPENSATION); + LOGV("%s : new_exposure_compensation %d", __func__, new_exposure_compensation); + if ((min_exposure_compensation <= new_exposure_compensation) && + (max_exposure_compensation >= new_exposure_compensation)) { + if (mSecCamera->setExposure(new_exposure_compensation) < 0) { + LOGE("ERR(%s):Fail on mSecCamera->setExposure(exposure(%d))", __func__, new_exposure_compensation); + ret = UNKNOWN_ERROR; + } else { + mParameters.set(CameraParameters::KEY_EXPOSURE_COMPENSATION, new_exposure_compensation); + } + } + + const char *new_AE_lock = params.get(CameraParameters::KEY_AUTO_EXPOSURE_LOCK); + const char *old_AE_lock = mParameters.get(CameraParameters::KEY_AUTO_EXPOSURE_LOCK); + if ((new_AE_lock != NULL) && mUseInternalISP && mPreviewRunning) { + if (strncmp(new_AE_lock, old_AE_lock, 4)) { + int ae_value = !strncmp(new_AE_lock, "true", 4); + if (mSecCamera->setAutoExposureLock(ae_value) < 0) { + LOGE("ERR(%s):Fail on mSecCamera->setExposureLock", __func__); + ret = UNKNOWN_ERROR; + } else { + mParameters.set(CameraParameters::KEY_AUTO_EXPOSURE_LOCK, new_AE_lock); + } + } + } + + // ISO + const char *new_iso_str = params.get("iso"); + LOGV("%s : new_iso_str %s", __func__, new_iso_str); + if (new_iso_str != NULL) { + int new_iso = -1; + + if (!strcmp(new_iso_str, "auto")) { + new_iso = ISO_AUTO; + } else if (!strcmp(new_iso_str, "50")) { + new_iso = ISO_50; + } else if (!strcmp(new_iso_str, "100")) { + new_iso = ISO_100; + } else if (!strcmp(new_iso_str, "200")) { + new_iso = ISO_200; + } else if (!strcmp(new_iso_str, "400")) { + new_iso = ISO_400; + } else if (!strcmp(new_iso_str, "800")) { + new_iso = ISO_800; + } else if (!strcmp(new_iso_str, "1600")) { + new_iso = ISO_1600; + } else { + LOGE("ERR(%s):Invalid iso value(%s)", __func__, new_iso_str); + ret = UNKNOWN_ERROR; + } + + if (0 <= new_iso) { + if (mSecCamera->setISO(new_iso) < 0) { + LOGE("ERR(%s):Fail on mSecCamera->setISO(iso(%d))", __func__, new_iso); + ret = UNKNOWN_ERROR; + } else { + mParameters.set("iso", new_iso_str); + } + } + } + + // Metering + const char *new_metering_str = params.get("metering"); + LOGV("%s : new_metering_str %s", __func__, new_metering_str); + if (new_metering_str != NULL) { + int new_metering = -1; + + if (!strcmp(new_metering_str, "center")) { + new_metering = METERING_CENTER; + } else if (!strcmp(new_metering_str, "spot")) { + new_metering = METERING_SPOT; + } else if (!strcmp(new_metering_str, "matrix")) { + new_metering = METERING_MATRIX; + } else { + LOGE("ERR(%s):Invalid metering value(%s)", __func__, new_metering_str); + ret = UNKNOWN_ERROR; + } + + if (0 <= new_metering) { + if (mSecCamera->setMetering(new_metering) < 0) { + LOGE("ERR(%s):Fail on mSecCamera->setMetering(metering(%d))", __func__, new_metering); + ret = UNKNOWN_ERROR; + } else { + mParameters.set("metering", new_metering_str); + } + } + } + + // AFC + const char *new_antibanding_str = params.get(CameraParameters::KEY_ANTIBANDING); + LOGV("%s : new_antibanding_str %s", __func__, new_antibanding_str); + if (new_antibanding_str != NULL) { + int new_antibanding = -1; + + if (!strcmp(new_antibanding_str, CameraParameters::ANTIBANDING_AUTO)) { + if (mUseInternalISP) + new_antibanding = IS_AFC_AUTO; + else + new_antibanding = ANTI_BANDING_AUTO; + } else if (!strcmp(new_antibanding_str, CameraParameters::ANTIBANDING_50HZ)) { + if (mUseInternalISP) + new_antibanding = IS_AFC_MANUAL_50HZ; + else + new_antibanding = ANTI_BANDING_50HZ; + } else if (!strcmp(new_antibanding_str, CameraParameters::ANTIBANDING_60HZ)) { + if (mUseInternalISP) + new_antibanding = IS_AFC_MANUAL_60HZ; + else + new_antibanding = ANTI_BANDING_60HZ; + } else if (!strcmp(new_antibanding_str, CameraParameters::ANTIBANDING_OFF)) { + if (mUseInternalISP) + new_antibanding = IS_AFC_DISABLE; + else + new_antibanding = ANTI_BANDING_OFF; + } else { + LOGE("ERR(%s):Invalid antibanding value(%s)", __func__, new_antibanding_str); + ret = UNKNOWN_ERROR; + } + + if (0 <= new_antibanding) { + if (mSecCamera->setAntiBanding(new_antibanding) < 0) { + LOGE("ERR(%s):Fail on mSecCamera->setAntiBanding(antibanding(%d))", __func__, new_antibanding); + ret = UNKNOWN_ERROR; + } else { + mParameters.set(CameraParameters::KEY_ANTIBANDING, new_antibanding_str); + } + } + } + + // scene mode + const char *new_scene_mode_str = params.get(CameraParameters::KEY_SCENE_MODE); + const char *current_scene_mode_str = mParameters.get(CameraParameters::KEY_SCENE_MODE); + + // fps range + int new_min_fps = 0; + int new_max_fps = 0; + int current_min_fps, current_max_fps; + params.getPreviewFpsRange(&new_min_fps, &new_max_fps); + mParameters.getPreviewFpsRange(¤t_min_fps, ¤t_max_fps); + /* our fps range is determined by the sensor, reject any request + * that isn't exactly what we're already at. + * but the check is performed when requesting only changing fps range + */ + if (new_scene_mode_str && current_scene_mode_str) { + if (!strcmp(new_scene_mode_str, current_scene_mode_str)) { + if ((new_min_fps != current_min_fps) || (new_max_fps != current_max_fps)) { + LOGW("%s : requested new_min_fps = %d, new_max_fps = %d not allowed", + __func__, new_min_fps, new_max_fps); + /* TODO : We need policy for fps. */ + LOGW("%s : current_min_fps = %d, current_max_fps = %d", + __func__, current_min_fps, current_max_fps); + //ret = UNKNOWN_ERROR; + } + } + } else { + /* Check basic validation if scene mode is different */ + if ((new_min_fps > new_max_fps) || + (new_min_fps < 0) || (new_max_fps < 0)) + ret = UNKNOWN_ERROR; + } + + const char *new_flash_mode_str = params.get(CameraParameters::KEY_FLASH_MODE); + const char *new_focus_mode_str = params.get(CameraParameters::KEY_FOCUS_MODE); + const char *new_white_str = params.get(CameraParameters::KEY_WHITE_BALANCE); + + // fps range is (15000,30000) by default. + mParameters.set(CameraParameters::KEY_SUPPORTED_PREVIEW_FPS_RANGE, "(15000,30000)"); + mParameters.set(CameraParameters::KEY_PREVIEW_FPS_RANGE, "15000,30000"); + + if ((new_scene_mode_str != NULL) && (current_scene_mode_str != NULL) && strncmp(new_scene_mode_str, current_scene_mode_str, 5)) { + int new_scene_mode = -1; + if (!strcmp(new_scene_mode_str, CameraParameters::SCENE_MODE_AUTO)) { + new_scene_mode = SCENE_MODE_NONE; + } else { + // defaults for non-auto scene modes + new_focus_mode_str = CameraParameters::FOCUS_MODE_AUTO; + new_flash_mode_str = CameraParameters::FLASH_MODE_OFF; + new_white_str = CameraParameters::WHITE_BALANCE_AUTO; + mParameters.set(CameraParameters::KEY_WHITE_BALANCE, new_white_str); + + if (!strcmp(new_scene_mode_str, CameraParameters::SCENE_MODE_PORTRAIT)) { + new_scene_mode = SCENE_MODE_PORTRAIT; + if (mCameraID == SecCamera::CAMERA_ID_BACK) + new_flash_mode_str = CameraParameters::FLASH_MODE_AUTO; + } else if (!strcmp(new_scene_mode_str, CameraParameters::SCENE_MODE_LANDSCAPE)) { + new_scene_mode = SCENE_MODE_LANDSCAPE; + } else if (!strcmp(new_scene_mode_str, CameraParameters::SCENE_MODE_SPORTS)) { + new_scene_mode = SCENE_MODE_SPORTS; + } else if (!strcmp(new_scene_mode_str, CameraParameters::SCENE_MODE_PARTY)) { + new_scene_mode = SCENE_MODE_PARTY_INDOOR; + if (mCameraID == SecCamera::CAMERA_ID_BACK) + new_flash_mode_str = CameraParameters::FLASH_MODE_AUTO; + } else if ((!strcmp(new_scene_mode_str, CameraParameters::SCENE_MODE_BEACH)) || + (!strcmp(new_scene_mode_str, CameraParameters::SCENE_MODE_SNOW))) { + new_scene_mode = SCENE_MODE_BEACH_SNOW; + } else if (!strcmp(new_scene_mode_str, CameraParameters::SCENE_MODE_SUNSET)) { + new_scene_mode = SCENE_MODE_SUNSET; + } else if (!strcmp(new_scene_mode_str, CameraParameters::SCENE_MODE_NIGHT)) { + new_scene_mode = SCENE_MODE_NIGHTSHOT; + mParameters.set(CameraParameters::KEY_SUPPORTED_PREVIEW_FPS_RANGE, "(4000,30000)"); + mParameters.set(CameraParameters::KEY_PREVIEW_FPS_RANGE, "4000,30000"); + } else if (!strcmp(new_scene_mode_str, CameraParameters::SCENE_MODE_FIREWORKS)) { + new_scene_mode = SCENE_MODE_FIREWORKS; + } else if (!strcmp(new_scene_mode_str, CameraParameters::SCENE_MODE_CANDLELIGHT)) { + new_scene_mode = SCENE_MODE_CANDLE_LIGHT; + } else { + LOGE("%s::unmatched scene_mode(%s)", + __func__, new_scene_mode_str); //action, night-portrait, theatre, steadyphoto + ret = UNKNOWN_ERROR; + } + } + + if (0 <= new_scene_mode) { + if (mSecCamera->setSceneMode(new_scene_mode) < 0) { + LOGE("%s::mSecCamera->setSceneMode(%d) fail", __func__, new_scene_mode); + ret = UNKNOWN_ERROR; + } else { + mParameters.set(CameraParameters::KEY_SCENE_MODE, new_scene_mode_str); + } + } + } + + // focus mode + /* TODO : currently only posible focus modes at BACK camera */ + if ((new_focus_mode_str != NULL) && (mCameraID == SecCamera::CAMERA_ID_BACK)) { + int new_focus_mode = -1; + + if (!strcmp(new_focus_mode_str, + CameraParameters::FOCUS_MODE_AUTO)) { + new_focus_mode = FOCUS_MODE_AUTO; + mParameters.set(CameraParameters::KEY_FOCUS_DISTANCES, + BACK_CAMERA_AUTO_FOCUS_DISTANCES_STR); + } else if (!strcmp(new_focus_mode_str, + CameraParameters::FOCUS_MODE_MACRO)) { + new_focus_mode = FOCUS_MODE_MACRO; + mParameters.set(CameraParameters::KEY_FOCUS_DISTANCES, + BACK_CAMERA_MACRO_FOCUS_DISTANCES_STR); + } else if (!strcmp(new_focus_mode_str, + CameraParameters::FOCUS_MODE_INFINITY)) { + new_focus_mode = FOCUS_MODE_INFINITY; + mParameters.set(CameraParameters::KEY_FOCUS_DISTANCES, + BACK_CAMERA_INFINITY_FOCUS_DISTANCES_STR); + } else if (!strcmp(new_focus_mode_str, + CameraParameters::FOCUS_MODE_CONTINUOUS_VIDEO) || + !strcmp(new_focus_mode_str, + CameraParameters::FOCUS_MODE_CONTINUOUS_PICTURE)) { + new_focus_mode = FOCUS_MODE_CONTINOUS; + } else { + /* TODO */ + /* This is temperary implementation. + When camera support all AF mode, this code will be changing */ + LOGE("%s::unmatched focus_mode(%s)", __func__, new_focus_mode_str); + ret = UNKNOWN_ERROR; + } + + if (0 <= new_focus_mode) { + if (mSecCamera->setFocusMode(new_focus_mode) < 0) { + LOGE("%s::mSecCamera->setFocusMode(%d) fail", __func__, new_focus_mode); + ret = UNKNOWN_ERROR; + } else { + mParameters.set(CameraParameters::KEY_FOCUS_MODE, new_focus_mode_str); + } + } + } + + // flash.. + if (new_flash_mode_str != NULL) { + int new_flash_mode = -1; + + if (!strcmp(new_flash_mode_str, CameraParameters::FLASH_MODE_OFF)) + new_flash_mode = FLASH_MODE_OFF; + else if (!strcmp(new_flash_mode_str, CameraParameters::FLASH_MODE_AUTO)) + new_flash_mode = FLASH_MODE_AUTO; + else if (!strcmp(new_flash_mode_str, CameraParameters::FLASH_MODE_ON)) + new_flash_mode = FLASH_MODE_ON; + else if (!strcmp(new_flash_mode_str, CameraParameters::FLASH_MODE_TORCH)) + new_flash_mode = FLASH_MODE_TORCH; + else { + LOGE("%s::unmatched flash_mode(%s)", __func__, new_flash_mode_str); //red-eye + ret = UNKNOWN_ERROR; + } + if (0 <= new_flash_mode) { + if (mSecCamera->setFlashMode(new_flash_mode) < 0) { + LOGE("%s::mSecCamera->setFlashMode(%d) fail", __func__, new_flash_mode); + ret = UNKNOWN_ERROR; + } else { + mParameters.set(CameraParameters::KEY_FLASH_MODE, new_flash_mode_str); + } + } + } + + // whitebalance + LOGV("%s : new_white_str %s", __func__, new_white_str); + if ((new_scene_mode_str != NULL) && !strcmp(new_scene_mode_str, CameraParameters::SCENE_MODE_AUTO)) { + if (new_white_str != NULL) { + int new_white = -1; + + if (!strcmp(new_white_str, CameraParameters::WHITE_BALANCE_AUTO)) { + new_white = WHITE_BALANCE_AUTO; + } else if (!strcmp(new_white_str, + CameraParameters::WHITE_BALANCE_DAYLIGHT)) { + new_white = WHITE_BALANCE_SUNNY; + } else if (!strcmp(new_white_str, + CameraParameters::WHITE_BALANCE_CLOUDY_DAYLIGHT)) { + new_white = WHITE_BALANCE_CLOUDY; + } else if (!strcmp(new_white_str, + CameraParameters::WHITE_BALANCE_FLUORESCENT)) { + new_white = WHITE_BALANCE_FLUORESCENT; + } else if (!strcmp(new_white_str, + CameraParameters::WHITE_BALANCE_INCANDESCENT)) { + new_white = WHITE_BALANCE_TUNGSTEN; + } else { + LOGE("ERR(%s):Invalid white balance(%s)", __func__, new_white_str); //twilight, shade, warm_flourescent + ret = UNKNOWN_ERROR; + } + + if (0 <= new_white) { + if (mSecCamera->setWhiteBalance(new_white) < 0) { + LOGE("ERR(%s):Fail on mSecCamera->setWhiteBalance(white(%d))", __func__, new_white); + ret = UNKNOWN_ERROR; + } else { + mParameters.set(CameraParameters::KEY_WHITE_BALANCE, new_white_str); + } + } + } + } + + const char *new_AWB_lock = params.get(CameraParameters::KEY_AUTO_WHITEBALANCE_LOCK); + const char *old_AWB_lock = mParameters.get(CameraParameters::KEY_AUTO_WHITEBALANCE_LOCK); + if (new_AWB_lock != NULL && mUseInternalISP && mPreviewRunning) { + if (strncmp(new_AWB_lock, old_AWB_lock, 4)) { + int awb_value = !strncmp(new_AWB_lock, "true", 4); + if (mSecCamera->setAutoWhiteBalanceLock(awb_value) < 0) { + LOGE("ERR(%s):Fail on mSecCamera->setoAutoWhiteBalanceLock()", __func__); + ret = UNKNOWN_ERROR; + } else { + mParameters.set(CameraParameters::KEY_AUTO_WHITEBALANCE_LOCK, new_AWB_lock); + } + } + } + + const char *new_touch_rect_str = params.get(CameraParameters::KEY_FOCUS_AREAS); + LOGV("Touched rect is '%s'", new_touch_rect_str); + + if (new_touch_rect_str != NULL) { + int left = 0, top = 0, right = 0, bottom = 0, touched = 0; + int objx, objy; + + char *end; + char delim = ','; + left = (int)strtol(new_touch_rect_str+1, &end, 10); + if (*end != delim) { + LOGE("Cannot find '%c' in str=%s", delim, new_touch_rect_str); + return -1; + } + top = (int)strtol(end+1, &end, 10); + if (*end != delim) { + LOGE("Cannot find '%c' in str=%s", delim, new_touch_rect_str); + return -1; + } + right = (int)strtol(end+1, &end, 10); + if (*end != delim) { + LOGE("Cannot find '%c' in str=%s", delim, new_touch_rect_str); + return -1; + } + bottom = (int)strtol(end+1, &end, 10); + if (*end != delim) { + LOGE("Cannot find '%c' in str=%s", delim, new_touch_rect_str); + return -1; + } + touched = (int)strtol(end+1, &end, 10); + if (*end != ')') { + LOGE("Cannot find ')' in str=%s", new_touch_rect_str); + return -1; + } + + /* TODO : Converting axis and Calcurating center of rect. Because driver need (x, y) point. */ + objx = (int)((1023 * (left + 1000)) / 2000) + 97; + objy = (int)((1023 * (top + 1000)) / 2000) + 128; + + mTouched = touched; + mSecCamera->setObjectPosition(objx, objy); + } + + // image effect + const char *new_image_effect_str = params.get(CameraParameters::KEY_EFFECT); + if (new_image_effect_str != NULL) { + + int new_image_effect = -1; + + if (!strcmp(new_image_effect_str, CameraParameters::EFFECT_NONE)) { + new_image_effect = IMAGE_EFFECT_NONE; + } else if (!strcmp(new_image_effect_str, CameraParameters::EFFECT_MONO)) { + new_image_effect = IMAGE_EFFECT_BNW; + } else if (!strcmp(new_image_effect_str, CameraParameters::EFFECT_SEPIA)) { + new_image_effect = IMAGE_EFFECT_SEPIA; + } else if (!strcmp(new_image_effect_str, CameraParameters::EFFECT_AQUA)) + new_image_effect = IMAGE_EFFECT_AQUA; + else if (!strcmp(new_image_effect_str, CameraParameters::EFFECT_NEGATIVE)) { + new_image_effect = IMAGE_EFFECT_NEGATIVE; + } else { + //posterize, whiteboard, blackboard, solarize + LOGE("ERR(%s):Invalid effect(%s)", __func__, new_image_effect_str); + ret = UNKNOWN_ERROR; + } + + if (new_image_effect >= 0) { + if (mSecCamera->setImageEffect(new_image_effect) < 0) { + LOGE("ERR(%s):Fail on mSecCamera->setImageEffect(effect(%d))", __func__, new_image_effect); + ret = UNKNOWN_ERROR; + } else { + const char *old_image_effect_str = mParameters.get(CameraParameters::KEY_EFFECT); + + if (old_image_effect_str) { + if (strcmp(old_image_effect_str, new_image_effect_str)) { + setSkipFrame(EFFECT_SKIP_FRAME); + } + } + + mParameters.set(CameraParameters::KEY_EFFECT, new_image_effect_str); + } + } + } + + //contrast + const char *new_contrast_str = params.get("contrast"); + LOGV("%s : new_contrast_str %s", __func__, new_contrast_str); + if (new_contrast_str != NULL) { + int new_contrast = -1; + + if (!strcmp(new_contrast_str, "auto")) { + if (mUseInternalISP) + new_contrast = IS_CONTRAST_AUTO; + else + LOGW("WARN(%s):Invalid contrast value (%s)", __func__, new_contrast_str); + } else if (!strcmp(new_contrast_str, "-2")) { + if (mUseInternalISP) + new_contrast = IS_CONTRAST_MINUS_2; + else + new_contrast = CONTRAST_MINUS_2; + } else if (!strcmp(new_contrast_str, "-1")) { + if (mUseInternalISP) + new_contrast = IS_CONTRAST_MINUS_1; + else + new_contrast = CONTRAST_MINUS_1; + } else if (!strcmp(new_contrast_str, "0")) { + if (mUseInternalISP) + new_contrast = IS_CONTRAST_DEFAULT; + else + new_contrast = CONTRAST_DEFAULT; + } else if (!strcmp(new_contrast_str, "1")) { + if (mUseInternalISP) + new_contrast = IS_CONTRAST_PLUS_1; + else + new_contrast = CONTRAST_PLUS_1; + } else if (!strcmp(new_contrast_str, "2")) { + if (mUseInternalISP) + new_contrast = IS_CONTRAST_PLUS_2; + else + new_contrast = CONTRAST_PLUS_2; + } else { + LOGE("ERR(%s):Invalid contrast value(%s)", __func__, new_contrast_str); + ret = UNKNOWN_ERROR; + } + + if (0 <= new_contrast) { + if (mSecCamera->setContrast(new_contrast) < 0) { + LOGE("ERR(%s):Fail on mSecCamera->setContrast(contrast(%d))", __func__, new_contrast); + ret = UNKNOWN_ERROR; + } else { + mParameters.set("contrast", new_contrast_str); + } + } + } + + //WDR + int new_wdr = params.getInt("wdr"); + LOGV("%s : new_wdr %d", __func__, new_wdr); + + if (0 <= new_wdr) { + if (mSecCamera->setWDR(new_wdr) < 0) { + LOGE("ERR(%s):Fail on mSecCamera->setWDR(%d)", __func__, new_wdr); + ret = UNKNOWN_ERROR; + } + } + + //anti shake + int new_anti_shake = mInternalParameters.getInt("anti-shake"); + + if (0 <= new_anti_shake) { + if (mSecCamera->setAntiShake(new_anti_shake) < 0) { + LOGE("ERR(%s):Fail on mSecCamera->setWDR(%d)", __func__, new_anti_shake); + ret = UNKNOWN_ERROR; + } + } + + // gps latitude + const char *new_gps_latitude_str = params.get(CameraParameters::KEY_GPS_LATITUDE); + if (mSecCamera->setGPSLatitude(new_gps_latitude_str) < 0) { + LOGE("%s::mSecCamera->setGPSLatitude(%s) fail", __func__, new_gps_latitude_str); + ret = UNKNOWN_ERROR; + } else { + if (new_gps_latitude_str) { + mParameters.set(CameraParameters::KEY_GPS_LATITUDE, new_gps_latitude_str); + } else { + mParameters.remove(CameraParameters::KEY_GPS_LATITUDE); + } + } + + // gps longitude + const char *new_gps_longitude_str = params.get(CameraParameters::KEY_GPS_LONGITUDE); + + if (mSecCamera->setGPSLongitude(new_gps_longitude_str) < 0) { + LOGE("%s::mSecCamera->setGPSLongitude(%s) fail", __func__, new_gps_longitude_str); + ret = UNKNOWN_ERROR; + } else { + if (new_gps_longitude_str) { + mParameters.set(CameraParameters::KEY_GPS_LONGITUDE, new_gps_longitude_str); + } else { + mParameters.remove(CameraParameters::KEY_GPS_LONGITUDE); + } + } + + // gps altitude + const char *new_gps_altitude_str = params.get(CameraParameters::KEY_GPS_ALTITUDE); + + if (mSecCamera->setGPSAltitude(new_gps_altitude_str) < 0) { + LOGE("%s::mSecCamera->setGPSAltitude(%s) fail", __func__, new_gps_altitude_str); + ret = UNKNOWN_ERROR; + } else { + if (new_gps_altitude_str) { + mParameters.set(CameraParameters::KEY_GPS_ALTITUDE, new_gps_altitude_str); + } else { + mParameters.remove(CameraParameters::KEY_GPS_ALTITUDE); + } + } + + // gps timestamp + const char *new_gps_timestamp_str = params.get(CameraParameters::KEY_GPS_TIMESTAMP); + + if (mSecCamera->setGPSTimeStamp(new_gps_timestamp_str) < 0) { + LOGE("%s::mSecCamera->setGPSTimeStamp(%s) fail", __func__, new_gps_timestamp_str); + ret = UNKNOWN_ERROR; + } else { + if (new_gps_timestamp_str) { + mParameters.set(CameraParameters::KEY_GPS_TIMESTAMP, new_gps_timestamp_str); + } else { + mParameters.remove(CameraParameters::KEY_GPS_TIMESTAMP); + } + } + + // gps processing method + const char *new_gps_processing_method_str = params.get(CameraParameters::KEY_GPS_PROCESSING_METHOD); + + if (mSecCamera->setGPSProcessingMethod(new_gps_processing_method_str) < 0) { + LOGE("%s::mSecCamera->setGPSProcessingMethod(%s) fail", __func__, new_gps_processing_method_str); + ret = UNKNOWN_ERROR; + } else { + if (new_gps_processing_method_str) { + mParameters.set(CameraParameters::KEY_GPS_PROCESSING_METHOD, new_gps_processing_method_str); + } else { + mParameters.remove(CameraParameters::KEY_GPS_PROCESSING_METHOD); + } + } + + // Recording size + /* TODO */ + /* GED application don't set different recording size before recording button is pushed */ + int new_recording_width = 0; + int new_recording_height = 0; + params.getVideoSize(&new_recording_width, &new_recording_height); + LOGV("new_recording_width (%d) new_recording_height (%d)", + new_recording_width, new_recording_height); + + int current_recording_width, current_recording_height; + mParameters.getVideoSize(¤t_recording_width, ¤t_recording_height); + LOGV("current_recording_width (%d) current_recording_height (%d)", + current_recording_width, current_recording_height); + + if (current_recording_width != new_recording_width || + current_recording_height != new_recording_height) { + if (0 < new_recording_width && 0 < new_recording_height) { + if (mSecCamera->setRecordingSize(new_recording_width, new_recording_height) < 0) { + LOGE("ERR(%s):Fail on mSecCamera->setRecordingSize(width(%d), height(%d))", + __func__, new_recording_width, new_recording_height); + ret = UNKNOWN_ERROR; + } + mParameters.setVideoSize(new_recording_width, new_recording_height); + } + } + + //gamma + const char *new_gamma_str = mInternalParameters.get("video_recording_gamma"); + + if (new_gamma_str != NULL) { + int new_gamma = -1; + if (!strcmp(new_gamma_str, "off")) + new_gamma = GAMMA_OFF; + else if (!strcmp(new_gamma_str, "on")) + new_gamma = GAMMA_ON; + else { + LOGE("%s::unmatched gamma(%s)", __func__, new_gamma_str); + ret = UNKNOWN_ERROR; + } + + if (0 <= new_gamma) { + if (mSecCamera->setGamma(new_gamma) < 0) { + LOGE("%s::mSecCamera->setGamma(%d) fail", __func__, new_gamma); + ret = UNKNOWN_ERROR; + } + } + } + + //slow ae + const char *new_slow_ae_str = mInternalParameters.get("slow_ae"); + + if (new_slow_ae_str != NULL) { + int new_slow_ae = -1; + + if (!strcmp(new_slow_ae_str, "off")) + new_slow_ae = SLOW_AE_OFF; + else if (!strcmp(new_slow_ae_str, "on")) + new_slow_ae = SLOW_AE_ON; + else { + LOGE("%s::unmatched slow_ae(%s)", __func__, new_slow_ae_str); + ret = UNKNOWN_ERROR; + } + + if (0 <= new_slow_ae) { + if (mSecCamera->setSlowAE(new_slow_ae) < 0) { + LOGE("%s::mSecCamera->setSlowAE(%d) fail", __func__, new_slow_ae); + ret = UNKNOWN_ERROR; + } + } + } + + /*Camcorder fix fps*/ + int new_sensor_mode = mInternalParameters.getInt("cam_mode"); + + if (0 <= new_sensor_mode) { + if (mSecCamera->setSensorMode(new_sensor_mode) < 0) { + LOGE("ERR(%s):Fail on mSecCamera->setSensorMode(%d)", __func__, new_sensor_mode); + ret = UNKNOWN_ERROR; + } + } else { + new_sensor_mode=0; + } + + /*Shot mode*/ + int new_shot_mode = mInternalParameters.getInt("shot_mode"); + + if (0 <= new_shot_mode) { + if (mSecCamera->setShotMode(new_shot_mode) < 0) { + LOGE("ERR(%s):Fail on mSecCamera->setShotMode(%d)", __func__, new_shot_mode); + ret = UNKNOWN_ERROR; + } + } else { + new_shot_mode=0; + } + + // chk_dataline + int new_dataline = mInternalParameters.getInt("chk_dataline"); + + if (0 <= new_dataline) { + if (mSecCamera->setDataLineCheck(new_dataline) < 0) { + LOGE("ERR(%s):Fail on mSecCamera->setDataLineCheck(%d)", __func__, new_dataline); + ret = UNKNOWN_ERROR; + } + } + LOGV("%s return ret = %d", __func__, ret); + + return ret; +} + +CameraParameters CameraHardwareSec::getParameters() const +{ + LOGV("%s :", __func__); + return mParameters; +} + +status_t CameraHardwareSec::sendCommand(int32_t command, int32_t arg1, int32_t arg2) +{ + /* TODO */ + /* CAMERA_CMD_START_FACE_DETECTION and CAMERA_CMD_STOP_FACE_DETECTION + for Face Detection */ + if(command == CAMERA_CMD_START_FACE_DETECTION) { + if (mSecCamera->setFaceDetect(FACE_DETECTION_ON) < 0) { + LOGE("ERR(%s): Fail on mSecCamera->startFaceDetection()"); + return BAD_VALUE; + } else { + return NO_ERROR; + } + } + if(command == CAMERA_CMD_STOP_FACE_DETECTION) { + if (mSecCamera->setFaceDetect(FACE_DETECTION_OFF) < 0) { + LOGE("ERR(%s): Fail on mSecCamera->stopFaceDetection()"); + return BAD_VALUE; + } else { + return NO_ERROR; + } + } + + return BAD_VALUE; +} + +void CameraHardwareSec::release() +{ + LOGV("%s", __func__); + + /* shut down any threads we have that might be running. do it here + * instead of the destructor. we're guaranteed to be on another thread + * than the ones below. if we used the destructor, since the threads + * have a reference to this object, we could wind up trying to wait + * for ourself to exit, which is a deadlock. + */ + if (mPreviewThread != NULL) { + /* this thread is normally already in it's threadLoop but blocked + * on the condition variable or running. signal it so it wakes + * up and can exit. + */ + mPreviewThread->requestExit(); + mExitPreviewThread = true; + mPreviewRunning = true; /* let it run so it can exit */ + mPreviewCondition.signal(); + mPreviewThread->requestExitAndWait(); + mPreviewThread.clear(); + } + if (mAutoFocusThread != NULL) { + /* this thread is normally already in it's threadLoop but blocked + * on the condition variable. signal it so it wakes up and can exit. + */ + mFocusLock.lock(); + mAutoFocusThread->requestExit(); + mExitAutoFocusThread = true; + mFocusCondition.signal(); + mFocusLock.unlock(); + mAutoFocusThread->requestExitAndWait(); + mAutoFocusThread.clear(); + } + if (mPictureThread != NULL) { + mPictureThread->requestExitAndWait(); + mPictureThread.clear(); + } + + if (mRawHeap) { + mRawHeap->release(mRawHeap); + mRawHeap = 0; + } + if (mPreviewHeap) { + mPreviewHeap->release(mPreviewHeap); + mPreviewHeap = 0; + } + for(int i = 0; i < BUFFER_COUNT_FOR_ARRAY; i++) { + if (mRecordHeap[i]) { + mRecordHeap[i]->release(mRecordHeap[i]); + mRecordHeap[i] = 0; + } + } + + /* close after all the heaps are cleared since those + * could have dup'd our file descriptor. + */ + mSecCamera->DestroyCamera(); +} + +static CameraInfo sCameraInfo[] = { + { + CAMERA_FACING_BACK, + 90, /* orientation */ + }, + { + CAMERA_FACING_FRONT, + 90, /* orientation */ + } +}; + +status_t CameraHardwareSec::storeMetaDataInBuffers(bool enable) +{ + // FIXME: + // metadata buffer mode can be turned on or off. + // Samsung needs to fix this. + if (!enable) { + LOGE("Non-metadata buffer mode is not supported!"); + return INVALID_OPERATION; + } + return OK; +} + +/** Close this device */ + +static camera_device_t *g_cam_device; + +static int HAL_camera_device_close(struct hw_device_t* device) +{ + LOGI("%s", __func__); + if (device) { + camera_device_t *cam_device = (camera_device_t *)device; + delete static_cast(cam_device->priv); + free(cam_device); + g_cam_device = 0; + } + return 0; +} + +static inline CameraHardwareSec *obj(struct camera_device *dev) +{ + return reinterpret_cast(dev->priv); +} + +/** Set the preview_stream_ops to which preview frames are sent */ +static int HAL_camera_device_set_preview_window(struct camera_device *dev, + struct preview_stream_ops *buf) +{ + LOGV("%s", __func__); + return obj(dev)->setPreviewWindow(buf); +} + +/** Set the notification and data callbacks */ +static void HAL_camera_device_set_callbacks(struct camera_device *dev, + camera_notify_callback notify_cb, + camera_data_callback data_cb, + camera_data_timestamp_callback data_cb_timestamp, + camera_request_memory get_memory, + void* user) +{ + LOGV("%s", __func__); + obj(dev)->setCallbacks(notify_cb, data_cb, data_cb_timestamp, + get_memory, + user); +} + +/** + * The following three functions all take a msg_type, which is a bitmask of + * the messages defined in include/ui/Camera.h + */ + +/** + * Enable a message, or set of messages. + */ +static void HAL_camera_device_enable_msg_type(struct camera_device *dev, int32_t msg_type) +{ + LOGV("%s", __func__); + obj(dev)->enableMsgType(msg_type); +} + +/** + * Disable a message, or a set of messages. + * + * Once received a call to disableMsgType(CAMERA_MSG_VIDEO_FRAME), camera + * HAL should not rely on its client to call releaseRecordingFrame() to + * release video recording frames sent out by the cameral HAL before and + * after the disableMsgType(CAMERA_MSG_VIDEO_FRAME) call. Camera HAL + * clients must not modify/access any video recording frame after calling + * disableMsgType(CAMERA_MSG_VIDEO_FRAME). + */ +static void HAL_camera_device_disable_msg_type(struct camera_device *dev, int32_t msg_type) +{ + LOGV("%s", __func__); + obj(dev)->disableMsgType(msg_type); +} + +/** + * Query whether a message, or a set of messages, is enabled. Note that + * this is operates as an AND, if any of the messages queried are off, this + * will return false. + */ +static int HAL_camera_device_msg_type_enabled(struct camera_device *dev, int32_t msg_type) +{ + LOGV("%s", __func__); + return obj(dev)->msgTypeEnabled(msg_type); +} + +/** + * Start preview mode. + */ +static int HAL_camera_device_start_preview(struct camera_device *dev) +{ + LOGV("%s", __func__); + return obj(dev)->startPreview(); +} + +/** + * Stop a previously started preview. + */ +static void HAL_camera_device_stop_preview(struct camera_device *dev) +{ + LOGV("%s", __func__); + obj(dev)->stopPreview(); +} + +/** + * Returns true if preview is enabled. + */ +static int HAL_camera_device_preview_enabled(struct camera_device *dev) +{ + LOGV("%s", __func__); + return obj(dev)->previewEnabled(); +} + +/** + * Request the camera HAL to store meta data or real YUV data in the video + * buffers sent out via CAMERA_MSG_VIDEO_FRAME for a recording session. If + * it is not called, the default camera HAL behavior is to store real YUV + * data in the video buffers. + * + * This method should be called before startRecording() in order to be + * effective. + * + * If meta data is stored in the video buffers, it is up to the receiver of + * the video buffers to interpret the contents and to find the actual frame + * data with the help of the meta data in the buffer. How this is done is + * outside of the scope of this method. + * + * Some camera HALs may not support storing meta data in the video buffers, + * but all camera HALs should support storing real YUV data in the video + * buffers. If the camera HAL does not support storing the meta data in the + * video buffers when it is requested to do do, INVALID_OPERATION must be + * returned. It is very useful for the camera HAL to pass meta data rather + * than the actual frame data directly to the video encoder, since the + * amount of the uncompressed frame data can be very large if video size is + * large. + * + * @param enable if true to instruct the camera HAL to store + * meta data in the video buffers; false to instruct + * the camera HAL to store real YUV data in the video + * buffers. + * + * @return OK on success. + */ +static int HAL_camera_device_store_meta_data_in_buffers(struct camera_device *dev, int enable) +{ + LOGV("%s", __func__); + return obj(dev)->storeMetaDataInBuffers(enable); +} + +/** + * Start record mode. When a record image is available, a + * CAMERA_MSG_VIDEO_FRAME message is sent with the corresponding + * frame. Every record frame must be released by a camera HAL client via + * releaseRecordingFrame() before the client calls + * disableMsgType(CAMERA_MSG_VIDEO_FRAME). After the client calls + * disableMsgType(CAMERA_MSG_VIDEO_FRAME), it is the camera HAL's + * responsibility to manage the life-cycle of the video recording frames, + * and the client must not modify/access any video recording frames. + */ +static int HAL_camera_device_start_recording(struct camera_device *dev) +{ + LOGV("%s", __func__); + return obj(dev)->startRecording(); +} + +/** + * Stop a previously started recording. + */ +static void HAL_camera_device_stop_recording(struct camera_device *dev) +{ + LOGV("%s", __func__); + obj(dev)->stopRecording(); +} + +/** + * Returns true if recording is enabled. + */ +static int HAL_camera_device_recording_enabled(struct camera_device *dev) +{ + LOGV("%s", __func__); + return obj(dev)->recordingEnabled(); +} + +/** + * Release a record frame previously returned by CAMERA_MSG_VIDEO_FRAME. + * + * It is camera HAL client's responsibility to release video recording + * frames sent out by the camera HAL before the camera HAL receives a call + * to disableMsgType(CAMERA_MSG_VIDEO_FRAME). After it receives the call to + * disableMsgType(CAMERA_MSG_VIDEO_FRAME), it is the camera HAL's + * responsibility to manage the life-cycle of the video recording frames. + */ +static void HAL_camera_device_release_recording_frame(struct camera_device *dev, + const void *opaque) +{ + LOGV("%s", __func__); + obj(dev)->releaseRecordingFrame(opaque); +} + +/** + * Start auto focus, the notification callback routine is called with + * CAMERA_MSG_FOCUS once when focusing is complete. autoFocus() will be + * called again if another auto focus is needed. + */ +static int HAL_camera_device_auto_focus(struct camera_device *dev) +{ + LOGV("%s", __func__); + return obj(dev)->autoFocus(); +} + +/** + * Cancels auto-focus function. If the auto-focus is still in progress, + * this function will cancel it. Whether the auto-focus is in progress or + * not, this function will return the focus position to the default. If + * the camera does not support auto-focus, this is a no-op. + */ +static int HAL_camera_device_cancel_auto_focus(struct camera_device *dev) +{ + LOGV("%s", __func__); + return obj(dev)->cancelAutoFocus(); +} + +/** + * Take a picture. + */ +static int HAL_camera_device_take_picture(struct camera_device *dev) +{ + LOGV("%s", __func__); + return obj(dev)->takePicture(); +} + +/** + * Cancel a picture that was started with takePicture. Calling this method + * when no picture is being taken is a no-op. + */ +static int HAL_camera_device_cancel_picture(struct camera_device *dev) +{ + LOGV("%s", __func__); + return obj(dev)->cancelPicture(); +} + +/** + * Set the camera parameters. This returns BAD_VALUE if any parameter is + * invalid or not supported. + */ +static int HAL_camera_device_set_parameters(struct camera_device *dev, + const char *parms) +{ + LOGV("%s", __func__); + String8 str(parms); + CameraParameters p(str); + return obj(dev)->setParameters(p); +} + +/** Return the camera parameters. */ +char *HAL_camera_device_get_parameters(struct camera_device *dev) +{ + LOGV("%s", __func__); + String8 str; + CameraParameters parms = obj(dev)->getParameters(); + str = parms.flatten(); + return strdup(str.string()); +} + +static void HAL_camera_device_put_parameters(struct camera_device *dev, char *parms) +{ + LOGV("%s", __func__); + free(parms); +} + +/** + * Send command to camera driver. + */ +static int HAL_camera_device_send_command(struct camera_device *dev, + int32_t cmd, int32_t arg1, int32_t arg2) +{ + LOGV("%s", __func__); + return obj(dev)->sendCommand(cmd, arg1, arg2); +} + +/** + * Release the hardware resources owned by this object. Note that this is + * *not* done in the destructor. + */ +static void HAL_camera_device_release(struct camera_device *dev) +{ + LOGV("%s", __func__); + obj(dev)->release(); +} + +/** + * Dump state of the camera hardware + */ +static int HAL_camera_device_dump(struct camera_device *dev, int fd) +{ + LOGV("%s", __func__); + return obj(dev)->dump(fd); +} + +static int HAL_getNumberOfCameras() +{ + LOGV("%s", __func__); + + int cam_fd; + static struct v4l2_input input; + + cam_fd = open(CAMERA_DEV_NAME, O_RDONLY); + if (cam_fd < 0) { + LOGE("ERR(%s):Cannot open %s (error : %s)", __func__, CAMERA_DEV_NAME, strerror(errno)); + return -1; + } + + input.index = 0; + while (ioctl(cam_fd, VIDIOC_ENUMINPUT, &input) == 0) { + LOGI("Name of input channel[%d] is %s", input.index, input.name); + input.index++; + } + + close(cam_fd); + + return --input.index; +} + +static int HAL_getCameraInfo(int cameraId, struct camera_info *cameraInfo) +{ + LOGV("%s", __func__); + memcpy(cameraInfo, &sCameraInfo[cameraId], sizeof(CameraInfo)); + return 0; +} + +#define SET_METHOD(m) m : HAL_camera_device_##m + +static camera_device_ops_t camera_device_ops = { + SET_METHOD(set_preview_window), + SET_METHOD(set_callbacks), + SET_METHOD(enable_msg_type), + SET_METHOD(disable_msg_type), + SET_METHOD(msg_type_enabled), + SET_METHOD(start_preview), + SET_METHOD(stop_preview), + SET_METHOD(preview_enabled), + SET_METHOD(store_meta_data_in_buffers), + SET_METHOD(start_recording), + SET_METHOD(stop_recording), + SET_METHOD(recording_enabled), + SET_METHOD(release_recording_frame), + SET_METHOD(auto_focus), + SET_METHOD(cancel_auto_focus), + SET_METHOD(take_picture), + SET_METHOD(cancel_picture), + SET_METHOD(set_parameters), + SET_METHOD(get_parameters), + SET_METHOD(put_parameters), + SET_METHOD(send_command), + SET_METHOD(release), + SET_METHOD(dump), +}; + +#undef SET_METHOD + +static int HAL_camera_device_open(const struct hw_module_t* module, + const char *id, + struct hw_device_t** device) +{ + LOGV("%s", __func__); + + int cameraId = atoi(id); + if (cameraId < 0 || cameraId >= HAL_getNumberOfCameras()) { + LOGE("Invalid camera ID %s", id); + return -EINVAL; + } + + if (g_cam_device) { + if (obj(g_cam_device)->getCameraId() == cameraId) { + LOGV("returning existing camera ID %s", id); + goto done; + } else { + LOGE("Cannot open camera %d. camera %d is already running!", + cameraId, obj(g_cam_device)->getCameraId()); + return -ENOSYS; + } + } + + g_cam_device = (camera_device_t *)malloc(sizeof(camera_device_t)); + if (!g_cam_device) + return -ENOMEM; + + g_cam_device->common.tag = HARDWARE_DEVICE_TAG; + g_cam_device->common.version = 1; + g_cam_device->common.module = const_cast(module); + g_cam_device->common.close = HAL_camera_device_close; + + g_cam_device->ops = &camera_device_ops; + + LOGI("%s: open camera %s", __func__, id); + + g_cam_device->priv = new CameraHardwareSec(cameraId, g_cam_device); + +done: + *device = (hw_device_t *)g_cam_device; + LOGI("%s: opened camera %s (%p)", __func__, id, *device); + return 0; +} + +static hw_module_methods_t camera_module_methods = { + open : HAL_camera_device_open +}; + +extern "C" { + struct camera_module HAL_MODULE_INFO_SYM = { + common : { + tag : HARDWARE_MODULE_TAG, + version_major : 1, + version_minor : 0, + id : CAMERA_HARDWARE_MODULE_ID, + name : "orion camera HAL", + author : "Samsung Corporation", + methods : &camera_module_methods, + }, + get_number_of_cameras : HAL_getNumberOfCameras, + get_camera_info : HAL_getCameraInfo + }; +} + +}; // namespace android diff --git a/exynos4/hal/libcamera/SecCameraHWInterface.h b/exynos4/hal/libcamera/SecCameraHWInterface.h new file mode 100644 index 0000000..321eb15 --- /dev/null +++ b/exynos4/hal/libcamera/SecCameraHWInterface.h @@ -0,0 +1,242 @@ +/* +** +** Copyright 2008, The Android Open Source Project +** Copyright 2010, Samsung Electronics Co. LTD +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + +#ifndef ANDROID_HARDWARE_CAMERA_HARDWARE_SEC_H +#define ANDROID_HARDWARE_CAMERA_HARDWARE_SEC_H + +#include "SecCamera.h" +#include +#include +#include +#include +#include +#include +#include +#ifdef BOARD_USE_V4L2_ION +#include +#include "gralloc_priv.h" + +#define BUFFER_COUNT_FOR_GRALLOC (MAX_BUFFERS + 4) +#define BUFFER_COUNT_FOR_ARRAY (MAX_BUFFERS) +#else +#define BUFFER_COUNT_FOR_GRALLOC (MAX_BUFFERS) +#define BUFFER_COUNT_FOR_ARRAY (1) +#endif + +namespace android { + class CameraHardwareSec : public virtual RefBase { +public: + virtual void setCallbacks(camera_notify_callback notify_cb, + camera_data_callback data_cb, + camera_data_timestamp_callback data_cb_timestamp, + camera_request_memory get_memory, + void *user); + + virtual void enableMsgType(int32_t msgType); + virtual void disableMsgType(int32_t msgType); + virtual bool msgTypeEnabled(int32_t msgType); + + virtual status_t startPreview(); + virtual void stopPreview(); + virtual bool previewEnabled(); + + virtual status_t startRecording(); + virtual void stopRecording(); + virtual bool recordingEnabled(); + virtual void releaseRecordingFrame(const void *opaque); + + virtual status_t autoFocus(); + virtual status_t cancelAutoFocus(); + virtual status_t takePicture(); + virtual status_t cancelPicture(); + virtual status_t dump(int fd) const; + virtual status_t setParameters(const CameraParameters& params); + virtual CameraParameters getParameters() const; + virtual status_t sendCommand(int32_t command, int32_t arg1, int32_t arg2); + virtual status_t setPreviewWindow(preview_stream_ops *w); + virtual status_t storeMetaDataInBuffers(bool enable); + virtual void release(); + + inline int getCameraId() const; + + CameraHardwareSec(int cameraId, camera_device_t *dev); + virtual ~CameraHardwareSec(); +private: + status_t startPreviewInternal(); + void stopPreviewInternal(); + + class PreviewThread : public Thread { + CameraHardwareSec *mHardware; + public: + PreviewThread(CameraHardwareSec *hw): + Thread(false), + mHardware(hw) { } + virtual void onFirstRef() { + run("CameraPreviewThread", PRIORITY_URGENT_DISPLAY); + } + virtual bool threadLoop() { + mHardware->previewThreadWrapper(); + return false; + } + }; + + class PictureThread : public Thread { + CameraHardwareSec *mHardware; + public: + PictureThread(CameraHardwareSec *hw): + Thread(false), + mHardware(hw) { } + virtual bool threadLoop() { + mHardware->pictureThread(); + return false; + } + }; + + class AutoFocusThread : public Thread { + CameraHardwareSec *mHardware; + public: + AutoFocusThread(CameraHardwareSec *hw): Thread(false), mHardware(hw) { } + virtual void onFirstRef() { + run("CameraAutoFocusThread", PRIORITY_DEFAULT); + } + virtual bool threadLoop() { + mHardware->autoFocusThread(); + return true; + } + }; + + void initDefaultParameters(int cameraId); + void initHeapLocked(); + + sp mPreviewThread; + int previewThread(); + int previewThreadWrapper(); + + sp mAutoFocusThread; + int autoFocusThread(); + + sp mPictureThread; + int pictureThread(); + bool mCaptureInProgress; + + int save_jpeg(unsigned char *real_jpeg, int jpeg_size); + void save_postview(const char *fname, uint8_t *buf, + uint32_t size); + int decodeInterleaveData(unsigned char *pInterleaveData, + int interleaveDataSize, + int yuvWidth, + int yuvHeight, + int *pJpegSize, + void *pJpegData, + void *pYuvData); + bool YUY2toNV21(void *srcBuf, void *dstBuf, uint32_t srcWidth, uint32_t srcHeight); + bool scaleDownYuv422(char *srcBuf, uint32_t srcWidth, + uint32_t srcHight, char *dstBuf, + uint32_t dstWidth, uint32_t dstHight); + + bool CheckVideoStartMarker(unsigned char *pBuf); + bool CheckEOIMarker(unsigned char *pBuf); + bool FindEOIMarkerInJPEG(unsigned char *pBuf, + int dwBufSize, int *pnJPEGsize); + bool SplitFrame(unsigned char *pFrame, int dwSize, + int dwJPEGLineLength, int dwVideoLineLength, + int dwVideoHeight, void *pJPEG, + int *pdwJPEGSize, void *pVideo, + int *pdwVideoSize); + void setSkipFrame(int frame); + bool isSupportedPreviewSize(const int width, + const int height) const; + bool getVideosnapshotSize(int *width, int *height); + /* used by auto focus thread to block until it's told to run */ + mutable Mutex mFocusLock; + mutable Condition mFocusCondition; + bool mExitAutoFocusThread; + int mTouched; + + /* used by preview thread to block until it's told to run */ + mutable Mutex mPreviewLock; + mutable Condition mPreviewCondition; + mutable Condition mPreviewStoppedCondition; + bool mPreviewRunning; + bool mPreviewStartDeferred; + bool mExitPreviewThread; + + preview_stream_ops *mPreviewWindow; + + /* used to guard threading state */ + mutable Mutex mStateLock; + + enum PREVIEW_FMT { + PREVIEW_FMT_1_PLANE = 0, + PREVIEW_FMT_2_PLANE, + PREVIEW_FMT_3_PLANE, + }; + + int mPreviewFmtPlane; + + CameraParameters mParameters; + CameraParameters mInternalParameters; + + int mFrameSizeDelta; + camera_memory_t *mPreviewHeap; + camera_memory_t *mRawHeap; + sp mPostviewHeap[CAP_BUFFERS]; + sp mThumbnailHeap; + camera_memory_t *mRecordHeap[BUFFER_COUNT_FOR_ARRAY]; + + camera_frame_metadata_t *mFaceData; + camera_memory_t *mFaceDataHeap; + + buffer_handle_t *mBufferHandle[BUFFER_COUNT_FOR_ARRAY]; + int mStride[BUFFER_COUNT_FOR_ARRAY]; + + + SecCamera *mSecCamera; + const __u8 *mCameraSensorName; + bool mUseInternalISP; + + mutable Mutex mSkipFrameLock; + int mSkipFrame; + + camera_notify_callback mNotifyCb; + camera_data_callback mDataCb; + camera_data_timestamp_callback mDataCbTimestamp; + camera_request_memory mGetMemoryCb; + void *mCallbackCookie; + + int32_t mMsgEnabled; + + bool mRecordRunning; + bool mRecordHint; + mutable Mutex mRecordLock; + int mPostViewWidth; + int mPostViewHeight; + int mPostViewSize; + struct SecBuffer mCapBuffer; + int mCapIndex; + int mCameraID; + + Vector mSupportedPreviewSizes; + + camera_device_t *mHalDevice; + static gralloc_module_t const* mGrallocHal; +}; + +}; // namespace android + +#endif diff --git a/exynos4/hal/libfimc/Android.mk b/exynos4/hal/libfimc/Android.mk new file mode 100644 index 0000000..624d39e --- /dev/null +++ b/exynos4/hal/libfimc/Android.mk @@ -0,0 +1,55 @@ +# Copyright (C) 2008 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +ifeq ($(filter-out exynos4,$(TARGET_BOARD_PLATFORM)),) + +LOCAL_PATH:= $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_PRELINK_MODULE := false +LOCAL_SHARED_LIBRARIES := liblog libutils libcutils +ifeq ($(BOARD_SUPPORT_SYSMMU),true) +LOCAL_SHARED_LIBRARIES+= libMali +endif + +ifeq ($(BOARD_SUPPORT_SYSMMU),true) +LOCAL_CFLAGS+=-DBOARD_SUPPORT_SYSMMU +endif + +ifeq ($(TARGET_SOC),exynos4210) +LOCAL_CFLAGS += -DSAMSUNG_EXYNOS4210 +endif + +ifeq ($(TARGET_SOC),exynos4x12) +LOCAL_CFLAGS += -DSAMSUNG_EXYNOS4x12 +endif + +ifeq ($(BOARD_USE_V4L2),true) +LOCAL_CFLAGS += -DBOARD_USE_V4L2 +endif + +LOCAL_CFLAGS += \ + -DDEFAULT_FB_NUM=$(DEFAULT_FB_NUM) + +LOCAL_C_INCLUDES := \ + $(LOCAL_PATH)/../include \ + framework/base/include + +LOCAL_SRC_FILES := SecFimc.cpp + +LOCAL_MODULE_TAGS := eng +LOCAL_MODULE := libfimc +include $(BUILD_SHARED_LIBRARY) + +endif diff --git a/exynos4/hal/libfimc/SecFimc.cpp b/exynos4/hal/libfimc/SecFimc.cpp new file mode 100644 index 0000000..ab744a2 --- /dev/null +++ b/exynos4/hal/libfimc/SecFimc.cpp @@ -0,0 +1,1701 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * Copyright@ Samsung Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/*! + * \file SecFimc.cpp + * \brief source file for Fimc HAL MODULE + * \author Hyunkyung, Kim(hk310.kim@samsung.com) + * \date 2010/10/13 + * + * Revision History: + * - 2010/10/13 : Hyunkyung, Kim(hk310.kim@samsung.com) \n + * Initial version + * + * - 2011/11/15 : Sunmi, Lee(carrotsm.lee@samsung.com) \n + * Adjust V4L2 architecture \n + */ + +#define LOG_TAG "libfimc" +#include + +#include "SecFimc.h" + +#define FIMC2_DEV_NAME "/dev/video2" + +//#define DEBUG_LIB_FIMC + +#ifdef BOARD_USE_V4L2 +#define V4L2_BUF_TYPE_OUTPUT V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE +#define V4L2_BUF_TYPE_CAPTURE V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE +#define V4L2_ROTATE V4L2_CID_ROTATE +#else +#define V4L2_BUF_TYPE_OUTPUT V4L2_BUF_TYPE_VIDEO_OUTPUT +#define V4L2_BUF_TYPE_CAPTURE V4L2_BUF_TYPE_VIDEO_CAPTURE +#define V4L2_ROTATE V4L2_CID_ROTATION +#endif + +#define V4L2_BUF_TYPE_SRC V4L2_BUF_TYPE_OUTPUT +#define V4L2_MEMORY_TYPE_SRC V4L2_MEMORY_USERPTR +#ifdef BOARD_USE_V4L2 +#define V4L2_BUF_TYPE_DST V4L2_BUF_TYPE_CAPTURE +#define V4L2_MEMORY_TYPE_DST V4L2_MEMORY_MMAP +#else +#define V4L2_BUF_TYPE_DST V4L2_BUF_TYPE_VIDEO_OVERLAY +#define V4L2_MEMORY_TYPE_DST V4L2_MEMORY_USERPTR +#endif + +struct yuv_fmt_list yuv_list[] = { + { "V4L2_PIX_FMT_NV12", "YUV420/2P/LSB_CBCR", V4L2_PIX_FMT_NV12, 12, 2 }, +#ifdef BOARD_USE_V4L2 + { "V4L2_PIX_FMT_NV12M", "YUV420/2P/LSB_CBCR", V4L2_PIX_FMT_NV12M, 12, 2 }, + { "V4L2_PIX_FMT_NV12MT", "YUV420/2P/LSB_CBCR", V4L2_PIX_FMT_NV12MT, 12, 2 }, +#endif + { "V4L2_PIX_FMT_NV12T", "YUV420/2P/LSB_CBCR", V4L2_PIX_FMT_NV12T, 12, 2 }, + { "V4L2_PIX_FMT_NV21", "YUV420/2P/LSB_CRCB", V4L2_PIX_FMT_NV21, 12, 2 }, + { "V4L2_PIX_FMT_NV21X", "YUV420/2P/MSB_CBCR", V4L2_PIX_FMT_NV21X, 12, 2 }, + { "V4L2_PIX_FMT_NV12X", "YUV420/2P/MSB_CRCB", V4L2_PIX_FMT_NV12X, 12, 2 }, +#ifdef BOARD_USE_V4L2 + { "V4L2_PIX_FMT_YUV420M", "YUV420/3P", V4L2_PIX_FMT_YUV420M, 12, 3 }, +#endif + { "V4L2_PIX_FMT_YUV420", "YUV420/3P", V4L2_PIX_FMT_YUV420, 12, 3 }, + { "V4L2_PIX_FMT_YUYV", "YUV422/1P/YCBYCR", V4L2_PIX_FMT_YUYV, 16, 1 }, + { "V4L2_PIX_FMT_YVYU", "YUV422/1P/YCRYCB", V4L2_PIX_FMT_YVYU, 16, 1 }, + { "V4L2_PIX_FMT_UYVY", "YUV422/1P/CBYCRY", V4L2_PIX_FMT_UYVY, 16, 1 }, + { "V4L2_PIX_FMT_VYUY", "YUV422/1P/CRYCBY", V4L2_PIX_FMT_VYUY, 16, 1 }, + { "V4L2_PIX_FMT_UV12", "YUV422/2P/LSB_CBCR", V4L2_PIX_FMT_NV16, 16, 2 }, + { "V4L2_PIX_FMT_UV21", "YUV422/2P/LSB_CRCB", V4L2_PIX_FMT_NV61, 16, 2 }, + { "V4L2_PIX_FMT_UV12X", "YUV422/2P/MSB_CBCR", V4L2_PIX_FMT_NV16X, 16, 2 }, + { "V4L2_PIX_FMT_UV21X", "YUV422/2P/MSB_CRCB", V4L2_PIX_FMT_NV61X, 16, 2 }, + { "V4L2_PIX_FMT_YUV422P", "YUV422/3P", V4L2_PIX_FMT_YUV422P, 16, 3 }, +}; + +#ifdef BOARD_USE_V4L2 +void dump_pixfmt_mp(struct v4l2_pix_format_mplane *pix_mp) +{ + LOGI("w: %d", pix_mp->width); + LOGI("h: %d", pix_mp->height); + LOGI("color: %x", pix_mp->colorspace); + + switch (pix_mp->pixelformat) { + case V4L2_PIX_FMT_YUYV: + LOGI ("YUYV"); + break; + case V4L2_PIX_FMT_UYVY: + LOGI ("UYVY"); + break; + case V4L2_PIX_FMT_RGB565: + LOGI ("RGB565"); + break; + case V4L2_PIX_FMT_RGB565X: + LOGI ("RGB565X"); + break; + default: + LOGI("not supported"); + } +} +#endif + +void dump_pixfmt(struct v4l2_pix_format *pix) +{ + LOGI("w: %d", pix->width); + LOGI("h: %d", pix->height); + LOGI("color: %x", pix->colorspace); + + switch (pix->pixelformat) { + case V4L2_PIX_FMT_YUYV: + LOGI ("YUYV"); + break; + case V4L2_PIX_FMT_UYVY: + LOGI ("UYVY"); + break; + case V4L2_PIX_FMT_RGB565: + LOGI ("RGB565"); + break; + case V4L2_PIX_FMT_RGB565X: + LOGI ("RGB565X"); + break; + default: + LOGI("not supported"); + } +} + +void dump_crop(struct v4l2_crop *crop) +{ + LOGI("crop l: %d", crop->c.left); + LOGI("crop t: %d", crop->c.top); + LOGI("crop w: %d", crop->c.width); + LOGI("crop h: %d", crop->c.height); +} + +void dump_window(struct v4l2_window *win) +{ + LOGI("window l: %d", win->w.left); + LOGI("window t: %d", win->w.top); + LOGI("window w: %d", win->w.width); + LOGI("window h: %d", win->w.height); +} + +void v4l2_overlay_dump_state(int fd) +{ + struct v4l2_format format; + struct v4l2_crop crop; + + format.type = V4L2_BUF_TYPE_OUTPUT; + if (ioctl(fd, VIDIOC_G_FMT, &format) < 0) + return; + + LOGI("dumping driver state:"); +#ifdef BOARD_USE_V4L2 + dump_pixfmt_mp(&format.fmt.pix_mp); +#else + dump_pixfmt(&format.fmt.pix); +#endif + + crop.type = format.type; + if (ioctl(fd, VIDIOC_G_CROP, &crop) < 0) + return; + + LOGI("input window(crop):"); + dump_crop(&crop); + + crop.type = V4L2_BUF_TYPE_CAPTURE; + if (ioctl(fd, VIDIOC_G_CROP, &crop) < 0) + return; + + LOGI("output crop:"); + dump_crop(&crop); + +} + +int fimc_v4l2_query_buf(int fd, SecBuffer *secBuf, enum v4l2_buf_type type, enum v4l2_memory memory, int buf_index, int num_plane) +{ + struct v4l2_buffer buf; + memset(&buf, 0, sizeof(struct v4l2_buffer)); + +#ifdef BOARD_USE_V4L2 + struct v4l2_plane planes[MAX_PLANES]; + for (int i = 0; i < MAX_PLANES; i++) + memset(&planes[i], 0, sizeof(struct v4l2_plane)); +#endif + + if (MAX_DST_BUFFERS <= buf_index || MAX_PLANES <= num_plane) { + LOGE("%s::exceed MAX! : buf_index=%d, num_plane=%d", __func__, buf_index, num_plane); + return -1; + } + + buf.type = type; + buf.memory = V4L2_MEMORY_MMAP; + buf.index = buf_index; +#ifdef BOARD_USE_V4L2 + buf.m.planes = planes; + buf.length = num_plane; +#endif + + if (ioctl(fd, VIDIOC_QUERYBUF, &buf) < 0) { + LOGE("%s::VIDIOC_QUERYBUF failed, plane_cnt=%d", __func__, buf.length); + return -1; + } + +#ifdef BOARD_USE_V4L2 + for (int i = 0; i < num_plane; i++) { + secBuf->phys.extP[i] = (unsigned int)buf.m.planes[i].cookie; + secBuf->size.extS[i] = buf.m.planes[i].length; + + if ((secBuf->virt.extP[i] = (char *)mmap(0, buf.m.planes[i].length, + PROT_READ | PROT_WRITE, MAP_SHARED, fd, buf.m.planes[i].m.mem_offset)) < 0) { + LOGE("%s::mmap failed", __func__); + LOGE("%s::Offset = 0x%x", __func__, buf.m.planes[i].m.mem_offset); + LOGE("%s::Legnth = %d" , __func__, buf.m.planes[i].length); + LOGE("%s::vaddr[%d][%d] = 0x%x", __func__, buf_index, i, (unsigned int)secBuf->virt.extP[i]); + LOGE("%s::paddr[%d][%d] = 0x%x", __func__, buf_index, i, (unsigned int)secBuf->phys.extP[i]); + return -1; + } + } +#else + secBuf->size.s = buf.length; + + if ((secBuf->virt.p = (char *)mmap(0, buf.length, + PROT_READ | PROT_WRITE, MAP_SHARED, fd, buf.m.offset)) < 0) { + LOGE("%s::mmap failed", __func__); + return -1; + } + LOGI("%s::buffers[%d] vaddr = 0x%x", __func__, buf_index, (unsigned int)secBuf->virt.p); +#endif + + return 0; +} + +int fimc_v4l2_req_buf(int fd, unsigned int num_bufs, enum v4l2_buf_type type, enum v4l2_memory memory) +{ + struct v4l2_requestbuffers reqbuf; + + reqbuf.type = type; + reqbuf.memory = memory; + reqbuf.count = num_bufs; + + if (ioctl(fd, VIDIOC_REQBUFS, &reqbuf) < 0) { + LOGE("%s::VIDIOC_REQBUFS failed", __func__); + return -1; + } + +#ifdef DEBUG_LIB_FIMC + LOGI("%d buffers allocated %d requested", reqbuf.count, 4); +#endif + + if (reqbuf.count < num_bufs) { + LOGE("%s::VIDIOC_REQBUFS failed ((reqbuf.count(%d) < num_bufs(%d))", + __func__, reqbuf.count, num_bufs); + return -1; + } + + return 0; +} + +int fimc_v4l2_s_ctrl(int fd, int id, int value) +{ + struct v4l2_control vc; + vc.id = id; + vc.value = value; + + if (ioctl(fd, VIDIOC_S_CTRL, &vc) < 0) { + LOGE("%s::VIDIOC_S_CTRL (id=%d,value=%d) failed", __func__, id, value); + return -1; + } + + return 0; +} + +int fimc_v4l2_set_fmt(int fd, enum v4l2_buf_type type, enum v4l2_field field, s5p_fimc_img_info *img_info, unsigned int addr) +{ + struct v4l2_framebuffer fbuf; + struct v4l2_format fmt; + struct v4l2_crop crop; + struct fimc_buf fimc_dst_buf; + struct v4l2_control vc; + + fmt.type = type; + if (ioctl(fd, VIDIOC_G_FMT, &fmt) < 0) { + LOGE("%s::VIDIOC_G_FMT failed", __func__); + return -1; + } + + switch (fmt.type) { + case V4L2_BUF_TYPE_VIDEO_OUTPUT: + case V4L2_BUF_TYPE_VIDEO_CAPTURE: + fmt.fmt.pix.width = img_info->full_width; + fmt.fmt.pix.height = img_info->full_height; + fmt.fmt.pix.pixelformat = img_info->color_space; + fmt.fmt.pix.field = field; + break; +#ifdef BOARD_USE_V4L2 + case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: + case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: + fmt.fmt.pix_mp.width = img_info->full_width; + fmt.fmt.pix_mp.height = img_info->full_height; + fmt.fmt.pix_mp.pixelformat = img_info->color_space; + fmt.fmt.pix_mp.field = field; + fmt.fmt.pix_mp.num_planes = img_info->planes; + break; +#endif + case V4L2_BUF_TYPE_VIDEO_OVERLAY: + if (ioctl(fd, VIDIOC_G_FBUF, &fbuf) < 0) { + LOGE("%s::VIDIOC_G_FBUF failed", __func__); + return -1; + } + + fbuf.base = (void *)addr; + fbuf.fmt.width = img_info->full_width; + fbuf.fmt.height = img_info->full_height; + fbuf.fmt.pixelformat = img_info->color_space; + + if (ioctl(fd, VIDIOC_S_FBUF, &fbuf) < 0) { + LOGE("%s::VIDIOC_S_FBUF (w=%d, h=%d, color=%d) failed", + __func__, + img_info->full_width, + img_info->full_height, + img_info->color_space); + return -1; + } + + fimc_dst_buf.base[0] = (unsigned int)img_info->buf_addr_phy_rgb_y; + fimc_dst_buf.base[1] = (unsigned int)img_info->buf_addr_phy_cb; + fimc_dst_buf.base[2] = (unsigned int)img_info->buf_addr_phy_cr; + + vc.id = V4L2_CID_DST_INFO; + vc.value = (unsigned int)&fimc_dst_buf.base[0]; + + if (ioctl(fd, VIDIOC_S_CTRL, &vc) < 0) { + LOGE("%s::VIDIOC_S_CTRL (id=%d,value=%d) failed", __func__, vc.id, vc.value); + return -1; + } + + fmt.fmt.win.w.left = img_info->start_x; + fmt.fmt.win.w.top = img_info->start_y; + fmt.fmt.win.w.width = img_info->width; + fmt.fmt.win.w.height = img_info->height; + break; + default: + LOGE("invalid buffer type"); + return -1; + break; + } + + if (ioctl(fd, VIDIOC_S_FMT, &fmt) < 0) { + LOGE("%s::VIDIOC_S_FMT failed", __func__); + return -1; + } + + if (fmt.type != V4L2_BUF_TYPE_VIDEO_OVERLAY) { + crop.type = type; + crop.c.left = img_info->start_x; + crop.c.top = img_info->start_y; + crop.c.width = img_info->width; + crop.c.height = img_info->height; + + if (ioctl(fd, VIDIOC_S_CROP, &crop) < 0) { + LOGE("%s::VIDIOC_S_CROP (x=%d, y=%d, w=%d, h=%d) failed", + __func__, + img_info->start_x, + img_info->start_y, + img_info->width, + img_info->height); + return -1; + } + } + + return 0; +} + +int fimc_v4l2_stream_on(int fd, enum v4l2_buf_type type) +{ + if (ioctl(fd, VIDIOC_STREAMON, &type) < 0) { + LOGE("%s::VIDIOC_STREAMON failed", __func__); + return -1; + } + + return 0; +} + +int fimc_v4l2_queue(int fd, SecBuffer *secBuf, enum v4l2_buf_type type, enum v4l2_memory memory, int index, int num_plane) +{ + struct v4l2_buffer buf; + memset(&buf, 0, sizeof(struct v4l2_buffer)); + +#ifdef BOARD_USE_V4L2 + struct v4l2_plane planes[MAX_PLANES]; + for (int i = 0; i < MAX_PLANES; i++) + memset(&planes[i], 0, sizeof(struct v4l2_plane)); +#else + struct fimc_buf fimcbuf; +#endif + + buf.type = type; + buf.memory = memory; + buf.length = num_plane; + buf.index = index; +#ifdef BOARD_USE_V4L2 + buf.m.planes = planes; + + for (unsigned int i = 0; i < buf.length; i++) { + buf.m.planes[i].length = secBuf->size.extS[i]; + buf.m.planes[i].m.userptr = (unsigned long)secBuf->phys.extP[i]; + } +#else + for (int i = 0; i < 3 ; i++) { + fimcbuf.base[i] = secBuf->phys.extP[i]; + fimcbuf.length[i] = secBuf->size.extS[i]; + } + + buf.m.userptr = (unsigned long)(&fimcbuf); + //buf.m.userptr = secBuf->phys.p; +#endif + + if (ioctl(fd, VIDIOC_QBUF, &buf) < 0) { + LOGE("%s::VIDIOC_QBUF failed", __func__); + return -1; + } + + return 0; +} + +int fimc_v4l2_dequeue(int fd, enum v4l2_buf_type type, enum v4l2_memory memory, int *index, int num_plane) +{ + struct v4l2_buffer buf; + memset(&buf, 0, sizeof(struct v4l2_buffer)); + +#ifdef BOARD_USE_V4L2 + struct v4l2_plane planes[MAX_PLANES]; + for (int i = 0; i < MAX_PLANES; i++) + memset(&planes[i], 0, sizeof(struct v4l2_plane)); +#endif + + buf.type = type; + buf.memory = memory; + buf.length = num_plane; +#ifdef BOARD_USE_V4L2 + buf.m.planes = planes; +#endif + if (ioctl(fd, VIDIOC_DQBUF, &buf) < 0) { + LOGE("%s::VIDIOC_DQBUF failed", __func__); + return -1; + } + *index = buf.index; + + return 0; +} + +int fimc_v4l2_stream_off(int fd, enum v4l2_buf_type type) +{ + if (ioctl(fd, VIDIOC_STREAMOFF, &type) < 0) { + LOGE("%s::VIDIOC_STREAMOFF failed", __func__); + return -1; + } + + return 0; +} + +int fimc_v4l2_clr_buf(int fd, enum v4l2_buf_type type, enum v4l2_memory memory) +{ + struct v4l2_requestbuffers req; + + req.count = 0; + req.type = type; + req.memory = memory; + + if (ioctl(fd, VIDIOC_REQBUFS, &req) < 0) { + LOGE("%s::VIDIOC_REQBUFS", __func__); + return -1; + } + + return 0; +} + +static inline int multipleOfN(int number, int N) +{ + int result = number; + switch (N) { + case 1: + case 2: + case 4: + case 8: + case 16: + case 32: + case 64: + case 128: + case 256: + result = (number - (number & (N-1))); + break; + default: + result = number - (number % N); + break; + } + return result; +} + +extern "C" SecFimc* create_instance() +{ + return new SecFimc; +} + +extern "C" void destroy_instance(SecFimc* handle) +{ + if (handle != NULL) + delete handle; +} + +SecFimc::SecFimc() +: mFlagCreate(false) +{ + memset(&mFimcCap, 0, sizeof(struct v4l2_capability)); + memset(&mS5pFimc, 0, sizeof(s5p_fimc_t)); + + mRotVal = 0; + mRealDev = -1; + mNumOfBuf = 0; + mHwVersion = 0; + mGlobalAlpha = 0x0; + mFlagStreamOn = false; + mFlagSetSrcParam = false; + mFlagSetDstParam = false; + mFlagGlobalAlpha = false; + mFlagLocalAlpha = false; + mFlagColorKey = false; + mFimcMode = 0; + mFd = 0; + mDev = 0; + mColorKey = 0x0; +} + +SecFimc::~SecFimc() +{ + if (mFlagCreate == true) { + LOGE("%s::this is not Destroyed fail", __func__); + if (destroy() == false) + LOGE("%s::destroy failed", __func__); + } +} + +bool SecFimc::create(enum DEV dev, enum MODE mode, int numOfBuf) +{ + if (mFlagCreate == true) { + LOGE("%s::Already Created fail", __func__); + return false; + } + + char node[20]; + struct v4l2_format fmt; + struct v4l2_control vc; + SecBuffer zeroBuf; + + mDev = dev; + mRealDev = dev; + + switch (mode) { + case MODE_SINGLE_BUF: + mFimcMode = FIMC_OVLY_NONE_SINGLE_BUF; + break; + case MODE_MULTI_BUF: + mFimcMode = FIMC_OVLY_NONE_MULTI_BUF; + break; + case MODE_DMA_AUTO: + mFimcMode = FIMC_OVLY_DMA_AUTO; + break; + default: + LOGE("%s::Invalid mode(%d) fail", __func__, mode); + mFimcMode = FIMC_OVLY_NOT_FIXED; + goto err; + break; + } + + mNumOfBuf = numOfBuf; + + for (int i = 0; i < MAX_DST_BUFFERS; i++) + mDstBuffer[i] = zeroBuf; + +#ifdef BOARD_USE_V4L2 + switch(mDev) { + case DEV_0: + mRealDev = 0; + break; + case DEV_1: + mRealDev = 2; + break; + case DEV_2: + mRealDev = 4; + break; + case DEV_3: + mRealDev = 5; + break; + default: + LOGE("%s::invalid mDev(%d)", __func__, mDev); + goto err; + break; + } +#endif + + sprintf(node, "%s%d", PFX_NODE_FIMC, (int)mRealDev); + + mFd = open(node, O_RDWR); + if (mFd < 0) { + LOGE("%s::open(%s) failed", __func__, node); + mFd = 0; + goto err; + } + + /* check capability */ + if (ioctl(mFd, VIDIOC_QUERYCAP, &mFimcCap) < 0) { + LOGE("%s::VIDIOC_QUERYCAP failed", __func__); + goto err; + } + + if (!(mFimcCap.capabilities & V4L2_CAP_STREAMING)) { + LOGE("%s::%s has no streaming support", __func__, node); + goto err; + } + +#ifdef BOARD_USE_V4L2 + if (!(mFimcCap.capabilities & V4L2_CAP_VIDEO_OUTPUT_MPLANE)) { + LOGE("%s::%s is no video output mplane", __func__, node); + goto err; + } + + if (!(mFimcCap.capabilities & V4L2_CAP_VIDEO_CAPTURE_MPLANE)) { + LOGE("%s::%s is no video capture mplane", __func__, node); + goto err; + } +#else + if (!(mFimcCap.capabilities & V4L2_CAP_VIDEO_OUTPUT)) { + LOGE("%s::%s is no video output", __func__, node); + goto err; + } + + fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT; + if (ioctl(mFd, VIDIOC_G_FMT, &fmt) < 0) { + LOGE("%s::VIDIOC_G_FMT failed", __func__); + goto err; + } + + vc.id = V4L2_CID_RESERVED_MEM_BASE_ADDR; + vc.value = 0; + if (ioctl(mFd, VIDIOC_G_CTRL, &vc) < 0) { + LOGE("%s::VIDIOC_G_CTRL - V4L2_CID_RESERVED_MEM_BAES_ADDR", __func__); + goto err; + } + + mDstBuffer[0].phys.p = (unsigned int)vc.value; + + mS5pFimc.out_buf.phys_addr = (void *)mDstBuffer[0].phys.p; + + vc.id = V4L2_CID_FIMC_VERSION; + vc.value = 0; + if (ioctl(mFd, VIDIOC_G_CTRL, &vc) < 0) { + LOGE("%s::VIDIOC_G_CTRL - V4L2_CID_FIMC_VERSION failed, FIMC version is set with default", __func__); + vc.value = 0x43; + } + + mHwVersion = vc.value; + + vc.id = V4L2_CID_OVLY_MODE; + vc.value = mFimcMode; + if (ioctl(mFd, VIDIOC_S_CTRL, &vc) < 0) { + LOGE("%s::VIDIOC_S_CTRL - V4L2_CID_OVLY_MODE failed", __func__); + goto err; + } +#endif + + mFlagCreate = true; + + return true; + +err : + if (0 < mFd) + close(mFd); + mFd = 0; + + return false; +} + +bool SecFimc::destroy() +{ + s5p_fimc_params_t *params = &(mS5pFimc.params); + + if (mFlagCreate == false) { + LOGE("%s::Already Destroyed fail", __func__); + return false; + } + + if (mFlagStreamOn == true) { + if (fimc_v4l2_stream_off(mFd, V4L2_BUF_TYPE_SRC) < 0) { + LOGE("%s::fimc_v4l2_stream_off() failed", __func__); + return false; + } +#ifdef BOARD_USE_V4L2 + if (fimc_v4l2_stream_off(mFd, V4L2_BUF_TYPE_DST) < 0) { + LOGE("%s::fimc_v4l2_stream_off() failed", __func__); + return false; + } +#endif + mFlagStreamOn = false; + } + + if (fimc_v4l2_clr_buf(mFd, V4L2_BUF_TYPE_SRC, V4L2_MEMORY_TYPE_SRC) < 0) { + LOGE("%s::fimc_v4l2_clr_buf()[src] failed", __func__); + return false; + } + +#ifdef BOARD_USE_V4L2 + if (fimc_v4l2_clr_buf(mFd, V4L2_BUF_TYPE_DST, V4L2_MEMORY_TYPE_DST) < 0) { + LOGE("%s::fimc_v4l2_clr_buf()[dst] failed", __func__); + return false; + } +#endif + if (mS5pFimc.out_buf.phys_addr != NULL) { + mS5pFimc.out_buf.phys_addr = NULL; + mS5pFimc.out_buf.length = 0; + } + + if (0 < mFd) + close(mFd); + mFd = 0; + + mFlagCreate = false; + + return true; +} + +bool SecFimc::flagCreate(void) +{ + return mFlagCreate; +} + +int SecFimc::getFd(void) +{ + return mFd; +} + +SecBuffer * SecFimc::getMemAddr(int index) +{ + if (mFlagCreate == false) { + LOGE("%s::Not yet created", __func__); + return false; + } + + return &mDstBuffer[index]; +} + +int SecFimc::getHWVersion(void) +{ + if (mFlagCreate == false) { + LOGE("%s::Not yet created", __func__); + return false; + } + + return mHwVersion; +} + +bool SecFimc::setSrcParams(unsigned int width, unsigned int height, + unsigned int cropX, unsigned int cropY, + unsigned int *cropWidth, unsigned int *cropHeight, + int colorFormat, + bool forceChange) +{ +#ifdef DEBUG_LIB_FIMC + LOGD("%s", __func__); +#endif + + if (mFlagCreate == false) { + LOGE("%s::Not yet created", __func__); + return false; + } + + int v4l2ColorFormat = HAL_PIXEL_FORMAT_2_V4L2_PIX(colorFormat); + if (v4l2ColorFormat < 0) { + LOGE("%s::not supported color format", __func__); + return false; + } + + s5p_fimc_params_t *params = &(mS5pFimc.params); + + unsigned int fimcWidth = *cropWidth; + unsigned int fimcHeight = *cropHeight; + int src_planes = m_getYuvPlanes(v4l2ColorFormat); + + m_checkSrcSize(width, height, + cropX, cropY, + &fimcWidth, &fimcHeight, + v4l2ColorFormat, + false); + + if (fimcWidth != *cropWidth || fimcHeight != *cropHeight) { + if (forceChange == true) { +#ifdef DEBUG_LIB_FIMC + LOGD("size is changed from [w = %d, h= %d] to [w = %d, h = %d]", + *cropWidth, *cropHeight, fimcWidth, fimcHeight); +#endif + } else { + LOGE("%s::invalid source params", __func__); + return false; + } + } + + if ( (params->src.full_width == width) + && (params->src.full_height == height) + && (params->src.start_x == cropX) + && (params->src.start_y == cropY) + && (params->src.width == fimcWidth) + && (params->src.height == fimcHeight) + && (params->src.color_space == (unsigned int)v4l2ColorFormat)) + return true; + + params->src.full_width = width; + params->src.full_height = height; + params->src.start_x = cropX; + params->src.start_y = cropY; + params->src.width = fimcWidth; + params->src.height = fimcHeight; + params->src.color_space = v4l2ColorFormat; + src_planes = (src_planes == -1) ? 1 : src_planes; + + if (mFlagSetSrcParam == true) { + if (fimc_v4l2_clr_buf(mFd, V4L2_BUF_TYPE_SRC, V4L2_MEMORY_TYPE_SRC) < 0) { + LOGE("%s::fimc_v4l2_clr_buf_src() failed", __func__); + return false; + } + } + + if (fimc_v4l2_set_fmt(mFd, V4L2_BUF_TYPE_SRC, V4L2_FIELD_NONE, &(params->src), 0) < 0) { + LOGE("%s::fimc_v4l2_set_fmt()[src] failed", __func__); + return false; + } + + if (fimc_v4l2_req_buf(mFd, 1, V4L2_BUF_TYPE_SRC, V4L2_MEMORY_TYPE_SRC) < 0) { + LOGE("%s::fimc_v4l2_req_buf()[src] failed", __func__); + return false; + } + + *cropWidth = fimcWidth; + *cropHeight = fimcHeight; + + mFlagSetSrcParam = true; + return true; +} + +bool SecFimc::getSrcParams(unsigned int *width, unsigned int *height, + unsigned int *cropX, unsigned int *cropY, + unsigned int *cropWidth, unsigned int *cropHeight, + int *colorFormat) +{ + struct v4l2_format fmt; + struct v4l2_crop crop; + + fmt.type = V4L2_BUF_TYPE_SRC; + + if (ioctl(mFd, VIDIOC_G_FMT, &fmt) < 0) { + LOGE("%s::VIDIOC_G_FMT(fmt.type : %d) failed", __func__, fmt.type); + return false; + } + + switch (fmt.type) { + case V4L2_BUF_TYPE_VIDEO_OUTPUT: + case V4L2_BUF_TYPE_VIDEO_CAPTURE: + case V4L2_BUF_TYPE_VIDEO_OVERLAY: + *width = fmt.fmt.pix.width; + *height = fmt.fmt.pix.height; + *colorFormat = fmt.fmt.pix.pixelformat; + break; +#ifdef BOARD_USE_V4L2 + case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: + case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: + *width = fmt.fmt.pix_mp.width; + *height = fmt.fmt.pix_mp.height; + *colorFormat = fmt.fmt.pix_mp.pixelformat; + break; +#endif + default: + LOGE("%s::Invalid buffer type", __func__); + return false; + break; + } + + crop.type = V4L2_BUF_TYPE_SRC; + if (ioctl(mFd, VIDIOC_G_CROP, &crop) < 0) { + LOGE("%s::VIDIOC_G_CROP failed", __func__); + return false; + } + + *cropX = crop.c.left; + *cropY = crop.c.top; + *cropWidth = crop.c.width; + *cropHeight = crop.c.height; + + return true; +} + +bool SecFimc::setSrcAddr(unsigned int physYAddr, + unsigned int physCbAddr, + unsigned int physCrAddr, + int colorFormat) +{ +#ifdef DEBUG_LIB_FIMC + LOGD("%s", __func__); +#endif + + if (mFlagCreate == false) { + LOGE("%s::Not yet created", __func__); + return false; + } + + s5p_fimc_params_t *params = &(mS5pFimc.params); + int src_planes = m_getYuvPlanes(params->src.color_space); + int src_bpp = m_getYuvBpp(params->src.color_space); + unsigned int frame_size = params->src.full_width * params->src.full_height; + src_planes = (src_planes == -1) ? 1 : src_planes; + + mSrcBuffer.phys.extP[0] = physYAddr; + + if (colorFormat == HAL_PIXEL_FORMAT_YV12) { + mSrcBuffer.phys.extP[1] = physCrAddr; + mSrcBuffer.phys.extP[2] = physCbAddr; + } else { + mSrcBuffer.phys.extP[1] = physCbAddr; + mSrcBuffer.phys.extP[2] = physCrAddr; + } + + if (2 <= src_planes && mSrcBuffer.phys.extP[1] == 0) + mSrcBuffer.phys.extP[1] = mSrcBuffer.phys.extP[0] + frame_size; + + if (3 == src_planes && mSrcBuffer.phys.extP[2] == 0) { + if (colorFormat == HAL_PIXEL_FORMAT_YV12) { + if (12 == src_bpp) + mSrcBuffer.phys.extP[1] = mSrcBuffer.phys.extP[2] + (frame_size >> 2); + else + mSrcBuffer.phys.extP[1] = mSrcBuffer.phys.extP[2] + (frame_size >> 1); + } else { + if (12 == src_bpp) + mSrcBuffer.phys.extP[2] = mSrcBuffer.phys.extP[1] + (frame_size >> 2); + else + mSrcBuffer.phys.extP[2] = mSrcBuffer.phys.extP[1] + (frame_size >> 1); + } + } + + return true; +} + +bool SecFimc::setDstParams(unsigned int width, unsigned int height, + unsigned int cropX, unsigned int cropY, + unsigned int *cropWidth, unsigned int *cropHeight, + int colorFormat, + bool forceChange) +{ +#ifdef DEBUG_LIB_FIMC + LOGD("%s", __func__); +#endif + + if (mFlagCreate == false) { + LOGE("%s::Not yet created", __func__); + return false; + } + + int v4l2ColorFormat = HAL_PIXEL_FORMAT_2_V4L2_PIX(colorFormat); + if (v4l2ColorFormat < 0) { + LOGE("%s::not supported color format", __func__); + return false; + } + + s5p_fimc_params_t *params = &(mS5pFimc.params); + + unsigned int fimcWidth = *cropWidth; + unsigned int fimcHeight = *cropHeight; + int dst_planes = m_getYuvPlanes(v4l2ColorFormat); + + m_checkDstSize(width, height, + cropX, cropY, + &fimcWidth, &fimcHeight, + v4l2ColorFormat, + mRotVal, + true); + + if (fimcWidth != *cropWidth || fimcHeight != *cropHeight) { + if (forceChange == true) { +#ifdef DEBUG_LIB_FIMC + LOGD("size is changed from [w = %d, h= %d] to [w = %d, h = %d]", + *cropWidth, *cropHeight, fimcWidth, fimcHeight); +#endif + } else { + LOGE("%s::Invalid destination params", __func__); + return false; + } + } + + if (90 == mRotVal || 270 == mRotVal) { + params->dst.full_width = height; + params->dst.full_height = width; + + if (90 == mRotVal) { + params->dst.start_x = cropY; + params->dst.start_y = width - (cropX + fimcWidth); + } else { + params->dst.start_x = height - (cropY + fimcHeight); + params->dst.start_y = cropX; + } + + params->dst.width = fimcHeight; + params->dst.height = fimcWidth; + + if (0x50 != mHwVersion) + params->dst.start_y += (fimcWidth - params->dst.height); + + } else { + params->dst.full_width = width; + params->dst.full_height = height; + + if (180 == mRotVal) { + params->dst.start_x = width - (cropX + fimcWidth); + params->dst.start_y = height - (cropY + fimcHeight); + } else { + params->dst.start_x = cropX; + params->dst.start_y = cropY; + } + + params->dst.width = fimcWidth; + params->dst.height = fimcHeight; + } + params->dst.color_space = v4l2ColorFormat; + dst_planes = (dst_planes == -1) ? 1 : dst_planes; + +#ifdef BOARD_USE_V4L2 + if (mFlagSetDstParam == true) { + if (fimc_v4l2_clr_buf(mFd, V4L2_BUF_TYPE_DST, V4L2_MEMORY_TYPE_DST) < 0) { + LOGE("%s::fimc_v4l2_clr_buf_dst() failed", __func__); + return false; + } + } +#endif + + if (fimc_v4l2_s_ctrl(mFd, V4L2_ROTATE, mRotVal) < 0) { + LOGE("%s::fimc_v4l2_s_ctrl(V4L2_ROTATE)", __func__); + return false; + } + + if (fimc_v4l2_set_fmt(mFd, V4L2_BUF_TYPE_DST, V4L2_FIELD_ANY, &(params->dst), (unsigned int)mS5pFimc.out_buf.phys_addr) < 0) { + LOGE("%s::fimc_v4l2_set_fmt()[dst] failed", __func__); + return false; + } + +#ifdef BOARD_USE_V4L2 + if (fimc_v4l2_req_buf(mFd, mNumOfBuf, V4L2_BUF_TYPE_DST, V4L2_MEMORY_TYPE_DST) < 0) { + LOGE("%s::fimc_v4l2_req_buf()[dst] failed", __func__); + return false; + } + + for (int i = 0; i < mNumOfBuf; i++) { + if (fimc_v4l2_query_buf(mFd, &(mDstBuffer[i]), + V4L2_BUF_TYPE_DST, V4L2_MEMORY_TYPE_DST, i, dst_planes) < 0) { + LOGE("%s::fimc_v4l2_query_buf() failed", __func__); + } + } +#endif + + *cropWidth = fimcWidth; + *cropHeight = fimcHeight; + + mFlagSetDstParam = true; + return true; +} + +bool SecFimc::getDstParams(unsigned int *width, unsigned int *height, + unsigned int *cropX, unsigned int *cropY, + unsigned int *cropWidth, unsigned int *cropHeight, + int *colorFormat) +{ + struct v4l2_framebuffer fbuf; + struct v4l2_format fmt; + struct v4l2_crop crop; + + fmt.type = V4L2_BUF_TYPE_DST; + if (ioctl(mFd, VIDIOC_G_FMT, &fmt) < 0) { + LOGE("%s::VIDIOC_G_FMT(fmt.type : %d) failed", __func__, fmt.type); + return false; + } + switch (fmt.type) { + case V4L2_BUF_TYPE_VIDEO_OUTPUT: + case V4L2_BUF_TYPE_VIDEO_CAPTURE: + *width = fmt.fmt.pix.width; + *height = fmt.fmt.pix.height; + *colorFormat = fmt.fmt.pix.pixelformat; + break; +#ifdef BOARD_USE_V4L2 + case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: + case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: + *width = fmt.fmt.pix_mp.width; + *height = fmt.fmt.pix_mp.height; + *colorFormat = fmt.fmt.pix_mp.pixelformat; + break; +#endif + case V4L2_BUF_TYPE_VIDEO_OVERLAY: + *cropX = fmt.fmt.win.w.left; + *cropY = fmt.fmt.win.w.top; + *cropWidth = fmt.fmt.win.w.width; + *cropHeight = fmt.fmt.win.w.height; + + if (ioctl(mFd, VIDIOC_G_FBUF, &fbuf) < 0) { + LOGE("%s::VIDIOC_G_FBUF failed", __func__); + return false; + } + + *width = fbuf.fmt.width; + *height = fbuf.fmt.height; + *colorFormat = fbuf.fmt.pixelformat; + break; + default: + LOGE("%s::Invalid buffer type", __func__); + return false; + break; + } + + if (fmt.type != V4L2_BUF_TYPE_VIDEO_OVERLAY) { + + crop.type = V4L2_BUF_TYPE_DST; + if (ioctl(mFd, VIDIOC_G_CROP, &crop) < 0) { + LOGE("%s::VIDIOC_G_CROP(crop.type : %d) failed", __func__, crop.type); + return false; + } + + *cropX = crop.c.left; + *cropY = crop.c.top; + *cropWidth = crop.c.width; + *cropHeight = crop.c.height; + } + + return true; +} + +bool SecFimc::setDstAddr(unsigned int physYAddr, unsigned int physCbAddr, unsigned int physCrAddr, int buf_index) +{ +#ifdef DEBUG_LIB_FIMC + LOGD("%s", __func__); +#endif + + s5p_fimc_params_t *params = &(mS5pFimc.params); + + if (mFlagCreate == false) { + LOGE("%s::Not yet created", __func__); + return false; + } + + mS5pFimc.out_buf.phys_addr = (void *)physYAddr; + + mDstBuffer[buf_index].phys.extP[0] = physYAddr; + mDstBuffer[buf_index].phys.extP[1] = physCbAddr; + mDstBuffer[buf_index].phys.extP[2] = physCrAddr; + +#ifdef BOARD_USE_V4L2 + if (physYAddr != 0) + mS5pFimc.use_ext_out_mem = 1; +#else + params->dst.buf_addr_phy_rgb_y = physYAddr; + params->dst.buf_addr_phy_cb = physCbAddr; + params->dst.buf_addr_phy_cr = physCrAddr; + + if ((physYAddr != 0) + && ((unsigned int)mS5pFimc.out_buf.phys_addr != mDstBuffer[0].phys.p)) + mS5pFimc.use_ext_out_mem = 1; + + if (fimc_v4l2_s_ctrl(mFd, V4L2_ROTATE, mRotVal) < 0) { + LOGE("%s::fimc_v4l2_s_ctrl(V4L2_ROTATE)", __func__); + return false; + } + + if (fimc_v4l2_set_fmt(mFd, V4L2_BUF_TYPE_DST, V4L2_FIELD_ANY, &(params->dst), (unsigned int)mS5pFimc.out_buf.phys_addr) < 0) { + LOGE("%s::fimc_v4l2_set_fmt()[dst] failed", __func__); + return false; + } +#endif + + return true; +} + +bool SecFimc::setRotVal(unsigned int rotVal) +{ + struct v4l2_control vc; + + if (mFlagCreate == false) { + LOGE("%s::Not yet created", __func__); + return false; + } + + if (fimc_v4l2_s_ctrl(mFd, V4L2_ROTATE, rotVal) < 0) { + LOGE("%s::fimc_v4l2_s_ctrl(V4L2_ROTATE) failed", __func__); + return false; + } + + mRotVal = rotVal; + return true; +} + +bool SecFimc::setGlobalAlpha(bool enable, int alpha) +{ + struct v4l2_framebuffer fbuf; + struct v4l2_format fmt; + + if (mFlagCreate == false) { + LOGE("%s::Not yet created", __func__); + return false; + } + + if (mFlagStreamOn == true) { + LOGE("%s::mFlagStreamOn == true", __func__); + return false; + } + + if (mFlagGlobalAlpha == enable && mGlobalAlpha == alpha) + return true; + + memset(&fbuf, 0, sizeof(fbuf)); + + if (ioctl(mFd, VIDIOC_G_FBUF, &fbuf) < 0) { + LOGE("%s::VIDIOC_G_FBUF failed", __func__); + return false; + } + + if (enable) + fbuf.flags |= V4L2_FBUF_FLAG_GLOBAL_ALPHA; + else + fbuf.flags &= ~V4L2_FBUF_FLAG_GLOBAL_ALPHA; + + if (ioctl(mFd, VIDIOC_S_FBUF, &fbuf) < 0) { + LOGE("%s::VIDIOC_S_FBUF failed", __func__); + return false; + } + + if (enable) { + memset(&fmt, 0, sizeof(fmt)); + fmt.type = V4L2_BUF_TYPE_VIDEO_OVERLAY; + + if (ioctl(mFd, VIDIOC_G_FMT, &fmt) < 0) { + LOGE("%s::VIDIOC_G_FMT failed", __func__); + return false; + } + + fmt.fmt.win.global_alpha = alpha & 0xFF; + if (ioctl(mFd, VIDIOC_S_FMT, &fmt) < 0) { + LOGE("%s::VIDIOC_S_FMT failed", __func__); + return false; + } + } + + mFlagGlobalAlpha = enable; + mGlobalAlpha = alpha; + + return true; + +} + +bool SecFimc::setLocalAlpha(bool enable) +{ + if (mFlagCreate == false) { + LOGE("%s::Not yet created", __func__); + return false; + } + + if (mFlagStreamOn == true) { + LOGE("%s::mFlagStreamOn == true", __func__); + return false; + } + + if (mFlagLocalAlpha == enable) + return true; + + return true; +} + +bool SecFimc::setColorKey(bool enable, int colorKey) +{ + struct v4l2_framebuffer fbuf; + struct v4l2_format fmt; + + if (mFlagCreate == false) { + LOGE("%s::Not yet created", __func__); + return false; + } + + if (mFlagStreamOn == true) { + LOGE("%s::mFlagStreamOn == true", __func__); + return false; + } + + if (mFlagColorKey == enable && mColorKey == colorKey) + return true; + + memset(&fbuf, 0, sizeof(fbuf)); + + if (ioctl(mFd, VIDIOC_G_FBUF, &fbuf) < 0) { + LOGE("%s::VIDIOC_G_FBUF failed", __func__); + return false; + } + + if (enable) + fbuf.flags |= V4L2_FBUF_FLAG_CHROMAKEY; + else + fbuf.flags &= ~V4L2_FBUF_FLAG_CHROMAKEY; + + if (ioctl(mFd, VIDIOC_S_FBUF, &fbuf) < 0) { + LOGE("%s::VIDIOC_S_FBUF failed", __func__); + return false; + } + + if (enable) { + memset(&fmt, 0, sizeof(fmt)); + fmt.type = V4L2_BUF_TYPE_VIDEO_OVERLAY; + + if (ioctl(mFd, VIDIOC_G_FMT, &fmt) < 0) { + LOGE("%s::VIDIOC_G_FMT failed", __func__); + return false; + } + + fmt.fmt.win.chromakey = colorKey & 0xFFFFFF; + + if (ioctl(mFd, VIDIOC_S_FMT, &fmt) < 0) + LOGE("%s::VIDIOC_S_FMT failed", __func__); + } + mFlagColorKey = enable; + mColorKey = colorKey; + return true; +} + +bool SecFimc::draw(int src_index, int dst_index) +{ +#ifdef DEBUG_LIB_FIMC + LOGD("%s", __func__); +#endif + + if (mFlagCreate == false) { + LOGE("%s::Not yet created", __func__); + return false; + } + + if (mFlagSetSrcParam == false) { + LOGE("%s::mFlagSetSrcParam == false fail", __func__); + return false; + } + + if (mFlagSetDstParam == false) { + LOGE("%s::mFlagSetDstParam == false fail", __func__); + return false; + } + + s5p_fimc_params_t *params = &(mS5pFimc.params); + bool flagStreamOn = false; + int src_planes = m_getYuvPlanes(params->src.color_space); + int dst_planes = m_getYuvPlanes(params->dst.color_space); + src_planes = (src_planes == -1) ? 1 : src_planes; + dst_planes = (dst_planes == -1) ? 1 : dst_planes; + +#ifdef BOARD_USE_V4L2 + if (mFlagStreamOn == false) { + if (m_streamOn() == false) { + LOGE("%s::m_streamOn failed", __func__); + return false; + } + mFlagStreamOn = true; + } + if (fimc_v4l2_dequeue(mFd, V4L2_BUF_TYPE_DST, V4L2_MEMORY_TYPE_DST, &dst_index, dst_planes) < 0) { + LOGE("%s::fimc_v4l2_dequeue[dst](mNumOfBuf : %d) failed", __func__, mNumOfBuf); + return false; + } + + if (fimc_v4l2_dequeue(mFd, V4L2_BUF_TYPE_SRC, V4L2_MEMORY_TYPE_SRC, &src_index, src_planes) < 0) { + LOGE("%s::fimc_v4l2_dequeue[src](mNumOfBuf : %d) failed", __func__, mNumOfBuf); + return false; + } + + if (fimc_v4l2_queue(mFd, &(mSrcBuffer), V4L2_BUF_TYPE_SRC, V4L2_MEMORY_TYPE_SRC, src_index, src_planes) < 0) { + LOGE("%s::fimc_v4l2_queue[src](index : %d) (mNumOfBuf : %d) failed", __func__, 0, mNumOfBuf); + return false; + } + + if (fimc_v4l2_queue(mFd, &(mDstBuffer[dst_index]), V4L2_BUF_TYPE_DST, V4L2_MEMORY_TYPE_DST, dst_index, dst_planes) < 0) { + LOGE("%s::fimc_v4l2_queue[dst](index : %d) (mNumOfBuf : %d) failed", __func__, dst_index, mNumOfBuf); + return false; + } +#else + if (fimc_v4l2_stream_on(mFd, V4L2_BUF_TYPE_SRC) < 0) { + LOGE("%s::fimc_v4l2_stream_on() failed", __func__); + goto err; + } + + flagStreamOn = true; + + if (fimc_v4l2_queue(mFd, &(mSrcBuffer), V4L2_BUF_TYPE_SRC, V4L2_MEMORY_TYPE_SRC, src_index, src_planes) < 0) { + LOGE("%s::fimc_v4l2_queue(index : %d) (mNumOfBuf : %d) failed", __func__, 0, mNumOfBuf); + goto err; + } + + if (fimc_v4l2_dequeue(mFd, V4L2_BUF_TYPE_SRC, V4L2_MEMORY_TYPE_SRC, &src_index, src_planes) < 0) { + LOGE("%s::fimc_v4l2_dequeue (mNumOfBuf : %d) failed", __func__, mNumOfBuf); + goto err; + } +#endif + +err : +#ifndef BOARD_USE_V4L2 + if (flagStreamOn == true) { + if (fimc_v4l2_stream_off(mFd, V4L2_BUF_TYPE_SRC) < 0) { + LOGE("%s::fimc_v4l2_stream_off() failed", __func__); + return false; + } + } +#endif + + return true; +} + +bool SecFimc::m_streamOn() +{ +#ifdef DEBUG_LIB_FIMC + LOGD("%s", __func__); +#endif + +#ifdef BOARD_USE_V4L2 + s5p_fimc_params_t *params = &(mS5pFimc.params); + int src_planes = m_getYuvPlanes(params->src.color_space); + int dst_planes = m_getYuvPlanes(params->dst.color_space); + src_planes = (src_planes == -1) ? 1 : src_planes; + dst_planes = (dst_planes == -1) ? 1 : dst_planes; + + if (params->src.color_space == V4L2_PIX_FMT_RGB32) { + mSrcBuffer.size.extS[0] = params->src.full_height * params->src.full_width * 4; + + } else if ( (params->src.color_space == V4L2_PIX_FMT_NV12MT) + || (params->src.color_space == V4L2_PIX_FMT_NV12M)) { + mSrcBuffer.size.extS[0] = params->src.full_height * params->src.full_width; + mSrcBuffer.size.extS[1] = params->src.full_height * params->src.full_width / 2; + } else if ( (params->src.color_space == V4L2_PIX_FMT_YUV420) + || (params->src.color_space == V4L2_PIX_FMT_YUV420M)) { + mSrcBuffer.size.extS[0] = params->src.full_height * params->src.full_width; + mSrcBuffer.size.extS[1] = params->src.full_height * params->src.full_width / 4; + mSrcBuffer.size.extS[2] = params->src.full_height * params->src.full_width / 4; + } else { + mSrcBuffer.size.extS[0] = params->src.full_height * params->src.full_width * 2; + } + + if (fimc_v4l2_queue(mFd, &(mSrcBuffer), V4L2_BUF_TYPE_SRC, V4L2_MEMORY_TYPE_SRC, 0, src_planes) < 0) { + LOGE("%s::fimc_v4l2_queue(index : %d) (mSrcBufNum : %d) failed", __func__, 0, 1); + return false; + } + + for (int i = 0; i < mNumOfBuf; i++) { + if (fimc_v4l2_queue(mFd, &(mDstBuffer[i]), + V4L2_BUF_TYPE_DST, V4L2_MEMORY_TYPE_DST, i, dst_planes) < 0) { + LOGE("%s::fimc_v4l2_queue(index : %d) (mDstBufNum : %d) failed", __func__, i, mNumOfBuf); + return false; + } + } +#endif + if (fimc_v4l2_stream_on(mFd, V4L2_BUF_TYPE_SRC) < 0) { + LOGE("%s::fimc_v4l2_stream_on() failed", __func__); + return false; + } + +#ifdef BOARD_USE_V4L2 + if (fimc_v4l2_stream_on(mFd, V4L2_BUF_TYPE_DST) < 0) { + LOGE("%s::fimc_v4l2_stream_on() failed", __func__); + return false; + } +#endif + return true; +} + +bool SecFimc::m_checkSrcSize(unsigned int width, unsigned int height, + unsigned int cropX, unsigned int cropY, + unsigned int *cropWidth, unsigned int *cropHeight, + int colorFormat, + bool forceChange) +{ + bool ret = true; + + if (8 <= height && *cropHeight < 8) { + if (forceChange) + *cropHeight = 8; + ret = false; + } + + if (16 <= width && *cropWidth < 16) { + if (forceChange) + *cropWidth = 16; + ret = false; + } + + if (0x50 == mHwVersion) { + if (colorFormat == V4L2_PIX_FMT_YUV422P) { + if (*cropHeight % 2 != 0) { + if (forceChange) + *cropHeight = multipleOfN(*cropHeight, 2); + ret = false; + } + if (*cropWidth % 2 != 0) { + if (forceChange) + *cropWidth = multipleOfN(*cropWidth, 2); + ret = false; + } + } + } else { + if (height < 8) + return false; + + if (width % 16 != 0) + return false; + + if (*cropWidth % 16 != 0) { + if (forceChange) + *cropWidth = multipleOfN(*cropWidth, 16); + ret = false; + } + } + + return ret; +} + +bool SecFimc::m_checkDstSize(unsigned int width, unsigned int height, + unsigned int cropX, unsigned int cropY, + unsigned int *cropWidth, unsigned int *cropHeight, + int colorFormat, int rotVal, bool forceChange) +{ + bool ret = true; + unsigned int rotWidth; + unsigned int rotHeight; + unsigned int *rotCropWidth; + unsigned int *rotCropHeight; + + if (rotVal == 90 || rotVal == 270) { + rotWidth = height; + rotHeight = width; + rotCropWidth = cropHeight; + rotCropHeight = cropWidth; + } else { + rotWidth = width; + rotHeight = height; + rotCropWidth = cropWidth; + rotCropHeight = cropHeight; + } + + if (rotHeight < 8) + return false; + + if (rotWidth % 8 != 0) + return false; + + switch (colorFormat) { + case V4L2_PIX_FMT_NV21: + case V4L2_PIX_FMT_NV12: + case V4L2_PIX_FMT_NV12T: +#ifdef BOARD_USE_V4L2 + case V4L2_PIX_FMT_NV12M: + case V4L2_PIX_FMT_NV12MT: + case V4L2_PIX_FMT_YUV420M: +#endif + case V4L2_PIX_FMT_YUV420: + if (*rotCropHeight % 2 != 0) { + if (forceChange) + *rotCropHeight = multipleOfN(*rotCropHeight, 2); + ret = false; + } + } + return ret; +} + +int SecFimc::m_widthOfFimc(int v4l2ColorFormat, int width) +{ + int newWidth = width; + + if (0x50 == mHwVersion) { + switch (v4l2ColorFormat) { + /* 422 1/2/3 plane */ + case V4L2_PIX_FMT_YUYV: + case V4L2_PIX_FMT_UYVY: + case V4L2_PIX_FMT_NV61: + case V4L2_PIX_FMT_NV16: + case V4L2_PIX_FMT_YUV422P: + /* 420 2/3 plane */ + case V4L2_PIX_FMT_NV21: + case V4L2_PIX_FMT_NV12: + case V4L2_PIX_FMT_NV12T: +#ifdef BOARD_USE_V4L2 + case V4L2_PIX_FMT_NV12MT: + case V4L2_PIX_FMT_YUV420M: +#endif + case V4L2_PIX_FMT_YUV420: + + newWidth = multipleOfN(width, 2); + break; + default : + break; + } + } else { + switch (v4l2ColorFormat) { + case V4L2_PIX_FMT_RGB565: + newWidth = multipleOfN(width, 8); + break; + case V4L2_PIX_FMT_RGB32: + newWidth = multipleOfN(width, 4); + break; + case V4L2_PIX_FMT_YUYV: + case V4L2_PIX_FMT_UYVY: + newWidth = multipleOfN(width, 4); + break; + case V4L2_PIX_FMT_NV61: + case V4L2_PIX_FMT_NV16: + newWidth = multipleOfN(width, 8); + break; + case V4L2_PIX_FMT_YUV422P: + newWidth = multipleOfN(width, 16); + break; + case V4L2_PIX_FMT_NV21: + case V4L2_PIX_FMT_NV12: + case V4L2_PIX_FMT_NV12T: +#ifdef BOARD_USE_V4L2 + case V4L2_PIX_FMT_NV12MT: +#endif + newWidth = multipleOfN(width, 8); + break; +#ifdef BOARD_USE_V4L2 + case V4L2_PIX_FMT_YUV420M: +#endif + case V4L2_PIX_FMT_YUV420: + newWidth = multipleOfN(width, 16); + break; + default : + break; + } + } + return newWidth; +} + +int SecFimc::m_heightOfFimc(int v4l2ColorFormat, int height) +{ + int newHeight = height; + + switch (v4l2ColorFormat) { + case V4L2_PIX_FMT_NV21: + case V4L2_PIX_FMT_NV12: + case V4L2_PIX_FMT_NV12T: +#ifdef BOARD_USE_V4L2 + case V4L2_PIX_FMT_NV12MT: + case V4L2_PIX_FMT_YUV420M: +#endif + case V4L2_PIX_FMT_YUV420: + newHeight = multipleOfN(height, 2); + break; + default : + break; + } + return newHeight; +} + +int SecFimc::m_getYuvBpp(unsigned int fmt) +{ + int i, sel = -1; + + for (i = 0; i < (int)(sizeof(yuv_list) / sizeof(struct yuv_fmt_list)); i++) { + if (yuv_list[i].fmt == fmt) { + sel = i; + break; + } + } + + if (sel == -1) + return sel; + else + return yuv_list[sel].bpp; +} + +int SecFimc::m_getYuvPlanes(unsigned int fmt) +{ + int i, sel = -1; + + for (i = 0; i < (int)(sizeof(yuv_list) / sizeof(struct yuv_fmt_list)); i++) { + if (yuv_list[i].fmt == fmt) { + sel = i; + break; + } + } + + if (sel == -1) + return sel; + else + return yuv_list[sel].planes; +} diff --git a/exynos4/hal/libfimg/Android.mk b/exynos4/hal/libfimg3x/Android.mk similarity index 55% rename from exynos4/hal/libfimg/Android.mk rename to exynos4/hal/libfimg3x/Android.mk index 0d607e2..c60274d 100644 --- a/exynos4/hal/libfimg/Android.mk +++ b/exynos4/hal/libfimg3x/Android.mk @@ -1,18 +1,22 @@ LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) -LOCAL_C_INCLUDES += \ - $(BOARD_HAL_PATH)/include \ +ifeq ($(BOARD_USES_FIMGAPI),true) -LOCAL_SRC_FILES := \ +LOCAL_C_INCLUDES += $(LOCAL_PATH)/../include + +LOCAL_MODULE_TAGS := optional + +LOCAL_SRC_FILES:= \ FimgApi.cpp \ FimgC210.cpp LOCAL_SHARED_LIBRARIES:= liblog libutils libbinder -LOCAL_MODULE_TAGS := eng -LOCAL_MODULE := libfimg +LOCAL_MODULE:= libfimg LOCAL_PRELINK_MODULE := false include $(BUILD_SHARED_LIBRARY) + +endif diff --git a/exynos4/hal/libfimg/FimgApi.cpp b/exynos4/hal/libfimg3x/FimgApi.cpp similarity index 100% rename from exynos4/hal/libfimg/FimgApi.cpp rename to exynos4/hal/libfimg3x/FimgApi.cpp diff --git a/exynos4/hal/libfimg/FimgApi.h b/exynos4/hal/libfimg3x/FimgApi.h similarity index 100% rename from exynos4/hal/libfimg/FimgApi.h rename to exynos4/hal/libfimg3x/FimgApi.h diff --git a/exynos4/hal/libfimg/FimgC210.cpp b/exynos4/hal/libfimg3x/FimgC210.cpp similarity index 100% rename from exynos4/hal/libfimg/FimgC210.cpp rename to exynos4/hal/libfimg3x/FimgC210.cpp diff --git a/exynos4/hal/libfimg/FimgC210.h b/exynos4/hal/libfimg3x/FimgC210.h similarity index 100% rename from exynos4/hal/libfimg/FimgC210.h rename to exynos4/hal/libfimg3x/FimgC210.h diff --git a/exynos4/hal/libfimg4x/Android.mk b/exynos4/hal/libfimg4x/Android.mk new file mode 100644 index 0000000..f42da3f --- /dev/null +++ b/exynos4/hal/libfimg4x/Android.mk @@ -0,0 +1,22 @@ +LOCAL_PATH:= $(call my-dir) +include $(CLEAR_VARS) + +ifeq ($(BOARD_USES_FIMGAPI),true) + +#LOCAL_C_INCLUDES += $(LOCAL_PATH)/../../include +LOCAL_C_INCLUDES += external/skia/include/core +LOCAL_MODULE_TAGS := optional + +LOCAL_SRC_FILES:= \ + FimgApi.cpp \ + FimgExynos4.cpp + +LOCAL_SHARED_LIBRARIES:= liblog libutils libbinder + +LOCAL_MODULE:= libfimg + +LOCAL_PRELINK_MODULE := false + +include $(BUILD_SHARED_LIBRARY) + +endif diff --git a/exynos4/hal/libfimg4x/FimgApi.cpp b/exynos4/hal/libfimg4x/FimgApi.cpp new file mode 100644 index 0000000..ff11b8d --- /dev/null +++ b/exynos4/hal/libfimg4x/FimgApi.cpp @@ -0,0 +1,376 @@ +/* +** +** Copyright 2009 Samsung Electronics Co, Ltd. +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +** +** +*/ + +#define LOG_NDEBUG 0 +#define LOG_TAG "SKIA" +#include + +#include "FimgApi.h" + +struct blit_op_table optbl[] = { + { (int)BLIT_OP_SOLID_FILL, "FILL" }, + { (int)BLIT_OP_CLR, "CLR" }, + { (int)BLIT_OP_SRC, "SRC" }, + { (int)BLIT_OP_DST, "DST" }, + { (int)BLIT_OP_SRC_OVER, "SRC_OVER" }, + { (int)BLIT_OP_DST_OVER, "DST_OVER" }, + { (int)BLIT_OP_SRC_IN, "SRC_IN" }, + { (int)BLIT_OP_DST_IN, "DST_IN" }, + { (int)BLIT_OP_SRC_OUT, "SRC_OUT" }, + { (int)BLIT_OP_DST_OUT, "DST_OUT" }, + { (int)BLIT_OP_SRC_ATOP, "SRC_ATOP" }, + { (int)BLIT_OP_DST_ATOP, "DST_ATOP" }, + { (int)BLIT_OP_XOR, "XOR" }, + { (int)BLIT_OP_ADD, "ADD" }, + { (int)BLIT_OP_MULTIPLY, "MULTIPLY" }, + { (int)BLIT_OP_SCREEN, "SCREEN" }, + { (int)BLIT_OP_DARKEN, "DARKEN" }, + { (int)BLIT_OP_LIGHTEN, "LIGHTEN" }, + { (int)BLIT_OP_DISJ_SRC_OVER, "DISJ_SRC_OVER" }, + { (int)BLIT_OP_DISJ_DST_OVER, "DISJ_DST_OVER" }, + { (int)BLIT_OP_DISJ_SRC_IN, "DISJ_SRC_IN" }, + { (int)BLIT_OP_DISJ_DST_IN, "DISJ_DST_IN" }, + { (int)BLIT_OP_DISJ_SRC_OUT, "DISJ_SRC_OUT" }, + { (int)BLIT_OP_DISJ_DST_OUT, "DISJ_DST_OUT" }, + { (int)BLIT_OP_DISJ_SRC_ATOP, "DISJ_SRC_ATOP" }, + { (int)BLIT_OP_DISJ_DST_ATOP, "DISJ_DST_ATOP" }, + { (int)BLIT_OP_DISJ_XOR, "DISJ_XOR" }, + { (int)BLIT_OP_CONJ_SRC_OVER, "CONJ_SRC_OVER" }, + { (int)BLIT_OP_CONJ_DST_OVER, "CONJ_DST_OVER" }, + { (int)BLIT_OP_CONJ_SRC_IN, "CONJ_SRC_IN" }, + { (int)BLIT_OP_CONJ_DST_IN, "CONJ_DST_IN" }, + { (int)BLIT_OP_CONJ_SRC_OUT, "CONJ_SRC_OUT" }, + { (int)BLIT_OP_CONJ_DST_OUT, "CONJ_DST_OUT" }, + { (int)BLIT_OP_CONJ_SRC_ATOP, "CONJ_SRC_ATOP" }, + { (int)BLIT_OP_CONJ_DST_ATOP, "CONJ_DST_ATOP" }, + { (int)BLIT_OP_CONJ_XOR, "CONJ_XOR" }, + { (int)BLIT_OP_USER_COEFF, "USER_COEFF" }, + { (int)BLIT_OP_END, "" }, +}; + +#ifndef REAL_DEBUG + void VOID_FUNC(const char *format, ...) + {} +#endif + +FimgApi::FimgApi() +{ + m_flagCreate = false; +} + +FimgApi::~FimgApi() +{ + if (m_flagCreate == true) + PRINT("%s::this is not Destroyed fail\n", __func__); +} + +bool FimgApi::Create(void) +{ + bool ret = false; + + if (t_Lock() == false) { + PRINT("%s::t_Lock() fail\n", __func__); + goto CREATE_DONE; + } + + if (m_flagCreate == true) { + PRINT("%s::Already Created fail\n", __func__); + goto CREATE_DONE; + } + + if (t_Create() == false) { + PRINT("%s::t_Create() fail\n", __func__); + goto CREATE_DONE; + } + + m_flagCreate = true; + + ret = true; + +CREATE_DONE : + + t_UnLock(); + + return ret; +} + +bool FimgApi::Destroy(void) +{ + bool ret = false; + + if (t_Lock() == false) { + PRINT("%s::t_Lock() fail\n", __func__); + goto DESTROY_DONE; + } + + if (m_flagCreate == false) { + PRINT("%s::Already Destroyed fail\n", __func__); + goto DESTROY_DONE; + } + + if (t_Destroy() == false) { + PRINT("%s::t_Destroy() fail\n", __func__); + goto DESTROY_DONE; + } + + m_flagCreate = false; + + ret = true; + +DESTROY_DONE : + + t_UnLock(); + + return ret; +} + +bool FimgApi::Stretch(struct fimg2d_blit *cmd) +{ + bool ret = false; + + if (t_Lock() == false) { + PRINT("%s::t_Lock() fail\n", __func__); + goto STRETCH_DONE; + } + + if (m_flagCreate == false) { + PRINT("%s::This is not Created fail\n", __func__); + goto STRETCH_DONE; + } + + if (t_Stretch(cmd) == false) { + goto STRETCH_DONE; + } + + ret = true; + +STRETCH_DONE : + + t_UnLock(); + + return ret; +} + +bool FimgApi::Sync(void) +{ + bool ret = false; + + if (m_flagCreate == false) { + PRINT("%s::This is not Created fail\n", __func__); + goto SYNC_DONE; + } + + if (t_Sync() == false) + goto SYNC_DONE; + + ret = true; + +SYNC_DONE : + + return ret; +} + +bool FimgApi::t_Create(void) +{ + PRINT("%s::This is empty virtual function fail\n", __func__); + return false; +} + +bool FimgApi::t_Destroy(void) +{ + PRINT("%s::This is empty virtual function fail\n", __func__); + return false; +} + +bool FimgApi::t_Stretch(struct fimg2d_blit *cmd) +{ + PRINT("%s::This is empty virtual function fail\n", __func__); + return false; +} + +bool FimgApi::t_Sync(void) +{ + PRINT("%s::This is empty virtual function fail\n", __func__); + return false; +} + +bool FimgApi::t_Lock(void) +{ + PRINT("%s::This is empty virtual function fail\n", __func__); + return false; +} + +bool FimgApi::t_UnLock(void) +{ + PRINT("%s::This is empty virtual function fail\n", __func__); + return false; +} + +//---------------------------------------------------------------------------// +// extern function +//---------------------------------------------------------------------------// +extern "C" int stretchFimgApi(struct fimg2d_blit *cmd) +{ + FimgApi * fimgApi = createFimgApi(); + + if (fimgApi == NULL) { + PRINT("%s::createFimgApi() fail\n", __func__); + return -1; + } + + if (fimgApi->Stretch(cmd) == false) { + if (fimgApi != NULL) + destroyFimgApi(fimgApi); + + return -1; + } + + if (fimgApi != NULL) + destroyFimgApi(fimgApi); + + return 0; +} + +extern "C" int SyncFimgApi(void) +{ + FimgApi * fimgApi = createFimgApi(); + if (fimgApi == NULL) { + PRINT("%s::createFimgApi() fail\n", __func__); + return -1; + } + + if (fimgApi->Sync() == false) { + if (fimgApi != NULL) + destroyFimgApi(fimgApi); + + return -1; + } + + if (fimgApi != NULL) + destroyFimgApi(fimgApi); + + return 0; +} + +void printDataBlit(char *title, struct fimg2d_blit *cmd) +{ + LOGI("%s\n", title); + + LOGI(" sequence_no. = %u\n", cmd->seq_no); + LOGI(" blit_op = %d(%s)\n", cmd->op, optbl[cmd->op].str); + LOGI(" fill_color = %X\n", cmd->solid_color); + LOGI(" global_alpha = %u\n", (unsigned int)cmd->g_alpha); + LOGI(" PREMULT = %s\n", cmd->premult == PREMULTIPLIED ? "PREMULTIPLIED" : "NON-PREMULTIPLIED"); + LOGI(" do_dither = %s\n", cmd->dither == true ? "dither" : "no-dither"); + + printDataBlitRotate(cmd->rotate); + + printDataBlitScale(cmd->scaling); + + printDataBlitImage("SRC", cmd->src); + printDataBlitImage("DST", cmd->dst); + printDataBlitImage("MSK", cmd->msk); + + printDataBlitRect("SRC", cmd->src_rect); + printDataBlitRect("DST", cmd->dst_rect); + printDataBlitRect("MSK", cmd->msk_rect); + + printDataBlitClip(cmd->clipping); +} + +void printDataBlitImage(char *title, struct fimg2d_image *image) +{ + if (NULL != image) { + LOGI(" Image_%s\n", title); + LOGI(" addr = %X\n", image->addr.start); + LOGI(" size = %u\n", image->addr.size); + LOGI(" (width, height) = (%d, %d)\n", image->width, image->height); + LOGI(" format = %d\n", image->fmt); + } else + LOGI(" Image_%s : NULL\n", title); +} + +void printDataBlitRect(char *title, struct fimg2d_rect *rect) +{ + if (NULL != rect) { + LOGI(" RECT_%s\n", title); + LOGI(" (x1, y1) = (%d, %d)\n", rect->x1, rect->y1); + LOGI(" (x2, y2) = (%d, %d)\n", rect->x2, rect->y2); + LOGI(" (width, height) = (%d, %d)\n", rect->x2 - rect->x1, rect->y2 - rect->y1); + } else + LOGI(" RECT_%s : NULL\n", title); +} + +void printDataBlitRotate(enum rotation rotate) +{ + LOGI(" ROTATE : %d\n", rotate); +} + +void printDataBlitClip(struct fimg2d_clip *clip) +{ + if (NULL != clip) { + LOGI(" CLIP\n"); + LOGI(" clip %s\n", clip->enable == true ? "enabled" : "disabled"); + LOGI(" (x1, y1) = (%d, %d)\n", clip->x1, clip->y1); + LOGI(" (x2, y2) = (%d, %d)\n", clip->x2, clip->y2); + LOGI(" (width, hight) = (%d, %d)\n", clip->x2 - clip->x1, clip->y2 - clip->y1); + } else + LOGI(" CLIP : NULL\n"); +} + +void printDataBlitScale(struct fimg2d_scale *scaling) +{ + if (NULL != scaling) { + LOGI(" SCALING\n"); + LOGI(" scale_mode : %s\n", scaling->mode == 0 ? + "NO_SCALING" : + (scaling->mode == 1 ? "SCALING_NEAREST" : "SCALING_BILINEAR")); + LOGI(" scaling_factor_unit : %s\n", scaling->factor == 0 ? "PERCENT" : "PIXEL"); + + if (scaling->factor == 0) + LOGI(" scaling_factor : (scale_w, scale_y) = (%d, %d)\n", scaling->scale_w, scaling->scale_h); + else { + LOGI(" src : (src_w, src_h) = (%d, %d)\n", scaling->src_w, scaling->src_h); + LOGI(" dst : (dst_w, dst_h) = (%d, %d)\n", scaling->dst_w, scaling->dst_h); + LOGI(" scaling_factor : (scale_w, scale_y) = (%3.2f, %3.2f)\n", (double)scaling->dst_w / scaling->src_w, (double)scaling->dst_h / scaling->src_h); + } + } else + LOGI(" SCALING : NULL(NO SCALE MODE)\n"); + +} + +void printDataMatrix(int matrixType) +{ + LOGI(" MATRIX\n"); + + if (matrixType & SkMatrix::kIdentity_Mask) + LOGI(" Matrix_type : Identity_Mask\n"); + + if (matrixType & SkMatrix::kTranslate_Mask) + LOGI(" Matrix_type : Translate_Mask(the matrix has translation)\n"); + + if (matrixType & SkMatrix::kScale_Mask) + LOGI(" Matrix_type : Scale_Mask(the matrix has X or Y scale)\n"); + + if (matrixType & SkMatrix::kAffine_Mask) + LOGI(" Matrix_type : Affine_Mask(the matrix skews or rotates)\n"); + + if (matrixType & SkMatrix::kPerspective_Mask) + LOGI(" Matrix_type : Perspective_Mask(the matrix is in perspective)\n"); +} diff --git a/exynos4/hal/libfimg4x/FimgApi.h b/exynos4/hal/libfimg4x/FimgApi.h new file mode 100644 index 0000000..a2c9eac --- /dev/null +++ b/exynos4/hal/libfimg4x/FimgApi.h @@ -0,0 +1,114 @@ +/* +** +** Copyright 2009 Samsung Electronics Co, Ltd. +** Copyright 2008, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +** +** +*/ + +#ifndef FIMG_API_H +#define FIMG_API_H + +#include +#include "SkMatrix.h" +#include "sec_g2d_4x.h" + +#define REAL_DEBUG +#define ANDROID_LOG + +#if defined(REAL_DEBUG) +#ifdef ANDROID_LOG +#define PRINT LOGE +#define PRINTD LOGD +#else +#define PRINT printf +#define PRINTD printf +#endif +#else +void VOID_FUNC(const char *format, ...); + +#define PRINT VOID_FUNC +#define PRINTD VOID_FUNC +#endif + +#ifdef __cplusplus + +struct blit_op_table { + int op; + const char *str; +}; + +extern struct blit_op_table optbl[]; + +class FimgApi +{ +public: +#endif + +#ifdef __cplusplus +private : + bool m_flagCreate; + +protected : + FimgApi(); + FimgApi(const FimgApi& rhs) {} + virtual ~FimgApi(); + +public: + bool Create(void); + bool Destroy(void); + inline bool FlagCreate(void) { return m_flagCreate; } + bool Stretch(struct fimg2d_blit *cmd); + bool Sync(void); + +protected: + virtual bool t_Create(void); + virtual bool t_Destroy(void); + virtual bool t_Stretch(struct fimg2d_blit *cmd); + virtual bool t_Sync(void); + virtual bool t_Lock(void); + virtual bool t_UnLock(void); + +}; +#endif + +#ifdef __cplusplus +extern "C" +#endif +struct FimgApi *createFimgApi(); + +#ifdef __cplusplus +extern "C" +#endif +void destroyFimgApi(FimgApi *ptrFimgApi); + +#ifdef __cplusplus +extern "C" +#endif +int stretchFimgApi(struct fimg2d_blit *cmd); +#ifdef __cplusplus +extern "C" +#endif +int SyncFimgApi(void); + +void printDataBlit(char *title, struct fimg2d_blit *cmd); +void printDataBlitRotate(enum rotation rotate); +void printDataBlitImage(char *title, struct fimg2d_image *image); +void printDataBlitRect(char *title, struct fimg2d_rect *rect); +void printDataBlitClip(struct fimg2d_clip *clip); +void printDataBlitScale(struct fimg2d_scale *scaling); +void printDataMatrix(int matrixType); + +#endif //FIMG_API_H diff --git a/exynos4/hal/libfimg4x/FimgExynos4.cpp b/exynos4/hal/libfimg4x/FimgExynos4.cpp new file mode 100644 index 0000000..f9a7f1e --- /dev/null +++ b/exynos4/hal/libfimg4x/FimgExynos4.cpp @@ -0,0 +1,302 @@ +/* +** +** Copyright 2009 Samsung Electronics Co, Ltd. +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +** +** +*/ + +#define LOG_NDEBUG 0 +#define LOG_TAG "FimgExynos4" +#include + +#include "FimgExynos4.h" + +namespace android +{ +Mutex FimgV4x::m_instanceLock; +unsigned FimgV4x::m_curFimgV4xIndex = 0; +int FimgV4x::m_numOfInstance = 0; +FimgApi * FimgV4x::m_ptrFimgApiList[NUMBER_FIMG_LIST] = {NULL, }; + +//---------------------------------------------------------------------------// + +FimgV4x::FimgV4x() + : m_g2dFd(0), + m_g2dVirtAddr(NULL), + m_g2dSize(0), + m_g2dSrcVirtAddr(NULL), + m_g2dSrcSize(0), + m_g2dDstVirtAddr(NULL), + m_g2dDstSize(0) +{ + memset(&(m_g2dPoll), 0, sizeof(struct pollfd)); + m_lock = new Mutex(Mutex::SHARED, "FimgV4x"); +} + +FimgV4x::~FimgV4x() +{ + delete m_lock; +} + +FimgApi *FimgV4x::CreateInstance() +{ + Mutex::Autolock autolock(m_instanceLock); + + FimgApi *ptrFimg = NULL; + + for(unsigned int i = m_curFimgV4xIndex; i < NUMBER_FIMG_LIST; i++) { + if (m_ptrFimgApiList[i] == NULL) + m_ptrFimgApiList[i] = new FimgV4x; + + if (m_ptrFimgApiList[i]->FlagCreate() == false) { + if (m_ptrFimgApiList[i]->Create() == false) { + PRINT("%s::Create(%d) fail\n", __func__, i); + goto CreateInstance_End; + } + else + m_numOfInstance++; + } + + if (i < NUMBER_FIMG_LIST - 1) + m_curFimgV4xIndex = i + 1; + else + m_curFimgV4xIndex = 0; + + ptrFimg = m_ptrFimgApiList[i]; + goto CreateInstance_End; + } + +CreateInstance_End : + + return ptrFimg; +} + +void FimgV4x::DestroyInstance(FimgApi * ptrFimgApi) +{ + Mutex::Autolock autolock(m_instanceLock); + + for(int i = 0; i < NUMBER_FIMG_LIST; i++) { + if (m_ptrFimgApiList[i] != NULL && m_ptrFimgApiList[i] == ptrFimgApi) { + if (m_ptrFimgApiList[i]->FlagCreate() == true && m_ptrFimgApiList[i]->Destroy() == false) { + PRINT("%s::Destroy() fail\n", __func__); + } else { + FimgV4x * tempFimgV4x = (FimgV4x *)m_ptrFimgApiList[i]; + delete tempFimgV4x; + m_ptrFimgApiList[i] = NULL; + + m_numOfInstance--; + } + + break; + } + } +} + +void FimgV4x::DestroyAllInstance(void) +{ + Mutex::Autolock autolock(m_instanceLock); + + for(int i = 0; i < NUMBER_FIMG_LIST; i++) { + if (m_ptrFimgApiList[i] != NULL) { + if (m_ptrFimgApiList[i]->FlagCreate() == true + && m_ptrFimgApiList[i]->Destroy() == false) { + PRINT("%s::Destroy() fail\n", __func__); + } else { + FimgV4x * tempFimgV4x = (FimgV4x *)m_ptrFimgApiList[i]; + delete tempFimgV4x; + m_ptrFimgApiList[i] = NULL; + } + } + } +} + +bool FimgV4x::t_Create(void) +{ + bool ret = true; + + if (m_CreateG2D() == false) { + PRINT("%s::m_CreateG2D() fail \n", __func__); + + if (m_DestroyG2D() == false) + PRINT("%s::m_DestroyG2D() fail \n", __func__); + + ret = false; + } + + return ret; +} + +bool FimgV4x::t_Destroy(void) +{ + bool ret = true; + + if (m_DestroyG2D() == false) { + PRINT("%s::m_DestroyG2D() fail \n", __func__); + ret = false; + } + + return ret; +} + +bool FimgV4x::t_Stretch(struct fimg2d_blit *cmd) +{ +#ifdef CHECK_FIMGV4x_PERFORMANCE +#define NUM_OF_STEP (10) + StopWatch stopWatch("CHECK_FIMGV4x_PERFORMANCE"); + const char *stopWatchName[NUM_OF_STEP]; + nsecs_t stopWatchTime[NUM_OF_STEP]; + int stopWatchIndex = 0; +#endif // CHECK_FIMGV4x_PERFORMANCE + + if (m_DoG2D(cmd) == false) { + goto STRETCH_FAIL; + } + +#ifdef G2D_NONE_BLOCKING_MODE + if (m_PollG2D(&m_g2dPoll) == false) + { + PRINT("%s::m_PollG2D() fail\n", __func__); + goto STRETCH_FAIL; + } +#endif + + #ifdef CHECK_FIMGV4x_PERFORMANCE + m_PrintFimgV4xPerformance(src, dst, stopWatchIndex, stopWatchName, stopWatchTime); + #endif // CHECK_FIMGV4x_PERFORMANCE + + return true; + +STRETCH_FAIL: + return false; + +} + +bool FimgV4x::t_Sync(void) +{ + if (m_PollG2D(&m_g2dPoll) == false) + { + PRINT("%s::m_PollG2D() fail\n", __func__); + goto SYNC_FAIL; + } + return true; + +SYNC_FAIL: + return false; + +} + +bool FimgV4x::t_Lock(void) +{ + m_lock->lock(); + return true; +} + +bool FimgV4x::t_UnLock(void) +{ + m_lock->unlock(); + return true; +} + +bool FimgV4x::m_CreateG2D(void) +{ + void * mmap_base; + + if (m_g2dFd != 0) { + PRINT("%s::m_g2dFd(%d) is not 0 fail\n", __func__, m_g2dFd); + return false; + } + +#ifdef G2D_NONE_BLOCKING_MODE + m_g2dFd = open(SEC_G2D_DEV_NAME, O_RDWR | O_NONBLOCK); +#else + m_g2dFd = open(SEC_G2D_DEV_NAME, O_RDWR); +#endif + if (m_g2dFd < 0) { + PRINT("%s::open(%s) fail(%s)\n", __func__, SEC_G2D_DEV_NAME, strerror(errno)); + m_g2dFd = 0; + return false; + } + + memset(&m_g2dPoll, 0, sizeof(m_g2dPoll)); + m_g2dPoll.fd = m_g2dFd; + m_g2dPoll.events = POLLOUT | POLLERR; + + return true; +} + +bool FimgV4x::m_DestroyG2D(void) +{ + if (m_g2dVirtAddr != NULL) { + munmap(m_g2dVirtAddr, m_g2dSize); + m_g2dVirtAddr = NULL; + m_g2dSize = 0; + } + + if (0 < m_g2dFd) { + close(m_g2dFd); + } + m_g2dFd = 0; + + return true; +} + +bool FimgV4x::m_DoG2D(struct fimg2d_blit *cmd) +{ + + if (ioctl(m_g2dFd, FIMG2D_BITBLT_BLIT, cmd) < 0) + return false; + + return true; +} + +inline bool FimgV4x::m_PollG2D(struct pollfd * events) +{ +#define G2D_POLL_TIME (1000) + + int ret; + + ret = poll(events, 1, G2D_POLL_TIME); + + if (ret < 0) { + PRINT("%s::poll fail \n", __func__); + return false; + } + else if (ret == 0) { + PRINT("%s::No data in %d milli secs..\n", __func__, G2D_POLL_TIME); + return false; + } + + return true; +} + +//---------------------------------------------------------------------------// +// extern function +//---------------------------------------------------------------------------// +extern "C" struct FimgApi * createFimgApi() +{ + if (fimgApiAutoFreeThread == 0) + fimgApiAutoFreeThread = new FimgApiAutoFreeThread(); + else + fimgApiAutoFreeThread->SetOneMoreSleep(); + + return FimgV4x::CreateInstance(); +} + +extern "C" void destroyFimgApi(FimgApi * ptrFimgApi) +{ + // Dont' call DestroyInstance. +} + +}; // namespace android diff --git a/exynos4/hal/libfimg4x/FimgExynos4.h b/exynos4/hal/libfimg4x/FimgExynos4.h new file mode 100644 index 0000000..2a7c42f --- /dev/null +++ b/exynos4/hal/libfimg4x/FimgExynos4.h @@ -0,0 +1,169 @@ +/* +** +** Copyright 2008, The Android Open Source Project +** Copyright 2009 Samsung Electronics Co, Ltd. All Rights Reserved. +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +** +** +*/ + +#ifndef FIMG_EXYNOS4_H +#define FIMG_EXYNOS4_H + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "FimgApi.h" + +#include "sec_g2d_4x.h" + +namespace android +{ + +#define NUMBER_FIMG_LIST (1) // kcoolsw : because of pmem +#define GET_RECT_SIZE(rect) ((rect->full_w) * (rect->h) * (rect->bytes_per_pixel)) +#define GET_REAL_SIZE(rect) ((rect->full_w) * (rect->h) * (rect->bytes_per_pixel)) +#define GET_START_ADDR(rect) (rect->virt_addr + ((rect->y * rect->full_w) * rect->bytes_per_pixel)) +#define SLEEP_TIME (3000000) // 3 sec + +//---------------------------------------------------------------------------// +// class FimgV4x : public FimgBase +//---------------------------------------------------------------------------// +class FimgV4x : public FimgApi +{ +private : + int m_g2dFd; + + unsigned char *m_g2dVirtAddr; + unsigned int m_g2dSize; + unsigned char *m_g2dSrcVirtAddr; + unsigned int m_g2dSrcSize; + unsigned char *m_g2dDstVirtAddr; + unsigned int m_g2dDstSize; + struct pollfd m_g2dPoll; + + Mutex *m_lock; + + static Mutex m_instanceLock; + static unsigned m_curFimgV4xIndex; + static int m_numOfInstance; + + static FimgApi *m_ptrFimgApiList[NUMBER_FIMG_LIST]; + +protected : + FimgV4x(); + virtual ~FimgV4x(); + +public: + static FimgApi *CreateInstance(); + static void DestroyInstance(FimgApi *ptrFimgApi); + static void DestroyAllInstance(void); + +protected: + virtual bool t_Create(void); + virtual bool t_Destroy(void); + virtual bool t_Stretch(struct fimg2d_blit *cmd); + virtual bool t_Sync(void); + virtual bool t_Lock(void); + virtual bool t_UnLock(void); + +private: + bool m_CreateG2D(void); + bool m_DestroyG2D(void); + + bool m_DoG2D(struct fimg2d_blit *cmd); + + inline bool m_PollG2D(struct pollfd *events); + + inline int m_ColorFormatFimgApi2FimgHw(int colorFormat); +}; + +class FimgApiAutoFreeThread; + +static sp fimgApiAutoFreeThread = 0; + +class FimgApiAutoFreeThread : public Thread +{ +private: + bool mOneMoreSleep; + bool mDestroyed; + +public: + FimgApiAutoFreeThread(void): + Thread(false), + mOneMoreSleep(true), + mDestroyed(false) + { } + ~FimgApiAutoFreeThread(void) + { + if (mDestroyed == false) + { + FimgV4x::DestroyAllInstance(); + mDestroyed = true; + } + } + + virtual void onFirstRef() + { + run("FimgApiAutoFreeThread", PRIORITY_BACKGROUND); + } + + virtual bool threadLoop() + { + + if (mOneMoreSleep == true) + { + mOneMoreSleep = false; + usleep(SLEEP_TIME); + + return true; + } + else + { + if (mDestroyed == false) + { + FimgV4x::DestroyAllInstance(); + mDestroyed = true; + } + + fimgApiAutoFreeThread = 0; + + return false; + } + } + + void SetOneMoreSleep(void) + { + mOneMoreSleep = true; + } +}; + +}; // namespace android + +#endif // FIMG_EXYNOS4_H diff --git a/exynos4/hal/libfimg4x/sec_g2d_4x.h b/exynos4/hal/libfimg4x/sec_g2d_4x.h new file mode 100644 index 0000000..b9ddbb2 --- /dev/null +++ b/exynos4/hal/libfimg4x/sec_g2d_4x.h @@ -0,0 +1,326 @@ +/* + * Copyright 2011, Samsung Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef __SEC_G2D_4X_H +#define __SEC_G2D_4X_H __FILE__ + +#define SEC_G2D_DEV_NAME "/dev/fimg2d" + +/* ioctl commands */ +#define FIMG2D_IOCTL_MAGIC 'F' +#define FIMG2D_BITBLT_BLIT _IOWR(FIMG2D_IOCTL_MAGIC, 0, struct fimg2d_blit) +#define FIMG2D_BITBLT_SYNC _IO(FIMG2D_IOCTL_MAGIC, 1) +#define FIMG2D_BITBLT_VERSION _IOR(FIMG2D_IOCTL_MAGIC, 2, struct fimg2d_version) + +#define G2D_ALPHA_VALUE_MAX (255) + +enum addr_space { + ADDR_UNKNOWN, + ADDR_PHYS, + ADDR_KERN, + ADDR_USER, + ADDR_DEVICE, +}; + +/** + * DO NOT CHANGE THIS ORDER + */ +enum pixel_order { + AX_RGB = 0, + RGB_AX, + AX_BGR, + BGR_AX, + ARGB_ORDER_END, + + P1_CRY1CBY0, + P1_CBY1CRY0, + P1_Y1CRY0CB, + P1_Y1CBY0CR, + P1_ORDER_END, + + P2_CRCB, + P2_CBCR, + P2_ORDER_END, +}; + +/** + * DO NOT CHANGE THIS ORDER + */ +enum color_format { + CF_XRGB_8888 = 0, + CF_ARGB_8888, + CF_RGB_565, + CF_XRGB_1555, + CF_ARGB_1555, + CF_XRGB_4444, + CF_ARGB_4444, + CF_RGB_888, + CF_YCBCR_444, + CF_YCBCR_422, + CF_YCBCR_420, + CF_A8, + CF_L8, + SRC_DST_FORMAT_END, + + CF_MSK_1BIT, + CF_MSK_4BIT, + CF_MSK_8BIT, + CF_MSK_16BIT_565, + CF_MSK_16BIT_1555, + CF_MSK_16BIT_4444, + CF_MSK_32BIT_8888, + MSK_FORMAT_END, +}; + +enum rotation { + ORIGIN, + ROT_90, /* clockwise */ + ROT_180, + ROT_270, + XFLIP, /* x-axis flip */ + YFLIP, /* y-axis flip */ +}; + +/** + * @NO_REPEAT: no effect + * @REPEAT_NORMAL: repeat horizontally and vertically + * @REPEAT_PAD: pad with pad color + * @REPEAT_REFLECT: reflect horizontally and vertically + * @REPEAT_CLAMP: pad with edge color of original image + * + * DO NOT CHANGE THIS ORDER + */ +enum repeat { + NO_REPEAT = 0, + REPEAT_NORMAL, /* default setting */ + REPEAT_PAD, + REPEAT_REFLECT, REPEAT_MIRROR = REPEAT_REFLECT, + REPEAT_CLAMP, +}; + +enum scaling { + NO_SCALING, + SCALING_NEAREST, + SCALING_BILINEAR, +}; + +/** + * @SCALING_PERCENTAGE: percentage of width, height + * @SCALING_PIXELS: coordinate of src, dest + */ +enum scaling_factor { + SCALING_PERCENTAGE, + SCALING_PIXELS, +}; + +/** + * premultiplied alpha + */ +enum premultiplied { + PREMULTIPLIED, + NON_PREMULTIPLIED, +}; + +/** + * @TRANSP: discard bluescreen color + * @BLUSCR: replace bluescreen color with background color + */ +enum bluescreen { + OPAQUE, + TRANSP, + BLUSCR, +}; + +/** + * DO NOT CHANGE THIS ORDER + */ +enum blit_op { + BLIT_OP_SOLID_FILL = 0, + + BLIT_OP_CLR, + BLIT_OP_SRC, BLIT_OP_SRC_COPY = BLIT_OP_SRC, + BLIT_OP_DST, + BLIT_OP_SRC_OVER, + BLIT_OP_DST_OVER, BLIT_OP_OVER_REV = BLIT_OP_DST_OVER, + BLIT_OP_SRC_IN, + BLIT_OP_DST_IN, BLIT_OP_IN_REV = BLIT_OP_DST_IN, + BLIT_OP_SRC_OUT, + BLIT_OP_DST_OUT, BLIT_OP_OUT_REV = BLIT_OP_DST_OUT, + BLIT_OP_SRC_ATOP, + BLIT_OP_DST_ATOP, BLIT_OP_ATOP_REV = BLIT_OP_DST_ATOP, + BLIT_OP_XOR, + + BLIT_OP_ADD, + BLIT_OP_MULTIPLY, + BLIT_OP_SCREEN, + BLIT_OP_DARKEN, + BLIT_OP_LIGHTEN, + + BLIT_OP_DISJ_SRC_OVER, + BLIT_OP_DISJ_DST_OVER, BLIT_OP_SATURATE = BLIT_OP_DISJ_DST_OVER, + BLIT_OP_DISJ_SRC_IN, + BLIT_OP_DISJ_DST_IN, BLIT_OP_DISJ_IN_REV = BLIT_OP_DISJ_DST_IN, + BLIT_OP_DISJ_SRC_OUT, + BLIT_OP_DISJ_DST_OUT, BLIT_OP_DISJ_OUT_REV = BLIT_OP_DISJ_DST_OUT, + BLIT_OP_DISJ_SRC_ATOP, + BLIT_OP_DISJ_DST_ATOP, BLIT_OP_DISJ_ATOP_REV = BLIT_OP_DISJ_DST_ATOP, + BLIT_OP_DISJ_XOR, + + BLIT_OP_CONJ_SRC_OVER, + BLIT_OP_CONJ_DST_OVER, BLIT_OP_CONJ_OVER_REV = BLIT_OP_CONJ_DST_OVER, + BLIT_OP_CONJ_SRC_IN, + BLIT_OP_CONJ_DST_IN, BLIT_OP_CONJ_IN_REV = BLIT_OP_CONJ_DST_IN, + BLIT_OP_CONJ_SRC_OUT, + BLIT_OP_CONJ_DST_OUT, BLIT_OP_CONJ_OUT_REV = BLIT_OP_CONJ_DST_OUT, + BLIT_OP_CONJ_SRC_ATOP, + BLIT_OP_CONJ_DST_ATOP, BLIT_OP_CONJ_ATOP_REV = BLIT_OP_CONJ_DST_ATOP, + BLIT_OP_CONJ_XOR, + + /* Add new operation type here */ + + /* user select coefficient manually */ + BLIT_OP_USER_COEFF, + + /* end of blit operation */ + BLIT_OP_END, + + /* driver not supporting format */ + BLIT_OP_NOT_SUPPORTED +}; + +#define MAX_FIMG2D_BLIT_OP (int)BLIT_OP_END + +struct fimg2d_version { + unsigned int hw; + unsigned int sw; +}; + +/** + * @start: start address or unique id of image + * @size: whole length of allocated image + * @cacheable: memory is cacheable + * @pinnable: memory is pinnable. currently not supported. + */ +struct fimg2d_addr { + enum addr_space type; + unsigned long start; + size_t size; + int cacheable; + int pinnable; +}; + +struct fimg2d_rect { + int x1; + int y1; + int x2; /* x1 + width */ + int y2; /* y1 + height */ +}; + +/** + * if factor is percentage, scale_w and scale_h are valid + * if factor is pixels, src_w, src_h, dst_w, dst_h are valid + */ +struct fimg2d_scale { + enum scaling mode; + enum scaling_factor factor; + + /* percentage */ + int scale_w; + int scale_h; + + /* pixels */ + int src_w, src_h; + int dst_w, dst_h; +}; + +/** + * coordinate from start address(0,0) of image + */ +struct fimg2d_clip { + bool enable; + int x1; + int y1; + int x2; /* x1 + width */ + int y2; /* y1 + height */ +}; + +struct fimg2d_repeat { + enum repeat mode; + unsigned long pad_color; +}; + +/** + * @bg_color: bg_color is valid only if bluescreen mode is BLUSCR. + */ +struct fimg2d_bluscr { + enum bluescreen mode; + unsigned long bs_color; + unsigned long bg_color; +}; + +/** + * @plane2: address info for CbCr in YCbCr 2plane mode + */ +struct fimg2d_image { + struct fimg2d_addr addr; + struct fimg2d_addr plane2; + int width; + int height; + int stride; + enum pixel_order order; + enum color_format fmt; +}; + +struct fimg2d_param { + enum blit_op op; + unsigned long fillcolor; + unsigned char g_alpha; + enum premultiplied premult; + bool dither; + enum rotation rotate; + struct fimg2d_scale *scaling; + struct fimg2d_repeat *repeat; + struct fimg2d_bluscr *bluscr; + struct fimg2d_clip *clipping; +}; + +/** + * @g_alpha: 0xff is opaque, 0x0 is transparnet + * @seq_no: used for debugging + */ +struct fimg2d_blit { + enum blit_op op; + + enum premultiplied premult; + unsigned char g_alpha; + bool dither; + enum rotation rotate; + struct fimg2d_scale *scaling; + struct fimg2d_repeat *repeat; + struct fimg2d_bluscr *bluscr; + struct fimg2d_clip *clipping; + + unsigned long solid_color; + struct fimg2d_image *src; + struct fimg2d_image *dst; + struct fimg2d_image *msk; + + struct fimg2d_rect *src_rect; + struct fimg2d_rect *dst_rect; + struct fimg2d_rect *msk_rect; + + unsigned int seq_no; +}; +#endif /* __SEC_G2D_4X_H__ */ diff --git a/exynos4/hal/libgralloc_ump/Android.mk b/exynos4/hal/libgralloc_ump/Android.mk new file mode 100644 index 0000000..20584a4 --- /dev/null +++ b/exynos4/hal/libgralloc_ump/Android.mk @@ -0,0 +1,56 @@ +# +# Copyright (C) 2010 ARM Limited. All rights reserved. +# +# Portions of this code have been modified from the original. +# These modifications are: +# * The build configuration for the Gralloc module +# +# Copyright (C) 2008 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +LOCAL_PATH := $(call my-dir) + +# HAL module implemenation, not prelinked and stored in +# hw/..so +include $(CLEAR_VARS) +LOCAL_PRELINK_MODULE := false +LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw +LOCAL_SHARED_LIBRARIES := liblog libcutils libUMP libGLESv1_CM libion + +# Include the UMP header files +LOCAL_C_INCLUDES += $(LOCAL_PATH)/../include + +LOCAL_SRC_FILES := \ + gralloc_module.cpp \ + alloc_device.cpp \ + framebuffer_device.cpp + +LOCAL_MODULE_TAGS := eng +#LOCAL_MODULE := gralloc.default +LOCAL_MODULE := gralloc.$(TARGET_DEVICE) +LOCAL_CFLAGS:= -DLOG_TAG=\"gralloc\" -DGRALLOC_32_BITS -DSTANDARD_LINUX_SCREEN +#LOCAL_CFLAGS+= -DMALI_VSYNC_EVENT_REPORT_ENABLE + +LOCAL_CFLAGS += -DSAMSUNG_EXYNOS +LOCAL_CFLAGS += -DSAMSUNG_EXYNOS_CACHE_UMP + +ifeq ($(TARGET_SOC),exynos4210) +LOCAL_CFLAGS += -DSAMSUNG_EXYNOS4210 +endif + +ifeq ($(TARGET_SOC),exynos4x12) +LOCAL_CFLAGS += -DSAMSUNG_EXYNOS4x12 +endif + +include $(BUILD_SHARED_LIBRARY) diff --git a/exynos4/hal/libgralloc_ump/alloc_device.cpp b/exynos4/hal/libgralloc_ump/alloc_device.cpp new file mode 100644 index 0000000..982f1b8 --- /dev/null +++ b/exynos4/hal/libgralloc_ump/alloc_device.cpp @@ -0,0 +1,498 @@ +/* + * Copyright (C) 2010 ARM Limited. All rights reserved. + * + * Portions of this code have been modified from the original. + * These modifications are: + * * includes + * * gralloc_alloc_buffer() + * * gralloc_alloc_framebuffer_locked() + * * gralloc_alloc_framebuffer() + * * alloc_device_alloc() + * * alloc_device_free() + * * alloc_device_close() + * * alloc_device_open() + * + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +#include +#include +#include +#include +#include "sec_format.h" + +#include "gralloc_priv.h" +#include "gralloc_helper.h" +#include "framebuffer_device.h" + +#include "ump.h" +#include "ump_ref_drv.h" + +/*****************************************************************************/ +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#if HAVE_ANDROID_OS +#include +#include +#endif + +#include "videodev2.h" +#include "s5p_fimc.h" + +#ifdef SAMSUNG_EXYNOS4x12 +#define PFX_NODE_FIMC1 "/dev/video3" +#endif +#ifdef SAMSUNG_EXYNOS4210 +#define PFX_NODE_FIMC1 "/dev/video1" +#endif + +#ifndef OMX_COLOR_FormatYUV420Planar +#define OMX_COLOR_FormatYUV420Planar 0x13 +#endif + +#ifndef OMX_COLOR_FormatYUV420SemiPlanar +#define OMX_COLOR_FormatYUV420SemiPlanar 0x15 +#endif + +bool ion_dev_open = true; +static pthread_mutex_t l_surface= PTHREAD_MUTEX_INITIALIZER; +static int buffer_offset = 0; +static int gfd = 0; + +#ifdef USE_PARTIAL_FLUSH +extern struct private_handle_rect *rect_list; +extern private_handle_rect *find_rect(int secure_id); +extern private_handle_rect *find_last_rect(int secure_id); +extern int release_rect(int secure_id); +#endif + +#define EXYNOS4_ALIGN( value, base ) (((value) + ((base) - 1)) & ~((base) - 1)) + +static int gralloc_alloc_buffer(alloc_device_t* dev, size_t size, int usage, + buffer_handle_t* pHandle, int w, int h, + int format, int bpp, int stride_raw, int stride) +{ + ump_handle ump_mem_handle; + void *cpu_ptr; + ump_secure_id ump_id; + + size = round_up_to_page_size(size); + if (usage & GRALLOC_USAGE_HW_FIMC1) { + int dev_fd=0; + char node[20]; + int ret; + int paddr=0; + int offset=0; + + struct v4l2_control vc; + sprintf(node, "%s", PFX_NODE_FIMC1); + + if (gfd == 0) { + gfd = open(node, O_RDWR); + + if (gfd < 0) { + LOGE("%s:: %s Post processor open error\n", __func__, node); + return false; + } + } + + vc.id = V4L2_CID_RESERVED_MEM_BASE_ADDR; + vc.value = 0; + ret = ioctl(gfd, VIDIOC_G_CTRL, &vc); + if (ret < 0) { + LOGE("Error in video VIDIOC_G_CTRL - V4L2_CID_RESERVED_MEM_BAES_ADDR (%d)\n", ret); + return false; + } + paddr = (unsigned int)vc.value; + + if ((buffer_offset + size) >= FIMC1_RESERVED_SIZE * 1024) + buffer_offset = 0; + + paddr += buffer_offset; + private_handle_t* hnd = new private_handle_t(private_handle_t::PRIV_FLAGS_USES_IOCTL, size, 0, + private_handle_t::LOCK_STATE_MAPPED, 0, 0); + + *pHandle = hnd; + hnd->format = format; + hnd->usage = usage; + hnd->width = w; + hnd->height = h; + hnd->bpp = bpp; + hnd->paddr = paddr; + hnd->offset = buffer_offset; + hnd->stride = stride; + hnd->fd = gfd; + hnd->uoffset = (EXYNOS4_ALIGN((EXYNOS4_ALIGN(hnd->width, 16) * EXYNOS4_ALIGN(hnd->height, 16)), 4096)); + hnd->voffset = (EXYNOS4_ALIGN((EXYNOS4_ALIGN((hnd->width >> 1), 16) * EXYNOS4_ALIGN((hnd->height >> 1), 16)), 4096)); + buffer_offset += size; + + return 0; + } else { + ion_buffer ion_fd = 0; + unsigned int ion_flags = 0; + int priv_alloc_flag = private_handle_t::PRIV_FLAGS_USES_UMP; + + if (usage & GRALLOC_USAGE_HW_ION) { + if (!ion_dev_open) { + LOGE("ERROR, failed to open ion"); + return -1; + } + + private_module_t* m = reinterpret_cast(dev->common.module); + ion_flags = ION_HEAP_EXYNOS_MASK; + ion_fd = ion_alloc(m->ion_client, size, 0, ion_flags); + + if (ion_fd < 0) { + LOGE("Failed to ion_alloc"); + return -1; + } + + cpu_ptr = ion_map(ion_fd, size, 0); + + if (NULL == cpu_ptr) { + LOGE("Failed to ion_map"); + ion_free(ion_fd); + return -1; + } + + ump_mem_handle = ump_ref_drv_ion_import(ion_fd, UMP_REF_DRV_CONSTRAINT_NONE); + + if (UMP_INVALID_MEMORY_HANDLE != ump_mem_handle) { + priv_alloc_flag = private_handle_t::PRIV_FLAGS_USES_ION; + } else { + LOGE("gralloc_alloc_buffer() failed to import ION memory"); + ion_unmap(cpu_ptr, size); + ion_free(ion_fd); + return -1; + } + } +#ifdef SAMSUNG_EXYNOS_CACHE_UMP + else if ((usage&GRALLOC_USAGE_SW_READ_MASK) == GRALLOC_USAGE_SW_READ_OFTEN) + ump_mem_handle = ump_ref_drv_allocate(size, UMP_REF_DRV_CONSTRAINT_USE_CACHE); + else + ump_mem_handle = ump_ref_drv_allocate(size, UMP_REF_DRV_CONSTRAINT_NONE); +#else + else + ump_mem_handle = ump_ref_drv_allocate(size, UMP_REF_DRV_CONSTRAINT_NONE); +#endif + if (UMP_INVALID_MEMORY_HANDLE != ump_mem_handle) { + if (!(usage & GRALLOC_USAGE_HW_ION)) + cpu_ptr = ump_mapped_pointer_get(ump_mem_handle); + if (NULL != cpu_ptr) { + ump_id = ump_secure_id_get(ump_mem_handle); + if (UMP_INVALID_SECURE_ID != ump_id) { + private_handle_t* hnd; + hnd = new private_handle_t(priv_alloc_flag, size, (int)cpu_ptr, + private_handle_t::LOCK_STATE_MAPPED, ump_id, ump_mem_handle, ion_fd, 0, 0); + if (NULL != hnd) { + *pHandle = hnd; +#ifdef USE_PARTIAL_FLUSH + if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_UMP) { + private_handle_rect *psRect; + private_handle_rect *psFRect; + psRect = (private_handle_rect *)calloc(1, sizeof(private_handle_rect)); + psRect->handle = (int)hnd->ump_id; + psRect->stride = (int)hnd->stride_raw; + psFRect = find_last_rect((int)hnd->ump_id); + psFRect->next = psRect; + } +#endif + hnd->format = format; + hnd->usage = usage; + hnd->width = w; + hnd->height = h; + hnd->bpp = bpp; + hnd->stride = stride; + hnd->uoffset = ((EXYNOS4_ALIGN(hnd->width, 16) * EXYNOS4_ALIGN(hnd->height, 16))); + hnd->voffset = ((EXYNOS4_ALIGN((hnd->width >> 1), 16) * EXYNOS4_ALIGN((hnd->height >> 1), 16))); + return 0; + } else { + LOGE("gralloc_alloc_buffer() failed to allocate handle"); + } + } else { + LOGE("gralloc_alloc_buffer() failed to retrieve valid secure id"); + } + + ump_mapped_pointer_release(ump_mem_handle); + } else { + LOGE("gralloc_alloc_buffer() failed to map UMP memory"); + } + + ump_reference_release(ump_mem_handle); + } else { + LOGE("gralloc_alloc_buffer() failed to allcoate UMP memory"); + } + } + return -1; +} + +static int gralloc_alloc_framebuffer_locked(alloc_device_t* dev, size_t size, int usage, + buffer_handle_t* pHandle, int w, int h, + int format, int bpp) +{ + private_module_t* m = reinterpret_cast(dev->common.module); + /* allocate the framebuffer */ + if (m->framebuffer == NULL) { + /* initialize the framebuffer, the framebuffer is mapped once and forever. */ + int err = init_frame_buffer_locked(m); + if (err < 0) + return err; + } + + const uint32_t bufferMask = m->bufferMask; + const uint32_t numBuffers = m->numBuffers; + const size_t bufferSize = m->finfo.line_length * m->info.yres; + if (numBuffers == 1) { + /* + * If we have only one buffer, we never use page-flipping. Instead, + * we return a regular buffer which will be memcpy'ed to the main + * screen when post is called. + */ + int newUsage = (usage & ~GRALLOC_USAGE_HW_FB) | GRALLOC_USAGE_HW_2D; + LOGE("fallback to single buffering"); + return gralloc_alloc_buffer(dev, bufferSize, newUsage, pHandle, w, h, format, bpp, 0, 0); + } + + if (bufferMask >= ((1LU<framebuffer->base; + /* find a free slot */ + for (uint32_t i = 0; i < numBuffers; i++) { + if ((bufferMask & (1LU<bufferMask |= (1LU<framebuffer->fd), vaddr - m->framebuffer->base); + + hnd->format = format; + hnd->usage = usage; + hnd->width = w; + hnd->height = h; + hnd->bpp = bpp; + + *pHandle = hnd; + + return 0; +} + +static int gralloc_alloc_framebuffer(alloc_device_t* dev, size_t size, int usage, + buffer_handle_t* pHandle, int w, int h, + int format, int bpp) +{ + private_module_t* m = reinterpret_cast(dev->common.module); + pthread_mutex_lock(&m->lock); + int err = gralloc_alloc_framebuffer_locked(dev, size, usage, pHandle, w, h, format, bpp); + pthread_mutex_unlock(&m->lock); + return err; +} + +static int alloc_device_alloc(alloc_device_t* dev, int w, int h, int format, + int usage, buffer_handle_t* pHandle, int* pStride) +{ + if (!pHandle || !pStride) + return -EINVAL; + + size_t size = 0; + size_t stride = 0; + size_t stride_raw = 0; + + if (format == HAL_PIXEL_FORMAT_YCbCr_420_SP || + format == HAL_PIXEL_FORMAT_YCrCb_420_SP || + format == HAL_PIXEL_FORMAT_YCbCr_422_SP || + format == HAL_PIXEL_FORMAT_YCbCr_420_P || + format == HAL_PIXEL_FORMAT_YV12 || + format == HAL_PIXEL_FORMAT_CUSTOM_YCrCb_420_SP || + format == HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_SP_TILED || + format == GGL_PIXEL_FORMAT_L_8 || + format == OMX_COLOR_FormatYUV420Planar || + format == OMX_COLOR_FormatYUV420SemiPlanar) { + /* FIXME: there is no way to return the vstride */ + int vstride; + stride = (w + 15) & ~15; + vstride = (h + 15) & ~15; + switch (format) { + case HAL_PIXEL_FORMAT_YCbCr_420_SP: + case HAL_PIXEL_FORMAT_YCrCb_420_SP: + case HAL_PIXEL_FORMAT_YCbCr_420_P: + case HAL_PIXEL_FORMAT_YV12: + case HAL_PIXEL_FORMAT_CUSTOM_YCrCb_420_SP: + case HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_SP_TILED: + case OMX_COLOR_FormatYUV420Planar: + case OMX_COLOR_FormatYUV420SemiPlanar: + size = stride * vstride * 2; + if(usage & GRALLOC_USAGE_HW_FIMC1) + size += PAGE_SIZE * 2; + break; + case HAL_PIXEL_FORMAT_YCbCr_422_SP: + size = (stride * vstride) + (w/2 * h/2) * 2; + break; + case GGL_PIXEL_FORMAT_L_8: + size = (stride * vstride); + break; + default: + return -EINVAL; + } + } else { + int align = 8; + int bpp = 0; + switch (format) { + case HAL_PIXEL_FORMAT_RGBA_8888: + case HAL_PIXEL_FORMAT_RGBX_8888: + case HAL_PIXEL_FORMAT_BGRA_8888: + bpp = 4; + break; + case HAL_PIXEL_FORMAT_RGB_888: + bpp = 3; + break; + case HAL_PIXEL_FORMAT_RGB_565: + case HAL_PIXEL_FORMAT_RGBA_5551: + case HAL_PIXEL_FORMAT_RGBA_4444: + bpp = 2; + break; + default: + return -EINVAL; + } + size_t bpr = (w*bpp + (align-1)) & ~(align-1); + size = bpr * h; + stride = bpr / bpp; + stride_raw = bpr; + } + + int err; + pthread_mutex_lock(&l_surface); + if (usage & GRALLOC_USAGE_HW_FB) + err = gralloc_alloc_framebuffer(dev, size, usage, pHandle, w, h, format, 32); + else + err = gralloc_alloc_buffer(dev, size, usage, pHandle, w, h, format, 0, (int)stride_raw, (int)stride); + + pthread_mutex_unlock(&l_surface); + + if (err < 0) + return err; + + *pStride = stride; + return 0; +} + +static int alloc_device_free(alloc_device_t* dev, buffer_handle_t handle) +{ + if (private_handle_t::validate(handle) < 0) + return -EINVAL; + + private_handle_t const* hnd = reinterpret_cast(handle); + private_module_t* m = reinterpret_cast(dev->common.module); + pthread_mutex_lock(&l_surface); + if (hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER) { + /* free this buffer */ + const size_t bufferSize = m->finfo.line_length * m->info.yres; + int index = (hnd->base - m->framebuffer->base) / bufferSize; + m->bufferMask &= ~(1<fd); + } else if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_UMP) { +#ifdef USE_PARTIAL_FLUSH + if (!release_rect((int)hnd->ump_id)) + LOGE("secure id: 0x%x, release error",(int)hnd->ump_id); +#endif + ump_mapped_pointer_release((ump_handle)hnd->ump_mem_handle); + ump_reference_release((ump_handle)hnd->ump_mem_handle); + } else if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_ION) { +#ifdef USE_PARTIAL_FLUSH + if (!release_rect((int)hnd->ump_id)) + LOGE("secure id: 0x%x, release error",(int)hnd->ump_id); +#endif + ump_mapped_pointer_release((ump_handle)hnd->ump_mem_handle); + ump_reference_release((ump_handle)hnd->ump_mem_handle); + + ion_unmap((void*)hnd->base, hnd->size); + ion_free(hnd->fd); + } + pthread_mutex_unlock(&l_surface); + delete hnd; + + return 0; +} + +static int alloc_device_close(struct hw_device_t *device) +{ + alloc_device_t* dev = reinterpret_cast(device); + if (dev) { + private_module_t* m = reinterpret_cast(dev->common.module); + if (ion_dev_open) + ion_client_destroy(m->ion_client); + delete dev; + ump_close(); + } + return 0; +} + +int alloc_device_open(hw_module_t const* module, const char* name, hw_device_t** device) +{ + alloc_device_t *dev; + + dev = new alloc_device_t; + if (NULL == dev) + return -1; + + dev->common.module = const_cast(module); + private_module_t* m = reinterpret_cast(dev->common.module); + m->ion_client = ion_client_create(); + ump_result ump_res = ump_open(); + if (0 > m->ion_client) + ion_dev_open = false; + if (UMP_OK != ump_res) { + LOGE("UMP open failed ump_res %d", ump_res); + delete dev; + return -1; + } + + /* initialize our state here */ + memset(dev, 0, sizeof(*dev)); + + /* initialize the procs */ + dev->common.tag = HARDWARE_DEVICE_TAG; + dev->common.version = 0; + dev->common.module = const_cast(module); + dev->common.close = alloc_device_close; + dev->alloc = alloc_device_alloc; + dev->free = alloc_device_free; + + *device = &dev->common; + + return 0; +} diff --git a/exynos4/hal/libgralloc_ump/alloc_device.h b/exynos4/hal/libgralloc_ump/alloc_device.h new file mode 100644 index 0000000..4609787 --- /dev/null +++ b/exynos4/hal/libgralloc_ump/alloc_device.h @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2010 ARM Limited. All rights reserved. + * + * Portions of this code have been modified from the original. + * These modifications are: + * * includes + * * alloc_device_open() + * + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +// Create an alloc device +int alloc_device_open(hw_module_t const* module, const char* name, hw_device_t** device); diff --git a/exynos4/hal/libgralloc_ump/framebuffer_device.cpp b/exynos4/hal/libgralloc_ump/framebuffer_device.cpp new file mode 100644 index 0000000..9413112 --- /dev/null +++ b/exynos4/hal/libgralloc_ump/framebuffer_device.cpp @@ -0,0 +1,465 @@ +/* + * Copyright (C) 2010 ARM Limited. All rights reserved. + * + * Portions of this code have been modified from the original. + * These modifications are: + * * includes + * * enums + * * fb_set_swap_interval() + * * fb_post() + * * init_frame_buffer_locked() + * * init_frame_buffer() + * * fb_close() + * * framebuffer_device_open() + * + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +#ifdef MALI_VSYNC_EVENT_REPORT_ENABLE +#include "gralloc_vsync_report.h" +#endif + +#include "gralloc_priv.h" +#include "gralloc_helper.h" + +#include "linux/fb.h" + +/* numbers of buffers for page flipping */ +#define NUM_BUFFERS 2 + +enum { + PAGE_FLIP = 0x00000001, +}; + +static int fb_set_swap_interval(struct framebuffer_device_t* dev, int interval) +{ + if (interval < dev->minSwapInterval || interval > dev->maxSwapInterval) + return -EINVAL; + + /* Currently not implemented */ + return 0; +} + +static int fb_post(struct framebuffer_device_t* dev, buffer_handle_t buffer) +{ + if (private_handle_t::validate(buffer) < 0) + return -EINVAL; + + private_handle_t const* hnd = reinterpret_cast(buffer); + private_module_t* m = reinterpret_cast(dev->common.module); + + if (m->currentBuffer) { + m->base.unlock(&m->base, m->currentBuffer); + m->currentBuffer = 0; + } + + if (hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER) { + m->base.lock(&m->base, buffer, private_module_t::PRIV_USAGE_LOCKED_FOR_POST, + 0, 0, m->info.xres, m->info.yres, NULL); + + const size_t offset = hnd->base - m->framebuffer->base; + int interrupt; + m->info.activate = FB_ACTIVATE_VBL; + m->info.yoffset = offset / m->finfo.line_length; + +#ifdef STANDARD_LINUX_SCREEN +#define FBIO_WAITFORVSYNC _IOW('F', 0x20, __u32) +#define S3CFB_SET_VSYNC_INT _IOW('F', 206, unsigned int) + if (ioctl(m->framebuffer->fd, FBIOPAN_DISPLAY, &m->info) == -1) { + LOGE("FBIOPAN_DISPLAY failed"); + m->base.unlock(&m->base, buffer); + return 0; + } + + if (m->enableVSync) { + /* enable VSYNC */ + interrupt = 1; + if (ioctl(m->framebuffer->fd, S3CFB_SET_VSYNC_INT, &interrupt) < 0) { + LOGE("S3CFB_SET_VSYNC_INT enable failed"); + return 0; + } + /* wait for VSYNC */ + +#ifdef MALI_VSYNC_EVENT_REPORT_ENABLE + gralloc_mali_vsync_report(MALI_VSYNC_EVENT_BEGIN_WAIT); +#endif + int crtc; + crtc = 0; + if (ioctl(m->framebuffer->fd, FBIO_WAITFORVSYNC, &crtc) < 0) { + LOGE("FBIO_WAITFORVSYNC failed"); +#ifdef MALI_VSYNC_EVENT_REPORT_ENABLE + gralloc_mali_vsync_report(MALI_VSYNC_EVENT_END_WAIT); +#endif + return 0; + } +#ifdef MALI_VSYNC_EVENT_REPORT_ENABLE + gralloc_mali_vsync_report(MALI_VSYNC_EVENT_END_WAIT); +#endif + // disable VSYNC + interrupt = 0; + if (ioctl(m->framebuffer->fd, S3CFB_SET_VSYNC_INT, &interrupt) < 0) { + LOGE("S3CFB_SET_VSYNC_INT disable failed"); + return 0; + } +#else + /*Standard Android way*/ +#ifdef MALI_VSYNC_EVENT_REPORT_ENABLE + gralloc_mali_vsync_report(MALI_VSYNC_EVENT_BEGIN_WAIT); +#endif + if (ioctl(m->framebuffer->fd, FBIOPUT_VSCREENINFO, &m->info) == -1) { + LOGE("FBIOPUT_VSCREENINFO failed"); +#ifdef MALI_VSYNC_EVENT_REPORT_ENABLE + gralloc_mali_vsync_report(MALI_VSYNC_EVENT_END_WAIT); +#endif + m->base.unlock(&m->base, buffer); + return -errno; + } +#ifdef MALI_VSYNC_EVENT_REPORT_ENABLE + gralloc_mali_vsync_report(MALI_VSYNC_EVENT_END_WAIT); +#endif +#endif + } + m->currentBuffer = buffer; + } else { + /* + * If we can't do the page_flip, just copy the buffer to the front + * FIXME: use copybit HAL instead of memcpy + */ + void* fb_vaddr; + void* buffer_vaddr; + + m->base.lock(&m->base, m->framebuffer, GRALLOC_USAGE_SW_WRITE_RARELY, + 0, 0, m->info.xres, m->info.yres, &fb_vaddr); + + m->base.lock(&m->base, buffer, GRALLOC_USAGE_SW_READ_RARELY, + 0, 0, m->info.xres, m->info.yres, &buffer_vaddr); + + memcpy(fb_vaddr, buffer_vaddr, m->finfo.line_length * m->info.yres); + + m->base.unlock(&m->base, buffer); + m->base.unlock(&m->base, m->framebuffer); + } + return 0; +} + +int init_frame_buffer_locked(struct private_module_t* module) +{ + /* Nothing to do, already initialized */ + if (module->framebuffer) + return 0; + + char const * const device_template[] = { + "/dev/graphics/fb%u", + "/dev/fb%u", + NULL + }; + + int fd = -1; + int i = 0; + char name[64]; + + while ((fd == -1) && device_template[i]) { + snprintf(name, 64, device_template[i], 0); + fd = open(name, O_RDWR, 0); + i++; + } + + if (fd < 0) + return -errno; + + struct fb_fix_screeninfo finfo; + if (ioctl(fd, FBIOGET_FSCREENINFO, &finfo) == -1) + return -errno; + + struct fb_var_screeninfo info; + if (ioctl(fd, FBIOGET_VSCREENINFO, &info) == -1) + return -errno; + + info.reserved[0] = 0; + info.reserved[1] = 0; + info.reserved[2] = 0; + info.xoffset = 0; + info.yoffset = 0; + info.activate = FB_ACTIVATE_NOW; + +#ifdef GRALLOC_16_BITS + /* + * Explicitly request 5/6/5 + */ + info.bits_per_pixel = 16; + info.red.offset = 11; + info.red.length = 5; + info.green.offset = 5; + info.green.length = 6; + info.blue.offset = 0; + info.blue.length = 5; + info.transp.offset = 0; + info.transp.length = 0; +#else + /* + * Explicitly request 8/8/8 + */ + info.bits_per_pixel = 32; + info.red.offset = 16; + info.red.length = 8; + info.green.offset = 8; + info.green.length = 8; + info.blue.offset = 0; + info.blue.length = 8; + info.transp.offset = 0; + info.transp.length = 0; +#endif + + /* + * Request NUM_BUFFERS screens (at lest 2 for page flipping) + */ + info.yres_virtual = info.yres * NUM_BUFFERS; + + uint32_t flags = PAGE_FLIP; + if (ioctl(fd, FBIOPUT_VSCREENINFO, &info) == -1) { + info.yres_virtual = info.yres; + flags &= ~PAGE_FLIP; + LOGW("FBIOPUT_VSCREENINFO failed, page flipping not supported"); + } + + if (info.yres_virtual < info.yres * 2) { + // we need at least 2 for page-flipping + info.yres_virtual = info.yres; + flags &= ~PAGE_FLIP; + LOGW("page flipping not supported (yres_virtual=%d, requested=%d)", + info.yres_virtual, info.yres * 2); + } + + if (ioctl(fd, FBIOGET_VSCREENINFO, &info) == -1) + return -errno; + + int refreshRate = 1000000000000000LLU / + ( + uint64_t( info.upper_margin + info.lower_margin + info.yres ) + * ( info.left_margin + info.right_margin + info.xres ) + * info.pixclock + ); + + if (refreshRate == 0) + refreshRate = 60 * 1000; /* 60 Hz */ + + if (int(info.width) <= 0 || int(info.height) <= 0) { + /* the driver doesn't return that information. default to 160 dpi */ + info.width = ((info.xres * 25.4f)/160.0f + 0.5f); + info.height = ((info.yres * 25.4f)/160.0f + 0.5f); + } + + float xdpi = (info.xres * 25.4f) / info.width; + float ydpi = (info.yres * 25.4f) / info.height; + float fps = refreshRate / 1000.0f; + + LOGI("using (fd=%d)\n" + "id = %s\n" + "xres = %d px\n" + "yres = %d px\n" + "xres_virtual = %d px\n" + "yres_virtual = %d px\n" + "bpp = %d\n" + "r = %2u:%u\n" + "g = %2u:%u\n" + "b = %2u:%u\n", + fd, + finfo.id, + info.xres, + info.yres, + info.xres_virtual, + info.yres_virtual, + info.bits_per_pixel, + info.red.offset, info.red.length, + info.green.offset, info.green.length, + info.blue.offset, info.blue.length); + + LOGI("width = %d mm (%f dpi)\n" + "height = %d mm (%f dpi)\n" + "refresh rate = %.2f Hz\n", + info.width, xdpi, + info.height, ydpi, + fps); + + if (ioctl(fd, FBIOGET_FSCREENINFO, &finfo) == -1) + return -errno; + + if (finfo.smem_len <= 0) + return -errno; + + module->flags = flags; + module->info = info; + module->finfo = finfo; + module->xdpi = xdpi; + module->ydpi = ydpi; + module->fps = fps; + + char value[32]; + property_get("debug.gralloc.vsync", value, "1"); + module->enableVSync = atoi(value); + /* + * map the framebuffer + */ + size_t fbSize = round_up_to_page_size(finfo.line_length * info.yres_virtual); + void* vaddr = mmap(0, fbSize, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); + if (vaddr == MAP_FAILED) { + LOGE("Error mapping the framebuffer (%s)", strerror(errno)); + return -errno; + } + + memset(vaddr, 0, fbSize); + + /* + * Create a "fake" buffer object for the entire frame buffer memory, + * and store it in the module + */ + module->framebuffer = new private_handle_t(private_handle_t::PRIV_FLAGS_FRAMEBUFFER, + fbSize, intptr_t(vaddr), 0, dup(fd), 0); + + module->numBuffers = info.yres_virtual / info.yres; + module->bufferMask = 0; + + return 0; +} + +int enableScreen(struct framebuffer_device_t* dev, int enable) +{ + private_module_t* m = reinterpret_cast(dev->common.module); + + if (enable == 1) { + if (ioctl(m->framebuffer->fd, FBIOBLANK, FB_BLANK_UNBLANK) < 0) { + LOGE("%s: FBIOBLANK failed : (%d:%s)", + __func__, m->framebuffer->fd, strerror(errno)); + return -EINVAL; + } + } else if (enable == 0) { + if (ioctl(m->framebuffer->fd, FBIOBLANK, FB_BLANK_POWERDOWN) < 0) { + LOGE("%s: FBIOBLANK failed : (%d:%s)", + __func__, m->framebuffer->fd, strerror(errno)); + return -EINVAL; + } + } else { + return -EINVAL; + } + return 0; +} +static int init_frame_buffer(struct private_module_t* module) +{ + pthread_mutex_lock(&module->lock); + int err = init_frame_buffer_locked(module); + pthread_mutex_unlock(&module->lock); + return err; +} + +static int fb_close(struct hw_device_t *device) +{ + framebuffer_device_t* dev = reinterpret_cast(device); + if (dev) { + ump_close(); + delete dev; + } + return 0; +} + +int compositionComplete(struct framebuffer_device_t* dev) +{ +#ifndef HWC_HWOVERLAY + unsigned char pixels[4]; + /* By doing a readpixel here we force the GL driver to start rendering + all the drawcalls up to this point, and to wait for the rendering to be complete. + Readpixel() also reads a dummy pixel, but this is not used. We only use this + function here to flush the render pipeline. */ + glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixels); + /* The rendering of the backbuffer is now completed. + When SurfaceFlinger later does a call to eglSwapBuffer(), the swap will be done + synchronously in the same thread, and not asynchronoulsy in a background thread later. + The SurfaceFlinger requires this behaviour since it releases the lock on all the + SourceBuffers (Layers) after the compositionComplete() function returns. + However this "bad" behaviour by SurfaceFlinger should not affect performance, + since the Applications that render the SourceBuffers (Layers) still get the + full renderpipeline using asynchronouls rendering. So they perform at maximum speed, + and because of their complexity compared to the Surface flinger jobs, the Surface flinger + is normally faster even if it does everyhing synchronous and serial. + */ +#endif + return 0; +} + +int framebuffer_device_open(hw_module_t const* module, const char* name, hw_device_t** device) +{ + int status = -EINVAL; + + alloc_device_t* gralloc_device; + status = gralloc_open(module, &gralloc_device); + if (status < 0) + return status; + + private_module_t* m = (private_module_t*)module; + status = init_frame_buffer(m); + if (status < 0) { + gralloc_close(gralloc_device); + return status; + } + + /* initialize our state here */ + framebuffer_device_t *dev = new framebuffer_device_t; + memset(dev, 0, sizeof(*dev)); + + /* initialize the procs */ + dev->common.tag = HARDWARE_DEVICE_TAG; + dev->common.version = 0; + dev->common.module = const_cast(module); + dev->common.close = fb_close; + dev->setSwapInterval = fb_set_swap_interval; + dev->post = fb_post; + dev->setUpdateRect = 0; + dev->compositionComplete = &compositionComplete; + dev->enableScreen = &enableScreen; + + int stride = m->finfo.line_length / (m->info.bits_per_pixel >> 3); + const_cast(dev->flags) = 0; + const_cast(dev->width) = m->info.xres; + const_cast(dev->height) = m->info.yres; + const_cast(dev->stride) = stride; +#ifdef GRALLOC_16_BITS + const_cast(dev->format) = HAL_PIXEL_FORMAT_RGB_565; +#else + const_cast(dev->format) = HAL_PIXEL_FORMAT_BGRA_8888; +#endif + const_cast(dev->xdpi) = m->xdpi; + const_cast(dev->ydpi) = m->ydpi; + const_cast(dev->fps) = m->fps; + const_cast(dev->minSwapInterval) = 1; + const_cast(dev->maxSwapInterval) = 1; + *device = &dev->common; + status = 0; + + return status; +} diff --git a/exynos4/hal/libgralloc_ump/framebuffer_device.h b/exynos4/hal/libgralloc_ump/framebuffer_device.h new file mode 100644 index 0000000..efcf1c3 --- /dev/null +++ b/exynos4/hal/libgralloc_ump/framebuffer_device.h @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2010 ARM Limited. All rights reserved. + * + * Portions of this code have been modified from the original. + * These modifications are: + * * includes + * * framebuffer_device_open() + * * init_frame_buffer_locked() + * + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +// Create a framebuffer device +int framebuffer_device_open(hw_module_t const* module, const char* name, hw_device_t** device); + +// Initialize the framebuffer (must keep module lock before calling +int init_frame_buffer_locked(struct private_module_t* module); \ No newline at end of file diff --git a/exynos4/hal/libgralloc_ump/gr.h b/exynos4/hal/libgralloc_ump/gr.h new file mode 100644 index 0000000..3a43aa7 --- /dev/null +++ b/exynos4/hal/libgralloc_ump/gr.h @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef GR_H_ +#define GR_H_ + +#include +#ifdef HAVE_ANDROID_OS // just want PAGE_SIZE define +# include +#else +# include +#endif +#include +#include +#include +#include +#include + +#include + +/*****************************************************************************/ + +struct private_module_t; +struct private_handle_t; + +inline size_t roundUpToPageSize(size_t x) { + return (x + (PAGE_SIZE-1)) & ~(PAGE_SIZE-1); +} + +int mapFrameBufferLocked(struct private_module_t* module); +int terminateBuffer(gralloc_module_t const* module, private_handle_t* hnd); +int mapBuffer(gralloc_module_t const* module, private_handle_t* hnd); + +/*****************************************************************************/ + +class Locker { + pthread_mutex_t mutex; +public: + class Autolock { + Locker& locker; + public: + inline Autolock(Locker& locker) : locker(locker) { locker.lock(); } + inline ~Autolock() { locker.unlock(); } + }; + inline Locker() { pthread_mutex_init(&mutex, 0); } + inline ~Locker() { pthread_mutex_destroy(&mutex); } + inline void lock() { pthread_mutex_lock(&mutex); } + inline void unlock() { pthread_mutex_unlock(&mutex); } +}; + +#endif /* GR_H_ */ diff --git a/exynos4/hal/libgralloc_ump/gralloc_helper.h b/exynos4/hal/libgralloc_ump/gralloc_helper.h new file mode 100644 index 0000000..21a5135 --- /dev/null +++ b/exynos4/hal/libgralloc_ump/gralloc_helper.h @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2010 ARM Limited. All rights reserved. + * + * Portions of this code have been modified from the original. + * These modifications are: + * * includes + * * round_up_to_page_size() + * + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef GRALLOC_HELPER_H_ +#define GRALLOC_HELPER_H_ + +#include + +inline size_t round_up_to_page_size(size_t x) +{ + return (x + (PAGE_SIZE-1)) & ~(PAGE_SIZE-1); +} + +#endif /* GRALLOC_HELPER_H_ */ diff --git a/exynos4/hal/libgralloc_ump/gralloc_module.cpp b/exynos4/hal/libgralloc_ump/gralloc_module.cpp new file mode 100644 index 0000000..fb8fc43 --- /dev/null +++ b/exynos4/hal/libgralloc_ump/gralloc_module.cpp @@ -0,0 +1,480 @@ +/* + * Copyright (C) 2010 ARM Limited. All rights reserved. + * + * Portions of this code have been modified from the original. + * These modifications are: + * * includes + * * enums + * * gralloc_device_open() + * * gralloc_register_buffer() + * * gralloc_unregister_buffer() + * * gralloc_lock() + * * gralloc_unlock() + * * gralloc_module_methods + * * HAL_MODULE_INFO_SYM + * + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "gralloc_priv.h" +#include "alloc_device.h" +#include "framebuffer_device.h" + +#include "ump.h" +#include "ump_ref_drv.h" +#include "s5p_fimc.h" +#include "exynos_mem.h" +static pthread_mutex_t s_map_lock = PTHREAD_MUTEX_INITIALIZER; +static pthread_mutex_t sMapLock = PTHREAD_MUTEX_INITIALIZER; + +static int s_ump_is_open = 0; +static int gMemfd = 0; +#define PFX_NODE_MEM "/dev/exynos-mem" + +/* we need this for now because pmem cannot mmap at an offset */ +#define PMEM_HACK 1 +#ifdef USE_PARTIAL_FLUSH +struct private_handle_rect *rect_list; + +private_handle_rect *find_rect(int secure_id) +{ + private_handle_rect *psRect; + + for (psRect = rect_list; psRect; psRect = psRect->next) + if (psRect->handle == secure_id) + break; + if (!psRect) + return NULL; + + return psRect; +} + +private_handle_rect *find_last_rect(int secure_id) +{ + private_handle_rect *psRect; + private_handle_rect *psFRect; + + if (rect_list == NULL) { + rect_list = (private_handle_rect *)calloc(1, sizeof(private_handle_rect)); + return rect_list; + } + + for (psRect = rect_list; psRect; psRect = psRect->next) { + if (psRect->handle == secure_id) + return psFRect; + psFRect = psRect; + } + return psFRect; +} + +int release_rect(int secure_id) +{ + private_handle_rect *psRect; + private_handle_rect *psTRect; + + for (psRect = rect_list; psRect; psRect = psRect->next) { + if (psRect->next) { + if (psRect->next->handle == secure_id) { + if (psRect->next->next) + psTRect = psRect->next->next; + else + psTRect = NULL; + + free(psRect->next); + psRect->next = psTRect; + return 1; + } + } + } + + return 0; +} +#endif + +static int gralloc_map(gralloc_module_t const* module, + buffer_handle_t handle, void** vaddr) +{ + private_handle_t* hnd = (private_handle_t*)handle; + if (!(hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER)) { + if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_IOCTL) { + size_t size = FIMC1_RESERVED_SIZE * 1024; + void *mappedAddress = mmap(0, size, + PROT_READ|PROT_WRITE, MAP_SHARED, gMemfd, (hnd->paddr - hnd->offset)); + if (mappedAddress == MAP_FAILED) { + LOGE("Could not mmap %s fd(%d)", strerror(errno),hnd->fd); + return -errno; + } + hnd->base = intptr_t(mappedAddress) + hnd->offset; + } else if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_ION) { + size_t size = hnd->size; + hnd->ion_client = ion_client_create(); + void *mappedAddress = ion_map(hnd->fd, size, 0); + + if (mappedAddress == MAP_FAILED) { + LOGE("Could not ion_map %s fd(%d)", strerror(errno), hnd->fd); + return -errno; + } + + hnd->base = intptr_t(mappedAddress) + hnd->offset; + } else { + size_t size = hnd->size; +#if PMEM_HACK + size += hnd->offset; +#endif + void *mappedAddress = mmap(0, size, + PROT_READ|PROT_WRITE, MAP_SHARED, hnd->fd, 0); + if (mappedAddress == MAP_FAILED) { + LOGE("Could not mmap %s fd(%d)", strerror(errno),hnd->fd); + return -errno; + } + hnd->base = intptr_t(mappedAddress) + hnd->offset; + } + } + *vaddr = (void*)hnd->base; + return 0; +} + +static int gralloc_unmap(gralloc_module_t const* module, + buffer_handle_t handle) +{ + private_handle_t* hnd = (private_handle_t*)handle; + if (!(hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER)) { + if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_IOCTL) { + void* base = (void*)(intptr_t(hnd->base) - hnd->offset); + size_t size = FIMC1_RESERVED_SIZE * 1024; + if (munmap(base, size) < 0) + LOGE("Could not unmap %s", strerror(errno)); + } else if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_ION) { + void* base = (void*)hnd->base; + size_t size = hnd->size; + if (ion_unmap(base, size) < 0) + LOGE("Could not ion_unmap %s", strerror(errno)); + ion_client_destroy(hnd->ion_client); + } else { + void* base = (void*)hnd->base; + size_t size = hnd->size; +#if PMEM_HACK + base = (void*)(intptr_t(base) - hnd->offset); + size += hnd->offset; +#endif + if (munmap(base, size) < 0) + LOGE("Could not unmap %s", strerror(errno)); + } + } + hnd->base = 0; + return 0; +} + +static int gralloc_device_open(const hw_module_t* module, const char* name, hw_device_t** device) +{ + int status = -EINVAL; + + if (!strcmp(name, GRALLOC_HARDWARE_GPU0)) + status = alloc_device_open(module, name, device); + else if (!strcmp(name, GRALLOC_HARDWARE_FB0)) + status = framebuffer_device_open(module, name, device); + + return status; +} + +static int gralloc_register_buffer(gralloc_module_t const* module, buffer_handle_t handle) +{ + int err = 0; + int retval = -EINVAL; + void *vaddr; + if (private_handle_t::validate(handle) < 0) { + LOGE("Registering invalid buffer, returning error"); + return -EINVAL; + } + + /* if this handle was created in this process, then we keep it as is. */ + private_handle_t* hnd = (private_handle_t*)handle; + +#ifdef USE_PARTIAL_FLUSH + if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_UMP) { + private_handle_rect *psRect; + private_handle_rect *psFRect; + psRect = (private_handle_rect *)calloc(1, sizeof(private_handle_rect)); + psRect->handle = (int)hnd->ump_id; + psRect->stride = (int)hnd->stride; + psFRect = find_last_rect((int)hnd->ump_id); + psFRect->next = psRect; + } +#endif + if (hnd->pid == getpid()) + return 0; + + if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_ION) + err = gralloc_map(module, handle, &vaddr); + + pthread_mutex_lock(&s_map_lock); + + if (!s_ump_is_open) { + ump_result res = ump_open(); /* TODO: Fix a ump_close() somewhere??? */ + if (res != UMP_OK) { + pthread_mutex_unlock(&s_map_lock); + LOGE("Failed to open UMP library"); + return retval; + } + s_ump_is_open = 1; + } + + if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_UMP) { + hnd->ump_mem_handle = (int)ump_handle_create_from_secure_id(hnd->ump_id); + if (UMP_INVALID_MEMORY_HANDLE != (ump_handle)hnd->ump_mem_handle) { + hnd->base = (int)ump_mapped_pointer_get((ump_handle)hnd->ump_mem_handle); + if (0 != hnd->base) { + hnd->lockState = private_handle_t::LOCK_STATE_MAPPED; + hnd->writeOwner = 0; + hnd->lockState = 0; + + pthread_mutex_unlock(&s_map_lock); + return 0; + } else { + LOGE("Failed to map UMP handle"); + } + + ump_reference_release((ump_handle)hnd->ump_mem_handle); + } else { + LOGE("Failed to create UMP handle"); + } + } else if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_PMEM) { + pthread_mutex_unlock(&s_map_lock); + return 0; + } else if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_IOCTL) { + void* vaddr = NULL; + + if (gMemfd == 0) { + gMemfd = open(PFX_NODE_MEM, O_RDWR); + if (gMemfd < 0) { + LOGE("%s:: %s exynos-mem open error\n", __func__, PFX_NODE_MEM); + return false; + } + } + + gralloc_map(module, handle, &vaddr); + pthread_mutex_unlock(&s_map_lock); + return 0; + } else if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_ION) { + hnd->ump_mem_handle = (int)ump_handle_create_from_secure_id(hnd->ump_id); + if (UMP_INVALID_MEMORY_HANDLE != (ump_handle)hnd->ump_mem_handle) { + vaddr = (void*)ump_mapped_pointer_get((ump_handle)hnd->ump_mem_handle); + if (0 != vaddr) { + hnd->lockState = private_handle_t::LOCK_STATE_MAPPED; + hnd->writeOwner = 0; + hnd->lockState = 0; + + pthread_mutex_unlock(&s_map_lock); + return 0; + } else { + LOGE("Failed to map UMP handle"); + } + ump_reference_release((ump_handle)hnd->ump_mem_handle); + } else { + LOGE("Failed to create UMP handle"); + } + } else { + LOGE("registering non-UMP buffer not supported"); + } + + pthread_mutex_unlock(&s_map_lock); + return retval; +} + +static int gralloc_unregister_buffer(gralloc_module_t const* module, buffer_handle_t handle) +{ + if (private_handle_t::validate(handle) < 0) { + LOGE("unregistering invalid buffer, returning error"); + return -EINVAL; + } + + private_handle_t* hnd = (private_handle_t*)handle; + +#ifdef USE_PARTIAL_FLUSH + if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_UMP) + if (!release_rect((int)hnd->ump_id)) + LOGE("secureID: 0x%x, release error", (int)hnd->ump_id); +#endif + LOGE_IF(hnd->lockState & private_handle_t::LOCK_STATE_READ_MASK, + "[unregister] handle %p still locked (state=%08x)", hnd, hnd->lockState); + + /* never unmap buffers that were created in this process */ + if (hnd->pid != getpid()) { + pthread_mutex_lock(&s_map_lock); + if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_UMP) { + ump_mapped_pointer_release((ump_handle)hnd->ump_mem_handle); + hnd->base = 0; + ump_reference_release((ump_handle)hnd->ump_mem_handle); + hnd->ump_mem_handle = (int)UMP_INVALID_MEMORY_HANDLE; + hnd->lockState = 0; + hnd->writeOwner = 0; + } else if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_IOCTL) { + if(hnd->base != 0) + gralloc_unmap(module, handle); + + pthread_mutex_unlock(&s_map_lock); + return 0; + } else if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_ION) { + ump_mapped_pointer_release((ump_handle)hnd->ump_mem_handle); + ump_reference_release((ump_handle)hnd->ump_mem_handle); + if (hnd->base) + gralloc_unmap(module, handle); + + hnd->base = 0; + hnd->ump_mem_handle = (int)UMP_INVALID_MEMORY_HANDLE; + hnd->lockState = 0; + hnd->writeOwner = 0; + } else { + LOGE("unregistering non-UMP buffer not supported"); + } + + pthread_mutex_unlock(&s_map_lock); + } + + return 0; +} + +static int gralloc_lock(gralloc_module_t const* module, buffer_handle_t handle, + int usage, int l, int t, int w, int h, void** vaddr) +{ + int err = 0; + if (private_handle_t::validate(handle) < 0) { + LOGE("Locking invalid buffer, returning error"); + return -EINVAL; + } + + private_handle_t* hnd = (private_handle_t*)handle; + +#ifdef SAMSUNG_EXYNOS_CACHE_UMP + if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_UMP) { +#ifdef USE_PARTIAL_FLUSH + private_handle_rect *psRect; + psRect = find_rect((int)hnd->ump_id); + psRect->l = l; + psRect->t = t; + psRect->w = w; + psRect->h= h; + psRect->locked = 1; +#endif + } +#endif + if (usage & (GRALLOC_USAGE_SW_READ_MASK | GRALLOC_USAGE_SW_WRITE_MASK)) + *vaddr = (void*)hnd->base; + + if (usage & GRALLOC_USAGE_YUV_ADDR) { + vaddr[0] = (void*)hnd->base; + vaddr[1] = (void*)(hnd->base + hnd->uoffset); + vaddr[2] = (void*)(hnd->base + hnd->uoffset + hnd->voffset); + } + return err; +} + +static int gralloc_unlock(gralloc_module_t const* module, buffer_handle_t handle) +{ + if (private_handle_t::validate(handle) < 0) { + LOGE("Unlocking invalid buffer, returning error"); + return -EINVAL; + } + + private_handle_t* hnd = (private_handle_t*)handle; + +#ifdef SAMSUNG_EXYNOS_CACHE_UMP + if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_UMP) { +#ifdef USE_PARTIAL_FLUSH + private_handle_rect *psRect; + psRect = find_rect((int)hnd->ump_id); + ump_cpu_msync_now((ump_handle)hnd->ump_mem_handle, UMP_MSYNC_CLEAN, + (void *)(hnd->base + (psRect->stride * psRect->t)), psRect->stride * psRect->h ); + return 0; +#endif + ump_cpu_msync_now((ump_handle)hnd->ump_mem_handle, UMP_MSYNC_CLEAN_AND_INVALIDATE, NULL, 0); + } +#endif + if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_ION) + ion_msync(hnd->ion_client, hnd->fd, IMSYNC_DEV_TO_RW | IMSYNC_SYNC_FOR_DEV, hnd->size, hnd->offset); + + if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_IOCTL) { + int ret; + exynos_mem_flush_range mem; + mem.start = hnd->paddr; + mem.length = hnd->size; + + ret = ioctl(gMemfd, EXYNOS_MEM_PADDR_CACHE_FLUSH, &mem); + if (ret < 0) { + LOGE("Error in exynos-mem : EXYNOS_MEM_PADDR_CACHE_FLUSH (%d)\n", ret); + return false; + } + } + + return 0; +} + +static int gralloc_getphys(gralloc_module_t const* module, buffer_handle_t handle, void** paddr) +{ + private_handle_t* hnd = (private_handle_t*)handle; + paddr[0] = (void*)hnd->paddr; + paddr[1] = (void*)(hnd->paddr + hnd->uoffset); + paddr[2] = (void*)(hnd->paddr + hnd->uoffset + hnd->voffset); + return 0; +} + +/* There is one global instance of the module */ +static struct hw_module_methods_t gralloc_module_methods = +{ + open: gralloc_device_open +}; + +struct private_module_t HAL_MODULE_INFO_SYM = +{ + base: + { + common: + { + tag: HARDWARE_MODULE_TAG, + version_major: 1, + version_minor: 0, + id: GRALLOC_HARDWARE_MODULE_ID, + name: "Graphics Memory Allocator Module", + author: "ARM Ltd.", + methods: &gralloc_module_methods, + dso: NULL, + reserved : {0,}, + }, + registerBuffer: gralloc_register_buffer, + unregisterBuffer: gralloc_unregister_buffer, + lock: gralloc_lock, + unlock: gralloc_unlock, + getphys: gralloc_getphys, + perform: NULL, + reserved_proc: {0,}, + }, + framebuffer: NULL, + flags: 0, + numBuffers: 0, + bufferMask: 0, + lock: PTHREAD_MUTEX_INITIALIZER, + currentBuffer: NULL, + ion_client: -1, +}; diff --git a/exynos4/hal/libhdmi/Android.mk b/exynos4/hal/libhdmi/Android.mk new file mode 100644 index 0000000..237c53c --- /dev/null +++ b/exynos4/hal/libhdmi/Android.mk @@ -0,0 +1,17 @@ +# Copyright (C) 2008 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +ifeq ($(filter-out exynos4,$(TARGET_BOARD_PLATFORM)),) +include $(all-subdir-makefiles) +endif diff --git a/exynos4/hal/libhdmi/SecHdmi/Android.mk b/exynos4/hal/libhdmi/SecHdmi/Android.mk new file mode 100644 index 0000000..e728309 --- /dev/null +++ b/exynos4/hal/libhdmi/SecHdmi/Android.mk @@ -0,0 +1,88 @@ +# Copyright (C) 2008 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +ifeq ($(BOARD_USES_HDMI),true) + +LOCAL_PATH:= $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_MODULE_TAGS := eng + +LOCAL_PRELINK_MODULE := false +#LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw +LOCAL_SHARED_LIBRARIES := libutils liblog libedid libcec + +LOCAL_SRC_FILES := \ + SecHdmiV4L2Utils.cpp \ + SecHdmi.cpp \ + fimd_api.c + +LOCAL_C_INCLUDES += $(LOCAL_PATH) +LOCAL_C_INCLUDES += $(LOCAL_PATH)/../../include + +ifeq ($(TARGET_SOC),exynos4210) +LOCAL_CFLAGS += -DSAMSUNG_EXYNOS4210 +endif + +ifeq ($(TARGET_SOC),exynos4x12) +LOCAL_CFLAGS += -DSAMSUNG_EXYNOS4x12 +endif + +LOCAL_CFLAGS += \ + -DSCREEN_WIDTH=$(SCREEN_WIDTH) \ + -DSCREEN_HEIGHT=$(SCREEN_HEIGHT) \ + -DDEFAULT_FB_NUM=$(DEFAULT_FB_NUM) + +LOCAL_SHARED_LIBRARIES += libfimc + +ifeq ($(BOARD_USES_HDMI_SUBTITLES),true) +LOCAL_CFLAGS += -DBOARD_USES_HDMI_SUBTITLES +endif + +ifeq ($(BOARD_USES_FIMGAPI),true) +LOCAL_CFLAGS += -DBOARD_USES_FIMGAPI +LOCAL_C_INCLUDES += $(TARGET_HAL_PATH)/libfimg4x +LOCAL_C_INCLUDES += external/skia/include/core +LOCAL_SHARED_LIBRARIES += libfimg +endif + +ifeq ($(BOARD_HDMI_STD), STD_NTSC_M) +LOCAL_CFLAGS += -DSTD_NTSC_M +endif + +ifeq ($(BOARD_HDMI_STD),STD_480P) +LOCAL_CFLAGS += -DSTD_480P +endif + +ifeq ($(BOARD_HDMI_STD),STD_720P) +LOCAL_CFLAGS += -DSTD_720P +endif + +ifeq ($(BOARD_HDMI_STD),STD_1080P) +LOCAL_CFLAGS += -DSTD_1080P +endif + +ifeq ($(BOARD_USE_V4L2),true) +LOCAL_CFLAGS += -DBOARD_USE_V4L2 +endif + +ifeq ($(BOARD_USE_V4L2_ION),true) +LOCAL_CFLAGS += -DBOARD_USE_V4L2_ION +LOCAL_SHARED_LIBRARIES += libion +endif + +LOCAL_MODULE := libhdmi +include $(BUILD_SHARED_LIBRARY) + +endif diff --git a/exynos4/hal/libhdmi/SecHdmi/SecHdmi.cpp b/exynos4/hal/libhdmi/SecHdmi/SecHdmi.cpp new file mode 100644 index 0000000..444a9db --- /dev/null +++ b/exynos4/hal/libhdmi/SecHdmi/SecHdmi.cpp @@ -0,0 +1,1957 @@ +/* + * Copyright@ Samsung Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +//#define LOG_NDEBUG 0 +//#define LOG_TAG "libhdmi" +#include + +#if defined(BOARD_USE_V4L2_ION) +#include "ion.h" +#endif + +#include "SecHdmi.h" +#include "SecHdmiV4L2Utils.h" + +#define CHECK_GRAPHIC_LAYER_TIME (0) + +namespace android { + +extern unsigned int output_type; +#if defined(BOARD_USE_V4L2) +extern unsigned int g_preset_id; +#endif +extern v4l2_std_id t_std_id; +extern int g_hpd_state; +extern unsigned int g_hdcp_en; + +#if !defined(BOARD_USE_V4L2) +extern int fp_tvout; +extern int fp_tvout_v; +extern int fp_tvout_g0; +extern int fp_tvout_g1; +#endif + +#if defined(BOARD_USES_FIMGAPI) +extern unsigned int g2d_reserved_memory[HDMI_G2D_OUTPUT_BUF_NUM]; +extern unsigned int g2d_reserved_memory_size; +extern unsigned int cur_g2d_address; +extern unsigned int g2d_buf_index; +#endif + +#if defined(BOARD_USES_CEC) +SecHdmi::CECThread::~CECThread() +{ +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("%s", __func__); +#endif + mFlagRunning = false; +} + +bool SecHdmi::CECThread::threadLoop() +{ + unsigned char buffer[CEC_MAX_FRAME_SIZE]; + int size; + unsigned char lsrc, ldst, opcode; + + { + Mutex::Autolock lock(mThreadLoopLock); + mFlagRunning = true; + + size = CECReceiveMessage(buffer, CEC_MAX_FRAME_SIZE, 100000); + + if (!size) // no data available or ctrl-c + return true; + + if (size == 1) + return true; // "Polling Message" + + lsrc = buffer[0] >> 4; + + /* ignore messages with src address == mLaddr*/ + if (lsrc == mLaddr) + return true; + + opcode = buffer[1]; + + if (CECIgnoreMessage(opcode, lsrc)) { + LOGE("### ignore message coming from address 15 (unregistered)\n"); + return true; + } + + if (!CECCheckMessageSize(opcode, size)) { + LOGE("### invalid message size: %d(opcode: 0x%x) ###\n", size, opcode); + return true; + } + + /* check if message broadcasted/directly addressed */ + if (!CECCheckMessageMode(opcode, (buffer[0] & 0x0F) == CEC_MSG_BROADCAST ? 1 : 0)) { + LOGE("### invalid message mode (directly addressed/broadcast) ###\n"); + return true; + } + + ldst = lsrc; + + //TODO: macroses to extract src and dst logical addresses + //TODO: macros to extract opcode + + switch (opcode) { + case CEC_OPCODE_GIVE_PHYSICAL_ADDRESS: + /* responce with "Report Physical Address" */ + buffer[0] = (mLaddr << 4) | CEC_MSG_BROADCAST; + buffer[1] = CEC_OPCODE_REPORT_PHYSICAL_ADDRESS; + buffer[2] = (mPaddr >> 8) & 0xFF; + buffer[3] = mPaddr & 0xFF; + buffer[4] = mDevtype; + size = 5; + break; + + case CEC_OPCODE_REQUEST_ACTIVE_SOURCE: + LOGD("[CEC_OPCODE_REQUEST_ACTIVE_SOURCE]\n"); + /* responce with "Active Source" */ + buffer[0] = (mLaddr << 4) | CEC_MSG_BROADCAST; + buffer[1] = CEC_OPCODE_ACTIVE_SOURCE; + buffer[2] = (mPaddr >> 8) & 0xFF; + buffer[3] = mPaddr & 0xFF; + size = 4; + LOGD("Tx : [CEC_OPCODE_ACTIVE_SOURCE]\n"); + break; + + case CEC_OPCODE_ABORT: + case CEC_OPCODE_FEATURE_ABORT: + default: + /* send "Feature Abort" */ + buffer[0] = (mLaddr << 4) | ldst; + buffer[1] = CEC_OPCODE_FEATURE_ABORT; + buffer[2] = CEC_OPCODE_ABORT; + buffer[3] = 0x04; // "refused" + size = 4; + break; + } + + if (CECSendMessage(buffer, size) != size) + LOGE("CECSendMessage() failed!!!\n"); + + } + return true; +} + +bool SecHdmi::CECThread::start() +{ +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("%s", __func__); +#endif + + Mutex::Autolock lock(mThreadControlLock); + if (exitPending()) { + if (requestExitAndWait() == WOULD_BLOCK) { + LOGE("mCECThread.requestExitAndWait() == WOULD_BLOCK"); + return false; + } + } + +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("EDIDGetCECPhysicalAddress"); +#endif + /* set to not valid physical address */ + mPaddr = CEC_NOT_VALID_PHYSICAL_ADDRESS; + + if (!EDIDGetCECPhysicalAddress(&mPaddr)) { + LOGE("Error: EDIDGetCECPhysicalAddress() failed.\n"); + return false; + } + +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("CECOpen"); +#endif + if (!CECOpen()) { + LOGE("CECOpen() failed!!!\n"); + return false; + } + + /* a logical address should only be allocated when a device \ + has a valid physical address, at all other times a device \ + should take the 'Unregistered' logical address (15) + */ + + /* if physical address is not valid device should take \ + the 'Unregistered' logical address (15) + */ + +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("CECAllocLogicalAddress"); +#endif + mLaddr = CECAllocLogicalAddress(mPaddr, mDevtype); + + if (!mLaddr) { + LOGE("CECAllocLogicalAddress() failed!!!\n"); + if (!CECClose()) + LOGE("CECClose() failed!\n"); + return false; + } + +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("request to run CECThread"); +#endif + + status_t ret = run("SecHdmi::CECThread", PRIORITY_DISPLAY); + if (ret != NO_ERROR) { + LOGE("%s fail to run thread", __func__); + return false; + } + return true; +} + +bool SecHdmi::CECThread::stop() +{ +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("%s request Exit", __func__); +#endif + Mutex::Autolock lock(mThreadControlLock); + if (requestExitAndWait() == WOULD_BLOCK) { + LOGE("mCECThread.requestExitAndWait() == WOULD_BLOCK"); + return false; + } + + if (!CECClose()) + LOGE("CECClose() failed!\n"); + + mFlagRunning = false; + return true; +} +#endif + +SecHdmi::SecHdmi(): +#if defined(BOARD_USES_CEC) + mCECThread(NULL), +#endif + mFlagCreate(false), + mFlagConnected(false), + mHdmiDstWidth(0), + mHdmiDstHeight(0), + mHdmiSrcYAddr(0), + mHdmiSrcCbCrAddr(0), + mHdmiOutputMode(DEFAULT_OUPUT_MODE), + mHdmiResolutionValue(DEFAULT_HDMI_RESOLUTION_VALUE), // V4L2_STD_480P_60_4_3 + mCompositeStd(DEFAULT_COMPOSITE_STD), + mHdcpMode(false), + mAudioMode(2), + mUIRotVal(0), + mG2DUIRotVal(0), + mCurrentHdmiOutputMode(-1), + mCurrentHdmiResolutionValue(0), // 1080960 + mCurrentHdcpMode(false), + mCurrentAudioMode(-1), + mHdmiInfoChange(true), + mFimcDstColorFormat(0), + mFimcCurrentOutBufIndex(0), + mFBaddr(NULL), + mFBsize(0), + mFBionfd(-1), + mFBIndex(0), + mDefaultFBFd(-1), + mDisplayWidth(DEFALULT_DISPLAY_WIDTH), + mDisplayHeight(DEFALULT_DISPLAY_HEIGHT) +{ +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("%s", __func__); +#endif + for (int i = 0; i < HDMI_LAYER_MAX; i++) { + mFlagLayerEnable[i] = false; + mFlagHdmiStart[i] = false; + + mSrcWidth [i] = 0; + mSrcHeight [i] = 0; + mSrcColorFormat[i] = 0; + mHdmiResolutionWidth [i] = 0; + mHdmiResolutionHeight [i] = 0; + mHdmiFd[i] = -1; + mDstWidth [i] = 0; + mDstHeight [i] = 0; + mPrevDstWidth [i] = 0; + mPrevDstHeight [i] = 0; + } + + mHdmiPresetId = DEFAULT_HDMI_PRESET_ID; + mHdmiStdId = DEFAULT_HDMI_STD_ID; + + //All layer is on + mFlagLayerEnable[HDMI_LAYER_VIDEO] = true; + mFlagLayerEnable[HDMI_LAYER_GRAPHIC_0] = true; + mFlagLayerEnable[HDMI_LAYER_GRAPHIC_1] = true; + + mHdmiSizeOfResolutionValueList = 14; + + mHdmiResolutionValueList[0] = 1080960; + mHdmiResolutionValueList[1] = 1080950; + mHdmiResolutionValueList[2] = 1080930; + mHdmiResolutionValueList[3] = 1080924; + mHdmiResolutionValueList[4] = 1080160; + mHdmiResolutionValueList[5] = 1080150; + mHdmiResolutionValueList[6] = 720960; + mHdmiResolutionValueList[7] = 7209601; + mHdmiResolutionValueList[8] = 720950; + mHdmiResolutionValueList[9] = 7209501; + mHdmiResolutionValueList[10] = 5769501; + mHdmiResolutionValueList[11] = 5769502; + mHdmiResolutionValueList[12] = 4809601; + mHdmiResolutionValueList[13] = 4809602; + +#if defined(BOARD_USES_CEC) + mCECThread = new CECThread(this); +#endif + + SecBuffer zeroBuf; + for (int i = 0; i < HDMI_FIMC_OUTPUT_BUF_NUM; i++) + mFimcReservedMem[i] = zeroBuf; +#if defined(BOARD_USE_V4L2) + for (int i = 0; i < HDMI_LAYER_MAX; i++) + for (int j = 0; j < MAX_BUFFERS_MIXER; j++) + mMixerBuffer[i][j] = zeroBuf; +#endif + + memset(&mDstRect, 0 , sizeof(struct v4l2_rect)); +} + +SecHdmi::~SecHdmi() +{ +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("%s", __func__); +#endif + if (mFlagCreate == true) + LOGE("%s::this is not Destroyed fail", __func__); + else + disconnect(); +} + +bool SecHdmi::create(int width, int height) +{ + Mutex::Autolock lock(mLock); + unsigned int fimc_buf_size = 0; + unsigned int gralloc_buf_size = 0; + mFimcCurrentOutBufIndex = 0; + int stride; + int vstride; + int BufNum = 0; +#if defined(BOARD_USE_V4L2_ION) + int IonClient = -1; + int IonFd = -1; + void *ion_base_addr = NULL; +#endif + +/* + * Video plaback (I420): output buffer size of FIMC3 is (1920 x 1088 x 1.5) + * Video plaback (NV12): FIMC3 is not used. + * Camera preview (YV12): output buffer size of FIMC3 is (640 x 480 x 1.5) + * UI mode (ARGB8888) : output buffer size of FIMC3 is (480 x 800 x 1.5) + */ +#ifndef SUPPORT_1080P_FIMC_OUT + setDisplaySize(width, height); +#endif + + stride = ALIGN(HDMI_MAX_WIDTH, 16); + vstride = ALIGN(HDMI_MAX_HEIGHT, 16); + + fimc_buf_size = stride * vstride * HDMI_FIMC_BUFFER_BPP_SIZE; + gralloc_buf_size = GRALLOC_BUF_SIZE * SIZE_1K; +#if defined(BOARD_USES_FIMGAPI) + g2d_reserved_memory_size = stride * vstride * HDMI_G2D_BUFFER_BPP_SIZE; +#endif + +#ifdef DEBUG_MSG_ENABLE + LOGD("%s", __func__); +#endif + + if (mFlagCreate == true) { + LOGE("%s::Already Created fail", __func__); + goto CREATE_FAIL; + } + + if (mDefaultFBFd <= 0) { + if ((mDefaultFBFd = fb_open(DEFAULT_FB)) < 0) { + LOGE("%s:Failed to open default FB", __func__); + return false; + } + } + +#ifdef BOARD_USE_V4L2 + BufNum = HDMI_FIMC_OUTPUT_BUF_NUM; +#else + BufNum = 1; +#endif + + if (mSecFimc.create(SecFimc::DEV_3, SecFimc::MODE_SINGLE_BUF, BufNum) == false) { + LOGE("%s::SecFimc create() fail", __func__); + goto CREATE_FAIL; + } + +#if defined(BOARD_USE_V4L2_ION) + IonClient = ion_client_create(); + if (IonClient < 0) { + LOGE("%s::ion_client_create() failed", __func__); + goto CREATE_FAIL; + } +#if defined(BOARD_USES_FIMGAPI) + IonFd = ion_alloc(IonClient, g2d_reserved_memory_size * HDMI_G2D_OUTPUT_BUF_NUM, 0, ION_HEAP_EXYNOS_MASK); + + if (IonFd < 0) { + LOGE("%s::ION memory allocation failed", __func__); + } else { + ion_base_addr = ion_map(IonFd, ALIGN(g2d_reserved_memory_size * HDMI_G2D_OUTPUT_BUF_NUM, PAGE_SIZE), 0); + if (ion_base_addr == MAP_FAILED) + LOGE("%s::ION mmap failed", __func__); + } + + for (int i = 0; i < HDMI_G2D_OUTPUT_BUF_NUM; i++) + g2d_reserved_memory[i] = ion_base_addr + (g2d_reserved_memory_size * i); +#endif +#else +#ifndef BOARD_USE_V4L2 + for (int i = 0; i < HDMI_FIMC_OUTPUT_BUF_NUM; i++) + mFimcReservedMem[i].phys.p = mSecFimc.getMemAddr()->phys.p + gralloc_buf_size + (fimc_buf_size * i); +#endif + +#if defined(BOARD_USES_FIMGAPI) +#if defined(BOARD_USES_HDMI_SUBTITLES) + for (int i = 0; i < HDMI_G2D_OUTPUT_BUF_NUM; i++) + g2d_reserved_memory[i] = mFimcReservedMem[HDMI_FIMC_OUTPUT_BUF_NUM - 1].phys.p + fimc_buf_size + (g2d_reserved_memory_size * i); +#else + for (int i = 0; i < HDMI_G2D_OUTPUT_BUF_NUM; i++) + g2d_reserved_memory[i] = mSecFimc.getMemAddr()->phys.p + gralloc_buf_size + (g2d_reserved_memory_size * i); +#endif +#endif +#endif + + v4l2_std_id std_id; + +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("%s::mHdmiOutputMode(%d) \n", __func__, mHdmiOutputMode); +#endif + if (mHdmiOutputMode == COMPOSITE_OUTPUT_MODE) { + std_id = composite_std_2_v4l2_std_id(mCompositeStd); + if ((int)std_id < 0) { + LOGE("%s::composite_std_2_v4l2_std_id(%d) fail\n", __func__, mCompositeStd); + goto CREATE_FAIL; + } + if (m_setCompositeResolution(mCompositeStd) == false) { + LOGE("%s::m_setCompositeResolution(%d) fail\n", __func__, mCompositeStd); + goto CREATE_FAIL; + } + } else if (mHdmiOutputMode >= HDMI_OUTPUT_MODE_YCBCR && + mHdmiOutputMode <= HDMI_OUTPUT_MODE_DVI) { +#if defined(BOARD_USE_V4L2) + unsigned int preset_id; + + if (hdmi_resolution_2_preset_id(mHdmiResolutionValue, &mHdmiDstWidth, &mHdmiDstHeight, &preset_id) < 0) { + LOGE("%s::hdmi_resolution_2_preset_id(%d) fail\n", __func__, mHdmiResolutionValue); + goto CREATE_FAIL; + } +#else + if (hdmi_resolution_2_std_id(mHdmiResolutionValue, &mHdmiDstWidth, &mHdmiDstHeight, &std_id) < 0) { + LOGE("%s::hdmi_resolution_2_std_id(%d) fail\n", __func__, mHdmiResolutionValue); + goto CREATE_FAIL; + } +#endif + } + + mFlagCreate = true; + + return true; + +CREATE_FAIL : + + if (mSecFimc.flagCreate() == true && + mSecFimc.destroy() == false) + LOGE("%s::fimc destory fail", __func__); + + return false; +} + +bool SecHdmi::destroy(void) +{ +#ifdef DEBUG_MSG_ENABLE + LOGD("%s", __func__); +#endif + + Mutex::Autolock lock(mLock); + + if (mFlagCreate == false) { + LOGE("%s::Already Destroyed fail \n", __func__); + goto DESTROY_FAIL; + } + + for (int layer = HDMI_LAYER_BASE + 1; layer <= HDMI_LAYER_GRAPHIC_0; layer++) { + if (mFlagHdmiStart[layer] == true && m_stopHdmi(layer) == false) { + LOGE("%s::m_stopHdmi: layer[%d] fail \n", __func__, layer); + goto DESTROY_FAIL; + } + + if (hdmi_deinit_layer(layer) < 0) { + LOGE("%s::hdmi_deinit_layer(%d) fail \n", __func__, layer); + goto DESTROY_FAIL; + } + } + +#if !defined(BOARD_USE_V4L2) + tvout_deinit(); +#endif + + if (mSecFimc.flagCreate() == true && mSecFimc.destroy() == false) { + LOGE("%s::fimc destory fail \n", __func__); + goto DESTROY_FAIL; + } + +#ifdef USE_LCD_ADDR_IN_HERE + { + if (0 < mDefaultFBFd) { + close(mDefaultFBFd); + mDefaultFBFd = -1; + } + } +#endif //USE_LCD_ADDR_IN_HERE + +#if defined(BOARD_USE_V4L2_ION) + if (mFBaddr != NULL) + ion_unmap((void *)mFBaddr, ALIGN(mFBsize * 4 * 2, PAGE_SIZE)); + + if (mFBionfd > 0) + ion_free(mFBionfd); + + mFBaddr = NULL; + mFBionfd = -1; + mFBsize = 0; +#endif + +#if defined(BOARD_USE_V4L2_ION) && defined(BOARD_USES_FIMGAPI) + ion_unmap((void *)g2d_reserved_memory[0], ALIGN(g2d_reserved_memory_size * HDMI_G2D_OUTPUT_BUF_NUM, PAGE_SIZE)); +#endif + + mFlagCreate = false; + + return true; + +DESTROY_FAIL : + + return false; +} + +bool SecHdmi::connect(void) +{ +#ifdef DEBUG_MSG_ENABLE + LOGD("%s", __func__); +#endif + + { + Mutex::Autolock lock(mLock); + + if (mFlagCreate == false) { + LOGE("%s::Not Yet Created \n", __func__); + return false; + } + + if (mFlagConnected == true) { + LOGD("%s::Already Connected.. \n", __func__); + return true; + } + + if (mHdmiOutputMode >= HDMI_OUTPUT_MODE_YCBCR && + mHdmiOutputMode <= HDMI_OUTPUT_MODE_DVI) { + if (m_flagHWConnected() == false) { + LOGD("%s::m_flagHWConnected() fail \n", __func__); + return false; + } + +#if defined(BOARD_USES_EDID) + if (!EDIDOpen()) + LOGE("EDIDInit() failed!\n"); + + if (!EDIDRead()) { + LOGE("EDIDRead() failed!\n"); + if (!EDIDClose()) + LOGE("EDIDClose() failed!\n"); + } +#endif + +#if defined(BOARD_USES_CEC) + if (!(mCECThread->mFlagRunning)) + mCECThread->start(); +#endif + } + } + + if (this->setHdmiOutputMode(mHdmiOutputMode, true) == false) + LOGE("%s::setHdmiOutputMode(%d) fail \n", __func__, mHdmiOutputMode); + + if (mHdmiOutputMode >= HDMI_OUTPUT_MODE_YCBCR && + mHdmiOutputMode <= HDMI_OUTPUT_MODE_DVI) { + if (this->setHdmiResolution(mHdmiResolutionValue, true) == false) + LOGE("%s::setHdmiResolution(%d) fail \n", __func__, mHdmiResolutionValue); + + if (this->setHdcpMode(mHdcpMode, false) == false) + LOGE("%s::setHdcpMode(%d) fail \n", __func__, mHdcpMode); + + mHdmiInfoChange = true; + mFlagConnected = true; + +#if defined(BOARD_USES_EDID) + // show display.. + display_menu(); +#endif + } + + return true; +} + +bool SecHdmi::disconnect(void) +{ +#ifdef DEBUG_MSG_ENABLE + LOGD("%s", __func__); +#endif + + Mutex::Autolock lock(mLock); + + if (mFlagCreate == false) { + LOGE("%s::Not Yet Created \n", __func__); + return false; + } + + if (mFlagConnected == false) { + LOGE("%s::Already Disconnected.. \n", __func__); + return true; + } + + if (mHdmiOutputMode >= HDMI_OUTPUT_MODE_YCBCR && + mHdmiOutputMode <= HDMI_OUTPUT_MODE_DVI) { +#if defined(BOARD_USES_CEC) + if (mCECThread->mFlagRunning) + mCECThread->stop(); +#endif + +#if defined(BOARD_USES_EDID) + if (!EDIDClose()) { + LOGE("EDIDClose() failed!\n"); + return false; + } +#endif + } + + for (int layer = SecHdmi::HDMI_LAYER_BASE + 1; layer <= SecHdmi::HDMI_LAYER_GRAPHIC_0; layer++) { + if (mFlagHdmiStart[layer] == true && m_stopHdmi(layer) == false) { + LOGE("%s::hdmiLayer(%d) layer fail \n", __func__, layer); + return false; + } + } + +#if defined(BOARD_USE_V4L2) + for (int layer = HDMI_LAYER_BASE + 1; layer < HDMI_LAYER_MAX; layer++) { + if (hdmi_deinit_layer(layer) < 0) + LOGE("%s::hdmi_deinit_layer(%d) fail", __func__, layer); + } +#else + tvout_deinit(); +#endif + + mFlagConnected = false; + + mHdmiOutputMode = DEFAULT_OUPUT_MODE; + mHdmiResolutionValue = DEFAULT_HDMI_RESOLUTION_VALUE; +#if defined(BOARD_USE_V4L2) + mHdmiPresetId = DEFAULT_HDMI_PRESET_ID; +#else + mHdmiStdId = DEFAULT_HDMI_STD_ID; +#endif + mCompositeStd = DEFAULT_COMPOSITE_STD; + mAudioMode = 2; + mCurrentHdmiOutputMode = -1; + mCurrentHdmiResolutionValue = 0; + mCurrentAudioMode = -1; + mFimcCurrentOutBufIndex = 0; + + return true; +} + +bool SecHdmi::flagConnected(void) +{ +#ifdef DEBUG_MSG_ENABLE + LOGD("%s", __func__); +#endif + + Mutex::Autolock lock(mLock); + + if (mFlagCreate == false) { + LOGE("%s::Not Yet Created \n", __func__); + return false; + } + + return mFlagConnected; +} + +bool SecHdmi::flush(int srcW, int srcH, int srcColorFormat, + unsigned int srcYAddr, unsigned int srcCbAddr, unsigned int srcCrAddr, + int dstX, int dstY, + int hdmiLayer, + int num_of_hwc_layer) +{ +#ifdef DEBUG_MSG_ENABLE + LOGD("%s [srcW=%d, srcH=%d, srcColorFormat=0x%x, srcYAddr=0x%x, srcCbAddr=0x%x, srcCrAddr=0x%x, dstX=%d, dstY=%d, hdmiLayer=%d]", + __func__, srcW, srcH, srcColorFormat, srcYAddr, srcCbAddr, srcCrAddr, dstX, dstY, hdmiLayer); +#endif + + Mutex::Autolock lock(mLock); + + if (mFlagCreate == false) { + LOGE("%s::Not Yet Created \n", __func__); + return false; + } + +#if defined(BOARD_USE_V4L2) + if (hdmiLayer == HDMI_LAYER_VIDEO) { + mDstWidth[hdmiLayer] = mHdmiDstWidth; + mDstHeight[hdmiLayer] = mHdmiDstHeight; + } else { + if (num_of_hwc_layer == 0) { + struct v4l2_rect rect; + int tempSrcW, tempSrcH; + + if (mG2DUIRotVal == 0 || mG2DUIRotVal == 180) { + tempSrcW = srcW; + tempSrcH = srcH; + } else { + tempSrcW = srcH; + tempSrcH = srcW; + } + + hdmi_cal_rect(tempSrcW, tempSrcH, mHdmiDstWidth, mHdmiDstHeight, &rect); + mDstWidth[hdmiLayer] = rect.width; + mDstHeight[hdmiLayer] = rect.height; + mDstWidth[HDMI_LAYER_VIDEO] = 0; + mDstHeight[HDMI_LAYER_VIDEO] = 0; + } else { + mDstWidth[hdmiLayer] = mHdmiDstWidth; + mDstHeight[hdmiLayer] = mHdmiDstHeight; + } + } +#ifdef DEBUG_MSG_ENABLE + LOGE("m_reset param(%d, %d, %d, %d)", + mDstWidth[hdmiLayer], mDstHeight[hdmiLayer], \ + mPrevDstWidth[hdmiLayer], mPrevDstHeight[hdmiLayer]); +#endif +#endif + + if (srcW != mSrcWidth[hdmiLayer] || + srcH != mSrcHeight[hdmiLayer] || + srcColorFormat != mSrcColorFormat[hdmiLayer] || + mHdmiDstWidth != mHdmiResolutionWidth[hdmiLayer] || + mHdmiDstHeight != mHdmiResolutionHeight[hdmiLayer] || +#if defined(BOARD_USE_V4L2) + mDstWidth[hdmiLayer] != mPrevDstWidth[hdmiLayer] || + mDstHeight[hdmiLayer] != mPrevDstHeight[hdmiLayer] || +#endif + mHdmiInfoChange == true) { +#ifdef DEBUG_MSG_ENABLE + LOGD("m_reset param(%d, %d, %d, %d, %d, %d, %d)", + srcW, mSrcWidth[hdmiLayer], \ + srcH, mSrcHeight[hdmiLayer], \ + srcColorFormat,mSrcColorFormat[hdmiLayer], \ + hdmiLayer); +#endif + + if (m_reset(srcW, srcH, srcColorFormat, hdmiLayer, num_of_hwc_layer) == false) { + LOGE("%s::m_reset(%d, %d, %d, %d, %d) fail", __func__, srcW, srcH, srcColorFormat, hdmiLayer, num_of_hwc_layer); + return false; + } + } + + if (srcYAddr == 0) { +#if defined(BOARD_USE_V4L2_ION) + unsigned int FB_size = ALIGN(srcW, 16) * ALIGN(srcH, 16) * HDMI_FB_BPP_SIZE; + void *virFBAddr = 0; + struct s3c_fb_user_ion_client ion_handle; + + if (mFBaddr != NULL) { + ion_unmap((void *)mFBaddr, ALIGN(mFBsize * 2, PAGE_SIZE)); + ion_free(mFBionfd); + } + + // get framebuffer virtual address for LCD + if (ioctl(mDefaultFBFd, S3CFB_GET_ION_USER_HANDLE, &ion_handle) < 0) { + LOGE("%s:ioctl(S3CFB_GET_ION_USER_HANDLE) fail", __func__); + return false; + } + + virFBAddr = ion_map(ion_handle.fd, ALIGN(FB_size * 2, PAGE_SIZE), 0); + if (virFBAddr == MAP_FAILED) { + LOGE("%s::ion_map fail", __func__); + ion_free(ion_handle.fd); + mFBaddr = NULL; + return false; + } + + if ((mFBIndex % 2) == 0) + srcYAddr = (unsigned int)virFBAddr; + else + srcYAddr = (unsigned int)virFBAddr + FB_size; + + srcCbAddr = srcYAddr; + + mFBIndex++; + mFBaddr = virFBAddr; + mFBsize = FB_size; + mFBionfd = ion_handle.fd; +#else + unsigned int phyFBAddr = 0; + + // get physical framebuffer address for LCD + if (ioctl(mDefaultFBFd, S3CFB_GET_FB_PHY_ADDR, &phyFBAddr) == -1) { + LOGE("%s:ioctl(S3CFB_GET_FB_PHY__ADDR) fail", __func__); + return false; + } + + /* + * when early suspend, FIMD IP off. + * so physical framebuffer address for LCD is 0x00000000 + * so JUST RETURN. + */ + if (phyFBAddr == 0) { + LOGE("%s::S3CFB_GET_FB_PHY_ADDR fail", __func__); + return true; + } + srcYAddr = phyFBAddr; + srcCbAddr = srcYAddr; +#endif + } + + if (hdmiLayer == HDMI_LAYER_VIDEO) { + if (srcColorFormat == HAL_PIXEL_FORMAT_YCbCr_420_SP || + srcColorFormat == HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_SP) { +#if defined(BOARD_USE_V4L2) + mMixerBuffer[hdmiLayer][0].virt.extP[0] = (char *)srcYAddr; + mMixerBuffer[hdmiLayer][0].virt.extP[1] = (char *)srcCbAddr; +#else + hdmi_set_v_param(hdmiLayer, + srcW, srcH, V4L2_PIX_FMT_NV12, + srcYAddr, srcCbAddr, + mHdmiDstWidth, mHdmiDstHeight); +#endif + } else if (srcColorFormat == HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_SP_TILED) { +#if defined(BOARD_USE_V4L2) + mMixerBuffer[hdmiLayer][0].virt.extP[0] = (char *)srcYAddr; + mMixerBuffer[hdmiLayer][0].virt.extP[1] = (char *)srcCbAddr; +#else + hdmi_set_v_param(hdmiLayer, + srcW, srcH, V4L2_PIX_FMT_NV12T, + srcYAddr, srcCbAddr, + mHdmiDstWidth, mHdmiDstHeight); +#endif + } else if (srcColorFormat == HAL_PIXEL_FORMAT_YCrCb_420_SP || + srcColorFormat == HAL_PIXEL_FORMAT_CUSTOM_YCrCb_420_SP) { +#if defined(BOARD_USE_V4L2) + mMixerBuffer[hdmiLayer][0].virt.extP[0] = (char *)srcYAddr; + mMixerBuffer[hdmiLayer][0].virt.extP[1] = (char *)srcCbAddr; +#else + hdmi_set_v_param(hdmiLayer, + srcW, srcH, V4L2_PIX_FMT_NV21, + srcYAddr, srcCbAddr, + mHdmiDstWidth, mHdmiDstHeight); +#endif + } else { + if (mSecFimc.setSrcAddr(srcYAddr, srcCbAddr, srcCrAddr, srcColorFormat) == false) { + LOGE("%s::setSrcAddr(%d, %d, %d) fail", + __func__, srcYAddr, srcCbAddr, srcCrAddr); + return false; + } + + int y_size = 0; + if (mUIRotVal == 0 || mUIRotVal == 180) + y_size = ALIGN(ALIGN(srcW,128) * ALIGN(srcH, 32), SZ_8K); + else + y_size = ALIGN(ALIGN(srcH,128) * ALIGN(srcW, 32), SZ_8K); + + mHdmiSrcYAddr = mFimcReservedMem[mFimcCurrentOutBufIndex].phys.extP[0]; +#ifdef BOARD_USE_V4L2 + mHdmiSrcCbCrAddr = mFimcReservedMem[mFimcCurrentOutBufIndex].phys.extP[1]; +#else + mHdmiSrcCbCrAddr = mFimcReservedMem[mFimcCurrentOutBufIndex].phys.extP[0] + y_size; +#endif + if (mSecFimc.setDstAddr(mHdmiSrcYAddr, mHdmiSrcCbCrAddr, 0, mFimcCurrentOutBufIndex) == false) { + LOGE("%s::mSecFimc.setDstAddr(%d, %d) fail \n", + __func__, mHdmiSrcYAddr, mHdmiSrcCbCrAddr); + return false; + } + + if (mSecFimc.draw(0, mFimcCurrentOutBufIndex) == false) { + LOGE("%s::mSecFimc.draw() fail \n", __func__); + return false; + } +#if defined(BOARD_USE_V4L2) + mMixerBuffer[hdmiLayer][0].virt.extP[0] = (char *)mHdmiSrcYAddr; + mMixerBuffer[hdmiLayer][0].virt.extP[1] = (char *)mHdmiSrcCbCrAddr; +#else + if (mUIRotVal == 0 || mUIRotVal == 180) + hdmi_set_v_param(hdmiLayer, + srcW, srcH, V4L2_PIX_FMT_NV12T, + mHdmiSrcYAddr, mHdmiSrcCbCrAddr, + mHdmiDstWidth, mHdmiDstHeight); + else + hdmi_set_v_param(hdmiLayer, + srcH, srcW, V4L2_PIX_FMT_NV12T, + mHdmiSrcYAddr, mHdmiSrcCbCrAddr, + mHdmiDstWidth, mHdmiDstHeight); +#endif + mFimcCurrentOutBufIndex++; + if (mFimcCurrentOutBufIndex >= HDMI_FIMC_OUTPUT_BUF_NUM) + mFimcCurrentOutBufIndex = 0; + } + + } else { + if (srcColorFormat != HAL_PIXEL_FORMAT_BGRA_8888 && + srcColorFormat != HAL_PIXEL_FORMAT_RGBA_8888 && + srcColorFormat != HAL_PIXEL_FORMAT_RGB_565) { + if (mSecFimc.setSrcAddr(srcYAddr, srcCbAddr, srcCrAddr, srcColorFormat) == false) { + LOGE("%s::setSrcAddr(%d, %d, %d) fail", + __func__, srcYAddr, srcCbAddr, srcCrAddr); + return false; + } + + if (mSecFimc.draw(0, mFimcCurrentOutBufIndex) == false) { + LOGE("%s::mSecFimc.draw() failed", __func__); + return false; + } +#if defined(BOARD_USE_V4L2) + if (hdmi_set_g_scaling(hdmiLayer, + HAL_PIXEL_FORMAT_BGRA_8888, + mDstRect.width, mDstRect.height, + mHdmiSrcYAddr, &mMixerBuffer[hdmiLayer][0], + mDstRect.left , mDstRect.top, + mHdmiDstWidth, mHdmiDstHeight, + mG2DUIRotVal, + num_of_hwc_layer) < 0) + return false; +#else + if (hdmi_gl_set_param(hdmiLayer, + HAL_PIXEL_FORMAT_BGRA_8888, + mDstRect.width, mDstRect.height, + mHdmiSrcYAddr, mHdmiSrcCbCrAddr, + mDstRect.left , mDstRect.top, + mHdmiDstWidth, mHdmiDstHeight, + mG2DUIRotVal) < 0) +#endif + return false; + } else { +#if CHECK_GRAPHIC_LAYER_TIME + nsecs_t start, end; + start = systemTime(); +#endif + if (num_of_hwc_layer == 0) { /* UI only mode */ + struct v4l2_rect rect; + + if (mG2DUIRotVal == 0 || mG2DUIRotVal == 180) + hdmi_cal_rect(srcW, srcH, mHdmiDstWidth, mHdmiDstHeight, &rect); + else + hdmi_cal_rect(srcH, srcW, mHdmiDstWidth, mHdmiDstHeight, &rect); + + rect.left = ALIGN(rect.left, 16); + +#if defined(BOARD_USE_V4L2) + if (hdmi_set_g_scaling(hdmiLayer, + srcColorFormat, + srcW, srcH, + srcYAddr, &mMixerBuffer[hdmiLayer][0], + rect.left, rect.top, + rect.width, rect.height, + mG2DUIRotVal, + num_of_hwc_layer) < 0) + return false; +#else + if (hdmi_gl_set_param(hdmiLayer, + srcColorFormat, + srcW, srcH, + srcYAddr, srcCbAddr, + rect.left, rect.top, + rect.width, rect.height, + mG2DUIRotVal) < 0) + return false; +#endif + } else { /* Video Playback Mode */ +#if defined(BOARD_USE_V4L2) + if (hdmi_set_g_scaling(hdmiLayer, + srcColorFormat, + srcW, srcH, + srcYAddr, &mMixerBuffer[hdmiLayer][0], + dstX, dstY, + mHdmiDstWidth, mHdmiDstHeight, + mG2DUIRotVal, + num_of_hwc_layer) < 0) + return false; +#else + if (hdmi_gl_set_param(hdmiLayer, + srcColorFormat, + srcW, srcH, + srcYAddr, srcCbAddr, + dstX, dstY, + mHdmiDstWidth, mHdmiDstHeight, + mG2DUIRotVal) < 0) + return false; +#endif + } +#if CHECK_GRAPHIC_LAYER_TIME + end = systemTime(); + LOGD("[UI] hdmi_gl_set_param[end-start] = %ld ms", long(ns2ms(end)) - long(ns2ms(start))); +#endif + } + } + + if (mFlagConnected) { +#if defined(BOARD_USE_V4L2) + unsigned int num_of_plane; + + if (hdmi_get_src_plane(srcColorFormat, &num_of_plane) < 0) { + LOGE("%s::hdmi_get_src_plane(%d) fail", __func__, srcColorFormat); + return false; + } + + if (mFlagHdmiStart[hdmiLayer] == false && m_startHdmi(hdmiLayer, num_of_plane) == false) { + LOGE("%s::hdmiLayer(%d) fail", __func__, hdmiLayer); + return false; + } +#else + if (mFlagHdmiStart[hdmiLayer] == false && m_startHdmi(hdmiLayer) == false) { + LOGE("%s::hdmiLayer(%d) fail", __func__, hdmiLayer); + return false; + } +#endif + } + + return true; +} + +bool SecHdmi::clear(int hdmiLayer) +{ +#ifdef DEBUG_MSG_ENABLE + LOGD("%s || hdmiLayer = %d", __func__, hdmiLayer); +#endif + + Mutex::Autolock lock(mLock); + + if (mFlagCreate == false) { + LOGE("%s::Not Yet Created \n", __func__); + return false; + } + if (mFlagHdmiStart[hdmiLayer] == true && m_stopHdmi(hdmiLayer) == false) { + LOGE("%s::m_stopHdmi: layer[%d] fail \n", __func__, hdmiLayer); + return false; + } + return true; +} + +bool SecHdmi::setHdmiOutputMode(int hdmiOutputMode, bool forceRun) +{ +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("%s::hdmiOutputMode = %d, forceRun = %d", __func__, hdmiOutputMode, forceRun); +#endif + + Mutex::Autolock lock(mLock); + + if (mFlagCreate == false) { + LOGE("%s::Not Yet Created \n", __func__); + return false; + } + + if (forceRun == false && mHdmiOutputMode == hdmiOutputMode) { +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("%s::same hdmiOutputMode(%d) \n", __func__, hdmiOutputMode); +#endif + return true; + } + + int newHdmiOutputMode = hdmiOutputMode; + + int v4l2OutputType = hdmi_outputmode_2_v4l2_output_type(hdmiOutputMode); + if (v4l2OutputType < 0) { + LOGD("%s::hdmi_outputmode_2_v4l2_output_type(%d) fail\n", __func__, hdmiOutputMode); + return false; + } + +#if defined(BOARD_USES_EDID) + int newV4l2OutputType = hdmi_check_output_mode(v4l2OutputType); + if (newV4l2OutputType != v4l2OutputType) { + newHdmiOutputMode = hdmi_v4l2_output_type_2_outputmode(newV4l2OutputType); + if (newHdmiOutputMode < 0) { + LOGD("%s::hdmi_v4l2_output_type_2_outputmode(%d) fail\n", __func__, newV4l2OutputType); + return false; + } + + LOGD("%s::calibration mode(%d -> %d)... \n", __func__, hdmiOutputMode, newHdmiOutputMode); + mHdmiInfoChange = true; + } +#endif + + if (mHdmiOutputMode != newHdmiOutputMode) { + mHdmiOutputMode = newHdmiOutputMode; + mHdmiInfoChange = true; + } + + return true; +} + +bool SecHdmi::setHdmiResolution(unsigned int hdmiResolutionValue, bool forceRun) +{ +#ifdef DEBUG_MSG_ENABLE + LOGD("%s:: hdmiResolutionValue = %d, forceRun = %d", __func__, hdmiResolutionValue, forceRun); +#endif + + Mutex::Autolock lock(mLock); + + if (mFlagCreate == false) { + LOGE("%s::Not Yet Created \n", __func__); + return false; + } + + if (forceRun == false && mHdmiResolutionValue == hdmiResolutionValue) { +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("%s::same hdmiResolutionValue(%d) \n", __func__, hdmiResolutionValue); +#endif + return true; + } + + unsigned int newHdmiResolutionValue = hdmiResolutionValue; + int w = 0; + int h = 0; + +#if defined(BOARD_USES_EDID) + // find perfect resolutions.. +#if defined(BOARD_USE_V4L2) + unsigned int preset_id; + if (hdmi_resolution_2_preset_id(newHdmiResolutionValue, &w, &h, &preset_id) < 0 || + hdmi_check_resolution(preset_id) < 0) { + bool flagFoundIndex = false; + int resolutionValueIndex = m_resolutionValueIndex(newHdmiResolutionValue); + + for (int i = resolutionValueIndex + 1; i < mHdmiSizeOfResolutionValueList; i++) { + if (hdmi_resolution_2_preset_id(mHdmiResolutionValueList[i], &w, &h, &preset_id) == 0 && + hdmi_check_resolution(preset_id) == 0) { + newHdmiResolutionValue = mHdmiResolutionValueList[i]; + flagFoundIndex = true; + break; + } + } + + if (flagFoundIndex == false) { + LOGE("%s::hdmi cannot control this resolution(%d) fail \n", __func__, hdmiResolutionValue); + // Set resolution to 480P + newHdmiResolutionValue = mHdmiResolutionValueList[mHdmiSizeOfResolutionValueList-2]; + } else { + LOGD("%s::HDMI resolutions size is calibrated(%d -> %d)..\n", __func__, hdmiResolutionValue, newHdmiResolutionValue); + } + } +#else + v4l2_std_id std_id; + if (hdmi_resolution_2_std_id(newHdmiResolutionValue, &w, &h, &std_id) < 0 || + hdmi_check_resolution(std_id) < 0) { + bool flagFoundIndex = false; + int resolutionValueIndex = m_resolutionValueIndex(newHdmiResolutionValue); + + for (int i = resolutionValueIndex + 1; i < mHdmiSizeOfResolutionValueList; i++) { + if (hdmi_resolution_2_std_id(mHdmiResolutionValueList[i], &w, &h, &std_id) == 0 && + hdmi_check_resolution(std_id) == 0) { + newHdmiResolutionValue = mHdmiResolutionValueList[i]; + flagFoundIndex = true; + break; + } + } + + if (flagFoundIndex == false) { + LOGE("%s::hdmi cannot control this resolution(%d) fail \n", __func__, hdmiResolutionValue); + // Set resolution to 480P + newHdmiResolutionValue = mHdmiResolutionValueList[mHdmiSizeOfResolutionValueList-2]; + } else { + LOGD("%s::HDMI resolutions size is calibrated(%d -> %d)..\n", __func__, hdmiResolutionValue, newHdmiResolutionValue); + } + } +#endif + else { +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("%s::find resolutions(%d) at once\n", __func__, hdmiResolutionValue); +#endif + } +#endif + + if (mHdmiResolutionValue != newHdmiResolutionValue) { + mHdmiResolutionValue = newHdmiResolutionValue; + mHdmiInfoChange = true; + } + + return true; +} + +bool SecHdmi::setHdcpMode(bool hdcpMode, bool forceRun) +{ +#ifdef DEBUG_MSG_ENABLE + LOGD("%s", __func__); +#endif + + Mutex::Autolock lock(mLock); + + if (mFlagCreate == false) { + LOGE("%s::Not Yet Created \n", __func__); + return false; + } + + if (forceRun == false && mHdcpMode == hdcpMode) { +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("%s::same hdcpMode(%d) \n", __func__, hdcpMode); +#endif + return true; + } + + mHdcpMode = hdcpMode; + mHdmiInfoChange = true; + + return true; +} + +bool SecHdmi::setUIRotation(unsigned int rotVal, unsigned int hwcLayer) +{ +#ifdef DEBUG_MSG_ENABLE + LOGD("%s", __func__); +#endif + + Mutex::Autolock lock(mLock); + + if (mFlagCreate == false) { + LOGE("%s::Not Yet Created \n", __func__); + return false; + } + + if (rotVal % 90 != 0) { + LOGE("%s::Invalid rotation value(%d)", __func__, rotVal); + return false; + } + + /* G2D rotation */ + if (rotVal != mG2DUIRotVal) { + mG2DUIRotVal = rotVal; + mHdmiInfoChange = true; + } + + /* FIMC rotation */ + if (hwcLayer == 0) { /* Rotate in UI only mode */ + if (rotVal != mUIRotVal) { + mSecFimc.setRotVal(rotVal); + mUIRotVal = rotVal; + mHdmiInfoChange = true; + } + } else { /* Don't rotate video layer when video is played. */ + rotVal = 0; + if (rotVal != mUIRotVal) { + mSecFimc.setRotVal(rotVal); + mUIRotVal = rotVal; + mHdmiInfoChange = true; + } + } + + return true; +} + +bool SecHdmi::setDisplaySize(int width, int height) +{ + mDisplayWidth = width; + mDisplayHeight = height; + + return true; +} + +bool SecHdmi::m_reset(int w, int h, int colorFormat, int hdmiLayer, int hwcLayer) +{ +#ifdef DEBUG_MSG_ENABLE + LOGD("%s", __func__); +#endif + +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("### %s called", __func__); +#endif + v4l2_std_id std_id = 0; + mFimcCurrentOutBufIndex = 0; + + int srcW = w; + int srcH = h; + +#if defined(BOARD_USE_V4L2) + if (mFlagHdmiStart[hdmiLayer] == true && m_stopHdmi(hdmiLayer) == false) { + LOGE("%s::m_stopHdmi: layer[%d] fail", __func__, hdmiLayer); + return false; + } +#else + // stop all.. + for (int layer = HDMI_LAYER_BASE + 1; layer < HDMI_LAYER_MAX; layer++) { + if (mFlagHdmiStart[layer] == true && m_stopHdmi(layer) == false) { + LOGE("%s::m_stopHdmi: layer[%d] fail", __func__, layer); + return false; + } + } +#endif + +#if defined(BOARD_USE_V4L2) + if (hdmi_deinit_layer(hdmiLayer) < 0) + LOGE("%s::hdmi_deinit_layer(%d) fail", __func__, hdmiLayer); + + mHdmiFd[hdmiLayer] = hdmi_init_layer(hdmiLayer); + if (mHdmiFd[hdmiLayer] < 0) + LOGE("%s::hdmi_init_layer(%d) fail", __func__, hdmiLayer); + + if (tvout_std_v4l2_init(mHdmiFd[hdmiLayer], mHdmiPresetId) < 0) + LOGE("%s::tvout_std_v4l2_init fail", __func__); +#endif + + if (w != mSrcWidth [hdmiLayer] || + h != mSrcHeight [hdmiLayer] || + mHdmiDstWidth != mHdmiResolutionWidth[hdmiLayer] || + mHdmiDstHeight != mHdmiResolutionHeight[hdmiLayer] || +#if defined(BOARD_USE_V4L2) + mDstWidth[hdmiLayer] != mPrevDstWidth[hdmiLayer] || + mDstHeight[hdmiLayer] != mPrevDstHeight[hdmiLayer] || +#endif + colorFormat != mSrcColorFormat[hdmiLayer]) { + int preVideoSrcColorFormat = mSrcColorFormat[hdmiLayer]; + int videoSrcColorFormat = colorFormat; + + if (preVideoSrcColorFormat != HAL_PIXEL_FORMAT_YCbCr_420_SP && + preVideoSrcColorFormat != HAL_PIXEL_FORMAT_YCrCb_420_SP && + preVideoSrcColorFormat != HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_SP && + preVideoSrcColorFormat != HAL_PIXEL_FORMAT_CUSTOM_YCrCb_420_SP && + preVideoSrcColorFormat != HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_SP_TILED) { + LOGI("%s: Unsupported preVideoSrcColorFormat = 0x%x\n", __func__, preVideoSrcColorFormat); + preVideoSrcColorFormat = HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_SP_TILED; + } + + if (hdmiLayer == HDMI_LAYER_VIDEO) { + if (colorFormat != HAL_PIXEL_FORMAT_YCbCr_420_SP && + colorFormat != HAL_PIXEL_FORMAT_YCrCb_420_SP && + colorFormat != HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_SP && + colorFormat != HAL_PIXEL_FORMAT_CUSTOM_YCrCb_420_SP && + colorFormat != HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_SP_TILED) { +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("### %s call mSecFimc.setSrcParams\n", __func__); +#endif + unsigned int full_wdith = ALIGN(w, 16); + unsigned int full_height = ALIGN(h, 2); + + if (mSecFimc.setSrcParams(full_wdith, full_height, 0, 0, + (unsigned int*)&w, (unsigned int*)&h, colorFormat, true) == false) { + LOGE("%s::mSecFimc.setSrcParams(%d, %d, %d) fail \n", + __func__, w, h, colorFormat); + return false; + } + + mFimcDstColorFormat = HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_SP_TILED; + +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("### %s call mSecFimc.setDstParams\n", __func__); +#endif + if (mUIRotVal == 0 || mUIRotVal == 180) { + if (mSecFimc.setDstParams((unsigned int)w, (unsigned int)h, 0, 0, + (unsigned int*)&w, (unsigned int*)&h, mFimcDstColorFormat, true) == false) { + LOGE("%s::mSecFimc.setDstParams(%d, %d, %d) fail \n", + __func__, w, h, mFimcDstColorFormat); + return false; + } +#if defined(BOARD_USE_V4L2) + hdmi_set_v_param(mHdmiFd[hdmiLayer], hdmiLayer, + mFimcDstColorFormat, srcW, srcH, + &mMixerBuffer[hdmiLayer][0], + 0, 0, mHdmiDstWidth, mHdmiDstHeight); +#endif + } else { + if (mSecFimc.setDstParams((unsigned int)h, (unsigned int)w, 0, 0, + (unsigned int*)&h, (unsigned int*)&w, mFimcDstColorFormat, true) == false) { + LOGE("%s::mSecFimc.setDstParams(%d, %d, %d) fail \n", + __func__, w, h, mFimcDstColorFormat); + return false; + } +#if defined(BOARD_USE_V4L2) + hdmi_set_v_param(mHdmiFd[hdmiLayer], hdmiLayer, + mFimcDstColorFormat, srcH, srcW, + &mMixerBuffer[hdmiLayer][0], + 0, 0, mHdmiDstWidth, mHdmiDstHeight); +#endif + } + } +#if defined(BOARD_USE_V4L2) + else { + hdmi_set_v_param(mHdmiFd[hdmiLayer], hdmiLayer, + colorFormat, srcW, srcH, + &mMixerBuffer[hdmiLayer][0], + 0, 0, mHdmiDstWidth, mHdmiDstHeight); + } +#endif + mPrevDstWidth[hdmiLayer] = mHdmiDstWidth; + mPrevDstHeight[hdmiLayer] = mHdmiDstHeight; + } else { +#if defined(BOARD_USE_V4L2) + struct v4l2_rect rect; + int tempSrcW, tempSrcH; + + if (mG2DUIRotVal == 0 || mG2DUIRotVal == 180) { + tempSrcW = srcW; + tempSrcH = srcH; + } else { + tempSrcW = srcH; + tempSrcH = srcW; + } + + hdmi_cal_rect(tempSrcW, tempSrcH, mHdmiDstWidth, mHdmiDstHeight, &rect); + rect.left = ALIGN(rect.left, 16); + + if (hwcLayer == 0) { /* UI only mode */ + hdmi_set_g_param(mHdmiFd[hdmiLayer], hdmiLayer, + colorFormat, srcW, srcH, + &mMixerBuffer[hdmiLayer][0], + rect.left, rect.top, rect.width, rect.height); + mPrevDstWidth[hdmiLayer] = rect.width; + mPrevDstHeight[hdmiLayer] = rect.height; + mPrevDstWidth[HDMI_LAYER_VIDEO] = 0; + mPrevDstHeight[HDMI_LAYER_VIDEO] = 0; + } else { /* Video Playback + UI Mode */ + hdmi_set_g_param(mHdmiFd[hdmiLayer], hdmiLayer, + colorFormat, srcW, srcH, + &mMixerBuffer[hdmiLayer][0], + 0, 0, mHdmiDstWidth, mHdmiDstHeight); + mPrevDstWidth[hdmiLayer] = mHdmiDstWidth; + mPrevDstHeight[hdmiLayer] = mHdmiDstHeight; + } +#endif + } + + if (preVideoSrcColorFormat != videoSrcColorFormat) + mHdmiInfoChange = true; + + mSrcWidth[hdmiLayer] = srcW; + mSrcHeight[hdmiLayer] = srcH; + mSrcColorFormat[hdmiLayer] = colorFormat; + + mHdmiResolutionWidth[hdmiLayer] = mHdmiDstWidth; + mHdmiResolutionHeight[hdmiLayer] = mHdmiDstHeight; + +#ifdef DEBUG_MSG_ENABLE + LOGD("m_reset saved param(%d, %d, %d, %d, %d, %d, %d) \n", + srcW, mSrcWidth[hdmiLayer], \ + srcH, mSrcHeight[hdmiLayer], \ + colorFormat,mSrcColorFormat[hdmiLayer], \ + hdmiLayer); +#endif + } + + if (mHdmiInfoChange == true) { +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("mHdmiInfoChange: %d\n", mHdmiInfoChange); +#endif + // stop all.. +#if defined(BOARD_USES_CEC) + if (mHdmiOutputMode >= HDMI_OUTPUT_MODE_YCBCR && + mHdmiOutputMode <= HDMI_OUTPUT_MODE_DVI) { + if (mCECThread->mFlagRunning) + mCECThread->stop(); + } +#endif + + if (m_setHdmiOutputMode(mHdmiOutputMode) == false) { + LOGE("%s::m_setHdmiOutputMode() fail \n", __func__); + return false; + } + if (mHdmiOutputMode == COMPOSITE_OUTPUT_MODE) { + std_id = composite_std_2_v4l2_std_id(mCompositeStd); + if ((int)std_id < 0) { + LOGE("%s::composite_std_2_v4l2_std_id(%d) fail\n", __func__, mCompositeStd); + return false; + } + if (m_setCompositeResolution(mCompositeStd) == false) { + LOGE("%s::m_setCompositeRsolution() fail \n", __func__); + return false; + } + } else if (mHdmiOutputMode >= HDMI_OUTPUT_MODE_YCBCR && + mHdmiOutputMode <= HDMI_OUTPUT_MODE_DVI) { + if (m_setHdmiResolution(mHdmiResolutionValue) == false) { + LOGE("%s::m_setHdmiResolution() fail \n", __func__); + return false; + } + + if (m_setHdcpMode(mHdcpMode) == false) { + LOGE("%s::m_setHdcpMode() fail \n", __func__); + return false; + } +#if !defined(BOARD_USE_V4L2) + std_id = mHdmiStdId; +#endif + } + +#if !defined(BOARD_USE_V4L2) + fp_tvout = tvout_init(std_id); + + for (int layer = HDMI_LAYER_BASE + 1; layer < HDMI_LAYER_MAX; layer++) { + if (hdmi_deinit_layer(layer) < 0) + LOGE("%s::hdmi_init_layer(%d) fail \n", __func__, layer); + } + + for (int layer = HDMI_LAYER_BASE + 1; layer < HDMI_LAYER_MAX; layer++) { + if (hdmi_init_layer(layer) < 0) + LOGE("%s::hdmi_init_layer(%d) fail \n", __func__, layer); + } +#endif + + if (mHdmiOutputMode >= HDMI_OUTPUT_MODE_YCBCR && + mHdmiOutputMode <= HDMI_OUTPUT_MODE_DVI) { +#if defined(BOARD_USES_CEC) + if (!(mCECThread->mFlagRunning)) + mCECThread->start(); +#endif + + if (m_setAudioMode(mAudioMode) == false) + LOGE("%s::m_setAudioMode() fail \n", __func__); + } + + mHdmiInfoChange = false; +#ifdef BOARD_USE_V4L2 + for (int i = 0; i < HDMI_FIMC_OUTPUT_BUF_NUM; i++) + mFimcReservedMem[i] = *(mSecFimc.getMemAddr(i)); +#endif + } + + return true; +} + +#if defined(BOARD_USE_V4L2) +bool SecHdmi::m_startHdmi(int hdmiLayer, unsigned int num_of_plane) +{ +#ifdef DEBUG_MSG_ENABLE + LOGD("%s", __func__); +#endif + + bool ret = true; + int buf_index = 0; + +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("### %s: hdmiLayer(%d) called\n", __func__, hdmiLayer); +#endif + + if (mFlagLayerEnable[hdmiLayer]) { + static unsigned int index = 0; + + if (mFlagHdmiStart[hdmiLayer] == false) { + index = 0; + if (tvout_std_v4l2_qbuf(mHdmiFd[hdmiLayer], V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, V4L2_MEMORY_USERPTR, + index, num_of_plane, &mMixerBuffer[hdmiLayer][0]) < 0) { + LOGE("%s::tvout_std_v4l2_qbuf(index : %d) (mSrcBufNum : %d) failed", __func__, index, HDMI_NUM_MIXER_BUF); + return false; + } + index++; + + if (tvout_std_v4l2_streamon(mHdmiFd[hdmiLayer], V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) < 0) { + LOGE("%s::tvout_std_v4l2_streamon() failed", __func__); + return false; + } + + mFlagHdmiStart[hdmiLayer] = true; + } else { + if (tvout_std_v4l2_qbuf(mHdmiFd[hdmiLayer], V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, V4L2_MEMORY_USERPTR, + index, num_of_plane, &mMixerBuffer[hdmiLayer][0]) < 0) { + LOGE("%s::tvout_std_v4l2_qbuf() failed", __func__); + return false; + } + + if (tvout_std_v4l2_dqbuf(mHdmiFd[hdmiLayer], V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, V4L2_MEMORY_USERPTR, &buf_index, num_of_plane) < 0) { + LOGE("%s::tvout_std_v4l2_dqbuf() failed", __func__); + return false; + } + index = buf_index; + } + } + + return true; +} +#else +bool SecHdmi::m_startHdmi(int hdmiLayer) +{ +#ifdef DEBUG_MSG_ENABLE + LOGD("%s", __func__); +#endif + + bool ret = true; + int buf_index = 0; + +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("### %s: hdmiLayer(%d) called\n", __func__, hdmiLayer); +#endif + + switch (hdmiLayer) { + case HDMI_LAYER_VIDEO: + tvout_v4l2_start_overlay(fp_tvout_v); + mFlagHdmiStart[hdmiLayer] = true; + break; + case HDMI_LAYER_GRAPHIC_0 : + if (mFlagLayerEnable[hdmiLayer]) { + if (ioctl(fp_tvout_g0, FBIOBLANK, (void *)FB_BLANK_UNBLANK) != -1) + mFlagHdmiStart[hdmiLayer] = true; + } + break; + case HDMI_LAYER_GRAPHIC_1 : + if (mFlagLayerEnable[hdmiLayer]) { + if (ioctl(fp_tvout_g1, FBIOBLANK, (void *)FB_BLANK_UNBLANK) != -1) + mFlagHdmiStart[hdmiLayer] = true; + } + break; + default : + LOGE("%s::unmathced layer(%d) fail", __func__, hdmiLayer); + ret = false; + break; + } + + return true; +} +#endif + +bool SecHdmi::m_stopHdmi(int hdmiLayer) +{ +#ifdef DEBUG_MSG_ENABLE + LOGD("%s", __func__); +#endif + + bool ret = true; + if (mFlagHdmiStart[hdmiLayer] == false) { + LOGD("%s::already HDMI(%d layer) stopped.. \n", __func__, hdmiLayer); + return true; + } + +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("### %s : layer[%d] called\n", __func__, hdmiLayer); +#endif + +#if defined(BOARD_USE_V4L2) + int fd; + + switch (hdmiLayer) { + case HDMI_LAYER_VIDEO: + break; + case HDMI_LAYER_GRAPHIC_0 : + break; + case HDMI_LAYER_GRAPHIC_1 : +#if defined(BOARD_USES_FIMGAPI) + cur_g2d_address = 0; + g2d_buf_index = 0; +#endif + break; + default : + LOGE("%s::unmathced layer(%d) fail", __func__, hdmiLayer); + ret = false; + break; + } + + if (mFlagLayerEnable[hdmiLayer]) { + if (tvout_std_v4l2_streamoff(mHdmiFd[hdmiLayer], V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) < 0) { + LOGE("%s::tvout_std_v4l2_streamon layer(%d) failed", __func__, hdmiLayer); + return false; + } + + /* clear buffer */ + if (tvout_std_v4l2_reqbuf(mHdmiFd[hdmiLayer], V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, V4L2_MEMORY_USERPTR, 0) < 0) { + LOGE("%s::tvout_std_v4l2_reqbuf(buf_num=%d)[graphic layer] failed", __func__, 0); + return -1; + } + + mFlagHdmiStart[hdmiLayer] = false; + } +#else + switch (hdmiLayer) { + case HDMI_LAYER_VIDEO: + tvout_v4l2_stop_overlay(fp_tvout_v); + mFlagHdmiStart[hdmiLayer] = false; + break; + case HDMI_LAYER_GRAPHIC_0 : + if (mFlagLayerEnable[hdmiLayer]) { + if (ioctl(fp_tvout_g0, FBIOBLANK, (void *)FB_BLANK_POWERDOWN) != -1) + mFlagHdmiStart[hdmiLayer] = false; + } + break; + case HDMI_LAYER_GRAPHIC_1 : +#if defined(BOARD_USES_FIMGAPI) + cur_g2d_address = 0; + g2d_buf_index = 0; +#endif + if (mFlagLayerEnable[hdmiLayer]) { + if (ioctl(fp_tvout_g1, FBIOBLANK, (void *)FB_BLANK_POWERDOWN) != -1) + mFlagHdmiStart[hdmiLayer] = false; + } + break; + default : + LOGE("%s::unmathced layer(%d) fail", __func__, hdmiLayer); + ret = false; + break; + } +#endif + + return true; +} + +bool SecHdmi::m_setHdmiOutputMode(int hdmiOutputMode) +{ +#ifdef DEBUG_MSG_ENABLE + LOGD("%s", __func__); +#endif + + if (hdmiOutputMode == mCurrentHdmiOutputMode) { +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("%s::same hdmiOutputMode(%d) \n", __func__, hdmiOutputMode); +#endif + return true; + } + +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("### %s called\n", __func__); +#endif + + int v4l2OutputType = hdmi_outputmode_2_v4l2_output_type(hdmiOutputMode); + if (v4l2OutputType < 0) { + LOGE("%s::hdmi_outputmode_2_v4l2_output_type(%d) fail\n", __func__, hdmiOutputMode); + return false; + } + + output_type = v4l2OutputType; + + mCurrentHdmiOutputMode = hdmiOutputMode; + + return true; +} + +bool SecHdmi::m_setCompositeResolution(unsigned int compositeStdId) +{ +#ifdef DEBUG_MSG_ENABLE + LOGD("%s", __func__); +#endif + +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("### %s called\n", __func__); +#endif + + int w = 0; + int h = 0; + + if (mHdmiOutputMode != COMPOSITE_OUTPUT_MODE) { + LOGE("%s:: not supported output type \n", __func__); + return false; + } + + switch (compositeStdId) { + case COMPOSITE_STD_NTSC_M: + case COMPOSITE_STD_NTSC_443: + w = 704; + h = 480; + break; + case COMPOSITE_STD_PAL_BDGHI: + case COMPOSITE_STD_PAL_M: + case COMPOSITE_STD_PAL_N: + case COMPOSITE_STD_PAL_Nc: + case COMPOSITE_STD_PAL_60: + w = 704; + h = 576; + break; + default: + LOGE("%s::unmathced composite_std(%d)", __func__, compositeStdId); + return false; + } + + t_std_id = composite_std_2_v4l2_std_id(mCompositeStd); + + mHdmiDstWidth = w; + mHdmiDstHeight = h; + + mCurrentHdmiResolutionValue = -1; + return true; +} + +bool SecHdmi::m_setHdmiResolution(unsigned int hdmiResolutionValue) +{ +#ifdef DEBUG_MSG_ENABLE + LOGD("%s", __func__); +#endif + + if (hdmiResolutionValue == mCurrentHdmiResolutionValue) { +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("%s::same hdmiResolutionValue(%d) \n", __func__, hdmiResolutionValue); +#endif + return true; + } + +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("### %s called\n", __func__); +#endif + + int w = 0; + int h = 0; + +#if defined(BOARD_USE_V4L2) + unsigned int preset_id; +#else + v4l2_std_id std_id; +#endif + + if (mHdmiOutputMode >= HDMI_OUTPUT_MODE_YCBCR && + mHdmiOutputMode <= HDMI_OUTPUT_MODE_DVI) { +#if defined(BOARD_USE_V4L2) + if (hdmi_resolution_2_preset_id(hdmiResolutionValue, &w, &h, &preset_id) < 0) { + LOGE("%s::hdmi_resolution_2_std_id(%d) fail\n", __func__, hdmiResolutionValue); + return false; + } + mHdmiPresetId = preset_id; +#else + if (hdmi_resolution_2_std_id(hdmiResolutionValue, &w, &h, &std_id) < 0) { + LOGE("%s::hdmi_resolution_2_std_id(%d) fail\n", __func__, hdmiResolutionValue); + return false; + } + mHdmiStdId = std_id; +#endif + } else { + LOGE("%s:: not supported output type \n", __func__); + return false; + } + +#if defined(BOARD_USE_V4L2) + g_preset_id = preset_id; +#else + t_std_id = std_id; +#endif + + mHdmiDstWidth = w; + mHdmiDstHeight = h; + + mCurrentHdmiResolutionValue = hdmiResolutionValue; + +#ifdef DEBUG_HDMI_HW_LEVEL +#if defined(BOARD_USE_V4L2) + LOGD("%s:: mHdmiDstWidth = %d, mHdmiDstHeight = %d, mHdmiPresetId = 0x%x, hdmiResolutionValue = 0x%x\n", + __func__, + mHdmiDstWidth, + mHdmiDstHeight, + mHdmiPresetId, + hdmiResolutionValue); +#else + LOGD("%s:: mHdmiDstWidth = %d, mHdmiDstHeight = %d, mHdmiStdId = 0x%x, hdmiResolutionValue = 0x%x\n", + __func__, + mHdmiDstWidth, + mHdmiDstHeight, + mHdmiStdId, + hdmiResolutionValue); +#endif +#endif + + return true; +} + +bool SecHdmi::m_setHdcpMode(bool hdcpMode) +{ +#ifdef DEBUG_MSG_ENABLE + LOGD("%s", __func__); +#endif + + if (hdcpMode == mCurrentHdcpMode) { +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("%s::same hdcpMode(%d) \n", __func__, hdcpMode); +#endif + + return true; + } + +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("### %s called\n", __func__); +#endif + + if (hdcpMode == true) + g_hdcp_en = 1; + else + g_hdcp_en = 0; + + mCurrentHdcpMode = hdcpMode; + + return true; +} + +bool SecHdmi::m_setAudioMode(int audioMode) +{ +#ifdef DEBUG_MSG_ENABLE + LOGD("%s", __func__); +#endif + + if (audioMode == mCurrentAudioMode) { +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("%s::same audioMode(%d) \n", __func__, audioMode); +#endif + return true; + } + +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("### %s called\n", __func__); +#endif + + if (hdmi_check_audio() < 0) { + LOGE("%s::hdmi_check_audio() fail \n", __func__); + return false; + } + + mCurrentAudioMode = audioMode; + + return true; +} + +int SecHdmi::m_resolutionValueIndex(unsigned int ResolutionValue) +{ +#ifdef DEBUG_MSG_ENABLE + LOGD("%s", __func__); +#endif + + int index = -1; + + for (int i = 0; i < mHdmiSizeOfResolutionValueList; i++) { + if (mHdmiResolutionValueList[i] == ResolutionValue) { + index = i; + break; + } + } + return index; +} + +bool SecHdmi::m_flagHWConnected(void) +{ +#ifdef DEBUG_MSG_ENABLE + LOGD("%s", __func__); +#endif + +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("### %s called\n", __func__); +#endif + + bool ret = true; + int hdmiStatus = hdmi_cable_status(); + + if (hdmiStatus <= 0) { +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("%s::hdmi_cable_status() fail \n", __func__); +#endif + ret = false; + } else { + ret = true; + } + + return ret; +} + +}; // namespace android diff --git a/exynos4/hal/libhdmi/SecHdmi/SecHdmiCommon.h b/exynos4/hal/libhdmi/SecHdmi/SecHdmiCommon.h new file mode 100644 index 0000000..203dfe4 --- /dev/null +++ b/exynos4/hal/libhdmi/SecHdmi/SecHdmiCommon.h @@ -0,0 +1,138 @@ +/* + * Copyright@ Samsung Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +** +** @author Sangwoo, Park(sw5771.park@samsung.com) +** @date 2010-09-10 +** +*/ + +//#define LOG_NDEBUG 0 +//#define LOG_TAG "libhdmi" +#include + +#include "videodev2.h" +#if defined(BOARD_USE_V4L2) +#include "s5p_tvout_v4l2.h" +#else +#include "s5p_tvout.h" +#endif + +//#define DEBUG_MSG_ENABLE +//#define DEBUG_HDMI_HW_LEVEL +#define BOARD_USES_EDID +//#define BOARD_USES_CEC +#if defined(SAMSUNG_EXYNOS4x12) +//#define SUPPORT_G2D_UI_MODE +#endif + +#define DEFAULT_FB (0) +#define TVOUT_FB_G0 (10) +#define TVOUT_FB_G1 (11) + +#define MAX_BUFFERS_MIXER (1) +#define MAX_PLANES_MIXER (3) + +#define HDMI_NUM_MIXER_BUF (2) +#define GRALLOC_BUF_SIZE (32768) +#define SIZE_1K (1024) + +#define HDMI_FIMC_OUTPUT_BUF_NUM (4) +#define HDMI_G2D_OUTPUT_BUF_NUM (2) +#define HDMI_FIMC_BUFFER_BPP_SIZE (1.5) //NV12 Tiled is 1.5 bytes, RGB565 is 2, RGB888 is 4, Default is NV12 Tiled +#define HDMI_G2D_BUFFER_BPP_SIZE (4) //NV12 Tiled is 1.5 bytes, RGB565 is 2, RGB888 is 4 +#define HDMI_FB_BPP_SIZE (4) //ARGB888 is 4 +#define SUPPORT_1080P_FIMC_OUT +#define HDMI_MAX_WIDTH (1920) +#define HDMI_MAX_HEIGHT (1080) + +#define ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1)) + +#if defined(STD_NTSC_M) + #define DEFAULT_OUPUT_MODE (COMPOSITE_OUTPUT_MODE) + #define DEFAULT_HDMI_RESOLUTION_VALUE (1080960) // 1080P_60 + #define DEFAULT_HDMI_PRESET_ID (V4L2_DV_1080P60) + #define DEFAULT_HDMI_STD_ID (V4L2_STD_1080P_60) + #define DEFALULT_DISPLAY_WIDTH (720) + #define DEFALULT_DISPLAY_HEIGHT (480) + #define DEFAULT_COMPOSITE_STD (COMPOSITE_STD_NTSC_M) +#elif (STD_1080P) + #define DEFAULT_OUPUT_MODE (HDMI_OUTPUT_MODE_RGB) + #define DEFAULT_HDMI_RESOLUTION_VALUE (1080960) // 1080P_60 + #define DEFAULT_HDMI_PRESET_ID (V4L2_DV_1080P60) + #define DEFAULT_HDMI_STD_ID (V4L2_STD_1080P_60) + #define DEFALULT_DISPLAY_WIDTH (1920) + #define DEFALULT_DISPLAY_HEIGHT (1080) + #define DEFAULT_COMPOSITE_STD (COMPOSITE_STD_NTSC_M) +#elif defined(STD_720P) + #define DEFAULT_OUPUT_MODE (HDMI_OUTPUT_MODE_YCBCR) + #define DEFAULT_HDMI_RESOLUTION_VALUE (720960) // 720P_60 + #define DEFAULT_HDMI_PRESET_ID (V4L2_DV_720P60) + #define DEFAULT_HDMI_STD_ID (V4L2_STD_720P_60) + #define DEFALULT_DISPLAY_WIDTH (1280) + #define DEFALULT_DISPLAY_HEIGHT (720) + #define DEFAULT_COMPOSITE_STD (COMPOSITE_STD_NTSC_M) +#elif defined(STD_480P) + #define DEFAULT_OUPUT_MODE (HDMI_OUTPUT_MODE_YCBCR) + #define DEFAULT_HDMI_RESOLUTION_VALUE (4809601) // 480P_60_4_3 + #define DEFAULT_HDMI_PRESET_ID (V4L2_DV_480P60) + #define DEFAULT_HDMI_STD_ID (V4L2_STD_480P_60_16_9) + #define DEFALULT_DISPLAY_WIDTH (720) + #define DEFALULT_DISPLAY_HEIGHT (480) + #define DEFAULT_COMPOSITE_STD (COMPOSITE_STD_NTSC_M) +#else + #define DEFAULT_OUPUT_MODE (HDMI_OUTPUT_MODE_YCBCR) + #define DEFAULT_HDMI_RESOLUTION_VALUE (4809602) // 480P_60_4_3 + #define DEFAULT_HDMI_PRESET_ID (V4L2_DV_480P60) + #define DEFAULT_HDMI_STD_ID (V4L2_STD_480P_60_4_3) + #define DEFALULT_DISPLAY_WIDTH (720) + #define DEFALULT_DISPLAY_HEIGHT (480) + #define DEFAULT_COMPOSITE_STD (COMPOSITE_STD_NTSC_M) +#endif + +enum hdp_cable_status { + HPD_CABLE_OUT = 0, // HPD_CABLE_OUT indicates HDMI cable out. + HPD_CABLE_IN // HPD_CABLE_IN indicates HDMI cable in. +}; + +enum state { + OFF = 0, + ON = 1, + NOT_SUPPORT = 2, +}; + +enum tv_mode { + HDMI_OUTPUT_MODE_YCBCR = 0, + HDMI_OUTPUT_MODE_RGB = 1, + HDMI_OUTPUT_MODE_DVI = 2, + COMPOSITE_OUTPUT_MODE = 3 +}; + +enum composite_std { + COMPOSITE_STD_NTSC_M = 0, + COMPOSITE_STD_PAL_BDGHI = 1, + COMPOSITE_STD_PAL_M = 2, + COMPOSITE_STD_PAL_N = 3, + COMPOSITE_STD_PAL_Nc = 4, + COMPOSITE_STD_PAL_60 = 5, + COMPOSITE_STD_NTSC_443 = 6 +}; + +enum hdmi_layer { + HDMI_LAYER_BASE = 0, + HDMI_LAYER_VIDEO, + HDMI_LAYER_GRAPHIC_0, + HDMI_LAYER_GRAPHIC_1, + HDMI_LAYER_MAX, +}; diff --git a/exynos4/hal/libhdmi/SecHdmi/SecHdmiV4L2Utils.cpp b/exynos4/hal/libhdmi/SecHdmi/SecHdmiV4L2Utils.cpp new file mode 100644 index 0000000..217ce51 --- /dev/null +++ b/exynos4/hal/libhdmi/SecHdmi/SecHdmiV4L2Utils.cpp @@ -0,0 +1,2434 @@ +/* + * Copyright@ Samsung Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +//#define LOG_NDEBUG 0 +//#define LOG_TAG "libhdmi" +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(BOARD_USE_V4L2) +#include "sec_utils_v4l2.h" +#include "s5p_tvout_v4l2.h" +#include "videodev2.h" +#else +#include "sec_utils.h" +#include "s5p_tvout.h" +#endif +#include "SecFimc.h" +#if defined(BOARD_USES_FIMGAPI) +#include "sec_g2d_4x.h" +#include "FimgApi.h" +#endif + +#include "audio.h" +#include "video.h" +#include "../libhdmi/libsForhdmi/libedid/libedid.h" +#include "../libhdmi/libsForhdmi/libcec/libcec.h" + +#include "SecHdmiCommon.h" +#include "SecHdmiV4L2Utils.h" + +namespace android { + +unsigned int output_type = V4L2_OUTPUT_TYPE_DIGITAL; +#if defined(BOARD_USE_V4L2) +unsigned int g_preset_id = V4L2_DV_1080P30; +#endif +v4l2_std_id t_std_id = V4L2_STD_1080P_30; +int g_hpd_state = HPD_CABLE_OUT; +unsigned int g_hdcp_en = 0; + +int fp_tvout = -1; +int fp_tvout_v = -1; +int fp_tvout_g0 = -1; +int fp_tvout_g1 = -1; + +struct vid_overlay_param vo_param; + +#if defined(BOARD_USES_FIMGAPI) +unsigned int g2d_reserved_memory[HDMI_G2D_OUTPUT_BUF_NUM]; +unsigned int g2d_reserved_memory_size = 0; +unsigned int cur_g2d_address = 0; +unsigned int g2d_buf_index = 0; +#endif + +void display_menu(void) +{ + struct HDMIVideoParameter video; + struct HDMIAudioParameter audio; + +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("%s", __func__); +#endif + + audio.formatCode = LPCM_FORMAT; + audio.outPacket = HDMI_ASP; + audio.channelNum = CH_2; + audio.sampleFreq = SF_44KHZ; + + LOGI("=============== HDMI Audio =============\n"); + + if (EDIDAudioModeSupport(&audio)) + LOGI("= 2CH_PCM 44100Hz audio supported =\n"); + + LOGI("========= HDMI Mode & Color Space =======\n"); + + video.mode = HDMI; + if (EDIDHDMIModeSupport(&video)) { + video.colorSpace = HDMI_CS_YCBCR444; + if (EDIDColorSpaceSupport(&video)) + LOGI("= 1. HDMI(YCbCr) =\n"); + + video.colorSpace = HDMI_CS_RGB; + if (EDIDColorSpaceSupport(&video)) + LOGI("= 2. HDMI(RGB) =\n"); + } else { + video.mode = DVI; + if (EDIDHDMIModeSupport(&video)) + LOGI("= 3. DVI =\n"); + } + + LOGI("=========== HDMI Rseolution ========\n"); + + /* 480P */ + video.resolution = v720x480p_60Hz; + video.pixelAspectRatio = HDMI_PIXEL_RATIO_16_9; + video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT; + if (EDIDVideoResolutionSupport(&video)) + LOGI("= 4. 480P_60_16_9 (0x04000000) =\n"); + + video.resolution = v640x480p_60Hz; + video.pixelAspectRatio = HDMI_PIXEL_RATIO_4_3; + video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT; + if (EDIDVideoResolutionSupport(&video)) + LOGI("= 5. 480P_60_4_3 (0x05000000) =\n"); + + /* 576P */ + video.resolution = v720x576p_50Hz; + video.pixelAspectRatio = HDMI_PIXEL_RATIO_16_9; + video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT; + if (EDIDVideoResolutionSupport(&video)) + LOGI("= 6. 576P_50_16_9 (0x06000000) =\n"); + + video.pixelAspectRatio = HDMI_PIXEL_RATIO_4_3; + video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT; + if (EDIDVideoResolutionSupport(&video)) + LOGI("= 7. 576P_50_4_3 (0x07000000) =\n"); + + /* 720P 60 */ + video.resolution = v1280x720p_60Hz; + video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT; + if (EDIDVideoResolutionSupport(&video)) + LOGI("= 8. 720P_60 (0x08000000) =\n"); + + /* 720P_50 */ + video.resolution = v1280x720p_50Hz; + video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT; + if (EDIDVideoResolutionSupport(&video)) + LOGI("= 9. 720P_50 (0x09000000) =\n"); + + /* 1080P_60 */ + video.resolution = v1920x1080p_60Hz; + video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT; + if (EDIDVideoResolutionSupport(&video)) + LOGI("= a. 1080P_60 (0x0a000000) =\n"); + + /* 1080P_50 */ + video.resolution = v1920x1080p_50Hz; + video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT; + if (EDIDVideoResolutionSupport(&video)) + LOGI("= b. 1080P_50 (0x0b000000) =\n"); + + /* 1080I_60 */ + video.resolution = v1920x1080i_60Hz; + video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT; + if (EDIDVideoResolutionSupport(&video)) + LOGI("= c. 1080I_60 (0x0c000000) =\n"); + + /* 1080I_50 */ + video.resolution = v1920x1080i_50Hz; + video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT; + if (EDIDVideoResolutionSupport(&video)) + LOGI("= d. 1080I_50 (0x0d000000) =\n"); + + /* 1080P_30 */ + video.resolution = v1920x1080p_30Hz; + video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT; + if (EDIDVideoResolutionSupport(&video)) + LOGI("= e. 1080P_30 (0x12000000) =\n"); + + LOGI("=========== HDMI 3D Format ========\n"); + + /* 720P_60_SBS_HALF */ + video.resolution = v1280x720p_60Hz; + video.hdmi_3d_format = HDMI_3D_SSH_FORMAT; + if (EDIDVideoResolutionSupport(&video)) + LOGI("= f. 720P_60_SBS_HALF (0x13000000) =\n"); + + /* 720P_59_SBS_HALF */ + video.resolution = v1280x720p_60Hz; + video.hdmi_3d_format = HDMI_3D_SSH_FORMAT; + if (EDIDVideoResolutionSupport(&video)) + LOGI("= 10. 720P_59_SBS_HALF (0x14000000) =\n"); + + /* 720P_50_TB */ + video.resolution = v1280x720p_50Hz; + video.hdmi_3d_format = HDMI_3D_TB_FORMAT; + if (EDIDVideoResolutionSupport(&video)) + LOGI("= 11. 720P_50_TB (0x15000000) =\n"); + + /* 1080P_24_TB */ + video.resolution = v1920x1080p_24Hz; + video.hdmi_3d_format = HDMI_3D_TB_FORMAT; + if (EDIDVideoResolutionSupport(&video)) + LOGI("= 12. 1080P_24_TB (0x16000000) =\n"); + + /* 1080P_23_TB */ + video.resolution = v1920x1080p_24Hz; + video.hdmi_3d_format = HDMI_3D_TB_FORMAT; + if (EDIDVideoResolutionSupport(&video)) + LOGI("= 13. 1080P_24_TB (0x17000000) =\n"); + LOGI("=========================================\n"); +} + +int tvout_open(const char *fp_name) +{ +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("%s", __func__); +#endif + + int fp; + + fp = open(fp_name, O_RDWR); + if (fp < 0) + LOGE("drv (%s) open failed!!\n", fp_name); + + return fp; +} +#if defined(BOARD_USE_V4L2) +int tvout_std_v4l2_init(int fd, unsigned int preset_id) +{ +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("%s:: preset_id = 0x%x", __func__, preset_id); +#endif + + int ret; + struct v4l2_output output; + struct v4l2_dv_preset preset; + + unsigned int matched = 0, i = 0; + int output_index; + +/* + if (output_type >= V4L2_OUTPUT_TYPE_DIGITAL && + output_type <= V4L2_OUTPUT_TYPE_DVI) + if (ioctl(fd_tvout, VIDIOC_HDCP_ENABLE, g_hdcp_en) < 0) + LOGE("%s::VIDIOC_HDCP_ENABLE failed %d", __func__, errno); +*/ + + i = 0; + + do { + output.index = i; + ret = tvout_std_v4l2_enum_output(fd, &output); + LOGD("tvout_v4l2_enum_output():: output_type=%d output.index=%d output.name=%s", output.type, output.index, output.name); + if (output.type == output_type) { + matched = 1; + break; + } + i++; + } while (ret >=0); + + if (!matched) { + LOGE("%s::no matched output type [type=%d]", __func__, output_type); +// return -1; + } + + // set output +// tvout_std_v4l2_s_output(fp_tvout, output.index); +// output_index = 0; +// tvout_std_v4l2_g_output(fp_tvout, &output_index); + +// if (output.capabilities & V4L2_OUT_CAP_PRESETS) { + tvout_std_v4l2_enum_dv_presets(fd); + preset.preset = preset_id; + if (tvout_std_v4l2_s_dv_preset(fd, &preset) < 0 ) { + LOGE("%s::tvout_std_v4l2_s_dv_preset failed", __func__); + return -1; + } +// } + + return 0; +} + +int tvout_std_v4l2_querycap(int fd, char *node) +{ +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("%s", __func__); +#endif + + struct v4l2_capability v4l2cap; + + if (ioctl(fd, VIDIOC_QUERYCAP, &v4l2cap) < 0) { + LOGE("%s::VIDIOC_QUERYCAP failed", __func__); + return -1; + } + + if (!(v4l2cap.capabilities & V4L2_CAP_STREAMING)) { + LOGE("%s::%s is not support streaming", __func__, node); + return -1; + } + + if (!(v4l2cap.capabilities & V4L2_CAP_VIDEO_OUTPUT_MPLANE)) { + LOGE("%s::%s is not support video output mplane", __func__, node); + return -1; + } + + return 0; +} + +int tvout_std_v4l2_enum_dv_presets(int fd) +{ +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("%s", __func__); +#endif + + struct v4l2_dv_enum_preset enum_preset; + int ret = -1; + + for (int index = 0; ; index++) { + enum_preset.index = index; + ret = ioctl(fd, VIDIOC_ENUM_DV_PRESETS, &enum_preset); + + if (ret < 0) { + if (errno == EINVAL) + break; + LOGE("%s::VIDIOC_ENUM_DV_PRESETS", __func__); + return -1; + } +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("%s::index=%d, preset=0x%08x, name=%s, w=%d, h=%d", + __func__, enum_preset.index, enum_preset.preset, enum_preset.name, enum_preset.width, enum_preset.height); +#endif + } + + return 0; +} + +int tvout_std_v4l2_s_dv_preset(int fd, struct v4l2_dv_preset *preset) +{ +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("%s", __func__); +#endif + + if (ioctl(fd, VIDIOC_S_DV_PRESET, preset) < 0) { + LOGE("%s::VIDIOC_S_DV_PRESET failed", __func__); + return -1; + } + + return 0; +} + +/* + ioctl VIDIOC_ENUMOUTPUT + To query the attributes of a video outputs applications initialize the index field of struct v4l2_output + and call the VIDIOC_ENUMOUTPUT ioctl with a pointer to this structure. Drivers fill the rest of the + structure or return an EINVAL error code when the index is out of bounds + */ +int tvout_std_v4l2_enum_output(int fd, struct v4l2_output *output) +{ +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("%s", __func__); +#endif + + int ret; + + ret = ioctl(fd, VIDIOC_ENUMOUTPUT, output); + + if (ret >=0) + LOGV("tvout_v4l2_enum_output" "enum. output [index = %d] :: type : 0x%08x , name = %s\n", + output->index,output->type,output->name); + + return ret; +} + +/* + ioctl VIDIOC_G_OUTPUT, VIDIOC_S_OUTPUT + To query the current video output applications call the VIDIOC_G_OUTPUT ioctl with a pointer to an + integer where the driver stores the number of the output, as in the struct v4l2_output index field. + This ioctl will fail only when there are no video outputs, returning the EINVAL error code + */ +int tvout_std_v4l2_s_output(int fd, int index) +{ +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("%s:: index = 0x%x", __func__, index); +#endif + + int ret; + + ret = ioctl(fd, VIDIOC_S_OUTPUT, &index); + if (ret < 0) { + LOGE("tvout_v4l2_s_output" "VIDIOC_S_OUTPUT failed %d\n", errno); + return ret; + } + + return ret; +} + +int tvout_std_v4l2_g_output(int fd, int *index) +{ +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("%s", __func__); +#endif + + int ret; + + ret = ioctl(fd, VIDIOC_G_OUTPUT, index); + if (ret < 0) { + LOGE("tvout_v4l2_g_output" "VIDIOC_G_OUTPUT failed %d\n", errno); + return ret; + } else { + LOGV("tvout_v4l2_g_output" "Current output index %d\n", *index); + } + + return ret; +} + +int tvout_std_v4l2_s_fmt(int fd, enum v4l2_buf_type type, enum v4l2_field field, int w, int h, int colorformat, int num_planes) +{ +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("%s", __func__); +#endif + + struct v4l2_format fmt; + + fmt.type = type; +// if (ioctl(fd, VIDIOC_G_FMT, &fmt) < 0) { +// LOGE("%s::VIDIOC_G_FMT failed", __func__); +// return -1; +// } + + switch (fmt.type) { + case V4L2_BUF_TYPE_VIDEO_OUTPUT: + case V4L2_BUF_TYPE_VIDEO_CAPTURE: + fmt.fmt.pix.width = w; + fmt.fmt.pix.height = h; + fmt.fmt.pix.pixelformat = colorformat; + fmt.fmt.pix.field = field; + break; + case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: + case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: + fmt.fmt.pix_mp.width = w; + fmt.fmt.pix_mp.height = h; + fmt.fmt.pix_mp.pixelformat = colorformat; + fmt.fmt.pix_mp.field = field; + fmt.fmt.pix_mp.num_planes = num_planes; + break; + default: + LOGE("%s::invalid buffer type", __func__); + return -1; + break; + } + + if (ioctl(fd, VIDIOC_S_FMT, &fmt) < 0) { + LOGE("%s::VIDIOC_S_FMT failed", __func__); + return -1; + } + + return 0; +} + +int tvout_std_v4l2_s_crop(int fd, enum v4l2_buf_type type, enum v4l2_field, int x, int y, int w, int h) +{ +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("%s", __func__); +#endif + + struct v4l2_crop crop; + + crop.type = type; + crop.c.left = x; + crop.c.top = y; + crop.c.width = w; + crop.c.height = h; + + if (ioctl(fd, VIDIOC_S_CROP, &crop) < 0) { + LOGE("%s::VIDIOC_S_CROP (x=%d, y=%d, w=%d, h=%d) failed", + __func__, x, y, w, h); + return -1; + } + + return 0; +} + +int tvout_std_v4l2_s_ctrl(int fd, int id, int value) +{ +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("%s", __func__); +#endif + + struct v4l2_control vc; + + vc.id = id; + vc.value = value; + + if (ioctl(fd, VIDIOC_S_CTRL, &vc) < 0) { + LOGE("%s::VIDIOC_S_CTRL (id=%d,value=%d) failed", __func__, id, value); + return -1; + } + + return 0; +} + +int tvout_std_v4l2_reqbuf(int fd, enum v4l2_buf_type type, enum v4l2_memory memory, unsigned int num_bufs) +{ +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("%s", __func__); +#endif + + struct v4l2_requestbuffers reqbuf; + + reqbuf.type = type; + reqbuf.memory = memory; + reqbuf.count = num_bufs; + + if (ioctl(fd, VIDIOC_REQBUFS, &reqbuf) < 0) { + LOGE("%s::VIDIOC_REQBUFS failed", __func__); + return -1; + } + + if (reqbuf.count < num_bufs) { + LOGE("%s::VIDIOC_REQBUFS failed ((reqbuf.count(%d) < num_bufs(%d))", + __func__, reqbuf.count, num_bufs); + return -1; + } + + return 0; +} + +int tvout_std_v4l2_querybuf(int fd, enum v4l2_buf_type type, enum v4l2_memory memory, unsigned int buf_index, unsigned int num_planes, SecBuffer *secBuf) +{ +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("%s", __func__); +#endif + + struct v4l2_buffer buf; + struct v4l2_plane planes[MAX_PLANES_MIXER]; + + memset(&buf, 0, sizeof(struct v4l2_buffer)); + + for (int i = 0; i < MAX_PLANES_MIXER; i++) + memset(&planes[i], 0, sizeof(struct v4l2_plane)); + + if (MAX_BUFFERS_MIXER <= buf_index || MAX_PLANES_MIXER <= num_planes) { + LOGE("%s::exceed MAX! : buf_index=%d, num_plane=%d", __func__, buf_index, num_planes); + return -1; + } + + buf.type = type; + buf.memory = V4L2_MEMORY_MMAP; + buf.index = buf_index; + buf.length = num_planes; + buf.m.planes = planes; + + if (ioctl(fd, VIDIOC_QUERYBUF, &buf) < 0) { + LOGE("%s::VIDIOC_QUERYBUF failed, plane_cnt=%d", __func__, buf.length); + return -1; + } + + for (unsigned int i = 0; i < num_planes; i++) { + if ((secBuf->virt.extP[i] = (char *)mmap(0, buf.m.planes[i].length, + PROT_READ | PROT_WRITE, MAP_SHARED, fd, buf.m.planes[i].m.mem_offset)) < 0) { + LOGE("%s::mmap failed", __func__); + LOGE("%s::Offset = 0x%x", __func__, buf.m.planes[i].m.mem_offset); + LOGE("%s::Legnth = %d" , __func__, buf.m.planes[i].length); + LOGE("%s::vaddr[%d][%d] = 0x%x", __func__, buf_index, i, (unsigned int)secBuf->virt.extP[i]); + return -1; + } + secBuf->size.extS[i] = buf.m.planes[i].length; + +#ifdef DEBUG_LIB_FIMC + LOGD("%s::vaddr[bufidx=%d][planeidx=%d] = 0x%x", __func__, buf_index, i, (unsigned int)secBuf->virt.extP[i]); + LOGD("%s::Legnth = %d" , __func__, buf.m.planes[i].length); +#endif + } + + return 0; +} + +int tvout_std_v4l2_qbuf(int fd, enum v4l2_buf_type type, enum v4l2_memory memory, int buf_index, int num_planes, SecBuffer *secBuf) +{ +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("%s", __func__); +#endif + + struct v4l2_buffer buf; + struct v4l2_plane planes[MAX_PLANES_MIXER]; + + memset(&buf, 0, sizeof(struct v4l2_buffer)); + + for (int i = 0; i < MAX_PLANES_MIXER; i++) + memset(&planes[i], 0, sizeof(struct v4l2_plane)); + + buf.type = type; + buf.memory = memory; + buf.length = num_planes; + buf.index = buf_index; + buf.m.planes = planes; + + for (unsigned int i = 0; i < buf.length; i++) { + buf.m.planes[i].m.userptr = (unsigned long)secBuf->virt.extP[i]; + buf.m.planes[i].length = secBuf->size.extS[i]; + } + + if (ioctl(fd, VIDIOC_QBUF, &buf) < 0) { + LOGE("%s::VIDIOC_QBUF failed", __func__); + return -1; + } + + return 0; +} + +int tvout_std_v4l2_dqbuf(int fd, enum v4l2_buf_type type, enum v4l2_memory memory, int *buf_index, int num_planes) +{ +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("%s", __func__); +#endif + + struct v4l2_buffer buf; + struct v4l2_plane planes[MAX_PLANES_MIXER]; + + memset(&buf, 0, sizeof(struct v4l2_buffer)); + + for (int i = 0; i < MAX_PLANES_MIXER; i++) + memset(&planes[i], 0, sizeof(struct v4l2_plane)); + + buf.type = type; + buf.memory = memory; + buf.length = num_planes; + buf.m.planes = planes; + + if (ioctl(fd, VIDIOC_DQBUF, &buf) < 0) { + LOGE("%s::VIDIOC_DQBUF failed", __func__); + return -1; + } + *buf_index = buf.index; + + return 0; +} + +int tvout_std_v4l2_streamon(int fd, enum v4l2_buf_type type) +{ +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("%s", __func__); +#endif + + if (ioctl(fd, VIDIOC_STREAMON, &type) < 0) { + LOGE("%s::VIDIOC_STREAMON failed", __func__); + return -1; + } + + return 0; +} + +int tvout_std_v4l2_streamoff(int fd, enum v4l2_buf_type type) +{ +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("%s", __func__); +#endif + + if (ioctl(fd, VIDIOC_STREAMOFF, &type) < 0) { + LOGE("%s::VIDIOC_STREAMOFF failed", __func__); + return -1; + } + + return 0; +} +#else +int tvout_init(v4l2_std_id std_id) +{ +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("%s:: std_id = 0x%x", __func__, std_id); +#endif + + int ret; + struct v4l2_output output; + struct v4l2_standard std; + v4l2_std_id std_g_id; + struct tvout_param tv_g_param; + + unsigned int matched = 0, i = 0; + int output_index; + + // It was initialized already + if (fp_tvout <= 0) { + fp_tvout = tvout_open(TVOUT_DEV); + if (fp_tvout < 0) { + LOGE("tvout video drv open failed\n"); + return -1; + } + } + + if (output_type >= V4L2_OUTPUT_TYPE_DIGITAL && + output_type <= V4L2_OUTPUT_TYPE_DVI) + if (ioctl(fp_tvout, VIDIOC_HDCP_ENABLE, g_hdcp_en) < 0) + LOGE("tvout_init" "VIDIOC_HDCP_ENABLE failed %d\n", errno); + + /* ============== query capability============== */ + tvout_v4l2_querycap(fp_tvout); + + tvout_v4l2_enum_std(fp_tvout, &std, std_id); + + // set std + tvout_v4l2_s_std(fp_tvout, std_id); + tvout_v4l2_g_std(fp_tvout, &std_g_id); + + i = 0; + + do { + output.index = i; + ret = tvout_v4l2_enum_output(fp_tvout, &output); + if (output.type == output_type) { + matched = 1; + break; + } + i++; + } while (ret >=0); + + if (!matched) { + LOGE("no matched output type [type : 0x%08x]\n", output_type); + return -1; + } + + // set output + tvout_v4l2_s_output(fp_tvout, output.index); + output_index = 0; + tvout_v4l2_g_output(fp_tvout, &output_index); + + //set fmt param + vo_param.src.base_y = (void *)0x0; + vo_param.src.base_c = (void *)0x0; + vo_param.src.pix_fmt.width = 0; + vo_param.src.pix_fmt.height = 0; + vo_param.src.pix_fmt.field = V4L2_FIELD_NONE; + vo_param.src.pix_fmt.pixelformat = V4L2_PIX_FMT_NV12T; + + vo_param.src_crop.left = 0; + vo_param.src_crop.top = 0; + vo_param.src_crop.width = 0; + vo_param.src_crop.height = 0; + + return fp_tvout; +} + +int tvout_deinit() +{ +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("%s", __func__); +#endif + + if (0 < fp_tvout) { + close(fp_tvout); + fp_tvout = -1; + } + return 0; +} + +int tvout_v4l2_querycap(int fp) +{ +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("%s:: fp = 0x%x", __func__, fp); +#endif + + struct v4l2_capability cap; + int ret; + + ret = ioctl(fp, VIDIOC_QUERYCAP, &cap); + + if (ret < 0) { + LOGE("tvout_v4l2_querycap" "VIDIOC_QUERYCAP failed %d\n", errno); + return ret; + } + +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("tvout_v4l2_querycap" "DRIVER : %s, CARD : %s, CAP.: 0x%08x\n", + cap.driver, cap.card, cap.capabilities); +#endif + + return ret; +} + +/* + ioctl VIDIOC_G_STD, VIDIOC_S_STD + To query and select the current video standard applications use the VIDIOC_G_STD and + VIDIOC_S_STD ioctls which take a pointer to a v4l2_std_id type as argument. VIDIOC_G_STD can + return a single flag or a set of flags as in struct v4l2_standard field id + */ + +int tvout_v4l2_g_std(int fp, v4l2_std_id *std_id) +{ +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("%s", __func__); +#endif + + int ret; + + ret = ioctl(fp, VIDIOC_G_STD, std_id); + if (ret < 0) { + LOGE("tvout_v4l2_g_std" "VIDIOC_G_STD failed %d\n", errno); + return ret; + } + + return ret; +} + +int tvout_v4l2_s_std(int fp, v4l2_std_id std_id) +{ +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("%s:: std_id = 0x%x", __func__, std_id); +#endif + + int ret; + + ret = ioctl(fp, VIDIOC_S_STD, &std_id); + if (ret < 0) { + LOGE("tvout_v4l2_s_std" "VIDIOC_S_STD failed %d\n", errno); + return ret; + } + + return ret; +} + +/* + ioctl VIDIOC_ENUMSTD + To query the attributes of a video standard, especially a custom (driver defined) one, applications + initialize the index field of struct v4l2_standard and call the VIDIOC_ENUMSTD ioctl with a pointer + to this structure. Drivers fill the rest of the structure or return an EINVAL error code when the index + is out of bounds. + */ +int tvout_v4l2_enum_std(int fp, struct v4l2_standard *std, v4l2_std_id std_id) +{ +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("%s", __func__); +#endif + + std->index = 0; + while (0 == ioctl (fp, VIDIOC_ENUMSTD, std)) { + if (std->id & std_id) + LOGV("tvout_v4l2_enum_std" "Current video standard: %s\n", std->name); + + std->index++; + } + + return 0; +} + +/* + ioctl VIDIOC_ENUMOUTPUT + To query the attributes of a video outputs applications initialize the index field of struct v4l2_output + and call the VIDIOC_ENUMOUTPUT ioctl with a pointer to this structure. Drivers fill the rest of the + structure or return an EINVAL error code when the index is out of bounds + */ +int tvout_v4l2_enum_output(int fp, struct v4l2_output *output) +{ +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("%s", __func__); +#endif + + int ret; + + ret = ioctl(fp, VIDIOC_ENUMOUTPUT, output); + + if (ret >=0) + LOGV("tvout_v4l2_enum_output" "enum. output [index = %d] :: type : 0x%08x , name = %s\n", + output->index,output->type,output->name); + + return ret; +} + +/* + ioctl VIDIOC_G_OUTPUT, VIDIOC_S_OUTPUT + To query the current video output applications call the VIDIOC_G_OUTPUT ioctl with a pointer to an + integer where the driver stores the number of the output, as in the struct v4l2_output index field. + This ioctl will fail only when there are no video outputs, returning the EINVAL error code + */ +int tvout_v4l2_s_output(int fp, int index) +{ +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("%s:: index = 0x%x", __func__, index); +#endif + + int ret; + + ret = ioctl(fp, VIDIOC_S_OUTPUT, &index); + if (ret < 0) { + LOGE("tvout_v4l2_s_output" "VIDIOC_S_OUTPUT failed %d\n", errno); + return ret; + } + + return ret; +} + +int tvout_v4l2_g_output(int fp, int *index) +{ +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("%s", __func__); +#endif + + int ret; + + ret = ioctl(fp, VIDIOC_G_OUTPUT, index); + if (ret < 0) { + LOGE("tvout_v4l2_g_output" "VIDIOC_G_OUTPUT failed %d\n", errno); + return ret; + } else { + LOGV("tvout_v4l2_g_output" "Current output index %d\n", *index); + } + + return ret; +} + +/* + ioctl VIDIOC_ENUM_FMT + To enumerate image formats applications initialize the type and index field of struct v4l2_fmtdesc + and call the VIDIOC_ENUM_FMT ioctl with a pointer to this structure. Drivers fill the rest of the + structure or return an EINVAL error code. All formats are enumerable by beginning at index zero + and incrementing by one until EINVAL is returned. + */ +int tvout_v4l2_enum_fmt(int fp, struct v4l2_fmtdesc *desc) +{ +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("%s", __func__); +#endif + + desc->index = 0; + while (0 == ioctl(fp, VIDIOC_ENUM_FMT, desc)) { + LOGV("tvout_v4l2_enum_fmt" "enum. fmt [id : 0x%08x] :: type = 0x%08x, name = %s, pxlfmt = 0x%08x\n", + desc->index, + desc->type, + desc->description, + desc->pixelformat); + desc->index++; + } + + return 0; +} + +int tvout_v4l2_g_fmt(int fp, int buf_type, void* ptr) +{ +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("%s", __func__); +#endif + + int ret; + struct v4l2_format format; + struct v4l2_pix_format_s5p_tvout *fmt_param = (struct v4l2_pix_format_s5p_tvout*)ptr; + + format.type = (enum v4l2_buf_type)buf_type; + + ret = ioctl(fp, VIDIOC_G_FMT, &format); + if (ret < 0) { + LOGE("tvout_v4l2_g_fmt" "type : %d, VIDIOC_G_FMT failed %d\n", buf_type, errno); + return ret; + } else { + memcpy(fmt_param, format.fmt.raw_data, sizeof(struct v4l2_pix_format_s5p_tvout)); + LOGV("tvout_v4l2_g_fmt" "get. fmt [base_c : 0x%08x], [base_y : 0x%08x] type = 0x%08x, width = %d, height = %d\n", + fmt_param->base_c, + fmt_param->base_y, + fmt_param->pix_fmt.pixelformat, + fmt_param->pix_fmt.width, + fmt_param->pix_fmt.height); + } + + return 0; +} + +int tvout_v4l2_s_fmt(int fp, int buf_type, void *ptr) +{ +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("%s", __func__); +#endif + + struct v4l2_format format; + int ret; + + format.type = (enum v4l2_buf_type)buf_type; + switch (buf_type) { + case V4L2_BUF_TYPE_VIDEO_OVERLAY: + format.fmt.win = *((struct v4l2_window *) ptr); + break; + + case V4L2_BUF_TYPE_PRIVATE: { + struct v4l2_vid_overlay_src *fmt_param = + (struct v4l2_vid_overlay_src *) ptr; + + memcpy(format.fmt.raw_data, fmt_param, + sizeof(struct v4l2_vid_overlay_src)); + break; + } + case V4L2_BUF_TYPE_VIDEO_OUTPUT: { + struct v4l2_pix_format_s5p_tvout *fmt_param = + (struct v4l2_pix_format_s5p_tvout *)ptr; + memcpy(format.fmt.raw_data, fmt_param, + sizeof(struct v4l2_pix_format_s5p_tvout)); + break; + } + default: + break; + } + + ret = ioctl(fp, VIDIOC_S_FMT, &format); + if (ret < 0) { + LOGE("tvout_v4l2_s_fmt [tvout_v4l2_s_fmt] : type : %d, VIDIOC_S_FMT failed %d\n", + buf_type, errno); + return ret; + } + return 0; + +} + +int tvout_v4l2_g_fbuf(int fp, struct v4l2_framebuffer *frame) +{ +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("%s", __func__); +#endif + + int ret; + + ret = ioctl(fp, VIDIOC_G_FBUF, frame); + if (ret < 0) { + LOGE("tvout_v4l2_g_fbuf" "VIDIOC_STREAMON failed %d\n", errno); + return ret; + } + + LOGV("tvout_v4l2_g_fbuf" "get. fbuf: base = 0x%08X, pixel format = %d\n", + frame->base, + frame->fmt.pixelformat); + return 0; +} + +int tvout_v4l2_s_fbuf(int fp, struct v4l2_framebuffer *frame) +{ +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("%s", __func__); +#endif + + int ret; + + ret = ioctl(fp, VIDIOC_S_FBUF, frame); + if (ret < 0) { + LOGE("tvout_v4l2_s_fbuf" "VIDIOC_STREAMON failed %d\n", errno); + return ret; + } + return 0; +} + +int tvout_v4l2_s_baseaddr(int fp, void *base_addr) +{ +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("%s", __func__); +#endif + + int ret; + + ret = ioctl(fp, S5PTVFB_WIN_SET_ADDR, base_addr); + if (ret < 0) { + LOGE("tvout_v4l2_baseaddr" "VIDIOC_S_BASEADDR failed %d\n", errno); + return ret; + } + return 0; +} + +int tvout_v4l2_g_crop(int fp, unsigned int type, struct v4l2_rect *rect) +{ +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("%s", __func__); +#endif + + int ret; + struct v4l2_crop crop; + crop.type = (enum v4l2_buf_type)type; + ret = ioctl(fp, VIDIOC_G_CROP, &crop); + if (ret < 0) { + LOGE("tvout_v4l2_g_crop" "VIDIOC_G_CROP failed %d\n", errno); + return ret; + } + + rect->left = crop.c.left; + rect->top = crop.c.top; + rect->width = crop.c.width; + rect->height = crop.c.height; + + LOGV("tvout_v4l2_g_crop" "get. crop : left = %d, top = %d, width = %d, height = %d\n", + rect->left, + rect->top, + rect->width, + rect->height); + return 0; +} + +int tvout_v4l2_s_crop(int fp, unsigned int type, struct v4l2_rect *rect) +{ +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("%s", __func__); +#endif + + struct v4l2_crop crop; + int ret; + + crop.type = (enum v4l2_buf_type)type; + + crop.c.left = rect->left; + crop.c.top = rect->top; + crop.c.width = rect->width; + crop.c.height = rect->height; + + ret = ioctl(fp, VIDIOC_S_CROP, &crop); + if (ret < 0) { + LOGE("tvout_v4l2_s_crop" "VIDIOC_S_CROP failed %d\n", errno); + return ret; + } + + return 0; +} + +int tvout_v4l2_start_overlay(int fp) +{ +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("%s", __func__); +#endif + + int ret, start = 1; + + ret = ioctl(fp, VIDIOC_OVERLAY, &start); + if (ret < 0) { + LOGE("tvout_v4l2_start_overlay" "VIDIOC_OVERLAY failed\n"); + return ret; + } + + return ret; +} + +int tvout_v4l2_stop_overlay(int fp) +{ +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("%s", __func__); +#endif + + int ret, stop =0; + + ret = ioctl(fp, VIDIOC_OVERLAY, &stop); + if (ret < 0) { + LOGE("tvout_v4l2_stop_overlay" "VIDIOC_OVERLAY failed\n"); + return ret; + } + + return ret; +} +#endif + +int hdmi_init_layer(int layer) +{ + int fd = -1; +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("### %s (layer = %d) called", __func__, layer); +#endif + + switch (layer) { + case HDMI_LAYER_VIDEO : + if (fp_tvout_v <= 0) { + fp_tvout_v = tvout_open(TVOUT_DEV_V); + if (fp_tvout_v < 0) { + LOGE("tvout video layer open failed\n"); + return -1; + } + fd = fp_tvout_v; + } + break; + case HDMI_LAYER_GRAPHIC_0 : + if (fp_tvout_g0 <= 0) { +#if defined(BOARD_USE_V4L2) + fp_tvout_g0 = tvout_open(TVOUT_DEV_G0); +#else + fp_tvout_g0 = fb_open(TVOUT_FB_G0); +#endif + if (fp_tvout_g0 < 0) { + LOGE("tvout graphic layer 0 open failed\n"); + return -1; + } + fd = fp_tvout_g0; + } + break; + case HDMI_LAYER_GRAPHIC_1 : + if (fp_tvout_g1 <= 0) { +#if defined(BOARD_USE_V4L2) + fp_tvout_g1 = tvout_open(TVOUT_DEV_G1); +#else + fp_tvout_g1 = fb_open(TVOUT_FB_G1); +#endif + if (fp_tvout_g1 < 0) { + LOGE("tvout graphic layer 1 open failed\n"); + return -1; + } + fd = fp_tvout_g1; + } + break; + default : + LOGE("%s::unmathced layer(%d) fail", __func__, layer); + fd = -1; + break; + } + + return fd; +} + +int hdmi_deinit_layer(int layer) +{ + int ret = 0; +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("### %s(layer = %d) called", __func__, layer); +#endif + switch (layer) { + case HDMI_LAYER_VIDEO : + if (0 < fp_tvout_v) { + close(fp_tvout_v); + fp_tvout_v = -1; + } + break; + case HDMI_LAYER_GRAPHIC_0 : + if (0 < fp_tvout_g0) { + close(fp_tvout_g0); + fp_tvout_g0 = -1; + } + break; + case HDMI_LAYER_GRAPHIC_1 : + if (0 < fp_tvout_g1) { + close(fp_tvout_g1); + fp_tvout_g1 = -1; + } + break; + default : + LOGE("%s::unmathced layer(%d) fail", __func__, layer); + ret = -1; + break; + } + + return ret; +} + +#define ROUND_UP(value, boundary) ((((uint32_t)(value)) + \ + (((uint32_t) boundary)-1)) & \ + (~(((uint32_t) boundary)-1))) + +void hdmi_cal_rect(int src_w, int src_h, int dst_w, int dst_h, struct v4l2_rect *dst_rect) +{ + if (dst_w * src_h <= dst_h * src_w) { + dst_rect->left = 0; + dst_rect->top = (dst_h - ((dst_w * src_h) / src_w)) >> 1; + dst_rect->width = dst_w; + dst_rect->height = ((dst_w * src_h) / src_w); + } else { + dst_rect->left = (dst_w - ((dst_h * src_w) / src_h)) >> 1; + dst_rect->top = 0; + dst_rect->width = ((dst_h * src_w) / src_h); + dst_rect->height = dst_h; + } +} + +#if defined(BOARD_USE_V4L2) +int hdmi_get_src_plane(int srcColorFormat, unsigned int *num_of_plane) +{ + int v4l2ColorFormat = HAL_PIXEL_FORMAT_2_V4L2_PIX(srcColorFormat); + + switch (v4l2ColorFormat) { + case V4L2_PIX_FMT_NV12: + case V4L2_PIX_FMT_NV21: + case V4L2_PIX_FMT_BGR32: + case V4L2_PIX_FMT_RGB32: + case V4L2_PIX_FMT_RGB565X: + *num_of_plane = 1; + break; + case V4L2_PIX_FMT_NV12M: + case V4L2_PIX_FMT_NV12MT: + case V4L2_PIX_FMT_NV21M: + *num_of_plane = 2; + break; + default: + LOGE("%s::invalid color type", __func__); + return -1; + } + + return 0; +} +#endif + +#if defined(BOARD_USE_V4L2) +int hdmi_set_v_param(int fd, int layer, + int srcColorFormat, + int src_w, int src_h, + SecBuffer * dstBuffer, + int dst_x, int dst_y, int dst_w, int dst_h) +{ +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("%s", __func__); +#endif + + int v4l2ColorFormat = HAL_PIXEL_FORMAT_2_V4L2_PIX(srcColorFormat); + int round_up_src_w; + int round_up_src_h; + unsigned int num_of_plane; + struct v4l2_rect rect; + + /* src_w, src_h round up to DWORD because of VP restriction */ +#if defined(SAMSUNG_EXYNOS4x12) + round_up_src_w = ROUND_UP(src_w, 16); +#else defined(SAMSUNG_EXYNOS4210) + round_up_src_w = ROUND_UP(src_w, 8); +#endif + round_up_src_h = ROUND_UP(src_h, 8); + + switch (v4l2ColorFormat) { + case V4L2_PIX_FMT_NV12: + case V4L2_PIX_FMT_NV21: + dstBuffer->size.s = (round_up_src_w * round_up_src_h * 3) >> 1; + num_of_plane = 1; + break; + case V4L2_PIX_FMT_NV12M: + case V4L2_PIX_FMT_NV12MT: + case V4L2_PIX_FMT_NV21M: + dstBuffer->size.extS[0] = (round_up_src_w * round_up_src_h * 3) >> 1; + dstBuffer->size.extS[1] = (round_up_src_w * round_up_src_h * 3) >> 2; + num_of_plane = 2; + break; + default: + LOGE("%s::invalid color type", __func__); + return false; + break; + } + + hdmi_cal_rect(src_w, src_h, dst_w, dst_h, &rect); + rect.left = ALIGN(rect.left, 16); + + /* set format for VP input */ + if (tvout_std_v4l2_s_fmt(fd, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, V4L2_FIELD_ANY, round_up_src_w, round_up_src_h, v4l2ColorFormat, num_of_plane) < 0) { + LOGE("%s::tvout_std_v4l2_s_fmt()[video layer] failed", __func__); + return -1; + } + + /* set crop for VP input */ + if (tvout_std_v4l2_s_crop(fd, V4L2_BUF_TYPE_VIDEO_OVERLAY, V4L2_FIELD_ANY, 0, 0, src_w, src_h) < 0) { + LOGE("%s::tvout_std_v4l2_s_crop()[video layer] failed", __func__); + return -1; + } + + /* set crop for VP output */ + if (tvout_std_v4l2_s_crop(fd, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, V4L2_FIELD_ANY, rect.left, rect.top, rect.width, rect.height) < 0) { + LOGE("%s::tvout_std_v4l2_s_crop()[video layer] failed", __func__); + return -1; + } + + /* request buffer for VP input */ + if (tvout_std_v4l2_reqbuf(fd, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, V4L2_MEMORY_USERPTR, HDMI_NUM_MIXER_BUF) < 0) { + LOGE("%s::tvout_std_v4l2_reqbuf(buf_num=%d)[video layer] failed", __func__, HDMI_NUM_MIXER_BUF); + return -1; + } + + return 0; +} + +int hdmi_set_g_param(int fd, int layer, + int srcColorFormat, + int src_w, int src_h, + SecBuffer * dstBuffer, + int dst_x, int dst_y, int dst_w, int dst_h) +{ +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("%s", __func__); +#endif + + struct v4l2_rect rect; + int v4l2ColorFormat = HAL_PIXEL_FORMAT_2_V4L2_PIX(srcColorFormat); + + rect.left = dst_x; + rect.top = dst_y; + +#if defined(BOARD_USES_FIMGAPI) + rect.width = dst_w; + rect.height = dst_h; +#else + rect.width = src_w; + rect.height = src_h; +#endif + + switch (v4l2ColorFormat) { + case V4L2_PIX_FMT_BGR32: + case V4L2_PIX_FMT_RGB32: + dstBuffer->size.s = rect.width * rect.height << 2; + break; + case V4L2_PIX_FMT_RGB565X: + dstBuffer->size.s = rect.width * rect.height << 1; + break; + default: + LOGE("%s::invalid color type", __func__); + return false; + break; + } + + /* set format for mixer graphic layer input device*/ + if (tvout_std_v4l2_s_fmt(fd, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, V4L2_FIELD_ANY, rect.width, rect.height, v4l2ColorFormat, 1) < 0) { + LOGE("%s::tvout_std_v4l2_s_fmt() [layer=%d] failed", __func__, layer); + return -1; + } + + /* set crop for mixer graphic layer input device*/ + if (tvout_std_v4l2_s_crop(fd, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, V4L2_FIELD_ANY, rect.left, rect.top, rect.width, rect.height) < 0) { + LOGE("%s::tvout_std_v4l2_s_crop() [layer=%d] failed", __func__, layer); + return -1; + } + + /* request buffer for mixer graphic layer input device */ + if (tvout_std_v4l2_reqbuf(fd, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, V4L2_MEMORY_USERPTR, HDMI_NUM_MIXER_BUF) < 0) { + LOGE("%s::tvout_std_v4l2_reqbuf(buf_num=%d) [layer=%d] failed", __func__, HDMI_NUM_MIXER_BUF, layer); + return -1; + } + + /* enable alpha blending for mixer graphic layer */ + if (tvout_std_v4l2_s_ctrl(fd, V4L2_CID_TV_LAYER_BLEND_ENABLE, 1) < 0) { + LOGE("%s::tvout_std_v4l2_s_ctrl() [layer=%d] failed", __func__, layer); + return -1; + } + + /* enable per-pixel blending for mixer graphic layer */ + if (tvout_std_v4l2_s_ctrl(fd, V4L2_CID_TV_PIXEL_BLEND_ENABLE, 1) < 0) { + LOGE("%s::tvout_std_v4l2_s_ctrl [layer=%d] failed", __func__, layer); + return false; + } + + /* set global alpha value for mixer graphic layer */ + if (tvout_std_v4l2_s_ctrl(fd, V4L2_CID_TV_LAYER_BLEND_ALPHA, 255) < 0) { + LOGE("%s::tvout_std_v4l2_s_ctrl() [layer=%d] failed", __func__, layer); + return -1; + } + + return 0; +} + +int hdmi_set_g_scaling(int layer, + int srcColorFormat, + int src_w, int src_h, + unsigned int src_address, SecBuffer * dstBuffer, + int dst_x, int dst_y, int dst_w, int dst_h, + int rotVal, unsigned int hwc_layer) +{ +#if defined(BOARD_USES_FIMGAPI) + int dst_color_format; + int dst_bpp; + unsigned char *dst_addr; + fimg2d_blit BlitParam; + rotation g2d_rotation; + + fimg2d_addr srcAddr; + fimg2d_image srcImage; + fimg2d_rect srcRect; + + fimg2d_addr dstAddr; + fimg2d_image dstImage; + fimg2d_rect dstRect; + + fimg2d_clip dstClip; + fimg2d_scale Scaling; + + switch (g_preset_id) { + case V4L2_DV_1080P60: + case V4L2_DV_1080P30: + case V4L2_DV_1080I60: + case V4L2_DV_720P60_SB_HALF: + case V4L2_DV_720P59_94_SB_HALF: + case V4L2_DV_1080P24_TB: + case V4L2_DV_1080P23_98_TB: + dst_color_format = CF_ARGB_8888; + dst_bpp = 4; + break; + case V4L2_DV_480P60: + case V4L2_DV_576P50: + case V4L2_DV_720P60: + case V4L2_DV_720P50_TB: + default: + dst_color_format = CF_ARGB_4444; + dst_bpp = 2; + break; + } + + static unsigned int prev_src_addr = 0; + + if ((cur_g2d_address == 0) || (src_address != prev_src_addr)) { + dst_addr = (unsigned char *)g2d_reserved_memory[g2d_buf_index]; + + g2d_buf_index++; + if (g2d_buf_index >= HDMI_G2D_OUTPUT_BUF_NUM) + g2d_buf_index = 0; + + cur_g2d_address = (unsigned int)dst_addr; + prev_src_addr = src_address; + + srcAddr = {(addr_space)ADDR_USER, (unsigned long)src_address, src_w * src_h * 4, 1, 0}; + srcImage = {srcAddr, srcAddr, src_w, src_h, src_w*4, AX_RGB, CF_ARGB_8888}; + srcRect = {0, 0, src_w, src_h}; + + dstAddr = {(addr_space)ADDR_USER, (unsigned long)dst_addr, dst_w * dst_h * dst_bpp, 1, 0}; + dstImage = {dstAddr, dstAddr, dst_w, dst_h, dst_w*dst_bpp, AX_RGB, (color_format)dst_color_format}; + dstRect = {0, 0, dst_w, dst_h}; + dstClip = {0, 0, 0, dst_w, dst_h}; + + if (rotVal == 0 || rotVal == 180) + Scaling = {SCALING_BILINEAR, SCALING_PIXELS, 0, 0, src_w, src_h, dst_w, dst_h}; + else + Scaling = {SCALING_BILINEAR, SCALING_PIXELS, 0, 0, src_w, src_h, dst_h, dst_w}; + + switch (rotVal) { + case 0: + g2d_rotation = ORIGIN; + break; + case 90: + g2d_rotation = ROT_90; + break; + case 180: + g2d_rotation = ROT_180; + break; + case 270: + g2d_rotation = ROT_270; + break; + default: + LOGE("%s::invalid rotVal(%d) fail", __func__, rotVal); + return -1; + break; + } + + BlitParam = {BLIT_OP_SRC, NON_PREMULTIPLIED, 0xff, 0, g2d_rotation, &Scaling, 0, 0, &dstClip, 0, &srcImage, &dstImage, NULL, &srcRect, &dstRect, NULL, 0}; + + if (stretchFimgApi(&BlitParam) < 0) { + LOGE("%s::stretchFimgApi() fail", __func__); + return -1; + } + +#ifdef DEBUG_MSG_ENABLE + LOGD("hdmi_set_g_scaling:: \n \\ + layer=%d,\n \\ + srcColorFormat=%d,\n \\ + src_w=%d, src_h=%d,\n\\ + src_address=0x%x, dst_addr=0x%x,\n\\ + dst_x=%d, dst_y=%d, dst_w=%d, dst_h=%d ", + layer, + srcColorFormat, + src_w, src_h, + src_address, dst_addr, + dst_x, dst_y, dst_w, dst_h); +#endif + dstBuffer->virt.p = (char *)dst_addr; + } +#else + dstBuffer->virt.p = (char *)src_address; +#endif + + return 0; +} +#else +int hdmi_set_v_param(int layer, + int src_w, int src_h, int colorFormat, + unsigned int src_y_address, unsigned int src_c_address, + int dst_w, int dst_h) +{ +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("%s", __func__); +#endif + + int round_up_src_w; + int round_up_src_h; + if (fp_tvout_v <= 0) { + LOGE("fp_tvout is < 0 fail\n"); + return -1; + } + + /* src_w, src_h round up to DWORD because of VP restriction */ +#if defined(SAMSUNG_EXYNOS4x12) + round_up_src_w = ROUND_UP(src_w, 16); +#else defined(SAMSUNG_EXYNOS4210) + round_up_src_w = ROUND_UP(src_w, 8); +#endif + round_up_src_h = ROUND_UP(src_h, 8); + + vo_param.src.base_y = (void *)src_y_address; + vo_param.src.base_c = (void *)src_c_address; + vo_param.src.pix_fmt.width = round_up_src_w; + vo_param.src.pix_fmt.height = round_up_src_h; + vo_param.src.pix_fmt.field = V4L2_FIELD_NONE; + vo_param.src.pix_fmt.pixelformat = colorFormat; + + tvout_v4l2_s_fmt(fp_tvout_v, V4L2_BUF_TYPE_PRIVATE, &vo_param.src); + + vo_param.src_crop.width = src_w; + vo_param.src_crop.height = src_h; + + tvout_v4l2_s_crop(fp_tvout_v, V4L2_BUF_TYPE_PRIVATE, &vo_param.src_crop); + + if (dst_w * src_h <= dst_h * src_w) { + vo_param.dst_win.w.left = 0; + vo_param.dst_win.w.top = (dst_h - ((dst_w * src_h) / src_w)) >> 1; + vo_param.dst_win.w.width = dst_w; + vo_param.dst_win.w.height = ((dst_w * src_h) / src_w); + } else { + vo_param.dst_win.w.left = (dst_w - ((dst_h * src_w) / src_h)) >> 1; + vo_param.dst_win.w.top = 0; + vo_param.dst_win.w.width = ((dst_h * src_w) / src_h); + vo_param.dst_win.w.height = dst_h; + } + + vo_param.dst.fmt.priv = 10; + vo_param.dst_win.global_alpha = 255; + tvout_v4l2_s_fbuf(fp_tvout_v, &vo_param.dst); + tvout_v4l2_s_fmt(fp_tvout_v, V4L2_BUF_TYPE_VIDEO_OVERLAY, &vo_param.dst_win); + + return 0; +} + +int hdmi_gl_set_param(int layer, + int srcColorFormat, + int src_w, int src_h, + unsigned int src_y_address, unsigned int src_c_address, + int dst_x, int dst_y, int dst_w, int dst_h, + int rotVal) +{ +#if defined(BOARD_USES_FIMGAPI) + int dst_color_format; + int dst_bpp; + unsigned char *dst_addr; + fimg2d_blit BlitParam; + rotation g2d_rotation; + + fimg2d_addr srcAddr; + fimg2d_image srcImage; + fimg2d_rect srcRect; + + fimg2d_addr dstAddr; + fimg2d_image dstImage; + fimg2d_rect dstRect; + + fimg2d_clip dstClip; + fimg2d_scale Scaling; + + struct fb_var_screeninfo var; + struct s5ptvfb_user_window window; + + int fp_tvout_g; + + if(layer == HDMI_LAYER_GRAPHIC_0) + fp_tvout_g = fp_tvout_g0; + else + fp_tvout_g = fp_tvout_g1; + + switch (t_std_id) { + case V4L2_STD_1080P_60: + case V4L2_STD_1080P_30: + case V4L2_STD_1080I_60: + case V4L2_STD_TVOUT_720P_60_SBS_HALF: + case V4L2_STD_TVOUT_720P_59_SBS_HALF: + case V4L2_STD_TVOUT_1080P_24_TB: + case V4L2_STD_TVOUT_1080P_23_TB: + dst_color_format = CF_ARGB_8888; + dst_bpp = 4; + var.bits_per_pixel = 32; + var.transp.length = 8; + break; + case V4L2_STD_480P_60_16_9: + case V4L2_STD_576P_50_16_9: + case V4L2_STD_720P_60: + case V4L2_STD_TVOUT_720P_50_TB: + default: + dst_color_format = CF_ARGB_4444; + dst_bpp = 2; + var.bits_per_pixel = 16; + var.transp.length = 4; + break; + } + + static unsigned int prev_src_addr = 0; + + if ((cur_g2d_address == 0) || (src_y_address != prev_src_addr)) { + dst_addr = (unsigned char *)g2d_reserved_memory[g2d_buf_index]; + + g2d_buf_index++; + if (g2d_buf_index >= HDMI_G2D_OUTPUT_BUF_NUM) + g2d_buf_index = 0; + + cur_g2d_address = (unsigned int)dst_addr; + prev_src_addr = src_y_address; + + srcAddr = {(addr_space)ADDR_PHYS, (unsigned long)src_y_address, src_w*src_h*4, 1, 0}; + srcImage = {srcAddr, srcAddr, src_w, src_h, src_w*4, AX_RGB, CF_ARGB_8888}; + srcRect = {0, 0, src_w, src_h}; + + dstAddr = {(addr_space)ADDR_PHYS, (unsigned long)dst_addr, dst_w*dst_h*dst_bpp, 1, 0}; + dstImage = {dstAddr, dstAddr, dst_w, dst_h, dst_w*dst_bpp, AX_RGB, (color_format)dst_color_format}; + dstRect = {0, 0, dst_w, dst_h}; + dstClip = {0, 0, 0, dst_w, dst_h}; + + if (rotVal == 0 || rotVal == 180) + Scaling = {SCALING_BILINEAR, SCALING_PIXELS, 0, 0, src_w, src_h, dst_w, dst_h}; + else + Scaling = {SCALING_BILINEAR, SCALING_PIXELS, 0, 0, src_w, src_h, dst_h, dst_w}; + + switch (rotVal) { + case 0: + g2d_rotation = ORIGIN; + break; + case 90: + g2d_rotation = ROT_90; + break; + case 180: + g2d_rotation = ROT_180; + break; + case 270: + g2d_rotation = ROT_270; + break; + default: + LOGE("%s::invalid rotVal(%d) fail", __func__, rotVal); + return -1; + break; + } + + BlitParam = {BLIT_OP_SRC, NON_PREMULTIPLIED, 0xff, 0, g2d_rotation, &Scaling, 0, 0, &dstClip, 0, &srcImage, &dstImage, NULL, &srcRect, &dstRect, NULL, 0}; + + if (stretchFimgApi(&BlitParam) < 0) { + LOGE("%s::stretchFimgApi() fail", __func__); + return -1; + } + + var.xres = dst_w; + var.yres = dst_h; + + var.xres_virtual = var.xres; + var.yres_virtual = var.yres; + var.xoffset = 0; + var.yoffset = 0; + var.width = 0; + var.height = 0; + var.activate = FB_ACTIVATE_FORCE; + + window.x = dst_x; + window.y = dst_y; + + tvout_v4l2_s_baseaddr(fp_tvout_g, (void *)dst_addr); + put_vscreeninfo(fp_tvout_g, &var); + + if (ioctl(fp_tvout_g, S5PTVFB_WIN_POSITION, &window) < 0) { + LOGE("%s::S5PTVFB_WIN_POSITION ioctl failed.", __func__); + return -1; + } + } + + return 0; +#else + struct fb_var_screeninfo var; + struct s5ptvfb_user_window window; + + struct overlay_param ov_param; + + // set base address for grp layer0 of mixer + int fp_tvout_g; + +#ifdef DEBUG_MSG_ENABLE + LOGD("hdmi_gl_set_param:: \n \\ + layer=%d,\n \\ + srcColorFormat=%d,\n \\ + src_w=%d, src_h=%d,\n\\ + src_y_address=0x%x, src_c_address=0x%x,\n\\ + dst_x=%d, dst_y=%d, dst_w=%d, dst_h=%d ", + layer, + srcColorFormat, + src_w, src_h, + src_y_address, src_c_address, + dst_x, dst_y, dst_w, dst_h); +#endif + + if (layer == HDMI_LAYER_GRAPHIC_0) + fp_tvout_g = fp_tvout_g0; + else + fp_tvout_g = fp_tvout_g1; + + var.xres = src_w; + var.yres = src_h; + var.xres_virtual = var.xres; + var.yres_virtual = var.yres; + var.xoffset = 0; + var.yoffset = 0; + var.width = src_w; + var.height = src_h; + var.activate = FB_ACTIVATE_FORCE; + if (srcColorFormat == HAL_PIXEL_FORMAT_RGB_565) { + var.bits_per_pixel = 16; + var.transp.length = 0; + } + else { + var.bits_per_pixel = 32; + var.transp.length = 8; + } + + window.x = dst_x; + window.y = dst_y; + + tvout_v4l2_s_baseaddr(fp_tvout_g, (void *)src_y_address); + put_vscreeninfo(fp_tvout_g, &var); + if (ioctl(fp_tvout_g, S5PTVFB_WIN_POSITION, &window) < 0) { + LOGE("%s:: S5PTVFB_WIN_POSITION ioctl failed.", __func__); + return -1; + } + + return 0; +#endif +} +#endif + +int hdmi_cable_status() +{ +#if defined(BOARD_USE_V4L2) +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("%s", __func__); +#endif + + int cable_status = 0; + int fd = 0; + struct v4l2_control ctrl; + + fd = open(TVOUT_DEV_G0, O_RDWR); + if (fd <= 0) { + LOGE("%s: graphic layer 0 drv open failed", __func__); + return -1; + } + + ctrl.id = V4L2_CID_TV_HPD_STATUS; + + if (ioctl(fd, VIDIOC_S_CTRL, &ctrl) < 0) { + LOGE("Get HPD_STATUS fail"); + cable_status = -1; + } else { + cable_status = ctrl.value; + } + +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("HPD_STATUS = %d", cable_status); +#endif + + close(fd); + + return cable_status; +#else + int cable_status = 0; + int fp_hpd = 0; + + fp_hpd = open(HPD_DEV, O_RDWR); + if (fp_hpd <= 0) { + LOGE("hpd drv open failed\n"); + return -1; + } + + //Delay about 0.3s + usleep(500000); + if (ioctl(fp_hpd, HPD_GET_STATE, &cable_status) < 0) { + LOGE("hpd drv HPD_GET_STATE ioctl failed\n"); + cable_status = -1; + } + + close(fp_hpd); + + return cable_status; +#endif +} + +int hdmi_outputmode_2_v4l2_output_type(int output_mode) +{ + int v4l2_output_type = -1; + + switch (output_mode) { + case HDMI_OUTPUT_MODE_YCBCR: + v4l2_output_type = V4L2_OUTPUT_TYPE_DIGITAL; + break; + case HDMI_OUTPUT_MODE_RGB: + v4l2_output_type = V4L2_OUTPUT_TYPE_HDMI_RGB; + break; + case HDMI_OUTPUT_MODE_DVI: + v4l2_output_type = V4L2_OUTPUT_TYPE_DVI; + break; + case COMPOSITE_OUTPUT_MODE: + v4l2_output_type = V4L2_OUTPUT_TYPE_COMPOSITE; + break; + default: + LOGE("%s::unmathced HDMI_mode(%d)", __func__, output_mode); + v4l2_output_type = -1; + break; + } + + return v4l2_output_type; +} + +int hdmi_v4l2_output_type_2_outputmode(int v4l2_output_type) +{ + int outputMode = -1; + + switch (v4l2_output_type) { + case V4L2_OUTPUT_TYPE_DIGITAL: + outputMode = HDMI_OUTPUT_MODE_YCBCR; + break; + case V4L2_OUTPUT_TYPE_HDMI_RGB: + outputMode = HDMI_OUTPUT_MODE_RGB; + break; + case V4L2_OUTPUT_TYPE_DVI: + outputMode = HDMI_OUTPUT_MODE_DVI; + break; + case V4L2_OUTPUT_TYPE_COMPOSITE: + outputMode = COMPOSITE_OUTPUT_MODE; + break; + default: + LOGE("%s::unmathced v4l2_output_type(%d)", __func__, v4l2_output_type); + outputMode = -1; + break; + } + + return outputMode; +} + +int composite_std_2_v4l2_std_id(int std) +{ + int std_id = -1; + + switch (std) { + case COMPOSITE_STD_NTSC_M: + std_id = V4L2_STD_NTSC_M; + break; + case COMPOSITE_STD_NTSC_443: + std_id = V4L2_STD_NTSC_443; + break; + case COMPOSITE_STD_PAL_BDGHI: + std_id = V4L2_STD_PAL_BDGHI; + break; + case COMPOSITE_STD_PAL_M: + std_id = V4L2_STD_PAL_M; + break; + case COMPOSITE_STD_PAL_N: + std_id = V4L2_STD_PAL_N; + break; + case COMPOSITE_STD_PAL_Nc: + std_id = V4L2_STD_PAL_Nc; + break; + case COMPOSITE_STD_PAL_60: + std_id = V4L2_STD_PAL_60; + break; + default: + LOGE("%s::unmathced composite_std(%d)", __func__, std); + break; + } + + return std_id; +} + +int hdmi_check_output_mode(int v4l2_output_type) +{ + struct HDMIVideoParameter video; + struct HDMIAudioParameter audio; + int calbirate_v4l2_mode = v4l2_output_type; + + audio.formatCode = LPCM_FORMAT; + audio.outPacket = HDMI_ASP; + audio.channelNum = CH_2; + audio.sampleFreq = SF_44KHZ; + + switch (v4l2_output_type) { + case V4L2_OUTPUT_TYPE_DIGITAL : + video.mode = HDMI; + if (!EDIDHDMIModeSupport(&video)) { + calbirate_v4l2_mode = V4L2_OUTPUT_TYPE_DVI; + LOGI("Change mode into DVI\n"); + break; + } + + video.colorSpace = HDMI_CS_YCBCR444; + if (!EDIDColorSpaceSupport(&video)) { + calbirate_v4l2_mode = V4L2_OUTPUT_TYPE_HDMI_RGB; + LOGI("Change mode into HDMI_RGB\n"); + } + break; + + case V4L2_OUTPUT_TYPE_HDMI_RGB: + video.mode = HDMI; + if (!EDIDHDMIModeSupport(&video)) { + calbirate_v4l2_mode = V4L2_OUTPUT_TYPE_DVI; + LOGI("Change mode into DVI\n"); + break; + } + + video.colorSpace = HDMI_CS_RGB; + if (!EDIDColorSpaceSupport(&video)) { + calbirate_v4l2_mode = V4L2_OUTPUT_TYPE_DIGITAL; + LOGI("Change mode into HDMI_YCBCR\n"); + } + break; + + case V4L2_OUTPUT_TYPE_DVI: + video.mode = DVI; + if (!EDIDHDMIModeSupport(&video)) { + video.colorSpace = HDMI_CS_YCBCR444; + if (!EDIDColorSpaceSupport(&video)) { + calbirate_v4l2_mode = V4L2_OUTPUT_TYPE_HDMI_RGB; + LOGI("Change mode into HDMI_RGB\n"); + } else { + calbirate_v4l2_mode = V4L2_OUTPUT_TYPE_DIGITAL; + LOGI("Change mode into HDMI_YCBCR\n"); + } + break; + } + + break; + + default: + break; + } + return calbirate_v4l2_mode; +} + +#if defined(BOARD_USE_V4L2) +int hdmi_check_resolution(unsigned int preset_id) +{ + struct HDMIVideoParameter video; + struct HDMIAudioParameter audio; + + switch (preset_id) { + case V4L2_DV_480P60: + video.resolution = v720x480p_60Hz; + video.pixelAspectRatio = HDMI_PIXEL_RATIO_16_9; + video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT; + break; + case V4L2_DV_576P50: + video.resolution = v720x576p_50Hz; + video.pixelAspectRatio = HDMI_PIXEL_RATIO_16_9; + video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT; + break; + case V4L2_DV_720P60: + video.resolution = v1280x720p_60Hz; + video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT; + break; + case V4L2_DV_720P50: + video.resolution = v1280x720p_50Hz; + video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT; + break; + case V4L2_DV_1080P60: + video.resolution = v1920x1080p_60Hz; + video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT; + break; + case V4L2_DV_1080P50: + video.resolution = v1920x1080p_50Hz; + video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT; + break; + case V4L2_DV_1080I60: + video.resolution = v1920x1080i_60Hz; + video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT; + break; + case V4L2_DV_1080I50: + video.resolution = v1920x1080i_50Hz; + video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT; + break; + case V4L2_DV_480P59_94: + video.resolution = v720x480p_60Hz; + video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT; + break; + case V4L2_DV_720P59_94: + video.resolution = v1280x720p_60Hz; + video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT; + break; + case V4L2_DV_1080I59_94: + video.resolution = v1920x1080i_60Hz; + video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT; + break; + case V4L2_DV_1080P59_94: + video.resolution = v1920x1080p_60Hz; + video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT; + break; + case V4L2_DV_1080P30: + video.resolution = v1920x1080p_30Hz; + video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT; + break; + case V4L2_DV_720P60_SB_HALF: + video.resolution = v1280x720p_60Hz; + video.hdmi_3d_format = HDMI_3D_SSH_FORMAT; + break; + case V4L2_DV_720P59_94_SB_HALF: + video.resolution = v1280x720p_60Hz; + video.hdmi_3d_format = HDMI_3D_SSH_FORMAT; + break; + case V4L2_DV_720P50_TB: + video.resolution = v1280x720p_50Hz; + video.hdmi_3d_format = HDMI_3D_TB_FORMAT; + break; + case V4L2_DV_1080P24_TB: + video.resolution = v1920x1080p_24Hz; + video.hdmi_3d_format = HDMI_3D_TB_FORMAT; + break; + case V4L2_DV_1080P23_98_TB: + video.resolution = v1920x1080p_24Hz; + video.hdmi_3d_format = HDMI_3D_TB_FORMAT; + break; + default: + LOGE("%s::unmathced preset_id(%d)", __func__, preset_id); + return -1; + break; + } + + if (!EDIDVideoResolutionSupport(&video)) { +#ifdef DEBUG_MSG_ENABLE + LOGD("%s::EDIDVideoResolutionSupport(%d) fail (not suppoted preset_id) \n", __func__, preset_id); +#endif + return -1; + } + + return 0; +} + +int hdmi_resolution_2_preset_id(unsigned int resolution, int * w, int * h, unsigned int *preset_id) +{ + int ret = 0; + + switch (resolution) { + case 1080960: + *w = 1920; + *h = 1080; + *preset_id = V4L2_DV_1080P60; + break; + case 1080950: + *w = 1920; + *h = 1080; + *preset_id = V4L2_DV_1080P50; + break; + case 1080930: + *w = 1920; + *h = 1080; + *preset_id = V4L2_DV_1080P30; + break; + case 1080924: + *w = 1920; + *h = 1080; + *preset_id = V4L2_DV_1080P24_TB; + break; + case 1080160: + *w = 1920; + *h = 1080; + *preset_id = V4L2_DV_1080I60; + break; + case 1080150: + *w = 1920; + *h = 1080; + *preset_id = V4L2_DV_1080I50; + break; + case 720960: + *w = 1280; + *h = 720; + *preset_id = V4L2_DV_720P60; + break; + case 7209601: + *w = 1280; + *h = 720; + *preset_id = V4L2_DV_720P60_SB_HALF; + break; + case 720950: + *w = 1280; + *h = 720; + *preset_id = V4L2_DV_720P50; + break; + case 7209501: + *w = 1280; + *h = 720; + *preset_id = V4L2_DV_720P50_TB; + break; + case 5769501: + *w = 720; + *h = 576; + *preset_id = V4L2_DV_576P50; + break; + case 5769502: + *w = 720; + *h = 576; + *preset_id = V4L2_DV_576P50; + break; + case 4809601: + *w = 720; + *h = 480; + *preset_id = V4L2_DV_480P60; + break; + case 4809602: + *w = 720; + *h = 480; + *preset_id = V4L2_DV_480P60; + break; + default: + LOGE("%s::unmathced resolution(%d)", __func__, resolution); + ret = -1; + break; + } + + return ret; +} +#else +int hdmi_check_resolution(v4l2_std_id std_id) +{ + struct HDMIVideoParameter video; + struct HDMIAudioParameter audio; + + switch (std_id) { + case V4L2_STD_480P_60_16_9: + video.resolution = v720x480p_60Hz; + video.pixelAspectRatio = HDMI_PIXEL_RATIO_16_9; + video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT; + break; + case V4L2_STD_480P_60_4_3: + video.resolution = v640x480p_60Hz; + video.pixelAspectRatio = HDMI_PIXEL_RATIO_4_3; + video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT; + break; + case V4L2_STD_576P_50_16_9: + video.resolution = v720x576p_50Hz; + video.pixelAspectRatio = HDMI_PIXEL_RATIO_16_9; + video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT; + break; + case V4L2_STD_576P_50_4_3: + video.resolution = v720x576p_50Hz; + video.pixelAspectRatio = HDMI_PIXEL_RATIO_4_3; + video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT; + break; + case V4L2_STD_720P_60: + video.resolution = v1280x720p_60Hz; + video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT; + break; + case V4L2_STD_720P_50: + video.resolution = v1280x720p_50Hz; + video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT; + break; + case V4L2_STD_1080P_60: + video.resolution = v1920x1080p_60Hz; + video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT; + break; + case V4L2_STD_1080P_50: + video.resolution = v1920x1080p_50Hz; + video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT; + break; + case V4L2_STD_1080I_60: + video.resolution = v1920x1080i_60Hz; + video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT; + break; + case V4L2_STD_1080I_50: + video.resolution = v1920x1080i_50Hz; + video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT; + break; + case V4L2_STD_480P_59: + video.resolution = v720x480p_60Hz; + video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT; + break; + case V4L2_STD_720P_59: + video.resolution = v1280x720p_60Hz; + video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT; + break; + case V4L2_STD_1080I_59: + video.resolution = v1920x1080i_60Hz; + video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT; + break; + case V4L2_STD_1080P_59: + video.resolution = v1920x1080p_60Hz; + video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT; + break; + case V4L2_STD_1080P_30: + video.resolution = v1920x1080p_30Hz; + video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT; + break; + case V4L2_STD_TVOUT_720P_60_SBS_HALF: + video.resolution = v1280x720p_60Hz; + video.hdmi_3d_format = HDMI_3D_SSH_FORMAT; + break; + case V4L2_STD_TVOUT_720P_59_SBS_HALF: + video.resolution = v1280x720p_60Hz; + video.hdmi_3d_format = HDMI_3D_SSH_FORMAT; + break; + case V4L2_STD_TVOUT_720P_50_TB: + video.resolution = v1280x720p_50Hz; + video.hdmi_3d_format = HDMI_3D_TB_FORMAT; + break; + case V4L2_STD_TVOUT_1080P_24_TB: + video.resolution = v1920x1080p_24Hz; + video.hdmi_3d_format = HDMI_3D_TB_FORMAT; + break; + case V4L2_STD_TVOUT_1080P_23_TB: + video.resolution = v1920x1080p_24Hz; + video.hdmi_3d_format = HDMI_3D_TB_FORMAT; + break; + default: + LOGE("%s::unmathced std_id(%lld)", __func__, std_id); + return -1; + break; + } + + if (!EDIDVideoResolutionSupport(&video)) { +#ifdef DEBUG_MSG_ENABLE + LOGD("%s::EDIDVideoResolutionSupport(%llx) fail (not suppoted std_id) \n", __func__, std_id); +#endif + return -1; + } + + return 0; +} + +int hdmi_resolution_2_std_id(unsigned int resolution, int * w, int * h, v4l2_std_id * std_id) +{ + int ret = 0; + + switch (resolution) { + case 1080960: + *std_id = V4L2_STD_1080P_60; + *w = 1920; + *h = 1080; + break; + case 1080950: + *std_id = V4L2_STD_1080P_50; + *w = 1920; + *h = 1080; + break; + case 1080930: + *std_id = V4L2_STD_1080P_30; + *w = 1920; + *h = 1080; + break; + case 1080924: + *std_id = V4L2_STD_TVOUT_1080P_24_TB; + *w = 1920; + *h = 1080; + break; + case 1080160: + *std_id = V4L2_STD_1080I_60; + *w = 1920; + *h = 1080; + break; + case 1080150: + *std_id = V4L2_STD_1080I_50; + *w = 1920; + *h = 1080; + break; + case 720960: + *std_id = V4L2_STD_720P_60; + *w = 1280; + *h = 720; + break; + case 7209601: + *std_id = V4L2_STD_TVOUT_720P_60_SBS_HALF; + *w = 1280; + *h = 720; + break; + case 720950: + *std_id = V4L2_STD_720P_50; + *w = 1280; + *h = 720; + break; + case 7209501: + *std_id = V4L2_STD_TVOUT_720P_50_TB; + *w = 1280; + *h = 720; + break; + case 5769501: + *std_id = V4L2_STD_576P_50_16_9; + *w = 720; + *h = 576; + break; + case 5769502: + *std_id = V4L2_STD_576P_50_4_3; + *w = 720; + *h = 576; + break; + case 4809601: + *std_id = V4L2_STD_480P_60_16_9; + *w = 720; + *h = 480; + break; + case 4809602: + *std_id = V4L2_STD_480P_60_4_3; + *w = 720; + *h = 480; + break; + default: + LOGE("%s::unmathced resolution(%d)", __func__, resolution); + ret = -1; + break; + } + + return ret; +} +#endif + +int hdmi_enable_hdcp(unsigned int hdcp_en) +{ + if (ioctl(fp_tvout, VIDIOC_HDCP_ENABLE, hdcp_en) < 0) { + LOGD("%s::VIDIOC_HDCP_ENABLE(%d) fail \n", __func__, hdcp_en); + return -1; + } + + return 0; +} + +int hdmi_check_audio(void) +{ + struct HDMIAudioParameter audio; + enum state audio_state = ON; + int ret = 0; + + audio.formatCode = LPCM_FORMAT; + audio.outPacket = HDMI_ASP; + audio.channelNum = CH_2; + audio.sampleFreq = SF_44KHZ; + +#if defined(BOARD_USES_EDID) + if (!EDIDAudioModeSupport(&audio)) + audio_state = NOT_SUPPORT; + else + audio_state = ON; +#endif + if (audio_state == ON) { + if (ioctl(fp_tvout, VIDIOC_INIT_AUDIO, 1) < 0) { + LOGE("%s::VIDIOC_INIT_AUDIO(1) fail", __func__); + ret = -1; + } + } else { + if (ioctl(fp_tvout, VIDIOC_INIT_AUDIO, 0) < 0) { + LOGE("%s::VIDIOC_INIT_AUDIO(0) fail", __func__); + ret = -1; + } + } + + return ret; +} + +} diff --git a/exynos4/hal/libhdmi/SecHdmi/SecHdmiV4L2Utils.h b/exynos4/hal/libhdmi/SecHdmi/SecHdmiV4L2Utils.h new file mode 100644 index 0000000..a4aa69c --- /dev/null +++ b/exynos4/hal/libhdmi/SecHdmi/SecHdmiV4L2Utils.h @@ -0,0 +1,132 @@ +/* + * Copyright@ Samsung Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __HDMI_HAL_V4L2_UTILS_H__ +#define __HDMI_HAL_V4L2_UTILS_H__ + +//#define LOG_NDEBUG 0 +//#define LOG_TAG "libhdmi" +#if defined(BOARD_USE_V4L2) +#include "SecBuffer.h" +#endif +#include "fimd_api.h" + +#ifdef __cplusplus +extern "C" { +#endif + +namespace android { + +void display_menu(void); + +int tvout_open(const char *fp_name); +#if defined(BOARD_USE_V4L2) +int tvout_std_v4l2_init(int fd, unsigned int preset_id); +int tvout_std_v4l2_querycap(int fd, char *node); +int tvout_std_v4l2_enum_dv_presets(int fd); +int tvout_std_v4l2_s_dv_preset(int fd, struct v4l2_dv_preset *preset); +int tvout_std_v4l2_enum_output(int fd, struct v4l2_output *output); +int tvout_std_v4l2_s_output(int fd, int index); +int tvout_std_v4l2_g_output(int fd, int *index); +int tvout_std_v4l2_s_fmt(int fd, enum v4l2_buf_type type, enum v4l2_field field, int w, int h, int colorformat, int num_planes); +int tvout_std_v4l2_s_crop(int fd, enum v4l2_buf_type type, enum v4l2_field field, int x, int y, int w, int h); +int tvout_std_v4l2_s_ctrl(int fd, int id, int value); +int tvout_std_v4l2_reqbuf(int fd, enum v4l2_buf_type type, enum v4l2_memory memory, unsigned int num_bufs); +int tvout_std_v4l2_querybuf(int fd, enum v4l2_buf_type type, enum v4l2_memory memory, unsigned int buf_index, unsigned int num_planes, SecBuffer *secBuf); +int tvout_std_v4l2_qbuf(int fd, enum v4l2_buf_type type, enum v4l2_memory memory, int buf_index, int num_planes, SecBuffer *secBuf); +int tvout_std_v4l2_dqbuf(int fd, enum v4l2_buf_type type, enum v4l2_memory memory, int *buf_index, int num_planes); +int tvout_std_v4l2_streamon(int fd, enum v4l2_buf_type type); +int tvout_std_v4l2_streamoff(int fd, enum v4l2_buf_type type); +#else +int tvout_init(v4l2_std_id std_id); +int tvout_deinit(); +int tvout_v4l2_querycap(int fp); +int tvout_v4l2_g_std(int fp, v4l2_std_id *std_id); +int tvout_v4l2_s_std(int fp, v4l2_std_id std_id); +int tvout_v4l2_enum_std(int fp, struct v4l2_standard *std, v4l2_std_id std_id); +int tvout_v4l2_enum_output(int fp, struct v4l2_output *output); +int tvout_v4l2_s_output(int fp, int index); +int tvout_v4l2_g_output(int fp, int *index); +int tvout_v4l2_enum_fmt(int fp, struct v4l2_fmtdesc *desc); +int tvout_v4l2_g_fmt(int fp, int buf_type, void* ptr); +int tvout_v4l2_s_fmt(int fp, int buf_type, void *ptr); +int tvout_v4l2_g_fbuf(int fp, struct v4l2_framebuffer *frame); +int tvout_v4l2_s_fbuf(int fp, struct v4l2_framebuffer *frame); +int tvout_v4l2_s_baseaddr(int fp, void *base_addr); +int tvout_v4l2_g_crop(int fp, unsigned int type, struct v4l2_rect *rect); +int tvout_v4l2_s_crop(int fp, unsigned int type, struct v4l2_rect *rect); +int tvout_v4l2_start_overlay(int fp); +int tvout_v4l2_stop_overlay(int fp); +#endif + +int hdmi_init_layer(int layer); +int hdmi_deinit_layer(int layer); +#if defined(BOARD_USE_V4L2) +int hdmi_set_v_param(int fd, int layer, + int srcColorFormat, + int src_w, int src_h, + SecBuffer * dstBuffer, + int dst_x, int dst_y, int dst_w, int dst_h); +int hdmi_set_g_param(int fd, int layer, + int srcColorFormat, + int src_w, int src_h, + SecBuffer * dstBuffer, + int dst_x, int dst_y, int dst_w, int dst_h); +int hdmi_set_g_scaling(int layer, + int srcColorFormat, + int src_w, int src_h, + unsigned int src_address, SecBuffer * dstBuffer, + int dst_x, int dst_y, int dst_w, int dst_h, + int rotVal, unsigned int hwc_layer); +#else +int hdmi_set_v_param(int layer, + int src_w, int src_h, int colorFormat, + unsigned int src_y_address, unsigned int src_c_address, + int dst_w, int dst_h); +int hdmi_gl_set_param(int layer, + int srcColorFormat, + int src_w, int src_h, + unsigned int src_y_address, unsigned int src_c_address, + int dst_x, int dst_y, int dst_w, int dst_h, + int rotVal); +#endif +void hdmi_cal_rect(int src_w, int src_h, int dst_w, int dst_h, struct v4l2_rect *dst_rect); +#if defined(BOARD_USE_V4L2) +int hdmi_get_src_plane(int srcColorFormat, unsigned int *num_of_plane); +#endif +int hdmi_cable_status(); +int hdmi_outputmode_2_v4l2_output_type(int output_mode); +int hdmi_v4l2_output_type_2_outputmode(int v4l2_output_type); +int composite_std_2_v4l2_std_id(int std); + +int hdmi_check_output_mode(int v4l2_output_type); +#if defined(BOARD_USE_V4L2) +int hdmi_check_resolution(unsigned int preset_id); +int hdmi_resolution_2_preset_id(unsigned int resolution, int * w, int * h, unsigned int *preset_id); +#else +int hdmi_check_resolution(v4l2_std_id std_id); +int hdmi_resolution_2_std_id(unsigned int resolution, int *w, int *h, v4l2_std_id *std_id); +#endif +int hdmi_enable_hdcp(unsigned int hdcp_en); +int hdmi_check_audio(void); + +#ifdef __cplusplus +} +#endif + +} //namespace android + +#endif //__HDMI_HAL_V4L2_UTILS_H__ diff --git a/exynos4/hal/libhdmi/SecHdmi/fimd_api.c b/exynos4/hal/libhdmi/SecHdmi/fimd_api.c new file mode 100644 index 0000000..0e07ef3 --- /dev/null +++ b/exynos4/hal/libhdmi/SecHdmi/fimd_api.c @@ -0,0 +1,229 @@ +/* +* Copyright@ Samsung Electronics Co. LTD +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "fimd_api.h" + +int fb_open(int win) +{ + char node[20]; + int fp = -1; + + sprintf(node, "%s%d", PFX_NODE_FB, win); + + fp = open(node, O_RDWR); + if (fp < 0) + LOGE("%s: fb[%d] open failed", __func__, win); + + return fp; +} + +int fb_close(int fp) +{ + if (fp) + close(fp); + else + LOGE("%s: fb is not allocated %d", __func__, fp); + + return 0; +} + +int get_fscreeninfo(int fp, struct fb_fix_screeninfo *fix) +{ + int ret = -1; + + ret = ioctl(fp, FBIOGET_FSCREENINFO, fix); + if (ret) + LOGE("%s: FBIOGET_FSCREENINFO failed", __func__); + + return ret; +} + +int get_vscreeninfo(int fp, struct fb_var_screeninfo *var) +{ + int ret = -1; + + ret = ioctl(fp, FBIOGET_VSCREENINFO, var); + if (ret) + LOGE("%s:: FBIOGET_VSCREENINFO failed", __func__); + + return ret; +} + +int put_vscreeninfo(int fp, struct fb_var_screeninfo *var) +{ + int ret = -1; + + ret = ioctl(fp, FBIOPUT_VSCREENINFO, var); + if (ret) + LOGE("%s:: FBIOPUT_VSCREENINFO failed", __func__); + + return ret; +} + +int get_bytes_per_pixel(int bits_per_pixel) +{ + return (bits_per_pixel == 24 || bits_per_pixel == 25 || + bits_per_pixel == 28) ? 4 : bits_per_pixel / 8; +} + +char *fb_mmap(__u32 size, int fp) +{ + char *buffer; + + buffer = (char *)mmap(0, size, PROT_READ | PROT_WRITE, + MAP_SHARED, fp, 0); + if (!buffer) { + LOGE("%s:: mmap failed", __func__); + return NULL; + } + + return buffer; +} + +int fb_ioctl(int fp, __u32 cmd, void *arg) +{ + int ret = -1; + + ret = ioctl(fp, cmd, arg); + if (ret < 0) + LOGE("%s:: ioctl (%d) failed", __func__, cmd); + + return ret; +} + +int fb_on(int fp) +{ + int ret = -1; + + ret = ioctl(fp, FBIOBLANK, FB_BLANK_UNBLANK); + if (ret) + LOGE("%s:: FBIOBLANK failed", __func__); + + return ret; +} + +int fb_off(int fp) +{ + int ret = -1; + + ret = ioctl(fp, FBIOBLANK, FB_BLANK_POWERDOWN); + if (ret) + LOGE("%s:: FBIOBLANK failed", __func__); + + return ret; +} + +int fb_off_all() +{ + int fp, i; + + for (i = 0; i < TOTAL_FB_NUM; i++) { + fp = fb_open(i); + if (fp < 0) + return -1; + + if (ioctl(fp, FBIOBLANK, FB_BLANK_POWERDOWN) < 0) + LOGE("%s:: FBIOBLANK failed", __func__); + + fb_off(fp); + fb_close(fp); + } + + return 0; +} + +char *fb_init_display(int fp, int width, int height, int left_x, int top_y, + int bpp) +{ + struct fb_var_screeninfo var; + struct s5ptvfb_user_window window; + int fb_size; + char *fb = NULL; + + var.xres = width; + var.yres = height; + var.bits_per_pixel = bpp; + window.x = left_x; + window.y = top_y; + + var.xres_virtual = var.xres; + var.yres_virtual = var.yres; + var.xoffset = 0; + var.yoffset = 0; + var.width = 0; + var.height = 0; + var.transp.length = 0; + var.activate = FB_ACTIVATE_FORCE; + fb_size = var.xres_virtual * var.yres_virtual * bpp / 8; + + /* FBIOPUT_VSCREENINFO should be first */ + put_vscreeninfo(fp, &var); + fb_ioctl(fp, S5PTVFB_WIN_POSITION, &window); + + /* draw image */ + fb = fb_mmap(fb_size, fp); + memset(fb, 0x0, fb_size); + + return fb; +} + +int simple_draw(char *dest, const char *src, int img_width, + struct fb_var_screeninfo *var) +{ + int bytes_per_pixel = get_bytes_per_pixel(var->bits_per_pixel); + unsigned int y; + + for (y = 0; y < var->yres; y++) + memcpy(dest + y * var->xres * bytes_per_pixel, + src + y * img_width * bytes_per_pixel, + var->xres * bytes_per_pixel); + + return 0; +} + +int draw(char *dest, const char *src, int img_width, + struct fb_var_screeninfo *var) +{ + int bytes_per_pixel = get_bytes_per_pixel(var->bits_per_pixel); + unsigned int y; + + if (var->bits_per_pixel == 16) { + memcpy(dest, src, var->xres * var->yres * 2); + } else { + for (y = 0; y < var->yres; y++) + memcpy(dest + y * var->xres * bytes_per_pixel, + src + y * img_width * bytes_per_pixel, + var->xres * bytes_per_pixel); + } + + return 0; +} diff --git a/exynos4/hal/libhdmi/SecHdmi/fimd_api.h b/exynos4/hal/libhdmi/SecHdmi/fimd_api.h new file mode 100644 index 0000000..a8561a4 --- /dev/null +++ b/exynos4/hal/libhdmi/SecHdmi/fimd_api.h @@ -0,0 +1,51 @@ +/* + * Copyright@ Samsung Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __FIMD_API_H__ +#define __FIMD_API_H__ + +#include +#include "s5p_tvout.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define TOTAL_FB_NUM 5 + +int fb_open(int win); +int fb_close(int fp); +int fb_on(int fp); +int fb_off(int fp); +int fb_off_all(void); +char *fb_init_display(int fp, int width, int height,\ + int left_x, int top_y, int bpp); +int fb_ioctl(int fp, __u32 cmd, void *arg); +char *fb_mmap(__u32 size, int fp); +int simple_draw(char *dest, const char *src,\ + int img_width, struct fb_var_screeninfo *var); +int draw(char *dest, const char *src,\ + int img_width, struct fb_var_screeninfo *var); +int get_fscreeninfo(int fp, struct fb_fix_screeninfo *fix); +int get_vscreeninfo(int fp, struct fb_var_screeninfo *var); +int put_vscreeninfo(int fp, struct fb_var_screeninfo *var); +int get_bytes_per_pixel(int bits_per_pixel); + +#ifdef __cplusplus +} +#endif + +#endif /* __FIMD_API_H__ */ diff --git a/exynos4/hal/libhdmi/libhdmiservice/Android.mk b/exynos4/hal/libhdmi/libhdmiservice/Android.mk new file mode 100644 index 0000000..ebfa9d5 --- /dev/null +++ b/exynos4/hal/libhdmi/libhdmiservice/Android.mk @@ -0,0 +1,126 @@ +# Copyright (C) 2008 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +ifeq ($(filter-out exynos4,$(TARGET_BOARD_PLATFORM)),) +ifeq ($(BOARD_USES_HDMI),true) + +LOCAL_PATH:= $(call my-dir) + +# +# libTVOut +# + +include $(CLEAR_VARS) +LOCAL_MODULE_TAGS := optional +LOCAL_PRELINK_MODULE := false + +LOCAL_SRC_FILES := \ + SecTVOutService.cpp \ + ISecTVOut.cpp \ + MessageQueue.cpp + +LOCAL_C_INCLUDES := \ + +LOCAL_SHARED_LIBRARIES := \ + libbinder \ + libutils \ + libcutils + +LOCAL_C_INCLUDES += $(TARGET_HAL_PATH)/include +LOCAL_C_INCLUDES += $(TARGET_HAL_PATH)/libhdmi +LOCAL_C_INCLUDES += $(TARGET_HAL_PATH)/libfimc +LOCAL_SHARED_LIBRARIES += libhdmi libfimc + +ifeq ($(BOARD_USES_HDMI_SUBTITLES),true) + LOCAL_CFLAGS += -DBOARD_USES_HDMI_SUBTITLES +endif + +ifeq ($(TARGET_SOC),exynos4210) + LOCAL_CFLAGS += -DSAMSUNG_EXYNOS4210 +endif + +ifeq ($(TARGET_SOC),exynos4x12) + LOCAL_CFLAGS += -DSAMSUNG_EXYNOS4x12 +endif + +LOCAL_CFLAGS += -DBOARD_USES_HDMI + +ifeq ($(BOARD_USE_V4L2),true) + LOCAL_CFLAGS += -DBOARD_USE_V4L2 +endif + +ifeq ($(BOARD_USE_V4L2_ION),true) + LOCAL_CFLAGS += -DBOARD_USE_V4L2_ION +endif + +LOCAL_MODULE := libTVOut + +include $(BUILD_SHARED_LIBRARY) + +# +# libhdmiclient +# + +include $(CLEAR_VARS) + +LOCAL_MODULE_TAGS := optional +LOCAL_PRELINK_MODULE := false + +LOCAL_SRC_FILES:= \ + SecHdmiClient.cpp + +LOCAL_C_INCLUDES += \ + $(JNI_H_INCLUDE) + +LOCAL_SHARED_LIBRARIES := \ + libbinder \ + libutils \ + libTVOut + +ifeq ($(TARGET_SIMULATOR),true) +ifeq ($(TARGET_OS),linux) +ifeq ($(TARGET_ARCH),x86) +LOCAL_LDLIBS += -lpthread -ldl -lrt +endif +endif +endif + +ifeq ($(WITH_MALLOC_LEAK_CHECK),true) + LOCAL_CFLAGS += -DMALLOC_LEAK_CHECK +endif + +ifeq ($(TARGET_SOC),exynos4210) + LOCAL_CFLAGS += -DSAMSUNG_EXYNOS4210 +endif + +ifeq ($(TARGET_SOC),exynos4x12) + LOCAL_CFLAGS += -DSAMSUNG_EXYNOS4x12 +endif + +LOCAL_CFLAGS += -DBOARD_USES_HDMI + +ifeq ($(BOARD_USE_V4L2),true) + LOCAL_CFLAGS += -DBOARD_USE_V4L2 +endif + +ifeq ($(BOARD_USE_V4L2_ION),true) + LOCAL_CFLAGS += -DBOARD_USE_V4L2_ION +endif + +LOCAL_MODULE:= libhdmiclient + +include $(BUILD_SHARED_LIBRARY) + +endif +endif diff --git a/exynos4/hal/libhdmi/libhdmiservice/Barrier.h b/exynos4/hal/libhdmi/libhdmiservice/Barrier.h new file mode 100644 index 0000000..6f8507e --- /dev/null +++ b/exynos4/hal/libhdmi/libhdmiservice/Barrier.h @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_BARRIER_H +#define ANDROID_BARRIER_H + +#include +#include +#include + +namespace android { + +class Barrier +{ +public: + inline Barrier() : state(CLOSED) { } + inline ~Barrier() { } + void open() { + Mutex::Autolock _l(lock); + state = OPENED; + cv.broadcast(); + } + void close() { + Mutex::Autolock _l(lock); + state = CLOSED; + } + void wait() const { + Mutex::Autolock _l(lock); + while (state == CLOSED) { + cv.wait(lock); + } + } +private: + enum { OPENED, CLOSED }; + mutable Mutex lock; + mutable Condition cv; + volatile int state; +}; + +}; // namespace android + +#endif // ANDROID_BARRIER_H diff --git a/exynos4/hal/libhdmi/libhdmiservice/ISecTVOut.cpp b/exynos4/hal/libhdmi/libhdmiservice/ISecTVOut.cpp new file mode 100644 index 0000000..a013bf1 --- /dev/null +++ b/exynos4/hal/libhdmi/libhdmiservice/ISecTVOut.cpp @@ -0,0 +1,111 @@ +/* +** +** Copyright 2008, The Android Open Source Project +** Copyright 2010, Samsung Electronics Co. LTD +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + +/* +** +** @author Taikyung, Yu(taikyung.yu@samsung.com) +** @date 2011-07-06 +*/ + +#include +#include +#include +#include +#include "ISecTVOut.h" + +namespace android { + + enum { + SET_HDMI_STATUS = IBinder::FIRST_CALL_TRANSACTION, + SET_HDMI_MODE, + SET_HDMI_RESOLUTION, + SET_HDMI_HDCP, + SET_HDMI_ROTATE, + SET_HDMI_HWCLAYER, + BLIT_2_HDMI + }; + + void BpSecTVOut::setHdmiCableStatus(uint32_t status) + { + Parcel data, reply; + data.writeInt32(status); + remote()->transact(SET_HDMI_STATUS, data, &reply); + } + + void BpSecTVOut::setHdmiMode(uint32_t mode) + { + Parcel data, reply; + data.writeInt32(mode); + remote()->transact(SET_HDMI_MODE, data, &reply); + } + + void BpSecTVOut::setHdmiResolution(uint32_t resolution) + { + Parcel data, reply; + data.writeInt32(resolution); + remote()->transact(SET_HDMI_RESOLUTION, data, &reply); + } + + void BpSecTVOut::setHdmiHdcp(uint32_t resolution) + { + Parcel data, reply; + data.writeInt32(resolution); + remote()->transact(SET_HDMI_HDCP, data, &reply); + } + + void BpSecTVOut::setHdmiRotate(uint32_t rotVal, uint32_t hwcLayer) + { + Parcel data, reply; + data.writeInt32(rotVal); + data.writeInt32(hwcLayer); + remote()->transact(SET_HDMI_ROTATE, data, &reply); + } + + void BpSecTVOut::setHdmiHwcLayer(uint32_t hwcLayer) + { + Parcel data, reply; + data.writeInt32(hwcLayer); + remote()->transact(SET_HDMI_HWCLAYER, data, &reply); + } + + void BpSecTVOut::blit2Hdmi(uint32_t w, uint32_t h, + uint32_t colorFormat, + uint32_t physYAddr, + uint32_t physCbAddr, + uint32_t physCrAddr, + uint32_t dstX, + uint32_t dstY, + uint32_t hdmiLayer, + uint32_t num_of_hwc_layer) + { + Parcel data, reply; + data.writeInt32(w); + data.writeInt32(h); + data.writeInt32(colorFormat); + data.writeInt32(physYAddr); + data.writeInt32(physCbAddr); + data.writeInt32(physCrAddr); + data.writeInt32(dstX); + data.writeInt32(dstY); + data.writeInt32(hdmiLayer); + data.writeInt32(num_of_hwc_layer); + remote()->transact(BLIT_2_HDMI, data, &reply); + } + + IMPLEMENT_META_INTERFACE(SecTVOut, "android.os.ISecTVOut"); +}; diff --git a/exynos4/hal/libhdmi/libhdmiservice/ISecTVOut.h b/exynos4/hal/libhdmi/libhdmiservice/ISecTVOut.h new file mode 100644 index 0000000..5506b57 --- /dev/null +++ b/exynos4/hal/libhdmi/libhdmiservice/ISecTVOut.h @@ -0,0 +1,74 @@ +/* +** +** Copyright 2008, The Android Open Source Project +** Copyright 2010, Samsung Electronics Co. LTD +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + +/* +** +** @author Taikyung, Yu(taikyung.yu@samsung.com) +** @date 2011-07-06 +*/ + +#ifndef ISECTVOUT_H +#define ISECTVOUT_H +#include +#include +#include + +namespace android { + class ISecTVOut: public IInterface + { + public: + DECLARE_META_INTERFACE(SecTVOut); + virtual void setHdmiCableStatus(uint32_t status) = 0; + virtual void setHdmiMode(uint32_t mode) = 0; + virtual void setHdmiResolution(uint32_t resolution) = 0; + virtual void setHdmiHdcp(uint32_t enHdcp) = 0; + virtual void setHdmiRotate(uint32_t rotVal, uint32_t hwcLayer) = 0; + virtual void setHdmiHwcLayer(uint32_t hwcLayer) = 0; + virtual void blit2Hdmi(uint32_t w, uint32_t h, + uint32_t colorFormat, + uint32_t physYAddr, + uint32_t physCbAddr, + uint32_t physCrAddr, + uint32_t dstX, + uint32_t dstY, + uint32_t hdmiLayer, + uint32_t num_of_hwc_layer) = 0; + }; + //-------------------------------------------------------------- + class BpSecTVOut: public BpInterface + { + public: + BpSecTVOut(const sp& impl): BpInterface(impl){} + virtual void setHdmiCableStatus(uint32_t status); + virtual void setHdmiMode(uint32_t mode); + virtual void setHdmiResolution(uint32_t resolution); + virtual void setHdmiHdcp(uint32_t enHdcp); + virtual void setHdmiRotate(uint32_t rotVal, uint32_t hwcLayer); + virtual void setHdmiHwcLayer(uint32_t hwcLayer); + virtual void blit2Hdmi(uint32_t w, uint32_t h, + uint32_t colorFormat, + uint32_t physYAddr, + uint32_t physCbAddr, + uint32_t physCrAddr, + uint32_t dstX, + uint32_t dstY, + uint32_t hdmiLayer, + uint32_t num_of_hwc_layer); + }; +}; +#endif diff --git a/exynos4/hal/libhdmi/libhdmiservice/MessageQueue.cpp b/exynos4/hal/libhdmi/libhdmiservice/MessageQueue.cpp new file mode 100644 index 0000000..aebe1b8 --- /dev/null +++ b/exynos4/hal/libhdmi/libhdmiservice/MessageQueue.cpp @@ -0,0 +1,197 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +#include +#include +#include +#include + +#include "MessageQueue.h" + +namespace android { + +// --------------------------------------------------------------------------- + +void MessageList::insert(const sp& node) +{ + LIST::iterator cur(mList.begin()); + LIST::iterator end(mList.end()); + while (cur != end) { + if (*node < **cur) { + mList.insert(cur, node); + return; + } + ++cur; + } + mList.insert(++end, node); +} + +void MessageList::remove(MessageList::LIST::iterator pos) +{ + mList.erase(pos); +} + +// --------------------------------------------------------------------------- + +MessageQueue::MessageQueue() + : mInvalidate(false) +{ + mInvalidateMessage = new MessageBase(INVALIDATE); +} + +MessageQueue::~MessageQueue() +{ +} + +sp MessageQueue::waitMessage(nsecs_t timeout) +{ + sp result; + + bool again; + do { + const nsecs_t timeoutTime = systemTime() + timeout; + while (true) { + Mutex::Autolock _l(mLock); + nsecs_t now = systemTime(); + nsecs_t nextEventTime = -1; + + LIST::iterator cur(mMessages.begin()); + if (cur != mMessages.end()) { + result = *cur; + } + + if (result != 0) { + if (result->when <= now) { + // there is a message to deliver + mMessages.remove(cur); + break; + } + nextEventTime = result->when; + result = 0; + } + + // see if we have an invalidate message + if (mInvalidate) { + mInvalidate = false; + mInvalidateMessage->when = now; + result = mInvalidateMessage; + break; + } + + if (timeout >= 0) { + if (timeoutTime < now) { + // we timed-out, return a NULL message + result = 0; + break; + } + if (nextEventTime > 0) { + if (nextEventTime > timeoutTime) { + nextEventTime = timeoutTime; + } + } else { + nextEventTime = timeoutTime; + } + } + + if (nextEventTime >= 0) { + //LOGD("nextEventTime = %lld ms", nextEventTime); + if (nextEventTime > 0) { + // we're about to wait, flush the binder command buffer + IPCThreadState::self()->flushCommands(); + const nsecs_t reltime = nextEventTime - systemTime(); + if (reltime > 0) { + mCondition.waitRelative(mLock, reltime); + } + } + } else { + //LOGD("going to wait"); + // we're about to wait, flush the binder command buffer + IPCThreadState::self()->flushCommands(); + mCondition.wait(mLock); + } + } + // here we're not holding the lock anymore + + if (result == 0) + break; + + again = result->handler(); + if (again) { + // the message has been processed. release our reference to it + // without holding the lock. + result->notify(); + result = 0; + } + + } while (again); + + return result; +} + +status_t MessageQueue::postMessage( + const sp& message, nsecs_t relTime, uint32_t flags) +{ + return queueMessage(message, relTime, flags); +} + +status_t MessageQueue::invalidate() { + Mutex::Autolock _l(mLock); + mInvalidate = true; + mCondition.signal(); + return NO_ERROR; +} + +status_t MessageQueue::queueMessage( + const sp& message, nsecs_t relTime, uint32_t flags) +{ + Mutex::Autolock _l(mLock); + message->when = systemTime() + relTime; + mMessages.insert(message); + + //LOGD("MessageQueue::queueMessage time = %lld ms", message->when); + //dumpLocked(message); + + mCondition.signal(); + return NO_ERROR; +} + +void MessageQueue::dump(const sp& message) +{ + Mutex::Autolock _l(mLock); + dumpLocked(message); +} + +void MessageQueue::dumpLocked(const sp& message) +{ + LIST::const_iterator cur(mMessages.begin()); + LIST::const_iterator end(mMessages.end()); + int c = 0; + while (cur != end) { + const char tick = (*cur == message) ? '>' : ' '; + LOGD("%c %d: msg{.what=%08x, when=%lld}", + tick, c, (*cur)->what, (*cur)->when); + ++cur; + c++; + } +} + +// --------------------------------------------------------------------------- + +}; // namespace android diff --git a/exynos4/hal/libhdmi/libhdmiservice/MessageQueue.h b/exynos4/hal/libhdmi/libhdmiservice/MessageQueue.h new file mode 100644 index 0000000..890f809 --- /dev/null +++ b/exynos4/hal/libhdmi/libhdmiservice/MessageQueue.h @@ -0,0 +1,126 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_MESSAGE_QUEUE_H +#define ANDROID_MESSAGE_QUEUE_H + +#include +#include +#include + +#include +#include +#include + +#include "Barrier.h" + +namespace android { + +// --------------------------------------------------------------------------- + +class MessageBase; + +class MessageList +{ + List< sp > mList; + typedef List< sp > LIST; +public: + inline LIST::iterator begin() { return mList.begin(); } + inline LIST::const_iterator begin() const { return mList.begin(); } + inline LIST::iterator end() { return mList.end(); } + inline LIST::const_iterator end() const { return mList.end(); } + inline bool isEmpty() const { return mList.empty(); } + void insert(const sp& node); + void remove(LIST::iterator pos); +}; + +// ============================================================================ + +class MessageBase : + public LightRefBase +{ +public: + nsecs_t when; + uint32_t what; + int32_t arg0; + + MessageBase() : when(0), what(0), arg0(0) { } + MessageBase(uint32_t what, int32_t arg0=0) + : when(0), what(what), arg0(arg0) { } + + // return true if message has a handler + virtual bool handler() { return false; } + + // waits for the handler to be processed + void wait() const { barrier.wait(); } + + // releases all waiters. this is done automatically if + // handler returns true + void notify() const { barrier.open(); } + +protected: + virtual ~MessageBase() { } + +private: + mutable Barrier barrier; + friend class LightRefBase; +}; + +inline bool operator < (const MessageBase& lhs, const MessageBase& rhs) { + return lhs.when < rhs.when; +} + +// --------------------------------------------------------------------------- + +class MessageQueue +{ + typedef List< sp > LIST; +public: + + MessageQueue(); + ~MessageQueue(); + + // pre-defined messages + enum { + INVALIDATE = '_upd' + }; + + sp waitMessage(nsecs_t timeout = -1); + + status_t postMessage(const sp& message, + nsecs_t reltime=0, uint32_t flags = 0); + + status_t invalidate(); + + void dump(const sp& message); + +private: + status_t queueMessage(const sp& message, + nsecs_t reltime, uint32_t flags); + void dumpLocked(const sp& message); + + Mutex mLock; + Condition mCondition; + MessageList mMessages; + bool mInvalidate; + sp mInvalidateMessage; +}; + +// --------------------------------------------------------------------------- + +}; // namespace android + +#endif /* ANDROID_MESSAGE_QUEUE_H */ diff --git a/exynos4/hal/libhdmi/libhdmiservice/SecHdmiClient.cpp b/exynos4/hal/libhdmi/libhdmiservice/SecHdmiClient.cpp new file mode 100644 index 0000000..c5cca78 --- /dev/null +++ b/exynos4/hal/libhdmi/libhdmiservice/SecHdmiClient.cpp @@ -0,0 +1,148 @@ +/* +** +** Copyright 2008, The Android Open Source Project +** Copyright 2010, Samsung Electronics Co. LTD +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + +/* +** +** @author Taikyung, Yu(taikyung.yu@samsung.com) +** @date 2011-07-06 +*/ + +#define LOG_TAG "libhdmiclient" + +#include "SecHdmiClient.h" + +namespace android { + +static sp g_SecTVOutService = 0; + +SecHdmiClient::SecHdmiClient() +{ + g_SecTVOutService = m_getSecTVOutService(); + mEnable = 0; +} + +SecHdmiClient::~SecHdmiClient() +{ +} + +SecHdmiClient * SecHdmiClient::getInstance(void) +{ + static SecHdmiClient singleton; + return &singleton; +} + +void SecHdmiClient::setHdmiCableStatus(int status) +{ + //LOGD("%s HDMI status: %d\n", __func__, status); + + if (g_SecTVOutService != 0) + g_SecTVOutService->setHdmiCableStatus(status); +} + +void SecHdmiClient::setHdmiMode(int mode) +{ + //LOGD("%s HDMI Mode: %d\n", __func__, mode); + + if (g_SecTVOutService != 0) + g_SecTVOutService->setHdmiMode(mode); +} + +void SecHdmiClient::setHdmiResolution(int resolution) +{ + //LOGD("%s HDMI Resolution: %d\n", __func__, resolution); + + if (g_SecTVOutService != 0) + g_SecTVOutService->setHdmiResolution(resolution); +} + +void SecHdmiClient::setHdmiHdcp(int enHdcp) +{ + //LOGD("%s HDMI HDCP: %d\n", __func__, enHdcp); + + if (g_SecTVOutService != 0) + g_SecTVOutService->setHdmiHdcp(enHdcp); +} + +void SecHdmiClient::setHdmiRotate(int rotVal, uint32_t hwcLayer) +{ + //LOGD("%s HDMI ROTATE: %d\n", __func__, rotVal); + + if (g_SecTVOutService != 0) + g_SecTVOutService->setHdmiRotate(rotVal, hwcLayer); +} + +void SecHdmiClient::setHdmiHwcLayer(uint32_t hwcLayer) +{ + //LOGD("%s HDMI HWCLAYER: %d\n", __func__, hwcLayer); + + if (g_SecTVOutService != 0) + g_SecTVOutService->setHdmiHwcLayer(hwcLayer); +} + +void SecHdmiClient::setHdmiEnable(uint32_t enable) +{ + //LOGD("%s HDMI ENABLE: %d\n", __func__, enable); + + if (g_SecTVOutService != 0) + mEnable = enable; +} + +void SecHdmiClient::blit2Hdmi(uint32_t w, uint32_t h, + uint32_t colorFormat, + uint32_t physYAddr, + uint32_t physCbAddr, + uint32_t physCrAddr, + uint32_t dstX, + uint32_t dstY, + uint32_t hdmiLayer, + uint32_t num_of_hwc_layer) +{ + if (g_SecTVOutService != 0 && mEnable == 1) + g_SecTVOutService->blit2Hdmi(w, h, colorFormat, physYAddr, physCbAddr, physCrAddr, dstX, dstY, hdmiLayer, num_of_hwc_layer); +} + +sp SecHdmiClient::m_getSecTVOutService(void) +{ + int ret = 0; + + if (g_SecTVOutService == 0) { + sp binder; + sp sc; + sp sm = defaultServiceManager(); + int getSvcTimes = 0; + for(getSvcTimes = 0; getSvcTimes < GETSERVICETIMEOUT; getSvcTimes++) { + binder = sm->getService(String16("SecTVOutService")); + if (binder == 0) { + LOGW("SecTVOutService not published, waiting..."); + usleep(500000); // 0.5 s + } else { + break; + } + } + // grab the lock again for updating g_surfaceFlinger + if (getSvcTimes < GETSERVICETIMEOUT) { + sc = interface_cast(binder); + g_SecTVOutService = sc; + } else { + LOGW("Failed to get SecTVOutService... SecHdmiClient will get it later.."); + } + } + return g_SecTVOutService; +} + +} diff --git a/exynos4/hal/libhdmi/libhdmiservice/SecHdmiClient.h b/exynos4/hal/libhdmi/libhdmiservice/SecHdmiClient.h new file mode 100644 index 0000000..ebee763 --- /dev/null +++ b/exynos4/hal/libhdmi/libhdmiservice/SecHdmiClient.h @@ -0,0 +1,86 @@ +/* +** +** Copyright 2008, The Android Open Source Project +** Copyright 2010, Samsung Electronics Co. LTD +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + +/* +** +** @author Taikyung, Yu(taikyung.yu@samsung.com) +** @date 2011-07-06 +*/ + +#ifndef __SEC_HDMI_CLIENT_H__ +#define __SEC_HDMI_CLIENT_H__ + +#include "utils/Log.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "ISecTVOut.h" + +#define GETSERVICETIMEOUT (5) + +namespace android { + +class SecHdmiClient +{ +public: + enum HDMI_MODE + { + HDMI_MODE_NONE = 0, + HDMI_MODE_UI, + HDMI_MODE_VIDEO, + }; + +private: + SecHdmiClient(); + virtual ~SecHdmiClient(); + uint32_t mEnable; + +public: + static SecHdmiClient * getInstance(void); + void setHdmiCableStatus(int status); + void setHdmiMode(int mode); + void setHdmiResolution(int resolution); + void setHdmiHdcp(int enHdcp); + void setHdmiRotate(int rotVal, uint32_t hwcLayer); + void setHdmiHwcLayer(uint32_t hwcLayer); + void setHdmiEnable(uint32_t enable); + virtual void blit2Hdmi(uint32_t w, uint32_t h, + uint32_t colorFormat, + uint32_t physYAddr, + uint32_t physCbAddr, + uint32_t physCrAddr, + uint32_t dstX, + uint32_t dstY, + uint32_t hdmiLayer, + uint32_t num_of_hwc_layer); + +private: + sp m_getSecTVOutService(void); + +}; + +}; + +#endif diff --git a/exynos4/hal/libhdmi/libhdmiservice/SecTVOutService.cpp b/exynos4/hal/libhdmi/libhdmiservice/SecTVOutService.cpp new file mode 100644 index 0000000..de98810 --- /dev/null +++ b/exynos4/hal/libhdmi/libhdmiservice/SecTVOutService.cpp @@ -0,0 +1,387 @@ +/* +** +** Copyright 2008, The Android Open Source Project +** Copyright 2010, Samsung Electronics Co. LTD +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + +/* +** +** @author Taikyung, Yu(taikyung.yu@samsung.com) +** @date 2011-07-06 +*/ + +#define LOG_TAG "SecTVOutService" + +#include +#include +#include +#include +#include +#include "SecTVOutService.h" +#include + +namespace android { +#define DEFAULT_LCD_WIDTH 800 +#define DEFAULT_LCD_HEIGHT 480 + +#define DIRECT_VIDEO_RENDERING (1) +#define DIRECT_UI_RENDERING (0) + + enum { + SET_HDMI_STATUS = IBinder::FIRST_CALL_TRANSACTION, + SET_HDMI_MODE, + SET_HDMI_RESOLUTION, + SET_HDMI_HDCP, + SET_HDMI_ROTATE, + SET_HDMI_HWCLAYER, + BLIT_2_HDMI + }; + + int SecTVOutService::HdmiFlushThread() + { + while (!mExitHdmiFlushThread) { + nsecs_t timeout = -1; + sp msg = mHdmiEventQueue.waitMessage(timeout); + } + + return 0; + } + + int SecTVOutService::instantiate() + { + LOGD("SecTVOutService instantiate"); + int r = defaultServiceManager()->addService(String16( "SecTVOutService"), new SecTVOutService ()); + LOGD("SecTVOutService r=%d", r); + + return r; + } + + SecTVOutService::SecTVOutService () { + LOGV("SecTVOutService created"); + mHdmiCableInserted = false; +#ifdef SUPPORT_G2D_UI_MODE + mUILayerMode = SecHdmi::HDMI_LAYER_GRAPHIC_1; +#else + mUILayerMode = SecHdmi::HDMI_LAYER_VIDEO; +#endif + mHwcLayer = 0; + mExitHdmiFlushThread = false; + + setLCDsize(); + if (mSecHdmi.create(mLCD_width, mLCD_height) == false) + LOGE("%s::mSecHdmi.create() fail", __func__); + else + setHdmiStatus(1); + + mHdmiFlushThread = new HDMIFlushThread(this); + } + + void SecTVOutService::setLCDsize(void) { + char const * const device_template[] = { + "/dev/graphics/fb%u", + "/dev/fb%u", + 0 }; + + int fd = -1; + int i = 0; + char name[64]; + + while ((fd==-1) && device_template[i]) { + snprintf(name, 64, device_template[i], 0); + fd = open(name, O_RDWR, 0); + i++; + } + if (fd > 0) { + struct fb_var_screeninfo info; + if (ioctl(fd, FBIOGET_VSCREENINFO, &info) != -1) { + mLCD_width = info.xres; + mLCD_height = info.yres; + } else { + mLCD_width = DEFAULT_LCD_WIDTH; + mLCD_height = DEFAULT_LCD_HEIGHT; + } + close(fd); + } + return; + } + + SecTVOutService::~SecTVOutService () { + LOGV ("SecTVOutService destroyed"); + + if (mHdmiFlushThread != NULL) { + mHdmiFlushThread->requestExit(); + mExitHdmiFlushThread = true; + mHdmiFlushThread->requestExitAndWait(); + mHdmiFlushThread.clear(); + } + } + + status_t SecTVOutService::onTransact(uint32_t code, const Parcel & data, Parcel * reply, uint32_t flags) + { + switch (code) { + case SET_HDMI_STATUS: { + int status = data.readInt32(); + setHdmiStatus(status); + } break; + + case SET_HDMI_MODE: { + int mode = data.readInt32(); + setHdmiMode(mode); + } break; + + case SET_HDMI_RESOLUTION: { + int resolution = data.readInt32(); + setHdmiResolution(resolution); + } break; + + case SET_HDMI_HDCP: { + int enHdcp = data.readInt32(); + setHdmiHdcp(enHdcp); + } break; + + case SET_HDMI_ROTATE: { + int rotVal = data.readInt32(); + int hwcLayer = data.readInt32(); + setHdmiRotate(rotVal, hwcLayer); + } break; + + case SET_HDMI_HWCLAYER: { + int hwcLayer = data.readInt32(); + setHdmiHwcLayer((uint32_t)hwcLayer); + } break; + + case BLIT_2_HDMI: { + uint32_t w = data.readInt32(); + uint32_t h = data.readInt32(); + uint32_t colorFormat = data.readInt32(); + uint32_t physYAddr = data.readInt32(); + uint32_t physCbAddr = data.readInt32(); + uint32_t physCrAddr = data.readInt32(); + uint32_t dstX = data.readInt32(); + uint32_t dstY = data.readInt32(); + uint32_t hdmiLayer = data.readInt32(); + uint32_t num_of_hwc_layer = data.readInt32(); + + blit2Hdmi(w, h, colorFormat, physYAddr, physCbAddr, physCrAddr, dstX, dstY, hdmiLayer, num_of_hwc_layer); + } break; + + default : + LOGE ( "onTransact::default"); + return BBinder::onTransact (code, data, reply, flags); + } + + return NO_ERROR; + } + + void SecTVOutService::setHdmiStatus(uint32_t status) + { + + LOGD("%s HDMI cable status = %d", __func__, status); + { + Mutex::Autolock _l(mLock); + + bool hdmiCableInserted = (bool)status; + + if (mHdmiCableInserted == hdmiCableInserted) + return; + + if (hdmiCableInserted == true) { + if (mSecHdmi.connect() == false) { + LOGE("%s::mSecHdmi.connect() fail", __func__); + hdmiCableInserted = false; + } + } else { + if (mSecHdmi.disconnect() == false) + LOGE("%s::mSecHdmi.disconnect() fail", __func__); + } + + mHdmiCableInserted = hdmiCableInserted; + } + + if (hdmiCableInserted() == true) + this->blit2Hdmi(mLCD_width, mLCD_height, HAL_PIXEL_FORMAT_BGRA_8888, 0, 0, 0, 0, 0, HDMI_MODE_UI, 0); + } + + void SecTVOutService::setHdmiMode(uint32_t mode) + { + LOGD("%s TV mode = %d", __func__, mode); + Mutex::Autolock _l(mLock); + + if ((hdmiCableInserted() == true) && (mSecHdmi.setHdmiOutputMode(mode)) == false) { + LOGE("%s::mSecHdmi.setHdmiOutputMode() fail", __func__); + return; + } + } + + void SecTVOutService::setHdmiResolution(uint32_t resolution) + { + //LOGD("%s TV resolution = %d", __func__, resolution); + Mutex::Autolock _l(mLock); + + if ((hdmiCableInserted() == true) && (mSecHdmi.setHdmiResolution(resolution)) == false) { + LOGE("%s::mSecHdmi.setHdmiResolution() fail", __func__); + return; + } + } + + void SecTVOutService::setHdmiHdcp(uint32_t hdcp_en) + { + LOGD("%s TV HDCP = %d", __func__, hdcp_en); + Mutex::Autolock _l(mLock); + + if ((hdmiCableInserted() == true) && (mSecHdmi.setHdcpMode(hdcp_en)) == false) { + LOGE("%s::mSecHdmi.setHdcpMode() fail", __func__); + return; + } + } + + void SecTVOutService::setHdmiRotate(uint32_t rotVal, uint32_t hwcLayer) + { + //LOGD("%s TV ROTATE = %d", __func__, rotVal); + Mutex::Autolock _l(mLock); + + if ((hdmiCableInserted() == true) && (mSecHdmi.setUIRotation(rotVal, hwcLayer)) == false) { + LOGE("%s::mSecHdmi.setUIRotation() fail", __func__); + return; + } + } + + void SecTVOutService::setHdmiHwcLayer(uint32_t hwcLayer) + { + //LOGD("%s TV HWCLAYER = %d", __func__, hwcLayer); + Mutex::Autolock _l(mLock); + + mHwcLayer = hwcLayer; + return; + } + + void SecTVOutService::blit2Hdmi(uint32_t w, uint32_t h, uint32_t colorFormat, + uint32_t pPhyYAddr, uint32_t pPhyCbAddr, uint32_t pPhyCrAddr, + uint32_t dstX, uint32_t dstY, + uint32_t hdmiMode, + uint32_t num_of_hwc_layer) + { + Mutex::Autolock _l(mLock); + + if (hdmiCableInserted() == false) + return; + + int hdmiLayer = SecHdmi::HDMI_LAYER_VIDEO; +#if defined(CHECK_UI_TIME) || defined(CHECK_VIDEO_TIME) + nsecs_t start, end; +#endif + + sp msg; + + switch (hdmiMode) { + case HDMI_MODE_UI : + if (mHwcLayer >= 2) + hdmiLayer = SecHdmi::HDMI_LAYER_GRAPHIC_0; + else if (mHwcLayer == 1) + hdmiLayer = SecHdmi::HDMI_LAYER_GRAPHIC_1; + else +#ifdef SUPPORT_G2D_UI_MODE + hdmiLayer = SecHdmi::HDMI_LAYER_GRAPHIC_1; +#else + hdmiLayer = SecHdmi::HDMI_LAYER_VIDEO; +#endif + +#ifdef SUPPORT_G2D_UI_MODE + if (mHwcLayer == 0) { + if (mSecHdmi.clear(SecHdmi::HDMI_LAYER_VIDEO) == false) + LOGE("%s::mSecHdmi.clear(%d) fail", __func__, SecHdmi::HDMI_LAYER_VIDEO); + if (mSecHdmi.clear(SecHdmi::HDMI_LAYER_GRAPHIC_0) == false) + LOGE("%s::mSecHdmi.clear(%d) fail", __func__, SecHdmi::HDMI_LAYER_GRAPHIC_0); + } +#endif + + if (mUILayerMode != hdmiLayer) { + if (mSecHdmi.clear(mUILayerMode) == false) + LOGE("%s::mSecHdmi.clear(%d) fail", __func__, mUILayerMode); + } + + mUILayerMode = hdmiLayer; + +#if !defined(BOARD_USES_HDMI_SUBTITLES) + if (mHwcLayer == 0) +#endif +#if (DIRECT_UI_RENDERING == 1) + { +#ifdef CHECK_UI_TIME + start = systemTime(); +#endif + if (mSecHdmi.flush(w, h, colorFormat, pPhyYAddr, pPhyCbAddr, pPhyCrAddr, dstX, dstY, + mUILayerMode, mHwcLayer) == false) + LOGE("%s::mSecHdmi.flush() on HDMI_MODE_UI fail", __func__); +#ifdef CHECK_UI_TIME + end = systemTime(); + LOGD("[UI] mSecHdmi.flush[end-start] = %ld ms", long(ns2ms(end)) - long(ns2ms(start))); +#endif + } +#else + { + msg = new SecHdmiEventMsg(&mSecHdmi, w, h, colorFormat, pPhyYAddr, pPhyCbAddr, pPhyCrAddr, + dstX, dstY, mUILayerMode, mHwcLayer, HDMI_MODE_UI); + + /* post to HdmiEventQueue */ + mHdmiEventQueue.postMessage(msg, 0, 0); + } +#endif + break; + + case HDMI_MODE_VIDEO : +#if !defined(BOARD_USES_HDMI_SUBTITLES) +#ifdef SUPPORT_G2D_UI_MODE + if (mSecHdmi.clear(SecHdmi::HDMI_LAYER_GRAPHIC_0) == false) + LOGE("%s::mSecHdmi.clear(%d) fail", __func__, SecHdmi::HDMI_LAYER_GRAPHIC_0); + if (mSecHdmi.clear(SecHdmi::HDMI_LAYER_GRAPHIC_1) == false) + LOGE("%s::mSecHdmi.clear(%d) fail", __func__, SecHdmi::HDMI_LAYER_GRAPHIC_1); +#endif +#endif + +#if (DIRECT_VIDEO_RENDERING == 1) +#ifdef CHECK_VIDEO_TIME + start = systemTime(); +#endif + if (mSecHdmi.flush(w, h, colorFormat, pPhyYAddr, pPhyCbAddr, pPhyCrAddr, dstX, dstY, + SecHdmi::HDMI_LAYER_VIDEO, mHwcLayer) == false) + LOGE("%s::mSecHdmi.flush() on HDMI_MODE_VIDEO fail", __func__); +#ifdef CHECK_VIDEO_TIME + end = systemTime(); + LOGD("[Video] mSecHdmi.flush[end-start] = %ld ms", long(ns2ms(end)) - long(ns2ms(start))); +#endif +#else + msg = new SecHdmiEventMsg(&mSecHdmi, w, h, colorFormat, pPhyYAddr, pPhyCbAddr, pPhyCrAddr, + dstX, dstY, SecHdmi::HDMI_LAYER_VIDEO, mHwcLayer, HDMI_MODE_VIDEO); + + /* post to HdmiEventQueue */ + mHdmiEventQueue.postMessage(msg, 0, 0); +#endif + break; + + default: + LOGE("unmatched HDMI_MODE : %d", hdmiMode); + break; + } + + return; + } + + bool SecTVOutService::hdmiCableInserted(void) + { + return mHdmiCableInserted; + } + +} diff --git a/exynos4/hal/libhdmi/libhdmiservice/SecTVOutService.h b/exynos4/hal/libhdmi/libhdmiservice/SecTVOutService.h new file mode 100644 index 0000000..1f5f251 --- /dev/null +++ b/exynos4/hal/libhdmi/libhdmiservice/SecTVOutService.h @@ -0,0 +1,174 @@ +/* +** +** Copyright 2008, The Android Open Source Project +** Copyright 2010, Samsung Electronics Co. LTD +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + +/* +** +** @author Taikyung, Yu(taikyung.yu@samsung.com) +** @date 2011-07-06 +*/ + +#ifndef SECTVOUTSERVICE_H +#define SECTVOUTSERVICE_H + +#include +#include +#include +#include + +#include "ISecTVOut.h" +#include "SecHdmi.h" +#include "sec_format.h" +#include "sec_utils.h" +#include "MessageQueue.h" + +namespace android { +//#define CHECK_VIDEO_TIME +//#define CHECK_UI_TIME + + class SecTVOutService : public BBinder + { + public : + enum { + HDMI_MODE_NONE = 0, + HDMI_MODE_UI, + HDMI_MODE_VIDEO, + }; + + mutable Mutex mLock; + + class HDMIFlushThread : public Thread { + SecTVOutService *mTVOutService; + public: + HDMIFlushThread(SecTVOutService *service): + Thread(false), + mTVOutService(service) { } + virtual void onFirstRef() { + run("HDMIFlushThread", PRIORITY_URGENT_DISPLAY); + } + virtual bool threadLoop() { + mTVOutService->HdmiFlushThread(); + return false; + } + }; + + sp mHdmiFlushThread; + int HdmiFlushThread(); + + mutable MessageQueue mHdmiEventQueue; + bool mExitHdmiFlushThread; + + SecTVOutService(); + static int instantiate (); + virtual status_t onTransact(uint32_t, const Parcel &, Parcel *, uint32_t); + virtual ~SecTVOutService (); + + virtual void setHdmiStatus(uint32_t status); + virtual void setHdmiMode(uint32_t mode); + virtual void setHdmiResolution(uint32_t resolution); + virtual void setHdmiHdcp(uint32_t enHdcp); + virtual void setHdmiRotate(uint32_t rotVal, uint32_t hwcLayer); + virtual void setHdmiHwcLayer(uint32_t hwcLayer); + virtual void blit2Hdmi(uint32_t w, uint32_t h, + uint32_t colorFormat, + uint32_t pPhyYAddr, uint32_t pPhyCbAddr, uint32_t pPhyCrAddr, + uint32_t dstX, uint32_t dstY, + uint32_t hdmiMode, uint32_t num_of_hwc_layer); + bool hdmiCableInserted(void); + void setLCDsize(void); + + private: + SecHdmi mSecHdmi; + bool mHdmiCableInserted; + int mUILayerMode; + uint32_t mLCD_width, mLCD_height; + uint32_t mHwcLayer; + }; + + class SecHdmiEventMsg : public MessageBase { + public: + enum { + HDMI_MODE_NONE = 0, + HDMI_MODE_UI, + HDMI_MODE_VIDEO, + }; + + mutable Mutex mBlitLock; + + SecHdmi *pSecHdmi; + uint32_t mSrcWidth, mSrcHeight; + uint32_t mSrcColorFormat; + uint32_t mSrcYAddr, mSrcCbAddr, mSrcCrAddr; + uint32_t mDstX, mDstY; + uint32_t mHdmiMode; + uint32_t mHdmiLayer, mHwcLayer; + + SecHdmiEventMsg(SecHdmi *SecHdmi, uint32_t srcWidth, uint32_t srcHeight, uint32_t srcColorFormat, + uint32_t srcYAddr, uint32_t srcCbAddr, uint32_t srcCrAddr, + uint32_t dstX, uint32_t dstY, uint32_t hdmiLayer, uint32_t hwcLayer, uint32_t hdmiMode) + : pSecHdmi(SecHdmi), mSrcWidth(srcWidth), mSrcHeight(srcHeight), mSrcColorFormat(srcColorFormat), + mSrcYAddr(srcYAddr), mSrcCbAddr(srcCbAddr), mSrcCrAddr(srcCrAddr), + mDstX(dstX), mDstY(dstY), mHdmiLayer(hdmiLayer), mHwcLayer(hwcLayer), mHdmiMode(hdmiMode) { + } + + virtual bool handler() { + Mutex::Autolock _l(mBlitLock); + bool ret = true; +#if defined(CHECK_UI_TIME) || defined(CHECK_VIDEO_TIME) + nsecs_t start, end; +#endif + + switch (mHdmiMode) { + case HDMI_MODE_UI: +#ifdef CHECK_UI_TIME + start = systemTime(); +#endif + if (pSecHdmi->flush(mSrcWidth, mSrcHeight, mSrcColorFormat, mSrcYAddr, mSrcCbAddr, mSrcCrAddr, + mDstX, mDstY, mHdmiLayer, mHwcLayer) == false) { + LOGE("%s::pSecHdmi->flush() fail on HDMI_MODE_UI", __func__); + ret = false; + } +#ifdef CHECK_UI_TIME + end = systemTime(); + LOGD("[UI] pSecHdmi->flush[end-start] = %ld ms", long(ns2ms(end)) - long(ns2ms(start))); +#endif + break; + case HDMI_MODE_VIDEO: +#ifdef CHECK_VIDEO_TIME + start = systemTime(); +#endif + if (pSecHdmi->flush(mSrcWidth, mSrcHeight, mSrcColorFormat, mSrcYAddr, mSrcCbAddr, mSrcCrAddr, + mDstX, mDstY, mHdmiLayer, mHwcLayer) == false) { + LOGE("%s::pSecHdmi->flush() fail on HDMI_MODE_VIDEO", __func__); + ret = false; + } +#ifdef CHECK_VIDEO_TIME + end = systemTime(); + LOGD("[VIDEO] pSecHdmi->flush[end-start] = %ld ms", long(ns2ms(end)) - long(ns2ms(start))); +#endif + break; + default: + LOGE("Undefined HDMI_MODE"); + ret = false; + break; + } + return ret; + } + }; + +}; +#endif diff --git a/exynos4/hal/libhdmi/libsForhdmi/Android.mk b/exynos4/hal/libhdmi/libsForhdmi/Android.mk new file mode 100644 index 0000000..237c53c --- /dev/null +++ b/exynos4/hal/libhdmi/libsForhdmi/Android.mk @@ -0,0 +1,17 @@ +# Copyright (C) 2008 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +ifeq ($(filter-out exynos4,$(TARGET_BOARD_PLATFORM)),) +include $(all-subdir-makefiles) +endif diff --git a/exynos4/hal/libump/ump.mak b/exynos4/hal/libhdmi/libsForhdmi/libcec/Android.mk similarity index 50% rename from exynos4/hal/libump/ump.mak rename to exynos4/hal/libhdmi/libsForhdmi/libcec/Android.mk index e417313..9a4b721 100644 --- a/exynos4/hal/libump/ump.mak +++ b/exynos4/hal/libhdmi/libsForhdmi/libcec/Android.mk @@ -1,34 +1,33 @@ +# Copyright (C) 2008 The Android Open Source Project # -# Copyright (C) 2011 ARM Limited. All rights reserved. -# # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# +# +# http://www.apache.org/licenses/LICENSE-2.0 +# # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -# -ifeq ($(UMP_NO_UMP),1) +ifeq ($(BOARD_USES_HDMI),true) -UMP_SRCS = \ - $(UMP_DIR)/arch_999_no_ump/ump_frontend.c \ - $(UMP_DIR)/arch_999_no_ump/ump_ref_drv.c +LOCAL_PATH:= $(call my-dir) +include $(CLEAR_VARS) -else +LOCAL_MODULE_TAGS := eng -UMP_SRCS = \ - $(UMP_DIR)/arch_011_udd/ump_frontend.c \ - $(UMP_DIR)/arch_011_udd/ump_ref_drv.c \ - $(UMP_DIR)/arch_011_udd/ump_arch.c \ - $(UMP_DIR)/os/$(UDD_OS)/ump_uku.c \ - $(UMP_DIR)/os/$(UDD_OS)/ump_osu_memory.c \ - $(UMP_DIR)/os/$(UDD_OS)/ump_osu_locks.c +LOCAL_PRELINK_MODULE := false +LOCAL_SHARED_LIBRARIES := liblog +LOCAL_SRC_FILES := libcec.c + +LOCAL_C_INCLUDES := \ + $(LOCAL_PATH) \ + $(LOCAL_PATH)/../../../include + +LOCAL_MODULE := libcec +include $(BUILD_SHARED_LIBRARY) endif - diff --git a/exynos4/hal/libhdmi/libsForhdmi/libcec/cec.h b/exynos4/hal/libhdmi/libsForhdmi/libcec/cec.h new file mode 100644 index 0000000..4b0d3af --- /dev/null +++ b/exynos4/hal/libhdmi/libsForhdmi/libcec/cec.h @@ -0,0 +1,11 @@ +#ifndef _LINUX_CEC_H_ +#define _LINUX_CEC_H_ + +#define CEC_IOC_MAGIC 'c' + +/** + * CEC device request code to set logical address. + */ +#define CEC_IOC_SETLADDR _IOW(CEC_IOC_MAGIC, 0, unsigned int) + +#endif /* _LINUX_CEC_H_ */ diff --git a/exynos4/hal/libhdmi/libsForhdmi/libcec/libcec.c b/exynos4/hal/libhdmi/libsForhdmi/libcec/libcec.c new file mode 100644 index 0000000..e688051 --- /dev/null +++ b/exynos4/hal/libhdmi/libsForhdmi/libcec/libcec.c @@ -0,0 +1,386 @@ +/* +* Copyright@ Samsung Electronics Co. LTD +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include + +/* drv. header */ +#include "cec.h" + +#include "libcec.h" + +#define CEC_DEBUG 0 + +/** + * @def CEC_DEVICE_NAME + * Defines simbolic name of the CEC device. + */ +#define CEC_DEVICE_NAME "/dev/CEC" + +static struct { + enum CECDeviceType devtype; + unsigned char laddr; +} laddresses[] = { + { CEC_DEVICE_RECODER, 1 }, + { CEC_DEVICE_RECODER, 2 }, + { CEC_DEVICE_TUNER, 3 }, + { CEC_DEVICE_PLAYER, 4 }, + { CEC_DEVICE_AUDIO, 5 }, + { CEC_DEVICE_TUNER, 6 }, + { CEC_DEVICE_TUNER, 7 }, + { CEC_DEVICE_PLAYER, 8 }, + { CEC_DEVICE_RECODER, 9 }, + { CEC_DEVICE_TUNER, 10 }, + { CEC_DEVICE_PLAYER, 11 }, +}; + +static int CECSetLogicalAddr(unsigned int laddr); + +#ifdef CEC_DEBUG +inline static void CECPrintFrame(unsigned char *buffer, unsigned int size); +#endif + +static int fd = -1; + +/** + * Open device driver and assign CEC file descriptor. + * + * @return If success to assign CEC file descriptor, return 1; otherwise, return 0. + */ +int CECOpen() +{ + int res = 1; + + if (fd != -1) + CECClose(); + + if ((fd = open(CEC_DEVICE_NAME, O_RDWR)) < 0) { + LOGE("Can't open %s!\n", CEC_DEVICE_NAME); + res = 0; + } + + return res; +} + +/** + * Close CEC file descriptor. + * + * @return If success to close CEC file descriptor, return 1; otherwise, return 0. + */ +int CECClose() +{ + int res = 1; + + if (fd != -1) { + if (close(fd) != 0) { + LOGE("close() failed!\n"); + res = 0; + } + fd = -1; + } + + return res; +} + +/** + * Allocate logical address. + * + * @param paddr [in] CEC device physical address. + * @param devtype [in] CEC device type. + * + * @return new logical address, or 0 if an arror occured. + */ +int CECAllocLogicalAddress(int paddr, enum CECDeviceType devtype) +{ + unsigned char laddr = CEC_LADDR_UNREGISTERED; + int i = 0; + + if (fd == -1) { + LOGE("open device first!\n"); + return 0; + } + + if (CECSetLogicalAddr(laddr) < 0) { + LOGE("CECSetLogicalAddr() failed!\n"); + return 0; + } + + if (paddr == CEC_NOT_VALID_PHYSICAL_ADDRESS) + return CEC_LADDR_UNREGISTERED; + + /* send "Polling Message" */ + while (i < sizeof(laddresses)/sizeof(laddresses[0])) { + if (laddresses[i].devtype == devtype) { + unsigned char _laddr = laddresses[i].laddr; + unsigned char message = ((_laddr << 4) | _laddr); + if (CECSendMessage(&message, 1) != 1) { + laddr = _laddr; + break; + } + } + i++; + } + + if (laddr == CEC_LADDR_UNREGISTERED) { + LOGE("All LA addresses in use!!!\n"); + return CEC_LADDR_UNREGISTERED; + } + + if (CECSetLogicalAddr(laddr) < 0) { + LOGE("CECSetLogicalAddr() failed!\n"); + return 0; + } + + /* broadcast "Report Physical Address" */ + unsigned char buffer[5]; + buffer[0] = (laddr << 4) | CEC_MSG_BROADCAST; + buffer[1] = CEC_OPCODE_REPORT_PHYSICAL_ADDRESS; + buffer[2] = (paddr >> 8) & 0xFF; + buffer[3] = paddr & 0xFF; + buffer[4] = devtype; + + if (CECSendMessage(buffer, 5) != 5) { + LOGE("CECSendMessage() failed!\n"); + return 0; + } + + return laddr; +} + +/** + * Send CEC message. + * + * @param *buffer [in] pointer to buffer address where message located. + * @param size [in] message size. + * + * @return number of bytes written, or 0 if an arror occured. + */ +int CECSendMessage(unsigned char *buffer, int size) +{ + if (fd == -1) { + LOGE("open device first!\n"); + return 0; + } + + if (size > CEC_MAX_FRAME_SIZE) { + LOGE("size should not exceed %d\n", CEC_MAX_FRAME_SIZE); + return 0; + } + +#if CEC_DEBUG + LOGI("CECSendMessage() : "); + CECPrintFrame(buffer, size); +#endif + + return write(fd, buffer, size); +} + +/** + * Receive CEC message. + * + * @param *buffer [in] pointer to buffer address where message will be stored. + * @param size [in] buffer size. + * @param timeout [in] timeout in microseconds. + * + * @return number of bytes received, or 0 if an arror occured. + */ +int CECReceiveMessage(unsigned char *buffer, int size, long timeout) +{ + int bytes = 0; + fd_set rfds; + struct timeval tv; + int retval; + + if (fd == -1) { + LOGE("open device first!\n"); + return 0; + } + + tv.tv_sec = 0; + tv.tv_usec = timeout; + + FD_ZERO(&rfds); + FD_SET(fd, &rfds); + + retval = select(fd + 1, &rfds, NULL, NULL, &tv); + + if (retval == -1) { + return 0; + } else if (retval) { + bytes = read(fd, buffer, size); +#if CEC_DEBUG + LOGI("CECReceiveMessage() : size(%d)", bytes); + if(bytes > 0) + CECPrintFrame(buffer, bytes); +#endif + } + + return bytes; +} + +/** + * Set CEC logical address. + * + * @return 1 if success, otherwise, return 0. + */ +int CECSetLogicalAddr(unsigned int laddr) +{ + if (ioctl(fd, CEC_IOC_SETLADDR, &laddr)) { + LOGE("ioctl(CEC_IOC_SETLA) failed!\n"); + return 0; + } + + return 1; +} + +#if CEC_DEBUG +/** + * Print CEC frame. + */ +void CECPrintFrame(unsigned char *buffer, unsigned int size) +{ + if (size > 0) { + int i; + LOGI("fsize: %d ", size); + LOGI("frame: "); + for (i = 0; i < size; i++) + LOGI("0x%02x ", buffer[i]); + + LOGI("\n"); + } +} +#endif + +/** + * Check CEC message. + * + * @param opcode [in] pointer to buffer address where message will be stored. + * @param lsrc [in] buffer size. + * + * @return 1 if message should be ignored, otherwise, return 0. + */ +//TODO: not finished +int CECIgnoreMessage(unsigned char opcode, unsigned char lsrc) +{ + int retval = 0; + + /* if a message coming from address 15 (unregistered) */ + if (lsrc == CEC_LADDR_UNREGISTERED) { + switch (opcode) { + case CEC_OPCODE_DECK_CONTROL: + case CEC_OPCODE_PLAY: + retval = 1; + default: + break; + } + } + + return retval; +} + +/** + * Check CEC message. + * + * @param opcode [in] pointer to buffer address where message will be stored. + * @param size [in] message size. + * + * @return 0 if message should be ignored, otherwise, return 1. + */ +//TODO: not finished +int CECCheckMessageSize(unsigned char opcode, int size) +{ + int retval = 1; + + switch (opcode) { + case CEC_OPCODE_REQUEST_ACTIVE_SOURCE: + if (size != 1) + retval = 0; + break; + case CEC_OPCODE_SET_SYSTEM_AUDIO_MODE: + if (size != 2) + retval = 0; + break; + case CEC_OPCODE_PLAY: + case CEC_OPCODE_DECK_CONTROL: + case CEC_OPCODE_SET_MENU_LANGUAGE: + case CEC_OPCODE_ACTIVE_SOURCE: + case CEC_OPCODE_ROUTING_INFORMATION: + case CEC_OPCODE_SET_STREAM_PATH: + if (size != 3) + retval = 0; + break; + case CEC_OPCODE_FEATURE_ABORT: + case CEC_OPCODE_DEVICE_VENDOR_ID: + case CEC_OPCODE_REPORT_PHYSICAL_ADDRESS: + if (size != 4) + retval = 0; + break; + case CEC_OPCODE_ROUTING_CHANGE: + if (size != 5) + retval = 0; + break; + /* CDC - 1.4 */ + case 0xf8: + if (!(size > 5 && size <= 16)) + retval = 0; + break; + default: + break; + } + + return retval; +} + +/** + * Check CEC message. + * + * @param opcode [in] pointer to buffer address where message will be stored. + * @param broadcast [in] broadcast/direct message. + * + * @return 0 if message should be ignored, otherwise, return 1. + */ +//TODO: not finished +int CECCheckMessageMode(unsigned char opcode, int broadcast) +{ + int retval = 1; + + switch (opcode) { + case CEC_OPCODE_REQUEST_ACTIVE_SOURCE: + case CEC_OPCODE_SET_MENU_LANGUAGE: + case CEC_OPCODE_ACTIVE_SOURCE: + if (!broadcast) + retval = 0; + break; + case CEC_OPCODE_GIVE_PHYSICAL_ADDRESS: + case CEC_OPCODE_DECK_CONTROL: + case CEC_OPCODE_PLAY: + case CEC_OPCODE_FEATURE_ABORT: + case CEC_OPCODE_ABORT: + if (broadcast) + retval = 0; + break; + default: + break; + } + + return retval; +} diff --git a/exynos4/hal/libhdmi/libsForhdmi/libcec/libcec.h b/exynos4/hal/libhdmi/libsForhdmi/libcec/libcec.h new file mode 100644 index 0000000..5bbfc15 --- /dev/null +++ b/exynos4/hal/libhdmi/libsForhdmi/libcec/libcec.h @@ -0,0 +1,209 @@ +/* + * Copyright@ Samsung Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _LIBCEC_H_ +#define _LIBCEC_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/** Maximum CEC frame size */ +#define CEC_MAX_FRAME_SIZE 16 +/** Not valid CEC physical address */ +#define CEC_NOT_VALID_PHYSICAL_ADDRESS 0xFFFF + +/** CEC broadcast address (as destination address) */ +#define CEC_MSG_BROADCAST 0x0F +/** CEC unregistered address (as initiator address) */ +#define CEC_LADDR_UNREGISTERED 0x0F + +/* + * CEC Messages + */ + +//@{ +/** @name Messages for the One Touch Play Feature */ +#define CEC_OPCODE_ACTIVE_SOURCE 0x82 +#define CEC_OPCODE_IMAGE_VIEW_ON 0x04 +#define CEC_OPCODE_TEXT_VIEW_ON 0x0D +//@} + +//@{ +/** @name Messages for the Routing Control Feature */ +#define CEC_OPCODE_INACTIVE_SOURCE 0x9D +#define CEC_OPCODE_REQUEST_ACTIVE_SOURCE 0x85 +#define CEC_OPCODE_ROUTING_CHANGE 0x80 +#define CEC_OPCODE_ROUTING_INFORMATION 0x81 +#define CEC_OPCODE_SET_STREAM_PATH 0x86 +//@} + +//@{ +/** @name Messages for the Standby Feature */ +#define CEC_OPCODE_STANDBY 0x36 +//@} + +//@{ +/** @name Messages for the One Touch Record Feature */ +#define CEC_OPCODE_RECORD_OFF 0x0B +#define CEC_OPCODE_RECORD_ON 0x09 +#define CEC_OPCODE_RECORD_STATUS 0x0A +#define CEC_OPCODE_RECORD_TV_SCREEN 0x0F +//@} + +//@{ +/** @name Messages for the Timer Programming Feature */ +#define CEC_OPCODE_CLEAR_ANALOGUE_TIMER 0x33 +#define CEC_OPCODE_CLEAR_DIGITAL_TIMER 0x99 +#define CEC_OPCODE_CLEAR_EXTERNAL_TIMER 0xA1 +#define CEC_OPCODE_SET_ANALOGUE_TIMER 0x34 +#define CEC_OPCODE_SET_DIGITAL_TIMER 0x97 +#define CEC_OPCODE_SET_EXTERNAL_TIMER 0xA2 +#define CEC_OPCODE_SET_TIMER_PROGRAM_TITLE 0x67 +#define CEC_OPCODE_TIMER_CLEARED_STATUS 0x43 +#define CEC_OPCODE_TIMER_STATUS 0x35 +//@} + +//@{ +/** @name Messages for the System Information Feature */ +#define CEC_OPCODE_CEC_VERSION 0x9E +#define CEC_OPCODE_GET_CEC_VERSION 0x9F +#define CEC_OPCODE_GIVE_PHYSICAL_ADDRESS 0x83 +#define CEC_OPCODE_GET_MENU_LANGUAGE 0x91 +//#define CEC_OPCODE_POLLING_MESSAGE +#define CEC_OPCODE_REPORT_PHYSICAL_ADDRESS 0x84 +#define CEC_OPCODE_SET_MENU_LANGUAGE 0x32 +//@} + +//@{ +/** @name Messages for the Deck Control Feature */ +#define CEC_OPCODE_DECK_CONTROL 0x42 +#define CEC_OPCODE_DECK_STATUS 0x1B +#define CEC_OPCODE_GIVE_DECK_STATUS 0x1A +#define CEC_OPCODE_PLAY 0x41 +//@} + +//@{ +/** @name Messages for the Tuner Control Feature */ +#define CEC_OPCODE_GIVE_TUNER_DEVICE_STATUS 0x08 +#define CEC_OPCODE_SELECT_ANALOGUE_SERVICE 0x92 +#define CEC_OPCODE_SELECT_DIGITAL_SERVICE 0x93 +#define CEC_OPCODE_TUNER_DEVICE_STATUS 0x07 +#define CEC_OPCODE_TUNER_STEP_DECREMENT 0x06 +#define CEC_OPCODE_TUNER_STEP_INCREMENT 0x05 +//@} + +//@{ +/** @name Messages for the Vendor Specific Commands Feature */ +#define CEC_OPCODE_DEVICE_VENDOR_ID 0x87 +#define CEC_OPCODE_GET_DEVICE_VENDOR_ID 0x8C +#define CEC_OPCODE_VENDOR_COMMAND 0x89 +#define CEC_OPCODE_VENDOR_COMMAND_WITH_ID 0xA0 +#define CEC_OPCODE_VENDOR_REMOTE_BUTTON_DOWN 0x8A +#define CEC_OPCODE_VENDOR_REMOVE_BUTTON_UP 0x8B +//@} + +//@{ +/** @name Messages for the OSD Display Feature */ +#define CEC_OPCODE_SET_OSD_STRING 0x64 +//@} + +//@{ +/** @name Messages for the Device OSD Transfer Feature */ +#define CEC_OPCODE_GIVE_OSD_NAME 0x46 +#define CEC_OPCODE_SET_OSD_NAME 0x47 +//@} + +//@{ +/** @name Messages for the Device Menu Control Feature */ +#define CEC_OPCODE_MENU_REQUEST 0x8D +#define CEC_OPCODE_MENU_STATUS 0x8E +#define CEC_OPCODE_USER_CONTROL_PRESSED 0x44 +#define CEC_OPCODE_USER_CONTROL_RELEASED 0x45 +//@} + +//@{ +/** @name Messages for the Remote Control Passthrough Feature */ +//@} + +//@{ +/** @name Messages for the Power Status Feature */ +#define CEC_OPCODE_GIVE_DEVICE_POWER_STATUS 0x8F +#define CEC_OPCODE_REPORT_POWER_STATUS 0x90 +//@} + +//@{ +/** @name Messages for General Protocol messages */ +#define CEC_OPCODE_FEATURE_ABORT 0x00 +#define CEC_OPCODE_ABORT 0xFF +//@} + +//@{ +/** @name Messages for the System Audio Control Feature */ +#define CEC_OPCODE_GIVE_AUDIO_STATUS 0x71 +#define CEC_OPCODE_GIVE_SYSTEM_AUDIO_MODE_STATUS 0x7D +#define CEC_OPCODE_REPORT_AUDIO_STATUS 0x7A +#define CEC_OPCODE_SET_SYSTEM_AUDIO_MODE 0x72 +#define CEC_OPCODE_SYSTEM_AUDIO_MODE_REQUEST 0x70 +#define CEC_OPCODE_SYSTEM_AUDIO_MODE_STATUS 0x7E +//@} + +//@{ +/** @name Messages for the Audio Rate Control Feature */ +#define CEC_OPCODE_SET_AUDIO_RATE 0x9A +//@} + +//@{ +/** @name CEC Operands */ + +//TODO: not finished + +#define CEC_DECK_CONTROL_MODE_STOP 0x03 +#define CEC_PLAY_MODE_PLAY_FORWARD 0x24 +//@} + +/** + * @enum CECDeviceType + * Type of CEC device + */ +enum CECDeviceType { + /** TV */ + CEC_DEVICE_TV, + /** Recording Device */ + CEC_DEVICE_RECODER, + /** Tuner */ + CEC_DEVICE_TUNER, + /** Playback Device */ + CEC_DEVICE_PLAYER, + /** Audio System */ + CEC_DEVICE_AUDIO, +}; + +int CECOpen(); +int CECClose(); +int CECAllocLogicalAddress(int paddr, enum CECDeviceType devtype); +int CECSendMessage(unsigned char *buffer, int size); +int CECReceiveMessage(unsigned char *buffer, int size, long timeout); + +int CECIgnoreMessage(unsigned char opcode, unsigned char lsrc); +int CECCheckMessageSize(unsigned char opcode, int size); +int CECCheckMessageMode(unsigned char opcode, int broadcast); + +#ifdef __cplusplus +} +#endif + +#endif /* _LIBCEC_H_ */ diff --git a/exynos4/hal/libhdmi/libsForhdmi/libddc/Android.mk b/exynos4/hal/libhdmi/libsForhdmi/libddc/Android.mk new file mode 100644 index 0000000..38891be --- /dev/null +++ b/exynos4/hal/libhdmi/libsForhdmi/libddc/Android.mk @@ -0,0 +1,45 @@ +# Copyright (C) 2008 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +ifeq ($(BOARD_USES_HDMI),true) + +LOCAL_PATH:= $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_MODULE_TAGS := eng + +LOCAL_PRELINK_MODULE := false +LOCAL_SHARED_LIBRARIES := liblog +LOCAL_SRC_FILES := libddc.c + +LOCAL_C_INCLUDES := \ + $(LOCAL_PATH) \ + $(LOCAL_PATH)/../../../include + +ifeq ($(BOARD_HDMI_DDC_CH), DDC_CH_I2C_7) +LOCAL_CFLAGS += -DDDC_CH_I2C_7 +endif + +ifeq ($(BOARD_HDMI_DDC_CH), DDC_CH_I2C_1) +LOCAL_CFLAGS += -DDDC_CH_I2C_1 +endif + +ifeq ($(BOARD_HDMI_DDC_CH), DDC_CH_I2C_2) +LOCAL_CFLAGS += -DDDC_CH_I2C_2 +endif + +LOCAL_MODULE := libddc +include $(BUILD_SHARED_LIBRARY) + +endif diff --git a/exynos4/hal/libhdmi/libsForhdmi/libddc/libddc.c b/exynos4/hal/libhdmi/libsForhdmi/libddc/libddc.c new file mode 100644 index 0000000..12910fb --- /dev/null +++ b/exynos4/hal/libhdmi/libsForhdmi/libddc/libddc.c @@ -0,0 +1,285 @@ +/* +* Copyright@ Samsung Electronics Co. LTD +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include "i2c-dev.h" + +#include "libddc.h" + +#define DDC_DEBUG 0 + +/** + * @brief DDC device name. + * User should change this. + */ +#ifdef DDC_CH_I2C_1 +#define DEV_NAME "/dev/i2c-1" +#endif + +#ifdef DDC_CH_I2C_2 +#define DEV_NAME "/dev/i2c-2" +#endif + +#ifdef DDC_CH_I2C_7 +#define DEV_NAME "/dev/i2c-7" +#endif + +/** + * DDC file descriptor + */ +static int ddc_fd = -1; + +/** + * Reference count of DDC file descriptor + */ +static unsigned int ref_cnt = 0; + +/** + * Check if DDC file is already opened or not + * @return If DDC file is already opened, return 1; Otherwise, return 0. + */ +static int DDCFileAvailable() +{ + return (ddc_fd < 0) ? 0 : 1; +} + +/** + * Initialze DDC library. Open DDC device + * @return If succeed in opening DDC device or it is already opened, return 1;@n + * Otherwise, return 0. + */ +int DDCOpen() +{ + int ret = 1; + + // check already open?? + if (ref_cnt > 0) { + ref_cnt++; + return 1; + } + + // open + if ((ddc_fd = open(DEV_NAME,O_RDWR)) < 0) { + LOGE("%s: Cannot open I2C_DDC : %s",__func__, DEV_NAME); + ret = 0; + } + + ref_cnt++; + return ret; +} + +/** + * Finalize DDC library. Close DDC device + * @return If succeed in closing DDC device or it is being used yet, return 1;@n + * Otherwise, return 0. + */ +int DDCClose() +{ + int ret = 1; + // check if fd is available + if (ref_cnt == 0) { +#if DDC_DEBUG + LOGE("%s: I2C_DDC is not available!!!!", __func__); +#endif + return 1; + } + + // close + if (ref_cnt > 1) { + ref_cnt--; + return 1; + } + + if (close(ddc_fd) < 0) { +#if DDC_DEBUG + LOGE("%s: Cannot close I2C_DDC : %s",__func__,DEV_NAME); +#endif + ret = 0; + } + + ref_cnt--; + ddc_fd = -1; + + return ret; +} + +/** + * Read data though DDC. For more information of DDC, refer DDC Spec. + * @param addr [in] Device address + * @param offset [in] Byte offset + * @param size [in] Sizes of data + * @param buffer [out] Pointer to buffer to store data + * @return If succeed in reading, return 1; Otherwise, return 0. + */ +int DDCRead(unsigned char addr, unsigned char offset, + unsigned int size, unsigned char* buffer) +{ + struct i2c_rdwr_ioctl_data msgset; + struct i2c_msg msgs[2]; + int ret = 1; + + if (!DDCFileAvailable()) { +#if DDC_DEBUG + LOGE("%s: I2C_DDC is not available!!!!", __func__); +#endif + return 0; + } + + // set offset + msgs[0].addr = addr>>1; + msgs[0].flags = 0; + msgs[0].len = 1; + msgs[0].buf = &offset; + + // read data + msgs[1].addr = addr>>1; + msgs[1].flags = I2C_M_RD; + msgs[1].len = size; + msgs[1].buf = buffer; + + // set rdwr ioctl data + msgset.nmsgs = 2; + msgset.msgs = msgs; + + // i2c fast read + if ((ret = ioctl(ddc_fd, I2C_RDWR, &msgset)) < 0) { + perror("ddc error:"); + ret = 0; + } + + return ret; +} + +/** + * Read data though E-DDC. For more information of E-DDC, refer E-DDC Spec. + * @param segpointer [in] Segment pointer + * @param segment [in] Segment number + * @param addr [in] Device address + * @param offset [in] Byte offset + * @param size [in] Sizes of data + * @param buffer [out] Pointer to buffer to store data + * @return If succeed in reading, return 1; Otherwise, return 0. + */ + +int EDDCRead(unsigned char segpointer, unsigned char segment, unsigned char addr, + unsigned char offset, unsigned int size, unsigned char* buffer) +{ + struct i2c_rdwr_ioctl_data msgset; + struct i2c_msg msgs[3]; + int ret = 1; + + if (!DDCFileAvailable()) { +#if DDC_DEBUG + LOGE("%s: I2C_DDC is not available!!!!", __func__); +#endif + return 0; + } + + // set segment pointer + msgs[0].addr = segpointer>>1; + // ignore ack only if segment is "0" + if (segment == 0) + msgs[0].flags = I2C_M_IGNORE_NAK; + else + msgs[0].flags = 0; + + msgs[0].len = 1; + msgs[0].buf = &segment; + + // set offset + msgs[1].addr = addr>>1; + msgs[1].flags = 0; + msgs[1].len = 1; + msgs[1].buf = &offset; + + // read data + msgs[2].addr = addr>>1; + msgs[2].flags = I2C_M_RD; + msgs[2].len = size; + msgs[2].buf = buffer; + + msgset.nmsgs = 3; + msgset.msgs = msgs; + + // eddc read + if (ioctl(ddc_fd, I2C_RDWR, &msgset) < 0) { +#if DDC_DEBUG + LOGE("%s: ioctl(I2C_RDWR) failed!!!", __func__); +#endif + ret = 0; + } + return ret; +} + +/** + * Write data though DDC. For more information of DDC, refer DDC Spec. + * @param addr [in] Device address + * @param offset [in] Byte offset + * @param size [in] Sizes of data + * @param buffer [out] Pointer to buffer to write + * @return If succeed in writing, return 1; Otherwise, return 0. + */ +int DDCWrite(unsigned char addr, unsigned char offset, unsigned int size, unsigned char* buffer) +{ + unsigned char* temp; + int bytes; + int retval = 0; + + // allocate temporary buffer + temp = (unsigned char*) malloc((size+1)*sizeof(unsigned char)); + if (!temp) { + LOGE("%s: not enough resources at %s", __FUNCTION__); + goto exit; + } + + temp[0] = offset; + memcpy(temp+1,buffer,size); + + if (!DDCFileAvailable()) { + LOGE("%s: I2C_DDC is not available!!!!", __func__); + goto exit; + } + + if (ioctl(ddc_fd, I2C_SLAVE, addr>>1) < 0) { + LOGE("%s: cannot set slave address 0x%02x", __func__,addr); + goto exit; + } + + // write temp buffer + if ((bytes = write(ddc_fd,temp,size+1)) != (size+1)) { + LOGE("%s: fail to write %d bytes, only write %d bytes",__func__, size, bytes); + goto exit; + } + + retval = 1; + +exit: + // free temp buffer + if (temp) + free(temp); + + return retval; +} diff --git a/exynos4/hal/libhdmi/libsForhdmi/libddc/libddc.h b/exynos4/hal/libhdmi/libsForhdmi/libddc/libddc.h new file mode 100644 index 0000000..368855b --- /dev/null +++ b/exynos4/hal/libhdmi/libsForhdmi/libddc/libddc.h @@ -0,0 +1,35 @@ +/* + * Copyright@ Samsung Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _LIBDDC_H_ +#define _LIBDDC_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +int DDCOpen(); +int DDCRead(unsigned char addr, unsigned char offset, unsigned int size, unsigned char* buffer); +int DDCWrite(unsigned char addr, unsigned char offset, unsigned int size, unsigned char* buffer); +int EDDCRead(unsigned char segpointer, unsigned char segment, unsigned char addr, + unsigned char offset, unsigned int size, unsigned char* buffer); +int DDCClose(); + +#ifdef __cplusplus +} +#endif + +#endif /* _LIBDDC_H_ */ diff --git a/exynos4/hal/libhdmi/libsForhdmi/libedid/Android.mk b/exynos4/hal/libhdmi/libsForhdmi/libedid/Android.mk new file mode 100644 index 0000000..602ae4d --- /dev/null +++ b/exynos4/hal/libhdmi/libsForhdmi/libedid/Android.mk @@ -0,0 +1,34 @@ +# Copyright (C) 2008 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +ifeq ($(BOARD_USES_HDMI),true) + +LOCAL_PATH:= $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_MODULE_TAGS := eng + +LOCAL_PRELINK_MODULE := false +LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES) +LOCAL_SHARED_LIBRARIES := liblog libddc +LOCAL_SRC_FILES := libedid.c + +LOCAL_C_INCLUDES := \ + $(LOCAL_PATH) \ + $(LOCAL_PATH)/../../../include + +LOCAL_MODULE := libedid +include $(BUILD_SHARED_LIBRARY) + +endif diff --git a/exynos4/hal/libhdmi/libsForhdmi/libedid/edid.h b/exynos4/hal/libhdmi/libsForhdmi/libedid/edid.h new file mode 100644 index 0000000..aea1309 --- /dev/null +++ b/exynos4/hal/libhdmi/libsForhdmi/libedid/edid.h @@ -0,0 +1,181 @@ +/* + * Copyright@ Samsung Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _EDID_H_ +#define _EDID_H_ + +//@{ +/** + * @name EDID Addresses + */ +#define EDID_ADDR (0xA0) +#define EDID_SEGMENT_POINTER (0x60) +//@} + +//@{ +/** + * @name EDID offset and bit values + */ +#define SIZEOFBYTE (8) +#define SIZEOFEDIDBLOCK (0x80) +#define EDID_EXTENSION_NUMBER_POS (0x7E) + +#define EDID_TIMING_EXT_TAG_ADDR_POS (0) +#define EDID_TIMING_EXT_REV_NUMBER_POS (1) +#define EDID_DETAILED_TIMING_OFFSET_POS (2) +#define EDID_DATA_BLOCK_START_POS (4) + +// for Extension Data Block +#define EDID_TIMING_EXT_TAG_VAL (0x02) +#define EDID_BLOCK_MAP_EXT_TAG_VAL (0xF0) + +#define EDID_SHORT_AUD_DEC_TAG_VAL (1<<5) +#define EDID_SHORT_VID_DEC_TAG_VAL (2<<5) +#define EDID_VSDB_TAG_VAL (3<<5) +#define EDID_SPEAKER_ALLOCATION_TAG_VAL (4<<5) +#define EDID_VESA_DTC_TAG_VAL (5<<5) +#define EDID_RESERVED_TAG_VAL (6<<5) + +#define EDID_EXTENDED_TAG_VAL (7<<5) +#define EDID_EXTENDED_COLORIMETRY_VAL (5) +#define EDID_EXTENDED_COLORIMETRY_BLOCK_LEN (3) + +#define EDID_TAG_CODE_MASK (1<<7 | 1<<6 | 1<<5) +#define EDID_DATA_BLOCK_SIZE_MASK (1<<4 | 1<<3 | 1<<2 | 1<<1 | 1<<0) + +#define EDID_VSDB_MIN_LENGTH_VAL (5) + +// for Established Timings +#define EDID_ET_POS (0x23) +#define EDID_ET_640x480p_VAL (0x20) + +// for DTD +#define EDID_DTD_START_ADDR (0x36) +#define EDID_DTD_BYTE_LENGTH (18) +#define EDID_DTD_TOTAL_LENGTH (EDID_DTD_BYTE_LENGTH*4) + +#define EDID_DTD_PIXELCLOCK_POS1 (0) +#define EDID_DTD_PIXELCLOCK_POS2 (1) + +#define EDID_DTD_HBLANK_POS1 (3) +#define EDID_DTD_HBLANK_POS2 (4) +#define EDID_DTD_HBLANK_POS2_MASK (0xF) + +#define EDID_DTD_HACTIVE_POS1 (2) +#define EDID_DTD_HACTIVE_POS2 (4) +#define EDID_DTD_HACTIVE_POS2_MASK (0xF0) + +#define EDID_DTD_VBLANK_POS1 (6) +#define EDID_DTD_VBLANK_POS2 (7) +#define EDID_DTD_VBLANK_POS2_MASK (0x0F) + +#define EDID_DTD_VACTIVE_POS1 (5) +#define EDID_DTD_VACTIVE_POS2 (7) +#define EDID_DTD_VACTIVE_POS2_MASK (0xF0) + +#define EDID_DTD_INTERLACE_POS (17) +#define EDID_DTD_INTERLACE_MASK (1<<7) + +// for SVD +#define EDID_SVD_VIC_MASK (0x7F) + +// for CS +#define EDID_COLOR_SPACE_POS (3) +#define EDID_YCBCR444_CS_MASK (1<<5) +#define EDID_YCBCR422_CS_MASK (1<<4) + +// for Color Depth +#define EDID_DC_48_VAL (1<<6) +#define EDID_DC_36_VAL (1<<5) +#define EDID_DC_30_VAL (1<<4) +#define EDID_DC_YCBCR_VAL (1<<3) + +#define EDID_DC_POS (6) +#define EDID_DC_MASK (EDID_DC_48_VAL | EDID_DC_36_VAL| EDID_DC_30_VAL | EDID_DC_YCBCR_VAL) + +// for colorimetry +#define EDID_XVYCC601_MASK (1<<0) +#define EDID_XVYCC709_MASK (1<<1) +#define EDID_EXTENDED_MASK (1<<0|1<<1|1<<2) + +// for SAD +#define SHORT_AUD_DESCRIPTOR_LPCM (1<<0) +#define SHORT_AUD_DESCRIPTOR_AC3 (1<<1) +#define SHORT_AUD_DESCRIPTOR_MPEG1 (1<<2) +#define SHORT_AUD_DESCRIPTOR_MP3 (1<<3) +#define SHORT_AUD_DESCRIPTOR_MPEG2 (1<<4) +#define SHORT_AUD_DESCRIPTOR_AAC (1<<5) +#define SHORT_AUD_DESCRIPTOR_DTS (1<<6) +#define SHORT_AUD_DESCRIPTOR_ATRAC (1<<7) + +#define EDID_SAD_CODE_MASK (1<<6 | 1<<5 | 1<<4 | 1<<3) +#define EDID_SAD_CHANNEL_MASK (1<<2 | 1<<1 | 1<<0) +#define EDID_SAD_192KHZ_MASK (1<<6) +#define EDID_SAD_176KHZ_MASK (1<<5) +#define EDID_SAD_96KHZ_MASK (1<<4) +#define EDID_SAD_88KHZ_MASK (1<<3) +#define EDID_SAD_48KHZ_MASK (1<<2) +#define EDID_SAD_44KHZ_MASK (1<<1) +#define EDID_SAD_32KHZ_MASK (1<<0) + +#define EDID_SAD_WORD_24_MASK (1<<2) +#define EDID_SAD_WORD_20_MASK (1<<1) +#define EDID_SAD_WORD_16_MASK (1<<0) + +// for CEC +#define EDID_CEC_PHYICAL_ADDR (4) + +// for 3D +#define EDID_HDMI_EXT_POS (8) +#define EDID_HDMI_VIDEO_PRESENT_MASK (1<<5) + +// latency +#define EDID_HDMI_LATENCY_MASK (1<<7|1<<6) +#define EDID_HDMI_LATENCY_POS (6) + +#define EDID_HDMI_3D_PRESENT_POS (13) +#define EDID_HDMI_3D_PRESENT_MASK (1<<7) +#define EDID_HDMI_3D_MULTI_PRESENT_MASK (1<<6 | 1<<5) +#define EDID_HDMI_3D_MULTI_PRESENT_BIT 5 + +#define EDID_3D_STRUCTURE_ONLY_EXIST (1<<5) +#define EDID_3D_STRUCTURE_MASK_EXIST (1<<6) + +#define EDID_3D_STRUCTURE_FP (0) +#define EDID_3D_STRUCTURE_FA (1) +#define EDID_3D_STRUCTURE_LA (2) +#define EDID_3D_STRUCTURE_SSF (3) +#define EDID_3D_STRUCTURE_LD (4) +#define EDID_3D_STRUCTURE_LDGFX (5) +#define EDID_3D_STRUCTURE_TB (6) +#define EDID_3D_STRUCTURE_SSH (8) + +#define EDID_HDMI_EXT_LENGTH_POS (14) +#define EDID_HDMI_VSDB_VIC_LEN_BIT (5) +#define EDID_HDMI_VSDB_VIC_LEN_MASK (1<<7|1<<6|1<<5) +#define EDID_HDMI_VSDB_3D_LEN_MASK (1<<4|1<<3|1<<2|1<<1|1<<0) + +#define EDID_HDMI_2D_VIC_ORDER_MASK (1<<7|1<<6|1<<5|1<<4) +#define EDID_HDMI_3D_STRUCTURE_MASK (1<<3|1<<2|1<<1|1<<0) + +// for MAX TMDS +#define EDID_MAX_TMDS_POS (7) + +// for 3D Structure +#define NUM_OF_VIC_FOR_3D 16 +//@} + +#endif /* _EDID_H_ */ diff --git a/exynos4/hal/libhdmi/libsForhdmi/libedid/libedid.c b/exynos4/hal/libhdmi/libsForhdmi/libedid/libedid.c new file mode 100644 index 0000000..c4af587 --- /dev/null +++ b/exynos4/hal/libhdmi/libsForhdmi/libedid/libedid.c @@ -0,0 +1,1262 @@ +/* +* Copyright@ Samsung Electronics Co. LTD +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include +#include +#include + +#include + +#include "edid.h" +#include "libedid.h" +#include "../libddc/libddc.h" + +//#define EDID_DEBUG 1 + +#ifdef EDID_DEBUG +#define DPRINTF(args...) LOGI(args) +#else +#define DPRINTF(args...) +#endif + +#define NUM_OF_VIC_FOR_3D 16 + +/** + * @var gEdidData + * Pointer to EDID data + */ +static unsigned char* gEdidData; + +/** + * @var gExtensions + * Number of EDID extensions + */ +static int gExtensions; + + +/** + * @var aVIC + * This contains first 16 VIC in EDID + */ +static unsigned char aVIC[NUM_OF_VIC_FOR_3D]; + +//! Structure for parsing video timing parameter in EDID +static const struct edid_params { + /** H Total */ + unsigned int HTotal; + + /** H Blank */ + unsigned int HBlank; + + /** V Total */ + unsigned int VTotal; + + /** V Blank */ + unsigned int VBlank; + + /** CEA VIC */ + unsigned char VIC; + + /** CEA VIC for 16:9 aspect ratio */ + unsigned char VIC16_9; + + /** 0 if progressive, 1 if interlaced */ + unsigned char interlaced; + + /** Pixel frequency */ + enum PixelFreq PixelClock; +} aVideoParams[] = +{ + { 800 , 160 , 525 , 45, 1 , 1 , 0, PIXEL_FREQ_25_200 ,}, // v640x480p_60Hz + { 858 , 138 , 525 , 45, 2 , 3 , 0, PIXEL_FREQ_27_027 ,}, // v720x480p_60Hz + { 1650, 370 , 750 , 30, 4 , 4 , 0, PIXEL_FREQ_74_250 ,}, // v1280x720p_60Hz + { 2200, 280 , 1125, 22, 5 , 5 , 1, PIXEL_FREQ_74_250 ,}, // v1920x1080i_60H + { 1716, 276 , 525 , 22, 6 , 7 , 1, PIXEL_FREQ_74_250 ,}, // v720x480i_60Hz + { 1716, 276 , 262 , 22, 8 , 9 , 0, PIXEL_FREQ_27_027 ,}, // v720x240p_60Hz + //{ 1716, 276 , 263 , 23, 8 , 9 , 0, PIXEL_FREQ_27_027 , }, // v720x240p_60Hz(mode 2) + { 3432, 552 , 525 , 22, 10, 11, 1, PIXEL_FREQ_54_054 , }, // v2880x480i_60Hz + { 3432, 552 , 262 , 22, 12, 13, 0, PIXEL_FREQ_54_054 , }, // v2880x240p_60Hz + //{ 3432, 552 , 263 , 23, 12, 13, 0, PIXEL_FREQ_54_054 , }, // v2880x240p_60Hz(mode 2) + { 1716, 276 , 525 , 45, 14, 15, 0, PIXEL_FREQ_54_054 , }, // v1440x480p_60Hz + { 2200, 280 , 1125, 45, 16, 16, 0, PIXEL_FREQ_148_500, }, // v1920x1080p_60H + { 864 , 144 , 625 , 49, 17, 18, 0, PIXEL_FREQ_27 , }, // v720x576p_50Hz + { 1980, 700 , 750 , 30, 19, 19, 0, PIXEL_FREQ_74_250 , }, // v1280x720p_50Hz + { 2640, 720 , 1125, 22, 20, 20, 1, PIXEL_FREQ_74_250 , }, // v1920x1080i_50H + { 1728, 288 , 625 , 24, 21, 22, 1, PIXEL_FREQ_27 , }, // v720x576i_50Hz + { 1728, 288 , 312 , 24, 23, 24, 0, PIXEL_FREQ_27 , }, // v720x288p_50Hz + //{ 1728, 288 , 313 , 25, 23, 24, 0, PIXEL_FREQ_27 , }, // v720x288p_50Hz(mode 2) + //{ 1728, 288 , 314 , 26, 23, 24, 0, PIXEL_FREQ_27 , }, // v720x288p_50Hz(mode 3) + { 3456, 576 , 625 , 24, 25, 26, 1, PIXEL_FREQ_54 , }, // v2880x576i_50Hz + { 3456, 576 , 312 , 24, 27, 28, 0, PIXEL_FREQ_54 , }, // v2880x288p_50Hz + //{ 3456, 576 , 313 , 25, 27, 28, 0, PIXEL_FREQ_54 , }, // v2880x288p_50Hz(mode 2) + //{ 3456, 576 , 314 , 26, 27, 28, 0, PIXEL_FREQ_54 , }, // v2880x288p_50Hz(mode 3) + { 1728, 288 , 625 , 49, 29, 30, 0, PIXEL_FREQ_54 , }, // v1440x576p_50Hz + { 2640, 720 , 1125, 45, 31, 31, 0, PIXEL_FREQ_148_500,}, // v1920x1080p_50Hz + { 2750, 830 , 1125, 45, 32, 32, 0, PIXEL_FREQ_74_250 ,}, // v1920x1080p_24Hz + { 2640, 720 , 1125, 45, 33, 33, 0, PIXEL_FREQ_74_250 ,}, // v1920x1080p_25Hz + { 2200, 280 , 1125, 45, 34, 34, 0, PIXEL_FREQ_74_250 ,}, // v1920x1080p_30Hz + { 3432, 552 , 525 , 45, 35, 36, 0, PIXEL_FREQ_108_108,}, // v2880x480p_60Hz + { 3456, 576 , 625 , 49, 37, 38, 0, PIXEL_FREQ_108 ,}, // v2880x576p_50Hz + { 2304, 384 , 1250, 85, 39, 39, 1, PIXEL_FREQ_72 ,}, // v1920x1080i_50Hz(1250) + { 2640, 720 , 1125, 22, 40, 40, 1, PIXEL_FREQ_148_500, }, // v1920x1080i_100Hz + { 1980, 700 , 750 , 30, 41, 41, 0, PIXEL_FREQ_148_500, }, // v1280x720p_100Hz + { 864 , 144 , 625 , 49, 42, 43, 0, PIXEL_FREQ_54 , }, // v720x576p_100Hz + { 1728, 288 , 625 , 24, 44, 45, 1, PIXEL_FREQ_54 , }, // v720x576i_100Hz + { 2200, 280 , 1125, 22, 46, 46, 1, PIXEL_FREQ_148_500, }, // v1920x1080i_120Hz + { 1650, 370 , 750 , 30, 47, 47, 0, PIXEL_FREQ_148_500, }, // v1280x720p_120Hz + { 858 , 138 , 525 , 54, 48, 49, 0, PIXEL_FREQ_54_054 , }, // v720x480p_120Hz + { 1716, 276 , 525 , 22, 50, 51, 1, PIXEL_FREQ_54_054 , }, // v720x480i_120Hz + { 864 , 144 , 625 , 49, 52, 53, 0, PIXEL_FREQ_108 , }, // v720x576p_200Hz + { 1728, 288 , 625 , 24, 54, 55, 1, PIXEL_FREQ_108 , }, // v720x576i_200Hz + { 858 , 138 , 525 , 45, 56, 57, 0, PIXEL_FREQ_108_108, }, // v720x480p_240Hz + { 1716, 276 , 525 , 22, 58, 59, 1, PIXEL_FREQ_108_108, }, // v720x480i_240Hz + // PHY Freq is not available yet + //{ 3300, 2020, 750 , 30, 60, 60, 0, PIXEL_FREQ_59_400 ,}, // v1280x720p24Hz + { 3960, 2680, 750 , 30, 61, 61, 0, PIXEL_FREQ_74_250 , }, // v1280x720p25Hz + { 3300, 2020, 750 , 30, 62, 62, 0, PIXEL_FREQ_74_250 ,}, // v1280x720p30Hz + // PHY Freq is not available yet + //{ 2200, 280 , 1125, 45, 63, 63, 0, PIXEL_FREQ_297, }, // v1920x1080p120Hz + //{ 2640, 720 , 1125, 45, 64, 64, 0, PIXEL_FREQ_297, }, // v1920x1080p100Hz + //{ 4400, 560 , 2250, 90, 1, 1, 0, 0, PIXEL_FREQ_297, }, // v4Kx2K30Hz +}; + +//! Structure for Checking 3D Mandatory Format in EDID +static const struct edid_3d_mandatory { + /** video Format */ + enum VideoFormat resolution; + + /** 3D Structure */ + enum HDMI3DVideoStructure hdmi_3d_format; +} edid_3d [] = +{ + { v1920x1080p_24Hz, HDMI_3D_FP_FORMAT }, // 1920x1080p @ 23.98/24Hz + { v1280x720p_60Hz, HDMI_3D_FP_FORMAT }, // 1280x720p @ 59.94/60Hz + { v1920x1080i_60Hz, HDMI_3D_SSH_FORMAT }, // 1920x1080i @ 59.94/60Hz + { v1920x1080p_24Hz, HDMI_3D_TB_FORMAT }, // 1920x1080p @ 23.98/24Hz + { v1280x720p_60Hz, HDMI_3D_TB_FORMAT }, // 1280x720p @ 59.94/60Hz + { v1280x720p_50Hz, HDMI_3D_FP_FORMAT }, // 1280x720p @ 50Hz + { v1920x1080i_50Hz, HDMI_3D_SSH_FORMAT }, // 1920x1080i @ 50Hz + { v1280x720p_50Hz, HDMI_3D_TB_FORMAT }, // 1280x720p @ 50Hz +}; + +/** + * Calculate a checksum. + * + * @param buffer [in] Pointer to data to calculate a checksum + * @param size [in] Sizes of data + * + * @return If checksum result is 0, return 1; Otherwise, return 0. + */ +static int CalcChecksum(const unsigned char* const buffer, const int size) +{ + unsigned char i,sum; + int ret = 1; + + // check parameter + if (buffer == NULL ) { + DPRINTF("invalid parameter : buffer\n"); + return 0; + } + for (sum = 0, i = 0 ; i < size; i++) + sum += buffer[i]; + + // check checksum + if (sum != 0) + ret = 0; + + return ret; +} + +/** + * Read EDID Block(128 bytes) + * + * @param blockNum [in] Number of block to read @n + * For example, EDID block = 0, EDID first Extension = 1, and so on. + * @param outBuffer [out] Pointer to buffer to store EDID data + * + * @return If fail to read, return 0; Otherwise, return 1. + */ +static int ReadEDIDBlock(const unsigned int blockNum, unsigned char* const outBuffer) +{ + int segNum, offset, dataPtr; + + // check parameter + if (outBuffer == NULL) { + DPRINTF("invalid parameter : outBuffer\n"); + return 0; + } + + // calculate + segNum = blockNum / 2; + offset = (blockNum % 2) * SIZEOFEDIDBLOCK; + dataPtr = (blockNum) * SIZEOFEDIDBLOCK; + + // read block + if (!EDDCRead(EDID_SEGMENT_POINTER, segNum, EDID_ADDR, offset, SIZEOFEDIDBLOCK, outBuffer)) { + DPRINTF("Fail to Read %dth EDID Block\n", blockNum); + return 0; + } + + if (!CalcChecksum(outBuffer, SIZEOFEDIDBLOCK)) { + DPRINTF("CheckSum fail : %dth EDID Block\n", blockNum); + return 0; + } + + // print data +#ifdef EDID_DEBUG + offset = 0; + do { + LOGI("0x%02X", outBuffer[offset++]); + if (offset % 16) + LOGI(" "); + else + LOGI("\n"); + } while (SIZEOFEDIDBLOCK > offset); +#endif // EDID_DEBUG + return 1; +} + +/** + * Check if EDID data is valid or not. + * + * @return if EDID data is valid, return 1; Otherwise, return 0. + */ +static inline int EDIDValid(void) +{ + return (gEdidData == NULL) ? 0 : 1; +} + +/** + * Search HDMI Vender Specific Data Block(VSDB) in EDID extension block. + * + * @param extension [in] the number of EDID extension block to check + * + * @return if there is a HDMI VSDB, return the offset from start of @n + * EDID extension block. if there is no VSDB, return 0. + */ +static int GetVSDBOffset(const int extension) +{ + unsigned int BlockOffset = extension*SIZEOFEDIDBLOCK; + unsigned int offset = BlockOffset + EDID_DATA_BLOCK_START_POS; + unsigned int tag,blockLen,DTDOffset; + + if (!EDIDValid() || (extension > gExtensions)) { + DPRINTF("EDID Data is not available\n"); + return 0; + } + + DTDOffset = gEdidData[BlockOffset + EDID_DETAILED_TIMING_OFFSET_POS]; + + // check if there is HDMI VSDB + while (offset < BlockOffset + DTDOffset) { + // find the block tag and length + // tag + tag = gEdidData[offset] & EDID_TAG_CODE_MASK; + // block len + blockLen = (gEdidData[offset] & EDID_DATA_BLOCK_SIZE_MASK) + 1; + + // check if it is HDMI VSDB + // if so, check identifier value, if it's hdmi vsbd - return offset + if (tag == EDID_VSDB_TAG_VAL && + gEdidData[offset+1] == 0x03 && + gEdidData[offset+2] == 0x0C && + gEdidData[offset+3] == 0x0 && + blockLen > EDID_VSDB_MIN_LENGTH_VAL ) + return offset; + + // else find next block + offset += blockLen; + } + + // return error + return 0; +} + +/** + * Check if Sink supports the HDMI mode. + * @return If Sink supports HDMI mode, return 1; Otherwise, return 0. + */ +static int CheckHDMIMode(void) +{ + int i; + + // read EDID + if (!EDIDRead()) + return 0; + + // find VSDB + for (i = 1; i <= gExtensions; i++) + if (GetVSDBOffset(i) > 0) // if there is a VSDB, it means RX support HDMI mode + return 1; + + return 0; +} + +/** + * Check if EDID extension block is timing extension block or not. + * @param extension [in] The number of EDID extension block to check + * @return If the block is timing extension, return 1; Otherwise, return 0. + */ +static int IsTimingExtension(const int extension) +{ + int ret = 0; + if (!EDIDValid() || (extension > gExtensions)) { + DPRINTF("EDID Data is not available\n"); + return ret; + } + + if (gEdidData[extension*SIZEOFEDIDBLOCK] == EDID_TIMING_EXT_TAG_VAL) { + // check extension revsion number + // revision num == 3 + if (gEdidData[extension*SIZEOFEDIDBLOCK + EDID_TIMING_EXT_REV_NUMBER_POS] == 3) + ret = 1; + // revison num != 3 && DVI mode + else if (!CheckHDMIMode() && + gEdidData[extension*SIZEOFEDIDBLOCK + EDID_TIMING_EXT_REV_NUMBER_POS] != 2) + ret = 1; + } + return ret; +} + +/** + * Check if the video format is contained in - @n + * Detailed Timing Descriptor(DTD) of EDID extension block. + * @param extension [in] Number of EDID extension block to check + * @param videoFormat [in] Video format to check + * @return If the video format is contained in DTD of EDID extension block, -@n + * return 1; Otherwise, return 0. + */ +static int IsContainVideoDTD(const int extension,const enum VideoFormat videoFormat) +{ + int i, StartOffset, EndOffset; + + if (!EDIDValid() || (extension > gExtensions)) { + DPRINTF("EDID Data is not available\n"); + return 0; + } + + // if edid block( 0th block ) + if (extension == 0) { + StartOffset = EDID_DTD_START_ADDR; + EndOffset = StartOffset + EDID_DTD_TOTAL_LENGTH; + } else { // if edid extension block + StartOffset = extension*SIZEOFEDIDBLOCK + gEdidData[extension*SIZEOFEDIDBLOCK + EDID_DETAILED_TIMING_OFFSET_POS]; + EndOffset = (extension+1)*SIZEOFEDIDBLOCK; + } + + // check DTD(Detailed Timing Description) + for (i = StartOffset; i < EndOffset; i+= EDID_DTD_BYTE_LENGTH) { + unsigned int hblank = 0, hactive = 0, vblank = 0, vactive = 0, interlaced = 0, pixelclock = 0; + unsigned int vHActive = 0, vVActive = 0, vVBlank = 0; + + // get pixel clock + pixelclock = (gEdidData[i+EDID_DTD_PIXELCLOCK_POS2] << SIZEOFBYTE); + pixelclock |= gEdidData[i+EDID_DTD_PIXELCLOCK_POS1]; + + if (!pixelclock) + continue; + + // get HBLANK value in pixels + hblank = gEdidData[i+EDID_DTD_HBLANK_POS2] & EDID_DTD_HBLANK_POS2_MASK; + hblank <<= SIZEOFBYTE; // lower 4 bits + hblank |= gEdidData[i+EDID_DTD_HBLANK_POS1]; + + // get HACTIVE value in pixels + hactive = gEdidData[i+EDID_DTD_HACTIVE_POS2] & EDID_DTD_HACTIVE_POS2_MASK; + hactive <<= (SIZEOFBYTE/2); // upper 4 bits + hactive |= gEdidData[i+EDID_DTD_HACTIVE_POS1]; + + // get VBLANK value in pixels + vblank = gEdidData[i+EDID_DTD_VBLANK_POS2] & EDID_DTD_VBLANK_POS2_MASK; + vblank <<= SIZEOFBYTE; // lower 4 bits + vblank |= gEdidData[i+EDID_DTD_VBLANK_POS1]; + + // get VACTIVE value in pixels + vactive = gEdidData[i+EDID_DTD_VACTIVE_POS2] & EDID_DTD_VACTIVE_POS2_MASK; + vactive <<= (SIZEOFBYTE/2); // upper 4 bits + vactive |= gEdidData[i+EDID_DTD_VACTIVE_POS1]; + + vHActive = aVideoParams[videoFormat].HTotal - aVideoParams[videoFormat].HBlank; + if (aVideoParams[videoFormat].interlaced == 1) { + if (aVideoParams[videoFormat].VIC == v1920x1080i_50Hz_1250) { // VTOP and VBOT are same + vVActive = (aVideoParams[videoFormat].VTotal - aVideoParams[videoFormat].VBlank*2)/2; + vVBlank = aVideoParams[videoFormat].VBlank; + } else { + vVActive = (aVideoParams[videoFormat].VTotal - aVideoParams[videoFormat].VBlank*2 - 1)/2; + vVBlank = aVideoParams[videoFormat].VBlank; + } + } else { + vVActive = aVideoParams[videoFormat].VTotal - aVideoParams[videoFormat].VBlank; + vVBlank = aVideoParams[videoFormat].VBlank; + } + + // get Interlaced Mode Value + interlaced = (int)(gEdidData[i+EDID_DTD_INTERLACE_POS] & EDID_DTD_INTERLACE_MASK); + if (interlaced) + interlaced = 1; + + DPRINTF("EDID: hblank = %d,vblank = %d, hactive = %d, vactive = %d\n" + ,hblank,vblank,hactive,vactive); + DPRINTF("REQ: hblank = %d,vblank = %d, hactive = %d, vactive = %d\n" + ,aVideoParams[videoFormat].HBlank + ,vVBlank,vHActive,vVActive); + + if (hblank == aVideoParams[videoFormat].HBlank && vblank == vVBlank // blank + && hactive == vHActive && vactive == vVActive) { //line + unsigned int EDIDpixelclock = aVideoParams[videoFormat].PixelClock; + EDIDpixelclock /= 100; pixelclock /= 100; + + if (pixelclock == EDIDpixelclock) { + DPRINTF("Sink Support the Video mode\n"); + return 1; + } + } + } + return 0; +} + +/** + * Check if a VIC(Video Identification Code) is contained in -@n + * EDID extension block. + * @param extension [in] Number of EDID extension block to check + * @param VIC [in] VIC to check + * @return If the VIC is contained in contained in EDID extension block, -@n + * return 1; Otherwise, return 0. + */ +static int IsContainVIC(const int extension, const int VIC) +{ + unsigned int StartAddr = extension*SIZEOFEDIDBLOCK; + unsigned int ExtAddr = StartAddr + EDID_DATA_BLOCK_START_POS; + unsigned int tag,blockLen; + unsigned int DTDStartAddr = gEdidData[StartAddr + EDID_DETAILED_TIMING_OFFSET_POS]; + + if (!EDIDValid() || (extension > gExtensions)) { + DPRINTF("EDID Data is not available\n"); + return 0; + } + + // while + while (ExtAddr < StartAddr + DTDStartAddr) { + // find the block tag and length + // tag + tag = gEdidData[ExtAddr] & EDID_TAG_CODE_MASK; + // block len + blockLen = (gEdidData[ExtAddr] & EDID_DATA_BLOCK_SIZE_MASK) + 1; + DPRINTF("tag = %d\n",tag); + DPRINTF("blockLen = %d\n",blockLen-1); + + // check if it is short video description + if (tag == EDID_SHORT_VID_DEC_TAG_VAL) { + // if so, check SVD + unsigned int i; + for (i = 1; i < blockLen; i++) { + DPRINTF("EDIDVIC = %d\n",gEdidData[ExtAddr+i] & EDID_SVD_VIC_MASK); + DPRINTF("VIC = %d\n",VIC); + + // check VIC with SVDB + if (VIC == (gEdidData[ExtAddr+i] & EDID_SVD_VIC_MASK)) { + DPRINTF("Sink Device supports requested video mode\n"); + return 1; + } + } + } + // else find next block + ExtAddr += blockLen; + } + + return 0; +} + +/** + * Check if EDID contains the video format. + * @param videoFormat [in] Video format to check + * @param pixelRatio [in] Pixel aspect ratio of video format to check + * @return if EDID contains the video format, return 1; Otherwise, return 0. + */ +static int CheckResolution(const enum VideoFormat videoFormat, + const enum PixelAspectRatio pixelRatio) +{ + int i, vic; + + // read EDID + if (!EDIDRead()) + return 0; + + // check ET(Established Timings) for 640x480p@60Hz + if (videoFormat == v640x480p_60Hz // if it's 640x480p@60Hz + && (gEdidData[EDID_ET_POS] & EDID_ET_640x480p_VAL)) // it support + return 1; + + // check STI(Standard Timing Identification) + // do not need + + // check DTD(Detailed Timing Description) of EDID block(0th) + if (IsContainVideoDTD(0,videoFormat)) + return 1; + + // check EDID Extension + vic = (pixelRatio == HDMI_PIXEL_RATIO_16_9) ? + aVideoParams[videoFormat].VIC16_9 : aVideoParams[videoFormat].VIC; + + // find VSDB + for (i = 1; i <= gExtensions; i++) { + if (IsTimingExtension(i)) // if it's timing block + if (IsContainVIC(i, vic) || IsContainVideoDTD(i, videoFormat)) + return 1; + } + + return 0; +} + +/** + * Check if EDID supports the color depth. + * @param depth [in] Color depth + * @param space [in] Color space + * @return If EDID supports the color depth, return 1; Otherwise, return 0. + */ +static int CheckColorDepth(const enum ColorDepth depth,const enum ColorSpace space) +{ + int i; + unsigned int StartAddr; + + // if color depth == 24 bit, no need to check + if (depth == HDMI_CD_24) + return 1; + + // check EDID data is valid or not + // read EDID + if (!EDIDRead()) + return 0; + + // find VSDB + for (i = 1; i <= gExtensions; i++) { + if (IsTimingExtension(i) // if it's timing block + && ((StartAddr = GetVSDBOffset(i)) > 0)) { // check block + int blockLength = gEdidData[StartAddr] & EDID_DATA_BLOCK_SIZE_MASK; + if (blockLength >= EDID_DC_POS) { + // get supported DC value + int deepColor = gEdidData[StartAddr + EDID_DC_POS] & EDID_DC_MASK; + DPRINTF("EDID deepColor = %x\n",deepColor); + // check supported DeepColor + // if YCBCR444 + if (space == HDMI_CS_YCBCR444) { + if ( !(deepColor & EDID_DC_YCBCR_VAL)) + return 0; + } + + // check colorDepth + switch (depth) { + case HDMI_CD_36: + deepColor &= EDID_DC_36_VAL; + break; + case HDMI_CD_30: + deepColor &= EDID_DC_30_VAL; + break; + default : + deepColor = 0; + } + if (deepColor) + return 1; + else + return 0; + } + } + } + + return 0; +} + +/** + * Check if EDID supports the color space. + * @param space [in] Color space + * @return If EDID supports the color space, return 1; Otherwise, return 0. + */ +static int CheckColorSpace(const enum ColorSpace space) +{ + int i; + + // RGB is default + if (space == HDMI_CS_RGB) + return 1; + + // check EDID data is valid or not + // read EDID + if (!EDIDRead()) + return 0; + + // find VSDB + for (i = 1; i <= gExtensions; i++) { + if (IsTimingExtension(i)) { // if it's timing block + // read Color Space + int CS = gEdidData[i*SIZEOFEDIDBLOCK + EDID_COLOR_SPACE_POS]; + + if ((space == HDMI_CS_YCBCR444 && (CS & EDID_YCBCR444_CS_MASK)) || // YCBCR444 + (space == HDMI_CS_YCBCR422 && (CS & EDID_YCBCR422_CS_MASK))) // YCBCR422 + return 1; + } + } + return 0; +} + +/** + * Check if EDID supports the colorimetry. + * @param color [in] Colorimetry + * @return If EDID supports the colorimetry, return 1; Otherwise, return 0. + */ +static int CheckColorimetry(const enum HDMIColorimetry color) +{ + int i; + + // do not need to parse if not extended colorimetry + if (color == HDMI_COLORIMETRY_NO_DATA || + color == HDMI_COLORIMETRY_ITU601 || + color == HDMI_COLORIMETRY_ITU709) + return 1; + + // read EDID + if (!EDIDRead()) + return 0; + + // find VSDB + for (i = 1; i <= gExtensions; i++) { + if (IsTimingExtension(i)) { // if it's timing block + // check address + unsigned int ExtAddr = i*SIZEOFEDIDBLOCK + EDID_DATA_BLOCK_START_POS; + unsigned int EndAddr = i*SIZEOFEDIDBLOCK + gEdidData[i*SIZEOFEDIDBLOCK + EDID_DETAILED_TIMING_OFFSET_POS]; + unsigned int tag,blockLen; + + while (ExtAddr < EndAddr) { + // find the block tag and length + // tag + tag = gEdidData[ExtAddr] & EDID_TAG_CODE_MASK; + // block len + blockLen = (gEdidData[ExtAddr] & EDID_DATA_BLOCK_SIZE_MASK) + 1; + + // check if it is colorimetry block + if (tag == EDID_EXTENDED_TAG_VAL && // extended tag + gEdidData[ExtAddr+1] == EDID_EXTENDED_COLORIMETRY_VAL && // colorimetry block + (blockLen-1) == EDID_EXTENDED_COLORIMETRY_BLOCK_LEN) { // check length + // get supported DC value + int colorimetry = (gEdidData[ExtAddr + 2]); + int metadata = (gEdidData[ExtAddr + 3]); + + DPRINTF("EDID extened colorimetry = %x\n",colorimetry); + DPRINTF("EDID gamut metadata profile = %x\n",metadata); + + // check colorDepth + switch (color) { + case HDMI_COLORIMETRY_EXTENDED_xvYCC601: + if (colorimetry & EDID_XVYCC601_MASK && metadata) + return 1; + break; + case HDMI_COLORIMETRY_EXTENDED_xvYCC709: + if (colorimetry & EDID_XVYCC709_MASK && metadata) + return 1; + break; + default: + break; + } + return 0; + } + // else find next block + ExtAddr += blockLen; + } + } + } + + return 0; +} + +/** + * Get Max TMDS clock that HDMI Rx can receive. + * @return If available, return MaxTMDS clock; Otherwise, return 0. + */ +static unsigned int GetMaxTMDS(void) +{ + int i; + unsigned int StartAddr; + + // find VSDB + for (i = 1; i <= gExtensions; i++) { + if (IsTimingExtension(i) // if it's timing block + && ((StartAddr = GetVSDBOffset(i)) > 0)) { // check block + int blockLength = gEdidData[StartAddr] & EDID_DATA_BLOCK_SIZE_MASK; + if (blockLength >= EDID_MAX_TMDS_POS) { + // get supported DC value + return gEdidData[StartAddr + EDID_MAX_TMDS_POS]; + } + } + } + + return 0; +} + +/** + * Save first 16 VIC of EDID + */ +static void SaveVIC(void) +{ + int extension; + int vic_count = 0; + for (extension = 1; extension <= gExtensions && vic_count < NUM_OF_VIC_FOR_3D; extension++) { + unsigned int StartAddr = extension*SIZEOFEDIDBLOCK; + unsigned int ExtAddr = StartAddr + EDID_DATA_BLOCK_START_POS; + unsigned int tag,blockLen; + unsigned int DTDStartAddr = gEdidData[StartAddr + EDID_DETAILED_TIMING_OFFSET_POS]; + + while (ExtAddr < StartAddr + DTDStartAddr) { + // find the block tag and length + // tag + tag = gEdidData[ExtAddr] & EDID_TAG_CODE_MASK; + // block len + blockLen = (gEdidData[ExtAddr] & EDID_DATA_BLOCK_SIZE_MASK) + 1; + + // check if it is short video description + if (tag == EDID_SHORT_VID_DEC_TAG_VAL) { + // if so, check SVD + unsigned int edid_index; + for (edid_index = 1; edid_index < blockLen && vic_count < NUM_OF_VIC_FOR_3D; edid_index++) { + DPRINTF("EDIDVIC = %d\r\n", gEdidData[ExtAddr+edid_index] & EDID_SVD_VIC_MASK); + + // check VIC with SVDB + aVIC[vic_count++] = (gEdidData[ExtAddr+edid_index] & EDID_SVD_VIC_MASK); + } + } + // else find next block + ExtAddr += blockLen; + } + } +} + +/** + * Check if Rx supports requested 3D format. + * @param pVideo [in] HDMI Video Parameter + * @return If Rx supports requested 3D format, return 1; Otherwise, return 0. + */ +static int EDID3DFormatSupport(const struct HDMIVideoParameter * const pVideo) +{ + int edid_index; + unsigned int StartAddr; + unsigned int vic; + vic = (pVideo->pixelAspectRatio == HDMI_PIXEL_RATIO_16_9) ? + aVideoParams[pVideo->resolution].VIC16_9 : aVideoParams[pVideo->resolution].VIC; + + // if format == 2D, no need to check + if (pVideo->hdmi_3d_format == HDMI_2D_VIDEO_FORMAT) + return 1; + + // check EDID data is valid or not + if (!EDIDRead()) + return 0; + + // save first 16 VIC to check + SaveVIC(); + + // find VSDB + for (edid_index = 1; edid_index <= gExtensions; edid_index++) { + if (IsTimingExtension(edid_index) // if it's timing block + && ((StartAddr = GetVSDBOffset(edid_index)) > 0)) { // check block + unsigned int blockLength = gEdidData[StartAddr] & EDID_DATA_BLOCK_SIZE_MASK; + unsigned int VSDBHdmiVideoPre = 0; + unsigned int VSDB3DPresent = 0; + unsigned int VSDB3DMultiPresent = 0; + unsigned int HDMIVICLen; + unsigned int HDMI3DLen; + int Hdmi3DStructure = 0; + unsigned int Hdmi3DMask = 0xFFFF; + unsigned int latency_offset = 0; + + DPRINTF("VSDB Block length[0x%x] = 0x%x\r\n",StartAddr,blockLength); + + // get HDMI Video Present value + if (blockLength >= EDID_HDMI_EXT_POS) { + VSDBHdmiVideoPre = gEdidData[StartAddr + EDID_HDMI_EXT_POS] + & EDID_HDMI_VIDEO_PRESENT_MASK; + DPRINTF("EDID HDMI Video Present = 0x%x\n",VSDBHdmiVideoPre); + } else { // data related to 3D format is not available + return 0; + } + + // check if latency field is available + latency_offset = (gEdidData[StartAddr + EDID_HDMI_EXT_POS] + & EDID_HDMI_LATENCY_MASK) >> EDID_HDMI_LATENCY_POS; + if (latency_offset == 0) + latency_offset = 4; + else if (latency_offset == 3) + latency_offset = 0; + else + latency_offset = 2; + + StartAddr -= latency_offset; + + // HDMI_VIC_LEN + HDMIVICLen = (gEdidData[StartAddr + EDID_HDMI_EXT_LENGTH_POS] + & EDID_HDMI_VSDB_VIC_LEN_MASK) >> EDID_HDMI_VSDB_VIC_LEN_BIT; + + if (pVideo->hdmi_3d_format == HDMI_VIC_FORMAT) { + if (HDMIVICLen) { + for (edid_index = 0; edid_index < (int)HDMIVICLen; edid_index++) { + if (vic == gEdidData[StartAddr + EDID_HDMI_EXT_LENGTH_POS + edid_index]) + return 1; + } + return 0; + } else { + return 0; + } + } + + // HDMI_3D_LEN + HDMI3DLen = gEdidData[StartAddr + EDID_HDMI_EXT_LENGTH_POS] + & EDID_HDMI_VSDB_3D_LEN_MASK; + + DPRINTF("HDMI VIC LENGTH[%x] = %x\r\n", + StartAddr + EDID_HDMI_EXT_LENGTH_POS, HDMIVICLen); + DPRINTF("HDMI 3D LENGTH[%x] = %x\r\n", + StartAddr + EDID_HDMI_EXT_LENGTH_POS, HDMI3DLen); + + // check 3D_Present bit + if (blockLength >= (EDID_HDMI_3D_PRESENT_POS - latency_offset)) { + VSDB3DPresent = gEdidData[StartAddr + EDID_HDMI_3D_PRESENT_POS] + & EDID_HDMI_3D_PRESENT_MASK; + VSDB3DMultiPresent = gEdidData[StartAddr + EDID_HDMI_3D_PRESENT_POS] + & EDID_HDMI_3D_MULTI_PRESENT_MASK; + } + + if (VSDB3DPresent) { + DPRINTF("VSDB 3D Present!!!\r\n"); + // check with 3D madatory format + if (CheckResolution(pVideo->resolution, pVideo->pixelAspectRatio)) { + int size = sizeof(edid_3d)/sizeof(struct edid_3d_mandatory); + for (edid_index = 0; edid_index < size; edid_index++) { + if (edid_3d[edid_index].resolution == pVideo->resolution && + edid_3d[edid_index].hdmi_3d_format == pVideo->hdmi_3d_format ) + return 1; + } + } + } + + // check 3D_Multi_Present bit + if (VSDB3DMultiPresent) { + DPRINTF("VSDB 3D Multi Present!!! = 0x%02x\r\n",VSDB3DMultiPresent); + // 3D Structure only + if (VSDB3DMultiPresent == EDID_3D_STRUCTURE_ONLY_EXIST) { + // 3D Structure All + Hdmi3DStructure = (gEdidData[StartAddr + EDID_HDMI_EXT_LENGTH_POS + HDMIVICLen + 1] << 8); + Hdmi3DStructure |= gEdidData[StartAddr + EDID_HDMI_EXT_LENGTH_POS + HDMIVICLen + 2]; + DPRINTF("VSDB 3D Structure!!! = [0x%02x]\r\n",Hdmi3DStructure); + } + + // 3D Structure and Mask + if (VSDB3DMultiPresent == EDID_3D_STRUCTURE_MASK_EXIST) { + // 3D Structure All + Hdmi3DStructure = (gEdidData[StartAddr + EDID_HDMI_EXT_LENGTH_POS + HDMIVICLen + 1] << 8); + Hdmi3DStructure |= gEdidData[StartAddr + EDID_HDMI_EXT_LENGTH_POS + HDMIVICLen + 2]; + // 3D Structure Mask + Hdmi3DMask |= (gEdidData[StartAddr + EDID_HDMI_EXT_LENGTH_POS + HDMIVICLen + 3] << 8); + Hdmi3DMask |= gEdidData[StartAddr + EDID_HDMI_EXT_LENGTH_POS + HDMIVICLen + 4]; + DPRINTF("VSDB 3D Structure!!! = [0x%02x]\r\n",Hdmi3DStructure); + DPRINTF("VSDB 3D Mask!!! = [0x%02x]\r\n",Hdmi3DMask); + DPRINTF("Current 3D Video format!!! = [%d]\r\n",pVideo->hdmi_3d_format); + DPRINTF("Current 3D Video format!!! = [0x%02x]\r\n",1<hdmi_3d_format); + } + + // check 3D Structure and Mask + if (Hdmi3DStructure & (1<hdmi_3d_format)) { + DPRINTF("VSDB 3D Structure Contains Current Video Structure!!!\r\n"); + // check first 16 EDID + for (edid_index = 0; edid_index < NUM_OF_VIC_FOR_3D; edid_index++) { + DPRINTF("VIC = %d, EDID Vic = %d!!!\r\n",vic,aVIC[edid_index]); + if (Hdmi3DMask & (1<= (EDID_HDMI_EXT_LENGTH_POS - latency_offset)) { + unsigned int HDMI3DExtLen = HDMI3DLen - (VSDB3DMultiPresent>>EDID_HDMI_3D_MULTI_PRESENT_BIT)*2; + unsigned int VICOrder; + + // check if there is 3D extra data ? + //TODO: check 3D_Detail in case of SSH + if (HDMI3DExtLen) { + // check HDMI 3D Extra Data + for (edid_index = 0; edid_index < (int)(HDMI3DExtLen / 2); edid_index++) { + VICOrder = gEdidData[StartAddr + EDID_HDMI_EXT_LENGTH_POS + HDMIVICLen + + (VSDB3DMultiPresent>>EDID_HDMI_3D_MULTI_PRESENT_BIT) * 2 + edid_index * 2] + & EDID_HDMI_2D_VIC_ORDER_MASK; + VICOrder = (1<>EDID_HDMI_3D_MULTI_PRESENT_BIT) * 2 + edid_index * 2] + & EDID_HDMI_3D_STRUCTURE_MASK; + Hdmi3DStructure = (1<hdmi_3d_format && vic == aVIC[VICOrder]) + return 1; + } + } + } + } + } + + return 0; +} + +/** + * Initialize EDID library. This will intialize DDC library. + * @return If success, return 1; Otherwise, return 0. + */ +int EDIDOpen(void) +{ + // init DDC + return DDCOpen(); +} + +/** + * Finalize EDID library. This will finalize DDC library. + * @return If success, return 1; Otherwise, return 0. + */ +int EDIDClose(void) +{ + // reset EDID + EDIDReset(); + + // close EDDC + return DDCClose(); +} + +/** + * Read EDID data of Rx. + * @return If success, return 1; Otherwise, return 0; + */ +int EDIDRead(void) +{ + int block,dataPtr; + unsigned char temp[SIZEOFEDIDBLOCK]; + + // if already read?? + if (EDIDValid()) + return 1; + + // read EDID Extension Number + // read EDID + if (!ReadEDIDBlock(0,temp)) + return 0; + + // get extension + gExtensions = temp[EDID_EXTENSION_NUMBER_POS]; + + // prepare buffer + gEdidData = (unsigned char*)malloc((gExtensions+1)*SIZEOFEDIDBLOCK); + if (!gEdidData) + return 0; + + // copy EDID Block 0 + memcpy(gEdidData,temp,SIZEOFEDIDBLOCK); + + // read EDID Extension + for (block = 1,dataPtr = SIZEOFEDIDBLOCK; block <= gExtensions; block++,dataPtr+=SIZEOFEDIDBLOCK) { + // read extension 1~gExtensions + if (!ReadEDIDBlock(block, gEdidData+dataPtr)) { + // reset buffer + EDIDReset(); + return 0; + } + } + + // check if extension is more than 1, and first extension block is not block map. + if (gExtensions > 1 && gEdidData[SIZEOFEDIDBLOCK] != EDID_BLOCK_MAP_EXT_TAG_VAL) { + // reset buffer + DPRINTF("EDID has more than 1 extension but, first extension block is not block map\n"); + EDIDReset(); + return 0; + } + + return 1; +} + +/** + * Reset stored EDID data. + */ +void EDIDReset(void) +{ + if (gEdidData) { + free(gEdidData); + gEdidData = NULL; + DPRINTF("\t\t\t\tEDID is reset!!!\n"); + } +} + +/** + * Get CEC physical address. + * @param outAddr [out] CEC physical address. LSB 2 bytes is available. [0:0:AB:CD] + * @return If success, return 1; Otherwise, return 0. + */ +int EDIDGetCECPhysicalAddress(int* const outAddr) +{ + int i; + unsigned int StartAddr; + + // check EDID data is valid or not + // read EDID + if (!EDIDRead()) + return 0; + + // find VSDB + for (i = 1; i <= gExtensions; i++) { + if (IsTimingExtension(i) // if it's timing block + && (StartAddr = GetVSDBOffset(i)) > 0) { // check block + // get supported DC value + // int tempDC1 = (int)(gEdidData[tempAddr+EDID_DC_POS]); + int phyAddr = gEdidData[StartAddr + EDID_CEC_PHYICAL_ADDR] << 8; + phyAddr |= gEdidData[StartAddr + EDID_CEC_PHYICAL_ADDR+1]; + + DPRINTF("phyAddr = %x\n",phyAddr); + + *outAddr = phyAddr; + + return 1; + } + } + + return 0; +} + +/** + * Check if Rx supports HDMI/DVI mode or not. + * @param video [in] HDMI or DVI mode to check + * @return If Rx supports requested mode, return 1; Otherwise, return 0. + */ +int EDIDHDMIModeSupport(struct HDMIVideoParameter * const video) +{ + // check if read edid? + if (!EDIDRead()) { + DPRINTF("EDID Read Fail!!!\n"); + return 0; + } + + // check hdmi mode + if (video->mode == HDMI) { + if (!CheckHDMIMode()) { + DPRINTF("HDMI mode Not Supported\n"); + return 0; + } + } + return 1; +} + +/** + * Check if Rx supports requested video resoultion or not. + * @param video [in] Video parameters to check + * @return If Rx supports video parameters, return 1; Otherwise, return 0. + */ +int EDIDVideoResolutionSupport(struct HDMIVideoParameter * const video) +{ + unsigned int TMDSClock; + unsigned int MaxTMDS = 0; + + // check if read edid? + if (!EDIDRead()) { + DPRINTF("EDID Read Fail!!!\n"); + return 0; + } + + // get max tmds + MaxTMDS = GetMaxTMDS()*5; + + // Check MAX TMDS + TMDSClock = aVideoParams[video->resolution].PixelClock/100; + if (video->colorDepth == HDMI_CD_36) + TMDSClock *= 1.5; + else if (video->colorDepth == HDMI_CD_30) + TMDSClock *=1.25; + + DPRINTF("MAX TMDS = %d, Current TMDS = %d\n",MaxTMDS, TMDSClock); + if (MaxTMDS != 0 && MaxTMDS < TMDSClock) { + DPRINTF("Pixel clock is beyond Maximun TMDS in EDID\n"); + return 0; + } + + // check resolution + if (!CheckResolution(video->resolution,video->pixelAspectRatio)) { + DPRINTF("Video Resolution Not Supported\n"); + return 0; + } + + // check 3D format + if (!EDID3DFormatSupport(video)) { + DPRINTF("3D Format Not Supported\n"); + return 0; + } + + return 1; +} + +/** + * Check if Rx supports requested color depth or not. + * @param video [in] Video parameters to check + * @return If Rx supports video parameters, return 1; Otherwise, return 0. + */ +int EDIDColorDepthSupport(struct HDMIVideoParameter * const video) +{ + // check if read edid? + if (!EDIDRead()) { + DPRINTF("EDID Read Fail!!!\n"); + return 0; + } + + // check resolution + if (!CheckColorDepth(video->colorDepth,video->colorSpace)) { + DPRINTF("Color Depth Not Supported\n"); + return 0; + } + + return 1; +} + +/** + * Check if Rx supports requested color space or not. + * @param video [in] Video parameters to check + * @return If Rx supports video parameters, return 1; Otherwise, return 0. + */ +int EDIDColorSpaceSupport(struct HDMIVideoParameter * const video) +{ + // check if read edid? + if (!EDIDRead()) { + DPRINTF("EDID Read Fail!!!\n"); + return 0; + } + // check color space + if (!CheckColorSpace(video->colorSpace)) { + DPRINTF("Color Space Not Supported\n"); + return 0; + } + + return 1; +} + +/** + * Check if Rx supports requested colorimetry or not. + * @param video [in] Video parameters to check + * @return If Rx supports video parameters, return 1; Otherwise, return 0. + */ +int EDIDColorimetrySupport(struct HDMIVideoParameter * const video) +{ + // check if read edid? + if (!EDIDRead()) { + DPRINTF("EDID Read Fail!!!\n"); + return 0; + } + + // check colorimetry + if (!CheckColorimetry(video->colorimetry)) { + DPRINTF("Colorimetry Not Supported\n"); + return 0; + } + + return 1; +} + +/** + * Check if Rx supports requested audio parameters or not. + * @param audio [in] Audio parameters to check + * @return If Rx supports audio parameters, return 1; Otherwise, return 0. + */ +int EDIDAudioModeSupport(struct HDMIAudioParameter * const audio) +{ + int i; + + // read EDID + if (!EDIDRead()) { + DPRINTF("EDID Read Fail!!!\n"); + return 0; + } + + // check EDID Extension + // find timing block + for (i = 1; i <= gExtensions; i++) { + if (IsTimingExtension(i)) { // if it's timing block + // find Short Audio Description + unsigned int StartAddr = i*SIZEOFEDIDBLOCK; + unsigned int ExtAddr = StartAddr + EDID_DATA_BLOCK_START_POS; + unsigned int tag,blockLen; + unsigned int DTDStartAddr = gEdidData[StartAddr + EDID_DETAILED_TIMING_OFFSET_POS]; + + while (ExtAddr < StartAddr + DTDStartAddr) { + // find the block tag and length + // tag + tag = gEdidData[ExtAddr] & EDID_TAG_CODE_MASK; + // block len + blockLen = (gEdidData[ExtAddr] & EDID_DATA_BLOCK_SIZE_MASK) + 1; + + DPRINTF("tag = %d\n",tag); + DPRINTF("blockLen = %d\n",blockLen-1); + + // check if it is short video description + if (tag == EDID_SHORT_AUD_DEC_TAG_VAL) { + // if so, check SAD + unsigned int j, channelNum; + int audioFormat,sampleFreq,wordLen; + for (j = 1; j < blockLen; j += 3) { + audioFormat = gEdidData[ExtAddr+j] & EDID_SAD_CODE_MASK; + channelNum = gEdidData[ExtAddr+j] & EDID_SAD_CHANNEL_MASK; + sampleFreq = gEdidData[ExtAddr+j+1]; + wordLen = gEdidData[ExtAddr+j+2]; + + DPRINTF("request = %d, EDIDAudioFormatCode = %d\n",(audio->formatCode)<<3, audioFormat); + DPRINTF("request = %d, EDIDChannelNumber= %d\n",(audio->channelNum)-1, channelNum); + DPRINTF("request = %d, EDIDSampleFreq= %d\n",1<<(audio->sampleFreq), sampleFreq); + DPRINTF("request = %d, EDIDWordLeng= %d\n",1<<(audio->wordLength), wordLen); + + // check parameter + // check audioFormat + if (audioFormat & ( (audio->formatCode) << 3) && // format code + channelNum >= ( (audio->channelNum) -1) && // channel number + (sampleFreq & (1<<(audio->sampleFreq)))) { // sample frequency + if (audioFormat == LPCM_FORMAT) { // check wordLen + int ret = 0; + switch (audio->wordLength) { + case WORD_16: + case WORD_17: + case WORD_18: + case WORD_19: + case WORD_20: + ret = wordLen & (1<<1); + break; + case WORD_21: + case WORD_22: + case WORD_23: + case WORD_24: + ret = wordLen & (1<<2); + break; + } + return ret; + } + return 1; // if not LPCM + } + } + } + // else find next block + ExtAddr += blockLen; + } + } + } + + return 0; +} diff --git a/exynos4/hal/libhdmi/libsForhdmi/libedid/libedid.h b/exynos4/hal/libhdmi/libsForhdmi/libedid/libedid.h new file mode 100644 index 0000000..dfd3096 --- /dev/null +++ b/exynos4/hal/libhdmi/libsForhdmi/libedid/libedid.h @@ -0,0 +1,42 @@ +/* + * Copyright@ Samsung Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _LIBEDID_H_ +#define _LIBEDID_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "video.h" +#include "audio.h" + +int EDIDOpen(void); +int EDIDRead(void); +void EDIDReset(void); +int EDIDHDMIModeSupport(struct HDMIVideoParameter *video); +int EDIDVideoResolutionSupport(struct HDMIVideoParameter *video); +int EDIDColorDepthSupport(struct HDMIVideoParameter *video); +int EDIDColorSpaceSupport(struct HDMIVideoParameter *video); +int EDIDColorimetrySupport(struct HDMIVideoParameter *video); +int EDIDAudioModeSupport(struct HDMIAudioParameter *audio); +int EDIDGetCECPhysicalAddress(int* outAddr); +int EDIDClose(void); + +#ifdef __cplusplus +} +#endif +#endif /* _LIBEDID_H_ */ diff --git a/exynos4/hal/libhwcomposer/Android.mk b/exynos4/hal/libhwcomposer/Android.mk new file mode 100644 index 0000000..902a72f --- /dev/null +++ b/exynos4/hal/libhwcomposer/Android.mk @@ -0,0 +1,88 @@ +# Copyright (C) 2008 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +LOCAL_PATH:= $(call my-dir) +# HAL module implemenation, not prelinked and stored in +# hw/..so + +include $(CLEAR_VARS) +LOCAL_PRELINK_MODULE := false +LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw +LOCAL_SHARED_LIBRARIES := liblog libcutils libEGL \ + libGLESv1_CM + +ifeq ($(BOARD_USE_V4L2_ION),true) +LOCAL_SHARED_LIBRARIES += libion +endif + +LOCAL_C_INCLUDES := \ + $(LOCAL_PATH)/../include + +LOCAL_SRC_FILES := SecHWCLog.cpp SecHWCUtils.cpp SecHWC.cpp + +LOCAL_C_INCLUDES += $(LOCAL_PATH)/../libfimg + +ifeq ($(TARGET_SOC),exynos4210) +LOCAL_CFLAGS += -DSAMSUNG_EXYNOS4210 +endif + +ifeq ($(TARGET_SOC),exynos4x12) +LOCAL_CFLAGS += -DSAMSUNG_EXYNOS4x12 +endif + +ifeq ($(BOARD_USES_HDMI),true) +LOCAL_C_INCLUDES += \ + $(TARGET_HAL_PATH)/libhwcomposer \ + $(TARGET_HAL_PATH)/include \ + $(TARGET_HAL_PATH)/libhdmi/libhdmiservice + +LOCAL_SHARED_LIBRARIES += libhdmiclient libTVOut + +LOCAL_CFLAGS += -DBOARD_USES_HDMI +LOCAL_CFLAGS += -DBOARD_HDMI_STD=$(BOARD_HDMI_STD) +LOCAL_CFLAGS += -DVIDEO_DUAL_DISPLAY + +ifeq ($(BOARD_USES_HDMI_SUBTITLES),true) + LOCAL_CFLAGS += -DBOARD_USES_HDMI_SUBTITLES +endif + +ifeq ($(BOARD_HDMI_STD), STD_NTSC_M) +LOCAL_CFLAGS += -DSTD_NTSC_M +endif + +ifeq ($(BOARD_HDMI_STD),STD_480P) +LOCAL_CFLAGS += -DSTD_480P +endif + +ifeq ($(BOARD_HDMI_STD),STD_720P) +LOCAL_CFLAGS += -DSTD_720P +endif + +ifeq ($(BOARD_HDMI_STD),STD_1080P) +LOCAL_CFLAGS += -DSTD_1080P +endif +endif + +ifeq ($(BOARD_USE_V4L2),true) +LOCAL_CFLAGS += -DBOARD_USE_V4L2 +endif + +ifeq ($(BOARD_USE_V4L2_ION),true) +LOCAL_CFLAGS += -DBOARD_USE_V4L2_ION +endif + +LOCAL_MODULE := hwcomposer.$(TARGET_BOARD_PLATFORM) +LOCAL_MODULE_TAGS := optional +include $(BUILD_SHARED_LIBRARY) diff --git a/exynos4/hal/libhwcomposer/SecHWC.cpp b/exynos4/hal/libhwcomposer/SecHWC.cpp new file mode 100644 index 0000000..d2f3ecc --- /dev/null +++ b/exynos4/hal/libhwcomposer/SecHWC.cpp @@ -0,0 +1,957 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * + * @author Rama, Meka(v.meka@samsung.com) + Sangwoo, Park(sw5771.park@samsung.com) + Jamie Oh (jung-min.oh@samsung.com) + * @date 2011-03-11 + * + */ + +#include +#include + +#include + +#include "SecHWCUtils.h" + +#include "gralloc_priv.h" +#ifdef HWC_HWOVERLAY +#include +#endif +#if defined(BOARD_USES_HDMI) +#include "SecHdmiClient.h" +#include "SecTVOutService.h" + +#include "SecHdmi.h" + +//#define CHECK_EGL_FPS +#ifdef CHECK_EGL_FPS +extern void check_fps(); +#endif + +static int lcd_width, lcd_height; +static int prev_usage = 0; + +#define CHECK_TIME_DEBUG 0 +#define SUPPORT_AUTO_UI_ROTATE +#endif +int testRenderNum =0; + +static int hwc_device_open(const struct hw_module_t* module, const char* name, + struct hw_device_t** device); + +static struct hw_module_methods_t hwc_module_methods = { + open: hwc_device_open +}; + +hwc_module_t HAL_MODULE_INFO_SYM = { + common: { + tag: HARDWARE_MODULE_TAG, + version_major: 1, + version_minor: 0, + id: HWC_HARDWARE_MODULE_ID, + name: "Samsung S5PC21X hwcomposer module", + author: "SAMSUNG", + methods: &hwc_module_methods, + } +}; + +/*****************************************************************************/ + +static void dump_layer(hwc_layer_t const* l) { + LOGD("\ttype=%d, flags=%08x, handle=%p, tr=%02x, blend=%04x, " + "{%d,%d,%d,%d}, {%d,%d,%d,%d}", + l->compositionType, l->flags, l->handle, l->transform, l->blending, + l->sourceCrop.left, + l->sourceCrop.top, + l->sourceCrop.right, + l->sourceCrop.bottom, + l->displayFrame.left, + l->displayFrame.top, + l->displayFrame.right, + l->displayFrame.bottom); +} + +void calculate_rect(struct hwc_win_info_t *win, hwc_layer_t *cur, + sec_rect *rect) +{ + rect->x = cur->displayFrame.left; + rect->y = cur->displayFrame.top; + rect->w = cur->displayFrame.right - cur->displayFrame.left; + rect->h = cur->displayFrame.bottom - cur->displayFrame.top; + + if (rect->x < 0) { + if (rect->w + rect->x > win->lcd_info.xres) + rect->w = win->lcd_info.xres; + else + rect->w = rect->w + rect->x; + rect->x = 0; + } else { + if (rect->w + rect->x > win->lcd_info.xres) + rect->w = win->lcd_info.xres - rect->x; + } + if (rect->y < 0) { + if (rect->h + rect->y > win->lcd_info.yres) + rect->h = win->lcd_info.yres; + else + rect->h = rect->h + rect->y; + rect->y = 0; + } else { + if (rect->h + rect->y > win->lcd_info.yres) + rect->h = win->lcd_info.yres - rect->y; + } +} + +static int set_src_dst_img_rect(hwc_layer_t *cur, + struct hwc_win_info_t *win, + struct sec_img *src_img, + struct sec_img *dst_img, + struct sec_rect *src_rect, + struct sec_rect *dst_rect, + int win_idx) +{ + private_handle_t *prev_handle = (private_handle_t *)(cur->handle); + sec_rect rect; + + /* 1. Set src_img from prev_handle */ + src_img->f_w = prev_handle->width; + src_img->f_h = prev_handle->height; + src_img->w = prev_handle->width; + src_img->h = prev_handle->height; + src_img->format = prev_handle->format; + src_img->base = (uint32_t)prev_handle->base; + src_img->offset = prev_handle->offset; + src_img->mem_id = prev_handle->fd; + src_img->paddr = prev_handle->paddr; + src_img->usage = prev_handle->usage; + src_img->uoffset = prev_handle->uoffset; + src_img->voffset = prev_handle->voffset; + + src_img->mem_type = HWC_VIRT_MEM_TYPE; + + switch (src_img->format) { + case HAL_PIXEL_FORMAT_YV12: /* To support video editor */ + case HAL_PIXEL_FORMAT_YCbCr_420_P: /* To support SW codec */ + case HAL_PIXEL_FORMAT_YCrCb_420_SP: + case HAL_PIXEL_FORMAT_YCbCr_420_SP: + case HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_SP: + case HAL_PIXEL_FORMAT_CUSTOM_YCrCb_420_SP: + case HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_SP_TILED: + case HAL_PIXEL_FORMAT_CUSTOM_YCbCr_422_SP: + case HAL_PIXEL_FORMAT_CUSTOM_YCrCb_422_SP: + case HAL_PIXEL_FORMAT_CUSTOM_YCbCr_422_I: + case HAL_PIXEL_FORMAT_CUSTOM_YCrCb_422_I: + case HAL_PIXEL_FORMAT_CUSTOM_CbYCrY_422_I: + case HAL_PIXEL_FORMAT_CUSTOM_CrYCbY_422_I: + src_img->f_w = (src_img->f_w + 15) & ~15; + src_img->f_h = (src_img->f_h + 1) & ~1; + break; + default: + src_img->f_w = src_img->w; + src_img->f_h = src_img->h; + break; + } + + /* 2. Set dst_img from window(lcd) */ + calculate_rect(win, cur, &rect); + dst_img->f_w = win->lcd_info.xres; + dst_img->f_h = win->lcd_info.yres; + dst_img->w = rect.w; + dst_img->h = rect.h; + + switch (win->lcd_info.bits_per_pixel) { + case 32: + dst_img->format = HAL_PIXEL_FORMAT_RGBX_8888; + break; + default: + dst_img->format = HAL_PIXEL_FORMAT_RGB_565; + break; + } + + dst_img->base = win->addr[win->buf_index]; + dst_img->offset = 0; + dst_img->mem_id = 0; + dst_img->mem_type = HWC_PHYS_MEM_TYPE; + + /* 3. Set src_rect(crop rect) */ + if (cur->displayFrame.left < 0) { + src_rect->x = + (0 - cur->displayFrame.left) + *(src_img->w) + /(cur->displayFrame.right - cur->displayFrame.left + 1); + if (cur->displayFrame.right + 1 > win->lcd_info.xres) { + src_rect->w = + (cur->sourceCrop.right - cur->sourceCrop.left + 1) - + src_rect->x - + (cur->displayFrame.right - win->lcd_info.xres) + *(src_img->w) + /(cur->displayFrame.right - cur->displayFrame.left + 1); + } else { + src_rect->w = + (cur->sourceCrop.right - cur->sourceCrop.left + 1) - + src_rect->x; + } + } else { + src_rect->x = cur->sourceCrop.left; + if (cur->displayFrame.right + 1 > win->lcd_info.xres) { + src_rect->w = + (cur->sourceCrop.right - cur->sourceCrop.left + 1) - + src_rect->x - + (cur->displayFrame.right - win->lcd_info.xres) + *(src_img->w) + /(cur->displayFrame.right - cur->displayFrame.left + 1); + } else { + src_rect->w = + (cur->sourceCrop.right - cur->sourceCrop.left + 1); + } + } + if (cur->displayFrame.top < 0) { + src_rect->y = + (0 - cur->displayFrame.top) + *(src_img->h) + /(cur->displayFrame.bottom - cur->displayFrame.top + 1); + if (cur->displayFrame.bottom + 1 > win->lcd_info.yres) { + src_rect->h = + (cur->sourceCrop.bottom - cur->sourceCrop.top + 1) - + src_rect->y - + (cur->displayFrame.bottom - win->lcd_info.yres) + *(src_img->h) + /(cur->displayFrame.bottom - cur->displayFrame.top + 1); + } else { + src_rect->h = + (cur->sourceCrop.bottom - cur->sourceCrop.top + 1) - + src_rect->y; + } + } else { + src_rect->y = cur->sourceCrop.top; + if (cur->displayFrame.bottom + 1 > win->lcd_info.yres) { + src_rect->h = + (cur->sourceCrop.bottom - cur->sourceCrop.top + 1) - + src_rect->y - + (cur->displayFrame.bottom - win->lcd_info.yres) + *(src_img->h) + /(cur->displayFrame.bottom - cur->displayFrame.top + 1); + } else { + src_rect->h = + (cur->sourceCrop.bottom - cur->sourceCrop.top + 1); + } + } + + SEC_HWC_Log(HWC_LOG_DEBUG, + "crop information()::" + "sourceCrop left(%d),top(%d),right(%d),bottom(%d)," + "src_rect x(%d),y(%d),w(%d),h(%d)," + "prev_handle w(%d),h(%d)", + cur->sourceCrop.left, + cur->sourceCrop.top, + cur->sourceCrop.right, + cur->sourceCrop.bottom, + src_rect->x, src_rect->y, src_rect->w, src_rect->h, + prev_handle->width, prev_handle->height); + + src_rect->x = SEC_MAX(src_rect->x, 0); + src_rect->y = SEC_MAX(src_rect->y, 0); + src_rect->w = SEC_MAX(src_rect->w, 0); + src_rect->w = SEC_MIN(src_rect->w, prev_handle->width); + src_rect->h = SEC_MAX(src_rect->h, 0); + src_rect->h = SEC_MIN(src_rect->h, prev_handle->height); + + /* 4. Set dst_rect(fb or lcd) + * fimc dst image will be stored from left top corner + */ + dst_rect->x = 0; + dst_rect->y = 0; + dst_rect->w = win->rect_info.w; + dst_rect->h = win->rect_info.h; + + /* Summery */ + SEC_HWC_Log(HWC_LOG_DEBUG, + "set_src_dst_img_rect()::" + "SRC w(%d),h(%d),f_w(%d),f_h(%d),fmt(0x%x)," + "base(0x%x),offset(%d),paddr(0x%X),mem_id(%d),mem_type(%d)=>\r\n" + " DST w(%d),h(%d),f(0x%x),base(0x%x)," + "offset(%d),mem_id(%d),mem_type(%d)," + "rot(%d),win_idx(%d)" + " SRC_RECT x(%d),y(%d),w(%d),h(%d)=>" + "DST_RECT x(%d),y(%d),w(%d),h(%d)", + src_img->w, src_img->h, src_img->f_w, src_img->f_h, src_img->format, + src_img->base, src_img->offset, src_img->paddr, src_img->mem_id, src_img->mem_type, + dst_img->w, dst_img->h, dst_img->format, dst_img->base, + dst_img->offset, dst_img->mem_id, dst_img->mem_type, + cur->transform, win_idx, + src_rect->x, src_rect->y, src_rect->w, src_rect->h, + dst_rect->x, dst_rect->y, dst_rect->w, dst_rect->h); + + return 0; +} + +static int get_hwc_compos_decision(hwc_layer_t* cur, int iter, int win_cnt) +{ + if(cur->flags & HWC_SKIP_LAYER || !cur->handle) { + SEC_HWC_Log(HWC_LOG_DEBUG, "%s::is_skip_layer %d cur->handle %x ", + __func__, cur->flags & HWC_SKIP_LAYER, cur->handle); + + return HWC_FRAMEBUFFER; + } + + private_handle_t *prev_handle = (private_handle_t *)(cur->handle); + int compositionType = HWC_FRAMEBUFFER; + + if (iter == 0) { + /* check here....if we have any resolution constraints */ + if (((cur->sourceCrop.right - cur->sourceCrop.left + 1) < 16) || + ((cur->sourceCrop.bottom - cur->sourceCrop.top + 1) < 8)) + return compositionType; + + if ((cur->transform == HAL_TRANSFORM_ROT_90) || + (cur->transform == HAL_TRANSFORM_ROT_270)) { + if (((cur->displayFrame.right - cur->displayFrame.left + 1) < 4) || + ((cur->displayFrame.bottom - cur->displayFrame.top + 1) < 8)) + return compositionType; + } else if (((cur->displayFrame.right - cur->displayFrame.left + 1) < 8) || + ((cur->displayFrame.bottom - cur->displayFrame.top + 1) < 4)) { + return compositionType; + } + + switch (prev_handle->format) { + case HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_SP: + case HAL_PIXEL_FORMAT_CUSTOM_YCrCb_420_SP: + case HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_SP_TILED: + compositionType = HWC_OVERLAY; + break; + case HAL_PIXEL_FORMAT_YV12: /* YCrCb_420_P */ + case HAL_PIXEL_FORMAT_YCbCr_420_P: + case HAL_PIXEL_FORMAT_YCrCb_420_SP: + case HAL_PIXEL_FORMAT_YCbCr_420_SP: + if ((prev_handle->usage & GRALLOC_USAGE_HWC_HWOVERLAY) && + (cur->blending == HWC_BLENDING_NONE)) + compositionType = HWC_OVERLAY; + else + compositionType = HWC_FRAMEBUFFER; + break; + default: + compositionType = HWC_FRAMEBUFFER; + break; + } + } + +#ifdef SUB_TITLES_HWC + else if ((win_cnt > 0) && + (prev_handle->usage & GRALLOC_USAGE_EXTERNAL_DISP)) { + switch (prev_handle->format) { + case HAL_PIXEL_FORMAT_RGBA_8888: + case HAL_PIXEL_FORMAT_RGBX_8888: + case HAL_PIXEL_FORMAT_BGRA_8888: + case HAL_PIXEL_FORMAT_RGB_888: + case HAL_PIXEL_FORMAT_RGB_565: + case HAL_PIXEL_FORMAT_RGBA_5551: + case HAL_PIXEL_FORMAT_RGBA_4444: + compositionType = HWC_OVERLAY; + break; + default: + compositionType = HWC_FRAMEBUFFER; + break; + } + + SEC_HWC_Log(HWC_LOG_DEBUG, "2nd iter###%s:: compositionType %d bpp %d" + " format %x src[%d %d %d %d] dst[%d %d %d %d] srcImg[%d %d]", + __func__, compositionType, prev_handle->bpp, + prev_handle->format, + cur->sourceCrop.left, cur->sourceCrop.right, + cur->sourceCrop.top, cur->sourceCrop.bottom, + cur->displayFrame.left, cur->displayFrame.right, + cur->displayFrame.top, cur->displayFrame.bottom, + prev_handle->width, prev_handle->height); + } +#endif + + SEC_HWC_Log(HWC_LOG_DEBUG, + "%s::compositionType(%d)=>0:FB,1:OVERLAY \r\n" + " format(0x%x),magic(0x%x),flags(%d),size(%d),offset(%d)" + "b_addr(0x%x),usage(%d),w(%d),h(%d),bpp(%d)", + "get_hwc_compos_decision()", compositionType, + prev_handle->format, prev_handle->magic, prev_handle->flags, + prev_handle->size, prev_handle->offset, prev_handle->base, + prev_handle->usage, prev_handle->width, prev_handle->height, + prev_handle->bpp); + + return compositionType; +} + +static void reset_win_rect_info(hwc_win_info_t *win) +{ + win->rect_info.x = 0; + win->rect_info.y = 0; + win->rect_info.w = 0; + win->rect_info.h = 0; + return; +} + + +static int assign_overlay_window(struct hwc_context_t *ctx, hwc_layer_t *cur, + int win_idx, int layer_idx) +{ + struct hwc_win_info_t *win; + sec_rect rect; + int ret = 0; + + if (NUM_OF_WIN <= win_idx) + return -1; + + win = &ctx->win[win_idx]; + + SEC_HWC_Log(HWC_LOG_DEBUG, + "%s:: left(%d),top(%d),right(%d),bottom(%d),transform(%d)" + "lcd_info.xres(%d),lcd_info.yres(%d)", + "++assign_overlay_window()", + cur->displayFrame.left, cur->displayFrame.top, + cur->displayFrame.right, cur->displayFrame.bottom, cur->transform, + win->lcd_info.xres, win->lcd_info.yres); + + calculate_rect(win, cur, &rect); + + if ((rect.x != win->rect_info.x) || (rect.y != win->rect_info.y) || + (rect.w != win->rect_info.w) || (rect.h != win->rect_info.h)){ + win->rect_info.x = rect.x; + win->rect_info.y = rect.y; + win->rect_info.w = rect.w; + win->rect_info.h = rect.h; + //turnoff the window and set the window position with new conf... + if (window_set_pos(win) < 0) { + SEC_HWC_Log(HWC_LOG_ERROR, "%s::window_set_pos is failed : %s", + __func__, strerror(errno)); + ret = -1; + } + ctx->layer_prev_buf[win_idx] = 0; + } + + win->layer_index = layer_idx; + win->status = HWC_WIN_RESERVED; + + SEC_HWC_Log(HWC_LOG_DEBUG, + "%s:: win_x %d win_y %d win_w %d win_h %d lay_idx %d win_idx %d\n", + "--assign_overlay_window()", + win->rect_info.x, win->rect_info.y, win->rect_info.w, + win->rect_info.h, win->layer_index, win_idx ); + + return 0; +} + +static int hwc_prepare(hwc_composer_device_t *dev, hwc_layer_list_t* list) +{ + struct hwc_context_t* ctx = (struct hwc_context_t*)dev; + int overlay_win_cnt = 0; + int compositionType = 0; + int ret; + + //if geometry is not changed, there is no need to do any work here + if (!list || (!(list->flags & HWC_GEOMETRY_CHANGED))) + return 0; + + //all the windows are free here.... + for (int i = 0 ; i < NUM_OF_WIN; i++) { + ctx->win[i].status = HWC_WIN_FREE; + ctx->win[i].buf_index = 0; + } + + ctx->num_of_hwc_layer = 0; + ctx->num_of_fb_layer = 0; + ctx->num_2d_blit_layer = 0; + + for (int i = 0; i < list->numHwLayers ; i++) { + hwc_layer_t* cur = &list->hwLayers[i]; + + if (overlay_win_cnt < NUM_OF_WIN) { + compositionType = get_hwc_compos_decision(cur, 0, overlay_win_cnt); + + if (compositionType == HWC_FRAMEBUFFER) { + cur->compositionType = HWC_FRAMEBUFFER; + ctx->num_of_fb_layer++; + } else { + ret = assign_overlay_window(ctx, cur, overlay_win_cnt, i); + if (ret != 0) { + LOGE("assign_overlay_window fail, change to frambuffer"); + cur->compositionType = HWC_FRAMEBUFFER; + ctx->num_of_fb_layer++; + continue; + } + + cur->compositionType = HWC_OVERLAY; + cur->hints = HWC_HINT_CLEAR_FB; + overlay_win_cnt++; + ctx->num_of_hwc_layer++; + } + } else { + cur->compositionType = HWC_FRAMEBUFFER; + ctx->num_of_fb_layer++; + } + } + +#ifdef SUB_TITLES_HWC + for (int i = 0; i < list->numHwLayers ; i++) { + if (overlay_win_cnt < NUM_OF_WIN) { + hwc_layer_t* cur = &list->hwLayers[i]; + if (get_hwc_compos_decision(cur, 1, overlay_win_cnt) == HWC_OVERLAY) { + ret = assign_overlay_window(ctx, cur, overlay_win_cnt, i); + if (ret == 0) { + cur->compositionType = HWC_OVERLAY; + cur->hints = HWC_HINT_CLEAR_FB; + overlay_win_cnt++; + ctx->num_of_hwc_layer++; + ctx->num_of_fb_layer--; + ctx->num_2d_blit_layer = 1; + } + } + } + else + break; + } +#endif + +#if defined(BOARD_USES_HDMI) + android::SecHdmiClient *mHdmiClient = android::SecHdmiClient::getInstance(); + mHdmiClient->setHdmiHwcLayer(ctx->num_of_hwc_layer); +#endif + + if (list->numHwLayers != (ctx->num_of_fb_layer + ctx->num_of_hwc_layer)) + SEC_HWC_Log(HWC_LOG_DEBUG, + "%s:: numHwLayers %d num_of_fb_layer %d num_of_hwc_layer %d ", + __func__, list->numHwLayers, ctx->num_of_fb_layer, + ctx->num_of_hwc_layer); + + if (overlay_win_cnt < NUM_OF_WIN) { + //turn off the free windows + for (int i = overlay_win_cnt; i < NUM_OF_WIN; i++) { + window_hide(&ctx->win[i]); + reset_win_rect_info(&ctx->win[i]); + } + } + + return 0; +} + +static int hwc_set(hwc_composer_device_t *dev, + hwc_display_t dpy, + hwc_surface_t sur, + hwc_layer_list_t* list) +{ + struct hwc_context_t *ctx = (struct hwc_context_t *)dev; + int skipped_window_mask = 0; + hwc_layer_t* cur; + struct hwc_win_info_t *win; + int ret; + int pmem_phyaddr; + static int egl_check; + int egl_run = 0; + struct sec_img src_img; + struct sec_img dst_img; + struct sec_rect src_work_rect; + struct sec_rect dst_work_rect; + + memset(&src_img, 0, sizeof(src_img)); + memset(&dst_img, 0, sizeof(dst_img)); + memset(&src_work_rect, 0, sizeof(src_work_rect)); + memset(&dst_work_rect, 0, sizeof(dst_work_rect)); + +#if defined(BOARD_USES_HDMI) + int skip_hdmi_rendering = 0; + int rotVal = 0; +#endif + + if (!list) { + //turn off the all windows + for (int i = 0; i < NUM_OF_WIN; i++) { + window_hide(&ctx->win[i]); + reset_win_rect_info(&ctx->win[i]); + ctx->win[i].status = HWC_WIN_FREE; + } + ctx->num_of_hwc_layer = 0; + + if (sur == NULL && dpy == NULL) + return HWC_EGL_ERROR; + } + + if(ctx->num_of_hwc_layer > NUM_OF_WIN) + ctx->num_of_hwc_layer = NUM_OF_WIN; + + //compose hardware layers here + for (int i = 0; i < ctx->num_of_hwc_layer - ctx->num_2d_blit_layer; i++) { + win = &ctx->win[i]; + if (win->status == HWC_WIN_RESERVED) { + cur = &list->hwLayers[win->layer_index]; + + if (cur->compositionType == HWC_OVERLAY) { + if (ctx->layer_prev_buf[i] == (uint32_t)cur->handle) { + /* + * In android platform, all the graphic buffer are at least + * double buffered (2 or more) this buffer is already rendered. + * It is the redundant src buffer for FIMC rendering. + */ + LOGD("SKIP FIMC rendering for Layer%d", win->layer_index); +#if defined(BOARD_USES_HDMI) + skip_hdmi_rendering = 1; +#endif + continue; + } + ctx->layer_prev_buf[i] = (uint32_t)cur->handle; + // initialize the src & dist context for fimc + set_src_dst_img_rect(cur, win, &src_img, &dst_img, + &src_work_rect, &dst_work_rect, i); + + ret = runFimc(ctx, + &src_img, &src_work_rect, + &dst_img, &dst_work_rect, + cur->transform); + + if (ret < 0) { + SEC_HWC_Log(HWC_LOG_ERROR, "%s::runFimc fail : ret=%d\n", + __func__, ret); + skipped_window_mask |= (1 << i); + continue; + } + + window_pan_display(win); + + win->buf_index = (win->buf_index + 1) % NUM_OF_WIN_BUF; + if (win->power_state == 0) + window_show(win); + } else { + SEC_HWC_Log(HWC_LOG_ERROR, + "%s:: error : layer %d compositionType should have been" + " HWC_OVERLAY ", __func__, win->layer_index); + skipped_window_mask |= (1 << i); + continue; + } + } else { + SEC_HWC_Log(HWC_LOG_ERROR, "%s:: error : window status should have " + "been HWC_WIN_RESERVED by now... ", __func__); + skipped_window_mask |= (1 << i); + continue; + } + } + +#ifdef SUB_TITLES_HWC + if (ctx->num_2d_blit_layer) { + g2d_rect srcRect; + g2d_rect dstRect; + + win = &ctx->win[ctx->num_of_hwc_layer - 1]; + cur = &list->hwLayers[win->layer_index]; + set_src_dst_g2d_rect(cur, win, &srcRect, &dstRect); + ret = runG2d(ctx, &srcRect, &dstRect, + cur->transform); + if (ret < 0) { + SEC_HWC_Log(HWC_LOG_ERROR, "%s::runG2d fail : ret=%d\n", + __func__, ret); + skipped_window_mask |= (1 << (ctx->num_of_hwc_layer - 1)); + goto g2d_error; + } + + window_pan_display(win); + + win->buf_index = (win->buf_index + 1) % NUM_OF_WIN_BUF; + if (win->power_state == 0) + window_show(win); + } + +g2d_error: +#endif + + if (skipped_window_mask) { + //turn off the free windows + for (int i = 0; i < NUM_OF_WIN; i++) { + if (skipped_window_mask & (1 << i)) { + window_hide(&ctx->win[i]); + reset_win_rect_info(&ctx->win[i]); + } + } + } + + if (0 < ctx->num_of_fb_layer) { +#ifdef CHECK_EGL_FPS + check_fps(); +#endif +#ifdef HWC_HWOVERLAY + unsigned char pixels[4]; + glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixels); +#endif + egl_check = 1; + egl_run = 1; + } else { + if (egl_check == 1) { + egl_check = 0; + egl_run = 1; + } + } + + if (egl_run == 1) { + EGLBoolean sucess = eglSwapBuffers((EGLDisplay)dpy, (EGLSurface)sur); + if (!sucess) + return HWC_EGL_ERROR; + } + +#if defined(BOARD_USES_HDMI) + android::SecHdmiClient *mHdmiClient = android::SecHdmiClient::getInstance(); + + if (skip_hdmi_rendering == 1) + return 0; + + if (list == NULL) { + // Don't display unnecessary image + mHdmiClient->setHdmiEnable(0); + return 0; + } else { + mHdmiClient->setHdmiEnable(1); + } + +#ifdef SUPPORT_AUTO_UI_ROTATE + cur = &list->hwLayers[0]; + + if (cur->transform == HAL_TRANSFORM_ROT_90 || cur->transform == HAL_TRANSFORM_ROT_270) + mHdmiClient->setHdmiRotate(270, ctx->num_of_hwc_layer); + else + mHdmiClient->setHdmiRotate(0, ctx->num_of_hwc_layer); +#endif + + // To support S3D video playback (automatic TV mode change to 3D mode) + if (ctx->num_of_hwc_layer == 1) { + if (src_img.usage != prev_usage) + mHdmiClient->setHdmiResolution(DEFAULT_HDMI_RESOLUTION_VALUE); // V4L2_STD_1080P_60 + + if ((src_img.usage & GRALLOC_USAGE_PRIVATE_SBS_LR) || + (src_img.usage & GRALLOC_USAGE_PRIVATE_SBS_RL)) + mHdmiClient->setHdmiResolution(7209601); // V4L2_STD_TVOUT_720P_60_SBS_HALF + else if ((src_img.usage & GRALLOC_USAGE_PRIVATE_TB_LR) || + (src_img.usage & GRALLOC_USAGE_PRIVATE_TB_RL)) + mHdmiClient->setHdmiResolution(1080924); // V4L2_STD_TVOUT_1080P_24_TB + + prev_usage = src_img.usage; + } else { + if ((prev_usage & GRALLOC_USAGE_PRIVATE_SBS_LR) || + (prev_usage & GRALLOC_USAGE_PRIVATE_SBS_RL) || + (prev_usage & GRALLOC_USAGE_PRIVATE_TB_LR) || + (prev_usage & GRALLOC_USAGE_PRIVATE_TB_RL)) + mHdmiClient->setHdmiResolution(DEFAULT_HDMI_RESOLUTION_VALUE); // V4L2_STD_1080P_60 + + prev_usage = 0; + } + + if (ctx->num_of_hwc_layer == 1) { + if ((src_img.format == HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_SP_TILED)|| + (src_img.format == HAL_PIXEL_FORMAT_CUSTOM_YCrCb_420_SP)) { + ADDRS * addr = (ADDRS *)(src_img.base); + + mHdmiClient->blit2Hdmi(src_img.w, src_img.h, + src_img.format, + (unsigned int)addr->addr_y, (unsigned int)addr->addr_cbcr, (unsigned int)addr->addr_cbcr, + 0, 0, + android::SecHdmiClient::HDMI_MODE_VIDEO, + ctx->num_of_hwc_layer); + } else if ((src_img.format == HAL_PIXEL_FORMAT_YCbCr_420_SP) || + (src_img.format == HAL_PIXEL_FORMAT_YCrCb_420_SP) || + (src_img.format == HAL_PIXEL_FORMAT_YCbCr_420_P) || + (src_img.format == HAL_PIXEL_FORMAT_YV12)) { + mHdmiClient->blit2Hdmi(src_img.w, src_img.h, + src_img.format, + (unsigned int)ctx->fimc.params.src.buf_addr_phy_rgb_y, + (unsigned int)ctx->fimc.params.src.buf_addr_phy_cb, + (unsigned int)ctx->fimc.params.src.buf_addr_phy_cr, + 0, 0, + android::SecHdmiClient::HDMI_MODE_VIDEO, + ctx->num_of_hwc_layer); + } else { + LOGE("%s: Unsupported format = %d", __func__, src_img.format); + } + } +#endif + return 0; +} + +static int hwc_device_close(struct hw_device_t *dev) +{ + struct hwc_context_t* ctx = (struct hwc_context_t*)dev; + int ret = 0; + int i; + if (ctx) { + if (destroyFimc(&ctx->fimc) < 0) { + SEC_HWC_Log(HWC_LOG_ERROR, "%s::destroyFimc fail", __func__); + ret = -1; + } +#ifdef SUB_TITLES_HWC + if (destroyG2d(&ctx->g2d) < 0) { + SEC_HWC_Log(HWC_LOG_ERROR, "%s::destroyG2d() fail", __func__); + ret = -1; + } +#endif + if (destroyMem(&ctx->s3c_mem) < 0) { + SEC_HWC_Log(HWC_LOG_ERROR, "%s::destroyMem fail", __func__); + ret = -1; + } + +#ifdef USE_HW_PMEM + if (destroyPmem(&ctx->sec_pmem) < 0) { + SEC_HWC_Log(HWC_LOG_ERROR, "%s::destroyPmem fail", __func__); + ret = -1; + } +#endif + for (i = 0; i < NUM_OF_WIN; i++) { + if (window_close(&ctx->win[i]) < 0) + SEC_HWC_Log(HWC_LOG_DEBUG, "%s::window_close() fail", __func__); + } + + free(ctx); + } + return ret; +} + +static int hwc_device_open(const struct hw_module_t* module, const char* name, + struct hw_device_t** device) +{ + int status = 0; + struct hwc_win_info_t *win; + + if (strcmp(name, HWC_HARDWARE_COMPOSER)) + return -EINVAL; + + struct hwc_context_t *dev; + dev = (hwc_context_t*)malloc(sizeof(*dev)); + + /* initialize our state here */ + memset(dev, 0, sizeof(*dev)); + + /* initialize the procs */ + dev->device.common.tag = HARDWARE_DEVICE_TAG; + dev->device.common.version = 0; + dev->device.common.module = const_cast(module); + dev->device.common.close = hwc_device_close; + + dev->device.prepare = hwc_prepare; + dev->device.set = hwc_set; + + *device = &dev->device.common; + + //initializing + memset(&(dev->fimc), 0, sizeof(s5p_fimc_t)); + memset(&(dev->s3c_mem), 0, sizeof(struct s3c_mem_t)); +#ifdef USE_HW_PMEM + memset(&(dev->sec_pmem), 0, sizeof(sec_pmem_t)); +#endif + /* open WIN0 & WIN1 here */ + for (int i = 0; i < NUM_OF_WIN; i++) { + if (window_open(&(dev->win[i]), i) < 0) { + SEC_HWC_Log(HWC_LOG_ERROR, + "%s:: Failed to open window %d device ", __func__, i); + status = -EINVAL; + goto err; + } + } + + if (window_get_global_lcd_info(dev->win[0].fd, &dev->lcd_info) < 0) { + SEC_HWC_Log(HWC_LOG_ERROR, + "%s::window_get_global_lcd_info is failed : %s", + __func__, strerror(errno)); + status = -EINVAL; + goto err; + } + +#if defined(BOARD_USES_HDMI) + lcd_width = dev->lcd_info.xres; + lcd_height = dev->lcd_info.yres; +#endif + + /* initialize the window context */ + for (int i = 0; i < NUM_OF_WIN; i++) { + win = &dev->win[i]; + memcpy(&win->lcd_info, &dev->lcd_info, sizeof(struct fb_var_screeninfo)); + memcpy(&win->var_info, &dev->lcd_info, sizeof(struct fb_var_screeninfo)); + + win->rect_info.x = 0; + win->rect_info.y = 0; + win->rect_info.w = win->var_info.xres; + win->rect_info.h = win->var_info.yres; + + if (window_set_pos(win) < 0) { + SEC_HWC_Log(HWC_LOG_ERROR, "%s::window_set_pos is failed : %s", + __func__, strerror(errno)); + status = -EINVAL; + goto err; + } + + if (window_get_info(win, i) < 0) { + SEC_HWC_Log(HWC_LOG_ERROR, "%s::window_get_info is failed : %s", + __func__, strerror(errno)); + status = -EINVAL; + goto err; + } + + } + +#ifdef USE_HW_PMEM + if (createPmem(&dev->sec_pmem, PMEM_SIZE) < 0) { + SEC_HWC_Log(HWC_LOG_ERROR, "%s::initPmem(%d) fail", __func__, PMEM_SIZE); + } +#endif + + if (createMem(&dev->s3c_mem, 0, 0) < 0) { + SEC_HWC_Log(HWC_LOG_ERROR, "%s::createMem() fail (size=0)", __func__); + status = -EINVAL; + goto err; + } + + //create PP + if (createFimc(&dev->fimc) < 0) { + SEC_HWC_Log(HWC_LOG_ERROR, "%s::creatFimc() fail", __func__); + status = -EINVAL; + goto err; + } + +#ifdef SUB_TITLES_HWC + if (createG2d(&dev->g2d) < 0) { + SEC_HWC_Log(HWC_LOG_ERROR, "%s::createG2d() fail", __func__); + status = -EINVAL; + goto err; + } +#endif + + SEC_HWC_Log(HWC_LOG_DEBUG, "%s:: hwc_device_open: SUCCESS", __func__); + + return 0; + +err: + if (destroyFimc(&dev->fimc) < 0) + SEC_HWC_Log(HWC_LOG_ERROR, "%s::destroyFimc() fail", __func__); +#ifdef SUB_TITLES_HWC + if (destroyG2d(&dev->g2d) < 0) + SEC_HWC_Log(HWC_LOG_ERROR, "%s::destroyG2d() fail", __func__); +#endif + if (destroyMem(&dev->s3c_mem) < 0) + SEC_HWC_Log(HWC_LOG_ERROR, "%s::destroyMem() fail", __func__); + +#ifdef USE_HW_PMEM + if (destroyPmem(&dev->sec_pmem) < 0) + SEC_HWC_Log(HWC_LOG_ERROR, "%s::destroyPmem() fail", __func__); +#endif + + for (int i = 0; i < NUM_OF_WIN; i++) { + if (window_close(&dev->win[i]) < 0) + SEC_HWC_Log(HWC_LOG_DEBUG, "%s::window_close() fail", __func__); + } + + return status; +} diff --git a/exynos4/hal/libhwcomposer/SecHWCLog.cpp b/exynos4/hal/libhwcomposer/SecHWCLog.cpp new file mode 100644 index 0000000..6ad4283 --- /dev/null +++ b/exynos4/hal/libhwcomposer/SecHWCLog.cpp @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * + * @author Rama, Meka(v.meka@samsung.com) + Sangwoo, Park(sw5771.park@samsung.com) + Jamie Oh (jung-min.oh@samsung.com) + * @date 2011-03-11 + * + */ + +#include + +#include "SecHWCUtils.h" + +void _SEC_HWC_Log(HWC_LOG_LEVEL logLevel, const char *tag, const char *msg, ...) +{ + va_list argptr; + + va_start(argptr, msg); + + switch (logLevel) { + case HWC_LOG_DEBUG: + __android_log_vprint(ANDROID_LOG_DEBUG, tag, msg, argptr); + break; + case HWC_LOG_WARNING: + __android_log_vprint(ANDROID_LOG_WARN, tag, msg, argptr); + break; + case HWC_LOG_ERROR: + __android_log_vprint(ANDROID_LOG_ERROR, tag, msg, argptr); + break; + default: + __android_log_vprint(ANDROID_LOG_VERBOSE, tag, msg, argptr); + } + + va_end(argptr); +} diff --git a/exynos4/hal/libhwcomposer/SecHWCUtils.cpp b/exynos4/hal/libhwcomposer/SecHWCUtils.cpp new file mode 100644 index 0000000..5214e40 --- /dev/null +++ b/exynos4/hal/libhwcomposer/SecHWCUtils.cpp @@ -0,0 +1,2077 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Revision History: + * - 2011/03/11 : Rama, Meka(v.meka@samsung.com) + * Initial version + * + * - 2011/12/07 : Jeonghee, Kim(jhhhh.kim@samsung.com) + * Add V4L2_PIX_FMT_YUV420M V4L2_PIX_FMT_NV12M + * + */ + +#include "SecHWCUtils.h" + +#ifdef BOARD_USE_V4L2_ION +#define V4L2_BUF_TYPE_OUTPUT V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE +#define V4L2_BUF_TYPE_CAPTURE V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE +#else +#define V4L2_BUF_TYPE_OUTPUT V4L2_BUF_TYPE_VIDEO_OUTPUT +#define V4L2_BUF_TYPE_CAPTURE V4L2_BUF_TYPE_VIDEO_CAPTURE +#endif + +#define EXYNOS4_ALIGN( value, base ) (((value) + ((base) - 1)) & ~((base) - 1)) + +//#define CHECK_FPS +#ifdef CHECK_FPS +#include +#include +#define CHK_FRAME_CNT 30 + +void check_fps() +{ + static struct timeval tick, tick_old; + static int total = 0; + static int cnt = 0; + int FPS; + cnt++; + gettimeofday(&tick, NULL); + if (cnt > 10) { + if (tick.tv_sec > tick_old.tv_sec) + total += ((tick.tv_usec/1000) + (tick.tv_sec - tick_old.tv_sec)*1000 - (tick_old.tv_usec/1000)); + else + total += ((tick.tv_usec - tick_old.tv_usec)/1000); + + memcpy(&tick_old, &tick, sizeof(timeval)); + if (cnt == (10 + CHK_FRAME_CNT)) { + FPS = 1000*CHK_FRAME_CNT/total; + LOGE("[FPS]:%d\n", FPS); + total = 0; + cnt = 10; + } + } else { + memcpy(&tick_old, &tick, sizeof(timeval)); + total = 0; + } +} +#endif + +struct yuv_fmt_list yuv_list[] = { + { "V4L2_PIX_FMT_NV12", "YUV420/2P/LSB_CBCR", V4L2_PIX_FMT_NV12, 12, 2 }, + { "V4L2_PIX_FMT_NV12T", "YUV420/2P/LSB_CBCR", V4L2_PIX_FMT_NV12T, 12, 2 }, + { "V4L2_PIX_FMT_NV21", "YUV420/2P/LSB_CRCB", V4L2_PIX_FMT_NV21, 12, 2 }, + { "V4L2_PIX_FMT_NV21X", "YUV420/2P/MSB_CBCR", V4L2_PIX_FMT_NV21X, 12, 2 }, + { "V4L2_PIX_FMT_NV12X", "YUV420/2P/MSB_CRCB", V4L2_PIX_FMT_NV12X, 12, 2 }, + { "V4L2_PIX_FMT_YUV420", "YUV420/3P", V4L2_PIX_FMT_YUV420, 12, 3 }, +#ifdef BOARD_USE_V4L2_ION + { "V4L2_PIX_FMT_YUV420M", "YUV420/3P", V4L2_PIX_FMT_YUV420M, 12, 3 }, + { "V4L2_PIX_FMT_NV12M", "YUV420/2P", V4L2_PIX_FMT_NV12M, 12, 2 }, +#endif + { "V4L2_PIX_FMT_YUYV", "YUV422/1P/YCBYCR", V4L2_PIX_FMT_YUYV, 16, 1 }, + { "V4L2_PIX_FMT_YVYU", "YUV422/1P/YCRYCB", V4L2_PIX_FMT_YVYU, 16, 1 }, + { "V4L2_PIX_FMT_UYVY", "YUV422/1P/CBYCRY", V4L2_PIX_FMT_UYVY, 16, 1 }, + { "V4L2_PIX_FMT_VYUY", "YUV422/1P/CRYCBY", V4L2_PIX_FMT_VYUY, 16, 1 }, + { "V4L2_PIX_FMT_UV12", "YUV422/2P/LSB_CBCR", V4L2_PIX_FMT_NV16, 16, 2 }, + { "V4L2_PIX_FMT_UV21", "YUV422/2P/LSB_CRCB", V4L2_PIX_FMT_NV61, 16, 2 }, + { "V4L2_PIX_FMT_UV12X", "YUV422/2P/MSB_CBCR", V4L2_PIX_FMT_NV16X, 16, 2 }, + { "V4L2_PIX_FMT_UV21X", "YUV422/2P/MSB_CRCB", V4L2_PIX_FMT_NV61X, 16, 2 }, + { "V4L2_PIX_FMT_YUV422P", "YUV422/3P", V4L2_PIX_FMT_YUV422P, 16, 3 }, +}; + +int window_open(struct hwc_win_info_t *win, int id) +{ + int fd = 0; + char name[64]; + int vsync = 1; + int real_id = id; + + char const * const device_template = "/dev/graphics/fb%u"; + // window & FB maping + // fb0 -> win-id : 2 + // fb1 -> win-id : 3 + // fb2 -> win-id : 4 + // fb3 -> win-id : 0 + // fb4 -> win_id : 1 + // it is pre assumed that ...win0 or win1 is used here.. + + switch (id) { + case 0: +#ifdef BOARD_USE_V4L2_ION + real_id = 2; +#else + real_id = 3; +#endif + break; + case 1: +#ifdef BOARD_USE_V4L2_ION + real_id = 1; +#else + real_id = 4; +#endif + break; + default: + SEC_HWC_Log(HWC_LOG_ERROR, "%s::id(%d) is weird", __func__, id); + goto error; +} + +// 0/10 +// snprintf(name, 64, device_template, id + 3); +// 5/10 +// snprintf(name, 64, device_template, id + 0); +// 0/10 +// snprintf(name, 64, device_template, id + 1); + snprintf(name, 64, device_template, real_id); + + win->fd = open(name, O_RDWR); + if (win->fd <= 0) { + SEC_HWC_Log(HWC_LOG_ERROR, "%s::Failed to open window device (%s) : %s", + __func__, strerror(errno), name); + goto error; + } + +#ifdef ENABLE_FIMD_VSYNC + if (ioctl(win->fd, S3CFB_SET_VSYNC_INT, &vsync) < 0) { + SEC_HWC_Log(HWC_LOG_ERROR, "%s::S3CFB_SET_VSYNC_INT fail", __func__); + goto error; + } +#endif + + return 0; + +error: + if (0 < win->fd) + close(win->fd); + win->fd = 0; + + return -1; +} + +int window_close(struct hwc_win_info_t *win) +{ + int ret = 0; + + if (0 < win->fd) { + +#ifdef BOARD_USE_V4L2_ION + ion_unmap((void *)win->addr[0], ALIGN(win->size * NUM_OF_WIN_BUF, PAGE_SIZE)); + ion_free(win->ion_fd); +#endif + +#ifdef ENABLE_FIMD_VSYNC + int vsync = 0; + if (ioctl(win->fd, S3CFB_SET_VSYNC_INT, &vsync) < 0) + SEC_HWC_Log(HWC_LOG_ERROR, "%s::S3CFB_SET_VSYNC_INT fail", __func__); +#endif + ret = close(win->fd); + } + win->fd = 0; + + return ret; +} + +int window_set_pos(struct hwc_win_info_t *win) +{ + struct s3cfb_user_window window; + + //before changing the screen configuration...powerdown the window + if (window_hide(win) != 0) + return -1; + + SEC_HWC_Log(HWC_LOG_DEBUG, "%s:: x(%d), y(%d)", + __func__, win->rect_info.x, win->rect_info.y); + + win->var_info.xres_virtual = (win->lcd_info.xres + 15) & ~ 15; + win->var_info.yres_virtual = win->lcd_info.yres * NUM_OF_WIN_BUF; + win->var_info.xres = win->rect_info.w; + win->var_info.yres = win->rect_info.h; + + win->var_info.activate &= ~FB_ACTIVATE_MASK; + win->var_info.activate |= FB_ACTIVATE_FORCE; + + if (ioctl(win->fd, FBIOPUT_VSCREENINFO, &(win->var_info)) < 0) { + SEC_HWC_Log(HWC_LOG_ERROR, "%s::FBIOPUT_VSCREENINFO(%d, %d) fail", + __func__, win->rect_info.w, win->rect_info.h); + return -1; + } + + window.x = win->rect_info.x; + window.y = win->rect_info.y; + + if (ioctl(win->fd, S3CFB_WIN_POSITION, &window) < 0) { + SEC_HWC_Log(HWC_LOG_ERROR, "%s::S3CFB_WIN_POSITION(%d, %d) fail", + __func__, window.x, window.y); + return -1; + } + + return 0; +} + +int window_get_info(struct hwc_win_info_t *win, int win_num) +{ + int temp_size = 0; + + if (ioctl(win->fd, FBIOGET_FSCREENINFO, &win->fix_info) < 0) { + SEC_HWC_Log(HWC_LOG_ERROR, "FBIOGET_FSCREENINFO failed : %s", + strerror(errno)); + goto error; + } + + win->size = win->fix_info.line_length * win->var_info.yres; + +#ifdef BOARD_USE_V4L2_ION + struct s3c_fb_user_ion_client ion_handle; + void *ion_start_addr; + + if (ioctl(win->fd, S3CFB_GET_ION_USER_HANDLE, &ion_handle) < 0) { + SEC_HWC_Log(HWC_LOG_ERROR, "Get fb ion client is failed\n"); + return -1; + } + + win->ion_fd = ion_handle.fd; + ion_start_addr = ion_map(win->ion_fd, ALIGN(win->size * NUM_OF_WIN_BUF, PAGE_SIZE), 0); +#endif + + for (int j = 0; j < NUM_OF_WIN_BUF; j++) { + temp_size = win->size * j; +#ifdef BOARD_USE_V4L2_ION + win->addr[j] = (uint32_t)ion_start_addr + temp_size; +#else + win->addr[j] = win->fix_info.smem_start + temp_size; +#endif + SEC_HWC_Log(HWC_LOG_DEBUG, "%s::win-%d add[%d] %x ", + __func__, win_num, j, win->addr[j]); + } + return 0; + +error: + win->fix_info.smem_start = 0; + + return -1; +} + +int window_pan_display(struct hwc_win_info_t *win) +{ + struct fb_var_screeninfo *lcd_info = &(win->lcd_info); + +#ifdef ENABLE_FIMD_VSYNC +#ifdef BOARD_USE_V4L2_ION + int fimd_num = 0; + if (ioctl(win->fd, FBIO_WAITFORVSYNC, &fimd_num) < 0) + SEC_HWC_Log(HWC_LOG_ERROR, "%s::FBIO_WAITFORVSYNC fail(%s)", + __func__, strerror(errno)); +#else + if (ioctl(win->fd, FBIO_WAITFORVSYNC, 0) < 0) + SEC_HWC_Log(HWC_LOG_ERROR, "%s::FBIO_WAITFORVSYNC fail(%s)", + __func__, strerror(errno)); +#endif +#endif + + lcd_info->yoffset = lcd_info->yres * win->buf_index; + + if (ioctl(win->fd, FBIOPAN_DISPLAY, lcd_info) < 0) { + SEC_HWC_Log(HWC_LOG_ERROR, "%s::FBIOPAN_DISPLAY(%d / %d / %d) fail(%s)", + __func__, + lcd_info->yres, + win->buf_index, lcd_info->yres_virtual, + strerror(errno)); + return -1; + } + return 0; +} + +int window_show(struct hwc_win_info_t *win) +{ + if (win->power_state == 0) { + if (ioctl(win->fd, FBIOBLANK, FB_BLANK_UNBLANK) < 0) { + SEC_HWC_Log(HWC_LOG_ERROR, "%s::FBIOBLANK failed : (%d:%s)", + __func__, win->fd, strerror(errno)); + return -1; + } + win->power_state = 1; + } + return 0; +} + +int window_hide(struct hwc_win_info_t *win) +{ + if (win->power_state == 1) { + if (ioctl(win->fd, FBIOBLANK, FB_BLANK_POWERDOWN) < 0) { + SEC_HWC_Log(HWC_LOG_ERROR, "%s::FBIOBLANK failed : (%d:%s)", + __func__, win->fd, strerror(errno)); + return -1; + } + win->power_state = 0; + } + return 0; +} + +int window_get_global_lcd_info(int fd, struct fb_var_screeninfo *lcd_info) +{ + if (ioctl(fd, FBIOGET_VSCREENINFO, lcd_info) < 0) { + SEC_HWC_Log(HWC_LOG_ERROR, "FBIOGET_VSCREENINFO failed : %s", + strerror(errno)); + return -1; + } + + SEC_HWC_Log(HWC_LOG_DEBUG, "%s:: Default LCD x(%d),y(%d)", + __func__, lcd_info->xres, lcd_info->yres); + return 0; +} + +int fimc_v4l2_set_src(int fd, unsigned int hw_ver, s5p_fimc_img_info *src) +{ + struct v4l2_format fmt; + struct v4l2_cropcap cropcap; + struct v4l2_crop crop; + struct v4l2_requestbuffers req; + +#ifdef BOARD_USE_V4L2_ION + /* You MUST initialize structure for v4l2 */ + memset(&fmt, 0, sizeof(fmt)); + memset(&cropcap, 0, sizeof(cropcap)); + memset(&crop, 0, sizeof(crop)); + memset(&req, 0, sizeof(req)); + + /* To set size & format for source image (DMA-INPUT) */ + fmt.fmt.pix_mp.num_planes = src->planes; + fmt.fmt.pix_mp.width = src->full_width; + fmt.fmt.pix_mp.height = src->full_height; + fmt.fmt.pix_mp.pixelformat = src->color_space; + fmt.fmt.pix_mp.field = V4L2_FIELD_ANY; +#else + fmt.fmt.pix.width = src->full_width; + fmt.fmt.pix.height = src->full_height; + fmt.fmt.pix.pixelformat = src->color_space; + fmt.fmt.pix.field = V4L2_FIELD_NONE; +#endif + fmt.type = V4L2_BUF_TYPE_OUTPUT; + + if (ioctl(fd, VIDIOC_S_FMT, &fmt) < 0) { + SEC_HWC_Log(HWC_LOG_ERROR, "%s::VIDIOC_S_FMT failed : errno=%d (%s)" + " : fd=%d\n", __func__, errno, strerror(errno), fd); + return -1; + } + + /* crop input size */ + crop.type = V4L2_BUF_TYPE_OUTPUT; + crop.c.width = src->width; + crop.c.height = src->height; +#ifdef BOARD_USE_V4L2_ION + crop.c.left = src->start_x; + crop.c.top = src->start_y; +#else + if (0x50 <= hw_ver) { + crop.c.left = src->start_x; + crop.c.top = src->start_y; + } else { + crop.c.left = 0; + crop.c.top = 0; + } + +#endif + + if (ioctl(fd, VIDIOC_S_CROP, &crop) < 0) { + SEC_HWC_Log(HWC_LOG_ERROR, "%s::Error in video VIDIOC_S_CROP :" + "crop.c.left : (%d), crop.c.top : (%d), crop.c.width : (%d), crop.c.height : (%d)", + __func__, crop.c.left, crop.c.top, crop.c.width, crop.c.height); + return -1; + } + + /* input buffer type */ + req.count = 1; + req.memory = V4L2_MEMORY_USERPTR; + req.type = V4L2_BUF_TYPE_OUTPUT; + + if (ioctl(fd, VIDIOC_REQBUFS, &req) < 0) { + SEC_HWC_Log(HWC_LOG_ERROR, "%s::Error in VIDIOC_REQBUFS", __func__); + return -1; + } + + return 0; +} + +int fimc_v4l2_set_dst(int fd, s5p_fimc_img_info *dst, + int rotation, int hflip, int vflip, unsigned int addr) +{ + struct v4l2_format sFormat; + struct v4l2_control vc; + struct v4l2_framebuffer fbuf; +#ifdef BOARD_USE_V4L2_ION + struct v4l2_crop crop; + struct v4l2_requestbuffers req; +#endif + int ret; + +#ifdef BOARD_USE_V4L2_ION + /* You MUST initialize structure for v4l2 */ + memset(&sFormat, 0, sizeof(sFormat)); + memset(&vc, 0, sizeof(vc)); + memset(&fbuf, 0, sizeof(fbuf)); + memset(&crop, 0, sizeof(crop)); + memset(&req, 0, sizeof(req)); +#endif + + /* set rotation configuration */ +#ifdef BOARD_USE_V4L2_ION + vc.id = V4L2_CID_ROTATE; +#else + vc.id = V4L2_CID_ROTATION; +#endif + vc.value = rotation; + + ret = ioctl(fd, VIDIOC_S_CTRL, &vc); + if (ret < 0) { + SEC_HWC_Log(HWC_LOG_ERROR, + "%s::Error in video VIDIOC_S_CTRL - rotation (%d)" + "vc.id : (%d), vc.value : (%d)", __func__, ret, vc.id, vc.value); + return -1; + } + + vc.id = V4L2_CID_HFLIP; + vc.value = hflip; + + ret = ioctl(fd, VIDIOC_S_CTRL, &vc); + if (ret < 0) { + SEC_HWC_Log(HWC_LOG_ERROR, + "%s::Error in video VIDIOC_S_CTRL - hflip (%d)" + "vc.id : (%d), vc.value : (%d)", __func__, ret, vc.id, vc.value); + return -1; + } + + vc.id = V4L2_CID_VFLIP; + vc.value = vflip; + + ret = ioctl(fd, VIDIOC_S_CTRL, &vc); + if (ret < 0) { + SEC_HWC_Log(HWC_LOG_ERROR, + "%s::Error in video VIDIOC_S_CTRL - vflip (%d)" + "vc.id : (%d), vc.value : (%d)", __func__, ret, vc.id, vc.value); + return -1; + } + +#ifdef BOARD_USE_V4L2_ION + /* set destination */ + sFormat.type = V4L2_BUF_TYPE_CAPTURE; + sFormat.fmt.pix_mp.width = dst->full_width; + sFormat.fmt.pix_mp.height = dst->full_height; + sFormat.fmt.pix_mp.pixelformat = dst->color_space; + sFormat.fmt.pix_mp.num_planes = dst->planes; + sFormat.fmt.pix.field = V4L2_FIELD_ANY; + + ret = ioctl(fd, VIDIOC_S_FMT, &sFormat); + if (ret < 0) { + SEC_HWC_Log(HWC_LOG_ERROR, "%s::Error in video VIDIOC_S_FMT (%d)", __func__, ret); + return -1; + } + + /* set destination window */ + crop.type = V4L2_BUF_TYPE_CAPTURE; + crop.c.left = dst->start_x; + crop.c.top = dst->start_y; + crop.c.width = dst->width; + crop.c.height = dst->height; + + ret = ioctl(fd, VIDIOC_S_CROP, &crop); + if (ret < 0) { + SEC_HWC_Log(HWC_LOG_ERROR, "%s::Error in video VIDIOC_S_CROP (%d)", __func__, ret); + return -1; + } + + /* input buffer type */ + req.count = 1; + req.type = V4L2_BUF_TYPE_CAPTURE; + req.memory = V4L2_MEMORY_USERPTR; + + ret = ioctl (fd, VIDIOC_REQBUFS, &req); + if (ret < 0) { + SEC_HWC_Log(HWC_LOG_ERROR, "%s::Error in VIDIOC_REQBUFS (%d)", __func__, ret); + return -1; + } +#else + /* set size, format & address for destination image (DMA-OUTPUT) */ + ret = ioctl(fd, VIDIOC_G_FBUF, &fbuf); + if (ret < 0) { + SEC_HWC_Log(HWC_LOG_ERROR, "%s::Error in video VIDIOC_G_FBUF (%d)", __func__, ret); + return -1; + } + + fbuf.base = (void *)addr; + fbuf.fmt.width = dst->full_width; + fbuf.fmt.height = dst->full_height; + fbuf.fmt.pixelformat = dst->color_space; + + ret = ioctl(fd, VIDIOC_S_FBUF, &fbuf); + if (ret < 0) { + SEC_HWC_Log(HWC_LOG_ERROR, "%s::Error in video VIDIOC_S_FBUF (%d)", __func__, ret); + return -1; + } + + /* set destination window */ + sFormat.type = V4L2_BUF_TYPE_VIDEO_OVERLAY; + sFormat.fmt.win.w.left = dst->start_x; + sFormat.fmt.win.w.top = dst->start_y; + sFormat.fmt.win.w.width = dst->width; + sFormat.fmt.win.w.height = dst->height; + + ret = ioctl(fd, VIDIOC_S_FMT, &sFormat); + if (ret < 0) { + SEC_HWC_Log(HWC_LOG_ERROR, "%s::Error in video VIDIOC_S_FMT (%d)", __func__, ret); + return -1; + } +#endif + + return 0; +} + +int fimc_v4l2_stream_on(int fd, enum v4l2_buf_type type) +{ + if (-1 == ioctl(fd, VIDIOC_STREAMON, &type)) { + SEC_HWC_Log(HWC_LOG_ERROR, "Error in VIDIOC_STREAMON\n"); + return -1; + } + + return 0; +} + +int fimc_v4l2_queue(int fd, struct fimc_buf *fimc_buf, enum v4l2_buf_type type, int index) +{ +#ifdef BOARD_USE_V4L2_ION + struct v4l2_plane plane[3]; + int i; +#endif + struct v4l2_buffer buf; + int ret; + +#ifdef BOARD_USE_V4L2_ION + buf.length = fimc_buf->planes; +#else + buf.length = 0; + buf.m.userptr = (unsigned long)fimc_buf; +#endif + buf.memory = V4L2_MEMORY_USERPTR; + buf.index = index; + buf.type = type; + +#ifdef BOARD_USE_V4L2_ION + if (buf.type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE || + buf.type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { + for (i = 0; i < buf.length; i++) { + plane[i].m.userptr = fimc_buf->base[i]; + plane[i].length = fimc_buf->size[i]; + } + } + buf.m.planes = plane; +#endif + + ret = ioctl(fd, VIDIOC_QBUF, &buf); + if (0 > ret) { + SEC_HWC_Log(HWC_LOG_ERROR, "Error in VIDIOC_QBUF : (%d)", ret); + return -1; + } + + return 0; +} + +int fimc_v4l2_dequeue(int fd, struct fimc_buf *fimc_buf, enum v4l2_buf_type type) +{ + struct v4l2_buffer buf; +#ifdef BOARD_USE_V4L2_ION + struct v4l2_plane plane[3]; +#endif + +#ifdef BOARD_USE_V4L2_ION + buf.m.planes = plane; + buf.length = fimc_buf->planes; +#endif + buf.memory = V4L2_MEMORY_USERPTR; + buf.type = type; + + if (-1 == ioctl(fd, VIDIOC_DQBUF, &buf)) { + SEC_HWC_Log(HWC_LOG_ERROR, "Error in VIDIOC_DQBUF\n"); + return -1; + } + + return buf.index; +} + +int fimc_v4l2_stream_off(int fd, enum v4l2_buf_type type) +{ + if (-1 == ioctl(fd, VIDIOC_STREAMOFF, &type)) { + SEC_HWC_Log(HWC_LOG_ERROR, "Error in VIDIOC_STREAMOFF\n"); + return -1; + } + + return 0; +} + +int fimc_v4l2_clr_buf(int fd, enum v4l2_buf_type type) +{ + struct v4l2_requestbuffers req; + + req.count = 0; + req.memory = V4L2_MEMORY_USERPTR; + req.type = type; + + if (ioctl(fd, VIDIOC_REQBUFS, &req) == -1) { + SEC_HWC_Log(HWC_LOG_ERROR, "Error in VIDIOC_REQBUFS"); + } + + return 0; +} + +int fimc_v4l2_S_ctrl(int fd) +{ + struct v4l2_control vc; + + vc.id = V4L2_CID_CACHEABLE; + vc.value = 1; + + if (ioctl(fd, VIDIOC_S_CTRL, &vc) < 0) { + SEC_HWC_Log(HWC_LOG_ERROR, "Error in VIDIOC_S_CTRL"); + return -1; + } + + return 0; +} + +int fimc_handle_oneshot(int fd, struct fimc_buf *fimc_src_buf, struct fimc_buf *fimc_dst_buf) +{ +#ifdef CHECK_FPS + check_fps(); +#endif + +#ifdef BOARD_USE_V4L2_ION + if (fimc_v4l2_queue(fd, fimc_src_buf, V4L2_BUF_TYPE_OUTPUT, 0) < 0) { + SEC_HWC_Log(HWC_LOG_ERROR, "Fail : SRC v4l2_queue()"); + return -1; + } + + if (fimc_v4l2_queue(fd, fimc_dst_buf, V4L2_BUF_TYPE_CAPTURE, 0) < 0) { + SEC_HWC_Log(HWC_LOG_ERROR, "Fail : DST v4l2_queue()"); + return -2; + } + + if (fimc_v4l2_stream_on(fd, V4L2_BUF_TYPE_OUTPUT) < 0) { + SEC_HWC_Log(HWC_LOG_ERROR, "Fail : SRC v4l2_stream_on()"); + return -3; + } + + if (fimc_v4l2_stream_on(fd, V4L2_BUF_TYPE_CAPTURE) < 0) { + SEC_HWC_Log(HWC_LOG_ERROR, "Fail : DST v4l2_stream_on()"); + return -4; + } +#else + if (fimc_v4l2_stream_on(fd, V4L2_BUF_TYPE_OUTPUT) < 0) { + SEC_HWC_Log(HWC_LOG_ERROR, "Fail : SRC v4l2_stream_on()"); + return -5; + } + + if (fimc_v4l2_queue(fd, fimc_src_buf, V4L2_BUF_TYPE_OUTPUT, 0) < 0) { + SEC_HWC_Log(HWC_LOG_ERROR, "Fail : SRC v4l2_queue()"); + goto STREAM_OFF; + } +#endif + if (fimc_v4l2_dequeue(fd, fimc_src_buf, V4L2_BUF_TYPE_OUTPUT) < 0) { + SEC_HWC_Log(HWC_LOG_ERROR, "Fail : SRC v4l2_dequeue()"); + return -6; + } +#ifdef BOARD_USE_V4L2_ION + if (fimc_v4l2_dequeue(fd, fimc_dst_buf, V4L2_BUF_TYPE_CAPTURE) < 0) { + SEC_HWC_Log(HWC_LOG_ERROR, "Fail : DST v4l2_dequeue()"); + return -7; + } +#endif +STREAM_OFF: + if (fimc_v4l2_stream_off(fd, V4L2_BUF_TYPE_OUTPUT) < 0) { + SEC_HWC_Log(HWC_LOG_ERROR, "Fail : SRC v4l2_stream_off()"); + return -8; + } +#ifdef BOARD_USE_V4L2_ION + if (fimc_v4l2_stream_off(fd, V4L2_BUF_TYPE_CAPTURE) < 0) { + SEC_HWC_Log(HWC_LOG_ERROR, "Fail : DST v4l2_stream_off()"); + return -9; + } +#endif + if (fimc_v4l2_clr_buf(fd, V4L2_BUF_TYPE_OUTPUT) < 0) { + SEC_HWC_Log(HWC_LOG_ERROR, "Fail : SRC v4l2_clr_buf()"); + return -10; + } +#ifdef BOARD_USE_V4L2_ION + if (fimc_v4l2_clr_buf(fd, V4L2_BUF_TYPE_CAPTURE)< 0) { + SEC_HWC_Log(HWC_LOG_ERROR, "Fail : DST v4l2_clr_buf()"); + return -11; + } +#endif + return 0; +} + +static int memcpy_rect(void *dst, void *src, int fullW, int fullH, int realW, int realH, int format) +{ + unsigned char *srcCb, *srcCr; + unsigned char *dstCb, *dstCr; + unsigned char *srcY, *dstY; + int srcCbOffset, srcCrOffset; + int dstCbOffset, dstFrameOffset, dstCrOffset; + int cbFullW, cbRealW, cbFullH, cbRealH; + int ySrcFW, ySrcFH, ySrcRW, ySrcRH; + int planes; + int i; + + SEC_HWC_Log(HWC_LOG_DEBUG, + "++memcpy_rect()::" + "dst(0x%x),src(0x%x),f.w(%d),f.h(%d),r.w(%d),r.h(%d),format(0x%x)", + (unsigned int)dst, (unsigned int)src, fullW, fullH, realW, realH, format); + +// Set dst Y, Cb, Cr address for FIMC + { + cbFullW = fullW >> 1; + cbRealW = realW >> 1; + cbFullH = fullH >> 1; + cbRealH = realH >> 1; + dstFrameOffset = fullW * fullH; + dstCrOffset = cbFullW * cbFullH; + dstY = (unsigned char *)dst; + dstCb = (unsigned char *)dst + dstFrameOffset; + dstCr = (unsigned char *)dstCb + dstCrOffset; + } + +// Get src Y, Cb, Cr address for source buffer. +// Each address is aligned by 16's multiple for GPU both width and height. + { + ySrcFW = fullW; + ySrcFH = fullH; + ySrcRW = realW; + ySrcRH = realH; + srcCbOffset = EXYNOS4_ALIGN(ySrcRW,16)* EXYNOS4_ALIGN(ySrcRH,16); + srcCrOffset = EXYNOS4_ALIGN(cbRealW,16)* EXYNOS4_ALIGN(cbRealH,16); + srcY = (unsigned char *)src; + srcCb = (unsigned char *)src + srcCbOffset; + srcCr = (unsigned char *)srcCb + srcCrOffset; + } + SEC_HWC_Log(HWC_LOG_DEBUG, + "--memcpy_rect()::\n" + "dstY(0x%x),dstCb(0x%x),dstCr(0x%x) \n" + "srcY(0x%x),srcCb(0x%x),srcCr(0x%x) \n" + "cbRealW(%d),cbRealH(%d)", + (unsigned int)dstY,(unsigned int)dstCb,(unsigned int)dstCr, + (unsigned int)srcY,(unsigned int)srcCb,(unsigned int)srcCr, + cbRealW, cbRealH); + + if (format == HAL_PIXEL_FORMAT_YV12) { //YV12(Y,Cr,Cv) + planes = 3; +//This is code for VE, deleted temporory by SSONG 2011.09.22 +// This will be enabled later. +/* + //as defined in hardware.h, cb & cr full_width should be aligned to 16. ALIGN(y_stride/2, 16). + ////Alignment is hard coded to 16. + ////for example...check frameworks/media/libvideoeditor/lvpp/VideoEditorTools.cpp file for UV stride cal + cbSrcFW = (cbSrcFW + 15) & (~15); + srcCbOffset = ySrcFW * fullH; + srcCrOffset = srcCbOffset + ((cbSrcFW * fullH) >> 1); + srcY = (unsigned char *)src; + srcCb = (unsigned char *)src + srcCbOffset; + srcCr = (unsigned char *)src + srcCrOffset; +*/ + } else if ((format == HAL_PIXEL_FORMAT_YCbCr_420_P)) { + planes = 3; + } else if (format == HAL_PIXEL_FORMAT_YCbCr_420_SP || format == HAL_PIXEL_FORMAT_YCrCb_420_SP) { + planes = 2; + } else { + SEC_HWC_Log(HWC_LOG_ERROR, "use default memcpy instead of memcpy_rect"); + return -1; + } +//#define CHECK_PERF +#ifdef CHECK_PERF + struct timeval start, end; + gettimeofday(&start, NULL); +#endif + for (i = 0; i < realH; i++) + memcpy(dstY + fullW * i, srcY + ySrcFW * i, ySrcRW); + if (planes == 2) { + for (i = 0; i < cbRealH; i++) + memcpy(dstCb + ySrcFW * i, srcCb + ySrcFW * i, ySrcRW); + } else if (planes == 3) { + for (i = 0; i < cbRealH; i++) + memcpy(dstCb + cbFullW * i, srcCb + cbFullW * i, cbRealW); + for (i = 0; i < cbRealH; i++) + memcpy(dstCr + cbFullW * i, srcCr + cbFullW * i, cbRealW); + } +#ifdef CHECK_PERF + gettimeofday(&end, NULL); + SEC_HWC_Log(HWC_LOG_ERROR, "[COPY]=%d,",(end.tv_sec - start.tv_sec)*1000+(end.tv_usec - start.tv_usec)/1000); +#endif + + return 0; +} + +/*****************************************************************************/ +static int get_src_phys_addr(struct hwc_context_t *ctx, + sec_img *src_img, sec_rect *src_rect) +{ + s5p_fimc_t *fimc = &ctx->fimc; + struct s3c_mem_alloc *ptr_mem_alloc = &ctx->s3c_mem.mem_alloc[0]; + struct s3c_mem_dma_param s3c_mem_dma; +#ifdef USE_HW_PMEM + sec_pmem_alloc_t *pm_alloc = &ctx->sec_pmem.sec_pmem_alloc[0]; +#endif + + unsigned int src_virt_addr = 0; + unsigned int src_phys_addr = 0; + unsigned int src_frame_size = 0; + + struct pmem_region region; + ADDRS * addr; + + // error check routine + if (0 == src_img->base && !(src_img->usage & GRALLOC_USAGE_HW_FIMC1)) { + SEC_HWC_Log(HWC_LOG_ERROR, "%s invalid src image base\n", __func__); + return 0; + } + + switch (src_img->mem_type) { + case HWC_PHYS_MEM_TYPE: + src_phys_addr = src_img->base + src_img->offset; + break; + + case HWC_VIRT_MEM_TYPE: + case HWC_UNKNOWN_MEM_TYPE: + switch (src_img->format) { + case HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_SP: + case HAL_PIXEL_FORMAT_CUSTOM_YCrCb_420_SP: + case HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_SP_TILED: + case HAL_PIXEL_FORMAT_CUSTOM_YCbCr_422_SP: + case HAL_PIXEL_FORMAT_CUSTOM_YCrCb_422_SP: + addr = (ADDRS *)(src_img->base); + fimc->params.src.buf_addr_phy_rgb_y = addr->addr_y; + fimc->params.src.buf_addr_phy_cb = addr->addr_cbcr; + + src_phys_addr = fimc->params.src.buf_addr_phy_rgb_y; + if (0 == src_phys_addr) { + SEC_HWC_Log(HWC_LOG_ERROR, "%s address error " + "(format=CUSTOM_YCbCr/YCrCb_420_SP Y-addr=0x%x " + "CbCr-Addr=0x%x)", + __func__, fimc->params.src.buf_addr_phy_rgb_y, + fimc->params.src.buf_addr_phy_cb); + return 0; + } + break; + case HAL_PIXEL_FORMAT_CUSTOM_YCbCr_422_I: + case HAL_PIXEL_FORMAT_CUSTOM_YCrCb_422_I: + case HAL_PIXEL_FORMAT_CUSTOM_CbYCrY_422_I: + case HAL_PIXEL_FORMAT_CUSTOM_CrYCbY_422_I: + addr = (ADDRS *)(src_img->base + src_img->offset); + fimc->params.src.buf_addr_phy_rgb_y = addr->addr_y; + src_phys_addr = fimc->params.src.buf_addr_phy_rgb_y; + if (0 == src_phys_addr) { + SEC_HWC_Log(HWC_LOG_ERROR, "%s address error " + "(format=CUSTOM_YCbCr/CbYCrY_422_I Y-addr=0x%x)", + __func__, fimc->params.src.buf_addr_phy_rgb_y); + return 0; + } + break; + default: +#ifdef BOARD_USE_V4L2_ION + fimc->params.src.buf_addr_phy_rgb_y = src_img->base; + fimc->params.src.buf_addr_phy_cb = src_img->base + src_img->uoffset; + fimc->params.src.buf_addr_phy_cr = src_img->base + src_img->uoffset + src_img->voffset; + src_phys_addr = fimc->params.src.buf_addr_phy_rgb_y; + break; +#endif + if (src_img->usage & GRALLOC_USAGE_HW_FIMC1) { + fimc->params.src.buf_addr_phy_rgb_y = src_img->paddr; + fimc->params.src.buf_addr_phy_cb = src_img->paddr + src_img->uoffset; + fimc->params.src.buf_addr_phy_cr = src_img->paddr + src_img->uoffset + src_img->voffset; + src_phys_addr = fimc->params.src.buf_addr_phy_rgb_y; + break; + } + // copy + src_frame_size = FRAME_SIZE(src_img->format, src_img->w, src_img->h); + if (src_frame_size == 0) { + SEC_HWC_Log(HWC_LOG_ERROR, "%s::FRAME_SIZE fail", __func__); + return 0; + } + +#ifdef USE_HW_PMEM + if (0 <= checkPmem(&ctx->sec_pmem, 0, src_frame_size)) { + src_virt_addr = pm_alloc->virt_addr; + src_phys_addr = pm_alloc->phys_addr; + pm_alloc->size = src_frame_size; + } else +#endif + if (0 <= checkMem(&ctx->s3c_mem, 0, src_frame_size)) { + src_virt_addr = ptr_mem_alloc->vir_addr; + src_phys_addr = ptr_mem_alloc->phy_addr; + ptr_mem_alloc->size = src_frame_size; + } else { + SEC_HWC_Log(HWC_LOG_ERROR, "%s::check_mem fail", __func__); + return 0; + } + if ((src_img->format == HAL_PIXEL_FORMAT_YCbCr_420_P) || + (src_img->format == HAL_PIXEL_FORMAT_YV12) || + (src_img->format == HAL_PIXEL_FORMAT_YCbCr_420_SP) || + (src_img->format == HAL_PIXEL_FORMAT_YCrCb_420_SP)) { + if (memcpy_rect((void *)src_virt_addr, (void*)((unsigned int)src_img->base), + src_img->f_w, src_img->f_h, src_rect->w, src_rect->h, src_img->format) != 0) + return 0; + } else { + memcpy((void *)src_virt_addr, (void*)((unsigned int)src_img->base), src_frame_size); + } + +#ifdef USE_HW_PMEM + if (pm_alloc->size == src_frame_size) { + region.offset = 0; + region.len = src_frame_size; + if (ioctl(ctx->sec_pmem.pmem_master_fd, PMEM_CACHE_FLUSH, ®ion) < 0) + SEC_HWC_Log(HWC_LOG_ERROR, "%s::pmem cache flush fail ", __func__); + } +#endif + break; + } + } + + return src_phys_addr; +} + +static int get_dst_phys_addr(struct hwc_context_t *ctx, sec_img *dst_img, + sec_rect *dst_rect, int *dst_memcpy_flag) +{ + unsigned int dst_phys_addr = 0; + + if (HWC_PHYS_MEM_TYPE == dst_img->mem_type && 0 != dst_img->base) + dst_phys_addr = dst_img->base; + else + dst_phys_addr = dst_img->base; + + return dst_phys_addr; +} + +static inline int rotateValueHAL2PP(unsigned char transform) +{ + int rotate_flag = transform & 0x7; + + switch (rotate_flag) { + case HAL_TRANSFORM_ROT_90: return 90; + case HAL_TRANSFORM_ROT_180: return 180; + case HAL_TRANSFORM_ROT_270: return 270; + case HAL_TRANSFORM_FLIP_H | HAL_TRANSFORM_ROT_90: return 90; + case HAL_TRANSFORM_FLIP_V | HAL_TRANSFORM_ROT_90: return 90; + case HAL_TRANSFORM_FLIP_H: return 0; + case HAL_TRANSFORM_FLIP_V: return 0; + } + return 0; +} + +static inline int hflipValueHAL2PP(unsigned char transform) +{ + int flip_flag = transform & 0x7; + switch (flip_flag) { + case HAL_TRANSFORM_FLIP_H: + case HAL_TRANSFORM_FLIP_H | HAL_TRANSFORM_ROT_90: + return 1; + case HAL_TRANSFORM_FLIP_V | HAL_TRANSFORM_ROT_90: + case HAL_TRANSFORM_ROT_90: + case HAL_TRANSFORM_ROT_180: + case HAL_TRANSFORM_ROT_270: + case HAL_TRANSFORM_FLIP_V: + break; + } + return 0; +} + +static inline int vflipValueHAL2PP(unsigned char transform) +{ + int flip_flag = transform & 0x7; + switch (flip_flag) { + case HAL_TRANSFORM_FLIP_V: + case HAL_TRANSFORM_FLIP_V | HAL_TRANSFORM_ROT_90: + return 1; + case HAL_TRANSFORM_FLIP_H | HAL_TRANSFORM_ROT_90: + case HAL_TRANSFORM_ROT_90: + case HAL_TRANSFORM_ROT_180: + case HAL_TRANSFORM_ROT_270: + case HAL_TRANSFORM_FLIP_H: + break; + } + return 0; +} + +static inline int multipleOf2(int number) +{ + if (number % 2 == 1) + return (number - 1); + else + return number; +} + +static inline int multipleOf4(int number) +{ + int remain_number = number % 4; + + if (remain_number != 0) + return (number - remain_number); + else + return number; +} + +static inline int multipleOf8(int number) +{ + int remain_number = number % 8; + + if (remain_number != 0) + return (number - remain_number); + else + return number; +} + +static inline int multipleOf16(int number) +{ + int remain_number = number % 16; + + if (remain_number != 0) + return (number - remain_number); + else + return number; +} + +static inline int widthOfPP(unsigned int ver, int pp_color_format, int number) +{ +#ifdef BOARD_USE_V4L2_ION + if (1) { +#else + if (0x50 <= ver) { +#endif + switch (pp_color_format) { + /* 422 1/2/3 plane */ + case V4L2_PIX_FMT_YUYV: + case V4L2_PIX_FMT_UYVY: + case V4L2_PIX_FMT_NV61: + case V4L2_PIX_FMT_NV16: + case V4L2_PIX_FMT_YUV422P: + + /* 420 2/3 plane */ + case V4L2_PIX_FMT_NV21: + case V4L2_PIX_FMT_NV12: + case V4L2_PIX_FMT_NV12T: + case V4L2_PIX_FMT_YUV420: + return multipleOf2(number); + + default : + return number; + } + } else { + switch (pp_color_format) { + case V4L2_PIX_FMT_RGB565: + return multipleOf8(number); + + case V4L2_PIX_FMT_RGB32: + return multipleOf4(number); + + case V4L2_PIX_FMT_YUYV: + case V4L2_PIX_FMT_UYVY: + return multipleOf4(number); + + case V4L2_PIX_FMT_NV61: + case V4L2_PIX_FMT_NV16: + return multipleOf8(number); + + case V4L2_PIX_FMT_YUV422P: + return multipleOf16(number); + + case V4L2_PIX_FMT_NV21: + case V4L2_PIX_FMT_NV12: + case V4L2_PIX_FMT_NV12T: + return multipleOf8(number); + + case V4L2_PIX_FMT_YUV420: + return multipleOf16(number); + + default : + return number; + } + } + return number; +} + +static inline int heightOfPP(int pp_color_format, int number) +{ + switch (pp_color_format) { + case V4L2_PIX_FMT_NV21: + case V4L2_PIX_FMT_NV12: + case V4L2_PIX_FMT_NV12T: + case V4L2_PIX_FMT_YUV420: + return multipleOf2(number); + + default : + return number; + break; + } + return number; +} + +static unsigned int get_yuv_bpp(unsigned int fmt) +{ + int i, sel = -1; + + for (i = 0; i < (int)(sizeof(yuv_list) / sizeof(struct yuv_fmt_list)); i++) { + if (yuv_list[i].fmt == fmt) { + sel = i; + break; + } + } + + if (sel == -1) + return sel; + else + return yuv_list[sel].bpp; +} + +static unsigned int get_yuv_planes(unsigned int fmt) +{ + int i, sel = -1; + + for (i = 0; i < (int)(sizeof(yuv_list) / sizeof(struct yuv_fmt_list)); i++) { + if (yuv_list[i].fmt == fmt) { + sel = i; + break; + } + } + + if (sel == -1) + return sel; + else + return yuv_list[sel].planes; +} + +static int runcFimcCore(struct hwc_context_t *ctx, + unsigned int src_phys_addr, sec_img *src_img, sec_rect *src_rect, + uint32_t src_color_space, + unsigned int dst_phys_addr, sec_img *dst_img, sec_rect *dst_rect, + uint32_t dst_color_space, int transform) +{ + s5p_fimc_t * fimc = &ctx->fimc; + s5p_fimc_params_t * params = &(fimc->params); + + struct fimc_buf fimc_src_buf; + int src_bpp, src_planes; + +#ifdef BOARD_USE_V4L2_ION + struct fimc_buf fimc_dst_buf; + int dst_bpp, dst_planes; + unsigned int src_frame_size = 0; + unsigned int dst_frame_size = 0; +#endif + unsigned int frame_size = 0; + + bool src_cbcr_order = true; + int rotate_value = rotateValueHAL2PP(transform); + int hflip = hflipValueHAL2PP(transform); + int vflip = vflipValueHAL2PP(transform); + + /* 1. param(fimc config)->src information + * - src_img,src_rect => s_fw,s_fh,s_w,s_h,s_x,s_y + */ + params->src.full_width = src_img->f_w; + params->src.full_height = src_img->f_h; + params->src.width = src_rect->w; + params->src.height = src_rect->h; + params->src.start_x = src_rect->x; + params->src.start_y = src_rect->y; + params->src.color_space = src_color_space; + params->src.buf_addr_phy_rgb_y = src_phys_addr; + +#ifdef BOARD_USE_V4L2_ION + params->dst.full_width = dst_img->f_w; + params->dst.full_height = dst_img->f_h; + params->dst.width = widthOfPP(fimc->hw_ver, dst_color_space, dst_rect->w); + params->dst.height = heightOfPP(dst_color_space, dst_rect->h); + params->dst.start_x = dst_rect->x; + params->dst.start_y = dst_rect->y; + params->dst.color_space = dst_color_space; + params->dst.buf_addr_phy_rgb_y = dst_phys_addr; +#endif + + /* check src minimum */ + if (src_rect->w < 16 || src_rect->h < 8) { + SEC_HWC_Log(HWC_LOG_ERROR, + "%s src size is not supported by fimc : f_w=%d f_h=%d " + "x=%d y=%d w=%d h=%d (ow=%d oh=%d) format=0x%x", __func__, + params->src.full_width, params->src.full_height, + params->src.start_x, params->src.start_y, + params->src.width, params->src.height, + src_rect->w, src_rect->h, + params->src.color_space); + return -1; + } + +#ifdef BOARD_USE_V4L2_ION +#else + /* 2. param(fimc config)->dst information + * - dst_img,dst_rect,rot => d_fw,d_fh,d_w,d_h,d_x,d_y + */ + switch (rotate_value) { + case 0: + params->dst.full_width = dst_img->f_w; + params->dst.full_height = dst_img->f_h; + + params->dst.start_x = dst_rect->x; + params->dst.start_y = dst_rect->y; + + params->dst.width = + widthOfPP(fimc->hw_ver, dst_color_space, dst_rect->w); + params->dst.height = heightOfPP(dst_color_space, dst_rect->h); + break; + case 90: + params->dst.full_width = dst_img->f_h; + params->dst.full_height = dst_img->f_w; + + params->dst.start_x = dst_rect->y; + params->dst.start_y = dst_img->f_w - (dst_rect->x + dst_rect->w); + + params->dst.width = + widthOfPP(fimc->hw_ver, dst_color_space, dst_rect->h); + params->dst.height = + widthOfPP(fimc->hw_ver, dst_color_space, dst_rect->w); + + if (0x50 > fimc->hw_ver) + params->dst.start_y += (dst_rect->w - params->dst.height); + break; + case 180: + params->dst.full_width = dst_img->f_w; + params->dst.full_height = dst_img->f_h; + + params->dst.start_x = dst_img->f_w - (dst_rect->x + dst_rect->w); + params->dst.start_y = dst_img->f_h - (dst_rect->y + dst_rect->h); + + params->dst.width = + widthOfPP(fimc->hw_ver, dst_color_space, dst_rect->w); + params->dst.height = heightOfPP(dst_color_space, dst_rect->h); + break; + case 270: + params->dst.full_width = dst_img->f_h; + params->dst.full_height = dst_img->f_w; + + params->dst.start_x = dst_img->f_h - (dst_rect->y + dst_rect->h); + params->dst.start_y = dst_rect->x; + + params->dst.width = + widthOfPP(fimc->hw_ver, dst_color_space, dst_rect->h); + params->dst.height = + widthOfPP(fimc->hw_ver, dst_color_space, dst_rect->w); + + if (0x50 > fimc->hw_ver) + params->dst.start_y += (dst_rect->w - params->dst.height); + break; + } + params->dst.color_space = dst_color_space; +#endif + + SEC_HWC_Log(HWC_LOG_DEBUG, + "runcFimcCore()::" + "SRC f.w(%d),f.h(%d),x(%d),y(%d),w(%d),h(%d)=>" + "DST f.w(%d),f.h(%d),x(%d),y(%d),w(%d),h(%d)", + params->src.full_width, params->src.full_height, + params->src.start_x, params->src.start_y, + params->src.width, params->src.height, + params->dst.full_width, params->dst.full_height, + params->dst.start_x, params->dst.start_y, + params->dst.width, params->dst.height); + + /* check dst minimum */ + if (dst_rect->w < 8 || dst_rect->h < 4) { + SEC_HWC_Log(HWC_LOG_ERROR, + "%s dst size is not supported by fimc : f_w=%d f_h=%d " + "x=%d y=%d w=%d h=%d (ow=%d oh=%d) format=0x%x", __func__, + params->dst.full_width, params->dst.full_height, + params->dst.start_x, params->dst.start_y, + params->dst.width, params->dst.height, + dst_rect->w, dst_rect->h, params->dst.color_space); + return -1; + } + /* check scaling limit + * the scaling limie must not be more than MAX_RESIZING_RATIO_LIMIT + */ + if (((src_rect->w > dst_rect->w) && + ((src_rect->w / dst_rect->w) > MAX_RESIZING_RATIO_LIMIT)) || + ((dst_rect->w > src_rect->w) && + ((dst_rect->w / src_rect->w) > MAX_RESIZING_RATIO_LIMIT))) { + SEC_HWC_Log(HWC_LOG_ERROR, + "%s over scaling limit : src.w=%d dst.w=%d (limit=%d)", + __func__, src_rect->w, dst_rect->w, MAX_RESIZING_RATIO_LIMIT); + return -1; + } + + /* 3. Set configuration related to destination (DMA-OUT) + * - set input format & size + * - crop input size + * - set input buffer + * - set buffer type (V4L2_MEMORY_USERPTR) + */ +#ifdef BOARD_USE_V4L2_ION + switch (dst_img->format) { + case HAL_PIXEL_FORMAT_RGBA_8888: + case HAL_PIXEL_FORMAT_RGBX_8888: + case HAL_PIXEL_FORMAT_RGB_888: + case HAL_PIXEL_FORMAT_BGRA_8888: + dst_planes = 1; + dst_bpp = 32; + break; + + case HAL_PIXEL_FORMAT_RGB_565: + case HAL_PIXEL_FORMAT_RGBA_5551: + case HAL_PIXEL_FORMAT_RGBA_4444: + dst_planes = 1; + dst_bpp = 16; + break; + } + + dst_frame_size = params->dst.width * params->dst.height ; + params->dst.planes = dst_planes; + + if (dst_planes == 1) { + fimc_dst_buf.base[0] = params->dst.buf_addr_phy_rgb_y; + if (dst_bpp == 32) + fimc_dst_buf.size[0] = dst_frame_size * 4; + else if (dst_bpp == 16) + fimc_dst_buf.size[0] = dst_frame_size * 2; + } +#endif + + if (fimc_v4l2_set_dst(fimc->dev_fd, ¶ms->dst, rotate_value, hflip, vflip, dst_phys_addr) < 0) { + SEC_HWC_Log(HWC_LOG_ERROR, "fimc_v4l2_set_dst is failed\n"); + return -1; + } + + /* 4. Set configuration related to source (DMA-INPUT) + * - set input format & size + * - crop input size + * - set input buffer + * - set buffer type (V4L2_MEMORY_USERPTR) + */ +#ifndef BOARD_USE_V4L2_ION + if (fimc_v4l2_set_src(fimc->dev_fd, fimc->hw_ver, ¶ms->src) < 0) { + SEC_HWC_Log(HWC_LOG_ERROR, "fimc_v4l2_set_src is failed\n"); + return -1; + } +#endif + + /* 5. Set input dma address (Y/RGB, Cb, Cr) + * - zero copy : mfc, camera + * - memcpy to pmem : SW dec(420P), video editor(YV12) + */ + switch (src_img->format) { + case HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_SP: + case HAL_PIXEL_FORMAT_CUSTOM_YCrCb_420_SP: + case HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_SP_TILED: + case HAL_PIXEL_FORMAT_CUSTOM_YCbCr_422_SP: + case HAL_PIXEL_FORMAT_CUSTOM_YCrCb_422_SP: + /* for video contents zero copy case */ + fimc_src_buf.base[0] = params->src.buf_addr_phy_rgb_y; + fimc_src_buf.base[1] = params->src.buf_addr_phy_cb; + break; + + case HAL_PIXEL_FORMAT_CUSTOM_YCbCr_422_I: + case HAL_PIXEL_FORMAT_CUSTOM_YCrCb_422_I: + case HAL_PIXEL_FORMAT_CUSTOM_CbYCrY_422_I: + case HAL_PIXEL_FORMAT_CUSTOM_CrYCbY_422_I: + case HAL_PIXEL_FORMAT_RGB_565: + case HAL_PIXEL_FORMAT_YV12: + default: + if (src_img->format == HAL_PIXEL_FORMAT_YV12) + src_cbcr_order = false; + +#ifdef BOARD_USE_V4L2_ION + fimc_src_buf.base[0] = params->src.buf_addr_phy_rgb_y; + if (src_cbcr_order == true) { + fimc_src_buf.base[1] = params->src.buf_addr_phy_cb; + fimc_src_buf.base[2] = params->src.buf_addr_phy_cr; + } else { + fimc_src_buf.base[1] = params->src.buf_addr_phy_cr; + fimc_src_buf.base[2] = params->src.buf_addr_phy_cb; + } + SEC_HWC_Log(HWC_LOG_DEBUG, + "runFimcCore - Y=0x%X, U=0x%X, V=0x%X\n", + fimc_src_buf.base[0], fimc_src_buf.base[1],fimc_src_buf.base[2]); + src_frame_size = params->src.full_width * params->src.full_height; + fimc_src_buf.size[0] = src_frame_size; + fimc_src_buf.size[1] = src_frame_size >> 2; + fimc_src_buf.size[2] = src_frame_size >> 2; + SEC_HWC_Log(HWC_LOG_DEBUG, + "runFimcCore - Y_length=%d, U_length=%d, V_length=%d\n", + fimc_src_buf.size[0], fimc_src_buf.size[1],fimc_src_buf.size[2]); + src_planes = get_yuv_planes(src_color_space); + + break; +#endif + + if (src_img->usage & GRALLOC_USAGE_HW_FIMC1) { + fimc_src_buf.base[0] = params->src.buf_addr_phy_rgb_y; + if (src_cbcr_order == true) { + fimc_src_buf.base[1] = params->src.buf_addr_phy_cb; + fimc_src_buf.base[2] = params->src.buf_addr_phy_cr; + } + else { + fimc_src_buf.base[2] = params->src.buf_addr_phy_cb; + fimc_src_buf.base[1] = params->src.buf_addr_phy_cr; + } + SEC_HWC_Log(HWC_LOG_DEBUG, + "runFimcCore - Y=0x%X, U=0x%X, V=0x%X\n", + fimc_src_buf.base[0], fimc_src_buf.base[1],fimc_src_buf.base[2]); + break; + } + + /* set source Y image */ + fimc_src_buf.base[0] = params->src.buf_addr_phy_rgb_y; + /* set source Cb,Cr images for 2 or 3 planes */ + src_bpp = get_yuv_bpp(src_color_space); + src_planes = get_yuv_planes(src_color_space); + if (2 == src_planes) { /* 2 planes */ + frame_size = params->src.full_width * params->src.full_height; + params->src.buf_addr_phy_cb = + params->src.buf_addr_phy_rgb_y + frame_size; + /* CbCr */ + fimc_src_buf.base[1] = params->src.buf_addr_phy_cb; + } else if (3 == src_planes) { /* 3 planes */ + frame_size = params->src.full_width * params->src.full_height; + params->src.buf_addr_phy_cb = + params->src.buf_addr_phy_rgb_y + frame_size; + if (12 == src_bpp) + params->src.buf_addr_phy_cr = + params->src.buf_addr_phy_cb + (frame_size >> 2); + else + params->src.buf_addr_phy_cr = + params->src.buf_addr_phy_cb + (frame_size >> 1); + /* Cb, Cr */ + if (src_cbcr_order == true) { + fimc_src_buf.base[1] = params->src.buf_addr_phy_cb; + fimc_src_buf.base[2] = params->src.buf_addr_phy_cr; + } + else { + fimc_src_buf.base[2] = params->src.buf_addr_phy_cb; + fimc_src_buf.base[1] = params->src.buf_addr_phy_cr; + } + } + break; + } + + /* 6. Run FIMC + * - stream on => queue => dequeue => stream off => clear buf + */ +#ifdef BOARD_USE_V4L2_ION + int ret = 0; + params->src.planes = src_planes; + + if (fimc_v4l2_set_src(fimc->dev_fd, fimc->hw_ver, ¶ms->src) < 0) { + SEC_HWC_Log(HWC_LOG_ERROR, "fimc_v4l2_set_src is failed\n"); + return -1; + } + + fimc_src_buf.planes = src_planes; + fimc_dst_buf.planes = dst_planes; + + ret = fimc_handle_oneshot(fimc->dev_fd, &fimc_src_buf, &fimc_dst_buf); + + if (ret < 0) { + SEC_HWC_Log(HWC_LOG_ERROR,"fimc_handle_oneshot = %d\n",ret); + if (ret == -2) { + fimc_v4l2_clr_buf(fimc->dev_fd, V4L2_BUF_TYPE_OUTPUT); + } else if (ret == -3) { + fimc_v4l2_clr_buf(fimc->dev_fd, V4L2_BUF_TYPE_OUTPUT); + fimc_v4l2_clr_buf(fimc->dev_fd, V4L2_BUF_TYPE_CAPTURE); + } + return ret; + } +#else + if (fimc_handle_oneshot(fimc->dev_fd, &fimc_src_buf, NULL) < 0) { + fimc_v4l2_clr_buf(fimc->dev_fd, V4L2_BUF_TYPE_OUTPUT); + return -1; + } +#endif + + return 0; +} + +#ifdef SUB_TITLES_HWC +int createG2d(sec_g2d_t *g2d) +{ + g2d->dev_fd = open(SEC_G2D_DEV_NAME, O_RDWR); + + if (g2d->dev_fd <= 0) { + SEC_HWC_Log(HWC_LOG_ERROR, "%s::G2d open error (%d)", __func__, errno); + goto err; + } + + return 0; +err: + if (0 < g2d->dev_fd) + close(g2d->dev_fd); + g2d->dev_fd =0; + + return -1; +} + +int destroyG2d(sec_g2d_t *g2d) +{ + // close + if (0 < g2d->dev_fd) + close(g2d->dev_fd); + g2d->dev_fd = 0; + + return 0; +} +#endif + +int createFimc(s5p_fimc_t *fimc) +{ + struct v4l2_capability cap; + struct v4l2_format fmt; + struct v4l2_control vc; + + // open device file + if (fimc->dev_fd <= 0) + fimc->dev_fd = open(PP_DEVICE_DEV_NAME, O_RDWR); + + if (fimc->dev_fd <= 0) { + SEC_HWC_Log(HWC_LOG_ERROR, "%s::Post processor open error (%d)", + __func__, errno); + goto err; + } + + // check capability + if (ioctl(fimc->dev_fd, VIDIOC_QUERYCAP, &cap) < 0) { + SEC_HWC_Log(HWC_LOG_ERROR, "VIDIOC_QUERYCAP failed"); + goto err; + } + + if (!(cap.capabilities & V4L2_CAP_STREAMING)) { + SEC_HWC_Log(HWC_LOG_ERROR, "%d has no streaming support", fimc->dev_fd); + goto err; + } + + if (!(cap.capabilities & V4L2_CAP_VIDEO_OUTPUT)) { + SEC_HWC_Log(HWC_LOG_ERROR, "%d is no video output", fimc->dev_fd); + goto err; + } + + /* + * malloc fimc_outinfo structure + */ + fmt.type = V4L2_BUF_TYPE_OUTPUT; + if (ioctl(fimc->dev_fd, VIDIOC_G_FMT, &fmt) < 0) { + SEC_HWC_Log(HWC_LOG_ERROR, "%s::Error in video VIDIOC_G_FMT", __func__); + goto err; + } + +#ifdef BOARD_USE_V4L2_ION +#else + vc.id = V4L2_CID_FIMC_VERSION; + vc.value = 0; + + if (ioctl(fimc->dev_fd, VIDIOC_G_CTRL, &vc) < 0) { + SEC_HWC_Log(HWC_LOG_ERROR, "%s::Error in video VIDIOC_G_CTRL", __func__); + goto err; + } + fimc->hw_ver = vc.value; +#endif + + return 0; + +err: + if (0 < fimc->dev_fd) + close(fimc->dev_fd); + fimc->dev_fd =0; + + return -1; +} + +int destroyFimc(s5p_fimc_t *fimc) +{ + if (fimc->out_buf.virt_addr != NULL) { + fimc->out_buf.virt_addr = NULL; + fimc->out_buf.length = 0; + } + + // close + if (0 < fimc->dev_fd) + close(fimc->dev_fd); + fimc->dev_fd = 0; + + return 0; +} + +int runFimc(struct hwc_context_t *ctx, + struct sec_img *src_img, struct sec_rect *src_rect, + struct sec_img *dst_img, struct sec_rect *dst_rect, + uint32_t transform) +{ + s5p_fimc_t * fimc = &ctx->fimc; + + unsigned int src_phys_addr = 0; + unsigned int dst_phys_addr = 0; + int rotate_value = 0; + int flag_force_memcpy = 0; + int32_t src_color_space; + int32_t dst_color_space; + + /* 1. source address and size */ + src_phys_addr = get_src_phys_addr(ctx, src_img, src_rect); + if (0 == src_phys_addr) + return -1; + + /* 2. destination address and size */ + dst_phys_addr = get_dst_phys_addr(ctx, dst_img, dst_rect, &flag_force_memcpy); + if (0 == dst_phys_addr) + return -2; + + /* 3. check whether fimc supports the src format */ + src_color_space = HAL_PIXEL_FORMAT_2_V4L2_PIX(src_img->format); + if (0 > src_color_space) + return -3; + dst_color_space = HAL_PIXEL_FORMAT_2_V4L2_PIX(dst_img->format); + if (0 > dst_color_space) + return -4; + + /* 4. FIMC: src_rect of src_img => dst_rect of dst_img */ + if (runcFimcCore(ctx, src_phys_addr, src_img, src_rect, + (uint32_t)src_color_space, dst_phys_addr, dst_img, dst_rect, + (uint32_t)dst_color_space, transform) < 0) + return -5; + + if (flag_force_memcpy == 1) { +#ifdef USE_HW_PMEM + if (0 != ctx->sec_pmem.sec_pmem_alloc[1].size) { + struct s3c_mem_dma_param s3c_mem_dma; + + s3c_mem_dma.src_addr = + (unsigned long)(ctx->sec_pmem.sec_pmem_alloc[1].virt_addr); + s3c_mem_dma.size = ctx->sec_pmem.sec_pmem_alloc[1].size; + + ioctl(ctx->s3c_mem.fd, S3C_MEM_CACHE_INVAL, &s3c_mem_dma); + + memcpy((void*)((unsigned int)dst_img->base), + (void *)(ctx->sec_pmem.sec_pmem_alloc[1].virt_addr), + ctx->sec_pmem.sec_pmem_alloc[1].size); + } else +#endif + { + struct s3c_mem_alloc *ptr_mem_alloc = &ctx->s3c_mem.mem_alloc[1]; + struct s3c_mem_dma_param s3c_mem_dma; + + s3c_mem_dma.src_addr = (unsigned long)ptr_mem_alloc->vir_addr; + s3c_mem_dma.size = ptr_mem_alloc->size; + + ioctl(ctx->s3c_mem.fd, S3C_MEM_CACHE_INVAL, &s3c_mem_dma); + + memcpy((void*)((unsigned int)dst_img->base), + (void *)ptr_mem_alloc->vir_addr, ptr_mem_alloc->size); + } + } + + return 0; +} + +#ifdef SUB_TITLES_HWC +static int get_g2d_src_phys_addr(struct hwc_context_t *ctx, g2d_rect *src_rect) +{ + sec_g2d_t *g2d = &ctx->g2d; + struct s3c_mem_alloc *ptr_mem_alloc = &ctx->s3c_mem.mem_alloc[0]; +#ifdef USE_HW_PMEM + sec_pmem_alloc_t *pm_alloc = &ctx->sec_pmem.sec_pmem_alloc[0]; +#endif + + unsigned int src_virt_addr = 0; + unsigned int src_phys_addr = 0; + unsigned int src_frame_size = 0; + + struct pmem_region region; + + // error check routine + if (0 == src_rect->virt_addr) { + SEC_HWC_Log(HWC_LOG_ERROR, "%s invalid src address\n", __func__); + return 0; + } + + src_frame_size = FRAME_SIZE(src_rect->color_format, + src_rect->full_w, src_rect->full_h); + if (src_frame_size == 0) { + SEC_HWC_Log(HWC_LOG_ERROR, "%s::FRAME_SIZE fail", __func__); + return 0; + } + +#ifdef USE_HW_PMEM + if (0 <= checkPmem(&ctx->sec_pmem, 0, src_frame_size)) { + src_virt_addr = pm_alloc->virt_addr; + src_phys_addr = pm_alloc->phys_addr; + pm_alloc->size = src_frame_size; + } else +#endif + if (0 <= checkMem(&ctx->s3c_mem, 0, src_frame_size)) { + src_virt_addr = ptr_mem_alloc->vir_addr; + src_phys_addr = ptr_mem_alloc->phy_addr; + ptr_mem_alloc->size = src_frame_size; + } else { + SEC_HWC_Log(HWC_LOG_ERROR, "%s::check_mem fail", __func__); + return 0; + } + memcpy((void *)src_virt_addr, (void*)((unsigned int)src_rect->virt_addr), src_frame_size); + + return src_phys_addr; +} + +int get_HAL_2_G2D_FORMAT(int format) +{ + switch (format) { + case HAL_PIXEL_FORMAT_RGBA_8888: return G2D_ABGR_8888; + case HAL_PIXEL_FORMAT_RGBX_8888: return G2D_XBGR_8888; + case HAL_PIXEL_FORMAT_BGRA_8888: return G2D_ARGB_8888; + case HAL_PIXEL_FORMAT_RGB_888: return G2D_PACKED_BGR_888; + case HAL_PIXEL_FORMAT_RGB_565: return G2D_RGB_565; + case HAL_PIXEL_FORMAT_RGBA_5551: return G2D_RGBA_5551; + case HAL_PIXEL_FORMAT_RGBA_4444: return G2D_RGBA_4444; + default: + return -1; + } +} + +static inline int rotateValueHAL2G2D(unsigned char transform) +{ + int rotate_flag = transform & 0x7; + + switch (rotate_flag) { + case HAL_TRANSFORM_ROT_90: return G2D_ROT_90; + case HAL_TRANSFORM_ROT_180: return G2D_ROT_180; + case HAL_TRANSFORM_ROT_270: return G2D_ROT_270; + default: + return G2D_ROT_0; + } +} + +int runG2d(struct hwc_context_t *ctx, g2d_rect *src_rect, g2d_rect *dst_rect, + uint32_t transform) +{ + sec_g2d_t * g2d = &ctx->g2d; + g2d_flag flag = {G2D_ROT_0, G2D_ALPHA_BLENDING_OPAQUE, 0, 0, 0, 0, 0, 0}; + int rotate_value = 0; + + // 1 : source address and size + src_rect->phys_addr = get_g2d_src_phys_addr(ctx, src_rect); + if (0 == src_rect->phys_addr) + return -1; + + // 2 : destination address and size + if (0 == dst_rect->phys_addr) + return -2; + + // check whether g2d supports the src format + src_rect->color_format = get_HAL_2_G2D_FORMAT(src_rect->color_format); + if (0 > src_rect->color_format) + return -3; + + dst_rect->color_format = get_HAL_2_G2D_FORMAT(dst_rect->color_format); + if (0 > dst_rect->color_format) + return -4; + + flag.rotate_val = rotateValueHAL2G2D(transform); + + // scale and rotate and alpha with FIMG + if(stretchSecFimg(src_rect, dst_rect, &flag) < 0) + return -5; + + return 0; +} +#endif + +int createMem(struct s3c_mem_t *mem, unsigned int index, unsigned int size) +{ + struct s3c_mem_alloc *ptr_mem_alloc; + struct s3c_mem_alloc mem_alloc_info; + + if (index >= NUM_OF_MEM_OBJ) { + SEC_HWC_Log(HWC_LOG_ERROR, "%s::invalid index (%d >= %d)", + __func__, index, NUM_OF_MEM_OBJ); + goto err; + } + + ptr_mem_alloc = &mem->mem_alloc[index]; + + if (mem->fd <= 0) { + mem->fd = open(S3C_MEM_DEV_NAME, O_RDWR); + if (mem->fd <= 0) { + SEC_HWC_Log(HWC_LOG_ERROR, "%s::open(%s) fail(%s)", + __func__, S3C_MEM_DEV_NAME, strerror(errno)); + goto err; + } + } + + // kcoolsw : what the hell of this line?? + if (0 == size) + return 0; + + mem_alloc_info.size = size; + + if (ioctl(mem->fd, S3C_MEM_CACHEABLE_ALLOC, &mem_alloc_info) < 0) { + SEC_HWC_Log(HWC_LOG_ERROR, "%s::S3C_MEM_ALLOC(size : %d) fail", + __func__, mem_alloc_info.size); + goto err; + } + + ptr_mem_alloc->phy_addr = mem_alloc_info.phy_addr; + ptr_mem_alloc->vir_addr = mem_alloc_info.vir_addr; + ptr_mem_alloc->size = mem_alloc_info.size; + + return 0; + +err: + if (0 < mem->fd) + close(mem->fd); + mem->fd = 0; + + return 0; +} + +int destroyMem(struct s3c_mem_t *mem) +{ + int i; + struct s3c_mem_alloc *ptr_mem_alloc; + + if (mem->fd <= 0) { + SEC_HWC_Log(HWC_LOG_ERROR, "%s::invalied fd(%d) fail", __func__, mem->fd); + return -1; + } + + for (i = 0; i < NUM_OF_MEM_OBJ; i++) { + ptr_mem_alloc = &mem->mem_alloc[i]; + + if (0 != ptr_mem_alloc->vir_addr) { + if (ioctl(mem->fd, S3C_MEM_FREE, ptr_mem_alloc) < 0) { + SEC_HWC_Log(HWC_LOG_ERROR, "%s::S3C_MEM_FREE fail", __func__); + return -1; + } + + ptr_mem_alloc->phy_addr = 0; + ptr_mem_alloc->vir_addr = 0; + ptr_mem_alloc->size = 0; + } + } + + close(mem->fd); + mem->fd = 0; + + return 0; +} + +int checkMem(struct s3c_mem_t *mem, unsigned int index, unsigned int size) +{ + int ret; + struct s3c_mem_alloc *ptr_mem_alloc; + struct s3c_mem_alloc mem_alloc_info; + + if (index >= NUM_OF_MEM_OBJ) { + SEC_HWC_Log(HWC_LOG_ERROR, "%s::invalid index (%d >= %d)", __func__, + index, NUM_OF_MEM_OBJ); + return -1; + } + + if (mem->fd <= 0) { + ret = createMem(mem, index, size); + return ret; + } + + ptr_mem_alloc = &mem->mem_alloc[index]; + + if (ptr_mem_alloc->size < (int)size) { + if (0 < ptr_mem_alloc->size) { + // free allocated mem + if (ioctl(mem->fd, S3C_MEM_FREE, ptr_mem_alloc) < 0) { + SEC_HWC_Log(HWC_LOG_ERROR, "%s::S3C_MEM_FREE fail", __func__); + return -1; + } + } + + // allocate mem with requested size + mem_alloc_info.size = size; + if (ioctl(mem->fd, S3C_MEM_CACHEABLE_ALLOC, &mem_alloc_info) < 0) { + SEC_HWC_Log(HWC_LOG_ERROR, "%s::S3C_MEM_ALLOC(size : %d) fail", + __func__, mem_alloc_info.size); + return -1; + } + + ptr_mem_alloc->phy_addr = mem_alloc_info.phy_addr; + ptr_mem_alloc->vir_addr = mem_alloc_info.vir_addr; + ptr_mem_alloc->size = mem_alloc_info.size; + } + + return 0; +} + +#ifdef USE_HW_PMEM +int createPmem(sec_pmem_t *pm, unsigned int buf_size) +{ + int master_fd, err = 0, i; + void *base; + unsigned int phys_base; + size_t size, sub_size[NUM_OF_MEM_OBJ]; + struct pmem_region region; + + master_fd = open(PMEM_DEVICE_DEV_NAME, O_RDWR, 0); + if (master_fd < 0) { + pm->pmem_master_fd = -1; + if (EACCES == errno) { + return 0; + } else { + SEC_HWC_Log(HWC_LOG_ERROR, "%s::open(%s) fail(%s)", + __func__, PMEM_DEVICE_DEV_NAME, strerror(errno)); + return -errno; + } + } + + if (ioctl(master_fd, PMEM_GET_TOTAL_SIZE, ®ion) < 0) { + SEC_HWC_Log(HWC_LOG_ERROR, "PMEM_GET_TOTAL_SIZE failed, default mode"); + size = 8<<20; // 8 MiB + } else { + size = region.len; + } + + base = mmap(0, size, PROT_READ|PROT_WRITE, MAP_SHARED, master_fd, 0); + if (base == MAP_FAILED) { + SEC_HWC_Log(HWC_LOG_ERROR, "[%s] mmap failed : %d (%s)", __func__, + errno, strerror(errno)); + base = 0; + close(master_fd); + master_fd = -1; + return -errno; + } + + if (ioctl(master_fd, PMEM_GET_PHYS, ®ion) < 0) { + SEC_HWC_Log(HWC_LOG_ERROR, "PMEM_GET_PHYS failed, limp mode"); + region.offset = 0; + } + + pm->pmem_master_fd = master_fd; + pm->pmem_master_base = base; + pm->pmem_total_size = size; + //pm->pmem_master_phys_base = region.offset; + phys_base = region.offset; + + // sec_pmem_alloc[0] for temporary buffer for source + sub_size[0] = buf_size; + sub_size[0] = roundUpToPageSize(sub_size[0]); + + for (i = 0; i < NUM_OF_MEM_OBJ; i++) { + sec_pmem_alloc_t *pm_alloc = &(pm->sec_pmem_alloc[i]); + int fd, ret; + int offset = i ? sub_size[i-1] : 0; + struct pmem_region sub = { offset, sub_size[i] }; + + // create the "sub-heap" + if (0 > (fd = open(PMEM_DEVICE_DEV_NAME, O_RDWR, 0))) { + SEC_HWC_Log(HWC_LOG_ERROR, + "[%s][index=%d] open failed (%dL) : %d (%s)", + __func__, i, __LINE__, errno, strerror(errno)); + return -errno; + } + + // connect to it + if (0 != (ret = ioctl(fd, PMEM_CONNECT, pm->pmem_master_fd))) { + SEC_HWC_Log(HWC_LOG_ERROR, + "[%s][index=%d] ioctl(PMEM_CONNECT) failed : %d (%s)", + __func__, i, errno, strerror(errno)); + close(fd); + return -errno; + } + + // make it available to the client process + if (0 != (ret = ioctl(fd, PMEM_MAP, &sub))) { + SEC_HWC_Log(HWC_LOG_ERROR, + "[%s][index=%d] ioctl(PMEM_MAP) failed : %d (%s)", + __func__, i, errno, strerror(errno)); + close(fd); + return -errno; + } + + pm_alloc->fd = fd; + pm_alloc->total_size = sub_size[i]; + pm_alloc->offset = offset; + pm_alloc->virt_addr = (unsigned int)base + (unsigned int)offset; + pm_alloc->phys_addr = (unsigned int)phys_base + (unsigned int)offset; + +#if defined (PMEM_DEBUG) + SEC_HWC_Log(HWC_LOG_DEBUG, "[%s] pm_alloc[%d] fd=%d total_size=%d " + "offset=0x%x virt_addr=0x%x phys_addr=0x%x", + __func__, i, pm_alloc->fd, pm_alloc->total_size, + pm_alloc->offset, pm_alloc->virt_addr, pm_alloc->phys_addr); +#endif + } + + return err; +} + +int destroyPmem(sec_pmem_t *pm) +{ + int i, err; + + for (i=0; isec_pmem_alloc[i]); + + if (0 <= pm_alloc->fd) { + struct pmem_region sub = { pm_alloc->offset, pm_alloc->total_size }; + + if (0 > (err = ioctl(pm_alloc->fd, PMEM_UNMAP, &sub))) + SEC_HWC_Log(HWC_LOG_ERROR, + "[%s][index=%d] ioctl(PMEM_UNMAP) failed : %d (%s)", + __func__, i, errno, strerror(errno)); +#if defined (PMEM_DEBUG) + else + SEC_HWC_Log(HWC_LOG_DEBUG, + "[%s] pm_alloc[%d] unmap fd=%d total_size=%d offset=0x%x", + __func__, i, pm_alloc->fd, pm_alloc->total_size, + pm_alloc->offset); +#endif + close(pm_alloc->fd); + + pm_alloc->fd = -1; + pm_alloc->total_size = 0; + pm_alloc->offset = 0; + pm_alloc->virt_addr = 0; + pm_alloc->phys_addr = 0; + } + } + + if (0 <= pm->pmem_master_fd) { + munmap(pm->pmem_master_base, pm->pmem_total_size); + close(pm->pmem_master_fd); + pm->pmem_master_fd = -1; + } + + pm->pmem_master_base = 0; + pm->pmem_total_size = 0; + + return 0; +} + +int checkPmem(sec_pmem_t *pm, unsigned int index, unsigned int requested_size) +{ + sec_pmem_alloc_t *pm_alloc = &(pm->sec_pmem_alloc[index]); + + if (0 < pm_alloc->virt_addr && + requested_size <= (unsigned int)(pm_alloc->total_size)) + return 0; + + pm_alloc->size = 0; + return -1; +} + +#endif diff --git a/exynos4/hal/libhwcomposer/SecHWCUtils.h b/exynos4/hal/libhwcomposer/SecHWCUtils.h new file mode 100644 index 0000000..005b694 --- /dev/null +++ b/exynos4/hal/libhwcomposer/SecHWCUtils.h @@ -0,0 +1,331 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * + * @author Rama, Meka(v.meka@samsung.com) + Sangwoo, Park(sw5771.park@samsung.com) + Jamie, Oh (jung-min.oh@samsung.com) + * @date 2011-03-11 + * + */ + +#ifndef ANDROID_SEC_HWC_UTILS_H_ +#define ANDROID_SEC_HWC_UTILS_H_ + +#include +#include +#include + +#include +#include +#include + +#ifdef BOARD_USE_V4L2_ION +#include +#include "s5p_fimc_v4l2.h" +#include "sec_utils_v4l2.h" +#else +#include +#include "s5p_fimc.h" +#include "sec_utils.h" +#endif + +#include +#include +#include +#include + +#include "linux/fb.h" + +#include "s3c_lcd.h" +#include "s3c_mem.h" +#include "sec_format.h" + +//#define HWC_DEBUG +#if defined(BOARD_USES_FIMGAPI) +#include "sec_g2d.h" +//#define SUB_TITLES_HWC +#endif + +#define NUM_OF_WIN (2) +#define NUM_OF_WIN_BUF (2) +#define NUM_OF_MEM_OBJ (1) + +#if (NUM_OF_WIN_BUF < 2) + #define ENABLE_FIMD_VSYNC +#endif + +#define MAX_RESIZING_RATIO_LIMIT (63) + +#ifdef SAMSUNG_EXYNOS4x12 +#ifdef BOARD_USE_V4L2_ION +#define PP_DEVICE_DEV_NAME "/dev/video4" +#else +#define PP_DEVICE_DEV_NAME "/dev/video3" +#endif +#endif + +#ifdef SAMSUNG_EXYNOS4210 +#define PP_DEVICE_DEV_NAME "/dev/video1" +#endif + +#define S3C_MEM_DEV_NAME "/dev/s3c-mem" +#define PMEM_DEVICE_DEV_NAME "/dev/pmem_gpu1" + +#ifdef BOARD_USE_V4L2_ION +#undef USE_HW_PMEM +#else +#define USE_HW_PMEM +#endif + +#define PMEM_SIZE (1920 * 1280 * 2) + +struct sec_rect { + int32_t x; + int32_t y; + int32_t w; + int32_t h; +}; + +struct sec_img { + uint32_t f_w; + uint32_t f_h; + uint32_t w; + uint32_t h; + uint32_t format; + uint32_t base; + uint32_t offset; + uint32_t paddr; + uint32_t uoffset; + uint32_t voffset; + int usage; + int mem_id; + int mem_type; +}; + +inline int SEC_MIN(int x, int y) +{ + return ((x < y) ? x : y); +} + +inline int SEC_MAX(int x, int y) +{ + return ((x > y) ? x : y); +} + +struct s3c_mem_t { + int fd; + struct s3c_mem_alloc mem_alloc[NUM_OF_MEM_OBJ]; +}; + +#ifdef USE_HW_PMEM +typedef struct __sec_pmem_alloc { + int fd; + int total_size; + int offset; + int size; + unsigned int virt_addr; + unsigned int phys_addr; +} sec_pmem_alloc_t; + +typedef struct __sec_pmem { + int pmem_master_fd; + void *pmem_master_base; + int pmem_total_size; + sec_pmem_alloc_t sec_pmem_alloc[NUM_OF_MEM_OBJ]; +} sec_pmem_t; + +inline size_t roundUpToPageSize(size_t x) +{ + return (x + (PAGE_SIZE-1)) & ~(PAGE_SIZE-1); +} +#endif + +struct hwc_win_info_t { + int fd; + int size; + sec_rect rect_info; + uint32_t addr[NUM_OF_WIN_BUF]; + int buf_index; + + int power_state; + int blending; + int layer_index; + int status; + int vsync; +#ifdef BOARD_USE_V4L2_ION + int ion_fd; +#endif + + struct fb_fix_screeninfo fix_info; + struct fb_var_screeninfo var_info; + struct fb_var_screeninfo lcd_info; +}; + +enum { + HWC_WIN_FREE = 0, + HWC_WIN_RESERVED, +}; + +enum { + HWC_UNKNOWN_MEM_TYPE = 0, + HWC_PHYS_MEM_TYPE, + HWC_VIRT_MEM_TYPE, +}; + +struct hwc_context_t { + hwc_composer_device_t device; + + /* our private state goes below here */ + struct hwc_win_info_t win[NUM_OF_WIN]; + struct fb_var_screeninfo lcd_info; + s5p_fimc_t fimc; +#ifdef SUB_TITLES_HWC + sec_g2d_t g2d; +#endif + struct s3c_mem_t s3c_mem; +#ifdef USE_HW_PMEM + sec_pmem_t sec_pmem; +#endif + int num_of_fb_layer; + int num_of_hwc_layer; + int num_2d_blit_layer; + uint32_t layer_prev_buf[NUM_OF_WIN]; +}; + +typedef enum _LOG_LEVEL { + HWC_LOG_DEBUG, + HWC_LOG_WARNING, + HWC_LOG_ERROR, +} HWC_LOG_LEVEL; + +#define SEC_HWC_LOG_TAG "SECHWC_LOG" + +#ifdef HWC_DEBUG +#define SEC_HWC_Log(a, ...) ((void)_SEC_HWC_Log(a, SEC_HWC_LOG_TAG, __VA_ARGS__)) +#else +#define SEC_HWC_Log(a, ...) \ + do { \ + if (a == HWC_LOG_ERROR) \ + ((void)_SEC_HWC_Log(a, SEC_HWC_LOG_TAG, __VA_ARGS__)); \ + } while (0) +#endif + +extern void _SEC_HWC_Log(HWC_LOG_LEVEL logLevel, const char *tag, const char *msg, ...); + +/* copied from gralloc module ..*/ +typedef struct { + native_handle_t base; + + /* These fields can be sent cross process. They are also valid + * to duplicate within the same process. + * + * A table is stored within psPrivateData on gralloc_module_t (this + * is obviously per-process) which maps stamps to a mapped + * PVRSRV_CLIENT_MEM_INFO in that process. Each map entry has a lock + * count associated with it, satisfying the requirements of the + * Android API. This also prevents us from leaking maps/allocations. + * + * This table has entries inserted either by alloc() + * (alloc_device_t) or map() (gralloc_module_t). Entries are removed + * by free() (alloc_device_t) and unmap() (gralloc_module_t). + * + * As a special case for framebuffer_device_t, framebuffer_open() + * will add and framebuffer_close() will remove from this table. + */ + +#define IMG_NATIVE_HANDLE_NUMFDS 1 + /* The `fd' field is used to "export" a meminfo to another process. + * Therefore, it is allocated by alloc_device_t, and consumed by + * gralloc_module_t. The framebuffer_device_t does not need a handle, + * and the special value IMG_FRAMEBUFFER_FD is used instead. + */ + int fd; + +#if 1 + int format; + int magic; + int flags; + int size; + int offset; + int base_addr; +#define IMG_NATIVE_HANDLE_NUMINTS ((sizeof(uint64_t) / sizeof(int)) + 4 + 6) +#else +#define IMG_NATIVE_HANDLE_NUMINTS ((sizeof(IMG_UINT64) / sizeof(int)) + 4) +#endif + /* A KERNEL unique identifier for any exported kernel meminfo. Each + * exported kernel meminfo will have a unique stamp, but note that in + * userspace, several meminfos across multiple processes could have + * the same stamp. As the native_handle can be dup(2)'d, there could be + * multiple handles with the same stamp but different file descriptors. + */ + uint64_t ui64Stamp; + + /* We could live without this, but it lets us perform some additional + * validation on the client side. Normally, we'd have no visibility + * of the allocated usage, just the lock usage. + */ + int usage; + + /* In order to do efficient cache flushes we need the buffer dimensions + * and format. These are available on the android_native_buffer_t, + * but the platform doesn't pass them down to the graphics HAL. + * + * TODO: Ideally the platform would be modified to not require this. + */ + int width; + int height; + int bpp; +} +__attribute__((aligned(sizeof(int)),packed)) sec_native_handle_t; + +int window_open (struct hwc_win_info_t *win, int id); +int window_close (struct hwc_win_info_t *win); +int window_set_pos (struct hwc_win_info_t *win); +int window_get_info (struct hwc_win_info_t *win, int win_num); +int window_pan_display(struct hwc_win_info_t *win); +int window_show (struct hwc_win_info_t *win); +int window_hide (struct hwc_win_info_t *win); +int window_get_global_lcd_info(int fd, struct fb_var_screeninfo *lcd_info); + +int createFimc (s5p_fimc_t *fimc); +int destroyFimc(s5p_fimc_t *fimc); +int runFimc(struct hwc_context_t *ctx, + struct sec_img *src_img, struct sec_rect *src_rect, + struct sec_img *dst_img, struct sec_rect *dst_rect, + uint32_t transform); + +#ifdef SUB_TITLES_HWC +int runG2d(struct hwc_context_t *ctx, + g2d_rect *src_rect, g2d_rect *dst_rect, + uint32_t transform); + +int destroyG2d(sec_g2d_t *g2d); +int createG2d(sec_g2d_t *g2d); +#endif + +int createMem (struct s3c_mem_t *mem, unsigned int index, unsigned int size); +int destroyMem(struct s3c_mem_t *mem); +int checkMem (struct s3c_mem_t *mem, unsigned int index, unsigned int size); + +#ifdef USE_HW_PMEM +int createPmem (sec_pmem_t *pm, unsigned int size); +int destroyPmem(sec_pmem_t *pm); +int checkPmem (sec_pmem_t *pm, unsigned int index, unsigned int size); +#endif + +#endif /* ANDROID_SEC_HWC_UTILS_H_*/ diff --git a/exynos4/hal/libhwconverter/Android.mk b/exynos4/hal/libhwconverter/Android.mk index ecda03b..c1ded53 100644 --- a/exynos4/hal/libhwconverter/Android.mk +++ b/exynos4/hal/libhwconverter/Android.mk @@ -12,6 +12,8 @@ # See the License for the specific language governing permissions and # limitations under the License. +ifeq ($(filter-out exynos4,$(TARGET_BOARD_PLATFORM)),) + LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) @@ -21,10 +23,13 @@ LOCAL_SHARED_LIBRARIES := liblog libutils libcutils libfimc LOCAL_SRC_FILES := HardwareConverter.cpp LOCAL_C_INCLUDES := \ - $(TOP)/$(BOARD_HAL_PATH)/include \ - $(TOP)/$(BOARD_HMM_PATH)/openmax/sec_omx/include/khronos \ - $(TOP)/$(BOARD_HMM_PATH)/openmax/sec_omx/include/sec + $(LOCAL_PATH)/../include \ + $(TOP)/$(TARGET_HAL_PATH)/include \ + $(TOP)/$(TARGET_OMX_PATH)/include/khronos \ + $(TOP)/$(TARGET_OMX_PATH)/include/sec LOCAL_MODULE_TAGS := eng LOCAL_MODULE := libhwconverter include $(BUILD_SHARED_LIBRARY) + +endif diff --git a/exynos4/hal/libhwconverter/HardwareConverter.cpp b/exynos4/hal/libhwconverter/HardwareConverter.cpp index 3a66767..9ff6e55 100644 --- a/exynos4/hal/libhwconverter/HardwareConverter.cpp +++ b/exynos4/hal/libhwconverter/HardwareConverter.cpp @@ -15,7 +15,6 @@ */ #include - #include "SEC_OMX_Def.h" #include "SecFimc.h" #include "HardwareConverter.h" @@ -25,7 +24,7 @@ HardwareConverter::HardwareConverter() SecFimc* handle_fimc = new SecFimc(); mSecFimc = (void *)handle_fimc; - if (handle_fimc->create(SecFimc::DEV_2, SecFimc::MODE_MULTI_BUF, 1) == false) + if (handle_fimc->create(SecFimc::DEV_0, SecFimc::MODE_MULTI_BUF, 1) == false) bHWconvert_flag = 0; else bHWconvert_flag = 1; diff --git a/exynos4/hal/libhwjpeg/Android.mk b/exynos4/hal/libhwjpeg/Android.mk new file mode 100644 index 0000000..21a99fb --- /dev/null +++ b/exynos4/hal/libhwjpeg/Android.mk @@ -0,0 +1,33 @@ +# Copyright (C) 2008 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +LOCAL_PATH:= $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_C_INCLUDES := $(LOCAL_PATH) \ + $(LOCAL_PATH)/../include + +LOCAL_SRC_FILES:= \ + jpeg_hal_unit.c \ + +LOCAL_SHARED_LIBRARIES := \ + libcutils \ + +LOCAL_STATIC_LIBRARIES := \ + +LOCAL_MODULE:= libhwjpeg + +LOCAL_MODULE_TAGS := eng + +include $(BUILD_SHARED_LIBRARY) diff --git a/exynos4/hal/libhwjpeg/jpeg_hal_unit.c b/exynos4/hal/libhwjpeg/jpeg_hal_unit.c new file mode 100644 index 0000000..a0b4224 --- /dev/null +++ b/exynos4/hal/libhwjpeg/jpeg_hal_unit.c @@ -0,0 +1,572 @@ +/* + * Copyright@ Samsung Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "libhwjpeg" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "jpeg_hal.h" + +#ifdef JPEG_PERF_MEAS +unsigned long measure_time(struct timeval *start, struct timeval *stop) +{ + unsigned long sec, usec, time; + + sec = stop->tv_sec - start->tv_sec; + + if (stop->tv_usec >= start->tv_usec) { + usec = stop->tv_usec - start->tv_usec; + } else { + usec = stop->tv_usec + 1000000 - start->tv_usec; + sec--; + } + + time = (sec * 1000000) + usec; + + return time; +} +#endif + +static int jpeg_v4l2_querycap(int fd) +{ + struct v4l2_capability cap; + int ret = 0; + + ret = ioctl(fd, VIDIOC_QUERYCAP, &cap); + + if (!(cap.capabilities & V4L2_CAP_STREAMING)) + LOGE("[%s]: does not support streaming", __func__); + + if (!(cap.capabilities & V4L2_CAP_VIDEO_OUTPUT)) + LOGE("[%s]: does not support output", __func__); + + if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) + LOGE("[%s]: does not support capture", __func__); + + return ret; +} + +static int jpeg_v4l2_s_jpegcomp(int fd, int quality) +{ + struct v4l2_jpegcompression arg; + int ret = 0; + + arg.quality = quality; + + ret = ioctl(fd, VIDIOC_S_JPEGCOMP, &arg); + + return ret; +} + +static int jpeg_v4l2_s_fmt(int fd, enum v4l2_buf_type type, struct jpeg_config *config) +{ + struct v4l2_format fmt; + int ret = 0; + + fmt.type = type; + fmt.fmt.pix_mp.width = config->width; + fmt.fmt.pix_mp.height = config->height; + fmt.fmt.pix_mp.field = V4L2_FIELD_ANY; + fmt.fmt.pix_mp.num_planes = config->num_planes; + + if (config->mode == JPEG_ENCODE) + fmt.fmt.pix_mp.colorspace = V4L2_COLORSPACE_JPEG; + + switch (fmt.type) { + case V4L2_BUF_TYPE_VIDEO_OUTPUT: /* fall through */ + case V4L2_BUF_TYPE_VIDEO_CAPTURE: + break; + case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: + if (config->mode == JPEG_ENCODE) { + fmt.fmt.pix_mp.pixelformat = config->pix.enc_fmt.in_fmt; + } else { + fmt.fmt.pix_mp.pixelformat = config->pix.dec_fmt.in_fmt; + fmt.fmt.pix_mp.plane_fmt[0].sizeimage = config->sizeJpeg; + } + break; + case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: + if (config->mode == JPEG_ENCODE) { + fmt.fmt.pix_mp.pixelformat = config->pix.enc_fmt.out_fmt; + } else { + fmt.fmt.pix_mp.pixelformat = config->pix.dec_fmt.out_fmt; + fmt.fmt.pix_mp.width = config->scaled_width; + fmt.fmt.pix_mp.height = config->scaled_height; + } + break; + default: + LOGE("[%s]: invalid v4l2 buf type", __func__); + return -1; + } + + ret = ioctl(fd, VIDIOC_S_FMT, &fmt); + + return ret; +} + +static int jpeg_v4l2_g_fmt(int fd, enum v4l2_buf_type type, struct jpeg_config *config) +{ + struct v4l2_format fmt; + int ret = 0; + + fmt.type = type; + ret = ioctl(fd, VIDIOC_G_FMT, &fmt); + if (ret < 0) + return -1; + + config->width = fmt.fmt.pix_mp.width; + config->height = fmt.fmt.pix_mp.height; + + switch (fmt.type) { + case V4L2_BUF_TYPE_VIDEO_OUTPUT: /* fall through */ + case V4L2_BUF_TYPE_VIDEO_CAPTURE: + break; + case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: + if (config->mode == JPEG_ENCODE) + config->pix.enc_fmt.in_fmt = fmt.fmt.pix_mp.pixelformat; + else + config->pix.dec_fmt.in_fmt = fmt.fmt.pix_mp.pixelformat; + break; + case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: + if (config->mode == JPEG_ENCODE) + config->pix.enc_fmt.out_fmt = fmt.fmt.pix_mp.pixelformat; + else + config->pix.dec_fmt.out_fmt = fmt.fmt.pix_mp.pixelformat; + break; + default: + LOGE("[%s]: invalid v4l2 buf type", __func__); + return -1; + } + + return ret; +} + +int jpeghal_getconfig(int fd, struct jpeg_config *config) +{ + int ret = 0; + + ret = jpeg_v4l2_g_fmt(fd, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, config); + if (ret < 0) { + LOGE("[%s]: input G_FMT failed", __func__); + return -1; + } + + ret = jpeg_v4l2_g_fmt(fd, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, config); + if (ret < 0) + LOGE("[%s]: output G_FMT failed", __func__); + + return ret; +} + +static int jpeg_v4l2_reqbufs(int fd, int buf_cnt, struct jpeg_buf *buf) +{ + struct v4l2_requestbuffers req; + int ret = 0; + + memset(&req, 0, sizeof(req)); + + req.type = buf->buf_type; + req.memory = buf->memory; + + req.count = buf_cnt; + + ret = ioctl(fd, VIDIOC_REQBUFS, &req); + + return ret; +} + +static int jpeg_v4l2_querybuf(int fd, struct jpeg_buf *buf) +{ + struct v4l2_buffer v4l2_buf; + struct v4l2_plane plane[JPEG_MAX_PLANE_CNT]; + int i; + int ret = 0; + + memset(plane, 0, (int)JPEG_MAX_PLANE_CNT * sizeof(struct v4l2_plane)); + + v4l2_buf.index = 0; + v4l2_buf.type = buf->buf_type; + v4l2_buf.memory = buf->memory; + v4l2_buf.length = buf->num_planes; + v4l2_buf.m.planes = plane; + + ret = ioctl(fd, VIDIOC_QUERYBUF, &v4l2_buf); + if (ret < 0) { + LOGE("[%s:%d]: VIDIOC_QUERYBUF failed", __func__, ret); + return ret; + } + + for (i= 0; i < buf->num_planes; i++) { + buf->length[i] = v4l2_buf.m.planes[i].length; + buf->start[i] = (char *) mmap(0, buf->length[i], + PROT_READ | PROT_WRITE, MAP_SHARED, fd, + v4l2_buf.m.planes[i].m.mem_offset); + + //LOGI("[%s]: buf.start[%d] = %p, length = %d", __func__, 0, buf->start[0], buf->length[0]); + if (buf->start[0] == MAP_FAILED) { + LOGE("[%s]: mmap failed", __func__); + return -1; + } + } + + return ret; +} + +static int jpeg_v4l2_qbuf(int fd, struct jpeg_buf *buf) +{ + struct v4l2_buffer v4l2_buf; + struct v4l2_plane plane[JPEG_MAX_PLANE_CNT]; + int i; + int ret = 0; + + memset(&v4l2_buf, 0, sizeof(struct v4l2_buffer)); + memset(plane, 0, (int)JPEG_MAX_PLANE_CNT * sizeof(struct v4l2_plane)); + + v4l2_buf.index = 0; + v4l2_buf.type = buf->buf_type; + v4l2_buf.memory = buf->memory; + v4l2_buf.length = buf->num_planes; + v4l2_buf.m.planes = plane; + + if (buf->memory == V4L2_MEMORY_USERPTR) { + for (i = 0; i < buf->num_planes; i++) { + v4l2_buf.m.planes[i].m.userptr = (unsigned long)buf->start[i]; + v4l2_buf.m.planes[i].length = buf->length[i]; + } + } + + ret = ioctl(fd, VIDIOC_QBUF, &v4l2_buf); + if (ret < 0) { + LOGE("[%s:%d] QBUF failed", __func__, ret); + return -1; + } + + return ret; +} + +static int jpeg_v4l2_dqbuf(int fd, enum v4l2_buf_type type, enum v4l2_memory memory) +{ + struct v4l2_buffer buf; + int ret = 0; + + memset(&buf, 0, sizeof(struct v4l2_buffer)); + + buf.type = type; + buf.memory = memory; + + ret = ioctl(fd, VIDIOC_DQBUF, &buf); + if (ret < 0) { + LOGE("[%s:%d] DQBUF failed", __func__, ret); + return -1; + } + + return ret; +} + +static int jpeg_v4l2_streamon(int fd, enum v4l2_buf_type type) +{ + int ret = 0; + + ret = ioctl(fd, VIDIOC_STREAMON, &type); + if (ret < 0) { + LOGE("[%s:%d] STREAMON failed", __func__, ret); + return -1; + } + + return ret; +} + +static int jpeg_v4l2_streamoff(int fd, enum v4l2_buf_type type) +{ + int ret = 0; + + ret = ioctl(fd, VIDIOC_STREAMOFF, &type); + if (ret < 0) { + LOGE("[%s:%d] STREAMOFF failed", __func__, ret); + return -1; + } + + return ret; +} + +int jpeghal_dec_init() +{ + int fd; + int ret = 0; + + fd = open(JPEG_DEC_NODE, O_RDWR, 0); + + if (fd < 0) { + LOGE("[%s]: JPEG dec open failed", __func__); + return -1; + } + + ret = jpeg_v4l2_querycap(fd); + if (ret < 0) { + LOGE("[%s]: QUERYCAP failed", __func__); + return -1; + } + + return fd; +} + +int jpeghal_enc_init() +{ + int fd; + int ret = 0; + + fd = open(JPEG_ENC_NODE, O_RDWR, 0); + if (fd < 0) { + LOGE("[%s]: JPEG enc open failed", __func__); + return -1; + } + + ret = jpeg_v4l2_querycap(fd); + if (ret < 0) { + LOGE("[%s]: QUERYCAP failed", __func__); + return -1; + } + + return fd; +} + +int jpeghal_dec_setconfig(int fd, struct jpeg_config *config) +{ + int ret = 0; + + config->mode = JPEG_DECODE; + + ret = jpeg_v4l2_s_fmt(fd, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, config); + if (ret < 0) { + LOGE("[%s]: decoder input S_FMT failed", __func__); + return -1; + } + + ret = jpeg_v4l2_s_fmt(fd, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, config); + if (ret < 0) { + LOGE("[%s]: decoder output S_FMT failed", __func__); + return -1; + } + + return ret; +} + +int jpeghal_dec_getconfig(int fd, struct jpeg_config *config) +{ + int ret = 0; + + jpeghal_getconfig(fd, config); + + return ret; +} + +int jpeghal_enc_setconfig(int fd, struct jpeg_config *config) +{ + int ret = 0; + + ret = jpeg_v4l2_s_jpegcomp(fd, config->enc_qual); + if (ret < 0) { + LOGE("[%s]: S_JPEGCOMP failed", __func__); + return -1; + } + + config->mode = JPEG_ENCODE; + + ret = jpeg_v4l2_s_fmt(fd, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, config); + if (ret < 0) { + LOGE("[%s]: encoder input S_FMT failed", __func__); + return -1; + } + + ret = jpeg_v4l2_s_fmt(fd, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, config); + if (ret < 0) { + LOGE("[%s]: encoder output S_FMT failed", __func__); + return -1; + } + + return ret; +} + +int jpeghal_enc_getconfig(int fd, struct jpeg_config *config) +{ + int ret = 0; + + jpeghal_getconfig(fd, config); + + return ret; +} + +int jpeghal_set_inbuf(int fd, struct jpeg_buf *buf) +{ + int ret = 0; + + buf->buf_type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; + + ret = jpeg_v4l2_reqbufs(fd, 1, buf); + if (ret < 0) { + LOGE("[%s:%d]: Input REQBUFS failed", __func__, ret); + return -1; + } + + if (buf->memory == V4L2_MEMORY_MMAP) { + ret = jpeg_v4l2_querybuf(fd, buf); + if (ret < 0) { + LOGE("[%s:%d]: Input QUERYBUF failed", __func__, ret); + return -1; + } + } + + return ret; +} + +int jpeghal_set_outbuf(int fd, struct jpeg_buf *buf) +{ + int ret = 0; + + buf->buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; + + ret = jpeg_v4l2_reqbufs(fd, 1, buf); + if (ret < 0) { + LOGE("[%s:%d]: Output REQBUFS failed", __func__, ret); + return -1; + } + + if (buf->memory == V4L2_MEMORY_MMAP) { + ret = jpeg_v4l2_querybuf(fd, buf); + if (ret < 0) { + LOGE("[%s:%d]: Output QUERYBUF failed", __func__, ret); + return -1; + } + } + + return ret; +} + +static int jpeg_exe(int fd, struct jpeg_buf *in_buf, struct jpeg_buf *out_buf) +{ + int ret = 0; + + ret = jpeg_v4l2_qbuf(fd, in_buf); + if (ret < 0) { + LOGE("[%s:%d]: Input QBUF failed", __func__, ret); + return -1; + } + + ret = jpeg_v4l2_qbuf(fd, out_buf); + if (ret < 0) { + LOGE("[%s:%d]: Output QBUF failed", __func__, ret); + return -1; + } + + ret = jpeg_v4l2_streamon(fd, in_buf->buf_type); + ret = jpeg_v4l2_streamon(fd, out_buf->buf_type); + + ret = jpeg_v4l2_dqbuf(fd, in_buf->buf_type, in_buf->memory); + ret = jpeg_v4l2_dqbuf(fd, out_buf->buf_type, out_buf->memory); + + return ret; +} + +int jpeghal_dec_exe(int fd, struct jpeg_buf *in_buf, struct jpeg_buf *out_buf) +{ + int ret = 0; + + ret = jpeg_exe(fd, in_buf, out_buf); + if (ret < 0) + LOGE("[%s]: JPEG decoding is failed", __func__); + + return ret; +} + +int jpeghal_enc_exe(int fd, struct jpeg_buf *in_buf, struct jpeg_buf *out_buf) +{ + int ret = 0; + + ret = jpeg_exe(fd, in_buf, out_buf); + if (ret < 0) + LOGE("[%s]: JPEG Encoding is failed", __func__); + + return ret; +} + +int jpeghal_deinit(int fd, struct jpeg_buf *in_buf, struct jpeg_buf *out_buf) +{ + int ret = 0; + + jpeg_v4l2_streamoff(fd, in_buf->buf_type); + jpeg_v4l2_streamoff(fd, out_buf->buf_type); + + if (in_buf->memory == V4L2_MEMORY_MMAP) + munmap((char *)(in_buf->start[0]), in_buf->length[0]); + + if (out_buf->memory == V4L2_MEMORY_MMAP) + munmap((char *)(out_buf->start[0]), out_buf->length[0]); + + jpeg_v4l2_reqbufs(fd, 0, in_buf); + + jpeg_v4l2_reqbufs(fd, 0, out_buf); + + ret = close(fd); + + return ret; +} + +int jpeghal_s_ctrl(int fd, int cid, int value) +{ + struct v4l2_control vc; + int ret = 0; + + vc.id = cid; + vc.value = value; + + ret = ioctl(fd, VIDIOC_S_CTRL, &vc); + if (ret != 0) { + LOGE("[%s] ioctl : cid(%d), value(%d)\n", __func__, cid, value); + return -1; + } + + return ret; +} + +int jpeghal_g_ctrl(int fd, int id) +{ + struct v4l2_control ctrl; + int ret = 0; + + ctrl.id = id; + + ret = ioctl(fd, VIDIOC_G_CTRL, &ctrl); + if (ret < 0) { + LOGE("[%s] ioctl : cid(%d)\n", __func__, ctrl.id); + return -1; + } + + return ctrl.value; +} diff --git a/exynos4/hal/libs5pjpeg/Android.mk b/exynos4/hal/libs5pjpeg/Android.mk index e1ac187..c6d8cf6 100644 --- a/exynos4/hal/libs5pjpeg/Android.mk +++ b/exynos4/hal/libs5pjpeg/Android.mk @@ -15,9 +15,8 @@ LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) -LOCAL_C_INCLUDES := \ - $(LOCAL_PATH) \ - $(BOARD_HAL_PATH)/include \ +LOCAL_C_INCLUDES := $(LOCAL_PATH) +LOCAL_C_INCLUDES += $(LOCAL_PATH)/../include LOCAL_SRC_FILES:= \ jpeg_api.c \ diff --git a/exynos4/hal/libswconverter/Android.mk b/exynos4/hal/libswconverter/Android.mk index ce6daf4..e52aea7 100644 --- a/exynos4/hal/libswconverter/Android.mk +++ b/exynos4/hal/libswconverter/Android.mk @@ -1,20 +1,9 @@ -# Copyright (C) 2008 The Android Open Source Project -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - LOCAL_PATH := $(call my-dir) + include $(CLEAR_VARS) +LOCAL_MODULE_TAGS := optional + LOCAL_SRC_FILES := \ swconvertor.c \ csc_linear_to_tiled_crop_neon.s \ @@ -24,21 +13,24 @@ LOCAL_SRC_FILES := \ csc_interleave_memcpy_neon.s LOCAL_C_INCLUDES := \ - $(TOP)/$(BOARD_HMM_PATH)/openmax/include/khronos \ - $(TOP)/$(BOARD_HMM_PATH)/openmax/include/sec \ - $(TOP)/$(BOARD_HAL_PATH)/include \ - $(TOP)/$(BOARD_HAL_PATH)/libhwconverter + $(TOP)/$(TARGET_OMX_PATH)/include/khronos \ + $(TOP)/$(TARGET_OMX_PATH)/include/sec \ + $(TOP)/$(TARGET_HAL_PATH)/include \ + $(TOP)/$(TARGET_HAL_PATH)/libhwconverter ifeq ($(BOARD_USE_SAMSUNG_COLORFORMAT), true) LOCAL_CFLAGS += -DUSE_SAMSUNG_COLORFORMAT endif -LOCAL_MODULE_TAGS := eng LOCAL_MODULE := libswconverter LOCAL_PRELINK_MODULE := false + +LOCAL_CFLAGS := + LOCAL_ARM_MODE := arm +LOCAL_STATIC_LIBRARIES := LOCAL_SHARED_LIBRARIES := liblog libfimc libhwconverter include $(BUILD_STATIC_LIBRARY) diff --git a/exynos4/hal/libump/Android.mk b/exynos4/hal/libump/Android.mk deleted file mode 100644 index 306b6af..0000000 --- a/exynos4/hal/libump/Android.mk +++ /dev/null @@ -1,48 +0,0 @@ -# -# Copyright (C) 2010 ARM Limited. All rights reserved. -# -# Copyright (C) 2008 The Android Open Source Project -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -LOCAL_PATH := $(call my-dir) -include $(CLEAR_VARS) - -UMP_SRCS := \ - arch_011_udd/ump_frontend.c \ - arch_011_udd/ump_ref_drv.c \ - arch_011_udd/ump_arch.c \ - os/linux/ump_uku.c \ - os/linux/ump_osu_memory.c \ - os/linux/ump_osu_locks.c - -# Shared and static library for target -# ======================================================== -include $(CLEAR_VARS) -LOCAL_MODULE := libUMP -LOCAL_SRC_FILES := $(UMP_SRCS) - -LOCAL_C_INCLUDES:= \ - $(BOARD_HAL_PATH)/libump/ \ - $(BOARD_HAL_PATH)/libump/include \ - -LOCAL_MODULE_TAGS := optional -LOCAL_MODULE_PATH := $(TARGET_OUT_STATIC_LIBRARIES)/ -include $(BUILD_STATIC_LIBRARY) - -include $(CLEAR_VARS) -LOCAL_MODULE := libUMP -LOCAL_MODULE_TAGS := optional -LOCAL_WHOLE_STATIC_LIBRARIES := libUMP -LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/ -include $(BUILD_SHARED_LIBRARY) diff --git a/exynos4/hal/libump/Makefile b/exynos4/hal/libump/Makefile deleted file mode 100644 index b936fe9..0000000 --- a/exynos4/hal/libump/Makefile +++ /dev/null @@ -1,38 +0,0 @@ -# -# Copyright (C) 2010-2011 ARM Limited. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -UMP_DIR ?= . -UMP_LIB ?= libUMP -UDD_OS ?= android -#CROSS_COMPILE ?= arm-none-linux-gnueabi- -TARGET_CC ?= $(CROSS_COMPILE)gcc -TARGET_AR ?= $(CROSS_COMPILE)ar -CFLAGS += -I$(UMP_DIR)/include -I$(UMP_DIR)/include/ump -Wall -march=armv6 -mthumb-interwork -fno-strict-aliasing -Wno-strict-aliasing -Wno-long-long -O3 - -include ump.mak - -%.o: %.c - $(TARGET_CC) -c -o $@ $< $(CFLAGS) - -UMP_OBJS := $(UMP_SRCS:.c=.o) - -libUMP.so: $(UMP_OBJS) - arm-none-linux-gnueabi-gcc -shared -o $@ $(UMP_OBJS) $(CFLAGS) -libUMP.a: $(UMP_OBJS) - $(TARGET_AR) rcs $@ $(UMP_OBJS) - -clean: - -rm -f $(UMP_OBJS) libUMP.so libUMP.a diff --git a/exynos4/hal/libump/arch_011_udd/ump_arch.c b/exynos4/hal/libump/arch_011_udd/ump_arch.c deleted file mode 100644 index 79c3c18..0000000 --- a/exynos4/hal/libump/arch_011_udd/ump_arch.c +++ /dev/null @@ -1,260 +0,0 @@ -/* - * Copyright (C) 2010-2011 ARM Limited. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @file ump_arch.c - * - * UMP arch layer for UMP-UDD - */ - -#include -#include "ump_arch.h" -#include - -#include -#include "../os/ump_uku.h" - -/** Pointer to an OS-Specific context that we should pass in _uku_ calls */ -void *ump_uk_ctx = NULL; - -/** Reference counting of ump_arch_open() and ump_arch_close(). */ -volatile static int ump_ref_count = 0; - -/** Lock for critical section in open/close */ -_ump_osu_lock_t * ump_lock = NULL; - -ump_result ump_arch_open(void) -{ - ump_result retval = UMP_OK; - - _ump_osu_lock_auto_init( &ump_lock, 0, 0, 0 ); - - /* Check that the lock was initialized */ - if (NULL == ump_lock) - { - UMP_DEBUG_PRINT(1, ("UMP: ump_arch_open() failed to init lock\n")); - return UMP_ERROR; - } - - /* Attempt to obtain a lock */ - if( _UMP_OSU_ERR_OK != _ump_osu_lock_wait( ump_lock, _UMP_OSU_LOCKMODE_RW ) ) - { - UMP_DEBUG_PRINT(1, ("UMP: ump_arch_open() failed to acquire lock\n")); - return UMP_ERROR; - } - - /* ASSERT NEEDED */ - UMP_DEBUG_ASSERT(0 <= ump_ref_count, ("UMP: Reference count invalid at _ump_base_arch_open()")); - ump_ref_count++; - - if (1 == ump_ref_count) - { - /* We are the first, open the UMP device driver */ - - if (_UMP_OSU_ERR_OK != _ump_uku_open( &ump_uk_ctx )) - { - UMP_DEBUG_PRINT(1, ("UMP: ump_arch_open() failed to open UMP device driver\n")); - retval = UMP_ERROR; - ump_ref_count--; - } - } - - /* Signal the lock so someone else can use it */ - _ump_osu_lock_signal( ump_lock, _UMP_OSU_LOCKMODE_RW ); - - return retval; -} - - - -void ump_arch_close(void) -{ - _ump_osu_lock_auto_init( &ump_lock, 0, 0, 0 ); - - /* Check that the lock was initialized */ - if(NULL == ump_lock) - { - UMP_DEBUG_PRINT(1, ("UMP: ump_arch_close() failed to init lock\n")); - return; - } - - /* Attempt to obtain a lock */ - if( _UMP_OSU_ERR_OK != _ump_osu_lock_wait( ump_lock, _UMP_OSU_LOCKMODE_RW ) ) - { - UMP_DEBUG_PRINT(1, ("UMP: ump_arch_close() failed to acquire lock\n")); - return; - } - - UMP_DEBUG_ASSERT(0 < ump_ref_count, ("UMP: ump_arch_close() called while no references exist")); - if (ump_ref_count > 0) - { - ump_ref_count--; - if (0 == ump_ref_count) - { - _ump_osu_errcode_t retval = _ump_uku_close(&ump_uk_ctx); - UMP_DEBUG_ASSERT(retval == _UMP_OSU_ERR_OK, ("UMP: Failed to close UMP interface")); - UMP_IGNORE(retval); - ump_uk_ctx = NULL; - _ump_osu_lock_signal( ump_lock, _UMP_OSU_LOCKMODE_RW ); - _ump_osu_lock_term( ump_lock ); /* Not 100% thread safe, since another thread can already be waiting for this lock in ump_arch_open() */ - ump_lock = NULL; - return; - } - } - - /* Signal the lock so someone else can use it */ - _ump_osu_lock_signal( ump_lock, _UMP_OSU_LOCKMODE_RW ); -} - - - -ump_secure_id ump_arch_allocate(unsigned long * size, ump_alloc_constraints constraints) -{ - _ump_uk_allocate_s call_arg; - - if ( NULL == size ) - { - return UMP_INVALID_SECURE_ID; - } - - call_arg.ctx = ump_uk_ctx; - call_arg.secure_id = UMP_INVALID_SECURE_ID; - call_arg.size = *size; -#ifdef UMP_DEBUG_SKIP_CODE - /** Run-time ASSERTing that _ump_uk_api_version_s and ump_alloc_constraints are - * interchangable */ - switch (constraints) - { - case UMP_REF_DRV_CONSTRAINT_NONE: - UMP_DEBUG_ASSERT( UMP_REF_DRV_UK_CONSTRAINT_NONE == constraints, ("ump_uk_alloc_constraints out of sync with ump_alloc_constraints") ); - break; - case UMP_REF_DRV_CONSTRAINT_PHYSICALLY_LINEAR: - UMP_DEBUG_ASSERT( UMP_REF_DRV_UK_CONSTRAINT_PHYSICALLY_LINEAR == constraints, ("ump_uk_alloc_constraints out of sync with ump_alloc_constraints") ); - break; - default: - UMP_DEBUG_ASSERT( 1, ("ump_uk_alloc_constraints out of sync with ump_alloc_constraints: %d unrecognized", constraints) ); - break; - } -#endif - call_arg.constraints = (ump_uk_alloc_constraints)constraints; - - if ( _UMP_OSU_ERR_OK != _ump_uku_allocate(&call_arg) ) - { - return UMP_INVALID_SECURE_ID; - } - - *size = call_arg.size; - - UMP_DEBUG_PRINT(4, ("UMP: Allocated ID %u, size %ul", call_arg.secure_id, call_arg.size)); - - return call_arg.secure_id; -} - - - -unsigned long ump_arch_size_get(ump_secure_id secure_id) -{ - _ump_uk_size_get_s dd_size_call_arg; - - dd_size_call_arg.ctx = ump_uk_ctx; - dd_size_call_arg.secure_id = secure_id; - dd_size_call_arg.size = 0; - - if (_UMP_OSU_ERR_OK == _ump_uku_size_get( &dd_size_call_arg ) ) - { - return dd_size_call_arg.size; - } - - return 0; -} - - -void ump_arch_reference_release(ump_secure_id secure_id) -{ - _ump_uk_release_s dd_release_call_arg; - _ump_osu_errcode_t retval; - - dd_release_call_arg.ctx = ump_uk_ctx; - dd_release_call_arg.secure_id = secure_id; - - UMP_DEBUG_PRINT(4, ("UMP: Releasing ID %u", secure_id)); - - retval = _ump_uku_release( &dd_release_call_arg ); - UMP_DEBUG_ASSERT(retval == _UMP_OSU_ERR_OK, ("UMP: Failed to release reference to UMP memory")); - UMP_IGNORE(retval); -} - - -void* ump_arch_map(ump_secure_id secure_id, unsigned long size, ump_cache_enabled cache, unsigned long *cookie_out) -{ - _ump_uk_map_mem_s dd_map_call_arg; - - UMP_DEBUG_ASSERT_POINTER( cookie_out ); - - dd_map_call_arg.ctx = ump_uk_ctx; - dd_map_call_arg.secure_id = secure_id; - dd_map_call_arg.size = size; - dd_map_call_arg.is_cached = (u32) (UMP_CACHE_ENABLE==cache); - - if ( -1 == _ump_uku_map_mem( &dd_map_call_arg ) ) - { - UMP_DEBUG_PRINT(4, ("UMP: Mapping failed for ID %u", secure_id)); - return NULL; - } - - UMP_DEBUG_PRINT(4, ("Mapped %u at 0x%08lx", secure_id, (unsigned long)dd_map_call_arg.mapping)); - - *cookie_out = dd_map_call_arg.cookie; - return dd_map_call_arg.mapping; -} - - - -void ump_arch_unmap(void* mapping, unsigned long size, unsigned long cookie) -{ - _ump_uk_unmap_mem_s dd_unmap_call_arg; - - dd_unmap_call_arg.ctx = ump_uk_ctx; - dd_unmap_call_arg.mapping = mapping; - dd_unmap_call_arg.size = size; - dd_unmap_call_arg.cookie = cookie; - - UMP_DEBUG_PRINT(4, ("Unmapping 0x%08lx", (unsigned long)mapping)); - _ump_uku_unmap_mem( &dd_unmap_call_arg ); -} - -/** Memory synchronization - cache flushing of mapped memory */ -int ump_arch_msync(ump_secure_id secure_id, void* mapping, unsigned long cookie, void * address, unsigned long size, ump_cpu_msync_op op) -{ - _ump_uk_msync_s dd_msync_call_arg; - - dd_msync_call_arg.ctx = ump_uk_ctx; - dd_msync_call_arg.mapping = mapping; - dd_msync_call_arg.address = address; - dd_msync_call_arg.size = size; - dd_msync_call_arg.op = (ump_uk_msync_op)op; - dd_msync_call_arg.cookie = cookie; - dd_msync_call_arg.secure_id = secure_id; - dd_msync_call_arg.is_cached = 0; - - UMP_DEBUG_PRINT(4, ("Msync 0x%08lx", (unsigned long)mapping)); - _ump_uku_msynch( &dd_msync_call_arg ); - if ( 0==dd_msync_call_arg.is_cached ) - { - UMP_DEBUG_PRINT(4, ("Trying to flush uncached UMP mem ID: %d", secure_id)); - } - return dd_msync_call_arg.is_cached; -} diff --git a/exynos4/hal/libump/arch_011_udd/ump_arch.h b/exynos4/hal/libump/arch_011_udd/ump_arch.h deleted file mode 100644 index 064d7c5..0000000 --- a/exynos4/hal/libump/arch_011_udd/ump_arch.h +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (C) 2010-2011 ARM Limited. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @file ump_arch.h - * - * Header file for the arch dependent backend, which will do the communication with the UMP device driver. - */ - -#ifndef _UNIFIED_MEMORY_PROVIDER_ARCH_H_ -#define _UNIFIED_MEMORY_PROVIDER_ARCH_H_ - -#include -#include -#include "ump_internal.h" - -#ifdef __cplusplus -extern "C" { -#endif - - - -/** Open UMP interface. */ -ump_result ump_arch_open(void); - -/** Close UMP interface. */ -void ump_arch_close(void); - -/** Allocate UMP memory. */ -ump_secure_id ump_arch_allocate(unsigned long * size, ump_alloc_constraints constraints); - -/** Query size of specified UMP memory, in bytes. */ -unsigned long ump_arch_size_get(ump_secure_id secure_id); - -/** Release a reference from specified UMP memory. */ -void ump_arch_reference_release(ump_secure_id secure_id); - -/** Map specified UMP memory into CPU address space */ -void* ump_arch_map(ump_secure_id secure_id, unsigned long size, ump_cache_enabled cache, unsigned long *cookie_out); - -/** Unmap specified UMP memory from CPU adderss space */ -void ump_arch_unmap(void* mapping, unsigned long size, unsigned long cookie); - -/** Memory synchronization - cache flushing of mapped memory - * @return Is_cached: 1==True 0==NonCached */ -int ump_arch_msync(ump_secure_id secure_id, void* mapping, unsigned long cookie, void * address, unsigned long size, ump_cpu_msync_op op); - -#ifdef __cplusplus -} -#endif - -#endif /* _UNIFIED_MEMORY_PROVIDER_ARCH_H_ */ diff --git a/exynos4/hal/libump/arch_011_udd/ump_frontend.c b/exynos4/hal/libump/arch_011_udd/ump_frontend.c deleted file mode 100644 index 8c93332..0000000 --- a/exynos4/hal/libump/arch_011_udd/ump_frontend.c +++ /dev/null @@ -1,213 +0,0 @@ -/* - * Copyright (C) 2010-2011 ARM Limited. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @file ump_frontend.c - * - * This file implements the user space API of the UMP API. - * It relies heavily on a arch backend to do the communication with the UMP device driver. - */ - -#include -#include "ump_internal.h" -#include "ump_arch.h" -#include -#include - -UMP_API_EXPORT ump_result ump_open(void) -{ - return ump_arch_open(); -} - -UMP_API_EXPORT void ump_close(void) -{ - ump_arch_close(); -} - -UMP_API_EXPORT ump_secure_id ump_secure_id_get(ump_handle memh) -{ - ump_mem * mem = (ump_mem*)memh; - - UMP_DEBUG_ASSERT(UMP_INVALID_MEMORY_HANDLE != memh, ("Handle is invalid")); - UMP_DEBUG_ASSERT(UMP_INVALID_SECURE_ID != mem->secure_id, ("Secure ID is inavlid")); - UMP_DEBUG_ASSERT(0 < mem->ref_count, ("Reference count too low")); - UMP_DEBUG_ASSERT(0 < mem->size, ("Memory size of passed handle too low")); - - return mem->secure_id; -} - -UMP_API_EXPORT ump_handle ump_handle_create_from_secure_id(ump_secure_id secure_id) -{ - unsigned long size; - - UMP_DEBUG_ASSERT(UMP_INVALID_SECURE_ID != secure_id, ("Secure ID is invalid")); - - size = ump_arch_size_get(secure_id); - if (0 != size) - { - unsigned long cookie; - /* - * The UMP memory which the secure_id referes to could now be deleted and re-created - * since we don't have any references to it yet. The mapping below will however fail if - * we have supplied incorrect size, so we are safe. - */ - void * mapping = ump_arch_map(secure_id, size, UMP_CACHE_DISABLE, &cookie); - if (NULL != mapping) - { - ump_mem * mem = _ump_osu_calloc(1, sizeof(*mem)); - if (NULL != mem) - { - mem->secure_id = secure_id; - mem->mapped_mem = mapping; - mem->size = size; - mem->cookie = cookie; - mem->is_cached = 1; /* Is set to actually check in the ump_cpu_msync_now() function */ - - _ump_osu_lock_auto_init(&mem->ref_lock, 0, 0, 0); - UMP_DEBUG_ASSERT(NULL != mem->ref_lock, ("Failed to initialize lock\n")); - mem->ref_count = 1; - - /* This is called only to set the cache settings in this handle */ - ump_cpu_msync_now((ump_handle)mem, UMP_MSYNC_READOUT_CACHE_ENABLED, NULL, 0); - - UMP_DEBUG_PRINT(4, ("UMP handle created for ID %u of size %lu, mapped into address 0x%08lx", mem->secure_id, mem->size, (unsigned long)mem->mapped_mem)); - - return (ump_handle)mem; - } - - ump_arch_unmap(mapping, size, cookie); - } - } - - UMP_DEBUG_PRINT(2, ("UMP handle creation failed for ID %u", secure_id)); - - return UMP_INVALID_MEMORY_HANDLE; -} - -UMP_API_EXPORT unsigned long ump_size_get(ump_handle memh) -{ - ump_mem * mem = (ump_mem*)memh; - - UMP_DEBUG_ASSERT(UMP_INVALID_MEMORY_HANDLE != memh, ("Handle is invalid")); - UMP_DEBUG_ASSERT(UMP_INVALID_SECURE_ID != mem->secure_id, ("Secure ID is inavlid")); - UMP_DEBUG_ASSERT(0 < mem->ref_count, ("Reference count too low")); - UMP_DEBUG_ASSERT(0 < mem->size, ("Memory size of passed handle too low")); - - return mem->size; -} - -UMP_API_EXPORT void ump_read(void *dst, ump_handle srch, unsigned long offset, unsigned long length) -{ - ump_mem * src = (ump_mem*)srch; - - UMP_DEBUG_ASSERT(UMP_INVALID_MEMORY_HANDLE != srch, ("Handle is invalid")); - UMP_DEBUG_ASSERT(UMP_INVALID_SECURE_ID != src->secure_id, ("Secure ID is inavlid")); - UMP_DEBUG_ASSERT(0 < src->ref_count, ("Reference count too low")); - UMP_DEBUG_ASSERT(0 < src->size, ("Memory size of passed handle too low")); - UMP_DEBUG_ASSERT(NULL != src->mapped_mem, ("UMP Memory is not mapped")); - UMP_DEBUG_ASSERT((src->size) >= (offset + length), ("Requested read beyond end of UMP memory")); - - _ump_osu_memcpy(dst,(char*)(src->mapped_mem) + offset, length); -} - -UMP_API_EXPORT void ump_write(ump_handle dsth, unsigned long offset, const void *src, unsigned long length) -{ - ump_mem * dst = (ump_mem*)dsth; - - UMP_DEBUG_ASSERT(UMP_INVALID_MEMORY_HANDLE != dsth, ("Handle is invalid")); - UMP_DEBUG_ASSERT(UMP_INVALID_SECURE_ID != dst->secure_id, ("Secure ID is inavlid")); - UMP_DEBUG_ASSERT(0 < dst->ref_count, ("Reference count too low")); - UMP_DEBUG_ASSERT(0 < dst->size, ("Memory size of passed handle too low")); - UMP_DEBUG_ASSERT(NULL != dst->mapped_mem, ("UMP Memory is not mapped")); - UMP_DEBUG_ASSERT((dst->size) >= (offset + length), ("Requested write beyond end of UMP memory")); - - _ump_osu_memcpy((char*)(dst->mapped_mem) + offset, src, length); -} - - - -UMP_API_EXPORT void* ump_mapped_pointer_get(ump_handle memh) -{ - ump_mem * mem = (ump_mem*)memh; - - UMP_DEBUG_ASSERT(UMP_INVALID_MEMORY_HANDLE != memh, ("Handle is invalid")); - UMP_DEBUG_ASSERT(UMP_INVALID_SECURE_ID != mem->secure_id, ("Secure ID is inavlid")); - UMP_DEBUG_ASSERT(0 < mem->ref_count, ("Reference count too low")); - UMP_DEBUG_ASSERT(0 < mem->size, ("Memory size of passed handle too low")); - UMP_DEBUG_ASSERT(NULL != mem->mapped_mem, ("Error in mapping pointer (not mapped)")); - - return mem->mapped_mem; -} - - - -UMP_API_EXPORT void ump_mapped_pointer_release(ump_handle memh) -{ - UMP_DEBUG_ASSERT(UMP_INVALID_MEMORY_HANDLE != memh, ("Handle is invalid")); - UMP_DEBUG_ASSERT(UMP_INVALID_SECURE_ID != ((ump_mem*)memh)->secure_id, ("Secure ID is inavlid")); - UMP_DEBUG_ASSERT(0 < ((ump_mem*)memh)->ref_count, ("Reference count too low")); - UMP_DEBUG_ASSERT(0 < ((ump_mem*)memh)->size, ("Memory size of passed handle too low")); - UMP_DEBUG_ASSERT(NULL != ((ump_mem*)memh)->mapped_mem, ("Error in mapping pointer (not mapped)")); - - /* noop, cos we map in the pointer when handle is created, and unmap it when handle is destroyed */ -} - - - -UMP_API_EXPORT void ump_reference_add(ump_handle memh) -{ - ump_mem * mem = (ump_mem*)memh; - - UMP_DEBUG_ASSERT(UMP_INVALID_MEMORY_HANDLE != memh, ("Handle is invalid")); - UMP_DEBUG_ASSERT(UMP_INVALID_SECURE_ID != mem->secure_id, ("Secure ID is inavlid")); - UMP_DEBUG_ASSERT(0 < mem->ref_count, ("Reference count too low")); - UMP_DEBUG_ASSERT(0 < mem->size, ("Memory size of passed handle too low")); - - _ump_osu_lock_wait(mem->ref_lock, _UMP_OSU_LOCKMODE_RW); - mem->ref_count += 1; - _ump_osu_lock_signal(mem->ref_lock, _UMP_OSU_LOCKMODE_RW); -} - - - -UMP_API_EXPORT void ump_reference_release(ump_handle memh) -{ - ump_mem * mem = (ump_mem*)memh; - - UMP_DEBUG_ASSERT(UMP_INVALID_MEMORY_HANDLE != memh, ("Handle is invalid")); - UMP_DEBUG_ASSERT(UMP_INVALID_SECURE_ID != ((ump_mem*)mem)->secure_id, ("Secure ID is inavlid")); - UMP_DEBUG_ASSERT(0 < (((ump_mem*)mem)->ref_count), ("Reference count too low")); - UMP_DEBUG_ASSERT(0 < ((ump_mem*)mem)->size, ("Memory size of passed handle too low")); - UMP_DEBUG_ASSERT(NULL != ((ump_mem*)mem)->mapped_mem, ("Error in mapping pointer (not mapped)")); - - _ump_osu_lock_wait(mem->ref_lock, _UMP_OSU_LOCKMODE_RW); - mem->ref_count -= 1; - if (0 == mem->ref_count) - { - /* Remove memory mapping, which holds our only reference towards the UMP kernel space driver */ - ump_arch_unmap(mem->mapped_mem, mem->size, mem->cookie); - - _ump_osu_lock_signal(mem->ref_lock, _UMP_OSU_LOCKMODE_RW); - - /* Free the lock protecting the reference count */ - _ump_osu_lock_term(mem->ref_lock); - - /* Free the memory for this handle */ - _ump_osu_free(mem); - } else { - _ump_osu_lock_signal(mem->ref_lock, _UMP_OSU_LOCKMODE_RW); - } -} diff --git a/exynos4/hal/libump/arch_011_udd/ump_internal.h b/exynos4/hal/libump/arch_011_udd/ump_internal.h deleted file mode 100644 index bc1f2a9..0000000 --- a/exynos4/hal/libump/arch_011_udd/ump_internal.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (C) 2010-2011 ARM Limited. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @file ump_internal.c - * - * Internal definitions and debugging macros for the UMP implementation. - */ - -#ifndef _UNIFIED_MEMORY_PROVIDER_INTERNAL_H_ -#define _UNIFIED_MEMORY_PROVIDER_INTERNAL_H_ - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -typedef enum ump_cache_enabled -{ - UMP_CACHE_DISABLE = 0, - UMP_CACHE_ENABLE = 1 -} ump_cache_enabled; - -/** - * The actual (hidden) definition of ump_handles. - */ -typedef struct ump_mem -{ - ump_secure_id secure_id; /**< UMP device driver cookie */ - void * mapped_mem; /**< Mapped memory; all read and write use this */ - unsigned long size; /**< Size of allocated memory */ - _ump_osu_lock_t* ref_lock; /**< Lock protection ref_count */ - int ref_count; /**< The reference count of the ump_handle in userspace. It is used for finding out - when to free the memory used by this userspace handle. It is NOT the same as the - real ump_mem reference count in the devicedriver which do reference counting - for the memory that this handle reveals. */ - unsigned long cookie; /**< cookie for use in arch_unmap calls */ - ump_cache_enabled is_cached; -} ump_mem; - -#ifdef __cplusplus -} -#endif - - - -#endif /* _UNIFIED_MEMORY_PROVIDER_INTERNAL_H_ */ diff --git a/exynos4/hal/libump/arch_011_udd/ump_ref_drv.c b/exynos4/hal/libump/arch_011_udd/ump_ref_drv.c deleted file mode 100644 index cf3b9eb..0000000 --- a/exynos4/hal/libump/arch_011_udd/ump_ref_drv.c +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright (C) 2010-2011 ARM Limited. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @file ump_ref_drv.c - * - * Implementation of the user space API extensions provided by the reference implementation. - */ - -#include -#include -#include "ump_internal.h" -#include "ump_arch.h" -#include -#include - -/* Allocate a buffer which can be used directly by hardware, 4kb aligned */ -static ump_handle ump_ref_drv_allocate_internal(unsigned long size, ump_alloc_constraints constraints, ump_cache_enabled cache); - - - -/* Allocate a buffer which can be used directly by hardware, 4kb aligned */ -ump_handle ump_ref_drv_allocate(unsigned long size, ump_alloc_constraints constraints) -{ - ump_cache_enabled cache= UMP_CACHE_DISABLE; - if ( 0!=(constraints&UMP_REF_DRV_CONSTRAINT_USE_CACHE) ) - { - cache = UMP_CACHE_ENABLE; - } - return ump_ref_drv_allocate_internal(size, constraints, cache); -} - -UMP_API_EXPORT int ump_cpu_msync_now(ump_handle memh, ump_cpu_msync_op op, void* address, int size) -{ - ump_mem * mem = (ump_mem*)memh; - UMP_DEBUG_ASSERT(UMP_INVALID_MEMORY_HANDLE != memh, ("Handle is invalid")); - - /* If the op is readout, we do the readout from DD. - Else we skip flushing if the userspace handle says that it is uncached */ - if ((UMP_MSYNC_READOUT_CACHE_ENABLED!=op) && (0 == mem->is_cached) ) return 0; - - UMP_DEBUG_ASSERT(0 < (((ump_mem*)mem)->ref_count), ("Reference count too low")); - UMP_DEBUG_ASSERT((size>=0) && (size <= ((ump_mem*)mem)->size), ("Memory size of passed handle too low")); - UMP_DEBUG_ASSERT(NULL != ((ump_mem*)mem)->mapped_mem, ("Error in mapping pointer (not mapped)")); - - if (size > mem->size) size = mem->size; - - mem->is_cached = ump_arch_msync(mem->secure_id, mem->mapped_mem, mem->cookie, address, size, op); - return mem->is_cached ; -} - -/* Allocate a buffer which can be used directly by hardware, 4kb aligned */ -static ump_handle ump_ref_drv_allocate_internal(unsigned long size, ump_alloc_constraints constraints, ump_cache_enabled cache) -{ - ump_secure_id secure_id; - unsigned long allocated_size = size; - - UMP_DEBUG_PRINT(4, ("Allocating UMP memory of size %lu", size)); - - secure_id = ump_arch_allocate(&allocated_size, constraints); - if (secure_id != UMP_INVALID_SECURE_ID) - { - unsigned long cookie; - void * mapping; - - mapping = ump_arch_map(secure_id, allocated_size, cache, &cookie); - if (NULL != mapping) - { - /* - * PS: By now we have actually increased the ref count in the device driver by 2, - * one for the allocation iteself, and one for the mapping. - */ - ump_mem * mem; - mem = _ump_osu_calloc(1, sizeof(*mem)); - if (NULL != mem) - { - mem->secure_id = secure_id; - mem->mapped_mem = mapping; - mem->size = allocated_size; - mem->cookie = cookie; - mem->is_cached = 1; /* Default to ON, is disabled later if not */ - - _ump_osu_lock_auto_init(&mem->ref_lock, 0, 0, 0); - UMP_DEBUG_ASSERT(NULL != mem->ref_lock, ("Failed to initialize lock\n")); - mem->ref_count = 1; - - /* - * ump_arch_allocate() gave us a kernel space reference, and the same did ump_arch_map() - * We release the one from ump_arch_allocate(), and rely solely on the one from the ump_arch_map() - * That is, ump_arch_unmap() should now do the final release towards the UMP kernel space driver. - */ - ump_arch_reference_release(secure_id); - - /* This is called only to set the cache settings in this handle */ - ump_cpu_msync_now((ump_handle)mem, UMP_MSYNC_READOUT_CACHE_ENABLED, NULL, 0); - - UMP_DEBUG_PRINT(4, ("UMP handle created for ID %u of size %lu, mapped into address 0x%08lx", mem->secure_id, mem->size, (unsigned long)mem->mapped_mem)); - - return (ump_handle)mem; - } - - ump_arch_unmap(mapping, allocated_size, cookie); /* Unmap the memory */ - ump_arch_reference_release(secure_id); /* Release reference added when we allocated the UMP memory */ - } - - ump_arch_reference_release(secure_id); /* Release reference added when we allocated the UMP memory */ - } - - UMP_DEBUG_PRINT(4, ("Allocation of UMP memory failed")); - return UMP_INVALID_MEMORY_HANDLE; -} diff --git a/exynos4/hal/libump/include/ump/ump_debug.h b/exynos4/hal/libump/include/ump/ump_debug.h deleted file mode 100644 index 5ede8a3..0000000 --- a/exynos4/hal/libump/include/ump/ump_debug.h +++ /dev/null @@ -1,287 +0,0 @@ -/* - * Copyright (C) 2010-2011 ARM Limited. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @file ump_debug.h - * - * The file include several useful macros for debugging and printing. - * - UMP_PRINTF(...) Do not use this function: Will be included in Release builds. - * - UMP_DEBUG_TRACE() Prints current location in code. - * - UMP_DEBUG_PRINT(nr, (X) ) Prints the second argument if nr<=UMP_DEBUG_LEVEL. - * - UMP_DEBUG_TPRINT(nr, X ) Prints the source trace and second argument if nr<=UMP_DEBUG_LEVEL. - * - UMP_DEBUG_ERROR( (X) ) Prints an errortext, a source trace, and the given error message. - * - UMP_DEBUG_ASSERT(exp,(X)) If the asserted expr is false, the program will exit. - * - UMP_DEBUG_ASSERT_RANGE(x, min, max) Triggers if variable x is not between or equal to max and min. - * - UMP_DEBUG_ASSERT_LEQ(x, max) Triggers if variable x is not less than equal to max. - * - UMP_DEBUG_ASSERT_POINTER(pointer) Triggers if the pointer is a zero pointer. - * - UMP_DEBUG_CODE( X ) The code inside the macro is only copiled in Debug builds. - * - * The (X) means that you must add an extra parantese around the argumentlist. - * - * The printf function: UMP_PRINTF(...) is routed to _ump_sys_printf - * - * Suggested range for the DEBUG-LEVEL is [1:6] where - * [1:2] Is messages with highest priority, indicate possible errors. - * [3:4] Is messages with medium priority, output important variables. - * [5:6] Is messages with low priority, used during extensive debugging. - * - */ -#ifndef _UMP_DEBUG_H_ -#define _UMP_DEBUG_H_ - -#include -#include - -/* START: Configuration */ -#ifndef UMP_PRINTF - #define UMP_PRINTF printf -#endif /* UMP_PRINTF */ - -#ifndef UMP_PRINT_FLUSH - #define UMP_PRINT_FLUSH do {} while (0) -#endif /* UMP_PRINT_FLUSH */ - -#ifndef UMP_DEBUG_LEVEL - #define UMP_DEBUG_LEVEL 1 -#endif /* UMP_DEBUG_LEVEL */ - -#ifndef UMP_DEBUG_ERROR_START_MSG - #define UMP_DEBUG_ERROR_START_MSG do {\ - UMP_PRINTF("*********************************************************************\n");\ - UMP_PRINT_FLUSH; } while (0) -#endif /* UMP_DEBUG_ERROR_START_MSG */ - -#ifndef UMP_DEBUG_ERROR_STOP_MSG - #define UMP_DEBUG_ERROR_STOP_MSG do { UMP_PRINTF("\n"); UMP_PRINT_FLUSH; } while (0) -#endif /* UMP_DEBUG_ERROR_STOP_MSG */ - -#ifndef UMP_ASSERT_QUIT_CMD - #define UMP_ASSERT_QUIT_CMD abort() -#endif /* UMP_ASSERT_QUIT_CMD */ -/* STOP: Configuration */ - -/** - * The macro UMP_FUNCTION evaluates to the name of the function enclosing - * this macro's usage, or "" if not supported. - */ -#if (defined(__SYMBIAN32__) && defined(__ARMCC__)) || defined(_MSC_VER) -# define UMP_FUNCTION __FUNCTION__ -#elif __STDC__ && __STDC_VERSION__ >= 199901L -# define UMP_FUNCTION __FUNCTION__ -#elif defined(__GNUC__) && __GNUC__ >= 2 -# define UMP_FUNCTION __FUNCTION__ -#elif defined(__func__) -# define UMP_FUNCTION __func__ -#else -# define UMP_FUNCTION "" -#endif - -/** - * Explicitly ignore a parameter passed into a function, to suppress compiler warnings. - * Should only be used with parameter names. - */ -#define UMP_IGNORE(x) (void)x - -/** - * @def UMP_DEBUG_TRACE() - * @brief Prints current location in code. - * Can be turned off by defining UMP_DEBUG_SKIP_TRACE - */ - -#ifndef UMP_DEBUG_SKIP_TRACE - #ifndef UMP_DEBUG_SKIP_PRINT_FUNCTION_NAME - #define UMP_DEBUG_TRACE() do { UMP_PRINTF( "In file: "__FILE__ \ - " function: %s() line:%4d\n" , UMP_FUNCTION, __LINE__); UMP_PRINT_FLUSH; } while (0) - #else - #define UMP_DEBUG_TRACE() do { UMP_PRINTF( "In file: "__FILE__ " line:%4d\n" , __LINE__); UMP_PRINT_FLUSH; } while (0) - #endif /* UMP_DEBUG_SKIP_PRINT_FUNCTION_NAME */ -#else - #define UMP_DEBUG_TRACE() -#endif /* UMP_DEBUG_SKIP_TRACE */ - -/** - * @def UMP_DEBUG_PRINT(nr, (X) ) - * @brief Prints the second argument if nr<=UMP_DEBUG_LEVEL. - * Can be turned off by defining UMP_DEBUG_SKIP_PRINT - * @param nr If nr <= UMP_DEBUG_LEVEL, we print the text. - * @param X A parantese with the contents to be sent to UMP_PRINTF - */ -#ifndef UMP_DEBUG_SKIP_PRINT - #define UMP_DEBUG_PRINT(nr, X ) do { if ( nr<=UMP_DEBUG_LEVEL ) { UMP_PRINTF X ; UMP_PRINT_FLUSH; } } while (0) -#else - #define UMP_DEBUG_PRINT(nr, X ) -#endif /* UMP_DEBUG_SKIP_PRINT */ - -/** - * @def UMP_DEBUG_TPRINT(nr, (X) ) - * @brief Prints the second argument if nr<=UMP_DEBUG_LEVEL. - * Can be turned off by defining UMP_DEBUG_SKIP_TPRINT. - * Can be shortened by defining UMP_DEBUG_TPRINT_SKIP_FUNCTION. - * @param nr If nr <= UMP_DEBUG_LEVEL, we print the text. - * @param X A parantese with the contents to be sent to UMP_PRINTF - */ - -/* helper to handle if the function name should be included or not */ -#ifndef UMP_DEBUG_TPRINT_SKIP_FUNCTION - #define UMP_DEBUG_TPRINT_INTERN do {UMP_PRINTF( ""__FILE__" %s()%4d " , UMP_FUNCTION, __LINE__); UMP_PRINT_FLUSH; } while (0) -#else - #define UMP_DEBUG_TPRINT_INTERN do {UMP_PRINTF( ""__FILE__ "%4d " , __LINE__); UMP_PRINT_FLUSH; } while (0) -#endif /* UMP_DEBUG_TPRINT_SKIP_FUNCTION */ - -#ifndef UMP_DEBUG_SKIP_TPRINT - #define UMP_DEBUG_TPRINT(nr, X ) \ - do{\ - if ( nr<=UMP_DEBUG_LEVEL )\ - {\ - UMP_DEBUG_TPRINT_INTERN;\ - UMP_PRINTF X ;\ - UMP_PRINT_FLUSH;\ - }\ - } while (0) -#else - #define UMP_DEBUG_TPRINT(nr, X ) -#endif /* UMP_DEBUG_SKIP_TPRINT */ - -/** - * @def UMP_DEBUG_ERROR( (X) ) - * @brief Prints an errortext, a source Trace, and the given error message. - * Prints filename, function, linenr, and the given error message. - * The error message must be inside a second parantese. - * The error message is written on a separate line, and a NL char is added. - * Can be turned of by defining UMP_DEBUG_SKIP_ERROR; - * You do not need to type the words ERROR in the message, since it will - * be added anyway. - * - * @note You should not end the text with a newline, since it is added by the macro. - * @note You should not write "ERROR" in the text, since it is added by the macro. - * @param X A parantese with the contents to be sent to UMP_PRINTF - */ - -#ifndef UMP_DEBUG_SKIP_ERROR - #define UMP_DEBUG_ERROR( X ) \ - do{ \ - UMP_DEBUG_ERROR_START_MSG;\ - UMP_PRINTF("ERROR: ");\ - UMP_PRINT_FLUSH;\ - UMP_DEBUG_TRACE(); \ - UMP_PRINTF X ; \ - UMP_PRINT_FLUSH;\ - UMP_DEBUG_ERROR_STOP_MSG;\ - } while (0) -#else - #define UMP_DEBUG_ERROR( X ) do{ ; } while ( 0 ) -#endif /* UMP_DEBUG_SKIP_ERROR */ - -/** - * @def UMP_DEBUG_ASSERT(expr, (X) ) - * @brief If the asserted expr is false, the program will exit. - * Prints filename, function, linenr, and the given error message. - * The error message must be inside a second parantese. - * The error message is written on a separate line, and a NL char is added. - * Can be turned of by defining UMP_DEBUG_SKIP_ERROR; - * You do not need to type the words ASSERT in the message, since it will - * be added anyway. - * - * @param X A parantese with the contents to be sent to UMP_PRINTF - * Prints filename, function, linenr, and the error message - * on a separte line. A newline char is added at the end. - * Can be turned of by defining UMP_DEBUG_SKIP_ASSERT - * @param expr Will exit program if \a expr is false; - * @param (X) Text that will be written if the assertion toggles. - */ - -#ifndef UMP_DEBUG_SKIP_ASSERT - #define UMP_DEBUG_ASSERT(expr, X ) \ - do{\ - if ( !(expr) ) \ - { \ - UMP_DEBUG_ERROR_START_MSG;\ - UMP_PRINTF("ASSERT EXIT: ");\ - UMP_PRINT_FLUSH;\ - UMP_DEBUG_TRACE(); \ - UMP_PRINTF X ; \ - UMP_PRINT_FLUSH;\ - UMP_DEBUG_ERROR_STOP_MSG;\ - UMP_ASSERT_QUIT_CMD;\ - }\ - } while (0) -#else - #define UMP_DEBUG_ASSERT(expr, X) -#endif /* UMP_DEBUG_SKIP_ASSERT */ - - -/** - * @def UMP_DEBUG_ASSERT_POINTER(pointer) - * @brief If the asserted pointer is NULL, the program terminates and TRACE info is printed - * The checking is disabled if "UMP_DEBUG_SKIP_ASSERT" is defined. - */ -#define UMP_DEBUG_ASSERT_POINTER(pointer) UMP_DEBUG_ASSERT(pointer, ("Null pointer " #pointer) ) - -/** - * @def UMP_DEBUG_ASSERT_HANDLE(handle) - * @brief If the asserted handle is not a valid handle, the program terminates and TRACE info is printed - * The checking is disabled if "UMP_DEBUG_SKIP_ASSERT" is defined. - */ -#define UMP_DEBUG_ASSERT_HANDLE(handle) UMP_DEBUG_ASSERT(UMP_NO_HANDLE != (handle), ("Invalid handle" #handle) ) - -/** - * @def UMP_DEBUG_ASSERT_ALIGNMENT(ptr, align) - * @brief If the asserted pointer is not aligned to align, the program terminates with trace info printed. - * The checking is disabled if "UMP_DEBUG_SKIP_ASSERT" is defined. - */ -#ifndef UMP_DEBUG_SKIP_ASSERT - #define UMP_DEBUG_ASSERT_ALIGNMENT(ptr, align) do { \ - UMP_DEBUG_ASSERT(0 == (align & (align - 1)), ("align %d is not a power-of-two", align)); \ - UMP_DEBUG_ASSERT(0 == (((u32)(ptr)) & (align - 1)), ("ptr %p not aligned to %d bytes", (void*)ptr, align)); \ - } while (0) -#else - #define UMP_DEBUG_ASSERT_ALIGNMENT(ptr, align) -#endif /* UMP_DEBUG_SKIP_ASSERT */ - -/** - * @def UMP_DEBUG_ASSERT_RANGE(x,min,max) - * @brief If variable x is not between or equal to max and min, the assertion triggers. - * The checking is disabled if "UMP_DEBUG_SKIP_ASSERT" is defined. - */ -#define UMP_DEBUG_ASSERT_RANGE(x, min, max) \ - UMP_DEBUG_ASSERT( (x) >= (min) && (x) <= (max), \ - (#x " out of range (%2.2f)", (double)x ) \ - ) - -/** - * @def UMP_DEBUG_ASSERT_LEQ(x,max) - * @brief If variable x is less than or equal to max, the assertion triggers. - * The checking is disabled if "UMP_DEBUG_SKIP_ASSERT" is defined. - */ -#define UMP_DEBUG_ASSERT_LEQ(x, max) \ - UMP_DEBUG_ASSERT( (x) <= (max), \ - (#x " out of range (%2.2f)", (double)x ) \ - ) - -/** - * @def UMP_DEBUG_CODE( X ) - * @brief Run the code X on debug builds. - * The code will not be used if UMP_DEBUG_SKIP_CODE is defined . - * - */ -#ifdef UMP_DEBUG_SKIP_CODE - #define UMP_DEBUG_CODE( X ) -#else - #define UMP_DEBUG_CODE( X ) X -#endif /* UMP_DEBUG_SKIP_CODE */ - -#endif /* _UMP_DEBUG_H_ */ - diff --git a/exynos4/hal/libump/include/ump/ump_osu.h b/exynos4/hal/libump/include/ump/ump_osu.h deleted file mode 100644 index 5c9a650..0000000 --- a/exynos4/hal/libump/include/ump/ump_osu.h +++ /dev/null @@ -1,430 +0,0 @@ -/* - * Copyright (C) 2010-2011 ARM Limited. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @file ump_osu.h - * Defines the OS abstraction layer for the base driver - */ - -#ifndef __UMP_OSU_H__ -#define __UMP_OSU_H__ - -#include - -#ifdef __cplusplus -extern "C" -{ -#endif - - -typedef unsigned int u32; -#ifdef _MSC_VER - typedef unsigned __int64 u64; - typedef signed __int64 s64; -#else - typedef unsigned long long u64; - typedef signed long long s64; -#endif - -#ifndef NULL -#define NULL ((void*)0) -#endif - -typedef unsigned long ump_bool; - -#ifndef UMP_TRUE -#define UMP_TRUE ((ump_bool)1) -#endif - -#ifndef UMP_FALSE -#define UMP_FALSE ((ump_bool)0) -#endif - -#define UMP_STATIC static - -/** - * @addtogroup ump_user_space_api Unified Device Driver (UDD) APIs used by UMP - * - * @{ - */ - -/** - * @defgroup ump_osuapi UDD OS Abstraction for User-side (OSU) APIs for UMP - * - * @{ - */ - -/* The following is necessary to prevent the _ump_osk_errcode_t doxygen from - * becoming unreadable: */ -/** @cond OSU_COPY_OF__UMP_OSU_ERRCODE_T */ - -/** - * @brief OSU/OSK Error codes. - * - * Each OS may use its own set of error codes, and may require that the - * User/Kernel interface take certain error code. This means that the common - * error codes need to be sufficiently rich to pass the correct error code - * through from the OSK/OSU to U/K layer, across all OSs. - * - * The result is that some error codes will appear redundant on some OSs. - * Under all OSs, the OSK/OSU layer must translate native OS error codes to - * _ump_osk/u_errcode_t codes. Similarly, the U/K layer must translate from - * _ump_osk/u_errcode_t codes to native OS error codes. - * - */ -typedef enum -{ - _UMP_OSK_ERR_OK = 0, /**< Success. */ - _UMP_OSK_ERR_FAULT = -1, /**< General non-success */ - _UMP_OSK_ERR_INVALID_FUNC = -2, /**< Invalid function requested through User/Kernel interface (e.g. bad IOCTL number) */ - _UMP_OSK_ERR_INVALID_ARGS = -3, /**< Invalid arguments passed through User/Kernel interface */ - _UMP_OSK_ERR_NOMEM = -4, /**< Insufficient memory */ - _UMP_OSK_ERR_TIMEOUT = -5, /**< Timeout occured */ - _UMP_OSK_ERR_RESTARTSYSCALL = -6, /**< Special: On certain OSs, must report when an interruptable mutex is interrupted. Ignore otherwise. */ - _UMP_OSK_ERR_ITEM_NOT_FOUND = -7, /**< Table Lookup failed */ - _UMP_OSK_ERR_BUSY = -8, /**< Device/operation is busy. Try again later */ - _UMP_OSK_ERR_UNSUPPORTED = -9, /**< Optional part of the interface used, and is unsupported */ -} _ump_osk_errcode_t; - -/** @endcond */ /* end cond OSU_COPY_OF__UMP_OSU_ERRCODE_T */ - -/** - * @brief OSU Error codes. - * - * OSU error codes - enum values intentionally same as OSK - */ -typedef enum -{ - _UMP_OSU_ERR_OK = 0, /**< Success. */ - _UMP_OSU_ERR_FAULT = -1, /**< General non-success */ - _UMP_OSU_ERR_TIMEOUT = -2, /**< Timeout occured */ -} _ump_osu_errcode_t; - -/** @brief Translate OSU error code to base driver error code. - * - * The _UMP_OSU_TRANSLATE_ERROR macro translates an OSU error code to the - * error codes in use by the base driver. - */ -#define _UMP_OSU_TRANSLATE_ERROR(_ump_osu_errcode) ( ( _UMP_OSU_ERR_OK == (_ump_osu_errcode) ) ? UMP_ERR_NO_ERROR : UMP_ERR_FUNCTION_FAILED) - -/** @defgroup _ump_osu_lock OSU Mutual Exclusion Locks - * @{ */ - -/** @brief OSU Mutual Exclusion Lock flags type. - * - * This is made to look like and function identically to the OSK locks (refer - * to \ref _ump_osk_lock). However, please note the following \b important - * differences: - * - the OSU default lock is a Sleeping, non-interruptible mutex. - * - the OSU adds the ANYUNLOCK type of lock which allows a thread which doesn't - * own the lock to release the lock. - * - the order parameter when creating a lock is currently unused - * - * @note Pay careful attention to the difference in default locks for OSU and - * OSK locks; OSU locks are always non-interruptible, but OSK locks are by - * default, interruptible. This has implications for systems that do not - * distinguish between user and kernel mode. - */ -typedef enum -{ - _UMP_OSU_LOCKFLAG_DEFAULT = 0, /**< Default lock type. */ - /** @enum _ump_osu_lock_flags_t - * - * Flags from 0x8000--0x1 are RESERVED for Kernel-mode - */ - _UMP_OSU_LOCKFLAG_ANYUNLOCK = 0x10000, /**< Mutex that guarantees that any thread can unlock it when locked. Otherwise, this will not be possible. */ - /** @enum _ump_osu_lock_flags_t - * - * Flags from 0x80000000 are RESERVED for User-mode - */ - _UMP_OSU_LOCKFLAG_STATIC = 0x80000000, /* Flag in OSU reserved range to identify lock as a statically initialized lock */ - - } _ump_osu_lock_flags_t; - -typedef enum -{ - _UMP_OSU_LOCKMODE_UNDEF = -1, /**< Undefined lock mode. For internal use only */ - _UMP_OSU_LOCKMODE_RW = 0x0, /**< Default. Lock is used to protect data that is read from and written to */ - /** @enum _ump_osu_lock_mode_t - * - * Lock modes 0x1--0x3F are RESERVED for Kernel-mode */ -} _ump_osu_lock_mode_t; - -/** @brief Private type for Mutual Exclusion lock objects. */ -typedef struct _ump_osu_lock_t_struct _ump_osu_lock_t; - -/** @brief The number of static locks supported in _ump_osu_lock_static(). */ -#define UMP_OSU_STATIC_LOCK_COUNT (sizeof(_ump_osu_static_locks) / sizeof(_ump_osu_lock_t)) - -/** @} */ /* end group _ump_osu_lock */ - -/** @defgroup _ump_osu_memory OSU Memory Allocation - * @{ */ - -/** @brief Allocate zero-initialized memory. - * - * Returns a buffer capable of containing at least \a n elements of \a size - * bytes each. The buffer is initialized to zero. - * - * The buffer is suitably aligned for storage and subsequent access of every - * type that the compiler supports. Therefore, the pointer to the start of the - * buffer may be cast into any pointer type, and be subsequently accessed from - * such a pointer, without loss of information. - * - * When the buffer is no longer in use, it must be freed with _ump_osu_free(). - * Failure to do so will cause a memory leak. - * - * @note Most toolchains supply memory allocation functions that meet the - * compiler's alignment requirements. - * - * @param n Number of elements to allocate - * @param size Size of each element - * @return On success, the zero-initialized buffer allocated. NULL on failure - */ -void *_ump_osu_calloc( u32 n, u32 size ); - -/** @brief Allocate memory. - * - * Returns a buffer capable of containing at least \a size bytes. The - * contents of the buffer are undefined. - * - * The buffer is suitably aligned for storage and subsequent access of every - * type that the compiler supports. Therefore, the pointer to the start of the - * buffer may be cast into any pointer type, and be subsequently accessed from - * such a pointer, without loss of information. - * - * When the buffer is no longer in use, it must be freed with _ump_osu_free(). - * Failure to do so will cause a memory leak. - * - * @note Most toolchains supply memory allocation functions that meet the - * compiler's alignment requirements. - * - * Remember to free memory using _ump_osu_free(). - * @param size Number of bytes to allocate - * @return On success, the buffer allocated. NULL on failure. - */ -void *_ump_osu_malloc( u32 size ); - -/** @brief Free memory. - * - * Reclaims the buffer pointed to by the parameter \a ptr for the system. - * All memory returned from _ump_osu_malloc(), _ump_osu_calloc() and - * _ump_osu_realloc() must be freed before the application exits. Otherwise, - * a memory leak will occur. - * - * Memory must be freed once. It is an error to free the same non-NULL pointer - * more than once. - * - * It is legal to free the NULL pointer. - * - * @param ptr Pointer to buffer to free - */ -void _ump_osu_free( void *ptr ); - -/** @brief Copies memory. - * - * Copies the \a len bytes from the buffer pointed by the parameter \a src - * directly to the buffer pointed by \a dst. - * - * It is an error for \a src to overlap \a dst anywhere in \a len bytes. - * - * @param dst Pointer to the destination array where the content is to be - * copied. - * @param src Pointer to the source of data to be copied. - * @param len Number of bytes to copy. - * @return \a dst is always passed through unmodified. - */ -void *_ump_osu_memcpy( void *dst, const void *src, u32 len ); - -/** @brief Fills memory. - * - * Sets the first \a size bytes of the block of memory pointed to by \a ptr to - * the specified value - * @param ptr Pointer to the block of memory to fill. - * @param chr Value to be set, passed as u32. Only the 8 Least Significant Bits (LSB) - * are used. - * @param size Number of bytes to be set to the value. - * @return \a ptr is always passed through unmodified - */ -void *_ump_osu_memset( void *ptr, u32 chr, u32 size ); - -/** @} */ /* end group _ump_osu_memory */ - - -/** @addtogroup _ump_osu_lock - * @{ */ - -/** @brief Initialize a Mutual Exclusion Lock. - * - * Locks are created in the signalled (unlocked) state. - * - * The parameter \a initial must be zero. - * - * At present, the parameter \a order must be zero. It remains for future - * expansion for mutex order checking. - * - * @param flags flags combined with bitwise OR ('|'), or zero. There are - * restrictions on which flags can be combined, see \ref _ump_osu_lock_flags_t. - * @param initial For future expansion into semaphores. SBZ. - * @param order The locking order of the mutex. SBZ. - * @return On success, a pointer to a \ref _ump_osu_lock_t object. NULL on failure. - */ -_ump_osu_lock_t *_ump_osu_lock_init( _ump_osu_lock_flags_t flags, u32 initial, u32 order ); - -/** @brief Obtain a statically initialized Mutual Exclusion Lock. - * - * Retrieves a reference to a statically initialized lock. Up to - * _UMP_OSU_STATIC_LOCK_COUNT statically initialized locks are - * available. Only _ump_osu_lock_wait(), _ump_osu_lock_trywait(), - * _ump_osu_lock_signal() can be used with statically initialized locks. - * _UMP_OSU_LOCKMODE_RW mode should be used when waiting and signalling - * statically initialized locks. - * - * For the same \a nr a pointer to the same statically initialized lock is - * returned. That is, given the following code: - * @code - * extern u32 n; - * - * _ump_osu_lock_t *locka = _ump_osu_lock_static(n); - * _ump_osu_lock_t *lockb = _ump_osu_lock_static(n); - * @endcode - * Then (locka == lockb), for all 0 <= n < UMP_OSU_STATIC_LOCK_COUNT. - * - * @param nr index of a statically initialized lock [0..UMP_OSU_STATIC_LOCK_COUNT-1] - * @return On success, a pointer to a _ump_osu_lock_t object. NULL on failure. - */ -_ump_osu_lock_t *_ump_osu_lock_static( u32 nr ); - -/** @brief Initialize a Mutual Exclusion Lock safely across multiple threads. - * - * The _ump_osu_lock_auto_init() function guarantees that the given lock will - * be initialized once and precisely once, even in a situation involving - * multiple threads. - * - * This is necessary because the first call to certain Public API functions must - * initialize the API. However, there can be a race involved to call the first - * library function in multi-threaded applications. To resolve this race, a - * mutex can be used. This mutex must be initialized, but initialized only once - * by any thread that might compete for its initialization. This function - * guarantees the initialization to happen correctly, even when there is an - * initialization race between multiple threads. - * - * Otherwise, the operation is identical to the _ump_osu_lock_init() function. - * For more details, refer to _ump_osu_lock_init(). - * - * @param pplock pointer to storage for a _ump_osu_lock_t pointer. This - * _ump_osu_lock_t pointer may point to a _ump_osu_lock_t that has been - * initialized already - * @param flags flags combined with bitwise OR ('|'), or zero. There are - * restrictions on which flags can be combined. Refer to - * \ref _ump_osu_lock_flags_t for more information. - * The absence of any flags (the value 0) results in a sleeping-mutex, - * which is non-interruptible. - * @param initial For future expansion into semaphores. SBZ. - * @param order The locking order of the mutex. SBZ. - * @return On success, _UMP_OSU_ERR_OK is returned and a pointer to an - * initialized \ref _ump_osu_lock_t object is written into \a *pplock. - * _UMP_OSU_ERR_FAULT is returned on failure. - */ -_ump_osu_errcode_t _ump_osu_lock_auto_init( _ump_osu_lock_t **pplock, _ump_osu_lock_flags_t flags, u32 initial, u32 order ); - -/** @brief Wait for a lock to be signalled (obtained). - * - * After a thread has successfully waited on the lock, the lock is obtained by - * the thread, and is marked as unsignalled. The thread releases the lock by - * signalling it. - * - * To prevent deadlock, locks must always be obtained in the same order. - * - * @param lock the lock to wait upon (obtain). - * @param mode the mode in which the lock should be obtained. Currently this - * must be _UMP_OSU_LOCKMODE_RW. - * @return On success, _UMP_OSU_ERR_OK, _UMP_OSU_ERR_FAULT on error. - */ -_ump_osu_errcode_t _ump_osu_lock_wait( _ump_osu_lock_t *lock, _ump_osu_lock_mode_t mode); - -/** @brief Wait for a lock to be signalled (obtained) with timeout - * - * After a thread has successfully waited on the lock, the lock is obtained by - * the thread, and is marked as unsignalled. The thread releases the lock by - * signalling it. - * - * To prevent deadlock, locks must always be obtained in the same order. - * - * This version can return early if it cannot obtain the lock within the given timeout. - * - * @param lock the lock to wait upon (obtain). - * @param mode the mode in which the lock should be obtained. Currently this - * must be _UMP_OSU_LOCKMODE_RW. - * @param timeout Relative time in microseconds for the timeout - * @return _UMP_OSU_ERR_OK if the lock was obtained, _UMP_OSU_ERR_TIMEOUT if the timeout expired or _UMP_OSU_ERR_FAULT on error. - */ -_ump_osu_errcode_t _ump_osu_lock_timed_wait( _ump_osu_lock_t *lock, _ump_osu_lock_mode_t mode, u64 timeout); - -/** @brief Test for a lock to be signalled and obtains the lock when so. - * - * Obtains the lock only when it is in signalled state. The lock is then - * marked as unsignalled. The lock is released again by signalling - * it by _ump_osu_lock_signal(). - * - * If the lock could not be obtained immediately (that is, another thread - * currently holds the lock), then this function \b does \b not wait for the - * lock to be in a signalled state. Instead, an error code is immediately - * returned to indicate that the thread could not obtain the lock. - * - * To prevent deadlock, locks must always be obtained in the same order. - * - * @param lock the lock to wait upon (obtain). - * @param mode the mode in which the lock should be obtained. Currently this - * must be _UMP_OSU_LOCKMODE_RW. - * @return When the lock was obtained, _UMP_OSU_ERR_OK. If the lock could not - * be obtained, _UMP_OSU_ERR_FAULT. - */ -_ump_osu_errcode_t _ump_osu_lock_trywait( _ump_osu_lock_t *lock, _ump_osu_lock_mode_t mode); - -/** @brief Signal (release) a lock. - * - * Locks may only be signalled by the thread that originally waited upon the - * lock, unless the lock was created using the _UMP_OSU_LOCKFLAG_ANYUNLOCK flag. - * - * @param lock the lock to signal (release). - * @param mode the mode in which the lock should be obtained. This must match - * the mode in which the lock was waited upon. - */ -void _ump_osu_lock_signal( _ump_osu_lock_t *lock, _ump_osu_lock_mode_t mode ); - -/** @brief Terminate a lock. - * - * This terminates a lock and frees all associated resources. - * - * It is a programming error to terminate the lock when it is held (unsignalled) - * by a thread. - * - * @param lock the lock to terminate. - */ -void _ump_osu_lock_term( _ump_osu_lock_t *lock ); -/** @} */ /* end group _ump_osu_lock */ - -/** @} */ /* end group osuapi */ - -/** @} */ /* end group uddapi */ - - -#ifdef __cplusplus -} -#endif - -#endif /* __UMP_OSU_H__ */ diff --git a/exynos4/hal/libump/include/ump/ump_platform.h b/exynos4/hal/libump/include/ump/ump_platform.h deleted file mode 100644 index 68e01be..0000000 --- a/exynos4/hal/libump/include/ump/ump_platform.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (C) 2010-2011 ARM Limited. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @file ump_platform.h - * - * This file should define UMP_API_EXPORT, - * which dictates how the UMP user space API should be exported/imported. - * Modify this file, if needed, to match your platform setup. - */ - -#ifndef __UMP_PLATFORM_H__ -#define __UMP_PLATFORM_H__ - -/** @addtogroup ump_user_space_api - * @{ */ - -/** - * A define which controls how UMP user space API functions are imported and exported. - * This define should be set by the implementor of the UMP API. - */ -#if defined(_WIN32) - -#define UMP_API_EXPORT - -#elif defined(__SYMBIAN32__) - -#define UMP_API_EXPORT IMPORT_C - -#else - -#if defined(__GNUC__) -#if __GNUC__ >= 4 -# define MALI_VISIBLE __attribute__ ((visibility ("default"))) /**< Function should be visible from outside the dll */ -#else -# define MALI_VISIBLE -#endif - -#elif defined(__ARMCC_VERSION) -/* ARMCC specific */ -# define MALI_VISIBLE __declspec(dllexport) - -#else -# define MALI_VISIBLE - -#endif - -#define UMP_API_EXPORT MALI_VISIBLE - -#endif - -/** @} */ /* end group ump_user_space_api */ - - -#endif /* __UMP_PLATFORM_H__ */ diff --git a/exynos4/hal/libump/include/ump/ump_uk_types.h b/exynos4/hal/libump/include/ump/ump_uk_types.h deleted file mode 100644 index 1a4c1c8..0000000 --- a/exynos4/hal/libump/include/ump/ump_uk_types.h +++ /dev/null @@ -1,147 +0,0 @@ -/* - * Copyright (C) 2010 ARM Limited. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @file ump_uk_types.h - * Defines the types and constants used in the user-kernel interface - */ - -#ifndef __UMP_UK_TYPES_H__ -#define __UMP_UK_TYPES_H__ - -#ifdef __cplusplus -extern "C" -{ -#endif - -/* Helpers for API version handling */ -#define MAKE_VERSION_ID(x) (((x) << 16UL) | (x)) -#define IS_VERSION_ID(x) (((x) & 0xFFFF) == (((x) >> 16UL) & 0xFFFF)) -#define GET_VERSION(x) (((x) >> 16UL) & 0xFFFF) -#define IS_API_MATCH(x, y) (IS_VERSION_ID((x)) && IS_VERSION_ID((y)) && (GET_VERSION((x)) == GET_VERSION((y)))) - -/** - * API version define. - * Indicates the version of the kernel API - * The version is a 16bit integer incremented on each API change. - * The 16bit integer is stored twice in a 32bit integer - * So for version 1 the value would be 0x00010001 - */ -#define UMP_IOCTL_API_VERSION MAKE_VERSION_ID(2) - -typedef enum -{ - _UMP_IOC_QUERY_API_VERSION = 1, - _UMP_IOC_ALLOCATE, - _UMP_IOC_RELEASE, - _UMP_IOC_SIZE_GET, - _UMP_IOC_MAP_MEM, /* not used in Linux */ - _UMP_IOC_UNMAP_MEM, /* not used in Linux */ - _UMP_IOC_MSYNC, -}_ump_uk_functions; - -typedef enum -{ - UMP_REF_DRV_UK_CONSTRAINT_NONE = 0, - UMP_REF_DRV_UK_CONSTRAINT_PHYSICALLY_LINEAR = 1, - UMP_REF_DRV_UK_CONSTRAINT_USE_CACHE = 4, -} ump_uk_alloc_constraints; - -typedef enum -{ - _UMP_UK_MSYNC_CLEAN = 0, - _UMP_UK_MSYNC_CLEAN_AND_INVALIDATE = 1, - _UMP_UK_MSYNC_READOUT_CACHE_ENABLED = 128, -} ump_uk_msync_op; - -/** - * Get API version ([in,out] u32 api_version, [out] u32 compatible) - */ -typedef struct _ump_uk_api_version_s -{ - void *ctx; /**< [in,out] user-kernel context (trashed on output) */ - u32 version; /**< Set to the user space version on entry, stores the device driver version on exit */ - u32 compatible; /**< Non-null if the device is compatible with the client */ -} _ump_uk_api_version_s; - -/** - * ALLOCATE ([out] u32 secure_id, [in,out] u32 size, [in] contraints) - */ -typedef struct _ump_uk_allocate_s -{ - void *ctx; /**< [in,out] user-kernel context (trashed on output) */ - u32 secure_id; /**< Return value from DD to Userdriver */ - u32 size; /**< Input and output. Requested size; input. Returned size; output */ - ump_uk_alloc_constraints constraints; /**< Only input to Devicedriver */ -} _ump_uk_allocate_s; - -/** - * SIZE_GET ([in] u32 secure_id, [out]size ) - */ -typedef struct _ump_uk_size_get_s -{ - void *ctx; /**< [in,out] user-kernel context (trashed on output) */ - u32 secure_id; /**< Input to DD */ - u32 size; /**< Returned size; output */ -} _ump_uk_size_get_s; - -/** - * Release ([in] u32 secure_id) - */ -typedef struct _ump_uk_release_s -{ - void *ctx; /**< [in,out] user-kernel context (trashed on output) */ - u32 secure_id; /**< Input to DD */ -} _ump_uk_release_s; - -typedef struct _ump_uk_map_mem_s -{ - void *ctx; /**< [in,out] user-kernel context (trashed on output) */ - void *mapping; /**< [out] Returns user-space virtual address for the mapping */ - void *phys_addr; /**< [in] physical address */ - unsigned long size; /**< [in] size */ - u32 secure_id; /**< [in] secure_id to assign to mapping */ - void * _ukk_private; /**< Only used inside linux port between kernel frontend and common part to store vma */ - u32 cookie; - u32 is_cached; /**< [in,out] caching of CPU mappings */ -} _ump_uk_map_mem_s; - -typedef struct _ump_uk_unmap_mem_s -{ - void *ctx; /**< [in,out] user-kernel context (trashed on output) */ - void *mapping; - u32 size; - void * _ukk_private; - u32 cookie; -} _ump_uk_unmap_mem_s; - -typedef struct _ump_uk_msync_s -{ - void *ctx; /**< [in,out] user-kernel context (trashed on output) */ - void *mapping; /**< [in] mapping addr */ - void *address; /**< [in] flush start addr */ - u32 size; /**< [in] size to flush */ - ump_uk_msync_op op; /**< [in] flush operation */ - u32 cookie; /**< [in] cookie stored with reference to the kernel mapping internals */ - u32 secure_id; /**< [in] cookie stored with reference to the kernel mapping internals */ - u32 is_cached; /**< [out] caching of CPU mappings */ -} _ump_uk_msync_s; - -#ifdef __cplusplus -} -#endif - -#endif /* __UMP_UK_TYPES_H__ */ diff --git a/exynos4/hal/libump/os/linux/ump_ioctl.h b/exynos4/hal/libump/os/linux/ump_ioctl.h deleted file mode 100644 index a62c31a..0000000 --- a/exynos4/hal/libump/os/linux/ump_ioctl.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (C) 2010-2011 ARM Limited. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef __UMP_IOCTL_H__ -#define __UMP_IOCTL_H__ - -#ifdef __cplusplus -extern "C" -{ -#endif - -#include -#include - -#include - -#ifndef __user -#define __user -#endif - - -/** - * @file UMP_ioctl.h - * This file describes the interface needed to use the Linux device driver. - * The interface is used by the userpace UMP driver. - */ - -#define UMP_IOCTL_NR 0x90 - - -#define UMP_IOC_QUERY_API_VERSION _IOR(UMP_IOCTL_NR, _UMP_IOC_QUERY_API_VERSION, _ump_uk_api_version_s) -#define UMP_IOC_ALLOCATE _IOWR(UMP_IOCTL_NR, _UMP_IOC_ALLOCATE, _ump_uk_allocate_s) -#define UMP_IOC_RELEASE _IOR(UMP_IOCTL_NR, _UMP_IOC_RELEASE, _ump_uk_release_s) -#define UMP_IOC_SIZE_GET _IOWR(UMP_IOCTL_NR, _UMP_IOC_SIZE_GET, _ump_uk_size_get_s) -#define UMP_IOC_MSYNC _IOW(UMP_IOCTL_NR, _UMP_IOC_MSYNC, _ump_uk_size_get_s) - - -#ifdef __cplusplus -} -#endif - -#endif /* __UMP_IOCTL_H__ */ diff --git a/exynos4/hal/libump/os/linux/ump_osu_locks.c b/exynos4/hal/libump/os/linux/ump_osu_locks.c deleted file mode 100644 index 97ba858..0000000 --- a/exynos4/hal/libump/os/linux/ump_osu_locks.c +++ /dev/null @@ -1,537 +0,0 @@ -/* - * Copyright (C) 2010-2011 ARM Limited. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#if ((!defined _XOPEN_SOURCE) || ((_XOPEN_SOURCE - 0) < 600)) -#undef _XOPEN_SOURCE -#define _XOPEN_SOURCE 600 -#endif - - -#define _POSIX_C_SOURCE 200112L - -#include -#include - -#include -#include -#include -#include - -/** - * @file ump_osu_locks.c - * File implements the user side of the OS interface - */ - -/** @opt Most of the time, we use the plain mutex type of osu_lock, and so - * only require the flags and mutex members. This costs 2 extra DWORDS, but - * most of the time we don't use those DWORDS. - * Therefore, ANY_UNLOCK type osu_locks can be implemented as a second - * structure containing the member _ump_osu_lock_t lock_t, plus the extra - * state required. Then, we use &container->lock_t when passing out of the - * OSU api, and CONTAINER_OF() when passing back in to recover the original - * structure. */ - -/** Private declaration of the OSU lock type */ -struct _ump_osu_lock_t_struct -{ - /** At present, only two types of mutex, so we store this information as - * the flags supplied at init time */ - _ump_osu_lock_flags_t flags; - - pthread_mutex_t mutex; /**< Used in both plain and ANY_UNLOCK osu_locks */ - - /* Extra State for ANY_UNLOCK osu_locks. These are UNINITIALIZED when - * flags does not contain _UMP_OSU_LOCKFLAG_ANYUNLOCK: */ - pthread_cond_t condition; /**< The condition object to use while blocking */ - ump_bool state; /**< The boolean which indicates the event's state */ - - UMP_DEBUG_CODE( - /** debug checking of locks */ - _ump_osu_lock_mode_t locked_as; - ) /* UMP_DEBUG_CODE */ - -}; - -/* Provide two statically initialized locks */ -UMP_STATIC _ump_osu_lock_t _ump_osu_static_locks[] = -{ - { - _UMP_OSU_LOCKFLAG_STATIC, - PTHREAD_MUTEX_INITIALIZER, - PTHREAD_COND_INITIALIZER, - UMP_FALSE, - UMP_DEBUG_CODE( _UMP_OSU_LOCKMODE_UNDEF ) - }, - { - _UMP_OSU_LOCKFLAG_STATIC, - PTHREAD_MUTEX_INITIALIZER, - PTHREAD_COND_INITIALIZER, - UMP_FALSE, - UMP_DEBUG_CODE( _UMP_OSU_LOCKMODE_UNDEF ) - }, - { - _UMP_OSU_LOCKFLAG_STATIC, - PTHREAD_MUTEX_INITIALIZER, - PTHREAD_COND_INITIALIZER, - UMP_FALSE, - UMP_DEBUG_CODE( _UMP_OSU_LOCKMODE_UNDEF ) - }, - { - _UMP_OSU_LOCKFLAG_STATIC, - PTHREAD_MUTEX_INITIALIZER, - PTHREAD_COND_INITIALIZER, - UMP_FALSE, - UMP_DEBUG_CODE( _UMP_OSU_LOCKMODE_UNDEF ) - }, -}; - -/* Critical section for auto_init */ -UMP_STATIC pthread_mutex_t static_auto_init_mutex = PTHREAD_MUTEX_INITIALIZER; - - -_ump_osu_errcode_t _ump_osu_lock_auto_init( _ump_osu_lock_t **pplock, _ump_osu_lock_flags_t flags, u32 initial, u32 order ) -{ - int call_result; - /* Validate parameters: */ - UMP_DEBUG_ASSERT_POINTER( pplock ); - - /** @opt We don't lock the Critical Section or do anything if this is already non-null */ - if ( NULL != *pplock) - { - return _UMP_OSU_ERR_OK; - } - - /* We MIGHT need to initialize it, lock the Critical Section and check again */ - call_result = pthread_mutex_lock(&static_auto_init_mutex); - /* It would be a programming error for this to fail: */ - UMP_DEBUG_ASSERT( 0 == call_result, - ("failed to lock critical section\n") ); - - if ( NULL != *pplock ) - { - /* - We caught a race condition to initialize this osu_lock. - The other thread won the race, so the osu_lock is now initialized. - */ - call_result = pthread_mutex_unlock(&static_auto_init_mutex); - - UMP_DEBUG_ASSERT(0 == call_result, - ("failed to unlock critical section\n")); - - return _UMP_OSU_ERR_OK; - } - - /* We're the first thread in: initialize the osu_lock */ - *pplock = _ump_osu_lock_init( flags, initial, order ); - - if ( NULL == *pplock ) - { - /* osu_lock creation failed */ - call_result = pthread_mutex_unlock(&static_auto_init_mutex); - UMP_DEBUG_ASSERT(0 == call_result, - ("failed to unlock critical section\n")); - - return _UMP_OSU_ERR_FAULT; - } - - - /* osu_lock created OK */ - call_result = pthread_mutex_unlock(&static_auto_init_mutex); - - UMP_DEBUG_ASSERT(0 == call_result, - ("failed to unlock critical section\n")); - - UMP_IGNORE( call_result ); - - return _UMP_OSU_ERR_OK; -} - - -_ump_osu_lock_t *_ump_osu_lock_init( _ump_osu_lock_flags_t flags, u32 initial, u32 order ) -{ - _ump_osu_lock_t * lock; - pthread_mutexattr_t mutex_attributes; - - /* Validate parameters: */ - /* Flags acceptable */ - UMP_DEBUG_ASSERT( 0 == ( flags & ~( _UMP_OSU_LOCKFLAG_ANYUNLOCK)), - ("incorrect flags or trying to initialise a statically initialized lock, %.8X\n", flags) ); - - /* Parameter initial SBZ - for future expansion */ - UMP_DEBUG_ASSERT( 0 == initial, - ("initial must be zero\n") ); - - if (0 != pthread_mutexattr_init(&mutex_attributes)) - { - return NULL; - } - -#if UMP_DEBUG_EXTENDED_MUTEX_LOCK_CHECKING -#define UMP_PTHREADS_MUTEX_TYPE PTHREAD_MUTEX_ERRORCHECK -#else -#define UMP_PTHREADS_MUTEX_TYPE PTHREAD_MUTEX_DEFAULT -#endif - - if (0 != pthread_mutexattr_settype(&mutex_attributes, UMP_PTHREADS_MUTEX_TYPE)) - { - /** Return NULL on failure */ - pthread_mutexattr_destroy(&mutex_attributes); - return NULL; - - } - -#undef UMP_PTHREADS_MUTEX_TYPE - - /** @opt use containing structures for the ANY_UNLOCK type, to - * save 2 DWORDS when not in use */ - lock = _ump_osu_malloc( sizeof(_ump_osu_lock_t) ); - - if( NULL == lock ) - { - /** Return NULL on failure */ - pthread_mutexattr_destroy(&mutex_attributes); - return NULL; - } - - if (0 != pthread_mutex_init( &lock->mutex, &mutex_attributes )) - { - pthread_mutexattr_destroy(&mutex_attributes); - _ump_osu_free( lock ); - return NULL; - } - - /* done with the mutexattr object */ - pthread_mutexattr_destroy(&mutex_attributes); - - /* ANY_UNLOCK type */ - if ( flags & _UMP_OSU_LOCKFLAG_ANYUNLOCK ) - { - if (0 != pthread_cond_init( &lock->condition, NULL )) - { - /* cleanup */ - pthread_mutex_destroy( &lock->mutex ); - _ump_osu_free( lock ); - return NULL; - } - lock->state = UMP_FALSE; /* mark as unlocked by default */ - } - - lock->flags = flags; - - /** Debug lock checking */ - UMP_DEBUG_CODE( lock->locked_as = _UMP_OSU_LOCKMODE_UNDEF ); - - return lock; -} - -_ump_osu_errcode_t _ump_osu_lock_timed_wait( _ump_osu_lock_t *lock, _ump_osu_lock_mode_t mode, u64 timeout) -{ - /* absolute time specifier */ - struct timespec ts; - struct timeval tv; - - /* Parameter validation */ - UMP_DEBUG_ASSERT_POINTER( lock ); - - UMP_DEBUG_ASSERT( _UMP_OSU_LOCKMODE_RW == mode, - ("unrecognised mode, %.8X\n", mode) ); - UMP_DEBUG_ASSERT( _UMP_OSU_LOCKFLAG_ANYUNLOCK == lock->flags, ("Timed operations only implemented for ANYUNLOCK type locks")); - - /* calculate the realtime timeout value */ - - if (0 != gettimeofday(&tv, NULL)) - { - UMP_DEBUG_PRINT(1,("Could not get the current realtime value to calculate the absolute value for a timed mutex lock with a timeout")); - return _UMP_OSU_ERR_FAULT; - } - - tv.tv_usec += timeout; - -#define UMP_USECS_PER_SECOND 1000000ULL -#define UMP_NANOSECS_PER_USEC 1000ULL - - /* did we overflow a second in the usec part? */ - while (tv.tv_usec >= UMP_USECS_PER_SECOND) - { - tv.tv_usec -= UMP_USECS_PER_SECOND; - tv.tv_sec++; - } - - /* copy to the correct struct */ - ts.tv_sec = tv.tv_sec; - ts.tv_nsec = (tv.tv_usec * UMP_NANOSECS_PER_USEC); - -#undef UMP_USECS_PER_SECOND -#undef UMP_NANOSECS_PER_USEC - - /* lock the mutex protecting access to the state field */ - pthread_mutex_lock( &lock->mutex ); - /* loop while locked (state is UMP_TRUE) */ - /* pthread_cond_timedwait unlocks the mutex, wait, and locks the mutex once unblocked (either due to the event or the timeout) */ - while ( UMP_TRUE == lock->state ) - { - int res; - res = pthread_cond_timedwait( &lock->condition, &lock->mutex, &ts ); - if (0 == res) continue; /* test the state variable again (loop condition) */ - else if (ETIMEDOUT == res) - { - /* timeout, need to clean up and return the correct error code */ - pthread_mutex_unlock(&lock->mutex); - return _UMP_OSU_ERR_TIMEOUT; - } - else - { - UMP_DEBUG_PRINT(1, ("Unexpected return from pthread_cond_timedwait 0x%08X\n", res)); - - pthread_mutex_unlock(&lock->mutex); - return _UMP_OSU_ERR_FAULT; - } - - } - - /* DEBUG tracking of previously locked state - occurs while lock is obtained */ - UMP_DEBUG_ASSERT( _UMP_OSU_LOCKMODE_UNDEF == lock->locked_as, - ("This lock was already locked\n") ); - UMP_DEBUG_CODE( lock->locked_as = mode ); - - /* the state is UMP_FALSE (unlocked), so we set it to UMP_TRUE to indicate that it's locked and can return knowing that we own the lock */ - lock->state = UMP_TRUE; - /* final unlock of the mutex */ - pthread_mutex_unlock(&lock->mutex); - - return _UMP_OSU_ERR_OK; - -} - -_ump_osu_errcode_t _ump_osu_lock_wait( _ump_osu_lock_t *lock, _ump_osu_lock_mode_t mode) -{ - /* Parameter validation */ - UMP_DEBUG_ASSERT_POINTER( lock ); - - UMP_DEBUG_ASSERT( _UMP_OSU_LOCKMODE_RW == mode, - ("unrecognised mode, %.8X\n", mode) ); - - /** @note since only one flag can be set, we use a switch statement here. - * Otherwise, MUST add an enum into the _ump_osu_lock_t to store the - * implemented lock type */ - switch ( lock->flags ) - { - case _UMP_OSU_LOCKFLAG_STATIC: - case 0: - /* Usual Mutex type */ - { - int call_result; - call_result = pthread_mutex_lock( &lock->mutex ); - UMP_DEBUG_ASSERT( 0 == call_result, - ("pthread_mutex_lock call failed with error code %d\n", call_result)); - UMP_IGNORE( call_result ); - } - - /* DEBUG tracking of previously locked state - occurs while lock is obtained */ - UMP_DEBUG_ASSERT( _UMP_OSU_LOCKMODE_UNDEF == lock->locked_as, - ("This lock was already locked\n") ); - UMP_DEBUG_CODE( lock->locked_as = mode ); - break; - - case _UMP_OSU_LOCKFLAG_ANYUNLOCK: - /** @note Use of bitflags in a case statement ONLY works because this - * is the ONLY flag that is supported */ - - /* lock the mutex protecting access to the state field */ - pthread_mutex_lock( &lock->mutex ); - /* loop while locked (state is UMP_TRUE) */ - /* pthread_cond_wait unlocks the mutex, wait, and locks the mutex once unblocked */ - while ( UMP_TRUE == lock->state ) pthread_cond_wait( &lock->condition, &lock->mutex ); - - /* DEBUG tracking of previously locked state - occurs while lock is obtained */ - UMP_DEBUG_ASSERT( _UMP_OSU_LOCKMODE_UNDEF == lock->locked_as, - ("This lock was already locked\n") ); - UMP_DEBUG_CODE( lock->locked_as = mode ); - - /* the state is UMP_FALSE (unlocked), so we set it to UMP_TRUE to indicate that it's locked and can return knowing that we own the lock */ - lock->state = UMP_TRUE; - /* final unlock of the mutex */ - pthread_mutex_unlock(&lock->mutex); - break; - - default: - UMP_DEBUG_ERROR( ("lock has incorrect flags==%.8X\n", lock->flags) ); - break; - } - - return _UMP_OSU_ERR_OK; -} - -_ump_osu_errcode_t _ump_osu_lock_trywait( _ump_osu_lock_t *lock, _ump_osu_lock_mode_t mode) -{ - _ump_osu_errcode_t err = _UMP_OSU_ERR_FAULT; - /* Parameter validation */ - UMP_DEBUG_ASSERT_POINTER( lock ); - - UMP_DEBUG_ASSERT( _UMP_OSU_LOCKMODE_RW == mode, - ("unrecognised mode, %.8X\n", mode) ); - - /** @note since only one flag can be set, we use a switch statement here. - * Otherwise, MUST add an enum into the _ump_osu_lock_t to store the - * implemented lock type */ - switch ( lock->flags ) - { - case _UMP_OSU_LOCKFLAG_STATIC: - case 0: - /* Usual Mutex type */ - { - /* This is not subject to UMP_CHECK - overriding the result would cause a programming error */ - if ( 0 == pthread_mutex_trylock( &lock->mutex ) ) - { - err = _UMP_OSU_ERR_OK; - - /* DEBUG tracking of previously locked state - occurs while lock is obtained */ - UMP_DEBUG_ASSERT( _UMP_OSU_LOCKMODE_UNDEF == lock->locked_as - || mode == lock->locked_as, - ("tried as mode==%.8X, but was locked as %.8X\n", mode, lock->locked_as) ); - UMP_DEBUG_CODE( lock->locked_as = mode ); - } - } - break; - - case _UMP_OSU_LOCKFLAG_ANYUNLOCK: - /** @note Use of bitflags in a case statement ONLY works because this - * is the ONLY flag that is supported */ - - /* lock the mutex protecting access to the state field */ - pthread_mutex_lock(&lock->mutex); - - if ( UMP_FALSE == lock->state) - { - /* unlocked, take the lock */ - lock->state = UMP_TRUE; - err = _UMP_OSU_ERR_OK; - } - - /* DEBUG tracking of previously locked state - occurs while lock is obtained */ - /* Can do this regardless of whether we obtained ANYUNLOCK: */ - - - UMP_DEBUG_ASSERT( _UMP_OSU_LOCKMODE_UNDEF == lock->locked_as - || mode == lock->locked_as, - ("tried as mode==%.8X, but was locked as %.8X\n", mode, lock->locked_as) ); - /* If we were already locked, this does no harm, because of the above assert: */ - UMP_DEBUG_CODE( lock->locked_as = mode ); - - pthread_mutex_unlock(&lock->mutex); - break; - - default: - UMP_DEBUG_ERROR( ("lock has incorrect flags==%.8X\n", lock->flags) ); - break; - } - - return err; -} - - -void _ump_osu_lock_signal( _ump_osu_lock_t *lock, _ump_osu_lock_mode_t mode ) -{ - /* Parameter validation */ - UMP_DEBUG_ASSERT_POINTER( lock ); - - UMP_DEBUG_ASSERT( _UMP_OSU_LOCKMODE_RW == mode, - ("unrecognised mode, %.8X\n", mode) ); - - /** @note since only one flag can be set, we use a switch statement here. - * Otherwise, MUST add an enum into the _ump_osu_lock_t to store the - * implemented lock type */ - switch ( lock->flags ) - { - case _UMP_OSU_LOCKFLAG_STATIC: - case 0: - /* Usual Mutex type */ - - /* DEBUG tracking of previously locked state - occurs while lock is obtained */ - UMP_DEBUG_ASSERT( mode == lock->locked_as, - ("This lock was locked as==%.8X, but tried to unlock as mode==%.8X\n", lock->locked_as, mode)); - UMP_DEBUG_CODE( lock->locked_as = _UMP_OSU_LOCKMODE_UNDEF ); - - { - int call_result; - call_result = pthread_mutex_unlock( &lock->mutex ); - UMP_DEBUG_ASSERT( 0 == call_result, - ("pthread_mutex_lock call failed with error code %d\n", call_result)); - UMP_IGNORE( call_result ); - } - break; - - case _UMP_OSU_LOCKFLAG_ANYUNLOCK: - /** @note Use of bitflags in a case statement ONLY works because this - * is the ONLY flag that is supported */ - - pthread_mutex_lock(&lock->mutex); - UMP_DEBUG_ASSERT( UMP_TRUE == lock->state, ("Unlocking a _ump_osu_lock_t %p which is not locked\n", lock)); - - /* DEBUG tracking of previously locked state - occurs while lock is obtained */ - UMP_DEBUG_ASSERT( mode == lock->locked_as, - ("This lock was locked as==%.8X, but tried to unlock as %.8X\n", lock->locked_as, mode )); - UMP_DEBUG_CODE( lock->locked_as = _UMP_OSU_LOCKMODE_UNDEF ); - - /* mark as unlocked */ - lock->state = UMP_FALSE; - - /* signal the condition, only wake a single thread */ - pthread_cond_signal(&lock->condition); - - pthread_mutex_unlock(&lock->mutex); - break; - - default: - UMP_DEBUG_ERROR( ("lock has incorrect flags==%.8X\n", lock->flags) ); - break; - } -} - -void _ump_osu_lock_term( _ump_osu_lock_t *lock ) -{ - int call_result; - UMP_DEBUG_ASSERT_POINTER( lock ); - - /** Debug lock checking: */ - /* Lock is signalled on terminate - not a guarantee, since we could be locked immediately beforehand */ - UMP_DEBUG_ASSERT( _UMP_OSU_LOCKMODE_UNDEF == lock->locked_as, - ("cannot terminate held lock\n") ); - - call_result = pthread_mutex_destroy( &lock->mutex ); - UMP_DEBUG_ASSERT( 0 == call_result, - ("Incorrect mutex use detected: pthread_mutex_destroy call failed with error code %d\n", call_result) ); - - /* Destroy extra state for ANY_UNLOCK type osu_locks */ - if ( lock->flags & _UMP_OSU_LOCKFLAG_ANYUNLOCK ) - { - UMP_DEBUG_ASSERT( UMP_FALSE == lock->state, ("terminate called on locked object %p\n", lock)); - call_result = pthread_cond_destroy(&lock->condition); - UMP_DEBUG_ASSERT( 0 == call_result, - ("Incorrect condition-variable use detected: pthread_cond_destroy call failed with error code %d\n", call_result) ); - } - - UMP_IGNORE(call_result); - - _ump_osu_free( lock ); -} - -_ump_osu_lock_t *_ump_osu_lock_static( u32 nr ) -{ - UMP_DEBUG_ASSERT( nr < UMP_OSU_STATIC_LOCK_COUNT, - ("provided static lock index (%d) out of bounds (0 < nr < %d)\n", nr, UMP_OSU_STATIC_LOCK_COUNT) ); - return &_ump_osu_static_locks[nr]; -} diff --git a/exynos4/hal/libump/os/linux/ump_osu_memory.c b/exynos4/hal/libump/os/linux/ump_osu_memory.c deleted file mode 100644 index 5807594..0000000 --- a/exynos4/hal/libump/os/linux/ump_osu_memory.c +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (C) 2010-2011 ARM Limited. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include - -#include -#include /* memcmp, memchr, memset */ - -/** - * @file ump_osu_memory.c - * File implements the user side of the OS interface - */ - -void *_ump_osu_calloc( u32 n, u32 size ) -{ - return calloc( n, size ); -} - -void *_ump_osu_malloc( u32 size ) -{ - return malloc( size ); -} - -void *_ump_osu_realloc( void *ptr, u32 size ) -{ - return realloc( ptr, size ); -} - -void _ump_osu_free( void *ptr ) -{ - free( ptr ); -} - -void *_ump_osu_memcpy( void *dst, const void *src, u32 len ) -{ - return memcpy( dst, src, len ); -} - -void *_ump_osu_memset( void *ptr, u32 chr, u32 size ) -{ - return memset( ptr, chr, size ); -} - -int _ump_osu_memcmp( const void *ptr1, const void *ptr2, u32 size ) -{ - return memcmp( ptr1, ptr2, size ); -} diff --git a/exynos4/hal/libump/os/linux/ump_uku.c b/exynos4/hal/libump/os/linux/ump_uku.c deleted file mode 100644 index f46a2c7..0000000 --- a/exynos4/hal/libump/os/linux/ump_uku.c +++ /dev/null @@ -1,193 +0,0 @@ -/* - * Copyright (C) 2010-2011 ARM Limited. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @file ump_uku.c - * File implements the user side of the user-kernel interface - */ - -#include "../ump_uku.h" -#include -#include "ump_ioctl.h" - -#include - -/* Needed for file operations on the device file*/ -#include -#include -#include -#include -#include - -static _ump_osu_errcode_t ump_driver_ioctl(void *context, u32 command, void *args); - -static int ump_ioctl_api_version_used = UMP_IOCTL_API_VERSION; - -/** - * The device file to access the UMP device driver - * This is a character special file giving access to the device driver. - * Usually created using the mknod command line utility. - */ -static const char ump_device_file_name[] = "/dev/ump"; - -_ump_osu_errcode_t _ump_uku_open( void **context ) -{ - int ump_device_file; - if(NULL == context) - { - return _UMP_OSU_ERR_FAULT; - } - - ump_device_file = open(ump_device_file_name, O_RDWR); - - if (-1 == ump_device_file) - { - return _UMP_OSU_ERR_FAULT; - } - - { - struct _ump_uk_api_version_s args; - args.ctx = (void*)ump_device_file; - args.version = UMP_IOCTL_API_VERSION; - args.compatible = 3; - ump_driver_ioctl(args.ctx, UMP_IOC_QUERY_API_VERSION, &args); - if ( 1 != args.compatible ) - { - if (IS_API_MATCH(MAKE_VERSION_ID(1), args.version)) - { - ump_ioctl_api_version_used = MAKE_VERSION_ID(1); - UMP_PRINTF("The UMP devicedriver does not support cached UMP. Update it if this is needed.\n"); - } - else - { - UMP_PRINTF("The UMP devicedriver is version: %d, UMP libraries is version: %d.\n", GET_VERSION(args.version), GET_VERSION(UMP_IOCTL_API_VERSION) ); - close(ump_device_file); - return _UMP_OSU_ERR_FAULT; - } - } - } - - *context = (void *) ump_device_file; - return _UMP_OSU_ERR_OK; -} - -_ump_osu_errcode_t _ump_uku_close( void **context ) -{ - if(NULL == context) - { - return _UMP_OSU_ERR_FAULT; - } - - if(-1 == (int)*context) - { - return _UMP_OSU_ERR_FAULT; - } - - close((int)*context); - *context = (void *)-1; - - return _UMP_OSU_ERR_OK; -} - -int _ump_uku_allocate(_ump_uk_allocate_s *args) -{ - return ump_driver_ioctl(args->ctx, UMP_IOC_ALLOCATE, args); -} - -_ump_osu_errcode_t _ump_uku_release(_ump_uk_release_s *args) -{ - return ump_driver_ioctl(args->ctx, UMP_IOC_RELEASE, args); -} - -_ump_osu_errcode_t _ump_uku_size_get(_ump_uk_size_get_s *args) -{ - return ump_driver_ioctl(args->ctx, UMP_IOC_SIZE_GET, args); -} - - -void _ump_uku_msynch(_ump_uk_msync_s *args) -{ - /* This is for backwards compatibillity */ - if ( MAKE_VERSION_ID(1) == ump_ioctl_api_version_used) - { - args->is_cached = 0; - if ( _UMP_UK_MSYNC_READOUT_CACHE_ENABLED != args->op ) - { - UMP_DEBUG_PRINT(3, ("Warning: Doing UMP cache flush operations on a Device Driver that does not support cached UMP mem.\n")); - } - return; - } - ump_driver_ioctl(args->ctx, UMP_IOC_MSYNC, args); -} - -int _ump_uku_map_mem(_ump_uk_map_mem_s *args) -{ - int flags; - if( -1 == (int)args->ctx ) - { - return -1; - } - - flags = MAP_SHARED; - - /* This is for backwards compatibillity */ - if ( MAKE_VERSION_ID(1) == ump_ioctl_api_version_used) - { - args->is_cached = 0; - } - - /* If we want the Caching to be enabled we set the flags to be PRIVATE. The UMP DD reads this and do proper handling - Note: this enforces the user to use proper invalidation*/ - if ( args->is_cached ) flags = MAP_PRIVATE; - - args->mapping = mmap(NULL, args->size, PROT_READ | PROT_WRITE ,flags , (int)args->ctx, (off_t)args->secure_id * sysconf(_SC_PAGE_SIZE)); - if (MAP_FAILED == args->mapping) - { - return -1; - } - - args->cookie = 0; /* Cookie is not used in linux _ump_uku_unmap_mem */ - - return 0; -} - -void _ump_uku_unmap_mem( _ump_uk_unmap_mem_s *args ) -{ - /* - * If a smaller size is used Linux will just remove the requested range but don't tell - * the ump driver before all of it is unmapped, either via another unmap request or upon process shutdown. - * Unmapping too much will just ignore the overhead or hit undefined behavior, - * only affecting the calling process which could mess itself up in other ways anyway. - * So we don't need any security checks here. - */ - munmap(args->mapping, args->size); -} - -static _ump_osu_errcode_t ump_driver_ioctl(void *context, u32 command, void *args) -{ - /*UMP_CHECK_NON_NULL(args, _UMP_OSK_ERR_INVALID_ARGS);*/ - - /* check for a valid file descriptor */ - /** @note manual type safety check-point */ - if( -1 == (int)context ) - { - return _UMP_OSU_ERR_FAULT; - } - - /* call ioctl handler of driver */ - if (0 != ioctl((int)context, command, args)) return -1; - return _UMP_OSU_ERR_OK; -} diff --git a/exynos4/hal/libump/os/ump_uku.h b/exynos4/hal/libump/os/ump_uku.h deleted file mode 100644 index 7da7185..0000000 --- a/exynos4/hal/libump/os/ump_uku.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (C) 2010-2011 ARM Limited. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @file ump_uku.h - * Defines the user-side interface of the user-kernel interface - */ - -#ifndef __UMP_UKU_H__ -#define __UMP_UKU_H__ - -#include -#include -#include - -#ifdef __cplusplus -extern "C" -{ -#endif - -_ump_osu_errcode_t _ump_uku_open( void **context ); - -_ump_osu_errcode_t _ump_uku_close( void **context ); - -_ump_osu_errcode_t _ump_uku_allocate( _ump_uk_allocate_s *args ); - -_ump_osu_errcode_t _ump_uku_release( _ump_uk_release_s *args ); - -_ump_osu_errcode_t _ump_uku_size_get( _ump_uk_size_get_s *args ); - -_ump_osu_errcode_t _ump_uku_get_api_version( _ump_uk_api_version_s *args ); - -int _ump_uku_map_mem( _ump_uk_map_mem_s *args ); - -void _ump_uku_unmap_mem( _ump_uk_unmap_mem_s *args ); - -void _ump_uku_msynch(_ump_uk_msync_s *args); - -#ifdef __cplusplus -} -#endif - -#endif /* __UMP_UKU_H__ */ diff --git a/exynos4/hal/libump/readme.txt b/exynos4/hal/libump/readme.txt deleted file mode 100644 index 297df38..0000000 --- a/exynos4/hal/libump/readme.txt +++ /dev/null @@ -1,31 +0,0 @@ -# -# Copyright (C) 2010-2011 ARM Limited. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -Building the UMP user space library for Linux ---------------------------------------------- - -A simple Makefile is provided, and the UMP user space library can be built -simply by issuing make. This Makefile is setup to use the ARM GCC compiler -from CodeSourcery, and it builds for ARMv6. Modification to this Makefile -is needed in order to build for other configurations. - -In order to use this library from the Mali GPU driver, invoke the Mali GPU -driver build system with the following two make variables set; -- UMP_INCLUDE_DIR should point to the include folder inside this package -- UMP_LIB should point to the built library (libUMP.so) - -This does not apply to Android builds, where the Android.mk file for the -Mali GPU driver needs to be manually edited in order to add the correct -include path and link against the correct library. diff --git a/exynos4/multimedia/libs/Android.mk b/exynos4/multimedia/libs/Android.mk deleted file mode 100644 index 55ca333..0000000 --- a/exynos4/multimedia/libs/Android.mk +++ /dev/null @@ -1 +0,0 @@ -include $(all-subdir-makefiles) \ No newline at end of file diff --git a/exynos4/multimedia/libs/libcsc/Android.mk b/exynos4/multimedia/libs/libcsc/Android.mk deleted file mode 100644 index 6f3f753..0000000 --- a/exynos4/multimedia/libs/libcsc/Android.mk +++ /dev/null @@ -1,64 +0,0 @@ -LOCAL_PATH := $(call my-dir) - -include $(CLEAR_VARS) - -LOCAL_COPY_HEADERS_TO := libsecmm -LOCAL_COPY_HEADERS := \ - csc.h - -LOCAL_MODULE_TAGS := optional - -LOCAL_SRC_FILES := \ - csc.c - -ifeq ($(BOARD_USE_EXYNOS_OMX), true) -OMX_NAME := exynos -else -OMX_NAME := sec -endif - -LOCAL_C_INCLUDES := \ - $(TOP)/$(BOARD_HMM_PATH)/openmax/$(OMX_NAME)_omx/include/khronos \ - $(TOP)/$(BOARD_HMM_PATH)/openmax/$(OMX_NAME)_omx/include/$(OMX_NAME) - -LOCAL_CFLAGS := - -LOCAL_MODULE := libcsc - -LOCAL_PRELINK_MODULE := false - -LOCAL_ARM_MODE := arm - -LOCAL_STATIC_LIBRARIES := libswconverter -LOCAL_SHARED_LIBRARIES := liblog - -ifeq ($(BOARD_USE_SAMSUNG_COLORFORMAT), true) -LOCAL_CFLAGS += -DUSE_SAMSUNG_COLORFORMAT -endif - -ifeq ($(TARGET_BOARD_PLATFORM), exynos4) -LOCAL_SRC_FILES += hwconverter_wrapper.cpp -LOCAL_C_INCLUDES += $(TOP)/$(BOARD_HMM_PATH)/utils/csc/exynos4 \ - $(TOP)/$(BOARD_HAL_PATH)/include \ - $(TOP)/$(BOARD_HAL_PATH)/libhwconverter -LOCAL_CFLAGS += -DUSE_FIMC -LOCAL_SHARED_LIBRARIES += libfimc libhwconverter -endif - -ifeq ($(TARGET_BOARD_PLATFORM), exynos5) -LOCAL_C_INCLUDES += $(TOP)/$(BOARD_HMM_PATH)/utils/csc/exynos5 \ - $(TOP)/device/samsung/exynos5/include -LOCAL_CFLAGS += -DUSE_GSCALER -LOCAL_SHARED_LIBRARIES += libexynosgscaler -endif - -ifeq ($(BOARD_USE_V4L2_ION),true) -LOCAL_CFLAGS += -DUSE_ION -LOCAL_SHARED_LIBRARIES += libion -endif - -ifeq ($(BOARD_USE_EXYNOS_OMX), true) -LOCAL_CFLAGS += -DEXYNOS_OMX -endif - -include $(BUILD_SHARED_LIBRARY) diff --git a/exynos4/multimedia/libs/libcsc/csc.c b/exynos4/multimedia/libs/libcsc/csc.c deleted file mode 100644 index 19bd203..0000000 --- a/exynos4/multimedia/libs/libcsc/csc.c +++ /dev/null @@ -1,740 +0,0 @@ -/* - * - * Copyright 2012 Samsung Electronics S.LSI Co. LTD - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* - * @file csc.c - * - * @brief color space convertion abstract source - * - * @author Pyoungjae Jung(pjet.jung@samsung.com) - * - * @version 1.0.0 - * - * @history - * 2012.1.11 : Create - */ -#define LOG_TAG "libcsc" -#include - -#include -#include -#include - -#include "csc.h" -#include "sec_format.h" -#include "sec_utils_v4l2.h" -#include "swconverter.h" - -#ifdef EXYNOS_OMX -#include "Exynos_OMX_Def.h" -#else -#include "SEC_OMX_Def.h" -#endif - -#ifdef USE_FIMC -#include "hwconverter_wrapper.h" -#endif - -#ifdef USE_GSCALER -#include "exynos_gscaler.h" -#endif - -#define GSCALER_IMG_ALIGN 16 -#define CSC_MAX_PLANES 3 -#define ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1)) - -typedef enum _CSC_PLANE { - CSC_Y_PLANE = 0, - CSC_RGB_PLANE = 0, - CSC_U_PLANE = 1, - CSC_UV_PLANE = 1, - CSC_V_PLANE = 2 -} CSC_PLANE; - -typedef enum _CSC_HW_TYPE { - CSC_HW_TYPE_FIMC = 0, - CSC_HW_TYPE_GSCALER -} CSC_HW_TYPE; - -typedef struct _CSC_FORMAT { - unsigned int width; - unsigned int height; - unsigned int crop_left; - unsigned int crop_top; - unsigned int crop_width; - unsigned int crop_height; - unsigned int color_format; - unsigned int cacheable; -} CSC_FORMAT; - -typedef struct _CSC_BUFFER { - unsigned char *planes[CSC_MAX_PLANES]; - int ion_fd; -} CSC_BUFFER; - -typedef struct _CSC_HANDLE { - CSC_FORMAT dst_format; - CSC_FORMAT src_format; - CSC_BUFFER dst_buffer; - CSC_BUFFER src_buffer; - CSC_METHOD csc_method; - CSC_HW_TYPE csc_hw_type; - void *csc_hw_handle; -} CSC_HANDLE; - -OMX_COLOR_FORMATTYPE hal_2_omx_pixel_format( - unsigned int hal_format) -{ - OMX_COLOR_FORMATTYPE omx_format; - switch (hal_format) { - case HAL_PIXEL_FORMAT_YCbCr_420_P: - omx_format = OMX_COLOR_FormatYUV420Planar; - break; - case HAL_PIXEL_FORMAT_YCbCr_420_SP: - omx_format = OMX_COLOR_FormatYUV420SemiPlanar; - break; - case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED: - omx_format = OMX_SEC_COLOR_FormatNV12Tiled; - break; - case HAL_PIXEL_FORMAT_ARGB888: - omx_format = OMX_COLOR_Format32bitARGB8888; - break; - default: - omx_format = OMX_COLOR_FormatYUV420Planar; - break; - } - return omx_format; -} - -unsigned int omx_2_hal_pixel_format( - OMX_COLOR_FORMATTYPE omx_format) -{ - unsigned int hal_format; - switch (omx_format) { - case OMX_COLOR_FormatYUV420Planar: - hal_format = HAL_PIXEL_FORMAT_YCbCr_420_P; - break; - case OMX_COLOR_FormatYUV420SemiPlanar: - hal_format = HAL_PIXEL_FORMAT_YCbCr_420_SP; - break; - case OMX_SEC_COLOR_FormatNV12Tiled: - hal_format = HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED; - break; - case OMX_COLOR_Format32bitARGB8888: - hal_format = HAL_PIXEL_FORMAT_ARGB888; - break; - default: - hal_format = HAL_PIXEL_FORMAT_YCbCr_420_P; - break; - } - return hal_format; -} - -/* source is RGB888 */ -static CSC_ERRORCODE conv_sw_src_argb888( - CSC_HANDLE *handle) -{ - CSC_ERRORCODE ret = CSC_ErrorNone; - - switch (handle->dst_format.color_format) { - case HAL_PIXEL_FORMAT_YCbCr_420_P: - csc_ARGB8888_to_YUV420P( - (unsigned char *)handle->dst_buffer.planes[CSC_Y_PLANE], - (unsigned char *)handle->dst_buffer.planes[CSC_U_PLANE], - (unsigned char *)handle->dst_buffer.planes[CSC_V_PLANE], - (unsigned char *)handle->src_buffer.planes[CSC_RGB_PLANE], - handle->src_format.width, - handle->src_format.height); - ret = CSC_ErrorNone; - break; - case HAL_PIXEL_FORMAT_YCbCr_420_SP: - csc_ARGB8888_to_YUV420SP( - (unsigned char *)handle->dst_buffer.planes[CSC_Y_PLANE], - (unsigned char *)handle->dst_buffer.planes[CSC_UV_PLANE], - (unsigned char *)handle->src_buffer.planes[CSC_RGB_PLANE], - handle->src_format.width, - handle->src_format.height); - ret = CSC_ErrorNone; - break; - default: - ret = CSC_ErrorUnsupportFormat; - break; - } - - return ret; -} - -/* source is NV12T */ -static CSC_ERRORCODE conv_sw_src_nv12t( - CSC_HANDLE *handle) -{ - CSC_ERRORCODE ret = CSC_ErrorNone; - - switch (handle->dst_format.color_format) { - case HAL_PIXEL_FORMAT_YCbCr_420_P: - csc_tiled_to_linear_y_neon( - (unsigned char *)handle->dst_buffer.planes[CSC_Y_PLANE], - (unsigned char *)handle->src_buffer.planes[CSC_Y_PLANE], - handle->src_format.width, - handle->src_format.height); - csc_tiled_to_linear_uv_deinterleave_neon( - (unsigned char *)handle->dst_buffer.planes[CSC_U_PLANE], - (unsigned char *)handle->dst_buffer.planes[CSC_V_PLANE], - (unsigned char *)handle->src_buffer.planes[CSC_UV_PLANE], - handle->src_format.width, - handle->src_format.height / 2); - ret = CSC_ErrorNone; - break; - case HAL_PIXEL_FORMAT_YCbCr_420_SP: - csc_tiled_to_linear_y_neon( - (unsigned char *)handle->dst_buffer.planes[CSC_Y_PLANE], - (unsigned char *)handle->src_buffer.planes[CSC_Y_PLANE], - handle->src_format.width, - handle->src_format.height); - csc_tiled_to_linear_uv_neon( - (unsigned char *)handle->dst_buffer.planes[CSC_UV_PLANE], - (unsigned char *)handle->src_buffer.planes[CSC_UV_PLANE], - handle->src_format.width, - handle->src_format.height / 2); - ret = CSC_ErrorNone; - break; - default: - ret = CSC_ErrorUnsupportFormat; - break; - } - - return ret; -} - -/* source is YUV420P */ -static CSC_ERRORCODE conv_sw_src_yuv420p( - CSC_HANDLE *handle) -{ - CSC_ERRORCODE ret = CSC_ErrorNone; - - switch (handle->dst_format.color_format) { - case HAL_PIXEL_FORMAT_YCbCr_420_P: /* bypass */ - memcpy((unsigned char *)handle->dst_buffer.planes[CSC_Y_PLANE], - (unsigned char *)handle->src_buffer.planes[CSC_Y_PLANE], - handle->src_format.width * handle->src_format.height); - memcpy((unsigned char *)handle->dst_buffer.planes[CSC_U_PLANE], - (unsigned char *)handle->src_buffer.planes[CSC_U_PLANE], - (handle->src_format.width * handle->src_format.height) >> 2); - memcpy((unsigned char *)handle->dst_buffer.planes[CSC_V_PLANE], - (unsigned char *)handle->src_buffer.planes[CSC_V_PLANE], - (handle->src_format.width * handle->src_format.height) >> 2); - ret = CSC_ErrorNone; - break; - case HAL_PIXEL_FORMAT_YCbCr_420_SP: - memcpy((unsigned char *)handle->dst_buffer.planes[CSC_Y_PLANE], - (unsigned char *)handle->src_buffer.planes[CSC_Y_PLANE], - handle->src_format.width * handle->src_format.height); - csc_interleave_memcpy_neon( - (unsigned char *)handle->dst_buffer.planes[CSC_UV_PLANE], - (unsigned char *)handle->src_buffer.planes[CSC_U_PLANE], - (unsigned char *)handle->src_buffer.planes[CSC_V_PLANE], - (handle->src_format.width * handle->src_format.height) >> 2); - ret = CSC_ErrorNone; - break; - default: - ret = CSC_ErrorUnsupportFormat; - break; - } - - return ret; -} - -/* source is YUV420SP */ -static CSC_ERRORCODE conv_sw_src_yuv420sp( - CSC_HANDLE *handle) -{ - CSC_ERRORCODE ret = CSC_ErrorNone; - - switch (handle->dst_format.color_format) { - case HAL_PIXEL_FORMAT_YCbCr_420_P: - memcpy((unsigned char *)handle->dst_buffer.planes[CSC_Y_PLANE], - (unsigned char *)handle->src_buffer.planes[CSC_Y_PLANE], - handle->src_format.width * handle->src_format.height); - csc_deinterleave_memcpy( - (unsigned char *)handle->dst_buffer.planes[CSC_U_PLANE], - (unsigned char *)handle->dst_buffer.planes[CSC_V_PLANE], - (unsigned char *)handle->src_buffer.planes[CSC_UV_PLANE], - handle->src_format.width * handle->src_format.height >> 1); - ret = CSC_ErrorNone; - break; - case HAL_PIXEL_FORMAT_YCbCr_420_SP: /* bypass */ - memcpy((unsigned char *)handle->dst_buffer.planes[CSC_Y_PLANE], - (unsigned char *)handle->src_buffer.planes[CSC_Y_PLANE], - handle->src_format.width * handle->src_format.height); - memcpy((unsigned char *)handle->dst_buffer.planes[CSC_UV_PLANE], - (unsigned char *)handle->src_buffer.planes[CSC_UV_PLANE], - handle->src_format.width * handle->src_format.height >> 1); - ret = CSC_ErrorNone; - break; - default: - ret = CSC_ErrorUnsupportFormat; - break; - } - - return ret; -} - -static CSC_ERRORCODE conv_sw( - CSC_HANDLE *handle) -{ - CSC_ERRORCODE ret = CSC_ErrorNone; - - switch (handle->src_format.color_format) { - case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED: - ret = conv_sw_src_nv12t(handle); - break; - case HAL_PIXEL_FORMAT_YCbCr_420_P: - ret = conv_sw_src_yuv420p(handle); - break; - case HAL_PIXEL_FORMAT_YCbCr_420_SP: - ret = conv_sw_src_yuv420sp(handle); - break; - case HAL_PIXEL_FORMAT_ARGB888: - ret = conv_sw_src_argb888(handle); - break; - default: - ret = CSC_ErrorUnsupportFormat; - break; - } - - return ret; -} - -static CSC_ERRORCODE conv_hw( - CSC_HANDLE *handle) -{ - CSC_ERRORCODE ret = CSC_ErrorNone; - - switch (handle->csc_hw_type) { -#ifdef USE_FIMC - case CSC_HW_TYPE_FIMC: - { - void *src_addr[3]; - void *dst_addr[3]; - OMX_COLOR_FORMATTYPE omx_format; - src_addr[0] = handle->src_buffer.planes[CSC_Y_PLANE]; - src_addr[1] = handle->src_buffer.planes[CSC_UV_PLANE]; - dst_addr[0] = handle->dst_buffer.planes[CSC_Y_PLANE]; - dst_addr[1] = handle->dst_buffer.planes[CSC_U_PLANE]; - dst_addr[2] = handle->dst_buffer.planes[CSC_V_PLANE]; - omx_format = hal_2_omx_pixel_format(handle->dst_format.color_format); - csc_hwconverter_convert_nv12t( - handle->csc_hw_handle, - dst_addr, - src_addr, - handle->dst_format.width, - handle->dst_format.height, - omx_format); - break; - } -#endif -#ifdef USE_GSCALER - case CSC_HW_TYPE_GSCALER: - exynos_gsc_convert(handle->csc_hw_handle); - break; -#endif - default: - LOGE("%s:: unsupported csc_hw_type", __func__); - break; - } - - return CSC_ErrorNotImplemented; -} - -void *csc_init( - CSC_METHOD *method) -{ - CSC_HANDLE *csc_handle; - csc_handle = (CSC_HANDLE *)malloc(sizeof(CSC_HANDLE)); - if (csc_handle == NULL) - return NULL; - - memset(csc_handle, 0, sizeof(CSC_HANDLE)); - - csc_handle->csc_method = *method; - - if (csc_handle->csc_method == CSC_METHOD_HW || - csc_handle->csc_method == CSC_METHOD_PREFER_HW) { -#ifdef USE_FIMC - csc_handle->csc_hw_type = CSC_HW_TYPE_FIMC; -#endif -#ifdef USE_GSCALER - csc_handle->csc_hw_type = CSC_HW_TYPE_GSCALER; -#endif - switch (csc_handle->csc_hw_type) { -#ifdef USE_FIMC - case CSC_HW_TYPE_FIMC: - csc_handle->csc_hw_handle = csc_hwconverter_open(); - LOGD("%s:: CSC_HW_TYPE_FIMC", __func__); - break; -#endif -#ifdef USE_GSCALER - case CSC_HW_TYPE_GSCALER: - csc_handle->csc_hw_handle = exynos_gsc_create(); - LOGD("%s:: CSC_HW_TYPE_GSCALER", __func__); - break; -#endif - default: - LOGE("%s:: unsupported csc_hw_type, csc use sw", __func__); - csc_handle->csc_hw_handle == NULL; - break; - } - } - - if (csc_handle->csc_method == CSC_METHOD_PREFER_HW) { - if (csc_handle->csc_hw_handle == NULL) { - csc_handle->csc_method = CSC_METHOD_SW; - *method = CSC_METHOD_SW; - } else { - csc_handle->csc_method = CSC_METHOD_HW; - *method = CSC_METHOD_HW; - } - } - - if (csc_handle->csc_method == CSC_METHOD_HW) { - if (csc_handle->csc_hw_handle == NULL) { - LOGE("%s:: CSC_METHOD_HW can't open HW", __func__); - free(csc_handle); - csc_handle = NULL; - } - } - - LOGD("%s:: CSC_METHOD=%d", __func__, csc_handle->csc_method); - - return (void *)csc_handle; -} - -CSC_ERRORCODE csc_deinit( - void *handle) -{ - CSC_ERRORCODE ret = CSC_ErrorNone; - CSC_HANDLE *csc_handle; - - csc_handle = (CSC_HANDLE *)handle; - if (csc_handle->csc_method == CSC_METHOD_HW) { - switch (csc_handle->csc_hw_type) { -#ifdef USE_FIMC - case CSC_HW_TYPE_FIMC: - csc_hwconverter_close(csc_handle->csc_hw_handle); - break; -#endif -#ifdef USE_GSCALER - case CSC_HW_TYPE_GSCALER: - exynos_gsc_destroy(csc_handle->csc_hw_handle); - break; -#endif - default: - LOGE("%s:: unsupported csc_hw_type", __func__); - break; - } - } - - if (csc_handle != NULL) { - free(csc_handle); - ret = CSC_ErrorNone; - } - - return ret; -} - -CSC_ERRORCODE csc_get_method( - void *handle, - CSC_METHOD *method) -{ - CSC_HANDLE *csc_handle; - CSC_ERRORCODE ret = CSC_ErrorNone; - - if (handle == NULL) - return CSC_ErrorNotInit; - - csc_handle = (CSC_HANDLE *)handle; - *method = csc_handle->csc_method; - - return ret; -} - -CSC_ERRORCODE csc_get_src_format( - void *handle, - unsigned int *width, - unsigned int *height, - unsigned int *crop_left, - unsigned int *crop_top, - unsigned int *crop_width, - unsigned int *crop_height, - unsigned int *color_format, - unsigned int *cacheable) -{ - CSC_HANDLE *csc_handle; - CSC_ERRORCODE ret = CSC_ErrorNone; - - if (handle == NULL) - return CSC_ErrorNotInit; - - csc_handle = (CSC_HANDLE *)handle; - *width = csc_handle->src_format.width; - *height = csc_handle->src_format.height; - *crop_left = csc_handle->src_format.crop_left; - *crop_top = csc_handle->src_format.crop_top; - *crop_width = csc_handle->src_format.crop_width; - *crop_height = csc_handle->src_format.crop_height; - *color_format = csc_handle->src_format.color_format; - *cacheable = csc_handle->src_format.cacheable; - - return ret; -} - -CSC_ERRORCODE csc_set_src_format( - void *handle, - unsigned int width, - unsigned int height, - unsigned int crop_left, - unsigned int crop_top, - unsigned int crop_width, - unsigned int crop_height, - unsigned int color_format, - unsigned int cacheable) -{ - CSC_HANDLE *csc_handle; - CSC_ERRORCODE ret = CSC_ErrorNone; - - if (handle == NULL) - return CSC_ErrorNotInit; - - csc_handle = (CSC_HANDLE *)handle; - csc_handle->src_format.width = width; - csc_handle->src_format.height = height; - csc_handle->src_format.crop_left = crop_left; - csc_handle->src_format.crop_top = crop_top; - csc_handle->src_format.crop_width = crop_width; - csc_handle->src_format.crop_height = crop_height; - csc_handle->src_format.color_format = color_format; - csc_handle->src_format.cacheable = cacheable; - - if (csc_handle->csc_method == CSC_METHOD_HW) { - switch (csc_handle->csc_hw_type) { - case CSC_HW_TYPE_FIMC: - break; -#ifdef USE_GSCALER - case CSC_HW_TYPE_GSCALER: - exynos_gsc_set_src_format( - csc_handle->csc_hw_handle, - ALIGN(csc_handle->src_format.width, GSCALER_IMG_ALIGN), - ALIGN(csc_handle->src_format.height, GSCALER_IMG_ALIGN), - csc_handle->src_format.crop_left, - csc_handle->src_format.crop_top, - ALIGN(csc_handle->src_format.crop_width, GSCALER_IMG_ALIGN), - ALIGN(csc_handle->src_format.crop_height, GSCALER_IMG_ALIGN), - HAL_PIXEL_FORMAT_2_V4L2_PIX(csc_handle->src_format.color_format), - csc_handle->src_format.cacheable); - break; -#endif - default: - LOGE("%s:: unsupported csc_hw_type", __func__); - break; - } - } - - return ret; -} - -CSC_ERRORCODE csc_get_dst_format( - void *handle, - unsigned int *width, - unsigned int *height, - unsigned int *crop_left, - unsigned int *crop_top, - unsigned int *crop_width, - unsigned int *crop_height, - unsigned int *color_format, - unsigned int *cacheable) -{ - CSC_HANDLE *csc_handle; - CSC_ERRORCODE ret = CSC_ErrorNone; - - if (handle == NULL) - return CSC_ErrorNotInit; - - csc_handle = (CSC_HANDLE *)handle; - *width = csc_handle->dst_format.width; - *height = csc_handle->dst_format.height; - *crop_left = csc_handle->dst_format.crop_left; - *crop_top = csc_handle->dst_format.crop_top; - *crop_width = csc_handle->dst_format.crop_width; - *crop_height = csc_handle->dst_format.crop_height; - *color_format = csc_handle->dst_format.color_format; - *cacheable = csc_handle->dst_format.cacheable; - - return ret; -} - -CSC_ERRORCODE csc_set_dst_format( - void *handle, - unsigned int width, - unsigned int height, - unsigned int crop_left, - unsigned int crop_top, - unsigned int crop_width, - unsigned int crop_height, - unsigned int color_format, - unsigned int cacheable) -{ - CSC_HANDLE *csc_handle; - CSC_ERRORCODE ret = CSC_ErrorNone; - - if (handle == NULL) - return CSC_ErrorNotInit; - - csc_handle = (CSC_HANDLE *)handle; - csc_handle->dst_format.width = width; - csc_handle->dst_format.height = height; - csc_handle->dst_format.crop_left = crop_left; - csc_handle->dst_format.crop_top = crop_top; - csc_handle->dst_format.crop_width = crop_width; - csc_handle->dst_format.crop_height = crop_height; - csc_handle->dst_format.color_format = color_format; - csc_handle->dst_format.cacheable = cacheable; - - if (csc_handle->csc_method == CSC_METHOD_HW) { - switch (csc_handle->csc_hw_type) { - case CSC_HW_TYPE_FIMC: - break; -#ifdef USE_GSCALER - case CSC_HW_TYPE_GSCALER: - exynos_gsc_set_dst_format( - csc_handle->csc_hw_handle, - ALIGN(csc_handle->dst_format.width, GSCALER_IMG_ALIGN), - ALIGN(csc_handle->dst_format.height, GSCALER_IMG_ALIGN), - csc_handle->dst_format.crop_left, - csc_handle->dst_format.crop_top, - ALIGN(csc_handle->dst_format.crop_width, GSCALER_IMG_ALIGN), - ALIGN(csc_handle->dst_format.crop_height, GSCALER_IMG_ALIGN), - HAL_PIXEL_FORMAT_2_V4L2_PIX(csc_handle->dst_format.color_format), - csc_handle->dst_format.cacheable); - break; -#endif - default: - LOGE("%s:: unsupported csc_hw_type", __func__); - break; - } - } - - return ret; -} - -CSC_ERRORCODE csc_set_src_buffer( - void *handle, - unsigned char *y, - unsigned char *u, - unsigned char *v, - int ion_fd) -{ - CSC_HANDLE *csc_handle; - CSC_ERRORCODE ret = CSC_ErrorNone; - void *addr[3] = {NULL, }; - - if (handle == NULL) - return CSC_ErrorNotInit; - - csc_handle = (CSC_HANDLE *)handle; - csc_handle->src_buffer.planes[CSC_Y_PLANE] = y; - csc_handle->src_buffer.planes[CSC_U_PLANE] = u; - csc_handle->src_buffer.planes[CSC_V_PLANE] = v; - - if (csc_handle->csc_method == CSC_METHOD_HW) { - addr[0] = csc_handle->src_buffer.planes[CSC_Y_PLANE]; - addr[1] = csc_handle->src_buffer.planes[CSC_U_PLANE]; - addr[2] = csc_handle->src_buffer.planes[CSC_V_PLANE]; - - switch (csc_handle->csc_hw_type) { - case CSC_HW_TYPE_FIMC: - break; -#ifdef USE_GSCALER - case CSC_HW_TYPE_GSCALER: - exynos_gsc_set_src_addr(csc_handle->csc_hw_handle, addr); - break; -#endif - default: - LOGE("%s:: unsupported csc_hw_type", __func__); - break; - } - } - - return ret; -} - -CSC_ERRORCODE csc_set_dst_buffer( - void *handle, - unsigned char *y, - unsigned char *u, - unsigned char *v, - int ion_fd) -{ - CSC_HANDLE *csc_handle; - CSC_ERRORCODE ret = CSC_ErrorNone; - void *addr[3] = {NULL, }; - - if (handle == NULL) - return CSC_ErrorNotInit; - - csc_handle = (CSC_HANDLE *)handle; - csc_handle->dst_buffer.planes[CSC_Y_PLANE] = y; - csc_handle->dst_buffer.planes[CSC_U_PLANE] = u; - csc_handle->dst_buffer.planes[CSC_V_PLANE] = v; - - if (csc_handle->csc_method == CSC_METHOD_HW) { - addr[0] = csc_handle->dst_buffer.planes[CSC_Y_PLANE]; - addr[1] = csc_handle->dst_buffer.planes[CSC_U_PLANE]; - addr[2] = csc_handle->dst_buffer.planes[CSC_V_PLANE]; - - switch (csc_handle->csc_hw_type) { - case CSC_HW_TYPE_FIMC: - break; -#ifdef USE_GSCALER - case CSC_HW_TYPE_GSCALER: - exynos_gsc_set_dst_addr(csc_handle->csc_hw_handle, addr); - break; -#endif - default: - LOGE("%s:: unsupported csc_hw_type", __func__); - break; - } - } - - return ret; -} - -CSC_ERRORCODE csc_convert( - void *handle) -{ - CSC_HANDLE *csc_handle = (CSC_HANDLE *)handle; - CSC_ERRORCODE ret = CSC_ErrorNone; - - if (csc_handle == NULL) - return CSC_ErrorNotInit; - - if (csc_handle->csc_method == CSC_METHOD_HW) - ret = conv_hw(csc_handle); - else - ret = conv_sw(csc_handle); - - return ret; -} diff --git a/exynos4/multimedia/libs/libcsc/csc.h b/exynos4/multimedia/libs/libcsc/csc.h deleted file mode 100644 index 9069392..0000000 --- a/exynos4/multimedia/libs/libcsc/csc.h +++ /dev/null @@ -1,355 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* - * @file csc.h - * - * @brief color space convertion abstract header - * - * @author Pyoungjae Jung (pjet.jung@samsung.com) - * - * @version 1.0 - * - * @history - * 2011.12.27 : Create - */ - -#ifndef CSC_H -#define CSC_H - -#ifdef __cplusplus -extern "C" { -#endif - -typedef enum _CSC_ERRORCODE { - CSC_ErrorNone = 0, - CSC_Error, - CSC_ErrorNotInit, - CSC_ErrorInvalidAddress, - CSC_ErrorUnsupportFormat, - CSC_ErrorNotImplemented -} CSC_ERRORCODE; - -typedef enum _CSC_METHOD { - CSC_METHOD_SW = 0, - CSC_METHOD_HW, - CSC_METHOD_PREFER_HW -} CSC_METHOD; - -/* - * change hal pixel format to omx pixel format - * - * @param hal_format - * hal pixel format[in] - * - * @return - * omx pixel format - */ -unsigned int hal_2_omx_pixel_format( - unsigned int hal_format); - -/* - * change omx pixel format to hal pixel format - * - * @param hal_format - * omx pixel format[in] - * - * @return - * hal pixel format - */ -unsigned int omx_2_hal_pixel_format( - unsigned int omx_format); - -/* - * Init CSC handle - * - * @return - * csc handle - */ -void *csc_init( - CSC_METHOD *method); - -/* - * Deinit CSC handle - * - * @param handle - * CSC handle[in] - * - * @return - * error code - */ -CSC_ERRORCODE csc_deinit( - void *handle); - -/* - * get color space converter method - * - * @param handle - * CSC handle[in] - * - * @param method - * CSC method[out] - * - * @return - * error code - */ -CSC_ERRORCODE csc_get_method( - void *handle, - CSC_METHOD *method); - -/* - * Get source format. - * - * @param handle - * CSC handle[in] - * - * @param width - * address of image width[out] - * - * @param height - * address of image height[out] - * - * @param crop_left - * address of image left crop size[out] - * - * @param crop_top - * address of image top crop size[out] - * - * @param crop_width - * address of cropped image width[out] - * - * @param crop_height - * address of cropped image height[out] - * - * @param color_format - * address of source color format(HAL format)[out] - * - * @return - * error code - */ -CSC_ERRORCODE csc_get_src_format( - void *handle, - unsigned int *width, - unsigned int *height, - unsigned int *crop_left, - unsigned int *crop_top, - unsigned int *crop_width, - unsigned int *crop_height, - unsigned int *color_format, - unsigned int *cacheable); - -/* - * Set source format. - * Don't call each converting time. - * Pls call this function as below. - * 1. first converting time - * 2. format is changed - * - * @param handle - * CSC handle[in] - * - * @param width - * image width[in] - * - * @param height - * image height[in] - * - * @param crop_left - * image left crop size[in] - * - * @param crop_top - * image top crop size[in] - * - * @param crop_width - * cropped image width[in] - * - * @param crop_height - * cropped image height[in] - * - * @param color_format - * source color format(HAL format)[in] - * - * @return - * error code - */ -CSC_ERRORCODE csc_set_src_format( - void *handle, - unsigned int width, - unsigned int height, - unsigned int crop_left, - unsigned int crop_top, - unsigned int crop_width, - unsigned int crop_height, - unsigned int color_format, - unsigned int cacheable); - -/* - * Get destination format. - * - * @param handle - * CSC handle[in] - * - * @param width - * address of image width[out] - * - * @param height - * address of image height[out] - * - * @param crop_left - * address of image left crop size[out] - * - * @param crop_top - * address of image top crop size[out] - * - * @param crop_width - * address of cropped image width[out] - * - * @param crop_height - * address of cropped image height[out] - * - * @param color_format - * address of color format(HAL format)[out] - * - * @return - * error code - */ -CSC_ERRORCODE csc_get_dst_format( - void *handle, - unsigned int *width, - unsigned int *height, - unsigned int *crop_left, - unsigned int *crop_top, - unsigned int *crop_width, - unsigned int *crop_height, - unsigned int *color_format, - unsigned int *cacheable); - -/* - * Set destination format - * Don't call each converting time. - * Pls call this function as below. - * 1. first converting time - * 2. format is changed - * - * @param handle - * CSC handle[in] - * - * @param width - * image width[in] - * - * @param height - * image height[in] - * - * @param crop_left - * image left crop size[in] - * - * @param crop_top - * image top crop size[in] - * - * @param crop_width - * cropped image width[in] - * - * @param crop_height - * cropped image height[in] - * - * @param color_format - * destination color format(HAL format)[in] - * - * @return - * error code - */ -CSC_ERRORCODE csc_set_dst_format( - void *handle, - unsigned int width, - unsigned int height, - unsigned int crop_left, - unsigned int crop_top, - unsigned int crop_width, - unsigned int crop_height, - unsigned int color_format, - unsigned int cacheable); - -/* - * Setup source buffer - * set_format func should be called before this this func. - * - * @param handle - * CSC handle[in] - * - * @param src_buffer - * source buffer pointer array[in] - * - * @param y - * y or RGB destination pointer[in] - * - * @param u - * u or uv destination pointer[in] - * - * @param v - * v or none destination pointer[in] - * - * @return - * error code - */ -CSC_ERRORCODE csc_set_src_buffer( - void *handle, - unsigned char *y, - unsigned char *u, - unsigned char *v, - int ion_fd); - -/* - * Setup destination buffer - * - * @param handle - * CSC handle[in] - * - * @param y - * y or RGB destination pointer[in] - * - * @param u - * u or uv destination pointer[in] - * - * @param v - * v or none destination pointer[in] - * - * @return - * error code - */ -CSC_ERRORCODE csc_set_dst_buffer( - void *handle, - unsigned char *y, - unsigned char *u, - unsigned char *v, - int ion_fd); - -/* - * Convert color space with presetup color format - * - * @param handle - * CSC handle[in] - * - * @return - * error code - */ -CSC_ERRORCODE csc_convert( - void *handle); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/exynos4/multimedia/openmax/Android.mk b/exynos4/multimedia/openmax/Android.mk deleted file mode 100644 index 6571161..0000000 --- a/exynos4/multimedia/openmax/Android.mk +++ /dev/null @@ -1 +0,0 @@ -include $(all-subdir-makefiles) diff --git a/exynos4/multimedia/openmax/sec_omx/component/video/dec/h264/Android.mk b/exynos4/multimedia/openmax/sec_omx/component/video/dec/h264/Android.mk deleted file mode 100644 index da5880e..0000000 --- a/exynos4/multimedia/openmax/sec_omx/component/video/dec/h264/Android.mk +++ /dev/null @@ -1,84 +0,0 @@ -LOCAL_PATH := $(call my-dir) -include $(CLEAR_VARS) - -LOCAL_MODULE_TAGS := optional - -LOCAL_SRC_FILES := \ - SEC_OMX_H264dec.c \ - library_register.c - -LOCAL_PRELINK_MODULE := false -LOCAL_MODULE := libOMX.SEC.AVC.Decoder -LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/omx - -LOCAL_CFLAGS := - -ifeq ($(BOARD_NONBLOCK_MODE_PROCESS), true) -LOCAL_CFLAGS += -DNONBLOCK_MODE_PROCESS -endif - -ifeq ($(BOARD_USE_DRM), true) -LOCAL_CFLAGS += -DUSE_DRM -endif - -ifeq ($(BOARD_USE_ANB), true) -LOCAL_CFLAGS += -DUSE_ANB -ifeq ($(BOARD_USE_CSC_FIMC), true) -ifeq ($(BOARD_USE_V4L2_ION), false) -LOCAL_CFLAGS += -DUSE_CSC_FIMC -endif -endif - -ifeq ($(BOARD_USE_CSC_GSCALER), true) -LOCAL_CFLAGS += -DUSE_CSC_GSCALER -endif -endif - - -ifeq ($(TARGET_BOARD_PLATFORM), exynos4) -ifeq ($(BOARD_USE_V4L2_ION),false) -ifeq ($(BOARD_USE_S3D_SUPPORT), true) -LOCAL_CFLAGS += -DS3D_SUPPORT -endif -endif -endif - -ifeq ($(TARGET_BOARD_PLATFORM), exynos5) -ifeq ($(BOARD_USE_S3D_SUPPORT), true) -LOCAL_CFLAGS += -DS3D_SUPPORT -endif -endif - -LOCAL_ARM_MODE := arm - -LOCAL_STATIC_LIBRARIES := libSEC_OMX_Vdec libsecosal libsecbasecomponent \ - libswconverter libsecmfcapi -LOCAL_SHARED_LIBRARIES := libc libdl libcutils libutils libui \ - libSEC_OMX_Resourcemanager libcsc - -ifeq ($(filter-out exynos4,$(TARGET_BOARD_PLATFORM)),) -LOCAL_SHARED_LIBRARIES += libfimc libhwconverter -endif - -ifeq ($(filter-out exynos5,$(TARGET_BOARD_PLATFORM)),) -LOCAL_SHARED_LIBRARIES += libexynosgscaler -endif - -#ifeq ($(BOARD_USE_V4L2_ION),true) -#LOCAL_SHARED_LIBRARIES += libion -#endif - -ifeq ($(BOARD_USES_MFC_FPS),true) -LOCAL_CFLAGS += -DCONFIG_MFC_FPS -endif - -LOCAL_C_INCLUDES := $(SEC_OMX_INC)/khronos \ - $(SEC_OMX_INC)/sec \ - $(SEC_OMX_TOP)/osal \ - $(SEC_OMX_TOP)/core \ - $(SEC_OMX_COMPONENT)/common \ - $(SEC_OMX_COMPONENT)/video/dec \ - $(TARGET_OUT_HEADERS)/$(SEC_COPY_HEADERS_TO) \ - $(BOARD_HAL_PATH)/include - -include $(BUILD_SHARED_LIBRARY) diff --git a/exynos4210.mk b/exynos4210.mk new file mode 100644 index 0000000..527891e --- /dev/null +++ b/exynos4210.mk @@ -0,0 +1,23 @@ +# Copyright (C) 2012 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +ifeq ($(TARGET_BOARD_PLATFORM),exynos4) +ifeq ($(TARGET_SOC),exynos4210) + +include $(TARGET_HAL_PATH)/Android.mk +include hardware/samsung/exynos/multimedia/Android.mk +include hardware/samsung/exynos4/exynos4210/Android.mk + +endif +endif diff --git a/exynos4x12.mk b/exynos4x12.mk new file mode 100644 index 0000000..29cc4d5 --- /dev/null +++ b/exynos4x12.mk @@ -0,0 +1,22 @@ +# Copyright (C) 2012 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +ifeq ($(TARGET_BOARD_PLATFORM),exynos4) +ifeq ($(TARGET_SOC),exynos4x12) + +include $(TARGET_HAL_PATH)/Android.mk +include hardware/samsung/exynos/multimedia/Android.mk + +endif +endif diff --git a/exynos5/hal/Android.mk b/exynos5/hal/Android.mk new file mode 100644 index 0000000..6fe94d2 --- /dev/null +++ b/exynos5/hal/Android.mk @@ -0,0 +1,28 @@ +# +# Copyright (C) 2009 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +ifeq ($(TARGET_BOARD_PLATFORM),exynos5) +common_exynos5_dirs := libgralloc_ump libhdmi libhwcomposer libfimg4x libcamera +exynos5250_dirs := $(common_exynos5_dirs) + +ifeq ($(BOARD_USES_HWJPEG),true) +exynos5250_dirs += libhwjpeg +endif + +ifeq ($(TARGET_SOC),exynos5250) + include $(call all-named-subdir-makefiles,$(exynos5250_dirs)) +endif +endif diff --git a/exynos5/hal/include/Exif.h b/exynos5/hal/include/Exif.h new file mode 100644 index 0000000..71e2241 --- /dev/null +++ b/exynos5/hal/include/Exif.h @@ -0,0 +1,231 @@ +/* + * Copyright Samsung Electronics Co.,LTD. + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef ANDROID_HARDWARE_EXIF_H +#define ANDROID_HARDWARE_EXIF_H + +#include + +#define EXIF_LOG2(x) (log((double)(x)) / log(2.0)) +#define APEX_FNUM_TO_APERTURE(x) ((int)(EXIF_LOG2((double)(x)) * 2 + 0.5)) +#define APEX_EXPOSURE_TO_SHUTTER(x) ((x) >= 1 ? \ + (int)(-(EXIF_LOG2((double)(x)) + 0.5)) : \ + (int)(-(EXIF_LOG2((double)(x)) - 0.5))) +#define APEX_ISO_TO_FILMSENSITIVITY(x) ((int)(EXIF_LOG2((x) / 3.125) + 0.5)) + +#define NUM_SIZE 2 +#define IFD_SIZE 12 +#define OFFSET_SIZE 4 + +#define NUM_0TH_IFD_TIFF 10 +#define NUM_0TH_IFD_EXIF 22 +#define NUM_0TH_IFD_GPS 10 +#define NUM_1TH_IFD_TIFF 9 + +/* Type */ +#define EXIF_TYPE_BYTE 1 +#define EXIF_TYPE_ASCII 2 +#define EXIF_TYPE_SHORT 3 +#define EXIF_TYPE_LONG 4 +#define EXIF_TYPE_RATIONAL 5 +#define EXIF_TYPE_UNDEFINED 7 +#define EXIF_TYPE_SLONG 9 +#define EXIF_TYPE_SRATIONAL 10 + +#define EXIF_FILE_SIZE 28800 + +/* 0th IFD TIFF Tags */ +#define EXIF_TAG_IMAGE_WIDTH 0x0100 +#define EXIF_TAG_IMAGE_HEIGHT 0x0101 +#define EXIF_TAG_MAKE 0x010f +#define EXIF_TAG_MODEL 0x0110 +#define EXIF_TAG_ORIENTATION 0x0112 +#define EXIF_TAG_SOFTWARE 0x0131 +#define EXIF_TAG_DATE_TIME 0x0132 +#define EXIF_TAG_YCBCR_POSITIONING 0x0213 +#define EXIF_TAG_EXIF_IFD_POINTER 0x8769 +#define EXIF_TAG_GPS_IFD_POINTER 0x8825 + +/* 0th IFD Exif Private Tags */ +#define EXIF_TAG_EXPOSURE_TIME 0x829A +#define EXIF_TAG_FNUMBER 0x829D +#define EXIF_TAG_EXPOSURE_PROGRAM 0x8822 +#define EXIF_TAG_ISO_SPEED_RATING 0x8827 +#define EXIF_TAG_EXIF_VERSION 0x9000 +#define EXIF_TAG_DATE_TIME_ORG 0x9003 +#define EXIF_TAG_DATE_TIME_DIGITIZE 0x9004 +#define EXIF_TAG_SHUTTER_SPEED 0x9201 +#define EXIF_TAG_APERTURE 0x9202 +#define EXIF_TAG_BRIGHTNESS 0x9203 +#define EXIF_TAG_EXPOSURE_BIAS 0x9204 +#define EXIF_TAG_MAX_APERTURE 0x9205 +#define EXIF_TAG_METERING_MODE 0x9207 +#define EXIF_TAG_FLASH 0x9209 +#define EXIF_TAG_FOCAL_LENGTH 0x920A +#define EXIF_TAG_USER_COMMENT 0x9286 +#define EXIF_TAG_COLOR_SPACE 0xA001 +#define EXIF_TAG_PIXEL_X_DIMENSION 0xA002 +#define EXIF_TAG_PIXEL_Y_DIMENSION 0xA003 +#define EXIF_TAG_EXPOSURE_MODE 0xA402 +#define EXIF_TAG_WHITE_BALANCE 0xA403 +#define EXIF_TAG_SCENCE_CAPTURE_TYPE 0xA406 + +/* 0th IFD GPS Info Tags */ +#define EXIF_TAG_GPS_VERSION_ID 0x0000 +#define EXIF_TAG_GPS_LATITUDE_REF 0x0001 +#define EXIF_TAG_GPS_LATITUDE 0x0002 +#define EXIF_TAG_GPS_LONGITUDE_REF 0x0003 +#define EXIF_TAG_GPS_LONGITUDE 0x0004 +#define EXIF_TAG_GPS_ALTITUDE_REF 0x0005 +#define EXIF_TAG_GPS_ALTITUDE 0x0006 +#define EXIF_TAG_GPS_TIMESTAMP 0x0007 +#define EXIF_TAG_GPS_PROCESSING_METHOD 0x001B +#define EXIF_TAG_GPS_DATESTAMP 0x001D + +/* 1th IFD TIFF Tags */ +#define EXIF_TAG_COMPRESSION_SCHEME 0x0103 +#define EXIF_TAG_X_RESOLUTION 0x011A +#define EXIF_TAG_Y_RESOLUTION 0x011B +#define EXIF_TAG_RESOLUTION_UNIT 0x0128 +#define EXIF_TAG_JPEG_INTERCHANGE_FORMAT 0x0201 +#define EXIF_TAG_JPEG_INTERCHANGE_FORMAT_LEN 0x0202 + +typedef enum { + EXIF_ORIENTATION_UP = 1, + EXIF_ORIENTATION_90 = 6, + EXIF_ORIENTATION_180 = 3, + EXIF_ORIENTATION_270 = 8, +} ExifOrientationType; + +typedef enum { + EXIF_SCENE_STANDARD, + EXIF_SCENE_LANDSCAPE, + EXIF_SCENE_PORTRAIT, + EXIF_SCENE_NIGHT, +} CamExifSceneCaptureType; + +typedef enum { + EXIF_METERING_UNKNOWN, + EXIF_METERING_AVERAGE, + EXIF_METERING_CENTER, + EXIF_METERING_SPOT, + EXIF_METERING_MULTISPOT, + EXIF_METERING_PATTERN, + EXIF_METERING_PARTIAL, + EXIF_METERING_OTHER = 255, +} CamExifMeteringModeType; + +typedef enum { + EXIF_EXPOSURE_AUTO, + EXIF_EXPOSURE_MANUAL, + EXIF_EXPOSURE_AUTO_BRACKET, +} CamExifExposureModeType; + +typedef enum { + EXIF_WB_AUTO, + EXIF_WB_MANUAL, +} CamExifWhiteBalanceType; + +/* Values */ +#define EXIF_DEF_MAKER "SAMSUNG" +#define EXIF_DEF_MODEL "SAMSUNG" +#define EXIF_DEF_SOFTWARE "SAMSUNG" +#define EXIF_DEF_EXIF_VERSION "0220" +#define EXIF_DEF_USERCOMMENTS "User comments" + +#define EXIF_DEF_YCBCR_POSITIONING 1 /* centered */ +#define EXIF_DEF_FNUMBER_NUM 26 /* 2.6 */ +#define EXIF_DEF_FNUMBER_DEN 10 +#define EXIF_DEF_EXPOSURE_PROGRAM 3 /* aperture priority */ +#define EXIF_DEF_FOCAL_LEN_NUM 278 /* 2.78mm */ +#define EXIF_DEF_FOCAL_LEN_DEN 100 +#define EXIF_DEF_FLASH 0 /* O: off, 1: on*/ +#define EXIF_DEF_COLOR_SPACE 1 +#define EXIF_DEF_EXPOSURE_MODE EXIF_EXPOSURE_AUTO +#define EXIF_DEF_APEX_DEN 10 + +#define EXIF_DEF_COMPRESSION 6 +#define EXIF_DEF_RESOLUTION_NUM 72 +#define EXIF_DEF_RESOLUTION_DEN 1 +#define EXIF_DEF_RESOLUTION_UNIT 2 /* inches */ + +typedef struct { + uint32_t num; + uint32_t den; +} rational_t; + +typedef struct { + int32_t num; + int32_t den; +} srational_t; + +typedef struct { + bool enableGps; + bool enableThumb; + + unsigned char maker[32]; + unsigned char model[32]; + unsigned char software[32]; + unsigned char exif_version[4]; + unsigned char date_time[20]; + unsigned char user_comment[150]; + + uint32_t width; + uint32_t height; + uint32_t widthThumb; + uint32_t heightThumb; + + uint16_t orientation; + uint16_t ycbcr_positioning; + uint16_t exposure_program; + uint16_t iso_speed_rating; + uint16_t metering_mode; + uint16_t flash; + uint16_t color_space; + uint16_t exposure_mode; + uint16_t white_balance; + uint16_t scene_capture_type; + + rational_t exposure_time; + rational_t fnumber; + rational_t aperture; + rational_t max_aperture; + rational_t focal_length; + + srational_t shutter_speed; + srational_t brightness; + srational_t exposure_bias; + + unsigned char gps_latitude_ref[2]; + unsigned char gps_longitude_ref[2]; + + uint8_t gps_version_id[4]; + uint8_t gps_altitude_ref; + + rational_t gps_latitude[3]; + rational_t gps_longitude[3]; + rational_t gps_altitude; + rational_t gps_timestamp[3]; + unsigned char gps_datestamp[11]; + unsigned char gps_processing_method[100]; + + rational_t x_resolution; + rational_t y_resolution; + uint16_t resolution_unit; + uint16_t compression_scheme; +} exif_attribute_t; + +#endif /* ANDROID_HARDWARE_EXIF_H */ diff --git a/exynos5/hal/include/SecBuffer.h b/exynos5/hal/include/SecBuffer.h new file mode 100644 index 0000000..b8a41df --- /dev/null +++ b/exynos5/hal/include/SecBuffer.h @@ -0,0 +1,158 @@ +/* + * Copyright@ Samsung Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +*/ + +/*! + * \file SecBuffer.h + * \brief header file for SecBuffer + * \author Sangwoo, Park(sw5771.park@samsung.com) + * \date 2011/06/02 + * + * Revision History: + * - 2010/06/03 : Sangwoo, Park(sw5771.park@samsung.com) \n + * Initial version + * + */ + +/** + * @page SecBuffer + * + * @section Introduction + * SecBuffer is common struct for buffer + * + * @section Copyright + * Copyright (c) 2008-2011 Samsung Electronics Co., Ltd.All rights reserved. \n + * Proprietary and Confidential + * + * @image html samsung.png + */ + +#ifndef __SEC_BUFFER_H__ +#define __SEC_BUFFER_H__ + +#include + +//! Buffer information +struct SecBuffer +{ +public: + //! Buffer type + enum BUFFER_TYPE + { + BUFFER_TYPE_BASE = 0, + BUFFER_TYPE_VIRT = 1, //!< virtual address + BUFFER_TYPE_PHYS = 1 << 1, //!< physical address + BUFFER_TYPE_RESERVED = 1 << 2, //!< reserved type + BUFFER_TYPE_MAX, + }; + + //! Buffer virtual address + union { + char *p; //! single address. + char *extP[3]; //! Y Cb Cr. + } virt; + + //! Buffer physical address + union { + unsigned int p; //! single address. + unsigned int extP[3]; //! Y Cb Cr. + } phys; + + //! Buffer reserved id + union { + unsigned int p; //! \n + unsigned int extP[3]; //! \n + } reserved; + + //! Buffer size + union { + unsigned int s; + unsigned int extS[3]; + } size; + + //! Constructor + SecBuffer() + { + for (int i = 0; i < 3; i++) { + virt. extP[i] = NULL; + phys. extP[i] = 0; + reserved.extP[i] = 0; + size. extS[i] = 0; + } + } + + //! Constructor + SecBuffer(const SecBuffer *other) + { + for (int i = 0; i < 3; i++) { + virt. extP[i] = other->virt.extP[i]; + phys. extP[i] = other->phys.extP[i]; + reserved.extP[i] = other->reserved.extP[i]; + size. extS[i] = other->size.extS[i]; + } + } + + //! Operator(=) override + SecBuffer& operator =(const SecBuffer &other) + { + for (int i = 0; i < 3; i++) { + virt. extP[i] = other.virt.extP[i]; + phys. extP[i] = other.phys.extP[i]; + reserved.extP[i] = other.reserved.extP[i]; + size. extS[i] = other.size.extS[i]; + } + return *this; + } + + //! Operator(==) override + bool operator ==(const SecBuffer &other) const + { + return ( virt. extP[0] == other.virt.extP[0] + && virt. extP[1] == other.virt.extP[1] + && virt. extP[2] == other.virt.extP[2] + && phys. extP[0] == other.phys.extP[0] + && phys. extP[1] == other.phys.extP[1] + && phys. extP[2] == other.phys.extP[2] + && reserved.extP[0] == other.reserved.extP[0] + && reserved.extP[1] == other.reserved.extP[1] + && reserved.extP[2] == other.reserved.extP[2] + && size. extS[0] == other.size.extS[0] + && size. extS[1] == other.size.extS[1] + && size. extS[2] == other.size.extS[2]); + } + + //! Operator(!=) override + bool operator !=(const SecBuffer &other) const + { + // use operator(==) + return !(*this == other); + } + + //! Get Buffer type + static int BUFFER_TYPE(SecBuffer *buf) + { + int type = BUFFER_TYPE_BASE; + if (buf->virt.p) + type |= BUFFER_TYPE_VIRT; + if (buf->phys.p) + type |= BUFFER_TYPE_PHYS; + if (buf->reserved.p) + type |= BUFFER_TYPE_RESERVED; + + return type; + } +}; + +#endif //__SEC_BUFFER_H__ diff --git a/exynos5/hal/include/SecFimc.h b/exynos5/hal/include/SecFimc.h new file mode 100644 index 0000000..c7f9945 --- /dev/null +++ b/exynos5/hal/include/SecFimc.h @@ -0,0 +1,186 @@ +/* + * Copyright@ Samsung Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/*! + * \file SecFimc.h + * \brief header file for Fimc HAL MODULE + * \author Hyunkyung, Kim(hk310.kim@samsung.com) + * \date 2010/10/13 + * + * Revision History: + * - 2010/10/13 : Hyunkyung, Kim(hk310.kim@samsung.com) \n + * Initial version + * + * - 2011/11/15 : Sunmi, Lee(carrotsm.lee@samsung.com) \n + * Adjust V4L2 architecture \n + */ + +#ifndef __SEC_FIMC_H__ +#define __SEC_FIMC_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "utils/Timers.h" + +#include "s5p_fimc_v4l2.h" +#include "sec_utils_v4l2.h" +#include "sec_format.h" + +#include "SecBuffer.h" +#include "SecRect.h" + +#define PFX_NODE_FIMC "/dev/video" +#define MAX_DST_BUFFERS (3) +#define MAX_SRC_BUFFERS (1) +#define MAX_PLANES (3) + +#ifdef __cplusplus +} + +class SecFimc +{ +public: + enum DEV { + DEV_0 = 0, + DEV_1, + DEV_2, + DEV_3, + DEV_MAX, + }; + + enum MODE { + MODE_NONE = 0, + MODE_SINGLE_BUF, + MODE_MULTI_BUF, + MODE_DMA_AUTO, + MODE_MAX, + }; + +private: + bool mFlagCreate; + int mDev; + int mFimcMode; + int mNumOfBuf; + + int mRealDev; + int mFd; + int mHwVersion; + int mBufIndex; + int mRotVal; + bool mFlagGlobalAlpha; + int mGlobalAlpha; + bool mFlagLocalAlpha; + bool mFlagColorKey; + int mColorKey; + bool mFlagSetSrcParam; + bool mFlagSetDstParam; + bool mFlagStreamOn; + + s5p_fimc_t mS5pFimc; + struct v4l2_capability mFimcCap; + + SecBuffer mSrcBuffer; + SecBuffer mDstBuffer[MAX_DST_BUFFERS]; + +public: + SecFimc(); + virtual ~SecFimc(); + + bool create(enum DEV dev, enum MODE mode, int numOfBuf); + bool destroy(void); + bool flagCreate(void); + + int getFd(void); + + SecBuffer * getMemAddr(int index = 0); + + int getHWVersion(void); + + bool setSrcParams(unsigned int width, unsigned int height, + unsigned int cropX, unsigned int cropY, + unsigned int *cropWidth, unsigned int *cropHeight, + int colorFormat, + bool forceChange = true); + + bool getSrcParams(unsigned int *width, unsigned int *height, + unsigned int *cropX, unsigned int *cropY, + unsigned int *cropWidth, unsigned int *cropHeight, + int *colorFormat); + + bool setSrcAddr(unsigned int physYAddr, + unsigned int physCbAddr = 0, + unsigned int physCrAddr = 0, + int colorFormat = 0); + + bool setDstParams(unsigned int width, unsigned int height, + unsigned int cropX, unsigned int cropY, + unsigned int *cropWidth, unsigned int *cropHeight, + int colorFormat, + bool forceChange = true); + + bool getDstParams(unsigned int *width, unsigned int *height, + unsigned int *cropX, unsigned int *cropY, + unsigned int *cropWidth, unsigned int *cropHeight, + int *colorFormat); + + bool setDstAddr(unsigned int physYAddr, unsigned int physCbAddr = 0, unsigned int physCrAddr = 0, int buf_index = 0); + + bool setRotVal(unsigned int rotVal); + bool setGlobalAlpha(bool enable = true, int alpha = 0xff); + bool setLocalAlpha(bool enable); + bool setColorKey(bool enable = true, int colorKey = 0xff); + + bool draw(int src_index, int dst_index); + +private: + bool m_streamOn(void); + bool m_checkSrcSize(unsigned int width, unsigned int height, + unsigned int cropX, unsigned int cropY, + unsigned int *cropWidth, unsigned int *cropHeight, + int colorFormat, + bool forceChange = false); + + bool m_checkDstSize(unsigned int width, unsigned int height, + unsigned int cropX, unsigned int cropY, + unsigned int *cropWidth, unsigned int *cropHeight, + int colorFormat, + int rotVal, + bool forceChange = false); + int m_widthOfFimc(int v4l2ColorFormat, int width); + int m_heightOfFimc(int v4l2ColorFormat, int height); + int m_getYuvBpp(unsigned int fmt); + int m_getYuvPlanes(unsigned int fmt); +}; +#endif + +#endif //__SEC_FIMC_H__ diff --git a/exynos5/hal/include/SecHdmi.h b/exynos5/hal/include/SecHdmi.h new file mode 100644 index 0000000..1811c73 --- /dev/null +++ b/exynos5/hal/include/SecHdmi.h @@ -0,0 +1,250 @@ +/* + * Copyright@ Samsung Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +** +** @author Sangwoo, Park(sw5771.park@samsung.com) +** @date 2010-09-10 +** +*/ + +#ifndef __SEC_HDMI_H__ +#define __SEC_HDMI_H__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "s5p_tvout_v4l2.h" +#include "v4l2-mediabus.h" + +#if defined(BOARD_USES_HDMI_FIMGAPI) +#include "sec_g2d.h" +#include "FimgApi.h" +#endif + +#include "s3c_lcd.h" +#include "SecBuffer.h" + +#include "../libhdmi/libsForhdmi/libedid/libedid.h" +#include "../libhdmi/libsForhdmi/libcec/libcec.h" + +#include "../libhdmi/SecHdmi/SecHdmiCommon.h" +#include "../libhdmi/SecHdmi/SecHdmiV4L2Utils.h" +#include "../libhdmi/SecHdmi/SecGscaler.h" + + +#include +#include + +namespace android { + +class SecHdmi: virtual public RefBase +{ +public : + enum HDMI_LAYER { + HDMI_LAYER_BASE = 0, + HDMI_LAYER_VIDEO, + HDMI_LAYER_GRAPHIC_0, + HDMI_LAYER_GRAPHIC_1, + HDMI_LAYER_MAX, + }; + +private : + class CECThread: public Thread + { + public: + bool mFlagRunning; + + private: + sp mSecHdmi; + Mutex mThreadLoopLock; + Mutex mThreadControlLock; + virtual bool threadLoop(); + enum CECDeviceType mDevtype; + int mLaddr; + int mPaddr; + + public: + CECThread(sp secHdmi) + :Thread(false), + mFlagRunning(false), + mSecHdmi(secHdmi), + mDevtype(CEC_DEVICE_PLAYER), + mLaddr(0), + mPaddr(0){ + }; + virtual ~CECThread(); + + bool start(); + bool stop(); + + }; + + Mutex mLock; + + sp mCECThread; + + bool mFlagCreate; + bool mFlagConnected; + bool mFlagLayerEnable[HDMI_LAYER_MAX]; + bool mFlagHdmiStart[HDMI_LAYER_MAX]; + + int mSrcWidth[HDMI_LAYER_MAX]; + int mSrcHeight[HDMI_LAYER_MAX]; + int mSrcColorFormat[HDMI_LAYER_MAX]; + int mHdmiResolutionWidth[HDMI_LAYER_MAX]; + int mHdmiResolutionHeight[HDMI_LAYER_MAX]; + int mPreviousNumofHwLayer[HDMI_LAYER_MAX]; + __u32 mPreviousHdmiPresetId; + int mHdmiDstWidth; + int mHdmiDstHeight; + + unsigned int mHdmiSrcYAddr; + unsigned int mHdmiSrcCbCrAddr; + + unsigned int mFBaddr; + unsigned int mFBsize; + int mFBionfd; + unsigned int mFBoffset; + + int mHdmiOutputMode; + unsigned int mHdmiResolutionValue; + v4l2_std_id mHdmiStdId; + __u32 mHdmiPresetId; + unsigned int mCompositeStd; + bool mHdcpMode; + int mAudioMode; + unsigned int mUIRotVal; + unsigned int mG2DUIRotVal; + + int mCurrentsrcW; + int mCurrentsrcH; + int mCurrentsrcColorFormat; + unsigned int mCurrentsrcYAddr; + unsigned int mCurrentsrcCbAddr; + int mCurrentdstX; + int mCurrentdstY; + int mCurrenthdmiLayer; + int mCurrentNumOfHWCLayer; + + int mCurrentHdmiOutputMode; + unsigned int mCurrentHdmiResolutionValue; + bool mCurrentHdcpMode; + int mCurrentAudioMode; + bool mHdmiInfoChange; + + bool mFlagGscalerStart; + int mGscalerDstColorFormat; + + int mVideodevFd[HDMI_LAYER_MAX]; + int mMediadevFd; + int mSubdevMixerFd; + + __u32 mMixerSubdevEntity; + + SecBuffer mSrcBuffer[HDMI_LAYER_MAX][MAX_BUFFERS_MIXER]; + int mSrcIndex[HDMI_LAYER_MAX]; + SecGscaler mSecGscaler; + + struct v4l2_rect mSrcRect; + struct media_link_desc mlink_desc; + + int mIonClient; + + unsigned int mHdmiResolutionValueList[14]; + int mHdmiSizeOfResolutionValueList; + + int mDefaultFBFd; + int mDisplayWidth; + int mDisplayHeight; + + bool mGscalerForceUpdate; + +public : + + SecHdmi(); + virtual ~SecHdmi(); + bool create(int width, int height); + bool destroy(void); + inline bool flagCreate(void) { return mFlagCreate; } + + bool connect(void); + bool disconnect(void); + + bool flagConnected(void); + + bool flush(int srcW, int srcH, int srcColorFormat, + unsigned int srcYAddr, unsigned int srcCbAddr, unsigned int srcCrAddr, + int dstX, int dstY, + int hdmiLayer, + int num_of_hwc_layer); + + bool clear(int hdmiLayer); + + void clearGraphicLayer(int hdmiLayer); + bool enableGraphicLayer(int hdmiLayer); + bool disableGraphicLayer(int hdmiLayer); + + bool startHdmi(int hdmiLayer); + bool stopHdmi(int hdmiLayer); + + bool setHdmiOutputMode(int hdmiOutputMode, bool forceRun = false); + bool setHdmiResolution(unsigned int hdmiResolutionValue, bool forceRun = true); + bool setHdcpMode(bool hdcpMode, bool forceRun = false); + bool setUIRotation(unsigned int rotVal, unsigned int hwcLayer); + bool setDisplaySize(int width, int height); + void setDisplayInfo(int srcW, int srcH, int srcColorFormat, + unsigned int srcYAddr, unsigned int srcCbAddr, + int dstX, int dstY, + int hdmiLayer, + int num_of_hwc_layer); +private: + bool m_setupLink(void); + bool m_openLayer(int layer); + bool m_closeLayer(int layer); + + bool m_reset(int w, int h, int dstX, int dstY, int colorFormat, int hdmiLayer, int num_of_hwc_layer); + bool m_streamOn(int hdmiLayer); + + bool m_run(int hdmiLayer); + bool m_startHdmi(int hdmiLayer); + bool m_stopHdmi(int hdmiLayer); + + bool m_setHdmiOutputMode(int hdmiOutputMode); + bool m_setHdmiResolution(unsigned int hdmiResolutionValue); + bool m_setCompositeResolution(unsigned int compositeStdId); + bool m_setHdcpMode(bool hdcpMode); + bool m_setAudioMode(int audioMode); + + int m_resolutionValueIndex(unsigned int ResolutionValue); + + bool m_flagHWConnected(void); + bool m_flush(int srcW, int srcH, int srcColorFormat, + unsigned int srcYAddr, unsigned int srcCbAddr, unsigned int srcCrAddr, + int dstX, int dstY, + int hdmiLayer, + int nun_of_hwc_layer); +}; + +}; // namespace android + +#endif //__SEC_HDMI_H__ diff --git a/exynos5/hal/include/SecJpegCodecHal.h b/exynos5/hal/include/SecJpegCodecHal.h new file mode 100644 index 0000000..55db15d --- /dev/null +++ b/exynos5/hal/include/SecJpegCodecHal.h @@ -0,0 +1,217 @@ +/* + * Copyright Samsung Electronics Co.,LTD. + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __SEC_JPG_CODEC_HAL_H__ +#define __SEC_JPG_CODEC_HAL_H__ + +#include "videodev2.h" + +#define JPEG_DEC_NODE "/dev/video11" +#define JPEG_ENC_NODE "/dev/video12" + +#define JPEG_MAX_PLANE_CNT (3) +#define JPEG_BYTE_ALIGN (32) + +#define MAX_JPG_WIDTH 8192 +#define MAX_JPG_HEIGHT 8192 + +#define JPEG_CACHE_OFF (0) +#define JPEG_CACHE_ON (1) + +class SecJpegCodecHal { +public: + ; + SecJpegCodecHal(); + virtual ~SecJpegCodecHal(); + + enum ERROR_JPEG_HAL { + ERROR_JPEG_DEVICE_ALREADY_CREATE = -0x100, + ERROR_CANNOT_OPEN_JPEG_DEVICE, + ERROR_JPEG_DEVICE_ALREADY_CLOSED, + ERROR_JPEG_DEVICE_ALREADY_DESTROY, + ERROR_JPEG_DEVICE_NOT_CREATE_YET, + ERROR_INVALID_COLOR_FORMAT, + ERROR_INVALID_JPEG_FORMAT, + ERROR_INVALID_IMAGE_SIZE, + ERROR_JPEG_CONFIG_POINTER_NULL, + ERROR_INVALID_JPEG_CONFIG, + ERROR_IN_BUFFER_CREATE_FAIL, + ERROR_OUT_BUFFER_CREATE_FAIL, + ERROR_EXCUTE_FAIL, + ERROR_JPEG_SIZE_TOO_SMALL, + ERROR_CANNOT_CHANGE_CACHE_SETTING, + ERROR_SIZE_NOT_SET_YET, + ERROR_BUFFR_IS_NULL, + ERROR_BUFFER_TOO_SMALL, + ERROR_GET_SIZE_FAIL, + ERROR_REQBUF_FAIL, + ERROR_INVALID_V4l2_BUF_TYPE = -0x80, + ERROR_MMAP_FAILED, + ERROR_FAIL, + ERROR_NONE = 0 + }; + + enum MODE { + MODE_ENCODE = 0, + MODE_DECODE + }; + + struct BUFFER{ + int numOfPlanes; + char *addr[JPEG_MAX_PLANE_CNT]; + int size[JPEG_MAX_PLANE_CNT]; + }; + + struct BUF_INFO{ + int numOfPlanes; + enum v4l2_memory memory; + enum v4l2_buf_type buf_type; + int reserved[4]; + }; + + struct PIX_FMT{ + int in_fmt; + int out_fmt; + int reserved[4]; + }; + + struct CONFIG{ + int mode; + int enc_qual; + + int width; + int height; + int scaled_width; + int scaled_height; + + int numOfPlanes; + + int sizeJpeg; + + union { + PIX_FMT enc_fmt; + PIX_FMT dec_fmt; + } pix; + + int reserved[8]; + }; + +protected: + // variables + bool t_bFlagCreate; + bool t_bFlagCreateInBuf; + bool t_bFlagCreateOutBuf; + bool t_bFlagExcute; + + int t_iPlaneNum; + + int t_iJpegFd; + struct CONFIG t_stJpegConfig; + struct BUFFER t_stJpegInbuf; + struct BUFFER t_stJpegOutbuf; + + //functions + int t_v4l2Querycap(int iFd); + int t_v4l2SetJpegcomp(int iFd, int iQuality); + int t_v4l2SetFmt(int iFd, enum v4l2_buf_type eType, struct CONFIG *pstConfig); + int t_v4l2GetFmt(int iFd, enum v4l2_buf_type eType, struct CONFIG *pstConfig); + int t_v4l2Reqbufs(int iFd, int iBufCount, struct BUF_INFO *pstBufInfo); + int t_v4l2Querybuf(int iFd, struct BUF_INFO *pstBufInfo, struct BUFFER *pstBuf); + int t_v4l2Qbuf(int iFd, struct BUF_INFO *pstBufInfo, struct BUFFER *pstBuf); + int t_v4l2Dqbuf(int iFd, enum v4l2_buf_type eType, enum v4l2_memory eMemory); + int t_v4l2StreamOn(int iFd, enum v4l2_buf_type eType); + int t_v4l2StreamOff(int iFd, enum v4l2_buf_type eType); + int t_v4l2SetCtrl(int iFd, int iCid, int iValue); + int t_v4l2GetCtrl(int iFd, int iCid); +}; + +class SecJpegEncoderHal : SecJpegCodecHal { +public: + ; + SecJpegEncoderHal(); + virtual ~SecJpegEncoderHal(); + + enum QUALITY { + QUALITY_LEVEL_1 = 0, /* high */ + QUALITY_LEVEL_2, + QUALITY_LEVEL_3, + QUALITY_LEVEL_4, /* low */ + }; + + int create(void); + int destroy(void); + + int setSize(int iW, int iH); + + int setJpegConfig(void* pConfig); + void *getJpegConfig(void); + + + char **getInBuf(int *piInputSize); + char *getOutBuf(int *piOutputSize); + + int setCache(int iValue); + + int setInBuf(char **pcBuf, int *iSize); + int setOutBuf(char *pcBuf, int iSize); + + int getSize(int *piWidth, int *piHeight); + int setColorFormat(int iV4l2ColorFormat); + int setJpegFormat(int iV4l2JpegFormat); + int updateConfig(void); + + int setQuality(int iQuality); + int getJpegSize(void); + + int encode(void); +}; + +class SecJpegDecoderHal : SecJpegCodecHal { +public: + ; + SecJpegDecoderHal(); + virtual ~SecJpegDecoderHal(); + + int create(void); + int destroy(void); + + int setSize(int iW, int iH); + + int setJpegConfig(void* pConfig); + void *getJpegConfig(void); + + + char *getInBuf(int *piInputSize); + char **getOutBuf(int *piOutputSize); + + int setCache(int iValue); + + int setInBuf(char *pcBuf, int iSize); + int setOutBuf(char **pcBuf, int *iSize); + + int getSize(int *piWidth, int *piHeight); + int setColorFormat(int iV4l2ColorFormat); + int setJpegFormat(int iV4l2JpegFormat); + int updateConfig(void); + + int setScaledSize(int iW, int iH); + int setJpegSize(int iJpegSize); + + int decode(void); +}; + +#endif /* __SEC_JPG_CODEC_HAL_H__ */ diff --git a/exynos5/hal/include/SecJpegEncoder.h b/exynos5/hal/include/SecJpegEncoder.h new file mode 100644 index 0000000..c7390f9 --- /dev/null +++ b/exynos5/hal/include/SecJpegEncoder.h @@ -0,0 +1,157 @@ +/* + * Copyright Samsung Electronics Co.,LTD. + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __SEC_JPG_ENC_H__ +#define __SEC_JPG_ENC_H__ + +#include "Exif.h" + +#include "SecJpegCodecHal.h" + +#include +#include "ion.h" + +#define JPEG_THUMBNAIL_QUALITY 60 +#define EXIF_LIMIT_SIZE 64*1024 +//#define JPEG_WA_FOR_PAGEFAULT +#define JPEG_WA_BUFFER_SIZE 64 + +class SecJpegEncoder { +public : + ; + enum ERROR { + ERROR_ALREADY_CREATE = -0x200, + ERROR_CANNOT_CREATE_SEC_JPEG_ENC_HAL, + ERROR_NOT_YET_CREATED, + ERROR_ALREADY_DESTROY, + ERROR_INPUT_DATA_SIZE_TOO_LARGE, + ERROR_OUT_BUFFER_SIZE_TOO_SMALL, + ERROR_EXIFOUT_ALLOC_FAIL, + ERROR_MAKE_EXIF_FAIL, + ERROR_INVALID_SCALING_WIDTH_HEIGHT, + ERROR_CANNOT_CREATE_SEC_THUMB, + ERROR_THUMB_JPEG_SIZE_TOO_SMALL, + ERROR_IMPLEMENT_NOT_YET, + ERROR_JPEG_DEVICE_ALREADY_CREATE = -0x100, + ERROR_CANNOT_OPEN_JPEG_DEVICE, + ERROR_JPEG_DEVICE_ALREADY_CLOSED, + ERROR_JPEG_DEVICE_ALREADY_DESTROY, + ERROR_JPEG_DEVICE_NOT_CREATE_YET, + ERROR_INVALID_COLOR_FORMAT, + ERROR_INVALID_JPEG_FORMAT, + ERROR_JPEG_CONFIG_POINTER_NULL, + ERROR_INVALID_JPEG_CONFIG, + ERROR_IN_BUFFER_CREATE_FAIL, + ERROR_OUT_BUFFER_CREATE_FAIL, + ERROR_EXCUTE_FAIL, + ERROR_JPEG_SIZE_TOO_SMALL, + ERROR_CANNOT_CHANGE_CACHE_SETTING, + ERROR_SIZE_NOT_SET_YET, + ERROR_BUFFR_IS_NULL, + ERROR_BUFFER_TOO_SMALL, + ERROR_GET_SIZE_FAIL, + ERROR_REQBUF_FAIL, + ERROR_INVALID_V4l2_BUF_TYPE = -0x80, + ERROR_MMAP_FAILED, + ERROR_FAIL, + ERROR_NONE = 0 + }; + + SecJpegEncoder(); + virtual ~SecJpegEncoder(); + + bool flagCreate(); + int create(void); + int destroy(void); + + int setSize(int w, int h); + int setQuality(int quality); + int setColorFormat(int colorFormat); + int setJpegFormat(int jpegFormat); + + int updateConfig(void); + + char *getInBuf(int *input_size); + char *getOutBuf(int *output_size); + int setInBuf(char *buf, int size); + int setOutBuf(char *buf, int size); + + int encode(int *size, exif_attribute_t *exifInfo); + + int setThumbnailSize(int w, int h); + + int makeExif(unsigned char *exifOut, + exif_attribute_t *exifIn, + unsigned int *size, + bool useMainbufForThumb = false); + +private: + inline void writeExifIfd(unsigned char **pCur, + unsigned short tag, + unsigned short type, + unsigned int count, + uint32_t value); + inline void writeExifIfd(unsigned char **pCur, + unsigned short tag, + unsigned short type, + unsigned int count, + unsigned char *pValue); + inline void writeExifIfd(unsigned char **pCur, + unsigned short tag, + unsigned short type, + unsigned int count, + rational_t *pValue, + unsigned int *offset, + unsigned char *start); + inline void writeExifIfd(unsigned char **pCur, + unsigned short tag, + unsigned short type, + unsigned int count, + unsigned char *pValue, + unsigned int *offset, + unsigned char *start); + int m_scaleDownYuv422(char *srcBuf, uint32_t srcWidth, uint32_t srcHight, + char *dstBuf, uint32_t dstWidth, uint32_t dstHight); + // thumbnail + int encodeThumbnail(unsigned int *size, bool useMain = true); + + int allocJpegIonMemory(ion_client ionClient, ion_buffer *ionBuffer, char **buffer, int size); + void freeJpegIonMemory(ion_client ionClient, ion_buffer *ionBuffer, char **buffer, int size); + + bool m_flagCreate; + + SecJpegEncoderHal *m_jpegMain; + SecJpegEncoderHal *m_jpegThumb; + + char *m_pThumbInputBuffer; + char *m_pThumbOutputBuffer; +#ifdef JPEG_WA_FOR_PAGEFAULT + char *m_pExtInBuf; + char *m_pJpegInputBuffer; + int m_iInBufSize; +#endif // JPEG_WA_FOR_PAGEFAULT + ion_client m_ionJpegClient; + ion_buffer m_ionThumbInBuffer, m_ionThumbOutBuffer; +#ifdef JPEG_WA_FOR_PAGEFAULT + ion_buffer m_ionJpegInBuffer; +#endif // JPEG_WA_FOR_PAGEFAULT + + int m_thumbnailW; + int m_thumbnailH; +}; + +#endif /* __SEC_JPG_ENC_H__ */ diff --git a/exynos5/hal/include/SecRect.h b/exynos5/hal/include/SecRect.h new file mode 100644 index 0000000..1160a0b --- /dev/null +++ b/exynos5/hal/include/SecRect.h @@ -0,0 +1,172 @@ +/* + * Copyright@ Samsung Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +*/ + +/*! + * \file SecRect.h + * \brief header file for SecRect + * \author Sangwoo, Park(sw5771.park@samsung.com) + * \date 2011/06/02 + * + * Revision History: + * - 2010/06/03 : Sangwoo, Park(sw5771.park@samsung.com) \n + * Initial version + * + */ + +/** + * @page SecRect + * + * @section Introduction + * SetRect is common struct for rectangle + * + * @section Copyright + * Copyright (c) 2008-2011 Samsung Electronics Co., Ltd.All rights reserved. \n + * Proprietary and Confidential + * + * @image html samsung.png + */ + +#ifndef __SEC_RECT_H__ +#define __SEC_RECT_H__ + +//! Rectangle information +struct SecRect +{ + int x; //!< x pos + int y; //!< y pos + int w; //!< width + int h; //!< height + int fullW; //!< full width of image + int fullH; //!< full height of image + int colorFormat; //!< V4L2_PIX_FMT_XXX + + //! Constructor + SecRect(int _x_ = 0, + int _y_ = 0, + int _w_ = 0, + int _h_ = 0, + int _fullW_ = 0, + int _fullH_ = 0, + int _colorFormat_ = 0) + { + x = _x_; + y = _y_; + w = _w_; + h = _h_; + fullW = _fullW_; + fullH = _fullH_; + colorFormat = _colorFormat_; + } + + //! Constructor + SecRect(const SecRect *other) + { + x = other->x; + y = other->y; + w = other->w; + h = other->h; + fullW = other->fullW; + fullH = other->fullH; + colorFormat = other->colorFormat; + } + + //! Operator(=) override + SecRect& operator =(const SecRect &other) + { + x = other.x; + y = other.y; + w = other.w; + h = other.h; + fullW = other.fullW; + fullH = other.fullH; + colorFormat = other.colorFormat; + return *this; + } + + //! Operator(==) override + bool operator ==(const SecRect &other) const + { + return ( x == other.x + && y == other.y + && w == other.w + && h == other.h + && fullW == other.fullW + && fullH == other.fullH + && colorFormat == other.colorFormat); + } + + //! Operator(!=) override + bool operator !=(const SecRect &other) const + { + // use operator(==) + return !(*this == other); + } +}; + +//! Clip information +struct SecRect2 +{ + int x1; //!< Left (The x-coordinate value of upper-left corner) + int y1; //!< Top (The y-coordinate value of upper-left corner) + int x2; //!< Right (The x-coordinate value of lower-right corner) + int y2; //!< Bottom (The y-coordinate value of lower-right corner) + + //! Constructor + SecRect2(int _x1_ = 0, int _y1_ = 0, int _x2_ = 0, int _y2_ = 0) + { + x1 = _x1_; + y1 = _y1_; + x2 = _x2_; + y2 = _y2_; + } + + //! Constructor + SecRect2(const SecRect2 *other) + { + x1 = other->x1; + y1 = other->y1; + x2 = other->x2; + y2 = other->y2; + } + + //! Operator(=) override + SecRect2& operator =(const SecRect2 &other) + { + x1 = other.x1; + y1 = other.y1; + x2 = other.x2; + y2 = other.y2; + return *this; + } + + //! Operator(==) override + bool operator ==(const SecRect2 &other) const + { + return ( x1 == other.x1 + && y1 == other.y1 + && x2 == other.x2 + && y2 == other.y2); + } + + //! Operator(!=) override + bool operator !=(const SecRect2 &other) const + { + // use operator(==) + return !(*this == other); + } +}; + +#endif //__SEC_RECT_H__ diff --git a/exynos5/hal/include/audio.h b/exynos5/hal/include/audio.h new file mode 100644 index 0000000..1275db3 --- /dev/null +++ b/exynos5/hal/include/audio.h @@ -0,0 +1,363 @@ +/* + * Copyright@ Samsung Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _AUDIO_H_ +#define _AUDIO_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef __HDMI_AUDIO_HDMIAUDIOPORT__ +#define __HDMI_AUDIO_HDMIAUDIOPORT__ +/** + * @enum HDMIAudioPort + * Available audio inputs on HDMI HW module. + */ +enum HDMIAudioPort { + /** I2S input port */ + I2S_PORT, + /** SPDIF input port */ + SPDIF_PORT, + /** DSD input port */ + DSD_PORT, +}; +#endif /* __HDMI_AUDIO_HDMIAUDIOPORT__ */ + +#ifndef __HDMI_AUDIO_AUDIOFORMAT__ +#define __HDMI_AUDIO_AUDIOFORMAT__ +/** + * @enum AudioFormat + * The encoding format of audio stream + */ +enum AudioFormat { + /** LPCM encoding format */ + LPCM_FORMAT = 1, + /** AC3 encoding format */ + AC3_FORMAT, + /** MPEG1 encoding format */ + MPEG1_FORMAT, + /** MP3 encoding format */ + MP3_FORMAT, + /** MPEG2 encoding format */ + MPEG2_FORMAT, + /** AAC encoding format */ + AAC_FORMAT, + /** DTS encoding format */ + DTS_FORMAT, + /** ATRAC encoding format */ + ATRAC_FORMAT, + /** DSD encoding format */ + DSD_FORMAT, + /** Dolby Digital+ encoding format */ + Dolby_Digital_Plus_FORMAT, + /** DTS HD encoding format */ + DTS_HD_FORMAT, + /** MAT encoding format */ + MAT_FORMAT, + /** DST encoding format */ + DST_FORMAT, + /** WAM_Pro encoding format */ + WAM_Pro_FORMAT +}; +#endif /* __HDMI_AUDIO_AUDIOFORMAT__ */ + +#ifndef __HDMI_AUDIO_LPCMWORDLENGTH__ +#define __HDMI_AUDIO_LPCMWORDLENGTH__ +/** + * @enum LPCM_WordLen + * Word length of LPCM audio stream. + */ +enum LPCM_WordLen { + /** 16bit word length */ + WORD_16 = 0, + /** 17bit word length */ + WORD_17, + /** 18bit word length */ + WORD_18, + /** 19bit word length */ + WORD_19, + /** 20bit word length */ + WORD_20, + /** 21bit word length */ + WORD_21, + /** 22bit word length */ + WORD_22, + /** 23bit word length */ + WORD_23, + /** 24bit word length */ + WORD_24 +}; +#endif /* __HDMI_AUDIO_LPCMWORDLENGTH__ */ + +#ifndef __HDMI_AUDIO_SAMPLINGFREQUENCY__ +#define __HDMI_AUDIO_SAMPLINGFREQUENCY__ +/** + * @enum SamplingFreq + * Sampling frequency of audio stream. + */ +enum SamplingFreq { + /** 32KHz sampling frequency */ + SF_32KHZ = 0, + /** 44.1KHz sampling frequency */ + SF_44KHZ, + /** 48KHz sampling frequency */ + SF_48KHZ, + /** 88.2KHz sampling frequency */ + SF_88KHZ, + /** 96KHz sampling frequency */ + SF_96KHZ, + /** 176.4KHz sampling frequency */ + SF_176KHZ, + /** 192KHz sampling frequency */ + SF_192KHZ +}; +#endif /* __HDMI_AUDIO_SAMPLINGFREQUENCY__ */ + +#ifndef __HDMI_AUDIO_CHANNELNUMBER__ +#define __HDMI_AUDIO_CHANNELNUMBER__ +/** + * @enum ChannelNum + * Channel number of audio stream. + */ +enum ChannelNum { + /** 2 channel audio stream */ + CH_2 = 2, + /** 3 channel audio stream */ + CH_3, + /** 4 channel audio stream */ + CH_4, + /** 5 channel audio stream */ + CH_5, + /** 6 channel audio stream */ + CH_6, + /** 7 channel audio stream */ + CH_7, + /** 8 channel audio stream */ + CH_8, +}; +#endif /* __HDMI_AUDIO_CHANNELNUMBER__ */ + +#ifndef __HDMI_AUDIO_AUDIOSAMPLEPACKETTYPE__ +#define __HDMI_AUDIO_AUDIOSAMPLEPACKETTYPE__ +/** + * @enum HDMIASPType + * Type of HDMI audio sample packet + */ +enum HDMIASPType { + /** Audio Sample Packet Type */ + HDMI_ASP, + /** One Bit Audio Packet Type */ + HDMI_DSD, + /** High Bit Rate Packet Type */ + HDMI_HBR, + /** DST Packet Type */ + HDMI_DST +}; +#endif /* __HDMI_AUDID_AUDIOSAMPLEPACKETTYPE__ */ + +#ifndef __HDMI_AUDIO_I2S_CUV_AUDIO_CODING_TYPE__ +#define __HDMI_AUDIO_I2S_CUV_AUDIO_CODING_TYPE__ +/** + * @enum CUVAudioCoding + * Audio coding type information for CUV fields. + */ +enum CUVAudioCoding { + /** Linear PCM coding type */ + CUV_LPCM, + /** Non-linear PCM coding type */ + CUV_NLPCM +}; +#endif /* __HDMI_AUDIO_I2S_CUV_AUDIO_CODING_TYPE__ */ + +#ifndef __HDMI_AUDIO_SPDIF_AUDIO_CODING_TYPE__ +#define __HDMI_AUDIO_SPDIF_AUDIO_CODING_TYPE__ +/** + * @enum SPDIFAudioCoding + * Audio coding type information for SPDIF input port. + */ +enum SPDIFAudioCoding { + /** Linear PCM coding type */ + SPDIF_LPCM, + /** Non-linear PCM coding type */ + SPDIF_NLPCM +}; +#endif /* __HDMI_AUDIO_SPDIF_AUDIO_CODING_TYPE__ */ + +#ifndef __HDMI_AUDIO_I2S_CUV_CHANNEL_NUMBER__ +#define __HDMI_AUDIO_I2S_CUV_CHANNEL_NUMBER__ +/** + * @enum CUVChannelNumber + * Channel number information for CUV fields. + */ +enum CUVChannelNumber { + /** Unknown channel audio stream */ + CUV_CH_UNDEFINED = 0, + /** 1 channel audio stream */ + CUV_CH_01, + /** 2 channel audio stream */ + CUV_CH_02, + /** 3 channel audio stream */ + CUV_CH_03, + /** 4 channel audio stream */ + CUV_CH_04, + /** 5 channel audio stream */ + CUV_CH_05, + /** 6 channel audio stream */ + CUV_CH_06, + /** 7 channel audio stream */ + CUV_CH_07, + /** 8 channel audio stream */ + CUV_CH_08, + /** 9 channel audio stream */ + CUV_CH_09, + /** 10 channel audio stream */ + CUV_CH_10, + /** 11 channel audio stream */ + CUV_CH_11, + /** 12 channel audio stream */ + CUV_CH_12, + /** 13 channel audio stream */ + CUV_CH_13, + /** 14 channel audio stream */ + CUV_CH_14, + /** 15 channel audio stream */ + CUV_CH_15, +}; +#endif /* __HDMI_AUDIO_I2S_CUV_CHANNEL_NUMBER__ */ + +#ifndef __HDMI_AUDIO_I2S_CUV_WORD_LENGTH__ +#define __HDMI_AUDIO_I2S_CUV_WORD_LENGTH__ +/** + * @enum CUVWordLength + * Word length information of LPCM audio stream for CUV fields. + */ +enum CUVWordLength { + /** Max word length is 20 bits, number of valid bits is not defined */ + CUV_WL_20_NOT_DEFINED, + /** Max word length is 20 bits, 16 bits are valid */ + CUV_WL_20_16, + /** Max word length is 20 bits, 18 bits are valid */ + CUV_WL_20_18, + /** Max word length is 20 bits, 19 bits are valid */ + CUV_WL_20_19, + /** Max word length is 20 bits, 20 bits are valid */ + CUV_WL_20_20, + /** Max word length is 20 bits, 17 bits are valid */ + CUV_WL_20_17, + /** Max word length is 24 bits, number of valid bits is not defined */ + CUV_WL_24_NOT_DEFINED, + /** Max word length is 24 bits, 20 bits are valid */ + CUV_WL_24_20, + /** Max word length is 24 bits, 22 bits are valid */ + CUV_WL_24_22, + /** Max word length is 24 bits, 23 bits are valid */ + CUV_WL_24_23, + /** Max word length is 24 bits, 24 bits are valid */ + CUV_WL_24_24, + /** Max word length is 24 bits, 21 bits are valid */ + CUV_WL_24_21, +}; +#endif /* __HDMI_AUDIO_I2S_CUV_WORD_LENGTH__ */ + +#ifndef __HDMI_AUDIO_I2S_BITS_PER_CHANNEL__ +#define __HDMI_AUDIO_I2S_BITS_PER_CHANNEL__ + +/** + * @enum I2SBitsPerChannel + * Serial data bit per channel in I2S audio stream. + */ +enum I2SBitsPerChannel { + /** 16 bits per channel */ + I2S_BPC_16, + /** 20 bits per channel */ + I2S_BPC_20, + /** 24 bits per channel */ + I2S_BPC_24 +}; + +#endif /* __HDMI_AUDIO_I2S_BITS_PER_CHANNEL__ */ + +#ifndef __HDMI_AUDIO_I2S_DATA_FORMAT__ +#define __HDMI_AUDIO_I2S_DATA_FORMAT__ + +/** + * @enum I2SDataFormat + * Foramt of data in I2S audio stream. + */ +enum I2SDataFormat { + /** Basic format */ + I2S_BASIC, + /** Left justified format */ + I2S_LEFT_JUSTIFIED, + /** Right justified format */ + I2S_RIGHT_JUSTIFIED +}; + +#endif /* __HDMI_AUDIO_I2S_DATA_FORMAT__ */ + +#ifndef __HDMI_AUDIO_I2S_CLOCK_PER_FRAME__ +#define __HDMI_AUDIO_I2S_CLOCK_PER_FRAME__ + +/** + * @enum I2SClockPerFrame + * Bit clock per Frame in I2S audio stream. + */ +enum I2SClockPerFrame { + /** 32 clock per Frame */ + I2S_32FS, + /** 48 clock per Frame */ + I2S_48FS, + /** 64 clock per Frame */ + I2S_64FS +}; + +#endif /* __HDMI_AUDIO_I2S_CLOCK_PER_FRAME__ */ + +#ifndef __HDMI_AUDIO_I2S_PARAMETER__ +#define __HDMI_AUDIO_I2S_PARAMETER__ + +//! Structure for I2S audio stream +struct I2SParameter { + enum I2SBitsPerChannel bpc; + enum I2SDataFormat format; + enum I2SClockPerFrame clk; +}; +#endif /* __HDMI_AUDIO_I2S_PARAMETER__ */ + +//! Structure for HDMI audio input +struct HDMIAudioParameter { + /** Input audio port to HDMI HW */ + enum HDMIAudioPort inputPort; + /** Output Packet type **/ + enum HDMIASPType outPacket; + /** Encoding format */ + enum AudioFormat formatCode; + /** Channel number */ + enum ChannelNum channelNum; + /** Sampling frequency */ + enum SamplingFreq sampleFreq; + /** Word length. This is avaliable only if LPCM encoding format */ + enum LPCM_WordLen wordLength; + /** structure for I2S audio stream */ + struct I2SParameter i2sParam; +}; + +#ifdef __cplusplus +} +#endif + +#endif // _AUDIO_H_ diff --git a/exynos5/hal/include/exynos_mem.h b/exynos5/hal/include/exynos_mem.h new file mode 100644 index 0000000..a65f030 --- /dev/null +++ b/exynos5/hal/include/exynos_mem.h @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef __INCLUDE_EXYNOS_MEM_H +#define __INCLUDE_EXYNOS_MEM_H __FILE__ + +/* IOCTL commands */ +#define EXYNOS_MEM_SET_CACHEABLE _IOW('M', 200, bool) +#define EXYNOS_MEM_PADDR_CACHE_FLUSH _IOW('M', 201, struct exynos_mem_flush_range) + +struct exynos_mem_flush_range { + dma_addr_t start; + size_t length; +}; + +#endif /* __INCLUDE_EXYNOS_MEM_H */ diff --git a/exynos5/hal/include/gralloc_priv.h b/exynos5/hal/include/gralloc_priv.h new file mode 100644 index 0000000..05d7754 --- /dev/null +++ b/exynos5/hal/include/gralloc_priv.h @@ -0,0 +1,210 @@ +/* + * Copyright (C) 2010-2011 ARM Limited. All rights reserved. + * + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef GRALLOC_PRIV_H_ +#define GRALLOC_PRIV_H_ + +#include +#include +#include +#include + +#include +#include + +#include "ump.h" + +/* + * HWC_HWOVERLAY is flag for location of glFinish(). + * Enable this define if you want that glFinish() is in HWComposer. + * If you disable this define, glFinish() is called in threadloop(). + */ +#define HWC_HWOVERLAY 1 + +#define GRALLOC_ARM_UMP_MODULE 1 + +struct private_handle_t; + +struct private_module_t +{ + gralloc_module_t base; + + private_handle_t* framebuffer; + uint32_t flags; + uint32_t numBuffers; + uint32_t bufferMask; + pthread_mutex_t lock; + buffer_handle_t currentBuffer; + int ion_client; + + struct fb_var_screeninfo info; + struct fb_fix_screeninfo finfo; + float xdpi; + float ydpi; + float fps; + + enum { + PRIV_USAGE_LOCKED_FOR_POST = 0x80000000 + }; +}; + +#ifdef __cplusplus +struct private_handle_t : public native_handle +{ +#else +struct private_handle_t +{ + struct native_handle nativeHandle; +#endif + + enum { + PRIV_FLAGS_FRAMEBUFFER = 0x00000001, + PRIV_FLAGS_USES_UMP = 0x00000002, + PRIV_FLAGS_USES_ION = 0x00000020, + }; + + enum { + LOCK_STATE_WRITE = 1<<31, + LOCK_STATE_MAPPED = 1<<30, + LOCK_STATE_READ_MASK = 0x3FFFFFFF + }; + + // Following member is for ION memory only + int fd; + int magic; + int flags; + int size; + int base; + int lockState; + int writeOwner; + int pid; + + // Following members are for UMP memory only + ump_secure_id ump_id; + ump_handle ump_mem_handle; + + // Following members is for framebuffer only + int offset; + int paddr; + + int format; + int usage; + int width; + int height; + int bpp; + int stride; + + /* Following members are for YUV information */ + unsigned int yaddr; + unsigned int uoffset; + unsigned int voffset; + int ion_client; + +#ifdef __cplusplus + static const int sNumInts = 21; + static const int sNumFds = 1; + static const int sMagic = 0x3141592; + + private_handle_t(int flags, int size, int base, int lock_state, ump_secure_id secure_id, ump_handle handle): + magic(sMagic), + flags(flags), + size(size), + base(base), + lockState(lock_state), + writeOwner(0), + pid(getpid()), + ump_id(secure_id), + ump_mem_handle(handle), + fd(0), + format(0), + usage(0), + width(0), + height(0), + bpp(0), + stride(0), + yaddr(0), + uoffset(0), + voffset(0), + offset(0) + { + version = sizeof(native_handle); + numFds = sNumFds; + numInts = sNumInts; + } + + private_handle_t(int flags, int size, int base, int lock_state, int fb_file, int fb_offset): + magic(sMagic), + flags(flags), + size(size), + base(base), + lockState(lock_state), + writeOwner(0), + pid(getpid()), + ump_id(UMP_INVALID_SECURE_ID), + ump_mem_handle(UMP_INVALID_MEMORY_HANDLE), + fd(fb_file), + format(0), + usage(0), + width(0), + height(0), + bpp(0), + stride(0), + yaddr(0), + uoffset(0), + voffset(0), + offset(fb_offset) + { + version = sizeof(native_handle); + numFds = sNumFds; + numInts = sNumInts; + } + + ~private_handle_t() + { + magic = 0; + } + + bool usesPhysicallyContiguousMemory() + { + return (flags & PRIV_FLAGS_FRAMEBUFFER) ? true : false; + } + + static int validate(const native_handle* h) + { + const private_handle_t* hnd = (const private_handle_t*)h; + + if (!h || h->version != sizeof(native_handle) || + h->numInts != sNumInts || + h->numFds != sNumFds || + hnd->magic != sMagic) + return -EINVAL; + + return 0; + } + + static private_handle_t* dynamicCast(const native_handle* in) + { + if (validate(in) == 0) + return (private_handle_t*) in; + + return NULL; + } +#endif +}; + +#endif /* GRALLOC_PRIV_H_ */ diff --git a/exynos5/hal/include/i2c-dev.h b/exynos5/hal/include/i2c-dev.h new file mode 100644 index 0000000..a7a35a7 --- /dev/null +++ b/exynos5/hal/include/i2c-dev.h @@ -0,0 +1,74 @@ +/* + i2c-dev.h - i2c-bus driver, char device interface + + Copyright (C) 1995-97 Simon G. Vogl + Copyright (C) 1998-99 Frodo Looijaard + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef _LINUX_I2C_DEV_H +#define _LINUX_I2C_DEV_H + +#include +#include + +/* /dev/i2c-X ioctl commands. The ioctl's parameter is always an + * unsigned long, except for: + * - I2C_FUNCS, takes pointer to an unsigned long + * - I2C_RDWR, takes pointer to struct i2c_rdwr_ioctl_data + * - I2C_SMBUS, takes pointer to struct i2c_smbus_ioctl_data + */ +#define I2C_RETRIES 0x0701 /* number of times a device address should + be polled when not acknowledging */ +#define I2C_TIMEOUT 0x0702 /* set timeout in units of 10 ms */ + +/* NOTE: Slave address is 7 or 10 bits, but 10-bit addresses + * are NOT supported! (due to code brokenness) + */ +#define I2C_SLAVE 0x0703 /* Use this slave address */ +#define I2C_SLAVE_FORCE 0x0706 /* Use this slave address, even if it + is already in use by a driver! */ +#define I2C_TENBIT 0x0704 /* 0 for 7 bit addrs, != 0 for 10 bit */ + +#define I2C_FUNCS 0x0705 /* Get the adapter functionality mask */ + +#define I2C_RDWR 0x0707 /* Combined R/W transfer (one STOP only) */ + +#define I2C_PEC 0x0708 /* != 0 to use PEC with SMBus */ +#define I2C_SMBUS 0x0720 /* SMBus transfer */ + + +/* This is the structure as used in the I2C_SMBUS ioctl call */ +struct i2c_smbus_ioctl_data { + __u8 read_write; + __u8 command; + __u32 size; + union i2c_smbus_data __user *data; +}; + +/* This is the structure as used in the I2C_RDWR ioctl call */ +struct i2c_rdwr_ioctl_data { + struct i2c_msg __user *msgs; /* pointers to i2c_msgs */ + __u32 nmsgs; /* number of i2c_msgs */ +}; + +#define I2C_RDRW_IOCTL_MAX_MSGS 42 + +#ifdef __KERNEL__ +#define I2C_MAJOR 89 /* Device major number */ +#endif + +#endif /* _LINUX_I2C_DEV_H */ diff --git a/exynos5/hal/include/ion.h b/exynos5/hal/include/ion.h new file mode 100644 index 0000000..dbb8896 --- /dev/null +++ b/exynos5/hal/include/ion.h @@ -0,0 +1,144 @@ +#ifndef _LIB_ION_H_ +#define _LIB_ION_H_ + +#include /* size_t */ + +#define ION_HEAP_SYSTEM_MASK (1 << 0) +#define ION_HEAP_SYSTEM_CONTIG_MASK (1 << 1) +#define ION_HEAP_EXYNOS_MASK (1 << 4) +#define ION_HEAP_EXYNOS_CONTIG_MASK (1 << 5) + +/* ION_MSYNC_FLAGS + * values of @flags parameter to ion_msync() + * + * IMSYNC_DEV_TO_READ: Device only reads the buffer + * IMSYNC_DEV_TO_WRITE: Device may writes to the buffer + * IMSYNC_DEV_TO_RW: Device reads and writes to the buffer + * + * IMSYNC_SYNC_FOR_DEV: ion_msync() for device to access the buffer + * IMSYNC_SYNC_FOR_CPU: ion_msync() for CPU to access the buffer after device + * has accessed it. + * + * The values must be ORed with one of IMSYNC_DEV_* and one of IMSYNC_SYNC_*. + * Otherwise, ion_msync() will not effect. + */ +enum ION_MSYNC_FLAGS { + IMSYNC_DEV_TO_READ = 0, + IMSYNC_DEV_TO_WRITE = 1, + IMSYNC_DEV_TO_RW = 2, + IMSYNC_SYNC_FOR_DEV = 0x10000, + IMSYNC_SYNC_FOR_CPU = 0x20000, +}; + +#ifdef __cplusplus +extern "C" { +#endif + +/* ion_client + * An ION client is an object or an entity that needs to use the service of + * ION and has unique address space. ion_client is an identifier of an ION + * client and it represents the ION client. + * All operations on ION needs a valid ion_client value and it can be obtained + * by ion_client_create(). + */ +typedef int ion_client; + +/* ion_buffer + * An identifier of a buffer allocated from ION. You must obtain to access + * a buffer allocated from ION. If you have an effective ion_buffer, you have + * three options to work with it. + * - To access the buffer, you can request an address (user virtual address) + * of the buffer with ion_map(). + * - To pass the buffer to the kernel, you can pass the ion_buffer to the + * kernel driver directly, if the kernel driver can work with ION. + * - To pass the buffer to other processes, you can pass the ion_buffer to + * other processes through RPC machanism such as socket communication or + * Android Binder because ion_buffer is actually an open file descripotor + * of the current process. + */ +typedef int ion_buffer; + +/* ion_client_create() + * @RETURN: new ion_client. + * netative value if creating new ion_client is failed. + * + * A call to ion_client_create() must be paired with ion_client_destroy(), + * symmetrically. ion_client_destroy() needs a valid ion_client that + * is returned by ion_client_create(). + */ +ion_client ion_client_create(void); + +/* ion_client_destroy() + * @client: An ion_client value to remove. + */ +void ion_client_destroy(ion_client client); + +/* ion_alloc() - Allocates new buffer from ION. + * @client: A valid ion_client value returned by ion_client_create(). + * @len: Size of a buffer required in bytes. + * @align: Alignment requirements of @len and the start address of the allocated + * buffer. If the @len is not aligned by @align, ION allocates a buffer + * that is aligned by @align and the size of the buffer will be larger + * than @len. + * @flags: Additional requirements about buffer. ION_HEAP_SYSTEM_CONTIG_MASK + * for allocating physically contiguous buffer and ION_HEAP_SYSTEM_MASK + * for virtually contiguous buffer. You can combine those flags or + * simply give -1(0xFFFFFFFF) if you do not care about the contiguouty + * of the buffer. + * @RETURN: An ion_buffer that represents the buffer allocated. It is only + * unique in the context of the given client, @client. + * -error if the allocation failed. + * See the description of ion_buffer above for detailed information. + */ +ion_buffer ion_alloc(ion_client client, size_t len, size_t align, + unsigned int flags); + +/* ion_free() - Frees an existing buffer that is allocated by ION + * @buffer: An ion_buffer of the buffer to be released. + */ +void ion_free(ion_buffer buffer); + +/* ion_map() - Obtains a virtual address of the buffer identied by @buffer + * @buffer: The buffer to map. The virtual address returned is allocated by the + * kernel. + * @len: The size of the buffer to map. This must not exceed the size of the + * buffer represented by @fd_buf. Thus you need to know the size of it + * before calling this function. If @len is less than the size of the + * buffer, this function just map just the size requested (@len) not the + * entire buffer. + * @offset: How many pages will be ignored while mapping.@offset number of + * pages from the start of the buffer will not be mapped. + * @RETURN: The start virtual addres mapped. + * MAP_FAILED if mapping fails. + * + * Note that @len + (@offset * PAGE_SIZE) must not exceed the size of the + * buffer. + */ +void *ion_map(ion_buffer buffer, size_t len, off_t offset); + +/* ion_unmap() - Frees the buffer mapped by ion_map() + * @addr: The address returned by ion_map(). + * @len: The size of the buffer mapped by ion_map(). + * @RETURN: 0 on success, and -1 on failure. + * errno is also set on failure. + */ +int ion_unmap(void *addr, size_t len); + +/* ion_msync() - Makes sure that data in the buffer are visible to H/W peri. + * @client: A valid ion_client value returned by ion_client_create(). + * @buffer: The buffer to perform ion_msync(). + * @flags: Direction of access of H/W peri and CPU. See the description of + * ION_MSYNC_FLAGS. + * @size: Size to ion_msync() in bytes. + * @offset: Where ion_msync() start in @buffer, size in bytes. + * @RETURN: 0 if successful. -error, otherwise. + * + * Note that @offset + @size must not exceed the size of @buffer. + */ +int ion_msync(ion_client client, ion_buffer buffer, long flags, + size_t size, off_t offset); + +#ifdef __cplusplus +} +#endif +#endif /* _LIB_ION_H_ */ diff --git a/exynos5/hal/include/jpeg_api.h b/exynos5/hal/include/jpeg_api.h new file mode 100644 index 0000000..f2685e1 --- /dev/null +++ b/exynos5/hal/include/jpeg_api.h @@ -0,0 +1,121 @@ +#ifndef __JPEG_API_H__ +#define __JPEG_API_H__ + +#define JPEG_DRIVER_NAME "/dev/s5p-jpeg" + +#define MAX_JPEG_WIDTH 3264 +#define MAX_JPEG_HEIGHT 2448 + +#define MAX_JPEG_RES (MAX_JPEG_WIDTH * MAX_JPEG_HEIGHT) + +#define JPEG_STREAM_BUF_SIZE MAX_JPEG_RES +#define JPEG_FRAME_BUF_SIZE (MAX_JPEG_RES * 3) + +#define JPEG_TOTAL_BUF_SIZE (JPEG_STREAM_BUF_SIZE + JPEG_FRAME_BUF_SIZE) + +#define JPEG_IOCTL_MAGIC 'J' + +#define IOCTL_JPEG_DEC_EXE _IO(JPEG_IOCTL_MAGIC, 1) +#define IOCTL_JPEG_ENC_EXE _IO(JPEG_IOCTL_MAGIC, 2) +#define IOCTL_GET_DEC_IN_BUF _IO(JPEG_IOCTL_MAGIC, 3) +#define IOCTL_GET_DEC_OUT_BUF _IO(JPEG_IOCTL_MAGIC, 4) +#define IOCTL_GET_ENC_IN_BUF _IO(JPEG_IOCTL_MAGIC, 5) +#define IOCTL_GET_ENC_OUT_BUF _IO(JPEG_IOCTL_MAGIC, 6) +#define IOCTL_SET_DEC_PARAM _IO(JPEG_IOCTL_MAGIC, 7) +#define IOCTL_SET_ENC_PARAM _IO(JPEG_IOCTL_MAGIC, 8) + +enum jpeg_ret_type{ + JPEG_FAIL, + JPEG_OK, + JPEG_ENCODE_FAIL, + JPEG_ENCODE_OK, + JPEG_DECODE_FAIL, + JPEG_DECODE_OK, + JPEG_OUT_OF_MEMORY, + JPEG_UNKNOWN_ERROR +}; + +enum jpeg_img_quality_level { + QUALITY_LEVEL_1 = 0, /* high */ + QUALITY_LEVEL_2, + QUALITY_LEVEL_3, + QUALITY_LEVEL_4, /* low */ +}; + +/* raw data image format */ +enum jpeg_frame_format { + YUV_422, /* decode output, encode input */ + YUV_420, /* decode output, encode output */ + RGB_565, /* encode input */ +}; + +/* jpeg data format */ +enum jpeg_stream_format { + JPEG_422, /* decode input, encode output */ + JPEG_420, /* decode input, encode output */ + JPEG_444, /* decode input*/ + JPEG_GRAY, /* decode input*/ + JPEG_RESERVED, +}; + +enum jpeg_test_mode { + encode_mode, + decode_mode, +}; + +struct jpeg_dec_param { + unsigned int width; + unsigned int height; + unsigned int size; + enum jpeg_stream_format in_fmt; + enum jpeg_frame_format out_fmt; +}; + +struct jpeg_enc_param { + unsigned int width; + unsigned int height; + unsigned int size; + enum jpeg_frame_format in_fmt; + enum jpeg_stream_format out_fmt; + enum jpeg_img_quality_level quality; +}; + +struct jpeg_args{ + char *in_buf; + unsigned int in_cookie; + unsigned int in_buf_size; + char *out_buf; + unsigned int out_cookie; + unsigned int out_buf_size; + char *mmapped_addr; + struct jpeg_dec_param *dec_param; + struct jpeg_enc_param *enc_param; +}; + +struct jpeg_lib { + int jpeg_fd; + struct jpeg_args args; +}; + +#ifdef __cplusplus +extern "C" { +#endif +int api_jpeg_decode_init(); +int api_jpeg_encode_init(); +int api_jpeg_decode_deinit(int dev_fd); +int api_jpeg_encode_deinit(int dev_fd); +void *api_jpeg_get_decode_in_buf(int dev_fd, unsigned int size); +void *api_jpeg_get_encode_in_buf(int dev_fd, unsigned int size); +void *api_jpeg_get_decode_out_buf(int dev_fd); +void *api_jpeg_get_encode_out_buf(int dev_fd); +void api_jpeg_set_decode_param(struct jpeg_dec_param *param); +void api_jpeg_set_encode_param(struct jpeg_enc_param *param); +enum jpeg_ret_type api_jpeg_decode_exe(int dev_fd, + struct jpeg_dec_param *dec_param); +enum jpeg_ret_type api_jpeg_encode_exe(int dev_fd, + struct jpeg_enc_param *enc_param); +#ifdef __cplusplus +} +#endif + +#endif//__JPEG_API_H__ diff --git a/exynos5/hal/include/jpeg_hal.h b/exynos5/hal/include/jpeg_hal.h new file mode 100644 index 0000000..4d9c160 --- /dev/null +++ b/exynos5/hal/include/jpeg_hal.h @@ -0,0 +1,135 @@ +/* + * Copyright@ Samsung Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "videodev2.h" + +#define JPEG_DEC_NODE "/dev/video11" +#define JPEG_ENC_NODE "/dev/video12" + +#define JPEG_MAX_PLANE_CNT 3 +#define JPEG_DEC_OUT_BYTE_ALIGN 8 + +//#define JPEG_PERF_MEAS + +#ifdef JPEG_PERF_MEAS +#define JPEG_PERF_DEFINE(n) \ + struct timeval time_start_##n, time_stop_##n; unsigned long log_time_##n = 0; + +#define JPEG_PERF_START(n) \ + gettimeofday(&time_start_##n, NULL); + +#define JPEG_PERF_END(n) \ + gettimeofday(&time_stop_##n, NULL); log_time_##n = measure_time(&time_start_##n, &time_stop_##n); + +#define JPEG_PERF(n) \ + log_time_##n +#else +#define JPEG_PERF_DEFINE(n) +#define JPEG_PERF_START(n) +#define JPEG_PERF_END(n) +#define JPEG_PERF(n) +#endif + +enum jpeg_ret_type { + JPEG_FAIL, + JPEG_OK, + JPEG_ENCODE_FAIL, + JPEG_ENCODE_OK, + JPEG_DECODE_FAIL, + JPEG_DECODE_OK, + JPEG_OUT_OF_MEMORY, + JPEG_UNKNOWN_ERROR +}; + +enum jpeg_quality_level { + QUALITY_LEVEL_1 = 0, /* high */ + QUALITY_LEVEL_2, + QUALITY_LEVEL_3, + QUALITY_LEVEL_4, /* low */ +}; + +enum jpeg_mode { + JPEG_ENCODE, + JPEG_DECODE +}; + +struct jpeg_buf { + int num_planes; + void *start[JPEG_MAX_PLANE_CNT]; + int length[JPEG_MAX_PLANE_CNT]; +}; + +struct jpeg_buf_info { + int num_planes; + enum v4l2_memory memory; + enum v4l2_buf_type buf_type; + int reserved[4]; +}; + +struct jpeg_pixfmt { + int in_fmt; + int out_fmt; + int reserved[4]; +}; + +struct jpeg_config { + enum jpeg_mode mode; + enum jpeg_quality_level enc_qual; + + int width; + int height; + + int num_planes; + + int scaled_width; + int scaled_height; + + int sizeJpeg; + + union { + struct jpeg_pixfmt enc_fmt; + struct jpeg_pixfmt dec_fmt; + } pix; + + int reserved[8]; +}; + +#ifdef __cplusplus +extern "C" { +#endif +int jpeghal_dec_init(); +int jpeghal_enc_init(); + +int jpeghal_dec_setconfig(int fd, struct jpeg_config *config); +int jpeghal_enc_setconfig(int fd, struct jpeg_config *config); +int jpeghal_dec_getconfig(int fd, struct jpeg_config *config); +int jpeghal_enc_getconfig(int fd, struct jpeg_config *config); + +int jpeghal_set_inbuf(int fd, struct jpeg_buf *buf); +int jpeghal_set_outbuf(int fd, struct jpeg_buf *buf); + +int jpeghal_dec_exe(int fd, struct jpeg_buf *in_buf, struct jpeg_buf *out_buf); +int jpeghal_enc_exe(int fd, struct jpeg_buf *in_buf, struct jpeg_buf *out_buf); + +int jpeghal_deinit(int fd, struct jpeg_buf *in_buf, struct jpeg_buf *out_buf); + +int jpeghal_s_ctrl(int fd, int cid, int value); +int jpeghal_g_ctrl(int fd, int id); + +unsigned long measure_time(struct timeval *start, struct timeval *stop); +#ifdef __cplusplus +} +#endif diff --git a/exynos5/hal/include/malisw/arm_cstd/arm_cstd.h b/exynos5/hal/include/malisw/arm_cstd/arm_cstd.h new file mode 100644 index 0000000..61520b5 --- /dev/null +++ b/exynos5/hal/include/malisw/arm_cstd/arm_cstd.h @@ -0,0 +1,469 @@ +/* + * + * (C) COPYRIGHT 2007-2011 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + + + +/** + * @addtogroup malisw + * @{ + */ + +/* ============================================================================ + Description +============================================================================ */ +/** + * @defgroup arm_cstd_coding_standard ARM C standard types and constants + * The common files are a set of standard headers which are used by all parts + * of this development, describing types, and generic constants. + * + * Files in group: + * - arm_cstd.h + * - arm_cstd_compilers.h + * - arm_cstd_types.h + * - arm_cstd_types_rvct.h + * - arm_cstd_types_gcc.h + * - arm_cstd_types_msvc.h + * - arm_cstd_pack_push.h + * - arm_cstd_pack_pop.h + */ + +/** + * @addtogroup arm_cstd_coding_standard + * @{ + */ + +#ifndef _ARM_CSTD_ +#define _ARM_CSTD_ + +/* ============================================================================ + Import standard C99 types +============================================================================ */ +#include "arm_cstd_compilers.h" +#include "arm_cstd_types.h" + +/* ============================================================================ + Min and Max Values +============================================================================ */ +#if !defined(INT8_MAX) + #define INT8_MAX ((int8_t) 0x7F) +#endif +#if !defined(INT8_MIN) + #define INT8_MIN (-INT8_MAX - 1) +#endif + +#if !defined(INT16_MAX) + #define INT16_MAX ((int16_t)0x7FFF) +#endif +#if !defined(INT16_MIN) + #define INT16_MIN (-INT16_MAX - 1) +#endif + +#if !defined(INT32_MAX) + #define INT32_MAX ((int32_t)0x7FFFFFFF) +#endif +#if !defined(INT32_MIN) + #define INT32_MIN (-INT32_MAX - 1) +#endif + +#if !defined(INT64_MAX) + #define INT64_MAX ((int64_t)0x7FFFFFFFFFFFFFFFLL) +#endif +#if !defined(INT64_MIN) + #define INT64_MIN (-INT64_MAX - 1) +#endif + +#if !defined(UINT8_MAX) + #define UINT8_MAX ((uint8_t) 0xFF) +#endif + +#if !defined(UINT16_MAX) + #define UINT16_MAX ((uint16_t)0xFFFF) +#endif + +#if !defined(UINT32_MAX) + #define UINT32_MAX ((uint32_t)0xFFFFFFFF) +#endif + +#if !defined(UINT64_MAX) + #define UINT64_MAX ((uint64_t)0xFFFFFFFFFFFFFFFFULL) +#endif + +/* fallbacks if limits.h wasn't available */ +#if !defined(UCHAR_MAX) + #define UCHAR_MAX ((unsigned char)~0U) +#endif + +#if !defined(SCHAR_MAX) + #define SCHAR_MAX ((signed char)(UCHAR_MAX >> 1)) +#endif +#if !defined(SCHAR_MIN) + #define SCHAR_MIN ((signed char)(-SCHAR_MAX - 1)) +#endif + +#if !defined(USHRT_MAX) + #define USHRT_MAX ((unsigned short)~0U) +#endif + +#if !defined(SHRT_MAX) + #define SHRT_MAX ((signed short)(USHRT_MAX >> 1)) +#endif +#if !defined(SHRT_MIN) + #define SHRT_MIN ((signed short)(-SHRT_MAX - 1)) +#endif + +#if !defined(UINT_MAX) + #define UINT_MAX ((unsigned int)~0U) +#endif + +#if !defined(INT_MAX) + #define INT_MAX ((signed int)(UINT_MAX >> 1)) +#endif +#if !defined(INT_MIN) + #define INT_MIN ((signed int)(-INT_MAX - 1)) +#endif + +#if !defined(ULONG_MAX) + #define ULONG_MAX ((unsigned long)~0UL) +#endif + +#if !defined(LONG_MAX) + #define LONG_MAX ((signed long)(ULONG_MAX >> 1)) +#endif +#if !defined(LONG_MIN) + #define LONG_MIN ((signed long)(-LONG_MAX - 1)) +#endif + +#if !defined(ULLONG_MAX) + #define ULLONG_MAX ((unsigned long long)~0ULL) +#endif + +#if !defined(LLONG_MAX) + #define LLONG_MAX ((signed long long)(ULLONG_MAX >> 1)) +#endif +#if !defined(LLONG_MIN) + #define LLONG_MIN ((signed long long)(-LLONG_MAX - 1)) +#endif + +#if !defined(SIZE_MAX) + #if 1 == CSTD_CPU_32BIT + #define SIZE_MAX UINT32_MAX + #elif 1 == CSTD_CPU_64BIT + #define SIZE_MAX UINT64_MAX + #endif +#endif + +/* ============================================================================ + Keywords +============================================================================ */ +/* Portable keywords. */ + +#if !defined(CONST) +/** + * @hideinitializer + * Variable is a C @c const, which can be made non-const for testing purposes. + */ + #define CONST const +#endif + +#if !defined(STATIC) +/** + * @hideinitializer + * Variable is a C @c static, which can be made non-static for testing + * purposes. + */ + #define STATIC static +#endif + +/** + * Specifies a function as being exported outside of a logical module. + */ +#define PUBLIC + +/** + * @def PROTECTED + * Specifies a a function which is internal to an logical module, but which + * should not be used outside of that module. This cannot be enforced by the + * compiler, as a module is typically more than one translation unit. + */ +#define PROTECTED + +/** + * Specify an assertion value which is evaluated at compile time. Recommended + * usage is specification of a @c static @c INLINE function containing all of + * the assertions thus: + * + * @code + * static INLINE [module]_compile_time_assertions( void ) + * { + * COMPILE_TIME_ASSERT( sizeof(uintptr_t) == sizeof(intptr_t) ); + * } + * @endcode + * + * @note Use @c static not @c STATIC. We never want to turn off this @c static + * specification for testing purposes. + */ +#define CSTD_COMPILE_TIME_ASSERT( expr ) \ + do { switch(0){case 0: case (expr):;} } while( FALSE ) + +/** + * @hideinitializer + * @deprecated Prefered form is @c CSTD_UNUSED + * Function-like macro for suppressing unused variable warnings. Where possible + * such variables should be removed; this macro is present for cases where we + * much support API backwards compatibility. + */ +#define UNUSED( x ) ((void)(x)) + +/** + * @hideinitializer + * Function-like macro for suppressing unused variable warnings. Where possible + * such variables should be removed; this macro is present for cases where we + * much support API backwards compatibility. + */ +#define CSTD_UNUSED( x ) ((void)(x)) + +/** + * @hideinitializer + * Function-like macro for use where "no behavior" is desired. This is useful + * when compile time macros turn a function-like macro in to a no-op, but + * where having no statement is otherwise invalid. + */ +#define CSTD_NOP( ... ) ((void)#__VA_ARGS__) + +/** + * @hideinitializer + * Function-like macro for converting a pointer in to a u64 for storing into + * an external data structure. This is commonly used when pairing a 32-bit + * CPU with a 64-bit peripheral, such as a Midgard GPU. C's type promotion + * is complex and a straight cast does not work reliably as pointers are + * often considered as signed. + */ +#define CSTD_PTR_TO_U64( x ) ((uint64_t)((uintptr_t)(x))) + +/** + * @hideinitializer + * Function-like macro for stringizing a single level macro. + * @code + * #define MY_MACRO 32 + * CSTD_STR1( MY_MACRO ) + * > "MY_MACRO" + * @endcode + */ +#define CSTD_STR1( x ) #x + +/** + * @hideinitializer + * Function-like macro for stringizing a macro's value. This should not be used + * if the macro is defined in a way which may have no value; use the + * alternative @c CSTD_STR2N macro should be used instead. + * @code + * #define MY_MACRO 32 + * CSTD_STR2( MY_MACRO ) + * > "32" + * @endcode + */ +#define CSTD_STR2( x ) CSTD_STR1( x ) + +/** + * @hideinitializer + * Utility function for stripping the first character off a string. + */ +static INLINE char* arm_cstd_strstrip( char * string ) +{ + return ++string; +} + +/** + * @hideinitializer + * Function-like macro for stringizing a single level macro where the macro + * itself may not have a value. Parameter @c a should be set to any single + * character which is then stripped by the macro via an inline function. This + * should only be used via the @c CSTD_STR2N macro; for printing a single + * macro only the @c CSTD_STR1 macro is a better alternative. + * + * This macro requires run-time code to handle the case where the macro has + * no value (you can't concat empty strings in the preprocessor). + */ +#define CSTD_STR1N( a, x ) arm_cstd_strstrip( CSTD_STR1( a##x ) ) + +/** + * @hideinitializer + * Function-like macro for stringizing a two level macro where the macro itself + * may not have a value. + * @code + * #define MY_MACRO 32 + * CSTD_STR2N( MY_MACRO ) + * > "32" + * + * #define MY_MACRO 32 + * CSTD_STR2N( MY_MACRO ) + * > "32" + * @endcode + */ +#define CSTD_STR2N( x ) CSTD_STR1N( _, x ) + +/* ============================================================================ + Validate portability constructs +============================================================================ */ +static INLINE void arm_cstd_compile_time_assertions( void ) +{ + CSTD_COMPILE_TIME_ASSERT( sizeof(uint8_t) == 1 ); + CSTD_COMPILE_TIME_ASSERT( sizeof(int8_t) == 1 ); + CSTD_COMPILE_TIME_ASSERT( sizeof(uint16_t) == 2 ); + CSTD_COMPILE_TIME_ASSERT( sizeof(int16_t) == 2 ); + CSTD_COMPILE_TIME_ASSERT( sizeof(uint32_t) == 4 ); + CSTD_COMPILE_TIME_ASSERT( sizeof(int32_t) == 4 ); + CSTD_COMPILE_TIME_ASSERT( sizeof(uint64_t) == 8 ); + CSTD_COMPILE_TIME_ASSERT( sizeof(int64_t) == 8 ); + CSTD_COMPILE_TIME_ASSERT( sizeof(intptr_t) == sizeof(uintptr_t) ); + + CSTD_COMPILE_TIME_ASSERT( 1 == TRUE ); + CSTD_COMPILE_TIME_ASSERT( 0 == FALSE ); + +#if 1 == CSTD_CPU_32BIT + CSTD_COMPILE_TIME_ASSERT( sizeof(uintptr_t) == 4 ); +#elif 1 == CSTD_CPU_64BIT + CSTD_COMPILE_TIME_ASSERT( sizeof(uintptr_t) == 8 ); +#endif + +} + +/* ============================================================================ + Useful function-like macro +============================================================================ */ +/** + * @brief Return the lesser of two values. + * As a macro it may evaluate its arguments more than once. + * @see CSTD_MAX + */ +#define CSTD_MIN( x, y ) ((x) < (y) ? (x) : (y)) + +/** + * @brief Return the greater of two values. + * As a macro it may evaluate its arguments more than once. + * If called on the same two arguments as CSTD_MIN it is guaranteed to return + * the one that CSTD_MIN didn't return. This is significant for types where not + * all values are comparable e.g. NaNs in floating-point types. But if you want + * to retrieve the min and max of two values, consider using a conditional swap + * instead. + */ +#define CSTD_MAX( x, y ) ((x) < (y) ? (y) : (x)) + +/** + * @brief Clamp value @c x to within @c min and @c max inclusive. + */ +#define CSTD_CLAMP( x, min, max ) ((x)<(min) ? (min):((x)>(max) ? (max):(x))) + +/** + * Flag a cast as a reinterpretation, usually of a pointer type. + */ +#define CSTD_REINTERPRET_CAST(type) (type) + +/** + * Flag a cast as casting away const, usually of a pointer type. + */ +#define CSTD_CONST_CAST(type) (type) + +/** + * Flag a cast as a (potentially complex) value conversion, usually of a + * numerical type. + */ +#define CSTD_STATIC_CAST(type) (type) + +/* ============================================================================ + Useful bit constants +============================================================================ */ +/** + * @cond arm_cstd_utilities + */ + +/* Common bit constant values, useful in embedded programming. */ +#define F_BIT_0 ((uint32_t)0x00000001) +#define F_BIT_1 ((uint32_t)0x00000002) +#define F_BIT_2 ((uint32_t)0x00000004) +#define F_BIT_3 ((uint32_t)0x00000008) +#define F_BIT_4 ((uint32_t)0x00000010) +#define F_BIT_5 ((uint32_t)0x00000020) +#define F_BIT_6 ((uint32_t)0x00000040) +#define F_BIT_7 ((uint32_t)0x00000080) +#define F_BIT_8 ((uint32_t)0x00000100) +#define F_BIT_9 ((uint32_t)0x00000200) +#define F_BIT_10 ((uint32_t)0x00000400) +#define F_BIT_11 ((uint32_t)0x00000800) +#define F_BIT_12 ((uint32_t)0x00001000) +#define F_BIT_13 ((uint32_t)0x00002000) +#define F_BIT_14 ((uint32_t)0x00004000) +#define F_BIT_15 ((uint32_t)0x00008000) +#define F_BIT_16 ((uint32_t)0x00010000) +#define F_BIT_17 ((uint32_t)0x00020000) +#define F_BIT_18 ((uint32_t)0x00040000) +#define F_BIT_19 ((uint32_t)0x00080000) +#define F_BIT_20 ((uint32_t)0x00100000) +#define F_BIT_21 ((uint32_t)0x00200000) +#define F_BIT_22 ((uint32_t)0x00400000) +#define F_BIT_23 ((uint32_t)0x00800000) +#define F_BIT_24 ((uint32_t)0x01000000) +#define F_BIT_25 ((uint32_t)0x02000000) +#define F_BIT_26 ((uint32_t)0x04000000) +#define F_BIT_27 ((uint32_t)0x08000000) +#define F_BIT_28 ((uint32_t)0x10000000) +#define F_BIT_29 ((uint32_t)0x20000000) +#define F_BIT_30 ((uint32_t)0x40000000) +#define F_BIT_31 ((uint32_t)0x80000000) + +/* Common 2^n size values, useful in embedded programming. */ +#define C_SIZE_1B ((uint32_t)0x00000001) +#define C_SIZE_2B ((uint32_t)0x00000002) +#define C_SIZE_4B ((uint32_t)0x00000004) +#define C_SIZE_8B ((uint32_t)0x00000008) +#define C_SIZE_16B ((uint32_t)0x00000010) +#define C_SIZE_32B ((uint32_t)0x00000020) +#define C_SIZE_64B ((uint32_t)0x00000040) +#define C_SIZE_128B ((uint32_t)0x00000080) +#define C_SIZE_256B ((uint32_t)0x00000100) +#define C_SIZE_512B ((uint32_t)0x00000200) +#define C_SIZE_1KB ((uint32_t)0x00000400) +#define C_SIZE_2KB ((uint32_t)0x00000800) +#define C_SIZE_4KB ((uint32_t)0x00001000) +#define C_SIZE_8KB ((uint32_t)0x00002000) +#define C_SIZE_16KB ((uint32_t)0x00004000) +#define C_SIZE_32KB ((uint32_t)0x00008000) +#define C_SIZE_64KB ((uint32_t)0x00010000) +#define C_SIZE_128KB ((uint32_t)0x00020000) +#define C_SIZE_256KB ((uint32_t)0x00040000) +#define C_SIZE_512KB ((uint32_t)0x00080000) +#define C_SIZE_1MB ((uint32_t)0x00100000) +#define C_SIZE_2MB ((uint32_t)0x00200000) +#define C_SIZE_4MB ((uint32_t)0x00400000) +#define C_SIZE_8MB ((uint32_t)0x00800000) +#define C_SIZE_16MB ((uint32_t)0x01000000) +#define C_SIZE_32MB ((uint32_t)0x02000000) +#define C_SIZE_64MB ((uint32_t)0x04000000) +#define C_SIZE_128MB ((uint32_t)0x08000000) +#define C_SIZE_256MB ((uint32_t)0x10000000) +#define C_SIZE_512MB ((uint32_t)0x20000000) +#define C_SIZE_1GB ((uint32_t)0x40000000) +#define C_SIZE_2GB ((uint32_t)0x80000000) + +/** + * @endcond + */ + +/** + * @} + */ + +/** + * @} + */ + +#endif /* End (_ARM_CSTD_) */ diff --git a/exynos5/hal/include/malisw/arm_cstd/arm_cstd_compilers.h b/exynos5/hal/include/malisw/arm_cstd/arm_cstd_compilers.h new file mode 100644 index 0000000..0dcb5e2 --- /dev/null +++ b/exynos5/hal/include/malisw/arm_cstd/arm_cstd_compilers.h @@ -0,0 +1,565 @@ +/* + * + * (C) COPYRIGHT 2005-2011 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + + + +#ifndef _ARM_CSTD_COMPILERS_H_ +#define _ARM_CSTD_COMPILERS_H_ + +/* ============================================================================ + Document default definitions - assuming nothing set at this point. +============================================================================ */ +/** + * @addtogroup arm_cstd_coding_standard + * @{ + */ + +/** + * @hideinitializer + * Defined with value of 1 if toolchain is Microsoft Visual Studio, 0 + * otherwise. + */ +#define CSTD_TOOLCHAIN_MSVC 0 + +/** + * @hideinitializer + * Defined with value of 1 if toolchain is the GNU Compiler Collection, 0 + * otherwise. + */ +#define CSTD_TOOLCHAIN_GCC 0 + +/** + * @hideinitializer + * Defined with value of 1 if toolchain is ARM RealView Compiler Tools, 0 + * otherwise. Note - if running RVCT in GCC mode this define will be set to 0; + * @c CSTD_TOOLCHAIN_GCC and @c CSTD_TOOLCHAIN_RVCT_GCC_MODE will both be + * defined as 1. + */ +#define CSTD_TOOLCHAIN_RVCT 0 + +/** + * @hideinitializer + * Defined with value of 1 if toolchain is ARM RealView Compiler Tools running + * in GCC mode, 0 otherwise. + */ +#define CSTD_TOOLCHAIN_RVCT_GCC_MODE 0 + +/** + * @hideinitializer + * Defined with value of 1 if processor is an x86 32-bit machine, 0 otherwise. + */ +#define CSTD_CPU_X86_32 0 + +/** + * @hideinitializer + * Defined with value of 1 if processor is an x86-64 (AMD64) machine, 0 + * otherwise. + */ +#define CSTD_CPU_X86_64 0 + +/** + * @hideinitializer + * Defined with value of 1 if processor is an ARM machine, 0 otherwise. + */ +#define CSTD_CPU_ARM 0 + +/** + * @hideinitializer + * Defined with value of 1 if processor is a MIPS machine, 0 otherwise. + */ +#define CSTD_CPU_MIPS 0 + +/** + * @hideinitializer + * Defined with value of 1 if CPU is 32-bit, 0 otherwise. + */ +#define CSTD_CPU_32BIT 0 + +/** + * @hideinitializer + * Defined with value of 1 if CPU is 64-bit, 0 otherwise. + */ +#define CSTD_CPU_64BIT 0 + +/** + * @hideinitializer + * Defined with value of 1 if processor configured as big-endian, 0 if it + * is little-endian. + */ +#define CSTD_CPU_BIG_ENDIAN 0 + +/** + * @hideinitializer + * Defined with value of 1 if operating system is a version of Windows, 0 if + * it is not. + */ +#define CSTD_OS_WINDOWS 0 + +/** + * @hideinitializer + * Defined with value of 1 if operating system is a 32-bit version of Windows, + * 0 if it is not. + */ +#define CSTD_OS_WIN32 0 + +/** + * @hideinitializer + * Defined with value of 1 if operating system is a 64-bit version of Windows, + * 0 if it is not. + */ +#define CSTD_OS_WIN64 0 + +/** + * @hideinitializer + * Defined with value of 1 if operating system is Linux, 0 if it is not. + */ +#define CSTD_OS_LINUX 0 + +/** + * @hideinitializer + * Defined with value of 1 if we are compiling Linux kernel code, 0 otherwise. + */ +#define CSTD_OS_LINUX_KERNEL 0 + +/** + * @hideinitializer + * Defined with value of 1 if operating system is a 32-bit version of Linux, + * 0 if it is not. + */ +#define CSTD_OS_LINUX32 0 + +/** + * @hideinitializer + * Defined with value of 1 if operating system is a 64-bit version of Linux, + * 0 if it is not. + */ +#define CSTD_OS_LINUX64 0 + +/** + * @hideinitializer + * Defined with value of 1 if operating system is Android, 0 if it is not. + */ +#define CSTD_OS_ANDROID 0 + +/** + * @hideinitializer + * Defined with value of 1 if we are compiling Android kernel code, 0 otherwise. + */ +#define CSTD_OS_ANDROID_KERNEL 0 + +/** + * @hideinitializer + * Defined with value of 1 if operating system is a 32-bit version of Android, + * 0 if it is not. + */ +#define CSTD_OS_ANDROID32 0 + +/** + * @hideinitializer + * Defined with value of 1 if operating system is a 64-bit version of Android, + * 0 if it is not. + */ +#define CSTD_OS_ANDROID64 0 + +/** + * @hideinitializer + * Defined with value of 1 if operating system is a version of Apple OS, + * 0 if it is not. + */ +#define CSTD_OS_APPLEOS 0 + +/** + * @hideinitializer + * Defined with value of 1 if operating system is a 32-bit version of Apple OS, + * 0 if it is not. + */ +#define CSTD_OS_APPLEOS32 0 + +/** + * @hideinitializer + * Defined with value of 1 if operating system is a 64-bit version of Apple OS, + * 0 if it is not. + */ +#define CSTD_OS_APPLEOS64 0 + +/** + * @def CSTD_OS_SYMBIAN + * @hideinitializer + * Defined with value of 1 if operating system is Symbian, 0 if it is not. + */ +#define CSTD_OS_SYMBIAN 0 + +/** + * @def CSTD_OS_NONE + * @hideinitializer + * Defined with value of 1 if there is no operating system (bare metal), 0 + * otherwise + */ +#define CSTD_OS_NONE 0 + +/* ============================================================================ + Determine the compiler in use +============================================================================ */ +#if defined(_MSC_VER) + #undef CSTD_TOOLCHAIN_MSVC + #define CSTD_TOOLCHAIN_MSVC 1 + +#elif defined(__GNUC__) + #undef CSTD_TOOLCHAIN_GCC + #define CSTD_TOOLCHAIN_GCC 1 + + /* Detect RVCT pretending to be GCC. */ + #if defined(__ARMCC_VERSION) + #undef CSTD_TOOLCHAIN_RVCT_GCC_MODE + #define CSTD_TOOLCHAIN_RVCT_GCC_MODE 1 + #endif + +#elif defined(__ARMCC_VERSION) + #undef CSTD_TOOLCHAIN_RVCT + #define CSTD_TOOLCHAIN_RVCT 1 + +#else + #warning "Unsupported or unknown toolchain" + +#endif + +/* ============================================================================ + Determine the processor +============================================================================ */ +#if 1 == CSTD_TOOLCHAIN_MSVC + #if defined(_M_IX86) + #undef CSTD_CPU_X86_32 + #define CSTD_CPU_X86_32 1 + + #elif defined(_M_X64) || defined(_M_AMD64) + #undef CSTD_CPU_X86_64 + #define CSTD_CPU_X86_64 1 + + #elif defined(_M_ARM) + #undef CSTD_CPU_ARM + #define CSTD_CPU_ARM 1 + + #elif defined(_M_MIPS) + #undef CSTD_CPU_MIPS + #define CSTD_CPU_MIPS 1 + + #else + #warning "Unsupported or unknown host CPU for MSVC tools" + + #endif + +#elif 1 == CSTD_TOOLCHAIN_GCC + #if defined(__amd64__) + #undef CSTD_CPU_X86_64 + #define CSTD_CPU_X86_64 1 + + #elif defined(__i386__) + #undef CSTD_CPU_X86_32 + #define CSTD_CPU_X86_32 1 + + #elif defined(__arm__) + #undef CSTD_CPU_ARM + #define CSTD_CPU_ARM 1 + + #elif defined(__mips__) + #undef CSTD_CPU_MIPS + #define CSTD_CPU_MIPS 1 + + #else + #warning "Unsupported or unknown host CPU for GCC tools" + + #endif + +#elif 1 == CSTD_TOOLCHAIN_RVCT + #undef CSTD_CPU_ARM + #define CSTD_CPU_ARM 1 + +#else + #warning "Unsupported or unknown toolchain" + +#endif + +/* ============================================================================ + Determine the Processor Endianness +============================================================================ */ + +#if ((1 == CSTD_CPU_X86_32) || (1 == CSTD_CPU_X86_64)) + /* Note: x86 and x86-64 are always little endian, so leave at default. */ + +#elif 1 == CSTD_TOOLCHAIN_RVCT + #if defined(__BIG_ENDIAN) + #undef CSTD_ENDIAN_BIG + #define CSTD_ENDIAN_BIG 1 + #endif + +#elif ((1 == CSTD_TOOLCHAIN_GCC) && (1 == CSTD_CPU_ARM)) + #if defined(__ARMEB__) + #undef CSTD_ENDIAN_BIG + #define CSTD_ENDIAN_BIG 1 + #endif + +#elif ((1 == CSTD_TOOLCHAIN_GCC) && (1 == CSTD_CPU_MIPS)) + #if defined(__MIPSEB__) + #undef CSTD_ENDIAN_BIG + #define CSTD_ENDIAN_BIG 1 + #endif + +#elif 1 == CSTD_TOOLCHAIN_MSVC + /* Note: Microsoft only support little endian, so leave at default. */ + +#else + #warning "Unsupported or unknown CPU" + +#endif + +/* ============================================================================ + Determine the operating system and addressing width +============================================================================ */ +#if 1 == CSTD_TOOLCHAIN_MSVC + #if defined(_WIN32) && !defined(_WIN64) + #undef CSTD_OS_WINDOWS + #define CSTD_OS_WINDOWS 1 + #undef CSTD_OS_WIN32 + #define CSTD_OS_WIN32 1 + #undef CSTD_CPU_32BIT + #define CSTD_CPU_32BIT 1 + + #elif defined(_WIN32) && defined(_WIN64) + #undef CSTD_OS_WINDOWS + #define CSTD_OS_WINDOWS 1 + #undef CSTD_OS_WIN64 + #define CSTD_OS_WIN64 1 + #undef CSTD_CPU_64BIT + #define CSTD_CPU_64BIT 1 + + #else + #warning "Unsupported or unknown host OS for MSVC tools" + + #endif + +#elif 1 == CSTD_TOOLCHAIN_GCC + #if defined(_WIN32) && defined(_WIN64) + #undef CSTD_OS_WINDOWS + #define CSTD_OS_WINDOWS 1 + #undef CSTD_OS_WIN64 + #define CSTD_OS_WIN64 1 + #undef CSTD_CPU_64BIT + #define CSTD_CPU_64BIT 1 + + #elif defined(_WIN32) && !defined(_WIN64) + #undef CSTD_OS_WINDOWS + #define CSTD_OS_WINDOWS 1 + #undef CSTD_OS_WIN32 + #define CSTD_OS_WIN32 1 + #undef CSTD_CPU_32BIT + #define CSTD_CPU_32BIT 1 + + #elif defined(ANDROID) + #undef CSTD_OS_ANDROID + #define CSTD_OS_ANDROID 1 + + #if defined(__KERNEL__) + #undef CSTD_OS_ANDROID_KERNEL + #define CSTD_OS_ANDROID_KERNEL 1 + #endif + + #if defined(__LP64__) || defined(_LP64) + #undef CSTD_OS_ANDROID64 + #define CSTD_OS_ANDROID64 1 + #undef CSTD_CPU_64BIT + #define CSTD_CPU_64BIT 1 + #else + #undef CSTD_OS_ANDROID32 + #define CSTD_OS_ANDROID32 1 + #undef CSTD_CPU_32BIT + #define CSTD_CPU_32BIT 1 + #endif + + #elif defined(__linux) + #undef CSTD_OS_LINUX + #define CSTD_OS_LINUX 1 + + #if defined(__KERNEL__) + #undef CSTD_OS_LINUX_KERNEL + #define CSTD_OS_LINUX_KERNEL 1 + #endif + + #if defined(__LP64__) || defined(_LP64) + #undef CSTD_OS_LINUX64 + #define CSTD_OS_LINUX64 1 + #undef CSTD_CPU_64BIT + #define CSTD_CPU_64BIT 1 + #else + #undef CSTD_OS_LINUX32 + #define CSTD_OS_LINUX32 1 + #undef CSTD_CPU_32BIT + #define CSTD_CPU_32BIT 1 + #endif + + #elif defined(__APPLE__) + #undef CSTD_OS_APPLEOS + #define CSTD_OS_APPLEOS 1 + + #if defined(__LP64__) || defined(_LP64) + #undef CSTD_OS_APPLEOS64 + #define CSTD_OS_APPLEOS64 1 + #undef CSTD_CPU_64BIT + #define CSTD_CPU_64BIT 1 + #else + #undef CSTD_OS_APPLEOS32 + #define CSTD_OS_APPLEOS32 1 + #undef CSTD_CPU_32BIT + #define CSTD_CPU_32BIT 1 + #endif + + #elif defined(__SYMBIAN32__) + #undef CSTD_OS_SYMBIAN + #define CSTD_OS_SYMBIAN 1 + #undef CSTD_CPU_32BIT + #define CSTD_CPU_32BIT 1 + + #else + #undef CSTD_OS_NONE + #define CSTD_OS_NONE 1 + #undef CSTD_CPU_32BIT + #define CSTD_CPU_32BIT 1 + +#endif + +#elif 1 == CSTD_TOOLCHAIN_RVCT + + #if defined(ANDROID) + #undef CSTD_OS_ANDROID + #undef CSTD_OS_ANDROID32 + #define CSTD_OS_ANDROID 1 + #define CSTD_OS_ANDROID32 1 + + #elif defined(__linux) + #undef CSTD_OS_LINUX + #undef CSTD_OS_LINUX32 + #define CSTD_OS_LINUX 1 + #define CSTD_OS_LINUX32 1 + + #elif defined(__SYMBIAN32__) + #undef CSTD_OS_SYMBIAN + #define CSTD_OS_SYMBIAN 1 + + #else + #undef CSTD_OS_NONE + #define CSTD_OS_NONE 1 + +#endif + +#else + #warning "Unsupported or unknown host OS" + +#endif + +/* ============================================================================ + Determine the correct linker symbol Import and Export Macros +============================================================================ */ +/** + * @defgroup arm_cstd_linkage_specifiers Linkage Specifiers + * @{ + * + * This set of macros contain system-dependent linkage specifiers which + * determine the visibility of symbols across DLL boundaries. A header for a + * particular DLL should define a set of local macros derived from these, + * and should not use these macros to decorate functions directly as there may + * be multiple DLLs being used. + * + * These DLL library local macros should be (with appropriate library prefix) + * [MY_LIBRARY]_API, [MY_LIBRARY]_IMPL, and + * [MY_LIBRARY]_LOCAL. + * + * - [MY_LIBRARY]_API should be use to decorate the function + * declarations in the header. It should be defined as either + * @c CSTD_LINK_IMPORT or @c CSTD_LINK_EXPORT, depending whether the + * current situation is a compile of the DLL itself (use export) or a + * compile of an external user of the DLL (use import). + * - [MY_LIBRARY]_IMPL should be defined as @c CSTD_LINK_IMPL + * and should be used to decorate the definition of functions in the C + * file. + * - [MY_LIBRARY]_LOCAL should be used to decorate function + * declarations which are exported across translation units within the + * DLL, but which are not exported outside of the DLL boundary. + * + * Functions which are @c static in either a C file or in a header file do not + * need any form of linkage decoration, and should therefore have no linkage + * macro applied to them. + */ + +/** + * @def CSTD_LINK_IMPORT + * Specifies a function as being imported to a translation unit across a DLL + * boundary. + */ + +/** + * @def CSTD_LINK_EXPORT + * Specifies a function as being exported across a DLL boundary by a + * translation unit. + */ + +/** + * @def CSTD_LINK_IMPL + * Specifies a function which will be exported across a DLL boundary as + * being implemented by a translation unit. + */ + +/** + * @def CSTD_LINK_LOCAL + * Specifies a function which is internal to a DLL, and which should not be + * exported outside of it. + */ + +/** + * @} + */ + +#if 1 == CSTD_OS_LINUX + #define CSTD_LINK_IMPORT __attribute__((visibility("default"))) + #define CSTD_LINK_EXPORT __attribute__((visibility("default"))) + #define CSTD_LINK_IMPL __attribute__((visibility("default"))) + #define CSTD_LINK_LOCAL __attribute__((visibility("hidden"))) + +#elif 1 == CSTD_OS_WINDOWS + #define CSTD_LINK_IMPORT __declspec(dllimport) + #define CSTD_LINK_EXPORT __declspec(dllexport) + #define CSTD_LINK_IMPL __declspec(dllexport) + #define CSTD_LINK_LOCAL + +#elif 1 == CSTD_OS_SYMBIAN + #define CSTD_LINK_IMPORT IMPORT_C + #define CSTD_LINK_EXPORT IMPORT_C + #define CSTD_LINK_IMPL EXPORT_C + #define CSTD_LINK_LOCAL + +#elif 1 == CSTD_OS_APPLEOS + #define CSTD_LINK_IMPORT __attribute__((visibility("default"))) + #define CSTD_LINK_EXPORT __attribute__((visibility("default"))) + #define CSTD_LINK_IMPL __attribute__((visibility("default"))) + #define CSTD_LINK_LOCAL __attribute__((visibility("hidden"))) + +#else /* CSTD_OS_NONE */ + #define CSTD_LINK_IMPORT + #define CSTD_LINK_EXPORT + #define CSTD_LINK_IMPL + #define CSTD_LINK_LOCAL + +#endif + +/** + * @} + */ + +#endif /* End (_ARM_CSTD_COMPILERS_H_) */ diff --git a/exynos5/hal/include/malisw/arm_cstd/arm_cstd_pack_pop.h b/exynos5/hal/include/malisw/arm_cstd/arm_cstd_pack_pop.h new file mode 100644 index 0000000..01f8fab --- /dev/null +++ b/exynos5/hal/include/malisw/arm_cstd/arm_cstd_pack_pop.h @@ -0,0 +1,22 @@ +/* + * + * (C) COPYRIGHT 2009-2011 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + + + +#ifndef _ARM_CSTD_PACK_POP_H_ +#define _ARM_CSTD_PACK_POP_H_ + +#if 1 == CSTD_TOOLCHAIN_MSVC + #include +#endif + +#endif /* End (_ARM_CSTD_PACK_POP_H_) */ diff --git a/exynos5/hal/include/malisw/arm_cstd/arm_cstd_pack_push.h b/exynos5/hal/include/malisw/arm_cstd/arm_cstd_pack_push.h new file mode 100644 index 0000000..ac1ff93 --- /dev/null +++ b/exynos5/hal/include/malisw/arm_cstd/arm_cstd_pack_push.h @@ -0,0 +1,22 @@ +/* + * + * (C) COPYRIGHT 2009-2011 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + + + +#ifndef _ARM_CSTD_PACK_PUSH_H_ +#define _ARM_CSTD_PACK_PUSH_H_ + +#if 1 == CSTD_TOOLCHAIN_MSVC + #include +#endif + +#endif /* End (_ARM_CSTD_PACK_PUSH_H_) */ diff --git a/exynos5/hal/include/malisw/arm_cstd/arm_cstd_types.h b/exynos5/hal/include/malisw/arm_cstd/arm_cstd_types.h new file mode 100644 index 0000000..2e50b57 --- /dev/null +++ b/exynos5/hal/include/malisw/arm_cstd/arm_cstd_types.h @@ -0,0 +1,28 @@ +/* + * + * (C) COPYRIGHT 2009-2011 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + + + +#ifndef _ARM_CSTD_TYPES_H_ +#define _ARM_CSTD_TYPES_H_ + +#if 1 == CSTD_TOOLCHAIN_MSVC + #include "arm_cstd_types_msvc.h" +#elif 1 == CSTD_TOOLCHAIN_GCC + #include "arm_cstd_types_gcc.h" +#elif 1 == CSTD_TOOLCHAIN_RVCT + #include "arm_cstd_types_rvct.h" +#else + #error "Toolchain not recognized" +#endif + +#endif /* End (_ARM_CSTD_TYPES_H_) */ diff --git a/exynos5/hal/include/malisw/arm_cstd/arm_cstd_types_gcc.h b/exynos5/hal/include/malisw/arm_cstd/arm_cstd_types_gcc.h new file mode 100644 index 0000000..54d06fe --- /dev/null +++ b/exynos5/hal/include/malisw/arm_cstd/arm_cstd_types_gcc.h @@ -0,0 +1,87 @@ +/* + * + * (C) COPYRIGHT 2009-2011 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + + + +#ifndef _ARM_CSTD_TYPES_GCC_H_ +#define _ARM_CSTD_TYPES_GCC_H_ + +/* ============================================================================ + Type definitions +============================================================================ */ +/* All modern versions of GCC support stdint outside of C99 Mode. */ +/* However, Linux kernel limits what headers are available! */ +#if 1 == CSTD_OS_LINUX_KERNEL + #include + #include + #include + #include + + /* Fix up any types which CSTD provdes but which Linux is missing. */ + /* Note Linux assumes pointers are "long", so this is safe. */ + #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) + typedef unsigned long uintptr_t; + #endif + typedef long intptr_t; + +#else + #include + #include + #include +#endif + +typedef uint32_t bool_t; + +#if !defined(TRUE) + #define TRUE ((bool_t)1) +#endif + +#if !defined(FALSE) + #define FALSE ((bool_t)0) +#endif + +/* ============================================================================ + Keywords +============================================================================ */ +/* Doxygen documentation for these is in the RVCT header. */ +#define ASM __asm__ + +#define INLINE __inline__ + +#define FORCE_INLINE __attribute__((__always_inline__)) __inline__ + +#define NEVER_INLINE __attribute__((__noinline__)) + +#define PURE __attribute__((__pure__)) + +#define PACKED __attribute__((__packed__)) + +/* GCC does not support pointers to UNALIGNED data, so we do not define it to + * force a compile error if this macro is used. */ + +#define RESTRICT __restrict__ + +/* RVCT in GCC mode does not support the CHECK_RESULT attribute. */ +#if 0 == CSTD_TOOLCHAIN_RVCT_GCC_MODE + #define CHECK_RESULT __attribute__((__warn_unused_result__)) +#else + #define CHECK_RESULT +#endif + +/* RVCT in GCC mode does not support the __func__ name outside of C99. */ +#if (0 == CSTD_TOOLCHAIN_RVCT_GCC_MODE) + #define CSTD_FUNC __func__ +#else + #define CSTD_FUNC __FUNCTION__ +#endif + +#endif /* End (_ARM_CSTD_TYPES_GCC_H_) */ diff --git a/exynos5/hal/include/malisw/arm_cstd/arm_cstd_types_rvct.h b/exynos5/hal/include/malisw/arm_cstd/arm_cstd_types_rvct.h new file mode 100644 index 0000000..8bae4c2 --- /dev/null +++ b/exynos5/hal/include/malisw/arm_cstd/arm_cstd_types_rvct.h @@ -0,0 +1,187 @@ +/* + * + * (C) COPYRIGHT 2009-2011 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + + + +#ifndef _ARM_CSTD_TYPES_RVCT_H_ +#define _ARM_CSTD_TYPES_RVCT_H_ + +/* ============================================================================ + Type definitions +============================================================================ */ +#include +#include + +#if 199901L <= __STDC_VERSION__ + #include +#else + typedef unsigned char uint8_t; + typedef signed char int8_t; + typedef unsigned short uint16_t; + typedef signed short int16_t; + typedef unsigned int uint32_t; + typedef signed int int32_t; + typedef unsigned __int64 uint64_t; + typedef signed __int64 int64_t; + typedef ptrdiff_t intptr_t; + typedef size_t uintptr_t; +#endif + +typedef uint32_t bool_t; + +#if !defined(TRUE) + #define TRUE ((bool_t)1) +#endif + +#if !defined(FALSE) + #define FALSE ((bool_t)0) +#endif + +/* ============================================================================ + Keywords +============================================================================ */ +/** + * @addtogroup arm_cstd_coding_standard + * @{ + */ + +/** + * @def ASM + * @hideinitializer + * Mark an assembler block. Such blocks are often compiler specific, so often + * need to be surrounded in appropriate @c ifdef and @c endif blocks + * using the relevant @c CSTD_TOOLCHAIN macro. + */ +#define ASM __asm + +/** + * @def INLINE + * @hideinitializer + * Mark a definition as something which should be inlined. This is not always + * possible on a given compiler, and may be disabled at lower optimization + * levels. + */ +#define INLINE __inline + +/** + * @def FORCE_INLINE + * @hideinitializer + * Mark a definition as something which should be inlined. This provides a much + * stronger hint to the compiler than @c INLINE, and if supported should always + * result in an inlined function being emitted. If not supported this falls + * back to using the @c INLINE definition. + */ +#define FORCE_INLINE __forceinline + +/** + * @def NEVER_INLINE + * @hideinitializer + * Mark a definition as something which should not be inlined. This provides a + * stronger hint to the compiler than the function should not be inlined, + * bypassing any heuristic rules the compiler normally applies. If not + * supported by a toolchain this falls back to being an empty macro. + */ +#define NEVER_INLINE __declspec(noinline) + +/** + * @def PURE + * @hideinitializer + * Denotes that a function's return is only dependent on its inputs, enabling + * more efficient optimizations. Falls back to an empty macro if not supported. + */ +#define PURE __pure + +/** + * @def PACKED + * @hideinitializer + * Denotes that a structure should be stored in a packed form. This macro must + * be used in conjunction with the @c arm_cstd_pack_* headers for portability: + * + * @code + * #include + * + * struct PACKED myStruct { + * ... + * }; + * + * #include + * PACKED + * @endcode + */ +#define PACKED __packed + +/** + * @def UNALIGNED + * @hideinitializer + * Denotes that a pointer points to a buffer with lower alignment than the + * natural alignment required by the C standard. This should only be used + * in extreme cases, as the emitted code is normally more efficient if memory + * is aligned. + * + * @warning This is \b NON-PORTABLE. The GNU tools are anti-unaligned pointers + * and have no support for such a construction. + */ +#define UNALIGNED __packed + +/** + * @def RESTRICT + * @hideinitializer + * Denotes that a pointer does not overlap with any other points currently in + * scope, increasing the range of optimizations which can be performed by the + * compiler. + * + * @warning Specification of @c RESTRICT is a contract between the programmer + * and the compiler. If you place @c RESTICT on buffers which do actually + * overlap the behavior is undefined, and likely to vary at different + * optimization levels.! + */ +#define RESTRICT __restrict + +/** + * @def CHECK_RESULT + * @hideinitializer + * Function attribute which causes a warning to be emitted if the compiler's + * return value is not used by the caller. Compiles to an empty macro if + * there is no supported mechanism for this check in the underlying compiler. + * + * @note At the time of writing this is only supported by GCC. RVCT does not + * support this attribute, even in GCC mode, so engineers are encouraged to + * compile their code using GCC even if primarily working with another + * compiler. + * + * @code + * CHECK_RESULT int my_func( void ); + * @endcode + */ +#define CHECK_RESULT + +/** + * @def CSTD_FUNC + * Specify the @c CSTD_FUNC macro, a portable construct containing the name of + * the current function. On most compilers it is illegal to use this macro + * outside of a function scope. If not supported by the compiler we define + * @c CSTD_FUNC as an empty string. + * + * @warning Due to the implementation of this on most modern compilers this + * expands to a magically defined "static const" variable, not a constant + * string. This makes injecting @c CSTD_FUNC directly in to compile-time + * strings impossible, so if you want to make the function name part of a + * larger string you must use a printf-like function with a @c @%s template + * which is populated with @c CSTD_FUNC + */ +#define CSTD_FUNC __FUNCTION__ + +/** + * @} + */ + +#endif /* End (_ARM_CSTD_TYPES_RVCT_H_) */ diff --git a/exynos5/hal/include/malisw/mali_malisw.h b/exynos5/hal/include/malisw/mali_malisw.h new file mode 100644 index 0000000..c19f14f --- /dev/null +++ b/exynos5/hal/include/malisw/mali_malisw.h @@ -0,0 +1,237 @@ +/* + * + * (C) COPYRIGHT 2010-2011 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + + + +#ifndef _MALISW_H_ +#define _MALISW_H_ + +#define MALI_MODULE_MALISW_MAJOR 2 +#define MALI_MODULE_MALISW_MINOR 4 + +/** + * @file mali_malisw.h + * Driver-wide include for common macros and types. + */ + +/** + * @defgroup malisw Mali software definitions and types + * @{ + */ + +#include + +#include "mali_stdtypes.h" +#include "mali_version_macros.h" + +/** @brief Gets the container object when given a pointer to a member of an object. */ +#define CONTAINER_OF(ptr, type, member) ((type *)((char *)(ptr) - offsetof(type,member))) + +/** @brief Gets the number of elements of type s in a fixed length array of s */ +#define NELEMS(s) (sizeof(s)/sizeof((s)[0])) + +/** + * @brief The lesser of two values. + * May evaluate its arguments more than once. + * @see CSTD_MIN + */ +#define MIN(x,y) CSTD_MIN(x,y) + +/** + * @brief The greater of two values. + * May evaluate its arguments more than once. + * @see CSTD_MAX + */ +#define MAX(x,y) CSTD_MAX(x,y) + +/** + * @brief Clamp value x to within min and max inclusive + * May evaluate its arguments more than once. + * @see CSTD_CLAMP + */ +#define CLAMP( x, min, max ) CSTD_CLAMP( x, min, max ) + +/** + * @brief Convert a pointer into a u64 for storing in a data structure. + * This is commonly used when pairing a 32-bit CPU with a 64-bit peripheral, + * such as a Midgard GPU. C's type promotion is complex and a straight cast + * does not work reliably as pointers are often considered as signed. + */ +#define PTR_TO_U64( x ) CSTD_PTR_TO_U64( x ) + +/** + * @name Mali library linkage specifiers + * These directly map to the cstd versions described in detail here: @ref arm_cstd_linkage_specifiers + * @{ + */ +#define MALI_IMPORT CSTD_LINK_IMPORT +#define MALI_EXPORT CSTD_LINK_EXPORT +#define MALI_IMPL CSTD_LINK_IMPL +#define MALI_LOCAL CSTD_LINK_LOCAL + +/** @brief Decorate exported function prototypes. + * + * The file containing the implementation of the function should define this to be MALI_EXPORT before including + * malisw/mali_malisw.h. + */ +#ifndef MALI_API +#define MALI_API MALI_IMPORT +#endif +/** @} */ + +/** @name Testable static functions + * @{ + * + * These macros can be used to allow functions to be static in release builds but exported from a shared library in unit + * test builds, allowing them to be tested or used to assist testing. + * + * Example mali_foo_bar.c containing the function to test: + * + * @code + * #define MALI_API MALI_EXPORT + * + * #include + * #include "mali_foo_testable_statics.h" + * + * MALI_TESTABLE_STATIC_IMPL void my_func() + * { + * //Implementation + * } + * @endcode + * + * Example mali_foo_testable_statics.h: + * + * @code + * #if 1 == MALI_UNIT_TEST + * #include + * + * MALI_TESTABLE_STATIC_API void my_func(); + * + * #endif + * @endcode + * + * Example mali_foo_tests.c: + * + * @code + * #include + * + * void my_test_func() + * { + * my_func(); + * } + * @endcode + */ + +/** @brief Decorate testable static function implementations. + * + * A header file containing a MALI_TESTABLE_STATIC_API-decorated prototype for each static function will be required + * when MALI_UNIT_TEST == 1 in order to link the function from the test. + */ +#if 1 == MALI_UNIT_TEST +#define MALI_TESTABLE_STATIC_IMPL MALI_IMPL +#else +#define MALI_TESTABLE_STATIC_IMPL static +#endif + +/** @brief Decorate testable static function prototypes. + * + * @note Prototypes should @em only be declared when MALI_UNIT_TEST == 1 + */ +#define MALI_TESTABLE_STATIC_API MALI_API +/** @} */ + +/** @name Testable local functions + * @{ + * + * These macros can be used to allow functions to be local to a shared library in release builds but be exported in unit + * test builds, allowing them to be tested or used to assist testing. + * + * Example mali_foo_bar.c containing the function to test: + * + * @code + * #define MALI_API MALI_EXPORT + * + * #include + * #include "mali_foo_bar.h" + * + * MALI_TESTABLE_LOCAL_IMPL void my_func() + * { + * //Implementation + * } + * @endcode + * + * Example mali_foo_bar.h: + * + * @code + * #include + * + * MALI_TESTABLE_LOCAL_API void my_func(); + * + * @endcode + * + * Example mali_foo_tests.c: + * + * @code + * #include + * + * void my_test_func() + * { + * my_func(); + * } + * @endcode + */ + +/** @brief Decorate testable local function implementations. + * + * This can be used to have a function normally local to the shared library except in unit test builds where it will be + * exported. + */ +#if 1 == MALI_UNIT_TEST +#define MALI_TESTABLE_LOCAL_IMPL MALI_IMPL +#else +#define MALI_TESTABLE_LOCAL_IMPL MALI_LOCAL +#endif + +/** @brief Decorate testable local function prototypes. + * + * This can be used to have a function normally local to the shared library except in unit test builds where it will be + * exported. + */ +#if 1 == MALI_UNIT_TEST +#define MALI_TESTABLE_LOCAL_API MALI_API +#else +#define MALI_TESTABLE_LOCAL_API MALI_LOCAL +#endif +/** @} */ + +/** + * Flag a cast as a reinterpretation, usually of a pointer type. + * @see CSTD_REINTERPRET_CAST + */ +#define REINTERPRET_CAST(type) CSTD_REINTERPRET_CAST(type) + +/** + * Flag a cast as casting away const, usually of a pointer type. + * @see CSTD_CONST_CAST + */ +#define CONST_CAST(type) (type) CSTD_CONST_CAST(type) + +/** + * Flag a cast as a (potentially complex) value conversion, usually of a numerical type. + * @see CSTD_STATIC_CAST + */ +#define STATIC_CAST(type) (type) CSTD_STATIC_CAST(type) + + +/** @} */ + +#endif /* _MALISW_H_ */ diff --git a/exynos5/hal/include/malisw/mali_stdtypes.h b/exynos5/hal/include/malisw/mali_stdtypes.h new file mode 100644 index 0000000..545c085 --- /dev/null +++ b/exynos5/hal/include/malisw/mali_stdtypes.h @@ -0,0 +1,210 @@ +/* + * + * (C) COPYRIGHT 2010-2011 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + + + +#ifndef _MALISW_STDTYPES_H_ +#define _MALISW_STDTYPES_H_ + +/** + * @file mali_stdtypes.h + * This file defines the standard types used by the Mali codebase. + */ + +/** + * @addtogroup malisw + * @{ + */ + +/** + * @defgroup malisw_stdtypes Mali software standard types + * + * Basic driver-wide types. + */ + +/** + * @addtogroup malisw_stdtypes + * @{ + */ + +#include "arm_cstd/arm_cstd.h" + +/** + * @name Scalar types. + * These are the scalar types used within the mali driver. + * @{ + */ +/* Note: if compiling the Linux kernel then avoid redefining these. */ +#if 0 == CSTD_OS_LINUX_KERNEL + typedef uint64_t u64; + typedef uint32_t u32; + typedef uint16_t u16; + typedef uint8_t u8; + + typedef int64_t s64; + typedef int32_t s32; + typedef int16_t s16; + typedef int8_t s8; +#endif + +typedef double f64; +typedef float f32; +typedef u16 f16; + +typedef u32 mali_fixed16_16; +/* @} */ + +/** + * @name Boolean types. + * The intended use is for bool8 to be used when storing boolean values in + * structures, casting to mali_bool to be used in code sections. + * @{ + */ +typedef bool_t mali_bool; +typedef u8 mali_bool8; + +#define MALI_FALSE FALSE +#define MALI_TRUE TRUE +/* @} */ + +/** + * @name Integer bounding values + * Maximum and minimum values for integer types + * @{ + */ +#define U64_MAX UINT64_MAX +#define U32_MAX UINT32_MAX +#define U16_MAX UINT16_MAX +#define U8_MAX UINT8_MAX + +#define S64_MAX INT64_MAX +#define S64_MIN INT64_MIN +#define S32_MAX INT32_MAX +#define S32_MIN INT32_MIN +#define S16_MAX INT16_MAX +#define S16_MIN INT16_MIN +#define S8_MAX INT8_MAX +#define S8_MIN INT8_MIN +/* @} */ + +/** + * @name GPU address types + * Types for integers which hold a GPU pointer or GPU pointer offsets. + * @{ + */ +typedef u64 mali_addr64; +typedef u32 mali_addr32; +typedef u64 mali_size64; +typedef s64 mali_offset64; +/* 32 bit offsets and sizes are always for native types and so use ptrdiff_t and size_t respectively */ +/* @} */ + +/** + * @name Mali error types + * @brief The common error type for the mali drivers + * The mali_error type, all driver error handling should be of this type unless + * it must deal with a specific APIs error type. + * @{ + */ +typedef enum +{ + /** + * @brief Common Mali errors for the entire driver + * MALI_ERROR_NONE is guaranteed to be 0. + * @{ + */ + MALI_ERROR_NONE = 0, + MALI_ERROR_OUT_OF_GPU_MEMORY, + MALI_ERROR_OUT_OF_MEMORY, + MALI_ERROR_FUNCTION_FAILED, + /* @} */ + /** + * @brief Mali errors for Client APIs to pass to EGL when creating EGLImages + * These errors must only be returned to EGL from one of the Client APIs as part of the + * (clientapi)_egl_image_interface.h + * @{ + */ + MALI_ERROR_EGLP_BAD_ACCESS, + MALI_ERROR_EGLP_BAD_PARAMETER, + /* @} */ + /** + * @brief Mali errors for the MCL module. + * These errors must only be used within the private components of the OpenCL implementation that report + * directly to API functions for cases where errors cannot be detected in the entrypoints file. They must + * not be passed between driver components. + * These are errors in the mali error space specifically for the MCL module, hence the MCLP prefix. + * @{ + */ + MALI_ERROR_MCLP_DEVICE_NOT_FOUND, + MALI_ERROR_MCLP_DEVICE_NOT_AVAILABLE, + MALI_ERROR_MCLP_COMPILER_NOT_AVAILABLE, + MALI_ERROR_MCLP_MEM_OBJECT_ALLOCATION_FAILURE, + MALI_ERROR_MCLP_PROFILING_INFO_NOT_AVAILABLE, + MALI_ERROR_MCLP_MEM_COPY_OVERLAP, + MALI_ERROR_MCLP_IMAGE_FORMAT_MISMATCH, + MALI_ERROR_MCLP_IMAGE_FORMAT_NOT_SUPPORTED, + MALI_ERROR_MCLP_BUILD_PROGRAM_FAILURE, + MALI_ERROR_MCLP_MAP_FAILURE, + MALI_ERROR_MCLP_MISALIGNED_SUB_BUFFER_OFFSET, + MALI_ERROR_MCLP_EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST, + MALI_ERROR_MCLP_INVALID_VALUE, + MALI_ERROR_MCLP_INVALID_DEVICE_TYPE, + MALI_ERROR_MCLP_INVALID_PLATFORM, + MALI_ERROR_MCLP_INVALID_DEVICE, + MALI_ERROR_MCLP_INVALID_CONTEXT, + MALI_ERROR_MCLP_INVALID_QUEUE_PROPERTIES, + MALI_ERROR_MCLP_INVALID_COMMAND_QUEUE, + MALI_ERROR_MCLP_INVALID_HOST_PTR, + MALI_ERROR_MCLP_INVALID_MEM_OBJECT, + MALI_ERROR_MCLP_INVALID_IMAGE_FORMAT_DESCRIPTOR, + MALI_ERROR_MCLP_INVALID_IMAGE_SIZE, + MALI_ERROR_MCLP_INVALID_SAMPLER, + MALI_ERROR_MCLP_INVALID_BINARY, + MALI_ERROR_MCLP_INVALID_BUILD_OPTIONS, + MALI_ERROR_MCLP_INVALID_PROGRAM, + MALI_ERROR_MCLP_INVALID_PROGRAM_EXECUTABLE, + MALI_ERROR_MCLP_INVALID_KERNEL_NAME, + MALI_ERROR_MCLP_INVALID_KERNEL_DEFINITION, + MALI_ERROR_MCLP_INVALID_KERNEL, + MALI_ERROR_MCLP_INVALID_ARG_INDEX, + MALI_ERROR_MCLP_INVALID_ARG_VALUE, + MALI_ERROR_MCLP_INVALID_ARG_SIZE, + MALI_ERROR_MCLP_INVALID_KERNEL_ARGS, + MALI_ERROR_MCLP_INVALID_WORK_DIMENSION, + MALI_ERROR_MCLP_INVALID_WORK_GROUP_SIZE, + MALI_ERROR_MCLP_INVALID_WORK_ITEM_SIZE, + MALI_ERROR_MCLP_INVALID_GLOBAL_OFFSET, + MALI_ERROR_MCLP_INVALID_EVENT_WAIT_LIST, + MALI_ERROR_MCLP_INVALID_EVENT, + MALI_ERROR_MCLP_INVALID_OPERATION, + MALI_ERROR_MCLP_INVALID_GL_OBJECT, + MALI_ERROR_MCLP_INVALID_BUFFER_SIZE, + MALI_ERROR_MCLP_INVALID_MIP_LEVEL, + MALI_ERROR_MCLP_INVALID_GLOBAL_WORK_SIZE, + /* @} */ + /** + * @brief Mali errors for the BASE module + * These errors must only be used within the private components of the Base implementation. They will not + * passed to other modules by the base driver. + * These are errors in the mali error space specifically for the BASE module, hence the BASEP prefix. + * @{ + */ + MALI_ERROR_BASEP_INVALID_FUNCTION + /* @} */ +} mali_error; +/* @} */ + +/* @} */ + +/* @} */ + +#endif /* _MALISW_STDTYPES_H_ */ diff --git a/exynos5/hal/include/malisw/mali_version_macros.h b/exynos5/hal/include/malisw/mali_version_macros.h new file mode 100644 index 0000000..e7dc43e --- /dev/null +++ b/exynos5/hal/include/malisw/mali_version_macros.h @@ -0,0 +1,243 @@ +/* + * + * (C) COPYRIGHT 2010-2011 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + + + +#ifndef _MALISW_VERSION_MACROS_H_ +#define _MALISW_VERSION_MACROS_H_ + +/** + * @file mali_version_macros.h + * Mali version control macros. + */ + +/** + * @addtogroup malisw + * @{ + */ + +/** + * @defgroup malisw_version Mali module version control + * + * This file provides a set of macros used to check a module's version. This + * version information can be used to perform compile time checks of a module's + * suitability for use with another. + * + * Module versions have both a Major and Minor value which specify the version + * of the interface only. These are defined in the following way: + * + * @li Major: This version is incremented whenever a compatibility-breaking + * change is made. For example, removing an interface function. + * @li Minor: This version is incremented whenever an interface change is made + * that does not break compatibility. For example, adding a new function to the + * interface. This value is reset to zero whenever the major number is + * incremented. + * + * When providing a driver module that will be used with this system, the public + * header must include a major and minor define of the following form: + * + * @code + * #define MALI_MODULE__MAJOR X + * #define MALI_MODULE__MINOR Y + * @endcode + * e.g. for a module CZAM with include czam/mali_czam.h + * @code + * + * #define MALI_MODULE_CZAM_MAJOR 1 + * #define MALI_MODULE_CZAM_MINOR 0 + * @endcode + * + * The version assertion macros outlined below are wrapped with a static function. + * This provides more useful error messages when the assertions fail, and allows + * the assertions to be specified adjacent to the inclusion of the module header. + * + * These macros should be used in the global scope of the file. Normal use would be: + * + * @code + * #include + * #include + * #include + * #include + * + * // This module added an enum we needed on minor 4 of major release 2 + * MALI_MODULE_ASSERT_MAJOR_EQUALS_MINOR_AT_LEAST( MODULEW, 2, 4 ) + * + * // this module really needs to be a specific version + * MALI_MODULE_ASSERT_EQUALS( MODULEX, 2, 0 ) + * + * // 1.4 has performance problems + * MALI_MODULE_ASSERT_MAXIMUM( MODULEY, 1, 3 ) + * + * // Major defines a backward compatible series of versions + * MALI_MODULE_ASSERT_MAJOR_EQUALS( MODULEZ, 1 ) + * @endcode + * + * @par Version Assertions + * + * This module provides the following compile time version assertion macros. + * + * @li #MALI_MODULE_ASSERT_MAJOR_EQUALS_MINOR_AT_LEAST + * @li #MALI_MODULE_ASSERT_MAJOR_EQUALS + * @li #MALI_MODULE_ASSERT_EQUALS + * @li #MALI_MODULE_ASSERT_MINIMUM + * @li #MALI_MODULE_ASSERT_MAXIMUM + * + * @par Limitations + * + * To allow the macros to be placed in the global scope and report more readable + * errors, they produce a static function. This makes them unsuitable for use + * within headers as the names are only unique on the name of the module under test, + * the line number of the current file, and assert type (min, max, equals, ...). + */ + +/** + * @addtogroup malisw_version + * @{ + */ + +#include "arm_cstd/arm_cstd.h" + +/** + * Private helper macro, indirection so that __LINE__ resolves correctly. + */ +#define MALIP_MODULE_ASSERT_FUNCTION_SIGNATURE2( module, type, line ) \ + static INLINE void _mali_module_##module##_version_check_##type##_##line(void) + +#define MALIP_MODULE_ASSERT_FUNCTION_SIGNATURE( module, type, line ) \ + MALIP_MODULE_ASSERT_FUNCTION_SIGNATURE2( module, type, line ) + +/** + * @hideinitializer + * This macro provides a compile time assert that a module interface that has been + * @#included in the source base has is greater than or equal to the version specified. + * + * Expected use is for cases where a module version before the requested minimum + * does not support a specific function or is missing an enum affecting the code that is + * importing the module. + * + * It should be invoked at the global scope and ideally following straight after + * the module header has been included. For example: + * + * @code + * #include + * + * MALI_MODULE_ASSERT_MINIMUM( MODULEX, 1, 3 ) + * @endcode + */ +#define MALI_MODULE_ASSERT_MINIMUM( module, major, minor ) \ + MALIP_MODULE_ASSERT_FUNCTION_SIGNATURE( module, minimum, __LINE__ ) \ + { \ + CSTD_COMPILE_TIME_ASSERT( ( ( MALI_MODULE_##module##_MAJOR << 16 ) | MALI_MODULE_##module##_MINOR ) \ + >= ( ( (major) << 16 ) | (minor) ) ); \ + } + +/** + * @hideinitializer + * This macro provides a compile time assert that a module interface that has been + * @#included in the source base is less than or equal to the version specified. + * + * Expected use is for cases where a later published minor version is found to be + * incompatible in some way after the new minor has been issued. + * + * It should be invoked at the global scope and ideally following straight after + * the module header has been included. For example: + * + * @code + * #include + * + * MALI_MODULE_ASSERT_MAXIMUM( MODULEX, 1, 3 ) + * @endcode + */ +#define MALI_MODULE_ASSERT_MAXIMUM( module, major, minor ) \ + MALIP_MODULE_ASSERT_FUNCTION_SIGNATURE( module, maximum, __LINE__ ) \ + { \ + CSTD_COMPILE_TIME_ASSERT( ( ( MALI_MODULE_##module##_MAJOR << 16 ) | MALI_MODULE_##module##_MINOR ) \ + <= ( ( (major) << 16 ) | (minor) ) ); \ + } + +/** + * @hideinitializer + * This macro provides a compile time assert that a module interface that has been + * @#included in the source base is equal to the version specified. + * + * Expected use is for cases where a specific version is known to work and other + * versions are considered to be risky. + * + * It should be invoked at the global scope and ideally following straight after + * the module header has been included. For example: + * + * @code + * #include + * + * MALI_MODULE_ASSERT_EQUALS( MODULEX, 1, 3 ) + * @endcode + */ +#define MALI_MODULE_ASSERT_EQUALS( module, major, minor ) \ + MALIP_MODULE_ASSERT_FUNCTION_SIGNATURE( module, equals, __LINE__ ) \ + { \ + CSTD_COMPILE_TIME_ASSERT( MALI_MODULE_##module##_MAJOR == major ); \ + CSTD_COMPILE_TIME_ASSERT( MALI_MODULE_##module##_MINOR == minor ); \ + } + +/** + * @hideinitializer + * This macro provides a compile time assert that a module interface that has been + * @#included in the source base has a major version equal to the major version specified. + * + * Expected use is for cases where a module is considered low risk and any minor changes + * are not considered to be important. + * + * It should be invoked at the global scope and ideally following straight after + * the module header has been included. For example: + * + * @code + * #include + * + * MALI_MODULE_ASSERT_MAJOR_EQUALS( MODULEX, 1, 3 ) + * @endcode + */ +#define MALI_MODULE_ASSERT_MAJOR_EQUALS( module, major ) \ + MALIP_MODULE_ASSERT_FUNCTION_SIGNATURE( module, major_equals, __LINE__ ) \ + { \ + CSTD_COMPILE_TIME_ASSERT( MALI_MODULE_##module##_MAJOR == major ); \ + } + +/** + * @hideinitializer + * This macro provides a compile time assert that a module interface that has been + * @#included in the source base has a major version equal to the major version specified + * and that the minor version is at least that which is specified. + * + * Expected use is for cases where a major revision is suitable from a specific minor + * revision but future major versions are a risk. + * + * It should be invoked at the global scope and ideally following straight after + * the module header has been included. For example: + * + * @code + * #include + * + * MALI_MODULE_ASSERT_MAJOR_EQUALS_MINOR_AT_LEAST( MODULEX, 1, 3 ) + * @endcode + */ +#define MALI_MODULE_ASSERT_MAJOR_EQUALS_MINOR_AT_LEAST( module, major, minor ) \ + MALIP_MODULE_ASSERT_FUNCTION_SIGNATURE( module, major_equals_minor_at_least, __LINE__ ) \ + { \ + CSTD_COMPILE_TIME_ASSERT( MALI_MODULE_##module##_MAJOR == major ); \ + CSTD_COMPILE_TIME_ASSERT( MALI_MODULE_##module##_MINOR >= minor ); \ + } + +/* @} */ + +/* @} */ + +#endif /* _MALISW_VERSION_MACROS_H_ */ diff --git a/exynos5/hal/include/media.h b/exynos5/hal/include/media.h new file mode 100644 index 0000000..0ef8833 --- /dev/null +++ b/exynos5/hal/include/media.h @@ -0,0 +1,132 @@ +/* + * Multimedia device API + * + * Copyright (C) 2010 Nokia Corporation + * + * Contacts: Laurent Pinchart + * Sakari Ailus + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __LINUX_MEDIA_H +#define __LINUX_MEDIA_H + +#include +#include +#include + +#define MEDIA_API_VERSION KERNEL_VERSION(0, 1, 0) + +struct media_device_info { + char driver[16]; + char model[32]; + char serial[40]; + char bus_info[32]; + __u32 media_version; + __u32 hw_revision; + __u32 driver_version; + __u32 reserved[31]; +}; + +#define MEDIA_ENT_ID_FLAG_NEXT (1 << 31) + +#define MEDIA_ENT_TYPE_SHIFT 16 +#define MEDIA_ENT_TYPE_MASK 0x00ff0000 +#define MEDIA_ENT_SUBTYPE_MASK 0x0000ffff + +#define MEDIA_ENT_T_DEVNODE (1 << MEDIA_ENT_TYPE_SHIFT) +#define MEDIA_ENT_T_DEVNODE_V4L (MEDIA_ENT_T_DEVNODE + 1) +#define MEDIA_ENT_T_DEVNODE_FB (MEDIA_ENT_T_DEVNODE + 2) +#define MEDIA_ENT_T_DEVNODE_ALSA (MEDIA_ENT_T_DEVNODE + 3) +#define MEDIA_ENT_T_DEVNODE_DVB (MEDIA_ENT_T_DEVNODE + 4) + +#define MEDIA_ENT_T_V4L2_SUBDEV (2 << MEDIA_ENT_TYPE_SHIFT) +#define MEDIA_ENT_T_V4L2_SUBDEV_SENSOR (MEDIA_ENT_T_V4L2_SUBDEV + 1) +#define MEDIA_ENT_T_V4L2_SUBDEV_FLASH (MEDIA_ENT_T_V4L2_SUBDEV + 2) +#define MEDIA_ENT_T_V4L2_SUBDEV_LENS (MEDIA_ENT_T_V4L2_SUBDEV + 3) + +#define MEDIA_ENT_FL_DEFAULT (1 << 0) + +struct media_entity_desc { + __u32 id; + char name[32]; + __u32 type; + __u32 revision; + __u32 flags; + __u32 group_id; + __u16 pads; + __u16 links; + + __u32 reserved[4]; + + union { + /* Node specifications */ + struct { + __u32 major; + __u32 minor; + } v4l; + struct { + __u32 major; + __u32 minor; + } fb; + struct { + __u32 card; + __u32 device; + __u32 subdevice; + } alsa; + int dvb; + + /* Sub-device specifications */ + /* Nothing needed yet */ + __u8 raw[184]; + }; +}; + +#define MEDIA_PAD_FL_SINK (1 << 0) +#define MEDIA_PAD_FL_SOURCE (1 << 1) + +struct media_pad_desc { + __u32 entity; /* entity ID */ + __u16 index; /* pad index */ + __u32 flags; /* pad flags */ + __u32 reserved[2]; +}; + +#define MEDIA_LNK_FL_ENABLED (1 << 0) +#define MEDIA_LNK_FL_IMMUTABLE (1 << 1) +#define MEDIA_LNK_FL_DYNAMIC (1 << 2) + +struct media_link_desc { + struct media_pad_desc source; + struct media_pad_desc sink; + __u32 flags; + __u32 reserved[2]; +}; + +struct media_links_enum { + __u32 entity; + /* Should have enough room for pads elements */ + struct media_pad_desc __user *pads; + /* Should have enough room for links elements */ + struct media_link_desc __user *links; + __u32 reserved[4]; +}; + +#define MEDIA_IOC_DEVICE_INFO _IOWR('|', 0x00, struct media_device_info) +#define MEDIA_IOC_ENUM_ENTITIES _IOWR('|', 0x01, struct media_entity_desc) +#define MEDIA_IOC_ENUM_LINKS _IOWR('|', 0x02, struct media_links_enum) +#define MEDIA_IOC_SETUP_LINK _IOWR('|', 0x03, struct media_link_desc) + +#endif /* __LINUX_MEDIA_H */ diff --git a/exynos5/hal/include/s3c_lcd.h b/exynos5/hal/include/s3c_lcd.h new file mode 100644 index 0000000..22ebf86 --- /dev/null +++ b/exynos5/hal/include/s3c_lcd.h @@ -0,0 +1,83 @@ +/* + * Copyright@ Samsung Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _S3CFB_LCD_ +#define _S3CFB_LCD_ + +/* + * S T R U C T U R E S F O R C U S T O M I O C T L S + * +*/ +struct s3cfb_user_window { + int x; + int y; +}; + +struct s3cfb_user_plane_alpha { + int channel; + unsigned char red; + unsigned char green; + unsigned char blue; +}; + +struct s3cfb_user_chroma { + int enabled; + unsigned char red; + unsigned char green; + unsigned char blue; +}; + +typedef struct { + unsigned int phy_start_addr; + unsigned int xres; /* visible resolution*/ + unsigned int yres; + unsigned int xres_virtual; /* virtual resolution*/ + unsigned int yres_virtual; + unsigned int xoffset; /* offset from virtual to visible */ + unsigned int yoffset; /* resolution */ + unsigned int lcd_offset_x; + unsigned int lcd_offset_y; +} s3c_fb_next_info_t; + +struct s3c_fb_user_ion_client { + int fd; +}; + +/* + * C U S T O M I O C T L S + * +*/ + +#define S3CFB_WIN_POSITION _IOW ('F', 203, struct s3cfb_user_window) +#define S3CFB_WIN_SET_PLANE_ALPHA _IOW ('F', 204, struct s3cfb_user_plane_alpha) +#define S3CFB_WIN_SET_CHROMA _IOW ('F', 205, struct s3cfb_user_chroma) +#define S3CFB_SET_VSYNC_INT _IOW ('F', 206, unsigned int) +#define S3CFB_SET_SUSPEND_FIFO _IOW ('F', 300, unsigned long) +#define S3CFB_SET_RESUME_FIFO _IOW ('F', 301, unsigned long) +#define S3CFB_GET_LCD_WIDTH _IOR ('F', 302, int) +#define S3CFB_GET_LCD_HEIGHT _IOR ('F', 303, int) +#define S3CFB_GET_FB_PHY_ADDR _IOR ('F', 310, unsigned int) +#define S3C_FB_GET_CURR_FB_INFO _IOR ('F', 305, s3c_fb_next_info_t) +#define S3CFB_GET_ION_USER_HANDLE _IOWR('F', 208, struct s3c_fb_user_ion_client) + +/***************** LCD frame buffer *****************/ +#define FB0_NAME "/dev/fb0" +#define FB1_NAME "/dev/fb1" +#define FB2_NAME "/dev/fb2" +#define FB3_NAME "/dev/fb3" +#define FB4_NAME "/dev/fb4" + +#endif diff --git a/exynos5/hal/include/s3c_mem.h b/exynos5/hal/include/s3c_mem.h new file mode 100644 index 0000000..dd4cbdb --- /dev/null +++ b/exynos5/hal/include/s3c_mem.h @@ -0,0 +1,48 @@ +/* + * Copyright@ Samsung Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _S3C_MEM_COMMON_H_ +#define _S3C_MEM_COMMON_H_ + +#define MEM_IOCTL_MAGIC 'M' + +#define S3C_MEM_ALLOC _IOWR(MEM_IOCTL_MAGIC, 310, struct s3c_mem_alloc) +#define S3C_MEM_FREE _IOWR(MEM_IOCTL_MAGIC, 311, struct s3c_mem_alloc) + +#define S3C_MEM_SHARE_ALLOC _IOWR(MEM_IOCTL_MAGIC, 314, struct s3c_mem_alloc) +#define S3C_MEM_SHARE_FREE _IOWR(MEM_IOCTL_MAGIC, 315, struct s3c_mem_alloc) + +#define S3C_MEM_CACHEABLE_ALLOC _IOWR(MEM_IOCTL_MAGIC, 316, struct s3c_mem_alloc) +#define S3C_MEM_CACHEABLE_SHARE_ALLOC _IOWR(MEM_IOCTL_MAGIC, 317, struct s3c_mem_alloc) + +#define S3C_MEM_CACHE_FLUSH _IOWR(MEM_IOCTL_MAGIC, 318, struct s3c_mem_alloc) +#define S3C_MEM_CACHE_INVAL _IOWR(MEM_IOCTL_MAGIC, 319, struct s3c_mem_alloc) +#define S3C_MEM_CACHE_CLEAN _IOWR(MEM_IOCTL_MAGIC, 320, struct s3c_mem_alloc) + +struct s3c_mem_alloc { + int size; + unsigned int vir_addr; + unsigned int phy_addr; +}; + +struct s3c_mem_dma_param { + int size; + unsigned int src_addr; + unsigned int dst_addr; + int cfg; +}; + +#endif // _S3C_MEM_COMMON_H_ diff --git a/exynos5/hal/include/s5p_fimc.h b/exynos5/hal/include/s5p_fimc.h new file mode 100644 index 0000000..d41fee1 --- /dev/null +++ b/exynos5/hal/include/s5p_fimc.h @@ -0,0 +1,160 @@ +/* Copyright(c) 2011 Samsung Electronics Co, Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Alternatively, Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +*/ + +#ifndef _S5P_FIMC_H_ +#define _S5P_FIMC_H_ + +#include +#include "SecBuffer.h" +/* + * G E N E R A L S + * +*/ +#define MIN(x, y) ((x < y) ? x : y) + +/* + * P I X E L F O R M A T G U I D E + * + * The 'x' means 'DO NOT CARE' + * The '*' means 'FIMC SPECIFIC' + * For some fimc formats, we couldn't find equivalent format in the V4L2 FOURCC. + * + * FIMC TYPE PLANES ORDER V4L2_PIX_FMT + * --------------------------------------------------------- + * RGB565 x x V4L2_PIX_FMT_RGB565 + * RGB888 x x V4L2_PIX_FMT_RGB24 + * YUV420 2 LSB_CBCR V4L2_PIX_FMT_NV12 + * YUV420 2 LSB_CRCB V4L2_PIX_FMT_NV21 + * YUV420 2 MSB_CBCR V4L2_PIX_FMT_NV21X* + * YUV420 2 MSB_CRCB V4L2_PIX_FMT_NV12X* + * YUV420 3 x V4L2_PIX_FMT_YUV420 + * YUV422 1 YCBYCR V4L2_PIX_FMT_YUYV + * YUV422 1 YCRYCB V4L2_PIX_FMT_YVYU + * YUV422 1 CBYCRY V4L2_PIX_FMT_UYVY + * YUV422 1 CRYCBY V4L2_PIX_FMT_VYUY* + * YUV422 2 LSB_CBCR V4L2_PIX_FMT_NV16* + * YUV422 2 LSB_CRCB V4L2_PIX_FMT_NV61* + * YUV422 2 MSB_CBCR V4L2_PIX_FMT_NV16X* + * YUV422 2 MSB_CRCB V4L2_PIX_FMT_NV61X* + * YUV422 3 x V4L2_PIX_FMT_YUV422P + * +*/ + +/* + * V 4 L 2 F I M C E X T E N S I O N S + * +*/ +#define V4L2_PIX_FMT_YVYU v4l2_fourcc('Y', 'V', 'Y', 'U') + +/* FOURCC for FIMC specific */ +#define V4L2_PIX_FMT_NV12X v4l2_fourcc('N', '1', '2', 'X') +#define V4L2_PIX_FMT_NV21X v4l2_fourcc('N', '2', '1', 'X') +#define V4L2_PIX_FMT_VYUY v4l2_fourcc('V', 'Y', 'U', 'Y') +#define V4L2_PIX_FMT_NV16 v4l2_fourcc('N', 'V', '1', '6') +#define V4L2_PIX_FMT_NV61 v4l2_fourcc('N', 'V', '6', '1') +#define V4L2_PIX_FMT_NV16X v4l2_fourcc('N', '1', '6', 'X') +#define V4L2_PIX_FMT_NV61X v4l2_fourcc('N', '6', '1', 'X') + +#define V4L2_PIX_FMT_NV12T v4l2_fourcc('T', 'V', '1', '2') /* 12 Y/CbCr 4:2:0 64x32 macroblocks */ + +/* CID extensions */ +#define V4L2_CID_ROTATION (V4L2_CID_PRIVATE_BASE + 0) +#define V4L2_CID_OVLY_MODE (V4L2_CID_PRIVATE_BASE + 9) +#define V4L2_CID_GET_PHY_SRC_YADDR (V4L2_CID_PRIVATE_BASE + 12) +#define V4L2_CID_GET_PHY_SRC_CADDR (V4L2_CID_PRIVATE_BASE + 13) +#define V4L2_CID_RESERVED_MEM_BASE_ADDR (V4L2_CID_PRIVATE_BASE + 20) +#define V4L2_CID_FIMC_VERSION (V4L2_CID_PRIVATE_BASE + 21) + +/* + * U S E R D E F I N E D T Y P E S + * +*/ +#define FIMC1_RESERVED_SIZE 32768 + +enum fimc_overlay_mode { + FIMC_OVLY_NOT_FIXED = 0x0, /* Overlay mode isn't fixed. */ + FIMC_OVLY_FIFO = 0x1, /* Non-destructive Overlay with FIFO */ + FIMC_OVLY_DMA_AUTO = 0x2, /* Non-destructive Overlay with DMA */ + FIMC_OVLY_DMA_MANUAL = 0x3, /* Non-destructive Overlay with DMA */ + FIMC_OVLY_NONE_SINGLE_BUF = 0x4, /* Destructive Overlay with DMA single destination buffer */ + FIMC_OVLY_NONE_MULTI_BUF = 0x5, /* Destructive Overlay with DMA multiple dstination buffer */ +}; + +typedef unsigned int dma_addr_t; + +struct fimc_buf { + dma_addr_t base[3]; + size_t length[3]; +}; + +struct fimc_buffer { + void *virt_addr; + void *phys_addr; + size_t length; +}; + +struct yuv_fmt_list { + const char *name; + const char *desc; + unsigned int fmt; + int bpp; + int planes; +}; + +struct img_offset { + int y_h; + int y_v; + int cb_h; + int cb_v; + int cr_h; + int cr_v; +}; + +//------------ STRUCT ---------------------------------------------------------// + +typedef struct +{ + unsigned int full_width; // Source Image Full Width (Virtual screen size) + unsigned int full_height; // Source Image Full Height (Virtual screen size) + unsigned int start_x; // Source Image Start width offset + unsigned int start_y; // Source Image Start height offset + unsigned int width; // Source Image Width + unsigned int height; // Source Image Height + unsigned int buf_addr_phy_rgb_y; // Base Address of the Source Image (RGB or Y): Physical Address + unsigned int buf_addr_phy_cb; // Base Address of the Source Image (CB Component) : Physical Address + unsigned int buf_addr_phy_cr; // Base Address of the Source Image (CR Component) : Physical Address + unsigned int color_space; // Color Space of the Source Image +} s5p_fimc_img_info; + +typedef struct +{ + s5p_fimc_img_info src; + s5p_fimc_img_info dst; +} s5p_fimc_params_t; + +typedef struct _s5p_fimc_t { + int dev_fd; + struct fimc_buffer out_buf; + + s5p_fimc_params_t params; + + int use_ext_out_mem; +}s5p_fimc_t; + +#endif diff --git a/exynos5/hal/include/s5p_fimc_v4l2.h b/exynos5/hal/include/s5p_fimc_v4l2.h new file mode 100644 index 0000000..e69951d --- /dev/null +++ b/exynos5/hal/include/s5p_fimc_v4l2.h @@ -0,0 +1,162 @@ +/* Copyright(c) 2011 Samsung Electronics Co, Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Alternatively, Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +*/ + +#ifndef _S5P_FIMC_H_ +#define _S5P_FIMC_H_ + +#include "videodev2.h" +#include "SecBuffer.h" + +/* + * G E N E R A L S + * +*/ + +/* + * P I X E L F O R M A T G U I D E + * + * The 'x' means 'DO NOT CARE' + * The '*' means 'FIMC SPECIFIC' + * For some fimc formats, we couldn't find equivalent format in the V4L2 FOURCC. + * + * FIMC TYPE PLANES ORDER V4L2_PIX_FMT + * --------------------------------------------------------- + * RGB565 x x V4L2_PIX_FMT_RGB565 + * RGB888 x x V4L2_PIX_FMT_RGB24 + * YUV420 2 LSB_CBCR V4L2_PIX_FMT_NV12 + * YUV420 2 LSB_CRCB V4L2_PIX_FMT_NV21 + * YUV420 2 MSB_CBCR V4L2_PIX_FMT_NV21X* + * YUV420 2 MSB_CRCB V4L2_PIX_FMT_NV12X* + * YUV420 3 x V4L2_PIX_FMT_YUV420 + * YUV422 1 YCBYCR V4L2_PIX_FMT_YUYV + * YUV422 1 YCRYCB V4L2_PIX_FMT_YVYU + * YUV422 1 CBYCRY V4L2_PIX_FMT_UYVY + * YUV422 1 CRYCBY V4L2_PIX_FMT_VYUY* + * YUV422 2 LSB_CBCR V4L2_PIX_FMT_NV16* + * YUV422 2 LSB_CRCB V4L2_PIX_FMT_NV61* + * YUV422 2 MSB_CBCR V4L2_PIX_FMT_NV16X* + * YUV422 2 MSB_CRCB V4L2_PIX_FMT_NV61X* + * YUV422 3 x V4L2_PIX_FMT_YUV422P + * +*/ + +/* + * V 4 L 2 F I M C E X T E N S I O N S + * +*/ +#define V4L2_PIX_FMT_YVYU v4l2_fourcc('Y', 'V', 'Y', 'U') + +/* FOURCC for FIMC specific */ +#define V4L2_PIX_FMT_NV12X v4l2_fourcc('N', '1', '2', 'X') +#define V4L2_PIX_FMT_NV21X v4l2_fourcc('N', '2', '1', 'X') +#define V4L2_PIX_FMT_VYUY v4l2_fourcc('V', 'Y', 'U', 'Y') +#define V4L2_PIX_FMT_NV16 v4l2_fourcc('N', 'V', '1', '6') +#define V4L2_PIX_FMT_NV61 v4l2_fourcc('N', 'V', '6', '1') +#define V4L2_PIX_FMT_NV16X v4l2_fourcc('N', '1', '6', 'X') +#define V4L2_PIX_FMT_NV61X v4l2_fourcc('N', '6', '1', 'X') + +#define V4L2_PIX_FMT_NV12T v4l2_fourcc('T', 'V', '1', '2') /* 12 Y/CbCr 4:2:0 64x32 macroblocks */ + +/* CID extensions */ +#define V4L2_CID_ROTATION (V4L2_CID_PRIVATE_BASE + 0) +#define V4L2_CID_OVLY_MODE (V4L2_CID_PRIVATE_BASE + 9) +#define V4L2_CID_GET_PHY_SRC_YADDR (V4L2_CID_PRIVATE_BASE + 12) +#define V4L2_CID_GET_PHY_SRC_CADDR (V4L2_CID_PRIVATE_BASE + 13) +#define V4L2_CID_RESERVED_MEM_BASE_ADDR (V4L2_CID_PRIVATE_BASE + 20) +#define V4L2_CID_FIMC_VERSION (V4L2_CID_PRIVATE_BASE + 21) + +/* + * U S E R D E F I N E D T Y P E S + * +*/ +#define FIMC1_RESERVED_SIZE 32768 + +enum fimc_overlay_mode { + FIMC_OVLY_NOT_FIXED = 0x0, /* Overlay mode isn't fixed. */ + FIMC_OVLY_FIFO = 0x1, /* Non-destructive Overlay with FIFO */ + FIMC_OVLY_DMA_AUTO = 0x2, /* Non-destructive Overlay with DMA */ + FIMC_OVLY_DMA_MANUAL = 0x3, /* Non-destructive Overlay with DMA */ + FIMC_OVLY_NONE_SINGLE_BUF = 0x4, /* Destructive Overlay with DMA single destination buffer */ + FIMC_OVLY_NONE_MULTI_BUF = 0x5, /* Destructive Overlay with DMA multiple dstination buffer */ +}; + +typedef unsigned int dma_addr_t; + +struct fimc_buf { + dma_addr_t base[3]; + size_t size[3]; + int planes; +}; + +struct fimc_buffer { + void *virt_addr; + void *phys_addr; + size_t length; +}; + +struct yuv_fmt_list { + const char *name; + const char *desc; + unsigned int fmt; + int bpp; + int planes; +}; + +struct img_offset { + int y_h; + int y_v; + int cb_h; + int cb_v; + int cr_h; + int cr_v; +}; + +//------------ STRUCT ---------------------------------------------------------// + +typedef struct +{ + unsigned int full_width; // Source Image Full Width (Virtual screen size) + unsigned int full_height; // Source Image Full Height (Virtual screen size) + unsigned int start_x; // Source Image Start width offset + unsigned int start_y; // Source Image Start height offset + unsigned int width; // Source Image Width + unsigned int height; // Source Image Height + unsigned int buf_addr_phy_rgb_y; // Base Address of the Source Image (RGB or Y): Physical Address + unsigned int buf_addr_phy_cb; // Base Address of the Source Image (CB Component) : Physical Address + unsigned int buf_addr_phy_cr; // Base Address of the Source Image (CR Component) : Physical Address + unsigned int color_space; // Color Space of the Source Image + unsigned int planes; // number of planes for the Image +} s5p_fimc_img_info; + +typedef struct +{ + s5p_fimc_img_info src; + s5p_fimc_img_info dst; +} s5p_fimc_params_t; + +typedef struct _s5p_fimc_t { + int dev_fd; + struct fimc_buffer out_buf; + + s5p_fimc_params_t params; + + int use_ext_out_mem; +} s5p_fimc_t; + +#endif diff --git a/exynos5/hal/include/s5p_tvout.h b/exynos5/hal/include/s5p_tvout.h new file mode 100644 index 0000000..fd31bec --- /dev/null +++ b/exynos5/hal/include/s5p_tvout.h @@ -0,0 +1,198 @@ +/* + * Copyright@ Samsung Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __S5P_TVOUT_H__ +#define __S5P_TVOUT_H__ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/******************************************* + * Define + *******************************************/ +/* TVOUT control */ +#ifdef SAMSUNG_EXYNOS4210 +#define TVOUT_DEV "/dev/video14" +#else +#define TVOUT_DEV "/dev/video16" +#endif +#define HPD_DEV "/dev/HPD" + +/* ------------- Output -----------------*/ +/* type */ +#define V4L2_OUTPUT_TYPE_MSDMA 4 +#define V4L2_OUTPUT_TYPE_COMPOSITE 5 +#define V4L2_OUTPUT_TYPE_SVIDEO 6 +#define V4L2_OUTPUT_TYPE_YPBPR_INERLACED 7 +#define V4L2_OUTPUT_TYPE_YPBPR_PROGRESSIVE 8 +#define V4L2_OUTPUT_TYPE_RGB_PROGRESSIVE 9 +#define V4L2_OUTPUT_TYPE_DIGITAL 10 +#define V4L2_OUTPUT_TYPE_HDMI V4L2_OUTPUT_TYPE_DIGITAL +#define V4L2_OUTPUT_TYPE_HDMI_RGB 11 +#define V4L2_OUTPUT_TYPE_DVI 12 + +/* ------------- STD -------------------*/ +#define V4L2_STD_PAL_BDGHI\ + (V4L2_STD_PAL_B|V4L2_STD_PAL_D|V4L2_STD_PAL_G|V4L2_STD_PAL_H|V4L2_STD_PAL_I) + +#define V4L2_STD_480P_60_16_9 ((v4l2_std_id)0x04000000) +#define V4L2_STD_480P_60_4_3 ((v4l2_std_id)0x05000000) +#define V4L2_STD_576P_50_16_9 ((v4l2_std_id)0x06000000) +#define V4L2_STD_576P_50_4_3 ((v4l2_std_id)0x07000000) +#define V4L2_STD_720P_60 ((v4l2_std_id)0x08000000) +#define V4L2_STD_720P_50 ((v4l2_std_id)0x09000000) +#define V4L2_STD_1080P_60 ((v4l2_std_id)0x0a000000) +#define V4L2_STD_1080P_50 ((v4l2_std_id)0x0b000000) +#define V4L2_STD_1080I_60 ((v4l2_std_id)0x0c000000) +#define V4L2_STD_1080I_50 ((v4l2_std_id)0x0d000000) +#define V4L2_STD_480P_59 ((v4l2_std_id)0x0e000000) +#define V4L2_STD_720P_59 ((v4l2_std_id)0x0f000000) +#define V4L2_STD_1080I_59 ((v4l2_std_id)0x10000000) +#define V4L2_STD_1080P_59 ((v4l2_std_id)0x11000000) +#define V4L2_STD_1080P_30 ((v4l2_std_id)0x12000000) +#define V4L2_STD_TVOUT_720P_60_SBS_HALF ((v4l2_std_id)0x13000000) +#define V4L2_STD_TVOUT_720P_59_SBS_HALF ((v4l2_std_id)0x14000000) +#define V4L2_STD_TVOUT_720P_50_TB ((v4l2_std_id)0x15000000) +#define V4L2_STD_TVOUT_1080P_24_TB ((v4l2_std_id)0x16000000) +#define V4L2_STD_TVOUT_1080P_23_TB ((v4l2_std_id)0x17000000) + +/* TVOUT video */ +#ifdef SAMSUNG_EXYNOS4210 +#define TVOUT_DEV_V "/dev/video21" +#else +#define TVOUT_DEV_V "/dev/video20" +#endif + +/* ------------- Input ------------------*/ +/* type */ +#define V4L2_INPUT_TYPE_MSDMA 3 +#define V4L2_INPUT_TYPE_FIFO 4 + +/* TVOUT video */ +#define PFX_NODE_FB "/dev/graphics/fb" + +/******************************************* + * structures + *******************************************/ + +/* TVOUT */ +struct v4l2_vid_overlay_src { + void *base_y; + void *base_c; + struct v4l2_pix_format pix_fmt; +}; + +struct v4l2_window_s5p_tvout { + __u32 capability; + __u32 flags; + __u32 priority; + struct v4l2_window win; +}; + +struct v4l2_pix_format_s5p_tvout { + void *base_y; + void *base_c; + __u32 src_img_endian; + struct v4l2_pix_format pix_fmt; +}; + +struct vid_overlay_param { + struct v4l2_vid_overlay_src src; + struct v4l2_rect src_crop; + struct v4l2_framebuffer dst; + struct v4l2_window dst_win; +}; + +struct tvout_param { + struct v4l2_pix_format_s5p_tvout tvout_src; + struct v4l2_window_s5p_tvout tvout_rect; + struct v4l2_rect tvout_dst; +}; + +struct overlay_param { + struct v4l2_framebuffer overlay_frame; + struct v4l2_window_s5p_tvout overlay_rect; + struct v4l2_rect overlay_dst; +}; + +/* FB */ +struct s5ptvfb_user_window { + int x; + int y; +}; + +struct s5ptvfb_user_plane_alpha { + int channel; + unsigned char alpha; +}; + +struct s5ptvfb_user_chroma { + int enabled; + unsigned char red; + unsigned char green; + unsigned char blue; +}; + +enum s5ptvfb_ver_scaling_t { + VERTICAL_X1, + VERTICAL_X2, +}; + +enum s5ptvfb_hor_scaling_t { + HORIZONTAL_X1, + HORIZONTAL_X2, +}; + +struct s5ptvfb_user_scaling { + enum s5ptvfb_ver_scaling_t ver; + enum s5ptvfb_hor_scaling_t hor; +}; + +/******************************************* + * custom ioctls + *******************************************/ + +#define VIDIOC_S_BASEADDR _IOR('V', 83, int) + +#define VIDIOC_HDCP_ENABLE _IOWR('V', 100, unsigned int) +#define VIDIOC_HDCP_STATUS _IOR('V', 101, unsigned int) +#define VIDIOC_HDCP_PROT_STATUS _IOR('V', 102, unsigned int) + +#define VIDIOC_INIT_AUDIO _IOR('V', 103, unsigned int) +#define VIDIOC_AV_MUTE _IOR('V', 104, unsigned int) +#define VIDIOC_G_AVMUTE _IOR('V', 105, unsigned int) +#define HPD_GET_STATE _IOR('H', 100, unsigned int) + +#define S5PTVFB_WIN_POSITION _IOW('F', 213, struct s5ptvfb_user_window) +#define S5PTVFB_WIN_SET_PLANE_ALPHA _IOW('F', 214, struct s5ptvfb_user_plane_alpha) +#define S5PTVFB_WIN_SET_CHROMA _IOW('F', 215, struct s5ptvfb_user_chroma) + +#define S5PTVFB_SET_VSYNC_INT _IOW('F', 216, unsigned int) +#define S5PTVFB_WAITFORVSYNC _IO('F', 32) +#define S5PTVFB_WIN_SET_ADDR _IOW('F', 219, unsigned int) +#define S5PTVFB_SET_WIN_ON _IOW('F', 220, unsigned int) +#define S5PTVFB_SET_WIN_OFF _IOW('F', 221, unsigned int) +#define S5PTVFB_SCALING _IOW('F', 222, struct s5ptvfb_user_scaling) + +#ifdef __cplusplus +} +#endif + +#endif /* __S5P_TVOUT_H__ */ diff --git a/exynos5/hal/include/s5p_tvout_v4l2.h b/exynos5/hal/include/s5p_tvout_v4l2.h new file mode 100644 index 0000000..49ac288 --- /dev/null +++ b/exynos5/hal/include/s5p_tvout_v4l2.h @@ -0,0 +1,207 @@ +/* + * Copyright@ Samsung Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __S5P_TVOUT_H__ +#define __S5P_TVOUT_H__ + +#include + +#include "videodev2.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/******************************************* + * Define + *******************************************/ +/* TVOUT control */ +#define PFX_NODE_FB "/dev/graphics/fb" + +#define PFX_NODE_MEDIADEV "/dev/media" +#define PFX_NODE_SUBDEV "/dev/v4l-subdev" +#define PFX_NODE_VIDEODEV "/dev/video" +#define PFX_ENTITY_SUBDEV_MIXER "s5p-mixer%d" + +/* Sub-Mixer 0 */ +#define TVOUT0_DEV_G0 "/dev/video16" +#define TVOUT0_DEV_G1 "/dev/video17" +/* Sub-Mixer 1 */ +#define TVOUT1_DEV_G0 "/dev/video18" +#define TVOUT1_DEV_G1 "/dev/video19" + +#define MIXER_V_SUBDEV_PAD_SINK (0) +#define MIXER_V_SUBDEV_PAD_SOURCE (3) +#define MIXER_G0_SUBDEV_PAD_SINK (1) +#define MIXER_G0_SUBDEV_PAD_SOURCE (4) +#define MIXER_G1_SUBDEV_PAD_SINK (2) +#define MIXER_G1_SUBDEV_PAD_SOURCE (5) + +#define GSCALER_SUBDEV_PAD_SOURCE (1) + +#define HPD_DEV "/dev/HPD" + +/* ------------- Output -----------------*/ +/* type */ +#define V4L2_OUTPUT_TYPE_MSDMA 4 +#define V4L2_OUTPUT_TYPE_COMPOSITE 5 +#define V4L2_OUTPUT_TYPE_SVIDEO 6 +#define V4L2_OUTPUT_TYPE_YPBPR_INERLACED 7 +#define V4L2_OUTPUT_TYPE_YPBPR_PROGRESSIVE 8 +#define V4L2_OUTPUT_TYPE_RGB_PROGRESSIVE 9 +#define V4L2_OUTPUT_TYPE_DIGITAL 10 +#define V4L2_OUTPUT_TYPE_HDMI V4L2_OUTPUT_TYPE_DIGITAL +#define V4L2_OUTPUT_TYPE_HDMI_RGB 11 +#define V4L2_OUTPUT_TYPE_DVI 12 + +/* ------------- STD -------------------*/ +#define V4L2_STD_PAL_BDGHI\ + (V4L2_STD_PAL_B|V4L2_STD_PAL_D|V4L2_STD_PAL_G|V4L2_STD_PAL_H|V4L2_STD_PAL_I) + +#define V4L2_STD_480P_60_16_9 ((v4l2_std_id)0x04000000) +#define V4L2_STD_480P_60_4_3 ((v4l2_std_id)0x05000000) +#define V4L2_STD_576P_50_16_9 ((v4l2_std_id)0x06000000) +#define V4L2_STD_576P_50_4_3 ((v4l2_std_id)0x07000000) +#define V4L2_STD_720P_60 ((v4l2_std_id)0x08000000) +#define V4L2_STD_720P_50 ((v4l2_std_id)0x09000000) +#define V4L2_STD_1080P_60 ((v4l2_std_id)0x0a000000) +#define V4L2_STD_1080P_50 ((v4l2_std_id)0x0b000000) +#define V4L2_STD_1080I_60 ((v4l2_std_id)0x0c000000) +#define V4L2_STD_1080I_50 ((v4l2_std_id)0x0d000000) +#define V4L2_STD_480P_59 ((v4l2_std_id)0x0e000000) +#define V4L2_STD_720P_59 ((v4l2_std_id)0x0f000000) +#define V4L2_STD_1080I_59 ((v4l2_std_id)0x10000000) +#define V4L2_STD_1080P_59 ((v4l2_std_id)0x11000000) +#define V4L2_STD_1080P_30 ((v4l2_std_id)0x12000000) +#define V4L2_STD_TVOUT_720P_60_SBS_HALF ((v4l2_std_id)0x13000000) +#define V4L2_STD_TVOUT_720P_59_SBS_HALF ((v4l2_std_id)0x14000000) +#define V4L2_STD_TVOUT_720P_50_TB ((v4l2_std_id)0x15000000) +#define V4L2_STD_TVOUT_1080P_24_TB ((v4l2_std_id)0x16000000) +#define V4L2_STD_TVOUT_1080P_23_TB ((v4l2_std_id)0x17000000) + +/* ------------- Input ------------------*/ +/* type */ +#define V4L2_INPUT_TYPE_MSDMA 3 +#define V4L2_INPUT_TYPE_FIFO 4 + +/******************************************* + * structures + *******************************************/ + +/* TVOUT */ +struct v4l2_vid_overlay_src { + void *base_y; + void *base_c; + struct v4l2_pix_format pix_fmt; +}; + +struct v4l2_window_s5p_tvout { + __u32 capability; + __u32 flags; + __u32 priority; + struct v4l2_window win; +}; + +struct v4l2_pix_format_s5p_tvout { + void *base_y; + void *base_c; + __u32 src_img_endian; + struct v4l2_pix_format pix_fmt; +}; + +struct vid_overlay_param { + struct v4l2_vid_overlay_src src; + struct v4l2_rect src_crop; + struct v4l2_framebuffer dst; + struct v4l2_window dst_win; +}; + +struct tvout_param { + struct v4l2_pix_format_s5p_tvout tvout_src; + struct v4l2_window_s5p_tvout tvout_rect; + struct v4l2_rect tvout_dst; +}; + +struct overlay_param { + struct v4l2_framebuffer overlay_frame; + struct v4l2_window_s5p_tvout overlay_rect; + struct v4l2_rect overlay_dst; +}; + +/* FB */ +struct s5ptvfb_user_window { + int x; + int y; +}; + +struct s5ptvfb_user_plane_alpha { + int channel; + unsigned char alpha; +}; + +struct s5ptvfb_user_chroma { + int enabled; + unsigned char red; + unsigned char green; + unsigned char blue; +}; + +enum s5ptvfb_ver_scaling_t { + VERTICAL_X1, + VERTICAL_X2, +}; + +enum s5ptvfb_hor_scaling_t { + HORIZONTAL_X1, + HORIZONTAL_X2, +}; + +struct s5ptvfb_user_scaling { + enum s5ptvfb_ver_scaling_t ver; + enum s5ptvfb_hor_scaling_t hor; +}; + +/******************************************* + * custom ioctls + *******************************************/ + +#define VIDIOC_S_BASEADDR _IOR('V', 83, int) + +#define VIDIOC_HDCP_ENABLE _IOWR('V', 100, unsigned int) +#define VIDIOC_HDCP_STATUS _IOR('V', 101, unsigned int) +#define VIDIOC_HDCP_PROT_STATUS _IOR('V', 102, unsigned int) + +#define VIDIOC_INIT_AUDIO _IOR('V', 103, unsigned int) +#define VIDIOC_AV_MUTE _IOR('V', 104, unsigned int) +#define VIDIOC_G_AVMUTE _IOR('V', 105, unsigned int) +#define HPD_GET_STATE _IOR('H', 100, unsigned int) + +#define S5PTVFB_WIN_POSITION _IOW('F', 213, struct s5ptvfb_user_window) +#define S5PTVFB_WIN_SET_PLANE_ALPHA _IOW('F', 214, struct s5ptvfb_user_plane_alpha) +#define S5PTVFB_WIN_SET_CHROMA _IOW('F', 215, struct s5ptvfb_user_chroma) + +#define S5PTVFB_SET_VSYNC_INT _IOW('F', 216, unsigned int) +#define S5PTVFB_WAITFORVSYNC _IO('F', 32) +#define S5PTVFB_WIN_SET_ADDR _IOW('F', 219, unsigned int) +#define S5PTVFB_SET_WIN_ON _IOW('F', 220, unsigned int) +#define S5PTVFB_SET_WIN_OFF _IOW('F', 221, unsigned int) +#define S5PTVFB_SCALING _IOW('F', 222, struct s5ptvfb_user_scaling) + +#ifdef __cplusplus +} +#endif + +#endif /* __S5P_TVOUT_H__ */ diff --git a/exynos5/hal/include/sec_format.h b/exynos5/hal/include/sec_format.h new file mode 100644 index 0000000..1f7b70b --- /dev/null +++ b/exynos5/hal/include/sec_format.h @@ -0,0 +1,48 @@ +/* + * Copyright@ Samsung Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +*/ + +#ifndef _SEC_FORMAT_H_ +#define _SEC_FORMAT_H_ + +/* enum related to pixel format */ + +enum { + HAL_PIXEL_FORMAT_YCbCr_422_P = 0x100, + HAL_PIXEL_FORMAT_YCbCr_420_P = 0x101, + HAL_PIXEL_FORMAT_YCbCr_420_I = 0x102, + HAL_PIXEL_FORMAT_CbYCrY_422_I = 0x103, + HAL_PIXEL_FORMAT_CbYCrY_420_I = 0x104, + HAL_PIXEL_FORMAT_YCbCr_420_SP = 0x105, + HAL_PIXEL_FORMAT_YCrCb_422_SP = 0x106, + // support custom format for zero copy + HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_SP = 0x110, + HAL_PIXEL_FORMAT_CUSTOM_YCrCb_420_SP = 0x111, + HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_SP_TILED = 0x112, + HAL_PIXEL_FORMAT_CUSTOM_YCbCr_422_SP = 0x113, + HAL_PIXEL_FORMAT_CUSTOM_YCrCb_422_SP = 0x114, + HAL_PIXEL_FORMAT_CUSTOM_YCbCr_422_I = 0x115, + HAL_PIXEL_FORMAT_CUSTOM_YCrCb_422_I = 0x116, + HAL_PIXEL_FORMAT_CUSTOM_CbYCrY_422_I = 0x117, + HAL_PIXEL_FORMAT_CUSTOM_CrYCbY_422_I = 0x118, + HAL_PIXEL_FORMAT_CUSTOM_CbYCr_422_I = 0x11B, + HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_P_SBS_LR = 0x11C, + HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_P_SBS_RL = 0x11D, + HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_P_TB_LR = 0x11E, + HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_P_TB_RL = 0x11F, + HAL_PIXEL_FORMAT_CUSTOM_MAX +}; + +#endif diff --git a/exynos5/hal/include/sec_g2d.h b/exynos5/hal/include/sec_g2d.h new file mode 100644 index 0000000..772cbf8 --- /dev/null +++ b/exynos5/hal/include/sec_g2d.h @@ -0,0 +1,251 @@ +/* + * Copyright@ Samsung Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _SEC_G2D_DRIVER_H_ +#define _SEC_G2D_DRIVER_H_ +typedef unsigned char u8; +typedef unsigned short u16; +typedef unsigned long u32; + +#define SEC_G2D_DEV_NAME "/dev/fimg2d" + +#define G2D_IOCTL_MAGIC 'G' + +#define G2D_BLIT _IO(G2D_IOCTL_MAGIC,0) +#define G2D_GET_VERSION _IO(G2D_IOCTL_MAGIC,1) +#define G2D_GET_MEMORY _IOR(G2D_IOCTL_MAGIC,2, unsigned int) +#define G2D_GET_MEMORY_SIZE _IOR(G2D_IOCTL_MAGIC,3, unsigned int) +#define G2D_DMA_CACHE_CLEAN _IOWR(G2D_IOCTL_MAGIC,4, struct g2d_dma_info) +#define G2D_DMA_CACHE_FLUSH _IOWR(G2D_IOCTL_MAGIC,5, struct g2d_dma_info) +#define G2D_SYNC _IO(G2D_IOCTL_MAGIC,6) +#define G2D_RESET _IO(G2D_IOCTL_MAGIC,7) + +#define G2D_MAX_WIDTH (2048) +#define G2D_MAX_HEIGHT (2048) + +#define G2D_ALPHA_VALUE_MAX (255) + +#define G2D_POLLING (1<<0) +#define G2D_INTERRUPT (0<<0) +#define G2D_CACHE_OP (1<<1) +#define G2D_NONE_INVALIDATE (0<<1) +#define G2D_HYBRID_MODE (1<<2) + +typedef enum { + G2D_ROT_0 = 0, + G2D_ROT_90, + G2D_ROT_180, + G2D_ROT_270, + G2D_ROT_X_FLIP, + G2D_ROT_Y_FLIP +} G2D_ROT_DEG; + +typedef enum { + G2D_ALPHA_BLENDING_MIN = 0, // wholly transparent + G2D_ALPHA_BLENDING_MAX = 255, // 255 + G2D_ALPHA_BLENDING_OPAQUE = 256, // opaque +} G2D_ALPHA_BLENDING_MODE; + +typedef enum { + G2D_COLORKEY_NONE = 0, + G2D_COLORKEY_SRC_ON, + G2D_COLORKEY_DST_ON, + G2D_COLORKEY_SRC_DST_ON, +} G2D_COLORKEY_MODE; + +typedef enum { + G2D_BLUE_SCREEN_NONE = 0, + G2D_BLUE_SCREEN_TRANSPARENT, + G2D_BLUE_SCREEN_WITH_COLOR, +} G2D_BLUE_SCREEN_MODE; + +typedef enum { + G2D_ROP_SRC = 0, + G2D_ROP_DST, + G2D_ROP_SRC_AND_DST, + G2D_ROP_SRC_OR_DST, + G2D_ROP_3RD_OPRND, + G2D_ROP_SRC_AND_3RD_OPRND, + G2D_ROP_SRC_OR_3RD_OPRND, + G2D_ROP_SRC_XOR_3RD_OPRND, + G2D_ROP_DST_OR_3RD, +} G2D_ROP_TYPE; + +typedef enum { + G2D_THIRD_OP_NONE = 0, + G2D_THIRD_OP_PATTERN, + G2D_THIRD_OP_FG, + G2D_THIRD_OP_BG +} G2D_THIRD_OP_MODE; + +typedef enum { + G2D_BLACK = 0, + G2D_RED, + G2D_GREEN, + G2D_BLUE, + G2D_WHITE, + G2D_YELLOW, + G2D_CYAN, + G2D_MAGENTA +} G2D_COLOR; + +typedef enum { + G2D_RGB_565 = ((0<<4)|2), + + G2D_ABGR_8888 = ((2<<4)|1), + G2D_BGRA_8888 = ((3<<4)|1), + G2D_ARGB_8888 = ((0<<4)|1), + G2D_RGBA_8888 = ((1<<4)|1), + + G2D_XBGR_8888 = ((2<<4)|0), + G2D_BGRX_8888 = ((3<<4)|0), + G2D_XRGB_8888 = ((0<<4)|0), + G2D_RGBX_8888 = ((1<<4)|0), + + G2D_ABGR_1555 = ((2<<4)|4), + G2D_BGRA_5551 = ((3<<4)|4), + G2D_ARGB_1555 = ((0<<4)|4), + G2D_RGBA_5551 = ((1<<4)|4), + + G2D_XBGR_1555 = ((2<<4)|3), + G2D_BGRX_5551 = ((3<<4)|3), + G2D_XRGB_1555 = ((0<<4)|3), + G2D_RGBX_5551 = ((1<<4)|3), + + G2D_ABGR_4444 = ((2<<4)|6), + G2D_BGRA_4444 = ((3<<4)|6), + G2D_ARGB_4444 = ((0<<4)|6), + G2D_RGBA_4444 = ((1<<4)|6), + + G2D_XBGR_4444 = ((2<<4)|5), + G2D_BGRX_4444 = ((3<<4)|5), + G2D_XRGB_4444 = ((0<<4)|5), + G2D_RGBX_4444 = ((1<<4)|5), + + G2D_PACKED_BGR_888 = ((2<<4)|7), + G2D_PACKED_RGB_888 = ((0<<4)|7), + + G2D_MAX_COLOR_SPACE +} G2D_COLOR_SPACE; + +typedef enum { + G2D_Clear_Mode, //!< [0, 0] + G2D_Src_Mode, //!< [Sa, Sc] + G2D_Dst_Mode, //!< [Da, Dc] + G2D_SrcOver_Mode, //!< [Sa + Da - Sa*Da, Rc = Sc + (1 - Sa)*Dc] + G2D_DstOver_Mode, //!< [Sa + Da - Sa*Da, Rc = Dc + (1 - Da)*Sc] + G2D_SrcIn_Mode, //!< [Sa * Da, Sc * Da] + G2D_DstIn_Mode, //!< [Sa * Da, Sa * Dc] + G2D_SrcOut_Mode, //!< [Sa * (1 - Da), Sc * (1 - Da)] + G2D_DstOut_Mode, //!< [Da * (1 - Sa), Dc * (1 - Sa)] + G2D_SrcATop_Mode, //!< [Da, Sc * Da + (1 - Sa) * Dc] + G2D_DstATop_Mode, //!< [Sa, Sa * Dc + Sc * (1 - Da)] + G2D_Xor_Mode, //!< [Sa + Da - 2 * Sa * Da, Sc * (1 - Da) + (1 - Sa) * Dc] + + // these modes are defined in the SVG Compositing standard + // http://www.w3.org/TR/2009/WD-SVGCompositing-20090430/ + G2D_Plus_Mode, + G2D_Multiply_Mode, + G2D_Screen_Mode, + G2D_Overlay_Mode, + G2D_Darken_Mode, + G2D_Lighten_Mode, + G2D_ColorDodge_Mode, + G2D_ColorBurn_Mode, + G2D_HardLight_Mode, + G2D_SoftLight_Mode, + G2D_Difference_Mode, + G2D_Exclusion_Mode, + + kLastMode = G2D_Exclusion_Mode +} G2D_PORTTERDUFF_MODE; + +typedef enum { + G2D_MEMORY_KERNEL, + G2D_MEMORY_USER +} G2D_MEMORY_TYPE; + +typedef struct { + int x; + int y; + unsigned int w; + unsigned int h; + unsigned int full_w; + unsigned int full_h; + int color_format; + unsigned int bytes_per_pixel; + unsigned char * addr; +} g2d_rect; + +typedef struct { + unsigned int rotate_val; + unsigned int alpha_val; + + unsigned int blue_screen_mode; //true : enable, false : disable + unsigned int color_key_val; //screen color value + unsigned int color_switch_val; //one color + + unsigned int src_color; // when set one color on SRC + + unsigned int third_op_mode; + unsigned int rop_mode; + unsigned int mask_mode; + unsigned int render_mode; + unsigned int potterduff_mode; + unsigned int memory_type; +} g2d_flag; + +typedef struct { + unsigned int t; + unsigned int b; + unsigned int l; + unsigned int r; +} g2d_clip; + +typedef struct { + g2d_rect src_rect; + g2d_rect dst_rect; + g2d_clip clip; + g2d_flag flag; +} g2d_params; + +struct g2d_dma_info { + unsigned long addr; + unsigned int size; +}; + +typedef struct _sec_g2d_t { + int dev_fd; + g2d_params params; +}sec_g2d_t; + +typedef struct __s5p_rect { + uint32_t x; + uint32_t y; + uint32_t w; + uint32_t h; +} __s5p_rect; + +typedef struct __s5p_img { + uint32_t width; + uint32_t height; + uint32_t format; + uint32_t offset; + uint32_t base; + int memory_id; +} __s5p_img; + +#endif /*_SEC_G2D_DRIVER_H_*/ diff --git a/exynos5/hal/include/sec_utils.h b/exynos5/hal/include/sec_utils.h new file mode 100644 index 0000000..4aed6e0 --- /dev/null +++ b/exynos5/hal/include/sec_utils.h @@ -0,0 +1,306 @@ +/* + * Copyright@ Samsung Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +*/ + +#ifndef __SAMSUNG_SYSLSI_SEC_COMMON_H__ +#define __SAMSUNG_SYSLSI_SEC_COMMON_H__ + +//---------------------------------------------------------// +// Include +//---------------------------------------------------------// + +#include +#include "sec_format.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include "videodev2_samsung.h" + +#ifdef __cplusplus +} +#endif + +//---------------------------------------------------------// +// Common structure // +//---------------------------------------------------------// +struct ADDRS { + unsigned int addr_y; + unsigned int addr_cbcr; + unsigned int buf_idx; + unsigned int reserved; +}; + +//---------------------------------------------------------// +// Common function // +//---------------------------------------------------------// +inline int HAL_PIXEL_FORMAT_2_V4L2_PIX(int HAL_PIXEL_FORMAT) +{ + int V4L2_PIX = -1; + + switch (HAL_PIXEL_FORMAT) { + case HAL_PIXEL_FORMAT_RGBA_8888: + case HAL_PIXEL_FORMAT_RGBX_8888: + V4L2_PIX = V4L2_PIX_FMT_RGB32; + break; + + case HAL_PIXEL_FORMAT_RGB_888: + V4L2_PIX = V4L2_PIX_FMT_RGB24; + break; + + case HAL_PIXEL_FORMAT_RGB_565: + V4L2_PIX = V4L2_PIX_FMT_RGB565; + break; + + case HAL_PIXEL_FORMAT_BGRA_8888: + V4L2_PIX = V4L2_PIX_FMT_RGB32; + break; + + case HAL_PIXEL_FORMAT_RGBA_5551: + V4L2_PIX = V4L2_PIX_FMT_RGB555X; + break; + + case HAL_PIXEL_FORMAT_RGBA_4444: + V4L2_PIX = V4L2_PIX_FMT_RGB444; + break; + + case HAL_PIXEL_FORMAT_YV12: + case HAL_PIXEL_FORMAT_YCbCr_420_P: + case HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_P_SBS_LR: + case HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_P_SBS_RL: + case HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_P_TB_LR: + case HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_P_TB_RL: + V4L2_PIX = V4L2_PIX_FMT_YUV420; + break; + + case HAL_PIXEL_FORMAT_YCbCr_422_SP: + case HAL_PIXEL_FORMAT_CUSTOM_YCbCr_422_SP: + V4L2_PIX = V4L2_PIX_FMT_NV61; + break; + + case HAL_PIXEL_FORMAT_YCbCr_420_SP: + case HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_SP: + V4L2_PIX = V4L2_PIX_FMT_NV12; + break; + + case HAL_PIXEL_FORMAT_YCbCr_422_I: + case HAL_PIXEL_FORMAT_CUSTOM_YCbCr_422_I: + V4L2_PIX = V4L2_PIX_FMT_YUYV; + break; + + case HAL_PIXEL_FORMAT_YCbCr_422_P: + V4L2_PIX = V4L2_PIX_FMT_YUV422P; + break; + + case HAL_PIXEL_FORMAT_CbYCrY_422_I: + case HAL_PIXEL_FORMAT_CUSTOM_CbYCrY_422_I: + V4L2_PIX = V4L2_PIX_FMT_UYVY; + break; + + case HAL_PIXEL_FORMAT_YCrCb_422_SP: + case HAL_PIXEL_FORMAT_CUSTOM_YCrCb_422_SP: + V4L2_PIX = V4L2_PIX_FMT_NV16; + break; + + case HAL_PIXEL_FORMAT_YCrCb_420_SP: + case HAL_PIXEL_FORMAT_CUSTOM_YCrCb_420_SP: + V4L2_PIX = V4L2_PIX_FMT_NV21; + break; + + case HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_SP_TILED: + V4L2_PIX = V4L2_PIX_FMT_NV12T; + break; + + case HAL_PIXEL_FORMAT_CUSTOM_YCrCb_422_I: + V4L2_PIX = V4L2_PIX_FMT_YVYU; + break; + + case HAL_PIXEL_FORMAT_CUSTOM_CrYCbY_422_I: + V4L2_PIX = V4L2_PIX_FMT_VYUY; + break; + + default: + LOGE("%s::unmatched HAL_PIXEL_FORMAT color_space(0x%x)\n", + __func__, HAL_PIXEL_FORMAT); + break; + } + + return V4L2_PIX; +} + +inline int V4L2_PIX_2_HAL_PIXEL_FORMAT(int V4L2_PIX) +{ + int HAL_PIXEL_FORMAT = -1; + + switch (V4L2_PIX) { + case V4L2_PIX_FMT_RGB32: + HAL_PIXEL_FORMAT = HAL_PIXEL_FORMAT_RGBA_8888; + break; + + case V4L2_PIX_FMT_RGB24: + HAL_PIXEL_FORMAT = HAL_PIXEL_FORMAT_RGB_888; + break; + + case V4L2_PIX_FMT_RGB565: + HAL_PIXEL_FORMAT = HAL_PIXEL_FORMAT_RGB_565; + break; + + case V4L2_PIX_FMT_BGR32: + HAL_PIXEL_FORMAT = HAL_PIXEL_FORMAT_BGRA_8888; + break; + + case V4L2_PIX_FMT_RGB555X: + HAL_PIXEL_FORMAT = HAL_PIXEL_FORMAT_RGBA_5551; + break; + + case V4L2_PIX_FMT_RGB444: + HAL_PIXEL_FORMAT = HAL_PIXEL_FORMAT_RGBA_4444; + break; + + case V4L2_PIX_FMT_YUV420: + HAL_PIXEL_FORMAT = HAL_PIXEL_FORMAT_YCbCr_420_P; + break; + + case V4L2_PIX_FMT_NV16: + HAL_PIXEL_FORMAT = HAL_PIXEL_FORMAT_CUSTOM_YCrCb_422_SP; + break; + + case V4L2_PIX_FMT_NV12: + HAL_PIXEL_FORMAT = HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_SP; + break; + + case V4L2_PIX_FMT_YUYV: + HAL_PIXEL_FORMAT = HAL_PIXEL_FORMAT_CUSTOM_YCbCr_422_I; + break; + + case V4L2_PIX_FMT_YUV422P: + HAL_PIXEL_FORMAT = HAL_PIXEL_FORMAT_YCbCr_422_P; + break; + + case V4L2_PIX_FMT_UYVY: + HAL_PIXEL_FORMAT = HAL_PIXEL_FORMAT_CUSTOM_CbYCrY_422_I; + break; + + case V4L2_PIX_FMT_NV21: + HAL_PIXEL_FORMAT = HAL_PIXEL_FORMAT_CUSTOM_YCrCb_420_SP; + break; + + case V4L2_PIX_FMT_NV12T: + HAL_PIXEL_FORMAT = HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_SP_TILED; + break; + + case V4L2_PIX_FMT_NV61: + HAL_PIXEL_FORMAT = HAL_PIXEL_FORMAT_CUSTOM_YCbCr_422_SP; + break; + + case V4L2_PIX_FMT_YVYU: + HAL_PIXEL_FORMAT = HAL_PIXEL_FORMAT_CUSTOM_YCrCb_422_I; + break; + + case V4L2_PIX_FMT_VYUY: + HAL_PIXEL_FORMAT = HAL_PIXEL_FORMAT_CUSTOM_CrYCbY_422_I; + break; + + default: + LOGE("%s::unmatched V4L2_PIX color_space(%d)\n", + __func__, V4L2_PIX); + break; + } + + return HAL_PIXEL_FORMAT; +} + +#define ALIGN_TO_32B(x) ((((x) + (1 << 5) - 1) >> 5) << 5) +#define ALIGN_TO_128B(x) ((((x) + (1 << 7) - 1) >> 7) << 7) +#define ALIGN_TO_8KB(x) ((((x) + (1 << 13) - 1) >> 13) << 13) + +#define GET_32BPP_FRAME_SIZE(w, h) (((w) * (h)) << 2) +#define GET_24BPP_FRAME_SIZE(w, h) (((w) * (h)) * 3) +#define GET_16BPP_FRAME_SIZE(w, h) (((w) * (h)) << 1) + +inline unsigned int FRAME_SIZE(int HAL_PIXEL_FORMAT, int w, int h) +{ + unsigned int frame_size = 0; + unsigned int size = 0; + + switch (HAL_PIXEL_FORMAT) { + // 16bpp + case HAL_PIXEL_FORMAT_RGB_565: + case HAL_PIXEL_FORMAT_RGBA_5551: + case HAL_PIXEL_FORMAT_RGBA_4444: + frame_size = GET_16BPP_FRAME_SIZE(w, h); + break; + + // 24bpp + case HAL_PIXEL_FORMAT_RGB_888: + frame_size = GET_24BPP_FRAME_SIZE(w, h); + break; + + // 32bpp + case HAL_PIXEL_FORMAT_RGBA_8888: + case HAL_PIXEL_FORMAT_BGRA_8888: + case HAL_PIXEL_FORMAT_RGBX_8888: + frame_size = GET_32BPP_FRAME_SIZE(w, h); + break; + + // 12bpp + case HAL_PIXEL_FORMAT_YV12: + case HAL_PIXEL_FORMAT_YCrCb_420_SP: + case HAL_PIXEL_FORMAT_YCbCr_420_P: + case HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_P_SBS_LR: + case HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_P_SBS_RL: + case HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_P_TB_LR: + case HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_P_TB_RL: + case HAL_PIXEL_FORMAT_YCbCr_420_I: + case HAL_PIXEL_FORMAT_CbYCrY_420_I: + case HAL_PIXEL_FORMAT_YCbCr_420_SP: + case HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_SP: + case HAL_PIXEL_FORMAT_CUSTOM_YCrCb_420_SP: + size = w * h; + frame_size = size + ((size >> 2) << 1); + break; + + case HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_SP_TILED: + frame_size = ALIGN_TO_8KB(ALIGN_TO_128B(w) * ALIGN_TO_32B(h)) + + ALIGN_TO_8KB(ALIGN_TO_128B(w) * ALIGN_TO_32B(h >> 1)); + break; + + // 16bpp + case HAL_PIXEL_FORMAT_YCbCr_422_SP: + case HAL_PIXEL_FORMAT_YCbCr_422_I: + case HAL_PIXEL_FORMAT_YCbCr_422_P: + case HAL_PIXEL_FORMAT_CbYCrY_422_I: + case HAL_PIXEL_FORMAT_YCrCb_422_SP: + case HAL_PIXEL_FORMAT_CUSTOM_YCbCr_422_SP: + case HAL_PIXEL_FORMAT_CUSTOM_YCrCb_422_SP: + case HAL_PIXEL_FORMAT_CUSTOM_YCbCr_422_I: + case HAL_PIXEL_FORMAT_CUSTOM_YCrCb_422_I: + case HAL_PIXEL_FORMAT_CUSTOM_CbYCrY_422_I: + case HAL_PIXEL_FORMAT_CUSTOM_CrYCbY_422_I: + frame_size = GET_16BPP_FRAME_SIZE(w, h); + break; + + default: + LOGD("%s::no matching source colorformat(0x%x), w(%d), h(%d) fail\n", + __func__, HAL_PIXEL_FORMAT, w, h); + break; + } + + return frame_size; +} + +#endif //__SAMSUNG_SYSLSI_SEC_COMMON_H__ \ No newline at end of file diff --git a/exynos5/hal/include/sec_utils_v4l2.h b/exynos5/hal/include/sec_utils_v4l2.h new file mode 100644 index 0000000..5c05c1d --- /dev/null +++ b/exynos5/hal/include/sec_utils_v4l2.h @@ -0,0 +1,330 @@ +/* + * Copyright@ Samsung Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +*/ + +/* + * file sec_utils_v4l2.h + * brief header file for sec_utils_v4l2.h + * author Sangwoo, Park(sw5771.park@samsung.com) + * date 2011/06/02 + * + * Revision History: + * - 2010/06/03 : Sangwoo, Park(sw5771.park@samsung.com) + * Initial version + * + * - 2011/12/07 : Hyeonmyeong Choi( hyeon.choi@samsung.com) + * Add V4L2_PIX_FMT_YVU420M + * + */ + +#ifndef __SAMSUNG_SYSLSI_SEC_COMMON_H__ +#define __SAMSUNG_SYSLSI_SEC_COMMON_H__ + +//---------------------------------------------------------// +// Include +//---------------------------------------------------------// + +#include +#include "sec_format.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#include "videodev2.h" + +#ifdef __cplusplus +} +#endif + +//---------------------------------------------------------// +// Common structure // +//---------------------------------------------------------// +struct ADDRS { + unsigned int addr_y; + unsigned int addr_cbcr; + unsigned int buf_idx; + unsigned int reserved; +}; + +//---------------------------------------------------------// +// Common function // +//---------------------------------------------------------// +inline int HAL_PIXEL_FORMAT_2_V4L2_PIX(int HAL_PIXEL_FORMAT) +{ + int V4L2_PIX = -1; + + switch (HAL_PIXEL_FORMAT) { + case HAL_PIXEL_FORMAT_RGBA_8888: + case HAL_PIXEL_FORMAT_RGBX_8888: + V4L2_PIX = V4L2_PIX_FMT_RGB32; + break; + + case HAL_PIXEL_FORMAT_RGB_888: + V4L2_PIX = V4L2_PIX_FMT_RGB24; + break; + + case HAL_PIXEL_FORMAT_RGB_565: + V4L2_PIX = V4L2_PIX_FMT_RGB565; + break; + + case HAL_PIXEL_FORMAT_BGRA_8888: + V4L2_PIX = V4L2_PIX_FMT_BGR32; + break; + + case HAL_PIXEL_FORMAT_RGBA_5551: + V4L2_PIX = V4L2_PIX_FMT_RGB555X; + break; + + case HAL_PIXEL_FORMAT_RGBA_4444: + V4L2_PIX = V4L2_PIX_FMT_RGB444; + break; + + case HAL_PIXEL_FORMAT_YV12: + V4L2_PIX = V4L2_PIX_FMT_YVU420M; + break; + + case HAL_PIXEL_FORMAT_YCbCr_420_P: + case HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_P_SBS_LR: + case HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_P_SBS_RL: + case HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_P_TB_LR: + case HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_P_TB_RL: + V4L2_PIX = V4L2_PIX_FMT_YUV420M; + break; + + case HAL_PIXEL_FORMAT_YCbCr_422_SP: + case HAL_PIXEL_FORMAT_CUSTOM_YCbCr_422_SP: + V4L2_PIX = V4L2_PIX_FMT_NV61; + break; + + case HAL_PIXEL_FORMAT_YCbCr_420_SP: + case HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_SP: + V4L2_PIX = V4L2_PIX_FMT_NV12M; + break; + + case HAL_PIXEL_FORMAT_YCbCr_422_I: + case HAL_PIXEL_FORMAT_CUSTOM_YCbCr_422_I: + V4L2_PIX = V4L2_PIX_FMT_YUYV; + break; + + case HAL_PIXEL_FORMAT_YCbCr_422_P: + V4L2_PIX = V4L2_PIX_FMT_YUV422P; + break; + + case HAL_PIXEL_FORMAT_CbYCrY_422_I: + case HAL_PIXEL_FORMAT_CUSTOM_CbYCrY_422_I: + V4L2_PIX = V4L2_PIX_FMT_UYVY; + break; + + case HAL_PIXEL_FORMAT_YCrCb_422_SP: + case HAL_PIXEL_FORMAT_CUSTOM_YCrCb_422_SP: + V4L2_PIX = V4L2_PIX_FMT_NV16; + break; + + case HAL_PIXEL_FORMAT_YCrCb_420_SP: + case HAL_PIXEL_FORMAT_CUSTOM_YCrCb_420_SP: + V4L2_PIX = V4L2_PIX_FMT_NV21; + break; + + case HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_SP_TILED: + V4L2_PIX = V4L2_PIX_FMT_NV12MT; + break; + + case HAL_PIXEL_FORMAT_CUSTOM_YCrCb_422_I: + V4L2_PIX = V4L2_PIX_FMT_YVYU; + break; + + case HAL_PIXEL_FORMAT_CUSTOM_CrYCbY_422_I: + V4L2_PIX = V4L2_PIX_FMT_VYUY; + break; + + default: + LOGE("%s::unmatched HAL_PIXEL_FORMAT color_space(0x%x)\n", + __func__, HAL_PIXEL_FORMAT); + break; + } + + return V4L2_PIX; +} + +inline int V4L2_PIX_2_HAL_PIXEL_FORMAT(int V4L2_PIX) +{ + int HAL_PIXEL_FORMAT = -1; + + switch (V4L2_PIX) { + case V4L2_PIX_FMT_RGB32: + HAL_PIXEL_FORMAT = HAL_PIXEL_FORMAT_RGBA_8888; + break; + + case V4L2_PIX_FMT_RGB24: + HAL_PIXEL_FORMAT = HAL_PIXEL_FORMAT_RGB_888; + break; + + case V4L2_PIX_FMT_RGB565: + HAL_PIXEL_FORMAT = HAL_PIXEL_FORMAT_RGB_565; + break; + + case V4L2_PIX_FMT_BGR32: + HAL_PIXEL_FORMAT = HAL_PIXEL_FORMAT_BGRA_8888; + break; + + case V4L2_PIX_FMT_RGB555X: + HAL_PIXEL_FORMAT = HAL_PIXEL_FORMAT_RGBA_5551; + break; + + case V4L2_PIX_FMT_RGB444: + HAL_PIXEL_FORMAT = HAL_PIXEL_FORMAT_RGBA_4444; + break; + + case V4L2_PIX_FMT_YUV420: + case V4L2_PIX_FMT_YUV420M: + HAL_PIXEL_FORMAT = HAL_PIXEL_FORMAT_YCbCr_420_P; + break; + + case V4L2_PIX_FMT_YVU420: + case V4L2_PIX_FMT_YVU420M: + HAL_PIXEL_FORMAT = HAL_PIXEL_FORMAT_YV12; + break; + + case V4L2_PIX_FMT_NV16: + HAL_PIXEL_FORMAT = HAL_PIXEL_FORMAT_CUSTOM_YCrCb_422_SP; + break; + + case V4L2_PIX_FMT_NV12: + HAL_PIXEL_FORMAT = HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_SP; + break; + + case V4L2_PIX_FMT_YUYV: + HAL_PIXEL_FORMAT = HAL_PIXEL_FORMAT_CUSTOM_YCbCr_422_I; + break; + + case V4L2_PIX_FMT_YUV422P: + HAL_PIXEL_FORMAT = HAL_PIXEL_FORMAT_YCbCr_422_P; + break; + + case V4L2_PIX_FMT_UYVY: + HAL_PIXEL_FORMAT = HAL_PIXEL_FORMAT_CUSTOM_CbYCrY_422_I; + break; + + case V4L2_PIX_FMT_NV21: + HAL_PIXEL_FORMAT = HAL_PIXEL_FORMAT_CUSTOM_YCrCb_420_SP; + break; + case V4L2_PIX_FMT_NV12MT: + + HAL_PIXEL_FORMAT = HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_SP_TILED; + break; + + case V4L2_PIX_FMT_NV61: + HAL_PIXEL_FORMAT = HAL_PIXEL_FORMAT_CUSTOM_YCbCr_422_SP; + break; + + case V4L2_PIX_FMT_YVYU: + HAL_PIXEL_FORMAT = HAL_PIXEL_FORMAT_CUSTOM_YCrCb_422_I; + break; + + case V4L2_PIX_FMT_VYUY: + HAL_PIXEL_FORMAT = HAL_PIXEL_FORMAT_CUSTOM_CrYCbY_422_I; + break; + + default: + LOGE("%s::unmatched V4L2_PIX color_space(%d)\n", + __func__, V4L2_PIX); + break; + } + + return HAL_PIXEL_FORMAT; +} + +#define ALIGN_TO_32B(x) ((((x) + (1 << 5) - 1) >> 5) << 5) +#define ALIGN_TO_128B(x) ((((x) + (1 << 7) - 1) >> 7) << 7) +#define ALIGN_TO_8KB(x) ((((x) + (1 << 13) - 1) >> 13) << 13) +#define ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1)) + +#define GET_32BPP_FRAME_SIZE(w, h) (((w) * (h)) << 2) +#define GET_24BPP_FRAME_SIZE(w, h) (((w) * (h)) * 3) +#define GET_16BPP_FRAME_SIZE(w, h) (((w) * (h)) << 1) + +inline unsigned int FRAME_SIZE(int HAL_PIXEL_FORMAT, int w, int h) +{ + unsigned int frame_size = 0; + unsigned int size = 0; + + switch (HAL_PIXEL_FORMAT) { + // 16bpp + case HAL_PIXEL_FORMAT_RGB_565: + case HAL_PIXEL_FORMAT_RGBA_5551: + case HAL_PIXEL_FORMAT_RGBA_4444: + frame_size = GET_16BPP_FRAME_SIZE(w, h); + break; + + // 24bpp + case HAL_PIXEL_FORMAT_RGB_888: + frame_size = GET_24BPP_FRAME_SIZE(w, h); + break; + + // 32bpp + case HAL_PIXEL_FORMAT_RGBA_8888: + case HAL_PIXEL_FORMAT_BGRA_8888: + case HAL_PIXEL_FORMAT_RGBX_8888: + frame_size = GET_32BPP_FRAME_SIZE(w, h); + break; + + // 12bpp + case HAL_PIXEL_FORMAT_YV12: + case HAL_PIXEL_FORMAT_YCrCb_420_SP: + case HAL_PIXEL_FORMAT_YCbCr_420_P: + case HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_P_SBS_LR: + case HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_P_SBS_RL: + case HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_P_TB_LR: + case HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_P_TB_RL: + case HAL_PIXEL_FORMAT_YCbCr_420_I: + case HAL_PIXEL_FORMAT_CbYCrY_420_I: + case HAL_PIXEL_FORMAT_YCbCr_420_SP: + case HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_SP: + case HAL_PIXEL_FORMAT_CUSTOM_YCrCb_420_SP: + size = w * h; + frame_size = size + ((size >> 2) << 1); + break; + + case HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_SP_TILED: + frame_size = ALIGN_TO_8KB(ALIGN_TO_128B(w) * ALIGN_TO_32B(h)) + + ALIGN_TO_8KB(ALIGN_TO_128B(w) * ALIGN_TO_32B(h >> 1)); + break; + + // 16bpp + case HAL_PIXEL_FORMAT_YCbCr_422_SP: + case HAL_PIXEL_FORMAT_YCbCr_422_I: + case HAL_PIXEL_FORMAT_YCbCr_422_P: + case HAL_PIXEL_FORMAT_CbYCrY_422_I: + case HAL_PIXEL_FORMAT_YCrCb_422_SP: + case HAL_PIXEL_FORMAT_CUSTOM_YCbCr_422_SP: + case HAL_PIXEL_FORMAT_CUSTOM_YCrCb_422_SP: + case HAL_PIXEL_FORMAT_CUSTOM_YCbCr_422_I: + case HAL_PIXEL_FORMAT_CUSTOM_YCrCb_422_I: + case HAL_PIXEL_FORMAT_CUSTOM_CbYCrY_422_I: + case HAL_PIXEL_FORMAT_CUSTOM_CrYCbY_422_I: + frame_size = GET_16BPP_FRAME_SIZE(w, h); + break; + + default: + LOGD("%s::no matching source colorformat(0x%x), w(%d), h(%d) fail\n", + __func__, HAL_PIXEL_FORMAT, w, h); + break; + } + + return frame_size; +} + +#endif //__SAMSUNG_SYSLSI_SEC_COMMON_H__ diff --git a/exynos5/hal/include/ump.h b/exynos5/hal/include/ump.h new file mode 100644 index 0000000..487e2c2 --- /dev/null +++ b/exynos5/hal/include/ump.h @@ -0,0 +1,627 @@ +/* + * This confidential and proprietary software may be used only as + * authorised by a licensing agreement from ARM Limited + * (C) COPYRIGHT 2008-2011 ARM Limited + * ALL RIGHTS RESERVED + * The entire notice above must be reproduced on all authorised + * copies and copies may only be made to the extent permitted + * by a licensing agreement from ARM Limited. + */ + +/** + * @file ump.h + * + * This file contains the user space part of the UMP API. + * + */ + +#ifndef _UMP_H_ +#define _UMP_H_ + +/** + * @page page_base_ump Unified Memory Provider API + * + * UMP(Universal Memory Provider) is an API to allocate memory with some special unique requirements; + * @li Known physical addresses + * @li Non-relocatable/pinned + * @li Won't be paged out + * @li Shareable between processes (selectable per allocation for security reasons) + * @li Shareable with multiple hardware devices + * @li Physically contiguous (optional) + * @li Extended (not valid with the physically contiguous requirement for obvious reasons) + * + * Allocations from UMP can safely be used with hardware devices and other processes. + * All uses are reference counted, so memory won't be released until all participating hardware devices and processes have released their use of the allocation. + * This means that even if a process frees memory too early or crashes any hardware using the memory won't corrupt freed memory. + * + * Allocations inside a process is represented using an UMP memory handle. + * + * Each allocation is represented by a system-wide unique ID (called a secure ID), + * which can be obtained from a handle and be shared with other processes or given to a device driver. + * + * Based on a secure ID a new handle can be created either in kernel space by a driver + * or in user space by some other process to use the same allocation. + * + * Based on the handle a driver in kernel space can obtain information about the physical memory block(s) + * an allocation consists of and increment or decrement the reference count. + * + * Usage in user-space also adds a reference to the memory, but it's managed by the UMP device driver. + * + * The user-space reference count is only local to the process, so a process can't by accident decrement + * the count one time too many and cause the memory to be freed while it's in use by a hardware device. + * + * This is all handled by the UMP kernel code, no user-space code cooperation is needed. + * + * By default an allocation is only accessible in the same process or what other security boundary the OS uses. + * If marked as shared it can be accessed in all processes, the kernel space customer defined security filter permitting of course. + * See @ref ump_dd_security_filter for more information about this security filter. + * + * @sa ump_api + * @sa example_user_api.c + * @sa example_kernel_api.c + * + * @example example_user_api.c + * @example example_kernel_api.c + * + */ + +/** @defgroup ump_api Unified Memory Provider APIs + */ + +/** + * @addtogroup ump_api + * @{ + */ + +/** @defgroup ump_user_space_api UMP User Space API + * @{ */ + + +#include "ump_platform.h" +#include "ump_common.h" +#include "ion.h" + +#ifndef __KERNEL__ +#include +#include +#include +#include +#include +#endif + +#ifdef __cplusplus +extern "C" +{ +#endif + +/** + * External representation of a UMP handle in user space. + */ +typedef void * ump_handle; + +/** + * Value to indicate an invalid UMP memory handle. + */ +#define UMP_INVALID_MEMORY_HANDLE ((ump_handle)0) + +/** + * Opens and initializes the UMP library. + * + * This function must be called at least once before calling any other UMP API functions. + * Each successful open call is reference counted and must be matched with a call to @ref ump_close. + * It is safe to call @a ump_open after a @a ump_close has terminated a previous session. + * + * UMP_ERROR will be returned if: + * - the reference count is ULONG_MAX so would overflow. + * - the reference count is 0 and the backend fails to open. + * + * UMP API: v1 and v2 + * @see ump_close + * + * @return UMP_OK indicates success, UMP_ERROR indicates failure. + */ +UMP_API_EXPORT ump_result ump_open(void) CHECK_RESULT; + + +/** + * Terminate the UMP library. + * + * This must be called once for every successful @ref ump_open. The UMP library is + * terminated when, and only when, the last open reference to the UMP interface is closed. + * + * If this is called while having active allocations or mappings the behavior is undefined. + * + * UMP API: v1 and v2 + * @see ump_open + */ +UMP_API_EXPORT void ump_close(void); + + +/** + * Retrieves the secure ID for the specified UMP memory. + * + * This identifier is unique across the entire system, and uniquely identifies + * the specified UMP memory allocation. This identifier can later be used through the + * v2 API: + * @ref ump_from_secure_id or + * @ref ump_dd_from_secure_id + * v1 API: + * @ref ump_handle_create_from_secure_id or + * @ref ump_dd_handle_create_from_secure_id + * + * functions in order to access this UMP memory, for instance from another process. + * Unless the allocation was marked as shared the returned ID will only be resolvable in the same process as did the allocation. + * + * If called on an @a UMP_INVALID_MEMORY_HANDLE it will return @a UMP_INVALID_SECURE_ID. + * + * @note There is a kernel space equivalent function called @ref ump_dd_secure_id_get + * + * UMP API: v1 and v2 + * + * @see ump_dd_secure_id_get + * v2 API: + * @see ump_from_secure_id + * @see ump_dd_from_secure_id + * v1 API: + * @see ump_handle_create_from_secure_id + * @see ump_dd_from_secure_id + * + * @param mem Handle to UMP memory. + * + * @return Returns the secure ID for the specified UMP memory. + */ +UMP_API_EXPORT ump_secure_id ump_secure_id_get(const ump_handle mem) CHECK_RESULT; + + +/** + * Synchronous mapping cache sync operation. + * + * Performs the requested CPU side cache sync operations before returning. + * A clean must be done before the memory is guaranteed to be visible in main memory. + * Any device-specific cache clean/invalidate must be done in combination with this routine, if needed. + * Function returns cache status for the allocation. + * + * Example: + * @code + * ump_cpu_msync_now(handle, UMP_MSYNC_CLEAN, ptr, size); + * device_invalidate(...); + * // ... run device ... + * device_clean(...); + * ump_cpu_msync_now(handle, UMP_MSYNC_CLEAN_AND_INVALIDATE, ptr, size); + * // ... safe to access on the cpu side again ... + * @endcode + * + * + * Calls to operate on an @a UMP_INVALID_MEMORY_HANDLE will result in undefined behavior. + * Debug builds will assert on this. + * + * If @a address is not inside a mapping previously obtained from the @a ump_handle provided results in undefined behavior. + * If @a address combined with @a size results on reaching beyond the end of the buffer results in undefined behavior. + * + * UMP API: v1 and v2 + * @param mem Handle to UMP memory + * @param op Cache operation to perform + * @param[in] address The CPU address where to start the sync operation, this can be at an offset from the start of the allocation. + * @param size The number of bytes to be synced. + * + * @return Returns 1 if cache is enabled, 0 if cache is disabled for the given allocation. + * + */ +UMP_API_EXPORT int ump_cpu_msync_now(ump_handle mem, ump_cpu_msync_op op, void * address, size_t size); + + +#ifndef UMP_BLOCK_V2_API + +/** + * Allocate a buffer. + * The life-time of the allocation is controlled by a reference count. + * The reference count of the returned buffer is set to 1. + * The memory will be freed once the reference count reaches 0. + * Use @ref ump_retain and @ref ump_release to control the reference count. + * The contens of the memory returned will be zero initialized. + * + * The @ref UMP_V1_API_DEFAULT_ALLOCATION_FLAGS can be used + * to create a buffer that can be shared with v1 API applications. + * The allocation will be limited to 32-bit PA. + * + * The @ref UMP_CONSTRAINT_UNCACHED flag disables cache for all cpu mappings for this allocation. + * + * UMP API: v2 + * @param size Number of bytes to allocate. Will be padded up to a multiple of the page size. + * @param flags Bit-wise OR of zero or more of the allocation flag bits. + * @return Handle to the new allocation, or @a UMP_INVALID_MEMORY_HANDLE on allocation failure. + */ +UMP_API_EXPORT ump_handle ump_allocate_64(u64 size, ump_alloc_flags flags) CHECK_RESULT; + + +/** + * Creates a handle based on a shared UMP memory allocation. + * + * The usage of UMP memory is reference counted, so this will increment the reference + * count by one for the specified UMP memory. + * + * If called on an @a UMP_INVALID_SECURE_ID this will return @a UMP_INVALID_MEMORY_HANDLE. + * If called on an non-shared allocation and this is a different process @a UMP_INVALID_MEMORY_HANDLE will be returned. + * + * Use @ref ump_release when there is no longer any + * use for the retrieved handle. + * + * @note There is a kernel space equivalent function called @ref ump_dd_from_secure_id + * + * UMP API: v2 + * @see ump_release + * @see ump_dd_from_secure_id + * + * @param secure_id The secure ID of the UMP memory to open, that can be retrieved using the @ref ump_secure_id_get function. + * + * @return @a UMP_INVALID_MEMORY_HANDLE indicates failure, otherwise a valid handle is returned. + */ +UMP_API_EXPORT ump_handle ump_from_secure_id(ump_secure_id secure_id) CHECK_RESULT; + + +/** + * 64 bit version of @ref ump_size_get. Retrieves the actual size of the specified UMP memory. + * + * The size is reported in bytes, and is typically a multiple of the page size. + * If called on an @a UMP_INVALID_MEMORY_HANDLE will result in undefined behavior. + * Debug builds will assert on this. + * + * @note There is a kernel space equivalent function called @ref ump_dd_size_get_64 + * + * UMP API: v2 + * @see ump_dd_size_get_64 + * + * @param mem Handle to UMP memory. + * + * @return Returns the allocated 64-bit size of the specified UMP memory, in bytes. + */ +UMP_API_EXPORT u64 ump_size_get_64(const ump_handle mem) CHECK_RESULT; + + +/** + * Retrieves a memory mapped pointer to the specified UMP memory. + * + * This function retrieves a memory mapped pointer to the specified UMP memory, that can be used by the CPU.@n + * Every successful call to @a ump_map must be matched with a call to @ref ump_unmap when the mapping is no longer needed. + * + * An offset and/or size resulting in going beyond the end of the buffer will case the function to return NULL. + * + * Calling on @a UMP_INVALID_MEMORY_HANDLE results in undefined behavior. + * Debug builds will assert on this. + * + * @note Systems without a MMU for the CPU only return the physical address, because no mapping is required. + * + * UMP API: v2 + * @see ump_unmap + * + * @param mem Handle to UMP memory. + * @param offset An offset at which the mapping begins. + * @param size The number of bytes to map. Passing 0 does not retrieve a memory mapped + * pointer - instead NULL is returned. + * + * @return NULL indicates failure, otherwise a CPU mapped pointer is returned. + */ +UMP_API_EXPORT void * ump_map(ump_handle mem, u64 offset, size_t size) CHECK_RESULT; + + +/** + * Releases a previously mapped pointer to the specified UMP memory. + * + * Every successful call to @ref ump_map must be matched with a call to @a ump_unmap when the mapping is no longer needed. + * + * The following results in undefined behavior: + * - Called with an address not returned from @ref ump_map + * - Called with a different @a ump_handle than was used to obtain the pointer + * - Called with a different @a size than was used to obtain the pointer + * + * @note Systems without a MMU must still implement this function, even though no unmapping should be needed. + * + * UMP API: v2 + * @param mem Handle to UMP memory. + * @param[in] address The CPU virtual address returned by @ref ump_map + * @param size Size matching argument given to ump_map + */ +UMP_API_EXPORT void ump_unmap(ump_handle mem, void* address, size_t size); + + +/** + * Adds an extra reference to the specified UMP memory. + * + * This function adds an extra reference to the specified UMP memory. This function should + * be used every time a UMP memory handle is duplicated, that is, assigned to another ump_handle + * variable. The function @ref ump_release must then be used + * to release each copy of the UMP memory handle. + * + * It's safe to call this on both shared and non-shared handles. + * Calling on an @a UMP_INVALID_MEMORY_HANDLE results in undefined behavior. + * Debug builds will assert on this. + * + * @note You are not required to call @ref ump_retain + * for UMP handles returned from + * @ref ump_from_secure_id, + * because these handles are already reference counted by this function. + * + * @note There is a kernel space equivalent function called @ref ump_dd_retain + * + * UMP API: v2 + * @see ump_dd_retain + * + * @param mem Handle to UMP memory. + * @return UMP_OK indicates success, UMP_ERROR indicates failure. + */ +UMP_API_EXPORT ump_result ump_retain(ump_handle mem); + + +/** + * Releases a reference from the specified UMP memory. + * + * This function should be called once for every reference to the UMP memory handle. + * When the last reference is released, all resources associated with this UMP memory + * handle are freed. + * + * One can only call ump_release when matched with a successful ump_retain, ump_allocate_64 or ump_from_secure_id + * It's safe to call this on both shared and non-shared handles. + * If called on an @a UMP_INVALID_MEMORY_HANDLE it will return early. + * + * @note There is a kernel space equivalent function called @ref ump_dd_release + * + * UMP API: v2 + * @see ump_release + * + * @param mem Handle to UMP memory. + */ +UMP_API_EXPORT void ump_release(ump_handle mem); + + +/** + * Import external memory into UMP. + * + * This function creates a ump_handle wrapping memory provided by some external source. + * + * For reference counted types the returned handle represents one new reference, + * which must be freed using @a ump_release. + * The handle passed in still holds its reference and can still be used and must be released + * as it would be normally. + * + * For ownership based types the returned handle has claimed the ownership which will be released + * with @a ump_release. + * The handle passed in is no longer valid. + * + * A pointer to the handle type is required, not the type it self. + * + * The flags are used in the same way as for @a ump_allocate_64, except that these flags are ignored: + * @li UMP_CONSTRAINT_32BIT_ADDRESSABLE + * @li UMP_CONSTRAINT_PHYSICALLY_LINEAR + * + * The returned UMP handle can be used as any other ump_handle. + * + * Example for UMP_EXTERNAL_MEM_TYPE_ION: + * + * @code + * ump_handle h; + * ump_alloc_flags flags = get_requested_flags(); + * int fd = ion_fd_get(); + * h = ump_import(UMP_EXTERNAL_MEM_TYPE_ION, &fd, flags); + * // native release + * close(fd); + * ... + * ump_release(h); + * @endcode + * + * Example for a generic ownership based type: + * + * @code + * ump_handle h; + * ump_alloc_flags = get_requested_flags(); + * type t = type_claim(); + * h = ump_import(UMP_OWNERSHIP_BASED_TYPE, &t, flags); + * // native handle no longer valid + * t = INVALID; + * ... + * ump_release(h); + * @endcode + * + * UMP API: v2 + * @see ump_release + * + * @param type Type of external memory to import + * @param phandle Pointer to the handle to import. + * @param flags Bit-wise OR of zero or more of the allocation flag bits. + * @return Handle wrapping the imported memory, or @a UMP_INVALID_MEMORY_HANDLE on import failure. + */ +UMP_API_EXPORT ump_handle ump_import(enum ump_external_memory_type type, void * phandle, ump_alloc_flags flags) CHECK_RESULT; + +#endif /* UMP_BLOCK_V2_API */ + +/** @name UMP v1 API + * Functions provided to support compatibility with UMP v1 API + * + * You should use v1 API only with handles created with @ref ump_ref_drv_allocate + * and @ref ump_handle_create_from_secure_id. + * Using v1 API for handles created with v2 API can cause undefined behavior. + * + *@{ + */ + +#ifndef UMP_BLOCK_V1_API + +/** Allocate an UMP handle containing a memory buffer. + * + * If usage is UMP_REF_DRV_CONSTRAINT_USE_CACHE, the allocation is mapped as cached by the cpu. + * If it is UMP_REF_DRV_CONSTRAINT_NONE it is mapped as noncached. + * The flag UMP_REF_DRV_CONSTRAINT_PHYSICALLY_LINEAR is not supported. + * + * UMP API: v1 + * @param size The minimum size for the allocation. + * @param usage The allocation constraints. + */ + +UMP_API_EXPORT ump_handle ump_ref_drv_allocate(unsigned long size, ump_alloc_constraints usage); + + +/** + * Retrieves the actual size of the specified UMP memory. + * + * The size is reported in bytes, and is typically page aligned. + * + * @note There is a kernel space equivalent function called @ref ump_dd_size_get "ump_dd_size_get" + * + * UMP API: v1 + * @see ump_dd_size_get + * + * @param mem Handle to UMP memory. + * + * @return Returns the allocated size of the specified UMP memory, in bytes. + */ +UMP_API_EXPORT unsigned long ump_size_get(ump_handle mem) CHECK_RESULT; + + +/** + * Retrieves a handle to allocated UMP memory. + * + * The usage of UMP memory is reference counted, so this will increment the reference + * count by one for the specified UMP memory. + * Use @ref ump_reference_release "ump_reference_release" when there is no longer any + * use for the retrieved handle. + * + * @note There is a kernel space equivalent function called @ref ump_dd_handle_create_from_secure_id "ump_dd_handle_create_from_secure_id" + * + * UMP API: v1 + * @see ump_reference_release + * @see ump_dd_handle_create_from_secure_id + * + * @param secure_id The secure ID of the UMP memory to open, that can be retrieved using the @ref ump_secure_id_get "ump_secure_id_get " function. + * + * @return UMP_INVALID_MEMORY_HANDLE indicates failure, otherwise a valid handle is returned. + */ +UMP_API_EXPORT ump_handle ump_handle_create_from_secure_id(ump_secure_id secure_id) CHECK_RESULT; + + +/** + * Adds an extra reference to the specified UMP memory. + * + * This function adds an extra reference to the specified UMP memory. This function should + * be used every time a UMP memory handle is duplicated, that is, assigned to another ump_handle + * variable. The function @ref ump_reference_release "ump_reference_release" must then be used + * to release each copy of the UMP memory handle. + * + * @note You are not required to call @ref ump_reference_add "ump_reference_add" + * for UMP handles returned from + * @ref ump_handle_create_from_secure_id "ump_handle_create_from_secure_id", + * because these handles are already reference counted by this function. + * + * @note There is a kernel space equivalent function called @ref ump_dd_reference_add "ump_dd_reference_add" + * + * UMP API: v1 + * @see ump_dd_reference_add + * + * @param mem Handle to UMP memory. + */ +UMP_API_EXPORT void ump_reference_add(ump_handle mem); + + +/** + * Releases a reference from the specified UMP memory. + * + * This function should be called once for every reference to the UMP memory handle. + * When the last reference is released, all resources associated with this UMP memory + * handle are freed. + * + * @note There is a kernel space equivalent function called @ref ump_dd_reference_release "ump_dd_reference_release" + * + * UMP API: v1 + * @see ump_dd_reference_release + * + * @param mem Handle to UMP memory. + */ +UMP_API_EXPORT void ump_reference_release(ump_handle mem); + + +/** + * Retrieves a memory mapped pointer to the specified UMP memory. + * + * This function retrieves a memory mapped pointer to the specified UMP memory, + * that can be used by the CPU. Every successful call to + * @ref ump_mapped_pointer_get "ump_mapped_pointer_get" is reference counted, + * and must therefor be followed by a call to + * @ref ump_mapped_pointer_release "ump_mapped_pointer_release " when the + * memory mapping is no longer needed. + * + * @note Systems without a MMU for the CPU only return the physical address, because no mapping is required. + * + * UMP API: v1 + * @see ump_mapped_pointer_release + * + * @param mem Handle to UMP memory. + * + * @return NULL indicates failure, otherwise a CPU mapped pointer is returned. + */ +UMP_API_EXPORT void * ump_mapped_pointer_get(ump_handle mem); + + +/** + * Releases a previously mapped pointer to the specified UMP memory. + * + * The CPU mapping of the specified UMP memory memory is reference counted, + * so every call to @ref ump_mapped_pointer_get "ump_mapped_pointer_get" must + * be matched with a call to this function when the mapping is no longer needed. + * + * The CPU mapping is not removed before all references to the mapping is released. + * + * UMP API: v1 + * @note Systems without a MMU must still implement this function, even though no unmapping should be needed. + * + * @param mem Handle to UMP memory. + */ +UMP_API_EXPORT void ump_mapped_pointer_release(ump_handle mem); + + +/** + * Read from specified UMP memory. + * + * Another way of reading from (and writing to) UMP memory is to use the + * @ref ump_mapped_pointer_get "ump_mapped_pointer_get" to retrieve + * a CPU mapped pointer to the memory. + * + * UMP API: v1 + * @see ump_mapped_pointer_get + * + * @param dst Destination buffer. + * @param src Handle to UMP memory to read from. + * @param offset Where to start reading, given in bytes. + * @param length How much to read, given in bytes. + */ +UMP_API_EXPORT void ump_read(void * dst, ump_handle src, unsigned long offset, unsigned long length); + + +/** + * Write to specified UMP memory. + * + * Another way of writing to (and reading from) UMP memory is to use the + * @ref ump_mapped_pointer_get "ump_mapped_pointer_get" to retrieve + * a CPU mapped pointer to the memory. + * + * UMP API: v1 + * @see ump_mapped_pointer_get + * + * @param dst Handle to UMP memory to write to. + * @param offset Where to start writing, given in bytes. + * @param src Buffer to read from. + * @param length How much to write, given in bytes. + */ +UMP_API_EXPORT void ump_write(ump_handle dst, unsigned long offset, const void * src, unsigned long length); + +#endif /* UMP_BLOCK_V1_API */ + +/* @} */ + +#ifdef __cplusplus +} +#endif + + +/** @} */ /* end group ump_user_space_api */ + +/** @} */ /* end group ump_api */ + +#endif /* _UMP_H_ */ diff --git a/exynos5/hal/include/ump_common.h b/exynos5/hal/include/ump_common.h new file mode 100644 index 0000000..8fdeef1 --- /dev/null +++ b/exynos5/hal/include/ump_common.h @@ -0,0 +1,232 @@ +/* + * + * (C) COPYRIGHT 2010-2011 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + + + +/** + * @file ump_common.h + * + * This file contains some common enum values used both in both the user and kernel space side of UMP. + */ + +#ifndef _UMP_COMMON_H_ +#define _UMP_COMMON_H_ + +#ifdef __cplusplus +extern "C" +{ +#endif + +#ifdef __KERNEL__ +#include +#else +#include +#endif + +/** + * Values to identify major and minor version of UMP + */ +#define UMP_VERSION_MAJOR 2 +#define UMP_VERSION_MINOR 0 + +/** + * Typedef for a secure ID, a system wide identifier for UMP memory buffers. + */ +typedef uint32_t ump_secure_id; + +/** + * Value to indicate an invalid secure Id. + */ +#define UMP_INVALID_SECURE_ID ((ump_secure_id)-1) + +/** + * UMP error codes. + */ +typedef enum +{ + UMP_OK = 0, /**< indicates success */ + UMP_ERROR = 1 /**< indicates failure */ +} ump_result; + +/** + * Allocation flag bits. + * + * ump_allocate accepts zero or more flags to specify the type of memory to allocate and how to expose it to devices. + * + * For each supported device there are 4 flags to control access permissions and give usage characteristic hints to optimize the allocation/mapping. + * They are; + * @li @a UMP_PROT__RD read permission + * @li @a UMP_PROT__WR write permission + * @li @a UMP_HINT__RD read often + * @li @a UMP_HINT__WR written often + * + * 5 devices are currently supported, with a device being the CPU itself. + * The other 4 devices will be mapped to real devices per SoC design. + * They are just named W,X,Y,Z by UMP as it has no knowledge of their real names/identifiers. + * As an example device W could be a camera device while device Z could be an ARM GPU device, leaving X and Y unused. + * + * 2 additional flags control the allocation; + * @li @a UMP_CONSTRAINT_PHYSICALLY_LINEAR the allocation must be physical linear. Typical for devices without an MMU and no IOMMU to help it. + * @li @a UMP_PROT_SHAREABLE the allocation can be shared with other processes on the system. Without this flag the returned allocation won't be resolvable in other processes. + * + * All UMP allocation are growable unless they're @a UMP_PROT_SHAREABLE. + * The hint bits should be used to indicate the access pattern so the driver can select the most optimal memory type and cache settings based on the what the system supports. + */ +typedef enum +{ + /* Generic helpers */ + UMP_PROT_DEVICE_RD = (1u << 0), + UMP_PROT_DEVICE_WR = (1u << 1), + UMP_HINT_DEVICE_RD = (1u << 2), + UMP_HINT_DEVICE_WR = (1u << 3), + UMP_DEVICE_MASK = 0xF, + UMP_DEVICE_CPU_SHIFT = 0, + UMP_DEVICE_W_SHIFT = 4, + UMP_DEVICE_X_SHIFT = 8, + UMP_DEVICE_Y_SHIFT = 12, + UMP_DEVICE_Z_SHIFT = 16, + + /* CPU protection and hints. */ + UMP_PROT_CPU_RD = (1u << 0), + UMP_PROT_CPU_WR = (1u << 1), + UMP_HINT_CPU_RD = (1u << 2), + UMP_HINT_CPU_WR = (1u << 3), + + /* device W */ + UMP_PROT_W_RD = (1u << 4), + UMP_PROT_W_WR = (1u << 5), + UMP_HINT_W_RD = (1u << 6), + UMP_HINT_W_WR = (1u << 7), + + /* device X */ + UMP_PROT_X_RD = (1u << 8), + UMP_PROT_X_WR = (1u << 9), + UMP_HINT_X_RD = (1u << 10), + UMP_HINT_X_WR = (1u << 11), + + /* device Y */ + UMP_PROT_Y_RD = (1u << 12), + UMP_PROT_Y_WR = (1u << 13), + UMP_HINT_Y_RD = (1u << 14), + UMP_HINT_Y_WR = (1u << 15), + + /* device Z */ + UMP_PROT_Z_RD = (1u << 16), + UMP_PROT_Z_WR = (1u << 17), + UMP_HINT_Z_RD = (1u << 18), + UMP_HINT_Z_WR = (1u << 19), + + /* 20-26 reserved for future use */ + UMPP_ALLOCBITS_UNUSED = (0x7Fu << 20), + /** Allocations marked as @ UMP_CONSTRAINT_UNCACHED won't be mapped as cached by the cpu */ + UMP_CONSTRAINT_UNCACHED = (1u << 27), + /** Require 32-bit physically addressable memory */ + UMP_CONSTRAINT_32BIT_ADDRESSABLE = (1u << 28), + /** For devices without an MMU and with no IOMMU assistance. */ + UMP_CONSTRAINT_PHYSICALLY_LINEAR = (1u << 29), + /** Shareable must be set to allow the allocation to be used by other processes, the default is non-shared */ + UMP_PROT_SHAREABLE = (1u << 30) + /* (1u << 31) should not be used to ensure compiler portability */ +} ump_allocation_bits; + +/** + * ump_allocation_bits combination argument type. + * + * Type used to pass zero or more bits from the @ref ump_allocation_bits enum + */ +typedef uint32_t ump_alloc_flags; + + +/** + * Default allocation flags for UMP v1 compatible allocations. + */ +#define UMP_V1_API_DEFAULT_ALLOCATION_FLAGS UMP_PROT_CPU_RD | UMP_PROT_CPU_WR | \ + UMP_PROT_W_RD | UMP_PROT_W_WR | \ + UMP_PROT_X_RD | UMP_PROT_X_WR | \ + UMP_PROT_Y_RD | UMP_PROT_Y_WR | \ + UMP_PROT_Z_RD | UMP_PROT_Z_WR | \ + UMP_PROT_SHAREABLE | \ + UMP_CONSTRAINT_32BIT_ADDRESSABLE + +/** + * CPU cache sync operations. + * + * Cache synchronization operations to pass to @ref ump_cpu_msync_now + */ +enum +{ + /** + * Cleans any dirty cache lines to main memory, but the data will still be available in the cache. + * After a clean the contents of memory is considered to be "owned" by the device. + * */ + UMP_MSYNC_CLEAN = 1, + + /** Cleans any dirty cache lines to main memory and Ejects all lines from the cache. + * After an clean&invalidate the contents of memory is considered to be "owned" by the CPU. + * Any subsequent access will fetch data from main memory. + * + * @note Due to CPUs doing speculative prefetching a UMP_MSYNC_CLEAN_AND_INVALIDATE must be done before and after interacting with hardware. + * */ + UMP_MSYNC_CLEAN_AND_INVALIDATE + +}; + +typedef u32 ump_cpu_msync_op; + +/** + * Memory import types supported. + * If new import types are added they will appear here. + * They must be added before UMPP_EXTERNAL_MEM_COUNT and + * must be assigned an explicit sequantial number. + * + * @li UMP_EXTERNAL_MEM_TYPE_ION - Import an ION allocation + * Takes a int* (pointer to a file descriptor) + * Another ION reference is taken which is released on the final ump_release + */ +enum ump_external_memory_type +{ + UMPP_EXTERNAL_MEM_TYPE_UNUSED = 0, /* reserve type 0 */ + UMP_EXTERNAL_MEM_TYPE_ION = 1, + UMPP_EXTERNAL_MEM_COUNT +}; + +/** @name UMP v1 API + * + *@{ + */ + +/** + * Allocation constraints. + * + * Allocation flags to pass @ref ump_ref_drv_allocate + * + * UMP v1 API only. + */ +typedef enum +{ + /** the allocation is mapped as noncached. */ + UMP_REF_DRV_CONSTRAINT_NONE = 0, + /** not supported. */ + UMP_REF_DRV_CONSTRAINT_PHYSICALLY_LINEAR = 1, + /** the allocation is mapped as cached by the cpu. */ + UMP_REF_DRV_CONSTRAINT_USE_CACHE = 4 +} ump_alloc_constraints; + +/* @} */ + + +#ifdef __cplusplus +} +#endif + + +#endif /* _UMP_COMMON_H_ */ diff --git a/exynos5/hal/include/ump_platform.h b/exynos5/hal/include/ump_platform.h new file mode 100644 index 0000000..31f9343 --- /dev/null +++ b/exynos5/hal/include/ump_platform.h @@ -0,0 +1,57 @@ +/* + * This confidential and proprietary software may be used only as + * authorised by a licensing agreement from ARM Limited + * (C) COPYRIGHT 2008-2010 ARM Limited + * ALL RIGHTS RESERVED + * The entire notice above must be reproduced on all authorised + * copies and copies may only be made to the extent permitted + * by a licensing agreement from ARM Limited. + */ + +/** + * @file ump_platform.h + * + * This file should define UMP_API_EXPORT, + * which dictates how the UMP user space API should be exported/imported. + * Modify this file, if needed, to match your platform setup. + */ + + +#ifndef _UMP_PLATFORM_H_ +#define _UMP_PLATFORM_H_ + +#include "malisw/mali_stdtypes.h" + +/** @addtogroup ump_user_space_api + * @{ */ + +/** + * A define which controls how UMP user space API functions are imported and exported. + * + * Functions exported by the driver is tagged with UMP_API_EXPORT to allow + * the compiler/build system/OS loader to detect and handle functions which is to be exported/imported from a shared library. @n + * This define should be set by the implementor of the UMP API to match their needs if needed. + * + * Typical usage example in the driver: + * + * UMP_API_EXPORT void my_api_call(void); + */ + +#if defined(_WIN32) + +#define UMP_API_EXPORT + +#elif defined(__SYMBIAN32__) + +#define UMP_API_EXPORT IMPORT_C + +#else + +#define UMP_API_EXPORT + +#endif + +/** @} */ /* end group ump_user_space_api */ + + +#endif /* _UMP_PLATFORM_H_ */ diff --git a/exynos5/hal/include/ump_ref_drv.h b/exynos5/hal/include/ump_ref_drv.h new file mode 100644 index 0000000..6320f1d --- /dev/null +++ b/exynos5/hal/include/ump_ref_drv.h @@ -0,0 +1,59 @@ +/* + * This confidential and proprietary software may be used only as + * authorised by a licensing agreement from ARM Limited + * (C) COPYRIGHT 2009-2010 ARM Limited + * ALL RIGHTS RESERVED + * The entire notice above must be reproduced on all authorised + * copies and copies may only be made to the extent permitted + * by a licensing agreement from ARM Limited. + */ + +/** + * @file ump_ref_drv.h + * + * Reference driver extensions to the UMP user space API for allocating UMP memory + */ + +#ifndef _UNIFIED_MEMORY_PROVIDER_REF_DRV_H_ +#define _UNIFIED_MEMORY_PROVIDER_REF_DRV_H_ + +#include "ump.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + /* This enum must match with the IOCTL enum in ump_ioctl.h */ + UMP_REF_DRV_CONSTRAINT_NONE = 0, + UMP_REF_DRV_CONSTRAINT_PHYSICALLY_LINEAR = 1, + /* This enum is included by samsung */ + UMP_REF_DRV_CONSTRAINT_USE_CACHE = 128, +} ump_alloc_constraints; + +/** Allocate an UMP handle containing a memory buffer. + * Input: Size: The minimum size for the allocation. + * Usage: If this is UMP_REF_DRV_CONSTRAINT_USE_CACHE, the allocation is mapped as cached by the cpu. + * If it is UMP_REF_DRV_CONSTRAINT_NONE it is mapped as noncached. + * The flag UMP_REF_DRV_CONSTRAINT_PHYSICALLY_LINEAR is not supported.*/ +UMP_API_EXPORT ump_handle ump_ref_drv_allocate(unsigned long size, ump_alloc_constraints usage); + +UMP_API_EXPORT ump_handle ump_ref_drv_ion_import(int ion_fd, ump_alloc_constraints constraints); +typedef enum { + UMP_MSYNC_CLEAN = 0 , + UMP_MSYNC_CLEAN_AND_INVALIDATE = 1, + UMP_MSYNC_READOUT_CACHE_ENABLED = 128, +} ump_cpu_msync_op; + +/** Flushing cache for an ump_handle. + * The function will always CLEAN_AND_INVALIDATE as long as the \a op is not UMP_MSYNC_READOUT_CACHE_ENABLED. + * If so it will only report back if the given ump_handle is cacheable. + * At the momement the implementation does not use \a address or \a size. + * Return value is 1 if cache is enabled, and 0 if it is disabled for the given allocation.*/ +UMP_API_EXPORT int ump_cpu_msync_now(ump_handle mem, ump_cpu_msync_op op, void* address, int size); + +#ifdef __cplusplus +} +#endif + +#endif /*_UNIFIED_MEMORY_PROVIDER_REF_DRV_H_ */ diff --git a/exynos5/hal/include/v4l2-mediabus.h b/exynos5/hal/include/v4l2-mediabus.h new file mode 100644 index 0000000..1a13cf3 --- /dev/null +++ b/exynos5/hal/include/v4l2-mediabus.h @@ -0,0 +1,116 @@ +/* + * Media Bus API header + * + * Copyright (C) 2009, Guennadi Liakhovetski + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef __LINUX_V4L2_MEDIABUS_H +#define __LINUX_V4L2_MEDIABUS_H + +#include +#include + +/* + * These pixel codes uniquely identify data formats on the media bus. Mostly + * they correspond to similarly named V4L2_PIX_FMT_* formats, format 0 is + * reserved, V4L2_MBUS_FMT_FIXED shall be used by host-client pairs, where the + * data format is fixed. Additionally, "2X8" means that one pixel is transferred + * in two 8-bit samples, "BE" or "LE" specify in which order those samples are + * transferred over the bus: "LE" means that the least significant bits are + * transferred first, "BE" means that the most significant bits are transferred + * first, and "PADHI" and "PADLO" define which bits - low or high, in the + * incomplete high byte, are filled with padding bits. + * + * The pixel codes are grouped by type, bus_width, bits per component, samples + * per pixel and order of subsamples. Numerical values are sorted using generic + * numerical sort order (8 thus comes before 10). + * + * As their value can't change when a new pixel code is inserted in the + * enumeration, the pixel codes are explicitly given a numerical value. The next + * free values for each category are listed below, update them when inserting + * new pixel codes. + */ +enum v4l2_mbus_pixelcode { + V4L2_MBUS_FMT_FIXED = 0x0001, + + /* RGB - next is 0x1009 */ + V4L2_MBUS_FMT_RGB444_2X8_PADHI_BE = 0x1001, + V4L2_MBUS_FMT_RGB444_2X8_PADHI_LE = 0x1002, + V4L2_MBUS_FMT_RGB555_2X8_PADHI_BE = 0x1003, + V4L2_MBUS_FMT_RGB555_2X8_PADHI_LE = 0x1004, + V4L2_MBUS_FMT_BGR565_2X8_BE = 0x1005, + V4L2_MBUS_FMT_BGR565_2X8_LE = 0x1006, + V4L2_MBUS_FMT_RGB565_2X8_BE = 0x1007, + V4L2_MBUS_FMT_RGB565_2X8_LE = 0x1008, + V4L2_MBUS_FMT_XRGB8888_4X8_LE = 0x1009, + + /* YUV (including grey) - next is 0x2014 */ + V4L2_MBUS_FMT_Y8_1X8 = 0x2001, + V4L2_MBUS_FMT_UYVY8_1_5X8 = 0x2002, + V4L2_MBUS_FMT_VYUY8_1_5X8 = 0x2003, + V4L2_MBUS_FMT_YUYV8_1_5X8 = 0x2004, + V4L2_MBUS_FMT_YVYU8_1_5X8 = 0x2005, + V4L2_MBUS_FMT_UYVY8_2X8 = 0x2006, + V4L2_MBUS_FMT_VYUY8_2X8 = 0x2007, + V4L2_MBUS_FMT_YUYV8_2X8 = 0x2008, + V4L2_MBUS_FMT_YVYU8_2X8 = 0x2009, + V4L2_MBUS_FMT_Y10_1X10 = 0x200a, + V4L2_MBUS_FMT_YUYV10_2X10 = 0x200b, + V4L2_MBUS_FMT_YVYU10_2X10 = 0x200c, + V4L2_MBUS_FMT_Y12_1X12 = 0x2013, + V4L2_MBUS_FMT_UYVY8_1X16 = 0x200f, + V4L2_MBUS_FMT_VYUY8_1X16 = 0x2010, + V4L2_MBUS_FMT_YUYV8_1X16 = 0x2011, + V4L2_MBUS_FMT_YVYU8_1X16 = 0x2012, + V4L2_MBUS_FMT_YUV8_1X24 = 0x2014, + V4L2_MBUS_FMT_YUYV10_1X20 = 0x200d, + V4L2_MBUS_FMT_YVYU10_1X20 = 0x200e, + + /* Bayer - next is 0x3015 */ + V4L2_MBUS_FMT_SBGGR8_1X8 = 0x3001, + V4L2_MBUS_FMT_SGBRG8_1X8 = 0x3013, + V4L2_MBUS_FMT_SGRBG8_1X8 = 0x3002, + V4L2_MBUS_FMT_SRGGB8_1X8 = 0x3014, + V4L2_MBUS_FMT_SBGGR10_DPCM8_1X8 = 0x300b, + V4L2_MBUS_FMT_SGBRG10_DPCM8_1X8 = 0x300c, + V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8 = 0x3009, + V4L2_MBUS_FMT_SRGGB10_DPCM8_1X8 = 0x300d, + V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_BE = 0x3003, + V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_LE = 0x3004, + V4L2_MBUS_FMT_SBGGR10_2X8_PADLO_BE = 0x3005, + V4L2_MBUS_FMT_SBGGR10_2X8_PADLO_LE = 0x3006, + V4L2_MBUS_FMT_SBGGR10_1X10 = 0x3007, + V4L2_MBUS_FMT_SGBRG10_1X10 = 0x300e, + V4L2_MBUS_FMT_SGRBG10_1X10 = 0x300a, + V4L2_MBUS_FMT_SRGGB10_1X10 = 0x300f, + V4L2_MBUS_FMT_SBGGR12_1X12 = 0x3008, + V4L2_MBUS_FMT_SGBRG12_1X12 = 0x3010, + V4L2_MBUS_FMT_SGRBG12_1X12 = 0x3011, + V4L2_MBUS_FMT_SRGGB12_1X12 = 0x3012, + + /* JPEG compressed formats - next is 0x4002 */ + V4L2_MBUS_FMT_JPEG_1X8 = 0x4001, +}; + +/** + * struct v4l2_mbus_framefmt - frame format on the media bus + * @width: frame width + * @height: frame height + * @code: data format code (from enum v4l2_mbus_pixelcode) + * @field: used interlacing type (from enum v4l2_field) + * @colorspace: colorspace of the data (from enum v4l2_colorspace) + */ +struct v4l2_mbus_framefmt { + __u32 width; + __u32 height; + __u32 code; + __u32 field; + __u32 colorspace; + __u32 reserved[7]; +}; + +#endif diff --git a/exynos5/hal/include/v4l2-subdev.h b/exynos5/hal/include/v4l2-subdev.h new file mode 100644 index 0000000..f5dd9a1 --- /dev/null +++ b/exynos5/hal/include/v4l2-subdev.h @@ -0,0 +1,141 @@ +/* + * V4L2 subdev userspace API + * + * Copyright (C) 2010 Nokia Corporation + * + * Contacts: Laurent Pinchart + * Sakari Ailus + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __LINUX_V4L2_SUBDEV_H +#define __LINUX_V4L2_SUBDEV_H + +#include +#include +#include "v4l2-mediabus.h" + +/** + * enum v4l2_subdev_format_whence - Media bus format type + * @V4L2_SUBDEV_FORMAT_TRY: try format, for negotiation only + * @V4L2_SUBDEV_FORMAT_ACTIVE: active format, applied to the device + */ +enum v4l2_subdev_format_whence { + V4L2_SUBDEV_FORMAT_TRY = 0, + V4L2_SUBDEV_FORMAT_ACTIVE = 1, +}; + +/** + * struct v4l2_subdev_format - Pad-level media bus format + * @which: format type (from enum v4l2_subdev_format_whence) + * @pad: pad number, as reported by the media API + * @format: media bus format (format code and frame size) + */ +struct v4l2_subdev_format { + __u32 which; + __u32 pad; + struct v4l2_mbus_framefmt format; + __u32 reserved[8]; +}; + +/** + * struct v4l2_subdev_crop - Pad-level crop settings + * @which: format type (from enum v4l2_subdev_format_whence) + * @pad: pad number, as reported by the media API + * @rect: pad crop rectangle boundaries + */ +struct v4l2_subdev_crop { + __u32 which; + __u32 pad; + struct v4l2_rect rect; + __u32 reserved[8]; +}; + +/** + * struct v4l2_subdev_mbus_code_enum - Media bus format enumeration + * @pad: pad number, as reported by the media API + * @index: format index during enumeration + * @code: format code (from enum v4l2_mbus_pixelcode) + */ +struct v4l2_subdev_mbus_code_enum { + __u32 pad; + __u32 index; + __u32 code; + __u32 reserved[9]; +}; + +/** + * struct v4l2_subdev_frame_size_enum - Media bus format enumeration + * @pad: pad number, as reported by the media API + * @index: format index during enumeration + * @code: format code (from enum v4l2_mbus_pixelcode) + */ +struct v4l2_subdev_frame_size_enum { + __u32 index; + __u32 pad; + __u32 code; + __u32 min_width; + __u32 max_width; + __u32 min_height; + __u32 max_height; + __u32 reserved[9]; +}; + +/** + * struct v4l2_subdev_frame_interval - Pad-level frame rate + * @pad: pad number, as reported by the media API + * @interval: frame interval in seconds + */ +struct v4l2_subdev_frame_interval { + __u32 pad; + struct v4l2_fract interval; + __u32 reserved[9]; +}; + +/** + * struct v4l2_subdev_frame_interval_enum - Frame interval enumeration + * @pad: pad number, as reported by the media API + * @index: frame interval index during enumeration + * @code: format code (from enum v4l2_mbus_pixelcode) + * @width: frame width in pixels + * @height: frame height in pixels + * @interval: frame interval in seconds + */ +struct v4l2_subdev_frame_interval_enum { + __u32 index; + __u32 pad; + __u32 code; + __u32 width; + __u32 height; + struct v4l2_fract interval; + __u32 reserved[9]; +}; + +#define VIDIOC_SUBDEV_G_FMT _IOWR('V', 4, struct v4l2_subdev_format) +#define VIDIOC_SUBDEV_S_FMT _IOWR('V', 5, struct v4l2_subdev_format) +#define VIDIOC_SUBDEV_G_FRAME_INTERVAL \ + _IOWR('V', 21, struct v4l2_subdev_frame_interval) +#define VIDIOC_SUBDEV_S_FRAME_INTERVAL \ + _IOWR('V', 22, struct v4l2_subdev_frame_interval) +#define VIDIOC_SUBDEV_ENUM_MBUS_CODE \ + _IOWR('V', 2, struct v4l2_subdev_mbus_code_enum) +#define VIDIOC_SUBDEV_ENUM_FRAME_SIZE \ + _IOWR('V', 74, struct v4l2_subdev_frame_size_enum) +#define VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL \ + _IOWR('V', 75, struct v4l2_subdev_frame_interval_enum) +#define VIDIOC_SUBDEV_G_CROP _IOWR('V', 59, struct v4l2_subdev_crop) +#define VIDIOC_SUBDEV_S_CROP _IOWR('V', 60, struct v4l2_subdev_crop) + +#endif diff --git a/exynos5/hal/include/video.h b/exynos5/hal/include/video.h new file mode 100644 index 0000000..0565b85 --- /dev/null +++ b/exynos5/hal/include/video.h @@ -0,0 +1,363 @@ +#ifndef _VIDEO_H_ +#define _VIDEO_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef __HDMI_VIDEO_VIDEOFORMAT__ +#define __HDMI_VIDEO_VIDEOFORMAT__ +/** + * @enum VideoFormat + * Video format + */ +enum VideoFormat { + /** 640x480p\@60Hz */ + v640x480p_60Hz = 0, + /** 720x480p\@60Hz */ + v720x480p_60Hz, + /** 1280x700p\@60Hz */ + v1280x720p_60Hz, + /** 1920x1080i\@60Hz */ + v1920x1080i_60Hz, + /** 720x480i\@60Hz */ + v720x480i_60Hz, + /** 720x240p\@60Hz */ + v720x240p_60Hz, + /** 2880x480i\@60Hz */ + v2880x480i_60Hz, + /** 2880x240p\@60Hz */ + v2880x240p_60Hz, + /** 1440x480p\@60Hz */ + v1440x480p_60Hz, + /** 1920x1080p\@60Hz */ + v1920x1080p_60Hz, + /** 720x576p\@60Hz */ + v720x576p_50Hz, + /** 1280x720p\@50Hz */ + v1280x720p_50Hz, + /** 1920x1080i\@50Hz (V total = 1125) */ + v1920x1080i_50Hz, + /** 720x576i\@50Hz */ + v720x576i_50Hz, + /** 720x288p\@50Hz */ + v720x288p_50Hz, + /** 2880x576i\@50Hz */ + v2880x576i_50Hz, + /** 2880x288p\@50Hz */ + v2880x288p_50Hz, + /** 1440x576p\@50Hz */ + v1440x576p_50Hz, + /** 1920x1080p\@50Hz */ + v1920x1080p_50Hz, + /** 1920x1080p\@24Hz */ + v1920x1080p_24Hz, + /** 1920x1080p\@25Hz */ + v1920x1080p_25Hz, + /** 1920x1080p\@30Hz */ + v1920x1080p_30Hz, + /** 2880x480p\@60Hz */ + v2880x480p_60Hz, + /** 2880x576p\@60Hz */ + v2880x576p_50Hz, + /** 1920x1080i\@50Hz (V total = 1250) */ + v1920x1080i_50Hz_1250, + /** 1920x1080i\@100Hz */ + v1920x1080i_100Hz, + /** 1280x720p\@100Hz */ + v1280x720p_100Hz, + /** 720x576p\@100Hz */ + v720x576p_100Hz, + /** 720x576i\@100Hz */ + v720x576i_100Hz, + /** 1920x1080i\@120Hz */ + v1920x1080i_120Hz, + /** 1280x720p\@120Hz */ + v1280x720p_120Hz, + /** 720x480p\@120Hz */ + v720x480p_120Hz, + /** 720x480i\@120Hz */ + v720x480i_120Hz, + /** 720x576p\@200Hz */ + v720x576p_200Hz, + /** 720x576i\@200Hz */ + v720x576i_200Hz, + /** 720x480p\@240Hz */ + v720x480p_240Hz, + /** 720x480i\@240Hz */ + v720x480i_240Hz, + /** 1280x720p\@24Hz */ + v1280x720p_24Hz, + /** 1280x720p\@25Hz */ + v1280x720p_25Hz, + /** 1280x720p\@30Hz */ + v1280x720p_30Hz, + /** 1920x1080p\@120Hz */ + v1920x1080p_120Hz, + /** 1920x1080p\@100Hz */ + v1920x1080p_100Hz, + /** 4Kx2K\@30Hz */ + v4Kx2K_30Hz, +}; +#endif /* __HDMI_VIDEO_VIDEOFORMAT__ */ +#ifndef __HDMI_VIDEO_COLORSPACE__ +#define __HDMI_VIDEO_COLORSPACE__ +/** + * @enum ColorSpace + * Color space of video stream. + */ +enum ColorSpace { + /** RGB color space */ + HDMI_CS_RGB, + /** YCbCr 4:4:4 color space */ + HDMI_CS_YCBCR444, + /** YCbCr 4:2:2 color space */ + HDMI_CS_YCBCR422 +}; +#endif /* __HDMI_VIDEO_COLORSPACE__ */ + +#ifndef __HDMI_VIDEO_COLORDEPTH__ +#define __HDMI_VIDEO_COLORDEPTH__ +/** + * @enum ColorDepth + * Color depth per pixel of video stream + */ +enum ColorDepth { + /** 36 bit color depth per pixel */ + HDMI_CD_36, + /** 30 bit color depth per pixel */ + HDMI_CD_30, + /** 24 bit color depth per pixel */ + HDMI_CD_24 +}; +#endif /* __HDMI_VIDEO_COLORDEPTH__ */ + +#ifndef __HDMI_VIDEO_HDMIMODE__ +#define __HDMI_VIDEO_HDMIMODE__ +/** + * @enum HDMIMode + * System mode + */ +enum HDMIMode { + /** DVI mode */ + DVI = 0, + /** HDMI mode */ + HDMI +}; +#endif /* __HDMI_VIDEO_HDMIMODE__ */ + +#ifndef __HDMI_VIDEO_PIXELLIMIT__ +#define __HDMI_VIDEO_PIXELLIMIT__ +/** + * @enum PixelLimit + * Pixel limitation of video stream + */ +enum PixelLimit { + /** Full range */ + HDMI_FULL_RANGE, + /** Limit range for RGB color space */ + HDMI_RGB_LIMIT_RANGE, + /** Limit range for YCbCr color space */ + HDMI_YCBCR_LIMIT_RANGE +}; +#endif /* __HDMI_VIDEO_PIXELLIMIT__ */ + +#ifndef __HDMI_VIDEO_COLORIMETRY__ +#define __HDMI_VIDEO_COLORIMETRY__ +/** + * @enum HDMIColorimetry + * Colorimetry of video stream + */ +enum HDMIColorimetry { + /** Colorimetry is not defined */ + HDMI_COLORIMETRY_NO_DATA, + /** ITU601 colorimetry */ + HDMI_COLORIMETRY_ITU601, + /** ITU709 colorimetry */ + HDMI_COLORIMETRY_ITU709, + /** Extended ITU601 colorimetry */ + HDMI_COLORIMETRY_EXTENDED_xvYCC601, + /** Extended ITU709 colorimetry */ + HDMI_COLORIMETRY_EXTENDED_xvYCC709 +}; +#endif /* __HDMI_VIDEO_COLORIMETRY__ */ + +#ifndef __HDMI_VIDEO_PIXELASPECTRATIO__ +#define __HDMI_VIDEO_PIXELASPECTRATIO__ +/** + * @enum PixelAspectRatio + * Pixel aspect ratio of video stream + */ +enum PixelAspectRatio { + /** as picutre pixel ratio */ + HDMI_PIXEL_RATIO_AS_PICTURE, + /** 4:3 pixel ratio */ + HDMI_PIXEL_RATIO_4_3, + /** 16:9 pixel ratio */ + HDMI_PIXEL_RATIO_16_9 +}; +#endif /* __HDMI_VIDEO_PIXELASPECTRATIO__ */ + +#ifndef __HDMI_VIDEO_PIXELFREQUENCY__ +#define __HDMI_VIDEO_PIXELFREQUENCY__ +/** + * @enum PixelFreq + * Pixel Frequency + */ +enum PixelFreq { + /** 25.2 MHz pixel frequency */ + PIXEL_FREQ_25_200 = 2520, + /** 25.175 MHz pixel frequency */ + PIXEL_FREQ_25_175 = 2517, + /** 27 MHz pixel frequency */ + PIXEL_FREQ_27 = 2700, + /** 27.027 MHz pixel frequency */ + PIXEL_FREQ_27_027 = 2702, + /** 54 MHz pixel frequency */ + PIXEL_FREQ_54 = 5400, + /** 54.054 MHz pixel frequency */ + PIXEL_FREQ_54_054 = 5405, + /** 74.25 MHz pixel frequency */ + PIXEL_FREQ_74_250 = 7425, + /** 74.176 MHz pixel frequency */ + PIXEL_FREQ_74_176 = 7417, + /** 148.5 MHz pixel frequency */ + PIXEL_FREQ_148_500 = 14850, + /** 148.352 MHz pixel frequency */ + PIXEL_FREQ_148_352 = 14835, + /** 108.108 MHz pixel frequency */ + PIXEL_FREQ_108_108 = 10810, + /** 72 MHz pixel frequency */ + PIXEL_FREQ_72 = 7200, + /** 25 MHz pixel frequency */ + PIXEL_FREQ_25 = 2500, + /** 65 MHz pixel frequency */ + PIXEL_FREQ_65 = 6500, + /** 108 MHz pixel frequency */ + PIXEL_FREQ_108 = 10800, + /** 162 MHz pixel frequency */ + PIXEL_FREQ_162 = 16200, + /** 59.4 MHz pixel frequency */ + PIXEL_FREQ_59_400 = 5940, +}; +#endif /* __HDMI_VIDEO_PIXELFREQUENCY__ */ + +#ifndef __HDMI_PHY_PIXELFREQUENCY__ +#define __HDMI_PHY_PIXELFREQUENCY__ + +/** + * @enum PHYFreq + * PHY Frequency + */ +enum PHYFreq { + /** Not supported */ + PHY_FREQ_NOT_SUPPORTED = -1, + /** 25.2 MHz pixel frequency */ + PHY_FREQ_25_200 = 0, + /** 25.175 MHz pixel frequency */ + PHY_FREQ_25_175, + /** 27 MHz pixel frequency */ + PHY_FREQ_27, + /** 27.027 MHz pixel frequency */ + PHY_FREQ_27_027, + /** 54 MHz pixel frequency */ + PHY_FREQ_54, + /** 54.054 MHz pixel frequency */ + PHY_FREQ_54_054, + /** 74.25 MHz pixel frequency */ + PHY_FREQ_74_250, + /** 74.176 MHz pixel frequency */ + PHY_FREQ_74_176, + /** 148.5 MHz pixel frequency */ + PHY_FREQ_148_500, + /** 148.352 MHz pixel frequency */ + PHY_FREQ_148_352, + /** 108.108 MHz pixel frequency */ + PHY_FREQ_108_108, + /** 72 MHz pixel frequency */ + PHY_FREQ_72, + /** 25 MHz pixel frequency */ + PHY_FREQ_25, + /** 65 MHz pixel frequency */ + PHY_FREQ_65, + /** 108 MHz pixel frequency */ + PHY_FREQ_108, + /** 162 MHz pixel frequency */ + PHY_FREQ_162, + /** 59.4 MHz pixel frequency */ + PHY_FREQ_59_400, +}; + +#endif /* __HDMI_PHY_PIXELFREQUENCY__ */ + +#ifndef __HDMI_VIDEO_SOURCE__ +#define __HDMI_VIDEO_SOURCE__ +/** + * @enum HDMIVideoSource + * Type of video source. + */ +enum HDMIVideoSource { + /** Internal Video Source */ + HDMI_SOURCE_INTERNAL, + /** External Video Source */ + HDMI_SOURCE_EXTERNAL, +}; +#endif /* __HDMI_VIDEO_SOURCE__ */ + +#ifndef __HDMI_3D_VIDEO_STRUCTURE__ +#define __HDMI_3D_VIDEO_STRUCTURE__ +/** + * @enum HDMI3DVideoStructure + * Type of 3D Video Structure + */ +enum HDMI3DVideoStructure { + /** 2D Video Format */ + HDMI_2D_VIDEO_FORMAT = -1, + /** 3D Frame Packing Structure */ + HDMI_3D_FP_FORMAT = 0, + /** 3D Field Alternative Structure */ + HDMI_3D_FA_FORMAT, + /** 3D Line Alternative Structure */ + HDMI_3D_LA_FORMAT, + /** Side-by-Side(Full)Structure */ + HDMI_3D_SSF_FORMAT, + /** 3D L+Depth Structure */ + HDMI_3D_LD_FORMAT, + /** 3D L+Depth+Graphics Structure */ + HDMI_3D_LDGFX_FORMAT, + /** 3D Top-and-Bottom Structure */ + HDMI_3D_TB_FORMAT, + /** HDMI VIC Structure (ex. 4Kx2K) */ + HDMI_VIC_FORMAT, + /** Side-by-Side(Half)Structure */ + HDMI_3D_SSH_FORMAT, +}; +#endif /* __HDMI_3D_VIDEO_STRUCTURE__ */ + +#ifndef __HDMI_VIDEO_PARAMETER__ +#define __HDMI_VIDEO_PARAMETER__ +//! Structure for HDMI video +struct HDMIVideoParameter { + /** Video interface */ + enum HDMIMode mode; + /** Video format */ + enum VideoFormat resolution; + /** Color space */ + enum ColorSpace colorSpace; + /** Color depth */ + enum ColorDepth colorDepth; + /** Colorimetry */ + enum HDMIColorimetry colorimetry; + /** Pixel aspect ratio */ + enum PixelAspectRatio pixelAspectRatio; + /** Video Source */ + enum HDMIVideoSource videoSrc; + /** 3D Video Structure */ + enum HDMI3DVideoStructure hdmi_3d_format; +}; +#endif /* __HDMI_VIDEO_PARAMETER__*/ + +#ifdef __cplusplus +} +#endif +#endif /* _VIDEO_H_ */ diff --git a/exynos5/hal/include/videodev2.h b/exynos5/hal/include/videodev2.h new file mode 100644 index 0000000..48b3081 --- /dev/null +++ b/exynos5/hal/include/videodev2.h @@ -0,0 +1,2227 @@ +/* + * Video for Linux Two header file + * + * Copyright (C) 1999-2007 the contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Alternatively you can redistribute this file under the terms of the + * BSD license as stated below: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. The names of its contributors may not 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. + * + * Header file for v4l or V4L2 drivers and applications + * with public API. + * All kernel-specific stuff were moved to media/v4l2-dev.h, so + * no #if __KERNEL tests are allowed here + * + * See http://linuxtv.org for more info + * + * Author: Bill Dirks + * Justin Schoeman + * Hans Verkuil + * et al. + */ +#ifndef __LINUX_VIDEODEV2_H +#define __LINUX_VIDEODEV2_H + +#ifdef __KERNEL__ +#include /* need struct timeval */ +#else +#include +#endif +#include +#include +#include + +/* + * Common stuff for both V4L1 and V4L2 + * Moved from videodev.h + */ +#define VIDEO_MAX_FRAME 32 +#define VIDEO_MAX_PLANES 8 + +#ifndef __KERNEL__ + +/* These defines are V4L1 specific and should not be used with the V4L2 API! + They will be removed from this header in the future. */ + +#define VID_TYPE_CAPTURE 1 /* Can capture */ +#define VID_TYPE_TUNER 2 /* Can tune */ +#define VID_TYPE_TELETEXT 4 /* Does teletext */ +#define VID_TYPE_OVERLAY 8 /* Overlay onto frame buffer */ +#define VID_TYPE_CHROMAKEY 16 /* Overlay by chromakey */ +#define VID_TYPE_CLIPPING 32 /* Can clip */ +#define VID_TYPE_FRAMERAM 64 /* Uses the frame buffer memory */ +#define VID_TYPE_SCALES 128 /* Scalable */ +#define VID_TYPE_MONOCHROME 256 /* Monochrome only */ +#define VID_TYPE_SUBCAPTURE 512 /* Can capture subareas of the image */ +#define VID_TYPE_MPEG_DECODER 1024 /* Can decode MPEG streams */ +#define VID_TYPE_MPEG_ENCODER 2048 /* Can encode MPEG streams */ +#define VID_TYPE_MJPEG_DECODER 4096 /* Can decode MJPEG streams */ +#define VID_TYPE_MJPEG_ENCODER 8192 /* Can encode MJPEG streams */ +#endif + +/* + * M I S C E L L A N E O U S + */ + +/* Four-character-code (FOURCC) */ +#define v4l2_fourcc(a, b, c, d)\ + ((__u32)(a) | ((__u32)(b) << 8) | ((__u32)(c) << 16) | ((__u32)(d) << 24)) + +/* + * E N U M S + */ +enum v4l2_field { + V4L2_FIELD_ANY = 0, /* driver can choose from none, + top, bottom, interlaced + depending on whatever it thinks + is approximate ... */ + V4L2_FIELD_NONE = 1, /* this device has no fields ... */ + V4L2_FIELD_TOP = 2, /* top field only */ + V4L2_FIELD_BOTTOM = 3, /* bottom field only */ + V4L2_FIELD_INTERLACED = 4, /* both fields interlaced */ + V4L2_FIELD_SEQ_TB = 5, /* both fields sequential into one + buffer, top-bottom order */ + V4L2_FIELD_SEQ_BT = 6, /* same as above + bottom-top order */ + V4L2_FIELD_ALTERNATE = 7, /* both fields alternating into + separate buffers */ + V4L2_FIELD_INTERLACED_TB = 8, /* both fields interlaced, top field + first and the top field is + transmitted first */ + V4L2_FIELD_INTERLACED_BT = 9, /* both fields interlaced, top field + first and the bottom field is + transmitted first */ +}; +#define V4L2_FIELD_HAS_TOP(field) \ + ((field) == V4L2_FIELD_TOP ||\ + (field) == V4L2_FIELD_INTERLACED ||\ + (field) == V4L2_FIELD_INTERLACED_TB ||\ + (field) == V4L2_FIELD_INTERLACED_BT ||\ + (field) == V4L2_FIELD_SEQ_TB ||\ + (field) == V4L2_FIELD_SEQ_BT) +#define V4L2_FIELD_HAS_BOTTOM(field) \ + ((field) == V4L2_FIELD_BOTTOM ||\ + (field) == V4L2_FIELD_INTERLACED ||\ + (field) == V4L2_FIELD_INTERLACED_TB ||\ + (field) == V4L2_FIELD_INTERLACED_BT ||\ + (field) == V4L2_FIELD_SEQ_TB ||\ + (field) == V4L2_FIELD_SEQ_BT) +#define V4L2_FIELD_HAS_BOTH(field) \ + ((field) == V4L2_FIELD_INTERLACED ||\ + (field) == V4L2_FIELD_INTERLACED_TB ||\ + (field) == V4L2_FIELD_INTERLACED_BT ||\ + (field) == V4L2_FIELD_SEQ_TB ||\ + (field) == V4L2_FIELD_SEQ_BT) + +enum v4l2_buf_type { + V4L2_BUF_TYPE_VIDEO_CAPTURE = 1, + V4L2_BUF_TYPE_VIDEO_OUTPUT = 2, + V4L2_BUF_TYPE_VIDEO_OVERLAY = 3, + V4L2_BUF_TYPE_VBI_CAPTURE = 4, + V4L2_BUF_TYPE_VBI_OUTPUT = 5, + V4L2_BUF_TYPE_SLICED_VBI_CAPTURE = 6, + V4L2_BUF_TYPE_SLICED_VBI_OUTPUT = 7, +#if 1 + /* Experimental */ + V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY = 8, +#endif + V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE = 9, + V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE = 10, + V4L2_BUF_TYPE_PRIVATE = 0x80, +}; + +#define V4L2_TYPE_IS_MULTIPLANAR(type) \ + ((type) == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE \ + || (type) == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) + +#define V4L2_TYPE_IS_OUTPUT(type) \ + ((type) == V4L2_BUF_TYPE_VIDEO_OUTPUT \ + || (type) == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE \ + || (type) == V4L2_BUF_TYPE_VIDEO_OVERLAY \ + || (type) == V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY \ + || (type) == V4L2_BUF_TYPE_VBI_OUTPUT \ + || (type) == V4L2_BUF_TYPE_SLICED_VBI_OUTPUT) + +enum v4l2_tuner_type { + V4L2_TUNER_RADIO = 1, + V4L2_TUNER_ANALOG_TV = 2, + V4L2_TUNER_DIGITAL_TV = 3, +}; + +enum v4l2_memory { + V4L2_MEMORY_MMAP = 1, + V4L2_MEMORY_USERPTR = 2, + V4L2_MEMORY_OVERLAY = 3, +}; + +/* see also http://vektor.theorem.ca/graphics/ycbcr/ */ +enum v4l2_colorspace { + /* ITU-R 601 -- broadcast NTSC/PAL */ + V4L2_COLORSPACE_SMPTE170M = 1, + + /* 1125-Line (US) HDTV */ + V4L2_COLORSPACE_SMPTE240M = 2, + + /* HD and modern captures. */ + V4L2_COLORSPACE_REC709 = 3, + + /* broken BT878 extents (601, luma range 16-253 instead of 16-235) */ + V4L2_COLORSPACE_BT878 = 4, + + /* These should be useful. Assume 601 extents. */ + V4L2_COLORSPACE_470_SYSTEM_M = 5, + V4L2_COLORSPACE_470_SYSTEM_BG = 6, + + /* I know there will be cameras that send this. So, this is + * unspecified chromaticities and full 0-255 on each of the + * Y'CbCr components + */ + V4L2_COLORSPACE_JPEG = 7, + + /* For RGB colourspaces, this is probably a good start. */ + V4L2_COLORSPACE_SRGB = 8, +}; + +enum v4l2_priority { + V4L2_PRIORITY_UNSET = 0, /* not initialized */ + V4L2_PRIORITY_BACKGROUND = 1, + V4L2_PRIORITY_INTERACTIVE = 2, + V4L2_PRIORITY_RECORD = 3, + V4L2_PRIORITY_DEFAULT = V4L2_PRIORITY_INTERACTIVE, +}; + +struct v4l2_rect { + __s32 left; + __s32 top; + __s32 width; + __s32 height; +}; + +struct v4l2_fract { + __u32 numerator; + __u32 denominator; +}; + +/* + * D R I V E R C A P A B I L I T I E S + */ +struct v4l2_capability { + __u8 driver[16]; /* i.e. "bttv" */ + __u8 card[32]; /* i.e. "Hauppauge WinTV" */ + __u8 bus_info[32]; /* "PCI:" + pci_name(pci_dev) */ + __u32 version; /* should use KERNEL_VERSION() */ + __u32 capabilities; /* Device capabilities */ + __u32 reserved[4]; +}; + +/* Values for 'capabilities' field */ +#define V4L2_CAP_VIDEO_CAPTURE 0x00000001 /* Is a video capture device */ +#define V4L2_CAP_VIDEO_OUTPUT 0x00000002 /* Is a video output device */ +#define V4L2_CAP_VIDEO_OVERLAY 0x00000004 /* Can do video overlay */ +#define V4L2_CAP_VBI_CAPTURE 0x00000010 /* Is a raw VBI capture device */ +#define V4L2_CAP_VBI_OUTPUT 0x00000020 /* Is a raw VBI output device */ +#define V4L2_CAP_SLICED_VBI_CAPTURE 0x00000040 /* Is a sliced VBI capture device */ +#define V4L2_CAP_SLICED_VBI_OUTPUT 0x00000080 /* Is a sliced VBI output device */ +#define V4L2_CAP_RDS_CAPTURE 0x00000100 /* RDS data capture */ +#define V4L2_CAP_VIDEO_OUTPUT_OVERLAY 0x00000200 /* Can do video output overlay */ +#define V4L2_CAP_HW_FREQ_SEEK 0x00000400 /* Can do hardware frequency seek */ +#define V4L2_CAP_RDS_OUTPUT 0x00000800 /* Is an RDS encoder */ + +/* Is a video capture device that supports multiplanar formats */ +#define V4L2_CAP_VIDEO_CAPTURE_MPLANE 0x00001000 +/* Is a video output device that supports multiplanar formats */ +#define V4L2_CAP_VIDEO_OUTPUT_MPLANE 0x00002000 + +#define V4L2_CAP_TUNER 0x00010000 /* has a tuner */ +#define V4L2_CAP_AUDIO 0x00020000 /* has audio support */ +#define V4L2_CAP_RADIO 0x00040000 /* is a radio device */ +#define V4L2_CAP_MODULATOR 0x00080000 /* has a modulator */ + +#define V4L2_CAP_READWRITE 0x01000000 /* read/write systemcalls */ +#define V4L2_CAP_ASYNCIO 0x02000000 /* async I/O */ +#define V4L2_CAP_STREAMING 0x04000000 /* streaming I/O ioctls */ + +/* + * V I D E O I M A G E F O R M A T + */ +struct v4l2_pix_format { + __u32 width; + __u32 height; + __u32 pixelformat; + enum v4l2_field field; + __u32 bytesperline; /* for padding, zero if unused */ + __u32 sizeimage; + enum v4l2_colorspace colorspace; + __u32 priv; /* private data, depends on pixelformat */ +}; + +/* Pixel format FOURCC depth Description */ + +/* RGB formats */ +#define V4L2_PIX_FMT_RGB332 v4l2_fourcc('R', 'G', 'B', '1') /* 8 RGB-3-3-2 */ +#define V4L2_PIX_FMT_RGB444 v4l2_fourcc('R', '4', '4', '4') /* 16 xxxxrrrr ggggbbbb */ +#define V4L2_PIX_FMT_RGB555 v4l2_fourcc('R', 'G', 'B', 'O') /* 16 RGB-5-5-5 */ +#define V4L2_PIX_FMT_RGB565 v4l2_fourcc('R', 'G', 'B', 'P') /* 16 RGB-5-6-5 */ +#define V4L2_PIX_FMT_RGB555X v4l2_fourcc('R', 'G', 'B', 'Q') /* 16 RGB-5-5-5 BE */ +#define V4L2_PIX_FMT_RGB565X v4l2_fourcc('R', 'G', 'B', 'R') /* 16 RGB-5-6-5 BE */ +#define V4L2_PIX_FMT_BGR666 v4l2_fourcc('B', 'G', 'R', 'H') /* 18 BGR-6-6-6 */ +#define V4L2_PIX_FMT_BGR24 v4l2_fourcc('B', 'G', 'R', '3') /* 24 BGR-8-8-8 */ +#define V4L2_PIX_FMT_RGB24 v4l2_fourcc('R', 'G', 'B', '3') /* 24 RGB-8-8-8 */ +#define V4L2_PIX_FMT_BGR32 v4l2_fourcc('B', 'G', 'R', '4') /* 32 BGR-8-8-8-8 */ +#define V4L2_PIX_FMT_RGB32 v4l2_fourcc('R', 'G', 'B', '4') /* 32 RGB-8-8-8-8 */ + +/* Grey formats */ +#define V4L2_PIX_FMT_GREY v4l2_fourcc('G', 'R', 'E', 'Y') /* 8 Greyscale */ +#define V4L2_PIX_FMT_Y4 v4l2_fourcc('Y', '0', '4', ' ') /* 4 Greyscale */ +#define V4L2_PIX_FMT_Y6 v4l2_fourcc('Y', '0', '6', ' ') /* 6 Greyscale */ +#define V4L2_PIX_FMT_Y10 v4l2_fourcc('Y', '1', '0', ' ') /* 10 Greyscale */ +#define V4L2_PIX_FMT_Y12 v4l2_fourcc('Y', '1', '2', ' ') /* 12 Greyscale */ +#define V4L2_PIX_FMT_Y16 v4l2_fourcc('Y', '1', '6', ' ') /* 16 Greyscale */ + +/* Grey bit-packed formats */ +#define V4L2_PIX_FMT_Y10BPACK v4l2_fourcc('Y', '1', '0', 'B') /* 10 Greyscale bit-packed */ + +/* Palette formats */ +#define V4L2_PIX_FMT_PAL8 v4l2_fourcc('P', 'A', 'L', '8') /* 8 8-bit palette */ + +/* Luminance+Chrominance formats */ +#define V4L2_PIX_FMT_YVU410 v4l2_fourcc('Y', 'V', 'U', '9') /* 9 YVU 4:1:0 */ +#define V4L2_PIX_FMT_YVU420 v4l2_fourcc('Y', 'V', '1', '2') /* 12 YVU 4:2:0 */ +#define V4L2_PIX_FMT_YUYV v4l2_fourcc('Y', 'U', 'Y', 'V') /* 16 YUV 4:2:2 */ +#define V4L2_PIX_FMT_YYUV v4l2_fourcc('Y', 'Y', 'U', 'V') /* 16 YUV 4:2:2 */ +#define V4L2_PIX_FMT_YVYU v4l2_fourcc('Y', 'V', 'Y', 'U') /* 16 YVU 4:2:2 */ +#define V4L2_PIX_FMT_UYVY v4l2_fourcc('U', 'Y', 'V', 'Y') /* 16 YUV 4:2:2 */ +#define V4L2_PIX_FMT_VYUY v4l2_fourcc('V', 'Y', 'U', 'Y') /* 16 YUV 4:2:2 */ +#define V4L2_PIX_FMT_YUV422P v4l2_fourcc('4', '2', '2', 'P') /* 16 YVU422 planar */ +#define V4L2_PIX_FMT_YUV411P v4l2_fourcc('4', '1', '1', 'P') /* 16 YVU411 planar */ +#define V4L2_PIX_FMT_Y41P v4l2_fourcc('Y', '4', '1', 'P') /* 12 YUV 4:1:1 */ +#define V4L2_PIX_FMT_YUV444 v4l2_fourcc('Y', '4', '4', '4') /* 16 xxxxyyyy uuuuvvvv */ +#define V4L2_PIX_FMT_YUV555 v4l2_fourcc('Y', 'U', 'V', 'O') /* 16 YUV-5-5-5 */ +#define V4L2_PIX_FMT_YUV565 v4l2_fourcc('Y', 'U', 'V', 'P') /* 16 YUV-5-6-5 */ +#define V4L2_PIX_FMT_YUV32 v4l2_fourcc('Y', 'U', 'V', '4') /* 32 YUV-8-8-8-8 */ +#define V4L2_PIX_FMT_YUV410 v4l2_fourcc('Y', 'U', 'V', '9') /* 9 YUV 4:1:0 */ +#define V4L2_PIX_FMT_YUV420 v4l2_fourcc('Y', 'U', '1', '2') /* 12 YUV 4:2:0 */ +#define V4L2_PIX_FMT_HI240 v4l2_fourcc('H', 'I', '2', '4') /* 8 8-bit color */ +#define V4L2_PIX_FMT_HM12 v4l2_fourcc('H', 'M', '1', '2') /* 8 YUV 4:2:0 16x16 macroblocks */ +#define V4L2_PIX_FMT_M420 v4l2_fourcc('M', '4', '2', '0') /* 12 YUV 4:2:0 2 lines y, 1 line uv interleaved */ + +/* two planes -- one Y, one Cr + Cb interleaved */ +#define V4L2_PIX_FMT_NV12 v4l2_fourcc('N', 'V', '1', '2') /* 12 Y/CbCr 4:2:0 */ +#define V4L2_PIX_FMT_NV21 v4l2_fourcc('N', 'V', '2', '1') /* 12 Y/CrCb 4:2:0 */ +#define V4L2_PIX_FMT_NV16 v4l2_fourcc('N', 'V', '1', '6') /* 16 Y/CbCr 4:2:2 */ +#define V4L2_PIX_FMT_NV61 v4l2_fourcc('N', 'V', '6', '1') /* 16 Y/CrCb 4:2:2 */ + +/* two non contiguous planes - one Y, one Cr + Cb interleaved */ +#define V4L2_PIX_FMT_NV12M v4l2_fourcc('N', 'M', '1', '2') /* 12 Y/CbCr 4:2:0 */ +#define V4L2_PIX_FMT_NV21M v4l2_fourcc('N', 'M', '2', '1') /* 21 Y/CrCb 4:2:0 */ +#define V4L2_PIX_FMT_NV12MT v4l2_fourcc('T', 'M', '1', '2') /* 12 Y/CbCr 4:2:0 64x32 macroblocks */ +#define V4L2_PIX_FMT_NV12MT_16X16 v4l2_fourcc('V', 'M', '1', '2') /* 12 Y/CbCr 4:2:0 16x16 macroblocks */ + +/* three non contiguous planes - Y, Cb, Cr */ +#define V4L2_PIX_FMT_YUV420M v4l2_fourcc('Y', 'U', 'V', 'M') /* 12 YUV420 planar */ +#define V4L2_PIX_FMT_YVU420M v4l2_fourcc('Y', 'V', 'U', 'M') /* 12 YVU420 planar */ + +/* Bayer formats - see http://www.siliconimaging.com/RGB%20Bayer.htm */ +#define V4L2_PIX_FMT_SBGGR8 v4l2_fourcc('B', 'A', '8', '1') /* 8 BGBG.. GRGR.. */ +#define V4L2_PIX_FMT_SGBRG8 v4l2_fourcc('G', 'B', 'R', 'G') /* 8 GBGB.. RGRG.. */ +#define V4L2_PIX_FMT_SGRBG8 v4l2_fourcc('G', 'R', 'B', 'G') /* 8 GRGR.. BGBG.. */ +#define V4L2_PIX_FMT_SRGGB8 v4l2_fourcc('R', 'G', 'G', 'B') /* 8 RGRG.. GBGB.. */ +#define V4L2_PIX_FMT_SBGGR10 v4l2_fourcc('B', 'G', '1', '0') /* 10 BGBG.. GRGR.. */ +#define V4L2_PIX_FMT_SGBRG10 v4l2_fourcc('G', 'B', '1', '0') /* 10 GBGB.. RGRG.. */ +#define V4L2_PIX_FMT_SGRBG10 v4l2_fourcc('B', 'A', '1', '0') /* 10 GRGR.. BGBG.. */ +#define V4L2_PIX_FMT_SRGGB10 v4l2_fourcc('R', 'G', '1', '0') /* 10 RGRG.. GBGB.. */ +#define V4L2_PIX_FMT_SBGGR12 v4l2_fourcc('B', 'G', '1', '2') /* 12 BGBG.. GRGR.. */ +#define V4L2_PIX_FMT_SGBRG12 v4l2_fourcc('G', 'B', '1', '2') /* 12 GBGB.. RGRG.. */ +#define V4L2_PIX_FMT_SGRBG12 v4l2_fourcc('B', 'A', '1', '2') /* 12 GRGR.. BGBG.. */ +#define V4L2_PIX_FMT_SRGGB12 v4l2_fourcc('R', 'G', '1', '2') /* 12 RGRG.. GBGB.. */ + /* 10bit raw bayer DPCM compressed to 8 bits */ +#define V4L2_PIX_FMT_SGRBG10DPCM8 v4l2_fourcc('B', 'D', '1', '0') + /* + * 10bit raw bayer, expanded to 16 bits + * xxxxrrrrrrrrrrxxxxgggggggggg xxxxggggggggggxxxxbbbbbbbbbb... + */ +#define V4L2_PIX_FMT_SBGGR16 v4l2_fourcc('B', 'Y', 'R', '2') /* 16 BGBG.. GRGR.. */ + +/* compressed formats */ +#define V4L2_PIX_FMT_MJPEG v4l2_fourcc('M', 'J', 'P', 'G') /* Motion-JPEG */ +#define V4L2_PIX_FMT_JPEG v4l2_fourcc('J', 'P', 'E', 'G') /* JFIF JPEG */ +#define V4L2_PIX_FMT_DV v4l2_fourcc('d', 'v', 's', 'd') /* 1394 */ +#define V4L2_PIX_FMT_MPEG v4l2_fourcc('M', 'P', 'E', 'G') /* MPEG-1/2/4 */ + + +#define V4L2_PIX_FMT_H264 v4l2_fourcc('H', '2', '6', '4') /* H264 */ +#define V4L2_PIX_FMT_H263 v4l2_fourcc('H', '2', '6', '3') /* H263 */ +#define V4L2_PIX_FMT_MPEG12 v4l2_fourcc('M', 'P', '1', '2') /* MPEG-1/2 */ +#define V4L2_PIX_FMT_MPEG4 v4l2_fourcc('M', 'P', 'G', '4') /* MPEG-4 */ +#define V4L2_PIX_FMT_FIMV v4l2_fourcc('F', 'I', 'M', 'V') /* FIMV */ +#define V4L2_PIX_FMT_FIMV1 v4l2_fourcc('F', 'I', 'M', '1') /* FIMV1 */ +#define V4L2_PIX_FMT_FIMV2 v4l2_fourcc('F', 'I', 'M', '2') /* FIMV2 */ +#define V4L2_PIX_FMT_FIMV3 v4l2_fourcc('F', 'I', 'M', '3') /* FIMV3 */ +#define V4L2_PIX_FMT_FIMV4 v4l2_fourcc('F', 'I', 'M', '4') /* FIMV4 */ +#define V4L2_PIX_FMT_XVID v4l2_fourcc('X', 'V', 'I', 'D') /* Xvid */ +#define V4L2_PIX_FMT_VC1 v4l2_fourcc('V', 'C', '1', 'A') /* VC-1 */ +#define V4L2_PIX_FMT_VC1_RCV v4l2_fourcc('V', 'C', '1', 'R') /* VC-1 RCV */ +#define V4L2_PIX_FMT_VP8 v4l2_fourcc('V', 'P', '8', '0') /* VP8 */ + + +/* Vendor-specific formats */ +#define V4L2_PIX_FMT_CPIA1 v4l2_fourcc('C', 'P', 'I', 'A') /* cpia1 YUV */ +#define V4L2_PIX_FMT_WNVA v4l2_fourcc('W', 'N', 'V', 'A') /* Winnov hw compress */ +#define V4L2_PIX_FMT_SN9C10X v4l2_fourcc('S', '9', '1', '0') /* SN9C10x compression */ +#define V4L2_PIX_FMT_SN9C20X_I420 v4l2_fourcc('S', '9', '2', '0') /* SN9C20x YUV 4:2:0 */ +#define V4L2_PIX_FMT_PWC1 v4l2_fourcc('P', 'W', 'C', '1') /* pwc older webcam */ +#define V4L2_PIX_FMT_PWC2 v4l2_fourcc('P', 'W', 'C', '2') /* pwc newer webcam */ +#define V4L2_PIX_FMT_ET61X251 v4l2_fourcc('E', '6', '2', '5') /* ET61X251 compression */ +#define V4L2_PIX_FMT_SPCA501 v4l2_fourcc('S', '5', '0', '1') /* YUYV per line */ +#define V4L2_PIX_FMT_SPCA505 v4l2_fourcc('S', '5', '0', '5') /* YYUV per line */ +#define V4L2_PIX_FMT_SPCA508 v4l2_fourcc('S', '5', '0', '8') /* YUVY per line */ +#define V4L2_PIX_FMT_SPCA561 v4l2_fourcc('S', '5', '6', '1') /* compressed GBRG bayer */ +#define V4L2_PIX_FMT_PAC207 v4l2_fourcc('P', '2', '0', '7') /* compressed BGGR bayer */ +#define V4L2_PIX_FMT_MR97310A v4l2_fourcc('M', '3', '1', '0') /* compressed BGGR bayer */ +#define V4L2_PIX_FMT_SN9C2028 v4l2_fourcc('S', 'O', 'N', 'X') /* compressed GBRG bayer */ +#define V4L2_PIX_FMT_SQ905C v4l2_fourcc('9', '0', '5', 'C') /* compressed RGGB bayer */ +#define V4L2_PIX_FMT_PJPG v4l2_fourcc('P', 'J', 'P', 'G') /* Pixart 73xx JPEG */ +#define V4L2_PIX_FMT_OV511 v4l2_fourcc('O', '5', '1', '1') /* ov511 JPEG */ +#define V4L2_PIX_FMT_OV518 v4l2_fourcc('O', '5', '1', '8') /* ov518 JPEG */ +#define V4L2_PIX_FMT_STV0680 v4l2_fourcc('S', '6', '8', '0') /* stv0680 bayer */ +#define V4L2_PIX_FMT_TM6000 v4l2_fourcc('T', 'M', '6', '0') /* tm5600/tm60x0 */ +#define V4L2_PIX_FMT_CIT_YYVYUY v4l2_fourcc('C', 'I', 'T', 'V') /* one line of Y then 1 line of VYUY */ +#define V4L2_PIX_FMT_KONICA420 v4l2_fourcc('K', 'O', 'N', 'I') /* YUV420 planar in blocks of 256 pixels */ +#define V4L2_PIX_FMT_JPGL v4l2_fourcc('J', 'P', 'G', 'L') /* JPEG-Lite */ + +#define V4L2_PIX_FMT_JPEG_444 v4l2_fourcc('J', 'P', 'G', '4') /* yuv444 of JFIF JPEG */ +#define V4L2_PIX_FMT_JPEG_422 v4l2_fourcc('J', 'P', 'G', '2') /* yuv422 of JFIF JPEG */ +#define V4L2_PIX_FMT_JPEG_420 v4l2_fourcc('J', 'P', 'G', '0') /* yuv420 of JFIF JPEG */ +#define V4L2_PIX_FMT_JPEG_GRAY v4l2_fourcc('J', 'P', 'G', 'G') /* grey of JFIF JPEG */ +#define V4L2_PIX_FMT_YUV444_2P v4l2_fourcc('Y', 'U', '2', 'P') /* 16 xxxxyyyy uuuuvvvv */ +#define V4L2_PIX_FMT_YVU444_2P v4l2_fourcc('Y', 'V', '2', 'P') /* 16 xxxxyyyy uuuuvvvv */ +#define V4L2_PIX_FMT_YUV444_3P v4l2_fourcc('Y', 'U', '3', 'P') /* 16 xxxxyyyy uuuuvvvv */ +/* + * F O R M A T E N U M E R A T I O N + */ +struct v4l2_fmtdesc { + __u32 index; /* Format number */ + enum v4l2_buf_type type; /* buffer type */ + __u32 flags; + __u8 description[32]; /* Description string */ + __u32 pixelformat; /* Format fourcc */ + __u32 reserved[4]; +}; + +#define V4L2_FMT_FLAG_COMPRESSED 0x0001 +#define V4L2_FMT_FLAG_EMULATED 0x0002 + +#if 1 + /* Experimental Frame Size and frame rate enumeration */ +/* + * F R A M E S I Z E E N U M E R A T I O N + */ +enum v4l2_frmsizetypes { + V4L2_FRMSIZE_TYPE_DISCRETE = 1, + V4L2_FRMSIZE_TYPE_CONTINUOUS = 2, + V4L2_FRMSIZE_TYPE_STEPWISE = 3, +}; + +struct v4l2_frmsize_discrete { + __u32 width; /* Frame width [pixel] */ + __u32 height; /* Frame height [pixel] */ +}; + +struct v4l2_frmsize_stepwise { + __u32 min_width; /* Minimum frame width [pixel] */ + __u32 max_width; /* Maximum frame width [pixel] */ + __u32 step_width; /* Frame width step size [pixel] */ + __u32 min_height; /* Minimum frame height [pixel] */ + __u32 max_height; /* Maximum frame height [pixel] */ + __u32 step_height; /* Frame height step size [pixel] */ +}; + +struct v4l2_frmsizeenum { + __u32 index; /* Frame size number */ + __u32 pixel_format; /* Pixel format */ + __u32 type; /* Frame size type the device supports. */ + + union { /* Frame size */ + struct v4l2_frmsize_discrete discrete; + struct v4l2_frmsize_stepwise stepwise; + }; + + __u32 reserved[2]; /* Reserved space for future use */ +}; + +/* + * F R A M E R A T E E N U M E R A T I O N + */ +enum v4l2_frmivaltypes { + V4L2_FRMIVAL_TYPE_DISCRETE = 1, + V4L2_FRMIVAL_TYPE_CONTINUOUS = 2, + V4L2_FRMIVAL_TYPE_STEPWISE = 3, +}; + +struct v4l2_frmival_stepwise { + struct v4l2_fract min; /* Minimum frame interval [s] */ + struct v4l2_fract max; /* Maximum frame interval [s] */ + struct v4l2_fract step; /* Frame interval step size [s] */ +}; + +struct v4l2_frmivalenum { + __u32 index; /* Frame format index */ + __u32 pixel_format; /* Pixel format */ + __u32 width; /* Frame width */ + __u32 height; /* Frame height */ + __u32 type; /* Frame interval type the device supports. */ + + union { /* Frame interval */ + struct v4l2_fract discrete; + struct v4l2_frmival_stepwise stepwise; + }; + + __u32 reserved[2]; /* Reserved space for future use */ +}; +#endif + +/* + * T I M E C O D E + */ +struct v4l2_timecode { + __u32 type; + __u32 flags; + __u8 frames; + __u8 seconds; + __u8 minutes; + __u8 hours; + __u8 userbits[4]; +}; + +/* Type */ +#define V4L2_TC_TYPE_24FPS 1 +#define V4L2_TC_TYPE_25FPS 2 +#define V4L2_TC_TYPE_30FPS 3 +#define V4L2_TC_TYPE_50FPS 4 +#define V4L2_TC_TYPE_60FPS 5 + +/* Flags */ +#define V4L2_TC_FLAG_DROPFRAME 0x0001 /* "drop-frame" mode */ +#define V4L2_TC_FLAG_COLORFRAME 0x0002 +#define V4L2_TC_USERBITS_field 0x000C +#define V4L2_TC_USERBITS_USERDEFINED 0x0000 +#define V4L2_TC_USERBITS_8BITCHARS 0x0008 +/* The above is based on SMPTE timecodes */ + +struct v4l2_jpegcompression { + int quality; + + int APPn; /* Number of APP segment to be written, + * must be 0..15 */ + int APP_len; /* Length of data in JPEG APPn segment */ + char APP_data[60]; /* Data in the JPEG APPn segment. */ + + int COM_len; /* Length of data in JPEG COM segment */ + char COM_data[60]; /* Data in JPEG COM segment */ + + __u32 jpeg_markers; /* Which markers should go into the JPEG + * output. Unless you exactly know what + * you do, leave them untouched. + * Inluding less markers will make the + * resulting code smaller, but there will + * be fewer applications which can read it. + * The presence of the APP and COM marker + * is influenced by APP_len and COM_len + * ONLY, not by this property! */ + +#define V4L2_JPEG_MARKER_DHT (1<<3) /* Define Huffman Tables */ +#define V4L2_JPEG_MARKER_DQT (1<<4) /* Define Quantization Tables */ +#define V4L2_JPEG_MARKER_DRI (1<<5) /* Define Restart Interval */ +#define V4L2_JPEG_MARKER_COM (1<<6) /* Comment segment */ +#define V4L2_JPEG_MARKER_APP (1<<7) /* App segment, driver will + * allways use APP0 */ +}; + +/* + * M E M O R Y - M A P P I N G B U F F E R S + */ +struct v4l2_requestbuffers { + __u32 count; + enum v4l2_buf_type type; + enum v4l2_memory memory; + __u32 reserved[2]; +}; + +/** + * struct v4l2_plane - plane info for multi-planar buffers + * @bytesused: number of bytes occupied by data in the plane (payload) + * @length: size of this plane (NOT the payload) in bytes + * @mem_offset: when memory in the associated struct v4l2_buffer is + * V4L2_MEMORY_MMAP, equals the offset from the start of + * the device memory for this plane (or is a "cookie" that + * should be passed to mmap() called on the video node) + * @userptr: when memory is V4L2_MEMORY_USERPTR, a userspace pointer + * pointing to this plane + * @data_offset: offset in the plane to the start of data; usually 0, + * unless there is a header in front of the data + * + * Multi-planar buffers consist of one or more planes, e.g. an YCbCr buffer + * with two planes can have one plane for Y, and another for interleaved CbCr + * components. Each plane can reside in a separate memory buffer, or even in + * a completely separate memory node (e.g. in embedded devices). + */ +struct v4l2_plane { + __u32 bytesused; + __u32 length; + union { + __u32 mem_offset; + unsigned long userptr; + } m; + __u32 data_offset; + void *cookie; + void *share; + __u32 reserved[9]; +}; + +/** + * struct v4l2_buffer - video buffer info + * @index: id number of the buffer + * @type: buffer type (type == *_MPLANE for multiplanar buffers) + * @bytesused: number of bytes occupied by data in the buffer (payload); + * unused (set to 0) for multiplanar buffers + * @flags: buffer informational flags + * @field: field order of the image in the buffer + * @timestamp: frame timestamp + * @timecode: frame timecode + * @sequence: sequence count of this frame + * @memory: the method, in which the actual video data is passed + * @offset: for non-multiplanar buffers with memory == V4L2_MEMORY_MMAP; + * offset from the start of the device memory for this plane, + * (or a "cookie" that should be passed to mmap() as offset) + * @userptr: for non-multiplanar buffers with memory == V4L2_MEMORY_USERPTR; + * a userspace pointer pointing to this buffer + * @planes: for multiplanar buffers; userspace pointer to the array of plane + * info structs for this buffer + * @length: size in bytes of the buffer (NOT its payload) for single-plane + * buffers (when type != *_MPLANE); number of elements in the + * planes array for multi-plane buffers + * @input: input number from which the video data has has been captured + * + * Contains data exchanged by application and driver using one of the Streaming + * I/O methods. + */ +struct v4l2_buffer { + __u32 index; + enum v4l2_buf_type type; + __u32 bytesused; + __u32 flags; + enum v4l2_field field; + struct timeval timestamp; + struct v4l2_timecode timecode; + __u32 sequence; + + /* memory location */ + enum v4l2_memory memory; + union { + __u32 offset; + unsigned long userptr; + struct v4l2_plane *planes; + } m; + __u32 length; + __u32 input; + __u32 reserved; +}; + +/* Flags for 'flags' field */ +#define V4L2_BUF_FLAG_MAPPED 0x0001 /* Buffer is mapped (flag) */ +#define V4L2_BUF_FLAG_QUEUED 0x0002 /* Buffer is queued for processing */ +#define V4L2_BUF_FLAG_DONE 0x0004 /* Buffer is ready */ +#define V4L2_BUF_FLAG_KEYFRAME 0x0008 /* Image is a keyframe (I-frame) */ +#define V4L2_BUF_FLAG_PFRAME 0x0010 /* Image is a P-frame */ +#define V4L2_BUF_FLAG_BFRAME 0x0020 /* Image is a B-frame */ +/* Buffer is ready, but the data contained within is corrupted. */ +#define V4L2_BUF_FLAG_ERROR 0x0040 +#define V4L2_BUF_FLAG_TIMECODE 0x0100 /* timecode field is valid */ +#define V4L2_BUF_FLAG_INPUT 0x0200 /* input field is valid */ + +/* + * O V E R L A Y P R E V I E W + */ +struct v4l2_framebuffer { + __u32 capability; + __u32 flags; +/* FIXME: in theory we should pass something like PCI device + memory + * region + offset instead of some physical address */ + void *base; + struct v4l2_pix_format fmt; +}; +/* Flags for the 'capability' field. Read only */ +#define V4L2_FBUF_CAP_EXTERNOVERLAY 0x0001 +#define V4L2_FBUF_CAP_CHROMAKEY 0x0002 +#define V4L2_FBUF_CAP_LIST_CLIPPING 0x0004 +#define V4L2_FBUF_CAP_BITMAP_CLIPPING 0x0008 +#define V4L2_FBUF_CAP_LOCAL_ALPHA 0x0010 +#define V4L2_FBUF_CAP_GLOBAL_ALPHA 0x0020 +#define V4L2_FBUF_CAP_LOCAL_INV_ALPHA 0x0040 +#define V4L2_FBUF_CAP_SRC_CHROMAKEY 0x0080 +/* Flags for the 'flags' field. */ +#define V4L2_FBUF_FLAG_PRIMARY 0x0001 +#define V4L2_FBUF_FLAG_OVERLAY 0x0002 +#define V4L2_FBUF_FLAG_CHROMAKEY 0x0004 +#define V4L2_FBUF_FLAG_LOCAL_ALPHA 0x0008 +#define V4L2_FBUF_FLAG_GLOBAL_ALPHA 0x0010 +#define V4L2_FBUF_FLAG_LOCAL_INV_ALPHA 0x0020 +#define V4L2_FBUF_FLAG_SRC_CHROMAKEY 0x0040 + +struct v4l2_clip { + struct v4l2_rect c; + struct v4l2_clip __user *next; +}; + +struct v4l2_window { + struct v4l2_rect w; + enum v4l2_field field; + __u32 chromakey; + struct v4l2_clip __user *clips; + __u32 clipcount; + void __user *bitmap; + __u8 global_alpha; +}; + +/* + * C A P T U R E P A R A M E T E R S + */ +struct v4l2_captureparm { + __u32 capability; /* Supported modes */ + __u32 capturemode; /* Current mode */ + struct v4l2_fract timeperframe; /* Time per frame in .1us units */ + __u32 extendedmode; /* Driver-specific extensions */ + __u32 readbuffers; /* # of buffers for read */ + __u32 reserved[4]; +}; + +/* Flags for 'capability' and 'capturemode' fields */ +#define V4L2_MODE_HIGHQUALITY 0x0001 /* High quality imaging mode */ +#define V4L2_CAP_TIMEPERFRAME 0x1000 /* timeperframe field is supported */ + +struct v4l2_outputparm { + __u32 capability; /* Supported modes */ + __u32 outputmode; /* Current mode */ + struct v4l2_fract timeperframe; /* Time per frame in seconds */ + __u32 extendedmode; /* Driver-specific extensions */ + __u32 writebuffers; /* # of buffers for write */ + __u32 reserved[4]; +}; + +/* + * I N P U T I M A G E C R O P P I N G + */ +struct v4l2_cropcap { + enum v4l2_buf_type type; + struct v4l2_rect bounds; + struct v4l2_rect defrect; + struct v4l2_fract pixelaspect; +}; + +struct v4l2_crop { + enum v4l2_buf_type type; + struct v4l2_rect c; +}; + +/* + * A N A L O G V I D E O S T A N D A R D + */ + +typedef __u64 v4l2_std_id; + +/* one bit for each */ +#define V4L2_STD_PAL_B ((v4l2_std_id)0x00000001) +#define V4L2_STD_PAL_B1 ((v4l2_std_id)0x00000002) +#define V4L2_STD_PAL_G ((v4l2_std_id)0x00000004) +#define V4L2_STD_PAL_H ((v4l2_std_id)0x00000008) +#define V4L2_STD_PAL_I ((v4l2_std_id)0x00000010) +#define V4L2_STD_PAL_D ((v4l2_std_id)0x00000020) +#define V4L2_STD_PAL_D1 ((v4l2_std_id)0x00000040) +#define V4L2_STD_PAL_K ((v4l2_std_id)0x00000080) + +#define V4L2_STD_PAL_M ((v4l2_std_id)0x00000100) +#define V4L2_STD_PAL_N ((v4l2_std_id)0x00000200) +#define V4L2_STD_PAL_Nc ((v4l2_std_id)0x00000400) +#define V4L2_STD_PAL_60 ((v4l2_std_id)0x00000800) + +#define V4L2_STD_NTSC_M ((v4l2_std_id)0x00001000) +#define V4L2_STD_NTSC_M_JP ((v4l2_std_id)0x00002000) +#define V4L2_STD_NTSC_443 ((v4l2_std_id)0x00004000) +#define V4L2_STD_NTSC_M_KR ((v4l2_std_id)0x00008000) + +#define V4L2_STD_SECAM_B ((v4l2_std_id)0x00010000) +#define V4L2_STD_SECAM_D ((v4l2_std_id)0x00020000) +#define V4L2_STD_SECAM_G ((v4l2_std_id)0x00040000) +#define V4L2_STD_SECAM_H ((v4l2_std_id)0x00080000) +#define V4L2_STD_SECAM_K ((v4l2_std_id)0x00100000) +#define V4L2_STD_SECAM_K1 ((v4l2_std_id)0x00200000) +#define V4L2_STD_SECAM_L ((v4l2_std_id)0x00400000) +#define V4L2_STD_SECAM_LC ((v4l2_std_id)0x00800000) + +/* ATSC/HDTV */ +#define V4L2_STD_ATSC_8_VSB ((v4l2_std_id)0x01000000) +#define V4L2_STD_ATSC_16_VSB ((v4l2_std_id)0x02000000) + +/* FIXME: + Although std_id is 64 bits, there is an issue on PPC32 architecture that + makes switch(__u64) to break. So, there's a hack on v4l2-common.c rounding + this value to 32 bits. + As, currently, the max value is for V4L2_STD_ATSC_16_VSB (30 bits wide), + it should work fine. However, if needed to add more than two standards, + v4l2-common.c should be fixed. + */ + +/* some merged standards */ +#define V4L2_STD_MN (V4L2_STD_PAL_M|V4L2_STD_PAL_N|V4L2_STD_PAL_Nc|V4L2_STD_NTSC) +#define V4L2_STD_B (V4L2_STD_PAL_B|V4L2_STD_PAL_B1|V4L2_STD_SECAM_B) +#define V4L2_STD_GH (V4L2_STD_PAL_G|V4L2_STD_PAL_H|V4L2_STD_SECAM_G|V4L2_STD_SECAM_H) +#define V4L2_STD_DK (V4L2_STD_PAL_DK|V4L2_STD_SECAM_DK) + +/* some common needed stuff */ +#define V4L2_STD_PAL_BG (V4L2_STD_PAL_B |\ + V4L2_STD_PAL_B1 |\ + V4L2_STD_PAL_G) +#define V4L2_STD_PAL_DK (V4L2_STD_PAL_D |\ + V4L2_STD_PAL_D1 |\ + V4L2_STD_PAL_K) +#define V4L2_STD_PAL (V4L2_STD_PAL_BG |\ + V4L2_STD_PAL_DK |\ + V4L2_STD_PAL_H |\ + V4L2_STD_PAL_I) +#define V4L2_STD_NTSC (V4L2_STD_NTSC_M |\ + V4L2_STD_NTSC_M_JP |\ + V4L2_STD_NTSC_M_KR) +#define V4L2_STD_SECAM_DK (V4L2_STD_SECAM_D |\ + V4L2_STD_SECAM_K |\ + V4L2_STD_SECAM_K1) +#define V4L2_STD_SECAM (V4L2_STD_SECAM_B |\ + V4L2_STD_SECAM_G |\ + V4L2_STD_SECAM_H |\ + V4L2_STD_SECAM_DK |\ + V4L2_STD_SECAM_L |\ + V4L2_STD_SECAM_LC) + +#define V4L2_STD_525_60 (V4L2_STD_PAL_M |\ + V4L2_STD_PAL_60 |\ + V4L2_STD_NTSC |\ + V4L2_STD_NTSC_443) +#define V4L2_STD_625_50 (V4L2_STD_PAL |\ + V4L2_STD_PAL_N |\ + V4L2_STD_PAL_Nc |\ + V4L2_STD_SECAM) +#define V4L2_STD_ATSC (V4L2_STD_ATSC_8_VSB |\ + V4L2_STD_ATSC_16_VSB) + +#define V4L2_STD_UNKNOWN 0 +#define V4L2_STD_ALL (V4L2_STD_525_60 |\ + V4L2_STD_625_50) + +struct v4l2_standard { + __u32 index; + v4l2_std_id id; + __u8 name[24]; + struct v4l2_fract frameperiod; /* Frames, not fields */ + __u32 framelines; + __u32 reserved[4]; +}; + +/* + * V I D E O T I M I N G S D V P R E S E T + */ +struct v4l2_dv_preset { + __u32 preset; + __u32 reserved[4]; +}; + +/* + * D V P R E S E T S E N U M E R A T I O N + */ +struct v4l2_dv_enum_preset { + __u32 index; + __u32 preset; + __u8 name[32]; /* Name of the preset timing */ + __u32 width; + __u32 height; + __u32 reserved[4]; +}; + +/* + * D V P R E S E T V A L U E S + */ +#define V4L2_DV_INVALID 0 +#define V4L2_DV_480P59_94 1 /* BT.1362 */ +#define V4L2_DV_576P50 2 /* BT.1362 */ +#define V4L2_DV_720P24 3 /* SMPTE 296M */ +#define V4L2_DV_720P25 4 /* SMPTE 296M */ +#define V4L2_DV_720P30 5 /* SMPTE 296M */ +#define V4L2_DV_720P50 6 /* SMPTE 296M */ +#define V4L2_DV_720P59_94 7 /* SMPTE 274M */ +#define V4L2_DV_720P60 8 /* SMPTE 274M/296M */ +#define V4L2_DV_1080I29_97 9 /* BT.1120/ SMPTE 274M */ +#define V4L2_DV_1080I30 10 /* BT.1120/ SMPTE 274M */ +#define V4L2_DV_1080I25 11 /* BT.1120 */ +#define V4L2_DV_1080I50 12 /* SMPTE 296M */ +#define V4L2_DV_1080I60 13 /* SMPTE 296M */ +#define V4L2_DV_1080P24 14 /* SMPTE 296M */ +#define V4L2_DV_1080P25 15 /* SMPTE 296M */ +#define V4L2_DV_1080P30 16 /* SMPTE 296M */ +#define V4L2_DV_1080P50 17 /* BT.1120 */ +#define V4L2_DV_1080P60 18 /* BT.1120 */ + +#define V4L2_DV_480P60 19 +#define V4L2_DV_1080I59_94 20 +#define V4L2_DV_1080P59_94 21 + +#define V4L2_DV_720P60_FP 22 +#define V4L2_DV_720P60_SB_HALF 23 +#define V4L2_DV_720P60_TB 24 +#define V4L2_DV_720P59_94_FP 25 +#define V4L2_DV_720P59_94_SB_HALF 26 +#define V4L2_DV_720P59_94_TB 27 +#define V4L2_DV_720P50_FP 28 +#define V4L2_DV_720P50_SB_HALF 29 +#define V4L2_DV_720P50_TB 30 +#define V4L2_DV_1080P24_FP 31 +#define V4L2_DV_1080P24_SB_HALF 32 +#define V4L2_DV_1080P24_TB 33 +#define V4L2_DV_1080P23_98_FP 34 +#define V4L2_DV_1080P23_98_SB_HALF 35 +#define V4L2_DV_1080P23_98_TB 36 +#define V4L2_DV_1080I60_SB_HALF 37 +#define V4L2_DV_1080I59_94_SB_HALF 38 +#define V4L2_DV_1080I50_SB_HALF 39 +#define V4L2_DV_1080P60_SB_HALF 40 +#define V4L2_DV_1080P60_TB 41 +#define V4L2_DV_1080P30_FP 42 +#define V4L2_DV_1080P30_SB_HALF 43 +#define V4L2_DV_1080P30_TB 44 + +/* + * D V B T T I M I N G S + */ + +/* BT.656/BT.1120 timing data */ +struct v4l2_bt_timings { + __u32 width; /* width in pixels */ + __u32 height; /* height in lines */ + __u32 interlaced; /* Interlaced or progressive */ + __u32 polarities; /* Positive or negative polarity */ + __u64 pixelclock; /* Pixel clock in HZ. Ex. 74.25MHz->74250000 */ + __u32 hfrontporch; /* Horizpontal front porch in pixels */ + __u32 hsync; /* Horizontal Sync length in pixels */ + __u32 hbackporch; /* Horizontal back porch in pixels */ + __u32 vfrontporch; /* Vertical front porch in pixels */ + __u32 vsync; /* Vertical Sync length in lines */ + __u32 vbackporch; /* Vertical back porch in lines */ + __u32 il_vfrontporch; /* Vertical front porch for bottom field of + * interlaced field formats + */ + __u32 il_vsync; /* Vertical sync length for bottom field of + * interlaced field formats + */ + __u32 il_vbackporch; /* Vertical back porch for bottom field of + * interlaced field formats + */ + __u32 reserved[16]; +} __attribute__ ((packed)); + +/* Interlaced or progressive format */ +#define V4L2_DV_PROGRESSIVE 0 +#define V4L2_DV_INTERLACED 1 + +/* Polarities. If bit is not set, it is assumed to be negative polarity */ +#define V4L2_DV_VSYNC_POS_POL 0x00000001 +#define V4L2_DV_HSYNC_POS_POL 0x00000002 + + +/* DV timings */ +struct v4l2_dv_timings { + __u32 type; + union { + struct v4l2_bt_timings bt; + __u32 reserved[32]; + }; +} __attribute__ ((packed)); + +/* Values for the type field */ +#define V4L2_DV_BT_656_1120 0 /* BT.656/1120 timing type */ + +/* + * V I D E O I N P U T S + */ +struct v4l2_input { + __u32 index; /* Which input */ + __u8 name[32]; /* Label */ + __u32 type; /* Type of input */ + __u32 audioset; /* Associated audios (bitfield) */ + __u32 tuner; /* Associated tuner */ + v4l2_std_id std; + __u32 status; + __u32 capabilities; + __u32 reserved[3]; +}; + +/* Values for the 'type' field */ +#define V4L2_INPUT_TYPE_TUNER 1 +#define V4L2_INPUT_TYPE_CAMERA 2 + +/* field 'status' - general */ +#define V4L2_IN_ST_NO_POWER 0x00000001 /* Attached device is off */ +#define V4L2_IN_ST_NO_SIGNAL 0x00000002 +#define V4L2_IN_ST_NO_COLOR 0x00000004 + +/* field 'status' - sensor orientation */ +/* If sensor is mounted upside down set both bits */ +#define V4L2_IN_ST_HFLIP 0x00000010 /* Frames are flipped horizontally */ +#define V4L2_IN_ST_VFLIP 0x00000020 /* Frames are flipped vertically */ + +/* field 'status' - analog */ +#define V4L2_IN_ST_NO_H_LOCK 0x00000100 /* No horizontal sync lock */ +#define V4L2_IN_ST_COLOR_KILL 0x00000200 /* Color killer is active */ + +/* field 'status' - digital */ +#define V4L2_IN_ST_NO_SYNC 0x00010000 /* No synchronization lock */ +#define V4L2_IN_ST_NO_EQU 0x00020000 /* No equalizer lock */ +#define V4L2_IN_ST_NO_CARRIER 0x00040000 /* Carrier recovery failed */ + +/* field 'status' - VCR and set-top box */ +#define V4L2_IN_ST_MACROVISION 0x01000000 /* Macrovision detected */ +#define V4L2_IN_ST_NO_ACCESS 0x02000000 /* Conditional access denied */ +#define V4L2_IN_ST_VTR 0x04000000 /* VTR time constant */ + +/* capabilities flags */ +#define V4L2_IN_CAP_PRESETS 0x00000001 /* Supports S_DV_PRESET */ +#define V4L2_IN_CAP_CUSTOM_TIMINGS 0x00000002 /* Supports S_DV_TIMINGS */ +#define V4L2_IN_CAP_STD 0x00000004 /* Supports S_STD */ + +/* + * V I D E O O U T P U T S + */ +struct v4l2_output { + __u32 index; /* Which output */ + __u8 name[32]; /* Label */ + __u32 type; /* Type of output */ + __u32 audioset; /* Associated audios (bitfield) */ + __u32 modulator; /* Associated modulator */ + v4l2_std_id std; + __u32 capabilities; + __u32 reserved[3]; +}; +/* Values for the 'type' field */ +#define V4L2_OUTPUT_TYPE_MODULATOR 1 +#define V4L2_OUTPUT_TYPE_ANALOG 2 +#define V4L2_OUTPUT_TYPE_ANALOGVGAOVERLAY 3 + +/* capabilities flags */ +#define V4L2_OUT_CAP_PRESETS 0x00000001 /* Supports S_DV_PRESET */ +#define V4L2_OUT_CAP_CUSTOM_TIMINGS 0x00000002 /* Supports S_DV_TIMINGS */ +#define V4L2_OUT_CAP_STD 0x00000004 /* Supports S_STD */ + +/* + * C O N T R O L S + */ +struct v4l2_control { + __u32 id; + __s32 value; +}; + +struct v4l2_ext_control { + __u32 id; + __u32 size; + __u32 reserved2[1]; + union { + __s32 value; + __s64 value64; + char *string; + }; +} __attribute__ ((packed)); + +struct v4l2_ext_controls { + __u32 ctrl_class; + __u32 count; + __u32 error_idx; + __u32 reserved[2]; + struct v4l2_ext_control *controls; +}; + +/* Values for ctrl_class field */ +#define V4L2_CTRL_CLASS_USER 0x00980000 /* Old-style 'user' controls */ +#define V4L2_CTRL_CLASS_MPEG 0x00990000 /* MPEG-compression controls */ +#define V4L2_CTRL_CLASS_CAMERA 0x009a0000 /* Camera class controls */ +#define V4L2_CTRL_CLASS_FM_TX 0x009b0000 /* FM Modulator control class */ +#define V4L2_CTRL_CLASS_CODEC 0x009c0000 /* Codec control class */ + +#define V4L2_CTRL_ID_MASK (0x0fffffff) +#define V4L2_CTRL_ID2CLASS(id) ((id) & 0x0fff0000UL) +#define V4L2_CTRL_DRIVER_PRIV(id) (((id) & 0xffff) >= 0x1000) + +enum v4l2_ctrl_type { + V4L2_CTRL_TYPE_INTEGER = 1, + V4L2_CTRL_TYPE_BOOLEAN = 2, + V4L2_CTRL_TYPE_MENU = 3, + V4L2_CTRL_TYPE_BUTTON = 4, + V4L2_CTRL_TYPE_INTEGER64 = 5, + V4L2_CTRL_TYPE_CTRL_CLASS = 6, + V4L2_CTRL_TYPE_STRING = 7, +}; + +/* Used in the VIDIOC_QUERYCTRL ioctl for querying controls */ +struct v4l2_queryctrl { + __u32 id; + enum v4l2_ctrl_type type; + __u8 name[32]; /* Whatever */ + __s32 minimum; /* Note signedness */ + __s32 maximum; + __s32 step; + __s32 default_value; + __u32 flags; + __u32 reserved[2]; +}; + +/* Used in the VIDIOC_QUERYMENU ioctl for querying menu items */ +struct v4l2_querymenu { + __u32 id; + __u32 index; + __u8 name[32]; /* Whatever */ + __u32 reserved; +}; + +/* Control flags */ +#define V4L2_CTRL_FLAG_DISABLED 0x0001 +#define V4L2_CTRL_FLAG_GRABBED 0x0002 +#define V4L2_CTRL_FLAG_READ_ONLY 0x0004 +#define V4L2_CTRL_FLAG_UPDATE 0x0008 +#define V4L2_CTRL_FLAG_INACTIVE 0x0010 +#define V4L2_CTRL_FLAG_SLIDER 0x0020 +#define V4L2_CTRL_FLAG_WRITE_ONLY 0x0040 + +/* Query flag, to be ORed with the control ID */ +#define V4L2_CTRL_FLAG_NEXT_CTRL 0x80000000 + +/* User-class control IDs defined by V4L2 */ +#define V4L2_CID_BASE (V4L2_CTRL_CLASS_USER | 0x900) +#define V4L2_CID_USER_BASE V4L2_CID_BASE +/* IDs reserved for driver specific controls */ +#define V4L2_CID_PRIVATE_BASE 0x08000000 + +#define V4L2_CID_USER_CLASS (V4L2_CTRL_CLASS_USER | 1) +#define V4L2_CID_BRIGHTNESS (V4L2_CID_BASE+0) +#define V4L2_CID_CONTRAST (V4L2_CID_BASE+1) +#define V4L2_CID_SATURATION (V4L2_CID_BASE+2) +#define V4L2_CID_HUE (V4L2_CID_BASE+3) +#define V4L2_CID_AUDIO_VOLUME (V4L2_CID_BASE+5) +#define V4L2_CID_AUDIO_BALANCE (V4L2_CID_BASE+6) +#define V4L2_CID_AUDIO_BASS (V4L2_CID_BASE+7) +#define V4L2_CID_AUDIO_TREBLE (V4L2_CID_BASE+8) +#define V4L2_CID_AUDIO_MUTE (V4L2_CID_BASE+9) +#define V4L2_CID_AUDIO_LOUDNESS (V4L2_CID_BASE+10) +#define V4L2_CID_BLACK_LEVEL (V4L2_CID_BASE+11) /* Deprecated */ +#define V4L2_CID_AUTO_WHITE_BALANCE (V4L2_CID_BASE+12) +#define V4L2_CID_DO_WHITE_BALANCE (V4L2_CID_BASE+13) +#define V4L2_CID_RED_BALANCE (V4L2_CID_BASE+14) +#define V4L2_CID_BLUE_BALANCE (V4L2_CID_BASE+15) +#define V4L2_CID_GAMMA (V4L2_CID_BASE+16) +#define V4L2_CID_WHITENESS (V4L2_CID_GAMMA) /* Deprecated */ +#define V4L2_CID_EXPOSURE (V4L2_CID_BASE+17) +#define V4L2_CID_AUTOGAIN (V4L2_CID_BASE+18) +#define V4L2_CID_GAIN (V4L2_CID_BASE+19) +#define V4L2_CID_HFLIP (V4L2_CID_BASE+20) +#define V4L2_CID_VFLIP (V4L2_CID_BASE+21) + +/* Deprecated; use V4L2_CID_PAN_RESET and V4L2_CID_TILT_RESET */ +#define V4L2_CID_HCENTER (V4L2_CID_BASE+22) +#define V4L2_CID_VCENTER (V4L2_CID_BASE+23) + +#define V4L2_CID_POWER_LINE_FREQUENCY (V4L2_CID_BASE+24) +enum v4l2_power_line_frequency { + V4L2_CID_POWER_LINE_FREQUENCY_DISABLED = 0, + V4L2_CID_POWER_LINE_FREQUENCY_50HZ = 1, + V4L2_CID_POWER_LINE_FREQUENCY_60HZ = 2, +}; +#define V4L2_CID_HUE_AUTO (V4L2_CID_BASE+25) +#define V4L2_CID_WHITE_BALANCE_TEMPERATURE (V4L2_CID_BASE+26) +#define V4L2_CID_SHARPNESS (V4L2_CID_BASE+27) +#define V4L2_CID_BACKLIGHT_COMPENSATION (V4L2_CID_BASE+28) +#define V4L2_CID_CHROMA_AGC (V4L2_CID_BASE+29) +#define V4L2_CID_COLOR_KILLER (V4L2_CID_BASE+30) +#define V4L2_CID_COLORFX (V4L2_CID_BASE+31) +enum v4l2_colorfx { + V4L2_COLORFX_NONE = 0, + V4L2_COLORFX_BW = 1, + V4L2_COLORFX_SEPIA = 2, + V4L2_COLORFX_NEGATIVE = 3, + V4L2_COLORFX_EMBOSS = 4, + V4L2_COLORFX_SKETCH = 5, + V4L2_COLORFX_SKY_BLUE = 6, + V4L2_COLORFX_GRASS_GREEN = 7, + V4L2_COLORFX_SKIN_WHITEN = 8, + V4L2_COLORFX_VIVID = 9, +}; +#define V4L2_CID_AUTOBRIGHTNESS (V4L2_CID_BASE+32) +#define V4L2_CID_BAND_STOP_FILTER (V4L2_CID_BASE+33) + +#define V4L2_CID_ROTATE (V4L2_CID_BASE+34) +#define V4L2_CID_BG_COLOR (V4L2_CID_BASE+35) + +#define V4L2_CID_CHROMA_GAIN (V4L2_CID_BASE+36) + +#define V4L2_CID_ILLUMINATORS_1 (V4L2_CID_BASE+37) +#define V4L2_CID_ILLUMINATORS_2 (V4L2_CID_BASE+38) + +/* + * This is custom CID + */ +/* for rgb alpha function */ +#define V4L2_CID_GLOBAL_ALPHA (V4L2_CID_BASE+39) + +/* cacheable configuration */ +#define V4L2_CID_CACHEABLE (V4L2_CID_BASE+40) + +/* jpeg captured size */ +#define V4L2_CID_CAM_JPEG_MEMSIZE (V4L2_CID_BASE+41) +#define V4L2_CID_CAM_JPEG_ENCODEDSIZE (V4L2_CID_BASE+42) + +#define V4L2_CID_SET_SHAREABLE (V4L2_CID_BASE+43) + +/* TV configuration */ +#define V4L2_CID_TV_LAYER_BLEND_ENABLE (V4L2_CID_BASE+44) +#define V4L2_CID_TV_LAYER_BLEND_ALPHA (V4L2_CID_BASE+45) +#define V4L2_CID_TV_PIXEL_BLEND_ENABLE (V4L2_CID_BASE+46) +#define V4L2_CID_TV_CHROMA_ENABLE (V4L2_CID_BASE+47) +#define V4L2_CID_TV_CHROMA_VALUE (V4L2_CID_BASE+48) +#define V4L2_CID_TV_HPD_STATUS (V4L2_CID_BASE+49) + +/* last CID + 1 */ +#define V4L2_CID_LASTP1 (V4L2_CID_BASE+50) + +/* MPEG-class control IDs defined by V4L2 */ +#define V4L2_CID_MPEG_BASE (V4L2_CTRL_CLASS_MPEG | 0x900) +#define V4L2_CID_MPEG_CLASS (V4L2_CTRL_CLASS_MPEG | 1) + +/* MPEG streams */ +#define V4L2_CID_MPEG_STREAM_TYPE (V4L2_CID_MPEG_BASE+0) +enum v4l2_mpeg_stream_type { + V4L2_MPEG_STREAM_TYPE_MPEG2_PS = 0, /* MPEG-2 program stream */ + V4L2_MPEG_STREAM_TYPE_MPEG2_TS = 1, /* MPEG-2 transport stream */ + V4L2_MPEG_STREAM_TYPE_MPEG1_SS = 2, /* MPEG-1 system stream */ + V4L2_MPEG_STREAM_TYPE_MPEG2_DVD = 3, /* MPEG-2 DVD-compatible stream */ + V4L2_MPEG_STREAM_TYPE_MPEG1_VCD = 4, /* MPEG-1 VCD-compatible stream */ + V4L2_MPEG_STREAM_TYPE_MPEG2_SVCD = 5, /* MPEG-2 SVCD-compatible stream */ +}; +#define V4L2_CID_MPEG_STREAM_PID_PMT (V4L2_CID_MPEG_BASE+1) +#define V4L2_CID_MPEG_STREAM_PID_AUDIO (V4L2_CID_MPEG_BASE+2) +#define V4L2_CID_MPEG_STREAM_PID_VIDEO (V4L2_CID_MPEG_BASE+3) +#define V4L2_CID_MPEG_STREAM_PID_PCR (V4L2_CID_MPEG_BASE+4) +#define V4L2_CID_MPEG_STREAM_PES_ID_AUDIO (V4L2_CID_MPEG_BASE+5) +#define V4L2_CID_MPEG_STREAM_PES_ID_VIDEO (V4L2_CID_MPEG_BASE+6) +#define V4L2_CID_MPEG_STREAM_VBI_FMT (V4L2_CID_MPEG_BASE+7) +enum v4l2_mpeg_stream_vbi_fmt { + V4L2_MPEG_STREAM_VBI_FMT_NONE = 0, /* No VBI in the MPEG stream */ + V4L2_MPEG_STREAM_VBI_FMT_IVTV = 1, /* VBI in private packets, IVTV format */ +}; + +/* MPEG audio */ +#define V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ (V4L2_CID_MPEG_BASE+100) +enum v4l2_mpeg_audio_sampling_freq { + V4L2_MPEG_AUDIO_SAMPLING_FREQ_44100 = 0, + V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000 = 1, + V4L2_MPEG_AUDIO_SAMPLING_FREQ_32000 = 2, +}; +#define V4L2_CID_MPEG_AUDIO_ENCODING (V4L2_CID_MPEG_BASE+101) +enum v4l2_mpeg_audio_encoding { + V4L2_MPEG_AUDIO_ENCODING_LAYER_1 = 0, + V4L2_MPEG_AUDIO_ENCODING_LAYER_2 = 1, + V4L2_MPEG_AUDIO_ENCODING_LAYER_3 = 2, + V4L2_MPEG_AUDIO_ENCODING_AAC = 3, + V4L2_MPEG_AUDIO_ENCODING_AC3 = 4, +}; +#define V4L2_CID_MPEG_AUDIO_L1_BITRATE (V4L2_CID_MPEG_BASE+102) +enum v4l2_mpeg_audio_l1_bitrate { + V4L2_MPEG_AUDIO_L1_BITRATE_32K = 0, + V4L2_MPEG_AUDIO_L1_BITRATE_64K = 1, + V4L2_MPEG_AUDIO_L1_BITRATE_96K = 2, + V4L2_MPEG_AUDIO_L1_BITRATE_128K = 3, + V4L2_MPEG_AUDIO_L1_BITRATE_160K = 4, + V4L2_MPEG_AUDIO_L1_BITRATE_192K = 5, + V4L2_MPEG_AUDIO_L1_BITRATE_224K = 6, + V4L2_MPEG_AUDIO_L1_BITRATE_256K = 7, + V4L2_MPEG_AUDIO_L1_BITRATE_288K = 8, + V4L2_MPEG_AUDIO_L1_BITRATE_320K = 9, + V4L2_MPEG_AUDIO_L1_BITRATE_352K = 10, + V4L2_MPEG_AUDIO_L1_BITRATE_384K = 11, + V4L2_MPEG_AUDIO_L1_BITRATE_416K = 12, + V4L2_MPEG_AUDIO_L1_BITRATE_448K = 13, +}; +#define V4L2_CID_MPEG_AUDIO_L2_BITRATE (V4L2_CID_MPEG_BASE+103) +enum v4l2_mpeg_audio_l2_bitrate { + V4L2_MPEG_AUDIO_L2_BITRATE_32K = 0, + V4L2_MPEG_AUDIO_L2_BITRATE_48K = 1, + V4L2_MPEG_AUDIO_L2_BITRATE_56K = 2, + V4L2_MPEG_AUDIO_L2_BITRATE_64K = 3, + V4L2_MPEG_AUDIO_L2_BITRATE_80K = 4, + V4L2_MPEG_AUDIO_L2_BITRATE_96K = 5, + V4L2_MPEG_AUDIO_L2_BITRATE_112K = 6, + V4L2_MPEG_AUDIO_L2_BITRATE_128K = 7, + V4L2_MPEG_AUDIO_L2_BITRATE_160K = 8, + V4L2_MPEG_AUDIO_L2_BITRATE_192K = 9, + V4L2_MPEG_AUDIO_L2_BITRATE_224K = 10, + V4L2_MPEG_AUDIO_L2_BITRATE_256K = 11, + V4L2_MPEG_AUDIO_L2_BITRATE_320K = 12, + V4L2_MPEG_AUDIO_L2_BITRATE_384K = 13, +}; +#define V4L2_CID_MPEG_AUDIO_L3_BITRATE (V4L2_CID_MPEG_BASE+104) +enum v4l2_mpeg_audio_l3_bitrate { + V4L2_MPEG_AUDIO_L3_BITRATE_32K = 0, + V4L2_MPEG_AUDIO_L3_BITRATE_40K = 1, + V4L2_MPEG_AUDIO_L3_BITRATE_48K = 2, + V4L2_MPEG_AUDIO_L3_BITRATE_56K = 3, + V4L2_MPEG_AUDIO_L3_BITRATE_64K = 4, + V4L2_MPEG_AUDIO_L3_BITRATE_80K = 5, + V4L2_MPEG_AUDIO_L3_BITRATE_96K = 6, + V4L2_MPEG_AUDIO_L3_BITRATE_112K = 7, + V4L2_MPEG_AUDIO_L3_BITRATE_128K = 8, + V4L2_MPEG_AUDIO_L3_BITRATE_160K = 9, + V4L2_MPEG_AUDIO_L3_BITRATE_192K = 10, + V4L2_MPEG_AUDIO_L3_BITRATE_224K = 11, + V4L2_MPEG_AUDIO_L3_BITRATE_256K = 12, + V4L2_MPEG_AUDIO_L3_BITRATE_320K = 13, +}; +#define V4L2_CID_MPEG_AUDIO_MODE (V4L2_CID_MPEG_BASE+105) +enum v4l2_mpeg_audio_mode { + V4L2_MPEG_AUDIO_MODE_STEREO = 0, + V4L2_MPEG_AUDIO_MODE_JOINT_STEREO = 1, + V4L2_MPEG_AUDIO_MODE_DUAL = 2, + V4L2_MPEG_AUDIO_MODE_MONO = 3, +}; +#define V4L2_CID_MPEG_AUDIO_MODE_EXTENSION (V4L2_CID_MPEG_BASE+106) +enum v4l2_mpeg_audio_mode_extension { + V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_4 = 0, + V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_8 = 1, + V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_12 = 2, + V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_16 = 3, +}; +#define V4L2_CID_MPEG_AUDIO_EMPHASIS (V4L2_CID_MPEG_BASE+107) +enum v4l2_mpeg_audio_emphasis { + V4L2_MPEG_AUDIO_EMPHASIS_NONE = 0, + V4L2_MPEG_AUDIO_EMPHASIS_50_DIV_15_uS = 1, + V4L2_MPEG_AUDIO_EMPHASIS_CCITT_J17 = 2, +}; +#define V4L2_CID_MPEG_AUDIO_CRC (V4L2_CID_MPEG_BASE+108) +enum v4l2_mpeg_audio_crc { + V4L2_MPEG_AUDIO_CRC_NONE = 0, + V4L2_MPEG_AUDIO_CRC_CRC16 = 1, +}; +#define V4L2_CID_MPEG_AUDIO_MUTE (V4L2_CID_MPEG_BASE+109) +#define V4L2_CID_MPEG_AUDIO_AAC_BITRATE (V4L2_CID_MPEG_BASE+110) +#define V4L2_CID_MPEG_AUDIO_AC3_BITRATE (V4L2_CID_MPEG_BASE+111) +enum v4l2_mpeg_audio_ac3_bitrate { + V4L2_MPEG_AUDIO_AC3_BITRATE_32K = 0, + V4L2_MPEG_AUDIO_AC3_BITRATE_40K = 1, + V4L2_MPEG_AUDIO_AC3_BITRATE_48K = 2, + V4L2_MPEG_AUDIO_AC3_BITRATE_56K = 3, + V4L2_MPEG_AUDIO_AC3_BITRATE_64K = 4, + V4L2_MPEG_AUDIO_AC3_BITRATE_80K = 5, + V4L2_MPEG_AUDIO_AC3_BITRATE_96K = 6, + V4L2_MPEG_AUDIO_AC3_BITRATE_112K = 7, + V4L2_MPEG_AUDIO_AC3_BITRATE_128K = 8, + V4L2_MPEG_AUDIO_AC3_BITRATE_160K = 9, + V4L2_MPEG_AUDIO_AC3_BITRATE_192K = 10, + V4L2_MPEG_AUDIO_AC3_BITRATE_224K = 11, + V4L2_MPEG_AUDIO_AC3_BITRATE_256K = 12, + V4L2_MPEG_AUDIO_AC3_BITRATE_320K = 13, + V4L2_MPEG_AUDIO_AC3_BITRATE_384K = 14, + V4L2_MPEG_AUDIO_AC3_BITRATE_448K = 15, + V4L2_MPEG_AUDIO_AC3_BITRATE_512K = 16, + V4L2_MPEG_AUDIO_AC3_BITRATE_576K = 17, + V4L2_MPEG_AUDIO_AC3_BITRATE_640K = 18, +}; + +/* MPEG video */ +#define V4L2_CID_MPEG_VIDEO_ENCODING (V4L2_CID_MPEG_BASE+200) +enum v4l2_mpeg_video_encoding { + V4L2_MPEG_VIDEO_ENCODING_MPEG_1 = 0, + V4L2_MPEG_VIDEO_ENCODING_MPEG_2 = 1, + V4L2_MPEG_VIDEO_ENCODING_MPEG_4_AVC = 2, +}; +#define V4L2_CID_MPEG_VIDEO_ASPECT (V4L2_CID_MPEG_BASE+201) +enum v4l2_mpeg_video_aspect { + V4L2_MPEG_VIDEO_ASPECT_1x1 = 0, + V4L2_MPEG_VIDEO_ASPECT_4x3 = 1, + V4L2_MPEG_VIDEO_ASPECT_16x9 = 2, + V4L2_MPEG_VIDEO_ASPECT_221x100 = 3, +}; +#define V4L2_CID_MPEG_VIDEO_B_FRAMES (V4L2_CID_MPEG_BASE+202) +#define V4L2_CID_MPEG_VIDEO_GOP_SIZE (V4L2_CID_MPEG_BASE+203) +#define V4L2_CID_MPEG_VIDEO_GOP_CLOSURE (V4L2_CID_MPEG_BASE+204) +#define V4L2_CID_MPEG_VIDEO_PULLDOWN (V4L2_CID_MPEG_BASE+205) +#define V4L2_CID_MPEG_VIDEO_BITRATE_MODE (V4L2_CID_MPEG_BASE+206) +enum v4l2_mpeg_video_bitrate_mode { + V4L2_MPEG_VIDEO_BITRATE_MODE_VBR = 0, + V4L2_MPEG_VIDEO_BITRATE_MODE_CBR = 1, +}; +#define V4L2_CID_MPEG_VIDEO_BITRATE (V4L2_CID_MPEG_BASE+207) +#define V4L2_CID_MPEG_VIDEO_BITRATE_PEAK (V4L2_CID_MPEG_BASE+208) +#define V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION (V4L2_CID_MPEG_BASE+209) +#define V4L2_CID_MPEG_VIDEO_MUTE (V4L2_CID_MPEG_BASE+210) +#define V4L2_CID_MPEG_VIDEO_MUTE_YUV (V4L2_CID_MPEG_BASE+211) + +/* MPEG-class control IDs specific to the CX2341x driver as defined by V4L2 */ +#define V4L2_CID_MPEG_CX2341X_BASE (V4L2_CTRL_CLASS_MPEG | 0x1000) +#define V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE (V4L2_CID_MPEG_CX2341X_BASE+0) +enum v4l2_mpeg_cx2341x_video_spatial_filter_mode { + V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_MANUAL = 0, + V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO = 1, +}; +#define V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER (V4L2_CID_MPEG_CX2341X_BASE+1) +#define V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE (V4L2_CID_MPEG_CX2341X_BASE+2) +enum v4l2_mpeg_cx2341x_video_luma_spatial_filter_type { + V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_OFF = 0, + V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_1D_HOR = 1, + V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_1D_VERT = 2, + V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_2D_HV_SEPARABLE = 3, + V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_2D_SYM_NON_SEPARABLE = 4, +}; +#define V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE (V4L2_CID_MPEG_CX2341X_BASE+3) +enum v4l2_mpeg_cx2341x_video_chroma_spatial_filter_type { + V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_OFF = 0, + V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_1D_HOR = 1, +}; +#define V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE (V4L2_CID_MPEG_CX2341X_BASE+4) +enum v4l2_mpeg_cx2341x_video_temporal_filter_mode { + V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_MANUAL = 0, + V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_AUTO = 1, +}; +#define V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER (V4L2_CID_MPEG_CX2341X_BASE+5) +#define V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE (V4L2_CID_MPEG_CX2341X_BASE+6) +enum v4l2_mpeg_cx2341x_video_median_filter_type { + V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF = 0, + V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_HOR = 1, + V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_VERT = 2, + V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_HOR_VERT = 3, + V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_DIAG = 4, +}; +#define V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM (V4L2_CID_MPEG_CX2341X_BASE+7) +#define V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP (V4L2_CID_MPEG_CX2341X_BASE+8) +#define V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM (V4L2_CID_MPEG_CX2341X_BASE+9) +#define V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP (V4L2_CID_MPEG_CX2341X_BASE+10) +#define V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS (V4L2_CID_MPEG_CX2341X_BASE+11) + +/* For codecs */ + +#define V4L2_CID_CODEC_BASE (V4L2_CTRL_CLASS_CODEC | 0x900) +#define V4L2_CID_CODEC_CLASS (V4L2_CTRL_CLASS_CODEC | 1) + +/* Codec class control IDs specific to the MFC5X driver */ +#define V4L2_CID_CODEC_MFC5X_BASE (V4L2_CTRL_CLASS_CODEC | 0x1000) + +/* For both decoding and encoding */ + +/* For decoding */ + +#define V4L2_CID_CODEC_LOOP_FILTER_MPEG4_ENABLE (V4L2_CID_CODEC_BASE + 110) +#define V4L2_CID_CODEC_DISPLAY_DELAY (V4L2_CID_CODEC_BASE + 137) +#define V4L2_CID_CODEC_REQ_NUM_BUFS (V4L2_CID_CODEC_BASE + 140) +#define V4L2_CID_CODEC_SLICE_INTERFACE (V4L2_CID_CODEC_BASE + 141) +#define V4L2_CID_CODEC_PACKED_PB (V4L2_CID_CODEC_BASE + 142) +#define V4L2_CID_CODEC_FRAME_TAG (V4L2_CID_CODEC_BASE + 143) +#define V4L2_CID_CODEC_CRC_ENABLE (V4L2_CID_CODEC_BASE + 144) +#define V4L2_CID_CODEC_CRC_DATA_LUMA (V4L2_CID_CODEC_BASE + 145) +#define V4L2_CID_CODEC_CRC_DATA_CHROMA (V4L2_CID_CODEC_BASE + 146) +#define V4L2_CID_CODEC_CRC_DATA_LUMA_BOT (V4L2_CID_CODEC_BASE + 147) +#define V4L2_CID_CODEC_CRC_DATA_CHROMA_BOT (V4L2_CID_CODEC_BASE + 148) +#define V4L2_CID_CODEC_CRC_GENERATED (V4L2_CID_CODEC_BASE + 149) +#define V4L2_CID_CODEC_FRAME_TYPE (V4L2_CID_CODEC_BASE + 154) +#define V4L2_CID_CODEC_CHECK_STATE (V4L2_CID_CODEC_BASE + 155) +#define V4L2_CID_CODEC_DISPLAY_STATUS (V4L2_CID_CODEC_BASE + 156) +#define V4L2_CID_CODEC_FRAME_PACK_SEI_PARSE (V4L2_CID_CODEC_BASE + 157) +#define V4L2_CID_CODEC_FRAME_PACK_SEI_AVAIL (V4L2_CID_CODEC_BASE + 158) +#define V4L2_CID_CODEC_FRAME_PACK_ARRGMENT_ID (V4L2_CID_CODEC_BASE + 159) +#define V4L2_CID_CODEC_FRAME_PACK_SEI_INFO (V4L2_CID_CODEC_BASE + 160) +#define V4L2_CID_CODEC_FRAME_PACK_GRID_POS (V4L2_CID_CODEC_BASE + 161) + +/* For encoding */ +#define V4L2_CID_CODEC_LOOP_FILTER_H264 (V4L2_CID_CODEC_BASE + 9) +enum v4l2_cid_codec_loop_filter_h264 { + V4L2_CID_CODEC_LOOP_FILTER_H264_ENABLE = 0, + V4L2_CID_CODEC_LOOP_FILTER_H264_DISABLE = 1, + V4L2_CID_CODEC_LOOP_FILTER_H264_DISABLE_AT_BOUNDARY = 2, +}; + +#define V4L2_CID_CODEC_FRAME_INSERTION (V4L2_CID_CODEC_BASE + 10) +enum v4l2_cid_codec_frame_insertion { + V4L2_CID_CODEC_FRAME_INSERT_NONE = 0x0, + V4L2_CID_CODEC_FRAME_INSERT_I_FRAME = 0x1, + V4L2_CID_CODEC_FRAME_INSERT_NOT_CODED = 0x2, +}; + +#define V4L2_CID_CODEC_ENCODED_LUMA_ADDR (V4L2_CID_CODEC_BASE + 11) +#define V4L2_CID_CODEC_ENCODED_CHROMA_ADDR (V4L2_CID_CODEC_BASE + 12) + +#define V4L2_CID_CODEC_ENCODED_I_PERIOD_CH V4L2_CID_CODEC_MFC5X_ENC_GOP_SIZE +#define V4L2_CID_CODEC_ENCODED_FRAME_RATE_CH V4L2_CID_CODEC_MFC5X_ENC_H264_RC_FRAME_RATE +#define V4L2_CID_CODEC_ENCODED_BIT_RATE_CH V4L2_CID_CODEC_MFC5X_ENC_RC_BIT_RATE + +#define V4L2_CID_CODEC_FRAME_PACK_SEI_GEN (V4L2_CID_CODEC_BASE + 13) +#define V4L2_CID_CODEC_FRAME_PACK_FRM0_FLAG (V4L2_CID_CODEC_BASE + 14) +enum v4l2_codec_mfc5x_enc_flag { + V4L2_CODEC_MFC5X_ENC_FLAG_DISABLE = 0, + V4L2_CODEC_MFC5X_ENC_FLAG_ENABLE = 1, +}; +#define V4L2_CID_CODEC_FRAME_PACK_ARRGMENT_TYPE (V4L2_CID_CODEC_BASE + 15) +enum v4l2_codec_mfc5x_enc_frame_pack_arrgment_type { + V4L2_CODEC_MFC5X_ENC_FRAME_PACK_SIDE_BY_SIDE = 0, + V4L2_CODEC_MFC5X_ENC_FRAME_PACK_TOP_AND_BOT = 1, + V4L2_CODEC_MFC5X_ENC_FRAME_PACK_TMP_INTER = 2, +}; + +/* common */ +enum v4l2_codec_mfc5x_enc_switch { + V4L2_CODEC_MFC5X_ENC_SW_DISABLE = 0, + V4L2_CODEC_MFC5X_ENC_SW_ENABLE = 1, +}; +enum v4l2_codec_mfc5x_enc_switch_inv { + V4L2_CODEC_MFC5X_ENC_SW_INV_ENABLE = 0, + V4L2_CODEC_MFC5X_ENC_SW_INV_DISABLE = 1, +}; +#define V4L2_CID_CODEC_MFC5X_ENC_GOP_SIZE (V4L2_CID_CODEC_MFC5X_BASE+300) +#define V4L2_CID_CODEC_MFC5X_ENC_MULTI_SLICE_MODE (V4L2_CID_CODEC_MFC5X_BASE+301) +enum v4l2_codec_mfc5x_enc_multi_slice_mode { + V4L2_CODEC_MFC5X_ENC_MULTI_SLICE_MODE_DISABLE = 0, + V4L2_CODEC_MFC5X_ENC_MULTI_SLICE_MODE_MACROBLOCK_COUNT = 1, + V4L2_CODEC_MFC5X_ENC_MULTI_SLICE_MODE_BIT_COUNT = 3, +}; +#define V4L2_CID_CODEC_MFC5X_ENC_MULTI_SLICE_MB (V4L2_CID_CODEC_MFC5X_BASE+302) +#define V4L2_CID_CODEC_MFC5X_ENC_MULTI_SLICE_BIT (V4L2_CID_CODEC_MFC5X_BASE+303) +#define V4L2_CID_CODEC_MFC5X_ENC_INTRA_REFRESH_MB (V4L2_CID_CODEC_MFC5X_BASE+304) +#define V4L2_CID_CODEC_MFC5X_ENC_PAD_CTRL_ENABLE (V4L2_CID_CODEC_MFC5X_BASE+305) +#define V4L2_CID_CODEC_MFC5X_ENC_PAD_LUMA_VALUE (V4L2_CID_CODEC_MFC5X_BASE+306) +#define V4L2_CID_CODEC_MFC5X_ENC_PAD_CB_VALUE (V4L2_CID_CODEC_MFC5X_BASE+307) +#define V4L2_CID_CODEC_MFC5X_ENC_PAD_CR_VALUE (V4L2_CID_CODEC_MFC5X_BASE+308) +#define V4L2_CID_CODEC_MFC5X_ENC_RC_FRAME_ENABLE (V4L2_CID_CODEC_MFC5X_BASE+309) +#define V4L2_CID_CODEC_MFC5X_ENC_RC_BIT_RATE (V4L2_CID_CODEC_MFC5X_BASE+310) +#define V4L2_CID_CODEC_MFC5X_ENC_RC_REACTION_COEFF (V4L2_CID_CODEC_MFC5X_BASE+311) +#define V4L2_CID_CODEC_MFC5X_ENC_STREAM_SIZE (V4L2_CID_CODEC_MFC5X_BASE+312) +#define V4L2_CID_CODEC_MFC5X_ENC_FRAME_COUNT (V4L2_CID_CODEC_MFC5X_BASE+313) +#define V4L2_CID_CODEC_MFC5X_ENC_FRAME_TYPE (V4L2_CID_CODEC_MFC5X_BASE+314) +enum v4l2_codec_mfc5x_enc_frame_type { + V4L2_CODEC_MFC5X_ENC_FRAME_TYPE_NOT_CODED = 0, + V4L2_CODEC_MFC5X_ENC_FRAME_TYPE_I_FRAME = 1, + V4L2_CODEC_MFC5X_ENC_FRAME_TYPE_P_FRAME = 2, + V4L2_CODEC_MFC5X_ENC_FRAME_TYPE_B_FRAME = 3, + V4L2_CODEC_MFC5X_ENC_FRAME_TYPE_SKIPPED = 4, + V4L2_CODEC_MFC5X_ENC_FRAME_TYPE_OTHERS = 5, +}; +#define V4L2_CID_CODEC_MFC5X_ENC_FORCE_FRAME_TYPE (V4L2_CID_CODEC_MFC5X_BASE+315) +enum v4l2_codec_mfc5x_enc_force_frame_type { + V4L2_CODEC_MFC5X_ENC_FORCE_FRAME_TYPE_I_FRAME = 1, + V4L2_CODEC_MFC5X_ENC_FORCE_FRAME_TYPE_NOT_CODED = 2, +}; +#define V4L2_CID_CODEC_MFC5X_ENC_VBV_BUF_SIZE (V4L2_CID_CODEC_MFC5X_BASE+316) +#define V4L2_CID_CODEC_MFC5X_ENC_SEQ_HDR_MODE (V4L2_CID_CODEC_MFC5X_BASE+317) +enum v4l2_codec_mfc5x_enc_seq_hdr_mode { + V4L2_CODEC_MFC5X_ENC_SEQ_HDR_MODE_SEQ = 0, + V4L2_CODEC_MFC5X_ENC_SEQ_HDR_MODE_SEQ_FRAME = 1, +}; +#define V4L2_CID_CODEC_MFC5X_ENC_FRAME_SKIP_MODE (V4L2_CID_CODEC_MFC5X_BASE+318) +enum v4l2_codec_mfc5x_enc_frame_skip_mode { + V4L2_CODEC_MFC5X_ENC_FRAME_SKIP_MODE_DISABLE = 0, + V4L2_CODEC_MFC5X_ENC_FRAME_SKIP_MODE_LEVEL = 1, + V4L2_CODEC_MFC5X_ENC_FRAME_SKIP_MODE_VBV_BUF_SIZE = 2, +}; +#define V4L2_CID_CODEC_MFC5X_ENC_RC_FIXED_TARGET_BIT (V4L2_CID_CODEC_MFC5X_BASE+319) +#define V4L2_CID_CODEC_MFC5X_ENC_FRAME_DELTA (V4L2_CID_CODEC_MFC5X_BASE+320) + +/* codec specific */ +#define V4L2_CID_CODEC_MFC5X_ENC_H264_B_FRAMES (V4L2_CID_CODEC_MFC5X_BASE+400) +#define V4L2_CID_CODEC_MFC5X_ENC_H264_PROFILE (V4L2_CID_CODEC_MFC5X_BASE+401) +enum v4l2_codec_mfc5x_enc_h264_profile { + V4L2_CODEC_MFC5X_ENC_H264_PROFILE_MAIN = 0, + V4L2_CODEC_MFC5X_ENC_H264_PROFILE_HIGH = 1, + V4L2_CODEC_MFC5X_ENC_H264_PROFILE_BASELINE = 2, +}; +#define V4L2_CID_CODEC_MFC5X_ENC_H264_LEVEL (V4L2_CID_CODEC_MFC5X_BASE+402) +#define V4L2_CID_CODEC_MFC5X_ENC_H264_INTERLACE (V4L2_CID_CODEC_MFC5X_BASE+403) +#define V4L2_CID_CODEC_MFC5X_ENC_H264_LOOP_FILTER_MODE (V4L2_CID_CODEC_MFC5X_BASE+404) +enum v4l2_codec_mfc5x_enc_h264_loop_filter { + V4L2_CODEC_MFC5X_ENC_H264_LOOP_FILTER_ENABLE = 0, + V4L2_CODEC_MFC5X_ENC_H264_LOOP_FILTER_DISABLE = 1, + V4L2_CODEC_MFC5X_ENC_H264_LOOP_FILTER_DISABLE_AT_BOUNDARY = 2, +}; +#define V4L2_CID_CODEC_MFC5X_ENC_H264_LOOP_FILTER_ALPHA (V4L2_CID_CODEC_MFC5X_BASE+405) +#define V4L2_CID_CODEC_MFC5X_ENC_H264_LOOP_FILTER_BETA (V4L2_CID_CODEC_MFC5X_BASE+406) +#define V4L2_CID_CODEC_MFC5X_ENC_H264_ENTROPY_MODE (V4L2_CID_CODEC_MFC5X_BASE+407) +enum v4l2_codec_mfc5x_enc_h264_entropy_mode { + V4L2_CODEC_MFC5X_ENC_H264_ENTROPY_MODE_CAVLC = 0, + V4L2_CODEC_MFC5X_ENC_H264_ENTROPY_MODE_CABAC = 1, +}; +#define V4L2_CID_CODEC_MFC5X_ENC_H264_MAX_REF_PIC (V4L2_CID_CODEC_MFC5X_BASE+408) +#define V4L2_CID_CODEC_MFC5X_ENC_H264_NUM_REF_PIC_4P (V4L2_CID_CODEC_MFC5X_BASE+409) +#define V4L2_CID_CODEC_MFC5X_ENC_H264_8X8_TRANSFORM (V4L2_CID_CODEC_MFC5X_BASE+410) +#define V4L2_CID_CODEC_MFC5X_ENC_H264_RC_MB_ENABLE (V4L2_CID_CODEC_MFC5X_BASE+411) +#define V4L2_CID_CODEC_MFC5X_ENC_H264_RC_FRAME_RATE (V4L2_CID_CODEC_MFC5X_BASE+412) +#define V4L2_CID_CODEC_MFC5X_ENC_H264_RC_FRAME_QP (V4L2_CID_CODEC_MFC5X_BASE+413) +#define V4L2_CID_CODEC_MFC5X_ENC_H264_RC_MIN_QP (V4L2_CID_CODEC_MFC5X_BASE+414) +#define V4L2_CID_CODEC_MFC5X_ENC_H264_RC_MAX_QP (V4L2_CID_CODEC_MFC5X_BASE+415) +#define V4L2_CID_CODEC_MFC5X_ENC_H264_RC_MB_DARK (V4L2_CID_CODEC_MFC5X_BASE+416) +#define V4L2_CID_CODEC_MFC5X_ENC_H264_RC_MB_SMOOTH (V4L2_CID_CODEC_MFC5X_BASE+417) +#define V4L2_CID_CODEC_MFC5X_ENC_H264_RC_MB_STATIC (V4L2_CID_CODEC_MFC5X_BASE+418) +#define V4L2_CID_CODEC_MFC5X_ENC_H264_RC_MB_ACTIVITY (V4L2_CID_CODEC_MFC5X_BASE+419) +#define V4L2_CID_CODEC_MFC5X_ENC_H264_RC_P_FRAME_QP (V4L2_CID_CODEC_MFC5X_BASE+420) +#define V4L2_CID_CODEC_MFC5X_ENC_H264_RC_B_FRAME_QP (V4L2_CID_CODEC_MFC5X_BASE+421) +#define V4L2_CID_CODEC_MFC5X_ENC_H264_AR_VUI_ENABLE (V4L2_CID_CODEC_MFC5X_BASE+422) +#define V4L2_CID_CODEC_MFC5X_ENC_H264_AR_VUI_IDC (V4L2_CID_CODEC_MFC5X_BASE+423) +#define V4L2_CID_CODEC_MFC5X_ENC_H264_EXT_SAR_WIDTH (V4L2_CID_CODEC_MFC5X_BASE+424) +#define V4L2_CID_CODEC_MFC5X_ENC_H264_EXT_SAR_HEIGHT (V4L2_CID_CODEC_MFC5X_BASE+425) +#define V4L2_CID_CODEC_MFC5X_ENC_H264_OPEN_GOP (V4L2_CID_CODEC_MFC5X_BASE+426) +#define V4L2_CID_CODEC_MFC5X_ENC_H264_I_PERIOD (V4L2_CID_CODEC_MFC5X_BASE+427) +#define V4L2_CID_CODEC_MFC5X_ENC_H264_HIER_P_ENABLE (V4L2_CID_CODEC_MFC5X_BASE+428) +#define V4L2_CID_CODEC_MFC5X_ENC_H264_LAYER0_QP (V4L2_CID_CODEC_MFC5X_BASE+429) +#define V4L2_CID_CODEC_MFC5X_ENC_H264_LAYER1_QP (V4L2_CID_CODEC_MFC5X_BASE+430) +#define V4L2_CID_CODEC_MFC5X_ENC_H264_LAYER2_QP (V4L2_CID_CODEC_MFC5X_BASE+431) + +#define V4L2_CID_CODEC_MFC5X_ENC_MPEG4_B_FRAMES (V4L2_CID_CODEC_MFC5X_BASE+440) +#define V4L2_CID_CODEC_MFC5X_ENC_MPEG4_PROFILE (V4L2_CID_CODEC_MFC5X_BASE+441) +enum v4l2_codec_mfc5x_enc_mpeg4_profile { + V4L2_CODEC_MFC5X_ENC_MPEG4_PROFILE_SIMPLE = 0, + V4L2_CODEC_MFC5X_ENC_MPEG4_PROFILE_ADVANCED_SIMPLE = 1, +}; +#define V4L2_CID_CODEC_MFC5X_ENC_MPEG4_LEVEL (V4L2_CID_CODEC_MFC5X_BASE+442) +#define V4L2_CID_CODEC_MFC5X_ENC_MPEG4_RC_FRAME_QP (V4L2_CID_CODEC_MFC5X_BASE+443) +#define V4L2_CID_CODEC_MFC5X_ENC_MPEG4_RC_MIN_QP (V4L2_CID_CODEC_MFC5X_BASE+444) +#define V4L2_CID_CODEC_MFC5X_ENC_MPEG4_RC_MAX_QP (V4L2_CID_CODEC_MFC5X_BASE+445) +#define V4L2_CID_CODEC_MFC5X_ENC_MPEG4_QUARTER_PIXEL (V4L2_CID_CODEC_MFC5X_BASE+446) +#define V4L2_CID_CODEC_MFC5X_ENC_MPEG4_RC_P_FRAME_QP (V4L2_CID_CODEC_MFC5X_BASE+447) +#define V4L2_CID_CODEC_MFC5X_ENC_MPEG4_RC_B_FRAME_QP (V4L2_CID_CODEC_MFC5X_BASE+448) +#define V4L2_CID_CODEC_MFC5X_ENC_MPEG4_VOP_TIME_RES (V4L2_CID_CODEC_MFC5X_BASE+449) +#define V4L2_CID_CODEC_MFC5X_ENC_MPEG4_VOP_FRM_DELTA (V4L2_CID_CODEC_MFC5X_BASE+450) +#define V4L2_CID_CODEC_MFC5X_ENC_MPEG4_RC_MB_ENABLE (V4L2_CID_CODEC_MFC5X_BASE+451) + +#define V4L2_CID_CODEC_MFC5X_ENC_H263_RC_FRAME_RATE (V4L2_CID_CODEC_MFC5X_BASE+460) +#define V4L2_CID_CODEC_MFC5X_ENC_H263_RC_FRAME_QP (V4L2_CID_CODEC_MFC5X_BASE+461) +#define V4L2_CID_CODEC_MFC5X_ENC_H263_RC_MIN_QP (V4L2_CID_CODEC_MFC5X_BASE+462) +#define V4L2_CID_CODEC_MFC5X_ENC_H263_RC_MAX_QP (V4L2_CID_CODEC_MFC5X_BASE+463) +#define V4L2_CID_CODEC_MFC5X_ENC_H263_RC_P_FRAME_QP (V4L2_CID_CODEC_MFC5X_BASE+464) +#define V4L2_CID_CODEC_MFC5X_ENC_H263_RC_MB_ENABLE (V4L2_CID_CODEC_MFC5X_BASE+465) + +/* Camera class control IDs */ +#define V4L2_CID_CAMERA_CLASS_BASE (V4L2_CTRL_CLASS_CAMERA | 0x900) +#define V4L2_CID_CAMERA_CLASS (V4L2_CTRL_CLASS_CAMERA | 1) + +#define V4L2_CID_EXPOSURE_AUTO (V4L2_CID_CAMERA_CLASS_BASE+1) +enum v4l2_exposure_auto_type { + V4L2_EXPOSURE_AUTO = 0, + V4L2_EXPOSURE_MANUAL = 1, + V4L2_EXPOSURE_SHUTTER_PRIORITY = 2, + V4L2_EXPOSURE_APERTURE_PRIORITY = 3 +}; +#define V4L2_CID_EXPOSURE_ABSOLUTE (V4L2_CID_CAMERA_CLASS_BASE+2) +#define V4L2_CID_EXPOSURE_AUTO_PRIORITY (V4L2_CID_CAMERA_CLASS_BASE+3) + +#define V4L2_CID_PAN_RELATIVE (V4L2_CID_CAMERA_CLASS_BASE+4) +#define V4L2_CID_TILT_RELATIVE (V4L2_CID_CAMERA_CLASS_BASE+5) +#define V4L2_CID_PAN_RESET (V4L2_CID_CAMERA_CLASS_BASE+6) +#define V4L2_CID_TILT_RESET (V4L2_CID_CAMERA_CLASS_BASE+7) + +#define V4L2_CID_PAN_ABSOLUTE (V4L2_CID_CAMERA_CLASS_BASE+8) +#define V4L2_CID_TILT_ABSOLUTE (V4L2_CID_CAMERA_CLASS_BASE+9) + +#define V4L2_CID_FOCUS_ABSOLUTE (V4L2_CID_CAMERA_CLASS_BASE+10) +#define V4L2_CID_FOCUS_RELATIVE (V4L2_CID_CAMERA_CLASS_BASE+11) +#define V4L2_CID_FOCUS_AUTO (V4L2_CID_CAMERA_CLASS_BASE+12) + +#define V4L2_CID_ZOOM_ABSOLUTE (V4L2_CID_CAMERA_CLASS_BASE+13) +#define V4L2_CID_ZOOM_RELATIVE (V4L2_CID_CAMERA_CLASS_BASE+14) +#define V4L2_CID_ZOOM_CONTINUOUS (V4L2_CID_CAMERA_CLASS_BASE+15) + +#define V4L2_CID_PRIVACY (V4L2_CID_CAMERA_CLASS_BASE+16) + +#define V4L2_CID_IRIS_ABSOLUTE (V4L2_CID_CAMERA_CLASS_BASE+17) +#define V4L2_CID_IRIS_RELATIVE (V4L2_CID_CAMERA_CLASS_BASE+18) + +/* FM Modulator class control IDs */ +#define V4L2_CID_FM_TX_CLASS_BASE (V4L2_CTRL_CLASS_FM_TX | 0x900) +#define V4L2_CID_FM_TX_CLASS (V4L2_CTRL_CLASS_FM_TX | 1) + +#define V4L2_CID_RDS_TX_DEVIATION (V4L2_CID_FM_TX_CLASS_BASE + 1) +#define V4L2_CID_RDS_TX_PI (V4L2_CID_FM_TX_CLASS_BASE + 2) +#define V4L2_CID_RDS_TX_PTY (V4L2_CID_FM_TX_CLASS_BASE + 3) +#define V4L2_CID_RDS_TX_PS_NAME (V4L2_CID_FM_TX_CLASS_BASE + 5) +#define V4L2_CID_RDS_TX_RADIO_TEXT (V4L2_CID_FM_TX_CLASS_BASE + 6) + +#define V4L2_CID_AUDIO_LIMITER_ENABLED (V4L2_CID_FM_TX_CLASS_BASE + 64) +#define V4L2_CID_AUDIO_LIMITER_RELEASE_TIME (V4L2_CID_FM_TX_CLASS_BASE + 65) +#define V4L2_CID_AUDIO_LIMITER_DEVIATION (V4L2_CID_FM_TX_CLASS_BASE + 66) + +#define V4L2_CID_AUDIO_COMPRESSION_ENABLED (V4L2_CID_FM_TX_CLASS_BASE + 80) +#define V4L2_CID_AUDIO_COMPRESSION_GAIN (V4L2_CID_FM_TX_CLASS_BASE + 81) +#define V4L2_CID_AUDIO_COMPRESSION_THRESHOLD (V4L2_CID_FM_TX_CLASS_BASE + 82) +#define V4L2_CID_AUDIO_COMPRESSION_ATTACK_TIME (V4L2_CID_FM_TX_CLASS_BASE + 83) +#define V4L2_CID_AUDIO_COMPRESSION_RELEASE_TIME (V4L2_CID_FM_TX_CLASS_BASE + 84) + +#define V4L2_CID_PILOT_TONE_ENABLED (V4L2_CID_FM_TX_CLASS_BASE + 96) +#define V4L2_CID_PILOT_TONE_DEVIATION (V4L2_CID_FM_TX_CLASS_BASE + 97) +#define V4L2_CID_PILOT_TONE_FREQUENCY (V4L2_CID_FM_TX_CLASS_BASE + 98) + +#define V4L2_CID_TUNE_PREEMPHASIS (V4L2_CID_FM_TX_CLASS_BASE + 112) +enum v4l2_preemphasis { + V4L2_PREEMPHASIS_DISABLED = 0, + V4L2_PREEMPHASIS_50_uS = 1, + V4L2_PREEMPHASIS_75_uS = 2, +}; +#define V4L2_CID_TUNE_POWER_LEVEL (V4L2_CID_FM_TX_CLASS_BASE + 113) +#define V4L2_CID_TUNE_ANTENNA_CAPACITOR (V4L2_CID_FM_TX_CLASS_BASE + 114) + +/* + * T U N I N G + */ +struct v4l2_tuner { + __u32 index; + __u8 name[32]; + enum v4l2_tuner_type type; + __u32 capability; + __u32 rangelow; + __u32 rangehigh; + __u32 rxsubchans; + __u32 audmode; + __s32 signal; + __s32 afc; + __u32 reserved[4]; +}; + +struct v4l2_modulator { + __u32 index; + __u8 name[32]; + __u32 capability; + __u32 rangelow; + __u32 rangehigh; + __u32 txsubchans; + __u32 reserved[4]; +}; + +/* Flags for the 'capability' field */ +#define V4L2_TUNER_CAP_LOW 0x0001 +#define V4L2_TUNER_CAP_NORM 0x0002 +#define V4L2_TUNER_CAP_STEREO 0x0010 +#define V4L2_TUNER_CAP_LANG2 0x0020 +#define V4L2_TUNER_CAP_SAP 0x0020 +#define V4L2_TUNER_CAP_LANG1 0x0040 +#define V4L2_TUNER_CAP_RDS 0x0080 +#define V4L2_TUNER_CAP_RDS_BLOCK_IO 0x0100 +#define V4L2_TUNER_CAP_RDS_CONTROLS 0x0200 + +/* Flags for the 'rxsubchans' field */ +#define V4L2_TUNER_SUB_MONO 0x0001 +#define V4L2_TUNER_SUB_STEREO 0x0002 +#define V4L2_TUNER_SUB_LANG2 0x0004 +#define V4L2_TUNER_SUB_SAP 0x0004 +#define V4L2_TUNER_SUB_LANG1 0x0008 +#define V4L2_TUNER_SUB_RDS 0x0010 + +/* Values for the 'audmode' field */ +#define V4L2_TUNER_MODE_MONO 0x0000 +#define V4L2_TUNER_MODE_STEREO 0x0001 +#define V4L2_TUNER_MODE_LANG2 0x0002 +#define V4L2_TUNER_MODE_SAP 0x0002 +#define V4L2_TUNER_MODE_LANG1 0x0003 +#define V4L2_TUNER_MODE_LANG1_LANG2 0x0004 + +struct v4l2_frequency { + __u32 tuner; + enum v4l2_tuner_type type; + __u32 frequency; + __u32 reserved[8]; +}; + +struct v4l2_hw_freq_seek { + __u32 tuner; + enum v4l2_tuner_type type; + __u32 seek_upward; + __u32 wrap_around; + __u32 spacing; + __u32 reserved[7]; +}; + +/* + * R D S + */ + +struct v4l2_rds_data { + __u8 lsb; + __u8 msb; + __u8 block; +} __attribute__ ((packed)); + +#define V4L2_RDS_BLOCK_MSK 0x7 +#define V4L2_RDS_BLOCK_A 0 +#define V4L2_RDS_BLOCK_B 1 +#define V4L2_RDS_BLOCK_C 2 +#define V4L2_RDS_BLOCK_D 3 +#define V4L2_RDS_BLOCK_C_ALT 4 +#define V4L2_RDS_BLOCK_INVALID 7 + +#define V4L2_RDS_BLOCK_CORRECTED 0x40 +#define V4L2_RDS_BLOCK_ERROR 0x80 + +/* + * A U D I O + */ +struct v4l2_audio { + __u32 index; + __u8 name[32]; + __u32 capability; + __u32 mode; + __u32 reserved[2]; +}; + +/* Flags for the 'capability' field */ +#define V4L2_AUDCAP_STEREO 0x00001 +#define V4L2_AUDCAP_AVL 0x00002 + +/* Flags for the 'mode' field */ +#define V4L2_AUDMODE_AVL 0x00001 + +struct v4l2_audioout { + __u32 index; + __u8 name[32]; + __u32 capability; + __u32 mode; + __u32 reserved[2]; +}; + +/* + * M P E G S E R V I C E S + * + * NOTE: EXPERIMENTAL API + */ +#if 1 +#define V4L2_ENC_IDX_FRAME_I (0) +#define V4L2_ENC_IDX_FRAME_P (1) +#define V4L2_ENC_IDX_FRAME_B (2) +#define V4L2_ENC_IDX_FRAME_MASK (0xf) + +struct v4l2_enc_idx_entry { + __u64 offset; + __u64 pts; + __u32 length; + __u32 flags; + __u32 reserved[2]; +}; + +#define V4L2_ENC_IDX_ENTRIES (64) +struct v4l2_enc_idx { + __u32 entries; + __u32 entries_cap; + __u32 reserved[4]; + struct v4l2_enc_idx_entry entry[V4L2_ENC_IDX_ENTRIES]; +}; + + +#define V4L2_ENC_CMD_START (0) +#define V4L2_ENC_CMD_STOP (1) +#define V4L2_ENC_CMD_PAUSE (2) +#define V4L2_ENC_CMD_RESUME (3) + +/* Flags for V4L2_ENC_CMD_STOP */ +#define V4L2_ENC_CMD_STOP_AT_GOP_END (1 << 0) + +struct v4l2_encoder_cmd { + __u32 cmd; + __u32 flags; + union { + struct { + __u32 data[8]; + } raw; + }; +}; + +#endif + + +/* + * D A T A S E R V I C E S ( V B I ) + * + * Data services API by Michael Schimek + */ + +/* Raw VBI */ +struct v4l2_vbi_format { + __u32 sampling_rate; /* in 1 Hz */ + __u32 offset; + __u32 samples_per_line; + __u32 sample_format; /* V4L2_PIX_FMT_* */ + __s32 start[2]; + __u32 count[2]; + __u32 flags; /* V4L2_VBI_* */ + __u32 reserved[2]; /* must be zero */ +}; + +/* VBI flags */ +#define V4L2_VBI_UNSYNC (1 << 0) +#define V4L2_VBI_INTERLACED (1 << 1) + +/* Sliced VBI + * + * This implements is a proposal V4L2 API to allow SLICED VBI + * required for some hardware encoders. It should change without + * notice in the definitive implementation. + */ + +struct v4l2_sliced_vbi_format { + __u16 service_set; + /* service_lines[0][...] specifies lines 0-23 (1-23 used) of the first field + service_lines[1][...] specifies lines 0-23 (1-23 used) of the second field + (equals frame lines 313-336 for 625 line video + standards, 263-286 for 525 line standards) */ + __u16 service_lines[2][24]; + __u32 io_size; + __u32 reserved[2]; /* must be zero */ +}; + +/* Teletext World System Teletext + (WST), defined on ITU-R BT.653-2 */ +#define V4L2_SLICED_TELETEXT_B (0x0001) +/* Video Program System, defined on ETS 300 231*/ +#define V4L2_SLICED_VPS (0x0400) +/* Closed Caption, defined on EIA-608 */ +#define V4L2_SLICED_CAPTION_525 (0x1000) +/* Wide Screen System, defined on ITU-R BT1119.1 */ +#define V4L2_SLICED_WSS_625 (0x4000) + +#define V4L2_SLICED_VBI_525 (V4L2_SLICED_CAPTION_525) +#define V4L2_SLICED_VBI_625 (V4L2_SLICED_TELETEXT_B | V4L2_SLICED_VPS | V4L2_SLICED_WSS_625) + +struct v4l2_sliced_vbi_cap { + __u16 service_set; + /* service_lines[0][...] specifies lines 0-23 (1-23 used) of the first field + service_lines[1][...] specifies lines 0-23 (1-23 used) of the second field + (equals frame lines 313-336 for 625 line video + standards, 263-286 for 525 line standards) */ + __u16 service_lines[2][24]; + enum v4l2_buf_type type; + __u32 reserved[3]; /* must be 0 */ +}; + +struct v4l2_sliced_vbi_data { + __u32 id; + __u32 field; /* 0: first field, 1: second field */ + __u32 line; /* 1-23 */ + __u32 reserved; /* must be 0 */ + __u8 data[48]; +}; + +/* + * Sliced VBI data inserted into MPEG Streams + */ + +/* + * V4L2_MPEG_STREAM_VBI_FMT_IVTV: + * + * Structure of payload contained in an MPEG 2 Private Stream 1 PES Packet in an + * MPEG-2 Program Pack that contains V4L2_MPEG_STREAM_VBI_FMT_IVTV Sliced VBI + * data + * + * Note, the MPEG-2 Program Pack and Private Stream 1 PES packet header + * definitions are not included here. See the MPEG-2 specifications for details + * on these headers. + */ + +/* Line type IDs */ +#define V4L2_MPEG_VBI_IVTV_TELETEXT_B (1) +#define V4L2_MPEG_VBI_IVTV_CAPTION_525 (4) +#define V4L2_MPEG_VBI_IVTV_WSS_625 (5) +#define V4L2_MPEG_VBI_IVTV_VPS (7) + +struct v4l2_mpeg_vbi_itv0_line { + __u8 id; /* One of V4L2_MPEG_VBI_IVTV_* above */ + __u8 data[42]; /* Sliced VBI data for the line */ +} __attribute__ ((packed)); + +struct v4l2_mpeg_vbi_itv0 { + __le32 linemask[2]; /* Bitmasks of VBI service lines present */ + struct v4l2_mpeg_vbi_itv0_line line[35]; +} __attribute__ ((packed)); + +struct v4l2_mpeg_vbi_ITV0 { + struct v4l2_mpeg_vbi_itv0_line line[36]; +} __attribute__ ((packed)); + +#define V4L2_MPEG_VBI_IVTV_MAGIC0 "itv0" +#define V4L2_MPEG_VBI_IVTV_MAGIC1 "ITV0" + +struct v4l2_mpeg_vbi_fmt_ivtv { + __u8 magic[4]; + union { + struct v4l2_mpeg_vbi_itv0 itv0; + struct v4l2_mpeg_vbi_ITV0 ITV0; + }; +} __attribute__ ((packed)); + +/* + * A G G R E G A T E S T R U C T U R E S + */ + +/** + * struct v4l2_plane_pix_format - additional, per-plane format definition + * @sizeimage: maximum size in bytes required for data, for which + * this plane will be used + * @bytesperline: distance in bytes between the leftmost pixels in two + * adjacent lines + */ +struct v4l2_plane_pix_format { + __u32 sizeimage; + __u16 bytesperline; + __u16 reserved[7]; +} __attribute__ ((packed)); + +/** + * struct v4l2_pix_format_mplane - multiplanar format definition + * @width: image width in pixels + * @height: image height in pixels + * @pixelformat: little endian four character code (fourcc) + * @field: field order (for interlaced video) + * @colorspace: supplemental to pixelformat + * @plane_fmt: per-plane information + * @num_planes: number of planes for this format + */ +struct v4l2_pix_format_mplane { + __u32 width; + __u32 height; + __u32 pixelformat; + enum v4l2_field field; + enum v4l2_colorspace colorspace; + + struct v4l2_plane_pix_format plane_fmt[VIDEO_MAX_PLANES]; + __u8 num_planes; + __u8 reserved[11]; +} __attribute__ ((packed)); + +/** + * struct v4l2_format - stream data format + * @type: type of the data stream + * @pix: definition of an image format + * @pix_mp: definition of a multiplanar image format + * @win: definition of an overlaid image + * @vbi: raw VBI capture or output parameters + * @sliced: sliced VBI capture or output parameters + * @raw_data: placeholder for future extensions and custom formats + */ +struct v4l2_format { + enum v4l2_buf_type type; + union { + struct v4l2_pix_format pix; /* V4L2_BUF_TYPE_VIDEO_CAPTURE */ + struct v4l2_pix_format_mplane pix_mp; /* V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE */ + struct v4l2_window win; /* V4L2_BUF_TYPE_VIDEO_OVERLAY */ + struct v4l2_vbi_format vbi; /* V4L2_BUF_TYPE_VBI_CAPTURE */ + struct v4l2_sliced_vbi_format sliced; /* V4L2_BUF_TYPE_SLICED_VBI_CAPTURE */ + __u8 raw_data[200]; /* user-defined */ + } fmt; +}; + +/* Stream type-dependent parameters + */ +struct v4l2_streamparm { + enum v4l2_buf_type type; + union { + struct v4l2_captureparm capture; + struct v4l2_outputparm output; + __u8 raw_data[200]; /* user-defined */ + } parm; +}; + +/* + * E V E N T S + */ + +#define V4L2_EVENT_ALL 0 +#define V4L2_EVENT_VSYNC 1 +#define V4L2_EVENT_EOS 2 +#define V4L2_EVENT_PRIVATE_START 0x08000000 + +/* Payload for V4L2_EVENT_VSYNC */ +struct v4l2_event_vsync { + /* Can be V4L2_FIELD_ANY, _NONE, _TOP or _BOTTOM */ + __u8 field; +} __attribute__ ((packed)); + +struct v4l2_event { + __u32 type; + union { + struct v4l2_event_vsync vsync; + __u8 data[64]; + } u; + __u32 pending; + __u32 sequence; + struct timespec timestamp; + __u32 reserved[9]; +}; + +struct v4l2_event_subscription { + __u32 type; + __u32 reserved[7]; +}; + +/* + * A D V A N C E D D E B U G G I N G + * + * NOTE: EXPERIMENTAL API, NEVER RELY ON THIS IN APPLICATIONS! + * FOR DEBUGGING, TESTING AND INTERNAL USE ONLY! + */ + +/* VIDIOC_DBG_G_REGISTER and VIDIOC_DBG_S_REGISTER */ + +#define V4L2_CHIP_MATCH_HOST 0 /* Match against chip ID on host (0 for the host) */ +#define V4L2_CHIP_MATCH_I2C_DRIVER 1 /* Match against I2C driver name */ +#define V4L2_CHIP_MATCH_I2C_ADDR 2 /* Match against I2C 7-bit address */ +#define V4L2_CHIP_MATCH_AC97 3 /* Match against anciliary AC97 chip */ + +struct v4l2_dbg_match { + __u32 type; /* Match type */ + union { /* Match this chip, meaning determined by type */ + __u32 addr; + char name[32]; + }; +} __attribute__ ((packed)); + +struct v4l2_dbg_register { + struct v4l2_dbg_match match; + __u32 size; /* register size in bytes */ + __u64 reg; + __u64 val; +} __attribute__ ((packed)); + +/* VIDIOC_DBG_G_CHIP_IDENT */ +struct v4l2_dbg_chip_ident { + struct v4l2_dbg_match match; + __u32 ident; /* chip identifier as specified in */ + __u32 revision; /* chip revision, chip specific */ +} __attribute__ ((packed)); + +/* + * I O C T L C O D E S F O R V I D E O D E V I C E S + * + */ +#define VIDIOC_QUERYCAP _IOR('V', 0, struct v4l2_capability) +#define VIDIOC_RESERVED _IO('V', 1) +#define VIDIOC_ENUM_FMT _IOWR('V', 2, struct v4l2_fmtdesc) +#define VIDIOC_G_FMT _IOWR('V', 4, struct v4l2_format) +#define VIDIOC_S_FMT _IOWR('V', 5, struct v4l2_format) +#define VIDIOC_REQBUFS _IOWR('V', 8, struct v4l2_requestbuffers) +#define VIDIOC_QUERYBUF _IOWR('V', 9, struct v4l2_buffer) +#define VIDIOC_G_FBUF _IOR('V', 10, struct v4l2_framebuffer) +#define VIDIOC_S_FBUF _IOW('V', 11, struct v4l2_framebuffer) +#define VIDIOC_OVERLAY _IOW('V', 14, int) +#define VIDIOC_QBUF _IOWR('V', 15, struct v4l2_buffer) +#define VIDIOC_DQBUF _IOWR('V', 17, struct v4l2_buffer) +#define VIDIOC_STREAMON _IOW('V', 18, int) +#define VIDIOC_STREAMOFF _IOW('V', 19, int) +#define VIDIOC_G_PARM _IOWR('V', 21, struct v4l2_streamparm) +#define VIDIOC_S_PARM _IOWR('V', 22, struct v4l2_streamparm) +#define VIDIOC_G_STD _IOR('V', 23, v4l2_std_id) +#define VIDIOC_S_STD _IOW('V', 24, v4l2_std_id) +#define VIDIOC_ENUMSTD _IOWR('V', 25, struct v4l2_standard) +#define VIDIOC_ENUMINPUT _IOWR('V', 26, struct v4l2_input) +#define VIDIOC_G_CTRL _IOWR('V', 27, struct v4l2_control) +#define VIDIOC_S_CTRL _IOWR('V', 28, struct v4l2_control) +#define VIDIOC_G_TUNER _IOWR('V', 29, struct v4l2_tuner) +#define VIDIOC_S_TUNER _IOW('V', 30, struct v4l2_tuner) +#define VIDIOC_G_AUDIO _IOR('V', 33, struct v4l2_audio) +#define VIDIOC_S_AUDIO _IOW('V', 34, struct v4l2_audio) +#define VIDIOC_QUERYCTRL _IOWR('V', 36, struct v4l2_queryctrl) +#define VIDIOC_QUERYMENU _IOWR('V', 37, struct v4l2_querymenu) +#define VIDIOC_G_INPUT _IOR('V', 38, int) +#define VIDIOC_S_INPUT _IOWR('V', 39, int) +#define VIDIOC_G_OUTPUT _IOR('V', 46, int) +#define VIDIOC_S_OUTPUT _IOWR('V', 47, int) +#define VIDIOC_ENUMOUTPUT _IOWR('V', 48, struct v4l2_output) +#define VIDIOC_G_AUDOUT _IOR('V', 49, struct v4l2_audioout) +#define VIDIOC_S_AUDOUT _IOW('V', 50, struct v4l2_audioout) +#define VIDIOC_G_MODULATOR _IOWR('V', 54, struct v4l2_modulator) +#define VIDIOC_S_MODULATOR _IOW('V', 55, struct v4l2_modulator) +#define VIDIOC_G_FREQUENCY _IOWR('V', 56, struct v4l2_frequency) +#define VIDIOC_S_FREQUENCY _IOW('V', 57, struct v4l2_frequency) +#define VIDIOC_CROPCAP _IOWR('V', 58, struct v4l2_cropcap) +#define VIDIOC_G_CROP _IOWR('V', 59, struct v4l2_crop) +#define VIDIOC_S_CROP _IOW('V', 60, struct v4l2_crop) +#define VIDIOC_G_JPEGCOMP _IOR('V', 61, struct v4l2_jpegcompression) +#define VIDIOC_S_JPEGCOMP _IOW('V', 62, struct v4l2_jpegcompression) +#define VIDIOC_QUERYSTD _IOR('V', 63, v4l2_std_id) +#define VIDIOC_TRY_FMT _IOWR('V', 64, struct v4l2_format) +#define VIDIOC_ENUMAUDIO _IOWR('V', 65, struct v4l2_audio) +#define VIDIOC_ENUMAUDOUT _IOWR('V', 66, struct v4l2_audioout) +#define VIDIOC_G_PRIORITY _IOR('V', 67, enum v4l2_priority) +#define VIDIOC_S_PRIORITY _IOW('V', 68, enum v4l2_priority) +#define VIDIOC_G_SLICED_VBI_CAP _IOWR('V', 69, struct v4l2_sliced_vbi_cap) +#define VIDIOC_LOG_STATUS _IO('V', 70) +#define VIDIOC_G_EXT_CTRLS _IOWR('V', 71, struct v4l2_ext_controls) +#define VIDIOC_S_EXT_CTRLS _IOWR('V', 72, struct v4l2_ext_controls) +#define VIDIOC_TRY_EXT_CTRLS _IOWR('V', 73, struct v4l2_ext_controls) +#if 1 +#define VIDIOC_ENUM_FRAMESIZES _IOWR('V', 74, struct v4l2_frmsizeenum) +#define VIDIOC_ENUM_FRAMEINTERVALS _IOWR('V', 75, struct v4l2_frmivalenum) +#define VIDIOC_G_ENC_INDEX _IOR('V', 76, struct v4l2_enc_idx) +#define VIDIOC_ENCODER_CMD _IOWR('V', 77, struct v4l2_encoder_cmd) +#define VIDIOC_TRY_ENCODER_CMD _IOWR('V', 78, struct v4l2_encoder_cmd) +#endif + +#if 1 +/* Experimental, meant for debugging, testing and internal use. + Only implemented if CONFIG_VIDEO_ADV_DEBUG is defined. + You must be root to use these ioctls. Never use these in applications! */ +#define VIDIOC_DBG_S_REGISTER _IOW('V', 79, struct v4l2_dbg_register) +#define VIDIOC_DBG_G_REGISTER _IOWR('V', 80, struct v4l2_dbg_register) + +/* Experimental, meant for debugging, testing and internal use. + Never use this ioctl in applications! */ +#define VIDIOC_DBG_G_CHIP_IDENT _IOWR('V', 81, struct v4l2_dbg_chip_ident) +#endif + +#define VIDIOC_S_HW_FREQ_SEEK _IOW('V', 82, struct v4l2_hw_freq_seek) +#define VIDIOC_ENUM_DV_PRESETS _IOWR('V', 83, struct v4l2_dv_enum_preset) +#define VIDIOC_S_DV_PRESET _IOWR('V', 84, struct v4l2_dv_preset) +#define VIDIOC_G_DV_PRESET _IOWR('V', 85, struct v4l2_dv_preset) +#define VIDIOC_QUERY_DV_PRESET _IOR('V', 86, struct v4l2_dv_preset) +#define VIDIOC_S_DV_TIMINGS _IOWR('V', 87, struct v4l2_dv_timings) +#define VIDIOC_G_DV_TIMINGS _IOWR('V', 88, struct v4l2_dv_timings) +#define VIDIOC_DQEVENT _IOR('V', 89, struct v4l2_event) +#define VIDIOC_SUBSCRIBE_EVENT _IOW('V', 90, struct v4l2_event_subscription) +#define VIDIOC_UNSUBSCRIBE_EVENT _IOW('V', 91, struct v4l2_event_subscription) + +/* Reminder: when adding new ioctls please add support for them to + drivers/media/video/v4l2-compat-ioctl32.c as well! */ + +#define BASE_VIDIOC_PRIVATE 192 /* 192-255 are private */ + +#endif /* __LINUX_VIDEODEV2_H */ diff --git a/exynos5/hal/include/videodev2_samsung.h b/exynos5/hal/include/videodev2_samsung.h new file mode 100644 index 0000000..f93688c --- /dev/null +++ b/exynos5/hal/include/videodev2_samsung.h @@ -0,0 +1,1060 @@ +/* + * Video for Linux Two header file for samsung + * + * Copyright (C) 2009, Dongsoo Nathaniel Kim + * + * This header file contains several v4l2 APIs to be proposed to v4l2 + * community and until bein accepted, will be used restrictly in Samsung's + * camera interface driver FIMC. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Alternatively, Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __LINUX_VIDEODEV2_SAMSUNG_H +#define __LINUX_VIDEODEV2_SAMSUNG_H + +/* Values for 'capabilities' field */ +/* Object detection device */ +#define V4L2_CAP_OBJ_RECOGNITION 0x10000000 +/* strobe control */ +#define V4L2_CAP_STROBE 0x20000000 + +#define V4L2_CID_FOCUS_MODE (V4L2_CID_CAMERA_CLASS_BASE+17) +/* Focus Methods */ +enum v4l2_focus_mode { + V4L2_FOCUS_MODE_AUTO = 0, + V4L2_FOCUS_MODE_MACRO = 1, + V4L2_FOCUS_MODE_MANUAL = 2, + V4L2_FOCUS_MODE_LASTP = 2, +}; + +#define V4L2_CID_ZOOM_MODE (V4L2_CID_CAMERA_CLASS_BASE+18) +/* Zoom Methods */ +enum v4l2_zoom_mode { + V4L2_ZOOM_MODE_CONTINUOUS = 0, + V4L2_ZOOM_MODE_OPTICAL = 1, + V4L2_ZOOM_MODE_DIGITAL = 2, + V4L2_ZOOM_MODE_LASTP = 2, +}; + +/* Exposure Methods */ +#define V4L2_CID_PHOTOMETRY (V4L2_CID_CAMERA_CLASS_BASE+19) +enum v4l2_photometry_mode { + V4L2_PHOTOMETRY_MULTISEG = 0, /*Multi Segment*/ + V4L2_PHOTOMETRY_CWA = 1, /*Centre Weighted Average*/ + V4L2_PHOTOMETRY_SPOT = 2, + V4L2_PHOTOMETRY_AFSPOT = 3, /*Spot metering on focused point*/ + V4L2_PHOTOMETRY_LASTP = V4L2_PHOTOMETRY_AFSPOT, +}; + +/* Manual exposure control items menu type: iris, shutter, iso */ +#define V4L2_CID_CAM_APERTURE (V4L2_CID_CAMERA_CLASS_BASE+20) +#define V4L2_CID_CAM_SHUTTER (V4L2_CID_CAMERA_CLASS_BASE+21) +#define V4L2_CID_CAM_ISO (V4L2_CID_CAMERA_CLASS_BASE+22) + +/* Following CIDs are menu type */ +#define V4L2_CID_SCENEMODE (V4L2_CID_CAMERA_CLASS_BASE+23) +#define V4L2_CID_CAM_STABILIZE (V4L2_CID_CAMERA_CLASS_BASE+24) +#define V4L2_CID_CAM_MULTISHOT (V4L2_CID_CAMERA_CLASS_BASE+25) + +/* Control dynamic range */ +#define V4L2_CID_CAM_DR (V4L2_CID_CAMERA_CLASS_BASE+26) + +/* White balance preset control */ +#define V4L2_CID_WHITE_BALANCE_PRESET (V4L2_CID_CAMERA_CLASS_BASE+27) +#define V4L2_CID_CAM_SENSOR_FW_VER (V4L2_CID_CAMERA_CLASS_BASE + 28) +#define V4L2_CID_CAM_PHONE_FW_VER (V4L2_CID_CAMERA_CLASS_BASE + 29) + +/* CID extensions */ +#define V4L2_CID_ROTATION (V4L2_CID_PRIVATE_BASE + 0) +#define V4L2_CID_PADDR_Y (V4L2_CID_PRIVATE_BASE + 1) +#define V4L2_CID_PADDR_CB (V4L2_CID_PRIVATE_BASE + 2) +#define V4L2_CID_PADDR_CR (V4L2_CID_PRIVATE_BASE + 3) +#define V4L2_CID_PADDR_CBCR (V4L2_CID_PRIVATE_BASE + 4) +#define V4L2_CID_OVERLAY_AUTO (V4L2_CID_PRIVATE_BASE + 5) +#define V4L2_CID_OVERLAY_VADDR0 (V4L2_CID_PRIVATE_BASE + 6) +#define V4L2_CID_OVERLAY_VADDR1 (V4L2_CID_PRIVATE_BASE + 7) +#define V4L2_CID_OVERLAY_VADDR2 (V4L2_CID_PRIVATE_BASE + 8) +#define V4L2_CID_OVLY_MODE (V4L2_CID_PRIVATE_BASE + 9) +#define V4L2_CID_DST_INFO (V4L2_CID_PRIVATE_BASE + 10) +/* UMP secure id control */ +#define V4L2_CID_GET_UMP_SECURE_ID (V4L2_CID_PRIVATE_BASE + 11) +#define V4L2_CID_GET_PHY_SRC_YADDR (V4L2_CID_PRIVATE_BASE + 12) +#define V4L2_CID_GET_PHY_SRC_CADDR (V4L2_CID_PRIVATE_BASE + 13) +#define V4L2_CID_IMAGE_EFFECT_FN (V4L2_CID_PRIVATE_BASE + 16) +#define V4L2_CID_IMAGE_EFFECT_APPLY (V4L2_CID_PRIVATE_BASE + 17) +#define V4L2_CID_IMAGE_EFFECT_CB (V4L2_CID_PRIVATE_BASE + 18) +#define V4L2_CID_IMAGE_EFFECT_CR (V4L2_CID_PRIVATE_BASE + 19) +#define V4L2_CID_RESERVED_MEM_BASE_ADDR (V4L2_CID_PRIVATE_BASE + 20) +#define V4L2_CID_FIMC_VERSION (V4L2_CID_PRIVATE_BASE + 21) + +#define V4L2_CID_STREAM_PAUSE (V4L2_CID_PRIVATE_BASE + 53) + +/* CID Extensions for camera sensor operations */ +#define V4L2_CID_CAM_PREVIEW_ONOFF (V4L2_CID_PRIVATE_BASE + 64) +#define V4L2_CID_CAM_CAPTURE (V4L2_CID_PRIVATE_BASE + 65) +//#define V4L2_CID_CAM_JPEG_MEMSIZE (V4L2_CID_PRIVATE_BASE + 66) + +#define V4L2_CID_CAM_DATE_INFO_YEAR (V4L2_CID_PRIVATE_BASE + 14) +#define V4L2_CID_CAM_DATE_INFO_MONTH (V4L2_CID_PRIVATE_BASE + 15) +#define V4L2_CID_CAM_DATE_INFO_DATE (V4L2_CID_PRIVATE_BASE + 22) +#define V4L2_CID_CAM_SENSOR_VER (V4L2_CID_PRIVATE_BASE + 23) +#define V4L2_CID_CAM_FW_MINOR_VER (V4L2_CID_PRIVATE_BASE + 24) +#define V4L2_CID_CAM_FW_MAJOR_VER (V4L2_CID_PRIVATE_BASE + 25) +#define V4L2_CID_CAM_PRM_MINOR_VER (V4L2_CID_PRIVATE_BASE + 26) +#define V4L2_CID_CAM_PRM_MAJOR_VER (V4L2_CID_PRIVATE_BASE + 27) +#define V4L2_CID_CAM_FW_VER (V4L2_CID_PRIVATE_BASE + 28) +#define V4L2_CID_CAM_SET_FW_ADDR (V4L2_CID_PRIVATE_BASE + 29) +#define V4L2_CID_CAM_SET_FW_SIZE (V4L2_CID_PRIVATE_BASE + 30) +#define V4L2_CID_CAM_UPDATE_FW (V4L2_CID_PRIVATE_BASE + 31) +enum v4l2_firmware_mode { + FW_MODE_UPDATE, + FW_MODE_VERSION, + FW_MODE_DUMP, +}; + +#define V4L2_CID_CAM_JPEG_MAIN_SIZE (V4L2_CID_PRIVATE_BASE + 32) +#define V4L2_CID_CAM_JPEG_MAIN_OFFSET (V4L2_CID_PRIVATE_BASE + 33) +#define V4L2_CID_CAM_JPEG_THUMB_SIZE (V4L2_CID_PRIVATE_BASE + 34) +#define V4L2_CID_CAM_JPEG_THUMB_OFFSET (V4L2_CID_PRIVATE_BASE + 35) +#define V4L2_CID_CAM_JPEG_POSTVIEW_OFFSET (V4L2_CID_PRIVATE_BASE + 36) +#define V4L2_CID_CAM_JPEG_QUALITY (V4L2_CID_PRIVATE_BASE + 37) +#define V4L2_CID_CAM_SENSOR_MAKER (V4L2_CID_PRIVATE_BASE + 38) +#define V4L2_CID_CAM_SENSOR_OPTICAL (V4L2_CID_PRIVATE_BASE + 39) +#define V4L2_CID_CAM_AF_VER_LOW (V4L2_CID_PRIVATE_BASE + 40) +#define V4L2_CID_CAM_AF_VER_HIGH (V4L2_CID_PRIVATE_BASE + 41) +#define V4L2_CID_CAM_GAMMA_RG_LOW (V4L2_CID_PRIVATE_BASE + 42) +#define V4L2_CID_CAM_GAMMA_RG_HIGH (V4L2_CID_PRIVATE_BASE + 43) +#define V4L2_CID_CAM_GAMMA_BG_LOW (V4L2_CID_PRIVATE_BASE + 44) +#define V4L2_CID_CAM_GAMMA_BG_HIGH (V4L2_CID_PRIVATE_BASE + 45) +#define V4L2_CID_CAM_DUMP_FW (V4L2_CID_PRIVATE_BASE + 46) +#define V4L2_CID_CAM_GET_DUMP_SIZE (V4L2_CID_PRIVATE_BASE + 47) +#define V4L2_CID_CAMERA_VT_MODE (V4L2_CID_PRIVATE_BASE + 48) +#define V4L2_CID_CAMERA_VGA_BLUR (V4L2_CID_PRIVATE_BASE + 49) +#define V4L2_CID_CAMERA_CAPTURE (V4L2_CID_PRIVATE_BASE + 50) +#define V4L2_CID_CAMERA_HDR (V4L2_CID_PRIVATE_BASE + 51) + +#define V4L2_CID_MAIN_SW_DATE_INFO_YEAR (V4L2_CID_PRIVATE_BASE + 54) +#define V4L2_CID_MAIN_SW_DATE_INFO_MONTH (V4L2_CID_PRIVATE_BASE + 55) +#define V4L2_CID_MAIN_SW_DATE_INFO_DATE (V4L2_CID_PRIVATE_BASE + 56) +#define V4L2_CID_MAIN_SW_FW_MINOR_VER (V4L2_CID_PRIVATE_BASE + 57) +#define V4L2_CID_MAIN_SW_FW_MAJOR_VER (V4L2_CID_PRIVATE_BASE + 58) +#define V4L2_CID_MAIN_SW_PRM_MINOR_VER (V4L2_CID_PRIVATE_BASE + 59) +#define V4L2_CID_MAIN_SW_PRM_MAJOR_VER (V4L2_CID_PRIVATE_BASE + 60) + +#define V4L2_CID_FIMC_IS_BASE (V4L2_CTRL_CLASS_CAMERA | 0x1000) + +#define V4L2_CID_IS_LOAD_FW (V4L2_CID_FIMC_IS_BASE + 10) +#define V4L2_CID_IS_INIT_PARAM (V4L2_CID_FIMC_IS_BASE + 11) +#define V4L2_CID_IS_RESET (V4L2_CID_FIMC_IS_BASE + 12) +#define V4L2_CID_IS_S_POWER (V4L2_CID_FIMC_IS_BASE + 13) +enum is_set_power { + IS_POWER_OFF, + IS_POWER_ON +}; + +#define V4L2_CID_IS_S_STREAM (V4L2_CID_FIMC_IS_BASE + 14) +enum is_set_stream { + IS_DISABLE_STREAM, + IS_ENABLE_STREAM +}; + +#define V4L2_CID_IS_S_SCENARIO_MODE (V4L2_CID_FIMC_IS_BASE + 15) +#define V4L2_CID_IS_S_FORMAT_SCENARIO (V4L2_CID_FIMC_IS_BASE + 16) +enum scenario_mode { + IS_MODE_PREVIEW_STILL, + IS_MODE_PREVIEW_VIDEO, + IS_MODE_CAPTURE_STILL, + IS_MODE_CAPTURE_VIDEO, + IS_MODE_MAX +}; + +/* global */ +#define V4L2_CID_IS_CAMERA_SHOT_MODE_NORMAL (V4L2_CID_FIMC_IS_BASE + 101) +/* value : 1 : single shot , >=2 : continuous shot */ + +#define V4L2_CID_IS_CAMERA_SENSOR_NUM (V4L2_CID_FIMC_IS_BASE + 201) +#define V4L2_CID_IS_CAMERA_FOCUS_MODE (V4L2_CID_FIMC_IS_BASE + 401) +enum is_focus_mode { + IS_FOCUS_MODE_AUTO, + IS_FOCUS_MODE_MACRO, + IS_FOCUS_MODE_INFINITY, + IS_FOCUS_MODE_CONTINUOUS, + IS_FOCUS_MODE_TOUCH, + IS_FOCUS_MODE_FACEDETECT, + IS_FOCUS_MODE_MAX, +}; + +#define V4L2_CID_IS_CAMERA_FLASH_MODE (V4L2_CID_FIMC_IS_BASE + 402) +enum is_flash_mode { + IS_FLASH_MODE_OFF, + IS_FLASH_MODE_AUTO, + IS_FLASH_MODE_AUTO_REDEYE, + IS_FLASH_MODE_ON, + IS_FLASH_MODE_TORCH, + IS_FLASH_MODE_MAX +}; + +#define V4L2_CID_IS_CAMERA_AWB_MODE (V4L2_CID_FIMC_IS_BASE + 403) +enum is_awb_mode { + IS_AWB_AUTO, + IS_AWB_DAYLIGHT, + IS_AWB_CLOUDY, + IS_AWB_TUNGSTEN, + IS_AWB_FLUORESCENT, + IS_AWB_MAX +}; + +#define V4L2_CID_IS_CAMERA_IMAGE_EFFECT (V4L2_CID_FIMC_IS_BASE + 404) +enum is_image_effect { + IS_IMAGE_EFFECT_DISABLE, + IS_IMAGE_EFFECT_MONOCHROME, + IS_IMAGE_EFFECT_NEGATIVE_MONO, + IS_IMAGE_EFFECT_NEGATIVE_COLOR, + IS_IMAGE_EFFECT_SEPIA, + IS_IMAGE_EFFECT_SEPIA_CB, + IS_IMAGE_EFFECT_SEPIA_CR, + IS_IMAGE_EFFECT_NEGATIVE, + IS_IMAGE_EFFECT_ARTFREEZE, + IS_IMAGE_EFFECT_EMBOSSING, + IS_IMAGE_EFFECT_SILHOUETTE, + IS_IMAGE_EFFECT_MAX +}; + +#define V4L2_CID_IS_CAMERA_ISO (V4L2_CID_FIMC_IS_BASE + 405) +enum is_iso { + IS_ISO_AUTO, + IS_ISO_50, + IS_ISO_100, + IS_ISO_200, + IS_ISO_400, + IS_ISO_800, + IS_ISO_1600, + IS_ISO_MAX +}; + +#define V4L2_CID_IS_CAMERA_CONTRAST (V4L2_CID_FIMC_IS_BASE + 406) +enum is_contrast { + IS_CONTRAST_AUTO, + IS_CONTRAST_MINUS_2, + IS_CONTRAST_MINUS_1, + IS_CONTRAST_DEFAULT, + IS_CONTRAST_PLUS_1, + IS_CONTRAST_PLUS_2, + IS_CONTRAST_MAX +}; + +#define V4L2_CID_IS_CAMERA_SATURATION (V4L2_CID_FIMC_IS_BASE + 407) +enum is_saturation { + IS_SATURATION_MINUS_2, + IS_SATURATION_MINUS_1, + IS_SATURATION_DEFAULT, + IS_SATURATION_PLUS1, + IS_SATURATION_PLUS2, + IS_SATURATION_MAX +}; + +#define V4L2_CID_IS_CAMERA_SHARPNESS (V4L2_CID_FIMC_IS_BASE + 408) +enum is_sharpness { + IS_SHARPNESS_MINUS_2, + IS_SHARPNESS_MINUS_1, + IS_SHARPNESS_DEFAULT, + IS_SHARPNESS_PLUS1, + IS_SHARPNESS_PLUS2, + IS_SHARPNESS_MAX +}; + +#define V4L2_CID_IS_CAMERA_EXPOSURE (V4L2_CID_FIMC_IS_BASE + 409) +enum is_exposure { + IS_EXPOSURE_MINUS_2, + IS_EXPOSURE_MINUS_1, + IS_EXPOSURE_DEFAULT, + IS_EXPOSURE_PLUS1, + IS_EXPOSURE_PLUS2, + IS_EXPOSURE_MAX +}; + +#define V4L2_CID_IS_CAMERA_BRIGHTNESS (V4L2_CID_FIMC_IS_BASE + 410) +enum is_brightness { + IS_BRIGHTNESS_MINUS_2, + IS_BRIGHTNESS_MINUS_1, + IS_BRIGHTNESS_DEFAULT, + IS_BRIGHTNESS_PLUS1, + IS_BRIGHTNESS_PLUS2, + IS_BRIGHTNESS_MAX +}; + +#define V4L2_CID_IS_CAMERA_HUE (V4L2_CID_FIMC_IS_BASE + 411) +enum is_hue { + IS_HUE_MINUS_2, + IS_HUE_MINUS_1, + IS_HUE_DEFAULT, + IS_HUE_PLUS1, + IS_HUE_PLUS2, + IS_HUE_MAX +}; + +#define V4L2_CID_IS_CAMERA_METERING (V4L2_CID_FIMC_IS_BASE + 412) +enum is_metering { + IS_METERING_AVERAGE, + IS_METERING_SPOT, + IS_METERING_MATRIX, + IS_METERING_MAX +}; +#define V4L2_CID_IS_CAMERA_METERING_POSITION_X (V4L2_CID_FIMC_IS_BASE + 500) +#define V4L2_CID_IS_CAMERA_METERING_POSITION_Y (V4L2_CID_FIMC_IS_BASE + 501) +#define V4L2_CID_IS_CAMERA_METERING_WINDOW_X (V4L2_CID_FIMC_IS_BASE + 502) +#define V4L2_CID_IS_CAMERA_METERING_WINDOW_Y (V4L2_CID_FIMC_IS_BASE + 503) + +#define V4L2_CID_IS_CAMERA_AFC_MODE (V4L2_CID_FIMC_IS_BASE + 413) +enum is_afc_mode { + IS_AFC_DISABLE, + IS_AFC_AUTO, + IS_AFC_MANUAL_50HZ, + IS_AFC_MANUAL_60HZ, + IS_AFC_MAX +}; + +#define V4L2_CID_IS_FD_NUM_FACE (V4L2_CID_FIMC_IS_BASE + 414) +/* value : maximum number of face */ + +#define V4L2_CID_IS_FD_GET_FACE_COUNT (V4L2_CID_FIMC_IS_BASE + 416) +#define V4L2_CID_IS_FD_GET_FACE_FRAME_NUMBER (V4L2_CID_FIMC_IS_BASE + 417) +#define V4L2_CID_IS_FD_GET_FACE_CONFIDENCE (V4L2_CID_FIMC_IS_BASE + 418) +#define V4L2_CID_IS_FD_GET_FACE_SMILELEVEL (V4L2_CID_FIMC_IS_BASE + 419) +#define V4L2_CID_IS_FD_GET_FACE_BLINKLEVEL (V4L2_CID_FIMC_IS_BASE + 420) +#define V4L2_CID_IS_FD_GET_FACE_OFFSET_X (V4L2_CID_FIMC_IS_BASE + 421) +#define V4L2_CID_IS_FD_GET_FACE_OFFSET_Y (V4L2_CID_FIMC_IS_BASE + 422) +#define V4L2_CID_IS_FD_GET_FACE_SIZE_X (V4L2_CID_FIMC_IS_BASE + 423) +#define V4L2_CID_IS_FD_GET_FACE_SIZE_Y (V4L2_CID_FIMC_IS_BASE + 424) +#define V4L2_CID_IS_FD_GET_LEFT_EYE_OFFSET_X (V4L2_CID_FIMC_IS_BASE + 425) +#define V4L2_CID_IS_FD_GET_LEFT_EYE_OFFSET_Y (V4L2_CID_FIMC_IS_BASE + 426) +#define V4L2_CID_IS_FD_GET_LEFT_EYE_SIZE_X (V4L2_CID_FIMC_IS_BASE + 427) +#define V4L2_CID_IS_FD_GET_LEFT_EYE_SIZE_Y (V4L2_CID_FIMC_IS_BASE + 428) +#define V4L2_CID_IS_FD_GET_RIGHT_EYE_OFFSET_X (V4L2_CID_FIMC_IS_BASE + 429) +#define V4L2_CID_IS_FD_GET_RIGHT_EYE_OFFSET_Y (V4L2_CID_FIMC_IS_BASE + 430) +#define V4L2_CID_IS_FD_GET_RIGHT_EYE_SIZE_X (V4L2_CID_FIMC_IS_BASE + 431) +#define V4L2_CID_IS_FD_GET_RIGHT_EYE_SIZE_Y (V4L2_CID_FIMC_IS_BASE + 432) +#define V4L2_CID_IS_FD_GET_MOUTH_OFFSET_X (V4L2_CID_FIMC_IS_BASE + 433) +#define V4L2_CID_IS_FD_GET_MOUTH_OFFSET_Y (V4L2_CID_FIMC_IS_BASE + 434) +#define V4L2_CID_IS_FD_GET_MOUTH_SIZE_X (V4L2_CID_FIMC_IS_BASE + 435) +#define V4L2_CID_IS_FD_GET_MOUTH_SIZE_Y (V4L2_CID_FIMC_IS_BASE + 436) +#define V4L2_CID_IS_FD_GET_ANGLE (V4L2_CID_FIMC_IS_BASE + 437) +#define V4L2_CID_IS_FD_SET_ORIENTATION (V4L2_CID_FIMC_IS_BASE + 438) +#define V4L2_CID_IS_FD_SET_DATA_ADDRESS (V4L2_CID_FIMC_IS_BASE + 439) +#define V4L2_CID_IS_FD_GET_DATA (V4L2_CID_FIMC_IS_BASE + 500) +#define V4L2_CID_IS_FD_SET_YAW_ANGLE (V4L2_CID_FIMC_IS_BASE + 501) +#define V4L2_CID_IS_FD_SET_ROLL_ANGLE (V4L2_CID_FIMC_IS_BASE + 502) + +#define V4L2_CID_IS_SET_ISP (V4L2_CID_FIMC_IS_BASE + 440) +enum is_isp_bypass_mode { + IS_ISP_BYPASS_DISABLE, + IS_ISP_BYPASS_ENABLE, + IS_ISP_BYPASS_MAX +}; + +#define V4L2_CID_IS_SET_DRC (V4L2_CID_FIMC_IS_BASE + 441) +enum is_drc_bypass_mode { + IS_DRC_BYPASS_DISABLE, + IS_DRC_BYPASS_ENABLE, + IS_DRC_BYPASS_MAX +}; + +#define V4L2_CID_IS_SET_FD (V4L2_CID_FIMC_IS_BASE + 442) +enum is_fd_bypass_mode { + IS_FD_BYPASS_DISABLE, + IS_FD_BYPASS_ENABLE, + IS_FD_BYPASS_MAX +}; + +#define V4L2_CID_IS_SET_ODC (V4L2_CID_FIMC_IS_BASE + 443) +enum is_odc_bypass_mode { + IS_ODC_BYPASS_DISABLE, + IS_ODC_BYPASS_ENABLE, + IS_ODC_BYPASS_MAX +}; + +#define V4L2_CID_IS_SET_DIS (V4L2_CID_FIMC_IS_BASE + 444) +enum is_dis_bypass_mode { + IS_DIS_BYPASS_DISABLE, + IS_DIS_BYPASS_ENABLE, + IS_DIS_BYPASS_MAX +}; + +#define V4L2_CID_IS_SET_3DNR (V4L2_CID_FIMC_IS_BASE + 445) +enum is_tdnr_bypass_mode { + IS_TDNR_BYPASS_DISABLE, + IS_TDNR_BYPASS_ENABLE, + IS_TDNR_BYPASS_MAX +}; + +#define V4L2_CID_IS_SET_SCALERC (V4L2_CID_FIMC_IS_BASE + 446) +enum is_scalerc_bypass_mode { + IS_SCALERC_BYPASS_DISABLE, + IS_SCALERC_BYPASS_ENABLE, + IS_SCALERC_BYPASS_MAX +}; + +#define V4L2_CID_IS_SET_SCALERP (V4L2_CID_FIMC_IS_BASE + 446) +enum is_scalerp_bypass_mode { + IS_SCALERP_BYPASS_DISABLE, + IS_SCALERP_BYPASS_ENABLE, + IS_SCALERP_BYPASS_MAX +}; + +#define V4L2_CID_IS_ROTATION_MODE (V4L2_CID_FIMC_IS_BASE + 450) +enum is_rotation_mode { + IS_ROTATION_0, + IS_ROTATION_90, + IS_ROTATION_180, + IS_ROTATION_270, + IS_ROTATION_MAX +}; + +#define V4L2_CID_IS_3DNR_1ST_FRAME_MODE (V4L2_CID_FIMC_IS_BASE + 451) +enum is_tdnr_1st_frame_mode { + IS_TDNR_1ST_FRAME_NOPROCESSING, + IS_TDNR_1ST_FRAME_2DNR, + IS_TDNR_MAX +}; + +#define V4L2_CID_IS_CAMERA_OBJECT_POSITION_X (V4L2_CID_FIMC_IS_BASE + 452) +#define V4L2_CID_IS_CAMERA_OBJECT_POSITION_Y (V4L2_CID_FIMC_IS_BASE + 453) +#define V4L2_CID_IS_CAMERA_WINDOW_SIZE_X (V4L2_CID_FIMC_IS_BASE + 454) +#define V4L2_CID_IS_CAMERA_WINDOW_SIZE_Y (V4L2_CID_FIMC_IS_BASE + 455) + +#define V4L2_CID_IS_CAMERA_EXIF_EXPTIME (V4L2_CID_FIMC_IS_BASE + 456) +#define V4L2_CID_IS_CAMERA_EXIF_FLASH (V4L2_CID_FIMC_IS_BASE + 457) +#define V4L2_CID_IS_CAMERA_EXIF_ISO (V4L2_CID_FIMC_IS_BASE + 458) +#define V4L2_CID_IS_CAMERA_EXIF_SHUTTERSPEED (V4L2_CID_FIMC_IS_BASE + 459) +#define V4L2_CID_IS_CAMERA_EXIF_BRIGHTNESS (V4L2_CID_FIMC_IS_BASE + 460) + +#define V4L2_CID_IS_CAMERA_ISP_SEL_INPUT (V4L2_CID_FIMC_IS_BASE + 461) +enum is_isp_sel_input { + IS_ISP_INPUT_OTF, + IS_ISP_INPUT_DMA1, + IS_ISP_INPUT_DMA2, + IS_ISP_INPUT_DMA12, + IS_ISP_INPUT_MAX +}; + +#define V4L2_CID_IS_CAMERA_ISP_SEL_OUTPUT (V4L2_CID_FIMC_IS_BASE + 462) +enum is_isp_sel_output { + IS_ISP_OUTPUT_OTF, + IS_ISP_OUTPUT_DMA1, + IS_ISP_OUTPUT_DMA2, + IS_ISP_OUTPUT_DMA12, + IS_ISP_OUTPUT_OTF_DMA1, + IS_ISP_OUTPUT_OTF_DMA2, + IS_ISP_OUTPUT_OTF_DMA12, + IS_ISP_OUTPUT_MAX +}; + +#define V4L2_CID_IS_CAMERA_DRC_SEL_INPUT (V4L2_CID_FIMC_IS_BASE + 463) +enum is_drc_sel_input { + IS_DRC_INPUT_OTF, + IS_DRC_INPUT_DMA, + IS_DRC_INPUT_MAX +}; + +#define V4L2_CID_IS_CAMERA_FD_SEL_INPUT (V4L2_CID_FIMC_IS_BASE + 464) +enum is_fd_sel_input { + IS_FD_INPUT_OTF, + IS_FD_INPUT_DMA, + IS_FD_INPUT_MAX +}; + +#define V4L2_CID_IS_CAMERA_INIT_WIDTH (V4L2_CID_FIMC_IS_BASE + 465) +#define V4L2_CID_IS_CAMERA_INIT_HEIGHT (V4L2_CID_FIMC_IS_BASE + 466) + +#define V4L2_CID_IS_CMD_ISP (V4L2_CID_FIMC_IS_BASE + 467) +enum is_isp_cmd_mode { + IS_ISP_COMMAND_STOP, + IS_ISP_COMMAND_START, + IS_ISP_COMMAND_MAX +}; + +#define V4L2_CID_IS_CMD_DRC (V4L2_CID_FIMC_IS_BASE + 468) +enum is_drc_cmd_mode { + IS_DRC_COMMAND_STOP, + IS_DRC_COMMAND_START, + IS_DRC_COMMAND_MAX +}; + +#define V4L2_CID_IS_CMD_FD (V4L2_CID_FIMC_IS_BASE + 469) +enum is_fd_cmd_mode { + IS_FD_COMMAND_STOP, + IS_FD_COMMAND_START, + IS_FD_COMMAND_MAX +}; + +#define V4L2_CID_IS_CMD_ODC (V4L2_CID_FIMC_IS_BASE + 470) +enum is_odc_cmd_mode { + IS_ODC_COMMAND_STOP, + IS_ODC_COMMAND_START, + IS_ODC_COMMAND_MAX +}; + +#define V4L2_CID_IS_CMD_DIS (V4L2_CID_FIMC_IS_BASE + 471) +enum is_dis_cmd_mode { + IS_DIS_COMMAND_STOP, + IS_DIS_COMMAND_START, + IS_DIS_COMMAND_MAX +}; + +#define V4L2_CID_IS_CMD_TDNR (V4L2_CID_FIMC_IS_BASE + 472) +enum is_tdnr_cmd_mode { + IS_TDNR_COMMAND_STOP, + IS_TDNR_COMMAND_START, + IS_TDNR_COMMAND_MAX +}; + +#define V4L2_CID_IS_CMD_SCALERC (V4L2_CID_FIMC_IS_BASE + 473) +enum is_scalerc_cmd_mode { + IS_SCALERC_COMMAND_STOP, + IS_SCALERC_COMMAND_START, + IS_SCALERC_COMMAND_MAX +}; + +#define V4L2_CID_IS_CMD_SCALERP (V4L2_CID_FIMC_IS_BASE + 474) +enum is_scalerp_cmd_mode { + IS_SCALERP_COMMAND_STOP, + IS_SCALERP_COMMAND_START, + IS_SCALERP_COMMAND_MAX +}; + +#define V4L2_CID_IS_GET_SENSOR_OFFSET_X (V4L2_CID_FIMC_IS_BASE + 480) +#define V4L2_CID_IS_GET_SENSOR_OFFSET_Y (V4L2_CID_FIMC_IS_BASE + 481) +#define V4L2_CID_IS_GET_SENSOR_WIDTH (V4L2_CID_FIMC_IS_BASE + 482) +#define V4L2_CID_IS_GET_SENSOR_HEIGHT (V4L2_CID_FIMC_IS_BASE + 483) + +#define V4L2_CID_IS_GET_FRAME_VALID (V4L2_CID_FIMC_IS_BASE + 484) +#define V4L2_CID_IS_SET_FRAME_VALID (V4L2_CID_FIMC_IS_BASE + 485) +#define V4L2_CID_IS_GET_FRAME_BADMARK (V4L2_CID_FIMC_IS_BASE + 486) +#define V4L2_CID_IS_SET_FRAME_BADMARK (V4L2_CID_FIMC_IS_BASE + 487) +#define V4L2_CID_IS_GET_FRAME_CAPTURED (V4L2_CID_FIMC_IS_BASE + 488) +#define V4L2_CID_IS_SET_FRAME_CAPTURED (V4L2_CID_FIMC_IS_BASE + 489) +#define V4L2_CID_IS_SET_FRAME_NUMBER (V4L2_CID_FIMC_IS_BASE + 490) +#define V4L2_CID_IS_GET_FRAME_NUMBER (V4L2_CID_FIMC_IS_BASE + 491) +#define V4L2_CID_IS_CLEAR_FRAME_NUMBER (V4L2_CID_FIMC_IS_BASE + 492) +#define V4L2_CID_IS_GET_LOSTED_FRAME_NUMBER (V4L2_CID_FIMC_IS_BASE + 493) +#define V4L2_CID_IS_ISP_DMA_BUFFER_NUM (V4L2_CID_FIMC_IS_BASE + 494) +#define V4L2_CID_IS_ISP_DMA_BUFFER_ADDRESS (V4L2_CID_FIMC_IS_BASE + 495) + +enum v4l2_blur { + BLUR_LEVEL_0 = 0, + BLUR_LEVEL_1, + BLUR_LEVEL_2, + BLUR_LEVEL_3, + BLUR_LEVEL_MAX, +}; + +#if 1 +#define V4L2_CID_CAMERA_SCENE_MODE (V4L2_CID_PRIVATE_BASE+70) +enum v4l2_scene_mode { + SCENE_MODE_BASE, + SCENE_MODE_NONE, + SCENE_MODE_PORTRAIT, + SCENE_MODE_NIGHTSHOT, + SCENE_MODE_BACK_LIGHT, + SCENE_MODE_LANDSCAPE, + SCENE_MODE_SPORTS, + SCENE_MODE_PARTY_INDOOR, + SCENE_MODE_BEACH_SNOW, + SCENE_MODE_SUNSET, + SCENE_MODE_DUSK_DAWN, + SCENE_MODE_FALL_COLOR, + SCENE_MODE_FIREWORKS, + SCENE_MODE_TEXT, + SCENE_MODE_CANDLE_LIGHT, + SCENE_MODE_MAX, +}; + +#define V4L2_CID_CAMERA_FLASH_MODE (V4L2_CID_PRIVATE_BASE+71) +enum v4l2_flash_mode { + FLASH_MODE_BASE, + FLASH_MODE_OFF, + FLASH_MODE_AUTO, + FLASH_MODE_ON, + FLASH_MODE_TORCH, + FLASH_MODE_MAX, +}; + +#define V4L2_CID_CAMERA_BRIGHTNESS (V4L2_CID_PRIVATE_BASE+72) +enum v4l2_ev_mode { + EV_MINUS_4 = -4, + EV_MINUS_3 = -3, + EV_MINUS_2 = -2, + EV_MINUS_1 = -1, + EV_DEFAULT = 0, + EV_PLUS_1 = 1, + EV_PLUS_2 = 2, + EV_PLUS_3 = 3, + EV_PLUS_4 = 4, + EV_MAX, +}; + +#define V4L2_CID_CAMERA_WHITE_BALANCE (V4L2_CID_PRIVATE_BASE+73) +enum v4l2_wb_mode { + WHITE_BALANCE_BASE = 0, + WHITE_BALANCE_AUTO, + WHITE_BALANCE_SUNNY, + WHITE_BALANCE_CLOUDY, + WHITE_BALANCE_TUNGSTEN, + WHITE_BALANCE_FLUORESCENT, + WHITE_BALANCE_MAX, +}; + +#define V4L2_CID_CAMERA_EFFECT (V4L2_CID_PRIVATE_BASE+74) +enum v4l2_effect_mode { + IMAGE_EFFECT_BASE = 0, + IMAGE_EFFECT_NONE, + IMAGE_EFFECT_BNW, + IMAGE_EFFECT_SEPIA, + IMAGE_EFFECT_AQUA, + IMAGE_EFFECT_ANTIQUE, + IMAGE_EFFECT_NEGATIVE, + IMAGE_EFFECT_SHARPEN, + IMAGE_EFFECT_MAX, +}; + +#define V4L2_CID_CAMERA_ISO (V4L2_CID_PRIVATE_BASE+75) +enum v4l2_iso_mode { + ISO_AUTO = 0, + ISO_50, + ISO_100, + ISO_200, + ISO_400, + ISO_800, + ISO_1600, + ISO_SPORTS, + ISO_NIGHT, + ISO_MOVIE, + ISO_MAX, +}; + +#define V4L2_CID_CAMERA_METERING (V4L2_CID_PRIVATE_BASE+76) +enum v4l2_metering_mode { + METERING_BASE = 0, + METERING_MATRIX, + METERING_CENTER, + METERING_SPOT, + METERING_MAX, +}; + +#define V4L2_CID_CAMERA_CONTRAST (V4L2_CID_PRIVATE_BASE+77) +enum v4l2_contrast_mode { + CONTRAST_MINUS_2 = 0, + CONTRAST_MINUS_1, + CONTRAST_DEFAULT, + CONTRAST_PLUS_1, + CONTRAST_PLUS_2, + CONTRAST_MAX, +}; + +#define V4L2_CID_CAMERA_SATURATION (V4L2_CID_PRIVATE_BASE+78) +enum v4l2_saturation_mode { + SATURATION_MINUS_2 = 0, + SATURATION_MINUS_1, + SATURATION_DEFAULT, + SATURATION_PLUS_1, + SATURATION_PLUS_2, + SATURATION_MAX, +}; + +#define V4L2_CID_CAMERA_SHARPNESS (V4L2_CID_PRIVATE_BASE+79) +enum v4l2_sharpness_mode { + SHARPNESS_MINUS_2 = 0, + SHARPNESS_MINUS_1, + SHARPNESS_DEFAULT, + SHARPNESS_PLUS_1, + SHARPNESS_PLUS_2, + SHARPNESS_MAX, +}; + +#define V4L2_CID_CAMERA_WDR (V4L2_CID_PRIVATE_BASE+80) +enum v4l2_wdr_mode { + WDR_OFF, + WDR_ON, + WDR_MAX, +}; + +#define V4L2_CID_CAMERA_ANTI_SHAKE (V4L2_CID_PRIVATE_BASE+81) +enum v4l2_anti_shake_mode { + ANTI_SHAKE_OFF, + ANTI_SHAKE_STILL_ON, + ANTI_SHAKE_MOVIE_ON, + ANTI_SHAKE_MAX, +}; + +#define V4L2_CID_CAMERA_TOUCH_AF_START_STOP (V4L2_CID_PRIVATE_BASE+82) +enum v4l2_touch_af { + TOUCH_AF_STOP = 0, + TOUCH_AF_START, + TOUCH_AF_MAX, +}; + +#define V4L2_CID_CAMERA_SMART_AUTO (V4L2_CID_PRIVATE_BASE+83) +enum v4l2_smart_auto { + SMART_AUTO_OFF = 0, + SMART_AUTO_ON, + SMART_AUTO_MAX, +}; + +#define V4L2_CID_CAMERA_VINTAGE_MODE (V4L2_CID_PRIVATE_BASE+84) +enum v4l2_vintage_mode { + VINTAGE_MODE_BASE, + VINTAGE_MODE_OFF, + VINTAGE_MODE_NORMAL, + VINTAGE_MODE_WARM, + VINTAGE_MODE_COOL, + VINTAGE_MODE_BNW, + VINTAGE_MODE_MAX, +}; + +#define V4L2_CID_CAMERA_JPEG_QUALITY (V4L2_CID_PRIVATE_BASE+85) +#define V4L2_CID_CAMERA_GPS_LATITUDE (V4L2_CID_CAMERA_CLASS_BASE + 30)//(V4L2_CID_PRIVATE_BASE+86) +#define V4L2_CID_CAMERA_GPS_LONGITUDE (V4L2_CID_CAMERA_CLASS_BASE + 31)//(V4L2_CID_PRIVATE_BASE+87) +#define V4L2_CID_CAMERA_GPS_TIMESTAMP (V4L2_CID_CAMERA_CLASS_BASE + 32)//(V4L2_CID_PRIVATE_BASE+88) +#define V4L2_CID_CAMERA_GPS_ALTITUDE (V4L2_CID_CAMERA_CLASS_BASE + 33)//(V4L2_CID_PRIVATE_BASE+89) +#define V4L2_CID_CAMERA_EXIF_TIME_INFO (V4L2_CID_CAMERA_CLASS_BASE + 34) +#define V4L2_CID_CAMERA_GPS_PROCESSINGMETHOD (V4L2_CID_CAMERA_CLASS_BASE+35) +#define V4L2_CID_CAMERA_ZOOM (V4L2_CID_PRIVATE_BASE+90) +enum v4l2_zoom_level { + ZOOM_LEVEL_0 = 0, + ZOOM_LEVEL_1, + ZOOM_LEVEL_2, + ZOOM_LEVEL_3, + ZOOM_LEVEL_4, + ZOOM_LEVEL_5, + ZOOM_LEVEL_6, + ZOOM_LEVEL_7, + ZOOM_LEVEL_8, + ZOOM_LEVEL_9, + ZOOM_LEVEL_10, + ZOOM_LEVEL_11, + ZOOM_LEVEL_12, + ZOOM_LEVEL_MAX = 31, +}; + +#define V4L2_CID_CAMERA_FACE_DETECTION (V4L2_CID_PRIVATE_BASE+91) +enum v4l2_face_detection { + FACE_DETECTION_OFF = 0, + FACE_DETECTION_ON, + FACE_DETECTION_NOLINE, + FACE_DETECTION_ON_BEAUTY, + FACE_DETECTION_MAX, +}; + +#define V4L2_CID_CAMERA_SMART_AUTO_STATUS (V4L2_CID_PRIVATE_BASE+92) +enum v4l2_smart_auto_status { + SMART_AUTO_STATUS_AUTO = 0, + SMART_AUTO_STATUS_LANDSCAPE, + SMART_AUTO_STATUS_PORTRAIT, + SMART_AUTO_STATUS_MACRO, + SMART_AUTO_STATUS_NIGHT, + SMART_AUTO_STATUS_PORTRAIT_NIGHT, + SMART_AUTO_STATUS_BACKLIT, + SMART_AUTO_STATUS_PORTRAIT_BACKLIT, + SMART_AUTO_STATUS_ANTISHAKE, + SMART_AUTO_STATUS_PORTRAIT_ANTISHAKE, + SMART_AUTO_STATUS_MAX, +}; + +#define V4L2_CID_CAMERA_SET_AUTO_FOCUS (V4L2_CID_PRIVATE_BASE+93) +enum v4l2_auto_focus { + AUTO_FOCUS_OFF = 0, + AUTO_FOCUS_ON, + AUTO_FOCUS_MAX, +}; + +#define V4L2_CID_CAMERA_BEAUTY_SHOT (V4L2_CID_PRIVATE_BASE+94) +enum v4l2_beauty_shot { + BEAUTY_SHOT_OFF = 0, + BEAUTY_SHOT_ON, + BEAUTY_SHOT_MAX, +}; + +#define V4L2_CID_CAMERA_AEAWB_LOCK_UNLOCK (V4L2_CID_PRIVATE_BASE+95) +enum v4l2_ae_awb_lockunlock { + AE_UNLOCK_AWB_UNLOCK = 0, + AE_LOCK_AWB_UNLOCK, + AE_UNLOCK_AWB_LOCK, + AE_LOCK_AWB_LOCK, + AE_AWB_MAX +}; + +#define V4L2_CID_CAMERA_FACEDETECT_LOCKUNLOCK (V4L2_CID_PRIVATE_BASE+96) +enum v4l2_face_lock { + FACE_LOCK_OFF = 0, + FACE_LOCK_ON, + FIRST_FACE_TRACKING, + FACE_LOCK_MAX, +}; + +#define V4L2_CID_CAMERA_OBJECT_POSITION_X (V4L2_CID_PRIVATE_BASE+97) +#define V4L2_CID_CAMERA_OBJECT_POSITION_Y (V4L2_CID_PRIVATE_BASE+98) +#define V4L2_CID_CAMERA_FOCUS_MODE (V4L2_CID_PRIVATE_BASE+99) +enum v4l2_focusmode { + FOCUS_MODE_AUTO = 0, + FOCUS_MODE_MACRO, + FOCUS_MODE_FACEDETECT, + FOCUS_MODE_INFINITY, + FOCUS_MODE_CONTINOUS, + FOCUS_MODE_TOUCH, + FOCUS_MODE_MAX, + FOCUS_MODE_DEFAULT = (1 << 8), +}; + +#define V4L2_CID_CAMERA_OBJ_TRACKING_STATUS (V4L2_CID_PRIVATE_BASE+100) +enum v4l2_obj_tracking_status { + OBJECT_TRACKING_STATUS_BASE, + OBJECT_TRACKING_STATUS_PROGRESSING, + OBJECT_TRACKING_STATUS_SUCCESS, + OBJECT_TRACKING_STATUS_FAIL, + OBJECT_TRACKING_STATUS_MISSING, + OBJECT_TRACKING_STATUS_MAX, +}; + +#define V4L2_CID_CAMERA_OBJ_TRACKING_START_STOP (V4L2_CID_PRIVATE_BASE+101) +enum v4l2_ot_start_stop { + OT_STOP = 0, + OT_START, + OT_MAX, +}; + +#define V4L2_CID_CAMERA_CAF_START_STOP (V4L2_CID_PRIVATE_BASE+102) +enum v4l2_caf_start_stop { + CAF_STOP = 0, + CAF_START, + CAF_MAX, +}; + +#define V4L2_CID_CAMERA_AUTO_FOCUS_RESULT (V4L2_CID_PRIVATE_BASE+103) +#define V4L2_CID_CAMERA_FRAME_RATE (V4L2_CID_PRIVATE_BASE+104) +enum v4l2_frame_rate { + FRAME_RATE_AUTO = 0, + FRAME_RATE_7 = 7, + FRAME_RATE_15 = 15, + FRAME_RATE_30 = 30, + FRAME_RATE_60 = 60, + FRAME_RATE_120 = 120, + FRAME_RATE_MAX +}; + +#define V4L2_CID_CAMERA_ANTI_BANDING (V4L2_CID_PRIVATE_BASE+105) +enum v4l2_anti_banding { + ANTI_BANDING_AUTO = 0, + ANTI_BANDING_50HZ = 1, + ANTI_BANDING_60HZ = 2, + ANTI_BANDING_OFF = 3, +}; + +#define V4L2_CID_CAMERA_SET_GAMMA (V4L2_CID_PRIVATE_BASE+106) +enum v4l2_gamma_mode { + GAMMA_OFF = 0, + GAMMA_ON = 1, + GAMMA_MAX, +}; + +#define V4L2_CID_CAMERA_SET_SLOW_AE (V4L2_CID_PRIVATE_BASE+107) +enum v4l2_slow_ae_mode { + SLOW_AE_OFF, + SLOW_AE_ON, + SLOW_AE_MAX, +}; + +#define V4L2_CID_CAMERA_BATCH_REFLECTION (V4L2_CID_PRIVATE_BASE+108) +#define V4L2_CID_CAMERA_EXIF_ORIENTATION (V4L2_CID_PRIVATE_BASE+109) + +#define V4L2_CID_CAMERA_RESET (V4L2_CID_PRIVATE_BASE+111) //s1_camera [ Defense process by ESD input ] +#define V4L2_CID_CAMERA_CHECK_DATALINE (V4L2_CID_PRIVATE_BASE+112) +#define V4L2_CID_CAMERA_CHECK_DATALINE_STOP (V4L2_CID_PRIVATE_BASE+113) + +#endif + +#if defined(CONFIG_ARIES_NTT) // Modify NTTS1 +#define V4L2_CID_CAMERA_AE_AWB_DISABLE_LOCK (V4L2_CID_PRIVATE_BASE+114) +#endif +#define V4L2_CID_CAMERA_THUMBNAIL_NULL (V4L2_CID_PRIVATE_BASE+115) +#define V4L2_CID_CAMERA_SENSOR_MODE (V4L2_CID_PRIVATE_BASE+116) +enum v4l2_sensor_mode { + SENSOR_CAMERA, + SENSOR_MOVIE, +}; + +typedef enum { + STREAM_MODE_CAM_OFF, + STREAM_MODE_CAM_ON, + STREAM_MODE_MOVIE_OFF, + STREAM_MODE_MOVIE_ON, +} stream_mode_t; + +#define V4L2_CID_CAMERA_EXIF_EXPTIME (V4L2_CID_PRIVATE_BASE+117) +#define V4L2_CID_CAMERA_EXIF_FLASH (V4L2_CID_PRIVATE_BASE+118) +#define V4L2_CID_CAMERA_EXIF_ISO (V4L2_CID_PRIVATE_BASE+119) +#define V4L2_CID_CAMERA_EXIF_TV (V4L2_CID_PRIVATE_BASE+120) +#define V4L2_CID_CAMERA_EXIF_BV (V4L2_CID_PRIVATE_BASE+121) +#define V4L2_CID_CAMERA_EXIF_EBV (V4L2_CID_PRIVATE_BASE+122) +#define V4L2_CID_CAMERA_CHECK_ESD (V4L2_CID_PRIVATE_BASE+123) +#define V4L2_CID_CAMERA_APP_CHECK (V4L2_CID_PRIVATE_BASE+124) + +/* Pixel format FOURCC depth Description */ +enum v4l2_pix_format_mode { + V4L2_PIX_FMT_MODE_PREVIEW, + V4L2_PIX_FMT_MODE_CAPTURE, + V4L2_PIX_FMT_MODE_HDR, + V4L2_PIX_FMT_MODE_VT_MIRROR, + V4L2_PIX_FMT_MODE_VT_NONMIRROR, +}; +/* 12 Y/CbCr 4:2:0 64x32 macroblocks */ +#define V4L2_PIX_FMT_NV12T v4l2_fourcc('T', 'V', '1', '2') +#define V4L2_PIX_FMT_NV21T v4l2_fourcc('T', 'V', '2', '1') + + +/* + * * V4L2 extention for digital camera + * */ +/* Strobe flash light */ +enum v4l2_strobe_control { + /* turn off the flash light */ + V4L2_STROBE_CONTROL_OFF = 0, + /* turn on the flash light */ + V4L2_STROBE_CONTROL_ON = 1, + /* act guide light before splash */ + V4L2_STROBE_CONTROL_AFGUIDE = 2, + /* charge the flash light */ + V4L2_STROBE_CONTROL_CHARGE = 3, +}; + +enum v4l2_strobe_conf { + V4L2_STROBE_OFF = 0, /* Always off */ + V4L2_STROBE_ON = 1, /* Always splashes */ + /* Auto control presets */ + V4L2_STROBE_AUTO = 2, + V4L2_STROBE_REDEYE_REDUCTION = 3, + V4L2_STROBE_SLOW_SYNC = 4, + V4L2_STROBE_FRONT_CURTAIN = 5, + V4L2_STROBE_REAR_CURTAIN = 6, + /* Extra manual control presets */ + /* keep turned on until turning off */ + V4L2_STROBE_PERMANENT = 7, + V4L2_STROBE_EXTERNAL = 8, +}; + +enum v4l2_strobe_status { + V4L2_STROBE_STATUS_OFF = 0, + /* while processing configurations */ + V4L2_STROBE_STATUS_BUSY = 1, + V4L2_STROBE_STATUS_ERR = 2, + V4L2_STROBE_STATUS_CHARGING = 3, + V4L2_STROBE_STATUS_CHARGED = 4, +}; + +/* capabilities field */ +/* No strobe supported */ +#define V4L2_STROBE_CAP_NONE 0x0000 +/* Always flash off mode */ +#define V4L2_STROBE_CAP_OFF 0x0001 +/* Always use flash light mode */ +#define V4L2_STROBE_CAP_ON 0x0002 +/* Flashlight works automatic */ +#define V4L2_STROBE_CAP_AUTO 0x0004 +/* Red-eye reduction */ +#define V4L2_STROBE_CAP_REDEYE 0x0008 +/* Slow sync */ +#define V4L2_STROBE_CAP_SLOWSYNC 0x0010 +/* Front curtain */ +#define V4L2_STROBE_CAP_FRONT_CURTAIN 0x0020 +/* Rear curtain */ +#define V4L2_STROBE_CAP_REAR_CURTAIN 0x0040 +/* keep turned on until turning off */ +#define V4L2_STROBE_CAP_PERMANENT 0x0080 +/* use external strobe */ +#define V4L2_STROBE_CAP_EXTERNAL 0x0100 + +/* Set mode and Get status */ +struct v4l2_strobe { + /* off/on/charge:0/1/2 */ + enum v4l2_strobe_control control; + /* supported strobe capabilities */ + __u32 capabilities; + enum v4l2_strobe_conf mode; + enum v4l2_strobe_status status; /* read only */ + /* default is 0 and range of value varies from each models */ + __u32 flash_ev; + __u32 reserved[4]; +}; + +#define VIDIOC_S_STROBE _IOWR('V', 83, struct v4l2_strobe) +#define VIDIOC_G_STROBE _IOR('V', 84, struct v4l2_strobe) + +/* Object recognition and collateral actions */ +enum v4l2_recog_mode { + V4L2_RECOGNITION_MODE_OFF = 0, + V4L2_RECOGNITION_MODE_ON = 1, + V4L2_RECOGNITION_MODE_LOCK = 2, +}; + +enum v4l2_recog_action { + V4L2_RECOGNITION_ACTION_NONE = 0, /* only recognition */ + V4L2_RECOGNITION_ACTION_BLINK = 1, /* Capture on blinking */ + V4L2_RECOGNITION_ACTION_SMILE = 2, /* Capture on smiling */ +}; + +enum v4l2_recog_pattern { + V4L2_RECOG_PATTERN_FACE = 0, /* Face */ + V4L2_RECOG_PATTERN_HUMAN = 1, /* Human */ + V4L2_RECOG_PATTERN_CHAR = 2, /* Character */ +}; + +struct v4l2_recog_rect { + enum v4l2_recog_pattern p; /* detected pattern */ + struct v4l2_rect o; /* detected area */ + __u32 reserved[4]; +}; + +struct v4l2_recog_data { + __u8 detect_cnt; /* detected object counter */ + struct v4l2_rect o; /* detected area */ + __u32 reserved[4]; +}; + +struct v4l2_recognition { + enum v4l2_recog_mode mode; + + /* Which pattern to detect */ + enum v4l2_recog_pattern pattern; + + /* How many object to detect */ + __u8 obj_num; + + /* select detected object */ + __u32 detect_idx; + + /* read only :Get object coordination */ + struct v4l2_recog_data data; + + enum v4l2_recog_action action; + __u32 reserved[4]; +}; + +#define VIDIOC_S_RECOGNITION _IOWR('V', 85, struct v4l2_recognition) +#define VIDIOC_G_RECOGNITION _IOR('V', 86, struct v4l2_recognition) + +#endif /* __LINUX_VIDEODEV2_SAMSUNG_H */ diff --git a/exynos5/hal/libcamera/Android.mk b/exynos5/hal/libcamera/Android.mk new file mode 100644 index 0000000..9ab5b2f --- /dev/null +++ b/exynos5/hal/libcamera/Android.mk @@ -0,0 +1,28 @@ +LOCAL_PATH:= $(call my-dir) +include $(CLEAR_VARS) + +# HAL module implemenation stored in +# hw/..so +LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw + +LOCAL_C_INCLUDES += $(LOCAL_PATH)/../include + +LOCAL_SRC_FILES:= \ + SecCamera.cpp \ + SecCameraHWInterface.cpp \ + mediactl.cpp \ + +LOCAL_SHARED_LIBRARIES:= libutils libcutils libbinder liblog libcamera_client libhardware + +LOCAL_CFLAGS += -DGAIA_FW_BETA + +ifeq ($(BOARD_USES_HWJPEG),true) +LOCAL_SHARED_LIBRARIES += libhwjpeg +LOCAL_CFLAGS += -DSAMSUNG_EXYNOS5250 +endif + +LOCAL_MODULE := camera.$(TARGET_DEVICE) + +LOCAL_MODULE_TAGS := optional + +include $(BUILD_SHARED_LIBRARY) diff --git a/exynos5/hal/libcamera/NOTICE b/exynos5/hal/libcamera/NOTICE new file mode 100644 index 0000000..f921593 --- /dev/null +++ b/exynos5/hal/libcamera/NOTICE @@ -0,0 +1,190 @@ + + Copyright (C) 2008 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + diff --git a/exynos5/hal/libcamera/SecCamera.cpp b/exynos5/hal/libcamera/SecCamera.cpp new file mode 100644 index 0000000..2b434c5 --- /dev/null +++ b/exynos5/hal/libcamera/SecCamera.cpp @@ -0,0 +1,3693 @@ +/* + * Copyright 2008, The Android Open Source Project + * Copyright 2010, Samsung Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* +************************************ +* Filename: SecCamera.cpp +* Author: Sachin P. Kamat +* Purpose: This file interacts with the Camera and JPEG drivers. +************************************* +*/ + +//#define LOG_NDEBUG 0 +#define LOG_TAG "SecCamera" + +#include +#include +#include +#include +#include "SecCamera.h" +#include "cutils/properties.h" +#include +#include "mediactl.h" +#include "v4l2subdev.h" + +using namespace android; + +#define CHECK(return_value) \ + if (return_value < 0) { \ + LOGE("%s::%d fail. errno: %s, m_camera_id = %d", \ + __func__, __LINE__, strerror(errno), m_camera_id); \ + return -1; \ + } + +#define CHECK_PTR(return_value) \ + if (return_value < 0) { \ + LOGE("%s::%d fail, errno: %s, m_camera_id = %d", \ + __func__,__LINE__, strerror(errno), m_camera_id); \ + return NULL; \ + } + +#define ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1)) + +namespace android { + +static struct timeval time_start; +static struct timeval time_stop; +int cam_fd1, cam_fd2; + +#if defined(LOG_NDEBUG) && LOG_NDEBUG == 0 +unsigned long measure_time_camera(struct timeval *start, struct timeval *stop) +{ + unsigned long sec, usec, time; + + sec = stop->tv_sec - start->tv_sec; + + if (stop->tv_usec >= start->tv_usec) { + usec = stop->tv_usec - start->tv_usec; + } else { + usec = stop->tv_usec + 1000000 - start->tv_usec; + sec--; + } + + time = (sec * 1000000) + usec; + + return time; +} +#endif + +static int gsc_cap_open(int id) +{ + char node[20]; + int fd; + + id += GSC_VD_NODE_OFFSET; + sprintf(node, "%s%d", PFX_NODE_GSC, id); + LOGE("(%s): %s%d", __func__, PFX_NODE_GSC, id); + + fd = open(node, O_RDWR, 0); + if(fd < 0) { + LOGE("ERR(%s): Open gscaler video device failed", __func__); + return -1; + } + LOGE("%s open", node); + + return fd; +} + +static int close_buffers(struct SecBuffer *buffers) +{ + int i, j; + int ret; + + for (i = 0; i < MAX_BUFFERS; i++) { + for(j = 0; j < MAX_PLANES; j++) { + if (buffers[i].virt.extP[j]) { + buffers[i].virt.extP[j] = NULL; + } + } + } + + return 0; +} + +static int get_pixel_depth(unsigned int fmt) +{ + int depth = 0; + + switch (fmt) { + case V4L2_PIX_FMT_JPEG: + depth = 8; + break; + + case V4L2_PIX_FMT_NV12: + case V4L2_PIX_FMT_NV12T: + case V4L2_PIX_FMT_NV21: + case V4L2_PIX_FMT_YUV420: + case V4L2_PIX_FMT_YVU420: + case V4L2_PIX_FMT_YVU420M: + case V4L2_PIX_FMT_NV12M: + case V4L2_PIX_FMT_NV12MT: + depth = 12; + break; + + case V4L2_PIX_FMT_RGB565: + case V4L2_PIX_FMT_RGB565X: + case V4L2_PIX_FMT_YUYV: + case V4L2_PIX_FMT_YVYU: + case V4L2_PIX_FMT_UYVY: + case V4L2_PIX_FMT_VYUY: + case V4L2_PIX_FMT_NV16: + case V4L2_PIX_FMT_NV61: + case V4L2_PIX_FMT_YUV422P: + depth = 16; + break; + + case V4L2_PIX_FMT_RGB32: + depth = 32; + break; + + default: + LOGE("ERR(%s):Get depth failed.", __func__); + break; + } + + return depth; +} + +static int gsc_cap_poll(struct pollfd *events) +{ + int ret; + + /* 10 second delay is because sensor can take a long time + * to do auto focus and capture in dark settings + */ + ret = poll(events, 1, 10000); + if (ret < 0) { + LOGE("ERR(%s):poll error", __func__); + return ret; + } + + if (ret == 0) { + LOGE("ERR(%s):No data in 10 secs..", __func__); + return ret; + } + + return ret; +} + +static int v4l2_gsc_cap_querycap(int fp) +{ + struct v4l2_capability cap; + + if (ioctl(fp, VIDIOC_QUERYCAP, &cap) < 0) { + LOGE("ERR(%s):VIDIOC_QUERYCAP failed", __func__); + return -1; + } + + if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE_MPLANE)) { + LOGE("ERR(%s):no capture devices", __func__); + return -1; + } + if (!(cap.capabilities & V4L2_CAP_STREAMING)) { + LOGE("ERR(%s):no streaming capture devices", __func__); + return -1; + } + + return 0; +} + +static const __u8* v4l2_gsc_cap_enuminput(int fp, int index) +{ + static struct v4l2_input input; + + input.index = index; + if (ioctl(fp, VIDIOC_ENUMINPUT, &input) != 0) { + LOGE("ERR(%s):No matching index found", __func__); + return NULL; + } + LOGI("Name of input channel[%d] is %s", input.index, input.name); + + return input.name; +} + +static int v4l2_gsc_cap_s_input(int fp, int index) +{ + struct v4l2_input input; + + input.index = index; + + if (ioctl(fp, VIDIOC_S_INPUT, &input) < 0) { + LOGE("ERR(%s):VIDIOC_S_INPUT failed", __func__); + return -1; + } + + return 0; +} + +static int v4l2_gsc_cap_g_fmt(int fp) +{ + struct v4l2_format v4l2_fmt; + + v4l2_fmt.type = V4L2_BUF_TYPE; + + if(ioctl(fp, VIDIOC_G_FMT, &v4l2_fmt) < 0){ + LOGE("ERR(%s):VIDIOC_G_FMT failed", __func__); + return -1; + } + + return 0; +} + +static int v4l2_gsc_cap_s_fmt(int fp, int width, int height, unsigned int fmt, enum v4l2_field field, unsigned int num_plane) +{ + struct v4l2_format v4l2_fmt; + struct v4l2_pix_format pixfmt; + unsigned int framesize; + + memset(&v4l2_fmt, 0, sizeof(struct v4l2_format)); + v4l2_fmt.type = V4L2_BUF_TYPE; + + framesize = (width * height * get_pixel_depth(fmt)) / 8; + + v4l2_fmt.fmt.pix_mp.width = width; + v4l2_fmt.fmt.pix_mp.height = height; + v4l2_fmt.fmt.pix_mp.pixelformat = fmt; + v4l2_fmt.fmt.pix_mp.field = field; + if (num_plane == 1) { + v4l2_fmt.fmt.pix_mp.plane_fmt[0].sizeimage = framesize; + } else if (num_plane == 2) { + v4l2_fmt.fmt.pix_mp.plane_fmt[0].sizeimage = ALIGN(width * height, 2048); + v4l2_fmt.fmt.pix_mp.plane_fmt[1].sizeimage = ALIGN(width/2, 16) * ALIGN(height/2, 16) * 2; + } else if (num_plane == 3) { + v4l2_fmt.fmt.pix_mp.plane_fmt[0].sizeimage = ALIGN(width, 16) * ALIGN(height, 16); + v4l2_fmt.fmt.pix_mp.plane_fmt[1].sizeimage = ALIGN(width/2, 8) * ALIGN(height/2, 8); + v4l2_fmt.fmt.pix_mp.plane_fmt[2].sizeimage = ALIGN(width/2, 8) * ALIGN(height/2, 8); + } else { + LOGE("ERR(%s): Invalid plane number", __func__); + return -1; + } + v4l2_fmt.fmt.pix_mp.num_planes = num_plane; + + /* Set up for capture */ + if (ioctl(fp, VIDIOC_S_FMT, &v4l2_fmt) < 0) { + LOGE("ERR(%s):VIDIOC_S_FMT failed", __func__); + return -1; + } + + return 0; +} + +static int v4l2_gsc_cap_s_fmt_cap(int fp, int width, int height, unsigned int fmt) +{ + struct v4l2_format v4l2_fmt; + struct v4l2_pix_format pixfmt; + + memset(&pixfmt, 0, sizeof(pixfmt)); + + v4l2_fmt.type = V4L2_BUF_TYPE; + + pixfmt.width = width; + pixfmt.height = height; + pixfmt.pixelformat = fmt; + if (fmt == V4L2_PIX_FMT_JPEG) + pixfmt.colorspace = V4L2_COLORSPACE_JPEG; + + v4l2_fmt.fmt.pix = pixfmt; + + /* Set up for capture */ + if (ioctl(fp, VIDIOC_S_FMT, &v4l2_fmt) < 0) { + LOGE("ERR(%s):VIDIOC_S_FMT failed", __func__); + return -1; + } + + return 0; +} + +int v4l2_gsc_cap_s_fmt_is(int fp, int width, int height, unsigned int fmt, enum v4l2_field field) +{ + struct v4l2_format v4l2_fmt; + struct v4l2_pix_format pixfmt; + + memset(&pixfmt, 0, sizeof(pixfmt)); + + v4l2_fmt.type = V4L2_BUF_TYPE_PRIVATE; + + pixfmt.width = width; + pixfmt.height = height; + pixfmt.pixelformat = fmt; + pixfmt.field = field; + + v4l2_fmt.fmt.pix = pixfmt; + + /* Set up for capture */ + if (ioctl(fp, VIDIOC_S_FMT, &v4l2_fmt) < 0) { + LOGE("ERR(%s):VIDIOC_S_FMT failed", __func__); + return -1; + } + + return 0; +} + +static int v4l2_gsc_cap_enum_fmt(int fp, unsigned int fmt) +{ + struct v4l2_fmtdesc fmtdesc; + int found = 0; + + fmtdesc.type = V4L2_BUF_TYPE; + fmtdesc.index = 0; + + while (ioctl(fp, VIDIOC_ENUM_FMT, &fmtdesc) == 0) { + if (fmtdesc.pixelformat == fmt) { + LOGV("Passed fmt = %#x found pixel format[%d]: %s", fmt, fmtdesc.index, fmtdesc.description); + found = 1; + break; + } + + fmtdesc.index++; + } + + if (!found) { + LOGE("unsupported pixel format"); + return -1; + } + + return 0; +} + +static int v4l2_gsc_cap_reqbufs(int fp, enum v4l2_buf_type type, int nr_bufs) +{ + struct v4l2_requestbuffers req; + + req.count = nr_bufs; + req.type = type; + req.memory = V4L2_MEMORY_TYPE; + + if (ioctl(fp, VIDIOC_REQBUFS, &req) < 0) { + LOGE("ERR(%s):VIDIOC_REQBUFS failed", __func__); + return -1; + } + + if (req.count > MAX_BUFFERS ) { + LOGE("ERR(%s):Insufficient buffer memory on", __func__); + return -1; + } + + return req.count; +} + +static int v4l2_gsc_cap_querybuf(int fp, struct SecBuffer *buffers, enum v4l2_buf_type type, int nr_frames, int num_plane) +{ + struct v4l2_buffer v4l2_buf; + struct v4l2_plane planes[VIDEO_MAX_PLANES]; + int i, plane_index; + + for (i = 0; i < nr_frames; i++) { + v4l2_buf.type = type; + v4l2_buf.memory = V4L2_MEMORY_TYPE; + v4l2_buf.index = i; + v4l2_buf.m.planes = planes; + v4l2_buf.length = num_plane; // this is for multi-planar + LOGV("QUERYBUF(index=%d)", i); + LOGV("Memory plane is %d", v4l2_buf.length); + + if (ioctl(fp, VIDIOC_QUERYBUF, &v4l2_buf) < 0) { + LOGE("ERR(%s):VIDIOC_QUERYBUF failed", __func__); + return -1; + } + + for (plane_index = 0; plane_index < num_plane; plane_index++) { + LOGV("Offset : 0x%x", v4l2_buf.m.planes[plane_index].m.mem_offset); + LOGV("Plane Length : 0x%x", v4l2_buf.m.planes[plane_index].length); + + buffers[i].phys.extP[plane_index] = (unsigned int)v4l2_buf.m.planes[plane_index].cookie; + + buffers[i].size.extS[plane_index] = v4l2_buf.m.planes[plane_index].length; + LOGV("Length[%d] : 0x%x", i, buffers[i].size.extS[plane_index]); + if ((buffers[i].virt.extP[plane_index] = (char *)mmap(0, v4l2_buf.m.planes[plane_index].length, + PROT_READ | PROT_WRITE, MAP_SHARED, fp, v4l2_buf.m.planes[plane_index].m.mem_offset)) < 0) { + LOGE("mmap failed"); + return -1; + } + LOGV("vaddr[%d][%d] : 0x%x", i, plane_index, (__u32) buffers[i].virt.extP[plane_index]); + } + } + return 0; +} + +static int v4l2_gsc_cap_streamon(int fp) +{ + enum v4l2_buf_type type = V4L2_BUF_TYPE; + int ret; + + LOGV("%s : On streaming I/O", __func__); + ret = ioctl(fp, VIDIOC_STREAMON, &type); + if (ret < 0) { + LOGE("ERR(%s):VIDIOC_STREAMON failed", __func__); + return ret; + } + + return ret; +} + +static int v4l2_gsc_cap_streamoff(int fp) +{ + enum v4l2_buf_type type = V4L2_BUF_TYPE; + int ret; + + LOGV("%s :", __func__); + ret = ioctl(fp, VIDIOC_STREAMOFF, &type); + if (ret < 0) { + LOGE("ERR(%s):VIDIOC_STREAMOFF failed", __func__); + return ret; + } + + return 0; +} + +static int v4l2_gsc_cap_qbuf(int fp, int width, int height, struct SecBuffer *vaddr, int index, int num_plane) +{ + struct v4l2_buffer v4l2_buf; + int ret; + + struct v4l2_plane planes[VIDEO_MAX_PLANES]; + + v4l2_buf.m.planes = planes; + v4l2_buf.length = num_plane; + + v4l2_buf.type = V4L2_BUF_TYPE; + v4l2_buf.memory = V4L2_MEMORY_TYPE; + v4l2_buf.index = index; + + if(fp == cam_fd1) { + if (num_plane == 1) { + v4l2_buf.m.planes[0].m.userptr = (long unsigned int)vaddr[index].virt.extP[0]; + v4l2_buf.m.planes[0].length = width * height * 2; + } else if (num_plane == 2) { + v4l2_buf.m.planes[0].m.userptr = (long unsigned int)vaddr[index].virt.extP[0]; + v4l2_buf.m.planes[0].length = ALIGN(width, 16) * ALIGN(height, 16); + v4l2_buf.m.planes[1].m.userptr = (long unsigned int)vaddr[index].virt.extP[1]; + v4l2_buf.m.planes[1].length = ALIGN(width/2, 16) * ALIGN(height/2, 16); + } else if (num_plane == 3) { + v4l2_buf.m.planes[0].m.userptr = (long unsigned int)vaddr[index].virt.extP[0]; + v4l2_buf.m.planes[0].length = ALIGN(width, 16) * ALIGN(height, 16); + v4l2_buf.m.planes[1].m.userptr = (long unsigned int)vaddr[index].virt.extP[1]; + v4l2_buf.m.planes[1].length = ALIGN(width/2, 8) * ALIGN(height/2, 8); + v4l2_buf.m.planes[2].m.userptr = (long unsigned int)vaddr[index].virt.extP[2]; + v4l2_buf.m.planes[2].length = ALIGN(width/2, 8) * ALIGN(height/2, 8); + } else { + LOGE("ERR(%s): Invalid plane number", __func__); + return -1; + } + } + else if(fp == cam_fd2) { + v4l2_buf.m.planes[0].m.userptr = (long unsigned int)vaddr[index].virt.extP[0]; + v4l2_buf.m.planes[0].length = ALIGN(ALIGN(width, 16) * ALIGN(height, 16), 2048); + v4l2_buf.m.planes[1].m.userptr = (long unsigned int)vaddr[index].virt.extP[1]; + v4l2_buf.m.planes[1].length = ALIGN(ALIGN(width, 16) * ALIGN(height >> 1, 8), 2048); + } + else { + return -1; + } + + ret = ioctl(fp, VIDIOC_QBUF, &v4l2_buf); + if (ret < 0) { + LOGE("ERR(%s):VIDIOC_QBUF failed", __func__); + return ret; + } + + return 0; +} + +static int v4l2_gsc_cap_dqbuf(int fp, int num_plane) +{ + struct v4l2_buffer v4l2_buf; + int ret; + + struct v4l2_plane planes[VIDEO_MAX_PLANES]; + + v4l2_buf.m.planes = planes; + v4l2_buf.length = num_plane; + + v4l2_buf.type = V4L2_BUF_TYPE; + v4l2_buf.memory = V4L2_MEMORY_TYPE; + + ret = ioctl(fp, VIDIOC_DQBUF, &v4l2_buf); + if (ret < 0) { + LOGE("ERR(%s):VIDIOC_DQBUF failed, dropped frame", __func__); + return ret; + } + + return v4l2_buf.index; +} + +static int v4l2_gsc_cap_g_ctrl(int fp, unsigned int id) +{ + struct v4l2_control ctrl; + int ret; + + ctrl.id = id; + + ret = ioctl(fp, VIDIOC_G_CTRL, &ctrl); + if (ret < 0) { + LOGE("ERR(%s): VIDIOC_G_CTRL(id = 0x%x (%d)) failed, ret = %d", + __func__, id, id-V4L2_CID_PRIVATE_BASE, ret); + return ret; + } + + return ctrl.value; +} + +static int v4l2_gsc_cap_s_ctrl(int fp, unsigned int id, unsigned int value) +{ + struct v4l2_control ctrl; + int ret; + + ctrl.id = id; + ctrl.value = value; + + ret = ioctl(fp, VIDIOC_S_CTRL, &ctrl); + if (ret < 0) { + LOGE("ERR(%s):VIDIOC_S_CTRL(id = %#x (%d), value = %d) failed ret = %d", + __func__, id, id-V4L2_CID_PRIVATE_BASE, value, ret); + + return ret; + } + + return ctrl.value; +} + +static int v4l2_gsc_cap_s_ext_ctrl(int fp, unsigned int id, void *value) +{ + struct v4l2_ext_controls ctrls; + struct v4l2_ext_control ctrl; + int ret; + + ctrl.id = id; + + ctrls.ctrl_class = V4L2_CTRL_CLASS_CAMERA; + ctrls.count = 1; + ctrls.controls = &ctrl; + + ret = ioctl(fp, VIDIOC_S_EXT_CTRLS, &ctrls); + if (ret < 0) + LOGE("ERR(%s):VIDIOC_S_EXT_CTRLS failed", __func__); + + return ret; +} + +static int v4l2_gsc_cap_g_parm(int fp, struct v4l2_streamparm *streamparm) +{ + int ret; + + streamparm->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + + ret = ioctl(fp, VIDIOC_G_PARM, streamparm); + if (ret < 0) { + LOGE("ERR(%s):VIDIOC_G_PARM failed", __func__); + return ret; + } + + LOGV("%s : timeperframe: numerator %d, denominator %d", __func__, + streamparm->parm.capture.timeperframe.numerator, + streamparm->parm.capture.timeperframe.denominator); + + return ret; +} + +static int v4l2_gsc_cap_s_parm(int fp, struct v4l2_streamparm *streamparm) +{ + int ret; + + streamparm->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; + + ret = ioctl(fp, VIDIOC_S_PARM, streamparm); + if (ret < 0) { + LOGE("ERR(%s):VIDIOC_S_PARM failed", __func__); + return ret; + } + + return ret; +} + +static int v4l2_subdev_open(struct media_entity *entity) +{ + int fd; + + fd = open(entity->devname, O_RDWR, 0); + if(fd < 0){ + LOGE("ERR(%s): Open failed.", __func__); + return -1; + } + + return 0; +} + +static int v4l2_subdev_get_fmt(int fd, struct v4l2_subdev_format *fmt) +{ + if(ioctl(fd, VIDIOC_SUBDEV_G_FMT, fmt)) { + LOGE("ERR(%s): subdev get foramt failed.", __func__); + return -1; + } + + return 0; +} + +SecCamera::SecCamera() : + m_flagCreate(0), + m_camera_id(CAMERA_ID_BACK), + m_gsc_vd_fd(-1), + m_cam_fd2(-1), + m_jpeg_fd(-1), + m_flag_record_start(0), + m_preview_v4lformat(V4L2_PIX_FMT_YVU420M), + m_preview_width (0), + m_preview_height (0), + m_preview_max_width (MAX_BACK_CAMERA_PREVIEW_WIDTH), + m_preview_max_height (MAX_BACK_CAMERA_PREVIEW_HEIGHT), + m_snapshot_v4lformat(-1), + m_snapshot_width (0), + m_snapshot_height (0), + m_snapshot_max_width (MAX_BACK_CAMERA_SNAPSHOT_WIDTH), + m_snapshot_max_height (MAX_BACK_CAMERA_SNAPSHOT_HEIGHT), + m_picture_vaddr(NULL), + m_recording_en (0), + m_recording_width (0), + m_recording_height (0), + m_angle(-1), + m_anti_banding(-1), + m_wdr(-1), + m_anti_shake(-1), + m_zoom_level(-1), + m_object_tracking(-1), + m_smart_auto(-1), + m_beauty_shot(-1), + m_vintage_mode(-1), + m_face_detect(-1), + m_object_tracking_start_stop(-1), + m_gps_latitude(-1), + m_gps_longitude(-1), + m_gps_altitude(-1), + m_gps_timestamp(-1), + m_sensor_mode(-1), + m_shot_mode(-1), + m_exif_orientation(-1), + m_chk_dataline(-1), + m_video_gamma(-1), + m_slow_ae(-1), + m_camera_af_flag(-1), + m_flag_camera_start(0), + m_jpeg_thumbnail_width (0), + m_jpeg_thumbnail_height(0), + m_jpeg_thumbnail_quality(100), + m_jpeg_quality(100), + m_touch_af_start_stop(-1), + m_postview_offset(0) +#ifdef ENABLE_ESD_PREVIEW_CHECK + , + m_esd_check_count(0) +#endif // ENABLE_ESD_PREVIEW_CHECK +{ + memset(&m_streamparm, 0, sizeof(m_streamparm)); + m_params = (struct sec_cam_parm*)&m_streamparm.parm.raw_data; + struct v4l2_captureparm capture; + m_params->capture.timeperframe.numerator = 1; + m_params->capture.timeperframe.denominator = 0; + m_params->contrast = -1; + m_params->effects = -1; + m_params->brightness = -1; + m_params->exposure = -1; + m_params->flash_mode = -1; + m_params->focus_mode = -1; + m_params->iso = -1; + m_params->metering = -1; + m_params->saturation = -1; + m_params->scene_mode = -1; + m_params->sharpness = -1; + m_params->white_balance = -1; + + memset(&mExifInfo, 0, sizeof(mExifInfo)); + + memset(&m_events_c, 0, sizeof(m_events_c)); + memset(&m_events_c2, 0, sizeof(m_events_c2)); +} + +SecCamera::~SecCamera() +{ + LOGV("%s :", __func__); + DestroyCamera(); +} + +bool SecCamera::CreateCamera(int index) +{ + LOGV("%s:", __func__); + char node[30]; + int i; + int ret = 0; + + LOGV("%s: m_flagCreate : %d", __func__, m_flagCreate); + if (!m_flagCreate) { + /* Arun C + * Reset the lense position only during camera starts; don't do + * reset between shot to shot + */ + m_flagCreate = 1; + m_camera_af_flag = -1; + + /* media device open */ + LOGV("%s: m_flagCreate : %d", __func__, m_flagCreate); + + media = media_open(); + if (media == NULL) { + LOGE("ERR(%s):Cannot open media device (error : %s)", __func__, strerror(errno)); + return -1; + } + +#ifndef GAIA_FW_BETA + ////////////////// + /* GET ENTITIES */ + ////////////////// + /* camera subdev */ + strcpy(node, M5MOLS_ENTITY_NAME); + LOGV("%s : node : %s", __func__, node); + camera_sd_entity = media_get_entity_by_name(media, node, strlen(node)); + LOGV("%s : camera_sd_entity : 0x%p", __func__, camera_sd_entity); + + /* mipi-csis subdev */ + sprintf(node, "%s.%d", PFX_SUBDEV_ENTITY_MIPI_CSIS, MIPI_NUM); + LOGV("%s : node : %s", __func__, node); + mipi_sd_entity = media_get_entity_by_name(media, node, strlen(node)); + LOGV("%s : mipi_sd_entity : 0x%p", __func__, mipi_sd_entity); + + /* fimc-lite subdev */ + sprintf(node, "%s.%d", PFX_SUBDEV_ENTITY_FLITE, FLITE_NUM); + LOGV("%s : node : %s", __func__, node); + flite_sd_entity = media_get_entity_by_name(media, node, strlen(node)); + LOGV("%s : flite_sd_entity : 0x%p", __func__, flite_sd_entity); + + /* gscaler-capture subdev */ + sprintf(node, "%s.%d", PFX_SUBDEV_ENTITY_GSC_CAP, GSC_NUM); + LOGV("%s : node : %s", __func__, node); + gsc_cap_sd_entity = media_get_entity_by_name(media, node, strlen(node)); + LOGV("%s : gsc_cap_sd_entity : 0x%p", __func__, gsc_cap_sd_entity); + + /* gscaler-capture subdev */ + sprintf(node, "%s.%d", PFX_VIDEODEV_ENTITY_GSC_CAP, GSC_NUM); + LOGV("%s : node : %s", __func__, node); + gsc_cap_vd_entity = media_get_entity_by_name(media, node, strlen(node)); + LOGV("%s : gsc_cap_vd_entity : 0x%p", __func__, gsc_cap_vd_entity); + + LOGV("camera_sd : numlink : %d", camera_sd_entity->num_links); + LOGV("mipi_sd : numlink : %d", mipi_sd_entity->num_links); + LOGV("flite_sd : numlink : %d", flite_sd_entity->num_links); + LOGV("gsc_cap_sd : numlink : %d", gsc_cap_sd_entity->num_links); + LOGV("gsc_cap_vd : numlink : %d", gsc_cap_vd_entity->num_links); + + ////////////////// + /* SETUP LINKS */ + ////////////////// + /*camera sensor to mipi-csis */ + links = camera_sd_entity->links; + if (links == NULL || + links->source->entity != camera_sd_entity || + links->sink->entity != mipi_sd_entity) { + LOGE("ERR(%s): Cannot make link camera sensor to mipi-csis", __func__); + return -1; + } + if (media_setup_link(media, links->source, links->sink, MEDIA_LNK_FL_ENABLED) < 0) { + LOGE("ERR(%s): Cannot make setup camera sensor to mipi-csis", __func__); + return -1; + } + LOGV("[LINK SUCCESS] camera seneor to mipi-csis"); + + /*mipi-csis to fimc-lite*/ + for(i = 0; i < mipi_sd_entity->num_links; i++) { + links = &mipi_sd_entity->links[i]; + LOGV("(%s), i=%d: links->source->entity : %p, mipi_sd_entity : %p", __func__, i, + links->source->entity, mipi_sd_entity); + LOGV("(%s), i=%d: links->sink->entity : %p, flite_sd_entity : %p", __func__, i, + links->sink->entity, flite_sd_entity); + if (links == NULL || + links->source->entity != mipi_sd_entity || + links->sink->entity != flite_sd_entity) { + continue; + } else if (media_setup_link(media, links->source, links->sink, MEDIA_LNK_FL_ENABLED) < 0) { + LOGE("ERR(%s): Cannot make setup mipi-csis to fimc-lite", __func__); + return -1; + } + } + LOGV("[LINK SUCCESS] mipi-csis to fimc-lite"); + + /*fimc-lite to gscaler capture device*/ + for(i = 0; i < gsc_cap_sd_entity->num_links; i++) { + links = &gsc_cap_sd_entity->links[i]; + LOGV("(%s), i=%d: links->source->entity : %p, flite_sd_entity : %p", __func__, i, + links->source->entity, flite_sd_entity); + LOGV("(%s), i=%d: links->sink->entity : %p, gsc_cap_sd_entity : %p", __func__, i, + links->sink->entity, gsc_cap_sd_entity); + if (links == NULL || + links->source->entity != flite_sd_entity || + links->sink->entity != gsc_cap_sd_entity) { + continue; + } else if (media_setup_link(media, links->source, links->sink, MEDIA_LNK_FL_ENABLED) < 0) { + LOGE("ERR(%s): Cannot make setup fimc-lite to gscaler capture device", __func__); + return -1; + } + } + LOGV("[LINK SUCCESS] fimc-lite to gscaler capture device"); + + /*gscaler capture device to gscaler video device*/ + for(i = 0; i < gsc_cap_vd_entity->num_links; i++) { + links = &gsc_cap_vd_entity->links[i]; + LOGV("(%s), i=%d: links->source->entity : %p, gsc_cap_sd_entity : %p", __func__, i, + links->source->entity, gsc_cap_sd_entity); + LOGV("(%s), i=%d: links->sink->entity : %p, gsc_cap_vd_entity : %p", __func__, i, + links->sink->entity, gsc_cap_vd_entity); + if (links == NULL || + links->source->entity != gsc_cap_sd_entity || + links->sink->entity != gsc_cap_vd_entity) { + continue; + } else if (media_setup_link(media, links->source, links->sink, MEDIA_LNK_FL_ENABLED) < 0) { + LOGE("ERR(%s): Cannot make setup gscaler capture device to gscaler video device", __func__); + return -1; + } + } + LOGV("[LINK SUCCESS] gscaler capture device to gscaler video device"); +#else +////////////////////////////// +// internal IS +////////////////////////////// + ////////////////// + /* GET ENTITIES */ + ////////////////// + /* ISP sensor subdev */ + memset(&node, 0x00, sizeof(node)); + strcpy(node, ISP_SENSOR_ENTITY_NAME); + isp_sensor_entity = media_get_entity_by_name(media, node, strlen(node)); + + /* ISP front subdev */ + memset(&node, 0x00, sizeof(node)); + strcpy(node, ISP_FRONT_ENTITY_NAME); + isp_front_entity = media_get_entity_by_name(media, node, strlen(node)); + + /* ISP back subdev */ + memset(&node, 0x00, sizeof(node)); + strcpy(node, ISP_BACK_ENTITY_NAME); + isp_back_entity = media_get_entity_by_name(media, node, strlen(node)); + + + /* ISP ScalerC video node */ + memset(&node, 0x00, sizeof(node)); + strcpy(node, ISP_VIDEO_SCALERC_NAME); + isp_scalerc_entity = media_get_entity_by_name(media, node, strlen(node)); + + /* ISP ScalerP video node */ + memset(&node, 0x00, sizeof(node)); + strcpy(node, ISP_VIDEO_SCALERP_NAME); + isp_scalerp_entity = media_get_entity_by_name(media, node, strlen(node)); + + /* ISP 3DNR video node */ + memset(&node, 0x00, sizeof(node)); + strcpy(node, ISP_VIDEO_3DNR_NAME); + isp_3dnr_entity = media_get_entity_by_name(media, node, strlen(node)); + + LOGV("isp_sensor_entity : numlink : %d", isp_sensor_entity->num_links); + LOGV("isp_front_entity : numlink : %d", isp_front_entity->num_links); + LOGV("isp_back_entity : numlink : %d", isp_back_entity->num_links); + LOGV("isp_scalerc_entity : numlink : %d", isp_scalerc_entity->num_links); + LOGV("isp_scalerp_entity : numlink : %d", isp_scalerp_entity->num_links); + LOGV("isp_3dnr_entity : numlink : %d", isp_3dnr_entity->num_links); + + ////////////////// + /* SETUP LINKS */ + ////////////////// + /* SENSOR TO FRONT */ + links = isp_sensor_entity->links; + if (links == NULL || + links->source->entity != isp_sensor_entity || + links->sink->entity != isp_front_entity) { + LOGE("[ERR] Can not make link isp_sensor to isp_front\n"); + return -1; + } + if(media_setup_link(media, links->source, links->sink, MEDIA_LNK_FL_ENABLED) < 0) { + LOGE("[ERR] Can not make setup isp_sensor to isp_front\n"); + return -1; + } + LOGV("[LINK SUCCESS] Sensor to front"); + + /* FRONT TO BACK */ + for (i = 0; i < isp_front_entity->num_links; i++){ + links = &isp_front_entity->links[i]; + if (links == NULL || + links->source->entity != isp_front_entity || + links->sink->entity != isp_back_entity) { + LOGV("(%s), i=%d: links->source->entity : %p, isp_front_entity : %p", __func__, i, + links->source->entity, isp_front_entity); + LOGV("(%s), i=%d: links->sink->entity : %p, isp_back_entity : %p", __func__, i, + links->sink->entity, isp_back_entity); + continue; + } else if(media_setup_link(media, links->source, links->sink, MEDIA_LNK_FL_ENABLED) < 0) { + LOGE("[ERR] Can not make setup isp_front to isp_back\n"); + return -1; + } + } + LOGV("[LINK SUCCESS] front to back"); + + /* BACK TO ScalerP Video*/ + for (i = 0; i < isp_back_entity->num_links; i++){ + links = &isp_back_entity->links[i]; + if (links == NULL || + links->source->entity != isp_back_entity || + links->sink->entity != isp_scalerp_entity) { + LOGV("(%s), i=%d: links->source->entity : %p, isp_front_entity : %p", __func__, i, + links->source->entity, isp_front_entity); + LOGV("(%s), i=%d: links->sink->entity : %p, isp_back_entity : %p", __func__, i, + links->sink->entity, isp_back_entity); + continue; + } + if(media_setup_link(media, links->source, links->sink, MEDIA_LNK_FL_ENABLED) < 0) { + LOGE("[ERR] Can not make setup isp_back to scalerP\n"); + return -1; + } + } + LOGV("[LINK SUCCESS] back to scalerP"); +#endif + + m_gsc_vd_fd = gsc_cap_open(0); + cam_fd1 = m_gsc_vd_fd; + if (m_gsc_vd_fd < 0) { + LOGE("ERR(%s):Cannot open %s (error : %s)", __func__, PFX_NODE_GSC, strerror(errno)); + return -1; + } + +#ifndef GAIA_FW_BETA + if (!v4l2_gsc_cap_enuminput(m_gsc_vd_fd, index)) { + LOGE("m_gsc_vd_fd(%d) v4l2_gsc_cap_enuminput fail", m_gsc_vd_fd); + return -1; + } + + ret = v4l2_gsc_cap_s_input(m_gsc_vd_fd, index); + CHECK(ret); +#endif + + m_camera_id = index; + + switch (m_camera_id) { + case CAMERA_ID_FRONT: + m_preview_max_width = MAX_FRONT_CAMERA_PREVIEW_WIDTH; + m_preview_max_height = MAX_FRONT_CAMERA_PREVIEW_HEIGHT; + m_snapshot_max_width = MAX_FRONT_CAMERA_SNAPSHOT_WIDTH; + m_snapshot_max_height = MAX_FRONT_CAMERA_SNAPSHOT_HEIGHT; + break; + + case CAMERA_ID_BACK: + m_preview_max_width = MAX_BACK_CAMERA_PREVIEW_WIDTH; + m_preview_max_height = MAX_BACK_CAMERA_PREVIEW_HEIGHT; + m_snapshot_max_width = MAX_BACK_CAMERA_SNAPSHOT_WIDTH; + m_snapshot_max_height = MAX_BACK_CAMERA_SNAPSHOT_HEIGHT; + break; + } + + //setExifFixedAttribute(); + } + return 0; +} + +void SecCamera::resetCamera() +{ + LOGV("%s :", __func__); + DestroyCamera(); + CreateCamera(m_camera_id); +} + +bool SecCamera::DestroyCamera() +{ + LOGV("%s :", __func__); + + if (m_flagCreate) { + + stopRecord(); + + /* close m_gsc_vd_fd after stopRecord() because stopRecord() + * uses m_gsc_vd_fd to change frame rate + */ + LOGI("DestroyCamera: m_gsc_vd_fd(%d)", m_gsc_vd_fd); + if (m_gsc_vd_fd > -1) { + close(m_gsc_vd_fd); + m_gsc_vd_fd = -1; + } + + LOGI("DestroyCamera: m_cam_fd2(%d)", m_cam_fd2); + if (m_cam_fd2 > -1) { + close(m_cam_fd2); + m_cam_fd2 = -1; + } + + m_flagCreate = 0; + } else + LOGI("%s : already deinitialized", __func__); + + return 0; +} + +int SecCamera::getCameraFd(void) +{ + return m_gsc_vd_fd; +} + +unsigned char* SecCamera::getPictureVaddr(void) +{ + return m_picture_vaddr; +} + +int SecCamera::startPreview(void) +{ + v4l2_streamparm streamparm; + struct sec_cam_parm *parms; + int ret; + + parms = (struct sec_cam_parm*)&streamparm.parm.raw_data; + LOGV("%s :", __func__); + + // check preview is aleady started. + if (m_flag_camera_start > 0) { + LOGE("ERR(%s):Preview was already started", __func__); + return 0; + } + + if (m_gsc_vd_fd <= 0) { + LOGE("ERR(%s):Camera was closed", __func__); + return -1; + } + + memset(&m_events_c, 0, sizeof(m_events_c)); + m_events_c.fd = m_gsc_vd_fd; + m_events_c.events = POLLIN | POLLERR; + +#ifndef GAIA_FW_BETA + /* enum_fmt, s_fmt sample */ + ret = v4l2_gsc_cap_enum_fmt(m_gsc_vd_fd, m_preview_v4lformat); + CHECK(ret); + + int Internal_is = !strncmp((const char*)getCameraSensorName(), "ISP Camera", 10); + LOGV("Internal_is(%d), %s", Internal_is, (const char*)getCameraSensorName()); + + if (Internal_is) { + if (!m_recording_en) + v4l2_gsc_cap_s_fmt_is(m_gsc_vd_fd, m_preview_width, m_preview_height, + m_preview_v4lformat, (enum v4l2_field) IS_MODE_PREVIEW_STILL); + else + v4l2_gsc_cap_s_fmt_is(m_gsc_vd_fd, m_recording_width, m_recording_height, + m_preview_v4lformat, (enum v4l2_field) IS_MODE_PREVIEW_STILL); + + } + + ret = v4l2_gsc_cap_s_fmt(m_gsc_vd_fd, m_preview_width, m_preview_height, m_preview_v4lformat, V4L2_FIELD_ANY, PREVIEW_NUM_PLANE); + CHECK(ret); + + if (Internal_is) { + if (!m_recording_en) + ret = v4l2_gsc_cap_s_ctrl(m_gsc_vd_fd, V4L2_CID_IS_S_SCENARIO_MODE, IS_MODE_PREVIEW_STILL); + else + ret = v4l2_gsc_cap_s_ctrl(m_gsc_vd_fd, V4L2_CID_IS_S_SCENARIO_MODE, IS_MODE_PREVIEW_STILL); + } + CHECK(ret); + + ret = v4l2_gsc_cap_s_ctrl(m_gsc_vd_fd, V4L2_CID_CACHEABLE, 1); + CHECK(ret); +#endif + + ret = v4l2_gsc_cap_reqbufs(m_gsc_vd_fd, V4L2_BUF_TYPE, MAX_BUFFERS); + CHECK(ret); + + LOGV("%s : m_preview_width: %d m_preview_height: %d m_angle: %d", + __func__, m_preview_width, m_preview_height, m_angle); + + LOGV("m_camera_id : %d", m_camera_id); + + /* start with all buffers in queue */ + for (int i = 0; i < MAX_BUFFERS; i++) { + ret = v4l2_gsc_cap_qbuf(m_gsc_vd_fd, m_preview_width, m_preview_height, m_buffers_preview, i, PREVIEW_NUM_PLANE); + CHECK(ret); + } + + ret = v4l2_gsc_cap_streamon(m_gsc_vd_fd); + CHECK(ret); + + m_flag_camera_start = 1; +/* TO DO : Frame Rate set is will be availeable. + if (setFrameRate(m_params->capture.timeperframe.denominator) < 0) + LOGE("ERR(%s):Fail on setFrameRate(%d)", + __func__, m_params->capture.timeperframe.denominator); +*/ + LOGV("%s: got the first frame of the preview", __func__); + + return 0; +} + +int SecCamera::stopPreview(void) +{ + int ret; + + LOGV("%s :", __func__); + + if (m_flag_camera_start == 0) { + LOGW("%s: doing nothing because m_flag_camera_start is zero", __func__); + return 0; + } + + if (m_params->flash_mode == FLASH_MODE_TORCH) + setFlashMode(FLASH_MODE_OFF); + + if (m_gsc_vd_fd <= 0) { + LOGE("ERR(%s):Camera was closed", __func__); + return -1; + } + + ret = v4l2_gsc_cap_streamoff(m_gsc_vd_fd); + CHECK(ret); + + close_buffers(m_buffers_preview); + + v4l2_gsc_cap_reqbufs(m_gsc_vd_fd, V4L2_BUF_TYPE, 0); + + m_flag_camera_start = 0; + + return ret; +} + +//Recording +int SecCamera::startRecord(void) +{ + int ret, i; + + LOGV("%s :", __func__); + + // aleady started + if (m_flag_record_start > 0) { + LOGE("ERR(%s):Preview was already started", __func__); + return 0; + } + + if (m_cam_fd2 <= 0) { + LOGE("ERR(%s):Camera was closed", __func__); + return -1; + } + + /* enum_fmt, s_fmt sample */ + ret = v4l2_gsc_cap_enum_fmt(m_cam_fd2, RECORD_PIX_FMT); + CHECK(ret); + + LOGI("%s: m_recording_width = %d, m_recording_height = %d", + __func__, m_recording_width, m_recording_height); + + int Internal_is = !strncmp((const char*)getCameraSensorName(), "ISP Camera", 10); + LOGV("Internal_is(%d), %s", Internal_is, (const char*)getCameraSensorName()); + +// if (Internal_is) +// v4l2_gsc_cap_s_fmt_is(m_cam_fd2, m_recording_width, m_recording_height, RECORD_PIX_FMT, (enum v4l2_field) IS_MODE_CAPTURE_VIDEO); + + ret = v4l2_gsc_cap_s_fmt(m_cam_fd2, m_recording_width, + m_recording_height, RECORD_PIX_FMT, V4L2_FIELD_ANY, RECORD_NUM_PLANE); + CHECK(ret); + + ret = v4l2_gsc_cap_reqbufs(m_cam_fd2, V4L2_BUF_TYPE, MAX_BUFFERS); + CHECK(ret); + + /* start with all buffers in queue */ + for (i = 0; i < MAX_BUFFERS; i++) { + ret = v4l2_gsc_cap_qbuf(m_cam_fd2, m_recording_width, m_recording_height, m_buffers_record, i, RECORD_NUM_PLANE); + CHECK(ret); + } + + // Get and throw away the first frame since it is often garbled. + memset(&m_events_c2, 0, sizeof(m_events_c2)); + m_events_c2.fd = m_cam_fd2; + m_events_c2.events = POLLIN | POLLERR; + + ret = v4l2_gsc_cap_streamon(m_cam_fd2); + CHECK(ret); + + m_flag_record_start = 1; + + return 0; +} + +int SecCamera::stopRecord(void) +{ + int ret; + + LOGV("%s :", __func__); + + if (m_flag_record_start == 0) { + LOGW("%s: doing nothing because m_flag_record_start is zero", __func__); + return 0; + } + + if (m_cam_fd2 <= 0) { + LOGE("ERR(%s):Camera was closed", __func__); + return -1; + } + + m_flag_record_start = 0; + + ret = v4l2_gsc_cap_streamoff(m_cam_fd2); + CHECK(ret); + + close_buffers(m_buffers_record); + + v4l2_gsc_cap_reqbufs(m_cam_fd2, V4L2_BUF_TYPE, 0); + + return 0; +} + +int SecCamera::getRecordAddr(int index, SecBuffer *buffer) +{ + buffer->phys.extP[0] = (unsigned int)m_buffers_record[index].phys.extP[0]; + buffer->phys.extP[1] = (unsigned int)(m_buffers_record[index].phys.extP[0] + (m_recording_width * m_recording_height)); + return 0; +} + +int SecCamera::getPreviewAddr(int index, SecBuffer *buffer) +{ + buffer->phys.extP[0] = (unsigned int)m_buffers_preview[index].phys.extP[0]; + buffer->phys.extP[1] = (unsigned int)m_buffers_preview[index].phys.extP[1]; + buffer->virt.extP[0] = m_buffers_preview[index].virt.extP[0]; + return 0; +} + +void SecCamera::setUserBufferAddr(void *ptr, int index, int mode) +{ + if (mode == PREVIEW_MODE) { + m_buffers_preview[index].virt.extP[0] = (char *)((unsigned int *)ptr)[0]; + m_buffers_preview[index].virt.extP[1] = (char *)((unsigned int *)ptr)[1]; + m_buffers_preview[index].virt.extP[2] = (char *)((unsigned int *)ptr)[2]; + } else if (mode == RECORD_MODE) { + m_buffers_record[index].virt.extP[0] = (char *)ptr; + m_buffers_record[index].virt.extP[1] = (char *)ptr + ((ALIGN(m_recording_width, 16) * ALIGN(m_recording_height, 16))); + } else + LOGE("%s: Invalid fd!!!", __func__); +} + +int SecCamera::getPreview() +{ + int index; + int ret; + + LOGV("%s: ", __func__); + if (m_flag_camera_start == 0 || gsc_cap_poll(&m_events_c) == 0) { + LOGE("ERR(%s):Start Camera Device Reset", __func__); + /* + * When there is no data for more than 1 second from the camera we inform + * the FIMC driver by calling v4l2_gsc_cap_s_input() with a special value = 1000 + * FIMC driver identify that there is something wrong with the camera + * and it restarts the sensor. + */ + stopPreview(); + /* Reset Only Camera Device */ + ret = v4l2_gsc_cap_querycap(m_gsc_vd_fd); + CHECK(ret); +#ifndef GAIA_FW_BETA + if (v4l2_gsc_cap_enuminput(m_gsc_vd_fd, m_camera_id)) + return -1; + ret = v4l2_gsc_cap_s_input(m_gsc_vd_fd, 1000); + CHECK(ret); +#endif + m_preview_state = 0; + return -1; + ret = startPreview(); + if (ret < 0) { + LOGE("ERR(%s): startPreview() return %d", __func__, ret); + return 0; + } + } + + index = v4l2_gsc_cap_dqbuf(m_gsc_vd_fd, PREVIEW_NUM_PLANE); + if (!(0 <= index && index < MAX_BUFFERS)) { + LOGE("ERR(%s):wrong index = %d", __func__, index); + return -1; + } + + return index; +} + +int SecCamera::setPreviewFrame(int index) +{ + int ret; + ret = v4l2_gsc_cap_qbuf(m_gsc_vd_fd, m_preview_width, m_preview_height, m_buffers_preview, index, PREVIEW_NUM_PLANE); + CHECK(ret); + + return ret; +} + +int SecCamera::getRecordFrame() +{ + if (m_flag_record_start == 0) { + LOGE("%s: m_flag_record_start is 0", __func__); + return -1; + } + + gsc_cap_poll(&m_events_c2); + int index = v4l2_gsc_cap_dqbuf(m_cam_fd2, RECORD_NUM_PLANE); + if (!(0 <= index && index < MAX_BUFFERS)) { + LOGE("ERR(%s):wrong index = %d", __func__, index); + return -1; + } + + return index; +} + +int SecCamera::releaseRecordFrame(int index) +{ + if (!m_flag_record_start) { + /* this can happen when recording frames are returned after + * the recording is stopped at the driver level. we don't + * need to return the buffers in this case and we've seen + * cases where fimc could crash if we called qbuf and it + * wasn't expecting it. + */ + LOGI("%s: recording not in progress, ignoring", __func__); + return 0; + } + + return v4l2_gsc_cap_qbuf(m_cam_fd2, m_recording_width, m_recording_height, m_buffers_record, index, RECORD_NUM_PLANE); +} + +int SecCamera::setPreviewSize(int width, int height, int pixel_format) +{ + LOGV("%s(width(%d), height(%d), format(%d))", __func__, width, height, pixel_format); + + int v4lpixelformat = pixel_format; + +#if defined(LOG_NDEBUG) && LOG_NDEBUG == 0 + if (v4lpixelformat == V4L2_PIX_FMT_YUV420) + LOGV("PreviewFormat:V4L2_PIX_FMT_YUV420"); + else if (v4lpixelformat == V4L2_PIX_FMT_YVU420) + LOGV("PreviewFormat:V4L2_PIX_FMT_YVU420"); + else if (v4lpixelformat == V4L2_PIX_FMT_YVU420M) + LOGV("PreviewFormat:V4L2_PIX_FMT_YVU420M"); + else if (v4lpixelformat == V4L2_PIX_FMT_NV12) + LOGV("PreviewFormat:V4L2_PIX_FMT_NV12"); + else if (v4lpixelformat == V4L2_PIX_FMT_NV12M) + LOGV("PreviewFormat:V4L2_PIX_FMT_NV12M"); + else if (v4lpixelformat == V4L2_PIX_FMT_NV12T) + LOGV("PreviewFormat:V4L2_PIX_FMT_NV12T"); + else if (v4lpixelformat == V4L2_PIX_FMT_NV21) + LOGV("PreviewFormat:V4L2_PIX_FMT_NV21"); + else if (v4lpixelformat == V4L2_PIX_FMT_YUV422P) + LOGV("PreviewFormat:V4L2_PIX_FMT_YUV422P"); + else if (v4lpixelformat == V4L2_PIX_FMT_YUYV) + LOGV("PreviewFormat:V4L2_PIX_FMT_YUYV"); + else if (v4lpixelformat == V4L2_PIX_FMT_RGB565) + LOGV("PreviewFormat:V4L2_PIX_FMT_RGB565"); + else + LOGV("PreviewFormat:UnknownFormat"); +#endif + m_preview_width = width; + m_preview_height = height; + m_preview_v4lformat = v4lpixelformat; + + return 0; +} + +int SecCamera::getPreviewSize(int *width, int *height, int *frame_size) +{ + *width = m_preview_width; + *height = m_preview_height; + *frame_size = FRAME_SIZE(V4L2_PIX_2_HAL_PIXEL_FORMAT(m_preview_v4lformat), *width, *height); + return 0; +} + +int SecCamera::getPreviewMaxSize(int *width, int *height) +{ + *width = m_preview_max_width; + *height = m_preview_max_height; + + return 0; +} + +int SecCamera::getPreviewPixelFormat(void) +{ + return m_preview_v4lformat; +} + +/* + * Devide getJpeg() as two funcs, setSnapshotCmd() & getJpeg() because of the shutter sound timing. + * Here, just send the capture cmd to camera ISP to start JPEG capture. + */ +int SecCamera::setSnapshotCmd(void) +{ + LOGV("%s :", __func__); + + int ret = 0; + + if (m_gsc_vd_fd <= 0) { + LOGE("ERR(%s):Camera was closed", __func__); + return 0; + } + + if (m_flag_camera_start > 0) { + LOGW("WARN(%s):Camera was in preview, should have been stopped", __func__); + stopPreview(); + } + + memset(&m_events_c, 0, sizeof(m_events_c)); + m_events_c.fd = m_gsc_vd_fd; + m_events_c.events = POLLIN | POLLERR; + + int nframe = 1; + + ret = v4l2_gsc_cap_enum_fmt(m_gsc_vd_fd,m_snapshot_v4lformat); + CHECK(ret); + + ret = v4l2_gsc_cap_reqbufs(m_gsc_vd_fd, V4L2_BUF_TYPE, nframe); + CHECK(ret); + +#ifdef GAIA_FW_BETA + ret = v4l2_gsc_cap_querybuf(m_gsc_vd_fd, &m_capture_buf, V4L2_BUF_TYPE, 1, 2); + CHECK(ret); +#endif + + ret = v4l2_gsc_cap_qbuf(m_gsc_vd_fd, m_snapshot_width, m_snapshot_height, m_buffers_preview, 0, 1); + CHECK(ret); + + ret = v4l2_gsc_cap_streamon(m_gsc_vd_fd); + CHECK(ret); + + return 0; +} + +int SecCamera::endSnapshot(void) +{ + int ret; + + LOGI("%s :", __func__); + if (m_capture_buf.virt.extP[0]) { + munmap(m_capture_buf.virt.extP[0], m_capture_buf.size.extS[0]); + LOGI("munmap():virt. addr %p size = %d", + m_capture_buf.virt.extP[0], m_capture_buf.size.extS[0]); + m_capture_buf.virt.extP[0] = NULL; + m_capture_buf.size.extS[0] = 0; + } + return 0; +} + +/* + * Set Jpeg quality & exif info and get JPEG data from camera ISP + */ +unsigned char* SecCamera::getJpeg(int *jpeg_size, unsigned int *phyaddr) +{ + int index, ret = 0; + unsigned char *addr; + SecBuffer jpegAddr; + + // capture + ret = gsc_cap_poll(&m_events_c); + CHECK_PTR(ret); + index = v4l2_gsc_cap_dqbuf(m_gsc_vd_fd, 1); + + if (index != 0) { + LOGE("ERR(%s):wrong index = %d", __func__, index); + return NULL; + } + + *jpeg_size = v4l2_gsc_cap_g_ctrl(m_gsc_vd_fd, V4L2_CID_CAM_JPEG_MAIN_SIZE); + CHECK_PTR(*jpeg_size); + + int main_offset = v4l2_gsc_cap_g_ctrl(m_gsc_vd_fd, V4L2_CID_CAM_JPEG_MAIN_OFFSET); + CHECK_PTR(main_offset); + m_postview_offset = v4l2_gsc_cap_g_ctrl(m_gsc_vd_fd, V4L2_CID_CAM_JPEG_POSTVIEW_OFFSET); + CHECK_PTR(m_postview_offset); + + ret = v4l2_gsc_cap_s_ctrl(m_gsc_vd_fd, V4L2_CID_STREAM_PAUSE, 0); + CHECK_PTR(ret); + LOGV("\nsnapshot dqueued buffer = %d snapshot_width = %d snapshot_height = %d, size = %d", + index, m_snapshot_width, m_snapshot_height, *jpeg_size); + + addr = (unsigned char*)(m_capture_buf.virt.extP[0]) + main_offset; + getPreviewAddr(index, &jpegAddr); + *phyaddr = jpegAddr.phys.extP[0] + m_postview_offset; + + ret = v4l2_gsc_cap_streamoff(m_gsc_vd_fd); + CHECK_PTR(ret); + + return addr; +} + +int SecCamera::getExif(unsigned char *pExifDst, unsigned char *pThumbSrc) +{ + /*TODO : to be added HW JPEG code. */ + return 0; +} + +void SecCamera::getPostViewConfig(int *width, int *height, int *size) +{ + *width = m_snapshot_width; + *height = m_snapshot_height; + *size = FRAME_SIZE(V4L2_PIX_2_HAL_PIXEL_FORMAT(m_snapshot_v4lformat), *width, *height); + LOGV("[5B] m_preview_width : %d, mPostViewWidth = %d mPostViewHeight = %d mPostViewSize = %d", + m_preview_width, *width, *height, *size); +} + +void SecCamera::getThumbnailConfig(int *width, int *height, int *size) +{ + *width = m_jpeg_thumbnail_width; + *height = m_jpeg_thumbnail_height; + *size = FRAME_SIZE(V4L2_PIX_2_HAL_PIXEL_FORMAT(m_snapshot_v4lformat), *width, *height); +} + +int SecCamera::getPostViewOffset(void) +{ + return m_postview_offset; +} + +int SecCamera::getSnapshotAndJpeg(unsigned char *yuv_buf, unsigned char *jpeg_buf, + unsigned int *output_size) +{ + LOGV("%s :", __func__); + + int index; + unsigned char *addr; + int ret = 0; + + if (m_gsc_vd_fd <= 0) { + LOGE("ERR(%s):Camera was closed", __func__); + return -1; + } + + if (m_flag_camera_start > 0) { + LOGW("WARN(%s):Camera was in preview, should have been stopped", __func__); + stopPreview(); + } + + memset(&m_events_c, 0, sizeof(m_events_c)); + m_events_c.fd = m_gsc_vd_fd; + m_events_c.events = POLLIN | POLLERR; + +#if defined(LOG_NDEBUG) && LOG_NDEBUG == 0 + if (m_snapshot_v4lformat == V4L2_PIX_FMT_YUV420) + LOGV("SnapshotFormat:V4L2_PIX_FMT_YUV420"); + else if (m_snapshot_v4lformat == V4L2_PIX_FMT_NV12) + LOGV("SnapshotFormat:V4L2_PIX_FMT_NV12"); + else if (m_snapshot_v4lformat == V4L2_PIX_FMT_NV12T) + LOGV("SnapshotFormat:V4L2_PIX_FMT_NV12T"); + else if (m_snapshot_v4lformat == V4L2_PIX_FMT_NV21) + LOGV("SnapshotFormat:V4L2_PIX_FMT_NV21"); + else if (m_snapshot_v4lformat == V4L2_PIX_FMT_YUV422P) + LOGV("SnapshotFormat:V4L2_PIX_FMT_YUV422P"); + else if (m_snapshot_v4lformat == V4L2_PIX_FMT_YUYV) + LOGV("SnapshotFormat:V4L2_PIX_FMT_YUYV"); + else if (m_snapshot_v4lformat == V4L2_PIX_FMT_UYVY) + LOGV("SnapshotFormat:V4L2_PIX_FMT_UYVY"); + else if (m_snapshot_v4lformat == V4L2_PIX_FMT_RGB565) + LOGV("SnapshotFormat:V4L2_PIX_FMT_RGB565"); + else + LOGV("SnapshotFormat:UnknownFormat"); +#endif + + int nframe = 1; + + ret = v4l2_gsc_cap_enum_fmt(m_gsc_vd_fd, m_snapshot_v4lformat); + CHECK(ret); + + int Internal_is = !strncmp((const char*)getCameraSensorName(), "ISP Camera", 10); + LOGV("Internal_is(%d), %s", Internal_is, (const char*)getCameraSensorName()); + + ret = v4l2_gsc_cap_s_fmt_cap(m_gsc_vd_fd, m_snapshot_width, m_snapshot_height, m_snapshot_v4lformat); + CHECK(ret); + + ret = v4l2_gsc_cap_s_ctrl(m_gsc_vd_fd, V4L2_CID_CACHEABLE, 1); + CHECK(ret); + ret = v4l2_gsc_cap_reqbufs(m_gsc_vd_fd, V4L2_BUF_TYPE, nframe); + CHECK(ret); + +#ifdef GAIA_FW_BETA + ret = v4l2_gsc_cap_querybuf(m_gsc_vd_fd, &m_capture_buf, V4L2_BUF_TYPE, 1, 2); + CHECK(ret); +#endif + + struct SecBuffer my_buf; + my_buf.virt.p = (char *)yuv_buf; + +#ifndef GAIA_FW_BETA + ret = v4l2_gsc_cap_qbuf(m_gsc_vd_fd, m_snapshot_width, m_snapshot_height, &my_buf, 0, 1); + CHECK(ret); +#else + ret = v4l2_gsc_cap_qbuf(m_gsc_vd_fd, m_snapshot_width, m_snapshot_height, &m_capture_buf, 0, 1); + CHECK(ret); +#endif + + ret = v4l2_gsc_cap_streamon(m_gsc_vd_fd); + CHECK(ret); + + gsc_cap_poll(&m_events_c); + + index = v4l2_gsc_cap_dqbuf(m_gsc_vd_fd, 1); + +#ifdef GAIA_FW_BETA + ret = v4l2_gsc_cap_s_ctrl(m_gsc_vd_fd, V4L2_CID_STREAM_PAUSE, 0); + CHECK_PTR(ret); + LOGV("\nsnapshot dequeued buffer = %d snapshot_width = %d snapshot_height = %d", + index, m_snapshot_width, m_snapshot_height); + + yuv_buf = (unsigned char*)m_capture_buf.virt.extP[0]; +#endif + m_picture_vaddr = yuv_buf; + v4l2_gsc_cap_streamoff(m_gsc_vd_fd); + + /* TODO: JPEG encode for smdk5250 */ + + return 0; +} + +int SecCamera::setSnapshotSize(int width, int height) +{ + LOGV("%s(width(%d), height(%d))", __func__, width, height); + + m_snapshot_width = width; + m_snapshot_height = height; + + return 0; +} + +int SecCamera::getSnapshotSize(int *width, int *height, int *frame_size) +{ + *width = m_snapshot_width; + *height = m_snapshot_height; + + int frame = 0; + + frame = FRAME_SIZE(V4L2_PIX_2_HAL_PIXEL_FORMAT(m_snapshot_v4lformat), *width, *height); + + // set it big. + if (frame == 0) + frame = m_snapshot_width * m_snapshot_height * BPP; + + *frame_size = frame; + + return 0; +} + +int SecCamera::getSnapshotMaxSize(int *width, int *height) +{ + switch (m_camera_id) { + case CAMERA_ID_FRONT: + m_snapshot_max_width = MAX_FRONT_CAMERA_SNAPSHOT_WIDTH; + m_snapshot_max_height = MAX_FRONT_CAMERA_SNAPSHOT_HEIGHT; + break; + + default: + case CAMERA_ID_BACK: + m_snapshot_max_width = MAX_BACK_CAMERA_SNAPSHOT_WIDTH; + m_snapshot_max_height = MAX_BACK_CAMERA_SNAPSHOT_HEIGHT; + break; + } + + *width = m_snapshot_max_width; + *height = m_snapshot_max_height; + + return 0; +} + +int SecCamera::setSnapshotPixelFormat(int pixel_format) +{ + int v4lpixelformat = pixel_format; + + if (m_snapshot_v4lformat != v4lpixelformat) { + m_snapshot_v4lformat = v4lpixelformat; + } + +#if defined(LOG_NDEBUG) && LOG_NDEBUG == 0 + if (m_snapshot_v4lformat == V4L2_PIX_FMT_YUV420) + LOGE("%s : SnapshotFormat:V4L2_PIX_FMT_YUV420", __func__); + else if (m_snapshot_v4lformat == V4L2_PIX_FMT_NV12) + LOGD("%s : SnapshotFormat:V4L2_PIX_FMT_NV12", __func__); + else if (m_snapshot_v4lformat == V4L2_PIX_FMT_NV12T) + LOGD("%s : SnapshotFormat:V4L2_PIX_FMT_NV12T", __func__); + else if (m_snapshot_v4lformat == V4L2_PIX_FMT_NV21) + LOGD("%s : SnapshotFormat:V4L2_PIX_FMT_NV21", __func__); + else if (m_snapshot_v4lformat == V4L2_PIX_FMT_YUV422P) + LOGD("%s : SnapshotFormat:V4L2_PIX_FMT_YUV422P", __func__); + else if (m_snapshot_v4lformat == V4L2_PIX_FMT_YUYV) + LOGD("%s : SnapshotFormat:V4L2_PIX_FMT_YUYV", __func__); + else if (m_snapshot_v4lformat == V4L2_PIX_FMT_UYVY) + LOGD("%s : SnapshotFormat:V4L2_PIX_FMT_UYVY", __func__); + else if (m_snapshot_v4lformat == V4L2_PIX_FMT_RGB565) + LOGD("%s : SnapshotFormat:V4L2_PIX_FMT_RGB565", __func__); + else + LOGD("SnapshotFormat:UnknownFormat"); +#endif + return 0; +} + +int SecCamera::getSnapshotPixelFormat(void) +{ + return m_snapshot_v4lformat; +} + +int SecCamera::getCameraId(void) +{ + return m_camera_id; +} + +int SecCamera::setAutofocus(void) +{ + LOGV("%s :", __func__); + + if (m_gsc_vd_fd <= 0) { + LOGE("ERR(%s):Camera was closed", __func__); + return -1; + } + + if (v4l2_gsc_cap_s_ctrl(m_gsc_vd_fd, V4L2_CID_CAMERA_SET_AUTO_FOCUS, AUTO_FOCUS_ON) < 0) { + LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_SET_AUTO_FOCUS", __func__); + return -1; + } + + return 0; +} + +int SecCamera::getAutoFocusResult(void) +{ + int af_result; + + af_result = v4l2_gsc_cap_g_ctrl(m_gsc_vd_fd, V4L2_CID_CAMERA_AUTO_FOCUS_RESULT); + + LOGV("%s : returning %d", __func__, af_result); + + return af_result; +} + +int SecCamera::cancelAutofocus(void) +{ + LOGV("%s :", __func__); + + if (m_gsc_vd_fd <= 0) { + LOGE("ERR(%s):Camera was closed", __func__); + return -1; + } + + return 0; +} + +int SecCamera::SetRotate(int angle) +{ + LOGE("%s(angle(%d))", __func__, angle); + + if (m_angle != angle) { + switch (angle) { + case -360: + case 0: + case 360: + m_angle = 0; + break; + + case -270: + case 90: + m_angle = 90; + break; + + case -180: + case 180: + m_angle = 180; + break; + + case -90: + case 270: + m_angle = 270; + break; + + default: + LOGE("ERR(%s):Invalid angle(%d)", __func__, angle); + return -1; + } + + if (m_flag_camera_start) { + if (v4l2_gsc_cap_s_ctrl(m_gsc_vd_fd, V4L2_CID_ROTATION, angle) < 0) { + LOGE("ERR(%s):Fail on V4L2_CID_ROTATION", __func__); + return -1; + } + } + } + + return 0; +} + +int SecCamera::getRotate(void) +{ + LOGV("%s : angle(%d)", __func__, m_angle); + return m_angle; +} + +int SecCamera::setFrameRate(int frame_rate) +{ + LOGV("%s(FrameRate(%d))", __func__, frame_rate); + + if (frame_rate < FRAME_RATE_AUTO || FRAME_RATE_MAX < frame_rate ) + LOGE("ERR(%s):Invalid frame_rate(%d)", __func__, frame_rate); + + m_params->capture.timeperframe.denominator = frame_rate; + if (m_flag_camera_start) { + if (v4l2_gsc_cap_s_ctrl(m_gsc_vd_fd, V4L2_CID_CAMERA_FRAME_RATE, frame_rate) < 0) { + LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_FRAME_RATE", __func__); + return -1; + } + } + + return 0; +} + +int SecCamera::setVerticalMirror(void) +{ + LOGV("%s :", __func__); + + if (m_gsc_vd_fd <= 0) { + LOGE("ERR(%s):Camera was closed", __func__); + return -1; + } + + if (v4l2_gsc_cap_s_ctrl(m_gsc_vd_fd, V4L2_CID_VFLIP, 0) < 0) { + LOGE("ERR(%s):Fail on V4L2_CID_VFLIP", __func__); + return -1; + } + + return 0; +} + +int SecCamera::setHorizontalMirror(void) +{ + LOGV("%s :", __func__); + + if (m_gsc_vd_fd <= 0) { + LOGE("ERR(%s):Camera was closed", __func__); + return -1; + } + + if (v4l2_gsc_cap_s_ctrl(m_gsc_vd_fd, V4L2_CID_HFLIP, 0) < 0) { + LOGE("ERR(%s):Fail on V4L2_CID_HFLIP", __func__); + return -1; + } + + return 0; +} + +int SecCamera::setWhiteBalance(int white_balance) +{ + LOGV("%s(white_balance(%d))", __func__, white_balance); + int Internal_is = !strncmp((const char*)getCameraSensorName(), "ISP Camera", 10); + + if (Internal_is) { + if (white_balance < IS_AWB_AUTO || IS_AWB_MAX <= white_balance) { + LOGE("ERR(%s):Invalid white_balance(%d)", __func__, white_balance); + return -1; + } + } else { + if (white_balance <= WHITE_BALANCE_BASE || WHITE_BALANCE_MAX <= white_balance) { + LOGE("ERR(%s):Invalid white_balance(%d)", __func__, white_balance); + return -1; + } + } + + if (m_params->white_balance != white_balance) { + m_params->white_balance = white_balance; + if (m_flag_camera_start) { + if (Internal_is) { + if (v4l2_gsc_cap_s_ctrl(m_gsc_vd_fd, V4L2_CID_IS_CAMERA_AWB_MODE, white_balance) < 0) { + LOGE("ERR(%s):Fail on V4L2_CID_IS_CAMERA_AWB_MODE", __func__); + return -1; + } + } else { + if (v4l2_gsc_cap_s_ctrl(m_gsc_vd_fd, V4L2_CID_CAMERA_WHITE_BALANCE, white_balance) < 0) { + LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_WHITE_BALANCE", __func__); + return -1; + } + } + } + } + + return 0; +} + +int SecCamera::getWhiteBalance(void) +{ + LOGV("%s : white_balance(%d)", __func__, m_params->white_balance); + return m_params->white_balance; +} + +int SecCamera::setBrightness(int brightness) +{ + LOGV("%s(brightness(%d))", __func__, brightness); + int Internal_is = !strncmp((const char*)getCameraSensorName(), "ISP Camera", 10); + + if (Internal_is) { + brightness += IS_BRIGHTNESS_DEFAULT; + if (brightness < IS_BRIGHTNESS_MINUS_2 || IS_BRIGHTNESS_PLUS2 < brightness) { + LOGE("ERR(%s):Invalid brightness(%d)", __func__, brightness); + return -1; + } + } else { + LOGW("WARN(%s):Not supported brightness setting", __func__); + return 0; + } + + if (m_params->brightness != brightness) { + m_params->brightness = brightness; + if (m_flag_camera_start) { + if (v4l2_gsc_cap_s_ctrl(m_gsc_vd_fd, V4L2_CID_IS_CAMERA_BRIGHTNESS, brightness) < EV_MINUS_4) { + LOGE("ERR(%s):Fail on V4L2_CID_IS_CAMERA_BRIGHTNESS", __func__); + return -1; + } + } + } + + return 0; +} + +int SecCamera::getBrightness(void) +{ + LOGV("%s : brightness(%d)", __func__, m_params->brightness); + return m_params->brightness; +} + +int SecCamera::setExposure(int exposure) +{ + LOGV("%s(exposure(%d))", __func__, exposure); + int Internal_is = !strncmp((const char*)getCameraSensorName(), "ISP Camera", 10); + + if (Internal_is) { + exposure += IS_EXPOSURE_DEFAULT; + if (exposure < IS_EXPOSURE_MINUS_2 || IS_EXPOSURE_PLUS2 < exposure) { + LOGE("ERR(%s):Invalid exposure(%d)", __func__, exposure); + return -1; + } + } else { + exposure += EV_DEFAULT; + if (exposure < EV_MINUS_4 || EV_PLUS_4 < exposure) { + LOGE("ERR(%s):Invalid exposure(%d)", __func__, exposure); + return -1; + } + } + + if (m_params->exposure != exposure) { + m_params->exposure = exposure; + if (m_flag_camera_start) { + if (Internal_is) { + if (v4l2_gsc_cap_s_ctrl(m_gsc_vd_fd, V4L2_CID_IS_CAMERA_EXPOSURE, exposure) < 0) { + LOGE("ERR(%s):Fail on V4L2_CID_IS_CAMERA_EXPOSURE", __func__); + return -1; + } + } else { + if (v4l2_gsc_cap_s_ctrl(m_gsc_vd_fd, V4L2_CID_CAMERA_BRIGHTNESS, exposure) < EV_MINUS_4) { + LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_BRIGHTNESS", __func__); + return -1; + } + } + } + } + + return 0; +} + +int SecCamera::getExposure(void) +{ + LOGV("%s : exposure(%d)", __func__, m_params->exposure); + return m_params->exposure; +} + +int SecCamera::setImageEffect(int image_effect) +{ + LOGV("%s(image_effect(%d))", __func__, image_effect); + int Internal_is = !strncmp((const char*)getCameraSensorName(), "ISP Camera", 10); + + if (Internal_is) { + if (image_effect < IS_IMAGE_EFFECT_DISABLE || IS_IMAGE_EFFECT_MAX <= image_effect) { + LOGE("ERR(%s):Invalid image_effect(%d)", __func__, image_effect); + return -1; + } + } else { + if (image_effect <= IMAGE_EFFECT_BASE || IMAGE_EFFECT_MAX <= image_effect) { + LOGE("ERR(%s):Invalid image_effect(%d)", __func__, image_effect); + return -1; + } + } + + if (m_params->effects != image_effect) { + m_params->effects = image_effect; + if (m_flag_camera_start) { + if (Internal_is) { + if (v4l2_gsc_cap_s_ctrl(m_gsc_vd_fd, V4L2_CID_IS_CAMERA_IMAGE_EFFECT, image_effect) < 0) { + LOGE("ERR(%s):Fail on V4L2_CID_IS_CAMERA_IMAGE_EFFECT", __func__); + return -1; + } + } else { + if (v4l2_gsc_cap_s_ctrl(m_gsc_vd_fd, V4L2_CID_CAMERA_EFFECT, image_effect) < 0) { + LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_EFFECT", __func__); + return -1; + } + } + } + } + + return 0; +} + +int SecCamera::getImageEffect(void) +{ + LOGV("%s : image_effect(%d)", __func__, m_params->effects); + return m_params->effects; +} + +int SecCamera::setAntiBanding(int anti_banding) +{ + LOGV("%s(anti_banding(%d))", __func__, anti_banding); + int Internal_is = !strncmp((const char*)getCameraSensorName(), "ISP Camera", 10); + + if (Internal_is) { + if (anti_banding < IS_AFC_DISABLE || IS_AFC_MAX <= anti_banding) { + LOGE("ERR(%s):Invalid anti_banding (%d)", __func__, anti_banding); + return -1; + } + } else { + if (anti_banding < ANTI_BANDING_AUTO || ANTI_BANDING_OFF < anti_banding) { + LOGE("ERR(%s):Invalid anti_banding (%d)", __func__, anti_banding); + return -1; + } + } + + if (m_anti_banding != anti_banding) { + m_anti_banding = anti_banding; + if (m_flag_camera_start) { + if (Internal_is) { + if (v4l2_gsc_cap_s_ctrl(m_gsc_vd_fd, V4L2_CID_IS_CAMERA_AFC_MODE, anti_banding) < 0) { + LOGE("ERR(%s):Fail on V4L2_CID_IS_CAMERA_AFC_MODE", __func__); + return -1; + } + } else { + if (v4l2_gsc_cap_s_ctrl(m_gsc_vd_fd, V4L2_CID_CAMERA_ANTI_BANDING, anti_banding) < 0) { + LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_ANTI_BANDING", __func__); + return -1; + } + } + } + } + + return 0; +} + +int SecCamera::setSceneMode(int scene_mode) +{ + LOGV("%s(scene_mode(%d))", __func__, scene_mode); + + if (scene_mode <= SCENE_MODE_BASE || SCENE_MODE_MAX <= scene_mode) { + LOGE("ERR(%s):Invalid scene_mode (%d)", __func__, scene_mode); + return -1; + } + + if (m_params->scene_mode != scene_mode) { + m_params->scene_mode = scene_mode; + if (m_flag_camera_start) { + if (v4l2_gsc_cap_s_ctrl(m_gsc_vd_fd, V4L2_CID_CAMERA_SCENE_MODE, scene_mode) < 0) { + LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_SCENE_MODE", __func__); + return -1; + } + } + } + + return 0; +} + +int SecCamera::getSceneMode(void) +{ + return m_params->scene_mode; +} + +int SecCamera::setFlashMode(int flash_mode) +{ + LOGV("%s(flash_mode(%d))", __func__, flash_mode); + int Internal_is = !strncmp((const char*)getCameraSensorName(), "ISP Camera", 10); + + if (Internal_is) { + if (flash_mode <= IS_FLASH_MODE_OFF || IS_FLASH_MODE_MAX <= flash_mode) { + LOGE("ERR(%s):Invalid flash_mode (%d)", __func__, flash_mode); + return -1; + } + } else { + if (flash_mode <= FLASH_MODE_BASE || FLASH_MODE_MAX <= flash_mode) { + LOGE("ERR(%s):Invalid flash_mode (%d)", __func__, flash_mode); + return -1; + } + } + + if (m_params->flash_mode != flash_mode) { + m_params->flash_mode = flash_mode; + if (m_flag_camera_start) { + if (Internal_is) { + if (v4l2_gsc_cap_s_ctrl(m_gsc_vd_fd, V4L2_CID_IS_CAMERA_FLASH_MODE, flash_mode) < 0) { + LOGE("ERR(%s):Fail on V4L2_CID_IS_CAMERA_FLASH_MODE", __func__); + return -1; + } + } else { + if (v4l2_gsc_cap_s_ctrl(m_gsc_vd_fd, V4L2_CID_CAMERA_FLASH_MODE, flash_mode) < 0) { + LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_FLASH_MODE", __func__); + return -1; + } + } + } + } + + return 0; +} + +int SecCamera::getFlashMode(void) +{ + return m_params->flash_mode; +} + +int SecCamera::setISO(int iso_value) +{ + LOGV("%s(iso_value(%d))", __func__, iso_value); + int Internal_is = !strncmp((const char*)getCameraSensorName(), "ISP Camera", 10); + + if (Internal_is) { + if (iso_value < IS_ISO_AUTO || IS_ISO_MAX <= iso_value) { + LOGE("ERR(%s):Invalid iso_value (%d)", __func__, iso_value); + return -1; + } + } else { + if (iso_value < ISO_AUTO || ISO_MAX <= iso_value) { + LOGE("ERR(%s):Invalid iso_value (%d)", __func__, iso_value); + return -1; + } + } + + if (m_params->iso != iso_value) { + m_params->iso = iso_value; + if (m_flag_camera_start) { + if (Internal_is) { + if (v4l2_gsc_cap_s_ctrl(m_gsc_vd_fd, V4L2_CID_IS_CAMERA_ISO, iso_value) < 0) { + LOGE("ERR(%s):Fail on V4L2_CID_IS_CAMERA_ISO", __func__); + return -1; + } + } else { + if (v4l2_gsc_cap_s_ctrl(m_gsc_vd_fd, V4L2_CID_CAMERA_ISO, iso_value) < 0) { + LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_ISO", __func__); + return -1; + } + } + } + } + + return 0; +} + +int SecCamera::getISO(void) +{ + return m_params->iso; +} + +int SecCamera::setContrast(int contrast_value) +{ + LOGV("%s(contrast_value(%d))", __func__, contrast_value); + int Internal_is = !strncmp((const char*)getCameraSensorName(), "ISP Camera", 10); + + if (Internal_is) { + if (contrast_value < IS_CONTRAST_AUTO || IS_CONTRAST_MAX <= contrast_value) { + LOGE("ERR(%s):Invalid contrast_value (%d)", __func__, contrast_value); + return -1; + } + } else { + if (contrast_value < CONTRAST_MINUS_2 || CONTRAST_MAX <= contrast_value) { + LOGE("ERR(%s):Invalid contrast_value (%d)", __func__, contrast_value); + return -1; + } + } + + if (m_params->contrast != contrast_value) { + m_params->contrast = contrast_value; + if (m_flag_camera_start) { + if (Internal_is) { + if (v4l2_gsc_cap_s_ctrl(m_gsc_vd_fd, V4L2_CID_IS_CAMERA_CONTRAST, contrast_value) < 0) { + LOGE("ERR(%s):Fail on V4L2_CID_IS_CAMERA_CONTRAST", __func__); + return -1; + } + } else { + if (v4l2_gsc_cap_s_ctrl(m_gsc_vd_fd, V4L2_CID_CAMERA_CONTRAST, contrast_value) < 0) { + LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_CONTRAST", __func__); + return -1; + } + } + } + } + + return 0; +} + +int SecCamera::getContrast(void) +{ + return m_params->contrast; +} + +int SecCamera::setSaturation(int saturation_value) +{ + LOGV("%s(saturation_value(%d))", __func__, saturation_value); + int Internal_is = !strncmp((const char*)getCameraSensorName(), "ISP Camera", 10); + + if (Internal_is) { + saturation_value += IS_SATURATION_DEFAULT; + if (saturation_value < IS_SATURATION_MINUS_2 || IS_SATURATION_MAX <= saturation_value) { + LOGE("ERR(%s):Invalid saturation_value (%d)", __func__, saturation_value); + return -1; + } + } else { + saturation_value += SATURATION_DEFAULT; + if (saturation_value < SATURATION_MINUS_2 || SATURATION_MAX <= saturation_value) { + LOGE("ERR(%s):Invalid saturation_value (%d)", __func__, saturation_value); + return -1; + } + } + + if (m_params->saturation != saturation_value) { + m_params->saturation = saturation_value; + if (m_flag_camera_start) { + if (Internal_is) { + if (v4l2_gsc_cap_s_ctrl(m_gsc_vd_fd, V4L2_CID_IS_CAMERA_SATURATION, saturation_value) < 0) { + LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_SATURATION", __func__); + return -1; + } + } else { + if (v4l2_gsc_cap_s_ctrl(m_gsc_vd_fd, V4L2_CID_CAMERA_SATURATION, saturation_value) < 0) { + LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_SATURATION", __func__); + return -1; + } + } + } + } + + return 0; +} + +int SecCamera::getSaturation(void) +{ + return m_params->saturation; +} + +int SecCamera::setSharpness(int sharpness_value) +{ + LOGV("%s(sharpness_value(%d))", __func__, sharpness_value); + int Internal_is = !strncmp((const char*)getCameraSensorName(), "ISP Camera", 10); + + if (Internal_is) { + sharpness_value += IS_SHARPNESS_DEFAULT; + if (sharpness_value < IS_SHARPNESS_MINUS_2 || IS_SHARPNESS_MAX <= sharpness_value) { + LOGE("ERR(%s):Invalid sharpness_value (%d)", __func__, sharpness_value); + return -1; + } + } else { + sharpness_value += SHARPNESS_DEFAULT; + if (sharpness_value < SHARPNESS_MINUS_2 || SHARPNESS_MAX <= sharpness_value) { + LOGE("ERR(%s):Invalid sharpness_value (%d)", __func__, sharpness_value); + return -1; + } + } + + if (m_params->sharpness != sharpness_value) { + m_params->sharpness = sharpness_value; + if (m_flag_camera_start) { + if (Internal_is) { + if (v4l2_gsc_cap_s_ctrl(m_gsc_vd_fd, V4L2_CID_IS_CAMERA_SHARPNESS, sharpness_value) < 0) { + LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_SHARPNESS", __func__); + return -1; + } + } else { + if (v4l2_gsc_cap_s_ctrl(m_gsc_vd_fd, V4L2_CID_CAMERA_SHARPNESS, sharpness_value) < 0) { + LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_SHARPNESS", __func__); + return -1; + } + } + } + } + + return 0; +} + +int SecCamera::getSharpness(void) +{ + return m_params->sharpness; +} + +int SecCamera::setHue(int hue_value) +{ + LOGV("%s(hue_value(%d))", __func__, hue_value); + int Internal_is = !strncmp((const char*)getCameraSensorName(), "ISP Camera", 10); + + if (Internal_is) { + hue_value += IS_HUE_DEFAULT; + if (hue_value < IS_HUE_MINUS_2 || IS_HUE_MAX <= hue_value) { + LOGE("ERR(%s):Invalid hue_value (%d)", __func__, hue_value); + return -1; + } + } else { + LOGW("WARN(%s):Not supported hue setting", __func__); + return 0; + } + + if (m_params->hue != hue_value) { + m_params->hue = hue_value; + if (m_flag_camera_start) { + if (v4l2_gsc_cap_s_ctrl(m_gsc_vd_fd, V4L2_CID_IS_CAMERA_HUE, hue_value) < 0) { + LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_HUE", __func__); + return -1; + } + } + } + + return 0; +} + +int SecCamera::getHue(void) +{ + return m_params->hue; +} + +int SecCamera::setWDR(int wdr_value) +{ + LOGV("%s(wdr_value(%d))", __func__, wdr_value); + int Internal_is = !strncmp((const char*)getCameraSensorName(), "ISP Camera", 10); + + if (Internal_is) { + if (wdr_value < IS_DRC_BYPASS_DISABLE || IS_DRC_BYPASS_MAX <= wdr_value) { + LOGE("ERR(%s):Invalid drc_value (%d)", __func__, wdr_value); + return -1; + } + } else { + if (wdr_value < WDR_OFF || WDR_MAX <= wdr_value) { + LOGE("ERR(%s):Invalid wdr_value (%d)", __func__, wdr_value); + return -1; + } + } + + if (m_wdr != wdr_value) { + m_wdr = wdr_value; + if (m_flag_camera_start) { + if (Internal_is) { + if (v4l2_gsc_cap_s_ctrl(m_gsc_vd_fd, V4L2_CID_IS_SET_DRC, wdr_value) < 0) { + LOGE("ERR(%s):Fail on V4L2_CID_IS_SET_DRC", __func__); + return -1; + } + } else { + if (v4l2_gsc_cap_s_ctrl(m_gsc_vd_fd, V4L2_CID_CAMERA_WDR, wdr_value) < 0) { + LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_WDR", __func__); + return -1; + } + } + } + } + + return 0; +} + +int SecCamera::getWDR(void) +{ + return m_wdr; +} + +int SecCamera::setAntiShake(int anti_shake) +{ + LOGV("%s(anti_shake(%d))", __func__, anti_shake); + + if (anti_shake < ANTI_SHAKE_OFF || ANTI_SHAKE_MAX <= anti_shake) { + LOGE("ERR(%s):Invalid anti_shake (%d)", __func__, anti_shake); + return -1; + } + + if (m_anti_shake != anti_shake) { + m_anti_shake = anti_shake; + if (m_flag_camera_start) { + if (v4l2_gsc_cap_s_ctrl(m_gsc_vd_fd, V4L2_CID_CAMERA_ANTI_SHAKE, anti_shake) < 0) { + LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_ANTI_SHAKE", __func__); + return -1; + } + } + } + + return 0; +} + +int SecCamera::getAntiShake(void) +{ + return m_anti_shake; +} + +int SecCamera::setMetering(int metering_value) +{ + LOGV("%s(metering (%d))", __func__, metering_value); + int Internal_is = !strncmp((const char*)getCameraSensorName(), "ISP Camera", 10); + + if (Internal_is) { + if (metering_value < IS_METERING_AVERAGE || IS_METERING_MAX <= metering_value) { + LOGE("ERR(%s):Invalid metering_value (%d)", __func__, metering_value); + return -1; + } + } else { + if (metering_value <= METERING_BASE || METERING_MAX <= metering_value) { + LOGE("ERR(%s):Invalid metering_value (%d)", __func__, metering_value); + return -1; + } + } + + if (m_params->metering != metering_value) { + m_params->metering = metering_value; + if (m_flag_camera_start) { + if (Internal_is) { + if (v4l2_gsc_cap_s_ctrl(m_gsc_vd_fd, V4L2_CID_IS_CAMERA_METERING, metering_value) < 0) { + LOGE("ERR(%s):Fail on V4L2_CID_IS_CAMERA_METERING", __func__); + return -1; + } + } else { + if (v4l2_gsc_cap_s_ctrl(m_gsc_vd_fd, V4L2_CID_CAMERA_METERING, metering_value) < 0) { + LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_METERING", __func__); + return -1; + } + } + } + } + + return 0; +} + +int SecCamera::getMetering(void) +{ + return m_params->metering; +} + +int SecCamera::setJpegQuality(int jpeg_quality) +{ + LOGV("%s(jpeg_quality (%d))", __func__, jpeg_quality); + + if (jpeg_quality < JPEG_QUALITY_ECONOMY || JPEG_QUALITY_MAX <= jpeg_quality) { + LOGE("ERR(%s):Invalid jpeg_quality (%d)", __func__, jpeg_quality); + return -1; + } + + if (m_jpeg_quality != jpeg_quality) { + m_jpeg_quality = jpeg_quality; +#ifdef JPEG_FROM_SENSOR + if (m_flag_camera_start && (m_camera_id == CAMERA_ID_BACK)) { + if (v4l2_gsc_cap_s_ctrl(m_gsc_vd_fd, V4L2_CID_CAM_JPEG_QUALITY, jpeg_quality) < 0) { + LOGE("ERR(%s):Fail on V4L2_CID_CAM_JPEG_QUALITY", __func__); + return -1; + } + } +#endif + } + + return 0; +} + +int SecCamera::getJpegQuality(void) +{ + return m_jpeg_quality; +} + +int SecCamera::setZoom(int zoom_level) +{ + LOGV("%s(zoom_level (%d))", __func__, zoom_level); + + if (zoom_level < ZOOM_LEVEL_0 || ZOOM_LEVEL_MAX <= zoom_level) { + LOGE("ERR(%s):Invalid zoom_level (%d)", __func__, zoom_level); + return -1; + } + + if (m_zoom_level != zoom_level) { + m_zoom_level = zoom_level; + if (m_flag_camera_start) { + if (v4l2_gsc_cap_s_ctrl(m_gsc_vd_fd, V4L2_CID_CAMERA_ZOOM, zoom_level) < 0) { + LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_ZOOM", __func__); + return -1; + } + } + } + + return 0; +} + +int SecCamera::getZoom(void) +{ + return m_zoom_level; +} + +int SecCamera::setObjectTracking(int object_tracking) +{ + LOGV("%s(object_tracking (%d))", __func__, object_tracking); + + if (object_tracking < OBJECT_TRACKING_OFF || OBJECT_TRACKING_MAX <= object_tracking) { + LOGE("ERR(%s):Invalid object_tracking (%d)", __func__, object_tracking); + return -1; + } + + if (m_object_tracking != object_tracking) + m_object_tracking = object_tracking; + + return 0; +} + +int SecCamera::getObjectTracking(void) +{ + return m_object_tracking; +} + +int SecCamera::getObjectTrackingStatus(void) +{ + int obj_status = 0; + obj_status = v4l2_gsc_cap_g_ctrl(m_gsc_vd_fd, V4L2_CID_CAMERA_OBJ_TRACKING_STATUS); + return obj_status; +} + +int SecCamera::setObjectTrackingStartStop(int start_stop) +{ + LOGV("%s(object_tracking_start_stop (%d))", __func__, start_stop); + + if (m_object_tracking_start_stop != start_stop) { + m_object_tracking_start_stop = start_stop; + if (v4l2_gsc_cap_s_ctrl(m_gsc_vd_fd, V4L2_CID_CAMERA_OBJ_TRACKING_START_STOP, start_stop) < 0) { + LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_OBJ_TRACKING_START_STOP", __func__); + return -1; + } + } + + return 0; +} + +int SecCamera::setTouchAFStartStop(int start_stop) +{ + LOGV("%s(touch_af_start_stop (%d))", __func__, start_stop); + + if (m_touch_af_start_stop != start_stop) { + m_touch_af_start_stop = start_stop; + if (v4l2_gsc_cap_s_ctrl(m_gsc_vd_fd, V4L2_CID_CAMERA_TOUCH_AF_START_STOP, start_stop) < 0) { + LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_TOUCH_AF_START_STOP", __func__); + return -1; + } + } + + return 0; +} + +int SecCamera::setSmartAuto(int smart_auto) +{ + LOGV("%s(smart_auto (%d))", __func__, smart_auto); + + if (smart_auto < SMART_AUTO_OFF || SMART_AUTO_MAX <= smart_auto) { + LOGE("ERR(%s):Invalid smart_auto (%d)", __func__, smart_auto); + return -1; + } + + if (m_smart_auto != smart_auto) { + m_smart_auto = smart_auto; + if (m_flag_camera_start) { + if (v4l2_gsc_cap_s_ctrl(m_gsc_vd_fd, V4L2_CID_CAMERA_SMART_AUTO, smart_auto) < 0) { + LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_SMART_AUTO", __func__); + return -1; + } + } + } + + return 0; +} + +int SecCamera::getSmartAuto(void) +{ + return m_smart_auto; +} + +int SecCamera::getAutosceneStatus(void) +{ + int autoscene_status = -1; + + if (getSmartAuto() == SMART_AUTO_ON) { + autoscene_status = v4l2_gsc_cap_g_ctrl(m_gsc_vd_fd, V4L2_CID_CAMERA_SMART_AUTO_STATUS); + + if ((autoscene_status < SMART_AUTO_STATUS_AUTO) || (autoscene_status > SMART_AUTO_STATUS_MAX)) { + LOGE("ERR(%s):Invalid getAutosceneStatus (%d)", __func__, autoscene_status); + return -1; + } + } + return autoscene_status; +} + +int SecCamera::setBeautyShot(int beauty_shot) +{ + LOGV("%s(beauty_shot (%d))", __func__, beauty_shot); + + if (beauty_shot < BEAUTY_SHOT_OFF || BEAUTY_SHOT_MAX <= beauty_shot) { + LOGE("ERR(%s):Invalid beauty_shot (%d)", __func__, beauty_shot); + return -1; + } + + if (m_beauty_shot != beauty_shot) { + m_beauty_shot = beauty_shot; + if (m_flag_camera_start) { + if (v4l2_gsc_cap_s_ctrl(m_gsc_vd_fd, V4L2_CID_CAMERA_BEAUTY_SHOT, beauty_shot) < 0) { + LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_BEAUTY_SHOT", __func__); + return -1; + } + } + + setFaceDetect(FACE_DETECTION_ON_BEAUTY); + } + + return 0; +} + +int SecCamera::getBeautyShot(void) +{ + return m_beauty_shot; +} + +int SecCamera::setVintageMode(int vintage_mode) +{ + LOGV("%s(vintage_mode(%d))", __func__, vintage_mode); + + if (vintage_mode <= VINTAGE_MODE_BASE || VINTAGE_MODE_MAX <= vintage_mode) { + LOGE("ERR(%s):Invalid vintage_mode (%d)", __func__, vintage_mode); + return -1; + } + + if (m_vintage_mode != vintage_mode) { + m_vintage_mode = vintage_mode; + if (m_flag_camera_start) { + if (v4l2_gsc_cap_s_ctrl(m_gsc_vd_fd, V4L2_CID_CAMERA_VINTAGE_MODE, vintage_mode) < 0) { + LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_VINTAGE_MODE", __func__); + return -1; + } + } + } + + return 0; +} + +int SecCamera::getVintageMode(void) +{ + return m_vintage_mode; +} + +int SecCamera::setFocusMode(int focus_mode) +{ + LOGV("%s(focus_mode(%d))", __func__, focus_mode); + int Internal_is = !strncmp((const char*)getCameraSensorName(), "ISP Camera", 10); + + if (Internal_is) { + if (IS_FOCUS_MODE_MAX <= focus_mode) { + LOGE("ERR(%s):Invalid focus_mode (%d)", __func__, focus_mode); + return -1; + } + } else { + if (FOCUS_MODE_MAX <= focus_mode) { + LOGE("ERR(%s):Invalid focus_mode (%d)", __func__, focus_mode); + return -1; + } + } + + if (m_params->focus_mode != focus_mode) { + m_params->focus_mode = focus_mode; +#ifdef AF_SUPPORT + if (m_flag_camera_start) { + if (Internal_is) { + if (v4l2_gsc_cap_s_ctrl(m_gsc_vd_fd, V4L2_CID_IS_CAMERA_FOCUS_MODE, focus_mode) < 0) { + LOGE("ERR(%s):Fail on V4L2_CID_IS_CAMERA_FOCUS_MODE", __func__); + return -1; + } + } else { + if (v4l2_gsc_cap_s_ctrl(m_gsc_vd_fd, V4L2_CID_CAMERA_FOCUS_MODE, focus_mode) < 0) { + LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_FOCUS_MODE", __func__); + return -1; + } + } + } +#endif + } + + return 0; +} + +int SecCamera::getFocusMode(void) +{ + return m_params->focus_mode; +} + +int SecCamera::setFaceDetect(int face_detect) +{ + LOGV("%s(face_detect(%d))", __func__, face_detect); + int Internal_is = !strncmp((const char*)getCameraSensorName(), "ISP Camera", 10); + + if (m_face_detect != face_detect) { + m_face_detect = face_detect; + if (m_flag_camera_start) { + if (m_face_detect != FACE_DETECTION_OFF) { + if (Internal_is) { + if (v4l2_gsc_cap_s_ctrl(m_gsc_vd_fd, V4L2_CID_IS_CAMERA_FOCUS_MODE, IS_FOCUS_MODE_AUTO) < 0) { + LOGE("ERR(%s):Fail on V4L2_CID_IS_CAMERA_FOCUS_MODin face detecion", __func__); + return -1; + } + } else { + if (v4l2_gsc_cap_s_ctrl(m_gsc_vd_fd, V4L2_CID_CAMERA_FOCUS_MODE, FOCUS_MODE_AUTO) < 0) { + LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_FOCUS_MODin face detecion", __func__); + return -1; + } + } + } + if (Internal_is) { + if (v4l2_gsc_cap_s_ctrl(m_gsc_vd_fd, V4L2_CID_IS_CMD_FD, face_detect) < 0) { + LOGE("ERR(%s):Fail on V4L2_CID_IS_CMD_FD", __func__); + return -1; + } + } else { + if (v4l2_gsc_cap_s_ctrl(m_gsc_vd_fd, V4L2_CID_CAMERA_FACE_DETECTION, face_detect) < 0) { + LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_FACE_DETECTION", __func__); + return -1; + } + } + } + } + + return 0; +} + +int SecCamera::getFaceDetect(void) +{ + return m_face_detect; +} + +int SecCamera::setGPSLatitude(const char *gps_latitude) +{ + double conveted_latitude = 0; + LOGV("%s(gps_latitude(%s))", __func__, gps_latitude); + if (gps_latitude == NULL) + m_gps_latitude = 0; + else { + conveted_latitude = atof(gps_latitude); + m_gps_latitude = (long)(conveted_latitude * 10000 / 1); + } + + LOGV("%s(m_gps_latitude(%ld))", __func__, m_gps_latitude); + return 0; +} + +int SecCamera::setGPSLongitude(const char *gps_longitude) +{ + double conveted_longitude = 0; + LOGV("%s(gps_longitude(%s))", __func__, gps_longitude); + if (gps_longitude == NULL) + m_gps_longitude = 0; + else { + conveted_longitude = atof(gps_longitude); + m_gps_longitude = (long)(conveted_longitude * 10000 / 1); + } + + LOGV("%s(m_gps_longitude(%ld))", __func__, m_gps_longitude); + return 0; +} + +int SecCamera::setGPSAltitude(const char *gps_altitude) +{ + double conveted_altitude = 0; + LOGV("%s(gps_altitude(%s))", __func__, gps_altitude); + if (gps_altitude == NULL) + m_gps_altitude = 0; + else { + conveted_altitude = atof(gps_altitude); + m_gps_altitude = (long)(conveted_altitude * 100 / 1); + } + + LOGV("%s(m_gps_altitude(%ld))", __func__, m_gps_altitude); + return 0; +} + +int SecCamera::setGPSTimeStamp(const char *gps_timestamp) +{ + LOGV("%s(gps_timestamp(%s))", __func__, gps_timestamp); + if (gps_timestamp == NULL) + m_gps_timestamp = 0; + else + m_gps_timestamp = atol(gps_timestamp); + + LOGV("%s(m_gps_timestamp(%ld))", __func__, m_gps_timestamp); + return 0; +} + +int SecCamera::setGPSProcessingMethod(const char *gps_processing_method) +{ + LOGV("%s(gps_processing_method(%s))", __func__, gps_processing_method); + memset(mExifInfo.gps_processing_method, 0, sizeof(mExifInfo.gps_processing_method)); + if (gps_processing_method != NULL) { + size_t len = strlen(gps_processing_method); + if (len > sizeof(mExifInfo.gps_processing_method)) { + len = sizeof(mExifInfo.gps_processing_method); + } + memcpy(mExifInfo.gps_processing_method, gps_processing_method, len); + } + return 0; +} + +int SecCamera::setFaceDetectLockUnlock(int facedetect_lockunlock) +{ + LOGV("%s(facedetect_lockunlock(%d))", __func__, facedetect_lockunlock); + + if (v4l2_gsc_cap_s_ctrl(m_gsc_vd_fd, V4L2_CID_CAMERA_FACEDETECT_LOCKUNLOCK, facedetect_lockunlock) < 0) { + LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_FACEDETECT_LOCKUNLOCK", __func__); + return -1; + } + + return 0; +} + +int SecCamera::setObjectPosition(int x, int y) +{ + LOGV("%s(setObjectPosition(x=%d, y=%d))", __func__, x, y); + + if (m_preview_width ==640) + x = x - 80; + + if (v4l2_gsc_cap_s_ctrl(m_gsc_vd_fd, V4L2_CID_CAMERA_OBJECT_POSITION_X, x) < 0) { + LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_OBJECT_POSITION_X", __func__); + return -1; + } + + if (v4l2_gsc_cap_s_ctrl(m_gsc_vd_fd, V4L2_CID_CAMERA_OBJECT_POSITION_Y, y) < 0) { + LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_OBJECT_POSITION_Y", __func__); + return -1; + } + + return 0; +} + +int SecCamera::setGamma(int gamma) +{ + LOGV("%s(gamma(%d))", __func__, gamma); + + if (gamma < GAMMA_OFF || GAMMA_MAX <= gamma) { + LOGE("ERR(%s):Invalid gamma (%d)", __func__, gamma); + return -1; + } + + if (m_video_gamma != gamma) { + m_video_gamma = gamma; + if (m_flag_camera_start) { + if (v4l2_gsc_cap_s_ctrl(m_gsc_vd_fd, V4L2_CID_CAMERA_SET_GAMMA, gamma) < 0) { + LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_SET_GAMMA", __func__); + return -1; + } + } + } + + return 0; +} + +int SecCamera::setSlowAE(int slow_ae) +{ + LOGV("%s(slow_ae(%d))", __func__, slow_ae); + + if (slow_ae < GAMMA_OFF || GAMMA_MAX <= slow_ae) { + LOGE("ERR(%s):Invalid slow_ae (%d)", __func__, slow_ae); + return -1; + } + + if (m_slow_ae!= slow_ae) { + m_slow_ae = slow_ae; + if (m_flag_camera_start) { + if (v4l2_gsc_cap_s_ctrl(m_gsc_vd_fd, V4L2_CID_CAMERA_SET_SLOW_AE, slow_ae) < 0) { + LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_SET_SLOW_AE", __func__); + return -1; + } + } + } + + return 0; +} + +int SecCamera::setRecording(int recording_en) +{ + LOGV("%s(recoding_en(%d))", __func__, recording_en); + + m_recording_en = recording_en; + + return 0; +} + +int SecCamera::setRecordingSize(int width, int height) +{ + LOGV("%s(width(%d), height(%d))", __func__, width, height); + + m_recording_width = width; + m_recording_height = height; + + return 0; +} + +int SecCamera::getRecordingSize(int *width, int *height) +{ + *width = m_recording_width; + *height = m_recording_height; + + return 0; +} + +int SecCamera::setExifOrientationInfo(int orientationInfo) +{ + LOGV("%s(orientationInfo(%d))", __func__, orientationInfo); + + if (orientationInfo < 0) { + LOGE("ERR(%s):Invalid orientationInfo (%d)", __func__, orientationInfo); + return -1; + } + m_exif_orientation = orientationInfo; + + return 0; +} + +int SecCamera::setBatchReflection() +{ + if (m_flag_camera_start) { + if (v4l2_gsc_cap_s_ctrl(m_gsc_vd_fd, V4L2_CID_CAMERA_BATCH_REFLECTION, 1) < 0) { + LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_BATCH_REFLECTION", __func__); + return -1; + } + } + + return 0; +} + +/* Camcorder fix fps */ +int SecCamera::setSensorMode(int sensor_mode) +{ + LOGV("%s(sensor_mode (%d))", __func__, sensor_mode); + + if (sensor_mode < SENSOR_MODE_CAMERA || SENSOR_MODE_MOVIE < sensor_mode) { + LOGE("ERR(%s):Invalid sensor mode (%d)", __func__, sensor_mode); + return -1; + } + + if (m_sensor_mode != sensor_mode) + m_sensor_mode = sensor_mode; + + return 0; +} + +/* Shot mode */ +/* SINGLE = 0 +* CONTINUOUS = 1 +* PANORAMA = 2 +* SMILE = 3 +* SELF = 6 +*/ +int SecCamera::setShotMode(int shot_mode) +{ + LOGV("%s(shot_mode (%d))", __func__, shot_mode); + if (shot_mode < SHOT_MODE_SINGLE || SHOT_MODE_SELF < shot_mode) { + LOGE("ERR(%s):Invalid shot_mode (%d)", __func__, shot_mode); + return -1; + } + m_shot_mode = shot_mode; + + return 0; +} + +int SecCamera::setDataLineCheck(int chk_dataline) +{ + LOGV("%s(chk_dataline (%d))", __func__, chk_dataline); + + if (chk_dataline < CHK_DATALINE_OFF || CHK_DATALINE_MAX <= chk_dataline) { + LOGE("ERR(%s):Invalid chk_dataline (%d)", __func__, chk_dataline); + return -1; + } + + m_chk_dataline = chk_dataline; + + return 0; +} + +int SecCamera::getDataLineCheck(void) +{ + return m_chk_dataline; +} + +int SecCamera::setDataLineCheckStop(void) +{ + LOGV("%s", __func__); + + if (m_flag_camera_start) { + if (v4l2_gsc_cap_s_ctrl(m_gsc_vd_fd, V4L2_CID_CAMERA_CHECK_DATALINE_STOP, 1) < 0) { + LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_CHECK_DATALINE_STOP", __func__); + return -1; + } + } + return 0; +} + +const __u8* SecCamera::getCameraSensorName(void) +{ + LOGV("%s", __func__); + + return v4l2_gsc_cap_enuminput(m_gsc_vd_fd, getCameraId()); +} + +#ifdef ENABLE_ESD_PREVIEW_CHECK +int SecCamera::getCameraSensorESDStatus(void) +{ + LOGV("%s", __func__); + + // 0 : normal operation, 1 : abnormal operation + int status = v4l2_gsc_cap_g_ctrl(m_gsc_vd_fd, V4L2_CID_ESD_INT); + + return status; +} +#endif // ENABLE_ESD_PREVIEW_CHECK + +int SecCamera::setJpegThumbnailSize(int width, int height) +{ + LOGV("%s(width(%d), height(%d))", __func__, width, height); + + m_jpeg_thumbnail_width = width; + m_jpeg_thumbnail_height = height; + + return 0; +} + +int SecCamera::getJpegThumbnailSize(int *width, int *height) +{ + if (width) + *width = m_jpeg_thumbnail_width; + if (height) + *height = m_jpeg_thumbnail_height; + + return 0; +} + +int SecCamera::setJpegThumbnailQuality(int jpeg_thumbnail_quality) +{ + LOGV("%s(jpeg_thumbnail_quality (%d))", __func__, jpeg_thumbnail_quality); + + if (jpeg_thumbnail_quality < JPEG_QUALITY_ECONOMY || JPEG_QUALITY_MAX <= jpeg_thumbnail_quality) { + LOGE("ERR(%s):Invalid jpeg_thumbnail_quality (%d)", __func__, jpeg_thumbnail_quality); + return -1; + } + + if (m_jpeg_thumbnail_quality != jpeg_thumbnail_quality) { + m_jpeg_thumbnail_quality = jpeg_thumbnail_quality; + } + + return 0; +} + +int SecCamera::getJpegThumbnailQuality(void) +{ + return m_jpeg_thumbnail_quality; +} + +void SecCamera::setExifFixedAttribute() +{ + char property[PROPERTY_VALUE_MAX]; + + //2 0th IFD TIFF Tags + //3 Maker + property_get("ro.product.brand", property, EXIF_DEF_MAKER); + strncpy((char *)mExifInfo.maker, property, + sizeof(mExifInfo.maker) - 1); + mExifInfo.maker[sizeof(mExifInfo.maker) - 1] = '\0'; + //3 Model + property_get("ro.product.model", property, EXIF_DEF_MODEL); + strncpy((char *)mExifInfo.model, property, + sizeof(mExifInfo.model) - 1); + mExifInfo.model[sizeof(mExifInfo.model) - 1] = '\0'; + //3 Software + property_get("ro.build.id", property, EXIF_DEF_SOFTWARE); + strncpy((char *)mExifInfo.software, property, + sizeof(mExifInfo.software) - 1); + mExifInfo.software[sizeof(mExifInfo.software) - 1] = '\0'; + + //3 YCbCr Positioning + mExifInfo.ycbcr_positioning = EXIF_DEF_YCBCR_POSITIONING; + + //2 0th IFD Exif Private Tags + //3 F Number + mExifInfo.fnumber.num = EXIF_DEF_FNUMBER_NUM; + mExifInfo.fnumber.den = EXIF_DEF_FNUMBER_DEN; + //3 Exposure Program + mExifInfo.exposure_program = EXIF_DEF_EXPOSURE_PROGRAM; + //3 Exif Version + memcpy(mExifInfo.exif_version, EXIF_DEF_EXIF_VERSION, sizeof(mExifInfo.exif_version)); + //3 Aperture + uint32_t av = APEX_FNUM_TO_APERTURE((double)mExifInfo.fnumber.num/mExifInfo.fnumber.den); + mExifInfo.aperture.num = av*EXIF_DEF_APEX_DEN; + mExifInfo.aperture.den = EXIF_DEF_APEX_DEN; + //3 Maximum lens aperture + mExifInfo.max_aperture.num = mExifInfo.aperture.num; + mExifInfo.max_aperture.den = mExifInfo.aperture.den; + //3 Lens Focal Length + if (m_camera_id == CAMERA_ID_BACK) + mExifInfo.focal_length.num = BACK_CAMERA_FOCAL_LENGTH; + else + mExifInfo.focal_length.num = FRONT_CAMERA_FOCAL_LENGTH; + + mExifInfo.focal_length.den = EXIF_DEF_FOCAL_LEN_DEN; + //3 User Comments + strcpy((char *)mExifInfo.user_comment, EXIF_DEF_USERCOMMENTS); + //3 Color Space information + mExifInfo.color_space = EXIF_DEF_COLOR_SPACE; + //3 Exposure Mode + mExifInfo.exposure_mode = EXIF_DEF_EXPOSURE_MODE; + + //2 0th IFD GPS Info Tags + unsigned char gps_version[4] = { 0x02, 0x02, 0x00, 0x00 }; + memcpy(mExifInfo.gps_version_id, gps_version, sizeof(gps_version)); + + //2 1th IFD TIFF Tags + mExifInfo.compression_scheme = EXIF_DEF_COMPRESSION; + mExifInfo.x_resolution.num = EXIF_DEF_RESOLUTION_NUM; + mExifInfo.x_resolution.den = EXIF_DEF_RESOLUTION_DEN; + mExifInfo.y_resolution.num = EXIF_DEF_RESOLUTION_NUM; + mExifInfo.y_resolution.den = EXIF_DEF_RESOLUTION_DEN; + mExifInfo.resolution_unit = EXIF_DEF_RESOLUTION_UNIT; +} + +void SecCamera::setExifChangedAttribute() +{ + //2 0th IFD TIFF Tags + //3 Width + mExifInfo.width = m_snapshot_width; + //3 Height + mExifInfo.height = m_snapshot_height; + //3 Orientation + switch (m_exif_orientation) { + case 90: + mExifInfo.orientation = EXIF_ORIENTATION_90; + break; + case 180: + mExifInfo.orientation = EXIF_ORIENTATION_180; + break; + case 270: + mExifInfo.orientation = EXIF_ORIENTATION_270; + break; + case 0: + default: + mExifInfo.orientation = EXIF_ORIENTATION_UP; + break; + } + //3 Date time + time_t rawtime; + struct tm *timeinfo; + time(&rawtime); + timeinfo = localtime(&rawtime); + strftime((char *)mExifInfo.date_time, 20, "%Y:%m:%d %H:%M:%S", timeinfo); + + //2 0th IFD Exif Private Tags + //3 Exposure Time + //int shutterSpeed = v4l2_gsc_cap_g_ctrl(m_gsc_vd_fd, V4L2_CID_CAMERA_GET_SHT_TIME); + int shutterSpeed = 100; + + /* TBD - front camera needs to be fixed to support this g_ctrl, + it current returns a negative err value, so avoid putting + odd value into exif for now */ + if (shutterSpeed < 0) { + LOGE("%s: error %d getting shutterSpeed, camera_id = %d, using 100", + __func__, shutterSpeed, m_camera_id); + shutterSpeed = 100; + } + mExifInfo.exposure_time.num = 1; + // x us -> 1/x s */ + mExifInfo.exposure_time.den = (uint32_t)(1000000 / shutterSpeed); + + //3 ISO Speed Rating + int iso = m_params->iso; + //int iso = v4l2_gsc_cap_g_ctrl(m_gsc_vd_fd, V4L2_CID_CAMERA_GET_ISO); + /* TBD - front camera needs to be fixed to support this g_ctrl, + it current returns a negative err value, so avoid putting + odd value into exif for now */ + if (iso < 0) { + LOGE("%s: error %d getting iso, camera_id = %d, using 100", + __func__, iso, m_camera_id); + iso = ISO_100; + } + switch(iso) { + case ISO_50: + mExifInfo.iso_speed_rating = 50; + break; + case ISO_100: + mExifInfo.iso_speed_rating = 100; + break; + case ISO_200: + mExifInfo.iso_speed_rating = 200; + break; + case ISO_400: + mExifInfo.iso_speed_rating = 400; + break; + case ISO_800: + mExifInfo.iso_speed_rating = 800; + break; + case ISO_1600: + mExifInfo.iso_speed_rating = 1600; + break; + default: + mExifInfo.iso_speed_rating = 100; + break; + } + + uint32_t av, tv, bv, sv, ev; + av = APEX_FNUM_TO_APERTURE((double)mExifInfo.fnumber.num / mExifInfo.fnumber.den); + tv = APEX_EXPOSURE_TO_SHUTTER((double)mExifInfo.exposure_time.num / mExifInfo.exposure_time.den); + sv = APEX_ISO_TO_FILMSENSITIVITY(mExifInfo.iso_speed_rating); + bv = av + tv - sv; + ev = av + tv; + LOGD("Shutter speed=%d us, iso=%d", shutterSpeed, mExifInfo.iso_speed_rating); + LOGD("AV=%d, TV=%d, SV=%d", av, tv, sv); + + //3 Shutter Speed + mExifInfo.shutter_speed.num = tv*EXIF_DEF_APEX_DEN; + mExifInfo.shutter_speed.den = EXIF_DEF_APEX_DEN; + //3 Brightness + mExifInfo.brightness.num = bv*EXIF_DEF_APEX_DEN; + mExifInfo.brightness.den = EXIF_DEF_APEX_DEN; + //3 Exposure Bias + if (m_params->scene_mode == SCENE_MODE_BEACH_SNOW) { + mExifInfo.exposure_bias.num = EXIF_DEF_APEX_DEN; + mExifInfo.exposure_bias.den = EXIF_DEF_APEX_DEN; + } else { + mExifInfo.exposure_bias.num = 0; + mExifInfo.exposure_bias.den = 0; + } + //3 Metering Mode + switch (m_params->metering) { + case METERING_SPOT: + mExifInfo.metering_mode = EXIF_METERING_SPOT; + break; + case METERING_MATRIX: + mExifInfo.metering_mode = EXIF_METERING_AVERAGE; + break; + case METERING_CENTER: + mExifInfo.metering_mode = EXIF_METERING_CENTER; + break; + default : + mExifInfo.metering_mode = EXIF_METERING_AVERAGE; + break; + } + + //3 Flash + int flash = m_params->flash_mode; + //int flash = v4l2_gsc_cap_g_ctrl(m_gsc_vd_fd, V4L2_CID_CAMERA_GET_FLASH_ONOFF); + if (flash < 0) + mExifInfo.flash = EXIF_DEF_FLASH; + else + mExifInfo.flash = flash; + + //3 White Balance + if (m_params->white_balance == WHITE_BALANCE_AUTO) + mExifInfo.white_balance = EXIF_WB_AUTO; + else + mExifInfo.white_balance = EXIF_WB_MANUAL; + //3 Scene Capture Type + switch (m_params->scene_mode) { + case SCENE_MODE_PORTRAIT: + mExifInfo.scene_capture_type = EXIF_SCENE_PORTRAIT; + break; + case SCENE_MODE_LANDSCAPE: + mExifInfo.scene_capture_type = EXIF_SCENE_LANDSCAPE; + break; + case SCENE_MODE_NIGHTSHOT: + mExifInfo.scene_capture_type = EXIF_SCENE_NIGHT; + break; + default: + mExifInfo.scene_capture_type = EXIF_SCENE_STANDARD; + break; + } + + //2 0th IFD GPS Info Tags + if (m_gps_latitude != 0 && m_gps_longitude != 0) { + if (m_gps_latitude > 0) + strcpy((char *)mExifInfo.gps_latitude_ref, "N"); + else + strcpy((char *)mExifInfo.gps_latitude_ref, "S"); + + if (m_gps_longitude > 0) + strcpy((char *)mExifInfo.gps_longitude_ref, "E"); + else + strcpy((char *)mExifInfo.gps_longitude_ref, "W"); + + if (m_gps_altitude > 0) + mExifInfo.gps_altitude_ref = 0; + else + mExifInfo.gps_altitude_ref = 1; + + double latitude = fabs(m_gps_latitude / 10000.0); + double longitude = fabs(m_gps_longitude / 10000.0); + double altitude = fabs(m_gps_altitude / 100.0); + + mExifInfo.gps_latitude[0].num = (uint32_t)latitude; + mExifInfo.gps_latitude[0].den = 1; + mExifInfo.gps_latitude[1].num = (uint32_t)((latitude - mExifInfo.gps_latitude[0].num) * 60); + mExifInfo.gps_latitude[1].den = 1; + mExifInfo.gps_latitude[2].num = (uint32_t)((((latitude - mExifInfo.gps_latitude[0].num) * 60) + - mExifInfo.gps_latitude[1].num) * 60); + mExifInfo.gps_latitude[2].den = 1; + + mExifInfo.gps_longitude[0].num = (uint32_t)longitude; + mExifInfo.gps_longitude[0].den = 1; + mExifInfo.gps_longitude[1].num = (uint32_t)((longitude - mExifInfo.gps_longitude[0].num) * 60); + mExifInfo.gps_longitude[1].den = 1; + mExifInfo.gps_longitude[2].num = (uint32_t)((((longitude - mExifInfo.gps_longitude[0].num) * 60) + - mExifInfo.gps_longitude[1].num) * 60); + mExifInfo.gps_longitude[2].den = 1; + + mExifInfo.gps_altitude.num = (uint32_t)altitude; + mExifInfo.gps_altitude.den = 1; + + struct tm tm_data; + gmtime_r(&m_gps_timestamp, &tm_data); + mExifInfo.gps_timestamp[0].num = tm_data.tm_hour; + mExifInfo.gps_timestamp[0].den = 1; + mExifInfo.gps_timestamp[1].num = tm_data.tm_min; + mExifInfo.gps_timestamp[1].den = 1; + mExifInfo.gps_timestamp[2].num = tm_data.tm_sec; + mExifInfo.gps_timestamp[2].den = 1; + snprintf((char*)mExifInfo.gps_datestamp, sizeof(mExifInfo.gps_datestamp), + "%04d:%02d:%02d", tm_data.tm_year + 1900, tm_data.tm_mon + 1, tm_data.tm_mday); + + mExifInfo.enableGps = true; + } else { + mExifInfo.enableGps = false; + } + + //2 1th IFD TIFF Tags + mExifInfo.widthThumb = m_jpeg_thumbnail_width; + mExifInfo.heightThumb = m_jpeg_thumbnail_height; +} + +int SecCamera::makeExif (unsigned char *exifOut, + unsigned char *thumb_buf, + unsigned int thumb_size, + exif_attribute_t *exifInfo, + unsigned int *size, + bool useMainbufForThumb) +{ + unsigned char *pCur, *pApp1Start, *pIfdStart, *pGpsIfdPtr, *pNextIfdOffset; + unsigned int tmp, LongerTagOffest = 0; + pApp1Start = pCur = exifOut; + + //2 Exif Identifier Code & TIFF Header + pCur += 4; // Skip 4 Byte for APP1 marker and length + unsigned char ExifIdentifierCode[6] = { 0x45, 0x78, 0x69, 0x66, 0x00, 0x00 }; + memcpy(pCur, ExifIdentifierCode, 6); + pCur += 6; + + /* Byte Order - little endian, Offset of IFD - 0x00000008.H */ + unsigned char TiffHeader[8] = { 0x49, 0x49, 0x2A, 0x00, 0x08, 0x00, 0x00, 0x00 }; + memcpy(pCur, TiffHeader, 8); + pIfdStart = pCur; + pCur += 8; + + //2 0th IFD TIFF Tags + if (exifInfo->enableGps) + tmp = NUM_0TH_IFD_TIFF; + else + tmp = NUM_0TH_IFD_TIFF - 1; + + memcpy(pCur, &tmp, NUM_SIZE); + pCur += NUM_SIZE; + + LongerTagOffest += 8 + NUM_SIZE + tmp*IFD_SIZE + OFFSET_SIZE; + + writeExifIfd(&pCur, EXIF_TAG_IMAGE_WIDTH, EXIF_TYPE_LONG, + 1, exifInfo->width); + writeExifIfd(&pCur, EXIF_TAG_IMAGE_HEIGHT, EXIF_TYPE_LONG, + 1, exifInfo->height); + writeExifIfd(&pCur, EXIF_TAG_MAKE, EXIF_TYPE_ASCII, + strlen((char *)exifInfo->maker) + 1, exifInfo->maker, &LongerTagOffest, pIfdStart); + writeExifIfd(&pCur, EXIF_TAG_MODEL, EXIF_TYPE_ASCII, + strlen((char *)exifInfo->model) + 1, exifInfo->model, &LongerTagOffest, pIfdStart); + writeExifIfd(&pCur, EXIF_TAG_ORIENTATION, EXIF_TYPE_SHORT, + 1, exifInfo->orientation); + writeExifIfd(&pCur, EXIF_TAG_SOFTWARE, EXIF_TYPE_ASCII, + strlen((char *)exifInfo->software) + 1, exifInfo->software, &LongerTagOffest, pIfdStart); + writeExifIfd(&pCur, EXIF_TAG_DATE_TIME, EXIF_TYPE_ASCII, + 20, exifInfo->date_time, &LongerTagOffest, pIfdStart); + writeExifIfd(&pCur, EXIF_TAG_YCBCR_POSITIONING, EXIF_TYPE_SHORT, + 1, exifInfo->ycbcr_positioning); + writeExifIfd(&pCur, EXIF_TAG_EXIF_IFD_POINTER, EXIF_TYPE_LONG, + 1, LongerTagOffest); + if (exifInfo->enableGps) { + pGpsIfdPtr = pCur; + pCur += IFD_SIZE; // Skip a ifd size for gps IFD pointer + } + + pNextIfdOffset = pCur; // Skip a offset size for next IFD offset + pCur += OFFSET_SIZE; + + //2 0th IFD Exif Private Tags + pCur = pIfdStart + LongerTagOffest; + + tmp = NUM_0TH_IFD_EXIF; + memcpy(pCur, &tmp , NUM_SIZE); + pCur += NUM_SIZE; + + LongerTagOffest += NUM_SIZE + NUM_0TH_IFD_EXIF*IFD_SIZE + OFFSET_SIZE; + + writeExifIfd(&pCur, EXIF_TAG_EXPOSURE_TIME, EXIF_TYPE_RATIONAL, + 1, &exifInfo->exposure_time, &LongerTagOffest, pIfdStart); + writeExifIfd(&pCur, EXIF_TAG_FNUMBER, EXIF_TYPE_RATIONAL, + 1, &exifInfo->fnumber, &LongerTagOffest, pIfdStart); + writeExifIfd(&pCur, EXIF_TAG_EXPOSURE_PROGRAM, EXIF_TYPE_SHORT, + 1, exifInfo->exposure_program); + writeExifIfd(&pCur, EXIF_TAG_ISO_SPEED_RATING, EXIF_TYPE_SHORT, + 1, exifInfo->iso_speed_rating); + writeExifIfd(&pCur, EXIF_TAG_EXIF_VERSION, EXIF_TYPE_UNDEFINED, + 4, exifInfo->exif_version); + writeExifIfd(&pCur, EXIF_TAG_DATE_TIME_ORG, EXIF_TYPE_ASCII, + 20, exifInfo->date_time, &LongerTagOffest, pIfdStart); + writeExifIfd(&pCur, EXIF_TAG_DATE_TIME_DIGITIZE, EXIF_TYPE_ASCII, + 20, exifInfo->date_time, &LongerTagOffest, pIfdStart); + writeExifIfd(&pCur, EXIF_TAG_SHUTTER_SPEED, EXIF_TYPE_SRATIONAL, + 1, (rational_t *)&exifInfo->shutter_speed, &LongerTagOffest, pIfdStart); + writeExifIfd(&pCur, EXIF_TAG_APERTURE, EXIF_TYPE_RATIONAL, + 1, &exifInfo->aperture, &LongerTagOffest, pIfdStart); + writeExifIfd(&pCur, EXIF_TAG_BRIGHTNESS, EXIF_TYPE_SRATIONAL, + 1, (rational_t *)&exifInfo->brightness, &LongerTagOffest, pIfdStart); + writeExifIfd(&pCur, EXIF_TAG_EXPOSURE_BIAS, EXIF_TYPE_SRATIONAL, + 1, (rational_t *)&exifInfo->exposure_bias, &LongerTagOffest, pIfdStart); + writeExifIfd(&pCur, EXIF_TAG_MAX_APERTURE, EXIF_TYPE_RATIONAL, + 1, &exifInfo->max_aperture, &LongerTagOffest, pIfdStart); + writeExifIfd(&pCur, EXIF_TAG_METERING_MODE, EXIF_TYPE_SHORT, + 1, exifInfo->metering_mode); + writeExifIfd(&pCur, EXIF_TAG_FLASH, EXIF_TYPE_SHORT, + 1, exifInfo->flash); + writeExifIfd(&pCur, EXIF_TAG_FOCAL_LENGTH, EXIF_TYPE_RATIONAL, + 1, &exifInfo->focal_length, &LongerTagOffest, pIfdStart); + char code[8] = { 0x00, 0x00, 0x00, 0x49, 0x49, 0x43, 0x53, 0x41 }; + int commentsLen = strlen((char *)exifInfo->user_comment) + 1; + memmove(exifInfo->user_comment + sizeof(code), exifInfo->user_comment, commentsLen); + memcpy(exifInfo->user_comment, code, sizeof(code)); + writeExifIfd(&pCur, EXIF_TAG_USER_COMMENT, EXIF_TYPE_UNDEFINED, + commentsLen + sizeof(code), exifInfo->user_comment, &LongerTagOffest, pIfdStart); + writeExifIfd(&pCur, EXIF_TAG_COLOR_SPACE, EXIF_TYPE_SHORT, + 1, exifInfo->color_space); + writeExifIfd(&pCur, EXIF_TAG_PIXEL_X_DIMENSION, EXIF_TYPE_LONG, + 1, exifInfo->width); + writeExifIfd(&pCur, EXIF_TAG_PIXEL_Y_DIMENSION, EXIF_TYPE_LONG, + 1, exifInfo->height); + writeExifIfd(&pCur, EXIF_TAG_EXPOSURE_MODE, EXIF_TYPE_LONG, + 1, exifInfo->exposure_mode); + writeExifIfd(&pCur, EXIF_TAG_WHITE_BALANCE, EXIF_TYPE_LONG, + 1, exifInfo->white_balance); + writeExifIfd(&pCur, EXIF_TAG_SCENCE_CAPTURE_TYPE, EXIF_TYPE_LONG, + 1, exifInfo->scene_capture_type); + tmp = 0; + memcpy(pCur, &tmp, OFFSET_SIZE); // next IFD offset + pCur += OFFSET_SIZE; + + //2 0th IFD GPS Info Tags + if (exifInfo->enableGps) { + writeExifIfd(&pGpsIfdPtr, EXIF_TAG_GPS_IFD_POINTER, EXIF_TYPE_LONG, + 1, LongerTagOffest); // GPS IFD pointer skipped on 0th IFD + + pCur = pIfdStart + LongerTagOffest; + + if (exifInfo->gps_processing_method[0] == 0) { + // don't create GPS_PROCESSING_METHOD tag if there isn't any + tmp = NUM_0TH_IFD_GPS - 1; + } else { + tmp = NUM_0TH_IFD_GPS; + } + memcpy(pCur, &tmp, NUM_SIZE); + pCur += NUM_SIZE; + + LongerTagOffest += NUM_SIZE + tmp*IFD_SIZE + OFFSET_SIZE; + + writeExifIfd(&pCur, EXIF_TAG_GPS_VERSION_ID, EXIF_TYPE_BYTE, + 4, exifInfo->gps_version_id); + writeExifIfd(&pCur, EXIF_TAG_GPS_LATITUDE_REF, EXIF_TYPE_ASCII, + 2, exifInfo->gps_latitude_ref); + writeExifIfd(&pCur, EXIF_TAG_GPS_LATITUDE, EXIF_TYPE_RATIONAL, + 3, exifInfo->gps_latitude, &LongerTagOffest, pIfdStart); + writeExifIfd(&pCur, EXIF_TAG_GPS_LONGITUDE_REF, EXIF_TYPE_ASCII, + 2, exifInfo->gps_longitude_ref); + writeExifIfd(&pCur, EXIF_TAG_GPS_LONGITUDE, EXIF_TYPE_RATIONAL, + 3, exifInfo->gps_longitude, &LongerTagOffest, pIfdStart); + writeExifIfd(&pCur, EXIF_TAG_GPS_ALTITUDE_REF, EXIF_TYPE_BYTE, + 1, exifInfo->gps_altitude_ref); + writeExifIfd(&pCur, EXIF_TAG_GPS_ALTITUDE, EXIF_TYPE_RATIONAL, + 1, &exifInfo->gps_altitude, &LongerTagOffest, pIfdStart); + writeExifIfd(&pCur, EXIF_TAG_GPS_TIMESTAMP, EXIF_TYPE_RATIONAL, + 3, exifInfo->gps_timestamp, &LongerTagOffest, pIfdStart); + tmp = strlen((char*)exifInfo->gps_processing_method); + if (tmp > 0) { + if (tmp > 100) { + tmp = 100; + } + static const char ExifAsciiPrefix[] = { 0x41, 0x53, 0x43, 0x49, 0x49, 0x0, 0x0, 0x0 }; + unsigned char tmp_buf[100+sizeof(ExifAsciiPrefix)]; + memcpy(tmp_buf, ExifAsciiPrefix, sizeof(ExifAsciiPrefix)); + memcpy(&tmp_buf[sizeof(ExifAsciiPrefix)], exifInfo->gps_processing_method, tmp); + writeExifIfd(&pCur, EXIF_TAG_GPS_PROCESSING_METHOD, EXIF_TYPE_UNDEFINED, + tmp+sizeof(ExifAsciiPrefix), tmp_buf, &LongerTagOffest, pIfdStart); + } + writeExifIfd(&pCur, EXIF_TAG_GPS_DATESTAMP, EXIF_TYPE_ASCII, + 11, exifInfo->gps_datestamp, &LongerTagOffest, pIfdStart); + tmp = 0; + memcpy(pCur, &tmp, OFFSET_SIZE); // next IFD offset + pCur += OFFSET_SIZE; + } + + //2 1th IFD TIFF Tags + + unsigned char *thumbBuf = thumb_buf; + unsigned int thumbSize = thumb_size; + + if (exifInfo->enableThumb && (thumbBuf != NULL) && (thumbSize > 0)) { + tmp = LongerTagOffest; + memcpy(pNextIfdOffset, &tmp, OFFSET_SIZE); // NEXT IFD offset skipped on 0th IFD + + pCur = pIfdStart + LongerTagOffest; + + tmp = NUM_1TH_IFD_TIFF; + memcpy(pCur, &tmp, NUM_SIZE); + pCur += NUM_SIZE; + + LongerTagOffest += NUM_SIZE + NUM_1TH_IFD_TIFF*IFD_SIZE + OFFSET_SIZE; + + writeExifIfd(&pCur, EXIF_TAG_IMAGE_WIDTH, EXIF_TYPE_LONG, + 1, exifInfo->widthThumb); + writeExifIfd(&pCur, EXIF_TAG_IMAGE_HEIGHT, EXIF_TYPE_LONG, + 1, exifInfo->heightThumb); + writeExifIfd(&pCur, EXIF_TAG_COMPRESSION_SCHEME, EXIF_TYPE_SHORT, + 1, exifInfo->compression_scheme); + writeExifIfd(&pCur, EXIF_TAG_ORIENTATION, EXIF_TYPE_SHORT, + 1, exifInfo->orientation); + writeExifIfd(&pCur, EXIF_TAG_X_RESOLUTION, EXIF_TYPE_RATIONAL, + 1, &exifInfo->x_resolution, &LongerTagOffest, pIfdStart); + writeExifIfd(&pCur, EXIF_TAG_Y_RESOLUTION, EXIF_TYPE_RATIONAL, + 1, &exifInfo->y_resolution, &LongerTagOffest, pIfdStart); + writeExifIfd(&pCur, EXIF_TAG_RESOLUTION_UNIT, EXIF_TYPE_SHORT, + 1, exifInfo->resolution_unit); + writeExifIfd(&pCur, EXIF_TAG_JPEG_INTERCHANGE_FORMAT, EXIF_TYPE_LONG, + 1, LongerTagOffest); + writeExifIfd(&pCur, EXIF_TAG_JPEG_INTERCHANGE_FORMAT_LEN, EXIF_TYPE_LONG, + 1, thumbSize); + + tmp = 0; + memcpy(pCur, &tmp, OFFSET_SIZE); // next IFD offset + pCur += OFFSET_SIZE; + + memcpy(pIfdStart + LongerTagOffest, thumbBuf, thumbSize); + LongerTagOffest += thumbSize; + } else { + tmp = 0; + memcpy(pNextIfdOffset, &tmp, OFFSET_SIZE); // NEXT IFD offset skipped on 0th IFD + } + + unsigned char App1Marker[2] = { 0xff, 0xe1 }; + memcpy(pApp1Start, App1Marker, 2); + pApp1Start += 2; + + *size = 10 + LongerTagOffest; + tmp = *size - 2; // APP1 Maker isn't counted + unsigned char size_mm[2] = {(tmp >> 8) & 0xFF, tmp & 0xFF}; + memcpy(pApp1Start, size_mm, 2); + + LOGD("makeExif X"); + + return 0; +} + +inline void SecCamera::writeExifIfd(unsigned char **pCur, + unsigned short tag, + unsigned short type, + unsigned int count, + uint32_t value) +{ + memcpy(*pCur, &tag, 2); + *pCur += 2; + memcpy(*pCur, &type, 2); + *pCur += 2; + memcpy(*pCur, &count, 4); + *pCur += 4; + memcpy(*pCur, &value, 4); + *pCur += 4; +} + +inline void SecCamera::writeExifIfd(unsigned char **pCur, + unsigned short tag, + unsigned short type, + unsigned int count, + unsigned char *pValue) +{ + char buf[4] = { 0,}; + + memcpy(buf, pValue, count); + memcpy(*pCur, &tag, 2); + *pCur += 2; + memcpy(*pCur, &type, 2); + *pCur += 2; + memcpy(*pCur, &count, 4); + *pCur += 4; + memcpy(*pCur, buf, 4); + *pCur += 4; +} + +inline void SecCamera::writeExifIfd(unsigned char **pCur, + unsigned short tag, + unsigned short type, + unsigned int count, + unsigned char *pValue, + unsigned int *offset, + unsigned char *start) +{ + memcpy(*pCur, &tag, 2); + *pCur += 2; + memcpy(*pCur, &type, 2); + *pCur += 2; + memcpy(*pCur, &count, 4); + *pCur += 4; + memcpy(*pCur, offset, 4); + *pCur += 4; + memcpy(start + *offset, pValue, count); + *offset += count; +} + +inline void SecCamera::writeExifIfd(unsigned char **pCur, + unsigned short tag, + unsigned short type, + unsigned int count, + rational_t *pValue, + unsigned int *offset, + unsigned char *start) +{ + memcpy(*pCur, &tag, 2); + *pCur += 2; + memcpy(*pCur, &type, 2); + *pCur += 2; + memcpy(*pCur, &count, 4); + *pCur += 4; + memcpy(*pCur, offset, 4); + *pCur += 4; + memcpy(start + *offset, pValue, 8 * count); + *offset += 8 * count; +} + +status_t SecCamera::dump(int fd) +{ + const size_t SIZE = 256; + char buffer[SIZE]; + String8 result; + snprintf(buffer, 255, "dump(%d)\n", fd); + result.append(buffer); + ::write(fd, result.string(), result.size()); + return NO_ERROR; +} + +double SecCamera::jpeg_ratio = 0.7; +int SecCamera::interleaveDataSize = 5242880; +int SecCamera::jpegLineLength = 636; + +}; // namespace android diff --git a/exynos5/hal/libcamera/SecCamera.h b/exynos5/hal/libcamera/SecCamera.h new file mode 100644 index 0000000..1af19ee --- /dev/null +++ b/exynos5/hal/libcamera/SecCamera.h @@ -0,0 +1,698 @@ +/* +** +** Copyright 2008, The Android Open Source Project +** Copyright 2010, Samsung Electronics Co. LTD +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + +#ifndef ANDROID_HARDWARE_CAMERA_SEC_H +#define ANDROID_HARDWARE_CAMERA_SEC_H + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include "SecBuffer.h" + +#include +#include + +#include + +#include "SecJpegEncoder.h" + +#include "Exif.h" +namespace android { + +//#define ENABLE_ESD_PREVIEW_CHECK + +#if defined(LOG_NDEBUG) && (LOG_NDEBUG == 0) +#define LOG_CAMERA LOGD +#define LOG_CAMERA_PREVIEW LOGD + +#define LOG_TIME_DEFINE(n) \ + struct timeval time_start_##n, time_stop_##n; unsigned long log_time_##n = 0; + +#define LOG_TIME_START(n) \ + gettimeofday(&time_start_##n, NULL); + +#define LOG_TIME_END(n) \ + gettimeofday(&time_stop_##n, NULL); log_time_##n = measure_time_camera(&time_start_##n, &time_stop_##n); + +#define LOG_TIME(n) \ + log_time_##n + +#else +#define LOG_CAMERA(...) +#define LOG_CAMERA_PREVIEW(...) +#define LOG_TIME_DEFINE(n) +#define LOG_TIME_START(n) +#define LOG_TIME_END(n) +#define LOG_TIME(n) +#endif + +#define JOIN(x, y) JOIN_AGAIN(x, y) +#define JOIN_AGAIN(x, y) x ## y + +#define FRONT_CAM M5MO +#define BACK_CAM S5K4E5 + +#if !defined (FRONT_CAM) || !defined(BACK_CAM) +#error "Please define the Camera module" +#endif + +#define M5MO_PREVIEW_WIDTH 1920 +#define M5MO_PREVIEW_HEIGHT 1080 +#define M5MO_SNAPSHOT_WIDTH 3264 +#define M5MO_SNAPSHOT_HEIGHT 2448 + +#define M5MO_THUMBNAIL_WIDTH 320 +#define M5MO_THUMBNAIL_HEIGHT 240 +#define M5MO_THUMBNAIL_BPP 16 + +#define M5MO_FPS 30 + +/* focal length of 3.43mm */ +#define M5MO_FOCAL_LENGTH 343 + +#define S5K4E5_PREVIEW_WIDTH 1920 +#define S5K4E5_PREVIEW_HEIGHT 1080 +#define S5K4E5_SNAPSHOT_WIDTH 1920 +#define S5K4E5_SNAPSHOT_HEIGHT 1080 + +#define S5K4E5_THUMBNAIL_WIDTH 320 +#define S5K4E5_THUMBNAIL_HEIGHT 240 +#define S5K4E5_THUMBNAIL_BPP 16 + +#define S5K4E5_FPS 30 + +/* focal length of 0.9mm */ +#define S5K4E5_FOCAL_LENGTH 90 + +#define MAX_BACK_CAMERA_PREVIEW_WIDTH JOIN(BACK_CAM,_PREVIEW_WIDTH) +#define MAX_BACK_CAMERA_PREVIEW_HEIGHT JOIN(BACK_CAM,_PREVIEW_HEIGHT) +#define MAX_BACK_CAMERA_SNAPSHOT_WIDTH JOIN(BACK_CAM,_SNAPSHOT_WIDTH) +#define MAX_BACK_CAMERA_SNAPSHOT_HEIGHT JOIN(BACK_CAM,_SNAPSHOT_HEIGHT) + +#define BACK_CAMERA_THUMBNAIL_WIDTH JOIN(BACK_CAM,_THUMBNAIL_WIDTH) +#define BACK_CAMERA_THUMBNAIL_HEIGHT JOIN(BACK_CAM,_THUMBNAIL_HEIGHT) +#define BACK_CAMERA_THUMBNAIL_BPP JOIN(BACK_CAM,_THUMBNAIL_BPP) + +#define BACK_CAMERA_FPS JOIN(BACK_CAM,_FPS) + +#define BACK_CAMERA_FOCAL_LENGTH JOIN(BACK_CAM,_FOCAL_LENGTH) + +#define MAX_FRONT_CAMERA_PREVIEW_WIDTH JOIN(FRONT_CAM,_PREVIEW_WIDTH) +#define MAX_FRONT_CAMERA_PREVIEW_HEIGHT JOIN(FRONT_CAM,_PREVIEW_HEIGHT) +#define MAX_FRONT_CAMERA_SNAPSHOT_WIDTH JOIN(FRONT_CAM,_SNAPSHOT_WIDTH) +#define MAX_FRONT_CAMERA_SNAPSHOT_HEIGHT JOIN(FRONT_CAM,_SNAPSHOT_HEIGHT) + +#define FRONT_CAMERA_THUMBNAIL_WIDTH JOIN(FRONT_CAM,_THUMBNAIL_WIDTH) +#define FRONT_CAMERA_THUMBNAIL_HEIGHT JOIN(FRONT_CAM,_THUMBNAIL_HEIGHT) +#define FRONT_CAMERA_THUMBNAIL_BPP JOIN(FRONT_CAM,_THUMBNAIL_BPP) + +#define FRONT_CAMERA_FPS JOIN(FRONT_CAM,_FPS) + +#define FRONT_CAMERA_FOCAL_LENGTH JOIN(FRONT_CAM,_FOCAL_LENGTH) + +#define DEFAULT_JPEG_THUMBNAIL_WIDTH 256 +#define DEFAULT_JPEG_THUMBNAIL_HEIGHT 192 + +#define PFX_NODE_GSC "/dev/video" + +#define M5MOLS_ENTITY_NAME "M5MOLS 5-001f" +#define PFX_SUBDEV_ENTITY_MIPI_CSIS "s5p-mipi-csis" +#define PFX_SUBDEV_ENTITY_FLITE "exynos-fimc-lite" +#define PFX_SUBDEV_ENTITY_GSC_CAP "gsc-cap-subdev" +#define PFX_VIDEODEV_ENTITY_GSC_CAP "exynos-gsc" +#define FIMD1_ENTITY_NAME "s5p-fimd1" + +#define GAIA_FW_BETA 1 + +#ifndef GAIA_FW_BETA +#define GSC_VD_NODE_OFFSET 25 //GSCALER 0 (0:25, 1:28, 2:31, 3:34) +#else +#define GSC_VD_NODE_OFFSET 41 //INTERNAL_ISP 4E5 + +#define ISP_SENSOR_MAX_ENTITIES 1 +#define ISP_SENSOR_PAD_SOURCE_FRONT 0 +#define ISP_SENSOR_PADS_NUM 1 + +#define ISP_FRONT_MAX_ENTITIES 1 +#define ISP_FRONT_PAD_SINK 0 +#define ISP_FRONT_PAD_SOURCE_BACK 1 +#define ISP_FRONT_PAD_SOURCE_BAYER 2 +#define ISP_FRONT_PAD_SOURCE_SCALERC 3 +#define ISP_FRONT_PADS_NUM 4 + +#define ISP_BACK_MAX_ENTITIES 1 +#define ISP_BACK_PAD_SINK 0 +#define ISP_BACK_PAD_SOURCE_3DNR 1 +#define ISP_BACK_PAD_SOURCE_SCALERP 2 +#define ISP_BACK_PADS_NUM 3 + +#define ISP_MODULE_NAME "exynos5-fimc-is" +#define ISP_SENSOR_ENTITY_NAME "exynos5-fimc-is-sensor" +#define ISP_FRONT_ENTITY_NAME "exynos5-fimc-is-front" +#define ISP_BACK_ENTITY_NAME "exynos5-fimc-is-back" +#define ISP_VIDEO_BAYER_NAME "exynos5-fimc-is-bayer" +#define ISP_VIDEO_SCALERC_NAME "exynos5-fimc-is-scalerc" +#define ISP_VIDEO_3DNR_NAME "exynos5-fimc-is-3dnr" +#define ISP_VIDEO_SCALERP_NAME "exynos5-fimc-is-scalerp" + +#endif +#define MIPI_NUM 1 +#define FLITE_NUM 1 +#define GSC_NUM 0 + +#define PFX_SUBDEV_NODE "/dev/v4l-subdev" + +#define BPP 2 +#define MIN(x, y) (((x) < (y)) ? (x) : (y)) +#ifndef GAIA_FW_BETA +#define MAX_BUFFERS 8 +#else +#define MAX_BUFFERS 4 //external : 8, internal : 4 +#endif + +#define MAX_PLANES (3) +#define V4L2_BUF_TYPE V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE + +#define V4L2_MEMORY_TYPE V4L2_MEMORY_USERPTR +#define RECORD_PIX_FMT V4L2_PIX_FMT_NV12M +#define PREVIEW_NUM_PLANE (3) +#define RECORD_NUM_PLANE (2) + +/* + * V 4 L 2 F I M C E X T E N S I O N S + * + */ +#define V4L2_CID_ROTATION (V4L2_CID_PRIVATE_BASE + 0) +#define V4L2_CID_PADDR_Y (V4L2_CID_PRIVATE_BASE + 1) +#define V4L2_CID_PADDR_CB (V4L2_CID_PRIVATE_BASE + 2) +#define V4L2_CID_PADDR_CR (V4L2_CID_PRIVATE_BASE + 3) +#define V4L2_CID_PADDR_CBCR (V4L2_CID_PRIVATE_BASE + 4) +#define V4L2_CID_STREAM_PAUSE (V4L2_CID_PRIVATE_BASE + 53) + +#define V4L2_CID_CAM_JPEG_MAIN_SIZE (V4L2_CID_PRIVATE_BASE + 32) +#define V4L2_CID_CAM_JPEG_MAIN_OFFSET (V4L2_CID_PRIVATE_BASE + 33) +#define V4L2_CID_CAM_JPEG_THUMB_SIZE (V4L2_CID_PRIVATE_BASE + 34) +#define V4L2_CID_CAM_JPEG_THUMB_OFFSET (V4L2_CID_PRIVATE_BASE + 35) +#define V4L2_CID_CAM_JPEG_POSTVIEW_OFFSET (V4L2_CID_PRIVATE_BASE + 36) +#define V4L2_CID_CAM_JPEG_QUALITY (V4L2_CID_PRIVATE_BASE + 37) + +#define TPATTERN_COLORBAR 1 +#define TPATTERN_HORIZONTAL 2 +#define TPATTERN_VERTICAL 3 + +#define V4L2_PIX_FMT_YVYU v4l2_fourcc('Y', 'V', 'Y', 'U') + +/* FOURCC for FIMC specific */ +#define V4L2_PIX_FMT_VYUY v4l2_fourcc('V', 'Y', 'U', 'Y') +#define V4L2_PIX_FMT_NV16 v4l2_fourcc('N', 'V', '1', '6') +#define V4L2_PIX_FMT_NV61 v4l2_fourcc('N', 'V', '6', '1') +#define V4L2_PIX_FMT_NV12T v4l2_fourcc('T', 'V', '1', '2') +/* + * U S E R D E F I N E D T Y P E S + * + */ +#define PREVIEW_MODE 1 +#define RECORD_MODE 2 + +/* We use this struct as the v4l2_streamparm raw_data for + * VIDIOC_G_PARM and VIDIOC_S_PARM + */ +struct sec_cam_parm { + struct v4l2_captureparm capture; + int contrast; + int effects; + int brightness; + int exposure; + int flash_mode; + int focus_mode; + int iso; + int metering; + int saturation; + int scene_mode; + int sharpness; + int hue; + int white_balance; +}; + +struct yuv_fmt_list { + const char *name; + const char *desc; + unsigned int fmt; + int depth; + int planes; +}; + +struct camsensor_date_info { + unsigned int year; + unsigned int month; + unsigned int date; +}; + +class SecCamera : public virtual RefBase { +public: + + enum CAMERA_ID { + CAMERA_ID_BACK = 0, + CAMERA_ID_FRONT = 1, + }; + + enum JPEG_QUALITY { + JPEG_QUALITY_ECONOMY = 0, + JPEG_QUALITY_NORMAL = 50, + JPEG_QUALITY_SUPERFINE = 100, + JPEG_QUALITY_MAX, + }; + + enum OBJECT_TRACKING { + OBJECT_TRACKING_OFF, + OBJECT_TRACKING_ON, + OBJECT_TRACKING_MAX, + }; + + /*VT call*/ + enum VT_MODE { + VT_MODE_OFF, + VT_MODE_ON, + VT_MODE_MAX, + }; + + /*Camera sensor mode - Camcorder fix fps*/ + enum SENSOR_MODE { + SENSOR_MODE_CAMERA, + SENSOR_MODE_MOVIE, + }; + + /*Camera Shot mode*/ + enum SHOT_MODE { + SHOT_MODE_SINGLE = 0, + SHOT_MODE_CONTINUOUS = 1, + SHOT_MODE_PANORAMA = 2, + SHOT_MODE_SMILE = 3, + SHOT_MODE_SELF = 6, + }; + + enum CHK_DATALINE { + CHK_DATALINE_OFF, + CHK_DATALINE_ON, + CHK_DATALINE_MAX, + }; + + int m_touch_af_start_stop; + + SecCamera(); + virtual ~SecCamera(); + + static SecCamera* createInstance(void) + { + static SecCamera singleton; + return &singleton; + } + status_t dump(int fd); + + bool CreateCamera(int index); + bool DestroyCamera(void); + int getCameraId(void); + + int startPreview(void); + int stopPreview(void); + int getPreviewState(void) + { + return m_preview_state; + } + void clearPreviewState(void) + { + m_preview_state = 0; + } + + int startRecord(void); + int stopRecord(void); + int setPreviewFrame(int index); + int getRecordFrame(void); + int releaseRecordFrame(int index); + int getRecordAddr(int index, SecBuffer *buffer); + + int getPreview(void); + int setPreviewSize(int width, int height, int pixel_format); + int getPreviewSize(int *width, int *height, int *frame_size); + int getPreviewMaxSize(int *width, int *height); + int getPreviewPixelFormat(void); + int setPreviewImage(int index, unsigned char *buffer, int size); + + int setSnapshotSize(int width, int height); + int getSnapshotSize(int *width, int *height, int *frame_size); + int getSnapshotMaxSize(int *width, int *height); + int setSnapshotPixelFormat(int pixel_format); + int getSnapshotPixelFormat(void); + + unsigned char* getJpeg(unsigned char *snapshot_data, int snapshot_size, int *size); + unsigned char* yuv2Jpeg(unsigned char *raw_data, int raw_size, + int *jpeg_size, + int width, int height, int pixel_format); + + int setJpegThumbnailSize(int width, int height); + int getJpegThumbnailSize(int *width, int *height); + + int setJpegThumbnailQuality(int jpeg_thumbnail_quality); + int getJpegThumbnailQuality(void); + + int setAutofocus(void); + + int SetRotate(int angle); + int getRotate(void); + + int setVerticalMirror(void); + int setHorizontalMirror(void); + + int setWhiteBalance(int white_balance); + int getWhiteBalance(void); + + int setBrightness(int brightness); + int getBrightness(void); + + int setExposure(int exposure); + int getExposure(void); + + int setImageEffect(int image_effect); + int getImageEffect(void); + + int setSceneMode(int scene_mode); + int getSceneMode(void); + + int setFlashMode(int flash_mode); + int getFlashMode(void); + + int setMetering(int metering_value); + int getMetering(void); + + int setISO(int iso_value); + int getISO(void); + + int setContrast(int contrast_value); + int getContrast(void); + + int setSaturation(int saturation_value); + int getSaturation(void); + + int setSharpness(int sharpness_value); + int getSharpness(void); + + int setHue(int hue_value); + int getHue(void); + + int setWDR(int wdr_value); + int getWDR(void); + + int setAntiShake(int anti_shake); + int getAntiShake(void); + + int setJpegQuality(int jpeg_qality); + int getJpegQuality(void); + + int setZoom(int zoom_level); + int getZoom(void); + + int setObjectTracking(int object_tracking); + int getObjectTracking(void); + int getObjectTrackingStatus(void); + + int setSmartAuto(int smart_auto); + int getSmartAuto(void); + int getAutosceneStatus(void); + + int setBeautyShot(int beauty_shot); + int getBeautyShot(void); + + int setVintageMode(int vintage_mode); + int getVintageMode(void); + + int setFocusMode(int focus_mode); + int getFocusMode(void); + + int setFaceDetect(int face_detect); + int getFaceDetect(void); + + int setGPSLatitude(const char *gps_latitude); + int setGPSLongitude(const char *gps_longitude); + int setGPSAltitude(const char *gps_altitude); + int setGPSTimeStamp(const char *gps_timestamp); + int setGPSProcessingMethod(const char *gps_timestamp); + int cancelAutofocus(void); + int setFaceDetectLockUnlock(int facedetect_lockunlock); + int setObjectPosition(int x, int y); + int setObjectTrackingStartStop(int start_stop); + int setTouchAFStartStop(int start_stop); + int setCAFStatus(int on_off); + int getAutoFocusResult(void); + int setAntiBanding(int anti_banding); + int getPostview(void); + int setRecording(int recording_en); + int setRecordingSize(int width, int height); + int getRecordingSize(int *width, int *height); + int setGamma(int gamma); + int setSlowAE(int slow_ae); + int setExifOrientationInfo(int orientationInfo); + int setBatchReflection(void); + int setSnapshotCmd(void); + int endSnapshot(void); + int setCameraSensorReset(void); + int setSensorMode(int sensor_mode); /* Camcorder fix fps */ + int setShotMode(int shot_mode); /* Shot mode */ + int setDataLineCheck(int chk_dataline); + int getDataLineCheck(void); + int setDataLineCheckStop(void); + int setDefultIMEI(int imei); + int getDefultIMEI(void); + const __u8* getCameraSensorName(void); +#ifdef ENABLE_ESD_PREVIEW_CHECK + int getCameraSensorESDStatus(void); +#endif // ENABLE_ESD_PREVIEW_CHECK + + int setFrameRate(int frame_rate); + unsigned char* getJpeg(int*, unsigned int*); + int getSnapshotAndJpeg(unsigned char *yuv_buf, unsigned char *jpeg_buf, + unsigned int *output_size); + int getExif(unsigned char *pExifDst, unsigned char *pThumbSrc); + + void getPostViewConfig(int*, int*, int*); + void getThumbnailConfig(int *width, int *height, int *size); + + int getPostViewOffset(void); + int getCameraFd(void); + unsigned char* getPictureVaddr(void); + int getJpegFd(void); + void SetJpgAddr(unsigned char *addr); + int getPreviewAddr(int index, SecBuffer *buffer); + void setUserBufferAddr(void *ptr, int index, int mode); + static void setJpegRatio(double ratio) + { + if((ratio < 0) || (ratio > 1)) + return; + + jpeg_ratio = ratio; + } + + static double getJpegRatio() + { + return jpeg_ratio; + } + + static void setInterleaveDataSize(int x) + { + interleaveDataSize = x; + } + + static int getInterleaveDataSize() + { + return interleaveDataSize; + } + + static void setJpegLineLength(int x) + { + jpegLineLength = x; + } + + static int getJpegLineLength() + { + return jpegLineLength; + } + +private: + v4l2_streamparm m_streamparm; + struct sec_cam_parm *m_params; + int m_flagCreate; + int m_preview_state; + int m_camera_id; + + /* v4l2 sub-dev file description */ + int m_cam_sd_fd; + int m_mipi_sd_fd; + int m_flite_sd_fd; + int m_gsc_sd_fd; + int m_gsc_vd_fd; + + /* media controller variable */ + struct media_device *media; + struct media_link *links; + struct media_pad *pads; + + struct media_entity *camera_sd_entity; + struct media_entity *mipi_sd_entity; + struct media_entity *flite_sd_entity; + struct media_entity *gsc_cap_sd_entity; + struct media_entity *gsc_cap_vd_entity; + struct media_entity *isp_sensor_entity; + struct media_entity *isp_front_entity; + struct media_entity *isp_back_entity; + struct media_entity *isp_scalerc_entity; + struct media_entity *isp_scalerp_entity; + struct media_entity *isp_3dnr_entity; + + int m_cam_fd; + + int m_cam_fd2; + struct pollfd m_events_c2; + int m_flag_record_start; + + int m_preview_v4lformat; + int m_preview_width; + int m_preview_height; + int m_preview_max_width; + int m_preview_max_height; + + int m_snapshot_v4lformat; + int m_snapshot_width; + int m_snapshot_height; + int m_snapshot_max_width; + int m_snapshot_max_height; + unsigned char* m_picture_vaddr; + + int m_angle; + int m_anti_banding; + int m_wdr; + int m_anti_shake; + int m_zoom_level; + int m_object_tracking; + int m_smart_auto; + int m_beauty_shot; + int m_vintage_mode; + int m_face_detect; + int m_object_tracking_start_stop; + int m_recording_en; + int m_recording_width; + int m_recording_height; + long m_gps_latitude; + long m_gps_longitude; + long m_gps_altitude; + long m_gps_timestamp; + int m_sensor_mode; /*Camcorder fix fps */ + int m_shot_mode; /* Shot mode */ + int m_exif_orientation; + int m_chk_dataline; + int m_video_gamma; + int m_slow_ae; + int m_camera_af_flag; + + int m_flag_camera_start; + + int m_jpeg_fd; + int m_jpeg_thumbnail_width; + int m_jpeg_thumbnail_height; + int m_jpeg_thumbnail_quality; + int m_jpeg_quality; + + int m_postview_offset; + +#ifdef ENABLE_ESD_PREVIEW_CHECK + int m_esd_check_count; +#endif // ENABLE_ESD_PREVIEW_CHECK + + exif_attribute_t mExifInfo; + + struct SecBuffer m_capture_buf; + struct SecBuffer m_buffers_preview[MAX_BUFFERS]; + struct SecBuffer m_buffers_record[MAX_BUFFERS]; + struct pollfd m_events_c; + + inline void writeExifIfd(unsigned char **pCur, + unsigned short tag, + unsigned short type, + unsigned int count, + uint32_t value); + inline void writeExifIfd(unsigned char **pCur, + unsigned short tag, + unsigned short type, + unsigned int count, + unsigned char *pValue); + inline void writeExifIfd(unsigned char **pCur, + unsigned short tag, + unsigned short type, + unsigned int count, + rational_t *pValue, + unsigned int *offset, + unsigned char *start); + inline void writeExifIfd(unsigned char **pCur, + unsigned short tag, + unsigned short type, + unsigned int count, + unsigned char *pValue, + unsigned int *offset, + unsigned char *start); + + void setExifChangedAttribute(); + void setExifFixedAttribute(); + int makeExif (unsigned char *exifOut, + unsigned char *thumb_buf, + unsigned int thumb_size, + exif_attribute_t *exifInfo, + unsigned int *size, + bool useMainbufForThumb); + void resetCamera(); + + static double jpeg_ratio; + static int interleaveDataSize; + static int jpegLineLength; +}; + +extern unsigned long measure_time_camera(struct timeval *start, struct timeval *stop); + +}; // namespace android + +#endif // ANDROID_HARDWARE_CAMERA_SEC_H diff --git a/exynos5/hal/libcamera/SecCameraHWInterface.cpp b/exynos5/hal/libcamera/SecCameraHWInterface.cpp new file mode 100644 index 0000000..8cfbccc --- /dev/null +++ b/exynos5/hal/libcamera/SecCameraHWInterface.cpp @@ -0,0 +1,3043 @@ +/* +** +** Copyright 2008, The Android Open Source Project +** Copyright 2010, Samsung Electronics Co. LTD +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +//#define LOG_NDEBUG 0 +#define LOG_TAG "CameraHardwareSec" +#include + +#include "SecCameraHWInterface.h" +#include +#include +#include +#include +#include + +#define VIDEO_COMMENT_MARKER_H 0xFFBE +#define VIDEO_COMMENT_MARKER_L 0xFFBF +#define VIDEO_COMMENT_MARKER_LENGTH 4 +#define JPEG_EOI_MARKER 0xFFD9 +#define HIBYTE(x) (((x) >> 8) & 0xFF) +#define LOBYTE(x) ((x) & 0xFF) +#define ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1)) + +#define BACK_CAMERA_AUTO_FOCUS_DISTANCES_STR "0.10,1.20,Infinity" +#define BACK_CAMERA_MACRO_FOCUS_DISTANCES_STR "0.10,0.20,Infinity" +#define BACK_CAMERA_INFINITY_FOCUS_DISTANCES_STR "0.10,1.20,Infinity" +#define FRONT_CAMERA_FOCUS_DISTANCES_STR "0.20,0.25,Infinity" +//#define USE_EGL + +// This hack does two things: +// -- it sets preview to NV21 (YUV420SP) +// -- it sets gralloc to YV12 +// +// The reason being: the samsung encoder understands only yuv420sp, and gralloc +// does yv12 and rgb565. So what we do is we break up the interleaved UV in +// separate V and U planes, which makes preview look good, and enabled the +// encoder as well. +// +// FIXME: Samsung needs to enable support for proper yv12 coming out of the +// camera, and to fix their video encoder to work with yv12. +// FIXME: It also seems like either Samsung's YUV420SP (NV21) or img's YV12 has +// the color planes switched. We need to figure which side is doing it +// wrong and have the respective party fix it. + +namespace android { + +struct addrs { + uint32_t type; // make sure that this is 4 byte. + unsigned int addr_y; + unsigned int addr_cbcr; + unsigned int buf_index; + unsigned int reserved; +}; + +struct addrs_cap { + unsigned int addr_y; + unsigned int width; + unsigned int height; +}; + +static const int INITIAL_SKIP_FRAME = 3; +static const int EFFECT_SKIP_FRAME = 1; + +gralloc_module_t const* CameraHardwareSec::mGrallocHal; + +CameraHardwareSec::CameraHardwareSec(int cameraId, camera_device_t *dev) + : + mCaptureInProgress(false), + mParameters(), + mFrameSizeDelta(0), + mCameraSensorName(NULL), + mSkipFrame(0), + mNotifyCb(0), + mDataCb(0), + mDataCbTimestamp(0), + mCallbackCookie(0), + mMsgEnabled(CAMERA_MSG_RAW_IMAGE), + mRecordRunning(false), + mPostViewWidth(0), + mPostViewHeight(0), + mPostViewSize(0), + mHalDevice(dev) +{ + LOGV("%s :", __func__); + int ret = 0; + + mPreviewWindow = NULL; + mSecCamera = SecCamera::createInstance(); + + mRawHeap = NULL; + mPreviewHeap = NULL; + for(int i = 0; i < BUFFER_COUNT_FOR_ARRAY; i++) + mRecordHeap[i] = NULL; + + if (!mGrallocHal) { + ret = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, (const hw_module_t **)&mGrallocHal); + if (ret) + LOGE("ERR(%s):Fail on loading gralloc HAL", __func__); + } + + ret = mSecCamera->CreateCamera(cameraId); + if (ret < 0) { + LOGE("ERR(%s):Fail on mSecCamera init", __func__); + mSecCamera->DestroyCamera(); + } + + initDefaultParameters(cameraId); + + mExitAutoFocusThread = false; + mExitPreviewThread = false; + /* whether the PreviewThread is active in preview or stopped. we + * create the thread but it is initially in stopped state. + */ + mPreviewRunning = false; + mPreviewStartDeferred = false; + mPreviewThread = new PreviewThread(this); + mAutoFocusThread = new AutoFocusThread(this); + mPictureThread = new PictureThread(this); +} + +int CameraHardwareSec::getCameraId() const +{ + return mSecCamera->getCameraId(); +} + +void CameraHardwareSec::initDefaultParameters(int cameraId) +{ + if (mSecCamera == NULL) { + LOGE("ERR(%s):mSecCamera object is NULL", __func__); + return; + } + + CameraParameters p; + CameraParameters ip; + +#ifndef GAIA_FW_BETA + mCameraSensorName = mSecCamera->getCameraSensorName(); + if (mCameraSensorName == NULL) { + LOGE("ERR(%s):mCameraSensorName is NULL", __func__); + return; + } + LOGV("CameraSensorName: %s", mCameraSensorName); + int Internal_is = !strncmp((const char*)mCameraSensorName, "ISP Camera", 10); +#else + int Internal_is = 0; + //sprintf((char *)mCameraSensorName, "%s", "temp name"); +#endif + int preview_max_width = 0; + int preview_max_height = 0; + int snapshot_max_width = 0; + int snapshot_max_height = 0; + + if (cameraId == SecCamera::CAMERA_ID_BACK) { + p.set(CameraParameters::KEY_SUPPORTED_PREVIEW_SIZES, + "3264x2448,2576x1948,1920x1080,1280x720,800x480,720x480,640x480,320x240,528x432,176x144"); + p.set(CameraParameters::KEY_SUPPORTED_PICTURE_SIZES, + "3264x2448,1920x1080,1280x720,800x480,720x480,640x480"); + if (Internal_is) + p.set(CameraParameters::KEY_SUPPORTED_VIDEO_SIZES, + "1920x1080,1280x720,640x480,176x144"); + } else { + p.set(CameraParameters::KEY_SUPPORTED_PREVIEW_SIZES, + "1392x1392,1280x720,640x480,352x288,320x240,176x144"); + p.set(CameraParameters::KEY_SUPPORTED_PICTURE_SIZES, + "1392x1392,1280x960,640x480"); + if (Internal_is) + p.set(CameraParameters::KEY_SUPPORTED_VIDEO_SIZES, + "1280x720,640x480,176x144"); + } + + p.getSupportedPreviewSizes(mSupportedPreviewSizes); + + // If these fail, then we are using an invalid cameraId and we'll leave the + // sizes at zero to catch the error. + if (mSecCamera->getPreviewMaxSize(&preview_max_width, + &preview_max_height) < 0) + LOGE("getPreviewMaxSize fail (%d / %d)", + preview_max_width, preview_max_height); + if (mSecCamera->getSnapshotMaxSize(&snapshot_max_width, + &snapshot_max_height) < 0) + LOGE("getSnapshotMaxSize fail (%d / %d)", + snapshot_max_width, snapshot_max_height); + + p.setPreviewFormat(CameraParameters::PIXEL_FORMAT_YUV420P); mFrameSizeDelta = 16; + p.set(CameraParameters::KEY_SUPPORTED_PREVIEW_FORMATS, CameraParameters::PIXEL_FORMAT_YUV420P); + p.set(CameraParameters::KEY_VIDEO_FRAME_FORMAT, CameraParameters::PIXEL_FORMAT_YUV420SP); + p.setPreviewSize(preview_max_width, preview_max_height); + + p.setPictureFormat(CameraParameters::PIXEL_FORMAT_JPEG); + p.setPictureSize(snapshot_max_width, snapshot_max_height); + p.set(CameraParameters::KEY_JPEG_QUALITY, "100"); // maximum quality + p.set(CameraParameters::KEY_SUPPORTED_PICTURE_FORMATS, + CameraParameters::PIXEL_FORMAT_JPEG); + + p.set(CameraParameters::KEY_PREFERRED_PREVIEW_SIZE_FOR_VIDEO, "1280x720"); + + String8 parameterString; + + if (cameraId == SecCamera::CAMERA_ID_BACK) { + parameterString = CameraParameters::FOCUS_MODE_AUTO; + parameterString.append(","); + parameterString.append(CameraParameters::FOCUS_MODE_INFINITY); + parameterString.append(","); + parameterString.append(CameraParameters::FOCUS_MODE_MACRO); + p.set(CameraParameters::KEY_SUPPORTED_FOCUS_MODES, + parameterString.string()); + p.set(CameraParameters::KEY_FOCUS_MODE, + CameraParameters::FOCUS_MODE_AUTO); + p.set(CameraParameters::KEY_FOCUS_DISTANCES, + BACK_CAMERA_AUTO_FOCUS_DISTANCES_STR); + p.set(CameraParameters::KEY_SUPPORTED_JPEG_THUMBNAIL_SIZES, + "320x240,0x0"); + p.set(CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH, "320"); + p.set(CameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT, "240"); + p.set(CameraParameters::KEY_SUPPORTED_PREVIEW_FRAME_RATES, "7,15,30"); + p.setPreviewFrameRate(30); + } else { + parameterString = CameraParameters::FOCUS_MODE_FIXED; + p.set(CameraParameters::KEY_SUPPORTED_FOCUS_MODES, + parameterString.string()); + p.set(CameraParameters::KEY_FOCUS_MODE, + CameraParameters::FOCUS_MODE_FIXED); + p.set(CameraParameters::KEY_FOCUS_DISTANCES, + FRONT_CAMERA_FOCUS_DISTANCES_STR); + p.set(CameraParameters::KEY_SUPPORTED_JPEG_THUMBNAIL_SIZES, + "160x120,0x0"); + p.set(CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH, "160"); + p.set(CameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT, "120"); + p.set(CameraParameters::KEY_SUPPORTED_PREVIEW_FRAME_RATES, "7,15,30"); + p.setPreviewFrameRate(30); + } + + parameterString = CameraParameters::EFFECT_NONE; + parameterString.append(","); + parameterString.append(CameraParameters::EFFECT_MONO); + parameterString.append(","); + parameterString.append(CameraParameters::EFFECT_NEGATIVE); + parameterString.append(","); + parameterString.append(CameraParameters::EFFECT_SEPIA); + p.set(CameraParameters::KEY_SUPPORTED_EFFECTS, parameterString.string()); + + if (cameraId == SecCamera::CAMERA_ID_BACK) { + parameterString = CameraParameters::FLASH_MODE_ON; + parameterString.append(","); + parameterString.append(CameraParameters::FLASH_MODE_OFF); + parameterString.append(","); + parameterString.append(CameraParameters::FLASH_MODE_AUTO); + parameterString.append(","); + parameterString.append(CameraParameters::FLASH_MODE_TORCH); + p.set(CameraParameters::KEY_SUPPORTED_FLASH_MODES, + parameterString.string()); + p.set(CameraParameters::KEY_FLASH_MODE, + CameraParameters::FLASH_MODE_OFF); + + parameterString = CameraParameters::SCENE_MODE_AUTO; + parameterString.append(","); + parameterString.append(CameraParameters::SCENE_MODE_PORTRAIT); + parameterString.append(","); + parameterString.append(CameraParameters::SCENE_MODE_LANDSCAPE); + parameterString.append(","); + parameterString.append(CameraParameters::SCENE_MODE_BEACH); + parameterString.append(","); + parameterString.append(CameraParameters::SCENE_MODE_SNOW); + parameterString.append(","); + parameterString.append(CameraParameters::SCENE_MODE_FIREWORKS); + parameterString.append(","); + parameterString.append(CameraParameters::SCENE_MODE_SPORTS); + parameterString.append(","); + parameterString.append(CameraParameters::SCENE_MODE_PARTY); + parameterString.append(","); + parameterString.append(CameraParameters::SCENE_MODE_CANDLELIGHT); + p.set(CameraParameters::KEY_SUPPORTED_SCENE_MODES, + parameterString.string()); + p.set(CameraParameters::KEY_SCENE_MODE, + CameraParameters::SCENE_MODE_AUTO); + + /* we have two ranges, 4-30fps for night mode and + * 15-30fps for all others + */ + p.set(CameraParameters::KEY_SUPPORTED_PREVIEW_FPS_RANGE, "(15000,30000)"); + p.set(CameraParameters::KEY_PREVIEW_FPS_RANGE, "15000,30000"); + + p.set(CameraParameters::KEY_FOCAL_LENGTH, "3.43"); + } else { + p.set(CameraParameters::KEY_SUPPORTED_PREVIEW_FPS_RANGE, "(7500,30000)"); + p.set(CameraParameters::KEY_PREVIEW_FPS_RANGE, "7500,30000"); + + p.set(CameraParameters::KEY_FOCAL_LENGTH, "0.9"); + } + + parameterString = CameraParameters::WHITE_BALANCE_AUTO; + parameterString.append(","); + parameterString.append(CameraParameters::WHITE_BALANCE_INCANDESCENT); + parameterString.append(","); + parameterString.append(CameraParameters::WHITE_BALANCE_FLUORESCENT); + parameterString.append(","); + parameterString.append(CameraParameters::WHITE_BALANCE_DAYLIGHT); + parameterString.append(","); + parameterString.append(CameraParameters::WHITE_BALANCE_CLOUDY_DAYLIGHT); + p.set(CameraParameters::KEY_SUPPORTED_WHITE_BALANCE, + parameterString.string()); + + p.set(CameraParameters::KEY_JPEG_THUMBNAIL_QUALITY, "100"); + + p.set(CameraParameters::KEY_ROTATION, 0); + p.set(CameraParameters::KEY_WHITE_BALANCE, CameraParameters::WHITE_BALANCE_AUTO); + + p.set(CameraParameters::KEY_EFFECT, CameraParameters::EFFECT_NONE); + + p.set("contrast", "auto"); + p.set("iso", "auto"); + p.set("metering", "center"); + p.set("wdr", 0); + + ip.set("chk_dataline", 0); + if (cameraId == SecCamera::CAMERA_ID_FRONT) { + ip.set("vtmode", 0); + ip.set("blur", 0); + } + + p.set(CameraParameters::KEY_HORIZONTAL_VIEW_ANGLE, "51.2"); + p.set(CameraParameters::KEY_VERTICAL_VIEW_ANGLE, "39.4"); + + p.set(CameraParameters::KEY_EXPOSURE_COMPENSATION, "0"); + p.set(CameraParameters::KEY_MAX_EXPOSURE_COMPENSATION, "2"); + p.set(CameraParameters::KEY_MIN_EXPOSURE_COMPENSATION, "-2"); + p.set(CameraParameters::KEY_EXPOSURE_COMPENSATION_STEP, "1"); + + p.set("brightness", 0); + p.set("brightness-max", 2); + p.set("brightness-min", -2); + + p.set("saturation", 0); + p.set("saturation-max", 2); + p.set("saturation-min", -2); + + p.set("sharpness", 0); + p.set("sharpness-max", 2); + p.set("sharpness-min", -2); + + p.set("hue", 0); + p.set("hue-max", 2); + p.set("hue-min", -2); + + parameterString = CameraParameters::ANTIBANDING_AUTO; + parameterString.append(","); + parameterString.append(CameraParameters::ANTIBANDING_50HZ); + parameterString.append(","); + parameterString.append(CameraParameters::ANTIBANDING_60HZ); + parameterString.append(","); + parameterString.append(CameraParameters::ANTIBANDING_OFF); + p.set(CameraParameters::KEY_SUPPORTED_ANTIBANDING, + parameterString.string()); + + p.set(CameraParameters::KEY_ANTIBANDING, CameraParameters::ANTIBANDING_OFF); + + mParameters = p; + mInternalParameters = ip; + + /* make sure mSecCamera has all the settings we do. applications + * aren't required to call setParameters themselves (only if they + * want to change something. + */ + setParameters(p); + if (cameraId == SecCamera::CAMERA_ID_BACK) + mSecCamera->setFrameRate(BACK_CAMERA_FPS); + else + mSecCamera->setFrameRate(FRONT_CAMERA_FPS); +} + +CameraHardwareSec::~CameraHardwareSec() +{ + LOGV("%s", __func__); + mSecCamera->DestroyCamera(); +} + +status_t CameraHardwareSec::setPreviewWindow(preview_stream_ops *w) +{ + int min_bufs; + + mPreviewWindow = w; + LOGV("%s: mPreviewWindow %p", __func__, mPreviewWindow); + + if (!w) { + LOGE("preview window is NULL!"); + return OK; + } + + mPreviewLock.lock(); + + if (mPreviewRunning && !mPreviewStartDeferred) { + LOGI("stop preview (window change)"); + stopPreviewInternal(); + } + + if (w->get_min_undequeued_buffer_count(w, &min_bufs)) { + LOGE("%s: could not retrieve min undequeued buffer count", __func__); + return INVALID_OPERATION; + } + + if (min_bufs >= BUFFER_COUNT_FOR_GRALLOC) { + LOGE("%s: min undequeued buffer count %d is too high (expecting at most %d)", __func__, + min_bufs, BUFFER_COUNT_FOR_GRALLOC - 1); + } + + LOGV("%s: setting buffer count to %d", __func__, BUFFER_COUNT_FOR_GRALLOC); + if (w->set_buffer_count(w, BUFFER_COUNT_FOR_GRALLOC)) { + LOGE("%s: could not set buffer count", __func__); + return INVALID_OPERATION; + } + + int preview_width; + int preview_height; + mParameters.getPreviewSize(&preview_width, &preview_height); + + int hal_pixel_format; + + const char *str_preview_format = mParameters.getPreviewFormat(); + LOGV("%s: str preview format %s width : %d height : %d ", __func__, str_preview_format, preview_width, preview_height); + mFrameSizeDelta = 16; + + hal_pixel_format = HAL_PIXEL_FORMAT_YV12; + + if (!strcmp(str_preview_format, + CameraParameters::PIXEL_FORMAT_RGB565)) { + hal_pixel_format = HAL_PIXEL_FORMAT_RGB_565; + mFrameSizeDelta = 0; + } else if (!strcmp(str_preview_format, + CameraParameters::PIXEL_FORMAT_RGBA8888)) { + hal_pixel_format = HAL_PIXEL_FORMAT_RGBA_8888; + mFrameSizeDelta = 0; + } else if (!strcmp(str_preview_format, + CameraParameters::PIXEL_FORMAT_YUV420SP)) { + hal_pixel_format = HAL_PIXEL_FORMAT_YCrCb_420_SP; + } else if (!strcmp(str_preview_format, + CameraParameters::PIXEL_FORMAT_YUV420P)) + hal_pixel_format = HAL_PIXEL_FORMAT_YV12; + +#ifdef USE_EGL + if (w->set_usage(w, GRALLOC_USAGE_SW_WRITE_OFTEN | GRALLOC_USAGE_HW_ION)) { + LOGE("%s: could not set usage on gralloc buffer", __func__); + return INVALID_OPERATION; + } +#else + if (w->set_usage(w, GRALLOC_USAGE_SW_WRITE_OFTEN + | GRALLOC_USAGE_HWC_HWOVERLAY | GRALLOC_USAGE_HW_ION)) { + LOGE("%s: could not set usage on gralloc buffer", __func__); + return INVALID_OPERATION; + } +#endif + + if (w->set_buffers_geometry(w, + preview_width, preview_height, + hal_pixel_format)) { + LOGE("%s: could not set buffers geometry to %s", + __func__, str_preview_format); + return INVALID_OPERATION; + } + + for(int i = 0; i < BUFFER_COUNT_FOR_ARRAY; i++) + if (0 != mPreviewWindow->dequeue_buffer(mPreviewWindow, &mBufferHandle[i], &mStride[i])) { + LOGE("%s: Could not dequeue gralloc buffer[%d]!!", __func__, i); + return INVALID_OPERATION; + } + + if (mPreviewRunning && mPreviewStartDeferred) { + LOGV("start/resume preview"); + status_t ret = startPreviewInternal(); + if (ret == OK) { + mPreviewStartDeferred = false; + mPreviewCondition.signal(); + } + } + mPreviewLock.unlock(); + + return OK; +} + +void CameraHardwareSec::setCallbacks(camera_notify_callback notify_cb, + camera_data_callback data_cb, + camera_data_timestamp_callback data_cb_timestamp, + camera_request_memory get_memory, + void *user) +{ + mNotifyCb = notify_cb; + mDataCb = data_cb; + mDataCbTimestamp = data_cb_timestamp; + mGetMemoryCb = get_memory; + mCallbackCookie = user; +} + +void CameraHardwareSec::enableMsgType(int32_t msgType) +{ + LOGV("%s : msgType = 0x%x, mMsgEnabled before = 0x%x", + __func__, msgType, mMsgEnabled); + mMsgEnabled |= msgType; + + mPreviewLock.lock(); + if ((msgType & (CAMERA_MSG_PREVIEW_FRAME | CAMERA_MSG_VIDEO_FRAME)) && + mPreviewRunning && mPreviewStartDeferred) { + LOGV("%s: starting deferred preview", __func__); + if (startPreviewInternal() == OK) { + mPreviewStartDeferred = false; + mPreviewCondition.signal(); + } + } + mPreviewLock.unlock(); + + LOGV("%s : mMsgEnabled = 0x%x", __func__, mMsgEnabled); +} + +void CameraHardwareSec::disableMsgType(int32_t msgType) +{ + LOGV("%s : msgType = 0x%x, mMsgEnabled before = 0x%x", + __func__, msgType, mMsgEnabled); + mMsgEnabled &= ~msgType; + LOGV("%s : mMsgEnabled = 0x%x", __func__, mMsgEnabled); +} + +bool CameraHardwareSec::msgTypeEnabled(int32_t msgType) +{ + return (mMsgEnabled & msgType); +} + +void CameraHardwareSec::setSkipFrame(int frame) +{ + Mutex::Autolock lock(mSkipFrameLock); + if (frame < mSkipFrame) + return; + + mSkipFrame = frame; +} + +int CameraHardwareSec::previewThreadWrapper() +{ + LOGI("%s: starting", __func__); + while (1) { + mPreviewLock.lock(); + while (!mPreviewRunning) { + LOGI("%s: calling mSecCamera->stopPreview() and waiting", __func__); + mSecCamera->stopPreview(); + /* signal that we're stopping */ + mPreviewStoppedCondition.signal(); + mPreviewCondition.wait(mPreviewLock); + LOGI("%s: return from wait", __func__); + } + mPreviewLock.unlock(); + + if (mExitPreviewThread) { + LOGI("%s: exiting", __func__); + mSecCamera->stopPreview(); + return 0; + } + previewThread(); + } +} + +int CameraHardwareSec::previewThread() +{ + int index; + nsecs_t timestamp; + SecBuffer previewAddr, recordAddr; + static int numArray = 0; + void *virAddr[3]; + private_handle_t *hnd = NULL; + + index = mSecCamera->getPreview(); + + if (index < 0) { + LOGE("ERR(%s):Fail on SecCamera->getPreview()", __func__); + if (mSecCamera->getPreviewState()) { + stopPreview(); + startPreview(); + mSecCamera->clearPreviewState(); + } + return UNKNOWN_ERROR; + } + + mSkipFrameLock.lock(); + if (mSkipFrame > 0) { + mSkipFrame--; + mSkipFrameLock.unlock(); + LOGV("%s: index %d skipping frame", __func__, index); + if (mSecCamera->setPreviewFrame(index) < 0) { + LOGE("%s: Could not qbuff[%d]!!", __func__, index); + return UNKNOWN_ERROR; + } + return NO_ERROR; + } + mSkipFrameLock.unlock(); + + timestamp = systemTime(SYSTEM_TIME_MONOTONIC); + + int width, height, frame_size, offset; + + mSecCamera->getPreviewSize(&width, &height, &frame_size); + + offset = frame_size * index; + + if (mPreviewWindow && mGrallocHal && mPreviewRunning) { + hnd = (private_handle_t*)*mBufferHandle[index]; + + if (mPreviewHeap) { + mPreviewHeap->release(mPreviewHeap); + mPreviewHeap = 0; + } + + mPreviewHeap = mGetMemoryCb(hnd->fd, frame_size, 1, 0); + + hnd = NULL; + + mGrallocHal->unlock(mGrallocHal, *mBufferHandle[index]); + if (0 != mPreviewWindow->enqueue_buffer(mPreviewWindow, mBufferHandle[index])) { + LOGE("%s: Could not enqueue gralloc buffer[%d]!!", __func__, index); + goto callbacks; + } + + numArray = index; + + if (0 != mPreviewWindow->dequeue_buffer(mPreviewWindow, &mBufferHandle[numArray], &mStride[numArray])) { + LOGE("%s: Could not dequeue gralloc buffer[%d]!!", __func__, numArray); + goto callbacks; + } + + if (!mGrallocHal->lock(mGrallocHal, + *mBufferHandle[numArray], + GRALLOC_USAGE_SW_WRITE_OFTEN | GRALLOC_USAGE_YUV_ADDR, + 0, 0, width, height, virAddr)) { + mSecCamera->getPreviewAddr(index, &previewAddr); + char *frame = (char *)previewAddr.virt.extP[0]; + +#ifdef USE_EGL + int m_Ywidth = ALIGN(width, 16); + int m_Yheight = ALIGN(height, 16); + int m_UVwidth = ALIGN(width/2, 8); + int m_UVheight = ALIGN(height/2, 8); + virAddr[1] = virAddr[0] + (m_Ywidth * m_Yheight); + virAddr[2] = virAddr[1] + (m_UVwidth * m_UVheight); +#endif + + mSecCamera->setUserBufferAddr(virAddr, index, PREVIEW_MODE); + } + else + LOGE("%s: could not obtain gralloc buffer", __func__); + + if (mSecCamera->setPreviewFrame(index) < 0) { + LOGE("%s: Fail qbuf, index(%d)", __func__, index); + goto callbacks; + } + index = 0; + } + +callbacks: + // Notify the client of a new frame. + if (mMsgEnabled & CAMERA_MSG_PREVIEW_FRAME) + mDataCb(CAMERA_MSG_PREVIEW_FRAME, mPreviewHeap, index, NULL, mCallbackCookie); + + Mutex::Autolock lock(mRecordLock); + if (mRecordRunning == true) { + int recordingIndex = 0; + + index = mSecCamera->getRecordFrame(); + if (index < 0) { + LOGE("ERR(%s):Fail on SecCamera->getRecordFrame()", __func__); + return UNKNOWN_ERROR; + } + + numArray = index; + + // Notify the client of a new frame. + if (mMsgEnabled & CAMERA_MSG_VIDEO_FRAME) + mDataCbTimestamp(timestamp, CAMERA_MSG_VIDEO_FRAME, + mRecordHeap[numArray], recordingIndex, mCallbackCookie); + else + mSecCamera->releaseRecordFrame(index); + } + + return NO_ERROR; +} + +status_t CameraHardwareSec::startPreview() +{ + int ret = 0; + + LOGV("%s :", __func__); + + Mutex::Autolock lock(mStateLock); + if (mCaptureInProgress) { + LOGE("%s : capture in progress, not allowed", __func__); + return INVALID_OPERATION; + } + + mPreviewLock.lock(); + if (mPreviewRunning) { + // already running + LOGE("%s : preview thread already running", __func__); + mPreviewLock.unlock(); + return INVALID_OPERATION; + } + + mPreviewRunning = true; + mPreviewStartDeferred = false; + + if (!mPreviewWindow && + !(mMsgEnabled & CAMERA_MSG_PREVIEW_FRAME) && + !(mMsgEnabled & CAMERA_MSG_VIDEO_FRAME)) { + LOGI("%s : deferring", __func__); + mPreviewStartDeferred = true; + mPreviewLock.unlock(); + return NO_ERROR; + } + + ret = startPreviewInternal(); + if (ret == OK) + mPreviewCondition.signal(); + + mPreviewLock.unlock(); + return ret; +} + +status_t CameraHardwareSec::startPreviewInternal() +{ + LOGV("%s", __func__); + int width, height, frame_size; + + mSecCamera->getPreviewSize(&width, &height, &frame_size); + LOGD("mPreviewHeap(fd(%d), size(%d), width(%d), height(%d))", + mSecCamera->getCameraFd(), frame_size + mFrameSizeDelta, width, height); + + void *vaddr[3]; + + for (int i = 0; i < MAX_BUFFERS; i++) { + !mGrallocHal->lock(mGrallocHal, + *mBufferHandle[i], + GRALLOC_USAGE_SW_WRITE_OFTEN | GRALLOC_USAGE_YUV_ADDR, + 0, 0, width, height, vaddr); + memset(vaddr[0], 0, width*height*2); + int m_Ywidth = ALIGN(width, 16); + int m_Yheight = ALIGN(height, 16); + int m_UVwidth = ALIGN(width/2, 8); + int m_UVheight = ALIGN(height/2, 8); + vaddr[1] = vaddr[0] + (m_Ywidth * m_Yheight); + vaddr[2] = vaddr[1] + (m_UVwidth * m_UVheight); + mSecCamera->setUserBufferAddr(vaddr, i, PREVIEW_MODE); + } + + int ret = mSecCamera->startPreview(); + LOGV("%s : mSecCamera->startPreview() returned %d", __func__, ret); + + if (ret < 0) { + LOGE("ERR(%s):Fail on mSecCamera->startPreview()", __func__); + return UNKNOWN_ERROR; + } + + setSkipFrame(INITIAL_SKIP_FRAME); + + if (mPreviewHeap) { + mPreviewHeap->release(mPreviewHeap); + mPreviewHeap = 0; + } + + mSecCamera->getPostViewConfig(&mPostViewWidth, &mPostViewHeight, &mPostViewSize); + LOGV("CameraHardwareSec: mPostViewWidth = %d mPostViewHeight = %d mPostViewSize = %d", + mPostViewWidth,mPostViewHeight,mPostViewSize); + + return NO_ERROR; +} + +void CameraHardwareSec::stopPreviewInternal() +{ + LOGV("%s :", __func__); + + /* request that the preview thread stop. */ + if (mPreviewRunning) { + mPreviewRunning = false; + if (!mPreviewStartDeferred) { + mPreviewCondition.signal(); + /* wait until preview thread is stopped */ + mPreviewStoppedCondition.wait(mPreviewLock); + + for (int i = 0; i < MAX_BUFFERS; i++) { + if (0 != mPreviewWindow->enqueue_buffer(mPreviewWindow, mBufferHandle[i])) + LOGE("%s: Fail to enqueue buffer[%d]", __func__, i); + } + } + else + LOGV("%s : preview running but deferred, doing nothing", __func__); + } else + LOGI("%s : preview not running, doing nothing", __func__); +} + +void CameraHardwareSec::stopPreview() +{ + LOGV("%s :", __func__); + + /* request that the preview thread stop. */ + mPreviewLock.lock(); + stopPreviewInternal(); + mPreviewLock.unlock(); +} + +bool CameraHardwareSec::previewEnabled() +{ + Mutex::Autolock lock(mPreviewLock); + LOGV("%s : %d", __func__, mPreviewRunning); + return mPreviewRunning; +} + +status_t CameraHardwareSec::startRecording() +{ + LOGV("%s :", __func__); + + Mutex::Autolock lock(mRecordLock); + + for(int i = 0; irelease(mRecordHeap[i]); + mRecordHeap[i] = 0; + } + + int width, height; + + mSecCamera->getRecordingSize(&width, &height); + mRecordHeap[i] = mGetMemoryCb(-1, (ALIGN((ALIGN(width, 16) * ALIGN(height, 16)), 2048) + + ALIGN((ALIGN(width, 16) * ALIGN(height >> 1, 8)), 2048)), 1, NULL); + mSecCamera->setUserBufferAddr((void *)(mRecordHeap[i]->data), i, RECORD_MODE); + if (!mRecordHeap[i]) { + LOGE("ERR(%s): Record heap[%d] creation fail", __func__, i); + return UNKNOWN_ERROR; + } + } + + LOGV("mRecordHeaps alloc done"); + + if (mRecordRunning == false) { + if (mSecCamera->startRecord() < 0) { + LOGE("ERR(%s):Fail on mSecCamera->startRecord()", __func__); + return UNKNOWN_ERROR; + } + mRecordRunning = true; + } + return NO_ERROR; +} + +void CameraHardwareSec::stopRecording() +{ + LOGV("%s :", __func__); + + Mutex::Autolock lock(mRecordLock); + + if (mRecordRunning == true) { + if (mSecCamera->stopRecord() < 0) { + LOGE("ERR(%s):Fail on mSecCamera->stopRecord()", __func__); + return; + } + mRecordRunning = false; + } +} + +bool CameraHardwareSec::recordingEnabled() +{ + LOGV("%s :", __func__); + LOGV("%s : %d", __func__, mPreviewRunning); + + return mRecordRunning; +} + +void CameraHardwareSec::releaseRecordingFrame(const void *opaque) +{ + int i; + for (i = 0; i < MAX_BUFFERS; i++) + if ((char *)mRecordHeap[i]->data == (char *)opaque) + break; + + mSecCamera->releaseRecordFrame(i); +} + +int CameraHardwareSec::autoFocusThread() +{ + int count =0; + int af_status =0 ; + + LOGV("%s : starting", __func__); + + + /* block until we're told to start. we don't want to use + * a restartable thread and requestExitAndWait() in cancelAutoFocus() + * because it would cause deadlock between our callbacks and the + * caller of cancelAutoFocus() which both want to grab the same lock + * in CameraServices layer. + */ + mFocusLock.lock(); + /* check early exit request */ + if (mExitAutoFocusThread) { + mFocusLock.unlock(); + LOGV("%s : exiting on request0", __func__); + return NO_ERROR; + } + mFocusCondition.wait(mFocusLock); + /* check early exit request */ + if (mExitAutoFocusThread) { + mFocusLock.unlock(); + LOGV("%s : exiting on request1", __func__); + return NO_ERROR; + } + mFocusLock.unlock(); + +#ifdef GAIA_FW_BETA + if (mMsgEnabled & CAMERA_MSG_FOCUS) + mNotifyCb(CAMERA_MSG_FOCUS, false, 0, mCallbackCookie); + + //LOGV("%s : exiting with no error", __func__); + return NO_ERROR; +#else + +#ifdef AF_SUPPORT + LOGV("%s : calling setAutoFocus", __func__); + if (mSecCamera->setAutofocus() < 0) { + LOGE("ERR(%s):Fail on mSecCamera->setAutofocus()", __func__); + return UNKNOWN_ERROR; + } + + af_status = mSecCamera->getAutoFocusResult(); +#else + sleep(1); + af_status = 0x02; +#endif + + if (af_status == 0x01) { + LOGV("%s : AF Success!!", __func__); + if (mMsgEnabled & CAMERA_MSG_FOCUS) + mNotifyCb(CAMERA_MSG_FOCUS, true, 0, mCallbackCookie); + } else if (af_status == 0x02) { + LOGV("%s : AF Cancelled !!", __func__); + if (mMsgEnabled & CAMERA_MSG_FOCUS) { + /* CAMERA_MSG_FOCUS only takes a bool. true for + * finished and false for failure. cancel is still + * considered a true result. + */ + mNotifyCb(CAMERA_MSG_FOCUS, true, 0, mCallbackCookie); + } + } else { + LOGV("%s : AF Fail !!", __func__); + LOGV("%s : mMsgEnabled = 0x%x", __func__, mMsgEnabled); + if (mMsgEnabled & CAMERA_MSG_FOCUS) + mNotifyCb(CAMERA_MSG_FOCUS, false, 0, mCallbackCookie); + } + + LOGV("%s : exiting with no error", __func__); + return NO_ERROR; +#endif +} + +status_t CameraHardwareSec::autoFocus() +{ + LOGV("%s :", __func__); + /* signal autoFocusThread to run once */ + mFocusCondition.signal(); + return NO_ERROR; +} + +status_t CameraHardwareSec::cancelAutoFocus() +{ + LOGV("%s :", __func__); +#ifndef GAIA_FW_BETA + + if (mSecCamera->cancelAutofocus() < 0) { + LOGE("ERR(%s):Fail on mSecCamera->cancelAutofocus()", __func__); + return UNKNOWN_ERROR; + } +#endif + return NO_ERROR; +} + +int CameraHardwareSec::save_jpeg( unsigned char *real_jpeg, int jpeg_size) +{ + FILE *yuv_fp = NULL; + char filename[100], *buffer = NULL; + + /* file create/open, note to "wb" */ + yuv_fp = fopen("/data/camera_dump.jpeg", "wb"); + if (yuv_fp == NULL) { + LOGE("Save jpeg file open error"); + return -1; + } + + LOGV("[BestIQ] real_jpeg size ========> %d", jpeg_size); + buffer = (char *) malloc(jpeg_size); + if (buffer == NULL) { + LOGE("Save YUV] buffer alloc failed"); + if (yuv_fp) + fclose(yuv_fp); + + return -1; + } + + memcpy(buffer, real_jpeg, jpeg_size); + + fflush(stdout); + + fwrite(buffer, 1, jpeg_size, yuv_fp); + + fflush(yuv_fp); + + if (yuv_fp) + fclose(yuv_fp); + if (buffer) + free(buffer); + + return 0; +} + +void CameraHardwareSec::save_postview(const char *fname, uint8_t *buf, uint32_t size) +{ + int nw; + int cnt = 0; + uint32_t written = 0; + + LOGD("opening file [%s]", fname); + int fd = open(fname, O_RDWR | O_CREAT); + if (fd < 0) { + LOGE("failed to create file [%s]: %s", fname, strerror(errno)); + return; + } + + LOGD("writing %d bytes to file [%s]", size, fname); + while (written < size) { + nw = ::write(fd, buf + written, size - written); + if (nw < 0) { + LOGE("failed to write to file %d [%s]: %s",written,fname, strerror(errno)); + break; + } + written += nw; + cnt++; + } + LOGD("done writing %d bytes to file [%s] in %d passes",size, fname, cnt); + ::close(fd); +} + +bool CameraHardwareSec::scaleDownYuv422(char *srcBuf, uint32_t srcWidth, uint32_t srcHeight, + char *dstBuf, uint32_t dstWidth, uint32_t dstHeight) +{ + int32_t step_x, step_y; + int32_t iXsrc, iXdst; + int32_t x, y, src_y_start_pos, dst_pos, src_pos; + + if (dstWidth % 2 != 0 || dstHeight % 2 != 0) { + LOGE("scale_down_yuv422: invalid width, height for scaling"); + return false; + } + + step_x = srcWidth / dstWidth; + step_y = srcHeight / dstHeight; + + dst_pos = 0; + for (uint32_t y = 0; y < dstHeight; y++) { + src_y_start_pos = (y * step_y * (srcWidth * 2)); + + for (uint32_t x = 0; x < dstWidth; x += 2) { + src_pos = src_y_start_pos + (x * (step_x * 2)); + + dstBuf[dst_pos++] = srcBuf[src_pos ]; + dstBuf[dst_pos++] = srcBuf[src_pos + 1]; + dstBuf[dst_pos++] = srcBuf[src_pos + 2]; + dstBuf[dst_pos++] = srcBuf[src_pos + 3]; + } + } + + return true; +} + +bool CameraHardwareSec::YUY2toNV21(void *srcBuf, void *dstBuf, uint32_t srcWidth, uint32_t srcHeight) +{ + int32_t x, y, src_y_start_pos, dst_cbcr_pos, dst_pos, src_pos; + unsigned char *srcBufPointer = (unsigned char *)srcBuf; + unsigned char *dstBufPointer = (unsigned char *)dstBuf; + + dst_pos = 0; + dst_cbcr_pos = srcWidth*srcHeight; + for (uint32_t y = 0; y < srcHeight; y++) { + src_y_start_pos = (y * (srcWidth * 2)); + + for (uint32_t x = 0; x < (srcWidth * 2); x += 2) { + src_pos = src_y_start_pos + x; + + dstBufPointer[dst_pos++] = srcBufPointer[src_pos]; + } + } + for (uint32_t y = 0; y < srcHeight; y += 2) { + src_y_start_pos = (y * (srcWidth * 2)); + + for (uint32_t x = 0; x < (srcWidth * 2); x += 4) { + src_pos = src_y_start_pos + x; + + dstBufPointer[dst_cbcr_pos++] = srcBufPointer[src_pos + 3]; + dstBufPointer[dst_cbcr_pos++] = srcBufPointer[src_pos + 1]; + } + } + + return true; +} + +int CameraHardwareSec::pictureThread() +{ + LOGV("%s :", __func__); + + int jpeg_size = 0; + int ret = NO_ERROR; + unsigned char *jpeg_data = NULL; + int postview_offset = 0; + unsigned char *postview_data = NULL; + + unsigned char *addr = NULL; + int mPostViewWidth, mPostViewHeight, mPostViewSize; + int mThumbWidth, mThumbHeight, mThumbSize; + int cap_width, cap_height, cap_frame_size; + + unsigned int output_size = 0; + + mSecCamera->getPostViewConfig(&mPostViewWidth, &mPostViewHeight, &mPostViewSize); + mSecCamera->getThumbnailConfig(&mThumbWidth, &mThumbHeight, &mThumbSize); + int postviewHeapSize = mPostViewSize; + mSecCamera->getSnapshotSize(&cap_width, &cap_height, &cap_frame_size); + int mJpegHeapSize; +#ifdef JPEG_FROM_SENSOR + if (mSecCamera->getCameraId() == SecCamera::CAMERA_ID_BACK) + mJpegHeapSize = cap_frame_size * SecCamera::getJpegRatio(); + else +#endif + mJpegHeapSize = cap_frame_size; + + //sp buffer = new MemoryBase(mRawHeap, 0, mPostViewSize + 8); + + LOGV("[5B] mPostViewWidth = %d mPostViewHeight = %d\n",mPostViewWidth,mPostViewHeight); + + camera_memory_t *JpegHeap = mGetMemoryCb(-1, mJpegHeapSize, 1, 0); +#ifndef GAIA_FW_BETA + sp PostviewHeap = new MemoryHeapBaseIon(mPostViewSize); + sp ThumbnailHeap = new MemoryHeapBaseIon(mThumbSize); +#else + sp PostviewHeap = new MemoryHeapBase(mPostViewSize); + sp ThumbnailHeap = new MemoryHeapBase(mThumbSize); +#endif + + if (mMsgEnabled & CAMERA_MSG_RAW_IMAGE) { + int picture_size, picture_width, picture_height; + mSecCamera->getSnapshotSize(&picture_width, &picture_height, &picture_size); + int picture_format = mSecCamera->getSnapshotPixelFormat(); + + unsigned int phyAddr; + + // Modified the shutter sound timing for Jpeg capture +#ifdef JPEG_FROM_SENSOR + if (mSecCamera->getCameraId() == SecCamera::CAMERA_ID_BACK) + mSecCamera->setSnapshotCmd(); + if (mMsgEnabled & CAMERA_MSG_SHUTTER) + mNotifyCb(CAMERA_MSG_SHUTTER, 0, 0, mCallbackCookie); + if (mSecCamera->getCameraId() == SecCamera::CAMERA_ID_BACK){ + jpeg_data = mSecCamera->getJpeg(&jpeg_size, &phyAddr); + if (jpeg_data == NULL) { + LOGE("ERR(%s):Fail on SecCamera->getSnapshot()", __func__); + ret = UNKNOWN_ERROR; + } + } else { +#endif + if (mMsgEnabled & CAMERA_MSG_SHUTTER) + mNotifyCb(CAMERA_MSG_SHUTTER, 0, 0, mCallbackCookie); + if (mSecCamera->getSnapshotAndJpeg((unsigned char*)PostviewHeap->base(), + (unsigned char*)JpegHeap->data, &output_size) < 0) { + mStateLock.lock(); + mCaptureInProgress = false; + mStateLock.unlock(); + JpegHeap->release(JpegHeap); + return UNKNOWN_ERROR; + } + LOGI("snapshotandjpeg done"); +#ifdef JPEG_FROM_SENSOR + } +#endif + } + + int JpegImageSize, JpegExifSize; + bool isLSISensor = false; + +#ifdef JPEG_FROM_SENSOR + if (mSecCamera->getCameraId() == SecCamera::CAMERA_ID_BACK) { + LOGV("%s, %s", __func__, (const char*)mCameraSensorName); //to check sensor name + isLSISensor = !strncmp((const char*)mCameraSensorName, "S5K4ECGX", 8); + if (isLSISensor) { + LOGI("== Camera Sensor Detect %s - Samsung LSI SOC 5M ==", mCameraSensorName); + // LSI 5M SOC + if (!SplitFrame(jpeg_data, SecCamera::getInterleaveDataSize(), + SecCamera::getJpegLineLength(), + mPostViewWidth * 2, mPostViewWidth, + JpegHeap->data, &JpegImageSize, + PostviewHeap->base(), &mPostViewSize)) { + JpegHeap->release(JpegHeap); + return UNKNOWN_ERROR; + } + } else { + LOGI("== Camera Sensor Detect %s Sony SOC 5M ==", mCameraSensorName); + decodeInterleaveData(jpeg_data, + SecCamera::getInterleaveDataSize(), + mPostViewWidth, mPostViewHeight, + &JpegImageSize, JpegHeap->data, PostviewHeap->base()); + } + } else +#endif + JpegImageSize = static_cast(output_size); + + scaleDownYuv422((char *)mSecCamera->getPictureVaddr(), mPostViewWidth, mPostViewHeight, + (char *)ThumbnailHeap->base(), mThumbWidth, mThumbHeight); + +#ifdef GAIA_FW_BETA + int rawHeapSize = mPostViewSize; + LOGV("mRawHeap : MemoryHeapBase(previewHeapSize(%d))", rawHeapSize); + mRawHeap = mGetMemoryCb((int)mSecCamera->getCameraFd(), rawHeapSize, 1, 0); + if (!mRawHeap) + LOGE("ERR(%s): Raw heap creation fail", __func__); + + if (mMsgEnabled & CAMERA_MSG_RAW_IMAGE) + mDataCb(CAMERA_MSG_RAW_IMAGE, mRawHeap, 0, NULL, mCallbackCookie); +#endif + + mStateLock.lock(); + mCaptureInProgress = false; + mStateLock.unlock(); + + if (mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE) { + camera_memory_t *ExifHeap = + mGetMemoryCb(-1, EXIF_FILE_SIZE + mThumbSize, 1, 0); + + JpegExifSize = mSecCamera->getExif((unsigned char *)ExifHeap->data, + (unsigned char *)ThumbnailHeap->base()); + LOGV("JpegExifSize=%d", JpegExifSize); + + if (JpegExifSize < 0) { + ret = UNKNOWN_ERROR; + goto out; + } + + int mJpegHeapSize_out = JpegImageSize + JpegExifSize; + camera_memory_t *JpegHeap_out = mGetMemoryCb(-1, mJpegHeapSize_out, 1, 0); + + unsigned char *ExifStart = (unsigned char *)JpegHeap_out->data + 2; + unsigned char *ImageStart = ExifStart + JpegExifSize; + + memcpy(JpegHeap_out->data, JpegHeap->data, 2); + memcpy(ExifStart, ExifHeap->data, JpegExifSize); + memcpy(ImageStart, JpegHeap->data + 2, JpegImageSize - 2); + + mDataCb(CAMERA_MSG_COMPRESSED_IMAGE, JpegHeap_out, 0, NULL, mCallbackCookie); + + if (ExifHeap) { + ExifHeap->release(ExifHeap); + ExifHeap = 0; + } + + if (JpegHeap_out) { + JpegHeap_out->release(JpegHeap_out); + JpegHeap_out = 0; + } + } + + LOGV("%s : pictureThread end", __func__); + +out: + if (JpegHeap) { + JpegHeap->release(JpegHeap); + JpegHeap = 0; + } + + if (mRawHeap) { + mRawHeap->release(mRawHeap); + mRawHeap = 0; + } + + return ret; +} + +status_t CameraHardwareSec::takePicture() +{ + LOGV("%s :", __func__); + + stopPreview(); + + Mutex::Autolock lock(mStateLock); + if (mCaptureInProgress) { + LOGE("%s : capture already in progress", __func__); + return INVALID_OPERATION; + } + + if (mPictureThread->run("CameraPictureThread", PRIORITY_DEFAULT) != NO_ERROR) { + LOGE("%s : couldn't run picture thread", __func__); + return INVALID_OPERATION; + } + mCaptureInProgress = true; + + return NO_ERROR; +} + +status_t CameraHardwareSec::cancelPicture() +{ + LOGV("%s", __func__); + + if (mPictureThread.get()) { + LOGV("%s: waiting for picture thread to exit", __func__); + mPictureThread->requestExitAndWait(); + LOGV("%s: picture thread has exited", __func__); + } + + return NO_ERROR; +} + +bool CameraHardwareSec::CheckVideoStartMarker(unsigned char *pBuf) +{ + if (!pBuf) { + LOGE("CheckVideoStartMarker() => pBuf is NULL"); + return false; + } + + if (HIBYTE(VIDEO_COMMENT_MARKER_H) == * pBuf && LOBYTE(VIDEO_COMMENT_MARKER_H) == *(pBuf + 1) && + HIBYTE(VIDEO_COMMENT_MARKER_L) == *(pBuf + 2) && LOBYTE(VIDEO_COMMENT_MARKER_L) == *(pBuf + 3)) + return true; + + return false; +} + +bool CameraHardwareSec::CheckEOIMarker(unsigned char *pBuf) +{ + if (!pBuf) { + LOGE("CheckEOIMarker() => pBuf is NULL"); + return false; + } + + // EOI marker [FF D9] + if (HIBYTE(JPEG_EOI_MARKER) == *pBuf && LOBYTE(JPEG_EOI_MARKER) == *(pBuf + 1)) + return true; + + return false; +} + +bool CameraHardwareSec::FindEOIMarkerInJPEG(unsigned char *pBuf, int dwBufSize, int *pnJPEGsize) +{ + if (NULL == pBuf || 0 >= dwBufSize) { + LOGE("FindEOIMarkerInJPEG() => There is no contents."); + return false; + } + + unsigned char *pBufEnd = pBuf + dwBufSize; + + while (pBuf < pBufEnd) { + if (CheckEOIMarker(pBuf++)) + return true; + + (*pnJPEGsize)++; + } + + return false; +} + +bool CameraHardwareSec::SplitFrame(unsigned char *pFrame, int dwSize, + int dwJPEGLineLength, int dwVideoLineLength, int dwVideoHeight, + void *pJPEG, int *pdwJPEGSize, + void *pVideo, int *pdwVideoSize) +{ + LOGV("===========SplitFrame Start=============="); + + if (NULL == pFrame || 0 >= dwSize) { + LOGE("There is no contents (pFrame=%p, dwSize=%d", pFrame, dwSize); + return false; + } + + if (0 == dwJPEGLineLength || 0 == dwVideoLineLength) { + LOGE("There in no input information for decoding interleaved jpeg"); + return false; + } + + unsigned char *pSrc = pFrame; + unsigned char *pSrcEnd = pFrame + dwSize; + + unsigned char *pJ = (unsigned char *)pJPEG; + int dwJSize = 0; + unsigned char *pV = (unsigned char *)pVideo; + int dwVSize = 0; + + bool bRet = false; + bool isFinishJpeg = false; + + while (pSrc < pSrcEnd) { + // Check video start marker + if (CheckVideoStartMarker(pSrc)) { + int copyLength; + + if (pSrc + dwVideoLineLength <= pSrcEnd) + copyLength = dwVideoLineLength; + else + copyLength = pSrcEnd - pSrc - VIDEO_COMMENT_MARKER_LENGTH; + + // Copy video data + if (pV) { + memcpy(pV, pSrc + VIDEO_COMMENT_MARKER_LENGTH, copyLength); + pV += copyLength; + dwVSize += copyLength; + } + + pSrc += copyLength + VIDEO_COMMENT_MARKER_LENGTH; + } else { + // Copy pure JPEG data + int size = 0; + int dwCopyBufLen = dwJPEGLineLength <= pSrcEnd-pSrc ? dwJPEGLineLength : pSrcEnd - pSrc; + + if (FindEOIMarkerInJPEG((unsigned char *)pSrc, dwCopyBufLen, &size)) { + isFinishJpeg = true; + size += 2; // to count EOF marker size + } else { + if ((dwCopyBufLen == 1) && (pJPEG < pJ)) { + unsigned char checkBuf[2] = { *(pJ - 1), *pSrc }; + + if (CheckEOIMarker(checkBuf)) + isFinishJpeg = true; + } + size = dwCopyBufLen; + } + + memcpy(pJ, pSrc, size); + + dwJSize += size; + + pJ += dwCopyBufLen; + pSrc += dwCopyBufLen; + } + if (isFinishJpeg) + break; + } + + if (isFinishJpeg) { + bRet = true; + if (pdwJPEGSize) + *pdwJPEGSize = dwJSize; + if (pdwVideoSize) + *pdwVideoSize = dwVSize; + } else { + LOGE("DecodeInterleaveJPEG_WithOutDT() => Can not find EOI"); + bRet = false; + if (pdwJPEGSize) + *pdwJPEGSize = 0; + if (pdwVideoSize) + *pdwVideoSize = 0; + } + LOGV("===========SplitFrame end=============="); + + return bRet; +} + +int CameraHardwareSec::decodeInterleaveData(unsigned char *pInterleaveData, + int interleaveDataSize, + int yuvWidth, + int yuvHeight, + int *pJpegSize, + void *pJpegData, + void *pYuvData) +{ + if (pInterleaveData == NULL) + return false; + + bool ret = true; + unsigned int *interleave_ptr = (unsigned int *)pInterleaveData; + unsigned char *jpeg_ptr = (unsigned char *)pJpegData; + unsigned char *yuv_ptr = (unsigned char *)pYuvData; + unsigned char *p; + int jpeg_size = 0; + int yuv_size = 0; + + int i = 0; + + LOGV("decodeInterleaveData Start~~~"); + while (i < interleaveDataSize) { + if ((*interleave_ptr == 0xFFFFFFFF) || (*interleave_ptr == 0x02FFFFFF) || + (*interleave_ptr == 0xFF02FFFF)) { + // Padding Data + interleave_ptr++; + i += 4; + } else if ((*interleave_ptr & 0xFFFF) == 0x05FF) { + // Start-code of YUV Data + p = (unsigned char *)interleave_ptr; + p += 2; + i += 2; + + // Extract YUV Data + if (pYuvData != NULL) { + memcpy(yuv_ptr, p, yuvWidth * 2); + yuv_ptr += yuvWidth * 2; + yuv_size += yuvWidth * 2; + } + p += yuvWidth * 2; + i += yuvWidth * 2; + + // Check End-code of YUV Data + if ((*p == 0xFF) && (*(p + 1) == 0x06)) { + interleave_ptr = (unsigned int *)(p + 2); + i += 2; + } else { + ret = false; + break; + } + } else { + // Extract JPEG Data + if (pJpegData != NULL) { + memcpy(jpeg_ptr, interleave_ptr, 4); + jpeg_ptr += 4; + jpeg_size += 4; + } + interleave_ptr++; + i += 4; + } + } + if (ret) { + if (pJpegData != NULL) { + // Remove Padding after EOI + for (i = 0; i < 3; i++) { + if (*(--jpeg_ptr) != 0xFF) { + break; + } + jpeg_size--; + } + *pJpegSize = jpeg_size; + + } + // Check YUV Data Size + if (pYuvData != NULL) { + if (yuv_size != (yuvWidth * yuvHeight * 2)) { + ret = false; + } + } + } + LOGV("decodeInterleaveData End~~~"); + return ret; +} + +status_t CameraHardwareSec::dump(int fd) const +{ + const size_t SIZE = 256; + char buffer[SIZE]; + String8 result; + const Vector args; + + if (mSecCamera != 0) { + mSecCamera->dump(fd); + mParameters.dump(fd, args); + mInternalParameters.dump(fd, args); + snprintf(buffer, 255, " preview running(%s)\n", mPreviewRunning?"true": "false"); + result.append(buffer); + } else + result.append("No camera client yet.\n"); + write(fd, result.string(), result.size()); + return NO_ERROR; +} + +bool CameraHardwareSec::isSupportedPreviewSize(const int width, + const int height) const +{ + unsigned int i; + + for (i = 0; i < mSupportedPreviewSizes.size(); i++) { + if (mSupportedPreviewSizes[i].width == width && + mSupportedPreviewSizes[i].height == height) + return true; + } + + return false; +} + +status_t CameraHardwareSec::setParameters(const CameraParameters& params) +{ + LOGV("%s :", __func__); +#ifndef GAIA_FW_BETA + int Internal_is = !strncmp((const char*)mSecCamera->getCameraSensorName(), "ISP Camera", 10); +#else + int Internal_is = 0; +#endif + status_t ret = NO_ERROR; + + /* if someone calls us while picture thread is running, it could screw + * up the sensor quite a bit so return error. we can't wait because + * that would cause deadlock with the callbacks + */ + mStateLock.lock(); + if (mCaptureInProgress) { + mStateLock.unlock(); + LOGE("%s : capture in progress, not allowed", __func__); + return UNKNOWN_ERROR; + } + mStateLock.unlock(); + + // preview size +#ifdef GAIA_FW_BETA + int new_preview_width = 1920; + int new_preview_height = 1080; +#else + int new_preview_width = 0; + int new_preview_height = 0; + params.getPreviewSize(&new_preview_width, &new_preview_height); +#endif + const char *new_str_preview_format = params.getPreviewFormat(); + LOGV("%s : new_preview_width x new_preview_height = %dx%d, format = %s", + __func__, new_preview_width, new_preview_height, new_str_preview_format); + + if (0 < new_preview_width && 0 < new_preview_height && + new_str_preview_format != NULL && + isSupportedPreviewSize(new_preview_width, new_preview_height)) { + int new_preview_format = 0; + + mFrameSizeDelta = 16; + if (!strcmp(new_str_preview_format, + CameraParameters::PIXEL_FORMAT_RGB565)) { + new_preview_format = V4L2_PIX_FMT_RGB565; + mFrameSizeDelta = 0; + } + else if (!strcmp(new_str_preview_format, + CameraParameters::PIXEL_FORMAT_RGBA8888)) { + new_preview_format = V4L2_PIX_FMT_RGB32; + mFrameSizeDelta = 0; + } + else if (!strcmp(new_str_preview_format, + CameraParameters::PIXEL_FORMAT_YUV420SP)) + new_preview_format = V4L2_PIX_FMT_NV21; + else if (!strcmp(new_str_preview_format, + CameraParameters::PIXEL_FORMAT_YUV420P)) + new_preview_format = V4L2_PIX_FMT_YVU420M; + + else if (!strcmp(new_str_preview_format, "yuv420sp_custom")) + new_preview_format = V4L2_PIX_FMT_NV12T; + else if (!strcmp(new_str_preview_format, "yuv422i")) + new_preview_format = V4L2_PIX_FMT_YUYV; + else if (!strcmp(new_str_preview_format, "yuv422p")) + new_preview_format = V4L2_PIX_FMT_YUV422P; + else + new_preview_format = V4L2_PIX_FMT_NV21; //for 3rd party + + int current_preview_width, current_preview_height, current_frame_size; + mSecCamera->getPreviewSize(¤t_preview_width, + ¤t_preview_height, + ¤t_frame_size); + int current_pixel_format = mSecCamera->getPreviewPixelFormat(); + + if (current_preview_width != new_preview_width || + current_preview_height != new_preview_height || + current_pixel_format != new_preview_format) { + if (mSecCamera->setPreviewSize(new_preview_width, new_preview_height, + new_preview_format) < 0) { + LOGE("ERR(%s):Fail on mSecCamera->setPreviewSize(width(%d), height(%d), format(%d))", + __func__, new_preview_width, new_preview_height, new_preview_format); + ret = UNKNOWN_ERROR; + } else { + if (mPreviewWindow) { + if (mPreviewRunning && !mPreviewStartDeferred) { + LOGE("ERR(%s): preview is running, cannot change size and format!", + __func__); + ret = INVALID_OPERATION; + } + + LOGV("%s: mPreviewWindow (%p) set_buffers_geometry", __func__, mPreviewWindow); + LOGV("%s: mPreviewWindow->set_buffers_geometry (%p)", __func__, + mPreviewWindow->set_buffers_geometry); + mPreviewWindow->set_buffers_geometry(mPreviewWindow, + new_preview_width, new_preview_height, + new_preview_format); + LOGV("%s: DONE mPreviewWindow (%p) set_buffers_geometry", __func__, mPreviewWindow); + } + mParameters.setPreviewSize(new_preview_width, new_preview_height); + mParameters.setPreviewFormat(new_str_preview_format); + } + } + else LOGV("%s: preview size and format has not changed", __func__); + } else { + LOGE("%s: Invalid preview size(%dx%d)", + __func__, new_preview_width, new_preview_height); + + ret = INVALID_OPERATION; + } + +#ifndef GAIA_FW_BETA + int new_picture_width = 0; + int new_picture_height = 0; + + params.getPictureSize(&new_picture_width, &new_picture_height); + LOGV("%s : new_picture_width x new_picture_height = %dx%d", __func__, new_picture_width, new_picture_height); + if (0 < new_picture_width && 0 < new_picture_height) { + LOGV("%s: setSnapshotSize", __func__); + if (mSecCamera->setSnapshotSize(new_picture_width, new_picture_height) < 0) { + LOGE("ERR(%s):Fail on mSecCamera->setSnapshotSize(width(%d), height(%d))", + __func__, new_picture_width, new_picture_height); + ret = UNKNOWN_ERROR; + } else + mParameters.setPictureSize(new_picture_width, new_picture_height); + } + + // picture format + const char *new_str_picture_format = params.getPictureFormat(); + LOGV("%s : new_str_picture_format %s", __func__, new_str_picture_format); + if (new_str_picture_format != NULL) { + int new_picture_format = 0; + + if (!strcmp(new_str_picture_format, CameraParameters::PIXEL_FORMAT_RGB565)) + new_picture_format = V4L2_PIX_FMT_RGB565; + else if (!strcmp(new_str_picture_format, CameraParameters::PIXEL_FORMAT_RGBA8888)) + new_picture_format = V4L2_PIX_FMT_RGB32; + else if (!strcmp(new_str_picture_format, CameraParameters::PIXEL_FORMAT_YUV420SP)) + new_picture_format = V4L2_PIX_FMT_NV21; + else if (!strcmp(new_str_picture_format, "yuv420sp_custom")) + new_picture_format = V4L2_PIX_FMT_NV12T; + else if (!strcmp(new_str_picture_format, "yuv420p")) + new_picture_format = V4L2_PIX_FMT_YUV420; + else if (!strcmp(new_str_picture_format, "yuv422i")) + new_picture_format = V4L2_PIX_FMT_YUYV; + else if (!strcmp(new_str_picture_format, "uyv422i_custom")) //Zero copy UYVY format + new_picture_format = V4L2_PIX_FMT_UYVY; + else if (!strcmp(new_str_picture_format, "uyv422i")) //Non-zero copy UYVY format + new_picture_format = V4L2_PIX_FMT_UYVY; + else if (!strcmp(new_str_picture_format, CameraParameters::PIXEL_FORMAT_JPEG)) + new_picture_format = V4L2_PIX_FMT_YUYV; + else if (!strcmp(new_str_picture_format, "yuv422p")) + new_picture_format = V4L2_PIX_FMT_YUV422P; + else + new_picture_format = V4L2_PIX_FMT_NV21; //for 3rd party + + if (mSecCamera->setSnapshotPixelFormat(new_picture_format) < 0) { + LOGE("ERR(%s):Fail on mSecCamera->setSnapshotPixelFormat(format(%d))", __func__, new_picture_format); + ret = UNKNOWN_ERROR; + } else + mParameters.setPictureFormat(new_str_picture_format); + } + + // JPEG image quality + int new_jpeg_quality = params.getInt(CameraParameters::KEY_JPEG_QUALITY); + LOGV("%s : new_jpeg_quality %d", __func__, new_jpeg_quality); + /* we ignore bad values */ + if (new_jpeg_quality >=1 && new_jpeg_quality <= 100) { + if (mSecCamera->setJpegQuality(new_jpeg_quality) < 0) { + LOGE("ERR(%s):Fail on mSecCamera->setJpegQuality(quality(%d))", __func__, new_jpeg_quality); + ret = UNKNOWN_ERROR; + } else + mParameters.set(CameraParameters::KEY_JPEG_QUALITY, new_jpeg_quality); + } + + // JPEG thumbnail size + int new_jpeg_thumbnail_width = params.getInt(CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH); + int new_jpeg_thumbnail_height= params.getInt(CameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT); + if (0 <= new_jpeg_thumbnail_width && 0 <= new_jpeg_thumbnail_height) { + if (mSecCamera->setJpegThumbnailSize(new_jpeg_thumbnail_width, new_jpeg_thumbnail_height) < 0) { + LOGE("ERR(%s):Fail on mSecCamera->setJpegThumbnailSize(width(%d), height(%d))", __func__, new_jpeg_thumbnail_width, new_jpeg_thumbnail_height); + ret = UNKNOWN_ERROR; + } else { + mParameters.set(CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH, new_jpeg_thumbnail_width); + mParameters.set(CameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT, new_jpeg_thumbnail_height); + } + } + + // JPEG thumbnail quality + int new_jpeg_thumbnail_quality = params.getInt(CameraParameters::KEY_JPEG_THUMBNAIL_QUALITY); + LOGV("%s : new_jpeg_thumbnail_quality %d", __func__, new_jpeg_thumbnail_quality); + /* we ignore bad values */ + if (new_jpeg_thumbnail_quality >=1 && new_jpeg_thumbnail_quality <= 100) { + if (mSecCamera->setJpegThumbnailQuality(new_jpeg_thumbnail_quality) < 0) { + LOGE("ERR(%s):Fail on mSecCamera->setJpegThumbnailQuality(quality(%d))", + __func__, new_jpeg_thumbnail_quality); + ret = UNKNOWN_ERROR; + } else + mParameters.set(CameraParameters::KEY_JPEG_THUMBNAIL_QUALITY, new_jpeg_thumbnail_quality); + } + + // frame rate + int new_frame_rate = params.getPreviewFrameRate(); + /* ignore any fps request, we're determine fps automatically based + * on scene mode. don't return an error because it causes CTS failure. + */ + if (new_frame_rate != mParameters.getPreviewFrameRate()) { + if (mSecCamera->setFrameRate(new_frame_rate) < 0){ + LOGE("ERR(%s):Fail on mSecCamera->setFrameRate(%d)", __func__, new_frame_rate); + ret = UNKNOWN_ERROR; + } else { + mParameters.setPreviewFrameRate(new_frame_rate); + } + } + + // rotation + int new_rotation = params.getInt(CameraParameters::KEY_ROTATION); + LOGV("%s : new_rotation %d", __func__, new_rotation); + if (0 <= new_rotation) { + LOGV("%s : set orientation:%d", __func__, new_rotation); + if (mSecCamera->setExifOrientationInfo(new_rotation) < 0) { + LOGE("ERR(%s):Fail on mSecCamera->setExifOrientationInfo(%d)", __func__, new_rotation); + ret = UNKNOWN_ERROR; + } else + mParameters.set(CameraParameters::KEY_ROTATION, new_rotation); + } + + // brightness + int new_brightness = params.getInt("brightness"); + int max_brightness = params.getInt("brightness-max"); + int min_brightness = params.getInt("brightness-min"); + LOGV("%s : new_brightness %d", __func__, new_brightness); + if ((min_brightness <= new_brightness) && + (max_brightness >= new_brightness)) { + if (mSecCamera->setBrightness(new_brightness) < 0) { + LOGE("ERR(%s):Fail on mSecCamera->setBrightness(brightness(%d))", __func__, new_brightness); + ret = UNKNOWN_ERROR; + } else { + mParameters.set("brightness", new_brightness); + } + } + + // saturation + int new_saturation = params.getInt("saturation"); + int max_saturation = params.getInt("saturation-max"); + int min_saturation = params.getInt("saturation-min"); + LOGV("%s : new_saturation %d", __func__, new_saturation); + if ((min_saturation <= new_saturation) && + (max_saturation >= new_saturation)) { + if (mSecCamera->setSaturation(new_saturation) < 0) { + LOGE("ERR(%s):Fail on mSecCamera->setSaturation(saturation(%d))", __func__, new_saturation); + ret = UNKNOWN_ERROR; + } else { + mParameters.set("saturation", new_saturation); + } + } + + // sharpness + int new_sharpness = params.getInt("sharpness"); + int max_sharpness = params.getInt("sharpness-max"); + int min_sharpness = params.getInt("sharpness-min"); + LOGV("%s : new_sharpness %d", __func__, new_sharpness); + if ((min_sharpness <= new_sharpness) && + (max_sharpness >= new_sharpness)) { + if (mSecCamera->setSharpness(new_sharpness) < 0) { + LOGE("ERR(%s):Fail on mSecCamera->setSharpness(sharpness(%d))", __func__, new_sharpness); + ret = UNKNOWN_ERROR; + } else { + mParameters.set("sharpness", new_sharpness); + } + } + + // hue + int new_hue = params.getInt("hue"); + int max_hue = params.getInt("hue-max"); + int min_hue = params.getInt("hue-min"); + LOGV("%s : new_hue %d", __func__, new_hue); + if ((min_hue <= new_hue) && + (max_hue >= new_hue)) { + if (mSecCamera->setHue(new_hue) < 0) { + LOGE("ERR(%s):Fail on mSecCamera->setHue(hue(%d))", __func__, new_hue); + ret = UNKNOWN_ERROR; + } else { + mParameters.set("hue", new_hue); + } + } + + // exposure + int new_exposure_compensation = params.getInt(CameraParameters::KEY_EXPOSURE_COMPENSATION); + int max_exposure_compensation = params.getInt(CameraParameters::KEY_MAX_EXPOSURE_COMPENSATION); + int min_exposure_compensation = params.getInt(CameraParameters::KEY_MIN_EXPOSURE_COMPENSATION); + LOGV("%s : new_exposure_compensation %d", __func__, new_exposure_compensation); + if ((min_exposure_compensation <= new_exposure_compensation) && + (max_exposure_compensation >= new_exposure_compensation)) { + if (mSecCamera->setExposure(new_exposure_compensation) < 0) { + LOGE("ERR(%s):Fail on mSecCamera->setExposure(exposure(%d))", __func__, new_exposure_compensation); + ret = UNKNOWN_ERROR; + } else { + mParameters.set(CameraParameters::KEY_EXPOSURE_COMPENSATION, new_exposure_compensation); + } + } + + // ISO + const char *new_iso_str = params.get("iso"); + LOGV("%s : new_iso_str %s", __func__, new_iso_str); + if (new_iso_str != NULL) { + int new_iso = -1; + + if (!strcmp(new_iso_str, "auto")) { + if (Internal_is) + new_iso = IS_ISO_AUTO; + else + new_iso = ISO_AUTO; + } else if (!strcmp(new_iso_str, "50")) { + if (Internal_is) + new_iso = IS_ISO_50; + else + new_iso = ISO_50; + } else if (!strcmp(new_iso_str, "100")) { + if (Internal_is) + new_iso = IS_ISO_100; + else + new_iso = ISO_100; + } else if (!strcmp(new_iso_str, "200")) { + if (Internal_is) + new_iso = IS_ISO_200; + else + new_iso = ISO_200; + } else if (!strcmp(new_iso_str, "400")) { + if (Internal_is) + new_iso = IS_ISO_400; + else + new_iso = ISO_400; + } else if (!strcmp(new_iso_str, "800")) { + if (Internal_is) + new_iso = IS_ISO_800; + else + new_iso = ISO_800; + } else if (!strcmp(new_iso_str, "1600")) { + if (Internal_is) + new_iso = IS_ISO_1600; + else + new_iso = ISO_1600; + } else { + LOGE("ERR(%s):Invalid iso value(%s)", __func__, new_iso_str); + ret = UNKNOWN_ERROR; + } + + if (0 <= new_iso) { + if (mSecCamera->setISO(new_iso) < 0) { + LOGE("ERR(%s):Fail on mSecCamera->setISO(iso(%d))", __func__, new_iso); + ret = UNKNOWN_ERROR; + } else { + mParameters.set("iso", new_iso_str); + } + } + } + + // whitebalance + const char *new_white_str = params.get(CameraParameters::KEY_WHITE_BALANCE); + LOGV("%s : new_white_str %s", __func__, new_white_str); + if (new_white_str != NULL) { + int new_white = -1; + + if (!strcmp(new_white_str, CameraParameters::WHITE_BALANCE_AUTO)) { + if (Internal_is) + new_white = IS_AWB_AUTO; + else + new_white = WHITE_BALANCE_AUTO; + } else if (!strcmp(new_white_str, + CameraParameters::WHITE_BALANCE_DAYLIGHT)) { + if (Internal_is) + new_white = IS_AWB_DAYLIGHT; + else + new_white = WHITE_BALANCE_SUNNY; + } else if (!strcmp(new_white_str, + CameraParameters::WHITE_BALANCE_CLOUDY_DAYLIGHT)) { + if (Internal_is) + new_white = IS_AWB_CLOUDY; + else + new_white = WHITE_BALANCE_CLOUDY; + } else if (!strcmp(new_white_str, + CameraParameters::WHITE_BALANCE_FLUORESCENT)) { + if (Internal_is) + new_white = IS_AWB_FLUORESCENT; + else + new_white = WHITE_BALANCE_FLUORESCENT; + } else if (!strcmp(new_white_str, + CameraParameters::WHITE_BALANCE_INCANDESCENT)) { + if (Internal_is) + new_white = IS_AWB_TUNGSTEN; + else + new_white = WHITE_BALANCE_TUNGSTEN; + } else { + LOGE("ERR(%s):Invalid white balance(%s)", __func__, new_white_str); //twilight, shade, warm_flourescent + ret = UNKNOWN_ERROR; + } + + if (0 <= new_white) { + if (mSecCamera->setWhiteBalance(new_white) < 0) { + LOGE("ERR(%s):Fail on mSecCamera->setWhiteBalance(white(%d))", __func__, new_white); + ret = UNKNOWN_ERROR; + } else { + mParameters.set(CameraParameters::KEY_WHITE_BALANCE, new_white_str); + } + } + } + + // Metering + const char *new_metering_str = params.get("metering"); + LOGV("%s : new_metering_str %s", __func__, new_metering_str); + if (new_metering_str != NULL) { + int new_metering = -1; + + if (!strcmp(new_metering_str, "center")) { + if (Internal_is) + new_metering = IS_METERING_AVERAGE; + else + new_metering = METERING_CENTER; + } else if (!strcmp(new_metering_str, "spot")) { + if (Internal_is) + new_metering = IS_METERING_SPOT; + else + new_metering = METERING_SPOT; + } else if (!strcmp(new_metering_str, "matrix")) { + if (Internal_is) + new_metering = IS_METERING_MATRIX; + else + new_metering = METERING_MATRIX; + } else { + LOGE("ERR(%s):Invalid metering value(%s)", __func__, new_metering_str); + ret = UNKNOWN_ERROR; + } + + if (0 <= new_metering) { + if (mSecCamera->setMetering(new_metering) < 0) { + LOGE("ERR(%s):Fail on mSecCamera->setMetering(metering(%d))", __func__, new_metering); + ret = UNKNOWN_ERROR; + } else { + mParameters.set("metering", new_metering_str); + } + } + } + + // AFC + const char *new_antibanding_str = params.get(CameraParameters::KEY_ANTIBANDING); + LOGV("%s : new_antibanding_str %s", __func__, new_antibanding_str); + if (new_antibanding_str != NULL) { + int new_antibanding = -1; + + if (!strcmp(new_antibanding_str, CameraParameters::ANTIBANDING_AUTO)) { + if (Internal_is) + new_antibanding = IS_AFC_AUTO; + else + new_antibanding = ANTI_BANDING_AUTO; + } else if (!strcmp(new_antibanding_str, CameraParameters::ANTIBANDING_50HZ)) { + if (Internal_is) + new_antibanding = IS_AFC_MANUAL_50HZ; + else + new_antibanding = ANTI_BANDING_50HZ; + } else if (!strcmp(new_antibanding_str, CameraParameters::ANTIBANDING_60HZ)) { + if (Internal_is) + new_antibanding = IS_AFC_MANUAL_60HZ; + else + new_antibanding = ANTI_BANDING_60HZ; + } else if (!strcmp(new_antibanding_str, CameraParameters::ANTIBANDING_OFF)) { + if (Internal_is) + new_antibanding = IS_AFC_DISABLE; + else + new_antibanding = ANTI_BANDING_OFF; + } else { + LOGE("ERR(%s):Invalid antibanding value(%s)", __func__, new_antibanding_str); + ret = UNKNOWN_ERROR; + } + + if (0 <= new_antibanding) { + if (mSecCamera->setAntiBanding(new_antibanding) < 0) { + LOGE("ERR(%s):Fail on mSecCamera->setAntiBanding(antibanding(%d))", __func__, new_antibanding); + ret = UNKNOWN_ERROR; + } else { + mParameters.set(CameraParameters::KEY_ANTIBANDING, new_antibanding_str); + } + } + } + + // scene mode + const char *new_scene_mode_str = params.get(CameraParameters::KEY_SCENE_MODE); + const char *current_scene_mode_str = mParameters.get(CameraParameters::KEY_SCENE_MODE); + + // fps range + int new_min_fps = 0; + int new_max_fps = 0; + int current_min_fps, current_max_fps; + params.getPreviewFpsRange(&new_min_fps, &new_max_fps); + mParameters.getPreviewFpsRange(¤t_min_fps, ¤t_max_fps); + /* our fps range is determined by the sensor, reject any request + * that isn't exactly what we're already at. + * but the check is performed when requesting only changing fps range + */ + if (new_scene_mode_str && current_scene_mode_str) { + if (!strcmp(new_scene_mode_str, current_scene_mode_str)) { + if ((new_min_fps != current_min_fps) || (new_max_fps != current_max_fps)) { + LOGW("%s : requested new_min_fps = %d, new_max_fps = %d not allowed", + __func__, new_min_fps, new_max_fps); + LOGE("%s : current_min_fps = %d, current_max_fps = %d", + __func__, current_min_fps, current_max_fps); + ret = UNKNOWN_ERROR; + } + } + } else { + /* Check basic validation if scene mode is different */ + if ((new_min_fps > new_max_fps) || + (new_min_fps < 0) || (new_max_fps < 0)) + ret = UNKNOWN_ERROR; + } + + if (new_scene_mode_str != NULL) { + int new_scene_mode = -1; + + const char *new_flash_mode_str = params.get(CameraParameters::KEY_FLASH_MODE); + const char *new_focus_mode_str; + + new_focus_mode_str = params.get(CameraParameters::KEY_FOCUS_MODE); + // fps range is (15000,30000) by default. + mParameters.set(CameraParameters::KEY_SUPPORTED_PREVIEW_FPS_RANGE, "(15000,30000)"); + mParameters.set(CameraParameters::KEY_PREVIEW_FPS_RANGE, + "15000,30000"); + + if (!strcmp(new_scene_mode_str, CameraParameters::SCENE_MODE_AUTO)) { + new_scene_mode = SCENE_MODE_NONE; + } else { + // defaults for non-auto scene modes + if (mSecCamera->getCameraId() == SecCamera::CAMERA_ID_BACK) { + new_focus_mode_str = CameraParameters::FOCUS_MODE_AUTO; + } + new_flash_mode_str = CameraParameters::FLASH_MODE_OFF; + + if (!strcmp(new_scene_mode_str, + CameraParameters::SCENE_MODE_PORTRAIT)) { + new_scene_mode = SCENE_MODE_PORTRAIT; + new_flash_mode_str = CameraParameters::FLASH_MODE_AUTO; + } else if (!strcmp(new_scene_mode_str, + CameraParameters::SCENE_MODE_LANDSCAPE)) { + new_scene_mode = SCENE_MODE_LANDSCAPE; + } else if (!strcmp(new_scene_mode_str, + CameraParameters::SCENE_MODE_SPORTS)) { + new_scene_mode = SCENE_MODE_SPORTS; + } else if (!strcmp(new_scene_mode_str, + CameraParameters::SCENE_MODE_PARTY)) { + new_scene_mode = SCENE_MODE_PARTY_INDOOR; + new_flash_mode_str = CameraParameters::FLASH_MODE_AUTO; + } else if ((!strcmp(new_scene_mode_str, + CameraParameters::SCENE_MODE_BEACH)) || + (!strcmp(new_scene_mode_str, + CameraParameters::SCENE_MODE_SNOW))) { + new_scene_mode = SCENE_MODE_BEACH_SNOW; + } else if (!strcmp(new_scene_mode_str, + CameraParameters::SCENE_MODE_SUNSET)) { + new_scene_mode = SCENE_MODE_SUNSET; + } else if (!strcmp(new_scene_mode_str, + CameraParameters::SCENE_MODE_NIGHT)) { + new_scene_mode = SCENE_MODE_NIGHTSHOT; + mParameters.set(CameraParameters::KEY_SUPPORTED_PREVIEW_FPS_RANGE, "(4000,30000)"); + mParameters.set(CameraParameters::KEY_PREVIEW_FPS_RANGE, + "4000,30000"); + } else if (!strcmp(new_scene_mode_str, + CameraParameters::SCENE_MODE_FIREWORKS)) { + new_scene_mode = SCENE_MODE_FIREWORKS; + } else if (!strcmp(new_scene_mode_str, + CameraParameters::SCENE_MODE_CANDLELIGHT)) { + new_scene_mode = SCENE_MODE_CANDLE_LIGHT; + } else { + LOGE("%s::unmatched scene_mode(%s)", + __func__, new_scene_mode_str); //action, night-portrait, theatre, steadyphoto + ret = UNKNOWN_ERROR; + } + } + + // focus mode + if (new_focus_mode_str != NULL) { + int new_focus_mode = -1; + + if (!strcmp(new_focus_mode_str, + CameraParameters::FOCUS_MODE_AUTO)) { + new_focus_mode = FOCUS_MODE_AUTO; + mParameters.set(CameraParameters::KEY_FOCUS_DISTANCES, + BACK_CAMERA_AUTO_FOCUS_DISTANCES_STR); + } else if (!strcmp(new_focus_mode_str, + CameraParameters::FOCUS_MODE_MACRO)) { + new_focus_mode = FOCUS_MODE_MACRO; + mParameters.set(CameraParameters::KEY_FOCUS_DISTANCES, + BACK_CAMERA_MACRO_FOCUS_DISTANCES_STR); + } else if (!strcmp(new_focus_mode_str, + CameraParameters::FOCUS_MODE_INFINITY)) { + new_focus_mode = FOCUS_MODE_INFINITY; + mParameters.set(CameraParameters::KEY_FOCUS_DISTANCES, + BACK_CAMERA_INFINITY_FOCUS_DISTANCES_STR); + } else { + LOGE("%s::unmatched focus_mode(%s)", __func__, new_focus_mode_str); + ret = UNKNOWN_ERROR; + } + + if (0 <= new_focus_mode) { + if (mSecCamera->setFocusMode(new_focus_mode) < 0) { + LOGE("%s::mSecCamera->setFocusMode(%d) fail", __func__, new_focus_mode); + ret = UNKNOWN_ERROR; + } else { + mParameters.set(CameraParameters::KEY_FOCUS_MODE, new_focus_mode_str); + } + } + } + + // flash.. + if (new_flash_mode_str != NULL) { + int new_flash_mode = -1; + + if (!strcmp(new_flash_mode_str, CameraParameters::FLASH_MODE_OFF)) + new_flash_mode = FLASH_MODE_OFF; + else if (!strcmp(new_flash_mode_str, CameraParameters::FLASH_MODE_AUTO)) + new_flash_mode = FLASH_MODE_AUTO; + else if (!strcmp(new_flash_mode_str, CameraParameters::FLASH_MODE_ON)) + new_flash_mode = FLASH_MODE_ON; + else if (!strcmp(new_flash_mode_str, CameraParameters::FLASH_MODE_TORCH)) + new_flash_mode = FLASH_MODE_TORCH; + else { + LOGE("%s::unmatched flash_mode(%s)", __func__, new_flash_mode_str); //red-eye + ret = UNKNOWN_ERROR; + } + if (0 <= new_flash_mode) { + if (mSecCamera->setFlashMode(new_flash_mode) < 0) { + LOGE("%s::mSecCamera->setFlashMode(%d) fail", __func__, new_flash_mode); + ret = UNKNOWN_ERROR; + } else { + mParameters.set(CameraParameters::KEY_FLASH_MODE, new_flash_mode_str); + } + } + } + + // scene.. + if (0 <= new_scene_mode) { + if (mSecCamera->setSceneMode(new_scene_mode) < 0) { + LOGE("%s::mSecCamera->setSceneMode(%d) fail", __func__, new_scene_mode); + ret = UNKNOWN_ERROR; + } else { + mParameters.set(CameraParameters::KEY_SCENE_MODE, new_scene_mode_str); + } + } + } + + // image effect + const char *new_image_effect_str = params.get(CameraParameters::KEY_EFFECT); + if (new_image_effect_str != NULL) { + + int new_image_effect = -1; + + if (!strcmp(new_image_effect_str, CameraParameters::EFFECT_NONE)) { + if (Internal_is) + new_image_effect = IS_IMAGE_EFFECT_DISABLE; + else + new_image_effect = IMAGE_EFFECT_NONE; + } else if (!strcmp(new_image_effect_str, CameraParameters::EFFECT_MONO)) { + if (Internal_is) + new_image_effect = IS_IMAGE_EFFECT_MONOCHROME; + else + new_image_effect = IMAGE_EFFECT_BNW; + } else if (!strcmp(new_image_effect_str, CameraParameters::EFFECT_SEPIA)) { + if (Internal_is) + new_image_effect = IS_IMAGE_EFFECT_SEPIA; + else + new_image_effect = IMAGE_EFFECT_SEPIA; + } else if (!strcmp(new_image_effect_str, CameraParameters::EFFECT_AQUA)) + new_image_effect = IMAGE_EFFECT_AQUA; + else if (!strcmp(new_image_effect_str, CameraParameters::EFFECT_NEGATIVE)) { + if (Internal_is) + new_image_effect = IS_IMAGE_EFFECT_NEGATIVE_MONO; + else + LOGW("WARN(%s):Invalid effect value (%s)", __func__, new_image_effect_str); + } else { + //posterize, whiteboard, blackboard, solarize + LOGE("ERR(%s):Invalid effect(%s)", __func__, new_image_effect_str); + ret = UNKNOWN_ERROR; + } + + if (new_image_effect >= 0) { + if (mSecCamera->setImageEffect(new_image_effect) < 0) { + LOGE("ERR(%s):Fail on mSecCamera->setImageEffect(effect(%d))", __func__, new_image_effect); + ret = UNKNOWN_ERROR; + } else { + const char *old_image_effect_str = mParameters.get(CameraParameters::KEY_EFFECT); + + if (old_image_effect_str) { + if (strcmp(old_image_effect_str, new_image_effect_str)) { + setSkipFrame(EFFECT_SKIP_FRAME); + } + } + + mParameters.set(CameraParameters::KEY_EFFECT, new_image_effect_str); + } + } + } + + //contrast + const char *new_contrast_str = params.get("contrast"); + LOGV("%s : new_contrast_str %s", __func__, new_contrast_str); + if (new_contrast_str != NULL) { + int new_contrast = -1; + + if (!strcmp(new_contrast_str, "auto")) { + if (Internal_is) + new_contrast = IS_CONTRAST_AUTO; + else + LOGW("WARN(%s):Invalid contrast value (%s)", __func__, new_contrast_str); + } else if (!strcmp(new_contrast_str, "-2")) { + if (Internal_is) + new_contrast = IS_CONTRAST_MINUS_2; + else + new_contrast = CONTRAST_MINUS_2; + } else if (!strcmp(new_contrast_str, "-1")) { + if (Internal_is) + new_contrast = IS_CONTRAST_MINUS_1; + else + new_contrast = CONTRAST_MINUS_1; + } else if (!strcmp(new_contrast_str, "0")) { + if (Internal_is) + new_contrast = IS_CONTRAST_DEFAULT; + else + new_contrast = CONTRAST_DEFAULT; + } else if (!strcmp(new_contrast_str, "1")) { + if (Internal_is) + new_contrast = IS_CONTRAST_PLUS_1; + else + new_contrast = CONTRAST_PLUS_1; + } else if (!strcmp(new_contrast_str, "2")) { + if (Internal_is) + new_contrast = IS_CONTRAST_PLUS_2; + else + new_contrast = CONTRAST_PLUS_2; + } else { + LOGE("ERR(%s):Invalid contrast value(%s)", __func__, new_contrast_str); + ret = UNKNOWN_ERROR; + } + + if (0 <= new_contrast) { + if (mSecCamera->setContrast(new_contrast) < 0) { + LOGE("ERR(%s):Fail on mSecCamera->setContrast(contrast(%d))", __func__, new_contrast); + ret = UNKNOWN_ERROR; + } else { + mParameters.set("contrast", new_contrast_str); + } + } + } + + //WDR + int new_wdr = params.getInt("wdr"); + LOGV("%s : new_wdr %d", __func__, new_wdr); + + if (0 <= new_wdr) { + if (mSecCamera->setWDR(new_wdr) < 0) { + LOGE("ERR(%s):Fail on mSecCamera->setWDR(%d)", __func__, new_wdr); + ret = UNKNOWN_ERROR; + } + } + + //anti shake + int new_anti_shake = mInternalParameters.getInt("anti-shake"); + + if (0 <= new_anti_shake) { + if (mSecCamera->setAntiShake(new_anti_shake) < 0) { + LOGE("ERR(%s):Fail on mSecCamera->setWDR(%d)", __func__, new_anti_shake); + ret = UNKNOWN_ERROR; + } + } + + // gps latitude + const char *new_gps_latitude_str = params.get(CameraParameters::KEY_GPS_LATITUDE); + if (mSecCamera->setGPSLatitude(new_gps_latitude_str) < 0) { + LOGE("%s::mSecCamera->setGPSLatitude(%s) fail", __func__, new_gps_latitude_str); + ret = UNKNOWN_ERROR; + } else { + if (new_gps_latitude_str) { + mParameters.set(CameraParameters::KEY_GPS_LATITUDE, new_gps_latitude_str); + } else { + mParameters.remove(CameraParameters::KEY_GPS_LATITUDE); + } + } + + // gps longitude + const char *new_gps_longitude_str = params.get(CameraParameters::KEY_GPS_LONGITUDE); + + if (mSecCamera->setGPSLongitude(new_gps_longitude_str) < 0) { + LOGE("%s::mSecCamera->setGPSLongitude(%s) fail", __func__, new_gps_longitude_str); + ret = UNKNOWN_ERROR; + } else { + if (new_gps_longitude_str) { + mParameters.set(CameraParameters::KEY_GPS_LONGITUDE, new_gps_longitude_str); + } else { + mParameters.remove(CameraParameters::KEY_GPS_LONGITUDE); + } + } + + // gps altitude + const char *new_gps_altitude_str = params.get(CameraParameters::KEY_GPS_ALTITUDE); + + if (mSecCamera->setGPSAltitude(new_gps_altitude_str) < 0) { + LOGE("%s::mSecCamera->setGPSAltitude(%s) fail", __func__, new_gps_altitude_str); + ret = UNKNOWN_ERROR; + } else { + if (new_gps_altitude_str) { + mParameters.set(CameraParameters::KEY_GPS_ALTITUDE, new_gps_altitude_str); + } else { + mParameters.remove(CameraParameters::KEY_GPS_ALTITUDE); + } + } + + // gps timestamp + const char *new_gps_timestamp_str = params.get(CameraParameters::KEY_GPS_TIMESTAMP); + + if (mSecCamera->setGPSTimeStamp(new_gps_timestamp_str) < 0) { + LOGE("%s::mSecCamera->setGPSTimeStamp(%s) fail", __func__, new_gps_timestamp_str); + ret = UNKNOWN_ERROR; + } else { + if (new_gps_timestamp_str) { + mParameters.set(CameraParameters::KEY_GPS_TIMESTAMP, new_gps_timestamp_str); + } else { + mParameters.remove(CameraParameters::KEY_GPS_TIMESTAMP); + } + } + + // gps processing method + const char *new_gps_processing_method_str = params.get(CameraParameters::KEY_GPS_PROCESSING_METHOD); + + if (mSecCamera->setGPSProcessingMethod(new_gps_processing_method_str) < 0) { + LOGE("%s::mSecCamera->setGPSProcessingMethod(%s) fail", __func__, new_gps_processing_method_str); + ret = UNKNOWN_ERROR; + } else { + if (new_gps_processing_method_str) { + mParameters.set(CameraParameters::KEY_GPS_PROCESSING_METHOD, new_gps_processing_method_str); + } else { + mParameters.remove(CameraParameters::KEY_GPS_PROCESSING_METHOD); + } + } + + // Recording size + int new_recording_width = 0; + int new_recording_height = 0; + params.getVideoSize(&new_recording_width, &new_recording_height); + LOGV("new_recording_width (%d) new_recording_height (%d)", + new_recording_width, new_recording_height); + + int current_recording_width, current_recording_height; + mSecCamera->getRecordingSize(¤t_recording_width, ¤t_recording_height); + LOGV("current_recording_width (%d) current_recording_height (%d)", + current_recording_width, current_recording_height); + + if (0 < new_recording_width && 0 < new_recording_height) { + if (current_recording_width != new_recording_width || + current_recording_height != new_recording_height) { + if (mSecCamera->setRecordingSize(new_recording_width, new_recording_height) < 0) { + LOGE("ERR(%s):Fail on mSecCamera->setRecordingSize(width(%d), height(%d))", + __func__, new_recording_width, new_recording_height); + ret = UNKNOWN_ERROR; + } else { + if (Internal_is && mPreviewWindow && mPreviewRunning) { + mSecCamera->setRecording(1); + stopPreview(); + startPreview(); + mSecCamera->setRecording(0); + } + } + } + mParameters.setVideoSize(new_recording_width, new_recording_height); + } else { + if (mSecCamera->setRecordingSize(new_preview_width, new_preview_height) < 0) { + LOGE("ERR(%s):Fail on mSecCamera->setRecordingSize(width(%d), height(%d))", + __func__, new_preview_width, new_preview_height); + ret = UNKNOWN_ERROR; + } + } + + //gamma + const char *new_gamma_str = mInternalParameters.get("video_recording_gamma"); + + if (new_gamma_str != NULL) { + int new_gamma = -1; + if (!strcmp(new_gamma_str, "off")) + new_gamma = GAMMA_OFF; + else if (!strcmp(new_gamma_str, "on")) + new_gamma = GAMMA_ON; + else { + LOGE("%s::unmatched gamma(%s)", __func__, new_gamma_str); + ret = UNKNOWN_ERROR; + } + + if (0 <= new_gamma) { + if (mSecCamera->setGamma(new_gamma) < 0) { + LOGE("%s::mSecCamera->setGamma(%d) fail", __func__, new_gamma); + ret = UNKNOWN_ERROR; + } + } + } + + //slow ae + const char *new_slow_ae_str = mInternalParameters.get("slow_ae"); + + if (new_slow_ae_str != NULL) { + int new_slow_ae = -1; + + if (!strcmp(new_slow_ae_str, "off")) + new_slow_ae = SLOW_AE_OFF; + else if (!strcmp(new_slow_ae_str, "on")) + new_slow_ae = SLOW_AE_ON; + else { + LOGE("%s::unmatched slow_ae(%s)", __func__, new_slow_ae_str); + ret = UNKNOWN_ERROR; + } + + if (0 <= new_slow_ae) { + if (mSecCamera->setSlowAE(new_slow_ae) < 0) { + LOGE("%s::mSecCamera->setSlowAE(%d) fail", __func__, new_slow_ae); + ret = UNKNOWN_ERROR; + } + } + } + + /*Camcorder fix fps*/ + int new_sensor_mode = mInternalParameters.getInt("cam_mode"); + + if (0 <= new_sensor_mode) { + if (mSecCamera->setSensorMode(new_sensor_mode) < 0) { + LOGE("ERR(%s):Fail on mSecCamera->setSensorMode(%d)", __func__, new_sensor_mode); + ret = UNKNOWN_ERROR; + } + } else { + new_sensor_mode=0; + } + + /*Shot mode*/ + int new_shot_mode = mInternalParameters.getInt("shot_mode"); + + if (0 <= new_shot_mode) { + if (mSecCamera->setShotMode(new_shot_mode) < 0) { + LOGE("ERR(%s):Fail on mSecCamera->setShotMode(%d)", __func__, new_shot_mode); + ret = UNKNOWN_ERROR; + } + } else { + new_shot_mode=0; + } + + // chk_dataline + int new_dataline = mInternalParameters.getInt("chk_dataline"); + + if (0 <= new_dataline) { + if (mSecCamera->setDataLineCheck(new_dataline) < 0) { + LOGE("ERR(%s):Fail on mSecCamera->setDataLineCheck(%d)", __func__, new_dataline); + ret = UNKNOWN_ERROR; + } + } + LOGV("%s return ret = %d", __func__, ret); +#endif + + return ret; +} + +CameraParameters CameraHardwareSec::getParameters() const +{ + LOGV("%s :", __func__); + return mParameters; +} + +status_t CameraHardwareSec::sendCommand(int32_t command, int32_t arg1, int32_t arg2) +{ + return BAD_VALUE; +} + +void CameraHardwareSec::release() +{ + LOGV("%s", __func__); + + /* shut down any threads we have that might be running. do it here + * instead of the destructor. we're guaranteed to be on another thread + * than the ones below. if we used the destructor, since the threads + * have a reference to this object, we could wind up trying to wait + * for ourself to exit, which is a deadlock. + */ + if (mPreviewThread != NULL) { + /* this thread is normally already in it's threadLoop but blocked + * on the condition variable or running. signal it so it wakes + * up and can exit. + */ + mPreviewThread->requestExit(); + mExitPreviewThread = true; + mPreviewRunning = true; /* let it run so it can exit */ + mPreviewCondition.signal(); + mPreviewThread->requestExitAndWait(); + mPreviewThread.clear(); + } + if (mAutoFocusThread != NULL) { + /* this thread is normally already in it's threadLoop but blocked + * on the condition variable. signal it so it wakes up and can exit. + */ + mFocusLock.lock(); + mAutoFocusThread->requestExit(); + mExitAutoFocusThread = true; + mFocusCondition.signal(); + mFocusLock.unlock(); + mAutoFocusThread->requestExitAndWait(); + mAutoFocusThread.clear(); + } + if (mPictureThread != NULL) { + mPictureThread->requestExitAndWait(); + mPictureThread.clear(); + } + + if (mRawHeap) { + mRawHeap->release(mRawHeap); + mRawHeap = 0; + } + if (mPreviewHeap) { + mPreviewHeap->release(mPreviewHeap); + mPreviewHeap = 0; + } + for(int i = 0; i < BUFFER_COUNT_FOR_ARRAY; i++) { + if (mRecordHeap[i]) { + mRecordHeap[i]->release(mRecordHeap[i]); + mRecordHeap[i] = 0; + } + } + + /* close after all the heaps are cleared since those + * could have dup'd our file descriptor. + */ + mSecCamera->DestroyCamera(); +} + +static CameraInfo sCameraInfo[] = { + { + CAMERA_FACING_BACK, + 0, /* orientation */ + }, + { + CAMERA_FACING_FRONT, + 0, /* orientation */ + } +}; + +status_t CameraHardwareSec::storeMetaDataInBuffers(bool enable) +{ + if (!enable) { + LOGE("Non-metadata buffer mode is not supported!"); + return INVALID_OPERATION; + } + return OK; +} + +/** Close this device */ + +static camera_device_t *g_cam_device; + +static int HAL_camera_device_close(struct hw_device_t* device) +{ + LOGI("%s", __func__); + if (device) { + camera_device_t *cam_device = (camera_device_t *)device; + delete static_cast(cam_device->priv); + free(cam_device); + g_cam_device = 0; + } + return 0; +} + +static inline CameraHardwareSec *obj(struct camera_device *dev) +{ + return reinterpret_cast(dev->priv); +} + +/** Set the preview_stream_ops to which preview frames are sent */ +static int HAL_camera_device_set_preview_window(struct camera_device *dev, + struct preview_stream_ops *buf) +{ + LOGV("%s", __func__); + return obj(dev)->setPreviewWindow(buf); +} + +/** Set the notification and data callbacks */ +static void HAL_camera_device_set_callbacks(struct camera_device *dev, + camera_notify_callback notify_cb, + camera_data_callback data_cb, + camera_data_timestamp_callback data_cb_timestamp, + camera_request_memory get_memory, + void* user) +{ + LOGV("%s", __func__); + obj(dev)->setCallbacks(notify_cb, data_cb, data_cb_timestamp, + get_memory, + user); +} + +/** + * The following three functions all take a msg_type, which is a bitmask of + * the messages defined in include/ui/Camera.h + */ + +/** + * Enable a message, or set of messages. + */ +static void HAL_camera_device_enable_msg_type(struct camera_device *dev, int32_t msg_type) +{ + LOGV("%s", __func__); + obj(dev)->enableMsgType(msg_type); +} + +/** + * Disable a message, or a set of messages. + * + * Once received a call to disableMsgType(CAMERA_MSG_VIDEO_FRAME), camera + * HAL should not rely on its client to call releaseRecordingFrame() to + * release video recording frames sent out by the cameral HAL before and + * after the disableMsgType(CAMERA_MSG_VIDEO_FRAME) call. Camera HAL + * clients must not modify/access any video recording frame after calling + * disableMsgType(CAMERA_MSG_VIDEO_FRAME). + */ +static void HAL_camera_device_disable_msg_type(struct camera_device *dev, int32_t msg_type) +{ + LOGV("%s", __func__); + obj(dev)->disableMsgType(msg_type); +} + +/** + * Query whether a message, or a set of messages, is enabled. Note that + * this is operates as an AND, if any of the messages queried are off, this + * will return false. + */ +static int HAL_camera_device_msg_type_enabled(struct camera_device *dev, int32_t msg_type) +{ + LOGV("%s", __func__); + return obj(dev)->msgTypeEnabled(msg_type); +} + +/** + * Start preview mode. + */ +static int HAL_camera_device_start_preview(struct camera_device *dev) +{ + LOGV("%s", __func__); + return obj(dev)->startPreview(); +} + +/** + * Stop a previously started preview. + */ +static void HAL_camera_device_stop_preview(struct camera_device *dev) +{ + LOGV("%s", __func__); + obj(dev)->stopPreview(); +} + +/** + * Returns true if preview is enabled. + */ +static int HAL_camera_device_preview_enabled(struct camera_device *dev) +{ + LOGV("%s", __func__); + return obj(dev)->previewEnabled(); +} + +/** + * Request the camera HAL to store meta data or real YUV data in the video + * buffers sent out via CAMERA_MSG_VIDEO_FRAME for a recording session. If + * it is not called, the default camera HAL behavior is to store real YUV + * data in the video buffers. + * + * This method should be called before startRecording() in order to be + * effective. + * + * If meta data is stored in the video buffers, it is up to the receiver of + * the video buffers to interpret the contents and to find the actual frame + * data with the help of the meta data in the buffer. How this is done is + * outside of the scope of this method. + * + * Some camera HALs may not support storing meta data in the video buffers, + * but all camera HALs should support storing real YUV data in the video + * buffers. If the camera HAL does not support storing the meta data in the + * video buffers when it is requested to do do, INVALID_OPERATION must be + * returned. It is very useful for the camera HAL to pass meta data rather + * than the actual frame data directly to the video encoder, since the + * amount of the uncompressed frame data can be very large if video size is + * large. + * + * @param enable if true to instruct the camera HAL to store + * meta data in the video buffers; false to instruct + * the camera HAL to store real YUV data in the video + * buffers. + * + * @return OK on success. + */ +static int HAL_camera_device_store_meta_data_in_buffers(struct camera_device *dev, int enable) +{ + LOGV("%s", __func__); + return obj(dev)->storeMetaDataInBuffers(enable); +} + +/** + * Start record mode. When a record image is available, a + * CAMERA_MSG_VIDEO_FRAME message is sent with the corresponding + * frame. Every record frame must be released by a camera HAL client via + * releaseRecordingFrame() before the client calls + * disableMsgType(CAMERA_MSG_VIDEO_FRAME). After the client calls + * disableMsgType(CAMERA_MSG_VIDEO_FRAME), it is the camera HAL's + * responsibility to manage the life-cycle of the video recording frames, + * and the client must not modify/access any video recording frames. + */ +static int HAL_camera_device_start_recording(struct camera_device *dev) +{ + LOGV("%s", __func__); + return obj(dev)->startRecording(); +} + +/** + * Stop a previously started recording. + */ +static void HAL_camera_device_stop_recording(struct camera_device *dev) +{ + LOGV("%s", __func__); + obj(dev)->stopRecording(); +} + +/** + * Returns true if recording is enabled. + */ +static int HAL_camera_device_recording_enabled(struct camera_device *dev) +{ + LOGV("%s", __func__); + return obj(dev)->recordingEnabled(); +} + +/** + * Release a record frame previously returned by CAMERA_MSG_VIDEO_FRAME. + * + * It is camera HAL client's responsibility to release video recording + * frames sent out by the camera HAL before the camera HAL receives a call + * to disableMsgType(CAMERA_MSG_VIDEO_FRAME). After it receives the call to + * disableMsgType(CAMERA_MSG_VIDEO_FRAME), it is the camera HAL's + * responsibility to manage the life-cycle of the video recording frames. + */ +static void HAL_camera_device_release_recording_frame(struct camera_device *dev, + const void *opaque) +{ + LOGV("%s", __func__); + obj(dev)->releaseRecordingFrame(opaque); +} + +/** + * Start auto focus, the notification callback routine is called with + * CAMERA_MSG_FOCUS once when focusing is complete. autoFocus() will be + * called again if another auto focus is needed. + */ +static int HAL_camera_device_auto_focus(struct camera_device *dev) +{ + LOGV("%s", __func__); + return obj(dev)->autoFocus(); +} + +/** + * Cancels auto-focus function. If the auto-focus is still in progress, + * this function will cancel it. Whether the auto-focus is in progress or + * not, this function will return the focus position to the default. If + * the camera does not support auto-focus, this is a no-op. + */ +static int HAL_camera_device_cancel_auto_focus(struct camera_device *dev) +{ + LOGV("%s", __func__); + return obj(dev)->cancelAutoFocus(); +} + +/** + * Take a picture. + */ +static int HAL_camera_device_take_picture(struct camera_device *dev) +{ + LOGV("%s", __func__); + return obj(dev)->takePicture(); +} + +/** + * Cancel a picture that was started with takePicture. Calling this method + * when no picture is being taken is a no-op. + */ +static int HAL_camera_device_cancel_picture(struct camera_device *dev) +{ + LOGV("%s", __func__); + return obj(dev)->cancelPicture(); +} + +/** + * Set the camera parameters. This returns BAD_VALUE if any parameter is + * invalid or not supported. + */ +static int HAL_camera_device_set_parameters(struct camera_device *dev, + const char *parms) +{ + LOGV("%s", __func__); + String8 str(parms); + CameraParameters p(str); + return obj(dev)->setParameters(p); +} + +/** Return the camera parameters. */ +char *HAL_camera_device_get_parameters(struct camera_device *dev) +{ + LOGV("%s", __func__); + String8 str; + CameraParameters parms = obj(dev)->getParameters(); + str = parms.flatten(); + return strdup(str.string()); +} + +static void HAL_camera_device_put_parameters(struct camera_device *dev, char *parms) +{ + LOGV("%s", __func__); + free(parms); +} + +/** + * Send command to camera driver. + */ +static int HAL_camera_device_send_command(struct camera_device *dev, + int32_t cmd, int32_t arg1, int32_t arg2) +{ + LOGV("%s", __func__); + return obj(dev)->sendCommand(cmd, arg1, arg2); +} + +/** + * Release the hardware resources owned by this object. Note that this is + * *not* done in the destructor. + */ +static void HAL_camera_device_release(struct camera_device *dev) +{ + LOGV("%s", __func__); + obj(dev)->release(); +} + +/** + * Dump state of the camera hardware + */ +static int HAL_camera_device_dump(struct camera_device *dev, int fd) +{ + LOGV("%s", __func__); + return obj(dev)->dump(fd); +} + +static int HAL_getNumberOfCameras() +{ + LOGV("%s", __func__); + return sizeof(sCameraInfo) / sizeof(sCameraInfo[0]); +} + +static int HAL_getCameraInfo(int cameraId, struct camera_info *cameraInfo) +{ + LOGV("%s", __func__); + memcpy(cameraInfo, &sCameraInfo[cameraId], sizeof(CameraInfo)); + return 0; +} + +#define SET_METHOD(m) m : HAL_camera_device_##m + +static camera_device_ops_t camera_device_ops = { + SET_METHOD(set_preview_window), + SET_METHOD(set_callbacks), + SET_METHOD(enable_msg_type), + SET_METHOD(disable_msg_type), + SET_METHOD(msg_type_enabled), + SET_METHOD(start_preview), + SET_METHOD(stop_preview), + SET_METHOD(preview_enabled), + SET_METHOD(store_meta_data_in_buffers), + SET_METHOD(start_recording), + SET_METHOD(stop_recording), + SET_METHOD(recording_enabled), + SET_METHOD(release_recording_frame), + SET_METHOD(auto_focus), + SET_METHOD(cancel_auto_focus), + SET_METHOD(take_picture), + SET_METHOD(cancel_picture), + SET_METHOD(set_parameters), + SET_METHOD(get_parameters), + SET_METHOD(put_parameters), + SET_METHOD(send_command), + SET_METHOD(release), + SET_METHOD(dump), +}; + +#undef SET_METHOD + +static int HAL_camera_device_open(const struct hw_module_t* module, + const char *id, + struct hw_device_t** device) +{ + LOGV("%s", __func__); + + int cameraId = atoi(id); + if (cameraId < 0 || cameraId >= HAL_getNumberOfCameras()) { + LOGE("Invalid camera ID %s", id); + return -EINVAL; + } + + if (g_cam_device) { + if (obj(g_cam_device)->getCameraId() == cameraId) { + LOGV("returning existing camera ID %s", id); + goto done; + } else { + LOGE("Cannot open camera %d. camera %d is already running!", + cameraId, obj(g_cam_device)->getCameraId()); + return -ENOSYS; + } + } + + g_cam_device = (camera_device_t *)malloc(sizeof(camera_device_t)); + if (!g_cam_device) + return -ENOMEM; + + g_cam_device->common.tag = HARDWARE_DEVICE_TAG; + g_cam_device->common.version = 1; + g_cam_device->common.module = const_cast(module); + g_cam_device->common.close = HAL_camera_device_close; + + g_cam_device->ops = &camera_device_ops; + + LOGI("%s: open camera %s", __func__, id); + + g_cam_device->priv = new CameraHardwareSec(cameraId, g_cam_device); + +done: + *device = (hw_device_t *)g_cam_device; + LOGI("%s: opened camera %s (%p)", __func__, id, *device); + return 0; +} + +static hw_module_methods_t camera_module_methods = { + open : HAL_camera_device_open +}; + +extern "C" { + struct camera_module HAL_MODULE_INFO_SYM = { + common : { + tag : HARDWARE_MODULE_TAG, + version_major : 1, + version_minor : 0, + id : CAMERA_HARDWARE_MODULE_ID, + name : "orion camera HAL", + author : "Samsung Corporation", + methods : &camera_module_methods, + }, + get_number_of_cameras : HAL_getNumberOfCameras, + get_camera_info : HAL_getCameraInfo + }; +} + +}; // namespace android diff --git a/exynos5/hal/libcamera/SecCameraHWInterface.h b/exynos5/hal/libcamera/SecCameraHWInterface.h new file mode 100644 index 0000000..6be8ae2 --- /dev/null +++ b/exynos5/hal/libcamera/SecCameraHWInterface.h @@ -0,0 +1,219 @@ +/* +** +** Copyright 2008, The Android Open Source Project +** Copyright 2010, Samsung Electronics Co. LTD +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + +#ifndef ANDROID_HARDWARE_CAMERA_HARDWARE_SEC_H + +#include "SecCamera.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "gralloc_priv.h" + +#define BUFFER_COUNT_FOR_GRALLOC (MAX_BUFFERS + 4) +#define BUFFER_COUNT_FOR_ARRAY (MAX_BUFFERS) + +namespace android { + class CameraHardwareSec : public virtual RefBase { +public: + virtual void setCallbacks(camera_notify_callback notify_cb, + camera_data_callback data_cb, + camera_data_timestamp_callback data_cb_timestamp, + camera_request_memory get_memory, + void *user); + + virtual void enableMsgType(int32_t msgType); + virtual void disableMsgType(int32_t msgType); + virtual bool msgTypeEnabled(int32_t msgType); + + virtual status_t startPreview(); + virtual void stopPreview(); + virtual bool previewEnabled(); + + virtual status_t startRecording(); + virtual void stopRecording(); + virtual bool recordingEnabled(); + virtual void releaseRecordingFrame(const void *opaque); + + virtual status_t autoFocus(); + virtual status_t cancelAutoFocus(); + virtual status_t takePicture(); + virtual status_t cancelPicture(); + virtual status_t dump(int fd) const; + virtual status_t setParameters(const CameraParameters& params); + virtual CameraParameters getParameters() const; + virtual status_t sendCommand(int32_t command, int32_t arg1, int32_t arg2); + virtual status_t setPreviewWindow(preview_stream_ops *w); + virtual status_t storeMetaDataInBuffers(bool enable); + virtual void release(); + + inline int getCameraId() const; + + CameraHardwareSec(int cameraId, camera_device_t *dev); + virtual ~CameraHardwareSec(); +private: + status_t startPreviewInternal(); + void stopPreviewInternal(); + + class PreviewThread : public Thread { + CameraHardwareSec *mHardware; + public: + PreviewThread(CameraHardwareSec *hw): + Thread(false), + mHardware(hw) { } + virtual void onFirstRef() { + run("CameraPreviewThread", PRIORITY_URGENT_DISPLAY); + } + virtual bool threadLoop() { + mHardware->previewThreadWrapper(); + return false; + } + }; + + class PictureThread : public Thread { + CameraHardwareSec *mHardware; + public: + PictureThread(CameraHardwareSec *hw): + Thread(false), + mHardware(hw) { } + virtual bool threadLoop() { + mHardware->pictureThread(); + mHardware->mSecCamera->endSnapshot(); + return false; + } + }; + + class AutoFocusThread : public Thread { + CameraHardwareSec *mHardware; + public: + AutoFocusThread(CameraHardwareSec *hw): Thread(false), mHardware(hw) { } + virtual void onFirstRef() { + run("CameraAutoFocusThread", PRIORITY_DEFAULT); + } + virtual bool threadLoop() { + mHardware->autoFocusThread(); + return true; + } + }; + + void initDefaultParameters(int cameraId); + void initHeapLocked(); + + sp mPreviewThread; + int previewThread(); + int previewThreadWrapper(); + + sp mAutoFocusThread; + int autoFocusThread(); + + sp mPictureThread; + int pictureThread(); + bool mCaptureInProgress; + + int save_jpeg(unsigned char *real_jpeg, int jpeg_size); + void save_postview(const char *fname, uint8_t *buf, + uint32_t size); + int decodeInterleaveData(unsigned char *pInterleaveData, + int interleaveDataSize, + int yuvWidth, + int yuvHeight, + int *pJpegSize, + void *pJpegData, + void *pYuvData); + bool YUY2toNV21(void *srcBuf, void *dstBuf, uint32_t srcWidth, uint32_t srcHeight); + bool scaleDownYuv422(char *srcBuf, uint32_t srcWidth, + uint32_t srcHight, char *dstBuf, + uint32_t dstWidth, uint32_t dstHight); + + bool CheckVideoStartMarker(unsigned char *pBuf); + bool CheckEOIMarker(unsigned char *pBuf); + bool FindEOIMarkerInJPEG(unsigned char *pBuf, + int dwBufSize, int *pnJPEGsize); + bool SplitFrame(unsigned char *pFrame, int dwSize, + int dwJPEGLineLength, int dwVideoLineLength, + int dwVideoHeight, void *pJPEG, + int *pdwJPEGSize, void *pVideo, + int *pdwVideoSize); + void setSkipFrame(int frame); + bool isSupportedPreviewSize(const int width, + const int height) const; + /* used by auto focus thread to block until it's told to run */ + mutable Mutex mFocusLock; + mutable Condition mFocusCondition; + bool mExitAutoFocusThread; + + /* used by preview thread to block until it's told to run */ + mutable Mutex mPreviewLock; + mutable Condition mPreviewCondition; + mutable Condition mPreviewStoppedCondition; + bool mPreviewRunning; + bool mPreviewStartDeferred; + bool mExitPreviewThread; + + preview_stream_ops *mPreviewWindow; + + /* used to guard threading state */ + mutable Mutex mStateLock; + + CameraParameters mParameters; + CameraParameters mInternalParameters; + + int mFrameSizeDelta; + camera_memory_t *mPreviewHeap; + camera_memory_t *mRawHeap; + camera_memory_t *mRecordHeap[BUFFER_COUNT_FOR_ARRAY]; + + buffer_handle_t *mBufferHandle[BUFFER_COUNT_FOR_ARRAY]; + int mStride[BUFFER_COUNT_FOR_ARRAY]; + + + SecCamera *mSecCamera; + const __u8 *mCameraSensorName; + + mutable Mutex mSkipFrameLock; + int mSkipFrame; + + camera_notify_callback mNotifyCb; + camera_data_callback mDataCb; + camera_data_timestamp_callback mDataCbTimestamp; + camera_request_memory mGetMemoryCb; + void *mCallbackCookie; + + int32_t mMsgEnabled; + + bool mRecordRunning; + mutable Mutex mRecordLock; + int mPostViewWidth; + int mPostViewHeight; + int mPostViewSize; + + Vector mSupportedPreviewSizes; + + camera_device_t *mHalDevice; + static gralloc_module_t const* mGrallocHal; +}; + +}; // namespace android + +#endif diff --git a/exynos5/hal/libcamera/mediactl.cpp b/exynos5/hal/libcamera/mediactl.cpp new file mode 100644 index 0000000..468acc4 --- /dev/null +++ b/exynos5/hal/libcamera/mediactl.cpp @@ -0,0 +1,668 @@ +/* + * Media controller interface library + * + * Copyright (C) 2010-2011 Ideas on board SPRL + * + * Contact: Laurent Pinchart + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +//#include "config.h" +#define LOG_NDEBUG 0 +#define LOG_TAG "Mediactl" + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "mediactl.h" + +#define KF_MSG 0x1 +#define KF_ANY 0x2 + +#define perror_exit(cond, func) \ + if (cond) { \ + fprintf(stderr, "[%s:%d]: ", __func__, __LINE__);\ + perror(func);\ + exit(EXIT_FAILURE);\ + } + +struct media_pad *media_entity_remote_source(struct media_pad *pad) +{ + unsigned int i; + + if (!(pad->flags & MEDIA_PAD_FL_SINK)) + return NULL; + + for (i = 0; i < pad->entity->num_links; ++i) { + struct media_link *link = &pad->entity->links[i]; + + if (!(link->flags & MEDIA_LNK_FL_ENABLED)) + continue; + + if (link->sink == pad) + return link->source; + } + + return NULL; +} + +struct media_entity *media_get_entity_by_name(struct media_device *media, + const char *name, size_t length) +{ + unsigned int i; + struct media_entity *entity; + entity = (struct media_entity*)calloc(1, sizeof(struct media_entity)); + for (i = 0; i < media->entities_count; ++i) { + entity = &media->entities[i]; + + if (strncmp(entity->info.name, name, length) == 0) + return entity; + } + + return NULL; +} + +struct media_entity *media_get_entity_by_id(struct media_device *media, + __u32 id) +{ + unsigned int i; + + for (i = 0; i < media->entities_count; ++i) { + struct media_entity *entity = &media->entities[i]; + + if (entity->info.id == id) + return entity; + } + + return NULL; +} + +int media_setup_link(struct media_device *media, + struct media_pad *source, + struct media_pad *sink, + __u32 flags) +{ + struct media_link *link; + struct media_link_desc ulink; + unsigned int i; + int ret; + + for (i = 0; i < source->entity->num_links; i++) { + link = &source->entity->links[i]; + + if (link->source->entity == source->entity && + link->source->index == source->index && + link->sink->entity == sink->entity && + link->sink->index == sink->index) + break; + } + + if (i == source->entity->num_links) { + LOGE("%s: Link not found", __func__); + return -ENOENT; + } + + /* source pad */ + ulink.source.entity = source->entity->info.id; + ulink.source.index = source->index; + ulink.source.flags = MEDIA_PAD_FL_SOURCE; + + /* sink pad */ + ulink.sink.entity = sink->entity->info.id; + ulink.sink.index = sink->index; + ulink.sink.flags = MEDIA_PAD_FL_SINK; + + ulink.flags = flags | (link->flags & MEDIA_LNK_FL_IMMUTABLE); + + ret = ioctl(media->fd, MEDIA_IOC_SETUP_LINK, &ulink); + if (ret == -1) { + LOGE("%s: Unable to setup link (%s)", + __func__, strerror(errno)); + return -errno; + } + + link->flags = ulink.flags; + link->twin->flags = ulink.flags; + return 0; +} + +int media_reset_links(struct media_device *media) +{ + unsigned int i, j; + int ret; + + for (i = 0; i < media->entities_count; ++i) { + struct media_entity *entity = &media->entities[i]; + + for (j = 0; j < entity->num_links; j++) { + struct media_link *link = &entity->links[j]; + + if (link->flags & MEDIA_LNK_FL_IMMUTABLE || + link->source->entity != entity) + continue; + + ret = media_setup_link(media, link->source, link->sink, + link->flags & ~MEDIA_LNK_FL_ENABLED); + if (ret < 0) + return ret; + } + } + + return 0; +} + +static struct media_link *media_entity_add_link(struct media_entity *entity) +{ + if (entity->num_links >= entity->max_links) { + struct media_link *links = entity->links; + unsigned int max_links = entity->max_links * 2; + unsigned int i; + + links = (struct media_link*)realloc(links, max_links * sizeof *links); + if (links == NULL) + return NULL; + + for (i = 0; i < entity->num_links; ++i) + links[i].twin->twin = &links[i]; + + entity->max_links = max_links; + entity->links = links; + } + + return &entity->links[entity->num_links++]; +} + +static int media_enum_links(struct media_device *media) +{ + LOGV("%s: start", __func__); + __u32 id; + int ret = 0; + + for (id = 1; id <= media->entities_count; id++) { + struct media_entity *entity = &media->entities[id - 1]; + struct media_links_enum links; + unsigned int i; + + links.entity = entity->info.id; + links.pads = (struct media_pad_desc*)malloc(entity->info.pads * sizeof(struct media_pad_desc)); + links.links = (struct media_link_desc*)malloc(entity->info.links * sizeof(struct media_link_desc)); + + if (ioctl(media->fd, MEDIA_IOC_ENUM_LINKS, &links) < 0) { + LOGE( + "%s: Unable to enumerate pads and links (%s).", + __func__, strerror(errno)); + free(links.pads); + free(links.links); + return -errno; + } + + for (i = 0; i < entity->info.pads; ++i) { + entity->pads[i].entity = entity; + entity->pads[i].index = links.pads[i].index; + entity->pads[i].flags = links.pads[i].flags; + } + + for (i = 0; i < entity->info.links; ++i) { + struct media_link_desc *link = &links.links[i]; + struct media_link *fwdlink; + struct media_link *backlink; + struct media_entity *source; + struct media_entity *sink; + + source = media_get_entity_by_id(media, link->source.entity); + sink = media_get_entity_by_id(media, link->sink.entity); + if (source == NULL || sink == NULL) { + LOGE( + "WARNING entity %u link %u from %u/%u to %u/%u is invalid!", + id, i, link->source.entity, + link->source.index, + link->sink.entity, + link->sink.index); + ret = -EINVAL; + } else { + fwdlink = media_entity_add_link(source); + fwdlink->source = &source->pads[link->source.index]; + fwdlink->sink = &sink->pads[link->sink.index]; + fwdlink->flags = link->flags; + + backlink = media_entity_add_link(sink); + backlink->source = &source->pads[link->source.index]; + backlink->sink = &sink->pads[link->sink.index]; + backlink->flags = link->flags; + + fwdlink->twin = backlink; + backlink->twin = fwdlink; + } + } + + free(links.pads); + free(links.links); + } + return ret; +} + +#ifdef HAVE_LIBUDEV + +#include + +static inline int media_udev_open(struct udev **udev) +{ + *udev = udev_new(); + if (*udev == NULL) + return -ENOMEM; + return 0; +} + +static inline void media_udev_close(struct udev *udev) +{ + if (udev != NULL) + udev_unref(udev); +} + +static int media_get_devname_udev(struct udev *udev, + struct media_entity *entity) +{ + struct udev_device *device; + dev_t devnum; + const char *p; + int ret = -ENODEV; + + if (udev == NULL) + return -EINVAL; + + devnum = makedev(entity->info.v4l.major, entity->info.v4l.minor); + LOGE("looking up device: %u:%u", + major(devnum), minor(devnum)); + device = udev_device_new_from_devnum(udev, 'c', devnum); + if (device) { + p = udev_device_get_devnode(device); + if (p) { + strncpy(entity->devname, p, sizeof(entity->devname)); + entity->devname[sizeof(entity->devname) - 1] = '\0'; + } + ret = 0; + } + + udev_device_unref(device); + + return ret; +} + +#else /* HAVE_LIBUDEV */ + +struct udev; + +static inline int media_udev_open(struct udev **udev) { return 0; } + +static inline void media_udev_close(struct udev *udev) { } + +static inline int media_get_devname_udev(struct udev *udev, + struct media_entity *entity) +{ + return -ENOTSUP; +} + +#endif /* HAVE_LIBUDEV */ + +static int media_get_devname_sysfs(struct media_entity *entity) +{ + //struct stat devstat; + char devname[32]; + char sysname[32]; + char target[1024]; + char *p; + int ret; + + sprintf(sysname, "/sys/dev/char/%u:%u", entity->info.v4l.major, + entity->info.v4l.minor); + + ret = readlink(sysname, target, sizeof(target)); + if (ret < 0) + return -errno; + + target[ret] = '\0'; + p = strrchr(target, '/'); + if (p == NULL) + return -EINVAL; + + sprintf(devname, "/tmp/%s", p + 1); + + ret = mknod(devname, 0666 | S_IFCHR, MKDEV(81, entity->info.v4l.minor)); + strcpy(entity->devname, devname); + + return 0; +} + +int get_media_fd(struct media_device *media) +{ + ssize_t num; + int media_node; + char *ptr; + char media_buf[6]; + + LOGV("%s(%s)", __func__, MEDIA_DEV); + + media->fd = open(MEDIA_DEV, O_RDWR, 0); + if( media->fd < 0) { + LOGE("Open sysfs media device failed, media->fd : 0x%p", media->fd); + return -1; + } + LOGV("media->fd : %p", media->fd); + + return media->fd; + +} + +static int media_enum_entities(struct media_device *media) +{ + struct media_entity *entity; + unsigned int size; + __u32 id; + int ret; + entity = (struct media_entity*)calloc(1, sizeof(struct media_entity)); + for (id = 0, ret = 0; ; id = entity->info.id) { + size = (media->entities_count + 1) * sizeof(*media->entities); + media->entities = (struct media_entity*)realloc(media->entities, size); + + entity = &media->entities[media->entities_count]; + memset(entity, 0, sizeof(*entity)); + entity->fd = -1; + entity->info.id = id | MEDIA_ENT_ID_FLAG_NEXT; + entity->media = media; + + ret = ioctl(media->fd, MEDIA_IOC_ENUM_ENTITIES, &entity->info); + + if (ret < 0) { + ret = errno != EINVAL ? -errno : 0; + break; + } + + /* Number of links (for outbound links) plus number of pads (for + * inbound links) is a good safe initial estimate of the total + * number of links. + */ + entity->max_links = entity->info.pads + entity->info.links; + + entity->pads = (struct media_pad*)malloc(entity->info.pads * sizeof(*entity->pads)); + entity->links = (struct media_link*)malloc(entity->max_links * sizeof(*entity->links)); + if (entity->pads == NULL || entity->links == NULL) { + ret = -ENOMEM; + break; + } + + media->entities_count++; + + /* Find the corresponding device name. */ + if (media_entity_type(entity) != MEDIA_ENT_T_DEVNODE && + media_entity_type(entity) != MEDIA_ENT_T_V4L2_SUBDEV) + continue; + + /* Fall back to get the device name via sysfs */ + media_get_devname_sysfs(entity); + if (ret < 0) + LOGE("media_get_devname failed"); + } + + return ret; +} + +static void media_debug_default(void *ptr, ...) +{ + va_list argptr; + va_start(argptr, ptr); + vprintf((const char*)ptr, argptr); + va_end(argptr); +} + +void media_debug_set_handler(struct media_device *media, + void (*debug_handler)(void *, ...), + void *debug_priv) +{ + if (debug_handler) { + media->debug_handler = debug_handler; + media->debug_priv = debug_priv; + } else { + media->debug_handler = media_debug_default; + media->debug_priv = NULL; + } +} + +struct media_device *media_open_debug( + const char *name, void (*debug_handler)(void *, ...), + void *debug_priv) +{ + struct media_device *media; + int ret; + + media = (struct media_device*)calloc(1, sizeof(struct media_device)); + if (media == NULL) { + LOGE("%s: media : %p", __func__, media); + return NULL; + } + + media_debug_set_handler(media, debug_handler, debug_priv); + + LOGV("Opening media device %s", name); + LOGV("%s: media : %p", __func__, media); + + media->fd = get_media_fd(media); + if (media->fd < 0) { + media_close(media); + LOGE("%s: failed get_media_fd %s", + __func__, name); + return NULL; + } + + LOGV("%s: media->fd : %p", __func__, media->fd); + ret = media_enum_entities(media); + + if (ret < 0) { + LOGE( + "%s: Unable to enumerate entities for device %s (%s)", + __func__, name, strerror(-ret)); + media_close(media); + return NULL; + } + + LOGV("Found %u entities", media->entities_count); + LOGV("Enumerating pads and links"); + + ret = media_enum_links(media); + if (ret < 0) { + LOGE( + "%s: Unable to enumerate pads and linksfor device %s", + __func__, name); + media_close(media); + return NULL; + } + + return media; +} + +struct media_device *media_open(void) +{ + return media_open_debug(NULL, (void (*)(void *, ...))fprintf, stdout); +} + +void media_close(struct media_device *media) +{ + unsigned int i; + + if (media->fd != -1) + close(media->fd); + + for (i = 0; i < media->entities_count; ++i) { + struct media_entity *entity = &media->entities[i]; + + free(entity->pads); + free(entity->links); + if (entity->fd != -1) + close(entity->fd); + } + + free(media->entities); + free(media); +} + +struct media_pad *media_parse_pad(struct media_device *media, + const char *p, char **endp) +{ + unsigned int entity_id, pad; + struct media_entity *entity; + char *end; + + for (; isspace(*p); ++p); + + if (*p == '"') { + for (end = (char *)p + 1; *end && *end != '"'; ++end); + if (*end != '"') + return NULL; + + entity = media_get_entity_by_name(media, p + 1, end - p - 1); + if (entity == NULL) + return NULL; + + ++end; + } else { + entity_id = strtoul(p, &end, 10); + entity = media_get_entity_by_id(media, entity_id); + if (entity == NULL) + return NULL; + } + for (; isspace(*end); ++end); + + if (*end != ':') + return NULL; + for (p = end + 1; isspace(*p); ++p); + + pad = strtoul(p, &end, 10); + for (p = end; isspace(*p); ++p); + + if (pad >= entity->info.pads) + return NULL; + + for (p = end; isspace(*p); ++p); + if (endp) + *endp = (char *)p; + + return &entity->pads[pad]; +} + +struct media_link *media_parse_link(struct media_device *media, + const char *p, char **endp) +{ + struct media_link *link; + struct media_pad *source; + struct media_pad *sink; + unsigned int i; + char *end; + + source = media_parse_pad(media, p, &end); + if (source == NULL) + return NULL; + + if (end[0] != '-' || end[1] != '>') + return NULL; + p = end + 2; + + sink = media_parse_pad(media, p, &end); + if (sink == NULL) + return NULL; + + *endp = end; + + for (i = 0; i < source->entity->num_links; i++) { + link = &source->entity->links[i]; + + if (link->source == source && link->sink == sink) + return link; + } + + return NULL; +} + +int media_parse_setup_link(struct media_device *media, + const char *p, char **endp) +{ + struct media_link *link; + __u32 flags; + char *end; + + link = media_parse_link(media, p, &end); + if (link == NULL) { + LOGE( + "%s: Unable to parse link", __func__); + return -EINVAL; + } + + p = end; + if (*p++ != '[') { + LOGE("Unable to parse link flags"); + return -EINVAL; + } + + flags = strtoul(p, &end, 10); + for (p = end; isspace(*p); p++); + if (*p++ != ']') { + LOGE("Unable to parse link flags"); + return -EINVAL; + } + + for (; isspace(*p); p++); + *endp = (char *)p; + + LOGV( + "Setting up link %u:%u -> %u:%u [%u]", + link->source->entity->info.id, link->source->index, + link->sink->entity->info.id, link->sink->index, + flags); + + return media_setup_link(media, link->source, link->sink, flags); +} + +int media_parse_setup_links(struct media_device *media, const char *p) +{ + char *end; + int ret; + + do { + ret = media_parse_setup_link(media, p, &end); + if (ret < 0) + return ret; + + p = end + 1; + } while (*end == ','); + + return *end ? -EINVAL : 0; +} diff --git a/exynos5/hal/libcamera/mediactl.h b/exynos5/hal/libcamera/mediactl.h new file mode 100644 index 0000000..f28ce16 --- /dev/null +++ b/exynos5/hal/libcamera/mediactl.h @@ -0,0 +1,270 @@ +/* + * Media controller interface library + * + * Copyright (C) 2010-2011 Ideas on board SPRL + * + * Contact: Laurent Pinchart + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +#ifndef __MEDIA_H__ +#define __MEDIA_H__ + +#include + +#define GAIA_FW_BETA 1 + +#ifndef GAIA_FW_BETA +#define MEDIA_DEV "/dev/media1" //M5MO : External ISP +#else +#define MEDIA_DEV "/dev/media2" //4E5 : Internal ISP +#endif + +#define MEDIA_MINOR 0 + +#define KF_MSG 0x1 +#define KF_ANY 0x2 + +struct media_link { + struct media_pad *source; + struct media_pad *sink; + struct media_link *twin; + __u32 flags; + __u32 padding[3]; +}; + +struct media_pad { + struct media_entity *entity; + __u32 index; + __u32 flags; + __u32 padding[3]; +}; + +struct media_entity { + struct media_device *media; + struct media_entity_desc info; + struct media_pad *pads; + struct media_link *links; + unsigned int max_links; + unsigned int num_links; + + char devname[32]; + int fd; + __u32 padding[6]; +}; + +struct media_device { + int fd; + struct media_entity *entities; + unsigned int entities_count; + void (*debug_handler)(void *, ...); + void *debug_priv; + __u32 padding[6]; +}; + +#define media_dbg(media, ...) \ + (media)->debug_handler((media)->debug_priv, __VA_ARGS__) + +/** + * @brief Set a handler for debug messages. + * @param media - device instance. + * @param debug_handler - debug message handler + * @param debug_priv - first argument to debug message handler + * + * Set a handler for debug messages that will be called whenever + * debugging information is to be printed. The handler expects an + * fprintf-like function. + */ +void media_debug_set_handler( + struct media_device *media, void (*debug_handler)(void *, ...), + void *debug_priv); + +/** + * @brief Open a media device with debugging enabled. + * @param name - name (including path) of the device node. + * @param debug_handler - debug message handler + * @param debug_priv - first argument to debug message handler + * + * Open the media device referenced by @a name and enumerate entities, pads and + * links. + * + * Calling media_open_debug() instead of media_open() is equivalent to + * media_open() and media_debug_set_handler() except that debugging is + * also enabled during media_open(). + * + * @return A pointer to a newly allocated media_device structure instance on + * success and NULL on failure. The returned pointer must be freed with + * media_close when the device isn't needed anymore. + */ +struct media_device *media_open_debug( + const char *name, void (*debug_handler)(void *, ...), + void *debug_priv); + +/** + * @brief Open a media device. + * @param name - name (including path) of the device node. + * + * Open the media device referenced by @a name and enumerate entities, pads and + * links. + * + * @return A pointer to a newly allocated media_device structure instance on + * success and NULL on failure. The returned pointer must be freed with + * media_close when the device isn't needed anymore. + */ +struct media_device *media_open(void); + +/** + * @brief Close a media device. + * @param media - device instance. + * + * Close the @a media device instance and free allocated resources. Access to the + * device instance is forbidden after this function returns. + */ +void media_close(struct media_device *media); + +/** + * @brief Locate the pad at the other end of a link. + * @param pad - sink pad at one end of the link. + * + * Locate the source pad connected to @a pad through an enabled link. As only one + * link connected to a sink pad can be enabled at a time, the connected source + * pad is guaranteed to be unique. + * + * @return A pointer to the connected source pad, or NULL if all links connected + * to @a pad are disabled. Return NULL also if @a pad is not a sink pad. + */ +struct media_pad *media_entity_remote_source(struct media_pad *pad); + +/** + * @brief Get the type of an entity. + * @param entity - the entity. + * + * @return The type of @a entity. + */ +static inline unsigned int media_entity_type(struct media_entity *entity) +{ + return entity->info.type & MEDIA_ENT_TYPE_MASK; +} + +/** + * @brief Find an entity by its name. + * @param media - media device. + * @param name - entity name. + * @param length - size of @a name. + * + * Search for an entity with a name equal to @a name. + * + * @return A pointer to the entity if found, or NULL otherwise. + */ +struct media_entity *media_get_entity_by_name(struct media_device *media, + const char *name, size_t length); + +/** + * @brief Find an entity by its ID. + * @param media - media device. + * @param id - entity ID. + * + * Search for an entity with an ID equal to @a id. + * + * @return A pointer to the entity if found, or NULL otherwise. + */ +struct media_entity *media_get_entity_by_id(struct media_device *media, + __u32 id); + +/** + * @brief Configure a link. + * @param media - media device. + * @param source - source pad at the link origin. + * @param sink - sink pad at the link target. + * @param flags - configuration flags. + * + * Locate the link between @a source and @a sink, and configure it by applying + * the new @a flags. + * + * Only the MEDIA_LINK_FLAG_ENABLED flag is writable. + * + * @return 0 on success, -1 on failure: + * -ENOENT: link not found + * - other error codes returned by MEDIA_IOC_SETUP_LINK + */ +int media_setup_link(struct media_device *media, + struct media_pad *source, struct media_pad *sink, + __u32 flags); + +/** + * @brief Reset all links to the disabled state. + * @param media - media device. + * + * Disable all links in the media device. This function is usually used after + * opening a media device to reset all links to a known state. + * + * @return 0 on success, or a negative error code on failure. + */ +int media_reset_links(struct media_device *media); + +/** + * @brief Parse string to a pad on the media device. + * @param media - media device. + * @param p - input string + * @param endp - pointer to string where parsing ended + * + * Parse NULL terminated string describing a pad and return its struct + * media_pad instance. + * + * @return Pointer to struct media_pad on success, NULL on failure. + */ +struct media_pad *media_parse_pad(struct media_device *media, + const char *p, char **endp); + +/** + * @brief Parse string to a link on the media device. + * @param media - media device. + * @param p - input string + * @param endp - pointer to p where parsing ended + * + * Parse NULL terminated string p describing a link and return its struct + * media_link instance. + * + * @return Pointer to struct media_link on success, NULL on failure. + */ +struct media_link *media_parse_link(struct media_device *media, + const char *p, char **endp); + +/** + * @brief Parse string to a link on the media device and set it up. + * @param media - media device. + * @param p - input string + * + * Parse NULL terminated string p describing a link and its configuration + * and configure the link. + * + * @return 0 on success, or a negative error code on failure. + */ +int media_parse_setup_link(struct media_device *media, + const char *p, char **endp); + +/** + * @brief Parse string to link(s) on the media device and set it up. + * @param media - media device. + * @param p - input string + * + * Parse NULL terminated string p describing link(s) separated by + * commas (,) and configure the link(s). + * + * @return 0 on success, or a negative error code on failure. + */ +int media_parse_setup_links(struct media_device *media, const char *p); + +#endif diff --git a/exynos5/hal/libcamera/v4l2subdev.h b/exynos5/hal/libcamera/v4l2subdev.h new file mode 100644 index 0000000..20e0557 --- /dev/null +++ b/exynos5/hal/libcamera/v4l2subdev.h @@ -0,0 +1,200 @@ +/* + * V4L2 subdev interface library + * + * Copyright (C) 2010-2011 Ideas on board SPRL + * + * Contact: Laurent Pinchart + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +#ifndef __SUBDEV_H__ +#define __SUBDEV_H__ + +#include + +struct media_entity; + +/** + * @brief Open a sub-device. + * @param entity - sub-device media entity. + * + * Open the V4L2 subdev device node associated with @a entity. The file + * descriptor is stored in the media_entity structure. + * + * @return 0 on success, or a negative error code on failure. + */ +int v4l2_subdev_open(struct media_entity *entity); + +/** + * @brief Close a sub-device. + * @param entity - sub-device media entity. + * + * Close the V4L2 subdev device node associated with the @a entity and opened by + * a previous call to v4l2_subdev_open() (either explicit or implicit). + */ +void v4l2_subdev_close(struct media_entity *entity); + +/** + * @brief Retrieve the format on a pad. + * @param entity - subdev-device media entity. + * @param format - format to be filled. + * @param pad - pad number. + * @param which - identifier of the format to get. + * + * Retrieve the current format on the @a entity @a pad and store it in the + * @a format structure. + * + * @a which is set to V4L2_SUBDEV_FORMAT_TRY to retrieve the try format stored + * in the file handle, of V4L2_SUBDEV_FORMAT_ACTIVE to retrieve the current + * active format. + * + * @return 0 on success, or a negative error code on failure. + */ +int v4l2_subdev_get_format(struct media_entity *entity, + struct v4l2_mbus_framefmt *format, unsigned int pad, + enum v4l2_subdev_format_whence which); + +/** + * @brief Set the format on a pad. + * @param entity - subdev-device media entity. + * @param format - format. + * @param pad - pad number. + * @param which - identifier of the format to set. + * + * Set the format on the @a entity @a pad to @a format. The driver is allowed to + * modify the requested format, in which case @a format is updated with the + * modifications. + * + * @a which is set to V4L2_SUBDEV_FORMAT_TRY to set the try format stored in the + * file handle, of V4L2_SUBDEV_FORMAT_ACTIVE to configure the device with an + * active format. + * + * @return 0 on success, or a negative error code on failure. + */ +int v4l2_subdev_set_format(struct media_entity *entity, + struct v4l2_mbus_framefmt *format, unsigned int pad, + enum v4l2_subdev_format_whence which); + +/** + * @brief Retrieve the crop rectangle on a pad. + * @param entity - subdev-device media entity. + * @param rect - crop rectangle to be filled. + * @param pad - pad number. + * @param which - identifier of the format to get. + * + * Retrieve the current crop rectangleon the @a entity @a pad and store it in + * the @a rect structure. + * + * @a which is set to V4L2_SUBDEV_FORMAT_TRY to retrieve the try crop rectangle + * stored in the file handle, of V4L2_SUBDEV_FORMAT_ACTIVE to retrieve the + * current active crop rectangle. + * + * @return 0 on success, or a negative error code on failure. + */ +int v4l2_subdev_get_crop(struct media_entity *entity, struct v4l2_rect *rect, + unsigned int pad, enum v4l2_subdev_format_whence which); + +/** + * @brief Set the crop rectangle on a pad. + * @param entity - subdev-device media entity. + * @param rect - crop rectangle. + * @param pad - pad number. + * @param which - identifier of the format to set. + * + * Set the crop rectangle on the @a entity @a pad to @a rect. The driver is + * allowed to modify the requested rectangle, in which case @a rect is updated + * with the modifications. + * + * @a which is set to V4L2_SUBDEV_FORMAT_TRY to set the try crop rectangle + * stored in the file handle, of V4L2_SUBDEV_FORMAT_ACTIVE to configure the + * device with an active crop rectangle. + * + * @return 0 on success, or a negative error code on failure. + */ +int v4l2_subdev_set_crop(struct media_entity *entity, struct v4l2_rect *rect, + unsigned int pad, enum v4l2_subdev_format_whence which); + +/** + * @brief Retrieve the frame interval on a sub-device. + * @param entity - subdev-device media entity. + * @param interval - frame interval to be filled. + * + * Retrieve the current frame interval on subdev @a entity and store it in the + * @a interval structure. + * + * Frame interval retrieving is usually supported only on devices at the + * beginning of video pipelines, such as sensors. + * + * @return 0 on success, or a negative error code on failure. + */ + +int v4l2_subdev_get_frame_interval(struct media_entity *entity, + struct v4l2_fract *interval); + +/** + * @brief Set the frame interval on a sub-device. + * @param entity - subdev-device media entity. + * @param interval - frame interval. + * + * Set the frame interval on subdev @a entity to @a interval. The driver is + * allowed to modify the requested frame interval, in which case @a interval is + * updated with the modifications. + * + * Frame interval setting is usually supported only on devices at the beginning + * of video pipelines, such as sensors. + * + * @return 0 on success, or a negative error code on failure. + */ +int v4l2_subdev_set_frame_interval(struct media_entity *entity, + struct v4l2_fract *interval); + +/** + * @brief Parse a string and apply format, crop and frame interval settings. + * @param media - media device. + * @param p - input string + * @param endp - pointer to string p where parsing ended (return) + * + * Parse string @a p and apply format, crop and frame interval settings to a + * subdev pad specified in @a p. @a endp will be written a pointer where + * parsing of @a p ended. + * + * Format strings are separeted by commas (,). + * + * @return 0 on success, or a negative error code on failure. + */ +int v4l2_subdev_parse_setup_formats(struct media_device *media, const char *p); + +/** + * @brief Convert media bus pixel code to string. + * @param code - input string + * + * Convert media bus pixel code @a code to a human-readable string. + * + * @return A pointer to a string on success, NULL on failure. + */ +const char *v4l2_subdev_pixelcode_to_string(enum v4l2_mbus_pixelcode code); + +/** + * @brief Parse string to media bus pixel code. + * @param string - input string + * @param lenght - length of the string + * + * Parse human readable string @a string to an media bus pixel code. + * + * @return media bus pixelcode on success, -1 on failure. + */ +enum v4l2_mbus_pixelcode v4l2_subdev_string_to_pixelcode(const char *string, + unsigned int length); +#endif diff --git a/exynos5/hal/libfimg4x/Android.mk b/exynos5/hal/libfimg4x/Android.mk new file mode 100644 index 0000000..d5d18e9 --- /dev/null +++ b/exynos5/hal/libfimg4x/Android.mk @@ -0,0 +1,22 @@ +LOCAL_PATH:= $(call my-dir) +include $(CLEAR_VARS) + +ifeq ($(BOARD_USES_FIMGAPI),true) + +#LOCAL_C_INCLUDES += $(LOCAL_PATH)/../../include +LOCAL_C_INCLUDES += external/skia/include/core +LOCAL_MODULE_TAGS := optional + +LOCAL_SRC_FILES:= \ + FimgApi.cpp \ + FimgExynos5.cpp + +LOCAL_SHARED_LIBRARIES:= liblog libutils libbinder + +LOCAL_MODULE:= libfimg + +LOCAL_PRELINK_MODULE := false + +include $(BUILD_SHARED_LIBRARY) + +endif diff --git a/exynos5/hal/libfimg4x/FimgApi.cpp b/exynos5/hal/libfimg4x/FimgApi.cpp new file mode 100644 index 0000000..ff11b8d --- /dev/null +++ b/exynos5/hal/libfimg4x/FimgApi.cpp @@ -0,0 +1,376 @@ +/* +** +** Copyright 2009 Samsung Electronics Co, Ltd. +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +** +** +*/ + +#define LOG_NDEBUG 0 +#define LOG_TAG "SKIA" +#include + +#include "FimgApi.h" + +struct blit_op_table optbl[] = { + { (int)BLIT_OP_SOLID_FILL, "FILL" }, + { (int)BLIT_OP_CLR, "CLR" }, + { (int)BLIT_OP_SRC, "SRC" }, + { (int)BLIT_OP_DST, "DST" }, + { (int)BLIT_OP_SRC_OVER, "SRC_OVER" }, + { (int)BLIT_OP_DST_OVER, "DST_OVER" }, + { (int)BLIT_OP_SRC_IN, "SRC_IN" }, + { (int)BLIT_OP_DST_IN, "DST_IN" }, + { (int)BLIT_OP_SRC_OUT, "SRC_OUT" }, + { (int)BLIT_OP_DST_OUT, "DST_OUT" }, + { (int)BLIT_OP_SRC_ATOP, "SRC_ATOP" }, + { (int)BLIT_OP_DST_ATOP, "DST_ATOP" }, + { (int)BLIT_OP_XOR, "XOR" }, + { (int)BLIT_OP_ADD, "ADD" }, + { (int)BLIT_OP_MULTIPLY, "MULTIPLY" }, + { (int)BLIT_OP_SCREEN, "SCREEN" }, + { (int)BLIT_OP_DARKEN, "DARKEN" }, + { (int)BLIT_OP_LIGHTEN, "LIGHTEN" }, + { (int)BLIT_OP_DISJ_SRC_OVER, "DISJ_SRC_OVER" }, + { (int)BLIT_OP_DISJ_DST_OVER, "DISJ_DST_OVER" }, + { (int)BLIT_OP_DISJ_SRC_IN, "DISJ_SRC_IN" }, + { (int)BLIT_OP_DISJ_DST_IN, "DISJ_DST_IN" }, + { (int)BLIT_OP_DISJ_SRC_OUT, "DISJ_SRC_OUT" }, + { (int)BLIT_OP_DISJ_DST_OUT, "DISJ_DST_OUT" }, + { (int)BLIT_OP_DISJ_SRC_ATOP, "DISJ_SRC_ATOP" }, + { (int)BLIT_OP_DISJ_DST_ATOP, "DISJ_DST_ATOP" }, + { (int)BLIT_OP_DISJ_XOR, "DISJ_XOR" }, + { (int)BLIT_OP_CONJ_SRC_OVER, "CONJ_SRC_OVER" }, + { (int)BLIT_OP_CONJ_DST_OVER, "CONJ_DST_OVER" }, + { (int)BLIT_OP_CONJ_SRC_IN, "CONJ_SRC_IN" }, + { (int)BLIT_OP_CONJ_DST_IN, "CONJ_DST_IN" }, + { (int)BLIT_OP_CONJ_SRC_OUT, "CONJ_SRC_OUT" }, + { (int)BLIT_OP_CONJ_DST_OUT, "CONJ_DST_OUT" }, + { (int)BLIT_OP_CONJ_SRC_ATOP, "CONJ_SRC_ATOP" }, + { (int)BLIT_OP_CONJ_DST_ATOP, "CONJ_DST_ATOP" }, + { (int)BLIT_OP_CONJ_XOR, "CONJ_XOR" }, + { (int)BLIT_OP_USER_COEFF, "USER_COEFF" }, + { (int)BLIT_OP_END, "" }, +}; + +#ifndef REAL_DEBUG + void VOID_FUNC(const char *format, ...) + {} +#endif + +FimgApi::FimgApi() +{ + m_flagCreate = false; +} + +FimgApi::~FimgApi() +{ + if (m_flagCreate == true) + PRINT("%s::this is not Destroyed fail\n", __func__); +} + +bool FimgApi::Create(void) +{ + bool ret = false; + + if (t_Lock() == false) { + PRINT("%s::t_Lock() fail\n", __func__); + goto CREATE_DONE; + } + + if (m_flagCreate == true) { + PRINT("%s::Already Created fail\n", __func__); + goto CREATE_DONE; + } + + if (t_Create() == false) { + PRINT("%s::t_Create() fail\n", __func__); + goto CREATE_DONE; + } + + m_flagCreate = true; + + ret = true; + +CREATE_DONE : + + t_UnLock(); + + return ret; +} + +bool FimgApi::Destroy(void) +{ + bool ret = false; + + if (t_Lock() == false) { + PRINT("%s::t_Lock() fail\n", __func__); + goto DESTROY_DONE; + } + + if (m_flagCreate == false) { + PRINT("%s::Already Destroyed fail\n", __func__); + goto DESTROY_DONE; + } + + if (t_Destroy() == false) { + PRINT("%s::t_Destroy() fail\n", __func__); + goto DESTROY_DONE; + } + + m_flagCreate = false; + + ret = true; + +DESTROY_DONE : + + t_UnLock(); + + return ret; +} + +bool FimgApi::Stretch(struct fimg2d_blit *cmd) +{ + bool ret = false; + + if (t_Lock() == false) { + PRINT("%s::t_Lock() fail\n", __func__); + goto STRETCH_DONE; + } + + if (m_flagCreate == false) { + PRINT("%s::This is not Created fail\n", __func__); + goto STRETCH_DONE; + } + + if (t_Stretch(cmd) == false) { + goto STRETCH_DONE; + } + + ret = true; + +STRETCH_DONE : + + t_UnLock(); + + return ret; +} + +bool FimgApi::Sync(void) +{ + bool ret = false; + + if (m_flagCreate == false) { + PRINT("%s::This is not Created fail\n", __func__); + goto SYNC_DONE; + } + + if (t_Sync() == false) + goto SYNC_DONE; + + ret = true; + +SYNC_DONE : + + return ret; +} + +bool FimgApi::t_Create(void) +{ + PRINT("%s::This is empty virtual function fail\n", __func__); + return false; +} + +bool FimgApi::t_Destroy(void) +{ + PRINT("%s::This is empty virtual function fail\n", __func__); + return false; +} + +bool FimgApi::t_Stretch(struct fimg2d_blit *cmd) +{ + PRINT("%s::This is empty virtual function fail\n", __func__); + return false; +} + +bool FimgApi::t_Sync(void) +{ + PRINT("%s::This is empty virtual function fail\n", __func__); + return false; +} + +bool FimgApi::t_Lock(void) +{ + PRINT("%s::This is empty virtual function fail\n", __func__); + return false; +} + +bool FimgApi::t_UnLock(void) +{ + PRINT("%s::This is empty virtual function fail\n", __func__); + return false; +} + +//---------------------------------------------------------------------------// +// extern function +//---------------------------------------------------------------------------// +extern "C" int stretchFimgApi(struct fimg2d_blit *cmd) +{ + FimgApi * fimgApi = createFimgApi(); + + if (fimgApi == NULL) { + PRINT("%s::createFimgApi() fail\n", __func__); + return -1; + } + + if (fimgApi->Stretch(cmd) == false) { + if (fimgApi != NULL) + destroyFimgApi(fimgApi); + + return -1; + } + + if (fimgApi != NULL) + destroyFimgApi(fimgApi); + + return 0; +} + +extern "C" int SyncFimgApi(void) +{ + FimgApi * fimgApi = createFimgApi(); + if (fimgApi == NULL) { + PRINT("%s::createFimgApi() fail\n", __func__); + return -1; + } + + if (fimgApi->Sync() == false) { + if (fimgApi != NULL) + destroyFimgApi(fimgApi); + + return -1; + } + + if (fimgApi != NULL) + destroyFimgApi(fimgApi); + + return 0; +} + +void printDataBlit(char *title, struct fimg2d_blit *cmd) +{ + LOGI("%s\n", title); + + LOGI(" sequence_no. = %u\n", cmd->seq_no); + LOGI(" blit_op = %d(%s)\n", cmd->op, optbl[cmd->op].str); + LOGI(" fill_color = %X\n", cmd->solid_color); + LOGI(" global_alpha = %u\n", (unsigned int)cmd->g_alpha); + LOGI(" PREMULT = %s\n", cmd->premult == PREMULTIPLIED ? "PREMULTIPLIED" : "NON-PREMULTIPLIED"); + LOGI(" do_dither = %s\n", cmd->dither == true ? "dither" : "no-dither"); + + printDataBlitRotate(cmd->rotate); + + printDataBlitScale(cmd->scaling); + + printDataBlitImage("SRC", cmd->src); + printDataBlitImage("DST", cmd->dst); + printDataBlitImage("MSK", cmd->msk); + + printDataBlitRect("SRC", cmd->src_rect); + printDataBlitRect("DST", cmd->dst_rect); + printDataBlitRect("MSK", cmd->msk_rect); + + printDataBlitClip(cmd->clipping); +} + +void printDataBlitImage(char *title, struct fimg2d_image *image) +{ + if (NULL != image) { + LOGI(" Image_%s\n", title); + LOGI(" addr = %X\n", image->addr.start); + LOGI(" size = %u\n", image->addr.size); + LOGI(" (width, height) = (%d, %d)\n", image->width, image->height); + LOGI(" format = %d\n", image->fmt); + } else + LOGI(" Image_%s : NULL\n", title); +} + +void printDataBlitRect(char *title, struct fimg2d_rect *rect) +{ + if (NULL != rect) { + LOGI(" RECT_%s\n", title); + LOGI(" (x1, y1) = (%d, %d)\n", rect->x1, rect->y1); + LOGI(" (x2, y2) = (%d, %d)\n", rect->x2, rect->y2); + LOGI(" (width, height) = (%d, %d)\n", rect->x2 - rect->x1, rect->y2 - rect->y1); + } else + LOGI(" RECT_%s : NULL\n", title); +} + +void printDataBlitRotate(enum rotation rotate) +{ + LOGI(" ROTATE : %d\n", rotate); +} + +void printDataBlitClip(struct fimg2d_clip *clip) +{ + if (NULL != clip) { + LOGI(" CLIP\n"); + LOGI(" clip %s\n", clip->enable == true ? "enabled" : "disabled"); + LOGI(" (x1, y1) = (%d, %d)\n", clip->x1, clip->y1); + LOGI(" (x2, y2) = (%d, %d)\n", clip->x2, clip->y2); + LOGI(" (width, hight) = (%d, %d)\n", clip->x2 - clip->x1, clip->y2 - clip->y1); + } else + LOGI(" CLIP : NULL\n"); +} + +void printDataBlitScale(struct fimg2d_scale *scaling) +{ + if (NULL != scaling) { + LOGI(" SCALING\n"); + LOGI(" scale_mode : %s\n", scaling->mode == 0 ? + "NO_SCALING" : + (scaling->mode == 1 ? "SCALING_NEAREST" : "SCALING_BILINEAR")); + LOGI(" scaling_factor_unit : %s\n", scaling->factor == 0 ? "PERCENT" : "PIXEL"); + + if (scaling->factor == 0) + LOGI(" scaling_factor : (scale_w, scale_y) = (%d, %d)\n", scaling->scale_w, scaling->scale_h); + else { + LOGI(" src : (src_w, src_h) = (%d, %d)\n", scaling->src_w, scaling->src_h); + LOGI(" dst : (dst_w, dst_h) = (%d, %d)\n", scaling->dst_w, scaling->dst_h); + LOGI(" scaling_factor : (scale_w, scale_y) = (%3.2f, %3.2f)\n", (double)scaling->dst_w / scaling->src_w, (double)scaling->dst_h / scaling->src_h); + } + } else + LOGI(" SCALING : NULL(NO SCALE MODE)\n"); + +} + +void printDataMatrix(int matrixType) +{ + LOGI(" MATRIX\n"); + + if (matrixType & SkMatrix::kIdentity_Mask) + LOGI(" Matrix_type : Identity_Mask\n"); + + if (matrixType & SkMatrix::kTranslate_Mask) + LOGI(" Matrix_type : Translate_Mask(the matrix has translation)\n"); + + if (matrixType & SkMatrix::kScale_Mask) + LOGI(" Matrix_type : Scale_Mask(the matrix has X or Y scale)\n"); + + if (matrixType & SkMatrix::kAffine_Mask) + LOGI(" Matrix_type : Affine_Mask(the matrix skews or rotates)\n"); + + if (matrixType & SkMatrix::kPerspective_Mask) + LOGI(" Matrix_type : Perspective_Mask(the matrix is in perspective)\n"); +} diff --git a/exynos5/hal/libfimg4x/FimgApi.h b/exynos5/hal/libfimg4x/FimgApi.h new file mode 100644 index 0000000..a2c9eac --- /dev/null +++ b/exynos5/hal/libfimg4x/FimgApi.h @@ -0,0 +1,114 @@ +/* +** +** Copyright 2009 Samsung Electronics Co, Ltd. +** Copyright 2008, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +** +** +*/ + +#ifndef FIMG_API_H +#define FIMG_API_H + +#include +#include "SkMatrix.h" +#include "sec_g2d_4x.h" + +#define REAL_DEBUG +#define ANDROID_LOG + +#if defined(REAL_DEBUG) +#ifdef ANDROID_LOG +#define PRINT LOGE +#define PRINTD LOGD +#else +#define PRINT printf +#define PRINTD printf +#endif +#else +void VOID_FUNC(const char *format, ...); + +#define PRINT VOID_FUNC +#define PRINTD VOID_FUNC +#endif + +#ifdef __cplusplus + +struct blit_op_table { + int op; + const char *str; +}; + +extern struct blit_op_table optbl[]; + +class FimgApi +{ +public: +#endif + +#ifdef __cplusplus +private : + bool m_flagCreate; + +protected : + FimgApi(); + FimgApi(const FimgApi& rhs) {} + virtual ~FimgApi(); + +public: + bool Create(void); + bool Destroy(void); + inline bool FlagCreate(void) { return m_flagCreate; } + bool Stretch(struct fimg2d_blit *cmd); + bool Sync(void); + +protected: + virtual bool t_Create(void); + virtual bool t_Destroy(void); + virtual bool t_Stretch(struct fimg2d_blit *cmd); + virtual bool t_Sync(void); + virtual bool t_Lock(void); + virtual bool t_UnLock(void); + +}; +#endif + +#ifdef __cplusplus +extern "C" +#endif +struct FimgApi *createFimgApi(); + +#ifdef __cplusplus +extern "C" +#endif +void destroyFimgApi(FimgApi *ptrFimgApi); + +#ifdef __cplusplus +extern "C" +#endif +int stretchFimgApi(struct fimg2d_blit *cmd); +#ifdef __cplusplus +extern "C" +#endif +int SyncFimgApi(void); + +void printDataBlit(char *title, struct fimg2d_blit *cmd); +void printDataBlitRotate(enum rotation rotate); +void printDataBlitImage(char *title, struct fimg2d_image *image); +void printDataBlitRect(char *title, struct fimg2d_rect *rect); +void printDataBlitClip(struct fimg2d_clip *clip); +void printDataBlitScale(struct fimg2d_scale *scaling); +void printDataMatrix(int matrixType); + +#endif //FIMG_API_H diff --git a/exynos5/hal/libfimg4x/FimgExynos5.cpp b/exynos5/hal/libfimg4x/FimgExynos5.cpp new file mode 100644 index 0000000..87c8527 --- /dev/null +++ b/exynos5/hal/libfimg4x/FimgExynos5.cpp @@ -0,0 +1,301 @@ +/* +** +** Copyright 2009 Samsung Electronics Co, Ltd. +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +** +** +*/ + +#define LOG_NDEBUG 0 +#define LOG_TAG "FimgExynos5" +#include + +#include "FimgExynos5.h" + +namespace android +{ +Mutex FimgV4x::m_instanceLock; +int FimgV4x::m_curFimgV4xIndex = 0; +int FimgV4x::m_numOfInstance = 0; +FimgApi * FimgV4x::m_ptrFimgApiList[NUMBER_FIMG_LIST] = {NULL, }; + +//---------------------------------------------------------------------------// + +FimgV4x::FimgV4x() + : m_g2dFd(0), + m_g2dVirtAddr(NULL), + m_g2dSize(0), + m_g2dSrcVirtAddr(NULL), + m_g2dSrcSize(0), + m_g2dDstVirtAddr(NULL), + m_g2dDstSize(0) +{ + m_lock = new Mutex(Mutex::SHARED, "FimgV4x"); +} + +FimgV4x::~FimgV4x() +{ + delete m_lock; +} + +FimgApi *FimgV4x::CreateInstance() +{ + Mutex::Autolock autolock(m_instanceLock); + + FimgApi *ptrFimg = NULL; + + for(int i = m_curFimgV4xIndex; i < NUMBER_FIMG_LIST; i++) { + if (m_ptrFimgApiList[i] == NULL) + m_ptrFimgApiList[i] = new FimgV4x; + + if (m_ptrFimgApiList[i]->FlagCreate() == false) { + if (m_ptrFimgApiList[i]->Create() == false) { + PRINT("%s::Create(%d) fail\n", __func__, i); + goto CreateInstance_End; + } + else + m_numOfInstance++; + } + + if (i < NUMBER_FIMG_LIST - 1) + m_curFimgV4xIndex = i + 1; + else + m_curFimgV4xIndex = 0; + + ptrFimg = m_ptrFimgApiList[i]; + goto CreateInstance_End; + } + +CreateInstance_End : + + return ptrFimg; +} + +void FimgV4x::DestroyInstance(FimgApi * ptrFimgApi) +{ + Mutex::Autolock autolock(m_instanceLock); + + for(int i = 0; i < NUMBER_FIMG_LIST; i++) { + if (m_ptrFimgApiList[i] != NULL && m_ptrFimgApiList[i] == ptrFimgApi) { + if (m_ptrFimgApiList[i]->FlagCreate() == true && m_ptrFimgApiList[i]->Destroy() == false) { + PRINT("%s::Destroy() fail\n", __func__); + } else { + FimgV4x * tempFimgV4x = (FimgV4x *)m_ptrFimgApiList[i]; + delete tempFimgV4x; + m_ptrFimgApiList[i] = NULL; + + m_numOfInstance--; + } + + break; + } + } +} + +void FimgV4x::DestroyAllInstance(void) +{ + Mutex::Autolock autolock(m_instanceLock); + + for(int i = 0; i < NUMBER_FIMG_LIST; i++) { + if (m_ptrFimgApiList[i] != NULL) { + if (m_ptrFimgApiList[i]->FlagCreate() == true + && m_ptrFimgApiList[i]->Destroy() == false) { + PRINT("%s::Destroy() fail\n", __func__); + } else { + FimgV4x * tempFimgV4x = (FimgV4x *)m_ptrFimgApiList[i]; + delete tempFimgV4x; + m_ptrFimgApiList[i] = NULL; + } + } + } +} + +bool FimgV4x::t_Create(void) +{ + bool ret = true; + + if (m_CreateG2D() == false) { + PRINT("%s::m_CreateG2D() fail \n", __func__); + + if (m_DestroyG2D() == false) + PRINT("%s::m_DestroyG2D() fail \n", __func__); + + ret = false; + } + + return ret; +} + +bool FimgV4x::t_Destroy(void) +{ + bool ret = true; + + if (m_DestroyG2D() == false) { + PRINT("%s::m_DestroyG2D() fail \n", __func__); + ret = false; + } + + return ret; +} + +bool FimgV4x::t_Stretch(struct fimg2d_blit *cmd) +{ +#ifdef CHECK_FIMGV4x_PERFORMANCE +#define NUM_OF_STEP (10) + StopWatch stopWatch("CHECK_FIMGV4x_PERFORMANCE"); + const char *stopWatchName[NUM_OF_STEP]; + nsecs_t stopWatchTime[NUM_OF_STEP]; + int stopWatchIndex = 0; +#endif // CHECK_FIMGV4x_PERFORMANCE + + if (m_DoG2D(cmd) == false) { + goto STRETCH_FAIL; + } + +#ifdef G2D_NONE_BLOCKING_MODE + if (m_PollG2D(&m_g2dPoll) == false) + { + PRINT("%s::m_PollG2D() fail\n", __func__); + goto STRETCH_FAIL; + } +#endif + + #ifdef CHECK_FIMGV4x_PERFORMANCE + m_PrintFimgV4xPerformance(src, dst, stopWatchIndex, stopWatchName, stopWatchTime); + #endif // CHECK_FIMGV4x_PERFORMANCE + + return true; + +STRETCH_FAIL: + return false; + +} + +bool FimgV4x::t_Sync(void) +{ + if (m_PollG2D(&m_g2dPoll) == false) + { + PRINT("%s::m_PollG2D() fail\n", __func__); + goto SYNC_FAIL; + } + return true; + +SYNC_FAIL: + return false; + +} + +bool FimgV4x::t_Lock(void) +{ + m_lock->lock(); + return true; +} + +bool FimgV4x::t_UnLock(void) +{ + m_lock->unlock(); + return true; +} + +bool FimgV4x::m_CreateG2D(void) +{ + void * mmap_base; + + if (m_g2dFd != 0) { + PRINT("%s::m_g2dFd(%d) is not 0 fail\n", __func__, m_g2dFd); + return false; + } + +#ifdef G2D_NONE_BLOCKING_MODE + m_g2dFd = open(SEC_G2D_DEV_NAME, O_RDWR | O_NONBLOCK); +#else + m_g2dFd = open(SEC_G2D_DEV_NAME, O_RDWR); +#endif + if (m_g2dFd < 0) { + PRINT("%s::open(%s) fail(%s)\n", __func__, SEC_G2D_DEV_NAME, strerror(errno)); + m_g2dFd = 0; + return false; + } + + memset(&m_g2dPoll, 0, sizeof(m_g2dPoll)); + m_g2dPoll.fd = m_g2dFd; + m_g2dPoll.events = POLLOUT | POLLERR; + + return true; +} + +bool FimgV4x::m_DestroyG2D(void) +{ + if (m_g2dVirtAddr != NULL) { + munmap(m_g2dVirtAddr, m_g2dSize); + m_g2dVirtAddr = NULL; + m_g2dSize = 0; + } + + if (0 < m_g2dFd) { + close(m_g2dFd); + } + m_g2dFd = 0; + + return true; +} + +bool FimgV4x::m_DoG2D(struct fimg2d_blit *cmd) +{ + + if (ioctl(m_g2dFd, FIMG2D_BITBLT_BLIT, cmd) < 0) + return false; + + return true; +} + +inline bool FimgV4x::m_PollG2D(struct pollfd * events) +{ +#define G2D_POLL_TIME (1000) + + int ret; + + ret = poll(events, 1, G2D_POLL_TIME); + + if (ret < 0) { + PRINT("%s::poll fail \n", __func__); + return false; + } + else if (ret == 0) { + PRINT("%s::No data in %d milli secs..\n", __func__, G2D_POLL_TIME); + return false; + } + + return true; +} + +//---------------------------------------------------------------------------// +// extern function +//---------------------------------------------------------------------------// +extern "C" struct FimgApi * createFimgApi() +{ + if (fimgApiAutoFreeThread == 0) + fimgApiAutoFreeThread = new FimgApiAutoFreeThread(); + else + fimgApiAutoFreeThread->SetOneMoreSleep(); + + return FimgV4x::CreateInstance(); +} + +extern "C" void destroyFimgApi(FimgApi * ptrFimgApi) +{ + // Dont' call DestroyInstance. +} + +}; // namespace android diff --git a/exynos5/hal/libfimg4x/FimgExynos5.h b/exynos5/hal/libfimg4x/FimgExynos5.h new file mode 100644 index 0000000..71295a6 --- /dev/null +++ b/exynos5/hal/libfimg4x/FimgExynos5.h @@ -0,0 +1,169 @@ +/* +** +** Copyright 2008, The Android Open Source Project +** Copyright 2009 Samsung Electronics Co, Ltd. All Rights Reserved. +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +** +** +*/ + +#ifndef FIMG_EXYNOS5_H +#define FIMG_EXYNOS5_H + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "FimgApi.h" + +#include "sec_g2d_4x.h" + +namespace android +{ + +#define NUMBER_FIMG_LIST (1) // kcoolsw : because of pmem +#define GET_RECT_SIZE(rect) ((rect->full_w) * (rect->h) * (rect->bytes_per_pixel)) +#define GET_REAL_SIZE(rect) ((rect->full_w) * (rect->h) * (rect->bytes_per_pixel)) +#define GET_START_ADDR(rect) (rect->virt_addr + ((rect->y * rect->full_w) * rect->bytes_per_pixel)) +#define SLEEP_TIME (3000000) // 3 sec + +//---------------------------------------------------------------------------// +// class FimgV4x : public FimgBase +//---------------------------------------------------------------------------// +class FimgV4x : public FimgApi +{ +private : + int m_g2dFd; + + unsigned char *m_g2dVirtAddr; + unsigned int m_g2dSize; + unsigned char *m_g2dSrcVirtAddr; + unsigned int m_g2dSrcSize; + unsigned char *m_g2dDstVirtAddr; + unsigned int m_g2dDstSize; + struct pollfd m_g2dPoll; + + Mutex *m_lock; + + static Mutex m_instanceLock; + static int m_curFimgV4xIndex; + static int m_numOfInstance; + + static FimgApi *m_ptrFimgApiList[NUMBER_FIMG_LIST]; + +protected : + FimgV4x(); + virtual ~FimgV4x(); + +public: + static FimgApi *CreateInstance(); + static void DestroyInstance(FimgApi *ptrFimgApi); + static void DestroyAllInstance(void); + +protected: + virtual bool t_Create(void); + virtual bool t_Destroy(void); + virtual bool t_Stretch(struct fimg2d_blit *cmd); + virtual bool t_Sync(void); + virtual bool t_Lock(void); + virtual bool t_UnLock(void); + +private: + bool m_CreateG2D(void); + bool m_DestroyG2D(void); + + bool m_DoG2D(struct fimg2d_blit *cmd); + + inline bool m_PollG2D(struct pollfd *events); + + inline int m_ColorFormatFimgApi2FimgHw(int colorFormat); +}; + +class FimgApiAutoFreeThread; + +static sp fimgApiAutoFreeThread = 0; + +class FimgApiAutoFreeThread : public Thread +{ +private: + bool mOneMoreSleep; + bool mDestroyed; + +public: + FimgApiAutoFreeThread(void): + Thread(false), + mOneMoreSleep(true), + mDestroyed(false) + { } + ~FimgApiAutoFreeThread(void) + { + if (mDestroyed == false) + { + FimgV4x::DestroyAllInstance(); + mDestroyed = true; + } + } + + virtual void onFirstRef() + { + run("FimgApiAutoFreeThread", PRIORITY_BACKGROUND); + } + + virtual bool threadLoop() + { + + if (mOneMoreSleep == true) + { + mOneMoreSleep = false; + usleep(SLEEP_TIME); + + return true; + } + else + { + if (mDestroyed == false) + { + FimgV4x::DestroyAllInstance(); + mDestroyed = true; + } + + fimgApiAutoFreeThread = 0; + + return false; + } + } + + void SetOneMoreSleep(void) + { + mOneMoreSleep = true; + } +}; + +}; // namespace android + +#endif // FIMG_EXYNOS5_H diff --git a/exynos5/hal/libfimg4x/sec_g2d_4x.h b/exynos5/hal/libfimg4x/sec_g2d_4x.h new file mode 100644 index 0000000..b9ddbb2 --- /dev/null +++ b/exynos5/hal/libfimg4x/sec_g2d_4x.h @@ -0,0 +1,326 @@ +/* + * Copyright 2011, Samsung Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef __SEC_G2D_4X_H +#define __SEC_G2D_4X_H __FILE__ + +#define SEC_G2D_DEV_NAME "/dev/fimg2d" + +/* ioctl commands */ +#define FIMG2D_IOCTL_MAGIC 'F' +#define FIMG2D_BITBLT_BLIT _IOWR(FIMG2D_IOCTL_MAGIC, 0, struct fimg2d_blit) +#define FIMG2D_BITBLT_SYNC _IO(FIMG2D_IOCTL_MAGIC, 1) +#define FIMG2D_BITBLT_VERSION _IOR(FIMG2D_IOCTL_MAGIC, 2, struct fimg2d_version) + +#define G2D_ALPHA_VALUE_MAX (255) + +enum addr_space { + ADDR_UNKNOWN, + ADDR_PHYS, + ADDR_KERN, + ADDR_USER, + ADDR_DEVICE, +}; + +/** + * DO NOT CHANGE THIS ORDER + */ +enum pixel_order { + AX_RGB = 0, + RGB_AX, + AX_BGR, + BGR_AX, + ARGB_ORDER_END, + + P1_CRY1CBY0, + P1_CBY1CRY0, + P1_Y1CRY0CB, + P1_Y1CBY0CR, + P1_ORDER_END, + + P2_CRCB, + P2_CBCR, + P2_ORDER_END, +}; + +/** + * DO NOT CHANGE THIS ORDER + */ +enum color_format { + CF_XRGB_8888 = 0, + CF_ARGB_8888, + CF_RGB_565, + CF_XRGB_1555, + CF_ARGB_1555, + CF_XRGB_4444, + CF_ARGB_4444, + CF_RGB_888, + CF_YCBCR_444, + CF_YCBCR_422, + CF_YCBCR_420, + CF_A8, + CF_L8, + SRC_DST_FORMAT_END, + + CF_MSK_1BIT, + CF_MSK_4BIT, + CF_MSK_8BIT, + CF_MSK_16BIT_565, + CF_MSK_16BIT_1555, + CF_MSK_16BIT_4444, + CF_MSK_32BIT_8888, + MSK_FORMAT_END, +}; + +enum rotation { + ORIGIN, + ROT_90, /* clockwise */ + ROT_180, + ROT_270, + XFLIP, /* x-axis flip */ + YFLIP, /* y-axis flip */ +}; + +/** + * @NO_REPEAT: no effect + * @REPEAT_NORMAL: repeat horizontally and vertically + * @REPEAT_PAD: pad with pad color + * @REPEAT_REFLECT: reflect horizontally and vertically + * @REPEAT_CLAMP: pad with edge color of original image + * + * DO NOT CHANGE THIS ORDER + */ +enum repeat { + NO_REPEAT = 0, + REPEAT_NORMAL, /* default setting */ + REPEAT_PAD, + REPEAT_REFLECT, REPEAT_MIRROR = REPEAT_REFLECT, + REPEAT_CLAMP, +}; + +enum scaling { + NO_SCALING, + SCALING_NEAREST, + SCALING_BILINEAR, +}; + +/** + * @SCALING_PERCENTAGE: percentage of width, height + * @SCALING_PIXELS: coordinate of src, dest + */ +enum scaling_factor { + SCALING_PERCENTAGE, + SCALING_PIXELS, +}; + +/** + * premultiplied alpha + */ +enum premultiplied { + PREMULTIPLIED, + NON_PREMULTIPLIED, +}; + +/** + * @TRANSP: discard bluescreen color + * @BLUSCR: replace bluescreen color with background color + */ +enum bluescreen { + OPAQUE, + TRANSP, + BLUSCR, +}; + +/** + * DO NOT CHANGE THIS ORDER + */ +enum blit_op { + BLIT_OP_SOLID_FILL = 0, + + BLIT_OP_CLR, + BLIT_OP_SRC, BLIT_OP_SRC_COPY = BLIT_OP_SRC, + BLIT_OP_DST, + BLIT_OP_SRC_OVER, + BLIT_OP_DST_OVER, BLIT_OP_OVER_REV = BLIT_OP_DST_OVER, + BLIT_OP_SRC_IN, + BLIT_OP_DST_IN, BLIT_OP_IN_REV = BLIT_OP_DST_IN, + BLIT_OP_SRC_OUT, + BLIT_OP_DST_OUT, BLIT_OP_OUT_REV = BLIT_OP_DST_OUT, + BLIT_OP_SRC_ATOP, + BLIT_OP_DST_ATOP, BLIT_OP_ATOP_REV = BLIT_OP_DST_ATOP, + BLIT_OP_XOR, + + BLIT_OP_ADD, + BLIT_OP_MULTIPLY, + BLIT_OP_SCREEN, + BLIT_OP_DARKEN, + BLIT_OP_LIGHTEN, + + BLIT_OP_DISJ_SRC_OVER, + BLIT_OP_DISJ_DST_OVER, BLIT_OP_SATURATE = BLIT_OP_DISJ_DST_OVER, + BLIT_OP_DISJ_SRC_IN, + BLIT_OP_DISJ_DST_IN, BLIT_OP_DISJ_IN_REV = BLIT_OP_DISJ_DST_IN, + BLIT_OP_DISJ_SRC_OUT, + BLIT_OP_DISJ_DST_OUT, BLIT_OP_DISJ_OUT_REV = BLIT_OP_DISJ_DST_OUT, + BLIT_OP_DISJ_SRC_ATOP, + BLIT_OP_DISJ_DST_ATOP, BLIT_OP_DISJ_ATOP_REV = BLIT_OP_DISJ_DST_ATOP, + BLIT_OP_DISJ_XOR, + + BLIT_OP_CONJ_SRC_OVER, + BLIT_OP_CONJ_DST_OVER, BLIT_OP_CONJ_OVER_REV = BLIT_OP_CONJ_DST_OVER, + BLIT_OP_CONJ_SRC_IN, + BLIT_OP_CONJ_DST_IN, BLIT_OP_CONJ_IN_REV = BLIT_OP_CONJ_DST_IN, + BLIT_OP_CONJ_SRC_OUT, + BLIT_OP_CONJ_DST_OUT, BLIT_OP_CONJ_OUT_REV = BLIT_OP_CONJ_DST_OUT, + BLIT_OP_CONJ_SRC_ATOP, + BLIT_OP_CONJ_DST_ATOP, BLIT_OP_CONJ_ATOP_REV = BLIT_OP_CONJ_DST_ATOP, + BLIT_OP_CONJ_XOR, + + /* Add new operation type here */ + + /* user select coefficient manually */ + BLIT_OP_USER_COEFF, + + /* end of blit operation */ + BLIT_OP_END, + + /* driver not supporting format */ + BLIT_OP_NOT_SUPPORTED +}; + +#define MAX_FIMG2D_BLIT_OP (int)BLIT_OP_END + +struct fimg2d_version { + unsigned int hw; + unsigned int sw; +}; + +/** + * @start: start address or unique id of image + * @size: whole length of allocated image + * @cacheable: memory is cacheable + * @pinnable: memory is pinnable. currently not supported. + */ +struct fimg2d_addr { + enum addr_space type; + unsigned long start; + size_t size; + int cacheable; + int pinnable; +}; + +struct fimg2d_rect { + int x1; + int y1; + int x2; /* x1 + width */ + int y2; /* y1 + height */ +}; + +/** + * if factor is percentage, scale_w and scale_h are valid + * if factor is pixels, src_w, src_h, dst_w, dst_h are valid + */ +struct fimg2d_scale { + enum scaling mode; + enum scaling_factor factor; + + /* percentage */ + int scale_w; + int scale_h; + + /* pixels */ + int src_w, src_h; + int dst_w, dst_h; +}; + +/** + * coordinate from start address(0,0) of image + */ +struct fimg2d_clip { + bool enable; + int x1; + int y1; + int x2; /* x1 + width */ + int y2; /* y1 + height */ +}; + +struct fimg2d_repeat { + enum repeat mode; + unsigned long pad_color; +}; + +/** + * @bg_color: bg_color is valid only if bluescreen mode is BLUSCR. + */ +struct fimg2d_bluscr { + enum bluescreen mode; + unsigned long bs_color; + unsigned long bg_color; +}; + +/** + * @plane2: address info for CbCr in YCbCr 2plane mode + */ +struct fimg2d_image { + struct fimg2d_addr addr; + struct fimg2d_addr plane2; + int width; + int height; + int stride; + enum pixel_order order; + enum color_format fmt; +}; + +struct fimg2d_param { + enum blit_op op; + unsigned long fillcolor; + unsigned char g_alpha; + enum premultiplied premult; + bool dither; + enum rotation rotate; + struct fimg2d_scale *scaling; + struct fimg2d_repeat *repeat; + struct fimg2d_bluscr *bluscr; + struct fimg2d_clip *clipping; +}; + +/** + * @g_alpha: 0xff is opaque, 0x0 is transparnet + * @seq_no: used for debugging + */ +struct fimg2d_blit { + enum blit_op op; + + enum premultiplied premult; + unsigned char g_alpha; + bool dither; + enum rotation rotate; + struct fimg2d_scale *scaling; + struct fimg2d_repeat *repeat; + struct fimg2d_bluscr *bluscr; + struct fimg2d_clip *clipping; + + unsigned long solid_color; + struct fimg2d_image *src; + struct fimg2d_image *dst; + struct fimg2d_image *msk; + + struct fimg2d_rect *src_rect; + struct fimg2d_rect *dst_rect; + struct fimg2d_rect *msk_rect; + + unsigned int seq_no; +}; +#endif /* __SEC_G2D_4X_H__ */ diff --git a/exynos5/hal/libgralloc_ump/Android.mk b/exynos5/hal/libgralloc_ump/Android.mk new file mode 100644 index 0000000..a4354d4 --- /dev/null +++ b/exynos5/hal/libgralloc_ump/Android.mk @@ -0,0 +1,59 @@ +# +# Copyright (C) 2010 ARM Limited. All rights reserved. +# +# Copyright (C) 2008 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +LOCAL_PATH := $(call my-dir) + +# HAL module implemenation, not prelinked and stored in +# hw/..so +include $(CLEAR_VARS) +LOCAL_PRELINK_MODULE := false +LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw +LOCAL_SHARED_LIBRARIES := liblog libcutils libGLESv1_CM libGLES_mali libion +LOCAL_MODULE_TAGS := eng optional + +# Include the UMP header files +LOCAL_C_INCLUDES := $(LOCAL_PATH)/../include + +LOCAL_SRC_FILES := \ + gralloc_module.cpp \ + alloc_device.cpp \ + framebuffer_device.cpp + +# For now we override arch and ABI values to allow us to work with a +# libmali that has been forced to armv7, eventually we can let android +# pick for us + +ifeq ($(TARGET_PRODUCT), armboard_v7a) +# Support for ARM platforms +LOCAL_CFLAGS:= -DLOG_TAG=\"gralloc\" -DGRALLOC_16_BITS -DSTANDARD_LINUX_SCREEN \ + -march=armv7-a \ + -mfloat-abi=softfp +LOCAL_MODULE := gralloc.default + +else +#Default to goldfish +LOCAL_CFLAGS:= -DLOG_TAG=\"gralloc\" -DSTANDARD_LINUX_SCREEN \ + -march=armv7-a \ + -mfloat-abi=softfp \ + -DVITHAR_HACK + +LOCAL_MODULE := gralloc.smdk5250 +endif + + +include $(BUILD_SHARED_LIBRARY) diff --git a/exynos5/hal/libgralloc_ump/alloc_device.cpp b/exynos5/hal/libgralloc_ump/alloc_device.cpp new file mode 100644 index 0000000..64be027 --- /dev/null +++ b/exynos5/hal/libgralloc_ump/alloc_device.cpp @@ -0,0 +1,380 @@ +/* + * Copyright (C) 2010-2011 ARM Limited. All rights reserved. + * + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +#include +#include +#include +#include + +#include "alloc_device.h" +#include "gralloc_priv.h" +#include "gralloc_helper.h" +#include "framebuffer_device.h" + +#include "ump.h" + +#include "sec_format.h" + +#include + +#ifdef ION_ALLOC +#include "ion.h" +#endif + +#include +#include + +/* Treat GPU as UMP Device Z */ +#define GRALLOC_DEVICE_SHIFT UMP_DEVICE_Z_SHIFT + +#define EXYNOS_ALIGN( value, base ) (((value) + ((base) - 1)) & ~((base) - 1)) +static int gralloc_alloc_buffer(alloc_device_t* dev, size_t size, int usage, + buffer_handle_t* pHandle, int w, int h, + int format, int bpp, int stride_raw, int stride) +{ + ion_buffer ion_fd = 0; + ump_handle ump_mem_handle; + void *cpu_ptr = NULL; + ump_secure_id ump_id=UMP_INVALID_SECURE_ID; + ump_alloc_flags ump_flags = UMP_PROT_SHAREABLE | UMP_HINT_CPU_RD | UMP_HINT_CPU_WR; + int sw_read_usage; + int sw_write_usage; + int hw_usage; + size = round_up_to_page_size(size); + + unsigned int ion_flags = 0; + int priv_alloc_flag = private_handle_t::PRIV_FLAGS_USES_UMP; + + if (usage & GRALLOC_USAGE_HW_ION) { + private_module_t* m = reinterpret_cast(dev->common.module); + ion_fd = ion_alloc(m->ion_client, size, 0, ION_HEAP_EXYNOS_MASK); + if (ion_fd < 0) { + LOGE("Failed to ion_alloc"); + return -1; + } + + cpu_ptr = ion_map(ion_fd, size, 0); + if (NULL == cpu_ptr) { + LOGE("Failed to ion_map"); + ion_free(ion_fd); + return -1; + } + /* TODO: GPU does not use ION. */ + ump_mem_handle = ump_import(UMP_EXTERNAL_MEM_TYPE_ION, &ion_fd, ump_flags); + if (UMP_INVALID_MEMORY_HANDLE != ump_mem_handle) { + priv_alloc_flag = private_handle_t::PRIV_FLAGS_USES_ION; + } else { + LOGE("gralloc_alloc_buffer() failed to import ION memory"); + ion_unmap(cpu_ptr, size); + ion_free(ion_fd); + return -1; + } + } else { + usage |= GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_HW_RENDER; + sw_read_usage = usage & GRALLOC_USAGE_SW_READ_MASK; + sw_write_usage = usage & GRALLOC_USAGE_SW_WRITE_MASK; + hw_usage = usage & GRALLOC_USAGE_HW_MASK; + + if (sw_read_usage) { + ump_flags |= UMP_PROT_CPU_RD; + if (sw_read_usage == GRALLOC_USAGE_SW_READ_OFTEN) + ump_flags |= UMP_HINT_CPU_RD; + } + if (sw_write_usage) { + ump_flags |= UMP_PROT_CPU_WR; + if (sw_write_usage == GRALLOC_USAGE_SW_WRITE_OFTEN) + ump_flags |= UMP_HINT_CPU_WR; + } + + if (hw_usage) { + int hw_flags = 0; + if (hw_usage & (GRALLOC_USAGE_HW_TEXTURE)) + hw_flags |= (UMP_PROT_DEVICE_RD | UMP_HINT_DEVICE_RD); + + if (hw_usage & (GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_FB)) + hw_flags |= (UMP_PROT_DEVICE_RD | UMP_HINT_DEVICE_RD | UMP_PROT_DEVICE_WR | UMP_HINT_DEVICE_WR); + + ump_flags |= (hw_flags << GRALLOC_DEVICE_SHIFT); + } + + ump_mem_handle = ump_allocate_64(size, ump_flags); + if (UMP_INVALID_MEMORY_HANDLE != ump_mem_handle) + cpu_ptr = ump_map(ump_mem_handle, 0, size); + else + LOGE("gralloc_alloc_buffer() failed to allcoate UMP memory"); + } + + if (NULL != cpu_ptr) { + ump_id = ump_secure_id_get(ump_mem_handle); + + if (UMP_INVALID_SECURE_ID != ump_id || usage & GRALLOC_USAGE_HW_ION) { + private_handle_t* hnd = new private_handle_t(priv_alloc_flag, size, (int)cpu_ptr, + private_handle_t::LOCK_STATE_MAPPED, + ump_id, + ump_mem_handle); + if (NULL != hnd) { + *pHandle = hnd; + hnd->fd = ion_fd; + hnd->format = format; + hnd->usage = usage; + hnd->width = w; + hnd->height = h; + hnd->bpp = bpp; + hnd->stride = stride; + hnd->uoffset = ((EXYNOS_ALIGN(hnd->width, 16) * EXYNOS_ALIGN(hnd->height, 16))); + hnd->voffset = ((EXYNOS_ALIGN((hnd->width >> 1), 8) * EXYNOS_ALIGN((hnd->height >> 1), 8))); + return 0; + } else { + LOGE("gralloc_alloc_buffer() failed to allocate handle"); + } + } else { + LOGE("gralloc_alloc_buffer() failed to retrieve valid secure id"); + } + + ump_unmap(ump_mem_handle, cpu_ptr, size); + } else { + LOGE("gralloc_alloc_buffer() failed to map UMP memory"); + } + + ump_release(ump_mem_handle); + + return -1; +} + +static int gralloc_alloc_framebuffer_locked(alloc_device_t* dev, size_t size, int usage, + buffer_handle_t* pHandle, int w, int h, + int format, int bpp) +{ + private_module_t* m = reinterpret_cast(dev->common.module); + + /* allocate the framebuffer */ + if (m->framebuffer == NULL) { + /* initialize the framebuffer, the framebuffer is mapped once and forever. */ + int err = init_frame_buffer_locked(m); + + if (err < 0) + return err; + } + + const uint32_t bufferMask = m->bufferMask; + const uint32_t numBuffers = m->numBuffers; + const size_t bufferSize = m->finfo.line_length * m->info.yres; + + if (numBuffers == 1) { + /* + * If we have only one buffer, we never use page-flipping. Instead, + * we return a regular buffer which will be memcpy'ed to the main + * screen when post is called. + */ + int newUsage = (usage & ~GRALLOC_USAGE_HW_FB) | GRALLOC_USAGE_HW_2D; + + LOGD("fallback to single buffering"); + + return gralloc_alloc_buffer(dev, bufferSize, newUsage, pHandle, w, h, format, bpp, 0, 0); + } + + if (bufferMask >= ((1LU<framebuffer->base; + /* find a free slot */ + for (uint32_t i = 0; i < numBuffers; i++) { + if ((bufferMask & (1LU<bufferMask |= (1LU<framebuffer->fd), vaddr - m->framebuffer->base); + hnd->format = format; + hnd->usage = usage; + hnd->width = w; + hnd->height = h; + hnd->bpp = bpp; + *pHandle = hnd; + + return 0; +} + +static int gralloc_alloc_framebuffer(alloc_device_t* dev, size_t size, int usage, + buffer_handle_t* pHandle, int w, int h, + int format, int bpp) +{ + private_module_t* m = reinterpret_cast(dev->common.module); + pthread_mutex_lock(&m->lock); + int err = gralloc_alloc_framebuffer_locked(dev, size, usage, pHandle, w, h, format, bpp); + pthread_mutex_unlock(&m->lock); + + return err; +} + +static int alloc_device_alloc(alloc_device_t* dev, int w, int h, int format, + int usage, buffer_handle_t* pHandle, int* pStride) +{ + if (!pHandle || !pStride) { + LOGE("Invalid Handle, Stride value"); + return -EINVAL; + } + + int err; + int align = 16; + int bpp = 0; + size_t stride_raw = 0; + size_t size = 0; + size_t stride = (w + 15) & ~15; + size_t vstride = (h + 15) & ~15; + + switch (format) { + case HAL_PIXEL_FORMAT_RGBA_8888: + case HAL_PIXEL_FORMAT_RGBX_8888: + case HAL_PIXEL_FORMAT_BGRA_8888: + bpp = 4; + break; + case HAL_PIXEL_FORMAT_RGB_888: + bpp = 3; + break; + case HAL_PIXEL_FORMAT_RGB_565: + case HAL_PIXEL_FORMAT_RGBA_5551: + case HAL_PIXEL_FORMAT_RGBA_4444: + bpp = 2; + break; + case HAL_PIXEL_FORMAT_YCbCr_420_P: + case HAL_PIXEL_FORMAT_YCbCr_420_SP: + case HAL_PIXEL_FORMAT_YV12: + size = stride * vstride * 2; + bpp = 4; + break; + default: + LOGE("Not Support Pixel Format"); + return -EINVAL; + } + + if (format != HAL_PIXEL_FORMAT_YCbCr_420_P && + format != HAL_PIXEL_FORMAT_YCbCr_420_SP && + format != HAL_PIXEL_FORMAT_YV12) { + size_t bpr = (w * bpp + (align-1)) & ~(align-1); + size = bpr * h; + stride = bpr / bpp; + stride_raw = bpr; + } + + if (usage & GRALLOC_USAGE_HW_FB) + err = gralloc_alloc_framebuffer(dev, size, usage, pHandle, w, h, format, 32); + else + err = gralloc_alloc_buffer(dev, size, usage, pHandle, w, h, + format, 0, (int)stride_raw, (int)stride); + + if (err < 0) { + LOGE("Fail to alloc Gralloc memory"); + return err; + } + + *pStride = stride; + return 0; +} + +static int alloc_device_free(alloc_device_t* dev, buffer_handle_t handle) +{ + if (private_handle_t::validate(handle) < 0) { + LOGE("Invalid Value : private_handle"); + return -EINVAL; + } + + private_handle_t const* hnd = reinterpret_cast(handle); + if (hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER) { + /* free this buffer */ + private_module_t* m = reinterpret_cast(dev->common.module); + const size_t bufferSize = m->finfo.line_length * m->info.yres; + int index = (hnd->base - m->framebuffer->base) / bufferSize; + m->bufferMask &= ~(1<fd); + } else if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_UMP) { + ump_unmap(hnd->ump_mem_handle, (void*)hnd->base, hnd->size); + ump_release(hnd->ump_mem_handle); + } else if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_ION) { + ump_mapped_pointer_release((ump_handle)hnd->ump_mem_handle); + ump_reference_release((ump_handle)hnd->ump_mem_handle); + + ion_unmap((void*)hnd->base, hnd->size); + ion_free(hnd->fd); + } + + delete hnd; + + return 0; +} + +static int alloc_device_close(struct hw_device_t *device) +{ + alloc_device_t* dev = reinterpret_cast(device); + if (dev) { + private_module_t* m = reinterpret_cast(dev->common.module); + ion_client_destroy(m->ion_client); + delete dev; + ump_close(); /* Our UMP memory refs will be released automatically here... */ + } + return 0; +} + +int alloc_device_open(hw_module_t const* module, const char* name, hw_device_t** device) +{ + alloc_device_t *dev; + + dev = new alloc_device_t; + if (NULL == dev) { + LOGE("Fail to create alloc_device"); + return -1; + } + + dev->common.module = const_cast(module); + private_module_t* m = reinterpret_cast(dev->common.module); + m->ion_client=ion_client_create(); + LOGI("gralloc create ion_client %d", m->ion_client); + + ump_result ump_res = ump_open(); + + if ((UMP_OK != ump_res) || (0 > m->ion_client)) { + LOGE("UMP open failed, ump_res %d, ion_client %d", ump_res, m->ion_client); + delete dev; + return -1; + } + + /* initialize our state here */ + memset(dev, 0, sizeof(*dev)); + + /* initialize the procs */ + dev->common.tag = HARDWARE_DEVICE_TAG; + dev->common.version = 0; + dev->common.module = const_cast(module); + dev->common.close = alloc_device_close; + dev->alloc = alloc_device_alloc; + dev->free = alloc_device_free; + + *device = &dev->common; + + return 0; +} diff --git a/exynos5/hal/libgralloc_ump/alloc_device.h b/exynos5/hal/libgralloc_ump/alloc_device.h new file mode 100644 index 0000000..9877d4d --- /dev/null +++ b/exynos5/hal/libgralloc_ump/alloc_device.h @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2010-2011 ARM Limited. All rights reserved. + * + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +// Create an alloc device +int alloc_device_open(hw_module_t const* module, const char* name, hw_device_t** device); diff --git a/exynos5/hal/libgralloc_ump/framebuffer_device.cpp b/exynos5/hal/libgralloc_ump/framebuffer_device.cpp new file mode 100644 index 0000000..0015e54 --- /dev/null +++ b/exynos5/hal/libgralloc_ump/framebuffer_device.cpp @@ -0,0 +1,394 @@ +/* + * Copyright (C) 2010-2011 ARM Limited. All rights reserved. + * + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include "gralloc_priv.h" +#include "gralloc_helper.h" + +#include "linux/fb.h" + +/* numbers of buffers for page flipping */ +#define NUM_BUFFERS 2 + +enum { + PAGE_FLIP = 0x00000001, +}; + +static int fb_set_swap_interval(struct framebuffer_device_t* dev, int interval) +{ + if (interval < dev->minSwapInterval || interval > dev->maxSwapInterval) + return -EINVAL; + + /* TODO: Currently not implemented */ + return 0; +} + +static int fb_post(struct framebuffer_device_t* dev, buffer_handle_t buffer) +{ + if (private_handle_t::validate(buffer) < 0) + return -EINVAL; + + private_handle_t const* hnd = reinterpret_cast(buffer); + private_module_t* m = reinterpret_cast(dev->common.module); + + if (m->currentBuffer) { + m->base.unlock(&m->base, m->currentBuffer); + m->currentBuffer = 0; + } + + if (hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER) { + m->base.lock(&m->base, buffer, private_module_t::PRIV_USAGE_LOCKED_FOR_POST, + 0, 0, m->info.xres, m->info.yres, NULL); + + const size_t offset = hnd->base - m->framebuffer->base; + m->info.activate = FB_ACTIVATE_VBL; + m->info.yoffset = offset / m->finfo.line_length; + +#ifdef STANDARD_LINUX_SCREEN + if (ioctl(m->framebuffer->fd, FBIOPAN_DISPLAY, &m->info) == -1) { + LOGE("FBIOPAN_DISPLAY failed"); + m->base.unlock(&m->base, buffer); + return 0; + } + + /* wait for VSYNC */ + int crtc = 0; + if (ioctl(m->framebuffer->fd, FBIO_WAITFORVSYNC, &crtc) < 0) { + LOGE("FBIO_WAITFORVSYNC failed"); + return 0; + } +#else + /* Standard Android way */ + if (ioctl(m->framebuffer->fd, FBIOPUT_VSCREENINFO, &m->info) == -1) { + LOGE("FBIOPUT_VSCREENINFO failed"); + m->base.unlock(&m->base, buffer); + return -errno; + } +#endif + + m->currentBuffer = buffer; + } else { + void* fb_vaddr; + void* buffer_vaddr; + + m->base.lock(&m->base, m->framebuffer, GRALLOC_USAGE_SW_WRITE_RARELY, + 0, 0, m->info.xres, m->info.yres, &fb_vaddr); + + m->base.lock(&m->base, buffer, GRALLOC_USAGE_SW_READ_RARELY, + 0, 0, m->info.xres, m->info.yres, &buffer_vaddr); + + memcpy(fb_vaddr, buffer_vaddr, m->finfo.line_length * m->info.yres); + + m->base.unlock(&m->base, buffer); + m->base.unlock(&m->base, m->framebuffer); + } + + return 0; +} + +int init_frame_buffer_locked(struct private_module_t* module) +{ + if (module->framebuffer) + return 0; /* Nothing to do, already initialized */ + + char const * const device_template[] = { + "/dev/graphics/fb%u", + "/dev/fb%u", + NULL + }; + + int fd = -1; + int i = 0; + char name[64]; + + while ((fd == -1) && device_template[i]) { + snprintf(name, 64, device_template[i], 0); + fd = open(name, O_RDWR, 0); + i++; + } + + if (fd < 0) { + LOGE("/dev/graphics/fb, /dev/fb Open fail"); + return -errno; + } + + struct fb_fix_screeninfo finfo; + if (ioctl(fd, FBIOGET_FSCREENINFO, &finfo) == -1) { + LOGE("Fail to get FB Screen Info"); + return -errno; + } + + struct fb_var_screeninfo info; + if (ioctl(fd, FBIOGET_VSCREENINFO, &info) == -1) { + LOGE("First, Fail to get FB VScreen Info"); + return -errno; + } + + info.reserved[0] = 0; + info.reserved[1] = 0; + info.reserved[2] = 0; + info.xoffset = 0; + info.yoffset = 0; + info.activate = FB_ACTIVATE_NOW; + +#ifdef GRALLOC_16_BITS + /* + * Explicitly request 5/6/5 + */ + info.bits_per_pixel = 16; + info.red.offset = 11; + info.red.length = 5; + info.green.offset = 5; + info.green.length = 6; + info.blue.offset = 0; + info.blue.length = 5; + info.transp.offset = 0; + info.transp.length = 0; +#else + /* + * Explicitly request 8/8/8 + */ + info.bits_per_pixel = 32; + info.red.offset = 16; + info.red.length = 8; + info.green.offset = 8; + info.green.length = 8; + info.blue.offset = 0; + info.blue.length = 8; + info.transp.offset = 0; + info.transp.length = 0; +#endif + + /* + * Request NUM_BUFFERS screens (at lest 2 for page flipping) + */ + info.yres_virtual = info.yres * NUM_BUFFERS; + + uint32_t flags = PAGE_FLIP; + if (ioctl(fd, FBIOPUT_VSCREENINFO, &info) == -1) { + info.yres_virtual = info.yres; + flags &= ~PAGE_FLIP; + LOGW("FBIOPUT_VSCREENINFO failed, page flipping not supported"); + } + + if (info.yres_virtual < info.yres * 2) { + /* we need at least 2 for page-flipping */ + info.yres_virtual = info.yres; + flags &= ~PAGE_FLIP; + LOGW("page flipping not supported (yres_virtual=%d, requested=%d)", + info.yres_virtual, info.yres*2); + } + + if (ioctl(fd, FBIOGET_VSCREENINFO, &info) == -1) { + LOGE("Second, Fail to get FB VScreen Info"); + return -errno; + } + + int refreshRate = 1000000000000000LLU / + ( + uint64_t( info.upper_margin + info.lower_margin + info.yres ) + * ( info.left_margin + info.right_margin + info.xres ) + * info.pixclock + ); + + if (refreshRate == 0) + refreshRate = 60*1000; /* 60 Hz */ + + if (int(info.width) <= 0 || int(info.height) <= 0) { + /* the driver doesn't return that information default to 160 dpi */ + info.width = ((info.xres * 25.4f) / 160.0f + 0.5f); + info.height = ((info.yres * 25.4f) / 160.0f + 0.5f); + } + + float xdpi = (info.xres * 25.4f) / info.width; + float ydpi = (info.yres * 25.4f) / info.height; + float fps = refreshRate / 1000.0f; + + LOGI("using (fd=%d)\n" + "id = %s\n" + "xres = %d px\n" + "yres = %d px\n" + "xres_virtual = %d px\n" + "yres_virtual = %d px\n" + "bpp = %d\n" + "r = %2u:%u\n" + "g = %2u:%u\n" + "b = %2u:%u\n", + fd, + finfo.id, + info.xres, + info.yres, + info.xres_virtual, + info.yres_virtual, + info.bits_per_pixel, + info.red.offset, info.red.length, + info.green.offset, info.green.length, + info.blue.offset, info.blue.length); + + LOGI("width = %d mm (%f dpi)\n" + "height = %d mm (%f dpi)\n" + "refresh rate = %.2f Hz\n", + info.width, xdpi, + info.height, ydpi, + fps); + + if (ioctl(fd, FBIOGET_FSCREENINFO, &finfo) == -1) { + LOGE("Fail to get FScreen Info"); + return -errno; + } + + if (finfo.smem_len <= 0) { + LOGE("Invalid Value : finfo.smem_len"); + return -errno; + } + + module->flags = flags; + module->info = info; + module->finfo = finfo; + module->xdpi = xdpi; + module->ydpi = ydpi; + module->fps = fps; + + /* + * map the framebuffer + */ + size_t fbSize = round_up_to_page_size(finfo.line_length * info.yres_virtual); + void* vaddr = mmap(0, fbSize, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); + if (vaddr == MAP_FAILED) { + LOGE("Error mapping the framebuffer (%s)", strerror(errno)); + return -errno; + } + + memset(vaddr, 0, fbSize); + + /* Create a "fake" buffer object for the entire frame buffer memory, + * and store it in the module */ + module->framebuffer = new private_handle_t(private_handle_t::PRIV_FLAGS_FRAMEBUFFER, + fbSize, intptr_t(vaddr), + 0, dup(fd), 0); + + module->numBuffers = info.yres_virtual / info.yres; + module->bufferMask = 0; + + return 0; +} + +static int init_frame_buffer(struct private_module_t* module) +{ + pthread_mutex_lock(&module->lock); + int err = init_frame_buffer_locked(module); + pthread_mutex_unlock(&module->lock); + return err; +} + +static int fb_close(struct hw_device_t *device) +{ + framebuffer_device_t* dev = reinterpret_cast(device); + if (dev) { + ump_close(); + delete dev; + } + return 0; +} + +int compositionComplete(struct framebuffer_device_t* dev) +{ + /* By doing a Finish here we force the GL driver to start rendering + all the drawcalls up to this point, and to wait for the rendering to be complete.*/ + + /* It move to HWComposit Module */ + + /* The rendering of the backbuffer is now completed. + When SurfaceFlinger later does a call to eglSwapBuffer(), the swap will be done + synchronously in the same thread, and not asynchronoulsy in a background thread later. + The SurfaceFlinger requires this behaviour since it releases the lock on all the + SourceBuffers (Layers) after the compositionComplete() function returns. + However this "bad" behaviour by SurfaceFlinger should not affect performance, + since the Applications that render the SourceBuffers (Layers) still get the + full renderpipeline using asynchronouls rendering. So they perform at maximum speed, + and because of their complexity compared to the Surface flinger jobs, the Surface flinger + is normally faster even if it does everyhing synchronous and serial. + */ + return 0; +} + +int framebuffer_device_open(hw_module_t const* module, const char* name, hw_device_t** device) +{ + int status = -EINVAL; + + alloc_device_t* gralloc_device; + status = gralloc_open(module, &gralloc_device); + if (status < 0) { + LOGE("Fail to Open gralloc device"); + return status; + } + + private_module_t* m = (private_module_t*)module; + status = init_frame_buffer(m); + if (status < 0) { + LOGE("Fail to init framebuffer"); + gralloc_close(gralloc_device); + return status; + } + + /* initialize our state here */ + framebuffer_device_t *dev = new framebuffer_device_t; + memset(dev, 0, sizeof(*dev)); + + /* initialize the procs */ + dev->common.tag = HARDWARE_DEVICE_TAG; + dev->common.version = 0; + dev->common.module = const_cast(module); + dev->common.close = fb_close; + dev->setSwapInterval = fb_set_swap_interval; + dev->post = fb_post; + dev->setUpdateRect = 0; + dev->compositionComplete = &compositionComplete; + + int stride = m->finfo.line_length / (m->info.bits_per_pixel >> 3); + const_cast(dev->flags) = 0; + const_cast(dev->width) = m->info.xres; + const_cast(dev->height) = m->info.yres; + const_cast(dev->stride) = stride; +#ifdef GRALLOC_16_BITS + const_cast(dev->format) = HAL_PIXEL_FORMAT_RGB_565; +#else + const_cast(dev->format) = HAL_PIXEL_FORMAT_BGRA_8888; +#endif + const_cast(dev->xdpi) = m->xdpi; + const_cast(dev->ydpi) = m->ydpi; + const_cast(dev->fps) = m->fps; + const_cast(dev->minSwapInterval) = 1; + const_cast(dev->maxSwapInterval) = 1; + *device = &dev->common; + status = 0; + + return status; +} diff --git a/exynos5/hal/libgralloc_ump/framebuffer_device.h b/exynos5/hal/libgralloc_ump/framebuffer_device.h new file mode 100644 index 0000000..4d84bef --- /dev/null +++ b/exynos5/hal/libgralloc_ump/framebuffer_device.h @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2010-2011 ARM Limited. All rights reserved. + * + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +// Create a framebuffer device +int framebuffer_device_open(hw_module_t const* module, const char* name, hw_device_t** device); + +// Initialize the framebuffer (must keep module lock before calling +int init_frame_buffer_locked(struct private_module_t* module); diff --git a/exynos5/hal/libgralloc_ump/gralloc_helper.h b/exynos5/hal/libgralloc_ump/gralloc_helper.h new file mode 100644 index 0000000..6a0a518 --- /dev/null +++ b/exynos5/hal/libgralloc_ump/gralloc_helper.h @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2010-2011 ARM Limited. All rights reserved. + * + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef GRALLOC_HELPER_H_ +#define GRALLOC_HELPER_H_ + +#include + +inline size_t round_up_to_page_size(size_t x) +{ + return (x + (PAGE_SIZE-1)) & ~(PAGE_SIZE-1); +} + +#endif /* GRALLOC_HELPER_H_ */ diff --git a/exynos5/hal/libgralloc_ump/gralloc_module.cpp b/exynos5/hal/libgralloc_ump/gralloc_module.cpp new file mode 100644 index 0000000..8ca500b --- /dev/null +++ b/exynos5/hal/libgralloc_ump/gralloc_module.cpp @@ -0,0 +1,289 @@ +/* + * Copyright (C) 2010-2011 ARM Limited. All rights reserved. + * + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#include +#include +#include +#include +#include "ump.h" + +#include "gralloc_priv.h" +#include "alloc_device.h" +#include "framebuffer_device.h" +#include "ion.h" +#include + +static pthread_mutex_t s_map_lock = PTHREAD_MUTEX_INITIALIZER; +static int s_ump_is_open = 0; + +static int gralloc_map(gralloc_module_t const* module, + buffer_handle_t handle, void** vaddr) +{ + private_handle_t* hnd = (private_handle_t*)handle; + private_module_t* m = (private_module_t*)module; + + if (!(hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER)) { + if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_ION) { + size_t size = hnd->size; + hnd->ion_client = ion_client_create(); + void *mappedAddress = ion_map(hnd->fd, size, 0); + + if (mappedAddress == MAP_FAILED) { + LOGE("Could not ion_map %s fd(%d)", strerror(errno), hnd->fd); + return -errno; + } + + hnd->base = intptr_t(mappedAddress) + hnd->offset; + LOGD("gralloc_map() succeeded fd=%d, off=%d, size=%d, vaddr=%p", + hnd->fd, hnd->offset, hnd->size, mappedAddress); + } else { + LOGE("In case of ION, It could not reach here!"); + } + } + *vaddr = (void*)hnd->base; + return 0; +} + +static int gralloc_unmap(gralloc_module_t const* module, + buffer_handle_t handle) +{ + private_handle_t* hnd = (private_handle_t*)handle; + private_module_t* m = (private_module_t*)module; + + if (!(hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER)) { + if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_ION) { + void* base = (void*)hnd->base; + size_t size = hnd->size; + LOGD("unmapping from %p, size=%d", base, size); + + if (ion_unmap(base, size) < 0) + LOGE("Could not ion_unmap %s", strerror(errno)); + + ion_client_destroy(hnd->ion_client); + } + } + hnd->base = 0; + return 0; +} + +static int gralloc_device_open(const hw_module_t* module, const char* name, hw_device_t** device) +{ + int status = -EINVAL; + + LOGI("Opening ARM Gralloc device"); + + if (!strcmp(name, GRALLOC_HARDWARE_GPU0)) + status = alloc_device_open(module, name, device); + else if (!strcmp(name, GRALLOC_HARDWARE_FB0)) + status = framebuffer_device_open(module, name, device); + + return status; +} + +static int gralloc_register_buffer(gralloc_module_t const* module, buffer_handle_t handle) +{ + int retval = -EINVAL; + void *vaddr; + if (private_handle_t::validate(handle) < 0) { + LOGE("Registering invalid buffer, returning error"); + return -EINVAL; + } + + // if this handle was created in this process, then we keep it as is. + private_handle_t* hnd = (private_handle_t*)handle; + if (hnd->pid == getpid()) { + LOGE("Invalid Process ID from Private_Handle"); + return 0; + } + + pthread_mutex_lock(&s_map_lock); + if (!s_ump_is_open) { + ump_result res = ump_open(); + if (res != UMP_OK) { + pthread_mutex_unlock(&s_map_lock); + LOGE("Failed to open UMP library"); + return retval; + } + s_ump_is_open = 1; + } + + if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_UMP) { + hnd->ump_mem_handle = ump_from_secure_id(hnd->ump_id); + if (UMP_INVALID_MEMORY_HANDLE != hnd->ump_mem_handle) { + hnd->base = (int)ump_map(hnd->ump_mem_handle, 0, hnd->size); + if (0 != hnd->base) { + hnd->lockState = private_handle_t::LOCK_STATE_MAPPED; + hnd->writeOwner = 0; + hnd->lockState = 0; + + pthread_mutex_unlock(&s_map_lock); + return 0; + } else { + LOGE("Failed to map UMP handle"); + } + + ump_release(hnd->ump_mem_handle); + } else { + LOGE("Failed to create UMP handle"); + } + } else if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_ION) { + hnd->ump_mem_handle = ump_handle_create_from_secure_id(hnd->ump_id); + retval = gralloc_map(module, handle, &vaddr); + } else { + LOGE("registering non-UMP&ION buffer not supported"); + } + + pthread_mutex_unlock(&s_map_lock); + + return retval; +} + +static int gralloc_unregister_buffer(gralloc_module_t const* module, buffer_handle_t handle) +{ + if (private_handle_t::validate(handle) < 0) { + LOGE("unregistering invalid buffer, returning error"); + return -EINVAL; + } + + private_handle_t* hnd = (private_handle_t*)handle; + + LOGE_IF(hnd->lockState & private_handle_t::LOCK_STATE_READ_MASK, + "[unregister] handle %p still locked (state=%08x)", hnd, hnd->lockState); + + /* never unmap buffers that were created in this process */ + if (hnd->pid != getpid()) { + pthread_mutex_lock(&s_map_lock); + + if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_UMP) { + ump_unmap(hnd->ump_mem_handle, (void*)hnd->base, hnd->size); + hnd->base = 0; + ump_release(hnd->ump_mem_handle); + hnd->ump_mem_handle = UMP_INVALID_MEMORY_HANDLE; + } else if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_ION) { + + ump_mapped_pointer_release((ump_handle)hnd->ump_mem_handle); + ump_reference_release((ump_handle)hnd->ump_mem_handle); + if (hnd->base) + gralloc_unmap(module, handle); + + hnd->base = 0; + hnd->ump_mem_handle = (int)UMP_INVALID_MEMORY_HANDLE; + hnd->lockState = 0; + hnd->writeOwner = 0; + } else { + LOGE("unregistering non-UMP buffer not supported"); + } + + hnd->base = 0; + hnd->lockState = 0; + hnd->writeOwner = 0; + + pthread_mutex_unlock(&s_map_lock); + } + + return 0; +} + +static int gralloc_lock(gralloc_module_t const* module, buffer_handle_t handle, + int usage, int l, int t, int w, int h, void** vaddr) +{ + if (private_handle_t::validate(handle) < 0) { + LOGE("Locking invalid buffer, returning error"); + return -EINVAL; + } + + private_handle_t* hnd = (private_handle_t*)handle; + if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_UMP) { + hnd->writeOwner = usage & GRALLOC_USAGE_SW_WRITE_MASK; + + if (usage & GRALLOC_USAGE_SW_READ_MASK) + ump_cpu_msync_now(hnd->ump_mem_handle, UMP_MSYNC_CLEAN_AND_INVALIDATE, + (void*)hnd->base, hnd->size); + } + + if (usage & (GRALLOC_USAGE_SW_READ_MASK | GRALLOC_USAGE_SW_WRITE_MASK)) + *vaddr = (void*)hnd->base; + + if (usage & GRALLOC_USAGE_YUV_ADDR) { + vaddr[0] = (void*)hnd->base; + vaddr[1] = (void*)(hnd->base + hnd->uoffset); + vaddr[2] = (void*)(hnd->base + hnd->uoffset + hnd->voffset); + } + return 0; +} + +static int gralloc_unlock(gralloc_module_t const* module, buffer_handle_t handle) +{ + if (private_handle_t::validate(handle) < 0) { + LOGE("Unlocking invalid buffer, returning error"); + return -EINVAL; + } + + private_handle_t* hnd = (private_handle_t*)handle; + private_module_t* m = (private_module_t*)module; + int32_t current_value; + int32_t new_value; + int retry; + + if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_UMP && hnd->writeOwner) + ump_cpu_msync_now(hnd->ump_mem_handle, UMP_MSYNC_CLEAN_AND_INVALIDATE, (void*)hnd->base, hnd->size); + else if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_ION) + ion_msync(hnd->ion_client, hnd->fd, IMSYNC_DEV_TO_READ | IMSYNC_SYNC_FOR_DEV, hnd->size, hnd->offset); + + return 0; +} + +static struct hw_module_methods_t gralloc_module_methods = +{ + open: gralloc_device_open +}; + +struct private_module_t HAL_MODULE_INFO_SYM = +{ + base: + { + common: + { + tag: HARDWARE_MODULE_TAG, + version_major: 1, + version_minor: 0, + id: GRALLOC_HARDWARE_MODULE_ID, + name: "Graphics Memory Allocator Module", + author: "ARM Ltd.", + methods: &gralloc_module_methods, + dso: NULL, + reserved : {0,}, + }, + registerBuffer: gralloc_register_buffer, + unregisterBuffer: gralloc_unregister_buffer, + lock: gralloc_lock, + unlock: gralloc_unlock, + perform: NULL, + reserved_proc: {0,}, + }, + framebuffer: NULL, + flags: 0, + numBuffers: 0, + bufferMask: 0, + lock: PTHREAD_MUTEX_INITIALIZER, + currentBuffer: NULL, + ion_client: -1, +}; diff --git a/exynos5/hal/libhdmi/Android.mk b/exynos5/hal/libhdmi/Android.mk new file mode 100644 index 0000000..9acbc52 --- /dev/null +++ b/exynos5/hal/libhdmi/Android.mk @@ -0,0 +1,17 @@ +# Copyright (C) 2008 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +ifeq ($(filter-out exynos5,$(TARGET_BOARD_PLATFORM)),) +include $(all-subdir-makefiles) +endif diff --git a/exynos5/hal/libhdmi/SecHdmi/Android.mk b/exynos5/hal/libhdmi/SecHdmi/Android.mk new file mode 100644 index 0000000..61bd1a9 --- /dev/null +++ b/exynos5/hal/libhdmi/SecHdmi/Android.mk @@ -0,0 +1,76 @@ +# Copyright (C) 2008 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +ifeq ($(BOARD_USES_HDMI),true) + +LOCAL_PATH:= $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_MODULE_TAGS := eng + +LOCAL_PRELINK_MODULE := false +#LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw +LOCAL_SHARED_LIBRARIES := libutils liblog libedid libcec + +LOCAL_SRC_FILES := \ + SecHdmiV4L2Utils.cpp \ + SecHdmi.cpp \ + SecGscaler.cpp \ + fimd_api.c + +LOCAL_C_INCLUDES += $(LOCAL_PATH) +LOCAL_C_INCLUDES += $(LOCAL_PATH)/../../include + +ifeq ($(TARGET_SOC),exynos5250) + LOCAL_CFLAGS += -DSAMSUNG_EXYNOS5250 +endif + +LOCAL_CFLAGS += \ + -DSCREEN_WIDTH=$(SCREEN_WIDTH) \ + -DSCREEN_HEIGHT=$(SCREEN_HEIGHT) \ + -DDEFAULT_FB_NUM=$(DEFAULT_FB_NUM) + +LOCAL_SHARED_LIBRARIES += libion + +ifeq ($(BOARD_USES_HDMI_SUBTITLES),true) + LOCAL_CFLAGS += -DBOARD_USES_HDMI_SUBTITLES +endif + +ifeq ($(BOARD_USES_HDMI_FIMGAPI),true) + LOCAL_CFLAGS += -DBOARD_USES_HDMI_FIMGAPI + LOCAL_C_INCLUDES += device/samsung/$(TARGET_BOARD_PLATFORM)/libfimg4x + LOCAL_C_INCLUDES += external/skia/include/core + LOCAL_SHARED_LIBRARIES += libfimg +endif + +ifeq ($(BOARD_HDMI_STD), STD_NTSC_M) + LOCAL_CFLAGS += -DSTD_NTSC_M +endif + +ifeq ($(BOARD_HDMI_STD),STD_480P) + LOCAL_CFLAGS += -DSTD_480P +endif + +ifeq ($(BOARD_HDMI_STD),STD_720P) + LOCAL_CFLAGS += -DSTD_720P +endif + +ifeq ($(BOARD_HDMI_STD),STD_1080P) + LOCAL_CFLAGS += -DSTD_1080P +endif + +LOCAL_MODULE := libhdmi +include $(BUILD_SHARED_LIBRARY) + +endif diff --git a/exynos5/hal/libhdmi/SecHdmi/SecGscaler.cpp b/exynos5/hal/libhdmi/SecHdmi/SecGscaler.cpp new file mode 100644 index 0000000..0a84d11 --- /dev/null +++ b/exynos5/hal/libhdmi/SecHdmi/SecGscaler.cpp @@ -0,0 +1,1524 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * Copyright@ Samsung Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +//#define DEBUG_LIB_FIMC +#define LOG_TAG "libgscaler" +//#define USE_GSC_USERPTR +#include +#include "../libhdmi/SecHdmi/SecGscaler.h" + +#ifdef USE_GSC_USERPTR +#define V4L2_MEMORY_TYPE V4L2_MEMORY_USERPTR +#else +#define V4L2_MEMORY_TYPE V4L2_MEMORY_MMAP +#endif + +struct yuv_fmt_list yuv_list[] = { + { "V4L2_PIX_FMT_NV12", "YUV420/2P/LSB_CBCR", V4L2_PIX_FMT_NV12, 12, 1 }, + { "V4L2_PIX_FMT_NV12M", "YUV420/2P/LSB_CBCR", V4L2_PIX_FMT_NV12M, 12, 2 }, + { "V4L2_PIX_FMT_NV12MT", "YUV420/2P/LSB_CBCR", V4L2_PIX_FMT_NV12MT, 12, 2 }, + { "V4L2_PIX_FMT_NV21", "YUV420/2P/LSB_CRCB", V4L2_PIX_FMT_NV21, 12, 1 }, + { "V4L2_PIX_FMT_NV21X", "YUV420/2P/MSB_CBCR", V4L2_PIX_FMT_NV21X, 12, 2 }, + { "V4L2_PIX_FMT_NV12X", "YUV420/2P/MSB_CRCB", V4L2_PIX_FMT_NV12X, 12, 2 }, + { "V4L2_PIX_FMT_YUV420", "YUV420/3P", V4L2_PIX_FMT_YUV420, 12, 3 }, + { "V4L2_PIX_FMT_YUV420M", "YUV420/3P", V4L2_PIX_FMT_YUV420M, 12, 3 }, + { "V4L2_PIX_FMT_YUYV", "YUV422/1P/YCBYCR", V4L2_PIX_FMT_YUYV, 16, 1 }, + { "V4L2_PIX_FMT_YVYU", "YUV422/1P/YCRYCB", V4L2_PIX_FMT_YVYU, 16, 1 }, + { "V4L2_PIX_FMT_UYVY", "YUV422/1P/CBYCRY", V4L2_PIX_FMT_UYVY, 16, 1 }, + { "V4L2_PIX_FMT_VYUY", "YUV422/1P/CRYCBY", V4L2_PIX_FMT_VYUY, 16, 1 }, + { "V4L2_PIX_FMT_UV12", "YUV422/2P/LSB_CBCR", V4L2_PIX_FMT_NV16, 16, 2 }, + { "V4L2_PIX_FMT_UV21", "YUV422/2P/LSB_CRCB", V4L2_PIX_FMT_NV61, 16, 2 }, + { "V4L2_PIX_FMT_UV12X", "YUV422/2P/MSB_CBCR", V4L2_PIX_FMT_NV16X, 16, 2 }, + { "V4L2_PIX_FMT_UV21X", "YUV422/2P/MSB_CRCB", V4L2_PIX_FMT_NV61X, 16, 2 }, + { "V4L2_PIX_FMT_YUV422P", "YUV422/3P", V4L2_PIX_FMT_YUV422P, 16, 3 }, +}; + +void dump_pixfmt_mp(struct v4l2_pix_format_mplane *pix_mp) +{ + LOGI("w: %d", pix_mp->width); + LOGI("h: %d", pix_mp->height); + LOGI("color: %x", pix_mp->colorspace); + + switch (pix_mp->pixelformat) { + case V4L2_PIX_FMT_YUYV: + LOGI ("YUYV"); + break; + case V4L2_PIX_FMT_UYVY: + LOGI ("UYVY"); + break; + case V4L2_PIX_FMT_RGB565: + LOGI ("RGB565"); + break; + case V4L2_PIX_FMT_RGB565X: + LOGI ("RGB565X"); + break; + default: + LOGI("not supported"); + } +} + +void dump_crop(struct v4l2_rect *rect) +{ + LOGI("crop l: %d", rect->left); + LOGI("crop t: %d", rect->top); + LOGI("crop w: %d", rect->width); + LOGI("crop h: %d", rect->height); +} + +void gsc_v4l2_dump_state(int fd) +{ + struct v4l2_format format; + struct v4l2_crop crop; + struct v4l2_subdev_crop sCrop; + + format.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; + if (ioctl(fd, VIDIOC_G_FMT, &format) < 0) + return; + + LOGI("dumping driver state:"); + dump_pixfmt_mp(&format.fmt.pix_mp); + + crop.type = format.type; + if (ioctl(fd, VIDIOC_G_CROP, &crop) < 0) + return; + + LOGI("input image crop:"); + dump_crop(&(crop.c)); + + sCrop.pad = GSC_SUBDEV_PAD_SOURCE; + sCrop.which = V4L2_SUBDEV_FORMAT_ACTIVE; + if (ioctl(fd, VIDIOC_SUBDEV_G_CROP, &sCrop) < 0) + return; + + LOGI("output image crop:"); + dump_crop(&(sCrop.rect)); + +} + +int gsc_v4l2_querycap(int fd, char *node) +{ +#ifdef DEBUG_LIB_FIMC + LOGD("%s", __func__); +#endif + struct v4l2_capability v4l2cap; + + if (ioctl(fd, VIDIOC_QUERYCAP, &v4l2cap) < 0) { + LOGE("%s::VIDIOC_QUERYCAP failed", __func__); + return -1; + } + + if (!(v4l2cap.capabilities & V4L2_CAP_STREAMING)) { + LOGE("%s::%s is not support streaming", __func__, node); + return -1; + } + + if (!(v4l2cap.capabilities & V4L2_CAP_VIDEO_OUTPUT_MPLANE)) { + LOGE("%s::%s is not support video output mplane", __func__, node); + return -1; + } + + return 0; +} + +int gsc_v4l2_query_buf(int fd, SecBuffer *secBuf, enum v4l2_buf_type type, enum v4l2_memory memory, unsigned int buf_index, int num_plane) +{ +#ifdef DEBUG_LIB_FIMC + LOGD("%s", __func__); +#endif + struct v4l2_buffer buf; + struct v4l2_plane planes[MAX_PLANES_GSCALER]; + + memset(&buf, 0, sizeof(struct v4l2_buffer)); + + for (int i = 0; i < MAX_PLANES_GSCALER; i++) + memset(&planes[i], 0, sizeof(struct v4l2_plane)); + + if (MAX_BUFFERS_GSCALER <= buf_index || MAX_PLANES_GSCALER < num_plane) { + LOGE("%s::exceed MAX! : buf_index=%d, num_plane=%d", __func__, buf_index, num_plane); + return -1; + } + + buf.type = type; + buf.memory = V4L2_MEMORY_MMAP; + buf.index = buf_index; + buf.length = num_plane; + buf.m.planes = planes; + + if (ioctl(fd, VIDIOC_QUERYBUF, &buf) < 0) { + LOGE("%s::VIDIOC_QUERYBUF failed, plane_cnt=%d", __func__, buf.length); + return -1; + } + + for (int i = 0; i < num_plane; i++) { + if ((secBuf->virt.extP[i] = (char *)mmap(0, buf.m.planes[i].length, + PROT_READ | PROT_WRITE, MAP_SHARED, fd, buf.m.planes[i].m.mem_offset)) < 0) { + LOGE("%s::mmap failed", __func__); + LOGE("%s::Offset = 0x%x", __func__, buf.m.planes[i].m.mem_offset); + LOGE("%s::Legnth = %d" , __func__, buf.m.planes[i].length); + LOGE("%s::vaddr[%d][%d] = 0x%x", __func__, buf_index, i, (unsigned int)secBuf->virt.extP[i]); + return -1; + } + secBuf->size.extS[i] = buf.m.planes[i].length; + +#ifdef DEBUG_LIB_FIMC + LOGD("%s::vaddr[bufindex=%d][planeindex=%d] = 0x%x", __func__, buf_index, i, (unsigned int)secBuf->virt.extP[i]); + LOGD("%s::Legnth = %d" , __func__, buf.m.planes[i].length); +#endif + } + + return 0; +} + +int gsc_v4l2_req_buf(int fd, enum v4l2_buf_type type, enum v4l2_memory memory, unsigned int num_bufs) +{ +#ifdef DEBUG_LIB_FIMC + LOGD("%s", __func__); +#endif + struct v4l2_requestbuffers reqbuf; + + reqbuf.type = type; + reqbuf.memory = memory; + reqbuf.count = num_bufs; + +#ifdef DEBUG_LIB_FIMC + LOGI("%d buffers needed", reqbuf.count); +#endif + + if (ioctl(fd, VIDIOC_REQBUFS, &reqbuf) < 0) { + LOGE("%s::VIDIOC_REQBUFS failed, reqbuf.count=%d", __func__, reqbuf.count); + return -1; + } + +#ifdef DEBUG_LIB_FIMC + LOGI("%d buffers allocated", reqbuf.count); +#endif + + if (reqbuf.count < num_bufs) { + LOGE("%s::VIDIOC_REQBUFS failed ((reqbuf.count(%d) < num_bufs(%d))", + __func__, reqbuf.count, num_bufs); + return -1; + } + + return 0; +} + +int gsc_v4l2_s_ctrl(int fd, int id, int value) +{ +#ifdef DEBUG_LIB_FIMC + LOGD("%s", __func__); +#endif + struct v4l2_control vc; + + vc.id = id; + vc.value = value; + + if (ioctl(fd, VIDIOC_S_CTRL, &vc) < 0) { + LOGE("%s::VIDIOC_S_CTRL (id=%d,value=%d) failed", __func__, id, value); + return -1; + } + + return 0; +} + +int gsc_v4l2_set_fmt(int fd, enum v4l2_buf_type type, enum v4l2_field field, s5p_fimc_img_info *img_info) +{ +#ifdef DEBUG_LIB_FIMC + LOGD("%s", __func__); +#endif + struct v4l2_format fmt; + struct v4l2_crop crop; + + fmt.type = type; +#ifdef DEBUG_LIB_FIMC + LOGD("%s::fmt.type=%d", __func__, fmt.type); +#endif + if (ioctl(fd, VIDIOC_G_FMT, &fmt) < 0) { + LOGE("%s::VIDIOC_G_FMT failed", __func__); + return -1; + } + + switch (fmt.type) { + case V4L2_BUF_TYPE_VIDEO_OUTPUT: + case V4L2_BUF_TYPE_VIDEO_CAPTURE: + fmt.fmt.pix.width = img_info->full_width; + fmt.fmt.pix.height = img_info->full_height; + fmt.fmt.pix.pixelformat = img_info->color_space; + fmt.fmt.pix.field = field; + break; + case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: + case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: + fmt.fmt.pix_mp.width = img_info->full_width; + fmt.fmt.pix_mp.height = img_info->full_height; + fmt.fmt.pix_mp.pixelformat = img_info->color_space; + fmt.fmt.pix_mp.field = field; + fmt.fmt.pix_mp.num_planes = img_info->planes; + break; + default: + LOGE("%s::invalid buffer type", __func__); + return -1; + break; + } + +#ifdef DEBUG_LIB_FIMC +for (int i = 0; i < 3; i++) { + LOGD("%s::fmt.fmt.pix_mp. w=%d, h=%d, pixelformat=0x%08x, filed=%d, num_planes=%d", + __func__, + fmt.fmt.pix_mp.width, fmt.fmt.pix_mp.height, + fmt.fmt.pix_mp.pixelformat, fmt.fmt.pix_mp.field, + fmt.fmt.pix_mp.num_planes); +} +#endif + + if (ioctl(fd, VIDIOC_S_FMT, &fmt) < 0) { + LOGE("%s::VIDIOC_S_FMT failed", __func__); + return -1; + } + +#ifdef DEBUG_LIB_FIMC +for (int i = 0; i < 3; i++) { + LOGD("%s::pix_mp.pix_mp.plane_fmt[%d].sizeimage =0x%08x", __func__, i, fmt.fmt.pix_mp.plane_fmt[i].sizeimage); + LOGD("%s::pix_mp.pix_mp.plane_fmt[%d].bytesperline=0x%08x", __func__, i, fmt.fmt.pix_mp.plane_fmt[i].bytesperline); +} +#endif + + crop.type = type; + crop.c.left = img_info->start_x; + crop.c.top = img_info->start_y; + crop.c.width = img_info->width; + crop.c.height = img_info->height; + + if (ioctl(fd, VIDIOC_S_CROP, &crop) < 0) { + LOGE("%s::VIDIOC_S_CROP (x=%d, y=%d, w=%d, h=%d) failed", + __func__, + img_info->start_x, + img_info->start_y, + img_info->width, + img_info->height); + return -1; + } + +#ifdef DEBUG_LIB_FIMC + LOGD("%s::pix_mp pixelformat=0x%08x", __func__, fmt.fmt.pix_mp.pixelformat); + LOGD("%s::pix_mp w=%d, h=%d, planes=%d", __func__, fmt.fmt.pix_mp.width, fmt.fmt.pix_mp.height, fmt.fmt.pix_mp.num_planes); + LOGD("%s::crop x=%d, y=%d, w=%d, h=%d", __func__, crop.c.left, crop.c.top, crop.c.width, crop.c.height); +#endif + + return 0; +} + +int gsc_v4l2_stream_on(int fd, enum v4l2_buf_type type) +{ +#ifdef DEBUG_LIB_FIMC + LOGD("%s", __func__); +#endif + if (ioctl(fd, VIDIOC_STREAMON, &type) < 0) { + LOGE("%s::VIDIOC_STREAMON failed", __func__); + return -1; + } + + return 0; +} + +int gsc_v4l2_queue(int fd, SecBuffer *secBuf, enum v4l2_buf_type type, enum v4l2_memory memory, unsigned int index, int num_plane) +{ +#ifdef DEBUG_LIB_FIMC + LOGD("%s", __func__); + LOGD("%s::num_plane=%d", __func__, num_plane); +#endif + struct v4l2_buffer buf; + struct v4l2_plane planes[MAX_PLANES_GSCALER]; + + memset(&buf, 0, sizeof(struct v4l2_buffer)); + + for (int i = 0; i < MAX_PLANES_GSCALER; i++) + memset(&planes[i], 0, sizeof(struct v4l2_plane)); + + buf.type = type; + buf.memory = memory; + buf.length = num_plane; + buf.index = index; + buf.m.planes = planes; + + for (unsigned int i = 0; i < buf.length; i++) { + buf.m.planes[i].m.userptr = (unsigned long)secBuf->virt.extP[i]; + buf.m.planes[i].length = secBuf->size.extS[i]; + buf.m.planes[i].bytesused = buf.m.planes[i].length; +#ifdef DEBUG_LIB_FIMC + LOGD("%s::buf.index=%d", __func__, buf.index); + LOGD("%s::buf.m.planes[%d].m.userptr=0x%08x", __func__, i, (unsigned int)buf.m.planes[i].m.userptr); + LOGD("%s::buf.m.planes[%d].length =0x%08x", __func__, i, buf.m.planes[i].length); + LOGD("%s::buf.m.planes[%d].bytesused=0x%08x", __func__, i, buf.m.planes[i].bytesused); +#endif + } + + if (ioctl(fd, VIDIOC_QBUF, &buf) < 0) { + LOGE("%s::VIDIOC_QBUF failed", __func__); + return -1; + } + + return 0; +} + +int gsc_v4l2_dequeue(int fd, enum v4l2_buf_type type, enum v4l2_memory memory, unsigned int *index, int num_plane) +{ +#ifdef DEBUG_LIB_FIMC + LOGD("%s", __func__); +#endif + struct v4l2_buffer buf; + struct v4l2_plane planes[MAX_PLANES_GSCALER]; + + memset(&buf, 0, sizeof(struct v4l2_buffer)); + + for (int i = 0; i < MAX_PLANES_GSCALER; i++) + memset(&planes[i], 0, sizeof(struct v4l2_plane)); + + + buf.type = type; + buf.memory = memory; + buf.length = num_plane; + buf.m.planes = planes; + + if (ioctl(fd, VIDIOC_DQBUF, &buf) < 0) { + LOGE("%s::VIDIOC_DQBUF failed", __func__); + return -1; + } + + *index = buf.index; + +#ifdef DEBUG_LIB_FIMC + LOGD("%s::buf.index=%d", __func__, buf.index); +#endif + + return 0; +} + +int gsc_v4l2_stream_off(int fd, enum v4l2_buf_type type) +{ +#ifdef DEBUG_LIB_FIMC + LOGD("%s", __func__); +#endif + if (ioctl(fd, VIDIOC_STREAMOFF, &type) < 0) { + LOGE("%s::VIDIOC_STREAMOFF failed", __func__); + return -1; + } + + return 0; +} + +int gsc_v4l2_clr_buf(int fd, enum v4l2_buf_type type, enum v4l2_memory memory) +{ +#ifdef DEBUG_LIB_FIMC + LOGD("%s", __func__); +#endif + struct v4l2_requestbuffers req; + + req.count = 0; + req.type = type; + req.memory = memory; + + if (ioctl(fd, VIDIOC_REQBUFS, &req) < 0) { + LOGE("%s::VIDIOC_REQBUFS failed", __func__); + return -1; + } + + return 0; +} + +int gsc_subdev_set_fmt(int fd, unsigned int pad, enum v4l2_mbus_pixelcode code, s5p_fimc_img_info *img_info) +{ +#ifdef DEBUG_LIB_FIMC + LOGD("%s", __func__); +#endif + struct v4l2_subdev_format fmt; + struct v4l2_subdev_crop crop; + + fmt.pad = pad; + fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE; + fmt.format.width = img_info->full_width; + fmt.format.height = img_info->full_height; + fmt.format.code = code; + + if (ioctl(fd, VIDIOC_SUBDEV_S_FMT, &fmt) < 0) { + LOGE("%s::VIDIOC_SUBDEV_S_FMT failed", __func__); + return -1; + } + + crop.pad = pad; + crop.which = V4L2_SUBDEV_FORMAT_ACTIVE; + crop.rect.left = img_info->start_x; + crop.rect.top = img_info->start_y; + crop.rect.width = img_info->width; + crop.rect.height = img_info->height; + +#ifdef DEBUG_LIB_FIMC + LOGD("%s::pix_mp w=%d, h=%d", __func__, fmt.format.width, fmt.format.height); + LOGD("%s::crop x=%d, y=%d, w=%d, h=%d", __func__, crop.rect.left, crop.rect.top, crop.rect.width, crop.rect.height); +#endif + + if (ioctl(fd, VIDIOC_SUBDEV_S_CROP, &crop) < 0) { + LOGE("%s::VIDIOC_SUBDEV_S_CROP failed", __func__); + return -1; + } + + return 0; +} + +static inline int multipleOfN(int number, int N) +{ + int result = number; + switch (N) { + case 1: + case 2: + case 4: + case 8: + case 16: + case 32: + case 64: + case 128: + case 256: + result = (number - (number & (N-1))); + break; + default: + result = number - (number % N); + break; + } + return result; +} + +SecGscaler::SecGscaler() +: mFlagCreate(false) +{ +} + +SecGscaler::~SecGscaler() +{ + if (mFlagCreate == true) { + LOGE("%s::this is not Destroyed fail", __func__); + + if (destroy() == false) + LOGE("%s::destroy failed", __func__); + } +} + +bool SecGscaler::create(enum DEV dev, enum MODE mode, unsigned int numOfBuf) +{ + create(dev, numOfBuf); + return true; +} + +bool SecGscaler::create(enum DEV dev, unsigned int numOfBuf) +{ +#ifdef DEBUG_LIB_FIMC + LOGD("%s", __func__); +#endif + if (mFlagCreate == true) { + LOGE("%s::Already Created", __func__); + return true; + } + + char node[20]; + char subdevname[32]; + char videodevname[32]; + + struct v4l2_capability v4l2cap; + struct media_entity_desc entity_desc; + + mDev = dev; + mVideoNodeNum = dev; + mNumOfBuf = numOfBuf; + + mVideodevFd = 0; + mMediadevFd = 0; + mSubdevFd = 0; + + mSrcIndex = 0; + mRotVal = 0; + mFlagGlobalAlpha = false; + mGlobalAlpha = 0x0; + mFlagLocalAlpha = false; + mFlagColorKey = false; + mColorKey = 0x0; + mFlagSetSrcParam = false; + mFlagSetDstParam = false; + mFlagStreamOn = false; + + memset(&mS5pFimc, 0, sizeof(s5p_fimc_t)); + + switch(mDev) { + case DEV_0: + mVideoNodeNum = 24; + mSubdevNodeNum = 4; + break; + case DEV_1: + mVideoNodeNum = 27; + mSubdevNodeNum = 5; + break; + case DEV_2: + mVideoNodeNum = 30; + mSubdevNodeNum = 6; + break; + case DEV_3: + mVideoNodeNum = 33; + mSubdevNodeNum = 3; // need to modify //carrotsm + break; + default: + LOGE("%s::invalid mDev(%d)", __func__, mDev); + goto err; + break; + } + + sprintf(node, "%s%d", PFX_NODE_MEDIADEV, 0); + mMediadevFd = open(node, O_RDONLY); + + if (mMediadevFd < 0) { + LOGE("%s::open(%s) failed : O_RDONLY", __func__, node); + goto err; + } + + sprintf(subdevname, PFX_ENTITY_SUBDEV_GSC, mDev); + sprintf(videodevname, PFX_ENTITY_OUTPUTDEV_GSC, mDev); + + for (__u32 id = 0; ; id = entity_desc.id) { + entity_desc.id = id | MEDIA_ENT_ID_FLAG_NEXT; + + if (ioctl(mMediadevFd, MEDIA_IOC_ENUM_ENTITIES, &entity_desc) < 0) { + if (errno == EINVAL) { + LOGD("%s::MEDIA_IOC_ENUM_ENTITIES ended", __func__); + break; + } + LOGE("%s::MEDIA_IOC_ENUM_ENTITIES failed", __func__); + goto err; + } + +#ifdef DEBUG_LIB_FIMC + LOGD("%s::entity_desc.id=%d, .minor=%d .name=%s", __func__, entity_desc.id, entity_desc.v4l.minor, entity_desc.name); +#endif + + if (strncmp(entity_desc.name, subdevname, strlen(subdevname)) == 0) + mSubdevEntity = entity_desc.id; + + if (strncmp(entity_desc.name, videodevname, strlen(videodevname)) == 0) + mVideodevEntity = entity_desc.id; + } + + if (0 < mMediadevFd) + close(mMediadevFd); + mMediadevFd = -1; + + sprintf(node, "%s%d", PFX_NODE_SUBDEV, mSubdevNodeNum); + mSubdevFd = open(node, O_RDWR); + if (mSubdevFd < 0) { + LOGE("%s::open(%s) failed", __func__, node); + goto err; + } + + sprintf(node, "%s%d", PFX_NODE_VIDEODEV, mVideoNodeNum); + mVideodevFd = open(node, O_RDWR); + if (mVideodevFd < 0) { + LOGE("%s::open(%s) failed", __func__, node); + goto err; + } + + /* check capability */ + if (gsc_v4l2_querycap(mVideodevFd, node) < 0 ) { + LOGE("%s::tvout_std_v4l2_querycap failed", __func__); + goto err; + } + + mFlagCreate = true; + + return true; + +err : + if (0 < mVideodevFd) + close(mVideodevFd); + + if (0 < mMediadevFd) + close(mMediadevFd); + + if (0 < mSubdevFd) + close(mSubdevFd); + + mVideodevFd = -1; + mMediadevFd = -1; + mSubdevFd = -1; + + return false; +} + +bool SecGscaler::destroy() +{ + s5p_fimc_params_t *params = &(mS5pFimc.params); + + if (mFlagCreate == false) { + LOGE("%s::Already Destroyed", __func__); + return true; + } + + if (mFlagStreamOn == true) { + if (streamOff() == false) { + LOGE("%s::streamOff() failed", __func__); + return false; + } + + if (closeVideodevFd() == false) { + LOGE("%s::closeVideodevFd() failed", __func__); + return false; + } + + mFlagStreamOn = false; + } + + if (0 < mMediadevFd) + close(mMediadevFd); + + if (0 < mSubdevFd) + close(mSubdevFd); + + mVideodevFd = -1; + mMediadevFd = -1; + mSubdevFd = -1; + + mFlagCreate = false; + + return true; +} + +bool SecGscaler::flagCreate(void) +{ + return mFlagCreate; +} + +int SecGscaler::getFd(void) +{ + return getVideodevFd(); +} + +int SecGscaler::getVideodevFd(void) +{ + return mVideodevFd; +} + +bool SecGscaler::openVideodevFd(void) +{ + char node[32]; + + sprintf(node, "%s%d", PFX_NODE_VIDEODEV, mVideoNodeNum); + mVideodevFd = open(node, O_RDWR); + if (mVideodevFd < 0) { + LOGE("%s::open(%s) failed", __func__, node); + return false; + } + + return true; +} + +bool SecGscaler::closeVideodevFd(void) +{ + if (mFlagSetSrcParam == true) { + if (gsc_v4l2_clr_buf(mVideodevFd, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, V4L2_MEMORY_TYPE) < 0) { + LOGE("%s::gsc_v4l2_clr_buf() failed", __func__); + return false; + } + } + + if (0 < mVideodevFd) { + if (close(mVideodevFd) < 0) { + LOGE("%s::close Videodev failed", __func__); + return false; + } + } + mVideodevFd = -1; + + return true; +} + +int SecGscaler::getSubdevFd(void) +{ + return mSubdevFd; +} + +__u32 SecGscaler::getSubdevEntity(void) +{ + return mSubdevEntity; +} + +__u32 SecGscaler::getVideodevEntity(void) +{ + return mVideodevEntity; +} + +bool SecGscaler::getFlagSteamOn(void) +{ + return mFlagStreamOn; +} + +SecBuffer * SecGscaler::getSrcBufferAddr(int index) +{ + if (mFlagCreate == false) { + LOGE("%s::Not yet created", __func__); + return false; + } + + return &mSrcBuffer[index]; +} + +bool SecGscaler::setSrcParams(unsigned int width, unsigned int height, + unsigned int cropX, unsigned int cropY, + unsigned int *cropWidth, unsigned int *cropHeight, + int colorFormat, + bool forceChange) +{ +#ifdef DEBUG_LIB_FIMC + LOGD("%s", __func__); +#endif + + if (mFlagCreate == false) { + LOGE("%s::Not yet created", __func__); + return false; + } + + int v4l2ColorFormat = HAL_PIXEL_FORMAT_2_V4L2_PIX(colorFormat); + if (v4l2ColorFormat < 0) { + LOGE("%s::not supported color format", __func__); + return false; + } + + s5p_fimc_params_t *params = &(mS5pFimc.params); + + unsigned int fimcWidth = *cropWidth; + unsigned int fimcHeight = *cropHeight; + int src_planes = m_getYuvPlanes(v4l2ColorFormat); + int src_bpp = m_getYuvBpp(v4l2ColorFormat); + unsigned int frame_size = width * height; + unsigned int frame_ratio = 8; + + if (m_checkSrcSize(width, height, cropX, cropY, + &fimcWidth, &fimcHeight, v4l2ColorFormat, false) == false) { + LOGE("%s::::size align error!", __func__); + return false; + } + + if (fimcWidth != *cropWidth || fimcHeight != *cropHeight) { + if (forceChange == true) { +#ifdef DEBUG_LIB_FIMC + LOGD("size is changed from [w=%d, h=%d] to [w=%d, h=%d]", + *cropWidth, *cropHeight, fimcWidth, fimcHeight); +#endif + } else { + LOGE("%s::invalid source params", __func__); + return false; + } + } + + if ( (params->src.full_width == width) + && (params->src.full_height == height) + && (params->src.start_x == cropX) + && (params->src.start_y == cropY) + && (params->src.width == fimcWidth) + && (params->src.height == fimcHeight) + && (params->src.color_space == (unsigned int)v4l2ColorFormat)) + return true; + + params->src.full_width = width; + params->src.full_height = height; + params->src.start_x = cropX; + params->src.start_y = cropY; + params->src.width = fimcWidth; + params->src.height = fimcHeight; + params->src.color_space = v4l2ColorFormat; + src_planes = (src_planes == -1) ? 1 : src_planes; + params->src.planes = src_planes; + + mSrcBuffer[mSrcIndex].size.extS[0] = 0; + mSrcBuffer[mSrcIndex].size.extS[1] = 0; + mSrcBuffer[mSrcIndex].size.extS[2] = 0; + + frame_ratio = frame_ratio * (src_planes -1) / (src_bpp - 8); +#ifdef USE_GSC_USERPTR + for (int buf_index = 0; buf_index < MAX_BUFFERS_GSCALER; buf_index++) { + switch (src_planes) { + case 1: + switch (v4l2ColorFormat) { + case V4L2_PIX_FMT_BGR32: + params->src.color_space = V4L2_PIX_FMT_RGB32; + case V4L2_PIX_FMT_RGB32: + mSrcBuffer[buf_index].size.extS[0] = frame_size << 2; + break; + case V4L2_PIX_FMT_RGB565X: + case V4L2_PIX_FMT_NV16: + case V4L2_PIX_FMT_NV61: + case V4L2_PIX_FMT_YUYV: + case V4L2_PIX_FMT_UYVY: + case V4L2_PIX_FMT_VYUY: + case V4L2_PIX_FMT_YVYU: + mSrcBuffer[buf_index].size.extS[0] = frame_size << 1; + break; + case V4L2_PIX_FMT_YUV420: + case V4L2_PIX_FMT_NV12: + case V4L2_PIX_FMT_NV21: + mSrcBuffer[buf_index].size.extS[0] = (frame_size * 3) >> 1; + break; + default: + LOGE("%s::invalid color type", __func__); + return false; + break; + } + mSrcBuffer[buf_index].size.extS[1] = 0; + mSrcBuffer[buf_index].size.extS[2] = 0; + break; + case 2: + case 3: + mSrcBuffer[buf_index].size.extS[0] = frame_size; + mSrcBuffer[buf_index].size.extS[1] = frame_size / frame_ratio; + mSrcBuffer[buf_index].size.extS[2] = frame_size / frame_ratio; + break; + default: + LOGE("%s::invalid color foarmt", __func__); + return false; + break; + } + } +#else + if (v4l2ColorFormat == V4L2_PIX_FMT_BGR32) + params->src.color_space = V4L2_PIX_FMT_RGB32; +#endif + + if (mFlagSetSrcParam == true) { + if (gsc_v4l2_clr_buf(mVideodevFd, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, V4L2_MEMORY_TYPE) < 0) { + LOGE("%s::gsc_v4l2_clr_buf() failed", __func__); + return false; + } + } + + if (gsc_v4l2_set_fmt(mVideodevFd, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, V4L2_FIELD_NONE, &(params->src)) < 0) { + LOGE("%s::fimc_v4l2_set_fmt()[src] failed", __func__); + return false; + } + + if (gsc_v4l2_req_buf(mVideodevFd, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, V4L2_MEMORY_TYPE, mNumOfBuf) < 0) { + LOGE("%s::fimc_v4l2_req_buf()[src] failed", __func__); + return false; + } +#ifdef USE_GSC_USERPTR +#else + for (unsigned int buf_index = 0; buf_index < MAX_BUFFERS_GSCALER; buf_index++) { + if (gsc_v4l2_query_buf(mVideodevFd, &mSrcBuffer[buf_index], V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, V4L2_MEMORY_MMAP, buf_index, params->src.planes) < 0) { + LOGE("%s::gsc_v4l2_query_buf() failed", __func__); + return false; + } + } +#endif + + *cropWidth = fimcWidth; + *cropHeight = fimcHeight; + + mFlagSetSrcParam = true; + + return true; +} + +bool SecGscaler::getSrcParams(unsigned int *width, unsigned int *height, + unsigned int *cropX, unsigned int *cropY, + unsigned int *cropWidth, unsigned int *cropHeight, + int *v4l2colorFormat) +{ + struct v4l2_format fmt; + struct v4l2_crop crop; + + fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; + + if (ioctl(mVideodevFd, VIDIOC_G_FMT, &fmt) < 0) { + LOGE("%s::VIDIOC_G_FMT(fmt.type : %d) failed", __func__, fmt.type); + return false; + } + + switch (fmt.type) { + case V4L2_BUF_TYPE_VIDEO_OUTPUT: + case V4L2_BUF_TYPE_VIDEO_CAPTURE: + case V4L2_BUF_TYPE_VIDEO_OVERLAY: + *width = fmt.fmt.pix.width; + *height = fmt.fmt.pix.height; + *v4l2colorFormat = fmt.fmt.pix.pixelformat; + break; + case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: + case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: + *width = fmt.fmt.pix_mp.width; + *height = fmt.fmt.pix_mp.height; + *v4l2colorFormat = fmt.fmt.pix_mp.pixelformat; + break; + default: + LOGE("%s::Invalid buffer type", __func__); + return false; + break; + } + + crop.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; + if (ioctl(mVideodevFd, VIDIOC_G_CROP, &crop) < 0) { + LOGE("%s::VIDIOC_G_CROP failed", __func__); + return false; + } + + *cropX = crop.c.left; + *cropY = crop.c.top; + *cropWidth = crop.c.width; + *cropHeight = crop.c.height; + + return true; +} + +bool SecGscaler::setSrcAddr(unsigned int YAddr, + unsigned int CbAddr, + unsigned int CrAddr, + int colorFormat) +{ +#ifdef DEBUG_LIB_FIMC + LOGD("%s", __func__); +#endif + + if (mFlagCreate == false) { + LOGE("%s::Not yet created", __func__); + return false; + } + + if (mFlagSetSrcParam == false) { + LOGE("%s::mFlagSetSrcParam == false", __func__); + return false; + } + +#ifdef USE_GSC_USERPTR + mSrcBuffer[mSrcIndex].virt.extP[0] = (char *)YAddr; + mSrcBuffer[mSrcIndex].virt.extP[1] = (char *)CbAddr; + mSrcBuffer[mSrcIndex].virt.extP[2] = (char *)CrAddr; +#else + unsigned int srcAddr[MAX_PLANES_GSCALER]; + + srcAddr[0] = YAddr; + srcAddr[1] = CbAddr; + srcAddr[2] = CrAddr; + + for (int plane_index = 0; plane_index < mS5pFimc.params.src.planes; plane_index++) { + memcpy((void *)mSrcBuffer[mSrcIndex].virt.extP[plane_index], (void *)srcAddr[plane_index], mSrcBuffer[mSrcIndex].size.extS[plane_index]); + } +#endif + + return true; +} + +bool SecGscaler::setDstParams(unsigned int width, unsigned int height, + unsigned int cropX, unsigned int cropY, + unsigned int *cropWidth, unsigned int *cropHeight, + int colorFormat, + bool forceChange) +{ +#ifdef DEBUG_LIB_FIMC + LOGD("%s", __func__); +#endif + + if (mFlagCreate == false) { + LOGE("%s::Not yet created", __func__); + return false; + } + + int mbusFormat = V4L2_MBUS_FMT_YUV8_1X24; + + s5p_fimc_params_t *params = &(mS5pFimc.params); + + unsigned int fimcWidth = *cropWidth; + unsigned int fimcHeight = *cropHeight; + + if( m_checkDstSize(width, height, cropX, cropY, + &fimcWidth, &fimcHeight, V4L2_PIX_FMT_YUV444, + mRotVal, true) == false) { + LOGE("%s::size align error!", __func__); + return false; + } + + + if (fimcWidth != *cropWidth || fimcHeight != *cropHeight) { + if (forceChange == true) { +#ifdef DEBUG_LIB_FIMC + LOGD("size is changed from [w = %d, h= %d] to [w = %d, h = %d]", + *cropWidth, *cropHeight, fimcWidth, fimcHeight); +#endif + } else { + LOGE("%s::Invalid destination params", __func__); + return false; + } + } + + if (90 == mRotVal || 270 == mRotVal) { + params->dst.full_width = height; + params->dst.full_height = width; + + if (90 == mRotVal) { + params->dst.start_x = cropY; + params->dst.start_y = width - (cropX + fimcWidth); + } else { + params->dst.start_x = height - (cropY + fimcHeight); + params->dst.start_y = cropX; + } + + params->dst.width = fimcHeight; + params->dst.height = fimcWidth; + + params->dst.start_y += (fimcWidth - params->dst.height); + + } else { + params->dst.full_width = width; + params->dst.full_height = height; + + if (180 == mRotVal) { + params->dst.start_x = width - (cropX + fimcWidth); + params->dst.start_y = height - (cropY + fimcHeight); + } else { + params->dst.start_x = cropX; + params->dst.start_y = cropY; + } + + params->dst.width = fimcWidth; + params->dst.height = fimcHeight; + } + + if (gsc_subdev_set_fmt(mSubdevFd, GSC_SUBDEV_PAD_SOURCE, V4L2_MBUS_FMT_YUV8_1X24, &(params->dst)) < 0) { + LOGE("%s::gsc_subdev_set_fmt()[dst] failed", __func__); + return false; + } + + mFlagSetDstParam = true; + + return true; +} + +bool SecGscaler::getDstParams(unsigned int *width, unsigned int *height, + unsigned int *cropX, unsigned int *cropY, + unsigned int *cropWidth, unsigned int *cropHeight, + int *mbusColorFormat) +{ + struct v4l2_subdev_format fmt; + struct v4l2_subdev_crop crop; + + fmt.pad = GSC_SUBDEV_PAD_SOURCE; + fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE; + + if (ioctl(mSubdevFd, VIDIOC_SUBDEV_G_FMT, &fmt) < 0) { + LOGE("%s::VIDIOC_SUBDEV_S_FMT", __func__); + return -1; + } + + *width = fmt.format.width; + *height = fmt.format.height; + *mbusColorFormat = fmt.format.code; + + crop.pad = GSC_SUBDEV_PAD_SOURCE; + crop.which = V4L2_SUBDEV_FORMAT_ACTIVE; + + if (ioctl(mSubdevFd, VIDIOC_SUBDEV_G_CROP, &crop) < 0) { + LOGE("%s::VIDIOC_SUBDEV_S_CROP", __func__); + return -1; + } + + *cropX = crop.rect.left; + *cropY = crop.rect.top; + *cropWidth = crop.rect.width; + *cropHeight = crop.rect.height; + + return true; +} + +bool SecGscaler::setDstAddr(unsigned int YAddr, unsigned int CbAddr, unsigned int CrAddr, int buf_index) +{ +#ifdef DEBUG_LIB_FIMC + LOGD("%s", __func__); +#endif + + if (mFlagCreate == false) { + LOGE("%s::Not yet created", __func__); + return false; + } + + return true; +} + +bool SecGscaler::setRotVal(unsigned int rotVal) +{ + struct v4l2_control vc; + + if (mFlagCreate == false) { + LOGE("%s::Not yet created", __func__); + return false; + } + + if (gsc_v4l2_s_ctrl(mVideodevFd, V4L2_CID_ROTATE, rotVal) < 0) { + LOGE("%s::fimc_v4l2_s_ctrl(V4L2_CID_ROTATE) failed", __func__); + return false; + } + + mRotVal = rotVal; + return true; +} + +bool SecGscaler::setGlobalAlpha(bool enable, int alpha) +{ + if (mFlagCreate == false) { + LOGE("%s::Not yet created", __func__); + return false; + } + + if (mFlagStreamOn == true) { + LOGE("%s::mFlagStreamOn == true", __func__); + return false; + } + + mFlagGlobalAlpha = enable; + mGlobalAlpha = alpha; + + return true; + +} + +bool SecGscaler::setLocalAlpha(bool enable) +{ + if (mFlagCreate == false) { + LOGE("%s::Not yet created", __func__); + return false; + } + + if (mFlagStreamOn == true) { + LOGE("%s::mFlagStreamOn == true", __func__); + return false; + } + + if (mFlagLocalAlpha == enable) + return true; + + return true; +} + +bool SecGscaler::setColorKey(bool enable, int colorKey) +{ + if (mFlagCreate == false) { + LOGE("%s::Not yet created", __func__); + return false; + } + + if (mFlagStreamOn == true) { + LOGE("%s::mFlagStreamOn == true", __func__); + return false; + } + + mFlagColorKey = enable; + mColorKey = colorKey; + + return true; +} + +bool SecGscaler::run() +{ +#ifdef DEBUG_LIB_FIMC + LOGD("%s", __func__); +#endif + + if (mFlagCreate == false) { + LOGE("%s::Not yet created", __func__); + return false; + } + + if (mFlagSetSrcParam == false) { + LOGE("%s::faild : Need to set source parameters of Gscaler", __func__); + return false; + } + + if (mFlagSetDstParam == false) { + LOGE("%s::faild : Need to set destination parameters of Gscaler", __func__); + return false; + } + + s5p_fimc_params_t *params = &(mS5pFimc.params); + int src_planes = m_getYuvPlanes(params->src.color_space); + unsigned int dqIndex = 0; + src_planes = (src_planes == -1) ? 1 : src_planes; + + if (gsc_v4l2_queue(mVideodevFd, &(mSrcBuffer[mSrcIndex]), V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, V4L2_MEMORY_TYPE, mSrcIndex, src_planes) < 0) { + LOGE("%s::fimc_v4l2_queue[src](mNumOfBuf : %d,mSrcIndex=%d) failed", __func__, mNumOfBuf, mSrcIndex); + return false; + } + + mSrcIndex++; + if (mSrcIndex >= MAX_BUFFERS_GSCALER) { + mSrcIndex = 0; + } + + if (gsc_v4l2_dequeue(mVideodevFd, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, V4L2_MEMORY_TYPE, &dqIndex, src_planes) < 0) { + LOGE("%s::fimc_v4l2_dequeue[src](mNumOfBuf : %d, dqIndex=%d) failed", __func__, mNumOfBuf, dqIndex); + return false; + } + + return true; +} + +bool SecGscaler::streamOn(void) +{ +#ifdef DEBUG_LIB_FIMC + LOGD("%s", __func__); +#endif + + if (mFlagCreate == false) { + LOGE("%s::Not yet created", __func__); + return false; + } + + if (mFlagStreamOn == true) { + LOGE("%s::already streamon", __func__); + return true; + } + + s5p_fimc_params_t *params = &(mS5pFimc.params); + int src_planes = m_getYuvPlanes(params->src.color_space); + src_planes = (src_planes == -1) ? 1 : src_planes; + + if (gsc_v4l2_queue(mVideodevFd, &(mSrcBuffer[mSrcIndex]), V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, V4L2_MEMORY_TYPE, mSrcIndex, src_planes) < 0) { + LOGE("%s::fimc_v4l2_queue[src](mNumOfBuf : %d,mSrcIndex=%d) failed", __func__, mNumOfBuf, mSrcIndex); + return false; + } + + mSrcIndex++; + if (mSrcIndex == MAX_BUFFERS_GSCALER - 1) { + if (gsc_v4l2_stream_on(mVideodevFd, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) < 0) { + LOGE("%s::fimc_v4l2_stream_on() failed", __func__); + return false; + } + mFlagStreamOn = true; + } + + if (mSrcIndex >= MAX_BUFFERS_GSCALER) { + mSrcIndex = 0; + } + + return true; +} + +bool SecGscaler::streamOff(void) +{ +#ifdef DEBUG_LIB_FIMC + LOGD("%s", __func__); +#endif + + if (mFlagCreate == false) { + LOGE("%s::Not yet created", __func__); + return false; + } + + if (mFlagStreamOn == false) { + LOGE("%s::already streamoff", __func__); + return true; + } + + if (gsc_v4l2_stream_off(mVideodevFd, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) < 0) { + LOGE("%s::fimc_v4l2_stream_off() failed", __func__); + return false; + } + + mSrcIndex = 0; +#ifdef USE_GSC_USERPTR + SecBuffer zeroBuf; + for (int buf_index = 0; buf_index < MAX_BUFFERS_GSCALER; buf_index++) + mSrcBuffer[buf_index] = zeroBuf; +#else + for (int buf_index = 0; buf_index < MAX_BUFFERS_GSCALER; buf_index++) { + for (int plane_index = 0; plane_index < MAX_PLANES_GSCALER; plane_index++) { + munmap((void *)mSrcBuffer[buf_index].virt.extP[plane_index], mSrcBuffer[buf_index].size.extS[plane_index]); + } + } +#endif + + mFlagStreamOn = false; + + return true; +} + +bool SecGscaler::m_checkSrcSize(unsigned int width, unsigned int height, + unsigned int cropX, unsigned int cropY, + unsigned int *cropWidth, unsigned int *cropHeight, + int colorFormat, + bool forceChange) +{ + bool ret = true; + + if (8 <= height && *cropHeight < 8) { + if (forceChange) + *cropHeight = 8; + ret = false; + } + + if (16 <= width && *cropWidth < 16) { + if (forceChange) + *cropWidth = 16; + ret = false; + } + + if (height < 8) + return false; + + if (width % 16 != 0) + return false; + + if (*cropWidth % 16 != 0) { + if (forceChange) + *cropWidth = multipleOfN(*cropWidth, 16); + ret = false; + } + + return ret; +} + +bool SecGscaler::m_checkDstSize(unsigned int width, unsigned int height, + unsigned int cropX, unsigned int cropY, + unsigned int *cropWidth, unsigned int *cropHeight, + int colorFormat, int rotVal, bool forceChange) +{ + bool ret = true; + unsigned int rotWidth; + unsigned int rotHeight; + unsigned int *rotCropWidth; + unsigned int *rotCropHeight; + + if (rotVal == 90 || rotVal == 270) { + rotWidth = height; + rotHeight = width; + rotCropWidth = cropHeight; + rotCropHeight = cropWidth; + } else { + rotWidth = width; + rotHeight = height; + rotCropWidth = cropWidth; + rotCropHeight = cropHeight; + } + + if (rotHeight < 8) + return false; + + if (rotWidth % 8 != 0) + return false; + + switch (colorFormat) { + case V4L2_PIX_FMT_NV21: + case V4L2_PIX_FMT_NV12: + case V4L2_PIX_FMT_NV12T: + case V4L2_PIX_FMT_NV12M: + case V4L2_PIX_FMT_NV12MT: + case V4L2_PIX_FMT_YUV420M: + case V4L2_PIX_FMT_YUV420: + if (*rotCropHeight % 2 != 0) { + if (forceChange) + *rotCropHeight = multipleOfN(*rotCropHeight, 2); + ret = false; + } + } + return ret; +} + +int SecGscaler::m_widthOfFimc(int v4l2ColorFormat, int width) +{ + int newWidth = width; + + switch (v4l2ColorFormat) { + case V4L2_PIX_FMT_RGB565: + newWidth = multipleOfN(width, 8); + break; + case V4L2_PIX_FMT_RGB32: + newWidth = multipleOfN(width, 4); + break; + case V4L2_PIX_FMT_YUYV: + case V4L2_PIX_FMT_UYVY: + newWidth = multipleOfN(width, 4); + break; + case V4L2_PIX_FMT_NV61: + case V4L2_PIX_FMT_NV16: + newWidth = multipleOfN(width, 8); + break; + case V4L2_PIX_FMT_YUV422P: + newWidth = multipleOfN(width, 16); + break; + case V4L2_PIX_FMT_NV21: + case V4L2_PIX_FMT_NV12: + case V4L2_PIX_FMT_NV12MT: + newWidth = multipleOfN(width, 8); + break; + case V4L2_PIX_FMT_YUV420: + case V4L2_PIX_FMT_YUV420M: + newWidth = multipleOfN(width, 16); + break; + default : + break; + } + + return newWidth; +} + +int SecGscaler::m_heightOfFimc(int v4l2ColorFormat, int height) +{ + int newHeight = height; + + switch (v4l2ColorFormat) { + case V4L2_PIX_FMT_NV21: + case V4L2_PIX_FMT_NV12: + case V4L2_PIX_FMT_NV12T: + case V4L2_PIX_FMT_NV12MT: + case V4L2_PIX_FMT_YUV420: + case V4L2_PIX_FMT_YUV420M: + newHeight = multipleOfN(height, 2); + break; + default : + break; + } + return newHeight; +} + +int SecGscaler::m_getYuvBpp(unsigned int fmt) +{ + int i, sel = -1; + + for (i = 0; i < (int)(sizeof(yuv_list) / sizeof(struct yuv_fmt_list)); i++) { + if (yuv_list[i].fmt == fmt) { + sel = i; + break; + } + } + + if (sel == -1) + return sel; + else + return yuv_list[sel].bpp; +} + +int SecGscaler::m_getYuvPlanes(unsigned int fmt) +{ + int i, sel = -1; + + for (i = 0; i < (int)(sizeof(yuv_list) / sizeof(struct yuv_fmt_list)); i++) { + if (yuv_list[i].fmt == fmt) { + sel = i; + break; + } + } + + if (sel == -1) + return sel; + else + return yuv_list[sel].planes; +} diff --git a/exynos5/hal/libhdmi/SecHdmi/SecGscaler.h b/exynos5/hal/libhdmi/SecHdmi/SecGscaler.h new file mode 100644 index 0000000..e9867ed --- /dev/null +++ b/exynos5/hal/libhdmi/SecHdmi/SecGscaler.h @@ -0,0 +1,195 @@ +/* + * Copyright@ Samsung Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __SEC_GSC_OUT_H__ +#define __SEC_GSC_OUT_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "utils/Timers.h" + +#include "s5p_fimc_v4l2.h" +#include "sec_utils_v4l2.h" +#include "media.h" +#include "v4l2-subdev.h" + +#include "sec_format.h" + +#include "SecBuffer.h" + +#define PFX_NODE_MEDIADEV "/dev/media" +#define PFX_NODE_SUBDEV "/dev/v4l-subdev" +#define PFX_NODE_VIDEODEV "/dev/video" +#define PFX_ENTITY_SUBDEV_GSC "exynos-gsc-sd.%d" +#define PFX_ENTITY_OUTPUTDEV_GSC "exynos-gsc.%d.output" + +#define GSC_SUBDEV_PAD_SINK (0) +#define GSC_SUBDEV_PAD_SOURCE (1) +#define GSC_VIDEODEV_PAD_SOURCE (0) +#define MAX_BUFFERS_GSCALER (2) +#define MAX_PLANES_GSCALER (3) + +#ifdef __cplusplus +} + +class SecGscaler +{ +public: + enum DEV { + DEV_0 = 0, + DEV_1, + DEV_2, + DEV_3, + DEV_MAX, + }; + + enum MODE { + MODE_NONE = 0, + MODE_SINGLE_BUF, + MODE_MULTI_BUF, + MODE_DMA_AUTO, + MODE_MAX, + }; + +private: + bool mFlagCreate; + int mDev; + int mVideoNodeNum; + int mSubdevNodeNum; + int mVideodevFd; + int mMediadevFd; + int mSubdevFd; + unsigned int mNumOfBuf; + unsigned int mSrcIndex; + int mRotVal; + bool mFlagGlobalAlpha; + int mGlobalAlpha; + bool mFlagLocalAlpha; + bool mFlagColorKey; + int mColorKey; + bool mFlagSetSrcParam; + bool mFlagSetDstParam; + bool mFlagStreamOn; + + s5p_fimc_t mS5pFimc; + SecBuffer mSrcBuffer[MAX_BUFFERS_GSCALER]; + + __u32 mSubdevEntity; + __u32 mVideodevEntity; + //struct media_link_desc mlink_desc; + +public: + SecGscaler(); + virtual ~SecGscaler(); + + bool create(enum DEV dev, enum MODE mode, unsigned int numOfBuf); + bool create(enum DEV dev, unsigned int numOfBuf); + + bool destroy(void); + bool flagCreate(void); + + int getFd(void); + int getVideodevFd(void); + bool openVideodevFd(void); + bool closeVideodevFd(void); + + int getSubdevFd(void); + __u32 getSubdevEntity(void); + __u32 getVideodevEntity(void); + bool getFlagSteamOn(void); + + SecBuffer * getSrcBufferAddr(int index); + + bool setSrcParams(unsigned int width, unsigned int height, + unsigned int cropX, unsigned int cropY, + unsigned int *cropWidth, unsigned int *cropHeight, + int colorFormat, + bool forceChange = true); + + bool getSrcParams(unsigned int *width, unsigned int *height, + unsigned int *cropX, unsigned int *cropY, + unsigned int *cropWidth, unsigned int *cropHeight, + int *v4l2colorFormat); + + bool setSrcAddr(unsigned int YAddr, + unsigned int CbAddr = 0, + unsigned int CrAddr = 0, + int colorFormat = 0); + + bool setDstParams(unsigned int width, unsigned int height, + unsigned int cropX, unsigned int cropY, + unsigned int *cropWidth, unsigned int *cropHeight, + int colorFormat, + bool forceChange = true); + + bool getDstParams(unsigned int *width, unsigned int *height, + unsigned int *cropX, unsigned int *cropY, + unsigned int *cropWidth, unsigned int *cropHeight, + int *mbusColorFormat); + + bool setDstAddr(unsigned int YAddr, + unsigned int CbAddr = 0, + unsigned int CrAddr = 0, + int buf_index = 0); + + bool setRotVal(unsigned int rotVal); + bool setGlobalAlpha(bool enable = true, int alpha = 0xff); + bool setLocalAlpha(bool enable); + bool setColorKey(bool enable = true, int colorKey = 0xff); + + bool run(void); + bool streamOn(void); + bool streamOff(void); + +private: + bool m_checkSrcSize(unsigned int width, unsigned int height, + unsigned int cropX, unsigned int cropY, + unsigned int *cropWidth, unsigned int *cropHeight, + int colorFormat, + bool forceChange = false); + + bool m_checkDstSize(unsigned int width, unsigned int height, + unsigned int cropX, unsigned int cropY, + unsigned int *cropWidth, unsigned int *cropHeight, + int colorFormat, + int rotVal, + bool forceChange = false); + int m_widthOfFimc(int v4l2ColorFormat, int width); + int m_heightOfFimc(int v4l2ColorFormat, int height); + int m_getYuvBpp(unsigned int fmt); + int m_getYuvPlanes(unsigned int fmt); +}; +#endif + +#endif //__SEC_GSC_OUT_H__ diff --git a/exynos5/hal/libhdmi/SecHdmi/SecHdmi.cpp b/exynos5/hal/libhdmi/SecHdmi/SecHdmi.cpp new file mode 100644 index 0000000..8f0f80b --- /dev/null +++ b/exynos5/hal/libhdmi/SecHdmi/SecHdmi.cpp @@ -0,0 +1,1985 @@ +/* + * Copyright@ Samsung Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +//#define DEBUG_MSG_ENABLE +//#define LOG_NDEBUG 0 +//#define LOG_TAG "libhdmi" +#include +#include "ion.h" +#include "SecHdmi.h" +#include "SecHdmiV4L2Utils.h" + +#define CHECK_GRAPHIC_LAYER_TIME (0) + +namespace android { + +extern unsigned int output_type; +extern v4l2_std_id t_std_id; +extern int g_hpd_state; +extern unsigned int g_hdcp_en; + +#if defined(BOARD_USES_HDMI_FIMGAPI) +extern unsigned int g2d_reserved_memory0; +extern unsigned int g2d_reserved_memory1; +extern unsigned int g2d_reserved_memory_size; +extern unsigned int cur_g2d_address; +#endif + +#if defined(BOARD_USES_CEC) +SecHdmi::CECThread::~CECThread() +{ +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("%s", __func__); +#endif + mFlagRunning = false; +} + +bool SecHdmi::CECThread::threadLoop() +{ + unsigned char buffer[CEC_MAX_FRAME_SIZE]; + int size; + unsigned char lsrc, ldst, opcode; + + { + Mutex::Autolock lock(mThreadLoopLock); + mFlagRunning = true; + + size = CECReceiveMessage(buffer, CEC_MAX_FRAME_SIZE, 100000); + + if (!size) // no data available or ctrl-c + return true; + + if (size == 1) + return true; // "Polling Message" + + lsrc = buffer[0] >> 4; + + /* ignore messages with src address == mLaddr*/ + if (lsrc == mLaddr) + return true; + + opcode = buffer[1]; + + if (CECIgnoreMessage(opcode, lsrc)) { + LOGE("### ignore message coming from address 15 (unregistered)\n"); + return true; + } + + if (!CECCheckMessageSize(opcode, size)) { + LOGE("### invalid message size: %d(opcode: 0x%x) ###\n", size, opcode); + return true; + } + + /* check if message broadcasted/directly addressed */ + if (!CECCheckMessageMode(opcode, (buffer[0] & 0x0F) == CEC_MSG_BROADCAST ? 1 : 0)) { + LOGE("### invalid message mode (directly addressed/broadcast) ###\n"); + return true; + } + + ldst = lsrc; + + //TODO: macroses to extract src and dst logical addresses + //TODO: macros to extract opcode + + switch (opcode) { + case CEC_OPCODE_GIVE_PHYSICAL_ADDRESS: + /* responce with "Report Physical Address" */ + buffer[0] = (mLaddr << 4) | CEC_MSG_BROADCAST; + buffer[1] = CEC_OPCODE_REPORT_PHYSICAL_ADDRESS; + buffer[2] = (mPaddr >> 8) & 0xFF; + buffer[3] = mPaddr & 0xFF; + buffer[4] = mDevtype; + size = 5; + break; + + case CEC_OPCODE_REQUEST_ACTIVE_SOURCE: + LOGD("[CEC_OPCODE_REQUEST_ACTIVE_SOURCE]\n"); + /* responce with "Active Source" */ + buffer[0] = (mLaddr << 4) | CEC_MSG_BROADCAST; + buffer[1] = CEC_OPCODE_ACTIVE_SOURCE; + buffer[2] = (mPaddr >> 8) & 0xFF; + buffer[3] = mPaddr & 0xFF; + size = 4; + LOGD("Tx : [CEC_OPCODE_ACTIVE_SOURCE]\n"); + break; + + case CEC_OPCODE_ABORT: + case CEC_OPCODE_FEATURE_ABORT: + default: + /* send "Feature Abort" */ + buffer[0] = (mLaddr << 4) | ldst; + buffer[1] = CEC_OPCODE_FEATURE_ABORT; + buffer[2] = CEC_OPCODE_ABORT; + buffer[3] = 0x04; // "refused" + size = 4; + break; + } + + if (CECSendMessage(buffer, size) != size) + LOGE("CECSendMessage() failed!!!\n"); + + } + return true; +} + +bool SecHdmi::CECThread::start() +{ +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("%s", __func__); +#endif + + Mutex::Autolock lock(mThreadControlLock); + if (exitPending()) { + if (requestExitAndWait() == WOULD_BLOCK) { + LOGE("mCECThread.requestExitAndWait() == WOULD_BLOCK"); + return false; + } + } + +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("EDIDGetCECPhysicalAddress"); +#endif + /* set to not valid physical address */ + mPaddr = CEC_NOT_VALID_PHYSICAL_ADDRESS; + + if (!EDIDGetCECPhysicalAddress(&mPaddr)) { + LOGE("Error: EDIDGetCECPhysicalAddress() failed.\n"); + return false; + } + +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("CECOpen"); +#endif + if (!CECOpen()) { + LOGE("CECOpen() failed!!!\n"); + return false; + } + + /* a logical address should only be allocated when a device \ + has a valid physical address, at all other times a device \ + should take the 'Unregistered' logical address (15) + */ + + /* if physical address is not valid device should take \ + the 'Unregistered' logical address (15) + */ + +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("CECAllocLogicalAddress"); +#endif + mLaddr = CECAllocLogicalAddress(mPaddr, mDevtype); + + if (!mLaddr) { + LOGE("CECAllocLogicalAddress() failed!!!\n"); + if (!CECClose()) + LOGE("CECClose() failed!\n"); + return false; + } + +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("request to run CECThread"); +#endif + + status_t ret = run("SecHdmi::CECThread", PRIORITY_DISPLAY); + if (ret != NO_ERROR) { + LOGE("%s fail to run thread", __func__); + return false; + } + return true; +} + +bool SecHdmi::CECThread::stop() +{ +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("%s request Exit", __func__); +#endif + Mutex::Autolock lock(mThreadControlLock); + if (requestExitAndWait() == WOULD_BLOCK) { + LOGE("mCECThread.requestExitAndWait() == WOULD_BLOCK"); + return false; + } + + if (!CECClose()) + LOGE("CECClose() failed!\n"); + + mFlagRunning = false; + return true; +} +#endif + +SecHdmi::SecHdmi(): +#if defined(BOARD_USES_CEC) + mCECThread(NULL), +#endif + mFlagCreate(false), + mFlagConnected(false), + mPreviousHdmiPresetId(V4L2_DV_1080P60), + mHdmiDstWidth(0), + mHdmiDstHeight(0), + mHdmiSrcYAddr(0), + mHdmiSrcCbCrAddr(0), + mFBaddr(0), + mFBsize(0), + mFBionfd(-1), + mFBoffset(0), + mHdmiOutputMode(DEFAULT_OUPUT_MODE), + mHdmiResolutionValue(DEFAULT_HDMI_RESOLUTION_VALUE), // V4L2_STD_480P_60_4_3 + mHdmiStdId(DEFAULT_HDMI_STD_ID), // V4L2_STD_480P_60_4_3 + mCompositeStd(DEFAULT_COMPOSITE_STD), + mHdcpMode(false), + mAudioMode(2), + mUIRotVal(0), + mG2DUIRotVal(0), + mCurrentHdmiOutputMode(-1), + mCurrentHdmiResolutionValue(0), // 1080960 + mCurrentHdcpMode(false), + mCurrentAudioMode(-1), + mHdmiInfoChange(true), + mFlagGscalerStart(false), + mGscalerDstColorFormat(0), + mDefaultFBFd(-1), + mCurrentsrcW(0), + mCurrentsrcH(0), + mCurrentsrcColorFormat(0), + mCurrentsrcYAddr(0), + mCurrentsrcCbAddr(0), + mCurrentdstX(0), + mCurrentdstY(0), + mCurrenthdmiLayer(0), + mCurrentNumOfHWCLayer(0), + mDisplayWidth(DEFALULT_DISPLAY_WIDTH), + mDisplayHeight(DEFALULT_DISPLAY_HEIGHT) +{ +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("%s", __func__); +#endif + for (int i = 0; i < HDMI_LAYER_MAX; i++) { + mFlagLayerEnable[i] = false; + mFlagHdmiStart[i] = false; + + mSrcWidth [i] = 0; + mSrcHeight [i] = 0; + mSrcColorFormat[i] = 0; + mHdmiResolutionWidth [i] = 0; + mHdmiResolutionHeight [i] = 0; + mPreviousNumofHwLayer [i] = 0; + mSrcIndex[i] = 0; + } + + //All layer is on + mFlagLayerEnable[HDMI_LAYER_VIDEO] = true; + mFlagLayerEnable[HDMI_LAYER_GRAPHIC_0] = true; + mFlagLayerEnable[HDMI_LAYER_GRAPHIC_1] = true; + + mHdmiSizeOfResolutionValueList = 14; + + mHdmiResolutionValueList[0] = 1080960; + mHdmiResolutionValueList[1] = 1080950; + mHdmiResolutionValueList[2] = 1080930; + mHdmiResolutionValueList[3] = 1080924; + mHdmiResolutionValueList[4] = 1080160; + mHdmiResolutionValueList[5] = 1080150; + mHdmiResolutionValueList[6] = 720960; + mHdmiResolutionValueList[7] = 7209601; + mHdmiResolutionValueList[8] = 720950; + mHdmiResolutionValueList[9] = 7209501; + mHdmiResolutionValueList[10] = 5769501; + mHdmiResolutionValueList[11] = 5769502; + mHdmiResolutionValueList[12] = 4809601; + mHdmiResolutionValueList[13] = 4809602; + +#if defined(BOARD_USES_CEC) + mCECThread = new CECThread(this); +#endif + + mGscalerForceUpdate = false; +} + +SecHdmi::~SecHdmi() +{ +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("%s", __func__); +#endif + if (mFlagCreate == true) + LOGE("%s::this is not Destroyed fail", __func__); + else + disconnect(); +} + +bool SecHdmi::create(int width, int height) +{ + Mutex::Autolock lock(mLock); + unsigned int fimc_buf_size = 0; + int stride; + int vstride; + + int ionfd_G2D = 0; + void * ion_base_addr = NULL; + + struct s3c_fb_user_ion_client ion_handle; + unsigned int FB_size = ALIGN(width, 16) * ALIGN(height, 16) * HDMI_G2D_BUFFER_BPP_SIZE * 2; + int ionfd_FB = 0; + +/* + * Video plaback (I420): output buffer size of FIMC3 is (1920 x 1088 x 1.5) + * Video plaback (NV12): FIMC3 is not used. + * Camera preview (YV12): output buffer size of FIMC3 is (640 x 480 x 1.5) + * UI mode (ARGB8888) : output buffer size of FIMC3 is (480 x 800 x 1.5) + */ +#ifndef SUPPORT_1080P_FIMC_OUT + setDisplaySize(width, height); +#endif + + stride = ALIGN(HDMI_MAX_WIDTH, 16); + vstride = ALIGN(HDMI_MAX_HEIGHT, 16); + + fimc_buf_size = stride * vstride * HDMI_FIMC_BUFFER_BPP_SIZE; +#if defined(BOARD_USES_HDMI_FIMGAPI) + g2d_reserved_memory_size = stride * vstride * HDMI_G2D_BUFFER_BPP_SIZE; +#endif + +#ifdef DEBUG_MSG_ENABLE + LOGD("%s", __func__); +#endif + + if (mFlagCreate == true) { + LOGE("%s::Already Created", __func__); + return true; + } + + if (mDefaultFBFd <= 0) { + if ((mDefaultFBFd = fb_open(DEFAULT_FB)) < 0) { + LOGE("%s:Failed to open default FB", __func__); + return false; + } + } + + if (mSecGscaler.create(SecGscaler::DEV_3, MAX_BUFFERS_GSCALER) == false) { + LOGE("%s::SecGscaler create() failed", __func__); + goto CREATE_FAIL; + } + + mIonClient = ion_client_create(); + if (mIonClient < 0) { + mIonClient = -1; + LOGE("%s::ion_client_create() failed", __func__); + goto CREATE_FAIL; + } + + // get framebuffer virtual address for LCD + if (ioctl(mDefaultFBFd, S3CFB_GET_ION_USER_HANDLE, &ion_handle) == -1) { + LOGE("%s:ioctl(S3CFB_GET_ION_USER_HANDLE) failed", __func__); + return false; + } + + mFBaddr = (unsigned int)ion_map(ion_handle.fd, ALIGN(FB_size, PAGE_SIZE), 0); + mFBsize = FB_size; + mFBionfd = ion_handle.fd; + +#if defined(BOARD_USES_HDMI_FIMGAPI) + ionfd_G2D = ion_alloc(mIonClient, ALIGN(g2d_reserved_memory_size * 2, PAGE_SIZE), 0, ION_HEAP_EXYNOS_MASK); + + if (ionfd_G2D < 0) { + LOGE("%s::ION memory allocation failed", __func__); + } else { + ion_base_addr = ion_map(ionfd_G2D, ALIGN(g2d_reserved_memory_size * 2, PAGE_SIZE), 0); + if (ion_base_addr == MAP_FAILED) + LOGE("%s::ION mmap failed", __func__); + } + + g2d_reserved_memory0 = (unsigned int)ion_base_addr; + g2d_reserved_memory1 = g2d_reserved_memory0 + g2d_reserved_memory_size; +#endif + + v4l2_std_id std_id; + __u32 preset_id; + +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("%s::mHdmiOutputMode(%d) \n", __func__, mHdmiOutputMode); +#endif + if (mHdmiOutputMode == COMPOSITE_OUTPUT_MODE) { + std_id = composite_std_2_v4l2_std_id(mCompositeStd); + if ((int)std_id < 0) { + LOGE("%s::composite_std_2_v4l2_std_id(%d) fail\n", __func__, mCompositeStd); + goto CREATE_FAIL; + } + if (m_setCompositeResolution(mCompositeStd) == false) { + LOGE("%s::m_setCompositeResolution(%d) fail\n", __func__, mCompositeStd); + goto CREATE_FAIL; + } + } else if (mHdmiOutputMode >= HDMI_OUTPUT_MODE_YCBCR && + mHdmiOutputMode <= HDMI_OUTPUT_MODE_DVI) { + if (hdmi_resolution_2_std_id(mHdmiResolutionValue, &mHdmiDstWidth, &mHdmiDstHeight, &std_id, &preset_id) < 0) { + LOGE("%s::hdmi_resolution_2_std_id(%d) fail\n", __func__, mHdmiResolutionValue); + goto CREATE_FAIL; + } + } + + if (m_setupLink() == false) { + LOGE("%s:Enable the link failed", __func__); + return false; + } + + for (int layer = HDMI_LAYER_BASE + 1; layer < HDMI_LAYER_MAX; layer++) { + if (m_openLayer(layer) == false) + LOGE("%s::hdmi_init_layer(%d) failed", __func__, layer); + } + + for (int layer = HDMI_LAYER_BASE + 2; layer < HDMI_LAYER_MAX; layer++) { + if (tvout_std_v4l2_s_ctrl(mVideodevFd[layer], V4L2_CID_TV_LAYER_BLEND_ENABLE, 1) < 0) { + LOGE("%s::tvout_std_v4l2_s_ctrl [layer=%d] (V4L2_CID_TV_LAYER_BLEND_ENABLE) failed", __func__, layer); + return false; + } + + if (tvout_std_v4l2_s_ctrl(mVideodevFd[layer], V4L2_CID_TV_PIXEL_BLEND_ENABLE, 1) < 0) { + LOGE("%s::tvout_std_v4l2_s_ctrl [layer=%d] (V4L2_CID_TV_LAYER_BLEND_ENABLE) failed", __func__, layer); + return false; + } + + if (tvout_std_v4l2_s_ctrl(mVideodevFd[layer], V4L2_CID_TV_LAYER_BLEND_ALPHA, 255) < 0) { + LOGE("%s::tvout_std_v4l2_s_ctrl [layer=%d] (V4L2_CID_TV_LAYER_BLEND_ALPHA) failed", __func__, layer); + return false; + } + } + + mFlagCreate = true; + + return true; + +CREATE_FAIL : + + if (mSecGscaler.flagCreate() == true && + mSecGscaler.destroy() == false) + LOGE("%s::Gscaler destory failed", __func__); + + return false; +} + +bool SecHdmi::destroy(void) +{ +#ifdef DEBUG_MSG_ENABLE + LOGD("%s", __func__); +#endif + + char node[32]; + Mutex::Autolock lock(mLock); + + if (mFlagCreate == false) { + LOGE("%s::Already Destroyed fail \n", __func__); + goto DESTROY_FAIL; + } + + for (int layer = HDMI_LAYER_BASE + 1; layer < HDMI_LAYER_MAX; layer++) { + if (mFlagHdmiStart[layer] == true && m_stopHdmi(layer) == false) { + LOGE("%s::m_stopHdmi: layer[%d] fail \n", __func__, layer); + goto DESTROY_FAIL; + } + } + + for (int layer = HDMI_LAYER_BASE + 1; layer < HDMI_LAYER_MAX; layer++) { + if (m_closeLayer(layer) == false) + LOGE("%s::hdmi_deinit_layer(%d) failed", __func__, layer); + } + + if (mSecGscaler.flagCreate() == true && mSecGscaler.destroy() == false) { + LOGE("%s::fimc destory fail \n", __func__); + goto DESTROY_FAIL; + } + +#ifdef USE_LCD_ADDR_IN_HERE + { + if (0 < mDefaultFBFd) { + close(mDefaultFBFd); + mDefaultFBFd = -1; + } + } +#endif //USE_LCD_ADDR_IN_HERE + +#if defined(BOARD_USES_HDMI_FIMGAPI) + ion_unmap((void *)g2d_reserved_memory0, ALIGN(g2d_reserved_memory_size * 2, PAGE_SIZE)); +#endif + + if (0 < mFBaddr) + ion_unmap((void *)mFBaddr, ALIGN(mFBsize, PAGE_SIZE)); + + if (0 < mFBionfd) + ion_free(mFBionfd); + + sprintf(node, "%s%d", PFX_NODE_MEDIADEV, 0); + mMediadevFd = open(node, O_RDONLY); + + if (mMediadevFd < 0) { + LOGE("%s::open(%s) failed", __func__, node); + goto DESTROY_FAIL; + } + + mlink_desc.flags = 0; + if (ioctl(mMediadevFd, MEDIA_IOC_SETUP_LINK, &mlink_desc) < 0) { + LOGE("%s::MEDIA_IOC_SETUP_UNLINK failed", __func__); + goto DESTROY_FAIL; + } + + for (int layer = HDMI_LAYER_BASE + 1; layer < HDMI_LAYER_MAX; layer++) { + if (m_closeLayer(layer) == false) + LOGE("%s::hdmi_deinit_layer(%d) failed", __func__, layer); + } + + if (0 < mMediadevFd) + close(mMediadevFd); + + if (0 < mSubdevMixerFd) + close(mSubdevMixerFd); + + mMediadevFd = -1; + mSubdevMixerFd = -1; + + mFlagCreate = false; + + return true; + +DESTROY_FAIL : + + return false; +} + +bool SecHdmi::connect(void) +{ +#ifdef DEBUG_MSG_ENABLE + LOGD("%s", __func__); +#endif + + { + Mutex::Autolock lock(mLock); + + if (mFlagCreate == false) { + LOGE("%s::Not Yet Created \n", __func__); + return false; + } + + if (mFlagConnected == true) { + LOGD("%s::Already Connected.. \n", __func__); + return true; + } + + if (mHdmiOutputMode >= HDMI_OUTPUT_MODE_YCBCR && + mHdmiOutputMode <= HDMI_OUTPUT_MODE_DVI) { + if (m_flagHWConnected() == false) { + LOGD("%s::m_flagHWConnected() fail \n", __func__); + return false; + } + +#if defined(BOARD_USES_EDID) + if (!EDIDOpen()) + LOGE("EDIDInit() failed!\n"); + + if (!EDIDRead()) { + LOGE("EDIDRead() failed!\n"); + if (!EDIDClose()) + LOGE("EDIDClose() failed!\n"); + } +#endif + +#if defined(BOARD_USES_CEC) + if (!(mCECThread->mFlagRunning)) + mCECThread->start(); +#endif + } + } + + if (this->setHdmiOutputMode(mHdmiOutputMode, true) == false) + LOGE("%s::setHdmiOutputMode(%d) fail \n", __func__, mHdmiOutputMode); + + if (mHdmiOutputMode >= HDMI_OUTPUT_MODE_YCBCR && + mHdmiOutputMode <= HDMI_OUTPUT_MODE_DVI) { + if (this->setHdmiResolution(mHdmiResolutionValue, true) == false) + LOGE("%s::setHdmiResolution(%d) fail \n", __func__, mHdmiResolutionValue); + + if (this->setHdcpMode(mHdcpMode, false) == false) + LOGE("%s::setHdcpMode(%d) fail \n", __func__, mHdcpMode); + +/* if (this->m_setAudioMode(mAudioMode) == false) + LOGE("%s::m_setAudioMode(%d) fail \n", __func__, mAudioMode); +*/ + mHdmiInfoChange = true; + mFlagConnected = true; + +#if defined(BOARD_USES_EDID) + display_menu(); +#endif + } + + return true; +} + +bool SecHdmi::disconnect(void) +{ +#ifdef DEBUG_MSG_ENABLE + LOGD("%s", __func__); +#endif + + Mutex::Autolock lock(mLock); + + if (mFlagCreate == false) { + LOGE("%s::Not Yet Created \n", __func__); + return false; + } + + if (mFlagConnected == false) { + LOGE("%s::Already Disconnected.. \n", __func__); + return true; + } + + if (mHdmiOutputMode >= HDMI_OUTPUT_MODE_YCBCR && + mHdmiOutputMode <= HDMI_OUTPUT_MODE_DVI) { +#if defined(BOARD_USES_CEC) + if (mCECThread->mFlagRunning) + mCECThread->stop(); +#endif + +#if defined(BOARD_USES_EDID) + if (!EDIDClose()) { + LOGE("EDIDClose() failed!\n"); + return false; + } +#endif + } + + for (int layer = HDMI_LAYER_BASE + 1; layer < HDMI_LAYER_MAX; layer++) { + if (mFlagHdmiStart[layer] == true && m_stopHdmi(layer) == false) { + LOGE("%s::hdmiLayer(%d) layer fail \n", __func__, layer); + return false; + } + } + + mFlagConnected = false; + mPreviousHdmiPresetId = V4L2_DV_1080P60; + + mHdmiOutputMode = DEFAULT_OUPUT_MODE; + mHdmiResolutionValue = DEFAULT_HDMI_RESOLUTION_VALUE; + mHdmiStdId = DEFAULT_HDMI_STD_ID; + mCompositeStd = DEFAULT_COMPOSITE_STD; + mAudioMode = 2; + mCurrentHdmiOutputMode = -1; + mCurrentHdmiResolutionValue = 0; + mCurrentAudioMode = -1; + + return true; +} + +bool SecHdmi::startHdmi(int hdmiLayer) +{ +#ifdef DEBUG_MSG_ENABLE + LOGD("%s", __func__); +#endif + + Mutex::Autolock lock(mLock); + if (mFlagHdmiStart[hdmiLayer] == false && + m_startHdmi(hdmiLayer) == false) { + LOGE("%s::hdmiLayer(%d) fail \n", __func__, hdmiLayer); + return false; + } + return true; +} + +bool SecHdmi::stopHdmi(int hdmiLayer) +{ +#ifdef DEBUG_MSG_ENABLE + LOGD("%s", __func__); +#endif + + Mutex::Autolock lock(mLock); + if (mFlagHdmiStart[hdmiLayer] == true && + m_stopHdmi(hdmiLayer) == false) { + LOGE("%s::hdmiLayer(%d) layer fail \n", __func__, hdmiLayer); + return false; + } + tvout_deinit(); + return true; +} + +bool SecHdmi::flagConnected(void) +{ +#ifdef DEBUG_MSG_ENABLE + LOGD("%s", __func__); +#endif + + Mutex::Autolock lock(mLock); + + if (mFlagCreate == false) { + LOGE("%s::Not Yet Created \n", __func__); + return false; + } + + return mFlagConnected; +} + +bool SecHdmi::flush(int srcW, int srcH, int srcColorFormat, + unsigned int srcYAddr, unsigned int srcCbAddr, unsigned int srcCrAddr, + int dstX, int dstY, + int hdmiLayer, + int num_of_hwc_layer) +{ +#ifdef DEBUG_MSG_ENABLE + LOGD("%s::hdmiLayer=%d", __func__, hdmiLayer); +#endif + + Mutex::Autolock lock(mLock); + +#ifdef DEBUG_MSG_ENABLE + LOGD("%s [srcW = %d, srcH = %d, srcColorFormat = 0x%x, srcYAddr= 0x%x, srcCbAddr = 0x%x, srcCrAddr = 0x%x, dstX = %d, dstY = %d, hdmiLayer = %d, num_of_hwc_layer=%d", + __func__, srcW, srcH, srcColorFormat, + srcYAddr, srcCbAddr, srcCrAddr, + dstX, dstY, hdmiLayer, num_of_hwc_layer); + LOGD("saved param(%d, %d, %d)", + mSrcWidth[hdmiLayer], mSrcHeight[hdmiLayer], mSrcColorFormat[hdmiLayer]); +#endif + + if (mFlagCreate == false) { + LOGE("%s::Not Yet Created", __func__); + return false; + } + + if (srcW != mSrcWidth[hdmiLayer] || + srcH != mSrcHeight[hdmiLayer] || + srcColorFormat != mSrcColorFormat[hdmiLayer] || + mHdmiDstWidth != mHdmiResolutionWidth[hdmiLayer] || + mHdmiDstHeight != mHdmiResolutionHeight[hdmiLayer] || + num_of_hwc_layer != mPreviousNumofHwLayer[hdmiLayer] || + mHdmiInfoChange == true) { +#ifdef DEBUG_MSG_ENABLE + LOGD("m_reset param(%d, %d, %d, %d, %d, %d, %d)", + srcW, mSrcWidth[hdmiLayer], + srcH, mSrcHeight[hdmiLayer], + srcColorFormat, mSrcColorFormat[hdmiLayer], + hdmiLayer); +#endif + if (m_reset(srcW, srcH, dstX, dstY, srcColorFormat, hdmiLayer, num_of_hwc_layer) == false) { + LOGE("%s::m_reset(%d, %d, %d, %d) failed", __func__, srcW, srcH, srcColorFormat, hdmiLayer); + return false; + } + } + + if (srcYAddr == 0) { + unsigned int FB_size = ALIGN(srcW, 16) * ALIGN(srcH, 16) * HDMI_G2D_BUFFER_BPP_SIZE; + + srcYAddr = (unsigned int)mFBaddr + mFBoffset; + srcCbAddr = srcYAddr; + + mFBoffset += FB_size; + if (FB_size < mFBoffset) + mFBoffset = 0; + +#ifdef DEBUG_MSG_ENABLE + LOGD("%s::mFBaddr=0x%08x, srcYAddr=0x%08x, mFBoffset=0x%08x", __func__, mFBaddr, srcYAddr, mFBoffset); +#endif + } + + if (hdmiLayer == HDMI_LAYER_VIDEO) { + if (mSecGscaler.setSrcAddr(srcYAddr, srcCbAddr, srcCrAddr, srcColorFormat) == false) { + LOGE("%s::setSrcAddr(0x%08x, 0x%08x, 0x%08x)", __func__, srcYAddr, srcCbAddr, srcCrAddr); + return false; + } + } else { +#if CHECK_GRAPHIC_LAYER_TIME + nsecs_t start, end; + start = systemTime(); +#endif + + if (num_of_hwc_layer == 0) { /* UI only mode */ + struct v4l2_rect rect; + + if (mG2DUIRotVal == 0 || mG2DUIRotVal == 180) { + hdmi_cal_rect(srcW, srcH, mHdmiDstWidth, mHdmiDstHeight, &rect); + } else { + hdmi_cal_rect(srcH, srcW, mHdmiDstWidth, mHdmiDstHeight, &rect); + } + + rect.left = ALIGN(rect.left, 16); + + if (hdmi_set_graphiclayer(mSubdevMixerFd, mVideodevFd[hdmiLayer], hdmiLayer, + srcColorFormat, + srcW, srcH, + srcYAddr, &mSrcBuffer[hdmiLayer][mSrcIndex[hdmiLayer]], + rect.left, rect.top, + rect.width, rect.height, + mG2DUIRotVal) < 0) + return false; + + } else { // Video Playback + UI Mode + if (hdmi_set_graphiclayer(mSubdevMixerFd, mVideodevFd[hdmiLayer], hdmiLayer, + srcColorFormat, + srcW, srcH, + srcYAddr, &mSrcBuffer[hdmiLayer][mSrcIndex[hdmiLayer]], + dstX, dstY, + mHdmiDstWidth, mHdmiDstHeight, + mG2DUIRotVal) < 0) + return false; + } + +#if CHECK_GRAPHIC_LAYER_TIME + end = systemTime(); + LOGD("[UI] hdmi_gl_set_param[end-start] = %ld ms", long(ns2ms(end)) - long(ns2ms(start))); +#endif + } + + if (mFlagConnected) { + if (mFlagHdmiStart[hdmiLayer] == true) { + if (m_run(hdmiLayer) == false) { + LOGE("%s::m_run(%d) failed", __func__, hdmiLayer); + return false; + } + } + + if (mFlagHdmiStart[hdmiLayer] == false && m_startHdmi(hdmiLayer) == false) { + LOGE("%s::start hdmiLayer(%d) failed", __func__, hdmiLayer); + return false; + } + } + return true; +} + +bool SecHdmi::clear(int hdmiLayer) +{ +#ifdef DEBUG_MSG_ENABLE + LOGD("%s::hdmiLayer = %d", __func__, hdmiLayer); +#endif + + Mutex::Autolock lock(mLock); + + if (mFlagCreate == false) { + LOGE("%s::Not Yet Created \n", __func__); + return false; + } + if (mFlagHdmiStart[hdmiLayer] == true && m_stopHdmi(hdmiLayer) == false) { + LOGE("%s::m_stopHdmi: layer[%d] fail \n", __func__, hdmiLayer); + return false; + } + return true; +} + +void SecHdmi::clearGraphicLayer(int hdmiLayer) +{ + mSrcWidth[hdmiLayer] = 0; + mSrcHeight[hdmiLayer] = 0; + mSrcColorFormat[hdmiLayer] = 0; +} + +bool SecHdmi::enableGraphicLayer(int hdmiLayer) +{ + Mutex::Autolock lock(mLock); +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("%s::hdmiLayer(%d)",__func__, hdmiLayer); +#endif + switch (hdmiLayer) { + case HDMI_LAYER_VIDEO: + case HDMI_LAYER_GRAPHIC_0: + case HDMI_LAYER_GRAPHIC_1: + mFlagLayerEnable[hdmiLayer] = true; + if (mFlagConnected == true) + m_startHdmi(hdmiLayer); + break; + default: + return false; + } + return true; +} + +bool SecHdmi::disableGraphicLayer(int hdmiLayer) +{ + Mutex::Autolock lock(mLock); +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("%s::hdmiLayer(%d)",__func__, hdmiLayer); +#endif + switch (hdmiLayer) { + case HDMI_LAYER_VIDEO: + case HDMI_LAYER_GRAPHIC_0: + case HDMI_LAYER_GRAPHIC_1: + if (mFlagConnected == true && mFlagLayerEnable[hdmiLayer]) + if (m_stopHdmi(hdmiLayer) == false ) + LOGE("%s::m_stopHdmi: layer[%d] fail \n", __func__, hdmiLayer); + + mFlagLayerEnable[hdmiLayer] = false; + break; + default: + return false; + } + return true; +} + +bool SecHdmi::setHdmiOutputMode(int hdmiOutputMode, bool forceRun) +{ +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("%s::hdmiOutputMode = %d, forceRun = %d", __func__, hdmiOutputMode, forceRun); +#endif + + Mutex::Autolock lock(mLock); + + if (mFlagCreate == false) { + LOGE("%s::Not Yet Created \n", __func__); + return false; + } + + if (forceRun == false && mHdmiOutputMode == hdmiOutputMode) { +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("%s::same hdmiOutputMode(%d) \n", __func__, hdmiOutputMode); +#endif + return true; + } + + int newHdmiOutputMode = hdmiOutputMode; + + int v4l2OutputType = hdmi_outputmode_2_v4l2_output_type(hdmiOutputMode); + if (v4l2OutputType < 0) { + LOGD("%s::hdmi_outputmode_2_v4l2_output_type(%d) fail\n", __func__, hdmiOutputMode); + return false; + } + +#if defined(BOARD_USES_EDID) + int newV4l2OutputType = hdmi_check_output_mode(v4l2OutputType); + if (newV4l2OutputType != v4l2OutputType) { + newHdmiOutputMode = hdmi_v4l2_output_type_2_outputmode(newV4l2OutputType); + if (newHdmiOutputMode < 0) { + LOGD("%s::hdmi_v4l2_output_type_2_outputmode(%d) fail\n", __func__, newV4l2OutputType); + return false; + } + + LOGD("%s::calibration mode(%d -> %d)... \n", __func__, hdmiOutputMode, newHdmiOutputMode); + mHdmiInfoChange = true; + } +#endif + + if (mHdmiOutputMode != newHdmiOutputMode) { + mHdmiOutputMode = newHdmiOutputMode; + mHdmiInfoChange = true; + } + + return true; +} + +bool SecHdmi::setHdmiResolution(unsigned int hdmiResolutionValue, bool forceRun) +{ +#ifdef DEBUG_MSG_ENABLE + LOGD("%s::hdmiResolutionValue = %d, forceRun = %d", __func__, hdmiResolutionValue, forceRun); +#endif + + Mutex::Autolock lock(mLock); + + if (mFlagCreate == false) { + LOGE("%s::Not Yet Created \n", __func__); + return false; + } + + if (forceRun == false && mHdmiResolutionValue == hdmiResolutionValue) { +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("%s::same hdmiResolutionValue(%d) \n", __func__, hdmiResolutionValue); +#endif + return true; + } + + unsigned int newHdmiResolutionValue = hdmiResolutionValue; + int w = 0; + int h = 0; + v4l2_std_id std_id; + __u32 preset_id; + +#if defined(BOARD_USES_EDID) + // find perfect resolutions.. + if (hdmi_resolution_2_std_id(newHdmiResolutionValue, &w, &h, &std_id, &preset_id) < 0 || + hdmi_check_resolution(std_id) < 0) { + bool flagFoundIndex = false; + int resolutionValueIndex = m_resolutionValueIndex(newHdmiResolutionValue); + + for (int i = resolutionValueIndex + 1; i < mHdmiSizeOfResolutionValueList; i++) { + if (hdmi_resolution_2_std_id(mHdmiResolutionValueList[i], &w, &h, &std_id, &preset_id) == 0 && + hdmi_check_resolution(std_id) == 0) { + newHdmiResolutionValue = mHdmiResolutionValueList[i]; + flagFoundIndex = true; + break; + } + } + + if (flagFoundIndex == false) { + LOGE("%s::hdmi cannot control this resolution(%d) fail \n", __func__, hdmiResolutionValue); + // Set resolution to 480P + newHdmiResolutionValue = mHdmiResolutionValueList[mHdmiSizeOfResolutionValueList-2]; + } else { + LOGD("%s::HDMI resolutions size is calibrated(%d -> %d)..\n", __func__, hdmiResolutionValue, newHdmiResolutionValue); + } + } else { +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("%s::find resolutions(%d) at once\n", __func__, hdmiResolutionValue); +#endif + } +#endif + + if (mHdmiResolutionValue != newHdmiResolutionValue) { + mHdmiResolutionValue = newHdmiResolutionValue; + mHdmiInfoChange = true; + } + + return true; +} + +bool SecHdmi::setHdcpMode(bool hdcpMode, bool forceRun) +{ +#ifdef DEBUG_MSG_ENABLE + LOGD("%s", __func__); +#endif + + Mutex::Autolock lock(mLock); + + if (mFlagCreate == false) { + LOGE("%s::Not Yet Created \n", __func__); + return false; + } + + if (forceRun == false && mHdcpMode == hdcpMode) { +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("%s::same hdcpMode(%d) \n", __func__, hdcpMode); +#endif + return true; + } + + mHdcpMode = hdcpMode; + mHdmiInfoChange = true; + + return true; +} + +bool SecHdmi::setUIRotation(unsigned int rotVal, unsigned int hwcLayer) +{ +#ifdef DEBUG_MSG_ENABLE + LOGD("%s", __func__); +#endif + + Mutex::Autolock lock(mLock); + + if (mFlagCreate == false) { + LOGE("%s::Not Yet Created \n", __func__); + return false; + } + + if (rotVal % 90 != 0) { + LOGE("%s::Invalid rotation value(%d)", __func__, rotVal); + return false; + } + + /* G2D rotation */ + if (rotVal != mG2DUIRotVal) { + mG2DUIRotVal = rotVal; + mHdmiInfoChange = true; + } + + /* FIMC rotation */ + if (hwcLayer == 0) { /* Rotate in UI only mode */ + if (rotVal != mUIRotVal) { + mSecGscaler.setRotVal(rotVal); + mUIRotVal = rotVal; + mHdmiInfoChange = true; + } + } else { /* Don't rotate video layer when video is played. */ + rotVal = 0; + if (rotVal != mUIRotVal) { + mSecGscaler.setRotVal(rotVal); + mUIRotVal = rotVal; + mHdmiInfoChange = true; + } + } + + return true; +} + +bool SecHdmi::setDisplaySize(int width, int height) +{ + mDisplayWidth = width; + mDisplayHeight = height; + + return true; +} + +void SecHdmi::setDisplayInfo(int srcW, int srcH, int srcColorFormat, + unsigned int srcYAddr, unsigned int srcCbAddr, + int dstX, int dstY, + int hdmiLayer, + int num_of_hwc_layer) +{ +#ifdef DEBUG_MSG_ENABLE +LOGD("%s [srcW = %d, srcH = %d, srcColorFormat = 0x%x, srcYAddr= 0x%x, srcCbAddr = 0x%x, dstX = %d, dstY = %d, hdmiLayer = %d", + __func__, srcW, srcH, srcColorFormat, srcYAddr, srcCbAddr, dstX, dstY, hdmiLayer); +#endif + + mCurrentsrcW = srcW; + mCurrentsrcH = srcH; + mCurrentsrcColorFormat = srcColorFormat; + mCurrentsrcYAddr = srcYAddr; + mCurrentsrcCbAddr = srcCbAddr, + mCurrentdstX = dstX; + mCurrentdstY = dstY; + mCurrenthdmiLayer = hdmiLayer; + mCurrentNumOfHWCLayer = num_of_hwc_layer; + + return; +} + +bool SecHdmi::m_setupLink(void) +{ +#ifdef DEBUG_MSG_ENABLE + LOGD("%s", __func__); +#endif + int ret; + char node[32]; + char subdevname[32]; + char videodevname[32]; + + struct v4l2_capability v4l2cap; + struct media_entity_desc entity_desc; + + sprintf(node, "%s%d", PFX_NODE_MEDIADEV, 0); + mMediadevFd = open(node, O_RDWR); + if (mMediadevFd < 0) { + LOGE("%s::open(%s) failed", __func__, node); + goto err; + } + + /* open subdev fd */ + sprintf(subdevname, PFX_ENTITY_SUBDEV_MIXER, 0); + for (__u32 id = 0; ; id = entity_desc.id) { + entity_desc.id = id | MEDIA_ENT_ID_FLAG_NEXT; + + if (ioctl(mMediadevFd, MEDIA_IOC_ENUM_ENTITIES, &entity_desc) < 0) { + if (errno == EINVAL) { + LOGD("%s::MEDIA_IOC_ENUM_ENTITIES ended", __func__); + break; + } + LOGE("%s::MEDIA_IOC_ENUM_ENTITIES failed", __func__); + goto err; + } + LOGD("%s::entity_desc.id=%d, .minor=%d .name=%s", __func__, entity_desc.id, entity_desc.v4l.minor, entity_desc.name); + + if (strncmp(entity_desc.name, subdevname, strlen(subdevname)) == 0) + mMixerSubdevEntity = entity_desc.id; + } + + mlink_desc.source.entity = mSecGscaler.getSubdevEntity(); + mlink_desc.source.index = GSCALER_SUBDEV_PAD_SOURCE; + mlink_desc.source.flags = MEDIA_PAD_FL_SOURCE; + + mlink_desc.sink.entity = mMixerSubdevEntity; + mlink_desc.sink.index = MIXER_V_SUBDEV_PAD_SINK; + mlink_desc.sink.flags = MEDIA_PAD_FL_SINK; + mlink_desc.flags = MEDIA_LNK_FL_ENABLED; + +#ifdef DEBUG_MSG_ENABLE + LOGD("%s::mlink_desc.source.entity=%02d, .pad=%d", __func__, mlink_desc.source.entity, mlink_desc.source.index); + LOGD("%s::mlink_desc.sink.entity =%02d, .pad=%d", __func__, mlink_desc.sink.entity, mlink_desc.sink.index); +#endif + + if (ioctl(mMediadevFd, MEDIA_IOC_SETUP_LINK, &mlink_desc) < 0) { + LOGE("%s::MEDIA_IOC_SETUP_LINK [src.entity=%d->sink.entity=%d] failed", __func__, mlink_desc.source.entity, mlink_desc.sink.entity); + goto err; + } + + sprintf(node, "%s%d", PFX_NODE_SUBDEV, 4); // Mixer0 minor=132 /dev/v4l-subdev4 // need to modify //carrotsm + mSubdevMixerFd = open(node, O_RDWR, 0); + if (mSubdevMixerFd < 0) { + LOGE("%s::open(%s) failed", __func__, node); + goto err; + } + + if (0 < mMediadevFd) + close(mMediadevFd); + mMediadevFd = -1; + + return true; + +err : + + if (0 < mMediadevFd) + close(mMediadevFd); + + if (0 < mSubdevMixerFd) + close(mSubdevMixerFd); + + mMediadevFd = -1; + mSubdevMixerFd = -1; + + return false; +} + +bool SecHdmi::m_openLayer(int layer) +{ +#ifdef DEBUG_MSG_ENABLE + LOGD("%s::layer=%d", __func__, layer); +#endif + char node[32]; + + switch (layer) { + case HDMI_LAYER_VIDEO: + mVideodevFd[layer] = mSecGscaler.getVideodevFd(); + + if (0 < mVideodevFd[layer]) { + LOGD("%s::Layer[%d] device already opened", __func__, layer); + return true; + } + + if (mSecGscaler.openVideodevFd() == false) + LOGE("%s::open(%s) failed", __func__, node); + else + mVideodevFd[layer] = mSecGscaler.getVideodevFd(); + + goto open_success; + break; + case HDMI_LAYER_GRAPHIC_0: + sprintf(node, "%s", TVOUT0_DEV_G0); + break; + case HDMI_LAYER_GRAPHIC_1: + sprintf(node, "%s", TVOUT0_DEV_G1); + break; + default: + LOGE("%s::unmatched layer[%d]", __func__, layer); + return false; + break; + } + + mVideodevFd[layer] = open(node, O_RDWR); + if (mVideodevFd[layer] < 0) { + LOGE("%s::open(%s) failed", __func__, node); + goto err; + } + +open_success : + +#ifdef DEBUG_MSG_ENABLE + LOGD("layer=%d, mVideodevFd=%d", layer, mVideodevFd[layer]); +#endif + + if (tvout_std_v4l2_querycap(mVideodevFd[layer], node) < 0 ) { + LOGE("%s::tvout_std_v4l2_querycap failed", __func__); + goto err; + } + + return true; + +err : + + if (0 < mVideodevFd[layer]) + close(mVideodevFd[layer]); + + mVideodevFd[layer] = -1; + + return false; + +} + +bool SecHdmi::m_closeLayer(int layer) +{ +#ifdef DEBUG_MSG_ENABLE + LOGD("%s::layer=%d", __func__, layer); +#endif + switch (layer) { + case HDMI_LAYER_VIDEO: + mVideodevFd[layer] = mSecGscaler.getVideodevFd(); + + if (mVideodevFd[layer] < 0) { + LOGD("%s::Layer[%d] device already closed", __func__, layer); + return true; + } else { + mSecGscaler.closeVideodevFd(); + mVideodevFd[layer] = mSecGscaler.getVideodevFd(); + } + goto close_success; + break; + case HDMI_LAYER_GRAPHIC_0: + case HDMI_LAYER_GRAPHIC_1: + /* clear buffer */ + if (0 < mVideodevFd[layer]) { + if (tvout_std_v4l2_reqbuf(mVideodevFd[layer], V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, V4L2_MEMORY_USERPTR, 0) < 0) { + LOGE("%s::tvout_std_v4l2_reqbuf(buf_num=%d)[graphic layer] failed", __func__, 0); + return -1; + } + } + break; + default: + LOGE("%s::unmatched layer[%d]", __func__, layer); + return false; + break; + } + + if (0 < mVideodevFd[layer]) { + if (close(mVideodevFd[layer]) < 0) { + LOGE("%s::close %d layer failed", __func__, layer); + return false; + } + } + + mVideodevFd[layer] = -1; + +close_success : + + return true; +} + +bool SecHdmi::m_reset(int w, int h, int dstX, int dstY, int colorFormat, int hdmiLayer, int num_of_hwc_layer) +{ +#ifdef DEBUG_MSG_ENABLE + LOGD("%s::w=%d, h=%d, dstX=%d, dstY=%d, colorFormat=%d, hdmiLayer=%d, num_of_hwc_layer=%d", + __func__, w, h, dstX, dstY, colorFormat, hdmiLayer, num_of_hwc_layer); +#endif + + v4l2_std_id std_id = 0; + + int srcW = w; + int srcH = h; + int dstW = 0; + int dstH = 0; + + if (mFlagHdmiStart[hdmiLayer] == true && m_stopHdmi(hdmiLayer) == false) { + LOGE("%s::m_stopHdmi: layer[%d] failed", __func__, hdmiLayer); + return false; + } + + if (m_closeLayer(hdmiLayer) == false) { + LOGE("%s::m_closeLayer: layer[%d] failed", __func__, hdmiLayer); + return false; + } + + if (m_openLayer(hdmiLayer) == false) { + LOGE("%s::m_closeLayer: layer[%d] failed", __func__, hdmiLayer); + return false; + } + + if (w != mSrcWidth[hdmiLayer] || + h != mSrcHeight[hdmiLayer] || + mHdmiDstWidth != mHdmiResolutionWidth[hdmiLayer] || + mHdmiDstHeight != mHdmiResolutionHeight[hdmiLayer] || + num_of_hwc_layer != mPreviousNumofHwLayer[hdmiLayer] || + colorFormat != mSrcColorFormat[hdmiLayer] || + mHdmiInfoChange == true) { + int preVideoSrcColorFormat = mSrcColorFormat[hdmiLayer]; + int videoSrcColorFormat = colorFormat; + + if (preVideoSrcColorFormat != HAL_PIXEL_FORMAT_YCbCr_420_SP && + preVideoSrcColorFormat != HAL_PIXEL_FORMAT_YCrCb_420_SP && + preVideoSrcColorFormat != HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_SP && + preVideoSrcColorFormat != HAL_PIXEL_FORMAT_CUSTOM_YCrCb_420_SP && + preVideoSrcColorFormat != HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_SP_TILED) { + LOGI("%s: Unsupported preVideoSrcColorFormat = 0x%x", __func__, preVideoSrcColorFormat); + preVideoSrcColorFormat = HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_SP_TILED; + } + + if (hdmiLayer == HDMI_LAYER_VIDEO) { + unsigned int full_wdith = ALIGN(w, 16); + unsigned int full_height = ALIGN(h, 16); + + if (mSecGscaler.setSrcParams(full_wdith, full_height, 0, 0, + (unsigned int*)&w, (unsigned int*)&h, colorFormat, true) == false) { + LOGE("%s::mSecGscaler.setSrcParams(w=%d, h=%d, color=%d) failed", + __func__, w, h, colorFormat); + return false; + } + mGscalerDstColorFormat = V4L2_MBUS_FMT_YUV8_1X24; + + /* calculate destination buffer width and height */ + struct v4l2_rect rect; + + if (mUIRotVal == 0 || mUIRotVal == 180) { + hdmi_cal_rect(srcW, srcH, mHdmiDstWidth, mHdmiDstHeight, &rect); + } else { + hdmi_cal_rect(srcH, srcW, mHdmiDstWidth, mHdmiDstHeight, &rect); + } + + rect.width = ALIGN(rect.width, 16); + + if (mSecGscaler.setDstParams((unsigned int)rect.width, (unsigned int)rect.height, 0, 0, + (unsigned int*)&rect.width, (unsigned int*)&rect.height, mGscalerDstColorFormat, true) == false) { + LOGE("%s::mSecGscaler.setDstParams(w=%d, h=%d, V4L2_MBUS_FMT_YUV8_1X24) failed", + __func__, rect.width, rect.height); + return false; + } + + hdmi_set_videolayer(mSubdevMixerFd, mHdmiDstWidth, mHdmiDstHeight, &rect); + } else { + if (tvout_std_v4l2_s_ctrl(mVideodevFd[hdmiLayer], V4L2_CID_TV_LAYER_BLEND_ENABLE, 1) < 0) { + LOGE("%s::tvout_std_v4l2_s_ctrl [layer=%d] (V4L2_CID_TV_LAYER_BLEND_ENABLE) failed", __func__, hdmiLayer); + return false; + } + + if (tvout_std_v4l2_s_ctrl(mVideodevFd[hdmiLayer], V4L2_CID_TV_PIXEL_BLEND_ENABLE, 1) < 0) { + LOGE("%s::tvout_std_v4l2_s_ctrl [layer=%d] (V4L2_CID_TV_LAYER_BLEND_ENABLE) failed", __func__, hdmiLayer); + return false; + } + + if (tvout_std_v4l2_s_ctrl(mVideodevFd[hdmiLayer], V4L2_CID_TV_LAYER_BLEND_ALPHA, 255) < 0) { + LOGE("%s::tvout_std_v4l2_s_ctrl [layer=%d] (V4L2_CID_TV_LAYER_BLEND_ALPHA) failed", __func__, hdmiLayer); + return false; + } + + struct v4l2_rect rect; + int tempSrcW, tempSrcH; + int gr_frame_size = 0; + + if (mG2DUIRotVal == 0 || mG2DUIRotVal == 180) { + tempSrcW = srcW; + tempSrcH = srcH; + } else { + tempSrcW = srcH; + tempSrcH = srcW; + } + + hdmi_cal_rect(tempSrcW, tempSrcH, mHdmiDstWidth, mHdmiDstHeight, &rect); + rect.left = ALIGN(rect.left, 16); + + if (num_of_hwc_layer == 0) { /* UI only mode */ + hdmi_set_g_Params(mSubdevMixerFd, mVideodevFd[hdmiLayer], hdmiLayer, + colorFormat, srcW, srcH, + rect.left, rect.top, rect.width, rect.height); + dstW = rect.width; + dstH = rect.height; + } else { /* Video Playback + UI Mode */ + hdmi_set_g_Params(mSubdevMixerFd, mVideodevFd[hdmiLayer], hdmiLayer, + colorFormat, srcW, srcH, + dstX, dstY, mHdmiDstWidth, mHdmiDstHeight); + dstW = mHdmiDstWidth; + dstH = mHdmiDstHeight; + } + +#if defined(BOARD_USES_HDMI_FIMGAPI) + gr_frame_size = dstW * dstH; +#else + gr_frame_size = srcW * srcH; +#endif + for (int buf_index = 0; buf_index < MAX_BUFFERS_MIXER; buf_index++) { + int v4l2ColorFormat = HAL_PIXEL_FORMAT_2_V4L2_PIX(colorFormat); + switch (v4l2ColorFormat) { + case V4L2_PIX_FMT_BGR32: + case V4L2_PIX_FMT_RGB32: + mSrcBuffer[hdmiLayer][buf_index].size.s = gr_frame_size << 2; + break; + case V4L2_PIX_FMT_RGB565X: + mSrcBuffer[hdmiLayer][buf_index].size.s = gr_frame_size << 1; + break; + default: + LOGE("%s::invalid color type", __func__); + return false; + break; + } + } + + } + + if (preVideoSrcColorFormat != videoSrcColorFormat) + mHdmiInfoChange = true; + + mSrcWidth[hdmiLayer] = srcW; + mSrcHeight[hdmiLayer] = srcH; + mSrcColorFormat[hdmiLayer] = colorFormat; + + mHdmiResolutionWidth[hdmiLayer] = mHdmiDstWidth; + mHdmiResolutionHeight[hdmiLayer] = mHdmiDstHeight; + mPreviousNumofHwLayer[hdmiLayer] = num_of_hwc_layer; + +#ifdef DEBUG_MSG_ENABLE + LOGD("m_reset saved param(%d, %d, %d, %d, %d, %d, %d)", + srcW, mSrcWidth[hdmiLayer], \ + srcH, mSrcHeight[hdmiLayer], \ + colorFormat,mSrcColorFormat[hdmiLayer], \ + hdmiLayer); +#endif + } + + if (mHdmiInfoChange == true) { +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("mHdmiInfoChange: %d", mHdmiInfoChange); +#endif + +#if defined(BOARD_USES_CEC) + if (mHdmiOutputMode >= HDMI_OUTPUT_MODE_YCBCR && + mHdmiOutputMode <= HDMI_OUTPUT_MODE_DVI) { + if (mCECThread->mFlagRunning) + mCECThread->stop(); + } +#endif + + if (m_setHdmiOutputMode(mHdmiOutputMode) == false) { + LOGE("%s::m_setHdmiOutputMode() failed", __func__); + return false; + } + if (mHdmiOutputMode == COMPOSITE_OUTPUT_MODE) { + std_id = composite_std_2_v4l2_std_id(mCompositeStd); + if ((int)std_id < 0) { + LOGE("%s::composite_std_2_v4l2_std_id(%d) failed", __func__, mCompositeStd); + return false; + } + if (m_setCompositeResolution(mCompositeStd) == false) { + LOGE("%s::m_setCompositeRsolution() failed", __func__); + return false; + } + } else if (mHdmiOutputMode >= HDMI_OUTPUT_MODE_YCBCR && + mHdmiOutputMode <= HDMI_OUTPUT_MODE_DVI) { + if (m_setHdmiResolution(mHdmiResolutionValue) == false) { + LOGE("%s::m_setHdmiResolution() failed", __func__); + return false; + } + + if (m_setHdcpMode(mHdcpMode) == false) { + LOGE("%s::m_setHdcpMode() failed", __func__); + return false; + } + std_id = mHdmiStdId; + } + + if (mPreviousHdmiPresetId != mHdmiPresetId) { + for (int layer = HDMI_LAYER_BASE + 1; layer < HDMI_LAYER_MAX; layer++) { + if (m_stopHdmi(layer) == false) { + LOGE("%s::m_stopHdmi(%d) failed", __func__, layer); + return false; + } + } + + if (tvout_init(mVideodevFd[HDMI_LAYER_GRAPHIC_0], mHdmiPresetId) < 0) { + LOGE("%s::tvout_init(mHdmiPresetId=%d) failed", __func__, mHdmiPresetId); + return false; + } + mPreviousHdmiPresetId = mHdmiPresetId; + } + + if (mHdmiOutputMode >= HDMI_OUTPUT_MODE_YCBCR && + mHdmiOutputMode <= HDMI_OUTPUT_MODE_DVI) { +#if defined(BOARD_USES_CEC) + if (!(mCECThread->mFlagRunning)) + mCECThread->start(); +#endif + +/* if (m_setAudioMode(mAudioMode) == false) + LOGE("%s::m_setAudioMode() failed", __func__); +*/ + } + + mHdmiInfoChange = false; + + } + + return true; +} + +bool SecHdmi::m_streamOn(int hdmiLayer) +{ +#ifdef DEBUG_MSG_ENABLE + LOGD("%s::hdmiLayer = %d", __func__, hdmiLayer); +#endif + + if (mFlagCreate == false) { + LOGE("%s::Not yet created", __func__); + return false; + } + + if (mFlagHdmiStart[hdmiLayer] == true) { + LOGE("%s::[layer=%d] already streamon", __func__, hdmiLayer); + return true; + } + + switch(hdmiLayer) { + case HDMI_LAYER_GRAPHIC_0: + break; + case HDMI_LAYER_GRAPHIC_1: + break; + default : + LOGE("%s::unmathced layer(%d) failed", __func__, hdmiLayer); + return false; + break; + } + + if (tvout_std_v4l2_qbuf(mVideodevFd[hdmiLayer], V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, V4L2_MEMORY_USERPTR, + mSrcIndex[hdmiLayer], 1, &mSrcBuffer[hdmiLayer][0]) < 0) { + LOGE("%s::gsc_v4l2_queue(index : %d) (mSrcBufNum : %d) failed", __func__, mSrcIndex[hdmiLayer], 1); + return false; + } + + mSrcIndex[hdmiLayer]++; + if (mSrcIndex[hdmiLayer] == MAX_BUFFERS_MIXER) { + if (tvout_std_v4l2_streamon(mVideodevFd[hdmiLayer], V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) < 0) { + LOGE("%s::gsc_v4l2_stream_on() failed", __func__); + return false; + } + mFlagHdmiStart[hdmiLayer] = true; + } + + if (mSrcIndex[hdmiLayer] >= MAX_BUFFERS_MIXER) { + mSrcIndex[hdmiLayer] = 0; + } + + return true; +} + +bool SecHdmi::m_run(int hdmiLayer) +{ +#ifdef DEBUG_MSG_ENABLE + LOGD("%s::hdmiLayer = %d", __func__, hdmiLayer); +#endif + + int buf_index = 0; + + if (mFlagHdmiStart[hdmiLayer] == false || mFlagLayerEnable[hdmiLayer] == false) { + LOGD("%s::HDMI(%d layer) started not yet", __func__, hdmiLayer); + return true; + } + + switch (hdmiLayer) { + case HDMI_LAYER_VIDEO: + if (mSecGscaler.run() == false) { + LOGE("%s::mSecGscaler.draw() failed", __func__); + return false; + } + break; + case HDMI_LAYER_GRAPHIC_0 : + case HDMI_LAYER_GRAPHIC_1 : + if (tvout_std_v4l2_dqbuf(mVideodevFd[hdmiLayer], V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, V4L2_MEMORY_USERPTR, &buf_index, 1) < 0) { + LOGE("%s::tvout_std_v4l2_dqbuf(mNumOfBuf : %d, dqIndex=%d) failed", __func__, 1, buf_index); + return false; + } + + if (tvout_std_v4l2_qbuf(mVideodevFd[hdmiLayer], V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, V4L2_MEMORY_USERPTR, + mSrcIndex[hdmiLayer], 1, &mSrcBuffer[hdmiLayer][mSrcIndex[hdmiLayer]]) < 0) { + LOGE("%s::tvout_std_v4l2_qbuf(mNumOfBuf : %d,mSrcIndex=%d) failed", __func__, 1, mSrcIndex[hdmiLayer]); + return false; + } + + mSrcIndex[hdmiLayer]++; + if (mSrcIndex[hdmiLayer] >= MAX_BUFFERS_MIXER) { + mSrcIndex[hdmiLayer] = 0; + } + + break; + default : + LOGE("%s::unmathced layer(%d) failed", __func__, hdmiLayer); + return false; + break; + } + + return true; +} + +bool SecHdmi::m_startHdmi(int hdmiLayer) +{ +#ifdef DEBUG_MSG_ENABLE + LOGD("%s::hdmiLayer = %d", __func__, hdmiLayer); +#endif + + int buf_index = 0; + + if (mFlagHdmiStart[hdmiLayer] == true) { + LOGD("%s::already HDMI(%d layer) started..", __func__, hdmiLayer); + return true; + } + +#ifdef DEBUG_MSG_ENABLE + LOGD("### %s: hdmiLayer(%d) called", __func__, hdmiLayer); +#endif + switch (hdmiLayer) { + case HDMI_LAYER_VIDEO: + if (mSecGscaler.streamOn() == false) { + LOGE("%s::mSecGscaler.streamOn() failed", __func__); + return false; + } + if (mSecGscaler.getFlagSteamOn() == true) + mFlagHdmiStart[hdmiLayer] = true; + break; + case HDMI_LAYER_GRAPHIC_0 : + case HDMI_LAYER_GRAPHIC_1 : + if (m_streamOn(hdmiLayer) == false) { + LOGE("%s::m_streamOn layer(%d) failed", __func__, hdmiLayer); + return false; + } + break; + default : + LOGE("%s::unmathced layer(%d) failed", __func__, hdmiLayer); + return false; + break; + } + return true; +} + +bool SecHdmi::m_stopHdmi(int hdmiLayer) +{ +#ifdef DEBUG_MSG_ENABLE + LOGD("%s::hdmiLayer = %d", __func__, hdmiLayer); +#endif + + if (mFlagHdmiStart[hdmiLayer] == false) { + LOGD("%s::already HDMI(%d layer) stopped..", __func__, hdmiLayer); + return true; + } + +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("### %s : layer[%d] called", __func__, hdmiLayer); +#endif + + switch (hdmiLayer) { + case HDMI_LAYER_VIDEO: + if (mSecGscaler.streamOff() == false) { + LOGE("%s::mSecGscaler.streamOff() failed", __func__); + return false; + } + mFlagHdmiStart[hdmiLayer] = false; + break; + case HDMI_LAYER_GRAPHIC_1 : + case HDMI_LAYER_GRAPHIC_0 : +#if defined(BOARD_USES_HDMI_FIMGAPI) + cur_g2d_address = 0; +#endif + if (tvout_std_v4l2_streamoff(mVideodevFd[hdmiLayer], V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) < 0) { + LOGE("%s::tvout_std_v4l2_streamon layer(%d) failed", __func__, hdmiLayer); + return false; + } + + mSrcIndex[hdmiLayer] = 0; + mFlagHdmiStart[hdmiLayer] = false; + break; + default : + LOGE("%s::unmathced layer(%d) failed", __func__, hdmiLayer); + return false; + break; + } + + return true; +} + +bool SecHdmi::m_setHdmiOutputMode(int hdmiOutputMode) +{ +#ifdef DEBUG_MSG_ENABLE + LOGD("%s", __func__); +#endif + + if (hdmiOutputMode == mCurrentHdmiOutputMode) { +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("%s::same hdmiOutputMode(%d) \n", __func__, hdmiOutputMode); +#endif + return true; + } + +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("### %s called\n", __func__); +#endif + + int v4l2OutputType = hdmi_outputmode_2_v4l2_output_type(hdmiOutputMode); + if (v4l2OutputType < 0) { + LOGE("%s::hdmi_outputmode_2_v4l2_output_type(%d) fail\n", __func__, hdmiOutputMode); + return false; + } + + output_type = v4l2OutputType; + + mCurrentHdmiOutputMode = hdmiOutputMode; + + return true; +} + +bool SecHdmi::m_setCompositeResolution(unsigned int compositeStdId) +{ +#ifdef DEBUG_MSG_ENABLE + LOGD("%s", __func__); +#endif + +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("### %s called\n", __func__); +#endif + + int w = 0; + int h = 0; + + if (mHdmiOutputMode != COMPOSITE_OUTPUT_MODE) { + LOGE("%s::not supported output type \n", __func__); + return false; + } + + switch (compositeStdId) { + case COMPOSITE_STD_NTSC_M: + case COMPOSITE_STD_NTSC_443: + w = 704; + h = 480; + break; + case COMPOSITE_STD_PAL_BDGHI: + case COMPOSITE_STD_PAL_M: + case COMPOSITE_STD_PAL_N: + case COMPOSITE_STD_PAL_Nc: + case COMPOSITE_STD_PAL_60: + w = 704; + h = 576; + break; + default: + LOGE("%s::unmathced composite_std(%d)", __func__, compositeStdId); + return false; + } + + t_std_id = composite_std_2_v4l2_std_id(mCompositeStd); + + mHdmiDstWidth = w; + mHdmiDstHeight = h; + + mCurrentHdmiResolutionValue = -1; + return true; +} + +bool SecHdmi::m_setHdmiResolution(unsigned int hdmiResolutionValue) +{ +#ifdef DEBUG_MSG_ENABLE + LOGD("%s", __func__); +#endif + + if (hdmiResolutionValue == mCurrentHdmiResolutionValue) { +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("%s::same hdmiResolutionValue(%d) \n", __func__, hdmiResolutionValue); +#endif + return true; + } + +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("### %s called\n", __func__); +#endif + + int w = 0; + int h = 0; + + v4l2_std_id std_id; + if (mHdmiOutputMode >= HDMI_OUTPUT_MODE_YCBCR && + mHdmiOutputMode <= HDMI_OUTPUT_MODE_DVI) { + if (hdmi_resolution_2_std_id(hdmiResolutionValue, &w, &h, &std_id, &mHdmiPresetId) < 0) { + LOGE("%s::hdmi_resolution_2_std_id(%d) fail\n", __func__, hdmiResolutionValue); + return false; + } + mHdmiStdId = std_id; + } else { + LOGE("%s::not supported output type \n", __func__); + return false; + } + + t_std_id = std_id; + + mHdmiDstWidth = w; + mHdmiDstHeight = h; + + mCurrentHdmiResolutionValue = hdmiResolutionValue; + +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("%s::mHdmiDstWidth = %d, mHdmiDstHeight = %d, mHdmiStdId = 0x%x, hdmiResolutionValue = 0x%x\n", + __func__, + mHdmiDstWidth, + mHdmiDstHeight, + mHdmiStdId, + hdmiResolutionValue); +#endif + + return true; +} + +bool SecHdmi::m_setHdcpMode(bool hdcpMode) +{ +#ifdef DEBUG_MSG_ENABLE + LOGD("%s", __func__); +#endif + + if (hdcpMode == mCurrentHdcpMode) { +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("%s::same hdcpMode(%d) \n", __func__, hdcpMode); +#endif + + return true; + } + +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("### %s called\n", __func__); +#endif + + if (hdcpMode == true) + g_hdcp_en = 1; + else + g_hdcp_en = 0; + + mCurrentHdcpMode = hdcpMode; + + return true; +} + +bool SecHdmi::m_setAudioMode(int audioMode) +{ +#ifdef DEBUG_MSG_ENABLE + LOGD("%s", __func__); +#endif + + if (audioMode == mCurrentAudioMode) { +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("%s::same audioMode(%d) \n", __func__, audioMode); +#endif + return true; + } + +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("### %s called\n", __func__); +#endif + + if (hdmi_check_audio(mVideodevFd[HDMI_LAYER_GRAPHIC_0]) < 0) { + LOGE("%s::hdmi_check_audio() fail \n", __func__); + return false; + } + + mCurrentAudioMode = audioMode; + + return true; +} + +int SecHdmi::m_resolutionValueIndex(unsigned int ResolutionValue) +{ +#ifdef DEBUG_MSG_ENABLE + LOGD("%s", __func__); +#endif + + int index = -1; + + for (int i = 0; i < mHdmiSizeOfResolutionValueList; i++) { + if (mHdmiResolutionValueList[i] == ResolutionValue) { + index = i; + break; + } + } + return index; +} + +bool SecHdmi::m_flagHWConnected(void) +{ +#ifdef DEBUG_MSG_ENABLE + LOGD("%s", __func__); +#endif + +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("### %s called\n", __func__); +#endif + + bool ret = true; + int hdmiStatus = hdmi_cable_status(); + + if (hdmiStatus <= 0) { +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("%s::hdmi_cable_status() fail \n", __func__); +#endif + ret = false; + } else { + ret = true; + } + + return ret; +} + +}; // namespace android diff --git a/exynos5/hal/libhdmi/SecHdmi/SecHdmiCommon.h b/exynos5/hal/libhdmi/SecHdmi/SecHdmiCommon.h new file mode 100644 index 0000000..5ca9e4e --- /dev/null +++ b/exynos5/hal/libhdmi/SecHdmi/SecHdmiCommon.h @@ -0,0 +1,118 @@ +/* + * Copyright@ Samsung Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +** +** @author Sangwoo, Park(sw5771.park@samsung.com) +** @date 2010-09-10 +** +*/ + +//#define LOG_NDEBUG 0 +//#define LOG_TAG "libhdmi" +#include + +#include "../libhdmi/SecHdmi/fimd_api.h" + +//#define DEBUG_MSG_ENABLE +//#define DEBUG_HDMI_HW_LEVEL +//#define BOARD_USES_EDID +//#define BOARD_USES_CEC +//#define SUPPORT_G2D_UI_MODE + +#define DEFAULT_FB (0) +#define MAX_MIXER_NUM (1) +#define MAX_BUFFERS_MIXER (2) +#define MAX_PLANES_MIXER (3) + +#define HDMI_GSCALER_BUF_NUM (3) +#define HDMI_FIMC_BUFFER_BPP_SIZE (1.5) //NV12 Tiled is 1.5 bytes, RGB565 is 2, RGB888 is 4, Default is NV12 Tiled +#define HDMI_G2D_BUFFER_BPP_SIZE (4) //NV12 Tiled is 1.5 bytes, RGB565 is 2, RGB888 is 4 +#define SUPPORT_1080P_FIMC_OUT +#define HDMI_MAX_WIDTH (1920) +#define HDMI_MAX_HEIGHT (1080) + +#define ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1)) + +#if defined(STD_NTSC_M) + #define DEFAULT_OUPUT_MODE (COMPOSITE_OUTPUT_MODE) + #define DEFAULT_HDMI_RESOLUTION_VALUE (1080960) // 1080P_60 + #define DEFAULT_HDMI_STD_ID (V4L2_STD_1080P_60) + #define DEFALULT_DISPLAY_WIDTH (720) + #define DEFALULT_DISPLAY_HEIGHT (480) + #define DEFAULT_COMPOSITE_STD (COMPOSITE_STD_NTSC_M) +#elif (STD_1080P) + #define DEFAULT_OUPUT_MODE (HDMI_OUTPUT_MODE_RGB) + #define DEFAULT_HDMI_RESOLUTION_VALUE (1080960) // 1080P_60 + #define DEFAULT_HDMI_STD_ID (V4L2_STD_1080P_60) + #define DEFALULT_DISPLAY_WIDTH (1920) + #define DEFALULT_DISPLAY_HEIGHT (1080) + #define DEFAULT_COMPOSITE_STD (COMPOSITE_STD_NTSC_M) +#elif defined(STD_720P) + #define DEFAULT_OUPUT_MODE (HDMI_OUTPUT_MODE_YCBCR) + #define DEFAULT_HDMI_RESOLUTION_VALUE (720960) // 720P_60 + #define DEFAULT_HDMI_STD_ID (V4L2_STD_720P_60) + #define DEFALULT_DISPLAY_WIDTH (1280) + #define DEFALULT_DISPLAY_HEIGHT (720) + #define DEFAULT_COMPOSITE_STD (COMPOSITE_STD_NTSC_M) +#elif defined(STD_480P) + #define DEFAULT_OUPUT_MODE (HDMI_OUTPUT_MODE_YCBCR) + #define DEFAULT_HDMI_RESOLUTION_VALUE (4809601) // 480P_60_4_3 + #define DEFAULT_HDMI_STD_ID (V4L2_STD_480P_60_16_9) + #define DEFALULT_DISPLAY_WIDTH (720) + #define DEFALULT_DISPLAY_HEIGHT (480) + #define DEFAULT_COMPOSITE_STD (COMPOSITE_STD_NTSC_M) +#else + #define DEFAULT_OUPUT_MODE (HDMI_OUTPUT_MODE_YCBCR) + #define DEFAULT_HDMI_RESOLUTION_VALUE (4809602) // 480P_60_4_3 + #define DEFAULT_HDMI_STD_ID (V4L2_STD_480P_60_4_3) + #define DEFALULT_DISPLAY_WIDTH (720) + #define DEFALULT_DISPLAY_HEIGHT (480) + #define DEFAULT_COMPOSITE_STD (COMPOSITE_STD_NTSC_M) +#endif + +enum hdp_cable_status { + HPD_CABLE_OUT = 0, // HPD_CABLE_OUT indicates HDMI cable out. + HPD_CABLE_IN // HPD_CABLE_IN indicates HDMI cable in. +}; + +enum state { + OFF = 0, + ON = 1, + NOT_SUPPORT = 2, +}; + +enum tv_mode { + HDMI_OUTPUT_MODE_YCBCR = 0, + HDMI_OUTPUT_MODE_RGB = 1, + HDMI_OUTPUT_MODE_DVI = 2, + COMPOSITE_OUTPUT_MODE = 3 +}; + +enum composite_std { + COMPOSITE_STD_NTSC_M = 0, + COMPOSITE_STD_PAL_BDGHI = 1, + COMPOSITE_STD_PAL_M = 2, + COMPOSITE_STD_PAL_N = 3, + COMPOSITE_STD_PAL_Nc = 4, + COMPOSITE_STD_PAL_60 = 5, + COMPOSITE_STD_NTSC_443 = 6 +}; + +enum hdmi_layer { + HDMI_LAYER_BASE = 0, + HDMI_LAYER_VIDEO, + HDMI_LAYER_GRAPHIC_0, + HDMI_LAYER_GRAPHIC_1, + HDMI_LAYER_MAX, +}; diff --git a/exynos5/hal/libhdmi/SecHdmi/SecHdmiV4L2Utils.cpp b/exynos5/hal/libhdmi/SecHdmi/SecHdmiV4L2Utils.cpp new file mode 100644 index 0000000..ac4717b --- /dev/null +++ b/exynos5/hal/libhdmi/SecHdmi/SecHdmiV4L2Utils.cpp @@ -0,0 +1,1350 @@ +/* + * Copyright@ Samsung Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +//#define LOG_NDEBUG 0 +//#define LOG_TAG "libhdmi" +//#define DEBUG_HDMI_HW_LEVEL +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sec_utils_v4l2.h" +#include "s5p_tvout_v4l2.h" + +#include "videodev2.h" + +#if defined(BOARD_USES_HDMI_FIMGAPI) +#include "sec_g2d_4x.h" +#include "FimgApi.h" +#endif + +#include "audio.h" +#include "video.h" +#include "../libhdmi/libsForhdmi/libedid/libedid.h" +#include "../libhdmi/libsForhdmi/libcec/libcec.h" + +#include "SecGscaler.h" +#include "SecHdmiCommon.h" +#include "SecHdmiV4L2Utils.h" + +namespace android { + +unsigned int output_type = V4L2_OUTPUT_TYPE_DIGITAL; +v4l2_std_id t_std_id = V4L2_STD_1080P_30; +int g_hpd_state = HPD_CABLE_OUT; +unsigned int g_hdcp_en = 0; + +#if defined(BOARD_USES_HDMI_FIMGAPI) +unsigned int g2d_reserved_memory0 = 0; +unsigned int g2d_reserved_memory1 = 0; +unsigned int g2d_reserved_memory_size = 0; +unsigned int cur_g2d_address = 0; +#endif + +void display_menu(void) +{ + struct HDMIVideoParameter video; + struct HDMIAudioParameter audio; + +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("%s", __func__); +#endif + + audio.formatCode = LPCM_FORMAT; + audio.outPacket = HDMI_ASP; + audio.channelNum = CH_2; + audio.sampleFreq = SF_44KHZ; + + LOGI("=============== HDMI Audio =============\n"); + + if (EDIDAudioModeSupport(&audio)) + LOGI("= 2CH_PCM 44100Hz audio supported =\n"); + + LOGI("========= HDMI Mode & Color Space =======\n"); + + video.mode = HDMI; + if (EDIDHDMIModeSupport(&video)) { + video.colorSpace = HDMI_CS_YCBCR444; + if (EDIDColorSpaceSupport(&video)) + LOGI("= 1. HDMI(YCbCr) =\n"); + + video.colorSpace = HDMI_CS_RGB; + if (EDIDColorSpaceSupport(&video)) + LOGI("= 2. HDMI(RGB) =\n"); + } else { + video.mode = DVI; + if (EDIDHDMIModeSupport(&video)) + LOGI("= 3. DVI =\n"); + } + + LOGI("=========== HDMI Rseolution ========\n"); + + /* 480P */ + video.resolution = v720x480p_60Hz; + video.pixelAspectRatio = HDMI_PIXEL_RATIO_16_9; + video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT; + if (EDIDVideoResolutionSupport(&video)) + LOGI("= 4. 480P_60_16_9 (0x04000000) =\n"); + + video.resolution = v640x480p_60Hz; + video.pixelAspectRatio = HDMI_PIXEL_RATIO_4_3; + video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT; + if (EDIDVideoResolutionSupport(&video)) + LOGI("= 5. 480P_60_4_3 (0x05000000) =\n"); + + /* 576P */ + video.resolution = v720x576p_50Hz; + video.pixelAspectRatio = HDMI_PIXEL_RATIO_16_9; + video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT; + if (EDIDVideoResolutionSupport(&video)) + LOGI("= 6. 576P_50_16_9 (0x06000000) =\n"); + + video.pixelAspectRatio = HDMI_PIXEL_RATIO_4_3; + video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT; + if (EDIDVideoResolutionSupport(&video)) + LOGI("= 7. 576P_50_4_3 (0x07000000) =\n"); + + /* 720P 60 */ + video.resolution = v1280x720p_60Hz; + video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT; + if (EDIDVideoResolutionSupport(&video)) + LOGI("= 8. 720P_60 (0x08000000) =\n"); + + /* 720P_50 */ + video.resolution = v1280x720p_50Hz; + video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT; + if (EDIDVideoResolutionSupport(&video)) + LOGI("= 9. 720P_50 (0x09000000) =\n"); + + /* 1080P_60 */ + video.resolution = v1920x1080p_60Hz; + video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT; + if (EDIDVideoResolutionSupport(&video)) + LOGI("= a. 1080P_60 (0x0a000000) =\n"); + + /* 1080P_50 */ + video.resolution = v1920x1080p_50Hz; + video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT; + if (EDIDVideoResolutionSupport(&video)) + LOGI("= b. 1080P_50 (0x0b000000) =\n"); + + /* 1080I_60 */ + video.resolution = v1920x1080i_60Hz; + video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT; + if (EDIDVideoResolutionSupport(&video)) + LOGI("= c. 1080I_60 (0x0c000000) =\n"); + + /* 1080I_50 */ + video.resolution = v1920x1080i_50Hz; + video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT; + if (EDIDVideoResolutionSupport(&video)) + LOGI("= d. 1080I_50 (0x0d000000) =\n"); + + /* 1080P_30 */ + video.resolution = v1920x1080p_30Hz; + video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT; + if (EDIDVideoResolutionSupport(&video)) + LOGI("= e. 1080P_30 (0x12000000) =\n"); + + LOGI("=========== HDMI 3D Format ========\n"); + + /* 720P_60_SBS_HALF */ + video.resolution = v1280x720p_60Hz; + video.hdmi_3d_format = HDMI_3D_SSH_FORMAT; + if (EDIDVideoResolutionSupport(&video)) + LOGI("= f. 720P_60_SBS_HALF (0x13000000) =\n"); + + /* 720P_59_SBS_HALF */ + video.resolution = v1280x720p_60Hz; + video.hdmi_3d_format = HDMI_3D_SSH_FORMAT; + if (EDIDVideoResolutionSupport(&video)) + LOGI("= 10. 720P_59_SBS_HALF (0x14000000) =\n"); + + /* 720P_50_TB */ + video.resolution = v1280x720p_50Hz; + video.hdmi_3d_format = HDMI_3D_TB_FORMAT; + if (EDIDVideoResolutionSupport(&video)) + LOGI("= 11. 720P_50_TB (0x15000000) =\n"); + + /* 1080P_24_TB */ + video.resolution = v1920x1080p_24Hz; + video.hdmi_3d_format = HDMI_3D_TB_FORMAT; + if (EDIDVideoResolutionSupport(&video)) + LOGI("= 12. 1080P_24_TB (0x16000000) =\n"); + + /* 1080P_23_TB */ + video.resolution = v1920x1080p_24Hz; + video.hdmi_3d_format = HDMI_3D_TB_FORMAT; + if (EDIDVideoResolutionSupport(&video)) + LOGI("= 13. 1080P_24_TB (0x17000000) =\n"); + LOGI("=========================================\n"); +} + +int tvout_init(int fd_tvout, __u32 preset_id) +{ +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("%s::preset_id = 0x%x", __func__, preset_id); +#endif + + int ret; + struct v4l2_output output; + struct v4l2_dv_preset preset; + + unsigned int matched = 0, i = 0; + int output_index; + + if (fd_tvout <= 0) { + fd_tvout = open(TVOUT0_DEV_G0, O_RDWR); + if (fd_tvout < 0) { + LOGE("%s::fd_tvout open failed", __func__); + return -1; + } + } +/* + if (output_type >= V4L2_OUTPUT_TYPE_DIGITAL && + output_type <= V4L2_OUTPUT_TYPE_DVI) + if (ioctl(fd_tvout, VIDIOC_HDCP_ENABLE, g_hdcp_en) < 0) + LOGE("%s::VIDIOC_HDCP_ENABLE failed %d", __func__, errno); +*/ + i = 0; + + do { + output.index = i; + ret = tvout_v4l2_enum_output(fd_tvout, &output); + LOGV("%s::output_type=%d output.index=%d .name=%s", __func__, output_type, output.index, output.name); + if (output.type == output_type) { + matched = 1; + break; + } + i++; + } while (ret >=0); +/* + if (!matched) { + LOGE("%s::no matched output type [type=0x%08x]", __func__, output_type); + return -1; + } + + tvout_v4l2_s_output(fd_tvout, output.index); + output_index = 0; + tvout_v4l2_g_output(fd_tvout, &output_index); +*/ + +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("%s::input preset_id=0x%08x", __func__, preset_id); +#endif + + if (output.capabilities & V4L2_OUT_CAP_PRESETS) { + tvout_std_v4l2_enum_dv_presets(fd_tvout); + preset.preset = preset_id; + if (tvout_std_v4l2_s_dv_preset(fd_tvout, &preset) < 0 ) { + LOGE("%s::tvout_std_v4l2_s_dv_preset failed", __func__); + return -1; + } + } + + return fd_tvout; +} + +int tvout_deinit() +{ +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("%s", __func__); +#endif + + return 0; +} + +int tvout_std_v4l2_querycap(int fd, char *node) +{ +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("%s", __func__); +#endif + struct v4l2_capability v4l2cap; + + if (ioctl(fd, VIDIOC_QUERYCAP, &v4l2cap) < 0) { + LOGE("%s::VIDIOC_QUERYCAP failed", __func__); + return -1; + } + + if (!(v4l2cap.capabilities & V4L2_CAP_STREAMING)) { + LOGE("%s::%s is not support streaming", __func__, node); + return -1; + } + + if (!(v4l2cap.capabilities & V4L2_CAP_VIDEO_OUTPUT_MPLANE)) { + LOGE("%s::%s is not support video output mplane", __func__, node); + return -1; + } + + return 0; +} + +int tvout_std_v4l2_s_fmt(int fd, enum v4l2_buf_type type, enum v4l2_field field, int w, int h, int colorformat, int num_planes) +{ +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("%s", __func__); +#endif + + struct v4l2_format fmt; + + fmt.type = type; + if (ioctl(fd, VIDIOC_G_FMT, &fmt) < 0) { + LOGE("%s::VIDIOC_G_FMT failed", __func__); + return -1; + } + + switch (fmt.type) { + case V4L2_BUF_TYPE_VIDEO_OUTPUT: + case V4L2_BUF_TYPE_VIDEO_CAPTURE: + fmt.fmt.pix.width = w; + fmt.fmt.pix.height = h; + fmt.fmt.pix.pixelformat = colorformat; + fmt.fmt.pix.field = field; + break; + case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: + case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: + fmt.fmt.pix_mp.width = w; + fmt.fmt.pix_mp.height = h; + fmt.fmt.pix_mp.pixelformat = colorformat; + fmt.fmt.pix_mp.field = field; + fmt.fmt.pix_mp.num_planes = num_planes; + break; + default: + LOGE("%s::invalid buffer type", __func__); + return -1; + break; + } + + if (ioctl(fd, VIDIOC_S_FMT, &fmt) < 0) { + LOGE("%s::VIDIOC_S_FMT failed", __func__); + return -1; + } + + return 0; +} + +int tvout_std_v4l2_s_crop(int fd, enum v4l2_buf_type type, enum v4l2_field, int x, int y, int w, int h) +{ +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("%s", __func__); +#endif + struct v4l2_crop crop; + + crop.type = type; + crop.c.left = x; + crop.c.top = y; + crop.c.width = w; + crop.c.height = h; + + if (ioctl(fd, VIDIOC_S_CROP, &crop) < 0) { + LOGE("%s::VIDIOC_S_CROP (x=%d, y=%d, w=%d, h=%d) failed", + __func__, x, y, w, h); + return -1; + } + + return 0; +} + +int tvout_std_v4l2_s_ctrl(int fd, int id, int value) +{ +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("%s", __func__); +#endif + struct v4l2_control vc; + + vc.id = id; + vc.value = value; + + if (ioctl(fd, VIDIOC_S_CTRL, &vc) < 0) { + LOGE("%s::VIDIOC_S_CTRL (id=%d,value=%d) failed", __func__, id, value); + return -1; + } + + return 0; +} + +int tvout_std_v4l2_reqbuf(int fd, enum v4l2_buf_type type, enum v4l2_memory memory, unsigned int num_bufs) +{ +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("%s", __func__); +#endif + struct v4l2_requestbuffers reqbuf; + + reqbuf.type = type; + reqbuf.memory = memory; + reqbuf.count = num_bufs; + + if (ioctl(fd, VIDIOC_REQBUFS, &reqbuf) < 0) { + LOGE("%s::VIDIOC_REQBUFS failed", __func__); + return -1; + } + + if (reqbuf.count < num_bufs) { + LOGE("%s::VIDIOC_REQBUFS failed ((reqbuf.count(%d) < num_bufs(%d))", + __func__, reqbuf.count, num_bufs); + return -1; + } + + return 0; +} + +int tvout_std_v4l2_querybuf(int fd, enum v4l2_buf_type type, enum v4l2_memory memory, unsigned int buf_index, unsigned int num_planes, SecBuffer *secBuf) +{ +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("%s", __func__); +#endif + struct v4l2_buffer buf; + struct v4l2_plane planes[MAX_PLANES_MIXER]; + + memset(&buf, 0, sizeof(struct v4l2_buffer)); + + for (int i = 0; i < MAX_PLANES_MIXER; i++) + memset(&planes[i], 0, sizeof(struct v4l2_plane)); + + if (MAX_BUFFERS_MIXER <= buf_index || MAX_PLANES_MIXER <= num_planes) { + LOGE("%s::exceed MAX! : buf_index=%d, num_plane=%d", __func__, buf_index, num_planes); + return -1; + } + + buf.type = type; + buf.memory = V4L2_MEMORY_MMAP; + buf.index = buf_index; + buf.length = num_planes; + buf.m.planes = planes; + + if (ioctl(fd, VIDIOC_QUERYBUF, &buf) < 0) { + LOGE("%s::VIDIOC_QUERYBUF failed, plane_cnt=%d", __func__, buf.length); + return -1; + } + + for (unsigned int i = 0; i < num_planes; i++) { + if ((secBuf->virt.extP[i] = (char *)mmap(0, buf.m.planes[i].length, + PROT_READ | PROT_WRITE, MAP_SHARED, fd, buf.m.planes[i].m.mem_offset)) < 0) { + LOGE("%s::mmap failed", __func__); + LOGE("%s::Offset = 0x%x", __func__, buf.m.planes[i].m.mem_offset); + LOGE("%s::Legnth = %d" , __func__, buf.m.planes[i].length); + LOGE("%s::vaddr[%d][%d] = 0x%x", __func__, buf_index, i, (unsigned int)secBuf->virt.extP[i]); + return -1; + } + secBuf->size.extS[i] = buf.m.planes[i].length; + +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("%s::vaddr[bufindex=%d][planeidx=%d] = 0x%x", __func__, buf_index, i, (unsigned int)secBuf->virt.extP[i]); + LOGD("%s::Legnth = %d" , __func__, buf.m.planes[i].length); +#endif + } + + return 0; +} + +int tvout_std_v4l2_qbuf(int fd, enum v4l2_buf_type type, enum v4l2_memory memory, int buf_index, int num_planes, SecBuffer *secBuf) +{ +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("%s", __func__); +#endif + struct v4l2_buffer buf; + struct v4l2_plane planes[MAX_PLANES_MIXER]; + + memset(&buf, 0, sizeof(struct v4l2_buffer)); + + for (int i = 0; i < MAX_PLANES_MIXER; i++) + memset(&planes[i], 0, sizeof(struct v4l2_plane)); + + buf.type = type; + buf.memory = memory; + buf.length = num_planes; + buf.index = buf_index; + buf.m.planes = planes; + + for (unsigned int i = 0; i < buf.length; i++) { + buf.m.planes[i].m.userptr = (unsigned long)secBuf->virt.extP[i]; + buf.m.planes[i].length = secBuf->size.extS[i]; + buf.m.planes[i].bytesused = buf.m.planes[i].length; + +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("%s::buf.index=%d", __func__, buf.index); + LOGD("%s::buf.m.planes[%d].m.userptr=0x%08x", __func__, i, (unsigned int)buf.m.planes[i].m.userptr); + LOGD("%s::buf.m.planes[%d].length =0x%08x", __func__, i, buf.m.planes[i].length); + LOGD("%s::buf.m.planes[%d].bytesused=0x%08x", __func__, i, buf.m.planes[i].bytesused); +#endif + } + + if (ioctl(fd, VIDIOC_QBUF, &buf) < 0) { + LOGE("%s::VIDIOC_QBUF failed", __func__); + return -1; + } + + return 0; +} + +int tvout_std_v4l2_dqbuf(int fd, enum v4l2_buf_type type, enum v4l2_memory memory, int *buf_index, int num_planes) +{ +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("%s", __func__); +#endif + struct v4l2_buffer buf; + struct v4l2_plane planes[MAX_PLANES_MIXER]; + + memset(&buf, 0, sizeof(struct v4l2_buffer)); + + for (int i = 0; i < MAX_PLANES_GSCALER; i++) + memset(&planes[i], 0, sizeof(struct v4l2_plane)); + + + buf.type = type; + buf.memory = memory; + buf.length = num_planes; + buf.m.planes = planes; + + if (ioctl(fd, VIDIOC_DQBUF, &buf) < 0) { + LOGE("%s::VIDIOC_DQBUF failed", __func__); + return -1; + } + *buf_index = buf.index; + +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("%s::buf.index=%d", __func__, buf.index); +#endif + + return 0; +} + +int tvout_std_v4l2_streamon(int fd, enum v4l2_buf_type type) +{ +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("%s", __func__); +#endif + if (ioctl(fd, VIDIOC_STREAMON, &type) < 0) { + LOGE("%s::VIDIOC_STREAMON failed", __func__); + return -1; + } + + return 0; +} + +int tvout_std_v4l2_streamoff(int fd, enum v4l2_buf_type type) +{ +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("%s", __func__); +#endif + if (ioctl(fd, VIDIOC_STREAMOFF, &type) < 0) { + LOGE("%s::VIDIOC_STREAMOFF failed", __func__); + return -1; + } + + return 0; +} + +int tvout_v4l2_enum_output(int fd, struct v4l2_output *output) +{ +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("%s", __func__); +#endif + int ret = -1 ; + ret = ioctl(fd, VIDIOC_ENUMOUTPUT, output); + + if (ret < 0) { + if (errno == EINVAL) + return -1; + LOGE("%s::VIDIOC_ENUMOUTPUT", __func__); + return -1; + } + LOGD("%s::index=%d, type=0x%08x, name=%s", + __func__, output->index, output->type, output->name); + + return ret; +} + +int tvout_v4l2_s_output(int fd, int index) +{ +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("%s", __func__); +#endif + if (ioctl(fd, VIDIOC_S_OUTPUT, &index) < 0) { + LOGE("%s::VIDIOC_S_OUTPUT failed", __func__); + return -1; + } + + return 0; +} + +int tvout_v4l2_g_output(int fd, int *index) +{ +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("%s", __func__); +#endif + if (ioctl(fd, VIDIOC_G_OUTPUT, index) < 0) { + LOGE("%s::VIDIOC_G_OUTPUT failed", __func__); + return -1; + } + + return 0; +} + +int tvout_std_v4l2_enum_dv_presets(int fd) +{ +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("%s", __func__); +#endif + struct v4l2_dv_enum_preset enum_preset; + int ret = -1; + + for (int index = 0; ; index++) { + enum_preset.index = index; + ret = ioctl(fd, VIDIOC_ENUM_DV_PRESETS, &enum_preset); + + if (ret < 0) { + if (errno == EINVAL) + break; + LOGE("%s::VIDIOC_ENUM_DV_PRESETS", __func__); + return -1; + } + LOGD("%s::index=%d, preset=0x%08x, name=%s, w=%d, h=%d", + __func__, enum_preset.index, enum_preset.preset, enum_preset.name, enum_preset.width, enum_preset.height); + } + + return 0; +} + +int tvout_std_v4l2_s_dv_preset(int fd, struct v4l2_dv_preset *preset) +{ +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("%s", __func__); +#endif + if (ioctl(fd, VIDIOC_S_DV_PRESET, preset) < 0) { + LOGE("%s::VIDIOC_S_DV_PRESET failed preset_id=%d", __func__, preset->preset); + return -1; + } +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("%s::preset_id=%d", __func__, preset->preset); +#endif + return 0; +} + +int tvout_std_subdev_s_fmt(int fd, unsigned int pad, int w, int h, enum v4l2_mbus_pixelcode code) +{ +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("%s", __func__); +#endif + struct v4l2_subdev_format fmt; + + fmt.pad = pad; + fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE; + fmt.format.width = w; + fmt.format.height = h; + fmt.format.code = code; + + if (ioctl(fd, VIDIOC_SUBDEV_S_FMT, &fmt) < 0) { + LOGE("%s::VIDIOC_SUBDEV_S_FMT", __func__); + return -1; + } + +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("%s::format w=%d, h=%d", __func__, fmt.format.width, fmt.format.height); +#endif + return 0; +} +int tvout_std_subdev_s_crop(int fd, unsigned int pad, int x, int y, int w, int h) +{ +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("%s::pad=%d, crop x=%d, y=%d, w=%d, h=%d", __func__, pad, x, y, w, h); +#endif + + struct v4l2_subdev_crop crop; + + crop.pad = pad; + crop.which = V4L2_SUBDEV_FORMAT_ACTIVE; + crop.rect.left = x; + crop.rect.top = y; + crop.rect.width = w; + crop.rect.height = h; + + if (ioctl(fd, VIDIOC_SUBDEV_S_CROP, &crop) < 0) { + LOGE("%s::VIDIOC_SUBDEV_S_CROP", __func__); + return -1; + } + +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("%s::pad=%d, crop x=%d, y=%d, w=%d, h=%d", __func__, pad, crop.rect.left, crop.rect.top, crop.rect.width, crop.rect.height); +#endif + + return 0; +} + +#define ROUND_UP(value, boundary) ((((uint32_t)(value)) + \ + (((uint32_t) boundary)-1)) & \ + (~(((uint32_t) boundary)-1))) + +void hdmi_cal_rect(int src_w, int src_h, int dst_w, int dst_h, struct v4l2_rect *dst_rect) +{ + if (dst_w * src_h <= dst_h * src_w) { + dst_rect->left = 0; + dst_rect->top = (dst_h - ((dst_w * src_h) / src_w)) >> 1; + dst_rect->width = dst_w; + dst_rect->height = ((dst_w * src_h) / src_w); + } else { + dst_rect->left = (dst_w - ((dst_h * src_w) / src_h)) >> 1; + dst_rect->top = 0; + dst_rect->width = ((dst_h * src_w) / src_h); + dst_rect->height = dst_h; + } +} + +int hdmi_set_videolayer(int fd, int hdmiW, int hdmiH, struct v4l2_rect * rect) +{ +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("%s", __func__); +#endif + if (tvout_std_subdev_s_fmt(fd, MIXER_V_SUBDEV_PAD_SINK, hdmiW, hdmiH, V4L2_MBUS_FMT_YUV8_1X24) < 0) { + LOGE("%s::tvout_std_subdev_s_fmt(PAD=%d)[videolayer] failed", __func__, MIXER_V_SUBDEV_PAD_SINK); + return -1; + } + + if (tvout_std_subdev_s_crop(fd, MIXER_V_SUBDEV_PAD_SINK, 0, 0, rect->width, rect->height) < 0) { + LOGE("%s::tvout_std_subdev_s_crop(PAD=%d)[videolayer] failed", __func__, MIXER_V_SUBDEV_PAD_SINK); + return -1; + } + + if (tvout_std_subdev_s_crop(fd, MIXER_V_SUBDEV_PAD_SOURCE, rect->left, rect->top, rect->width, rect->height) < 0) { + LOGE("%s::tvout_std_subdev_s_crop(PAD=%d)[videolayer] failed", __func__, MIXER_V_SUBDEV_PAD_SOURCE); + return -1; + } + return 0; +} + +int hdmi_set_graphiclayer(int fd_subdev, int fd_videodev,int layer, + int srcColorFormat, + int src_w, int src_h, + unsigned int src_address, SecBuffer * dstBuffer, + int dst_x, int dst_y, int dst_w, int dst_h, + int rotVal) +{ +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("%s", __func__); +#endif +#if defined(BOARD_USES_HDMI_FIMGAPI) + int dst_color_format; + int dst_bpp; + unsigned char *dst_addr; + fimg2d_blit BlitParam; + rotation g2d_rotation; + + fimg2d_addr srcAddr; + fimg2d_image srcImage; + fimg2d_rect srcRect; + + fimg2d_addr dstAddr; + fimg2d_image dstImage; + fimg2d_rect dstRect; + + fimg2d_clip dstClip; + fimg2d_scale Scaling; + + switch (t_std_id) { + case V4L2_STD_1080P_60: + case V4L2_STD_1080P_30: + case V4L2_STD_1080I_60: + case V4L2_STD_TVOUT_720P_60_SBS_HALF: + case V4L2_STD_TVOUT_720P_59_SBS_HALF: + case V4L2_STD_TVOUT_1080P_24_TB: + case V4L2_STD_TVOUT_1080P_23_TB: + dst_color_format = CF_ARGB_8888; + dst_bpp = 4; + break; + case V4L2_STD_480P_60_16_9: + case V4L2_STD_576P_50_16_9: + case V4L2_STD_720P_60: + case V4L2_STD_TVOUT_720P_50_TB: + default: + dst_color_format = CF_ARGB_4444; + dst_bpp = 2; + break; + } + + static unsigned int prev_src_addr = 0; + + if ((cur_g2d_address == 0) || (src_address != prev_src_addr)) { + if ((cur_g2d_address == 0) || (cur_g2d_address == g2d_reserved_memory1)) + dst_addr = (unsigned char *)g2d_reserved_memory0; + else + dst_addr = (unsigned char *)g2d_reserved_memory1; + + cur_g2d_address = (unsigned int)dst_addr; + prev_src_addr = src_address; + + srcAddr = {(addr_space)ADDR_USER, (unsigned long)src_address, src_w*src_h*4, 1, 0}; + srcImage = {srcAddr, srcAddr, src_w, src_h, src_w*4, AX_RGB, CF_ARGB_8888}; + srcRect = {0, 0, src_w, src_h}; + + dstAddr = {(addr_space)ADDR_USER, (unsigned long)dst_addr, dst_w*dst_h*dst_bpp, 1, 0}; + dstImage = {dstAddr, dstAddr, dst_w, dst_h, dst_w*dst_bpp, AX_RGB, (color_format)dst_color_format}; + dstRect = {0, 0, dst_w, dst_h}; + dstClip = {0, 0, 0, dst_w, dst_h}; + + if (rotVal == 0 || rotVal == 180) + Scaling = {SCALING_BILINEAR, SCALING_PIXELS, 0, 0, src_w, src_h, dst_w, dst_h}; + else + Scaling = {SCALING_BILINEAR, SCALING_PIXELS, 0, 0, src_w, src_h, dst_h, dst_w}; + + switch (rotVal) { + case 0: + g2d_rotation = ORIGIN; + break; + case 90: + g2d_rotation = ROT_90; + break; + case 180: + g2d_rotation = ROT_180; + break; + case 270: + g2d_rotation = ROT_270; + break; + default: + LOGE("%s::invalid rotVal(%d) : failed", __func__, rotVal); + return -1; + break; + } + + BlitParam = {BLIT_OP_SRC, NON_PREMULTIPLIED, 0xff, 0, g2d_rotation, &Scaling, 0, 0, &dstClip, 0, &srcImage, &dstImage, NULL, &srcRect, &dstRect, NULL, 0}; + + if (stretchFimgApi(&BlitParam) < 0) { + LOGE("%s::stretchFimgApi() failed", __func__); + return -1; + } + + dstBuffer->virt.p = (char *)dst_addr; + } +#else + dstBuffer->virt.p = (char *)src_address; +#endif + + return 0; +} + +int hdmi_set_g_Params(int fd_subdev, int fd_videodev, int layer, + int srcColorFormat, + int src_w, int src_h, + int dst_x, int dst_y, int dst_w, int dst_h) +{ +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("%s", __func__); +#endif + struct v4l2_rect rect; + int src_pad = 0; + int sink_pad = 0; + int v4l2ColorFormat = HAL_PIXEL_FORMAT_2_V4L2_PIX(srcColorFormat); + + switch (layer) { + case HDMI_LAYER_GRAPHIC_0: + sink_pad = MIXER_G0_SUBDEV_PAD_SINK; + src_pad = MIXER_G0_SUBDEV_PAD_SOURCE; + break; + case HDMI_LAYER_GRAPHIC_1: + sink_pad = MIXER_G1_SUBDEV_PAD_SINK; + src_pad = MIXER_G1_SUBDEV_PAD_SOURCE; + break; + default: + LOGE("%s::invalid layer(%d)", __func__, layer); + break; + }; + + rect.left = dst_x; + rect.top = dst_y; + +#if defined(BOARD_USES_HDMI_FIMGAPI) + rect.width = dst_w; + rect.height = dst_h; +#else + rect.width = src_w; + rect.height = src_h; +#endif + + /* set sub device for mixer graphic layer input */ + if (tvout_std_subdev_s_fmt(fd_subdev, sink_pad, rect.width, rect.height, V4L2_MBUS_FMT_XRGB8888_4X8_LE) < 0) { + LOGE("%s::tvout_std_subdev_s_fmt(PAD=%d)[graphic layer] failed", __func__, sink_pad); + return -1; + } + + if (tvout_std_subdev_s_crop(fd_subdev, sink_pad, 0, 0, rect.width, rect.height) < 0) { + LOGE("%s::tvout_std_subdev_s_crop(PAD=%d)[graphic layer] failed", __func__, sink_pad); + return -1; + } + + if (tvout_std_subdev_s_crop(fd_subdev, src_pad, rect.left, rect.top, rect.width, rect.height) < 0) { + LOGE("%s::tvout_std_subdev_s_crop(PAD=%d)[graphic layer] failed", __func__, src_pad); + return -1; + } + + /* set format for mixer graphic layer input device*/ + if (tvout_std_v4l2_s_fmt(fd_videodev, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, V4L2_FIELD_ANY, rect.width, rect.height, v4l2ColorFormat, 1) < 0) { + LOGE("%s::tvout_std_v4l2_s_fmt()[graphic layer] failed", __func__); + return -1; + } + + if (tvout_std_v4l2_s_crop(fd_videodev, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, V4L2_FIELD_ANY, rect.left, rect.top, rect.width, rect.height) < 0) { + LOGE("%s::tvout_std_v4l2_s_crop()[graphic layer] failed", __func__); + return -1; + } + + /* request buffer for mixer graphic layer input device */ + if (tvout_std_v4l2_reqbuf(fd_videodev, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, V4L2_MEMORY_USERPTR, 2) < 0) { + LOGE("%s::tvout_std_v4l2_reqbuf(buf_num=%d)[graphic layer] failed", __func__, 2); + return -1; + } + + return 0; +} + +int hdmi_cable_status() +{ +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("%s", __func__); +#endif + + int cable_status = 0; + int fd = 0; + struct v4l2_control ctrl; + + fd = open(TVOUT0_DEV_G0, O_RDWR); + if (fd <= 0) { + LOGE("%s: graphic layer 0 drv open failed", __func__); + return -1; + } + + ctrl.id = V4L2_CID_TV_HPD_STATUS; + + if (ioctl(fd, VIDIOC_S_CTRL, &ctrl) < 0) { + LOGE("Get HPD_STATUS fail"); + cable_status = -1; + } else { + cable_status = ctrl.value; + } + +#ifdef DEBUG_HDMI_HW_LEVEL + LOGD("HPD_STATUS = %d", cable_status); +#endif + + close(fd); + + return cable_status; +} + +int hdmi_outputmode_2_v4l2_output_type(int output_mode) +{ + int v4l2_output_type = -1; + + switch (output_mode) { + case HDMI_OUTPUT_MODE_YCBCR: + v4l2_output_type = V4L2_OUTPUT_TYPE_DIGITAL; + break; + case HDMI_OUTPUT_MODE_RGB: + v4l2_output_type = V4L2_OUTPUT_TYPE_HDMI_RGB; + break; + case HDMI_OUTPUT_MODE_DVI: + v4l2_output_type = V4L2_OUTPUT_TYPE_DVI; + break; + case COMPOSITE_OUTPUT_MODE: + v4l2_output_type = V4L2_OUTPUT_TYPE_COMPOSITE; + break; + default: + LOGE("%s::unmathced HDMI_mode(%d)", __func__, output_mode); + v4l2_output_type = -1; + break; + } + + return v4l2_output_type; +} + +int hdmi_v4l2_output_type_2_outputmode(int v4l2_output_type) +{ + int outputMode = -1; + + switch (v4l2_output_type) { + case V4L2_OUTPUT_TYPE_DIGITAL: + outputMode = HDMI_OUTPUT_MODE_YCBCR; + break; + case V4L2_OUTPUT_TYPE_HDMI_RGB: + outputMode = HDMI_OUTPUT_MODE_RGB; + break; + case V4L2_OUTPUT_TYPE_DVI: + outputMode = HDMI_OUTPUT_MODE_DVI; + break; + case V4L2_OUTPUT_TYPE_COMPOSITE: + outputMode = COMPOSITE_OUTPUT_MODE; + break; + default: + LOGE("%s::unmathced v4l2_output_type(%d)", __func__, v4l2_output_type); + outputMode = -1; + break; + } + + return outputMode; +} + +int composite_std_2_v4l2_std_id(int std) +{ + int std_id = -1; + + switch (std) { + case COMPOSITE_STD_NTSC_M: + std_id = V4L2_STD_NTSC_M; + break; + case COMPOSITE_STD_NTSC_443: + std_id = V4L2_STD_NTSC_443; + break; + case COMPOSITE_STD_PAL_BDGHI: + std_id = V4L2_STD_PAL_BDGHI; + break; + case COMPOSITE_STD_PAL_M: + std_id = V4L2_STD_PAL_M; + break; + case COMPOSITE_STD_PAL_N: + std_id = V4L2_STD_PAL_N; + break; + case COMPOSITE_STD_PAL_Nc: + std_id = V4L2_STD_PAL_Nc; + break; + case COMPOSITE_STD_PAL_60: + std_id = V4L2_STD_PAL_60; + break; + default: + LOGE("%s::unmathced composite_std(%d)", __func__, std); + break; + } + + return std_id; +} + +int hdmi_check_output_mode(int v4l2_output_type) +{ + struct HDMIVideoParameter video; + struct HDMIAudioParameter audio; + int calbirate_v4l2_mode = v4l2_output_type; + + audio.formatCode = LPCM_FORMAT; + audio.outPacket = HDMI_ASP; + audio.channelNum = CH_2; + audio.sampleFreq = SF_44KHZ; + + switch (v4l2_output_type) { + case V4L2_OUTPUT_TYPE_DIGITAL : + video.mode = HDMI; + if (!EDIDHDMIModeSupport(&video)) { + calbirate_v4l2_mode = V4L2_OUTPUT_TYPE_DVI; + LOGI("Change mode into DVI\n"); + break; + } + + video.colorSpace = HDMI_CS_YCBCR444; + if (!EDIDColorSpaceSupport(&video)) { + calbirate_v4l2_mode = V4L2_OUTPUT_TYPE_HDMI_RGB; + LOGI("Change mode into HDMI_RGB\n"); + } + break; + + case V4L2_OUTPUT_TYPE_HDMI_RGB: + video.mode = HDMI; + if (!EDIDHDMIModeSupport(&video)) { + calbirate_v4l2_mode = V4L2_OUTPUT_TYPE_DVI; + LOGI("Change mode into DVI\n"); + break; + } + + video.colorSpace = HDMI_CS_RGB; + if (!EDIDColorSpaceSupport(&video)) { + calbirate_v4l2_mode = V4L2_OUTPUT_TYPE_DIGITAL; + LOGI("Change mode into HDMI_YCBCR\n"); + } + break; + + case V4L2_OUTPUT_TYPE_DVI: + video.mode = DVI; + if (!EDIDHDMIModeSupport(&video)) { + video.colorSpace = HDMI_CS_YCBCR444; + if (!EDIDColorSpaceSupport(&video)) { + calbirate_v4l2_mode = V4L2_OUTPUT_TYPE_HDMI_RGB; + LOGI("Change mode into HDMI_RGB\n"); + } else { + calbirate_v4l2_mode = V4L2_OUTPUT_TYPE_DIGITAL; + LOGI("Change mode into HDMI_YCBCR\n"); + } + break; + } + + break; + + default: + break; + } + return calbirate_v4l2_mode; +} + +int hdmi_check_resolution(v4l2_std_id std_id) +{ + struct HDMIVideoParameter video; + struct HDMIAudioParameter audio; + + switch (std_id) { + case V4L2_STD_480P_60_16_9: + video.resolution = v720x480p_60Hz; + video.pixelAspectRatio = HDMI_PIXEL_RATIO_16_9; + video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT; + break; + case V4L2_STD_480P_60_4_3: + video.resolution = v640x480p_60Hz; + video.pixelAspectRatio = HDMI_PIXEL_RATIO_4_3; + video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT; + break; + case V4L2_STD_576P_50_16_9: + video.resolution = v720x576p_50Hz; + video.pixelAspectRatio = HDMI_PIXEL_RATIO_16_9; + video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT; + break; + case V4L2_STD_576P_50_4_3: + video.resolution = v720x576p_50Hz; + video.pixelAspectRatio = HDMI_PIXEL_RATIO_4_3; + video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT; + break; + case V4L2_STD_720P_60: + video.resolution = v1280x720p_60Hz; + video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT; + break; + case V4L2_STD_720P_50: + video.resolution = v1280x720p_50Hz; + video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT; + break; + case V4L2_STD_1080P_60: + video.resolution = v1920x1080p_60Hz; + video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT; + break; + case V4L2_STD_1080P_50: + video.resolution = v1920x1080p_50Hz; + video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT; + break; + case V4L2_STD_1080I_60: + video.resolution = v1920x1080i_60Hz; + video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT; + break; + case V4L2_STD_1080I_50: + video.resolution = v1920x1080i_50Hz; + video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT; + break; + case V4L2_STD_480P_59: + video.resolution = v720x480p_60Hz; + video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT; + break; + case V4L2_STD_720P_59: + video.resolution = v1280x720p_60Hz; + video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT; + break; + case V4L2_STD_1080I_59: + video.resolution = v1920x1080i_60Hz; + video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT; + break; + case V4L2_STD_1080P_59: + video.resolution = v1920x1080p_60Hz; + video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT; + break; + case V4L2_STD_1080P_30: + video.resolution = v1920x1080p_30Hz; + video.hdmi_3d_format = HDMI_2D_VIDEO_FORMAT; + break; + case V4L2_STD_TVOUT_720P_60_SBS_HALF: + video.resolution = v1280x720p_60Hz; + video.hdmi_3d_format = HDMI_3D_SSH_FORMAT; + break; + case V4L2_STD_TVOUT_720P_59_SBS_HALF: + video.resolution = v1280x720p_60Hz; + video.hdmi_3d_format = HDMI_3D_SSH_FORMAT; + break; + case V4L2_STD_TVOUT_720P_50_TB: + video.resolution = v1280x720p_50Hz; + video.hdmi_3d_format = HDMI_3D_TB_FORMAT; + break; + case V4L2_STD_TVOUT_1080P_24_TB: + video.resolution = v1920x1080p_24Hz; + video.hdmi_3d_format = HDMI_3D_TB_FORMAT; + break; + case V4L2_STD_TVOUT_1080P_23_TB: + video.resolution = v1920x1080p_24Hz; + video.hdmi_3d_format = HDMI_3D_TB_FORMAT; + break; + default: + LOGE("%s::unmathced std_id(%lld)", __func__, std_id); + return -1; + break; + } + + if (!EDIDVideoResolutionSupport(&video)) { +#ifdef DEBUG_MSG_ENABLE + LOGD("%s::EDIDVideoResolutionSupport(%llx) fail (not suppoted std_id) \n", __func__, std_id); +#endif + return -1; + } + + return 0; +} + +int hdmi_resolution_2_std_id(unsigned int resolution, int * w, int * h, v4l2_std_id * std_id, __u32 *preset_id) +{ + int ret = 0; + + switch (resolution) { + case 1080960: + *std_id = V4L2_STD_1080P_60; + *w = 1920; + *h = 1080; + *preset_id = V4L2_DV_1080P60; + break; + case 1080950: + *std_id = V4L2_STD_1080P_50; + *w = 1920; + *h = 1080; + *preset_id = V4L2_DV_1080P50; + break; + case 1080930: + *std_id = V4L2_STD_1080P_30; + *w = 1920; + *h = 1080; + *preset_id = V4L2_DV_1080P30; + break; + case 1080924: + *std_id = V4L2_STD_TVOUT_1080P_24_TB; + *w = 1920; + *h = 1080; + *preset_id = V4L2_DV_1080P24_TB; + break; + case 1080160: + *std_id = V4L2_STD_1080I_60; + *w = 1920; + *h = 1080; + *preset_id = V4L2_DV_1080I60; + break; + case 1080150: + *std_id = V4L2_STD_1080I_50; + *w = 1920; + *h = 1080; + *preset_id = V4L2_DV_1080I50; + break; + case 720960: + *std_id = V4L2_STD_720P_60; + *w = 1280; + *h = 720; + *preset_id = V4L2_DV_720P60; + break; + case 7209601: + *std_id = V4L2_STD_TVOUT_720P_60_SBS_HALF; + *w = 1280; + *h = 720; + *preset_id = V4L2_DV_720P60_SB_HALF; + break; + case 720950: + *std_id = V4L2_STD_720P_50; + *w = 1280; + *h = 720; + *preset_id = V4L2_DV_720P50; + break; + case 7209501: + *std_id = V4L2_STD_TVOUT_720P_50_TB; + *w = 1280; + *h = 720; + *preset_id = V4L2_DV_720P50_TB; + break; + case 5769501: + *std_id = V4L2_STD_576P_50_16_9; + *w = 720; + *h = 576; + *preset_id = V4L2_DV_576P50; + break; + case 5769502: + *std_id = V4L2_STD_576P_50_4_3; + *w = 720; + *h = 576; + *preset_id = V4L2_DV_576P50; + break; + case 4809601: + *std_id = V4L2_STD_480P_60_16_9; + *w = 720; + *h = 480; + *preset_id = V4L2_DV_480P60; + break; + case 4809602: + *std_id = V4L2_STD_480P_60_4_3; + *w = 720; + *h = 480; + *preset_id = V4L2_DV_480P60; + break; + default: + LOGE("%s::unmathced resolution(%d)", __func__, resolution); + ret = -1; + break; + } + + return ret; +} + +int hdmi_enable_hdcp(int fd, unsigned int hdcp_en) +{ + if (ioctl(fd, VIDIOC_HDCP_ENABLE, hdcp_en) < 0) { + LOGD("%s::VIDIOC_HDCP_ENABLE(%d) fail \n", __func__, hdcp_en); + return -1; + } + + return 0; +} + +int hdmi_check_audio(int fd) +{ + struct HDMIAudioParameter audio; + enum state audio_state = ON; + int ret = 0; + + audio.formatCode = LPCM_FORMAT; + audio.outPacket = HDMI_ASP; + audio.channelNum = CH_2; + audio.sampleFreq = SF_44KHZ; + +#if defined(BOARD_USES_EDID) + if (!EDIDAudioModeSupport(&audio)) + audio_state = NOT_SUPPORT; + else + audio_state = ON; +#endif + if (audio_state == ON) { + if (ioctl(fd, VIDIOC_INIT_AUDIO, 1) < 0) { + LOGE("%s::VIDIOC_INIT_AUDIO(1) failed", __func__); + ret = -1; + } + } else { + if (ioctl(fd, VIDIOC_INIT_AUDIO, 0) < 0) { + LOGE("%s::VIDIOC_INIT_AUDIO(0) failed", __func__); + ret = -1; + } + } + + return ret; +} + +} diff --git a/exynos5/hal/libhdmi/SecHdmi/SecHdmiV4L2Utils.h b/exynos5/hal/libhdmi/SecHdmi/SecHdmiV4L2Utils.h new file mode 100644 index 0000000..67c0729 --- /dev/null +++ b/exynos5/hal/libhdmi/SecHdmi/SecHdmiV4L2Utils.h @@ -0,0 +1,86 @@ +/* + * Copyright@ Samsung Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __HDMI_HAL_V4L2_UTILS_H__ +#define __HDMI_HAL_V4L2_UTILS_H__ + +//#define LOG_NDEBUG 0 +//#define LOG_TAG "libhdmi" + +#include "fimd_api.h" +#include "SecBuffer.h" + +#ifdef __cplusplus +extern "C" { +#endif + +namespace android { + +void display_menu(void); + +int tvout_init(int fd_tvout, __u32 preset_id); +int tvout_deinit(); +int tvout_std_v4l2_querycap(int fd, char *node); +int tvout_std_v4l2_s_fmt(int fd, enum v4l2_buf_type type, enum v4l2_field field, int w, int h, int colorformat, int num_planes); +int tvout_std_v4l2_s_crop(int fd, enum v4l2_buf_type type, enum v4l2_field field, int x, int y, int w, int h); +int tvout_std_v4l2_s_ctrl(int fd, int id, int value); +int tvout_std_v4l2_reqbuf(int fd, enum v4l2_buf_type type, enum v4l2_memory memory, unsigned int num_bufs); +int tvout_std_v4l2_querybuf(int fd, enum v4l2_buf_type type, enum v4l2_memory memory, unsigned int buf_index, unsigned int num_planes, SecBuffer *secBuf); +int tvout_std_v4l2_qbuf(int fd, enum v4l2_buf_type type, enum v4l2_memory memory, int buf_index, int num_planes, SecBuffer *secBuf); +int tvout_std_v4l2_dqbuf(int fd, enum v4l2_buf_type type, enum v4l2_memory memory, int *buf_index, int num_planes); +int tvout_std_v4l2_streamon(int fd, enum v4l2_buf_type type); +int tvout_std_v4l2_streamoff(int fd, enum v4l2_buf_type type); + +int tvout_v4l2_enum_output(int fp, struct v4l2_output *output); +int tvout_v4l2_s_output(int fp, int index); +int tvout_v4l2_g_output(int fp, int *index); +int tvout_std_v4l2_enum_dv_presets(int fd); +int tvout_std_v4l2_s_dv_preset(int fd, struct v4l2_dv_preset *preset); +int tvout_std_subdev_s_fmt(int fd, unsigned int pad, int w, int h, enum v4l2_mbus_pixelcode code); +int tvout_std_subdev_s_crop(int fd, unsigned int pad, int w, int h, int x, int y); + +void hdmi_cal_rect(int src_w, int src_h, int dst_w, int dst_h, struct v4l2_rect *dst_rect); +int hdmi_set_videolayer(int fd, int hdmiW, int hdmiH, struct v4l2_rect * rect); +int hdmi_set_graphiclayer(int fd_subdev, int fd_videodev,int layer, + int srcColorFormat, + int src_w, int src_h, + unsigned int src_address, SecBuffer * dstBuffer, + int dst_x, int dst_y, int dst_w, int dst_h, + int rotVal); +int hdmi_set_g_Params(int fd_subdev, int fd_videodev, int layer, + int srcColorFormat, + int src_w, int src_h, + int dst_x, int dst_y, int dst_w, int dst_h); + +int hdmi_cable_status(); +int hdmi_outputmode_2_v4l2_output_type(int output_mode); +int hdmi_v4l2_output_type_2_outputmode(int v4l2_output_type); +int composite_std_2_v4l2_std_id(int std); + +int hdmi_check_output_mode(int v4l2_output_type); +int hdmi_check_resolution(v4l2_std_id std_id); + +int hdmi_resolution_2_std_id(unsigned int resolution, int *w, int *h, v4l2_std_id *std_id, __u32 *preset_id); +int hdmi_enable_hdcp(int fd, unsigned int hdcp_en); +int hdmi_check_audio(int fd); + +#ifdef __cplusplus +} +#endif + +} //namespace android + +#endif //__HDMI_HAL_V4L2_UTILS_H__ diff --git a/exynos5/hal/libhdmi/SecHdmi/fimd_api.c b/exynos5/hal/libhdmi/SecHdmi/fimd_api.c new file mode 100644 index 0000000..0e07ef3 --- /dev/null +++ b/exynos5/hal/libhdmi/SecHdmi/fimd_api.c @@ -0,0 +1,229 @@ +/* +* Copyright@ Samsung Electronics Co. LTD +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "fimd_api.h" + +int fb_open(int win) +{ + char node[20]; + int fp = -1; + + sprintf(node, "%s%d", PFX_NODE_FB, win); + + fp = open(node, O_RDWR); + if (fp < 0) + LOGE("%s: fb[%d] open failed", __func__, win); + + return fp; +} + +int fb_close(int fp) +{ + if (fp) + close(fp); + else + LOGE("%s: fb is not allocated %d", __func__, fp); + + return 0; +} + +int get_fscreeninfo(int fp, struct fb_fix_screeninfo *fix) +{ + int ret = -1; + + ret = ioctl(fp, FBIOGET_FSCREENINFO, fix); + if (ret) + LOGE("%s: FBIOGET_FSCREENINFO failed", __func__); + + return ret; +} + +int get_vscreeninfo(int fp, struct fb_var_screeninfo *var) +{ + int ret = -1; + + ret = ioctl(fp, FBIOGET_VSCREENINFO, var); + if (ret) + LOGE("%s:: FBIOGET_VSCREENINFO failed", __func__); + + return ret; +} + +int put_vscreeninfo(int fp, struct fb_var_screeninfo *var) +{ + int ret = -1; + + ret = ioctl(fp, FBIOPUT_VSCREENINFO, var); + if (ret) + LOGE("%s:: FBIOPUT_VSCREENINFO failed", __func__); + + return ret; +} + +int get_bytes_per_pixel(int bits_per_pixel) +{ + return (bits_per_pixel == 24 || bits_per_pixel == 25 || + bits_per_pixel == 28) ? 4 : bits_per_pixel / 8; +} + +char *fb_mmap(__u32 size, int fp) +{ + char *buffer; + + buffer = (char *)mmap(0, size, PROT_READ | PROT_WRITE, + MAP_SHARED, fp, 0); + if (!buffer) { + LOGE("%s:: mmap failed", __func__); + return NULL; + } + + return buffer; +} + +int fb_ioctl(int fp, __u32 cmd, void *arg) +{ + int ret = -1; + + ret = ioctl(fp, cmd, arg); + if (ret < 0) + LOGE("%s:: ioctl (%d) failed", __func__, cmd); + + return ret; +} + +int fb_on(int fp) +{ + int ret = -1; + + ret = ioctl(fp, FBIOBLANK, FB_BLANK_UNBLANK); + if (ret) + LOGE("%s:: FBIOBLANK failed", __func__); + + return ret; +} + +int fb_off(int fp) +{ + int ret = -1; + + ret = ioctl(fp, FBIOBLANK, FB_BLANK_POWERDOWN); + if (ret) + LOGE("%s:: FBIOBLANK failed", __func__); + + return ret; +} + +int fb_off_all() +{ + int fp, i; + + for (i = 0; i < TOTAL_FB_NUM; i++) { + fp = fb_open(i); + if (fp < 0) + return -1; + + if (ioctl(fp, FBIOBLANK, FB_BLANK_POWERDOWN) < 0) + LOGE("%s:: FBIOBLANK failed", __func__); + + fb_off(fp); + fb_close(fp); + } + + return 0; +} + +char *fb_init_display(int fp, int width, int height, int left_x, int top_y, + int bpp) +{ + struct fb_var_screeninfo var; + struct s5ptvfb_user_window window; + int fb_size; + char *fb = NULL; + + var.xres = width; + var.yres = height; + var.bits_per_pixel = bpp; + window.x = left_x; + window.y = top_y; + + var.xres_virtual = var.xres; + var.yres_virtual = var.yres; + var.xoffset = 0; + var.yoffset = 0; + var.width = 0; + var.height = 0; + var.transp.length = 0; + var.activate = FB_ACTIVATE_FORCE; + fb_size = var.xres_virtual * var.yres_virtual * bpp / 8; + + /* FBIOPUT_VSCREENINFO should be first */ + put_vscreeninfo(fp, &var); + fb_ioctl(fp, S5PTVFB_WIN_POSITION, &window); + + /* draw image */ + fb = fb_mmap(fb_size, fp); + memset(fb, 0x0, fb_size); + + return fb; +} + +int simple_draw(char *dest, const char *src, int img_width, + struct fb_var_screeninfo *var) +{ + int bytes_per_pixel = get_bytes_per_pixel(var->bits_per_pixel); + unsigned int y; + + for (y = 0; y < var->yres; y++) + memcpy(dest + y * var->xres * bytes_per_pixel, + src + y * img_width * bytes_per_pixel, + var->xres * bytes_per_pixel); + + return 0; +} + +int draw(char *dest, const char *src, int img_width, + struct fb_var_screeninfo *var) +{ + int bytes_per_pixel = get_bytes_per_pixel(var->bits_per_pixel); + unsigned int y; + + if (var->bits_per_pixel == 16) { + memcpy(dest, src, var->xres * var->yres * 2); + } else { + for (y = 0; y < var->yres; y++) + memcpy(dest + y * var->xres * bytes_per_pixel, + src + y * img_width * bytes_per_pixel, + var->xres * bytes_per_pixel); + } + + return 0; +} diff --git a/exynos5/hal/libhdmi/SecHdmi/fimd_api.h b/exynos5/hal/libhdmi/SecHdmi/fimd_api.h new file mode 100644 index 0000000..a8561a4 --- /dev/null +++ b/exynos5/hal/libhdmi/SecHdmi/fimd_api.h @@ -0,0 +1,51 @@ +/* + * Copyright@ Samsung Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __FIMD_API_H__ +#define __FIMD_API_H__ + +#include +#include "s5p_tvout.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define TOTAL_FB_NUM 5 + +int fb_open(int win); +int fb_close(int fp); +int fb_on(int fp); +int fb_off(int fp); +int fb_off_all(void); +char *fb_init_display(int fp, int width, int height,\ + int left_x, int top_y, int bpp); +int fb_ioctl(int fp, __u32 cmd, void *arg); +char *fb_mmap(__u32 size, int fp); +int simple_draw(char *dest, const char *src,\ + int img_width, struct fb_var_screeninfo *var); +int draw(char *dest, const char *src,\ + int img_width, struct fb_var_screeninfo *var); +int get_fscreeninfo(int fp, struct fb_fix_screeninfo *fix); +int get_vscreeninfo(int fp, struct fb_var_screeninfo *var); +int put_vscreeninfo(int fp, struct fb_var_screeninfo *var); +int get_bytes_per_pixel(int bits_per_pixel); + +#ifdef __cplusplus +} +#endif + +#endif /* __FIMD_API_H__ */ diff --git a/exynos5/hal/libhdmi/libhdmiservice/Android.mk b/exynos5/hal/libhdmi/libhdmiservice/Android.mk new file mode 100644 index 0000000..bc0aa0d --- /dev/null +++ b/exynos5/hal/libhdmi/libhdmiservice/Android.mk @@ -0,0 +1,95 @@ +# Copyright (C) 2008 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +ifeq ($(filter-out exynos5,$(TARGET_BOARD_PLATFORM)),) +ifeq ($(BOARD_USES_HDMI),true) + +LOCAL_PATH:= $(call my-dir) + +# +# libTVOut +# + +include $(CLEAR_VARS) +LOCAL_MODULE_TAGS := optional +LOCAL_PRELINK_MODULE := false + +LOCAL_SRC_FILES := \ + SecTVOutService.cpp \ + ISecTVOut.cpp \ + MessageQueue.cpp + +LOCAL_C_INCLUDES := \ + +LOCAL_SHARED_LIBRARIES := \ + libbinder \ + libutils \ + libcutils + +LOCAL_C_INCLUDES += device/samsung/$(TARGET_BOARD_PLATFORM)/include +LOCAL_C_INCLUDES += device/samsung/$(TARGET_BOARD_PLATFORM)/libhdmi +LOCAL_SHARED_LIBRARIES += libhdmi + +ifeq ($(BOARD_USES_HDMI_SUBTITLES),true) + LOCAL_CFLAGS += -DBOARD_USES_HDMI_SUBTITLES +endif + +LOCAL_MODULE := libTVOut + +include $(BUILD_SHARED_LIBRARY) + +# +# libhdmiclient +# + +include $(CLEAR_VARS) + +LOCAL_MODULE_TAGS := optional +LOCAL_PRELINK_MODULE := false + +LOCAL_SRC_FILES:= \ + SecHdmiClient.cpp + +LOCAL_C_INCLUDES += \ + $(JNI_H_INCLUDE) + +LOCAL_SHARED_LIBRARIES := \ + libbinder \ + libutils \ + libTVOut + +ifeq ($(TARGET_SIMULATOR),true) +ifeq ($(TARGET_OS),linux) +ifeq ($(TARGET_ARCH),x86) +LOCAL_LDLIBS += -lpthread -ldl -lrt +endif +endif +endif + +ifeq ($(WITH_MALLOC_LEAK_CHECK),true) + LOCAL_CFLAGS += -DMALLOC_LEAK_CHECK +endif + +ifeq ($(TARGET_SOC),exynos5250) +LOCAL_CFLAGS += -DSAMSUNG_EXYNOS5250 +endif + +LOCAL_CFLAGS += -DBOARD_USES_HDMI + +LOCAL_MODULE:= libhdmiclient + +include $(BUILD_SHARED_LIBRARY) + +endif +endif diff --git a/exynos5/hal/libhdmi/libhdmiservice/Barrier.h b/exynos5/hal/libhdmi/libhdmiservice/Barrier.h new file mode 100644 index 0000000..6f8507e --- /dev/null +++ b/exynos5/hal/libhdmi/libhdmiservice/Barrier.h @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_BARRIER_H +#define ANDROID_BARRIER_H + +#include +#include +#include + +namespace android { + +class Barrier +{ +public: + inline Barrier() : state(CLOSED) { } + inline ~Barrier() { } + void open() { + Mutex::Autolock _l(lock); + state = OPENED; + cv.broadcast(); + } + void close() { + Mutex::Autolock _l(lock); + state = CLOSED; + } + void wait() const { + Mutex::Autolock _l(lock); + while (state == CLOSED) { + cv.wait(lock); + } + } +private: + enum { OPENED, CLOSED }; + mutable Mutex lock; + mutable Condition cv; + volatile int state; +}; + +}; // namespace android + +#endif // ANDROID_BARRIER_H diff --git a/exynos5/hal/libhdmi/libhdmiservice/ISecTVOut.cpp b/exynos5/hal/libhdmi/libhdmiservice/ISecTVOut.cpp new file mode 100644 index 0000000..a013bf1 --- /dev/null +++ b/exynos5/hal/libhdmi/libhdmiservice/ISecTVOut.cpp @@ -0,0 +1,111 @@ +/* +** +** Copyright 2008, The Android Open Source Project +** Copyright 2010, Samsung Electronics Co. LTD +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + +/* +** +** @author Taikyung, Yu(taikyung.yu@samsung.com) +** @date 2011-07-06 +*/ + +#include +#include +#include +#include +#include "ISecTVOut.h" + +namespace android { + + enum { + SET_HDMI_STATUS = IBinder::FIRST_CALL_TRANSACTION, + SET_HDMI_MODE, + SET_HDMI_RESOLUTION, + SET_HDMI_HDCP, + SET_HDMI_ROTATE, + SET_HDMI_HWCLAYER, + BLIT_2_HDMI + }; + + void BpSecTVOut::setHdmiCableStatus(uint32_t status) + { + Parcel data, reply; + data.writeInt32(status); + remote()->transact(SET_HDMI_STATUS, data, &reply); + } + + void BpSecTVOut::setHdmiMode(uint32_t mode) + { + Parcel data, reply; + data.writeInt32(mode); + remote()->transact(SET_HDMI_MODE, data, &reply); + } + + void BpSecTVOut::setHdmiResolution(uint32_t resolution) + { + Parcel data, reply; + data.writeInt32(resolution); + remote()->transact(SET_HDMI_RESOLUTION, data, &reply); + } + + void BpSecTVOut::setHdmiHdcp(uint32_t resolution) + { + Parcel data, reply; + data.writeInt32(resolution); + remote()->transact(SET_HDMI_HDCP, data, &reply); + } + + void BpSecTVOut::setHdmiRotate(uint32_t rotVal, uint32_t hwcLayer) + { + Parcel data, reply; + data.writeInt32(rotVal); + data.writeInt32(hwcLayer); + remote()->transact(SET_HDMI_ROTATE, data, &reply); + } + + void BpSecTVOut::setHdmiHwcLayer(uint32_t hwcLayer) + { + Parcel data, reply; + data.writeInt32(hwcLayer); + remote()->transact(SET_HDMI_HWCLAYER, data, &reply); + } + + void BpSecTVOut::blit2Hdmi(uint32_t w, uint32_t h, + uint32_t colorFormat, + uint32_t physYAddr, + uint32_t physCbAddr, + uint32_t physCrAddr, + uint32_t dstX, + uint32_t dstY, + uint32_t hdmiLayer, + uint32_t num_of_hwc_layer) + { + Parcel data, reply; + data.writeInt32(w); + data.writeInt32(h); + data.writeInt32(colorFormat); + data.writeInt32(physYAddr); + data.writeInt32(physCbAddr); + data.writeInt32(physCrAddr); + data.writeInt32(dstX); + data.writeInt32(dstY); + data.writeInt32(hdmiLayer); + data.writeInt32(num_of_hwc_layer); + remote()->transact(BLIT_2_HDMI, data, &reply); + } + + IMPLEMENT_META_INTERFACE(SecTVOut, "android.os.ISecTVOut"); +}; diff --git a/exynos5/hal/libhdmi/libhdmiservice/ISecTVOut.h b/exynos5/hal/libhdmi/libhdmiservice/ISecTVOut.h new file mode 100644 index 0000000..5506b57 --- /dev/null +++ b/exynos5/hal/libhdmi/libhdmiservice/ISecTVOut.h @@ -0,0 +1,74 @@ +/* +** +** Copyright 2008, The Android Open Source Project +** Copyright 2010, Samsung Electronics Co. LTD +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + +/* +** +** @author Taikyung, Yu(taikyung.yu@samsung.com) +** @date 2011-07-06 +*/ + +#ifndef ISECTVOUT_H +#define ISECTVOUT_H +#include +#include +#include + +namespace android { + class ISecTVOut: public IInterface + { + public: + DECLARE_META_INTERFACE(SecTVOut); + virtual void setHdmiCableStatus(uint32_t status) = 0; + virtual void setHdmiMode(uint32_t mode) = 0; + virtual void setHdmiResolution(uint32_t resolution) = 0; + virtual void setHdmiHdcp(uint32_t enHdcp) = 0; + virtual void setHdmiRotate(uint32_t rotVal, uint32_t hwcLayer) = 0; + virtual void setHdmiHwcLayer(uint32_t hwcLayer) = 0; + virtual void blit2Hdmi(uint32_t w, uint32_t h, + uint32_t colorFormat, + uint32_t physYAddr, + uint32_t physCbAddr, + uint32_t physCrAddr, + uint32_t dstX, + uint32_t dstY, + uint32_t hdmiLayer, + uint32_t num_of_hwc_layer) = 0; + }; + //-------------------------------------------------------------- + class BpSecTVOut: public BpInterface + { + public: + BpSecTVOut(const sp& impl): BpInterface(impl){} + virtual void setHdmiCableStatus(uint32_t status); + virtual void setHdmiMode(uint32_t mode); + virtual void setHdmiResolution(uint32_t resolution); + virtual void setHdmiHdcp(uint32_t enHdcp); + virtual void setHdmiRotate(uint32_t rotVal, uint32_t hwcLayer); + virtual void setHdmiHwcLayer(uint32_t hwcLayer); + virtual void blit2Hdmi(uint32_t w, uint32_t h, + uint32_t colorFormat, + uint32_t physYAddr, + uint32_t physCbAddr, + uint32_t physCrAddr, + uint32_t dstX, + uint32_t dstY, + uint32_t hdmiLayer, + uint32_t num_of_hwc_layer); + }; +}; +#endif diff --git a/exynos5/hal/libhdmi/libhdmiservice/MessageQueue.cpp b/exynos5/hal/libhdmi/libhdmiservice/MessageQueue.cpp new file mode 100644 index 0000000..fb58ef9 --- /dev/null +++ b/exynos5/hal/libhdmi/libhdmiservice/MessageQueue.cpp @@ -0,0 +1,190 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +#include +#include +#include +#include + +#include "MessageQueue.h" + +namespace android { + +void MessageList::insert(const sp& node) +{ + LIST::iterator cur(mList.begin()); + LIST::iterator end(mList.end()); + while (cur != end) { + if (*node < **cur) { + mList.insert(cur, node); + return; + } + ++cur; + } + mList.insert(++end, node); +} + +void MessageList::remove(MessageList::LIST::iterator pos) +{ + mList.erase(pos); +} + +MessageQueue::MessageQueue() + : mInvalidate(false) +{ + mInvalidateMessage = new MessageBase(INVALIDATE); +} + +MessageQueue::~MessageQueue() +{ +} + +sp MessageQueue::waitMessage(nsecs_t timeout) +{ + sp result; + + bool again; + do { + const nsecs_t timeoutTime = systemTime() + timeout; + while (true) { + Mutex::Autolock _l(mLock); + nsecs_t now = systemTime(); + nsecs_t nextEventTime = -1; + + LIST::iterator cur(mMessages.begin()); + if (cur != mMessages.end()) { + result = *cur; + } + + if (result != 0) { + if (result->when <= now) { + // there is a message to deliver + mMessages.remove(cur); + break; + } + nextEventTime = result->when; + result = 0; + } + + // see if we have an invalidate message + if (mInvalidate) { + mInvalidate = false; + mInvalidateMessage->when = now; + result = mInvalidateMessage; + break; + } + + if (timeout >= 0) { + if (timeoutTime < now) { + // we timed-out, return a NULL message + result = 0; + break; + } + if (nextEventTime > 0) { + if (nextEventTime > timeoutTime) { + nextEventTime = timeoutTime; + } + } else { + nextEventTime = timeoutTime; + } + } + + if (nextEventTime >= 0) { + //LOGD("nextEventTime = %lld ms", nextEventTime); + if (nextEventTime > 0) { + // we're about to wait, flush the binder command buffer + IPCThreadState::self()->flushCommands(); + const nsecs_t reltime = nextEventTime - systemTime(); + if (reltime > 0) { + mCondition.waitRelative(mLock, reltime); + } + } + } else { + //LOGD("going to wait"); + // we're about to wait, flush the binder command buffer + IPCThreadState::self()->flushCommands(); + mCondition.wait(mLock); + } + } + // here we're not holding the lock anymore + + if (result == 0) + break; + + again = result->handler(); + if (again) { + // the message has been processed. release our reference to it + // without holding the lock. + result->notify(); + result = 0; + } + } while (again); + + return result; +} + +status_t MessageQueue::postMessage( + const sp& message, nsecs_t relTime, uint32_t flags) +{ + return queueMessage(message, relTime, flags); +} + +status_t MessageQueue::invalidate() { + Mutex::Autolock _l(mLock); + mInvalidate = true; + mCondition.signal(); + return NO_ERROR; +} + +status_t MessageQueue::queueMessage( + const sp& message, nsecs_t relTime, uint32_t flags) +{ + Mutex::Autolock _l(mLock); + message->when = systemTime() + relTime; + mMessages.insert(message); + + //LOGD("MessageQueue::queueMessage time = %lld ms", message->when); + //dumpLocked(message); + + mCondition.signal(); + return NO_ERROR; +} + +void MessageQueue::dump(const sp& message) +{ + Mutex::Autolock _l(mLock); + dumpLocked(message); +} + +void MessageQueue::dumpLocked(const sp& message) +{ + LIST::const_iterator cur(mMessages.begin()); + LIST::const_iterator end(mMessages.end()); + int c = 0; + while (cur != end) { + const char tick = (*cur == message) ? '>' : ' '; + LOGD("%c %d: msg{.what=%08x, when=%lld}", + tick, c, (*cur)->what, (*cur)->when); + ++cur; + c++; + } +} + +}; // namespace android diff --git a/exynos5/hal/libhdmi/libhdmiservice/MessageQueue.h b/exynos5/hal/libhdmi/libhdmiservice/MessageQueue.h new file mode 100644 index 0000000..4fc752f --- /dev/null +++ b/exynos5/hal/libhdmi/libhdmiservice/MessageQueue.h @@ -0,0 +1,118 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_MESSAGE_QUEUE_H +#define ANDROID_MESSAGE_QUEUE_H + +#include +#include +#include + +#include +#include +#include + +#include "Barrier.h" + +namespace android { + +class MessageBase; + +class MessageList +{ + List< sp > mList; + typedef List< sp > LIST; +public: + inline LIST::iterator begin() { return mList.begin(); } + inline LIST::const_iterator begin() const { return mList.begin(); } + inline LIST::iterator end() { return mList.end(); } + inline LIST::const_iterator end() const { return mList.end(); } + inline bool isEmpty() const { return mList.empty(); } + void insert(const sp& node); + void remove(LIST::iterator pos); +}; + +class MessageBase : + public LightRefBase +{ +public: + nsecs_t when; + uint32_t what; + int32_t arg0; + + MessageBase() : when(0), what(0), arg0(0) { } + MessageBase(uint32_t what, int32_t arg0=0) + : when(0), what(what), arg0(arg0) { } + + // return true if message has a handler + virtual bool handler() { return false; } + + // waits for the handler to be processed + void wait() const { barrier.wait(); } + + // releases all waiters. this is done automatically if + // handler returns true + void notify() const { barrier.open(); } + +protected: + virtual ~MessageBase() { } + +private: + mutable Barrier barrier; + friend class LightRefBase; +}; + +inline bool operator < (const MessageBase& lhs, const MessageBase& rhs) { + return lhs.when < rhs.when; +} + +class MessageQueue +{ + typedef List< sp > LIST; +public: + + MessageQueue(); + ~MessageQueue(); + + // pre-defined messages + enum { + INVALIDATE = '_upd' + }; + + sp waitMessage(nsecs_t timeout = -1); + + status_t postMessage(const sp& message, + nsecs_t reltime=0, uint32_t flags = 0); + + status_t invalidate(); + + void dump(const sp& message); + +private: + status_t queueMessage(const sp& message, + nsecs_t reltime, uint32_t flags); + void dumpLocked(const sp& message); + + Mutex mLock; + Condition mCondition; + MessageList mMessages; + bool mInvalidate; + sp mInvalidateMessage; +}; + +}; // namespace android + +#endif /* ANDROID_MESSAGE_QUEUE_H */ diff --git a/exynos5/hal/libhdmi/libhdmiservice/SecHdmiClient.cpp b/exynos5/hal/libhdmi/libhdmiservice/SecHdmiClient.cpp new file mode 100644 index 0000000..150aadf --- /dev/null +++ b/exynos5/hal/libhdmi/libhdmiservice/SecHdmiClient.cpp @@ -0,0 +1,139 @@ +/* +** +** Copyright 2008, The Android Open Source Project +** Copyright 2010, Samsung Electronics Co. LTD +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + +/* +** +** @author Taikyung, Yu(taikyung.yu@samsung.com) +** @date 2011-07-06 +*/ + +#define LOG_TAG "libhdmiclient" + +#include "SecHdmiClient.h" + +namespace android { + +static sp g_SecTVOutService = 0; + +SecHdmiClient::SecHdmiClient() +{ + g_SecTVOutService = m_getSecTVOutService(); +} + +SecHdmiClient::~SecHdmiClient() +{ +} + +SecHdmiClient * SecHdmiClient::getInstance(void) +{ + static SecHdmiClient singleton; + return &singleton; +} + +void SecHdmiClient::setHdmiCableStatus(int status) +{ + LOGD("%s HDMI status: %d\n", __func__, status); + + if (g_SecTVOutService != 0) + g_SecTVOutService->setHdmiCableStatus(status); +} + +void SecHdmiClient::setHdmiMode(int mode) +{ + //LOGD("%s HDMI Mode: %d\n", __func__, mode); + + if (g_SecTVOutService != 0) + g_SecTVOutService->setHdmiMode(mode); +} + +void SecHdmiClient::setHdmiResolution(int resolution) +{ + //LOGD("%s HDMI Resolution: %d\n", __func__, resolution); + + if (g_SecTVOutService != 0) + g_SecTVOutService->setHdmiResolution(resolution); +} + +void SecHdmiClient::setHdmiHdcp(int enHdcp) +{ + //LOGD("%s HDMI HDCP: %d\n", __func__, enHdcp); + + if (g_SecTVOutService != 0) + g_SecTVOutService->setHdmiHdcp(enHdcp); +} + +void SecHdmiClient::setHdmiRotate(int rotVal, uint32_t hwcLayer) +{ + //LOGD("%s HDMI ROTATE: %d\n", __func__, rotVal); + + if (g_SecTVOutService != 0) + g_SecTVOutService->setHdmiRotate(rotVal, hwcLayer); +} + +void SecHdmiClient::setHdmiHwcLayer(uint32_t hwcLayer) +{ + //LOGD("%s HDMI HWCLAYER: %d\n", __func__, hwcLayer); + + if (g_SecTVOutService != 0) + g_SecTVOutService->setHdmiHwcLayer(hwcLayer); +} + +void SecHdmiClient::blit2Hdmi(uint32_t w, uint32_t h, + uint32_t colorFormat, + uint32_t physYAddr, + uint32_t physCbAddr, + uint32_t physCrAddr, + uint32_t dstX, + uint32_t dstY, + uint32_t hdmiLayer, + uint32_t num_of_hwc_layer) +{ + if (g_SecTVOutService != 0 ) + g_SecTVOutService->blit2Hdmi(w, h, colorFormat, physYAddr, physCbAddr, physCrAddr, dstX, dstY, hdmiLayer, num_of_hwc_layer); +} + +sp SecHdmiClient::m_getSecTVOutService(void) +{ + int ret = 0; + + if (g_SecTVOutService == 0) { + sp binder; + sp sc; + sp sm = defaultServiceManager(); + int getSvcTimes = 0; + for(getSvcTimes = 0; getSvcTimes < GETSERVICETIMEOUT; getSvcTimes++) { + binder = sm->getService(String16("SecTVOutService")); + if (binder == 0) { + LOGW("SecTVOutService not published, waiting..."); + usleep(500000); // 0.5 s + } else { + break; + } + } + // grab the lock again for updating g_surfaceFlinger + if (getSvcTimes < GETSERVICETIMEOUT) { + sc = interface_cast(binder); + g_SecTVOutService = sc; + } else { + LOGW("Failed to get SecTVOutService... SecHdmiClient will get it later.."); + } + } + return g_SecTVOutService; +} + +} diff --git a/exynos5/hal/libhdmi/libhdmiservice/SecHdmiClient.h b/exynos5/hal/libhdmi/libhdmiservice/SecHdmiClient.h new file mode 100644 index 0000000..e94e19a --- /dev/null +++ b/exynos5/hal/libhdmi/libhdmiservice/SecHdmiClient.h @@ -0,0 +1,84 @@ +/* +** +** Copyright 2008, The Android Open Source Project +** Copyright 2010, Samsung Electronics Co. LTD +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + +/* +** +** @author Taikyung, Yu(taikyung.yu@samsung.com) +** @date 2011-07-06 +*/ + +#ifndef __SEC_HDMI_CLIENT_H__ +#define __SEC_HDMI_CLIENT_H__ + +#include "utils/Log.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "ISecTVOut.h" + +#define GETSERVICETIMEOUT (5) + +namespace android { + +class SecHdmiClient +{ +public: + enum HDMI_MODE + { + HDMI_MODE_NONE = 0, + HDMI_MODE_UI, + HDMI_MODE_VIDEO, + }; + +private: + SecHdmiClient(); + virtual ~SecHdmiClient(); + +public: + static SecHdmiClient * getInstance(void); + void setHdmiCableStatus(int status); + void setHdmiMode(int mode); + void setHdmiResolution(int resolution); + void setHdmiHdcp(int enHdcp); + void setHdmiRotate(int rotVal, uint32_t hwcLayer); + void setHdmiHwcLayer(uint32_t hwcLayer); + virtual void blit2Hdmi(uint32_t w, uint32_t h, + uint32_t colorFormat, + uint32_t physYAddr, + uint32_t physCbAddr, + uint32_t physCrAddr, + uint32_t dstX, + uint32_t dstY, + uint32_t hdmiLayer, + uint32_t num_of_hwc_layer); + +private: + sp m_getSecTVOutService(void); + +}; + +}; + +#endif diff --git a/exynos5/hal/libhdmi/libhdmiservice/SecTVOutService.cpp b/exynos5/hal/libhdmi/libhdmiservice/SecTVOutService.cpp new file mode 100644 index 0000000..39ef742 --- /dev/null +++ b/exynos5/hal/libhdmi/libhdmiservice/SecTVOutService.cpp @@ -0,0 +1,377 @@ +/* +** +** Copyright 2008, The Android Open Source Project +** Copyright 2010, Samsung Electronics Co. LTD +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + +/* +** +** @author Taikyung, Yu(taikyung.yu@samsung.com) +** @date 2011-07-06 +*/ + +#define LOG_TAG "SecTVOutService" + +#include +#include +#include +#include +#include +#include "SecTVOutService.h" +#include + +namespace android { +#define DEFAULT_LCD_WIDTH 1280 +#define DEFAULT_LCD_HEIGHT 800 + +#define DIRECT_VIDEO_RENDERING (1) +#define DIRECT_UI_RENDERING (0) + + enum { + SET_HDMI_STATUS = IBinder::FIRST_CALL_TRANSACTION, + SET_HDMI_MODE, + SET_HDMI_RESOLUTION, + SET_HDMI_HDCP, + SET_HDMI_ROTATE, + SET_HDMI_HWCLAYER, + BLIT_2_HDMI + }; + + int SecTVOutService::HdmiFlushThread() + { + while (!mExitHdmiFlushThread) { + nsecs_t timeout = -1; + sp msg = mHdmiEventQueue.waitMessage(timeout); + } + + return 0; + } + + int SecTVOutService::instantiate() + { + LOGD("SecTVOutService instantiate"); + int r = defaultServiceManager()->addService(String16( "SecTVOutService"), new SecTVOutService ()); + LOGD("SecTVOutService r=%d", r); + + return r; + } + + SecTVOutService::SecTVOutService () { + LOGV("SecTVOutService created"); + mHdmiCableInserted = false; +#ifdef SUPPORT_G2D_UI_MODE + mUILayerMode = SecHdmi::HDMI_LAYER_GRAPHIC_1; +#else + mUILayerMode = SecHdmi::HDMI_LAYER_VIDEO; +#endif + mHwcLayer = 0; + mExitHdmiFlushThread = false; + + setLCDsize(); + if (mSecHdmi.create(mLCD_width, mLCD_height) == false) + LOGE("%s::mSecHdmi.create() fail", __func__); + else + setHdmiStatus(1); + + mHdmiFlushThread = new HDMIFlushThread(this); + } + + void SecTVOutService::setLCDsize(void) { + char const * const device_template[] = { + "/dev/graphics/fb%u", + "/dev/fb%u", + 0 }; + + int fd = -1; + int i = 0; + char name[64]; + + while ((fd==-1) && device_template[i]) { + snprintf(name, 64, device_template[i], 0); + fd = open(name, O_RDWR, 0); + i++; + } + if (fd > 0) { + struct fb_var_screeninfo info; + if (ioctl(fd, FBIOGET_VSCREENINFO, &info) != -1) { + mLCD_width = info.xres; + mLCD_height = info.yres; + } else { + mLCD_width = DEFAULT_LCD_WIDTH; + mLCD_height = DEFAULT_LCD_HEIGHT; + } + close(fd); + } + return; + } + + SecTVOutService::~SecTVOutService () { + LOGV ("SecTVOutService destroyed"); + + if (mHdmiFlushThread != NULL) { + mHdmiFlushThread->requestExit(); + mExitHdmiFlushThread = true; + mHdmiFlushThread->requestExitAndWait(); + mHdmiFlushThread.clear(); + } + } + + status_t SecTVOutService::onTransact(uint32_t code, const Parcel & data, Parcel * reply, uint32_t flags) + { + switch (code) { + case SET_HDMI_STATUS: { + int status = data.readInt32(); + setHdmiStatus(status); + } break; + + case SET_HDMI_MODE: { + int mode = data.readInt32(); + setHdmiMode(mode); + } break; + + case SET_HDMI_RESOLUTION: { + int resolution = data.readInt32(); + setHdmiResolution(resolution); + } break; + + case SET_HDMI_HDCP: { + int enHdcp = data.readInt32(); + setHdmiHdcp(enHdcp); + } break; + + case SET_HDMI_ROTATE: { + int rotVal = data.readInt32(); + int hwcLayer = data.readInt32(); + setHdmiRotate(rotVal, hwcLayer); + } break; + + case SET_HDMI_HWCLAYER: { + int hwcLayer = data.readInt32(); + setHdmiHwcLayer((uint32_t)hwcLayer); + } break; + + case BLIT_2_HDMI: { + uint32_t w = data.readInt32(); + uint32_t h = data.readInt32(); + uint32_t colorFormat = data.readInt32(); + uint32_t physYAddr = data.readInt32(); + uint32_t physCbAddr = data.readInt32(); + uint32_t physCrAddr = data.readInt32(); + uint32_t dstX = data.readInt32(); + uint32_t dstY = data.readInt32(); + uint32_t hdmiLayer = data.readInt32(); + uint32_t num_of_hwc_layer = data.readInt32(); + + blit2Hdmi(w, h, colorFormat, physYAddr, physCbAddr, physCrAddr, dstX, dstY, hdmiLayer, num_of_hwc_layer); + } break; + + default : + LOGE ( "onTransact::default"); + return BBinder::onTransact (code, data, reply, flags); + } + + return NO_ERROR; + } + + void SecTVOutService::setHdmiStatus(uint32_t status) + { + LOGD("%s HDMI cable status = %d", __func__, status); + { + Mutex::Autolock _l(mLock); + + bool hdmiCableInserted = (bool)status; + + if (mHdmiCableInserted == hdmiCableInserted) + return; + + if (hdmiCableInserted == true) { + if (mSecHdmi.connect() == false) { + LOGE("%s::mSecHdmi.connect() fail", __func__); + hdmiCableInserted = false; + } + } else { + if (mSecHdmi.disconnect() == false) + LOGE("%s::mSecHdmi.disconnect() fail", __func__); + } + + mHdmiCableInserted = hdmiCableInserted; + } + + if (hdmiCableInserted() == true) + this->blit2Hdmi(mLCD_width, mLCD_height, HAL_PIXEL_FORMAT_BGRA_8888, 0, 0, 0, 0, 0, HDMI_MODE_UI, 0); + } + + void SecTVOutService::setHdmiMode(uint32_t mode) + { + LOGD("%s TV mode = %d", __func__, mode); + Mutex::Autolock _l(mLock); + + if ((hdmiCableInserted() == true) && (mSecHdmi.setHdmiOutputMode(mode)) == false) { + LOGE("%s::mSecHdmi.setHdmiOutputMode() fail", __func__); + return; + } + } + + void SecTVOutService::setHdmiResolution(uint32_t resolution) + { + LOGD("%s TV resolution = %d", __func__, resolution); + Mutex::Autolock _l(mLock); + + if ((hdmiCableInserted() == true) && (mSecHdmi.setHdmiResolution(resolution)) == false) { + LOGE("%s::mSecHdmi.setHdmiResolution() fail", __func__); + return; + } + } + + void SecTVOutService::setHdmiHdcp(uint32_t hdcp_en) + { + LOGD("%s TV HDCP = %d", __func__, hdcp_en); + Mutex::Autolock _l(mLock); + + if ((hdmiCableInserted() == true) && (mSecHdmi.setHdcpMode(hdcp_en)) == false) { + LOGE("%s::mSecHdmi.setHdcpMode() fail", __func__); + return; + } + } + + void SecTVOutService::setHdmiRotate(uint32_t rotVal, uint32_t hwcLayer) + { + //LOGD("%s TV ROTATE = %d", __func__, rotVal); + Mutex::Autolock _l(mLock); + + if ((hdmiCableInserted() == true) && (mSecHdmi.setUIRotation(rotVal, hwcLayer)) == false) { + LOGE("%s::mSecHdmi.setUIRotation() fail", __func__); + return; + } + } + + void SecTVOutService::setHdmiHwcLayer(uint32_t hwcLayer) + { + //LOGD("%s TV HWCLAYER = %d", __func__, hwcLayer); + Mutex::Autolock _l(mLock); + + mHwcLayer = hwcLayer; + return; + } + + void SecTVOutService::blit2Hdmi(uint32_t w, uint32_t h, uint32_t colorFormat, + uint32_t pPhyYAddr, uint32_t pPhyCbAddr, uint32_t pPhyCrAddr, + uint32_t dstX, uint32_t dstY, + uint32_t hdmiMode, + uint32_t num_of_hwc_layer) + { + Mutex::Autolock _l(mLock); + + if (hdmiCableInserted() == false) + return; + + int hdmiLayer = SecHdmi::HDMI_LAYER_VIDEO; +#if defined(CHECK_UI_TIME) || defined(CHECK_VIDEO_TIME) + nsecs_t start, end; +#endif + + sp msg; + + switch (hdmiMode) { + case HDMI_MODE_UI : + if (mHwcLayer >= 2) + hdmiLayer = SecHdmi::HDMI_LAYER_GRAPHIC_0; + else if (mHwcLayer == 1) + hdmiLayer = SecHdmi::HDMI_LAYER_GRAPHIC_1; + else +#ifdef SUPPORT_G2D_UI_MODE + hdmiLayer = SecHdmi::HDMI_LAYER_GRAPHIC_1; +#else + hdmiLayer = SecHdmi::HDMI_LAYER_VIDEO; +#endif + + if (mHwcLayer == 0) { + for (int layer = SecHdmi::HDMI_LAYER_BASE + 1; layer < SecHdmi::HDMI_LAYER_MAX; layer++) { + if (layer != mUILayerMode) { + if (mSecHdmi.clear(layer) == false) + LOGE("%s::mSecHdmi.clear(%d) fail", __func__, layer); + } + } + } + + if (mUILayerMode != hdmiLayer) { + if (mSecHdmi.clear(mUILayerMode) == false) + LOGE("%s::mSecHdmi.clear(%d) fail", __func__, mUILayerMode); + } + + mUILayerMode = hdmiLayer; + +#if !defined(BOARD_USES_HDMI_SUBTITLES) + if (mHwcLayer == 0) +#endif +#if (DIRECT_UI_RENDERING == 1) + { +#ifdef CHECK_UI_TIME + start = systemTime(); +#endif + if (mSecHdmi.flush(w, h, colorFormat, pPhyYAddr, pPhyCbAddr, pPhyCrAddr, dstX, dstY, + mUILayerMode, mHwcLayer) == false) + LOGE("%s::mSecHdmi.flush() on HDMI_MODE_UI fail", __func__); +#ifdef CHECK_UI_TIME + end = systemTime(); + LOGD("[UI] mSecHdmi.flush[end-start] = %ld ms", long(ns2ms(end)) - long(ns2ms(start))); +#endif + } +#else + { + msg = new SecHdmiEventMsg(&mSecHdmi, w, h, colorFormat, pPhyYAddr, pPhyCbAddr, pPhyCrAddr, + dstX, dstY, mUILayerMode, mHwcLayer, HDMI_MODE_UI); + + /* post to HdmiEventQueue */ + mHdmiEventQueue.postMessage(msg, 0, 0); + } +#endif + break; + + case HDMI_MODE_VIDEO : +#if (DIRECT_VIDEO_RENDERING == 1) +#ifdef CHECK_VIDEO_TIME + start = systemTime(); +#endif + if (mSecHdmi.flush(w, h, colorFormat, pPhyYAddr, pPhyCbAddr, pPhyCrAddr, dstX, dstY, + SecHdmi::HDMI_LAYER_VIDEO, mHwcLayer) == false) + LOGE("%s::mSecHdmi.flush() on HDMI_MODE_VIDEO fail", __func__); +#ifdef CHECK_VIDEO_TIME + end = systemTime(); + LOGD("[Video] mSecHdmi.flush[end-start] = %ld ms", long(ns2ms(end)) - long(ns2ms(start))); +#endif +#else + msg = new SecHdmiEventMsg(&mSecHdmi, w, h, colorFormat, pPhyYAddr, pPhyCbAddr, pPhyCrAddr, + dstX, dstY, SecHdmi::HDMI_LAYER_VIDEO, mHwcLayer, HDMI_MODE_VIDEO); + + /* post to HdmiEventQueue */ + mHdmiEventQueue.postMessage(msg, 0, 0); +#endif + break; + + default: + LOGE("unmatched HDMI_MODE : %d", hdmiMode); + break; + } + + return; + } + + bool SecTVOutService::hdmiCableInserted(void) + { + return mHdmiCableInserted; + } + +} diff --git a/exynos5/hal/libhdmi/libhdmiservice/SecTVOutService.h b/exynos5/hal/libhdmi/libhdmiservice/SecTVOutService.h new file mode 100644 index 0000000..caece73 --- /dev/null +++ b/exynos5/hal/libhdmi/libhdmiservice/SecTVOutService.h @@ -0,0 +1,175 @@ +/* +** +** Copyright 2008, The Android Open Source Project +** Copyright 2010, Samsung Electronics Co. LTD +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + +/* +** +** @author Taikyung, Yu(taikyung.yu@samsung.com) +** @date 2011-07-06 +*/ + +#ifndef SECTVOUTSERVICE_H +#define SECTVOUTSERVICE_H + +#include +#include +#include +#include + +#include "ISecTVOut.h" +#include "SecHdmi.h" +#include "sec_format.h" +#include "sec_utils_v4l2.h" +#include "MessageQueue.h" + +namespace android { +//#define CHECK_VIDEO_TIME +//#define CHECK_UI_TIME + + class SecTVOutService : public BBinder + { + public : + enum { + HDMI_MODE_NONE = 0, + HDMI_MODE_UI, + HDMI_MODE_VIDEO, + }; + + mutable Mutex mLock; + + class HDMIFlushThread : public Thread { + SecTVOutService *mTVOutService; + public: + HDMIFlushThread(SecTVOutService *service): + Thread(false), + mTVOutService(service) { } + virtual void onFirstRef() { + run("HDMIFlushThread", PRIORITY_URGENT_DISPLAY); + } + virtual bool threadLoop() { + mTVOutService->HdmiFlushThread(); + return false; + } + }; + + sp mHdmiFlushThread; + int HdmiFlushThread(); + + mutable MessageQueue mHdmiEventQueue; + bool mExitHdmiFlushThread; + + SecTVOutService(); + static int instantiate (); + virtual status_t onTransact(uint32_t, const Parcel &, Parcel *, uint32_t); + virtual ~SecTVOutService (); + + virtual void setHdmiStatus(uint32_t status); + virtual void setHdmiMode(uint32_t mode); + virtual void setHdmiResolution(uint32_t resolution); + virtual void setHdmiHdcp(uint32_t enHdcp); + virtual void setHdmiRotate(uint32_t rotVal, uint32_t hwcLayer); + virtual void setHdmiHwcLayer(uint32_t hwcLayer); + virtual void blit2Hdmi(uint32_t w, uint32_t h, + uint32_t colorFormat, + uint32_t pPhyYAddr, uint32_t pPhyCbAddr, uint32_t pPhyCrAddr, + uint32_t dstX, uint32_t dstY, + uint32_t hdmiMode, uint32_t num_of_hwc_layer); + bool hdmiCableInserted(void); + void setLCDsize(void); + + private: + SecHdmi mSecHdmi; + bool mHdmiCableInserted; + int mUILayerMode; + uint32_t mLCD_width, mLCD_height; + uint32_t mHwcLayer; + }; + + class SecHdmiEventMsg : public MessageBase { + public: + enum { + HDMI_MODE_NONE = 0, + HDMI_MODE_UI, + HDMI_MODE_VIDEO, + }; + + mutable Mutex mBlitLock; + + SecHdmi *pSecHdmi; + uint32_t mSrcWidth, mSrcHeight; + uint32_t mSrcColorFormat; + uint32_t mSrcYAddr, mSrcCbAddr, mSrcCrAddr; + uint32_t mDstX, mDstY; + uint32_t mHdmiMode; + uint32_t mHdmiLayer, mHwcLayer; + + SecHdmiEventMsg(SecHdmi *SecHdmi, uint32_t srcWidth, uint32_t srcHeight, uint32_t srcColorFormat, + uint32_t srcYAddr, uint32_t srcCbAddr, uint32_t srcCrAddr, + uint32_t dstX, uint32_t dstY, uint32_t hdmiLayer, uint32_t hwcLayer, uint32_t hdmiMode) + : pSecHdmi(SecHdmi), mSrcWidth(srcWidth), mSrcHeight(srcHeight), mSrcColorFormat(srcColorFormat), + mSrcYAddr(srcYAddr), mSrcCbAddr(srcCbAddr), mSrcCrAddr(srcCrAddr), + mDstX(dstX), mDstY(dstY), mHdmiLayer(hdmiLayer), mHwcLayer(hwcLayer), mHdmiMode(hdmiMode) { + } + + virtual bool handler() { + Mutex::Autolock _l(mBlitLock); + bool ret = true; +#if defined(CHECK_UI_TIME) || defined(CHECK_VIDEO_TIME) + nsecs_t start, end; +#endif + + switch (mHdmiMode) { + case HDMI_MODE_UI: +#ifdef CHECK_UI_TIME + start = systemTime(); +#endif + if (pSecHdmi->flush(mSrcWidth, mSrcHeight, mSrcColorFormat, mSrcYAddr, mSrcCbAddr, mSrcCrAddr, + mDstX, mDstY, mHdmiLayer, mHwcLayer) == false) { + LOGE("%s::pSecHdmi->flush() fail on HDMI_MODE_UI", __func__); + ret = false; + } + +#ifdef CHECK_UI_TIME + end = systemTime(); + LOGD("[UI] pSecHdmi->flush[end-start] = %ld ms", long(ns2ms(end)) - long(ns2ms(start))); +#endif + break; + case HDMI_MODE_VIDEO: +#ifdef CHECK_VIDEO_TIME + start = systemTime(); +#endif + if (pSecHdmi->flush(mSrcWidth, mSrcHeight, mSrcColorFormat, mSrcYAddr, mSrcCbAddr, mSrcCrAddr, + mDstX, mDstY, mHdmiLayer, mHwcLayer) == false) { + LOGE("%s::pSecHdmi->flush() fail on HDMI_MODE_VIDEO", __func__); + ret = false; + } +#ifdef CHECK_VIDEO_TIME + end = systemTime(); + LOGD("[VIDEO] pSecHdmi->flush[end-start] = %ld ms", long(ns2ms(end)) - long(ns2ms(start))); +#endif + break; + default: + LOGE("Undefined HDMI_MODE"); + ret = false; + break; + } + return ret; + } + }; + +}; +#endif diff --git a/exynos5/hal/libhdmi/libsForhdmi/Android.mk b/exynos5/hal/libhdmi/libsForhdmi/Android.mk new file mode 100644 index 0000000..9acbc52 --- /dev/null +++ b/exynos5/hal/libhdmi/libsForhdmi/Android.mk @@ -0,0 +1,17 @@ +# Copyright (C) 2008 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +ifeq ($(filter-out exynos5,$(TARGET_BOARD_PLATFORM)),) +include $(all-subdir-makefiles) +endif diff --git a/exynos5/hal/libhdmi/libsForhdmi/libcec/Android.mk b/exynos5/hal/libhdmi/libsForhdmi/libcec/Android.mk new file mode 100644 index 0000000..9a4b721 --- /dev/null +++ b/exynos5/hal/libhdmi/libsForhdmi/libcec/Android.mk @@ -0,0 +1,33 @@ +# Copyright (C) 2008 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +ifeq ($(BOARD_USES_HDMI),true) + +LOCAL_PATH:= $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_MODULE_TAGS := eng + +LOCAL_PRELINK_MODULE := false +LOCAL_SHARED_LIBRARIES := liblog +LOCAL_SRC_FILES := libcec.c + +LOCAL_C_INCLUDES := \ + $(LOCAL_PATH) \ + $(LOCAL_PATH)/../../../include + +LOCAL_MODULE := libcec +include $(BUILD_SHARED_LIBRARY) + +endif diff --git a/exynos5/hal/libhdmi/libsForhdmi/libcec/cec.h b/exynos5/hal/libhdmi/libsForhdmi/libcec/cec.h new file mode 100644 index 0000000..4b0d3af --- /dev/null +++ b/exynos5/hal/libhdmi/libsForhdmi/libcec/cec.h @@ -0,0 +1,11 @@ +#ifndef _LINUX_CEC_H_ +#define _LINUX_CEC_H_ + +#define CEC_IOC_MAGIC 'c' + +/** + * CEC device request code to set logical address. + */ +#define CEC_IOC_SETLADDR _IOW(CEC_IOC_MAGIC, 0, unsigned int) + +#endif /* _LINUX_CEC_H_ */ diff --git a/exynos5/hal/libhdmi/libsForhdmi/libcec/libcec.c b/exynos5/hal/libhdmi/libsForhdmi/libcec/libcec.c new file mode 100644 index 0000000..e688051 --- /dev/null +++ b/exynos5/hal/libhdmi/libsForhdmi/libcec/libcec.c @@ -0,0 +1,386 @@ +/* +* Copyright@ Samsung Electronics Co. LTD +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include + +/* drv. header */ +#include "cec.h" + +#include "libcec.h" + +#define CEC_DEBUG 0 + +/** + * @def CEC_DEVICE_NAME + * Defines simbolic name of the CEC device. + */ +#define CEC_DEVICE_NAME "/dev/CEC" + +static struct { + enum CECDeviceType devtype; + unsigned char laddr; +} laddresses[] = { + { CEC_DEVICE_RECODER, 1 }, + { CEC_DEVICE_RECODER, 2 }, + { CEC_DEVICE_TUNER, 3 }, + { CEC_DEVICE_PLAYER, 4 }, + { CEC_DEVICE_AUDIO, 5 }, + { CEC_DEVICE_TUNER, 6 }, + { CEC_DEVICE_TUNER, 7 }, + { CEC_DEVICE_PLAYER, 8 }, + { CEC_DEVICE_RECODER, 9 }, + { CEC_DEVICE_TUNER, 10 }, + { CEC_DEVICE_PLAYER, 11 }, +}; + +static int CECSetLogicalAddr(unsigned int laddr); + +#ifdef CEC_DEBUG +inline static void CECPrintFrame(unsigned char *buffer, unsigned int size); +#endif + +static int fd = -1; + +/** + * Open device driver and assign CEC file descriptor. + * + * @return If success to assign CEC file descriptor, return 1; otherwise, return 0. + */ +int CECOpen() +{ + int res = 1; + + if (fd != -1) + CECClose(); + + if ((fd = open(CEC_DEVICE_NAME, O_RDWR)) < 0) { + LOGE("Can't open %s!\n", CEC_DEVICE_NAME); + res = 0; + } + + return res; +} + +/** + * Close CEC file descriptor. + * + * @return If success to close CEC file descriptor, return 1; otherwise, return 0. + */ +int CECClose() +{ + int res = 1; + + if (fd != -1) { + if (close(fd) != 0) { + LOGE("close() failed!\n"); + res = 0; + } + fd = -1; + } + + return res; +} + +/** + * Allocate logical address. + * + * @param paddr [in] CEC device physical address. + * @param devtype [in] CEC device type. + * + * @return new logical address, or 0 if an arror occured. + */ +int CECAllocLogicalAddress(int paddr, enum CECDeviceType devtype) +{ + unsigned char laddr = CEC_LADDR_UNREGISTERED; + int i = 0; + + if (fd == -1) { + LOGE("open device first!\n"); + return 0; + } + + if (CECSetLogicalAddr(laddr) < 0) { + LOGE("CECSetLogicalAddr() failed!\n"); + return 0; + } + + if (paddr == CEC_NOT_VALID_PHYSICAL_ADDRESS) + return CEC_LADDR_UNREGISTERED; + + /* send "Polling Message" */ + while (i < sizeof(laddresses)/sizeof(laddresses[0])) { + if (laddresses[i].devtype == devtype) { + unsigned char _laddr = laddresses[i].laddr; + unsigned char message = ((_laddr << 4) | _laddr); + if (CECSendMessage(&message, 1) != 1) { + laddr = _laddr; + break; + } + } + i++; + } + + if (laddr == CEC_LADDR_UNREGISTERED) { + LOGE("All LA addresses in use!!!\n"); + return CEC_LADDR_UNREGISTERED; + } + + if (CECSetLogicalAddr(laddr) < 0) { + LOGE("CECSetLogicalAddr() failed!\n"); + return 0; + } + + /* broadcast "Report Physical Address" */ + unsigned char buffer[5]; + buffer[0] = (laddr << 4) | CEC_MSG_BROADCAST; + buffer[1] = CEC_OPCODE_REPORT_PHYSICAL_ADDRESS; + buffer[2] = (paddr >> 8) & 0xFF; + buffer[3] = paddr & 0xFF; + buffer[4] = devtype; + + if (CECSendMessage(buffer, 5) != 5) { + LOGE("CECSendMessage() failed!\n"); + return 0; + } + + return laddr; +} + +/** + * Send CEC message. + * + * @param *buffer [in] pointer to buffer address where message located. + * @param size [in] message size. + * + * @return number of bytes written, or 0 if an arror occured. + */ +int CECSendMessage(unsigned char *buffer, int size) +{ + if (fd == -1) { + LOGE("open device first!\n"); + return 0; + } + + if (size > CEC_MAX_FRAME_SIZE) { + LOGE("size should not exceed %d\n", CEC_MAX_FRAME_SIZE); + return 0; + } + +#if CEC_DEBUG + LOGI("CECSendMessage() : "); + CECPrintFrame(buffer, size); +#endif + + return write(fd, buffer, size); +} + +/** + * Receive CEC message. + * + * @param *buffer [in] pointer to buffer address where message will be stored. + * @param size [in] buffer size. + * @param timeout [in] timeout in microseconds. + * + * @return number of bytes received, or 0 if an arror occured. + */ +int CECReceiveMessage(unsigned char *buffer, int size, long timeout) +{ + int bytes = 0; + fd_set rfds; + struct timeval tv; + int retval; + + if (fd == -1) { + LOGE("open device first!\n"); + return 0; + } + + tv.tv_sec = 0; + tv.tv_usec = timeout; + + FD_ZERO(&rfds); + FD_SET(fd, &rfds); + + retval = select(fd + 1, &rfds, NULL, NULL, &tv); + + if (retval == -1) { + return 0; + } else if (retval) { + bytes = read(fd, buffer, size); +#if CEC_DEBUG + LOGI("CECReceiveMessage() : size(%d)", bytes); + if(bytes > 0) + CECPrintFrame(buffer, bytes); +#endif + } + + return bytes; +} + +/** + * Set CEC logical address. + * + * @return 1 if success, otherwise, return 0. + */ +int CECSetLogicalAddr(unsigned int laddr) +{ + if (ioctl(fd, CEC_IOC_SETLADDR, &laddr)) { + LOGE("ioctl(CEC_IOC_SETLA) failed!\n"); + return 0; + } + + return 1; +} + +#if CEC_DEBUG +/** + * Print CEC frame. + */ +void CECPrintFrame(unsigned char *buffer, unsigned int size) +{ + if (size > 0) { + int i; + LOGI("fsize: %d ", size); + LOGI("frame: "); + for (i = 0; i < size; i++) + LOGI("0x%02x ", buffer[i]); + + LOGI("\n"); + } +} +#endif + +/** + * Check CEC message. + * + * @param opcode [in] pointer to buffer address where message will be stored. + * @param lsrc [in] buffer size. + * + * @return 1 if message should be ignored, otherwise, return 0. + */ +//TODO: not finished +int CECIgnoreMessage(unsigned char opcode, unsigned char lsrc) +{ + int retval = 0; + + /* if a message coming from address 15 (unregistered) */ + if (lsrc == CEC_LADDR_UNREGISTERED) { + switch (opcode) { + case CEC_OPCODE_DECK_CONTROL: + case CEC_OPCODE_PLAY: + retval = 1; + default: + break; + } + } + + return retval; +} + +/** + * Check CEC message. + * + * @param opcode [in] pointer to buffer address where message will be stored. + * @param size [in] message size. + * + * @return 0 if message should be ignored, otherwise, return 1. + */ +//TODO: not finished +int CECCheckMessageSize(unsigned char opcode, int size) +{ + int retval = 1; + + switch (opcode) { + case CEC_OPCODE_REQUEST_ACTIVE_SOURCE: + if (size != 1) + retval = 0; + break; + case CEC_OPCODE_SET_SYSTEM_AUDIO_MODE: + if (size != 2) + retval = 0; + break; + case CEC_OPCODE_PLAY: + case CEC_OPCODE_DECK_CONTROL: + case CEC_OPCODE_SET_MENU_LANGUAGE: + case CEC_OPCODE_ACTIVE_SOURCE: + case CEC_OPCODE_ROUTING_INFORMATION: + case CEC_OPCODE_SET_STREAM_PATH: + if (size != 3) + retval = 0; + break; + case CEC_OPCODE_FEATURE_ABORT: + case CEC_OPCODE_DEVICE_VENDOR_ID: + case CEC_OPCODE_REPORT_PHYSICAL_ADDRESS: + if (size != 4) + retval = 0; + break; + case CEC_OPCODE_ROUTING_CHANGE: + if (size != 5) + retval = 0; + break; + /* CDC - 1.4 */ + case 0xf8: + if (!(size > 5 && size <= 16)) + retval = 0; + break; + default: + break; + } + + return retval; +} + +/** + * Check CEC message. + * + * @param opcode [in] pointer to buffer address where message will be stored. + * @param broadcast [in] broadcast/direct message. + * + * @return 0 if message should be ignored, otherwise, return 1. + */ +//TODO: not finished +int CECCheckMessageMode(unsigned char opcode, int broadcast) +{ + int retval = 1; + + switch (opcode) { + case CEC_OPCODE_REQUEST_ACTIVE_SOURCE: + case CEC_OPCODE_SET_MENU_LANGUAGE: + case CEC_OPCODE_ACTIVE_SOURCE: + if (!broadcast) + retval = 0; + break; + case CEC_OPCODE_GIVE_PHYSICAL_ADDRESS: + case CEC_OPCODE_DECK_CONTROL: + case CEC_OPCODE_PLAY: + case CEC_OPCODE_FEATURE_ABORT: + case CEC_OPCODE_ABORT: + if (broadcast) + retval = 0; + break; + default: + break; + } + + return retval; +} diff --git a/exynos5/hal/libhdmi/libsForhdmi/libcec/libcec.h b/exynos5/hal/libhdmi/libsForhdmi/libcec/libcec.h new file mode 100644 index 0000000..5bbfc15 --- /dev/null +++ b/exynos5/hal/libhdmi/libsForhdmi/libcec/libcec.h @@ -0,0 +1,209 @@ +/* + * Copyright@ Samsung Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _LIBCEC_H_ +#define _LIBCEC_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/** Maximum CEC frame size */ +#define CEC_MAX_FRAME_SIZE 16 +/** Not valid CEC physical address */ +#define CEC_NOT_VALID_PHYSICAL_ADDRESS 0xFFFF + +/** CEC broadcast address (as destination address) */ +#define CEC_MSG_BROADCAST 0x0F +/** CEC unregistered address (as initiator address) */ +#define CEC_LADDR_UNREGISTERED 0x0F + +/* + * CEC Messages + */ + +//@{ +/** @name Messages for the One Touch Play Feature */ +#define CEC_OPCODE_ACTIVE_SOURCE 0x82 +#define CEC_OPCODE_IMAGE_VIEW_ON 0x04 +#define CEC_OPCODE_TEXT_VIEW_ON 0x0D +//@} + +//@{ +/** @name Messages for the Routing Control Feature */ +#define CEC_OPCODE_INACTIVE_SOURCE 0x9D +#define CEC_OPCODE_REQUEST_ACTIVE_SOURCE 0x85 +#define CEC_OPCODE_ROUTING_CHANGE 0x80 +#define CEC_OPCODE_ROUTING_INFORMATION 0x81 +#define CEC_OPCODE_SET_STREAM_PATH 0x86 +//@} + +//@{ +/** @name Messages for the Standby Feature */ +#define CEC_OPCODE_STANDBY 0x36 +//@} + +//@{ +/** @name Messages for the One Touch Record Feature */ +#define CEC_OPCODE_RECORD_OFF 0x0B +#define CEC_OPCODE_RECORD_ON 0x09 +#define CEC_OPCODE_RECORD_STATUS 0x0A +#define CEC_OPCODE_RECORD_TV_SCREEN 0x0F +//@} + +//@{ +/** @name Messages for the Timer Programming Feature */ +#define CEC_OPCODE_CLEAR_ANALOGUE_TIMER 0x33 +#define CEC_OPCODE_CLEAR_DIGITAL_TIMER 0x99 +#define CEC_OPCODE_CLEAR_EXTERNAL_TIMER 0xA1 +#define CEC_OPCODE_SET_ANALOGUE_TIMER 0x34 +#define CEC_OPCODE_SET_DIGITAL_TIMER 0x97 +#define CEC_OPCODE_SET_EXTERNAL_TIMER 0xA2 +#define CEC_OPCODE_SET_TIMER_PROGRAM_TITLE 0x67 +#define CEC_OPCODE_TIMER_CLEARED_STATUS 0x43 +#define CEC_OPCODE_TIMER_STATUS 0x35 +//@} + +//@{ +/** @name Messages for the System Information Feature */ +#define CEC_OPCODE_CEC_VERSION 0x9E +#define CEC_OPCODE_GET_CEC_VERSION 0x9F +#define CEC_OPCODE_GIVE_PHYSICAL_ADDRESS 0x83 +#define CEC_OPCODE_GET_MENU_LANGUAGE 0x91 +//#define CEC_OPCODE_POLLING_MESSAGE +#define CEC_OPCODE_REPORT_PHYSICAL_ADDRESS 0x84 +#define CEC_OPCODE_SET_MENU_LANGUAGE 0x32 +//@} + +//@{ +/** @name Messages for the Deck Control Feature */ +#define CEC_OPCODE_DECK_CONTROL 0x42 +#define CEC_OPCODE_DECK_STATUS 0x1B +#define CEC_OPCODE_GIVE_DECK_STATUS 0x1A +#define CEC_OPCODE_PLAY 0x41 +//@} + +//@{ +/** @name Messages for the Tuner Control Feature */ +#define CEC_OPCODE_GIVE_TUNER_DEVICE_STATUS 0x08 +#define CEC_OPCODE_SELECT_ANALOGUE_SERVICE 0x92 +#define CEC_OPCODE_SELECT_DIGITAL_SERVICE 0x93 +#define CEC_OPCODE_TUNER_DEVICE_STATUS 0x07 +#define CEC_OPCODE_TUNER_STEP_DECREMENT 0x06 +#define CEC_OPCODE_TUNER_STEP_INCREMENT 0x05 +//@} + +//@{ +/** @name Messages for the Vendor Specific Commands Feature */ +#define CEC_OPCODE_DEVICE_VENDOR_ID 0x87 +#define CEC_OPCODE_GET_DEVICE_VENDOR_ID 0x8C +#define CEC_OPCODE_VENDOR_COMMAND 0x89 +#define CEC_OPCODE_VENDOR_COMMAND_WITH_ID 0xA0 +#define CEC_OPCODE_VENDOR_REMOTE_BUTTON_DOWN 0x8A +#define CEC_OPCODE_VENDOR_REMOVE_BUTTON_UP 0x8B +//@} + +//@{ +/** @name Messages for the OSD Display Feature */ +#define CEC_OPCODE_SET_OSD_STRING 0x64 +//@} + +//@{ +/** @name Messages for the Device OSD Transfer Feature */ +#define CEC_OPCODE_GIVE_OSD_NAME 0x46 +#define CEC_OPCODE_SET_OSD_NAME 0x47 +//@} + +//@{ +/** @name Messages for the Device Menu Control Feature */ +#define CEC_OPCODE_MENU_REQUEST 0x8D +#define CEC_OPCODE_MENU_STATUS 0x8E +#define CEC_OPCODE_USER_CONTROL_PRESSED 0x44 +#define CEC_OPCODE_USER_CONTROL_RELEASED 0x45 +//@} + +//@{ +/** @name Messages for the Remote Control Passthrough Feature */ +//@} + +//@{ +/** @name Messages for the Power Status Feature */ +#define CEC_OPCODE_GIVE_DEVICE_POWER_STATUS 0x8F +#define CEC_OPCODE_REPORT_POWER_STATUS 0x90 +//@} + +//@{ +/** @name Messages for General Protocol messages */ +#define CEC_OPCODE_FEATURE_ABORT 0x00 +#define CEC_OPCODE_ABORT 0xFF +//@} + +//@{ +/** @name Messages for the System Audio Control Feature */ +#define CEC_OPCODE_GIVE_AUDIO_STATUS 0x71 +#define CEC_OPCODE_GIVE_SYSTEM_AUDIO_MODE_STATUS 0x7D +#define CEC_OPCODE_REPORT_AUDIO_STATUS 0x7A +#define CEC_OPCODE_SET_SYSTEM_AUDIO_MODE 0x72 +#define CEC_OPCODE_SYSTEM_AUDIO_MODE_REQUEST 0x70 +#define CEC_OPCODE_SYSTEM_AUDIO_MODE_STATUS 0x7E +//@} + +//@{ +/** @name Messages for the Audio Rate Control Feature */ +#define CEC_OPCODE_SET_AUDIO_RATE 0x9A +//@} + +//@{ +/** @name CEC Operands */ + +//TODO: not finished + +#define CEC_DECK_CONTROL_MODE_STOP 0x03 +#define CEC_PLAY_MODE_PLAY_FORWARD 0x24 +//@} + +/** + * @enum CECDeviceType + * Type of CEC device + */ +enum CECDeviceType { + /** TV */ + CEC_DEVICE_TV, + /** Recording Device */ + CEC_DEVICE_RECODER, + /** Tuner */ + CEC_DEVICE_TUNER, + /** Playback Device */ + CEC_DEVICE_PLAYER, + /** Audio System */ + CEC_DEVICE_AUDIO, +}; + +int CECOpen(); +int CECClose(); +int CECAllocLogicalAddress(int paddr, enum CECDeviceType devtype); +int CECSendMessage(unsigned char *buffer, int size); +int CECReceiveMessage(unsigned char *buffer, int size, long timeout); + +int CECIgnoreMessage(unsigned char opcode, unsigned char lsrc); +int CECCheckMessageSize(unsigned char opcode, int size); +int CECCheckMessageMode(unsigned char opcode, int broadcast); + +#ifdef __cplusplus +} +#endif + +#endif /* _LIBCEC_H_ */ diff --git a/exynos5/hal/libhdmi/libsForhdmi/libddc/Android.mk b/exynos5/hal/libhdmi/libsForhdmi/libddc/Android.mk new file mode 100644 index 0000000..99af09b --- /dev/null +++ b/exynos5/hal/libhdmi/libsForhdmi/libddc/Android.mk @@ -0,0 +1,49 @@ +# Copyright (C) 2008 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +ifeq ($(BOARD_USES_HDMI),true) + +LOCAL_PATH:= $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_MODULE_TAGS := eng + +LOCAL_PRELINK_MODULE := false +LOCAL_SHARED_LIBRARIES := liblog +LOCAL_SRC_FILES := libddc.c + +LOCAL_C_INCLUDES := \ + $(LOCAL_PATH) \ + $(LOCAL_PATH)/../../../include + +ifeq ($(BOARD_HDMI_DDC_CH), DDC_CH_I2C_7) +LOCAL_CFLAGS += -DDDC_CH_I2C_7 +endif + +ifeq ($(BOARD_HDMI_DDC_CH), DDC_CH_I2C_1) +LOCAL_CFLAGS += -DDDC_CH_I2C_1 +endif + +ifeq ($(BOARD_HDMI_DDC_CH), DDC_CH_I2C_2) +LOCAL_CFLAGS += -DDDC_CH_I2C_2 +endif + +ifeq ($(BOARD_HDMI_DDC_CH), DDC_CH_I2C_8) +LOCAL_CFLAGS += -DDDC_CH_I2C_8 +endif + +LOCAL_MODULE := libddc +include $(BUILD_SHARED_LIBRARY) + +endif diff --git a/exynos5/hal/libhdmi/libsForhdmi/libddc/libddc.c b/exynos5/hal/libhdmi/libsForhdmi/libddc/libddc.c new file mode 100644 index 0000000..4e6e374 --- /dev/null +++ b/exynos5/hal/libhdmi/libsForhdmi/libddc/libddc.c @@ -0,0 +1,289 @@ +/* +* Copyright@ Samsung Electronics Co. LTD +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include "i2c-dev.h" + +#include "libddc.h" + +#define DDC_DEBUG 0 + +/** + * @brief DDC device name. + * User should change this. + */ +#ifdef DDC_CH_I2C_1 +#define DEV_NAME "/dev/i2c-1" +#endif + +#ifdef DDC_CH_I2C_2 +#define DEV_NAME "/dev/i2c-2" +#endif + +#ifdef DDC_CH_I2C_7 +#define DEV_NAME "/dev/i2c-7" +#endif + +#ifdef DDC_CH_I2C_8 +#define DEV_NAME "/dev/i2c-8" +#endif + +/** + * DDC file descriptor + */ +static int ddc_fd = -1; + +/** + * Reference count of DDC file descriptor + */ +static unsigned int ref_cnt = 0; + +/** + * Check if DDC file is already opened or not + * @return If DDC file is already opened, return 1; Otherwise, return 0. + */ +static int DDCFileAvailable() +{ + return (ddc_fd < 0) ? 0 : 1; +} + +/** + * Initialze DDC library. Open DDC device + * @return If succeed in opening DDC device or it is already opened, return 1;@n + * Otherwise, return 0. + */ +int DDCOpen() +{ + int ret = 1; + + // check already open?? + if (ref_cnt > 0) { + ref_cnt++; + return 1; + } + + // open + if ((ddc_fd = open(DEV_NAME,O_RDWR)) < 0) { + LOGE("%s: Cannot open I2C_DDC : %s",__func__, DEV_NAME); + ret = 0; + } + + ref_cnt++; + return ret; +} + +/** + * Finalize DDC library. Close DDC device + * @return If succeed in closing DDC device or it is being used yet, return 1;@n + * Otherwise, return 0. + */ +int DDCClose() +{ + int ret = 1; + // check if fd is available + if (ref_cnt == 0) { +#if DDC_DEBUG + LOGE("%s: I2C_DDC is not available!!!!", __func__); +#endif + return 1; + } + + // close + if (ref_cnt > 1) { + ref_cnt--; + return 1; + } + + if (close(ddc_fd) < 0) { +#if DDC_DEBUG + LOGE("%s: Cannot close I2C_DDC : %s",__func__,DEV_NAME); +#endif + ret = 0; + } + + ref_cnt--; + ddc_fd = -1; + + return ret; +} + +/** + * Read data though DDC. For more information of DDC, refer DDC Spec. + * @param addr [in] Device address + * @param offset [in] Byte offset + * @param size [in] Sizes of data + * @param buffer [out] Pointer to buffer to store data + * @return If succeed in reading, return 1; Otherwise, return 0. + */ +int DDCRead(unsigned char addr, unsigned char offset, + unsigned int size, unsigned char* buffer) +{ + struct i2c_rdwr_ioctl_data msgset; + struct i2c_msg msgs[2]; + int ret = 1; + + if (!DDCFileAvailable()) { +#if DDC_DEBUG + LOGE("%s: I2C_DDC is not available!!!!", __func__); +#endif + return 0; + } + + // set offset + msgs[0].addr = addr>>1; + msgs[0].flags = 0; + msgs[0].len = 1; + msgs[0].buf = &offset; + + // read data + msgs[1].addr = addr>>1; + msgs[1].flags = I2C_M_RD; + msgs[1].len = size; + msgs[1].buf = buffer; + + // set rdwr ioctl data + msgset.nmsgs = 2; + msgset.msgs = msgs; + + // i2c fast read + if ((ret = ioctl(ddc_fd, I2C_RDWR, &msgset)) < 0) { + perror("ddc error:"); + ret = 0; + } + + return ret; +} + +/** + * Read data though E-DDC. For more information of E-DDC, refer E-DDC Spec. + * @param segpointer [in] Segment pointer + * @param segment [in] Segment number + * @param addr [in] Device address + * @param offset [in] Byte offset + * @param size [in] Sizes of data + * @param buffer [out] Pointer to buffer to store data + * @return If succeed in reading, return 1; Otherwise, return 0. + */ + +int EDDCRead(unsigned char segpointer, unsigned char segment, unsigned char addr, + unsigned char offset, unsigned int size, unsigned char* buffer) +{ + struct i2c_rdwr_ioctl_data msgset; + struct i2c_msg msgs[3]; + int ret = 1; + + if (!DDCFileAvailable()) { +#if DDC_DEBUG + LOGE("%s: I2C_DDC is not available!!!!", __func__); +#endif + return 0; + } + + // set segment pointer + msgs[0].addr = segpointer>>1; + // ignore ack only if segment is "0" + if (segment == 0) + msgs[0].flags = I2C_M_IGNORE_NAK; + else + msgs[0].flags = 0; + + msgs[0].len = 1; + msgs[0].buf = &segment; + + // set offset + msgs[1].addr = addr>>1; + msgs[1].flags = 0; + msgs[1].len = 1; + msgs[1].buf = &offset; + + // read data + msgs[2].addr = addr>>1; + msgs[2].flags = I2C_M_RD; + msgs[2].len = size; + msgs[2].buf = buffer; + + msgset.nmsgs = 3; + msgset.msgs = msgs; + + // eddc read + if (ioctl(ddc_fd, I2C_RDWR, &msgset) < 0) { +#if DDC_DEBUG + LOGE("%s: ioctl(I2C_RDWR) failed!!!", __func__); +#endif + ret = 0; + } + return ret; +} + +/** + * Write data though DDC. For more information of DDC, refer DDC Spec. + * @param addr [in] Device address + * @param offset [in] Byte offset + * @param size [in] Sizes of data + * @param buffer [out] Pointer to buffer to write + * @return If succeed in writing, return 1; Otherwise, return 0. + */ +int DDCWrite(unsigned char addr, unsigned char offset, unsigned int size, unsigned char* buffer) +{ + unsigned char* temp; + int bytes; + int retval = 0; + + // allocate temporary buffer + temp = (unsigned char*) malloc((size+1)*sizeof(unsigned char)); + if (!temp) { + LOGE("%s: not enough resources at %s", __FUNCTION__); + goto exit; + } + + temp[0] = offset; + memcpy(temp+1,buffer,size); + + if (!DDCFileAvailable()) { + LOGE("%s: I2C_DDC is not available!!!!", __func__); + goto exit; + } + + if (ioctl(ddc_fd, I2C_SLAVE, addr>>1) < 0) { + LOGE("%s: cannot set slave address 0x%02x", __func__,addr); + goto exit; + } + + // write temp buffer + if ((bytes = write(ddc_fd,temp,size+1)) != (size+1)) { + LOGE("%s: fail to write %d bytes, only write %d bytes",__func__, size, bytes); + goto exit; + } + + retval = 1; + +exit: + // free temp buffer + if (temp) + free(temp); + + return retval; +} diff --git a/exynos5/hal/libhdmi/libsForhdmi/libddc/libddc.h b/exynos5/hal/libhdmi/libsForhdmi/libddc/libddc.h new file mode 100644 index 0000000..368855b --- /dev/null +++ b/exynos5/hal/libhdmi/libsForhdmi/libddc/libddc.h @@ -0,0 +1,35 @@ +/* + * Copyright@ Samsung Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _LIBDDC_H_ +#define _LIBDDC_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +int DDCOpen(); +int DDCRead(unsigned char addr, unsigned char offset, unsigned int size, unsigned char* buffer); +int DDCWrite(unsigned char addr, unsigned char offset, unsigned int size, unsigned char* buffer); +int EDDCRead(unsigned char segpointer, unsigned char segment, unsigned char addr, + unsigned char offset, unsigned int size, unsigned char* buffer); +int DDCClose(); + +#ifdef __cplusplus +} +#endif + +#endif /* _LIBDDC_H_ */ diff --git a/exynos5/hal/libhdmi/libsForhdmi/libedid/Android.mk b/exynos5/hal/libhdmi/libsForhdmi/libedid/Android.mk new file mode 100644 index 0000000..602ae4d --- /dev/null +++ b/exynos5/hal/libhdmi/libsForhdmi/libedid/Android.mk @@ -0,0 +1,34 @@ +# Copyright (C) 2008 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +ifeq ($(BOARD_USES_HDMI),true) + +LOCAL_PATH:= $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_MODULE_TAGS := eng + +LOCAL_PRELINK_MODULE := false +LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES) +LOCAL_SHARED_LIBRARIES := liblog libddc +LOCAL_SRC_FILES := libedid.c + +LOCAL_C_INCLUDES := \ + $(LOCAL_PATH) \ + $(LOCAL_PATH)/../../../include + +LOCAL_MODULE := libedid +include $(BUILD_SHARED_LIBRARY) + +endif diff --git a/exynos5/hal/libhdmi/libsForhdmi/libedid/edid.h b/exynos5/hal/libhdmi/libsForhdmi/libedid/edid.h new file mode 100644 index 0000000..aea1309 --- /dev/null +++ b/exynos5/hal/libhdmi/libsForhdmi/libedid/edid.h @@ -0,0 +1,181 @@ +/* + * Copyright@ Samsung Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _EDID_H_ +#define _EDID_H_ + +//@{ +/** + * @name EDID Addresses + */ +#define EDID_ADDR (0xA0) +#define EDID_SEGMENT_POINTER (0x60) +//@} + +//@{ +/** + * @name EDID offset and bit values + */ +#define SIZEOFBYTE (8) +#define SIZEOFEDIDBLOCK (0x80) +#define EDID_EXTENSION_NUMBER_POS (0x7E) + +#define EDID_TIMING_EXT_TAG_ADDR_POS (0) +#define EDID_TIMING_EXT_REV_NUMBER_POS (1) +#define EDID_DETAILED_TIMING_OFFSET_POS (2) +#define EDID_DATA_BLOCK_START_POS (4) + +// for Extension Data Block +#define EDID_TIMING_EXT_TAG_VAL (0x02) +#define EDID_BLOCK_MAP_EXT_TAG_VAL (0xF0) + +#define EDID_SHORT_AUD_DEC_TAG_VAL (1<<5) +#define EDID_SHORT_VID_DEC_TAG_VAL (2<<5) +#define EDID_VSDB_TAG_VAL (3<<5) +#define EDID_SPEAKER_ALLOCATION_TAG_VAL (4<<5) +#define EDID_VESA_DTC_TAG_VAL (5<<5) +#define EDID_RESERVED_TAG_VAL (6<<5) + +#define EDID_EXTENDED_TAG_VAL (7<<5) +#define EDID_EXTENDED_COLORIMETRY_VAL (5) +#define EDID_EXTENDED_COLORIMETRY_BLOCK_LEN (3) + +#define EDID_TAG_CODE_MASK (1<<7 | 1<<6 | 1<<5) +#define EDID_DATA_BLOCK_SIZE_MASK (1<<4 | 1<<3 | 1<<2 | 1<<1 | 1<<0) + +#define EDID_VSDB_MIN_LENGTH_VAL (5) + +// for Established Timings +#define EDID_ET_POS (0x23) +#define EDID_ET_640x480p_VAL (0x20) + +// for DTD +#define EDID_DTD_START_ADDR (0x36) +#define EDID_DTD_BYTE_LENGTH (18) +#define EDID_DTD_TOTAL_LENGTH (EDID_DTD_BYTE_LENGTH*4) + +#define EDID_DTD_PIXELCLOCK_POS1 (0) +#define EDID_DTD_PIXELCLOCK_POS2 (1) + +#define EDID_DTD_HBLANK_POS1 (3) +#define EDID_DTD_HBLANK_POS2 (4) +#define EDID_DTD_HBLANK_POS2_MASK (0xF) + +#define EDID_DTD_HACTIVE_POS1 (2) +#define EDID_DTD_HACTIVE_POS2 (4) +#define EDID_DTD_HACTIVE_POS2_MASK (0xF0) + +#define EDID_DTD_VBLANK_POS1 (6) +#define EDID_DTD_VBLANK_POS2 (7) +#define EDID_DTD_VBLANK_POS2_MASK (0x0F) + +#define EDID_DTD_VACTIVE_POS1 (5) +#define EDID_DTD_VACTIVE_POS2 (7) +#define EDID_DTD_VACTIVE_POS2_MASK (0xF0) + +#define EDID_DTD_INTERLACE_POS (17) +#define EDID_DTD_INTERLACE_MASK (1<<7) + +// for SVD +#define EDID_SVD_VIC_MASK (0x7F) + +// for CS +#define EDID_COLOR_SPACE_POS (3) +#define EDID_YCBCR444_CS_MASK (1<<5) +#define EDID_YCBCR422_CS_MASK (1<<4) + +// for Color Depth +#define EDID_DC_48_VAL (1<<6) +#define EDID_DC_36_VAL (1<<5) +#define EDID_DC_30_VAL (1<<4) +#define EDID_DC_YCBCR_VAL (1<<3) + +#define EDID_DC_POS (6) +#define EDID_DC_MASK (EDID_DC_48_VAL | EDID_DC_36_VAL| EDID_DC_30_VAL | EDID_DC_YCBCR_VAL) + +// for colorimetry +#define EDID_XVYCC601_MASK (1<<0) +#define EDID_XVYCC709_MASK (1<<1) +#define EDID_EXTENDED_MASK (1<<0|1<<1|1<<2) + +// for SAD +#define SHORT_AUD_DESCRIPTOR_LPCM (1<<0) +#define SHORT_AUD_DESCRIPTOR_AC3 (1<<1) +#define SHORT_AUD_DESCRIPTOR_MPEG1 (1<<2) +#define SHORT_AUD_DESCRIPTOR_MP3 (1<<3) +#define SHORT_AUD_DESCRIPTOR_MPEG2 (1<<4) +#define SHORT_AUD_DESCRIPTOR_AAC (1<<5) +#define SHORT_AUD_DESCRIPTOR_DTS (1<<6) +#define SHORT_AUD_DESCRIPTOR_ATRAC (1<<7) + +#define EDID_SAD_CODE_MASK (1<<6 | 1<<5 | 1<<4 | 1<<3) +#define EDID_SAD_CHANNEL_MASK (1<<2 | 1<<1 | 1<<0) +#define EDID_SAD_192KHZ_MASK (1<<6) +#define EDID_SAD_176KHZ_MASK (1<<5) +#define EDID_SAD_96KHZ_MASK (1<<4) +#define EDID_SAD_88KHZ_MASK (1<<3) +#define EDID_SAD_48KHZ_MASK (1<<2) +#define EDID_SAD_44KHZ_MASK (1<<1) +#define EDID_SAD_32KHZ_MASK (1<<0) + +#define EDID_SAD_WORD_24_MASK (1<<2) +#define EDID_SAD_WORD_20_MASK (1<<1) +#define EDID_SAD_WORD_16_MASK (1<<0) + +// for CEC +#define EDID_CEC_PHYICAL_ADDR (4) + +// for 3D +#define EDID_HDMI_EXT_POS (8) +#define EDID_HDMI_VIDEO_PRESENT_MASK (1<<5) + +// latency +#define EDID_HDMI_LATENCY_MASK (1<<7|1<<6) +#define EDID_HDMI_LATENCY_POS (6) + +#define EDID_HDMI_3D_PRESENT_POS (13) +#define EDID_HDMI_3D_PRESENT_MASK (1<<7) +#define EDID_HDMI_3D_MULTI_PRESENT_MASK (1<<6 | 1<<5) +#define EDID_HDMI_3D_MULTI_PRESENT_BIT 5 + +#define EDID_3D_STRUCTURE_ONLY_EXIST (1<<5) +#define EDID_3D_STRUCTURE_MASK_EXIST (1<<6) + +#define EDID_3D_STRUCTURE_FP (0) +#define EDID_3D_STRUCTURE_FA (1) +#define EDID_3D_STRUCTURE_LA (2) +#define EDID_3D_STRUCTURE_SSF (3) +#define EDID_3D_STRUCTURE_LD (4) +#define EDID_3D_STRUCTURE_LDGFX (5) +#define EDID_3D_STRUCTURE_TB (6) +#define EDID_3D_STRUCTURE_SSH (8) + +#define EDID_HDMI_EXT_LENGTH_POS (14) +#define EDID_HDMI_VSDB_VIC_LEN_BIT (5) +#define EDID_HDMI_VSDB_VIC_LEN_MASK (1<<7|1<<6|1<<5) +#define EDID_HDMI_VSDB_3D_LEN_MASK (1<<4|1<<3|1<<2|1<<1|1<<0) + +#define EDID_HDMI_2D_VIC_ORDER_MASK (1<<7|1<<6|1<<5|1<<4) +#define EDID_HDMI_3D_STRUCTURE_MASK (1<<3|1<<2|1<<1|1<<0) + +// for MAX TMDS +#define EDID_MAX_TMDS_POS (7) + +// for 3D Structure +#define NUM_OF_VIC_FOR_3D 16 +//@} + +#endif /* _EDID_H_ */ diff --git a/exynos5/hal/libhdmi/libsForhdmi/libedid/libedid.c b/exynos5/hal/libhdmi/libsForhdmi/libedid/libedid.c new file mode 100644 index 0000000..c6bed50 --- /dev/null +++ b/exynos5/hal/libhdmi/libsForhdmi/libedid/libedid.c @@ -0,0 +1,1265 @@ +/* +* Copyright@ Samsung Electronics Co. LTD +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include +#include +#include + +#include + +#include "edid.h" +#include "libedid.h" +#include "../libddc/libddc.h" + +//#define EDID_DEBUG 1 + +#ifdef EDID_DEBUG +#define DPRINTF(args...) LOGI(args) +#else +#define DPRINTF(args...) +#endif + +#define NUM_OF_VIC_FOR_3D 16 + +/** + * @var gEdidData + * Pointer to EDID data + */ +static unsigned char* gEdidData; + +/** + * @var gExtensions + * Number of EDID extensions + */ +static int gExtensions; + + +/** + * @var aVIC + * This contains first 16 VIC in EDID + */ +static unsigned char aVIC[NUM_OF_VIC_FOR_3D]; + +//! Structure for parsing video timing parameter in EDID +static const struct edid_params { + /** H Total */ + unsigned int HTotal; + + /** H Blank */ + unsigned int HBlank; + + /** V Total */ + unsigned int VTotal; + + /** V Blank */ + unsigned int VBlank; + + /** CEA VIC */ + unsigned char VIC; + + /** CEA VIC for 16:9 aspect ratio */ + unsigned char VIC16_9; + + /** 0 if progressive, 1 if interlaced */ + unsigned char interlaced; + + /** Pixel frequency */ + enum PixelFreq PixelClock; +} aVideoParams[] = +{ + { 800 , 160 , 525 , 45, 1 , 1 , 0, PIXEL_FREQ_25_200 ,}, // v640x480p_60Hz + { 858 , 138 , 525 , 45, 2 , 3 , 0, PIXEL_FREQ_27_027 ,}, // v720x480p_60Hz + { 1650, 370 , 750 , 30, 4 , 4 , 0, PIXEL_FREQ_74_250 ,}, // v1280x720p_60Hz + { 2200, 280 , 1125, 22, 5 , 5 , 1, PIXEL_FREQ_74_250 ,}, // v1920x1080i_60H + { 1716, 276 , 525 , 22, 6 , 7 , 1, PIXEL_FREQ_74_250 ,}, // v720x480i_60Hz + { 1716, 276 , 262 , 22, 8 , 9 , 0, PIXEL_FREQ_27_027 ,}, // v720x240p_60Hz + //{ 1716, 276 , 263 , 23, 8 , 9 , 0, PIXEL_FREQ_27_027 , }, // v720x240p_60Hz(mode 2) + { 3432, 552 , 525 , 22, 10, 11, 1, PIXEL_FREQ_54_054 , }, // v2880x480i_60Hz + { 3432, 552 , 262 , 22, 12, 13, 0, PIXEL_FREQ_54_054 , }, // v2880x240p_60Hz + //{ 3432, 552 , 263 , 23, 12, 13, 0, PIXEL_FREQ_54_054 , }, // v2880x240p_60Hz(mode 2) + { 1716, 276 , 525 , 45, 14, 15, 0, PIXEL_FREQ_54_054 , }, // v1440x480p_60Hz + { 2200, 280 , 1125, 45, 16, 16, 0, PIXEL_FREQ_148_500, }, // v1920x1080p_60H + { 864 , 144 , 625 , 49, 17, 18, 0, PIXEL_FREQ_27 , }, // v720x576p_50Hz + { 1980, 700 , 750 , 30, 19, 19, 0, PIXEL_FREQ_74_250 , }, // v1280x720p_50Hz + { 2640, 720 , 1125, 22, 20, 20, 1, PIXEL_FREQ_74_250 , }, // v1920x1080i_50H + { 1728, 288 , 625 , 24, 21, 22, 1, PIXEL_FREQ_27 , }, // v720x576i_50Hz + { 1728, 288 , 312 , 24, 23, 24, 0, PIXEL_FREQ_27 , }, // v720x288p_50Hz + //{ 1728, 288 , 313 , 25, 23, 24, 0, PIXEL_FREQ_27 , }, // v720x288p_50Hz(mode 2) + //{ 1728, 288 , 314 , 26, 23, 24, 0, PIXEL_FREQ_27 , }, // v720x288p_50Hz(mode 3) + { 3456, 576 , 625 , 24, 25, 26, 1, PIXEL_FREQ_54 , }, // v2880x576i_50Hz + { 3456, 576 , 312 , 24, 27, 28, 0, PIXEL_FREQ_54 , }, // v2880x288p_50Hz + //{ 3456, 576 , 313 , 25, 27, 28, 0, PIXEL_FREQ_54 , }, // v2880x288p_50Hz(mode 2) + //{ 3456, 576 , 314 , 26, 27, 28, 0, PIXEL_FREQ_54 , }, // v2880x288p_50Hz(mode 3) + { 1728, 288 , 625 , 49, 29, 30, 0, PIXEL_FREQ_54 , }, // v1440x576p_50Hz + { 2640, 720 , 1125, 45, 31, 31, 0, PIXEL_FREQ_148_500,}, // v1920x1080p_50Hz + { 2750, 830 , 1125, 45, 32, 32, 0, PIXEL_FREQ_74_250 ,}, // v1920x1080p_24Hz + { 2640, 720 , 1125, 45, 33, 33, 0, PIXEL_FREQ_74_250 ,}, // v1920x1080p_25Hz + { 2200, 280 , 1125, 45, 34, 34, 0, PIXEL_FREQ_74_250 ,}, // v1920x1080p_30Hz + { 3432, 552 , 525 , 45, 35, 36, 0, PIXEL_FREQ_108_108,}, // v2880x480p_60Hz + { 3456, 576 , 625 , 49, 37, 38, 0, PIXEL_FREQ_108 ,}, // v2880x576p_50Hz + { 2304, 384 , 1250, 85, 39, 39, 1, PIXEL_FREQ_72 ,}, // v1920x1080i_50Hz(1250) + { 2640, 720 , 1125, 22, 40, 40, 1, PIXEL_FREQ_148_500, }, // v1920x1080i_100Hz + { 1980, 700 , 750 , 30, 41, 41, 0, PIXEL_FREQ_148_500, }, // v1280x720p_100Hz + { 864 , 144 , 625 , 49, 42, 43, 0, PIXEL_FREQ_54 , }, // v720x576p_100Hz + { 1728, 288 , 625 , 24, 44, 45, 1, PIXEL_FREQ_54 , }, // v720x576i_100Hz + { 2200, 280 , 1125, 22, 46, 46, 1, PIXEL_FREQ_148_500, }, // v1920x1080i_120Hz + { 1650, 370 , 750 , 30, 47, 47, 0, PIXEL_FREQ_148_500, }, // v1280x720p_120Hz + { 858 , 138 , 525 , 54, 48, 49, 0, PIXEL_FREQ_54_054 , }, // v720x480p_120Hz + { 1716, 276 , 525 , 22, 50, 51, 1, PIXEL_FREQ_54_054 , }, // v720x480i_120Hz + { 864 , 144 , 625 , 49, 52, 53, 0, PIXEL_FREQ_108 , }, // v720x576p_200Hz + { 1728, 288 , 625 , 24, 54, 55, 1, PIXEL_FREQ_108 , }, // v720x576i_200Hz + { 858 , 138 , 525 , 45, 56, 57, 0, PIXEL_FREQ_108_108, }, // v720x480p_240Hz + { 1716, 276 , 525 , 22, 58, 59, 1, PIXEL_FREQ_108_108, }, // v720x480i_240Hz + // PHY Freq is not available yet + //{ 3300, 2020, 750 , 30, 60, 60, 0, PIXEL_FREQ_59_400 ,}, // v1280x720p24Hz + { 3960, 2680, 750 , 30, 61, 61, 0, PIXEL_FREQ_74_250 , }, // v1280x720p25Hz + { 3300, 2020, 750 , 30, 62, 62, 0, PIXEL_FREQ_74_250 ,}, // v1280x720p30Hz + // PHY Freq is not available yet + //{ 2200, 280 , 1125, 45, 63, 63, 0, PIXEL_FREQ_297, }, // v1920x1080p120Hz + //{ 2640, 720 , 1125, 45, 64, 64, 0, PIXEL_FREQ_297, }, // v1920x1080p100Hz + //{ 4400, 560 , 2250, 90, 1, 1, 0, 0, PIXEL_FREQ_297, }, // v4Kx2K30Hz +}; + +//! Structure for Checking 3D Mandatory Format in EDID +static const struct edid_3d_mandatory { + /** video Format */ + enum VideoFormat resolution; + + /** 3D Structure */ + enum HDMI3DVideoStructure hdmi_3d_format; +} edid_3d [] = +{ + { v1920x1080p_24Hz, HDMI_3D_FP_FORMAT }, // 1920x1080p @ 23.98/24Hz + { v1280x720p_60Hz, HDMI_3D_FP_FORMAT }, // 1280x720p @ 59.94/60Hz + { v1920x1080i_60Hz, HDMI_3D_SSH_FORMAT }, // 1920x1080i @ 59.94/60Hz + { v1920x1080p_24Hz, HDMI_3D_TB_FORMAT }, // 1920x1080p @ 23.98/24Hz + { v1280x720p_60Hz, HDMI_3D_TB_FORMAT }, // 1280x720p @ 59.94/60Hz + { v1280x720p_50Hz, HDMI_3D_FP_FORMAT }, // 1280x720p @ 50Hz + { v1920x1080i_50Hz, HDMI_3D_SSH_FORMAT }, // 1920x1080i @ 50Hz + { v1280x720p_50Hz, HDMI_3D_TB_FORMAT }, // 1280x720p @ 50Hz +}; + +/** + * Calculate a checksum. + * + * @param buffer [in] Pointer to data to calculate a checksum + * @param size [in] Sizes of data + * + * @return If checksum result is 0, return 1; Otherwise, return 0. + */ +static int CalcChecksum(const unsigned char* const buffer, const int size) +{ + unsigned char i,sum; + int ret = 1; + + // check parameter + if (buffer == NULL ) { + DPRINTF("invalid parameter : buffer\n"); + return 0; + } + for (sum = 0, i = 0 ; i < size; i++) + sum += buffer[i]; + + // check checksum + if (sum != 0) + ret = 0; + + return ret; +} + +/** + * Read EDID Block(128 bytes) + * + * @param blockNum [in] Number of block to read @n + * For example, EDID block = 0, EDID first Extension = 1, and so on. + * @param outBuffer [out] Pointer to buffer to store EDID data + * + * @return If fail to read, return 0; Otherwise, return 1. + */ +static int ReadEDIDBlock(const unsigned int blockNum, unsigned char* const outBuffer) +{ + int segNum, offset, dataPtr; + + // check parameter + if (outBuffer == NULL) { + DPRINTF("invalid parameter : outBuffer\n"); + return 0; + } + + // calculate + segNum = blockNum / 2; + offset = (blockNum % 2) * SIZEOFEDIDBLOCK; + dataPtr = (blockNum) * SIZEOFEDIDBLOCK; + + // read block + if (!EDDCRead(EDID_SEGMENT_POINTER, segNum, EDID_ADDR, offset, SIZEOFEDIDBLOCK, outBuffer)) { + DPRINTF("Fail to Read %dth EDID Block\n", blockNum); + return 0; + } + + if (!CalcChecksum(outBuffer, SIZEOFEDIDBLOCK)) { + DPRINTF("CheckSum fail : %dth EDID Block\n", blockNum); + return 0; + } + + // print data +#ifdef EDID_DEBUG + offset = 0; + do { + LOGI("0x%02X", outBuffer[offset++]); + if (offset % 16) + LOGI(" "); + else + LOGI("\n"); + } while (SIZEOFEDIDBLOCK > offset); +#endif // EDID_DEBUG + return 1; +} + +/** + * Check if EDID data is valid or not. + * + * @return if EDID data is valid, return 1; Otherwise, return 0. + */ +static inline int EDIDValid(void) +{ + return (gEdidData == NULL) ? 0 : 1; +} + +/** + * Search HDMI Vender Specific Data Block(VSDB) in EDID extension block. + * + * @param extension [in] the number of EDID extension block to check + * + * @return if there is a HDMI VSDB, return the offset from start of @n + * EDID extension block. if there is no VSDB, return 0. + */ +static int GetVSDBOffset(const int extension) +{ + unsigned int BlockOffset = extension*SIZEOFEDIDBLOCK; + unsigned int offset = BlockOffset + EDID_DATA_BLOCK_START_POS; + unsigned int tag,blockLen,DTDOffset; + + if (!EDIDValid() || (extension > gExtensions)) { + DPRINTF("EDID Data is not available\n"); + return 0; + } + + DTDOffset = gEdidData[BlockOffset + EDID_DETAILED_TIMING_OFFSET_POS]; + + // check if there is HDMI VSDB + while (offset < BlockOffset + DTDOffset) { + // find the block tag and length + // tag + tag = gEdidData[offset] & EDID_TAG_CODE_MASK; + // block len + blockLen = (gEdidData[offset] & EDID_DATA_BLOCK_SIZE_MASK) + 1; + + // check if it is HDMI VSDB + // if so, check identifier value, if it's hdmi vsbd - return offset + if (tag == EDID_VSDB_TAG_VAL && + gEdidData[offset+1] == 0x03 && + gEdidData[offset+2] == 0x0C && + gEdidData[offset+3] == 0x0 && + blockLen > EDID_VSDB_MIN_LENGTH_VAL ) + return offset; + + // else find next block + offset += blockLen; + } + + // return error + return 0; +} + +/** + * Check if Sink supports the HDMI mode. + * @return If Sink supports HDMI mode, return 1; Otherwise, return 0. + */ +static int CheckHDMIMode(void) +{ + int i; + + // read EDID + if (!EDIDRead()) + return 0; + + // find VSDB + for (i = 1; i <= gExtensions; i++) + if (GetVSDBOffset(i) > 0) // if there is a VSDB, it means RX support HDMI mode + return 1; + + return 0; +} + +/** + * Check if EDID extension block is timing extension block or not. + * @param extension [in] The number of EDID extension block to check + * @return If the block is timing extension, return 1; Otherwise, return 0. + */ +static int IsTimingExtension(const int extension) +{ + int ret = 0; + if (!EDIDValid() || (extension > gExtensions)) { + DPRINTF("EDID Data is not available\n"); + return ret; + } + + if (gEdidData[extension*SIZEOFEDIDBLOCK] == EDID_TIMING_EXT_TAG_VAL) { + // check extension revsion number + // revision num == 3 + if (gEdidData[extension*SIZEOFEDIDBLOCK + EDID_TIMING_EXT_REV_NUMBER_POS] == 3) + ret = 1; + // revison num != 3 && DVI mode + else if (!CheckHDMIMode() && + gEdidData[extension*SIZEOFEDIDBLOCK + EDID_TIMING_EXT_REV_NUMBER_POS] != 2) + ret = 1; + } + return ret; +} + +/** + * Check if the video format is contained in - @n + * Detailed Timing Descriptor(DTD) of EDID extension block. + * @param extension [in] Number of EDID extension block to check + * @param videoFormat [in] Video format to check + * @return If the video format is contained in DTD of EDID extension block, -@n + * return 1; Otherwise, return 0. + */ +static int IsContainVideoDTD(const int extension,const enum VideoFormat videoFormat) +{ + int i, StartOffset, EndOffset; + + if (!EDIDValid() || (extension > gExtensions)) { + DPRINTF("EDID Data is not available\n"); + return 0; + } + + // if edid block( 0th block ) + if (extension == 0) { + StartOffset = EDID_DTD_START_ADDR; + EndOffset = StartOffset + EDID_DTD_TOTAL_LENGTH; + } else { // if edid extension block + StartOffset = extension*SIZEOFEDIDBLOCK + gEdidData[extension*SIZEOFEDIDBLOCK + EDID_DETAILED_TIMING_OFFSET_POS]; + EndOffset = (extension+1)*SIZEOFEDIDBLOCK; + } + + // check DTD(Detailed Timing Description) + for (i = StartOffset; i < EndOffset; i+= EDID_DTD_BYTE_LENGTH) { + unsigned int hblank = 0, hactive = 0, vblank = 0, vactive = 0, interlaced = 0, pixelclock = 0; + unsigned int vHActive = 0, vVActive = 0, vVBlank = 0; + + // get pixel clock + pixelclock = (gEdidData[i+EDID_DTD_PIXELCLOCK_POS2] << SIZEOFBYTE); + pixelclock |= gEdidData[i+EDID_DTD_PIXELCLOCK_POS1]; + + if (!pixelclock) + continue; + + // get HBLANK value in pixels + hblank = gEdidData[i+EDID_DTD_HBLANK_POS2] & EDID_DTD_HBLANK_POS2_MASK; + hblank <<= SIZEOFBYTE; // lower 4 bits + hblank |= gEdidData[i+EDID_DTD_HBLANK_POS1]; + + // get HACTIVE value in pixels + hactive = gEdidData[i+EDID_DTD_HACTIVE_POS2] & EDID_DTD_HACTIVE_POS2_MASK; + hactive <<= (SIZEOFBYTE/2); // upper 4 bits + hactive |= gEdidData[i+EDID_DTD_HACTIVE_POS1]; + + // get VBLANK value in pixels + vblank = gEdidData[i+EDID_DTD_VBLANK_POS2] & EDID_DTD_VBLANK_POS2_MASK; + vblank <<= SIZEOFBYTE; // lower 4 bits + vblank |= gEdidData[i+EDID_DTD_VBLANK_POS1]; + + // get VACTIVE value in pixels + vactive = gEdidData[i+EDID_DTD_VACTIVE_POS2] & EDID_DTD_VACTIVE_POS2_MASK; + vactive <<= (SIZEOFBYTE/2); // upper 4 bits + vactive |= gEdidData[i+EDID_DTD_VACTIVE_POS1]; + + vHActive = aVideoParams[videoFormat].HTotal - aVideoParams[videoFormat].HBlank; + if (aVideoParams[videoFormat].interlaced == 1) { + if (aVideoParams[videoFormat].VIC == v1920x1080i_50Hz_1250) { // VTOP and VBOT are same + vVActive = (aVideoParams[videoFormat].VTotal - aVideoParams[videoFormat].VBlank*2)/2; + vVBlank = aVideoParams[videoFormat].VBlank; + } else { + vVActive = (aVideoParams[videoFormat].VTotal - aVideoParams[videoFormat].VBlank*2 - 1)/2; + vVBlank = aVideoParams[videoFormat].VBlank; + } + } else { + vVActive = aVideoParams[videoFormat].VTotal - aVideoParams[videoFormat].VBlank; + vVBlank = aVideoParams[videoFormat].VBlank; + } + + // get Interlaced Mode Value + interlaced = (int)(gEdidData[i+EDID_DTD_INTERLACE_POS] & EDID_DTD_INTERLACE_MASK); + if (interlaced) + interlaced = 1; + + DPRINTF("EDID: hblank = %d,vblank = %d, hactive = %d, vactive = %d\n" + ,hblank,vblank,hactive,vactive); + DPRINTF("REQ: hblank = %d,vblank = %d, hactive = %d, vactive = %d\n" + ,aVideoParams[videoFormat].HBlank + ,vVBlank,vHActive,vVActive); + + if (hblank == aVideoParams[videoFormat].HBlank && vblank == vVBlank // blank + && hactive == vHActive && vactive == vVActive) { //line + unsigned int EDIDpixelclock = aVideoParams[videoFormat].PixelClock; + EDIDpixelclock /= 100; pixelclock /= 100; + + if (pixelclock == EDIDpixelclock) { + DPRINTF("Sink Support the Video mode\n"); + return 1; + } + } + } + return 0; +} + +/** + * Check if a VIC(Video Identification Code) is contained in -@n + * EDID extension block. + * @param extension [in] Number of EDID extension block to check + * @param VIC [in] VIC to check + * @return If the VIC is contained in contained in EDID extension block, -@n + * return 1; Otherwise, return 0. + */ +static int IsContainVIC(const int extension, const int VIC) +{ + unsigned int StartAddr = extension*SIZEOFEDIDBLOCK; + unsigned int ExtAddr = StartAddr + EDID_DATA_BLOCK_START_POS; + unsigned int tag,blockLen; + unsigned int DTDStartAddr = gEdidData[StartAddr + EDID_DETAILED_TIMING_OFFSET_POS]; + + if (!EDIDValid() || (extension > gExtensions)) { + DPRINTF("EDID Data is not available\n"); + return 0; + } + + // while + while (ExtAddr < StartAddr + DTDStartAddr) { + // find the block tag and length + // tag + tag = gEdidData[ExtAddr] & EDID_TAG_CODE_MASK; + // block len + blockLen = (gEdidData[ExtAddr] & EDID_DATA_BLOCK_SIZE_MASK) + 1; + DPRINTF("tag = %d\n",tag); + DPRINTF("blockLen = %d\n",blockLen-1); + + // check if it is short video description + if (tag == EDID_SHORT_VID_DEC_TAG_VAL) { + // if so, check SVD + unsigned int i; + for (i = 1; i < blockLen; i++) { + DPRINTF("EDIDVIC = %d\n",gEdidData[ExtAddr+i] & EDID_SVD_VIC_MASK); + DPRINTF("VIC = %d\n",VIC); + + // check VIC with SVDB + if (VIC == (gEdidData[ExtAddr+i] & EDID_SVD_VIC_MASK)) { + DPRINTF("Sink Device supports requested video mode\n"); + return 1; + } + } + } + // else find next block + ExtAddr += blockLen; + } + + return 0; +} + +/** + * Check if EDID contains the video format. + * @param videoFormat [in] Video format to check + * @param pixelRatio [in] Pixel aspect ratio of video format to check + * @return if EDID contains the video format, return 1; Otherwise, return 0. + */ +static int CheckResolution(const enum VideoFormat videoFormat, + const enum PixelAspectRatio pixelRatio) +{ + int i, vic; + + // read EDID + if (!EDIDRead()) + return 0; + + // check ET(Established Timings) for 640x480p@60Hz + if (videoFormat == v640x480p_60Hz // if it's 640x480p@60Hz + && (gEdidData[EDID_ET_POS] & EDID_ET_640x480p_VAL)) // it support + return 1; + + // check STI(Standard Timing Identification) + // do not need + + // check DTD(Detailed Timing Description) of EDID block(0th) + if (IsContainVideoDTD(0,videoFormat)) + return 1; + + // check EDID Extension + vic = (pixelRatio == HDMI_PIXEL_RATIO_16_9) ? + aVideoParams[videoFormat].VIC16_9 : aVideoParams[videoFormat].VIC; + + // find VSDB + for (i = 1; i <= gExtensions; i++) { + if (IsTimingExtension(i)) // if it's timing block + if (IsContainVIC(i, vic) || IsContainVideoDTD(i, videoFormat)) + return 1; + } + + return 0; +} + +/** + * Check if EDID supports the color depth. + * @param depth [in] Color depth + * @param space [in] Color space + * @return If EDID supports the color depth, return 1; Otherwise, return 0. + */ +static int CheckColorDepth(const enum ColorDepth depth,const enum ColorSpace space) +{ + int i; + unsigned int StartAddr; + + // if color depth == 24 bit, no need to check + if (depth == HDMI_CD_24) + return 1; + + // check EDID data is valid or not + // read EDID + if (!EDIDRead()) + return 0; + + // find VSDB + for (i = 1; i <= gExtensions; i++) { + if (IsTimingExtension(i) // if it's timing block + && ((StartAddr = GetVSDBOffset(i)) > 0)) { // check block + int blockLength = gEdidData[StartAddr] & EDID_DATA_BLOCK_SIZE_MASK; + if (blockLength >= EDID_DC_POS) { + // get supported DC value + int deepColor = gEdidData[StartAddr + EDID_DC_POS] & EDID_DC_MASK; + DPRINTF("EDID deepColor = %x\n",deepColor); + // check supported DeepColor + // if YCBCR444 + if (space == HDMI_CS_YCBCR444) { + if ( !(deepColor & EDID_DC_YCBCR_VAL)) + return 0; + } + + // check colorDepth + switch (depth) { + case HDMI_CD_36: + deepColor &= EDID_DC_36_VAL; + break; + case HDMI_CD_30: + deepColor &= EDID_DC_30_VAL; + break; + case HDMI_CD_24: + deepColor = 1; + break; + default : + deepColor = 0; + } + if (deepColor) + return 1; + else + return 0; + } + } + } + + return 0; +} + +/** + * Check if EDID supports the color space. + * @param space [in] Color space + * @return If EDID supports the color space, return 1; Otherwise, return 0. + */ +static int CheckColorSpace(const enum ColorSpace space) +{ + int i; + + // RGB is default + if (space == HDMI_CS_RGB) + return 1; + + // check EDID data is valid or not + // read EDID + if (!EDIDRead()) + return 0; + + // find VSDB + for (i = 1; i <= gExtensions; i++) { + if (IsTimingExtension(i)) { // if it's timing block + // read Color Space + int CS = gEdidData[i*SIZEOFEDIDBLOCK + EDID_COLOR_SPACE_POS]; + + if ((space == HDMI_CS_YCBCR444 && (CS & EDID_YCBCR444_CS_MASK)) || // YCBCR444 + (space == HDMI_CS_YCBCR422 && (CS & EDID_YCBCR422_CS_MASK))) // YCBCR422 + return 1; + } + } + return 0; +} + +/** + * Check if EDID supports the colorimetry. + * @param color [in] Colorimetry + * @return If EDID supports the colorimetry, return 1; Otherwise, return 0. + */ +static int CheckColorimetry(const enum HDMIColorimetry color) +{ + int i; + + // do not need to parse if not extended colorimetry + if (color == HDMI_COLORIMETRY_NO_DATA || + color == HDMI_COLORIMETRY_ITU601 || + color == HDMI_COLORIMETRY_ITU709) + return 1; + + // read EDID + if (!EDIDRead()) + return 0; + + // find VSDB + for (i = 1; i <= gExtensions; i++) { + if (IsTimingExtension(i)) { // if it's timing block + // check address + unsigned int ExtAddr = i*SIZEOFEDIDBLOCK + EDID_DATA_BLOCK_START_POS; + unsigned int EndAddr = i*SIZEOFEDIDBLOCK + gEdidData[i*SIZEOFEDIDBLOCK + EDID_DETAILED_TIMING_OFFSET_POS]; + unsigned int tag,blockLen; + + while (ExtAddr < EndAddr) { + // find the block tag and length + // tag + tag = gEdidData[ExtAddr] & EDID_TAG_CODE_MASK; + // block len + blockLen = (gEdidData[ExtAddr] & EDID_DATA_BLOCK_SIZE_MASK) + 1; + + // check if it is colorimetry block + if (tag == EDID_EXTENDED_TAG_VAL && // extended tag + gEdidData[ExtAddr+1] == EDID_EXTENDED_COLORIMETRY_VAL && // colorimetry block + (blockLen-1) == EDID_EXTENDED_COLORIMETRY_BLOCK_LEN) { // check length + // get supported DC value + int colorimetry = (gEdidData[ExtAddr + 2]); + int metadata = (gEdidData[ExtAddr + 3]); + + DPRINTF("EDID extened colorimetry = %x\n",colorimetry); + DPRINTF("EDID gamut metadata profile = %x\n",metadata); + + // check colorDepth + switch (color) { + case HDMI_COLORIMETRY_EXTENDED_xvYCC601: + if (colorimetry & EDID_XVYCC601_MASK && metadata) + return 1; + break; + case HDMI_COLORIMETRY_EXTENDED_xvYCC709: + if (colorimetry & EDID_XVYCC709_MASK && metadata) + return 1; + break; + default: + break; + } + return 0; + } + // else find next block + ExtAddr += blockLen; + } + } + } + + return 0; +} + +/** + * Get Max TMDS clock that HDMI Rx can receive. + * @return If available, return MaxTMDS clock; Otherwise, return 0. + */ +static unsigned int GetMaxTMDS(void) +{ + int i; + unsigned int StartAddr; + + // find VSDB + for (i = 1; i <= gExtensions; i++) { + if (IsTimingExtension(i) // if it's timing block + && ((StartAddr = GetVSDBOffset(i)) > 0)) { // check block + int blockLength = gEdidData[StartAddr] & EDID_DATA_BLOCK_SIZE_MASK; + if (blockLength >= EDID_MAX_TMDS_POS) { + // get supported DC value + return gEdidData[StartAddr + EDID_MAX_TMDS_POS]; + } + } + } + + return 0; +} + +/** + * Save first 16 VIC of EDID + */ +static void SaveVIC(void) +{ + int extension; + int vic_count = 0; + for (extension = 1; extension <= gExtensions && vic_count < NUM_OF_VIC_FOR_3D; extension++) { + unsigned int StartAddr = extension*SIZEOFEDIDBLOCK; + unsigned int ExtAddr = StartAddr + EDID_DATA_BLOCK_START_POS; + unsigned int tag,blockLen; + unsigned int DTDStartAddr = gEdidData[StartAddr + EDID_DETAILED_TIMING_OFFSET_POS]; + + while (ExtAddr < StartAddr + DTDStartAddr) { + // find the block tag and length + // tag + tag = gEdidData[ExtAddr] & EDID_TAG_CODE_MASK; + // block len + blockLen = (gEdidData[ExtAddr] & EDID_DATA_BLOCK_SIZE_MASK) + 1; + + // check if it is short video description + if (tag == EDID_SHORT_VID_DEC_TAG_VAL) { + // if so, check SVD + unsigned int edid_index; + for (edid_index = 1; edid_index < blockLen && vic_count < NUM_OF_VIC_FOR_3D; edid_index++) { + DPRINTF("EDIDVIC = %d\r\n", gEdidData[ExtAddr+edid_index] & EDID_SVD_VIC_MASK); + + // check VIC with SVDB + aVIC[vic_count++] = (gEdidData[ExtAddr+edid_index] & EDID_SVD_VIC_MASK); + } + } + // else find next block + ExtAddr += blockLen; + } + } +} + +/** + * Check if Rx supports requested 3D format. + * @param pVideo [in] HDMI Video Parameter + * @return If Rx supports requested 3D format, return 1; Otherwise, return 0. + */ +static int EDID3DFormatSupport(const struct HDMIVideoParameter * const pVideo) +{ + int edid_index; + unsigned int StartAddr; + unsigned int vic; + vic = (pVideo->pixelAspectRatio == HDMI_PIXEL_RATIO_16_9) ? + aVideoParams[pVideo->resolution].VIC16_9 : aVideoParams[pVideo->resolution].VIC; + + // if format == 2D, no need to check + if (pVideo->hdmi_3d_format == HDMI_2D_VIDEO_FORMAT) + return 1; + + // check EDID data is valid or not + if (!EDIDRead()) + return 0; + + // save first 16 VIC to check + SaveVIC(); + + // find VSDB + for (edid_index = 1; edid_index <= gExtensions; edid_index++) { + if (IsTimingExtension(edid_index) // if it's timing block + && ((StartAddr = GetVSDBOffset(edid_index)) > 0)) { // check block + unsigned int blockLength = gEdidData[StartAddr] & EDID_DATA_BLOCK_SIZE_MASK; + unsigned int VSDBHdmiVideoPre = 0; + unsigned int VSDB3DPresent = 0; + unsigned int VSDB3DMultiPresent = 0; + unsigned int HDMIVICLen; + unsigned int HDMI3DLen; + int Hdmi3DStructure = 0; + unsigned int Hdmi3DMask = 0xFFFF; + unsigned int latency_offset = 0; + + DPRINTF("VSDB Block length[0x%x] = 0x%x\r\n",StartAddr,blockLength); + + // get HDMI Video Present value + if (blockLength >= EDID_HDMI_EXT_POS) { + VSDBHdmiVideoPre = gEdidData[StartAddr + EDID_HDMI_EXT_POS] + & EDID_HDMI_VIDEO_PRESENT_MASK; + DPRINTF("EDID HDMI Video Present = 0x%x\n",VSDBHdmiVideoPre); + } else { // data related to 3D format is not available + return 0; + } + + // check if latency field is available + latency_offset = (gEdidData[StartAddr + EDID_HDMI_EXT_POS] + & EDID_HDMI_LATENCY_MASK) >> EDID_HDMI_LATENCY_POS; + if (latency_offset == 0) + latency_offset = 4; + else if (latency_offset == 3) + latency_offset = 0; + else + latency_offset = 2; + + StartAddr -= latency_offset; + + // HDMI_VIC_LEN + HDMIVICLen = (gEdidData[StartAddr + EDID_HDMI_EXT_LENGTH_POS] + & EDID_HDMI_VSDB_VIC_LEN_MASK) >> EDID_HDMI_VSDB_VIC_LEN_BIT; + + if (pVideo->hdmi_3d_format == HDMI_VIC_FORMAT) { + if (HDMIVICLen) { + for (edid_index = 0; edid_index < (int)HDMIVICLen; edid_index++) { + if (vic == gEdidData[StartAddr + EDID_HDMI_EXT_LENGTH_POS + edid_index]) + return 1; + } + return 0; + } else { + return 0; + } + } + + // HDMI_3D_LEN + HDMI3DLen = gEdidData[StartAddr + EDID_HDMI_EXT_LENGTH_POS] + & EDID_HDMI_VSDB_3D_LEN_MASK; + + DPRINTF("HDMI VIC LENGTH[%x] = %x\r\n", + StartAddr + EDID_HDMI_EXT_LENGTH_POS, HDMIVICLen); + DPRINTF("HDMI 3D LENGTH[%x] = %x\r\n", + StartAddr + EDID_HDMI_EXT_LENGTH_POS, HDMI3DLen); + + // check 3D_Present bit + if (blockLength >= (EDID_HDMI_3D_PRESENT_POS - latency_offset)) { + VSDB3DPresent = gEdidData[StartAddr + EDID_HDMI_3D_PRESENT_POS] + & EDID_HDMI_3D_PRESENT_MASK; + VSDB3DMultiPresent = gEdidData[StartAddr + EDID_HDMI_3D_PRESENT_POS] + & EDID_HDMI_3D_MULTI_PRESENT_MASK; + } + + if (VSDB3DPresent) { + DPRINTF("VSDB 3D Present!!!\r\n"); + // check with 3D madatory format + if (CheckResolution(pVideo->resolution, pVideo->pixelAspectRatio)) { + int size = sizeof(edid_3d)/sizeof(struct edid_3d_mandatory); + for (edid_index = 0; edid_index < size; edid_index++) { + if (edid_3d[edid_index].resolution == pVideo->resolution && + edid_3d[edid_index].hdmi_3d_format == pVideo->hdmi_3d_format ) + return 1; + } + } + } + + // check 3D_Multi_Present bit + if (VSDB3DMultiPresent) { + DPRINTF("VSDB 3D Multi Present!!! = 0x%02x\r\n",VSDB3DMultiPresent); + // 3D Structure only + if (VSDB3DMultiPresent == EDID_3D_STRUCTURE_ONLY_EXIST) { + // 3D Structure All + Hdmi3DStructure = (gEdidData[StartAddr + EDID_HDMI_EXT_LENGTH_POS + HDMIVICLen + 1] << 8); + Hdmi3DStructure |= gEdidData[StartAddr + EDID_HDMI_EXT_LENGTH_POS + HDMIVICLen + 2]; + DPRINTF("VSDB 3D Structure!!! = [0x%02x]\r\n",Hdmi3DStructure); + } + + // 3D Structure and Mask + if (VSDB3DMultiPresent == EDID_3D_STRUCTURE_MASK_EXIST) { + // 3D Structure All + Hdmi3DStructure = (gEdidData[StartAddr + EDID_HDMI_EXT_LENGTH_POS + HDMIVICLen + 1] << 8); + Hdmi3DStructure |= gEdidData[StartAddr + EDID_HDMI_EXT_LENGTH_POS + HDMIVICLen + 2]; + // 3D Structure Mask + Hdmi3DMask |= (gEdidData[StartAddr + EDID_HDMI_EXT_LENGTH_POS + HDMIVICLen + 3] << 8); + Hdmi3DMask |= gEdidData[StartAddr + EDID_HDMI_EXT_LENGTH_POS + HDMIVICLen + 4]; + DPRINTF("VSDB 3D Structure!!! = [0x%02x]\r\n",Hdmi3DStructure); + DPRINTF("VSDB 3D Mask!!! = [0x%02x]\r\n",Hdmi3DMask); + DPRINTF("Current 3D Video format!!! = [%d]\r\n",pVideo->hdmi_3d_format); + DPRINTF("Current 3D Video format!!! = [0x%02x]\r\n",1<hdmi_3d_format); + } + + // check 3D Structure and Mask + if (Hdmi3DStructure & (1<hdmi_3d_format)) { + DPRINTF("VSDB 3D Structure Contains Current Video Structure!!!\r\n"); + // check first 16 EDID + for (edid_index = 0; edid_index < NUM_OF_VIC_FOR_3D; edid_index++) { + DPRINTF("VIC = %d, EDID Vic = %d!!!\r\n",vic,aVIC[edid_index]); + if (Hdmi3DMask & (1<= (EDID_HDMI_EXT_LENGTH_POS - latency_offset)) { + unsigned int HDMI3DExtLen = HDMI3DLen - (VSDB3DMultiPresent>>EDID_HDMI_3D_MULTI_PRESENT_BIT)*2; + unsigned int VICOrder; + + // check if there is 3D extra data ? + //TODO: check 3D_Detail in case of SSH + if (HDMI3DExtLen) { + // check HDMI 3D Extra Data + for (edid_index = 0; edid_index < (int)(HDMI3DExtLen / 2); edid_index++) { + VICOrder = gEdidData[StartAddr + EDID_HDMI_EXT_LENGTH_POS + HDMIVICLen + + (VSDB3DMultiPresent>>EDID_HDMI_3D_MULTI_PRESENT_BIT) * 2 + edid_index * 2] + & EDID_HDMI_2D_VIC_ORDER_MASK; + VICOrder = (1<>EDID_HDMI_3D_MULTI_PRESENT_BIT) * 2 + edid_index * 2] + & EDID_HDMI_3D_STRUCTURE_MASK; + Hdmi3DStructure = (1<hdmi_3d_format && vic == aVIC[VICOrder]) + return 1; + } + } + } + } + } + + return 0; +} + +/** + * Initialize EDID library. This will intialize DDC library. + * @return If success, return 1; Otherwise, return 0. + */ +int EDIDOpen(void) +{ + // init DDC + return DDCOpen(); +} + +/** + * Finalize EDID library. This will finalize DDC library. + * @return If success, return 1; Otherwise, return 0. + */ +int EDIDClose(void) +{ + // reset EDID + EDIDReset(); + + // close EDDC + return DDCClose(); +} + +/** + * Read EDID data of Rx. + * @return If success, return 1; Otherwise, return 0; + */ +int EDIDRead(void) +{ + int block,dataPtr; + unsigned char temp[SIZEOFEDIDBLOCK]; + + // if already read?? + if (EDIDValid()) + return 1; + + // read EDID Extension Number + // read EDID + if (!ReadEDIDBlock(0,temp)) + return 0; + + // get extension + gExtensions = temp[EDID_EXTENSION_NUMBER_POS]; + + // prepare buffer + gEdidData = (unsigned char*)malloc((gExtensions+1)*SIZEOFEDIDBLOCK); + if (!gEdidData) + return 0; + + // copy EDID Block 0 + memcpy(gEdidData,temp,SIZEOFEDIDBLOCK); + + // read EDID Extension + for (block = 1,dataPtr = SIZEOFEDIDBLOCK; block <= gExtensions; block++,dataPtr+=SIZEOFEDIDBLOCK) { + // read extension 1~gExtensions + if (!ReadEDIDBlock(block, gEdidData+dataPtr)) { + // reset buffer + EDIDReset(); + return 0; + } + } + + // check if extension is more than 1, and first extension block is not block map. + if (gExtensions > 1 && gEdidData[SIZEOFEDIDBLOCK] != EDID_BLOCK_MAP_EXT_TAG_VAL) { + // reset buffer + DPRINTF("EDID has more than 1 extension but, first extension block is not block map\n"); + EDIDReset(); + return 0; + } + + return 1; +} + +/** + * Reset stored EDID data. + */ +void EDIDReset(void) +{ + if (gEdidData) { + free(gEdidData); + gEdidData = NULL; + DPRINTF("\t\t\t\tEDID is reset!!!\n"); + } +} + +/** + * Get CEC physical address. + * @param outAddr [out] CEC physical address. LSB 2 bytes is available. [0:0:AB:CD] + * @return If success, return 1; Otherwise, return 0. + */ +int EDIDGetCECPhysicalAddress(int* const outAddr) +{ + int i; + unsigned int StartAddr; + + // check EDID data is valid or not + // read EDID + if (!EDIDRead()) + return 0; + + // find VSDB + for (i = 1; i <= gExtensions; i++) { + if (IsTimingExtension(i) // if it's timing block + && (StartAddr = GetVSDBOffset(i)) > 0) { // check block + // get supported DC value + // int tempDC1 = (int)(gEdidData[tempAddr+EDID_DC_POS]); + int phyAddr = gEdidData[StartAddr + EDID_CEC_PHYICAL_ADDR] << 8; + phyAddr |= gEdidData[StartAddr + EDID_CEC_PHYICAL_ADDR+1]; + + DPRINTF("phyAddr = %x\n",phyAddr); + + *outAddr = phyAddr; + + return 1; + } + } + + return 0; +} + +/** + * Check if Rx supports HDMI/DVI mode or not. + * @param video [in] HDMI or DVI mode to check + * @return If Rx supports requested mode, return 1; Otherwise, return 0. + */ +int EDIDHDMIModeSupport(struct HDMIVideoParameter * const video) +{ + // check if read edid? + if (!EDIDRead()) { + DPRINTF("EDID Read Fail!!!\n"); + return 0; + } + + // check hdmi mode + if (video->mode == HDMI) { + if (!CheckHDMIMode()) { + DPRINTF("HDMI mode Not Supported\n"); + return 0; + } + } + return 1; +} + +/** + * Check if Rx supports requested video resoultion or not. + * @param video [in] Video parameters to check + * @return If Rx supports video parameters, return 1; Otherwise, return 0. + */ +int EDIDVideoResolutionSupport(struct HDMIVideoParameter * const video) +{ + unsigned int TMDSClock; + unsigned int MaxTMDS = 0; + + // check if read edid? + if (!EDIDRead()) { + DPRINTF("EDID Read Fail!!!\n"); + return 0; + } + + // get max tmds + MaxTMDS = GetMaxTMDS()*5; + + // Check MAX TMDS + TMDSClock = aVideoParams[video->resolution].PixelClock/100; + if (video->colorDepth == HDMI_CD_36) + TMDSClock *= 1.5; + else if (video->colorDepth == HDMI_CD_30) + TMDSClock *=1.25; + + DPRINTF("MAX TMDS = %d, Current TMDS = %d\n",MaxTMDS, TMDSClock); + if (MaxTMDS != 0 && MaxTMDS < TMDSClock) { + DPRINTF("Pixel clock is beyond Maximun TMDS in EDID\n"); + return 0; + } + + // check resolution + if (!CheckResolution(video->resolution,video->pixelAspectRatio)) { + DPRINTF("Video Resolution Not Supported\n"); + return 0; + } + + // check 3D format + if (!EDID3DFormatSupport(video)) { + DPRINTF("3D Format Not Supported\n"); + return 0; + } + + return 1; +} + +/** + * Check if Rx supports requested color depth or not. + * @param video [in] Video parameters to check + * @return If Rx supports video parameters, return 1; Otherwise, return 0. + */ +int EDIDColorDepthSupport(struct HDMIVideoParameter * const video) +{ + // check if read edid? + if (!EDIDRead()) { + DPRINTF("EDID Read Fail!!!\n"); + return 0; + } + + // check resolution + if (!CheckColorDepth(video->colorDepth,video->colorSpace)) { + DPRINTF("Color Depth Not Supported\n"); + return 0; + } + + return 1; +} + +/** + * Check if Rx supports requested color space or not. + * @param video [in] Video parameters to check + * @return If Rx supports video parameters, return 1; Otherwise, return 0. + */ +int EDIDColorSpaceSupport(struct HDMIVideoParameter * const video) +{ + // check if read edid? + if (!EDIDRead()) { + DPRINTF("EDID Read Fail!!!\n"); + return 0; + } + // check color space + if (!CheckColorSpace(video->colorSpace)) { + DPRINTF("Color Space Not Supported\n"); + return 0; + } + + return 1; +} + +/** + * Check if Rx supports requested colorimetry or not. + * @param video [in] Video parameters to check + * @return If Rx supports video parameters, return 1; Otherwise, return 0. + */ +int EDIDColorimetrySupport(struct HDMIVideoParameter * const video) +{ + // check if read edid? + if (!EDIDRead()) { + DPRINTF("EDID Read Fail!!!\n"); + return 0; + } + + // check colorimetry + if (!CheckColorimetry(video->colorimetry)) { + DPRINTF("Colorimetry Not Supported\n"); + return 0; + } + + return 1; +} + +/** + * Check if Rx supports requested audio parameters or not. + * @param audio [in] Audio parameters to check + * @return If Rx supports audio parameters, return 1; Otherwise, return 0. + */ +int EDIDAudioModeSupport(struct HDMIAudioParameter * const audio) +{ + int i; + + // read EDID + if (!EDIDRead()) { + DPRINTF("EDID Read Fail!!!\n"); + return 0; + } + + // check EDID Extension + // find timing block + for (i = 1; i <= gExtensions; i++) { + if (IsTimingExtension(i)) { // if it's timing block + // find Short Audio Description + unsigned int StartAddr = i*SIZEOFEDIDBLOCK; + unsigned int ExtAddr = StartAddr + EDID_DATA_BLOCK_START_POS; + unsigned int tag,blockLen; + unsigned int DTDStartAddr = gEdidData[StartAddr + EDID_DETAILED_TIMING_OFFSET_POS]; + + while (ExtAddr < StartAddr + DTDStartAddr) { + // find the block tag and length + // tag + tag = gEdidData[ExtAddr] & EDID_TAG_CODE_MASK; + // block len + blockLen = (gEdidData[ExtAddr] & EDID_DATA_BLOCK_SIZE_MASK) + 1; + + DPRINTF("tag = %d\n",tag); + DPRINTF("blockLen = %d\n",blockLen-1); + + // check if it is short video description + if (tag == EDID_SHORT_AUD_DEC_TAG_VAL) { + // if so, check SAD + unsigned int j, channelNum; + int audioFormat,sampleFreq,wordLen; + for (j = 1; j < blockLen; j += 3) { + audioFormat = gEdidData[ExtAddr+j] & EDID_SAD_CODE_MASK; + channelNum = gEdidData[ExtAddr+j] & EDID_SAD_CHANNEL_MASK; + sampleFreq = gEdidData[ExtAddr+j+1]; + wordLen = gEdidData[ExtAddr+j+2]; + + DPRINTF("request = %d, EDIDAudioFormatCode = %d\n",(audio->formatCode)<<3, audioFormat); + DPRINTF("request = %d, EDIDChannelNumber= %d\n",(audio->channelNum)-1, channelNum); + DPRINTF("request = %d, EDIDSampleFreq= %d\n",1<<(audio->sampleFreq), sampleFreq); + DPRINTF("request = %d, EDIDWordLeng= %d\n",1<<(audio->wordLength), wordLen); + + // check parameter + // check audioFormat + if (audioFormat & ( (audio->formatCode) << 3) && // format code + channelNum >= ( (audio->channelNum) -1) && // channel number + (sampleFreq & (1<<(audio->sampleFreq)))) { // sample frequency + if (audioFormat == LPCM_FORMAT) { // check wordLen + int ret = 0; + switch (audio->wordLength) { + case WORD_16: + case WORD_17: + case WORD_18: + case WORD_19: + case WORD_20: + ret = wordLen & (1<<1); + break; + case WORD_21: + case WORD_22: + case WORD_23: + case WORD_24: + ret = wordLen & (1<<2); + break; + } + return ret; + } + return 1; // if not LPCM + } + } + } + // else find next block + ExtAddr += blockLen; + } + } + } + + return 0; +} diff --git a/exynos5/hal/libhdmi/libsForhdmi/libedid/libedid.h b/exynos5/hal/libhdmi/libsForhdmi/libedid/libedid.h new file mode 100644 index 0000000..dfd3096 --- /dev/null +++ b/exynos5/hal/libhdmi/libsForhdmi/libedid/libedid.h @@ -0,0 +1,42 @@ +/* + * Copyright@ Samsung Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _LIBEDID_H_ +#define _LIBEDID_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "video.h" +#include "audio.h" + +int EDIDOpen(void); +int EDIDRead(void); +void EDIDReset(void); +int EDIDHDMIModeSupport(struct HDMIVideoParameter *video); +int EDIDVideoResolutionSupport(struct HDMIVideoParameter *video); +int EDIDColorDepthSupport(struct HDMIVideoParameter *video); +int EDIDColorSpaceSupport(struct HDMIVideoParameter *video); +int EDIDColorimetrySupport(struct HDMIVideoParameter *video); +int EDIDAudioModeSupport(struct HDMIAudioParameter *audio); +int EDIDGetCECPhysicalAddress(int* outAddr); +int EDIDClose(void); + +#ifdef __cplusplus +} +#endif +#endif /* _LIBEDID_H_ */ diff --git a/exynos5/hal/libhwcomposer/Android.mk b/exynos5/hal/libhwcomposer/Android.mk new file mode 100644 index 0000000..982d1be --- /dev/null +++ b/exynos5/hal/libhwcomposer/Android.mk @@ -0,0 +1,82 @@ +# Copyright (C) 2008 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +LOCAL_PATH:= $(call my-dir) +# HAL module implemenation, not prelinked and stored in +# hw/..so + +include $(CLEAR_VARS) +LOCAL_PRELINK_MODULE := false +LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw +LOCAL_SHARED_LIBRARIES := liblog libcutils libEGL \ + libGLESv1_CM + +LOCAL_SHARED_LIBRARIES += libion + +LOCAL_C_INCLUDES := \ + $(LOCAL_PATH)/../include + +LOCAL_SRC_FILES := SecHWCLog.cpp SecHWCUtils.cpp SecHWC.cpp + +LOCAL_C_INCLUDES += $(LOCAL_PATH)/../libfimg + +ifeq ($(TARGET_SOC),exynos4210) +LOCAL_CFLAGS += -DSAMSUNG_EXYNOS4210 +endif + +ifeq ($(TARGET_SOC),exynos4212) +LOCAL_CFLAGS += -DSAMSUNG_EXYNOS4212 +endif + +ifeq ($(TARGET_SOC),exynos5250) +LOCAL_CFLAGS += -DSAMSUNG_EXYNOS5250 +endif + +ifeq ($(BOARD_USES_HDMI),true) +LOCAL_C_INCLUDES += \ + device/samsung/$(TARGET_BOARD_PLATFORM)/libhwcomposer \ + device/samsung/$(TARGET_BOARD_PLATFORM)/include \ + device/samsung/$(TARGET_BOARD_PLATFORM)/libhdmi/libhdmiservice + +LOCAL_SHARED_LIBRARIES += libhdmiclient libTVOut + +LOCAL_CFLAGS += -DBOARD_USES_HDMI +LOCAL_CFLAGS += -DBOARD_HDMI_STD=$(BOARD_HDMI_STD) +LOCAL_CFLAGS += -DVIDEO_DUAL_DISPLAY + +ifeq ($(BOARD_USES_HDMI_SUBTITLES),true) + LOCAL_CFLAGS += -DBOARD_USES_HDMI_SUBTITLES +endif + +ifeq ($(BOARD_HDMI_STD), STD_NTSC_M) +LOCAL_CFLAGS += -DSTD_NTSC_M +endif + +ifeq ($(BOARD_HDMI_STD),STD_480P) +LOCAL_CFLAGS += -DSTD_480P +endif + +ifeq ($(BOARD_HDMI_STD),STD_720P) +LOCAL_CFLAGS += -DSTD_720P +endif + +ifeq ($(BOARD_HDMI_STD),STD_1080P) +LOCAL_CFLAGS += -DSTD_1080P +endif +endif + +LOCAL_MODULE := hwcomposer.$(TARGET_BOARD_PLATFORM) +LOCAL_MODULE_TAGS := optional +include $(BUILD_SHARED_LIBRARY) diff --git a/exynos5/hal/libhwcomposer/SecHWC.cpp b/exynos5/hal/libhwcomposer/SecHWC.cpp new file mode 100644 index 0000000..31ea1b5 --- /dev/null +++ b/exynos5/hal/libhwcomposer/SecHWC.cpp @@ -0,0 +1,901 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * + * @author Rama, Meka(v.meka@samsung.com) + Sangwoo, Park(sw5771.park@samsung.com) + Jamie Oh (jung-min.oh@samsung.com) + * @date 2011-03-11 + * + */ + +#include +#include +#include + +#include "SecHWCUtils.h" +#include "gralloc_priv.h" + +#ifdef HWC_HWOVERLAY +#include +#endif + +//#define CHECK_EGL_FPS +#ifdef CHECK_EGL_FPS +extern void check_fps(); +#endif + +#if defined(BOARD_USES_HDMI) +#include "SecHdmiClient.h" +#include "SecTVOutService.h" +#include "SecHdmi.h" + +static int lcd_width, lcd_height; +static int prev_format = 0; + +#define CHECK_TIME_DEBUG 0 +#define SUPPORT_AUTO_UI_ROTATE +#endif + +static int hwc_device_open(const struct hw_module_t* module, const char* name, + struct hw_device_t** device); + +static struct hw_module_methods_t hwc_module_methods = { + open: hwc_device_open +}; + +hwc_module_t HAL_MODULE_INFO_SYM = { + common: { + tag: HARDWARE_MODULE_TAG, + version_major: 1, + version_minor: 0, + id: HWC_HARDWARE_MODULE_ID, + name: "Samsung S5PC21X hwcomposer module", + author: "SAMSUNG", + methods: &hwc_module_methods, + } +}; + +/*****************************************************************************/ + +static void dump_layer(hwc_layer_t const* l) { + LOGD("\ttype=%d, flags=%08x, handle=%p, tr=%02x, blend=%04x, " + "{%d,%d,%d,%d}, {%d,%d,%d,%d}", + l->compositionType, l->flags, l->handle, l->transform, l->blending, + l->sourceCrop.left, + l->sourceCrop.top, + l->sourceCrop.right, + l->sourceCrop.bottom, + l->displayFrame.left, + l->displayFrame.top, + l->displayFrame.right, + l->displayFrame.bottom); +} + +void calculate_rect(struct hwc_win_info_t *win, hwc_layer_t *cur, + sec_rect *rect) +{ + rect->x = cur->displayFrame.left; + rect->y = cur->displayFrame.top; + rect->w = cur->displayFrame.right - cur->displayFrame.left; + rect->h = cur->displayFrame.bottom - cur->displayFrame.top; + + if (rect->x < 0) { + if (rect->w + rect->x > win->lcd_info.xres) + rect->w = win->lcd_info.xres; + else + rect->w = rect->w + rect->x; + rect->x = 0; + } else { + if (rect->w + rect->x > win->lcd_info.xres) + rect->w = win->lcd_info.xres - rect->x; + } + if (rect->y < 0) { + if (rect->h + rect->y > win->lcd_info.yres) + rect->h = win->lcd_info.yres; + else + rect->h = rect->h + rect->y; + rect->y = 0; + } else { + if (rect->h + rect->y > win->lcd_info.yres) + rect->h = win->lcd_info.yres - rect->y; + } +} + +static int set_src_dst_img_rect(hwc_layer_t *cur, + struct hwc_win_info_t *win, + struct sec_img *src_img, + struct sec_img *dst_img, + struct sec_rect *src_rect, + struct sec_rect *dst_rect, + int win_idx) +{ + private_handle_t *prev_handle = (private_handle_t *)(cur->handle); + sec_rect rect; + + /* 1. Set src_img from prev_handle */ + src_img->f_w = prev_handle->width; + src_img->f_h = prev_handle->height; + src_img->w = prev_handle->width; + src_img->h = prev_handle->height; + src_img->format = prev_handle->format; + src_img->base = (uint32_t)prev_handle->base; + src_img->offset = prev_handle->offset; + src_img->mem_id = prev_handle->fd; + src_img->paddr = prev_handle->paddr; + src_img->usage = prev_handle->usage; + src_img->uoffset = prev_handle->uoffset; + src_img->voffset = prev_handle->voffset; + + switch (src_img->format) { + case HAL_PIXEL_FORMAT_YV12: + case HAL_PIXEL_FORMAT_YCbCr_420_P: + case HAL_PIXEL_FORMAT_YCrCb_420_SP: + case HAL_PIXEL_FORMAT_YCbCr_420_SP: + case HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_P_SBS_LR: + case HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_P_SBS_RL: + case HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_P_TB_LR: + case HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_P_TB_RL: + src_img->f_w = (src_img->f_w + 15) & ~15; + src_img->f_h = (src_img->f_h + 15) & ~15; + break; + default: + src_img->f_w = src_img->w; + src_img->f_h = src_img->h; + break; + } + + /* 2. Set dst_img from window(lcd) */ + calculate_rect(win, cur, &rect); + dst_img->f_w = win->lcd_info.xres; + dst_img->f_h = win->lcd_info.yres; + dst_img->w = rect.w; + dst_img->h = rect.h; + + switch (win->lcd_info.bits_per_pixel) { + case 32: + dst_img->format = HAL_PIXEL_FORMAT_RGBX_8888; + break; + default: + dst_img->format = HAL_PIXEL_FORMAT_RGB_565; + break; + } + + dst_img->base = win->addr[win->buf_index]; + dst_img->offset = 0; + dst_img->mem_id = 0; + + /* 3. Set src_rect(crop rect) */ + if (cur->displayFrame.left < 0) { + src_rect->x = + (0 - cur->displayFrame.left) + *(src_img->w) + /(cur->displayFrame.right - cur->displayFrame.left + 1); + if (cur->displayFrame.right + 1 > win->lcd_info.xres) { + src_rect->w = + (cur->sourceCrop.right - cur->sourceCrop.left + 1) - + src_rect->x - + (cur->displayFrame.right - win->lcd_info.xres) + *(src_img->w) + /(cur->displayFrame.right - cur->displayFrame.left + 1); + } else { + src_rect->w = + (cur->sourceCrop.right - cur->sourceCrop.left + 1) - + src_rect->x; + } + } else { + src_rect->x = cur->sourceCrop.left; + if (cur->displayFrame.right + 1 > win->lcd_info.xres) { + src_rect->w = + (cur->sourceCrop.right - cur->sourceCrop.left + 1) - + src_rect->x - + (cur->displayFrame.right - win->lcd_info.xres) + *(src_img->w) + /(cur->displayFrame.right - cur->displayFrame.left + 1); + } else { + src_rect->w = + (cur->sourceCrop.right - cur->sourceCrop.left + 1); + } + } + if (cur->displayFrame.top < 0) { + src_rect->y = + (0 - cur->displayFrame.top) + *(src_img->h) + /(cur->displayFrame.bottom - cur->displayFrame.top + 1); + if (cur->displayFrame.bottom + 1 > win->lcd_info.yres) { + src_rect->h = + (cur->sourceCrop.bottom - cur->sourceCrop.top + 1) - + src_rect->y - + (cur->displayFrame.bottom - win->lcd_info.yres) + *(src_img->h) + /(cur->displayFrame.bottom - cur->displayFrame.top + 1); + } else { + src_rect->h = + (cur->sourceCrop.bottom - cur->sourceCrop.top + 1) - + src_rect->y; + } + } else { + src_rect->y = cur->sourceCrop.top; + if (cur->displayFrame.bottom + 1 > win->lcd_info.yres) { + src_rect->h = + (cur->sourceCrop.bottom - cur->sourceCrop.top + 1) - + src_rect->y - + (cur->displayFrame.bottom - win->lcd_info.yres) + *(src_img->h) + /(cur->displayFrame.bottom - cur->displayFrame.top + 1); + } else { + src_rect->h = + (cur->sourceCrop.bottom - cur->sourceCrop.top + 1); + } + } + + SEC_HWC_Log(HWC_LOG_DEBUG, + "crop information()::" + "sourceCrop left(%d),top(%d),right(%d),bottom(%d)," + "src_rect x(%d),y(%d),w(%d),h(%d)," + "prev_handle w(%d),h(%d)", + cur->sourceCrop.left, + cur->sourceCrop.top, + cur->sourceCrop.right, + cur->sourceCrop.bottom, + src_rect->x, src_rect->y, src_rect->w, src_rect->h, + prev_handle->width, prev_handle->height); + + src_rect->x = SEC_MAX(src_rect->x, 0); + src_rect->y = SEC_MAX(src_rect->y, 0); + src_rect->w = SEC_MAX(src_rect->w, 0); + src_rect->w = SEC_MIN(src_rect->w, prev_handle->width); + src_rect->h = SEC_MAX(src_rect->h, 0); + src_rect->h = SEC_MIN(src_rect->h, prev_handle->height); + + /* 4. Set dst_rect(fb or lcd) + * fimc dst image will be stored from left top corner + */ + dst_rect->x = 0; + dst_rect->y = 0; + dst_rect->w = win->rect_info.w; + dst_rect->h = win->rect_info.h; + + /* Summery */ + SEC_HWC_Log(HWC_LOG_DEBUG, + "set_src_dst_img_rect()::" + "SRC w(%d),h(%d),f_w(%d),f_h(%d),fmt(0x%x)," + "base(0x%x),offset(%d),paddr(0x%X)=>\r\n" + " DST w(%d),h(%d),f(0x%x),base(0x%x)," + "offset(%d),mem_id(%d)," + "rot(%d),win_idx(%d)" + " SRC_RECT x(%d),y(%d),w(%d),h(%d)=>" + "DST_RECT x(%d),y(%d),w(%d),h(%d)", + src_img->w, src_img->h, src_img->f_w, src_img->f_h, src_img->format, + src_img->base, src_img->offset, src_img->paddr, + dst_img->w, dst_img->h, dst_img->format, dst_img->base, + dst_img->offset, dst_img->mem_id, + cur->transform, win_idx, + src_rect->x, src_rect->y, src_rect->w, src_rect->h, + dst_rect->x, dst_rect->y, dst_rect->w, dst_rect->h); + + return 0; +} + +static int get_hwc_compos_decision(hwc_layer_t* cur, int iter, int win_cnt) +{ + if(cur->flags & HWC_SKIP_LAYER || !cur->handle) { + SEC_HWC_Log(HWC_LOG_DEBUG, "%s::is_skip_layer %d cur->handle %x ", + __func__, cur->flags & HWC_SKIP_LAYER, cur->handle); + + return HWC_FRAMEBUFFER; + } + + private_handle_t *prev_handle = (private_handle_t *)(cur->handle); + int compositionType = HWC_FRAMEBUFFER; + + if (iter == 0) { + /* check here....if we have any resolution constraints */ + if (((cur->sourceCrop.right - cur->sourceCrop.left + 1) < 16) || + ((cur->sourceCrop.bottom - cur->sourceCrop.top + 1) < 8)) + return compositionType; + + if ((cur->transform == HAL_TRANSFORM_ROT_90) || + (cur->transform == HAL_TRANSFORM_ROT_270)) { + if (((cur->displayFrame.right - cur->displayFrame.left + 1) < 4) || + ((cur->displayFrame.bottom - cur->displayFrame.top + 1) < 8)) + return compositionType; + } else if (((cur->displayFrame.right - cur->displayFrame.left + 1) < 8) || + ((cur->displayFrame.bottom - cur->displayFrame.top + 1) < 4)) { + return compositionType; + } + + switch (prev_handle->format) { + case HAL_PIXEL_FORMAT_YV12: /* YCrCb_420_P */ + case HAL_PIXEL_FORMAT_YCbCr_420_P: + case HAL_PIXEL_FORMAT_YCrCb_420_SP: + case HAL_PIXEL_FORMAT_YCbCr_420_SP: + case HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_P_SBS_LR: + case HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_P_SBS_RL: + case HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_P_TB_LR: + case HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_P_TB_RL: + if ((prev_handle->usage & GRALLOC_USAGE_HWC_HWOVERLAY) && + (cur->blending == HWC_BLENDING_NONE)) + compositionType = HWC_OVERLAY; + else + compositionType = HWC_FRAMEBUFFER; + break; + default: + compositionType = HWC_FRAMEBUFFER; + break; + } + } + +#ifdef SUB_TITLES_HWC + else if ((win_cnt > 0) && + (prev_handle->usage & GRALLOC_USAGE_EXTERNAL_DISP)) { + switch (prev_handle->format) { + case HAL_PIXEL_FORMAT_RGBA_8888: + case HAL_PIXEL_FORMAT_RGBX_8888: + case HAL_PIXEL_FORMAT_BGRA_8888: + case HAL_PIXEL_FORMAT_RGB_888: + case HAL_PIXEL_FORMAT_RGB_565: + case HAL_PIXEL_FORMAT_RGBA_5551: + case HAL_PIXEL_FORMAT_RGBA_4444: + compositionType = HWC_OVERLAY; + break; + default: + compositionType = HWC_FRAMEBUFFER; + break; + } + + SEC_HWC_Log(HWC_LOG_DEBUG, "2nd iter###%s:: compositionType %d bpp %d" + " format %x src[%d %d %d %d] dst[%d %d %d %d] srcImg[%d %d]", + __func__, compositionType, prev_handle->bpp, + prev_handle->format, + cur->sourceCrop.left, cur->sourceCrop.right, + cur->sourceCrop.top, cur->sourceCrop.bottom, + cur->displayFrame.left, cur->displayFrame.right, + cur->displayFrame.top, cur->displayFrame.bottom, + prev_handle->width, prev_handle->height); + } +#endif + + SEC_HWC_Log(HWC_LOG_DEBUG, + "%s::compositionType(%d)=>0:FB,1:OVERLAY \r\n" + " format(0x%x),magic(0x%x),flags(%d),size(%d),offset(%d)" + "b_addr(0x%x),usage(%d),w(%d),h(%d),bpp(%d)", + "get_hwc_compos_decision()", compositionType, + prev_handle->format, prev_handle->magic, prev_handle->flags, + prev_handle->size, prev_handle->offset, prev_handle->base, + prev_handle->usage, prev_handle->width, prev_handle->height, + prev_handle->bpp); + + return compositionType; +} + +static void reset_win_rect_info(hwc_win_info_t *win) +{ + win->rect_info.x = 0; + win->rect_info.y = 0; + win->rect_info.w = 0; + win->rect_info.h = 0; + return; +} + + +static int assign_overlay_window(struct hwc_context_t *ctx, hwc_layer_t *cur, + int win_idx, int layer_idx) +{ + struct hwc_win_info_t *win; + sec_rect rect; + int ret = 0; + + if (NUM_OF_WIN <= win_idx) + return -1; + + win = &ctx->win[win_idx]; + + SEC_HWC_Log(HWC_LOG_DEBUG, + "%s:: left(%d),top(%d),right(%d),bottom(%d),transform(%d)" + "lcd_info.xres(%d),lcd_info.yres(%d)", + "++assign_overlay_window()", + cur->displayFrame.left, cur->displayFrame.top, + cur->displayFrame.right, cur->displayFrame.bottom, cur->transform, + win->lcd_info.xres, win->lcd_info.yres); + + calculate_rect(win, cur, &rect); + + if ((rect.x != win->rect_info.x) || (rect.y != win->rect_info.y) || + (rect.w != win->rect_info.w) || (rect.h != win->rect_info.h)){ + win->rect_info.x = rect.x; + win->rect_info.y = rect.y; + win->rect_info.w = rect.w; + win->rect_info.h = rect.h; + //turnoff the window and set the window position with new conf... + if (window_set_pos(win) < 0) { + SEC_HWC_Log(HWC_LOG_ERROR, "%s::window_set_pos is failed : %s", + __func__, strerror(errno)); + ret = -1; + } + ctx->layer_prev_buf[win_idx] = 0; + } + + win->layer_index = layer_idx; + win->status = HWC_WIN_RESERVED; + + SEC_HWC_Log(HWC_LOG_DEBUG, + "%s:: win_x %d win_y %d win_w %d win_h %d lay_idx %d win_idx %d\n", + "--assign_overlay_window()", + win->rect_info.x, win->rect_info.y, win->rect_info.w, + win->rect_info.h, win->layer_index, win_idx ); + + return 0; +} + +static int hwc_prepare(hwc_composer_device_t *dev, hwc_layer_list_t* list) +{ + struct hwc_context_t* ctx = (struct hwc_context_t*)dev; + int overlay_win_cnt = 0; + int compositionType = 0; + int ret; + + //if geometry is not changed, there is no need to do any work here + if (!list || (!(list->flags & HWC_GEOMETRY_CHANGED))) + return 0; + + //all the windows are free here.... + for (int i = 0 ; i < NUM_OF_WIN; i++) { + ctx->win[i].status = HWC_WIN_FREE; + ctx->win[i].buf_index = 0; + } + + ctx->num_of_hwc_layer = 0; + ctx->num_of_fb_layer = 0; + ctx->num_2d_blit_layer = 0; + + for (int i = 0; i < list->numHwLayers ; i++) { + hwc_layer_t* cur = &list->hwLayers[i]; + + if (overlay_win_cnt < NUM_OF_WIN) { + compositionType = get_hwc_compos_decision(cur, 0, overlay_win_cnt); + + if (compositionType == HWC_FRAMEBUFFER) { + cur->compositionType = HWC_FRAMEBUFFER; + ctx->num_of_fb_layer++; + } else { + ret = assign_overlay_window(ctx, cur, overlay_win_cnt, i); + if (ret != 0) { + LOGE("assign_overlay_window fail, change to frambuffer"); + cur->compositionType = HWC_FRAMEBUFFER; + ctx->num_of_fb_layer++; + continue; + } + + cur->compositionType = HWC_OVERLAY; + cur->hints = HWC_HINT_CLEAR_FB; + overlay_win_cnt++; + ctx->num_of_hwc_layer++; + } + } else { + cur->compositionType = HWC_FRAMEBUFFER; + ctx->num_of_fb_layer++; + } + } + +#ifdef SUB_TITLES_HWC + for (int i = 0; i < list->numHwLayers ; i++) { + if (overlay_win_cnt < NUM_OF_WIN) { + hwc_layer_t* cur = &list->hwLayers[i]; + if (get_hwc_compos_decision(cur, 1, overlay_win_cnt) == HWC_OVERLAY) { + ret = assign_overlay_window(ctx, cur, overlay_win_cnt, i); + if (ret == 0) { + cur->compositionType = HWC_OVERLAY; + cur->hints = HWC_HINT_CLEAR_FB; + overlay_win_cnt++; + ctx->num_of_hwc_layer++; + ctx->num_of_fb_layer--; + ctx->num_2d_blit_layer = 1; + } + } + } + else + break; + } +#endif + +#if defined(BOARD_USES_HDMI) + android::SecHdmiClient *mHdmiClient = android::SecHdmiClient::getInstance(); + mHdmiClient->setHdmiHwcLayer(ctx->num_of_hwc_layer); +#endif + + if (list->numHwLayers != (ctx->num_of_fb_layer + ctx->num_of_hwc_layer)) + SEC_HWC_Log(HWC_LOG_DEBUG, + "%s:: numHwLayers %d num_of_fb_layer %d num_of_hwc_layer %d ", + __func__, list->numHwLayers, ctx->num_of_fb_layer, + ctx->num_of_hwc_layer); + + if (overlay_win_cnt < NUM_OF_WIN) { + //turn off the free windows + for (int i = overlay_win_cnt; i < NUM_OF_WIN; i++) { + window_hide(&ctx->win[i]); + reset_win_rect_info(&ctx->win[i]); + } + } + + return 0; +} + +static int hwc_set(hwc_composer_device_t *dev, + hwc_display_t dpy, + hwc_surface_t sur, + hwc_layer_list_t* list) +{ + struct hwc_context_t *ctx = (struct hwc_context_t *)dev; + int skipped_window_mask = 0; + hwc_layer_t* cur; + struct hwc_win_info_t *win; + int ret; + int pmem_phyaddr; + struct sec_img src_img; + struct sec_img dst_img; + struct sec_rect src_work_rect; + struct sec_rect dst_work_rect; +#if defined(BOARD_USES_HDMI) + int skip_hdmi_rendering = 0; + int rotVal = 0; +#endif + if (!list) { + //turn off the all windows + for (int i = 0; i < NUM_OF_WIN; i++) { + window_hide(&ctx->win[i]); + reset_win_rect_info(&ctx->win[i]); + ctx->win[i].status = HWC_WIN_FREE; + } + ctx->num_of_hwc_layer = 0; + } + + if(ctx->num_of_hwc_layer > NUM_OF_WIN) + ctx->num_of_hwc_layer = NUM_OF_WIN; + + //compose hardware layers here + for (int i = 0; i < ctx->num_of_hwc_layer - ctx->num_2d_blit_layer; i++) { + win = &ctx->win[i]; + if (win->status == HWC_WIN_RESERVED) { + cur = &list->hwLayers[win->layer_index]; + + if (cur->compositionType == HWC_OVERLAY) { + if (ctx->layer_prev_buf[i] == (uint32_t)cur->handle) { + /* + * In android platform, all the graphic buffer are at least + * double buffered (2 or more) this buffer is already rendered. + * It is the redundant src buffer for FIMC rendering. + */ + LOGD("SKIP FIMC rendering for Layer%d", win->layer_index); +#if defined(BOARD_USES_HDMI) + skip_hdmi_rendering = 1; +#endif + continue; + } + ctx->layer_prev_buf[i] = (uint32_t)cur->handle; + // initialize the src & dist context for fimc + set_src_dst_img_rect(cur, win, &src_img, &dst_img, + &src_work_rect, &dst_work_rect, i); + + ret = runFimc(ctx, + &src_img, &src_work_rect, + &dst_img, &dst_work_rect, + cur->transform); + + if (ret < 0) { + SEC_HWC_Log(HWC_LOG_ERROR, "%s::runFimc fail : ret=%d\n", + __func__, ret); + skipped_window_mask |= (1 << i); + continue; + } + + window_pan_display(win); + + win->buf_index = (win->buf_index + 1) % NUM_OF_WIN_BUF; + if (win->power_state == 0) + window_show(win); + } else { + SEC_HWC_Log(HWC_LOG_ERROR, + "%s:: error : layer %d compositionType should have been" + " HWC_OVERLAY ", __func__, win->layer_index); + skipped_window_mask |= (1 << i); + continue; + } + } else { + SEC_HWC_Log(HWC_LOG_ERROR, "%s:: error : window status should have " + "been HWC_WIN_RESERVED by now... ", __func__); + skipped_window_mask |= (1 << i); + continue; + } + } + +#ifdef SUB_TITLES_HWC + if (ctx->num_2d_blit_layer) { + g2d_rect srcRect; + g2d_rect dstRect; + + win = &ctx->win[ctx->num_of_hwc_layer - 1]; + cur = &list->hwLayers[win->layer_index]; + set_src_dst_g2d_rect(cur, win, &srcRect, &dstRect); + ret = runG2d(ctx, &srcRect, &dstRect, + cur->transform); + if (ret < 0) { + SEC_HWC_Log(HWC_LOG_ERROR, "%s::runG2d fail : ret=%d\n", + __func__, ret); + skipped_window_mask |= (1 << (ctx->num_of_hwc_layer - 1)); + goto g2d_error; + } + + window_pan_display(win); + + win->buf_index = (win->buf_index + 1) % NUM_OF_WIN_BUF; + if (win->power_state == 0) + window_show(win); + } + +g2d_error: +#endif + + if (skipped_window_mask) { + //turn off the free windows + for (int i = 0; i < NUM_OF_WIN; i++) { + if (skipped_window_mask & (1 << i)) { + window_hide(&ctx->win[i]); + reset_win_rect_info(&ctx->win[i]); + } + } + } + + if (0 < ctx->num_of_fb_layer) { +#ifdef CHECK_EGL_FPS + check_fps(); +#endif +#ifdef HWC_HWOVERLAY + glFinish(); +#endif + EGLBoolean sucess = eglSwapBuffers((EGLDisplay)dpy, (EGLSurface)sur); + if (!sucess) + return HWC_EGL_ERROR; + } + +#if defined(BOARD_USES_HDMI) + if (list == NULL || skip_hdmi_rendering == 1) + return 0; + + android::SecHdmiClient *mHdmiClient = android::SecHdmiClient::getInstance(); + +#ifdef SUPPORT_AUTO_UI_ROTATE + cur = &list->hwLayers[0]; + + if (cur->transform == HAL_TRANSFORM_ROT_90 || cur->transform == HAL_TRANSFORM_ROT_270) + mHdmiClient->setHdmiRotate(270, ctx->num_of_hwc_layer); + else + mHdmiClient->setHdmiRotate(0, ctx->num_of_hwc_layer); +#endif + + if (src_img.usage & GRALLOC_USAGE_PRIVATE_SBS_LR) + src_img.format = HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_P_SBS_LR; + else if (src_img.usage & GRALLOC_USAGE_PRIVATE_SBS_RL) + src_img.format = HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_P_SBS_RL; + else if (src_img.usage & GRALLOC_USAGE_PRIVATE_TB_LR) + src_img.format = HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_P_TB_LR; + else if (src_img.usage & GRALLOC_USAGE_PRIVATE_TB_RL) + src_img.format = HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_P_TB_RL; + + // To support S3D video playback (automatic TV mode change to 3D mode) + if (ctx->num_of_hwc_layer == 1) { + if (src_img.format != prev_format) { + if ((src_img.format == HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_P_SBS_LR) || + (src_img.format == HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_P_SBS_RL)) + mHdmiClient->setHdmiResolution(7209601); // V4L2_STD_TVOUT_720P_60_SBS_HALF + else if ((src_img.format == HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_P_TB_LR) || + (src_img.format == HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_P_TB_RL)) + mHdmiClient->setHdmiResolution(1080924); // V4L2_STD_TVOUT_1080P_24_TB + else + mHdmiClient->setHdmiResolution(DEFAULT_HDMI_RESOLUTION_VALUE); // V4L2_STD_1080P_60 + } + prev_format = src_img.format; + } else { + if ((prev_format == HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_P_SBS_LR) || + (prev_format == HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_P_SBS_RL) || + (prev_format == HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_P_TB_LR) || + (prev_format == HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_P_TB_RL)) + mHdmiClient->setHdmiResolution(DEFAULT_HDMI_RESOLUTION_VALUE); // V4L2_STD_1080P_60 + prev_format = HAL_PIXEL_FORMAT_BGRA_8888; + } + + if (ctx->num_of_hwc_layer == 1) { + if ((src_img.format == HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_SP_TILED)|| + (src_img.format == HAL_PIXEL_FORMAT_CUSTOM_YCrCb_420_SP) || + (src_img.format == HAL_PIXEL_FORMAT_YCbCr_420_SP) || + (src_img.format == HAL_PIXEL_FORMAT_YCrCb_420_SP) || + (src_img.format == HAL_PIXEL_FORMAT_YCbCr_420_P) || + (src_img.format == HAL_PIXEL_FORMAT_YV12) || + (src_img.format == HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_P_SBS_LR) || + (src_img.format == HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_P_SBS_RL) || + (src_img.format == HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_P_TB_LR) || + (src_img.format == HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_P_TB_RL)) { + mHdmiClient->blit2Hdmi(src_img.w, src_img.h, + src_img.format, + src_img.base, + src_img.base + src_img.uoffset, + src_img.base + src_img.uoffset + src_img.voffset, + 0, 0, + android::SecHdmiClient::HDMI_MODE_VIDEO, + ctx->num_of_hwc_layer); + } else { + LOGE("%s: Unsupported format = %d", __func__, src_img.format); + } + } +#endif + return 0; +} + +static int hwc_device_close(struct hw_device_t *dev) +{ + struct hwc_context_t* ctx = (struct hwc_context_t*)dev; + int ret = 0; + int i; + if (ctx) { + if (destroyVideoDev(&ctx->fimc) < 0) { + SEC_HWC_Log(HWC_LOG_ERROR, "%s::destroyVideoDev fail", __func__); + ret = -1; + } +#ifdef SUB_TITLES_HWC + if (destroyG2d(&ctx->g2d) < 0) { + SEC_HWC_Log(HWC_LOG_ERROR, "%s::destroyG2d() fail", __func__); + ret = -1; + } +#endif + for (i = 0; i < NUM_OF_WIN; i++) { + if (window_close(&ctx->win[i]) < 0) + SEC_HWC_Log(HWC_LOG_DEBUG, "%s::window_close() fail", __func__); + } + + free(ctx); + } + return ret; +} + +static int hwc_device_open(const struct hw_module_t* module, const char* name, + struct hw_device_t** device) +{ + int status = 0; + struct hwc_win_info_t *win; + + if (strcmp(name, HWC_HARDWARE_COMPOSER)) + return -EINVAL; + + struct hwc_context_t *dev; + dev = (hwc_context_t*)malloc(sizeof(*dev)); + + /* initialize our state here */ + memset(dev, 0, sizeof(*dev)); + + /* initialize the procs */ + dev->device.common.tag = HARDWARE_DEVICE_TAG; + dev->device.common.version = 0; + dev->device.common.module = const_cast(module); + dev->device.common.close = hwc_device_close; + + dev->device.prepare = hwc_prepare; + dev->device.set = hwc_set; + + *device = &dev->device.common; + + //initializing + memset(&(dev->fimc), 0, sizeof(s5p_fimc_t)); + memset(&(dev->s3c_mem), 0, sizeof(struct s3c_mem_t)); +#ifdef USE_HW_PMEM + memset(&(dev->sec_pmem), 0, sizeof(sec_pmem_t)); +#endif + /* open WIN0 & WIN1 here */ + for (int i = 0; i < NUM_OF_WIN; i++) { + if (window_open(&(dev->win[i]), i) < 0) { + SEC_HWC_Log(HWC_LOG_ERROR, + "%s:: Failed to open window %d device ", __func__, i); + status = -EINVAL; + goto err; + } + } + + if (window_get_global_lcd_info(dev->win[0].fd, &dev->lcd_info) < 0) { + SEC_HWC_Log(HWC_LOG_ERROR, + "%s::window_get_global_lcd_info is failed : %s", + __func__, strerror(errno)); + status = -EINVAL; + goto err; + } + +#if defined(BOARD_USES_HDMI) + lcd_width = dev->lcd_info.xres; + lcd_height = dev->lcd_info.yres; +#endif + + /* initialize the window context */ + for (int i = 0; i < NUM_OF_WIN; i++) { + win = &dev->win[i]; + memcpy(&win->lcd_info, &dev->lcd_info, sizeof(struct fb_var_screeninfo)); + memcpy(&win->var_info, &dev->lcd_info, sizeof(struct fb_var_screeninfo)); + + win->rect_info.x = 0; + win->rect_info.y = 0; + win->rect_info.w = win->var_info.xres; + win->rect_info.h = win->var_info.yres; + + if (window_set_pos(win) < 0) { + SEC_HWC_Log(HWC_LOG_ERROR, "%s::window_set_pos is failed : %s", + __func__, strerror(errno)); + status = -EINVAL; + goto err; + } + + if (window_get_info(win, i) < 0) { + SEC_HWC_Log(HWC_LOG_ERROR, "%s::window_get_info is failed : %s", + __func__, strerror(errno)); + status = -EINVAL; + goto err; + } + + } + +#ifdef USE_HW_PMEM + if (createPmem(&dev->sec_pmem, PMEM_SIZE) < 0) { + SEC_HWC_Log(HWC_LOG_ERROR, "%s::initPmem(%d) fail", __func__, PMEM_SIZE); + } +#endif + + //create PP + if (createVideoDev(&dev->fimc) < 0) { + SEC_HWC_Log(HWC_LOG_ERROR, "%s::creatFimc() fail", __func__); + status = -EINVAL; + goto err; + } + +#ifdef SUB_TITLES_HWC + if (createG2d(&dev->g2d) < 0) { + SEC_HWC_Log(HWC_LOG_ERROR, "%s::createG2d() fail", __func__); + status = -EINVAL; + goto err; + } +#endif + + SEC_HWC_Log(HWC_LOG_DEBUG, "%s:: hwc_device_open: SUCCESS", __func__); + return 0; + +err: + if (destroyVideoDev(&dev->fimc) < 0) + SEC_HWC_Log(HWC_LOG_ERROR, "%s::destroyVideoDev() fail", __func__); +#ifdef SUB_TITLES_HWC + if (destroyG2d(&dev->g2d) < 0) + SEC_HWC_Log(HWC_LOG_ERROR, "%s::destroyG2d() fail", __func__); +#endif + if (destroyMem(&dev->s3c_mem) < 0) + SEC_HWC_Log(HWC_LOG_ERROR, "%s::destroyMem() fail", __func__); + +#ifdef USE_HW_PMEM + if (destroyPmem(&dev->sec_pmem) < 0) + SEC_HWC_Log(HWC_LOG_ERROR, "%s::destroyPmem() fail", __func__); +#endif + + for (int i = 0; i < NUM_OF_WIN; i++) { + if (window_close(&dev->win[i]) < 0) + SEC_HWC_Log(HWC_LOG_DEBUG, "%s::window_close() fail", __func__); + } + + return status; +} diff --git a/exynos5/hal/libhwcomposer/SecHWCLog.cpp b/exynos5/hal/libhwcomposer/SecHWCLog.cpp new file mode 100644 index 0000000..6ad4283 --- /dev/null +++ b/exynos5/hal/libhwcomposer/SecHWCLog.cpp @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * + * @author Rama, Meka(v.meka@samsung.com) + Sangwoo, Park(sw5771.park@samsung.com) + Jamie Oh (jung-min.oh@samsung.com) + * @date 2011-03-11 + * + */ + +#include + +#include "SecHWCUtils.h" + +void _SEC_HWC_Log(HWC_LOG_LEVEL logLevel, const char *tag, const char *msg, ...) +{ + va_list argptr; + + va_start(argptr, msg); + + switch (logLevel) { + case HWC_LOG_DEBUG: + __android_log_vprint(ANDROID_LOG_DEBUG, tag, msg, argptr); + break; + case HWC_LOG_WARNING: + __android_log_vprint(ANDROID_LOG_WARN, tag, msg, argptr); + break; + case HWC_LOG_ERROR: + __android_log_vprint(ANDROID_LOG_ERROR, tag, msg, argptr); + break; + default: + __android_log_vprint(ANDROID_LOG_VERBOSE, tag, msg, argptr); + } + + va_end(argptr); +} diff --git a/exynos5/hal/libhwcomposer/SecHWCUtils.cpp b/exynos5/hal/libhwcomposer/SecHWCUtils.cpp new file mode 100644 index 0000000..9a03ed2 --- /dev/null +++ b/exynos5/hal/libhwcomposer/SecHWCUtils.cpp @@ -0,0 +1,1703 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * + * @author Rama, Meka(v.meka@samsung.com) + Sangwoo, Park(sw5771.park@samsung.com) + Jamie Oh (jung-min.oh@samsung.com) + * @date 2011-03-11 + * + */ + +#include "SecHWCUtils.h" + +#define V4L2_BUF_TYPE_OUTPUT V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE +#define V4L2_BUF_TYPE_CAPTURE V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE +#define EXYNOS4_ALIGN( value, base ) (((value) + ((base) - 1)) & ~((base) - 1)) + +//#define CHECK_FPS +#ifdef CHECK_FPS +#include +#include +#define CHK_FRAME_CNT 30 + +void check_fps() +{ + static struct timeval tick, tick_old; + static int total = 0; + static int cnt = 0; + int FPS; + cnt++; + gettimeofday(&tick, NULL); + if (cnt > 10) { + if (tick.tv_sec > tick_old.tv_sec) + total += ((tick.tv_usec/1000) + (tick.tv_sec - tick_old.tv_sec)*1000 - (tick_old.tv_usec/1000)); + else + total += ((tick.tv_usec - tick_old.tv_usec)/1000); + + memcpy(&tick_old, &tick, sizeof(timeval)); + if (cnt == (10 + CHK_FRAME_CNT)) { + FPS = 1000*CHK_FRAME_CNT/total; + LOGE("[FPS]:%d\n", FPS); + total = 0; + cnt = 10; + } + } else { + memcpy(&tick_old, &tick, sizeof(timeval)); + total = 0; + } +} +#endif + +struct yuv_fmt_list yuv_list[] = { + { "V4L2_PIX_FMT_NV12", "YUV420/2P/LSB_CBCR", V4L2_PIX_FMT_NV12, 12, 2 }, + { "V4L2_PIX_FMT_NV12T", "YUV420/2P/LSB_CBCR", V4L2_PIX_FMT_NV12T, 12, 2 }, + { "V4L2_PIX_FMT_NV21", "YUV420/2P/LSB_CRCB", V4L2_PIX_FMT_NV21, 12, 2 }, + { "V4L2_PIX_FMT_NV21X", "YUV420/2P/MSB_CBCR", V4L2_PIX_FMT_NV21X, 12, 2 }, + { "V4L2_PIX_FMT_NV12X", "YUV420/2P/MSB_CRCB", V4L2_PIX_FMT_NV12X, 12, 2 }, + { "V4L2_PIX_FMT_YUV420", "YUV420/3P", V4L2_PIX_FMT_YUV420, 12, 3 }, + { "V4L2_PIX_FMT_YUV420M", "YUV420/3P", V4L2_PIX_FMT_YUV420M, 12, 3 }, + { "V4L2_PIX_FMT_YVU420M", "YVU420/3P", V4L2_PIX_FMT_YVU420M, 12, 3 }, + { "V4L2_PIX_FMT_NV12M", "YUV420/2P/LSB_CBCR", V4L2_PIX_FMT_NV12M, 12, 2 }, + { "V4L2_PIX_FMT_YUYV", "YUV422/1P/YCBYCR", V4L2_PIX_FMT_YUYV, 16, 1 }, + { "V4L2_PIX_FMT_YVYU", "YUV422/1P/YCRYCB", V4L2_PIX_FMT_YVYU, 16, 1 }, + { "V4L2_PIX_FMT_UYVY", "YUV422/1P/CBYCRY", V4L2_PIX_FMT_UYVY, 16, 1 }, + { "V4L2_PIX_FMT_VYUY", "YUV422/1P/CRYCBY", V4L2_PIX_FMT_VYUY, 16, 1 }, + { "V4L2_PIX_FMT_UV12", "YUV422/2P/LSB_CBCR", V4L2_PIX_FMT_NV16, 16, 2 }, + { "V4L2_PIX_FMT_UV21", "YUV422/2P/LSB_CRCB", V4L2_PIX_FMT_NV61, 16, 2 }, + { "V4L2_PIX_FMT_UV12X", "YUV422/2P/MSB_CBCR", V4L2_PIX_FMT_NV16X, 16, 2 }, + { "V4L2_PIX_FMT_UV21X", "YUV422/2P/MSB_CRCB", V4L2_PIX_FMT_NV61X, 16, 2 }, + { "V4L2_PIX_FMT_YUV422P", "YUV422/3P", V4L2_PIX_FMT_YUV422P, 16, 3 }, +}; + +int window_open(struct hwc_win_info_t *win, int id) +{ + int fd = 0; + char name[64]; + int vsync = 1; + int real_id = id; + + char const * const device_template = "/dev/graphics/fb%u"; + // window & FB maping + // fb0 -> win-id : 2 + // fb1 -> win-id : 1 + // fb2 -> win-id : 0 + // fb3 -> no device node + // fb4 -> no device node + // it is pre assumed that ...win0 or win1 is used here.. + + switch (id) { + case 0: + real_id = 2; + break; + case 1: + real_id = 1; + break; + default: + SEC_HWC_Log(HWC_LOG_ERROR, "%s::id(%d) is weird", __func__, id); + goto error; +} + + snprintf(name, 64, device_template, real_id); + + win->fd = open(name, O_RDWR); + if (win->fd <= 0) { + SEC_HWC_Log(HWC_LOG_ERROR, "%s::Failed to open window device (%s) : %s", + __func__, strerror(errno), name); + goto error; + } + +#ifdef ENABLE_FIMD_VSYNC + vsync = 1; + if (ioctl(win->fd, S3CFB_SET_VSYNC_INT, &vsync) < 0) { + SEC_HWC_Log(HWC_LOG_ERROR, "%s::S3CFB_SET_VSYNC_INT fail", __func__); + goto error; + } +#endif + + return 0; + +error: + if (0 < win->fd) + close(win->fd); + win->fd = 0; + + return -1; +} + +int window_close(struct hwc_win_info_t *win) +{ + int ret = 0; + + if (0 < win->fd) { + ion_unmap((void *)win->addr[0], ALIGN(win->size * NUM_OF_WIN_BUF, PAGE_SIZE)); + ion_free(win->ion_fd); + +#ifdef ENABLE_FIMD_VSYNC + /* Set using VSYNC Interrupt for FIMD_0 */ + int vsync = 0; + if (ioctl(win->fd, S3CFB_SET_VSYNC_INT, &vsync) < 0) + SEC_HWC_Log(HWC_LOG_ERROR, "%s::S3CFB_SET_VSYNC_INT fail", __func__); +#endif + ret = close(win->fd); + } + win->fd = 0; + + return ret; +} + +int window_set_pos(struct hwc_win_info_t *win) +{ + struct s3cfb_user_window window; + + //before changing the screen configuration...powerdown the window + if (window_hide(win) != 0) + return -1; + + SEC_HWC_Log(HWC_LOG_DEBUG, "%s:: x(%d), y(%d)", + __func__, win->rect_info.x, win->rect_info.y); + + win->var_info.xres_virtual = (win->lcd_info.xres + 15) & ~ 15; + win->var_info.yres_virtual = win->lcd_info.yres * NUM_OF_WIN_BUF; + win->var_info.xres = win->rect_info.w; + win->var_info.yres = win->rect_info.h; + win->var_info.activate &= ~FB_ACTIVATE_MASK; + win->var_info.activate |= FB_ACTIVATE_FORCE; + if (ioctl(win->fd, FBIOPUT_VSCREENINFO, &(win->var_info)) < 0) { + SEC_HWC_Log(HWC_LOG_ERROR, "%s::FBIOPUT_VSCREENINFO(%d, %d) fail", + __func__, win->rect_info.w, win->rect_info.h); + return -1; + } + + window.x = win->rect_info.x; + window.y = win->rect_info.y; + if (ioctl(win->fd, S3CFB_WIN_POSITION, &window) < 0) { + SEC_HWC_Log(HWC_LOG_ERROR, "%s::S3CFB_WIN_POSITION(%d, %d) fail", + __func__, window.x, window.y); + return -1; + } + + return 0; +} + +int window_get_info(struct hwc_win_info_t *win, int win_num) +{ + int temp_size = 0; + + if (ioctl(win->fd, FBIOGET_FSCREENINFO, &win->fix_info) < 0) { + SEC_HWC_Log(HWC_LOG_ERROR, "FBIOGET_FSCREENINFO failed : %s", + strerror(errno)); + goto error; + } + + win->size = win->fix_info.line_length * win->var_info.yres; + + struct s3c_fb_user_ion_client ion_handle; + void *ion_start_addr; + if (ioctl(win->fd, S3CFB_GET_ION_USER_HANDLE, &ion_handle) < 0) { + SEC_HWC_Log(HWC_LOG_ERROR, "Get fb ion client is failed\n"); + return -1; + } + + win->ion_fd = ion_handle.fd; + ion_start_addr = ion_map(win->ion_fd, ALIGN(win->size * NUM_OF_WIN_BUF, PAGE_SIZE), 0); + + for (int j = 0; j < NUM_OF_WIN_BUF; j++) { + temp_size = win->size * j; + win->addr[j] = (uint32_t)ion_start_addr + temp_size; + SEC_HWC_Log(HWC_LOG_DEBUG, "%s::win-%d add[%d] %x ", + __func__, win_num, j, win->addr[j]); + } + return 0; + +error: + win->fix_info.smem_start = 0; + + return -1; +} + +int window_pan_display(struct hwc_win_info_t *win) +{ + struct fb_var_screeninfo *lcd_info = &(win->lcd_info); + +#ifdef ENABLE_FIMD_VSYNC + int pan_num = 0; + if (ioctl(win->fd, FBIO_WAITFORVSYNC, &pan_num) < 0) + SEC_HWC_Log(HWC_LOG_ERROR, "%s::FBIO_WAITFORVSYNC fail(%s)", + __func__, strerror(errno)); +#endif + + lcd_info->yoffset = lcd_info->yres * win->buf_index; + + if (ioctl(win->fd, FBIOPAN_DISPLAY, lcd_info) < 0) { + SEC_HWC_Log(HWC_LOG_ERROR, "%s::FBIOPAN_DISPLAY(%d / %d / %d) fail(%s)", + __func__, + lcd_info->yres, + win->buf_index, lcd_info->yres_virtual, + strerror(errno)); + return -1; + } + return 0; +} + +int window_show(struct hwc_win_info_t *win) +{ + if (win->power_state == 0) { + if (ioctl(win->fd, FBIOBLANK, FB_BLANK_UNBLANK) < 0) { + SEC_HWC_Log(HWC_LOG_ERROR, "%s::FBIOBLANK failed : (%d:%s)", + __func__, win->fd, strerror(errno)); + return -1; + } + win->power_state = 1; + } + return 0; +} + +int window_hide(struct hwc_win_info_t *win) +{ + if (win->power_state == 1) { + if (ioctl(win->fd, FBIOBLANK, FB_BLANK_POWERDOWN) < 0) { + SEC_HWC_Log(HWC_LOG_ERROR, "%s::FBIOBLANK failed : (%d:%s)", + __func__, win->fd, strerror(errno)); + return -1; + } + win->power_state = 0; + } + return 0; +} + +int window_get_global_lcd_info(int fd, struct fb_var_screeninfo *lcd_info) +{ + if (ioctl(fd, FBIOGET_VSCREENINFO, lcd_info) < 0) { + SEC_HWC_Log(HWC_LOG_ERROR, "FBIOGET_VSCREENINFO failed : %s", + strerror(errno)); + return -1; + } + + SEC_HWC_Log(HWC_LOG_DEBUG, "%s:: Default LCD x(%d),y(%d)", + __func__, lcd_info->xres, lcd_info->yres); + return 0; +} + +int fimc_v4l2_set_src(int fd, s5p_fimc_img_info *src) +{ + struct v4l2_format fmt; + struct v4l2_cropcap cropcap; + struct v4l2_crop crop; + struct v4l2_requestbuffers req; + + /* You MUST initialize structure for v4l2 */ + memset(&fmt, 0, sizeof(fmt)); + memset(&cropcap, 0, sizeof(cropcap)); + memset(&crop, 0, sizeof(crop)); + memset(&req, 0, sizeof(req)); + + /************** To set size & format for source image (DMA-INPUT) **************/ + fmt.fmt.pix_mp.num_planes = src->planes; + fmt.fmt.pix_mp.width = src->full_width; + fmt.fmt.pix_mp.height = src->full_height; + fmt.fmt.pix_mp.pixelformat = src->color_space; + fmt.fmt.pix_mp.field = V4L2_FIELD_ANY; + fmt.type = V4L2_BUF_TYPE_OUTPUT; + + SEC_HWC_Log(HWC_LOG_DEBUG, + "fimc_v4l2_set_src-VIDIOC_S_FMT, type(%d), field(%d), plane(%d)" + "pixelformat(0x%X), width(%d), height(%d)", + fmt.type, fmt.fmt.pix.field, fmt.fmt.pix_mp.num_planes, + fmt.fmt.pix_mp.pixelformat, fmt.fmt.pix_mp.width, fmt.fmt.pix_mp.height); + + if (ioctl(fd, VIDIOC_S_FMT, &fmt) < 0) { + SEC_HWC_Log(HWC_LOG_ERROR, "%s::VIDIOC_S_FMT failed : errno=%d (%s)" + " : fd=%d\n", __func__, errno, strerror(errno), fd); + return -1; + } + + /************** crop input size **************/ + crop.type = V4L2_BUF_TYPE_OUTPUT; + crop.c.width = src->width; + crop.c.height = src->height; + crop.c.left = src->start_x; + crop.c.top = src->start_y; + + SEC_HWC_Log(HWC_LOG_DEBUG, + "fimc_v4l2_set_src-VIDIOC_S_CROP, type(%d), XY(%d,%d), WH(%d,%d)", + crop.type, crop.c.left, crop.c.top, crop.c.width, crop.c.height); + + if (ioctl(fd, VIDIOC_S_CROP, &crop) < 0) { + SEC_HWC_Log(HWC_LOG_ERROR, "%s::Error in video VIDIOC_S_CROP :" + "crop.c.left : (%d), crop.c.top : (%d), crop.c.width : (%d), crop.c.height : (%d)", + __func__, crop.c.left, crop.c.top, crop.c.width, crop.c.height); + return -1; + } + + /************** input buffer type **************/ + req.count = 1; + req.memory = V4L2_MEMORY_USERPTR; + req.type = V4L2_BUF_TYPE_OUTPUT; + + SEC_HWC_Log(HWC_LOG_DEBUG, + "fimc_v4l2_set_src-VIDIOC_REQBUFS, count(%d), type(%d), memory(%d)", + req.count, req.type, req.memory); + + if (ioctl(fd, VIDIOC_REQBUFS, &req) < 0) { + SEC_HWC_Log(HWC_LOG_ERROR, "%s::Error in VIDIOC_REQBUFS", __func__); + return -1; + } + + return 0; +} + +int fimc_v4l2_set_dst(int fd, s5p_fimc_img_info *dst, + int rotation, int hflip, int vflip, unsigned int addr) +{ + struct v4l2_format sFormat; + struct v4l2_control vc; + struct v4l2_framebuffer fbuf; + struct v4l2_crop crop; + struct v4l2_requestbuffers req; + int ret; + + /* You MUST initialize structure for v4l2 */ + memset(&sFormat, 0, sizeof(sFormat)); + memset(&vc, 0, sizeof(vc)); + memset(&fbuf, 0, sizeof(fbuf)); + memset(&crop, 0, sizeof(crop)); + memset(&req, 0, sizeof(req)); + + /************** set rotation configuration **************/ + vc.id = V4L2_CID_ROTATE; + vc.value = rotation; + + SEC_HWC_Log(HWC_LOG_DEBUG, + "fimc_v4l2_set_dst-V4L2_CID_ROTATE, rot(%d)",vc.value); + + ret = ioctl(fd, VIDIOC_S_CTRL, &vc); + if (ret < 0) { + SEC_HWC_Log(HWC_LOG_ERROR, + "%s::Error in video VIDIOC_S_CTRL - rotation (%d)" + "vc.id : (%d), vc.value : (%d)", __func__, ret, vc.id, vc.value); + return -1; + } + + /************** set hflip configuration **************/ + vc.id = V4L2_CID_HFLIP; + vc.value = hflip; + + SEC_HWC_Log(HWC_LOG_DEBUG, + "fimc_v4l2_set_dst-V4L2_CID_HFLIP, hflip(%d)",vc.value); + + ret = ioctl(fd, VIDIOC_S_CTRL, &vc); + if (ret < 0) { + SEC_HWC_Log(HWC_LOG_ERROR, + "%s::Error in video VIDIOC_S_CTRL - hflip (%d)" + "vc.id : (%d), vc.value : (%d)", __func__, ret, vc.id, vc.value); + return -1; + } + + /************** set vflip configuration **************/ + vc.id = V4L2_CID_VFLIP; + vc.value = vflip; + + SEC_HWC_Log(HWC_LOG_DEBUG, + "fimc_v4l2_set_dst-V4L2_CID_VFLIP, vflip(%d)",vc.value); + + ret = ioctl(fd, VIDIOC_S_CTRL, &vc); + if (ret < 0) { + SEC_HWC_Log(HWC_LOG_ERROR, + "%s::Error in video VIDIOC_S_CTRL - vflip (%d)" + "vc.id : (%d), vc.value : (%d)", __func__, ret, vc.id, vc.value); + return -1; + } + + /************** set destination **************/ + sFormat.type = V4L2_BUF_TYPE_CAPTURE; + sFormat.fmt.pix_mp.width = dst->full_width; + sFormat.fmt.pix_mp.height = dst->full_height; + sFormat.fmt.pix_mp.pixelformat = dst->color_space; + sFormat.fmt.pix_mp.num_planes = dst->planes; + sFormat.fmt.pix.field = V4L2_FIELD_ANY; + + SEC_HWC_Log(HWC_LOG_DEBUG, + "fimc_v4l2_set_dst-VIDIOC_S_FMT, type(%d), field(%d), plane(%d)" + "pixelformat(0x%X), width(%d), height(%d)", + sFormat.type, sFormat.fmt.pix.field, sFormat.fmt.pix_mp.num_planes, + sFormat.fmt.pix_mp.pixelformat, sFormat.fmt.pix_mp.width, sFormat.fmt.pix_mp.height); + + ret = ioctl(fd, VIDIOC_S_FMT, &sFormat); + if (ret < 0) { + SEC_HWC_Log(HWC_LOG_ERROR, "%s::Error in video VIDIOC_S_FMT (%d)", __func__, ret); + return -1; + } + + /************** set destination window**************/ + crop.type = V4L2_BUF_TYPE_CAPTURE; + crop.c.left = dst->start_x; + crop.c.top = dst->start_y; + crop.c.width = dst->width; + crop.c.height = dst->height; + + SEC_HWC_Log(HWC_LOG_DEBUG, + "fimc_v4l2_set_dst-VIDIOC_S_CROP, type(%d), XY(%d,%d), WH(%d,%d)", + crop.type, crop.c.left, crop.c.top, crop.c.width, crop.c.height); + + ret = ioctl(fd, VIDIOC_S_CROP, &crop); + if (ret < 0) { + SEC_HWC_Log(HWC_LOG_ERROR, "%s::Error in video VIDIOC_S_CROP (%d)", __func__, ret); + return -1; + } + + /************** input buffer type **************/ + req.count = 1; + req.type = V4L2_BUF_TYPE_CAPTURE; + req.memory = V4L2_MEMORY_USERPTR; + + SEC_HWC_Log(HWC_LOG_DEBUG, + "fimc_v4l2_set_dst-VIDIOC_REQBUFS, count(%d), type(%d), memory(%d)", + req.count, req.type, req.memory); + + ret = ioctl (fd, VIDIOC_REQBUFS, &req); + if (ret < 0) { + SEC_HWC_Log(HWC_LOG_ERROR, "%s::Error in VIDIOC_REQBUFS (%d)", __func__, ret); + return -1; + } + + return 0; +} + +int fimc_v4l2_stream_on(int fd, enum v4l2_buf_type type) +{ + SEC_HWC_Log(HWC_LOG_DEBUG,"fimc_v4l2_stream_on-VIDIOC_STREAMON, type(%d)",type); + + if (-1 == ioctl(fd, VIDIOC_STREAMON, &type)) { + SEC_HWC_Log(HWC_LOG_ERROR, "Error in VIDIOC_STREAMON\n"); + return -1; + } + + return 0; +} + +int fimc_v4l2_queue(int fd, struct fimc_buf *fimc_buf, enum v4l2_buf_type type, int index) +{ + struct v4l2_plane plane[3]; + struct v4l2_buffer buf; + int i; + int ret; + + buf.length = fimc_buf->planes; + buf.memory = V4L2_MEMORY_USERPTR; + buf.index = index; + buf.type = type; + + if (buf.type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE || + buf.type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { + for (i = 0; i < buf.length; i++) { + plane[i].m.userptr = fimc_buf->base[i]; + plane[i].length = fimc_buf->size[i]; + } + } + buf.m.planes = plane; + + SEC_HWC_Log(HWC_LOG_DEBUG,"fimc_v4l2_queue-VIDIOC_QBUF, type(%d)," + "length(%d), memory(%d), index(%d)", + buf.type, buf.length, buf.memory, buf.index); + + ret = ioctl(fd, VIDIOC_QBUF, &buf); + if (0 > ret) { + SEC_HWC_Log(HWC_LOG_ERROR, "Error in VIDIOC_QBUF : (%d)", ret); + return -1; + } + + return 0; +} + +int fimc_v4l2_dequeue(int fd, struct fimc_buf *fimc_buf, enum v4l2_buf_type type) +{ + struct v4l2_buffer buf; + struct v4l2_plane plane[3]; + + buf.m.planes = plane; + buf.length = fimc_buf->planes; + buf.memory = V4L2_MEMORY_USERPTR; + buf.type = type; + + if (-1 == ioctl(fd, VIDIOC_DQBUF, &buf)) { + SEC_HWC_Log(HWC_LOG_ERROR, "Error in VIDIOC_DQBUF\n"); + return -1; + } + + return buf.index; +} + +int fimc_v4l2_stream_off(int fd, enum v4l2_buf_type type) +{ + SEC_HWC_Log(HWC_LOG_DEBUG,"fimc_v4l2_stream_off-VIDIOC_STREAMOFF, type(%d),",type); + + if (-1 == ioctl(fd, VIDIOC_STREAMOFF, &type)) { + SEC_HWC_Log(HWC_LOG_ERROR, "Error in VIDIOC_STREAMOFF\n"); + return -1; + } + + return 0; +} + +int fimc_v4l2_clr_buf(int fd, enum v4l2_buf_type type) +{ + struct v4l2_requestbuffers req; + + req.count = 0; + req.memory = V4L2_MEMORY_USERPTR; + req.type = type; + + SEC_HWC_Log(HWC_LOG_DEBUG,"fimc_v4l2_clr_buf-VIDIOC_REQBUFS," + "count(%d), memory(%d), type(%d)", + req.count, req.memory, req.type); + + if (ioctl(fd, VIDIOC_REQBUFS, &req) == -1) { + SEC_HWC_Log(HWC_LOG_ERROR, "Error in VIDIOC_REQBUFS"); + } + + return 0; +} + +int fimc_v4l2_S_ctrl(int fd) +{ + struct v4l2_control vc; + + vc.id = V4L2_CID_CACHEABLE; + vc.value = 1; + + SEC_HWC_Log(HWC_LOG_DEBUG,"fimc_v4l2_S_ctrl-VIDIOC_S_CTRL," + "id(%d), value(%d)",vc.id , vc.value); + + if (ioctl(fd, VIDIOC_S_CTRL, &vc) < 0) { + SEC_HWC_Log(HWC_LOG_ERROR, "Error in VIDIOC_S_CTRL"); + return -1; + } + + return 0; +} + +int fimc_handle_oneshot(int fd, struct fimc_buf *fimc_src_buf, struct fimc_buf *fimc_dst_buf) +{ +#ifdef CHECK_FPS + check_fps(); +#endif + + if (fimc_v4l2_queue(fd, fimc_src_buf, V4L2_BUF_TYPE_OUTPUT, 0) < 0) { + SEC_HWC_Log(HWC_LOG_ERROR, "Fail : SRC v4l2_queue()"); + return -1; + } + + if (fimc_v4l2_queue(fd, fimc_dst_buf, V4L2_BUF_TYPE_CAPTURE, 0) < 0) { + SEC_HWC_Log(HWC_LOG_ERROR, "Fail : DST v4l2_queue()"); + return -2; + } + + if (fimc_v4l2_stream_on(fd, V4L2_BUF_TYPE_OUTPUT) < 0) { + SEC_HWC_Log(HWC_LOG_ERROR, "Fail : SRC v4l2_stream_on()"); + return -3; + } + + if (fimc_v4l2_stream_on(fd, V4L2_BUF_TYPE_CAPTURE) < 0) { + SEC_HWC_Log(HWC_LOG_ERROR, "Fail : DST v4l2_stream_on()"); + return -4; + } + + if (fimc_v4l2_dequeue(fd, fimc_src_buf, V4L2_BUF_TYPE_OUTPUT) < 0) { + SEC_HWC_Log(HWC_LOG_ERROR, "Fail : SRC v4l2_dequeue()"); + return -6; + } + + if (fimc_v4l2_dequeue(fd, fimc_dst_buf, V4L2_BUF_TYPE_CAPTURE) < 0) { + SEC_HWC_Log(HWC_LOG_ERROR, "Fail : DST v4l2_dequeue()"); + return -7; + } + +STREAM_OFF: + if (fimc_v4l2_stream_off(fd, V4L2_BUF_TYPE_OUTPUT) < 0) { + SEC_HWC_Log(HWC_LOG_ERROR, "Fail : SRC v4l2_stream_off()"); + return -8; + } + + if (fimc_v4l2_stream_off(fd, V4L2_BUF_TYPE_CAPTURE) < 0) { + SEC_HWC_Log(HWC_LOG_ERROR, "Fail : DST v4l2_stream_off()"); + return -9; + } + + if (fimc_v4l2_clr_buf(fd, V4L2_BUF_TYPE_OUTPUT) < 0) { + SEC_HWC_Log(HWC_LOG_ERROR, "Fail : SRC v4l2_clr_buf()"); + return -10; + } + + if (fimc_v4l2_clr_buf(fd, V4L2_BUF_TYPE_CAPTURE)< 0) { + SEC_HWC_Log(HWC_LOG_ERROR, "Fail : DST v4l2_clr_buf()"); + return -11; + } + + return 0; +} + +static int memcpy_rect(void *dst, void *src, int fullW, int fullH, int realW, int realH, int format) +{ + unsigned char *srcCb, *srcCr; + unsigned char *dstCb, *dstCr; + unsigned char *srcY, *dstY; + int srcCbOffset, srcCrOffset; + int dstCbOffset, dstFrameOffset, dstCrOffset; + int cbFullW, cbRealW, cbFullH, cbRealH; + int ySrcFW, ySrcFH, ySrcRW, ySrcRH; + int planes; + int i; + + SEC_HWC_Log(HWC_LOG_DEBUG, + "++memcpy_rect()::" + "dst(0x%x),src(0x%x),f.w(%d),f.h(%d),r.w(%d),r.h(%d),format(0x%x)", + (unsigned int)dst, (unsigned int)src, fullW, fullH, realW, realH, format); + +// Set dst Y, Cb, Cr address for FIMC + { + cbFullW = fullW >> 1; + cbRealW = realW >> 1; + cbFullH = fullH >> 1; + cbRealH = realH >> 1; + dstFrameOffset = fullW * fullH; + dstCrOffset = cbFullW * cbFullH; + dstY = (unsigned char *)dst; + dstCb = (unsigned char *)dst + dstFrameOffset; + dstCr = (unsigned char *)dstCb + dstCrOffset; + } + +// Get src Y, Cb, Cr address for source buffer. +// Each address is aligned by 16's multiple for GPU both width and height. + { + ySrcFW = fullW; + ySrcFH = fullH; + ySrcRW = realW; + ySrcRH = realH; + srcCbOffset = EXYNOS4_ALIGN(ySrcRW,16)* EXYNOS4_ALIGN(ySrcRH,16); + srcCrOffset = EXYNOS4_ALIGN(cbRealW,16)* EXYNOS4_ALIGN(cbRealH,16); + srcY = (unsigned char *)src; + srcCb = (unsigned char *)src + srcCbOffset; + srcCr = (unsigned char *)srcCb + srcCrOffset; + } + SEC_HWC_Log(HWC_LOG_DEBUG, + "--memcpy_rect()::\n" + "dstY(0x%x),dstCb(0x%x),dstCr(0x%x) \n" + "srcY(0x%x),srcCb(0x%x),srcCr(0x%x) \n" + "cbRealW(%d),cbRealH(%d)", + (unsigned int)dstY,(unsigned int)dstCb,(unsigned int)dstCr, + (unsigned int)srcY,(unsigned int)srcCb,(unsigned int)srcCr, + cbRealW, cbRealH); + + if (format == HAL_PIXEL_FORMAT_YV12) { //YV12(Y,Cr,Cv) + planes = 3; +//This is code for VE, deleted temporory by SSONG 2011.09.22 +// This will be enabled later. +/* + //as defined in hardware.h, cb & cr full_width should be aligned to 16. ALIGN(y_stride/2, 16). + ////Alignment is hard coded to 16. + ////for example...check frameworks/media/libvideoeditor/lvpp/VideoEditorTools.cpp file for UV stride cal + cbSrcFW = (cbSrcFW + 15) & (~15); + srcCbOffset = ySrcFW * fullH; + srcCrOffset = srcCbOffset + ((cbSrcFW * fullH) >> 1); + srcY = (unsigned char *)src; + srcCb = (unsigned char *)src + srcCbOffset; + srcCr = (unsigned char *)src + srcCrOffset; +*/ + } else if ((format == HAL_PIXEL_FORMAT_YCbCr_420_P) || + (format == HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_P_SBS_LR) || + (format == HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_P_SBS_RL) || + (format == HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_P_TB_LR) || + (format == HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_P_TB_RL)) { + planes = 3; + } else if (format == HAL_PIXEL_FORMAT_YCbCr_420_SP || format == HAL_PIXEL_FORMAT_YCrCb_420_SP) { + planes = 2; + } else { + SEC_HWC_Log(HWC_LOG_ERROR, "use default memcpy instead of memcpy_rect"); + return -1; + } +//#define CHECK_PERF +#ifdef CHECK_PERF + struct timeval start, end; + gettimeofday(&start, NULL); +#endif + for (i = 0; i < realH; i++) + memcpy(dstY + fullW * i, srcY + ySrcFW * i, ySrcRW); + if (planes == 2) { + for (i = 0; i < cbRealH; i++) + memcpy(dstCb + ySrcFW * i, srcCb + ySrcFW * i, ySrcRW); + } else if (planes == 3) { + for (i = 0; i < cbRealH; i++) + memcpy(dstCb + cbFullW * i, srcCb + cbFullW * i, cbRealW); + for (i = 0; i < cbRealH; i++) + memcpy(dstCr + cbFullW * i, srcCr + cbFullW * i, cbRealW); + } +#ifdef CHECK_PERF + gettimeofday(&end, NULL); + SEC_HWC_Log(HWC_LOG_ERROR, "[COPY]=%d,",(end.tv_sec - start.tv_sec)*1000+(end.tv_usec - start.tv_usec)/1000); +#endif + + return 0; +} + +/*****************************************************************************/ +static int get_src_phys_addr(struct hwc_context_t *ctx, + sec_img *src_img, sec_rect *src_rect) +{ + s5p_fimc_t *fimc = &ctx->fimc; + struct s3c_mem_alloc *ptr_mem_alloc = &ctx->s3c_mem.mem_alloc[0]; + struct s3c_mem_dma_param s3c_mem_dma; + + unsigned int src_virt_addr = 0; + unsigned int src_phys_addr = 0; + unsigned int src_frame_size = 0; + + // error check routine + if (0 == src_img->base) { + SEC_HWC_Log(HWC_LOG_ERROR, "%s invalid src image base\n", __func__); + return 0; + } + + fimc->params.src.buf_addr_phy_rgb_y = src_img->base; + fimc->params.src.buf_addr_phy_cb = src_img->base + src_img->uoffset; + fimc->params.src.buf_addr_phy_cr = src_img->base + src_img->uoffset + src_img->voffset; + src_phys_addr = fimc->params.src.buf_addr_phy_rgb_y; + + return src_phys_addr; +} + +static int get_dst_phys_addr(struct hwc_context_t *ctx, sec_img *dst_img, + sec_rect *dst_rect, int *dst_memcpy_flag) +{ + unsigned int dst_phys_addr = 0; + + dst_phys_addr = dst_img->base; + + return dst_phys_addr; +} + +static inline int rotateValueHAL2PP(unsigned char transform) +{ + int rotate_flag = transform & 0x7; + + switch (rotate_flag) { + case HAL_TRANSFORM_ROT_90: return 90; + case HAL_TRANSFORM_ROT_180: return 180; + case HAL_TRANSFORM_ROT_270: return 270; + case HAL_TRANSFORM_FLIP_H | HAL_TRANSFORM_ROT_90: return 90; + case HAL_TRANSFORM_FLIP_V | HAL_TRANSFORM_ROT_90: return 90; + case HAL_TRANSFORM_FLIP_H: return 0; + case HAL_TRANSFORM_FLIP_V: return 0; + } + return 0; +} + +static inline int hflipValueHAL2PP(unsigned char transform) +{ + int flip_flag = transform & 0x7; + switch (flip_flag) { + case HAL_TRANSFORM_FLIP_H: + case HAL_TRANSFORM_FLIP_H | HAL_TRANSFORM_ROT_90: + return 1; + case HAL_TRANSFORM_FLIP_V | HAL_TRANSFORM_ROT_90: + case HAL_TRANSFORM_ROT_90: + case HAL_TRANSFORM_ROT_180: + case HAL_TRANSFORM_ROT_270: + case HAL_TRANSFORM_FLIP_V: + break; + } + return 0; +} + +static inline int vflipValueHAL2PP(unsigned char transform) +{ + int flip_flag = transform & 0x7; + switch (flip_flag) { + case HAL_TRANSFORM_FLIP_V: + case HAL_TRANSFORM_FLIP_V | HAL_TRANSFORM_ROT_90: + return 1; + case HAL_TRANSFORM_FLIP_H | HAL_TRANSFORM_ROT_90: + case HAL_TRANSFORM_ROT_90: + case HAL_TRANSFORM_ROT_180: + case HAL_TRANSFORM_ROT_270: + case HAL_TRANSFORM_FLIP_H: + break; + } + return 0; +} + +static inline int multipleOf2(int number) +{ + if (number % 2 == 1) + return (number - 1); + else + return number; +} + +static inline int multipleOf4(int number) +{ + int remain_number = number % 4; + + if (remain_number != 0) + return (number - remain_number); + else + return number; +} + +static inline int multipleOf8(int number) +{ + int remain_number = number % 8; + + if (remain_number != 0) + return (number - remain_number); + else + return number; +} + +static inline int multipleOf16(int number) +{ + int remain_number = number % 16; + + if (remain_number != 0) + return (number - remain_number); + else + return number; +} + +static inline int widthOfPP( int pp_color_format, int number) +{ + switch (pp_color_format) { + /* 422 1/2/3 plane */ + case V4L2_PIX_FMT_YUYV: + case V4L2_PIX_FMT_UYVY: + case V4L2_PIX_FMT_NV61: + case V4L2_PIX_FMT_NV16: + case V4L2_PIX_FMT_YUV422P: + + /* 420 2/3 plane */ + case V4L2_PIX_FMT_NV21: + case V4L2_PIX_FMT_NV12: + case V4L2_PIX_FMT_NV12T: + case V4L2_PIX_FMT_YUV420: + return multipleOf2(number); + + default : + return number; + } + +} + +static inline int heightOfPP(int pp_color_format, int number) +{ + switch (pp_color_format) { + case V4L2_PIX_FMT_NV21: + case V4L2_PIX_FMT_NV12: + case V4L2_PIX_FMT_NV12T: + case V4L2_PIX_FMT_YUV420: + return multipleOf2(number); + + default : + return number; + break; + } + return number; +} + +static unsigned int get_yuv_bpp(unsigned int fmt) +{ + int i, sel = -1; + + for (i = 0; i < (int)(sizeof(yuv_list) / sizeof(struct yuv_fmt_list)); i++) { + if (yuv_list[i].fmt == fmt) { + sel = i; + break; + } + } + + if (sel == -1) + return sel; + else + return yuv_list[sel].bpp; +} + +static unsigned int get_yuv_planes(unsigned int fmt) +{ + int i, sel = -1; + + for (i = 0; i < (int)(sizeof(yuv_list) / sizeof(struct yuv_fmt_list)); i++) { + if (yuv_list[i].fmt == fmt) { + sel = i; + break; + } + } + + if (sel == -1) + return sel; + else + return yuv_list[sel].planes; +} + +static int runFimcCore(struct hwc_context_t *ctx, + unsigned int src_phys_addr, sec_img *src_img, sec_rect *src_rect, + uint32_t src_color_space, + unsigned int dst_phys_addr, sec_img *dst_img, sec_rect *dst_rect, + uint32_t dst_color_space, int transform) +{ + s5p_fimc_t * fimc = &ctx->fimc; + s5p_fimc_params_t * params = &(fimc->params); + + struct fimc_buf fimc_src_buf; + int src_bpp, src_planes; + + struct fimc_buf fimc_dst_buf; + int dst_bpp, dst_planes; + unsigned int src_frame_size = 0; + unsigned int dst_frame_size = 0; + unsigned int frame_size = 0; + + bool src_cbcr_order = true; + int rotate_value = rotateValueHAL2PP(transform); + int hflip = hflipValueHAL2PP(transform); + int vflip = vflipValueHAL2PP(transform); + + /* 1. param(fimc config)->src information + * - src_img,src_rect => s_fw,s_fh,s_w,s_h,s_x,s_y + */ + params->src.full_width = src_img->f_w; + params->src.full_height = src_img->f_h; + params->src.width = src_rect->w; + params->src.height = src_rect->h; + params->src.start_x = src_rect->x; + params->src.start_y = src_rect->y; + params->src.color_space = src_color_space; + params->src.buf_addr_phy_rgb_y = src_phys_addr; + + params->dst.buf_addr_phy_rgb_y = dst_phys_addr; + + /* check src minimum */ + if (src_rect->w < 64 || src_rect->h < 32) { + SEC_HWC_Log(HWC_LOG_ERROR, + "%s src size is not supported by fimc : f_w=%d f_h=%d " + "x=%d y=%d w=%d h=%d (ow=%d oh=%d) format=0x%x", __func__, + params->src.full_width, params->src.full_height, + params->src.start_x, params->src.start_y, + params->src.width, params->src.height, + src_rect->w, src_rect->h, + params->src.color_space); + return -1; + } + + params->dst.full_width = dst_img->f_w; + params->dst.full_height = dst_img->f_h; + params->dst.start_x = dst_rect->x; + params->dst.start_y = dst_rect->y; + params->dst.width = widthOfPP(dst_color_space, dst_rect->w); + params->dst.height = heightOfPP(dst_color_space, dst_rect->h); + params->dst.color_space = dst_color_space; + + SEC_HWC_Log(HWC_LOG_DEBUG, + "runFimcCore()::" + "SRC f.w(%d),f.h(%d),x(%d),y(%d),w(%d),h(%d)=>" + "DST f.w(%d),f.h(%d),x(%d),y(%d),w(%d),h(%d)", + params->src.full_width, params->src.full_height, + params->src.start_x, params->src.start_y, + params->src.width, params->src.height, + params->dst.full_width, params->dst.full_height, + params->dst.start_x, params->dst.start_y, + params->dst.width, params->dst.height); + + /* check dst minimum */ +#if (GSC_VERSION == GSC_EVT0) + if (dst_rect->w < 64 || dst_rect->h < 32) { +#else + if (dst_rect->w < 32 || dst_rect->h < 8) { +#endif + + SEC_HWC_Log(HWC_LOG_ERROR, + "%s dst size is not supported by fimc : f_w=%d f_h=%d " + "x=%d y=%d w=%d h=%d (ow=%d oh=%d) format=0x%x", __func__, + params->dst.full_width, params->dst.full_height, + params->dst.start_x, params->dst.start_y, + params->dst.width, params->dst.height, + dst_rect->w, dst_rect->h, params->dst.color_space); + return -1; + } + + /* 2. Set configuration related to destination (DMA-OUT) + * - set input format & size + * - crop input size + * - set input buffer + * - set buffer type (V4L2_MEMORY_USERPTR) + */ + switch (dst_img->format) { + case HAL_PIXEL_FORMAT_RGBA_8888: + case HAL_PIXEL_FORMAT_RGBX_8888: + case HAL_PIXEL_FORMAT_RGB_888: + case HAL_PIXEL_FORMAT_BGRA_8888: + dst_planes = 1; + dst_bpp = 32; + break; + + case HAL_PIXEL_FORMAT_RGB_565: + case HAL_PIXEL_FORMAT_RGBA_5551: + case HAL_PIXEL_FORMAT_RGBA_4444: + dst_planes = 1; + dst_bpp = 16; + break; + } + + dst_frame_size = params->dst.width * params->dst.height ; + params->dst.planes = dst_planes; + + if (dst_planes == 1) { + fimc_dst_buf.base[0] = params->dst.buf_addr_phy_rgb_y; + if (dst_bpp == 32) + fimc_dst_buf.size[0] = dst_frame_size * 4; + else if (dst_bpp == 16) + fimc_dst_buf.size[0] = dst_frame_size * 2; + } + + if (fimc_v4l2_set_dst(fimc->dev_fd, ¶ms->dst, rotate_value, hflip, vflip, dst_phys_addr) < 0) { + SEC_HWC_Log(HWC_LOG_ERROR, "fimc_v4l2_set_dst is failed\n"); + return -1; + } + + /* 3. Set input dma address (Y/RGB, Cb, Cr) + * set source frame size + */ + src_frame_size = params->src.full_width * params->src.full_height; + fimc_src_buf.size[0] = src_frame_size; + fimc_src_buf.size[1] = src_frame_size >> 2; + fimc_src_buf.size[2] = src_frame_size >> 2; + + SEC_HWC_Log(HWC_LOG_DEBUG, + "runFimcCore - Y_length=%d, U_length=%d, V_length=%d\n", + fimc_src_buf.size[0], fimc_src_buf.size[1],fimc_src_buf.size[2]); + + /* set source Y image */ + fimc_src_buf.base[0] = params->src.buf_addr_phy_rgb_y; + /* set source Cb,Cr images for 2 or 3 planes */ + src_bpp = get_yuv_bpp(src_color_space); + src_planes = get_yuv_planes(src_color_space); + if (2 == src_planes) { /* 2 planes */ + frame_size = params->src.full_width * params->src.full_height; + params->src.buf_addr_phy_cb = + params->src.buf_addr_phy_rgb_y + frame_size; + /* CbCr */ + fimc_src_buf.base[1] = params->src.buf_addr_phy_cb; + } else if (3 == src_planes) { /* 3 planes */ + frame_size = params->src.full_width * params->src.full_height; + params->src.buf_addr_phy_cb = + params->src.buf_addr_phy_rgb_y + frame_size; + if (12 == src_bpp) + params->src.buf_addr_phy_cr = + params->src.buf_addr_phy_cb + (frame_size >> 2); + else + params->src.buf_addr_phy_cr = + params->src.buf_addr_phy_cb + (frame_size >> 1); + /* Cb, Cr */ + if (src_cbcr_order == true) { + fimc_src_buf.base[1] = params->src.buf_addr_phy_cb; + fimc_src_buf.base[2] = params->src.buf_addr_phy_cr; + } + else { + fimc_src_buf.base[2] = params->src.buf_addr_phy_cb; + fimc_src_buf.base[1] = params->src.buf_addr_phy_cr; + } + } + + SEC_HWC_Log(HWC_LOG_DEBUG, + "runFimcCore - Y=0x%X, U=0x%X, V=0x%X\n", + fimc_src_buf.base[0], fimc_src_buf.base[1],fimc_src_buf.base[2]); + + int ret = 0; + params->src.planes = src_planes; + + /* 4. Set configuration related to source (DMA-INPUT) + * - set input format & size + * - crop input size + * - set input buffer + * - set buffer type (V4L2_MEMORY_USERPTR) + */ + if (fimc_v4l2_set_src(fimc->dev_fd, ¶ms->src) < 0) { + SEC_HWC_Log(HWC_LOG_ERROR, "fimc_v4l2_set_src is failed\n"); + return -1; + } + + fimc_src_buf.planes = src_planes; + fimc_dst_buf.planes = dst_planes; + + /* 5. Run FIMC + * - stream on => queue => dequeue => stream off => clear buf + */ + ret = fimc_handle_oneshot(fimc->dev_fd, &fimc_src_buf, &fimc_dst_buf); + + if (ret < 0) { + SEC_HWC_Log(HWC_LOG_ERROR,"fimc_handle_oneshot = %d\n",ret); + if (ret == -2) { + fimc_v4l2_clr_buf(fimc->dev_fd, V4L2_BUF_TYPE_OUTPUT); + } else if (ret == -3) { + fimc_v4l2_clr_buf(fimc->dev_fd, V4L2_BUF_TYPE_OUTPUT); + fimc_v4l2_clr_buf(fimc->dev_fd, V4L2_BUF_TYPE_CAPTURE); + } + return ret; + } + + return 0; +} + +#ifdef SUB_TITLES_HWC +int createG2d(sec_g2d_t *g2d) +{ + g2d->dev_fd = open(SEC_G2D_DEV_NAME, O_RDWR); + + if (g2d->dev_fd <= 0) { + SEC_HWC_Log(HWC_LOG_ERROR, "%s::G2d open error (%d)", __func__, errno); + goto err; + } + + return 0; +err: + if (0 < g2d->dev_fd) + close(g2d->dev_fd); + g2d->dev_fd =0; + + return -1; +} + +int destroyG2d(sec_g2d_t *g2d) +{ + // close + if (0 < g2d->dev_fd) + close(g2d->dev_fd); + g2d->dev_fd = 0; + + return 0; +} +#endif + +int createVideoDev(s5p_fimc_t *fimc) +{ + struct v4l2_capability cap; + struct v4l2_format fmt; + struct v4l2_control vc; + + // open device file + if (fimc->dev_fd <= 0) + fimc->dev_fd = open(PP_DEVICE_DEV_NAME, O_RDWR); + + if (fimc->dev_fd <= 0) { + SEC_HWC_Log(HWC_LOG_ERROR, "%s::Post processor open error (%d)", + __func__, errno); + goto err; + } + + /* Initial debug log level for video driver. + User can use command below to change log level. + # echo 7 > /sys/module/gsc/parameters/gsc_dbg + # echo 8 > /proc/sys/kernel/printk + Each number for gsc_dgb means, + 3: error + 4: waring + 6: info + 7: debug + */ + system("echo 3 > /sys/module/gsc/parameters/gsc_dbg"); + + // check capability + if (ioctl(fimc->dev_fd, VIDIOC_QUERYCAP, &cap) < 0) { + SEC_HWC_Log(HWC_LOG_ERROR, "VIDIOC_QUERYCAP failed"); + goto err; + } + + if (!(cap.capabilities & V4L2_CAP_STREAMING)) { + SEC_HWC_Log(HWC_LOG_ERROR, "%d has no streaming support", fimc->dev_fd); + goto err; + } + + if (!(cap.capabilities & V4L2_CAP_VIDEO_OUTPUT)) { + SEC_HWC_Log(HWC_LOG_ERROR, "%d is no video output", fimc->dev_fd); + goto err; + } + + /* + * malloc fimc_outinfo structure + */ + fmt.type = V4L2_BUF_TYPE_OUTPUT; + if (ioctl(fimc->dev_fd, VIDIOC_G_FMT, &fmt) < 0) { + SEC_HWC_Log(HWC_LOG_ERROR, "%s::Error in video VIDIOC_G_FMT", __func__); + goto err; + } + + return 0; + +err: + if (0 < fimc->dev_fd) + close(fimc->dev_fd); + fimc->dev_fd =0; + + return -1; +} + +int destroyVideoDev(s5p_fimc_t *fimc) +{ + if (fimc->out_buf.virt_addr != NULL) { + fimc->out_buf.virt_addr = NULL; + fimc->out_buf.length = 0; + } + + // close + if (0 < fimc->dev_fd) + close(fimc->dev_fd); + fimc->dev_fd = 0; + + return 0; +} + +int runFimc(struct hwc_context_t *ctx, + struct sec_img *src_img, struct sec_rect *src_rect, + struct sec_img *dst_img, struct sec_rect *dst_rect, + uint32_t transform) +{ + s5p_fimc_t * fimc = &ctx->fimc; + + unsigned int src_phys_addr = 0; + unsigned int dst_phys_addr = 0; + int rotate_value = 0; + int flag_force_memcpy = 0; + int32_t src_color_space; + int32_t dst_color_space; + + /* 1. source address and size */ + src_phys_addr = get_src_phys_addr(ctx, src_img, src_rect); + if (0 == src_phys_addr) + return -1; + + /* 2. destination address and size */ + dst_phys_addr = get_dst_phys_addr(ctx, dst_img, dst_rect, &flag_force_memcpy); + if (0 == dst_phys_addr) + return -2; + + /* 3. check whether fimc supports the src format */ + src_color_space = HAL_PIXEL_FORMAT_2_V4L2_PIX(src_img->format); + if (0 > src_color_space) + return -3; + dst_color_space = HAL_PIXEL_FORMAT_2_V4L2_PIX(dst_img->format); + if (0 > dst_color_space) + return -4; + + /* 4. FIMC: src_rect of src_img => dst_rect of dst_img */ + if (runFimcCore(ctx, src_phys_addr, src_img, src_rect, + (uint32_t)src_color_space, dst_phys_addr, dst_img, dst_rect, + (uint32_t)dst_color_space, transform) < 0) + return -5; + + return 0; +} + +#ifdef SUB_TITLES_HWC +static int get_g2d_src_phys_addr(struct hwc_context_t *ctx, g2d_rect *src_rect) +{ + sec_g2d_t *g2d = &ctx->g2d; + struct s3c_mem_alloc *ptr_mem_alloc = &ctx->s3c_mem.mem_alloc[0]; +#ifdef USE_HW_PMEM + sec_pmem_alloc_t *pm_alloc = &ctx->sec_pmem.sec_pmem_alloc[0]; +#endif + + unsigned int src_virt_addr = 0; + unsigned int src_phys_addr = 0; + unsigned int src_frame_size = 0; + + struct pmem_region region; + + // error check routine + if (0 == src_rect->virt_addr) { + SEC_HWC_Log(HWC_LOG_ERROR, "%s invalid src address\n", __func__); + return 0; + } + + src_frame_size = FRAME_SIZE(src_rect->color_format, + src_rect->full_w, src_rect->full_h); + if (src_frame_size == 0) { + SEC_HWC_Log(HWC_LOG_ERROR, "%s::FRAME_SIZE fail", __func__); + return 0; + } + +#ifdef USE_HW_PMEM + if (0 <= checkPmem(&ctx->sec_pmem, 0, src_frame_size)) { + src_virt_addr = pm_alloc->virt_addr; + src_phys_addr = pm_alloc->phys_addr; + pm_alloc->size = src_frame_size; + } else +#endif + if (0 <= checkMem(&ctx->s3c_mem, 0, src_frame_size)) { + src_virt_addr = ptr_mem_alloc->vir_addr; + src_phys_addr = ptr_mem_alloc->phy_addr; + ptr_mem_alloc->size = src_frame_size; + } else { + SEC_HWC_Log(HWC_LOG_ERROR, "%s::check_mem fail", __func__); + return 0; + } + memcpy((void *)src_virt_addr, (void*)((unsigned int)src_rect->virt_addr), src_frame_size); + + return src_phys_addr; +} + +int get_HAL_2_G2D_FORMAT(int format) +{ + switch (format) { + case HAL_PIXEL_FORMAT_RGBA_8888: return G2D_ABGR_8888; + case HAL_PIXEL_FORMAT_RGBX_8888: return G2D_XBGR_8888; + case HAL_PIXEL_FORMAT_BGRA_8888: return G2D_ARGB_8888; + case HAL_PIXEL_FORMAT_RGB_888: return G2D_PACKED_BGR_888; + case HAL_PIXEL_FORMAT_RGB_565: return G2D_RGB_565; + case HAL_PIXEL_FORMAT_RGBA_5551: return G2D_RGBA_5551; + case HAL_PIXEL_FORMAT_RGBA_4444: return G2D_RGBA_4444; + default: + return -1; + } +} + +static inline int rotateValueHAL2G2D(unsigned char transform) +{ + int rotate_flag = transform & 0x7; + + switch (rotate_flag) { + case HAL_TRANSFORM_ROT_90: return G2D_ROT_90; + case HAL_TRANSFORM_ROT_180: return G2D_ROT_180; + case HAL_TRANSFORM_ROT_270: return G2D_ROT_270; + default: + return G2D_ROT_0; + } +} + +int runG2d(struct hwc_context_t *ctx, g2d_rect *src_rect, g2d_rect *dst_rect, + uint32_t transform) +{ + sec_g2d_t * g2d = &ctx->g2d; + g2d_flag flag = {G2D_ROT_0, G2D_ALPHA_BLENDING_OPAQUE, 0, 0, 0, 0, 0, 0}; + int rotate_value = 0; + + // 1 : source address and size + src_rect->phys_addr = get_g2d_src_phys_addr(ctx, src_rect); + if (0 == src_rect->phys_addr) + return -1; + + // 2 : destination address and size + if (0 == dst_rect->phys_addr) + return -2; + + // check whether g2d supports the src format + src_rect->color_format = get_HAL_2_G2D_FORMAT(src_rect->color_format); + if (0 > src_rect->color_format) + return -3; + + dst_rect->color_format = get_HAL_2_G2D_FORMAT(dst_rect->color_format); + if (0 > dst_rect->color_format) + return -4; + + flag.rotate_val = rotateValueHAL2G2D(transform); + + // scale and rotate and alpha with FIMG + if(stretchSecFimg(src_rect, dst_rect, &flag) < 0) + return -5; + + return 0; +} +#endif + +int createMem(struct s3c_mem_t *mem, unsigned int index, unsigned int size) +{ + struct s3c_mem_alloc *ptr_mem_alloc; + struct s3c_mem_alloc mem_alloc_info; + + if (index >= NUM_OF_MEM_OBJ) { + SEC_HWC_Log(HWC_LOG_ERROR, "%s::invalid index (%d >= %d)", + __func__, index, NUM_OF_MEM_OBJ); + goto err; + } + + ptr_mem_alloc = &mem->mem_alloc[index]; + + if (mem->fd <= 0) { + mem->fd = open(S3C_MEM_DEV_NAME, O_RDWR); + if (mem->fd <= 0) { + SEC_HWC_Log(HWC_LOG_ERROR, "%s::open(%s) fail(%s)", + __func__, S3C_MEM_DEV_NAME, strerror(errno)); + goto err; + } + } + + // kcoolsw : what the hell of this line?? + if (0 == size) + return 0; + + mem_alloc_info.size = size; + + if (ioctl(mem->fd, S3C_MEM_CACHEABLE_ALLOC, &mem_alloc_info) < 0) { + SEC_HWC_Log(HWC_LOG_ERROR, "%s::S3C_MEM_ALLOC(size : %d) fail", + __func__, mem_alloc_info.size); + goto err; + } + + ptr_mem_alloc->phy_addr = mem_alloc_info.phy_addr; + ptr_mem_alloc->vir_addr = mem_alloc_info.vir_addr; + ptr_mem_alloc->size = mem_alloc_info.size; + + return 0; + +err: + if (0 < mem->fd) + close(mem->fd); + mem->fd = 0; + + return 0; +} + +int destroyMem(struct s3c_mem_t *mem) +{ + int i; + struct s3c_mem_alloc *ptr_mem_alloc; + + if (mem->fd <= 0) { + SEC_HWC_Log(HWC_LOG_ERROR, "%s::invalied fd(%d) fail", __func__, mem->fd); + return -1; + } + + for (i = 0; i < NUM_OF_MEM_OBJ; i++) { + ptr_mem_alloc = &mem->mem_alloc[i]; + + if (0 != ptr_mem_alloc->vir_addr) { + if (ioctl(mem->fd, S3C_MEM_FREE, ptr_mem_alloc) < 0) { + SEC_HWC_Log(HWC_LOG_ERROR, "%s::S3C_MEM_FREE fail", __func__); + return -1; + } + + ptr_mem_alloc->phy_addr = 0; + ptr_mem_alloc->vir_addr = 0; + ptr_mem_alloc->size = 0; + } + } + + close(mem->fd); + mem->fd = 0; + + return 0; +} + +int checkMem(struct s3c_mem_t *mem, unsigned int index, unsigned int size) +{ + int ret; + struct s3c_mem_alloc *ptr_mem_alloc; + struct s3c_mem_alloc mem_alloc_info; + + if (index >= NUM_OF_MEM_OBJ) { + SEC_HWC_Log(HWC_LOG_ERROR, "%s::invalid index (%d >= %d)", __func__, + index, NUM_OF_MEM_OBJ); + return -1; + } + + if (mem->fd <= 0) { + ret = createMem(mem, index, size); + return ret; + } + + ptr_mem_alloc = &mem->mem_alloc[index]; + + if (ptr_mem_alloc->size < (int)size) { + if (0 < ptr_mem_alloc->size) { + // free allocated mem + if (ioctl(mem->fd, S3C_MEM_FREE, ptr_mem_alloc) < 0) { + SEC_HWC_Log(HWC_LOG_ERROR, "%s::S3C_MEM_FREE fail", __func__); + return -1; + } + } + + // allocate mem with requested size + mem_alloc_info.size = size; + if (ioctl(mem->fd, S3C_MEM_CACHEABLE_ALLOC, &mem_alloc_info) < 0) { + SEC_HWC_Log(HWC_LOG_ERROR, "%s::S3C_MEM_ALLOC(size : %d) fail", + __func__, mem_alloc_info.size); + return -1; + } + + ptr_mem_alloc->phy_addr = mem_alloc_info.phy_addr; + ptr_mem_alloc->vir_addr = mem_alloc_info.vir_addr; + ptr_mem_alloc->size = mem_alloc_info.size; + } + + return 0; +} + +#ifdef USE_HW_PMEM +int createPmem(sec_pmem_t *pm, unsigned int buf_size) +{ + int master_fd, err = 0, i; + void *base; + unsigned int phys_base; + size_t size, sub_size[NUM_OF_MEM_OBJ]; + struct pmem_region region; + + master_fd = open(PMEM_DEVICE_DEV_NAME, O_RDWR, 0); + if (master_fd < 0) { + pm->pmem_master_fd = -1; + if (EACCES == errno) { + return 0; + } else { + SEC_HWC_Log(HWC_LOG_ERROR, "%s::open(%s) fail(%s)", + __func__, PMEM_DEVICE_DEV_NAME, strerror(errno)); + return -errno; + } + } + + if (ioctl(master_fd, PMEM_GET_TOTAL_SIZE, ®ion) < 0) { + SEC_HWC_Log(HWC_LOG_ERROR, "PMEM_GET_TOTAL_SIZE failed, default mode"); + size = 8<<20; // 8 MiB + } else { + size = region.len; + } + + base = mmap(0, size, PROT_READ|PROT_WRITE, MAP_SHARED, master_fd, 0); + if (base == MAP_FAILED) { + SEC_HWC_Log(HWC_LOG_ERROR, "[%s] mmap failed : %d (%s)", __func__, + errno, strerror(errno)); + base = 0; + close(master_fd); + master_fd = -1; + return -errno; + } + + if (ioctl(master_fd, PMEM_GET_PHYS, ®ion) < 0) { + SEC_HWC_Log(HWC_LOG_ERROR, "PMEM_GET_PHYS failed, limp mode"); + region.offset = 0; + } + + pm->pmem_master_fd = master_fd; + pm->pmem_master_base = base; + pm->pmem_total_size = size; + //pm->pmem_master_phys_base = region.offset; + phys_base = region.offset; + + // sec_pmem_alloc[0] for temporary buffer for source + sub_size[0] = buf_size; + sub_size[0] = roundUpToPageSize(sub_size[0]); + + for (i = 0; i < NUM_OF_MEM_OBJ; i++) { + sec_pmem_alloc_t *pm_alloc = &(pm->sec_pmem_alloc[i]); + int fd, ret; + int offset = i ? sub_size[i-1] : 0; + struct pmem_region sub = { offset, sub_size[i] }; + + // create the "sub-heap" + if (0 > (fd = open(PMEM_DEVICE_DEV_NAME, O_RDWR, 0))) { + SEC_HWC_Log(HWC_LOG_ERROR, + "[%s][index=%d] open failed (%dL) : %d (%s)", + __func__, i, __LINE__, errno, strerror(errno)); + return -errno; + } + + // connect to it + if (0 != (ret = ioctl(fd, PMEM_CONNECT, pm->pmem_master_fd))) { + SEC_HWC_Log(HWC_LOG_ERROR, + "[%s][index=%d] ioctl(PMEM_CONNECT) failed : %d (%s)", + __func__, i, errno, strerror(errno)); + close(fd); + return -errno; + } + + // make it available to the client process + if (0 != (ret = ioctl(fd, PMEM_MAP, &sub))) { + SEC_HWC_Log(HWC_LOG_ERROR, + "[%s][index=%d] ioctl(PMEM_MAP) failed : %d (%s)", + __func__, i, errno, strerror(errno)); + close(fd); + return -errno; + } + + pm_alloc->fd = fd; + pm_alloc->total_size = sub_size[i]; + pm_alloc->offset = offset; + pm_alloc->virt_addr = (unsigned int)base + (unsigned int)offset; + pm_alloc->phys_addr = (unsigned int)phys_base + (unsigned int)offset; + +#if defined (PMEM_DEBUG) + SEC_HWC_Log(HWC_LOG_DEBUG, "[%s] pm_alloc[%d] fd=%d total_size=%d " + "offset=0x%x virt_addr=0x%x phys_addr=0x%x", + __func__, i, pm_alloc->fd, pm_alloc->total_size, + pm_alloc->offset, pm_alloc->virt_addr, pm_alloc->phys_addr); +#endif + } + + return err; +} + +int destroyPmem(sec_pmem_t *pm) +{ + int i, err; + + for (i=0; isec_pmem_alloc[i]); + + if (0 <= pm_alloc->fd) { + struct pmem_region sub = { pm_alloc->offset, pm_alloc->total_size }; + + if (0 > (err = ioctl(pm_alloc->fd, PMEM_UNMAP, &sub))) + SEC_HWC_Log(HWC_LOG_ERROR, + "[%s][index=%d] ioctl(PMEM_UNMAP) failed : %d (%s)", + __func__, i, errno, strerror(errno)); +#if defined (PMEM_DEBUG) + else + SEC_HWC_Log(HWC_LOG_DEBUG, + "[%s] pm_alloc[%d] unmap fd=%d total_size=%d offset=0x%x", + __func__, i, pm_alloc->fd, pm_alloc->total_size, + pm_alloc->offset); +#endif + close(pm_alloc->fd); + + pm_alloc->fd = -1; + pm_alloc->total_size = 0; + pm_alloc->offset = 0; + pm_alloc->virt_addr = 0; + pm_alloc->phys_addr = 0; + } + } + + if (0 <= pm->pmem_master_fd) { + munmap(pm->pmem_master_base, pm->pmem_total_size); + close(pm->pmem_master_fd); + pm->pmem_master_fd = -1; + } + + pm->pmem_master_base = 0; + pm->pmem_total_size = 0; + + return 0; +} + +int checkPmem(sec_pmem_t *pm, unsigned int index, unsigned int requested_size) +{ + sec_pmem_alloc_t *pm_alloc = &(pm->sec_pmem_alloc[index]); + + if (0 < pm_alloc->virt_addr && + requested_size <= (unsigned int)(pm_alloc->total_size)) + return 0; + + pm_alloc->size = 0; + return -1; +} + +#endif diff --git a/exynos5/hal/libhwcomposer/SecHWCUtils.h b/exynos5/hal/libhwcomposer/SecHWCUtils.h new file mode 100644 index 0000000..799fc65 --- /dev/null +++ b/exynos5/hal/libhwcomposer/SecHWCUtils.h @@ -0,0 +1,309 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * + * @author Rama, Meka(v.meka@samsung.com) + Sangwoo, Park(sw5771.park@samsung.com) + Jamie, Oh (jung-min.oh@samsung.com) + * @date 2011-03-11 + * + */ + +#ifndef ANDROID_SEC_HWC_UTILS_H_ +#define ANDROID_SEC_HWC_UTILS_H_ + +#include +#include +#include + +#include +#include +#include + +#include +#include "s5p_fimc_v4l2.h" +#include "sec_utils_v4l2.h" + +#include +#include +#include +#include + +#include "linux/fb.h" + +#include "s3c_lcd.h" +#include "s3c_mem.h" +#include "sec_format.h" + +//#define HWC_DEBUG +#if defined(BOARD_USES_FIMGAPI) +#include "sec_g2d.h" +//#define SUB_TITLES_HWC +#endif + +#define NUM_OF_WIN (2) +#define NUM_OF_WIN_BUF (2) +#define NUM_OF_MEM_OBJ (1) + +#if (NUM_OF_WIN_BUF < 2) + #define ENABLE_FIMD_VSYNC +#endif + +#ifdef SAMSUNG_EXYNOS5250 +#define PP_DEVICE_DEV_NAME "/dev/video29" +#endif + +#define S3C_MEM_DEV_NAME "/dev/s3c-mem" +#define PMEM_DEVICE_DEV_NAME "/dev/pmem_gpu1" + +#define GSC_VERSION GSC_EVT1 +//#define USE_HW_PMEM + +#define PMEM_SIZE (1920 * 1280 * 2) + +struct sec_rect { + int32_t x; + int32_t y; + int32_t w; + int32_t h; +}; + +struct sec_img { + uint32_t f_w; + uint32_t f_h; + uint32_t w; + uint32_t h; + uint32_t format; + uint32_t base; + uint32_t offset; + uint32_t paddr; + uint32_t uoffset; + uint32_t voffset; + int usage; + int mem_id; +}; + +inline int SEC_MIN(int x, int y) +{ + return ((x < y) ? x : y); +} + +inline int SEC_MAX(int x, int y) +{ + return ((x > y) ? x : y); +} + +struct s3c_mem_t { + int fd; + struct s3c_mem_alloc mem_alloc[NUM_OF_MEM_OBJ]; +}; + +#ifdef USE_HW_PMEM +typedef struct __sec_pmem_alloc { + int fd; + int total_size; + int offset; + int size; + unsigned int virt_addr; + unsigned int phys_addr; +} sec_pmem_alloc_t; + +typedef struct __sec_pmem { + int pmem_master_fd; + void *pmem_master_base; + int pmem_total_size; + sec_pmem_alloc_t sec_pmem_alloc[NUM_OF_MEM_OBJ]; +} sec_pmem_t; + +inline size_t roundUpToPageSize(size_t x) +{ + return (x + (PAGE_SIZE-1)) & ~(PAGE_SIZE-1); +} +#endif + +struct hwc_win_info_t { + int fd; + int size; + sec_rect rect_info; + uint32_t addr[NUM_OF_WIN_BUF]; + int buf_index; + + int power_state; + int blending; + int layer_index; + int status; + int vsync; + int ion_fd; + + struct fb_fix_screeninfo fix_info; + struct fb_var_screeninfo var_info; + struct fb_var_screeninfo lcd_info; +}; + +enum { + HWC_WIN_FREE = 0, + HWC_WIN_RESERVED, +}; + +enum { + HWC_UNKNOWN_MEM_TYPE = 0, + HWC_PHYS_MEM_TYPE, + HWC_VIRT_MEM_TYPE, +}; + +struct hwc_context_t { + hwc_composer_device_t device; + + /* our private state goes below here */ + struct hwc_win_info_t win[NUM_OF_WIN]; + struct fb_var_screeninfo lcd_info; + s5p_fimc_t fimc; +#ifdef SUB_TITLES_HWC + sec_g2d_t g2d; +#endif + struct s3c_mem_t s3c_mem; +#ifdef USE_HW_PMEM + sec_pmem_t sec_pmem; +#endif + int num_of_fb_layer; + int num_of_hwc_layer; + int num_2d_blit_layer; + uint32_t layer_prev_buf[NUM_OF_WIN]; +}; + +typedef enum _LOG_LEVEL { + HWC_LOG_DEBUG, + HWC_LOG_WARNING, + HWC_LOG_ERROR, +} HWC_LOG_LEVEL; + +#define SEC_HWC_LOG_TAG "SECHWC_LOG" + +#ifdef HWC_DEBUG +#define SEC_HWC_Log(a, ...) ((void)_SEC_HWC_Log(a, SEC_HWC_LOG_TAG, __VA_ARGS__)) +#else +#define SEC_HWC_Log(a, ...) \ + do { \ + if (a == HWC_LOG_ERROR) \ + ((void)_SEC_HWC_Log(a, SEC_HWC_LOG_TAG, __VA_ARGS__)); \ + } while (0) +#endif + +extern void _SEC_HWC_Log(HWC_LOG_LEVEL logLevel, const char *tag, const char *msg, ...); + +/* copied from gralloc module ..*/ +typedef struct { + native_handle_t base; + + /* These fields can be sent cross process. They are also valid + * to duplicate within the same process. + * + * A table is stored within psPrivateData on gralloc_module_t (this + * is obviously per-process) which maps stamps to a mapped + * PVRSRV_CLIENT_MEM_INFO in that process. Each map entry has a lock + * count associated with it, satisfying the requirements of the + * Android API. This also prevents us from leaking maps/allocations. + * + * This table has entries inserted either by alloc() + * (alloc_device_t) or map() (gralloc_module_t). Entries are removed + * by free() (alloc_device_t) and unmap() (gralloc_module_t). + * + * As a special case for framebuffer_device_t, framebuffer_open() + * will add and framebuffer_close() will remove from this table. + */ + +#define IMG_NATIVE_HANDLE_NUMFDS 1 + /* The `fd' field is used to "export" a meminfo to another process. + * Therefore, it is allocated by alloc_device_t, and consumed by + * gralloc_module_t. The framebuffer_device_t does not need a handle, + * and the special value IMG_FRAMEBUFFER_FD is used instead. + */ + int fd; + +#if 1 + int format; + int magic; + int flags; + int size; + int offset; + int base_addr; +#define IMG_NATIVE_HANDLE_NUMINTS ((sizeof(uint64_t) / sizeof(int)) + 4 + 6) +#else +#define IMG_NATIVE_HANDLE_NUMINTS ((sizeof(IMG_UINT64) / sizeof(int)) + 4) +#endif + /* A KERNEL unique identifier for any exported kernel meminfo. Each + * exported kernel meminfo will have a unique stamp, but note that in + * userspace, several meminfos across multiple processes could have + * the same stamp. As the native_handle can be dup(2)'d, there could be + * multiple handles with the same stamp but different file descriptors. + */ + uint64_t ui64Stamp; + + /* We could live without this, but it lets us perform some additional + * validation on the client side. Normally, we'd have no visibility + * of the allocated usage, just the lock usage. + */ + int usage; + + /* In order to do efficient cache flushes we need the buffer dimensions + * and format. These are available on the android_native_buffer_t, + * but the platform doesn't pass them down to the graphics HAL. + * + * TODO: Ideally the platform would be modified to not require this. + */ + int width; + int height; + int bpp; +} +__attribute__((aligned(sizeof(int)),packed)) sec_native_handle_t; + +int window_open (struct hwc_win_info_t *win, int id); +int window_close (struct hwc_win_info_t *win); +int window_set_pos (struct hwc_win_info_t *win); +int window_get_info (struct hwc_win_info_t *win, int win_num); +int window_pan_display(struct hwc_win_info_t *win); +int window_show (struct hwc_win_info_t *win); +int window_hide (struct hwc_win_info_t *win); +int window_get_global_lcd_info(int fd, struct fb_var_screeninfo *lcd_info); + +int createVideoDev (s5p_fimc_t *fimc); +int destroyVideoDev(s5p_fimc_t *fimc); +int runFimc(struct hwc_context_t *ctx, + struct sec_img *src_img, struct sec_rect *src_rect, + struct sec_img *dst_img, struct sec_rect *dst_rect, + uint32_t transform); + +#ifdef SUB_TITLES_HWC +int runG2d(struct hwc_context_t *ctx, + g2d_rect *src_rect, g2d_rect *dst_rect, + uint32_t transform); + +int destroyG2d(sec_g2d_t *g2d); +int createG2d(sec_g2d_t *g2d); +#endif + +int createMem (struct s3c_mem_t *mem, unsigned int index, unsigned int size); +int destroyMem(struct s3c_mem_t *mem); +int checkMem (struct s3c_mem_t *mem, unsigned int index, unsigned int size); + +#ifdef USE_HW_PMEM +int createPmem (sec_pmem_t *pm, unsigned int size); +int destroyPmem(sec_pmem_t *pm); +int checkPmem (sec_pmem_t *pm, unsigned int index, unsigned int size); +#endif + +#endif /* ANDROID_SEC_HWC_UTILS_H_*/ diff --git a/exynos5/hal/libhwjpeg/Android.mk b/exynos5/hal/libhwjpeg/Android.mk new file mode 100644 index 0000000..70e25fe --- /dev/null +++ b/exynos5/hal/libhwjpeg/Android.mk @@ -0,0 +1,37 @@ +# Copyright (C) 2008 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +LOCAL_PATH:= $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_C_INCLUDES := $(LOCAL_PATH) \ + $(LOCAL_PATH)/../include + +LOCAL_SRC_FILES:= \ + SecJpegCodecHal.cpp \ + SecJpegEncoderHal.cpp \ + SecJpegEncoder.cpp \ + SecJpegDecoderHal.cpp + +LOCAL_SHARED_LIBRARIES := \ + libcutils \ + libion + +#LOCAL_STATIC_LIBRARIES := \ + +LOCAL_MODULE:= libhwjpeg + +LOCAL_MODULE_TAGS := eng + +include $(BUILD_SHARED_LIBRARY) diff --git a/exynos5/hal/libhwjpeg/SecJpegCodecHal.cpp b/exynos5/hal/libhwjpeg/SecJpegCodecHal.cpp new file mode 100644 index 0000000..b78212b --- /dev/null +++ b/exynos5/hal/libhwjpeg/SecJpegCodecHal.cpp @@ -0,0 +1,338 @@ +/* + * Copyright Samsung Electronics Co.,LTD. + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include "SecJpegCodecHal.h" + +#define JPEG_ERROR_LOG(fmt,...) + +SecJpegCodecHal::SecJpegCodecHal() +{ +} + +SecJpegCodecHal::~SecJpegCodecHal() +{ +} + +int SecJpegCodecHal::t_v4l2Querycap(int iFd) +{ + struct v4l2_capability cap; + int iRet = ERROR_NONE; + + iRet = ioctl(iFd, VIDIOC_QUERYCAP, &cap); + if (iRet < 0) { + JPEG_ERROR_LOG("[%s:%d]: VIDIOC_QUERYCAP failed", __func__, iRet); + return iRet; + } + + return iRet; +} + +int SecJpegCodecHal::t_v4l2SetJpegcomp(int iFd, int iQuality) +{ + struct v4l2_jpegcompression arg; + int iRet = ERROR_NONE; + + arg.quality = iQuality; + + iRet = ioctl(iFd, VIDIOC_S_JPEGCOMP, &arg); + if (iRet < 0) { + JPEG_ERROR_LOG("[%s:%d]: VIDIOC_S_JPEGCOMP failed", __func__, iRet); + return iRet; + } + + return iRet; +} + +int SecJpegCodecHal::t_v4l2SetFmt(int iFd, enum v4l2_buf_type eType, struct CONFIG *pstConfig) +{ + struct v4l2_format fmt; + int iRet = ERROR_NONE; + + fmt.type = eType; + fmt.fmt.pix_mp.width = pstConfig->width; + fmt.fmt.pix_mp.height = pstConfig->height; + fmt.fmt.pix_mp.field = V4L2_FIELD_ANY; + fmt.fmt.pix_mp.num_planes = pstConfig->numOfPlanes; + + if (pstConfig->mode == MODE_ENCODE) + fmt.fmt.pix_mp.colorspace = V4L2_COLORSPACE_JPEG; + + switch (fmt.type) { + case V4L2_BUF_TYPE_VIDEO_OUTPUT: // fall through + case V4L2_BUF_TYPE_VIDEO_CAPTURE: + break; + case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: + if (pstConfig->mode == MODE_ENCODE) { + fmt.fmt.pix_mp.pixelformat = pstConfig->pix.enc_fmt.in_fmt; + } else { + fmt.fmt.pix_mp.pixelformat = pstConfig->pix.dec_fmt.in_fmt; + fmt.fmt.pix_mp.plane_fmt[0].sizeimage = pstConfig->sizeJpeg; + } + break; + case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: + if (pstConfig->mode == MODE_ENCODE) { + fmt.fmt.pix_mp.pixelformat = pstConfig->pix.enc_fmt.out_fmt; + } else { + fmt.fmt.pix_mp.pixelformat = pstConfig->pix.dec_fmt.out_fmt; + fmt.fmt.pix_mp.width = pstConfig->scaled_width; + fmt.fmt.pix_mp.height = pstConfig->scaled_height; + } + break; + default: + return -ERROR_INVALID_V4l2_BUF_TYPE; + break; + } + + iRet = ioctl(iFd, VIDIOC_S_FMT, &fmt); + if (iRet < 0) { + JPEG_ERROR_LOG("[%s:%d]: VIDIOC_S_FMT failed", __func__, iRet); + return iRet; + } + + return iRet; +} + +int SecJpegCodecHal::t_v4l2GetFmt(int iFd, enum v4l2_buf_type eType, struct CONFIG *pstConfig) +{ + struct v4l2_format fmt; + int iRet = ERROR_NONE; + + fmt.type = eType; + iRet = ioctl(iFd, VIDIOC_G_FMT, &fmt); + if (iRet < 0) { + JPEG_ERROR_LOG("[%s:%d]: VIDIOC_G_FMT failed", __func__, iRet); + return iRet; + } + + switch (fmt.type) { + case V4L2_BUF_TYPE_VIDEO_OUTPUT: // fall through + case V4L2_BUF_TYPE_VIDEO_CAPTURE: + pstConfig->width = fmt.fmt.pix.width; + pstConfig->height = fmt.fmt.pix.height; + break; + case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: + pstConfig->width = fmt.fmt.pix_mp.width; + pstConfig->height = fmt.fmt.pix_mp.height; + if (pstConfig->mode == MODE_ENCODE) + pstConfig->pix.enc_fmt.in_fmt = fmt.fmt.pix_mp.pixelformat; + else + pstConfig->pix.dec_fmt.in_fmt = fmt.fmt.pix_mp.pixelformat; + break; + case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: + pstConfig->width = fmt.fmt.pix_mp.width; + pstConfig->height = fmt.fmt.pix_mp.height; + if (pstConfig->mode == MODE_ENCODE) + pstConfig->pix.enc_fmt.out_fmt = fmt.fmt.pix_mp.pixelformat; + else + pstConfig->pix.dec_fmt.out_fmt = fmt.fmt.pix_mp.pixelformat; + break; + default: + return -ERROR_INVALID_V4l2_BUF_TYPE; + } + + return iRet; +} + +int SecJpegCodecHal::t_v4l2Reqbufs(int iFd, int iBufCount, struct BUF_INFO *pstBufInfo) +{ + struct v4l2_requestbuffers req; + int iRet = ERROR_NONE; + + memset(&req, 0, sizeof(req)); + + req.type = pstBufInfo->buf_type; + req.memory = pstBufInfo->memory; + + //if (pstBufInfo->memory == V4L2_MEMORY_MMAP) + req.count = iBufCount; + + iRet = ioctl(iFd, VIDIOC_REQBUFS, &req); + if (iRet < 0) { + JPEG_ERROR_LOG("[%s:%d]: VIDIOC_REQBUFS failed", __func__, iRet); + return iRet; + } + + return iRet; +} + +int SecJpegCodecHal::t_v4l2Querybuf(int iFd, struct BUF_INFO *pstBufInfo, struct BUFFER *pstBuf) +{ + struct v4l2_buffer v4l2_buf; + struct v4l2_plane plane[JPEG_MAX_PLANE_CNT]; + int iRet = ERROR_NONE; + int i; + + memset(plane, 0, (int)JPEG_MAX_PLANE_CNT * sizeof(struct v4l2_plane)); + + v4l2_buf.index = 0; + v4l2_buf.type = pstBufInfo->buf_type; + v4l2_buf.memory = pstBufInfo->memory; + v4l2_buf.length = pstBufInfo->numOfPlanes; + v4l2_buf.m.planes = plane; + + iRet = ioctl(iFd, VIDIOC_QUERYBUF, &v4l2_buf); + if (iRet < 0) { + JPEG_ERROR_LOG("[%s:%d]: VIDIOC_QUERYBUF failed", __func__, iRet); + return iRet; + } + + for (i= 0; i < v4l2_buf.length; i++) { + pstBuf->size[i] = v4l2_buf.m.planes[i].length; + pstBuf->addr[i] = (char *) mmap(0, + pstBuf->size[i], + PROT_READ | PROT_WRITE, MAP_SHARED, iFd, + v4l2_buf.m.planes[i].m.mem_offset); + + if (pstBuf->addr[i] == MAP_FAILED) { + JPEG_ERROR_LOG("[%s]: mmap failed", __func__); + return -ERROR_MMAP_FAILED; + } + } + + return iRet; +} + +int SecJpegCodecHal::t_v4l2Qbuf(int iFd, struct BUF_INFO *pstBufInfo, struct BUFFER *pstBuf) +{ + struct v4l2_buffer v4l2_buf; + struct v4l2_plane plane[JPEG_MAX_PLANE_CNT]; + int i; + int iRet = ERROR_NONE; + + memset(&v4l2_buf, 0, sizeof(struct v4l2_buffer)); + memset(plane, 0, (int)JPEG_MAX_PLANE_CNT * sizeof(struct v4l2_plane)); + + v4l2_buf.index = 0; + v4l2_buf.type = pstBufInfo->buf_type; + v4l2_buf.memory = pstBufInfo->memory; + v4l2_buf.length = pstBufInfo->numOfPlanes; + v4l2_buf.m.planes = plane; + + if (pstBufInfo->memory == V4L2_MEMORY_USERPTR) { + for (i = 0; i < pstBufInfo->numOfPlanes; i++) { + v4l2_buf.m.planes[i].m.userptr = (unsigned long)pstBuf->addr[i]; + v4l2_buf.m.planes[i].length = pstBuf->size[i]; + } + } + + iRet = ioctl(iFd, VIDIOC_QBUF, &v4l2_buf); + if (iRet < 0) { + JPEG_ERROR_LOG("[%s:%d] VIDIOC_QBUF failed", __func__, iRet); + pstBuf->numOfPlanes = 0; + return iRet; + } + + return iRet; +} + +int SecJpegCodecHal::t_v4l2Dqbuf(int iFd, enum v4l2_buf_type eType, enum v4l2_memory eMemory) +{ + struct v4l2_buffer buf; + int iRet = ERROR_NONE; + + memset(&buf, 0, sizeof(struct v4l2_buffer)); + + buf.type = eType; + buf.memory = eMemory; + + iRet = ioctl(iFd, VIDIOC_DQBUF, &buf); + if (iRet < 0) { + JPEG_ERROR_LOG("[%s:%d] VIDIOC_DQBUF failed", __func__, iRet); + return iRet; + } + + return iRet; +} + +int SecJpegCodecHal::t_v4l2StreamOn(int iFd, enum v4l2_buf_type eType) +{ + int iRet = ERROR_NONE; + + iRet = ioctl(iFd, VIDIOC_STREAMON, &eType); + if (iRet < 0) { + JPEG_ERROR_LOG("[%s:%d] VIDIOC_STREAMON failed", __func__, iRet); + return iRet; + } + + return iRet; +} + +int SecJpegCodecHal::t_v4l2StreamOff(int iFd, enum v4l2_buf_type eType) +{ + int iRet = ERROR_NONE; + + iRet = ioctl(iFd, VIDIOC_STREAMOFF, &eType); + if (iRet < 0) { + JPEG_ERROR_LOG("[%s:%d] VIDIOC_STREAMOFF failed", __func__, iRet); + return iRet; + } + + return iRet; +} + +int SecJpegCodecHal::t_v4l2SetCtrl(int iFd, int iCid, int iValue) +{ + struct v4l2_control vc; + int iRet = ERROR_NONE; + + vc.id = iCid; + vc.value = iValue; + + iRet = ioctl(iFd, VIDIOC_S_CTRL, &vc); + if (iRet < 0) { + JPEG_ERROR_LOG("[%s] VIDIOC_S_CTRL failed : cid(%d), value(%d)\n", __func__, iCid, iValue); + return iRet; + } + + return iRet; +} + +int SecJpegCodecHal::t_v4l2GetCtrl(int iFd, int iCid) +{ + struct v4l2_control ctrl; + int iRet = ERROR_NONE; + + ctrl.id = iCid; + + iRet = ioctl(iFd, VIDIOC_G_CTRL, &ctrl); + if (iRet < 0) { + JPEG_ERROR_LOG("[%s] VIDIOC_G_CTRL failed : cid(%d)\n", __func__, ctrl.id); + return iRet; + } + + return ctrl.value; +} + diff --git a/exynos5/hal/libhwjpeg/SecJpegDecoderHal.cpp b/exynos5/hal/libhwjpeg/SecJpegDecoderHal.cpp new file mode 100644 index 0000000..563b15a --- /dev/null +++ b/exynos5/hal/libhwjpeg/SecJpegDecoderHal.cpp @@ -0,0 +1,498 @@ +/* + * Copyright Samsung Electronics Co.,LTD. + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include "SecJpegCodecHal.h" + +#define JPEG_ERROR_LOG(fmt,...) + +#define NUM_PLANES (1) +#define NUM_BUFFERS (1) + +SecJpegDecoderHal::SecJpegDecoderHal() +{ + t_iJpegFd = -1; + t_bFlagCreate = false; +} + +SecJpegDecoderHal::~SecJpegDecoderHal() +{ + if (t_bFlagCreate == true) { + this->destroy(); + } +} + +int SecJpegDecoderHal::create(void) +{ + if (t_bFlagCreate == true) { + return ERROR_JPEG_DEVICE_ALREADY_CREATE; + } + + int iRet = ERROR_NONE; + + t_iJpegFd = open(JPEG_DEC_NODE, O_RDWR, 0); + + if (t_iJpegFd < 0) { + t_iJpegFd = -1; + JPEG_ERROR_LOG("[%s]: JPEG_DEC_NODE open failed", __func__); + return ERROR_CANNOT_OPEN_JPEG_DEVICE; + } + + if (t_iJpegFd <= 0) { + t_iJpegFd = -1; + JPEG_ERROR_LOG("ERR(%s):JPEG device was closed\n", __func__); + return ERROR_JPEG_DEVICE_ALREADY_CLOSED; + } + + iRet = t_v4l2Querycap(t_iJpegFd); + if (iRet < 0) { + JPEG_ERROR_LOG("[%s]: QUERYCAP failed", __func__); + close(t_iJpegFd); + return ERROR_CANNOT_OPEN_JPEG_DEVICE; + } + + memset(&t_stJpegConfig, 0, sizeof(struct CONFIG)); + memset(&t_stJpegInbuf, 0, sizeof(struct BUFFER)); + memset(&t_stJpegOutbuf, 0, sizeof(struct BUFFER)); + + t_stJpegConfig.mode = MODE_DECODE; + + t_bFlagCreate = true; + t_bFlagCreateInBuf = false; + t_bFlagCreateOutBuf = false; + t_bFlagExcute = false; + + t_iPlaneNum = 0; + + return ERROR_NONE; +} + +int SecJpegDecoderHal::destroy(void) +{ + if (t_bFlagCreate == false) { + return ERROR_JPEG_DEVICE_ALREADY_DESTROY; + } + + if (t_iJpegFd > 0) { + struct BUF_INFO stBufInfo; + int iRet = ERROR_NONE; + + if (t_bFlagExcute) { + iRet = t_v4l2StreamOff(t_iJpegFd, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); + } + + if (t_bFlagExcute) { + stBufInfo.numOfPlanes = NUM_PLANES; + stBufInfo.memory = V4L2_MEMORY_MMAP; + + stBufInfo.buf_type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; + iRet = t_v4l2Reqbufs(t_iJpegFd, 0, &stBufInfo); + + stBufInfo.numOfPlanes = t_iPlaneNum; + stBufInfo.buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; + iRet = t_v4l2Reqbufs(t_iJpegFd, 0, &stBufInfo); + } + + iRet = close(t_iJpegFd); + if (iRet < 0) { + JPEG_ERROR_LOG("[%s:%d]: JPEG_DEC_NODE close failed", __func__, iRet); + } + } + + t_iJpegFd = -1; + t_bFlagCreate = false; + return ERROR_NONE; +} + +int SecJpegDecoderHal::setSize(int iW, int iH) +{ + if (t_bFlagCreate == false) { + return ERROR_JPEG_DEVICE_NOT_CREATE_YET; + } + + if (iW < 0 || MAX_JPG_WIDTH < iW) { + return ERROR_INVALID_IMAGE_SIZE; + } + + if (iH < 0 || MAX_JPG_HEIGHT < iH) { + return ERROR_INVALID_IMAGE_SIZE; + } + + t_stJpegConfig.width = iW; + t_stJpegConfig.height = iH; + + return ERROR_NONE; +} + +int SecJpegDecoderHal::setJpegConfig(void *pConfig) +{ + if (t_bFlagCreate == false) { + return ERROR_JPEG_DEVICE_NOT_CREATE_YET; + } + + if (pConfig == NULL) { + return ERROR_JPEG_CONFIG_POINTER_NULL; + } + + memcpy(&t_stJpegConfig, pConfig, sizeof(struct CONFIG)); + + if (t_stJpegConfig.pix.dec_fmt.out_fmt == V4L2_PIX_FMT_NV12) { + t_iPlaneNum = 2; + } else { + t_iPlaneNum = 1; + } + + return ERROR_NONE; +} + +void *SecJpegDecoderHal::getJpegConfig(void) +{ + if (t_bFlagCreate == false) { + return NULL; + } + + return &t_stJpegConfig; +} + +char *SecJpegDecoderHal::getInBuf(int *piInputSize) +{ + if (t_bFlagCreate == false) { + return NULL; + } + + if (t_bFlagCreateInBuf == false) { + + *piInputSize = 0; + return NULL; + } + + *piInputSize = t_stJpegInbuf.size[0]; + + return (char *)(t_stJpegInbuf.addr[0]); +} + +char **SecJpegDecoderHal::getOutBuf(int *piOutputSize) +{ + if (t_bFlagCreate == false) { + return NULL; + } + + if (t_bFlagCreateOutBuf == false) { + + *piOutputSize = 0; + return NULL; + } + + for (int i=0;i + +#include "SecJpegEncoder.h" + +static const char ExifAsciiPrefix[] = { 0x41, 0x53, 0x43, 0x49, 0x49, 0x0, 0x0, 0x0 }; + +#define JPEG_ERROR_LOG(fmt,...) + +#define JPEG_MAIN_DUMP (0) +#define JPEG_THUMB_DUMP (0) + +SecJpegEncoder::SecJpegEncoder() +{ + m_flagCreate = false; + m_jpegMain = NULL; + m_jpegThumb = NULL; + m_thumbnailW = 0; + m_thumbnailH = 0; + m_pThumbInputBuffer = NULL; + m_pThumbOutputBuffer = NULL; +#ifdef JPEG_WA_FOR_PAGEFAULT + m_pJpegInputBuffer = 0; + m_pExtInBuf = NULL; + m_iInBufSize = 0; +#endif // JPEG_WA_FOR_PAGEFAULT + m_ionJpegClient = 0;; + m_ionThumbInBuffer = 0; + m_ionThumbOutBuffer = 0; +#ifdef JPEG_WA_FOR_PAGEFAULT + m_ionJpegInBuffer = 0;; +#endif // JPEG_WA_FOR_PAGEFAULT +} + +SecJpegEncoder::~SecJpegEncoder() +{ + if (m_flagCreate == true) { + this->destroy(); + } +} + +bool SecJpegEncoder::flagCreate(void) +{ + return m_flagCreate; +} + +int SecJpegEncoder::create(void) +{ + int ret = ERROR_NONE; + if (m_flagCreate == true) { + return ERROR_ALREADY_CREATE; + } + + if (m_jpegMain == NULL) { + m_jpegMain = new SecJpegEncoderHal; + + if (m_jpegMain == NULL) { + JPEG_ERROR_LOG("ERR(%s):Cannot create SecJpegEncoderHal class\n", __func__); + return ERROR_CANNOT_CREATE_SEC_JPEG_ENC_HAL; + } + + ret = m_jpegMain->create(); + if (ret) { + return ret; + } + + ret = m_jpegMain->setCache(JPEG_CACHE_ON); + + if (ret) { + m_jpegMain->destroy(); + return ret; + } + } + + m_flagCreate = true; + + return ERROR_NONE; +} + +int SecJpegEncoder::destroy(void) +{ + if (m_flagCreate == false) { + return ERROR_ALREADY_DESTROY; + } + + if (m_jpegMain != NULL) { + m_jpegMain->destroy(); + delete m_jpegMain; + m_jpegMain = NULL; + } + + if (m_jpegThumb != NULL) { + int iSize = sizeof(char)*m_thumbnailW*m_thumbnailH*4; + +#ifdef JPEG_WA_FOR_PAGEFAULT + iSize += JPEG_WA_BUFFER_SIZE; + + freeJpegIonMemory(m_ionJpegClient, &m_ionJpegInBuffer, &m_pJpegInputBuffer, m_iInBufSize); +#endif //JPEG_WA_FOR_PAGEFAULT + + freeJpegIonMemory(m_ionJpegClient, &m_ionThumbInBuffer, &m_pThumbInputBuffer, iSize); + freeJpegIonMemory(m_ionJpegClient, &m_ionThumbOutBuffer, &m_pThumbOutputBuffer, iSize); + + if (m_ionJpegClient != 0) { + ion_client_destroy(m_ionJpegClient); + m_ionJpegClient = 0; + } + + m_jpegThumb->destroy(); + delete m_jpegThumb; + m_jpegThumb = NULL; + } + + m_flagCreate = false; + m_thumbnailW = 0; + m_thumbnailH = 0; + return ERROR_NONE; +} + +int SecJpegEncoder::setSize(int w, int h) +{ + if (m_flagCreate == false) { + return ERROR_NOT_YET_CREATED; + } + + return m_jpegMain->setSize(w, h); +} + + +int SecJpegEncoder::setQuality(int quality) +{ + if (m_flagCreate == false) { + return ERROR_NOT_YET_CREATED; + } + + return m_jpegMain->setQuality(quality); +} + +int SecJpegEncoder::setColorFormat(int colorFormat) +{ + if (m_flagCreate == false) { + return ERROR_NOT_YET_CREATED; + } + + return m_jpegMain->setColorFormat(colorFormat); +} + +int SecJpegEncoder::setJpegFormat(int jpegFormat) +{ + if (m_flagCreate == false) { + return ERROR_NOT_YET_CREATED; + } + + return m_jpegMain->setJpegFormat(jpegFormat); +} + +int SecJpegEncoder::updateConfig(void) +{ + if (m_flagCreate == false) { + return ERROR_NOT_YET_CREATED; + } + + return m_jpegMain->updateConfig(); +} + +char *SecJpegEncoder::getInBuf(int *input_size) +{ + if (m_flagCreate == false) { + return NULL; + } + + int inSize = 0; + char *inBuf = *(m_jpegMain->getInBuf(&inSize)); + + if (inBuf == NULL) { + JPEG_ERROR_LOG("%s::Fail to JPEG input buffer!!\n", __func__); + return NULL; + } + + *input_size = inSize; + + return inBuf; +} + +char *SecJpegEncoder::getOutBuf(int *output_size) +{ + if (m_flagCreate == false) { + return NULL; + } + + int outSize = 0; + char *outBuf = m_jpegMain->getOutBuf(&outSize); + + if (outBuf == NULL) { + JPEG_ERROR_LOG("%s::Fail to JPEG input buffer!!\n", __func__); + return NULL; + } + + *output_size = outSize; + + return outBuf; +} + +int SecJpegEncoder::setInBuf(char *buf, int size) +{ + if (m_flagCreate == false) { + return ERROR_NOT_YET_CREATED; + } + + if (buf == NULL) { + return ERROR_BUFFR_IS_NULL; + } + + if (size<=0) { + return ERROR_BUFFER_TOO_SMALL; + } + + int ret = ERROR_NONE; + +#ifdef JPEG_WA_FOR_PAGEFAULT + size += JPEG_WA_BUFFER_SIZE; + + freeJpegIonMemory(m_ionJpegClient, &m_ionJpegInBuffer, &m_pJpegInputBuffer, size); + + if (m_ionJpegClient == 0) { + m_ionJpegClient = ion_client_create(); + if (m_ionJpegClient < 0) { + JPEG_ERROR_LOG("[%s]src ion client create failed, value = %d\n", __func__, size); + m_ionJpegClient = 0; + return ret; + } + } + + ret = allocJpegIonMemory(m_ionJpegClient, &m_ionJpegInBuffer, &m_pJpegInputBuffer, size); + if (ret != ERROR_NONE) { + return ret; + } + + ret = m_jpegMain->setInBuf(&m_pJpegInputBuffer, &size); + if (ret) { + JPEG_ERROR_LOG("%s::Fail to JPEG input buffer!!\n", __func__); + return ret; + } + m_iInBufSize = size; + + m_pExtInBuf = buf; + +#else // NO JPEG_WA_FOR_PAGEFAULT + ret = m_jpegMain->setInBuf(&buf, &size); + if (ret) { + JPEG_ERROR_LOG("%s::Fail to JPEG input buffer!!\n", __func__); + return ret; + } +#endif // JPEG_WA_FOR_PAGEFAULT + + return ERROR_NONE; +} + +int SecJpegEncoder::setOutBuf(char *buf, int size) +{ + if (m_flagCreate == false) { + return ERROR_NOT_YET_CREATED; + } + + if (buf == NULL) { + return ERROR_BUFFR_IS_NULL; + } + + if (size<=0) { + return ERROR_BUFFER_TOO_SMALL; + } + + int ret = ERROR_NONE; + ret = m_jpegMain->setOutBuf(buf, size); + if (ret) { + JPEG_ERROR_LOG("%s::Fail to JPEG output buffer!!\n", __func__); + return ret; + } + + return ERROR_NONE; +} + +int SecJpegEncoder::encode(int *size, exif_attribute_t *exifInfo) +{ + int ret = ERROR_NONE; + unsigned char *exifOut = NULL; + + if (m_flagCreate == false) { + return ERROR_NOT_YET_CREATED; + } + +#ifdef JPEG_WA_FOR_PAGEFAULT + memcpy(m_pJpegInputBuffer, m_pExtInBuf, m_iInBufSize-JPEG_WA_BUFFER_SIZE); +#endif // JPEG_WA_FOR_PAGEFAULT + + ret = m_jpegMain->encode(); + if (ret) { + JPEG_ERROR_LOG("encode failed\n"); + return ret; + } + + int iJpegSize = m_jpegMain->getJpegSize(); + + if (iJpegSize<=0) { + JPEG_ERROR_LOG("%s:: output_size is too small(%d)!!\n", __func__, iJpegSize); + return ERROR_OUT_BUFFER_SIZE_TOO_SMALL; + } + + int iOutputSize = 0; + char *pcJpegBuffer = m_jpegMain->getOutBuf(&iOutputSize); + + if (pcJpegBuffer == NULL) { + JPEG_ERROR_LOG("%s::buffer is null!!\n", __func__); + return ERROR_OUT_BUFFER_CREATE_FAIL; + } + + if (exifInfo != NULL) { + unsigned int thumbLen, exifLen; + + unsigned int bufSize = 0; + if (exifInfo->enableThumb) { + if (encodeThumbnail(&thumbLen)) { + bufSize = EXIF_FILE_SIZE; + exifInfo->enableThumb = false; + } else { + if (thumbLen > EXIF_LIMIT_SIZE) { + bufSize = EXIF_FILE_SIZE; + exifInfo->enableThumb = false; + } + else { + bufSize = EXIF_FILE_SIZE + thumbLen; + } + } + } else { + bufSize = EXIF_FILE_SIZE; + exifInfo->enableThumb = false; + } + + exifOut = new unsigned char[bufSize]; + if (exifOut == NULL) { + JPEG_ERROR_LOG("%s::Failed to allocate for exifOut", __func__); + delete[] exifOut; + return ERROR_EXIFOUT_ALLOC_FAIL; + } + memset(exifOut, 0, bufSize); + + if (makeExif (exifOut, exifInfo, &exifLen)) { + JPEG_ERROR_LOG("%s::Failed to make EXIF", __func__); + delete[] exifOut; + return ERROR_MAKE_EXIF_FAIL; + } + + if (exifLen <= EXIF_LIMIT_SIZE) { + memmove(pcJpegBuffer+exifLen+2, pcJpegBuffer+2, iJpegSize - 2); + memcpy(pcJpegBuffer+2, exifOut, exifLen); + iJpegSize += exifLen; + } + + delete[] exifOut; + } + + *size = iJpegSize; + + return ERROR_NONE; +} + +int SecJpegEncoder::makeExif (unsigned char *exifOut, + exif_attribute_t *exifInfo, + unsigned int *size, + bool useMainbufForThumb) +{ + unsigned char *pCur, *pApp1Start, *pIfdStart, *pGpsIfdPtr, *pNextIfdOffset; + unsigned int tmp, LongerTagOffest = 0, exifSizeExceptThumb; + pApp1Start = pCur = exifOut; + + //2 Exif Identifier Code & TIFF Header + pCur += 4; // Skip 4 Byte for APP1 marker and length + unsigned char ExifIdentifierCode[6] = { 0x45, 0x78, 0x69, 0x66, 0x00, 0x00 }; + memcpy(pCur, ExifIdentifierCode, 6); + pCur += 6; + + /* Byte Order - little endian, Offset of IFD - 0x00000008.H */ + unsigned char TiffHeader[8] = { 0x49, 0x49, 0x2A, 0x00, 0x08, 0x00, 0x00, 0x00 }; + memcpy(pCur, TiffHeader, 8); + pIfdStart = pCur; + pCur += 8; + + //2 0th IFD TIFF Tags + if (exifInfo->enableGps) + tmp = NUM_0TH_IFD_TIFF; + else + tmp = NUM_0TH_IFD_TIFF - 1; + + memcpy(pCur, &tmp, NUM_SIZE); + pCur += NUM_SIZE; + + LongerTagOffest += 8 + NUM_SIZE + tmp*IFD_SIZE + OFFSET_SIZE; + + writeExifIfd(&pCur, EXIF_TAG_IMAGE_WIDTH, EXIF_TYPE_LONG, + 1, exifInfo->width); + writeExifIfd(&pCur, EXIF_TAG_IMAGE_HEIGHT, EXIF_TYPE_LONG, + 1, exifInfo->height); + writeExifIfd(&pCur, EXIF_TAG_MAKE, EXIF_TYPE_ASCII, + strlen((char *)exifInfo->maker) + 1, exifInfo->maker, &LongerTagOffest, pIfdStart); + writeExifIfd(&pCur, EXIF_TAG_MODEL, EXIF_TYPE_ASCII, + strlen((char *)exifInfo->model) + 1, exifInfo->model, &LongerTagOffest, pIfdStart); + writeExifIfd(&pCur, EXIF_TAG_ORIENTATION, EXIF_TYPE_SHORT, + 1, exifInfo->orientation); + writeExifIfd(&pCur, EXIF_TAG_SOFTWARE, EXIF_TYPE_ASCII, + strlen((char *)exifInfo->software) + 1, exifInfo->software, &LongerTagOffest, pIfdStart); + writeExifIfd(&pCur, EXIF_TAG_DATE_TIME, EXIF_TYPE_ASCII, + 20, exifInfo->date_time, &LongerTagOffest, pIfdStart); + writeExifIfd(&pCur, EXIF_TAG_YCBCR_POSITIONING, EXIF_TYPE_SHORT, + 1, exifInfo->ycbcr_positioning); + writeExifIfd(&pCur, EXIF_TAG_EXIF_IFD_POINTER, EXIF_TYPE_LONG, + 1, LongerTagOffest); + if (exifInfo->enableGps) { + pGpsIfdPtr = pCur; + pCur += IFD_SIZE; // Skip a ifd size for gps IFD pointer + } + + pNextIfdOffset = pCur; // Skip a offset size for next IFD offset + pCur += OFFSET_SIZE; + + //2 0th IFD Exif Private Tags + pCur = pIfdStart + LongerTagOffest; + + tmp = NUM_0TH_IFD_EXIF; + memcpy(pCur, &tmp , NUM_SIZE); + pCur += NUM_SIZE; + + LongerTagOffest += NUM_SIZE + NUM_0TH_IFD_EXIF*IFD_SIZE + OFFSET_SIZE; + + writeExifIfd(&pCur, EXIF_TAG_EXPOSURE_TIME, EXIF_TYPE_RATIONAL, + 1, &exifInfo->exposure_time, &LongerTagOffest, pIfdStart); + writeExifIfd(&pCur, EXIF_TAG_FNUMBER, EXIF_TYPE_RATIONAL, + 1, &exifInfo->fnumber, &LongerTagOffest, pIfdStart); + writeExifIfd(&pCur, EXIF_TAG_EXPOSURE_PROGRAM, EXIF_TYPE_SHORT, + 1, exifInfo->exposure_program); + writeExifIfd(&pCur, EXIF_TAG_ISO_SPEED_RATING, EXIF_TYPE_SHORT, + 1, exifInfo->iso_speed_rating); + writeExifIfd(&pCur, EXIF_TAG_EXIF_VERSION, EXIF_TYPE_UNDEFINED, + 4, exifInfo->exif_version); + writeExifIfd(&pCur, EXIF_TAG_DATE_TIME_ORG, EXIF_TYPE_ASCII, + 20, exifInfo->date_time, &LongerTagOffest, pIfdStart); + writeExifIfd(&pCur, EXIF_TAG_DATE_TIME_DIGITIZE, EXIF_TYPE_ASCII, + 20, exifInfo->date_time, &LongerTagOffest, pIfdStart); + writeExifIfd(&pCur, EXIF_TAG_SHUTTER_SPEED, EXIF_TYPE_SRATIONAL, + 1, (rational_t *)&exifInfo->shutter_speed, &LongerTagOffest, pIfdStart); + writeExifIfd(&pCur, EXIF_TAG_APERTURE, EXIF_TYPE_RATIONAL, + 1, &exifInfo->aperture, &LongerTagOffest, pIfdStart); + writeExifIfd(&pCur, EXIF_TAG_BRIGHTNESS, EXIF_TYPE_SRATIONAL, + 1, (rational_t *)&exifInfo->brightness, &LongerTagOffest, pIfdStart); + writeExifIfd(&pCur, EXIF_TAG_EXPOSURE_BIAS, EXIF_TYPE_SRATIONAL, + 1, (rational_t *)&exifInfo->exposure_bias, &LongerTagOffest, pIfdStart); + writeExifIfd(&pCur, EXIF_TAG_MAX_APERTURE, EXIF_TYPE_RATIONAL, + 1, &exifInfo->max_aperture, &LongerTagOffest, pIfdStart); + writeExifIfd(&pCur, EXIF_TAG_METERING_MODE, EXIF_TYPE_SHORT, + 1, exifInfo->metering_mode); + writeExifIfd(&pCur, EXIF_TAG_FLASH, EXIF_TYPE_SHORT, + 1, exifInfo->flash); + writeExifIfd(&pCur, EXIF_TAG_FOCAL_LENGTH, EXIF_TYPE_RATIONAL, + 1, &exifInfo->focal_length, &LongerTagOffest, pIfdStart); + char code[8] = { 0x00, 0x00, 0x00, 0x49, 0x49, 0x43, 0x53, 0x41 }; + int commentsLen = strlen((char *)exifInfo->user_comment) + 1; + memmove(exifInfo->user_comment + sizeof(code), exifInfo->user_comment, commentsLen); + memcpy(exifInfo->user_comment, code, sizeof(code)); + writeExifIfd(&pCur, EXIF_TAG_USER_COMMENT, EXIF_TYPE_UNDEFINED, + commentsLen + sizeof(code), exifInfo->user_comment, &LongerTagOffest, pIfdStart); + writeExifIfd(&pCur, EXIF_TAG_COLOR_SPACE, EXIF_TYPE_SHORT, + 1, exifInfo->color_space); + writeExifIfd(&pCur, EXIF_TAG_PIXEL_X_DIMENSION, EXIF_TYPE_LONG, + 1, exifInfo->width); + writeExifIfd(&pCur, EXIF_TAG_PIXEL_Y_DIMENSION, EXIF_TYPE_LONG, + 1, exifInfo->height); + writeExifIfd(&pCur, EXIF_TAG_EXPOSURE_MODE, EXIF_TYPE_LONG, + 1, exifInfo->exposure_mode); + writeExifIfd(&pCur, EXIF_TAG_WHITE_BALANCE, EXIF_TYPE_LONG, + 1, exifInfo->white_balance); + writeExifIfd(&pCur, EXIF_TAG_SCENCE_CAPTURE_TYPE, EXIF_TYPE_LONG, + 1, exifInfo->scene_capture_type); + tmp = 0; + memcpy(pCur, &tmp, OFFSET_SIZE); // next IFD offset + pCur += OFFSET_SIZE; + + //2 0th IFD GPS Info Tags + if (exifInfo->enableGps) { + writeExifIfd(&pGpsIfdPtr, EXIF_TAG_GPS_IFD_POINTER, EXIF_TYPE_LONG, + 1, LongerTagOffest); // GPS IFD pointer skipped on 0th IFD + + pCur = pIfdStart + LongerTagOffest; + + if (exifInfo->gps_processing_method[0] == 0) { + // don't create GPS_PROCESSING_METHOD tag if there isn't any + tmp = NUM_0TH_IFD_GPS - 1; + } else { + tmp = NUM_0TH_IFD_GPS; + } + memcpy(pCur, &tmp, NUM_SIZE); + pCur += NUM_SIZE; + + LongerTagOffest += NUM_SIZE + tmp*IFD_SIZE + OFFSET_SIZE; + + writeExifIfd(&pCur, EXIF_TAG_GPS_VERSION_ID, EXIF_TYPE_BYTE, + 4, exifInfo->gps_version_id); + writeExifIfd(&pCur, EXIF_TAG_GPS_LATITUDE_REF, EXIF_TYPE_ASCII, + 2, exifInfo->gps_latitude_ref); + writeExifIfd(&pCur, EXIF_TAG_GPS_LATITUDE, EXIF_TYPE_RATIONAL, + 3, exifInfo->gps_latitude, &LongerTagOffest, pIfdStart); + writeExifIfd(&pCur, EXIF_TAG_GPS_LONGITUDE_REF, EXIF_TYPE_ASCII, + 2, exifInfo->gps_longitude_ref); + writeExifIfd(&pCur, EXIF_TAG_GPS_LONGITUDE, EXIF_TYPE_RATIONAL, + 3, exifInfo->gps_longitude, &LongerTagOffest, pIfdStart); + writeExifIfd(&pCur, EXIF_TAG_GPS_ALTITUDE_REF, EXIF_TYPE_BYTE, + 1, exifInfo->gps_altitude_ref); + writeExifIfd(&pCur, EXIF_TAG_GPS_ALTITUDE, EXIF_TYPE_RATIONAL, + 1, &exifInfo->gps_altitude, &LongerTagOffest, pIfdStart); + writeExifIfd(&pCur, EXIF_TAG_GPS_TIMESTAMP, EXIF_TYPE_RATIONAL, + 3, exifInfo->gps_timestamp, &LongerTagOffest, pIfdStart); + tmp = strlen((char*)exifInfo->gps_processing_method); + if (tmp > 0) { + if (tmp > 100) { + tmp = 100; + } + unsigned char tmp_buf[100+sizeof(ExifAsciiPrefix)]; + memcpy(tmp_buf, ExifAsciiPrefix, sizeof(ExifAsciiPrefix)); + memcpy(&tmp_buf[sizeof(ExifAsciiPrefix)], exifInfo->gps_processing_method, tmp); + writeExifIfd(&pCur, EXIF_TAG_GPS_PROCESSING_METHOD, EXIF_TYPE_UNDEFINED, + tmp+sizeof(ExifAsciiPrefix), tmp_buf, &LongerTagOffest, pIfdStart); + } + writeExifIfd(&pCur, EXIF_TAG_GPS_DATESTAMP, EXIF_TYPE_ASCII, + 11, exifInfo->gps_datestamp, &LongerTagOffest, pIfdStart); + tmp = 0; + memcpy(pCur, &tmp, OFFSET_SIZE); // next IFD offset + pCur += OFFSET_SIZE; + } + + //2 1th IFD TIFF Tags + char *thumbBuf = NULL; + unsigned int thumbSize = 0; + + if (useMainbufForThumb) { + if (m_jpegMain) { + thumbBuf = m_jpegMain->getOutBuf((int *)&thumbSize); + thumbSize = m_jpegMain->getJpegSize(); + } + } else { + if (m_jpegThumb) { + thumbBuf = m_jpegThumb->getOutBuf((int *)&thumbSize); + thumbSize = m_jpegThumb->getJpegSize(); + } + } + + if (exifInfo->enableThumb && (thumbBuf != NULL) && (thumbSize != 0)) { + exifSizeExceptThumb = tmp = LongerTagOffest; + memcpy(pNextIfdOffset, &tmp, OFFSET_SIZE); // NEXT IFD offset skipped on 0th IFD + + pCur = pIfdStart + LongerTagOffest; + + tmp = NUM_1TH_IFD_TIFF; + memcpy(pCur, &tmp, NUM_SIZE); + pCur += NUM_SIZE; + + LongerTagOffest += NUM_SIZE + NUM_1TH_IFD_TIFF*IFD_SIZE + OFFSET_SIZE; + + writeExifIfd(&pCur, EXIF_TAG_IMAGE_WIDTH, EXIF_TYPE_LONG, + 1, exifInfo->widthThumb); + writeExifIfd(&pCur, EXIF_TAG_IMAGE_HEIGHT, EXIF_TYPE_LONG, + 1, exifInfo->heightThumb); + writeExifIfd(&pCur, EXIF_TAG_COMPRESSION_SCHEME, EXIF_TYPE_SHORT, + 1, exifInfo->compression_scheme); + writeExifIfd(&pCur, EXIF_TAG_ORIENTATION, EXIF_TYPE_SHORT, + 1, exifInfo->orientation); + writeExifIfd(&pCur, EXIF_TAG_X_RESOLUTION, EXIF_TYPE_RATIONAL, + 1, &exifInfo->x_resolution, &LongerTagOffest, pIfdStart); + writeExifIfd(&pCur, EXIF_TAG_Y_RESOLUTION, EXIF_TYPE_RATIONAL, + 1, &exifInfo->y_resolution, &LongerTagOffest, pIfdStart); + writeExifIfd(&pCur, EXIF_TAG_RESOLUTION_UNIT, EXIF_TYPE_SHORT, + 1, exifInfo->resolution_unit); + writeExifIfd(&pCur, EXIF_TAG_JPEG_INTERCHANGE_FORMAT, EXIF_TYPE_LONG, + 1, LongerTagOffest); + writeExifIfd(&pCur, EXIF_TAG_JPEG_INTERCHANGE_FORMAT_LEN, EXIF_TYPE_LONG, + 1, thumbSize); + + tmp = 0; + memcpy(pCur, &tmp, OFFSET_SIZE); // next IFD offset + pCur += OFFSET_SIZE; + + memcpy(pIfdStart + LongerTagOffest, + thumbBuf, thumbSize); + LongerTagOffest += thumbSize; + if (LongerTagOffest > EXIF_LIMIT_SIZE) { + LongerTagOffest = exifSizeExceptThumb; + tmp = 0; + memcpy(pNextIfdOffset, &tmp, OFFSET_SIZE); // NEXT IFD offset skipped on 0th IFD + } + } else { + tmp = 0; + memcpy(pNextIfdOffset, &tmp, OFFSET_SIZE); // NEXT IFD offset skipped on 0th IFD + } + + unsigned char App1Marker[2] = { 0xff, 0xe1 }; + memcpy(pApp1Start, App1Marker, 2); + pApp1Start += 2; + + *size = 10 + LongerTagOffest; + tmp = *size - 2; // APP1 Maker isn't counted + unsigned char size_mm[2] = {(tmp >> 8) & 0xFF, tmp & 0xFF}; + memcpy(pApp1Start, size_mm, 2); + + return ERROR_NONE; +} + +/* + * private member functions +*/ +inline void SecJpegEncoder::writeExifIfd(unsigned char **pCur, + unsigned short tag, + unsigned short type, + unsigned int count, + unsigned int value) +{ + memcpy(*pCur, &tag, 2); + *pCur += 2; + memcpy(*pCur, &type, 2); + *pCur += 2; + memcpy(*pCur, &count, 4); + *pCur += 4; + memcpy(*pCur, &value, 4); + *pCur += 4; +} + +inline void SecJpegEncoder::writeExifIfd(unsigned char **pCur, + unsigned short tag, + unsigned short type, + unsigned int count, + unsigned char *pValue) +{ + char buf[4] = { 0,}; + + memcpy(buf, pValue, count); + memcpy(*pCur, &tag, 2); + *pCur += 2; + memcpy(*pCur, &type, 2); + *pCur += 2; + memcpy(*pCur, &count, 4); + *pCur += 4; + memcpy(*pCur, buf, 4); + *pCur += 4; +} + +inline void SecJpegEncoder::writeExifIfd(unsigned char **pCur, + unsigned short tag, + unsigned short type, + unsigned int count, + unsigned char *pValue, + unsigned int *offset, + unsigned char *start) +{ + memcpy(*pCur, &tag, 2); + *pCur += 2; + memcpy(*pCur, &type, 2); + *pCur += 2; + memcpy(*pCur, &count, 4); + *pCur += 4; + memcpy(*pCur, offset, 4); + *pCur += 4; + memcpy(start + *offset, pValue, count); + *offset += count; +} + +inline void SecJpegEncoder::writeExifIfd(unsigned char **pCur, + unsigned short tag, + unsigned short type, + unsigned int count, + rational_t *pValue, + unsigned int *offset, + unsigned char *start) +{ + memcpy(*pCur, &tag, 2); + *pCur += 2; + memcpy(*pCur, &type, 2); + *pCur += 2; + memcpy(*pCur, &count, 4); + *pCur += 4; + memcpy(*pCur, offset, 4); + *pCur += 4; + memcpy(start + *offset, pValue, 8 * count); + *offset += 8 * count; +} + +int SecJpegEncoder::m_scaleDownYuv422(char *srcBuf, unsigned int srcW, unsigned int srcH, + char *dstBuf, unsigned int dstW, unsigned int dstH) +{ + int step_x, step_y; + int iXsrc, iXdst; + int x, y, src_y_start_pos, dst_pos, src_pos; + + if (dstW & 0x01 || dstH & 0x01) { + return ERROR_INVALID_SCALING_WIDTH_HEIGHT; + } + + step_x = srcW / dstW; + step_y = srcH / dstH; + + unsigned int srcWStride = srcW * 2; + unsigned int stepXStride = step_x * 2; + + dst_pos = 0; + for (unsigned int y = 0; y < dstH; y++) { + src_y_start_pos = srcWStride * step_y * y; + + for (unsigned int x = 0; x < dstW; x += 2) { + src_pos = src_y_start_pos + (stepXStride * x); + + dstBuf[dst_pos++] = srcBuf[src_pos ]; + dstBuf[dst_pos++] = srcBuf[src_pos + 1]; + dstBuf[dst_pos++] = srcBuf[src_pos + 2]; + dstBuf[dst_pos++] = srcBuf[src_pos + 3]; + } + } + + return ERROR_NONE; +} + +// thumbnail +int SecJpegEncoder::setThumbnailSize(int w, int h) +{ + if (m_flagCreate == false) { + return ERROR_CANNOT_CREATE_SEC_JPEG_ENC_HAL; + } + + if (w < 0 || MAX_JPG_WIDTH < w) { + return false; + } + + if (h < 0 || MAX_JPG_HEIGHT < h) { + return false; + } + + m_thumbnailW = w; + m_thumbnailH = h; + return ERROR_NONE; +} + + +int SecJpegEncoder::encodeThumbnail(unsigned int *size, bool useMain) +{ + int ret = ERROR_NONE; + + if (m_flagCreate == false) { + return ERROR_CANNOT_CREATE_SEC_JPEG_ENC_HAL; + } + + // create jpeg thumbnail class + if (m_jpegThumb == NULL) { + m_jpegThumb = new SecJpegEncoderHal; + + if (m_jpegThumb == NULL) { + JPEG_ERROR_LOG("ERR(%s):Cannot open a jpeg device file\n", __func__); + return ERROR_CANNOT_CREATE_SEC_THUMB; + } + } + + ret = m_jpegThumb->create(); + if (ret) { + JPEG_ERROR_LOG("ERR(%s):Fail create\n", __func__); + return ret; + } + + ret = m_jpegThumb->setCache(JPEG_CACHE_ON); + if (ret) { + JPEG_ERROR_LOG("ERR(%s):Fail cache set\n", __func__); + return ret; + } + + void *pConfig = m_jpegMain->getJpegConfig(); + if (pConfig == NULL) { + JPEG_ERROR_LOG("ERR(%s):Fail getJpegConfig\n", __func__); + return ERROR_BUFFR_IS_NULL; + } + + ret = m_jpegThumb->setJpegConfig(pConfig); + if (ret) { + JPEG_ERROR_LOG("ERR(%s):Fail setJpegConfig\n", __func__); + return ret; + } + + ret = m_jpegThumb->setQuality(JPEG_THUMBNAIL_QUALITY); + if (ret) { + JPEG_ERROR_LOG("ERR(%s):Fail setQuality\n", __func__); + return ret; + } + + ret = m_jpegThumb->setSize(m_thumbnailW, m_thumbnailH); + if (ret) { + JPEG_ERROR_LOG("ERR(%s):Fail setSize\n", __func__); + return ret; + } + + int iThumbSize = sizeof(char)*m_thumbnailW*m_thumbnailH*4; +#ifdef JPEG_WA_FOR_PAGEFAULT + iThumbSize += JPEG_WA_BUFFER_SIZE; +#endif //JPEG_WA_FOR_PAGEFAULT + + freeJpegIonMemory(m_ionJpegClient, &m_ionThumbInBuffer, &m_pThumbInputBuffer, iThumbSize); + freeJpegIonMemory(m_ionJpegClient, &m_ionThumbOutBuffer, &m_pThumbOutputBuffer, iThumbSize); + + if (m_ionJpegClient == 0) { + m_ionJpegClient = ion_client_create(); + if (m_ionJpegClient < 0) { + JPEG_ERROR_LOG("[%s]src ion client create failed, value = %d\n", __func__, m_ionJpegClient); + m_ionJpegClient = 0; + return ret; + } + } + + ret = allocJpegIonMemory(m_ionJpegClient, &m_ionThumbInBuffer, &m_pThumbInputBuffer, iThumbSize); + if (ret != ERROR_NONE) { + return ret; + } + + ret = m_jpegThumb->setInBuf(&m_pThumbInputBuffer, &iThumbSize); + if (ret) { + JPEG_ERROR_LOG("ERR(%s):Fail setInBuf\n", __func__); + return ret; + } + + ret = allocJpegIonMemory(m_ionJpegClient, &m_ionThumbOutBuffer, &m_pThumbOutputBuffer, iThumbSize); + if (ret != ERROR_NONE) { + return ret; + } + + ret = m_jpegThumb->setOutBuf((char *)m_pThumbOutputBuffer, iThumbSize); + if (ret) { + JPEG_ERROR_LOG("ERR(%s):Fail setOutBuf\n", __func__); + return ret; + } + + ret = m_jpegThumb->updateConfig(); + if (ret) { + JPEG_ERROR_LOG("update config failed\n"); + return ret; + } + + if (useMain) { + + int iW=0, iH=0; + int input_sizeMain=0, input_sizeThumb=0; + + ret = m_jpegMain->getSize(&iW, &iH); + if (ret) { + JPEG_ERROR_LOG("ERR(%s):Fail setJpegConfig\n", __func__); + return ret; + } + + ret = m_scaleDownYuv422(*(m_jpegMain->getInBuf(&input_sizeMain)), + iW, + iH, + *(m_jpegThumb->getInBuf(&input_sizeThumb)), + m_thumbnailW, + m_thumbnailH); + if (ret) { + JPEG_ERROR_LOG("%s::m_scaleDownYuv422(%d, %d, %d, %d) fail", __func__, iW, iH, m_thumbnailW, m_thumbnailH); + return ret; + } + } + else { + return ERROR_IMPLEMENT_NOT_YET; + } + + int outSizeThumb; + + ret = m_jpegThumb->encode(); + if (ret) { + JPEG_ERROR_LOG("encode failed\n"); + return ret; + } + + outSizeThumb = m_jpegThumb->getJpegSize(); + if (outSizeThumb<=0) { + JPEG_ERROR_LOG("jpeg size is too small\n"); + return ERROR_THUMB_JPEG_SIZE_TOO_SMALL; + } + + *size = (unsigned int)outSizeThumb; + + return ERROR_NONE; + +} + +int SecJpegEncoder::allocJpegIonMemory(ion_client ionClient, ion_buffer *ionBuffer, char **buffer, int size) +{ + int ret = ERROR_NONE; + + if (ionClient == 0) { + JPEG_ERROR_LOG("[%s]ionClient is zero (%d)\n", __func__, ionClient); + return ERROR_BUFFR_IS_NULL; + } + + *ionBuffer = ion_alloc(ionClient, size, 0, ION_HEAP_SYSTEM_MASK); + if (*ionBuffer == -1) { + JPEG_ERROR_LOG("[%s]ion_alloc(%d) failed\n", __func__, size); + *ionBuffer = 0; + return ret; + } + + *buffer = (char *)ion_map(*ionBuffer, size, 0); + if (*buffer == MAP_FAILED) { + JPEG_ERROR_LOG("[%s]src ion map failed(%d)\n", __func__, size); + ion_free(*ionBuffer); + *ionBuffer = 0; + *buffer = NULL; + return ret; + } + + return ret; +} + +void SecJpegEncoder::freeJpegIonMemory(ion_client ionClient, ion_buffer *ionBuffer, char **buffer, int size) +{ + if (ionClient == 0) { + return; + } + + if (*buffer != NULL) { + ion_unmap(*buffer, size); + *buffer = NULL; + } + + if (*ionBuffer != 0) { + ion_free(*ionBuffer); + *ionBuffer = 0; + } +} + diff --git a/exynos5/hal/libhwjpeg/SecJpegEncoderHal.cpp b/exynos5/hal/libhwjpeg/SecJpegEncoderHal.cpp new file mode 100644 index 0000000..1a3deca --- /dev/null +++ b/exynos5/hal/libhwjpeg/SecJpegEncoderHal.cpp @@ -0,0 +1,497 @@ +/* + * Copyright Samsung Electronics Co.,LTD. + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include "SecJpegCodecHal.h" + +#define JPEG_ERROR_LOG(fmt,...) + +#define NUM_PLANES (1) +#define NUM_BUFFERS (1) + +SecJpegEncoderHal::SecJpegEncoderHal() +{ + t_iJpegFd = -1; + t_bFlagCreate = false; +} + +SecJpegEncoderHal::~SecJpegEncoderHal() +{ + if (t_bFlagCreate == true) { + this->destroy(); + } +} + +int SecJpegEncoderHal::create(void) +{ + if (t_bFlagCreate == true) { + return ERROR_JPEG_DEVICE_ALREADY_CREATE; + } + + int iRet = ERROR_NONE; + + t_iJpegFd = open(JPEG_ENC_NODE, O_RDWR, 0); + + if (t_iJpegFd < 0) { + t_iJpegFd = -1; + JPEG_ERROR_LOG("[%s]: JPEG_ENC_NODE open failed", __func__); + return ERROR_CANNOT_OPEN_JPEG_DEVICE; + } + + if (t_iJpegFd <= 0) { + t_iJpegFd = -1; + JPEG_ERROR_LOG("ERR(%s):JPEG device was closed\n", __func__); + return ERROR_JPEG_DEVICE_ALREADY_CLOSED; + } + + iRet = t_v4l2Querycap(t_iJpegFd); + if (iRet < 0) { + JPEG_ERROR_LOG("[%s]: QUERYCAP failed", __func__); + close(t_iJpegFd); + return ERROR_CANNOT_OPEN_JPEG_DEVICE; + } + + memset(&t_stJpegConfig, 0, sizeof(struct CONFIG)); + memset(&t_stJpegInbuf, 0, sizeof(struct BUFFER)); + memset(&t_stJpegOutbuf, 0, sizeof(struct BUFFER)); + + t_stJpegConfig.mode = MODE_ENCODE; + + t_bFlagCreate = true; + t_bFlagCreateInBuf = false; + t_bFlagCreateOutBuf = false; + t_bFlagExcute = false; + + t_iPlaneNum = 0; + + return ERROR_NONE; +} + +int SecJpegEncoderHal::destroy(void) +{ + if (t_bFlagCreate == false) { + return ERROR_JPEG_DEVICE_ALREADY_DESTROY; + } + + if (t_iJpegFd > 0) { + struct BUF_INFO stBufInfo; + int iRet = ERROR_NONE; + + if (t_bFlagExcute) { + iRet = t_v4l2StreamOff(t_iJpegFd, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); + } + + if (t_bFlagExcute) { + stBufInfo.numOfPlanes = t_iPlaneNum; + stBufInfo.memory = V4L2_MEMORY_MMAP; + + stBufInfo.buf_type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; + iRet = t_v4l2Reqbufs(t_iJpegFd, 0, &stBufInfo); + + stBufInfo.numOfPlanes = NUM_PLANES; + stBufInfo.buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; + iRet = t_v4l2Reqbufs(t_iJpegFd, 0, &stBufInfo); + } + + iRet = close(t_iJpegFd); + } + + t_iJpegFd = -1; + t_bFlagCreate = false; + return ERROR_NONE; +} + +int SecJpegEncoderHal::setSize(int iW, int iH) +{ + if (t_bFlagCreate == false) { + return ERROR_JPEG_DEVICE_NOT_CREATE_YET; + } + + if (iW < 0 || MAX_JPG_WIDTH < iW) { + return ERROR_INVALID_IMAGE_SIZE; + } + + if (iH < 0 || MAX_JPG_HEIGHT < iH) { + return ERROR_INVALID_IMAGE_SIZE; + } + + t_stJpegConfig.width = iW; + t_stJpegConfig.height = iH; + + return ERROR_NONE; +} + +int SecJpegEncoderHal::setJpegConfig(void *pConfig) +{ + if (t_bFlagCreate == false) { + return ERROR_JPEG_DEVICE_NOT_CREATE_YET; + } + + if (pConfig == NULL) { + return ERROR_JPEG_CONFIG_POINTER_NULL; + } + + memcpy(&t_stJpegConfig, pConfig, sizeof(struct CONFIG)); + + if (t_stJpegConfig.pix.enc_fmt.in_fmt == V4L2_PIX_FMT_NV12) { + t_iPlaneNum = 2; + } else { + t_iPlaneNum = 1; + } + + return ERROR_NONE; +} + +void *SecJpegEncoderHal::getJpegConfig(void) +{ + if (t_bFlagCreate == false) { + return NULL; + } + + return &t_stJpegConfig; +} + +char **SecJpegEncoderHal::getInBuf(int *piInputSize) +{ + if (t_bFlagCreate == false) { + return NULL; + } + + if (t_bFlagCreateInBuf == false) { + + *piInputSize = 0; + return NULL; + } + + for (int i=0;i= 90) + t_stJpegConfig.enc_qual = QUALITY_LEVEL_1; + else if (iV4l2Quality >= 80) + t_stJpegConfig.enc_qual = QUALITY_LEVEL_2; + else if (iV4l2Quality >= 70) + t_stJpegConfig.enc_qual = QUALITY_LEVEL_3; + else + t_stJpegConfig.enc_qual = QUALITY_LEVEL_4; + + return ERROR_NONE; +} + +int SecJpegEncoderHal::getJpegSize(void) +{ + if (t_bFlagCreate == false) { + return 0; + } + + int iSize = t_v4l2GetCtrl(t_iJpegFd, V4L2_CID_CAM_JPEG_ENCODEDSIZE); + + if (iSize < 0) { + JPEG_ERROR_LOG("%s::Fail to JPEG output buffer!!\n", __func__); + return 0; + } + + return iSize; +} + +int SecJpegEncoderHal::encode(void) +{ + if (t_bFlagCreate == false) { + return ERROR_JPEG_DEVICE_NOT_CREATE_YET; + } + + struct BUF_INFO stBufInfo; + int iRet = ERROR_NONE; + + t_bFlagExcute = true; + + stBufInfo.numOfPlanes = t_iPlaneNum; + stBufInfo.buf_type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; + + stBufInfo.memory = V4L2_MEMORY_USERPTR; + + iRet = t_v4l2Qbuf(t_iJpegFd, &stBufInfo, &t_stJpegInbuf); + if (iRet < 0) { + JPEG_ERROR_LOG("[%s:%d]: Input QBUF failed", __func__, iRet); + return ERROR_EXCUTE_FAIL; + } + + stBufInfo.numOfPlanes = NUM_PLANES; + stBufInfo.buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; + + iRet = t_v4l2Qbuf(t_iJpegFd, &stBufInfo, &t_stJpegOutbuf); + if (iRet < 0) { + JPEG_ERROR_LOG("[%s:%d]: Output QBUF failed", __func__, iRet); + return ERROR_EXCUTE_FAIL; + } + + stBufInfo.numOfPlanes = t_iPlaneNum; + iRet = t_v4l2StreamOn(t_iJpegFd, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); + if (iRet < 0) { + JPEG_ERROR_LOG("[%s:%d]: input stream on failed", __func__, iRet); + return ERROR_EXCUTE_FAIL; + } + stBufInfo.numOfPlanes = NUM_PLANES; + iRet = t_v4l2StreamOn(t_iJpegFd, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); + if (iRet < 0) { + JPEG_ERROR_LOG("[%s:%d]: output stream on failed", __func__, iRet); + return ERROR_EXCUTE_FAIL; + } + + stBufInfo.numOfPlanes = t_iPlaneNum; + iRet = t_v4l2Dqbuf(t_iJpegFd, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, V4L2_MEMORY_MMAP); + if (iRet < 0) { + JPEG_ERROR_LOG("[%s:%d]: Intput DQBUF failed", __func__, iRet); + return ERROR_EXCUTE_FAIL; + } + stBufInfo.numOfPlanes = NUM_PLANES; + iRet = t_v4l2Dqbuf(t_iJpegFd, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, V4L2_MEMORY_MMAP); + if (iRet < 0) { + JPEG_ERROR_LOG("[%s:%d]: Output DQBUF failed", __func__, iRet); + return ERROR_EXCUTE_FAIL; + } + return ERROR_NONE; +} +