diff --git a/adapter/khdf/linux/model/display/Makefile b/adapter/khdf/linux/model/display/Makefile index c990ef9daba2e05b8bdcf09ee11ff5792cef92d7..990488f40eadecdc4c273fde2f1cb1526f647635 100644 --- a/adapter/khdf/linux/model/display/Makefile +++ b/adapter/khdf/linux/model/display/Makefile @@ -45,6 +45,8 @@ obj-$(CONFIG_DRIVERS_HDF_LCD_ST7789) += \ $(DISPLAY_ROOT_DIR)/panel/ssp_st7789.o obj-$(CONFIG_ARCH_ROCKCHIP) += \ $(DISPLAY_ROOT_DIR)/panel/ili9881_st_5p5.o +obj-$(CONFIG_DRIVERS_HDF_PLATFORM_EDP) += \ + $(DISPLAY_ROOT_DIR)/panel/lcd_edp.o ccflags-y += -lm -lc -lgcc \ -I$(srctree)/drivers/hdf/framework/model/display/driver \ diff --git a/adapter/khdf/linux/platform/Kconfig b/adapter/khdf/linux/platform/Kconfig index eef06d38e3fd9e4d01dd2b3c392add73d9287026..f293fa99c782f0b7a60462158cdce80872f62574 100644 --- a/adapter/khdf/linux/platform/Kconfig +++ b/adapter/khdf/linux/platform/Kconfig @@ -170,3 +170,9 @@ config DRIVERS_HDF_PLATFORM_IMX8MM_MIPI_DSI help Answer Y to enable HDF platform imx8mm mipi_dsi driver. +config DRIVERS_HDF_PLATFORM_EDP + bool "Enable HDF platform display edp driver" + default y + depends on DRIVERS_HDF_PLATFORM + help + Answer Y to enable HDF platform display edp driver. diff --git a/adapter/khdf/linux/platform/Makefile b/adapter/khdf/linux/platform/Makefile index 690c5904651b48316ae99952fd6f7a76a02edb39..032899df8649d3be448f018104508710102d5328 100644 --- a/adapter/khdf/linux/platform/Makefile +++ b/adapter/khdf/linux/platform/Makefile @@ -25,3 +25,4 @@ obj-$(CONFIG_DRIVERS_HDF_PLATFORM_RTC) += rtc/ obj-$(CONFIG_DRIVERS_HDF_PLATFORM_ADC) += adc/ obj-$(CONFIG_DRIVERS_HDF_PLATFORM_CLOCK) += clock/ obj-$(CONFIG_DRIVERS_HDF_PLATFORM_REGULATOR) += regulator/ +obj-$(CONFIG_DRIVERS_HDF_PLATFORM_EDP) += edp/ diff --git a/adapter/khdf/linux/platform/edp/Makefile b/adapter/khdf/linux/platform/edp/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..70b1aea854ec31740b497a2e873feeab7e87428c --- /dev/null +++ b/adapter/khdf/linux/platform/edp/Makefile @@ -0,0 +1,25 @@ +# +# Copyright (c) 2023-2024 Huawei Device Co., Ltd. +# +# This software is licensed under the terms of the GNU General Public +# License version 2, as published by the Free Software Foundation, and +# may be copied, distributed, and modified under those terms. +# +# 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. +# +# +include drivers/hdf/khdf/platform/platform.mk + +obj-$(CONFIG_DRIVERS_HDF_PLATFORM_EDP) += \ + $(HDF_PLATFORM_FRAMEWORKS_ROOT)/src/edp/edp_core.o \ + $(HDF_PLATFORM_FRAMEWORKS_ROOT)/src/edp/edp_if.o \ + $(HDF_PLATFORM_FRAMEWORKS_ROOT)/src/edp/edp_dispatch.o \ + edp_adapter_impl.o \ + edp_analogix_reg.o \ + edp_rk35xx.o + +ccflags-$(CONFIG_DRIVERS_HDF_PLATFORM_EDP) += \ + -I$(KSRC)/include diff --git a/adapter/khdf/linux/platform/edp/edp_adapter_impl.c b/adapter/khdf/linux/platform/edp/edp_adapter_impl.c new file mode 100644 index 0000000000000000000000000000000000000000..b93181a2caa7882e9f35b88f7db954dc11950e38 --- /dev/null +++ b/adapter/khdf/linux/platform/edp/edp_adapter_impl.c @@ -0,0 +1,382 @@ +/* + * Copyright (c) 2023-2024 Huawei Device Co., Ltd. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * 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. + * + */ + +#include "osal.h" +#include "platform_if.h" +#include "platform_device.h" +#include "hdf_device_desc.h" +#include "device_resource_if.h" + +#include "edp_core.h" +#include "edp_if.h" +#include "edp_dispatch.h" +#include "securec.h" + +#include "edp_linux_def.h" + +#define HDF_LOG_TAG edp_adapter_impl + +static inline HdfEdpAdapterData *EdpAdapterPrivToEdpData(struct EdpCntlr *cntlr) +{ + if (cntlr == NULL) { + return NULL; + } + return (HdfEdpAdapterData *)cntlr->priv; +} + +static int32_t EdpAdapterDeepColorSet(struct EdpCntlr *cntlr, enum EdpColorDepth color) +{ + int32_t ret = -1; + HdfEdpAdapterData *edpAdapterData = EdpAdapterPrivToEdpData(cntlr); + if (edpAdapterData == NULL) { + HDF_LOGE("%s, edp priv data is null", __func__); + return ret; + } + + ret = LinuxEdpDeepColorSet(edpAdapterData, color); + return ret; +} + +static int32_t EdpAdapterDeepColorGet(struct EdpCntlr *cntlr, enum EdpColorDepth *color) +{ + int32_t ret = -1; + uint32_t colorGet = 0; + HdfEdpAdapterData *edpAdapterData = EdpAdapterPrivToEdpData(cntlr); + if (edpAdapterData == NULL) { + HDF_LOGE("%s, edp priv data is null", __func__); + return ret; + } + + ret = LinuxEdpDeepColorGet(edpAdapterData, &colorGet); + if (HDF_SUCCESS != ret) { + HDF_LOGE("%s, LinuxEdpDeepColorGet failed %d", __func__, ret); + return ret; + } + + *color = colorGet; + return ret; +} + +static int32_t EdpAdapterAvmuteSet(struct EdpCntlr *cntlr, bool enable) +{ + int32_t ret = HDF_FAILURE; + HdfEdpAdapterData *edpAdapterData = EdpAdapterPrivToEdpData(cntlr); + if (cntlr == NULL) { + HDF_LOGE("%s, invalid cntlr data\n", __func__); + return ret; + } + + HDF_LOGD("Audio Settings is not supported by eDP."); + ret = LinuxEdpAvMuteSet(edpAdapterData, enable); + return ret; +} + +static int32_t EdpAdapterSetVideoAttribute(struct EdpCntlr *cntlr, const struct EdpVideoAttr *attr) +{ + int32_t ret = -1; + HdfEdpAdapterData *edpAdapterData = EdpAdapterPrivToEdpData(cntlr); + if (cntlr == NULL || attr == NULL) { + HDF_LOGE("%s, invalid cntlr data\n", __func__); + return ret; + } + if (edpAdapterData == NULL) { + HDF_LOGE("%s, edp priv data is null", __func__); + return ret; + } + + ret = LinuxEdpSetVideoAttribute(edpAdapterData, (const void *)attr); + + return ret; +} + +static int32_t EdpAdapterSetAudioAttribute(struct EdpCntlr *cntlr, const struct EdpAudioAttr *attr) +{ + int32_t ret = HDF_FAILURE; + HdfEdpAdapterData *edpAdapterData = EdpAdapterPrivToEdpData(cntlr); + if (cntlr == NULL || attr == NULL) { + HDF_LOGE("%s, invalid cntlr data\n", __func__); + return ret; + } + HDF_LOGD("Audio Settings is not supported by eDP."); + ret = LinuxEdpSetAudioAttribute(edpAdapterData, attr); + return ret; +} + +static int32_t EdpAdapterRegisterHpdCallbackFunc(struct EdpCntlr *cntlr, struct EdpHpdCallbackInfo *callback) +{ + int32_t ret = HDF_FAILURE; + HdfEdpAdapterData *edpAdapterData = EdpAdapterPrivToEdpData(cntlr); + if (cntlr == NULL || callback == NULL) { + HDF_LOGE("%s, invalid cntlr data\n", __func__); + return ret; + } + + if (cntlr->hpdCbInfo != NULL) { + HDF_LOGE("%s, hpd callback has been registered!\n", __func__); + return HDF_ERR_INVALID_PARAM; + } + + ret = LinuxEdpRegisterHpdCallbackFunc(edpAdapterData, (void *)callback); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s, LinuxEdpRegisterHpdCallbackFunc failed\n", __func__); + return ret; + } + + cntlr->hpdCbInfo = (struct EdpHpdCallbackInfo *)OsalMemCalloc(sizeof(struct EdpHpdCallbackInfo)); + cntlr->hpdCbInfo->data = callback->data; + return HDF_SUCCESS; +} + +static int32_t EdpAdapterUnregisterHpdCallbackFunc(struct EdpCntlr *cntlr) +{ + int32_t ret = HDF_FAILURE; + HdfEdpAdapterData *edpAdapterData = EdpAdapterPrivToEdpData(cntlr); + if (cntlr == NULL) { + HDF_LOGE("%s, invalid cntlr data\n", __func__); + return ret; + } + ret = LinuxEdpUnRegisterHpdCallbackFunc(edpAdapterData); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s, LinuxEdpRegisterHpdCallbackFunc failed\n", __func__); + return ret; + } + + OsalMemFree(cntlr->hpdCbInfo); + cntlr->hpdCbInfo = NULL; + return HDF_SUCCESS; +} + +static int32_t EdpAdapterGetConnector(struct EdpCntlr *cntlr, DevHandle *connector) +{ + int32_t ret = HDF_FAILURE; + HdfEdpAdapterData *edpAdapterData = EdpAdapterPrivToEdpData(cntlr); + if (cntlr == NULL || connector == NULL) { + HDF_LOGE("%s, invalid cntlr data\n", __func__); + return ret; + } + + if (edpAdapterData == NULL) { + HDF_LOGE("%s, edp priv data is null", __func__); + return ret; + } + + ret = LinuxEdpGetConnector(edpAdapterData, (void **)connector); + return ret; +} + +static int32_t EdpAdapterEnable(struct EdpCntlr *cntlr) +{ + int32_t ret = HDF_FAILURE; + HdfEdpAdapterData *edpAdapterData = EdpAdapterPrivToEdpData(cntlr); + if (cntlr == NULL) { + HDF_LOGE("%s, invalid cntlr data\n", __func__); + return ret; + } + if (edpAdapterData == NULL) { + HDF_LOGE("%s, edp priv data is null", __func__); + return ret; + } + + ret = LinuxEdpEnable(edpAdapterData); + return ret; +} + +static int32_t EdpAdapterDisable(struct EdpCntlr *cntlr) +{ + int32_t ret = HDF_FAILURE; + HdfEdpAdapterData *edpAdapterData = EdpAdapterPrivToEdpData(cntlr); + if (cntlr == NULL) { + HDF_LOGE("%s, invalid cntlr data\n", __func__); + return ret; + } + if (edpAdapterData == NULL) { + HDF_LOGE("%s, edp priv data is null", __func__); + return ret; + } + + ret = LinuxEdpDisable(edpAdapterData); + return ret; +} + +static struct EdpCntlrOps g_edpCntlrOps = { + .open = NULL, + .close = NULL, + .enable = EdpAdapterEnable, + .disable = EdpAdapterDisable, + .avmuteSet = EdpAdapterAvmuteSet, + .deepColorSet = EdpAdapterDeepColorSet, + .deepColorGet = EdpAdapterDeepColorGet, + .setVideoAttribute = EdpAdapterSetVideoAttribute, + .setAudioAttribute = EdpAdapterSetAudioAttribute, + .registerHpdCallbackFunc = EdpAdapterRegisterHpdCallbackFunc, + .unregisterHpdCallbackFunc = EdpAdapterUnregisterHpdCallbackFunc, + .getConnector = EdpAdapterGetConnector, +}; + +static int32_t EdpAdapterOpsInit(struct EdpCntlr *cntlr) +{ + if (cntlr == NULL) { + return HDF_ERR_INVALID_OBJECT; + } + cntlr->ops = &g_edpCntlrOps; + + return HDF_SUCCESS; +} + +static int32_t EdpAdapterOpsDeInit(struct EdpCntlr *cntlr) +{ + cntlr->ops = NULL; + return HDF_SUCCESS; +} + +static int32_t EdpAdapterInit(struct EdpCntlr *cntlr) +{ + int32_t ret = -1; + HdfEdpAdapterData *edpAdapterData = NULL; + if (cntlr == NULL) { + HDF_LOGE("%s, device handle is null", __func__); + return ret; + } + + edpAdapterData = (HdfEdpAdapterData *)OsalMemCalloc(sizeof(HdfEdpAdapterData)); + if (NULL == edpAdapterData) { + HDF_LOGE("Alloc mem for adapter data failed\n"); + return ret; + } + + ret = LinuxEdpAdapterInit(edpAdapterData); + if (HDF_SUCCESS != ret) { + OsalMemFree(edpAdapterData); + return ret; + } + + EdpAdapterOpsInit(cntlr); + cntlr->hpdCbInfo = NULL; + cntlr->priv = (void *)edpAdapterData; + edpAdapterData->hdfHdl = (void *)cntlr; + return ret; +} + +static int32_t EdpCntlrInit(struct EdpCntlr *cntlr, struct HdfDeviceObject *obj) +{ + int32_t ret; + uint32_t num = 0; + struct DeviceResourceIface *iface = NULL; + + if (cntlr == NULL) { + return HDF_ERR_INVALID_OBJECT; + } + + if (obj == NULL) { + HDF_LOGE("EdpCntlrInit: no HdfDeviceObject attached!"); + return HDF_ERR_INVALID_OBJECT; + } + iface = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE); + if (iface == NULL || iface->GetUint32 == NULL) { + HDF_LOGE("HdfPwmInit: iface or GetUint32 is null!"); + return HDF_FAILURE; + } + + cntlr->hdfDevObj = obj; + cntlr->num = num; + cntlr->device.number = (int32_t)cntlr->deviceIndex; + cntlr->device.hdfDev = cntlr->hdfDevObj; + obj->priv = (void *)cntlr; + ret = EdpAdapterInit(cntlr); + return ret; +} + +static int32_t HdfEdpBind(struct HdfDeviceObject *obj) +{ + (void)obj; + return HDF_SUCCESS; +} + +static int32_t HdfEdpInit(struct HdfDeviceObject *obj) +{ + int32_t ret = -1; + struct EdpCntlr *cntlr = NULL; + + HDF_LOGI("%s: entry", __func__); + if (obj == NULL) { + HDF_LOGE("%s: obj is null", __func__); + return HDF_ERR_INVALID_OBJECT; + } + + cntlr = (struct EdpCntlr *)OsalMemCalloc(sizeof(struct EdpCntlr)); + if (cntlr == NULL) { + HDF_LOGE("%s: OsalMemCalloc cntlr error", __func__); + return HDF_ERR_MALLOC_FAIL; + } + + ret = OsalMutexInit(&cntlr->mutex); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: mutex init fail!", __func__); + return ret; + } + + cntlr->state = EDP_CNTLR_STATE_NONE; + cntlr->service.Dispatch = &EdpIoDispatch; + ret = EdpCntlrInit(cntlr, obj); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: error probe, ret is %d", __func__, ret); + OsalMemFree(cntlr); + } + ret = EdpCntlrAdd(obj, cntlr); + + return ret; +} + +static int32_t EdpAdapterDeInit(struct EdpCntlr *cntlr) +{ + int32_t ret = -1; + HdfEdpAdapterData *edpAdapterData = EdpAdapterPrivToEdpData(cntlr); + + if (NULL == edpAdapterData) { + HDF_LOGE("edp adapter data is NULL\n"); + return ret; + } + + LinuxEdpAdapterDeInit(edpAdapterData); + OsalMemFree(edpAdapterData); + + ret = 0; + return ret; +} + +static void EdpCntlrDeinit(struct EdpCntlr *cntlr) +{ + if (cntlr != NULL) { + EdpAdapterDeInit(cntlr); + EdpAdapterOpsDeInit(cntlr); + (void)OsalMutexDestroy(&cntlr->mutex); + } +} + +static void HdfEdpRelease(struct HdfDeviceObject *obj) +{ + HDF_LOGD("%s: entry", __func__); + struct EdpCntlr *cntlr = (struct EdpCntlr *)obj->priv; + EdpCntlrDeinit(cntlr); +} + +struct HdfDriverEntry g_hdfEdpEntry = { + .moduleVersion = 1, + .moduleName = "HDF_EDP", + .Bind = HdfEdpBind, + .Init = HdfEdpInit, + .Release = HdfEdpRelease, +}; + +HDF_INIT(g_hdfEdpEntry); \ No newline at end of file diff --git a/adapter/khdf/linux/platform/edp/edp_adaptor.h b/adapter/khdf/linux/platform/edp/edp_adaptor.h new file mode 100644 index 0000000000000000000000000000000000000000..9cadb6d6cc3d9b6ff01030a67bbc09f389075b42 --- /dev/null +++ b/adapter/khdf/linux/platform/edp/edp_adaptor.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2023-2024 Huawei Device Co., Ltd. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * 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. + * + */ + +#ifndef EDP_ADAPTER_H +#define EDP_ADAPTER_H + +#include "edp_core.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif /* __cplusplus */ + +void EdpInit(struct EdpCntlr *cntlr); +void EdpDeinit(struct EdpCntlr *cntlr); + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif /* __cplusplus */ + +#endif //EDP_ADAPTER_H \ No newline at end of file diff --git a/adapter/khdf/linux/platform/edp/edp_analogix_reg.c b/adapter/khdf/linux/platform/edp/edp_analogix_reg.c new file mode 100644 index 0000000000000000000000000000000000000000..59bda8dacad2398fba9ac1f33a4844f0b1b992ee --- /dev/null +++ b/adapter/khdf/linux/platform/edp/edp_analogix_reg.c @@ -0,0 +1,195 @@ +/* + * Copyright (c) 2023-2024 Huawei Device Co., Ltd. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * 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. + * + */ + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "edp_linux_def.h" +#include "edp_rk35xx.h" +#include "edp_analogix_reg.h" + +static void AnalogixDpWrite(struct AnalogixDpDevice *dp, u32 reg, u32 val) +{ + if (dp->platData) { + readl(dp->regBase); + writel(val, dp->regBase + reg); + } + + writel(val, dp->regBase + reg); +} + +static u32 AnalogixDpRead(struct AnalogixDpDevice *dp, u32 reg) +{ + if (dp->platData) + readl(dp->regBase + reg); + + return readl(dp->regBase + reg); +} + +void EdpEnableVideoMute(struct AnalogixDpDevice *dp, bool enable) +{ + u32 reg; + + if (enable) { + reg = AnalogixDpRead(dp, ANALOGIX_DP_VIDEO_CTL_1); + reg |= HDCP_VIDEO_MUTE; + AnalogixDpWrite(dp, ANALOGIX_DP_VIDEO_CTL_1, reg); + } else { + reg = AnalogixDpRead(dp, ANALOGIX_DP_VIDEO_CTL_1); + reg &= ~HDCP_VIDEO_MUTE; + AnalogixDpWrite(dp, ANALOGIX_DP_VIDEO_CTL_1, reg); + } +} + +void EdpSetVideoColorFormat(struct AnalogixDpDevice *dp) +{ + u32 reg; + + /* Configure the input color depth, color space, dynamic range */ + reg = (dp->videoInfo.dynamicRange << IN_D_RANGE_SHIFT) | + (dp->videoInfo.colorDepth << IN_BPC_SHIFT) | + (dp->videoInfo.colorSpace << IN_COLOR_F_SHIFT); + AnalogixDpWrite(dp, ANALOGIX_DP_VIDEO_CTL_2, reg); + + /* Set Input Color YCbCr Coefficients to ITU601 or ITU709 */ + reg = AnalogixDpRead(dp, ANALOGIX_DP_VIDEO_CTL_3); + reg &= ~IN_YC_COEFFI_MASK; + if (dp->videoInfo.ycbcrCoeff) + reg |= IN_YC_COEFFI_ITU709; + else + reg |= IN_YC_COEFFI_ITU601; + AnalogixDpWrite(dp, ANALOGIX_DP_VIDEO_CTL_3, reg); +} + +void EdpSetVideoTimingMode(struct AnalogixDpDevice *dp, u32 type) +{ + u32 reg; + + if (type == VIDEO_TIMING_FROM_CAPTURE) { + reg = AnalogixDpRead(dp, ANALOGIX_DP_VIDEO_CTL_10); + reg &= ~FORMAT_SEL; + AnalogixDpWrite(dp, ANALOGIX_DP_VIDEO_CTL_10, reg); + } else { + reg = AnalogixDpRead(dp, ANALOGIX_DP_VIDEO_CTL_10); + reg |= FORMAT_SEL; + AnalogixDpWrite(dp, ANALOGIX_DP_VIDEO_CTL_10, reg); + } +} + +void EdpSetVideoFormat(struct AnalogixDpDevice *dp) +{ + struct VideoInfo *video = &dp->videoInfo; + const struct drm_display_mode *mode = &video->mode; + unsigned int hsw, hfp, hbp, vsw, vfp, vbp; + + hsw = mode->hsync_end - mode->hsync_start; + hfp = mode->hsync_start - mode->hdisplay; + hbp = mode->htotal - mode->hsync_end; + vsw = mode->vsync_end - mode->vsync_start; + vfp = mode->vsync_start - mode->vdisplay; + vbp = mode->vtotal - mode->vsync_end; + + /* Set Video Format Parameters */ + AnalogixDpWrite(dp, ANALOGIX_DP_TOTAL_LINE_CFG_L, + TOTAL_LINE_CFG_L(mode->vtotal)); + AnalogixDpWrite(dp, ANALOGIX_DP_TOTAL_LINE_CFG_H, + TOTAL_LINE_CFG_H(mode->vtotal >> ANALOGIX_REG_BIT_8)); + AnalogixDpWrite(dp, ANALOGIX_DP_ACTIVE_LINE_CFG_L, + ACTIVE_LINE_CFG_L(mode->vdisplay)); + AnalogixDpWrite(dp, ANALOGIX_DP_ACTIVE_LINE_CFG_H, + ACTIVE_LINE_CFG_H(mode->vdisplay >> ANALOGIX_REG_BIT_8)); + AnalogixDpWrite(dp, ANALOGIX_DP_V_F_PORCH_CFG, + V_F_PORCH_CFG(vfp)); + AnalogixDpWrite(dp, ANALOGIX_DP_V_SYNC_WIDTH_CFG, + V_SYNC_WIDTH_CFG(vsw)); + AnalogixDpWrite(dp, ANALOGIX_DP_V_B_PORCH_CFG, + V_B_PORCH_CFG(vbp)); + AnalogixDpWrite(dp, ANALOGIX_DP_TOTAL_PIXEL_CFG_L, + TOTAL_PIXEL_CFG_L(mode->htotal)); + AnalogixDpWrite(dp, ANALOGIX_DP_TOTAL_PIXEL_CFG_H, + TOTAL_PIXEL_CFG_H(mode->htotal >> ANALOGIX_REG_BIT_8)); + AnalogixDpWrite(dp, ANALOGIX_DP_ACTIVE_PIXEL_CFG_L, + ACTIVE_PIXEL_CFG_L(mode->hdisplay)); + AnalogixDpWrite(dp, ANALOGIX_DP_ACTIVE_PIXEL_CFG_H, + ACTIVE_PIXEL_CFG_H(mode->hdisplay >> ANALOGIX_REG_BIT_8)); + AnalogixDpWrite(dp, ANALOGIX_DP_H_F_PORCH_CFG_L, + H_F_PORCH_CFG_L(hfp)); + AnalogixDpWrite(dp, ANALOGIX_DP_H_F_PORCH_CFG_H, + H_F_PORCH_CFG_H(hfp >> ANALOGIX_REG_BIT_8)); + AnalogixDpWrite(dp, ANALOGIX_DP_H_SYNC_CFG_L, + H_SYNC_CFG_L(hsw)); + AnalogixDpWrite(dp, ANALOGIX_DP_H_SYNC_CFG_H, + H_SYNC_CFG_H(hsw >> ANALOGIX_REG_BIT_8)); + AnalogixDpWrite(dp, ANALOGIX_DP_H_B_PORCH_CFG_L, + H_B_PORCH_CFG_L(hbp)); + AnalogixDpWrite(dp, ANALOGIX_DP_H_B_PORCH_CFG_H, + H_B_PORCH_CFG_H(hbp >> ANALOGIX_REG_BIT_8)); +} + +void EdpAudioConfigI2s(struct AnalogixDpDevice *dp) +{ + u32 reg; + + reg = AnalogixDpRead(dp, ANALOGIX_DP_SYS_CTL_4); + reg &= ~FIX_M_AUD; + AnalogixDpWrite(dp, ANALOGIX_DP_SYS_CTL_4, reg); + + reg = AnalogixDpRead(dp, ANALOGIX_DP_I2S_CTRL); + reg |= I2S_EN; + AnalogixDpWrite(dp, ANALOGIX_DP_I2S_CTRL, reg); +} + +void EdpAudioConfigSpdif(struct AnalogixDpDevice *dp) +{ + u32 reg; + + reg = AnalogixDpRead(dp, ANALOGIX_DP_SYS_CTL_4); + reg &= ~FIX_M_AUD; + AnalogixDpWrite(dp, ANALOGIX_DP_SYS_CTL_4, reg); + + reg = AnalogixDpRead(dp, ANALOGIX_DP_SPDIF_AUDIO_CTL_0); + reg |= AUD_SPDIF_EN; + AnalogixDpWrite(dp, ANALOGIX_DP_SPDIF_AUDIO_CTL_0, reg); +} + +void EdpAudioEnable(struct AnalogixDpDevice *dp) +{ + u32 reg; + + reg = AnalogixDpRead(dp, ANALOGIX_DP_FUNC_EN_1); + reg &= ~(AUD_FIFO_FUNC_EN_N | AUD_FUNC_EN_N); + AnalogixDpWrite(dp, ANALOGIX_DP_FUNC_EN_1, reg); + + reg = AnalogixDpRead(dp, ANALOGIX_DP_AUD_CTL); + reg |= MISC_CTRL_RESET | DP_AUDIO_EN; + AnalogixDpWrite(dp, ANALOGIX_DP_AUD_CTL, reg); +} + +void EdpAudioDisable(struct AnalogixDpDevice *dp) +{ + u32 reg; + + AnalogixDpWrite(dp, ANALOGIX_DP_AUD_CTL, 0); + + reg = AnalogixDpRead(dp, ANALOGIX_DP_FUNC_EN_1); + reg |= AUD_FIFO_FUNC_EN_N | AUD_FUNC_EN_N; + AnalogixDpWrite(dp, ANALOGIX_DP_FUNC_EN_1, reg); +} diff --git a/adapter/khdf/linux/platform/edp/edp_analogix_reg.h b/adapter/khdf/linux/platform/edp/edp_analogix_reg.h new file mode 100644 index 0000000000000000000000000000000000000000..7f18851b78e7d6de740d24de948d1a775d5ffa47 --- /dev/null +++ b/adapter/khdf/linux/platform/edp/edp_analogix_reg.h @@ -0,0 +1,557 @@ +/* + * Copyright (c) 2023-2024 Huawei Device Co., Ltd. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * 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. + * + */ + +#ifndef EDP_ANALOGIX_REG_H +#define EDP_ANALOGIX_REG_H + +#define ANALOGIX_DP_TX_SW_RESET 0x14 +#define ANALOGIX_DP_FUNC_EN_1 0x18 +#define ANALOGIX_DP_FUNC_EN_2 0x1C +#define ANALOGIX_DP_VIDEO_CTL_1 0x20 +#define ANALOGIX_DP_VIDEO_CTL_2 0x24 +#define ANALOGIX_DP_VIDEO_CTL_3 0x28 +#define ANALOGIX_DP_VIDEO_CTL_4 0x2C + +#define ANALOGIX_DP_VIDEO_CTL_8 0x3C +#define ANALOGIX_DP_VIDEO_CTL_10 0x44 +#define ANALOGIX_DP_TOTAL_LINE_CFG_L 0x48 +#define ANALOGIX_DP_TOTAL_LINE_CFG_H 0x4C +#define ANALOGIX_DP_ACTIVE_LINE_CFG_L 0x50 +#define ANALOGIX_DP_ACTIVE_LINE_CFG_H 0x54 +#define ANALOGIX_DP_V_F_PORCH_CFG 0x58 +#define ANALOGIX_DP_V_SYNC_WIDTH_CFG 0x5C +#define ANALOGIX_DP_V_B_PORCH_CFG 0x60 +#define ANALOGIX_DP_TOTAL_PIXEL_CFG_L 0x64 +#define ANALOGIX_DP_TOTAL_PIXEL_CFG_H 0x68 +#define ANALOGIX_DP_ACTIVE_PIXEL_CFG_L 0x6C +#define ANALOGIX_DP_ACTIVE_PIXEL_CFG_H 0x70 +#define ANALOGIX_DP_H_F_PORCH_CFG_L 0x74 +#define ANALOGIX_DP_H_F_PORCH_CFG_H 0x78 +#define ANALOGIX_DP_H_SYNC_CFG_L 0x7C +#define ANALOGIX_DP_H_SYNC_CFG_H 0x80 +#define ANALOGIX_DP_H_B_PORCH_CFG_L 0x84 +#define ANALOGIX_DP_H_B_PORCH_CFG_H 0x88 + +#define ANALOGIX_DP_SPDIF_AUDIO_CTL_0 0xD8 + +#define ANALOGIX_DP_PLL_REG_1 0xfc +#define ANALOGIX_DP_PLL_REG_2 0x9e4 +#define ANALOGIX_DP_PLL_REG_3 0x9e8 +#define ANALOGIX_DP_PLL_REG_4 0x9ec +#define ANALOGIX_DP_PLL_REG_5 0xa00 + +#define ANALOIGX_DP_SSC_REG 0x104 +#define ANALOGIX_DP_BIAS 0x124 +#define ANALOGIX_DP_PD 0x12c + +#define ANALOGIX_DP_IF_TYPE 0x244 +#define ANALOGIX_DP_IF_PKT_DB1 0x254 +#define ANALOGIX_DP_IF_PKT_DB2 0x258 +#define ANALOGIX_DP_SPD_HB0 0x2F8 +#define ANALOGIX_DP_SPD_HB1 0x2FC +#define ANALOGIX_DP_SPD_HB2 0x300 +#define ANALOGIX_DP_SPD_HB3 0x304 +#define ANALOGIX_DP_SPD_PB0 0x308 +#define ANALOGIX_DP_SPD_PB1 0x30C +#define ANALOGIX_DP_SPD_PB2 0x310 +#define ANALOGIX_DP_SPD_PB3 0x314 +#define ANALOGIX_DP_PSR_FRAME_UPDATE_CTRL 0x318 +#define ANALOGIX_DP_VSC_SHADOW_DB0 0x31C +#define ANALOGIX_DP_VSC_SHADOW_DB1 0x320 +#define ANALOGIX_DP_VSC_SHADOW_PB0 0x33C +#define ANALOGIX_DP_VSC_SHADOW_PB1 0x340 + +#define ANALOGIX_DP_LANE_MAP 0x35C + +#define ANALOGIX_DP_ANALOG_CTL_1 0x370 +#define ANALOGIX_DP_ANALOG_CTL_2 0x374 +#define ANALOGIX_DP_ANALOG_CTL_3 0x378 +#define ANALOGIX_DP_PLL_FILTER_CTL_1 0x37C +#define ANALOGIX_DP_TX_AMP_TUNING_CTL 0x380 + +#define ANALOGIX_DP_AUX_HW_RETRY_CTL 0x390 + +#define ANALOGIX_DP_COMMON_INT_STA_1 0x3C4 +#define ANALOGIX_DP_COMMON_INT_STA_2 0x3C8 +#define ANALOGIX_DP_COMMON_INT_STA_3 0x3CC +#define ANALOGIX_DP_COMMON_INT_STA_4 0x3D0 +#define ANALOGIX_DP_INT_STA 0x3DC +#define ANALOGIX_DP_COMMON_INT_MASK_1 0x3E0 +#define ANALOGIX_DP_COMMON_INT_MASK_2 0x3E4 +#define ANALOGIX_DP_COMMON_INT_MASK_3 0x3E8 +#define ANALOGIX_DP_COMMON_INT_MASK_4 0x3EC +#define ANALOGIX_DP_INT_STA_MASK 0x3F8 +#define ANALOGIX_DP_INT_CTL 0x3FC + +#define ANALOGIX_DP_SYS_CTL_1 0x600 +#define ANALOGIX_DP_SYS_CTL_2 0x604 +#define ANALOGIX_DP_SYS_CTL_3 0x608 +#define ANALOGIX_DP_SYS_CTL_4 0x60C +#define ANALOGIX_DP_AUD_CTL 0x618 +#define ANALOGIX_DP_PKT_SEND_CTL 0x640 +#define ANALOGIX_DP_HDCP_CTL 0x648 + +#define ANALOGIX_DP_LINK_BW_SET 0x680 +#define ANALOGIX_DP_LANE_COUNT_SET 0x684 +#define ANALOGIX_DP_TRAINING_PTN_SET 0x688 +#define ANALOGIX_DP_LN0_LINK_TRAINING_CTL 0x68C +#define ANALOGIX_DP_LN1_LINK_TRAINING_CTL 0x690 +#define ANALOGIX_DP_LN2_LINK_TRAINING_CTL 0x694 +#define ANALOGIX_DP_LN3_LINK_TRAINING_CTL 0x698 + +#define ANALOGIX_DP_DEBUG_CTL 0x6C0 +#define ANALOGIX_DP_HPD_DEGLITCH_L 0x6C4 +#define ANALOGIX_DP_HPD_DEGLITCH_H 0x6C8 +#define ANALOGIX_DP_LINK_DEBUG_CTL 0x6E0 + +#define ANALOGIX_DP_M_VID_0 0x700 +#define ANALOGIX_DP_M_VID_1 0x704 +#define ANALOGIX_DP_M_VID_2 0x708 +#define ANALOGIX_DP_N_VID_0 0x70C +#define ANALOGIX_DP_N_VID_1 0x710 +#define ANALOGIX_DP_N_VID_2 0x714 + +#define ANALOGIX_DP_PLL_CTL 0x71C +#define ANALOGIX_DP_PHY_PD 0x720 +#define ANALOGIX_DP_PHY_TEST 0x724 + +#define ANALOGIX_DP_VIDEO_FIFO_THRD 0x730 +#define ANALOGIX_DP_AUDIO_MARGIN 0x73C + +#define ANALOGIX_DP_M_VID_GEN_FILTER_TH 0x764 +#define ANALOGIX_DP_M_AUD_GEN_FILTER_TH 0x778 +#define ANALOGIX_DP_AUX_CH_STA 0x780 +#define ANALOGIX_DP_AUX_CH_DEFER_CTL 0x788 +#define ANALOGIX_DP_AUX_RX_COMM 0x78C +#define ANALOGIX_DP_BUFFER_DATA_CTL 0x790 +#define ANALOGIX_DP_AUX_CH_CTL_1 0x794 +#define ANALOGIX_DP_AUX_ADDR_7_0 0x798 +#define ANALOGIX_DP_AUX_ADDR_15_8 0x79C +#define ANALOGIX_DP_AUX_ADDR_19_16 0x7A0 +#define ANALOGIX_DP_AUX_CH_CTL_2 0x7A4 + +#define ANALOGIX_DP_BUF_DATA_0 0x7C0 + +#define ANALOGIX_DP_SOC_GENERAL_CTL 0x800 +#define ANALOGIX_DP_TEST_80B_PATTERN0 0x81C +#define ANALOGIX_DP_TEST_80B_PATTERN1 0x820 +#define ANALOGIX_DP_TEST_80B_PATTERN2 0x824 +#define ANALOGIX_DP_TEST_HBR2_PATTERN 0x828 +#define ANALOGIX_DP_AUD_CHANNEL_CTL 0x834 +#define ANALOGIX_DP_CRC_CON 0x890 +#define ANALOGIX_DP_I2S_CTRL 0x9C8 + +/* ANALOGIX_DP_TX_SW_RESET */ +#define RESET_DP_TX (0x1 << 0) + +/* ANALOGIX_DP_FUNC_EN_1 */ +#define MASTER_VID_FUNC_EN_N (0x1 << 7) +#define RK_VID_CAP_FUNC_EN_N (0x1 << 6) +#define SLAVE_VID_FUNC_EN_N (0x1 << 5) +#define RK_VID_FIFO_FUNC_EN_N (0x1 << 5) +#define AUD_FIFO_FUNC_EN_N (0x1 << 4) +#define AUD_FUNC_EN_N (0x1 << 3) +#define HDCP_FUNC_EN_N (0x1 << 2) +#define CRC_FUNC_EN_N (0x1 << 1) +#define SW_FUNC_EN_N (0x1 << 0) + +/* ANALOGIX_DP_FUNC_EN_2 */ +#define SSC_FUNC_EN_N (0x1 << 7) +#define AUX_FUNC_EN_N (0x1 << 2) +#define SERDES_FIFO_FUNC_EN_N (0x1 << 1) +#define LS_CLK_DOMAIN_FUNC_EN_N (0x1 << 0) + +/* ANALOGIX_DP_VIDEO_CTL_1 */ +#define VIDEO_EN (0x1 << 7) +#define HDCP_VIDEO_MUTE (0x1 << 6) + +/* ANALOGIX_DP_VIDEO_CTL_1 */ +#define IN_D_RANGE_MASK (0x1 << 7) +#define IN_D_RANGE_SHIFT (7) +#define IN_D_RANGE_CEA (0x1 << 7) +#define IN_D_RANGE_VESA (0x0 << 7) +#define IN_BPC_MASK (0x7 << 4) +#define IN_BPC_SHIFT (4) +#define IN_BPC_12_BITS (0x3 << 4) +#define IN_BPC_10_BITS (0x2 << 4) +#define IN_BPC_8_BITS (0x1 << 4) +#define IN_BPC_6_BITS (0x0 << 4) +#define IN_COLOR_F_MASK (0x3 << 0) +#define IN_COLOR_F_SHIFT (0) +#define IN_COLOR_F_YCBCR444 (0x2 << 0) +#define IN_COLOR_F_YCBCR422 (0x1 << 0) +#define IN_COLOR_F_RGB (0x0 << 0) + +/* ANALOGIX_DP_VIDEO_CTL_3 */ +#define IN_YC_COEFFI_MASK (0x1 << 7) +#define IN_YC_COEFFI_SHIFT (7) +#define IN_YC_COEFFI_ITU709 (0x1 << 7) +#define IN_YC_COEFFI_ITU601 (0x0 << 7) +#define VID_CHK_UPDATE_TYPE_MASK (0x1 << 4) +#define VID_CHK_UPDATE_TYPE_SHIFT (4) +#define VID_CHK_UPDATE_TYPE_1 (0x1 << 4) +#define VID_CHK_UPDATE_TYPE_0 (0x0 << 4) +#define REUSE_SPD_EN (0x1 << 3) + +/* ANALOGIX_DP_VIDEO_CTL_4 */ +#define BIST_EN (0x1 << 3) + +/* ANALOGIX_DP_VIDEO_CTL_10 */ +#define FORMAT_SEL (0x1 << 4) +#define INTERACE_SCAN_CFG (0x1 << 2) +#define VSYNC_POLARITY_CFG (0x1 << 1) +#define HSYNC_POLARITY_CFG (0x1 << 0) + +/* ANALOGIX_DP_TOTAL_LINE_CFG_L */ +inline unsigned int TOTAL_LINE_CFG_L(unsigned int x) +{ + return ((x & 0xff) << 0); +} + +/* ANALOGIX_DP_TOTAL_LINE_CFG_H */ +inline unsigned int TOTAL_LINE_CFG_H(unsigned int x) +{ + return ((x & 0xf) << 0); +} + +/* ANALOGIX_DP_ACTIVE_LINE_CFG_L */ +inline unsigned int ACTIVE_LINE_CFG_L(unsigned int x) +{ + return ((x & 0xff) << 0); +} + +/* ANALOGIX_DP_ACTIVE_LINE_CFG_H */ +inline unsigned int ACTIVE_LINE_CFG_H(unsigned int x) +{ + return ((x & 0xf) << 0); +} + +/* ANALOGIX_DP_V_F_PORCH_CFG */ +inline unsigned int V_F_PORCH_CFG(unsigned int x) +{ + return ((x & 0xff) << 0); +} + +/* ANALOGIX_DP_V_SYNC_WIDTH_CFG */ +inline unsigned int V_SYNC_WIDTH_CFG(unsigned int x) +{ + return ((x & 0xff) << 0); +} + +/* ANALOGIX_DP_V_B_PORCH_CFG */ +inline unsigned int V_B_PORCH_CFG(unsigned int x) +{ + return ((x & 0xff) << 0); +} + +/* ANALOGIX_DP_TOTAL_PIXEL_CFG_L */ +inline unsigned int TOTAL_PIXEL_CFG_L(unsigned int x) +{ + return ((x & 0xff) << 0); +} + +/* ANALOGIX_DP_TOTAL_PIXEL_CFG_H */ +inline unsigned int TOTAL_PIXEL_CFG_H(unsigned int x) +{ + return ((x & 0x3f) << 0); +} + +/* ANALOGIX_DP_ACTIVE_PIXEL_CFG_L */ +inline unsigned int ACTIVE_PIXEL_CFG_L(unsigned int x) +{ + return ((x & 0xff) << 0); +} + +/* ANALOGIX_DP_ACTIVE_PIXEL_CFG_H */ +inline unsigned int ACTIVE_PIXEL_CFG_H(unsigned int x) +{ + return ((x & 0x3f) << 0); +} + +/* ANALOGIX_DP_H_F_PORCH_CFG_L */ +inline unsigned int H_F_PORCH_CFG_L(unsigned int x) +{ + return ((x & 0xff) << 0); +} + +/* ANALOGIX_DP_H_F_PORCH_CFG_H */ +inline unsigned int H_F_PORCH_CFG_H(unsigned int x) +{ + return ((x & 0xf) << 0); +} + +/* ANALOGIX_DP_H_SYNC_CFG_L */ +inline unsigned int H_SYNC_CFG_L(unsigned int x) +{ + return ((x & 0xff) << 0); +} + +/* ANALOGIX_DP_H_SYNC_CFG_H */ +inline unsigned int H_SYNC_CFG_H(unsigned int x) +{ + return ((x & 0xf) << 0); +} + +/* ANALOGIX_DP_H_B_PORCH_CFG_L */ +inline unsigned int H_B_PORCH_CFG_L(unsigned int x) +{ + return ((x & 0xff) << 0); +} + +/* ANALOGIX_DP_H_B_PORCH_CFG_H */ +inline unsigned int H_B_PORCH_CFG_H(unsigned int x) +{ + return ((x & 0xf) << 0); +} + +/* ANALOGIX_DP_SPDIF_AUDIO_CTL_0 */ +#define AUD_SPDIF_EN (0x1 << 7) + +/* ANALOGIX_DP_PLL_REG_1 */ +#define REF_CLK_24M (0x1 << 0) +#define REF_CLK_27M (0x0 << 0) +#define REF_CLK_MASK (0x1 << 0) + +/* ANALOGIX_DP_PSR_FRAME_UPDATE_CTRL */ +#define PSR_FRAME_UP_TYPE_BURST (0x1 << 0) +#define PSR_FRAME_UP_TYPE_SINGLE (0x0 << 0) +#define PSR_CRC_SEL_HARDWARE (0x1 << 1) +#define PSR_CRC_SEL_MANUALLY (0x0 << 1) + +/* ANALOGIX_DP_LANE_MAP */ +#define LANE3_MAP_LOGIC_LANE_0 (0x0 << 6) +#define LANE3_MAP_LOGIC_LANE_1 (0x1 << 6) +#define LANE3_MAP_LOGIC_LANE_2 (0x2 << 6) +#define LANE3_MAP_LOGIC_LANE_3 (0x3 << 6) +#define LANE2_MAP_LOGIC_LANE_0 (0x0 << 4) +#define LANE2_MAP_LOGIC_LANE_1 (0x1 << 4) +#define LANE2_MAP_LOGIC_LANE_2 (0x2 << 4) +#define LANE2_MAP_LOGIC_LANE_3 (0x3 << 4) +#define LANE1_MAP_LOGIC_LANE_0 (0x0 << 2) +#define LANE1_MAP_LOGIC_LANE_1 (0x1 << 2) +#define LANE1_MAP_LOGIC_LANE_2 (0x2 << 2) +#define LANE1_MAP_LOGIC_LANE_3 (0x3 << 2) +#define LANE0_MAP_LOGIC_LANE_0 (0x0 << 0) +#define LANE0_MAP_LOGIC_LANE_1 (0x1 << 0) +#define LANE0_MAP_LOGIC_LANE_2 (0x2 << 0) +#define LANE0_MAP_LOGIC_LANE_3 (0x3 << 0) + +/* ANALOGIX_DP_ANALOG_CTL_1 */ +#define TX_TERMINAL_CTRL_50_OHM (0x1 << 4) + +/* ANALOGIX_DP_ANALOG_CTL_2 */ +#define SEL_24M (0x1 << 3) +#define TX_DVDD_BIT_1_0625V (0x4 << 0) + +/* ANALOGIX_DP_ANALOG_CTL_3 */ +#define DRIVE_DVDD_BIT_1_0625V (0x4 << 5) +#define VCO_BIT_600_MICRO (0x5 << 0) + +/* ANALOGIX_DP_PLL_FILTER_CTL_1 */ +#define PD_RING_OSC (0x1 << 6) +#define AUX_TERMINAL_CTRL_50_OHM (0x2 << 4) +#define TX_CUR1_2X (0x1 << 2) +#define TX_CUR_16_MA (0x3 << 0) + +/* ANALOGIX_DP_TX_AMP_TUNING_CTL */ +#define CH3_AMP_400_MV (0x0 << 24) +#define CH2_AMP_400_MV (0x0 << 16) +#define CH1_AMP_400_MV (0x0 << 8) +#define CH0_AMP_400_MV (0x0 << 0) + +/* ANALOGIX_DP_AUX_HW_RETRY_CTL */ +#define AUX_HW_RETRY_INTERVAL_MASK (0x3 << 3) +#define AUX_HW_RETRY_INTERVAL_600_MICROSECONDS (0x0 << 3) +#define AUX_HW_RETRY_INTERVAL_800_MICROSECONDS (0x1 << 3) +#define AUX_HW_RETRY_INTERVAL_1000_MICROSECONDS (0x2 << 3) +#define AUX_HW_RETRY_INTERVAL_1800_MICROSECONDS (0x3 << 3) + +/* ANALOGIX_DP_COMMON_INT_STA_1 */ +#define VSYNC_DET (0x1 << 7) +#define PLL_LOCK_CHG (0x1 << 6) +#define SPDIF_ERR (0x1 << 5) +#define SPDIF_UNSTBL (0x1 << 4) +#define VID_FORMAT_CHG (0x1 << 3) +#define AUD_CLK_CHG (0x1 << 2) +#define VID_CLK_CHG (0x1 << 1) +#define SW_INT (0x1 << 0) + +/* ANALOGIX_DP_COMMON_INT_STA_2 */ +#define ENC_EN_CHG (0x1 << 6) +#define HW_BKSV_RDY (0x1 << 3) +#define HW_SHA_DONE (0x1 << 2) +#define HW_AUTH_STATE_CHG (0x1 << 1) +#define HW_AUTH_DONE (0x1 << 0) + +/* ANALOGIX_DP_COMMON_INT_STA_3 */ +#define AFIFO_UNDER (0x1 << 7) +#define AFIFO_OVER (0x1 << 6) +#define R0_CHK_FLAG (0x1 << 5) + +/* ANALOGIX_DP_COMMON_INT_STA_4 */ +#define PSR_ACTIVE (0x1 << 7) +#define PSR_INACTIVE (0x1 << 6) +#define SPDIF_BI_PHASE_ERR (0x1 << 5) +#define HOTPLUG_CHG (0x1 << 2) +#define HPD_LOST (0x1 << 1) +#define PLUG (0x1 << 0) + +/* ANALOGIX_DP_INT_STA */ +#define INT_HPD (0x1 << 6) +#define HW_TRAINING_FINISH (0x1 << 5) +#define RPLY_RECEIV (0x1 << 1) +#define AUX_ERR (0x1 << 0) + +/* ANALOGIX_DP_INT_CTL */ +#define SOFT_INT_CTRL (0x1 << 2) +#define INT_POL1 (0x1 << 1) +#define INT_POL0 (0x1 << 0) + +/* ANALOGIX_DP_SYS_CTL_1 */ +#define DET_STA (0x1 << 2) +#define FORCE_DET (0x1 << 1) +#define DET_CTRL (0x1 << 0) + +/* ANALOGIX_DP_SYS_CTL_2 */ +#define CHA_STA (0x1 << 2) +#define FORCE_CHA (0x1 << 1) +#define CHA_CTRL (0x1 << 0) + +/* ANALOGIX_DP_SYS_CTL_3 */ +#define HPD_STATUS (0x1 << 6) +#define F_HPD (0x1 << 5) +#define HPD_CTRL (0x1 << 4) +#define HDCP_RDY (0x1 << 3) +#define STRM_VALID (0x1 << 2) +#define F_VALID (0x1 << 1) +#define VALID_CTRL (0x1 << 0) + +/* ANALOGIX_DP_SYS_CTL_4 */ +#define FIX_M_AUD (0x1 << 4) +#define ENHANCED (0x1 << 3) +#define FIX_M_VID (0x1 << 2) +#define M_VID_UPDATE_CTRL (0x3 << 0) + +/* ANALOGIX_DP_AUD_CTL */ +#define MISC_CTRL_RESET (0x1 << 4) +#define DP_AUDIO_EN (0x1 << 0) + +/* ANALOGIX_DP_TRAINING_PTN_SET */ +#define SCRAMBLER_TYPE (0x1 << 9) +#define HW_LINK_TRAINING_PATTERN (0x1 << 8) +#define SCRAMBLING_DISABLE (0x1 << 5) +#define SCRAMBLING_ENABLE (0x0 << 5) +#define LINK_QUAL_PATTERN_SET_MASK (0x7 << 2) +#define LINK_QUAL_PATTERN_SET_HBR2 (0x5 << 2) +#define LINK_QUAL_PATTERN_SET_80BIT (0x4 << 2) +#define LINK_QUAL_PATTERN_SET_PRBS7 (0x3 << 2) +#define LINK_QUAL_PATTERN_SET_D10_2 (0x1 << 2) +#define LINK_QUAL_PATTERN_SET_DISABLE (0x0 << 2) +#define SW_TRAINING_PATTERN_SET_MASK (0x3 << 0) +#define SW_TRAINING_PATTERN_SET_PTN3 (0x3 << 0) +#define SW_TRAINING_PATTERN_SET_PTN2 (0x2 << 0) +#define SW_TRAINING_PATTERN_SET_PTN1 (0x1 << 0) +#define SW_TRAINING_PATTERN_SET_NORMAL (0x0 << 0) + +/* ANALOGIX_DP_LN0_LINK_TRAINING_CTL */ +#define PRE_EMPHASIS_SET_MASK (0x3 << 3) +#define PRE_EMPHASIS_SET_SHIFT (3) + +/* ANALOGIX_DP_DEBUG_CTL */ +#define PLL_LOCK (0x1 << 4) +#define F_PLL_LOCK (0x1 << 3) +#define PLL_LOCK_CTRL (0x1 << 2) +#define PN_INV (0x1 << 0) + +/* ANALOGIX_DP_PLL_CTL */ +#define DP_PLL_PD (0x1 << 7) +#define DP_PLL_RESET (0x1 << 6) +#define DP_PLL_LOOP_BIT_DEFAULT (0x1 << 4) +#define DP_PLL_REF_BIT_1_1250V (0x5 << 0) +#define DP_PLL_REF_BIT_1_2500V (0x7 << 0) + +/* ANALOGIX_DP_PHY_PD */ +#define DP_INC_BG (0x1 << 7) +#define DP_EXP_BG (0x1 << 6) +#define DP_PHY_PD (0x1 << 5) +#define RK_AUX_PD (0x1 << 5) +#define AUX_PD (0x1 << 4) +#define RK_PLL_PD (0x1 << 4) +#define CH3_PD (0x1 << 3) +#define CH2_PD (0x1 << 2) +#define CH1_PD (0x1 << 1) +#define CH0_PD (0x1 << 0) +#define DP_ALL_PD (0xff) + +/* ANALOGIX_DP_PHY_TEST */ +#define MACRO_RST (0x1 << 5) +#define CH1_TEST (0x1 << 1) +#define CH0_TEST (0x1 << 0) + +/* ANALOGIX_DP_AUX_CH_STA */ +#define AUX_BUSY (0x1 << 4) +#define AUX_STATUS_MASK (0xf << 0) + +/* ANALOGIX_DP_AUX_CH_DEFER_CTL */ +#define DEFER_CTRL_EN (0x1 << 7) + +/* ANALOGIX_DP_AUX_RX_COMM */ +#define AUX_RX_COMM_I2C_DEFER (0x2 << 2) +#define AUX_RX_COMM_AUX_DEFER (0x2 << 0) + +/* ANALOGIX_DP_BUFFER_DATA_CTL */ +#define BUF_CLR (0x1 << 7) + +/* ANALOGIX_DP_AUX_CH_CTL_1 */ +#define AUX_TX_COMM_MASK (0xf << 0) +#define AUX_TX_COMM_DP_TRANSACTION (0x1 << 3) +#define AUX_TX_COMM_I2C_TRANSACTION (0x0 << 3) +#define AUX_TX_COMM_MOT (0x1 << 2) +#define AUX_TX_COMM_WRITE (0x0 << 0) +#define AUX_TX_COMM_READ (0x1 << 0) + +/* ANALOGIX_DP_AUX_CH_CTL_2 */ +#define ADDR_ONLY (0x1 << 1) +#define AUX_EN (0x1 << 0) + +/* ANALOGIX_DP_SOC_GENERAL_CTL */ +#define AUDIO_MODE_SPDIF_MODE (0x1 << 8) +#define AUDIO_MODE_MASTER_MODE (0x0 << 8) +#define MASTER_VIDEO_INTERLACE_EN (0x1 << 4) +#define VIDEO_MASTER_CLK_SEL (0x1 << 2) +#define VIDEO_MASTER_MODE_EN (0x1 << 1) +#define VIDEO_MODE_MASK (0x1 << 0) +#define VIDEO_MODE_SLAVE_MODE (0x1 << 0) +#define VIDEO_MODE_MASTER_MODE (0x0 << 0) + +/* ANALOGIX_DP_AUD_CHANNEL_CTL */ +#define AUD_CHANNEL_COUNT_6 (0x5 << 0) +#define AUD_CHANNEL_COUNT_4 (0x3 << 0) +#define AUD_CHANNEL_COUNT_2 (0x1 << 0) + +/* ANALOGIX_DP_PKT_SEND_CTL */ +#define IF_UP (0x1 << 4) +#define IF_EN (0x1 << 0) + +/* ANALOGIX_DP_CRC_CON */ +#define PSR_VID_CRC_FLUSH (0x1 << 2) +#define PSR_VID_CRC_ENABLE (0x1 << 0) + +/* ANALOGIX_DP_I2S_CTRL */ +#define I2S_EN (0x1 << 4) + +/* Bit define */ +#define ANALOGIX_REG_BIT_8 8 + +#endif /* EDP_ANALOGIX_REG_H */ diff --git a/adapter/khdf/linux/platform/edp/edp_linux_def.h b/adapter/khdf/linux/platform/edp/edp_linux_def.h new file mode 100644 index 0000000000000000000000000000000000000000..7f106bf9402abb851a5b3130954f55560ffd9ca1 --- /dev/null +++ b/adapter/khdf/linux/platform/edp/edp_linux_def.h @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2023-2024 Huawei Device Co., Ltd. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * 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. + * + */ + +#ifndef EDP_LINUX_DEF_H +#define EDP_LINUX_DEF_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef CONFIG_ARCH_ROCKCHIP + #include +#else + #include +#endif +#include +#include + +#include +#include +#include + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif /* __cplusplus */ + +typedef struct HdfEdpAdapterS { + struct platform_device *platDev; + struct device *dev; + struct device_node *node; + struct drm_device *drmDev; + struct drm_bridge *drmBridge; + struct drm_panel *drmPanel; + struct drm_connector *connector; + void *driverData; + void *hdfHdl; +}HdfEdpAdapterData; + +int32_t LinuxEdpAdapterInit(HdfEdpAdapterData *edpAdapterData); +void LinuxEdpAdapterDeInit(HdfEdpAdapterData *edpAdapterData); +int32_t LinuxEdpEnable(HdfEdpAdapterData *edpAdapterData); +int32_t LinuxEdpDisable(HdfEdpAdapterData *edpAdapterData); +int32_t LinuxEdpDeepColorSet(HdfEdpAdapterData *edpAdapterData, uint32_t color); +int32_t LinuxEdpDeepColorGet(HdfEdpAdapterData *edpAdapterData, uint32_t *color); +int32_t LinuxEdpAvMuteSet(HdfEdpAdapterData *edpAdapterData, bool enable); +int32_t LinuxEdpSetVideoAttribute(HdfEdpAdapterData *edpAdapterData, const void *attr); +int32_t LinuxEdpSetAudioAttribute(HdfEdpAdapterData *edpAdapterData, const void *attr); +int32_t LinuxEdpRegisterHpdCallbackFunc(HdfEdpAdapterData *edpAdapterData, void *hpdcb); +int32_t LinuxEdpUnRegisterHpdCallbackFunc(HdfEdpAdapterData *edpAdapterData); +int32_t LinuxEdpGetConnector(HdfEdpAdapterData *edpAdapterData, void **connector); + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif /* __cplusplus */ + +#endif //EDP_LINUX_DEF_H \ No newline at end of file diff --git a/adapter/khdf/linux/platform/edp/edp_rk35xx.c b/adapter/khdf/linux/platform/edp/edp_rk35xx.c new file mode 100644 index 0000000000000000000000000000000000000000..3e4aa1cdba46dc6e2ae1cbdae29ccb00bb9e6d6c --- /dev/null +++ b/adapter/khdf/linux/platform/edp/edp_rk35xx.c @@ -0,0 +1,514 @@ +/* + * Copyright (c) 2023-2024 Huawei Device Co., Ltd. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * 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. + * + */ + +#include "hdf_base.h" +#include "hdf_log.h" + +#include "edp_linux_def.h" +#include +#include +#include "edp_rk35xx.h" +#include "edp_if.h" +#include "edp_core.h" + +#define HDF_LOG_TAG edp_rk35xx_hdf + +#ifdef CONFIG_ARCH_ROCKCHIP +static int32_t EdpBpcToColorDepth(uint32_t bpc, uint32_t *color) +{ + int32_t ret = HDF_FAILURE; + switch (bpc) { + case COLOR_6: + *color = EDP_COLOR_DEPTH_6BIT; + break; + case COLOR_8: + *color = EDP_COLOR_DEPTH_8BIT; + break; + case COLOR_10: + *color = EDP_COLOR_DEPTH_10BIT; + break; + case COLOR_12: + *color = EDP_COLOR_DEPTH_12BIT; + break; + default: + return ret; + } + ret = 0; + return ret; +} + +static int32_t EdpColorDepthToBpc(uint32_t *bpc, uint32_t color) +{ + int32_t ret = HDF_FAILURE; + switch (color) { + case EDP_COLOR_DEPTH_6BIT: + *bpc = COLOR_6; + break; + case EDP_COLOR_DEPTH_8BIT: + *bpc = COLOR_8; + break; + case EDP_COLOR_DEPTH_10BIT: + *bpc = COLOR_10; + break; + case EDP_COLOR_DEPTH_12BIT: + *bpc = COLOR_12; + break; + default: + return ret; + } + ret = 0; + return ret; +} + +static int32_t EdpColorSpaceToFormat(uint32_t *colorFormats, uint32_t colorSpace) +{ + int32_t ret = HDF_SUCCESS; + switch (colorSpace) { + case EDP_COLOR_SPACE_RGB: + *colorFormats = DRM_COLOR_FORMAT_RGB444; + break; + case EDP_COLOR_SPACE_YCBCR422: + *colorFormats = DRM_COLOR_FORMAT_YCBCR422; + break; + case EDP_COLOR_SPACE_YCBCR444: + *colorFormats = DRM_COLOR_FORMAT_YCBCR444; + break; + default: + ret = HDF_FAILURE; + break; + } + + return ret; +} + +static int32_t EdpColorCoeffToYCBCRCoeff(uint32_t *color_coeff, uint32_t colorCoeff) +{ + int32_t ret = HDF_SUCCESS; + switch (colorCoeff) { + case EDP_COLOR_COEFF_YCBCR601: + *color_coeff = COLOR_YCBCR601; + break; + case EDP_COLOR_COEFF_YCBCR709: + *color_coeff = COLOR_YCBCR709; + break; + default: + ret = HDF_FAILURE; + break; + } + + return ret; +} + +static int32_t EdpSetupAudioHardwareParams(struct AnalogixDpDevice *dp, enum EdpAudioInterfaceType ifType) +{ + int32_t ret = HDF_SUCCESS; + switch (ifType) { + case EDP_AUDIO_IF_TYPE_I2S: + EdpAudioConfigI2s(dp); + break; + case EDP_AUDIO_IF_TYPE_SPDIF: + EdpAudioConfigSpdif(dp); + break; + default: + ret = HDF_FAILURE; + break; + } + + return ret; +} + +static int32_t EdpVideoAttrCheck(HdfEdpAdapterData *edpAdapterData, const struct EdpVideoAttr *pAttr) +{ + int32_t ret = HDF_FAILURE; + struct RockchipDpDevice *drvData = platform_get_drvdata(edpAdapterData->platDev); + struct AnalogixDpDevice *dp = drvData->adp; + struct VideoInfo *info = &dp->videoInfo; + struct drm_display_mode *origMode = &info->mode; + struct drm_display_mode adjMode; + drm_mode_copy(&adjMode, origMode); + + ret = EdpColorDepthToBpc(&info->colorDepth, pAttr->colorDepth); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s EdpColorDepthToBpc %d\n", __func__, ret); + return ret; + } + + ret = EdpColorSpaceToFormat(&info->colorSpace, pAttr->colorSpace); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s EdpColorSpaceToFormat %d\n", __func__, ret); + return ret; + } + + ret = EdpColorCoeffToYCBCRCoeff(&info->ycbcrCoeff, pAttr->colorSpace); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s EdpColorCoeffToYCBCRCoeff %d\n", __func__, ret); + return ret; + } + + dp->bridge.funcs->mode_set(&dp->bridge, origMode, &adjMode); + ret = HDF_SUCCESS; + return ret; +} +#endif + +int32_t LinuxEdpAdapterInit(HdfEdpAdapterData *edpAdapterData) +{ +#ifdef CONFIG_ARCH_ROCKCHIP + int32_t ret = HDF_FAILURE; + if (NULL == edpAdapterData) { + HDF_LOGE("%s null adapter get\n", __func__); + return ret; + } + struct drm_panel *edpDrmPanel = NULL; + struct drm_bridge *edpDrmBridge = NULL; + struct drm_mode_config *drmConfig = NULL; + struct device_node *edpNode = NULL; + struct platform_device *platDev = NULL; + void *privData = NULL; + edpNode = of_find_node_by_path("/edp@fe0c0000"); + if (NULL == edpNode) { + HDF_LOGE("find edp dt node failed\n"); + return ret; + } + platDev = of_find_device_by_node(edpNode); + if (NULL == platDev) { + HDF_LOGE("find platform device of edp dt node failed\n"); + return ret; + } + privData = platform_get_drvdata(platDev); + if (privData == NULL) { + HDF_LOGE("edp device is not probed correctly"); + return HDF_FAILURE; + } + ret = drm_of_find_panel_or_bridge(edpNode, 1, -1, &edpDrmPanel, &edpDrmBridge); + if (HDF_SUCCESS != ret) { + HDF_LOGE("drm_of_find_panel_or_bridge failed: %d\n", ret); + return ret; + } + + if (!edpDrmBridge) { + edpDrmBridge = &((struct RockchipDpDevice *)privData)->adp->bridge; + } + + edpAdapterData->platDev = platDev; + edpAdapterData->node = edpNode; + edpAdapterData->drmPanel = edpDrmPanel; + edpAdapterData->drmBridge = edpDrmBridge; + edpAdapterData->connector = &((struct RockchipDpDevice *)privData)->adp->connector; + + ret = HDF_SUCCESS; + return ret; +#else + return HDF_FAILURE; +#endif +} + +void LinuxEdpAdapterDeInit(HdfEdpAdapterData *edpAdapterData) +{ +#ifdef CONFIG_ARCH_ROCKCHIP + if (edpAdapterData == NULL) { + HDF_LOGE("%s, edp priv data is null", __func__); + return; + } +#endif +} + +int32_t LinuxEdpDisable(HdfEdpAdapterData* edpAdapterData) +{ +#ifdef CONFIG_ARCH_ROCKCHIP + int32_t ret = HDF_FAILURE; + if (edpAdapterData->drmPanel == NULL) { + HDF_LOGE("%s, edp panel is null", __func__); + return ret; + } + + ret = drm_panel_disable(edpAdapterData->drmPanel); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s, disable panel failed", __func__); + } + + ret = drm_panel_unprepare(edpAdapterData->drmPanel); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s, panel unprepare failed\n"); + return ret; + } + return ret; +#else + return HDF_FAILURE; +#endif +} + +int32_t LinuxEdpEnable(HdfEdpAdapterData* edpAdapterData) +{ +#ifdef CONFIG_ARCH_ROCKCHIP + int32_t ret = HDF_FAILURE; + if (edpAdapterData->drmPanel == NULL) { + HDF_LOGE("%s, edp panel is null", __func__); + return ret; + } + + ret = drm_panel_enable(edpAdapterData->drmPanel); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s, enable panel failed", __func__); + } + + ret = drm_panel_prepare(edpAdapterData->drmPanel); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s, panel prepare failed\n"); + return ret; + } + return ret; +#else + return HDF_FAILURE; +#endif +} + +int32_t LinuxEdpDeepColorSet(HdfEdpAdapterData* edpAdapterData, uint32_t color) +{ +#ifdef CONFIG_ARCH_ROCKCHIP + int32_t ret = HDF_FAILURE; + struct RockchipDpDevice *drvData = NULL; + struct drm_display_info *info = NULL; + struct drm_display_mode *mode = NULL; + + if (edpAdapterData == NULL) { + HDF_LOGE("%s, edp priv data is null", __func__); + return ret; + } + + drvData = platform_get_drvdata(edpAdapterData->platDev); + info = &edpAdapterData->connector->display_info; + mode = &drvData->adp->videoInfo.mode; + //modify video bpc to setup color depth by edp driver + ret = EdpColorDepthToBpc(&info->bpc, color); + if (ret != 0) { + HDF_LOGE("EdpColorDepthToBpc failed: %d\n", ret); + return ret; + } + + drvData->adp->bridge.funcs->mode_set(&drvData->adp->bridge, mode, mode); + HDF_LOGI("EdpSetVideoColorFormat()!!\n"); + EdpSetVideoColorFormat(drvData->adp); + + if (ret != 0) { + HDF_LOGE("%s failed: %d\n", __func__, ret); + } + + return ret; +#else + return HDF_FAILURE; +#endif +} + +int32_t LinuxEdpDeepColorGet(HdfEdpAdapterData* edpAdapterData, uint32_t *color) +{ +#ifdef CONFIG_ARCH_ROCKCHIP + int32_t ret = HDF_FAILURE; + struct RockchipDpDevice *drvData = NULL; + + if (edpAdapterData == NULL || color == NULL) { + HDF_LOGE("%s, edp priv data is null", __func__); + return ret; + } + + drvData = platform_get_drvdata(edpAdapterData->platDev); + if (drvData == NULL) { + HDF_LOGE("%s: drvData is null!", __func__); + return HDF_FAILURE; + } + HDF_LOGI("drm_display_info %x!!\n", edpAdapterData->connector); + drvData->platData.get_modes(&drvData->platData, edpAdapterData->connector); + struct drm_display_info *info = &edpAdapterData->connector->display_info; + ret = EdpBpcToColorDepth(info->bpc, color); + + return ret; +#else + return HDF_FAILURE; +#endif +} + +int32_t LinuxEdpAvMuteSet(HdfEdpAdapterData *edpAdapterData, bool enable) +{ +#ifdef CONFIG_ARCH_ROCKCHIP + //only for DP to HDMI + int32_t ret = HDF_SUCCESS; + struct RockchipDpDevice *drvData = NULL; + if (edpAdapterData == NULL) { + HDF_LOGE("%s, edp priv data is null", __func__); + return ret; + } + + drvData = platform_get_drvdata(edpAdapterData->platDev); + if (drvData == NULL) { + HDF_LOGE("%s: drvData is null!", __func__); + return HDF_FAILURE; + } + EdpEnableVideoMute(drvData->adp, enable); + return ret; +#else + return HDF_FAILURE; +#endif +} + +int32_t LinuxEdpSetVideoAttribute(HdfEdpAdapterData *edpAdapterData, const void *attr) +{ +#ifdef CONFIG_ARCH_ROCKCHIP + int32_t ret = HDF_SUCCESS; + struct RockchipDpDevice *drvData = NULL; + const struct EdpVideoAttr *pAttr = NULL; + struct VideoInfo *info = NULL; + + if (edpAdapterData == NULL || attr == NULL) { + HDF_LOGE("%s, edp priv data is null", __func__); + return ret; + } + + drvData = platform_get_drvdata(edpAdapterData->platDev); + if (drvData == NULL) { + HDF_LOGE("%s: drvData is null!", __func__); + return HDF_FAILURE; + } + + pAttr = (const struct EdpVideoAttr *)attr; + info = &drvData->adp->videoInfo; + ret = EdpVideoAttrCheck(edpAdapterData, pAttr); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s EdpVideoAttrCheck failed", __func__); + return ret; + } + EdpSetVideoColorFormat(drvData->adp); + EdpSetVideoFormat(drvData->adp); + return ret; +#else + return HDF_FAILURE; +#endif +} + +int32_t LinuxEdpSetAudioAttribute(HdfEdpAdapterData *edpAdapterData, const void *attr) +{ +#ifdef CONFIG_ARCH_ROCKCHIP + //For DP to HDMI only + int32_t ret = HDF_SUCCESS; + struct RockchipDpDevice *drvData = NULL; + const struct EdpAudioAttr *pAttr = NULL; + + if (edpAdapterData == NULL || attr == NULL) { + HDF_LOGE("%s, edp priv data is null", __func__); + return ret; + } + + drvData = platform_get_drvdata(edpAdapterData->platDev); + if (drvData == NULL) { + HDF_LOGE("%s: drvData is null!", __func__); + return HDF_FAILURE; + } + + pAttr = (const struct EdpAudioAttr*)attr; + EdpSetupAudioHardwareParams(drvData->adp, pAttr->ifType); + + return ret; +#else + return HDF_FAILURE; +#endif +} + +static void EdpHpdCallback(void *data, enum drm_connector_status status) +{ + HdfEdpAdapterData *edpAdapterData = NULL; + if (data == NULL) { + HDF_LOGE("%s, edp priv data is null", __func__); + return; + } + edpAdapterData = (HdfEdpAdapterData *)data; + bool hpd = false; + switch (status) { + case connector_status_connected: + hpd = true; + break; + case connector_status_disconnected: + default: + hpd = false; + break; + } + struct EdpCntlr *cntlr = (struct EdpCntlr *)edpAdapterData->hdfHdl; + cntlr->hpdCbInfo->callbackFunc(data, hpd); +} + +int32_t LinuxEdpRegisterHpdCallbackFunc(HdfEdpAdapterData *edpAdapterData, void *hpdcb) +{ +#ifdef CONFIG_ARCH_ROCKCHIP + int32_t ret = HDF_SUCCESS; + struct RockchipDpDevice *drvData = NULL; + + if (edpAdapterData == NULL || hpdcb == NULL) { + HDF_LOGE("%s, edp priv data is null", __func__); + return HDF_FAILURE; + } + //hpd is not supported for this device + drvData = platform_get_drvdata(edpAdapterData->platDev); + if (drvData == NULL) { + HDF_LOGE("%s: drvData is null!", __func__); + return HDF_FAILURE; + } + + drm_bridge_hpd_enable(&drvData->adp->bridge, EdpHpdCallback, (void *)edpAdapterData); + return ret; +#else + return HDF_FAILURE; +#endif +} + +int32_t LinuxEdpUnRegisterHpdCallbackFunc(HdfEdpAdapterData *edpAdapterData) +{ +#ifdef CONFIG_ARCH_ROCKCHIP + struct RockchipDpDevice *drvData = NULL; + if (edpAdapterData == NULL) { + HDF_LOGE("%s, edp priv data is null", __func__); + return HDF_FAILURE; + } + + drvData = platform_get_drvdata(edpAdapterData->platDev); + if (drvData == NULL) { + HDF_LOGE("%s: drvData is null!", __func__); + return HDF_FAILURE; + } + drm_bridge_hpd_disable(&drvData->adp->bridge); + return HDF_SUCCESS; +#else + return HDF_FAILURE; +#endif +} + +int32_t LinuxEdpGetConnector(HdfEdpAdapterData *edpAdapterData, void **connector) +{ +#ifdef CONFIG_ARCH_ROCKCHIP + int32_t ret = HDF_SUCCESS; + struct RockchipDpDevice *drvData = NULL; + if (edpAdapterData == NULL || connector == NULL) { + HDF_LOGE("%s, edp priv data is null", __func__); + return HDF_FAILURE; + } + + drvData = platform_get_drvdata(edpAdapterData->platDev); + if (drvData == NULL) { + HDF_LOGE("%s: drvData is null!", __func__); + return HDF_FAILURE; + } + + *connector = (void *)&drvData->adp->connector; + return ret; +#else + return HDF_FAILURE; +#endif +} diff --git a/adapter/khdf/linux/platform/edp/edp_rk35xx.h b/adapter/khdf/linux/platform/edp/edp_rk35xx.h new file mode 100644 index 0000000000000000000000000000000000000000..73635674b7ed43bf592143c03cef53d1a97bd250 --- /dev/null +++ b/adapter/khdf/linux/platform/edp/edp_rk35xx.h @@ -0,0 +1,267 @@ +/* + * Copyright (c) 2023-2024 Huawei Device Co., Ltd. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * 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. + * + */ + +#ifndef EDP_RK35XX_H +#define EDP_RK35XX_H + +#include + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif /* __cplusplus */ + +struct RockchipDrmSubDev; + +enum LinkLaneCountType { + LANE_COUNT1 = 1, + LANE_COUNT2 = 2, + LANE_COUNT4 = 4 +}; + +enum LinkTrainingState { + START, + CLOCK_RECOVERY, + EQUALIZER_TRAINING, + FINISHED, + FAILED +}; + +enum ColorSpace { + COLOR_RGB, + COLOR_YCBCR422, + COLOR_YCBCR444 +}; + +enum ColorDepth { + COLOR_6, + COLOR_8, + COLOR_10, + COLOR_12 +}; + +enum ColorCoefficient { + COLOR_YCBCR601, + COLOR_YCBCR709 +}; + +enum DynamicRange { + VESA, + CEA +}; + +enum VideoTimingRecognitionType { + VIDEO_TIMING_FROM_CAPTURE, + VIDEO_TIMING_FROM_REGISTER +}; + +struct RockchipDrmSubDev { + struct list_head list; + struct drm_connector *connector; + struct device_node *of_node; + void (*loaderProtect)(struct drm_encoder *encoder, bool on); + void (*oobHotplugEvent)(struct drm_connector *connector); +}; + +struct VideoInfo { + char *name; + struct drm_display_mode mode; + bool hSyncPolarity; + bool vSyncPolarity; + bool interlaced; + enum ColorSpace colorSpace; + enum DynamicRange dynamicRange; + enum ColorCoefficient ycbcrCoeff; + enum ColorDepth colorDepth; + int maxLinkRate; + enum LinkLaneCountType maxLaneCount; + bool videoBistEnable; +}; + +struct LinkTrain { + int eqLoop; + int crLoop[4]; + u8 linkRate; + u8 laneCount; + u8 trainingLane[4]; + bool ssc; + bool enhancedFraming; + enum LinkTrainingState ltState; +}; + +struct AnalogixDpDevice { + struct drm_encoder *encoder; + struct device *dev; + struct drm_device *drmDev; + struct drm_connector connector; + struct drm_bridge bridge; + struct drm_dp_aux aux; + struct clk_bulk_data *clks; + int nrClks; + unsigned int irq; + void __iomem *regBase; + struct VideoInfo videoInfo; + struct LinkTrain linkTrain; + struct phy *phy; + bool phyEnabled; + int dpmsMode; + struct gpio_desc *hpdGpiod; + bool forceHpd; + bool fastTrainEnable; + bool psrSupported; + struct mutex panelLock; + bool panelIsPrepared; + struct analogix_dp_plat_data *platData; +}; + +struct RockchipGrfRegField { + unsigned int reg; + unsigned int lsb; + unsigned int msb; + bool valid; +}; + +/** + * struct RockchipDpChipData - splite the grf setting of kind of chips + * @lcdcSel: grf register field of lcdcSel + * @spdifSel: grf register field of spdifSel + * @i2sSel: grf register field of i2sSel + * @edpMode: grf register field of edpMode + * @chipType: specific chip type + * @ssc: check if SSC is supported by source + * @audio: check if audio is supported by source + * @splitMode: check if split mode is supported + */ +struct RockchipDpChipData { + const struct RockchipGrfRegField lcdcSel; + const struct RockchipGrfRegField spdifSel; + const struct RockchipGrfRegField i2sSel; + const struct RockchipGrfRegField edpMode; + u32 chipType; + bool ssc; + bool audio; + bool splitMode; +}; + +struct RockchipDpDevice { + struct drm_device *drmDev; + struct device *dev; + struct drm_encoder encoder; + struct drm_bridge *bridge; + struct drm_display_mode mode; + struct regmap *grf; + struct reset_control *rst; + struct reset_control *apbReset; + struct platform_device *audioPdev; + const struct RockchipDpChipData *data; + int id; + struct AnalogixDpDevice *adp; + struct analogix_dp_plat_data platData; + struct RockchipDrmSubDev subDev; +}; + +#ifndef DP_RECEIVER_CAP_SIZE +#define DP_RECEIVER_CAP_SIZE 0xf +#endif +#define MAX_PHY 2 + +enum AudioFormat { + AFMT_I2S = 0, + AFMT_SPDIF = 1, + AFMT_UNUSED, +}; + +struct AudioInfo { + enum AudioFormat format; + int sampleRate; + int channels; + int sampleWidth; +}; + +enum VicPxlEncodingFormat { + PXL_RGB = 0x1, + YCBCR_4_4_4 = 0x2, + YCBCR_4_2_2 = 0x4, + YCBCR_4_2_0 = 0x8, + Y_ONLY = 0x10, +}; + +struct VideoInfos { + bool hSyncPolarity; + bool vSyncPolarity; + bool interlaced; + int colorDepth; + enum VicPxlEncodingFormat colorFmt; +}; + +struct CdnDpPort { + struct CdnDpDevice *dp; + struct phy *phy; + u8 lanes; + bool phyEnabled; + u8 id; +}; + +struct CdnDpDevice { + struct device *dev; + struct drm_device *drmDev; + struct drm_connector connector; + struct drm_encoder encoder; + struct drm_display_mode mode; + struct platform_device *audioPdev; + struct delayed_work eventWork; + struct edid *edid; + struct RockchipDrmSubDev subDev; + struct mutex lock; + bool connected; + bool active; + bool suspended; + const struct firmware *fw; /* cdn dp firmware */ + unsigned int fwVersion; /* cdn fw version */ + bool fwLoaded; + void __iomem *regs; + struct regmap *grf; + struct clk *coreClk; + struct clk *pclk; + struct clk *spdifClk; + struct clk *grfClk; + struct reset_control *spdifRst; + struct reset_control *dptxRst; + struct reset_control *apbRst; + struct reset_control *coreRst; + struct AudioInfo audioInfo; + struct VideoInfos videoInfo; + struct CdnDpPort *port[MAX_PHY]; + u8 ports; + u8 maxLanes; + unsigned int maxRate; + u8 lanes; + int activePort; + u8 dpcd[DP_RECEIVER_CAP_SIZE]; + bool sinkHasAudio; +}; + +extern void EdpSetVideoFormat(struct AnalogixDpDevice *dp); +extern void EdpEnableVideoMute(struct AnalogixDpDevice *dp, bool enable); +extern void EdpSetVideoColorFormat(struct AnalogixDpDevice *dp); +extern void EdpAudioConfigSpdif(struct AnalogixDpDevice *dp); +extern void EdpAudioConfigI2s(struct AnalogixDpDevice *dp); +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif /* __cplusplus */ + +#endif //EDP_RK35XX_H \ No newline at end of file diff --git a/adapter/khdf/linux/platform/platform.mk b/adapter/khdf/linux/platform/platform.mk index 95a222f1393a7402d53c46da0f813612ca124988..2b8c37fc07891da755d85470ba35788c53f5e49f 100644 --- a/adapter/khdf/linux/platform/platform.mk +++ b/adapter/khdf/linux/platform/platform.mk @@ -26,6 +26,7 @@ ccflags-$(CONFIG_DRIVERS_HDF_PLATFORM) +=-I$(srctree)/drivers/hdf/framework/incl -I$(srctree)/drivers/hdf/framework/support/platform/include/i3c \ -I$(srctree)/drivers/hdf/framework/support/platform/include/mipi \ -I$(srctree)/drivers/hdf/framework/support/platform/include/pwm \ + -I$(srctree)/drivers/hdf/framework/support/platform/include/edp \ -I$(srctree)/drivers/hdf/framework/support/platform/include/rtc \ -I$(srctree)/drivers/hdf/framework/support/platform/include/spi \ -I$(srctree)/drivers/hdf/framework/support/platform/include/uart \ diff --git a/adapter/khdf/linux/test/Makefile b/adapter/khdf/linux/test/Makefile index 1de758bffbd68ce4bd264a685b31b95bf1926c5f..f39a0241b7fb8406593ed939e7a61d4fea359be7 100644 --- a/adapter/khdf/linux/test/Makefile +++ b/adapter/khdf/linux/test/Makefile @@ -79,6 +79,8 @@ obj-$(CONFIG_DRIVERS_HDF_PLATFORM_MIPI_DSI) += $(HDF_FRAMWORK_TEST_ROOT)/platfor $(HDF_FRAMWORK_TEST_ROOT)/platform/entry/hdf_mipi_dsi_entry_test.o obj-$(CONFIG_DRIVERS_HDF_PLATFORM_MIPI_CSI) += $(HDF_FRAMWORK_TEST_ROOT)/platform/common/mipi_csi_test.o \ $(HDF_FRAMWORK_TEST_ROOT)/platform/entry/hdf_mipi_csi_entry_test.o +obj-$(CONFIG_DRIVERS_HDF_PLATFORM_EDP) += $(HDF_FRAMWORK_TEST_ROOT)/platform/common/edp_test.o \ + $(HDF_FRAMWORK_TEST_ROOT)/platform/entry/hdf_edp_entry_test.o obj-$(CONFIG_DRIVERS_HDF_PLATFORM_REGULATOR) += $(HDF_FRAMWORK_TEST_ROOT)/platform/common/regulator_test.o \ $(HDF_FRAMWORK_TEST_ROOT)/platform/entry/hdf_regulator_entry_test.o \ $(HDF_FRAMWORK_TEST_ROOT)/platform/virtual/regulator_linux_voltage_virtual_driver.o \ diff --git a/framework/include/platform/edp_if.h b/framework/include/platform/edp_if.h new file mode 100644 index 0000000000000000000000000000000000000000..e5baf17456b33e64304a357275f3e0304fa8b657 --- /dev/null +++ b/framework/include/platform/edp_if.h @@ -0,0 +1,307 @@ +/* + * Copyright (c) 2023-2024 Huawei Device Co., Ltd. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * 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. + * + */ + +#ifndef EDP_IF_H +#define EDP_IF_H + +#include "platform_if.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif /* __cplusplus */ + +enum EdpColorDepth { + EDP_COLOR_DEPTH_NONE = 0, + EDP_COLOR_DEPTH_6BIT = 6, + EDP_COLOR_DEPTH_8BIT = 8, + EDP_COLOR_DEPTH_10BIT = 10, + EDP_COLOR_DEPTH_12BIT = 12, + EDP_COLOR_DEPTH_INVALID, +}; + +enum EdpColorSpace { + EDP_COLOR_SPACE_RGB = 0, + EDP_COLOR_SPACE_YCBCR422 = 1, + EDP_COLOR_SPACE_YCBCR444 = 2, +}; + +enum EdpColorCoefficient { + EDP_COLOR_COEFF_YCBCR601, + EDP_COLOR_COEFF_YCBCR709, +}; + +enum EdpDynamicRange { + EDP_DYNAMIC_RANGE_VESA, + EDP_DYNAMIC_RANGE_CEA, +}; + +enum EdpVideoTimingRecognitionType { + EDP_VIDEO_TIMING_FROM_CAPTURE, + EDP_VIDEO_TIMING_FROM_REGISTER +}; + +/** + * extracted from drm + * enum dp_colorimetry - drm DP Colorimetry formats + * + * This enum is used to indicate DP VSC SDP Colorimetry formats. + * It is based on DP 1.4 spec [Table 2-117: VSC SDP Payload for DB16 through + * DB18] and a name of enum member follows DRM_MODE_COLORIMETRY definition. + * + * @DP_COLORIMETRY_DEFAULT: sRGB (IEC 61966-2-1) or + * ITU-R BT.601 colorimetry format + * @DP_COLORIMETRY_RGB_WIDE_FIXED: RGB wide gamut fixed point colorimetry format + * @DP_COLORIMETRY_BT709_YCC: ITU-R BT.709 colorimetry format + * @DP_COLORIMETRY_RGB_WIDE_FLOAT: RGB wide gamut floating point + * (scRGB (IEC 61966-2-2)) colorimetry format + * @DP_COLORIMETRY_XVYCC_601: xvYCC601 colorimetry format + * @DP_COLORIMETRY_OPRGB: OpRGB colorimetry format + * @DP_COLORIMETRY_XVYCC_709: xvYCC709 colorimetry format + * @DP_COLORIMETRY_DCI_P3_RGB: DCI-P3 (SMPTE RP 431-2) colorimetry format + * @DP_COLORIMETRY_SYCC_601: sYCC601 colorimetry format + * @DP_COLORIMETRY_RGB_CUSTOM: RGB Custom Color Profile colorimetry format + * @DP_COLORIMETRY_OPYCC_601: opYCC601 colorimetry format + * @DP_COLORIMETRY_BT2020_RGB: ITU-R BT.2020 R' G' B' colorimetry format + * @DP_COLORIMETRY_BT2020_CYCC: ITU-R BT.2020 Y'c C'bc C'rc colorimetry format + * @DP_COLORIMETRY_BT2020_YCC: ITU-R BT.2020 Y' C'b C'r colorimetry format + */ +enum EdpColorimetry { + EDP_COLORIMETRY_DEFAULT = 0, + EDP_COLORIMETRY_RGB_WIDE_FIXED = 0x1, + EDP_COLORIMETRY_BT709_YCC = 0x1, + EDP_COLORIMETRY_RGB_WIDE_FLOAT = 0x2, + EDP_COLORIMETRY_XVYCC_601 = 0x2, + EDP_COLORIMETRY_OPRGB = 0x3, + EDP_COLORIMETRY_XVYCC_709 = 0x3, + EDP_COLORIMETRY_DCI_P3_RGB = 0x4, + EDP_COLORIMETRY_SYCC_601 = 0x4, + EDP_COLORIMETRY_RGB_CUSTOM = 0x5, + EDP_COLORIMETRY_OPYCC_601 = 0x5, + EDP_COLORIMETRY_BT2020_RGB = 0x6, + EDP_COLORIMETRY_BT2020_CYCC = 0x6, + EDP_COLORIMETRY_BT2020_YCC = 0x7, +}; + +enum EdpSampleRate { + EDP_SAMPLE_RATE_UNKNOWN, + EDP_SAMPLE_RATE_8K = 8000, + EDP_SAMPLE_RATE_11K = 11025, + EDP_SAMPLE_RATE_12K = 12000, + EDP_SAMPLE_RATE_16K = 16000, + EDP_SAMPLE_RATE_22K = 22050, + EDP_SAMPLE_RATE_24K = 24000, + EDP_SAMPLE_RATE_32K = 32000, + EDP_SAMPLE_RATE_44K = 44100, + EDP_SAMPLE_RATE_48K = 48000, + EDP_SAMPLE_RATE_88K = 88200, + EDP_SAMPLE_RATE_96K = 96000, + EDP_SAMPLE_RATE_176K = 176400, + EDP_SAMPLE_RATE_192K = 192000, + EDP_SAMPLE_RATE_768K = 768000, + EDP_SAMPLE_RATE_BUTT, +}; + +enum EdpAudioBitDepth { + EDP_AUDIO_BIT_DEPTH_UNKNOWN, + EDP_AUDIO_BIT_DEPTH_8 = 8, + EDP_AUDIO_BIT_DEPTH_16 = 16, + EDP_AUDIO_BIT_DEPTH_18 = 18, + EDP_AUDIO_BIT_DEPTH_20 = 20, + EDP_AUDIO_BIT_DEPTH_24 = 24, + EDP_AUDIO_BIT_DEPTH_32 = 32, + EDP_AUDIO_BIT_DEPTH_BUTT, +}; + +enum EdpAudioCodingType { + EDP_AUDIO_CODING_TYPE_STREAM = 0, + EDP_AUDIO_CODING_TYPE_LPCM = 1, + EDP_AUDIO_CODING_TYPE_AC3 = 2, + EDP_AUDIO_CODING_TYPE_MPEG1 = 3, + EDP_AUDIO_CODING_TYPE_MP3 = 4, + EDP_AUDIO_CODING_TYPE_MPEG2 = 5, + EDP_AUDIO_CODING_TYPE_AAC_LC = 6, + EDP_AUDIO_CODING_TYPE_DTS = 7, + EDP_AUDIO_CODING_TYPE_ATRAC = 8, + EDP_AUDIO_CODING_TYPE_OBA = 9, + EDP_AUDIO_CODING_TYPE_EAC3 = 10, + EDP_AUDIO_CODING_TYPE_DTS_HD = 11, + EDP_AUDIO_CODING_TYPE_MLP = 12, + EDP_AUDIO_CODING_TYPE_DST = 13, + EDP_AUDIO_CODING_TYPE_WMA_PRO = 14, + EDP_AUDIO_CODING_TYPE_CXT = 15, +}; + +enum EdpVideoTiming { + EDP_VIDEO_TIMING_NONE = 0, + EDP_VIDEO_TIMING_640X480P60 = 1, + EDP_VIDEO_TIMING_720X480P60 = 2, + EDP_VIDEO_TIMING_1280X720P60 = 3, + EDP_VIDEO_TIMING_1920X1080P60 = 4, +}; + +enum EdpAudioInterfaceType { + EDP_AUDIO_IF_TYPE_I2S = 0, /* Inter-IC Sound */ + EDP_AUDIO_IF_TYPE_SPDIF = 1, /* Sony/Philips Digital Interface */ + EDP_AUDIO_IF_TYPE_OTHER, +}; + +enum EdpAudioFormatChannel { + EDP_AUDIO_FORMAT_CHANNEL_2 = 2, + EDP_AUDIO_FORMAT_CHANNEL_3, + EDP_AUDIO_FORMAT_CHANNEL_4, + EDP_AUDIO_FORMAT_CHANNEL_5, + EDP_AUDIO_FORMAT_CHANNEL_6, + EDP_AUDIO_FORMAT_CHANNEL_7, + EDP_AUDIO_FORMAT_CHANNEL_8, + EDP_AUDIO_FORMAT_CHANNEL_BUTT, +}; + +struct EdpVideoAttr { + uint32_t tmdsClock; /* unit: KHz */ + uint32_t pixelClock; /* unit: KHz */ + uint32_t pixelRepeat; + enum EdpColorSpace colorSpace; + enum EdpColorimetry colorimetry; + enum EdpColorDepth colorDepth; + enum EdpColorCoefficient colorCoeff; + enum EdpVideoTiming timing; +}; + +struct EdpAudioAttr { + enum EdpAudioCodingType codingType; + enum EdpAudioInterfaceType ifType; + enum EdpAudioBitDepth bitDepth; + enum EdpSampleRate sampleRate; + bool downSample; + enum EdpAudioFormatChannel channels; +}; + +struct EdpHpdCallbackInfo { + void *data; + void (*callbackFunc)(void *data, bool hpd); +}; + +/** + * @brief EdpOpen open Edp device by bus number + * + * @param busNum bus number of the target screen + * @return DevHandle handler of the target, return NULL while error occurs + */ +DevHandle EdpOpen(uint16_t busNum); + +/** + * @brief release handle resources both in user space and kernel space, + * It just release resources which is related to the handle. + * + * @param handle device handler + */ +void EdpClose(DevHandle handle); + +/** + * @brief EdpAvmuteSet mute edp audio output + * + * @param handle device handler of target + * @param enable true for muting output/false for turning on output + * @return int32_t 0 for sucess, other for error + */ +int32_t EdpAvmuteSet(DevHandle handle, bool enable); + +/** + * @brief EdpDeepColorSet setup deep color for screen + * + * @param handle device handler + * @param color color data for setup + * @return int32_t 0 for success, other for error + */ +int32_t EdpDeepColorSet(DevHandle handle, enum EdpColorDepth color); + +/** + * @brief EdpDeepColorGet fetch deep color current data from hdf service + * + * @param handle device handler + * @param color memory for get the data from hdf service + * @return int32_t 0 for sucess, other for error + */ +int32_t EdpDeepColorGet(DevHandle handle, enum EdpColorDepth *color); + +/** + * @brief EdpSetVideoAttribute setup video attribute + * + * @param handle device handler + * @param attr video attribute details for setup + * @return int32_t 0 for sucess, other for error + */ +int32_t EdpSetVideoAttribute(DevHandle handle, struct EdpVideoAttr *attr); + +/** + * @brief EdpSetAudioAttribute setup audio attribute + * + * @param handle device handler + * @param attr audio attribute details for setup + * @return int32_t 0 for sucess, other for error + */ +int32_t EdpSetAudioAttribute(DevHandle handle, struct EdpAudioAttr *attr); + +/** + * @brief EdpRegisterHpdCallbackFunc register callback for hpd event? + * + * I don't think this api can be implement in user space + * @param handle + * @param callback + * @return int32_t + */ +int32_t EdpRegisterHpdCallbackFunc(DevHandle handle, struct EdpHpdCallbackInfo *callback); + +/** + * @brief EdpUnregisterHpdCallbackFunc remove the registered hpd event cb in kernel space + * This is a terrible interface to perform this operation from a user request + * @param handle device handler + * @return int32_t + */ +int32_t EdpUnregisterHpdCallbackFunc(DevHandle handle); + +/** + * @brief EdpGetConnector get eDP connector handle + * + * @param handle device handler + * @param connector DevHandle conatainer to get connector + * @return int32_t + */ +int32_t EdpGetConnector(DevHandle handle, DevHandle *connector); + +/** + * @brief EdpDisable disable current edp panel + * + * @param handle device handler + * @return int32_t + */ +int32_t EdpDisable(DevHandle handle); + +/** + * @brief EdpEnable enable current edp panel + * + * @param handle device handler + * @return int32_t + */ +int32_t EdpEnable(DevHandle handle); + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif /* __cplusplus */ + +#endif //EDP_IF_H \ No newline at end of file diff --git a/framework/model/display/driver/panel/lcd_edp.c b/framework/model/display/driver/panel/lcd_edp.c new file mode 100644 index 0000000000000000000000000000000000000000..747d22c3d8bbd5bbd5198e9c4d51b9b352e648dc --- /dev/null +++ b/framework/model/display/driver/panel/lcd_edp.c @@ -0,0 +1,228 @@ +/* + * Copyright (c) 2023-2024 Huawei Device Co., Ltd. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * 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. + * + */ + +#include "lcd_edp.h" +#include "gpio_if.h" +#include "hdf_bl.h" +#include "hdf_disp.h" +#include "osal.h" +#include "hcs_tree_if.h" + +struct panel_edp_dev *g_edpPanelDev = NULL; + +static struct panel_edp_dev *ToPanelSimpleDev(const struct PanelData *panel) +{ + return (struct panel_edp_dev *)panel->object->priv; +} + +static int32_t PanelOn(struct PanelData *panel) +{ + struct panel_edp_dev *panelDev = NULL; + + panelDev = ToPanelSimpleDev(panel); + if (panelDev->hwDelay.enableDelay) { + OsalMSleep(panelDev->hwDelay.enableDelay); + } + return HDF_SUCCESS; +} + +static int32_t PanelOff(struct PanelData *panel) +{ + struct panel_edp_dev *panelDev = NULL; + + panelDev = ToPanelSimpleDev(panel); + if (panelDev->hwDelay.disableDelay) { + OsalMSleep(panelDev->hwDelay.disableDelay); + } + return HDF_SUCCESS; +} + +static int32_t PanelPrepare(struct PanelData *panel) +{ + int32_t ret; + struct panel_edp_dev *panelDev = NULL; + + panelDev = ToPanelSimpleDev(panel); + ret = regulator_enable(panelDev->supply); + if (ret < 0) { + HDF_LOGE("failed to enable supply: %d\n", ret); + return ret; + } + gpiod_set_value_cansleep(panelDev->enableGpio, 1); + + if (panelDev->hwDelay.resetDelay > 0) { + OsalMSleep(panelDev->hwDelay.resetDelay); + } + + gpiod_set_value_cansleep(panelDev->resetGpio, 1); + + if (panelDev->hwDelay.resetDelay > 0) { + OsalMSleep(panelDev->hwDelay.resetDelay); + } + + gpiod_set_value_cansleep(panelDev->resetGpio, 0); + + if (panelDev->hwDelay.prepareDelay > 0) { + OsalMSleep(panelDev->hwDelay.prepareDelay); + } + + if (panelDev->hwDelay.initDelay > 0) { + OsalMSleep(panelDev->hwDelay.initDelay); + } + + return HDF_SUCCESS; +} + +static int32_t PanelUnprepare(struct PanelData *panel) +{ + struct panel_edp_dev *panelDev = NULL; + + panelDev = ToPanelSimpleDev(panel); + + gpiod_set_value_cansleep(panelDev->resetGpio, 1); + gpiod_set_value_cansleep(panelDev->enableGpio, 0); + regulator_disable(panelDev->supply); + + if (panelDev->hwDelay.unprepareDelay) { + OsalMSleep(panelDev->hwDelay.unprepareDelay); + } + + return HDF_SUCCESS; +} + +static int32_t PanelInit(struct PanelData *panel) +{ + return 0; +} + +#define BLK_PWM_INDEX 2 +#define PWM_MAX_PERIOD 40000 +/* backlight setting */ +#define MIN_LEVEL 0 +#define MAX_LEVEL 255 +#define DEFAULT_LEVEL 127 + +static struct PanelInfo g_panelInfo = { + .width = 1920, /* width */ + .height = 1080, /* height */ + .hbp = 48, /* horizontal back porch */ + .hfp = 88, /* horizontal front porch */ + .hsw = 44, /* horizontal sync width */ + .vbp = 36, /* vertical back porch */ + .vfp = 4, /* vertical front porch */ + .vsw = 5, /* vertical sync width */ + .clockFreq = 70600000, /* clock */ + .pWidth = 298, /* physical width */ + .pHeight = 168, /* physical height */ + .connectorType = DRM_MODE_CONNECTOR_DPI, /* DRM_MODE_CONNECTOR_DPI=17 */ + .blk = { BLK_PWM, MIN_LEVEL, MAX_LEVEL, DEFAULT_LEVEL }, +}; + +static void PanelResInit(struct panel_edp_dev *panelDev) +{ + panelDev->panel.info = &g_panelInfo; + panelDev->panel.init = PanelInit; + panelDev->panel.on = PanelOn; + panelDev->panel.off = PanelOff; + panelDev->panel.prepare = PanelPrepare; + panelDev->panel.unprepare = PanelUnprepare; + panelDev->panel.priv = panelDev->edpDev; + panelDev->hwDelay.disableDelay = 50; /* 50:disableDelay time */ + panelDev->hwDelay.enableDelay = 120; /* 120:enableDelay */ + panelDev->hwDelay.initDelay = 20; /* 20:initDelay */ + panelDev->hwDelay.prepareDelay = 20; /* 20:prepareDelay */ + panelDev->hwDelay.resetDelay = 20; /* 20:resetDelay */ + panelDev->hwDelay.unprepareDelay = 20; /* 20:unprepareDelay */ +} + +static int32_t PanelEDPDevInit(struct panel_edp_dev *panelDev) +{ + panelDev->supply = devm_regulator_get(panelDev->edpDev, "power"); + if (panelDev->supply == NULL) { + HDF_LOGE("%s Get regulator fail", __func__); + goto FAIL; + } + + panelDev->enableGpio = devm_gpiod_get_optional(panelDev->edpDev, "enable", GPIOD_ASIS); + if (IS_ERR(panelDev->enableGpio)) { + HDF_LOGE("%s get enableGpio fail", __func__); + goto FAIL; + } + panelDev->hpdGpio = devm_gpiod_get_optional(panelDev->edpDev, "hpd", GPIOD_IN); + if (IS_ERR(panelDev->hpdGpio)) { + HDF_LOGE("%s get hpdGpio fail", __func__); + goto FAIL; + } + panelDev->resetGpio = devm_gpiod_get_optional(panelDev->edpDev, "reset", GPIOD_ASIS); + if (IS_ERR(panelDev->resetGpio)) { + HDF_LOGE("%s get resetGpio fail", __func__); + goto FAIL; + } + + return HDF_SUCCESS; +FAIL: + return HDF_FAILURE; +} + +static int32_t PanelEDPEntryInit(struct HdfDeviceObject *object) +{ + struct device_node *panelNode = NULL; + struct panel_edp_dev *panelDev = NULL; + struct platform_device *edpPlatformDev; + + panelDev = (struct panel_edp_dev *)OsalMemCalloc(sizeof(struct panel_edp_dev)); + if (panelDev == NULL) { + HDF_LOGE("%s panelDev malloc fail", __func__); + return HDF_FAILURE; + } + g_edpPanelDev = panelDev; + panelNode = of_find_compatible_node(NULL, NULL, "simple-panel"); + if (panelNode == NULL) { + HDF_LOGE("%s of_find_compatible_node fail", __func__); + goto FAIL; + } + + edpPlatformDev = of_find_device_by_node(panelNode); + panelDev->edpDev = &edpPlatformDev->dev; + if (panelDev->edpDev == NULL) { + HDF_LOGE("%s of_find_device_by_node fail", __func__); + goto FAIL; + } + + if (PanelEDPDevInit(panelDev) != HDF_SUCCESS) { + goto FAIL; + } + + PanelResInit(panelDev); + panelDev->panel.object = object; + object->priv = panelDev; + + if (RegisterPanel(&panelDev->panel) != HDF_SUCCESS) { + HDF_LOGE("%s RegisterPanel fail", __func__); + goto FAIL; + } + HDF_LOGI("%s success", __func__); + return HDF_SUCCESS; +FAIL: + OsalMemFree(panelDev); + return HDF_FAILURE; +} + +struct HdfDriverEntry PanelEDPDevEntry = { + .moduleVersion = 1, + .moduleName = "LCD_EDP", + .Init = PanelEDPEntryInit, +}; + +HDF_INIT(PanelEDPDevEntry); diff --git a/framework/model/display/driver/panel/lcd_edp.h b/framework/model/display/driver/panel/lcd_edp.h new file mode 100644 index 0000000000000000000000000000000000000000..77aa903a2cfabf8cf25effbe313e37cb7d219959 --- /dev/null +++ b/framework/model/display/driver/panel/lcd_edp.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2023-2024 Huawei Device Co., Ltd. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * 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. + * + */ + +#ifndef LCD_EDP_H +#define LCD_EDP_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include "hdf_disp.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +struct panel_edp_hw_delay { + uint32_t prepareDelay; + uint32_t hpdAbsentDelay; + uint32_t enableDelay; + uint32_t disableDelay; + uint32_t unprepareDelay; + uint32_t resetDelay; + uint32_t initDelay; +}; + +struct panel_edp_dev { + bool powerInvert; + struct PanelData panel; + struct device *edpDev; + struct regulator *supply; + struct gpio_desc *enableGpio; + struct gpio_desc *resetGpio; + struct gpio_desc *hpdGpio; + struct panel_edp_hw_delay hwDelay; +}; + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif + +#endif //LCD_EDP_H \ No newline at end of file diff --git a/framework/support/platform/include/edp/edp_core.h b/framework/support/platform/include/edp/edp_core.h new file mode 100644 index 0000000000000000000000000000000000000000..fea045a77760ef6dc2dde6ed56e63a89bca64326 --- /dev/null +++ b/framework/support/platform/include/edp/edp_core.h @@ -0,0 +1,193 @@ +/* + * Copyright (c) 2023-2024 Huawei Device Co., Ltd. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * 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. + * + */ + +#ifndef __EDP_CORE_H__ +#define __EDP_CORE_H__ + +// HDF common header files +#include "hdf_base.h" +#include "hdf_device_desc.h" +#include "osal_mutex.h" +#include "platform_core.h" +#include "osal_spinlock.h" + +#include "edp_if.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif /* __cplusplus */ + +#define EDP_ONE_BYTE_MARK 0xFF +#define EDP_ONE_BYTE_SHIFT 8 +#define EDP_TWO_BYTES_SHIFT 16 +#define EDP_SERVICE_NAME_LEN 32 +#define EDP_NAME_BUF_LEN 32 + +struct EdpPhyCfg { + uint32_t pixelClk; + uint32_t tmdsClk; /* TMDS clock, KHz */ + enum EdpColorDepth deepColor; /* deep color(color depth) */ + enum EdpColorSpace colorSpace; +}; + +struct EdpCntlr; + +union EdpCap { + uint32_t data; +}; + +enum EdpAudioFormat { + EDP_AFMT_I2S = 0, + EDP_AFMT_SPDIF = 1, + EDP_AFMT_UNUSED, +}; + +struct EdpAudioInfo { + enum EdpAudioFormat format; + int32_t sampleRate; + int32_t channels; + int32_t sampleWidth; +}; + +struct EdpCntlrCap { + union EdpCap baseCap; + uint32_t maxTmdsClock; + uint32_t defTmdsClock; /* unit: MHz */ + uint32_t maxFrlRate; + uint32_t videoTiming; + uint32_t quantization; + uint32_t colorSpace; + uint32_t colorimetry; + uint32_t audioIfType; + uint32_t audioBitDepth; + uint32_t audioSampleRate; + uint32_t audioChannels; + uint32_t hdrColorimetry; + uint32_t hdrUserMode; +}; + +struct EdpAudioConfigInfo { + bool enable; + bool downSample; + uint32_t tmdsClock; + uint32_t pixelRepeat; + enum EdpSampleRate sampleRate; +}; + +struct EdpCntlrOps { + int32_t (*open)(struct EdpCntlr *cntlr); + int32_t (*close)(struct EdpCntlr *cntlr); + int32_t (*enable)(struct EdpCntlr *cntlr); + int32_t (*disable)(struct EdpCntlr *cntlr); + int32_t (*avmuteSet)(struct EdpCntlr *cntlr, bool enable); + int32_t (*deepColorSet)(struct EdpCntlr *cntlr, enum EdpColorDepth color); + int32_t (*deepColorGet)(struct EdpCntlr *cntlr, enum EdpColorDepth *color); + int32_t (*setVideoAttribute)(struct EdpCntlr *cntlr, const struct EdpVideoAttr *attr); + int32_t (*getVideoAttribute)(struct EdpCntlr *cntlr, struct EdpVideoAttr *attr); + int32_t (*setAudioAttribute)(struct EdpCntlr *cntlr, const struct EdpAudioAttr *attr); + int32_t (*getAudioAttribute)(struct EdpCntlr *cntlr, struct EdpAudioAttr *attr); + int32_t (*registerHpdCallbackFunc)(struct EdpCntlr *cntlr, struct EdpHpdCallbackInfo *callback); + int32_t (*unregisterHpdCallbackFunc)(struct EdpCntlr *cntlr); + int32_t (*getConnector)(struct EdpCntlr *cntlr, DevHandle *connector); +}; + +enum EdpCntlrState { + EDP_CNTLR_STATE_NONE = 0, + EDP_CNTLR_STATE_OPEN = (1 << 0), + EDP_CNTLR_STATE_START = (1 << 1), + EDP_CNTLR_STATE_STOP = (1 << 2), + EDP_CNTLR_STATE_CLOSE = (1 << 3), +}; + +enum EdpEventType { + EDP_EVENT_TYPE_NONE, +}; + +struct EdpDevice { + struct EdpCntlr *cntlr; + void *priv; +}; + +struct EdpAttr { + struct EdpAudioInfo audioAttr; + struct EdpVideoAttr videoAttr; +}; + +struct EdpCntlr { + struct IDeviceIoService service; + struct HdfDeviceObject *hdfDevObj; + struct PlatformDevice device; + struct OsalMutex mutex; + struct EdpCntlrCap cap; + struct EdpAttr attr; + struct EdpCntlrOps *ops; + struct PlatformQueue *msgQueue; + struct EdpHpdCallbackInfo *hpdCbInfo; + uint32_t num; + uint32_t deviceIndex; + enum EdpCntlrState state; /* cntlr state. */ + OsalSpinlock lock; + void *priv; +}; + +static inline void EdpCntlrLock(struct EdpCntlr *cntlr) +{ + if (cntlr != NULL) { + (void)OsalMutexLock(&cntlr->mutex); + } +} + +static inline void EdpCntlrUnlock(struct EdpCntlr *cntlr) +{ + if (cntlr != NULL) { + (void)OsalMutexUnlock(&cntlr->mutex); + } +} + +static inline struct EdpCntlr *EdpCntlrGetByBusNum(uint16_t num) +{ + struct PlatformDevice *device = PlatformManagerGetDeviceByNumber(PlatformManagerGet(PLATFORM_MODULE_EDP), num); + + if (device == NULL) { + return NULL; + } + return CONTAINER_OF(device, struct EdpCntlr, device); +} + +DevHandle EdpCntlrOpen(uint16_t busNum); +void EdpCntlrClose(struct EdpCntlr *cntlr); +int32_t EdpCntlrDeepColorGet(struct EdpCntlr *cntlr, enum EdpColorDepth *color); +int32_t EdpCntlrDeepColorSet(struct EdpCntlr *cntlr, enum EdpColorDepth color); +int32_t EdpCntlrSetVideoAttribute(struct EdpCntlr *cntlr, const struct EdpVideoAttr *attr); +int32_t EdpCntlrGetVideoAttribute(struct EdpCntlr *cntlr, struct EdpVideoAttr *attr); +int32_t EdpCntlrSetAudioAttribute(struct EdpCntlr *cntlr, const struct EdpAudioAttr *attr); +int32_t EdpCntlrAvmuteSet(struct EdpCntlr *cntlr, bool enable); +int32_t EdpEventHandle(struct EdpCntlr *cntlr, enum EdpEventType event, void *data); +int32_t EdpCntlrDeviceAdd(struct HdfDeviceObject *obj, struct EdpCntlr *cntlr); +int32_t EdpCntlrRegisterHpdCallbackFunc(struct EdpCntlr *cntlr, struct EdpHpdCallbackInfo *callback); +int32_t EdpCntlrUnregisterHpdCallbackFunc(struct EdpCntlr *cntlr); +int32_t EdpCntlrGetConnector(struct EdpCntlr *cntlr, DevHandle *connector); +int32_t EdpCntlrAdd(struct HdfDeviceObject *obj, struct EdpCntlr *cntlr); +int32_t EdpCntlrDisable(struct EdpCntlr *cntlr); +int32_t EdpCntlrEnable(struct EdpCntlr *cntlr); + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif /* __cplusplus */ + +#endif //__EDP_CORE_H__ \ No newline at end of file diff --git a/framework/support/platform/include/edp/edp_dispatch.h b/framework/support/platform/include/edp/edp_dispatch.h new file mode 100644 index 0000000000000000000000000000000000000000..30588eeb6e60ed3fab88a71e3ff06bac44eb7b4a --- /dev/null +++ b/framework/support/platform/include/edp/edp_dispatch.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2023-2024 Huawei Device Co., Ltd. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * 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. + * + */ + +#ifndef EDP_DISPATCH_H +#define EDP_DISPATCH_H + +#include "hdf_base.h" +#include "devsvc_manager_clnt.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif /* __cplusplus */ + +enum EdpIoCmd { + EDP_CMD_OPEN, + EDP_CMD_CLOSE, + EDP_CMD_START, + EDP_CMD_STOP, + EDP_CMD_AVMUTE_SET, + EDP_CMD_DEEP_COLOR_SET, + EDP_CMD_DEEP_COLOR_GET, + EDP_CMD_VIDEO_ATTR_SET, + EDP_CMD_AUDIO_ATTR_SET, + EDP_CMD_HDR_ATTR_SET, + EDP_CMD_READ_SINK_EDID, + EDP_CMD_INFOFRAME_SET, + EDP_CMD_INFOFRAME_GET, + EDP_CMD_REGISTER_HPD_CALLBACK_FUNC, + EDP_CMD_UNREGISTER_HPD_CALLBACK_FUNC, + EDP_CMD_BUTT, +}; + +int32_t EdpIoDispatch(struct HdfDeviceIoClient *client, int cmdId, struct HdfSBuf *data, struct HdfSBuf *reply); +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif /* __cplusplus */ + +#endif //EDP_DISPATCH_H \ No newline at end of file diff --git a/framework/support/platform/include/fwk/platform_core.h b/framework/support/platform/include/fwk/platform_core.h index 7b78ef2c317ff36f7e8855d0361eb49f1e8c42eb..0d60f68bcec04c578391d84c5cda97de37b15e3a 100644 --- a/framework/support/platform/include/fwk/platform_core.h +++ b/framework/support/platform/include/fwk/platform_core.h @@ -50,6 +50,7 @@ enum PlatformModuleType { PLATFORM_MODULE_I3C, PLATFORM_MODULE_CAN, PLATFORM_MODULE_HDMI, + PLATFORM_MODULE_EDP, PLATFORM_MODULE_MMC, PLATFORM_MODULE_MTD, PLATFORM_MODULE_TIMER, diff --git a/framework/support/platform/src/edp/edp_core.c b/framework/support/platform/src/edp/edp_core.c new file mode 100644 index 0000000000000000000000000000000000000000..ca770b1cc6c0fe1022d71c3b5437653115797b82 --- /dev/null +++ b/framework/support/platform/src/edp/edp_core.c @@ -0,0 +1,351 @@ +/* + * Copyright (c) 2023-2024 Huawei Device Co., Ltd. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * 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. + * + */ + +#include "device_resource_if.h" +#include "hdf_log.h" +#include "osal_mem.h" +#include "osal_time.h" +#include "securec.h" + +#include "edp_if.h" +#include "edp_core.h" + +#define HDF_LOG_TAG edp_core + +static void *EdpCntlrObjGet(uint16_t busNum) +{ + char *serviceName = NULL; + void *obj = NULL; + + serviceName = (char *)OsalMemCalloc(EDP_SERVICE_NAME_LEN + 1); + if (serviceName == NULL) { + HDF_LOGE("EDP service name malloc fail."); + return NULL; + } + if (snprintf_s(serviceName, (EDP_SERVICE_NAME_LEN + 1), + EDP_SERVICE_NAME_LEN, "HDF_EDP") < 0) { + HDF_LOGE("get EDP service name fail."); + OsalMemFree(serviceName); + return obj; + } + obj = (void *)EdpCntlrGetByBusNum(busNum); + OsalMemFree(serviceName); + return obj; +} + +static int32_t EdpCntlrParseVideoCaps( + struct EdpCntlr *cntlr, struct DeviceResourceIface *drsOps, const struct DeviceResourceNode *node) +{ + int32_t ret; + + ret = drsOps->GetUint32(node, "maxTmdsClock", &(cntlr->cap.maxTmdsClock), 0); + if (ret != HDF_SUCCESS) { + HDF_LOGE("EdpCntlrParseVideoCaps: read maxTmdsClock fail!"); + return ret; + } + + ret = drsOps->GetUint32(node, "defTmdsClock", &(cntlr->cap.defTmdsClock), 0); + if (ret != HDF_SUCCESS) { + HDF_LOGE("EdpCntlrParseVideoCaps: read defTmdsClock fail!"); + return ret; + } + + ret = drsOps->GetUint32(node, "maxFrlRate", &(cntlr->cap.maxFrlRate), 0); + if (ret != HDF_SUCCESS) { + HDF_LOGE("EdpCntlrParseVideoCaps: read maxFrlRate fail!"); + return ret; + } + + ret = drsOps->GetUint32(node, "videoTiming", &(cntlr->cap.videoTiming), 0); + if (ret != HDF_SUCCESS) { + HDF_LOGE("EdpCntlrParseVideoCaps: read videoTiming fail!"); + return ret; + } + + ret = drsOps->GetUint32(node, "quantization", &(cntlr->cap.quantization), 0); + if (ret != HDF_SUCCESS) { + HDF_LOGE("EdpCntlrParseVideoCaps: read quantization fail!"); + return ret; + } + + ret = drsOps->GetUint32(node, "colorSpace", &(cntlr->cap.colorSpace), 0); + if (ret != HDF_SUCCESS) { + HDF_LOGE("EdpCntlrParseVideoCaps: read colorSpace fail!"); + return ret; + } + + ret = drsOps->GetUint32(node, "colorimetry", &(cntlr->cap.colorimetry), 0); + if (ret != HDF_SUCCESS) { + HDF_LOGE("EdpCntlrParseVideoCaps: read colorimetry fail!"); + return ret; + } + return HDF_SUCCESS; +} + +static int32_t EdpCntlrParseAudioCaps( + struct EdpCntlr *cntlr, struct DeviceResourceIface *drsOps, const struct DeviceResourceNode *node) +{ + int32_t ret; + + ret = drsOps->GetUint32(node, "audioIfType", &(cntlr->cap.audioIfType), 0); + if (ret != HDF_SUCCESS) { + HDF_LOGE("EdpCntlrParseAudioCaps: read audioIfType fail!"); + return ret; + } + HDF_LOGD("EdpCntlrParseAudioCaps: audioIfType = %d", cntlr->cap.audioIfType); + + ret = drsOps->GetUint32(node, "audioBitDepth", &(cntlr->cap.audioBitDepth), 0); + if (ret != HDF_SUCCESS) { + HDF_LOGE("EdpCntlrParseAudioCaps: read audioBitDepth fail!"); + return ret; + } + HDF_LOGD("EdpCntlrParseAudioCaps: audioBitDepth = %d", cntlr->cap.audioBitDepth); + + ret = drsOps->GetUint32(node, "audioSampleRate", &(cntlr->cap.audioSampleRate), 0); + if (ret != HDF_SUCCESS) { + HDF_LOGE("EdpCntlrParseAudioCaps: read audioSampleRate fail!"); + return ret; + } + HDF_LOGD("EdpCntlrParseAudioCaps: audioSampleRate = %d", cntlr->cap.audioSampleRate); + + ret = drsOps->GetUint32(node, "audioChannels", &(cntlr->cap.audioChannels), 0); + if (ret != HDF_SUCCESS) { + HDF_LOGE("EdpCntlrParseAudioCaps: read audioChannels fail!"); + return ret; + } + HDF_LOGD("EdpCntlrParseAudioCaps: audioChannels = %d", cntlr->cap.audioChannels); + return HDF_SUCCESS; +} + +int32_t EdpCntlrParse(struct EdpCntlr *cntlr, struct HdfDeviceObject *obj) +{ + const struct DeviceResourceNode *node = NULL; + struct DeviceResourceIface *drsOps = NULL; + int32_t ret = -1; + + if (obj == NULL || cntlr == NULL) { + HDF_LOGE("EdpCntlrParse: input param is NULL."); + return HDF_FAILURE; + } + + node = obj->property; + if (node == NULL) { + HDF_LOGE("EdpCntlrParse: drs node is NULL."); + return HDF_FAILURE; + } + drsOps = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE); + if (drsOps == NULL || drsOps->GetUint32 == NULL) { + HDF_LOGE("EdpCntlrParse: invalid drs ops fail!"); + return HDF_FAILURE; + } + + ret = drsOps->GetUint32(node, "index", &(cntlr->deviceIndex), 0); + if (ret != HDF_SUCCESS) { + HDF_LOGE("EdpCntlrParse: read hostId fail!"); + return ret; + } + + ret = drsOps->GetUint32(node, "cap", &(cntlr->cap.baseCap.data), 0); + if (ret != HDF_SUCCESS) { + HDF_LOGE("EdpCntlrParse: read baseCap fail!"); + return ret; + } + + ret = EdpCntlrParseVideoCaps(cntlr, drsOps, node); + if (ret != HDF_SUCCESS) { + HDF_LOGE("EdpCntlrParse: read video caps fail!"); + return ret; + } + + ret = EdpCntlrParseAudioCaps(cntlr, drsOps, node); + if (ret != HDF_SUCCESS) { + HDF_LOGE("EdpCntlrParse: read audio caps fail!"); + return ret; + } + return HDF_SUCCESS; +} + +int32_t EdpCntlrAdd(struct HdfDeviceObject *obj, struct EdpCntlr *cntlr) +{ + int32_t ret = -1; + if (obj == NULL || cntlr == NULL) { + HDF_LOGE("%s: invalid parameter", __func__); + return HDF_ERR_INVALID_PARAM; + } + if (cntlr->ops == NULL) { + HDF_LOGE("%s: edp ops is null", __func__); + return HDF_ERR_INVALID_PARAM; + } + if (OsalSpinInit(&(cntlr->lock)) != HDF_SUCCESS) { + HDF_LOGE("%s: init spinlock fail", __func__); + return HDF_FAILURE; + } + cntlr->device.manager = PlatformManagerGet(PLATFORM_MODULE_EDP); + ret = PlatformDeviceAdd(&cntlr->device); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: device add fail!", __func__); + return ret; + } + cntlr->hdfDevObj = obj; + cntlr->hdfDevObj->service = &(cntlr->service); + cntlr->device.hdfDev = obj; + cntlr->device.service = &cntlr->service; + return HDF_SUCCESS; +} + +DevHandle EdpCntlrOpen(uint16_t busNum) +{ + DevHandle hdl = EdpCntlrObjGet(busNum); + return hdl; +} + +int32_t EdpCntlrDeepColorSet(struct EdpCntlr *cntlr, enum EdpColorDepth color) +{ + int32_t ret = -1; + if (cntlr == NULL || cntlr->ops == NULL || cntlr->ops->deepColorSet == NULL) { + return HDF_ERR_INVALID_OBJECT; + } + + ret = cntlr->ops->deepColorSet(cntlr, color); + return ret; +} + +int32_t EdpCntlrDeepColorGet(struct EdpCntlr *cntlr, enum EdpColorDepth *color) +{ + int32_t ret = -1; + if (cntlr == NULL || cntlr->ops == NULL || cntlr->ops->deepColorGet == NULL) { + return HDF_ERR_INVALID_OBJECT; + } + + ret = cntlr->ops->deepColorGet(cntlr, color); + return ret; +} + +int32_t EdpCntlrSetVideoAttribute(struct EdpCntlr *cntlr, const struct EdpVideoAttr *attr) +{ + int32_t ret = HDF_FAILURE; + if (cntlr == NULL || cntlr->ops == NULL || cntlr->ops->setVideoAttribute == NULL) { + return HDF_ERR_INVALID_OBJECT; + } + ret = cntlr->ops->setVideoAttribute(cntlr, attr); + + return ret; +} + +int32_t EdpCntlrGetVideoAttribute(struct EdpCntlr *cntlr, struct EdpVideoAttr *attr) +{ + int32_t ret = HDF_FAILURE; + if (cntlr == NULL || cntlr->ops == NULL || cntlr->ops->getVideoAttribute == NULL) { + return HDF_ERR_INVALID_OBJECT; + } + ret = cntlr->ops->getVideoAttribute(cntlr, attr); + + return ret; +} + +int32_t EdpCntlrSetAudioAttribute(struct EdpCntlr *cntlr, const struct EdpAudioAttr *attr) +{ + int32_t ret = -1; + if (cntlr == NULL || cntlr->ops == NULL || cntlr->ops->setAudioAttribute == NULL) { + return HDF_ERR_INVALID_OBJECT; + } + ret = cntlr->ops->setAudioAttribute(cntlr, attr); + + return ret; +} + +void EdpCntlrClose(struct EdpCntlr *cntlr) +{ + if (cntlr == NULL || cntlr->ops == NULL || cntlr->ops->close == NULL) { + HDF_LOGE("%s: invalid parameter", __func__); + return; + } + cntlr->ops->close(cntlr); +} + +int32_t EdpCntlrRegisterHpdCallbackFunc(struct EdpCntlr *cntlr, struct EdpHpdCallbackInfo *callback) +{ + int32_t ret = -1; + if (cntlr == NULL || callback == NULL || cntlr->ops == NULL || cntlr->ops->registerHpdCallbackFunc == NULL) { + HDF_LOGE("%s: invalid parameter", __func__); + return ret; + } + return cntlr->ops->registerHpdCallbackFunc(cntlr, callback); +} + +int32_t EdpCntlrUnregisterHpdCallbackFunc(struct EdpCntlr *cntlr) +{ + int32_t ret = -1; + if (cntlr == NULL || cntlr->ops == NULL || cntlr->ops->unregisterHpdCallbackFunc == NULL) { + HDF_LOGE("%s: invalid parameter", __func__); + return ret; + } + return cntlr->ops->unregisterHpdCallbackFunc(cntlr); +} + +int32_t EdpCntlrAvmuteSet(struct EdpCntlr *cntlr, bool enable) +{ + int32_t ret = -1; + if (cntlr == NULL || cntlr->ops == NULL || cntlr->ops->avmuteSet == NULL) { + HDF_LOGE("%s: invalid parameter", __func__); + return ret; + } + + EdpCntlrLock(cntlr); + ret = cntlr->ops->avmuteSet(cntlr, enable); + EdpCntlrUnlock(cntlr); + return ret; +} + +int32_t EdpCntlrGetConnector(struct EdpCntlr *cntlr, DevHandle *connector) +{ + int32_t ret = HDF_FAILURE; + if (cntlr == NULL || cntlr->ops == NULL || cntlr->ops->getConnector == NULL) { + HDF_LOGE("%s: invalid parameter", __func__); + return ret; + } + + EdpCntlrLock(cntlr); + ret = cntlr->ops->getConnector(cntlr, connector); + EdpCntlrUnlock(cntlr); + return ret; +} + +int32_t EdpCntlrDisable(struct EdpCntlr *cntlr) +{ + int32_t ret = HDF_FAILURE; + if (cntlr == NULL || cntlr->ops == NULL || cntlr->ops->disable == NULL) { + HDF_LOGE("%s: invalid parameter", __func__); + return ret; + } + + EdpCntlrLock(cntlr); + ret = cntlr->ops->disable(cntlr); + EdpCntlrUnlock(cntlr); + return ret; +} + +int32_t EdpCntlrEnable(struct EdpCntlr *cntlr) +{ + int32_t ret = HDF_FAILURE; + if (cntlr == NULL || cntlr->ops == NULL || cntlr->ops->enable == NULL) { + HDF_LOGE("%s: invalid parameter", __func__); + return ret; + } + + EdpCntlrLock(cntlr); + ret = cntlr->ops->enable(cntlr); + EdpCntlrUnlock(cntlr); + return ret; +} \ No newline at end of file diff --git a/framework/support/platform/src/edp/edp_dispatch.c b/framework/support/platform/src/edp/edp_dispatch.c new file mode 100644 index 0000000000000000000000000000000000000000..9916f5498d91e178d8c3809ca0ccdead53712523 --- /dev/null +++ b/framework/support/platform/src/edp/edp_dispatch.c @@ -0,0 +1,153 @@ +/* + * Copyright (c) 2023-2024 Huawei Device Co., Ltd. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * 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. + * + */ + +#include "edp_dispatch.h" +#include "hdf_log.h" +#include "edp_core.h" +#include "edp_if.h" + +#define HDF_LOG_TAG edp_dispatch + +struct EdpDispatchFunc { + uint32_t cmd; + int32_t (*func)(struct EdpCntlr *cntlr, struct HdfSBuf *data, struct HdfSBuf *reply); +}; + +static int32_t EdpCmdOpen(struct EdpCntlr *cntlr, struct HdfSBuf *data, struct HdfSBuf *reply) +{ + (void)data; + (void)reply; + return EdpCntlrOpen(cntlr); +} + +static int32_t EdpCmdClose(struct EdpCntlr *cntlr, struct HdfSBuf *data, struct HdfSBuf *reply) +{ + (void)data; + (void)reply; + + EdpCntlrClose(cntlr); + return HDF_SUCCESS; +} + +static int32_t EdpCmdAvmuteSet(struct EdpCntlr *cntlr, struct HdfSBuf *data, struct HdfSBuf *reply) +{ + bool *enable = NULL; + uint32_t size; + (void)reply; + + if (!HdfSbufReadBuffer(data, (const void **)&enable, &size)) { + HDF_LOGE("EdpCmdAvmuteSet: sbuf read buffer failed"); + return HDF_ERR_IO; + } + EdpCntlrAvmuteSet(cntlr, *enable); + return HDF_SUCCESS; +} + +static int32_t EdpCmdDeepColorSet(struct EdpCntlr *cntlr, struct HdfSBuf *data, struct HdfSBuf *reply) +{ + enum EdpColorDepth *color = NULL; + uint32_t size; + (void)reply; + + if (!HdfSbufReadBuffer(data, (const void **)&color, &size)) { + HDF_LOGE("EdpCmdDeepColorSet: sbuf read buffer failed"); + return HDF_ERR_IO; + } + return EdpCntlrDeepColorSet(cntlr, *color); +} + +static int32_t EdpCmdDeepColorGet(struct EdpCntlr *cntlr, struct HdfSBuf *data, struct HdfSBuf *reply) +{ + int32_t ret; + enum EdpColorDepth color; + (void)data; + + if (reply == NULL) { + return HDF_ERR_INVALID_PARAM; + } + + ret = EdpCntlrDeepColorGet(cntlr, &color); + if (ret != HDF_SUCCESS) { + return ret; + } + + if (HdfSbufWriteBuffer(reply, &color, sizeof(color)) == false) { + HDF_LOGE("EdpCmdDeepColorGet: write back color fail!"); + return HDF_ERR_IO; + } + return HDF_SUCCESS; +} + +static int32_t EdpCmdVideoInfoSet(struct EdpCntlr *cntlr, struct HdfSBuf *data, struct HdfSBuf *reply) +{ + struct EdpVideoAttr *attr = NULL; + uint32_t size; + (void)reply; + + if (!HdfSbufReadBuffer(data, (const void **)&attr, &size)) { + HDF_LOGE("EdpCmdVideoInfoSet: sbuf read buffer failed"); + return HDF_ERR_IO; + } + return EdpCntlrSetVideoAttribute(cntlr, attr); +} + +static int32_t EdpCmdAudioInfoSet(struct EdpCntlr *cntlr, struct HdfSBuf *data, struct HdfSBuf *reply) +{ + struct EdpAudioAttr *attr = NULL; + uint32_t size; + (void)reply; + + if (!HdfSbufReadBuffer(data, (const void **)&attr, &size)) { + HDF_LOGE("EdpCmdAudioInfoSet: sbuf read buffer failed"); + return HDF_ERR_IO; + } + return EdpCntlrSetAudioAttribute(cntlr, attr); +} + +int32_t EdpIoDispatch(struct HdfDeviceIoClient *client, int cmd, struct HdfSBuf *data, struct HdfSBuf *reply) +{ + struct EdpCntlr *cntlr = NULL; + uint32_t i; + uint32_t len; + struct EdpDispatchFunc dispatchFunc[] = { + { EDP_CMD_OPEN, EdpCmdOpen }, + { EDP_CMD_CLOSE, EdpCmdClose }, + { EDP_CMD_AVMUTE_SET, EdpCmdAvmuteSet }, + { EDP_CMD_DEEP_COLOR_SET, EdpCmdDeepColorSet }, + { EDP_CMD_DEEP_COLOR_GET, EdpCmdDeepColorGet }, + { EDP_CMD_VIDEO_ATTR_SET, EdpCmdVideoInfoSet }, + { EDP_CMD_AUDIO_ATTR_SET, EdpCmdAudioInfoSet }, + }; + + if (client == NULL || client->device == NULL) { + HDF_LOGE("EdpIoDispatch: client or hdf dev obj is NULL"); + return HDF_ERR_INVALID_OBJECT; + } + + cntlr = (struct EdpCntlr *)client->device->service; + if (cntlr == NULL) { + HDF_LOGE("EdpIoDispatch: service is NULL"); + return HDF_ERR_INVALID_OBJECT; + } + + len = sizeof(dispatchFunc) / sizeof(dispatchFunc[0]); + for (i = 0; i < len; i++) { + if (dispatchFunc[i].cmd == cmd) { + return dispatchFunc[i].func(cntlr, data, reply); + } + } + + HDF_LOGE("EdpIoDispatch: cmd %d is not support", cmd); + return HDF_ERR_NOT_SUPPORT; +} diff --git a/framework/support/platform/src/edp/edp_if.c b/framework/support/platform/src/edp/edp_if.c new file mode 100644 index 0000000000000000000000000000000000000000..b402394d2899bc6159e496f43249240949087438 --- /dev/null +++ b/framework/support/platform/src/edp/edp_if.c @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2023-2024 Huawei Device Co., Ltd. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * 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. + * + */ + +#include "edp_if.h" +#include "hdf_base.h" +#include "hdf_log.h" +#include "osal_mem.h" +#include "edp_core.h" +#include "securec.h" + +#define HDF_LOG_TAG "edp_if" + +static void *EdpGetDevByNum(uint16_t busNum) +{ + char *pSrvcName = NULL; + void *pHdl = NULL; + + pSrvcName = (char *)OsalMemCalloc(EDP_NAME_BUF_LEN); + if (pSrvcName == NULL) { + HDF_LOGE("Edp service name malloc fail."); + return NULL; + } + if (snprintf_s(pSrvcName, (EDP_NAME_BUF_LEN), + EDP_NAME_BUF_LEN -1, "HDF_PLATFORM_EDP_%u", busNum) < 0) { + HDF_LOGE("Generate Edp service name fail."); + OsalMemFree(pSrvcName); + return NULL; + } + +#ifdef __USER__ + pHdl = (void *)HdfIoServiceBind(serviceName); +#else + pHdl = EdpCntlrGetByBusNum(busNum); +#endif + OsalMemFree(pSrvcName); + + return pHdl; +} + +DevHandle EdpOpen(uint16_t busNum) +{ + return EdpCntlrOpen(busNum); +} + +int32_t EdpStart(DevHandle handle) +{ + return HDF_SUCCESS; +} + +int32_t EdpStop(DevHandle handle) +{ + return HDF_SUCCESS; +} + +int32_t EdpAvmuteSet(DevHandle handle, bool enable) +{ + return EdpCntlrAvmuteSet((struct EdpCntlr *)handle, enable); +} + +int32_t EdpDeepColorSet(DevHandle handle, enum EdpColorDepth color) +{ + return EdpCntlrDeepColorSet((struct EdpCntlr *)handle, color); +} + +int32_t EdpDeepColorGet(DevHandle handle, enum EdpColorDepth *color) +{ + return EdpCntlrDeepColorGet((struct EdpCntlr *)handle, color); +} + +int32_t EdpSetVideoAttribute(DevHandle handle, struct EdpVideoAttr *attr) +{ + return EdpCntlrSetVideoAttribute((struct EdpCntlr *)handle, attr); +} + +int32_t EdpSetAudioAttribute(DevHandle handle, struct EdpAudioAttr *attr) +{ + return EdpCntlrSetAudioAttribute((struct EdpCntlr *)handle, attr); +} + +int32_t EdpRegisterHpdCallbackFunc( + DevHandle handle, + struct EdpHpdCallbackInfo *callback) +{ + return EdpCntlrRegisterHpdCallbackFunc((struct EdpCntlr *)handle, callback); +} + +int32_t EdpUnregisterHpdCallbackFunc(DevHandle handle) +{ + return EdpCntlrUnregisterHpdCallbackFunc((struct EdpCntlr *)handle); +} + +void EdpClose(DevHandle handle) +{ + EdpCntlrClose((struct EdpCntlr *)handle); +} + +int32_t EdpGetConnector(DevHandle handle, DevHandle *connector) +{ + return EdpCntlrGetConnector((struct EdpCntlr *)handle, connector); +} + +int32_t EdpDisable(DevHandle handle) +{ + return EdpCntlrDisable((struct EdpCntlr *)handle); +} + +int32_t EdpEnable(DevHandle handle) +{ + return EdpCntlrEnable((struct EdpCntlr *)handle); +} \ No newline at end of file diff --git a/framework/test/unittest/common/hdf_main_test.c b/framework/test/unittest/common/hdf_main_test.c index b00936ab365aa7528ffcd06ae40a0a4a31914a2a..f19781d194c0d15260d5992a00a73acdf41bd267 100644 --- a/framework/test/unittest/common/hdf_main_test.c +++ b/framework/test/unittest/common/hdf_main_test.c @@ -67,6 +67,9 @@ #if defined(LOSCFG_DRIVERS_HDF_PLATFORM_MIPI_CSI) || defined(CONFIG_DRIVERS_HDF_PLATFORM_MIPI_CSI) #include "hdf_mipi_csi_entry_test.h" #endif +#if defined(LOSCFG_DRIVERS_HDF_PLATFORM_EDP) || defined(CONFIG_DRIVERS_HDF_PLATFORM_EDP) +#include "hdf_edp_entry_test.h" +#endif #if (defined(LOSCFG_STORAGE_EMMC) && defined(LOSCFG_DRIVERS_HDF_PLATFORM_EMMC)) || \ defined(CONFIG_DRIVERS_HDF_PLATFORM_EMMC) #include "hdf_emmc_entry_test.h" @@ -152,6 +155,9 @@ HdfTestFuncList g_hdfTestFuncList[] = { #if defined(LOSCFG_DRIVERS_HDF_PLATFORM_MIPI_CSI) || defined(CONFIG_DRIVERS_HDF_PLATFORM_MIPI_CSI) { TEST_PAL_MIPI_CSI_TYPE, HdfMipiCsiEntry }, #endif +#if defined(LOSCFG_DRIVERS_HDF_PLATFORM_EDP) || defined(CONFIG_DRIVERS_HDF_PLATFORM_EDP) + { TEST_PAL_EDP_TYPE, HdfEdpTestEntry }, +#endif #if defined(LOSCFG_DRIVERS_HDF_PLATFORM_SDIO) || defined(CONFIG_DRIVERS_HDF_PLATFORM_SDIO) { TEST_PAL_SDIO_TYPE, HdfSdioUnitTestEntry }, #endif diff --git a/framework/test/unittest/common/hdf_main_test.h b/framework/test/unittest/common/hdf_main_test.h index 74630a5fd0d515ebfdaea5f62f902d651cd60c8d..55338773b960ac2202e220d3a095a776dcb9deb9 100644 --- a/framework/test/unittest/common/hdf_main_test.h +++ b/framework/test/unittest/common/hdf_main_test.h @@ -68,7 +68,8 @@ typedef enum { TEST_PAL_EVENT_TYPE = 197, TEST_PAL_DUMPER_TYPE = 198, TEST_PAL_TRACE_TYPE = 199, - TEST_PAL_END = 200, + TEST_PAL_EDP_TYPE = 200, + TEST_PAL_END = 201, TEST_OSAL_BEGIN = TEST_PAL_END, #define HDF_OSAL_TEST_ITEM(v) (TEST_OSAL_BEGIN + (v)) TEST_OSAL_ITEM = HDF_OSAL_TEST_ITEM(1), diff --git a/framework/test/unittest/platform/common/edp_test.c b/framework/test/unittest/platform/common/edp_test.c new file mode 100644 index 0000000000000000000000000000000000000000..7d1be37e73e2aa2dd4ed1d71d7d64c7e89cbff55 --- /dev/null +++ b/framework/test/unittest/platform/common/edp_test.c @@ -0,0 +1,319 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#include "edp_test.h" +#include "edp_if.h" +#include "hdf_base.h" +#include "hdf_io_service_if.h" +#include "hdf_log.h" +#include "osal_mem.h" +#include "securec.h" +#include "osal_thread.h" +#include "osal_time.h" + +#define DEFAULT_RATE 10000 +#define EDP_TEST_STACK_SIZE (1024 * 64) +#define EDP_TEST_SLEEP_TIME 2000 +#define EDP_TEST_WAIT_TIMEOUT 20 +#define HDF_LOG_TAG edp_test_c + +static DevHandle g_edpTesthdl = NULL; + +static DevHandle EdpTesterGet(void) +{ + HDF_LOGI("EdpTesterGet: enter!"); + if (g_edpTesthdl) { + return g_edpTesthdl; + } + g_edpTesthdl = EdpOpen(0); + if (g_edpTesthdl == NULL) { + HDF_LOGE("EdpTesterGet: open edp device:%u fail!", 0); + return NULL; + } + HDF_LOGI("EdpTesterGet: done!"); + return g_edpTesthdl; +} + +static int32_t EdpTestDeepColorSet(void) +{ + DevHandle edpHdl = NULL; + int32_t ret; + + HDF_LOGI("EdpTestEnable: enter!"); + edpHdl = EdpTesterGet(); + if (edpHdl == NULL) { + HDF_LOGE("EdpTestEnable: get edpHdl fail!"); + return HDF_ERR_INVALID_OBJECT; + } + + ret = EdpDeepColorSet(edpHdl, EDP_COLOR_DEPTH_10BIT); + + HDF_LOGI("EdpTestEnable: edp device num is %u!", edpHdl); + HDF_LOGI("EdpTestEnable: done!"); + return ret; +} + +static int32_t EdpTestDeepColorGet(void) +{ + DevHandle edpHdl = NULL; + int32_t ret; + enum EdpColorDepth color; + + HDF_LOGI("EdpTestDeepColorGet: enter!"); + edpHdl = EdpTesterGet(); + if (edpHdl == NULL) { + HDF_LOGE("EdpTestDeepColorGet: get edpHdl fail!"); + return HDF_ERR_INVALID_OBJECT; + } + + ret = EdpDeepColorGet(edpHdl, &color); + + HDF_LOGI("EdpTestDeepColorGet: done: %d!", color); + return ret; +} + +static int32_t EdpTestSetVideoAttribute(void) +{ + int32_t ret = HDF_SUCCESS; + DevHandle edpHdl = NULL; + struct EdpVideoAttr attr = { + .tmdsClock = 0, + .pixelClock = 0, + .pixelRepeat = 0, + .colorSpace = EDP_COLOR_SPACE_YCBCR422, + .colorDepth = EDP_COLOR_DEPTH_10BIT, + .colorCoeff = EDP_COLOR_COEFF_YCBCR709, + .colorimetry = EDP_COLORIMETRY_DEFAULT, + .timing = EDP_VIDEO_TIMING_NONE, + }; + + HDF_LOGI("%s: enter!", __func__); + edpHdl = EdpTesterGet(); + if (edpHdl == NULL) { + HDF_LOGE("%s: get edpHdl fail!", __func__); + return HDF_ERR_INVALID_OBJECT; + } + + ret = EdpSetVideoAttribute(edpHdl, &attr); + + HDF_LOGI("%s: done!", __func__); + return HDF_SUCCESS; +} + +static int32_t EdpTestSetAudioAttribute(void) +{ + DevHandle edpHdl = NULL; + int32_t ret; + struct EdpAudioAttr attr = { + .codingType = EDP_AUDIO_CODING_TYPE_STREAM, + .ifType = EDP_AUDIO_IF_TYPE_SPDIF, + .bitDepth = EDP_AUDIO_BIT_DEPTH_16, + }; + + HDF_LOGI("%s: enter!", __func__); + edpHdl = EdpTesterGet(); + if (edpHdl == NULL) { + HDF_LOGE("%s: get edpHdl fail!", __func__); + return HDF_ERR_INVALID_OBJECT; + } + ret = EdpSetAudioAttribute(edpHdl, &attr); + + HDF_LOGI("%s: done!", __func__); + return ret; +} + +static int32_t EdpTestEnable(void) +{ + DevHandle edpHdl = NULL; + int32_t ret = HDF_FAILURE; + + HDF_LOGI("%s: enter!", __func__); + edpHdl = EdpTesterGet(); + if (edpHdl == NULL || edpHdl == NULL) { + HDF_LOGE("%s: get edpHdl fail!", __func__); + return HDF_ERR_INVALID_OBJECT; + } + + ret = EdpEnable(edpHdl); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s EdpEnable failed", __func__); + } + HDF_LOGI("%s: done!", __func__); + return HDF_SUCCESS; +} + +static int32_t EdpTestDisable(void) +{ + DevHandle edpHdl = NULL; + int32_t ret = HDF_FAILURE; + + HDF_LOGI("%s: enter!", __func__); + edpHdl = EdpTesterGet(); + if (edpHdl == NULL || edpHdl == NULL) { + HDF_LOGE("%s: get edpHdl fail!", __func__); + return HDF_ERR_INVALID_OBJECT; + } + + ret = EdpDisable(edpHdl); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s EdpEnable failed", __func__); + } + HDF_LOGI("%s: done!", __func__); + OsalMSleep(EDP_TEST_SLEEP_TIME); + return HDF_SUCCESS; +} + +static void EdpTestHpdCallback(void *data, bool hpd) +{ + if (!hpd) { + return; + } + + HDF_LOGI("%s: eDP device hot-pluged detected with handle %p", __func__, data); +} + +static int32_t EdpTestRegisterHpdCallbackFunc(void) +{ + uint32_t rate; + HDF_LOGI("%s: enter!", __func__); + DevHandle edpHdl = NULL; + int32_t ret; + + edpHdl = EdpTesterGet(); + if (edpHdl == NULL) { + HDF_LOGE("%s: get edpHdl fail!", __func__); + return HDF_ERR_INVALID_OBJECT; + } + struct EdpHpdCallbackInfo cbInfo = { + .data = edpHdl, + .callbackFunc = &EdpTestHpdCallback, + }; + ret = EdpRegisterHpdCallbackFunc(edpHdl, &cbInfo); + HDF_LOGI("%s: done!", __func__); + return HDF_SUCCESS; +} + +static int32_t EdpTestUnRegisterHpdCallbackFunc(void) +{ + DevHandle edpHdl = NULL; + int32_t ret = HDF_FAILURE; + + HDF_LOGI("%s: enter!", __func__); + edpHdl = EdpTesterGet(); + if (edpHdl == NULL || edpHdl == NULL) { + HDF_LOGE("%s: get edpHdl fail!", __func__); + return HDF_ERR_INVALID_OBJECT; + } + + ret = EdpUnregisterHpdCallbackFunc(edpHdl); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s get edp failed", __func__); + } + HDF_LOGI("%s: done!", __func__); + return HDF_SUCCESS; +} + +static int32_t EdpTestGetConnector(void) +{ + DevHandle edpHdl = NULL; + DevHandle connector = NULL; + int32_t ret = HDF_FAILURE; + + HDF_LOGI("%s: enter!", __func__); + edpHdl = EdpTesterGet(); + if (edpHdl == NULL || edpHdl == NULL) { + HDF_LOGE("%s: get edpHdl fail!", __func__); + return HDF_ERR_INVALID_OBJECT; + } + + ret = EdpGetConnector(edpHdl, &connector); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s get edp failed", __func__); + } + HDF_LOGI("%s: done!", __func__); + return HDF_SUCCESS; +} + +struct EdpTestEntry { + int cmd; + int32_t (*func)(void); + const char *name; +}; + +static struct EdpTestEntry g_entry[] = { + {EDP_TEST_CMD_DEEP_COLOR_SET, EdpTestDeepColorSet, "EdpTestDeepColorSet"}, + {EDP_TEST_CMD_DEEP_COLOR_GET, EdpTestDeepColorGet, "EdpTestDeepColorGet"}, + {EDP_TEST_CMD_SET_VIDEO_ATTR, EdpTestSetVideoAttribute, "EdpTestSetVideoAttribute"}, + {EDP_TEST_CMD_SET_AUDIO_ATTR, EdpTestSetAudioAttribute, "EdpTestSetAudioAttribute"}, + {EDP_TEST_CMD_DISABLE, EdpTestDisable, "EdpTestDisable"}, + {EDP_TEST_CMD_ENABLE, EdpTestEnable, "EdpTestEnable"}, + {EDP_TEST_CMD_REGISTER_HPD_CB, EdpTestRegisterHpdCallbackFunc, "EdpTestRegisterHpdCallbackFunc"}, + {EDP_TEST_CMD_UNREGISTER_HPD_CB, EdpTestUnRegisterHpdCallbackFunc, "EdpTestUnRegisterHpdCallbackFunc"}, + {EDP_TEST_CMD_GET_CONNECTER, EdpTestGetConnector, "EdpTestGetConnector"}, +}; + +int32_t EdpTestExecute(int cmd) +{ + uint32_t i; + int32_t ret = HDF_ERR_NOT_SUPPORT; + + if (cmd > EDP_TEST_CMD_MAX) { + HDF_LOGE("EdpTestExecute: invalid cmd:%d!", cmd); + ret = HDF_ERR_NOT_SUPPORT; + HDF_LOGE("[EdpTestExecute][======cmd:%d====ret:%d======]", cmd, ret); + return ret; + } + + for (i = 0; i < sizeof(g_entry) / sizeof(g_entry[0]); i++) { + if (g_entry[i].cmd != cmd || g_entry[i].func == NULL) { + continue; + } + ret = g_entry[i].func(); + break; + } + + HDF_LOGE("[EdpTestExecute][======cmd:%d====ret:%d======]", cmd, ret); + return ret; +} + +static int32_t EdpTestDoTest(struct EdpTest *test, int32_t cmd) +{ + (void)test; + int32_t ret = HDF_FAILURE; + + ret = EdpTestExecute(cmd); + return ret; +} + +static int32_t EdpTestBind(struct HdfDeviceObject *device) +{ + static struct EdpTest test; + + test.total = EDP_TEST_CMD_MAX; + test.doTest = &EdpTestDoTest; + test.fails = 0; + test.handle = EdpTesterGet(); + test.devNo = 0; + test.device = device; + device->service = &test.service; + return HDF_SUCCESS; +} + +static int32_t EdpTestInit(struct HdfDeviceObject *device) +{ + (void)device; + return HDF_SUCCESS; +} + +struct HdfDriverEntry g_edpTestEntry = { + .moduleVersion = 1, + .Bind = EdpTestBind, + .Init = EdpTestInit, + .moduleName = "PLATFORM_EDP_TEST", +}; +HDF_INIT(g_edpTestEntry); \ No newline at end of file diff --git a/framework/test/unittest/platform/common/edp_test.h b/framework/test/unittest/platform/common/edp_test.h new file mode 100644 index 0000000000000000000000000000000000000000..9df64023a7aeec41486ae290860f733d27ac180f --- /dev/null +++ b/framework/test/unittest/platform/common/edp_test.h @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#ifndef EDP_TEST_H +#define EDP_TEST_H + +#include "hdf_device_desc.h" +#include "edp_if.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif /* __cplusplus */ + +struct EdpTestConfig { + uint32_t deviceIndex; +}; + +struct EdpTester { + struct EdpTestConfig config; + DevHandle handle; +}; + +enum EdpTestCmd { + EDP_TEST_CMD_DEEP_COLOR_SET = 0, + EDP_TEST_CMD_DEEP_COLOR_GET, + EDP_TEST_CMD_SET_VIDEO_ATTR, + EDP_TEST_CMD_SET_AUDIO_ATTR, + EDP_TEST_CMD_DISABLE, + EDP_TEST_CMD_ENABLE, + EDP_TEST_CMD_REGISTER_HPD_CB, + EDP_TEST_CMD_UNREGISTER_HPD_CB, + EDP_TEST_CMD_GET_CONNECTER, + EDP_TEST_CMD_MAX, +}; + +struct EdpTest { + struct IDeviceIoService service; + struct HdfDeviceObject *device; + int32_t (*doTest)(struct EdpTest *test, int32_t cmd); + DevHandle handle; + uint8_t devNo; + uint32_t total; + uint32_t fails; +}; + +static inline struct EdpTest *EdpTestServiceGet(void) +{ + return (struct EdpTest *)DevSvcManagerClntGetService("PLATFORM_EDP_TEST"); +} + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif /* __cplusplus */ + +#endif /* EDP_TEST_H */ diff --git a/framework/test/unittest/platform/entry/hdf_edp_entry_test.c b/framework/test/unittest/platform/entry/hdf_edp_entry_test.c new file mode 100644 index 0000000000000000000000000000000000000000..3686fb971adda1d5c55eaff38044e33a0b53e7db --- /dev/null +++ b/framework/test/unittest/platform/entry/hdf_edp_entry_test.c @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#include "hdf_edp_entry_test.h" +#include "edp_test.h" +#include "hdf_log.h" + +#define HDF_LOG_TAG hdf_edp_entry_test + +int32_t HdfEdpTestEntry(HdfTestMsg *msg) +{ + if (msg == NULL) { + HDF_LOGE("%s: msg is null!", __func__); + return HDF_ERR_INVALID_OBJECT; + } + + struct EdpTest *test = EdpTestServiceGet(); + if (test == NULL) { + HDF_LOGE("%s: test object is null\n", __func__); + return HDF_ERR_INVALID_OBJECT; + } + + msg->result = test->doTest(test, msg->subCmd); + + return HDF_SUCCESS; +} diff --git a/framework/test/unittest/platform/entry/hdf_edp_entry_test.h b/framework/test/unittest/platform/entry/hdf_edp_entry_test.h new file mode 100644 index 0000000000000000000000000000000000000000..e3c0b2b65c7f92aef1fab58b1e25dc5b50335e31 --- /dev/null +++ b/framework/test/unittest/platform/entry/hdf_edp_entry_test.h @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#ifndef HDF_EDP_ENTRY_TEST_H +#define HDF_EDP_ENTRY_TEST_H + +#include "hdf_main_test.h" + +int32_t HdfEdpTestEntry(HdfTestMsg *msg); + +#endif /* HDF_EDP_ENTRY_TEST_H */ \ No newline at end of file